@tscircuit/eval 0.0.1273 → 0.0.1274

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.
@@ -641,18 +641,18 @@ ${functionBody}
641
641
  `)};rects.push(rect);for(let pad2 of component.pads){let{absoluteCenter,size:size3,padId,networkId}=pad2,padRect={center:{x:absoluteCenter.x,y:absoluteCenter.y},width:size3.x,height:size3.y,label:`${padId} ${networkId}`,fill:"rgba(255,0,0,0.8)"};rects.push(padRect)}}for(let netId of allNetworkIds){let padsOnNet=packOutput.components.flatMap(c3=>c3.pads.filter(p3=>p3.networkId===netId));for(let i6=0;i6<padsOnNet.length;i6++)for(let j6=i6+1;j6<padsOnNet.length;j6++){let pad1=padsOnNet[i6],pad2=padsOnNet[j6],isStrong=isStrongConnection(pad1.padId,pad2.padId,packOutput.weightedConnections);lines.push({points:[pad1.absoluteCenter,pad2.absoluteCenter],strokeColor:colorMap2[netId],strokeDash:isStrong?void 0:"4 2"})}}return{coordinateSystem:"cartesian",rects,lines}};function getComponentCollisionBoxes(component){if(component.courtyard){let courtyard=component.courtyard,angleRad=component.ccwRotationOffset*Math.PI/180,rotatedOffset=rotatePoint4(courtyard.offsetFromCenter,angleRad),normalizedDeg=(component.ccwRotationOffset%360+360)%360,swapDims=normalizedDeg===90||normalizedDeg===270,width=courtyard.width,height=courtyard.height;return swapDims&&(width=courtyard.height,height=courtyard.width),[{center:{x:component.center.x+rotatedOffset.x,y:component.center.y+rotatedOffset.y},width,height}]}return component.pads.map(p3=>({center:{x:p3.absoluteCenter.x,y:p3.absoluteCenter.y},width:p3.size.x,height:p3.size.y}))}function checkOverlapWithPackedComponents({component,packedComponents,minGap}){let allPackedBoxes=packedComponents.flatMap(c3=>getComponentCollisionBoxes(c3)),newComponentBoxes=getComponentCollisionBoxes(component);for(let newBox of newComponentBoxes)for(let packedBox of allPackedBoxes){let{distance:boxDist}=computeDistanceBetweenBoxes(newBox,packedBox);if(boxDist+1e-6<minGap)return{hasOverlap:!0,gapDistance:boxDist}}return{hasOverlap:!1}}var SingleComponentPackSolver=class extends BaseSolver{constructor(params){super();__publicField(this,"componentToPack");__publicField(this,"packedComponents");__publicField(this,"packPlacementStrategy");__publicField(this,"minGap");__publicField(this,"obstacles");__publicField(this,"boundaryOutline");__publicField(this,"weightedConnections");__publicField(this,"currentPhase","outline");__publicField(this,"outlines",[]);__publicField(this,"queuedOutlineSegments",[]);__publicField(this,"currentSegmentIndex",0);__publicField(this,"currentRotationIndex",0);__publicField(this,"activeSubSolver",null);__publicField(this,"candidateResults",[]);__publicField(this,"rejectedCandidates",[]);__publicField(this,"bestCandidate");__publicField(this,"outputPackedComponent");__publicField(this,"bounds");this.componentToPack=params.componentToPack,this.packedComponents=params.packedComponents,this.packPlacementStrategy=params.packPlacementStrategy,this.minGap=params.minGap??0,this.obstacles=params.obstacles??[],this.bounds=params.bounds,this.boundaryOutline=params.boundaryOutline,this.weightedConnections=params.weightedConnections}getSolverName(){return"SingleComponentPackSolver"}_setup(){super._setup(),this.currentPhase="outline",this.outlines=[],this.queuedOutlineSegments=[],this.candidateResults=[],this.activeSubSolver=void 0,this.currentSegmentIndex=0,this.currentRotationIndex=0}_step(){if(!(this.solved||this.failed))switch(this.currentPhase){case"outline":this.executeOutlinePhase();break;case"segment_candidate":this.executeSegmentCandidatePhase();break;case"evaluate":this.executeEvaluatePhase();break}}executeOutlinePhase(){if(this.packedComponents.length===0){let availableRotations2=this.componentToPack.availableRotationDegrees??[0,90,180,270],position4={x:0,y:0},rotation5=availableRotations2[0]??0,candidate=this.createPackedComponent(position4,rotation5),candidateBoxes=getComponentCollisionBoxes(candidate);if(!(this.obstacles??[]).some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return candidateBoxes.some(box2=>{let{distance:distance8}=computeDistanceBetweenBoxes(box2,obsBox);return distance8+1e-6<this.minGap})})){this.outputPackedComponent=candidate,this.solved=!0;return}}this.outlines=constructOutlinesFromPackedComponents(this.packedComponents,{minGap:this.minGap,obstacles:this.obstacles});let availableRotations=this.componentToPack.availableRotationDegrees??[0,90,180,270];for(let segmentIndex=0;segmentIndex<this.outlines.length;segmentIndex++){let outline=this.outlines[segmentIndex];for(let i6=0;i6<outline.length;i6++){let segment2=outline[i6];this.queuedOutlineSegments.push({segment:segment2,availableRotations:[...availableRotations],segmentIndex:segmentIndex*1e3+i6,ccwFullOutline:outline})}}if(this.boundaryOutline&&this.boundaryOutline.length>=3){let boundarySegments=[];for(let i6=0;i6<this.boundaryOutline.length;i6++){let p12=this.boundaryOutline[i6],p22=this.boundaryOutline[(i6+1)%this.boundaryOutline.length];boundarySegments.push([p12,p22])}let boundaryOutlineIndex=this.outlines.length;for(let i6=0;i6<boundarySegments.length;i6++){let segment2=boundarySegments[i6];this.queuedOutlineSegments.push({segment:segment2,availableRotations:[...availableRotations],segmentIndex:boundaryOutlineIndex*1e3+i6,ccwFullOutline:boundarySegments})}}let obstacleOutlineIndex=this.outlines.length+1;for(let obstacle of this.obstacles){let hw2=obstacle.width/2+this.minGap,hh3=obstacle.height/2+this.minGap,cx3=obstacle.absoluteCenter.x,cy3=obstacle.absoluteCenter.y,obstacleCorners=[{x:cx3-hw2,y:cy3-hh3},{x:cx3+hw2,y:cy3-hh3},{x:cx3+hw2,y:cy3+hh3},{x:cx3-hw2,y:cy3+hh3}],obstacleSegments=[[obstacleCorners[0],obstacleCorners[1]],[obstacleCorners[1],obstacleCorners[2]],[obstacleCorners[2],obstacleCorners[3]],[obstacleCorners[3],obstacleCorners[0]]];for(let i6=0;i6<obstacleSegments.length;i6++){let segment2=obstacleSegments[i6];this.queuedOutlineSegments.push({segment:segment2,availableRotations:[...availableRotations],segmentIndex:obstacleOutlineIndex*1e3+i6,ccwFullOutline:obstacleSegments})}obstacleOutlineIndex++}this.currentPhase="segment_candidate",this.currentSegmentIndex=0,this.currentRotationIndex=0}executeSegmentCandidatePhase(){if(this.activeSubSolver?.solved||this.activeSubSolver?.failed){let queuedSegment=this.queuedOutlineSegments[this.currentSegmentIndex],rotation5=queuedSegment.availableRotations[this.currentRotationIndex],distance8=1/0,optimalPosition;if(this.activeSubSolver.solved&&this.activeSubSolver.optimalPosition){optimalPosition=this.activeSubSolver.optimalPosition;let candidateComponent=this.createPackedComponent(optimalPosition,rotation5),{hasOverlap,gapDistance}=checkOverlapWithPackedComponents({component:candidateComponent,packedComponents:this.packedComponents,minGap:this.minGap}),minObstacleGapDistance=1/0,candidateCollisionBoxes=getComponentCollisionBoxes(candidateComponent),tooCloseToObstacles=(this.obstacles??[]).some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return candidateCollisionBoxes.some(box2=>{let{distance:distance23}=computeDistanceBetweenBoxes(box2,obsBox);return minObstacleGapDistance=Math.min(minObstacleGapDistance,distance23),distance23+1e-6<this.minGap})}),outsideBounds=!1;if(this.bounds){let componentBounds=getComponentBounds(candidateComponent,0);outsideBounds=componentBounds.minX<this.bounds.minX||componentBounds.maxX>this.bounds.maxX||componentBounds.minY<this.bounds.minY||componentBounds.maxY>this.bounds.maxY}let outsideBoundaryOutline=!1;if(this.boundaryOutline&&this.boundaryOutline.length>=3){let componentBounds=getComponentBounds(candidateComponent,0),allPadsInside=candidateComponent.pads.every(pad2=>isPointInPolygon3(pad2.absoluteCenter,this.boundaryOutline)),cornersInside=[{x:componentBounds.minX,y:componentBounds.minY},{x:componentBounds.minX,y:componentBounds.maxY},{x:componentBounds.maxX,y:componentBounds.minY},{x:componentBounds.maxX,y:componentBounds.maxY}].every(corner=>isPointInPolygon3(corner,this.boundaryOutline));outsideBoundaryOutline=!allPadsInside||!cornersInside}distance8=this.calculateDistance(optimalPosition,rotation5),hasOverlap?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation5,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance}):tooCloseToObstacles?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation5,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance:minObstacleGapDistance}):outsideBounds?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation5,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance:-1}):outsideBoundaryOutline?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation5,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance:-1}):this.candidateResults.push({segment:queuedSegment.segment,rotation:rotation5,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex})}this.currentRotationIndex++,this.activeSubSolver=void 0}for(;!this.activeSubSolver;){if(this.currentSegmentIndex>=this.queuedOutlineSegments.length){this.currentPhase="evaluate";return}let queuedSegment=this.queuedOutlineSegments[this.currentSegmentIndex];if(this.currentRotationIndex>=queuedSegment.availableRotations.length){this.currentSegmentIndex++,this.currentRotationIndex=0;continue}let rotation5=queuedSegment.availableRotations[this.currentRotationIndex];this.activeSubSolver=new OutlineSegmentCandidatePointSolver({outlineSegment:queuedSegment.segment,ccwFullOutline:queuedSegment.ccwFullOutline,componentRotationDegrees:rotation5,packStrategy:this.packPlacementStrategy,minGap:this.minGap,packedComponents:this.packedComponents,componentToPack:this.componentToPack,obstacles:this.obstacles,globalBounds:this.bounds,boundaryOutline:this.boundaryOutline,weightedConnections:this.weightedConnections}),this.activeSubSolver.setup();break}this.activeSubSolver.step()}executeEvaluatePhase(){if(this.candidateResults.length===0){this.failed=!0,this.error="No valid candidates found";return}this.candidateResults.sort((a6,b6)=>a6.distance-b6.distance),this.bestCandidate=this.candidateResults[0],this.bestCandidate.optimalPosition&&(this.outputPackedComponent=this.createPackedComponent(this.bestCandidate.optimalPosition,this.bestCandidate.rotation)),this.solved=!0}calculateDistance(position4,rotation5){let tempComponent=this.createPackedComponent(position4,rotation5),totalDistance=0,useSquaredDistance=this.packPlacementStrategy==="minimum_sum_squared_distance_to_network"||this.packPlacementStrategy==="minimum_closest_sum_squared_distance";for(let pad2 of tempComponent.pads){let minDistanceToNetwork=1/0;for(let packedComponent of this.packedComponents)for(let packedPad of packedComponent.pads)if(packedPad.networkId===pad2.networkId){if(!isStrongConnection(pad2.padId,packedPad.padId,this.weightedConnections))continue;let dx3=pad2.absoluteCenter.x-packedPad.absoluteCenter.x,dy3=pad2.absoluteCenter.y-packedPad.absoluteCenter.y,dist=Math.sqrt(dx3*dx3+dy3*dy3);minDistanceToNetwork=Math.min(minDistanceToNetwork,dist)}minDistanceToNetwork<1/0&&(totalDistance+=useSquaredDistance?minDistanceToNetwork*minDistanceToNetwork:minDistanceToNetwork)}return totalDistance}createPackedComponent(position4,rotation5){let component={...this.componentToPack,center:position4,ccwRotationOffset:rotation5,pads:this.componentToPack.pads.map(pad2=>({...pad2,absoluteCenter:{x:0,y:0}}))};return setPackedComponentPadCenters(component),component}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=getGraphicsFromPackOutput({components:this.packedComponents,minGap:this.minGap,packOrderStrategy:"largest_to_smallest",packPlacementStrategy:this.packPlacementStrategy});if(graphics.points??(graphics.points=[]),graphics.lines??(graphics.lines=[]),graphics.rects??(graphics.rects=[]),graphics.texts??(graphics.texts=[]),graphics.circles??(graphics.circles=[]),this.obstacles&&this.obstacles.length>0)for(let obstacle of this.obstacles)graphics.rects.push({center:obstacle.absoluteCenter,width:obstacle.width,height:obstacle.height,fill:"rgba(0,0,0,0.1)",stroke:"#555",label:obstacle.obstacleId});if(this.bounds&&graphics.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"rgba(0,0,0,0.5)",strokeDash:"2 2"}),this.boundaryOutline&&this.boundaryOutline.length){let outlinePoints=[...this.boundaryOutline];outlinePoints.length>0&&(outlinePoints[0].x!==outlinePoints[outlinePoints.length-1].x||outlinePoints[0].y!==outlinePoints[outlinePoints.length-1].y)&&outlinePoints.push({...outlinePoints[0]}),graphics.lines.push({points:outlinePoints,strokeColor:"rgba(0, 0, 255, 0.5)",strokeDash:"4 2"})}switch(this.currentPhase){case"outline":this.visualizeOutlinePhase(graphics);break;case"segment_candidate":this.visualizeSegmentCandidatePhase(graphics);break;case"evaluate":this.visualizeEvaluatePhase(graphics);break}return graphics}visualizeOutlinePhase(graphics){for(let outline of this.outlines)for(let segment2 of outline){let[p12,p22]=segment2;graphics.lines.push({points:[p12,p22],strokeColor:"#ff4444"})}for(let i6=0;i6<this.outlines.length;i6++){let outline=this.outlines[i6];for(let u6=0;u6<outline.length;u6++){let[p12,p22]=outline[u6];graphics.points.push({x:p12.x,y:p12.y,label:`outlines [${i6}] [${u6}]`,color:"#ff4444"})}}}visualizeSegmentCandidatePhase(graphics){if(this.visualizeOutlinePhase(graphics),this.activeSubSolver){let subSolverViz=this.activeSubSolver.visualize();subSolverViz.lines&&graphics.lines.push(...subSolverViz.lines),subSolverViz.points&&graphics.points.push(...subSolverViz.points),subSolverViz.rects&&graphics.rects.push(...subSolverViz.rects),subSolverViz.circles&&graphics.circles.push(...subSolverViz.circles??[])}else for(let i6=0;i6<this.candidateResults.length;i6++){let candidate=this.candidateResults[i6];if(candidate.optimalPosition){let tempComponent=this.createPackedComponent(candidate.optimalPosition,candidate.rotation);for(let pad2 of tempComponent.pads)graphics.rects.push({center:pad2.absoluteCenter,width:pad2.size.x,height:pad2.size.y,fill:"rgba(255,165,0,0.3)",stroke:"rgba(255,165,0,0.8)",strokeWidth:1});graphics.points.push({x:candidate.optimalPosition.x,y:candidate.optimalPosition.y,label:`c${i6}, d=${candidate.distance.toFixed(3)}`,color:"rgba(255,165,0,0.8)"})}}}visualizeEvaluatePhase(graphics){this.visualizeOutlinePhase(graphics);for(let i6=0;i6<this.candidateResults.length;i6++){let candidate=this.candidateResults[i6];if(!candidate.optimalPosition)continue;let step=i6,isBest=step===0;graphics.points.push({x:candidate.optimalPosition.x,y:candidate.optimalPosition.y,label:`step=${step}, d=${candidate.distance.toFixed(3)}`,color:isBest?"rgba(0,255,0,0.8)":"rgba(255,165,0,0.6)"})}for(let i6=0;i6<this.rejectedCandidates.length;i6++){let candidate=this.rejectedCandidates[i6];candidate.optimalPosition&&graphics.points.push({x:candidate.optimalPosition.x,y:candidate.optimalPosition.y,label:`rejected, d=${candidate.distance.toFixed(3)}
642
642
  gap_distance=${candidate.gapDistance}`,color:"rgba(255,0,0,0.8)"})}if(this.outputPackedComponent)for(let pad2 of this.outputPackedComponent.pads)graphics.rects.push({center:pad2.absoluteCenter,width:pad2.size.x,height:pad2.size.y,fill:"rgba(0,255,0,0.7)"})}getResult(){return this.outputPackedComponent}getOutput(){return this.getResult()}getConstructorParams(){return{componentToPack:this.componentToPack,packedComponents:this.packedComponents,packPlacementStrategy:this.packPlacementStrategy,minGap:this.minGap,obstacles:this.obstacles,bounds:this.bounds,boundaryOutline:this.boundaryOutline,weightedConnections:this.weightedConnections}}};function getPolygonCentroid(points){if(points.length<3){let sumX=points.reduce((sum,p3)=>sum+p3.x,0),sumY=points.reduce((sum,p3)=>sum+p3.y,0);return{x:sumX/points.length,y:sumY/points.length}}let signedArea22=0,cx3=0,cy3=0;for(let i6=0;i6<points.length;i6++){let p12=points[i6],p22=points[(i6+1)%points.length],crossProduct=p12.x*p22.y-p22.x*p12.y;signedArea22+=crossProduct,cx3+=(p12.x+p22.x)*crossProduct,cy3+=(p12.y+p22.y)*crossProduct}if(signedArea22*=.5,Math.abs(signedArea22)<1e-10){let sumX=points.reduce((sum,p3)=>sum+p3.x,0),sumY=points.reduce((sum,p3)=>sum+p3.y,0);return{x:sumX/points.length,y:sumY/points.length}}return cx3/=6*signedArea22,cy3/=6*signedArea22,{x:cx3,y:cy3}}var PackSolver2=class extends BaseSolver{constructor(packInput){super();__publicField(this,"packInput");__publicField(this,"unpackedComponentQueue",[]);__publicField(this,"packedComponents",[]);__publicField(this,"componentToPack");this.packInput=packInput}getSolverName(){return"PackSolver2"}getConstructorParams(){return this.packInput}_setup(){let{components,packOrderStrategy,packFirst=[]}=this.packInput,validComponents=components.filter(component=>component.pads.length===0?!1:component.pads.every(pad2=>Number.isFinite(pad2.size.x)&&Number.isFinite(pad2.size.y)&&pad2.size.x>0&&pad2.size.y>0)),staticComponents=validComponents.filter(component=>component.isStatic),dynamicComponents=validComponents.filter(component=>!component.isStatic);this.packedComponents=staticComponents.map(component=>{let packedComponent={...component,center:component.center??{x:0,y:0},ccwRotationOffset:component.ccwRotationOffset??component.availableRotationDegrees?.[0]??0,pads:component.pads.map(pad2=>({...pad2,absoluteCenter:pad2.absoluteCenter??{x:0,y:0}}))};return setPackedComponentPadCenters(packedComponent),packedComponent}),this.unpackedComponentQueue=sortComponentQueue({components:dynamicComponents,packOrderStrategy,packFirst})}packFirstComponent(){let firstComponentToPack=this.unpackedComponentQueue.shift(),initialPosition={x:0,y:0};this.packInput.boundaryOutline&&this.packInput.boundaryOutline.length>=3&&(initialPosition=getPolygonCentroid(this.packInput.boundaryOutline));let newPackedComponent={...firstComponentToPack,center:initialPosition,ccwRotationOffset:firstComponentToPack.ccwRotationOffset??firstComponentToPack.availableRotationDegrees?.[0]??0,pads:firstComponentToPack.pads.map(p3=>({...p3,absoluteCenter:{x:0,y:0}}))};setPackedComponentPadCenters(newPackedComponent);let obstacles=this.packInput.obstacles??[],newComponentBoxes=getComponentCollisionBoxes(newPackedComponent),tooCloseToObstacles=obstacles.some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return newComponentBoxes.some(box2=>{let{distance:distance8}=computeDistanceBetweenBoxes(box2,obsBox);return distance8+1e-6<this.packInput.minGap})}),outsideBoundaryOutline=!1;if(this.packInput.boundaryOutline&&this.packInput.boundaryOutline.length>=3){let componentBounds=getComponentBounds(newPackedComponent,0),allPadsInside=newPackedComponent.pads.every(pad2=>isPointInPolygon3(pad2.absoluteCenter,this.packInput.boundaryOutline)),cornersInside=[{x:componentBounds.minX,y:componentBounds.minY},{x:componentBounds.minX,y:componentBounds.maxY},{x:componentBounds.maxX,y:componentBounds.minY},{x:componentBounds.maxX,y:componentBounds.maxY}].every(corner=>isPointInPolygon3(corner,this.packInput.boundaryOutline));outsideBoundaryOutline=!allPadsInside||!cornersInside}if(!tooCloseToObstacles&&!outsideBoundaryOutline){this.packedComponents.push(newPackedComponent);return}let fallbackSolver=new SingleComponentPackSolver({packedComponents:[],componentToPack:firstComponentToPack,packPlacementStrategy:this.packInput.packPlacementStrategy,minGap:this.packInput.minGap,obstacles,bounds:this.packInput.bounds,boundaryOutline:this.packInput.boundaryOutline,weightedConnections:this.packInput.weightedConnections});fallbackSolver.solve();let result=fallbackSolver.getResult();result?this.packedComponents.push(result):this.packedComponents.push(newPackedComponent)}_step(){if(!(this.solved||this.failed)){if(this.packedComponents.length===0){if(this.unpackedComponentQueue.length===0){this.solved=!0;return}this.packFirstComponent();return}if(!this.activeSubSolver){if(this.unpackedComponentQueue.length===0){this.solved=!0;return}if(this.componentToPack=this.unpackedComponentQueue.shift(),!this.componentToPack){this.solved=!0;return}this.activeSubSolver=new SingleComponentPackSolver({packedComponents:this.packedComponents,componentToPack:this.componentToPack,packPlacementStrategy:this.packInput.packPlacementStrategy,minGap:this.packInput.minGap,obstacles:this.packInput.obstacles??[],bounds:this.packInput.bounds,boundaryOutline:this.packInput.boundaryOutline,weightedConnections:this.packInput.weightedConnections}),this.activeSubSolver.setup()}if(this.activeSubSolver.step(),this.activeSubSolver.failed){this.failed=!0;return}if(this.activeSubSolver.solved){let result=this.activeSubSolver.getResult();if(result)this.packedComponents.push(result);else{let packedComponent={...this.componentToPack,center:{x:0,y:0},ccwRotationOffset:this.componentToPack?.ccwRotationOffset??this.componentToPack?.availableRotationDegrees?.[0]??0,pads:this.componentToPack.pads.map(p3=>({...p3,absoluteCenter:{x:0,y:0}}))};setPackedComponentPadCenters(packedComponent),this.packedComponents.push(packedComponent)}this.componentToPack=void 0,this.activeSubSolver=void 0}}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics={coordinateSystem:"cartesian",title:"Pack Solver 2",points:[],lines:[],rects:[],circles:[],texts:[],arrows:[]};if(this.packInput.obstacles&&this.packInput.obstacles.length>0)for(let obstacle of this.packInput.obstacles)graphics.rects.push({center:obstacle.absoluteCenter,width:obstacle.width,height:obstacle.height,fill:"rgba(0,0,0,0.1)",stroke:"#555",label:obstacle.obstacleId});if(this.packInput.bounds&&graphics.lines.push({points:[{x:this.packInput.bounds.minX,y:this.packInput.bounds.minY},{x:this.packInput.bounds.minX,y:this.packInput.bounds.maxY},{x:this.packInput.bounds.maxX,y:this.packInput.bounds.maxY},{x:this.packInput.bounds.maxX,y:this.packInput.bounds.minY},{x:this.packInput.bounds.minX,y:this.packInput.bounds.minY}],strokeColor:"rgba(0,0,0,0.5)",strokeDash:"2 2"}),this.packInput.boundaryOutline&&this.packInput.boundaryOutline.length){let points=[...this.packInput.boundaryOutline];points.length>0&&(points[0].x!==points[points.length-1].x||points[0].y!==points[points.length-1].y)&&points.push({...points[0]}),graphics.lines.push({points,strokeColor:"rgba(0, 0, 255, 0.5)",strokeDash:"4 2"})}if(this.packedComponents.length===0)for(let component of this.unpackedComponentQueue)for(let pad2 of component.pads)graphics.rects.push({center:{x:0,y:0},width:pad2.size.x,height:pad2.size.y,fill:"rgba(0,0,0,0.1)"});let allPads=this.packedComponents.flatMap(c3=>c3.pads),networkToPadMap=new Map;for(let pad2 of allPads)pad2.networkId&&networkToPadMap.set(pad2.networkId,[...networkToPadMap.get(pad2.networkId)||[],pad2]);for(let pad2 of allPads)graphics.rects.push({center:pad2.absoluteCenter,width:pad2.size.x,height:pad2.size.y,fill:"rgba(255,0,0,0.5)"});for(let[networkId,pads]of networkToPadMap.entries())for(let i6=0;i6<pads.length;i6++)for(let j6=i6+1;j6<pads.length;j6++){let pad1=pads[i6],pad2=pads[j6];graphics.lines.push({points:[pad1.absoluteCenter,pad2.absoluteCenter],strokeColor:getColorForString(networkId,.5)})}return graphics}getOutput(){return{packedComponents:this.packedComponents,unpackedComponents:this.unpackedComponentQueue}}},pack=input2=>{let solver=new PackSolver2(input2);return solver.solve(),{...input2,components:solver.packedComponents}},getPolygonBoundingBox=points=>{if(!points||points.length===0)return{minX:0,maxX:0,minY:0,maxY:0};let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let point6 of points)minX=Math.min(minX,point6.x),maxX=Math.max(maxX,point6.x),minY=Math.min(minY,point6.y),maxY=Math.max(maxY,point6.y);return{minX,maxX,minY,maxY}},getRotatedBoundingBoxSize=opts=>{let{width,height,ccwRotationDegrees}=opts,angleRad=ccwRotationDegrees*Math.PI/180,snapTrigMagnitude=value=>{let absoluteValue=Math.abs(value);return absoluteValue<1e-12?0:Math.abs(absoluteValue-1)<1e-12?1:absoluteValue},absCos=snapTrigMagnitude(Math.cos(angleRad)),absSin=snapTrigMagnitude(Math.sin(angleRad));return{width:width*absCos+height*absSin,height:width*absSin+height*absCos}},extractPadInfos=(pcbComponent,db2,getNetworkId)=>{let out=[],pushPad=({padId,pcbPortId,sx:sx3,sy:sy3,x:x6,y:y2})=>out.push({padId,networkId:getNetworkId(pcbPortId),size:{x:sx3,y:sy3},absoluteCenter:{x:x6,y:y2},pcbPortId});for(let via of db2.pcb_via.list({pcb_component_id:pcbComponent.pcb_component_id}))pushPad({padId:via.pcb_via_id,pcbPortId:via.pcb_port_id,sx:via.outer_diameter??via.hole_diameter??0,sy:via.outer_diameter??via.hole_diameter??0,x:via.x,y:via.y});for(let ph3 of db2.pcb_plated_hole.list({pcb_component_id:pcbComponent.pcb_component_id}))switch(ph3.shape){case"circle":{pushPad({padId:ph3.pcb_plated_hole_id,pcbPortId:ph3.pcb_port_id,sx:ph3.outer_diameter??ph3.hole_diameter??0,sy:ph3.outer_diameter??ph3.hole_diameter??0,x:ph3.x,y:ph3.y});break}case"oval":{pushPad({padId:ph3.pcb_plated_hole_id,pcbPortId:ph3.pcb_port_id,sx:ph3.outer_width,sy:ph3.outer_height,x:ph3.x,y:ph3.y});break}case"circular_hole_with_rect_pad":{pushPad({padId:ph3.pcb_plated_hole_id,pcbPortId:ph3.pcb_port_id,sx:ph3.rect_pad_width,sy:ph3.rect_pad_height,x:ph3.x,y:ph3.y});break}case"pill":{pushPad({padId:ph3.pcb_plated_hole_id,pcbPortId:ph3.pcb_port_id,sx:ph3.outer_width,sy:ph3.outer_height,x:ph3.x,y:ph3.y});break}case"pill_hole_with_rect_pad":{pushPad({padId:ph3.pcb_plated_hole_id,pcbPortId:ph3.pcb_port_id,sx:ph3.rect_pad_width,sy:ph3.rect_pad_height,x:ph3.x,y:ph3.y});break}case"rotated_pill_hole_with_rect_pad":{let size3=getRotatedBoundingBoxSize({width:ph3.rect_pad_width,height:ph3.rect_pad_height,ccwRotationDegrees:ph3.rect_ccw_rotation});pushPad({padId:ph3.pcb_plated_hole_id,pcbPortId:ph3.pcb_port_id,sx:size3.width,sy:size3.height,x:ph3.x,y:ph3.y});break}default:{console.warn(`Unsupported plated hole shape ${ph3.shape}`);break}}for(let sp3 of db2.pcb_smtpad.list({pcb_component_id:pcbComponent.pcb_component_id}))switch(sp3.shape){case"rect":{pushPad({padId:sp3.pcb_smtpad_id,pcbPortId:sp3.pcb_port_id,sx:sp3.width??0,sy:sp3.height??0,x:sp3.x,y:sp3.y});break}case"pill":{pushPad({padId:sp3.pcb_smtpad_id,pcbPortId:sp3.pcb_port_id,sx:sp3.width,sy:sp3.height,x:sp3.x,y:sp3.y});break}case"rotated_rect":case"rotated_pill":{let size3=getRotatedBoundingBoxSize({width:sp3.width,height:sp3.height,ccwRotationDegrees:sp3.ccw_rotation});pushPad({padId:sp3.pcb_smtpad_id,pcbPortId:sp3.pcb_port_id,sx:size3.width,sy:size3.height,x:sp3.x,y:sp3.y});break}case"circle":{pushPad({padId:sp3.pcb_smtpad_id,pcbPortId:sp3.pcb_port_id,sx:sp3.radius*2,sy:sp3.radius*2,x:sp3.x,y:sp3.y});break}case"polygon":{if(sp3.points&&sp3.points.length>0){let{minX,maxX,minY,maxY}=getPolygonBoundingBox(sp3.points),width=maxX-minX,height=maxY-minY,centerX=(minX+maxX)/2,centerY=(minY+maxY)/2;pushPad({padId:sp3.pcb_smtpad_id,pcbPortId:sp3.pcb_port_id,sx:width,sy:height,x:centerX,y:centerY})}else console.warn(`Polygon pad ${sp3.pcb_smtpad_id} has no points`);break}}return out},getElementOutsideTree=(db2,tree)=>{let componentIdsInTree=new Set,collectComponentIds=node=>{if(node){if(node.nodeType==="component"){let pcbId=node.otherChildElements?.[0]?.pcb_component_id;pcbId&&componentIdsInTree.add(pcbId)}for(let child of node.childNodes??[])collectComponentIds(child)}};collectComponentIds(tree);let outside=[];for(let ph3 of db2.pcb_plated_hole.list({})){if(!("pcb_component_id"in ph3)||!ph3.pcb_component_id){outside.push(ph3);continue}componentIdsInTree.has(ph3.pcb_component_id)||outside.push(ph3)}for(let hole of db2.pcb_hole.list({}))outside.push(hole);return outside},getRotatedRectBounds2=(width,height,ccwRotationDegrees)=>{let angleRad=ccwRotationDegrees*Math.PI/180,absCos=Math.abs(Math.cos(angleRad)),absSin=Math.abs(Math.sin(angleRad));return{width:width*absCos+height*absSin,height:width*absSin+height*absCos}},getObstacleFromElement=element=>{if(element.type==="pcb_plated_hole"&&element.shape==="circular_hole_with_rect_pad"){let{rect_pad_height,rect_pad_width,x:x6,y:y2}=element;return{obstacleId:element.pcb_plated_hole_id,absoluteCenter:{x:x6,y:y2},width:rect_pad_width,height:rect_pad_height}}if(element.type==="pcb_plated_hole"&&element.shape==="rotated_pill_hole_with_rect_pad"){let{rect_pad_height,rect_pad_width,rect_ccw_rotation,x:x6,y:y2}=element,bounds=getRotatedRectBounds2(rect_pad_width,rect_pad_height,rect_ccw_rotation);return{obstacleId:element.pcb_plated_hole_id,absoluteCenter:{x:x6,y:y2},width:bounds.width,height:bounds.height}}if(element.type==="pcb_hole"){let{x:x6,y:y2,pcb_hole_id}=element,width="hole_diameter"in element?element.hole_diameter:element.hole_width,height="hole_diameter"in element?element.hole_diameter:element.hole_height;return{obstacleId:pcb_hole_id,absoluteCenter:{x:x6,y:y2},width,height}}},extractCourtyardForComponent=opts=>{let{db:db2,pcbComponentIds,componentCenter}=opts;if(Array.from(new Set(pcbComponentIds)).length!==1)return;let idSet=new Set(pcbComponentIds),minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0,found=!1;for(let rect of db2.pcb_courtyard_rect.list())idSet.has(rect.pcb_component_id)&&(minX=Math.min(minX,rect.center.x-rect.width/2),maxX=Math.max(maxX,rect.center.x+rect.width/2),minY=Math.min(minY,rect.center.y-rect.height/2),maxY=Math.max(maxY,rect.center.y+rect.height/2),found=!0);for(let polygon2 of db2.pcb_courtyard_polygon.list())if(idSet.has(polygon2.pcb_component_id)){for(let pt3 of polygon2.points)minX=Math.min(minX,pt3.x),maxX=Math.max(maxX,pt3.x),minY=Math.min(minY,pt3.y),maxY=Math.max(maxY,pt3.y);found=!0}for(let outline of db2.pcb_courtyard_outline.list())if(idSet.has(outline.pcb_component_id)){for(let pt3 of outline.outline)minX=Math.min(minX,pt3.x),maxX=Math.max(maxX,pt3.x),minY=Math.min(minY,pt3.y),maxY=Math.max(maxY,pt3.y);found=!0}for(let circle2 of db2.pcb_courtyard_circle.list())idSet.has(circle2.pcb_component_id)&&(minX=Math.min(minX,circle2.center.x-circle2.radius),maxX=Math.max(maxX,circle2.center.x+circle2.radius),minY=Math.min(minY,circle2.center.y-circle2.radius),maxY=Math.max(maxY,circle2.center.y+circle2.radius),found=!0);if(!found)return;let courtyardCenterX=(minX+maxX)/2,courtyardCenterY=(minY+maxY)/2;return{offsetFromCenter:{x:courtyardCenterX-componentCenter.x,y:courtyardCenterY-componentCenter.y},width:maxX-minX,height:maxY-minY}},buildPackedComponent=(pcbComponents,componentId,db2,getNetworkId,shouldAddInnerObstacles,sourcePortToPadIds=new Map,chipMarginsMap={},isStatic=!1)=>{let padInfos=pcbComponents.flatMap(pc3=>{let pads2=extractPadInfos(pc3,db2,getNetworkId),margins=chipMarginsMap[pc3.pcb_component_id];return margins?pads2.map(p3=>({...p3,size:{x:p3.size.x+margins.left+margins.right,y:p3.size.y+margins.top+margins.bottom},absoluteCenter:{x:p3.absoluteCenter.x+(margins.right-margins.left)/2,y:p3.absoluteCenter.y+(margins.top-margins.bottom)/2}})):pads2}),minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let p3 of padInfos)minX=Math.min(minX,p3.absoluteCenter.x-p3.size.x/2),maxX=Math.max(maxX,p3.absoluteCenter.x+p3.size.x/2),minY=Math.min(minY,p3.absoluteCenter.y-p3.size.y/2),maxY=Math.max(maxY,p3.absoluteCenter.y+p3.size.y/2);let center2={x:(minX+maxX)/2,y:(minY+maxY)/2},pads=padInfos.map(p3=>({padId:p3.padId,networkId:p3.networkId,type:"rect",size:p3.size,absoluteCenter:p3.absoluteCenter,offset:{x:p3.absoluteCenter.x-center2.x,y:p3.absoluteCenter.y-center2.y}}));for(let padInfo of padInfos){if(!padInfo.pcbPortId)continue;let sourcePortId=db2.pcb_port.get(padInfo.pcbPortId)?.source_port_id;if(!sourcePortId)continue;let existingPadIds=sourcePortToPadIds.get(sourcePortId)??[];existingPadIds.push(padInfo.padId),sourcePortToPadIds.set(sourcePortId,existingPadIds)}if(shouldAddInnerObstacles){let innerPad={padId:`${componentId}-inner`,networkId:`${componentId}-inner`,type:"rect",size:{x:maxX-minX,y:maxY-minY},absoluteCenter:center2,offset:{x:0,y:0}};pads.push(innerPad)}let courtyard=extractCourtyardForComponent({db:db2,pcbComponentIds:pcbComponents.map(pc3=>pc3.pcb_component_id),componentCenter:center2});return{componentId,isStatic,center:center2,ccwRotationOffset:0,pads,courtyard}},collectPcbComponents=(node,db2)=>{if(node.nodeType==="component"){let pcbId=node.otherChildElements[0]?.pcb_component_id;return pcbId?[db2.pcb_component.get(pcbId)]:[]}return node.childNodes.flatMap(n3=>collectPcbComponents(n3,db2))},convertCircuitJsonToPackOutput=(circuitJson,opts={})=>{let packOutput={components:[],minGap:0,packOrderStrategy:"largest_to_smallest",packPlacementStrategy:"shortest_connection_along_outline",obstacles:opts.obstacles??[]},tree=getCircuitJsonTree(circuitJson,{source_group_id:opts.source_group_id}),db2=cju_default(circuitJson),unnamedCounter=0,sourcePortToPadIds=new Map,elementsOutsideTree=getElementOutsideTree(db2,tree),pcbBoard=circuitJson.find(item=>item.type==="pcb_board");pcbBoard?.outline&&(packOutput.boundaryOutline=pcbBoard.outline);let getNetworkId=pcbPortId=>{if(pcbPortId){let pcbPort=db2.pcb_port.get(pcbPortId);if(pcbPort){let sourcePort=db2.source_port.get(pcbPort.source_port_id);if(sourcePort?.subcircuit_connectivity_map_key)return sourcePort.subcircuit_connectivity_map_key}}return`unnamed${unnamedCounter++}`},topLevelNodes=tree.childNodes??[],collectRelativeToGroupAnchorComponents=node=>{let relativeComponents2=[];if(node.nodeType==="component"){let pcbComponent=node.otherChildElements.find(e6=>e6.type==="pcb_component");pcbComponent&&pcbComponent.position_mode==="relative_to_group_anchor"&&relativeComponents2.push(pcbComponent)}for(let child of node.childNodes??[])relativeComponents2.push(...collectRelativeToGroupAnchorComponents(child));return relativeComponents2},staticComponentIds=new Set(opts.staticPcbComponentIds??[]),pcbComponentIdsRepresentedByPackedGroups=new Set;for(let node of topLevelNodes)if(node.nodeType==="component"){let pcbComponent=node.otherChildElements.find(e6=>e6.type==="pcb_component");if(!pcbComponent||pcbComponent.position_mode==="relative_to_group_anchor")continue;let shouldAddInnerObstaclesForComp=opts.shouldAddInnerObstacles??!1;pcbComponent.obstructs_within_bounds===!0?shouldAddInnerObstaclesForComp=!0:pcbComponent.obstructs_within_bounds===!1&&(shouldAddInnerObstaclesForComp=!1),packOutput.components.push(buildPackedComponent([pcbComponent],pcbComponent.pcb_component_id,db2,getNetworkId,shouldAddInnerObstaclesForComp,sourcePortToPadIds,opts.chipMarginsMap,staticComponentIds.has(pcbComponent.pcb_component_id)))}else if(node.nodeType==="group"){let pcbComps=collectPcbComponents(node,db2);if(!pcbComps.length)continue;for(let pcbComponent of pcbComps)pcbComponentIdsRepresentedByPackedGroups.add(pcbComponent.pcb_component_id);let compId=node.sourceGroup?.source_group_id??node.sourceGroup?.name??`group_${packOutput.components.length}`;packOutput.components.push(buildPackedComponent(pcbComps,compId,db2,getNetworkId,void 0,sourcePortToPadIds,opts.chipMarginsMap,staticComponentIds.has(compId)))}let relativeComponents=topLevelNodes.flatMap(node=>collectRelativeToGroupAnchorComponents(node));for(let pcbComponent of relativeComponents){if(pcbComponentIdsRepresentedByPackedGroups.has(pcbComponent.pcb_component_id))continue;let courtyard=extractCourtyardForComponent({db:db2,pcbComponentIds:[pcbComponent.pcb_component_id],componentCenter:pcbComponent.center});if(courtyard){packOutput.obstacles.push({obstacleId:pcbComponent.pcb_component_id,absoluteCenter:{x:pcbComponent.center.x+courtyard.offsetFromCenter.x,y:pcbComponent.center.y+courtyard.offsetFromCenter.y},width:courtyard.width,height:courtyard.height});continue}let padInfos=extractPadInfos(pcbComponent,db2,getNetworkId);if(padInfos.length===0)continue;let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let pad2 of padInfos)minX=Math.min(minX,pad2.absoluteCenter.x-pad2.size.x/2),maxX=Math.max(maxX,pad2.absoluteCenter.x+pad2.size.x/2),minY=Math.min(minY,pad2.absoluteCenter.y-pad2.size.y/2),maxY=Math.max(maxY,pad2.absoluteCenter.y+pad2.size.y/2);let center2={x:(minX+maxX)/2,y:(minY+maxY)/2},width=maxX-minX,height=maxY-minY;packOutput.obstacles.push({obstacleId:pcbComponent.pcb_component_id,absoluteCenter:center2,width,height})}for(let element of elementsOutsideTree){let obstacle=getObstacleFromElement(element);obstacle&&packOutput.obstacles.push(obstacle)}let weightedConnections=[],seenConnections=new Set,sourceTraces=typeof db2.source_trace.list=="function"?db2.source_trace.list():circuitJson.filter(item=>item.type==="source_trace");for(let sourceTrace of sourceTraces){let connectedPorts=sourceTrace.connected_source_port_ids||[],connectedNets=sourceTrace.connected_source_net_ids||[];if(!(connectedPorts.length===2&&connectedNets.length===0))continue;let[portA,portB]=connectedPorts,padIdsA=portA?sourcePortToPadIds.get(portA)??[]:[],padIdsB=portB?sourcePortToPadIds.get(portB)??[]:[];for(let padA of padIdsA)for(let padB of padIdsB){let connectionKey=[padA,padB].sort().join("--");seenConnections.has(connectionKey)||(weightedConnections.push({padIds:[padA,padB],weight:1,ignoreWeakConnections:!0}),seenConnections.add(connectionKey))}}return weightedConnections.length>0&&(packOutput.weightedConnections=weightedConnections),packOutput},convertPackOutputToPackInput=packed=>{let strippedComponents=packed.components.map(pc3=>({...pc3.isStatic?{...pc3,pads:pc3.pads.map(pad2=>({...pad2}))}:{componentId:pc3.componentId,availableRotationDegrees:pc3.availableRotationDegrees,pads:pc3.pads.map(({absoluteCenter:_ac,...rest})=>rest),courtyard:pc3.courtyard}}));return{...packed,components:strippedComponents}};init_src();var BaseSolver4=class{constructor(){__publicField(this,"MAX_ITERATIONS",2e5);__publicField(this,"solved",!1);__publicField(this,"failed",!1);__publicField(this,"iterations",0);__publicField(this,"progress",0);__publicField(this,"error",null);__publicField(this,"activeSubSolver");__publicField(this,"failedSubSolvers");__publicField(this,"timeToSolve");__publicField(this,"stats",{})}step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(e6){throw this.error=`${this.constructor.name} error: ${e6}`,this.failed=!0,e6}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){let startTime=Date.now();for(;!this.solved&&!this.failed;)this.step();let endTime=Date.now();this.timeToSolve=endTime-startTime}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function rotatePoint5(point6,angleDegrees){let angleRad=angleDegrees*Math.PI/180,cos6=Math.cos(angleRad),sin6=Math.sin(angleRad);return{x:point6.x*cos6-point6.y*sin6,y:point6.x*sin6+point6.y*cos6}}function getRotatedDimensions(width,height,rotation5){let normalizedRotation=(rotation5%360+360)%360;return Math.round((normalizedRotation+90)%180)===0?{width:height,height:width}:{width,height}}function getChipLabelFontSize(width,height){let smallerDimension=Math.min(width,height);return Math.min(.35,Math.max(.08,smallerDimension*.22))}function getChipFillColor(chipId,isFixed=!1){let chipType=chipId.charAt(0).toUpperCase();if(isFixed){if(chipType==="C")return"rgba(30, 64, 175, 0.35)";if(chipType==="R")return"rgba(5, 150, 105, 0.35)";if(chipType==="L")return"rgba(126, 34, 206, 0.35)";if(chipType==="U")return"rgba(180, 83, 9, 0.35)"}return chipType==="C"?"rgba(59, 130, 246, 0.18)":chipType==="R"?"rgba(16, 185, 129, 0.18)":chipType==="L"?"rgba(168, 85, 247, 0.18)":chipType==="U"?"rgba(245, 158, 11, 0.18)":"rgba(59, 130, 246, 0.12)"}function visualizeInputProblem(inputProblem,basicLayout){let inputViz={points:[],rects:[],lines:[],circles:[],texts:[]},pinToNetMap={};for(let conn of Object.keys(inputProblem.netConnMap)){let[pinId,netId]=conn.split("-");pinToNetMap[pinId]=netId}for(let[chipId,chip]of Object.entries(inputProblem.chipMap)){let chipPins=chip.pins.map(p3=>inputProblem.chipPinMap[p3]),placement=basicLayout.chipPlacements[chipId];if(!placement)continue;let width,height;if(chip.size&&Number.isFinite(chip.size.x)&&Number.isFinite(chip.size.y))width=chip.size.x,height=chip.size.y;else{let xs3=chipPins.map(p3=>p3.offset.x),ys3=chipPins.map(p3=>p3.offset.y),minX=xs3.length?Math.min(...xs3):-5,maxX=xs3.length?Math.max(...xs3):5,minY=ys3.length?Math.min(...ys3):-5,maxY=ys3.length?Math.max(...ys3):5;width=Math.max(10,maxX-minX+6),height=Math.max(10,maxY-minY+6)}let chipCenterX=placement.x,chipCenterY=placement.y,rotatedDims=getRotatedDimensions(width,height,placement.ccwRotationDegrees),chipLabel=chip.fixedPosition?`${chipId} [fixed]`:chipId;inputViz.rects.push({center:{x:chipCenterX,y:chipCenterY},width:rotatedDims.width,height:rotatedDims.height,label:chipLabel,fill:getChipFillColor(chipId,!!chip.fixedPosition),stroke:"none"}),inputViz.texts.push({x:chipCenterX,y:chipCenterY,text:chipLabel,fontSize:getChipLabelFontSize(rotatedDims.width,rotatedDims.height)});for(let pin of chipPins){let rotatedOffset=rotatePoint5(pin.offset,placement.ccwRotationDegrees),pinAbsX=placement.x+rotatedOffset.x,pinAbsY=placement.y+rotatedOffset.y,netId=pinToNetMap[pin.pinId],label=netId?`${pin.pinId} (${netId})`:pin.pinId;inputViz.points.push({x:pinAbsX,y:pinAbsY,label})}}let netToPins={};for(let[pinId,netId]of Object.entries(pinToNetMap))netToPins[netId]||(netToPins[netId]=[]),netToPins[netId].push(pinId);for(let[,pinIds]of Object.entries(netToPins)){let pinPositions=pinIds.map(pinId=>{let chipPin=inputProblem.chipPinMap[pinId];if(chipPin){for(let[chipId,chip]of Object.entries(inputProblem.chipMap))if(chip.pins.includes(pinId)){let placement=basicLayout.chipPlacements[chipId];if(placement){let rotatedOffset=rotatePoint5(chipPin.offset,placement.ccwRotationDegrees);return{x:placement.x+rotatedOffset.x,y:placement.y+rotatedOffset.y}}}return chipPin.offset}return null}).filter(Boolean);for(let i6=0;i6<pinPositions.length;i6++)for(let j6=i6+1;j6<pinPositions.length;j6++)inputViz.lines.push({points:[pinPositions[i6],pinPositions[j6]],strokeColor:"rgba(0,0,0,0.1)"})}let getAbsolutePositionForPin=pinId=>{let chipPin=inputProblem.chipPinMap[pinId];if(chipPin){for(let[chipId,chip]of Object.entries(inputProblem.chipMap))if(chip.pins.includes(pinId)){let placement=basicLayout.chipPlacements[chipId];if(placement){let rotatedOffset=rotatePoint5(chipPin.offset,placement.ccwRotationDegrees);return{x:placement.x+rotatedOffset.x,y:placement.y+rotatedOffset.y}}}return chipPin.offset}return null},seenStrongConn=new Set;for(let[connKey,connected]of Object.entries(inputProblem.pinStrongConnMap)){if(!connected)continue;let[pinA,pinB]=connKey.split("-"),uniqueKey=pinA<pinB?`${pinA}-${pinB}`:`${pinB}-${pinA}`;if(seenStrongConn.has(uniqueKey))continue;seenStrongConn.add(uniqueKey);let p12=getAbsolutePositionForPin(pinA),p22=getAbsolutePositionForPin(pinB);!p12||!p22||inputViz.lines.push({points:[p12,p22]})}return inputViz}var hashInputProblem=inputProblem=>JSON.stringify(inputProblem),cachedProblems=new Map;function doBasicInputProblemLayout(inputProblem){let problemHash=hashInputProblem(inputProblem);if(cachedProblems.has(problemHash))return structuredClone(cachedProblems.get(problemHash));let components=Object.entries(inputProblem.chipMap).map(([chipId,chip])=>{let pads=chip.pins.map(pinId=>inputProblem.chipPinMap[pinId]).map(pin=>{let networkId=pin.pinId;for(let[connKey,connected]of Object.entries(inputProblem.pinStrongConnMap))if(connected&&connKey.includes(pin.pinId)){let[pin1Id,pin2Id]=connKey.split("-");if(pin1Id===pin.pinId||pin2Id===pin.pinId){networkId=[pin1Id,pin2Id].sort().join("_");break}}return{padId:pin.pinId,networkId,type:"rect",offset:pin.offset,size:{x:.001,y:.001}}});pads.push({padId:`${chipId}-body`,networkId:chipId,type:"rect",offset:{x:0,y:0},size:{x:chip.size.x,y:chip.size.y}});let fixedRotation=chip.availableRotations?.[0]??0;return{componentId:chipId,pads,availableRotationDegrees:chip.availableRotations??[0,90,180,270],...chip.fixedPosition&&{isStatic:!0,center:chip.fixedPosition,ccwRotationOffset:fixedRotation}}}),packResult=pack({components,minGap:.4,packOrderStrategy:"largest_to_smallest",packPlacementStrategy:"shortest_connection_along_outline"}),chipPlacements={};for(let component of packResult.components)chipPlacements[component.componentId]={x:component.center.x,y:component.center.y,ccwRotationDegrees:component.ccwRotationOffset};let outputLayout={chipPlacements,groupPlacements:{}};return cachedProblems.set(problemHash,outputLayout),structuredClone(outputLayout)}var createPinOwnerMap=inputProblem=>{let pinOwnerMap=new Map;for(let chip of Object.values(inputProblem.chipMap))for(let pinId of chip.pins)pinOwnerMap.set(pinId,chip);return pinOwnerMap},ChipPartitionsSolver=class extends BaseSolver4{constructor({inputProblem,decouplingCapGroups,crystalCircuitGroups}){super();__publicField(this,"inputProblem");__publicField(this,"partitions",[]);__publicField(this,"decouplingCapGroups");__publicField(this,"crystalCircuitGroups");this.inputProblem=inputProblem,this.decouplingCapGroups=decouplingCapGroups,this.crystalCircuitGroups=crystalCircuitGroups}_step(){this.partitions=this.createPartitions(this.inputProblem),this.solved=!0}createPartitions(inputProblem){let chipIds=Object.keys(inputProblem.chipMap),crystalChipIdSet=new Set,crystalGroupPartitions=[];for(let group of this.crystalCircuitGroups??[]){let groupChipIds=[group.crystalChipId,...group.loadCaps.map(cap2=>cap2.chipId),...group.seriesResistors.map(resistor=>resistor.chipId)].filter(chipId=>inputProblem.chipMap[chipId]);if(!(groupChipIds.length<3)){crystalGroupPartitions.push({chipIds:groupChipIds,group});for(let chipId of groupChipIds)crystalChipIdSet.add(chipId)}}let decapChipIdSet=new Set,decapGroupPartitions=[];if(this.decouplingCapGroups&&this.decouplingCapGroups.length>0)for(let group of this.decouplingCapGroups){let capsOnly=[];for(let capId of group.decouplingCapChipIds)inputProblem.chipMap[capId]&&!crystalChipIdSet.has(capId)&&capsOnly.push(capId);if(capsOnly.length>=2){decapGroupPartitions.push(capsOnly);for(let capId of capsOnly)decapChipIdSet.add(capId)}}let nonDecapChipIds=chipIds.filter(id3=>!decapChipIdSet.has(id3)&&!crystalChipIdSet.has(id3)),adjacencyMap=new Map,pinOwnerMap=createPinOwnerMap(inputProblem);for(let chipId of nonDecapChipIds)adjacencyMap.set(chipId,new Set);for(let[connKey,isConnected]of Object.entries(inputProblem.pinStrongConnMap)){if(!isConnected)continue;let[pin1Id,pin2Id]=connKey.split("-"),owner1=pinOwnerMap.get(pin1Id)?.chipId,owner2=pinOwnerMap.get(pin2Id)?.chipId;owner1&&owner2&&owner1!==owner2&&!decapChipIdSet.has(owner1)&&!decapChipIdSet.has(owner2)&&!crystalChipIdSet.has(owner1)&&!crystalChipIdSet.has(owner2)&&(adjacencyMap.get(owner1).add(owner2),adjacencyMap.get(owner2).add(owner1))}let visited=new Set,nonDecapPartitions=[];for(let componentId of nonDecapChipIds)if(!visited.has(componentId)){let partition=this.dfs(componentId,adjacencyMap,visited);partition.length>0&&nonDecapPartitions.push(partition)}return[...crystalGroupPartitions.map(({chipIds:chipIds2,group})=>this.createInputProblemFromPartition(chipIds2,inputProblem,{partitionType:"crystal_circuit",crystalCircuitGroup:group})),...decapGroupPartitions.map(partition=>{let decouplingCapGroup=this.decouplingCapGroups?.find(group=>group.decouplingCapChipIds.some(capId=>partition.includes(capId)));return this.createInputProblemFromPartition(partition,inputProblem,{partitionType:"decoupling_caps",decouplingMainChipId:decouplingCapGroup?.mainChipId,decouplingMainChipSide:decouplingCapGroup?.mainChipSide})}),...nonDecapPartitions.map(partition=>this.createInputProblemFromPartition(partition,inputProblem))]}dfs(startId,adjacencyMap,visited){let partition=[],stack=[startId];for(;stack.length>0;){let currentId=stack.pop();if(visited.has(currentId))continue;visited.add(currentId),partition.push(currentId);let neighbors=adjacencyMap.get(currentId)||new Set;for(let neighborId of neighbors)visited.has(neighborId)||stack.push(neighborId)}return partition}createInputProblemFromPartition(partition,originalProblem,opts){let chipIds=partition,relevantPinIds=new Set;for(let chipId of chipIds){let chip=originalProblem.chipMap[chipId];for(let pinId of chip.pins)relevantPinIds.add(pinId)}let chipMap={},chipPinMap={},netMap={},pinStrongConnMap={},netConnMap={};for(let chipId of chipIds)chipMap[chipId]=originalProblem.chipMap[chipId];for(let pinId of relevantPinIds)originalProblem.chipPinMap[pinId]&&(chipPinMap[pinId]=originalProblem.chipPinMap[pinId]);for(let[connKey,isConnected]of Object.entries(originalProblem.pinStrongConnMap)){let[pin1Id,pin2Id]=connKey.split("-");relevantPinIds.has(pin1Id)&&relevantPinIds.has(pin2Id)&&(pinStrongConnMap[connKey]=isConnected)}let relevantNetIds=new Set;for(let[connKey,isConnected]of Object.entries(originalProblem.netConnMap)){if(!isConnected)continue;let[pinId,netId]=connKey.split("-");relevantPinIds.has(pinId)&&(relevantNetIds.add(netId),netConnMap[connKey]=isConnected)}for(let netId of relevantNetIds)originalProblem.netMap[netId]&&(netMap[netId]=originalProblem.netMap[netId]);return{...originalProblem,chipMap,chipPinMap,netMap,pinStrongConnMap,netConnMap,isPartition:!0,partitionType:opts?.partitionType,decouplingMainChipId:opts?.decouplingMainChipId,decouplingMainChipSide:opts?.decouplingMainChipSide,crystalCircuitGroup:opts?.crystalCircuitGroup}}visualize(){if(this.partitions.length===0){let layout=doBasicInputProblemLayout(this.inputProblem);return visualizeInputProblem(this.inputProblem,layout)}let partitionVisualizations=this.partitions.map(partition=>{let layout=doBasicInputProblemLayout(partition);return visualizeInputProblem(partition,layout)}),titles=this.partitions.map((_6,index)=>`partition${index}`);return stackGraphicsHorizontally(partitionVisualizations,{titles})}},getColorFromString=(string,alpha=1)=>{let hash=0;for(let i6=0;i6<string.length;i6++){let char=string.charCodeAt(i6);hash=(hash<<5)-hash+char,hash=hash&hash}return`hsl(${Math.abs(hash)%360}, 70%, 50%, ${alpha})`},normalizeQuarterTurn=ccwRotationDegrees=>(Math.round(ccwRotationDegrees/90)*90%360+360)%360,rotatePinOffset=(offset,ccwRotationDegrees)=>{switch(normalizeQuarterTurn(ccwRotationDegrees)){case 90:return{x:-offset.y,y:offset.x};case 180:return{x:-offset.x,y:-offset.y};case 270:return{x:offset.y,y:-offset.x};default:return{x:offset.x,y:offset.y}}},getRotatedSize=(size3,ccwRotationDegrees)=>{let turn=normalizeQuarterTurn(ccwRotationDegrees);return turn===90||turn===270?{x:size3.y,y:size3.x}:{x:size3.x,y:size3.y}},getDecouplingRailNetId=({inputProblem,netIds})=>{let positiveNetIds=netIds.filter(netId=>inputProblem.netMap[netId]?.isPositiveVoltageSource);if(positiveNetIds.length===1)return positiveNetIds[0];let groundNetIds=netIds.filter(netId=>inputProblem.netMap[netId]?.isGround),nonGroundNetIds=netIds.filter(netId=>{let net=inputProblem.netMap[netId];return net?!net.isGround:!1});return groundNetIds.length!==1||nonGroundNetIds.length!==1?null:nonGroundNetIds[0]},MIN_CAPACITORS_PER_GROUP=2,netPairsMatch=(firstNetPair,secondNetPair)=>firstNetPair[0]===secondNetPair[0]&&firstNetPair[1]===secondNetPair[1],groupGroundedCapacitorsByNetPair=({groundedCapacitorsWithoutPowerMetadata})=>{let groundedCapacitorGroups=[];for(let groundedCapacitor of groundedCapacitorsWithoutPowerMetadata){let existingGroup=groundedCapacitorGroups.find(group=>netPairsMatch(group.netPair,groundedCapacitor.netPair));if(existingGroup){existingGroup.capacitorChipIds.push(groundedCapacitor.capacitorChipId);continue}groundedCapacitorGroups.push({capacitorChipIds:[groundedCapacitor.capacitorChipId],netPair:groundedCapacitor.netPair})}return groundedCapacitorGroups.filter(group=>group.capacitorChipIds.length>=MIN_CAPACITORS_PER_GROUP)},IdentifyDecouplingCapsSolver=class extends BaseSolver4{constructor(inputProblem){super();__publicField(this,"inputProblem");__publicField(this,"queuedChips");__publicField(this,"outputDecouplingCapGroups",[]);__publicField(this,"groundedCapacitorsWithoutPowerMetadata",[]);__publicField(this,"groupsByMainChipId",new Map);__publicField(this,"lastChip",null);this.inputProblem=inputProblem,this.queuedChips=Object.values(inputProblem.chipMap)}isTwoPinRestrictedRotation(chip){if(chip.pins.length!==2||!chip.availableRotations)return!1;let allowed=new Set([0,180]);return chip.availableRotations.length>0&&(chip.availableRotations.length===1||chip.availableRotations.every(r6=>allowed.has(r6)))}pinsOnOppositeYSidesAfterRotation(chip){if(chip.pins.length!==2)return!1;let[p12,p22]=chip.pins,cp1=this.inputProblem.chipPinMap[p12],cp22=this.inputProblem.chipPinMap[p22];if(!cp1||!cp22)return!1;let rotation5=chip.availableRotations?.[0]??0,offset1=rotatePinOffset(cp1.offset,rotation5),offset2=rotatePinOffset(cp22.offset,rotation5),verticalSeparation=Math.abs(offset1.y-offset2.y);return verticalSeparation>0&&verticalSeparation>=Math.abs(offset1.x-offset2.x)}getStronglyConnectedNeighborChips(pinId){let neighbors=new Set;for(let[connKey,connected]of Object.entries(this.inputProblem.pinStrongConnMap)){if(!connected)continue;let[a6,b6]=connKey.split("-");if(a6===pinId){let otherChipId=b6.split(".")[0];neighbors.add(otherChipId)}else if(b6===pinId){let otherChipId=a6.split(".")[0];neighbors.add(otherChipId)}}return neighbors}findMainChipIdForCap(capChip,netPair){return this.findStronglyConnectedMainChipId(capChip)??this.findRailSharingMainChipId(capChip,netPair)??this.findUniqueMainChipSharingNetPair(netPair)}findUniqueMainChipSharingNetPair(netPair){let candidates=Object.values(this.inputProblem.chipMap).filter(chip=>!chip.isCapacitor&&netPair.every(netId=>chip.pins.some(pinId=>this.getNetIdsForPin(pinId).has(netId))));return candidates.length===1?candidates[0].chipId:null}findStronglyConnectedMainChipId(capChip){let strongConnectionCounts=new Map;for(let pinId of capChip.pins){let neighborChipIds=this.getStronglyConnectedNeighborChips(pinId);for(let neighborChipId of neighborChipIds){if(neighborChipId===capChip.chipId)continue;let strongConnectionCount=strongConnectionCounts.get(neighborChipId)||0;strongConnectionCounts.set(neighborChipId,strongConnectionCount+1)}}let mainChipId=null,mainChipConnectionCount=0;for(let[chipId,strongConnectionCount]of strongConnectionCounts)strongConnectionCount<mainChipConnectionCount||mainChipId!==null&&strongConnectionCount===mainChipConnectionCount&&chipId>mainChipId||(mainChipId=chipId,mainChipConnectionCount=strongConnectionCount);return mainChipId}findRailSharingMainChipId(capChip,netPair){for(let sibling of Object.values(this.inputProblem.chipMap)){if(sibling.chipId===capChip.chipId||!sibling.isCapacitor)continue;let siblingPair=this.getNormalizedNetPair(sibling);if(!siblingPair||siblingPair[0]!==netPair[0]||siblingPair[1]!==netPair[1])continue;let mainChipId=this.findStronglyConnectedMainChipId(sibling);if(mainChipId)return mainChipId}return null}getNetIdsForPin(pinId){let nets=new Set;for(let[connKey,connected]of Object.entries(this.inputProblem.netConnMap)){if(!connected)continue;let[p3,n3]=connKey.split("-");p3===pinId&&nets.add(n3)}return nets}getNormalizedNetPair(capChip){if(capChip.pins.length!==2)return null;let nets=new Set;for(let pinId of capChip.pins){let pinNets=this.getNetIdsForPin(pinId);for(let n3 of pinNets)nets.add(n3)}if(nets.size!==2)return null;let[a6,b6]=Array.from(nets).sort();return[a6,b6]}addToGroup(mainChipId,netPair,capChipId){let[n12,n22]=netPair,groupKey=`${mainChipId}__${n12}__${n22}`,group=this.groupsByMainChipId.get(groupKey);group||(group={decouplingCapGroupId:`decap_group_${mainChipId}__${n12}__${n22}`,mainChipId,mainChipSide:this.getMainChipSide(mainChipId,netPair),netPair:[n12,n22],decouplingCapChipIds:[]},this.groupsByMainChipId.set(groupKey,group),this.outputDecouplingCapGroups.push(group)),group.decouplingCapChipIds.includes(capChipId)||group.decouplingCapChipIds.push(capChipId)}getMainChipSide(mainChipId,netPair){let mainChip=this.inputProblem.chipMap[mainChipId];if(!mainChip)return null;let railNetId=getDecouplingRailNetId({inputProblem:this.inputProblem,netIds:netPair});if(!railNetId)return null;let sideCounts=new Map;for(let pinId of mainChip.pins){let pin=this.inputProblem.chipPinMap[pinId];!pin||!this.getNetIdsForPin(pinId).has(railNetId)||sideCounts.set(pin.side,(sideCounts.get(pin.side)??0)+1)}let selectedSide=null,largestCount=0;for(let[side,count]of sideCounts)count<=largestCount||(selectedSide=side,largestCount=count);return selectedSide}addGroundedCapacitorGroupsWithoutPowerMetadata(){let groundedCapacitorGroups=groupGroundedCapacitorsByNetPair({groundedCapacitorsWithoutPowerMetadata:this.groundedCapacitorsWithoutPowerMetadata});for(let groundedCapacitorGroup of groundedCapacitorGroups){let mainChipId=this.findUniqueMainChipSharingNetPair(groundedCapacitorGroup.netPair);if(mainChipId)for(let capacitorChipId of groundedCapacitorGroup.capacitorChipIds)this.addToGroup(mainChipId,groundedCapacitorGroup.netPair,capacitorChipId)}}_step(){let currentChip=this.queuedChips.shift();if(this.lastChip=currentChip??null,!currentChip){this.addGroundedCapacitorGroupsWithoutPowerMetadata(),this.solved=!0;return}if(!currentChip.isCapacitor||!(this.isTwoPinRestrictedRotation(currentChip)&&this.pinsOnOppositeYSidesAfterRotation(currentChip)))return;let netPair=this.getNormalizedNetPair(currentChip);if(!netPair)return;let[n12,n22]=netPair,net1=this.inputProblem.netMap[n12],net2=this.inputProblem.netMap[n22];if(!(net1?.isGround&&net2?.isPositiveVoltageSource||net2?.isGround&&net1?.isPositiveVoltageSource)){netPair.filter(netId=>this.inputProblem.netMap[netId]?.isGround).length===1&&this.groundedCapacitorsWithoutPowerMetadata.push({capacitorChipId:currentChip.chipId,netPair});return}let mainChipId=this.findMainChipIdForCap(currentChip,netPair);mainChipId&&this.addToGroup(mainChipId,netPair,currentChip.chipId)}visualize(){let basicLayout=doBasicInputProblemLayout(this.inputProblem),graphics=visualizeInputProblem(this.inputProblem,basicLayout),chipDecapGroupMap=new Map;for(let group of this.outputDecouplingCapGroups){chipDecapGroupMap.set(group.mainChipId,group);for(let capChipId of group.decouplingCapChipIds)chipDecapGroupMap.set(capChipId,group)}for(let rect of graphics.rects||[])rect.label!==this.lastChip?.chipId&&(rect.fill="rgba(0,0,0,0.5)");for(let rect of graphics.rects||[]){let chipId=rect.label,group=chipDecapGroupMap.get(chipId);group&&(rect.label=`${rect.label}
643
643
  ${group.decouplingCapGroupId}`,rect.fill=getColorFromString(group.decouplingCapGroupId,.8))}return graphics}getConstructorParams(){return[this.inputProblem]}computeProgress(){let total=Object.keys(this.inputProblem.chipMap).length||1,processed=total-this.queuedChips.length;return Math.min(1,Math.max(0,processed/total))}},IdentifyCrystalCircuitsSolver=class extends BaseSolver4{constructor(inputProblem){super();__publicField(this,"inputProblem");__publicField(this,"queuedCrystals");__publicField(this,"outputCrystalCircuitGroups",[]);this.inputProblem=inputProblem,this.queuedCrystals=Object.values(inputProblem.chipMap).filter(chip=>chip.isCrystal)}getNetIdsForPin(pinId){let nets=new Set;for(let netId of Object.keys(this.inputProblem.netMap))this.inputProblem.netConnMap[`${pinId}-${netId}`]&&nets.add(netId);return nets}pinsAreConnected(pinA,pinB){if(this.inputProblem.pinStrongConnMap[`${pinA}-${pinB}`]||this.inputProblem.pinStrongConnMap[`${pinB}-${pinA}`])return!0;let netsA=this.getNetIdsForPin(pinA);return Array.from(this.getNetIdsForPin(pinB)).some(netId=>netsA.has(netId))}getGroundNetId(pinId){for(let netId of this.getNetIdsForPin(pinId))if(this.inputProblem.netMap[netId]?.isGround)return netId;return null}findLoadCapsForCrystalPin(crystalPinId){let candidates=[];for(let chip of Object.values(this.inputProblem.chipMap))if(!(!chip.isCapacitor||chip.pins.length!==2))for(let signalPinId of chip.pins){if(!this.pinsAreConnected(crystalPinId,signalPinId))continue;let groundPinId=chip.pins.find(pinId=>pinId!==signalPinId);if(!groundPinId)continue;let groundNetId=this.getGroundNetId(groundPinId);groundNetId&&candidates.push({chipId:chip.chipId,signalPinId,groundPinId,groundNetId})}return candidates}findSeriesResistors(activeCrystalPinIds,loadCapIds){let seriesResistors=[];for(let chip of Object.values(this.inputProblem.chipMap)){if(!chip.isResistor||chip.pins.length!==2||loadCapIds.has(chip.chipId))continue;let activeConnections=activeCrystalPinIds.flatMap(crystalPinId=>chip.pins.filter(pinId=>this.pinsAreConnected(crystalPinId,pinId)).map(connectedPinId=>({crystalPinId,connectedPinId})));if(activeConnections.length!==1)continue;let connection=activeConnections[0],outwardPinId=chip.pins.find(pinId=>pinId!==connection.connectedPinId);!outwardPinId||this.getGroundNetId(outwardPinId)||seriesResistors.push({chipId:chip.chipId,crystalPinId:connection.crystalPinId,connectedPinId:connection.connectedPinId})}return seriesResistors}identifyCrystal(crystal2){let activeCrystalPinIds=crystal2.pins.filter(pinId=>!this.getGroundNetId(pinId));if(activeCrystalPinIds.length!==2)return null;let[pinA,pinB]=activeCrystalPinIds,capsA=this.findLoadCapsForCrystalPin(pinA),capsB=this.findLoadCapsForCrystalPin(pinB);if(capsA.length!==1||capsB.length!==1||capsA[0].chipId===capsB[0].chipId||capsA[0].groundNetId!==capsB[0].groundNetId)return null;let loadCaps=[{chipId:capsA[0].chipId,signalPinId:capsA[0].signalPinId,groundPinId:capsA[0].groundPinId},{chipId:capsB[0].chipId,signalPinId:capsB[0].signalPinId,groundPinId:capsB[0].groundPinId}],loadCapIds=new Set(loadCaps.map(cap2=>cap2.chipId));return{crystalCircuitGroupId:`crystal_circuit_${crystal2.chipId}`,crystalChipId:crystal2.chipId,activeCrystalPinIds:[pinA,pinB],loadCaps,groundNetId:capsA[0].groundNetId,seriesResistors:this.findSeriesResistors([pinA,pinB],loadCapIds)}}_step(){let crystal2=this.queuedCrystals.shift();if(!crystal2){this.solved=!0;return}let group=this.identifyCrystal(crystal2);group&&this.outputCrystalCircuitGroups.push(group)}visualize(){return visualizeInputProblem(this.inputProblem,doBasicInputProblemLayout(this.inputProblem))}getConstructorParams(){return[this.inputProblem]}computeProgress(){let crystalCount=Object.values(this.inputProblem.chipMap).filter(chip=>chip.isCrystal).length;return crystalCount===0?1:(crystalCount-this.queuedCrystals.length)/crystalCount}},getGapBetweenAlignedChips=({firstChipId,secondChipId},inputProblem)=>{let firstChip=inputProblem.chipMap[firstChipId],secondChip=inputProblem.chipMap[secondChipId];return firstChip?.isCapacitor&&secondChip?.isCapacitor?inputProblem.decouplingCapsGap??inputProblem.chipGap:inputProblem.partitionGap},AlignPowerGroundRowsSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputLayout");__publicField(this,"outputLayout",null);this.inputProblem=params.inputProblem,this.inputLayout=params.inputLayout}_step(){this.outputLayout=this.createAlignedLayout()??this.inputLayout,this.solved=!0}isPowerGroundNet(netId){let net=this.inputProblem.netMap[netId];return net?.isPositiveVoltageSource===!0||net?.isGround===!0}getPinNetIds(pinId){let netIds=[];for(let[connKey,connected]of Object.entries(this.inputProblem.netConnMap))connected&&connKey.startsWith(`${pinId}-`)&&netIds.push(connKey.slice(pinId.length+1));return netIds}pinHasStrongConnection(pinId){for(let[connKey,connected]of Object.entries(this.inputProblem.pinStrongConnMap))if(connected&&(connKey.startsWith(`${pinId}-`)||connKey.endsWith(`-${pinId}`)))return!0;return!1}getAlignmentGroupId(chip){if(chip.fixedPosition||chip.pins.length!==2)return null;let signalNetIds=new Set,connectedPowerGroundPinCount=0;for(let pinId of chip.pins){let pinNetIds=this.getPinNetIds(pinId);if(pinNetIds.length===0){if(this.pinHasStrongConnection(pinId))return null;continue}let pinHasPowerGroundNet=!1;for(let netId of pinNetIds)this.isPowerGroundNet(netId)?pinHasPowerGroundNet=!0:signalNetIds.add(netId);pinHasPowerGroundNet&&connectedPowerGroundPinCount++}return connectedPowerGroundPinCount===0?null:signalNetIds.size===0?"power-ground":signalNetIds.size===1?`signal:${[...signalNetIds][0]}`:null}getAlignmentGroups(){let chipIds=Object.keys(this.inputProblem.chipMap);if(chipIds.length<2)return null;let groupMap=new Map;for(let chipId of chipIds){let chip=this.inputProblem.chipMap[chipId];if(!chip||!this.inputLayout.chipPlacements[chipId])continue;let groupId=this.getAlignmentGroupId(chip);if(!groupId)continue;let groupChipIds=groupMap.get(groupId)??[];groupChipIds.push(chipId),groupMap.set(groupId,groupChipIds)}return[...groupMap.values()].filter(groupChipIds=>groupChipIds.length>1).map(groupChipIds=>({chipIds:groupChipIds}))}alignGroup(chipPlacements,chipIds){if(chipIds.length<2)return;let cursorX=0,rowY=chipIds.reduce((sum,chipId)=>sum+this.inputLayout.chipPlacements[chipId].y,0)/chipIds.length,rowCenterX=chipIds.reduce((sum,chipId)=>sum+this.inputLayout.chipPlacements[chipId].x,0)/chipIds.length;for(let[index,chipId]of chipIds.entries()){let previousChipId=chipIds[index-1];previousChipId&&(cursorX+=getGapBetweenAlignedChips({firstChipId:previousChipId,secondChipId:chipId},this.inputProblem));let chip=this.inputProblem.chipMap[chipId],originalPlacement=this.inputLayout.chipPlacements[chipId],isRotated=originalPlacement.ccwRotationDegrees===90||originalPlacement.ccwRotationDegrees===270,width=chip.size.x;isRotated&&(width=chip.size.y);let x6=cursorX+width/2;chipPlacements[chipId]={x:x6,y:rowY,ccwRotationDegrees:originalPlacement.ccwRotationDegrees},cursorX+=width}let rowWidth=cursorX;for(let chipId of chipIds)chipPlacements[chipId].x+=rowCenterX-rowWidth/2}hasChipOverlap(chipPlacements){let chipIds=Object.keys(this.inputProblem.chipMap);for(let i6=0;i6<chipIds.length;i6++){let chipIdA=chipIds[i6],chipA=this.inputProblem.chipMap[chipIdA],placementA=chipPlacements[chipIdA];if(!placementA)continue;let isRotatedA=placementA.ccwRotationDegrees===90||placementA.ccwRotationDegrees===270,widthA=chipA.size.x,heightA=chipA.size.y;isRotatedA&&(widthA=chipA.size.y,heightA=chipA.size.x);for(let j6=i6+1;j6<chipIds.length;j6++){let chipIdB=chipIds[j6],chipB=this.inputProblem.chipMap[chipIdB],placementB=chipPlacements[chipIdB];if(!placementB)continue;let isRotatedB=placementB.ccwRotationDegrees===90||placementB.ccwRotationDegrees===270,widthB=chipB.size.x,heightB=chipB.size.y;isRotatedB&&(widthB=chipB.size.y,heightB=chipB.size.x);let overlapsX=Math.abs(placementA.x-placementB.x)<(widthA+widthB)/2,overlapsY=Math.abs(placementA.y-placementB.y)<(heightA+heightB)/2;if(overlapsX&&overlapsY)return!0}}return!1}createAlignedLayout(){let groups=this.getAlignmentGroups();if(!groups)return null;let chipPlacements={...this.inputLayout.chipPlacements};for(let group of groups)this.alignGroup(chipPlacements,group.chipIds);return this.hasChipOverlap(chipPlacements)?null:{chipPlacements,groupPlacements:{...this.inputLayout.groupPlacements}}}visualize(){return visualizeInputProblem(this.inputProblem,this.outputLayout??this.inputLayout)}getConstructorParams(){return[{inputProblem:this.inputProblem,inputLayout:this.inputLayout}]}},getPinIdToStronglyConnectedPinsObj=inputProblem=>{let pinIdToStronglyConnectedPins={},pinIds=Object.keys(inputProblem.chipPinMap);for(let i6=0;i6<pinIds.length;i6++)for(let j6=i6+1;j6<pinIds.length;j6++){let pinId1=pinIds[i6],pinId2=pinIds[j6];(inputProblem.pinStrongConnMap[`${pinId1}-${pinId2}`]||inputProblem.pinStrongConnMap[`${pinId2}-${pinId1}`])&&(pinIdToStronglyConnectedPins[pinId1]??(pinIdToStronglyConnectedPins[pinId1]=[]),pinIdToStronglyConnectedPins[pinId2]??(pinIdToStronglyConnectedPins[pinId2]=[]),pinIdToStronglyConnectedPins[pinId1].push(inputProblem.chipPinMap[pinId2]),pinIdToStronglyConnectedPins[pinId2].push(inputProblem.chipPinMap[pinId1]))}return pinIdToStronglyConnectedPins},getPlacementBounds=({placement,size:size3,margin=0})=>{let rotatedSize=getRotatedSize(size3,placement.ccwRotationDegrees);return getBoundFromCenteredRect({center:placement,width:rotatedSize.x+margin*2,height:rotatedSize.y+margin*2})},placementsOverlap=({inputProblem,chipIdA,placementA,chipIdB,placementB})=>{let boundsA=getPlacementBounds({placement:placementA,size:inputProblem.chipMap[chipIdA].size,margin:inputProblem.chipGap}),boundsB=getPlacementBounds({placement:placementB,size:inputProblem.chipMap[chipIdB].size});return boundsAreaOverlap(boundsA,boundsB)>0},MINIMUM_COLLISION_SEARCH_STEP=.2,getLooseTestPointRowAxes=({looseTestPointChipIds},context)=>{let xPositions=looseTestPointChipIds.map(chipId=>context.chipPlacements[chipId].x),yPositions=looseTestPointChipIds.map(chipId=>context.chipPlacements[chipId].y),horizontalSpan=Math.max(...xPositions)-Math.min(...xPositions),verticalSpan=Math.max(...yPositions)-Math.min(...yPositions);return horizontalSpan>=verticalSpan?{perpendicularAxis:"y",tangentAxis:"x"}:{perpendicularAxis:"x",tangentAxis:"y"}},packLooseTestPointRow=({looseTestPointChipIds,perpendicularAxis,tangentAxis},context)=>{let perpendicularCenter=looseTestPointChipIds.reduce((sum,chipId)=>sum+context.chipPlacements[chipId][perpendicularAxis],0)/looseTestPointChipIds.length,orderedTestPointChipIds=[...looseTestPointChipIds].sort((chipIdA,chipIdB)=>context.chipPlacements[chipIdA][tangentAxis]-context.chipPlacements[chipIdB][tangentAxis]),testPointRow={},previousTestPointChipId;for(let chipId of orderedTestPointChipIds){let placement={...context.chipPlacements[chipId],[perpendicularAxis]:perpendicularCenter};if(previousTestPointChipId){let previousPlacement=testPointRow[previousTestPointChipId],previousSize=getRotatedSize(context.inputProblem.chipMap[previousTestPointChipId].size,previousPlacement.ccwRotationDegrees),size3=getRotatedSize(context.inputProblem.chipMap[chipId].size,placement.ccwRotationDegrees),minimumTangentPosition=previousPlacement[tangentAxis]+previousSize[tangentAxis]/2+context.inputProblem.chipGap+size3[tangentAxis]/2;placement[tangentAxis]<minimumTangentPosition&&(placement[tangentAxis]=minimumTangentPosition)}testPointRow[chipId]=placement,previousTestPointChipId=chipId}return testPointRow},testPointRowOverlapsOtherChips=({looseTestPointChipIds,testPointRow},context)=>{let looseTestPointChipIdSet=new Set(looseTestPointChipIds);return looseTestPointChipIds.some(chipId=>Object.entries(context.chipPlacements).some(([otherChipId,otherPlacement])=>!looseTestPointChipIdSet.has(otherChipId)&&placementsOverlap({inputProblem:context.inputProblem,chipIdA:chipId,placementA:testPointRow[chipId],chipIdB:otherChipId,placementB:otherPlacement})))},moveLooseTestPointRowUntilClear=({looseTestPointChipIds,perpendicularAxis,testPointRow},context)=>{let searchStep=Math.max(context.inputProblem.chipGap,MINIMUM_COLLISION_SEARCH_STEP),searchStepIndex=0;for(;;){let offsets=[0];searchStepIndex>0&&(offsets.length=0,offsets.push(-searchStepIndex*searchStep,searchStepIndex*searchStep));for(let offset of offsets){let shiftedTestPointRow=structuredClone(testPointRow);for(let chipId of looseTestPointChipIds)shiftedTestPointRow[chipId][perpendicularAxis]+=offset;if(!testPointRowOverlapsOtherChips({looseTestPointChipIds,testPointRow:shiftedTestPointRow},context))return shiftedTestPointRow}searchStepIndex++}},alignLooseTestPoints=({anchoredTestPointChipIds},context)=>{let looseTestPointChipIds=Object.values(context.inputProblem.chipMap).filter(chip=>chip.isTestPoint&&!chip.fixedPosition&&chip.pins.length===1&&context.chipPlacements[chip.chipId]&&!anchoredTestPointChipIds.has(chip.chipId)).map(chip=>chip.chipId);if(looseTestPointChipIds.length<2)return;let{perpendicularAxis,tangentAxis}=getLooseTestPointRowAxes({looseTestPointChipIds},context),testPointRow=packLooseTestPointRow({looseTestPointChipIds,perpendicularAxis,tangentAxis},context),clearTestPointRow=moveLooseTestPointRowUntilClear({looseTestPointChipIds,perpendicularAxis,testPointRow},context);for(let[chipId,placement]of Object.entries(clearTestPointRow))context.chipPlacements[chipId]=placement},MAXIMUM_NEARBY_PIN_GAP_IN_PIN_PITCHES=1.5,MINIMUM_COLLISION_SEARCH_STEP2=.2,PIN_POSITION_EPSILON=1e-6,TANGENT_SEARCH_BOUNDARY_PADDING_STEPS=2,TANGENT_SEARCH_PARTITION_GAP_FRACTION=.5,SIDE_VECTORS={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},SIDE_AXES={"x-":{normalAxis:"x",tangentAxis:"y",direction:-1},"x+":{normalAxis:"x",tangentAxis:"y",direction:1},"y-":{normalAxis:"y",tangentAxis:"x",direction:-1},"y+":{normalAxis:"y",tangentAxis:"x",direction:1}},OPPOSITE_SIDE={"x-":"x+","x+":"x-","y-":"y+","y+":"y-"},vectorToSide=vector2=>Math.abs(vector2.x)>Math.abs(vector2.y)?vector2.x<0?"x-":"x+":vector2.y<0?"y-":"y+",rotateSide=(side,ccwRotationDegrees)=>vectorToSide(rotatePinOffset(SIDE_VECTORS[side],ccwRotationDegrees)),getAnchorPinTangentPosition=({anchorChipId,anchorPinId,side},context)=>{let anchorPlacement=context.inputLayout.chipPlacements[anchorChipId],anchorPin=context.inputProblem.chipPinMap[anchorPinId],rotatedOffset=rotatePinOffset(anchorPin.offset,anchorPlacement.ccwRotationDegrees),tangentAxis=SIDE_AXES[side].tangentAxis;return anchorPlacement[tangentAxis]+rotatedOffset[tangentAxis]},splitGroupByPinProximity=({group},context)=>{if(group.members.length<2)return[group];let anchorChip=context.inputProblem.chipMap[group.anchorChipId],anchorPlacement=context.inputLayout.chipPlacements[group.anchorChipId],sidePinPositions=anchorChip.pins.filter(pinId=>{let pin=context.inputProblem.chipPinMap[pinId];return pin&&rotateSide(pin.side,anchorPlacement.ccwRotationDegrees)===group.side}).map(pinId=>getAnchorPinTangentPosition({anchorChipId:group.anchorChipId,anchorPinId:pinId,side:group.side},context)).sort((a6,b6)=>a6-b6),pinGaps=sidePinPositions.slice(1).map((position4,index)=>position4-sidePinPositions[index]).filter(gap=>gap>PIN_POSITION_EPSILON);if(pinGaps.length===0)return[group];let maximumNearbyGap=Math.min(...pinGaps)*MAXIMUM_NEARBY_PIN_GAP_IN_PIN_PITCHES,splitGroups=[],members=[],previousPosition;for(let member of group.members){let position4=getAnchorPinTangentPosition({anchorChipId:member.anchorChipId,anchorPinId:member.anchorPinId,side:member.side},context);previousPosition!==void 0&&position4-previousPosition>maximumNearbyGap+PIN_POSITION_EPSILON&&(splitGroups.push({...group,members}),members=[]),members.push(member),previousPosition=position4}return members.length>0&&splitGroups.push({...group,members}),splitGroups},createTestPointSideGroups=context=>{let pinOwnerMap=createPinOwnerMap(context.inputProblem),pinIdToStronglyConnectedPins=getPinIdToStronglyConnectedPinsObj(context.inputProblem),groups=[];for(let testPoint of Object.values(context.inputProblem.chipMap)){if(!testPoint.isTestPoint||testPoint.fixedPosition||testPoint.pins.length!==1)continue;let testPointPinId=testPoint.pins[0],anchorPin=pinIdToStronglyConnectedPins[testPointPinId]?.[0];if(!anchorPin)continue;let anchorPinId=anchorPin.pinId,anchorChipId=pinOwnerMap.get(anchorPinId)?.chipId;if(!anchorChipId||anchorChipId===testPoint.chipId||context.inputProblem.chipMap[anchorChipId]?.isTestPoint)continue;let anchorPlacement=context.inputLayout.chipPlacements[anchorChipId];if(!anchorPlacement)continue;let side=rotateSide(anchorPin.side,anchorPlacement.ccwRotationDegrees),group=groups.find(candidate=>candidate.anchorChipId===anchorChipId&&candidate.side===side);group||(group={anchorChipId,side,members:[]},groups.push(group)),group.members.push({testPointChipId:testPoint.chipId,testPointPinId,anchorChipId,anchorPinId,side})}for(let group of groups)group.members.sort((a6,b6)=>getAnchorPinTangentPosition({anchorChipId:a6.anchorChipId,anchorPinId:a6.anchorPinId,side:a6.side},context)-getAnchorPinTangentPosition({anchorChipId:b6.anchorChipId,anchorPinId:b6.anchorPinId,side:b6.side},context));return groups.flatMap(group=>splitGroupByPinProximity({group},context))},getTestPointCcwRotationDegrees=({member},context)=>{let chip=context.inputProblem.chipMap[member.testPointChipId],pin=context.inputProblem.chipPinMap[member.testPointPinId],allowedRotations=chip.availableRotations??[0,90,180,270],desiredPinSide=OPPOSITE_SIDE[member.side];return allowedRotations.find(ccwRotationDegrees=>rotateSide(pin.side,ccwRotationDegrees)===desiredPinSide)??allowedRotations[0]},placeTestPointSideGroup=({group},context)=>{let{inputProblem,chipPlacements}=context,anchorPlacement=chipPlacements[group.anchorChipId],anchorChip=inputProblem.chipMap[group.anchorChipId],anchorBounds=getPlacementBounds({placement:anchorPlacement,size:anchorChip.size}),{normalAxis,tangentAxis,direction:direction2}=SIDE_AXES[group.side],members=group.members.map(member=>{let anchorPin=inputProblem.chipPinMap[member.anchorPinId],rotatedAnchorPinOffset=rotatePinOffset(anchorPin.offset,anchorPlacement.ccwRotationDegrees),anchorPinPosition={x:anchorPlacement.x+rotatedAnchorPinOffset.x,y:anchorPlacement.y+rotatedAnchorPinOffset.y},ccwRotationDegrees=getTestPointCcwRotationDegrees({member},context),size3=getRotatedSize(inputProblem.chipMap[member.testPointChipId].size,ccwRotationDegrees);return{member,anchorPinPosition,ccwRotationDegrees,size:size3}}).sort((a6,b6)=>a6.anchorPinPosition[tangentAxis]-b6.anchorPinPosition[tangentAxis]),previousTangentEnd=-1/0;for(let memberPlacement of members){let tangentExtent=memberPlacement.size[tangentAxis],desiredTangent=memberPlacement.anchorPinPosition[tangentAxis],tangentCenter=Math.max(desiredTangent,previousTangentEnd+inputProblem.chipGap+tangentExtent/2);previousTangentEnd=tangentCenter+tangentExtent/2;let pinNormal=memberPlacement.anchorPinPosition[normalAxis],anchorEdge=anchorBounds.minX;normalAxis==="y"&&(anchorEdge=anchorBounds.minY),normalAxis==="x"&&direction2>0&&(anchorEdge=anchorBounds.maxX),normalAxis==="y"&&direction2>0&&(anchorEdge=anchorBounds.maxY);let outwardBoundary=Math.min(anchorEdge,pinNormal);direction2>0&&(outwardBoundary=Math.max(anchorEdge,pinNormal));let normalCenter=outwardBoundary+direction2*(inputProblem.chipGap+memberPlacement.size[normalAxis]/2),x6=normalCenter,y2=tangentCenter;normalAxis==="y"&&(x6=tangentCenter,y2=normalCenter),chipPlacements[memberPlacement.member.testPointChipId]={x:x6,y:y2,ccwRotationDegrees:memberPlacement.ccwRotationDegrees}}},testPointGroupOverlapsOtherChips=({group},context)=>{let groupChipIds=new Set(group.members.map(member=>member.testPointChipId));return group.members.some(member=>{let testPointPlacement=context.chipPlacements[member.testPointChipId];return Object.entries(context.chipPlacements).some(([otherChipId,otherPlacement])=>otherChipId!==group.anchorChipId&&!groupChipIds.has(otherChipId)&&placementsOverlap({inputProblem:context.inputProblem,chipIdA:member.testPointChipId,placementA:testPointPlacement,chipIdB:otherChipId,placementB:otherPlacement}))})},moveTestPointGroupOutwardUntilClear=({group},context)=>{let{normalAxis,direction:direction2}=SIDE_AXES[group.side],searchStep=Math.max(context.inputProblem.chipGap,MINIMUM_COLLISION_SEARCH_STEP2);for(;testPointGroupOverlapsOtherChips({group},context);)for(let member of group.members)context.chipPlacements[member.testPointChipId][normalAxis]+=direction2*searchStep},getAbsolutePinPosition=({inputProblem,pinId,placement})=>{let pin=inputProblem.chipPinMap[pinId],rotatedOffset=rotatePinOffset(pin.offset,placement.ccwRotationDegrees);return{x:placement.x+rotatedOffset.x,y:placement.y+rotatedOffset.y}},countConnectionBodyCrossings=({group},context)=>{let groupChipIds=new Set(group.members.map(member=>member.testPointChipId)),crossingCount=0;for(let member of group.members){let segmentStart=getAbsolutePinPosition({inputProblem:context.inputProblem,pinId:member.testPointPinId,placement:context.chipPlacements[member.testPointChipId]}),segmentEnd=getAbsolutePinPosition({inputProblem:context.inputProblem,pinId:member.anchorPinId,placement:context.chipPlacements[member.anchorChipId]});for(let[otherChipId,otherPlacement]of Object.entries(context.chipPlacements)){if(otherChipId===member.anchorChipId||groupChipIds.has(otherChipId))continue;let otherBounds=getPlacementBounds({placement:otherPlacement,size:context.inputProblem.chipMap[otherChipId].size});doesSegmentIntersectRect(segmentStart,segmentEnd,otherBounds)&&crossingCount++}}return crossingCount},getMaximumTangentSearchSteps=({group,tangentAxis,searchStep},context)=>{let groupChipIds=new Set(group.members.map(member=>member.testPointChipId)),groupCenter=group.members.reduce((sum,member)=>sum+context.chipPlacements[member.testPointChipId][tangentAxis],0)/group.members.length,maximumGroupExtent=Math.max(...group.members.map(member=>{let placement=context.chipPlacements[member.testPointChipId];return getRotatedSize(context.inputProblem.chipMap[member.testPointChipId].size,placement.ccwRotationDegrees)[tangentAxis]})),maximumSearchDistance=Object.entries(context.chipPlacements).reduce((maximumDistance,[chipId,placement])=>{if(groupChipIds.has(chipId))return maximumDistance;let chipExtent=getRotatedSize(context.inputProblem.chipMap[chipId].size,placement.ccwRotationDegrees)[tangentAxis];return Math.max(maximumDistance,Math.abs(placement[tangentAxis]-groupCenter)+chipExtent+maximumGroupExtent)},0)+context.inputProblem.partitionGap;return Math.ceil(maximumSearchDistance/searchStep)+TANGENT_SEARCH_BOUNDARY_PADDING_STEPS},moveTestPointGroupAlongTangent=({group},context)=>{let{tangentAxis}=SIDE_AXES[group.side],originalPlacements=new Map(group.members.map(member=>[member.testPointChipId,{...context.chipPlacements[member.testPointChipId]}])),searchStep=Math.max(context.inputProblem.partitionGap*TANGENT_SEARCH_PARTITION_GAP_FRACTION,context.inputProblem.chipGap,MINIMUM_COLLISION_SEARCH_STEP2),maximumSearchSteps=getMaximumTangentSearchSteps({group,tangentAxis,searchStep},context),bestOffset=0,bestCrossingCount=Number.POSITIVE_INFINITY;for(let stepIndex=0;stepIndex<=maximumSearchSteps;stepIndex++){let offsets=[0];stepIndex>0&&(offsets.length=0,offsets.push(-stepIndex*searchStep,stepIndex*searchStep));for(let offset of offsets){for(let member of group.members){let originalPlacement=originalPlacements.get(member.testPointChipId);context.chipPlacements[member.testPointChipId]={...originalPlacement,[tangentAxis]:originalPlacement[tangentAxis]+offset}}if(testPointGroupOverlapsOtherChips({group},context))continue;let crossingCount=countConnectionBodyCrossings({group},context);if(crossingCount<bestCrossingCount&&(bestCrossingCount=crossingCount,bestOffset=offset),crossingCount===0)break}if(bestCrossingCount===0)break}for(let member of group.members){let originalPlacement=originalPlacements.get(member.testPointChipId);context.chipPlacements[member.testPointChipId]={...originalPlacement,[tangentAxis]:originalPlacement[tangentAxis]+bestOffset}}},AlignTestPointsSolver=class extends BaseSolver4{constructor(options){super();__publicField(this,"inputProblem");__publicField(this,"inputLayout");__publicField(this,"outputLayout",null);__publicField(this,"testPointSideGroups",[]);__publicField(this,"connectionBodyCrossingCount",0);this.inputProblem=options.inputProblem,this.inputLayout=options.inputLayout}_step(){let chipPlacements=structuredClone(this.inputLayout.chipPlacements),placementContext={inputProblem:this.inputProblem,chipPlacements};this.testPointSideGroups=createTestPointSideGroups({inputProblem:this.inputProblem,inputLayout:this.inputLayout});for(let group of this.testPointSideGroups)placeTestPointSideGroup({group},placementContext);for(let group of this.testPointSideGroups)moveTestPointGroupOutwardUntilClear({group},placementContext),moveTestPointGroupAlongTangent({group},placementContext);this.connectionBodyCrossingCount=this.testPointSideGroups.reduce((crossingCount,group)=>crossingCount+countConnectionBodyCrossings({group},placementContext),0);let anchoredTestPointChipIds=new Set(this.testPointSideGroups.flatMap(group=>group.members.map(member=>member.testPointChipId)));alignLooseTestPoints({anchoredTestPointChipIds},placementContext),this.outputLayout={chipPlacements,groupPlacements:{...this.inputLayout.groupPlacements}},this.solved=!0}visualize(){return visualizeInputProblem(this.inputProblem,this.outputLayout??this.inputLayout)}};function createFilteredNetworkMapping(params){let{inputProblem,pinIdToStronglyConnectedPins}=params,pinToNetworkMap=new Map,filteredPins=new Set,hasStrongConnections=!1,strongConnectedChipSides=new Map;for(let[connKey,connected]of Object.entries(inputProblem.pinStrongConnMap)){if(!connected)continue;hasStrongConnections=!0;let pins=connKey.split("-");if(pins.length===2&&pins[0]&&pins[1]){let pin1=inputProblem.chipPinMap[pins[0]],pin2=inputProblem.chipPinMap[pins[1]];if(pin1&&pin2){let chip1Id=pins[0].split(".")[0],chip2Id=pins[1].split(".")[0];if(chip1Id&&chip2Id&&chip1Id!==chip2Id){let key1=`${chip1Id}-${chip2Id}`,key2=`${chip2Id}-${chip1Id}`;strongConnectedChipSides.has(key1)||strongConnectedChipSides.set(key1,new Set),strongConnectedChipSides.has(key2)||strongConnectedChipSides.set(key2,new Set),strongConnectedChipSides.get(key1).add(pin1.side),strongConnectedChipSides.get(key2).add(pin2.side)}}}}if(hasStrongConnections)for(let[connKey,connected]of Object.entries(inputProblem.netConnMap)){if(!connected)continue;let[pinId,netId]=connKey.split("-");pinId&&netId&&filteredPins.add(pinId)}else for(let[connKey,connected]of Object.entries(inputProblem.netConnMap)){if(!connected)continue;let[pinId,netId]=connKey.split("-");if(pinId&&netId){if(!inputProblem.chipPinMap[pinId])continue;let chipId=pinId.split(".")[0],shouldIncludeInNetwork=!0;for(let[strongKey,strongSides]of strongConnectedChipSides.entries()){let[fromChip,toChip]=strongKey.split("-");if(fromChip===chipId)for(let[otherConnKey,otherConnected]of Object.entries(inputProblem.netConnMap)){if(!otherConnected)continue;let[otherPinId,otherNetId]=otherConnKey.split("-");if(otherNetId===netId&&otherPinId&&otherPinId!==pinId){let otherPin=inputProblem.chipPinMap[otherPinId];if(!otherPin)continue;if(otherPinId.split(".")[0]===toChip&&!strongSides.has(otherPin.side)){shouldIncludeInNetwork=!1;break}}}}if(shouldIncludeInNetwork)pinToNetworkMap.set(pinId,netId);else{let disconnectedNetworkId=`${pinId}_opposite-strong-side-disconnected`;pinToNetworkMap.set(pinId,disconnectedNetworkId),filteredPins.add(pinId)}}}for(let[connKey,connected]of Object.entries(inputProblem.pinStrongConnMap)){if(!connected)continue;let pins=connKey.split("-");if(pins.length===2&&pins[0]&&pins[1]){let existingNet=pinToNetworkMap.get(pins[0])||pinToNetworkMap.get(pins[1]);existingNet?(pinToNetworkMap.set(pins[0],existingNet),pinToNetworkMap.set(pins[1],existingNet)):(pinToNetworkMap.set(pins[0],connKey),pinToNetworkMap.set(pins[1],connKey))}}return{pinToNetworkMap,filteredPins}}var getPadsBoundingBox=pads=>{let xs3=pads.flatMap(p3=>[p3.offset.x-p3.size.x/2,p3.offset.x+p3.size.x/2]),ys3=pads.flatMap(p3=>[p3.offset.y-p3.size.y/2,p3.offset.y+p3.size.y/2]),minX=xs3.length?Math.min(...xs3):0,maxX=xs3.length?Math.max(...xs3):0,minY=ys3.length?Math.min(...ys3):0,maxY=ys3.length?Math.max(...ys3):0;return{minX,maxX,minY,maxY}},TRACE_CLEARANCE=.2,ALIGNMENT_TOLERANCE=1e-6,TWO_PIN_COMPONENT_PIN_COUNT=2,getAbsolutePinPosition2=(pin,placement)=>{let offset=rotatePinOffset(pin.offset,placement.ccwRotationDegrees);return{x:placement.x+offset.x,y:placement.y+offset.y}},pinConnectsToGround=(inputProblem,pinId)=>{for(let[netId,net]of Object.entries(inputProblem.netMap))if(net.isGround&&inputProblem.netConnMap[`${pinId}-${netId}`])return!0;return!1},chipPinsAreVerticallyOriented=({chip,inputProblem,placement})=>{let[firstPinId,secondPinId]=chip.pins,firstPin=firstPinId&&inputProblem.chipPinMap[firstPinId],secondPin=secondPinId&&inputProblem.chipPinMap[secondPinId];if(!firstPin||!secondPin)return!1;let firstOffset=rotatePinOffset(firstPin.offset,placement.ccwRotationDegrees),secondOffset=rotatePinOffset(secondPin.offset,placement.ccwRotationDegrees);return Math.abs(firstOffset.y-secondOffset.y)>Math.abs(firstOffset.x-secondOffset.x)},placementHasClearance=({chipId,chipPlacements,inputProblem})=>{let chip=inputProblem.chipMap[chipId],placement=chipPlacements[chipId];if(!chip||!placement)return!1;let size3=getRotatedSize(chip.size,placement.ccwRotationDegrees),bounds=getBoundFromCenteredRect({center:placement,width:size3.x,height:size3.y});for(let[otherChipId,otherPlacement]of Object.entries(chipPlacements)){if(otherChipId===chipId)continue;let otherChip=inputProblem.chipMap[otherChipId];if(!otherChip)continue;let otherSize=getRotatedSize(otherChip.size,otherPlacement.ccwRotationDegrees),otherBounds=getBoundFromCenteredRect({center:otherPlacement,width:otherSize.x,height:otherSize.y});if(boundsDistance(bounds,otherBounds)<inputProblem.chipGap-ALIGNMENT_TOLERANCE)return!1}return!0},tryOffsetChips=({chipIds,dx:dx3,dy:dy3,chipPlacements,inputProblem})=>{let placements=chipIds.map(chipId=>chipPlacements[chipId]).filter(placement=>!!placement);if(placements.length!==chipIds.length)return;for(let placement of placements)placement.x+=dx3,placement.y+=dy3;if(!chipIds.every(chipId=>placementHasClearance({chipId,chipPlacements,inputProblem})))for(let placement of placements)placement.x-=dx3,placement.y-=dy3},applyDirectPassiveTraceClearance=({inputProblem,connectedPinsByPinId,chipPlacements,rigidChipGroups=[]})=>{let pinOwnerMap=createPinOwnerMap(inputProblem),chipCount=Object.keys(inputProblem.chipMap).length;for(let mainChip of Object.values(inputProblem.chipMap))if(!(mainChip.pins.length<=TWO_PIN_COMPONENT_PIN_COUNT))for(let mainPinId of mainChip.pins)for(let connectedPin of connectedPinsByPinId[mainPinId]??[]){let connectedChip=pinOwnerMap.get(connectedPin.pinId);if(!connectedChip||connectedChip.fixedPosition||connectedChip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT)continue;let mainPin=inputProblem.chipPinMap[mainPinId],mainPlacement=chipPlacements[mainChip.chipId],connectedPlacement=chipPlacements[connectedChip.chipId];if(!mainPin||!mainPlacement||!connectedPlacement)continue;let mainPinPosition=getAbsolutePinPosition2(mainPin,mainPlacement),connectedPinPosition=getAbsolutePinPosition2(connectedPin,connectedPlacement),pinsShareX=Math.abs(mainPinPosition.x-connectedPinPosition.x)<=ALIGNMENT_TOLERANCE,pinsShareY=Math.abs(mainPinPosition.y-connectedPinPosition.y)<=ALIGNMENT_TOLERANCE,pinsAreVerticallyOriented=chipPinsAreVerticallyOriented({chip:connectedChip,inputProblem,placement:connectedPlacement}),rigidChipGroup=rigidChipGroups.find(chipIds=>chipIds.includes(connectedChip.chipId)),chipIdsToOffset=rigidChipGroup??[connectedChip.chipId];if(pinsShareX&&pinsAreVerticallyOriented){if(rigidChipGroup)continue;tryOffsetChips({chipIds:[connectedChip.chipId],dx:-TRACE_CLEARANCE,dy:0,chipPlacements,inputProblem});continue}let isSingleVerticalPassive=chipCount===TWO_PIN_COMPONENT_PIN_COUNT&&pinsAreVerticallyOriented&&(connectedChip.isCapacitor||connectedChip.isResistor),otherPinId=connectedChip.pins.find(pinId=>pinId!==connectedPin.pinId),isGroundedLoad=otherPinId&&pinConnectsToGround(inputProblem,otherPinId);pinsShareY&&(isSingleVerticalPassive||isGroundedLoad)&&tryOffsetChips({chipIds:chipIdsToOffset,dx:0,dy:-TRACE_CLEARANCE,chipPlacements,inputProblem})}},offsetChipAnchoredGroundedLoadConnections=({groundedLoadPairs,inputProblem,chipPlacements})=>{for(let groundedLoadPair of groundedLoadPairs){if(!groundedLoadPair.mainPinId||!groundedLoadPair.upperChip.isResistor)continue;let upperPin=inputProblem.chipPinMap[groundedLoadPair.upperInnerPinId],lowerPin=inputProblem.chipPinMap[groundedLoadPair.lowerInnerPinId],upperPlacement=chipPlacements[groundedLoadPair.upperChip.chipId],lowerPlacement=chipPlacements[groundedLoadPair.lowerChip.chipId];if(!upperPin||!lowerPin||!upperPlacement||!lowerPlacement)continue;let upperPinPosition=getAbsolutePinPosition2(upperPin,upperPlacement),lowerPinPosition=getAbsolutePinPosition2(lowerPin,lowerPlacement);Math.abs(upperPinPosition.x-lowerPinPosition.x)>ALIGNMENT_TOLERANCE||tryOffsetChips({chipIds:[groundedLoadPair.upperChip.chipId],dx:-TRACE_CLEARANCE,dy:0,chipPlacements,inputProblem})}},offsetChipConnectedRailLoadConnections=({railLoadPairs,inputProblem,chipPlacements})=>{for(let railLoadPair of railLoadPairs){let mainPin=inputProblem.chipPinMap[railLoadPair.mainPinId],resistorPin=inputProblem.chipPinMap[railLoadPair.resistorMainPinId],mainPlacement=chipPlacements[railLoadPair.mainChipId],resistorPlacement=chipPlacements[railLoadPair.resistor.chipId];if(!mainPin||!resistorPin||!mainPlacement||!resistorPlacement)continue;let mainPinPosition=getAbsolutePinPosition2(mainPin,mainPlacement),resistorPinPosition=getAbsolutePinPosition2(resistorPin,resistorPlacement);Math.abs(mainPinPosition.y-resistorPinPosition.y)>ALIGNMENT_TOLERANCE||tryOffsetChips({chipIds:[railLoadPair.railComponent.chipId,railLoadPair.resistor.chipId],dx:0,dy:TRACE_CLEARANCE,chipPlacements,inputProblem})}},PIN_SIZE=.1,SingleInnerPartitionPackingSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"partitionInputProblem");__publicField(this,"layout",null);__publicField(this,"pinIdToStronglyConnectedPins");this.partitionInputProblem=params.partitionInputProblem,this.pinIdToStronglyConnectedPins=params.pinIdToStronglyConnectedPins}_step(){if(!this.activeSubSolver){let pinToNetworkMap=createFilteredNetworkMapping({inputProblem:this.partitionInputProblem,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}).pinToNetworkMap,packInput=this.createPackInput(pinToNetworkMap);this.activeSubSolver=new PackSolver2(packInput),this.activeSubSolver.MAX_ITERATIONS=this.MAX_ITERATIONS}if(this.activeSubSolver.step(),this.activeSubSolver.failed){this.failed=!0,this.error=`PackSolver2 failed: ${this.activeSubSolver.error}`;return}this.activeSubSolver.solved&&(this.layout=this.createLayoutFromPackingResult(this.activeSubSolver.packedComponents),this.solved=!0,this.activeSubSolver=null)}createPackInput(pinToNetworkMap){let packComponents=Object.entries(this.partitionInputProblem.chipMap).map(([chipId,chip])=>{let pads=[];for(let pinId of chip.pins){let pin=this.partitionInputProblem.chipPinMap[pinId];if(!pin)continue;let networkId=pinToNetworkMap.get(pinId)||`${pinId}_isolated`;pads.push({padId:pinId,networkId,type:"rect",offset:{x:pin.offset.x,y:pin.offset.y},size:{x:PIN_SIZE,y:PIN_SIZE}})}let padsBoundingBox=getPadsBoundingBox(pads),padsBoundingBoxSize={x:padsBoundingBox.maxX-padsBoundingBox.minX,y:padsBoundingBox.maxY-padsBoundingBox.minY};pads.push({padId:`${chipId}_body`,networkId:`${chipId}_body_disconnected`,type:"rect",offset:{x:0,y:0},size:{x:Math.max(padsBoundingBoxSize.x,chip.size.x),y:Math.max(padsBoundingBoxSize.y,chip.size.y)}});let fixedRotation=chip.availableRotations?.[0]??0;return{componentId:chipId,pads,availableRotationDegrees:chip.availableRotations??[0,90,180,270],...chip.fixedPosition&&{isStatic:!0,center:chip.fixedPosition,ccwRotationOffset:fixedRotation}}}),minGap=this.partitionInputProblem.chipGap;return this.partitionInputProblem.partitionType==="decoupling_caps"&&(minGap=this.partitionInputProblem.decouplingCapsGap??minGap),{components:packComponents,minGap,packOrderStrategy:"largest_to_smallest",packPlacementStrategy:"minimum_closest_sum_squared_distance"}}createLayoutFromPackingResult(packedComponents){let chipPlacements={};for(let packedComponent of packedComponents){let chipId=packedComponent.componentId;chipPlacements[chipId]={x:packedComponent.center.x,y:packedComponent.center.y,ccwRotationDegrees:packedComponent.ccwRotationDegrees??packedComponent.ccwRotationOffset??0}}return applyDirectPassiveTraceClearance({inputProblem:this.partitionInputProblem,connectedPinsByPinId:this.pinIdToStronglyConnectedPins,chipPlacements}),{chipPlacements,groupPlacements:{}}}visualize(){if(this.activeSubSolver&&!this.solved)return this.activeSubSolver.visualize();if(!this.layout){let basicLayout=doBasicInputProblemLayout(this.partitionInputProblem);return visualizeInputProblem(this.partitionInputProblem,basicLayout)}return visualizeInputProblem(this.partitionInputProblem,this.layout)}getConstructorParams(){return[this.partitionInputProblem]}},PASSIVE_PIN_COUNT=2,MAIN_CHIP_MIN_PINS=4,MIN_PASSIVE_GROUP_SIZE=3,MIN_COMMON_NODE_PASSIVE_GROUP_SIZE=2,buildPinToChip=problem=>{let pinToChip={};for(let[chipId,chip]of Object.entries(problem.chipMap))for(let pinId of chip.pins)pinToChip[pinId]=chipId;return pinToChip},getStrongPinPairs=problem=>{let pairs5=[],seen=new Set;for(let[connKey,connected]of Object.entries(problem.pinStrongConnMap)){if(!connected)continue;let[a6,b6]=connKey.split("-"),key=`${a6}|${b6}`;b6<a6&&(key=`${b6}|${a6}`),!seen.has(key)&&(seen.add(key),pairs5.push([a6,b6]))}return pairs5},getNetForPin=(problem,pinId)=>{for(let[connKey,connected]of Object.entries(problem.netConnMap))if(connected&&connKey.startsWith(`${pinId}-`))return connKey.slice(pinId.length+1);return null},getMainChipPinSide=(offset,mainChipRotation)=>{let o6=rotatePinOffset(offset,mainChipRotation);return Math.abs(o6.x)>=Math.abs(o6.y)?o6.x>=0?"x+":"x-":o6.y>=0?"y+":"y-"},edgeCoordForSide=(offset,side)=>side==="x-"||side==="x+"?offset.y:offset.x,findSameSidePassiveGroups=problem=>{let pinToChip=buildPinToChip(problem),pairs5=getStrongPinPairs(problem),stronglyConnectedPinIds=new Set(pairs5.flat()),strongByChip=new Map;for(let[a6,b6]of pairs5){let chipA=pinToChip[a6],chipB=pinToChip[b6];!chipA||!chipB||chipA===chipB||(strongByChip.has(chipA)||strongByChip.set(chipA,[]),strongByChip.has(chipB)||strongByChip.set(chipB,[]),strongByChip.get(chipA).push({selfPin:a6,otherPin:b6,otherChip:chipB}),strongByChip.get(chipB).push({selfPin:b6,otherPin:a6,otherChip:chipA}))}let commonNodeGroups=[];for(let strongs of strongByChip.values()){let strongsByPin=new Map;for(let strong of strongs){let fanout=strongsByPin.get(strong.selfPin)??[];fanout.push(strong),strongsByPin.set(strong.selfPin,fanout)}for(let[commonPinId,fanout]of strongsByPin){if(fanout.length<MIN_COMMON_NODE_PASSIVE_GROUP_SIZE)continue;let commonNodePins=[commonPinId,...fanout.map(s6=>s6.otherPin)],candidatesByNet=new Map;for(let connectedPinId of commonNodePins){let chipId=pinToChip[connectedPinId],chip=problem.chipMap[chipId];if(!chipId||chip?.fixedPosition||chip?.pins.length!==2)continue;let otherPinId=chip.pins.find(pinId=>pinId!==connectedPinId);if(!otherPinId||stronglyConnectedPinIds.has(otherPinId))continue;let netId=getNetForPin(problem,otherPinId);netId&&candidatesByNet.set(netId,[...candidatesByNet.get(netId)??[],chipId])}for(let passiveChipIds of candidatesByNet.values()){if(passiveChipIds.length<MIN_COMMON_NODE_PASSIVE_GROUP_SIZE)continue;let anchorPins=commonNodePins.filter(pinId=>!passiveChipIds.includes(pinToChip[pinId]));if(anchorPins.length!==1)continue;let mainChipPinId=anchorPins[0],mainChipId=pinToChip[mainChipPinId];if(!mainChipId)continue;let mainChip=problem.chipMap[mainChipId],mainChipPin=problem.chipPinMap[mainChipPinId];!mainChip||!mainChipPin||commonNodeGroups.push({mainChipId,side:getMainChipPinSide(mainChipPin.offset,mainChip.availableRotations?.[0]??0),passiveChipIds,mainChipPinIds:passiveChipIds.map(()=>mainChipPinId)})}}}let commonNodePassiveChipIds=new Set(commonNodeGroups.flatMap(group=>group.passiveChipIds)),candidates=[];for(let[passiveChipId,passiveChip]of Object.entries(problem.chipMap)){if(commonNodePassiveChipIds.has(passiveChipId)||passiveChip.pins.length!==PASSIVE_PIN_COUNT)continue;let strongs=strongByChip.get(passiveChipId)??[];if(strongs.length!==1)continue;let{selfPin,otherPin:mainChipPinId,otherChip:mainChipId}=strongs[0],mainChip=problem.chipMap[mainChipId];if(!mainChip||mainChip.pins.length<MAIN_CHIP_MIN_PINS)continue;let passiveOtherPinId=passiveChip.pins.find(p3=>p3!==selfPin);if(!passiveOtherPinId)continue;let sharedNetId=getNetForPin(problem,passiveOtherPinId);if(!sharedNetId)continue;let mainChipRotation=mainChip.availableRotations?.[0]??0,mainChipPinOffset=rotatePinOffset(problem.chipPinMap[mainChipPinId].offset,mainChipRotation),side=getMainChipPinSide(problem.chipPinMap[mainChipPinId].offset,mainChipRotation);candidates.push({passiveChipId,mainChipId,mainChipPinId,side,sharedNetId,edgeCoord:edgeCoordForSide(mainChipPinOffset,side)})}let candidatesByGroup=new Map;for(let candidate of candidates){let key=`${candidate.mainChipId}|${candidate.side}|${candidate.sharedNetId}`,list=candidatesByGroup.get(key)??[];list.push(candidate),candidatesByGroup.set(key,list)}let groups=[...commonNodeGroups];for(let list of candidatesByGroup.values())list.length<MIN_PASSIVE_GROUP_SIZE||(list.sort((a6,b6)=>a6.edgeCoord-b6.edgeCoord),groups.push({mainChipId:list[0].mainChipId,side:list[0].side,passiveChipIds:list.map(c3=>c3.passiveChipId),mainChipPinIds:list.map(c3=>c3.mainChipPinId)}));return groups},CLEARANCE_EPSILON=1e-6,MAX_RESOLVE_ITERATIONS=16,OUTWARD_BY_SIDE={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},axisGap=(a6,b6,axis)=>axis==="x"?Math.max(0,a6.minX-b6.maxX,b6.minX-a6.maxX):Math.max(0,a6.minY-b6.maxY,b6.minY-a6.maxY),ParallelAlignedPassiveSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"partitionInputProblem");__publicField(this,"layout",null);__publicField(this,"pinIdToStronglyConnectedPins");__publicField(this,"packingSolver",null);this.partitionInputProblem=params.partitionInputProblem,this.pinIdToStronglyConnectedPins=params.pinIdToStronglyConnectedPins}_step(){if(this.packingSolver||(this.packingSolver=new SingleInnerPartitionPackingSolver({partitionInputProblem:this.partitionInputProblem,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}),this.activeSubSolver=this.packingSolver),this.packingSolver.step(),this.packingSolver.failed){this.failed=!0,this.error=this.packingSolver.error;return}this.packingSolver.solved&&this.packingSolver.layout&&(this.layout=this.alignPassiveGroups(this.packingSolver.layout),this.activeSubSolver=null,this.solved=!0)}alignPassiveGroups(base){let placements={};for(let[chipId,placement]of Object.entries(base.chipPlacements))placements[chipId]={...placement};let passiveGroups=findSameSidePassiveGroups(this.partitionInputProblem);for(let passiveGroup of passiveGroups)this.reflowPassiveGroup(placements,passiveGroup);return applyDirectPassiveTraceClearance({inputProblem:this.partitionInputProblem,connectedPinsByPinId:this.pinIdToStronglyConnectedPins,chipPlacements:placements,rigidChipGroups:passiveGroups.map(passiveGroup=>passiveGroup.passiveChipIds)}),{chipPlacements:placements,groupPlacements:base.groupPlacements}}reflowPassiveGroup(placements,passiveGroup){let prob=this.partitionInputProblem,gap=prob.chipGap,mainChipPlacement=placements[passiveGroup.mainChipId];if(!mainChipPlacement)return;let outward=OUTWARD_BY_SIDE[passiveGroup.side],sideIsHorizontal=outward.x!==0,mainChipBox=this.boxFor(passiveGroup.mainChipId,mainChipPlacement),mainChipCenter=getBoundsCenter2(mainChipBox),mainChipPinPositions=passiveGroup.mainChipPinIds.map(pinId=>{let rotatedOffset=rotatePinOffset(prob.chipPinMap[pinId].offset,mainChipPlacement.ccwRotationDegrees);return{x:mainChipPlacement.x+rotatedOffset.x,y:mainChipPlacement.y+rotatedOffset.y}}),mainChipPinCentroid=mainChipCenter;if(mainChipPinPositions.length>0){let sumX=mainChipPinPositions.reduce((s6,p3)=>s6+p3.x,0),sumY=mainChipPinPositions.reduce((s6,p3)=>s6+p3.y,0);mainChipPinCentroid={x:sumX/mainChipPinPositions.length,y:sumY/mainChipPinPositions.length}}let sizes=passiveGroup.passiveChipIds.map(id3=>getRotatedSize(prob.chipMap[id3].size,placements[id3].ccwRotationDegrees)),rowXOffsets=[],cursor=0;for(let i6=0;i6<sizes.length;i6++)rowXOffsets[i6]=cursor+sizes[i6].x/2,cursor+=sizes[i6].x+gap;let rowWidth=Math.max(0,cursor-gap);for(let i6=0;i6<rowXOffsets.length;i6++)rowXOffsets[i6]-=rowWidth/2;let rowHeight=Math.max(...sizes.map(s6=>s6.y)),passiveChipIdSet=new Set(passiveGroup.passiveChipIds),candidateCentres=[];if(sideIsHorizontal){let outwardDistance=(mainChipBox.maxX-mainChipBox.minX)/2+gap+rowWidth/2,rowCentreX=mainChipCenter.x+outward.x*outwardDistance,lowestPinY=mainChipPinCentroid.y;mainChipPinPositions.length>0&&(lowestPinY=Math.min(...mainChipPinPositions.map(p3=>p3.y))),candidateCentres.push({x:rowCentreX,y:lowestPinY-rowHeight/2}),candidateCentres.push({x:rowCentreX,y:mainChipPinCentroid.y})}else{let outwardDistance=(mainChipBox.maxY-mainChipBox.minY)/2+gap+rowHeight/2;candidateCentres.push({x:mainChipPinCentroid.x,y:mainChipCenter.y+outward.y*outwardDistance})}let maxSlide=mainChipBox.maxX-mainChipBox.minX+rowWidth;for(let centre of candidateCentres){let slide=0;for(let iter=0;iter<MAX_RESOLVE_ITERATIONS;iter++){let candidate={};for(let i6=0;i6<passiveGroup.passiveChipIds.length;i6++){let id3=passiveGroup.passiveChipIds[i6];candidate[id3]={x:centre.x+slide+rowXOffsets[i6],y:centre.y,ccwRotationDegrees:placements[id3].ccwRotationDegrees}}let adjustment=this.clearanceAdjustment(candidate,placements,passiveChipIdSet,gap);if(adjustment===0){for(let id3 of passiveGroup.passiveChipIds)placements[id3]=candidate[id3];return}if(adjustment===null)break;let next2=slide+adjustment;if(Math.abs(next2)>maxSlide)break;slide=next2}}}clearanceAdjustment(candidate,placements,passiveChipIdSet,gap){let needPlus=0,needMinus=0;for(let[passiveChipId,passivePlacement]of Object.entries(candidate)){let passiveBox=this.boxFor(passiveChipId,passivePlacement);for(let[otherChipId,otherPlacement]of Object.entries(placements)){if(passiveChipIdSet.has(otherChipId))continue;let otherBox=this.boxFor(otherChipId,otherPlacement);if(boundsDistance(passiveBox,otherBox)>=gap-CLEARANCE_EPSILON)continue;let yGap=axisGap(passiveBox,otherBox,"y"),xGap=axisGap(passiveBox,otherBox,"x"),deficit=Math.sqrt(Math.max(0,gap*gap-yGap*yGap))-xGap;deficit<=CLEARANCE_EPSILON||(getBoundsCenter2(passiveBox).x>=getBoundsCenter2(otherBox).x?needPlus=Math.max(needPlus,deficit):needMinus=Math.max(needMinus,deficit))}}return needPlus>CLEARANCE_EPSILON&&needMinus>CLEARANCE_EPSILON?null:needPlus>CLEARANCE_EPSILON?needPlus:needMinus>CLEARANCE_EPSILON?-needMinus:0}boxFor(chipId,placement){let chip=this.partitionInputProblem.chipMap[chipId],size3=getRotatedSize(chip.size,placement.ccwRotationDegrees),points=[{x:placement.x-size3.x/2,y:placement.y-size3.y/2},{x:placement.x+size3.x/2,y:placement.y+size3.y/2}];for(let pinId of chip.pins){let pin=this.partitionInputProblem.chipPinMap[pinId];if(!pin)continue;let rotatedOffset=rotatePinOffset(pin.offset,placement.ccwRotationDegrees);points.push({x:placement.x+rotatedOffset.x,y:placement.y+rotatedOffset.y})}return getBoundsFromPoints2(points)}visualize(){if(this.activeSubSolver&&!this.solved)return this.activeSubSolver.visualize();if(!this.layout){let basicLayout=doBasicInputProblemLayout(this.partitionInputProblem);return visualizeInputProblem(this.partitionInputProblem,basicLayout)}return visualizeInputProblem(this.partitionInputProblem,this.layout)}getConstructorParams(){return[this.partitionInputProblem]}},getPinAxis=(chip,problem)=>{if(chip.pins.length!==2)return null;let[pinA,pinB]=chip.pins.map(pinId=>problem.chipPinMap[pinId]);if(!pinA||!pinB)return null;let rotation5=chip.availableRotations?.[0]??0,offsetA=rotatePinOffset(pinA.offset,rotation5),offsetB=rotatePinOffset(pinB.offset,rotation5);return Math.abs(offsetA.y-offsetB.y)>=Math.abs(offsetA.x-offsetB.x)?"y":"x"},canLayoutDecouplingCapRow=partition=>{if(partition.partitionType!=="decoupling_caps")return!1;let chips=Object.values(partition.chipMap);if(chips.length<2)return!1;let sharedPinAxis=null;for(let chip of chips){if(chip.fixedPosition)return!1;let pinAxis=getPinAxis(chip,partition);if(!pinAxis||sharedPinAxis&&sharedPinAxis!==pinAxis)return!1;sharedPinAxis=pinAxis}return sharedPinAxis!==null},DecouplingCapRowSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"partitionInputProblem");__publicField(this,"layout",null);this.partitionInputProblem=params.partitionInputProblem}getRotation(chip){return chip.availableRotations?.[0]??0}isOnRailNet(pinId){let problem=this.partitionInputProblem,railNetId=getDecouplingRailNetId({inputProblem:problem,netIds:Object.keys(problem.netMap)});return railNetId?problem.netConnMap[`${pinId}-${railNetId}`]===!0:!1}getRailOffset(chip,pinAxis){let railPinId=chip.pins.find(pinId=>this.isOnRailNet(pinId));if(!railPinId)return 0;let pin=this.partitionInputProblem.chipPinMap[railPinId];return pin?-rotatePinOffset(pin.offset,this.getRotation(chip))[pinAxis]:0}_step(){let problem=this.partitionInputProblem,chips=Object.values(problem.chipMap),pinAxis=getPinAxis(chips[0],problem),rowAxis="y";pinAxis==="y"&&(rowAxis="x");let gap=problem.decouplingCapsGap??problem.chipGap,extents=chips.map(chip=>getRotatedSize(chip.size,this.getRotation(chip))[rowAxis]),rowLength=extents.reduce((sum,extent)=>sum+extent,0)+gap*(chips.length-1),chipPlacements={},cursor=-rowLength/2,rowDirection=1,mainChipSide=problem.decouplingMainChipSide;(rowAxis==="x"&&mainChipSide==="x-"||rowAxis==="y"&&mainChipSide==="y-")&&(cursor=rowLength/2,rowDirection=-1),chips.forEach((chip,index)=>{let extent=extents[index],placement={x:0,y:0,ccwRotationDegrees:this.getRotation(chip)};placement[rowAxis]=cursor+rowDirection*extent/2,placement[pinAxis]=this.getRailOffset(chip,pinAxis),chipPlacements[chip.chipId]=placement,cursor+=rowDirection*(extent+gap)}),this.layout={chipPlacements,groupPlacements:{}},this.solved=!0}visualize(){return visualizeInputProblem(this.partitionInputProblem,this.layout??{chipPlacements:{},groupPlacements:{}})}getConstructorParams(){return[{partitionInputProblem:this.partitionInputProblem}]}},rotationsFor=chip=>chip.availableRotations?.length?chip.availableRotations:[0],chooseCrystalRotation=(chip,activePinIds,problem)=>{let bestRotation=rotationsFor(chip)[0],bestHorizontalScore=-1/0;for(let rotation5 of rotationsFor(chip)){let pinA=problem.chipPinMap[activePinIds[0]],pinB=problem.chipPinMap[activePinIds[1]];if(!pinA||!pinB)continue;let offsetA=rotatePinOffset(pinA.offset,rotation5),offsetB=rotatePinOffset(pinB.offset,rotation5),score=Math.abs(offsetA.x-offsetB.x)-Math.abs(offsetA.y-offsetB.y);score>bestHorizontalScore&&(bestHorizontalScore=score,bestRotation=rotation5)}return bestRotation},chooseCapRotation=(chip,signalPinId,groundPinId,problem)=>{let bestRotation=rotationsFor(chip)[0],bestVerticalScore=-1/0;for(let rotation5 of rotationsFor(chip)){let signalPin=problem.chipPinMap[signalPinId],groundPin=problem.chipPinMap[groundPinId];if(!signalPin||!groundPin)continue;let signalOffset=rotatePinOffset(signalPin.offset,rotation5),groundOffset=rotatePinOffset(groundPin.offset,rotation5),score=signalOffset.y-groundOffset.y-Math.abs(signalOffset.x-groundOffset.x);score>bestVerticalScore&&(bestVerticalScore=score,bestRotation=rotation5)}return bestRotation},chooseResistorRotation=(chip,connectedPinId,problem)=>{let otherPinId=chip.pins.find(pinId=>pinId!==connectedPinId),bestRotation=rotationsFor(chip)[0],bestUpwardScore=-1/0;for(let rotation5 of rotationsFor(chip)){let connectedPin=problem.chipPinMap[connectedPinId],otherPin=otherPinId&&problem.chipPinMap[otherPinId];if(!connectedPin||!otherPin)continue;let connectedOffset=rotatePinOffset(connectedPin.offset,rotation5),otherOffset=rotatePinOffset(otherPin.offset,rotation5),score=otherOffset.y-connectedOffset.y-Math.abs(otherOffset.x-connectedOffset.x);score>bestUpwardScore&&(bestUpwardScore=score,bestRotation=rotation5)}return bestRotation},canLayoutCrystalCircuit=partition=>partition.partitionType!=="crystal_circuit"||!partition.crystalCircuitGroup?!1:Object.values(partition.chipMap).every(chip=>chip.fixedPosition===void 0),CrystalCircuitLayoutSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"partitionInputProblem");__publicField(this,"layout",null);this.partitionInputProblem=params.partitionInputProblem}_step(){let problem=this.partitionInputProblem,group=problem.crystalCircuitGroup,crystal2=problem.chipMap[group.crystalChipId],crystalRotation=chooseCrystalRotation(crystal2,group.activeCrystalPinIds,problem),crystalSize=getRotatedSize(crystal2.size,crystalRotation),gap=problem.chipGap,chipPlacements={[crystal2.chipId]:{x:0,y:0,ccwRotationDegrees:crystalRotation}},activePinOffsets=new Map;for(let pinId of group.activeCrystalPinIds){let pin=problem.chipPinMap[pinId];activePinOffsets.set(pinId,rotatePinOffset(pin.offset,crystalRotation))}let activeOffsetA=activePinOffsets.get(group.activeCrystalPinIds[0]),activeOffsetB=activePinOffsets.get(group.activeCrystalPinIds[1]),crystalPinAxis;Math.abs(activeOffsetA.x-activeOffsetB.x)>=Math.abs(activeOffsetA.y-activeOffsetB.y)?crystalPinAxis="x":crystalPinAxis="y";let capGeometry=group.loadCaps.map((loadCap,index)=>{let chip=problem.chipMap[loadCap.chipId],rotation5=chooseCapRotation(chip,loadCap.signalPinId,loadCap.groundPinId,problem),size3=getRotatedSize(chip.size,rotation5),signalOffset=rotatePinOffset(problem.chipPinMap[loadCap.signalPinId].offset,rotation5),groundOffset=rotatePinOffset(problem.chipPinMap[loadCap.groundPinId].offset,rotation5),crystalPinId=group.activeCrystalPinIds[index],crystalPinOffset=activePinOffsets.get(crystalPinId),highestCenterY=-crystalSize.y/2-gap-size3.y/2;return{chip,rotation:rotation5,size:size3,signalOffset,groundOffset,crystalPinOffset,highestGroundY:highestCenterY+groundOffset.y}});if(crystalPinAxis==="x"){let groundRailY=Math.min(...capGeometry.map(geometry=>geometry.highestGroundY));for(let geometry of capGeometry)chipPlacements[geometry.chip.chipId]={x:geometry.crystalPinOffset.x-geometry.signalOffset.x,y:groundRailY-geometry.groundOffset.y,ccwRotationDegrees:geometry.rotation};let[leftCap,rightCap]=[...capGeometry].sort((a6,b6)=>chipPlacements[a6.chip.chipId].x-chipPlacements[b6.chip.chipId].x),leftPlacement=chipPlacements[leftCap.chip.chipId],rightPlacement=chipPlacements[rightCap.chip.chipId],currentGap=rightPlacement.x-rightCap.size.x/2-(leftPlacement.x+leftCap.size.x/2),adjustment=Math.max(0,(gap*2-currentGap)/2);leftPlacement.x-=adjustment,rightPlacement.x+=adjustment}else capGeometry.forEach((geometry,index)=>{let side;index===0?side=-1:side=1,chipPlacements[geometry.chip.chipId]={x:side*(crystalSize.x/2+gap+geometry.size.x/2),y:geometry.crystalPinOffset.y-geometry.signalOffset.y,ccwRotationDegrees:geometry.rotation}});for(let seriesResistor of group.seriesResistors){let chip=problem.chipMap[seriesResistor.chipId],rotation5=chooseResistorRotation(chip,seriesResistor.connectedPinId,problem),size3=getRotatedSize(chip.size,rotation5),connectedOffset=rotatePinOffset(problem.chipPinMap[seriesResistor.connectedPinId].offset,rotation5),crystalPinOffset=activePinOffsets.get(seriesResistor.crystalPinId);chipPlacements[chip.chipId]={x:crystalPinOffset.x-connectedOffset.x,y:crystalSize.y/2+gap+size3.y/2,ccwRotationDegrees:rotation5}}this.layout={chipPlacements,groupPlacements:{}},this.solved=!0}visualize(){return visualizeInputProblem(this.partitionInputProblem,this.layout??{chipPlacements:{},groupPlacements:{}})}getConstructorParams(){return[{partitionInputProblem:this.partitionInputProblem}]}},TWO_PIN_COMPONENT_PIN_COUNT2=2,buildConnectionsByChip=inputProblem=>{let pinOwnerMap=new Map;for(let chip of Object.values(inputProblem.chipMap))for(let pinId of chip.pins)pinOwnerMap.set(pinId,chip.chipId);let connectedPinsByPinId=getPinIdToStronglyConnectedPinsObj(inputProblem),connectionsByChip=new Map;for(let[pinId,connectedPins]of Object.entries(connectedPinsByPinId)){let chipId=pinOwnerMap.get(pinId);if(chipId)for(let connectedPin of connectedPins){let otherChipId=pinOwnerMap.get(connectedPin.pinId);if(!otherChipId||otherChipId===chipId)continue;let connections=connectionsByChip.get(chipId)??[];connections.push({selfPinId:pinId,otherPinId:connectedPin.pinId,otherChipId}),connectionsByChip.set(chipId,connections)}}return connectionsByChip},findTwoPinComponentPath=({inputProblem,connectionsByChip,mainChipId,startChipId,endChipId})=>{if(startChipId===endChipId)return null;let canUseChip=chipId=>{let chip=inputProblem.chipMap[chipId];return chipId!==mainChipId&&chip?.pins.length===TWO_PIN_COMPONENT_PIN_COUNT2&&!chip.fixedPosition};if(!canUseChip(startChipId)||!canUseChip(endChipId))return null;let queue=[[startChipId]],visited=new Set([startChipId]);for(;queue.length>0;){let path=queue.shift(),chipId=path[path.length-1];if(chipId===endChipId)return path;for(let connection of connectionsByChip.get(chipId)??[]){let nextChipId=connection.otherChipId;!canUseChip(nextChipId)||visited.has(nextChipId)||(visited.add(nextChipId),queue.push([...path,nextChipId]))}}return null},getOrderedSeriesComponents=({inputProblem,connectionsByChip,mainChipId,mainPinIds,pathChipIds})=>{let ordered=[];for(let index=0;index<pathChipIds.length;index++){let chipId=pathChipIds[index],chip=inputProblem.chipMap[chipId],connections=connectionsByChip.get(chipId)??[];if(!chip||connections.length!==TWO_PIN_COMPONENT_PIN_COUNT2||new Set(connections.map(connection=>connection.selfPinId)).size!==TWO_PIN_COMPONENT_PIN_COUNT2)return null;let previousChipId=index===0?mainChipId:pathChipIds[index-1],nextChipId=index===pathChipIds.length-1?mainChipId:pathChipIds[index+1],previousConnection=connections.find(connection=>connection.otherChipId===previousChipId),nextConnection=connections.find(connection=>connection.otherChipId===nextChipId);if(!previousConnection||!nextConnection||previousConnection.selfPinId===nextConnection.selfPinId||index===0&&previousConnection.otherPinId!==mainPinIds[0]||index===pathChipIds.length-1&&nextConnection.otherPinId!==mainPinIds[1])return null;ordered.push({chipId,nearPinId:previousConnection.selfPinId,farPinId:nextConnection.selfPinId})}return ordered},findParallelSeriesBranchGroups=inputProblem=>{let connectionsByChip=buildConnectionsByChip(inputProblem),groups=[],usedPathChipIds=new Set;for(let mainChip of Object.values(inputProblem.chipMap)){if(mainChip.pins.length<=TWO_PIN_COMPONENT_PIN_COUNT2)continue;let mainConnections=connectionsByChip.get(mainChip.chipId)??[];for(let firstIndex=0;firstIndex<mainConnections.length;firstIndex++){let firstConnection=mainConnections[firstIndex],firstPin=inputProblem.chipPinMap[firstConnection.selfPinId];if(firstPin)for(let secondIndex=firstIndex+1;secondIndex<mainConnections.length;secondIndex++){let secondConnection=mainConnections[secondIndex],secondPin=inputProblem.chipPinMap[secondConnection.selfPinId];if(!secondPin||firstPin.side!==secondPin.side||firstConnection.selfPinId===secondConnection.selfPinId)continue;let pathChipIds=findTwoPinComponentPath({inputProblem,connectionsByChip,mainChipId:mainChip.chipId,startChipId:firstConnection.otherChipId,endChipId:secondConnection.otherChipId});if(!pathChipIds||pathChipIds.length<TWO_PIN_COMPONENT_PIN_COUNT2||pathChipIds.length%2!==0||pathChipIds.some(chipId=>usedPathChipIds.has(chipId)))continue;let mainPinIds=[firstConnection.selfPinId,secondConnection.selfPinId],orderedComponents=getOrderedSeriesComponents({inputProblem,connectionsByChip,mainChipId:mainChip.chipId,mainPinIds,pathChipIds});if(!orderedComponents)continue;let splitIndex=orderedComponents.length/2,firstBranch=orderedComponents.slice(0,splitIndex),secondBranch=orderedComponents.slice(splitIndex).reverse().map(component=>({chipId:component.chipId,nearPinId:component.farPinId,farPinId:component.nearPinId}));groups.push({mainChipId:mainChip.chipId,mainPinIds,branches:[firstBranch,secondBranch]});for(let chipId of pathChipIds)usedPathChipIds.add(chipId)}}}return groups},DEFAULT_ROTATIONS=[0,90,180,270],CLEARANCE_EPSILON2=1e-6,dot=(point6,axis)=>point6.x*axis.x+point6.y*axis.y,pointFromCoordinates=({outwardCoordinate,tangentCoordinate,axes})=>({x:axes.outward.x*outwardCoordinate+axes.tangent.x*tangentCoordinate,y:axes.outward.y*outwardCoordinate+axes.tangent.y*tangentCoordinate}),getLayoutAxes=({pinOffset})=>Math.abs(pinOffset.x)>=Math.abs(pinOffset.y)?{outward:getUnitVectorFromDirection(pinOffset.x>=0?"right":"left"),tangent:getUnitVectorFromDirection("up")}:{outward:getUnitVectorFromDirection(pinOffset.y>=0?"up":"down"),tangent:getUnitVectorFromDirection("right")},getHalfExtent=({size:size3,axis})=>(Math.abs(axis.x)*size3.x+Math.abs(axis.y)*size3.y)/2,getOutwardRotation=({chip,nearPinId,farPinId,inputProblem,outward,originalRotation})=>{let nearPin=inputProblem.chipPinMap[nearPinId],farPin=inputProblem.chipPinMap[farPinId];if(!nearPin||!farPin)return originalRotation;let rotations=chip.availableRotations??DEFAULT_ROTATIONS,bestRotation=rotations[0]??0,bestScore=Number.NEGATIVE_INFINITY;for(let rotation5 of rotations){let nearOffset=rotatePinOffset(nearPin.offset,rotation5),farOffset=rotatePinOffset(farPin.offset,rotation5),score=dot({x:farOffset.x-nearOffset.x,y:farOffset.y-nearOffset.y},outward);(score>bestScore||score===bestScore&&rotation5===originalRotation)&&(bestScore=score,bestRotation=rotation5)}return bestRotation},getBounds3=({chip,placement})=>{let size3=getRotatedSize(chip.size,placement.ccwRotationDegrees);return getBoundFromCenteredRect({center:placement,width:size3.x,height:size3.y})},layoutBranch=({branch,mainPinId,mainChip,mainPlacement,inputProblem,axes,originalPlacements,extraGap})=>{let mainPin=inputProblem.chipPinMap[mainPinId];if(!mainPin)return null;let mainSize=getRotatedSize(mainChip.size,mainPlacement.ccwRotationDegrees),mainPinOffset=rotatePinOffset(mainPin.offset,mainPlacement.ccwRotationDegrees),mainPinPosition={x:mainPlacement.x+mainPinOffset.x,y:mainPlacement.y+mainPinOffset.y},previousOuterBodyCoordinate=dot(mainPlacement,axes.outward)+getHalfExtent({size:mainSize,axis:axes.outward});previousOuterBodyCoordinate=Math.max(previousOuterBodyCoordinate,dot(mainPinPosition,axes.outward));let previousFarPinTangentCoordinate=dot(mainPinPosition,axes.tangent),placements={},terminalOutwardCoordinate=previousOuterBodyCoordinate;for(let branchComponent of branch){let chip=inputProblem.chipMap[branchComponent.chipId],originalPlacement=originalPlacements[branchComponent.chipId],nearPin=inputProblem.chipPinMap[branchComponent.nearPinId],farPin=inputProblem.chipPinMap[branchComponent.farPinId];if(!chip||!originalPlacement||!nearPin||!farPin)return null;let rotation5=getOutwardRotation({chip,nearPinId:branchComponent.nearPinId,farPinId:branchComponent.farPinId,inputProblem,outward:axes.outward,originalRotation:originalPlacement.ccwRotationDegrees}),size3=getRotatedSize(chip.size,rotation5),halfOutwardExtent=getHalfExtent({size:size3,axis:axes.outward}),nearPinOffset=rotatePinOffset(nearPin.offset,rotation5),farPinOffset=rotatePinOffset(farPin.offset,rotation5),outwardCoordinate=previousOuterBodyCoordinate+inputProblem.chipGap+extraGap+halfOutwardExtent,tangentCoordinate=previousFarPinTangentCoordinate-dot(nearPinOffset,axes.tangent),center2=pointFromCoordinates({outwardCoordinate,tangentCoordinate,axes});placements[chip.chipId]={...center2,ccwRotationDegrees:rotation5},previousOuterBodyCoordinate=outwardCoordinate+halfOutwardExtent,previousFarPinTangentCoordinate=tangentCoordinate+dot(farPinOffset,axes.tangent),terminalOutwardCoordinate=outwardCoordinate+dot(farPinOffset,axes.outward)}return{placements,terminalOutwardCoordinate}},translateBranchAlongTangent=({branchLayout,shift,tangent})=>{for(let placement of Object.values(branchLayout.placements))placement.x+=tangent.x*shift,placement.y+=tangent.y*shift},getBranchTangentBounds=({branchLayout,inputProblem,tangent})=>{let bounds=getBoundsFromPoints2(Object.entries(branchLayout.placements).flatMap(([chipId,placement])=>{let chipBounds=getBounds3({chip:inputProblem.chipMap[chipId],placement});return[{x:chipBounds.minX,y:chipBounds.minY},{x:chipBounds.maxX,y:chipBounds.maxY}]}));return bounds?Math.abs(tangent.x)>=Math.abs(tangent.y)?{min:bounds.minX,max:bounds.maxX}:{min:bounds.minY,max:bounds.maxY}:{min:0,max:0}},candidateHasClearance=({candidatePlacements,originalPlacements,inputProblem})=>{let candidateChipIds=new Set(Object.keys(candidatePlacements)),candidateEntries=Object.entries(candidatePlacements);for(let index=0;index<candidateEntries.length;index++){let[chipId,placement]=candidateEntries[index],chip=inputProblem.chipMap[chipId];if(!chip)return!1;let bounds=getBounds3({chip,placement});for(let otherIndex=index+1;otherIndex<candidateEntries.length;otherIndex++){let[otherChipId,otherPlacement]=candidateEntries[otherIndex],otherChip=inputProblem.chipMap[otherChipId];if(!otherChip||boundsDistance(bounds,getBounds3({chip:otherChip,placement:otherPlacement}))<inputProblem.chipGap-CLEARANCE_EPSILON2)return!1}for(let[otherChipId,otherPlacement]of Object.entries(originalPlacements)){if(candidateChipIds.has(otherChipId))continue;let otherChip=inputProblem.chipMap[otherChipId];if(!otherChip||boundsDistance(bounds,getBounds3({chip:otherChip,placement:otherPlacement}))<inputProblem.chipGap-CLEARANCE_EPSILON2)return!1}}return!0},layoutParallelSeriesBranchGroup=({group,chipPlacements,inputProblem})=>{let mainChip=inputProblem.chipMap[group.mainChipId],mainPlacement=chipPlacements[group.mainChipId],firstMainPin=inputProblem.chipPinMap[group.mainPinIds[0]];if(!mainChip||!mainPlacement||!firstMainPin)return null;let rotatedMainPinOffset=rotatePinOffset(firstMainPin.offset,mainPlacement.ccwRotationDegrees),axes=getLayoutAxes({pinOffset:rotatedMainPinOffset}),branchEntries=group.branches.map((branch,index)=>({branch,mainPinId:group.mainPinIds[index]})).sort((first,second)=>{let getMainPinTangentCoordinate=pinId=>{let pin=inputProblem.chipPinMap[pinId],offset=rotatePinOffset(pin.offset,mainPlacement.ccwRotationDegrees);return dot({x:mainPlacement.x+offset.x,y:mainPlacement.y+offset.y},axes.tangent)};return getMainPinTangentCoordinate(first.mainPinId)-getMainPinTangentCoordinate(second.mainPinId)}),branchLayouts=branchEntries.map(({branch,mainPinId})=>layoutBranch({branch,mainPinId,mainChip,mainPlacement,inputProblem,axes,originalPlacements:chipPlacements,extraGap:0}));if(branchLayouts.some(layout=>!layout))return null;let terminalOutwardCoordinate=Math.max(...branchLayouts.map(layout=>layout.terminalOutwardCoordinate));if(branchLayouts=branchEntries.map(({branch,mainPinId},index)=>{let branchLayout=branchLayouts[index],extraGap=(terminalOutwardCoordinate-branchLayout.terminalOutwardCoordinate)/branch.length;return layoutBranch({branch,mainPinId,mainChip,mainPlacement,inputProblem,axes,originalPlacements:chipPlacements,extraGap})}),branchLayouts.some(layout=>!layout))return null;let firstBounds=getBranchTangentBounds({branchLayout:branchLayouts[0],inputProblem,tangent:axes.tangent}),secondBounds=getBranchTangentBounds({branchLayout:branchLayouts[1],inputProblem,tangent:axes.tangent}),separationDeficit=Math.max(0,firstBounds.max+inputProblem.chipGap-secondBounds.min);translateBranchAlongTangent({branchLayout:branchLayouts[0],shift:-separationDeficit/2,tangent:axes.tangent}),translateBranchAlongTangent({branchLayout:branchLayouts[1],shift:separationDeficit/2,tangent:axes.tangent});let candidatePlacements=Object.assign({},branchLayouts[0].placements,branchLayouts[1].placements);return candidateHasClearance({candidatePlacements,originalPlacements:chipPlacements,inputProblem})?candidatePlacements:null},canLayoutParallelSeriesBranches=partition=>findParallelSeriesBranchGroups(partition).length>0,ParallelSeriesBranchSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"partitionInputProblem");__publicField(this,"layout",null);__publicField(this,"pinIdToStronglyConnectedPins");__publicField(this,"packingSolver",null);this.partitionInputProblem=params.partitionInputProblem,this.pinIdToStronglyConnectedPins=params.pinIdToStronglyConnectedPins}_step(){if(this.packingSolver||(this.packingSolver=new SingleInnerPartitionPackingSolver({partitionInputProblem:this.partitionInputProblem,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}),this.activeSubSolver=this.packingSolver),this.packingSolver.step(),this.packingSolver.failed){this.failed=!0,this.error=this.packingSolver.error;return}this.packingSolver.solved&&this.packingSolver.layout&&(this.layout=this.refinePackedLayout(this.packingSolver.layout),this.activeSubSolver=null,this.solved=!0)}refinePackedLayout(baseLayout){let chipPlacements={};for(let[chipId,placement]of Object.entries(baseLayout.chipPlacements))chipPlacements[chipId]={...placement};for(let group of findParallelSeriesBranchGroups(this.partitionInputProblem)){let candidatePlacements=layoutParallelSeriesBranchGroup({group,chipPlacements,inputProblem:this.partitionInputProblem});candidatePlacements&&Object.assign(chipPlacements,candidatePlacements)}return{chipPlacements,groupPlacements:baseLayout.groupPlacements}}visualize(){if(this.activeSubSolver&&!this.solved)return this.activeSubSolver.visualize();if(!this.layout){let basicLayout=doBasicInputProblemLayout(this.partitionInputProblem);return visualizeInputProblem(this.partitionInputProblem,basicLayout)}return visualizeInputProblem(this.partitionInputProblem,this.layout)}getConstructorParams(){return[this.partitionInputProblem]}};function definePartitionSolverStrategy(solverName,solverClass,appliesTo,getConstructorParams){return{solverName,solverClass,appliesTo,getConstructorParams}}var PARTITION_SOLVER_STRATEGIES=[definePartitionSolverStrategy("crystalCircuitLayoutSolver",CrystalCircuitLayoutSolver,canLayoutCrystalCircuit,instance=>[{partitionInputProblem:instance.partitions[instance.currentPartitionIndex]}]),definePartitionSolverStrategy("decouplingCapRowSolver",DecouplingCapRowSolver,canLayoutDecouplingCapRow,instance=>[{partitionInputProblem:instance.partitions[instance.currentPartitionIndex]}]),definePartitionSolverStrategy("parallelAlignedPassiveSolver",ParallelAlignedPassiveSolver,partition=>findSameSidePassiveGroups(partition).length>0,instance=>[{partitionInputProblem:instance.partitions[instance.currentPartitionIndex],pinIdToStronglyConnectedPins:instance.pinIdToStronglyConnectedPins}]),definePartitionSolverStrategy("parallelSeriesBranchSolver",ParallelSeriesBranchSolver,canLayoutParallelSeriesBranches,instance=>[{partitionInputProblem:instance.partitions[instance.currentPartitionIndex],pinIdToStronglyConnectedPins:instance.pinIdToStronglyConnectedPins}]),definePartitionSolverStrategy("singleInnerPartitionPackingSolver",SingleInnerPartitionPackingSolver,()=>!0,instance=>[{partitionInputProblem:instance.partitions[instance.currentPartitionIndex],pinIdToStronglyConnectedPins:instance.pinIdToStronglyConnectedPins}])],PackInnerPartitionsSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"partitions");__publicField(this,"packedPartitions",[]);__publicField(this,"completedSolvers",[]);__publicField(this,"activeSolver",null);__publicField(this,"currentPartitionIndex",0);__publicField(this,"pinIdToStronglyConnectedPins");this.partitions=params.partitions,this.pinIdToStronglyConnectedPins=params.pinIdToStronglyConnectedPins}_step(){if(this.currentPartitionIndex>=this.partitions.length){this.solved=!0;return}if(!this.activeSolver){let currentPartition=this.partitions[this.currentPartitionIndex],strategy=PARTITION_SOLVER_STRATEGIES.find(s6=>s6.appliesTo(currentPartition)),constructorParams=strategy.getConstructorParams(this);this.activeSolver=new strategy.solverClass(...constructorParams),this.activeSubSolver=this.activeSolver}if(this.activeSolver.step(),this.activeSolver.failed){this.failed=!0,this.error=`Partition ${this.currentPartitionIndex} failed: ${this.activeSolver.error}`;return}if(this.activeSolver.solved){if(this.completedSolvers.push(this.activeSolver),this.activeSolver.layout)this.packedPartitions.push({inputProblem:this.partitions[this.currentPartitionIndex],layout:this.activeSolver.layout});else{this.failed=!0,this.error=`Partition ${this.currentPartitionIndex} completed but has no layout`;return}this.activeSolver=null,this.activeSubSolver=null,this.currentPartitionIndex++}}visualize(){if(this.activeSolver)return this.activeSolver.visualize();if(this.completedSolvers.length===0){let partitionVisualizations2=this.partitions.map(partition=>{let layout=doBasicInputProblemLayout(partition);return visualizeInputProblem(partition,layout)}),titles2=this.partitions.map((_6,index)=>`partition${index}`);return stackGraphicsHorizontally(partitionVisualizations2,{titles:titles2})}let partitionVisualizations=this.completedSolvers.map(solver=>solver.visualize()),titles=this.completedSolvers.map((_6,index)=>`packed_partition_${index}`);return stackGraphicsHorizontally(partitionVisualizations,{titles})}getConstructorParams(){return[this.partitions]}},PartitionPackingSolver=class extends BaseSolver4{constructor(input2){super();__publicField(this,"packedPartitions");__publicField(this,"inputProblem");__publicField(this,"finalLayout",null);__publicField(this,"packSolver2",null);this.packedPartitions=input2.packedPartitions,this.inputProblem=input2.inputProblem}partitionHasFixedChip(partitionIndex){let packedPartition=this.packedPartitions[partitionIndex];return packedPartition?Object.values(packedPartition.inputProblem.chipMap).some(chip=>chip.fixedPosition!==void 0):!1}_step(){try{if(this.packedPartitions.length===0){this.finalLayout={chipPlacements:{},groupPlacements:{}},this.solved=!0;return}if(this.packedPartitions.length===1){this.finalLayout=this.packedPartitions[0].layout,this.solved=!0;return}let partitionGroups=this.organizePackedPartitions();if(!this.packSolver2){let packInput=this.createPackInput(partitionGroups);this.packSolver2=new PackSolver2(packInput),this.activeSubSolver=this.packSolver2}if(this.packSolver2.step(),this.packSolver2.failed){this.failed=!0,this.error=`PackSolver2 failed: ${this.packSolver2.error}`;return}if(this.packSolver2.solved){let packedLayout=this.applyPackingResult(this.packSolver2.packedComponents,partitionGroups);this.finalLayout=packedLayout,this.solved=!0,this.activeSubSolver=null}}catch(error2){this.failed=!0,this.error=`Failed to pack partitions: ${error2}`}}buildConnectivityMap(){let pinToNetworkMap=new Map;for(let packedPartition of this.packedPartitions){for(let[connKey,connected]of Object.entries(packedPartition.inputProblem.netConnMap)){if(!connected)continue;let[pinId,netId]=connKey.split("-");pinId&&netId&&pinToNetworkMap.set(pinId,netId)}for(let[connKey,connected]of Object.entries(packedPartition.inputProblem.pinStrongConnMap)){if(!connected)continue;let pins=connKey.split("-");if(pins.length===2&&pins[0]&&pins[1]){let existingNet=pinToNetworkMap.get(pins[0])||pinToNetworkMap.get(pins[1]);existingNet?(pinToNetworkMap.set(pins[0],existingNet),pinToNetworkMap.set(pins[1],existingNet)):(pinToNetworkMap.set(pins[0],connKey),pinToNetworkMap.set(pins[1],connKey))}}}return pinToNetworkMap}organizePackedPartitions(){let partitionGroups=[];for(let i6=0;i6<this.packedPartitions.length;i6++){let packedPartition=this.packedPartitions[i6],partitionChipIds=Object.keys(packedPartition.layout.chipPlacements);if(partitionChipIds.length>0){let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let chipId of partitionChipIds){let placement=packedPartition.layout.chipPlacements[chipId],chip=packedPartition.inputProblem.chipMap[chipId],chipWidth=chip.size.x,chipHeight=chip.size.y;(placement.ccwRotationDegrees===90||placement.ccwRotationDegrees===270)&&([chipWidth,chipHeight]=[chipHeight,chipWidth]);let chipMinX=placement.x-chipWidth/2,chipMaxX=placement.x+chipWidth/2,chipMinY=placement.y-chipHeight/2,chipMaxY=placement.y+chipHeight/2;minX=Math.min(minX,chipMinX),maxX=Math.max(maxX,chipMaxX),minY=Math.min(minY,chipMinY),maxY=Math.max(maxY,chipMaxY)}partitionGroups.push({partitionIndex:i6,chipIds:partitionChipIds,bounds:{minX,maxX,minY,maxY}})}}return partitionGroups}createPackInput(groups){let pinToNetworkMap=this.buildConnectivityMap();return{components:groups.map(group=>{let packedPartition=this.packedPartitions[group.partitionIndex],isFixed=this.partitionHasFixedChip(group.partitionIndex),partitionWidth=group.bounds.maxX-group.bounds.minX,partitionHeight=group.bounds.maxY-group.bounds.minY,centerX=(group.bounds.minX+group.bounds.maxX)/2,centerY=(group.bounds.minY+group.bounds.maxY)/2,pads=[{padId:`partition_${group.partitionIndex}_body`,networkId:`partition_${group.partitionIndex}_disconnected`,type:"rect",offset:{x:0,y:0},size:{x:Math.max(partitionWidth,.1),y:Math.max(partitionHeight,.1)}}],addedNetworks=new Set;for(let chipId of group.chipIds){let chipPlacement=packedPartition.layout.chipPlacements[chipId],chip=packedPartition.inputProblem.chipMap[chipId];for(let pinId of chip.pins){let chipPin=packedPartition.inputProblem.chipPinMap[pinId];if(!chipPin)continue;let rotatedPinOffset={x:chipPin.offset.x,y:chipPin.offset.y},chipRotationDeg=chipPlacement.ccwRotationDegrees??0;chipRotationDeg===90?rotatedPinOffset={x:-chipPin.offset.y,y:chipPin.offset.x}:chipRotationDeg===180?rotatedPinOffset={x:-chipPin.offset.x,y:-chipPin.offset.y}:chipRotationDeg===270&&(rotatedPinOffset={x:chipPin.offset.y,y:-chipPin.offset.x});let absolutePinX=chipPlacement.x+rotatedPinOffset.x,absolutePinY=chipPlacement.y+rotatedPinOffset.y,networkId=pinToNetworkMap.get(pinId)??`${pinId}_disconnected`;addedNetworks.has(networkId)||(addedNetworks.add(networkId),pads.push({padId:`${group.partitionIndex}_pin_${pinId}`,networkId,type:"rect",offset:{x:absolutePinX-centerX,y:absolutePinY-centerY},size:{x:.01,y:.01}}))}}return{componentId:`partition_${group.partitionIndex}`,pads,availableRotationDegrees:[0],...isFixed&&{isStatic:!0,center:{x:centerX,y:centerY},ccwRotationOffset:0}}}),minGap:this.inputProblem.partitionGap,packOrderStrategy:"largest_to_smallest",packPlacementStrategy:"minimum_sum_squared_distance_to_network"}}applyPackingResult(packedComponents,partitionGroups){let newChipPlacements={};for(let packedComponent of packedComponents){let partitionIndex=parseInt(packedComponent.componentId.replace("partition_","")),group=partitionGroups.find(g4=>g4.partitionIndex===partitionIndex),packedPartition=this.packedPartitions[partitionIndex];if(group&&packedPartition){let currentCenterX=(group.bounds.minX+group.bounds.maxX)/2,currentCenterY=(group.bounds.minY+group.bounds.maxY)/2,newCenterX=packedComponent.center.x,newCenterY=packedComponent.center.y,offsetX=newCenterX-currentCenterX,offsetY=newCenterY-currentCenterY;for(let chipId of group.chipIds){let originalPlacement=packedPartition.layout.chipPlacements[chipId];newChipPlacements[chipId]={x:originalPlacement.x+offsetX,y:originalPlacement.y+offsetY,ccwRotationDegrees:originalPlacement.ccwRotationDegrees}}}}return{chipPlacements:newChipPlacements,groupPlacements:{}}}getCombinedPackedPartitionsProblem(){let combinedProblem={chipMap:{},chipPinMap:{},pinStrongConnMap:{},netMap:{},netConnMap:{},chipGap:this.inputProblem.chipGap,partitionGap:this.inputProblem.partitionGap};for(let packedPartition of this.packedPartitions)Object.assign(combinedProblem.chipMap,packedPartition.inputProblem.chipMap),Object.assign(combinedProblem.chipPinMap,packedPartition.inputProblem.chipPinMap),Object.assign(combinedProblem.pinStrongConnMap,packedPartition.inputProblem.pinStrongConnMap),Object.assign(combinedProblem.netMap,packedPartition.inputProblem.netMap),Object.assign(combinedProblem.netConnMap,packedPartition.inputProblem.netConnMap);return combinedProblem}getCombinedPackedPartitionsLayout(){let chipPlacements={};for(let packedPartition of this.packedPartitions)Object.assign(chipPlacements,packedPartition.layout.chipPlacements);return{chipPlacements,groupPlacements:{}}}visualize(){return this.packSolver2&&!this.solved?this.packSolver2.visualize():this.finalLayout?visualizeInputProblem(this.getCombinedPackedPartitionsProblem(),this.finalLayout):this.packedPartitions.length===0?super.visualize():visualizeInputProblem(this.getCombinedPackedPartitionsProblem(),this.getCombinedPackedPartitionsLayout())}getConstructorParams(){return{packedPartitions:this.packedPartitions,inputProblem:this.inputProblem}}},VERTICAL_PIN_CLEARANCE=.2,getPinY=(pin,placement)=>placement.y+rotatePinOffset(pin.offset,placement.ccwRotationDegrees).y,getVerticalPinClearanceOffset=({upperPin,upperPlacement,lowerPin,lowerPlacement})=>getPinY(upperPin,upperPlacement)-getPinY(lowerPin,lowerPlacement)-VERTICAL_PIN_CLEARANCE,getPositiveRailPin=({chipId,side},inputProblem)=>inputProblem.chipMap[chipId]?.pins.filter(pinId=>!side||inputProblem.chipPinMap[pinId]?.side===side).map(pinId=>inputProblem.chipPinMap[pinId]).find(pin=>pin&&Object.values(inputProblem.netMap).some(net=>net.isPositiveVoltageSource&&inputProblem.netConnMap[`${pin.pinId}-${net.netId}`])),getChipBounds=(chipId,{inputProblem,layout})=>{let placement=layout.chipPlacements[chipId],chip=inputProblem.chipMap[chipId];if(!placement||!chip)return null;let size3=getRotatedSize(chip.size,placement.ccwRotationDegrees);return getBoundFromCenteredRect({center:placement,width:size3.x,height:size3.y})},getPartitionBounds=(chipIds,context)=>{let corners=chipIds.flatMap(chipId=>{let bounds=getChipBounds(chipId,context);return bounds?[{x:bounds.minX,y:bounds.minY},{x:bounds.maxX,y:bounds.maxY}]:[]});return getBoundsFromPoints2(corners)},getDirectNeighbor=({mainPartition,mainChipId,side},inputProblem)=>{let sidePins=new Set(inputProblem.chipMap[mainChipId]?.pins.filter(pinId=>inputProblem.chipPinMap[pinId]?.side===side)),pinOwnerMap=createPinOwnerMap(mainPartition.inputProblem);for(let[connection,connected]of Object.entries(inputProblem.pinStrongConnMap)){if(!connected)continue;let[pinA,pinB]=connection.split("-"),neighborPin=sidePins.has(pinA)?pinB:sidePins.has(pinB)?pinA:null;if(!neighborPin)continue;let neighbor=pinOwnerMap.get(neighborPin);if(neighbor?.chipId!==mainChipId&&neighbor)return neighbor.chipId}return null},partitionsHaveDirectConnection=({partitionA,partitionB},inputProblem)=>{let pinsA=new Set(Object.keys(partitionA.inputProblem.chipPinMap)),pinsB=new Set(Object.keys(partitionB.inputProblem.chipPinMap));return Object.entries(inputProblem.pinStrongConnMap).some(([connection,connected])=>{if(!connected)return!1;let[pinA,pinB]=connection.split("-");return pinsA.has(pinA)&&pinsB.has(pinB)||pinsA.has(pinB)&&pinsB.has(pinA)})},movedChipsOverlap=(movedChipIds,context)=>{let movedChipIdSet=new Set(movedChipIds);return movedChipIds.some(movedChipId=>{let movedBounds=getChipBounds(movedChipId,context);return Object.keys(context.layout.chipPlacements).some(chipId=>{if(!movedBounds||movedChipIdSet.has(chipId))return!1;let chipBounds=getChipBounds(chipId,context);return chipBounds?doBoundsOverlap(movedBounds,chipBounds):!1})})},getRowOffset=({side,chipGap,mainBounds,rowBounds,neighbor})=>{let rowCenter=getBoundsCenter2(rowBounds),offset={x:neighbor.x-rowCenter.x,y:neighbor.y-rowCenter.y};return side==="x+"&&(offset.x=mainBounds.maxX+chipGap-rowBounds.minX),side==="x-"&&(offset.x=mainBounds.minX-chipGap-rowBounds.maxX),side==="y+"&&(offset.y=mainBounds.maxY+chipGap-rowBounds.minY),side==="y-"&&(offset.y=mainBounds.minY-chipGap-rowBounds.maxY),offset},placeNetOnlyDecouplingRow=({layout,decouplingPartition},{inputProblem,packedPartitions})=>{let partition=decouplingPartition.inputProblem,mainChipId=partition.decouplingMainChipId,side=partition.decouplingMainChipSide;if(partition.partitionType!=="decoupling_caps"||!mainChipId||!side)return;let mainPartition=packedPartitions.find(candidate=>candidate!==decouplingPartition&&candidate.inputProblem.chipMap[mainChipId]);if(!mainPartition||partitionsHaveDirectConnection({partitionA:decouplingPartition,partitionB:mainPartition},inputProblem))return;let neighborId=getDirectNeighbor({mainPartition,mainChipId,side},inputProblem),neighbor=layout.chipPlacements[mainChipId];neighborId&&(neighbor=layout.chipPlacements[neighborId]);let rowChipIds=Object.keys(partition.chipMap),boundsContext={inputProblem,layout},mainBounds=getPartitionBounds(Object.keys(mainPartition.inputProblem.chipMap),boundsContext),rowBounds=getPartitionBounds(rowChipIds,boundsContext);if(!neighbor||!mainBounds||!rowBounds)return;if(!neighborId){let rowChipId=rowChipIds[0],mainRailPin=getPositiveRailPin({chipId:mainChipId,side},inputProblem),rowRailPin=rowChipId&&getPositiveRailPin({chipId:rowChipId},inputProblem),rowPlacement=rowChipId&&layout.chipPlacements[rowChipId];if(!mainRailPin||!rowRailPin||!rowPlacement)return;neighbor={...neighbor,y:neighbor.y+getVerticalPinClearanceOffset({upperPin:mainRailPin,upperPlacement:neighbor,lowerPin:rowRailPin,lowerPlacement:{...rowPlacement,y:neighbor.y}})}}let mainToRowGap=inputProblem.chipGap;neighborId||(mainToRowGap=inputProblem.partitionGap);let offset=getRowOffset({side,chipGap:mainToRowGap,mainBounds,rowBounds,neighbor}),rowToPlacedTransform=translate(offset.x,offset.y),previousPlacements=new Map;for(let chipId of rowChipIds){let placement=layout.chipPlacements[chipId];placement&&(previousPlacements.set(chipId,placement),layout.chipPlacements[chipId]={...placement,...applyToPoint(rowToPlacedTransform,placement)})}if(movedChipsOverlap(rowChipIds,boundsContext))for(let[chipId,placement]of previousPlacements)layout.chipPlacements[chipId]=placement},PlaceNetOnlyDecouplingRowsSolver=class extends BaseSolver4{constructor(options){super();__publicField(this,"options");__publicField(this,"outputLayout",null);this.options=options}_step(){this.outputLayout=structuredClone(this.options.inputLayout);for(let decouplingPartition of this.options.packedPartitions)placeNetOnlyDecouplingRow({layout:this.outputLayout,decouplingPartition},this.options);this.solved=!0}visualize(){return visualizeInputProblem(this.options.inputProblem,this.outputLayout??this.options.inputLayout)}getConstructorParams(){return[this.options]}},DEFAULT_CCW_ROTATIONS_DEGREES=[0,90,180,270],DEFAULT_CCW_ROTATION_DEGREES=0,HALF=.5,getVerticalRotation=({chip,upperPinId,lowerPinId,inputProblem})=>{let upperPin=inputProblem.chipPinMap[upperPinId],lowerPin=inputProblem.chipPinMap[lowerPinId];if(!upperPin||!lowerPin)return DEFAULT_CCW_ROTATION_DEGREES;let ccwRotationsDegrees=chip.availableRotations??DEFAULT_CCW_ROTATIONS_DEGREES,bestCcwRotationDegrees=DEFAULT_CCW_ROTATION_DEGREES,bestPinDeltaY=Number.NEGATIVE_INFINITY;for(let ccwRotationDegrees of ccwRotationsDegrees){let upperPinOffset=rotatePinOffset(upperPin.offset,ccwRotationDegrees),lowerPinOffset=rotatePinOffset(lowerPin.offset,ccwRotationDegrees),pinDeltaY=upperPinOffset.y-lowerPinOffset.y;pinDeltaY<=bestPinDeltaY||(bestPinDeltaY=pinDeltaY,bestCcwRotationDegrees=ccwRotationDegrees)}return bestCcwRotationDegrees},alignChipConnectedRailLoads=({railLoadPairs,inputProblem,inputLayout})=>{let outputLayout=structuredClone(inputLayout),{chipPlacements}=outputLayout,railLoadPairsByMainChipId=new Map;for(let railLoadPair of railLoadPairs){let mainChipRailLoadPairs=railLoadPairsByMainChipId.get(railLoadPair.mainChipId)??[];mainChipRailLoadPairs.push(railLoadPair),railLoadPairsByMainChipId.set(railLoadPair.mainChipId,mainChipRailLoadPairs)}for(let mainChipRailLoadPairs of railLoadPairsByMainChipId.values()){let rowRightEdge;for(let railLoadPair of mainChipRailLoadPairs){let railComponentPlacement=chipPlacements[railLoadPair.railComponent.chipId],resistorPlacement=chipPlacements[railLoadPair.resistor.chipId],mainChipPlacement=chipPlacements[railLoadPair.mainChipId],mainPin=inputProblem.chipPinMap[railLoadPair.mainPinId];if(!railComponentPlacement||!resistorPlacement||!mainChipPlacement||!mainPin)continue;let railComponentCcwRotationDegrees=getVerticalRotation({chip:railLoadPair.railComponent,upperPinId:railLoadPair.railPinId,lowerPinId:railLoadPair.railComponentResistorPinId,inputProblem}),resistorCcwRotationDegrees=getVerticalRotation({chip:railLoadPair.resistor,upperPinId:railLoadPair.resistorRailComponentPinId,lowerPinId:railLoadPair.resistorMainPinId,inputProblem}),railComponentSize=getRotatedSize(railLoadPair.railComponent.size,railComponentCcwRotationDegrees),resistorSize=getRotatedSize(railLoadPair.resistor.size,resistorCcwRotationDegrees),centerDistance=railComponentSize.y*HALF+inputProblem.chipGap+resistorSize.y*HALF,mainPinOffset=rotatePinOffset(mainPin.offset,mainChipPlacement.ccwRotationDegrees),resistorMainPin=inputProblem.chipPinMap[railLoadPair.resistorMainPinId];if(!resistorMainPin)continue;let resistorMainPinOffset=rotatePinOffset(resistorMainPin.offset,resistorCcwRotationDegrees),pairX=(railComponentPlacement.x+resistorPlacement.x)*HALF,resistorRowY=mainChipPlacement.y+mainPinOffset.y-resistorMainPinOffset.y,railComponentRowY=resistorRowY+centerDistance;chipPlacements[railLoadPair.railComponent.chipId]={x:pairX,y:railComponentRowY,ccwRotationDegrees:railComponentCcwRotationDegrees},chipPlacements[railLoadPair.resistor.chipId]={x:pairX,y:resistorRowY,ccwRotationDegrees:resistorCcwRotationDegrees};let pairHalfWidth=Math.max(railComponentSize.x,resistorSize.x)*HALF,pairMinX=pairX-pairHalfWidth,pairMaxX=pairX+pairHalfWidth;if(rowRightEdge!==void 0){let horizontalShift=rowRightEdge+inputProblem.partitionGap-pairMinX;pairX+=horizontalShift,chipPlacements[railLoadPair.railComponent.chipId].x=pairX,chipPlacements[railLoadPair.resistor.chipId].x=pairX,rowRightEdge=pairMaxX+horizontalShift;continue}rowRightEdge=pairMaxX}}return offsetChipConnectedRailLoadConnections({railLoadPairs,inputProblem,chipPlacements}),outputLayout},TWO_PIN_COMPONENT_PIN_COUNT3=2,getStronglyConnectedPinIds=({connectedPinsByPinId,pinId})=>(connectedPinsByPinId[pinId]??[]).map(connectedPin=>connectedPin.pinId),pinConnectsToPositiveVoltage=({inputProblem,pinId})=>{for(let[netId,net]of Object.entries(inputProblem.netMap))if(net.isPositiveVoltageSource&&inputProblem.netConnMap[`${pinId}-${netId}`])return!0;return!1},getRailLoadPair=(resistor,context)=>{let{inputProblem,pinOwnerMap,connectedPinsByPinId}=context;for(let resistorMainPinId of resistor.pins){let mainPinId=getStronglyConnectedPinIds({connectedPinsByPinId,pinId:resistorMainPinId}).find(pinId=>{let chip=pinOwnerMap.get(pinId);return chip?chip.pins.length>TWO_PIN_COMPONENT_PIN_COUNT3&&!chip.isCrystal:!1});if(!mainPinId)continue;let mainChip=pinOwnerMap.get(mainPinId);if(!mainChip)continue;let resistorRailComponentPinId=resistor.pins.find(pinId=>pinId!==resistorMainPinId);if(!resistorRailComponentPinId)continue;let railComponentResistorPinId=getStronglyConnectedPinIds({connectedPinsByPinId,pinId:resistorRailComponentPinId}).find(pinId=>{let chip=pinOwnerMap.get(pinId);return!chip||chip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT3?!1:!chip.isResistor&&!chip.isCapacitor&&!chip.fixedPosition});if(!railComponentResistorPinId)continue;let railComponent=pinOwnerMap.get(railComponentResistorPinId);if(!railComponent)continue;let railPinId=railComponent.pins.find(pinId=>pinId!==railComponentResistorPinId&&pinConnectsToPositiveVoltage({inputProblem,pinId}));if(railPinId)return{railComponent,resistor,railPinId,railComponentResistorPinId,resistorRailComponentPinId,resistorMainPinId,mainChipId:mainChip.chipId,mainPinId}}return null},getChipConnectedRailLoadPairs=inputProblem=>{let context={inputProblem,pinOwnerMap:createPinOwnerMap(inputProblem),connectedPinsByPinId:getPinIdToStronglyConnectedPinsObj(inputProblem)},railLoadPairs=[];for(let chip of Object.values(inputProblem.chipMap)){if(!chip.isResistor||chip.fixedPosition)continue;let railLoadPair=getRailLoadPair(chip,context);railLoadPair&&railLoadPairs.push(railLoadPair)}return railLoadPairs},AlignChipConnectedRailLoadsSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"params");__publicField(this,"outputLayout",null);this.params=params}_step(){let railLoadPairs=getChipConnectedRailLoadPairs(this.params.inputProblem);this.outputLayout=alignChipConnectedRailLoads({railLoadPairs,inputProblem:this.params.inputProblem,inputLayout:this.params.inputLayout}),this.solved=!0}visualize(){let outputLayout=this.params.inputLayout;return this.outputLayout&&(outputLayout=this.outputLayout),visualizeInputProblem(this.params.inputProblem,outputLayout)}getConstructorParams(){return[this.params]}},TWO_PIN_COMPONENT_PIN_COUNT4=2,getStronglyConnectedPinIds2=({connectedPinsByPinId,pinId})=>(connectedPinsByPinId[pinId]??[]).map(connectedPin=>connectedPin.pinId),getNetIdsForPin=({inputProblem,pinId})=>{let netIds=[];for(let netId of Object.keys(inputProblem.netMap))inputProblem.netConnMap[`${pinId}-${netId}`]&&netIds.push(netId);return netIds},getPinIdsForNet=({inputProblem,netId})=>{let pinIds=[];for(let pinId of Object.keys(inputProblem.chipPinMap))inputProblem.netConnMap[`${pinId}-${netId}`]&&pinIds.push(pinId);return pinIds},getGroundConnection=({lowerChip,lowerInnerPinId,inputProblem})=>{for(let groundPinId of lowerChip.pins){if(groundPinId===lowerInnerPinId)continue;let groundNetId=getNetIdsForPin({inputProblem,pinId:groundPinId}).find(netId=>inputProblem.netMap[netId]?.isGround===!0);if(groundNetId)return{groundPinId,groundNetId}}return null},pinConnectsToPositiveVoltage2=({inputProblem,pinId})=>getNetIdsForPin({inputProblem,pinId}).some(netId=>inputProblem.netMap[netId]?.isPositiveVoltageSource===!0),getDirectlyConnectedGroundedLowerChip=({upperInnerPinId},ctx)=>{let{inputProblem,pinOwnerMap,connectedPinsByPinId,pairedChipIds}=ctx;for(let lowerInnerPinId of getStronglyConnectedPinIds2({connectedPinsByPinId,pinId:upperInnerPinId})){let lowerChip=pinOwnerMap.get(lowerInnerPinId);if(!lowerChip||lowerChip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT4||lowerChip.fixedPosition||pairedChipIds.has(lowerChip.chipId))continue;let groundConnection=getGroundConnection({lowerChip,lowerInnerPinId,inputProblem});if(groundConnection)return{lowerChip,lowerInnerPinId,...groundConnection}}return null},getChipConnectedPair=(upperChip,ctx)=>{let{inputProblem,pinOwnerMap,connectedPinsByPinId,pairedChipIds}=ctx;for(let upperOuterPinId of upperChip.pins){let mainPinId=getStronglyConnectedPinIds2({connectedPinsByPinId,pinId:upperOuterPinId}).find(pinId=>{let chip=pinOwnerMap.get(pinId);return chip?chip.pins.length>TWO_PIN_COMPONENT_PIN_COUNT4&&!chip.isCrystal:!1});if(!mainPinId)continue;let mainChip=pinOwnerMap.get(mainPinId);if(!mainChip)continue;let upperInnerPinId=upperChip.pins.find(pinId=>pinId!==upperOuterPinId);if(!upperInnerPinId)continue;let lowerChip=getStronglyConnectedPinIds2({connectedPinsByPinId,pinId:upperInnerPinId}).map(pinId=>pinOwnerMap.get(pinId)).find(chip=>!chip||chip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT4||chip.chipId===upperChip.chipId||chip.fixedPosition?!1:!pairedChipIds.has(chip.chipId));if(!lowerChip)continue;let lowerInnerPinId=lowerChip.pins.find(pinId=>getStronglyConnectedPinIds2({connectedPinsByPinId,pinId}).some(connectedPinId=>pinOwnerMap.get(connectedPinId)?.chipId===upperChip.chipId));if(!lowerInnerPinId)continue;let groundConnection=getGroundConnection({lowerChip,lowerInnerPinId,inputProblem});if(groundConnection)return{upperChip,lowerChip,mainChipId:mainChip.chipId,mainPinId,upperOuterPinId,upperInnerPinId,lowerInnerPinId,...groundConnection}}return null},getRailConnectedPair=(upperChip,ctx)=>{let{inputProblem,pinOwnerMap,pairedChipIds}=ctx,upperOuterPinId=upperChip.pins.find(pinId=>pinConnectsToPositiveVoltage2({inputProblem,pinId}));if(!upperOuterPinId)return null;let upperInnerPinId=upperChip.pins.find(pinId=>pinId!==upperOuterPinId);if(!upperInnerPinId)return null;let directlyConnectedLowerChip=getDirectlyConnectedGroundedLowerChip({upperInnerPinId},ctx);if(directlyConnectedLowerChip)return{upperChip,upperOuterPinId,upperInnerPinId,...directlyConnectedLowerChip};let internalNetId=getNetIdsForPin({inputProblem,pinId:upperInnerPinId}).find(netId=>{let net=inputProblem.netMap[netId];return!net?.isGround&&!net?.isPositiveVoltageSource});if(!internalNetId)return null;let internalPinIds=getPinIdsForNet({inputProblem,netId:internalNetId});if(internalPinIds.length!==TWO_PIN_COMPONENT_PIN_COUNT4)return null;let lowerInnerPinId=internalPinIds.find(pinId=>pinId!==upperInnerPinId);if(!lowerInnerPinId)return null;let lowerChip=pinOwnerMap.get(lowerInnerPinId);if(!lowerChip||lowerChip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT4||lowerChip.fixedPosition||pairedChipIds.has(lowerChip.chipId))return null;let groundConnection=getGroundConnection({lowerChip,lowerInnerPinId,inputProblem});return groundConnection?{upperChip,lowerChip,upperOuterPinId,upperInnerPinId,lowerInnerPinId,...groundConnection}:null},getSignalConnectedPair=(upperChip,ctx)=>{let{inputProblem}=ctx;for(let upperOuterPinId of upperChip.pins){if(!getNetIdsForPin({inputProblem,pinId:upperOuterPinId}).some(netId=>{let net=inputProblem.netMap[netId];return net?.isGround||net?.isPositiveVoltageSource?!1:getPinIdsForNet({inputProblem,netId}).length===1}))continue;let upperInnerPinId=upperChip.pins.find(pinId=>pinId!==upperOuterPinId);if(!upperInnerPinId)continue;let directlyConnectedLowerChip=getDirectlyConnectedGroundedLowerChip({upperInnerPinId},ctx);if(directlyConnectedLowerChip)return{upperChip,upperOuterPinId,upperInnerPinId,...directlyConnectedLowerChip,isStandaloneSignalChain:!0}}return null},getGroundedLoadPairs=inputProblem=>{let pinOwnerMap=createPinOwnerMap(inputProblem),groundedLoadPairs=[],pairedChipIds=new Set,connectedPinsByPinId=getPinIdToStronglyConnectedPinsObj(inputProblem),ctx={inputProblem,pinOwnerMap,connectedPinsByPinId,pairedChipIds};for(let upperChip of Object.values(inputProblem.chipMap)){if(upperChip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT4||upperChip.fixedPosition||pairedChipIds.has(upperChip.chipId))continue;let groundedLoadPair=getChipConnectedPair(upperChip,ctx);groundedLoadPair&&(groundedLoadPairs.push(groundedLoadPair),pairedChipIds.add(groundedLoadPair.upperChip.chipId),pairedChipIds.add(groundedLoadPair.lowerChip.chipId))}for(let upperChip of Object.values(inputProblem.chipMap)){if(upperChip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT4||upperChip.fixedPosition||pairedChipIds.has(upperChip.chipId))continue;let groundedLoadPair=getSignalConnectedPair(upperChip,ctx);groundedLoadPair&&(groundedLoadPairs.push(groundedLoadPair),pairedChipIds.add(groundedLoadPair.upperChip.chipId),pairedChipIds.add(groundedLoadPair.lowerChip.chipId))}for(let upperChip of Object.values(inputProblem.chipMap)){if(upperChip.pins.length!==TWO_PIN_COMPONENT_PIN_COUNT4||upperChip.fixedPosition||pairedChipIds.has(upperChip.chipId))continue;let groundedLoadPair=getRailConnectedPair(upperChip,ctx);groundedLoadPair&&(groundedLoadPairs.push(groundedLoadPair),pairedChipIds.add(groundedLoadPair.upperChip.chipId),pairedChipIds.add(groundedLoadPair.lowerChip.chipId))}return groundedLoadPairs},DEFAULT_CCW_ROTATIONS_DEGREES2=[0,90,180,270],DEFAULT_CCW_ROTATION_DEGREES2=0,HALF2=.5,getVerticalRotation2=({chip,upperPinId,lowerPinId,inputProblem})=>{let upperPin=inputProblem.chipPinMap[upperPinId],lowerPin=inputProblem.chipPinMap[lowerPinId];if(!upperPin||!lowerPin)return DEFAULT_CCW_ROTATION_DEGREES2;let ccwRotationsDegrees=DEFAULT_CCW_ROTATIONS_DEGREES2;chip.availableRotations&&(ccwRotationsDegrees=chip.availableRotations);let bestCcwRotationDegrees=DEFAULT_CCW_ROTATION_DEGREES2,bestPinDeltaY=Number.NEGATIVE_INFINITY;for(let ccwRotationDegrees of ccwRotationsDegrees){let upperPinOffset=rotatePinOffset(upperPin.offset,ccwRotationDegrees),lowerPinOffset=rotatePinOffset(lowerPin.offset,ccwRotationDegrees),pinDeltaY=upperPinOffset.y-lowerPinOffset.y;pinDeltaY<=bestPinDeltaY||(bestPinDeltaY=pinDeltaY,bestCcwRotationDegrees=ccwRotationDegrees)}return bestCcwRotationDegrees},getChipBounds2=({chip,placement})=>{let size3=getRotatedSize(chip.size,placement.ccwRotationDegrees);return getBoundFromCenteredRect({center:placement,width:size3.x,height:size3.y})},movePairBelowObstacles=({groundedLoadPair,chipPlacements,inputProblem})=>{let upperPlacement=chipPlacements[groundedLoadPair.upperChip.chipId],lowerPlacement=chipPlacements[groundedLoadPair.lowerChip.chipId];if(!upperPlacement||!lowerPlacement)return;let upperBounds=getChipBounds2({chip:groundedLoadPair.upperChip,placement:upperPlacement}),lowerBounds=getChipBounds2({chip:groundedLoadPair.lowerChip,placement:lowerPlacement}),pairBounds=getBoundsFromPoints2([{x:upperBounds.minX,y:upperBounds.minY},{x:upperBounds.maxX,y:upperBounds.maxY},{x:lowerBounds.minX,y:lowerBounds.minY},{x:lowerBounds.maxX,y:lowerBounds.maxY}]);if(!pairBounds)return;let downwardShift=0;for(let[chipId,placement]of Object.entries(chipPlacements)){if(chipId===groundedLoadPair.upperChip.chipId||chipId===groundedLoadPair.lowerChip.chipId)continue;let chip=inputProblem.chipMap[chipId];if(!chip)continue;let bounds=getChipBounds2({chip,placement});if(pairBounds.maxX+inputProblem.chipGap<=bounds.minX||pairBounds.minX-inputProblem.chipGap>=bounds.maxX||bounds.maxY<=pairBounds.maxY)continue;let requiredShift=pairBounds.maxY+inputProblem.chipGap-bounds.minY;downwardShift=Math.max(downwardShift,requiredShift)}upperPlacement.y-=downwardShift,lowerPlacement.y-=downwardShift},layoutGroundedLoadPair=({groundedLoadPair,chipPlacements,inputProblem})=>{let upperPlacement=chipPlacements[groundedLoadPair.upperChip.chipId],lowerPlacement=chipPlacements[groundedLoadPair.lowerChip.chipId];if(!upperPlacement||!lowerPlacement)return;let upperCcwRotationDegrees=getVerticalRotation2({chip:groundedLoadPair.upperChip,upperPinId:groundedLoadPair.upperOuterPinId,lowerPinId:groundedLoadPair.upperInnerPinId,inputProblem}),lowerCcwRotationDegrees=getVerticalRotation2({chip:groundedLoadPair.lowerChip,upperPinId:groundedLoadPair.lowerInnerPinId,lowerPinId:groundedLoadPair.groundPinId,inputProblem}),upperSize=getRotatedSize(groundedLoadPair.upperChip.size,upperCcwRotationDegrees),lowerSize=getRotatedSize(groundedLoadPair.lowerChip.size,lowerCcwRotationDegrees),centerDistance=upperSize.y*HALF2+inputProblem.chipGap+lowerSize.y*HALF2,upperInnerPin=inputProblem.chipPinMap[groundedLoadPair.upperInnerPinId],lowerInnerPin=inputProblem.chipPinMap[groundedLoadPair.lowerInnerPinId];if(!upperInnerPin||!lowerInnerPin)return;let upperInnerPinOffset=rotatePinOffset(upperInnerPin.offset,upperCcwRotationDegrees),lowerInnerPinOffset=rotatePinOffset(lowerInnerPin.offset,lowerCcwRotationDegrees),initialPairBounds=getBoundsFromPoints2([upperPlacement,lowerPlacement]);if(!initialPairBounds)return;let pairCenter=getBoundsCenter2(initialPairBounds),nextUpperPlacement={x:pairCenter.x-upperInnerPinOffset.x,y:pairCenter.y+centerDistance*HALF2,ccwRotationDegrees:upperCcwRotationDegrees},mainPinId=groundedLoadPair.mainPinId;if(mainPinId){let mainChipId=groundedLoadPair.mainChipId;if(!mainChipId)return;let mainPlacement=chipPlacements[mainChipId];if(!mainPlacement)return;let upperOuterPin=inputProblem.chipPinMap[groundedLoadPair.upperOuterPinId],mainPin=inputProblem.chipPinMap[mainPinId];if(!upperOuterPin||!mainPin)return;let oldUpperOuterPinOffset=rotatePinOffset(upperOuterPin.offset,upperPlacement.ccwRotationDegrees),newUpperOuterPinOffset=rotatePinOffset(upperOuterPin.offset,upperCcwRotationDegrees);nextUpperPlacement.x=upperPlacement.x+oldUpperOuterPinOffset.x-newUpperOuterPinOffset.x,nextUpperPlacement.y=upperPlacement.y+oldUpperOuterPinOffset.y-newUpperOuterPinOffset.y,nextUpperPlacement.y+=getVerticalPinClearanceOffset({upperPin:mainPin,upperPlacement:mainPlacement,lowerPin:upperOuterPin,lowerPlacement:nextUpperPlacement})}chipPlacements[groundedLoadPair.upperChip.chipId]=nextUpperPlacement,chipPlacements[groundedLoadPair.lowerChip.chipId]={x:nextUpperPlacement.x+upperInnerPinOffset.x-lowerInnerPinOffset.x,y:nextUpperPlacement.y-centerDistance,ccwRotationDegrees:lowerCcwRotationDegrees},movePairBelowObstacles({groundedLoadPair,chipPlacements,inputProblem})},MINIMUM_PAIRS_PER_ROW=2,getPairBounds=(groundedLoadPair,context)=>{let{chipPlacements}=context,upperPlacement=chipPlacements[groundedLoadPair.upperChip.chipId],lowerPlacement=chipPlacements[groundedLoadPair.lowerChip.chipId],upperBounds=getPlacementBounds({placement:upperPlacement,size:groundedLoadPair.upperChip.size}),lowerBounds=getPlacementBounds({placement:lowerPlacement,size:groundedLoadPair.lowerChip.size});return{minX:Math.min(upperBounds.minX,lowerBounds.minX),maxX:Math.max(upperBounds.maxX,lowerBounds.maxX)}},getGroundPinY=(groundedLoadPair,context)=>{let{chipPlacements,inputProblem}=context,placement=chipPlacements[groundedLoadPair.lowerChip.chipId],groundPin=inputProblem.chipPinMap[groundedLoadPair.groundPinId],groundPinOffset=rotatePinOffset(groundPin.offset,placement.ccwRotationDegrees);return placement.y+groundPinOffset.y},translateGroundedLoadPair=({groundedLoadPair,dx:dx3,dy:dy3},context)=>{let{chipPlacements}=context;for(let chipId of[groundedLoadPair.upperChip.chipId,groundedLoadPair.lowerChip.chipId]){let placement=chipPlacements[chipId];placement.x+=dx3,placement.y+=dy3}},getLeftPairEdge=(groundedLoadPair,context)=>getPairBounds(groundedLoadPair,context).minX,alignGroundedLoadPairRow=(groundedLoadPairs,context)=>{let{inputProblem}=context,leftToRightPairs=[...groundedLoadPairs].sort((pairA,pairB)=>getLeftPairEdge(pairA,context)-getLeftPairEdge(pairB,context)),initialGroundPinYs=leftToRightPairs.map(groundedLoadPair=>getGroundPinY(groundedLoadPair,context)),targetGroundPinY=Math.min(...initialGroundPinYs);for(let groundedLoadPair of leftToRightPairs){let groundPinY=getGroundPinY(groundedLoadPair,context);translateGroundedLoadPair({groundedLoadPair,dx:0,dy:targetGroundPinY-groundPinY},context)}let previousPairMaxX;for(let groundedLoadPair of leftToRightPairs){let pairBounds=getPairBounds(groundedLoadPair,context);if(previousPairMaxX===void 0){previousPairMaxX=pairBounds.maxX;continue}let dx3=previousPairMaxX+inputProblem.partitionGap-pairBounds.minX;translateGroundedLoadPair({groundedLoadPair,dx:dx3,dy:0},context),previousPairMaxX=pairBounds.maxX+dx3}},alignGroundedLoadPairRows=({groundedLoadPairs,chipPlacements,inputProblem})=>{let context={chipPlacements,inputProblem},pairsByGroundNetId=new Map;for(let groundedLoadPair of groundedLoadPairs){if(groundedLoadPair.mainChipId||!chipPlacements[groundedLoadPair.upperChip.chipId]||!chipPlacements[groundedLoadPair.lowerChip.chipId]||!inputProblem.chipPinMap[groundedLoadPair.groundPinId])continue;let groundNetId=groundedLoadPair.groundNetId,rowPairs=pairsByGroundNetId.get(groundNetId)??[];rowPairs.push(groundedLoadPair),pairsByGroundNetId.set(groundNetId,rowPairs)}for(let rowPairs of pairsByGroundNetId.values())rowPairs.length<MINIMUM_PAIRS_PER_ROW||alignGroundedLoadPairRow(rowPairs,context)},GroundedLoadPairSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"params");__publicField(this,"outputLayout",null);__publicField(this,"groundedLoadPairs",[]);this.params=params}_step(){let chipPlacements={};for(let[chipId,placement]of Object.entries(this.params.inputLayout.chipPlacements))chipPlacements[chipId]={...placement};this.groundedLoadPairs=getGroundedLoadPairs(this.params.inputProblem);for(let groundedLoadPair of this.groundedLoadPairs)layoutGroundedLoadPair({groundedLoadPair,chipPlacements,inputProblem:this.params.inputProblem});alignGroundedLoadPairRows({groundedLoadPairs:this.groundedLoadPairs,chipPlacements,inputProblem:this.params.inputProblem}),offsetChipAnchoredGroundedLoadConnections({groundedLoadPairs:this.groundedLoadPairs,inputProblem:this.params.inputProblem,chipPlacements}),this.outputLayout={chipPlacements,groupPlacements:{...this.params.inputLayout.groupPlacements}},this.solved=!0}visualize(){let outputLayout=this.params.inputLayout;return this.outputLayout&&(outputLayout=this.outputLayout),visualizeInputProblem(this.params.inputProblem,outputLayout)}getConstructorParams(){return[this.params]}},isTwoPinLoadPartition=partition=>{let chips=Object.values(partition.inputProblem.chipMap);return chips.length>1&&chips.every(chip=>chip.pins.length===2&&!chip.isCapacitor&&!chip.fixedPosition)},getRailConnectedLoadGroups=({groundedLoadPairs,packedPartitions})=>{let loadGroups=packedPartitions.filter(isTwoPinLoadPartition).map(partition=>({chipIds:Object.keys(partition.inputProblem.chipMap)})),groupedChipIds=new Set(loadGroups.flatMap(loadGroup=>loadGroup.chipIds));for(let groundedLoadPair of groundedLoadPairs){if(groundedLoadPair.mainChipId||groundedLoadPair.isStandaloneSignalChain)continue;let pairChipIds=[groundedLoadPair.upperChip.chipId,groundedLoadPair.lowerChip.chipId];if(!pairChipIds.some(chipId=>groupedChipIds.has(chipId))){loadGroups.push({chipIds:pairChipIds});for(let chipId of pairChipIds)groupedChipIds.add(chipId)}}return loadGroups},getChipBounds3=({chipId},context)=>{let chip=context.inputProblem.chipMap[chipId],placement=context.layout.chipPlacements[chipId];if(!chip||!placement)return null;let size3=getRotatedSize(chip.size,placement.ccwRotationDegrees);return getBoundFromCenteredRect({center:placement,width:size3.x,height:size3.y})},getPartitionBounds2=({chipIds},context)=>getBoundsFromPoints2(chipIds.flatMap(chipId=>{let bounds=getChipBounds3({chipId},context);return bounds?[{x:bounds.minX,y:bounds.minY},{x:bounds.maxX,y:bounds.maxY}]:[]})),getUpperRailPin=({chipIds,railNetIds},context)=>{let upperRailPin=null;for(let chipId of chipIds){let chip=context.inputProblem.chipMap[chipId];if(!chip)continue;let placement=context.layout.chipPlacements[chip.chipId];if(placement)for(let pinId of chip.pins){if(![...railNetIds].some(netId=>context.inputProblem.netConnMap[`${pinId}-${netId}`]))continue;let pin=context.inputProblem.chipPinMap[pinId];if(!pin)continue;let offset=rotatePinOffset(pin.offset,placement.ccwRotationDegrees),pinY=placement.y+offset.y;(upperRailPin===null||pinY>upperRailPin.y)&&(upperRailPin={chipId:chip.chipId,y:pinY})}}return upperRailPin},getRailNetIds=({chipIds},{inputProblem})=>{let railNetIds=new Set;for(let chipId of chipIds){let chip=inputProblem.chipMap[chipId];if(chip)for(let pinId of chip.pins)for(let[netId,net]of Object.entries(inputProblem.netMap))!net.isGround&&!net.isPositiveVoltageSource||inputProblem.netConnMap[`${pinId}-${netId}`]&&railNetIds.add(netId)}return railNetIds},haveSameRails=(railA,railB)=>railA.size>=2&&railA.size===railB.size&&[...railA].every(netId=>railB.has(netId)),movePartition=({chipIds,offset},{layout})=>{let previousPlacements=new Map;for(let chipId of chipIds){let placement=layout.chipPlacements[chipId];placement&&(previousPlacements.set(chipId,placement),layout.chipPlacements[chipId]={...placement,x:placement.x+offset.x,y:placement.y+offset.y})}return previousPlacements},movedPartitionOverlaps=({movedChipIds},context)=>{let movedChipIdSet=new Set(movedChipIds);return movedChipIds.some(movedChipId=>{let movedBounds=getChipBounds3({chipId:movedChipId},context);return movedBounds?Object.keys(context.layout.chipPlacements).some(chipId=>{if(movedChipIdSet.has(chipId))return!1;let bounds=getChipBounds3({chipId},context);return bounds?doBoundsOverlap(movedBounds,bounds):!1}):!1})},placeRailConnectedLoads=options=>{let{groundedLoadPairs,inputProblem,packedPartitions}=options,layout=structuredClone(options.inputLayout),context={inputProblem,layout},capacitorPartitions=packedPartitions.filter(partition=>partition.inputProblem.partitionType==="decoupling_caps"),loadGroups=getRailConnectedLoadGroups({groundedLoadPairs,packedPartitions}),placedLoadGroups=new Set;for(let capacitorPartition of capacitorPartitions){let capacitorRails=getRailNetIds({chipIds:Object.keys(capacitorPartition.inputProblem.chipMap)},context),capacitorChipIds=Object.keys(capacitorPartition.inputProblem.chipMap),initialCapacitorBounds=getPartitionBounds2({chipIds:capacitorChipIds},context);if(!initialCapacitorBounds)continue;let capacitorRailPin=getUpperRailPin({chipIds:capacitorChipIds,railNetIds:capacitorRails},context);if(!capacitorRailPin)continue;let rowRightEdge=initialCapacitorBounds.maxX;for(let loadGroup of loadGroups){if(placedLoadGroups.has(loadGroup))continue;let loadRails=getRailNetIds({chipIds:loadGroup.chipIds},context);if(!haveSameRails(capacitorRails,loadRails))continue;let loadChipIds=loadGroup.chipIds;if(!getPartitionBounds2({chipIds:loadChipIds},context))continue;let loadRailPin=getUpperRailPin({chipIds:loadChipIds,railNetIds:loadRails},context);if(!loadRailPin)continue;let loadAnchorBounds=getChipBounds3({chipId:loadRailPin.chipId},context);if(!loadAnchorBounds)continue;let previousPlacements=movePartition({chipIds:loadChipIds,offset:{x:rowRightEdge+inputProblem.partitionGap-loadAnchorBounds.minX,y:capacitorRailPin.y-loadRailPin.y}},context);if(movedPartitionOverlaps({movedChipIds:loadChipIds},context)){for(let[chipId,placement]of previousPlacements)layout.chipPlacements[chipId]=placement;continue}let placedBounds=getPartitionBounds2({chipIds:loadChipIds},context);placedBounds&&(rowRightEdge=placedBounds.maxX),placedLoadGroups.add(loadGroup)}}return layout},PlaceRailConnectedLoadsSolver=class extends BaseSolver4{constructor(options){super();__publicField(this,"options");__publicField(this,"outputLayout",null);this.options=options}_step(){this.outputLayout=placeRailConnectedLoads(this.options),this.solved=!0}visualize(){return visualizeInputProblem(this.options.inputProblem,this.outputLayout??this.options.inputLayout)}getConstructorParams(){return[this.options]}};function definePipelineStep3(solverName,solverClass,getConstructorParams,opts={}){return{solverName,solverClass,getConstructorParams,onSolved:opts.onSolved}}var LayoutPipelineSolver=class extends BaseSolver4{constructor(inputProblem){super();__publicField(this,"identifyCrystalCircuitsSolver");__publicField(this,"identifyDecouplingCapsSolver");__publicField(this,"chipPartitionsSolver");__publicField(this,"packInnerPartitionsSolver");__publicField(this,"partitionPackingSolver");__publicField(this,"groundedLoadPairSolver");__publicField(this,"alignPowerGroundRowsSolver");__publicField(this,"alignTestPointsSolver");__publicField(this,"placeNetOnlyDecouplingRowsSolver");__publicField(this,"placeRailConnectedLoadsSolver");__publicField(this,"alignChipConnectedRailLoadsSolver");__publicField(this,"startTimeOfPhase");__publicField(this,"endTimeOfPhase");__publicField(this,"timeSpentOnPhase");__publicField(this,"firstIterationOfPhase");__publicField(this,"pinIdToStronglyConnectedPins");__publicField(this,"inputProblem");__publicField(this,"chipPartitions");__publicField(this,"packedPartitions");__publicField(this,"pipelineDef",[definePipelineStep3("identifyCrystalCircuitsSolver",IdentifyCrystalCircuitsSolver,()=>[this.inputProblem]),definePipelineStep3("identifyDecouplingCapsSolver",IdentifyDecouplingCapsSolver,()=>[this.inputProblem],{onSolved:_layoutSolver=>{}}),definePipelineStep3("chipPartitionsSolver",ChipPartitionsSolver,()=>[{inputProblem:this.inputProblem,decouplingCapGroups:this.identifyDecouplingCapsSolver?.outputDecouplingCapGroups,crystalCircuitGroups:this.identifyCrystalCircuitsSolver?.outputCrystalCircuitGroups}],{onSolved:_layoutSolver=>{this.chipPartitions=this.chipPartitionsSolver.partitions}}),definePipelineStep3("packInnerPartitionsSolver",PackInnerPartitionsSolver,()=>[{partitions:this.chipPartitions,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}],{onSolved:_solver=>{this.packedPartitions=this.packInnerPartitionsSolver.packedPartitions}}),definePipelineStep3("partitionPackingSolver",PartitionPackingSolver,()=>[{packedPartitions:this.packedPartitions||[],inputProblem:this.inputProblem}],{onSolved:_solver=>{}}),definePipelineStep3("alignPowerGroundRowsSolver",AlignPowerGroundRowsSolver,()=>[{inputProblem:this.inputProblem,inputLayout:this.partitionPackingSolver.finalLayout}]),definePipelineStep3("placeNetOnlyDecouplingRowsSolver",PlaceNetOnlyDecouplingRowsSolver,()=>[{inputProblem:this.inputProblem,packedPartitions:this.packedPartitions,inputLayout:this.alignPowerGroundRowsSolver.outputLayout}]),definePipelineStep3("groundedLoadPairSolver",GroundedLoadPairSolver,()=>[{inputProblem:this.inputProblem,inputLayout:this.placeNetOnlyDecouplingRowsSolver.outputLayout}]),definePipelineStep3("placeRailConnectedLoadsSolver",PlaceRailConnectedLoadsSolver,()=>[{inputProblem:this.inputProblem,groundedLoadPairs:this.groundedLoadPairSolver.groundedLoadPairs,packedPartitions:this.packedPartitions,inputLayout:this.groundedLoadPairSolver.outputLayout}]),definePipelineStep3("alignChipConnectedRailLoadsSolver",AlignChipConnectedRailLoadsSolver,()=>[{inputProblem:this.inputProblem,inputLayout:this.placeRailConnectedLoadsSolver.outputLayout}]),definePipelineStep3("alignTestPointsSolver",AlignTestPointsSolver,()=>[{inputProblem:this.inputProblem,inputLayout:this.alignChipConnectedRailLoadsSolver.outputLayout??this.placeRailConnectedLoadsSolver.outputLayout??this.groundedLoadPairSolver.outputLayout??this.placeNetOnlyDecouplingRowsSolver.outputLayout??this.alignPowerGroundRowsSolver.outputLayout??this.partitionPackingSolver.finalLayout}])]);__publicField(this,"currentPipelineStepIndex",0);this.inputProblem=inputProblem,this.MAX_ITERATIONS=1e6,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={},this.firstIterationOfPhase={},this.pinIdToStronglyConnectedPins=getPinIdToStronglyConnectedPinsObj(inputProblem)}getSolverName(){return"LayoutPipelineSolver"}_step(){let pipelineStepDef=this.pipelineDef[this.currentPipelineStepIndex];if(!pipelineStepDef){this.solved=!0;return}if(this.activeSubSolver){this.activeSubSolver.step(),this.activeSubSolver.solved?(this.endTimeOfPhase[pipelineStepDef.solverName]=performance.now(),this.timeSpentOnPhase[pipelineStepDef.solverName]=this.endTimeOfPhase[pipelineStepDef.solverName]-this.startTimeOfPhase[pipelineStepDef.solverName],pipelineStepDef.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null);return}let constructorParams=pipelineStepDef.getConstructorParams(this);this.activeSubSolver=new pipelineStepDef.solverClass(...constructorParams),this[pipelineStepDef.solverName]=this.activeSubSolver,this.timeSpentOnPhase[pipelineStepDef.solverName]=0,this.startTimeOfPhase[pipelineStepDef.solverName]=performance.now(),this.firstIterationOfPhase[pipelineStepDef.solverName]=this.iterations}solveUntilPhase(phase){for(;this.getCurrentPhase()!==phase;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();if(this.solved&&this.alignTestPointsSolver?.solved)return this.alignTestPointsSolver.visualize();if(this.solved&&this.placeNetOnlyDecouplingRowsSolver?.solved)return this.placeNetOnlyDecouplingRowsSolver.visualize();if(this.solved&&this.alignPowerGroundRowsSolver?.solved)return this.alignPowerGroundRowsSolver.visualize();if(this.solved&&this.groundedLoadPairSolver?.solved)return this.groundedLoadPairSolver.visualize();if(this.solved&&this.partitionPackingSolver?.solved)return this.partitionPackingSolver.visualize();let identifyCrystalCircuitsViz=this.identifyCrystalCircuitsSolver?.visualize(),identifyDecouplingCapsViz=this.identifyDecouplingCapsSolver?.visualize(),chipPartitionsViz=this.chipPartitionsSolver?.visualize(),packInnerPartitionsViz=this.packInnerPartitionsSolver?.visualize(),partitionPackingViz=this.partitionPackingSolver?.visualize(),groundedLoadPairViz=this.groundedLoadPairSolver?.visualize(),alignPowerGroundRowsViz=this.alignPowerGroundRowsSolver?.visualize(),alignTestPointsViz=this.alignTestPointsSolver?.visualize(),placeNetOnlyDecouplingRowsViz=this.placeNetOnlyDecouplingRowsSolver?.visualize(),basicLayout=doBasicInputProblemLayout(this.inputProblem),visualizations=[visualizeInputProblem(this.inputProblem,basicLayout),identifyCrystalCircuitsViz,identifyDecouplingCapsViz,chipPartitionsViz,packInnerPartitionsViz,partitionPackingViz,groundedLoadPairViz,alignPowerGroundRowsViz,placeNetOnlyDecouplingRowsViz,alignTestPointsViz].filter(Boolean).map((viz,stepIndex)=>{for(let rect of viz.rects??[])rect.step=stepIndex;for(let point6 of viz.points??[])point6.step=stepIndex;for(let circle2 of viz.circles??[])circle2.step=stepIndex;for(let text of viz.texts??[])text.step=stepIndex;for(let line2 of viz.lines??[])line2.step=stepIndex;return viz});return visualizations.length===1?visualizations[0]:{points:visualizations.flatMap(v6=>v6.points||[]),rects:visualizations.flatMap(v6=>v6.rects||[]),lines:visualizations.flatMap(v6=>v6.lines||[]),circles:visualizations.flatMap(v6=>v6.circles||[]),texts:visualizations.flatMap(v6=>v6.texts||[])}}preview(){return this.activeSubSolver?this.activeSubSolver.preview():this.alignTestPointsSolver?.solved?this.alignTestPointsSolver.visualize():this.placeNetOnlyDecouplingRowsSolver?.solved?this.placeNetOnlyDecouplingRowsSolver.visualize():this.alignPowerGroundRowsSolver?.solved?this.alignPowerGroundRowsSolver.visualize():this.partitionPackingSolver?.solved?this.partitionPackingSolver.visualize():this.packInnerPartitionsSolver?.solved?this.packInnerPartitionsSolver.visualize():this.chipPartitionsSolver?.solved?this.chipPartitionsSolver.visualize():this.identifyDecouplingCapsSolver?.solved?this.identifyDecouplingCapsSolver.visualize():this.identifyCrystalCircuitsSolver?.solved?this.identifyCrystalCircuitsSolver.visualize():super.preview()}checkForOverlaps(layout){let overlaps=[],chipIds=Object.keys(layout.chipPlacements);for(let i6=0;i6<chipIds.length;i6++)for(let j6=i6+1;j6<chipIds.length;j6++){let chip1Id=chipIds[i6],chip2Id=chipIds[j6],placement1=layout.chipPlacements[chip1Id],placement2=layout.chipPlacements[chip2Id],chip1=this.inputProblem.chipMap[chip1Id],chip2=this.inputProblem.chipMap[chip2Id];if(!chip1||!chip2)continue;let bounds1=this.getRotatedBounds(placement1,chip1.size),bounds2=this.getRotatedBounds(placement2,chip2.size),overlapArea=this.calculateOverlapArea(bounds1,bounds2);overlapArea>0&&overlaps.push({chip1:chip1Id,chip2:chip2Id,overlapArea})}return overlaps}getRotatedBounds(placement,size3){let halfWidth=size3.x/2,halfHeight=size3.y/2,angleRad=placement.ccwRotationDegrees*Math.PI/180,cos6=Math.abs(Math.cos(angleRad)),sin6=Math.abs(Math.sin(angleRad)),rotatedWidth=halfWidth*cos6+halfHeight*sin6,rotatedHeight=halfWidth*sin6+halfHeight*cos6;return{minX:placement.x-rotatedWidth,maxX:placement.x+rotatedWidth,minY:placement.y-rotatedHeight,maxY:placement.y+rotatedHeight}}calculateOverlapArea(bounds1,bounds2){if(bounds1.maxX<=bounds2.minX||bounds1.minX>=bounds2.maxX||bounds1.maxY<=bounds2.minY||bounds1.minY>=bounds2.maxY)return 0;let overlapWidth=Math.min(bounds1.maxX,bounds2.maxX)-Math.max(bounds1.minX,bounds2.minX),overlapHeight=Math.min(bounds1.maxY,bounds2.maxY)-Math.max(bounds1.minY,bounds2.minY);return overlapWidth*overlapHeight}getOutputLayout(){if(!this.solved)throw new Error("Pipeline not solved yet. Call solve() or step() until solved.");let finalLayout;if(this.alignTestPointsSolver?.solved&&this.alignTestPointsSolver.outputLayout)finalLayout=this.alignTestPointsSolver.outputLayout;else if(this.placeNetOnlyDecouplingRowsSolver?.solved&&this.placeNetOnlyDecouplingRowsSolver.outputLayout)finalLayout=this.placeNetOnlyDecouplingRowsSolver.outputLayout;else if(this.alignPowerGroundRowsSolver?.solved&&this.alignPowerGroundRowsSolver.outputLayout)finalLayout=this.alignPowerGroundRowsSolver.outputLayout;else if(this.partitionPackingSolver?.solved&&this.partitionPackingSolver.finalLayout)finalLayout=this.partitionPackingSolver.finalLayout;else throw new Error("No layout available. Pipeline may have failed or not progressed far enough.");let overlaps=this.checkForOverlaps(finalLayout);if(overlaps.length>0){let overlapDetails=overlaps.map(overlap=>`${overlap.chip1} overlaps ${overlap.chip2} (area: ${overlap.overlapArea.toFixed(4)})`).join(", ");console.warn(`Warning: ${overlaps.length} chip overlaps detected in final layout: ${overlapDetails}`)}return finalLayout}};var ConnectivityMap2=class{constructor(netMap){__publicField(this,"netMap");__publicField(this,"idToNetMap");this.netMap=netMap,this.idToNetMap={};for(let[netId,ids]of Object.entries(netMap))for(let id3 of ids)this.idToNetMap[id3]=netId}addConnections(connections){for(let connection of connections){let existingNets=new Set;for(let id3 of connection){let existingNetId=this.idToNetMap[id3];existingNetId&&existingNets.add(existingNetId)}let targetNetId;if(existingNets.size===0)targetNetId=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[targetNetId]=[];else if(existingNets.size===1)targetNetId=existingNets.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{targetNetId=existingNets.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(let netId of existingNets)if(netId!==targetNetId){let targetNet=this.netMap[targetNetId],sourceNet=this.netMap[netId];if(targetNet&&sourceNet){targetNet.push(...sourceNet),this.netMap[netId]=targetNet;for(let id3 of targetNet)this.idToNetMap[id3]=targetNetId}}}for(let id3 of connection){let targetNet=this.netMap[targetNetId];targetNet&&!targetNet.includes(id3)&&targetNet.push(id3),this.idToNetMap[id3]=targetNetId}}}getIdsConnectedToNet(netId){return this.netMap[netId]||[]}getNetConnectedToId(id3){return this.idToNetMap[id3]}areIdsConnected(id1,id22){if(id1===id22)return!0;let netId1=this.getNetConnectedToId(id1);if(!netId1)return!1;let netId2=this.getNetConnectedToId(id22);return netId2?netId1===netId2||netId2===id1||netId2===id1:!1}areAllIdsConnected(ids){if(ids.length===0)return!0;let netId=this.getNetConnectedToId(ids[0]);if(!netId)return!1;for(let id3 of ids){let nextNetId=this.getNetConnectedToId(id3);if(nextNetId===void 0||nextNetId!==netId)return!1}return!0}};init_dist6();init_dist6();var FlatQueue=class{constructor(capacity2=1/0,ValuesArray=Float64Array,IdsArray=Uint32Array){let fixed=capacity2!==1/0;this.ids=fixed?new IdsArray(capacity2):[],this.values=fixed?new ValuesArray(capacity2):[],this.capacity=capacity2,this.length=0}clear(){this.length=0}push(item,priority){if(this.length===this.capacity)throw new RangeError("Queue is at capacity.");let pos=this.length++;for(;pos>0;){let parent=pos-1>>1,parentValue=this.values[parent];if(priority>=parentValue)break;this.ids[pos]=this.ids[parent],this.values[pos]=parentValue,pos=parent}this.ids[pos]=item,this.values[pos]=priority}pop(){if(this.length===0)return;let ids=this.ids,values=this.values,top=ids[0],last=--this.length;if(last>0){let id3=ids[last],value=values[last],pos=0,halfLen=last>>1;for(;pos<halfLen;){let left=(pos<<1)+1,right=left+1,child=left+(+(right<last)&+(values[right]<values[left]));if(values[child]>=value)break;ids[pos]=ids[child],values[pos]=values[child],pos=child}ids[pos]=id3,values[pos]=value}return top}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){Array.isArray(this.ids)&&(this.ids.length=this.length),Array.isArray(this.values)&&(this.values.length=this.length)}};var ARRAY_TYPES=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],VERSION=3,Flatbush=class _Flatbush{static from(data,byteOffset=0){if(byteOffset%8!==0)throw new Error("byteOffset must be 8-byte aligned.");if(!data||data.byteLength===void 0||"buffer"in data)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");let[magic,versionAndType]=new Uint8Array(data,byteOffset+0,2);if(magic!==251)throw new Error("Data does not appear to be in a Flatbush format.");let version2=versionAndType>>4;if(version2!==VERSION)throw new Error(`Got v${version2} data when expected v${VERSION}.`);let ArrayType=ARRAY_TYPES[versionAndType&15];if(!ArrayType)throw new Error("Unrecognized array type.");let[nodeSize]=new Uint16Array(data,byteOffset+2,1),[numItems]=new Uint32Array(data,byteOffset+4,1);return new _Flatbush(numItems,nodeSize,ArrayType,void 0,data,byteOffset)}constructor(numItems,nodeSize=16,ArrayType=Float64Array,ArrayBufferType=ArrayBuffer,data,byteOffset=0){if(numItems===void 0)throw new Error("Missing required argument: numItems.");if(isNaN(numItems)||numItems<=0)throw new Error(`Unexpected numItems value: ${numItems}.`);this.numItems=+numItems,this.nodeSize=Math.min(Math.max(+nodeSize,2),65535),this.byteOffset=byteOffset;let n3=numItems,numNodes=n3;this._levelBounds=[n3*4];do n3=Math.ceil(n3/this.nodeSize),numNodes+=n3,this._levelBounds.push(numNodes*4);while(n3!==1);this.ArrayType=ArrayType,this.IndexArrayType=numNodes<16384?Uint16Array:Uint32Array;let arrayTypeIndex=ARRAY_TYPES.indexOf(ArrayType),nodesByteSize=numNodes*4*ArrayType.BYTES_PER_ELEMENT;if(arrayTypeIndex<0)throw new Error(`Unexpected typed array class: ${ArrayType}.`);let BoxCtor=ArrayType,IdxCtor=this.IndexArrayType;if(data)this.data=data,this._boxes=new BoxCtor(data,byteOffset+8,numNodes*4),this._indices=new IdxCtor(data,byteOffset+8+nodesByteSize,numNodes),this._pos=numNodes*4,this.minX=this._boxes[this._pos-4],this.minY=this._boxes[this._pos-3],this.maxX=this._boxes[this._pos-2],this.maxY=this._boxes[this._pos-1];else{let data2=this.data=new ArrayBufferType(8+nodesByteSize+numNodes*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new BoxCtor(data2,8,numNodes*4),this._indices=new IdxCtor(data2,8+nodesByteSize,numNodes),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(data2,0,2).set([251,(VERSION<<4)+arrayTypeIndex]),new Uint16Array(data2,2,1)[0]=nodeSize,new Uint32Array(data2,4,1)[0]=numItems}this._queue=new FlatQueue}add(minX,minY,maxX=minX,maxY=minY){let pos=this._pos,index=pos>>2,boxes=this._boxes;return this._indices[index]=index,boxes[pos]=minX,boxes[pos+1]=minY,boxes[pos+2]=maxX,boxes[pos+3]=maxY,this._pos=pos+4,minX<this.minX&&(this.minX=minX),minY<this.minY&&(this.minY=minY),maxX>this.maxX&&(this.maxX=maxX),maxY>this.maxY&&(this.maxY=maxY),index}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);let boxes=this._boxes;if(this.numItems<=this.nodeSize){boxes[this._pos++]=this.minX,boxes[this._pos++]=this.minY,boxes[this._pos++]=this.maxX,boxes[this._pos++]=this.maxY;return}let{numItems,minX,minY,nodeSize,_indices:indices,_levelBounds:levelBounds}=this,width=this.maxX-minX||1,height=this.maxY-minY||1,hilbertValues=new Int32Array(numItems),hilbertMax=65535,sx3=hilbertMax/width,sy3=hilbertMax/height;for(let i6=0,pos2=0;i6<numItems;i6++){let itemMinX=boxes[pos2++],itemMinY=boxes[pos2++],itemMaxX=boxes[pos2++],itemMaxY=boxes[pos2++],x6=sx3*((itemMinX+itemMaxX)/2-minX)|0,y2=sy3*((itemMinY+itemMaxY)/2-minY)|0;hilbertValues[i6]=hilbert(x6,y2)}sort(hilbertValues,boxes,indices,0,numItems-1,nodeSize);let pos=numItems*4;for(let i6=0,readPos=0;i6<levelBounds.length-1;i6++){let end=levelBounds[i6];for(;readPos<end;){let nodeIndex=readPos,nodeMinX=boxes[readPos++],nodeMinY=boxes[readPos++],nodeMaxX=boxes[readPos++],nodeMaxY=boxes[readPos++];for(let j6=1;j6<nodeSize&&readPos<end;j6++)nodeMinX=Math.min(nodeMinX,boxes[readPos++]),nodeMinY=Math.min(nodeMinY,boxes[readPos++]),nodeMaxX=Math.max(nodeMaxX,boxes[readPos++]),nodeMaxY=Math.max(nodeMaxY,boxes[readPos++]);indices[pos>>2]=nodeIndex,boxes[pos++]=nodeMinX,boxes[pos++]=nodeMinY,boxes[pos++]=nodeMaxX,boxes[pos++]=nodeMaxY}}this._pos=pos}search(minX,minY,maxX,maxY,filterFn){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let{_boxes:boxes,_levelBounds:levelBounds,_indices:indices,nodeSize}=this,numItems4=this.numItems*4,nodeIndex=boxes.length-4,level=levelBounds.length-1,q5=[],results=[],contained=!1;for(;nodeIndex!==void 0;){let end=Math.min(nodeIndex+nodeSize*4,levelBounds[level]),isNode=nodeIndex>=numItems4;if(contained)this._collectContained(nodeIndex,end,level,numItems4,results,filterFn);else for(let pos=nodeIndex;pos<end;pos+=4){let x03=boxes[pos];if(maxX<x03)continue;let y03=boxes[pos+1];if(maxY<y03)continue;let x12=boxes[pos+2];if(minX>x12)continue;let y12=boxes[pos+3];if(minY>y12)continue;let index=indices[pos>>2]|0;if(isNode){let c3=+(minX<=x03&&minY<=y03&&maxX>=x12&&maxY>=y12);q5.push(index|c3,level-1)}else(filterFn===void 0||filterFn(index,x03,y03,x12,y12))&&results.push(index)}level=q5.pop(),nodeIndex=q5.pop(),nodeIndex!==void 0&&(contained=(nodeIndex&1)===1,nodeIndex&=-2)}return results}_collectContained(nodeIndex,end,level,numItems4,results,filterFn){let boxes=this._boxes,indices=this._indices,pos=nodeIndex;for(let l6=level;l6>0;l6--)pos=indices[pos>>2];let leafEnd=Math.min(pos+(end-nodeIndex)*this.nodeSize**level,numItems4);if(filterFn===void 0)for(;pos<leafEnd;pos+=4)results.push(indices[pos>>2]|0);else for(;pos<leafEnd;pos+=4){let index=indices[pos>>2]|0;filterFn(index,boxes[pos],boxes[pos+1],boxes[pos+2],boxes[pos+3])&&results.push(index)}}neighbors(x6,y2,maxResults=1/0,maxDistance=1/0,filterFn){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let{_boxes:boxes,_levelBounds:levelBounds,_indices:indices,_queue:q5,nodeSize}=this,numItems4=this.numItems*4,nodeSize4=nodeSize*4,results=[],maxDistSquared=maxDistance*maxDistance,trackNearest=maxResults===1,bound=maxDistSquared;for(q5.push(boxes.length-4<<1,0);q5.length;){let top=q5.ids[0];if(top&1){if(q5.pop(),results.push(top>>1),results.length===maxResults)break;continue}q5.pop();let nodeIndex=top>>1,isLeafLevel=nodeIndex<numItems4,end=Math.min(nodeIndex+nodeSize4,upperBound(nodeIndex,levelBounds));for(let pos=nodeIndex;pos<end;pos+=4){let minX=boxes[pos],minY=boxes[pos+1],maxX=boxes[pos+2],maxY=boxes[pos+3],dx3=Math.max(Math.max(minX-x6,x6-maxX),0),dy3=Math.max(Math.max(minY-y2,y2-maxY),0),dist=dx3*dx3+dy3*dy3;if(dist>bound)continue;let childIndex=indices[pos>>2]|0;isLeafLevel?(filterFn===void 0||filterFn(childIndex))&&(q5.push(childIndex<<1|1,dist),trackNearest&&dist<bound&&(bound=dist)):q5.push(childIndex<<1,dist)}}return q5.clear(),results}};function upperBound(value,arr){let i6=0,j6=arr.length-1;for(;i6<j6;){let m6=i6+j6>>1;arr[m6]>value?j6=m6:i6=m6+1}return arr[i6]}function sort(values,boxes,indices,left,right,nodeSize){let stack=[left,right];for(;stack.length;){let r6=stack.pop()||0,l6=stack.pop()||0;if(r6-l6<=nodeSize&&Math.floor(l6/nodeSize)>=Math.floor(r6/nodeSize))continue;let a6=values[l6],b6=values[l6+r6>>1],c3=values[r6],pivot=a6>b6!=a6>c3?a6:b6<a6!=b6<c3?b6:c3,i6=l6-1,j6=r6+1;for(;;){do i6++;while(values[i6]<pivot);do j6--;while(values[j6]>pivot);if(i6>=j6)break;swap(values,boxes,indices,i6,j6)}stack.push(l6,j6,j6+1,r6)}}function swap(values,boxes,indices,i6,j6){let temp=values[i6];values[i6]=values[j6],values[j6]=temp;let k7=4*i6,m6=4*j6,a6=boxes[k7],b6=boxes[k7+1],c3=boxes[k7+2],d3=boxes[k7+3];boxes[k7]=boxes[m6],boxes[k7+1]=boxes[m6+1],boxes[k7+2]=boxes[m6+2],boxes[k7+3]=boxes[m6+3],boxes[m6]=a6,boxes[m6+1]=b6,boxes[m6+2]=c3,boxes[m6+3]=d3;let e6=indices[i6];indices[i6]=indices[j6],indices[j6]=e6}function hilbert(x6,y2){let a6=x6^y2,b6=65535^a6,c3=65535^(x6|y2),d3=x6&(y2^65535),A4=a6|b6>>1,B4=a6>>1^a6,C4=c3^(c3>>1^b6&d3>>1),D5=d3^(a6&c3>>1^d3>>1);return a6=A4&A4>>2^B4&B4>>2,b6=A4&B4>>2^B4&(A4^B4)>>2,c3=C4^(A4&C4>>2^B4&D5>>2),d3=D5^(B4&C4>>2^(A4^B4)&D5>>2),A4=a6&a6>>4^b6&b6>>4,B4=a6&b6>>4^b6&(a6^b6)>>4,C4=c3^(a6&c3>>4^b6&d3>>4),D5=d3^(b6&c3>>4^(a6^b6)&d3>>4),c3=C4^(A4&C4>>8^B4&D5>>8),d3=D5^(B4&C4>>8^(A4^B4)&D5>>8),c3^=c3>>1,d3^=d3>>1,a6=x6^y2,b6=d3|65535^(a6|c3),a6=(a6|a6<<8)&16711935,a6=(a6|a6<<4)&252645135,a6=(a6|a6<<2)&858993459,a6=(a6|a6<<1)&1431655765,b6=(b6|b6<<8)&16711935,b6=(b6|b6<<4)&252645135,b6=(b6|b6<<2)&858993459,b6=(b6|b6<<1)&1431655765,((b6<<1|a6)>>>0)-2147483648}var BaseSolver5=class{constructor(){__publicField(this,"MAX_ITERATIONS",1e5);__publicField(this,"solved",!1);__publicField(this,"failed",!1);__publicField(this,"iterations",0);__publicField(this,"progress",0);__publicField(this,"error",null);__publicField(this,"activeSubSolver");__publicField(this,"failedSubSolvers");__publicField(this,"timeToSolve");__publicField(this,"stats",{})}step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(e6){throw this.error=`${this.constructor.name} error: ${e6}`,this.failed=!0,e6}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){let startTime=Date.now();for(;!this.solved&&!this.failed;)this.step();let endTime=Date.now();this.timeToSolve=endTime-startTime}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}},getColorFromString2=(string,alpha=1)=>`hsl(${string.split("").reduce((acc,char)=>acc*31+char.charCodeAt(0),0)%360}, 100%, 50%, ${alpha})`,getSectionNameForPin=(sectionByChipId,sectionByPinId,pin)=>{if(pin.chipId){let chipSection=sectionByChipId.get(pin.chipId);if(chipSection)return chipSection}return sectionByPinId.get(pin.pinId)},arePinsInDifferentSchematicSections=(inputProblem,p12,p22)=>{let sectionByChipId=new Map,sectionByPinId=new Map;for(let chip of inputProblem.chips)if(chip.sectionId){sectionByChipId.set(chip.chipId,chip.sectionId);for(let pin of chip.pins)sectionByPinId.set(pin.pinId,chip.sectionId)}if(sectionByChipId.size===0)return!1;let s12=getSectionNameForPin(sectionByChipId,sectionByPinId,p12),s22=getSectionNameForPin(sectionByChipId,sectionByPinId,p22);return s12!==s22},getPinDirection=(pin,chip)=>{let{x:x6,y:y2}=pin,{center:center2,width,height}=chip,yPlusEdge=center2.y+height/2,yMinusEdge=center2.y-height/2,xPlusEdge=center2.x+width/2,xMinusEdge=center2.x-width/2,yPlusDistance=yPlusEdge-y2,yMinusDistance=y2-yMinusEdge,xPlusDistance=xPlusEdge-x6,xMinusDistance=x6-xMinusEdge,minDistance=Math.min(yPlusDistance,yMinusDistance,xPlusDistance,xMinusDistance);return minDistance===yPlusDistance?"y+":minDistance===yMinusDistance?"y-":minDistance===xPlusDistance?"x+":"x-"},visualizeInputProblem2=(inputProblem,opts={})=>{let{connectionAlpha=.8,chipAlpha=.8,hideRatsNet=inputProblem._hideRatsNet??!1}=opts,graphics={lines:[],points:[],rects:[]},pinIdMap=new Map;for(let chip of inputProblem.chips)for(let pin of chip.pins)pinIdMap.set(pin.pinId,pin);for(let chip of inputProblem.chips){graphics.rects.push({label:chip.chipId,center:chip.center,width:chip.width,height:chip.height,fill:getColorFromString2(chip.chipId,chipAlpha)});for(let pin of chip.pins)graphics.points.push({label:`${pin.displayName??pin.pinId}
644
- ${pin._facingDirection??getPinDirection(pin,chip)}`,x:pin.x,y:pin.y,color:getColorFromString2(pin.pinId,.8)})}for(let textBox of inputProblem.textBoxes??[])graphics.rects.push({label:textBox.text??"schematic_text",center:textBox.center,width:textBox.width,height:textBox.height,fill:"rgba(160, 0, 220, 0.14)",strokeColor:"rgba(160, 0, 220, 0.9)"});if(!hideRatsNet){for(let directConn of inputProblem.directConnections){let[pinId1,pinId2]=directConn.pinIds,pin1=pinIdMap.get(pinId1),pin2=pinIdMap.get(pinId2);arePinsInDifferentSchematicSections(inputProblem,pin1,pin2)||graphics.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:getColorFromString2(directConn.netId??`${pinId1}-${pinId2}`,connectionAlpha)})}for(let netConn of inputProblem.netConnections){let pins=netConn.pinIds.map(pinId=>pinIdMap.get(pinId));for(let i6=0;i6<pins.length-1;i6++)for(let j6=i6+1;j6<pins.length;j6++){let pin1=pins[i6],pin2=pins[j6];arePinsInDifferentSchematicSections(inputProblem,pin1,pin2)||graphics.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:getColorFromString2(netConn.netId,connectionAlpha),strokeDash:"4 2"})}}}return graphics},getRestrictedCenterLines=params=>{let{pins,inputProblem,pinIdMap,chipMap}=params,findAllDirectlyConnectedPins=startPinId=>{let visited=new Set,queue=[startPinId];visited.add(startPinId);let directConns=inputProblem.directConnections||[];for(;queue.length;){let cur=queue.shift();for(let dc2 of directConns)if(dc2.pinIds.includes(cur))for(let p3 of dc2.pinIds)visited.has(p3)||(visited.add(p3),queue.push(p3))}return visited},p03=pins[0].pinId,p12=pins[1].pinId,relatedPinIds=new Set([...findAllDirectlyConnectedPins(p03),...findAllDirectlyConnectedPins(p12)]),restrictedCenterLines=new Map,chipFacingMap=new Map,chipsOfFacingPins=new Set(pins.map(p3=>p3.chipId));for(let pinId of relatedPinIds){let pin=pinIdMap.get(pinId);if(!pin)continue;let chip=chipMap[pin.chipId];if(!chip)continue;let facing=pin._facingDirection??getPinDirection(pin,chip),entry=chipFacingMap.get(chip.chipId);if(!entry){entry={center:chip.center};let counts={xPos:0,xNeg:0,yPos:0,yNeg:0};for(let cp3 of chip.pins){let cpFacing=cp3._facingDirection??getPinDirection(cp3,chip);cpFacing==="x+"&&counts.xPos++,cpFacing==="x-"&&counts.xNeg++,cpFacing==="y+"&&counts.yPos++,cpFacing==="y-"&&counts.yNeg++}entry.counts=counts,chipFacingMap.set(chip.chipId,entry)}facing==="x+"&&(entry.hasXPos=!0),facing==="x-"&&(entry.hasXNeg=!0),facing==="y+"&&(entry.hasYPos=!0),facing==="y-"&&(entry.hasYNeg=!0)}for(let[chipId,faces]of chipFacingMap){let axes=new Set,rcl={axes},counts=faces.counts;!(counts&&(counts.xPos>1||counts.xNeg>1||counts.yPos>1||counts.yNeg>1))&&chipsOfFacingPins.has(chipId)||(faces.hasXPos&&faces.hasXNeg&&(rcl.x=faces.center.x,axes.add("x")),faces.hasYPos&&faces.hasYNeg&&(rcl.y=faces.center.y,axes.add("y"))),axes.size>0&&restrictedCenterLines.set(chipId,rcl)}return restrictedCenterLines},doesPairCrossRestrictedCenterLines=params=>{let{inputProblem,chipMap,pinIdMap,p1:p12,p2:p22}=params,restrictedCenterLines=getRestrictedCenterLines({pins:[p12,p22],inputProblem,pinIdMap,chipMap});if(restrictedCenterLines.size===0)return!1;let EPS142=1e-9,crossesSegment=(a6,b6)=>{for(let[,rcl]of restrictedCenterLines)if(rcl.axes.has("x")&&typeof rcl.x=="number"&&(a6.x-rcl.x)*(b6.x-rcl.x)<-EPS142||rcl.axes.has("y")&&typeof rcl.y=="number"&&(a6.y-rcl.y)*(b6.y-rcl.y)<-EPS142)return!0;return!1};if(Math.abs(p12.x-p22.x)<EPS142||Math.abs(p12.y-p22.y)<EPS142)return crossesSegment({x:p12.x,y:p12.y},{x:p22.x,y:p22.y});let elbowHV={x:p22.x,y:p12.y},elbowVH={x:p12.x,y:p22.y},hvCrosses=crossesSegment({x:p12.x,y:p12.y},elbowHV)||crossesSegment(elbowHV,{x:p22.x,y:p22.y}),vhCrosses=crossesSegment({x:p12.x,y:p12.y},elbowVH)||crossesSegment(elbowVH,{x:p22.x,y:p22.y});return hvCrosses&&vhCrosses},getConnectivityMapsFromInputProblem=inputProblem=>{let directConnMap=new ConnectivityMap2({});for(let directConn of inputProblem.directConnections)directConnMap.addConnections([directConn.netId?[directConn.netId,...directConn.pinIds]:directConn.pinIds]);let netConnMap=new ConnectivityMap2(directConnMap.netMap);for(let netConn of inputProblem.netConnections)netConnMap.addConnections([[netConn.netId,...netConn.pinIds]]);return{directConnMap,netConnMap}};function getOrthogonalMinimumSpanningTree(pins,opts={}){let n3=pins.length,maxDistance=opts?.maxDistance??Number.POSITIVE_INFINITY;if(n3<=1)return[];{let seen=new Set;for(let p3 of pins){if(seen.has(p3.pinId))throw new Error(`Duplicate pinId detected: "${p3.pinId}"`);seen.add(p3.pinId)}}let manhattan=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),inTree=new Array(n3).fill(!1),bestDist=new Array(n3).fill(Number.POSITIVE_INFINITY),parent=new Array(n3).fill(-1),startIndex=0;for(let i6=1;i6<n3;i6++)pins[i6].pinId<pins[startIndex].pinId&&(startIndex=i6);bestDist[startIndex]=0;let edges=[];for(let iter=0;iter<n3;iter++){let u6=-1,best=Number.POSITIVE_INFINITY,bestId="";for(let i6=0;i6<n3;i6++)if(!inTree[i6]){let d3=bestDist[i6];(d3<best||d3===best&&(bestId===""||pins[i6].pinId<bestId))&&(best=d3,bestId=pins[i6].pinId,u6=i6)}inTree[u6]=!0,parent[u6]!==-1&&edges.push([pins[u6].pinId,pins[parent[u6]].pinId]);for(let v6=0;v6<n3;v6++)if(!inTree[v6]){let d03=manhattan(pins[u6],pins[v6]),isForbidden=opts?.forbidEdge?.(pins[u6],pins[v6])??!1,d3=d03>maxDistance||isForbidden?Number.POSITIVE_INFINITY:d03;(d3<bestDist[v6]||d3===bestDist[v6]&&pins[u6].pinId<pins[parent[v6]]?.pinId)&&(bestDist[v6]=d3,parent[v6]=u6)}}return edges}var NET_LABEL_HORIZONTAL_WIDTH=.45,NET_LABEL_HORIZONTAL_HEIGHT=.2;function getDimsForOrientation(params){let{orientation:orientation4,netLabelWidth,netLabelHeight}=params,horizWidth=typeof netLabelWidth=="number"?netLabelWidth:NET_LABEL_HORIZONTAL_WIDTH,horizHeight=typeof netLabelHeight=="number"?netLabelHeight:NET_LABEL_HORIZONTAL_HEIGHT;return orientation4==="y+"||orientation4==="y-"?{width:horizHeight,height:horizWidth}:{width:horizWidth,height:horizHeight}}function getCenterFromAnchor(anchor,orientation4,width,height){switch(orientation4){case"x+":return{x:anchor.x+width/2,y:anchor.y};case"x-":return{x:anchor.x-width/2,y:anchor.y};case"y+":return{x:anchor.x,y:anchor.y+height/2};case"y-":return{x:anchor.x,y:anchor.y-height/2}}}function getRectBounds(center2,w4,h3){return{minX:center2.x-w4/2,minY:center2.y-h3/2,maxX:center2.x+w4/2,maxY:center2.y+h3/2}}var getLabeledConnectionRouteReason=({inputProblem,chipMap,pins})=>{let[firstPin,secondPin]=pins,directConnection=inputProblem.directConnections.find(connection=>connection.pinIds.includes(firstPin.pinId)&&connection.pinIds.includes(secondPin.pinId));if(directConnection?.netLabelWidth===void 0)return null;let firstChip=chipMap[firstPin.chipId],secondChip=chipMap[secondPin.chipId];if(!firstChip||!secondChip)return null;let firstFacingDirection=firstPin._facingDirection;firstFacingDirection||(firstFacingDirection=getPinDirection(firstPin,firstChip));let secondFacingDirection=secondPin._facingDirection;if(secondFacingDirection||(secondFacingDirection=getPinDirection(secondPin,secondChip)),!(firstFacingDirection==="x-"&&secondFacingDirection==="x+"||firstFacingDirection==="x+"&&secondFacingDirection==="x-"))return null;if(firstChip.pins.length===1||secondChip.pins.length===1)return"single-pin-peripheral";if(!(firstChip.sectionId&&firstChip.sectionId===secondChip.sectionId?firstChip.sectionId:null))return null;let directionsPointTowardEachOther=firstPin.x<=secondPin.x?firstFacingDirection==="x+"&&secondFacingDirection==="x-":firstFacingDirection==="x-"&&secondFacingDirection==="x+",labelsOverlapAlongX=Math.abs(firstPin.x-secondPin.x)<directConnection.netLabelWidth*2,labelsOverlapAlongY=Math.abs(firstPin.y-secondPin.y)<NET_LABEL_HORIZONTAL_HEIGHT;return directionsPointTowardEachOther&&labelsOverlapAlongX&&labelsOverlapAlongY?"overlapping-fallback-labels":null},isLabeledPeripheralConnection=params=>getLabeledConnectionRouteReason(params)!==null,DEFAULT_MAX_MSP_PAIR_DISTANCE=1,getPinPairKey=pinIds=>[...pinIds].sort().join("::"),MspConnectionPairSolver=class extends BaseSolver5{constructor({inputProblem}){super();__publicField(this,"inputProblem");__publicField(this,"mspConnectionPairs",[]);__publicField(this,"dcConnMap");__publicField(this,"globalConnMap");__publicField(this,"queuedDcNetIds");__publicField(this,"chipMap");__publicField(this,"maxMspPairDistance");__publicField(this,"pinMap");__publicField(this,"userNetIdByPinId");__publicField(this,"directConnectionPinPairKeys");this.inputProblem=inputProblem,this.maxMspPairDistance=inputProblem.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE;let{directConnMap,netConnMap}=getConnectivityMapsFromInputProblem(inputProblem);this.dcConnMap=directConnMap,this.globalConnMap=netConnMap,this.pinMap={};for(let chip of inputProblem.chips)for(let pin of chip.pins)this.pinMap[pin.pinId]={...pin,chipId:chip.chipId};this.chipMap={};for(let chip of inputProblem.chips)this.chipMap[chip.chipId]=chip;this.userNetIdByPinId={},this.directConnectionPinPairKeys=new Set;for(let dc2 of inputProblem.directConnections)if(this.directConnectionPinPairKeys.add(getPinPairKey(dc2.pinIds)),dc2.netId){let[a6,b6]=dc2.pinIds;this.userNetIdByPinId[a6]=dc2.netId,this.userNetIdByPinId[b6]=dc2.netId}for(let nc3 of inputProblem.netConnections)for(let pid of nc3.pinIds)this.userNetIdByPinId[pid]=nc3.netId;this.queuedDcNetIds=Object.keys(netConnMap.netMap)}getConstructorParams(){return{inputProblem:this.inputProblem}}_step(){if(this.queuedDcNetIds.length===0){this.solved=!0;return}let dcNetId=this.queuedDcNetIds.shift(),directlyConnectedPins=this.globalConnMap.getIdsConnectedToNet(dcNetId).filter(id3=>!!this.pinMap[id3]);if(directlyConnectedPins.length<=1)return;if(directlyConnectedPins.length===2){let[pin1,pin2]=directlyConnectedPins,p12=this.pinMap[pin1],p22=this.pinMap[pin2],pinPairKey=getPinPairKey([pin1,pin2]),pairDistance=Math.abs(p12.x-p22.x)+Math.abs(p12.y-p22.y);this.directConnectionPinPairKeys.has(pinPairKey)&&(pairDistance=distance2(p12,p22));let labeledConnectionRouteReason=getLabeledConnectionRouteReason({inputProblem:this.inputProblem,chipMap:this.chipMap,pins:[p12,p22]});if(pairDistance>this.maxMspPairDistance&&!labeledConnectionRouteReason||arePinsInDifferentSchematicSections(this.inputProblem,p12,p22))return;let pinIdMap2=new Map(Object.entries(this.pinMap));if(doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap:pinIdMap2,p1:p12,p2:p22}))return;let globalConnNetId=this.globalConnMap.getNetConnectedToId(pin1),userNetId=this.userNetIdByPinId[pin1]??this.userNetIdByPinId[pin2],suppressNetLabel=pairDistance>this.maxMspPairDistance&&labeledConnectionRouteReason==="overlapping-fallback-labels";this.mspConnectionPairs.push({mspPairId:`${pin1}-${pin2}`,dcConnNetId:dcNetId,globalConnNetId,userNetId,suppressNetLabel,pins:[p12,p22]});return}let pinIdMap=new Map(Object.entries(this.pinMap)),msp=getOrthogonalMinimumSpanningTree(directlyConnectedPins.map(p3=>this.pinMap[p3]).filter(Boolean),{maxDistance:this.maxMspPairDistance,forbidEdge:(a6,b6)=>arePinsInDifferentSchematicSections(this.inputProblem,a6,b6)||doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap,p1:a6,p2:b6})});for(let[pin1,pin2]of msp){let p1Obj=this.pinMap[pin1],p2Obj=this.pinMap[pin2];if(arePinsInDifferentSchematicSections(this.inputProblem,p1Obj,p2Obj)||doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap,p1:p1Obj,p2:p2Obj}))continue;let globalConnNetId=this.globalConnMap.getNetConnectedToId(pin1),userNetId=this.userNetIdByPinId[pin1]??this.userNetIdByPinId[pin2];this.mspConnectionPairs.push({mspPairId:`${pin1}-${pin2}`,dcConnNetId:dcNetId,globalConnNetId,userNetId,pins:[p1Obj,p2Obj]})}}visualize(){let graphics=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});for(let pair of this.mspConnectionPairs)graphics.lines.push({points:[{x:pair.pins[0].x,y:pair.pins[0].y},{x:pair.pins[1].x,y:pair.pins[1].y}],strokeColor:getColorFromString2(pair.mspPairId,.75)});return graphics}},getConfiguredWidth=(connections,isPortOnlyLabel2)=>{let width=connections.find(connection=>connection?.netLabelWidth!==void 0)?.netLabelWidth;return width!==void 0||!isPortOnlyLabel2?width:connections.find(connection=>connection?.anchoredNetLabelWidth!==void 0)?.anchoredNetLabelWidth},getNetLabelWidthForConnection=({inputProblem,netId,pinIds,isPortOnlyLabel:isPortOnlyLabel2})=>{if(netId){let widthByNetId=getConfiguredWidth([inputProblem.netConnections.find(connection=>connection.netId===netId),inputProblem.directConnections.find(connection=>connection.netId===netId)],isPortOnlyLabel2);if(widthByNetId!==void 0)return widthByNetId}return getConfiguredWidth([inputProblem.directConnections.find(connection=>connection.pinIds.some(pinId=>pinIds.includes(pinId))),inputProblem.netConnections.find(connection=>connection.pinIds.some(pinId=>pinIds.includes(pinId)))],isPortOnlyLabel2)};function getTextBoxBounds(textBox,padding={}){return{minX:textBox.center.x-textBox.width/2-(padding.minX??0),minY:textBox.center.y-textBox.height/2-(padding.minY??0),maxX:textBox.center.x+textBox.width/2+(padding.maxX??0),maxY:textBox.center.y+textBox.height/2+(padding.maxY??0)}}function boundsOverlap(a6,b6,eps=1e-9){return a6.minX<b6.maxX-eps&&a6.maxX>b6.minX+eps&&a6.minY<b6.maxY-eps&&a6.maxY>b6.minY+eps}function rectIntersectsAnyTextBox(bounds,inputProblem){for(let textBox of inputProblem.textBoxes??[])if(boundsOverlap(bounds,getTextBoxBounds(textBox)))return!0;return!1}var MAX_SHORT_TRACE_DISTANCE=.15,SHORT_TRACE_OVERSHOOT=MAX_SHORT_TRACE_DISTANCE/7.5,FALLBACK_ELBOW_MAX_OVERSHOOT=.2;function segmentDirection(from,to3){return to3.x>from.x?"x+":to3.x<from.x?"x-":to3.y>from.y?"y+":to3.y<from.y?"y-":null}function pathMatchesPinDirections({path,pin1,pin2}){let firstDirection=segmentDirection(path[0],path[1]),lastDirection=segmentDirection(path[path.length-1],path[path.length-2]);return firstDirection===pin1._facingDirection&&lastDirection===pin2._facingDirection}function calculateShortOrthogonalRoute(pin1,pin2){if(pin1.x===pin2.x||pin1.y===pin2.y)return null;let firstDir=pin1._facingDirection,lastDir=pin2._facingDirection,start={x:pin1.x,y:pin1.y},end={x:pin2.x,y:pin2.y},path=null;if(firstDir?.startsWith("y")&&lastDir?.startsWith("x")){let yOffset=-SHORT_TRACE_OVERSHOOT;firstDir==="y+"&&(yOffset=SHORT_TRACE_OVERSHOOT);let routeY=start.y+yOffset,routeX=(start.x+end.x)/2;path=[start,{x:start.x,y:routeY},{x:routeX,y:routeY},{x:routeX,y:end.y},end]}else if(firstDir?.startsWith("x")&&lastDir?.startsWith("y")){let xOffset=-SHORT_TRACE_OVERSHOOT;firstDir==="x+"&&(xOffset=SHORT_TRACE_OVERSHOOT);let routeX=start.x+xOffset,routeY=(start.y+end.y)/2;path=[start,{x:routeX,y:start.y},{x:routeX,y:routeY},{x:end.x,y:routeY},end]}return path&&pathMatchesPinDirections({path,pin1,pin2})?path:null}function calculateDirectShortPath(pin1,pin2){let routingDistance=Math.abs(pin1.x-pin2.x)+Math.abs(pin1.y-pin2.y);if(routingDistance>MAX_SHORT_TRACE_DISTANCE)return null;let start={x:pin1.x,y:pin1.y},end={x:pin2.x,y:pin2.y},orthogonalRoute=calculateShortOrthogonalRoute(pin1,pin2);if(orthogonalRoute)return orthogonalRoute;let candidatePaths=[];pin1.x!==pin2.x&&pin1.y!==pin2.y?candidatePaths=[[start,{x:pin2.x,y:pin1.y},end],[start,{x:pin1.x,y:pin2.y},end]]:candidatePaths=[[start,end]];for(let path of candidatePaths)if(pathMatchesPinDirections({path,pin1,pin2}))return path;return calculateElbow({x:pin1.x,y:pin1.y,facingDirection:pin1._facingDirection},{x:pin2.x,y:pin2.y,facingDirection:pin2._facingDirection},{overshoot:Math.min(FALLBACK_ELBOW_MAX_OVERSHOOT,Math.max(SHORT_TRACE_OVERSHOOT,routingDistance/4))})}var EPS=1e-9,isVertical=(a6,b6,eps=EPS)=>Math.abs(a6.x-b6.x)<eps,isHorizontal=(a6,b6,eps=EPS)=>Math.abs(a6.y-b6.y)<eps,segmentIntersectsRect=(a6,b6,r6,eps=EPS)=>{let vert=isVertical(a6,b6,eps),horz=isHorizontal(a6,b6,eps);if(!vert&&!horz)return!1;if(vert){let x6=a6.x;if(x6<r6.minX-eps||x6>r6.maxX+eps)return!1;let segMinY=Math.min(a6.y,b6.y),segMaxY=Math.max(a6.y,b6.y);return Math.min(segMaxY,r6.maxY)-Math.max(segMinY,r6.minY)>eps}else{let y2=a6.y;if(y2<r6.minY-eps||y2>r6.maxY+eps)return!1;let segMinX=Math.min(a6.x,b6.x),segMaxX=Math.max(a6.x,b6.x);return Math.min(segMaxX,r6.maxX)-Math.max(segMinX,r6.minX)>eps}},segmentOverlapsRectBoundary=(a6,b6,r6,eps=EPS)=>isVertical(a6,b6,eps)?Math.abs(a6.x-r6.minX)<=eps||Math.abs(a6.x-r6.maxX)<=eps?Math.min(Math.max(a6.y,b6.y),r6.maxY)-Math.max(Math.min(a6.y,b6.y),r6.minY)>eps:!1:isHorizontal(a6,b6,eps)&&(Math.abs(a6.y-r6.minY)<=eps||Math.abs(a6.y-r6.maxY)<=eps)?Math.min(Math.max(a6.x,b6.x),r6.maxX)-Math.max(Math.min(a6.x,b6.x),r6.minX)>eps:!1,findFirstCollision=(pts,rects,opts={})=>{for(let i6=0;i6<pts.length-1;i6++){let a6=pts[i6],b6=pts[i6+1],excluded=opts.excludeRectsForSegment?.(i6)??new Set;for(let r6 of rects)if(!excluded.has(r6)&&segmentIntersectsRect(a6,b6,r6))return{segIndex:i6,rect:r6}}return null},isPathCollidingWithObstacles=(path,obstacles)=>{for(let i6=0;i6<path.length-1;i6++)for(let obstacle of obstacles)if(segmentIntersectsRect(path[i6],path[i6+1],obstacle))return!0;return!1},EPS2=1e-9,OBSTACLE_CLEARANCE=.2,aabbFromPoints=(a6,b6)=>({minX:Math.min(a6.x,b6.x),maxX:Math.max(a6.x,b6.x),minY:Math.min(a6.y,b6.y),maxY:Math.max(a6.y,b6.y)}),midBetweenPointAndRect=(axis,p3,r6,eps=EPS2)=>axis==="x"?p3.x<r6.minX-eps?[(p3.x+r6.minX)/2]:p3.x>r6.maxX+eps?[(p3.x+r6.maxX)/2]:[r6.minX-OBSTACLE_CLEARANCE,r6.maxX+OBSTACLE_CLEARANCE]:p3.y<r6.minY-eps?[(p3.y+r6.minY)/2]:p3.y>r6.maxY+eps?[(p3.y+r6.maxY)/2]:[r6.minY-OBSTACLE_CLEARANCE,r6.maxY+OBSTACLE_CLEARANCE],candidateMidsFromSet=(axis,colliding,collisionRects,aabb,opts={})=>{let{allowOpenSideCandidates=!1,eps=EPS2}=opts,setRects=[...collisionRects];if(axis==="x"){let leftBoundaries=[aabb.minX,...setRects.map(r6=>r6.maxX)].filter(v6=>v6<colliding.minX-eps),rightBoundaries=[aabb.maxX,...setRects.map(r6=>r6.minX)].filter(v6=>v6>colliding.maxX+eps),leftNeighbor=leftBoundaries.length>0?Math.max(...leftBoundaries):void 0,rightNeighbor=rightBoundaries.length>0?Math.min(...rightBoundaries):void 0,out=[];return leftNeighbor!==void 0?out.push((leftNeighbor+colliding.minX)/2):allowOpenSideCandidates&&out.push(colliding.minX-OBSTACLE_CLEARANCE),rightNeighbor!==void 0?out.push((colliding.maxX+rightNeighbor)/2):allowOpenSideCandidates&&out.push(colliding.maxX+OBSTACLE_CLEARANCE),out}else{let bottomBoundaries=[aabb.minY,...setRects.map(r6=>r6.maxY)].filter(v6=>v6<colliding.minY-eps),topBoundaries=[aabb.maxY,...setRects.map(r6=>r6.minY)].filter(v6=>v6>colliding.maxY+eps),bottomNeighbor=bottomBoundaries.length>0?Math.max(...bottomBoundaries):void 0,topNeighbor=topBoundaries.length>0?Math.min(...topBoundaries):void 0,out=[];return bottomNeighbor!==void 0?out.push((bottomNeighbor+colliding.minY)/2):allowOpenSideCandidates&&out.push(colliding.minY-OBSTACLE_CLEARANCE),topNeighbor!==void 0?out.push((colliding.maxY+topNeighbor)/2):allowOpenSideCandidates&&out.push(colliding.maxY+OBSTACLE_CLEARANCE),out}},EPS3=1e-9,hasOnlyNonzeroOrthogonalSegments=path=>path.every((point6,index)=>{let nextPoint=path[index+1];return nextPoint?!isHorizontal(point6,nextPoint)&&!isVertical(point6,nextPoint)?!1:Math.abs(point6.x-nextPoint.x)+Math.abs(point6.y-nextPoint.y)>0:!0}),shiftSegmentOrth=(pts,segIndex,axis,newCoord,eps=EPS3)=>{if(segIndex<0||segIndex>=pts.length-1)return null;let a6=pts[segIndex],b6=pts[segIndex+1],vert=isVertical(a6,b6,eps),horz=isHorizontal(a6,b6,eps);if(!vert&&!horz||vert&&axis!=="x"||horz&&axis!=="y")return null;let out=pts.map(p3=>({...p3}));if(axis==="x"){if(Math.abs(a6.x-newCoord)<eps&&Math.abs(b6.x-newCoord)<eps)return null;out[segIndex]={...out[segIndex],x:newCoord},out[segIndex+1]={...out[segIndex+1],x:newCoord}}else{if(Math.abs(a6.y-newCoord)<eps&&Math.abs(b6.y-newCoord)<eps)return null;out[segIndex]={...out[segIndex],y:newCoord},out[segIndex+1]={...out[segIndex+1],y:newCoord}}if(segIndex-1>=0){let p3=out[segIndex-1],q5=out[segIndex];if(Math.abs(p3.x-q5.x)+Math.abs(p3.y-q5.y)<eps)return null}if(segIndex+2<=out.length-1){let p3=out[segIndex+1],q5=out[segIndex+2];if(Math.abs(p3.x-q5.x)+Math.abs(p3.y-q5.y)<eps)return null}for(let i6=0;i6<out.length-1;i6++){let u6=out[i6],v6=out[i6+1];if(!isHorizontal(u6,v6,eps)&&!isVertical(u6,v6,eps))return null}return out},pathKey=(pts,decimals=6)=>pts.map(p3=>`${p3.x.toFixed(decimals)},${p3.y.toFixed(decimals)}`).join("|"),getSegmentAxis=(start,end)=>isVertical(start,end)?"x":isHorizontal(start,end)?"y":null,generateEndpointCollisionDetours=({path,collidingSegmentIndex,obstacle})=>{if(path.length<3||path.length>4)return[];let lastSegmentIndex=path.length-2;if(collidingSegmentIndex!==0&&collidingSegmentIndex!==lastSegmentIndex)return[];let shouldReverse=collidingSegmentIndex===lastSegmentIndex,orderedPath=shouldReverse?[...path].reverse():path,[start,corner,end]=orderedPath,firstSegmentAxis=getSegmentAxis(start,corner),secondSegmentAxis=getSegmentAxis(corner,end);if(!firstSegmentAxis||!secondSegmentAxis)return[];if(firstSegmentAxis===secondSegmentAxis)return[];let escapeCoordinates=[...midBetweenPointAndRect(secondSegmentAxis,start,obstacle),...midBetweenPointAndRect(secondSegmentAxis,end,obstacle)],detourCoordinates=[...midBetweenPointAndRect(firstSegmentAxis,start,obstacle),...midBetweenPointAndRect(firstSegmentAxis,end,obstacle)],detours=[];for(let escapeCoordinate of[...new Set(escapeCoordinates)])for(let detourCoordinate of[...new Set(detourCoordinates)]){let orderedDetour=[...firstSegmentAxis==="y"?[start,{x:escapeCoordinate,y:start.y},{x:escapeCoordinate,y:detourCoordinate},{x:end.x,y:detourCoordinate},end]:[start,{x:start.x,y:escapeCoordinate},{x:detourCoordinate,y:escapeCoordinate},{x:detourCoordinate,y:end.y},end],...orderedPath.slice(3)],detour=shouldReverse?orderedDetour.reverse():orderedDetour;hasOnlyNonzeroOrthogonalSegments(detour)&&detours.push(detour)}return detours},EPS4=1e-9,DEFAULT_CLEARANCE=.2,isStrictlyBetween=(value,a6,b6)=>value>Math.min(a6,b6)+EPS4&&value<Math.max(a6,b6)-EPS4,generateInternalSegmentCollisionDetours=({path,collidingSegmentIndex,obstacle,clearance=DEFAULT_CLEARANCE})=>{if(collidingSegmentIndex<=0||collidingSegmentIndex>=path.length-2)return[];let start=path[collidingSegmentIndex],end=path[collidingSegmentIndex+1],detourPoints=[];if(isHorizontal(start,end)){let movingRight=start.x<end.x,entryX=movingRight?obstacle.minX-clearance:obstacle.maxX+clearance,exitX=movingRight?obstacle.maxX+clearance:obstacle.minX-clearance;if(!isStrictlyBetween(entryX,start.x,end.x)||!isStrictlyBetween(exitX,start.x,end.x))return[];for(let detourY of[obstacle.minY-clearance,obstacle.maxY+clearance])detourPoints.push([{x:entryX,y:start.y},{x:entryX,y:detourY},{x:exitX,y:detourY},{x:exitX,y:end.y}])}else if(isVertical(start,end)){let movingUp=start.y<end.y,entryY=movingUp?obstacle.minY-clearance:obstacle.maxY+clearance,exitY=movingUp?obstacle.maxY+clearance:obstacle.minY-clearance;if(!isStrictlyBetween(entryY,start.y,end.y)||!isStrictlyBetween(exitY,start.y,end.y))return[];for(let detourX of[obstacle.minX-clearance,obstacle.maxX+clearance])detourPoints.push([{x:start.x,y:entryY},{x:detourX,y:entryY},{x:detourX,y:exitY},{x:end.x,y:exitY}])}return detourPoints.map(points=>[...path.slice(0,collidingSegmentIndex+1),...points,...path.slice(collidingSegmentIndex+1)]).filter(hasOnlyNonzeroOrthogonalSegments)};function getInputChipBounds(chip){let halfWidth=chip.width/2,halfHeight=chip.height/2;return{minX:chip.center.x-halfWidth,maxX:chip.center.x+halfWidth,minY:chip.center.y-halfHeight,maxY:chip.center.y+halfHeight}}var MIN_ROUTABLE_OBSTACLE_GAP=.05,isTextBoxObstacle=obstacle=>obstacle.kind==="text_box",chipToRect=chip=>{let b6=getInputChipBounds(chip);return{kind:"chip",chipId:chip.chipId,...b6}},getObstacleRects=(problem,opts={})=>{let chipRects=problem.chips.map(chipToRect),textBoxRects=(problem.textBoxes??[]).map(textBox=>{let textBounds=getTextBoxBounds(textBox,opts.textBoxPadding),attachedChipBounds=chipRects.find(chip=>chip.chipId===textBox.chipId),gap=attachedChipBounds?boundsDistance(textBounds,attachedChipBounds):Number.POSITIVE_INFINITY,b6=attachedChipBounds&&gap>0&&gap<MIN_ROUTABLE_OBSTACLE_GAP?{minX:Math.min(textBounds.minX,attachedChipBounds.maxX),maxX:Math.max(textBounds.maxX,attachedChipBounds.minX),minY:Math.min(textBounds.minY,attachedChipBounds.maxY),maxY:Math.max(textBounds.maxY,attachedChipBounds.minY)}:textBounds;return{kind:"text_box",textBox,...b6}});return[...chipRects,...textBoxRects]},calculateElbowForPins=({pin1,pin2,overshoot})=>calculateElbow({x:pin1.x,y:pin1.y,facingDirection:pin1._facingDirection},{x:pin2.x,y:pin2.y,facingDirection:pin2._facingDirection},{overshoot}),pinsFaceEachOther=({pin1,pin2})=>{let xDistance=pin2.x-pin1.x,yDistance=pin2.y-pin1.y;return Math.abs(xDistance)>=Math.abs(yDistance)?xDistance>0?pin1._facingDirection==="x+"&&pin2._facingDirection==="x-":pin1._facingDirection==="x-"&&pin2._facingDirection==="x+":yDistance>0?pin1._facingDirection==="y+"&&pin2._facingDirection==="y-":pin1._facingDirection==="y-"&&pin2._facingDirection==="y+"},SchematicTraceSingleLineSolver2=class extends BaseSolver5{constructor(params){super();__publicField(this,"pins");__publicField(this,"connectionPair");__publicField(this,"inputProblem");__publicField(this,"chipMap");__publicField(this,"obstacles");__publicField(this,"textObstacles");__publicField(this,"endpointTextObstacles");__publicField(this,"aabb");__publicField(this,"baseElbow");__publicField(this,"solvedTracePath",null);__publicField(this,"queue",[]);__publicField(this,"visited",new Set);this.pins=params.pins,this.connectionPair=params.connectionPair,this.inputProblem=params.inputProblem,this.chipMap=params.chipMap;for(let pin of this.pins)if(!pin._facingDirection){let chip=this.chipMap[pin.chipId];pin._facingDirection=getPinDirection(pin,chip)}this.obstacles=getObstacleRects(this.inputProblem,{textBoxPadding:this.getTextBoxPaddingForConnectionPair()}),this.textObstacles=new Set(this.obstacles.filter(isTextBoxObstacle));let endpointChipIds=new Set(this.pins.map(pin=>pin.chipId));this.endpointTextObstacles=new Set(this.obstacles.filter(isTextBoxObstacle).filter(obstacle=>obstacle.textBox.chipId!==void 0&&endpointChipIds.has(obstacle.textBox.chipId)));let[pin1,pin2]=this.pins,directShortPath=calculateDirectShortPath(pin1,pin2),defaultElbow=calculateElbowForPins({pin1,pin2,overshoot:.2}),routingDistance=Math.abs(pin1.x-pin2.x)+Math.abs(pin1.y-pin2.y),adaptiveElbow=calculateElbowForPins({pin1,pin2,overshoot:Math.min(.2,Math.max(.02,routingDistance/4))}),adaptiveElbowIsShorter=this.pathLength(adaptiveElbow)<this.pathLength(defaultElbow),defaultElbowBacktracks=this.pathLength(defaultElbow)>routingDistance+1e-9,shouldUseAdaptiveElbow=findFirstCollision(adaptiveElbow,this.obstacles)===null&&(pinsFaceEachOther({pin1,pin2})&&defaultElbowBacktracks&&adaptiveElbowIsShorter||findFirstCollision(defaultElbow,this.obstacles)!==null);this.baseElbow=defaultElbow,shouldUseAdaptiveElbow&&(this.baseElbow=adaptiveElbow),directShortPath&&(this.baseElbow=directShortPath),this.solvedTracePath=directShortPath,this.aabb=aabbFromPoints({x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}),this.queue.push({path:this.baseElbow,collisionRects:new Set}),this.visited.add(pathKey(this.baseElbow))}getConstructorParams(){return{chipMap:this.chipMap,pins:this.pins,connectionPair:this.connectionPair,inputProblem:this.inputProblem}}getTextBoxPaddingForConnectionPair(){if(!this.inputProblem.textBoxes?.length)return{};let netId=this.connectionPair?.userNetId;if(!netId)return{};let orientations=this.inputProblem.availableNetLabelOrientations[netId]??["x+","x-","y+","y-"],netLabelWidth=getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId,pinIds:this.pins.map(pin=>pin.pinId),isPortOnlyLabel:!1}),netLabelHeight=this.getNetLabelHeightForConnectionPair(netId),padding={minX:0,minY:0,maxX:0,maxY:0};for(let orientation4 of orientations){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth,netLabelHeight});orientation4==="y+"||orientation4==="y-"?(padding.minX=Math.max(padding.minX,width/2),padding.maxX=Math.max(padding.maxX,width/2),orientation4==="y+"?padding.minY=Math.max(padding.minY,height):padding.maxY=Math.max(padding.maxY,height)):(padding.minY=Math.max(padding.minY,height/2),padding.maxY=Math.max(padding.maxY,height/2),orientation4==="x+"?padding.minX=Math.max(padding.minX,width):padding.maxX=Math.max(padding.maxX,width))}return padding}getNetLabelHeightForConnectionPair(netId){let ncHeight=this.inputProblem.netConnections.find(nc3=>nc3.netId===netId)?.netLabelHeight;if(ncHeight!==void 0)return ncHeight;let pinIds=this.pins.map(p3=>p3.pinId);return this.inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>pinIds.includes(pid)))?.netLabelHeight}axisOfSegment(a6,b6){return isVertical(a6,b6)?"x":isHorizontal(a6,b6)?"y":null}pathLength(pts){let sum=0;for(let i6=0;i6<pts.length-1;i6++)sum+=Math.abs(pts[i6+1].x-pts[i6].x)+Math.abs(pts[i6+1].y-pts[i6].y);return sum}getPinBandPenalty(path){let penalty=0;for(let i6=1;i6<path.length-2;i6++){let a6=path[i6],b6=path[i6+1];(isHorizontal(a6,b6)&&a6.y>this.aabb.minY&&a6.y<this.aabb.maxY||isVertical(a6,b6)&&a6.x>this.aabb.minX&&a6.x<this.aabb.maxX)&&(penalty+=10)}return penalty}isSegmentOutsidePinBand(a6,b6){return isHorizontal(a6,b6)?a6.y<=this.aabb.minY||a6.y>=this.aabb.maxY:isVertical(a6,b6)?a6.x<=this.aabb.minX||a6.x>=this.aabb.maxX:!1}_step(){if(this.solvedTracePath){this.solved=!0;return}let state2=this.queue.shift();if(!state2){this.failed=!0,this.error="No collision-free path found";return}let{path,collisionRects}=state2,[PA3,PB2]=this.pins,collision=findFirstCollision(path,this.obstacles,{excludeRectsForSegment:segIndex2=>{let lastSegIndex2=path.length-2,excludedRects=new Set;if(segIndex2===0||segIndex2===lastSegIndex2)for(let textObstacle of this.textObstacles)excludedRects.add(textObstacle);let segmentStart=path[segIndex2],segmentEnd=path[segIndex2+1],endpointEpsilon=1e-9,segmentTouchesPin=pin=>[segmentStart,segmentEnd].some(point6=>Math.abs(point6.x-pin.x)<=endpointEpsilon&&Math.abs(point6.y-pin.y)<=endpointEpsilon);for(let pin of this.pins){if(!segmentTouchesPin(pin))continue;let endpointChipObstacle=this.obstacles.find(obstacle=>obstacle.kind==="chip"&&obstacle.chipId===pin.chipId);endpointChipObstacle&&segmentOverlapsRectBoundary(segmentStart,segmentEnd,endpointChipObstacle)&&excludedRects.add(endpointChipObstacle)}let adjacentEndpointSegIndex=segIndex2===1?2:segIndex2===lastSegIndex2-1?lastSegIndex2-2:null;if(adjacentEndpointSegIndex!==null&&adjacentEndpointSegIndex>=0&&adjacentEndpointSegIndex<lastSegIndex2&&this.isSegmentOutsidePinBand(path[adjacentEndpointSegIndex],path[adjacentEndpointSegIndex+1]))for(let textObstacle of this.endpointTextObstacles){let textBounds=getTextBoxBounds(textObstacle.textBox);segmentIntersectsRect(segmentStart,segmentEnd,textBounds)||excludedRects.add(textObstacle)}return excludedRects}});if(!collision){let first=path[0],last=path[path.length-1],EPS142=1e-9,samePoint=(p3,q5)=>Math.abs(p3.x-q5.x)<EPS142&&Math.abs(p3.y-q5.y)<EPS142;samePoint(first,{x:PA3.x,y:PA3.y})&&samePoint(last,{x:PB2.x,y:PB2.y})&&(this.solvedTracePath=path,this.solved=!0);return}let originalSegIndex=collision.segIndex,{segIndex,rect}=collision,isFirstSegment=segIndex===0,isLastSegment=segIndex===path.length-2,isEndpointChipObstacle=rect.kind==="chip"&&this.pins.some(pin=>pin.chipId===rect.chipId);if((path.length===3||path.length===4&&this.connectionPair!==void 0&&!isEndpointChipObstacle)&&(isFirstSegment||isLastSegment)){let compareDetours=path.length===4?(a22,b22)=>this.getPinBandPenalty(a22)-this.getPinBandPenalty(b22)||this.pathLength(a22)-this.pathLength(b22):(a22,b22)=>this.pathLength(a22)-this.pathLength(b22)||this.getPinBandPenalty(a22)-this.getPinBandPenalty(b22),detours=generateEndpointCollisionDetours({path,collidingSegmentIndex:segIndex,obstacle:rect}).filter(detour=>{let key=pathKey(detour);return this.visited.has(key)?!1:(this.visited.add(key),!0)}).sort(compareDetours);for(let detour of detours){let nextCollisionRects=new Set(collisionRects);nextCollisionRects.add(rect),this.queue.push({path:detour,collisionRects:nextCollisionRects})}return}if(isFirstSegment){if(path.length<3)return;segIndex=1}else if(isLastSegment){if(path.length<3)return;segIndex=path.length-3}let a6=path[segIndex],b6=path[segIndex+1],axis=this.axisOfSegment(a6,b6);if(!axis)return;let candidates=[],candidateMidOptions={allowOpenSideCandidates:this.connectionPair!==void 0};if(collisionRects.size===0){let m12=midBetweenPointAndRect(axis,{x:PA3.x,y:PA3.y},rect),m22=midBetweenPointAndRect(axis,{x:PB2.x,y:PB2.y},rect),allCandidates=[...m12,...m22],uniqueCandidates=[...new Set(allCandidates)];candidates.push(...uniqueCandidates)}else{let mids=candidateMidsFromSet(axis,rect,collisionRects,this.aabb,candidateMidOptions);candidates.push(...mids)}let newStates=[],addPathCandidate=newPath=>{let key=pathKey(newPath);if(this.visited.has(key))return;this.visited.add(key);let nextSet=new Set(collisionRects);nextSet.add(rect),newStates.push({path:newPath,collisionRects:nextSet,length:this.pathLength(newPath),pinBandPenalty:this.getPinBandPenalty(newPath)})},addShiftedCandidate=(candidateSegIndex,candidateAxis,coord)=>{let newPath=shiftSegmentOrth(path,candidateSegIndex,candidateAxis,coord);newPath&&addPathCandidate(newPath)},lastSegIndex=path.length-2;if(this.connectionPair===void 0&&rect.kind==="text_box"&&this.endpointTextObstacles.has(rect)&&!collisionRects.has(rect)&&originalSegIndex>0&&originalSegIndex<lastSegIndex)for(let detour of generateInternalSegmentCollisionDetours({path,collidingSegmentIndex:originalSegIndex,obstacle:rect}))addPathCandidate(detour);for(let coord of candidates)addShiftedCandidate(segIndex,axis,coord);let adjacentSegmentIndexes=originalSegIndex===1?[2]:originalSegIndex===lastSegIndex-1?[lastSegIndex-2]:[];for(let adjacentSegIndex of adjacentSegmentIndexes){if(adjacentSegIndex<0||adjacentSegIndex>=lastSegIndex)continue;let adjacentAxis=this.axisOfSegment(path[adjacentSegIndex],path[adjacentSegIndex+1]);if(!adjacentAxis||adjacentAxis===axis)continue;let adjacentCandidates=[...midBetweenPointAndRect(adjacentAxis,{x:PA3.x,y:PA3.y},rect),...midBetweenPointAndRect(adjacentAxis,{x:PB2.x,y:PB2.y},rect)];collisionRects.size>0&&adjacentCandidates.push(...candidateMidsFromSet(adjacentAxis,rect,collisionRects,this.aabb,candidateMidOptions));for(let coord of[...new Set(adjacentCandidates)])addShiftedCandidate(adjacentSegIndex,adjacentAxis,coord)}newStates.sort((a22,b22)=>a22.length-b22.length||a22.pinBandPenalty-b22.pinBandPenalty);for(let st3 of newStates)this.queue.push({path:st3.path,collisionRects:st3.collisionRects})}visualize(){let g4=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});g4.lines.push({points:this.baseElbow,strokeColor:"red",strokeDash:"4 4"});let[pin1,pin2]=this.pins;g4.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:"blue",strokeDash:"5 5"});for(let{path}of this.queue)g4.lines.push({points:path,strokeColor:"teal",strokeDash:"2 2"});return this.solvedTracePath?g4.lines.push({points:this.solvedTracePath,strokeColor:"green"}):this.queue.length>0&&g4.lines.push({points:this.queue[0].path,strokeColor:"orange"}),g4}},SchematicTraceLinesSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"mspConnectionPairs");__publicField(this,"dcConnMap");__publicField(this,"globalConnMap");__publicField(this,"queuedConnectionPairs");__publicField(this,"chipMap");__publicField(this,"currentConnectionPair",null);__publicField(this,"solvedTracePaths",[]);__publicField(this,"failedConnectionPairs",[]);this.inputProblem=params.inputProblem,this.mspConnectionPairs=params.mspConnectionPairs,this.dcConnMap=params.dcConnMap,this.globalConnMap=params.globalConnMap,this.chipMap=params.chipMap,this.queuedConnectionPairs=[...this.mspConnectionPairs]}getConstructorParams(){return{inputProblem:this.inputProblem,chipMap:this.chipMap,mspConnectionPairs:this.mspConnectionPairs,dcConnMap:this.dcConnMap,globalConnMap:this.globalConnMap}}_step(){if(this.activeSubSolver?.solved&&(this.solvedTracePaths.push({...this.currentConnectionPair,tracePath:this.activeSubSolver.solvedTracePath,mspConnectionPairIds:[this.currentConnectionPair.mspPairId],pinIds:[this.currentConnectionPair.pins[0].pinId,this.currentConnectionPair.pins[1].pinId]}),this.activeSubSolver=null,this.currentConnectionPair=null),this.activeSubSolver?.failed&&(this.currentConnectionPair&&this.failedConnectionPairs.push({...this.currentConnectionPair,error:this.activeSubSolver.error||void 0}),this.activeSubSolver=null,this.currentConnectionPair=null),this.activeSubSolver){this.activeSubSolver.step();return}let connectionPair=this.queuedConnectionPairs.shift();if(!connectionPair){this.solved=!0;return}this.currentConnectionPair=connectionPair;let{pins}=connectionPair;this.activeSubSolver=new SchematicTraceSingleLineSolver2({inputProblem:this.inputProblem,pins,connectionPair,chipMap:this.chipMap})}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});for(let{mspPairId,tracePath}of this.solvedTracePaths)graphics.lines.push({points:tracePath,strokeColor:"green"});for(let pair of this.failedConnectionPairs)graphics.lines.push({points:[{x:pair.pins[0].x,y:pair.pins[0].y},{x:pair.pins[1].x,y:pair.pins[1].y}],strokeColor:"red",strokeDash:"4 2"});return graphics}},applyJogToTerminalSegment=({pts,segmentIndex:si3,offset,JOG_SIZE,EPS:EPS142=1e-6})=>{if(si3!==0&&si3!==pts.length-2)return;let start=pts[si3],end=pts[si3+1],isVertical52=Math.abs(start.x-end.x)<EPS142,isHorizontal42=Math.abs(start.y-end.y)<EPS142;if(!isVertical52&&!isHorizontal42)return;let segDir=isVertical52?end.y>start.y?1:-1:end.x>start.x?1:-1;if(pts.length===2){if(isVertical52){let jogYNearStart=start.y+segDir*JOG_SIZE,jogYNearEnd=end.y-segDir*JOG_SIZE;pts.splice(1,0,{x:start.x,y:jogYNearStart},{x:start.x+offset,y:jogYNearStart},{x:end.x+offset,y:jogYNearEnd},{x:end.x,y:jogYNearEnd})}else{let jogXNearStart=start.x+segDir*JOG_SIZE,jogXNearEnd=end.x-segDir*JOG_SIZE;pts.splice(1,0,{x:jogXNearStart,y:start.y},{x:jogXNearStart,y:start.y+offset},{x:jogXNearEnd,y:end.y+offset},{x:jogXNearEnd,y:end.y})}return}if(si3===0)if(isVertical52){let jogY=start.y+segDir*JOG_SIZE;pts.splice(1,1,{x:start.x,y:jogY},{x:start.x+offset,y:jogY},{x:end.x+offset,y:end.y})}else{let jogX=start.x+segDir*JOG_SIZE;pts.splice(1,1,{x:jogX,y:start.y},{x:jogX,y:start.y+offset},{x:end.x,y:end.y+offset})}else if(isVertical52){let jogY=end.y-segDir*JOG_SIZE;pts.splice(si3,1,{x:start.x+offset,y:start.y},{x:end.x+offset,y:jogY},{x:end.x,y:jogY})}else{let jogX=end.x-segDir*JOG_SIZE;pts.splice(si3,1,{x:start.x,y:start.y+offset},{x:jogX,y:end.y+offset},{x:jogX,y:end.y})}},EPS5=1e-6,TraceOverlapIssueSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"overlappingTraceSegments");__publicField(this,"interactionKind");__publicField(this,"traceNetIslands");__publicField(this,"traceIdsToShift");__publicField(this,"obstacleRects");__publicField(this,"SHIFT_DISTANCE",.1);__publicField(this,"correctedTraceMap",{});this.overlappingTraceSegments=params.overlappingTraceSegments,this.interactionKind=params.interactionKind,this.traceNetIslands=params.traceNetIslands,this.traceIdsToShift=params.traceIdsToShift,this.obstacleRects=getObstacleRects(params.inputProblem);for(let{connNetId,pathsWithOverlap}of this.overlappingTraceSegments)for(let{solvedTracePathIndex,traceSegmentIndex}of pathsWithOverlap){let mspPairId=this.traceNetIslands[connNetId][solvedTracePathIndex].mspPairId;this.correctedTraceMap[mspPairId]=this.traceNetIslands[connNetId][solvedTracePathIndex]}}_step(){let containsStraightPinToPinTrace=group=>group.pathsWithOverlap.some(({solvedTracePathIndex})=>this.traceNetIslands[group.connNetId][solvedTracePathIndex].tracePath.length===2),groupShouldStayInPlace=this.overlappingTraceSegments.map(group=>this.traceIdsToShift?group.pathsWithOverlap.every(({solvedTracePathIndex})=>{let path=this.traceNetIslands[group.connNetId][solvedTracePathIndex];return!this.traceIdsToShift.has(path.mspPairId)}):containsStraightPinToPinTrace(group)),someGroupCanShift=groupShouldStayInPlace.some(shouldStay=>!shouldStay),getSeparationOffsets=firstDirection=>this.overlappingTraceSegments.map((group,groupIndex)=>{if(someGroupCanShift&&groupShouldStayInPlace[groupIndex])return 0;let n3=Math.floor(groupIndex/2)+1,direction2=groupIndex%2===0?firstDirection:-firstDirection;return this.getObstacleAwareOffset({group,offset:direction2*n3*this.SHIFT_DISTANCE})}),establishedOffsets=getSeparationOffsets(-1);if(this.interactionKind==="overlap"&&this.overlappingTraceSegments.some(group=>group.pathsWithOverlap.length>1)){this.correctedTraceMap=this.applyOffsets(establishedOffsets),this.solved=!0;return}let offsetCandidates=this.interactionKind==="overlap"?[establishedOffsets,getSeparationOffsets(1)]:[];if(this.interactionKind==="point_contact"){let movableGroupIndexes=this.overlappingTraceSegments.map((_6,groupIndex)=>groupIndex).filter(groupIndex=>!someGroupCanShift||!groupShouldStayInPlace[groupIndex]).reverse();for(let groupIndex of movableGroupIndexes){let group=this.overlappingTraceSegments[groupIndex];for(let direction2 of[-1,1]){let offsets=this.overlappingTraceSegments.map(()=>0);offsets[groupIndex]=this.getObstacleAwareOffset({group,offset:direction2*this.SHIFT_DISTANCE}),offsetCandidates.push(offsets)}}}let candidates=offsetCandidates.map(offsets=>{let correctedTraceMap=this.applyOffsets(offsets);return{correctedTraceMap,intersectionCount:this.countDifferentNetIntersections(correctedTraceMap),totalDisplacement:offsets.reduce((total,offset)=>total+Math.abs(offset),0)}});candidates.sort((a6,b6)=>a6.intersectionCount-b6.intersectionCount||a6.totalDisplacement-b6.totalDisplacement),this.correctedTraceMap=candidates[0].correctedTraceMap,this.solved=!0}applyOffsets(offsets){let correctedTraceMap={...this.correctedTraceMap},eq2=(a6,b6)=>Math.abs(a6-b6)<EPS5,samePoint=(p3,q5)=>!!p3&&!!q5&&eq2(p3.x,q5.x)&&eq2(p3.y,q5.y);return this.overlappingTraceSegments.forEach((group,groupIndex)=>{let offset=offsets[groupIndex];if(offset===0)return;let byPath=new Map;for(let loc of group.pathsWithOverlap)byPath.has(loc.solvedTracePathIndex)||byPath.set(loc.solvedTracePathIndex,new Set),byPath.get(loc.solvedTracePathIndex).add(loc.traceSegmentIndex);for(let[pathIdx,segIdxSet]of byPath){let original=this.traceNetIslands[group.connNetId][pathIdx],current3=correctedTraceMap[original.mspPairId]??original,pts=current3.tracePath.map(p3=>({...p3})),segIdxsRev=Array.from(segIdxSet).sort((a6,b6)=>a6-b6).reverse(),segmentAxes=new Map;for(let si3 of segIdxsRev){let start=pts[si3],end=pts[si3+1];!start||!end||(Math.abs(start.x-end.x)<EPS5?segmentAxes.set(si3,"vertical"):Math.abs(start.y-end.y)<EPS5&&segmentAxes.set(si3,"horizontal"))}let shiftedXPointIndexes=new Set,shiftedYPointIndexes=new Set,JOG_SIZE=this.SHIFT_DISTANCE;for(let si3 of segIdxsRev)if(!(si3<0||si3>=pts.length-1))if(si3===0||si3===pts.length-2)applyJogToTerminalSegment({pts,segmentIndex:si3,offset,JOG_SIZE,EPS:EPS5});else{let start=pts[si3],end=pts[si3+1],axis=segmentAxes.get(si3);axis==="vertical"?(shiftedXPointIndexes.has(si3)||(start.x+=offset,shiftedXPointIndexes.add(si3)),shiftedXPointIndexes.has(si3+1)||(end.x+=offset,shiftedXPointIndexes.add(si3+1))):axis==="horizontal"&&(shiftedYPointIndexes.has(si3)||(start.y+=offset,shiftedYPointIndexes.add(si3)),shiftedYPointIndexes.has(si3+1)||(end.y+=offset,shiftedYPointIndexes.add(si3+1)))}let cleaned=[];for(let p3 of pts)(cleaned.length===0||!samePoint(cleaned[cleaned.length-1],p3))&&cleaned.push(p3);correctedTraceMap[original.mspPairId]={...current3,tracePath:cleaned}}}),correctedTraceMap}countDifferentNetIntersections(correctedTraceMap){let traces=Object.values(this.traceNetIslands).flatMap(island=>island.map(trace=>correctedTraceMap[trace.mspPairId]??trace)),intersectionCount=0;for(let traceIndex=0;traceIndex<traces.length;traceIndex++){let trace=traces[traceIndex];for(let otherTraceIndex=traceIndex+1;otherTraceIndex<traces.length;otherTraceIndex++){let otherTrace=traces[otherTraceIndex];if(trace.globalConnNetId!==otherTrace.globalConnNetId)for(let segmentIndex=0;segmentIndex<trace.tracePath.length-1;segmentIndex++)for(let otherSegmentIndex=0;otherSegmentIndex<otherTrace.tracePath.length-1;otherSegmentIndex++)doSegmentsIntersect(trace.tracePath[segmentIndex],trace.tracePath[segmentIndex+1],otherTrace.tracePath[otherSegmentIndex],otherTrace.tracePath[otherSegmentIndex+1])&&intersectionCount++}}return intersectionCount}getObstacleAwareOffset({group,offset}){let blockingCollisions=this.getBlockingCollisions({group,offset});if(blockingCollisions.length===0)return offset;let crossesThroughObstacle=candidateOffset=>blockingCollisions.some(({start,isVertical:isVertical52,obstacle})=>{let orig,min,max2;isVertical52?(orig=start.x,min=obstacle.minX,max2=obstacle.maxX):(orig=start.y,min=obstacle.minY,max2=obstacle.maxY);let next2=orig+candidateOffset;return orig<=min+EPS5&&next2>=max2-EPS5||orig>=max2-EPS5&&next2<=min+EPS5}),edges=blockingCollisions.map(({start,isVertical:isVertical52,obstacle})=>isVertical52?{coord:start.x,lowEdge:obstacle.minX,highEdge:obstacle.maxX}:{coord:start.y,lowEdge:obstacle.minY,highEdge:obstacle.maxY}),bestCandidate=clearance=>edges.flatMap(({coord,lowEdge,highEdge})=>[lowEdge-coord-clearance,highEdge-coord+clearance]).filter(candidateOffset=>!crossesThroughObstacle(candidateOffset)).filter(candidateOffset=>this.getBlockingCollisions({group,offset:candidateOffset}).length===0).sort((a6,b6)=>Math.abs(a6-offset)-Math.abs(b6-offset))[0],EDGE_MARGIN=this.SHIFT_DISTANCE/10;return bestCandidate(this.SHIFT_DISTANCE)??bestCandidate(EDGE_MARGIN)??offset}getBlockingCollisions({group,offset}){let blockingCollisions=[];for(let{solvedTracePathIndex,traceSegmentIndex}of group.pathsWithOverlap){let trace=this.traceNetIslands[group.connNetId][solvedTracePathIndex],start=trace.tracePath[traceSegmentIndex],end=trace.tracePath[traceSegmentIndex+1];if(!start||!end)continue;let isVertical52=Math.abs(start.x-end.x)<EPS5,isHorizontal42=Math.abs(start.y-end.y)<EPS5;if(!isVertical52&&!isHorizontal42)continue;let shiftedSegment=isVertical52?[{...start,x:start.x+offset},{...end,x:end.x+offset}]:[{...start,y:start.y+offset},{...end,y:end.y+offset}],collision=findFirstCollision(shiftedSegment,this.obstacleRects);collision&&blockingCollisions.push({start,isVertical:isVertical52,obstacle:collision.rect})}return blockingCollisions}visualize(){let graphics={lines:[],points:[],rects:[],circles:[]};for(let group of this.overlappingTraceSegments)for(let{solvedTracePathIndex,traceSegmentIndex}of group.pathsWithOverlap){let path=this.traceNetIslands[group.connNetId][solvedTracePathIndex],segStart=path.tracePath[traceSegmentIndex],segEnd=path.tracePath[traceSegmentIndex+1];graphics.lines.push({points:[segStart,segEnd],strokeColor:"red"})}for(let trace of Object.values(this.correctedTraceMap))graphics.lines.push({points:trace.tracePath,strokeColor:"blue",strokeDash:"4 2"});return graphics}},TRACE_STATE_POSITION_EPSILON=1e-6,TraceOverlapShiftSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTracePaths");__publicField(this,"globalConnMap");__publicField(this,"traceIdsToShift");__publicField(this,"traceNetIslands",{});__publicField(this,"correctedTraceMap",{});__publicField(this,"recentTraceStates",[]);__publicField(this,"cleanupPhase",null);this.inputProblem=params.inputProblem,this.inputTracePaths=params.inputTracePaths,this.globalConnMap=params.globalConnMap,this.traceIdsToShift=params.traceIdsToShift;for(let tracePath of this.inputTracePaths){let{mspPairId}=tracePath;this.correctedTraceMap[mspPairId]=tracePath}this.rememberTraceState(this.correctedTraceMap),this.traceNetIslands=this.computeTraceNetIslands()}getConstructorParams(){return{inputProblem:this.inputProblem,inputTracePaths:this.inputTracePaths,globalConnMap:this.globalConnMap,traceIdsToShift:this.traceIdsToShift}}computeTraceNetIslands(){let islands={};for(let original of this.inputTracePaths){let path=this.correctedTraceMap[original.mspPairId]??original,key=path.globalConnNetId;islands[key]||(islands[key]=[]),islands[key].push(path)}return islands}findNextOverlapIssue(){let netIds=Object.keys(this.traceNetIslands);for(let i6=0;i6<netIds.length;i6++)for(let j6=i6+1;j6<netIds.length;j6++){let netA=netIds[i6],netB=netIds[j6],pathsA=this.traceNetIslands[netA]||[],pathsB=this.traceNetIslands[netB]||[],overlapsA=[],overlapsB=[],pointContacts=[],seenA=new Set,seenB=new Set,getRangeOverlap1D=(a12,a22,b12,b22)=>{let minA=Math.min(a12,a22),maxA=Math.max(a12,a22),minB=Math.min(b12,b22),maxB=Math.max(b12,b22);return Math.min(maxA,maxB)-Math.max(minA,minB)},recordCollinearInteraction=({pathAIndex,segmentAIndex,pathBIndex,segmentBIndex,rangeOverlap})=>{if(rangeOverlap>.002){let keyA=`${pathAIndex}:${segmentAIndex}`,keyB=`${pathBIndex}:${segmentBIndex}`;seenA.has(keyA)||(overlapsA.push({solvedTracePathIndex:pathAIndex,traceSegmentIndex:segmentAIndex}),seenA.add(keyA)),seenB.has(keyB)||(overlapsB.push({solvedTracePathIndex:pathBIndex,traceSegmentIndex:segmentBIndex}),seenB.add(keyB));return}if(rangeOverlap<-.002)return;let pathA=pathsA[pathAIndex].tracePath,pathB=pathsB[pathBIndex].tracePath,segmentAStart=pathA[segmentAIndex],segmentAEnd=pathA[segmentAIndex+1],segmentBStart=pathB[segmentBIndex],segmentBEnd=pathB[segmentBIndex+1];segmentAIndex===0||segmentAIndex===pathA.length-2||segmentBIndex===0||segmentBIndex===pathB.length-2||pointContacts.push({pathAIndex,segmentAIndex,pathBIndex,segmentBIndex,combinedLength:Math.abs(segmentAStart.x-segmentAEnd.x)+Math.abs(segmentAStart.y-segmentAEnd.y)+Math.abs(segmentBStart.x-segmentBEnd.x)+Math.abs(segmentBStart.y-segmentBEnd.y)})};for(let pa3=0;pa3<pathsA.length;pa3++){let pathA=pathsA[pa3],ptsA=pathA.tracePath;for(let sa3=0;sa3<ptsA.length-1;sa3++){let a12=ptsA[sa3],a22=ptsA[sa3+1],aVert=Math.abs(a12.x-a22.x)<.002,aHorz=Math.abs(a12.y-a22.y)<.002;if(!(!aVert&&!aHorz))for(let pb2=0;pb2<pathsB.length;pb2++){let pathB=pathsB[pb2];if(this.traceIdsToShift&&!this.traceIdsToShift.has(pathA.mspPairId)&&!this.traceIdsToShift.has(pathB.mspPairId))continue;let ptsB=pathB.tracePath;for(let sb2=0;sb2<ptsB.length-1;sb2++){let b12=ptsB[sb2],b22=ptsB[sb2+1],bVert=Math.abs(b12.x-b22.x)<.002,bHorz=Math.abs(b12.y-b22.y)<.002;!bVert&&!bHorz||(aVert&&bVert?Math.abs(a12.x-b12.x)<.002&&recordCollinearInteraction({pathAIndex:pa3,segmentAIndex:sa3,pathBIndex:pb2,segmentBIndex:sb2,rangeOverlap:getRangeOverlap1D(a12.y,a22.y,b12.y,b22.y)}):aHorz&&bHorz&&Math.abs(a12.y-b12.y)<.002&&recordCollinearInteraction({pathAIndex:pa3,segmentAIndex:sa3,pathBIndex:pb2,segmentBIndex:sb2,rangeOverlap:getRangeOverlap1D(a12.x,a22.x,b12.x,b22.x)}))}}}}if(overlapsA.length>0&&overlapsB.length>0)return{interactionKind:"overlap",overlappingTraceSegments:[{connNetId:netA,pathsWithOverlap:overlapsA},{connNetId:netB,pathsWithOverlap:overlapsB}]};let bestPointContact=pointContacts.sort((a6,b6)=>b6.combinedLength-a6.combinedLength)[0];if(bestPointContact)return{interactionKind:"point_contact",overlappingTraceSegments:[{connNetId:netA,pathsWithOverlap:[{solvedTracePathIndex:bestPointContact.pathAIndex,traceSegmentIndex:bestPointContact.segmentAIndex}]},{connNetId:netB,pathsWithOverlap:[{solvedTracePathIndex:bestPointContact.pathBIndex,traceSegmentIndex:bestPointContact.segmentBIndex}]}]}}return null}findNextDiagonalSegment(){for(let mspPairId in this.correctedTraceMap){let tracePath=this.correctedTraceMap[mspPairId].tracePath;for(let i6=0;i6<tracePath.length-1;i6++){let p12=tracePath[i6],p22=tracePath[i6+1],isHorizontal42=Math.abs(p12.y-p22.y)<.002,isVertical52=Math.abs(p12.x-p22.x)<.002;if(!isHorizontal42&&!isVertical52)return{mspPairId,tracePath,i:i6,p1:p12,p2:p22}}}return null}findAndFixNextDiagonalSegment(){let diagonalInfo=this.findNextDiagonalSegment();if(!diagonalInfo)return!1;let{mspPairId,tracePath,i:i6,p1:p12,p2:p22}=diagonalInfo,EPS142=.002,p03=i6>0?tracePath[i6-1]:null,p3=i6+2<tracePath.length?tracePath[i6+2]:null,prevIsVertical=p03?Math.abs(p03.x-p12.x)<EPS142:!1,prevIsHorizontal=p03?Math.abs(p03.y-p12.y)<EPS142:!1,nextIsVertical=p3?Math.abs(p22.x-p3.x)<EPS142:!1,nextIsHorizontal=p3?Math.abs(p22.y-p3.y)<EPS142:!1,elbow1={x:p12.x,y:p22.y},elbow2={x:p22.x,y:p12.y},score1=0;prevIsVertical&&score1++,nextIsHorizontal&&score1++;let score2=0;prevIsHorizontal&&score2++,nextIsVertical&&score2++;let elbowPoint=score1<score2?elbow1:elbow2;return tracePath.splice(i6+1,0,elbowPoint),!0}_step(){if(this.activeSubSolver?.solved){let nextTraceState={...this.correctedTraceMap,...this.activeSubSolver.correctedTraceMap};if(this.returnsToPreviousTraceState(nextTraceState)){this.activeSubSolver=null,this.solved=!0;return}this.correctedTraceMap=nextTraceState,this.rememberTraceState(nextTraceState),this.activeSubSolver=null,this.traceNetIslands=this.computeTraceNetIslands()}if(this.activeSubSolver){this.activeSubSolver.step();return}let overlapIssue=this.findNextOverlapIssue();if(overlapIssue===null){if(this.cleanupPhase===null&&(this.cleanupPhase="diagonals"),this.cleanupPhase==="diagonals"){this.findAndFixNextDiagonalSegment()||(this.cleanupPhase="done",this.solved=!0);return}this.solved=!0;return}let{interactionKind,overlappingTraceSegments}=overlapIssue;this.activeSubSolver=new TraceOverlapIssueSolver({inputProblem:this.inputProblem,interactionKind,overlappingTraceSegments,traceNetIslands:this.traceNetIslands,traceIdsToShift:this.traceIdsToShift})}rememberTraceState(traceState){this.recentTraceStates.push({...traceState}),this.recentTraceStates.length>2&&this.recentTraceStates.shift()}returnsToPreviousTraceState(candidateTraceState){if(this.recentTraceStates.length<2)return!1;let previousTraceState=this.recentTraceStates[0],traceIds=Object.keys(candidateTraceState);if(traceIds.length!==Object.keys(previousTraceState).length)return!1;for(let traceId of traceIds){let candidatePath=candidateTraceState[traceId],previousPath=previousTraceState[traceId];if(!candidatePath||!previousPath||candidatePath.tracePath.length!==previousPath.tracePath.length)return!1;for(let i6=0;i6<candidatePath.tracePath.length;i6++){let candidatePoint=candidatePath.tracePath[i6],previousPoint=previousPath.tracePath[i6];if(Math.abs(candidatePoint.x-previousPoint.x)>TRACE_STATE_POSITION_EPSILON||Math.abs(candidatePoint.y-previousPoint.y)>TRACE_STATE_POSITION_EPSILON)return!1}}return!0}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);graphics.circles=graphics.circles||[];for(let trace of Object.values(this.correctedTraceMap))graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});if(this.cleanupPhase==="diagonals"){let diagonalInfo=this.findNextDiagonalSegment();diagonalInfo&&graphics.lines.push({points:[diagonalInfo.p1,diagonalInfo.p2],strokeColor:"red",strokeWidth:.05})}return graphics}},ChipObstacleSpatialIndex=class{constructor(chips){__publicField(this,"chips");__publicField(this,"spatialIndex");__publicField(this,"spatialIndexIdToChip");this.chips=chips.map(chip=>({...chip,bounds:getInputChipBounds(chip),spatialIndexId:null})),this.spatialIndexIdToChip=new Map,this.spatialIndex=new Flatbush(chips.length);for(let chip of this.chips)chip.spatialIndexId=this.spatialIndex.add(chip.bounds.minX,chip.bounds.minY,chip.bounds.maxX,chip.bounds.maxY),this.spatialIndexIdToChip.set(chip.spatialIndexId,chip);this.spatialIndex.finish()}getChipsInBounds(bounds){return this.spatialIndex.search(bounds.minX,bounds.minY,bounds.maxX,bounds.maxY).map(id3=>this.spatialIndexIdToChip.get(id3))}doesOrthogonalLineIntersectChip(line2,opts={}){let excludeChipIds=opts.excludeChipIds??[],[p12,p22]=line2,{x:x12,y:y12}=p12,{x:x22,y:y2}=p22;return this.getChipsInBounds({minX:Math.min(x12,x22),minY:Math.min(y12,y2),maxX:Math.max(x12,x22),maxY:Math.max(y12,y2)}).filter(chip=>!excludeChipIds.includes(chip.chipId)).length>0}};function segmentIntersectsRect2(p12,p22,rect,EPS142=1e-9){let isVert=Math.abs(p12.x-p22.x)<EPS142,isHorz=Math.abs(p12.y-p22.y)<EPS142;if(!isVert&&!isHorz)return!1;if(isVert){let x6=p12.x;if(x6<rect.minX-EPS142||x6>rect.maxX+EPS142)return!1;let segMinY=Math.min(p12.y,p22.y),segMaxY=Math.max(p12.y,p22.y);return Math.min(segMaxY,rect.maxY)-Math.max(segMinY,rect.minY)>EPS142}else{let y2=p12.y;if(y2<rect.minY-EPS142||y2>rect.maxY+EPS142)return!1;let segMinX=Math.min(p12.x,p22.x),segMaxX=Math.max(p12.x,p22.x);return Math.min(segMaxX,rect.maxX)-Math.max(segMinX,rect.minX)>EPS142}}function rectIntersectsAnyTrace(bounds,inputTraceMap,hostPathId,hostSegIndex){for(let[pairId,solved]of Object.entries(inputTraceMap)){let pts=solved.tracePath;for(let i6=0;i6<pts.length-1;i6++)if(!(pairId===hostPathId&&i6===hostSegIndex)&&segmentIntersectsRect2(pts[i6],pts[i6+1],bounds))return{hasIntersection:!0,mspPairId:pairId,segIndex:i6}}return{hasIntersection:!1}}function lengthOfTrace(path){let sum=0,pts=path.tracePath;for(let i6=0;i6<pts.length-1;i6++)sum+=Math.abs(pts[i6+1].x-pts[i6].x)+Math.abs(pts[i6+1].y-pts[i6].y);return sum}function chooseHostTraceForGroup(params){let{inputProblem,inputTraceMap,globalConnNetId,fallbackTrace,mspConnectionPairIds}=params,chipsById=Object.fromEntries(inputProblem.chips.map(c3=>[c3.chipId,c3])),groupTraces=Object.values(inputTraceMap).filter(t53=>t53.globalConnNetId===globalConnNetId);if(mspConnectionPairIds&&mspConnectionPairIds.length>0){let idSet=new Set(mspConnectionPairIds);groupTraces=groupTraces.filter(t53=>t53.mspConnectionPairIds.some(id3=>idSet.has(id3)))}let chipIdsInGroup=new Set;for(let t53 of groupTraces)chipIdsInGroup.add(t53.pins[0].chipId),chipIdsInGroup.add(t53.pins[1].chipId);let largestChipId=null,largestPinCount=-1;for(let id3 of chipIdsInGroup){let count=chipsById[id3]?.pins?.length??0;count>largestPinCount&&(largestPinCount=count,largestChipId=id3)}let hostCandidates=largestChipId==null?[]:groupTraces.filter(t53=>t53.pins[0].chipId===largestChipId||t53.pins[1].chipId===largestChipId);return hostCandidates.length>0?hostCandidates.reduce((a6,b6)=>lengthOfTrace(a6)>=lengthOfTrace(b6)?a6:b6):fallbackTrace}function anchorsForSegment(a6,b6){return[{x:a6.x,y:a6.y},{x:(a6.x+b6.x)/2,y:(a6.y+b6.y)/2},{x:b6.x,y:b6.y}]}function solveNetLabelPlacementForPortOnlyPin(params){let{inputProblem,inputTraceMap,chipObstacleSpatialIndex,overlappingSameNetTraceGroup,availableOrientations,netLabelWidth,netLabelHeight}=params,pinId=overlappingSameNetTraceGroup.portOnlyPinId;if(!pinId)return{placement:null,testedCandidates:[],error:"No portOnlyPinId provided"};let pin=null,pinFacingDirection=null;for(let chip of inputProblem.chips){let p3=chip.pins.find(pp3=>pp3.pinId===pinId);if(p3){pin={x:p3.x,y:p3.y},pinFacingDirection=p3._facingDirection||getPinDirection(p3,chip);break}}if(!pin||!pinFacingDirection)return{placement:null,testedCandidates:[],error:`Port-only pin not found: ${pinId}`};let orientations=availableOrientations.length>0?availableOrientations:["x+","x-","y+","y-"],anchor={x:pin.x,y:pin.y},outwardOf=o6=>o6==="x+"?{x:1,y:0}:o6==="x-"?{x:-1,y:0}:o6==="y+"?{x:0,y:1}:{x:0,y:-1},testedCandidates=[];for(let orientation4 of orientations){let{width:width2,height:height2}=getDimsForOrientation({orientation:orientation4,netLabelWidth,netLabelHeight}),baseCenter2=getCenterFromAnchor(anchor,orientation4,width2,height2),outward2=outwardOf(orientation4),offset2=.001,center2={x:baseCenter2.x+outward2.x*offset2,y:baseCenter2.y+outward2.y*offset2},bounds=getRectBounds(center2,width2,height2);if(chipObstacleSpatialIndex.getChipsInBounds(bounds).length>0){testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"chip-collision",hostSegIndex:-1});continue}if(rectIntersectsAnyTextBox(bounds,inputProblem)){testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"text-collision",hostSegIndex:-1});continue}if(rectIntersectsAnyTrace(bounds,inputTraceMap,"",-1).hasIntersection){testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"trace-collision",hostSegIndex:-1});continue}return testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"ok",hostSegIndex:-1}),{placement:{globalConnNetId:overlappingSameNetTraceGroup.globalConnNetId,dcConnNetId:void 0,netId:overlappingSameNetTraceGroup.netId,netLabelText:overlappingSameNetTraceGroup.netLabelText,mspConnectionPairIds:[],pinIds:[pinId],orientation:orientation4,anchorPoint:anchor,width:width2,height:height2,center:center2},testedCandidates}}let fallbackOrientation=pinFacingDirection,{width,height}=getDimsForOrientation({orientation:fallbackOrientation,netLabelWidth}),baseCenter=getCenterFromAnchor(anchor,fallbackOrientation,width,height),outward=outwardOf(fallbackOrientation),offset=.001,fallbackCenter={x:baseCenter.x+outward.x*offset,y:baseCenter.y+outward.y*offset};return{placement:{globalConnNetId:overlappingSameNetTraceGroup.globalConnNetId,dcConnNetId:void 0,netId:overlappingSameNetTraceGroup.netId,netLabelText:overlappingSameNetTraceGroup.netLabelText,mspConnectionPairIds:[],pinIds:[pinId],orientation:fallbackOrientation,anchorPoint:anchor,width,height,center:fallbackCenter},testedCandidates}}function visualizeSingleNetLabelPlacementSolver(solver){let graphics=visualizeInputProblem2(solver.inputProblem),groupId=solver.overlappingSameNetTraceGroup.globalConnNetId,host=chooseHostTraceForGroup({inputProblem:solver.inputProblem,inputTraceMap:solver.inputTraceMap,globalConnNetId:groupId,fallbackTrace:solver.overlappingSameNetTraceGroup.overlappingTraces}),groupStroke=getColorFromString2(groupId,.9),groupFill=getColorFromString2(groupId,.5);for(let trace of Object.values(solver.inputTraceMap)){let isHost=host?trace.mspPairId===host.mspPairId:!1;graphics.lines.push({points:trace.tracePath})}for(let c3 of solver.testedCandidates){let fill=c3.status==="ok"?"rgba(0, 180, 0, 0.25)":c3.status==="chip-collision"?"rgba(220, 0, 0, 0.25)":c3.status==="trace-collision"?"rgba(220, 140, 0, 0.25)":c3.status==="text-collision"?"rgba(160, 0, 220, 0.2)":"rgba(120, 120, 120, 0.15)",stroke=c3.status==="ok"?"green":c3.status==="chip-collision"?"red":c3.status==="trace-collision"?"orange":c3.status==="text-collision"?"purple":"gray",candidateLabel=c3.status==="ok"?"status: ok(valid net label candidate)":c3.status==="chip-collision"?"status: chip-collision":c3.status==="trace-collision"?"status: trace-collision":c3.status==="text-collision"?"status: text-collision":"status: parallel-to-segment";graphics.rects.push({center:{x:(c3.bounds.minX+c3.bounds.maxX)/2,y:(c3.bounds.minY+c3.bounds.maxY)/2},width:c3.width,height:c3.height,fill,strokeColor:stroke,label:`${candidateLabel}
644
+ ${pin._facingDirection??getPinDirection(pin,chip)}`,x:pin.x,y:pin.y,color:getColorFromString2(pin.pinId,.8)})}for(let textBox of inputProblem.textBoxes??[])graphics.rects.push({label:textBox.text??"schematic_text",center:textBox.center,width:textBox.width,height:textBox.height,fill:"rgba(160, 0, 220, 0.14)",strokeColor:"rgba(160, 0, 220, 0.9)"});if(!hideRatsNet){for(let directConn of inputProblem.directConnections){let[pinId1,pinId2]=directConn.pinIds,pin1=pinIdMap.get(pinId1),pin2=pinIdMap.get(pinId2);arePinsInDifferentSchematicSections(inputProblem,pin1,pin2)||graphics.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:getColorFromString2(directConn.netId??`${pinId1}-${pinId2}`,connectionAlpha)})}for(let netConn of inputProblem.netConnections){let pins=netConn.pinIds.map(pinId=>pinIdMap.get(pinId));for(let i6=0;i6<pins.length-1;i6++)for(let j6=i6+1;j6<pins.length;j6++){let pin1=pins[i6],pin2=pins[j6];arePinsInDifferentSchematicSections(inputProblem,pin1,pin2)||graphics.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:getColorFromString2(netConn.netId,connectionAlpha),strokeDash:"4 2"})}}}return graphics},getRestrictedCenterLines=params=>{let{pins,inputProblem,pinIdMap,chipMap}=params,findAllDirectlyConnectedPins=startPinId=>{let visited=new Set,queue=[startPinId];visited.add(startPinId);let directConns=inputProblem.directConnections||[];for(;queue.length;){let cur=queue.shift();for(let dc2 of directConns)if(dc2.pinIds.includes(cur))for(let p3 of dc2.pinIds)visited.has(p3)||(visited.add(p3),queue.push(p3))}return visited},p03=pins[0].pinId,p12=pins[1].pinId,relatedPinIds=new Set([...findAllDirectlyConnectedPins(p03),...findAllDirectlyConnectedPins(p12)]),restrictedCenterLines=new Map,chipFacingMap=new Map,chipsOfFacingPins=new Set(pins.map(p3=>p3.chipId));for(let pinId of relatedPinIds){let pin=pinIdMap.get(pinId);if(!pin)continue;let chip=chipMap[pin.chipId];if(!chip)continue;let facing=pin._facingDirection??getPinDirection(pin,chip),entry=chipFacingMap.get(chip.chipId);if(!entry){entry={center:chip.center};let counts={xPos:0,xNeg:0,yPos:0,yNeg:0};for(let cp3 of chip.pins){let cpFacing=cp3._facingDirection??getPinDirection(cp3,chip);cpFacing==="x+"&&counts.xPos++,cpFacing==="x-"&&counts.xNeg++,cpFacing==="y+"&&counts.yPos++,cpFacing==="y-"&&counts.yNeg++}entry.counts=counts,chipFacingMap.set(chip.chipId,entry)}facing==="x+"&&(entry.hasXPos=!0),facing==="x-"&&(entry.hasXNeg=!0),facing==="y+"&&(entry.hasYPos=!0),facing==="y-"&&(entry.hasYNeg=!0)}for(let[chipId,faces]of chipFacingMap){let axes=new Set,rcl={axes},counts=faces.counts;!(counts&&(counts.xPos>1||counts.xNeg>1||counts.yPos>1||counts.yNeg>1))&&chipsOfFacingPins.has(chipId)||(faces.hasXPos&&faces.hasXNeg&&(rcl.x=faces.center.x,axes.add("x")),faces.hasYPos&&faces.hasYNeg&&(rcl.y=faces.center.y,axes.add("y"))),axes.size>0&&restrictedCenterLines.set(chipId,rcl)}return restrictedCenterLines},doesPairCrossRestrictedCenterLines=params=>{let{inputProblem,chipMap,pinIdMap,p1:p12,p2:p22}=params,restrictedCenterLines=getRestrictedCenterLines({pins:[p12,p22],inputProblem,pinIdMap,chipMap});if(restrictedCenterLines.size===0)return!1;let EPS142=1e-9,crossesSegment=(a6,b6)=>{for(let[,rcl]of restrictedCenterLines)if(rcl.axes.has("x")&&typeof rcl.x=="number"&&(a6.x-rcl.x)*(b6.x-rcl.x)<-EPS142||rcl.axes.has("y")&&typeof rcl.y=="number"&&(a6.y-rcl.y)*(b6.y-rcl.y)<-EPS142)return!0;return!1};if(Math.abs(p12.x-p22.x)<EPS142||Math.abs(p12.y-p22.y)<EPS142)return crossesSegment({x:p12.x,y:p12.y},{x:p22.x,y:p22.y});let elbowHV={x:p22.x,y:p12.y},elbowVH={x:p12.x,y:p22.y},hvCrosses=crossesSegment({x:p12.x,y:p12.y},elbowHV)||crossesSegment(elbowHV,{x:p22.x,y:p22.y}),vhCrosses=crossesSegment({x:p12.x,y:p12.y},elbowVH)||crossesSegment(elbowVH,{x:p22.x,y:p22.y});return hvCrosses&&vhCrosses},getConnectivityMapsFromInputProblem=inputProblem=>{let directConnMap=new ConnectivityMap2({});for(let directConn of inputProblem.directConnections)directConnMap.addConnections([directConn.netId?[directConn.netId,...directConn.pinIds]:directConn.pinIds]);let netConnMap=new ConnectivityMap2(directConnMap.netMap);for(let netConn of inputProblem.netConnections)netConnMap.addConnections([[netConn.netId,...netConn.pinIds]]);return{directConnMap,netConnMap}};function getOrthogonalMinimumSpanningTree(pins,opts={}){let n3=pins.length,maxDistance=opts?.maxDistance??Number.POSITIVE_INFINITY;if(n3<=1)return[];{let seen=new Set;for(let p3 of pins){if(seen.has(p3.pinId))throw new Error(`Duplicate pinId detected: "${p3.pinId}"`);seen.add(p3.pinId)}}let manhattan=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),inTree=new Array(n3).fill(!1),bestDist=new Array(n3).fill(Number.POSITIVE_INFINITY),parent=new Array(n3).fill(-1),startIndex=0;for(let i6=1;i6<n3;i6++)pins[i6].pinId<pins[startIndex].pinId&&(startIndex=i6);bestDist[startIndex]=0;let edges=[];for(let iter=0;iter<n3;iter++){let u6=-1,best=Number.POSITIVE_INFINITY,bestId="";for(let i6=0;i6<n3;i6++)if(!inTree[i6]){let d3=bestDist[i6];(d3<best||d3===best&&(bestId===""||pins[i6].pinId<bestId))&&(best=d3,bestId=pins[i6].pinId,u6=i6)}inTree[u6]=!0,parent[u6]!==-1&&edges.push([pins[u6].pinId,pins[parent[u6]].pinId]);for(let v6=0;v6<n3;v6++)if(!inTree[v6]){let d03=manhattan(pins[u6],pins[v6]),isForbidden=opts?.forbidEdge?.(pins[u6],pins[v6])??!1,d3=d03>maxDistance||isForbidden?Number.POSITIVE_INFINITY:d03;(d3<bestDist[v6]||d3===bestDist[v6]&&pins[u6].pinId<pins[parent[v6]]?.pinId)&&(bestDist[v6]=d3,parent[v6]=u6)}}return edges}var NET_LABEL_HORIZONTAL_WIDTH=.45,NET_LABEL_HORIZONTAL_HEIGHT=.2;function getDimsForOrientation(params){let{orientation:orientation4,netLabelWidth,netLabelHeight}=params,horizWidth=typeof netLabelWidth=="number"?netLabelWidth:NET_LABEL_HORIZONTAL_WIDTH,horizHeight=typeof netLabelHeight=="number"?netLabelHeight:NET_LABEL_HORIZONTAL_HEIGHT;return orientation4==="y+"||orientation4==="y-"?{width:horizHeight,height:horizWidth}:{width:horizWidth,height:horizHeight}}function getCenterFromAnchor(anchor,orientation4,width,height){switch(orientation4){case"x+":return{x:anchor.x+width/2,y:anchor.y};case"x-":return{x:anchor.x-width/2,y:anchor.y};case"y+":return{x:anchor.x,y:anchor.y+height/2};case"y-":return{x:anchor.x,y:anchor.y-height/2}}}function getRectBounds(center2,w4,h3){return{minX:center2.x-w4/2,minY:center2.y-h3/2,maxX:center2.x+w4/2,maxY:center2.y+h3/2}}var getLabeledConnectionRouteReason=({inputProblem,chipMap,pins})=>{let[firstPin,secondPin]=pins,directConnection=inputProblem.directConnections.find(connection=>connection.pinIds.includes(firstPin.pinId)&&connection.pinIds.includes(secondPin.pinId));if(directConnection?.netLabelWidth===void 0)return null;let firstChip=chipMap[firstPin.chipId],secondChip=chipMap[secondPin.chipId];if(!firstChip||!secondChip)return null;let firstFacingDirection=firstPin._facingDirection;firstFacingDirection||(firstFacingDirection=getPinDirection(firstPin,firstChip));let secondFacingDirection=secondPin._facingDirection;if(secondFacingDirection||(secondFacingDirection=getPinDirection(secondPin,secondChip)),!(firstFacingDirection==="x-"&&secondFacingDirection==="x+"||firstFacingDirection==="x+"&&secondFacingDirection==="x-"))return null;if(firstChip.pins.length===1||secondChip.pins.length===1)return"single-pin-peripheral";if(!(firstChip.sectionId&&firstChip.sectionId===secondChip.sectionId?firstChip.sectionId:null))return null;let directionsPointTowardEachOther=firstPin.x<=secondPin.x?firstFacingDirection==="x+"&&secondFacingDirection==="x-":firstFacingDirection==="x-"&&secondFacingDirection==="x+",labelsOverlapAlongX=Math.abs(firstPin.x-secondPin.x)<directConnection.netLabelWidth*2,labelsOverlapAlongY=Math.abs(firstPin.y-secondPin.y)<NET_LABEL_HORIZONTAL_HEIGHT;return directionsPointTowardEachOther&&labelsOverlapAlongX&&labelsOverlapAlongY?"overlapping-fallback-labels":null},isLabeledPeripheralConnection=params=>getLabeledConnectionRouteReason(params)!==null,DEFAULT_MAX_MSP_PAIR_DISTANCE=1,getPinPairKey=pinIds=>[...pinIds].sort().join("::"),MspConnectionPairSolver=class extends BaseSolver5{constructor({inputProblem}){super();__publicField(this,"inputProblem");__publicField(this,"mspConnectionPairs",[]);__publicField(this,"dcConnMap");__publicField(this,"globalConnMap");__publicField(this,"queuedDcNetIds");__publicField(this,"chipMap");__publicField(this,"maxMspPairDistance");__publicField(this,"pinMap");__publicField(this,"userNetIdByPinId");__publicField(this,"directConnectionPinPairKeys");this.inputProblem=inputProblem,this.maxMspPairDistance=inputProblem.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE;let{directConnMap,netConnMap}=getConnectivityMapsFromInputProblem(inputProblem);this.dcConnMap=directConnMap,this.globalConnMap=netConnMap,this.pinMap={};for(let chip of inputProblem.chips)for(let pin of chip.pins)this.pinMap[pin.pinId]={...pin,chipId:chip.chipId};this.chipMap={};for(let chip of inputProblem.chips)this.chipMap[chip.chipId]=chip;this.userNetIdByPinId={},this.directConnectionPinPairKeys=new Set;for(let dc2 of inputProblem.directConnections)if(this.directConnectionPinPairKeys.add(getPinPairKey(dc2.pinIds)),dc2.netId){let[a6,b6]=dc2.pinIds;this.userNetIdByPinId[a6]=dc2.netId,this.userNetIdByPinId[b6]=dc2.netId}for(let nc3 of inputProblem.netConnections)for(let pid of nc3.pinIds)this.userNetIdByPinId[pid]=nc3.netId;this.queuedDcNetIds=Object.keys(netConnMap.netMap)}getConstructorParams(){return{inputProblem:this.inputProblem}}_step(){if(this.queuedDcNetIds.length===0){this.solved=!0;return}let dcNetId=this.queuedDcNetIds.shift(),directlyConnectedPins=this.globalConnMap.getIdsConnectedToNet(dcNetId).filter(id3=>!!this.pinMap[id3]);if(directlyConnectedPins.length<=1)return;if(directlyConnectedPins.length===2){let[pin1,pin2]=directlyConnectedPins,p12=this.pinMap[pin1],p22=this.pinMap[pin2],pinPairKey=getPinPairKey([pin1,pin2]),pairDistance=Math.abs(p12.x-p22.x)+Math.abs(p12.y-p22.y);this.directConnectionPinPairKeys.has(pinPairKey)&&(pairDistance=distance2(p12,p22));let labeledConnectionRouteReason=getLabeledConnectionRouteReason({inputProblem:this.inputProblem,chipMap:this.chipMap,pins:[p12,p22]});if(pairDistance>this.maxMspPairDistance&&!labeledConnectionRouteReason||arePinsInDifferentSchematicSections(this.inputProblem,p12,p22))return;let pinIdMap2=new Map(Object.entries(this.pinMap));if(doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap:pinIdMap2,p1:p12,p2:p22}))return;let globalConnNetId=this.globalConnMap.getNetConnectedToId(pin1),userNetId=this.userNetIdByPinId[pin1]??this.userNetIdByPinId[pin2],suppressNetLabel=pairDistance>this.maxMspPairDistance&&labeledConnectionRouteReason==="overlapping-fallback-labels";this.mspConnectionPairs.push({mspPairId:`${pin1}-${pin2}`,dcConnNetId:dcNetId,globalConnNetId,userNetId,suppressNetLabel,pins:[p12,p22]});return}let pinIdMap=new Map(Object.entries(this.pinMap)),msp=getOrthogonalMinimumSpanningTree(directlyConnectedPins.map(p3=>this.pinMap[p3]).filter(Boolean),{maxDistance:this.maxMspPairDistance,forbidEdge:(a6,b6)=>arePinsInDifferentSchematicSections(this.inputProblem,a6,b6)||doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap,p1:a6,p2:b6})});for(let[pin1,pin2]of msp){let p1Obj=this.pinMap[pin1],p2Obj=this.pinMap[pin2];if(arePinsInDifferentSchematicSections(this.inputProblem,p1Obj,p2Obj)||doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap,p1:p1Obj,p2:p2Obj}))continue;let globalConnNetId=this.globalConnMap.getNetConnectedToId(pin1),userNetId=this.userNetIdByPinId[pin1]??this.userNetIdByPinId[pin2];this.mspConnectionPairs.push({mspPairId:`${pin1}-${pin2}`,dcConnNetId:dcNetId,globalConnNetId,userNetId,pins:[p1Obj,p2Obj]})}}visualize(){let graphics=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});for(let pair of this.mspConnectionPairs)graphics.lines.push({points:[{x:pair.pins[0].x,y:pair.pins[0].y},{x:pair.pins[1].x,y:pair.pins[1].y}],strokeColor:getColorFromString2(pair.mspPairId,.75)});return graphics}},getConfiguredWidth=(connections,isPortOnlyLabel2)=>{let width=connections.find(connection=>connection?.netLabelWidth!==void 0)?.netLabelWidth;return width!==void 0||!isPortOnlyLabel2?width:connections.find(connection=>connection?.anchoredNetLabelWidth!==void 0)?.anchoredNetLabelWidth},getNetLabelWidthForConnection=({inputProblem,netId,pinIds,isPortOnlyLabel:isPortOnlyLabel2})=>{if(netId){let widthByNetId=getConfiguredWidth([inputProblem.netConnections.find(connection=>connection.netId===netId),inputProblem.directConnections.find(connection=>connection.netId===netId)],isPortOnlyLabel2);if(widthByNetId!==void 0)return widthByNetId}return getConfiguredWidth([inputProblem.directConnections.find(connection=>connection.pinIds.some(pinId=>pinIds.includes(pinId))),inputProblem.netConnections.find(connection=>connection.pinIds.some(pinId=>pinIds.includes(pinId)))],isPortOnlyLabel2)};function getTextBoxBounds(textBox,padding={}){return{minX:textBox.center.x-textBox.width/2-(padding.minX??0),minY:textBox.center.y-textBox.height/2-(padding.minY??0),maxX:textBox.center.x+textBox.width/2+(padding.maxX??0),maxY:textBox.center.y+textBox.height/2+(padding.maxY??0)}}function boundsOverlap(a6,b6,eps=1e-9){return a6.minX<b6.maxX-eps&&a6.maxX>b6.minX+eps&&a6.minY<b6.maxY-eps&&a6.maxY>b6.minY+eps}function rectIntersectsAnyTextBox(bounds,inputProblem){for(let textBox of inputProblem.textBoxes??[])if(boundsOverlap(bounds,getTextBoxBounds(textBox)))return!0;return!1}var MAX_SHORT_TRACE_DISTANCE=.15,SHORT_TRACE_OVERSHOOT=MAX_SHORT_TRACE_DISTANCE/7.5,FALLBACK_ELBOW_MAX_OVERSHOOT=.2;function segmentDirection(from,to3){return to3.x>from.x?"x+":to3.x<from.x?"x-":to3.y>from.y?"y+":to3.y<from.y?"y-":null}function pathMatchesPinDirections({path,pin1,pin2}){let firstDirection=segmentDirection(path[0],path[1]),lastDirection=segmentDirection(path[path.length-1],path[path.length-2]);return firstDirection===pin1._facingDirection&&lastDirection===pin2._facingDirection}function calculateShortOrthogonalRoute(pin1,pin2){if(pin1.x===pin2.x||pin1.y===pin2.y)return null;let firstDir=pin1._facingDirection,lastDir=pin2._facingDirection,start={x:pin1.x,y:pin1.y},end={x:pin2.x,y:pin2.y},path=null;if(firstDir?.startsWith("y")&&lastDir?.startsWith("x")){let yOffset=-SHORT_TRACE_OVERSHOOT;firstDir==="y+"&&(yOffset=SHORT_TRACE_OVERSHOOT);let routeY=start.y+yOffset,routeX=(start.x+end.x)/2;path=[start,{x:start.x,y:routeY},{x:routeX,y:routeY},{x:routeX,y:end.y},end]}else if(firstDir?.startsWith("x")&&lastDir?.startsWith("y")){let xOffset=-SHORT_TRACE_OVERSHOOT;firstDir==="x+"&&(xOffset=SHORT_TRACE_OVERSHOOT);let routeX=start.x+xOffset,routeY=(start.y+end.y)/2;path=[start,{x:routeX,y:start.y},{x:routeX,y:routeY},{x:end.x,y:routeY},end]}return path&&pathMatchesPinDirections({path,pin1,pin2})?path:null}function calculateDirectShortPath(pin1,pin2){let routingDistance=Math.abs(pin1.x-pin2.x)+Math.abs(pin1.y-pin2.y);if(routingDistance>MAX_SHORT_TRACE_DISTANCE)return null;let start={x:pin1.x,y:pin1.y},end={x:pin2.x,y:pin2.y},orthogonalRoute=calculateShortOrthogonalRoute(pin1,pin2);if(orthogonalRoute)return orthogonalRoute;let candidatePaths=[];pin1.x!==pin2.x&&pin1.y!==pin2.y?candidatePaths=[[start,{x:pin2.x,y:pin1.y},end],[start,{x:pin1.x,y:pin2.y},end]]:candidatePaths=[[start,end]];for(let path of candidatePaths)if(pathMatchesPinDirections({path,pin1,pin2}))return path;return calculateElbow({x:pin1.x,y:pin1.y,facingDirection:pin1._facingDirection},{x:pin2.x,y:pin2.y,facingDirection:pin2._facingDirection},{overshoot:Math.min(FALLBACK_ELBOW_MAX_OVERSHOOT,Math.max(SHORT_TRACE_OVERSHOOT,routingDistance/4))})}var EPS=1e-9,isVertical=(a6,b6,eps=EPS)=>Math.abs(a6.x-b6.x)<eps,isHorizontal=(a6,b6,eps=EPS)=>Math.abs(a6.y-b6.y)<eps,segmentIntersectsRect=(a6,b6,r6,eps=EPS)=>{let vert=isVertical(a6,b6,eps),horz=isHorizontal(a6,b6,eps);if(!vert&&!horz)return!1;if(vert){let x6=a6.x;if(x6<r6.minX-eps||x6>r6.maxX+eps)return!1;let segMinY=Math.min(a6.y,b6.y),segMaxY=Math.max(a6.y,b6.y);return Math.min(segMaxY,r6.maxY)-Math.max(segMinY,r6.minY)>eps}else{let y2=a6.y;if(y2<r6.minY-eps||y2>r6.maxY+eps)return!1;let segMinX=Math.min(a6.x,b6.x),segMaxX=Math.max(a6.x,b6.x);return Math.min(segMaxX,r6.maxX)-Math.max(segMinX,r6.minX)>eps}},segmentOverlapsRectBoundary=(a6,b6,r6,eps=EPS)=>isVertical(a6,b6,eps)?Math.abs(a6.x-r6.minX)<=eps||Math.abs(a6.x-r6.maxX)<=eps?Math.min(Math.max(a6.y,b6.y),r6.maxY)-Math.max(Math.min(a6.y,b6.y),r6.minY)>eps:!1:isHorizontal(a6,b6,eps)&&(Math.abs(a6.y-r6.minY)<=eps||Math.abs(a6.y-r6.maxY)<=eps)?Math.min(Math.max(a6.x,b6.x),r6.maxX)-Math.max(Math.min(a6.x,b6.x),r6.minX)>eps:!1,findFirstCollision=(pts,rects,opts={})=>{for(let i6=0;i6<pts.length-1;i6++){let a6=pts[i6],b6=pts[i6+1],excluded=opts.excludeRectsForSegment?.(i6)??new Set;for(let r6 of rects)if(!excluded.has(r6)&&segmentIntersectsRect(a6,b6,r6))return{segIndex:i6,rect:r6}}return null},isPathCollidingWithObstacles=(path,obstacles)=>{for(let i6=0;i6<path.length-1;i6++)for(let obstacle of obstacles)if(segmentIntersectsRect(path[i6],path[i6+1],obstacle))return!0;return!1},EPS2=1e-9,OBSTACLE_CLEARANCE=.2,aabbFromPoints=(a6,b6)=>({minX:Math.min(a6.x,b6.x),maxX:Math.max(a6.x,b6.x),minY:Math.min(a6.y,b6.y),maxY:Math.max(a6.y,b6.y)}),midBetweenPointAndRect=(axis,p3,r6,eps=EPS2)=>axis==="x"?p3.x<r6.minX-eps?[(p3.x+r6.minX)/2]:p3.x>r6.maxX+eps?[(p3.x+r6.maxX)/2]:[r6.minX-OBSTACLE_CLEARANCE,r6.maxX+OBSTACLE_CLEARANCE]:p3.y<r6.minY-eps?[(p3.y+r6.minY)/2]:p3.y>r6.maxY+eps?[(p3.y+r6.maxY)/2]:[r6.minY-OBSTACLE_CLEARANCE,r6.maxY+OBSTACLE_CLEARANCE],candidateMidsFromSet=(axis,colliding,collisionRects,aabb,opts={})=>{let{allowOpenSideCandidates=!1,eps=EPS2}=opts,setRects=[...collisionRects];if(axis==="x"){let leftBoundaries=[aabb.minX,...setRects.map(r6=>r6.maxX)].filter(v6=>v6<colliding.minX-eps),rightBoundaries=[aabb.maxX,...setRects.map(r6=>r6.minX)].filter(v6=>v6>colliding.maxX+eps),leftNeighbor=leftBoundaries.length>0?Math.max(...leftBoundaries):void 0,rightNeighbor=rightBoundaries.length>0?Math.min(...rightBoundaries):void 0,out=[];return leftNeighbor!==void 0?out.push((leftNeighbor+colliding.minX)/2):allowOpenSideCandidates&&out.push(colliding.minX-OBSTACLE_CLEARANCE),rightNeighbor!==void 0?out.push((colliding.maxX+rightNeighbor)/2):allowOpenSideCandidates&&out.push(colliding.maxX+OBSTACLE_CLEARANCE),out}else{let bottomBoundaries=[aabb.minY,...setRects.map(r6=>r6.maxY)].filter(v6=>v6<colliding.minY-eps),topBoundaries=[aabb.maxY,...setRects.map(r6=>r6.minY)].filter(v6=>v6>colliding.maxY+eps),bottomNeighbor=bottomBoundaries.length>0?Math.max(...bottomBoundaries):void 0,topNeighbor=topBoundaries.length>0?Math.min(...topBoundaries):void 0,out=[];return bottomNeighbor!==void 0?out.push((bottomNeighbor+colliding.minY)/2):allowOpenSideCandidates&&out.push(colliding.minY-OBSTACLE_CLEARANCE),topNeighbor!==void 0?out.push((colliding.maxY+topNeighbor)/2):allowOpenSideCandidates&&out.push(colliding.maxY+OBSTACLE_CLEARANCE),out}},EPS3=1e-9,hasOnlyNonzeroOrthogonalSegments=path=>path.every((point6,index)=>{let nextPoint=path[index+1];return nextPoint?!isHorizontal(point6,nextPoint)&&!isVertical(point6,nextPoint)?!1:Math.abs(point6.x-nextPoint.x)+Math.abs(point6.y-nextPoint.y)>0:!0}),shiftSegmentOrth=(pts,segIndex,axis,newCoord,eps=EPS3)=>{if(segIndex<0||segIndex>=pts.length-1)return null;let a6=pts[segIndex],b6=pts[segIndex+1],vert=isVertical(a6,b6,eps),horz=isHorizontal(a6,b6,eps);if(!vert&&!horz||vert&&axis!=="x"||horz&&axis!=="y")return null;let out=pts.map(p3=>({...p3}));if(axis==="x"){if(Math.abs(a6.x-newCoord)<eps&&Math.abs(b6.x-newCoord)<eps)return null;out[segIndex]={...out[segIndex],x:newCoord},out[segIndex+1]={...out[segIndex+1],x:newCoord}}else{if(Math.abs(a6.y-newCoord)<eps&&Math.abs(b6.y-newCoord)<eps)return null;out[segIndex]={...out[segIndex],y:newCoord},out[segIndex+1]={...out[segIndex+1],y:newCoord}}if(segIndex-1>=0){let p3=out[segIndex-1],q5=out[segIndex];if(Math.abs(p3.x-q5.x)+Math.abs(p3.y-q5.y)<eps)return null}if(segIndex+2<=out.length-1){let p3=out[segIndex+1],q5=out[segIndex+2];if(Math.abs(p3.x-q5.x)+Math.abs(p3.y-q5.y)<eps)return null}for(let i6=0;i6<out.length-1;i6++){let u6=out[i6],v6=out[i6+1];if(!isHorizontal(u6,v6,eps)&&!isVertical(u6,v6,eps))return null}return out},pathKey=(pts,decimals=6)=>pts.map(p3=>`${p3.x.toFixed(decimals)},${p3.y.toFixed(decimals)}`).join("|"),getSegmentAxis=(start,end)=>isVertical(start,end)?"x":isHorizontal(start,end)?"y":null,generateEndpointCollisionDetours=({path,collidingSegmentIndex,obstacle})=>{if(path.length<3||path.length>4)return[];let lastSegmentIndex=path.length-2;if(collidingSegmentIndex!==0&&collidingSegmentIndex!==lastSegmentIndex)return[];let shouldReverse=collidingSegmentIndex===lastSegmentIndex,orderedPath=shouldReverse?[...path].reverse():path,[start,corner,end]=orderedPath,firstSegmentAxis=getSegmentAxis(start,corner),secondSegmentAxis=getSegmentAxis(corner,end);if(!firstSegmentAxis||!secondSegmentAxis)return[];if(firstSegmentAxis===secondSegmentAxis)return[];let escapeCoordinates=[...midBetweenPointAndRect(secondSegmentAxis,start,obstacle),...midBetweenPointAndRect(secondSegmentAxis,end,obstacle)],detourCoordinates=[...midBetweenPointAndRect(firstSegmentAxis,start,obstacle),...midBetweenPointAndRect(firstSegmentAxis,end,obstacle)],detours=[];for(let escapeCoordinate of[...new Set(escapeCoordinates)])for(let detourCoordinate of[...new Set(detourCoordinates)]){let orderedDetour=[...firstSegmentAxis==="y"?[start,{x:escapeCoordinate,y:start.y},{x:escapeCoordinate,y:detourCoordinate},{x:end.x,y:detourCoordinate},end]:[start,{x:start.x,y:escapeCoordinate},{x:detourCoordinate,y:escapeCoordinate},{x:detourCoordinate,y:end.y},end],...orderedPath.slice(3)],detour=shouldReverse?orderedDetour.reverse():orderedDetour;hasOnlyNonzeroOrthogonalSegments(detour)&&detours.push(detour)}return detours},EPS4=1e-9,DEFAULT_CLEARANCE=.2,isStrictlyBetween=(value,a6,b6)=>value>Math.min(a6,b6)+EPS4&&value<Math.max(a6,b6)-EPS4,generateInternalSegmentCollisionDetours=({path,collidingSegmentIndex,obstacle,clearance=DEFAULT_CLEARANCE})=>{if(collidingSegmentIndex<=0||collidingSegmentIndex>=path.length-2)return[];let start=path[collidingSegmentIndex],end=path[collidingSegmentIndex+1],detourPoints=[];if(isHorizontal(start,end)){let movingRight=start.x<end.x,entryX=movingRight?obstacle.minX-clearance:obstacle.maxX+clearance,exitX=movingRight?obstacle.maxX+clearance:obstacle.minX-clearance;if(!isStrictlyBetween(entryX,start.x,end.x)||!isStrictlyBetween(exitX,start.x,end.x))return[];for(let detourY of[obstacle.minY-clearance,obstacle.maxY+clearance])detourPoints.push([{x:entryX,y:start.y},{x:entryX,y:detourY},{x:exitX,y:detourY},{x:exitX,y:end.y}])}else if(isVertical(start,end)){let movingUp=start.y<end.y,entryY=movingUp?obstacle.minY-clearance:obstacle.maxY+clearance,exitY=movingUp?obstacle.maxY+clearance:obstacle.minY-clearance;if(!isStrictlyBetween(entryY,start.y,end.y)||!isStrictlyBetween(exitY,start.y,end.y))return[];for(let detourX of[obstacle.minX-clearance,obstacle.maxX+clearance])detourPoints.push([{x:start.x,y:entryY},{x:detourX,y:entryY},{x:detourX,y:exitY},{x:end.x,y:exitY}])}return detourPoints.map(points=>[...path.slice(0,collidingSegmentIndex+1),...points,...path.slice(collidingSegmentIndex+1)]).filter(hasOnlyNonzeroOrthogonalSegments)};function getInputChipBounds(chip){let halfWidth=chip.width/2,halfHeight=chip.height/2;return{minX:chip.center.x-halfWidth,maxX:chip.center.x+halfWidth,minY:chip.center.y-halfHeight,maxY:chip.center.y+halfHeight}}var MIN_ROUTABLE_OBSTACLE_GAP=.05,isTextBoxObstacle=obstacle=>obstacle.kind==="text_box",chipToRect=chip=>{let b6=getInputChipBounds(chip);return{kind:"chip",chipId:chip.chipId,...b6}},getObstacleRects=(problem,opts={})=>{let chipRects=problem.chips.map(chipToRect),textBoxRects=(problem.textBoxes??[]).map(textBox=>{let textBounds=getTextBoxBounds(textBox,opts.textBoxPadding),attachedChipBounds=chipRects.find(chip=>chip.chipId===textBox.chipId),gap=attachedChipBounds?boundsDistance(textBounds,attachedChipBounds):Number.POSITIVE_INFINITY,b6=attachedChipBounds&&gap>0&&gap<MIN_ROUTABLE_OBSTACLE_GAP?{minX:Math.min(textBounds.minX,attachedChipBounds.maxX),maxX:Math.max(textBounds.maxX,attachedChipBounds.minX),minY:Math.min(textBounds.minY,attachedChipBounds.maxY),maxY:Math.max(textBounds.maxY,attachedChipBounds.minY)}:textBounds;return{kind:"text_box",textBox,...b6}});return[...chipRects,...textBoxRects]},calculateElbowForPins=({pin1,pin2,overshoot})=>calculateElbow({x:pin1.x,y:pin1.y,facingDirection:pin1._facingDirection},{x:pin2.x,y:pin2.y,facingDirection:pin2._facingDirection},{overshoot}),pinsFaceEachOther=({pin1,pin2})=>{let xDistance=pin2.x-pin1.x,yDistance=pin2.y-pin1.y;return Math.abs(xDistance)>=Math.abs(yDistance)?xDistance>0?pin1._facingDirection==="x+"&&pin2._facingDirection==="x-":pin1._facingDirection==="x-"&&pin2._facingDirection==="x+":yDistance>0?pin1._facingDirection==="y+"&&pin2._facingDirection==="y-":pin1._facingDirection==="y-"&&pin2._facingDirection==="y+"},SchematicTraceSingleLineSolver2=class extends BaseSolver5{constructor(params){super();__publicField(this,"pins");__publicField(this,"connectionPair");__publicField(this,"inputProblem");__publicField(this,"chipMap");__publicField(this,"obstacles");__publicField(this,"textObstacles");__publicField(this,"endpointTextObstacles");__publicField(this,"aabb");__publicField(this,"baseElbow");__publicField(this,"preferExteriorDetours");__publicField(this,"solvedTracePath",null);__publicField(this,"queue",[]);__publicField(this,"visited",new Set);this.pins=params.pins,this.connectionPair=params.connectionPair,this.inputProblem=params.inputProblem,this.chipMap=params.chipMap,this.preferExteriorDetours=params.preferExteriorDetours??!0;for(let pin of this.pins)if(!pin._facingDirection){let chip=this.chipMap[pin.chipId];pin._facingDirection=getPinDirection(pin,chip)}this.obstacles=getObstacleRects(this.inputProblem,{textBoxPadding:this.getTextBoxPaddingForConnectionPair()}),this.textObstacles=new Set(this.obstacles.filter(isTextBoxObstacle));let endpointChipIds=new Set(this.pins.map(pin=>pin.chipId));this.endpointTextObstacles=new Set(this.obstacles.filter(isTextBoxObstacle).filter(obstacle=>obstacle.textBox.chipId!==void 0&&endpointChipIds.has(obstacle.textBox.chipId)));let[pin1,pin2]=this.pins,directShortPath=calculateDirectShortPath(pin1,pin2),defaultElbow=calculateElbowForPins({pin1,pin2,overshoot:.2}),routingDistance=Math.abs(pin1.x-pin2.x)+Math.abs(pin1.y-pin2.y),adaptiveElbow=calculateElbowForPins({pin1,pin2,overshoot:Math.min(.2,Math.max(.02,routingDistance/4))}),adaptiveElbowIsShorter=this.pathLength(adaptiveElbow)<this.pathLength(defaultElbow),defaultElbowBacktracks=this.pathLength(defaultElbow)>routingDistance+1e-9,shouldUseAdaptiveElbow=findFirstCollision(adaptiveElbow,this.obstacles)===null&&(pinsFaceEachOther({pin1,pin2})&&defaultElbowBacktracks&&adaptiveElbowIsShorter||findFirstCollision(defaultElbow,this.obstacles)!==null);this.baseElbow=defaultElbow,shouldUseAdaptiveElbow&&(this.baseElbow=adaptiveElbow),directShortPath&&(this.baseElbow=directShortPath),this.solvedTracePath=directShortPath,this.aabb=aabbFromPoints({x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}),this.queue.push({path:this.baseElbow,collisionRects:new Set}),this.visited.add(pathKey(this.baseElbow))}getConstructorParams(){return{chipMap:this.chipMap,pins:this.pins,connectionPair:this.connectionPair,inputProblem:this.inputProblem,preferExteriorDetours:this.preferExteriorDetours}}getTextBoxPaddingForConnectionPair(){if(!this.inputProblem.textBoxes?.length)return{};let netId=this.connectionPair?.userNetId;if(!netId)return{};let orientations=this.inputProblem.availableNetLabelOrientations[netId]??["x+","x-","y+","y-"],netLabelWidth=getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId,pinIds:this.pins.map(pin=>pin.pinId),isPortOnlyLabel:!1}),netLabelHeight=this.getNetLabelHeightForConnectionPair(netId),padding={minX:0,minY:0,maxX:0,maxY:0};for(let orientation4 of orientations){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth,netLabelHeight});orientation4==="y+"||orientation4==="y-"?(padding.minX=Math.max(padding.minX,width/2),padding.maxX=Math.max(padding.maxX,width/2),orientation4==="y+"?padding.minY=Math.max(padding.minY,height):padding.maxY=Math.max(padding.maxY,height)):(padding.minY=Math.max(padding.minY,height/2),padding.maxY=Math.max(padding.maxY,height/2),orientation4==="x+"?padding.minX=Math.max(padding.minX,width):padding.maxX=Math.max(padding.maxX,width))}return padding}getNetLabelHeightForConnectionPair(netId){let ncHeight=this.inputProblem.netConnections.find(nc3=>nc3.netId===netId)?.netLabelHeight;if(ncHeight!==void 0)return ncHeight;let pinIds=this.pins.map(p3=>p3.pinId);return this.inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>pinIds.includes(pid)))?.netLabelHeight}axisOfSegment(a6,b6){return isVertical(a6,b6)?"x":isHorizontal(a6,b6)?"y":null}pathLength(pts){let sum=0;for(let i6=0;i6<pts.length-1;i6++)sum+=Math.abs(pts[i6+1].x-pts[i6].x)+Math.abs(pts[i6+1].y-pts[i6].y);return sum}getPinBandPenalty(path){let penalty=0;for(let i6=1;i6<path.length-2;i6++){let a6=path[i6],b6=path[i6+1];(isHorizontal(a6,b6)&&a6.y>this.aabb.minY&&a6.y<this.aabb.maxY||isVertical(a6,b6)&&a6.x>this.aabb.minX&&a6.x<this.aabb.maxX)&&(penalty+=10)}return penalty}isSegmentOutsidePinBand(a6,b6){return isHorizontal(a6,b6)?a6.y<=this.aabb.minY||a6.y>=this.aabb.maxY:isVertical(a6,b6)?a6.x<=this.aabb.minX||a6.x>=this.aabb.maxX:!1}_step(){if(this.solvedTracePath){this.solved=!0;return}let state2=this.queue.shift();if(!state2){this.failed=!0,this.error="No collision-free path found";return}let{path,collisionRects}=state2,[PA3,PB2]=this.pins,collision=findFirstCollision(path,this.obstacles,{excludeRectsForSegment:segIndex2=>{let lastSegIndex2=path.length-2,excludedRects=new Set;if(segIndex2===0||segIndex2===lastSegIndex2)for(let textObstacle of this.textObstacles)excludedRects.add(textObstacle);let segmentStart=path[segIndex2],segmentEnd=path[segIndex2+1],endpointEpsilon=1e-9,segmentTouchesPin=pin=>[segmentStart,segmentEnd].some(point6=>Math.abs(point6.x-pin.x)<=endpointEpsilon&&Math.abs(point6.y-pin.y)<=endpointEpsilon);for(let pin of this.pins){if(!segmentTouchesPin(pin))continue;let endpointChipObstacle=this.obstacles.find(obstacle=>obstacle.kind==="chip"&&obstacle.chipId===pin.chipId);endpointChipObstacle&&segmentOverlapsRectBoundary(segmentStart,segmentEnd,endpointChipObstacle)&&excludedRects.add(endpointChipObstacle)}let adjacentEndpointSegIndex=segIndex2===1?2:segIndex2===lastSegIndex2-1?lastSegIndex2-2:null;if(adjacentEndpointSegIndex!==null&&adjacentEndpointSegIndex>=0&&adjacentEndpointSegIndex<lastSegIndex2&&this.isSegmentOutsidePinBand(path[adjacentEndpointSegIndex],path[adjacentEndpointSegIndex+1]))for(let textObstacle of this.endpointTextObstacles){let textBounds=getTextBoxBounds(textObstacle.textBox);segmentIntersectsRect(segmentStart,segmentEnd,textBounds)||excludedRects.add(textObstacle)}return excludedRects}});if(!collision){let first=path[0],last=path[path.length-1],EPS142=1e-9,samePoint=(p3,q5)=>Math.abs(p3.x-q5.x)<EPS142&&Math.abs(p3.y-q5.y)<EPS142;samePoint(first,{x:PA3.x,y:PA3.y})&&samePoint(last,{x:PB2.x,y:PB2.y})&&(this.solvedTracePath=path,this.solved=!0);return}let originalSegIndex=collision.segIndex,{segIndex,rect}=collision,isFirstSegment=segIndex===0,isLastSegment=segIndex===path.length-2,isEndpointChipObstacle=rect.kind==="chip"&&this.pins.some(pin=>pin.chipId===rect.chipId);if((path.length===3||path.length===4&&this.connectionPair!==void 0&&!isEndpointChipObstacle)&&(isFirstSegment||isLastSegment)){let detours=generateEndpointCollisionDetours({path,collidingSegmentIndex:segIndex,obstacle:rect}).filter(detour=>{let key=pathKey(detour);return this.visited.has(key)?!1:(this.visited.add(key),!0)}).sort((a22,b22)=>path.length===4&&this.preferExteriorDetours?this.getPinBandPenalty(a22)-this.getPinBandPenalty(b22)||this.pathLength(a22)-this.pathLength(b22):this.pathLength(a22)-this.pathLength(b22)||this.getPinBandPenalty(a22)-this.getPinBandPenalty(b22));for(let detour of detours){let nextCollisionRects=new Set(collisionRects);nextCollisionRects.add(rect),this.queue.push({path:detour,collisionRects:nextCollisionRects})}return}if(isFirstSegment){if(path.length<3)return;segIndex=1}else if(isLastSegment){if(path.length<3)return;segIndex=path.length-3}let a6=path[segIndex],b6=path[segIndex+1],axis=this.axisOfSegment(a6,b6);if(!axis)return;let candidates=[],candidateMidOptions={allowOpenSideCandidates:this.connectionPair!==void 0};if(collisionRects.size===0){let m12=midBetweenPointAndRect(axis,{x:PA3.x,y:PA3.y},rect),m22=midBetweenPointAndRect(axis,{x:PB2.x,y:PB2.y},rect),allCandidates=[...m12,...m22],uniqueCandidates=[...new Set(allCandidates)];candidates.push(...uniqueCandidates)}else{let mids=candidateMidsFromSet(axis,rect,collisionRects,this.aabb,candidateMidOptions);candidates.push(...mids)}let newStates=[],addPathCandidate=newPath=>{let key=pathKey(newPath);if(this.visited.has(key))return;this.visited.add(key);let nextSet=new Set(collisionRects);nextSet.add(rect),newStates.push({path:newPath,collisionRects:nextSet,length:this.pathLength(newPath),pinBandPenalty:this.getPinBandPenalty(newPath)})},addShiftedCandidate=(candidateSegIndex,candidateAxis,coord)=>{let newPath=shiftSegmentOrth(path,candidateSegIndex,candidateAxis,coord);newPath&&addPathCandidate(newPath)},lastSegIndex=path.length-2;if(this.connectionPair===void 0&&rect.kind==="text_box"&&this.endpointTextObstacles.has(rect)&&!collisionRects.has(rect)&&originalSegIndex>0&&originalSegIndex<lastSegIndex)for(let detour of generateInternalSegmentCollisionDetours({path,collidingSegmentIndex:originalSegIndex,obstacle:rect}))addPathCandidate(detour);for(let coord of candidates)addShiftedCandidate(segIndex,axis,coord);let adjacentSegmentIndexes=originalSegIndex===1?[2]:originalSegIndex===lastSegIndex-1?[lastSegIndex-2]:[];for(let adjacentSegIndex of adjacentSegmentIndexes){if(adjacentSegIndex<0||adjacentSegIndex>=lastSegIndex)continue;let adjacentAxis=this.axisOfSegment(path[adjacentSegIndex],path[adjacentSegIndex+1]);if(!adjacentAxis||adjacentAxis===axis)continue;let adjacentCandidates=[...midBetweenPointAndRect(adjacentAxis,{x:PA3.x,y:PA3.y},rect),...midBetweenPointAndRect(adjacentAxis,{x:PB2.x,y:PB2.y},rect)];collisionRects.size>0&&adjacentCandidates.push(...candidateMidsFromSet(adjacentAxis,rect,collisionRects,this.aabb,candidateMidOptions));for(let coord of[...new Set(adjacentCandidates)])addShiftedCandidate(adjacentSegIndex,adjacentAxis,coord)}newStates.sort((a22,b22)=>a22.length-b22.length||a22.pinBandPenalty-b22.pinBandPenalty);for(let st3 of newStates)this.queue.push({path:st3.path,collisionRects:st3.collisionRects})}visualize(){let g4=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});g4.lines.push({points:this.baseElbow,strokeColor:"red",strokeDash:"4 4"});let[pin1,pin2]=this.pins;g4.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:"blue",strokeDash:"5 5"});for(let{path}of this.queue)g4.lines.push({points:path,strokeColor:"teal",strokeDash:"2 2"});return this.solvedTracePath?g4.lines.push({points:this.solvedTracePath,strokeColor:"green"}):this.queue.length>0&&g4.lines.push({points:this.queue[0].path,strokeColor:"orange"}),g4}},shouldPreferExteriorDetours=({connectionPair,allConnectionPairs,inputProblem})=>{let[firstPin,secondPin]=connectionPair.pins;return inputProblem.netConnections.some(netConnection=>netConnection.pinIds.includes(firstPin.pinId)&&netConnection.pinIds.includes(secondPin.pinId))?!0:allConnectionPairs.some(otherPair=>{if(otherPair===connectionPair)return!1;let[otherFirstPin,otherSecondPin]=otherPair.pins;return firstPin.chipId===otherFirstPin.chipId&&secondPin.chipId===otherSecondPin.chipId?!0:firstPin.chipId===otherSecondPin.chipId&&secondPin.chipId===otherFirstPin.chipId})},SchematicTraceLinesSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"mspConnectionPairs");__publicField(this,"dcConnMap");__publicField(this,"globalConnMap");__publicField(this,"queuedConnectionPairs");__publicField(this,"chipMap");__publicField(this,"currentConnectionPair",null);__publicField(this,"solvedTracePaths",[]);__publicField(this,"failedConnectionPairs",[]);this.inputProblem=params.inputProblem,this.mspConnectionPairs=params.mspConnectionPairs,this.dcConnMap=params.dcConnMap,this.globalConnMap=params.globalConnMap,this.chipMap=params.chipMap,this.queuedConnectionPairs=[...this.mspConnectionPairs]}getConstructorParams(){return{inputProblem:this.inputProblem,chipMap:this.chipMap,mspConnectionPairs:this.mspConnectionPairs,dcConnMap:this.dcConnMap,globalConnMap:this.globalConnMap}}_step(){if(this.activeSubSolver?.solved&&(this.solvedTracePaths.push({...this.currentConnectionPair,tracePath:this.activeSubSolver.solvedTracePath,mspConnectionPairIds:[this.currentConnectionPair.mspPairId],pinIds:[this.currentConnectionPair.pins[0].pinId,this.currentConnectionPair.pins[1].pinId]}),this.activeSubSolver=null,this.currentConnectionPair=null),this.activeSubSolver?.failed&&(this.currentConnectionPair&&this.failedConnectionPairs.push({...this.currentConnectionPair,error:this.activeSubSolver.error||void 0}),this.activeSubSolver=null,this.currentConnectionPair=null),this.activeSubSolver){this.activeSubSolver.step();return}let connectionPair=this.queuedConnectionPairs.shift();if(!connectionPair){this.solved=!0;return}this.currentConnectionPair=connectionPair;let{pins}=connectionPair;this.activeSubSolver=new SchematicTraceSingleLineSolver2({inputProblem:this.inputProblem,pins,connectionPair,chipMap:this.chipMap,preferExteriorDetours:shouldPreferExteriorDetours({connectionPair,allConnectionPairs:this.mspConnectionPairs,inputProblem:this.inputProblem})})}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});for(let{mspPairId,tracePath}of this.solvedTracePaths)graphics.lines.push({points:tracePath,strokeColor:"green"});for(let pair of this.failedConnectionPairs)graphics.lines.push({points:[{x:pair.pins[0].x,y:pair.pins[0].y},{x:pair.pins[1].x,y:pair.pins[1].y}],strokeColor:"red",strokeDash:"4 2"});return graphics}},applyJogToTerminalSegment=({pts,segmentIndex:si3,offset,JOG_SIZE,EPS:EPS142=1e-6})=>{if(si3!==0&&si3!==pts.length-2)return;let start=pts[si3],end=pts[si3+1],isVertical52=Math.abs(start.x-end.x)<EPS142,isHorizontal42=Math.abs(start.y-end.y)<EPS142;if(!isVertical52&&!isHorizontal42)return;let segDir=isVertical52?end.y>start.y?1:-1:end.x>start.x?1:-1;if(pts.length===2){if(isVertical52){let jogYNearStart=start.y+segDir*JOG_SIZE,jogYNearEnd=end.y-segDir*JOG_SIZE;pts.splice(1,0,{x:start.x,y:jogYNearStart},{x:start.x+offset,y:jogYNearStart},{x:end.x+offset,y:jogYNearEnd},{x:end.x,y:jogYNearEnd})}else{let jogXNearStart=start.x+segDir*JOG_SIZE,jogXNearEnd=end.x-segDir*JOG_SIZE;pts.splice(1,0,{x:jogXNearStart,y:start.y},{x:jogXNearStart,y:start.y+offset},{x:jogXNearEnd,y:end.y+offset},{x:jogXNearEnd,y:end.y})}return}if(si3===0)if(isVertical52){let jogY=start.y+segDir*JOG_SIZE;pts.splice(1,1,{x:start.x,y:jogY},{x:start.x+offset,y:jogY},{x:end.x+offset,y:end.y})}else{let jogX=start.x+segDir*JOG_SIZE;pts.splice(1,1,{x:jogX,y:start.y},{x:jogX,y:start.y+offset},{x:end.x,y:end.y+offset})}else if(isVertical52){let jogY=end.y-segDir*JOG_SIZE;pts.splice(si3,1,{x:start.x+offset,y:start.y},{x:end.x+offset,y:jogY},{x:end.x,y:jogY})}else{let jogX=end.x-segDir*JOG_SIZE;pts.splice(si3,1,{x:start.x,y:start.y+offset},{x:jogX,y:end.y+offset},{x:jogX,y:end.y})}},EPS5=1e-6,TraceOverlapIssueSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"overlappingTraceSegments");__publicField(this,"interactionKind");__publicField(this,"traceNetIslands");__publicField(this,"traceIdsToShift");__publicField(this,"obstacleRects");__publicField(this,"SHIFT_DISTANCE",.1);__publicField(this,"correctedTraceMap",{});this.overlappingTraceSegments=params.overlappingTraceSegments,this.interactionKind=params.interactionKind,this.traceNetIslands=params.traceNetIslands,this.traceIdsToShift=params.traceIdsToShift,this.obstacleRects=getObstacleRects(params.inputProblem);for(let{connNetId,pathsWithOverlap}of this.overlappingTraceSegments)for(let{solvedTracePathIndex,traceSegmentIndex}of pathsWithOverlap){let mspPairId=this.traceNetIslands[connNetId][solvedTracePathIndex].mspPairId;this.correctedTraceMap[mspPairId]=this.traceNetIslands[connNetId][solvedTracePathIndex]}}_step(){let containsStraightPinToPinTrace=group=>group.pathsWithOverlap.some(({solvedTracePathIndex})=>this.traceNetIslands[group.connNetId][solvedTracePathIndex].tracePath.length===2),groupShouldStayInPlace=this.overlappingTraceSegments.map(group=>this.traceIdsToShift?group.pathsWithOverlap.every(({solvedTracePathIndex})=>{let path=this.traceNetIslands[group.connNetId][solvedTracePathIndex];return!this.traceIdsToShift.has(path.mspPairId)}):containsStraightPinToPinTrace(group)),someGroupCanShift=groupShouldStayInPlace.some(shouldStay=>!shouldStay),getSeparationOffsets=firstDirection=>this.overlappingTraceSegments.map((group,groupIndex)=>{if(someGroupCanShift&&groupShouldStayInPlace[groupIndex])return 0;let n3=Math.floor(groupIndex/2)+1,direction2=groupIndex%2===0?firstDirection:-firstDirection;return this.getObstacleAwareOffset({group,offset:direction2*n3*this.SHIFT_DISTANCE})}),establishedOffsets=getSeparationOffsets(-1);if(this.interactionKind==="overlap"&&this.overlappingTraceSegments.some(group=>group.pathsWithOverlap.length>1)){this.correctedTraceMap=this.applyOffsets(establishedOffsets),this.solved=!0;return}let offsetCandidates=this.interactionKind==="overlap"?[establishedOffsets,getSeparationOffsets(1)]:[];if(this.interactionKind==="point_contact"){let movableGroupIndexes=this.overlappingTraceSegments.map((_6,groupIndex)=>groupIndex).filter(groupIndex=>!someGroupCanShift||!groupShouldStayInPlace[groupIndex]).reverse();for(let groupIndex of movableGroupIndexes){let group=this.overlappingTraceSegments[groupIndex];for(let direction2 of[-1,1]){let offsets=this.overlappingTraceSegments.map(()=>0);offsets[groupIndex]=this.getObstacleAwareOffset({group,offset:direction2*this.SHIFT_DISTANCE}),offsetCandidates.push(offsets)}}}let candidates=offsetCandidates.map(offsets=>{let correctedTraceMap=this.applyOffsets(offsets);return{correctedTraceMap,intersectionCount:this.countDifferentNetIntersections(correctedTraceMap),totalDisplacement:offsets.reduce((total,offset)=>total+Math.abs(offset),0)}});candidates.sort((a6,b6)=>a6.intersectionCount-b6.intersectionCount||a6.totalDisplacement-b6.totalDisplacement),this.correctedTraceMap=candidates[0].correctedTraceMap,this.solved=!0}applyOffsets(offsets){let correctedTraceMap={...this.correctedTraceMap},eq2=(a6,b6)=>Math.abs(a6-b6)<EPS5,samePoint=(p3,q5)=>!!p3&&!!q5&&eq2(p3.x,q5.x)&&eq2(p3.y,q5.y);return this.overlappingTraceSegments.forEach((group,groupIndex)=>{let offset=offsets[groupIndex];if(offset===0)return;let byPath=new Map;for(let loc of group.pathsWithOverlap)byPath.has(loc.solvedTracePathIndex)||byPath.set(loc.solvedTracePathIndex,new Set),byPath.get(loc.solvedTracePathIndex).add(loc.traceSegmentIndex);for(let[pathIdx,segIdxSet]of byPath){let original=this.traceNetIslands[group.connNetId][pathIdx],current3=correctedTraceMap[original.mspPairId]??original,pts=current3.tracePath.map(p3=>({...p3})),segIdxsRev=Array.from(segIdxSet).sort((a6,b6)=>a6-b6).reverse(),segmentAxes=new Map;for(let si3 of segIdxsRev){let start=pts[si3],end=pts[si3+1];!start||!end||(Math.abs(start.x-end.x)<EPS5?segmentAxes.set(si3,"vertical"):Math.abs(start.y-end.y)<EPS5&&segmentAxes.set(si3,"horizontal"))}let shiftedXPointIndexes=new Set,shiftedYPointIndexes=new Set,JOG_SIZE=this.SHIFT_DISTANCE;for(let si3 of segIdxsRev)if(!(si3<0||si3>=pts.length-1))if(si3===0||si3===pts.length-2)applyJogToTerminalSegment({pts,segmentIndex:si3,offset,JOG_SIZE,EPS:EPS5});else{let start=pts[si3],end=pts[si3+1],axis=segmentAxes.get(si3);axis==="vertical"?(shiftedXPointIndexes.has(si3)||(start.x+=offset,shiftedXPointIndexes.add(si3)),shiftedXPointIndexes.has(si3+1)||(end.x+=offset,shiftedXPointIndexes.add(si3+1))):axis==="horizontal"&&(shiftedYPointIndexes.has(si3)||(start.y+=offset,shiftedYPointIndexes.add(si3)),shiftedYPointIndexes.has(si3+1)||(end.y+=offset,shiftedYPointIndexes.add(si3+1)))}let cleaned=[];for(let p3 of pts)(cleaned.length===0||!samePoint(cleaned[cleaned.length-1],p3))&&cleaned.push(p3);correctedTraceMap[original.mspPairId]={...current3,tracePath:cleaned}}}),correctedTraceMap}countDifferentNetIntersections(correctedTraceMap){let traces=Object.values(this.traceNetIslands).flatMap(island=>island.map(trace=>correctedTraceMap[trace.mspPairId]??trace)),intersectionCount=0;for(let traceIndex=0;traceIndex<traces.length;traceIndex++){let trace=traces[traceIndex];for(let otherTraceIndex=traceIndex+1;otherTraceIndex<traces.length;otherTraceIndex++){let otherTrace=traces[otherTraceIndex];if(trace.globalConnNetId!==otherTrace.globalConnNetId)for(let segmentIndex=0;segmentIndex<trace.tracePath.length-1;segmentIndex++)for(let otherSegmentIndex=0;otherSegmentIndex<otherTrace.tracePath.length-1;otherSegmentIndex++)doSegmentsIntersect(trace.tracePath[segmentIndex],trace.tracePath[segmentIndex+1],otherTrace.tracePath[otherSegmentIndex],otherTrace.tracePath[otherSegmentIndex+1])&&intersectionCount++}}return intersectionCount}getObstacleAwareOffset({group,offset}){let blockingCollisions=this.getBlockingCollisions({group,offset});if(blockingCollisions.length===0)return offset;let crossesThroughObstacle=candidateOffset=>blockingCollisions.some(({start,isVertical:isVertical52,obstacle})=>{let orig,min,max2;isVertical52?(orig=start.x,min=obstacle.minX,max2=obstacle.maxX):(orig=start.y,min=obstacle.minY,max2=obstacle.maxY);let next2=orig+candidateOffset;return orig<=min+EPS5&&next2>=max2-EPS5||orig>=max2-EPS5&&next2<=min+EPS5}),edges=blockingCollisions.map(({start,isVertical:isVertical52,obstacle})=>isVertical52?{coord:start.x,lowEdge:obstacle.minX,highEdge:obstacle.maxX}:{coord:start.y,lowEdge:obstacle.minY,highEdge:obstacle.maxY}),bestCandidate=clearance=>edges.flatMap(({coord,lowEdge,highEdge})=>[lowEdge-coord-clearance,highEdge-coord+clearance]).filter(candidateOffset=>!crossesThroughObstacle(candidateOffset)).filter(candidateOffset=>this.getBlockingCollisions({group,offset:candidateOffset}).length===0).sort((a6,b6)=>Math.abs(a6-offset)-Math.abs(b6-offset))[0],EDGE_MARGIN=this.SHIFT_DISTANCE/10;return bestCandidate(this.SHIFT_DISTANCE)??bestCandidate(EDGE_MARGIN)??offset}getBlockingCollisions({group,offset}){let blockingCollisions=[];for(let{solvedTracePathIndex,traceSegmentIndex}of group.pathsWithOverlap){let trace=this.traceNetIslands[group.connNetId][solvedTracePathIndex],start=trace.tracePath[traceSegmentIndex],end=trace.tracePath[traceSegmentIndex+1];if(!start||!end)continue;let isVertical52=Math.abs(start.x-end.x)<EPS5,isHorizontal42=Math.abs(start.y-end.y)<EPS5;if(!isVertical52&&!isHorizontal42)continue;let shiftedSegment=isVertical52?[{...start,x:start.x+offset},{...end,x:end.x+offset}]:[{...start,y:start.y+offset},{...end,y:end.y+offset}],collision=findFirstCollision(shiftedSegment,this.obstacleRects);collision&&blockingCollisions.push({start,isVertical:isVertical52,obstacle:collision.rect})}return blockingCollisions}visualize(){let graphics={lines:[],points:[],rects:[],circles:[]};for(let group of this.overlappingTraceSegments)for(let{solvedTracePathIndex,traceSegmentIndex}of group.pathsWithOverlap){let path=this.traceNetIslands[group.connNetId][solvedTracePathIndex],segStart=path.tracePath[traceSegmentIndex],segEnd=path.tracePath[traceSegmentIndex+1];graphics.lines.push({points:[segStart,segEnd],strokeColor:"red"})}for(let trace of Object.values(this.correctedTraceMap))graphics.lines.push({points:trace.tracePath,strokeColor:"blue",strokeDash:"4 2"});return graphics}},TRACE_STATE_POSITION_EPSILON=1e-6,TraceOverlapShiftSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTracePaths");__publicField(this,"globalConnMap");__publicField(this,"traceIdsToShift");__publicField(this,"traceNetIslands",{});__publicField(this,"correctedTraceMap",{});__publicField(this,"recentTraceStates",[]);__publicField(this,"cleanupPhase",null);this.inputProblem=params.inputProblem,this.inputTracePaths=params.inputTracePaths,this.globalConnMap=params.globalConnMap,this.traceIdsToShift=params.traceIdsToShift;for(let tracePath of this.inputTracePaths){let{mspPairId}=tracePath;this.correctedTraceMap[mspPairId]=tracePath}this.rememberTraceState(this.correctedTraceMap),this.traceNetIslands=this.computeTraceNetIslands()}getConstructorParams(){return{inputProblem:this.inputProblem,inputTracePaths:this.inputTracePaths,globalConnMap:this.globalConnMap,traceIdsToShift:this.traceIdsToShift}}computeTraceNetIslands(){let islands={};for(let original of this.inputTracePaths){let path=this.correctedTraceMap[original.mspPairId]??original,key=path.globalConnNetId;islands[key]||(islands[key]=[]),islands[key].push(path)}return islands}findNextOverlapIssue(){let netIds=Object.keys(this.traceNetIslands);for(let i6=0;i6<netIds.length;i6++)for(let j6=i6+1;j6<netIds.length;j6++){let netA=netIds[i6],netB=netIds[j6],pathsA=this.traceNetIslands[netA]||[],pathsB=this.traceNetIslands[netB]||[],overlapsA=[],overlapsB=[],pointContacts=[],seenA=new Set,seenB=new Set,getRangeOverlap1D=(a12,a22,b12,b22)=>{let minA=Math.min(a12,a22),maxA=Math.max(a12,a22),minB=Math.min(b12,b22),maxB=Math.max(b12,b22);return Math.min(maxA,maxB)-Math.max(minA,minB)},recordCollinearInteraction=({pathAIndex,segmentAIndex,pathBIndex,segmentBIndex,rangeOverlap})=>{if(rangeOverlap>.002){let keyA=`${pathAIndex}:${segmentAIndex}`,keyB=`${pathBIndex}:${segmentBIndex}`;seenA.has(keyA)||(overlapsA.push({solvedTracePathIndex:pathAIndex,traceSegmentIndex:segmentAIndex}),seenA.add(keyA)),seenB.has(keyB)||(overlapsB.push({solvedTracePathIndex:pathBIndex,traceSegmentIndex:segmentBIndex}),seenB.add(keyB));return}if(rangeOverlap<-.002)return;let pathA=pathsA[pathAIndex].tracePath,pathB=pathsB[pathBIndex].tracePath,segmentAStart=pathA[segmentAIndex],segmentAEnd=pathA[segmentAIndex+1],segmentBStart=pathB[segmentBIndex],segmentBEnd=pathB[segmentBIndex+1];segmentAIndex===0||segmentAIndex===pathA.length-2||segmentBIndex===0||segmentBIndex===pathB.length-2||pointContacts.push({pathAIndex,segmentAIndex,pathBIndex,segmentBIndex,combinedLength:Math.abs(segmentAStart.x-segmentAEnd.x)+Math.abs(segmentAStart.y-segmentAEnd.y)+Math.abs(segmentBStart.x-segmentBEnd.x)+Math.abs(segmentBStart.y-segmentBEnd.y)})};for(let pa3=0;pa3<pathsA.length;pa3++){let pathA=pathsA[pa3],ptsA=pathA.tracePath;for(let sa3=0;sa3<ptsA.length-1;sa3++){let a12=ptsA[sa3],a22=ptsA[sa3+1],aVert=Math.abs(a12.x-a22.x)<.002,aHorz=Math.abs(a12.y-a22.y)<.002;if(!(!aVert&&!aHorz))for(let pb2=0;pb2<pathsB.length;pb2++){let pathB=pathsB[pb2];if(this.traceIdsToShift&&!this.traceIdsToShift.has(pathA.mspPairId)&&!this.traceIdsToShift.has(pathB.mspPairId))continue;let ptsB=pathB.tracePath;for(let sb2=0;sb2<ptsB.length-1;sb2++){let b12=ptsB[sb2],b22=ptsB[sb2+1],bVert=Math.abs(b12.x-b22.x)<.002,bHorz=Math.abs(b12.y-b22.y)<.002;!bVert&&!bHorz||(aVert&&bVert?Math.abs(a12.x-b12.x)<.002&&recordCollinearInteraction({pathAIndex:pa3,segmentAIndex:sa3,pathBIndex:pb2,segmentBIndex:sb2,rangeOverlap:getRangeOverlap1D(a12.y,a22.y,b12.y,b22.y)}):aHorz&&bHorz&&Math.abs(a12.y-b12.y)<.002&&recordCollinearInteraction({pathAIndex:pa3,segmentAIndex:sa3,pathBIndex:pb2,segmentBIndex:sb2,rangeOverlap:getRangeOverlap1D(a12.x,a22.x,b12.x,b22.x)}))}}}}if(overlapsA.length>0&&overlapsB.length>0)return{interactionKind:"overlap",overlappingTraceSegments:[{connNetId:netA,pathsWithOverlap:overlapsA},{connNetId:netB,pathsWithOverlap:overlapsB}]};let bestPointContact=pointContacts.sort((a6,b6)=>b6.combinedLength-a6.combinedLength)[0];if(bestPointContact)return{interactionKind:"point_contact",overlappingTraceSegments:[{connNetId:netA,pathsWithOverlap:[{solvedTracePathIndex:bestPointContact.pathAIndex,traceSegmentIndex:bestPointContact.segmentAIndex}]},{connNetId:netB,pathsWithOverlap:[{solvedTracePathIndex:bestPointContact.pathBIndex,traceSegmentIndex:bestPointContact.segmentBIndex}]}]}}return null}findNextDiagonalSegment(){for(let mspPairId in this.correctedTraceMap){let tracePath=this.correctedTraceMap[mspPairId].tracePath;for(let i6=0;i6<tracePath.length-1;i6++){let p12=tracePath[i6],p22=tracePath[i6+1],isHorizontal42=Math.abs(p12.y-p22.y)<.002,isVertical52=Math.abs(p12.x-p22.x)<.002;if(!isHorizontal42&&!isVertical52)return{mspPairId,tracePath,i:i6,p1:p12,p2:p22}}}return null}findAndFixNextDiagonalSegment(){let diagonalInfo=this.findNextDiagonalSegment();if(!diagonalInfo)return!1;let{mspPairId,tracePath,i:i6,p1:p12,p2:p22}=diagonalInfo,EPS142=.002,p03=i6>0?tracePath[i6-1]:null,p3=i6+2<tracePath.length?tracePath[i6+2]:null,prevIsVertical=p03?Math.abs(p03.x-p12.x)<EPS142:!1,prevIsHorizontal=p03?Math.abs(p03.y-p12.y)<EPS142:!1,nextIsVertical=p3?Math.abs(p22.x-p3.x)<EPS142:!1,nextIsHorizontal=p3?Math.abs(p22.y-p3.y)<EPS142:!1,elbow1={x:p12.x,y:p22.y},elbow2={x:p22.x,y:p12.y},score1=0;prevIsVertical&&score1++,nextIsHorizontal&&score1++;let score2=0;prevIsHorizontal&&score2++,nextIsVertical&&score2++;let elbowPoint=score1<score2?elbow1:elbow2;return tracePath.splice(i6+1,0,elbowPoint),!0}_step(){if(this.activeSubSolver?.solved){let nextTraceState={...this.correctedTraceMap,...this.activeSubSolver.correctedTraceMap};if(this.returnsToPreviousTraceState(nextTraceState)){this.activeSubSolver=null,this.solved=!0;return}this.correctedTraceMap=nextTraceState,this.rememberTraceState(nextTraceState),this.activeSubSolver=null,this.traceNetIslands=this.computeTraceNetIslands()}if(this.activeSubSolver){this.activeSubSolver.step();return}let overlapIssue=this.findNextOverlapIssue();if(overlapIssue===null){if(this.cleanupPhase===null&&(this.cleanupPhase="diagonals"),this.cleanupPhase==="diagonals"){this.findAndFixNextDiagonalSegment()||(this.cleanupPhase="done",this.solved=!0);return}this.solved=!0;return}let{interactionKind,overlappingTraceSegments}=overlapIssue;this.activeSubSolver=new TraceOverlapIssueSolver({inputProblem:this.inputProblem,interactionKind,overlappingTraceSegments,traceNetIslands:this.traceNetIslands,traceIdsToShift:this.traceIdsToShift})}rememberTraceState(traceState){this.recentTraceStates.push({...traceState}),this.recentTraceStates.length>2&&this.recentTraceStates.shift()}returnsToPreviousTraceState(candidateTraceState){if(this.recentTraceStates.length<2)return!1;let previousTraceState=this.recentTraceStates[0],traceIds=Object.keys(candidateTraceState);if(traceIds.length!==Object.keys(previousTraceState).length)return!1;for(let traceId of traceIds){let candidatePath=candidateTraceState[traceId],previousPath=previousTraceState[traceId];if(!candidatePath||!previousPath||candidatePath.tracePath.length!==previousPath.tracePath.length)return!1;for(let i6=0;i6<candidatePath.tracePath.length;i6++){let candidatePoint=candidatePath.tracePath[i6],previousPoint=previousPath.tracePath[i6];if(Math.abs(candidatePoint.x-previousPoint.x)>TRACE_STATE_POSITION_EPSILON||Math.abs(candidatePoint.y-previousPoint.y)>TRACE_STATE_POSITION_EPSILON)return!1}}return!0}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);graphics.circles=graphics.circles||[];for(let trace of Object.values(this.correctedTraceMap))graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});if(this.cleanupPhase==="diagonals"){let diagonalInfo=this.findNextDiagonalSegment();diagonalInfo&&graphics.lines.push({points:[diagonalInfo.p1,diagonalInfo.p2],strokeColor:"red",strokeWidth:.05})}return graphics}},ChipObstacleSpatialIndex=class{constructor(chips){__publicField(this,"chips");__publicField(this,"spatialIndex");__publicField(this,"spatialIndexIdToChip");this.chips=chips.map(chip=>({...chip,bounds:getInputChipBounds(chip),spatialIndexId:null})),this.spatialIndexIdToChip=new Map,this.spatialIndex=new Flatbush(chips.length);for(let chip of this.chips)chip.spatialIndexId=this.spatialIndex.add(chip.bounds.minX,chip.bounds.minY,chip.bounds.maxX,chip.bounds.maxY),this.spatialIndexIdToChip.set(chip.spatialIndexId,chip);this.spatialIndex.finish()}getChipsInBounds(bounds){return this.spatialIndex.search(bounds.minX,bounds.minY,bounds.maxX,bounds.maxY).map(id3=>this.spatialIndexIdToChip.get(id3))}doesOrthogonalLineIntersectChip(line2,opts={}){let excludeChipIds=opts.excludeChipIds??[],[p12,p22]=line2,{x:x12,y:y12}=p12,{x:x22,y:y2}=p22;return this.getChipsInBounds({minX:Math.min(x12,x22),minY:Math.min(y12,y2),maxX:Math.max(x12,x22),maxY:Math.max(y12,y2)}).filter(chip=>!excludeChipIds.includes(chip.chipId)).length>0}};function segmentIntersectsRect2(p12,p22,rect,EPS142=1e-9){let isVert=Math.abs(p12.x-p22.x)<EPS142,isHorz=Math.abs(p12.y-p22.y)<EPS142;if(!isVert&&!isHorz)return!1;if(isVert){let x6=p12.x;if(x6<rect.minX-EPS142||x6>rect.maxX+EPS142)return!1;let segMinY=Math.min(p12.y,p22.y),segMaxY=Math.max(p12.y,p22.y);return Math.min(segMaxY,rect.maxY)-Math.max(segMinY,rect.minY)>EPS142}else{let y2=p12.y;if(y2<rect.minY-EPS142||y2>rect.maxY+EPS142)return!1;let segMinX=Math.min(p12.x,p22.x),segMaxX=Math.max(p12.x,p22.x);return Math.min(segMaxX,rect.maxX)-Math.max(segMinX,rect.minX)>EPS142}}function rectIntersectsAnyTrace(bounds,inputTraceMap,hostPathId,hostSegIndex){for(let[pairId,solved]of Object.entries(inputTraceMap)){let pts=solved.tracePath;for(let i6=0;i6<pts.length-1;i6++)if(!(pairId===hostPathId&&i6===hostSegIndex)&&segmentIntersectsRect2(pts[i6],pts[i6+1],bounds))return{hasIntersection:!0,mspPairId:pairId,segIndex:i6}}return{hasIntersection:!1}}function lengthOfTrace(path){let sum=0,pts=path.tracePath;for(let i6=0;i6<pts.length-1;i6++)sum+=Math.abs(pts[i6+1].x-pts[i6].x)+Math.abs(pts[i6+1].y-pts[i6].y);return sum}function chooseHostTraceForGroup(params){let{inputProblem,inputTraceMap,globalConnNetId,fallbackTrace,mspConnectionPairIds}=params,chipsById=Object.fromEntries(inputProblem.chips.map(c3=>[c3.chipId,c3])),groupTraces=Object.values(inputTraceMap).filter(t53=>t53.globalConnNetId===globalConnNetId);if(mspConnectionPairIds&&mspConnectionPairIds.length>0){let idSet=new Set(mspConnectionPairIds);groupTraces=groupTraces.filter(t53=>t53.mspConnectionPairIds.some(id3=>idSet.has(id3)))}let chipIdsInGroup=new Set;for(let t53 of groupTraces)chipIdsInGroup.add(t53.pins[0].chipId),chipIdsInGroup.add(t53.pins[1].chipId);let largestChipId=null,largestPinCount=-1;for(let id3 of chipIdsInGroup){let count=chipsById[id3]?.pins?.length??0;count>largestPinCount&&(largestPinCount=count,largestChipId=id3)}let hostCandidates=largestChipId==null?[]:groupTraces.filter(t53=>t53.pins[0].chipId===largestChipId||t53.pins[1].chipId===largestChipId);return hostCandidates.length>0?hostCandidates.reduce((a6,b6)=>lengthOfTrace(a6)>=lengthOfTrace(b6)?a6:b6):fallbackTrace}function anchorsForSegment(a6,b6){return[{x:a6.x,y:a6.y},{x:(a6.x+b6.x)/2,y:(a6.y+b6.y)/2},{x:b6.x,y:b6.y}]}function solveNetLabelPlacementForPortOnlyPin(params){let{inputProblem,inputTraceMap,chipObstacleSpatialIndex,overlappingSameNetTraceGroup,availableOrientations,netLabelWidth,netLabelHeight}=params,pinId=overlappingSameNetTraceGroup.portOnlyPinId;if(!pinId)return{placement:null,testedCandidates:[],error:"No portOnlyPinId provided"};let pin=null,pinFacingDirection=null;for(let chip of inputProblem.chips){let p3=chip.pins.find(pp3=>pp3.pinId===pinId);if(p3){pin={x:p3.x,y:p3.y},pinFacingDirection=p3._facingDirection||getPinDirection(p3,chip);break}}if(!pin||!pinFacingDirection)return{placement:null,testedCandidates:[],error:`Port-only pin not found: ${pinId}`};let orientations=availableOrientations.length>0?availableOrientations:["x+","x-","y+","y-"],anchor={x:pin.x,y:pin.y},outwardOf=o6=>o6==="x+"?{x:1,y:0}:o6==="x-"?{x:-1,y:0}:o6==="y+"?{x:0,y:1}:{x:0,y:-1},testedCandidates=[];for(let orientation4 of orientations){let{width:width2,height:height2}=getDimsForOrientation({orientation:orientation4,netLabelWidth,netLabelHeight}),baseCenter2=getCenterFromAnchor(anchor,orientation4,width2,height2),outward2=outwardOf(orientation4),offset2=.001,center2={x:baseCenter2.x+outward2.x*offset2,y:baseCenter2.y+outward2.y*offset2},bounds=getRectBounds(center2,width2,height2);if(chipObstacleSpatialIndex.getChipsInBounds(bounds).length>0){testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"chip-collision",hostSegIndex:-1});continue}if(rectIntersectsAnyTextBox(bounds,inputProblem)){testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"text-collision",hostSegIndex:-1});continue}if(rectIntersectsAnyTrace(bounds,inputTraceMap,"",-1).hasIntersection){testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"trace-collision",hostSegIndex:-1});continue}return testedCandidates.push({center:center2,width:width2,height:height2,bounds,anchor,orientation:orientation4,status:"ok",hostSegIndex:-1}),{placement:{globalConnNetId:overlappingSameNetTraceGroup.globalConnNetId,dcConnNetId:void 0,netId:overlappingSameNetTraceGroup.netId,netLabelText:overlappingSameNetTraceGroup.netLabelText,mspConnectionPairIds:[],pinIds:[pinId],orientation:orientation4,anchorPoint:anchor,width:width2,height:height2,center:center2},testedCandidates}}let fallbackOrientation=pinFacingDirection,{width,height}=getDimsForOrientation({orientation:fallbackOrientation,netLabelWidth}),baseCenter=getCenterFromAnchor(anchor,fallbackOrientation,width,height),outward=outwardOf(fallbackOrientation),offset=.001,fallbackCenter={x:baseCenter.x+outward.x*offset,y:baseCenter.y+outward.y*offset};return{placement:{globalConnNetId:overlappingSameNetTraceGroup.globalConnNetId,dcConnNetId:void 0,netId:overlappingSameNetTraceGroup.netId,netLabelText:overlappingSameNetTraceGroup.netLabelText,mspConnectionPairIds:[],pinIds:[pinId],orientation:fallbackOrientation,anchorPoint:anchor,width,height,center:fallbackCenter},testedCandidates}}function visualizeSingleNetLabelPlacementSolver(solver){let graphics=visualizeInputProblem2(solver.inputProblem),groupId=solver.overlappingSameNetTraceGroup.globalConnNetId,host=chooseHostTraceForGroup({inputProblem:solver.inputProblem,inputTraceMap:solver.inputTraceMap,globalConnNetId:groupId,fallbackTrace:solver.overlappingSameNetTraceGroup.overlappingTraces}),groupStroke=getColorFromString2(groupId,.9),groupFill=getColorFromString2(groupId,.5);for(let trace of Object.values(solver.inputTraceMap)){let isHost=host?trace.mspPairId===host.mspPairId:!1;graphics.lines.push({points:trace.tracePath})}for(let c3 of solver.testedCandidates){let fill=c3.status==="ok"?"rgba(0, 180, 0, 0.25)":c3.status==="chip-collision"?"rgba(220, 0, 0, 0.25)":c3.status==="trace-collision"?"rgba(220, 140, 0, 0.25)":c3.status==="text-collision"?"rgba(160, 0, 220, 0.2)":"rgba(120, 120, 120, 0.15)",stroke=c3.status==="ok"?"green":c3.status==="chip-collision"?"red":c3.status==="trace-collision"?"orange":c3.status==="text-collision"?"purple":"gray",candidateLabel=c3.status==="ok"?"status: ok(valid net label candidate)":c3.status==="chip-collision"?"status: chip-collision":c3.status==="trace-collision"?"status: trace-collision":c3.status==="text-collision"?"status: text-collision":"status: parallel-to-segment";graphics.rects.push({center:{x:(c3.bounds.minX+c3.bounds.maxX)/2,y:(c3.bounds.minY+c3.bounds.maxY)/2},width:c3.width,height:c3.height,fill,strokeColor:stroke,label:`${candidateLabel}
645
645
  orientation: ${c3.orientation}`}),graphics.points.push({x:c3.anchor.x,y:c3.anchor.y,color:stroke,label:`anchor
646
646
  orientation: ${c3.orientation}`})}if(solver.netLabelPlacement){let p3=solver.netLabelPlacement;graphics.rects.push({center:p3.center,width:p3.width,height:p3.height,fill:"rgba(0, 128, 255, 0.35)",strokeColor:"blue",label:`netId: ${p3.netId}
647
647
  globalConnNetId: ${p3.globalConnNetId}`}),graphics.points.push({x:p3.anchorPoint.x,y:p3.anchorPoint.y,color:"blue",label:`anchor
648
648
  orientation: ${p3.orientation}`})}return graphics}var SingleNetLabelPlacementSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTraceMap");__publicField(this,"overlappingSameNetTraceGroup");__publicField(this,"availableOrientations");__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"netLabelWidth");__publicField(this,"netLabelHeight");__publicField(this,"netLabelPlacement",null);__publicField(this,"testedCandidates",[]);this.inputProblem=params.inputProblem,this.inputTraceMap=params.inputTraceMap,this.overlappingSameNetTraceGroup=params.overlappingSameNetTraceGroup,this.availableOrientations=params.availableOrientations,this.netLabelWidth=params.netLabelWidth,this.netLabelHeight=params.netLabelHeight,this.chipObstacleSpatialIndex=params.inputProblem._chipObstacleSpatialIndex??new ChipObstacleSpatialIndex(params.inputProblem.chips)}getConstructorParams(){return{inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,overlappingSameNetTraceGroup:this.overlappingSameNetTraceGroup,availableOrientations:this.availableOrientations,netLabelWidth:this.netLabelWidth,netLabelHeight:this.netLabelHeight}}_step(){if(this.netLabelPlacement){this.solved=!0;return}if(this.overlappingSameNetTraceGroup.portOnlyPinId){let res2=solveNetLabelPlacementForPortOnlyPin({inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,chipObstacleSpatialIndex:this.chipObstacleSpatialIndex,overlappingSameNetTraceGroup:this.overlappingSameNetTraceGroup,availableOrientations:this.availableOrientations,netLabelWidth:this.netLabelWidth,netLabelHeight:this.netLabelHeight});if(this.testedCandidates.push(...res2.testedCandidates),res2.placement){this.netLabelPlacement=res2.placement,this.solved=!0;return}this.failed=!0,this.error=res2.error??"Could not place net label at port without collisions";return}let groupId=this.overlappingSameNetTraceGroup.globalConnNetId,host=chooseHostTraceForGroup({inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,globalConnNetId:groupId,fallbackTrace:this.overlappingSameNetTraceGroup.overlappingTraces,mspConnectionPairIds:this.overlappingSameNetTraceGroup.mspConnectionPairIds});if(!host){this.failed=!0,this.error="No host trace found for net label placement";return}let traceIdSet=new Set(this.overlappingSameNetTraceGroup.mspConnectionPairIds??[]),tracesToScanBase=Object.values(this.inputTraceMap).filter(t53=>t53.globalConnNetId===groupId&&(traceIdSet.size===0||t53.mspConnectionPairIds.some(id3=>traceIdSet.has(id3)))),tracesToScan=this.availableOrientations.length===1?[host,...tracesToScanBase.filter(t53=>t53.mspPairId!==host.mspPairId)]:[host],orientations=this.availableOrientations.length>0?this.availableOrientations:["x+","x-","y+","y-"],singleOrientationMode=this.availableOrientations.length===1,scoreFor=(orientation4,anchor)=>{switch(orientation4){case"y+":return anchor.y;case"y-":return-anchor.y;case"x+":return anchor.x;case"x-":return-anchor.x}},bestCandidate=null,bestScore=-1/0,EPS142=1e-6;for(let curr of tracesToScan){let pts=curr.tracePath.slice();for(let si3=0;si3<pts.length-1;si3++){let a6=pts[si3],b6=pts[si3+1],isH=Math.abs(a6.y-b6.y)<EPS142,isV=Math.abs(a6.x-b6.x)<EPS142;if(!isH&&!isV)continue;let segmentAllowed=isH?["y+","y-"]:["x+","x-"],candidateOrients=orientations.filter(o6=>segmentAllowed.includes(o6));if(candidateOrients.length===0)continue;let anchors=anchorsForSegment(a6,b6);for(let anchor of anchors)for(let orientation4 of candidateOrients){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:this.netLabelWidth,netLabelHeight:this.netLabelHeight}),center2=getCenterFromAnchor(anchor,orientation4,width,height),outward=orientation4==="x+"?{x:1,y:0}:orientation4==="x-"?{x:-1,y:0}:orientation4==="y+"?{x:0,y:1}:{x:0,y:-1},offset=1e-4,testCenter={x:center2.x+outward.x*offset,y:center2.y+outward.y*offset},bounds=getRectBounds(testCenter,width,height);if(this.chipObstacleSpatialIndex.getChipsInBounds(bounds).length>0){this.testedCandidates.push({center:testCenter,width,height,bounds,anchor,orientation:orientation4,status:"chip-collision",hostSegIndex:si3});continue}if(rectIntersectsAnyTextBox(bounds,this.inputProblem)){this.testedCandidates.push({center:testCenter,width,height,bounds,anchor,orientation:orientation4,status:"text-collision",hostSegIndex:si3});continue}if(rectIntersectsAnyTrace(bounds,this.inputTraceMap,curr.mspPairId,si3).hasIntersection){this.testedCandidates.push({center:testCenter,width,height,bounds,anchor,orientation:orientation4,status:"trace-collision",hostSegIndex:si3});continue}if(this.testedCandidates.push({center:testCenter,width,height,bounds,anchor,orientation:orientation4,status:"ok",hostSegIndex:si3}),singleOrientationMode){let s6=scoreFor(orientation4,anchor);s6>bestScore+1e-9&&(bestScore=s6,bestCandidate={anchor,orientation:orientation4,width,height,center:center2,hostSegIndex:si3,dcConnNetId:curr.dcConnNetId,mspPairId:curr.mspPairId,pinIds:[curr.pins[0].pinId,curr.pins[1].pinId]});continue}this.netLabelPlacement={globalConnNetId:this.overlappingSameNetTraceGroup.globalConnNetId,dcConnNetId:curr.dcConnNetId,netId:this.overlappingSameNetTraceGroup.netId,netLabelText:this.overlappingSameNetTraceGroup.netLabelText,mspConnectionPairIds:[curr.mspPairId],pinIds:[curr.pins[0].pinId,curr.pins[1].pinId],orientation:orientation4,anchorPoint:anchor,width,height,center:center2},this.solved=!0;return}}}if(singleOrientationMode&&bestCandidate){this.netLabelPlacement={globalConnNetId:this.overlappingSameNetTraceGroup.globalConnNetId,dcConnNetId:bestCandidate.dcConnNetId,netId:this.overlappingSameNetTraceGroup.netId,netLabelText:this.overlappingSameNetTraceGroup.netLabelText,mspConnectionPairIds:[bestCandidate.mspPairId],pinIds:bestCandidate.pinIds,orientation:bestCandidate.orientation,anchorPoint:bestCandidate.anchor,width:bestCandidate.width,height:bestCandidate.height,center:bestCandidate.center},this.solved=!0;return}this.failed=!0,this.error="Could not place net label without collisions"}visualize(){return visualizeSingleNetLabelPlacementSolver(this)}},NetLabelPlacementSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTraceMap");__publicField(this,"overlappingSameNetTraceGroups");__publicField(this,"queuedOverlappingSameNetTraceGroups");__publicField(this,"netLabelPlacements",[]);__publicField(this,"failedGroups",[]);__publicField(this,"currentGroup",null);__publicField(this,"triedAnyOrientationFallbackForCurrentGroup",!1);this.inputProblem=params.inputProblem,this.inputTraceMap=params.inputTraceMap,this.overlappingSameNetTraceGroups=this.computeOverlappingSameNetTraceGroups(),this.queuedOverlappingSameNetTraceGroups=[...this.overlappingSameNetTraceGroups]}computeOverlappingSameNetTraceGroups(){let byGlobal={};for(let trace of Object.values(this.inputTraceMap)){let key=trace.globalConnNetId;byGlobal[key]||(byGlobal[key]=[]),byGlobal[key].push(trace)}let{netConnMap}=getConnectivityMapsFromInputProblem(this.inputProblem),pinIdToPinMap=new Map;for(let chip of this.inputProblem.chips)for(let pin of chip.pins)pinIdToPinMap.set(pin.pinId,pin);let userNetIdByPinId={},netLabelTextByPinId={};for(let dc2 of this.inputProblem.directConnections){if(dc2.netId){let[a6,b6]=dc2.pinIds;userNetIdByPinId[a6]=dc2.netId,userNetIdByPinId[b6]=dc2.netId}let netLabelText=dc2.netLabelText?.trim();if(netLabelText){let[a6,b6]=dc2.pinIds;netLabelTextByPinId[a6]=netLabelText,netLabelTextByPinId[b6]=netLabelText}}for(let nc3 of this.inputProblem.netConnections)for(let pid of nc3.pinIds){userNetIdByPinId[pid]=nc3.netId;let netLabelText=nc3.netLabelText?.trim();netLabelText&&(netLabelTextByPinId[pid]=netLabelText)}let groups=[],allPinIds=this.inputProblem.chips.flatMap(c3=>c3.pins.map(p3=>p3.pinId)),allGlobalConnNetIds=new Set;for(let pinId of allPinIds){let netId=netConnMap.getNetConnectedToId(pinId);netId&&allGlobalConnNetIds.add(netId)}for(let globalConnNetId of allGlobalConnNetIds){let pinsInNet=netConnMap.getIdsConnectedToNet(globalConnNetId).filter(id3=>pinIdToPinMap.has(id3)),adj={};for(let pid of pinsInNet)adj[pid]=new Set;for(let t53 of byGlobal[globalConnNetId]??[]){let a6=t53.pins[0].pinId,b6=t53.pins[1].pinId;adj[a6]&&adj[b6]&&(adj[a6].add(b6),adj[b6].add(a6))}let visited=new Set;for(let pid of pinsInNet){if(visited.has(pid))continue;let stack=[pid],component=new Set;for(visited.add(pid);stack.length>0;){let u6=stack.pop();component.add(u6);for(let v6 of adj[u6]??[])visited.has(v6)||(visited.add(v6),stack.push(v6))}let compTraces=(byGlobal[globalConnNetId]??[]).filter(t53=>component.has(t53.pins[0].pinId)&&component.has(t53.pins[1].pinId));if(compTraces.length>0){if(compTraces.some(trace=>trace.suppressNetLabel))continue;let lengthOf=path=>{let sum=0,pts=path.tracePath;for(let i6=0;i6<pts.length-1;i6++)sum+=Math.abs(pts[i6+1].x-pts[i6].x)+Math.abs(pts[i6+1].y-pts[i6].y);return sum},rep=compTraces[0],repLen=lengthOf(rep);for(let i6=1;i6<compTraces.length;i6++){let len=lengthOf(compTraces[i6]);len>repLen&&(rep=compTraces[i6],repLen=len)}let userNetId=compTraces.find(t53=>t53.userNetId!=null)?.userNetId;if(!userNetId){for(let p3 of component)if(userNetIdByPinId[p3]){userNetId=userNetIdByPinId[p3];break}}let mspConnectionPairIds=Array.from(new Set(compTraces.flatMap(t53=>t53.mspConnectionPairIds??[t53.mspPairId]))),group={globalConnNetId,netId:userNetId,netLabelText:[...component].map(pinId=>netLabelTextByPinId[pinId]).find(text=>!!text),overlappingTraces:rep,mspConnectionPairIds};groups.push(group)}else for(let p3 of component){let userNetId=userNetIdByPinId[p3];userNetId&&groups.push({globalConnNetId,netId:userNetId,netLabelText:netLabelTextByPinId[p3],portOnlyPinId:p3})}}}return groups}getNetLabelWidthForGroup(group){let pinIds=group.overlappingTraces?.pins.map(p3=>p3.pinId)??[];return group.portOnlyPinId&&pinIds.push(group.portOnlyPinId),getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:group.netId,pinIds,isPortOnlyLabel:group.portOnlyPinId!==void 0})}getNetLabelHeightForGroup(group){if(group.netId){let ncHeight=this.inputProblem.netConnections.find(nc3=>nc3.netId===group.netId)?.netLabelHeight;if(ncHeight!==void 0)return ncHeight}let pinIds=group.overlappingTraces?.pins.map(p3=>p3.pinId)??[];return group.portOnlyPinId&&pinIds.push(group.portOnlyPinId),this.inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>pinIds.includes(pid)))?.netLabelHeight}_step(){if(this.activeSubSolver?.solved){this.netLabelPlacements.push(this.activeSubSolver.netLabelPlacement),this.activeSubSolver=null,this.currentGroup=null,this.triedAnyOrientationFallbackForCurrentGroup=!1;return}if(this.activeSubSolver?.failed){let fullOrients=["x+","x-","y+","y-"],currOrients=this.activeSubSolver.availableOrientations,isAlreadyFull=currOrients.length===4&&fullOrients.every(o6=>currOrients.includes(o6));if(!this.triedAnyOrientationFallbackForCurrentGroup&&!isAlreadyFull&&this.currentGroup){this.triedAnyOrientationFallbackForCurrentGroup=!0;let netLabelWidth2=this.getNetLabelWidthForGroup(this.currentGroup),netLabelHeight2=this.getNetLabelHeightForGroup(this.currentGroup);this.activeSubSolver=new SingleNetLabelPlacementSolver({inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,overlappingSameNetTraceGroup:this.currentGroup,availableOrientations:fullOrients,netLabelWidth:netLabelWidth2,netLabelHeight:netLabelHeight2});return}this.currentGroup&&this.failedGroups.push(this.currentGroup),this.activeSubSolver=null,this.currentGroup=null,this.triedAnyOrientationFallbackForCurrentGroup=!1;return}if(this.activeSubSolver){this.activeSubSolver.step();return}let nextOverlappingSameNetTraceGroup=this.queuedOverlappingSameNetTraceGroups.shift();if(!nextOverlappingSameNetTraceGroup){this.solved=!0;return}let netId=nextOverlappingSameNetTraceGroup.netId??nextOverlappingSameNetTraceGroup.globalConnNetId;this.currentGroup=nextOverlappingSameNetTraceGroup,this.triedAnyOrientationFallbackForCurrentGroup=!1;let netLabelWidth=this.getNetLabelWidthForGroup(this.currentGroup),netLabelHeight=this.getNetLabelHeightForGroup(this.currentGroup);this.activeSubSolver=new SingleNetLabelPlacementSolver({inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,overlappingSameNetTraceGroup:nextOverlappingSameNetTraceGroup,availableOrientations:this.inputProblem.availableNetLabelOrientations[netId]??["x+","x-","y+","y-"],netLabelWidth,netLabelHeight})}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);for(let trace of Object.values(this.inputTraceMap))graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let p3 of this.netLabelPlacements)graphics.rects.push({center:p3.center,width:p3.width,height:p3.height,fill:getColorFromString2(p3.globalConnNetId,.35),strokeColor:getColorFromString2(p3.globalConnNetId,.9),label:`netId: ${p3.netId}
649
649
  globalConnNetId: ${p3.globalConnNetId}`}),graphics.points.push({x:p3.anchorPoint.x,y:p3.anchorPoint.y,color:getColorFromString2(p3.globalConnNetId,.9),label:`anchorPoint
650
- orientation: ${p3.orientation}`});return graphics}},AVAILABLE_Y_PLUS_COLOR="#ef4444",AVAILABLE_Y_MINUS_COLOR="#000000",AVAILABLE_ORIENTATION_FILL_ALPHA="66",colorAvailableNetOrientationLabels=(graphicsObject,inputProblem)=>{let availableOrientations=inputProblem.availableNetLabelOrientations;if(availableOrientations)for(let rect of graphicsObject.rects??[]){let orientations=getAvailableOrientationsForRect(rect.label,availableOrientations);if(!orientations)continue;let hasYPlus=orientations.includes("y+"),hasYMinus=orientations.includes("y-");if(hasYPlus===hasYMinus)continue;let color=hasYPlus?AVAILABLE_Y_PLUS_COLOR:AVAILABLE_Y_MINUS_COLOR;rect.fill=`${color}${AVAILABLE_ORIENTATION_FILL_ALPHA}`,rect.stroke=color,rect.color=color}},getAvailableOrientationsForRect=(label,availableOrientations)=>{for(let netId of getNetIdsFromRectLabel(label))if(Object.hasOwn(availableOrientations,netId))return availableOrientations[netId]},getNetIdsFromRectLabel=label=>label?[label.match(/^netId: (.+)$/m)?.[1],label.match(/^globalConnNetId: (.+)$/m)?.[1]].filter(netId=>!!(netId&&netId!=="undefined")):[],groupLabelsByChipAndOrientation=({labels,chips})=>{let groupedLabels={},chipIdByPinId=new Map(chips.flatMap(chip=>chip.pins.map(pin=>[pin.pinId,chip.chipId])));for(let label of labels){if(label.pinIds.length===0)continue;let pinId=label.pinIds[0],chipId=(pinId.includes(".")?pinId.split(".")[0]:void 0)??chipIdByPinId.get(pinId);if(!chipId)continue;let key=`${chipId}-${label.orientation}`;groupedLabels[key]||(groupedLabels[key]=[]),groupedLabels[key].push(label)}return groupedLabels},mergeLabelGroup=(group,groupKey)=>{if(group.length===0)throw new Error("Cannot merge an empty group of labels.");let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0,allPinIds=new Set,allMspConnectionPairIds=new Set,originalNetIds=new Set;for(let label of group){let bounds=getRectBounds(label.center,label.width,label.height);minX=Math.min(minX,bounds.minX),minY=Math.min(minY,bounds.minY),maxX=Math.max(maxX,bounds.maxX),maxY=Math.max(maxY,bounds.maxY),label.pinIds.forEach(id3=>allPinIds.add(id3)),label.mspConnectionPairIds.forEach(id3=>allMspConnectionPairIds.add(id3)),originalNetIds.add(label.globalConnNetId)}let newWidth=maxX-minX,newHeight=maxY-minY,newCenter={x:minX+newWidth/2,y:minY+newHeight/2},template=group[0],syntheticId=`merged-group-${groupKey}`;return{mergedLabel:{...template,globalConnNetId:syntheticId,center:newCenter,width:newWidth,height:newHeight,pinIds:Array.from(allPinIds),mspConnectionPairIds:Array.from(allMspConnectionPairIds)},originalNetIds}},filterLabelsAtTraceEdges=({labels,traces,distanceThreshold=.5})=>{let tracesByNetId=new Map;if(!traces)throw new Error("No traces provided to filterLabelsAtTraceEdges");for(let trace of traces)trace.globalConnNetId&&(tracesByNetId.has(trace.globalConnNetId)||tracesByNetId.set(trace.globalConnNetId,[]),tracesByNetId.get(trace.globalConnNetId).push(trace));let filteredLabels=[];for(let label of labels){if(label.mspConnectionPairIds.length===0){filteredLabels.push(label);continue}let relevantTraces=tracesByNetId.get(label.globalConnNetId),isNearTraceEdge=!1;if(!(!relevantTraces||relevantTraces.length===0)){for(let trace of relevantTraces){if(trace.tracePath.length===0)continue;let startPoint=trace.tracePath[0],endPoint=trace.tracePath[trace.tracePath.length-1],startDist=distance2(label.center,startPoint),endDist=distance2(label.center,endPoint);if(startDist<=distanceThreshold||endDist<=distanceThreshold){isNearTraceEdge=!0;break}}isNearTraceEdge&&filteredLabels.push(label)}}return filteredLabels},MergedNetLabelObstacleSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"output");__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"pipelineStep","filtering_labels");__publicField(this,"filteredLabels",[]);__publicField(this,"labelGroups",{});__publicField(this,"groupKeysToProcess",[]);__publicField(this,"finalPlacements",[]);__publicField(this,"mergedLabelNetIdMap",{});__publicField(this,"activeMergingGroupKey",null);this.input=solverInput,this.inputProblem=solverInput.inputProblem,this.traces=solverInput.traces,this.output={netLabelPlacements:solverInput.netLabelPlacements,mergedLabelNetIdMap:{}}}_step(){switch(this.pipelineStep){case"filtering_labels":this.filteredLabels=filterLabelsAtTraceEdges({labels:this.input.netLabelPlacements,traces:this.traces}),this.pipelineStep="grouping_labels";break;case"grouping_labels":this.labelGroups=groupLabelsByChipAndOrientation({labels:this.filteredLabels,chips:this.inputProblem.chips}),this.groupKeysToProcess=Object.keys(this.labelGroups),this.pipelineStep="merging_groups";break;case"merging_groups":if(this.groupKeysToProcess.length===0){this.pipelineStep="finalizing",this.activeMergingGroupKey=null;break}let groupKey=this.groupKeysToProcess.pop();this.activeMergingGroupKey=groupKey;let group=this.labelGroups[groupKey];if(group.length>1){let{mergedLabel,originalNetIds}=mergeLabelGroup(group,groupKey);this.finalPlacements.push(mergedLabel),this.mergedLabelNetIdMap[mergedLabel.globalConnNetId]=originalNetIds}else this.finalPlacements.push(...group);break;case"finalizing":let processedOriginalIds=new Set(this.finalPlacements.flatMap(p3=>this.mergedLabelNetIdMap[p3.globalConnNetId]?[...this.mergedLabelNetIdMap[p3.globalConnNetId]]:[p3.globalConnNetId])),unprocessedLabels=this.input.netLabelPlacements.filter(l6=>!processedOriginalIds.has(l6.globalConnNetId));this.output={netLabelPlacements:[...this.finalPlacements,...unprocessedLabels],mergedLabelNetIdMap:this.mergedLabelNetIdMap},this.solved=!0;break}}getOutput(){return this.output}visualize(){let graphics=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});graphics.rects||(graphics.rects=[]),graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.texts||(graphics.texts=[]);let originalLabelsById=new Map;for(let label of this.input.netLabelPlacements)originalLabelsById.set(label.globalConnNetId,label);for(let trace of this.traces){let line2={points:trace.tracePath.map(p3=>({x:p3.x,y:p3.y})),strokeColor:"blue"};graphics.lines.push(line2)}if(this.activeMergingGroupKey&&this.labelGroups[this.activeMergingGroupKey]){let activeGroup=this.labelGroups[this.activeMergingGroupKey];for(let label of activeGroup)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:"rgba(255, 165, 0, 0.5)",stroke:"orange"})}for(let finalLabel of this.output.netLabelPlacements){let isMerged=finalLabel.globalConnNetId.startsWith("merged-group-"),color=getColorFromString2(finalLabel.globalConnNetId);if(isMerged){graphics.rects.push({center:finalLabel.center,width:finalLabel.width,height:finalLabel.height,fill:color.replace(/, 1\)/,", 0.2)"),stroke:color,label:finalLabel.globalConnNetId});let originalNetIds=this.output.mergedLabelNetIdMap[finalLabel.globalConnNetId];if(originalNetIds)for(let originalNetId of originalNetIds){let originalLabel=originalLabelsById.get(originalNetId);if(originalLabel){let bounds=getRectBounds(originalLabel.center,originalLabel.width,originalLabel.height),p12={x:bounds.minX,y:bounds.minY},p22={x:bounds.maxX,y:bounds.minY},p3={x:bounds.maxX,y:bounds.maxY},p42={x:bounds.minX,y:bounds.maxY};graphics.lines.push({points:[p12,p22,p3,p42,p12],strokeColor:color,strokeDash:"4 4"}),graphics.lines.push({points:[originalLabel.center,finalLabel.center],strokeColor:color,strokeDash:"2 2"})}}}else graphics.rects.push({center:finalLabel.center,width:finalLabel.width,height:finalLabel.height,stroke:color,label:finalLabel.globalConnNetId})}return graphics}},detectTraceLabelOverlap=({traces,netLabels=[]})=>{let overlaps=[];for(let trace of traces)for(let label of netLabels){let labelBounds=getRectBounds(label.center,label.width,label.height);for(let j6=0;j6<trace.tracePath.length-1;j6++){let p12=trace.tracePath[j6],p22=trace.tracePath[j6+1];if(segmentIntersectsRect2(p12,p22,labelBounds)){if(trace.globalConnNetId===label.globalConnNetId)break;overlaps.push({trace,label});break}}}return overlaps},findTraceViolationZone=({path,labelBounds,paddedBounds=labelBounds})=>{let firstCollidingSeg=-1,lastCollidingSeg=-1;for(let i6=0;i6<path.length-1;i6++)segmentIntersectsRect2(path[i6],path[i6+1],labelBounds)&&(firstCollidingSeg===-1&&(firstCollidingSeg=i6),lastCollidingSeg=i6);if(firstCollidingSeg===-1)return{firstInsideIndex:-1,lastInsideIndex:-1};let isInsidePadded=p3=>p3.x>paddedBounds.minX&&p3.x<paddedBounds.maxX&&p3.y>paddedBounds.minY&&p3.y<paddedBounds.maxY,entryIndex=firstCollidingSeg;for(;entryIndex>0&&isInsidePadded(path[entryIndex]);)entryIndex--;let exitIndex=lastCollidingSeg+1;for(;exitIndex<path.length-1&&isInsidePadded(path[exitIndex]);)exitIndex++;return{firstInsideIndex:entryIndex+1,lastInsideIndex:exitIndex-1}},generateSnipAndReconnectCandidates=({initialTrace,firstInsideIndex,lastInsideIndex,labelBounds,paddingBuffer,detourCount})=>{if(firstInsideIndex<=0||lastInsideIndex>=initialTrace.tracePath.length-1)return[];let entryPoint=initialTrace.tracePath[firstInsideIndex-1],exitPoint=initialTrace.tracePath[lastInsideIndex+1],pathToEntry=initialTrace.tracePath.slice(0,firstInsideIndex),pathFromExit=initialTrace.tracePath.slice(lastInsideIndex+1),allCandidateDetours=[];entryPoint.x!==exitPoint.x&&entryPoint.y!==exitPoint.y?(allCandidateDetours.push([{x:exitPoint.x,y:entryPoint.y}]),allCandidateDetours.push([{x:entryPoint.x,y:exitPoint.y}])):(entryPoint.x===exitPoint.x||entryPoint.y===exitPoint.y)&&allCandidateDetours.push([]);let buffer=paddingBuffer+detourCount*paddingBuffer,leftX=labelBounds.minX-buffer,rightX=labelBounds.maxX+buffer,topY=labelBounds.maxY+buffer,bottomY=labelBounds.minY-buffer;return(entryPoint.x<=labelBounds.minX||exitPoint.x<=labelBounds.minX)&&entryPoint.x<labelBounds.maxX&&exitPoint.x<labelBounds.maxX&&allCandidateDetours.push([{x:leftX,y:entryPoint.y},{x:leftX,y:exitPoint.y}]),(entryPoint.x>=labelBounds.maxX||exitPoint.x>=labelBounds.maxX)&&entryPoint.x>labelBounds.minX&&exitPoint.x>labelBounds.minX&&allCandidateDetours.push([{x:rightX,y:entryPoint.y},{x:rightX,y:exitPoint.y}]),(entryPoint.y>=labelBounds.maxY||exitPoint.y>=labelBounds.maxY)&&entryPoint.y>labelBounds.minY&&exitPoint.y>labelBounds.minY&&allCandidateDetours.push([{x:entryPoint.x,y:topY},{x:exitPoint.x,y:topY}]),(entryPoint.y<=labelBounds.minY||exitPoint.y<=labelBounds.minY)&&entryPoint.y<labelBounds.maxY&&exitPoint.y<labelBounds.maxY&&allCandidateDetours.push([{x:entryPoint.x,y:bottomY},{x:exitPoint.x,y:bottomY}]),allCandidateDetours.map(detour=>[...pathToEntry,...detour,...pathFromExit])},generateFourPointDetourCandidates=({initialTrace,label,labelBounds,paddingBuffer,detourCount})=>{let isMergedLabel=label.globalConnNetId.startsWith("merged-group-"),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},entryPoint,exitPoint,entryIndex,exitIndex,isPointInRect=p3=>p3.x>=paddedLabelBounds.minX&&p3.x<=paddedLabelBounds.maxX&&p3.y>=paddedLabelBounds.minY&&p3.y<=paddedLabelBounds.maxY;if(isMergedLabel){let firstInsideIndex=-1;for(let i6=0;i6<initialTrace.tracePath.length;i6++)if(isPointInRect(initialTrace.tracePath[i6])){firstInsideIndex=i6;break}if(firstInsideIndex===-1)return[];entryIndex=Math.max(0,firstInsideIndex-1),entryPoint=initialTrace.tracePath[entryIndex];let firstOutsideIndex=-1;for(let i6=firstInsideIndex;i6<initialTrace.tracePath.length;i6++)if(!isPointInRect(initialTrace.tracePath[i6])){firstOutsideIndex=i6;break}firstOutsideIndex===-1?exitIndex=initialTrace.tracePath.length-1:exitIndex=firstOutsideIndex,exitPoint=initialTrace.tracePath[exitIndex]}else{let firstCollidingSeg=-1,lastCollidingSeg=-1;for(let i6=0;i6<initialTrace.tracePath.length-1;i6++)segmentIntersectsRect(initialTrace.tracePath[i6],initialTrace.tracePath[i6+1],{...labelBounds,chipId:"temp-obstacle"})&&(firstCollidingSeg===-1&&(firstCollidingSeg=i6),lastCollidingSeg=i6);if(firstCollidingSeg===-1)return[];entryIndex=firstCollidingSeg,exitIndex=lastCollidingSeg+1,entryPoint=initialTrace.tracePath[entryIndex],exitPoint=initialTrace.tracePath[exitIndex]}if(!entryPoint||!exitPoint||entryIndex>=exitIndex)return[];let candidateDetours=[],dx3=exitPoint.x-entryPoint.x,dy3=exitPoint.y-entryPoint.y;if(Math.abs(dx3)>Math.abs(dy3)){let yCandidates=[paddedLabelBounds.maxY,paddedLabelBounds.minY];for(let newY of yCandidates)candidateDetours.push(dx3>0?[{x:paddedLabelBounds.minX,y:entryPoint.y},{x:paddedLabelBounds.minX,y:newY},{x:paddedLabelBounds.maxX,y:newY},{x:paddedLabelBounds.maxX,y:exitPoint.y}]:[{x:paddedLabelBounds.maxX,y:entryPoint.y},{x:paddedLabelBounds.maxX,y:newY},{x:paddedLabelBounds.minX,y:newY},{x:paddedLabelBounds.minX,y:exitPoint.y}])}else{let xCandidates=[paddedLabelBounds.maxX,paddedLabelBounds.minX];for(let newX of xCandidates)candidateDetours.push(dy3>0?[{x:entryPoint.x,y:paddedLabelBounds.minY},{x:newX,y:paddedLabelBounds.minY},{x:newX,y:paddedLabelBounds.maxY},{x:exitPoint.x,y:paddedLabelBounds.maxY}]:[{x:entryPoint.x,y:paddedLabelBounds.maxY},{x:newX,y:paddedLabelBounds.maxY},{x:newX,y:paddedLabelBounds.minY},{x:exitPoint.x,y:paddedLabelBounds.minY}])}return candidateDetours.map(detourPoints=>[...initialTrace.tracePath.slice(0,entryIndex),entryPoint,...detourPoints,exitPoint,...initialTrace.tracePath.slice(exitIndex+1)])},simplifyPath=path=>{if(path.length<3)return path;let newPath=[path[0]];for(let i6=1;i6<path.length-1;i6++){let p12=newPath[newPath.length-1],p22=path[i6],p3=path[i6+1];isVertical(p12,p22)&&isVertical(p22,p3)||isHorizontal(p12,p22)&&isHorizontal(p22,p3)||newPath.push(p22)}if(newPath.push(path[path.length-1]),newPath.length<3)return newPath;let finalPath=[newPath[0]];for(let i6=1;i6<newPath.length-1;i6++){let p12=finalPath[finalPath.length-1],p22=newPath[i6],p3=newPath[i6+1];isVertical(p12,p22)&&isVertical(p22,p3)||isHorizontal(p12,p22)&&isHorizontal(p22,p3)||finalPath.push(p22)}return finalPath.push(newPath[newPath.length-1]),finalPath},generateRerouteCandidates=({trace,label,paddingBuffer,detourCount})=>{let initialTrace={...trace,tracePath:simplifyPath(trace.tracePath)};if(trace.globalConnNetId===label.globalConnNetId)return[initialTrace.tracePath];let labelBoundsRaw=getRectBounds(label.center,label.width,label.height),labelBounds={minX:labelBoundsRaw.minX,minY:labelBoundsRaw.minY,maxX:labelBoundsRaw.maxX,maxY:labelBoundsRaw.maxY,chipId:`netlabel-${label.netId}`},fourPointCandidates=generateFourPointDetourCandidates({initialTrace,label,labelBounds,paddingBuffer,detourCount}),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},{firstInsideIndex,lastInsideIndex}=findTraceViolationZone({path:initialTrace.tracePath,labelBounds,paddedBounds:paddedLabelBounds}),snipReconnectCandidates=generateSnipAndReconnectCandidates({initialTrace,firstInsideIndex,lastInsideIndex,labelBounds,paddingBuffer,detourCount});return[...fourPointCandidates,...snipReconnectCandidates]},COINCIDENT_EPS=.002,GEOMETRY_EPS=1e-6,SCHEMATIC_TRACE_STROKE_WIDTH=.02,SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE=SCHEMATIC_TRACE_STROKE_WIDTH+GEOMETRY_EPS,SCHEMATIC_TRACE_MIN_VISUAL_CENTERLINE_CLEARANCE=SCHEMATIC_TRACE_STROKE_WIDTH*3,doesPathCoincideWithTraces=(path,traces)=>{let rangesOverlap1D=(a12,a22,b12,b22)=>Math.min(Math.max(a12,a22),Math.max(b12,b22))-Math.max(Math.min(a12,a22),Math.min(b12,b22))>COINCIDENT_EPS;for(let i6=0;i6<path.length-1;i6++){let pathSegStart=path[i6],pathSegEnd=path[i6+1],isVertical52=Math.abs(pathSegStart.x-pathSegEnd.x)<COINCIDENT_EPS,isHorizontal42=Math.abs(pathSegStart.y-pathSegEnd.y)<COINCIDENT_EPS;if(!isVertical52&&!isHorizontal42)continue;let crossAxis=isVertical52?"x":"y",alongAxis=isVertical52?"y":"x";for(let trace of traces)for(let j6=0;j6<trace.tracePath.length-1;j6++){let traceSegStart=trace.tracePath[j6],traceSegEnd=trace.tracePath[j6+1];if(!(!(Math.abs(traceSegStart[crossAxis]-traceSegEnd[crossAxis])<COINCIDENT_EPS)||!(Math.abs(pathSegStart[crossAxis]-traceSegStart[crossAxis])<COINCIDENT_EPS))&&rangesOverlap1D(pathSegStart[alongAxis],pathSegEnd[alongAxis],traceSegStart[alongAxis],traceSegEnd[alongAxis]))return!0}}return!1},doesPathOverlapTraceStrokes=(path,traces)=>{let traceStrokeRadius=SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE/2,getStrokeBounds=(start,end,isVertical52)=>isVertical52?{minX:start.x-traceStrokeRadius,maxX:start.x+traceStrokeRadius,minY:Math.min(start.y,end.y),maxY:Math.max(start.y,end.y)}:{minX:Math.min(start.x,end.x),maxX:Math.max(start.x,end.x),minY:start.y-traceStrokeRadius,maxY:start.y+traceStrokeRadius};for(let pathIndex=0;pathIndex<path.length-1;pathIndex++){let pathStart=path[pathIndex],pathEnd=path[pathIndex+1],isVertical52=Math.abs(pathStart.x-pathEnd.x)<COINCIDENT_EPS,isHorizontal42=Math.abs(pathStart.y-pathEnd.y)<COINCIDENT_EPS;if(!isVertical52&&!isHorizontal42)continue;let pathBounds=getStrokeBounds(pathStart,pathEnd,isVertical52);for(let trace of traces)for(let traceIndex=0;traceIndex<trace.tracePath.length-1;traceIndex++){let traceStart=trace.tracePath[traceIndex],traceEnd=trace.tracePath[traceIndex+1];if(!(isVertical52?Math.abs(traceStart.x-traceEnd.x)<COINCIDENT_EPS:Math.abs(traceStart.y-traceEnd.y)<COINCIDENT_EPS))continue;let overlap=boundsIntersection(pathBounds,getStrokeBounds(traceStart,traceEnd,isVertical52));if(!overlap)continue;if((isVertical52?overlap.maxY-overlap.minY:overlap.maxX-overlap.minX)>COINCIDENT_EPS)return!0}}return!1},MAX_TRIES=5,PATH_LENGTH_EPSILON=1e-9,getPathLength=points=>{let length4=0;for(let pointIndex=0;pointIndex<points.length-1;pointIndex++){let point6=points[pointIndex],nextPoint=points[pointIndex+1];length4+=Math.abs(nextPoint.x-point6.x)+Math.abs(nextPoint.y-point6.y)}return length4},SingleOverlapSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"queuedCandidatePaths");__publicField(this,"solvedTracePath",null);__publicField(this,"initialTrace");__publicField(this,"problem");__publicField(this,"obstacles");__publicField(this,"label");__publicField(this,"tracesToAvoidOverlapping");__publicField(this,"netLabelPlacements");__publicField(this,"detourCount");__publicField(this,"_tried",0);this.initialTrace=solverInput.trace,this.problem=solverInput.problem,this.label=solverInput.label,this.detourCount=solverInput.detourCount,this.tracesToAvoidOverlapping=(solverInput.tracesToAvoidOverlapping??[]).filter(t53=>t53.globalConnNetId!==solverInput.trace.globalConnNetId),this.netLabelPlacements=solverInput.netLabelPlacements??[solverInput.label],this.obstacles=getObstacleRects(this.problem);let effectivePadding=solverInput.paddingBuffer+solverInput.detourCount*solverInput.paddingBuffer,candidates=generateRerouteCandidates({...solverInput,paddingBuffer:effectivePadding}),getLabelOverlapCount=path=>detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:path}],netLabels:this.netLabelPlacements}).length,candidateByPath=new Map;for(let candidate of candidates){let simplifiedCandidate=simplifyPath(candidate);candidateByPath.set(simplifiedCandidate.map(point6=>`${point6.x},${point6.y}`).join(";"),simplifiedCandidate)}this.queuedCandidatePaths=[...candidateByPath.values()].sort((a6,b6)=>{let pathLengthDifference=getPathLength(a6)-getPathLength(b6);if(Math.abs(pathLengthDifference)>=PATH_LENGTH_EPSILON)return pathLengthDifference;let overlapCountDifference=getLabelOverlapCount(a6)-getLabelOverlapCount(b6);return overlapCountDifference!==0?overlapCountDifference:a6.length-b6.length})}_step(){if(this.queuedCandidatePaths.length===0||this._tried>=MAX_TRIES){this.failed=!0;return}this._tried++;let nextCandidatePath=this.queuedCandidatePaths.shift(),simplifiedPath=simplifyPath(nextCandidatePath),stillOverlapsLabel=detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:simplifiedPath}],netLabels:[this.label]}).length>0,initialPath=simplifyPath(this.initialTrace.tracePath),initialLabelOverlaps=detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:initialPath}],netLabels:this.netLabelPlacements}),candidateLabelOverlaps=detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:simplifiedPath}],netLabels:this.netLabelPlacements});!stillOverlapsLabel&&candidateLabelOverlaps.length<=initialLabelOverlaps.length&&!isPathCollidingWithObstacles(simplifiedPath,this.obstacles)&&!doesPathCoincideWithTraces(simplifiedPath,this.tracesToAvoidOverlapping)&&(this.solvedTracePath=simplifiedPath,this.solved=!0)}visualize(){let graphics=visualizeInputProblem2(this.problem,{chipAlpha:.1,connectionAlpha:.1});return graphics.lines||(graphics.lines=[]),graphics.rects||(graphics.rects=[]),graphics.lines.push({points:this.initialTrace.tracePath,strokeColor:"red",strokeDash:"4 4"}),graphics.rects.push({center:this.label.center,width:this.label.width,height:this.label.height,fill:"rgba(255, 0, 0, 0.2)"}),!this.solvedTracePath&&this.queuedCandidatePaths.length>0&&graphics.lines.push({points:this.queuedCandidatePaths[0],strokeColor:"orange"}),this.solvedTracePath&&graphics.lines.push({points:this.solvedTracePath,strokeColor:"green"}),graphics}},doesTraceStartOrEndInLabel=({trace,label})=>{if(trace.tracePath.length<2)return!1;let firstSegmentTrace={...trace,tracePath:[trace.tracePath[0],trace.tracePath[1]]};if(detectTraceLabelOverlap({traces:[firstSegmentTrace],netLabels:[label]}).length>0)return!0;if(trace.tracePath.length>2){let lastPoint=trace.tracePath[trace.tracePath.length-1],secondToLastPoint=trace.tracePath[trace.tracePath.length-2],lastSegmentTrace={...trace,tracePath:[secondToLastPoint,lastPoint]};if(detectTraceLabelOverlap({traces:[lastSegmentTrace],netLabels:[label]}).length>0)return!0}return!1},visualizeDecomposition=params=>{let{decomposedChildLabels,collidingTrace,mergedLabel,graphics}=params;graphics.rects||(graphics.rects=[]),graphics.texts||(graphics.texts=[]);for(let childLabel of decomposedChildLabels){let isOwnLabel=childLabel.globalConnNetId===collidingTrace.globalConnNetId;graphics.rects.push({center:childLabel.center,width:childLabel.width,height:childLabel.height,fill:isOwnLabel?"green":"red"})}return graphics.texts.push({x:mergedLabel.center.x,y:mergedLabel.center.y+mergedLabel.height/2+.5,text:`DECOMPOSITION: Trace ${collidingTrace.mspPairId} vs Merged Label ${mergedLabel.globalConnNetId}`,fontSize:.3,color:"blue"}),graphics},OverlapAvoidanceStepSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"inputProblem");__publicField(this,"initialNetLabelPlacements");__publicField(this,"mergedNetLabelPlacements");__publicField(this,"mergedLabelNetIdMap");__publicField(this,"allTraces");__publicField(this,"tracesToAvoidOverlapping");__publicField(this,"modifiedTraces",[]);__publicField(this,"completedReroutes",[]);__publicField(this,"PADDING_BUFFER",.1);__publicField(this,"detourCounts",new Map);__publicField(this,"activeSubSolver",null);__publicField(this,"overlapQueue",[]);__publicField(this,"activeOverlap",null);__publicField(this,"recentlyFailed",new Set);__publicField(this,"currentlyProcessingOverlap",null);__publicField(this,"decomposedChildLabels",null);this.inputProblem=solverInput.inputProblem,this.initialNetLabelPlacements=solverInput.initialNetLabelPlacements,this.mergedNetLabelPlacements=solverInput.mergedNetLabelPlacements,this.mergedLabelNetIdMap=solverInput.mergedLabelNetIdMap,this.allTraces=[...solverInput.traces],this.tracesToAvoidOverlapping=solverInput.tracesToAvoidOverlapping??[],this.detourCounts=solverInput.detourCounts}_step(){if(this.currentlyProcessingOverlap=null,this.decomposedChildLabels=null,this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){let solvedPath=this.activeSubSolver.solvedTracePath;if(solvedPath){this.completedReroutes.push({initialTrace:{...this.activeSubSolver.initialTrace,tracePath:this.activeSubSolver.initialTrace.tracePath.map(point6=>({...point6}))},reroutedTracePath:solvedPath.map(point6=>({...point6})),label:this.activeSubSolver.label,detourCount:this.activeSubSolver.detourCount});let traceIndex=this.allTraces.findIndex(t53=>t53.mspPairId===this.activeSubSolver.initialTrace.mspPairId);traceIndex!==-1&&(this.allTraces[traceIndex].tracePath=solvedPath,this.modifiedTraces.push(this.allTraces[traceIndex]))}this.activeSubSolver=null,this.activeOverlap=null,this.recentlyFailed.clear()}else if(this.activeSubSolver.failed){let overlapId=`${this.activeOverlap.trace.mspPairId}-${this.activeOverlap.label.globalConnNetId}`;this.recentlyFailed.add(overlapId),this.activeSubSolver=null,this.activeOverlap=null}return}let overlaps=detectTraceLabelOverlap({traces:this.allTraces,netLabels:this.mergedNetLabelPlacements});if(overlaps.length===0){this.solved=!0;return}let nonFailedOverlaps=overlaps.filter(o6=>{let overlapId=`${o6.trace.mspPairId}-${o6.label.globalConnNetId}`;return!this.recentlyFailed.has(overlapId)});if(nonFailedOverlaps.length===0){this.solved=!0;return}this.overlapQueue=nonFailedOverlaps;let nextOverlap=this.overlapQueue.shift();if(this.currentlyProcessingOverlap=nextOverlap??null,nextOverlap){let traceToFix=this.allTraces.find(t53=>t53.mspPairId===nextOverlap.trace.mspPairId),labelToAvoid=nextOverlap.label,originalNetIds=this.mergedLabelNetIdMap[labelToAvoid.globalConnNetId];if(originalNetIds?.has(traceToFix.globalConnNetId)){let childLabels=this.initialNetLabelPlacements.filter(l6=>originalNetIds.has(l6.globalConnNetId));this.decomposedChildLabels=childLabels;let actualOverlapLabel=null;for(let childLabel of childLabels)if(detectTraceLabelOverlap({traces:[traceToFix],netLabels:[childLabel]}).length>0){actualOverlapLabel=childLabel;break}if(actualOverlapLabel){let detourCount2=this.detourCounts.get(actualOverlapLabel.globalConnNetId)??0;this.detourCounts.set(actualOverlapLabel.globalConnNetId,detourCount2+1),this.activeOverlap=nextOverlap,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:actualOverlapLabel,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount:detourCount2,tracesToAvoidOverlapping:this.tracesToAvoidOverlapping,netLabelPlacements:this.initialNetLabelPlacements})}else{let overlapId=`${traceToFix.mspPairId}-${labelToAvoid.globalConnNetId}`;this.recentlyFailed.add(overlapId)}return}if(originalNetIds&&doesTraceStartOrEndInLabel({trace:traceToFix,label:labelToAvoid})){let childLabels=this.initialNetLabelPlacements.filter(l6=>originalNetIds.has(l6.globalConnNetId));this.decomposedChildLabels=childLabels;let actualOverlapLabel=null;for(let childLabel of childLabels)if(detectTraceLabelOverlap({traces:[traceToFix],netLabels:[childLabel]}).length>0){actualOverlapLabel=childLabel;break}if(actualOverlapLabel){let detourCount2=this.detourCounts.get(actualOverlapLabel.globalConnNetId)??0;this.detourCounts.set(actualOverlapLabel.globalConnNetId,detourCount2+1),this.activeOverlap=nextOverlap,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:actualOverlapLabel,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount:detourCount2,tracesToAvoidOverlapping:this.tracesToAvoidOverlapping,netLabelPlacements:this.initialNetLabelPlacements})}else{let overlapId=`${traceToFix.mspPairId}-${labelToAvoid.globalConnNetId}`;this.recentlyFailed.add(overlapId)}return}let detourCount=this.detourCounts.get(labelToAvoid.globalConnNetId)??0;this.detourCounts.set(labelToAvoid.globalConnNetId,detourCount+1),this.activeOverlap=nextOverlap,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:labelToAvoid,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount,tracesToAvoidOverlapping:this.tracesToAvoidOverlapping,netLabelPlacements:this.initialNetLabelPlacements})}}getOutput(){return{allTraces:this.allTraces,modifiedTraces:this.modifiedTraces,detourCounts:this.detourCounts}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);graphics.lines||(graphics.lines=[]);for(let trace of this.allTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});if(this.currentlyProcessingOverlap){let{trace,label}=this.currentlyProcessingOverlap;graphics.lines.push({points:trace.tracePath,strokeColor:"red"}),this.decomposedChildLabels?visualizeDecomposition({decomposedChildLabels:this.decomposedChildLabels,collidingTrace:trace,mergedLabel:label,graphics}):(graphics.rects||(graphics.rects=[]),graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:"yellow"}),graphics.texts||(graphics.texts=[]),graphics.texts.push({x:label.center.x,y:label.center.y+label.height/2+.5,text:`COLLISION: Trace ${trace.mspPairId} vs Label ${label.globalConnNetId}`,fontSize:.3,color:"red"}))}return graphics}},TraceLabelOverlapAvoidanceSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"inputProblem");__publicField(this,"netLabelPlacements");__publicField(this,"unprocessedTraces",[]);__publicField(this,"cleanTraces",[]);__publicField(this,"subSolvers",[]);__publicField(this,"phase","searching_for_overlaps");__publicField(this,"detourCounts",new Map);__publicField(this,"labelMergingSolver");__publicField(this,"allInputTraces");this.inputProblem=solverInput.inputProblem,this.unprocessedTraces=[...solverInput.traces],this.allInputTraces=solverInput.traces,this.netLabelPlacements=solverInput.netLabelPlacements,this.cleanTraces=[],this.subSolvers=[]}_step(){if(this.phase==="searching_for_overlaps"){if(this.unprocessedTraces.length===0){this.phase="fixing_overlaps";return}let currentTargetTrace=this.unprocessedTraces.shift(),localOverlaps=detectTraceLabelOverlap({traces:[currentTargetTrace],netLabels:this.netLabelPlacements});if(localOverlaps.length===0)this.cleanTraces.push(currentTargetTrace);else{let collidingLabels=localOverlaps.map(o6=>o6.label),labelMerger=new MergedNetLabelObstacleSolver({netLabelPlacements:collidingLabels,inputProblem:this.inputProblem,traces:[currentTargetTrace]});labelMerger.solve();let mergingOutput=labelMerger.getOutput(),subSolver=new OverlapAvoidanceStepSolver({inputProblem:this.inputProblem,traces:[currentTargetTrace],initialNetLabelPlacements:this.netLabelPlacements,mergedNetLabelPlacements:mergingOutput.netLabelPlacements,mergedLabelNetIdMap:mergingOutput.mergedLabelNetIdMap,detourCounts:this.detourCounts,tracesToAvoidOverlapping:this.allInputTraces.filter(t53=>t53.mspPairId!==currentTargetTrace.mspPairId)});this.subSolvers.push(subSolver)}}else if(this.phase==="fixing_overlaps"){if(this.subSolvers.every(s6=>s6.solved||s6.failed)){this.labelMergingSolver||(this.labelMergingSolver=new MergedNetLabelObstacleSolver({netLabelPlacements:this.netLabelPlacements,inputProblem:this.inputProblem,traces:this.getOutput().traces}),this.labelMergingSolver.solve()),this.solved=!0;return}for(let solver of this.subSolvers)!solver.solved&&!solver.failed&&solver.step()}}getOutput(){let solvedTraces=this.subSolvers.flatMap(s6=>s6.getOutput().allTraces);return{traces:[...this.cleanTraces,...solvedTraces],completedReroutes:this.subSolvers.flatMap(solver=>solver.completedReroutes),netLabelPlacements:this.labelMergingSolver?.getOutput().netLabelPlacements??this.netLabelPlacements}}visualize(){let graphics=visualizeInputProblem2(this.inputProblem);graphics.lines||(graphics.lines=[]),graphics.rects||(graphics.rects=[]);for(let trace of this.cleanTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let solver of this.subSolvers){let solverGraphics=solver.visualize();graphics.lines.push(...solverGraphics.lines??[]),graphics.rects.push(...solverGraphics.rects??[]),graphics.points.push(...solverGraphics.points??[])}for(let label of this.netLabelPlacements){let color=getColorFromString2(label.globalConnNetId,.3);graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:color,stroke:color.replace("0.3","1"),label:label.globalConnNetId})}return graphics}},correctPinsInsideChips=problem=>{for(let chip of problem.chips){let bounds=getInputChipBounds(chip);for(let pin of chip.pins){if(!(pin.x>bounds.minX&&pin.x<bounds.maxX&&pin.y>bounds.minY&&pin.y<bounds.maxY))continue;if(pin._facingDirection){pin._facingDirection==="x-"?pin.x=bounds.minX:pin._facingDirection==="x+"?pin.x=bounds.maxX:pin._facingDirection==="y-"?pin.y=bounds.minY:pin.y=bounds.maxY;continue}let distLeft=pin.x-bounds.minX,distRight=bounds.maxX-pin.x,distBottom=pin.y-bounds.minY,distTop=bounds.maxY-pin.y,minDist=Math.min(distLeft,distRight,distBottom,distTop);minDist===distLeft?pin.x=bounds.minX:minDist===distRight?pin.x=bounds.maxX:minDist===distBottom?pin.y=bounds.minY:pin.y=bounds.maxY,pin._facingDirection=void 0}}},expandChipsToFitPins=problem=>{for(let chip of problem.chips){let halfWidth=chip.width/2,halfHeight=chip.height/2,maxDx=0,maxDy=0;for(let pin of chip.pins){let dx3=Math.abs(pin.x-chip.center.x),dy3=Math.abs(pin.y-chip.center.y);dx3>maxDx&&(maxDx=dx3),dy3>maxDy&&(maxDy=dy3)}let newHalfWidth=Math.max(halfWidth,maxDx),newHalfHeight=Math.max(halfHeight,maxDy);if(newHalfWidth>halfWidth||newHalfHeight>halfHeight){chip.width=newHalfWidth*2,chip.height=newHalfHeight*2;for(let pin of chip.pins)pin._facingDirection=void 0}}};function doesTraceOverlapWithExistingTraces(newTracePath,existingTraces){for(let i6=0;i6<newTracePath.length-1;i6++){let newSegmentP1=newTracePath[i6],newSegmentP2=newTracePath[i6+1];for(let existingTrace of existingTraces)for(let j6=0;j6<existingTrace.tracePath.length-1;j6++){let existingSegmentP1=existingTrace.tracePath[j6],existingSegmentP2=existingTrace.tracePath[j6+1];if(doSegmentsIntersect(newSegmentP1,newSegmentP2,existingSegmentP1,existingSegmentP2))return!0}}return!1}var NEAREST_NEIGHBOR_COUNT=3,distance32=(p12,p22)=>Math.sqrt(Math.pow(p12.x-p22.x,2)+Math.pow(p12.y-p22.y,2)),manhattanDistance=(p12,p22)=>Math.abs(p12.x-p22.x)+Math.abs(p12.y-p22.y),EPS6=1e-9,between=(value,first,second)=>value>=Math.min(first,second)-EPS6&&value<=Math.max(first,second)+EPS6,getAxisAlignedIntersection=(firstStart,firstEnd,secondStart,secondEnd)=>{let firstIsHorizontal=Math.abs(firstStart.y-firstEnd.y)<=EPS6,firstIsVertical=Math.abs(firstStart.x-firstEnd.x)<=EPS6,secondIsHorizontal=Math.abs(secondStart.y-secondEnd.y)<=EPS6,secondIsVertical=Math.abs(secondStart.x-secondEnd.x)<=EPS6;if(firstIsHorizontal&&secondIsVertical){let point6={x:secondStart.x,y:firstStart.y};return between(point6.x,firstStart.x,firstEnd.x)&&between(point6.y,secondStart.y,secondEnd.y)?point6:null}if(firstIsVertical&&secondIsHorizontal){let point6={x:firstStart.x,y:secondStart.y};return between(point6.y,firstStart.y,firstEnd.y)&&between(point6.x,secondStart.x,secondEnd.x)?point6:null}if(firstIsHorizontal&&secondIsHorizontal&&Math.abs(firstStart.y-secondStart.y)<=EPS6){let overlapMin=Math.max(Math.min(firstStart.x,firstEnd.x),Math.min(secondStart.x,secondEnd.x)),overlapMax=Math.min(Math.max(firstStart.x,firstEnd.x),Math.max(secondStart.x,secondEnd.x));return overlapMin>overlapMax+EPS6?null:{x:Math.max(overlapMin,Math.min(firstStart.x,overlapMax)),y:firstStart.y}}if(firstIsVertical&&secondIsVertical&&Math.abs(firstStart.x-secondStart.x)<=EPS6){let overlapMin=Math.max(Math.min(firstStart.y,firstEnd.y),Math.min(secondStart.y,secondEnd.y)),overlapMax=Math.min(Math.max(firstStart.y,firstEnd.y),Math.max(secondStart.y,secondEnd.y));return overlapMin>overlapMax+EPS6?null:{x:firstStart.x,y:Math.max(overlapMin,Math.min(firstStart.y,overlapMax))}}return null},clipPathAtFirstIntersection=(tracePath,existingTraces)=>{for(let pathIndex=0;pathIndex<tracePath.length-1;pathIndex++){let pathStart=tracePath[pathIndex],pathEnd=tracePath[pathIndex+1],intersections=existingTraces.flatMap(trace=>trace.tracePath.slice(0,-1).flatMap((traceStart,traceIndex)=>{let intersection2=getAxisAlignedIntersection(pathStart,pathEnd,traceStart,trace.tracePath[traceIndex+1]);return intersection2?[intersection2]:[]}));intersections.sort((first,second)=>distance32(pathStart,first)-distance32(pathStart,second));let intersection=intersections[0];if(!intersection)continue;let clippedPath=tracePath.slice(0,pathIndex+1);return distance32(clippedPath.at(-1),intersection)>EPS6&&clippedPath.push(intersection),clippedPath}return null},LongDistancePairSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"params");__publicField(this,"solvedLongDistanceTraces",[]);__publicField(this,"queuedCandidatePairs",[]);__publicField(this,"currentCandidatePair",null);__publicField(this,"queuedFailedConnectionPairs",[]);__publicField(this,"currentFailedConnectionPair",null);__publicField(this,"subSolver",null);__publicField(this,"chipMap",{});__publicField(this,"inputProblem");__publicField(this,"netConnMap");__publicField(this,"newlyConnectedPinIds",new Set);__publicField(this,"allSolvedTraces",[]);__publicField(this,"maxMspPairDistance");this.params=params;let{inputProblem,primaryMspConnectionPairs,alreadySolvedTraces}=this.params;this.inputProblem=inputProblem,this.allSolvedTraces=[...alreadySolvedTraces],this.maxMspPairDistance=inputProblem.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE;let primaryConnectedPinIds=new Set;for(let pair of primaryMspConnectionPairs)primaryConnectedPinIds.add(pair.pins[0].pinId),primaryConnectedPinIds.add(pair.pins[1].pinId);let{netConnMap}=getConnectivityMapsFromInputProblem(inputProblem);this.netConnMap=netConnMap;let pinMap=new Map;for(let chip of inputProblem.chips){this.chipMap[chip.chipId]=chip;for(let pin of chip.pins)pinMap.set(pin.pinId,{...pin,chipId:chip.chipId})}this.queuedFailedConnectionPairs=this.params.failedConnectionPairs.filter(connectionPair=>isLabeledPeripheralConnection({inputProblem:this.inputProblem,chipMap:this.chipMap,pins:connectionPair.pins}));let candidatePairs=[],addedPairKeys=new Set;for(let netId of Object.keys(netConnMap.netMap)){let allPinIdsInNet=netConnMap.getIdsConnectedToNet(netId);if(allPinIdsInNet.length<2)continue;let unconnectedPinIds=allPinIdsInNet.filter(pinId=>!primaryConnectedPinIds.has(pinId));for(let unconnectedPinId of unconnectedPinIds){let sourcePin=pinMap.get(unconnectedPinId);if(!sourcePin)continue;let neighbors=allPinIdsInNet.filter(otherPinId=>otherPinId!==unconnectedPinId).flatMap(otherPinId=>{let targetPin=pinMap.get(otherPinId);return targetPin?inputProblem.netConnections.some(connection=>connection.pinIds.length===2&&connection.pinIds.includes(sourcePin.pinId)&&connection.pinIds.includes(targetPin.pinId))&&manhattanDistance(sourcePin,targetPin)>this.maxMspPairDistance?[]:[{pin:targetPin,distance:distance32(sourcePin,targetPin)}]:[]}).sort((a6,b6)=>a6.distance-b6.distance).slice(0,NEAREST_NEIGHBOR_COUNT);for(let neighbor of neighbors){let pair=[sourcePin,neighbor.pin];if(arePinsInDifferentSchematicSections(inputProblem,pair[0],pair[1]))continue;let pairKey=pair.map(p3=>p3.pinId).sort().join("--");addedPairKeys.has(pairKey)||(candidatePairs.push(pair),addedPairKeys.add(pairKey))}}}this.queuedCandidatePairs=candidatePairs}getConstructorParams(){return this.params}acceptFailedConnectionPair(tracePath){let connectionPair=this.currentFailedConnectionPair;if(!connectionPair)return;let solvedTrace={...connectionPair,tracePath,mspConnectionPairIds:[connectionPair.mspPairId],pinIds:connectionPair.pins.map(pin=>pin.pinId)};this.solvedLongDistanceTraces.push(solvedTrace),this.allSolvedTraces.push(solvedTrace);for(let pin of connectionPair.pins)this.newlyConnectedPinIds.add(pin.pinId)}_step(){if(this.subSolver?.solved&&this.currentFailedConnectionPair){let tracePath=this.subSolver.solvedTracePath;tracePath&&this.acceptFailedConnectionPair(tracePath),this.subSolver=null,this.currentCandidatePair=null,this.currentFailedConnectionPair=null}else if(this.subSolver?.solved){let newTracePath=this.subSolver.solvedTracePath;if(newTracePath&&this.currentCandidatePair){let[p12,p22]=this.currentCandidatePair,globalConnNetId=this.netConnMap.getNetConnectedToId(p12.pinId),sameNetTraces=this.allSolvedTraces.filter(trace=>trace.globalConnNetId===globalConnNetId),inputNetConnection=this.inputProblem.netConnections.find(connection=>connection.pinIds.length===3&&connection.pinIds.includes(p12.pinId)&&connection.pinIds.includes(p22.pinId)),sourceChip=this.chipMap[p12.chipId],targetRailTrace=sameNetTraces.find(trace=>trace.pinIds.includes(p22.pinId)&&trace.pins.every(pin=>pin.chipId===p22.chipId)),junctionTracePath=inputNetConnection!==void 0&&sourceChip?.pins.length===2&&targetRailTrace!==void 0?clipPathAtFirstIntersection(newTracePath,sameNetTraces):null,acceptedTracePath=junctionTracePath??newTracePath,tracesToCheck=junctionTracePath?this.allSolvedTraces.filter(trace=>trace.globalConnNetId!==globalConnNetId):this.allSolvedTraces;if(!doesTraceOverlapWithExistingTraces(acceptedTracePath,tracesToCheck)){let mspPairId=`${p12.pinId}-${p22.pinId}`,newSolvedTrace={mspPairId,dcConnNetId:globalConnNetId,globalConnNetId,pins:[p12,p22],tracePath:acceptedTracePath,mspConnectionPairIds:[mspPairId],pinIds:[p12.pinId,p22.pinId]};this.solvedLongDistanceTraces.push(newSolvedTrace),this.allSolvedTraces.push(newSolvedTrace),this.newlyConnectedPinIds.add(p12.pinId),this.newlyConnectedPinIds.add(p22.pinId)}}this.subSolver=null,this.currentCandidatePair=null}else this.subSolver?.failed&&(this.subSolver=null,this.currentCandidatePair=null,this.currentFailedConnectionPair=null);if(this.subSolver){this.subSolver.step();return}let failedConnectionPair=this.queuedFailedConnectionPairs.shift();if(failedConnectionPair){this.currentFailedConnectionPair=failedConnectionPair,this.currentCandidatePair=failedConnectionPair.pins,this.subSolver=new SchematicTraceSingleLineSolver2({inputProblem:this.params.inputProblem,pins:failedConnectionPair.pins,chipMap:this.chipMap});return}for(;this.queuedCandidatePairs.length>0;){let nextPair=this.queuedCandidatePairs.shift(),[p12,p22]=nextPair;if(!(this.newlyConnectedPinIds.has(p12.pinId)||this.newlyConnectedPinIds.has(p22.pinId))){this.currentCandidatePair=nextPair,this.subSolver=new SchematicTraceSingleLineSolver2({inputProblem:this.params.inputProblem,pins:this.currentCandidatePair,chipMap:this.chipMap});return}}this.solved=!0}visualize(){if(this.subSolver)return this.subSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);for(let trace of this.solvedLongDistanceTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let[p12,p22]of this.queuedCandidatePairs)graphics.lines.push({points:[p12,p22],strokeColor:"gray",strokeDash:"4 4"});return graphics}getOutput(){return this.solved?{newTraces:this.solvedLongDistanceTraces,allTracesMerged:[...this.params.alreadySolvedTraces,...this.solvedLongDistanceTraces]}:{newTraces:[],allTracesMerged:this.params.alreadySolvedTraces}}},hasCollisions=(pathSegments,obstacles)=>{for(let i6=0;i6<pathSegments.length-1;i6++){let p12=pathSegments[i6],p22=pathSegments[i6+1];for(let obstacle of obstacles){let box2={center:{x:obstacle.minX+(obstacle.maxX-obstacle.minX)/2,y:obstacle.minY+(obstacle.maxY-obstacle.minY)/2},width:obstacle.maxX-obstacle.minX,height:obstacle.maxY-obstacle.minY};if(segmentToBoxMinDistance(p12,p22,box2)<=0)return!0}}return!1},countTurns=points=>{let turns=0;for(let i6=1;i6<points.length-1;i6++){let prev=points[i6-1],curr=points[i6],next2=points[i6+1],prevVertical=prev.x===curr.x,nextVertical=curr.x===next2.x;prevVertical!==nextVertical&&turns++}return turns},tryConnectPoints=(start,end)=>{let candidates=[];return start.x===end.x||start.y===end.y?candidates.push([start,end]):(candidates.push([start,{x:end.x,y:start.y},end]),candidates.push([start,{x:start.x,y:end.y},end])),candidates},hasCollisionsWithLabels=(pathSegments,labels)=>{for(let i6=0;i6<pathSegments.length-1;i6++){let p12=pathSegments[i6],p22=pathSegments[i6+1];for(let label of labels)if(segmentIntersectsRect(p12,p22,label))return!0}return!1},recognizeStairStepPattern=(pathToCheck,startIdx)=>{if(startIdx>=pathToCheck.length-3)return-1;let endIdx=startIdx,isStairStep=!0;for(let i6=startIdx;i6<pathToCheck.length-2&&i6<startIdx+10&&!(i6+2>=pathToCheck.length);i6++){let p12=pathToCheck[i6],p22=pathToCheck[i6+1],p3=pathToCheck[i6+2],seg1Vertical=p12.x===p22.x,seg2Vertical=p22.x===p3.x;if(seg1Vertical===seg2Vertical)break;let seg1Direction=Math.sign(seg1Vertical?p22.y-p12.y:p22.x-p12.x);if(i6>startIdx){let prevP=pathToCheck[i6-1],prevSegVertical=prevP.x===p12.x,prevDirection=Math.sign(prevSegVertical?p12.y-prevP.y:p12.x-prevP.x);if(seg1Vertical&&prevSegVertical&&seg1Direction!==prevDirection||!seg1Vertical&&!prevSegVertical&&seg1Direction!==prevDirection){isStairStep=!1;break}}endIdx=i6+2}return isStairStep&&endIdx-startIdx>=3?endIdx:-1},isSegmentAnEndpointSegment=(p12,p22,originalPath)=>{if(originalPath.length<2)return!1;let originalStart=originalPath[0],originalEnd=originalPath[originalPath.length-1];return p12.x===originalStart.x&&p12.y===originalStart.y&&p22.x===originalPath[1].x&&p22.y===originalPath[1].y||p12.x===originalPath[originalPath.length-2].x&&p12.y===originalPath[originalPath.length-2].y&&p22.x===originalEnd.x&&p22.y===originalEnd.y},minimizeTurns=({path,obstacles,labelBounds,originalPath})=>{if(path.length<=2)return path;let optimizedPath=[...path],currentTurns=countTurns(optimizedPath),improved=!0;for(;improved;){improved=!1;for(let startIdx=0;startIdx<optimizedPath.length-3;startIdx++){let stairEndIdx=recognizeStairStepPattern(optimizedPath,startIdx);if(stairEndIdx>0){if(isSegmentAnEndpointSegment(optimizedPath[startIdx],optimizedPath[startIdx+1],originalPath)||isSegmentAnEndpointSegment(optimizedPath[stairEndIdx-1],optimizedPath[stairEndIdx],originalPath))continue;let startPoint=optimizedPath[startIdx],endPoint=optimizedPath[stairEndIdx],connectionOptions=tryConnectPoints(startPoint,endPoint);for(let connection of connectionOptions){let testPath=[...optimizedPath.slice(0,startIdx+1),...connection.slice(1,-1),...optimizedPath.slice(stairEndIdx)],collidesWithObstacles=hasCollisions(connection,obstacles),collidesWithLabels=hasCollisionsWithLabels(connection,labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){let newTurns=countTurns(testPath);optimizedPath=testPath,currentTurns=newTurns,improved=!0;break}}if(improved)break}}if(!improved)for(let startIdx=0;startIdx<optimizedPath.length-2;startIdx++){let maxRemove=Math.min(optimizedPath.length-startIdx-2,optimizedPath.length-2);for(let removeCount=1;removeCount<=maxRemove;removeCount++){let endIdx=startIdx+removeCount+1;if(endIdx>=optimizedPath.length||isSegmentAnEndpointSegment(optimizedPath[startIdx],optimizedPath[startIdx+1],originalPath)||isSegmentAnEndpointSegment(optimizedPath[endIdx-1],optimizedPath[endIdx],originalPath))continue;let startPoint=optimizedPath[startIdx],endPoint=optimizedPath[endIdx],connectionOptions=tryConnectPoints(startPoint,endPoint);for(let connection of connectionOptions){let testPath=[...optimizedPath.slice(0,startIdx+1),...connection.slice(1,-1),...optimizedPath.slice(endIdx)],connectionSegments=connection,collidesWithObstacles=hasCollisions(connectionSegments,obstacles),collidesWithLabels=hasCollisionsWithLabels(connectionSegments,labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){let newTurns=countTurns(testPath);if(newTurns<currentTurns||newTurns===currentTurns&&testPath.length<optimizedPath.length){optimizedPath=testPath,currentTurns=newTurns,improved=!0;break}}}if(improved)break}if(improved)break}if(!improved)for(let i6=0;i6<optimizedPath.length-2;i6++){let p12=optimizedPath[i6],p22=optimizedPath[i6+1],p3=optimizedPath[i6+2];if(isSegmentAnEndpointSegment(p12,p22,originalPath)||isSegmentAnEndpointSegment(p22,p3,originalPath))continue;let allVertical=p12.x===p22.x&&p22.x===p3.x,allHorizontal=p12.y===p22.y&&p22.y===p3.y;if(allVertical||allHorizontal){let testPath=[...optimizedPath.slice(0,i6+1),...optimizedPath.slice(i6+2)],collidesWithObstacles=hasCollisions([p12,p3],obstacles),collidesWithLabels=hasCollisionsWithLabels([p12,p3],labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){optimizedPath=testPath,improved=!0;break}}}}return simplifyPath(optimizedPath)},RAIL_ALIGNMENT_EPSILON=.002,nearlyEqual=(a6,b6)=>Math.abs(a6-b6)<RAIL_ALIGNMENT_EPSILON,isHorizontal2=(a6,b6)=>nearlyEqual(a6.y,b6.y),isVertical2=(a6,b6)=>nearlyEqual(a6.x,b6.x),isPositiveLength=(a6,b6)=>Math.abs(a6.x-b6.x)>=RAIL_ALIGNMENT_EPSILON||Math.abs(a6.y-b6.y)>=RAIL_ALIGNMENT_EPSILON,getRailOrientation=(a6,b6)=>isPositiveLength(a6,b6)?isVertical2(a6,b6)?"vertical":isHorizontal2(a6,b6)?"horizontal":null:null,rangesTouchOrOverlap=(a6,b6)=>Math.min(a6.maxAlong,b6.maxAlong)-Math.max(a6.minAlong,b6.minAlong)>=-RAIL_ALIGNMENT_EPSILON,pointsEqual2=(a6,b6)=>nearlyEqual(a6.x,b6.x)&&nearlyEqual(a6.y,b6.y),getDistinctCoordinates=coordinates=>{let distinct=[];for(let coordinate of coordinates)distinct.some(item=>nearlyEqual(item,coordinate))||distinct.push(coordinate);return distinct},getMergedIntervalMetrics=intervals=>{let groups=[];for(let interval of intervals){let group=groups.find(items=>nearlyEqual(items[0].coordinate,interval.coordinate));group?group.push(interval):groups.push([interval])}return groups.reduce((total,group)=>{let sorted=[...group].sort((a6,b6)=>a6.min-b6.min),groupLength=0,segmentCount=1,currentMin=sorted[0].min,currentMax=sorted[0].max;for(let interval of sorted.slice(1))interval.min<=currentMax+RAIL_ALIGNMENT_EPSILON?currentMax=Math.max(currentMax,interval.max):(groupLength+=currentMax-currentMin,segmentCount++,currentMin=interval.min,currentMax=interval.max);return{length:total.length+groupLength+currentMax-currentMin,segmentCount:total.segmentCount+segmentCount}},{length:0,segmentCount:0})},getVisibleTraceMetrics=traces=>{let horizontal=[],vertical=[];for(let trace of traces)for(let index=0;index<trace.tracePath.length-1;index++){let start=trace.tracePath[index],end=trace.tracePath[index+1];isHorizontal2(start,end)?horizontal.push({coordinate:start.y,min:Math.min(start.x,end.x),max:Math.max(start.x,end.x)}):isVertical2(start,end)&&vertical.push({coordinate:start.x,min:Math.min(start.y,end.y),max:Math.max(start.y,end.y)})}let horizontalMetrics=getMergedIntervalMetrics(horizontal),verticalMetrics=getMergedIntervalMetrics(vertical);return{length:horizontalMetrics.length+verticalMetrics.length,segmentCount:horizontalMetrics.segmentCount+verticalMetrics.segmentCount}},getVisibleTraceLength=traces=>getVisibleTraceMetrics(traces).length,getVisibleTraceSegmentCount=traces=>getVisibleTraceMetrics(traces).segmentCount,MIN_EXCESSIVE_DETOUR_LENGTH_RATIO=2.5,getTracePathLength=tracePath=>{let pathLength4=0;for(let pointIndex=1;pointIndex<tracePath.length;pointIndex++){let previousPoint=tracePath[pointIndex-1],point6=tracePath[pointIndex];pathLength4+=Math.abs(point6.x-previousPoint.x)+Math.abs(point6.y-previousPoint.y)}return pathLength4},shortenExcessiveLabelPaddingDetour=({inputProblem,trace})=>{let exactConnection=inputProblem.directConnections.find(connection=>connection.pinIds.every(pinId=>trace.pinIds.includes(pinId)));if(!exactConnection)return trace;let chipMap={};for(let chip of inputProblem.chips)chipMap[chip.chipId]=chip;let candidateSolver=new SchematicTraceSingleLineSolver2({pins:trace.pins,connectionPair:trace,inputProblem:{...inputProblem,directConnections:[exactConnection,...inputProblem.directConnections.filter(connection=>connection!==exactConnection)]},chipMap});if(candidateSolver.solve(),!candidateSolver.solvedTracePath)return trace;let currentLength=getTracePathLength(trace.tracePath),candidateLength=getTracePathLength(candidateSolver.solvedTracePath);return currentLength<=candidateLength*MIN_EXCESSIVE_DETOUR_LENGTH_RATIO?trace:{...trace,tracePath:candidateSolver.solvedTracePath}},minimizeTurnsWithFilteredLabels=({targetMspConnectionPairId,traces,inputProblem,allLabelPlacements,mergedLabelNetIdMap,paddingBuffer})=>{let originalTargetTrace=traces.find(t53=>t53.mspPairId===targetMspConnectionPairId);if(!originalTargetTrace)throw new Error(`Target trace ${targetMspConnectionPairId} not found`);let targetTrace=shortenExcessiveLabelPaddingDetour({inputProblem,trace:originalTargetTrace}),targetPinIds=new Set(targetTrace.pinIds),otherTraces=traces.filter(trace=>trace.mspPairId!==targetMspConnectionPairId),relaxedObstacleTraces=otherTraces.filter(trace=>{let sharesEndpoint=trace.pinIds.some(pinId=>targetPinIds.has(pinId));return trace.globalConnNetId!==targetTrace.globalConnNetId||!sharesEndpoint}),TRACE_WIDTH=.01,getTraceObstacles2=obstacleTraces=>obstacleTraces.flatMap((trace,i6)=>trace.tracePath.slice(0,-1).map((p12,pi3)=>{let p22=trace.tracePath[pi3+1];return{chipId:`trace-obstacle-${i6}-${pi3}`,minX:Math.min(p12.x,p22.x)-TRACE_WIDTH/2,minY:Math.min(p12.y,p22.y)-TRACE_WIDTH/2,maxX:Math.max(p12.x,p22.x)+TRACE_WIDTH/2,maxY:Math.max(p12.y,p22.y)+TRACE_WIDTH/2}})),staticObstaclesRaw=getObstacleRects(inputProblem),PADDING=.01,staticObstacles=staticObstaclesRaw.map(obs=>({...obs,minX:obs.minX-PADDING,minY:obs.minY-PADDING,maxX:obs.maxX+PADDING,maxY:obs.maxY+PADDING})),originalPath=targetTrace.tracePath,labelBounds=allLabelPlacements.filter(label=>{let originalNetIds=mergedLabelNetIdMap[label.globalConnNetId];return originalNetIds?!originalNetIds.has(targetTrace.globalConnNetId):label.globalConnNetId!==targetTrace.globalConnNetId}).map(nl3=>({minX:nl3.center.x-nl3.width/2-paddingBuffer,maxX:nl3.center.x+nl3.width/2+paddingBuffer,minY:nl3.center.y-nl3.height/2-paddingBuffer,maxY:nl3.center.y+nl3.height/2+paddingBuffer})),strictPath=minimizeTurns({path:originalPath,obstacles:[...staticObstacles,...getTraceObstacles2(otherTraces)],labelBounds,originalPath}),relaxedPath=minimizeTurns({path:originalPath,obstacles:[...staticObstacles,...getTraceObstacles2(relaxedObstacleTraces)],labelBounds,originalPath}),sameNetTraces=otherTraces.filter(trace=>trace.globalConnNetId===targetTrace.globalConnNetId),getSameNetReadability=tracePath=>{let tracesWithCandidate=[...sameNetTraces,{...targetTrace,tracePath}];return{segmentCount:getVisibleTraceSegmentCount(tracesWithCandidate),visibleLength:getVisibleTraceLength(tracesWithCandidate)}},strictTurns=countTurns(strictPath),relaxedTurns=countTurns(relaxedPath),newPath=strictPath;if(relaxedTurns<strictTurns)newPath=relaxedPath;else if(relaxedTurns===strictTurns){let strictReadability=getSameNetReadability(strictPath),relaxedReadability=getSameNetReadability(relaxedPath);(relaxedReadability.segmentCount<strictReadability.segmentCount||relaxedReadability.segmentCount===strictReadability.segmentCount&&relaxedReadability.visibleLength<strictReadability.visibleLength-RAIL_ALIGNMENT_EPSILON)&&(newPath=relaxedPath)}return{...targetTrace,tracePath:newPath}},balanceZShapes=({targetMspConnectionPairId,traces,inputProblem,allLabelPlacements,mergedLabelNetIdMap,paddingBuffer})=>{let targetTrace=traces.find(t53=>t53.mspPairId===targetMspConnectionPairId);if(!targetTrace)throw new Error(`Target trace ${targetMspConnectionPairId} not found`);let TOLERANCE2=1e-5,coordsEqual=(a6,b6)=>Math.abs(a6-b6)<TOLERANCE2,obstacleTraces=traces.filter(t53=>t53.mspPairId!==targetMspConnectionPairId),TRACE_WIDTH=.01,traceObstacles=obstacleTraces.flatMap((trace,i6)=>trace.tracePath.slice(0,-1).map((p12,pi3)=>{let p22=trace.tracePath[pi3+1];return{chipId:`trace-obstacle-${i6}-${pi3}`,minX:Math.min(p12.x,p22.x)-TRACE_WIDTH/2,minY:Math.min(p12.y,p22.y)-TRACE_WIDTH/2,maxX:Math.max(p12.x,p22.x)+TRACE_WIDTH/2,maxY:Math.max(p12.y,p22.y)+TRACE_WIDTH/2}})),combinedObstacles=[...getObstacleRects(inputProblem).map(obs=>({...obs,minX:obs.minX+TOLERANCE2,maxX:obs.maxX-TOLERANCE2,minY:obs.minY+TOLERANCE2,maxY:obs.maxY-TOLERANCE2})),...traceObstacles],segmentIntersectsAnyRect=(p12,p22,rects)=>{for(let rect of rects)if(segmentIntersectsRect(p12,p22,rect))return!0;return!1},labelBounds=allLabelPlacements.filter(label=>{let originalNetIds=mergedLabelNetIdMap[label.globalConnNetId];return originalNetIds?!originalNetIds.has(targetTrace.globalConnNetId):label.globalConnNetId!==targetTrace.globalConnNetId}).map(nl3=>({minX:nl3.center.x-nl3.width/2+TOLERANCE2,maxX:nl3.center.x+nl3.width/2-TOLERANCE2,minY:nl3.center.y-nl3.height/2+TOLERANCE2,maxY:nl3.center.y+nl3.height/2-TOLERANCE2})),newPath=[...targetTrace.tracePath];if(newPath.length<4)return{...targetTrace};if(newPath.length===4){let[p03,p12,p22,p3]=newPath,p1New,p2New;if(coordsEqual(p03.y,p12.y)&&coordsEqual(p12.x,p22.x)&&coordsEqual(p22.y,p3.y)){let idealX=(p03.x+p3.x)/2;p1New={x:idealX,y:p12.y},p2New={x:idealX,y:p22.y}}else{let idealY=(p03.y+p3.y)/2;p1New={x:p12.x,y:idealY},p2New={x:p22.x,y:idealY}}return segmentIntersectsAnyRect(p03,p1New,combinedObstacles)||segmentIntersectsAnyRect(p1New,p2New,combinedObstacles)||segmentIntersectsAnyRect(p2New,p3,combinedObstacles)||segmentIntersectsAnyRect(p03,p1New,labelBounds)||segmentIntersectsAnyRect(p1New,p2New,labelBounds)||segmentIntersectsAnyRect(p2New,p3,labelBounds)||(newPath[1]=p1New,newPath[2]=p2New),{...targetTrace,tracePath:simplifyPath(newPath)}}for(let i6=1;i6<newPath.length-4;i6++){let p12=newPath[i6],p22=newPath[i6+1],p3=newPath[i6+2],p42=newPath[i6+3],isHVHZShape=coordsEqual(p12.y,p22.y)&&coordsEqual(p22.x,p3.x)&&coordsEqual(p3.y,p42.y),isVHVZShape=coordsEqual(p12.x,p22.x)&&coordsEqual(p22.y,p3.y)&&coordsEqual(p3.x,p42.x),isCollinearHorizontal=coordsEqual(p12.y,p22.y)&&coordsEqual(p22.y,p3.y)&&coordsEqual(p3.y,p42.y),isCollinearVertical=coordsEqual(p12.x,p22.x)&&coordsEqual(p22.x,p3.x)&&coordsEqual(p3.x,p42.x),isCollinear2=isCollinearHorizontal||isCollinearVertical,isSameDirection=!1;if(isHVHZShape?isSameDirection=Math.sign(p22.x-p12.x)===Math.sign(p42.x-p3.x):isVHVZShape&&(isSameDirection=Math.sign(p22.y-p12.y)===Math.sign(p42.y-p3.y)),!((isHVHZShape||isVHVZShape)&&!isCollinear2&&isSameDirection))continue;let p2New,p3New,len1Original=Math.abs(isHVHZShape?p12.x-p22.x:p12.y-p22.y),len2Original=Math.abs(isHVHZShape?p3.x-p42.x:p3.y-p42.y);if(Math.abs(len1Original-len2Original)<.001)continue;if(isHVHZShape){let idealX=(p12.x+p42.x)/2;p2New={x:idealX,y:p22.y},p3New={x:idealX,y:p3.y}}else{let idealY=(p12.y+p42.y)/2;p2New={x:p22.x,y:idealY},p3New={x:p3.x,y:idealY}}segmentIntersectsAnyRect(p12,p2New,combinedObstacles)||segmentIntersectsAnyRect(p2New,p3New,combinedObstacles)||segmentIntersectsAnyRect(p3New,p42,combinedObstacles)||segmentIntersectsAnyRect(p12,p2New,labelBounds)||segmentIntersectsAnyRect(p2New,p3New,labelBounds)||segmentIntersectsAnyRect(p3New,p42,labelBounds)||(newPath[i6+1]=p2New,newPath[i6+2]=p3New,i6=0)}let finalSimplifiedPath=simplifyPath(newPath);return{...targetTrace,tracePath:finalSimplifiedPath}},getAlongBounds=(orientation4,minAlong,maxAlong)=>orientation4==="vertical"?{minX:0,maxX:0,minY:minAlong,maxY:maxAlong}:{minX:minAlong,maxX:maxAlong,minY:0,maxY:0},hasPositiveAlongOverlap=(orientation4,first,second)=>{let overlap=boundsIntersection(first,second);return overlap?(orientation4==="vertical"?overlap.maxY-overlap.minY:overlap.maxX-overlap.minX)>RAIL_ALIGNMENT_EPSILON:!1},getRailAlignmentFallbackCoordinates=({group,originalCoordinates,otherNetTraces})=>{let orientation4=group[0].orientation,groupAlongBounds=group.map(segment2=>getAlongBounds(orientation4,segment2.minAlong,segment2.maxAlong)),fallbackClearance=SCHEMATIC_TRACE_MIN_VISUAL_CENTERLINE_CLEARANCE,coordinates=[];for(let trace of otherNetTraces)for(let index=0;index<trace.tracePath.length-1;index++){let start=trace.tracePath[index],end=trace.tracePath[index+1];if(getRailOrientation(start,end)!==orientation4)continue;let minAlong=orientation4==="vertical"?Math.min(start.y,end.y):Math.min(start.x,end.x),maxAlong=orientation4==="vertical"?Math.max(start.y,end.y):Math.max(start.x,end.x),traceAlongBounds=getAlongBounds(orientation4,minAlong,maxAlong);if(!groupAlongBounds.some(bounds=>hasPositiveAlongOverlap(orientation4,bounds,traceAlongBounds)))continue;let coordinate=orientation4==="vertical"?start.x:start.y;originalCoordinates.some(originalCoordinate=>Math.abs(originalCoordinate-coordinate)<=SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE)&&coordinates.push(coordinate-fallbackClearance,coordinate+fallbackClearance)}return getDistinctCoordinates(coordinates)},moveRailSegments=(trace,segments,coordinate)=>{let pointsToMove=new Set;for(let segment2 of segments)pointsToMove.add(segment2.segmentIndex),pointsToMove.add(segment2.segmentIndex+1);let orientation4=segments[0].orientation,tracePath=simplifyPath(trace.tracePath.map((point6,index)=>pointsToMove.has(index)?orientation4==="vertical"?{...point6,x:coordinate}:{...point6,y:coordinate}:point6));return{...trace,tracePath}},EPS7=1e-6,isTraceLine=trace=>getUniquePinCount(trace.pinIds)>=2,rectsOverlap=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>EPS7&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>EPS7,getTraceCorners=path=>{let corners=[];for(let i6=1;i6<path.length-1;i6++){let previousPoint=path[i6-1],cornerPoint=path[i6],nextPoint=path[i6+1];isTraceCorner(previousPoint,cornerPoint,nextPoint)&&corners.push(cornerPoint)}return corners},tracePathContainsPoint=(path,point6)=>{for(let i6=0;i6<path.length-1;i6++)if(isPointOnSegment4(point6,path[i6],path[i6+1]))return!0;return!1},getDistance=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),getUniquePinCount=pinIds=>new Set(pinIds).size,isTraceCorner=(a6,b6,c3)=>getSegmentOrientation(a6,b6)!==getSegmentOrientation(b6,c3),isPointOnSegment4=(point6,start,end)=>getSegmentOrientation(start,end)==="horizontal"?Math.abs(point6.y-start.y)<=EPS7&&point6.x>=Math.min(start.x,end.x)-EPS7&&point6.x<=Math.max(start.x,end.x)+EPS7:Math.abs(point6.x-start.x)<=EPS7&&point6.y>=Math.min(start.y,end.y)-EPS7&&point6.y<=Math.max(start.y,end.y)+EPS7,getSegmentOrientation=(a6,b6)=>Math.abs(a6.y-b6.y)<=EPS7?"horizontal":"vertical",getAnchoredTraceIds=(label,traces)=>new Set(traces.filter(trace=>trace.globalConnNetId===label.globalConnNetId&&tracePathContainsPoint(trace.tracePath,label.anchorPoint)).map(trace=>trace.mspPairId)),preservesLabelAnchors=(labels,before,after)=>labels.every(label=>{let anchoredBefore=getAnchoredTraceIds(label,before);if(anchoredBefore.size===0)return!0;let anchoredAfter=getAnchoredTraceIds(label,after);return[...anchoredBefore].every(traceId=>anchoredAfter.has(traceId))}),EPS8=1e-9,segmentRunsAlongRectBoundary=(start,end,rect)=>{let isVertical52=Math.abs(start.x-end.x)<EPS8,isHorizontal42=Math.abs(start.y-end.y)<EPS8;return isVertical52?Math.abs(start.x-rect.minX)<EPS8||Math.abs(start.x-rect.maxX)<EPS8:isHorizontal42?Math.abs(start.y-rect.minY)<EPS8||Math.abs(start.y-rect.maxY)<EPS8:!1},getPathKey=path=>path.map(point6=>`${point6.x},${point6.y}`).join(";"),getPathLength2=path=>{let length4=0;for(let i6=0;i6<path.length-1;i6++)length4+=Math.abs(path[i6+1].x-path[i6].x)+Math.abs(path[i6+1].y-path[i6].y);return length4},getDistance2=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),isAxisAlignedSegment=(start,end)=>Math.abs(start.x-end.x)<EPS8||Math.abs(start.y-end.y)<EPS8,getSegmentOrientation2=(start,end)=>Math.abs(start.y-end.y)<EPS8?"horizontal":"vertical",projectPointToSegment=(point6,start,end)=>Math.abs(start.x-end.x)<EPS8?{x:start.x,y:Math.min(Math.max(point6.y,Math.min(start.y,end.y)),Math.max(start.y,end.y))}:Math.abs(start.y-end.y)<EPS8?{x:Math.min(Math.max(point6.x,Math.min(start.x,end.x)),Math.max(start.x,end.x)),y:start.y}:start,getPointToSegmentDistance=(point6,start,end)=>getDistance2(point6,projectPointToSegment(point6,start,end)),getSegments=path=>{let segments=[];for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];isAxisAlignedSegment(start,end)&&segments.push({start,end,orientation:getSegmentOrientation2(start,end)})}return segments},findSegmentContainingPoint=(path,point6)=>{for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];if(isAxisAlignedSegment(start,end)&&!(getPointToSegmentDistance(point6,start,end)>1e-6))return{index:i6,start,end,orientation:getSegmentOrientation2(start,end)}}return null},isPointWithinSegmentPrimaryRange=(point6,segment2)=>segment2.orientation==="horizontal"?point6.x>=Math.min(segment2.start.x,segment2.end.x)-EPS8&&point6.x<=Math.max(segment2.start.x,segment2.end.x)+EPS8:point6.y>=Math.min(segment2.start.y,segment2.end.y)-EPS8&&point6.y<=Math.max(segment2.start.y,segment2.end.y)+EPS8,findPreferredReroutedSegment=(path,originalSegmentIndex,originalSegmentCount,orientation4,anchorPoint)=>{let matchingSegments=getSegments(path).filter(segment2=>segment2.orientation===orientation4);if(matchingSegments.length===0)return null;let containingSegments=matchingSegments.filter(segment2=>isPointWithinSegmentPrimaryRange(anchorPoint,segment2)),candidateSegments=containingSegments.length>0?containingSegments:matchingSegments;return originalSegmentIndex<originalSegmentCount/2?candidateSegments[0]:candidateSegments[candidateSegments.length-1]},projectPointToPath=(point6,path)=>{let bestPoint=null,bestDistance=Number.POSITIVE_INFINITY;for(let i6=0;i6<path.length-1;i6++){let projectedPoint=projectPointToSegment(point6,path[i6],path[i6+1]),distance52=getDistance2(point6,projectedPoint);distance52<bestDistance&&(bestPoint=projectedPoint,bestDistance=distance52)}return bestPoint},segmentsIntersect2=(a12,a22,b12,b22)=>{let aVertical=Math.abs(a12.x-a22.x)<EPS8,bVertical=Math.abs(b12.x-b22.x)<EPS8,between2=(value,p12,p22)=>value>=Math.min(p12,p22)-EPS8&&value<=Math.max(p12,p22)+EPS8;if(aVertical&&bVertical)return Math.abs(a12.x-b12.x)>EPS8?!1:Math.min(Math.max(a12.y,a22.y),Math.max(b12.y,b22.y))-Math.max(Math.min(a12.y,a22.y),Math.min(b12.y,b22.y))>EPS8;if(!aVertical&&!bVertical)return Math.abs(a12.y-b12.y)>EPS8?!1:Math.min(Math.max(a12.x,a22.x),Math.max(b12.x,b22.x))-Math.max(Math.min(a12.x,a22.x),Math.min(b12.x,b22.x))>EPS8;let verticalA=aVertical?a12:b12,verticalB=aVertical?a22:b22,horizontalA=aVertical?b12:a12,horizontalB=aVertical?b22:a22;return between2(verticalA.x,horizontalA.x,horizontalB.x)&&between2(horizontalA.y,verticalA.y,verticalB.y)},countPathIntersections=(pathA,pathB)=>{let count=0;for(let i6=0;i6<pathA.length-1;i6++)for(let j6=0;j6<pathB.length-1;j6++)segmentsIntersect2(pathA[i6],pathA[i6+1],pathB[j6],pathB[j6+1])&&count++;return count},isPathCollidingWithChipInterior=(path,chipObstacles)=>{for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];for(let obstacle of chipObstacles)if(segmentIntersectsRect(start,end,obstacle)&&!segmentRunsAlongRectBoundary(start,end,obstacle))return!0}return!1},countOtherNetCrossings=(traces,allTraces)=>{let crossings=0;for(let trace of traces)for(let otherTrace of allTraces)trace.globalConnNetId!==otherTrace.globalConnNetId&&(crossings+=countPathIntersections(trace.tracePath,otherTrace.tracePath));return crossings},getTraceGeometryMetrics=(traces,allTraces)=>({turnCount:traces.reduce((total,trace)=>total+countTurns(trace.tracePath),0),visibleLength:getVisibleTraceLength(traces),pathLength:traces.reduce((sum,trace)=>sum+getPathLength2(trace.tracePath),0),otherNetCrossings:countOtherNetCrossings(traces,allTraces)}),scoreIsBetter=(candidate,best)=>candidate.turnCount!==best.turnCount?candidate.turnCount<best.turnCount:nearlyEqual(candidate.visibleLength,best.visibleLength)?nearlyEqual(candidate.pathLength,best.pathLength)?candidate.otherNetCrossings!==best.otherNetCrossings?candidate.otherNetCrossings<best.otherNetCrossings:nearlyEqual(candidate.displacement,best.displacement)?candidate.coordinate<best.coordinate:candidate.displacement<best.displacement:candidate.pathLength<best.pathLength:candidate.visibleLength<best.visibleLength,isReadabilityImprovement=(candidate,baseline)=>candidate.turnCount<=baseline.turnCount&&(candidate.turnCount<baseline.turnCount||candidate.visibleLength<=baseline.visibleLength+RAIL_ALIGNMENT_EPSILON),tracePathChanged=(original,candidate)=>original.tracePath.length!==candidate.tracePath.length||candidate.tracePath.some((point6,index)=>!pointsEqual2(point6,original.tracePath[index])),evaluateRailGroup=({group,traces,netLabelPlacements,obstacles,eligibleTraceIds})=>{let groupTraceIds=new Set(group.map(segment2=>segment2.traceId)),originalGroupTraces=traces.filter(trace=>groupTraceIds.has(trace.mspPairId)),baseline=getTraceGeometryMetrics(originalGroupTraces,traces),originalCoordinates=getDistinctCoordinates(group.map(segment2=>segment2.coordinate)),otherNetTraces=traces.filter(trace=>trace.globalConnNetId!==group[0].globalConnNetId),immutableSameNetTraces=traces.filter(trace=>trace.globalConnNetId===group[0].globalConnNetId&&!eligibleTraceIds.has(trace.mspPairId)),evaluateCoordinates=coordinates=>{let best=null;for(let coordinate of coordinates){let candidateMap=new Map;for(let trace of originalGroupTraces){let candidateTrace=moveRailSegments(trace,group.filter(segment2=>segment2.traceId===trace.mspPairId),coordinate);candidateMap.set(trace.mspPairId,candidateTrace)}let candidateTraces=[...candidateMap.values()],allCandidateTraces=traces.map(trace=>candidateMap.get(trace.mspPairId)??trace);if(!candidateTraces.every(candidate2=>!isPathCollidingWithObstacles(candidate2.tracePath,obstacles)&&detectTraceLabelOverlap({traces:[candidate2],netLabels:netLabelPlacements}).length===0&&!doesPathOverlapTraceStrokes(candidate2.tracePath,otherNetTraces)&&!doesPathCoincideWithTraces(candidate2.tracePath,immutableSameNetTraces.filter(trace=>trace.mspPairId!==candidate2.mspPairId)))||!preservesLabelAnchors(netLabelPlacements,traces,allCandidateTraces))continue;let metrics=getTraceGeometryMetrics(candidateTraces,allCandidateTraces);if(metrics.otherNetCrossings>baseline.otherNetCrossings||!isReadabilityImprovement(metrics,baseline))continue;let score={...metrics,displacement:group.reduce((sum,segment2)=>sum+Math.abs(segment2.coordinate-coordinate),0),coordinate},changedTraceIds=candidateTraces.filter(candidate2=>{let original=traces.find(trace=>trace.mspPairId===candidate2.mspPairId);return tracePathChanged(original,candidate2)}).map(trace=>trace.mspPairId);if(changedTraceIds.length===0)continue;let candidate={traces:allCandidateTraces,changedTraceIds,score};(!best||scoreIsBetter(candidate.score,best.score))&&(best=candidate)}return best},originalCandidate=evaluateCoordinates(originalCoordinates);return originalCandidate||evaluateCoordinates(getRailAlignmentFallbackCoordinates({group,originalCoordinates,otherNetTraces}))},getMovableRailSegments=trace=>{let segments=[],path=trace.tracePath;for(let segmentIndex=1;segmentIndex<path.length-2;segmentIndex++){let previous=path[segmentIndex-1],start=path[segmentIndex],end=path[segmentIndex+1],next2=path[segmentIndex+2],orientation4=getRailOrientation(start,end);if(!orientation4)continue;let previousOrientation=getRailOrientation(previous,start),nextOrientation=getRailOrientation(end,next2);if(!previousOrientation||!nextOrientation||previousOrientation===orientation4||nextOrientation===orientation4)continue;let alongValues=orientation4==="vertical"?[start.y,end.y]:[start.x,end.x];segments.push({traceId:trace.mspPairId,segmentIndex,globalConnNetId:trace.globalConnNetId,orientation:orientation4,coordinate:orientation4==="vertical"?start.x:start.y,minAlong:Math.min(...alongValues),maxAlong:Math.max(...alongValues)})}return segments},railIsOutsideComponent=(segment2,chip,facingDirection)=>{let minX=chip.center.x-chip.width/2,maxX=chip.center.x+chip.width/2,minY=chip.center.y-chip.height/2,maxY=chip.center.y+chip.height/2;switch(facingDirection){case"x-":return segment2.orientation==="vertical"&&segment2.coordinate<=minX+RAIL_ALIGNMENT_EPSILON;case"x+":return segment2.orientation==="vertical"&&segment2.coordinate>=maxX-RAIL_ALIGNMENT_EPSILON;case"y+":return segment2.orientation==="horizontal"&&segment2.coordinate>=maxY-RAIL_ALIGNMENT_EPSILON;case"y-":return segment2.orientation==="horizontal"&&segment2.coordinate<=minY+RAIL_ALIGNMENT_EPSILON}},getComponentSideRailSegments=(trace,chipMap)=>{let segments=[];for(let segment2 of getMovableRailSegments(trace)){let associations=trace.pins.flatMap((pin,pinIndex)=>{let chip=chipMap.get(pin.chipId);if(!chip)return[];let componentFacingDirection=pin._facingDirection??getPinDirection(pin,chip);return railIsOutsideComponent(segment2,chip,componentFacingDirection)?[{componentId:chip.chipId,componentFacingDirection,distanceFromEndpoint:pinIndex===0?segment2.segmentIndex:trace.tracePath.length-2-segment2.segmentIndex}]:[]});associations.sort((a6,b6)=>a6.distanceFromEndpoint-b6.distanceFromEndpoint);let association=associations[0];association&&segments.push({...segment2,...association})}return segments},getCorridor=(a6,b6)=>{let overlapMin=Math.max(a6.minAlong,b6.minAlong),overlapMax=Math.min(a6.maxAlong,b6.maxAlong),along=(overlapMin+overlapMax)/2;return a6.orientation==="vertical"?[{x:a6.coordinate,y:along},{x:b6.coordinate,y:along}]:[{x:along,y:a6.coordinate},{x:along,y:b6.coordinate}]},corridorIsClear=(a6,b6,obstacles)=>{if(!rangesTouchOrOverlap(a6,b6))return!0;let[start,end]=getCorridor(a6,b6);return!obstacles.some(obstacle=>segmentIntersectsRect(start,end,obstacle))},tracesSharePin=(a6,b6,traceMap)=>{if(a6.traceId===b6.traceId)return!0;let aPinIds=new Set(traceMap.get(a6.traceId).pins.map(pin=>pin.pinId));return traceMap.get(b6.traceId).pins.some(pin=>aPinIds.has(pin.pinId))},canJoinRailGroup=(start,current3,candidate,traceMap,obstacles)=>candidate.globalConnNetId===start.globalConnNetId&&candidate.orientation===start.orientation&&candidate.componentId===start.componentId&&candidate.componentFacingDirection===start.componentFacingDirection&&(rangesTouchOrOverlap(current3,candidate)||tracesSharePin(current3,candidate,traceMap))&&corridorIsClear(current3,candidate,obstacles),getRailGroups=(traces,eligibleTraceIds,inputProblem,obstacles)=>{let chipMap=new Map(inputProblem.chips.map(chip=>[chip.chipId,chip])),segments=traces.filter(trace=>eligibleTraceIds.has(trace.mspPairId)).flatMap(trace=>getComponentSideRailSegments(trace,chipMap)),traceMap=new Map(traces.map(trace=>[trace.mspPairId,trace])),visited=new Set,groups=[];for(let startIndex=0;startIndex<segments.length;startIndex++){if(visited.has(startIndex))continue;let start=segments[startIndex],queue=[startIndex],group=[];visited.add(startIndex);for(let queueIndex=0;queueIndex<queue.length;queueIndex++){let current3=segments[queue[queueIndex]];group.push(current3);for(let candidateIndex=0;candidateIndex<segments.length;candidateIndex++){if(visited.has(candidateIndex))continue;let candidate=segments[candidateIndex];canJoinRailGroup(start,current3,candidate,traceMap,obstacles)&&(visited.add(candidateIndex),queue.push(candidateIndex))}}let traceCount=new Set(group.map(segment2=>segment2.traceId)).size,hasDifferentCoordinates=group.some(segment2=>!nearlyEqual(segment2.coordinate,group[0].coordinate));traceCount>=2&&hasDifferentCoordinates&&groups.push(group)}return groups},alignSameNetRails=({inputProblem,traces,netLabelPlacements,eligibleTraceIds})=>{let outputTraces=[...traces],obstacles=getObstacleRects(inputProblem),alignedTraceIds=new Set,alignedRailGroupCount=0,maximumPasses=Math.max(1,traces.reduce((sum,trace)=>sum+trace.tracePath.length,0));for(let pass=0;pass<maximumPasses;pass++){let groups=getRailGroups(outputTraces,eligibleTraceIds,inputProblem,obstacles),applied=null;for(let group of groups)if(applied=evaluateRailGroup({group,traces:outputTraces,netLabelPlacements,obstacles,eligibleTraceIds}),applied)break;if(!applied)break;outputTraces=applied.traces,alignedRailGroupCount++;for(let traceId of applied.changedTraceIds)alignedTraceIds.add(traceId)}return{traces:outputTraces,alignedRailGroupCount,alignedTraceCount:alignedTraceIds.size}},findAllLShapedTurns=tracePath=>{let lShapes=[];if(tracePath.length<3)return lShapes;for(let i6=0;i6<tracePath.length-2;i6++){let p12=tracePath[i6],p22=tracePath[i6+1],p3=tracePath[i6+2],dx1=p22.x-p12.x,dy1=p22.y-p12.y,dx22=p3.x-p22.x,dy22=p3.y-p22.y;(dx1===0&&dy22===0&&dy1!==0&&dx22!==0||dy1===0&&dx22===0&&dx1!==0&&dy22!==0)&&dx1*dx1+dy1*dy1>=.25&&dx22*dx22+dy22*dy22>=.25&&lShapes.push({p1:p12,p2:p22,p3})}return lShapes},getTraceObstacles=(allTraces,excludeTraceId)=>{let obstacles=[];for(let trace of allTraces)trace.mspPairId!==excludeTraceId&&obstacles.push({points:trace.tracePath});return obstacles},EPS9=1e-6,findIntersectionsWithObstacles=(p12,p22,obstacles)=>{let intersections=[];for(let obstacle of obstacles){let obstaclePath=obstacle.points;for(let i6=0;i6<obstaclePath.length-1;i6++){let o12=obstaclePath[i6],o22=obstaclePath[i6+1];if(!o12||!o22)continue;let intersection=getSegmentIntersection(p12,p22,o12,o22);intersection&&intersections.push(intersection)}}return intersections},isSamePoint=(first,second)=>Math.abs(first.x-second.x)<EPS9&&Math.abs(first.y-second.y)<EPS9,findPerpendicularPathCrossings=(path,otherPath)=>{let crossings=[];for(let pathSegmentIndex=1;pathSegmentIndex<path.length-2;pathSegmentIndex++){let start=path[pathSegmentIndex],end=path[pathSegmentIndex+1],isVertical52=Math.abs(start.x-end.x)<EPS9;for(let otherPathSegmentIndex=1;otherPathSegmentIndex<otherPath.length-2;otherPathSegmentIndex++){let otherStart=otherPath[otherPathSegmentIndex],otherEnd=otherPath[otherPathSegmentIndex+1],otherIsVertical=Math.abs(otherStart.x-otherEnd.x)<EPS9;if(isVertical52===otherIsVertical)continue;let intersection=getSegmentIntersection(start,end,otherStart,otherEnd);!intersection||[start,end,otherStart,otherEnd].some(point6=>isSamePoint(point6,intersection))||crossings.push({pathSegmentIndex,otherPathSegmentIndex})}}return crossings},EPS10=1e-6,isVertical3=(a6,b6,eps=EPS10)=>Math.abs(a6.x-b6.x)<eps,generateLShapeRerouteCandidates=({lShape,rectangle,padding=.5,interactionPoint1,interactionPoint2})=>{let{p1:p12,p2:p22,p3}=lShape,{x:x6,y:y2,width,height}=rectangle,c22,i1_padded=interactionPoint1,i2_padded=interactionPoint2;if(Math.abs(p22.x-x6)<EPS10&&Math.abs(p22.y-(y2+height))<EPS10)c22={x:x6+width+padding,y:y2-padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y-padding}:i1_padded={x:interactionPoint1.x+padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y-padding}:i2_padded={x:interactionPoint2.x+padding,y:interactionPoint2.y};else if(Math.abs(p22.x-(x6+width))<EPS10&&Math.abs(p22.y-(y2+height))<EPS10)c22={x:x6-padding,y:y2-padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y-padding}:i1_padded={x:interactionPoint1.x-padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y-padding}:i2_padded={x:interactionPoint2.x-padding,y:interactionPoint2.y};else if(Math.abs(p22.x-x6)<EPS10&&Math.abs(p22.y-y2)<EPS10)c22={x:x6+width+padding,y:y2+height+padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y+padding}:i1_padded={x:interactionPoint1.x+padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y+padding}:i2_padded={x:interactionPoint2.x+padding,y:interactionPoint2.y};else if(Math.abs(p22.x-(x6+width))<EPS10&&Math.abs(p22.y-y2)<EPS10)c22={x:x6-padding,y:y2+height+padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y+padding}:i1_padded={x:interactionPoint1.x-padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y+padding}:i2_padded={x:interactionPoint2.x-padding,y:interactionPoint2.y};else return[];return[[i1_padded,c22,i2_padded]]},generatePerimeterCornerTraceDetours=({trace,chipBounds,clearance})=>{if(trace.tracePath.length<4||chipBounds.length===0)return[];let start=trace.tracePath[0],firstEscape=trace.tracePath[1],lastEscape=trace.tracePath.at(-2),end=trace.tracePath.at(-1),minX=Math.min(...chipBounds.map(bounds=>bounds.minX))-clearance,maxX=Math.max(...chipBounds.map(bounds=>bounds.maxX))+clearance,minY=Math.min(...chipBounds.map(bounds=>bounds.minY))-clearance,maxY=Math.max(...chipBounds.map(bounds=>bounds.maxY))+clearance,candidates=[];for(let channelX of[minX,maxX])for(let channelY of[minY,maxY])candidates.push({traceId:trace.mspPairId,path:simplifyPath([start,firstEscape,{x:firstEscape.x,y:channelY},{x:channelX,y:channelY},{x:channelX,y:lastEscape.y},lastEscape,end])}),candidates.push({traceId:trace.mspPairId,path:simplifyPath([start,firstEscape,{x:channelX,y:firstEscape.y},{x:channelX,y:channelY},{x:lastEscape.x,y:channelY},lastEscape,end])});return candidates},generatePerpendicularTraceDetours=({trace,segmentIndex,obstacleStart,obstacleEnd,chipBounds,clearance})=>{let buildDetours=(path,index)=>{let start=path[index],end=path[index+1],movingAxis=Math.abs(start.x-end.x)<EPS10?"y":"x",detourAxis=movingAxis==="x"?"y":"x",gate=obstacleStart[movingAxis]+Math.sign(start[movingAxis]-obstacleStart[movingAxis])*clearance,obstacleRange=[obstacleStart[detourAxis],obstacleEnd[detourAxis]],lowBound=detourAxis==="x"?"minX":"minY",highBound=detourAxis==="x"?"maxX":"maxY",detourCoordinates=[Math.min(...obstacleRange)-clearance,Math.max(...obstacleRange)+clearance,...chipBounds.flatMap(bounds=>[bounds[lowBound]-clearance,bounds[highBound]+clearance])];return[...new Set(detourCoordinates)].map(detour=>simplifyPath([...path.slice(0,index+1),{...start,[movingAxis]:gate},{...start,[movingAxis]:gate,[detourAxis]:detour},{...end,[detourAxis]:detour},...path.slice(index+2)]))},reversedPath=[...trace.tracePath].reverse(),reversedIndex=trace.tracePath.length-2-segmentIndex;return[...buildDetours(trace.tracePath,segmentIndex),...buildDetours(reversedPath,reversedIndex).map(path=>path.reverse())].map(path=>({traceId:trace.mspPairId,path}))},isPathColliding=(path,allTraces,traceIdToExclude)=>{if(path.length<2)return{isColliding:!1};for(let i6=0;i6<path.length-1;i6++){let pathSegP1=path[i6],pathSegQ1=path[i6+1];for(let existingTrace of allTraces)if(existingTrace.mspPairId!==traceIdToExclude)for(let j6=0;j6<existingTrace.tracePath.length-1;j6++){let existingSegP2=existingTrace.tracePath[j6],existingSegQ2=existingTrace.tracePath[j6+1],intersectionPoint=getSegmentIntersection(pathSegP1,pathSegQ1,existingSegP2,existingSegQ2);if(intersectionPoint)return{isColliding:!0,collidingTraceId:existingTrace.mspPairId,collisionPoint:intersectionPoint}}}return{isColliding:!1}},generateRectangleCandidates=(intersections1,intersections2)=>{let rectangleCandidates=[];for(let p12 of intersections1)for(let p22 of intersections2){let minX=Math.min(p12.x,p22.x),minY=Math.min(p12.y,p22.y),maxX=Math.max(p12.x,p22.x),maxY=Math.max(p12.y,p22.y),width=maxX-minX,height=maxY-minY;width>1e-6&&height>1e-6&&rectangleCandidates.push({rect:{x:minX,y:minY,width,height},i1:p12,i2:p22})}return rectangleCandidates},visualizeLSapes=lShapes=>{let graphics={circles:[],lines:[]},lShapesArray=Array.isArray(lShapes)?lShapes:[lShapes];for(let lShape of lShapesArray)graphics.circles.push({center:{x:lShape.p2.x,y:lShape.p2.y},radius:.01,fill:"blue"}),graphics.lines.push({points:[lShape.p1,lShape.p2,lShape.p3],strokeColor:"lightblue"});return graphics},visualizeIntersectionPoints=(points,color="red")=>{let graphics={circles:[]};for(let point6 of points)graphics.circles.push({center:{x:point6.x,y:point6.y},radius:.01,fill:color});return graphics},visualizeTightRectangle=rectangle=>{let graphics={rects:[]};return graphics.rects.push({center:{x:rectangle.x+rectangle.width/2,y:rectangle.y+rectangle.height/2},width:rectangle.width,height:rectangle.height,stroke:"green"}),graphics},visualizeCandidates=(candidates,color="gray",intersectionPoints=[])=>{let graphics={lines:[],circles:[]};for(let candidate of candidates)graphics.lines.push({points:candidate,strokeColor:color});for(let point6 of intersectionPoints)graphics.circles.push({center:point6,radius:.01,fill:"green"});return graphics},mergeGraphicsObjects=objects=>{let merged={lines:[],points:[],rects:[],circles:[],texts:[]};for(let obj of objects)obj&&(obj.lines&&merged.lines.push(...obj.lines),obj.points&&merged.points.push(...obj.points),obj.rects&&merged.rects.push(...obj.rects),obj.circles&&merged.circles.push(...obj.circles),obj.texts&&merged.texts.push(...obj.texts));return merged},visualizeCollision=collisionInfo=>{let collisionGraphics={circles:[]};return collisionInfo?.isColliding&&collisionInfo.collisionPoint&&collisionGraphics.circles.push({center:collisionInfo.collisionPoint,radius:.01,fill:"red"}),collisionGraphics},UntangleTraceSubsolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"lShapesToProcess",[]);__publicField(this,"ignoredCrossings",new Set);__publicField(this,"reroutedTraceIds",new Set);__publicField(this,"processingCrossings",!0);__publicField(this,"visualizationMode","l_shapes");__publicField(this,"currentLShape",null);__publicField(this,"intersectionPoints",[]);__publicField(this,"tightRectangle",null);__publicField(this,"candidates",[]);__publicField(this,"bestRoute",null);__publicField(this,"lastCollision",null);__publicField(this,"collidingCandidate",null);__publicField(this,"rectangleCandidates",[]);__publicField(this,"currentRectangleIndex",0);__publicField(this,"isInitialStep",!0);__publicField(this,"currentCandidateIndex",0);__publicField(this,"lShapeProcessingStep","idle");__publicField(this,"lShapeJustProcessed",!1);__publicField(this,"bestRouteFound",null);this.input=solverInput,this.visualizationMode="l_shapes",this.chipObstacleSpatialIndex=this.input.inputProblem._chipObstacleSpatialIndex??new ChipObstacleSpatialIndex(this.input.inputProblem.chips),this.input.inputProblem._chipObstacleSpatialIndex||(this.input.inputProblem._chipObstacleSpatialIndex=this.chipObstacleSpatialIndex)}_step(){if(this.isInitialStep){this.isInitialStep=!1;return}if(this.processingCrossings){let crossing=this._findCrossing();if(crossing){this._resolveCrossing(crossing)||this.ignoredCrossings.add(this._crossingKey(crossing));return}this.processingCrossings=!1,this._initializeLShapes();return}if(this.lShapeJustProcessed){this._resetAfterLShapProcessing();return}if(this.lShapesToProcess.length===0&&this.currentLShape===null){this.solved=!0;return}switch(this.lShapeProcessingStep){case"idle":this._handleIdleStep();break;case"intersections":this._handleIntersectionsStep();break;case"rectangle_selection":this._handleRectangleSelectionStep();break;case"candidate_evaluation":this._handleCandidateEvaluationStep();break}}_initializeLShapes(){for(let trace of this.input.allTraces)this.lShapesToProcess.push(...findAllLShapedTurns(trace.tracePath).map(lShape=>({...lShape,traceId:trace.mspPairId})))}_crossingKey(crossing){return`${crossing.trace.mspPairId}:${crossing.segmentIndex}:${crossing.otherTrace.mspPairId}:${crossing.otherSegmentIndex}`}_isTraceBundle(first,second){let componentPair=trace=>trace.pins.map(pin=>pin.chipId).sort().join(":");return componentPair(first)!==componentPair(second)?!1:Object.values(this.input.mergedLabelNetIdMap).some(netIds=>netIds.has(first.globalConnNetId)&&netIds.has(second.globalConnNetId))}_findCrossing(){let traces=this.input.allTraces;for(let firstIndex=0;firstIndex<traces.length;firstIndex++){let trace=traces[firstIndex];for(let secondIndex=firstIndex+1;secondIndex<traces.length;secondIndex++){let otherTrace=traces[secondIndex];if(trace.globalConnNetId===otherTrace.globalConnNetId)continue;let isInitialBundleCrossing=this._isTraceBundle(trace,otherTrace),isEligibleInitialCrossing=this.input.eligibleTraceIds?.has(trace.mspPairId)===!0||this.input.eligibleTraceIds?.has(otherTrace.mspPairId)===!0;if(!isInitialBundleCrossing&&!isEligibleInitialCrossing&&!this.reroutedTraceIds.has(trace.mspPairId)&&!this.reroutedTraceIds.has(otherTrace.mspPairId))continue;let crossings=findPerpendicularPathCrossings(trace.tracePath,otherTrace.tracePath);for(let{pathSegmentIndex,otherPathSegmentIndex}of crossings){let crossing={trace,segmentIndex:pathSegmentIndex,otherTrace,otherSegmentIndex:otherPathSegmentIndex,isInitialBundleCrossing};if(!this.ignoredCrossings.has(this._crossingKey(crossing)))return crossing}}}return null}_resolveCrossing(crossing){let chipBounds=this.chipObstacleSpatialIndex.chips.map(chip=>chip.bounds),candidates=[...generatePerpendicularTraceDetours({trace:crossing.trace,segmentIndex:crossing.segmentIndex,obstacleStart:crossing.otherTrace.tracePath[crossing.otherSegmentIndex],obstacleEnd:crossing.otherTrace.tracePath[crossing.otherSegmentIndex+1],chipBounds,clearance:this.input.paddingBuffer}),...generatePerpendicularTraceDetours({trace:crossing.otherTrace,segmentIndex:crossing.otherSegmentIndex,obstacleStart:crossing.trace.tracePath[crossing.segmentIndex],obstacleEnd:crossing.trace.tracePath[crossing.segmentIndex+1],chipBounds,clearance:this.input.paddingBuffer}),...generatePerimeterCornerTraceDetours({trace:crossing.trace,chipBounds,clearance:this.input.paddingBuffer}),...generatePerimeterCornerTraceDetours({trace:crossing.otherTrace,chipBounds,clearance:this.input.paddingBuffer})],chipObstacles=getObstacleRects(this.input.inputProblem).filter(obstacle=>obstacle.kind==="chip"),bestCandidate=candidates.map(candidate=>({...candidate,collision:isPathColliding(candidate.path,this.input.allTraces,candidate.traceId)})).filter(candidate=>!isPathCollidingWithChipInterior(candidate.path,chipObstacles)&&!isPathColliding(candidate.path,[crossing.trace,crossing.otherTrace],candidate.traceId).isColliding&&(crossing.isInitialBundleCrossing||!candidate.collision.isColliding)).sort((first,second)=>Number(first.collision.isColliding)-Number(second.collision.isColliding)||getPathLength2(first.path)-getPathLength2(second.path))[0];if(!bestCandidate)return!1;let traceIndex=this.input.allTraces.findIndex(trace=>trace.mspPairId===bestCandidate.traceId);return this.input.allTraces[traceIndex]={...this.input.allTraces[traceIndex],tracePath:bestCandidate.path},this.reroutedTraceIds.add(bestCandidate.traceId),!0}_resetAfterLShapProcessing(){this.lShapeProcessingStep="idle",this.currentLShape=null,this.currentCandidateIndex=0,this.lShapeJustProcessed=!1,this.visualizationMode="l_shapes",this.intersectionPoints=[],this.tightRectangle=null,this.candidates=[],this.bestRoute=null,this.lastCollision=null,this.collidingCandidate=null}_handleIdleStep(){if(this.currentLShape=this.lShapesToProcess.shift(),!this.currentLShape){this.solved=!0;return}this.lShapeProcessingStep="intersections",this.visualizationMode="l_shapes"}_handleIntersectionsStep(){if(!this.currentLShape.traceId){this.lShapeProcessingStep="idle";return}let allObstacles=getTraceObstacles(this.input.allTraces,this.currentLShape.traceId),intersections1=findIntersectionsWithObstacles(this.currentLShape.p1,this.currentLShape.p2,allObstacles),intersections2=findIntersectionsWithObstacles(this.currentLShape.p2,this.currentLShape.p3,allObstacles);if(this.intersectionPoints=[...intersections1,...intersections2],intersections1.length===0||intersections2.length===0){this.lShapeProcessingStep="idle";return}this.rectangleCandidates=generateRectangleCandidates(intersections1,intersections2),this.currentRectangleIndex=0,this.lShapeProcessingStep="rectangle_selection"}_handleRectangleSelectionStep(){if(this.currentRectangleIndex>=this.rectangleCandidates.length){this.lShapeProcessingStep="idle";return}let{rect,i1:i12,i2:i22}=this.rectangleCandidates[this.currentRectangleIndex];this.tightRectangle=rect,this.candidates=generateLShapeRerouteCandidates({lShape:this.currentLShape,rectangle:this.tightRectangle,padding:2*this.input.paddingBuffer,interactionPoint1:i12,interactionPoint2:i22}),this.currentCandidateIndex=0,this.lastCollision=null,this.collidingCandidate=null,this.visualizationMode="candidates",this.lShapeProcessingStep="candidate_evaluation"}_handleCandidateEvaluationStep(){if(this.visualizationMode="candidates",this.bestRouteFound){this._applyBestRoute(this.bestRouteFound),this.bestRouteFound=null;return}if(this.currentCandidateIndex>=this.candidates.length){this.currentRectangleIndex++,this.lShapeProcessingStep="rectangle_selection";return}let currentCandidate=this.candidates[this.currentCandidateIndex],collisionResult=isPathColliding(currentCandidate,this.input.allTraces,this.currentLShape.traceId);if(!collisionResult?.isColliding&&this._doesCandidateCrossChip(currentCandidate)){this.lastCollision=null,this.collidingCandidate=currentCandidate,this.currentCandidateIndex++;return}collisionResult?.isColliding?(this.lastCollision=collisionResult,this.collidingCandidate=currentCandidate,this.currentCandidateIndex++):(this.bestRouteFound=currentCandidate,this.lastCollision=null,this.collidingCandidate=null)}_doesCandidateCrossChip(candidate){for(let i6=0;i6<candidate.length-1;i6++)if(this.chipObstacleSpatialIndex.doesOrthogonalLineIntersectChip([candidate[i6],candidate[i6+1]]))return!0;return!1}_applyBestRoute(bestRoute){this.bestRoute=bestRoute,this.collidingCandidate=null,this.lastCollision=null;let traceIndex=this.input.allTraces.findIndex(trace=>trace.mspPairId===this.currentLShape.traceId);if(traceIndex!==-1){let originalTrace=this.input.allTraces[traceIndex],p2Index=originalTrace.tracePath.findIndex(p3=>p3.x===this.currentLShape.p2.x&&p3.y===this.currentLShape.p2.y);if(p2Index!==-1){let newTracePath=[...originalTrace.tracePath.slice(0,p2Index),...bestRoute,...originalTrace.tracePath.slice(p2Index+1)];this.input.allTraces[traceIndex]={...originalTrace,tracePath:newTracePath},this.lShapesToProcess=this.lShapesToProcess.filter(l6=>l6.traceId!==this.currentLShape.traceId)}}this.lShapeJustProcessed=!0}getOutput(){return{traces:this.input.allTraces}}visualize(){switch(this.visualizationMode){case"l_shapes":return visualizeLSapes(this.lShapesToProcess);case"intersection_points":return mergeGraphicsObjects([this.currentLShape?visualizeLSapes(this.currentLShape):void 0,visualizeIntersectionPoints(this.intersectionPoints)]);case"tight_rectangle":return mergeGraphicsObjects([this.currentLShape?visualizeLSapes(this.currentLShape):void 0,visualizeIntersectionPoints(this.intersectionPoints),this.tightRectangle?visualizeTightRectangle(this.tightRectangle):void 0]);case"candidates":{if(this.lShapeJustProcessed){let allTracesGraphics2={lines:[]};for(let trace of this.input.allTraces){let isUpdatedTrace=trace.mspPairId===this.currentLShape?.traceId;for(let i6=0;i6<trace.tracePath.length-1;i6++)allTracesGraphics2.lines.push({points:[trace.tracePath[i6],trace.tracePath[i6+1]],strokeColor:isUpdatedTrace?"green":"#ccc"})}return allTracesGraphics2}let allTracesGraphics={lines:[]};for(let trace of this.input.allTraces)for(let i6=0;i6<trace.tracePath.length-1;i6++)allTracesGraphics.lines.push({points:[trace.tracePath[i6],trace.tracePath[i6+1]],strokeColor:"#ccc"});let candidateToDraw;return this.bestRouteFound?candidateToDraw=this.bestRouteFound:this.lastCollision?.isColliding?candidateToDraw=this.collidingCandidate??void 0:this.currentCandidateIndex<this.candidates.length&&(candidateToDraw=this.candidates[this.currentCandidateIndex]),mergeGraphicsObjects([allTracesGraphics,this.currentLShape?visualizeLSapes(this.currentLShape):void 0,this.tightRectangle?visualizeTightRectangle(this.tightRectangle):void 0,candidateToDraw?visualizeCandidates([candidateToDraw],this.bestRouteFound?"green":"blue",this.intersectionPoints):void 0,this.lastCollision?visualizeCollision(this.lastCollision):void 0])}default:return{}}}},EPS11=1e-6,sameX=(a6,b6)=>Math.abs(a6.x-b6.x)<=EPS11,sameY=(a6,b6)=>Math.abs(a6.y-b6.y)<=EPS11,is4PointRectangle=path=>{if(path.length!==4)return!1;let[p03,p12,p22,p3]=path,isHVHC=sameY(p03,p12)&&sameX(p12,p22)&&sameY(p22,p3)&&sameX(p03,p3),isVHVC=sameX(p03,p12)&&sameY(p12,p22)&&sameX(p22,p3)&&sameY(p03,p3);return isHVHC||isVHVC},DEFAULT_OPERATIONS=["untangling_traces","minimizing_turns","balancing_l_shapes"],TraceCleanupSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"traceIdQueue");__publicField(this,"tracesMap");__publicField(this,"operations");__publicField(this,"operationIndex",0);__publicField(this,"pipelineStep");__publicField(this,"activeTraceId",null);__publicField(this,"activeSubSolver",null);this.input=solverInput,this.outputTraces=[...solverInput.allTraces],this.tracesMap=new Map(this.outputTraces.map(t53=>[t53.mspPairId,t53])),this.operations=solverInput.operations??DEFAULT_OPERATIONS,this.pipelineStep=this.operations[0]??null,this.traceIdQueue=Array.from(solverInput.allTraces.map(e6=>e6.mspPairId))}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){let output=this.activeSubSolver.getOutput();this.outputTraces=output.traces,this.tracesMap=new Map(this.outputTraces.map(t53=>[t53.mspPairId,t53])),this.activeSubSolver=null,this._advancePipeline()}else this.activeSubSolver.failed&&(this.activeSubSolver=null,this._advancePipeline());return}if(!this.pipelineStep){this.solved=!0;return}switch(this.pipelineStep){case"untangling_traces":this._runUntangleTracesStep();break;case"minimizing_turns":this._runMinimizeTurnsStep();break;case"balancing_l_shapes":this._runBalanceLShapesStep();break;case"aligning_same_net_rails":this._runAlignSameNetRailsStep();break}}_advancePipeline(){this.operationIndex++,this.pipelineStep=this.operations[this.operationIndex]??null,this.traceIdQueue=this.outputTraces.map(trace=>trace.mspPairId),this.pipelineStep&&(this.activeTraceId=null)}_runUntangleTracesStep(){this.activeSubSolver=new UntangleTraceSubsolver({...this.input,allTraces:Array.from(this.tracesMap.values())})}_runMinimizeTurnsStep(){if(this.traceIdQueue.length===0){this._advancePipeline();return}this._processTrace("minimizing_turns")}_runBalanceLShapesStep(){if(this.traceIdQueue.length===0){this._advancePipeline();return}this._processTrace("balancing_l_shapes")}_processTrace(step){let targetMspConnectionPairId=this.traceIdQueue.shift();this.activeTraceId=targetMspConnectionPairId;let originalTrace=this.tracesMap.get(targetMspConnectionPairId);if(is4PointRectangle(originalTrace.tracePath))return;let allTraces=Array.from(this.tracesMap.values()),updatedTrace;step==="minimizing_turns"?updatedTrace=minimizeTurnsWithFilteredLabels({...this.input,targetMspConnectionPairId,traces:allTraces}):updatedTrace=balanceZShapes({...this.input,targetMspConnectionPairId,traces:allTraces}),this.tracesMap.set(targetMspConnectionPairId,updatedTrace),this.outputTraces=Array.from(this.tracesMap.values())}_runAlignSameNetRailsStep(){let alignment=alignSameNetRails({inputProblem:this.input.inputProblem,traces:this.outputTraces,netLabelPlacements:this.input.allLabelPlacements,eligibleTraceIds:this.input.eligibleTraceIds??new Set(this.outputTraces.map(trace=>trace.mspPairId))});this.outputTraces=alignment.traces,this.tracesMap=new Map(this.outputTraces.map(t53=>[t53.mspPairId,t53])),this.stats.alignedRailGroupCount=alignment.alignedRailGroupCount,this.stats.alignedTraceCount=alignment.alignedTraceCount,this._advancePipeline()}getOutput(){return{traces:this.outputTraces}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.input.inputProblem,{chipAlpha:.1,connectionAlpha:.1});graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.rects||(graphics.rects=[]),graphics.circles||(graphics.circles=[]),graphics.texts||(graphics.texts=[]);for(let trace of this.outputTraces){let line2={points:trace.tracePath.map(p3=>({x:p3.x,y:p3.y})),strokeColor:trace.mspPairId===this.activeTraceId?"red":"blue"};graphics.lines.push(line2)}return graphics}},getPinMap=inputProblem=>{let pinMap={};for(let chip of inputProblem.chips)for(let pin of chip.pins)pinMap[pin.pinId]={...pin,chipId:chip.chipId};return pinMap},getTracePins=(label,pinMap)=>{let pins=label.pinIds.flatMap(pinId=>{let pin=pinMap[pinId];return pin?[pin]:[]});if(pins.length>=2)return[pins[0],pins[1]];if(pins.length===1)return[pins[0],pins[0]];let syntheticPin={pinId:`${label.globalConnNetId}-netlabel-anchor`,x:label.anchorPoint.x,y:label.anchorPoint.y,chipId:"available-net-orientation"};return[syntheticPin,syntheticPin]},toNetLabelPlacementPatch=candidate=>({orientation:candidate.orientation,anchorPoint:candidate.anchorPoint,center:candidate.center,width:candidate.width,height:candidate.height}),dir=facingDirection=>{switch(facingDirection){case"x+":return{x:1,y:0};case"x-":return{x:-1,y:0};case"y+":return{x:0,y:1};case"y-":return{x:0,y:-1}}throw new Error(`Invalid facing direction: ${facingDirection}`)},getMovedAnchorPointForReroute=(anchorPoint,originalTracePath,reroutedTracePath)=>{let originalSegment=findSegmentContainingPoint(originalTracePath,anchorPoint);if(!originalSegment)return null;let preferredSegment=findPreferredReroutedSegment(reroutedTracePath,originalSegment.index,originalTracePath.length-1,originalSegment.orientation,anchorPoint);return preferredSegment?projectPointToSegment(anchorPoint,preferredSegment.start,preferredSegment.end):projectPointToPath(anchorPoint,reroutedTracePath)},isLabelAttachedToTrace=(label,trace)=>label.globalConnNetId===trace.globalConnNetId||label.mspConnectionPairIds.includes(trace.mspPairId),moveAttachedLabelsToReroutedTrace=({trace,originalTracePath,reroutedTracePath,netLabelPlacements})=>netLabelPlacements.map(label=>{if(!isLabelAttachedToTrace(label,trace))return label;let movedAnchorPoint=getMovedAnchorPointForReroute(label.anchorPoint,originalTracePath,reroutedTracePath);if(!movedAnchorPoint)return label;let delta={x:movedAnchorPoint.x-label.anchorPoint.x,y:movedAnchorPoint.y-label.anchorPoint.y};return{...label,anchorPoint:movedAnchorPoint,center:{x:label.center.x+delta.x,y:label.center.y+delta.y}}}),moveNetLabelConnectorsToReroutedTraces=({originalTraces,reroutedTraces,netLabelPlacements})=>{let traces=[...reroutedTraces],reroutedTraceMap=new Map(reroutedTraces.map(trace=>[trace.mspPairId,trace])),labels=netLabelPlacements.map(label=>{let originalHostTrace=originalTraces.find(trace=>{if(!label.mspConnectionPairIds.includes(trace.mspPairId))return!1;let reroutedTrace=reroutedTraceMap.get(trace.mspPairId);return reroutedTrace?reroutedTrace.tracePath!==trace.tracePath:!1});if(!originalHostTrace)return label;let reroutedHostTrace=reroutedTraceMap.get(originalHostTrace.mspPairId),connectorIndex=originalTraces.findIndex(trace=>trace.mspPairId===originalHostTrace.mspPairId||trace.globalConnNetId!==label.globalConnNetId||!tracePathContainsPoint(trace.tracePath,label.anchorPoint)?!1:label.pinIds.every(pinId=>trace.pinIds.includes(pinId)));if(connectorIndex<0)return label;let connector=originalTraces[connectorIndex],originalJunction=connector.tracePath.find(point6=>tracePathContainsPoint(originalHostTrace.tracePath,point6));if(!originalJunction)return label;let reroutedJunction=getMovedAnchorPointForReroute(originalJunction,originalHostTrace.tracePath,reroutedHostTrace.tracePath);if(!reroutedJunction)return label;let delta={x:reroutedJunction.x-originalJunction.x,y:reroutedJunction.y-originalJunction.y},movedConnector={...connector,tracePath:connector.tracePath.map(point6=>({x:point6.x+delta.x,y:point6.y+delta.y}))};return traces[connectorIndex]=movedConnector,moveAttachedLabelsToReroutedTrace({trace:connector,originalTracePath:connector.tracePath,reroutedTracePath:movedConnector.tracePath,netLabelPlacements:[label]})[0]});return{traces,netLabelPlacements:labels}},doesPathRunAlongChipBoundary=(path,chipObstacles)=>{for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];for(let obstacle of chipObstacles)if(segmentRunsAlongRectBoundary(start,end,obstacle)&&getSegmentOverlapWithRectSpan(start,end,obstacle)>EPS8)return!0}return!1},getChipBoundaryOverlap=(path,chipObstacles)=>{let total=0;for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];for(let obstacle of chipObstacles){if(!segmentRunsAlongRectBoundary(start,end,obstacle))continue;let overlap=getSegmentOverlapWithRectSpan(start,end,obstacle);overlap>EPS8&&(total+=overlap)}}return total},getSegmentOverlapWithRectSpan=(start,end,rect)=>Math.abs(start.x-end.x)<EPS8?Math.min(Math.max(start.y,end.y),rect.maxY)-Math.max(Math.min(start.y,end.y),rect.minY):Math.min(Math.max(start.x,end.x),rect.maxX)-Math.max(Math.min(start.x,end.x),rect.minX),LABEL_CLEARANCE=.1,MAX_CORRIDOR_SHIFTS=16,corridorHasOtherNetTrace=({x:x6,lowY,highY,outputTraces,netId})=>{for(let other of outputTraces){if(other.globalConnNetId===netId)continue;let path=other.tracePath;for(let i6=0;i6+1<path.length;i6++){let start=path[i6],end=path[i6+1];if(Math.abs(start.x-end.x)>=1e-9||Math.abs(start.x-x6)>=LABEL_CLEARANCE/2)continue;let segLowY=Math.min(start.y,end.y),segHighY=Math.max(start.y,end.y);if(Math.min(highY,segHighY)-Math.max(lowY,segLowY)>1e-6)return!0}}return!1},findBestReroutePath=({trace,obstacleLabel,inputProblem,outputTraces,outputNetLabelPlacements,chipObstacles})=>{let candidateResults=generateRerouteCandidateResults({trace,label:obstacleLabel,inputProblem,outputTraces,outputNetLabelPlacements,chipObstacles}),bestPath=selectBestReroutePath({trace,obstacleLabel,outputTraces,outputNetLabelPlacements,candidateResults,chipObstacles});return markSelectedCandidate(candidateResults,bestPath),{bestPath,candidateResults}},generateRerouteCandidateResults=({trace,label,inputProblem,outputTraces,outputNetLabelPlacements,chipObstacles})=>{let seen=new Set,candidateResults=[],horizontalSegmentPushCandidate=generateHorizontalSegmentPushCandidate({trace,label,outputTraces});horizontalSegmentPushCandidate&&candidateResults.push(createCandidateResult({trace,obstacleLabel:label,path:horizontalSegmentPushCandidate,seen,outputTraces,outputNetLabelPlacements,chipObstacles,usesHorizontalSegmentPush:!0}));let rawCandidates=[...generateLabelHugCandidates(trace,label),...generateRerouteCandidates({trace,label,problem:inputProblem,paddingBuffer:LABEL_CLEARANCE,detourCount:0}),...generateEndpointDetourCandidates(trace,label)];for(let rawCandidate of rawCandidates)candidateResults.push(createCandidateResult({trace,obstacleLabel:label,path:simplifyPath(rawCandidate),seen,outputTraces,outputNetLabelPlacements,chipObstacles}));return candidateResults},createCandidateResult=({trace,obstacleLabel,path,seen,outputTraces,outputNetLabelPlacements,chipObstacles,usesHorizontalSegmentPush})=>{let key=getPathKey(path);return seen.has(key)?{path,status:"duplicate",usesHorizontalSegmentPush,selected:!1}:(seen.add(key),isPathCollidingWithChipInterior(path,chipObstacles)?{path,status:"chip-collision",usesHorizontalSegmentPush,selected:!1}:{path,score:scoreTracePath({trace,tracePath:path,obstacleLabel,outputTraces,outputNetLabelPlacements,chipObstacles}),status:"valid",usesHorizontalSegmentPush,selected:!1})},generateEndpointDetourCandidates=(trace,label)=>{let start=trace.tracePath[0],end=trace.tracePath[trace.tracePath.length-1];if(!start||!end)return[];let startExit=trace.tracePath[1]??start,endEntry=trace.tracePath[trace.tracePath.length-2]??end,bounds=getRectBounds(label.center,label.width,label.height),padding=LABEL_CLEARANCE,labelDirection=dir(label.orientation),labelSideX=labelDirection.x<0?bounds.minX-padding:bounds.maxX+padding,oppositeSideX=labelDirection.x<0?bounds.maxX+padding:bounds.minX-padding,topY=bounds.maxY+padding,bottomY=bounds.minY-padding,candidates=[];for(let sideX of[labelSideX,oppositeSideX])candidates.push([start,startExit,{x:startExit.x,y:topY},{x:sideX,y:topY},{x:sideX,y:bottomY},{x:endEntry.x,y:bottomY},endEntry,end],[start,startExit,{x:startExit.x,y:bottomY},{x:sideX,y:bottomY},{x:sideX,y:topY},{x:endEntry.x,y:topY},endEntry,end]);return candidates},generateLabelHugCandidates=(trace,label)=>{let start=trace.tracePath[0],end=trace.tracePath[trace.tracePath.length-1];if(!start||!end)return[];let startExit=trace.tracePath[1]??start,endEntry=trace.tracePath[trace.tracePath.length-2]??end,labelDirection=dir(label.orientation);if(labelDirection.x===0)return[];let bounds=getRectBounds(label.center,label.width,label.height),sideX=labelDirection.x<0?bounds.minX-LABEL_CLEARANCE:bounds.maxX+LABEL_CLEARANCE,topY=bounds.maxY+LABEL_CLEARANCE,bottomY=bounds.minY-LABEL_CLEARANCE,startsAboveEnd=startExit.y>=endEntry.y,firstY=startsAboveEnd?topY:bottomY,secondY=startsAboveEnd?bottomY:topY;return[[start,startExit,{x:startExit.x,y:firstY},{x:sideX,y:firstY},{x:sideX,y:secondY},{x:endEntry.x,y:secondY},endEntry,end],[start,startExit,{x:startExit.x,y:secondY},{x:sideX,y:secondY},{x:sideX,y:firstY},{x:endEntry.x,y:firstY},endEntry,end]]},selectBestReroutePath=({trace,obstacleLabel,outputTraces,outputNetLabelPlacements,candidateResults,chipObstacles})=>{for(let candidate of candidateResults)if(candidate.usesHorizontalSegmentPush&&candidate.status==="valid"&&candidate.score)return candidate.path;let bestPath=null,bestScore=scoreTracePath({trace,tracePath:trace.tracePath,obstacleLabel,outputTraces,outputNetLabelPlacements,chipObstacles});for(let candidate of candidateResults)candidate.status!=="valid"||!candidate.score||isBetterScore(candidate.score,bestScore)&&(bestScore=candidate.score,bestPath=candidate.path);return bestPath},generateHorizontalSegmentPushCandidate=({trace,label,outputTraces})=>{let labelDirection=dir(label.orientation);if(labelDirection.x===0)return null;let path=trace.tracePath,bounds=getRectBounds(label.center,label.width,label.height),collidingVerticalSegmentIndex=path.findIndex((start,index)=>{let end=path[index+1];return!end||Math.abs(start.x-end.x)>=1e-9?!1:segmentIntersectsRect2(start,end,bounds)});if(collidingVerticalSegmentIndex<=0||collidingVerticalSegmentIndex>=path.length-2)return null;let previousAnchor=path[collidingVerticalSegmentIndex-1],verticalStart=path[collidingVerticalSegmentIndex],verticalEnd=path[collidingVerticalSegmentIndex+1],nextAnchor=path[collidingVerticalSegmentIndex+2];if(Math.abs(previousAnchor.y-verticalStart.y)>=1e-9||Math.abs(verticalEnd.y-nextAnchor.y)>=1e-9)return null;let segmentPushX=bounds.minX-LABEL_CLEARANCE;labelDirection.x>0&&(segmentPushX=bounds.maxX+LABEL_CLEARANCE);let corridorStep=labelDirection.x>0?LABEL_CLEARANCE:-LABEL_CLEARANCE,verticalLowY=Math.min(verticalStart.y,verticalEnd.y),verticalHighY=Math.max(verticalStart.y,verticalEnd.y);for(let shift=0;shift<MAX_CORRIDOR_SHIFTS&&corridorHasOtherNetTrace({x:segmentPushX,lowY:verticalLowY,highY:verticalHighY,outputTraces,netId:trace.globalConnNetId});shift++)segmentPushX+=corridorStep;let segmentPushStartY=getClearedHorizontalY({start:previousAnchor,end:{x:segmentPushX,y:verticalStart.y},labelBounds:bounds}),segmentPushEndY=getClearedHorizontalY({start:{x:segmentPushX,y:verticalEnd.y},end:nextAnchor,labelBounds:bounds}),segmentPushPath=[...path.slice(0,collidingVerticalSegmentIndex-1),previousAnchor];return Math.abs(previousAnchor.y-segmentPushStartY)>=1e-9&&segmentPushPath.push({x:previousAnchor.x,y:segmentPushStartY}),segmentPushPath.push({x:segmentPushX,y:segmentPushStartY}),segmentPushPath.push({x:segmentPushX,y:segmentPushEndY}),Math.abs(nextAnchor.y-segmentPushEndY)>=1e-9&&segmentPushPath.push({x:nextAnchor.x,y:segmentPushEndY}),segmentPushPath.push(nextAnchor,...path.slice(collidingVerticalSegmentIndex+3)),simplifyPath(segmentPushPath)},getClearedHorizontalY=({start,end,labelBounds})=>{if(!segmentIntersectsRect2(start,end,labelBounds))return start.y;let labelCenterY=(labelBounds.minY+labelBounds.maxY)/2;return start.y>=labelCenterY?labelBounds.maxY+LABEL_CLEARANCE:labelBounds.minY-LABEL_CLEARANCE},markSelectedCandidate=(candidateResults,bestPath)=>{if(bestPath)for(let candidate of candidateResults)candidate.selected=candidate.path===bestPath},scoreTracePath=({trace,tracePath,obstacleLabel,outputTraces,outputNetLabelPlacements,chipObstacles})=>{let candidateTrace={...trace,tracePath};return{labelIntersections:detectTraceLabelOverlap({traces:[candidateTrace],netLabels:outputNetLabelPlacements}).length,labelHugDistance:getLabelHugDistance(tracePath,obstacleLabel),traceIntersections:countTraceIntersections(candidateTrace,outputTraces),chipBoundaryOverlap:getChipBoundaryOverlap(tracePath,chipObstacles),pathLength:getPathLength2(tracePath)}},countTraceIntersections=(trace,outputTraces)=>{let count=0;for(let otherTrace of outputTraces)otherTrace.mspPairId!==trace.mspPairId&&(count+=countPathIntersections(trace.tracePath,otherTrace.tracePath));return count},isBetterScore=(score,bestScore)=>{let scoreHasLabelOverlap=score.labelIntersections>0,bestHasLabelOverlap=bestScore.labelIntersections>0;return scoreHasLabelOverlap!==bestHasLabelOverlap?!scoreHasLabelOverlap:score.chipBoundaryOverlap!==bestScore.chipBoundaryOverlap?score.chipBoundaryOverlap<bestScore.chipBoundaryOverlap:score.labelIntersections!==bestScore.labelIntersections?score.labelIntersections<bestScore.labelIntersections:score.labelHugDistance!==bestScore.labelHugDistance?score.labelHugDistance<bestScore.labelHugDistance:score.traceIntersections!==bestScore.traceIntersections?score.traceIntersections<bestScore.traceIntersections:score.pathLength<bestScore.pathLength},getLabelHugDistance=(tracePath,obstacleLabel)=>{let bounds=getRectBounds(obstacleLabel.center,obstacleLabel.width,obstacleLabel.height),distance52=0;for(let point6 of tracePath)distance52+=getPointDistanceFromRect(point6,bounds);return distance52},getPointDistanceFromRect=(point6,rect)=>{let dx3=Math.max(rect.minX-point6.x,0,point6.x-rect.maxX),dy3=Math.max(rect.minY-point6.y,0,point6.y-rect.maxY);return dx3+dy3},countCrossingsWithOtherTraces=params=>{let{trace,outputTraces}=params,crossingCount=0;for(let otherTrace of outputTraces)otherTrace.mspPairId!==trace.mspPairId&&otherTrace.globalConnNetId!==trace.globalConnNetId&&(crossingCount+=countPathIntersections(trace.tracePath,otherTrace.tracePath));return crossingCount},scoreSolutionTracePath=params=>{let{traces,outputTraces,chipObstacles}=params,chipEdgeRuns=0,traceCrossings=0;for(let trace of traces)doesPathRunAlongChipBoundary(trace.tracePath,chipObstacles)&&(chipEdgeRuns+=1),traceCrossings+=countCrossingsWithOtherTraces({trace,outputTraces});return{chipEdgeRuns,traceCrossings}},CANDIDATE_SELECTED_COLOR="blue",CANDIDATE_REJECTED_COLOR="red",visualizeExample28Solver=state2=>{let graphics=visualizeInputProblem2(state2.inputProblem);return drawTraces(graphics,state2),drawNetLabels(graphics,state2),state2.solved||(drawCurrentCandidates(graphics,state2.currentCandidateResults),drawCurrentOverlap(graphics,state2)),graphics},drawTraces=(graphics,state2)=>{for(let trace of state2.outputTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels=(graphics,state2)=>{for(let label of state2.outputNetLabelPlacements){let color=getColorFromString2(label.globalConnNetId,.35);graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:color,strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
650
+ orientation: ${p3.orientation}`});return graphics}},AVAILABLE_Y_PLUS_COLOR="#ef4444",AVAILABLE_Y_MINUS_COLOR="#000000",AVAILABLE_ORIENTATION_FILL_ALPHA="66",colorAvailableNetOrientationLabels=(graphicsObject,inputProblem)=>{let availableOrientations=inputProblem.availableNetLabelOrientations;if(availableOrientations)for(let rect of graphicsObject.rects??[]){let orientations=getAvailableOrientationsForRect(rect.label,availableOrientations);if(!orientations)continue;let hasYPlus=orientations.includes("y+"),hasYMinus=orientations.includes("y-");if(hasYPlus===hasYMinus)continue;let color=hasYPlus?AVAILABLE_Y_PLUS_COLOR:AVAILABLE_Y_MINUS_COLOR;rect.fill=`${color}${AVAILABLE_ORIENTATION_FILL_ALPHA}`,rect.stroke=color,rect.color=color}},getAvailableOrientationsForRect=(label,availableOrientations)=>{for(let netId of getNetIdsFromRectLabel(label))if(Object.hasOwn(availableOrientations,netId))return availableOrientations[netId]},getNetIdsFromRectLabel=label=>label?[label.match(/^netId: (.+)$/m)?.[1],label.match(/^globalConnNetId: (.+)$/m)?.[1]].filter(netId=>!!(netId&&netId!=="undefined")):[],groupLabelsByChipAndOrientation=({labels,chips})=>{let groupedLabels={},chipIdByPinId=new Map(chips.flatMap(chip=>chip.pins.map(pin=>[pin.pinId,chip.chipId])));for(let label of labels){if(label.pinIds.length===0)continue;let pinId=label.pinIds[0],chipId=(pinId.includes(".")?pinId.split(".")[0]:void 0)??chipIdByPinId.get(pinId);if(!chipId)continue;let key=`${chipId}-${label.orientation}`;groupedLabels[key]||(groupedLabels[key]=[]),groupedLabels[key].push(label)}return groupedLabels},mergeLabelGroup=(group,groupKey)=>{if(group.length===0)throw new Error("Cannot merge an empty group of labels.");let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0,allPinIds=new Set,allMspConnectionPairIds=new Set,originalNetIds=new Set;for(let label of group){let bounds=getRectBounds(label.center,label.width,label.height);minX=Math.min(minX,bounds.minX),minY=Math.min(minY,bounds.minY),maxX=Math.max(maxX,bounds.maxX),maxY=Math.max(maxY,bounds.maxY),label.pinIds.forEach(id3=>allPinIds.add(id3)),label.mspConnectionPairIds.forEach(id3=>allMspConnectionPairIds.add(id3)),originalNetIds.add(label.globalConnNetId)}let newWidth=maxX-minX,newHeight=maxY-minY,newCenter={x:minX+newWidth/2,y:minY+newHeight/2},template=group[0],syntheticId=`merged-group-${groupKey}`;return{mergedLabel:{...template,globalConnNetId:syntheticId,center:newCenter,width:newWidth,height:newHeight,pinIds:Array.from(allPinIds),mspConnectionPairIds:Array.from(allMspConnectionPairIds)},originalNetIds}},filterLabelsAtTraceEdges=({labels,traces,distanceThreshold=.5})=>{let tracesByNetId=new Map;if(!traces)throw new Error("No traces provided to filterLabelsAtTraceEdges");for(let trace of traces)trace.globalConnNetId&&(tracesByNetId.has(trace.globalConnNetId)||tracesByNetId.set(trace.globalConnNetId,[]),tracesByNetId.get(trace.globalConnNetId).push(trace));let filteredLabels=[];for(let label of labels){if(label.mspConnectionPairIds.length===0){filteredLabels.push(label);continue}let relevantTraces=tracesByNetId.get(label.globalConnNetId),isNearTraceEdge=!1;if(!(!relevantTraces||relevantTraces.length===0)){for(let trace of relevantTraces){if(trace.tracePath.length===0)continue;let startPoint=trace.tracePath[0],endPoint=trace.tracePath[trace.tracePath.length-1],startDist=distance2(label.center,startPoint),endDist=distance2(label.center,endPoint);if(startDist<=distanceThreshold||endDist<=distanceThreshold){isNearTraceEdge=!0;break}}isNearTraceEdge&&filteredLabels.push(label)}}return filteredLabels},MergedNetLabelObstacleSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"output");__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"pipelineStep","filtering_labels");__publicField(this,"filteredLabels",[]);__publicField(this,"labelGroups",{});__publicField(this,"groupKeysToProcess",[]);__publicField(this,"finalPlacements",[]);__publicField(this,"mergedLabelNetIdMap",{});__publicField(this,"activeMergingGroupKey",null);this.input=solverInput,this.inputProblem=solverInput.inputProblem,this.traces=solverInput.traces,this.output={netLabelPlacements:solverInput.netLabelPlacements,mergedLabelNetIdMap:{}}}_step(){switch(this.pipelineStep){case"filtering_labels":this.filteredLabels=filterLabelsAtTraceEdges({labels:this.input.netLabelPlacements,traces:this.traces}),this.pipelineStep="grouping_labels";break;case"grouping_labels":this.labelGroups=groupLabelsByChipAndOrientation({labels:this.filteredLabels,chips:this.inputProblem.chips}),this.groupKeysToProcess=Object.keys(this.labelGroups),this.pipelineStep="merging_groups";break;case"merging_groups":if(this.groupKeysToProcess.length===0){this.pipelineStep="finalizing",this.activeMergingGroupKey=null;break}let groupKey=this.groupKeysToProcess.pop();this.activeMergingGroupKey=groupKey;let group=this.labelGroups[groupKey];if(group.length>1){let{mergedLabel,originalNetIds}=mergeLabelGroup(group,groupKey);this.finalPlacements.push(mergedLabel),this.mergedLabelNetIdMap[mergedLabel.globalConnNetId]=originalNetIds}else this.finalPlacements.push(...group);break;case"finalizing":let processedOriginalIds=new Set(this.finalPlacements.flatMap(p3=>this.mergedLabelNetIdMap[p3.globalConnNetId]?[...this.mergedLabelNetIdMap[p3.globalConnNetId]]:[p3.globalConnNetId])),unprocessedLabels=this.input.netLabelPlacements.filter(l6=>!processedOriginalIds.has(l6.globalConnNetId));this.output={netLabelPlacements:[...this.finalPlacements,...unprocessedLabels],mergedLabelNetIdMap:this.mergedLabelNetIdMap},this.solved=!0;break}}getOutput(){return this.output}visualize(){let graphics=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});graphics.rects||(graphics.rects=[]),graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.texts||(graphics.texts=[]);let originalLabelsById=new Map;for(let label of this.input.netLabelPlacements)originalLabelsById.set(label.globalConnNetId,label);for(let trace of this.traces){let line2={points:trace.tracePath.map(p3=>({x:p3.x,y:p3.y})),strokeColor:"blue"};graphics.lines.push(line2)}if(this.activeMergingGroupKey&&this.labelGroups[this.activeMergingGroupKey]){let activeGroup=this.labelGroups[this.activeMergingGroupKey];for(let label of activeGroup)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:"rgba(255, 165, 0, 0.5)",stroke:"orange"})}for(let finalLabel of this.output.netLabelPlacements){let isMerged=finalLabel.globalConnNetId.startsWith("merged-group-"),color=getColorFromString2(finalLabel.globalConnNetId);if(isMerged){graphics.rects.push({center:finalLabel.center,width:finalLabel.width,height:finalLabel.height,fill:color.replace(/, 1\)/,", 0.2)"),stroke:color,label:finalLabel.globalConnNetId});let originalNetIds=this.output.mergedLabelNetIdMap[finalLabel.globalConnNetId];if(originalNetIds)for(let originalNetId of originalNetIds){let originalLabel=originalLabelsById.get(originalNetId);if(originalLabel){let bounds=getRectBounds(originalLabel.center,originalLabel.width,originalLabel.height),p12={x:bounds.minX,y:bounds.minY},p22={x:bounds.maxX,y:bounds.minY},p3={x:bounds.maxX,y:bounds.maxY},p42={x:bounds.minX,y:bounds.maxY};graphics.lines.push({points:[p12,p22,p3,p42,p12],strokeColor:color,strokeDash:"4 4"}),graphics.lines.push({points:[originalLabel.center,finalLabel.center],strokeColor:color,strokeDash:"2 2"})}}}else graphics.rects.push({center:finalLabel.center,width:finalLabel.width,height:finalLabel.height,stroke:color,label:finalLabel.globalConnNetId})}return graphics}},detectTraceLabelOverlap=({traces,netLabels=[]})=>{let overlaps=[];for(let trace of traces)for(let label of netLabels){let labelBounds=getRectBounds(label.center,label.width,label.height);for(let j6=0;j6<trace.tracePath.length-1;j6++){let p12=trace.tracePath[j6],p22=trace.tracePath[j6+1];if(segmentIntersectsRect2(p12,p22,labelBounds)){if(trace.globalConnNetId===label.globalConnNetId)break;overlaps.push({trace,label});break}}}return overlaps},findTraceViolationZone=({path,labelBounds,paddedBounds=labelBounds})=>{let firstCollidingSeg=-1,lastCollidingSeg=-1;for(let i6=0;i6<path.length-1;i6++)segmentIntersectsRect2(path[i6],path[i6+1],labelBounds)&&(firstCollidingSeg===-1&&(firstCollidingSeg=i6),lastCollidingSeg=i6);if(firstCollidingSeg===-1)return{firstInsideIndex:-1,lastInsideIndex:-1};let isInsidePadded=p3=>p3.x>paddedBounds.minX&&p3.x<paddedBounds.maxX&&p3.y>paddedBounds.minY&&p3.y<paddedBounds.maxY,entryIndex=firstCollidingSeg;for(;entryIndex>0&&isInsidePadded(path[entryIndex]);)entryIndex--;let exitIndex=lastCollidingSeg+1;for(;exitIndex<path.length-1&&isInsidePadded(path[exitIndex]);)exitIndex++;return{firstInsideIndex:entryIndex+1,lastInsideIndex:exitIndex-1}},generateSnipAndReconnectCandidates=({initialTrace,firstInsideIndex,lastInsideIndex,labelBounds,paddingBuffer,detourCount})=>{if(firstInsideIndex<=0||lastInsideIndex>=initialTrace.tracePath.length-1)return[];let entryPoint=initialTrace.tracePath[firstInsideIndex-1],exitPoint=initialTrace.tracePath[lastInsideIndex+1],pathToEntry=initialTrace.tracePath.slice(0,firstInsideIndex),pathFromExit=initialTrace.tracePath.slice(lastInsideIndex+1),allCandidateDetours=[];entryPoint.x!==exitPoint.x&&entryPoint.y!==exitPoint.y?(allCandidateDetours.push([{x:exitPoint.x,y:entryPoint.y}]),allCandidateDetours.push([{x:entryPoint.x,y:exitPoint.y}])):(entryPoint.x===exitPoint.x||entryPoint.y===exitPoint.y)&&allCandidateDetours.push([]);let buffer=paddingBuffer+detourCount*paddingBuffer,leftX=labelBounds.minX-buffer,rightX=labelBounds.maxX+buffer,topY=labelBounds.maxY+buffer,bottomY=labelBounds.minY-buffer;return(entryPoint.x<=labelBounds.minX||exitPoint.x<=labelBounds.minX)&&entryPoint.x<labelBounds.maxX&&exitPoint.x<labelBounds.maxX&&allCandidateDetours.push([{x:leftX,y:entryPoint.y},{x:leftX,y:exitPoint.y}]),(entryPoint.x>=labelBounds.maxX||exitPoint.x>=labelBounds.maxX)&&entryPoint.x>labelBounds.minX&&exitPoint.x>labelBounds.minX&&allCandidateDetours.push([{x:rightX,y:entryPoint.y},{x:rightX,y:exitPoint.y}]),(entryPoint.y>=labelBounds.maxY||exitPoint.y>=labelBounds.maxY)&&entryPoint.y>labelBounds.minY&&exitPoint.y>labelBounds.minY&&allCandidateDetours.push([{x:entryPoint.x,y:topY},{x:exitPoint.x,y:topY}]),(entryPoint.y<=labelBounds.minY||exitPoint.y<=labelBounds.minY)&&entryPoint.y<labelBounds.maxY&&exitPoint.y<labelBounds.maxY&&allCandidateDetours.push([{x:entryPoint.x,y:bottomY},{x:exitPoint.x,y:bottomY}]),allCandidateDetours.map(detour=>[...pathToEntry,...detour,...pathFromExit])},generateFourPointDetourCandidates=({initialTrace,label,labelBounds,paddingBuffer,detourCount})=>{let isMergedLabel=label.globalConnNetId.startsWith("merged-group-"),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},entryPoint,exitPoint,entryIndex,exitIndex,isPointInRect=p3=>p3.x>=paddedLabelBounds.minX&&p3.x<=paddedLabelBounds.maxX&&p3.y>=paddedLabelBounds.minY&&p3.y<=paddedLabelBounds.maxY;if(isMergedLabel){let firstInsideIndex=-1;for(let i6=0;i6<initialTrace.tracePath.length;i6++)if(isPointInRect(initialTrace.tracePath[i6])){firstInsideIndex=i6;break}if(firstInsideIndex===-1)return[];entryIndex=Math.max(0,firstInsideIndex-1),entryPoint=initialTrace.tracePath[entryIndex];let firstOutsideIndex=-1;for(let i6=firstInsideIndex;i6<initialTrace.tracePath.length;i6++)if(!isPointInRect(initialTrace.tracePath[i6])){firstOutsideIndex=i6;break}firstOutsideIndex===-1?exitIndex=initialTrace.tracePath.length-1:exitIndex=firstOutsideIndex,exitPoint=initialTrace.tracePath[exitIndex]}else{let firstCollidingSeg=-1,lastCollidingSeg=-1;for(let i6=0;i6<initialTrace.tracePath.length-1;i6++)segmentIntersectsRect(initialTrace.tracePath[i6],initialTrace.tracePath[i6+1],{...labelBounds,chipId:"temp-obstacle"})&&(firstCollidingSeg===-1&&(firstCollidingSeg=i6),lastCollidingSeg=i6);if(firstCollidingSeg===-1)return[];entryIndex=firstCollidingSeg,exitIndex=lastCollidingSeg+1,entryPoint=initialTrace.tracePath[entryIndex],exitPoint=initialTrace.tracePath[exitIndex]}if(!entryPoint||!exitPoint||entryIndex>=exitIndex)return[];let candidateDetours=[],dx3=exitPoint.x-entryPoint.x,dy3=exitPoint.y-entryPoint.y;if(Math.abs(dx3)>Math.abs(dy3)){let yCandidates=[paddedLabelBounds.maxY,paddedLabelBounds.minY];for(let newY of yCandidates)candidateDetours.push(dx3>0?[{x:paddedLabelBounds.minX,y:entryPoint.y},{x:paddedLabelBounds.minX,y:newY},{x:paddedLabelBounds.maxX,y:newY},{x:paddedLabelBounds.maxX,y:exitPoint.y}]:[{x:paddedLabelBounds.maxX,y:entryPoint.y},{x:paddedLabelBounds.maxX,y:newY},{x:paddedLabelBounds.minX,y:newY},{x:paddedLabelBounds.minX,y:exitPoint.y}])}else{let xCandidates=[paddedLabelBounds.maxX,paddedLabelBounds.minX];for(let newX of xCandidates)candidateDetours.push(dy3>0?[{x:entryPoint.x,y:paddedLabelBounds.minY},{x:newX,y:paddedLabelBounds.minY},{x:newX,y:paddedLabelBounds.maxY},{x:exitPoint.x,y:paddedLabelBounds.maxY}]:[{x:entryPoint.x,y:paddedLabelBounds.maxY},{x:newX,y:paddedLabelBounds.maxY},{x:newX,y:paddedLabelBounds.minY},{x:exitPoint.x,y:paddedLabelBounds.minY}])}return candidateDetours.map(detourPoints=>[...initialTrace.tracePath.slice(0,entryIndex),entryPoint,...detourPoints,exitPoint,...initialTrace.tracePath.slice(exitIndex+1)])},simplifyPath=path=>{if(path.length<3)return path;let newPath=[path[0]];for(let i6=1;i6<path.length-1;i6++){let p12=newPath[newPath.length-1],p22=path[i6],p3=path[i6+1];isVertical(p12,p22)&&isVertical(p22,p3)||isHorizontal(p12,p22)&&isHorizontal(p22,p3)||newPath.push(p22)}if(newPath.push(path[path.length-1]),newPath.length<3)return newPath;let finalPath=[newPath[0]];for(let i6=1;i6<newPath.length-1;i6++){let p12=finalPath[finalPath.length-1],p22=newPath[i6],p3=newPath[i6+1];isVertical(p12,p22)&&isVertical(p22,p3)||isHorizontal(p12,p22)&&isHorizontal(p22,p3)||finalPath.push(p22)}return finalPath.push(newPath[newPath.length-1]),finalPath},generateRerouteCandidates=({trace,label,paddingBuffer,detourCount})=>{let initialTrace={...trace,tracePath:simplifyPath(trace.tracePath)};if(trace.globalConnNetId===label.globalConnNetId)return[initialTrace.tracePath];let labelBoundsRaw=getRectBounds(label.center,label.width,label.height),labelBounds={minX:labelBoundsRaw.minX,minY:labelBoundsRaw.minY,maxX:labelBoundsRaw.maxX,maxY:labelBoundsRaw.maxY,chipId:`netlabel-${label.netId}`},fourPointCandidates=generateFourPointDetourCandidates({initialTrace,label,labelBounds,paddingBuffer,detourCount}),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},{firstInsideIndex,lastInsideIndex}=findTraceViolationZone({path:initialTrace.tracePath,labelBounds,paddedBounds:paddedLabelBounds}),snipReconnectCandidates=generateSnipAndReconnectCandidates({initialTrace,firstInsideIndex,lastInsideIndex,labelBounds,paddingBuffer,detourCount});return[...fourPointCandidates,...snipReconnectCandidates]},COINCIDENT_EPS=.002,GEOMETRY_EPS=1e-6,SCHEMATIC_TRACE_STROKE_WIDTH=.02,SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE=SCHEMATIC_TRACE_STROKE_WIDTH+GEOMETRY_EPS,SCHEMATIC_TRACE_MIN_VISUAL_CENTERLINE_CLEARANCE=SCHEMATIC_TRACE_STROKE_WIDTH*3,doesPathCoincideWithTraces=(path,traces)=>{let rangesOverlap1D=(a12,a22,b12,b22)=>Math.min(Math.max(a12,a22),Math.max(b12,b22))-Math.max(Math.min(a12,a22),Math.min(b12,b22))>COINCIDENT_EPS;for(let i6=0;i6<path.length-1;i6++){let pathSegStart=path[i6],pathSegEnd=path[i6+1],isVertical52=Math.abs(pathSegStart.x-pathSegEnd.x)<COINCIDENT_EPS,isHorizontal42=Math.abs(pathSegStart.y-pathSegEnd.y)<COINCIDENT_EPS;if(!isVertical52&&!isHorizontal42)continue;let crossAxis=isVertical52?"x":"y",alongAxis=isVertical52?"y":"x";for(let trace of traces)for(let j6=0;j6<trace.tracePath.length-1;j6++){let traceSegStart=trace.tracePath[j6],traceSegEnd=trace.tracePath[j6+1];if(!(!(Math.abs(traceSegStart[crossAxis]-traceSegEnd[crossAxis])<COINCIDENT_EPS)||!(Math.abs(pathSegStart[crossAxis]-traceSegStart[crossAxis])<COINCIDENT_EPS))&&rangesOverlap1D(pathSegStart[alongAxis],pathSegEnd[alongAxis],traceSegStart[alongAxis],traceSegEnd[alongAxis]))return!0}}return!1},doesPathOverlapTraceStrokes=(path,traces)=>{let traceStrokeRadius=SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE/2,getStrokeBounds=(start,end,isVertical52)=>isVertical52?{minX:start.x-traceStrokeRadius,maxX:start.x+traceStrokeRadius,minY:Math.min(start.y,end.y),maxY:Math.max(start.y,end.y)}:{minX:Math.min(start.x,end.x),maxX:Math.max(start.x,end.x),minY:start.y-traceStrokeRadius,maxY:start.y+traceStrokeRadius};for(let pathIndex=0;pathIndex<path.length-1;pathIndex++){let pathStart=path[pathIndex],pathEnd=path[pathIndex+1],isVertical52=Math.abs(pathStart.x-pathEnd.x)<COINCIDENT_EPS,isHorizontal42=Math.abs(pathStart.y-pathEnd.y)<COINCIDENT_EPS;if(!isVertical52&&!isHorizontal42)continue;let pathBounds=getStrokeBounds(pathStart,pathEnd,isVertical52);for(let trace of traces)for(let traceIndex=0;traceIndex<trace.tracePath.length-1;traceIndex++){let traceStart=trace.tracePath[traceIndex],traceEnd=trace.tracePath[traceIndex+1];if(!(isVertical52?Math.abs(traceStart.x-traceEnd.x)<COINCIDENT_EPS:Math.abs(traceStart.y-traceEnd.y)<COINCIDENT_EPS))continue;let overlap=boundsIntersection(pathBounds,getStrokeBounds(traceStart,traceEnd,isVertical52));if(!overlap)continue;if((isVertical52?overlap.maxY-overlap.minY:overlap.maxX-overlap.minX)>COINCIDENT_EPS)return!0}}return!1},MAX_TRIES=5,PATH_LENGTH_EPSILON=1e-9,getPathLength=points=>{let length4=0;for(let pointIndex=0;pointIndex<points.length-1;pointIndex++){let point6=points[pointIndex],nextPoint=points[pointIndex+1];length4+=Math.abs(nextPoint.x-point6.x)+Math.abs(nextPoint.y-point6.y)}return length4},SingleOverlapSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"queuedCandidatePaths");__publicField(this,"solvedTracePath",null);__publicField(this,"initialTrace");__publicField(this,"problem");__publicField(this,"obstacles");__publicField(this,"label");__publicField(this,"tracesToAvoidOverlapping");__publicField(this,"netLabelPlacements");__publicField(this,"detourCount");__publicField(this,"_tried",0);this.initialTrace=solverInput.trace,this.problem=solverInput.problem,this.label=solverInput.label,this.detourCount=solverInput.detourCount,this.tracesToAvoidOverlapping=(solverInput.tracesToAvoidOverlapping??[]).filter(t53=>t53.globalConnNetId!==solverInput.trace.globalConnNetId),this.netLabelPlacements=solverInput.netLabelPlacements??[solverInput.label],this.obstacles=getObstacleRects(this.problem);let effectivePadding=solverInput.paddingBuffer+solverInput.detourCount*solverInput.paddingBuffer,candidates=generateRerouteCandidates({...solverInput,paddingBuffer:effectivePadding}),getLabelOverlapCount=path=>detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:path}],netLabels:this.netLabelPlacements}).length,candidateByPath=new Map;for(let candidate of candidates){let simplifiedCandidate=simplifyPath(candidate);candidateByPath.set(simplifiedCandidate.map(point6=>`${point6.x},${point6.y}`).join(";"),simplifiedCandidate)}this.queuedCandidatePaths=[...candidateByPath.values()].sort((a6,b6)=>{let pathLengthDifference=getPathLength(a6)-getPathLength(b6);if(Math.abs(pathLengthDifference)>=PATH_LENGTH_EPSILON)return pathLengthDifference;let overlapCountDifference=getLabelOverlapCount(a6)-getLabelOverlapCount(b6);return overlapCountDifference!==0?overlapCountDifference:a6.length-b6.length})}_step(){if(this.queuedCandidatePaths.length===0||this._tried>=MAX_TRIES){this.failed=!0;return}this._tried++;let nextCandidatePath=this.queuedCandidatePaths.shift(),simplifiedPath=simplifyPath(nextCandidatePath),stillOverlapsLabel=detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:simplifiedPath}],netLabels:[this.label]}).length>0,initialPath=simplifyPath(this.initialTrace.tracePath),initialLabelOverlaps=detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:initialPath}],netLabels:this.netLabelPlacements}),candidateLabelOverlaps=detectTraceLabelOverlap({traces:[{...this.initialTrace,tracePath:simplifiedPath}],netLabels:this.netLabelPlacements});!stillOverlapsLabel&&candidateLabelOverlaps.length<=initialLabelOverlaps.length&&!isPathCollidingWithObstacles(simplifiedPath,this.obstacles)&&!doesPathCoincideWithTraces(simplifiedPath,this.tracesToAvoidOverlapping)&&(this.solvedTracePath=simplifiedPath,this.solved=!0)}visualize(){let graphics=visualizeInputProblem2(this.problem,{chipAlpha:.1,connectionAlpha:.1});return graphics.lines||(graphics.lines=[]),graphics.rects||(graphics.rects=[]),graphics.lines.push({points:this.initialTrace.tracePath,strokeColor:"red",strokeDash:"4 4"}),graphics.rects.push({center:this.label.center,width:this.label.width,height:this.label.height,fill:"rgba(255, 0, 0, 0.2)"}),!this.solvedTracePath&&this.queuedCandidatePaths.length>0&&graphics.lines.push({points:this.queuedCandidatePaths[0],strokeColor:"orange"}),this.solvedTracePath&&graphics.lines.push({points:this.solvedTracePath,strokeColor:"green"}),graphics}},doesTraceStartOrEndInLabel=({trace,label})=>{if(trace.tracePath.length<2)return!1;let firstSegmentTrace={...trace,tracePath:[trace.tracePath[0],trace.tracePath[1]]};if(detectTraceLabelOverlap({traces:[firstSegmentTrace],netLabels:[label]}).length>0)return!0;if(trace.tracePath.length>2){let lastPoint=trace.tracePath[trace.tracePath.length-1],secondToLastPoint=trace.tracePath[trace.tracePath.length-2],lastSegmentTrace={...trace,tracePath:[secondToLastPoint,lastPoint]};if(detectTraceLabelOverlap({traces:[lastSegmentTrace],netLabels:[label]}).length>0)return!0}return!1},visualizeDecomposition=params=>{let{decomposedChildLabels,collidingTrace,mergedLabel,graphics}=params;graphics.rects||(graphics.rects=[]),graphics.texts||(graphics.texts=[]);for(let childLabel of decomposedChildLabels){let isOwnLabel=childLabel.globalConnNetId===collidingTrace.globalConnNetId;graphics.rects.push({center:childLabel.center,width:childLabel.width,height:childLabel.height,fill:isOwnLabel?"green":"red"})}return graphics.texts.push({x:mergedLabel.center.x,y:mergedLabel.center.y+mergedLabel.height/2+.5,text:`DECOMPOSITION: Trace ${collidingTrace.mspPairId} vs Merged Label ${mergedLabel.globalConnNetId}`,fontSize:.3,color:"blue"}),graphics},OverlapAvoidanceStepSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"inputProblem");__publicField(this,"initialNetLabelPlacements");__publicField(this,"mergedNetLabelPlacements");__publicField(this,"mergedLabelNetIdMap");__publicField(this,"allTraces");__publicField(this,"tracesToAvoidOverlapping");__publicField(this,"modifiedTraces",[]);__publicField(this,"completedReroutes",[]);__publicField(this,"PADDING_BUFFER",.1);__publicField(this,"detourCounts",new Map);__publicField(this,"activeSubSolver",null);__publicField(this,"overlapQueue",[]);__publicField(this,"activeOverlap",null);__publicField(this,"recentlyFailed",new Set);__publicField(this,"currentlyProcessingOverlap",null);__publicField(this,"decomposedChildLabels",null);this.inputProblem=solverInput.inputProblem,this.initialNetLabelPlacements=solverInput.initialNetLabelPlacements,this.mergedNetLabelPlacements=solverInput.mergedNetLabelPlacements,this.mergedLabelNetIdMap=solverInput.mergedLabelNetIdMap,this.allTraces=[...solverInput.traces],this.tracesToAvoidOverlapping=solverInput.tracesToAvoidOverlapping??[],this.detourCounts=solverInput.detourCounts}_step(){if(this.currentlyProcessingOverlap=null,this.decomposedChildLabels=null,this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){let solvedPath=this.activeSubSolver.solvedTracePath;if(solvedPath){this.completedReroutes.push({initialTrace:{...this.activeSubSolver.initialTrace,tracePath:this.activeSubSolver.initialTrace.tracePath.map(point6=>({...point6}))},reroutedTracePath:solvedPath.map(point6=>({...point6})),label:this.activeSubSolver.label,detourCount:this.activeSubSolver.detourCount});let traceIndex=this.allTraces.findIndex(t53=>t53.mspPairId===this.activeSubSolver.initialTrace.mspPairId);traceIndex!==-1&&(this.allTraces[traceIndex].tracePath=solvedPath,this.modifiedTraces.push(this.allTraces[traceIndex]))}this.activeSubSolver=null,this.activeOverlap=null,this.recentlyFailed.clear()}else if(this.activeSubSolver.failed){let overlapId=`${this.activeOverlap.trace.mspPairId}-${this.activeOverlap.label.globalConnNetId}`;this.recentlyFailed.add(overlapId),this.activeSubSolver=null,this.activeOverlap=null}return}let overlaps=detectTraceLabelOverlap({traces:this.allTraces,netLabels:this.mergedNetLabelPlacements});if(overlaps.length===0){this.solved=!0;return}let nonFailedOverlaps=overlaps.filter(o6=>{let overlapId=`${o6.trace.mspPairId}-${o6.label.globalConnNetId}`;return!this.recentlyFailed.has(overlapId)});if(nonFailedOverlaps.length===0){this.solved=!0;return}this.overlapQueue=nonFailedOverlaps;let nextOverlap=this.overlapQueue.shift();if(this.currentlyProcessingOverlap=nextOverlap??null,nextOverlap){let traceToFix=this.allTraces.find(t53=>t53.mspPairId===nextOverlap.trace.mspPairId),labelToAvoid=nextOverlap.label,originalNetIds=this.mergedLabelNetIdMap[labelToAvoid.globalConnNetId];if(originalNetIds?.has(traceToFix.globalConnNetId)){let childLabels=this.initialNetLabelPlacements.filter(l6=>originalNetIds.has(l6.globalConnNetId));this.decomposedChildLabels=childLabels;let actualOverlapLabel=null;for(let childLabel of childLabels)if(detectTraceLabelOverlap({traces:[traceToFix],netLabels:[childLabel]}).length>0){actualOverlapLabel=childLabel;break}if(actualOverlapLabel){let detourCount2=this.detourCounts.get(actualOverlapLabel.globalConnNetId)??0;this.detourCounts.set(actualOverlapLabel.globalConnNetId,detourCount2+1),this.activeOverlap=nextOverlap,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:actualOverlapLabel,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount:detourCount2,tracesToAvoidOverlapping:this.tracesToAvoidOverlapping,netLabelPlacements:this.initialNetLabelPlacements})}else{let overlapId=`${traceToFix.mspPairId}-${labelToAvoid.globalConnNetId}`;this.recentlyFailed.add(overlapId)}return}if(originalNetIds&&doesTraceStartOrEndInLabel({trace:traceToFix,label:labelToAvoid})){let childLabels=this.initialNetLabelPlacements.filter(l6=>originalNetIds.has(l6.globalConnNetId));this.decomposedChildLabels=childLabels;let actualOverlapLabel=null;for(let childLabel of childLabels)if(detectTraceLabelOverlap({traces:[traceToFix],netLabels:[childLabel]}).length>0){actualOverlapLabel=childLabel;break}if(actualOverlapLabel){let detourCount2=this.detourCounts.get(actualOverlapLabel.globalConnNetId)??0;this.detourCounts.set(actualOverlapLabel.globalConnNetId,detourCount2+1),this.activeOverlap=nextOverlap,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:actualOverlapLabel,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount:detourCount2,tracesToAvoidOverlapping:this.tracesToAvoidOverlapping,netLabelPlacements:this.initialNetLabelPlacements})}else{let overlapId=`${traceToFix.mspPairId}-${labelToAvoid.globalConnNetId}`;this.recentlyFailed.add(overlapId)}return}let detourCount=this.detourCounts.get(labelToAvoid.globalConnNetId)??0;this.detourCounts.set(labelToAvoid.globalConnNetId,detourCount+1),this.activeOverlap=nextOverlap,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:labelToAvoid,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount,tracesToAvoidOverlapping:this.tracesToAvoidOverlapping,netLabelPlacements:this.initialNetLabelPlacements})}}getOutput(){return{allTraces:this.allTraces,modifiedTraces:this.modifiedTraces,detourCounts:this.detourCounts}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);graphics.lines||(graphics.lines=[]);for(let trace of this.allTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});if(this.currentlyProcessingOverlap){let{trace,label}=this.currentlyProcessingOverlap;graphics.lines.push({points:trace.tracePath,strokeColor:"red"}),this.decomposedChildLabels?visualizeDecomposition({decomposedChildLabels:this.decomposedChildLabels,collidingTrace:trace,mergedLabel:label,graphics}):(graphics.rects||(graphics.rects=[]),graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:"yellow"}),graphics.texts||(graphics.texts=[]),graphics.texts.push({x:label.center.x,y:label.center.y+label.height/2+.5,text:`COLLISION: Trace ${trace.mspPairId} vs Label ${label.globalConnNetId}`,fontSize:.3,color:"red"}))}return graphics}},TraceLabelOverlapAvoidanceSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"inputProblem");__publicField(this,"netLabelPlacements");__publicField(this,"unprocessedTraces",[]);__publicField(this,"cleanTraces",[]);__publicField(this,"subSolvers",[]);__publicField(this,"phase","searching_for_overlaps");__publicField(this,"detourCounts",new Map);__publicField(this,"labelMergingSolver");__publicField(this,"allInputTraces");this.inputProblem=solverInput.inputProblem,this.unprocessedTraces=[...solverInput.traces],this.allInputTraces=solverInput.traces,this.netLabelPlacements=solverInput.netLabelPlacements,this.cleanTraces=[],this.subSolvers=[]}_step(){if(this.phase==="searching_for_overlaps"){if(this.unprocessedTraces.length===0){this.phase="fixing_overlaps";return}let currentTargetTrace=this.unprocessedTraces.shift(),localOverlaps=detectTraceLabelOverlap({traces:[currentTargetTrace],netLabels:this.netLabelPlacements});if(localOverlaps.length===0)this.cleanTraces.push(currentTargetTrace);else{let collidingLabels=localOverlaps.map(o6=>o6.label),labelMerger=new MergedNetLabelObstacleSolver({netLabelPlacements:collidingLabels,inputProblem:this.inputProblem,traces:[currentTargetTrace]});labelMerger.solve();let mergingOutput=labelMerger.getOutput(),subSolver=new OverlapAvoidanceStepSolver({inputProblem:this.inputProblem,traces:[currentTargetTrace],initialNetLabelPlacements:this.netLabelPlacements,mergedNetLabelPlacements:mergingOutput.netLabelPlacements,mergedLabelNetIdMap:mergingOutput.mergedLabelNetIdMap,detourCounts:this.detourCounts,tracesToAvoidOverlapping:this.allInputTraces.filter(t53=>t53.mspPairId!==currentTargetTrace.mspPairId)});this.subSolvers.push(subSolver)}}else if(this.phase==="fixing_overlaps"){if(this.subSolvers.every(s6=>s6.solved||s6.failed)){this.labelMergingSolver||(this.labelMergingSolver=new MergedNetLabelObstacleSolver({netLabelPlacements:this.netLabelPlacements,inputProblem:this.inputProblem,traces:this.getOutput().traces}),this.labelMergingSolver.solve()),this.solved=!0;return}for(let solver of this.subSolvers)!solver.solved&&!solver.failed&&solver.step()}}getOutput(){let solvedTraces=this.subSolvers.flatMap(s6=>s6.getOutput().allTraces);return{traces:[...this.cleanTraces,...solvedTraces],completedReroutes:this.subSolvers.flatMap(solver=>solver.completedReroutes),netLabelPlacements:this.labelMergingSolver?.getOutput().netLabelPlacements??this.netLabelPlacements}}visualize(){let graphics=visualizeInputProblem2(this.inputProblem);graphics.lines||(graphics.lines=[]),graphics.rects||(graphics.rects=[]);for(let trace of this.cleanTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let solver of this.subSolvers){let solverGraphics=solver.visualize();graphics.lines.push(...solverGraphics.lines??[]),graphics.rects.push(...solverGraphics.rects??[]),graphics.points.push(...solverGraphics.points??[])}for(let label of this.netLabelPlacements){let color=getColorFromString2(label.globalConnNetId,.3);graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:color,stroke:color.replace("0.3","1"),label:label.globalConnNetId})}return graphics}},correctPinsInsideChips=problem=>{for(let chip of problem.chips){let bounds=getInputChipBounds(chip);for(let pin of chip.pins){if(!(pin.x>bounds.minX&&pin.x<bounds.maxX&&pin.y>bounds.minY&&pin.y<bounds.maxY))continue;if(pin._facingDirection){pin._facingDirection==="x-"?pin.x=bounds.minX:pin._facingDirection==="x+"?pin.x=bounds.maxX:pin._facingDirection==="y-"?pin.y=bounds.minY:pin.y=bounds.maxY;continue}let distLeft=pin.x-bounds.minX,distRight=bounds.maxX-pin.x,distBottom=pin.y-bounds.minY,distTop=bounds.maxY-pin.y,minDist=Math.min(distLeft,distRight,distBottom,distTop);minDist===distLeft?pin.x=bounds.minX:minDist===distRight?pin.x=bounds.maxX:minDist===distBottom?pin.y=bounds.minY:pin.y=bounds.maxY,pin._facingDirection=void 0}}},expandChipsToFitPins=problem=>{for(let chip of problem.chips){let halfWidth=chip.width/2,halfHeight=chip.height/2,maxDx=0,maxDy=0;for(let pin of chip.pins){let dx3=Math.abs(pin.x-chip.center.x),dy3=Math.abs(pin.y-chip.center.y);dx3>maxDx&&(maxDx=dx3),dy3>maxDy&&(maxDy=dy3)}let newHalfWidth=Math.max(halfWidth,maxDx),newHalfHeight=Math.max(halfHeight,maxDy);if(newHalfWidth>halfWidth||newHalfHeight>halfHeight){chip.width=newHalfWidth*2,chip.height=newHalfHeight*2;for(let pin of chip.pins)pin._facingDirection=void 0}}};function doesTraceOverlapWithExistingTraces(newTracePath,existingTraces){for(let i6=0;i6<newTracePath.length-1;i6++){let newSegmentP1=newTracePath[i6],newSegmentP2=newTracePath[i6+1];for(let existingTrace of existingTraces)for(let j6=0;j6<existingTrace.tracePath.length-1;j6++){let existingSegmentP1=existingTrace.tracePath[j6],existingSegmentP2=existingTrace.tracePath[j6+1];if(doSegmentsIntersect(newSegmentP1,newSegmentP2,existingSegmentP1,existingSegmentP2))return!0}}return!1}var NEAREST_NEIGHBOR_COUNT=3,distance32=(p12,p22)=>Math.sqrt(Math.pow(p12.x-p22.x,2)+Math.pow(p12.y-p22.y,2)),manhattanDistance=(p12,p22)=>Math.abs(p12.x-p22.x)+Math.abs(p12.y-p22.y),EPS6=1e-9,between=(value,first,second)=>value>=Math.min(first,second)-EPS6&&value<=Math.max(first,second)+EPS6,getAxisAlignedIntersection=(firstStart,firstEnd,secondStart,secondEnd)=>{let firstIsHorizontal=Math.abs(firstStart.y-firstEnd.y)<=EPS6,firstIsVertical=Math.abs(firstStart.x-firstEnd.x)<=EPS6,secondIsHorizontal=Math.abs(secondStart.y-secondEnd.y)<=EPS6,secondIsVertical=Math.abs(secondStart.x-secondEnd.x)<=EPS6;if(firstIsHorizontal&&secondIsVertical){let point6={x:secondStart.x,y:firstStart.y};return between(point6.x,firstStart.x,firstEnd.x)&&between(point6.y,secondStart.y,secondEnd.y)?point6:null}if(firstIsVertical&&secondIsHorizontal){let point6={x:firstStart.x,y:secondStart.y};return between(point6.y,firstStart.y,firstEnd.y)&&between(point6.x,secondStart.x,secondEnd.x)?point6:null}if(firstIsHorizontal&&secondIsHorizontal&&Math.abs(firstStart.y-secondStart.y)<=EPS6){let overlapMin=Math.max(Math.min(firstStart.x,firstEnd.x),Math.min(secondStart.x,secondEnd.x)),overlapMax=Math.min(Math.max(firstStart.x,firstEnd.x),Math.max(secondStart.x,secondEnd.x));return overlapMin>overlapMax+EPS6?null:{x:Math.max(overlapMin,Math.min(firstStart.x,overlapMax)),y:firstStart.y}}if(firstIsVertical&&secondIsVertical&&Math.abs(firstStart.x-secondStart.x)<=EPS6){let overlapMin=Math.max(Math.min(firstStart.y,firstEnd.y),Math.min(secondStart.y,secondEnd.y)),overlapMax=Math.min(Math.max(firstStart.y,firstEnd.y),Math.max(secondStart.y,secondEnd.y));return overlapMin>overlapMax+EPS6?null:{x:firstStart.x,y:Math.max(overlapMin,Math.min(firstStart.y,overlapMax))}}return null},clipPathAtFirstIntersection=(tracePath,existingTraces)=>{for(let pathIndex=0;pathIndex<tracePath.length-1;pathIndex++){let pathStart=tracePath[pathIndex],pathEnd=tracePath[pathIndex+1],intersections=existingTraces.flatMap(trace=>trace.tracePath.slice(0,-1).flatMap((traceStart,traceIndex)=>{let intersection2=getAxisAlignedIntersection(pathStart,pathEnd,traceStart,trace.tracePath[traceIndex+1]);return intersection2?[intersection2]:[]}));intersections.sort((first,second)=>distance32(pathStart,first)-distance32(pathStart,second));let intersection=intersections[0];if(!intersection)continue;let clippedPath=tracePath.slice(0,pathIndex+1);return distance32(clippedPath.at(-1),intersection)>EPS6&&clippedPath.push(intersection),clippedPath}return null},LongDistancePairSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"params");__publicField(this,"solvedLongDistanceTraces",[]);__publicField(this,"queuedCandidatePairs",[]);__publicField(this,"currentCandidatePair",null);__publicField(this,"queuedFailedConnectionPairs",[]);__publicField(this,"currentFailedConnectionPair",null);__publicField(this,"subSolver",null);__publicField(this,"chipMap",{});__publicField(this,"inputProblem");__publicField(this,"netConnMap");__publicField(this,"newlyConnectedPinIds",new Set);__publicField(this,"allSolvedTraces",[]);__publicField(this,"maxMspPairDistance");this.params=params;let{inputProblem,primaryMspConnectionPairs,alreadySolvedTraces}=this.params;this.inputProblem=inputProblem,this.allSolvedTraces=[...alreadySolvedTraces],this.maxMspPairDistance=inputProblem.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE;let primaryConnectedPinIds=new Set;for(let pair of primaryMspConnectionPairs)primaryConnectedPinIds.add(pair.pins[0].pinId),primaryConnectedPinIds.add(pair.pins[1].pinId);let{netConnMap}=getConnectivityMapsFromInputProblem(inputProblem);this.netConnMap=netConnMap;let pinMap=new Map;for(let chip of inputProblem.chips){this.chipMap[chip.chipId]=chip;for(let pin of chip.pins)pinMap.set(pin.pinId,{...pin,chipId:chip.chipId})}this.queuedFailedConnectionPairs=this.params.failedConnectionPairs.filter(connectionPair=>isLabeledPeripheralConnection({inputProblem:this.inputProblem,chipMap:this.chipMap,pins:connectionPair.pins}));let candidatePairs=[],addedPairKeys=new Set;for(let netId of Object.keys(netConnMap.netMap)){let allPinIdsInNet=netConnMap.getIdsConnectedToNet(netId);if(allPinIdsInNet.length<2)continue;let unconnectedPinIds=allPinIdsInNet.filter(pinId=>!primaryConnectedPinIds.has(pinId));for(let unconnectedPinId of unconnectedPinIds){let sourcePin=pinMap.get(unconnectedPinId);if(!sourcePin)continue;let neighbors=allPinIdsInNet.filter(otherPinId=>otherPinId!==unconnectedPinId).flatMap(otherPinId=>{let targetPin=pinMap.get(otherPinId);return targetPin?inputProblem.netConnections.some(connection=>connection.pinIds.length===2&&connection.pinIds.includes(sourcePin.pinId)&&connection.pinIds.includes(targetPin.pinId))&&manhattanDistance(sourcePin,targetPin)>this.maxMspPairDistance?[]:[{pin:targetPin,distance:distance32(sourcePin,targetPin)}]:[]}).sort((a6,b6)=>a6.distance-b6.distance).slice(0,NEAREST_NEIGHBOR_COUNT);for(let neighbor of neighbors){let pair=[sourcePin,neighbor.pin];if(arePinsInDifferentSchematicSections(inputProblem,pair[0],pair[1]))continue;let pairKey=pair.map(p3=>p3.pinId).sort().join("--");addedPairKeys.has(pairKey)||(candidatePairs.push(pair),addedPairKeys.add(pairKey))}}}this.queuedCandidatePairs=candidatePairs}getConstructorParams(){return this.params}acceptFailedConnectionPair(tracePath){let connectionPair=this.currentFailedConnectionPair;if(!connectionPair)return;let solvedTrace={...connectionPair,tracePath,mspConnectionPairIds:[connectionPair.mspPairId],pinIds:connectionPair.pins.map(pin=>pin.pinId)};this.solvedLongDistanceTraces.push(solvedTrace),this.allSolvedTraces.push(solvedTrace);for(let pin of connectionPair.pins)this.newlyConnectedPinIds.add(pin.pinId)}_step(){if(this.subSolver?.solved&&this.currentFailedConnectionPair){let tracePath=this.subSolver.solvedTracePath;tracePath&&this.acceptFailedConnectionPair(tracePath),this.subSolver=null,this.currentCandidatePair=null,this.currentFailedConnectionPair=null}else if(this.subSolver?.solved){let newTracePath=this.subSolver.solvedTracePath;if(newTracePath&&this.currentCandidatePair){let[p12,p22]=this.currentCandidatePair,globalConnNetId=this.netConnMap.getNetConnectedToId(p12.pinId),sameNetTraces=this.allSolvedTraces.filter(trace=>trace.globalConnNetId===globalConnNetId),inputNetConnection=this.inputProblem.netConnections.find(connection=>connection.pinIds.length===3&&connection.pinIds.includes(p12.pinId)&&connection.pinIds.includes(p22.pinId)),sourceChip=this.chipMap[p12.chipId],targetRailTrace=sameNetTraces.find(trace=>trace.pinIds.includes(p22.pinId)&&trace.pins.every(pin=>pin.chipId===p22.chipId)),junctionTracePath=inputNetConnection!==void 0&&sourceChip?.pins.length===2&&targetRailTrace!==void 0?clipPathAtFirstIntersection(newTracePath,sameNetTraces):null,acceptedTracePath=junctionTracePath??newTracePath,tracesToCheck=junctionTracePath?this.allSolvedTraces.filter(trace=>trace.globalConnNetId!==globalConnNetId):this.allSolvedTraces;if(!doesTraceOverlapWithExistingTraces(acceptedTracePath,tracesToCheck)){let mspPairId=`${p12.pinId}-${p22.pinId}`,newSolvedTrace={mspPairId,dcConnNetId:globalConnNetId,globalConnNetId,pins:[p12,p22],tracePath:acceptedTracePath,mspConnectionPairIds:[mspPairId],pinIds:[p12.pinId,p22.pinId]};this.solvedLongDistanceTraces.push(newSolvedTrace),this.allSolvedTraces.push(newSolvedTrace),this.newlyConnectedPinIds.add(p12.pinId),this.newlyConnectedPinIds.add(p22.pinId)}}this.subSolver=null,this.currentCandidatePair=null}else this.subSolver?.failed&&(this.subSolver=null,this.currentCandidatePair=null,this.currentFailedConnectionPair=null);if(this.subSolver){this.subSolver.step();return}let failedConnectionPair=this.queuedFailedConnectionPairs.shift();if(failedConnectionPair){this.currentFailedConnectionPair=failedConnectionPair,this.currentCandidatePair=failedConnectionPair.pins,this.subSolver=new SchematicTraceSingleLineSolver2({inputProblem:this.params.inputProblem,pins:failedConnectionPair.pins,chipMap:this.chipMap});return}for(;this.queuedCandidatePairs.length>0;){let nextPair=this.queuedCandidatePairs.shift(),[p12,p22]=nextPair;if(!(this.newlyConnectedPinIds.has(p12.pinId)||this.newlyConnectedPinIds.has(p22.pinId))){this.currentCandidatePair=nextPair,this.subSolver=new SchematicTraceSingleLineSolver2({inputProblem:this.params.inputProblem,pins:this.currentCandidatePair,chipMap:this.chipMap});return}}this.solved=!0}visualize(){if(this.subSolver)return this.subSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);for(let trace of this.solvedLongDistanceTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let[p12,p22]of this.queuedCandidatePairs)graphics.lines.push({points:[p12,p22],strokeColor:"gray",strokeDash:"4 4"});return graphics}getOutput(){return this.solved?{newTraces:this.solvedLongDistanceTraces,allTracesMerged:[...this.params.alreadySolvedTraces,...this.solvedLongDistanceTraces]}:{newTraces:[],allTracesMerged:this.params.alreadySolvedTraces}}},hasCollisions=(pathSegments,obstacles)=>{for(let i6=0;i6<pathSegments.length-1;i6++){let p12=pathSegments[i6],p22=pathSegments[i6+1];for(let obstacle of obstacles){let box2={center:{x:obstacle.minX+(obstacle.maxX-obstacle.minX)/2,y:obstacle.minY+(obstacle.maxY-obstacle.minY)/2},width:obstacle.maxX-obstacle.minX,height:obstacle.maxY-obstacle.minY};if(segmentToBoxMinDistance(p12,p22,box2)<=0)return!0}}return!1},countTurns=points=>{let turns=0;for(let i6=1;i6<points.length-1;i6++){let prev=points[i6-1],curr=points[i6],next2=points[i6+1],prevVertical=prev.x===curr.x,nextVertical=curr.x===next2.x;prevVertical!==nextVertical&&turns++}return turns},tryConnectPoints=(start,end)=>{let candidates=[];return start.x===end.x||start.y===end.y?candidates.push([start,end]):(candidates.push([start,{x:end.x,y:start.y},end]),candidates.push([start,{x:start.x,y:end.y},end])),candidates},hasCollisionsWithLabels=(pathSegments,labels)=>{for(let i6=0;i6<pathSegments.length-1;i6++){let p12=pathSegments[i6],p22=pathSegments[i6+1];for(let label of labels)if(segmentIntersectsRect(p12,p22,label))return!0}return!1},recognizeStairStepPattern=(pathToCheck,startIdx)=>{if(startIdx>=pathToCheck.length-3)return-1;let endIdx=startIdx,isStairStep=!0;for(let i6=startIdx;i6<pathToCheck.length-2&&i6<startIdx+10&&!(i6+2>=pathToCheck.length);i6++){let p12=pathToCheck[i6],p22=pathToCheck[i6+1],p3=pathToCheck[i6+2],seg1Vertical=p12.x===p22.x,seg2Vertical=p22.x===p3.x;if(seg1Vertical===seg2Vertical)break;let seg1Direction=Math.sign(seg1Vertical?p22.y-p12.y:p22.x-p12.x);if(i6>startIdx){let prevP=pathToCheck[i6-1],prevSegVertical=prevP.x===p12.x,prevDirection=Math.sign(prevSegVertical?p12.y-prevP.y:p12.x-prevP.x);if(seg1Vertical&&prevSegVertical&&seg1Direction!==prevDirection||!seg1Vertical&&!prevSegVertical&&seg1Direction!==prevDirection){isStairStep=!1;break}}endIdx=i6+2}return isStairStep&&endIdx-startIdx>=3?endIdx:-1},isSegmentAnEndpointSegment=(p12,p22,originalPath)=>{if(originalPath.length<2)return!1;let originalStart=originalPath[0],originalEnd=originalPath[originalPath.length-1];return p12.x===originalStart.x&&p12.y===originalStart.y&&p22.x===originalPath[1].x&&p22.y===originalPath[1].y||p12.x===originalPath[originalPath.length-2].x&&p12.y===originalPath[originalPath.length-2].y&&p22.x===originalEnd.x&&p22.y===originalEnd.y},minimizeTurns=({path,obstacles,labelBounds,originalPath})=>{if(path.length<=2)return path;let optimizedPath=[...path],currentTurns=countTurns(optimizedPath),improved=!0;for(;improved;){improved=!1;for(let startIdx=0;startIdx<optimizedPath.length-3;startIdx++){let stairEndIdx=recognizeStairStepPattern(optimizedPath,startIdx);if(stairEndIdx>0){if(isSegmentAnEndpointSegment(optimizedPath[startIdx],optimizedPath[startIdx+1],originalPath)||isSegmentAnEndpointSegment(optimizedPath[stairEndIdx-1],optimizedPath[stairEndIdx],originalPath))continue;let startPoint=optimizedPath[startIdx],endPoint=optimizedPath[stairEndIdx],connectionOptions=tryConnectPoints(startPoint,endPoint);for(let connection of connectionOptions){let testPath=[...optimizedPath.slice(0,startIdx+1),...connection.slice(1,-1),...optimizedPath.slice(stairEndIdx)],collidesWithObstacles=hasCollisions(connection,obstacles),collidesWithLabels=hasCollisionsWithLabels(connection,labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){let newTurns=countTurns(testPath);optimizedPath=testPath,currentTurns=newTurns,improved=!0;break}}if(improved)break}}if(!improved)for(let startIdx=0;startIdx<optimizedPath.length-2;startIdx++){let maxRemove=Math.min(optimizedPath.length-startIdx-2,optimizedPath.length-2);for(let removeCount=1;removeCount<=maxRemove;removeCount++){let endIdx=startIdx+removeCount+1;if(endIdx>=optimizedPath.length||isSegmentAnEndpointSegment(optimizedPath[startIdx],optimizedPath[startIdx+1],originalPath)||isSegmentAnEndpointSegment(optimizedPath[endIdx-1],optimizedPath[endIdx],originalPath))continue;let startPoint=optimizedPath[startIdx],endPoint=optimizedPath[endIdx],connectionOptions=tryConnectPoints(startPoint,endPoint);for(let connection of connectionOptions){let testPath=[...optimizedPath.slice(0,startIdx+1),...connection.slice(1,-1),...optimizedPath.slice(endIdx)],connectionSegments=connection,collidesWithObstacles=hasCollisions(connectionSegments,obstacles),collidesWithLabels=hasCollisionsWithLabels(connectionSegments,labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){let newTurns=countTurns(testPath);if(newTurns<currentTurns||newTurns===currentTurns&&testPath.length<optimizedPath.length){optimizedPath=testPath,currentTurns=newTurns,improved=!0;break}}}if(improved)break}if(improved)break}if(!improved)for(let i6=0;i6<optimizedPath.length-2;i6++){let p12=optimizedPath[i6],p22=optimizedPath[i6+1],p3=optimizedPath[i6+2];if(isSegmentAnEndpointSegment(p12,p22,originalPath)||isSegmentAnEndpointSegment(p22,p3,originalPath))continue;let allVertical=p12.x===p22.x&&p22.x===p3.x,allHorizontal=p12.y===p22.y&&p22.y===p3.y;if(allVertical||allHorizontal){let testPath=[...optimizedPath.slice(0,i6+1),...optimizedPath.slice(i6+2)],collidesWithObstacles=hasCollisions([p12,p3],obstacles),collidesWithLabels=hasCollisionsWithLabels([p12,p3],labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){optimizedPath=testPath,improved=!0;break}}}}return simplifyPath(optimizedPath)},RAIL_ALIGNMENT_EPSILON=.002,nearlyEqual=(a6,b6)=>Math.abs(a6-b6)<RAIL_ALIGNMENT_EPSILON,isHorizontal2=(a6,b6)=>nearlyEqual(a6.y,b6.y),isVertical2=(a6,b6)=>nearlyEqual(a6.x,b6.x),isPositiveLength=(a6,b6)=>Math.abs(a6.x-b6.x)>=RAIL_ALIGNMENT_EPSILON||Math.abs(a6.y-b6.y)>=RAIL_ALIGNMENT_EPSILON,getRailOrientation=(a6,b6)=>isPositiveLength(a6,b6)?isVertical2(a6,b6)?"vertical":isHorizontal2(a6,b6)?"horizontal":null:null,rangesTouchOrOverlap=(a6,b6)=>Math.min(a6.maxAlong,b6.maxAlong)-Math.max(a6.minAlong,b6.minAlong)>=-RAIL_ALIGNMENT_EPSILON,pointsEqual2=(a6,b6)=>nearlyEqual(a6.x,b6.x)&&nearlyEqual(a6.y,b6.y),getDistinctCoordinates=coordinates=>{let distinct=[];for(let coordinate of coordinates)distinct.some(item=>nearlyEqual(item,coordinate))||distinct.push(coordinate);return distinct},getMergedIntervalMetrics=intervals=>{let groups=[];for(let interval of intervals){let group=groups.find(items=>nearlyEqual(items[0].coordinate,interval.coordinate));group?group.push(interval):groups.push([interval])}return groups.reduce((total,group)=>{let sorted=[...group].sort((a6,b6)=>a6.min-b6.min),groupLength=0,segmentCount=1,currentMin=sorted[0].min,currentMax=sorted[0].max;for(let interval of sorted.slice(1))interval.min<=currentMax+RAIL_ALIGNMENT_EPSILON?currentMax=Math.max(currentMax,interval.max):(groupLength+=currentMax-currentMin,segmentCount++,currentMin=interval.min,currentMax=interval.max);return{length:total.length+groupLength+currentMax-currentMin,segmentCount:total.segmentCount+segmentCount}},{length:0,segmentCount:0})},getVisibleTraceMetrics=traces=>{let horizontal=[],vertical=[];for(let trace of traces)for(let index=0;index<trace.tracePath.length-1;index++){let start=trace.tracePath[index],end=trace.tracePath[index+1];isHorizontal2(start,end)?horizontal.push({coordinate:start.y,min:Math.min(start.x,end.x),max:Math.max(start.x,end.x)}):isVertical2(start,end)&&vertical.push({coordinate:start.x,min:Math.min(start.y,end.y),max:Math.max(start.y,end.y)})}let horizontalMetrics=getMergedIntervalMetrics(horizontal),verticalMetrics=getMergedIntervalMetrics(vertical);return{length:horizontalMetrics.length+verticalMetrics.length,segmentCount:horizontalMetrics.segmentCount+verticalMetrics.segmentCount}},getVisibleTraceLength=traces=>getVisibleTraceMetrics(traces).length,getVisibleTraceSegmentCount=traces=>getVisibleTraceMetrics(traces).segmentCount,MIN_EXCESSIVE_DETOUR_LENGTH_RATIO=2.5,getTracePathLength=tracePath=>{let pathLength4=0;for(let pointIndex=1;pointIndex<tracePath.length;pointIndex++){let previousPoint=tracePath[pointIndex-1],point6=tracePath[pointIndex];pathLength4+=Math.abs(point6.x-previousPoint.x)+Math.abs(point6.y-previousPoint.y)}return pathLength4},shortenExcessiveLabelPaddingDetour=({inputProblem,trace})=>{let exactConnection=inputProblem.directConnections.find(connection=>connection.pinIds.every(pinId=>trace.pinIds.includes(pinId)));if(!exactConnection)return trace;let chipMap={};for(let chip of inputProblem.chips)chipMap[chip.chipId]=chip;let candidateSolver=new SchematicTraceSingleLineSolver2({pins:trace.pins,connectionPair:trace,inputProblem:{...inputProblem,directConnections:[exactConnection,...inputProblem.directConnections.filter(connection=>connection!==exactConnection)]},chipMap});if(candidateSolver.solve(),!candidateSolver.solvedTracePath)return trace;let currentLength=getTracePathLength(trace.tracePath),candidateLength=getTracePathLength(candidateSolver.solvedTracePath);return currentLength<=candidateLength*MIN_EXCESSIVE_DETOUR_LENGTH_RATIO?trace:{...trace,tracePath:candidateSolver.solvedTracePath}},minimizeTurnsWithFilteredLabels=({targetMspConnectionPairId,traces,inputProblem,allLabelPlacements,mergedLabelNetIdMap,paddingBuffer})=>{let originalTargetTrace=traces.find(t53=>t53.mspPairId===targetMspConnectionPairId);if(!originalTargetTrace)throw new Error(`Target trace ${targetMspConnectionPairId} not found`);let targetTrace=shortenExcessiveLabelPaddingDetour({inputProblem,trace:originalTargetTrace}),targetPinIds=new Set(targetTrace.pinIds),otherTraces=traces.filter(trace=>trace.mspPairId!==targetMspConnectionPairId),relaxedObstacleTraces=otherTraces.filter(trace=>{let sharesEndpoint=trace.pinIds.some(pinId=>targetPinIds.has(pinId));return trace.globalConnNetId!==targetTrace.globalConnNetId||!sharesEndpoint}),TRACE_WIDTH=.01,getTraceObstacles2=obstacleTraces=>obstacleTraces.flatMap((trace,i6)=>trace.tracePath.slice(0,-1).map((p12,pi3)=>{let p22=trace.tracePath[pi3+1];return{chipId:`trace-obstacle-${i6}-${pi3}`,minX:Math.min(p12.x,p22.x)-TRACE_WIDTH/2,minY:Math.min(p12.y,p22.y)-TRACE_WIDTH/2,maxX:Math.max(p12.x,p22.x)+TRACE_WIDTH/2,maxY:Math.max(p12.y,p22.y)+TRACE_WIDTH/2}})),staticObstaclesRaw=getObstacleRects(inputProblem),PADDING=.01,staticObstacles=staticObstaclesRaw.map(obs=>({...obs,minX:obs.minX-PADDING,minY:obs.minY-PADDING,maxX:obs.maxX+PADDING,maxY:obs.maxY+PADDING})),originalPath=targetTrace.tracePath,labelBounds=allLabelPlacements.filter(label=>{let originalNetIds=mergedLabelNetIdMap[label.globalConnNetId];return originalNetIds?!originalNetIds.has(targetTrace.globalConnNetId):label.globalConnNetId!==targetTrace.globalConnNetId}).map(nl3=>({minX:nl3.center.x-nl3.width/2-paddingBuffer,maxX:nl3.center.x+nl3.width/2+paddingBuffer,minY:nl3.center.y-nl3.height/2-paddingBuffer,maxY:nl3.center.y+nl3.height/2+paddingBuffer})),strictPath=minimizeTurns({path:originalPath,obstacles:[...staticObstacles,...getTraceObstacles2(otherTraces)],labelBounds,originalPath}),relaxedPath=minimizeTurns({path:originalPath,obstacles:[...staticObstacles,...getTraceObstacles2(relaxedObstacleTraces)],labelBounds,originalPath}),sameNetTraces=otherTraces.filter(trace=>trace.globalConnNetId===targetTrace.globalConnNetId),getSameNetReadability=tracePath=>{let tracesWithCandidate=[...sameNetTraces,{...targetTrace,tracePath}];return{segmentCount:getVisibleTraceSegmentCount(tracesWithCandidate),visibleLength:getVisibleTraceLength(tracesWithCandidate)}},strictTurns=countTurns(strictPath),relaxedTurns=countTurns(relaxedPath),newPath=strictPath;if(relaxedTurns<strictTurns)newPath=relaxedPath;else if(relaxedTurns===strictTurns){let strictReadability=getSameNetReadability(strictPath),relaxedReadability=getSameNetReadability(relaxedPath);(relaxedReadability.segmentCount<strictReadability.segmentCount||relaxedReadability.segmentCount===strictReadability.segmentCount&&relaxedReadability.visibleLength<strictReadability.visibleLength-RAIL_ALIGNMENT_EPSILON)&&(newPath=relaxedPath)}return{...targetTrace,tracePath:newPath}},balanceZShapes=({targetMspConnectionPairId,traces,inputProblem,allLabelPlacements,mergedLabelNetIdMap,paddingBuffer})=>{let targetTrace=traces.find(t53=>t53.mspPairId===targetMspConnectionPairId);if(!targetTrace)throw new Error(`Target trace ${targetMspConnectionPairId} not found`);let TOLERANCE2=1e-5,coordsEqual=(a6,b6)=>Math.abs(a6-b6)<TOLERANCE2,obstacleTraces=traces.filter(t53=>t53.mspPairId!==targetMspConnectionPairId),TRACE_WIDTH=.01,traceObstacles=obstacleTraces.flatMap((trace,i6)=>trace.tracePath.slice(0,-1).map((p12,pi3)=>{let p22=trace.tracePath[pi3+1];return{chipId:`trace-obstacle-${i6}-${pi3}`,minX:Math.min(p12.x,p22.x)-TRACE_WIDTH/2,minY:Math.min(p12.y,p22.y)-TRACE_WIDTH/2,maxX:Math.max(p12.x,p22.x)+TRACE_WIDTH/2,maxY:Math.max(p12.y,p22.y)+TRACE_WIDTH/2}})),combinedObstacles=[...getObstacleRects(inputProblem).map(obs=>({...obs,minX:obs.minX+TOLERANCE2,maxX:obs.maxX-TOLERANCE2,minY:obs.minY+TOLERANCE2,maxY:obs.maxY-TOLERANCE2})),...traceObstacles],segmentIntersectsAnyRect=(p12,p22,rects)=>{for(let rect of rects)if(segmentIntersectsRect(p12,p22,rect))return!0;return!1},labelBounds=allLabelPlacements.filter(label=>{let originalNetIds=mergedLabelNetIdMap[label.globalConnNetId];return originalNetIds?!originalNetIds.has(targetTrace.globalConnNetId):label.globalConnNetId!==targetTrace.globalConnNetId}).map(nl3=>({minX:nl3.center.x-nl3.width/2+TOLERANCE2,maxX:nl3.center.x+nl3.width/2-TOLERANCE2,minY:nl3.center.y-nl3.height/2+TOLERANCE2,maxY:nl3.center.y+nl3.height/2-TOLERANCE2})),newPath=[...targetTrace.tracePath];if(newPath.length<4)return{...targetTrace};if(newPath.length===4){let[p03,p12,p22,p3]=newPath,p1New,p2New;if(coordsEqual(p03.y,p12.y)&&coordsEqual(p12.x,p22.x)&&coordsEqual(p22.y,p3.y)){let idealX=(p03.x+p3.x)/2;p1New={x:idealX,y:p12.y},p2New={x:idealX,y:p22.y}}else{let idealY=(p03.y+p3.y)/2;p1New={x:p12.x,y:idealY},p2New={x:p22.x,y:idealY}}return segmentIntersectsAnyRect(p03,p1New,combinedObstacles)||segmentIntersectsAnyRect(p1New,p2New,combinedObstacles)||segmentIntersectsAnyRect(p2New,p3,combinedObstacles)||segmentIntersectsAnyRect(p03,p1New,labelBounds)||segmentIntersectsAnyRect(p1New,p2New,labelBounds)||segmentIntersectsAnyRect(p2New,p3,labelBounds)||(newPath[1]=p1New,newPath[2]=p2New),{...targetTrace,tracePath:simplifyPath(newPath)}}for(let i6=1;i6<newPath.length-4;i6++){let p12=newPath[i6],p22=newPath[i6+1],p3=newPath[i6+2],p42=newPath[i6+3],isHVHZShape=coordsEqual(p12.y,p22.y)&&coordsEqual(p22.x,p3.x)&&coordsEqual(p3.y,p42.y),isVHVZShape=coordsEqual(p12.x,p22.x)&&coordsEqual(p22.y,p3.y)&&coordsEqual(p3.x,p42.x),isCollinearHorizontal=coordsEqual(p12.y,p22.y)&&coordsEqual(p22.y,p3.y)&&coordsEqual(p3.y,p42.y),isCollinearVertical=coordsEqual(p12.x,p22.x)&&coordsEqual(p22.x,p3.x)&&coordsEqual(p3.x,p42.x),isCollinear2=isCollinearHorizontal||isCollinearVertical,isSameDirection=!1;if(isHVHZShape?isSameDirection=Math.sign(p22.x-p12.x)===Math.sign(p42.x-p3.x):isVHVZShape&&(isSameDirection=Math.sign(p22.y-p12.y)===Math.sign(p42.y-p3.y)),!((isHVHZShape||isVHVZShape)&&!isCollinear2&&isSameDirection))continue;let p2New,p3New,len1Original=Math.abs(isHVHZShape?p12.x-p22.x:p12.y-p22.y),len2Original=Math.abs(isHVHZShape?p3.x-p42.x:p3.y-p42.y);if(Math.abs(len1Original-len2Original)<.001)continue;if(isHVHZShape){let idealX=(p12.x+p42.x)/2;p2New={x:idealX,y:p22.y},p3New={x:idealX,y:p3.y}}else{let idealY=(p12.y+p42.y)/2;p2New={x:p22.x,y:idealY},p3New={x:p3.x,y:idealY}}segmentIntersectsAnyRect(p12,p2New,combinedObstacles)||segmentIntersectsAnyRect(p2New,p3New,combinedObstacles)||segmentIntersectsAnyRect(p3New,p42,combinedObstacles)||segmentIntersectsAnyRect(p12,p2New,labelBounds)||segmentIntersectsAnyRect(p2New,p3New,labelBounds)||segmentIntersectsAnyRect(p3New,p42,labelBounds)||(newPath[i6+1]=p2New,newPath[i6+2]=p3New,i6=0)}let finalSimplifiedPath=simplifyPath(newPath);return{...targetTrace,tracePath:finalSimplifiedPath}},getAlongBounds=(orientation4,minAlong,maxAlong)=>orientation4==="vertical"?{minX:0,maxX:0,minY:minAlong,maxY:maxAlong}:{minX:minAlong,maxX:maxAlong,minY:0,maxY:0},hasPositiveAlongOverlap=(orientation4,first,second)=>{let overlap=boundsIntersection(first,second);return overlap?(orientation4==="vertical"?overlap.maxY-overlap.minY:overlap.maxX-overlap.minX)>RAIL_ALIGNMENT_EPSILON:!1},getRailAlignmentFallbackCoordinates=({group,originalCoordinates,otherNetTraces})=>{let orientation4=group[0].orientation,groupAlongBounds=group.map(segment2=>getAlongBounds(orientation4,segment2.minAlong,segment2.maxAlong)),fallbackClearance=SCHEMATIC_TRACE_MIN_VISUAL_CENTERLINE_CLEARANCE,coordinates=[];for(let trace of otherNetTraces)for(let index=0;index<trace.tracePath.length-1;index++){let start=trace.tracePath[index],end=trace.tracePath[index+1];if(getRailOrientation(start,end)!==orientation4)continue;let minAlong=orientation4==="vertical"?Math.min(start.y,end.y):Math.min(start.x,end.x),maxAlong=orientation4==="vertical"?Math.max(start.y,end.y):Math.max(start.x,end.x),traceAlongBounds=getAlongBounds(orientation4,minAlong,maxAlong);if(!groupAlongBounds.some(bounds=>hasPositiveAlongOverlap(orientation4,bounds,traceAlongBounds)))continue;let coordinate=orientation4==="vertical"?start.x:start.y;originalCoordinates.some(originalCoordinate=>Math.abs(originalCoordinate-coordinate)<=SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE)&&coordinates.push(coordinate-fallbackClearance,coordinate+fallbackClearance)}return getDistinctCoordinates(coordinates)},EPS7=1e-6,isTraceLine=trace=>getUniquePinCount(trace.pinIds)>=2,rectsOverlap=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>EPS7&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>EPS7,getTraceCorners=path=>{let corners=[];for(let i6=1;i6<path.length-1;i6++){let previousPoint=path[i6-1],cornerPoint=path[i6],nextPoint=path[i6+1];isTraceCorner(previousPoint,cornerPoint,nextPoint)&&corners.push(cornerPoint)}return corners},tracePathContainsPoint=(path,point6)=>{for(let i6=0;i6<path.length-1;i6++)if(isPointOnSegment4(point6,path[i6],path[i6+1]))return!0;return!1},getDistance=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),getUniquePinCount=pinIds=>new Set(pinIds).size,isTraceCorner=(a6,b6,c3)=>getSegmentOrientation(a6,b6)!==getSegmentOrientation(b6,c3),isPointOnSegment4=(point6,start,end)=>getSegmentOrientation(start,end)==="horizontal"?Math.abs(point6.y-start.y)<=EPS7&&point6.x>=Math.min(start.x,end.x)-EPS7&&point6.x<=Math.max(start.x,end.x)+EPS7:Math.abs(point6.x-start.x)<=EPS7&&point6.y>=Math.min(start.y,end.y)-EPS7&&point6.y<=Math.max(start.y,end.y)+EPS7,getSegmentOrientation=(a6,b6)=>Math.abs(a6.y-b6.y)<=EPS7?"horizontal":"vertical",getTransitivelyConnectedTraceIds=(group,traces)=>{let groupNetId=group[0].globalConnNetId,sameNetTraces=traces.filter(trace=>trace.globalConnNetId===groupNetId),connectedTraceIds=new Set(group.map(segment2=>segment2.traceId)),connectedPinIds=new Set(sameNetTraces.filter(trace=>connectedTraceIds.has(trace.mspPairId)).flatMap(trace=>trace.pinIds));for(let changed=!0;changed;){changed=!1;for(let trace of sameNetTraces)if(!connectedTraceIds.has(trace.mspPairId)&&trace.pinIds.some(pinId=>connectedPinIds.has(pinId))){connectedTraceIds.add(trace.mspPairId);for(let pinId of trace.pinIds)connectedPinIds.add(pinId);changed=!0}}return connectedTraceIds},getLabelsLinkedToRailGroup=(group,netLabelPlacements,traces)=>{let traceIds=getTransitivelyConnectedTraceIds(group,traces);return netLabelPlacements.filter(label=>label.mspConnectionPairIds.some(traceId=>traceIds.has(traceId)))},getFixedLabelCoordinate=(group,netLabelPlacements,traces)=>{let traceMap=new Map(traces.map(trace=>[trace.mspPairId,trace]));if(![...new Set(group.map(segment2=>segment2.traceId))].every(traceId=>traceMap.get(traceId)?.tracePath.length===4))return null;let orientation4=group[0].orientation,anchoringLabels=getLabelsLinkedToRailGroup(group,netLabelPlacements,traces).filter(label=>label.orientation===group[0].componentFacingDirection&&label.mspConnectionPairIds.some(traceId=>{let trace=traceMap.get(traceId);return trace&&tracePathContainsPoint(trace.tracePath,label.anchorPoint)})),coordinates=getDistinctCoordinates(anchoringLabels.map(label=>orientation4==="vertical"?label.anchorPoint.x:label.anchorPoint.y));if(coordinates.length!==1)return null;let labelCoordinate=coordinates[0],coordinate=group.find(segment2=>Math.abs(segment2.coordinate-labelCoordinate)<=RAIL_ALIGNMENT_EPSILON)?.coordinate??labelCoordinate;return anchoringLabels.some(label=>label.mspConnectionPairIds.some(traceId=>(traceMap.get(traceId)?.tracePath.length??0)>4))||group.every(segment2=>{let trace=traceMap.get(segment2.traceId);return trace?Math.abs(segment2.coordinate-coordinate)<=distance2(trace.pins[0],trace.pins[1])+RAIL_ALIGNMENT_EPSILON:!1})?coordinate:null},moveRailSegments=(trace,segments,coordinate)=>{let pointsToMove=new Set;for(let segment2 of segments)nearlyEqual(segment2.coordinate,coordinate)||(pointsToMove.add(segment2.segmentIndex),pointsToMove.add(segment2.segmentIndex+1));let orientation4=segments[0].orientation,tracePath=simplifyPath(trace.tracePath.map((point6,index)=>pointsToMove.has(index)?orientation4==="vertical"?{...point6,x:coordinate}:{...point6,y:coordinate}:point6));return{...trace,tracePath}},getAnchoredTraceIds=(label,traces)=>new Set(traces.filter(trace=>trace.globalConnNetId===label.globalConnNetId&&tracePathContainsPoint(trace.tracePath,label.anchorPoint)).map(trace=>trace.mspPairId)),preservesLabelAnchors=(labels,before,after)=>labels.every(label=>{let anchoredBefore=getAnchoredTraceIds(label,before);if(anchoredBefore.size===0)return!0;let anchoredAfter=getAnchoredTraceIds(label,after);return[...anchoredBefore].every(traceId=>anchoredAfter.has(traceId))}),EPS8=1e-9,segmentRunsAlongRectBoundary=(start,end,rect)=>{let isVertical52=Math.abs(start.x-end.x)<EPS8,isHorizontal42=Math.abs(start.y-end.y)<EPS8;return isVertical52?Math.abs(start.x-rect.minX)<EPS8||Math.abs(start.x-rect.maxX)<EPS8:isHorizontal42?Math.abs(start.y-rect.minY)<EPS8||Math.abs(start.y-rect.maxY)<EPS8:!1},getPathKey=path=>path.map(point6=>`${point6.x},${point6.y}`).join(";"),getPathLength2=path=>{let length4=0;for(let i6=0;i6<path.length-1;i6++)length4+=Math.abs(path[i6+1].x-path[i6].x)+Math.abs(path[i6+1].y-path[i6].y);return length4},getDistance2=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),isAxisAlignedSegment=(start,end)=>Math.abs(start.x-end.x)<EPS8||Math.abs(start.y-end.y)<EPS8,getSegmentOrientation2=(start,end)=>Math.abs(start.y-end.y)<EPS8?"horizontal":"vertical",projectPointToSegment=(point6,start,end)=>Math.abs(start.x-end.x)<EPS8?{x:start.x,y:Math.min(Math.max(point6.y,Math.min(start.y,end.y)),Math.max(start.y,end.y))}:Math.abs(start.y-end.y)<EPS8?{x:Math.min(Math.max(point6.x,Math.min(start.x,end.x)),Math.max(start.x,end.x)),y:start.y}:start,getPointToSegmentDistance=(point6,start,end)=>getDistance2(point6,projectPointToSegment(point6,start,end)),getSegments=path=>{let segments=[];for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];isAxisAlignedSegment(start,end)&&segments.push({start,end,orientation:getSegmentOrientation2(start,end)})}return segments},findSegmentContainingPoint=(path,point6)=>{for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];if(isAxisAlignedSegment(start,end)&&!(getPointToSegmentDistance(point6,start,end)>1e-6))return{index:i6,start,end,orientation:getSegmentOrientation2(start,end)}}return null},isPointWithinSegmentPrimaryRange=(point6,segment2)=>segment2.orientation==="horizontal"?point6.x>=Math.min(segment2.start.x,segment2.end.x)-EPS8&&point6.x<=Math.max(segment2.start.x,segment2.end.x)+EPS8:point6.y>=Math.min(segment2.start.y,segment2.end.y)-EPS8&&point6.y<=Math.max(segment2.start.y,segment2.end.y)+EPS8,findPreferredReroutedSegment=(path,originalSegmentIndex,originalSegmentCount,orientation4,anchorPoint)=>{let matchingSegments=getSegments(path).filter(segment2=>segment2.orientation===orientation4);if(matchingSegments.length===0)return null;let containingSegments=matchingSegments.filter(segment2=>isPointWithinSegmentPrimaryRange(anchorPoint,segment2)),candidateSegments=containingSegments.length>0?containingSegments:matchingSegments;return originalSegmentIndex<originalSegmentCount/2?candidateSegments[0]:candidateSegments[candidateSegments.length-1]},projectPointToPath=(point6,path)=>{let bestPoint=null,bestDistance=Number.POSITIVE_INFINITY;for(let i6=0;i6<path.length-1;i6++){let projectedPoint=projectPointToSegment(point6,path[i6],path[i6+1]),distance72=getDistance2(point6,projectedPoint);distance72<bestDistance&&(bestPoint=projectedPoint,bestDistance=distance72)}return bestPoint},segmentsIntersect2=(a12,a22,b12,b22)=>{let aVertical=Math.abs(a12.x-a22.x)<EPS8,bVertical=Math.abs(b12.x-b22.x)<EPS8,between2=(value,p12,p22)=>value>=Math.min(p12,p22)-EPS8&&value<=Math.max(p12,p22)+EPS8;if(aVertical&&bVertical)return Math.abs(a12.x-b12.x)>EPS8?!1:Math.min(Math.max(a12.y,a22.y),Math.max(b12.y,b22.y))-Math.max(Math.min(a12.y,a22.y),Math.min(b12.y,b22.y))>EPS8;if(!aVertical&&!bVertical)return Math.abs(a12.y-b12.y)>EPS8?!1:Math.min(Math.max(a12.x,a22.x),Math.max(b12.x,b22.x))-Math.max(Math.min(a12.x,a22.x),Math.min(b12.x,b22.x))>EPS8;let verticalA=aVertical?a12:b12,verticalB=aVertical?a22:b22,horizontalA=aVertical?b12:a12,horizontalB=aVertical?b22:a22;return between2(verticalA.x,horizontalA.x,horizontalB.x)&&between2(horizontalA.y,verticalA.y,verticalB.y)},countPathIntersections=(pathA,pathB)=>{let count=0;for(let i6=0;i6<pathA.length-1;i6++)for(let j6=0;j6<pathB.length-1;j6++)segmentsIntersect2(pathA[i6],pathA[i6+1],pathB[j6],pathB[j6+1])&&count++;return count},isPathCollidingWithChipInterior=(path,chipObstacles)=>{for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];for(let obstacle of chipObstacles)if(segmentIntersectsRect(start,end,obstacle)&&!segmentRunsAlongRectBoundary(start,end,obstacle))return!0}return!1},countOtherNetCrossings=(traces,allTraces)=>{let crossings=0;for(let trace of traces)for(let otherTrace of allTraces)trace.globalConnNetId!==otherTrace.globalConnNetId&&(crossings+=countPathIntersections(trace.tracePath,otherTrace.tracePath));return crossings},getTraceGeometryMetrics=(traces,allTraces)=>({turnCount:traces.reduce((total,trace)=>total+countTurns(trace.tracePath),0),visibleLength:getVisibleTraceLength(traces),pathLength:traces.reduce((sum,trace)=>sum+getPathLength2(trace.tracePath),0),otherNetCrossings:countOtherNetCrossings(traces,allTraces)}),scoreIsBetter=(candidate,best)=>candidate.turnCount!==best.turnCount?candidate.turnCount<best.turnCount:nearlyEqual(candidate.visibleLength,best.visibleLength)?nearlyEqual(candidate.pathLength,best.pathLength)?candidate.otherNetCrossings!==best.otherNetCrossings?candidate.otherNetCrossings<best.otherNetCrossings:nearlyEqual(candidate.displacement,best.displacement)?candidate.coordinate<best.coordinate:candidate.displacement<best.displacement:candidate.pathLength<best.pathLength:candidate.visibleLength<best.visibleLength,isReadabilityImprovement=(candidate,baseline)=>candidate.turnCount<=baseline.turnCount&&(candidate.turnCount<baseline.turnCount||candidate.visibleLength<=baseline.visibleLength+RAIL_ALIGNMENT_EPSILON),tracePathChanged=(original,candidate)=>original.tracePath.length!==candidate.tracePath.length||candidate.tracePath.some((point6,index)=>!pointsEqual2(point6,original.tracePath[index])),evaluateRailGroup=({group,traces,netLabelPlacements,obstacles,eligibleTraceIds})=>{let groupTraceIds=new Set(group.map(segment2=>segment2.traceId)),originalGroupTraces=traces.filter(trace=>groupTraceIds.has(trace.mspPairId)),baseline=getTraceGeometryMetrics(originalGroupTraces,traces),originalCoordinates=getDistinctCoordinates(group.map(segment2=>segment2.coordinate)),fixedLabelCoordinate=getFixedLabelCoordinate(group,netLabelPlacements,traces),otherNetTraces=traces.filter(trace=>trace.globalConnNetId!==group[0].globalConnNetId),immutableSameNetTraces=traces.filter(trace=>trace.globalConnNetId===group[0].globalConnNetId&&!eligibleTraceIds.has(trace.mspPairId)),evaluateCoordinates=(coordinates,options)=>{let best=null;for(let coordinate of coordinates){let candidateMap=new Map;for(let trace of originalGroupTraces){let candidateTrace=moveRailSegments(trace,group.filter(segment2=>segment2.traceId===trace.mspPairId),coordinate);candidateMap.set(trace.mspPairId,candidateTrace)}let candidateTraces=[...candidateMap.values()],allCandidateTraces=traces.map(trace=>candidateMap.get(trace.mspPairId)??trace);if(!candidateTraces.every(candidate2=>!isPathCollidingWithObstacles(candidate2.tracePath,obstacles)&&detectTraceLabelOverlap({traces:[candidate2],netLabels:netLabelPlacements}).length===0&&!doesPathOverlapTraceStrokes(candidate2.tracePath,otherNetTraces)&&!doesPathCoincideWithTraces(candidate2.tracePath,immutableSameNetTraces.filter(trace=>trace.mspPairId!==candidate2.mspPairId)))||!preservesLabelAnchors(netLabelPlacements,traces,allCandidateTraces))continue;let metrics=getTraceGeometryMetrics(candidateTraces,allCandidateTraces);if(metrics.otherNetCrossings>baseline.otherNetCrossings||(options?.coordinateIsFixedByLabel?metrics.turnCount>baseline.turnCount:!isReadabilityImprovement(metrics,baseline)))continue;let score={...metrics,displacement:group.reduce((sum,segment2)=>sum+Math.abs(segment2.coordinate-coordinate),0),coordinate},changedTraceIds=candidateTraces.filter(candidate2=>{let original=traces.find(trace=>trace.mspPairId===candidate2.mspPairId);return tracePathChanged(original,candidate2)}).map(trace=>trace.mspPairId);if(changedTraceIds.length===0)continue;let candidate={traces:allCandidateTraces,changedTraceIds,score};(!best||scoreIsBetter(candidate.score,best.score))&&(best=candidate)}return best},originalCandidate=evaluateCoordinates(fixedLabelCoordinate===null?originalCoordinates:[fixedLabelCoordinate],{coordinateIsFixedByLabel:fixedLabelCoordinate!==null});return originalCandidate||(fixedLabelCoordinate!==null?null:evaluateCoordinates(getRailAlignmentFallbackCoordinates({group,originalCoordinates,otherNetTraces})))},getMovableRailSegments=trace=>{let segments=[],path=trace.tracePath;for(let segmentIndex=1;segmentIndex<path.length-2;segmentIndex++){let previous=path[segmentIndex-1],start=path[segmentIndex],end=path[segmentIndex+1],next2=path[segmentIndex+2],orientation4=getRailOrientation(start,end);if(!orientation4)continue;let previousOrientation=getRailOrientation(previous,start),nextOrientation=getRailOrientation(end,next2);if(!previousOrientation||!nextOrientation||previousOrientation===orientation4||nextOrientation===orientation4)continue;let alongValues=orientation4==="vertical"?[start.y,end.y]:[start.x,end.x];segments.push({traceId:trace.mspPairId,segmentIndex,globalConnNetId:trace.globalConnNetId,orientation:orientation4,coordinate:orientation4==="vertical"?start.x:start.y,minAlong:Math.min(...alongValues),maxAlong:Math.max(...alongValues)})}return segments},railIsOutsideComponent=(segment2,chip,facingDirection)=>{let minX=chip.center.x-chip.width/2,maxX=chip.center.x+chip.width/2,minY=chip.center.y-chip.height/2,maxY=chip.center.y+chip.height/2;switch(facingDirection){case"x-":return segment2.orientation==="vertical"&&segment2.coordinate<=minX+RAIL_ALIGNMENT_EPSILON;case"x+":return segment2.orientation==="vertical"&&segment2.coordinate>=maxX-RAIL_ALIGNMENT_EPSILON;case"y+":return segment2.orientation==="horizontal"&&segment2.coordinate>=maxY-RAIL_ALIGNMENT_EPSILON;case"y-":return segment2.orientation==="horizontal"&&segment2.coordinate<=minY+RAIL_ALIGNMENT_EPSILON}},getComponentSideRailSegments=(trace,chipMap,options)=>{let segments=[],isLocalConnection=distance2(trace.pins[0],trace.pins[1])<=(options?.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE);for(let segment2 of getMovableRailSegments(trace)){let associations=trace.pins.flatMap((pin,pinIndex)=>{let chip=chipMap.get(pin.chipId);if(!chip)return[];let componentFacingDirection=pin._facingDirection??getPinDirection(pin,chip);return railIsOutsideComponent(segment2,chip,componentFacingDirection)?[{componentId:chip.chipId,componentFacingDirection,distanceFromEndpoint:pinIndex===0?segment2.segmentIndex:trace.tracePath.length-2-segment2.segmentIndex}]:[]});associations.sort((a6,b6)=>a6.distanceFromEndpoint-b6.distanceFromEndpoint);let minimumDistance=associations[0]?.distanceFromEndpoint,nearestAssociationKeys=new Set;for(let association of associations){if(nearestAssociationKeys.size>0&&(!options?.includeTiedEndpointAssociations||!isLocalConnection))break;if(association.distanceFromEndpoint!==minimumDistance)continue;let associationKey=`${association.componentId}:${association.componentFacingDirection}`;nearestAssociationKeys.has(associationKey)||(nearestAssociationKeys.add(associationKey),segments.push({...segment2,...association}))}}return segments},getCorridor=(a6,b6)=>{let overlapMin=Math.max(a6.minAlong,b6.minAlong),overlapMax=Math.min(a6.maxAlong,b6.maxAlong),along=(overlapMin+overlapMax)/2;return a6.orientation==="vertical"?[{x:a6.coordinate,y:along},{x:b6.coordinate,y:along}]:[{x:along,y:a6.coordinate},{x:along,y:b6.coordinate}]},corridorIsClear=(a6,b6,obstacles)=>{if(!rangesTouchOrOverlap(a6,b6))return!0;let[start,end]=getCorridor(a6,b6);return!obstacles.some(obstacle=>segmentIntersectsRect(start,end,obstacle))},tracesSharePin=(a6,b6,traceMap)=>{if(a6.traceId===b6.traceId)return!0;let aPinIds=new Set(traceMap.get(a6.traceId).pins.map(pin=>pin.pinId));return traceMap.get(b6.traceId).pins.some(pin=>aPinIds.has(pin.pinId))},canJoinRailGroup=(start,current3,candidate,traceMap,obstacles)=>candidate.globalConnNetId===start.globalConnNetId&&candidate.orientation===start.orientation&&candidate.componentId===start.componentId&&candidate.componentFacingDirection===start.componentFacingDirection&&(rangesTouchOrOverlap(current3,candidate)||tracesSharePin(current3,candidate,traceMap))&&corridorIsClear(current3,candidate,obstacles),getRailGroups=(traces,eligibleTraceIds,inputProblem,obstacles,netLabelPlacements)=>{let chipMap=new Map(inputProblem.chips.map(chip=>[chip.chipId,chip])),traceMap=new Map(traces.map(trace=>[trace.mspPairId,trace])),eligibleTraces=traces.filter(trace=>eligibleTraceIds.has(trace.mspPairId)),collectConnectedGroups=segments=>{let visited=new Set,connectedGroups=[];for(let startIndex=0;startIndex<segments.length;startIndex++){if(visited.has(startIndex))continue;let start=segments[startIndex],queue=[startIndex],group=[];visited.add(startIndex);for(let queueIndex=0;queueIndex<queue.length;queueIndex++){let current3=segments[queue[queueIndex]];group.push(current3);for(let candidateIndex=0;candidateIndex<segments.length;candidateIndex++){if(visited.has(candidateIndex))continue;let candidate=segments[candidateIndex];canJoinRailGroup(start,current3,candidate,traceMap,obstacles)&&(visited.add(candidateIndex),queue.push(candidateIndex))}}connectedGroups.push(group)}return connectedGroups},groupKey=group=>[group[0].componentId,group[0].componentFacingDirection,group[0].orientation,...group.map(segment2=>`${segment2.traceId}:${segment2.segmentIndex}`).sort()].join("|"),selectedGroups=[],selectedGroupKeys=new Set,addEligibleGroup=(group,options)=>{if(new Set(group.map(segment2=>segment2.traceId)).size<2)return;let fixedLabelCoordinate=getFixedLabelCoordinate(group,netLabelPlacements,traces);if(options?.requireFixedLabel&&fixedLabelCoordinate===null)return;let hasDifferentCoordinates=group.some(segment2=>!nearlyEqual(segment2.coordinate,group[0].coordinate)),hasDifferentFixedLabelCoordinate=fixedLabelCoordinate!==null&&!nearlyEqual(fixedLabelCoordinate,group[0].coordinate);if(!hasDifferentCoordinates&&!hasDifferentFixedLabelCoordinate)return;let key=groupKey(group);selectedGroupKeys.has(key)||(selectedGroupKeys.add(key),selectedGroups.push(group))},primarySegments=eligibleTraces.flatMap(trace=>getComponentSideRailSegments(trace,chipMap));for(let group of collectConnectedGroups(primarySegments))addEligibleGroup(group);let tiedEndpointSegments=eligibleTraces.flatMap(trace=>getComponentSideRailSegments(trace,chipMap,{includeTiedEndpointAssociations:!0,maxMspPairDistance:inputProblem.maxMspPairDistance}));for(let group of collectConnectedGroups(tiedEndpointSegments))addEligibleGroup(group,{requireFixedLabel:!0});return selectedGroups},getTraceStateKey=traces=>JSON.stringify(traces.map(trace=>({mspPairId:trace.mspPairId,tracePath:trace.tracePath}))),alignSameNetRails=({inputProblem,traces,netLabelPlacements,eligibleTraceIds})=>{let outputTraces=[...traces],seenTraceStates=new Set([getTraceStateKey(outputTraces)]),obstacles=getObstacleRects(inputProblem),alignedTraceIds=new Set,alignedRailGroupCount=0,maximumPasses=Math.max(1,traces.reduce((sum,trace)=>sum+trace.tracePath.length,0));for(let pass=0;pass<maximumPasses;pass++){let groups=getRailGroups(outputTraces,eligibleTraceIds,inputProblem,obstacles,netLabelPlacements),applied=null;for(let group of groups)if(applied=evaluateRailGroup({group,traces:outputTraces,netLabelPlacements,obstacles,eligibleTraceIds}),applied)break;if(!applied)break;let candidateStateKey=getTraceStateKey(applied.traces),repeatsSeenState=seenTraceStates.has(candidateStateKey);repeatsSeenState||seenTraceStates.add(candidateStateKey),outputTraces=applied.traces,alignedRailGroupCount++;for(let traceId of applied.changedTraceIds)alignedTraceIds.add(traceId);if(repeatsSeenState)break}return{traces:outputTraces,alignedRailGroupCount,alignedTraceCount:alignedTraceIds.size}},findAllLShapedTurns=tracePath=>{let lShapes=[];if(tracePath.length<3)return lShapes;for(let i6=0;i6<tracePath.length-2;i6++){let p12=tracePath[i6],p22=tracePath[i6+1],p3=tracePath[i6+2],dx1=p22.x-p12.x,dy1=p22.y-p12.y,dx22=p3.x-p22.x,dy22=p3.y-p22.y;(dx1===0&&dy22===0&&dy1!==0&&dx22!==0||dy1===0&&dx22===0&&dx1!==0&&dy22!==0)&&dx1*dx1+dy1*dy1>=.25&&dx22*dx22+dy22*dy22>=.25&&lShapes.push({p1:p12,p2:p22,p3})}return lShapes},getTraceObstacles=(allTraces,excludeTraceId)=>{let obstacles=[];for(let trace of allTraces)trace.mspPairId!==excludeTraceId&&obstacles.push({points:trace.tracePath});return obstacles},EPS9=1e-6,findIntersectionsWithObstacles=(p12,p22,obstacles)=>{let intersections=[];for(let obstacle of obstacles){let obstaclePath=obstacle.points;for(let i6=0;i6<obstaclePath.length-1;i6++){let o12=obstaclePath[i6],o22=obstaclePath[i6+1];if(!o12||!o22)continue;let intersection=getSegmentIntersection(p12,p22,o12,o22);intersection&&intersections.push(intersection)}}return intersections},isSamePoint=(first,second)=>Math.abs(first.x-second.x)<EPS9&&Math.abs(first.y-second.y)<EPS9,findPerpendicularPathCrossings=(path,otherPath)=>{let crossings=[];for(let pathSegmentIndex=1;pathSegmentIndex<path.length-2;pathSegmentIndex++){let start=path[pathSegmentIndex],end=path[pathSegmentIndex+1],isVertical52=Math.abs(start.x-end.x)<EPS9;for(let otherPathSegmentIndex=1;otherPathSegmentIndex<otherPath.length-2;otherPathSegmentIndex++){let otherStart=otherPath[otherPathSegmentIndex],otherEnd=otherPath[otherPathSegmentIndex+1],otherIsVertical=Math.abs(otherStart.x-otherEnd.x)<EPS9;if(isVertical52===otherIsVertical)continue;let intersection=getSegmentIntersection(start,end,otherStart,otherEnd);!intersection||[start,end,otherStart,otherEnd].some(point6=>isSamePoint(point6,intersection))||crossings.push({pathSegmentIndex,otherPathSegmentIndex})}}return crossings},EPS10=1e-6,isVertical3=(a6,b6,eps=EPS10)=>Math.abs(a6.x-b6.x)<eps,generateLShapeRerouteCandidates=({lShape,rectangle,padding=.5,interactionPoint1,interactionPoint2})=>{let{p1:p12,p2:p22,p3}=lShape,{x:x6,y:y2,width,height}=rectangle,c22,i1_padded=interactionPoint1,i2_padded=interactionPoint2;if(Math.abs(p22.x-x6)<EPS10&&Math.abs(p22.y-(y2+height))<EPS10)c22={x:x6+width+padding,y:y2-padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y-padding}:i1_padded={x:interactionPoint1.x+padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y-padding}:i2_padded={x:interactionPoint2.x+padding,y:interactionPoint2.y};else if(Math.abs(p22.x-(x6+width))<EPS10&&Math.abs(p22.y-(y2+height))<EPS10)c22={x:x6-padding,y:y2-padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y-padding}:i1_padded={x:interactionPoint1.x-padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y-padding}:i2_padded={x:interactionPoint2.x-padding,y:interactionPoint2.y};else if(Math.abs(p22.x-x6)<EPS10&&Math.abs(p22.y-y2)<EPS10)c22={x:x6+width+padding,y:y2+height+padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y+padding}:i1_padded={x:interactionPoint1.x+padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y+padding}:i2_padded={x:interactionPoint2.x+padding,y:interactionPoint2.y};else if(Math.abs(p22.x-(x6+width))<EPS10&&Math.abs(p22.y-y2)<EPS10)c22={x:x6-padding,y:y2+height+padding},isVertical3(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y+padding}:i1_padded={x:interactionPoint1.x-padding,y:interactionPoint1.y},isVertical3(p22,p3)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y+padding}:i2_padded={x:interactionPoint2.x-padding,y:interactionPoint2.y};else return[];return[[i1_padded,c22,i2_padded]]},generatePerimeterCornerTraceDetours=({trace,chipBounds,clearance})=>{if(trace.tracePath.length<4||chipBounds.length===0)return[];let start=trace.tracePath[0],firstEscape=trace.tracePath[1],lastEscape=trace.tracePath.at(-2),end=trace.tracePath.at(-1),minX=Math.min(...chipBounds.map(bounds=>bounds.minX))-clearance,maxX=Math.max(...chipBounds.map(bounds=>bounds.maxX))+clearance,minY=Math.min(...chipBounds.map(bounds=>bounds.minY))-clearance,maxY=Math.max(...chipBounds.map(bounds=>bounds.maxY))+clearance,candidates=[];for(let channelX of[minX,maxX])for(let channelY of[minY,maxY])candidates.push({traceId:trace.mspPairId,path:simplifyPath([start,firstEscape,{x:firstEscape.x,y:channelY},{x:channelX,y:channelY},{x:channelX,y:lastEscape.y},lastEscape,end])}),candidates.push({traceId:trace.mspPairId,path:simplifyPath([start,firstEscape,{x:channelX,y:firstEscape.y},{x:channelX,y:channelY},{x:lastEscape.x,y:channelY},lastEscape,end])});return candidates},generatePerpendicularTraceDetours=({trace,segmentIndex,obstacleStart,obstacleEnd,chipBounds,clearance})=>{let buildDetours=(path,index)=>{let start=path[index],end=path[index+1],movingAxis=Math.abs(start.x-end.x)<EPS10?"y":"x",detourAxis=movingAxis==="x"?"y":"x",gate=obstacleStart[movingAxis]+Math.sign(start[movingAxis]-obstacleStart[movingAxis])*clearance,obstacleRange=[obstacleStart[detourAxis],obstacleEnd[detourAxis]],lowBound=detourAxis==="x"?"minX":"minY",highBound=detourAxis==="x"?"maxX":"maxY",detourCoordinates=[Math.min(...obstacleRange)-clearance,Math.max(...obstacleRange)+clearance,...chipBounds.flatMap(bounds=>[bounds[lowBound]-clearance,bounds[highBound]+clearance])];return[...new Set(detourCoordinates)].map(detour=>simplifyPath([...path.slice(0,index+1),{...start,[movingAxis]:gate},{...start,[movingAxis]:gate,[detourAxis]:detour},{...end,[detourAxis]:detour},...path.slice(index+2)]))},reversedPath=[...trace.tracePath].reverse(),reversedIndex=trace.tracePath.length-2-segmentIndex;return[...buildDetours(trace.tracePath,segmentIndex),...buildDetours(reversedPath,reversedIndex).map(path=>path.reverse())].map(path=>({traceId:trace.mspPairId,path}))},isPathColliding=(path,allTraces,traceIdToExclude)=>{if(path.length<2)return{isColliding:!1};for(let i6=0;i6<path.length-1;i6++){let pathSegP1=path[i6],pathSegQ1=path[i6+1];for(let existingTrace of allTraces)if(existingTrace.mspPairId!==traceIdToExclude)for(let j6=0;j6<existingTrace.tracePath.length-1;j6++){let existingSegP2=existingTrace.tracePath[j6],existingSegQ2=existingTrace.tracePath[j6+1],intersectionPoint=getSegmentIntersection(pathSegP1,pathSegQ1,existingSegP2,existingSegQ2);if(intersectionPoint)return{isColliding:!0,collidingTraceId:existingTrace.mspPairId,collisionPoint:intersectionPoint}}}return{isColliding:!1}},generateRectangleCandidates=(intersections1,intersections2)=>{let rectangleCandidates=[];for(let p12 of intersections1)for(let p22 of intersections2){let minX=Math.min(p12.x,p22.x),minY=Math.min(p12.y,p22.y),maxX=Math.max(p12.x,p22.x),maxY=Math.max(p12.y,p22.y),width=maxX-minX,height=maxY-minY;width>1e-6&&height>1e-6&&rectangleCandidates.push({rect:{x:minX,y:minY,width,height},i1:p12,i2:p22})}return rectangleCandidates},visualizeLSapes=lShapes=>{let graphics={circles:[],lines:[]},lShapesArray=Array.isArray(lShapes)?lShapes:[lShapes];for(let lShape of lShapesArray)graphics.circles.push({center:{x:lShape.p2.x,y:lShape.p2.y},radius:.01,fill:"blue"}),graphics.lines.push({points:[lShape.p1,lShape.p2,lShape.p3],strokeColor:"lightblue"});return graphics},visualizeIntersectionPoints=(points,color="red")=>{let graphics={circles:[]};for(let point6 of points)graphics.circles.push({center:{x:point6.x,y:point6.y},radius:.01,fill:color});return graphics},visualizeTightRectangle=rectangle=>{let graphics={rects:[]};return graphics.rects.push({center:{x:rectangle.x+rectangle.width/2,y:rectangle.y+rectangle.height/2},width:rectangle.width,height:rectangle.height,stroke:"green"}),graphics},visualizeCandidates=(candidates,color="gray",intersectionPoints=[])=>{let graphics={lines:[],circles:[]};for(let candidate of candidates)graphics.lines.push({points:candidate,strokeColor:color});for(let point6 of intersectionPoints)graphics.circles.push({center:point6,radius:.01,fill:"green"});return graphics},mergeGraphicsObjects=objects=>{let merged={lines:[],points:[],rects:[],circles:[],texts:[]};for(let obj of objects)obj&&(obj.lines&&merged.lines.push(...obj.lines),obj.points&&merged.points.push(...obj.points),obj.rects&&merged.rects.push(...obj.rects),obj.circles&&merged.circles.push(...obj.circles),obj.texts&&merged.texts.push(...obj.texts));return merged},visualizeCollision=collisionInfo=>{let collisionGraphics={circles:[]};return collisionInfo?.isColliding&&collisionInfo.collisionPoint&&collisionGraphics.circles.push({center:collisionInfo.collisionPoint,radius:.01,fill:"red"}),collisionGraphics},UntangleTraceSubsolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"lShapesToProcess",[]);__publicField(this,"ignoredCrossings",new Set);__publicField(this,"reroutedTraceIds",new Set);__publicField(this,"processingCrossings",!0);__publicField(this,"visualizationMode","l_shapes");__publicField(this,"currentLShape",null);__publicField(this,"intersectionPoints",[]);__publicField(this,"tightRectangle",null);__publicField(this,"candidates",[]);__publicField(this,"bestRoute",null);__publicField(this,"lastCollision",null);__publicField(this,"collidingCandidate",null);__publicField(this,"rectangleCandidates",[]);__publicField(this,"currentRectangleIndex",0);__publicField(this,"isInitialStep",!0);__publicField(this,"currentCandidateIndex",0);__publicField(this,"lShapeProcessingStep","idle");__publicField(this,"lShapeJustProcessed",!1);__publicField(this,"bestRouteFound",null);this.input=solverInput,this.visualizationMode="l_shapes",this.chipObstacleSpatialIndex=this.input.inputProblem._chipObstacleSpatialIndex??new ChipObstacleSpatialIndex(this.input.inputProblem.chips),this.input.inputProblem._chipObstacleSpatialIndex||(this.input.inputProblem._chipObstacleSpatialIndex=this.chipObstacleSpatialIndex)}_step(){if(this.isInitialStep){this.isInitialStep=!1;return}if(this.processingCrossings){let crossing=this._findCrossing();if(crossing){this._resolveCrossing(crossing)||this.ignoredCrossings.add(this._crossingKey(crossing));return}this.processingCrossings=!1,this._initializeLShapes();return}if(this.lShapeJustProcessed){this._resetAfterLShapProcessing();return}if(this.lShapesToProcess.length===0&&this.currentLShape===null){this.solved=!0;return}switch(this.lShapeProcessingStep){case"idle":this._handleIdleStep();break;case"intersections":this._handleIntersectionsStep();break;case"rectangle_selection":this._handleRectangleSelectionStep();break;case"candidate_evaluation":this._handleCandidateEvaluationStep();break}}_initializeLShapes(){for(let trace of this.input.allTraces)this.lShapesToProcess.push(...findAllLShapedTurns(trace.tracePath).map(lShape=>({...lShape,traceId:trace.mspPairId})))}_crossingKey(crossing){return`${crossing.trace.mspPairId}:${crossing.segmentIndex}:${crossing.otherTrace.mspPairId}:${crossing.otherSegmentIndex}`}_isTraceBundle(first,second){let componentPair=trace=>trace.pins.map(pin=>pin.chipId).sort().join(":");return componentPair(first)!==componentPair(second)?!1:Object.values(this.input.mergedLabelNetIdMap).some(netIds=>netIds.has(first.globalConnNetId)&&netIds.has(second.globalConnNetId))}_findCrossing(){let traces=this.input.allTraces;for(let firstIndex=0;firstIndex<traces.length;firstIndex++){let trace=traces[firstIndex];for(let secondIndex=firstIndex+1;secondIndex<traces.length;secondIndex++){let otherTrace=traces[secondIndex];if(trace.globalConnNetId===otherTrace.globalConnNetId)continue;let isInitialBundleCrossing=this._isTraceBundle(trace,otherTrace),isEligibleInitialCrossing=this.input.eligibleTraceIds?.has(trace.mspPairId)===!0||this.input.eligibleTraceIds?.has(otherTrace.mspPairId)===!0;if(!isInitialBundleCrossing&&!isEligibleInitialCrossing&&!this.reroutedTraceIds.has(trace.mspPairId)&&!this.reroutedTraceIds.has(otherTrace.mspPairId))continue;let crossings=findPerpendicularPathCrossings(trace.tracePath,otherTrace.tracePath);for(let{pathSegmentIndex,otherPathSegmentIndex}of crossings){let crossing={trace,segmentIndex:pathSegmentIndex,otherTrace,otherSegmentIndex:otherPathSegmentIndex,isInitialBundleCrossing};if(!this.ignoredCrossings.has(this._crossingKey(crossing)))return crossing}}}return null}_resolveCrossing(crossing){let chipBounds=this.chipObstacleSpatialIndex.chips.map(chip=>chip.bounds),candidates=[...generatePerpendicularTraceDetours({trace:crossing.trace,segmentIndex:crossing.segmentIndex,obstacleStart:crossing.otherTrace.tracePath[crossing.otherSegmentIndex],obstacleEnd:crossing.otherTrace.tracePath[crossing.otherSegmentIndex+1],chipBounds,clearance:this.input.paddingBuffer}),...generatePerpendicularTraceDetours({trace:crossing.otherTrace,segmentIndex:crossing.otherSegmentIndex,obstacleStart:crossing.trace.tracePath[crossing.segmentIndex],obstacleEnd:crossing.trace.tracePath[crossing.segmentIndex+1],chipBounds,clearance:this.input.paddingBuffer}),...generatePerimeterCornerTraceDetours({trace:crossing.trace,chipBounds,clearance:this.input.paddingBuffer}),...generatePerimeterCornerTraceDetours({trace:crossing.otherTrace,chipBounds,clearance:this.input.paddingBuffer})],chipObstacles=getObstacleRects(this.input.inputProblem).filter(obstacle=>obstacle.kind==="chip"),bestCandidate=candidates.map(candidate=>({...candidate,collision:isPathColliding(candidate.path,this.input.allTraces,candidate.traceId)})).filter(candidate=>!isPathCollidingWithChipInterior(candidate.path,chipObstacles)&&!isPathColliding(candidate.path,[crossing.trace,crossing.otherTrace],candidate.traceId).isColliding&&(crossing.isInitialBundleCrossing||!candidate.collision.isColliding)).sort((first,second)=>Number(first.collision.isColliding)-Number(second.collision.isColliding)||getPathLength2(first.path)-getPathLength2(second.path))[0];if(!bestCandidate)return!1;let traceIndex=this.input.allTraces.findIndex(trace=>trace.mspPairId===bestCandidate.traceId);return this.input.allTraces[traceIndex]={...this.input.allTraces[traceIndex],tracePath:bestCandidate.path},this.reroutedTraceIds.add(bestCandidate.traceId),!0}_resetAfterLShapProcessing(){this.lShapeProcessingStep="idle",this.currentLShape=null,this.currentCandidateIndex=0,this.lShapeJustProcessed=!1,this.visualizationMode="l_shapes",this.intersectionPoints=[],this.tightRectangle=null,this.candidates=[],this.bestRoute=null,this.lastCollision=null,this.collidingCandidate=null}_handleIdleStep(){if(this.currentLShape=this.lShapesToProcess.shift(),!this.currentLShape){this.solved=!0;return}this.lShapeProcessingStep="intersections",this.visualizationMode="l_shapes"}_handleIntersectionsStep(){if(!this.currentLShape.traceId){this.lShapeProcessingStep="idle";return}let allObstacles=getTraceObstacles(this.input.allTraces,this.currentLShape.traceId),intersections1=findIntersectionsWithObstacles(this.currentLShape.p1,this.currentLShape.p2,allObstacles),intersections2=findIntersectionsWithObstacles(this.currentLShape.p2,this.currentLShape.p3,allObstacles);if(this.intersectionPoints=[...intersections1,...intersections2],intersections1.length===0||intersections2.length===0){this.lShapeProcessingStep="idle";return}this.rectangleCandidates=generateRectangleCandidates(intersections1,intersections2),this.currentRectangleIndex=0,this.lShapeProcessingStep="rectangle_selection"}_handleRectangleSelectionStep(){if(this.currentRectangleIndex>=this.rectangleCandidates.length){this.lShapeProcessingStep="idle";return}let{rect,i1:i12,i2:i22}=this.rectangleCandidates[this.currentRectangleIndex];this.tightRectangle=rect,this.candidates=generateLShapeRerouteCandidates({lShape:this.currentLShape,rectangle:this.tightRectangle,padding:2*this.input.paddingBuffer,interactionPoint1:i12,interactionPoint2:i22}),this.currentCandidateIndex=0,this.lastCollision=null,this.collidingCandidate=null,this.visualizationMode="candidates",this.lShapeProcessingStep="candidate_evaluation"}_handleCandidateEvaluationStep(){if(this.visualizationMode="candidates",this.bestRouteFound){this._applyBestRoute(this.bestRouteFound),this.bestRouteFound=null;return}if(this.currentCandidateIndex>=this.candidates.length){this.currentRectangleIndex++,this.lShapeProcessingStep="rectangle_selection";return}let currentCandidate=this.candidates[this.currentCandidateIndex],collisionResult=isPathColliding(currentCandidate,this.input.allTraces,this.currentLShape.traceId);if(!collisionResult?.isColliding&&this._doesCandidateCrossChip(currentCandidate)){this.lastCollision=null,this.collidingCandidate=currentCandidate,this.currentCandidateIndex++;return}collisionResult?.isColliding?(this.lastCollision=collisionResult,this.collidingCandidate=currentCandidate,this.currentCandidateIndex++):(this.bestRouteFound=currentCandidate,this.lastCollision=null,this.collidingCandidate=null)}_doesCandidateCrossChip(candidate){for(let i6=0;i6<candidate.length-1;i6++)if(this.chipObstacleSpatialIndex.doesOrthogonalLineIntersectChip([candidate[i6],candidate[i6+1]]))return!0;return!1}_applyBestRoute(bestRoute){this.bestRoute=bestRoute,this.collidingCandidate=null,this.lastCollision=null;let traceIndex=this.input.allTraces.findIndex(trace=>trace.mspPairId===this.currentLShape.traceId);if(traceIndex!==-1){let originalTrace=this.input.allTraces[traceIndex],p2Index=originalTrace.tracePath.findIndex(p3=>p3.x===this.currentLShape.p2.x&&p3.y===this.currentLShape.p2.y);if(p2Index!==-1){let newTracePath=[...originalTrace.tracePath.slice(0,p2Index),...bestRoute,...originalTrace.tracePath.slice(p2Index+1)];this.input.allTraces[traceIndex]={...originalTrace,tracePath:newTracePath},this.lShapesToProcess=this.lShapesToProcess.filter(l6=>l6.traceId!==this.currentLShape.traceId)}}this.lShapeJustProcessed=!0}getOutput(){return{traces:this.input.allTraces}}visualize(){switch(this.visualizationMode){case"l_shapes":return visualizeLSapes(this.lShapesToProcess);case"intersection_points":return mergeGraphicsObjects([this.currentLShape?visualizeLSapes(this.currentLShape):void 0,visualizeIntersectionPoints(this.intersectionPoints)]);case"tight_rectangle":return mergeGraphicsObjects([this.currentLShape?visualizeLSapes(this.currentLShape):void 0,visualizeIntersectionPoints(this.intersectionPoints),this.tightRectangle?visualizeTightRectangle(this.tightRectangle):void 0]);case"candidates":{if(this.lShapeJustProcessed){let allTracesGraphics2={lines:[]};for(let trace of this.input.allTraces){let isUpdatedTrace=trace.mspPairId===this.currentLShape?.traceId;for(let i6=0;i6<trace.tracePath.length-1;i6++)allTracesGraphics2.lines.push({points:[trace.tracePath[i6],trace.tracePath[i6+1]],strokeColor:isUpdatedTrace?"green":"#ccc"})}return allTracesGraphics2}let allTracesGraphics={lines:[]};for(let trace of this.input.allTraces)for(let i6=0;i6<trace.tracePath.length-1;i6++)allTracesGraphics.lines.push({points:[trace.tracePath[i6],trace.tracePath[i6+1]],strokeColor:"#ccc"});let candidateToDraw;return this.bestRouteFound?candidateToDraw=this.bestRouteFound:this.lastCollision?.isColliding?candidateToDraw=this.collidingCandidate??void 0:this.currentCandidateIndex<this.candidates.length&&(candidateToDraw=this.candidates[this.currentCandidateIndex]),mergeGraphicsObjects([allTracesGraphics,this.currentLShape?visualizeLSapes(this.currentLShape):void 0,this.tightRectangle?visualizeTightRectangle(this.tightRectangle):void 0,candidateToDraw?visualizeCandidates([candidateToDraw],this.bestRouteFound?"green":"blue",this.intersectionPoints):void 0,this.lastCollision?visualizeCollision(this.lastCollision):void 0])}default:return{}}}},EPS11=1e-6,sameX=(a6,b6)=>Math.abs(a6.x-b6.x)<=EPS11,sameY=(a6,b6)=>Math.abs(a6.y-b6.y)<=EPS11,is4PointRectangle=path=>{if(path.length!==4)return!1;let[p03,p12,p22,p3]=path,isHVHC=sameY(p03,p12)&&sameX(p12,p22)&&sameY(p22,p3)&&sameX(p03,p3),isVHVC=sameX(p03,p12)&&sameY(p12,p22)&&sameX(p22,p3)&&sameY(p03,p3);return isHVHC||isVHVC},DEFAULT_OPERATIONS=["untangling_traces","minimizing_turns","balancing_l_shapes"],TraceCleanupSolver=class extends BaseSolver5{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"traceIdQueue");__publicField(this,"tracesMap");__publicField(this,"operations");__publicField(this,"operationIndex",0);__publicField(this,"pipelineStep");__publicField(this,"activeTraceId",null);__publicField(this,"activeSubSolver",null);this.input=solverInput,this.outputTraces=[...solverInput.allTraces],this.tracesMap=new Map(this.outputTraces.map(t53=>[t53.mspPairId,t53])),this.operations=solverInput.operations??DEFAULT_OPERATIONS,this.pipelineStep=this.operations[0]??null,this.traceIdQueue=Array.from(solverInput.allTraces.map(e6=>e6.mspPairId))}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){let output=this.activeSubSolver.getOutput();this.outputTraces=output.traces,this.tracesMap=new Map(this.outputTraces.map(t53=>[t53.mspPairId,t53])),this.activeSubSolver=null,this._advancePipeline()}else this.activeSubSolver.failed&&(this.activeSubSolver=null,this._advancePipeline());return}if(!this.pipelineStep){this.solved=!0;return}switch(this.pipelineStep){case"untangling_traces":this._runUntangleTracesStep();break;case"minimizing_turns":this._runMinimizeTurnsStep();break;case"balancing_l_shapes":this._runBalanceLShapesStep();break;case"aligning_same_net_rails":this._runAlignSameNetRailsStep();break}}_advancePipeline(){this.operationIndex++,this.pipelineStep=this.operations[this.operationIndex]??null,this.traceIdQueue=this.outputTraces.map(trace=>trace.mspPairId),this.pipelineStep&&(this.activeTraceId=null)}_runUntangleTracesStep(){this.activeSubSolver=new UntangleTraceSubsolver({...this.input,allTraces:Array.from(this.tracesMap.values())})}_runMinimizeTurnsStep(){if(this.traceIdQueue.length===0){this._advancePipeline();return}this._processTrace("minimizing_turns")}_runBalanceLShapesStep(){if(this.traceIdQueue.length===0){this._advancePipeline();return}this._processTrace("balancing_l_shapes")}_processTrace(step){let targetMspConnectionPairId=this.traceIdQueue.shift();this.activeTraceId=targetMspConnectionPairId;let originalTrace=this.tracesMap.get(targetMspConnectionPairId);if(is4PointRectangle(originalTrace.tracePath))return;let allTraces=Array.from(this.tracesMap.values()),updatedTrace;step==="minimizing_turns"?updatedTrace=minimizeTurnsWithFilteredLabels({...this.input,targetMspConnectionPairId,traces:allTraces}):updatedTrace=balanceZShapes({...this.input,targetMspConnectionPairId,traces:allTraces}),this.tracesMap.set(targetMspConnectionPairId,updatedTrace),this.outputTraces=Array.from(this.tracesMap.values())}_runAlignSameNetRailsStep(){let alignment=alignSameNetRails({inputProblem:this.input.inputProblem,traces:this.outputTraces,netLabelPlacements:this.input.allLabelPlacements,eligibleTraceIds:this.input.eligibleTraceIds??new Set(this.outputTraces.map(trace=>trace.mspPairId))});this.outputTraces=alignment.traces,this.tracesMap=new Map(this.outputTraces.map(t53=>[t53.mspPairId,t53])),this.stats.alignedRailGroupCount=alignment.alignedRailGroupCount,this.stats.alignedTraceCount=alignment.alignedTraceCount,this._advancePipeline()}getOutput(){return{traces:this.outputTraces}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.input.inputProblem,{chipAlpha:.1,connectionAlpha:.1});graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.rects||(graphics.rects=[]),graphics.circles||(graphics.circles=[]),graphics.texts||(graphics.texts=[]);for(let trace of this.outputTraces){let line2={points:trace.tracePath.map(p3=>({x:p3.x,y:p3.y})),strokeColor:trace.mspPairId===this.activeTraceId?"red":"blue"};graphics.lines.push(line2)}return graphics}},getPinMap=inputProblem=>{let pinMap={};for(let chip of inputProblem.chips)for(let pin of chip.pins)pinMap[pin.pinId]={...pin,chipId:chip.chipId};return pinMap},getTracePins=(label,pinMap)=>{let pins=label.pinIds.flatMap(pinId=>{let pin=pinMap[pinId];return pin?[pin]:[]});if(pins.length>=2)return[pins[0],pins[1]];if(pins.length===1)return[pins[0],pins[0]];let syntheticPin={pinId:`${label.globalConnNetId}-netlabel-anchor`,x:label.anchorPoint.x,y:label.anchorPoint.y,chipId:"available-net-orientation"};return[syntheticPin,syntheticPin]},toNetLabelPlacementPatch=candidate=>({orientation:candidate.orientation,anchorPoint:candidate.anchorPoint,center:candidate.center,width:candidate.width,height:candidate.height}),dir=facingDirection=>{switch(facingDirection){case"x+":return{x:1,y:0};case"x-":return{x:-1,y:0};case"y+":return{x:0,y:1};case"y-":return{x:0,y:-1}}throw new Error(`Invalid facing direction: ${facingDirection}`)},getMovedAnchorPointForReroute=(anchorPoint,originalTracePath,reroutedTracePath)=>{let originalSegment=findSegmentContainingPoint(originalTracePath,anchorPoint);if(!originalSegment)return null;let preferredSegment=findPreferredReroutedSegment(reroutedTracePath,originalSegment.index,originalTracePath.length-1,originalSegment.orientation,anchorPoint);return preferredSegment?projectPointToSegment(anchorPoint,preferredSegment.start,preferredSegment.end):projectPointToPath(anchorPoint,reroutedTracePath)},isLabelAttachedToTrace=(label,trace)=>label.globalConnNetId===trace.globalConnNetId||label.mspConnectionPairIds.includes(trace.mspPairId),moveAttachedLabelsToReroutedTrace=({trace,originalTracePath,reroutedTracePath,netLabelPlacements})=>netLabelPlacements.map(label=>{if(!isLabelAttachedToTrace(label,trace))return label;let movedAnchorPoint=getMovedAnchorPointForReroute(label.anchorPoint,originalTracePath,reroutedTracePath);if(!movedAnchorPoint)return label;let delta={x:movedAnchorPoint.x-label.anchorPoint.x,y:movedAnchorPoint.y-label.anchorPoint.y};return{...label,anchorPoint:movedAnchorPoint,center:{x:label.center.x+delta.x,y:label.center.y+delta.y}}}),moveNetLabelConnectorsToReroutedTraces=({originalTraces,reroutedTraces,netLabelPlacements})=>{let traces=[...reroutedTraces],reroutedTraceMap=new Map(reroutedTraces.map(trace=>[trace.mspPairId,trace])),labels=netLabelPlacements.map(label=>{let originalHostTrace=originalTraces.find(trace=>{if(!label.mspConnectionPairIds.includes(trace.mspPairId))return!1;let reroutedTrace=reroutedTraceMap.get(trace.mspPairId);return reroutedTrace?reroutedTrace.tracePath!==trace.tracePath:!1});if(!originalHostTrace)return label;let reroutedHostTrace=reroutedTraceMap.get(originalHostTrace.mspPairId),connectorIndex=originalTraces.findIndex(trace=>trace.mspPairId===originalHostTrace.mspPairId||trace.globalConnNetId!==label.globalConnNetId||!tracePathContainsPoint(trace.tracePath,label.anchorPoint)?!1:label.pinIds.every(pinId=>trace.pinIds.includes(pinId)));if(connectorIndex<0)return label;let connector=originalTraces[connectorIndex],originalJunction=connector.tracePath.find(point6=>tracePathContainsPoint(originalHostTrace.tracePath,point6));if(!originalJunction)return label;let reroutedJunction=getMovedAnchorPointForReroute(originalJunction,originalHostTrace.tracePath,reroutedHostTrace.tracePath);if(!reroutedJunction)return label;let delta={x:reroutedJunction.x-originalJunction.x,y:reroutedJunction.y-originalJunction.y},movedConnector={...connector,tracePath:connector.tracePath.map(point6=>({x:point6.x+delta.x,y:point6.y+delta.y}))};return traces[connectorIndex]=movedConnector,moveAttachedLabelsToReroutedTrace({trace:connector,originalTracePath:connector.tracePath,reroutedTracePath:movedConnector.tracePath,netLabelPlacements:[label]})[0]});return{traces,netLabelPlacements:labels}},doesPathRunAlongChipBoundary=(path,chipObstacles)=>{for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];for(let obstacle of chipObstacles)if(segmentRunsAlongRectBoundary(start,end,obstacle)&&getSegmentOverlapWithRectSpan(start,end,obstacle)>EPS8)return!0}return!1},getChipBoundaryOverlap=(path,chipObstacles)=>{let total=0;for(let i6=0;i6<path.length-1;i6++){let start=path[i6],end=path[i6+1];for(let obstacle of chipObstacles){if(!segmentRunsAlongRectBoundary(start,end,obstacle))continue;let overlap=getSegmentOverlapWithRectSpan(start,end,obstacle);overlap>EPS8&&(total+=overlap)}}return total},getSegmentOverlapWithRectSpan=(start,end,rect)=>Math.abs(start.x-end.x)<EPS8?Math.min(Math.max(start.y,end.y),rect.maxY)-Math.max(Math.min(start.y,end.y),rect.minY):Math.min(Math.max(start.x,end.x),rect.maxX)-Math.max(Math.min(start.x,end.x),rect.minX),LABEL_CLEARANCE=.1,MAX_CORRIDOR_SHIFTS=16,corridorHasOtherNetTrace=({x:x6,lowY,highY,outputTraces,netId})=>{for(let other of outputTraces){if(other.globalConnNetId===netId)continue;let path=other.tracePath;for(let i6=0;i6+1<path.length;i6++){let start=path[i6],end=path[i6+1];if(Math.abs(start.x-end.x)>=1e-9||Math.abs(start.x-x6)>=LABEL_CLEARANCE/2)continue;let segLowY=Math.min(start.y,end.y),segHighY=Math.max(start.y,end.y);if(Math.min(highY,segHighY)-Math.max(lowY,segLowY)>1e-6)return!0}}return!1},findBestReroutePath=({trace,obstacleLabel,inputProblem,outputTraces,outputNetLabelPlacements,chipObstacles})=>{let candidateResults=generateRerouteCandidateResults({trace,label:obstacleLabel,inputProblem,outputTraces,outputNetLabelPlacements,chipObstacles}),bestPath=selectBestReroutePath({trace,obstacleLabel,outputTraces,outputNetLabelPlacements,candidateResults,chipObstacles});return markSelectedCandidate(candidateResults,bestPath),{bestPath,candidateResults}},generateRerouteCandidateResults=({trace,label,inputProblem,outputTraces,outputNetLabelPlacements,chipObstacles})=>{let seen=new Set,candidateResults=[],horizontalSegmentPushCandidate=generateHorizontalSegmentPushCandidate({trace,label,outputTraces});horizontalSegmentPushCandidate&&candidateResults.push(createCandidateResult({trace,obstacleLabel:label,path:horizontalSegmentPushCandidate,seen,outputTraces,outputNetLabelPlacements,chipObstacles,usesHorizontalSegmentPush:!0}));let rawCandidates=[...generateLabelHugCandidates(trace,label),...generateRerouteCandidates({trace,label,problem:inputProblem,paddingBuffer:LABEL_CLEARANCE,detourCount:0}),...generateEndpointDetourCandidates(trace,label)];for(let rawCandidate of rawCandidates)candidateResults.push(createCandidateResult({trace,obstacleLabel:label,path:simplifyPath(rawCandidate),seen,outputTraces,outputNetLabelPlacements,chipObstacles}));return candidateResults},createCandidateResult=({trace,obstacleLabel,path,seen,outputTraces,outputNetLabelPlacements,chipObstacles,usesHorizontalSegmentPush})=>{let key=getPathKey(path);return seen.has(key)?{path,status:"duplicate",usesHorizontalSegmentPush,selected:!1}:(seen.add(key),isPathCollidingWithChipInterior(path,chipObstacles)?{path,status:"chip-collision",usesHorizontalSegmentPush,selected:!1}:{path,score:scoreTracePath({trace,tracePath:path,obstacleLabel,outputTraces,outputNetLabelPlacements,chipObstacles}),status:"valid",usesHorizontalSegmentPush,selected:!1})},generateEndpointDetourCandidates=(trace,label)=>{let start=trace.tracePath[0],end=trace.tracePath[trace.tracePath.length-1];if(!start||!end)return[];let startExit=trace.tracePath[1]??start,endEntry=trace.tracePath[trace.tracePath.length-2]??end,bounds=getRectBounds(label.center,label.width,label.height),padding=LABEL_CLEARANCE,labelDirection=dir(label.orientation),labelSideX=labelDirection.x<0?bounds.minX-padding:bounds.maxX+padding,oppositeSideX=labelDirection.x<0?bounds.maxX+padding:bounds.minX-padding,topY=bounds.maxY+padding,bottomY=bounds.minY-padding,candidates=[];for(let sideX of[labelSideX,oppositeSideX])candidates.push([start,startExit,{x:startExit.x,y:topY},{x:sideX,y:topY},{x:sideX,y:bottomY},{x:endEntry.x,y:bottomY},endEntry,end],[start,startExit,{x:startExit.x,y:bottomY},{x:sideX,y:bottomY},{x:sideX,y:topY},{x:endEntry.x,y:topY},endEntry,end]);return candidates},generateLabelHugCandidates=(trace,label)=>{let start=trace.tracePath[0],end=trace.tracePath[trace.tracePath.length-1];if(!start||!end)return[];let startExit=trace.tracePath[1]??start,endEntry=trace.tracePath[trace.tracePath.length-2]??end,labelDirection=dir(label.orientation);if(labelDirection.x===0)return[];let bounds=getRectBounds(label.center,label.width,label.height),sideX=labelDirection.x<0?bounds.minX-LABEL_CLEARANCE:bounds.maxX+LABEL_CLEARANCE,topY=bounds.maxY+LABEL_CLEARANCE,bottomY=bounds.minY-LABEL_CLEARANCE,startsAboveEnd=startExit.y>=endEntry.y,firstY=startsAboveEnd?topY:bottomY,secondY=startsAboveEnd?bottomY:topY;return[[start,startExit,{x:startExit.x,y:firstY},{x:sideX,y:firstY},{x:sideX,y:secondY},{x:endEntry.x,y:secondY},endEntry,end],[start,startExit,{x:startExit.x,y:secondY},{x:sideX,y:secondY},{x:sideX,y:firstY},{x:endEntry.x,y:firstY},endEntry,end]]},selectBestReroutePath=({trace,obstacleLabel,outputTraces,outputNetLabelPlacements,candidateResults,chipObstacles})=>{for(let candidate of candidateResults)if(candidate.usesHorizontalSegmentPush&&candidate.status==="valid"&&candidate.score)return candidate.path;let bestPath=null,bestScore=scoreTracePath({trace,tracePath:trace.tracePath,obstacleLabel,outputTraces,outputNetLabelPlacements,chipObstacles});for(let candidate of candidateResults)candidate.status!=="valid"||!candidate.score||isBetterScore(candidate.score,bestScore)&&(bestScore=candidate.score,bestPath=candidate.path);return bestPath},generateHorizontalSegmentPushCandidate=({trace,label,outputTraces})=>{let labelDirection=dir(label.orientation);if(labelDirection.x===0)return null;let path=trace.tracePath,bounds=getRectBounds(label.center,label.width,label.height),collidingVerticalSegmentIndex=path.findIndex((start,index)=>{let end=path[index+1];return!end||Math.abs(start.x-end.x)>=1e-9?!1:segmentIntersectsRect2(start,end,bounds)});if(collidingVerticalSegmentIndex<=0||collidingVerticalSegmentIndex>=path.length-2)return null;let previousAnchor=path[collidingVerticalSegmentIndex-1],verticalStart=path[collidingVerticalSegmentIndex],verticalEnd=path[collidingVerticalSegmentIndex+1],nextAnchor=path[collidingVerticalSegmentIndex+2];if(Math.abs(previousAnchor.y-verticalStart.y)>=1e-9||Math.abs(verticalEnd.y-nextAnchor.y)>=1e-9)return null;let segmentPushX=bounds.minX-LABEL_CLEARANCE;labelDirection.x>0&&(segmentPushX=bounds.maxX+LABEL_CLEARANCE);let corridorStep=labelDirection.x>0?LABEL_CLEARANCE:-LABEL_CLEARANCE,verticalLowY=Math.min(verticalStart.y,verticalEnd.y),verticalHighY=Math.max(verticalStart.y,verticalEnd.y);for(let shift=0;shift<MAX_CORRIDOR_SHIFTS&&corridorHasOtherNetTrace({x:segmentPushX,lowY:verticalLowY,highY:verticalHighY,outputTraces,netId:trace.globalConnNetId});shift++)segmentPushX+=corridorStep;let segmentPushStartY=getClearedHorizontalY({start:previousAnchor,end:{x:segmentPushX,y:verticalStart.y},labelBounds:bounds}),segmentPushEndY=getClearedHorizontalY({start:{x:segmentPushX,y:verticalEnd.y},end:nextAnchor,labelBounds:bounds}),segmentPushPath=[...path.slice(0,collidingVerticalSegmentIndex-1),previousAnchor];return Math.abs(previousAnchor.y-segmentPushStartY)>=1e-9&&segmentPushPath.push({x:previousAnchor.x,y:segmentPushStartY}),segmentPushPath.push({x:segmentPushX,y:segmentPushStartY}),segmentPushPath.push({x:segmentPushX,y:segmentPushEndY}),Math.abs(nextAnchor.y-segmentPushEndY)>=1e-9&&segmentPushPath.push({x:nextAnchor.x,y:segmentPushEndY}),segmentPushPath.push(nextAnchor,...path.slice(collidingVerticalSegmentIndex+3)),simplifyPath(segmentPushPath)},getClearedHorizontalY=({start,end,labelBounds})=>{if(!segmentIntersectsRect2(start,end,labelBounds))return start.y;let labelCenterY=(labelBounds.minY+labelBounds.maxY)/2;return start.y>=labelCenterY?labelBounds.maxY+LABEL_CLEARANCE:labelBounds.minY-LABEL_CLEARANCE},markSelectedCandidate=(candidateResults,bestPath)=>{if(bestPath)for(let candidate of candidateResults)candidate.selected=candidate.path===bestPath},scoreTracePath=({trace,tracePath,obstacleLabel,outputTraces,outputNetLabelPlacements,chipObstacles})=>{let candidateTrace={...trace,tracePath};return{labelIntersections:detectTraceLabelOverlap({traces:[candidateTrace],netLabels:outputNetLabelPlacements}).length,labelHugDistance:getLabelHugDistance(tracePath,obstacleLabel),traceIntersections:countTraceIntersections(candidateTrace,outputTraces),chipBoundaryOverlap:getChipBoundaryOverlap(tracePath,chipObstacles),pathLength:getPathLength2(tracePath)}},countTraceIntersections=(trace,outputTraces)=>{let count=0;for(let otherTrace of outputTraces)otherTrace.mspPairId!==trace.mspPairId&&(count+=countPathIntersections(trace.tracePath,otherTrace.tracePath));return count},isBetterScore=(score,bestScore)=>{let scoreHasLabelOverlap=score.labelIntersections>0,bestHasLabelOverlap=bestScore.labelIntersections>0;return scoreHasLabelOverlap!==bestHasLabelOverlap?!scoreHasLabelOverlap:score.chipBoundaryOverlap!==bestScore.chipBoundaryOverlap?score.chipBoundaryOverlap<bestScore.chipBoundaryOverlap:score.labelIntersections!==bestScore.labelIntersections?score.labelIntersections<bestScore.labelIntersections:score.labelHugDistance!==bestScore.labelHugDistance?score.labelHugDistance<bestScore.labelHugDistance:score.traceIntersections!==bestScore.traceIntersections?score.traceIntersections<bestScore.traceIntersections:score.pathLength<bestScore.pathLength},getLabelHugDistance=(tracePath,obstacleLabel)=>{let bounds=getRectBounds(obstacleLabel.center,obstacleLabel.width,obstacleLabel.height),distance72=0;for(let point6 of tracePath)distance72+=getPointDistanceFromRect(point6,bounds);return distance72},getPointDistanceFromRect=(point6,rect)=>{let dx3=Math.max(rect.minX-point6.x,0,point6.x-rect.maxX),dy3=Math.max(rect.minY-point6.y,0,point6.y-rect.maxY);return dx3+dy3},countCrossingsWithOtherTraces=params=>{let{trace,outputTraces}=params,crossingCount=0;for(let otherTrace of outputTraces)otherTrace.mspPairId!==trace.mspPairId&&otherTrace.globalConnNetId!==trace.globalConnNetId&&(crossingCount+=countPathIntersections(trace.tracePath,otherTrace.tracePath));return crossingCount},scoreSolutionTracePath=params=>{let{traces,outputTraces,chipObstacles}=params,chipEdgeRuns=0,traceCrossings=0;for(let trace of traces)doesPathRunAlongChipBoundary(trace.tracePath,chipObstacles)&&(chipEdgeRuns+=1),traceCrossings+=countCrossingsWithOtherTraces({trace,outputTraces});return{chipEdgeRuns,traceCrossings}},CANDIDATE_SELECTED_COLOR="blue",CANDIDATE_REJECTED_COLOR="red",visualizeExample28Solver=state2=>{let graphics=visualizeInputProblem2(state2.inputProblem);return drawTraces(graphics,state2),drawNetLabels(graphics,state2),state2.solved||(drawCurrentCandidates(graphics,state2.currentCandidateResults),drawCurrentOverlap(graphics,state2)),graphics},drawTraces=(graphics,state2)=>{for(let trace of state2.outputTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels=(graphics,state2)=>{for(let label of state2.outputNetLabelPlacements){let color=getColorFromString2(label.globalConnNetId,.35);graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:color,strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
651
651
  globalConnNetId: ${label.globalConnNetId}`}),graphics.points.push({...label.anchorPoint,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
652
652
  orientation: ${label.orientation}`})}},drawCurrentCandidates=(graphics,candidateResults)=>{for(let candidate of candidateResults){let scoreLabel=candidate.score?`
653
653
  label intersections: ${candidate.score.labelIntersections}
654
654
  trace intersections: ${candidate.score.traceIntersections}`:"";graphics.lines.push({points:candidate.path,strokeColor:candidate.selected?CANDIDATE_SELECTED_COLOR:CANDIDATE_REJECTED_COLOR,strokeDash:candidate.selected?void 0:"4 2",label:`${candidate.selected?"selected":candidate.status} reroute${scoreLabel}`})}},drawCurrentOverlap=(graphics,state2)=>{if(!state2.currentOverlap)return;let label=state2.currentOverlap.label;graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:"rgba(255, 0, 0, 0.2)",strokeColor:CANDIDATE_REJECTED_COLOR,label:`overlap target
655
- ${label.netId??label.globalConnNetId}`})},LABEL_OUTWARD_STEP=.1,LABEL_MAX_OUTWARD_STEPS=10,LABEL_TRACE_CLEARANCE=.1,isScoreBetter=(rerouteScore,labelMoveScore)=>rerouteScore?rerouteScore.chipEdgeRuns!==labelMoveScore.chipEdgeRuns?rerouteScore.chipEdgeRuns<labelMoveScore.chipEdgeRuns:rerouteScore.traceCrossings<labelMoveScore.traceCrossings:!1,Example28Solver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"outputTraces");__publicField(this,"outputNetLabelPlacements");__publicField(this,"queuedOverlaps",[]);__publicField(this,"currentOverlap",null);__publicField(this,"currentCandidateResults",[]);__publicField(this,"chipObstacles");__publicField(this,"pinMap");this.inputProblem=params.inputProblem,this.traces=params.traces,this.netLabelPlacements=params.netLabelPlacements,this.outputTraces=[...params.traces],this.outputNetLabelPlacements=[...params.netLabelPlacements],this.chipObstacles=getObstacleRects(params.inputProblem),this.pinMap=getPinMap(params.inputProblem),this.initializeQueuedOverlaps(),this.currentOverlap=this.queuedOverlaps[0]??null}getConstructorParams(){return{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.netLabelPlacements}}_step(){let overlap=this.queuedOverlaps.shift();if(!overlap){this.finish();return}if(!this.isOverlapStillPresent(overlap)){this.currentOverlap=overlap,this.currentCandidateResults=[];return}this.rerouteOverlappingTrace(overlap)}finish(){this.currentOverlap=null,this.currentCandidateResults=[],this.solved=!0}initializeQueuedOverlaps(){let queuedOverlaps=[],seenPairs=new Set;for(let overlap of this.getTraceLabelOverlaps()){if(!this.shouldRerouteOverlap(overlap))continue;let key=this.getOverlapKey(overlap);seenPairs.has(key)||(seenPairs.add(key),queuedOverlaps.push(overlap))}this.queuedOverlaps=queuedOverlaps}getTraceLabelOverlaps(){return detectTraceLabelOverlap({traces:this.outputTraces,netLabels:this.outputNetLabelPlacements})}shouldRerouteOverlap(overlap){return this.isXFacingLabel(overlap.label)&&!this.hasExplicitOrientationConstraint(overlap.label)}isXFacingLabel(label){return label.orientation==="x+"||label.orientation==="x-"}hasExplicitOrientationConstraint(label){let effectiveNetId=label.netId??label.globalConnNetId;return Object.hasOwn(this.inputProblem.availableNetLabelOrientations,effectiveNetId)}getOverlapKey(overlap){let labelNetId=overlap.label.netId??overlap.label.globalConnNetId;return`${overlap.trace.mspPairId}:${labelNetId}:${overlap.label.anchorPoint.x}:${overlap.label.anchorPoint.y}`}isOverlapStillPresent(overlap){let currentTrace=this.getCurrentTrace(overlap.trace);return currentTrace?detectTraceLabelOverlap({traces:[currentTrace],netLabels:[overlap.label]}).length>0:!1}getCurrentTrace(trace){return this.outputTraces.find(t53=>t53.mspPairId===trace.mspPairId)}rerouteOverlappingTrace(overlap){this.currentOverlap=overlap,this.currentCandidateResults=[];let traceIndex=this.outputTraces.findIndex(trace=>trace.mspPairId===overlap.trace.mspPairId);if(traceIndex===-1)return;let currentTrace=this.outputTraces[traceIndex],labelMove=this.tryMoveLabelOutward(overlap.label),rerouteResult=findBestReroutePath({trace:currentTrace,obstacleLabel:overlap.label,inputProblem:this.inputProblem,outputTraces:this.outputTraces,outputNetLabelPlacements:this.outputNetLabelPlacements,chipObstacles:this.chipObstacles});this.currentCandidateResults=rerouteResult.candidateResults;let rerouteScore=null;if(rerouteResult.bestPath&&(rerouteScore=scoreSolutionTracePath({traces:[{...currentTrace,tracePath:rerouteResult.bestPath}],outputTraces:this.outputTraces,chipObstacles:this.chipObstacles})),labelMove){let labelMoveScore=scoreSolutionTracePath({traces:[labelMove.connectorTrace,currentTrace],outputTraces:this.outputTraces,chipObstacles:this.chipObstacles});if(!isScoreBetter(rerouteScore,labelMoveScore)){this.outputNetLabelPlacements[labelMove.labelIndex]=labelMove.movedLabel,this.outputTraces.push(labelMove.connectorTrace);return}}if(!rerouteResult.bestPath)return;let originalTracePath=currentTrace.tracePath;this.outputTraces[traceIndex]={...currentTrace,tracePath:rerouteResult.bestPath},this.outputNetLabelPlacements=moveAttachedLabelsToReroutedTrace({trace:currentTrace,originalTracePath,reroutedTracePath:rerouteResult.bestPath,netLabelPlacements:this.outputNetLabelPlacements})}tryMoveLabelOutward(labelToMove){let labelIndex=this.outputNetLabelPlacements.findIndex(label2=>label2.globalConnNetId===labelToMove.globalConnNetId&&label2.anchorPoint.x===labelToMove.anchorPoint.x&&label2.anchorPoint.y===labelToMove.anchorPoint.y&&label2.pinIds.join(",")===labelToMove.pinIds.join(","));if(labelIndex===-1)return null;let label=this.outputNetLabelPlacements[labelIndex];if(label.mspConnectionPairIds.length>0||label.pinIds.length!==1||this.outputNetLabelPlacements.filter(otherLabel=>otherLabel.globalConnNetId===label.globalConnNetId).length!==1)return null;let outward=dir(label.orientation);if(outward.x===0&&outward.y===0)return null;for(let step=1;step<=LABEL_MAX_OUTWARD_STEPS;step++){let distance52=step*LABEL_OUTWARD_STEP,candidate={...label,anchorPoint:{x:label.anchorPoint.x+outward.x*distance52,y:label.anchorPoint.y+outward.y*distance52},center:{x:label.center.x+outward.x*distance52,y:label.center.y+outward.y*distance52}},candidateWithClearance={...candidate,width:candidate.width+LABEL_TRACE_CLEARANCE*2,height:candidate.height+LABEL_TRACE_CLEARANCE*2};if(detectTraceLabelOverlap({traces:this.outputTraces,netLabels:[candidateWithClearance]}).length>0)continue;let connectorTrace=createPortOnlyLabelConnectorTrace({label,movedLabel:candidate,pinMap:this.pinMap});if(!(detectTraceLabelOverlap({traces:[connectorTrace],netLabels:this.outputNetLabelPlacements}).length>0))return{labelIndex,movedLabel:candidate,connectorTrace}}return null}visualize(){return visualizeExample28Solver({inputProblem:this.inputProblem,outputTraces:this.outputTraces,outputNetLabelPlacements:this.outputNetLabelPlacements,solved:this.solved,currentOverlap:this.currentOverlap,currentCandidateResults:this.currentCandidateResults})}},getPortOnlyLabelConnectorMspPairId=label=>`port-only-label-connector-${label.globalConnNetId}-${label.pinIds[0]}`,createPortOnlyLabelConnectorTrace=({label,movedLabel,pinMap})=>{let mspPairId=getPortOnlyLabelConnectorMspPairId(label);return{mspPairId,dcConnNetId:label.dcConnNetId??label.globalConnNetId,globalConnNetId:label.globalConnNetId,userNetId:label.netId,pins:getTracePins(label,pinMap),tracePath:[label.anchorPoint,movedLabel.anchorPoint],mspConnectionPairIds:[mspPairId],pinIds:label.pinIds}},LABEL_SEARCH_STEP=.05,MAX_RECORDED_CANDIDATES=2e3,WICK_CLEARANCE=.001,EPS12=1e-9,TRACE_BOUNDARY_TOLERANCE=WICK_CLEARANCE+EPS12,CANDIDATE_SELECTED_COLOR2="blue",CANDIDATE_REJECTED_COLOR2="red",isYOrientation=orientation4=>orientation4==="y+"||orientation4==="y-",isXOrientation=orientation4=>orientation4==="x+"||orientation4==="x-",rectsOverlap2=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>EPS12&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>EPS12,rangesOverlap=(minA,maxA,minB,maxB)=>Math.min(maxA,maxB)-Math.max(minA,minB)>EPS12,traceCrossesBoundsInterior=(bounds,traceMap)=>{for(let trace of Object.values(traceMap)){let points=trace.tracePath;for(let i6=0;i6<points.length-1;i6++)if(segmentCrossesBoundsInterior(points[i6],points[i6+1],bounds))return!0}return!1},segmentCrossesBoundsInterior=(p12,p22,bounds)=>{let interiorBounds={minX:bounds.minX+TRACE_BOUNDARY_TOLERANCE,minY:bounds.minY+TRACE_BOUNDARY_TOLERANCE,maxX:bounds.maxX-TRACE_BOUNDARY_TOLERANCE,maxY:bounds.maxY-TRACE_BOUNDARY_TOLERANCE};return interiorBounds.minX>=interiorBounds.maxX||interiorBounds.minY>=interiorBounds.maxY?!1:sameX2(p12,p22)?p12.x<=interiorBounds.minX+EPS12||p12.x>=interiorBounds.maxX-EPS12?!1:rangesOverlap(Math.min(p12.y,p22.y),Math.max(p12.y,p22.y),interiorBounds.minY,interiorBounds.maxY):sameY2(p12,p22)?p12.y<=interiorBounds.minY+EPS12||p12.y>=interiorBounds.maxY-EPS12?!1:rangesOverlap(Math.min(p12.x,p22.x),Math.max(p12.x,p22.x),interiorBounds.minX,interiorBounds.maxX):!1},tracePathIntersectsBounds=(tracePath,bounds)=>{for(let i6=0;i6<tracePath.length-1;i6++)if(segmentIntersectsRect2(tracePath[i6],tracePath[i6+1],bounds))return!0;return!1},getSideDistances=(point6,bounds)=>[["left",Math.abs(point6.x-bounds.minX)],["right",Math.abs(point6.x-bounds.maxX)],["bottom",Math.abs(point6.y-bounds.minY)],["top",Math.abs(point6.y-bounds.maxY)]],getConnectorTracePath=(source,target,orientation4)=>simplifyOrthogonalPath(isYOrientation(orientation4)?[source,{x:target.x,y:source.y},target]:[source,{x:source.x,y:target.y},target]),simplifyOrthogonalPath=path=>{let deduped=path.filter((point6,index)=>index===0||!pointsEqual22(point6,path[index-1]));if(deduped.length<3)return deduped;let simplified=[deduped[0]];for(let i6=1;i6<deduped.length-1;i6++){let prev=simplified[simplified.length-1],point6=deduped[i6],next2=deduped[i6+1];sameX2(prev,point6)&&sameX2(point6,next2)||sameY2(prev,point6)&&sameY2(point6,next2)||simplified.push(point6)}return simplified.push(deduped[deduped.length-1]),simplified},pointsEqual22=(a6,b6)=>sameX2(a6,b6)&&sameY2(a6,b6),sameX2=(a6,b6)=>Math.abs(a6.x-b6.x)<=EPS12,sameY2=(a6,b6)=>Math.abs(a6.y-b6.y)<=EPS12,getMaxSearchDistance=inputProblem=>Math.max(...inputProblem.chips.map(chip=>chip.width),1)*3,isPortOnlyLabel=label=>label.mspConnectionPairIds.length===0,orderRoutedLabelsBeforeOverlappingPortLabels=({labelIndices,netLabelPlacements})=>{let orderedLabelIndices=[...labelIndices];for(let routedLabelIndex of labelIndices){let routedLabel=netLabelPlacements[routedLabelIndex];if(isPortOnlyLabel(routedLabel))continue;let routedBounds=getRectBounds(routedLabel.center,routedLabel.width,routedLabel.height),blockingPosition=orderedLabelIndices.findIndex(labelIndex=>{let portOnlyLabel=netLabelPlacements[labelIndex];if(!isPortOnlyLabel(portOnlyLabel)||portOnlyLabel.globalConnNetId===routedLabel.globalConnNetId)return!1;let portOnlyBounds=getRectBounds(portOnlyLabel.center,portOnlyLabel.width,portOnlyLabel.height);return rectsOverlap2(routedBounds,portOnlyBounds)}),routedPosition=orderedLabelIndices.indexOf(routedLabelIndex);blockingPosition===-1||blockingPosition>routedPosition||(orderedLabelIndices.splice(routedPosition,1),orderedLabelIndices.splice(blockingPosition,0,routedLabelIndex))}return orderedLabelIndices},visualizeAvailableNetOrientationSolver=params=>{let graphics=visualizeInputProblem2(params.inputProblem);return ensureGraphicsArrays(graphics),drawTraces2(graphics,params.traces),drawNetLabels2(graphics,params.outputNetLabelPlacements),drawCurrentLabel(graphics,params.currentLabel,params.solved),drawCurrentCandidates2(graphics,params.currentCandidateResults,params.solved),graphics},drawTraces2=(graphics,traces)=>{for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels2=(graphics,labels)=>{for(let label of labels)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
655
+ ${label.netId??label.globalConnNetId}`})},LABEL_OUTWARD_STEP=.1,LABEL_MAX_OUTWARD_STEPS=10,LABEL_TRACE_CLEARANCE=.1,isScoreBetter=(rerouteScore,labelMoveScore)=>rerouteScore?rerouteScore.chipEdgeRuns!==labelMoveScore.chipEdgeRuns?rerouteScore.chipEdgeRuns<labelMoveScore.chipEdgeRuns:rerouteScore.traceCrossings<labelMoveScore.traceCrossings:!1,Example28Solver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"outputTraces");__publicField(this,"outputNetLabelPlacements");__publicField(this,"queuedOverlaps",[]);__publicField(this,"currentOverlap",null);__publicField(this,"currentCandidateResults",[]);__publicField(this,"chipObstacles");__publicField(this,"pinMap");this.inputProblem=params.inputProblem,this.traces=params.traces,this.netLabelPlacements=params.netLabelPlacements,this.outputTraces=[...params.traces],this.outputNetLabelPlacements=[...params.netLabelPlacements],this.chipObstacles=getObstacleRects(params.inputProblem),this.pinMap=getPinMap(params.inputProblem),this.initializeQueuedOverlaps(),this.currentOverlap=this.queuedOverlaps[0]??null}getConstructorParams(){return{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.netLabelPlacements}}_step(){let overlap=this.queuedOverlaps.shift();if(!overlap){this.finish();return}if(!this.isOverlapStillPresent(overlap)){this.currentOverlap=overlap,this.currentCandidateResults=[];return}this.rerouteOverlappingTrace(overlap)}finish(){this.currentOverlap=null,this.currentCandidateResults=[],this.solved=!0}initializeQueuedOverlaps(){let queuedOverlaps=[],seenPairs=new Set;for(let overlap of this.getTraceLabelOverlaps()){if(!this.shouldRerouteOverlap(overlap))continue;let key=this.getOverlapKey(overlap);seenPairs.has(key)||(seenPairs.add(key),queuedOverlaps.push(overlap))}this.queuedOverlaps=queuedOverlaps}getTraceLabelOverlaps(){return detectTraceLabelOverlap({traces:this.outputTraces,netLabels:this.outputNetLabelPlacements})}shouldRerouteOverlap(overlap){return this.isXFacingLabel(overlap.label)&&!this.hasExplicitOrientationConstraint(overlap.label)}isXFacingLabel(label){return label.orientation==="x+"||label.orientation==="x-"}hasExplicitOrientationConstraint(label){let effectiveNetId=label.netId??label.globalConnNetId;return Object.hasOwn(this.inputProblem.availableNetLabelOrientations,effectiveNetId)}getOverlapKey(overlap){let labelNetId=overlap.label.netId??overlap.label.globalConnNetId;return`${overlap.trace.mspPairId}:${labelNetId}:${overlap.label.anchorPoint.x}:${overlap.label.anchorPoint.y}`}isOverlapStillPresent(overlap){let currentTrace=this.getCurrentTrace(overlap.trace);return currentTrace?detectTraceLabelOverlap({traces:[currentTrace],netLabels:[overlap.label]}).length>0:!1}getCurrentTrace(trace){return this.outputTraces.find(t53=>t53.mspPairId===trace.mspPairId)}rerouteOverlappingTrace(overlap){this.currentOverlap=overlap,this.currentCandidateResults=[];let traceIndex=this.outputTraces.findIndex(trace=>trace.mspPairId===overlap.trace.mspPairId);if(traceIndex===-1)return;let currentTrace=this.outputTraces[traceIndex],labelMove=this.tryMoveLabelOutward(overlap.label),rerouteResult=findBestReroutePath({trace:currentTrace,obstacleLabel:overlap.label,inputProblem:this.inputProblem,outputTraces:this.outputTraces,outputNetLabelPlacements:this.outputNetLabelPlacements,chipObstacles:this.chipObstacles});this.currentCandidateResults=rerouteResult.candidateResults;let rerouteScore=null;if(rerouteResult.bestPath&&(rerouteScore=scoreSolutionTracePath({traces:[{...currentTrace,tracePath:rerouteResult.bestPath}],outputTraces:this.outputTraces,chipObstacles:this.chipObstacles})),labelMove){let labelMoveScore=scoreSolutionTracePath({traces:[labelMove.connectorTrace,currentTrace],outputTraces:this.outputTraces,chipObstacles:this.chipObstacles});if(!isScoreBetter(rerouteScore,labelMoveScore)){this.outputNetLabelPlacements[labelMove.labelIndex]=labelMove.movedLabel,this.outputTraces.push(labelMove.connectorTrace);return}}if(!rerouteResult.bestPath)return;let originalTracePath=currentTrace.tracePath;this.outputTraces[traceIndex]={...currentTrace,tracePath:rerouteResult.bestPath},this.outputNetLabelPlacements=moveAttachedLabelsToReroutedTrace({trace:currentTrace,originalTracePath,reroutedTracePath:rerouteResult.bestPath,netLabelPlacements:this.outputNetLabelPlacements})}tryMoveLabelOutward(labelToMove){let labelIndex=this.outputNetLabelPlacements.findIndex(label2=>label2.globalConnNetId===labelToMove.globalConnNetId&&label2.anchorPoint.x===labelToMove.anchorPoint.x&&label2.anchorPoint.y===labelToMove.anchorPoint.y&&label2.pinIds.join(",")===labelToMove.pinIds.join(","));if(labelIndex===-1)return null;let label=this.outputNetLabelPlacements[labelIndex];if(label.mspConnectionPairIds.length>0||label.pinIds.length!==1||this.outputNetLabelPlacements.filter(otherLabel=>otherLabel.globalConnNetId===label.globalConnNetId).length!==1)return null;let outward=dir(label.orientation);if(outward.x===0&&outward.y===0)return null;for(let step=1;step<=LABEL_MAX_OUTWARD_STEPS;step++){let distance72=step*LABEL_OUTWARD_STEP,candidate={...label,anchorPoint:{x:label.anchorPoint.x+outward.x*distance72,y:label.anchorPoint.y+outward.y*distance72},center:{x:label.center.x+outward.x*distance72,y:label.center.y+outward.y*distance72}},candidateWithClearance={...candidate,width:candidate.width+LABEL_TRACE_CLEARANCE*2,height:candidate.height+LABEL_TRACE_CLEARANCE*2};if(detectTraceLabelOverlap({traces:this.outputTraces,netLabels:[candidateWithClearance]}).length>0)continue;let connectorTrace=createPortOnlyLabelConnectorTrace({label,movedLabel:candidate,pinMap:this.pinMap});if(!(detectTraceLabelOverlap({traces:[connectorTrace],netLabels:this.outputNetLabelPlacements}).length>0))return{labelIndex,movedLabel:candidate,connectorTrace}}return null}visualize(){return visualizeExample28Solver({inputProblem:this.inputProblem,outputTraces:this.outputTraces,outputNetLabelPlacements:this.outputNetLabelPlacements,solved:this.solved,currentOverlap:this.currentOverlap,currentCandidateResults:this.currentCandidateResults})}},getPortOnlyLabelConnectorMspPairId=label=>`port-only-label-connector-${label.globalConnNetId}-${label.pinIds[0]}`,createPortOnlyLabelConnectorTrace=({label,movedLabel,pinMap})=>{let mspPairId=getPortOnlyLabelConnectorMspPairId(label);return{mspPairId,dcConnNetId:label.dcConnNetId??label.globalConnNetId,globalConnNetId:label.globalConnNetId,userNetId:label.netId,pins:getTracePins(label,pinMap),tracePath:[label.anchorPoint,movedLabel.anchorPoint],mspConnectionPairIds:[mspPairId],pinIds:label.pinIds}},LABEL_SEARCH_STEP=.05,MAX_RECORDED_CANDIDATES=2e3,WICK_CLEARANCE=.001,EPS12=1e-9,TRACE_BOUNDARY_TOLERANCE=WICK_CLEARANCE+EPS12,CANDIDATE_SELECTED_COLOR2="blue",CANDIDATE_REJECTED_COLOR2="red",isYOrientation=orientation4=>orientation4==="y+"||orientation4==="y-",isXOrientation=orientation4=>orientation4==="x+"||orientation4==="x-",rectsOverlap2=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>EPS12&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>EPS12,rangesOverlap=(minA,maxA,minB,maxB)=>Math.min(maxA,maxB)-Math.max(minA,minB)>EPS12,traceCrossesBoundsInterior=(bounds,traceMap)=>{for(let trace of Object.values(traceMap)){let points=trace.tracePath;for(let i6=0;i6<points.length-1;i6++)if(segmentCrossesBoundsInterior(points[i6],points[i6+1],bounds))return!0}return!1},segmentCrossesBoundsInterior=(p12,p22,bounds)=>{let interiorBounds={minX:bounds.minX+TRACE_BOUNDARY_TOLERANCE,minY:bounds.minY+TRACE_BOUNDARY_TOLERANCE,maxX:bounds.maxX-TRACE_BOUNDARY_TOLERANCE,maxY:bounds.maxY-TRACE_BOUNDARY_TOLERANCE};return interiorBounds.minX>=interiorBounds.maxX||interiorBounds.minY>=interiorBounds.maxY?!1:sameX2(p12,p22)?p12.x<=interiorBounds.minX+EPS12||p12.x>=interiorBounds.maxX-EPS12?!1:rangesOverlap(Math.min(p12.y,p22.y),Math.max(p12.y,p22.y),interiorBounds.minY,interiorBounds.maxY):sameY2(p12,p22)?p12.y<=interiorBounds.minY+EPS12||p12.y>=interiorBounds.maxY-EPS12?!1:rangesOverlap(Math.min(p12.x,p22.x),Math.max(p12.x,p22.x),interiorBounds.minX,interiorBounds.maxX):!1},tracePathIntersectsBounds=(tracePath,bounds)=>{for(let i6=0;i6<tracePath.length-1;i6++)if(segmentIntersectsRect2(tracePath[i6],tracePath[i6+1],bounds))return!0;return!1},getSideDistances=(point6,bounds)=>[["left",Math.abs(point6.x-bounds.minX)],["right",Math.abs(point6.x-bounds.maxX)],["bottom",Math.abs(point6.y-bounds.minY)],["top",Math.abs(point6.y-bounds.maxY)]],getConnectorTracePath=(source,target,orientation4)=>simplifyOrthogonalPath(isYOrientation(orientation4)?[source,{x:target.x,y:source.y},target]:[source,{x:source.x,y:target.y},target]),simplifyOrthogonalPath=path=>{let deduped=path.filter((point6,index)=>index===0||!pointsEqual22(point6,path[index-1]));if(deduped.length<3)return deduped;let simplified=[deduped[0]];for(let i6=1;i6<deduped.length-1;i6++){let prev=simplified[simplified.length-1],point6=deduped[i6],next2=deduped[i6+1];sameX2(prev,point6)&&sameX2(point6,next2)||sameY2(prev,point6)&&sameY2(point6,next2)||simplified.push(point6)}return simplified.push(deduped[deduped.length-1]),simplified},pointsEqual22=(a6,b6)=>sameX2(a6,b6)&&sameY2(a6,b6),sameX2=(a6,b6)=>Math.abs(a6.x-b6.x)<=EPS12,sameY2=(a6,b6)=>Math.abs(a6.y-b6.y)<=EPS12,getMaxSearchDistance=inputProblem=>Math.max(...inputProblem.chips.map(chip=>chip.width),1)*3,isPortOnlyLabel=label=>label.mspConnectionPairIds.length===0,orderRoutedLabelsBeforeOverlappingPortLabels=({labelIndices,netLabelPlacements})=>{let orderedLabelIndices=[...labelIndices];for(let routedLabelIndex of labelIndices){let routedLabel=netLabelPlacements[routedLabelIndex];if(isPortOnlyLabel(routedLabel))continue;let routedBounds=getRectBounds(routedLabel.center,routedLabel.width,routedLabel.height),blockingPosition=orderedLabelIndices.findIndex(labelIndex=>{let portOnlyLabel=netLabelPlacements[labelIndex];if(!isPortOnlyLabel(portOnlyLabel)||portOnlyLabel.globalConnNetId===routedLabel.globalConnNetId)return!1;let portOnlyBounds=getRectBounds(portOnlyLabel.center,portOnlyLabel.width,portOnlyLabel.height);return rectsOverlap2(routedBounds,portOnlyBounds)}),routedPosition=orderedLabelIndices.indexOf(routedLabelIndex);blockingPosition===-1||blockingPosition>routedPosition||(orderedLabelIndices.splice(routedPosition,1),orderedLabelIndices.splice(blockingPosition,0,routedLabelIndex))}return orderedLabelIndices},visualizeAvailableNetOrientationSolver=params=>{let graphics=visualizeInputProblem2(params.inputProblem);return ensureGraphicsArrays(graphics),drawTraces2(graphics,params.traces),drawNetLabels2(graphics,params.outputNetLabelPlacements),drawCurrentLabel(graphics,params.currentLabel,params.solved),drawCurrentCandidates2(graphics,params.currentCandidateResults,params.solved),graphics},drawTraces2=(graphics,traces)=>{for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels2=(graphics,labels)=>{for(let label of labels)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
656
656
  globalConnNetId: ${label.globalConnNetId}`}),graphics.points.push({x:label.anchorPoint.x,y:label.anchorPoint.y,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
657
657
  orientation: ${label.orientation}`})},drawCurrentLabel=(graphics,currentLabel,solved)=>{!currentLabel||solved||graphics.rects.push({center:currentLabel.center,width:currentLabel.width,height:currentLabel.height,fill:"rgba(255, 0, 0, 0.2)",strokeColor:CANDIDATE_REJECTED_COLOR2,label:`available orientation target
658
658
  ${currentLabel.netId??currentLabel.globalConnNetId}`})},drawCurrentCandidates2=(graphics,candidates,solved)=>{if(!solved)for(let candidate of candidates){let color=candidate.selected?CANDIDATE_SELECTED_COLOR2:CANDIDATE_REJECTED_COLOR2,distanceLabel=candidate.distance===void 0?"":`
@@ -661,13 +661,13 @@ outward distance: ${candidate.outwardDistance.toFixed(3)}`;graphics.rects.push({
661
661
  phase: ${candidate.phase}
662
662
  orientation: ${candidate.orientation}${distanceLabel}${outwardDistanceLabel}`}),graphics.points.push({x:candidate.anchorPoint.x,y:candidate.anchorPoint.y,color,label:`candidate anchor
663
663
  ${candidate.phase}
664
- ${candidate.orientation}`})}},ensureGraphicsArrays=graphics=>{graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.rects||(graphics.rects=[]),graphics.circles||(graphics.circles=[]),graphics.texts||(graphics.texts=[])},AvailableNetOrientationObstacleIndex=class{constructor(params){__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"labelIndex",null);__publicField(this,"traceSegmentIndex",null);__publicField(this,"traceSegments",[]);this.chipObstacleSpatialIndex=params.chipObstacleSpatialIndex,this.rebuild(params)}rebuild(params){this.labelIndex=this.buildLabelIndex(params.netLabelPlacements),this.traceSegments=this.getTraceSegments(params.traces),this.traceSegmentIndex=this.buildTraceSegmentIndex(this.traceSegments)}getLabelIndicesInBounds(bounds){return this.labelIndex?this.labelIndex.search(bounds.minX,bounds.minY,bounds.maxX,bounds.maxY):[]}getTraceSegmentsInBounds(bounds){if(!this.traceSegmentIndex)return[];let searchBounds=getPaddedBounds(bounds,EPS12);return this.traceSegmentIndex.search(searchBounds.minX,searchBounds.minY,searchBounds.maxX,searchBounds.maxY).map(segmentIndex=>this.traceSegments[segmentIndex])}getLabelIndicesNearTracePath(tracePath){let labelIndices=new Set;for(let pointIndex=0;pointIndex<tracePath.length-1;pointIndex++){let segmentBounds=getPaddedBounds(getSegmentBounds(tracePath[pointIndex],tracePath[pointIndex+1]),EPS12);for(let labelIndex of this.getLabelIndicesInBounds(segmentBounds))labelIndices.add(labelIndex)}return[...labelIndices].sort((a6,b6)=>a6-b6)}doesTracePathCrossChip(tracePath){for(let pointIndex=0;pointIndex<tracePath.length-1;pointIndex++){let start=tracePath[pointIndex],end=tracePath[pointIndex+1],nearbyChips=this.chipObstacleSpatialIndex.getChipsInBounds(getPaddedBounds(getSegmentBounds(start,end),EPS12));for(let chip of nearbyChips)if(segmentCrossesBoundsInterior(start,end,chip.bounds))return!0}return!1}doesTraceCrossBoundsInterior(bounds){for(let segment2 of this.getTraceSegmentsInBounds(bounds))if(segmentCrossesBoundsInterior(segment2.start,segment2.end,bounds))return!0;return!1}doesTraceIntersectBounds(params){for(let segment2 of this.getTraceSegmentsInBounds(params.bounds))if(segment2.trace.globalConnNetId!==params.excludedGlobalConnNetId&&segmentIntersectsRect2(segment2.start,segment2.end,params.bounds))return!0;return!1}buildLabelIndex(netLabelPlacements){if(netLabelPlacements.length===0)return null;let labelIndex=new Flatbush(netLabelPlacements.length);for(let label of netLabelPlacements)labelIndex.add(label.center.x-label.width/2,label.center.y-label.height/2,label.center.x+label.width/2,label.center.y+label.height/2);return labelIndex.finish(),labelIndex}getTraceSegments(traces){let traceSegments=[];for(let trace of traces)for(let pointIndex=0;pointIndex<trace.tracePath.length-1;pointIndex++)traceSegments.push({trace,start:trace.tracePath[pointIndex],end:trace.tracePath[pointIndex+1]});return traceSegments}buildTraceSegmentIndex(traceSegments){if(traceSegments.length===0)return null;let traceSegmentIndex=new Flatbush(traceSegments.length);for(let segment2 of traceSegments)traceSegmentIndex.add(Math.min(segment2.start.x,segment2.end.x),Math.min(segment2.start.y,segment2.end.y),Math.max(segment2.start.x,segment2.end.x),Math.max(segment2.start.y,segment2.end.y));return traceSegmentIndex.finish(),traceSegmentIndex}};function getSegmentBounds(start,end){return{minX:Math.min(start.x,end.x),minY:Math.min(start.y,end.y),maxX:Math.max(start.x,end.x),maxY:Math.max(start.y,end.y)}}function getPaddedBounds(bounds,padding){return{minX:bounds.minX-padding,minY:bounds.minY-padding,maxX:bounds.maxX+padding,maxY:bounds.maxY+padding}}var LABEL_TRACE_CLEARANCE2=.1,AvailableNetOrientationSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"outputNetLabelPlacements");__publicField(this,"queuedLabelIndices",[]);__publicField(this,"currentLabelIndex",null);__publicField(this,"currentLabel",null);__publicField(this,"currentCandidateResults",[]);__publicField(this,"crowdedPortOnlyLabelIndices",new Set);__publicField(this,"blockedStandaloneLabelIndex",null);__publicField(this,"blockedStandaloneLabelTargetAnchorX",null);__publicField(this,"traceMap");__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"maxSearchDistance");__publicField(this,"pinMap");__publicField(this,"obstacleIndex");this.inputProblem=params.inputProblem,this.traces=[...params.traces],this.netLabelPlacements=params.netLabelPlacements,this.outputNetLabelPlacements=[...params.netLabelPlacements],this.traceMap=Object.fromEntries(this.traces.map(trace=>[trace.mspPairId,trace])),this.pinMap=getPinMap(params.inputProblem),this.chipObstacleSpatialIndex=params.inputProblem._chipObstacleSpatialIndex??new ChipObstacleSpatialIndex(params.inputProblem.chips),this.maxSearchDistance=getMaxSearchDistance(params.inputProblem),this.obstacleIndex=new AvailableNetOrientationObstacleIndex({chipObstacleSpatialIndex:this.chipObstacleSpatialIndex,netLabelPlacements:this.outputNetLabelPlacements,traces:this.traces}),this.crowdedPortOnlyLabelIndices=this.getCrowdedPortOnlyLabelIndices(),this.queuedLabelIndices=this.getProcessableLabelIndices(),this.setCurrentLabel(this.queuedLabelIndices[0]??null)}getConstructorParams(){return{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.netLabelPlacements}}_step(){let labelIndex=this.queuedLabelIndices.shift();if(labelIndex===void 0){this.finish();return}this.processLabel(labelIndex)}getOutput(){return{traces:this.traces,netLabelPlacements:this.outputNetLabelPlacements}}getProcessableLabelIndices(){let indices=[];for(let i6=0;i6<this.outputNetLabelPlacements.length;i6++)this.shouldProcessLabel(this.outputNetLabelPlacements[i6],i6)&&indices.push(i6);this.sortCrowdedTopBankByPin(indices);let orderedIndices=orderRoutedLabelsBeforeOverlappingPortLabels({labelIndices:indices,netLabelPlacements:this.outputNetLabelPlacements}),blockedStandaloneLabelIndex=orderedIndices.find(index=>{let label=this.outputNetLabelPlacements[index],orientations=this.getAvailableOrientations(label);return this.isPortOnlyLabel(label)&&this.isStandaloneSinglePinNetLabel(label)&&orientations.length===1&&isYOrientation(orientations[0])&&this.labelIntersectsDifferentNetTrace(label)});if(blockedStandaloneLabelIndex===void 0)return orderedIndices;this.blockedStandaloneLabelIndex=blockedStandaloneLabelIndex,this.blockedStandaloneLabelTargetAnchorX=null;let blockedLabel=this.outputNetLabelPlacements[blockedStandaloneLabelIndex],requiredOrientation=this.getAvailableOrientations(blockedLabel)[0],chipSide=this.getChipSideForPoint(blockedLabel.anchorPoint),affectedSlots=[],labelsToOrder=[];for(let slot=0;slot<orderedIndices.length;slot++){let index=orderedIndices[slot],label=this.outputNetLabelPlacements[index],orientations=this.getAvailableOrientations(label);this.getChipSideForPoint(label.anchorPoint)===chipSide&&orientations.length===1&&orientations[0]===requiredOrientation&&(affectedSlots.push(slot),labelsToOrder.push(index))}labelsToOrder.sort((a6,b6)=>{let aY2=this.outputNetLabelPlacements[a6].anchorPoint.y,bY2=this.outputNetLabelPlacements[b6].anchorPoint.y;return requiredOrientation==="y+"?bY2-aY2:aY2-bY2});let blockedLabelWidth=getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:blockedLabel.netId,pinIds:blockedLabel.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(blockedLabel)}),columnLabelIndex;if(blockedLabelWidth!==void 0&&(columnLabelIndex=labelsToOrder.find(index=>{if(index===blockedStandaloneLabelIndex)return!1;let label=this.outputNetLabelPlacements[index];return getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)})===blockedLabelWidth})),columnLabelIndex!==void 0){let columnLabel=this.outputNetLabelPlacements[columnLabelIndex];this.blockedStandaloneLabelTargetAnchorX=this.getSearchStartAnchor(columnLabel,requiredOrientation).x}for(let i6=0;i6<affectedSlots.length;i6++)orderedIndices[affectedSlots[i6]]=labelsToOrder[i6];return orderedIndices}sortCrowdedTopBankByPin(indices){let slotsByChip=new Map;for(let slot=0;slot<indices.length;slot++){let labelIndex=indices[slot];if(!this.crowdedPortOnlyLabelIndices.has(labelIndex))continue;let label=this.outputNetLabelPlacements[labelIndex];if(this.getChipSideForPoint(label.anchorPoint)!=="top")continue;let pin=this.pinMap[label.pinIds[0]];if(!pin)continue;let slots=slotsByChip.get(pin.chipId)??[];slots.push(slot),slotsByChip.set(pin.chipId,slots)}for(let slots of slotsByChip.values()){let labelIndices=slots.map(slot=>indices[slot]).sort((a6,b6)=>{let aPin=this.pinMap[this.outputNetLabelPlacements[a6].pinIds[0]],bPin=this.pinMap[this.outputNetLabelPlacements[b6].pinIds[0]];return aPin.x-bPin.x});for(let position4=0;position4<slots.length;position4++)indices[slots[position4]]=labelIndices[position4]}}shouldProcessLabel(label,labelIndex){let orientations=this.getAvailableOrientations(label);if(orientations.length===0)return!1;if(!orientations.includes(label.orientation))return!0;if(!this.crowdedPortOnlyLabelIndices.has(labelIndex))return!1;let bounds=getRectBounds(label.center,label.width,label.height);return this.outputNetLabelPlacements.some((otherLabel,otherIndex)=>otherIndex===labelIndex||otherLabel.globalConnNetId===label.globalConnNetId?!1:rectsOverlap2(bounds,getRectBounds(otherLabel.center,otherLabel.width,otherLabel.height)))}getCrowdedPortOnlyLabelIndices(){let labelIndicesByChipAndSide=new Map;for(let i6=0;i6<this.outputNetLabelPlacements.length;i6++){let label=this.outputNetLabelPlacements[i6];if(!this.isPortOnlyLabel(label)||!this.isStandaloneSinglePinNetLabel(label)||this.getAvailableOrientations(label).length===0)continue;let pin=this.pinMap[label.pinIds[0]];if(!pin)continue;let chipSide=this.getChipSideForPoint(label.anchorPoint);if(!chipSide)continue;let labelIndicesBySide=labelIndicesByChipAndSide.get(pin.chipId)??new Map,labelIndices=labelIndicesBySide.get(chipSide)??[];labelIndices.push(i6),labelIndicesBySide.set(chipSide,labelIndices),labelIndicesByChipAndSide.set(pin.chipId,labelIndicesBySide)}let crowdedIndices=new Set;for(let labelIndicesBySide of labelIndicesByChipAndSide.values())for(let labelIndices of labelIndicesBySide.values()){let hasWrongOrientation=labelIndices.some(index=>{let label=this.outputNetLabelPlacements[index];return!this.getAvailableOrientations(label).includes(label.orientation)}),hasOverlap=labelIndices.some((index,position4)=>{let label=this.outputNetLabelPlacements[index],bounds=getRectBounds(label.center,label.width,label.height);return labelIndices.slice(position4+1).some(otherIndex=>{let other=this.outputNetLabelPlacements[otherIndex];return rectsOverlap2(bounds,getRectBounds(other.center,other.width,other.height))})});if(!(!hasWrongOrientation||!hasOverlap))for(let index of labelIndices)crowdedIndices.add(index)}return crowdedIndices}processLabel(labelIndex){let label=this.outputNetLabelPlacements[labelIndex];this.setCurrentLabel(labelIndex),this.currentCandidateResults=[];let candidate=this.findCorrectedCandidate(label,labelIndex);candidate&&this.applyCandidate(label,candidate,labelIndex)}applyCandidate(label,candidate,labelIndex){this.outputNetLabelPlacements[labelIndex]={...label,...toNetLabelPlacementPatch(candidate)},this.addConnectorTrace(label,candidate,labelIndex),this.obstacleIndex.rebuild({netLabelPlacements:this.outputNetLabelPlacements,traces:this.traces})}addConnectorTrace(label,candidate,labelIndex){if(candidate.phase==="trace-anchor")return;let tracePath=this.getCandidateConnectorTrace(label,candidate,labelIndex);if(tracePath.length<2)return;let mspPairId=`available-net-orientation-${labelIndex}-${label.netId??label.globalConnNetId}`,connectorTrace={mspPairId,dcConnNetId:label.dcConnNetId??label.globalConnNetId,globalConnNetId:label.globalConnNetId,userNetId:label.netId,pins:getTracePins(label,this.pinMap),tracePath,mspConnectionPairIds:[mspPairId],pinIds:label.pinIds};this.traces.push(connectorTrace),this.traceMap[mspPairId]=connectorTrace}finish(){this.currentLabelIndex=null,this.currentLabel=null,this.currentCandidateResults=[],this.solved=!0}setCurrentLabel(labelIndex){this.currentLabelIndex=labelIndex,this.currentLabel=labelIndex===null?null:this.outputNetLabelPlacements[labelIndex]}findCorrectedCandidate(label,labelIndex){let orientations=this.getAvailableOrientations(label),requiredOrientation=orientations[0];if(this.crowdedPortOnlyLabelIndices.has(labelIndex)&&this.getChipSideForPoint(label.anchorPoint)==="top"&&isYOrientation(requiredOrientation)){let topFanoutCandidate=this.findValidCrowdedTopVerticalFanoutCandidate(label,labelIndex,requiredOrientation);if(topFanoutCandidate)return topFanoutCandidate}let netConnection=this.inputProblem.netConnections.find(connection=>connection.netId===label.netId),isTwoPinNet=netConnection?.pinIds.length===2,isDistanceSplitVerticalRail=(netConnection?.pinIds.length??0)>2&&isYOrientation(requiredOrientation)&&this.hasPortOnlyLabelOnSameNet(label),isPairedSameSidePowerRail=isYOrientation(requiredOrientation)&&this.hasOppositeVerticalRailOnSameChipSide(label,requiredOrientation);if(orientations.length===1&&isYOrientation(requiredOrientation)&&this.isOutwardHorizontalFallback(label)&&this.hasTraceContinuingInOrientation(label,requiredOrientation)&&(isDistanceSplitVerticalRail||isPairedSameSidePowerRail)){let traceAnchorCandidate2=this.findValidOutwardTraceAnchorCandidate(label,requiredOrientation,labelIndex);if(traceAnchorCandidate2)return traceAnchorCandidate2}if(isTwoPinNet&&orientations.length===1&&isYOrientation(requiredOrientation)&&this.hasTraceContinuingInOrientation(label,requiredOrientation)){let alignedCandidate=this.findValidCandidateInShiftColumn({label,labelIndex,orientation:requiredOrientation,direction:dir(requiredOrientation),baseAnchor:this.getWickOffsetAnchor(label.anchorPoint,requiredOrientation),maxSearchDistance:this.maxSearchDistance,outwardDistance:0,stopOnTraceCollision:!1});if(alignedCandidate)return alignedCandidate}let rotatedCandidate=this.findValidRotatedCandidate(label,labelIndex,orientations);if(rotatedCandidate)return rotatedCandidate;let traceAnchorCandidate=this.findValidTraceAnchorCandidate(label,orientations[0],labelIndex);if(traceAnchorCandidate)return traceAnchorCandidate;let shiftedCandidate=this.findValidShiftedCandidate(label,orientations[0],labelIndex);return shiftedCandidate||this.findValidLateralShiftedCandidate(label,orientations[0],labelIndex)}findValidCrowdedTopVerticalFanoutCandidate(label,labelIndex,orientation4){let pin=this.pinMap[label.pinIds[0]],chip=pin?this.chipObstacleSpatialIndex.chips.find(candidate=>candidate.chipId===pin.chipId):void 0;if(!chip)return null;let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),nextPinToRight=this.outputNetLabelPlacements.map((otherLabel,index)=>({index,pin:this.pinMap[otherLabel.pinIds[0]]})).filter(({index,pin:otherPin})=>this.crowdedPortOnlyLabelIndices.has(index)&&otherPin?.chipId===pin.chipId&&otherPin.x>pin.x+EPS12).sort((a6,b6)=>a6.pin.x-b6.pin.x)[0]?.pin;if(orientation4==="y-"&&nextPinToRight)return null;let anchorX=orientation4==="y-"?Math.max(label.anchorPoint.x+LABEL_SEARCH_STEP,chip.bounds.maxX+width/2+LABEL_TRACE_CLEARANCE2):Math.min(label.anchorPoint.x,(nextPinToRight?.x??chip.bounds.maxX)-LABEL_SEARCH_STEP-width/2),highestPlacedLabelY=chip.bounds.maxY,lowestUpFacingLabelY=Number.POSITIVE_INFINITY,highestUpFacingLabelY=Number.NEGATIVE_INFINITY;for(let index=0;index<this.outputNetLabelPlacements.length;index++){if(index===labelIndex||!this.crowdedPortOnlyLabelIndices.has(index)||this.queuedLabelIndices.includes(index))continue;let placedLabel=this.outputNetLabelPlacements[index],placedBounds=getRectBounds(placedLabel.center,placedLabel.width,placedLabel.height);highestPlacedLabelY=Math.max(highestPlacedLabelY,placedBounds.maxY),placedLabel.orientation==="y+"&&(lowestUpFacingLabelY=Math.min(lowestUpFacingLabelY,placedBounds.minY),highestUpFacingLabelY=Math.max(highestUpFacingLabelY,placedBounds.maxY))}let stackedAnchorY=highestPlacedLabelY+LABEL_SEARCH_STEP+(orientation4==="y-"?height:0),centeredAnchorY=Number.isFinite(lowestUpFacingLabelY)&&Number.isFinite(highestUpFacingLabelY)?(lowestUpFacingLabelY+highestUpFacingLabelY)/2:stackedAnchorY,anchorYs=orientation4==="y-"?[centeredAnchorY,stackedAnchorY]:[stackedAnchorY];for(let anchorY of anchorYs){if(anchorY-label.anchorPoint.y>this.maxSearchDistance+EPS12)continue;let candidate=this.createCandidate(label,{x:anchorX,y:anchorY},orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,"lateral-shift",anchorY-label.anchorPoint.y,anchorX-label.anchorPoint.x);if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}return null}hasTraceContinuingInOrientation(label,orientation4){let direction2=dir(orientation4);return Object.values(this.traceMap).some(trace=>{if(trace.globalConnNetId!==label.globalConnNetId)return!1;let path=trace.tracePath;return path.some((point6,pointIndex)=>Math.abs(point6.x-label.anchorPoint.x)>EPS12||Math.abs(point6.y-label.anchorPoint.y)>EPS12?!1:[path[pointIndex-1],path[pointIndex+1]].some(neighbor=>neighbor&&Math.abs(neighbor.x-point6.x)<=EPS12&&(neighbor.y-point6.y)*direction2.y>EPS12))})}findValidRotatedCandidate(label,labelIndex,orientations){for(let orientation4 of orientations){let candidate=this.createCandidate(label,this.getSearchStartAnchor(label,orientation4),orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,"rotate");if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}return null}findValidTraceAnchorCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),candidatePoints=this.getTraceAnchorCandidatePoints(label,orientation4).sort((a6,b6)=>{let aAlongDirection=a6.x*direction2.x+a6.y*direction2.y;return b6.x*direction2.x+b6.y*direction2.y-aAlongDirection});for(let anchorPoint of candidatePoints){let candidate=this.createCandidate(label,anchorPoint,orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,"trace-anchor");if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}return null}findValidOutwardTraceAnchorCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),candidatePoints=this.getTraceAnchorCandidatePoints(label,orientation4).sort((a6,b6)=>{let aAlongDirection=a6.x*direction2.x+a6.y*direction2.y;return b6.x*direction2.x+b6.y*direction2.y-aAlongDirection});for(let connectorSource of candidatePoints){let preservedColumnAnchor=this.getSearchStartAnchor(label,orientation4),preservedColumnCandidate=this.createCandidate(label,{x:preservedColumnAnchor.x,y:connectorSource.y},orientation4,connectorSource),preservedColumnResult=this.evaluateCandidate(preservedColumnCandidate,label,labelIndex,"outward-trace-anchor");if(this.recordCandidateResult(preservedColumnResult),preservedColumnResult.status==="valid")return preservedColumnResult.selected=!0,preservedColumnResult;let outwardDirection=this.getPerpendicularOutwardDirection(connectorSource,orientation4);if(!(outwardDirection.x===0&&outwardDirection.y===0))for(let distance52=LABEL_SEARCH_STEP;distance52<=this.maxSearchDistance+EPS12;distance52+=LABEL_SEARCH_STEP){let anchorPoint={x:connectorSource.x+outwardDirection.x*distance52,y:connectorSource.y+outwardDirection.y*distance52},candidate=this.createCandidate(label,anchorPoint,orientation4,connectorSource),result=this.evaluateCandidate(candidate,label,labelIndex,"outward-trace-anchor",distance52);if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}}return null}getTraceAnchorCandidatePoints(label,orientation4){let seen=new Set,points=[],connectedTraceIds=new Set(label.mspConnectionPairIds??[]);if(isYOrientation(orientation4)){let connectedPinIds=new Set;for(let traceId of connectedTraceIds)for(let pinId of this.traceMap[traceId]?.pinIds??[])connectedPinIds.add(pinId);let foundConnectedTrace=!0;for(;foundConnectedTrace;){foundConnectedTrace=!1;for(let trace of Object.values(this.traceMap)){if(connectedTraceIds.has(trace.mspPairId)||trace.mspPairId.startsWith("available-net-orientation-")||trace.globalConnNetId!==label.globalConnNetId||!trace.pinIds.some(pinId=>connectedPinIds.has(pinId)))continue;let connectedTraces=[...connectedTraceIds].flatMap(traceId=>{let connectedTrace=this.traceMap[traceId];return connectedTrace?[connectedTrace]:[]});if(this.sharesVerticalRailWithAny(trace,connectedTraces)){connectedTraceIds.add(trace.mspPairId);for(let pinId of trace.pinIds)connectedPinIds.add(pinId);foundConnectedTrace=!0}}}}for(let traceId of connectedTraceIds){let trace=this.traceMap[traceId];if(trace)for(let point6 of trace.tracePath){let key=`${point6.x.toFixed(9)},${point6.y.toFixed(9)}`;seen.has(key)||(seen.add(key),points.push(point6))}}return points}sharesVerticalRailWithAny(trace,otherTraces){let verticalRailXs=new Set;for(let otherTrace of otherTraces)for(let i6=0;i6<otherTrace.tracePath.length-1;i6++){let start=otherTrace.tracePath[i6],end=otherTrace.tracePath[i6+1];Math.abs(start.x-end.x)<=EPS12&&Math.abs(start.y-end.y)>EPS12&&verticalRailXs.add(start.x)}for(let i6=0;i6<trace.tracePath.length-1;i6++){let start=trace.tracePath[i6],end=trace.tracePath[i6+1];if(Math.abs(start.x-end.x)<=EPS12&&Math.abs(start.y-end.y)>EPS12&&[...verticalRailXs].some(x6=>Math.abs(x6-start.x)<=EPS12))return!0}return!1}getAvailableOrientations(label){let effectiveNetId=label.netId??label.globalConnNetId;return this.inputProblem.availableNetLabelOrientations[effectiveNetId]??[]}findValidShiftedCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),initialBaseAnchor=this.getSearchStartAnchor(label,orientation4),outwardDirection=this.getPerpendicularOutwardDirection(label.anchorPoint,orientation4),maxSearchDistance=this.getSearchDistanceLimit(label,orientation4),maxOutwardDistance=outwardDirection.x===0&&outwardDirection.y===0?0:this.maxSearchDistance;for(let outwardDistance=0;outwardDistance<=maxOutwardDistance+EPS12;outwardDistance+=LABEL_SEARCH_STEP){let baseAnchor={x:initialBaseAnchor.x+outwardDirection.x*outwardDistance,y:initialBaseAnchor.y+outwardDirection.y*outwardDistance},candidate=this.findValidCandidateInShiftColumn({label,labelIndex,orientation:orientation4,direction:direction2,baseAnchor,maxSearchDistance,outwardDistance});if(candidate)return candidate}return null}findValidLateralShiftedCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),initialBaseAnchor=this.getSearchStartAnchor(label,orientation4),lateralDir={x:isYOrientation(orientation4)?1:0,y:isXOrientation(orientation4)?1:0},maxSteps=Math.ceil(this.maxSearchDistance/LABEL_SEARCH_STEP);for(let step=1;step<=maxSteps;step++)for(let sign of[-1,1]){let lateralOffset=sign*step*LABEL_SEARCH_STEP,baseAnchor={x:initialBaseAnchor.x+lateralDir.x*lateralOffset,y:initialBaseAnchor.y+lateralDir.y*lateralOffset},maxSearchDistance=this.getLateralColumnMaxDistance(label,orientation4,baseAnchor),candidate=this.findValidCandidateInShiftColumn({label,labelIndex,orientation:orientation4,direction:direction2,baseAnchor,maxSearchDistance,outwardDistance:lateralOffset,phase:"lateral-shift"});if(candidate)return candidate}return null}findValidCandidateInShiftColumn(params){let{label,labelIndex,orientation:orientation4,direction:direction2,baseAnchor,maxSearchDistance,outwardDistance,phase="shift",stopOnTraceCollision=!0}=params;for(let distance52=LABEL_SEARCH_STEP;distance52<=maxSearchDistance+EPS12;distance52+=LABEL_SEARCH_STEP){let anchorPoint={x:baseAnchor.x+direction2.x*distance52,y:baseAnchor.y+direction2.y*distance52},candidate=this.createCandidate(label,anchorPoint,orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,phase,distance52,outwardDistance);if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result;if(stopOnTraceCollision&&result.status==="trace-collision")break}return null}evaluateCandidate(candidate,label,labelIndex,phase,distance52,outwardDistance){return{...candidate,phase,distance:distance52,outwardDistance,selected:!1,status:this.getCandidateStatus({candidate,label,labelIndex,phase})}}recordCandidateResult(candidate){this.stats.candidateEvaluations=(this.stats.candidateEvaluations??0)+1,this.currentCandidateResults.length<MAX_RECORDED_CANDIDATES?this.currentCandidateResults.push(candidate):candidate.status==="valid"&&(this.currentCandidateResults[MAX_RECORDED_CANDIDATES-1]=candidate),this.stats.maxRecordedCandidates=Math.max(this.stats.maxRecordedCandidates??0,this.currentCandidateResults.length)}getCandidateConnectorTrace(label,candidate,labelIndex){if(this.crowdedPortOnlyLabelIndices.has(labelIndex)&&this.getChipSideForPoint(label.anchorPoint)==="top"&&isYOrientation(candidate.orientation))return simplifyOrthogonalPath([label.anchorPoint,{x:label.anchorPoint.x,y:candidate.anchorPoint.y},candidate.anchorPoint]);if(candidate.phase==="lateral-shift"){let chipOutwardDir=this.crowdedPortOnlyLabelIndices.has(labelIndex)?this.getChipOutwardDirection(label.anchorPoint):(()=>{let orientDir=dir(candidate.orientation);return{x:-orientDir.x,y:-orientDir.y}})(),kickedSource={x:label.anchorPoint.x+chipOutwardDir.x*LABEL_SEARCH_STEP,y:label.anchorPoint.y+chipOutwardDir.y*LABEL_SEARCH_STEP};return simplifyOrthogonalPath([label.anchorPoint,...getConnectorTracePath(kickedSource,candidate.anchorPoint,candidate.orientation)])}return getConnectorTracePath(candidate.connectorSource??label.anchorPoint,candidate.anchorPoint,candidate.orientation)}isStandaloneSinglePinNetLabel(label){return this.inputProblem.netConnections.some(connection=>connection.netId===label.netId&&connection.pinIds.length===1&&connection.pinIds[0]===label.pinIds[0])}labelIntersectsDifferentNetTrace(label){let{width,height}=getDimsForOrientation({orientation:label.orientation,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),center2=getCenterFromAnchor(label.anchorPoint,label.orientation,width,height),bounds=getRectBounds(center2,width,height);return Object.values(this.traceMap).some(trace=>trace.globalConnNetId!==label.globalConnNetId&&tracePathIntersectsBounds(trace.tracePath,bounds))}getSearchStartAnchor(label,orientation4){let anchorPoint=this.getWickOffsetAnchor(label.anchorPoint,orientation4),{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),searchStartAnchor=this.getSideOffsetAnchor({anchorPoint,labelAnchorPoint:label.anchorPoint,orientation:orientation4,width,height});return this.blockedStandaloneLabelIndex!==null&&label===this.outputNetLabelPlacements[this.blockedStandaloneLabelIndex]&&isYOrientation(orientation4)&&this.blockedStandaloneLabelTargetAnchorX!==null&&(searchStartAnchor.x=this.blockedStandaloneLabelTargetAnchorX),searchStartAnchor}getWickOffsetAnchor(anchorPoint,orientation4){let direction2=dir(orientation4);return{x:anchorPoint.x+direction2.x*WICK_CLEARANCE,y:anchorPoint.y+direction2.y*WICK_CLEARANCE}}getSideOffsetAnchor(params){let{anchorPoint,labelAnchorPoint,orientation:orientation4,width,height}=params,chipSide=this.getChipSideForPoint(labelAnchorPoint),sideClearance=this.getContainingChipSide(labelAnchorPoint)?WICK_CLEARANCE:LABEL_SEARCH_STEP;return isYOrientation(orientation4)&&chipSide==="left"?{x:anchorPoint.x-width/2-sideClearance,y:anchorPoint.y}:isYOrientation(orientation4)&&chipSide==="right"?{x:anchorPoint.x+width/2+sideClearance,y:anchorPoint.y}:isXOrientation(orientation4)&&chipSide==="bottom"?{x:anchorPoint.x,y:anchorPoint.y-height/2-sideClearance}:isXOrientation(orientation4)&&chipSide==="top"?{x:anchorPoint.x,y:anchorPoint.y+height/2+sideClearance}:anchorPoint}getSearchDistanceLimit(label,orientation4){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),labelLength=orientation4==="y+"||orientation4==="y-"?height:width;return Math.min(this.maxSearchDistance,labelLength*2)}getLateralColumnMaxDistance(label,orientation4,baseAnchor){let availableOrientations=this.getAvailableOrientations(label),isSingleVerticalOrientation=availableOrientations.length===1&&isYOrientation(availableOrientations[0]),labelChipIds=new Set(label.pinIds.map(pinId=>this.pinMap[pinId]?.chipId).filter(chipId=>!!chipId)),connectedChips=this.chipObstacleSpatialIndex.chips.filter(chip=>labelChipIds.has(chip.chipId)),firstConnectedChipId=label.pinIds.map(pinId=>this.pinMap[pinId]?.chipId).find(Boolean),firstConnectedChip=connectedChips.find(chip=>chip.chipId===firstConnectedChipId),labelChips=isSingleVerticalOrientation?connectedChips:firstConnectedChip?[firstConnectedChip]:[];if(labelChips.length>0){if(orientation4==="y-")return Math.max(0,...labelChips.map(chip=>baseAnchor.y-chip.bounds.minY));if(orientation4==="y+")return Math.max(0,...labelChips.map(chip=>chip.bounds.maxY-baseAnchor.y));if(orientation4==="x-")return Math.max(0,...labelChips.map(chip=>baseAnchor.x-chip.bounds.minX));if(orientation4==="x+")return Math.max(0,...labelChips.map(chip=>chip.bounds.maxX-baseAnchor.x))}return this.getSearchDistanceLimit(label,orientation4)}createCandidate(label,anchorPoint,orientation4,connectorSource){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)});return{orientation:orientation4,anchorPoint,connectorSource,width,height,center:getCenterFromAnchor(anchorPoint,orientation4,width,height)}}getNetLabelHeight(label){if(label.netId){let ncHeight=this.inputProblem.netConnections.find(connection=>connection.netId===label.netId)?.netLabelHeight;if(ncHeight!==void 0)return ncHeight}return this.inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>label.pinIds.includes(pid)))?.netLabelHeight}getCandidateStatus(params){let{candidate,label,labelIndex,phase}=params,bounds=getRectBounds(candidate.center,candidate.width,candidate.height),boundsStatus=this.getBoundsStatus({bounds,labelIndex,label});if(boundsStatus!=="valid"){if(phase!=="trace-anchor"||boundsStatus!=="chip-collision"||!this.isAcceptableTraceAnchorChipCollision(candidate,label,bounds))return boundsStatus;let nonChipBoundsStatus=this.getBoundsStatus({bounds,labelIndex,label,ignoreChipCollisions:!0});if(nonChipBoundsStatus!=="valid")return nonChipBoundsStatus}let connectorTrace=this.getCandidateConnectorTrace(label,{anchorPoint:candidate.anchorPoint,orientation:candidate.orientation,phase},labelIndex);if(this.obstacleIndex.doesTracePathCrossChip(connectorTrace))return"chip-collision";for(let i6 of this.obstacleIndex.getLabelIndicesNearTracePath(connectorTrace)){if(i6===labelIndex||this.shouldIgnorePendingCrowdedLabel(labelIndex,i6))continue;let otherLabel=this.outputNetLabelPlacements[i6];if(tracePathIntersectsBounds(connectorTrace,getRectBounds(otherLabel.center,otherLabel.width,otherLabel.height)))return"netlabel-collision"}return"valid"}isAcceptableTraceAnchorChipCollision(candidate,label,bounds){let collidingChips=this.chipObstacleSpatialIndex.getChipsInBounds(bounds);if(collidingChips.length===0)return!1;let labelChipIds=new Set(label.pinIds.map(pinId=>this.pinMap[pinId]?.chipId).filter(chipId=>!!chipId));return collidingChips.every(chip=>{if(!labelChipIds.has(chip.chipId))return!1;let{anchorPoint,orientation:orientation4}=candidate,chipBounds=chip.bounds;return isYOrientation(orientation4)?anchorPoint.x<chipBounds.minX-EPS12||anchorPoint.x>chipBounds.maxX+EPS12:anchorPoint.y<chipBounds.minY-EPS12||anchorPoint.y>chipBounds.maxY+EPS12})}getBoundsStatus(candidateBoundsCheck){let{bounds,labelIndex,label,ignoreChipCollisions}=candidateBoundsCheck;return!ignoreChipCollisions&&(this.chipObstacleSpatialIndex.getChipsInBounds(bounds).length>0||this.sharesChipBoundary(bounds))?"chip-collision":rectIntersectsAnyTextBox(bounds,this.inputProblem)?"text-collision":this.obstacleIndex.doesTraceCrossBoundsInterior(bounds)?"trace-collision":this.isTraceTooCloseToLabel(bounds,label)?"trace-clearance-violation":this.intersectsAnyOtherNetLabel(bounds,labelIndex)?"netlabel-collision":"valid"}isTraceTooCloseToLabel(bounds,label){if(!this.shouldCheckTraceClearanceForLabel(label))return!1;let clearanceBounds=this.getLabelTraceClearanceBounds(bounds);return this.obstacleIndex.doesTraceIntersectBounds({bounds:clearanceBounds,excludedGlobalConnNetId:label.globalConnNetId})}getLabelTraceClearanceBounds(bounds){return{minX:bounds.minX-LABEL_TRACE_CLEARANCE2,minY:bounds.minY-LABEL_TRACE_CLEARANCE2,maxX:bounds.maxX+LABEL_TRACE_CLEARANCE2,maxY:bounds.maxY+LABEL_TRACE_CLEARANCE2}}shouldCheckTraceClearanceForLabel(label){return!this.isPortOnlyLabel(label)||!this.hasRoutedLabelOnSameNet(label)?!1:this.getAvailableOrientations(label).length===1}hasRoutedLabelOnSameNet(label){for(let otherLabel of this.outputNetLabelPlacements)if(otherLabel.globalConnNetId===label.globalConnNetId&&otherLabel.mspConnectionPairIds.length>0)return!0;return!1}isOutwardHorizontalFallback(label){let chipSide=this.getChipSideForPoint(label.anchorPoint);return chipSide==="left"&&label.orientation==="x-"||chipSide==="right"&&label.orientation==="x+"}hasPortOnlyLabelOnSameNet(label){return this.outputNetLabelPlacements.some(otherLabel=>otherLabel!==label&&otherLabel.globalConnNetId===label.globalConnNetId&&this.isPortOnlyLabel(otherLabel))}hasOppositeVerticalRailOnSameChipSide(label,orientation4){let currentConnection=this.inputProblem.netConnections.find(connection=>connection.netId===label.netId);if(!currentConnection)return!1;let currentSide=this.getSingleChipSideForNetConnection(currentConnection);if(!currentSide)return!1;let oppositeOrientation=orientation4==="y+"?"y-":"y+";return this.inputProblem.netConnections.some(connection=>{if(connection===currentConnection||connection.pinIds.length<2)return!1;let availableOrientations=this.inputProblem.availableNetLabelOrientations[connection.netId]??[];if(availableOrientations.length!==1||availableOrientations[0]!==oppositeOrientation)return!1;let connectionSide=this.getSingleChipSideForNetConnection(connection);return connectionSide?.chipId===currentSide.chipId&&connectionSide.side===currentSide.side})}getSingleChipSideForNetConnection(connection){if(connection.pinIds.length<2)return null;let pins=connection.pinIds.map(pinId=>this.pinMap[pinId]);if(pins.some(pin=>!pin)||new Set(pins.map(pin=>pin.chipId)).size!==1)return null;let chipId=pins[0].chipId,chip=this.chipObstacleSpatialIndex.chips.find(candidate=>candidate.chipId===chipId);if(!chip)return null;let sides=new Set(pins.map(pin=>Math.abs(pin.x-chip.bounds.minX)<=EPS12?"left":Math.abs(pin.x-chip.bounds.maxX)<=EPS12?"right":null));return sides.size!==1||sides.has(null)?null:{chipId,side:[...sides][0]}}isPortOnlyLabel(label){return label.mspConnectionPairIds.length===0}shouldIgnorePendingCrowdedLabel(labelIndex,otherLabelIndex){return this.crowdedPortOnlyLabelIndices.has(labelIndex)&&this.crowdedPortOnlyLabelIndices.has(otherLabelIndex)&&this.queuedLabelIndices.includes(otherLabelIndex)}intersectsAnyOtherNetLabel(bounds,labelIndex){let searchBounds={minX:bounds.minX-LABEL_SEARCH_STEP,minY:bounds.minY-LABEL_SEARCH_STEP,maxX:bounds.maxX+LABEL_SEARCH_STEP,maxY:bounds.maxY+LABEL_SEARCH_STEP},nearbyLabelIndices=this.obstacleIndex.getLabelIndicesInBounds(searchBounds).sort((a6,b6)=>a6-b6);for(let i6 of nearbyLabelIndices){if(i6===labelIndex||this.shouldIgnorePendingCrowdedLabel(labelIndex,i6))continue;let label=this.outputNetLabelPlacements[i6],otherBounds=getRectBounds(label.center,label.width,label.height);if(i6===this.blockedStandaloneLabelIndex&&isYOrientation(label.orientation)&&(otherBounds.minX-=LABEL_SEARCH_STEP,otherBounds.maxX+=LABEL_SEARCH_STEP),rectsOverlap2(bounds,otherBounds))return!0}return!1}sharesChipBoundary(bounds){let boundarySearchBounds={minX:bounds.minX-WICK_CLEARANCE-EPS12,minY:bounds.minY-WICK_CLEARANCE-EPS12,maxX:bounds.maxX+WICK_CLEARANCE+EPS12,maxY:bounds.maxY+WICK_CLEARANCE+EPS12},nearbyChips=this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);for(let chip of nearbyChips){let chipBounds=chip.bounds,adjacentToVerticalSide=Math.abs(bounds.minX-chipBounds.maxX)<=WICK_CLEARANCE+EPS12||Math.abs(bounds.maxX-chipBounds.minX)<=WICK_CLEARANCE+EPS12,adjacentToHorizontalSide=Math.abs(bounds.minY-chipBounds.maxY)<=WICK_CLEARANCE+EPS12||Math.abs(bounds.maxY-chipBounds.minY)<=WICK_CLEARANCE+EPS12;if(adjacentToVerticalSide&&rangesOverlap(bounds.minY,bounds.maxY,chipBounds.minY,chipBounds.maxY)||adjacentToHorizontalSide&&rangesOverlap(bounds.minX,bounds.maxX,chipBounds.minX,chipBounds.maxX))return!0}return!1}getChipSideForPoint(point6){let containingSide=this.getContainingChipSide(point6);if(containingSide)return containingSide;let side=this.getOutsideChipSide(point6);return side||this.getNearestChipSide(point6)}getPerpendicularOutwardDirection(point6,orientation4){let chipSide=this.getChipSideForPoint(point6);return isYOrientation(orientation4)&&chipSide==="left"?{x:-1,y:0}:isYOrientation(orientation4)&&chipSide==="right"?{x:1,y:0}:isXOrientation(orientation4)&&chipSide==="bottom"?{x:0,y:-1}:isXOrientation(orientation4)&&chipSide==="top"?{x:0,y:1}:{x:0,y:0}}getChipOutwardDirection(point6){switch(this.getChipSideForPoint(point6)){case"left":return{x:-1,y:0};case"right":return{x:1,y:0};case"bottom":return{x:0,y:-1};case"top":return{x:0,y:1};default:return{x:0,y:0}}}getContainingChipSide(point6){let nearestSide=null,nearestDistance=Number.POSITIVE_INFINITY;for(let chip of this.chipObstacleSpatialIndex.chips){let bounds=chip.bounds;if(!(point6.x<bounds.minX-EPS12||point6.x>bounds.maxX+EPS12||point6.y<bounds.minY-EPS12||point6.y>bounds.maxY+EPS12))for(let[side,distance52]of getSideDistances(point6,bounds))distance52<nearestDistance&&(nearestSide=side,nearestDistance=distance52)}return nearestSide}getOutsideChipSide(point6){let nearestSide=null,nearestDistanceSq=Number.POSITIVE_INFINITY;for(let chip of this.chipObstacleSpatialIndex.chips){let bounds=chip.bounds,dx3=point6.x<bounds.minX-EPS12?bounds.minX-point6.x:point6.x>bounds.maxX+EPS12?point6.x-bounds.maxX:0,dy3=point6.y<bounds.minY-EPS12?bounds.minY-point6.y:point6.y>bounds.maxY+EPS12?point6.y-bounds.maxY:0;if(dx3===0&&dy3===0)continue;let distanceSq=dx3**2+dy3**2;distanceSq>=nearestDistanceSq||(nearestDistanceSq=distanceSq,dx3>0?nearestSide=point6.x<bounds.minX?"left":"right":nearestSide=point6.y<bounds.minY?"bottom":"top")}return nearestSide}getNearestChipSide(point6){let nearestSide=null,nearestDistance=Number.POSITIVE_INFINITY;for(let chip of this.chipObstacleSpatialIndex.chips)for(let[side,distance52]of getSideDistances(point6,chip.bounds))distance52<nearestDistance&&(nearestSide=side,nearestDistance=distance52);return nearestSide}visualize(){return visualizeAvailableNetOrientationSolver({inputProblem:this.inputProblem,traces:this.traces,outputNetLabelPlacements:this.outputNetLabelPlacements,currentLabel:this.currentLabel,currentCandidateResults:this.currentCandidateResults,solved:this.solved})}},CANDIDATE_SELECTED_COLOR3="blue",CANDIDATE_REJECTED_COLOR3="red",visualizeRailNetLabelCornerPlacementSolver=state2=>{let graphics=visualizeInputProblem2(state2.inputProblem);return ensureGraphicsArrays2(graphics),drawTraces3(graphics,state2.traces),drawNetLabels3(graphics,state2.outputNetLabelPlacements),state2.solved||(drawCurrentLabel2(graphics,state2.currentLabel),drawCurrentCandidates3(graphics,state2.currentCandidateResults)),graphics},drawTraces3=(graphics,traces)=>{for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels3=(graphics,labels)=>{for(let label of labels)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
664
+ ${candidate.orientation}`})}},ensureGraphicsArrays=graphics=>{graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.rects||(graphics.rects=[]),graphics.circles||(graphics.circles=[]),graphics.texts||(graphics.texts=[])},AvailableNetOrientationObstacleIndex=class{constructor(params){__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"labelIndex",null);__publicField(this,"traceSegmentIndex",null);__publicField(this,"traceSegments",[]);this.chipObstacleSpatialIndex=params.chipObstacleSpatialIndex,this.rebuild(params)}rebuild(params){this.labelIndex=this.buildLabelIndex(params.netLabelPlacements),this.traceSegments=this.getTraceSegments(params.traces),this.traceSegmentIndex=this.buildTraceSegmentIndex(this.traceSegments)}getLabelIndicesInBounds(bounds){return this.labelIndex?this.labelIndex.search(bounds.minX,bounds.minY,bounds.maxX,bounds.maxY):[]}getTraceSegmentsInBounds(bounds){if(!this.traceSegmentIndex)return[];let searchBounds=getPaddedBounds(bounds,EPS12);return this.traceSegmentIndex.search(searchBounds.minX,searchBounds.minY,searchBounds.maxX,searchBounds.maxY).map(segmentIndex=>this.traceSegments[segmentIndex])}getLabelIndicesNearTracePath(tracePath){let labelIndices=new Set;for(let pointIndex=0;pointIndex<tracePath.length-1;pointIndex++){let segmentBounds=getPaddedBounds(getSegmentBounds(tracePath[pointIndex],tracePath[pointIndex+1]),EPS12);for(let labelIndex of this.getLabelIndicesInBounds(segmentBounds))labelIndices.add(labelIndex)}return[...labelIndices].sort((a6,b6)=>a6-b6)}doesTracePathCrossChip(tracePath){for(let pointIndex=0;pointIndex<tracePath.length-1;pointIndex++){let start=tracePath[pointIndex],end=tracePath[pointIndex+1],nearbyChips=this.chipObstacleSpatialIndex.getChipsInBounds(getPaddedBounds(getSegmentBounds(start,end),EPS12));for(let chip of nearbyChips)if(segmentCrossesBoundsInterior(start,end,chip.bounds))return!0}return!1}doesTraceCrossBoundsInterior(bounds){for(let segment2 of this.getTraceSegmentsInBounds(bounds))if(segmentCrossesBoundsInterior(segment2.start,segment2.end,bounds))return!0;return!1}doesTraceIntersectBounds(params){for(let segment2 of this.getTraceSegmentsInBounds(params.bounds))if(segment2.trace.globalConnNetId!==params.excludedGlobalConnNetId&&segmentIntersectsRect2(segment2.start,segment2.end,params.bounds))return!0;return!1}buildLabelIndex(netLabelPlacements){if(netLabelPlacements.length===0)return null;let labelIndex=new Flatbush(netLabelPlacements.length);for(let label of netLabelPlacements)labelIndex.add(label.center.x-label.width/2,label.center.y-label.height/2,label.center.x+label.width/2,label.center.y+label.height/2);return labelIndex.finish(),labelIndex}getTraceSegments(traces){let traceSegments=[];for(let trace of traces)for(let pointIndex=0;pointIndex<trace.tracePath.length-1;pointIndex++)traceSegments.push({trace,start:trace.tracePath[pointIndex],end:trace.tracePath[pointIndex+1]});return traceSegments}buildTraceSegmentIndex(traceSegments){if(traceSegments.length===0)return null;let traceSegmentIndex=new Flatbush(traceSegments.length);for(let segment2 of traceSegments)traceSegmentIndex.add(Math.min(segment2.start.x,segment2.end.x),Math.min(segment2.start.y,segment2.end.y),Math.max(segment2.start.x,segment2.end.x),Math.max(segment2.start.y,segment2.end.y));return traceSegmentIndex.finish(),traceSegmentIndex}};function getSegmentBounds(start,end){return{minX:Math.min(start.x,end.x),minY:Math.min(start.y,end.y),maxX:Math.max(start.x,end.x),maxY:Math.max(start.y,end.y)}}function getPaddedBounds(bounds,padding){return{minX:bounds.minX-padding,minY:bounds.minY-padding,maxX:bounds.maxX+padding,maxY:bounds.maxY+padding}}var LABEL_TRACE_CLEARANCE2=.1,AvailableNetOrientationSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"outputNetLabelPlacements");__publicField(this,"queuedLabelIndices",[]);__publicField(this,"currentLabelIndex",null);__publicField(this,"currentLabel",null);__publicField(this,"currentCandidateResults",[]);__publicField(this,"crowdedPortOnlyLabelIndices",new Set);__publicField(this,"blockedStandaloneLabelIndex",null);__publicField(this,"blockedStandaloneLabelTargetAnchorX",null);__publicField(this,"traceMap");__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"maxSearchDistance");__publicField(this,"pinMap");__publicField(this,"obstacleIndex");this.inputProblem=params.inputProblem,this.traces=[...params.traces],this.netLabelPlacements=params.netLabelPlacements,this.outputNetLabelPlacements=[...params.netLabelPlacements],this.traceMap=Object.fromEntries(this.traces.map(trace=>[trace.mspPairId,trace])),this.pinMap=getPinMap(params.inputProblem),this.chipObstacleSpatialIndex=params.inputProblem._chipObstacleSpatialIndex??new ChipObstacleSpatialIndex(params.inputProblem.chips),this.maxSearchDistance=getMaxSearchDistance(params.inputProblem),this.obstacleIndex=new AvailableNetOrientationObstacleIndex({chipObstacleSpatialIndex:this.chipObstacleSpatialIndex,netLabelPlacements:this.outputNetLabelPlacements,traces:this.traces}),this.crowdedPortOnlyLabelIndices=this.getCrowdedPortOnlyLabelIndices(),this.queuedLabelIndices=this.getProcessableLabelIndices(),this.setCurrentLabel(this.queuedLabelIndices[0]??null)}getConstructorParams(){return{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.netLabelPlacements}}_step(){let labelIndex=this.queuedLabelIndices.shift();if(labelIndex===void 0){this.finish();return}this.processLabel(labelIndex)}getOutput(){return{traces:this.traces,netLabelPlacements:this.outputNetLabelPlacements}}getProcessableLabelIndices(){let indices=[];for(let i6=0;i6<this.outputNetLabelPlacements.length;i6++)this.shouldProcessLabel(this.outputNetLabelPlacements[i6],i6)&&indices.push(i6);this.sortCrowdedTopBankByPin(indices);let orderedIndices=orderRoutedLabelsBeforeOverlappingPortLabels({labelIndices:indices,netLabelPlacements:this.outputNetLabelPlacements}),blockedStandaloneLabelIndex=orderedIndices.find(index=>{let label=this.outputNetLabelPlacements[index],orientations=this.getAvailableOrientations(label);return this.isPortOnlyLabel(label)&&this.isStandaloneSinglePinNetLabel(label)&&orientations.length===1&&isYOrientation(orientations[0])&&this.labelIntersectsDifferentNetTrace(label)});if(blockedStandaloneLabelIndex===void 0)return orderedIndices;this.blockedStandaloneLabelIndex=blockedStandaloneLabelIndex,this.blockedStandaloneLabelTargetAnchorX=null;let blockedLabel=this.outputNetLabelPlacements[blockedStandaloneLabelIndex],requiredOrientation=this.getAvailableOrientations(blockedLabel)[0],chipSide=this.getChipSideForPoint(blockedLabel.anchorPoint),affectedSlots=[],labelsToOrder=[];for(let slot=0;slot<orderedIndices.length;slot++){let index=orderedIndices[slot],label=this.outputNetLabelPlacements[index],orientations=this.getAvailableOrientations(label);this.getChipSideForPoint(label.anchorPoint)===chipSide&&orientations.length===1&&orientations[0]===requiredOrientation&&(affectedSlots.push(slot),labelsToOrder.push(index))}labelsToOrder.sort((a6,b6)=>{let aY2=this.outputNetLabelPlacements[a6].anchorPoint.y,bY2=this.outputNetLabelPlacements[b6].anchorPoint.y;return requiredOrientation==="y+"?bY2-aY2:aY2-bY2});let blockedLabelWidth=getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:blockedLabel.netId,pinIds:blockedLabel.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(blockedLabel)}),columnLabelIndex;if(blockedLabelWidth!==void 0&&(columnLabelIndex=labelsToOrder.find(index=>{if(index===blockedStandaloneLabelIndex)return!1;let label=this.outputNetLabelPlacements[index];return getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)})===blockedLabelWidth})),columnLabelIndex!==void 0){let columnLabel=this.outputNetLabelPlacements[columnLabelIndex];this.blockedStandaloneLabelTargetAnchorX=this.getSearchStartAnchor(columnLabel,requiredOrientation).x}for(let i6=0;i6<affectedSlots.length;i6++)orderedIndices[affectedSlots[i6]]=labelsToOrder[i6];return orderedIndices}sortCrowdedTopBankByPin(indices){let slotsByChip=new Map;for(let slot=0;slot<indices.length;slot++){let labelIndex=indices[slot];if(!this.crowdedPortOnlyLabelIndices.has(labelIndex))continue;let label=this.outputNetLabelPlacements[labelIndex];if(this.getChipSideForPoint(label.anchorPoint)!=="top")continue;let pin=this.pinMap[label.pinIds[0]];if(!pin)continue;let slots=slotsByChip.get(pin.chipId)??[];slots.push(slot),slotsByChip.set(pin.chipId,slots)}for(let slots of slotsByChip.values()){let labelIndices=slots.map(slot=>indices[slot]).sort((a6,b6)=>{let aPin=this.pinMap[this.outputNetLabelPlacements[a6].pinIds[0]],bPin=this.pinMap[this.outputNetLabelPlacements[b6].pinIds[0]];return aPin.x-bPin.x});for(let position4=0;position4<slots.length;position4++)indices[slots[position4]]=labelIndices[position4]}}shouldProcessLabel(label,labelIndex){let orientations=this.getAvailableOrientations(label);if(orientations.length===0)return!1;if(!orientations.includes(label.orientation))return!0;if(!this.crowdedPortOnlyLabelIndices.has(labelIndex))return!1;let bounds=getRectBounds(label.center,label.width,label.height);return this.outputNetLabelPlacements.some((otherLabel,otherIndex)=>otherIndex===labelIndex||otherLabel.globalConnNetId===label.globalConnNetId?!1:rectsOverlap2(bounds,getRectBounds(otherLabel.center,otherLabel.width,otherLabel.height)))}getCrowdedPortOnlyLabelIndices(){let labelIndicesByChipAndSide=new Map;for(let i6=0;i6<this.outputNetLabelPlacements.length;i6++){let label=this.outputNetLabelPlacements[i6];if(!this.isPortOnlyLabel(label)||!this.isStandaloneSinglePinNetLabel(label)||this.getAvailableOrientations(label).length===0)continue;let pin=this.pinMap[label.pinIds[0]];if(!pin)continue;let chipSide=this.getChipSideForPoint(label.anchorPoint);if(!chipSide)continue;let labelIndicesBySide=labelIndicesByChipAndSide.get(pin.chipId)??new Map,labelIndices=labelIndicesBySide.get(chipSide)??[];labelIndices.push(i6),labelIndicesBySide.set(chipSide,labelIndices),labelIndicesByChipAndSide.set(pin.chipId,labelIndicesBySide)}let crowdedIndices=new Set;for(let labelIndicesBySide of labelIndicesByChipAndSide.values())for(let labelIndices of labelIndicesBySide.values()){let hasWrongOrientation=labelIndices.some(index=>{let label=this.outputNetLabelPlacements[index];return!this.getAvailableOrientations(label).includes(label.orientation)}),hasOverlap=labelIndices.some((index,position4)=>{let label=this.outputNetLabelPlacements[index],bounds=getRectBounds(label.center,label.width,label.height);return labelIndices.slice(position4+1).some(otherIndex=>{let other=this.outputNetLabelPlacements[otherIndex];return rectsOverlap2(bounds,getRectBounds(other.center,other.width,other.height))})});if(!(!hasWrongOrientation||!hasOverlap))for(let index of labelIndices)crowdedIndices.add(index)}return crowdedIndices}processLabel(labelIndex){let label=this.outputNetLabelPlacements[labelIndex];this.setCurrentLabel(labelIndex),this.currentCandidateResults=[];let candidate=this.findCorrectedCandidate(label,labelIndex);candidate&&this.applyCandidate(label,candidate,labelIndex)}applyCandidate(label,candidate,labelIndex){this.outputNetLabelPlacements[labelIndex]={...label,...toNetLabelPlacementPatch(candidate)},this.addConnectorTrace(label,candidate,labelIndex),this.obstacleIndex.rebuild({netLabelPlacements:this.outputNetLabelPlacements,traces:this.traces})}addConnectorTrace(label,candidate,labelIndex){if(candidate.phase==="trace-anchor")return;let tracePath=this.getCandidateConnectorTrace(label,candidate,labelIndex);if(tracePath.length<2)return;let mspPairId=`available-net-orientation-${labelIndex}-${label.netId??label.globalConnNetId}`,connectorTrace={mspPairId,dcConnNetId:label.dcConnNetId??label.globalConnNetId,globalConnNetId:label.globalConnNetId,userNetId:label.netId,pins:getTracePins(label,this.pinMap),tracePath,mspConnectionPairIds:[mspPairId],pinIds:label.pinIds};this.traces.push(connectorTrace),this.traceMap[mspPairId]=connectorTrace}finish(){this.currentLabelIndex=null,this.currentLabel=null,this.currentCandidateResults=[],this.solved=!0}setCurrentLabel(labelIndex){this.currentLabelIndex=labelIndex,this.currentLabel=labelIndex===null?null:this.outputNetLabelPlacements[labelIndex]}findCorrectedCandidate(label,labelIndex){let orientations=this.getAvailableOrientations(label),requiredOrientation=orientations[0];if(this.crowdedPortOnlyLabelIndices.has(labelIndex)&&this.getChipSideForPoint(label.anchorPoint)==="top"&&isYOrientation(requiredOrientation)){let topFanoutCandidate=this.findValidCrowdedTopVerticalFanoutCandidate(label,labelIndex,requiredOrientation);if(topFanoutCandidate)return topFanoutCandidate}let netConnection=this.inputProblem.netConnections.find(connection=>connection.netId===label.netId),isTwoPinNet=netConnection?.pinIds.length===2,isDistanceSplitVerticalRail=(netConnection?.pinIds.length??0)>2&&isYOrientation(requiredOrientation)&&this.hasPortOnlyLabelOnSameNet(label),isPairedSameSidePowerRail=isYOrientation(requiredOrientation)&&this.hasOppositeVerticalRailOnSameChipSide(label,requiredOrientation);if(orientations.length===1&&isYOrientation(requiredOrientation)&&this.isOutwardHorizontalFallback(label)&&this.hasTraceContinuingInOrientation(label,requiredOrientation)&&(isDistanceSplitVerticalRail||isPairedSameSidePowerRail)){let traceAnchorCandidate2=this.findValidOutwardTraceAnchorCandidate(label,requiredOrientation,labelIndex);if(traceAnchorCandidate2)return traceAnchorCandidate2}if(isTwoPinNet&&orientations.length===1&&isYOrientation(requiredOrientation)&&this.hasTraceContinuingInOrientation(label,requiredOrientation)){let alignedCandidate=this.findValidCandidateInShiftColumn({label,labelIndex,orientation:requiredOrientation,direction:dir(requiredOrientation),baseAnchor:this.getWickOffsetAnchor(label.anchorPoint,requiredOrientation),maxSearchDistance:this.maxSearchDistance,outwardDistance:0,stopOnTraceCollision:!1});if(alignedCandidate)return alignedCandidate}let rotatedCandidate=this.findValidRotatedCandidate(label,labelIndex,orientations);if(rotatedCandidate)return rotatedCandidate;let traceAnchorCandidate=this.findValidTraceAnchorCandidate(label,orientations[0],labelIndex);if(traceAnchorCandidate)return traceAnchorCandidate;let shiftedCandidate=this.findValidShiftedCandidate(label,orientations[0],labelIndex);return shiftedCandidate||this.findValidLateralShiftedCandidate(label,orientations[0],labelIndex)}findValidCrowdedTopVerticalFanoutCandidate(label,labelIndex,orientation4){let pin=this.pinMap[label.pinIds[0]],chip=pin?this.chipObstacleSpatialIndex.chips.find(candidate=>candidate.chipId===pin.chipId):void 0;if(!chip)return null;let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),nextPinToRight=this.outputNetLabelPlacements.map((otherLabel,index)=>({index,pin:this.pinMap[otherLabel.pinIds[0]]})).filter(({index,pin:otherPin})=>this.crowdedPortOnlyLabelIndices.has(index)&&otherPin?.chipId===pin.chipId&&otherPin.x>pin.x+EPS12).sort((a6,b6)=>a6.pin.x-b6.pin.x)[0]?.pin;if(orientation4==="y-"&&nextPinToRight)return null;let anchorX=orientation4==="y-"?Math.max(label.anchorPoint.x+LABEL_SEARCH_STEP,chip.bounds.maxX+width/2+LABEL_TRACE_CLEARANCE2):Math.min(label.anchorPoint.x,(nextPinToRight?.x??chip.bounds.maxX)-LABEL_SEARCH_STEP-width/2),highestPlacedLabelY=chip.bounds.maxY,lowestUpFacingLabelY=Number.POSITIVE_INFINITY,highestUpFacingLabelY=Number.NEGATIVE_INFINITY;for(let index=0;index<this.outputNetLabelPlacements.length;index++){if(index===labelIndex||!this.crowdedPortOnlyLabelIndices.has(index)||this.queuedLabelIndices.includes(index))continue;let placedLabel=this.outputNetLabelPlacements[index],placedBounds=getRectBounds(placedLabel.center,placedLabel.width,placedLabel.height);highestPlacedLabelY=Math.max(highestPlacedLabelY,placedBounds.maxY),placedLabel.orientation==="y+"&&(lowestUpFacingLabelY=Math.min(lowestUpFacingLabelY,placedBounds.minY),highestUpFacingLabelY=Math.max(highestUpFacingLabelY,placedBounds.maxY))}let stackedAnchorY=highestPlacedLabelY+LABEL_SEARCH_STEP+(orientation4==="y-"?height:0),centeredAnchorY=Number.isFinite(lowestUpFacingLabelY)&&Number.isFinite(highestUpFacingLabelY)?(lowestUpFacingLabelY+highestUpFacingLabelY)/2:stackedAnchorY,anchorYs=orientation4==="y-"?[centeredAnchorY,stackedAnchorY]:[stackedAnchorY];for(let anchorY of anchorYs){if(anchorY-label.anchorPoint.y>this.maxSearchDistance+EPS12)continue;let candidate=this.createCandidate(label,{x:anchorX,y:anchorY},orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,"lateral-shift",anchorY-label.anchorPoint.y,anchorX-label.anchorPoint.x);if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}return null}hasTraceContinuingInOrientation(label,orientation4){let direction2=dir(orientation4);return Object.values(this.traceMap).some(trace=>{if(trace.globalConnNetId!==label.globalConnNetId)return!1;let path=trace.tracePath;return path.some((point6,pointIndex)=>Math.abs(point6.x-label.anchorPoint.x)>EPS12||Math.abs(point6.y-label.anchorPoint.y)>EPS12?!1:[path[pointIndex-1],path[pointIndex+1]].some(neighbor=>neighbor&&Math.abs(neighbor.x-point6.x)<=EPS12&&(neighbor.y-point6.y)*direction2.y>EPS12))})}findValidRotatedCandidate(label,labelIndex,orientations){for(let orientation4 of orientations){let candidate=this.createCandidate(label,this.getSearchStartAnchor(label,orientation4),orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,"rotate");if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}return null}findValidTraceAnchorCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),{points}=this.getTraceAnchorCandidates(label,orientation4),candidatePoints=points.sort((a6,b6)=>{let aAlongDirection=a6.x*direction2.x+a6.y*direction2.y;return b6.x*direction2.x+b6.y*direction2.y-aAlongDirection});for(let anchorPoint of candidatePoints){let candidate=this.createCandidate(label,anchorPoint,orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,"trace-anchor");if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}return null}findValidOutwardTraceAnchorCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),preservedColumnAnchor=this.getSearchStartAnchor(label,orientation4),{points,preferNearestBendOnOutwardRow}=this.getTraceAnchorCandidates(label,orientation4),candidatePoints=points.sort((a6,b6)=>{let aAlongDirection=a6.x*direction2.x+a6.y*direction2.y,bAlongDirection=b6.x*direction2.x+b6.y*direction2.y;if(!preferNearestBendOnOutwardRow)return bAlongDirection-aAlongDirection;let aPerpendicularDistance=isYOrientation(orientation4)?Math.abs(a6.x-preservedColumnAnchor.x):Math.abs(a6.y-preservedColumnAnchor.y),bPerpendicularDistance=isYOrientation(orientation4)?Math.abs(b6.x-preservedColumnAnchor.x):Math.abs(b6.y-preservedColumnAnchor.y);return bAlongDirection-aAlongDirection||aPerpendicularDistance-bPerpendicularDistance});for(let connectorSource of candidatePoints){let preservedColumnCandidate=this.createCandidate(label,{x:preservedColumnAnchor.x,y:connectorSource.y},orientation4,connectorSource),preservedColumnResult=this.evaluateCandidate(preservedColumnCandidate,label,labelIndex,"outward-trace-anchor");if(this.recordCandidateResult(preservedColumnResult),preservedColumnResult.status==="valid")return preservedColumnResult.selected=!0,preservedColumnResult;let outwardDirection=this.getPerpendicularOutwardDirection(connectorSource,orientation4);if(!(outwardDirection.x===0&&outwardDirection.y===0))for(let distance72=LABEL_SEARCH_STEP;distance72<=this.maxSearchDistance+EPS12;distance72+=LABEL_SEARCH_STEP){let anchorPoint={x:connectorSource.x+outwardDirection.x*distance72,y:connectorSource.y+outwardDirection.y*distance72},candidate=this.createCandidate(label,anchorPoint,orientation4,connectorSource),result=this.evaluateCandidate(candidate,label,labelIndex,"outward-trace-anchor",distance72);if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result}}return null}getTraceAnchorCandidates(label,orientation4){let seen=new Set,points=[],directHostTraceIds=new Set(label.mspConnectionPairIds??[]),connectedTraceIds=new Set(directHostTraceIds);if(isYOrientation(orientation4)){let connectedPinIds=new Set;for(let traceId of connectedTraceIds)for(let pinId of this.traceMap[traceId]?.pinIds??[])connectedPinIds.add(pinId);let foundConnectedTrace=!0;for(;foundConnectedTrace;){foundConnectedTrace=!1;for(let trace of Object.values(this.traceMap)){if(connectedTraceIds.has(trace.mspPairId)||trace.mspPairId.startsWith("available-net-orientation-")||trace.globalConnNetId!==label.globalConnNetId||!trace.pinIds.some(pinId=>connectedPinIds.has(pinId)))continue;let connectedTraces=[...connectedTraceIds].flatMap(traceId=>{let connectedTrace=this.traceMap[traceId];return connectedTrace?[connectedTrace]:[]});if(this.sharesVerticalRailWithAny(trace,connectedTraces)){connectedTraceIds.add(trace.mspPairId);for(let pinId of trace.pinIds)connectedPinIds.add(pinId);foundConnectedTrace=!0}}}}for(let traceId of connectedTraceIds){let trace=this.traceMap[traceId];if(trace)for(let point6 of trace.tracePath){let key=`${point6.x.toFixed(9)},${point6.y.toFixed(9)}`;seen.has(key)||(seen.add(key),points.push(point6))}}let direction2=dir(orientation4),furthestAlong=Math.max(...points.map(point6=>point6.x*direction2.x+point6.y*direction2.y)),furthestRowPoints=points.filter(point6=>Math.abs(point6.x*direction2.x+point6.y*direction2.y-furthestAlong)<=EPS12),directHostPinIds=new Set([...directHostTraceIds].flatMap(traceId=>this.traceMap[traceId]?.pinIds??[])),adjacentTraces=[...connectedTraceIds].flatMap(traceId=>{if(directHostTraceIds.has(traceId))return[];let trace=this.traceMap[traceId];return trace?.pinIds.some(pinId=>directHostPinIds.has(pinId))?[trace]:[]});return{points,preferNearestBendOnOutwardRow:adjacentTraces.some(trace=>furthestRowPoints.some(point6=>trace.tracePath.some(tracePoint=>Math.abs(tracePoint.x-point6.x)<=EPS12&&Math.abs(tracePoint.y-point6.y)<=EPS12)))}}sharesVerticalRailWithAny(trace,otherTraces){let verticalRailXs=new Set;for(let otherTrace of otherTraces)for(let i6=0;i6<otherTrace.tracePath.length-1;i6++){let start=otherTrace.tracePath[i6],end=otherTrace.tracePath[i6+1];Math.abs(start.x-end.x)<=EPS12&&Math.abs(start.y-end.y)>EPS12&&verticalRailXs.add(start.x)}for(let i6=0;i6<trace.tracePath.length-1;i6++){let start=trace.tracePath[i6],end=trace.tracePath[i6+1];if(Math.abs(start.x-end.x)<=EPS12&&Math.abs(start.y-end.y)>EPS12&&[...verticalRailXs].some(x6=>Math.abs(x6-start.x)<=EPS12))return!0}return!1}getAvailableOrientations(label){let effectiveNetId=label.netId??label.globalConnNetId;return this.inputProblem.availableNetLabelOrientations[effectiveNetId]??[]}findValidShiftedCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),initialBaseAnchor=this.getSearchStartAnchor(label,orientation4),outwardDirection=this.getPerpendicularOutwardDirection(label.anchorPoint,orientation4),maxSearchDistance=this.getSearchDistanceLimit(label,orientation4),maxOutwardDistance=outwardDirection.x===0&&outwardDirection.y===0?0:this.maxSearchDistance;for(let outwardDistance=0;outwardDistance<=maxOutwardDistance+EPS12;outwardDistance+=LABEL_SEARCH_STEP){let baseAnchor={x:initialBaseAnchor.x+outwardDirection.x*outwardDistance,y:initialBaseAnchor.y+outwardDirection.y*outwardDistance},candidate=this.findValidCandidateInShiftColumn({label,labelIndex,orientation:orientation4,direction:direction2,baseAnchor,maxSearchDistance,outwardDistance});if(candidate)return candidate}return null}findValidLateralShiftedCandidate(label,orientation4,labelIndex){let direction2=dir(orientation4),initialBaseAnchor=this.getSearchStartAnchor(label,orientation4),lateralDir={x:isYOrientation(orientation4)?1:0,y:isXOrientation(orientation4)?1:0},maxSteps=Math.ceil(this.maxSearchDistance/LABEL_SEARCH_STEP);for(let step=1;step<=maxSteps;step++)for(let sign of[-1,1]){let lateralOffset=sign*step*LABEL_SEARCH_STEP,baseAnchor={x:initialBaseAnchor.x+lateralDir.x*lateralOffset,y:initialBaseAnchor.y+lateralDir.y*lateralOffset},maxSearchDistance=this.getLateralColumnMaxDistance(label,orientation4,baseAnchor),candidate=this.findValidCandidateInShiftColumn({label,labelIndex,orientation:orientation4,direction:direction2,baseAnchor,maxSearchDistance,outwardDistance:lateralOffset,phase:"lateral-shift"});if(candidate)return candidate}return null}findValidCandidateInShiftColumn(params){let{label,labelIndex,orientation:orientation4,direction:direction2,baseAnchor,maxSearchDistance,outwardDistance,phase="shift",stopOnTraceCollision=!0}=params;for(let distance72=LABEL_SEARCH_STEP;distance72<=maxSearchDistance+EPS12;distance72+=LABEL_SEARCH_STEP){let anchorPoint={x:baseAnchor.x+direction2.x*distance72,y:baseAnchor.y+direction2.y*distance72},candidate=this.createCandidate(label,anchorPoint,orientation4),result=this.evaluateCandidate(candidate,label,labelIndex,phase,distance72,outwardDistance);if(this.recordCandidateResult(result),result.status==="valid")return result.selected=!0,result;if(stopOnTraceCollision&&result.status==="trace-collision")break}return null}evaluateCandidate(candidate,label,labelIndex,phase,distance72,outwardDistance){return{...candidate,phase,distance:distance72,outwardDistance,selected:!1,status:this.getCandidateStatus({candidate,label,labelIndex,phase})}}recordCandidateResult(candidate){this.stats.candidateEvaluations=(this.stats.candidateEvaluations??0)+1,this.currentCandidateResults.length<MAX_RECORDED_CANDIDATES?this.currentCandidateResults.push(candidate):candidate.status==="valid"&&(this.currentCandidateResults[MAX_RECORDED_CANDIDATES-1]=candidate),this.stats.maxRecordedCandidates=Math.max(this.stats.maxRecordedCandidates??0,this.currentCandidateResults.length)}getCandidateConnectorTrace(label,candidate,labelIndex){if(this.crowdedPortOnlyLabelIndices.has(labelIndex)&&this.getChipSideForPoint(label.anchorPoint)==="top"&&isYOrientation(candidate.orientation))return simplifyOrthogonalPath([label.anchorPoint,{x:label.anchorPoint.x,y:candidate.anchorPoint.y},candidate.anchorPoint]);if(candidate.phase==="lateral-shift"){let chipOutwardDir=this.crowdedPortOnlyLabelIndices.has(labelIndex)?this.getChipOutwardDirection(label.anchorPoint):(()=>{let orientDir=dir(candidate.orientation);return{x:-orientDir.x,y:-orientDir.y}})(),kickedSource={x:label.anchorPoint.x+chipOutwardDir.x*LABEL_SEARCH_STEP,y:label.anchorPoint.y+chipOutwardDir.y*LABEL_SEARCH_STEP};return simplifyOrthogonalPath([label.anchorPoint,...getConnectorTracePath(kickedSource,candidate.anchorPoint,candidate.orientation)])}return getConnectorTracePath(candidate.connectorSource??label.anchorPoint,candidate.anchorPoint,candidate.orientation)}isStandaloneSinglePinNetLabel(label){return this.inputProblem.netConnections.some(connection=>connection.netId===label.netId&&connection.pinIds.length===1&&connection.pinIds[0]===label.pinIds[0])}labelIntersectsDifferentNetTrace(label){let{width,height}=getDimsForOrientation({orientation:label.orientation,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),center2=getCenterFromAnchor(label.anchorPoint,label.orientation,width,height),bounds=getRectBounds(center2,width,height);return Object.values(this.traceMap).some(trace=>trace.globalConnNetId!==label.globalConnNetId&&tracePathIntersectsBounds(trace.tracePath,bounds))}getSearchStartAnchor(label,orientation4){let anchorPoint=this.getWickOffsetAnchor(label.anchorPoint,orientation4),{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),searchStartAnchor=this.getSideOffsetAnchor({anchorPoint,labelAnchorPoint:label.anchorPoint,orientation:orientation4,width,height});return this.blockedStandaloneLabelIndex!==null&&label===this.outputNetLabelPlacements[this.blockedStandaloneLabelIndex]&&isYOrientation(orientation4)&&this.blockedStandaloneLabelTargetAnchorX!==null&&(searchStartAnchor.x=this.blockedStandaloneLabelTargetAnchorX),searchStartAnchor}getWickOffsetAnchor(anchorPoint,orientation4){let direction2=dir(orientation4);return{x:anchorPoint.x+direction2.x*WICK_CLEARANCE,y:anchorPoint.y+direction2.y*WICK_CLEARANCE}}getSideOffsetAnchor(params){let{anchorPoint,labelAnchorPoint,orientation:orientation4,width,height}=params,chipSide=this.getChipSideForPoint(labelAnchorPoint),sideClearance=this.getContainingChipSide(labelAnchorPoint)?WICK_CLEARANCE:LABEL_SEARCH_STEP;return isYOrientation(orientation4)&&chipSide==="left"?{x:anchorPoint.x-width/2-sideClearance,y:anchorPoint.y}:isYOrientation(orientation4)&&chipSide==="right"?{x:anchorPoint.x+width/2+sideClearance,y:anchorPoint.y}:isXOrientation(orientation4)&&chipSide==="bottom"?{x:anchorPoint.x,y:anchorPoint.y-height/2-sideClearance}:isXOrientation(orientation4)&&chipSide==="top"?{x:anchorPoint.x,y:anchorPoint.y+height/2+sideClearance}:anchorPoint}getSearchDistanceLimit(label,orientation4){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)}),labelLength=orientation4==="y+"||orientation4==="y-"?height:width;return Math.min(this.maxSearchDistance,labelLength*2)}getLateralColumnMaxDistance(label,orientation4,baseAnchor){let availableOrientations=this.getAvailableOrientations(label),isSingleVerticalOrientation=availableOrientations.length===1&&isYOrientation(availableOrientations[0]),labelChipIds=new Set(label.pinIds.map(pinId=>this.pinMap[pinId]?.chipId).filter(chipId=>!!chipId)),connectedChips=this.chipObstacleSpatialIndex.chips.filter(chip=>labelChipIds.has(chip.chipId)),firstConnectedChipId=label.pinIds.map(pinId=>this.pinMap[pinId]?.chipId).find(Boolean),firstConnectedChip=connectedChips.find(chip=>chip.chipId===firstConnectedChipId),labelChips=isSingleVerticalOrientation?connectedChips:firstConnectedChip?[firstConnectedChip]:[];if(labelChips.length>0){if(orientation4==="y-")return Math.max(0,...labelChips.map(chip=>baseAnchor.y-chip.bounds.minY));if(orientation4==="y+")return Math.max(0,...labelChips.map(chip=>chip.bounds.maxY-baseAnchor.y));if(orientation4==="x-")return Math.max(0,...labelChips.map(chip=>baseAnchor.x-chip.bounds.minX));if(orientation4==="x+")return Math.max(0,...labelChips.map(chip=>chip.bounds.maxX-baseAnchor.x))}return this.getSearchDistanceLimit(label,orientation4)}createCandidate(label,anchorPoint,orientation4,connectorSource){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:getNetLabelWidthForConnection({inputProblem:this.inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:this.isPortOnlyLabel(label)}),netLabelHeight:this.getNetLabelHeight(label)});return{orientation:orientation4,anchorPoint,connectorSource,width,height,center:getCenterFromAnchor(anchorPoint,orientation4,width,height)}}getNetLabelHeight(label){if(label.netId){let ncHeight=this.inputProblem.netConnections.find(connection=>connection.netId===label.netId)?.netLabelHeight;if(ncHeight!==void 0)return ncHeight}return this.inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>label.pinIds.includes(pid)))?.netLabelHeight}getCandidateStatus(params){let{candidate,label,labelIndex,phase}=params,bounds=getRectBounds(candidate.center,candidate.width,candidate.height),boundsStatus=this.getBoundsStatus({bounds,labelIndex,label});if(boundsStatus!=="valid"){if(phase!=="trace-anchor"||boundsStatus!=="chip-collision"||!this.isAcceptableTraceAnchorChipCollision(candidate,label,bounds))return boundsStatus;let nonChipBoundsStatus=this.getBoundsStatus({bounds,labelIndex,label,ignoreChipCollisions:!0});if(nonChipBoundsStatus!=="valid")return nonChipBoundsStatus}let connectorTrace=this.getCandidateConnectorTrace(label,{anchorPoint:candidate.anchorPoint,orientation:candidate.orientation,phase},labelIndex);if(this.obstacleIndex.doesTracePathCrossChip(connectorTrace))return"chip-collision";for(let i6 of this.obstacleIndex.getLabelIndicesNearTracePath(connectorTrace)){if(i6===labelIndex||this.shouldIgnorePendingCrowdedLabel(labelIndex,i6))continue;let otherLabel=this.outputNetLabelPlacements[i6];if(tracePathIntersectsBounds(connectorTrace,getRectBounds(otherLabel.center,otherLabel.width,otherLabel.height)))return"netlabel-collision"}return"valid"}isAcceptableTraceAnchorChipCollision(candidate,label,bounds){let collidingChips=this.chipObstacleSpatialIndex.getChipsInBounds(bounds);if(collidingChips.length===0)return!1;let labelChipIds=new Set(label.pinIds.map(pinId=>this.pinMap[pinId]?.chipId).filter(chipId=>!!chipId));return collidingChips.every(chip=>{if(!labelChipIds.has(chip.chipId))return!1;let{anchorPoint,orientation:orientation4}=candidate,chipBounds=chip.bounds;return isYOrientation(orientation4)?anchorPoint.x<chipBounds.minX-EPS12||anchorPoint.x>chipBounds.maxX+EPS12:anchorPoint.y<chipBounds.minY-EPS12||anchorPoint.y>chipBounds.maxY+EPS12})}getBoundsStatus(candidateBoundsCheck){let{bounds,labelIndex,label,ignoreChipCollisions}=candidateBoundsCheck;return!ignoreChipCollisions&&(this.chipObstacleSpatialIndex.getChipsInBounds(bounds).length>0||this.sharesChipBoundary(bounds))?"chip-collision":rectIntersectsAnyTextBox(bounds,this.inputProblem)?"text-collision":this.obstacleIndex.doesTraceCrossBoundsInterior(bounds)?"trace-collision":this.isTraceTooCloseToLabel(bounds,label)?"trace-clearance-violation":this.intersectsAnyOtherNetLabel(bounds,labelIndex)?"netlabel-collision":"valid"}isTraceTooCloseToLabel(bounds,label){if(!this.shouldCheckTraceClearanceForLabel(label))return!1;let clearanceBounds=this.getLabelTraceClearanceBounds(bounds);return this.obstacleIndex.doesTraceIntersectBounds({bounds:clearanceBounds,excludedGlobalConnNetId:label.globalConnNetId})}getLabelTraceClearanceBounds(bounds){return{minX:bounds.minX-LABEL_TRACE_CLEARANCE2,minY:bounds.minY-LABEL_TRACE_CLEARANCE2,maxX:bounds.maxX+LABEL_TRACE_CLEARANCE2,maxY:bounds.maxY+LABEL_TRACE_CLEARANCE2}}shouldCheckTraceClearanceForLabel(label){return!this.isPortOnlyLabel(label)||!this.hasRoutedLabelOnSameNet(label)?!1:this.getAvailableOrientations(label).length===1}hasRoutedLabelOnSameNet(label){for(let otherLabel of this.outputNetLabelPlacements)if(otherLabel.globalConnNetId===label.globalConnNetId&&otherLabel.mspConnectionPairIds.length>0)return!0;return!1}isOutwardHorizontalFallback(label){let chipSide=this.getChipSideForPoint(label.anchorPoint);return chipSide==="left"&&label.orientation==="x-"||chipSide==="right"&&label.orientation==="x+"}hasPortOnlyLabelOnSameNet(label){return this.outputNetLabelPlacements.some(otherLabel=>otherLabel!==label&&otherLabel.globalConnNetId===label.globalConnNetId&&this.isPortOnlyLabel(otherLabel))}hasOppositeVerticalRailOnSameChipSide(label,orientation4){let currentConnection=this.inputProblem.netConnections.find(connection=>connection.netId===label.netId);if(!currentConnection)return!1;let currentSide=this.getSingleChipSideForNetConnection(currentConnection);if(!currentSide)return!1;let oppositeOrientation=orientation4==="y+"?"y-":"y+";return this.inputProblem.netConnections.some(connection=>{if(connection===currentConnection||connection.pinIds.length<2)return!1;let availableOrientations=this.inputProblem.availableNetLabelOrientations[connection.netId]??[];if(availableOrientations.length!==1||availableOrientations[0]!==oppositeOrientation)return!1;let connectionSide=this.getSingleChipSideForNetConnection(connection);return connectionSide?.chipId===currentSide.chipId&&connectionSide.side===currentSide.side})}getSingleChipSideForNetConnection(connection){if(connection.pinIds.length<2)return null;let pins=connection.pinIds.map(pinId=>this.pinMap[pinId]);if(pins.some(pin=>!pin)||new Set(pins.map(pin=>pin.chipId)).size!==1)return null;let chipId=pins[0].chipId,chip=this.chipObstacleSpatialIndex.chips.find(candidate=>candidate.chipId===chipId);if(!chip)return null;let sides=new Set(pins.map(pin=>Math.abs(pin.x-chip.bounds.minX)<=EPS12?"left":Math.abs(pin.x-chip.bounds.maxX)<=EPS12?"right":null));return sides.size!==1||sides.has(null)?null:{chipId,side:[...sides][0]}}isPortOnlyLabel(label){return label.mspConnectionPairIds.length===0}shouldIgnorePendingCrowdedLabel(labelIndex,otherLabelIndex){return this.crowdedPortOnlyLabelIndices.has(labelIndex)&&this.crowdedPortOnlyLabelIndices.has(otherLabelIndex)&&this.queuedLabelIndices.includes(otherLabelIndex)}intersectsAnyOtherNetLabel(bounds,labelIndex){let searchBounds={minX:bounds.minX-LABEL_SEARCH_STEP,minY:bounds.minY-LABEL_SEARCH_STEP,maxX:bounds.maxX+LABEL_SEARCH_STEP,maxY:bounds.maxY+LABEL_SEARCH_STEP},nearbyLabelIndices=this.obstacleIndex.getLabelIndicesInBounds(searchBounds).sort((a6,b6)=>a6-b6);for(let i6 of nearbyLabelIndices){if(i6===labelIndex||this.shouldIgnorePendingCrowdedLabel(labelIndex,i6))continue;let label=this.outputNetLabelPlacements[i6],otherBounds=getRectBounds(label.center,label.width,label.height);if(i6===this.blockedStandaloneLabelIndex&&isYOrientation(label.orientation)&&(otherBounds.minX-=LABEL_SEARCH_STEP,otherBounds.maxX+=LABEL_SEARCH_STEP),rectsOverlap2(bounds,otherBounds))return!0}return!1}sharesChipBoundary(bounds){let boundarySearchBounds={minX:bounds.minX-WICK_CLEARANCE-EPS12,minY:bounds.minY-WICK_CLEARANCE-EPS12,maxX:bounds.maxX+WICK_CLEARANCE+EPS12,maxY:bounds.maxY+WICK_CLEARANCE+EPS12},nearbyChips=this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);for(let chip of nearbyChips){let chipBounds=chip.bounds,adjacentToVerticalSide=Math.abs(bounds.minX-chipBounds.maxX)<=WICK_CLEARANCE+EPS12||Math.abs(bounds.maxX-chipBounds.minX)<=WICK_CLEARANCE+EPS12,adjacentToHorizontalSide=Math.abs(bounds.minY-chipBounds.maxY)<=WICK_CLEARANCE+EPS12||Math.abs(bounds.maxY-chipBounds.minY)<=WICK_CLEARANCE+EPS12;if(adjacentToVerticalSide&&rangesOverlap(bounds.minY,bounds.maxY,chipBounds.minY,chipBounds.maxY)||adjacentToHorizontalSide&&rangesOverlap(bounds.minX,bounds.maxX,chipBounds.minX,chipBounds.maxX))return!0}return!1}getChipSideForPoint(point6){let containingSide=this.getContainingChipSide(point6);if(containingSide)return containingSide;let side=this.getOutsideChipSide(point6);return side||this.getNearestChipSide(point6)}getPerpendicularOutwardDirection(point6,orientation4){let chipSide=this.getChipSideForPoint(point6);return isYOrientation(orientation4)&&chipSide==="left"?{x:-1,y:0}:isYOrientation(orientation4)&&chipSide==="right"?{x:1,y:0}:isXOrientation(orientation4)&&chipSide==="bottom"?{x:0,y:-1}:isXOrientation(orientation4)&&chipSide==="top"?{x:0,y:1}:{x:0,y:0}}getChipOutwardDirection(point6){switch(this.getChipSideForPoint(point6)){case"left":return{x:-1,y:0};case"right":return{x:1,y:0};case"bottom":return{x:0,y:-1};case"top":return{x:0,y:1};default:return{x:0,y:0}}}getContainingChipSide(point6){let nearestSide=null,nearestDistance=Number.POSITIVE_INFINITY;for(let chip of this.chipObstacleSpatialIndex.chips){let bounds=chip.bounds;if(!(point6.x<bounds.minX-EPS12||point6.x>bounds.maxX+EPS12||point6.y<bounds.minY-EPS12||point6.y>bounds.maxY+EPS12))for(let[side,distance72]of getSideDistances(point6,bounds))distance72<nearestDistance&&(nearestSide=side,nearestDistance=distance72)}return nearestSide}getOutsideChipSide(point6){let nearestSide=null,nearestDistanceSq=Number.POSITIVE_INFINITY;for(let chip of this.chipObstacleSpatialIndex.chips){let bounds=chip.bounds,dx3=point6.x<bounds.minX-EPS12?bounds.minX-point6.x:point6.x>bounds.maxX+EPS12?point6.x-bounds.maxX:0,dy3=point6.y<bounds.minY-EPS12?bounds.minY-point6.y:point6.y>bounds.maxY+EPS12?point6.y-bounds.maxY:0;if(dx3===0&&dy3===0)continue;let distanceSq=dx3**2+dy3**2;distanceSq>=nearestDistanceSq||(nearestDistanceSq=distanceSq,dx3>0?nearestSide=point6.x<bounds.minX?"left":"right":nearestSide=point6.y<bounds.minY?"bottom":"top")}return nearestSide}getNearestChipSide(point6){let nearestSide=null,nearestDistance=Number.POSITIVE_INFINITY;for(let chip of this.chipObstacleSpatialIndex.chips)for(let[side,distance72]of getSideDistances(point6,chip.bounds))distance72<nearestDistance&&(nearestSide=side,nearestDistance=distance72);return nearestSide}visualize(){return visualizeAvailableNetOrientationSolver({inputProblem:this.inputProblem,traces:this.traces,outputNetLabelPlacements:this.outputNetLabelPlacements,currentLabel:this.currentLabel,currentCandidateResults:this.currentCandidateResults,solved:this.solved})}},CANDIDATE_SELECTED_COLOR3="blue",CANDIDATE_REJECTED_COLOR3="red",visualizeRailNetLabelCornerPlacementSolver=state2=>{let graphics=visualizeInputProblem2(state2.inputProblem);return ensureGraphicsArrays2(graphics),drawTraces3(graphics,state2.traces),drawNetLabels3(graphics,state2.outputNetLabelPlacements),state2.solved||(drawCurrentLabel2(graphics,state2.currentLabel),drawCurrentCandidates3(graphics,state2.currentCandidateResults)),graphics},drawTraces3=(graphics,traces)=>{for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels3=(graphics,labels)=>{for(let label of labels)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
665
665
  globalConnNetId: ${label.globalConnNetId}`}),graphics.points.push({x:label.anchorPoint.x,y:label.anchorPoint.y,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
666
666
  orientation: ${label.orientation}`})},drawCurrentLabel2=(graphics,currentLabel)=>{currentLabel&&graphics.rects.push({center:currentLabel.center,width:currentLabel.width,height:currentLabel.height,fill:"rgba(255, 0, 0, 0.2)",strokeColor:CANDIDATE_REJECTED_COLOR3,label:`trace-line VCC target
667
667
  ${currentLabel.netId??currentLabel.globalConnNetId}`})},drawCurrentCandidates3=(graphics,candidates)=>{for(let candidate of candidates){let color=candidate.selected?CANDIDATE_SELECTED_COLOR3:CANDIDATE_REJECTED_COLOR3;graphics.rects.push({center:candidate.center,width:candidate.width,height:candidate.height,fill:candidate.selected?"rgba(0, 0, 255, 0.2)":"rgba(255, 0, 0, 0.15)",strokeColor:color,strokeDash:candidate.selected?void 0:"4 2",label:`${candidate.selected?"selected":candidate.status} trace corner
668
668
  trace: ${candidate.traceId}
669
669
  distance: ${candidate.distance.toFixed(3)}`}),graphics.points.push({...candidate.anchorPoint,color,label:`candidate anchor
670
- ${candidate.status}`})}},ensureGraphicsArrays2=graphics=>{graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.rects||(graphics.rects=[]),graphics.circles||(graphics.circles=[]),graphics.texts||(graphics.texts=[])},LABEL_TRACE_CLEARANCE3=.1,RailNetLabelCornerPlacementSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"outputNetLabelPlacements");__publicField(this,"queuedLabelIndices",[]);__publicField(this,"currentLabelIndex",null);__publicField(this,"currentLabel",null);__publicField(this,"currentCandidateResults",[]);__publicField(this,"queuedCornerCandidates",[]);__publicField(this,"shouldAdvanceToNextLabel",!1);__publicField(this,"traceMap");this.inputProblem=params.inputProblem,this.traces=params.traces,this.netLabelPlacements=params.netLabelPlacements,this.outputNetLabelPlacements=[...params.netLabelPlacements],this.traceMap=Object.fromEntries(params.traces.map(trace=>[trace.mspPairId,trace])),this.queuedLabelIndices=this.getProcessableLabelIndices(),this.prepareNextLabel()}getConstructorParams(){return{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.netLabelPlacements}}_step(){if(this.shouldAdvanceToNextLabel){this.advanceToNextLabel();return}let label=this.currentLabel,labelIndex=this.currentLabelIndex;if(label===null||labelIndex===null){this.finish();return}let candidate=this.queuedCornerCandidates.shift();if(!candidate){this.shouldAdvanceToNextLabel=!0;return}let result=this.evaluateCornerCandidate(label,labelIndex,candidate);this.currentCandidateResults.push(result),result.status==="valid"&&(result.selected=!0,this.applyCandidate(labelIndex,label,result),this.shouldAdvanceToNextLabel=!0)}getOutput(){return{traces:this.traces,netLabelPlacements:this.outputNetLabelPlacements}}getProcessableLabelIndices(){let labelIndices=[];for(let i6=0;i6<this.outputNetLabelPlacements.length;i6++){let label=this.outputNetLabelPlacements[i6];this.shouldProcessLabel(label)&&labelIndices.push(i6)}return labelIndices}prepareNextLabel(){let labelIndex=this.queuedLabelIndices.shift();if(labelIndex===void 0)return this.clearCurrentLabel(),!1;let label=this.outputNetLabelPlacements[labelIndex];return this.currentLabelIndex=labelIndex,this.currentLabel=label,this.currentCandidateResults=[],this.queuedCornerCandidates=this.getCornerCandidatesForLabel(label),!0}advanceToNextLabel(){this.shouldAdvanceToNextLabel=!1,this.prepareNextLabel()||this.finish()}clearCurrentLabel(){this.currentLabelIndex=null,this.currentLabel=null,this.currentCandidateResults=[],this.queuedCornerCandidates=[]}finish(){this.clearCurrentLabel(),this.solved=!0}evaluateCornerCandidate(label,labelIndex,candidate){let center2=getCenterFromAnchor(candidate.anchorPoint,label.orientation,label.width,label.height),bounds=getRectBounds(center2,label.width,label.height);return{...candidate,center:center2,width:label.width,height:label.height,status:this.getCandidateStatus(bounds,labelIndex,candidate),selected:!1}}getCandidateStatus(bounds,labelIndex,candidate){if(this.intersectsAnyChip(bounds))return"chip-collision";if(rectIntersectsAnyTextBox(bounds,this.inputProblem))return"text-collision";let candidateTraceMap=candidate.reroutedTracePath?{...this.traceMap,[candidate.traceId]:{...this.traceMap[candidate.traceId],tracePath:candidate.reroutedTracePath}}:this.traceMap;return traceCrossesBoundsInterior(bounds,candidateTraceMap)||candidate.reroutedTracePath&&!this.isReroutedTraceClear(candidate,labelIndex)?"trace-collision":this.intersectsAnyOtherNetLabel(bounds,labelIndex)?"netlabel-collision":"valid"}applyCandidate(labelIndex,label,candidate){if(candidate.reroutedTracePath){let originalTrace=this.traceMap[candidate.traceId],reroutedTrace={...originalTrace,tracePath:candidate.reroutedTracePath};this.traces=this.traces.map(trace=>trace.mspPairId===candidate.traceId?reroutedTrace:trace),this.traceMap[candidate.traceId]=reroutedTrace,this.outputNetLabelPlacements=moveAttachedLabelsToReroutedTrace({trace:originalTrace,originalTracePath:originalTrace.tracePath,reroutedTracePath:candidate.reroutedTracePath,netLabelPlacements:this.outputNetLabelPlacements})}this.outputNetLabelPlacements[labelIndex]={...label,anchorPoint:candidate.anchorPoint,center:candidate.center}}shouldProcessLabel(label){return(label.orientation==="y+"||label.orientation==="y-")&&this.getCornerCandidatesForLabel(label).length>0}intersectsAnyChip(bounds){return this.inputProblem.chips.some(chip=>rectsOverlap(bounds,getRectBounds(chip.center,chip.width,chip.height)))}intersectsAnyOtherNetLabel(bounds,labelIndex){return this.outputNetLabelPlacements.some((label,index)=>index===labelIndex?!1:rectsOverlap(bounds,getRectBounds(label.center,label.width,label.height)))}getCornerCandidatesForLabel(label){let anchorAlignedCandidates=[],railAlignedCandidates=[],labelTraces=this.getTraceLinesForLabel(label),allowRailAlignedFallback=this.isConfiguredRailLabel(label)&&(this.isLabelCrossedByOtherNetTrace(label)||!labelTraces.some(trace=>getTraceCorners(trace.tracePath).some(corner=>this.pointsEqual(corner,label.anchorPoint))));for(let trace of labelTraces){let path=trace.tracePath,pins=[path[0],path[path.length-1]];for(let anchorPoint of getTraceCorners(path)){let cornerIndex=path.indexOf(anchorPoint),anchorAlignedToPin=pins.some(pin=>Math.abs(pin.x-anchorPoint.x)<=EPS7),pinAligned=anchorAlignedToPin||allowRailAlignedFallback&&this.isPinAlignedCorner(path,cornerIndex);if(!pinAligned)continue;(anchorAlignedToPin?anchorAlignedCandidates:railAlignedCandidates).push({anchorPoint,traceId:trace.mspPairId,distance:getDistance(anchorPoint,label.anchorPoint),pinAligned},...this.getClearanceShiftedCornerCandidates({label,trace,cornerIndex,pinAligned}))}}return[...anchorAlignedCandidates.sort((a6,b6)=>a6.distance-b6.distance),...railAlignedCandidates.sort((a6,b6)=>a6.distance-b6.distance)]}isConfiguredRailLabel(label){return label.netId?this.inputProblem.availableNetLabelOrientations[label.netId]?.some(orientation4=>orientation4==="y+"||orientation4==="y-"):!1}isLabelCrossedByOtherNetTrace(label){let bounds=getRectBounds(label.center,label.width,label.height),otherNetTraceMap=Object.fromEntries(this.traces.filter(trace=>trace.globalConnNetId!==label.globalConnNetId).map(trace=>[trace.mspPairId,trace]));return traceCrossesBoundsInterior(bounds,otherNetTraceMap)}pointsEqual(a6,b6){return Math.abs(a6.x-b6.x)<=EPS7&&Math.abs(a6.y-b6.y)<=EPS7}getVerticalSegmentPointIndices(path,cornerIndex){let corner=path[cornerIndex],previousIsVertical=Math.abs(path[cornerIndex-1].x-corner.x)<=EPS7,nextIsVertical=Math.abs(path[cornerIndex+1].x-corner.x)<=EPS7;return previousIsVertical===nextIsVertical?null:previousIsVertical?[cornerIndex-1,cornerIndex]:[cornerIndex,cornerIndex+1]}isPinAlignedCorner(path,cornerIndex){let verticalPointIndices=this.getVerticalSegmentPointIndices(path,cornerIndex);if(!verticalPointIndices)return!1;let[startIndex,endIndex]=verticalPointIndices;return startIndex<=1||endIndex>=path.length-2}getClearanceShiftedCornerCandidates({label,trace,cornerIndex,pinAligned}){if(label.orientation!=="y+"&&label.orientation!=="y-")return[];let path=trace.tracePath,corner=path[cornerIndex],verticalPointIndices=this.getVerticalSegmentPointIndices(path,cornerIndex);if(!verticalPointIndices||verticalPointIndices.includes(0)||verticalPointIndices.includes(path.length-1))return[];let center2=getCenterFromAnchor(corner,label.orientation,label.width,label.height),labelBounds=getRectBounds(center2,label.width,label.height),collidingChipBounds=this.inputProblem.chips.map(chip=>getRectBounds(chip.center,chip.width,chip.height)).filter(chipBounds=>rectsOverlap(labelBounds,chipBounds)),shiftedCoordinates=new Set;for(let chipBounds of collidingChipBounds)shiftedCoordinates.add(chipBounds.minX-label.width/2),shiftedCoordinates.add(chipBounds.maxX+label.width/2);for(let otherTrace of this.traces)if(otherTrace.globalConnNetId!==label.globalConnNetId)for(let i6=0;i6<otherTrace.tracePath.length-1;i6++){let start=otherTrace.tracePath[i6],end=otherTrace.tracePath[i6+1];if(!segmentCrossesBoundsInterior(start,end,labelBounds))continue;let halfLabelWidth=label.width/2;Math.abs(start.x-end.x)<=EPS7?(shiftedCoordinates.add(start.x-halfLabelWidth-LABEL_TRACE_CLEARANCE3),shiftedCoordinates.add(start.x+halfLabelWidth+LABEL_TRACE_CLEARANCE3)):(shiftedCoordinates.add(Math.min(start.x,end.x)-halfLabelWidth-LABEL_TRACE_CLEARANCE3),shiftedCoordinates.add(Math.max(start.x,end.x)+halfLabelWidth+LABEL_TRACE_CLEARANCE3))}return[...shiftedCoordinates].flatMap(x6=>{if(Math.abs(x6-corner.x)<=EPS7)return[];let reroutedTracePath=simplifyPath(path.map((point6,pointIndex)=>verticalPointIndices.includes(pointIndex)?{...point6,x:x6}:point6)),anchorPoint={x:x6,y:corner.y};return getTraceCorners(reroutedTracePath).some(point6=>this.pointsEqual(point6,anchorPoint))?[{anchorPoint,traceId:trace.mspPairId,distance:getDistance(anchorPoint,label.anchorPoint),pinAligned,reroutedTracePath}]:[]})}isReroutedTraceClear(candidate,labelIndex){let reroutedTracePath=candidate.reroutedTracePath;if(isPathCollidingWithObstacles(reroutedTracePath,getObstacleRects(this.inputProblem)))return!1;let candidateTrace=this.traceMap[candidate.traceId],otherNetTraces=this.traces.filter(trace=>trace.mspPairId!==candidate.traceId&&trace.globalConnNetId!==candidateTrace.globalConnNetId);if(doesPathOverlapTraceStrokes(reroutedTracePath,otherNetTraces))return!1;let reroutedTraceMap={[candidate.traceId]:{...candidateTrace,tracePath:reroutedTracePath}};return this.outputNetLabelPlacements.every((label,index)=>index===labelIndex?!0:!traceCrossesBoundsInterior(getRectBounds(label.center,label.width,label.height),reroutedTraceMap))}getTraceLinesForLabel(label){return this.traces.filter(trace=>isTraceLine(trace)&&this.isTraceForLabel(trace,label))}isTraceForLabel(trace,label){if(!tracePathContainsPoint(trace.tracePath,label.anchorPoint))return!1;let traceIds=new Set(label.mspConnectionPairIds);return traceIds.size>0?traceIds.has(trace.mspPairId):trace.globalConnNetId===label.globalConnNetId}visualize(){return visualizeRailNetLabelCornerPlacementSolver({inputProblem:this.inputProblem,traces:this.traces,outputNetLabelPlacements:this.outputNetLabelPlacements,currentLabel:this.currentLabel,currentCandidateResults:this.currentCandidateResults,solved:this.solved})}},dedupeOrientations=orientations=>[...new Set(orientations)],dedupeStrings=values=>[...new Set(values.filter(value=>value!==void 0))],getOrientationConstraintKeys=(inputProblem,label)=>dedupeStrings([label.netId,label.globalConnNetId,...inputProblem.netConnections.filter(connection=>label.pinIds.some(pinId=>connection.pinIds.includes(pinId))).map(connection=>connection.netId)]),normalizeFacingDirection=value=>{switch(value){case"x+":case"+x":return"x+";case"x-":case"-x":return"x-";case"y+":case"+y":return"y+";case"y-":case"-y":return"y-"}},getOrientationConstraint=(inputProblem,label)=>{let availableOrientations=inputProblem.availableNetLabelOrientations??{};for(let netId of getOrientationConstraintKeys(inputProblem,label))if(Object.hasOwn(availableOrientations,netId))return dedupeOrientations((availableOrientations[netId]??[]).map(normalizeFacingDirection).filter(orientation4=>orientation4!==void 0));return null},EPS13=1e-6,TRACE_BOUNDARY_TOLERANCE2=1e-6,getLabelBounds=label=>getRectBounds(label.center,label.width,label.height),rectsOverlap3=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>EPS13&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>EPS13,rectsTouchOrOverlap=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>=-EPS13&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>=-EPS13,traceCrossesBoundsInterior2=(bounds,traces)=>{for(let trace of traces){let points=trace.tracePath;for(let i6=0;i6<points.length-1;i6++)if(segmentCrossesBoundsInterior2(points[i6],points[i6+1],bounds))return!0}return!1},getTraceLocationsForPoint=(point6,traces)=>{let locations=[];for(let trace of traces){if(getUniquePinCount2(trace.pinIds)<2)continue;let pathDistance=0;for(let i6=0;i6<trace.tracePath.length-1;i6++){let start=trace.tracePath[i6],end=trace.tracePath[i6+1],segmentLength=getManhattanDistance(start,end);isPointOnSegment22(point6,start,end)&&locations.push({trace,distance:pathDistance+getManhattanDistance(start,point6)}),pathDistance+=segmentLength}}return locations},getTraceLength=trace=>{let length4=0;for(let i6=0;i6<trace.tracePath.length-1;i6++)length4+=getManhattanDistance(trace.tracePath[i6],trace.tracePath[i6+1]);return length4},getPointAtTraceDistance=(trace,distance52)=>{let pathDistance=0;for(let i6=0;i6<trace.tracePath.length-1;i6++){let start=trace.tracePath[i6],end=trace.tracePath[i6+1],segmentLength=getManhattanDistance(start,end),nextDistance=pathDistance+segmentLength;if(distance52<=nextDistance+EPS13){let offset=Math.max(0,Math.min(segmentLength,distance52-pathDistance)),direction2=getSegmentDirection(start,end);return{x:start.x+direction2.x*offset,y:start.y+direction2.y*offset}}pathDistance=nextDistance}return trace.tracePath[trace.tracePath.length-1]},getTraceVertexDistances=trace=>{let distances=[],pathDistance=0;for(let i6=0;i6<trace.tracePath.length;i6++){distances.push(pathDistance);let nextPoint=trace.tracePath[i6+1];nextPoint&&(pathDistance+=getManhattanDistance(trace.tracePath[i6],nextPoint))}return distances},getManhattanDistance=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),segmentCrossesBoundsInterior2=(start,end,bounds)=>{let interior={minX:bounds.minX+TRACE_BOUNDARY_TOLERANCE2,minY:bounds.minY+TRACE_BOUNDARY_TOLERANCE2,maxX:bounds.maxX-TRACE_BOUNDARY_TOLERANCE2,maxY:bounds.maxY-TRACE_BOUNDARY_TOLERANCE2};return interior.minX>=interior.maxX||interior.minY>=interior.maxY?!1:isVertical4(start,end)?start.x<=interior.minX+EPS13||start.x>=interior.maxX-EPS13?!1:rangesOverlap2(Math.min(start.y,end.y),Math.max(start.y,end.y),interior.minY,interior.maxY):isHorizontal3(start,end)?start.y<=interior.minY+EPS13||start.y>=interior.maxY-EPS13?!1:rangesOverlap2(Math.min(start.x,end.x),Math.max(start.x,end.x),interior.minX,interior.maxX):!1},isPointOnSegment22=(point6,start,end)=>isHorizontal3(start,end)?Math.abs(point6.y-start.y)<=EPS13&&point6.x>=Math.min(start.x,end.x)-EPS13&&point6.x<=Math.max(start.x,end.x)+EPS13:isVertical4(start,end)?Math.abs(point6.x-start.x)<=EPS13&&point6.y>=Math.min(start.y,end.y)-EPS13&&point6.y<=Math.max(start.y,end.y)+EPS13:!1,getSegmentDirection=(start,end)=>({x:isVertical4(start,end)?0:Math.sign(end.x-start.x),y:isHorizontal3(start,end)?0:Math.sign(end.y-start.y)}),isHorizontal3=(start,end)=>Math.abs(start.y-end.y)<=EPS13,isVertical4=(start,end)=>Math.abs(start.x-end.x)<=EPS13,rangesOverlap2=(minA,maxA,minB,maxB)=>Math.min(maxA,maxB)-Math.max(minA,minB)>EPS13,getUniquePinCount2=pinIds=>new Set(pinIds).size,CANDIDATE_STEP=.1,generateCandidatesAlongTrace=params=>{let{inputProblem,label,traceLocation}=params,traceLength2=getTraceLength(traceLocation.trace),orientationConstraint=getOrientationConstraint(inputProblem,label),candidateDistances=getCandidateDistances(traceLength2,getTraceVertexDistances(traceLocation.trace)),netLabelWidth=getNetLabelWidth(inputProblem,label),netLabelHeight=getNetLabelHeight(inputProblem,label),candidates=[],seenCandidateKeys=new Set;for(let pathDistance of candidateDistances){let point6=getPointAtTraceDistance(traceLocation.trace,pathDistance),orientations=getOrientationsForPoint({inputProblem,label,point:point6,orientationConstraint});for(let orientation4 of orientations){if(isSamePlacement(label,point6,orientation4))continue;let key=[point6.x.toFixed(6),point6.y.toFixed(6),orientation4].join(":");seenCandidateKeys.has(key)||(seenCandidateKeys.add(key),candidates.push(createCandidate({point:point6,orientation:orientation4,netLabelWidth,netLabelHeight,traceLocation,pathDistance,label})))}}return candidates},getCandidateDistances=(traceLength2,vertexDistances)=>{let distances=new Set,maxSteps=Math.ceil(traceLength2/CANDIDATE_STEP);for(let i6=0;i6<=maxSteps;i6++){let distance52=Math.min(traceLength2,i6*CANDIDATE_STEP);distances.add(roundDistance(distance52))}for(let distance52 of vertexDistances)distances.add(roundDistance(distance52));return[...distances].filter(distance52=>distance52>=-EPS13&&distance52<=traceLength2+EPS13).sort((a6,b6)=>a6-b6)},getOrientationsForPoint=params=>{let{inputProblem,label,point:point6,orientationConstraint}=params;return orientationConstraint||getUnconstrainedOrientations({label,inputProblem,point:point6})},createCandidate=params=>{let{point:point6,orientation:orientation4,netLabelWidth,netLabelHeight,traceLocation,pathDistance,label}=params,{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth,netLabelHeight});return{anchorPoint:point6,center:getCenterFromAnchor(point6,orientation4,width,height),width,height,orientation:orientation4,traceId:traceLocation.trace.mspPairId,pathDistance,distanceFromOriginal:getManhattanDistance(point6,label.anchorPoint),status:"valid",selected:!1}},getUnconstrainedOrientations=params=>{let{label,inputProblem,point:point6}=params;return dedupeOrientations([...getInitialOrientations(label),...getOutwardOrientations({inputProblem,point:point6}),...ALL_ORIENTATIONS])},getInitialOrientations=label=>[label.orientation,getFlippedOrientation(label.orientation)],getOutwardOrientations=params=>{let{inputProblem,point:point6}=params,chipBounds=getChipBounds4(inputProblem);return dedupeOrientations(getOutwardOrientationOptions(point6,chipBounds).sort((a6,b6)=>b6.outwardScore-a6.outwardScore).map(({orientation:orientation4})=>orientation4))},getOutwardOrientationOptions=(point6,chipBounds)=>{let options=[];return options.push(getOutwardAxisOption({value:point6.y,min:chipBounds.minY,max:chipBounds.maxY,center:chipBounds.centerY,positiveOrientation:"y+",negativeOrientation:"y-"})),options.push(getOutwardAxisOption({value:point6.x,min:chipBounds.minX,max:chipBounds.maxX,center:chipBounds.centerX,positiveOrientation:"x+",negativeOrientation:"x-"})),options},getOutwardAxisOption=params=>{let{value,min,max:max2,center:center2,positiveOrientation,negativeOrientation}=params;return value>max2+EPS13?{orientation:positiveOrientation,outwardScore:1+value-max2}:value<min-EPS13?{orientation:negativeOrientation,outwardScore:1+min-value}:{orientation:value>=center2?positiveOrientation:negativeOrientation,outwardScore:getNormalizedCenterDistance(value,center2,max2-min)}},getNormalizedCenterDistance=(value,center2,span)=>Math.abs(value-center2)/Math.max(EPS13,span/2),ALL_ORIENTATIONS=["x+","x-","y+","y-"],getFlippedOrientation=orientation4=>{switch(orientation4){case"x+":return"x-";case"x-":return"x+";case"y+":return"y-";case"y-":return"y+"}},getChipBounds4=inputProblem=>{if(inputProblem.chips.length===0)return{minX:0,minY:0,maxX:0,maxY:0,centerX:0,centerY:0};let bounds=inputProblem.chips.reduce((acc,chip)=>({minX:Math.min(acc.minX,chip.center.x-chip.width/2),minY:Math.min(acc.minY,chip.center.y-chip.height/2),maxX:Math.max(acc.maxX,chip.center.x+chip.width/2),maxY:Math.max(acc.maxY,chip.center.y+chip.height/2)}),{minX:Number.POSITIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY});return{...bounds,centerX:(bounds.minX+bounds.maxX)/2,centerY:(bounds.minY+bounds.maxY)/2}},getNetLabelWidth=(inputProblem,label)=>{let configuredWidth=getNetLabelWidthForConnection({inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:label.mspConnectionPairIds.length===0});return configuredWidth!==void 0?configuredWidth:label.orientation==="y+"||label.orientation==="y-"?label.height:label.width},getNetLabelHeight=(inputProblem,label)=>{let ncHeightByNetId=inputProblem.netConnections.find(connection=>connection.netId===label.netId)?.netLabelHeight;return ncHeightByNetId!==void 0?ncHeightByNetId:inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>label.pinIds.includes(pid)))?.netLabelHeight},roundDistance=distance52=>Number(distance52.toFixed(6)),isSamePlacement=(label,point6,orientation4)=>Math.abs(point6.x-label.anchorPoint.x)<=EPS13&&Math.abs(point6.y-label.anchorPoint.y)<=EPS13&&orientation4===label.orientation,CANDIDATE_SELECTED_COLOR4="blue",CANDIDATE_REJECTED_COLOR4="red",visualizeTraceAnchoredNetLabelOverlapSolver=state2=>{let graphics=visualizeInputProblem2(state2.inputProblem);return ensureGraphicsArrays3(graphics),drawTraces4(graphics,state2.traces),drawNetLabels4(graphics,state2.inputProblem,state2.outputNetLabelPlacements),state2.solved||(drawCurrentOverlap2(graphics,state2),drawCurrentCandidates4(graphics,state2.currentCandidateResults)),graphics},drawTraces4=(graphics,traces)=>{for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels4=(graphics,inputProblem,labels)=>{for(let label of labels)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:getNetLabelVisualizationLabel(inputProblem,label)}),graphics.points.push({x:label.anchorPoint.x,y:label.anchorPoint.y,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
670
+ ${candidate.status}`})}},ensureGraphicsArrays2=graphics=>{graphics.lines||(graphics.lines=[]),graphics.points||(graphics.points=[]),graphics.rects||(graphics.rects=[]),graphics.circles||(graphics.circles=[]),graphics.texts||(graphics.texts=[])},LABEL_TRACE_CLEARANCE3=.1,RailNetLabelCornerPlacementSolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"outputNetLabelPlacements");__publicField(this,"queuedLabelIndices",[]);__publicField(this,"currentLabelIndex",null);__publicField(this,"currentLabel",null);__publicField(this,"currentCandidateResults",[]);__publicField(this,"queuedCornerCandidates",[]);__publicField(this,"shouldAdvanceToNextLabel",!1);__publicField(this,"traceMap");this.inputProblem=params.inputProblem,this.traces=params.traces,this.netLabelPlacements=params.netLabelPlacements,this.outputNetLabelPlacements=[...params.netLabelPlacements],this.traceMap=Object.fromEntries(params.traces.map(trace=>[trace.mspPairId,trace])),this.queuedLabelIndices=this.getProcessableLabelIndices(),this.prepareNextLabel()}getConstructorParams(){return{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.netLabelPlacements}}_step(){if(this.shouldAdvanceToNextLabel){this.advanceToNextLabel();return}let label=this.currentLabel,labelIndex=this.currentLabelIndex;if(label===null||labelIndex===null){this.finish();return}let candidate=this.queuedCornerCandidates.shift();if(!candidate){this.shouldAdvanceToNextLabel=!0;return}let result=this.evaluateCornerCandidate(label,labelIndex,candidate);this.currentCandidateResults.push(result),result.status==="valid"&&(result.selected=!0,this.applyCandidate(labelIndex,label,result),this.shouldAdvanceToNextLabel=!0)}getOutput(){return{traces:this.traces,netLabelPlacements:this.outputNetLabelPlacements}}getProcessableLabelIndices(){let labelIndices=[];for(let i6=0;i6<this.outputNetLabelPlacements.length;i6++){let label=this.outputNetLabelPlacements[i6];this.shouldProcessLabel(label)&&labelIndices.push(i6)}return labelIndices}prepareNextLabel(){let labelIndex=this.queuedLabelIndices.shift();if(labelIndex===void 0)return this.clearCurrentLabel(),!1;let label=this.outputNetLabelPlacements[labelIndex];return this.currentLabelIndex=labelIndex,this.currentLabel=label,this.currentCandidateResults=[],this.queuedCornerCandidates=this.getCornerCandidatesForLabel(label),!0}advanceToNextLabel(){this.shouldAdvanceToNextLabel=!1,this.prepareNextLabel()||this.finish()}clearCurrentLabel(){this.currentLabelIndex=null,this.currentLabel=null,this.currentCandidateResults=[],this.queuedCornerCandidates=[]}finish(){this.clearCurrentLabel(),this.solved=!0}evaluateCornerCandidate(label,labelIndex,candidate){let center2=getCenterFromAnchor(candidate.anchorPoint,label.orientation,label.width,label.height),bounds=getRectBounds(center2,label.width,label.height);return{...candidate,center:center2,width:label.width,height:label.height,status:this.getCandidateStatus(bounds,labelIndex,candidate),selected:!1}}getCandidateStatus(bounds,labelIndex,candidate){if(this.intersectsAnyChip(bounds))return"chip-collision";if(rectIntersectsAnyTextBox(bounds,this.inputProblem))return"text-collision";let candidateTraceMap=candidate.reroutedTracePath?{...this.traceMap,[candidate.traceId]:{...this.traceMap[candidate.traceId],tracePath:candidate.reroutedTracePath}}:this.traceMap;return traceCrossesBoundsInterior(bounds,candidateTraceMap)||candidate.reroutedTracePath&&!this.isReroutedTraceClear(candidate,labelIndex)?"trace-collision":this.intersectsAnyOtherNetLabel(bounds,labelIndex)?"netlabel-collision":"valid"}applyCandidate(labelIndex,label,candidate){if(candidate.reroutedTracePath){let originalTrace=this.traceMap[candidate.traceId],reroutedTrace={...originalTrace,tracePath:candidate.reroutedTracePath};this.traces=this.traces.map(trace=>trace.mspPairId===candidate.traceId?reroutedTrace:trace),this.traceMap[candidate.traceId]=reroutedTrace,this.outputNetLabelPlacements=moveAttachedLabelsToReroutedTrace({trace:originalTrace,originalTracePath:originalTrace.tracePath,reroutedTracePath:candidate.reroutedTracePath,netLabelPlacements:this.outputNetLabelPlacements})}this.outputNetLabelPlacements[labelIndex]={...label,anchorPoint:candidate.anchorPoint,center:candidate.center}}shouldProcessLabel(label){return(label.orientation==="y+"||label.orientation==="y-")&&this.getCornerCandidatesForLabel(label).length>0}intersectsAnyChip(bounds){return this.inputProblem.chips.some(chip=>rectsOverlap(bounds,getRectBounds(chip.center,chip.width,chip.height)))}intersectsAnyOtherNetLabel(bounds,labelIndex){return this.outputNetLabelPlacements.some((label,index)=>index===labelIndex?!1:rectsOverlap(bounds,getRectBounds(label.center,label.width,label.height)))}getCornerCandidatesForLabel(label){let anchorAlignedCandidates=[],railAlignedCandidates=[],labelTraces=this.getTraceLinesForLabel(label),allowRailAlignedFallback=this.isConfiguredRailLabel(label)&&(this.isLabelCrossedByOtherNetTrace(label)||!labelTraces.some(trace=>getTraceCorners(trace.tracePath).some(corner=>this.pointsEqual(corner,label.anchorPoint))));for(let trace of labelTraces){let path=trace.tracePath,pins=[path[0],path[path.length-1]];for(let anchorPoint of getTraceCorners(path)){let cornerIndex=path.indexOf(anchorPoint),anchorAlignedToPin=pins.some(pin=>Math.abs(pin.x-anchorPoint.x)<=EPS7),pinAligned=anchorAlignedToPin||allowRailAlignedFallback&&this.isPinAlignedCorner(path,cornerIndex);if(!pinAligned)continue;(anchorAlignedToPin?anchorAlignedCandidates:railAlignedCandidates).push({anchorPoint,traceId:trace.mspPairId,distance:getDistance(anchorPoint,label.anchorPoint),pinAligned},...this.getClearanceShiftedCornerCandidates({label,trace,cornerIndex,pinAligned}))}}return[...anchorAlignedCandidates.sort((a6,b6)=>a6.distance-b6.distance),...railAlignedCandidates.sort((a6,b6)=>a6.distance-b6.distance)]}isConfiguredRailLabel(label){return label.netId?this.inputProblem.availableNetLabelOrientations[label.netId]?.some(orientation4=>orientation4==="y+"||orientation4==="y-"):!1}isLabelCrossedByOtherNetTrace(label){let bounds=getRectBounds(label.center,label.width,label.height),otherNetTraceMap=Object.fromEntries(this.traces.filter(trace=>trace.globalConnNetId!==label.globalConnNetId).map(trace=>[trace.mspPairId,trace]));return traceCrossesBoundsInterior(bounds,otherNetTraceMap)}pointsEqual(a6,b6){return Math.abs(a6.x-b6.x)<=EPS7&&Math.abs(a6.y-b6.y)<=EPS7}getVerticalSegmentPointIndices(path,cornerIndex){let corner=path[cornerIndex],previousIsVertical=Math.abs(path[cornerIndex-1].x-corner.x)<=EPS7,nextIsVertical=Math.abs(path[cornerIndex+1].x-corner.x)<=EPS7;return previousIsVertical===nextIsVertical?null:previousIsVertical?[cornerIndex-1,cornerIndex]:[cornerIndex,cornerIndex+1]}isPinAlignedCorner(path,cornerIndex){let verticalPointIndices=this.getVerticalSegmentPointIndices(path,cornerIndex);if(!verticalPointIndices)return!1;let[startIndex,endIndex]=verticalPointIndices;return startIndex<=1||endIndex>=path.length-2}getClearanceShiftedCornerCandidates({label,trace,cornerIndex,pinAligned}){if(label.orientation!=="y+"&&label.orientation!=="y-")return[];let path=trace.tracePath,corner=path[cornerIndex],verticalPointIndices=this.getVerticalSegmentPointIndices(path,cornerIndex);if(!verticalPointIndices||verticalPointIndices.includes(0)||verticalPointIndices.includes(path.length-1))return[];let center2=getCenterFromAnchor(corner,label.orientation,label.width,label.height),labelBounds=getRectBounds(center2,label.width,label.height),collidingChipBounds=this.inputProblem.chips.map(chip=>getRectBounds(chip.center,chip.width,chip.height)).filter(chipBounds=>rectsOverlap(labelBounds,chipBounds)),shiftedCoordinates=new Set;for(let chipBounds of collidingChipBounds)shiftedCoordinates.add(chipBounds.minX-label.width/2),shiftedCoordinates.add(chipBounds.maxX+label.width/2);for(let otherTrace of this.traces)if(otherTrace.globalConnNetId!==label.globalConnNetId)for(let i6=0;i6<otherTrace.tracePath.length-1;i6++){let start=otherTrace.tracePath[i6],end=otherTrace.tracePath[i6+1];if(!segmentCrossesBoundsInterior(start,end,labelBounds))continue;let halfLabelWidth=label.width/2;Math.abs(start.x-end.x)<=EPS7?(shiftedCoordinates.add(start.x-halfLabelWidth-LABEL_TRACE_CLEARANCE3),shiftedCoordinates.add(start.x+halfLabelWidth+LABEL_TRACE_CLEARANCE3)):(shiftedCoordinates.add(Math.min(start.x,end.x)-halfLabelWidth-LABEL_TRACE_CLEARANCE3),shiftedCoordinates.add(Math.max(start.x,end.x)+halfLabelWidth+LABEL_TRACE_CLEARANCE3))}return[...shiftedCoordinates].flatMap(x6=>{if(Math.abs(x6-corner.x)<=EPS7)return[];let reroutedTracePath=simplifyPath(path.map((point6,pointIndex)=>verticalPointIndices.includes(pointIndex)?{...point6,x:x6}:point6)),anchorPoint={x:x6,y:corner.y};return getTraceCorners(reroutedTracePath).some(point6=>this.pointsEqual(point6,anchorPoint))?[{anchorPoint,traceId:trace.mspPairId,distance:getDistance(anchorPoint,label.anchorPoint),pinAligned,reroutedTracePath}]:[]})}isReroutedTraceClear(candidate,labelIndex){let reroutedTracePath=candidate.reroutedTracePath;if(isPathCollidingWithObstacles(reroutedTracePath,getObstacleRects(this.inputProblem)))return!1;let candidateTrace=this.traceMap[candidate.traceId],otherNetTraces=this.traces.filter(trace=>trace.mspPairId!==candidate.traceId&&trace.globalConnNetId!==candidateTrace.globalConnNetId);if(doesPathOverlapTraceStrokes(reroutedTracePath,otherNetTraces))return!1;let reroutedTraceMap={[candidate.traceId]:{...candidateTrace,tracePath:reroutedTracePath}};return this.outputNetLabelPlacements.every((label,index)=>index===labelIndex?!0:!traceCrossesBoundsInterior(getRectBounds(label.center,label.width,label.height),reroutedTraceMap))}getTraceLinesForLabel(label){return this.traces.filter(trace=>isTraceLine(trace)&&this.isTraceForLabel(trace,label))}isTraceForLabel(trace,label){if(!tracePathContainsPoint(trace.tracePath,label.anchorPoint))return!1;let traceIds=new Set(label.mspConnectionPairIds);return traceIds.size>0?traceIds.has(trace.mspPairId):trace.globalConnNetId===label.globalConnNetId}visualize(){return visualizeRailNetLabelCornerPlacementSolver({inputProblem:this.inputProblem,traces:this.traces,outputNetLabelPlacements:this.outputNetLabelPlacements,currentLabel:this.currentLabel,currentCandidateResults:this.currentCandidateResults,solved:this.solved})}},dedupeOrientations=orientations=>[...new Set(orientations)],dedupeStrings=values=>[...new Set(values.filter(value=>value!==void 0))],getOrientationConstraintKeys=(inputProblem,label)=>dedupeStrings([label.netId,label.globalConnNetId,...inputProblem.netConnections.filter(connection=>label.pinIds.some(pinId=>connection.pinIds.includes(pinId))).map(connection=>connection.netId)]),normalizeFacingDirection=value=>{switch(value){case"x+":case"+x":return"x+";case"x-":case"-x":return"x-";case"y+":case"+y":return"y+";case"y-":case"-y":return"y-"}},getOrientationConstraint=(inputProblem,label)=>{let availableOrientations=inputProblem.availableNetLabelOrientations??{};for(let netId of getOrientationConstraintKeys(inputProblem,label))if(Object.hasOwn(availableOrientations,netId))return dedupeOrientations((availableOrientations[netId]??[]).map(normalizeFacingDirection).filter(orientation4=>orientation4!==void 0));return null},EPS13=1e-6,TRACE_BOUNDARY_TOLERANCE2=1e-6,getLabelBounds=label=>getRectBounds(label.center,label.width,label.height),rectsOverlap3=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>EPS13&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>EPS13,rectsTouchOrOverlap=(a6,b6)=>Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX)>=-EPS13&&Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY)>=-EPS13,traceCrossesBoundsInterior2=(bounds,traces)=>{for(let trace of traces){let points=trace.tracePath;for(let i6=0;i6<points.length-1;i6++)if(segmentCrossesBoundsInterior2(points[i6],points[i6+1],bounds))return!0}return!1},getTraceLocationsForPoint=(point6,traces)=>{let locations=[];for(let trace of traces){if(getUniquePinCount2(trace.pinIds)<2)continue;let pathDistance=0;for(let i6=0;i6<trace.tracePath.length-1;i6++){let start=trace.tracePath[i6],end=trace.tracePath[i6+1],segmentLength=getManhattanDistance(start,end);isPointOnSegment22(point6,start,end)&&locations.push({trace,distance:pathDistance+getManhattanDistance(start,point6)}),pathDistance+=segmentLength}}return locations},getTraceLength=trace=>{let length4=0;for(let i6=0;i6<trace.tracePath.length-1;i6++)length4+=getManhattanDistance(trace.tracePath[i6],trace.tracePath[i6+1]);return length4},getPointAtTraceDistance=(trace,distance72)=>{let pathDistance=0;for(let i6=0;i6<trace.tracePath.length-1;i6++){let start=trace.tracePath[i6],end=trace.tracePath[i6+1],segmentLength=getManhattanDistance(start,end),nextDistance=pathDistance+segmentLength;if(distance72<=nextDistance+EPS13){let offset=Math.max(0,Math.min(segmentLength,distance72-pathDistance)),direction2=getSegmentDirection(start,end);return{x:start.x+direction2.x*offset,y:start.y+direction2.y*offset}}pathDistance=nextDistance}return trace.tracePath[trace.tracePath.length-1]},getTraceVertexDistances=trace=>{let distances=[],pathDistance=0;for(let i6=0;i6<trace.tracePath.length;i6++){distances.push(pathDistance);let nextPoint=trace.tracePath[i6+1];nextPoint&&(pathDistance+=getManhattanDistance(trace.tracePath[i6],nextPoint))}return distances},getManhattanDistance=(a6,b6)=>Math.abs(a6.x-b6.x)+Math.abs(a6.y-b6.y),segmentCrossesBoundsInterior2=(start,end,bounds)=>{let interior={minX:bounds.minX+TRACE_BOUNDARY_TOLERANCE2,minY:bounds.minY+TRACE_BOUNDARY_TOLERANCE2,maxX:bounds.maxX-TRACE_BOUNDARY_TOLERANCE2,maxY:bounds.maxY-TRACE_BOUNDARY_TOLERANCE2};return interior.minX>=interior.maxX||interior.minY>=interior.maxY?!1:isVertical4(start,end)?start.x<=interior.minX+EPS13||start.x>=interior.maxX-EPS13?!1:rangesOverlap2(Math.min(start.y,end.y),Math.max(start.y,end.y),interior.minY,interior.maxY):isHorizontal3(start,end)?start.y<=interior.minY+EPS13||start.y>=interior.maxY-EPS13?!1:rangesOverlap2(Math.min(start.x,end.x),Math.max(start.x,end.x),interior.minX,interior.maxX):!1},isPointOnSegment22=(point6,start,end)=>isHorizontal3(start,end)?Math.abs(point6.y-start.y)<=EPS13&&point6.x>=Math.min(start.x,end.x)-EPS13&&point6.x<=Math.max(start.x,end.x)+EPS13:isVertical4(start,end)?Math.abs(point6.x-start.x)<=EPS13&&point6.y>=Math.min(start.y,end.y)-EPS13&&point6.y<=Math.max(start.y,end.y)+EPS13:!1,getSegmentDirection=(start,end)=>({x:isVertical4(start,end)?0:Math.sign(end.x-start.x),y:isHorizontal3(start,end)?0:Math.sign(end.y-start.y)}),isHorizontal3=(start,end)=>Math.abs(start.y-end.y)<=EPS13,isVertical4=(start,end)=>Math.abs(start.x-end.x)<=EPS13,rangesOverlap2=(minA,maxA,minB,maxB)=>Math.min(maxA,maxB)-Math.max(minA,minB)>EPS13,getUniquePinCount2=pinIds=>new Set(pinIds).size,CANDIDATE_STEP=.1,generateCandidatesAlongTrace=params=>{let{inputProblem,label,traceLocation}=params,traceLength2=getTraceLength(traceLocation.trace),orientationConstraint=getOrientationConstraint(inputProblem,label),candidateDistances=getCandidateDistances(traceLength2,getTraceVertexDistances(traceLocation.trace)),netLabelWidth=getNetLabelWidth(inputProblem,label),netLabelHeight=getNetLabelHeight(inputProblem,label),candidates=[],seenCandidateKeys=new Set;for(let pathDistance of candidateDistances){let point6=getPointAtTraceDistance(traceLocation.trace,pathDistance),orientations=getOrientationsForPoint({inputProblem,label,point:point6,orientationConstraint});for(let orientation4 of orientations){if(isSamePlacement(label,point6,orientation4))continue;let key=[point6.x.toFixed(6),point6.y.toFixed(6),orientation4].join(":");seenCandidateKeys.has(key)||(seenCandidateKeys.add(key),candidates.push(createCandidate({point:point6,orientation:orientation4,netLabelWidth,netLabelHeight,traceLocation,pathDistance,label})))}}return candidates},getCandidateDistances=(traceLength2,vertexDistances)=>{let distances=new Set,maxSteps=Math.ceil(traceLength2/CANDIDATE_STEP);for(let i6=0;i6<=maxSteps;i6++){let distance72=Math.min(traceLength2,i6*CANDIDATE_STEP);distances.add(roundDistance(distance72))}for(let distance72 of vertexDistances)distances.add(roundDistance(distance72));return[...distances].filter(distance72=>distance72>=-EPS13&&distance72<=traceLength2+EPS13).sort((a6,b6)=>a6-b6)},getOrientationsForPoint=params=>{let{inputProblem,label,point:point6,orientationConstraint}=params;return orientationConstraint||getUnconstrainedOrientations({label,inputProblem,point:point6})},createCandidate=params=>{let{point:point6,orientation:orientation4,netLabelWidth,netLabelHeight,traceLocation,pathDistance,label}=params,{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth,netLabelHeight});return{anchorPoint:point6,center:getCenterFromAnchor(point6,orientation4,width,height),width,height,orientation:orientation4,traceId:traceLocation.trace.mspPairId,pathDistance,distanceFromOriginal:getManhattanDistance(point6,label.anchorPoint),status:"valid",selected:!1}},getUnconstrainedOrientations=params=>{let{label,inputProblem,point:point6}=params;return dedupeOrientations([...getInitialOrientations(label),...getOutwardOrientations({inputProblem,point:point6}),...ALL_ORIENTATIONS])},getInitialOrientations=label=>[label.orientation,getFlippedOrientation(label.orientation)],getOutwardOrientations=params=>{let{inputProblem,point:point6}=params,chipBounds=getChipBounds4(inputProblem);return dedupeOrientations(getOutwardOrientationOptions(point6,chipBounds).sort((a6,b6)=>b6.outwardScore-a6.outwardScore).map(({orientation:orientation4})=>orientation4))},getOutwardOrientationOptions=(point6,chipBounds)=>{let options=[];return options.push(getOutwardAxisOption({value:point6.y,min:chipBounds.minY,max:chipBounds.maxY,center:chipBounds.centerY,positiveOrientation:"y+",negativeOrientation:"y-"})),options.push(getOutwardAxisOption({value:point6.x,min:chipBounds.minX,max:chipBounds.maxX,center:chipBounds.centerX,positiveOrientation:"x+",negativeOrientation:"x-"})),options},getOutwardAxisOption=params=>{let{value,min,max:max2,center:center2,positiveOrientation,negativeOrientation}=params;return value>max2+EPS13?{orientation:positiveOrientation,outwardScore:1+value-max2}:value<min-EPS13?{orientation:negativeOrientation,outwardScore:1+min-value}:{orientation:value>=center2?positiveOrientation:negativeOrientation,outwardScore:getNormalizedCenterDistance(value,center2,max2-min)}},getNormalizedCenterDistance=(value,center2,span)=>Math.abs(value-center2)/Math.max(EPS13,span/2),ALL_ORIENTATIONS=["x+","x-","y+","y-"],getFlippedOrientation=orientation4=>{switch(orientation4){case"x+":return"x-";case"x-":return"x+";case"y+":return"y-";case"y-":return"y+"}},getChipBounds4=inputProblem=>{if(inputProblem.chips.length===0)return{minX:0,minY:0,maxX:0,maxY:0,centerX:0,centerY:0};let bounds=inputProblem.chips.reduce((acc,chip)=>({minX:Math.min(acc.minX,chip.center.x-chip.width/2),minY:Math.min(acc.minY,chip.center.y-chip.height/2),maxX:Math.max(acc.maxX,chip.center.x+chip.width/2),maxY:Math.max(acc.maxY,chip.center.y+chip.height/2)}),{minX:Number.POSITIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY});return{...bounds,centerX:(bounds.minX+bounds.maxX)/2,centerY:(bounds.minY+bounds.maxY)/2}},getNetLabelWidth=(inputProblem,label)=>{let configuredWidth=getNetLabelWidthForConnection({inputProblem,netId:label.netId,pinIds:label.pinIds,isPortOnlyLabel:label.mspConnectionPairIds.length===0});return configuredWidth!==void 0?configuredWidth:label.orientation==="y+"||label.orientation==="y-"?label.height:label.width},getNetLabelHeight=(inputProblem,label)=>{let ncHeightByNetId=inputProblem.netConnections.find(connection=>connection.netId===label.netId)?.netLabelHeight;return ncHeightByNetId!==void 0?ncHeightByNetId:inputProblem.netConnections.find(nc3=>nc3.pinIds.some(pid=>label.pinIds.includes(pid)))?.netLabelHeight},roundDistance=distance72=>Number(distance72.toFixed(6)),isSamePlacement=(label,point6,orientation4)=>Math.abs(point6.x-label.anchorPoint.x)<=EPS13&&Math.abs(point6.y-label.anchorPoint.y)<=EPS13&&orientation4===label.orientation,CANDIDATE_SELECTED_COLOR4="blue",CANDIDATE_REJECTED_COLOR4="red",visualizeTraceAnchoredNetLabelOverlapSolver=state2=>{let graphics=visualizeInputProblem2(state2.inputProblem);return ensureGraphicsArrays3(graphics),drawTraces4(graphics,state2.traces),drawNetLabels4(graphics,state2.inputProblem,state2.outputNetLabelPlacements),state2.solved||(drawCurrentOverlap2(graphics,state2),drawCurrentCandidates4(graphics,state2.currentCandidateResults)),graphics},drawTraces4=(graphics,traces)=>{for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"})},drawNetLabels4=(graphics,inputProblem,labels)=>{for(let label of labels)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:getNetLabelVisualizationLabel(inputProblem,label)}),graphics.points.push({x:label.anchorPoint.x,y:label.anchorPoint.y,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
671
671
  orientation: ${label.orientation}`})},drawCurrentOverlap2=(graphics,state2)=>{if(state2.currentOverlap)for(let labelIndex of[state2.currentOverlap.firstLabelIndex,state2.currentOverlap.secondLabelIndex]){let label=state2.outputNetLabelPlacements[labelIndex];label&&graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:"rgba(255, 0, 0, 0.2)",strokeColor:CANDIDATE_REJECTED_COLOR4,label:`netlabel overlap target
672
672
  ${label.netId??label.globalConnNetId}
673
673
  ${getAvailableOrientationText(state2.inputProblem,label)}`})}},drawCurrentCandidates4=(graphics,candidates)=>{for(let candidate of candidates){let color=candidate.selected?CANDIDATE_SELECTED_COLOR4:CANDIDATE_REJECTED_COLOR4;graphics.rects.push({center:candidate.center,width:candidate.width,height:candidate.height,fill:candidate.selected?"rgba(0, 0, 255, 0.2)":"rgba(255, 0, 0, 0.15)",strokeColor:color,strokeDash:candidate.selected?void 0:"4 2",label:`${candidate.selected?"selected":candidate.status} netlabel overlap candidate
@@ -684,9 +684,9 @@ globalConnNetId: ${label.globalConnNetId}`,pointColor=getColorFromString2(label.
684
684
  orientation: ${label.orientation}`})}let movingNetId=this.currentLabelToMove?this.currentLabelToMove.netId:"?";for(let c3 of this.candidateResults){let statusColor=CANDIDATE_STATUS_COLOR[c3.status],statusFill=CANDIDATE_STATUS_FILL[c3.status],strokeDash;c3.status!=="ok"&&(strokeDash="4 2"),graphics.rects.push({center:c3.center,width:c3.width,height:c3.height,fill:statusFill,strokeColor:statusColor,strokeDash,label:`candidate: ${c3.status}
685
685
  orientation: ${c3.orientation}
686
686
  moving: ${movingNetId}`}),graphics.points.push({x:c3.anchor.x,y:c3.anchor.y,color:statusColor,label:`candidate anchor
687
- ${c3.status}`})}return graphics}},ROUTE_CLEARANCE=.2,COORDINATE_TOLERANCE=1e-9,GROUND_NET_ID="GND",pointsAreEqual=(firstPoint,secondPoint)=>Math.abs(firstPoint.x-secondPoint.x)<=COORDINATE_TOLERANCE&&Math.abs(firstPoint.y-secondPoint.y)<=COORDINATE_TOLERANCE,removeConsecutiveDuplicatePoints=path=>{let filteredPath=[];for(let point6 of path){let previousPoint=filteredPath.at(-1);(!previousPoint||!pointsAreEqual(previousPoint,point6))&&filteredPath.push(point6)}return filteredPath},getPathLength3=path=>{let pathLength4=0;for(let pointIndex=0;pointIndex<path.length-1;pointIndex++){let startPoint=path[pointIndex],endPoint=path[pointIndex+1];pathLength4+=Math.abs(endPoint.x-startPoint.x)+Math.abs(endPoint.y-startPoint.y)}return pathLength4},getEscapePoint=({pin,facingDirection})=>{let escapePoint={x:pin.x,y:pin.y};return facingDirection==="x+"&&(escapePoint.x+=ROUTE_CLEARANCE),facingDirection==="x-"&&(escapePoint.x-=ROUTE_CLEARANCE),facingDirection==="y+"&&(escapePoint.y+=ROUTE_CLEARANCE),facingDirection==="y-"&&(escapePoint.y-=ROUTE_CLEARANCE),escapePoint},getOuterBounds=obstacles=>({minX:Math.min(...obstacles.map(obstacle=>obstacle.minX)),minY:Math.min(...obstacles.map(obstacle=>obstacle.minY)),maxX:Math.max(...obstacles.map(obstacle=>obstacle.maxX)),maxY:Math.max(...obstacles.map(obstacle=>obstacle.maxY))}),getPerimeterCandidates=({connectionPair,obstacles})=>{let[firstPin,secondPin]=connectionPair.pins,firstEscapePoint=getEscapePoint({pin:firstPin,facingDirection:firstPin._facingDirection}),secondEscapePoint=getEscapePoint({pin:secondPin,facingDirection:secondPin._facingDirection}),outerBounds=getOuterBounds(obstacles),horizontalChannels=[outerBounds.minY-ROUTE_CLEARANCE,outerBounds.maxY+ROUTE_CLEARANCE],verticalChannels=[outerBounds.minX-ROUTE_CLEARANCE,outerBounds.maxX+ROUTE_CLEARANCE],candidates=[];for(let channelY of horizontalChannels)candidates.push(removeConsecutiveDuplicatePoints([firstPin,firstEscapePoint,{x:firstEscapePoint.x,y:channelY},{x:secondEscapePoint.x,y:channelY},secondEscapePoint,secondPin]));for(let channelX of verticalChannels)candidates.push(removeConsecutiveDuplicatePoints([firstPin,firstEscapePoint,{x:channelX,y:firstEscapePoint.y},{x:channelX,y:secondEscapePoint.y},secondEscapePoint,secondPin]));return candidates.sort((firstPath,secondPath)=>getPathLength3(firstPath)-getPathLength3(secondPath))},getSegmentMidpoint=(startPoint,endPoint)=>({x:(startPoint.x+endPoint.x)/2,y:(startPoint.y+endPoint.y)/2}),getJunctionPoints=sameNetTraces=>{let junctionPoints=[];for(let trace of sameNetTraces){for(let pointIndex=0;pointIndex<trace.tracePath.length-1;pointIndex++){let startPoint=trace.tracePath[pointIndex],endPoint=trace.tracePath[pointIndex+1];junctionPoints.push(startPoint),junctionPoints.push(getSegmentMidpoint(startPoint,endPoint))}let lastPoint=trace.tracePath.at(-1);lastPoint&&junctionPoints.push(lastPoint)}return junctionPoints},getUnconnectedPins=({connectionPair,sameNetTraces})=>{let connectedPinIds=new Set(sameNetTraces.flatMap(trace=>trace.pinIds));return connectionPair.pins.filter(pin=>!connectedPinIds.has(pin.pinId))},getJunctionCandidates=({connectionPair,sameNetTraces,obstacles,maxConnectionDistance})=>{let outerBounds=getOuterBounds(obstacles),horizontalChannels=[outerBounds.minY-ROUTE_CLEARANCE,outerBounds.maxY+ROUTE_CLEARANCE],verticalChannels=[outerBounds.minX-ROUTE_CLEARANCE,outerBounds.maxX+ROUTE_CLEARANCE],candidates=[],junctionPoints=getJunctionPoints(sameNetTraces),unconnectedPins=getUnconnectedPins({connectionPair,sameNetTraces});for(let pin of unconnectedPins){let escapePoint=getEscapePoint({pin,facingDirection:pin._facingDirection});for(let junctionPoint of junctionPoints)if(!(distance2(pin,junctionPoint)>maxConnectionDistance)){candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:escapePoint.x,y:junctionPoint.y},junctionPoint])),candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:junctionPoint.x,y:escapePoint.y},junctionPoint]));for(let channelY of horizontalChannels)candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:escapePoint.x,y:channelY},{x:junctionPoint.x,y:channelY},junctionPoint]));for(let channelX of verticalChannels)candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:channelX,y:escapePoint.y},{x:channelX,y:junctionPoint.y},junctionPoint]))}}return candidates.sort((firstPath,secondPath)=>getPathLength3(firstPath)-getPathLength3(secondPath))},pathCollidesWithObstacles=({path,obstacles,connectionPair,rejectComponentBoundaryTravel})=>{let firstPathPoint=path[0],lastPathPoint=path.at(-1),firstPathPin=connectionPair.pins.find(pin=>pointsAreEqual(pin,firstPathPoint)),lastPathPin=connectionPair.pins.find(pin=>pointsAreEqual(pin,lastPathPoint)),pathConnectsPairPins=firstPathPin!==void 0&&lastPathPin!==void 0,firstChipObstacle=obstacles.find(obstacle=>obstacle.kind==="chip"&&obstacle.chipId===firstPathPin?.chipId),secondChipObstacle=obstacles.find(obstacle=>obstacle.kind==="chip"&&obstacle.chipId===lastPathPin?.chipId);return rejectComponentBoundaryTravel&&firstChipObstacle&&segmentOverlapsRectBoundary(path[0],path[1],firstChipObstacle)||rejectComponentBoundaryTravel&&secondChipObstacle&&segmentOverlapsRectBoundary(path[path.length-2],path[path.length-1],secondChipObstacle)?!0:findFirstCollision(path,obstacles,{excludeRectsForSegment:segmentIndex=>{let excludedObstacles=new Set;return segmentIndex===0&&firstChipObstacle&&excludedObstacles.add(firstChipObstacle),pathConnectsPairPins&&segmentIndex===path.length-2&&secondChipObstacle&&excludedObstacles.add(secondChipObstacle),excludedObstacles}})!==null},hasParallelFailedConnection=({connectionPair,failedConnectionPairs})=>{let connectionChipIds=new Set(connectionPair.pins.map(pin=>pin.chipId));return failedConnectionPairs.some(otherConnectionPair=>otherConnectionPair.mspPairId===connectionPair.mspPairId?!1:otherConnectionPair.pins.every(pin=>connectionChipIds.has(pin.chipId)))},segmentsOverlapBeyondEndpoint=({firstStart,firstEnd,secondStart,secondEnd})=>isHorizontal(firstStart,firstEnd)&&isHorizontal(secondStart,secondEnd)?Math.min(Math.max(firstStart.x,firstEnd.x),Math.max(secondStart.x,secondEnd.x))-Math.max(Math.min(firstStart.x,firstEnd.x),Math.min(secondStart.x,secondEnd.x))>COORDINATE_TOLERANCE:isVertical(firstStart,firstEnd)&&isVertical(secondStart,secondEnd)?Math.min(Math.max(firstStart.y,firstEnd.y),Math.max(secondStart.y,secondEnd.y))-Math.max(Math.min(firstStart.y,firstEnd.y),Math.min(secondStart.y,secondEnd.y))>COORDINATE_TOLERANCE:!1,getAllowedJunctionPoints=({connectionPair,existingTrace})=>{let existingPinIds=new Set(existingTrace.pinIds);return connectionPair.pins.filter(pin=>existingPinIds.has(pin.pinId))},pathCrossesExistingTraces=({path,connectionPair,existingTraces})=>{for(let existingTrace of existingTraces){if(existingTrace.globalConnNetId===connectionPair.globalConnNetId)continue;let allowedJunctionPoints=getAllowedJunctionPoints({connectionPair,existingTrace});for(let pathIndex=0;pathIndex<path.length-1;pathIndex++){let pathStart=path[pathIndex],pathEnd=path[pathIndex+1];for(let traceIndex=0;traceIndex<existingTrace.tracePath.length-1;traceIndex++){let traceStart=existingTrace.tracePath[traceIndex],traceEnd=existingTrace.tracePath[traceIndex+1];if(!(!doSegmentsIntersect(pathStart,pathEnd,traceStart,traceEnd)||allowedJunctionPoints.some(junctionPoint=>(pointsAreEqual(pathStart,junctionPoint)||pointsAreEqual(pathEnd,junctionPoint))&&(pointsAreEqual(traceStart,junctionPoint)||pointsAreEqual(traceEnd,junctionPoint)))&&!segmentsOverlapBeyondEndpoint({firstStart:pathStart,firstEnd:pathEnd,secondStart:traceStart,secondEnd:traceEnd})))return!0}}}return!1},UnroutedTraceRecoverySolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"params");__publicField(this,"inputProblem");__publicField(this,"alreadySolvedTraces");__publicField(this,"failedConnectionPairs");__publicField(this,"queuedConnectionPairs");__publicField(this,"maxConnectionDistance");__publicField(this,"groundGlobalConnNetId");__publicField(this,"solvedUnroutedTraces",[]);this.params=params,this.inputProblem=params.inputProblem,this.alreadySolvedTraces=params.alreadySolvedTraces,this.failedConnectionPairs=params.failedConnectionPairs,this.queuedConnectionPairs=[...params.failedConnectionPairs],this.maxConnectionDistance=this.inputProblem.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE;let{netConnMap}=getConnectivityMapsFromInputProblem(this.inputProblem);this.groundGlobalConnNetId=netConnMap.getNetConnectedToId(GROUND_NET_ID)??void 0}getConstructorParams(){return this.params}_step(){let connectionPair=this.queuedConnectionPairs.shift();if(!connectionPair){this.solved=!0;return}if(connectionPair.globalConnNetId===this.groundGlobalConnNetId||distance2(connectionPair.pins[0],connectionPair.pins[1])>this.maxConnectionDistance)return;let obstacles=getObstacleRects(this.inputProblem),existingTraces=[...this.alreadySolvedTraces,...this.solvedUnroutedTraces],sameNetTraces=existingTraces.filter(trace=>trace.globalConnNetId===connectionPair.globalConnNetId),junctionCandidates=getJunctionCandidates({connectionPair,sameNetTraces,obstacles,maxConnectionDistance:this.maxConnectionDistance}),perimeterCandidates=getPerimeterCandidates({connectionPair,obstacles}),candidates=[...junctionCandidates,...perimeterCandidates],rejectComponentBoundaryTravel=hasParallelFailedConnection({connectionPair,failedConnectionPairs:this.failedConnectionPairs});for(let tracePath of candidates)if(!pathCollidesWithObstacles({path:tracePath,obstacles,connectionPair,rejectComponentBoundaryTravel})&&!pathCrossesExistingTraces({path:tracePath,connectionPair,existingTraces})){this.solvedUnroutedTraces.push({...connectionPair,tracePath,mspConnectionPairIds:[connectionPair.mspPairId],pinIds:connectionPair.pins.map(pin=>pin.pinId)});return}}getOutput(){return{newTraces:this.solvedUnroutedTraces,allTracesMerged:[...this.alreadySolvedTraces,...this.solvedUnroutedTraces]}}visualize(){let graphics=visualizeInputProblem2(this.inputProblem);for(let trace of this.solvedUnroutedTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"blue"});return graphics}},NET_LABEL_INTERIOR_INSET=1e-6,pathIntersectsAnyNetLabel=({path,netLabelPlacements})=>{for(let label of netLabelPlacements){let labelBounds=getRectBounds(label.center,label.width,label.height);for(let index=0;index<path.length-1;index++)if(segmentIntersectsRect2(path[index],path[index+1],labelBounds))return!0}return!1},pathEntersAnyNetLabel=({path,netLabelPlacements})=>{for(let label of netLabelPlacements){let labelBounds=getRectBounds(label.center,label.width,label.height),labelInteriorBounds={minX:labelBounds.minX+NET_LABEL_INTERIOR_INSET,minY:labelBounds.minY+NET_LABEL_INTERIOR_INSET,maxX:labelBounds.maxX-NET_LABEL_INTERIOR_INSET,maxY:labelBounds.maxY-NET_LABEL_INTERIOR_INSET};for(let index=0;index<path.length-1;index++)if(segmentIntersectsRect2(path[index],path[index+1],labelInteriorBounds))return!0}return!1},MAX_ALIGNED_LOAD_PIN_OFFSET=.2,MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET=.2,getSharedPin=({donorTrace,branchTrace})=>{let branchPinIds=new Set(branchTrace.pins.map(pin=>pin.pinId));return donorTrace.pins.find(pin=>branchPinIds.has(pin.pinId))??null},getOtherPin=({trace,sharedPin})=>trace.pins.find(pin=>pin.pinId!==sharedPin.pinId)??null,getLongestHorizontalSegment=trace=>{let longest=null;for(let index=0;index<trace.tracePath.length-1;index++){let start=trace.tracePath[index],end=trace.tracePath[index+1];isHorizontal2(start,end)&&(!longest||Math.abs(end.x-start.x)>Math.abs(longest.end.x-longest.start.x))&&(longest={start,end})}return longest},getJunctionPoint=({segment:segment2,sharedPin})=>{let startDistance=Math.abs(segment2.start.x-sharedPin.x),endDistance=Math.abs(segment2.end.x-sharedPin.x);return startDistance<=endDistance?segment2.start:segment2.end},railIsOnFacingSide=({railY,pin})=>pin._facingDirection==="y+"?railY>pin.y:!1,getAttachedLabelIndexes=(trace,netLabelPlacements)=>netLabelPlacements.flatMap((label,index)=>(label.mspConnectionPairIds.includes(trace.mspPairId)||label.mspConnectionPairIds.length===0&&label.globalConnNetId===trace.globalConnNetId)&&tracePathContainsPoint(trace.tracePath,label.anchorPoint)?[index]:[]),moveAttachedLabels=({trace,reroutedTracePath,netLabelPlacements,attachedLabelIndexes})=>{let attachedLabels=attachedLabelIndexes.map(index=>netLabelPlacements[index]),movedAttachedLabels=moveAttachedLabelsToReroutedTrace({trace,originalTracePath:trace.tracePath,reroutedTracePath,netLabelPlacements:attachedLabels}),movedLabelByIndex=new Map(attachedLabelIndexes.map((labelIndex,index)=>[labelIndex,movedAttachedLabels[index]]));return netLabelPlacements.map((label,index)=>movedLabelByIndex.get(index)??label)},getAlignedBranchPath=({donorTrace,branchTrace})=>{let sharedPin=getSharedPin({donorTrace,branchTrace});if(!sharedPin)return null;let donorOtherPin=getOtherPin({trace:donorTrace,sharedPin});if(!donorOtherPin)return null;let otherPin=getOtherPin({trace:branchTrace,sharedPin});if(!otherPin||Math.abs(sharedPin.y-otherPin.y)>MAX_ALIGNED_LOAD_PIN_OFFSET)return null;let donorRail=getLongestHorizontalSegment(donorTrace);if(!donorRail)return null;let branchRail=getLongestHorizontalSegment(branchTrace);if(branchRail&&nearlyEqual(branchRail.start.y,donorRail.start.y)||!railIsOnFacingSide({railY:donorRail.start.y,pin:otherPin}))return null;let junction=getJunctionPoint({segment:donorRail,sharedPin});if(!(donorOtherPin.x<junction.x&&otherPin.x>junction.x||donorOtherPin.x>junction.x&&otherPin.x<junction.x))return null;let sharedToOther=simplifyPath([{x:sharedPin.x,y:sharedPin.y},{x:junction.x,y:sharedPin.y},{x:junction.x,y:junction.y},{x:otherPin.x,y:junction.y},{x:otherPin.x,y:otherPin.y}]);return branchTrace.pins[0].pinId===sharedPin.pinId?sharedToOther:[...sharedToOther].reverse()},candidateIsClear=({candidateTrace,originalTrace,traces,inputProblem,candidateNetLabelPlacements,attachedLabelIndexes})=>{let obstacles=getObstacleRects(inputProblem);if(isPathCollidingWithObstacles(candidateTrace.tracePath,obstacles))return!1;let otherNetTraces=traces.filter(trace=>trace.globalConnNetId!==candidateTrace.globalConnNetId);if(doesPathCoincideWithTraces(candidateTrace.tracePath,otherNetTraces)||!attachedLabelIndexes.every(index=>tracePathContainsPoint(candidateTrace.tracePath,candidateNetLabelPlacements[index].anchorPoint)))return!1;let otherNetLabelPlacements=candidateNetLabelPlacements.filter(label=>label.globalConnNetId!==candidateTrace.globalConnNetId);if(pathIntersectsAnyNetLabel({path:candidateTrace.tracePath,netLabelPlacements:otherNetLabelPlacements}))return!1;let sameNetLabelPlacements=candidateNetLabelPlacements.filter(label=>label.globalConnNetId===candidateTrace.globalConnNetId);if(!pathIntersectsAnyNetLabel({path:candidateTrace.tracePath,netLabelPlacements:sameNetLabelPlacements}))return!0;if(pathEntersAnyNetLabel({path:candidateTrace.tracePath,netLabelPlacements:sameNetLabelPlacements}))return!1;let originalRail=getLongestHorizontalSegment(originalTrace),candidateRail=getLongestHorizontalSegment(candidateTrace);return!originalRail||!candidateRail?!1:Math.abs(originalRail.start.y-candidateRail.start.y)<=MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET},alignSameNetJunctions=({inputProblem,traces,netLabelPlacements})=>{let outputTraces=[...traces],outputNetLabelPlacements=[...netLabelPlacements],alignedBranchTraceIds=new Set,alignedJunctionCount=0,donorTraceIds=traces.map(trace=>trace.mspPairId),pendingDonorTraceIds=new Set(donorTraceIds);for(let donorIndex=0;donorIndex<donorTraceIds.length;donorIndex++){let donorTraceId=donorTraceIds[donorIndex];pendingDonorTraceIds.delete(donorTraceId);let donorTrace=outputTraces.find(trace=>trace.mspPairId===donorTraceId);for(let branchTrace of outputTraces){if(alignedBranchTraceIds.has(branchTrace.mspPairId)||donorTrace.mspPairId===branchTrace.mspPairId||donorTrace.globalConnNetId!==branchTrace.globalConnNetId)continue;let candidatePath=getAlignedBranchPath({donorTrace,branchTrace});if(!candidatePath)continue;let candidateTrace={...branchTrace,tracePath:candidatePath},originalPair=[donorTrace,branchTrace],candidatePair=[donorTrace,candidateTrace],removesVisibleSegment=getVisibleTraceSegmentCount(candidatePair)<getVisibleTraceSegmentCount(originalPair),shortensVisibleTrace=getVisibleTraceLength(candidatePair)<getVisibleTraceLength(originalPair)&&!nearlyEqual(getVisibleTraceLength(candidatePair),getVisibleTraceLength(originalPair));if(!removesVisibleSegment&&!shortensVisibleTrace)continue;let attachedLabelIndexes=getAttachedLabelIndexes(branchTrace,outputNetLabelPlacements),candidateNetLabelPlacements=moveAttachedLabels({trace:branchTrace,reroutedTracePath:candidatePath,netLabelPlacements:outputNetLabelPlacements,attachedLabelIndexes});candidateIsClear({candidateTrace,originalTrace:branchTrace,traces:outputTraces,inputProblem,candidateNetLabelPlacements,attachedLabelIndexes})&&(outputTraces=outputTraces.map(trace=>trace.mspPairId===branchTrace.mspPairId?candidateTrace:trace),outputNetLabelPlacements=candidateNetLabelPlacements,alignedBranchTraceIds.add(branchTrace.mspPairId),alignedJunctionCount++,pendingDonorTraceIds.has(branchTrace.mspPairId)||(donorTraceIds.push(branchTrace.mspPairId),pendingDonorTraceIds.add(branchTrace.mspPairId)))}}return{traces:outputTraces,netLabelPlacements:outputNetLabelPlacements,alignedJunctionCount}},SameNetJunctionAlignmentSolver=class extends BaseSolver5{constructor(input2){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"outputNetLabelPlacements");this.input=input2,this.outputTraces=input2.traces,this.outputNetLabelPlacements=input2.netLabelPlacements}_step(){let result=alignSameNetJunctions(this.input);this.outputTraces=result.traces,this.outputNetLabelPlacements=result.netLabelPlacements,this.stats.alignedJunctionCount=result.alignedJunctionCount,this.solved=!0}getOutput(){return{traces:this.outputTraces,netLabelPlacements:this.outputNetLabelPlacements}}visualize(){let graphics=visualizeInputProblem2(this.input.inputProblem);graphics.lines??(graphics.lines=[]),graphics.rects??(graphics.rects=[]),graphics.points??(graphics.points=[]);for(let trace of this.outputTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let label of this.outputNetLabelPlacements){let labelRect={center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
687
+ ${c3.status}`})}return graphics}},ROUTE_CLEARANCE=.2,COORDINATE_TOLERANCE=1e-9,GROUND_NET_ID="GND",pointsAreEqual=(firstPoint,secondPoint)=>Math.abs(firstPoint.x-secondPoint.x)<=COORDINATE_TOLERANCE&&Math.abs(firstPoint.y-secondPoint.y)<=COORDINATE_TOLERANCE,removeConsecutiveDuplicatePoints=path=>{let filteredPath=[];for(let point6 of path){let previousPoint=filteredPath.at(-1);(!previousPoint||!pointsAreEqual(previousPoint,point6))&&filteredPath.push(point6)}return filteredPath},getPathLength3=path=>{let pathLength4=0;for(let pointIndex=0;pointIndex<path.length-1;pointIndex++){let startPoint=path[pointIndex],endPoint=path[pointIndex+1];pathLength4+=Math.abs(endPoint.x-startPoint.x)+Math.abs(endPoint.y-startPoint.y)}return pathLength4},getEscapePoint=({pin,facingDirection})=>{let escapePoint={x:pin.x,y:pin.y};return facingDirection==="x+"&&(escapePoint.x+=ROUTE_CLEARANCE),facingDirection==="x-"&&(escapePoint.x-=ROUTE_CLEARANCE),facingDirection==="y+"&&(escapePoint.y+=ROUTE_CLEARANCE),facingDirection==="y-"&&(escapePoint.y-=ROUTE_CLEARANCE),escapePoint},getOuterBounds=obstacles=>({minX:Math.min(...obstacles.map(obstacle=>obstacle.minX)),minY:Math.min(...obstacles.map(obstacle=>obstacle.minY)),maxX:Math.max(...obstacles.map(obstacle=>obstacle.maxX)),maxY:Math.max(...obstacles.map(obstacle=>obstacle.maxY))}),getPerimeterCandidates=({connectionPair,obstacles})=>{let[firstPin,secondPin]=connectionPair.pins,firstEscapePoint=getEscapePoint({pin:firstPin,facingDirection:firstPin._facingDirection}),secondEscapePoint=getEscapePoint({pin:secondPin,facingDirection:secondPin._facingDirection}),outerBounds=getOuterBounds(obstacles),horizontalChannels=[outerBounds.minY-ROUTE_CLEARANCE,outerBounds.maxY+ROUTE_CLEARANCE],verticalChannels=[outerBounds.minX-ROUTE_CLEARANCE,outerBounds.maxX+ROUTE_CLEARANCE],candidates=[];for(let channelY of horizontalChannels)candidates.push(removeConsecutiveDuplicatePoints([firstPin,firstEscapePoint,{x:firstEscapePoint.x,y:channelY},{x:secondEscapePoint.x,y:channelY},secondEscapePoint,secondPin]));for(let channelX of verticalChannels)candidates.push(removeConsecutiveDuplicatePoints([firstPin,firstEscapePoint,{x:channelX,y:firstEscapePoint.y},{x:channelX,y:secondEscapePoint.y},secondEscapePoint,secondPin]));return candidates.sort((firstPath,secondPath)=>getPathLength3(firstPath)-getPathLength3(secondPath))},getSegmentMidpoint=(startPoint,endPoint)=>({x:(startPoint.x+endPoint.x)/2,y:(startPoint.y+endPoint.y)/2}),getJunctionPoints=sameNetTraces=>{let junctionPoints=[];for(let trace of sameNetTraces){for(let pointIndex=0;pointIndex<trace.tracePath.length-1;pointIndex++){let startPoint=trace.tracePath[pointIndex],endPoint=trace.tracePath[pointIndex+1];junctionPoints.push(startPoint),junctionPoints.push(getSegmentMidpoint(startPoint,endPoint))}let lastPoint=trace.tracePath.at(-1);lastPoint&&junctionPoints.push(lastPoint)}return junctionPoints},getUnconnectedPins=({connectionPair,sameNetTraces})=>{let connectedPinIds=new Set(sameNetTraces.flatMap(trace=>trace.pinIds));return connectionPair.pins.filter(pin=>!connectedPinIds.has(pin.pinId))},getJunctionCandidates=({connectionPair,sameNetTraces,obstacles,maxConnectionDistance})=>{let outerBounds=getOuterBounds(obstacles),horizontalChannels=[outerBounds.minY-ROUTE_CLEARANCE,outerBounds.maxY+ROUTE_CLEARANCE],verticalChannels=[outerBounds.minX-ROUTE_CLEARANCE,outerBounds.maxX+ROUTE_CLEARANCE],candidates=[],junctionPoints=getJunctionPoints(sameNetTraces),unconnectedPins=getUnconnectedPins({connectionPair,sameNetTraces});for(let pin of unconnectedPins){let escapePoint=getEscapePoint({pin,facingDirection:pin._facingDirection});for(let junctionPoint of junctionPoints)if(!(distance2(pin,junctionPoint)>maxConnectionDistance)){candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:escapePoint.x,y:junctionPoint.y},junctionPoint])),candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:junctionPoint.x,y:escapePoint.y},junctionPoint]));for(let channelY of horizontalChannels)candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:escapePoint.x,y:channelY},{x:junctionPoint.x,y:channelY},junctionPoint]));for(let channelX of verticalChannels)candidates.push(removeConsecutiveDuplicatePoints([pin,escapePoint,{x:channelX,y:escapePoint.y},{x:channelX,y:junctionPoint.y},junctionPoint]))}}return candidates.sort((firstPath,secondPath)=>getPathLength3(firstPath)-getPathLength3(secondPath))},pathCollidesWithObstacles=({path,obstacles,connectionPair,rejectComponentBoundaryTravel})=>{let firstPathPoint=path[0],lastPathPoint=path.at(-1),firstPathPin=connectionPair.pins.find(pin=>pointsAreEqual(pin,firstPathPoint)),lastPathPin=connectionPair.pins.find(pin=>pointsAreEqual(pin,lastPathPoint)),pathConnectsPairPins=firstPathPin!==void 0&&lastPathPin!==void 0,firstChipObstacle=obstacles.find(obstacle=>obstacle.kind==="chip"&&obstacle.chipId===firstPathPin?.chipId),secondChipObstacle=obstacles.find(obstacle=>obstacle.kind==="chip"&&obstacle.chipId===lastPathPin?.chipId);return rejectComponentBoundaryTravel&&firstChipObstacle&&segmentOverlapsRectBoundary(path[0],path[1],firstChipObstacle)||rejectComponentBoundaryTravel&&secondChipObstacle&&segmentOverlapsRectBoundary(path[path.length-2],path[path.length-1],secondChipObstacle)?!0:findFirstCollision(path,obstacles,{excludeRectsForSegment:segmentIndex=>{let excludedObstacles=new Set;return segmentIndex===0&&firstChipObstacle&&excludedObstacles.add(firstChipObstacle),pathConnectsPairPins&&segmentIndex===path.length-2&&secondChipObstacle&&excludedObstacles.add(secondChipObstacle),excludedObstacles}})!==null},hasParallelFailedConnection=({connectionPair,failedConnectionPairs})=>{let connectionChipIds=new Set(connectionPair.pins.map(pin=>pin.chipId));return failedConnectionPairs.some(otherConnectionPair=>otherConnectionPair.mspPairId===connectionPair.mspPairId?!1:otherConnectionPair.pins.every(pin=>connectionChipIds.has(pin.chipId)))},segmentsOverlapBeyondEndpoint=({firstStart,firstEnd,secondStart,secondEnd})=>isHorizontal(firstStart,firstEnd)&&isHorizontal(secondStart,secondEnd)?Math.min(Math.max(firstStart.x,firstEnd.x),Math.max(secondStart.x,secondEnd.x))-Math.max(Math.min(firstStart.x,firstEnd.x),Math.min(secondStart.x,secondEnd.x))>COORDINATE_TOLERANCE:isVertical(firstStart,firstEnd)&&isVertical(secondStart,secondEnd)?Math.min(Math.max(firstStart.y,firstEnd.y),Math.max(secondStart.y,secondEnd.y))-Math.max(Math.min(firstStart.y,firstEnd.y),Math.min(secondStart.y,secondEnd.y))>COORDINATE_TOLERANCE:!1,getAllowedJunctionPoints=({connectionPair,existingTrace})=>{let existingPinIds=new Set(existingTrace.pinIds);return connectionPair.pins.filter(pin=>existingPinIds.has(pin.pinId))},pathCrossesExistingTraces=({path,connectionPair,existingTraces})=>{for(let existingTrace of existingTraces){if(existingTrace.globalConnNetId===connectionPair.globalConnNetId)continue;let allowedJunctionPoints=getAllowedJunctionPoints({connectionPair,existingTrace});for(let pathIndex=0;pathIndex<path.length-1;pathIndex++){let pathStart=path[pathIndex],pathEnd=path[pathIndex+1];for(let traceIndex=0;traceIndex<existingTrace.tracePath.length-1;traceIndex++){let traceStart=existingTrace.tracePath[traceIndex],traceEnd=existingTrace.tracePath[traceIndex+1];if(!(!doSegmentsIntersect(pathStart,pathEnd,traceStart,traceEnd)||allowedJunctionPoints.some(junctionPoint=>(pointsAreEqual(pathStart,junctionPoint)||pointsAreEqual(pathEnd,junctionPoint))&&(pointsAreEqual(traceStart,junctionPoint)||pointsAreEqual(traceEnd,junctionPoint)))&&!segmentsOverlapBeyondEndpoint({firstStart:pathStart,firstEnd:pathEnd,secondStart:traceStart,secondEnd:traceEnd})))return!0}}}return!1},UnroutedTraceRecoverySolver=class extends BaseSolver5{constructor(params){super();__publicField(this,"params");__publicField(this,"inputProblem");__publicField(this,"alreadySolvedTraces");__publicField(this,"failedConnectionPairs");__publicField(this,"queuedConnectionPairs");__publicField(this,"maxConnectionDistance");__publicField(this,"groundGlobalConnNetId");__publicField(this,"solvedUnroutedTraces",[]);this.params=params,this.inputProblem=params.inputProblem,this.alreadySolvedTraces=params.alreadySolvedTraces,this.failedConnectionPairs=params.failedConnectionPairs,this.queuedConnectionPairs=[...params.failedConnectionPairs],this.maxConnectionDistance=this.inputProblem.maxMspPairDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE;let{netConnMap}=getConnectivityMapsFromInputProblem(this.inputProblem);this.groundGlobalConnNetId=netConnMap.getNetConnectedToId(GROUND_NET_ID)??void 0}getConstructorParams(){return this.params}_step(){let connectionPair=this.queuedConnectionPairs.shift();if(!connectionPair){this.solved=!0;return}if(connectionPair.globalConnNetId===this.groundGlobalConnNetId||distance2(connectionPair.pins[0],connectionPair.pins[1])>this.maxConnectionDistance)return;let obstacles=getObstacleRects(this.inputProblem),existingTraces=[...this.alreadySolvedTraces,...this.solvedUnroutedTraces],sameNetTraces=existingTraces.filter(trace=>trace.globalConnNetId===connectionPair.globalConnNetId),junctionCandidates=getJunctionCandidates({connectionPair,sameNetTraces,obstacles,maxConnectionDistance:this.maxConnectionDistance}),perimeterCandidates=getPerimeterCandidates({connectionPair,obstacles}),candidates=[...junctionCandidates,...perimeterCandidates],rejectComponentBoundaryTravel=hasParallelFailedConnection({connectionPair,failedConnectionPairs:this.failedConnectionPairs});for(let tracePath of candidates)if(!pathCollidesWithObstacles({path:tracePath,obstacles,connectionPair,rejectComponentBoundaryTravel})&&!pathCrossesExistingTraces({path:tracePath,connectionPair,existingTraces})){this.solvedUnroutedTraces.push({...connectionPair,tracePath,mspConnectionPairIds:[connectionPair.mspPairId],pinIds:connectionPair.pins.map(pin=>pin.pinId)});return}}getOutput(){return{newTraces:this.solvedUnroutedTraces,allTracesMerged:[...this.alreadySolvedTraces,...this.solvedUnroutedTraces]}}visualize(){let graphics=visualizeInputProblem2(this.inputProblem);for(let trace of this.solvedUnroutedTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"blue"});return graphics}},NET_LABEL_INTERIOR_INSET=1e-6,pathIntersectsAnyNetLabel=({path,netLabelPlacements})=>{for(let label of netLabelPlacements){let labelBounds=getRectBounds(label.center,label.width,label.height);for(let index=0;index<path.length-1;index++)if(segmentIntersectsRect2(path[index],path[index+1],labelBounds))return!0}return!1},pathEntersAnyNetLabel=({path,netLabelPlacements})=>{for(let label of netLabelPlacements){let labelBounds=getRectBounds(label.center,label.width,label.height),labelInteriorBounds={minX:labelBounds.minX+NET_LABEL_INTERIOR_INSET,minY:labelBounds.minY+NET_LABEL_INTERIOR_INSET,maxX:labelBounds.maxX-NET_LABEL_INTERIOR_INSET,maxY:labelBounds.maxY-NET_LABEL_INTERIOR_INSET};for(let index=0;index<path.length-1;index++)if(segmentIntersectsRect2(path[index],path[index+1],labelInteriorBounds))return!0}return!1},MAX_ALIGNED_LOAD_PIN_OFFSET=.2,MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET=.2,MAX_SHARED_PIN_RAIL_OFFSET=.05,getSharedPin=({donorTrace,branchTrace})=>{let branchPinIds=new Set(branchTrace.pins.map(pin=>pin.pinId));return donorTrace.pins.find(pin=>branchPinIds.has(pin.pinId))??null},getOtherPin=({trace,sharedPin})=>trace.pins.find(pin=>pin.pinId!==sharedPin.pinId)??null,getLongestHorizontalSegment=trace=>{let longest=null;for(let index=0;index<trace.tracePath.length-1;index++){let start=trace.tracePath[index],end=trace.tracePath[index+1];isHorizontal2(start,end)&&(!longest||Math.abs(end.x-start.x)>Math.abs(longest.end.x-longest.start.x))&&(longest={start,end})}return longest},getJunctionPoint=({segment:segment2,sharedPin})=>{let startDistance=Math.abs(segment2.start.x-sharedPin.x),endDistance=Math.abs(segment2.end.x-sharedPin.x);return startDistance<=endDistance?segment2.start:segment2.end},railIsOnFacingSide=({railY,pin})=>pin._facingDirection==="y+"?railY>pin.y:!1,railIsOnSharedPinFacingSide=({railY,pin})=>pin._facingDirection==="y+"?railY>pin.y:pin._facingDirection==="y-"?railY<pin.y:!1,getHorizontalPinApproachPoint=({branchTrace,sharedPin,otherPin})=>{if(otherPin._facingDirection!=="x-"&&otherPin._facingDirection!=="x+")return null;let approachPoint=(branchTrace.pins[0].pinId===sharedPin.pinId?branchTrace.tracePath:[...branchTrace.tracePath].reverse()).at(-2);return!approachPoint||!nearlyEqual(approachPoint.y,otherPin.y)?null:(otherPin._facingDirection==="x-"?approachPoint.x<otherPin.x:approachPoint.x>otherPin.x)?approachPoint:null},getAttachedLabelIndexes=(trace,netLabelPlacements)=>netLabelPlacements.flatMap((label,index)=>(label.mspConnectionPairIds.includes(trace.mspPairId)||label.mspConnectionPairIds.length===0&&label.globalConnNetId===trace.globalConnNetId)&&tracePathContainsPoint(trace.tracePath,label.anchorPoint)?[index]:[]),moveAttachedLabels=({trace,reroutedTracePath,netLabelPlacements,attachedLabelIndexes})=>{let attachedLabels=attachedLabelIndexes.map(index=>netLabelPlacements[index]),movedAttachedLabels=moveAttachedLabelsToReroutedTrace({trace,originalTracePath:trace.tracePath,reroutedTracePath,netLabelPlacements:attachedLabels}),movedLabelByIndex=new Map(attachedLabelIndexes.map((labelIndex,index)=>[labelIndex,movedAttachedLabels[index]]));return netLabelPlacements.map((label,index)=>movedLabelByIndex.get(index)??label)},getAlignedBranchPath=({donorTrace,branchTrace})=>{let sharedPin=getSharedPin({donorTrace,branchTrace});if(!sharedPin)return null;let donorOtherPin=getOtherPin({trace:donorTrace,sharedPin});if(!donorOtherPin)return null;let otherPin=getOtherPin({trace:branchTrace,sharedPin});if(!otherPin||Math.abs(sharedPin.y-otherPin.y)>MAX_ALIGNED_LOAD_PIN_OFFSET)return null;let donorRail=getLongestHorizontalSegment(donorTrace);if(!donorRail)return null;let branchRail=getLongestHorizontalSegment(branchTrace);if(branchRail&&nearlyEqual(branchRail.start.y,donorRail.start.y))return null;let railFacesOtherPin=railIsOnFacingSide({railY:donorRail.start.y,pin:otherPin}),railFacesSharedPin=railIsOnSharedPinFacingSide({railY:donorRail.start.y,pin:sharedPin})&&Math.abs(donorRail.start.y-sharedPin.y)<=MAX_SHARED_PIN_RAIL_OFFSET;if(!railFacesOtherPin&&!railFacesSharedPin)return null;let junction=getJunctionPoint({segment:donorRail,sharedPin});if(!(donorOtherPin.x<junction.x&&otherPin.x>junction.x||donorOtherPin.x>junction.x&&otherPin.x<junction.x))return null;let sharedToOther;if(!railFacesOtherPin&&railFacesSharedPin){let approachPoint=getHorizontalPinApproachPoint({branchTrace,sharedPin,otherPin});if(!approachPoint)return null;sharedToOther=simplifyPath([{x:sharedPin.x,y:sharedPin.y},{x:junction.x,y:sharedPin.y},{x:junction.x,y:junction.y},{x:approachPoint.x,y:junction.y},{x:approachPoint.x,y:otherPin.y},{x:otherPin.x,y:otherPin.y}])}else sharedToOther=simplifyPath([{x:sharedPin.x,y:sharedPin.y},{x:junction.x,y:sharedPin.y},{x:junction.x,y:junction.y},{x:otherPin.x,y:junction.y},{x:otherPin.x,y:otherPin.y}]);return branchTrace.pins[0].pinId===sharedPin.pinId?sharedToOther:[...sharedToOther].reverse()},candidateIsClear=({candidateTrace,originalTrace,traces,inputProblem,candidateNetLabelPlacements,attachedLabelIndexes})=>{let obstacles=getObstacleRects(inputProblem);if(isPathCollidingWithObstacles(candidateTrace.tracePath,obstacles))return!1;let otherNetTraces=traces.filter(trace=>trace.globalConnNetId!==candidateTrace.globalConnNetId);if(doesPathCoincideWithTraces(candidateTrace.tracePath,otherNetTraces)||!attachedLabelIndexes.every(index=>tracePathContainsPoint(candidateTrace.tracePath,candidateNetLabelPlacements[index].anchorPoint)))return!1;let otherNetLabelPlacements=candidateNetLabelPlacements.filter(label=>label.globalConnNetId!==candidateTrace.globalConnNetId);if(pathIntersectsAnyNetLabel({path:candidateTrace.tracePath,netLabelPlacements:otherNetLabelPlacements}))return!1;let sameNetLabelPlacements=candidateNetLabelPlacements.filter(label=>label.globalConnNetId===candidateTrace.globalConnNetId);if(!pathIntersectsAnyNetLabel({path:candidateTrace.tracePath,netLabelPlacements:sameNetLabelPlacements}))return!0;if(pathEntersAnyNetLabel({path:candidateTrace.tracePath,netLabelPlacements:sameNetLabelPlacements}))return!1;let originalRail=getLongestHorizontalSegment(originalTrace),candidateRail=getLongestHorizontalSegment(candidateTrace);return!originalRail||!candidateRail?!1:Math.abs(originalRail.start.y-candidateRail.start.y)<=MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET},alignSameNetJunctions=({inputProblem,traces,netLabelPlacements})=>{let outputTraces=[...traces],outputNetLabelPlacements=[...netLabelPlacements],alignedBranchTraceIds=new Set,alignedJunctionCount=0,donorTraceIds=traces.map(trace=>trace.mspPairId),pendingDonorTraceIds=new Set(donorTraceIds);for(let donorIndex=0;donorIndex<donorTraceIds.length;donorIndex++){let donorTraceId=donorTraceIds[donorIndex];pendingDonorTraceIds.delete(donorTraceId);let donorTrace=outputTraces.find(trace=>trace.mspPairId===donorTraceId);for(let branchTrace of outputTraces){if(alignedBranchTraceIds.has(branchTrace.mspPairId)||donorTrace.mspPairId===branchTrace.mspPairId||donorTrace.globalConnNetId!==branchTrace.globalConnNetId)continue;let candidatePath=getAlignedBranchPath({donorTrace,branchTrace});if(!candidatePath)continue;let candidateTrace={...branchTrace,tracePath:candidatePath},originalPair=[donorTrace,branchTrace],candidatePair=[donorTrace,candidateTrace],removesVisibleSegment=getVisibleTraceSegmentCount(candidatePair)<getVisibleTraceSegmentCount(originalPair),shortensVisibleTrace=getVisibleTraceLength(candidatePair)<getVisibleTraceLength(originalPair)&&!nearlyEqual(getVisibleTraceLength(candidatePair),getVisibleTraceLength(originalPair));if(!removesVisibleSegment&&!shortensVisibleTrace)continue;let attachedLabelIndexes=getAttachedLabelIndexes(branchTrace,outputNetLabelPlacements),candidateNetLabelPlacements=moveAttachedLabels({trace:branchTrace,reroutedTracePath:candidatePath,netLabelPlacements:outputNetLabelPlacements,attachedLabelIndexes});candidateIsClear({candidateTrace,originalTrace:branchTrace,traces:outputTraces,inputProblem,candidateNetLabelPlacements,attachedLabelIndexes})&&(outputTraces=outputTraces.map(trace=>trace.mspPairId===branchTrace.mspPairId?candidateTrace:trace),outputNetLabelPlacements=candidateNetLabelPlacements,alignedBranchTraceIds.add(branchTrace.mspPairId),alignedJunctionCount++,pendingDonorTraceIds.has(branchTrace.mspPairId)||(donorTraceIds.push(branchTrace.mspPairId),pendingDonorTraceIds.add(branchTrace.mspPairId)))}}return{traces:outputTraces,netLabelPlacements:outputNetLabelPlacements,alignedJunctionCount}},SameNetJunctionAlignmentSolver=class extends BaseSolver5{constructor(input2){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"outputNetLabelPlacements");this.input=input2,this.outputTraces=input2.traces,this.outputNetLabelPlacements=input2.netLabelPlacements}_step(){let result=alignSameNetJunctions(this.input);this.outputTraces=result.traces,this.outputNetLabelPlacements=result.netLabelPlacements,this.stats.alignedJunctionCount=result.alignedJunctionCount,this.solved=!0}getOutput(){return{traces:this.outputTraces,netLabelPlacements:this.outputNetLabelPlacements}}visualize(){let graphics=visualizeInputProblem2(this.input.inputProblem);graphics.lines??(graphics.lines=[]),graphics.rects??(graphics.rects=[]),graphics.points??(graphics.points=[]);for(let trace of this.outputTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let label of this.outputNetLabelPlacements){let labelRect={center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
688
688
  globalConnNetId: ${label.globalConnNetId}`};graphics.rects.push(labelRect),graphics.points.push({x:label.anchorPoint.x,y:label.anchorPoint.y,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
689
- orientation: ${label.orientation}`})}return graphics}},isSimpleFiveSegmentElbow=path=>{let simplifiedPath=simplifyPath(path);if(simplifiedPath.length!==6)return!1;let segmentIsHorizontal=simplifiedPath.slice(0,-1).map((point6,index)=>isHorizontal(point6,simplifiedPath[index+1]));return segmentIsHorizontal.every((isHorizontalSegment,index)=>index===0||isHorizontalSegment!==segmentIsHorizontal[index-1])},generateSegmentShiftCandidates=({trace,label,paddingBuffer,detourCount})=>{if(trace.globalConnNetId===label.globalConnNetId)return[];let path=simplifyPath(trace.tracePath);if(!isSimpleFiveSegmentElbow(path))return[];let labelBounds=getRectBounds(label.center,label.width,label.height),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},candidates=[];for(let segmentIndex=1;segmentIndex<path.length-2;segmentIndex++){let segmentStart=path[segmentIndex],segmentEnd=path[segmentIndex+1];if(!segmentIntersectsRect(segmentStart,segmentEnd,labelBounds))continue;let isHorizontalSegment=isHorizontal(segmentStart,segmentEnd),isVerticalSegment=isVertical(segmentStart,segmentEnd);if(!isHorizontalSegment&&!isVerticalSegment)continue;let axis=isHorizontalSegment?"y":"x",coordinates=isHorizontalSegment?[paddedLabelBounds.minY,paddedLabelBounds.maxY]:[paddedLabelBounds.minX,paddedLabelBounds.maxX];for(let coordinate of coordinates){let shiftedPath=shiftSegmentOrth(path,segmentIndex,axis,coordinate);shiftedPath&&candidates.push(shiftedPath)}}return candidates},generateTransitionShiftCandidates=({trace,label,paddingBuffer,detourCount})=>{let path=simplifyPath(trace.tracePath);if(!isSimpleFiveSegmentElbow(path))return[];let labelBounds=getRectBounds(label.center,label.width,label.height),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},start=path[0],end=path[path.length-1],middleSegmentIndex=2,candidates=[];for(let segmentIndex=0;segmentIndex<path.length-1;segmentIndex++){let segmentStart=path[segmentIndex],segmentEnd=path[segmentIndex+1];if(!segmentIntersectsRect(segmentStart,segmentEnd,labelBounds)||Math.abs(segmentIndex-middleSegmentIndex)!==1)continue;let isHorizontalSegment=isHorizontal(segmentStart,segmentEnd),isVerticalSegment=isVertical(segmentStart,segmentEnd);if(!isHorizontalSegment&&!isVerticalSegment)continue;let axis=isHorizontalSegment?"x":"y",min=isHorizontalSegment?paddedLabelBounds.minX:paddedLabelBounds.minY,max2=isHorizontalSegment?paddedLabelBounds.maxX:paddedLabelBounds.maxY,startCoordinate=isHorizontalSegment?start.x:start.y,endCoordinate=isHorizontalSegment?end.x:end.y,corridorCoordinates=[];startCoordinate<min?corridorCoordinates.push((startCoordinate+min)/2):startCoordinate>max2&&corridorCoordinates.push((startCoordinate+max2)/2),endCoordinate<min?corridorCoordinates.push((endCoordinate+min)/2):endCoordinate>max2&&corridorCoordinates.push((endCoordinate+max2)/2);for(let coordinate of new Set(corridorCoordinates)){let shiftedPath=shiftSegmentOrth(path,middleSegmentIndex,axis,coordinate);shiftedPath&&candidates.push(shiftedPath)}}return candidates},generateElbowTransitionSimplificationCandidates=({trace,label,netLabelPlacements,paddingBuffer,detourCount})=>generateTransitionShiftCandidates({trace,label,paddingBuffer,detourCount}).flatMap(tracePath=>{let shiftedTrace={...trace,tracePath};return detectTraceLabelOverlap({traces:[shiftedTrace],netLabels:netLabelPlacements}).flatMap(({label:shiftedLabel})=>generateSegmentShiftCandidates({trace:shiftedTrace,label:shiftedLabel,paddingBuffer,detourCount}))}),PATH_LENGTH_EPSILON2=1e-9,getPathLength4=points=>points.slice(1).reduce((length4,point6,pointIndex)=>{let previousPoint=points[pointIndex];return length4+Math.abs(point6.x-previousPoint.x)+Math.abs(point6.y-previousPoint.y)},0),TraceElbowTransitionSimplificationSolver=class extends BaseSolver5{constructor(input2){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"traceIdQueue");__publicField(this,"obstacles");this.input=input2,this.outputTraces=[...input2.traces];let reroutedTraceIds=new Set(input2.completedReroutes.map(completedReroute=>completedReroute.initialTrace.mspPairId));this.traceIdQueue=input2.traces.map(trace=>trace.mspPairId).filter(traceId=>reroutedTraceIds.has(traceId)),this.obstacles=getObstacleRects(input2.inputProblem)}_step(){let traceId=this.traceIdQueue.shift();if(!traceId){this.solved=!0;return}let traceIndex=this.outputTraces.findIndex(trace2=>trace2.mspPairId===traceId),trace=this.outputTraces[traceIndex],tracePath=simplifyPath(trace.tracePath),initialOverlaps=detectTraceLabelOverlap({traces:[{...trace,tracePath}],netLabels:this.input.netLabelPlacements}),otherNetTraces=this.outputTraces.filter(otherTrace=>otherTrace.mspPairId!==trace.mspPairId&&otherTrace.globalConnNetId!==trace.globalConnNetId),candidateByPath=new Map,completedReroutes=this.input.completedReroutes.filter(completedReroute=>completedReroute.initialTrace.mspPairId===trace.mspPairId);for(let completedReroute of completedReroutes){let initialReroutePath=simplifyPath(completedReroute.initialTrace.tracePath),reroutedPath=simplifyPath(completedReroute.reroutedTracePath),initialRerouteOverlapCount=detectTraceLabelOverlap({traces:[{...completedReroute.initialTrace,tracePath:initialReroutePath}],netLabels:this.input.netLabelPlacements}).length,candidates=generateElbowTransitionSimplificationCandidates({trace:completedReroute.initialTrace,label:completedReroute.label,netLabelPlacements:this.input.netLabelPlacements,paddingBuffer:this.input.paddingBuffer,detourCount:completedReroute.detourCount});for(let candidate of candidates){let simplifiedCandidate=simplifyPath(candidate),candidateTrace={...completedReroute.initialTrace,tracePath:simplifiedCandidate};detectTraceLabelOverlap({traces:[candidateTrace],netLabels:this.input.netLabelPlacements}).length<initialRerouteOverlapCount&&Math.abs(getPathLength4(simplifiedCandidate)-getPathLength4(reroutedPath))<PATH_LENGTH_EPSILON2&&simplifiedCandidate.length<reroutedPath.length&&preservesLabelAnchors(this.input.netLabelPlacements,[completedReroute.initialTrace],[candidateTrace])&&candidateByPath.set(simplifiedCandidate.map(point6=>`${point6.x},${point6.y}`).join(";"),simplifiedCandidate)}}let initialOverlapIds=new Set(initialOverlaps.map(({label})=>`${label.globalConnNetId}:${label.netId}`)),initialPathLength=getPathLength4(tracePath),validCandidates=[...candidateByPath.values()].filter(candidatePath=>{let candidateTrace={...trace,tracePath:candidatePath},candidateOverlaps=detectTraceLabelOverlap({traces:[candidateTrace],netLabels:this.input.netLabelPlacements}),candidateOnlyKeepsExistingOverlaps=candidateOverlaps.every(({label})=>initialOverlapIds.has(`${label.globalConnNetId}:${label.netId}`)),reducesCollisions=candidateOverlaps.length<initialOverlaps.length,simplifiesGeometry=candidateOverlaps.length===initialOverlaps.length&&getPathLength4(candidatePath)<=initialPathLength+PATH_LENGTH_EPSILON2&&candidatePath.length<tracePath.length;return candidateOnlyKeepsExistingOverlaps&&(reducesCollisions||simplifiesGeometry)&&preservesLabelAnchors(this.input.netLabelPlacements,[trace],[candidateTrace])&&!isPathCollidingWithObstacles(candidatePath,this.obstacles)&&!doesPathCoincideWithTraces(candidatePath,otherNetTraces)}),getOverlapCount=candidatePath=>detectTraceLabelOverlap({traces:[{...trace,tracePath:candidatePath}],netLabels:this.input.netLabelPlacements}).length;validCandidates.sort((a6,b6)=>{let overlapDifference=getOverlapCount(a6)-getOverlapCount(b6);return overlapDifference!==0?overlapDifference:getPathLength4(a6)-getPathLength4(b6)||a6.length-b6.length});let bestCandidate=validCandidates[0];bestCandidate&&(this.outputTraces[traceIndex]={...trace,tracePath:bestCandidate},this.stats.simplifiedTraceCount=(this.stats.simplifiedTraceCount??0)+1)}getOutput(){return{traces:this.outputTraces,netLabelPlacements:this.input.netLabelPlacements}}visualize(){let graphics=visualizeInputProblem2(this.input.inputProblem);graphics.lines??(graphics.lines=[]);for(let trace of this.outputTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});return graphics}},getStubDirection=path=>{let[start,end]=path;return Math.abs(end.x-start.x)>=Math.abs(end.y-start.y)?end.x>=start.x?"x+":"x-":end.y>=start.y?"y+":"y-"},getStubLength=path=>{let[start,end]=path;return Math.abs(end.x-start.x)+Math.abs(end.y-start.y)},getLabelBounds2=placement=>{let isVertical52=placement.axis==="y",width=isVertical52?placement.height:placement.width,height=isVertical52?placement.width:placement.height;return{minX:placement.center.x-width/2,maxX:placement.center.x+width/2,minY:placement.center.y-height/2,maxY:placement.center.y+height/2}},getPathBounds=path=>({minX:Math.min(...path.map(point6=>point6.x)),maxX:Math.max(...path.map(point6=>point6.x)),minY:Math.min(...path.map(point6=>point6.y)),maxY:Math.max(...path.map(point6=>point6.y))}),doesPathIntersectBounds=(path,bounds)=>{for(let index=0;index<path.length-1;index++){let segmentBounds=getPathBounds([path[index],path[index+1]]);if(boundsOverlap(segmentBounds,bounds))return!0}return!1},resizeStub=(placement,direction2,targetLength)=>{let[start]=placement.stubTracePath,end=direction2==="x+"?{x:start.x+targetLength,y:start.y}:direction2==="x-"?{x:start.x-targetLength,y:start.y}:direction2==="y+"?{x:start.x,y:start.y+targetLength}:{x:start.x,y:start.y-targetLength},anchorPoint={x:(start.x+end.x)/2,y:(start.y+end.y)/2};return{...placement,stubTracePath:[start,end],anchorPoint,center:placement.center}},alignPortOnlyInlineNetLabelStubs=({placements,inputProblem,traces,netLabelPlacements})=>{let chipIdByPinId=new Map;for(let chip of inputProblem.chips)for(let pin of chip.pins)chipIdByPinId.set(pin.pinId,chip.chipId);let groups=new Map;for(let[placementIndex,placement]of placements.entries()){if(!placement.stubTracePath||placement.pinIds.length!==1)continue;let direction2=getStubDirection(placement.stubTracePath);if(!direction2)continue;let ownerChipId=chipIdByPinId.get(placement.pinIds[0]),groupKey=`${ownerChipId??placement.pinIds[0]}::${direction2}`,group=groups.get(groupKey)??[];group.push({placementIndex,placement,direction:direction2,ownerChipId}),groups.set(groupKey,group)}let alignedPlacements=[...placements],supersededGlobalNetIds=new Set(placements.map(placement=>placement.globalConnNetId)),retainedAnchoredLabelBounds=netLabelPlacements.filter(placement=>!supersededGlobalNetIds.has(placement.globalConnNetId)).map(getLabelBounds2);for(let group of groups.values()){if(group.length<2)continue;let targetLength=Math.max(...group.map(({placement})=>getStubLength(placement.stubTracePath))),proposals=group.map(({placement,direction:direction2})=>resizeStub(placement,direction2,targetLength)),groupPlacementIndices=new Set(group.map(({placementIndex})=>placementIndex)),fixedInlinePlacements=placements.filter((_6,placementIndex)=>!groupPlacementIndices.has(placementIndex));if(!proposals.some((proposal,proposalIndex)=>{let labelBounds=getLabelBounds2(proposal),stubPath=proposal.stubTracePath,stubBounds=getPathBounds(stubPath),ownerChipId=group[proposalIndex].ownerChipId;for(let chip of inputProblem.chips){let chipBounds={minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2};if(boundsOverlap(labelBounds,chipBounds)||chip.chipId!==ownerChipId&&boundsOverlap(stubBounds,chipBounds))return!0}for(let textBox of inputProblem.textBoxes??[]){let textBounds=getTextBoxBounds(textBox);if(boundsOverlap(labelBounds,textBounds)||boundsOverlap(stubBounds,textBounds))return!0}for(let trace of traces)if(trace.globalConnNetId!==proposal.globalConnNetId&&(doesPathIntersectBounds(trace.tracePath,labelBounds)||doesPathIntersectBounds(trace.tracePath,stubBounds)))return!0;if(retainedAnchoredLabelBounds.some(bounds=>boundsOverlap(labelBounds,bounds)||boundsOverlap(stubBounds,bounds)))return!0;for(let fixedPlacement of fixedInlinePlacements){let fixedLabelBounds=getLabelBounds2(fixedPlacement);if(boundsOverlap(labelBounds,fixedLabelBounds)||boundsOverlap(stubBounds,fixedLabelBounds)||fixedPlacement.stubTracePath&&(doesPathIntersectBounds(fixedPlacement.stubTracePath,labelBounds)||doesPathIntersectBounds(stubPath,fixedLabelBounds)))return!0}for(let[otherIndex,otherProposal]of proposals.entries()){if(otherIndex===proposalIndex)continue;let otherLabelBounds=getLabelBounds2(otherProposal);if(boundsOverlap(labelBounds,otherLabelBounds)||doesPathIntersectBounds(stubPath,otherLabelBounds))return!0}return!1}))for(let[groupIndex,{placementIndex}]of group.entries())alignedPlacements[placementIndex]=proposals[groupIndex]}return alignedPlacements},getAxisAlignedSegments=(path,epsilon=1e-6)=>{let segments=[],runStart=null,runAxis=null,runSign=0,closeRun=runEnd=>{if(runStart&&runAxis){let length4=Math.abs(runAxis==="x"?runEnd.x-runStart.x:runEnd.y-runStart.y);length4>epsilon&&segments.push({start:runStart,end:runEnd,axis:runAxis,length:length4})}runStart=null,runAxis=null,runSign=0};for(let i6=0;i6<path.length-1;i6++){let a6=path[i6],b6=path[i6+1],dx3=b6.x-a6.x,dy3=b6.y-a6.y;if(Math.abs(dx3)<=epsilon&&Math.abs(dy3)<=epsilon)continue;let axis=Math.abs(dy3)<=epsilon?"x":Math.abs(dx3)<=epsilon?"y":null;if(!axis){closeRun(a6);continue}let sign=Math.sign(axis==="x"?dx3:dy3);runStart&&runAxis===axis&&runSign===sign||(closeRun(a6),runStart=a6,runAxis=axis,runSign=sign)}return path.length>=2&&closeRun(path[path.length-1]),segments.sort((a6,b6)=>b6.length-a6.length)},LABEL_CLEARANCE2=.05,POINT_EPSILON=1e-6,CONTIGUOUS_LABEL_GAP=.01,MAX_OUTWARD_DISTANCE=5,getBounds32=placement=>{let renderedWidth=placement.axis==="y"?placement.height:placement.width,renderedHeight=placement.axis==="y"?placement.width:placement.height;return{minX:placement.center.x-renderedWidth/2,maxX:placement.center.x+renderedWidth/2,minY:placement.center.y-renderedHeight/2,maxY:placement.center.y+renderedHeight/2}},pointsEqual3=(a6,b6)=>Math.abs(a6.x-b6.x)<=POINT_EPSILON&&Math.abs(a6.y-b6.y)<=POINT_EPSILON,pathIntersectsBounds=(path,bounds)=>{for(let index=0;index<path.length-1;index++){let start=path[index],end=path[index+1],segmentBounds={minX:Math.min(start.x,end.x),maxX:Math.max(start.x,end.x),minY:Math.min(start.y,end.y),maxY:Math.max(start.y,end.y)};if(boundsOverlap(segmentBounds,bounds))return!0}return!1},isPointOnPath2=(point6,path)=>{for(let index=0;index<path.length-1;index++){let start=path[index],end=path[index+1],minX=Math.min(start.x,end.x)-POINT_EPSILON,maxX=Math.max(start.x,end.x)+POINT_EPSILON,minY=Math.min(start.y,end.y)-POINT_EPSILON,maxY=Math.max(start.y,end.y)+POINT_EPSILON,isHorizontal42=Math.abs(start.y-end.y)<=POINT_EPSILON,isVertical52=Math.abs(start.x-end.x)<=POINT_EPSILON;if((isHorizontal42&&Math.abs(point6.y-start.y)<=POINT_EPSILON||isVertical52&&Math.abs(point6.x-start.x)<=POINT_EPSILON)&&point6.x>=minX&&point6.x<=maxX&&point6.y>=minY&&point6.y<=maxY)return!0}return!1},getRequiredOutwardDistance=(label,inlineBounds)=>{let labelBounds=getBounds32(label);if(label.orientation==="x-"||label.orientation==="x+"){let nearby2=inlineBounds.filter(bounds=>labelBounds.minY<bounds.maxY&&labelBounds.maxY>bounds.minY);if(nearby2.length===0)return 0;if(label.orientation==="x-"){let targetMaxX=Math.min(...nearby2.map(bounds=>bounds.minX));return Math.max(0,labelBounds.maxX-targetMaxX+LABEL_CLEARANCE2)}let targetMinX=Math.max(...nearby2.map(bounds=>bounds.maxX));return Math.max(0,targetMinX-labelBounds.minX+LABEL_CLEARANCE2)}let nearby=inlineBounds.filter(bounds=>labelBounds.minX<bounds.maxX&&labelBounds.maxX>bounds.minX);if(nearby.length===0)return 0;if(label.orientation==="y-"){let targetMaxY=Math.min(...nearby.map(bounds=>bounds.minY));return Math.max(0,labelBounds.maxY-targetMaxY+LABEL_CLEARANCE2)}let targetMinY=Math.max(...nearby.map(bounds=>bounds.maxY));return Math.max(0,targetMinY-labelBounds.minY+LABEL_CLEARANCE2)},moveLabel=(label,orientation4,distance52)=>{let direction2=dir(orientation4);return{...label,anchorPoint:{x:label.anchorPoint.x+direction2.x*distance52,y:label.anchorPoint.y+direction2.y*distance52},center:{x:label.center.x+direction2.x*distance52,y:label.center.y+direction2.y*distance52}}},getDistanceToShoveBoundsPast=(obstacleBounds,movingBounds,orientation4)=>{switch(orientation4){case"x-":return obstacleBounds.maxX-movingBounds.minX+LABEL_CLEARANCE2;case"x+":return movingBounds.maxX-obstacleBounds.minX+LABEL_CLEARANCE2;case"y-":return obstacleBounds.maxY-movingBounds.minY+LABEL_CLEARANCE2;case"y+":return movingBounds.maxY-obstacleBounds.minY+LABEL_CLEARANCE2}},boundsGapOnPerpendicularAxis=(a6,b6,orientation4)=>orientation4==="x-"||orientation4==="x+"?Math.max(0,a6.minY-b6.maxY,b6.minY-a6.maxY):Math.max(0,a6.minX-b6.maxX,b6.minX-a6.maxX),sharesOwnerChip=(label,ownerChipIds,chipIdByPinId)=>label.pinIds.some(pinId=>ownerChipIds.has(chipIdByPinId.get(pinId)??"")),isGeneratedLabelConnector=trace=>trace.mspPairId.startsWith("available-net-orientation-")||trace.mspPairId.startsWith("inline-net-label-clearance-"),findConnectorTraceIndex=(label,traces)=>traces.findIndex(trace=>{if(trace.globalConnNetId!==label.globalConnNetId||!isGeneratedLabelConnector(trace))return!1;let first=trace.tracePath[0],last=trace.tracePath.at(-1);return!!(first&&pointsEqual3(first,label.anchorPoint)||last&&pointsEqual3(last,label.anchorPoint))}),canAddConnectorAtAnchor=(label,traces,pinMap)=>label.pinIds.some(pinId=>{let pin=pinMap[pinId];return pin&&pointsEqual3(pin,label.anchorPoint)})?!0:traces.some(trace=>trace.globalConnNetId===label.globalConnNetId&&isPointOnPath2(label.anchorPoint,trace.tracePath)),moveConnectorEndpoint=(trace,oldAnchor,newAnchor)=>{let tracePath=trace.tracePath.map(point6=>({...point6}));return pointsEqual3(tracePath[0],oldAnchor)&&(tracePath[0]=newAnchor),pointsEqual3(tracePath.at(-1),oldAnchor)&&(tracePath[tracePath.length-1]=newAnchor),{...trace,tracePath}},createConnectorTrace=({label,labelIndex,newAnchor,pinMap})=>{let mspPairId=`inline-net-label-clearance-${labelIndex}-${label.netId??label.globalConnNetId}`;return{mspPairId,dcConnNetId:label.dcConnNetId??label.globalConnNetId,globalConnNetId:label.globalConnNetId,userNetId:label.netId,pins:getTracePins(label,pinMap),tracePath:[label.anchorPoint,newAnchor],mspConnectionPairIds:[mspPairId],pinIds:label.pinIds}},getContiguousLabelGroup=({triggerIndex,labels,chipIdByPinId})=>{let trigger=labels[triggerIndex],ownerChipIds=new Set(trigger.pinIds.flatMap(pinId=>{let chipId=chipIdByPinId.get(pinId);return chipId?[chipId]:[]})),candidates=labels.map((label,labelIndex)=>({label,labelIndex})).filter(({label})=>label.orientation===trigger.orientation&&label.mspConnectionPairIds.length===0&&sharesOwnerChip(label,ownerChipIds,chipIdByPinId)),group=new Set([triggerIndex]),changed=!0;for(;changed;){changed=!1;for(let{label,labelIndex}of candidates)group.has(labelIndex)||[...group].some(memberIndex=>boundsGapOnPerpendicularAxis(getBounds32(labels[memberIndex]),getBounds32(label),trigger.orientation)<=CONTIGUOUS_LABEL_GAP)&&(group.add(labelIndex),changed=!0)}return{group,ownerChipIds}},pushAnchoredNetLabelsAwayFromInlineLabels=({inputProblem,traces,netLabelPlacements,inlineNetLabelPlacements})=>{let outputTraces=traces.map(trace=>({...trace,tracePath:trace.tracePath.map(point6=>({...point6}))})),outputLabels=netLabelPlacements.map(label=>({...label})),inlineBounds=inlineNetLabelPlacements.map(getBounds32),pinMap=getPinMap(inputProblem),chipIdByPinId=new Map;for(let chip of inputProblem.chips)for(let pin of chip.pins)chipIdByPinId.set(pin.pinId,chip.chipId);let movedLabelIndices=new Set;for(let triggerIndex=0;triggerIndex<outputLabels.length;triggerIndex++){let trigger=outputLabels[triggerIndex],distance52=getRequiredOutwardDistance(trigger,inlineBounds);if(distance52<=POINT_EPSILON||distance52>MAX_OUTWARD_DISTANCE)continue;let{group,ownerChipIds}=getContiguousLabelGroup({triggerIndex,labels:outputLabels,chipIdByPinId}),distances=new Map([...group].map(labelIndex=>[labelIndex,distance52])),failed=!1;for(let iteration=0;iteration<outputLabels.length;iteration++){let adjustedObstacle=!1;for(let[movingIndex,movingDistance]of distances){let movingBounds=getBounds32(moveLabel(outputLabels[movingIndex],trigger.orientation,movingDistance));for(let obstacleIndex=0;obstacleIndex<outputLabels.length;obstacleIndex++){if(group.has(obstacleIndex))continue;let obstacle=outputLabels[obstacleIndex],existingObstacleDistance=distances.get(obstacleIndex)??0,obstacleBounds=getBounds32(moveLabel(obstacle,trigger.orientation,existingObstacleDistance));if(!boundsOverlap(movingBounds,obstacleBounds))continue;if(!sharesOwnerChip(obstacle,ownerChipIds,chipIdByPinId)||findConnectorTraceIndex(obstacle,outputTraces)===-1&&!canAddConnectorAtAnchor(obstacle,outputTraces,pinMap)){failed=!0;break}let shoveDistance=getDistanceToShoveBoundsPast(getBounds32(obstacle),movingBounds,trigger.orientation);if(shoveDistance>MAX_OUTWARD_DISTANCE||shoveDistance<=existingObstacleDistance+POINT_EPSILON){failed=!0;break}distances.set(obstacleIndex,shoveDistance),adjustedObstacle=!0}if(failed)break}if(failed||!adjustedObstacle)break}if(failed)continue;let proposals=new Map;for(let[labelIndex,labelDistance]of distances)proposals.set(labelIndex,moveLabel(outputLabels[labelIndex],trigger.orientation,labelDistance));let finalLabelAt=labelIndex=>proposals.get(labelIndex)??outputLabels[labelIndex];for(let[labelIndex,movedLabel]of proposals){let movedBounds=getBounds32(movedLabel);if(inlineBounds.some(bounds=>boundsOverlap(movedBounds,bounds))){failed=!0;break}if(inputProblem.chips.some(chip=>boundsOverlap(movedBounds,{minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2}))||(inputProblem.textBoxes??[]).some(textBox=>boundsOverlap(movedBounds,getTextBoxBounds(textBox)))){failed=!0;break}if(outputLabels.some((_6,otherIndex)=>otherIndex!==labelIndex&&boundsOverlap(movedBounds,getBounds32(finalLabelAt(otherIndex))))){failed=!0;break}if(outputTraces.some(trace=>trace.globalConnNetId!==movedLabel.globalConnNetId&&pathIntersectsBounds(trace.tracePath,movedBounds))){failed=!0;break}}if(failed)continue;let connectorUpdates=[];for(let[labelIndex,movedLabel]of proposals){let label=outputLabels[labelIndex],connectorIndex=findConnectorTraceIndex(label,outputTraces);if(connectorIndex===-1&&!canAddConnectorAtAnchor(label,outputTraces,pinMap)){failed=!0;break}let connector=connectorIndex===-1?createConnectorTrace({label,labelIndex,newAnchor:movedLabel.anchorPoint,pinMap}):moveConnectorEndpoint(outputTraces[connectorIndex],label.anchorPoint,movedLabel.anchorPoint);if(inlineBounds.some(bounds=>pathIntersectsBounds(connector.tracePath,bounds))||inputProblem.chips.some(chip=>pathIntersectsBounds(connector.tracePath,{minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2}))||(inputProblem.textBoxes??[]).some(textBox=>pathIntersectsBounds(connector.tracePath,getTextBoxBounds(textBox)))||outputLabels.some((_6,otherIndex)=>otherIndex!==labelIndex&&pathIntersectsBounds(connector.tracePath,getBounds32(finalLabelAt(otherIndex))))){failed=!0;break}connectorUpdates.push({labelIndex,connectorIndex,trace:connector})}if(!failed){for(let[labelIndex,movedLabel]of proposals)outputLabels[labelIndex]=movedLabel,movedLabelIndices.add(labelIndex);for(let update of connectorUpdates)update.connectorIndex===-1?outputTraces.push(update.trace):outputTraces[update.connectorIndex]=update.trace}}return{traces:outputTraces,netLabelPlacements:outputLabels,movedLabelCount:movedLabelIndices.size}},DEFAULT_INLINE_NET_LABEL_HEIGHT=.18,INLINE_NET_LABEL_TRACE_MARGIN=.05,INLINE_NET_LABEL_STUB_TRACE_CLEARANCE=.05,INLINE_NET_LABEL_MAX_SPAN_JOG=.4,getPinPairKey2=pinIds=>[...pinIds].sort().join("::"),InlineNetLabelSolver=class extends BaseSolver5{constructor(input2){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"inputNetLabelPlacements");__publicField(this,"inlineNetLabelPlacements",[]);__publicField(this,"queuedConnections");__publicField(this,"tracesByPinPairKey");__publicField(this,"hasAlignedPortOnlyStubs",!1);__publicField(this,"postProcessedOutput");this.inputProblem=input2.inputProblem,this.traces=input2.traces,this.inputNetLabelPlacements=input2.netLabelPlacements,this.queuedConnections=[...this.inputProblem.directConnections.filter(connection=>connection.allowInlineNetLabel&&connection.netId),...this.inputProblem.netConnections.filter(connection=>connection.allowInlineNetLabel&&connection.pinIds.length>=1&&connection.pinIds.length<=2&&connection.netId)],this.tracesByPinPairKey=new Map;for(let trace of this.traces){let key=getPinPairKey2(trace.pins.map(p3=>p3.pinId)),existing=this.tracesByPinPairKey.get(key);existing?existing.push(trace):this.tracesByPinPairKey.set(key,[trace])}}getConstructorParams(){return[{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.inputNetLabelPlacements}]}_step(){let connection=this.queuedConnections.shift();if(connection){if((connection.pinIds.length===2?this.tracesByPinPairKey.get(getPinPairKey2(connection.pinIds))??[]:[]).length>0){let placement=this.computeInlinePlacement(connection);placement&&this.inlineNetLabelPlacements.push(placement)}else{let terminalPlacements=connection.pinIds.map(pinId=>this.computeTerminalInlinePlacement(connection,pinId));terminalPlacements.every(placement=>placement!==null)&&this.inlineNetLabelPlacements.push(...terminalPlacements)}return}if(!this.hasAlignedPortOnlyStubs){this.inlineNetLabelPlacements=alignPortOnlyInlineNetLabelStubs({placements:this.inlineNetLabelPlacements,inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.inputNetLabelPlacements}),this.hasAlignedPortOnlyStubs=!0;return}if(!this.postProcessedOutput){this.postProcessedOutput=this.buildPostProcessedOutput();return}this.solved=!0,this.stats.inlineNetLabelCount=this.inlineNetLabelPlacements.length}computeTerminalInlinePlacement(connection,pinId){if(!connection.netId)return null;let anchoredPlacement=this.inputNetLabelPlacements.find(placement=>placement.netId===connection.netId&&placement.pinIds.length===1&&placement.pinIds[0]===pinId);if(!anchoredPlacement)return null;let inputChip=this.inputProblem.chips.find(chip=>chip.pins.some(pin=>pin.pinId===pinId)),inputPin=inputChip?.pins.find(pin=>pin.pinId===pinId),height=connection.inlineNetLabelHeight??DEFAULT_INLINE_NET_LABEL_HEIGHT,netLabelText=connection.netLabelText?.trim()||void 0,width=connection.inlineNetLabelWidth??connection.netLabelWidth??estimateInlineNetLabelWidth(netLabelText??connection.netId,height),stubLength=Math.max(width+.2,.6),start=inputPin?{x:inputPin.x,y:inputPin.y}:anchoredPlacement.anchorPoint,direction2=inputPin&&inputChip?inputPin._facingDirection??getPinDirection(inputPin,inputChip):anchoredPlacement.orientation,intendedEnd=direction2==="x+"?{x:start.x+stubLength,y:start.y}:direction2==="x-"?{x:start.x-stubLength,y:start.y}:direction2==="y+"?{x:start.x,y:start.y+stubLength}:{x:start.x,y:start.y-stubLength},end=getCollisionLimitedTerminalStubEnd({start,intendedEnd,minimumLength:width+2*INLINE_NET_LABEL_TRACE_MARGIN,traces:this.traces,ownGlobalConnNetId:anchoredPlacement.globalConnNetId});if(!end)return null;let axis=direction2==="x+"||direction2==="x-"?"x":"y",side=axis==="x"?"y+":"x-",anchorPoint={x:(start.x+end.x)/2,y:(start.y+end.y)/2},offset=height/2+INLINE_NET_LABEL_TRACE_MARGIN,center2=side==="y+"?{x:anchorPoint.x,y:anchorPoint.y+offset}:{x:anchorPoint.x-offset,y:anchorPoint.y},halfAlong=width/2,halfAcross=height/2,bounds=axis==="x"?{minX:center2.x-halfAlong,maxX:center2.x+halfAlong,minY:center2.y-halfAcross,maxY:center2.y+halfAcross}:{minX:center2.x-halfAcross,maxX:center2.x+halfAcross,minY:center2.y-halfAlong,maxY:center2.y+halfAlong};return this.isObstructed(bounds,{ownGlobalConnNetId:anchoredPlacement.globalConnNetId})?null:{globalConnNetId:anchoredPlacement.globalConnNetId,netId:connection.netId,netLabelText,pinIds:[pinId],stubTracePath:[start,end],axis,anchorPoint,center:center2,width,height,side}}computeInlinePlacement(connection){let traces=this.tracesByPinPairKey.get(getPinPairKey2(connection.pinIds))??[];if(traces.length===0)return null;let trace=traces[0],segments=getAxisAlignedSegments(trace.tracePath);if(segments.length===0)return null;let height=connection.inlineNetLabelHeight??DEFAULT_INLINE_NET_LABEL_HEIGHT,netLabelText=connection.netLabelText?.trim()||void 0,width=connection.inlineNetLabelWidth??connection.netLabelWidth??estimateInlineNetLabelWidth(netLabelText??connection.netId,height),offset=height/2+INLINE_NET_LABEL_TRACE_MARGIN,usableSegments=segments.filter(segment2=>segment2.length>=width).sort((a6,b6)=>b6.length-a6.length);for(let segment2 of usableSegments){let sides=segment2.axis==="x"?["y+","y-"]:["x-","x+"];for(let side of sides)for(let anchorPoint of getAnchorCandidates(segment2,width)){let center2=side==="y+"?{x:anchorPoint.x,y:anchorPoint.y+offset}:side==="y-"?{x:anchorPoint.x,y:anchorPoint.y-offset}:side==="x-"?{x:anchorPoint.x-offset,y:anchorPoint.y}:{x:anchorPoint.x+offset,y:anchorPoint.y},halfAlong=width/2,halfAcross=height/2,bounds=segment2.axis==="x"?{minX:center2.x-halfAlong,maxX:center2.x+halfAlong,minY:center2.y-halfAcross,maxY:center2.y+halfAcross}:{minX:center2.x-halfAcross,maxX:center2.x+halfAcross,minY:center2.y-halfAlong,maxY:center2.y+halfAlong};if(!this.isObstructed(bounds,{ownTrace:trace,ownGlobalConnNetId:trace.globalConnNetId}))return{globalConnNetId:trace.globalConnNetId,netId:connection.netId,netLabelText,mspPairId:trace.mspPairId,pinIds:[...connection.pinIds],axis:segment2.axis,anchorPoint,center:center2,width,height,side}}}let spanPlacement=this.computeSpanPlacement({trace,connection,netLabelText,width,height,offset});return spanPlacement||null}computeSpanPlacement({trace,connection,netLabelText,width,height,offset}){let path=trace.tracePath;if(path.length<2)return null;let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of path)minX=Math.min(minX,point6.x),maxX=Math.max(maxX,point6.x),minY=Math.min(minY,point6.y),maxY=Math.max(maxY,point6.y);let extentX=maxX-minX,extentY=maxY-minY,axis=extentX>=extentY?"x":"y",spanLength=axis==="x"?extentX:extentY;if((axis==="x"?extentY:extentX)>INLINE_NET_LABEL_MAX_SPAN_JOG||spanLength<width)return null;let mid=((axis==="x"?minX:minY)+(axis==="x"?maxX:maxY))/2,halfRange=(spanLength-width)/2,offsets=[0];for(let value=.1;value<=halfRange+1e-9;value+=.1)offsets.push(value,-value);offsets.push(halfRange,-halfRange);let sides=axis==="x"?["y+","y-"]:["x-","x+"];for(let side of sides)for(let alongOffset of offsets){let along=mid+alongOffset,center2=side==="y+"?{x:along,y:maxY+offset}:side==="y-"?{x:along,y:minY-offset}:side==="x-"?{x:minX-offset,y:along}:{x:maxX+offset,y:along},halfAlong=width/2,halfAcross=height/2,bounds=axis==="x"?{minX:center2.x-halfAlong,maxX:center2.x+halfAlong,minY:center2.y-halfAcross,maxY:center2.y+halfAcross}:{minX:center2.x-halfAcross,maxX:center2.x+halfAcross,minY:center2.y-halfAlong,maxY:center2.y+halfAlong};if(this.isObstructed(bounds,{ownTrace:trace,ownGlobalConnNetId:trace.globalConnNetId}))continue;let anchorPoint=axis==="x"?{x:along,y:side==="y+"?maxY:minY}:{x:side==="x-"?minX:maxX,y:along};return{globalConnNetId:trace.globalConnNetId,netId:connection.netId,netLabelText,mspPairId:trace.mspPairId,pinIds:[...connection.pinIds],axis,anchorPoint,center:center2,width,height,side}}return null}isObstructed(bounds,{ownTrace,ownGlobalConnNetId}){for(let chip of this.inputProblem.chips){let chipBounds={minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2};if(boundsOverlap(bounds,chipBounds))return!0}for(let textBox of this.inputProblem.textBoxes??[])if(boundsOverlap(bounds,getTextBoxBounds(textBox)))return!0;for(let trace of this.traces)if(!(ownTrace&&trace.mspPairId===ownTrace.mspPairId)&&trace.globalConnNetId!==ownGlobalConnNetId&&doesPathIntersectBounds2(trace.tracePath,bounds))return!0;return!1}getSupersededNetLabelKeys(){let keys=new Set;for(let placement of this.inlineNetLabelPlacements)keys.add(placement.globalConnNetId);return keys}getOutputTraces(supersededNetLabelKeys){return this.traces.filter(trace=>!(supersededNetLabelKeys.has(trace.globalConnNetId)&&trace.mspPairId.startsWith("available-net-orientation-")))}buildPostProcessedOutput(){let superseded=this.getSupersededNetLabelKeys(),retainedNetLabelPlacements=this.inputNetLabelPlacements.filter(placement=>!superseded.has(placement.globalConnNetId)),outputTraces=this.getOutputTraces(superseded),pushed=pushAnchoredNetLabelsAwayFromInlineLabels({inputProblem:this.inputProblem,traces:outputTraces,netLabelPlacements:retainedNetLabelPlacements,inlineNetLabelPlacements:this.inlineNetLabelPlacements});return this.stats.pushedAnchoredNetLabelCount=pushed.movedLabelCount,{traces:pushed.traces,netLabelPlacements:pushed.netLabelPlacements,inlineNetLabelPlacements:this.inlineNetLabelPlacements}}getOutput(){return this.postProcessedOutput?this.postProcessedOutput:this.buildPostProcessedOutput()}visualize(){return visualizeInlineNetLabelOutput({inputProblem:this.inputProblem,...this.getOutput()})}},visualizeInlineNetLabelOutput=({inputProblem,traces,netLabelPlacements,inlineNetLabelPlacements})=>{let graphics=visualizeInputProblem2(inputProblem);graphics.lines??(graphics.lines=[]),graphics.rects??(graphics.rects=[]),graphics.points??(graphics.points=[]),graphics.texts??(graphics.texts=[]);for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let label of netLabelPlacements)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
689
+ orientation: ${label.orientation}`})}return graphics}},isSimpleFiveSegmentElbow=path=>{let simplifiedPath=simplifyPath(path);if(simplifiedPath.length!==6)return!1;let segmentIsHorizontal=simplifiedPath.slice(0,-1).map((point6,index)=>isHorizontal(point6,simplifiedPath[index+1]));return segmentIsHorizontal.every((isHorizontalSegment,index)=>index===0||isHorizontalSegment!==segmentIsHorizontal[index-1])},generateSegmentShiftCandidates=({trace,label,paddingBuffer,detourCount})=>{if(trace.globalConnNetId===label.globalConnNetId)return[];let path=simplifyPath(trace.tracePath);if(!isSimpleFiveSegmentElbow(path))return[];let labelBounds=getRectBounds(label.center,label.width,label.height),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},candidates=[];for(let segmentIndex=1;segmentIndex<path.length-2;segmentIndex++){let segmentStart=path[segmentIndex],segmentEnd=path[segmentIndex+1];if(!segmentIntersectsRect(segmentStart,segmentEnd,labelBounds))continue;let isHorizontalSegment=isHorizontal(segmentStart,segmentEnd),isVerticalSegment=isVertical(segmentStart,segmentEnd);if(!isHorizontalSegment&&!isVerticalSegment)continue;let axis=isHorizontalSegment?"y":"x",coordinates=isHorizontalSegment?[paddedLabelBounds.minY,paddedLabelBounds.maxY]:[paddedLabelBounds.minX,paddedLabelBounds.maxX];for(let coordinate of coordinates){let shiftedPath=shiftSegmentOrth(path,segmentIndex,axis,coordinate);shiftedPath&&candidates.push(shiftedPath)}}return candidates},generateTransitionShiftCandidates=({trace,label,paddingBuffer,detourCount})=>{let path=simplifyPath(trace.tracePath);if(!isSimpleFiveSegmentElbow(path))return[];let labelBounds=getRectBounds(label.center,label.width,label.height),effectivePadding=paddingBuffer+detourCount*paddingBuffer,paddedLabelBounds={minX:labelBounds.minX-effectivePadding,maxX:labelBounds.maxX+effectivePadding,minY:labelBounds.minY-effectivePadding,maxY:labelBounds.maxY+effectivePadding},start=path[0],end=path[path.length-1],middleSegmentIndex=2,candidates=[];for(let segmentIndex=0;segmentIndex<path.length-1;segmentIndex++){let segmentStart=path[segmentIndex],segmentEnd=path[segmentIndex+1];if(!segmentIntersectsRect(segmentStart,segmentEnd,labelBounds)||Math.abs(segmentIndex-middleSegmentIndex)!==1)continue;let isHorizontalSegment=isHorizontal(segmentStart,segmentEnd),isVerticalSegment=isVertical(segmentStart,segmentEnd);if(!isHorizontalSegment&&!isVerticalSegment)continue;let axis=isHorizontalSegment?"x":"y",min=isHorizontalSegment?paddedLabelBounds.minX:paddedLabelBounds.minY,max2=isHorizontalSegment?paddedLabelBounds.maxX:paddedLabelBounds.maxY,startCoordinate=isHorizontalSegment?start.x:start.y,endCoordinate=isHorizontalSegment?end.x:end.y,corridorCoordinates=[];startCoordinate<min?corridorCoordinates.push((startCoordinate+min)/2):startCoordinate>max2&&corridorCoordinates.push((startCoordinate+max2)/2),endCoordinate<min?corridorCoordinates.push((endCoordinate+min)/2):endCoordinate>max2&&corridorCoordinates.push((endCoordinate+max2)/2);for(let coordinate of new Set(corridorCoordinates)){let shiftedPath=shiftSegmentOrth(path,middleSegmentIndex,axis,coordinate);shiftedPath&&candidates.push(shiftedPath)}}return candidates},generateElbowTransitionSimplificationCandidates=({trace,label,netLabelPlacements,paddingBuffer,detourCount})=>generateTransitionShiftCandidates({trace,label,paddingBuffer,detourCount}).flatMap(tracePath=>{let shiftedTrace={...trace,tracePath};return detectTraceLabelOverlap({traces:[shiftedTrace],netLabels:netLabelPlacements}).flatMap(({label:shiftedLabel})=>generateSegmentShiftCandidates({trace:shiftedTrace,label:shiftedLabel,paddingBuffer,detourCount}))}),PATH_LENGTH_EPSILON2=1e-9,getPathLength4=points=>points.slice(1).reduce((length4,point6,pointIndex)=>{let previousPoint=points[pointIndex];return length4+Math.abs(point6.x-previousPoint.x)+Math.abs(point6.y-previousPoint.y)},0),TraceElbowTransitionSimplificationSolver=class extends BaseSolver5{constructor(input2){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"traceIdQueue");__publicField(this,"obstacles");this.input=input2,this.outputTraces=[...input2.traces];let reroutedTraceIds=new Set(input2.completedReroutes.map(completedReroute=>completedReroute.initialTrace.mspPairId));this.traceIdQueue=input2.traces.map(trace=>trace.mspPairId).filter(traceId=>reroutedTraceIds.has(traceId)),this.obstacles=getObstacleRects(input2.inputProblem)}_step(){let traceId=this.traceIdQueue.shift();if(!traceId){this.solved=!0;return}let traceIndex=this.outputTraces.findIndex(trace2=>trace2.mspPairId===traceId),trace=this.outputTraces[traceIndex],tracePath=simplifyPath(trace.tracePath),initialOverlaps=detectTraceLabelOverlap({traces:[{...trace,tracePath}],netLabels:this.input.netLabelPlacements}),otherNetTraces=this.outputTraces.filter(otherTrace=>otherTrace.mspPairId!==trace.mspPairId&&otherTrace.globalConnNetId!==trace.globalConnNetId),candidateByPath=new Map,completedReroutes=this.input.completedReroutes.filter(completedReroute=>completedReroute.initialTrace.mspPairId===trace.mspPairId);for(let completedReroute of completedReroutes){let initialReroutePath=simplifyPath(completedReroute.initialTrace.tracePath),reroutedPath=simplifyPath(completedReroute.reroutedTracePath),initialRerouteOverlapCount=detectTraceLabelOverlap({traces:[{...completedReroute.initialTrace,tracePath:initialReroutePath}],netLabels:this.input.netLabelPlacements}).length,candidates=generateElbowTransitionSimplificationCandidates({trace:completedReroute.initialTrace,label:completedReroute.label,netLabelPlacements:this.input.netLabelPlacements,paddingBuffer:this.input.paddingBuffer,detourCount:completedReroute.detourCount});for(let candidate of candidates){let simplifiedCandidate=simplifyPath(candidate),candidateTrace={...completedReroute.initialTrace,tracePath:simplifiedCandidate};detectTraceLabelOverlap({traces:[candidateTrace],netLabels:this.input.netLabelPlacements}).length<initialRerouteOverlapCount&&Math.abs(getPathLength4(simplifiedCandidate)-getPathLength4(reroutedPath))<PATH_LENGTH_EPSILON2&&simplifiedCandidate.length<reroutedPath.length&&preservesLabelAnchors(this.input.netLabelPlacements,[completedReroute.initialTrace],[candidateTrace])&&candidateByPath.set(simplifiedCandidate.map(point6=>`${point6.x},${point6.y}`).join(";"),simplifiedCandidate)}}let initialOverlapIds=new Set(initialOverlaps.map(({label})=>`${label.globalConnNetId}:${label.netId}`)),initialPathLength=getPathLength4(tracePath),validCandidates=[...candidateByPath.values()].filter(candidatePath=>{let candidateTrace={...trace,tracePath:candidatePath},candidateOverlaps=detectTraceLabelOverlap({traces:[candidateTrace],netLabels:this.input.netLabelPlacements}),candidateOnlyKeepsExistingOverlaps=candidateOverlaps.every(({label})=>initialOverlapIds.has(`${label.globalConnNetId}:${label.netId}`)),reducesCollisions=candidateOverlaps.length<initialOverlaps.length,simplifiesGeometry=candidateOverlaps.length===initialOverlaps.length&&getPathLength4(candidatePath)<=initialPathLength+PATH_LENGTH_EPSILON2&&candidatePath.length<tracePath.length;return candidateOnlyKeepsExistingOverlaps&&(reducesCollisions||simplifiesGeometry)&&preservesLabelAnchors(this.input.netLabelPlacements,[trace],[candidateTrace])&&!isPathCollidingWithObstacles(candidatePath,this.obstacles)&&!doesPathCoincideWithTraces(candidatePath,otherNetTraces)}),getOverlapCount=candidatePath=>detectTraceLabelOverlap({traces:[{...trace,tracePath:candidatePath}],netLabels:this.input.netLabelPlacements}).length;validCandidates.sort((a6,b6)=>{let overlapDifference=getOverlapCount(a6)-getOverlapCount(b6);return overlapDifference!==0?overlapDifference:getPathLength4(a6)-getPathLength4(b6)||a6.length-b6.length});let bestCandidate=validCandidates[0];bestCandidate&&(this.outputTraces[traceIndex]={...trace,tracePath:bestCandidate},this.stats.simplifiedTraceCount=(this.stats.simplifiedTraceCount??0)+1)}getOutput(){return{traces:this.outputTraces,netLabelPlacements:this.input.netLabelPlacements}}visualize(){let graphics=visualizeInputProblem2(this.input.inputProblem);graphics.lines??(graphics.lines=[]);for(let trace of this.outputTraces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});return graphics}},getStubDirection=path=>{let[start,end]=path;return Math.abs(end.x-start.x)>=Math.abs(end.y-start.y)?end.x>=start.x?"x+":"x-":end.y>=start.y?"y+":"y-"},getStubLength=path=>{let[start,end]=path;return Math.abs(end.x-start.x)+Math.abs(end.y-start.y)},getLabelBounds2=placement=>{let isVertical52=placement.axis==="y",width=isVertical52?placement.height:placement.width,height=isVertical52?placement.width:placement.height;return{minX:placement.center.x-width/2,maxX:placement.center.x+width/2,minY:placement.center.y-height/2,maxY:placement.center.y+height/2}},getPathBounds=path=>({minX:Math.min(...path.map(point6=>point6.x)),maxX:Math.max(...path.map(point6=>point6.x)),minY:Math.min(...path.map(point6=>point6.y)),maxY:Math.max(...path.map(point6=>point6.y))}),doesPathIntersectBounds=(path,bounds)=>{for(let index=0;index<path.length-1;index++){let segmentBounds=getPathBounds([path[index],path[index+1]]);if(boundsOverlap(segmentBounds,bounds))return!0}return!1},resizeStub=(placement,direction2,targetLength)=>{let[start]=placement.stubTracePath,end=direction2==="x+"?{x:start.x+targetLength,y:start.y}:direction2==="x-"?{x:start.x-targetLength,y:start.y}:direction2==="y+"?{x:start.x,y:start.y+targetLength}:{x:start.x,y:start.y-targetLength},anchorPoint={x:(start.x+end.x)/2,y:(start.y+end.y)/2};return{...placement,stubTracePath:[start,end],anchorPoint,center:placement.center}},alignPortOnlyInlineNetLabelStubs=({placements,inputProblem,traces,netLabelPlacements})=>{let chipIdByPinId=new Map;for(let chip of inputProblem.chips)for(let pin of chip.pins)chipIdByPinId.set(pin.pinId,chip.chipId);let groups=new Map;for(let[placementIndex,placement]of placements.entries()){if(!placement.stubTracePath||placement.pinIds.length!==1)continue;let direction2=getStubDirection(placement.stubTracePath);if(!direction2)continue;let ownerChipId=chipIdByPinId.get(placement.pinIds[0]),groupKey=`${ownerChipId??placement.pinIds[0]}::${direction2}`,group=groups.get(groupKey)??[];group.push({placementIndex,placement,direction:direction2,ownerChipId}),groups.set(groupKey,group)}let alignedPlacements=[...placements],supersededGlobalNetIds=new Set(placements.map(placement=>placement.globalConnNetId)),retainedAnchoredLabelBounds=netLabelPlacements.filter(placement=>!supersededGlobalNetIds.has(placement.globalConnNetId)).map(getLabelBounds2);for(let group of groups.values()){if(group.length<2)continue;let targetLength=Math.max(...group.map(({placement})=>getStubLength(placement.stubTracePath))),proposals=group.map(({placement,direction:direction2})=>resizeStub(placement,direction2,targetLength)),groupPlacementIndices=new Set(group.map(({placementIndex})=>placementIndex)),fixedInlinePlacements=placements.filter((_6,placementIndex)=>!groupPlacementIndices.has(placementIndex));if(!proposals.some((proposal,proposalIndex)=>{let labelBounds=getLabelBounds2(proposal),stubPath=proposal.stubTracePath,stubBounds=getPathBounds(stubPath),ownerChipId=group[proposalIndex].ownerChipId;for(let chip of inputProblem.chips){let chipBounds={minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2};if(boundsOverlap(labelBounds,chipBounds)||chip.chipId!==ownerChipId&&boundsOverlap(stubBounds,chipBounds))return!0}for(let textBox of inputProblem.textBoxes??[]){let textBounds=getTextBoxBounds(textBox);if(boundsOverlap(labelBounds,textBounds)||boundsOverlap(stubBounds,textBounds))return!0}for(let trace of traces)if(trace.globalConnNetId!==proposal.globalConnNetId&&(doesPathIntersectBounds(trace.tracePath,labelBounds)||doesPathIntersectBounds(trace.tracePath,stubBounds)))return!0;if(retainedAnchoredLabelBounds.some(bounds=>boundsOverlap(labelBounds,bounds)||boundsOverlap(stubBounds,bounds)))return!0;for(let fixedPlacement of fixedInlinePlacements){let fixedLabelBounds=getLabelBounds2(fixedPlacement);if(boundsOverlap(labelBounds,fixedLabelBounds)||boundsOverlap(stubBounds,fixedLabelBounds)||fixedPlacement.stubTracePath&&(doesPathIntersectBounds(fixedPlacement.stubTracePath,labelBounds)||doesPathIntersectBounds(stubPath,fixedLabelBounds)))return!0}for(let[otherIndex,otherProposal]of proposals.entries()){if(otherIndex===proposalIndex)continue;let otherLabelBounds=getLabelBounds2(otherProposal);if(boundsOverlap(labelBounds,otherLabelBounds)||doesPathIntersectBounds(stubPath,otherLabelBounds))return!0}return!1}))for(let[groupIndex,{placementIndex}]of group.entries())alignedPlacements[placementIndex]=proposals[groupIndex]}return alignedPlacements},getAxisAlignedSegments=(path,epsilon=1e-6)=>{let segments=[],runStart=null,runAxis=null,runSign=0,closeRun=runEnd=>{if(runStart&&runAxis){let length4=Math.abs(runAxis==="x"?runEnd.x-runStart.x:runEnd.y-runStart.y);length4>epsilon&&segments.push({start:runStart,end:runEnd,axis:runAxis,length:length4})}runStart=null,runAxis=null,runSign=0};for(let i6=0;i6<path.length-1;i6++){let a6=path[i6],b6=path[i6+1],dx3=b6.x-a6.x,dy3=b6.y-a6.y;if(Math.abs(dx3)<=epsilon&&Math.abs(dy3)<=epsilon)continue;let axis=Math.abs(dy3)<=epsilon?"x":Math.abs(dx3)<=epsilon?"y":null;if(!axis){closeRun(a6);continue}let sign=Math.sign(axis==="x"?dx3:dy3);runStart&&runAxis===axis&&runSign===sign||(closeRun(a6),runStart=a6,runAxis=axis,runSign=sign)}return path.length>=2&&closeRun(path[path.length-1]),segments.sort((a6,b6)=>b6.length-a6.length)},LABEL_CLEARANCE2=.05,POINT_EPSILON=1e-6,CONTIGUOUS_LABEL_GAP=.01,MAX_OUTWARD_DISTANCE=5,getBounds32=placement=>{let renderedWidth=placement.axis==="y"?placement.height:placement.width,renderedHeight=placement.axis==="y"?placement.width:placement.height;return{minX:placement.center.x-renderedWidth/2,maxX:placement.center.x+renderedWidth/2,minY:placement.center.y-renderedHeight/2,maxY:placement.center.y+renderedHeight/2}},pointsEqual3=(a6,b6)=>Math.abs(a6.x-b6.x)<=POINT_EPSILON&&Math.abs(a6.y-b6.y)<=POINT_EPSILON,pathIntersectsBounds=(path,bounds)=>{for(let index=0;index<path.length-1;index++){let start=path[index],end=path[index+1],segmentBounds={minX:Math.min(start.x,end.x),maxX:Math.max(start.x,end.x),minY:Math.min(start.y,end.y),maxY:Math.max(start.y,end.y)};if(boundsOverlap(segmentBounds,bounds))return!0}return!1},isPointOnPath2=(point6,path)=>{for(let index=0;index<path.length-1;index++){let start=path[index],end=path[index+1],minX=Math.min(start.x,end.x)-POINT_EPSILON,maxX=Math.max(start.x,end.x)+POINT_EPSILON,minY=Math.min(start.y,end.y)-POINT_EPSILON,maxY=Math.max(start.y,end.y)+POINT_EPSILON,isHorizontal42=Math.abs(start.y-end.y)<=POINT_EPSILON,isVertical52=Math.abs(start.x-end.x)<=POINT_EPSILON;if((isHorizontal42&&Math.abs(point6.y-start.y)<=POINT_EPSILON||isVertical52&&Math.abs(point6.x-start.x)<=POINT_EPSILON)&&point6.x>=minX&&point6.x<=maxX&&point6.y>=minY&&point6.y<=maxY)return!0}return!1},getRequiredOutwardDistance=(label,inlineBounds)=>{let labelBounds=getBounds32(label);if(label.orientation==="x-"||label.orientation==="x+"){let nearby2=inlineBounds.filter(bounds=>labelBounds.minY<bounds.maxY&&labelBounds.maxY>bounds.minY);if(nearby2.length===0)return 0;if(label.orientation==="x-"){let targetMaxX=Math.min(...nearby2.map(bounds=>bounds.minX));return Math.max(0,labelBounds.maxX-targetMaxX+LABEL_CLEARANCE2)}let targetMinX=Math.max(...nearby2.map(bounds=>bounds.maxX));return Math.max(0,targetMinX-labelBounds.minX+LABEL_CLEARANCE2)}let nearby=inlineBounds.filter(bounds=>labelBounds.minX<bounds.maxX&&labelBounds.maxX>bounds.minX);if(nearby.length===0)return 0;if(label.orientation==="y-"){let targetMaxY=Math.min(...nearby.map(bounds=>bounds.minY));return Math.max(0,labelBounds.maxY-targetMaxY+LABEL_CLEARANCE2)}let targetMinY=Math.max(...nearby.map(bounds=>bounds.maxY));return Math.max(0,targetMinY-labelBounds.minY+LABEL_CLEARANCE2)},moveLabel=(label,orientation4,distance72)=>{let direction2=dir(orientation4);return{...label,anchorPoint:{x:label.anchorPoint.x+direction2.x*distance72,y:label.anchorPoint.y+direction2.y*distance72},center:{x:label.center.x+direction2.x*distance72,y:label.center.y+direction2.y*distance72}}},getDistanceToShoveBoundsPast=(obstacleBounds,movingBounds,orientation4)=>{switch(orientation4){case"x-":return obstacleBounds.maxX-movingBounds.minX+LABEL_CLEARANCE2;case"x+":return movingBounds.maxX-obstacleBounds.minX+LABEL_CLEARANCE2;case"y-":return obstacleBounds.maxY-movingBounds.minY+LABEL_CLEARANCE2;case"y+":return movingBounds.maxY-obstacleBounds.minY+LABEL_CLEARANCE2}},boundsGapOnPerpendicularAxis=(a6,b6,orientation4)=>orientation4==="x-"||orientation4==="x+"?Math.max(0,a6.minY-b6.maxY,b6.minY-a6.maxY):Math.max(0,a6.minX-b6.maxX,b6.minX-a6.maxX),sharesOwnerChip=(label,ownerChipIds,chipIdByPinId)=>label.pinIds.some(pinId=>ownerChipIds.has(chipIdByPinId.get(pinId)??"")),isGeneratedLabelConnector=trace=>trace.mspPairId.startsWith("available-net-orientation-")||trace.mspPairId.startsWith("inline-net-label-clearance-"),findConnectorTraceIndex=(label,traces)=>traces.findIndex(trace=>{if(trace.globalConnNetId!==label.globalConnNetId||!isGeneratedLabelConnector(trace))return!1;let first=trace.tracePath[0],last=trace.tracePath.at(-1);return!!(first&&pointsEqual3(first,label.anchorPoint)||last&&pointsEqual3(last,label.anchorPoint))}),canAddConnectorAtAnchor=(label,traces,pinMap)=>label.pinIds.some(pinId=>{let pin=pinMap[pinId];return pin&&pointsEqual3(pin,label.anchorPoint)})?!0:traces.some(trace=>trace.globalConnNetId===label.globalConnNetId&&isPointOnPath2(label.anchorPoint,trace.tracePath)),moveConnectorEndpoint=(trace,oldAnchor,newAnchor)=>{let tracePath=trace.tracePath.map(point6=>({...point6}));return pointsEqual3(tracePath[0],oldAnchor)&&(tracePath[0]=newAnchor),pointsEqual3(tracePath.at(-1),oldAnchor)&&(tracePath[tracePath.length-1]=newAnchor),{...trace,tracePath}},createConnectorTrace=({label,labelIndex,newAnchor,pinMap})=>{let mspPairId=`inline-net-label-clearance-${labelIndex}-${label.netId??label.globalConnNetId}`;return{mspPairId,dcConnNetId:label.dcConnNetId??label.globalConnNetId,globalConnNetId:label.globalConnNetId,userNetId:label.netId,pins:getTracePins(label,pinMap),tracePath:[label.anchorPoint,newAnchor],mspConnectionPairIds:[mspPairId],pinIds:label.pinIds}},getContiguousLabelGroup=({triggerIndex,labels,chipIdByPinId})=>{let trigger=labels[triggerIndex],ownerChipIds=new Set(trigger.pinIds.flatMap(pinId=>{let chipId=chipIdByPinId.get(pinId);return chipId?[chipId]:[]})),candidates=labels.map((label,labelIndex)=>({label,labelIndex})).filter(({label})=>label.orientation===trigger.orientation&&label.mspConnectionPairIds.length===0&&sharesOwnerChip(label,ownerChipIds,chipIdByPinId)),group=new Set([triggerIndex]),changed=!0;for(;changed;){changed=!1;for(let{label,labelIndex}of candidates)group.has(labelIndex)||[...group].some(memberIndex=>boundsGapOnPerpendicularAxis(getBounds32(labels[memberIndex]),getBounds32(label),trigger.orientation)<=CONTIGUOUS_LABEL_GAP)&&(group.add(labelIndex),changed=!0)}return{group,ownerChipIds}},pushAnchoredNetLabelsAwayFromInlineLabels=({inputProblem,traces,netLabelPlacements,inlineNetLabelPlacements})=>{let outputTraces=traces.map(trace=>({...trace,tracePath:trace.tracePath.map(point6=>({...point6}))})),outputLabels=netLabelPlacements.map(label=>({...label})),inlineBounds=inlineNetLabelPlacements.map(getBounds32),pinMap=getPinMap(inputProblem),chipIdByPinId=new Map;for(let chip of inputProblem.chips)for(let pin of chip.pins)chipIdByPinId.set(pin.pinId,chip.chipId);let movedLabelIndices=new Set;for(let triggerIndex=0;triggerIndex<outputLabels.length;triggerIndex++){let trigger=outputLabels[triggerIndex],distance72=getRequiredOutwardDistance(trigger,inlineBounds);if(distance72<=POINT_EPSILON||distance72>MAX_OUTWARD_DISTANCE)continue;let{group,ownerChipIds}=getContiguousLabelGroup({triggerIndex,labels:outputLabels,chipIdByPinId}),distances=new Map([...group].map(labelIndex=>[labelIndex,distance72])),failed=!1;for(let iteration=0;iteration<outputLabels.length;iteration++){let adjustedObstacle=!1;for(let[movingIndex,movingDistance]of distances){let movingBounds=getBounds32(moveLabel(outputLabels[movingIndex],trigger.orientation,movingDistance));for(let obstacleIndex=0;obstacleIndex<outputLabels.length;obstacleIndex++){if(group.has(obstacleIndex))continue;let obstacle=outputLabels[obstacleIndex],existingObstacleDistance=distances.get(obstacleIndex)??0,obstacleBounds=getBounds32(moveLabel(obstacle,trigger.orientation,existingObstacleDistance));if(!boundsOverlap(movingBounds,obstacleBounds))continue;if(!sharesOwnerChip(obstacle,ownerChipIds,chipIdByPinId)||findConnectorTraceIndex(obstacle,outputTraces)===-1&&!canAddConnectorAtAnchor(obstacle,outputTraces,pinMap)){failed=!0;break}let shoveDistance=getDistanceToShoveBoundsPast(getBounds32(obstacle),movingBounds,trigger.orientation);if(shoveDistance>MAX_OUTWARD_DISTANCE||shoveDistance<=existingObstacleDistance+POINT_EPSILON){failed=!0;break}distances.set(obstacleIndex,shoveDistance),adjustedObstacle=!0}if(failed)break}if(failed||!adjustedObstacle)break}if(failed)continue;let proposals=new Map;for(let[labelIndex,labelDistance]of distances)proposals.set(labelIndex,moveLabel(outputLabels[labelIndex],trigger.orientation,labelDistance));let finalLabelAt=labelIndex=>proposals.get(labelIndex)??outputLabels[labelIndex];for(let[labelIndex,movedLabel]of proposals){let movedBounds=getBounds32(movedLabel);if(inlineBounds.some(bounds=>boundsOverlap(movedBounds,bounds))){failed=!0;break}if(inputProblem.chips.some(chip=>boundsOverlap(movedBounds,{minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2}))||(inputProblem.textBoxes??[]).some(textBox=>boundsOverlap(movedBounds,getTextBoxBounds(textBox)))){failed=!0;break}if(outputLabels.some((_6,otherIndex)=>otherIndex!==labelIndex&&boundsOverlap(movedBounds,getBounds32(finalLabelAt(otherIndex))))){failed=!0;break}if(outputTraces.some(trace=>trace.globalConnNetId!==movedLabel.globalConnNetId&&pathIntersectsBounds(trace.tracePath,movedBounds))){failed=!0;break}}if(failed)continue;let connectorUpdates=[];for(let[labelIndex,movedLabel]of proposals){let label=outputLabels[labelIndex],connectorIndex=findConnectorTraceIndex(label,outputTraces);if(connectorIndex===-1&&!canAddConnectorAtAnchor(label,outputTraces,pinMap)){failed=!0;break}let connector=connectorIndex===-1?createConnectorTrace({label,labelIndex,newAnchor:movedLabel.anchorPoint,pinMap}):moveConnectorEndpoint(outputTraces[connectorIndex],label.anchorPoint,movedLabel.anchorPoint);if(inlineBounds.some(bounds=>pathIntersectsBounds(connector.tracePath,bounds))||inputProblem.chips.some(chip=>pathIntersectsBounds(connector.tracePath,{minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2}))||(inputProblem.textBoxes??[]).some(textBox=>pathIntersectsBounds(connector.tracePath,getTextBoxBounds(textBox)))||outputLabels.some((_6,otherIndex)=>otherIndex!==labelIndex&&pathIntersectsBounds(connector.tracePath,getBounds32(finalLabelAt(otherIndex))))){failed=!0;break}connectorUpdates.push({labelIndex,connectorIndex,trace:connector})}if(!failed){for(let[labelIndex,movedLabel]of proposals)outputLabels[labelIndex]=movedLabel,movedLabelIndices.add(labelIndex);for(let update of connectorUpdates)update.connectorIndex===-1?outputTraces.push(update.trace):outputTraces[update.connectorIndex]=update.trace}}return{traces:outputTraces,netLabelPlacements:outputLabels,movedLabelCount:movedLabelIndices.size}},DEFAULT_INLINE_NET_LABEL_HEIGHT=.18,INLINE_NET_LABEL_TRACE_MARGIN=.05,INLINE_NET_LABEL_STUB_TRACE_CLEARANCE=.05,INLINE_NET_LABEL_MAX_SPAN_JOG=.4,getPinPairKey2=pinIds=>[...pinIds].sort().join("::"),InlineNetLabelSolver=class extends BaseSolver5{constructor(input2){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"inputNetLabelPlacements");__publicField(this,"inlineNetLabelPlacements",[]);__publicField(this,"queuedConnections");__publicField(this,"tracesByPinPairKey");__publicField(this,"hasAlignedPortOnlyStubs",!1);__publicField(this,"postProcessedOutput");this.inputProblem=input2.inputProblem,this.traces=input2.traces,this.inputNetLabelPlacements=input2.netLabelPlacements,this.queuedConnections=[...this.inputProblem.directConnections.filter(connection=>connection.allowInlineNetLabel&&connection.netId),...this.inputProblem.netConnections.filter(connection=>connection.allowInlineNetLabel&&connection.pinIds.length>=1&&connection.pinIds.length<=2&&connection.netId)],this.tracesByPinPairKey=new Map;for(let trace of this.traces){let key=getPinPairKey2(trace.pins.map(p3=>p3.pinId)),existing=this.tracesByPinPairKey.get(key);existing?existing.push(trace):this.tracesByPinPairKey.set(key,[trace])}}getConstructorParams(){return[{inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.inputNetLabelPlacements}]}_step(){let connection=this.queuedConnections.shift();if(connection){if((connection.pinIds.length===2?this.tracesByPinPairKey.get(getPinPairKey2(connection.pinIds))??[]:[]).length>0){let placement=this.computeInlinePlacement(connection);placement&&this.inlineNetLabelPlacements.push(placement)}else{let terminalPlacements=connection.pinIds.map(pinId=>this.computeTerminalInlinePlacement(connection,pinId));terminalPlacements.every(placement=>placement!==null)&&this.inlineNetLabelPlacements.push(...terminalPlacements)}return}if(!this.hasAlignedPortOnlyStubs){this.inlineNetLabelPlacements=alignPortOnlyInlineNetLabelStubs({placements:this.inlineNetLabelPlacements,inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.inputNetLabelPlacements}),this.hasAlignedPortOnlyStubs=!0;return}if(!this.postProcessedOutput){this.postProcessedOutput=this.buildPostProcessedOutput();return}this.solved=!0,this.stats.inlineNetLabelCount=this.inlineNetLabelPlacements.length}computeTerminalInlinePlacement(connection,pinId){if(!connection.netId)return null;let anchoredPlacement=this.inputNetLabelPlacements.find(placement=>placement.netId===connection.netId&&placement.pinIds.length===1&&placement.pinIds[0]===pinId);if(!anchoredPlacement)return null;let inputChip=this.inputProblem.chips.find(chip=>chip.pins.some(pin=>pin.pinId===pinId)),inputPin=inputChip?.pins.find(pin=>pin.pinId===pinId),height=connection.inlineNetLabelHeight??DEFAULT_INLINE_NET_LABEL_HEIGHT,netLabelText=connection.netLabelText?.trim()||void 0,width=connection.inlineNetLabelWidth??connection.netLabelWidth??estimateInlineNetLabelWidth(netLabelText??connection.netId,height),stubLength=Math.max(width+.2,.6),start=inputPin?{x:inputPin.x,y:inputPin.y}:anchoredPlacement.anchorPoint,direction2=inputPin&&inputChip?inputPin._facingDirection??getPinDirection(inputPin,inputChip):anchoredPlacement.orientation,intendedEnd=direction2==="x+"?{x:start.x+stubLength,y:start.y}:direction2==="x-"?{x:start.x-stubLength,y:start.y}:direction2==="y+"?{x:start.x,y:start.y+stubLength}:{x:start.x,y:start.y-stubLength},end=getCollisionLimitedTerminalStubEnd({start,intendedEnd,minimumLength:width+2*INLINE_NET_LABEL_TRACE_MARGIN,traces:this.traces,ownGlobalConnNetId:anchoredPlacement.globalConnNetId});if(!end)return null;let axis=direction2==="x+"||direction2==="x-"?"x":"y",side=axis==="x"?"y+":"x-",anchorPoint={x:(start.x+end.x)/2,y:(start.y+end.y)/2},offset=height/2+INLINE_NET_LABEL_TRACE_MARGIN,center2=side==="y+"?{x:anchorPoint.x,y:anchorPoint.y+offset}:{x:anchorPoint.x-offset,y:anchorPoint.y},halfAlong=width/2,halfAcross=height/2,bounds=axis==="x"?{minX:center2.x-halfAlong,maxX:center2.x+halfAlong,minY:center2.y-halfAcross,maxY:center2.y+halfAcross}:{minX:center2.x-halfAcross,maxX:center2.x+halfAcross,minY:center2.y-halfAlong,maxY:center2.y+halfAlong};return this.isObstructed(bounds,{ownGlobalConnNetId:anchoredPlacement.globalConnNetId})?null:{globalConnNetId:anchoredPlacement.globalConnNetId,netId:connection.netId,netLabelText,pinIds:[pinId],stubTracePath:[start,end],axis,anchorPoint,center:center2,width,height,side}}computeInlinePlacement(connection){let traces=this.tracesByPinPairKey.get(getPinPairKey2(connection.pinIds))??[];if(traces.length===0)return null;let trace=traces[0],segments=getAxisAlignedSegments(trace.tracePath);if(segments.length===0)return null;let height=connection.inlineNetLabelHeight??DEFAULT_INLINE_NET_LABEL_HEIGHT,netLabelText=connection.netLabelText?.trim()||void 0,width=connection.inlineNetLabelWidth??connection.netLabelWidth??estimateInlineNetLabelWidth(netLabelText??connection.netId,height),offset=height/2+INLINE_NET_LABEL_TRACE_MARGIN,usableSegments=segments.filter(segment2=>segment2.length>=width).sort((a6,b6)=>b6.length-a6.length);for(let segment2 of usableSegments){let sides=segment2.axis==="x"?["y+","y-"]:["x-","x+"];for(let side of sides)for(let anchorPoint of getAnchorCandidates(segment2,width)){let center2=side==="y+"?{x:anchorPoint.x,y:anchorPoint.y+offset}:side==="y-"?{x:anchorPoint.x,y:anchorPoint.y-offset}:side==="x-"?{x:anchorPoint.x-offset,y:anchorPoint.y}:{x:anchorPoint.x+offset,y:anchorPoint.y},halfAlong=width/2,halfAcross=height/2,bounds=segment2.axis==="x"?{minX:center2.x-halfAlong,maxX:center2.x+halfAlong,minY:center2.y-halfAcross,maxY:center2.y+halfAcross}:{minX:center2.x-halfAcross,maxX:center2.x+halfAcross,minY:center2.y-halfAlong,maxY:center2.y+halfAlong};if(!this.isObstructed(bounds,{ownTrace:trace,ownGlobalConnNetId:trace.globalConnNetId}))return{globalConnNetId:trace.globalConnNetId,netId:connection.netId,netLabelText,mspPairId:trace.mspPairId,pinIds:[...connection.pinIds],axis:segment2.axis,anchorPoint,center:center2,width,height,side}}}let spanPlacement=this.computeSpanPlacement({trace,connection,netLabelText,width,height,offset});return spanPlacement||null}computeSpanPlacement({trace,connection,netLabelText,width,height,offset}){let path=trace.tracePath;if(path.length<2)return null;let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of path)minX=Math.min(minX,point6.x),maxX=Math.max(maxX,point6.x),minY=Math.min(minY,point6.y),maxY=Math.max(maxY,point6.y);let extentX=maxX-minX,extentY=maxY-minY,axis=extentX>=extentY?"x":"y",spanLength=axis==="x"?extentX:extentY;if((axis==="x"?extentY:extentX)>INLINE_NET_LABEL_MAX_SPAN_JOG||spanLength<width)return null;let mid=((axis==="x"?minX:minY)+(axis==="x"?maxX:maxY))/2,halfRange=(spanLength-width)/2,offsets=[0];for(let value=.1;value<=halfRange+1e-9;value+=.1)offsets.push(value,-value);offsets.push(halfRange,-halfRange);let sides=axis==="x"?["y+","y-"]:["x-","x+"];for(let side of sides)for(let alongOffset of offsets){let along=mid+alongOffset,center2=side==="y+"?{x:along,y:maxY+offset}:side==="y-"?{x:along,y:minY-offset}:side==="x-"?{x:minX-offset,y:along}:{x:maxX+offset,y:along},halfAlong=width/2,halfAcross=height/2,bounds=axis==="x"?{minX:center2.x-halfAlong,maxX:center2.x+halfAlong,minY:center2.y-halfAcross,maxY:center2.y+halfAcross}:{minX:center2.x-halfAcross,maxX:center2.x+halfAcross,minY:center2.y-halfAlong,maxY:center2.y+halfAlong};if(this.isObstructed(bounds,{ownTrace:trace,ownGlobalConnNetId:trace.globalConnNetId}))continue;let anchorPoint=axis==="x"?{x:along,y:side==="y+"?maxY:minY}:{x:side==="x-"?minX:maxX,y:along};return{globalConnNetId:trace.globalConnNetId,netId:connection.netId,netLabelText,mspPairId:trace.mspPairId,pinIds:[...connection.pinIds],axis,anchorPoint,center:center2,width,height,side}}return null}isObstructed(bounds,{ownTrace,ownGlobalConnNetId}){for(let chip of this.inputProblem.chips){let chipBounds={minX:chip.center.x-chip.width/2,maxX:chip.center.x+chip.width/2,minY:chip.center.y-chip.height/2,maxY:chip.center.y+chip.height/2};if(boundsOverlap(bounds,chipBounds))return!0}for(let textBox of this.inputProblem.textBoxes??[])if(boundsOverlap(bounds,getTextBoxBounds(textBox)))return!0;for(let trace of this.traces)if(!(ownTrace&&trace.mspPairId===ownTrace.mspPairId)&&trace.globalConnNetId!==ownGlobalConnNetId&&doesPathIntersectBounds2(trace.tracePath,bounds))return!0;return!1}getSupersededNetLabelKeys(){let keys=new Set;for(let placement of this.inlineNetLabelPlacements)keys.add(placement.globalConnNetId);return keys}getOutputTraces(supersededNetLabelKeys){return this.traces.filter(trace=>!(supersededNetLabelKeys.has(trace.globalConnNetId)&&trace.mspPairId.startsWith("available-net-orientation-")))}buildPostProcessedOutput(){let superseded=this.getSupersededNetLabelKeys(),retainedNetLabelPlacements=this.inputNetLabelPlacements.filter(placement=>!superseded.has(placement.globalConnNetId)),outputTraces=this.getOutputTraces(superseded),pushed=pushAnchoredNetLabelsAwayFromInlineLabels({inputProblem:this.inputProblem,traces:outputTraces,netLabelPlacements:retainedNetLabelPlacements,inlineNetLabelPlacements:this.inlineNetLabelPlacements});return this.stats.pushedAnchoredNetLabelCount=pushed.movedLabelCount,{traces:pushed.traces,netLabelPlacements:pushed.netLabelPlacements,inlineNetLabelPlacements:this.inlineNetLabelPlacements}}getOutput(){return this.postProcessedOutput?this.postProcessedOutput:this.buildPostProcessedOutput()}visualize(){return visualizeInlineNetLabelOutput({inputProblem:this.inputProblem,...this.getOutput()})}},visualizeInlineNetLabelOutput=({inputProblem,traces,netLabelPlacements,inlineNetLabelPlacements})=>{let graphics=visualizeInputProblem2(inputProblem);graphics.lines??(graphics.lines=[]),graphics.rects??(graphics.rects=[]),graphics.points??(graphics.points=[]),graphics.texts??(graphics.texts=[]);for(let trace of traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let label of netLabelPlacements)graphics.rects.push({center:label.center,width:label.width,height:label.height,fill:getColorFromString2(label.globalConnNetId,.35),strokeColor:getColorFromString2(label.globalConnNetId,.9),label:`netId: ${label.netId}
690
690
  globalConnNetId: ${label.globalConnNetId}`}),graphics.points.push({x:label.anchorPoint.x,y:label.anchorPoint.y,color:getColorFromString2(label.globalConnNetId,.9),label:`anchorPoint
691
691
  orientation: ${label.orientation}`});for(let inlineLabel of inlineNetLabelPlacements){inlineLabel.stubTracePath&&graphics.lines.push({points:inlineLabel.stubTracePath,strokeColor:"purple"});let isHorizontal42=inlineLabel.axis==="x",renderedWidth=inlineLabel.width,renderedHeight=inlineLabel.height;isHorizontal42||(renderedWidth=inlineLabel.height,renderedHeight=inlineLabel.width),graphics.rects.push({center:inlineLabel.center,width:renderedWidth,height:renderedHeight,fill:getColorFromString2(inlineLabel.globalConnNetId,.35),strokeColor:"green",label:[`INLINE netId: ${inlineLabel.netId}`,`axis: ${inlineLabel.axis}`,`side: ${inlineLabel.side}`].join(`
692
692
  `)});let textX=inlineLabel.center.x,textY=inlineLabel.center.y,anchorSide="center",rotation5;if(inlineLabel.stubTracePath){let stubStart=inlineLabel.stubTracePath[0],stubEnd=inlineLabel.stubTracePath[1],labelOffset=inlineLabel.width/2;stubEnd[inlineLabel.axis]>stubStart[inlineLabel.axis]?(labelOffset=-inlineLabel.width/2,anchorSide="center_left"):anchorSide="center_right",inlineLabel.axis==="x"?textX+=labelOffset:textY+=labelOffset}inlineLabel.axis==="y"&&(rotation5=90),graphics.texts.push({x:textX,y:textY,text:inlineLabel.netLabelText??inlineLabel.netId??"",color:"green",fontSize:inlineLabel.height,anchorSide,rotation:rotation5}),graphics.points.push({x:inlineLabel.anchorPoint.x,y:inlineLabel.anchorPoint.y,color:"green",label:`inline anchor
@@ -738,7 +738,7 @@ ${rootLabel}`:layerName).join(`
738
738
  `)}};function visualizeSimpleRouteJson(srj){let layerNames=getCopperLayerNames(srj.layerCount),hasArbitraryCopperLayer=(srj.traces??[]).some(trace=>trace.route.some((routePoint,routePointIndex)=>{let nextRoutePoint=trace.route[routePointIndex+1];return routePoint.route_type==="wire"&&nextRoutePoint?.route_type==="wire"&&nextRoutePoint.layer===routePoint.layer&&!LEGACY_VISUALIZATION_LAYERS.has(routePoint.layer)})),connectionNames=new Set(srj.connections.map(({name})=>name)),traceOnlyConnections=hasArbitraryCopperLayer?[...new Set((srj.traces??[]).map(({connection_name})=>connection_name).filter(connectionName=>connectionName&&!connectionNames.has(connectionName)))].map(name=>({name,pointsToConnect:[]})):[],visualizedConnections=[...srj.connections,...traceOnlyConnections],colorMap2=getColorMap(visualizedConnections),formatObstacleLabel=createObstacleLabelFormatter({...srj,connections:visualizedConnections}),lines=[],circles=[],rects=[],points=[];for(let connection of visualizedConnections)for(let point6 of connection.pointsToConnect){let pointLayers=getPointLayers4(point6),rootNames=connection.__rootConnectionNames??[connection.name];points.push({x:point6.x,y:point6.y,color:colorMap2[connection.name],layer:getGraphicsLayer(layerNames,pointLayers),label:[connection.name,rootNames.join(", "),pointLayers.join(",")].join(`
739
739
  `)})}for(let trace of srj.traces??[]){let jumpers=trace.route.filter(routePoint=>routePoint.route_type==="jumper"),isWireSegmentInsideJumper=(start,end)=>jumpers.some(jumper=>Math.abs(start.x-jumper.start.x)<.01&&Math.abs(start.y-jumper.start.y)<.01&&Math.abs(end.x-jumper.end.x)<.01&&Math.abs(end.y-jumper.end.y)<.01||Math.abs(start.x-jumper.end.x)<.01&&Math.abs(start.y-jumper.end.y)<.01&&Math.abs(end.x-jumper.start.x)<.01&&Math.abs(end.y-jumper.start.y)<.01);for(let routePoint of trace.route)if(routePoint.route_type==="via"){let viaLayers=getViaLayerNames(layerNames,routePoint.from_layer,routePoint.to_layer);circles.push({center:{x:routePoint.x,y:routePoint.y},radius:(routePoint.via_diameter??getViaPadDiameter(srj))/2,fill:hasArbitraryCopperLayer?colorMap2[trace.connection_name]:"blue",stroke:"none",layer:getGraphicsLayer(layerNames,viaLayers)})}else routePoint.route_type==="through_obstacle"&&lines.push({points:[routePoint.start,routePoint.end],strokeColor:transparentize(colorMap2[trace.connection_name]??"purple",.35),strokeWidth:routePoint.width,strokeDash:[.1,.1],layer:getGraphicsLayer(layerNames,[routePoint.from_layer,routePoint.to_layer]),label:`${trace.connection_name} through_obstacle`});for(let routePointIndex=0;routePointIndex<trace.route.length-1;routePointIndex++){let routePoint=trace.route[routePointIndex],nextRoutePoint=trace.route[routePointIndex+1];if(routePoint.route_type==="jumper"){let color=colorMap2[trace.connection_name]??"rgba(255, 165, 0, 0.8)",dimensions=JUMPER_DIMENSIONS[routePoint.footprint==="1206x4_pair"?"1206x4_pair":"0603"],horizontal=Math.abs(routePoint.end.x-routePoint.start.x)>Math.abs(routePoint.end.y-routePoint.start.y),padWidth=horizontal?dimensions.padLength:dimensions.padWidth,padHeight=horizontal?dimensions.padWidth:dimensions.padLength,layer=getGraphicsLayer(layerNames,[routePoint.layer]);for(let center2 of[routePoint.start,routePoint.end])rects.push({center:center2,width:padWidth,height:padHeight,fill:transparentize(color,.5),stroke:"rgba(0, 0, 0, 0.5)",layer});lines.push({points:[routePoint.start,routePoint.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:dimensions.padWidth*.3,layer})}else if(routePoint.route_type==="wire"&&nextRoutePoint.route_type==="wire"&&nextRoutePoint.layer===routePoint.layer&&!isWireSegmentInsideJumper(routePoint,nextRoutePoint)){let layerIndex=getLayerIndex2(layerNames,routePoint.layer);lines.push({points:[{x:routePoint.x,y:routePoint.y},{x:nextRoutePoint.x,y:nextRoutePoint.y}],layer:`z${layerIndex}`,strokeWidth:routePoint.width,strokeColor:getCopperLayerColor(layerIndex),...hasArbitraryCopperLayer?{label:trace.connection_name}:{}})}}}for(let obstacle of srj.obstacles){if(obstacle.isCopperPour)continue;let layerIndexes=getObstacleLayerIndexes(obstacle,layerNames);if(layerIndexes.length===0)throw new Error(`FanoutSolver: cannot visualize obstacle "${obstacle.obstacleId??"unknown"}" without a valid layer`);let onlyLayerName=layerIndexes.length===1?layerNames[layerIndexes[0]]:void 0,fill=transparentize(onlyLayerName==="bottom"?"blue":"red",.5**layerIndexes.length),shape=obstacle.shape,common={center:obstacle.center,fill,layer:`z${layerIndexes.join(",")}`,label:formatObstacleLabel(obstacle)};shape==="circle"?circles.push({...common,radius:Math.min(obstacle.width,obstacle.height)/2}):rects.push({...common,width:obstacle.width,height:obstacle.height,ccwRotationDegrees:obstacle.ccwRotationDegrees})}for(let jumper of srj.jumpers??[])for(let pad2 of jumper.pads)rects.push({center:pad2.center,width:pad2.width,height:pad2.height,ccwRotationDegrees:pad2.ccwRotationDegrees,fill:"rgba(255, 165, 0, 0.3)",stroke:"rgba(255, 165, 0, 0.8)",layer:getGraphicsLayer(layerNames,pad2.layers)});return{rects,circles,lines,points}}function resolvePositiveNumber(label,value){if(!Number.isFinite(value)||value<=0)throw new Error(`FanoutSolver: ${label} must be a positive number, received ${value}`);return value}function resolveConfig(srj,options){let traceWidth=resolvePositiveNumber("traceWidth",options.traceWidth??srj.nominalTraceWidth??srj.minTraceWidth),viaDiameter=resolvePositiveNumber("viaDiameter",options.viaDiameter??srj.minViaPadDiameter??srj.min_via_pad_diameter??srj.minViaDiameter??Math.max(traceWidth*2,.3)),viaHoleDiameter=resolvePositiveNumber("viaHoleDiameter",options.viaHoleDiameter??srj.minViaHoleDiameter??srj.min_via_hole_diameter??viaDiameter*.5);if(viaHoleDiameter>=viaDiameter)throw new Error(`FanoutSolver: viaHoleDiameter ${viaHoleDiameter} must be smaller than viaDiameter ${viaDiameter}`);let clearance=resolvePositiveNumber("clearance",options.clearance??srj.minViaEdgeToPadEdgeClearance??srj.minTraceToPadEdgeClearance??srj.defaultObstacleMargin??srj.minTraceWidth),layerNames=getCopperLayerNames(srj.layerCount),escapeLayers=options.escapeLayers??layerNames;for(let layer of escapeLayers)if(!layerNames.includes(layer))throw new Error(`FanoutSolver: escape layer "${layer}" is not available in a ${srj.layerCount}-layer SimpleRouteJson`);if(new Set(escapeLayers).size!==escapeLayers.length)throw new Error("FanoutSolver: escapeLayers contains duplicates");let borderDistribution=options.borderDistribution??"preserve";if(borderDistribution!=="preserve"&&borderDistribution!=="even")throw new Error(`FanoutSolver: borderDistribution must be "preserve" or "even", received "${borderDistribution}"`);return{traceWidth,viaDiameter,viaHoleDiameter,clearance,compactBusTracks:options.compactBusTracks??!1,allowSameNetMerges:options.allowSameNetMerges??!1,singleLayerPushAndShove:options.singleLayerPushAndShove??!1,singleLayerAdaptiveExits:options.singleLayerAdaptiveExits??!1,borderDistribution,layerNames,escapeLayers,maxLayerCombinations:options.maxLayerCombinations===void 0?256:resolvePositiveNumber("maxLayerCombinations",options.maxLayerCombinations),balanceLayerLoadByConnectionCount:options.balanceLayerLoadByConnectionCount??!1}}function validateCornerBandCapacities(buses,config){let checkedBands=new Set,exitPitch=Math.max(config.traceWidth+config.clearance,config.viaDiameter+config.clearance),endInset=Math.max(config.viaDiameter/2+config.clearance,exitPitch);for(let bus of buses){let side=getCornerBandSide(bus.exitEdge,bus.preferredExit);if(!bus.exitEdge||!side)continue;let bandKey=`${bus.exitEdge}:${side}`;if(checkedBands.has(bandKey))continue;checkedBands.add(bandKey);let edgeLength=bus.exitEdge==="left"||bus.exitEdge==="right"?bus.sharedBoundary.maxY-bus.sharedBoundary.minY:bus.sharedBoundary.maxX-bus.sharedBoundary.minX,connectionCount=bus.cornerBandConnectionCount??bus.connections.length,halfTrackSpan=(connectionCount-1)*exitPitch/2,availableHalfTrackSpan=edgeLength/4-endInset;if(halfTrackSpan>availableHalfTrackSpan+1e-6)throw new Error(`FanoutSolver: ${side} band on the ${bus.exitEdge} edge cannot fit ${connectionCount} via-safe exits`)}}function assignmentLoadPenalty(assignment,buses,weightByConnectionCount){let connectionCountByBusId=new Map(buses.map(bus=>[bus.busId,bus.connections.length])),loadByLayer=new Map;for(let[busId,layer]of Object.entries(assignment))loadByLayer.set(layer,(loadByLayer.get(layer)??0)+(weightByConnectionCount?connectionCountByBusId.get(busId)??1:1));return[...loadByLayer.values()].reduce((penalty,load)=>penalty+load*load,0)}function getLayerLoadPenaltyWeight(config){return config.balanceLayerLoadByConnectionCount?.25:.01}function getPlanViaCount(plans){return plans.reduce((count,plan)=>count+ +!!plan.via+(plan.additionalVias?.length??0)+ +!!plan.planeEndpointVia,0)}function getBusDistanceToBoundary(bus){let averageSource=bus.connections.reduce((sum,connection)=>{let sourceAxis=bus.direction==="left"||bus.direction==="right"?connection.sourcePoint.x:connection.sourcePoint.y;return sum+sourceAxis},0)/bus.connections.length;switch(bus.direction){case"right":return bus.sharedBoundary.maxX-averageSource;case"left":return averageSource-bus.sharedBoundary.minX;case"up":return bus.sharedBoundary.maxY-averageSource;case"down":return averageSource-bus.sharedBoundary.minY}}function busUsesDestinationGuidedTracks(bus){let isHorizontal32=bus.direction==="left"||bus.direction==="right";return bus.connections.some(connection=>{let exitTargetPoint=connection.exitTargetPoint??connection.targetPoint,sourceTrack=isHorizontal32?connection.sourcePoint.y:connection.sourcePoint.x,targetTrack=isHorizontal32?exitTargetPoint.y:exitTargetPoint.x;return Math.abs(sourceTrack-targetTrack)>1e-6})}function getCommonExplicitExitTargetLayer(bus){if(bus.connections.length===0||bus.connections.some(connection=>!connection.hasExplicitLayeredExitTarget||!connection.exitTargetPoint?.layer))return;let targetLayers=new Set(bus.connections.map(connection=>connection.exitTargetPoint.layer));if(targetLayers.size!==1)return;let[targetLayer]=targetLayers;return targetLayer}function busIsOnOutwardComponentEdge2(bus){let isHorizontal32=bus.direction==="left"||bus.direction==="right",directionalCoordinates=isHorizontal32?bus.xCoordinates:bus.yCoordinates,averageSource=bus.connections.reduce((sum,connection)=>sum+(isHorizontal32?connection.sourcePoint.x:connection.sourcePoint.y),0)/bus.connections.length,outwardCoordinate=bus.direction==="right"||bus.direction==="up"?Math.max(...directionalCoordinates):Math.min(...directionalCoordinates);return Math.abs(averageSource-outwardCoordinate)<1e-6}function getBusDepthInRows(bus){let isHorizontal32=bus.direction==="left"||bus.direction==="right",directionalCoordinates=isHorizontal32?bus.xCoordinates:bus.yCoordinates,averageSource=bus.connections.reduce((sum,connection)=>sum+(isHorizontal32?connection.sourcePoint.x:connection.sourcePoint.y),0)/bus.connections.length,outwardCoordinate=bus.direction==="right"||bus.direction==="up"?Math.max(...directionalCoordinates):Math.min(...directionalCoordinates),directionalPitch=isHorizontal32?bus.pitchX:bus.pitchY;return Math.round(Math.abs(averageSource-outwardCoordinate)/directionalPitch)}function createInitialLayerAssignment(params){let{buses,escapeLayers,escapeLayersByBusId}=params,assignment={},directionsByComponent=new Map,nextViaLayerIndex=0;for(let bus of buses){let directions=directionsByComponent.get(bus.componentId)??new Set;directions.add(bus.direction),directionsByComponent.set(bus.componentId,directions)}for(let bus of buses){let sourceLayer=bus.connections[0]?.sourceLayer;if(!sourceLayer)throw new Error(`FanoutSolver: bus "${bus.busId}" has no connections`);if(bus.termination.type==="plane"){assignment[bus.busId]=bus.termination.layer;continue}let routableEscapeLayers=escapeLayersByBusId[bus.busId]??escapeLayers,viaLayers=routableEscapeLayers.filter(layer=>layer!==sourceLayer),commonExitTargetLayer=getCommonExplicitExitTargetLayer(bus);if(commonExitTargetLayer&&routableEscapeLayers.includes(commonExitTargetLayer))assignment[bus.busId]=commonExitTargetLayer;else if(!busUsesCoordinatedWinding(bus)&&routableEscapeLayers.includes(sourceLayer)&&(busUsesDestinationGuidedTracks(bus)||busIsOnOutwardComponentEdge2(bus)))assignment[bus.busId]=sourceLayer;else if(viaLayers.length>0){let componentDirections=directionsByComponent.get(bus.componentId);if(componentDirections.has("left")&&componentDirections.has("right")||componentDirections.has("up")&&componentDirections.has("down")){let depthInRows=getBusDepthInRows(bus);assignment[bus.busId]=viaLayers[Math.max(depthInRows-1,0)%viaLayers.length]}else assignment[bus.busId]=viaLayers[nextViaLayerIndex%viaLayers.length],nextViaLayerIndex++}else assignment[bus.busId]=sourceLayer}return assignment}function prioritizeLayerAssignment(params){let{initialAssignment,generatedAssignments,maxAssignments}=params,initialKey=JSON.stringify(initialAssignment);return[initialAssignment,...generatedAssignments.filter(assignment=>JSON.stringify(assignment)!==initialKey)].slice(0,maxAssignments)}function busUsesCoordinatedWinding(bus){return!!(bus.exitEdge&&bus.termination.type==="boundary"&&bus.connections.length>0&&bus.connections.every(connection=>connection.hasExplicitLayeredExitTarget===!0))}function getCandidateEscapeLayersForBus(params){let{bus,srj,config,staticClearanceCache}=params,busAllowedLayers=bus.allowedLayers,allowedEscapeLayers=busAllowedLayers===void 0?config.escapeLayers:config.escapeLayers.filter(layer=>busAllowedLayers.includes(layer));if(busUsesCoordinatedWinding(bus))return allowedEscapeLayers;let individuallyRoutableLayers=allowedEscapeLayers.filter(targetLayer=>routeBus({srj,bus,targetLayer,acceptedPlans:[],layerNames:config.layerNames,traceWidth:config.traceWidth,viaDiameter:config.viaDiameter,viaHoleDiameter:config.viaHoleDiameter,clearance:config.clearance,compactBusTracks:config.compactBusTracks,allowSameNetMerges:config.allowSameNetMerges,staticClearanceCache})!==null);return individuallyRoutableLayers.length>0?individuallyRoutableLayers:allowedEscapeLayers}var FanoutSolver=class extends BaseSolver{constructor(inputSrj,options={}){super();__publicField(this,"inputSrj");__publicField(this,"options");__publicField(this,"preparedBuses");__publicField(this,"attempts",[]);__publicField(this,"layerAssignments");__publicField(this,"config");__publicField(this,"routingSrj");__publicField(this,"escapeLayersByBusId");__publicField(this,"evaluatedAssignmentKeys",new Set);__publicField(this,"queuedAssignmentKeys",new Set);__publicField(this,"assignmentRepairDepthByKey",new Map);__publicField(this,"pendingRepairAssignments",[]);__publicField(this,"routeStaticClearanceCache",new Map);__publicField(this,"routingPrefixCache",new Map);__publicField(this,"groupedBeamEvaluated",!1);__publicField(this,"nextAssignmentIndex",0);__publicField(this,"nextGeneratedAssignmentIndex",0);__publicField(this,"bestAttempt",null);__publicField(this,"endpointCompletion",null);this.inputSrj=inputSrj,this.options=options,this.routingSrj={...inputSrj,obstacles:[...inputSrj.obstacles]},this.config=resolveConfig(inputSrj,options),this.preparedBuses=prepareFanoutBuses(this.routingSrj,options),validateCornerBandCapacities(this.preparedBuses,this.config);for(let bus of this.preparedBuses){for(let connection of bus.connections){if(!connection.hasExplicitLayeredExitTarget)continue;let targetLayer=connection.exitTargetPoint?.layer;if(typeof targetLayer!="string"||targetLayer.length===0||!this.config.layerNames.includes(targetLayer))throw new Error(`FanoutSolver: connection exit target for "${connection.connection.name}" uses unavailable layer "${String(targetLayer)}"`)}for(let allowedLayer of bus.allowedLayers??[])if(!this.config.layerNames.includes(allowedLayer))throw new Error(`FanoutSolver: bus "${bus.busId}" allows unavailable layer "${allowedLayer}"`);if(bus.termination.type==="boundary"&&bus.allowedLayers!==void 0&&!bus.allowedLayers.some(layer=>this.config.escapeLayers.includes(layer)))throw new Error(`FanoutSolver: bus "${bus.busId}" has no allowed layer in escapeLayers`);if(bus.routableEscapeLayers=this.config.escapeLayers.filter(layer=>bus.allowedLayers?.includes(layer)??!0),bus.termination.type!=="plane")continue;let planeLayer=bus.termination.layer;if(!this.config.layerNames.includes(planeLayer))throw new Error(`FanoutSolver: plane-terminated bus "${bus.busId}" targets unavailable layer "${planeLayer}"`);if(bus.allowedLayers!==void 0&&!bus.allowedLayers.includes(planeLayer))throw new Error(`FanoutSolver: plane-terminated bus "${bus.busId}" targets disallowed layer "${planeLayer}"`);if(bus.connections.some(connection=>connection.sourceLayer===planeLayer))throw new Error(`FanoutSolver: plane-terminated bus "${bus.busId}" must target a layer below its source pad`)}let boundaryBusIds=this.preparedBuses.filter(bus=>bus.termination.type==="boundary").map(bus=>bus.busId),fixedPlaneAssignments=Object.fromEntries(this.preparedBuses.flatMap(bus=>bus.termination.type==="plane"?[[bus.busId,bus.termination.layer]]:[])),escapeLayersByBusId=Object.fromEntries(this.preparedBuses.flatMap(bus=>bus.termination.type==="plane"?[]:[[bus.busId,getCandidateEscapeLayersForBus({bus,srj:this.routingSrj,config:this.config,staticClearanceCache:this.routeStaticClearanceCache})]]));this.escapeLayersByBusId=escapeLayersByBusId;let generatedAssignments=generateLayerAssignments({busIds:boundaryBusIds,layers:this.config.escapeLayers,layersByBusId:escapeLayersByBusId,maxAssignments:this.config.maxLayerCombinations}).map(assignment=>({...assignment,...fixedPlaneAssignments}));this.layerAssignments=prioritizeLayerAssignment({initialAssignment:createInitialLayerAssignment({buses:this.preparedBuses,escapeLayers:this.config.escapeLayers,escapeLayersByBusId}),generatedAssignments,maxAssignments:this.config.maxLayerCombinations}),this.MAX_ITERATIONS=this.config.maxLayerCombinations+2}getSolverName(){return"FanoutSolver"}completeBestAttemptEndpoints(){!this.options.completeOriginalEndpoints||this.endpointCompletion||!this.bestAttempt||(this.endpointCompletion=completeOriginalEndpoints({inputSrj:this.routingSrj,fanoutSrj:this.bestAttempt.outputSrj,plans:this.bestAttempt.plans,traceWidth:this.config.traceWidth,viaDiameter:this.config.viaDiameter,viaHoleDiameter:this.config.viaHoleDiameter,clearance:this.config.clearance,effort:this.options.endpointCompletionEffort,routeDownstreamConnections:this.options.routeDownstreamConnections}))}getValidationBoundary(){if(this.options.sharedBoundary)return this.options.sharedBoundary;let firstBoundary=this.preparedBuses[0]?.sharedBoundary;return firstBoundary?this.preparedBuses.slice(1).reduce((boundary,bus)=>({minX:Math.min(boundary.minX,bus.sharedBoundary.minX),maxX:Math.max(boundary.maxX,bus.sharedBoundary.maxX),minY:Math.min(boundary.minY,bus.sharedBoundary.minY),maxY:Math.max(boundary.maxY,bus.sharedBoundary.maxY)}),{...firstBoundary}):this.inputSrj.bounds}validateCompletePlans(plans,outputSrj){return validateFanoutSolution({inputSrj:this.inputSrj,outputSrj,plans,preparedBuses:this.preparedBuses,sharedBoundary:this.getValidationBoundary(),clearance:this.config.clearance})}evaluateAssignmentWithStrategy(assignmentIndex,busLayerAssignments,routingStrategy){let plans=[],failedBusIds=[],blockingBusCounts=new Map,isSingleLayerFanout=this.config.escapeLayers.length===1,useSingleLayerPushAndShove=isSingleLayerFanout&&this.config.singleLayerPushAndShove&&!this.preparedBuses.some(bus=>bus.exitEdge&&bus.preferredExit?.includes("-"));if(useSingleLayerPushAndShove){let singleLayerParams={srj:this.routingSrj,buses:this.preparedBuses,traceWidth:this.config.traceWidth,clearance:this.config.clearance,borderDistribution:this.config.borderDistribution},singleLayerPlans=routeSingleLayerWithPushAndShove(singleLayerParams)??(this.config.singleLayerAdaptiveExits?routeSingleLayerWithAdaptiveExits({...singleLayerParams,availableBoundaryRegions:resolveAvailableBoundaryRegions(this.options.availableCornersAndSides)}):null);singleLayerPlans?plans.push(...singleLayerPlans):failedBusIds.push(...this.preparedBuses.map(bus=>bus.busId))}let busesInRoutingOrder=[...this.preparedBuses].sort((a6,b6)=>{let aUsesCoordinatedWinding=busUsesCoordinatedWinding(a6),bUsesCoordinatedWinding=busUsesCoordinatedWinding(b6),aLayerIndex=this.config.layerNames.indexOf(busLayerAssignments[a6.busId]??""),bLayerIndex=this.config.layerNames.indexOf(busLayerAssignments[b6.busId]??"");return+(b6.termination.type==="plane")-+(a6.termination.type==="plane")||Number(bUsesCoordinatedWinding)-Number(aUsesCoordinatedWinding)||(aUsesCoordinatedWinding&&bUsesCoordinatedWinding?bLayerIndex-aLayerIndex:0)||(routingStrategy==="group-by-layer"?(busLayerAssignments[a6.busId]??"").localeCompare(busLayerAssignments[b6.busId]??""):0)||b6.componentObstacles.length-a6.componentObstacles.length||(isSingleLayerFanout?getBusDistanceToBoundary(b6)-getBusDistanceToBoundary(a6):b6.connections.length-a6.connections.length||(routingStrategy==="deep-first"?getBusDistanceToBoundary(b6)-getBusDistanceToBoundary(a6):getBusDistanceToBoundary(a6)-getBusDistanceToBoundary(b6)))}),routingPrefixKey=`${routingStrategy}|`;for(let bus of useSingleLayerPushAndShove?[]:busesInRoutingOrder){let targetLayer=busLayerAssignments[bus.busId];if(!targetLayer)throw new Error(`FanoutSolver: assignment ${assignmentIndex} has no layer for bus "${bus.busId}"`);routingPrefixKey+=`${bus.busId.length}:${bus.busId};${targetLayer.length}:${targetLayer};`;let cachedPrefix=this.routingPrefixCache.get(routingPrefixKey);if(cachedPrefix){plans=[...cachedPrefix.plans],failedBusIds=[...cachedPrefix.failedBusIds],blockingBusCounts=new Map(cachedPrefix.blockingBusCounts);continue}let currentBusBlockingCounts=new Map,busPlans=routeBus({srj:this.routingSrj,bus,targetLayer,acceptedPlans:plans,layerNames:this.config.layerNames,traceWidth:this.config.traceWidth,viaDiameter:this.config.viaDiameter,viaHoleDiameter:this.config.viaHoleDiameter,clearance:this.config.clearance,compactBusTracks:this.config.compactBusTracks,allowSameNetMerges:this.config.allowSameNetMerges,staticClearanceCache:this.routeStaticClearanceCache,blockingBusCounts:currentBusBlockingCounts});if(busPlans)plans.push(...busPlans);else{failedBusIds.push(bus.busId);for(let[blockingBusId,count]of currentBusBlockingCounts)blockingBusCounts.set(blockingBusId,(blockingBusCounts.get(blockingBusId)??0)+count)}this.routingPrefixCache.set(routingPrefixKey,{plans:[...plans],failedBusIds:[...failedBusIds],blockingBusCounts:new Map(blockingBusCounts)})}let validationIssues,outputSrj=buildOutputSimpleRouteJson({inputSrj:this.inputSrj,plans,layerNames:this.config.layerNames}),validation=plans.length===this.inputSrj.connections.length?this.validateCompletePlans(plans,outputSrj):null;validation&&!validation.valid&&(validationIssues=validation.issues,plans=[],failedBusIds=this.preparedBuses.map(bus=>bus.busId),blockingBusCounts.clear(),outputSrj=buildOutputSimpleRouteJson({inputSrj:this.inputSrj,plans,layerNames:this.config.layerNames}));let routedBusCount=this.preparedBuses.length-failedBusIds.length,routeLength=plans.reduce((total,plan)=>total+plan.length,0),score=(this.inputSrj.connections.length-plans.length)*1e6+failedBusIds.length*1e5+routeLength+getPlanViaCount(plans)*.1+assignmentLoadPenalty(busLayerAssignments,this.preparedBuses,this.config.balanceLayerLoadByConnectionCount)*getLayerLoadPenaltyWeight(this.config);return{summary:{assignmentIndex,busLayerAssignments,routedBusCount,routedConnectionCount:plans.length,failedBusIds,score,...validationIssues?{validationIssues}:{}},plans,blockingBusIds:[...blockingBusCounts.entries()].toSorted(([,firstCount],[,secondCount])=>secondCount-firstCount).map(([busId])=>busId),outputSrj}}evaluateAssignment(assignmentIndex,busLayerAssignments){let bestAttempt=this.evaluateAssignmentWithStrategy(assignmentIndex,busLayerAssignments,"default");if(bestAttempt.summary.routedConnectionCount===this.inputSrj.connections.length&&this.getCoordinatedAdditionalViaCount(bestAttempt.plans)===0)return bestAttempt;for(let routingStrategy of["group-by-layer","deep-first"]){let attempt=this.evaluateAssignmentWithStrategy(assignmentIndex,busLayerAssignments,routingStrategy);if(this.isAttemptBetter(attempt,bestAttempt)&&(bestAttempt=attempt),bestAttempt.summary.routedConnectionCount===this.inputSrj.connections.length&&this.getCoordinatedAdditionalViaCount(bestAttempt.plans)===0)return bestAttempt}return bestAttempt}evaluateGroupedBeam(assignmentIndex,groupByDirection=!1){if(this.config.escapeLayers.length<2||this.preparedBuses.length>56)return null;let totalConnections=this.inputSrj.connections.length;if(totalConnections>64||new Set(this.preparedBuses.map(bus=>bus.componentId)).size!==1)return null;let getMaximumViaSpan=bus=>{let sourceLayerIndex=this.config.layerNames.indexOf(bus.connections[0]?.sourceLayer??""),candidateLayers=bus.termination.type==="plane"?[bus.termination.layer]:this.escapeLayersByBusId[bus.busId]??this.config.escapeLayers;return Math.max(0,...candidateLayers.map(layer=>Math.abs(this.config.layerNames.indexOf(layer)-sourceLayerIndex)))},busesInSearchOrder=[...this.preparedBuses].sort((a6,b6)=>{let aUsesCoordinatedWinding=busUsesCoordinatedWinding(a6),bUsesCoordinatedWinding=busUsesCoordinatedWinding(b6),aLayerCount=a6.termination.type==="plane"?1:this.escapeLayersByBusId[a6.busId]?.length??this.config.escapeLayers.length,bLayerCount=b6.termination.type==="plane"?1:this.escapeLayersByBusId[b6.busId]?.length??this.config.escapeLayers.length;return+(b6.termination.type==="plane")-+(a6.termination.type==="plane")||Number(bUsesCoordinatedWinding)-Number(aUsesCoordinatedWinding)||(aUsesCoordinatedWinding&&bUsesCoordinatedWinding?getMaximumViaSpan(b6)-getMaximumViaSpan(a6):0)||(groupByDirection?a6.direction.localeCompare(b6.direction):0)||aLayerCount-bLayerCount||b6.componentObstacles.length-a6.componentObstacles.length||b6.connections.length-a6.connections.length||getBusDepthInRows(b6)-getBusDepthInRows(a6)||a6.busId.localeCompare(b6.busId)}),isSmallProblem=totalConnections<=24,hasMultiConnectionBus=this.preparedBuses.some(bus=>bus.connections.length>1),beamWidth=isSmallProblem?48:totalConnections<=32?24:12,alternativesPerLayer=isSmallProblem&&!hasMultiConnectionBus?4:1,states=[{assignment:{},plans:[]}],getStateScore=state2=>{let routeLength=state2.plans.reduce((total,plan)=>total+plan.length,0),viaCount=getPlanViaCount(state2.plans),offEndpointLayerConnectionCount=this.preparedBuses.reduce((count,bus)=>{if(bus.termination.type!=="boundary"||!busUsesDestinationGuidedTracks(bus))return count;let sourceLayer=bus.connections[0]?.sourceLayer,preferredLayer=getCommonExplicitExitTargetLayer(bus)??sourceLayer;return state2.assignment[bus.busId]===preferredLayer?count:count+bus.connections.length},0);return routeLength+viaCount*.1+offEndpointLayerConnectionCount*1e4+assignmentLoadPenalty(state2.assignment,this.preparedBuses,this.config.balanceLayerLoadByConnectionCount)*getLayerLoadPenaltyWeight(this.config)};for(let bus of busesInSearchOrder){let nextStates=[];for(let state2 of states){let candidateLayers=bus.termination.type==="plane"?[bus.termination.layer]:this.escapeLayersByBusId[bus.busId]??this.config.escapeLayers,layerLoads=new Map;for(let[assignedBusId,layer]of Object.entries(state2.assignment)){let assignedBus=this.preparedBuses.find(candidate=>candidate.busId===assignedBusId);layerLoads.set(layer,(layerLoads.get(layer)??0)+(this.config.balanceLayerLoadByConnectionCount?assignedBus?.connections.length??1:1))}let sourceLayer=bus.connections[0]?.sourceLayer,commonExitTargetLayer=getCommonExplicitExitTargetLayer(bus),preferSourceLayer=busUsesDestinationGuidedTracks(bus),orderedLayers=candidateLayers.toSorted((first,second)=>(layerLoads.get(first)??0)-(layerLoads.get(second)??0)||+(second===commonExitTargetLayer)-+(first===commonExitTargetLayer)||(preferSourceLayer?+(second===sourceLayer)-+(first===sourceLayer):+(first===sourceLayer)-+(second===sourceLayer))||first.localeCompare(second));for(let targetLayer of orderedLayers){let busAlternatives=routeBusAlternatives({srj:this.routingSrj,bus,targetLayer,acceptedPlans:state2.plans,layerNames:this.config.layerNames,traceWidth:this.config.traceWidth,viaDiameter:this.config.viaDiameter,viaHoleDiameter:this.config.viaHoleDiameter,clearance:this.config.clearance,compactBusTracks:this.config.compactBusTracks,allowSameNetMerges:this.config.allowSameNetMerges,staticClearanceCache:this.routeStaticClearanceCache},alternativesPerLayer);for(let busPlans of busAlternatives)nextStates.push({assignment:{...state2.assignment,[bus.busId]:targetLayer},plans:[...state2.plans,...busPlans]})}}if(nextStates.length===0)return null;nextStates.sort((first,second)=>{let additionalViaDifference=this.getCoordinatedAdditionalViaCount(first.plans)-this.getCoordinatedAdditionalViaCount(second.plans);if(additionalViaDifference!==0)return additionalViaDifference;let scoreDifference=getStateScore(first)-getStateScore(second);return Math.abs(scoreDifference)>1e-9?scoreDifference:JSON.stringify(first.assignment).localeCompare(JSON.stringify(second.assignment))});let statesByAssignment=new Map;states=[];for(let state2 of nextStates){let key=JSON.stringify(state2.assignment),sameAssignmentCount=statesByAssignment.get(key)??0;if(!(sameAssignmentCount>=2)&&(statesByAssignment.set(key,sameAssignmentCount+1),states.push(state2),states.length>=beamWidth))break}}let bestState,outputSrj;for(let state2 of states){if(state2.plans.length!==this.inputSrj.connections.length)continue;let candidateOutput=buildOutputSimpleRouteJson({inputSrj:this.inputSrj,plans:state2.plans,layerNames:this.config.layerNames});if(this.validateCompletePlans(state2.plans,candidateOutput).valid){bestState=state2,outputSrj=candidateOutput;break}}if(!bestState||!outputSrj)return null;let score=bestState.plans.length===this.inputSrj.connections.length?bestState.plans.reduce((total,plan)=>total+plan.length,0)+getPlanViaCount(bestState.plans)*.1+assignmentLoadPenalty(bestState.assignment,this.preparedBuses,this.config.balanceLayerLoadByConnectionCount)*getLayerLoadPenaltyWeight(this.config):Number.POSITIVE_INFINITY;return Number.isFinite(score)?{summary:{assignmentIndex,busLayerAssignments:bestState.assignment,routedBusCount:this.preparedBuses.length,routedConnectionCount:bestState.plans.length,failedBusIds:[],score},plans:bestState.plans,blockingBusIds:[],outputSrj}:null}prioritizeFailedBusRepairs(assignment,failedBusIds,blockingBusIds){let assignmentKey=JSON.stringify(assignment),repairDepth=this.assignmentRepairDepthByKey.get(assignmentKey)??0;if(repairDepth>=2)return;let maximumRepairs=8,repairs=[],repairKeys=new Set,addRepair=repair=>{let key=JSON.stringify(repair);repairKeys.has(key)||this.evaluatedAssignmentKeys.has(key)||this.queuedAssignmentKeys.has(key)||(repairKeys.add(key),this.queuedAssignmentKeys.add(key),this.assignmentRepairDepthByKey.set(key,repairDepth+1),repairs.push(repair))},repairBusIds=[];for(let index=0;index<Math.max(failedBusIds.length,blockingBusIds.length);index++){let failedBusId=failedBusIds[index],blockingBusId=blockingBusIds[index];failedBusId&&!repairBusIds.includes(failedBusId)&&repairBusIds.push(failedBusId),blockingBusId&&!repairBusIds.includes(blockingBusId)&&repairBusIds.push(blockingBusId)}for(let failedBusId of failedBusIds){let failedLayer=assignment[failedBusId],failedCandidateLayers=this.escapeLayersByBusId[failedBusId];if(!(!failedLayer||!failedCandidateLayers)){for(let blockingBusId of blockingBusIds.slice(0,4)){let blockingLayer=assignment[blockingBusId],blockingCandidateLayers=this.escapeLayersByBusId[blockingBusId];if(!(!blockingLayer||!blockingCandidateLayers||!failedCandidateLayers.includes(blockingLayer)||!blockingCandidateLayers.includes(failedLayer))&&(addRepair({...assignment,[failedBusId]:blockingLayer,[blockingBusId]:failedLayer}),repairs.length>=maximumRepairs))break}if(repairs.length>=maximumRepairs)break}}for(let busId of repairBusIds){let currentLayer=assignment[busId],candidateLayers=this.escapeLayersByBusId[busId];if(!currentLayer||!candidateLayers)continue;let currentLayerIndex=candidateLayers.indexOf(currentLayer);for(let shift=1;shift<candidateLayers.length;shift++){let candidateLayer=candidateLayers[(Math.max(currentLayerIndex,0)+shift)%candidateLayers.length];if(candidateLayer!==currentLayer&&(addRepair({...assignment,[busId]:candidateLayer}),repairs.length>=maximumRepairs))break}if(repairs.length>=maximumRepairs)break}this.pendingRepairAssignments.push(...repairs)}hasCompleteBestAttempt(){return this.bestAttempt?.summary.routedConnectionCount===this.inputSrj.connections.length}getCoordinatedAdditionalViaCount(plans){let coordinatedBusIds=new Set(this.preparedBuses.filter(busUsesCoordinatedWinding).map(bus=>bus.busId));return plans.reduce((count,plan)=>count+(coordinatedBusIds.has(plan.busId)?plan.additionalVias?.length??0:0),0)}isAttemptBetter(candidate,current3){if(candidate.summary.routedConnectionCount!==current3.summary.routedConnectionCount)return candidate.summary.routedConnectionCount>current3.summary.routedConnectionCount;if(candidate.summary.routedBusCount!==current3.summary.routedBusCount)return candidate.summary.routedBusCount>current3.summary.routedBusCount;let candidateAdditionalVias=this.getCoordinatedAdditionalViaCount(candidate.plans),currentAdditionalVias=this.getCoordinatedAdditionalViaCount(current3.plans);return candidateAdditionalVias!==currentAdditionalVias?candidateAdditionalVias<currentAdditionalVias:candidate.summary.score<current3.summary.score}hasGloballyViaMinimalBestAttempt(){return!this.hasCompleteBestAttempt()||!this.bestAttempt||this.preparedBuses.length===0||!this.preparedBuses.every(busUsesCoordinatedWinding)?!1:this.bestAttempt.plans.every(plan=>plan.via!==void 0&&(plan.additionalVias?.length??0)===0)}shouldEvaluateGroupedBeam(){return this.groupedBeamEvaluated||this.nextAssignmentIndex===0?!1:this.hasCompleteBestAttempt()||this.pendingRepairAssignments.length===0||this.nextAssignmentIndex>=this.config.maxLayerCombinations}_step(){if(this.nextAssignmentIndex>0&&this.hasGloballyViaMinimalBestAttempt()){this.completeBestAttemptEndpoints(),this.solved=!0;return}if(this.shouldEvaluateGroupedBeam()){this.groupedBeamEvaluated=!0;let beamAttempt=this.evaluateGroupedBeam(-1);if(beamAttempt||(beamAttempt=this.evaluateGroupedBeam(-1,!0)),beamAttempt){this.attempts.push(beamAttempt.summary),(!this.bestAttempt||this.isAttemptBetter(beamAttempt,this.bestAttempt))&&(this.bestAttempt=beamAttempt);let bestSummary=this.bestAttempt.summary;if(this.stats={assignment:bestSummary.assignmentIndex<0?0:bestSummary.assignmentIndex+1,assignmentCount:this.config.maxLayerCombinations,routedBuses:`${bestSummary.routedBusCount}/${this.preparedBuses.length}`,routedConnections:`${bestSummary.routedConnectionCount}/${this.inputSrj.connections.length}`,failedBuses:"none",bestScore:bestSummary.score},this.getCoordinatedAdditionalViaCount(this.bestAttempt.plans)===0){this.completeBestAttemptEndpoints(),this.solved=!0;return}}if(this.hasCompleteBestAttempt()&&this.bestAttempt&&this.getCoordinatedAdditionalViaCount(this.bestAttempt.plans)===0){this.completeBestAttemptEndpoints(),this.solved=!0;return}}let assignment;for(;!assignment&&this.nextAssignmentIndex<this.config.maxLayerCombinations;){let preferGeneratedAssignment=this.nextAssignmentIndex%3===0,candidate,candidateCameFromRepairQueue=!1;if(!this.groupedBeamEvaluated&&this.nextAssignmentIndex>0?(candidate=this.pendingRepairAssignments.pop(),candidateCameFromRepairQueue=candidate!==void 0):preferGeneratedAssignment?candidate=this.layerAssignments[this.nextGeneratedAssignmentIndex++]:(candidate=this.pendingRepairAssignments.pop(),candidateCameFromRepairQueue=candidate!==void 0),!candidate&&(this.groupedBeamEvaluated||this.nextAssignmentIndex===0)&&(candidate=preferGeneratedAssignment?this.pendingRepairAssignments.pop():this.layerAssignments[this.nextGeneratedAssignmentIndex++],candidateCameFromRepairQueue=preferGeneratedAssignment&&candidate!==void 0),!candidate)break;let candidateKey=JSON.stringify(candidate);candidateCameFromRepairQueue&&this.queuedAssignmentKeys.delete(candidateKey),!this.evaluatedAssignmentKeys.has(candidateKey)&&(assignment=candidate)}if(!assignment&&!this.groupedBeamEvaluated)return;if(!assignment){this.hasCompleteBestAttempt()?(this.completeBestAttemptEndpoints(),this.solved=!0):(this.failed=!0,this.error=this.bestAttempt?`FanoutSolver: best layer assignment routed ${this.bestAttempt.summary.routedConnectionCount}/${this.inputSrj.connections.length} connections`:"FanoutSolver: no layer assignment could be evaluated");return}let attempt=this.evaluateAssignment(this.nextAssignmentIndex,assignment);this.nextAssignmentIndex++,this.evaluatedAssignmentKeys.add(JSON.stringify(assignment)),(!this.bestAttempt||attempt.summary.routedConnectionCount>=this.bestAttempt.summary.routedConnectionCount)&&this.prioritizeFailedBusRepairs(assignment,attempt.summary.failedBusIds,attempt.blockingBusIds),this.attempts.push(attempt.summary),(!this.bestAttempt||this.isAttemptBetter(attempt,this.bestAttempt))&&(this.bestAttempt=attempt),this.stats={assignment:attempt.summary.assignmentIndex+1,assignmentCount:this.config.maxLayerCombinations,routedBuses:`${attempt.summary.routedBusCount}/${this.preparedBuses.length}`,routedConnections:`${attempt.summary.routedConnectionCount}/${this.inputSrj.connections.length}`,failedBuses:attempt.summary.failedBusIds.join(", ")||"none",bestScore:this.bestAttempt.summary.score},this.groupedBeamEvaluated&&attempt.summary.routedConnectionCount===this.inputSrj.connections.length&&this.getCoordinatedAdditionalViaCount(this.bestAttempt.plans)===0&&(this.completeBestAttemptEndpoints(),this.solved=!0)}computeProgress(){return this.solved||this.failed?1:this.nextAssignmentIndex/this.config.maxLayerCombinations}getConstructorParams(){return[this.inputSrj,this.options]}getOutput(){if(!this.solved||!this.bestAttempt)throw new Error("FanoutSolver: getOutput() called before a complete fanout was solved");let validation=this.validateCompletePlans(this.bestAttempt.plans,this.bestAttempt.outputSrj);if(!validation.valid)throw new Error(`FanoutSolver: completed output failed validation: ${validation.issues[0]?.message??"unknown validation error"}`);let finalSrj=this.endpointCompletion?.simpleRouteJson??this.bestAttempt.outputSrj,finalTraceById=new Map((finalSrj.traces??[]).map(trace=>[trace.pcb_trace_id,trace]));return{simpleRouteJson:this.endpointCompletion?.simpleRouteJson??this.bestAttempt.outputSrj,fanoutTraces:this.bestAttempt.plans.flatMap(plan=>[finalTraceById.get(plan.trace.pcb_trace_id)??plan.trace,...plan.planeEndpointTrace?[finalTraceById.get(plan.planeEndpointTrace.pcb_trace_id)??plan.planeEndpointTrace]:[]]),completionTraces:this.endpointCompletion?.traces??[],...this.endpointCompletion?{endpointCompletion:this.endpointCompletion.report}:{},planeTerminations:this.bestAttempt.plans.flatMap(plan=>plan.termination.type==="plane"&&plan.via?[{busId:plan.busId,connectionName:plan.connectionName,layer:plan.termination.layer,via:plan.via}]:[]),busLayerAssignments:this.bestAttempt.summary.busLayerAssignments,busDirections:Object.fromEntries(this.preparedBuses.map(bus=>[bus.busId,bus.direction])),attempts:[...this.attempts],validation}}getOutputSimpleRouteJson(){return this.getOutput().simpleRouteJson}visualize(){let visualizedSrj=this.endpointCompletion?.simpleRouteJson??this.bestAttempt?.outputSrj??this.inputSrj;return visualizeSimpleRouteJson(visualizedSrj)}},getDirectionalPadding=padding=>{if(typeof padding!="object"){let parsedPadding=distance.parse(padding);return{top:parsedPadding,right:parsedPadding,bottom:parsedPadding,left:parsedPadding}}return{top:padding.top===void 0?0:distance.parse(padding.top),right:padding.right===void 0?0:distance.parse(padding.right),bottom:padding.bottom===void 0?0:distance.parse(padding.bottom),left:padding.left===void 0?0:distance.parse(padding.left)}},getObstacleHalfExtents=obstacle=>{let rotationRadians=(obstacle.ccwRotationDegrees??0)*Math.PI/180,absoluteCosine=Math.abs(Math.cos(rotationRadians)),absoluteSine=Math.abs(Math.sin(rotationRadians));return{x:(absoluteCosine*obstacle.width+absoluteSine*obstacle.height)/2,y:(absoluteSine*obstacle.width+absoluteCosine*obstacle.height)/2}},getFanoutSharedBoundary=({preparedBuses,padding})=>{if(padding===void 0)return;let sourcePadsByComponentId=new Map;for(let bus of preparedBuses)sourcePadsByComponentId.has(bus.componentId)||sourcePadsByComponentId.set(bus.componentId,bus.componentObstacles.filter(obstacle=>obstacle.connectedTo.length>0));let sourcePadObstacles=[...sourcePadsByComponentId.values()].flat();if(sourcePadObstacles.length===0)throw new Error("Cannot apply fanout boundary padding without source pad obstacles");let obstacleBounds=sourcePadObstacles.map(obstacle=>{let halfExtents=getObstacleHalfExtents(obstacle);return{minX:obstacle.center.x-halfExtents.x,maxX:obstacle.center.x+halfExtents.x,minY:obstacle.center.y-halfExtents.y,maxY:obstacle.center.y+halfExtents.y}}),directionalPadding=getDirectionalPadding(padding),sharedBoundary={minX:Math.min(...obstacleBounds.map(bounds=>bounds.minX))-directionalPadding.left,maxX:Math.max(...obstacleBounds.map(bounds=>bounds.maxX))+directionalPadding.right,minY:Math.min(...obstacleBounds.map(bounds=>bounds.minY))-directionalPadding.bottom,maxY:Math.max(...obstacleBounds.map(bounds=>bounds.maxY))+directionalPadding.top};for(let bus of preparedBuses)if(bus.termination.type==="boundary")for(let connection of bus.connections)bus.direction==="left"||bus.direction==="right"?(sharedBoundary.minY=Math.min(sharedBoundary.minY,connection.targetPoint.y),sharedBoundary.maxY=Math.max(sharedBoundary.maxY,connection.targetPoint.y)):(sharedBoundary.minX=Math.min(sharedBoundary.minX,connection.targetPoint.x),sharedBoundary.maxX=Math.max(sharedBoundary.maxX,connection.targetPoint.x));return sharedBoundary},roundMm=value=>Math.round(value*1e3)/1e3,getPadBoundsForComponents=(input2,componentIds)=>{let bounds;for(let obstacle of input2.obstacles){if(!obstacle.componentId||!componentIds.has(obstacle.componentId))continue;let minX=obstacle.center.x-obstacle.width/2,maxX=obstacle.center.x+obstacle.width/2,minY=obstacle.center.y-obstacle.height/2,maxY=obstacle.center.y+obstacle.height/2;bounds=bounds?{minX:Math.min(bounds.minX,minX),maxX:Math.max(bounds.maxX,maxX),minY:Math.min(bounds.minY,minY),maxY:Math.max(bounds.maxY,maxY)}:{minX,maxX,minY,maxY}}return bounds},getNarrowestGap=(padBounds,boundary)=>Math.min(padBounds.minX-boundary.minX,boundary.maxX-padBounds.maxX,padBounds.minY-boundary.minY,boundary.maxY-padBounds.maxY),getFanoutSpaceErrorMessage=({input:input2,solverError,componentIds,sharedBoundary,componentNamesById})=>{let routedMatch=solverError?.match(/routed (\d+)\/(\d+) connections/),routedCount=routedMatch?Number(routedMatch[1]):void 0,connectionCount=routedMatch?Number(routedMatch[2]):input2.connections.length,componentLabels=[...componentIds].map(componentId=>componentNamesById?.get(componentId)??componentId).sort(),componentSummary=componentLabels.length>0?` for ${componentLabels.join(", ")}`:"",lines=[routedCount===void 0?`Fanout failed${componentSummary}: ${solverError??"the fanout solver did not report a reason"}.`:`Fanout failed${componentSummary}: only ${routedCount} of ${connectionCount} connections could escape to the breakout boundary.`],padBounds=getPadBoundsForComponents(input2,componentIds);if(padBounds&&sharedBoundary){let gap=getNarrowestGap(padBounds,sharedBoundary);lines.push(`The breakout boundary is ${roundMm(gap)}mm from the pads at its narrowest point, which all ${connectionCount} escapes have to share.`)}return lines.push("Give the fanout more room by increasing the breakout's padding, or by extending the breakout to include the parts crowding it (decoupling capacitors, series resistors) so their pads sit inside the boundary instead of against it."),lines.join(" ")},boundsDiffer=(first,second)=>Math.abs(first.minX-second.minX)>1e-6||Math.abs(first.maxX-second.maxX)>1e-6||Math.abs(first.minY-second.minY)>1e-6||Math.abs(first.maxY-second.maxY)>1e-6,expandBoundsToIncludePoints=(bounds,points)=>{if(!(!bounds&&points.length===0))return{minX:Math.min(bounds?.minX??Number.POSITIVE_INFINITY,...points.map(p3=>p3.x)),maxX:Math.max(bounds?.maxX??Number.NEGATIVE_INFINITY,...points.map(p3=>p3.x)),minY:Math.min(bounds?.minY??Number.POSITIVE_INFINITY,...points.map(p3=>p3.y)),maxY:Math.max(bounds?.maxY??Number.NEGATIVE_INFINITY,...points.map(p3=>p3.y))}},getFanoutSolverBuses=(buses,busFanoutDirections)=>buses?.map(bus=>{let{preferredLayer,preferredLayers,...fanoutBusWithoutPreferences}=bus,requestedDirection=busFanoutDirections?.[bus.busId],requestedDirectionLiteral=requestedDirection===void 0?void 0:getBusFanoutDirectionLiteral(requestedDirection),exitPosition=requestedDirectionLiteral&&requestedDirectionLiteral!=="center"&&isCanonicalBusFanoutDirection(requestedDirectionLiteral)?requestedDirectionLiteral:void 0,fanoutBus={...fanoutBusWithoutPreferences,...bus.termination?.type==="plane"?{}:exitPosition?{exitPosition}:{}},requestedFanoutLayers=[...preferredLayer===void 0?[]:[preferredLayer],...preferredLayers??[]].filter((layer,index,layers)=>layers.indexOf(layer)===index);if(requestedFanoutLayers.length===0)return fanoutBus;let busAllowedLayers=bus.allowedLayers,allowedLayers=busAllowedLayers===void 0?requestedFanoutLayers:requestedFanoutLayers.filter(layer=>busAllowedLayers.includes(layer));return{...fanoutBus,allowedLayers}}),getBusFanoutDirectionLiteral=fanoutDirection=>typeof fanoutDirection=="string"?fanoutDirection:fanoutDirection.direction,canonicalBusFanoutDirections=new Set(canonicalBusFanoutDirectionValues),isCanonicalBusFanoutDirection=direction2=>canonicalBusFanoutDirections.has(direction2),getLegacyFanoutBorderTarget=anchor=>{switch(anchor){case"top_left":return"top-left";case"top_center":return"top";case"top_right":return"top-right";case"center_left":return"left";case"center":return;case"center_right":return"right";case"bottom_left":return"bottom-left";case"bottom_center":return"bottom";case"bottom_right":return"bottom-right"}},getLegacyFanoutDirection=anchor=>{switch(anchor){case"top_left":case"top_center":case"top_right":return"up";case"center_left":return"left";case"center":return;case"center_right":return"right";case"bottom_left":case"bottom_center":case"bottom_right":return"down"}},getLocalFanoutDirection=fanoutDirection=>{let directionLiteral=getBusFanoutDirectionLiteral(fanoutDirection);return isCanonicalBusFanoutDirection(directionLiteral)?getFanoutExitPositionConfig(directionLiteral).direction:getLegacyFanoutDirection(directionLiteral)},getSourceComponentIdForPoint=(input2,point6)=>input2.obstacles.find(obstacle=>obstacle.componentId&&obstacle.layers.includes(point6.layer)&&(point6.pointId&&obstacle.connectedTo.includes(point6.pointId)||point6.x>=obstacle.center.x-obstacle.width/2&&point6.x<=obstacle.center.x+obstacle.width/2&&point6.y>=obstacle.center.y-obstacle.height/2&&point6.y<=obstacle.center.y+obstacle.height/2))?.componentId,inferPlaneBusDirection=(input2,bus)=>{let connectionNames=new Set(bus.connectionNames),sourcePointsByComponentId=new Map;for(let connection of input2.connections)if(connectionNames.has(connection.name))for(let point6 of connection.pointsToConnect){let componentId=getSourceComponentIdForPoint(input2,point6);if(!componentId)continue;let sourcePoints2=sourcePointsByComponentId.get(componentId)??[];sourcePoints2.push(point6),sourcePointsByComponentId.set(componentId,sourcePoints2)}let sourceComponent=[...sourcePointsByComponentId.entries()].sort(([firstComponentId,firstPoints],[secondComponentId,secondPoints])=>secondPoints.length-firstPoints.length||firstComponentId.localeCompare(secondComponentId))[0];if(!sourceComponent)return;let[sourceComponentId,sourcePoints]=sourceComponent,componentObstacles=input2.obstacles.filter(obstacle=>obstacle.componentId===sourceComponentId);if(componentObstacles.length===0)return;let componentXCoordinates=componentObstacles.map(obstacle=>obstacle.center.x),componentYCoordinates=componentObstacles.map(obstacle=>obstacle.center.y),minComponentX=Math.min(...componentXCoordinates),maxComponentX=Math.max(...componentXCoordinates),minComponentY=Math.min(...componentYCoordinates),maxComponentY=Math.max(...componentYCoordinates),componentCenter={x:(minComponentX+maxComponentX)/2,y:(minComponentY+maxComponentY)/2},componentHalfSpan={x:Math.max((maxComponentX-minComponentX)/2,1e-6),y:Math.max((maxComponentY-minComponentY)/2,1e-6)},averageSourcePoint={x:sourcePoints.reduce((sum,point6)=>sum+point6.x,0)/sourcePoints.length,y:sourcePoints.reduce((sum,point6)=>sum+point6.y,0)/sourcePoints.length},normalizedOffset={x:(averageSourcePoint.x-componentCenter.x)/componentHalfSpan.x,y:(averageSourcePoint.y-componentCenter.y)/componentHalfSpan.y};return Math.abs(normalizedOffset.x)>Math.abs(normalizedOffset.y)?normalizedOffset.x>=0?"right":"left":Math.abs(normalizedOffset.y)>1e-9?normalizedOffset.y>=0?"up":"down":"right"},createDownstreamSimpleRouteJson=({fanoutSimpleRouteJson,sourceComponentIds})=>{let sourceObstaclesByComponentId=new Map;for(let obstacle of fanoutSimpleRouteJson.obstacles){if(!obstacle.componentId||!sourceComponentIds.has(obstacle.componentId))continue;let sourceObstacles=sourceObstaclesByComponentId.get(obstacle.componentId)??[];sourceObstacles.push(obstacle),sourceObstaclesByComponentId.set(obstacle.componentId,sourceObstacles)}let sourceFootprintKeepouts=[];for(let[componentId,sourceObstacles]of sourceObstaclesByComponentId){let minX=Math.min(...sourceObstacles.map(obstacle=>obstacle.center.x-obstacle.width/2)),maxX=Math.max(...sourceObstacles.map(obstacle=>obstacle.center.x+obstacle.width/2)),minY=Math.min(...sourceObstacles.map(obstacle=>obstacle.center.y-obstacle.height/2)),maxY=Math.max(...sourceObstacles.map(obstacle=>obstacle.center.y+obstacle.height/2));sourceFootprintKeepouts.push({obstacleId:`fanout-source-keepout:${componentId}`,componentId,isFanoutSourceKeepout:!0,type:"rect",layers:getViaBoardLayers(fanoutSimpleRouteJson.layerCount),center:{x:(minX+maxX)/2,y:(minY+maxY)/2},width:maxX-minX,height:maxY-minY,connectedTo:[]})}return{...fanoutSimpleRouteJson,obstacles:[...fanoutSimpleRouteJson.obstacles.filter(obstacle=>!obstacle.componentId||!sourceComponentIds.has(obstacle.componentId)),...sourceFootprintKeepouts]}},FanoutAutorouter=class _FanoutAutorouter{constructor(input2,options){__publicField(this,"input");__publicField(this,"options");__publicField(this,"isRouting",!1);__publicField(this,"outputSimpleRouteJson");__publicField(this,"startTimeoutId");__publicField(this,"eventHandlers",{complete:[],error:[],progress:[]});this.input=input2,this.options=options}getLegacyBusExitPreferences(){if(!this.options.busFanoutDirections)return;let knownBusIds=new Set(this.input.buses?.map(bus=>bus.busId)??[]),planeBusIds=new Set(this.input.buses?.filter(bus=>bus.termination?.type==="plane").map(bus=>bus.busId)??[]),preferences={};for(let[busId,fanoutDirection]of Object.entries(this.options.busFanoutDirections)){if(!knownBusIds.has(busId))throw new Error(`Fanout direction references unknown bus "${busId}" in this autorouting phase`);if(planeBusIds.has(busId))continue;let directionLiteral=getBusFanoutDirectionLiteral(fanoutDirection);if(isCanonicalBusFanoutDirection(directionLiteral))continue;let target=getLegacyFanoutBorderTarget(directionLiteral);target&&(preferences[busId]=target)}return Object.keys(preferences).length>0?preferences:void 0}getPlaneBusDirections(){let planeBuses=this.input.buses?.filter(bus=>bus.termination?.type==="plane")??[],planeBusIds=new Set(planeBuses.map(bus=>bus.busId)),directions={};for(let[busId,fanoutDirection]of Object.entries(this.options.busFanoutDirections??{})){if(!planeBusIds.has(busId))continue;let direction2=getLocalFanoutDirection(fanoutDirection);direction2&&(directions[busId]=direction2)}for(let planeBus of planeBuses){if(directions[planeBus.busId])continue;let direction2=inferPlaneBusDirection(this.input,planeBus);direction2&&(directions[planeBus.busId]=direction2)}return Object.keys(directions).length>0?directions:void 0}getFanoutSolverOptions(){let commonOptions={buses:getFanoutSolverBuses(this.input.buses,this.options.busFanoutDirections),borderDistribution:"even",compactBusTracks:!0,busDirections:this.getPlaneBusDirections(),busExitPreferences:this.getLegacyBusExitPreferences(),escapeLayers:this.options.fanoutRoutingLayers};return this.options.mode==="single_layer_fanout"?{...commonOptions,escapeLayers:["top"],singleLayerPushAndShove:!0}:commonOptions}static resolveFanoutBounds(input2,options){let paddingBounds,inferredBounds;if(options.fanoutBoundaryPadding!==void 0){let boundsResolver=new _FanoutAutorouter(input2,options),fanoutSolver=new FanoutSolver(input2,boundsResolver.getFanoutSolverOptions());paddingBounds=getFanoutSharedBoundary({preparedBuses:fanoutSolver.preparedBuses,padding:options.fanoutBoundaryPadding})}else if(options.fanoutBounds===void 0){let boundsResolver=new _FanoutAutorouter(input2,options);inferredBounds=new FanoutSolver(input2,boundsResolver.getFanoutSolverOptions()).preparedBuses[0]?.sharedBoundary}return options.fanoutBounds&&paddingBounds&&boundsDiffer(options.fanoutBounds,paddingBounds)&&options.onFanoutBoundsConflict?.(),expandBoundsToIncludePoints(options.fanoutBounds??paddingBounds??inferredBounds,options.breakoutPoints??[])}solveFanout(){let fanoutSolverOptions=this.getFanoutSolverOptions(),fanoutSolver=new FanoutSolver(this.input,{...fanoutSolverOptions,...this.options.fanoutBounds?{sharedBoundary:this.options.fanoutBounds}:{}}),solverConstructorArgs=fanoutSolver.getConstructorParams();if(this.options.onSolverStarted?.({solverName:"FanoutSolver",solverParams:solverConstructorArgs[0],solverConstructorArgs}),fanoutSolver.solve(),fanoutSolver.failed)throw new Error(getFanoutSpaceErrorMessage({input:this.input,solverError:fanoutSolver.error,componentIds:new Set(fanoutSolver.preparedBuses.map(bus=>bus.componentId)),sharedBoundary:this.options.fanoutBounds??fanoutSolverOptions.sharedBoundary,componentNamesById:this.options.componentNamesById}));let output=fanoutSolver.getOutput(),fanoutSimpleRouteJson=output.simpleRouteJson,fanoutTraces=output.fanoutTraces;return{downstreamSimpleRouteJson:createDownstreamSimpleRouteJson({fanoutSimpleRouteJson,sourceComponentIds:new Set(fanoutSolver.preparedBuses.map(bus=>bus.componentId))}),fanoutTraces,debugGraphics:fanoutSolver.visualize()}}startFanout(){try{let{downstreamSimpleRouteJson,fanoutTraces,debugGraphics}=this.solveFanout();if(!this.isRouting)return;this.outputSimpleRouteJson=downstreamSimpleRouteJson,this.emitEvent({type:"progress",steps:1,progress:1,phase:this.options.mode,debugGraphics}),this.isRouting=!1,this.emitEvent({type:"complete",traces:fanoutTraces})}catch(caughtError){this.isRouting=!1,this.emitEvent({type:"error",error:caughtError instanceof Error?caughtError:new Error(String(caughtError))})}}start(){this.isRouting||(this.isRouting=!0,this.startTimeoutId=setTimeout(()=>{this.startTimeoutId=void 0,this.startFanout()},0))}stop(){this.startTimeoutId!==void 0&&(clearTimeout(this.startTimeoutId),this.startTimeoutId=void 0),this.isRouting=!1}on(event,callback){event==="complete"?this.eventHandlers.complete.push(callback):event==="error"?this.eventHandlers.error.push(callback):this.eventHandlers.progress.push(callback)}emitEvent(event){if(event.type==="complete")for(let handler of this.eventHandlers.complete)handler(event);else if(event.type==="error")for(let handler of this.eventHandlers.error)handler(event);else for(let handler of this.eventHandlers.progress)handler(event)}solveSync(){let{downstreamSimpleRouteJson,fanoutTraces}=this.solveFanout();return this.outputSimpleRouteJson=downstreamSimpleRouteJson,fanoutTraces}getOutputSimpleRouteJson(){return this.outputSimpleRouteJson}},createSourceTracesFromOffboardConnections=({db:db2,connectedOffboardObstacles,simpleRouteJson,subcircuit_id})=>{if(Object.keys(connectedOffboardObstacles).length===0)return;let pcbElementIdToSourcePortId=new Map;for(let pcbPort of db2.pcb_port.list())if(pcbPort.source_port_id){let smtpad2=db2.pcb_smtpad.getWhere({pcb_port_id:pcbPort.pcb_port_id});smtpad2&&pcbElementIdToSourcePortId.set(smtpad2.pcb_smtpad_id,pcbPort.source_port_id);let platedHole=db2.pcb_plated_hole.getWhere({pcb_port_id:pcbPort.pcb_port_id});platedHole&&pcbElementIdToSourcePortId.set(platedHole.pcb_plated_hole_id,pcbPort.source_port_id)}let obstacleById=new Map;for(let obstacle of simpleRouteJson.obstacles)obstacle.obstacleId&&obstacleById.set(obstacle.obstacleId,obstacle);let connectionGroups=new Map;for(let[obstacleId,rootConnectionName]of Object.entries(connectedOffboardObstacles))connectionGroups.has(rootConnectionName)||connectionGroups.set(rootConnectionName,[]),connectionGroups.get(rootConnectionName).push(obstacleId);for(let[rootConnectionName,obstacleIds]of connectionGroups){let sourcePortIds=new Set;for(let obstacleId of obstacleIds){let obstacle=obstacleById.get(obstacleId);if(obstacle)for(let connectedId of obstacle.connectedTo){let sourcePortId=pcbElementIdToSourcePortId.get(connectedId);sourcePortId&&sourcePortIds.add(sourcePortId)}}if(sourcePortIds.size<2)continue;let sourcePortIdArray=Array.from(sourcePortIds);db2.source_trace.list().some(trace=>{let tracePortIds=new Set(trace.connected_source_port_ids);return sourcePortIdArray.every(id3=>tracePortIds.has(id3))})||db2.source_trace.insert({connected_source_port_ids:sourcePortIdArray,connected_source_net_ids:[],subcircuit_id:subcircuit_id??void 0,display_name:`offboard_${rootConnectionName}`})}},getFanoutBoundaryPointSpacing=({traceWidth,traceToPadClearance,viaPadDiameter})=>(viaPadDiameter??Math.max(traceWidth*2,.3))+2*(traceWidth+traceToPadClearance),getPcbComponentNamesById=db2=>{let namesById=new Map;for(let pcbComponent of db2.pcb_component.list()){let sourceComponent=db2.source_component.get(pcbComponent.source_component_id);sourceComponent?.name&&namesById.set(pcbComponent.pcb_component_id,sourceComponent.name)}return namesById},normalizeAutorouterName=value=>value?.replace(/-/g,"_");function getLegacyAutorouterPreset(autorouterConfig2){if(!autorouterConfig2)return null;if(typeof autorouterConfig2=="string"){let normalizedAutorouterName=normalizeAutorouterName(autorouterConfig2);return normalizedAutorouterName==="sequential_trace"||normalizedAutorouterName==="auto_cloud"?normalizedAutorouterName:null}let normalizedPreset=normalizeAutorouterName(autorouterConfig2.preset);return normalizedPreset==="sequential_trace"||normalizedPreset==="auto_cloud"?normalizedPreset:normalizeAutorouterName(autorouterConfig2.groupMode)==="sequential_trace"?"sequential_trace":null}function getPresetAutoroutingConfig(autorouterConfig2,platformConfig2){let defaults2={serverUrl:"https://registry-api.tscircuit.com",serverMode:"job",serverCacheEnabled:!0};if(typeof autorouterConfig2=="object"&&!autorouterConfig2.preset)return{local:!(autorouterConfig2.serverUrl||autorouterConfig2.serverMode||autorouterConfig2.serverCacheEnabled),...defaults2,...autorouterConfig2};let preset=typeof autorouterConfig2=="object"?autorouterConfig2.preset:autorouterConfig2,providedConfig=typeof autorouterConfig2=="object"?autorouterConfig2:{},normalizedPreset=typeof preset=="string"?preset.replace(/_/g,"-"):preset,platformAutorouter=normalizedPreset&&typeof normalizedPreset=="string"?platformConfig2?.autorouterMap?.[normalizedPreset]:void 0;if(platformAutorouter)return{local:!0,groupMode:"subcircuit",algorithmFn:async simpleRouteJson=>platformAutorouter.createAutorouter(simpleRouteJson)};switch(normalizedPreset){case"default":case"auto":case"auto-local":return{local:!0,groupMode:"subcircuit"};case"sequential-trace":return{local:!0,groupMode:"sequential-trace"};case"subcircuit":return{local:!0,groupMode:"subcircuit"};case"beta-pipeline9":return{local:!0,groupMode:"subcircuit",autorouterVersion:"beta_pipeline9"};case"single-layer-fanout":return{local:!0,groupMode:"subcircuit",preset:"single_layer_fanout"};case"fanout":return{local:!0,groupMode:"subcircuit",preset:"fanout"};case"auto-cloud":{let{preset:_preset,local:_local,groupMode:_groupMode,...rest}=providedConfig;return{local:!1,groupMode:"subcircuit",...defaults2,...rest}}case"laser-prefab":{let{preset:_preset,local:_local,groupMode:_groupMode,...rest}=providedConfig;return{local:!0,groupMode:"subcircuit",preset:"laser_prefab",...rest}}case"auto-jumper":{let{preset:_preset,local:_local,groupMode:_groupMode,...rest}=providedConfig;return{local:!0,groupMode:"subcircuit",preset:"auto_jumper",...rest}}default:return{local:!0,groupMode:"subcircuit"}}}var SOLVERS={PackSolver2,LayoutPipelineSolver,AutoroutingPipelineSolver:Hq,AssignableAutoroutingPipeline2:Dl2,AssignableAutoroutingPipeline3:Hg,AutoroutingPipeline1_OriginalUnravel:al2,AutoroutingPipelineSolver3_HgPortPointPathing:yf2,AutoroutingPipelineSolver4:BY,AutoroutingPipelineSolver5:ZY,AutoroutingPipelineSolver7_MultiGraph:Hq,AutoroutingPipelineSolver8:Zq,AutoroutingPipelineSolver9_PreloadedTraceGraph:F02,CopperPourPipelineSolver,CreateFdmEnclosureSolver,FanoutSolver,SchematicTracePipelineSolver},AUTOROUTER_CACHE_KEY_PREFIX="capacity-autorouter:",cacheProvidersByLocalCacheEngine=new WeakMap;function isPromiseLike(value){return typeof value=="object"&&value!==null&&"then"in value&&typeof value.then=="function"}function isAsyncFunction(fn3){return fn3.constructor.name==="AsyncFunction"}var LocalCacheEngineCacheProvider=class{constructor(localCacheEngine2){__publicField(this,"localCacheEngine");__publicField(this,"isSyncCache");__publicField(this,"cacheHits",0);__publicField(this,"cacheMisses",0);__publicField(this,"cacheHitsByPrefix",{});__publicField(this,"cacheMissesByPrefix",{});__publicField(this,"knownCacheKeys",new Set);this.localCacheEngine=localCacheEngine2,this.isSyncCache=!isAsyncFunction(localCacheEngine2.getItem)&&!isAsyncFunction(localCacheEngine2.setItem)}getCachedSolutionSync(cacheKey){if(this.isSyncCache){this.knownCacheKeys.add(cacheKey);try{let cachedItem=this.localCacheEngine.getItem(this.getLocalCacheEngineKey(cacheKey));if(isPromiseLike(cachedItem)){this.isSyncCache=!1,Promise.resolve(cachedItem).catch(()=>{}),this.recordCacheMiss(cacheKey);return}return this.parseCachedItem(cacheKey,cachedItem)}catch{this.recordCacheMiss(cacheKey);return}}}async getCachedSolution(cacheKey){this.knownCacheKeys.add(cacheKey);try{let cachedItem=await this.localCacheEngine.getItem(this.getLocalCacheEngineKey(cacheKey));return this.parseCachedItem(cacheKey,cachedItem)}catch{this.recordCacheMiss(cacheKey);return}}setCachedSolutionSync(cacheKey,cachedSolution){if(this.isSyncCache){this.knownCacheKeys.add(cacheKey);try{let serializedSolution=JSON.stringify(cachedSolution);if(serializedSolution===void 0)return;let writeResult=this.localCacheEngine.setItem(this.getLocalCacheEngineKey(cacheKey),serializedSolution);isPromiseLike(writeResult)&&(this.isSyncCache=!1,Promise.resolve(writeResult).catch(()=>{}))}catch{}}}async setCachedSolution(cacheKey,cachedSolution){this.knownCacheKeys.add(cacheKey);try{let serializedSolution=JSON.stringify(cachedSolution);if(serializedSolution===void 0)return;await this.localCacheEngine.setItem(this.getLocalCacheEngineKey(cacheKey),serializedSolution)}catch{}}getAllCacheKeys(){return[...this.knownCacheKeys]}clearCache(){for(let cacheKey of this.knownCacheKeys){let localCacheEngineKey=this.getLocalCacheEngineKey(cacheKey);try{let clearResult=this.localCacheEngine.removeItem?this.localCacheEngine.removeItem(localCacheEngineKey):this.localCacheEngine.setItem(localCacheEngineKey,"null");isPromiseLike(clearResult)&&Promise.resolve(clearResult).catch(()=>{})}catch{}}this.knownCacheKeys.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getLocalCacheEngineKey(cacheKey){return`${AUTOROUTER_CACHE_KEY_PREFIX}${cacheKey}`}parseCachedItem(cacheKey,cachedItem){if(cachedItem===null){this.recordCacheMiss(cacheKey);return}try{let cachedSolution=JSON.parse(cachedItem);if(cachedSolution===null){this.recordCacheMiss(cacheKey);return}return this.recordCacheHit(cacheKey),cachedSolution}catch{this.recordCacheMiss(cacheKey);return}}recordCacheHit(cacheKey){this.cacheHits++;let prefix=cacheKey.split(":")[0];this.cacheHitsByPrefix[prefix]=(this.cacheHitsByPrefix[prefix]??0)+1}recordCacheMiss(cacheKey){this.cacheMisses++;let prefix=cacheKey.split(":")[0];this.cacheMissesByPrefix[prefix]=(this.cacheMissesByPrefix[prefix]??0)+1}};function getCacheProviderForLocalCacheEngine(localCacheEngine2){let cacheProvider=cacheProvidersByLocalCacheEngine.get(localCacheEngine2);return cacheProvider||(cacheProvider=new LocalCacheEngineCacheProvider(localCacheEngine2),cacheProvidersByLocalCacheEngine.set(localCacheEngine2,cacheProvider)),cacheProvider}function getCapacityAutorouterCacheProvider(platformConfig2){return platformConfig2?.localCacheEngine?getCacheProviderForLocalCacheEngine(platformConfig2.localCacheEngine):null}var TscircuitAutorouter=class{constructor(input2,options={}){__publicField(this,"input");__publicField(this,"isRouting",!1);__publicField(this,"solver");__publicField(this,"eventHandlers",{complete:[],error:[],progress:[]});__publicField(this,"cycleCount",0);__publicField(this,"stepDelay");__publicField(this,"timeoutId");this.input=input2;let{capacityDepth,targetMinCapacity,stepDelay=0,useAssignableSolver=!1,useAutoJumperSolver=!1,autorouterVersion:autorouterVersion22,useLaserPrefabSolver=!1,effort,platformConfig:platformConfig2,onSolverStarted}=options,solverName;autorouterVersion22==="beta_pipeline1"?solverName="AutoroutingPipeline1_OriginalUnravel":autorouterVersion22==="beta_pipeline3"?solverName="AutoroutingPipelineSolver3_HgPortPointPathing":autorouterVersion22==="beta_pipeline4"?solverName="AutoroutingPipelineSolver4":autorouterVersion22==="beta_pipeline5"?solverName="AutoroutingPipelineSolver5":autorouterVersion22==="beta_pipeline7"||autorouterVersion22==="latest"?solverName="AutoroutingPipelineSolver7_MultiGraph":autorouterVersion22==="beta_pipeline9"?solverName="AutoroutingPipelineSolver9_PreloadedTraceGraph":useLaserPrefabSolver?solverName="AutoroutingPipelineSolver8":useAutoJumperSolver?solverName="AssignableAutoroutingPipeline3":useAssignableSolver?solverName="AssignableAutoroutingPipeline2":solverName="AutoroutingPipelineSolver7_MultiGraph";let SolverClass=SOLVERS[solverName],solverCacheProvider=getCapacityAutorouterCacheProvider(platformConfig2);this.solver=new SolverClass(input2,{capacityDepth,targetMinCapacity,cacheProvider:solverCacheProvider,effort}),onSolverStarted?.({solverName,solverParams:{input:input2,options:{capacityDepth,targetMinCapacity,cacheProvider:solverCacheProvider,effort}}}),this.stepDelay=stepDelay}start(){this.isRouting||(this.isRouting=!0,this.cycleCount=0,this.runCycleAndQueueNextCycle())}async stepSolver(){if("stepAsync"in this.solver&&typeof this.solver.stepAsync=="function"){await this.solver.stepAsync();return}this.solver.step()}async runCycleAndQueueNextCycle(){if(this.isRouting)try{if(this.solver.solved||this.solver.failed){this.solver.failed?this.emitEvent({type:"error",error:new AutorouterError(this.solver.error||"Routing failed")}):this.emitEvent({type:"complete",traces:this.solver.getOutputSimpleRouteJson().traces||[]}),this.isRouting=!1;return}let startTime=Date.now(),startIterations=this.solver.iterations;for(;Date.now()-startTime<250&&!this.solver.failed&&!this.solver.solved;)await this.stepSolver();let iterationsPerSecond=(this.solver.iterations-startIterations)/(Date.now()-startTime)*1e3;this.cycleCount++;let debugGraphics=this.solver?.preview()||void 0,progress=this.solver.progress;this.emitEvent({type:"progress",steps:this.cycleCount,iterationsPerSecond,progress,phase:this.solver.getCurrentPhase(),debugGraphics}),this.stepDelay>0?this.timeoutId=setTimeout(()=>{this.runCycleAndQueueNextCycle()},this.stepDelay):this.timeoutId=setTimeout(()=>{this.runCycleAndQueueNextCycle()},0)}catch(error2){this.emitEvent({type:"error",error:error2 instanceof Error?new AutorouterError(error2.message):new AutorouterError(String(error2))}),this.isRouting=!1}}stop(){this.isRouting&&(this.isRouting=!1,this.timeoutId!==void 0&&(clearTimeout(this.timeoutId),this.timeoutId=void 0))}on(event,callback){event==="complete"?this.eventHandlers.complete.push(callback):event==="error"?this.eventHandlers.error.push(callback):event==="progress"&&this.eventHandlers.progress.push(callback)}emitEvent(event){if(event.type==="complete")for(let handler of this.eventHandlers.complete)handler(event);else if(event.type==="error")for(let handler of this.eventHandlers.error)handler(event);else if(event.type==="progress")for(let handler of this.eventHandlers.progress)handler(event)}solveSync(){if(this.solver.solve(),this.solver.failed)throw new AutorouterError(this.solver.error||"Routing failed");return this.solver.getOutputSimpleRouteJson().traces||[]}getConnectedOffboardObstacles(){return"getConnectedOffboardObstacles"in this.solver?this.solver.getConnectedOffboardObstacles():{}}},defaultLocalAutorouterStrategy={cacheable:!0,create:({simpleRouteJson,commonAutorouterOptions,onSolverStarted})=>new TscircuitAutorouter(simpleRouteJson,{...commonAutorouterOptions,onSolverStarted:details=>onSolverStarted?.({...details,solverConstructorArgs:[details.solverParams]})})},createFanoutAutorouterStrategy=mode=>({cacheable:!1,followUpAutorouter:"default",create:({simpleRouteJson,busFanoutDirections,fanoutBounds,fanoutRoutingLayers,componentNamesById,onSolverStarted})=>new FanoutAutorouter(simpleRouteJson,{mode,busFanoutDirections,fanoutBounds,fanoutRoutingLayers,componentNamesById,onSolverStarted})}),localAutorouterStrategies=new Map([["single_layer_fanout",createFanoutAutorouterStrategy("single_layer_fanout")],["fanout",createFanoutAutorouterStrategy("fanout")]]),getLocalAutorouterStrategy=preset=>localAutorouterStrategies.get(preset??"")??defaultLocalAutorouterStrategy,getLocalAutoroutingStages=(autorouterConfig2,platformConfig2)=>{let strategy=getLocalAutorouterStrategy(autorouterConfig2.preset),stages=[{autorouterConfig:autorouterConfig2,strategy,usesPreviousStageOutput:!1}];if(strategy.followUpAutorouter){let followUpAutorouterConfig=getPresetAutoroutingConfig(strategy.followUpAutorouter,platformConfig2);stages.push({autorouterConfig:followUpAutorouterConfig,strategy:getLocalAutorouterStrategy(followUpAutorouterConfig.preset),usesPreviousStageOutput:!0})}return stages},applyPcbEditEventsToManualEditsFile=({circuitJson,editEvents,manualEditsFile})=>{let updatedManualEditsFile={...manualEditsFile,pcb_placements:[...manualEditsFile.pcb_placements??[]]};for(let editEvent of editEvents)if(editEvent.edit_event_type==="edit_pcb_component_location"){let{pcb_component_id,new_center}=editEvent,pcb_component3=su2(circuitJson).pcb_component.get(pcb_component_id);if(!pcb_component3)continue;let source_component=su2(circuitJson).source_component.get(pcb_component3.source_component_id);if(!source_component)continue;let existingPlacementIndex=updatedManualEditsFile.pcb_placements?.findIndex(p3=>p3.selector===source_component.name),newPlacement={selector:source_component.name,center:new_center,relative_to:"group_center"};existingPlacementIndex>=0?updatedManualEditsFile.pcb_placements[existingPlacementIndex]=newPlacement:updatedManualEditsFile.pcb_placements.push(newPlacement)}return updatedManualEditsFile},applySchematicEditEventsToManualEditsFile=({circuitJson,editEvents,manualEditsFile})=>{let updatedManualEditsFile={...manualEditsFile,schematic_placements:[...manualEditsFile.schematic_placements??[]]};for(let editEvent of editEvents)if(editEvent.edit_event_type==="edit_schematic_component_location"){let{schematic_component_id,new_center}=editEvent,schematic_component22=su2(circuitJson).schematic_component.get(schematic_component_id);if(!schematic_component22||!schematic_component22.source_component_id)continue;let source_component=su2(circuitJson).source_component.get(schematic_component22.source_component_id);if(!source_component)continue;let existingPlacementIndex=updatedManualEditsFile.schematic_placements?.findIndex(p3=>p3.selector===source_component.name),newPlacement={selector:source_component.name,center:new_center,relative_to:"group_center"};existingPlacementIndex>=0?updatedManualEditsFile.schematic_placements[existingPlacementIndex]=newPlacement:updatedManualEditsFile.schematic_placements.push(newPlacement)}return updatedManualEditsFile},applyEditEventsToManualEditsFile=({circuitJson,editEvents,manualEditsFile})=>{let schematicEditEvents=editEvents.filter(event=>event.edit_event_type==="edit_schematic_component_location"),pcbEditEvents=editEvents.filter(event=>event.edit_event_type==="edit_pcb_component_location"),updatedManualEditsFile=manualEditsFile;return schematicEditEvents.length>0&&(updatedManualEditsFile=applySchematicEditEventsToManualEditsFile({circuitJson,editEvents:schematicEditEvents,manualEditsFile:updatedManualEditsFile})),pcbEditEvents.length>0&&(updatedManualEditsFile=applyPcbEditEventsToManualEditsFile({circuitJson,editEvents:pcbEditEvents,manualEditsFile:updatedManualEditsFile})),updatedManualEditsFile},applyTraceHintEditEvent=(circuitJson,edit_event)=>{if(su2(circuitJson).pcb_trace_hint.get(edit_event.pcb_trace_hint_id))circuitJson=circuitJson.map(e6=>e6.pcb_trace_hint_id===edit_event.pcb_trace_hint_id?{...e6,route:edit_event.route}:e6);else{let pcbPort=su2(circuitJson).pcb_port.get(edit_event.pcb_port_id);circuitJson=circuitJson.filter(e6=>!(e6.type==="pcb_trace_hint"&&e6.pcb_port_id===edit_event.pcb_port_id)).concat([{type:"pcb_trace_hint",pcb_trace_hint_id:edit_event.pcb_trace_hint_id,route:edit_event.route,pcb_port_id:edit_event.pcb_port_id,pcb_component_id:pcbPort?.pcb_component_id}])}return circuitJson},applyEditEvents=({circuitJson,editEvents})=>{circuitJson=JSON.parse(JSON.stringify(circuitJson));for(let editEvent of editEvents)if(editEvent.edit_event_type==="edit_pcb_component_location"){let component=circuitJson.find(e6=>e6.type==="pcb_component"&&e6.pcb_component_id===editEvent.pcb_component_id);if((!component||component.center.x!==editEvent.new_center.x||component.center.y!==editEvent.new_center.y)&&editEvent.original_center){let mat=translate2(editEvent.new_center.x-editEvent.original_center.x,editEvent.new_center.y-editEvent.original_center.y);circuitJson=circuitJson.map(e6=>e6.pcb_component_id!==editEvent.pcb_component_id?e6:transformPCBElement(e6,mat))}}else editEvent.edit_event_type==="edit_schematic_component_location"?circuitJson=circuitJson.map(e6=>e6.type==="schematic_component"&&e6.schematic_component_id===editEvent.schematic_component_id?{...e6,center:editEvent.new_center}:e6):editEvent.edit_event_type==="edit_pcb_trace_hint"&&(circuitJson=applyTraceHintEditEvent(circuitJson,editEvent));return circuitJson},Bus=class extends PrimitiveComponent2{get config(){return{componentName:"Bus",zodProps:busProps}}},resolvePointToPointConnection=(differentialPair,connectionSelector)=>{let{db:db2}=differentialPair.root,subcircuit=differentialPair.getSubcircuit(),matchingSourceTraces=db2.source_trace.list().filter(sourceTrace=>sourceTrace.subcircuit_id===subcircuit.subcircuit_id).filter(sourceTrace=>sourceTrace.name===connectionSelector),connectivityMapKeys=new Set;if(matchingSourceTraces.length>0)for(let sourceTrace of matchingSourceTraces)sourceTrace.subcircuit_connectivity_map_key&&connectivityMapKeys.add(sourceTrace.subcircuit_connectivity_map_key);else{let selectedPort=subcircuit.selectOne(connectionSelector,{type:"port"});if(selectedPort?.source_port_id){let sourcePort=db2.source_port.get(selectedPort.source_port_id);sourcePort?.subcircuit_connectivity_map_key&&connectivityMapKeys.add(sourcePort.subcircuit_connectivity_map_key)}}if(connectivityMapKeys.size!==1)return;let connectivityMapKey=connectivityMapKeys.values().next().value;return connectivityMapKey?{sourcePorts:db2.source_port.list().filter(sourcePort=>sourcePort.subcircuit_connectivity_map_key===connectivityMapKey),sourceTraceName:matchingSourceTraces.length>0?connectionSelector:void 0}:void 0},formatTerminalPinList=terminalPinSelectors=>terminalPinSelectors.length<=1?terminalPinSelectors.join(""):terminalPinSelectors.length===2?`${terminalPinSelectors[0]} and ${terminalPinSelectors[1]}`:`${terminalPinSelectors.slice(0,-1).join(", ")}, and ${terminalPinSelectors.at(-1)}`,getTerminalPinSelector=(sourcePort,sourceComponentsById)=>{let sourceComponent;if(sourcePort.source_component_id&&(sourceComponent=sourceComponentsById.get(sourcePort.source_component_id)),!sourceComponent?.name)return sourcePort.source_port_id;let portName=sourcePort.most_frequently_referenced_by_name??sourcePort.name;return`.${sourceComponent.name} > .${portName}`},getPointToPointWarningMessage=({differentialPairName,connectionPolarity,connectionSelector,sourceTraceName,terminalPinSelectors})=>{let terminalList=formatTerminalPinList(terminalPinSelectors),terminalListDescription=terminalList?`: ${terminalList}`:"";return sourceTraceName&&terminalPinSelectors.length>2?`Differential pair "${differentialPairName}" ${connectionPolarity}Connection uses the ambiguous trace name "${sourceTraceName}": its connection has more than 2 terminal pins${terminalListDescription}.`:`Differential pair "${differentialPairName}" ${connectionPolarity}Connection="${connectionSelector}" is not point-to-point: expected exactly 2 terminal pins, found ${terminalPinSelectors.length}${terminalListDescription}.`},DifferentialPair_doInitialSourceDesignRuleChecks=differentialPair=>{let{db:db2}=differentialPair.root,sourceComponentsById=new Map;for(let sourceComponent of db2.source_component.list())sourceComponentsById.set(sourceComponent.source_component_id,{name:sourceComponent.name});for(let connectionPolarity of["positive","negative"]){let connectionSelector=differentialPair._parsedProps.negativeConnection;connectionPolarity==="positive"&&(connectionSelector=differentialPair._parsedProps.positiveConnection);let resolvedConnection=resolvePointToPointConnection(differentialPair,connectionSelector);if(!resolvedConnection)continue;let terminalSourcePorts=resolvedConnection.sourcePorts;if(terminalSourcePorts.length===2)continue;let warningSourceComponentId="",firstTerminalSourcePort=terminalSourcePorts[0];if(firstTerminalSourcePort){if(!firstTerminalSourcePort.source_component_id)throw new Error(`Differential pair "${differentialPair.name}" resolved terminal port "${firstTerminalSourcePort.source_port_id}" without a source_component_id`);warningSourceComponentId=firstTerminalSourcePort.source_component_id}let terminalPinSelectors=terminalSourcePorts.map(sourcePort=>getTerminalPinSelector(sourcePort,sourceComponentsById)).sort((selectorA,selectorB)=>selectorA.localeCompare(selectorB));db2.source_property_ignored_warning.insert({source_component_id:warningSourceComponentId,property_name:`${connectionPolarity}Connection`,error_type:"source_property_ignored_warning",message:getPointToPointWarningMessage({differentialPairName:differentialPair.name,connectionPolarity,connectionSelector,sourceTraceName:resolvedConnection.sourceTraceName,terminalPinSelectors}),subcircuit_id:differentialPair.getSubcircuit().subcircuit_id??void 0})}},DifferentialPair=class extends PrimitiveComponent2{get config(){return{componentName:"DifferentialPair",zodProps:differentialPairProps}}doInitialSourceDesignRuleChecks(){DifferentialPair_doInitialSourceDesignRuleChecks(this)}},expandSrjBoundsToIncludeConnectionPoints=input2=>{let expandedBounds={...input2.bounds};for(let connection of input2.connections)if(!connection.isOffBoard)for(let point6 of connection.pointsToConnect)expandedBounds.minX=Math.min(expandedBounds.minX,point6.x),expandedBounds.maxX=Math.max(expandedBounds.maxX,point6.x),expandedBounds.minY=Math.min(expandedBounds.minY,point6.y),expandedBounds.maxY=Math.max(expandedBounds.maxY,point6.y);return expandedBounds},getBusSourceTraceSubcircuitConnectivityMapKeyOrThrow=({bus,busSourceTraces,traceNameOrPortSelector})=>{let sourceTracesWithMatchingName=busSourceTraces.filter(sourceTrace2=>sourceTrace2.name===traceNameOrPortSelector),selectedSourcePortId=(sourceTracesWithMatchingName.length===0?bus.getSubcircuit().selectOne(traceNameOrPortSelector,{type:"port"}):null)?.source_port_id??void 0,matchingSourceTraces=selectedSourcePortId?busSourceTraces.filter(sourceTrace2=>sourceTrace2.connected_source_port_ids.includes(selectedSourcePortId)):sourceTracesWithMatchingName;if(matchingSourceTraces.length===0)throw new Error(`Could not find source trace for trace name or port selector "${traceNameOrPortSelector}" in bus "${bus.name}"`);if(matchingSourceTraces.length>1)throw new Error(`Trace name or port selector "${traceNameOrPortSelector}" matches multiple source traces in bus "${bus.name}"`);let sourceTrace=matchingSourceTraces[0];if(!sourceTrace?.subcircuit_connectivity_map_key)throw new Error(`Source trace for "${traceNameOrPortSelector}" does not have a subcircuit connectivity map key in bus "${bus.name}"`);return sourceTrace.subcircuit_connectivity_map_key},getBusSrjConnectionNamesOrThrow=({srjConnections,bus,busSourceTraces,traceSubcircuitConnectivityMapKey,traceNameOrPortSelector})=>{let sourceTraceIds=busSourceTraces.filter(sourceTrace=>sourceTrace.subcircuit_connectivity_map_key===traceSubcircuitConnectivityMapKey).map(sourceTrace=>sourceTrace.source_trace_id),matchingSrjConnections=srjConnections.filter(srjConnection=>srjConnection.source_trace_id&&sourceTraceIds.includes(srjConnection.source_trace_id));if(matchingSrjConnections.length===0)throw new Error(`Could not find an SRJ connection for "${traceNameOrPortSelector}" in bus "${bus.name}"`);return matchingSrjConnections.map(srjConnection=>srjConnection.name)},normalizeNetName=netNameOrSelector=>netNameOrSelector.trim().replace(/^net\./,"").replace(/^\./,""),getPlaneTerminatedSourceTraceLayers=({fanoutPourNetMap,sourceNets,sourceTraces,subcircuitId})=>{let traceLayers=new Map;if(!fanoutPourNetMap)return traceLayers;let planeLayerBySourceNetId=new Map;for(let[layer,netOrNets]of Object.entries(fanoutPourNetMap)){let netNames=Array.isArray(netOrNets)?netOrNets:[netOrNets];for(let netNameOrSelector of netNames){let netName=normalizeNetName(netNameOrSelector);for(let sourceNet of sourceNets){if(sourceNet.name!==netName)continue;let previousLayer=planeLayerBySourceNetId.get(sourceNet.source_net_id);if(previousLayer&&previousLayer!==layer)throw new Error(`Fanout plane net "${netName}" maps to multiple layers ("${previousLayer}" and "${layer}"); use fanoutPourNetMap to select one`);planeLayerBySourceNetId.set(sourceNet.source_net_id,layer)}}}for(let sourceTrace of sourceTraces){if(subcircuitId&&sourceTrace.subcircuit_id!==subcircuitId||sourceTrace.connected_source_port_ids.length!==1)continue;let mappedLayers=new Set((sourceTrace.connected_source_net_ids??[]).map(sourceNetId=>planeLayerBySourceNetId.get(sourceNetId)).filter(layer2=>layer2!==void 0));if(mappedLayers.size>1)throw new Error(`Source trace "${sourceTrace.name??sourceTrace.source_trace_id}" connects to fanout planes on multiple layers`);let layer=mappedLayers.values().next().value;layer&&traceLayers.set(sourceTrace.source_trace_id,layer)}return traceLayers},getBusesForSimpleRouteJson=({srjConnections,buses,sourceTraces,subcircuitId,planeTerminatedSourceTraceLayers})=>{let declaredSrjBuses=[];for(let bus of buses){let busSubcircuitId=bus.getSubcircuit().subcircuit_id;if(subcircuitId&&busSubcircuitId!==subcircuitId)continue;let busSourceTraces=sourceTraces.filter(sourceTrace=>sourceTrace.subcircuit_id===busSubcircuitId),connectionNames=bus._parsedProps.connections.flatMap(traceNameOrPortSelector=>{let traceSubcircuitConnectivityMapKey=getBusSourceTraceSubcircuitConnectivityMapKeyOrThrow({bus,busSourceTraces,traceNameOrPortSelector});return getBusSrjConnectionNamesOrThrow({srjConnections,bus,busSourceTraces,traceSubcircuitConnectivityMapKey,traceNameOrPortSelector})});if(new Set(connectionNames).size!==connectionNames.length)throw new Error(`Bus "${bus.name}" resolves multiple entries to one trace`);declaredSrjBuses.push({busId:bus.name,name:bus.name,connectionNames,...bus._parsedProps.maxLengthSkew!==void 0?{maxLengthSkew:bus._parsedProps.maxLengthSkew}:{},...bus._parsedProps.pcbTraceWidth!==void 0?{traceWidth:bus._parsedProps.pcbTraceWidth}:{},...bus._parsedProps.pcbAllowedLayers!==void 0?{allowedLayers:bus._parsedProps.pcbAllowedLayers}:{},...bus._parsedProps.preferredLayer!==void 0?{preferredLayer:bus._parsedProps.preferredLayer}:{},...bus._parsedProps.preferredLayers!==void 0?{preferredLayers:bus._parsedProps.preferredLayers}:{}})}let planeSrjBuses=[];for(let[sourceTraceId,layer]of planeTerminatedSourceTraceLayers??[]){let sourceTrace=sourceTraces.find(candidate=>candidate.source_trace_id===sourceTraceId),srjConnection=srjConnections.find(connection=>connection.source_trace_id===sourceTraceId);if(!sourceTrace||!srjConnection)continue;let busId=sourceTrace.name??sourceTrace.source_trace_id;if([...declaredSrjBuses,...planeSrjBuses].some(bus=>bus.busId===busId))throw new Error(`Fanout plane trace "${busId}" conflicts with an existing bus name`);planeSrjBuses.push({busId,name:busId,connectionNames:[srjConnection.name],termination:{type:"plane",layer}})}let srjBuses=[...planeSrjBuses,...declaredSrjBuses];return srjBuses.length>0?srjBuses:void 0},getDifferentialPairSourceTracesByTraceName=(differentialPairSourceTraces,traceName)=>differentialPairSourceTraces.filter(sourceTrace=>sourceTrace.name===traceName),getDifferentialPairSourceTracesByPortId=(differentialPairSourceTraces,sourcePortId)=>differentialPairSourceTraces.filter(sourceTrace=>sourceTrace.connected_source_port_ids.includes(sourcePortId)),getDifferentialPairTraceSubcircuitConnectivityMapKeyOrThrow=({differentialPair,differentialPairSourceTraces,traceNameOrPortSelector})=>{let differentialPairSubcircuit=differentialPair.getSubcircuit(),sourceTracesWithMatchingName=getDifferentialPairSourceTracesByTraceName(differentialPairSourceTraces,traceNameOrPortSelector),selectedSourcePortId=(sourceTracesWithMatchingName.length===0?differentialPairSubcircuit.selectOne(traceNameOrPortSelector,{type:"port"}):null)?.source_port_id??void 0,matchingSourceTraces=selectedSourcePortId?getDifferentialPairSourceTracesByPortId(differentialPairSourceTraces,selectedSourcePortId):sourceTracesWithMatchingName;if(matchingSourceTraces.length===0)throw new Error(`Could not find source trace for trace name or port selector "${traceNameOrPortSelector}" in differential pair "${differentialPair.name}"`);if(matchingSourceTraces.length>1)throw new Error(`Trace name or port selector "${traceNameOrPortSelector}" matches multiple source traces for differential pair "${differentialPair.name}"`);let sourceTrace=matchingSourceTraces[0];if(!sourceTrace)throw new Error(`Expected one source trace for trace name or port selector "${traceNameOrPortSelector}" in differential pair "${differentialPair.name}"`);let subcircuitConnectivityMapKey=sourceTrace.subcircuit_connectivity_map_key;if(!subcircuitConnectivityMapKey)throw new Error(`Source trace "${sourceTrace.source_trace_id}" does not have a subcircuit connectivity map key for differential pair "${differentialPair.name}"`);return subcircuitConnectivityMapKey},getDifferentialPairSrjConnectionNameOrThrow=({srjConnections,differentialPairName,differentialPairSourceTraces,traceSubcircuitConnectivityMapKey,traceNameOrPortSelector})=>{let differentialPairSourceTraceIds=[];for(let sourceTrace of differentialPairSourceTraces)sourceTrace.subcircuit_connectivity_map_key===traceSubcircuitConnectivityMapKey&&differentialPairSourceTraceIds.push(sourceTrace.source_trace_id);let matchingSrjConnections=[];for(let srjConnection2 of srjConnections)srjConnection2.source_trace_id&&differentialPairSourceTraceIds.includes(srjConnection2.source_trace_id)&&matchingSrjConnections.push(srjConnection2);if(matchingSrjConnections.length===0)throw new Error(`Could not find an SRJ connection for trace name or port selector "${traceNameOrPortSelector}" in differential pair "${differentialPairName}"`);if(matchingSrjConnections.length>1)throw new Error(`Subcircuit connectivity map key "${traceSubcircuitConnectivityMapKey}" matches multiple SRJ connections for differential pair "${differentialPairName}"`);let srjConnection=matchingSrjConnections[0];if(!srjConnection)throw new Error(`Expected one SRJ connection for subcircuit connectivity map key "${traceSubcircuitConnectivityMapKey}"`);return srjConnection.name},getDifferentialPairsForSimpleRouteJson=({srjConnections,differentialPairs,sourceTraces,subcircuitId})=>{let srjDifferentialPairs=[];for(let differentialPair of differentialPairs){let differentialPairSubcircuitId=differentialPair.getSubcircuit().subcircuit_id;if(subcircuitId&&differentialPairSubcircuitId!==subcircuitId)continue;let differentialPairSourceTraces=sourceTraces.filter(sourceTrace=>sourceTrace.subcircuit_id===differentialPairSubcircuitId),positiveTraceNameOrPortSelector=differentialPair._parsedProps.positiveConnection,negativeTraceNameOrPortSelector=differentialPair._parsedProps.negativeConnection,positiveSubcircuitConnectivityMapKey=getDifferentialPairTraceSubcircuitConnectivityMapKeyOrThrow({differentialPair,differentialPairSourceTraces,traceNameOrPortSelector:positiveTraceNameOrPortSelector}),negativeSubcircuitConnectivityMapKey=getDifferentialPairTraceSubcircuitConnectivityMapKeyOrThrow({differentialPair,differentialPairSourceTraces,traceNameOrPortSelector:negativeTraceNameOrPortSelector}),positiveSrjConnectionName=getDifferentialPairSrjConnectionNameOrThrow({srjConnections,differentialPairName:differentialPair.name,differentialPairSourceTraces,traceSubcircuitConnectivityMapKey:positiveSubcircuitConnectivityMapKey,traceNameOrPortSelector:positiveTraceNameOrPortSelector}),negativeSrjConnectionName=getDifferentialPairSrjConnectionNameOrThrow({srjConnections,differentialPairName:differentialPair.name,differentialPairSourceTraces,traceSubcircuitConnectivityMapKey:negativeSubcircuitConnectivityMapKey,traceNameOrPortSelector:negativeTraceNameOrPortSelector}),lengthTolerance=differentialPair._parsedProps.maxLengthSkew??.1;srjDifferentialPairs.push({connectionNames:[positiveSrjConnectionName,negativeSrjConnectionName],lengthTolerance,...differentialPair._parsedProps.pcbTraceGap!==void 0?{traceGap:differentialPair._parsedProps.pcbTraceGap}:{},...differentialPair._parsedProps.maxUncoupledLength!==void 0?{maxUncoupledLength:differentialPair._parsedProps.maxUncoupledLength}:{}})}return srjDifferentialPairs.length>0?srjDifferentialPairs:void 0},getLayerName=layer=>typeof layer=="string"?layer:layer.name,getPreservedTraceConnectionName=trace=>trace.source_trace_id??trace.connection_name??trace.pcb_trace_id,getPhysicalConnectionIdsForPreservedTrace=trace=>{let physicallyConnectedIds=new Set(trace.connectsTo??[]);for(let routePoint of trace.route)if(routePoint.route_type==="wire")for(let pcbPortId of[routePoint.start_pcb_port_id,routePoint.end_pcb_port_id])pcbPortId&&physicallyConnectedIds.add(pcbPortId);return Array.from(physicallyConnectedIds)},getSimpleRouteForPreservedTrace=trace=>trace.route.map(routePoint=>{if(routePoint.route_type==="wire")return{route_type:"wire",x:routePoint.x,y:routePoint.y,width:routePoint.width,layer:getLayerName(routePoint.layer)};if(routePoint.route_type==="via"){let preservedViaRoutePoint=routePoint,viaDiameter=preservedViaRoutePoint.outer_diameter??preservedViaRoutePoint.via_diameter,viaHoleDiameter=preservedViaRoutePoint.hole_diameter??preservedViaRoutePoint.via_hole_diameter;return{route_type:"via",x:routePoint.x,y:routePoint.y,from_layer:getLayerName(routePoint.from_layer),to_layer:getLayerName(routePoint.to_layer),...viaDiameter!==void 0?{via_diameter:viaDiameter}:{},...viaHoleDiameter!==void 0?{via_hole_diameter:viaHoleDiameter}:{}}}return{route_type:"through_obstacle",start:routePoint.start,end:routePoint.end,from_layer:getLayerName(routePoint.start_layer),to_layer:getLayerName(routePoint.end_layer),width:routePoint.width}}),getPreservedRoutedSubcircuitTraces=({scopedDb,relevantSubcircuitIds})=>scopedDb.pcb_trace.list().filter(trace=>trace.subcircuit_id?relevantSubcircuitIds===null||relevantSubcircuitIds.has(trace.subcircuit_id):!1).map(trace=>{let preservedTrace=trace,connectionName=getPreservedTraceConnectionName(preservedTrace);return{type:"pcb_trace",pcb_trace_id:trace.pcb_trace_id,source_trace_id:trace.source_trace_id,connection_name:connectionName,connectsTo:getPhysicalConnectionIdsForPreservedTrace(preservedTrace),route:getSimpleRouteForPreservedTrace(preservedTrace)}}).filter(trace=>trace.route.length>=2),COPPER_POUR_RECT_HEIGHT=.5,dedupeStrings2=values=>Array.from(new Set(values.filter(value=>!!value))),getLayerName2=layer=>typeof layer=="string"?layer:layer.name,createCopperPourObstacle=({layer,connectedTo,center:center2,width,height})=>({type:"rect",layers:[layer],center:center2,width,height,connectedTo,isCopperPour:!0}),getCopperPourBoundary=({outline,group,board})=>outline&&outline.length>=3?outline:group?.outline&&group.outline.length>=3?group.outline:board?.outline&&board.outline.length>=3?board.outline:null,getCopperPourBoundsRect=({group,board})=>group?.width&&group.height?{center:group.center,width:group.width,height:group.height}:board?.width&&board.height?{center:board.center,width:board.width,height:board.height}:null,getCopperPourConnectedTo=(net,connMap)=>dedupeStrings2([net.source_net_id,net.subcircuit_connectivity_map_key,net.source_net_id?connMap.getNetConnectedToId(net.source_net_id):null]),getUnbrokenCopperPourObstacles=({connMap,subcircuitComponent,board,group})=>{if(!subcircuitComponent)return[];let obstacles=[],copperPours=subcircuitComponent.selectAll("copperpour");for(let copperPour of copperPours){let props=copperPour._parsedProps;if(!props.unbroken)continue;let net=copperPour.getSubcircuit().selectOne(props.connectsTo);if(!net?.source_net_id)continue;let layer=getLayerName2(props.layer),connectedTo=getCopperPourConnectedTo(net,connMap);if(connectedTo.length===0)continue;let boundary=getCopperPourBoundary({outline:props.outline,group,board});if(boundary){let rects=fillPolygonWithRects(boundary,{rectHeight:COPPER_POUR_RECT_HEIGHT});if(rects.length>0){obstacles.push(...rects.map(rect=>createCopperPourObstacle({layer,connectedTo,center:rect.center,width:rect.width,height:rect.height})));continue}}let boundsRect=getCopperPourBoundsRect({group,board});boundsRect&&obstacles.push(createCopperPourObstacle({layer,connectedTo,center:boundsRect.center,width:boundsRect.width,height:boundsRect.height}))}return obstacles},getSimpleRouteJsonFromCircuitJson=({db:db2,circuitJson,subcircuit_id,minTraceWidth,minTraceToPadEdgeClearance,minViaEdgeToPadEdgeClearance,minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance,minPadEdgeToPadEdgeClearance,minBoardEdgeClearance,minViaHoleDiameter,minViaPadDiameter,nominalTraceWidth,subcircuitComponent,routingPcbGroupId,fanoutPourNetMap,ignoreExistingTopLevelPcbRouteState=!1})=>{if(!db2&&circuitJson&&(db2=su2(circuitJson)),!db2)throw new Error("db or circuitJson is required");let traceHints=db2.pcb_trace_hint.list(),relevantSubcircuitIds=subcircuit_id?new Set([subcircuit_id]):null;if(subcircuit_id){let descendantSubcircuitIds=getDescendantSubcircuitIds2(db2,subcircuit_id);for(let id3 of descendantSubcircuitIds)relevantSubcircuitIds.add(id3)}let subcircuitElements=(circuitJson??db2.toArray()).filter(e6=>!subcircuit_id||"subcircuit_id"in e6&&relevantSubcircuitIds.has(e6.subcircuit_id)),board=null,subcircuitIsBoard=!1;if(subcircuit_id){let source_group_id=subcircuit_id.replace(/^subcircuit_/,""),source_board3=db2.source_board.getWhere({source_group_id});source_board3&&(board=db2.pcb_board.getWhere({source_board_id:source_board3.source_board_id}),board&&(subcircuitIsBoard=!0))}board||(board=db2.pcb_board.list()[0]),db2=su2(subcircuitElements);let getPortSelector=sourcePort=>{if(!sourcePort?.source_component_id)return;let sourceComponent=db2.source_component.get(sourcePort.source_component_id);if(sourceComponent?.name)return`${sourceComponent.name}.${sourcePort.name}`},pcbGroup;routingPcbGroupId?pcbGroup=db2.pcb_group.get(routingPcbGroupId):subcircuit_id&&(pcbGroup=db2.pcb_group.getWhere({subcircuit_id}));let activeRoutingPcbGroupId=subcircuitComponent?.pcb_group_id;activeRoutingPcbGroupId==null&&!subcircuitIsBoard&&(activeRoutingPcbGroupId=pcbGroup?.pcb_group_id);let sharedConnMap=getFullConnectivityMapFromCircuitJson(subcircuitElements),breakoutPoints=db2.pcb_breakout_point.list().filter(bp3=>!subcircuit_id||relevantSubcircuitIds?.has(bp3.subcircuit_id)),breakoutPointIsInActiveRoutingGroup=breakoutPoint=>breakoutPoint.subcircuit_id===subcircuit_id&&(activeRoutingPcbGroupId?breakoutPoint.pcb_group_id===activeRoutingPcbGroupId:!subcircuitIsBoard),preservedRoutedSubcircuitTraces=getPreservedRoutedSubcircuitTraces({scopedDb:db2,relevantSubcircuitIds}),preservedSrjTraceByPcbTraceId=new Map(preservedRoutedSubcircuitTraces.map(trace=>[trace.pcb_trace_id,trace])),isPcbViaRepresentedByPreservedSrjTrace=via=>{if(!via.pcb_trace_id)return!1;let preservedTrace=preservedSrjTraceByPcbTraceId.get(via.pcb_trace_id);if(!preservedTrace)return!1;let pcbViaLayerNames=new Set(via.layers);return preservedTrace.route.some(routePoint=>{if(routePoint.route_type!=="via"||routePoint.x!==via.x||routePoint.y!==via.y)return!1;let routeViaLayerNames=new Set(getViaSpanLayers({fromLayer:routePoint.from_layer,toLayer:routePoint.to_layer,layerCount:board?.num_layers??2}));return routeViaLayerNames.size===pcbViaLayerNames.size&&[...routeViaLayerNames].every(layer=>pcbViaLayerNames.has(layer))})},obstacles=getObstaclesFromCircuitJson2([...board?[board]:[],...db2.source_component.list(),...db2.source_port.list(),...db2.pcb_port.list(),...db2.pcb_component.list(),...db2.pcb_smtpad.list(),...db2.pcb_plated_hole.list(),...db2.pcb_hole.list(),...db2.pcb_trace.list().filter(trace=>!trace.source_trace_id),...db2.pcb_via.list().filter(via=>(!ignoreExistingTopLevelPcbRouteState||!!via.subcircuit_id)&&!isPcbViaRepresentedByPreservedSrjTrace(via)),...db2.pcb_keepout.list(),...db2.pcb_cutout.list()].filter(e6=>e6.type==="pcb_board"||!subcircuit_id||relevantSubcircuitIds?.has(e6.subcircuit_id)),sharedConnMap);obstacles.push(...getUnbrokenCopperPourObstacles({connMap:sharedConnMap,subcircuitComponent,board,group:pcbGroup}));for(let obstacle of obstacles){let additionalIds=obstacle.connectedTo.flatMap(id3=>sharedConnMap.getIdsConnectedToNet(id3));obstacle.connectedTo.push(...additionalIds)}let internalConnections=db2.source_component_internal_connection.list(),sourcePortIdToInternalConnectionId=new Map;for(let ic3 of internalConnections)for(let sourcePortId of ic3.source_port_ids)sourcePortIdToInternalConnectionId.set(sourcePortId,ic3.source_component_internal_connection_id);let pcbElementIdToSourcePortId=new Map;for(let pcbPort of db2.pcb_port.list())if(pcbPort.source_port_id){let smtpad2=db2.pcb_smtpad.getWhere({pcb_port_id:pcbPort.pcb_port_id});smtpad2&&pcbElementIdToSourcePortId.set(smtpad2.pcb_smtpad_id,pcbPort.source_port_id);let platedHole=db2.pcb_plated_hole.getWhere({pcb_port_id:pcbPort.pcb_port_id});platedHole&&pcbElementIdToSourcePortId.set(platedHole.pcb_plated_hole_id,pcbPort.source_port_id)}for(let obstacle of obstacles)for(let connectedId of obstacle.connectedTo){let sourcePortId=pcbElementIdToSourcePortId.get(connectedId);if(sourcePortId){let internalConnectionId=sourcePortIdToInternalConnectionId.get(sourcePortId);if(internalConnectionId){obstacle.offBoardConnectsTo=[internalConnectionId],obstacle.netIsAssignable=!0;break}}}let allPoints=obstacles.flatMap(o6=>[{x:o6.center.x-o6.width/2,y:o6.center.y-o6.height/2},{x:o6.center.x+o6.width/2,y:o6.center.y+o6.height/2}]).concat(board?.outline??[]),bounds,useGroupBoundsAsSrjBounds=!!(pcbGroup?.width&&pcbGroup.height&&subcircuit_id&&!subcircuitIsBoard);if(useGroupBoundsAsSrjBounds?bounds={minX:pcbGroup.center.x-pcbGroup.width/2,maxX:pcbGroup.center.x+pcbGroup.width/2,minY:pcbGroup.center.y-pcbGroup.height/2,maxY:pcbGroup.center.y+pcbGroup.height/2}:board&&!board.outline?bounds={minX:board.center.x-board.width/2,maxX:board.center.x+board.width/2,minY:board.center.y-board.height/2,maxY:board.center.y+board.height/2}:bounds={minX:Math.min(...allPoints.map(p3=>p3.x))-1,maxX:Math.max(...allPoints.map(p3=>p3.x))+1,minY:Math.min(...allPoints.map(p3=>p3.y))-1,maxY:Math.max(...allPoints.map(p3=>p3.y))+1},pcbGroup?.width&&pcbGroup.height&&!useGroupBoundsAsSrjBounds){let groupBounds={minX:pcbGroup.center.x-pcbGroup.width/2,maxX:pcbGroup.center.x+pcbGroup.width/2,minY:pcbGroup.center.y-pcbGroup.height/2,maxY:pcbGroup.center.y+pcbGroup.height/2};bounds={minX:Math.min(bounds.minX,groupBounds.minX),maxX:Math.max(bounds.maxX,groupBounds.maxX),minY:Math.min(bounds.minY,groupBounds.minY),maxY:Math.max(bounds.maxY,groupBounds.maxY)}}let sourceTraceIdsAlreadyPreservedAsSrjTraces=new Set(db2.pcb_trace.list().filter(t53=>t53.source_trace_id?subcircuit_id?t53.subcircuit_id===subcircuit_id:t53.subcircuit_id?db2.source_trace.get(t53.source_trace_id)?.subcircuit_id===t53.subcircuit_id:!1:!1).map(t53=>t53.source_trace_id).filter(id3=>!!id3)),sourcePortIdToBreakoutPoint=new Map;for(let bp3 of breakoutPoints){let spId=bp3.source_port_id;spId&&sourcePortIdToBreakoutPoint.set(spId,bp3)}let getPcbPortRoutePoint=pcbPort=>{let layer=pcbPort.layers?.[0]??"top",breakoutPoint=sourcePortIdToBreakoutPoint.get(pcbPort.source_port_id),portSelector=getPortSelector(db2.source_port.get(pcbPort.source_port_id));return breakoutPoint&&!breakoutPointIsInActiveRoutingGroup(breakoutPoint)?{x:breakoutPoint.x,y:breakoutPoint.y,layer:breakoutPoint.layer??layer,pointId:breakoutPoint.pcb_breakout_point_id,port_selector:portSelector}:{x:pcbPort.x,y:pcbPort.y,layer,pointId:pcbPort.pcb_port_id,pcb_port_id:pcbPort.pcb_port_id,port_selector:portSelector}},sourceTraces=db2.source_trace.list(),planeTerminatedSourceTraceLayers=getPlaneTerminatedSourceTraceLayers({fanoutPourNetMap,sourceNets:db2.source_net.list(),sourceTraces,subcircuitId:subcircuit_id}),directTraceConnections=sourceTraces.filter(trace=>!sourceTraceIdsAlreadyPreservedAsSrjTraces.has(trace.source_trace_id)).filter(trace=>!subcircuit_id||trace.subcircuit_id===subcircuit_id).map(trace=>{let connectedPcbPorts=trace.connected_source_port_ids.map(sourcePortId=>db2.pcb_port.getWhere({source_port_id:sourcePortId})).filter(pcbPort=>pcbPort!==null),isPlaneTerminatedSourceTrace=planeTerminatedSourceTraceLayers.has(trace.source_trace_id);if(connectedPcbPorts.length<2&&!(isPlaneTerminatedSourceTrace&&connectedPcbPorts.length===1))return null;for(let connectedPort of connectedPcbPorts)if(connectedPort.x===void 0||connectedPort.y===void 0)return console.error(`(source_port_id: ${connectedPort.source_port_id}) for trace ${trace.source_trace_id} does not have x/y coordinates. Skipping this trace.`),null;let connectedPcbPortIds=new Set(connectedPcbPorts.map(port=>port.pcb_port_id)),matchingHints=traceHints.filter(hint=>connectedPcbPortIds.has(hint.pcb_port_id)),hintPoints=[];for(let hint of matchingHints){let layer=db2.pcb_port.get(hint.pcb_port_id)?.layers?.[0]??"top";for(let pt3 of hint.route)hintPoints.push({x:pt3.x,y:pt3.y,layer})}let connectedPortRoutePoints=connectedPcbPorts.map(port=>getPcbPortRoutePoint(port)),[firstConnectedPortRoutePoint,...remainingPortRoutePoints]=connectedPortRoutePoints;return{name:trace.source_trace_id??sharedConnMap.getNetConnectedToId(trace.source_trace_id)??"",source_trace_id:trace.source_trace_id,nominalTraceWidth:trace.min_trace_thickness,width:trace.min_trace_thickness,pointsToConnect:[firstConnectedPortRoutePoint,...hintPoints,...remainingPortRoutePoints]}}).filter(c3=>c3!==null),source_nets=db2.source_net.list().filter(e6=>!subcircuit_id||e6.subcircuit_id===subcircuit_id),connectionsFromNets=[],connectionFromNetId=new Map,handledNetConnectivityKeys=new Set,sourceNetIds=new Set(source_nets.map(net=>net.source_net_id)),currentSubcircuitSourceTraces=db2.source_trace.list().filter(trace=>!subcircuit_id||trace.subcircuit_id===subcircuit_id),exposedBridgeSourceTraceIds=new Set((subcircuitComponent?.selectAll("trace")??[]).flatMap(trace=>{let candidate=trace;return candidate._exposesSubcircuitConnection&&candidate.source_trace_id?[candidate.source_trace_id]:[]})),exposedDescendantSourceNetIds=new Set;for(let trace of currentSubcircuitSourceTraces)if(exposedBridgeSourceTraceIds.has(trace.source_trace_id))for(let sourceNetId of trace.connected_source_net_ids??[])sourceNetIds.has(sourceNetId)||exposedDescendantSourceNetIds.add(sourceNetId);let routedDescendantSourceTraceIds=new Set(subcircuit_id?db2.pcb_trace.list().filter(trace=>trace.subcircuit_id&&trace.subcircuit_id!==subcircuit_id&&relevantSubcircuitIds?.has(trace.subcircuit_id)).map(trace=>trace.source_trace_id).filter(id3=>!!id3):[]),sourceTracesEligibleForNetConnections=db2.source_trace.list().filter(trace=>!planeTerminatedSourceTraceLayers.has(trace.source_trace_id)).filter(trace=>!sourceTraceIdsAlreadyPreservedAsSrjTraces.has(trace.source_trace_id)||subcircuit_id!=null&&trace.subcircuit_id===subcircuit_id).filter(trace=>!subcircuit_id||trace.subcircuit_id===subcircuit_id||(trace.connected_source_net_ids?.some(id3=>sourceNetIds.has(id3))??!1)||(trace.connected_source_net_ids?.some(id3=>exposedDescendantSourceNetIds.has(id3))??!1)&&!routedDescendantSourceTraceIds.has(trace.source_trace_id)),getSourceConnectivityKey=id3=>id3?sharedConnMap.getNetConnectedToId(id3)??id3:null;for(let net of source_nets){let netConnectivityKey=getSourceConnectivityKey(net.source_net_id);if(!netConnectivityKey||handledNetConnectivityKeys.has(netConnectivityKey))continue;handledNetConnectivityKeys.add(netConnectivityKey);let connectedSourceNetIds=source_nets.filter(sourceNet=>getSourceConnectivityKey(sourceNet.source_net_id)===netConnectivityKey).map(sourceNet=>sourceNet.source_net_id),connectedSourceTraces=sourceTracesEligibleForNetConnections.filter(st3=>[st3.source_trace_id,...st3.connected_source_net_ids??[]].some(id3=>getSourceConnectivityKey(id3)===netConnectivityKey)),nominalTraceWidthFromConnectedTraces;for(let sourceTrace of connectedSourceTraces)sourceTrace.min_trace_thickness!==void 0&&(nominalTraceWidthFromConnectedTraces=Math.max(nominalTraceWidthFromConnectedTraces??0,sourceTrace.min_trace_thickness));let pointsToConnect=[],addedPointIds=new Set;for(let st3 of connectedSourceTraces){let pcb_ports=db2.pcb_port.list().filter(p3=>st3.connected_source_port_ids.includes(p3.source_port_id));for(let p3 of pcb_ports){let routePoint=getPcbPortRoutePoint(p3);addedPointIds.has(routePoint.pointId)||(addedPointIds.add(routePoint.pointId),pointsToConnect.push(routePoint))}}let connection={name:net.source_net_id??sharedConnMap.getNetConnectedToId(net.source_net_id),nominalTraceWidth:nominalTraceWidthFromConnectedTraces,width:nominalTraceWidthFromConnectedTraces,pointsToConnect};if(pointsToConnect.length!==0){connectionsFromNets.push(connection);for(let sourceNetId of connectedSourceNetIds)connectionFromNetId.set(sourceNetId,connection)}}let connectionsFromBreakoutPoints=[];for(let bp3 of breakoutPoints){let bpSourcePortId=bp3.source_port_id,pt3={x:bp3.x,y:bp3.y,layer:bp3.layer??"top",pointId:bp3.pcb_breakout_point_id};if(bpSourcePortId){let pcb_port3=db2.pcb_port.getWhere({source_port_id:bpSourcePortId});if(!pcb_port3)continue;let portPt={x:pcb_port3.x,y:pcb_port3.y,layer:pcb_port3.layers?.[0]??"top",pointId:pcb_port3.pcb_port_id,pcb_port_id:pcb_port3.pcb_port_id,port_selector:getPortSelector(db2.source_port.get(pcb_port3.source_port_id))},isInActiveRoutingGroup=breakoutPointIsInActiveRoutingGroup(bp3),isInTransparentChildRoutingGroup=!isInActiveRoutingGroup&&bp3.subcircuit_id===subcircuit_id;if(isInActiveRoutingGroup||isInTransparentChildRoutingGroup){connectionsFromBreakoutPoints.push({name:isInTransparentChildRoutingGroup?`breakout:${bp3.pcb_breakout_point_id}`:bpSourcePortId,source_trace_id:bp3.source_trace_id,routingPcbGroupId:isInTransparentChildRoutingGroup?bp3.pcb_group_id:void 0,pointsToConnect:[portPt,pt3]});continue}bp3.source_trace_id||connectionsFromBreakoutPoints.push({name:bpSourcePortId,pointsToConnect:[portPt,pt3]});continue}if(bp3.source_net_id){let conn=connectionFromNetId.get(bp3.source_net_id);conn?conn.pointsToConnect.push(pt3):connectionsFromBreakoutPoints.push({name:bp3.source_net_id,pointsToConnect:[pt3]})}}let routableConnectionsFromNets=connectionsFromNets.filter(connection=>connection.pointsToConnect.length>=2),allConns=[...directTraceConnections,...routableConnectionsFromNets,...connectionsFromBreakoutPoints],defaultTraceWidth=minTraceWidth??board?.min_trace_width??.1;for(let conn of allConns)conn.nominalTraceWidth??(conn.nominalTraceWidth=nominalTraceWidth??defaultTraceWidth),conn.width??(conn.width=nominalTraceWidth??defaultTraceWidth);bounds=expandSrjBoundsToIncludeConnectionPoints({bounds,connections:allConns});let differentialPairs=subcircuitComponent?.selectAll("differentialpair")??[],buses=subcircuitComponent?.selectAll("bus")??[],srjDifferentialPairs=getDifferentialPairsForSimpleRouteJson({srjConnections:allConns,differentialPairs,sourceTraces:db2.source_trace.list(),subcircuitId:subcircuit_id}),srjBuses=getBusesForSimpleRouteJson({srjConnections:allConns,buses,sourceTraces:db2.source_trace.list(),subcircuitId:subcircuit_id,planeTerminatedSourceTraceLayers});if(subcircuit_id){let pointIdToConn=new Map;for(let conn of allConns)for(let pt3 of conn.pointsToConnect)pt3.pointId&&pointIdToConn.set(pt3.pointId,conn);let existingTraces=db2.pcb_trace.list().filter(t53=>relevantSubcircuitIds?.has(t53.subcircuit_id));for(let tr3 of existingTraces){let tracePortIds=new Set;for(let seg of tr3.route)seg.start_pcb_port_id&&tracePortIds.add(seg.start_pcb_port_id),seg.end_pcb_port_id&&tracePortIds.add(seg.end_pcb_port_id);if(tracePortIds.size<2)continue;let firstId=tracePortIds.values().next().value;if(!firstId)continue;let conn=pointIdToConn.get(firstId);conn&&[...tracePortIds].every(pid=>pointIdToConn.get(pid)===conn)&&(conn.externallyConnectedPointIds??(conn.externallyConnectedPointIds=[]),conn.externallyConnectedPointIds.push([...tracePortIds]))}}let resolvedMinViaHoleDiameter=minViaHoleDiameter??board?.min_via_hole_diameter,resolvedMinViaPadDiameter=minViaPadDiameter??board?.min_via_pad_diameter,resolvedMinTraceToPadEdgeClearance=minTraceToPadEdgeClearance??board?.min_trace_to_pad_edge_clearance,resolvedMinViaEdgeToPadEdgeClearance=minViaEdgeToPadEdgeClearance??board?.min_via_edge_to_pad_edge_clearance,resolvedMinViaHoleEdgeToViaHoleEdgeClearance=minViaHoleEdgeToViaHoleEdgeClearance??board?.min_via_hole_edge_to_via_hole_edge_clearance,resolvedMinPlatedHoleDrillEdgeToDrillEdgeClearance=minPlatedHoleDrillEdgeToDrillEdgeClearance??board?.min_plated_hole_drill_edge_to_drill_edge_clearance,resolvedMinPadEdgeToPadEdgeClearance=minPadEdgeToPadEdgeClearance??board?.min_pad_edge_to_pad_edge_clearance,resolvedMinBoardEdgeClearance=minBoardEdgeClearance??board?.min_board_edge_clearance;return{simpleRouteJson:{bounds,obstacles,connections:allConns,differentialPairs:srjDifferentialPairs,...srjBuses?{buses:srjBuses}:{},traces:preservedRoutedSubcircuitTraces.length>0?preservedRoutedSubcircuitTraces:void 0,layerCount:board?.num_layers??2,minTraceWidth:Math.min(defaultTraceWidth,...allConns.map(c3=>c3.width)),minViaDiameter:resolvedMinViaPadDiameter,minViaHoleDiameter:resolvedMinViaHoleDiameter,minViaPadDiameter:resolvedMinViaPadDiameter,min_via_hole_diameter:resolvedMinViaHoleDiameter,min_via_pad_diameter:resolvedMinViaPadDiameter,minTraceToPadEdgeClearance:resolvedMinTraceToPadEdgeClearance,minViaEdgeToPadEdgeClearance:resolvedMinViaEdgeToPadEdgeClearance,minViaHoleEdgeToViaHoleEdgeClearance:resolvedMinViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance:resolvedMinPlatedHoleDrillEdgeToDrillEdgeClearance,minPadEdgeToPadEdgeClearance:resolvedMinPadEdgeToPadEdgeClearance,minBoardEdgeClearance:resolvedMinBoardEdgeClearance,nominalTraceWidth,outline:board?.outline?.map(point6=>({...point6}))},connMap:sharedConnMap}},unroutedElementTypes=new Set(["pcb_trace","pcb_trace_error"]),unrouteCircuitJson=circuitJson=>circuitJson.filter(element=>!unroutedElementTypes.has(element.type)),getPhaseTimingsFromRenderEvents=renderEvents=>{let phaseTimings={};if(!renderEvents)return phaseTimings;for(let renderPhase of orderedRenderPhases)phaseTimings[renderPhase]=0;let startEvents=new Map;for(let event of renderEvents){let[,,phase,eventType]=event.type.split(":");if(eventType==="start"){startEvents.set(`${phase}:${event.renderId}`,event);continue}if(eventType==="end"){let startEvent=startEvents.get(`${phase}:${event.renderId}`);if(startEvent){let duration=event.createdAt-startEvent.createdAt;phaseTimings[phase]=(phaseTimings[phase]||0)+duration}}}return phaseTimings},normalizePinLabels=inputPinLabels=>{let unqInputPinLabels=inputPinLabels.map(labels=>[...new Set(labels)]),result=unqInputPinLabels.map(()=>[]),desiredNumbers=unqInputPinLabels.map(()=>null);for(let i6=0;i6<unqInputPinLabels.length;i6++)for(let label of unqInputPinLabels[i6])if(/^\d+$/.test(label)){desiredNumbers[i6]=Number.parseInt(label);break}let highestPinNumber=0,alreadyAcceptedDesiredNumbers=new Set;for(let i6=0;i6<desiredNumbers.length;i6++){let desiredNumber=desiredNumbers[i6];if(desiredNumber===null||desiredNumber<1)continue;if(!alreadyAcceptedDesiredNumbers.has(desiredNumber)){alreadyAcceptedDesiredNumbers.add(desiredNumber),result[i6].push(`pin${desiredNumber}`),highestPinNumber=Math.max(highestPinNumber,desiredNumber);continue}let existingAltsForPin=0;for(let label of result[i6])label.startsWith(`pin${desiredNumber}_alt`)&&existingAltsForPin++;result[i6].push(`pin${desiredNumber}_alt${existingAltsForPin+1}`)}for(let i6=0;i6<result.length;i6++)result[i6][0]?.includes("_alt")&&(highestPinNumber++,result[i6].unshift(`pin${highestPinNumber}`));for(let i6=0;i6<result.length;i6++)result[i6].length===0&&(highestPinNumber++,result[i6].push(`pin${highestPinNumber}`));let totalLabelCounts={};for(let inputLabels of unqInputPinLabels)for(let label of inputLabels)/^\d+$/.test(label)||(totalLabelCounts[label]=(totalLabelCounts[label]??0)+1);let incrementalLabelCounts={};for(let i6=0;i6<unqInputPinLabels.length;i6++){let inputLabels=unqInputPinLabels[i6];for(let label of inputLabels)/^\d+$/.test(label)||(totalLabelCounts[label]===1?result[i6].push(label):(incrementalLabelCounts[label]=(incrementalLabelCounts[label]??0)+1,result[i6].push(`${label}${incrementalLabelCounts[label]}`)))}return result},TraceHint=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"matchedPort",null)}get config(){return{componentName:"TraceHint",zodProps:traceHintProps}}doInitialPortMatching(){let{db:db2}=this.root,{_parsedProps:props,parent}=this;if(!parent)return;if(parent.componentName==="Trace"){this.renderError(`Port inference inside trace is not yet supported (${this})`);return}if(!parent)throw new Error("TraceHint has no parent");if(!props.for){this.renderError(`TraceHint has no for property (${this})`);return}let port=parent.selectOne(props.for,{type:"port"});port||this.renderError(`${this} could not find port for selector "${props.for}"`),this.matchedPort=port,port.registerMatch(this)}getPcbRouteHints(){let{_parsedProps:props}=this,offsets=props.offset?[props.offset]:props.offsets;if(!offsets)return[];let globalTransform=this._computePcbGlobalTransformBeforeLayout();return offsets.map(offset=>({...applyToPoint2(globalTransform,offset),via:offset.via,to_layer:offset.to_layer,trace_width:offset.trace_width}))}doInitialPcbTraceHintRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this;db2.pcb_trace_hint.insert({pcb_component_id:this.matchedPort?.pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,route:this.getPcbRouteHints()})}};function getTitleAnchorAndPosition({anchor,x:x6,y:y2,width,height,isInside}){switch(anchor){case"top_left":return{x:x6,y:y2+height,textAnchor:isInside?"top_left":"bottom_left"};case"top_center":return{x:x6+width/2,y:y2+height,textAnchor:isInside?"top_center":"bottom_center"};case"top_right":return{x:x6+width,y:y2+height,textAnchor:isInside?"top_right":"bottom_right"};case"center_left":return{x:x6,y:y2+height/2,textAnchor:isInside?"center_left":"center_right"};case"center":return{x:x6+width/2,y:y2+height/2,textAnchor:"center"};case"center_right":return{x:x6+width,y:y2+height/2,textAnchor:isInside?"center_right":"center_left"};case"bottom_left":return{x:x6,y:y2,textAnchor:isInside?"bottom_left":"top_left"};case"bottom_center":return{x:x6+width/2,y:y2,textAnchor:isInside?"bottom_center":"top_center"};case"bottom_right":return{x:x6+width,y:y2,textAnchor:isInside?"bottom_right":"top_right"};default:return{x:x6+width/2,y:y2+height,textAnchor:"center"}}}var getSchematicBoxPinLabels=pinLabels=>pinLabels?Object.entries(pinLabels).map(([pinKey,pinLabel])=>{let pinNumber=getPinNumberFromPinLabelsKey(pinKey);if(pinNumber===null)throw new Error(`Invalid schematicbox pinLabels key "${pinKey}". Expected pin<number>.`);let pinAliases=typeof pinLabel=="string"?[pinLabel]:[...pinLabel];return{pinNumber,displayPinLabel:pinAliases[0]??pinKey,pinAliases}}):[],getSchematicBoxPinStyleFromReferencedChip=({referencedChip,schematicBoxPins})=>{let referencedChipPinStyle=getNumericSchPinStyle(referencedChip._parsedProps.schPinStyle,referencedChip._parsedProps.pinLabels);if(!referencedChipPinStyle)return;let schematicBoxPinStyle={};for(let{pinNumber,referencedSourcePort}of schematicBoxPins){if(referencedSourcePort.pin_number===void 0)continue;let pinStyle=referencedChipPinStyle[`pin${referencedSourcePort.pin_number}`];pinStyle&&(schematicBoxPinStyle[`pin${pinNumber}`]=pinStyle)}return Object.keys(schematicBoxPinStyle).length>0?schematicBoxPinStyle:void 0},mergeSchematicBoxPinStyles=({inheritedPinStyle,overridePinStyle})=>{if(!inheritedPinStyle&&!overridePinStyle)return;let mergedPinStyle={...inheritedPinStyle};for(let[pinKey,pinStyle]of Object.entries(overridePinStyle??{}))mergedPinStyle[pinKey]={...mergedPinStyle[pinKey],...pinStyle};return Object.keys(mergedPinStyle).length>0?mergedPinStyle:void 0},SchematicBox_doInitialSchematicComponentRender=schematicBox=>{if(schematicBox.root?.schematicDisabled)return;let{db:db2}=schematicBox.root,props=schematicBox._parsedProps;if(!props.chipRef)return;let referencedChip=schematicBox.getSubcircuit().selectOne(props.chipRef);if(!referencedChip?.source_component_id)throw new Error(`Could not resolve chipRef "${props.chipRef}" for ${schematicBox.getString()}`);let schematicBoxPinLabels=getSchematicBoxPinLabels(props.pinLabels),pinLabelsByPinKey=Object.fromEntries(schematicBoxPinLabels.map(({pinNumber,displayPinLabel})=>[`pin${pinNumber}`,displayPinLabel])),sourcePorts=db2.source_port.list({source_component_id:referencedChip.source_component_id}),schematicBoxPins=schematicBoxPinLabels.map(schematicBoxPin=>{let referencedSourcePort=sourcePorts.find(sourcePort=>schematicBoxPin.pinAliases.some(pinAlias=>sourcePort.name===pinAlias||sourcePort.port_hints?.includes(pinAlias)));if(!referencedSourcePort)throw new Error(`Could not find pin "${schematicBoxPin.displayPinLabel}" on chipRef "${props.chipRef}"`);return{...schematicBoxPin,referencedSourcePort}}),inheritedPinStyle=getSchematicBoxPinStyleFromReferencedChip({referencedChip,schematicBoxPins}),schematicBoxPinStyle=mergeSchematicBoxPinStyles({inheritedPinStyle,overridePinStyle:getNumericSchPinStyle(props.schPinStyle,props.pinLabels)}),dimensions=getAllDimensionsForSchematicBox({schWidth:props.width,schHeight:props.height,schPinSpacing:.2,pinCount:schematicBoxPinLabels.length,schPortArrangement:props.schPinArrangement,numericSchPinStyle:getNumericSchPinStyle(schematicBoxPinStyle),pinLabels:pinLabelsByPinKey}),center2=schematicBox._getGlobalSchematicPositionBeforeLayout(),size3=dimensions.getSize(),schematicSheetId=schematicBox._resolveSchematicSheetId(),portLabels=Object.fromEntries(schematicBoxPinLabels.map(({pinNumber,displayPinLabel})=>[String(pinNumber),displayPinLabel])),schematicComponent=db2.schematic_component.insert({center:center2,size:size3,source_component_id:referencedChip.source_component_id,is_box_with_pins:!0,port_arrangement:underscorifyPortArrangement(props.schPinArrangement),port_labels:portLabels,pin_spacing:.2,pin_styles:underscorifyPinStyles(schematicBoxPinStyle),schematic_sheet_id:schematicSheetId});schematicBox.schematic_component_id=schematicComponent.schematic_component_id;for(let{pinNumber,displayPinLabel,referencedSourcePort}of schematicBoxPins){let portPosition=dimensions.getPortPositionByPinNumber(pinNumber);if(!portPosition)throw new Error(`Could not determine schematic position for ${schematicBox.getString()} pin${pinNumber}`);let facingDirection={left:"left",right:"right",top:"up",bottom:"down"}[portPosition.side];db2.schematic_port.insert({schematic_component_id:schematicComponent.schematic_component_id,center:{x:center2.x+portPosition.x,y:center2.y+portPosition.y},source_port_id:referencedSourcePort.source_port_id,facing_direction:facingDirection,distance_from_component_edge:.4,side_of_component:portPosition.side,pin_number:pinNumber,true_ccw_index:portPosition.trueIndex,display_pin_label:displayPinLabel,is_connected:!1,schematic_sheet_id:schematicSheetId})}let sectionName=props.name??props.chipRef;db2.schematic_text.insert({text:sectionName,schematic_component_id:schematicComponent.schematic_component_id,anchor:"left",rotation:0,position:{x:center2.x-size3.width/2,y:center2.y+size3.height/2+.13},color:"#006464",font_size:.18,schematic_sheet_id:schematicSheetId});let referencedSourceComponent=db2.source_component.get(referencedChip.source_component_id);db2.schematic_text.insert({text:referencedSourceComponent?.manufacturer_part_number??"",schematic_component_id:schematicComponent.schematic_component_id,anchor:"left",rotation:0,position:{x:center2.x-size3.width/2,y:center2.y-size3.height/2-.13},color:"#006464",font_size:.18,schematic_sheet_id:schematicSheetId})},SchematicBox=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0)}get config(){return{componentName:"SchematicBox",zodProps:schematicBoxProps,shouldRenderAsSchematicBox:!0}}doInitialSchematicComponentRender(){SchematicBox_doInitialSchematicComponentRender(this)}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled||this.getCollapsedSchematicBoxAncestor())return;let{db:db2}=this.root,{_parsedProps:props}=this;if(props.chipRef)return;let basePadding=.6,generalPadding=typeof props.padding=="number"?props.padding:0,paddingTop=typeof props.paddingTop=="number"?props.paddingTop:generalPadding,paddingBottom=typeof props.paddingBottom=="number"?props.paddingBottom:generalPadding,paddingLeft=typeof props.paddingLeft=="number"?props.paddingLeft:generalPadding,paddingRight=typeof props.paddingRight=="number"?props.paddingRight:generalPadding,hasOverlay=props.overlay&&props.overlay.length>0,hasFixedSize=typeof props.width=="number"&&typeof props.height=="number",width,height,x6,y2,centerX,centerY;if(hasOverlay){let portsWithPosition=props.overlay.map(selector=>({selector,port:this.getSubcircuit().selectOne(selector,{type:"port"})})).filter(({port})=>port!=null).map(({port})=>({position:port._getGlobalSchematicPositionAfterLayout()}));if(portsWithPosition.length===0)return;let xs3=portsWithPosition.map(p3=>p3.position.x),ys3=portsWithPosition.map(p3=>p3.position.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3),rawWidth=maxX-minX,rawHeight=maxY-minY,defaultHorizontalPadding=rawWidth===0?basePadding:0,defaultVerticalPadding=rawHeight===0?basePadding:0,finalPaddingLeft=paddingLeft+defaultHorizontalPadding/2,finalPaddingRight=paddingRight+defaultHorizontalPadding/2,finalPaddingTop=paddingTop+defaultVerticalPadding/2,finalPaddingBottom=paddingBottom+defaultVerticalPadding/2,left=minX-finalPaddingLeft,right=maxX+finalPaddingRight,top=minY-finalPaddingBottom,bottom=maxY+finalPaddingTop;width=right-left,height=bottom-top,x6=left+(props.schX??0),y2=top+(props.schY??0),centerX=x6+width/2,centerY=y2+height/2}else if(hasFixedSize){width=props.width,height=props.height;let center2=this._getGlobalSchematicPositionBeforeLayout();centerX=center2.x,centerY=center2.y,x6=centerX-width/2,y2=centerY-height/2}else return;if(db2.schematic_box.insert({height,width,x:x6,y:y2,is_dashed:props.strokeStyle==="dashed",schematic_sheet_id:this._resolveSchematicSheetId()}),props.title){let isInside=props.titleInside,TITLE_PADDING=.1,anchor=props.titleAlignment,anchorPos=getTitleAnchorAndPosition({anchor,x:x6,y:y2,width,height,isInside}),titleOffsetY,titleOffsetX,textAnchor=anchorPos.textAnchor;isInside?(titleOffsetY=anchor.includes("top")?-TITLE_PADDING:anchor.includes("bottom")?TITLE_PADDING:0,titleOffsetX=anchor.includes("left")?TITLE_PADDING:anchor.includes("right")?-TITLE_PADDING:0):(titleOffsetY=anchor.includes("top")?TITLE_PADDING:anchor.includes("bottom")?-TITLE_PADDING:0,titleOffsetX=anchor.includes("center_left")?-TITLE_PADDING:anchor.includes("center_right")?TITLE_PADDING:0);let titleX=anchorPos.x+titleOffsetX,titleY=anchorPos.y+titleOffsetY;db2.schematic_text.insert({anchor:textAnchor,text:props.title,font_size:props.titleFontSize??.18,color:props.titleColor??"#000000",position:{x:titleX,y:titleY},rotation:0,schematic_sheet_id:this._resolveSchematicSheetId()})}}},Group_doInitialAssignSchematicSheetToConnectedComponents=group=>{if(!group.isSubcircuit||group.root?.schematicDisabled)return;let{db:db2}=group.root,schematicSheetIdsBySubcircuitConnectivityMapKey=new Map,schematicBoxReferencedSourceComponentIds=new Set,schematicBoxes=group.getDescendants().filter(component=>component instanceof SchematicBox&&component.getSubcircuit()===group);for(let schematicBox of schematicBoxes){let{chipRef,pinLabels}=schematicBox._parsedProps,schematicSheetId=schematicBox._resolveSchematicSheetId();if(!chipRef||!schematicSheetId)continue;let referencedComponent=schematicBox.getSubcircuit().selectOne(chipRef);if(!(referencedComponent instanceof NormalComponent3)||!referencedComponent.source_component_id)continue;schematicBoxReferencedSourceComponentIds.add(referencedComponent.source_component_id);let referencedSourcePorts=db2.source_port.list({source_component_id:referencedComponent.source_component_id});for(let{pinAliases}of getSchematicBoxPinLabels(pinLabels)){let subcircuitConnectivityMapKey=referencedSourcePorts.find(sourcePort=>pinAliases.some(pinAlias=>sourcePort.name===pinAlias||sourcePort.port_hints?.includes(pinAlias)))?.subcircuit_connectivity_map_key;if(!subcircuitConnectivityMapKey)continue;let schematicSheetIds=schematicSheetIdsBySubcircuitConnectivityMapKey.get(subcircuitConnectivityMapKey)??new Set;schematicSheetIds.add(schematicSheetId),schematicSheetIdsBySubcircuitConnectivityMapKey.set(subcircuitConnectivityMapKey,schematicSheetIds)}}let normalComponents=group.getDescendants().filter(component=>component instanceof NormalComponent3&&component.getSubcircuit()===group);for(let normalComponent of normalComponents){if(!normalComponent.source_component_id||schematicBoxReferencedSourceComponentIds.has(normalComponent.source_component_id)||normalComponent._resolveSchematicSheetId())continue;let connectedSchematicSheetIds=new Set,sourcePorts=db2.source_port.list({source_component_id:normalComponent.source_component_id});for(let sourcePort of sourcePorts){let subcircuitConnectivityMapKey=sourcePort.subcircuit_connectivity_map_key;if(!subcircuitConnectivityMapKey)continue;let schematicSheetIds=schematicSheetIdsBySubcircuitConnectivityMapKey.get(subcircuitConnectivityMapKey);if(schematicSheetIds)for(let schematicSheetId of schematicSheetIds)connectedSchematicSheetIds.add(schematicSheetId)}if(connectedSchematicSheetIds.size!==1)continue;let[inferredSchematicSheetId]=connectedSchematicSheetIds;inferredSchematicSheetId&&(normalComponent.schematic_sheet_id=inferredSchematicSheetId)}},SUPPORTED_COMPONENT_FIELDS=new Set(["x","y","minx","maxx","miny","maxy","width","height"]);function Group_doInitialPcbCalcPlacementResolution(group){if(group.root?.pcbDisabled||!group.isSubcircuit)return;let{db:db2}=group.root,normalComponentNameMap=group.getNormalComponentNameMap?.()??new Map,allNormalComponents=collectNormalComponentsInSubcircuit(group),namedComponentVars={};for(let component of allNormalComponents)updateVarsForNamedComponent(component,namedComponentVars);let candidatesByName=new Map,inDegree=new Map,dependents=new Map;for(let component of allNormalComponents){if(!shouldResolvePlacementInCalcPhase(component))continue;let refs=getComponentRefsForCalcPlacement(component);if(!component.name)throw new Error(`Invalid pcb position expression for ${component.getString()}: component-relative calc requires the component to have a name`);candidatesByName.set(component.name,{component,refs}),inDegree.set(component.name,0)}for(let[candidateName,candidate]of candidatesByName.entries()){let referencedCandidateNames=new Set;for(let token of candidate.refs){let{referencePath,field}=parseComponentReferenceToken(token);if(!SUPPORTED_COMPONENT_FIELDS.has(field))throw new Error(`Invalid pcb position expression for ${candidate.component.getString()}: unsupported component field "${field}" in "${token}"`);let referencedComponentName=resolveReferencedComponentName({token,referencePath,candidate,normalComponentNameMap});candidatesByName.has(referencedComponentName)&&referencedComponentName!==candidateName&&referencedCandidateNames.add(referencedComponentName)}for(let referencedComponentName of referencedCandidateNames)inDegree.set(candidateName,(inDegree.get(candidateName)??0)+1),dependents.has(referencedComponentName)||dependents.set(referencedComponentName,new Set),dependents.get(referencedComponentName).add(candidateName)}let queue=[...inDegree.entries()].filter(([,degree])=>degree===0).map(([name])=>name),resolvedCount=0;for(;queue.length>0;){let name=queue.shift(),candidate=candidatesByName.get(name);if(candidate){resolveCandidatePlacement(candidate.component,namedComponentVars),resolvedCount++;for(let dependentName of dependents.get(name)??[]){let nextDegree=(inDegree.get(dependentName)??0)-1;inDegree.set(dependentName,nextDegree),nextDegree===0&&queue.push(dependentName)}}}if(resolvedCount<candidatesByName.size){let unresolvedNames=[...candidatesByName.keys()].filter(name=>(inDegree.get(name)??0)>0);throw new Error(`Circular pcb position calc references detected among: ${unresolvedNames.join(", ")}`)}function resolveCandidatePlacement(component,componentVars){if(!component.pcb_component_id)return;let pcbComponent=db2.pcb_component.get(component.pcb_component_id);if(!pcbComponent)return;let rawPcbX=component._parsedProps.pcbX,rawPcbY=component._parsedProps.pcbY,rawComponentProps=component.props,rawPcbLeftEdgeX=component._parsedProps.pcbLeftEdgeX??rawComponentProps.pcbLeftEdgeX,rawPcbRightEdgeX=component._parsedProps.pcbRightEdgeX??rawComponentProps.pcbRightEdgeX,rawPcbTopEdgeY=component._parsedProps.pcbTopEdgeY??rawComponentProps.pcbTopEdgeY,rawPcbBottomEdgeY=component._parsedProps.pcbBottomEdgeY??rawComponentProps.pcbBottomEdgeY;if(rawPcbLeftEdgeX!==void 0&&rawPcbRightEdgeX!==void 0)throw new Error(`${component.componentName} cannot set both pcbLeftEdgeX and pcbRightEdgeX`);if(rawPcbTopEdgeY!==void 0&&rawPcbBottomEdgeY!==void 0)throw new Error(`${component.componentName} cannot set both pcbTopEdgeY and pcbBottomEdgeY`);let componentWidth=pcbComponent.width??0,componentHeight=pcbComponent.height??0,nextCenter={x:pcbComponent.center.x,y:pcbComponent.center.y};if(rawPcbX!==void 0){let resolvedPcbX=component.resolvePcbCoordinate({rawValue:rawPcbX,axis:"pcbX",allowComponentVariables:!0,componentVariables:componentVars});component._resolvedPcbCalcOffsetX=resolvedPcbX,nextCenter.x=resolvedPcbX}else if(rawPcbLeftEdgeX!==void 0){let resolvedPcbX=component.resolvePcbCoordinate({rawValue:rawPcbLeftEdgeX,axis:"pcbX",allowComponentVariables:!0,componentVariables:componentVars,propertyName:"pcbLeftEdgeX"})+componentWidth/2;component._resolvedPcbCalcOffsetX=resolvedPcbX,nextCenter.x=resolvedPcbX}else if(rawPcbRightEdgeX!==void 0){let resolvedPcbX=component.resolvePcbCoordinate({rawValue:rawPcbRightEdgeX,axis:"pcbX",allowComponentVariables:!0,componentVariables:componentVars,propertyName:"pcbRightEdgeX"})-componentWidth/2;component._resolvedPcbCalcOffsetX=resolvedPcbX,nextCenter.x=resolvedPcbX}if(rawPcbY!==void 0){let resolvedPcbY=component.resolvePcbCoordinate({rawValue:rawPcbY,axis:"pcbY",allowComponentVariables:!0,componentVariables:componentVars});component._resolvedPcbCalcOffsetY=resolvedPcbY,nextCenter.y=resolvedPcbY}else if(rawPcbTopEdgeY!==void 0){let resolvedPcbY=component.resolvePcbCoordinate({rawValue:rawPcbTopEdgeY,axis:"pcbY",allowComponentVariables:!0,componentVariables:componentVars,propertyName:"pcbTopEdgeY"})-componentHeight/2;component._resolvedPcbCalcOffsetY=resolvedPcbY,nextCenter.y=resolvedPcbY}else if(rawPcbBottomEdgeY!==void 0){let resolvedPcbY=component.resolvePcbCoordinate({rawValue:rawPcbBottomEdgeY,axis:"pcbY",allowComponentVariables:!0,componentVariables:componentVars,propertyName:"pcbBottomEdgeY"})+componentHeight/2;component._resolvedPcbCalcOffsetY=resolvedPcbY,nextCenter.y=resolvedPcbY}component._repositionOnPcb(nextCenter),updateVarsForNamedComponent(component,componentVars)}}function shouldResolvePlacementInCalcPhase(component){let parsedProps=component._parsedProps,rawProps=component.props,pcbX=parsedProps.pcbX,pcbY=parsedProps.pcbY,pcbLeftEdgeX=parsedProps.pcbLeftEdgeX??rawProps.pcbLeftEdgeX,pcbRightEdgeX=parsedProps.pcbRightEdgeX??rawProps.pcbRightEdgeX,pcbTopEdgeY=parsedProps.pcbTopEdgeY??rawProps.pcbTopEdgeY,pcbBottomEdgeY=parsedProps.pcbBottomEdgeY??rawProps.pcbBottomEdgeY;return pcbLeftEdgeX!==void 0||pcbRightEdgeX!==void 0||pcbTopEdgeY!==void 0||pcbBottomEdgeY!==void 0?!0:typeof pcbX=="string"||typeof pcbY=="string"}function collectNormalComponentsInSubcircuit(group){let components=[],walk=node=>{node._isNormalComponent&&components.push(node);for(let child of node.children)child.isSubcircuit||walk(child)};for(let child of group.children)child.isSubcircuit||walk(child);return components}function getComponentRefsForCalcPlacement(component){let refs=new Set,rawPcbX=component._parsedProps.pcbX,rawPcbY=component._parsedProps.pcbY,rawComponentProps=component.props,rawPcbLeftEdgeX=component._parsedProps.pcbLeftEdgeX??rawComponentProps.pcbLeftEdgeX,rawPcbRightEdgeX=component._parsedProps.pcbRightEdgeX??rawComponentProps.pcbRightEdgeX,rawPcbTopEdgeY=component._parsedProps.pcbTopEdgeY??rawComponentProps.pcbTopEdgeY,rawPcbBottomEdgeY=component._parsedProps.pcbBottomEdgeY??rawComponentProps.pcbBottomEdgeY,addRefs=rawValue=>{if(typeof rawValue!="string")return;let identifiers=extractCalcIdentifiers(rawValue);for(let identifier of identifiers)identifier.startsWith("board.")||refs.add(identifier)};return addRefs(rawPcbX),addRefs(rawPcbY),addRefs(rawPcbLeftEdgeX),addRefs(rawPcbRightEdgeX),addRefs(rawPcbTopEdgeY),addRefs(rawPcbBottomEdgeY),refs}function parseComponentReferenceToken(token){let dotIndex=token.lastIndexOf(".");if(dotIndex<=0||dotIndex===token.length-1)throw new Error(`Invalid component reference token: "${token}"`);return{referencePath:token.slice(0,dotIndex),field:token.slice(dotIndex+1).toLowerCase()}}function resolveReferencedComponentName(params){let{token,referencePath,candidate,normalComponentNameMap}=params,directComponents=normalComponentNameMap.get(referencePath);if(directComponents&&directComponents.length>0){if(directComponents.length>1)throw new Error(`Invalid pcb position expression for ${candidate.component.getString()}: ambiguous component reference "${referencePath}" in "${token}"`);return referencePath}let bestMatch=null;for(let componentName of normalComponentNameMap.keys())referencePath.startsWith(`${componentName}.`)&&(!bestMatch||componentName.length>bestMatch.length)&&(bestMatch=componentName);if(!bestMatch)throw new Error(`Invalid pcb position expression for ${candidate.component.getString()}: unknown component reference "${referencePath}" in "${token}"`);return bestMatch}function updateVarsForNamedComponent(component,vars){if(!component.name||!component.pcb_component_id||!component.root)return;let pcbComponent=component.root.db.pcb_component.get(component.pcb_component_id);if(!pcbComponent)return;let width=pcbComponent.width??0,height=pcbComponent.height??0,x6=pcbComponent.center.x,y2=pcbComponent.center.y;setSubcircuitPcbComponentCalcVariables({vars,componentName:component.name,position:{x:x6,y:y2},size:{width,height}});let padElementsByReference=collectPadElementsByReference(component);for(let[referencePath,elements]of padElementsByReference.entries()){let bounds=getBoundsOfPcbElements(elements),minX=bounds.minX,maxX=bounds.maxX,minY=bounds.minY,maxY=bounds.maxY;vars[`${referencePath}.x`]=(minX+maxX)/2,vars[`${referencePath}.y`]=(minY+maxY)/2,vars[`${referencePath}.width`]=maxX-minX,vars[`${referencePath}.height`]=maxY-minY,vars[`${referencePath}.minX`]=minX,vars[`${referencePath}.maxX`]=maxX,vars[`${referencePath}.minY`]=minY,vars[`${referencePath}.maxY`]=maxY}}function collectPadElementsByReference(component){let refsToElements=new Map;if(!component.name||!component.pcb_component_id||!component.root)return refsToElements;let{db:db2}=component.root,padElements=[...db2.pcb_smtpad.list({pcb_component_id:component.pcb_component_id}),...db2.pcb_plated_hole.list({pcb_component_id:component.pcb_component_id})];for(let pad2 of padElements){let aliases2=new Set;for(let hint of pad2.port_hints??[])typeof hint=="string"&&hint.length>0&&aliases2.add(hint);let pcbPortId=pad2.pcb_port_id;if(pcbPortId){let pcbPort=db2.pcb_port.get(pcbPortId),sourcePort=pcbPort?.source_port_id?db2.source_port.get(pcbPort.source_port_id):null;sourcePort?.name&&aliases2.add(sourcePort.name),sourcePort?.pin_number!=null&&aliases2.add(`pin${sourcePort.pin_number}`)}for(let alias of aliases2){let referencePath=`${component.name}.${alias}`;refsToElements.has(referencePath)||refsToElements.set(referencePath,[]),refsToElements.get(referencePath).push(pad2)}}return refsToElements}function Group_doInitialPcbComponentAnchorAlignment(group){if(group.root?.pcbDisabled||!group.pcb_group_id)return;let pcbPositionAnchor=group._parsedProps?.pcbPositionAnchor;if(!pcbPositionAnchor)return;let targetPosition=group._getGlobalPcbPositionBeforeLayout(),{pcbX,pcbY}=group._parsedProps;if(pcbX===void 0&&pcbY===void 0)return;let{db:db2}=group.root,pcbGroup=db2.pcb_group.get(group.pcb_group_id);if(!pcbGroup)return;let width=pcbGroup.width,height=pcbGroup.height,{center:center2}=pcbGroup;if(pcbGroup.outline&&pcbGroup.outline.length>0){let bounds2=getBoundsFromPoints2(pcbGroup.outline);bounds2&&(width=bounds2.maxX-bounds2.minX,height=bounds2.maxY-bounds2.minY)}if(!width||!height)return;let bounds={left:center2.x-width/2,right:center2.x+width/2,top:center2.y+height/2,bottom:center2.y-height/2},currentCenter={...center2},anchorPos=null;if(new Set(["center","top_left","top_center","top_right","center_left","center_right","bottom_left","bottom_center","bottom_right"]).has(pcbPositionAnchor))switch(pcbPositionAnchor){case"center":anchorPos=currentCenter;break;case"top_left":anchorPos={x:bounds.left,y:bounds.top};break;case"top_center":anchorPos={x:currentCenter.x,y:bounds.top};break;case"top_right":anchorPos={x:bounds.right,y:bounds.top};break;case"center_left":anchorPos={x:bounds.left,y:currentCenter.y};break;case"center_right":anchorPos={x:bounds.right,y:currentCenter.y};break;case"bottom_left":anchorPos={x:bounds.left,y:bounds.bottom};break;case"bottom_center":anchorPos={x:currentCenter.x,y:bounds.bottom};break;case"bottom_right":anchorPos={x:bounds.right,y:bounds.bottom};break}if(!anchorPos)return;let newCenter={...currentCenter};targetPosition.x!==void 0&&(newCenter.x+=targetPosition.x-anchorPos.x),targetPosition.y!==void 0&&(newCenter.y+=targetPosition.y-anchorPos.y),(Math.abs(newCenter.x-currentCenter.x)>1e-6||Math.abs(newCenter.y-currentCenter.y)>1e-6)&&(group._repositionOnPcb(newCenter),db2.pcb_group.update(group.pcb_group_id,{center:newCenter})),db2.pcb_group.update(group.pcb_group_id,{anchor_position:targetPosition,anchor_alignment:pcbPositionAnchor,display_offset_x:pcbX,display_offset_y:pcbY})}var Group_doInitialPcbLayoutFlex=group=>{let{db:db2}=group.root,{_parsedProps:props}=group,pcbChildren=group.children.filter(c3=>c3.pcb_component_id||c3.pcb_group_id);if(pcbChildren.some(child=>{let childProps=child._parsedProps;return childProps?.pcbX!==void 0||childProps?.pcbY!==void 0}))return;let rawJustify=props.pcbJustifyContent??props.justifyContent,rawAlign=props.pcbAlignItems??props.alignItems,rawGap=props.pcbFlexGap??props.pcbGap??props.gap,direction2=props.pcbFlexDirection??"row",justifyContent={start:"flex-start",end:"flex-end","flex-start":"flex-start","flex-end":"flex-end",stretch:"space-between","space-between":"space-between","space-around":"space-around","space-evenly":"space-evenly",center:"center"}[rawJustify??"space-between"],alignItems={start:"flex-start",end:"flex-end","flex-start":"flex-start","flex-end":"flex-end",stretch:"stretch",center:"center"}[rawAlign??"center"];if(!justifyContent)throw new Error(`Invalid justifyContent value: "${rawJustify}"`);if(!alignItems)throw new Error(`Invalid alignItems value: "${rawAlign}"`);let rowGap=0,columnGap=0;typeof rawGap=="object"?(rowGap=rawGap.y??0,columnGap=rawGap.x??0):typeof rawGap=="number"?(rowGap=rawGap,columnGap=rawGap):typeof rawGap=="string"&&(rowGap=length.parse(rawGap),columnGap=length.parse(rawGap));let minFlexContainer,width=props.width??props.pcbWidth??void 0,height=props.height??props.pcbHeight??void 0;(width===void 0||height===void 0)&&(minFlexContainer=getMinimumFlexContainer(pcbChildren.map(child=>child._getMinimumFlexContainerSize()).filter(size3=>size3!==null),{alignItems,justifyContent,direction:direction2,rowGap,columnGap}),width=minFlexContainer.width,height=minFlexContainer.height);let flexBox=new RootFlexBox(width,height,{alignItems,justifyContent,direction:direction2,rowGap,columnGap});for(let child of pcbChildren){let size3=child._getMinimumFlexContainerSize();flexBox.addChild({metadata:child,width:size3?.width??0,height:size3?.height??0,flexBasis:size3?direction2==="row"?size3.width:size3.height:void 0})}flexBox.build();let bounds={minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0,width:0,height:0};for(let child of flexBox.children)bounds.minX=Math.min(bounds.minX,child.position.x),bounds.minY=Math.min(bounds.minY,child.position.y),bounds.maxX=Math.max(bounds.maxX,child.position.x+child.size.width),bounds.maxY=Math.max(bounds.maxY,child.position.y+child.size.height);bounds.width=bounds.maxX-bounds.minX,bounds.height=bounds.maxY-bounds.minY;let groupCenter=group._getGlobalPcbPositionBeforeLayout(),offset={x:groupCenter.x-(bounds.maxX+bounds.minX)/2,y:groupCenter.y-(bounds.maxY+bounds.minY)/2};for(let child of flexBox.children)child.metadata._repositionOnPcb({x:child.position.x+child.size.width/2+offset.x,y:child.position.y+child.size.height/2+offset.y});db2.pcb_group.update(group.pcb_group_id,{width:bounds.width,height:bounds.height,center:groupCenter})},MIN_GAP=1;function Group_doInitialPcbLayoutGrid(group){let{db:db2}=group.root,props=group._parsedProps,pcbChildren=getPcbChildren(group);if(pcbChildren.length===0)return;let childDimensions=calculateChildDimensions({db:db2,pcbChildren}),gridConfig=parseGridConfiguration(props),gridLayout=createGridLayout({props,pcbChildren,childDimensions,gridConfig}),cssGrid=createCssGrid({pcbChildren,childDimensions,gridLayout,gridConfig}),{itemCoordinates}=cssGrid.layout();positionChildren({db:db2,group,pcbChildren,itemCoordinates,gridLayout}),updateGroupDimensions({db:db2,group,props,gridLayout})}function getPcbChildren(group){return group.children.filter(child=>child.pcb_component_id||child.pcb_group_id)}function calculateChildDimensions(params){let{db:db2,pcbChildren}=params,maxWidth=0,maxHeight=0;for(let child of pcbChildren){let width=0,height=0;if(child.pcb_group_id){let pcbGroup=db2.pcb_group.get(child.pcb_group_id);width=pcbGroup?.width??0,height=pcbGroup?.height??0}else if(child.pcb_component_id){let pcbComp=db2.pcb_component.get(child.pcb_component_id);width=pcbComp?.width??0,height=pcbComp?.height??0}maxWidth=Math.max(maxWidth,width),maxHeight=Math.max(maxHeight,height)}return{width:maxWidth,height:maxHeight}}function parseGridConfiguration(props){let cols=props.pcbGridCols??props.gridCols??props.pcbLayout?.grid?.cols,rows=props.pcbGridRows??props.pcbLayout?.grid?.rows,templateColumns=props.pcbGridTemplateColumns,templateRows=props.pcbGridTemplateRows,parseGap=gapValue=>gapValue===void 0?MIN_GAP:typeof gapValue=="number"?gapValue:length.parse(gapValue),gridGapOption=props.pcbGridGap??props.gridGap??props.pcbLayout?.gridGap,rowGapOption=props.pcbGridRowGap??props.gridRowGap??props.pcbLayout?.gridRowGap,colGapOption=props.pcbGridColumnGap??props.gridColumnGap??props.pcbLayout?.gridColumnGap,gapX=MIN_GAP,gapY=MIN_GAP;if(rowGapOption!==void 0||colGapOption!==void 0){let fallbackX=typeof gridGapOption=="object"?gridGapOption?.x:gridGapOption,fallbackY=typeof gridGapOption=="object"?gridGapOption?.y:gridGapOption;gapX=parseGap(colGapOption??fallbackX),gapY=parseGap(rowGapOption??fallbackY)}else if(typeof gridGapOption=="object"&&gridGapOption!==null)gapX=parseGap(gridGapOption.x),gapY=parseGap(gridGapOption.y);else{let gap=parseGap(gridGapOption);gapX=gap,gapY=gap}return{cols,rows,gapX,gapY,templateColumns,templateRows}}function createGridLayout(params){let{props,pcbChildren,childDimensions,gridConfig}=params;return props.pcbGridTemplateColumns||props.pcbGridTemplateRows?createTemplateBasedLayout({props,gridConfig,pcbChildren,childDimensions}):createDefaultLayout({gridConfig,pcbChildren,childDimensions})}function createTemplateBasedLayout(params){let{props,gridConfig,pcbChildren,childDimensions}=params,gridTemplateColumns=props.pcbGridTemplateColumns??"",gridTemplateRows=props.pcbGridTemplateRows??"",extractRepeatCount=template=>{let match2=template.match(/repeat\((\d+),/);return match2?parseInt(match2[1]):Math.ceil(Math.sqrt(pcbChildren.length))},numCols=props.pcbGridTemplateColumns?extractRepeatCount(gridTemplateColumns):Math.ceil(Math.sqrt(pcbChildren.length)),numRows=props.pcbGridTemplateRows?extractRepeatCount(gridTemplateRows):Math.ceil(pcbChildren.length/numCols),containerWidth=numCols*childDimensions.width+Math.max(0,numCols-1)*gridConfig.gapX,containerHeight=numRows*childDimensions.height+Math.max(0,numRows-1)*gridConfig.gapY;return{gridTemplateColumns,gridTemplateRows,containerWidth,containerHeight}}function createDefaultLayout(params){let{gridConfig,pcbChildren,childDimensions}=params,numCols,numRows;gridConfig.cols!==void 0&&gridConfig.rows!==void 0?(numCols=gridConfig.cols,numRows=gridConfig.rows):gridConfig.cols!==void 0?(numCols=gridConfig.cols,numRows=Math.ceil(pcbChildren.length/numCols)):gridConfig.rows!==void 0?(numRows=gridConfig.rows,numCols=Math.ceil(pcbChildren.length/numRows)):(numCols=Math.ceil(Math.sqrt(pcbChildren.length)),numRows=Math.ceil(pcbChildren.length/numCols)),numCols=Math.max(1,numCols),numRows=Math.max(1,numRows);let containerWidth=numCols*childDimensions.width+Math.max(0,numCols-1)*gridConfig.gapX,containerHeight=numRows*childDimensions.height+Math.max(0,numRows-1)*gridConfig.gapY,gridTemplateColumns=`repeat(${numCols}, ${childDimensions.width}px)`,gridTemplateRows=`repeat(${numRows}, ${childDimensions.height}px)`;return{gridTemplateColumns,gridTemplateRows,containerWidth,containerHeight}}function createCssGrid(params){let{pcbChildren,childDimensions,gridLayout,gridConfig}=params,gridChildren=pcbChildren.map((child,index)=>({key:child.getString()||`child-${index}`,contentWidth:childDimensions.width,contentHeight:childDimensions.height}));return new CssGrid({containerWidth:gridLayout.containerWidth,containerHeight:gridLayout.containerHeight,gridTemplateColumns:gridLayout.gridTemplateColumns,gridTemplateRows:gridLayout.gridTemplateRows,gap:[gridConfig.gapY,gridConfig.gapX],children:gridChildren})}function positionChildren(params){let{db:db2,group,pcbChildren,itemCoordinates,gridLayout}=params,groupCenter=group._getGlobalPcbPositionBeforeLayout(),allCircuitJson=db2.toArray();for(let i6=0;i6<pcbChildren.length;i6++){let child=pcbChildren[i6],childKey=child.getString()||`child-${i6}`,coordinates=itemCoordinates[childKey];if(!coordinates){console.warn(`PCB grid layout: No coordinates found for child ${childKey}`);continue}let targetX=groupCenter.x-gridLayout.containerWidth/2+coordinates.x+coordinates.width/2,targetY=groupCenter.y+gridLayout.containerHeight/2-coordinates.y-coordinates.height/2;if(child.pcb_component_id)repositionPcbComponentTo(allCircuitJson,child.pcb_component_id,{x:targetX,y:targetY});else{let groupChild=child;groupChild.pcb_group_id&&groupChild.source_group_id&&repositionPcbGroupTo(allCircuitJson,groupChild.source_group_id,{x:targetX,y:targetY})}}}function updateGroupDimensions(params){let{db:db2,group,props,gridLayout}=params;if(group.pcb_group_id){let groupCenter=group._getGlobalPcbPositionBeforeLayout();db2.pcb_group.update(group.pcb_group_id,{width:props.width??gridLayout.containerWidth,height:props.height??gridLayout.containerHeight,center:groupCenter})}}var solvePackSolverWithTimeout=(solver,timeoutMs,getCurrentTime=()=>performance.now())=>{if(timeoutMs===void 0||!Number.isFinite(timeoutMs)||timeoutMs<=0)return solver.solve(),{elapsedMs:0,timedOut:!1};let startedAt=getCurrentTime(),elapsedMs=0;for(;!solver.solved&&!solver.failed&&(solver.step(),!(solver.solved||solver.failed));)if(elapsedMs=getCurrentTime()-startedAt,elapsedMs>=timeoutMs)return{elapsedMs,timedOut:!0};return{elapsedMs,timedOut:!1}},applyComponentConstraintClusters=(group,packInput)=>{let constraints=group.children.filter(c3=>c3.componentName==="Constraint"&&c3._parsedProps.pcb),clusterByRoot=new Map,parent={},find2=x6=>(parent[x6]!==x6&&(parent[x6]=find2(parent[x6])),parent[x6]),union2=(a6,b6)=>{let ra3=find2(a6),rb2=find2(b6);ra3!==rb2&&(parent[rb2]=ra3)},makeSet=x6=>{x6 in parent||(parent[x6]=x6)},getIdFromSelector=sel2=>{let name=sel2.startsWith(".")?sel2.slice(1):sel2;return group.children.find(c3=>c3.name===name)?.pcb_component_id??void 0};for(let constraint of constraints){let props=constraint._parsedProps;if("left"in props&&"right"in props){let a6=getIdFromSelector(props.left),b6=getIdFromSelector(props.right);a6&&b6&&(makeSet(a6),makeSet(b6),union2(a6,b6))}else if("top"in props&&"bottom"in props){let a6=getIdFromSelector(props.top),b6=getIdFromSelector(props.bottom);a6&&b6&&(makeSet(a6),makeSet(b6),union2(a6,b6))}else if("for"in props&&Array.isArray(props.for)){let ids=props.for.map(s6=>getIdFromSelector(s6)).filter(s6=>!!s6);for(let id3 of ids)makeSet(id3);for(let i6=1;i6<ids.length;i6++)union2(ids[0],ids[i6])}}for(let id3 of Object.keys(parent)){let rootId=find2(id3);clusterByRoot.has(rootId)||clusterByRoot.set(rootId,{componentIds:[],constraints:[]}),clusterByRoot.get(rootId).componentIds.push(id3)}for(let constraint of constraints){let props=constraint._parsedProps,compId;if("left"in props?compId=getIdFromSelector(props.left):"top"in props?compId=getIdFromSelector(props.top):"for"in props&&(compId=getIdFromSelector(props.for[0])),!compId)continue;let root=find2(compId);clusterByRoot.get(root)?.constraints.push(constraint)}let clusterMap={},packCompById=Object.fromEntries(packInput.components.map(c3=>[c3.componentId,c3]));for(let[rootId,info]of clusterByRoot.entries()){if(info.componentIds.length<=1)continue;let solver=new Solver,kVars={},getVar=(id3,axis)=>{let key=`${id3}_${axis}`;return kVars[key]||(kVars[key]=new Variable(key)),kVars[key]},anchor=info.componentIds[0];solver.addConstraint(new Constraint(getVar(anchor,"x"),Operator.Eq,0,Strength.required)),solver.addConstraint(new Constraint(getVar(anchor,"y"),Operator.Eq,0,Strength.required));for(let constraint of info.constraints){let props=constraint._parsedProps;if("xDist"in props){let left=getIdFromSelector(props.left),right=getIdFromSelector(props.right);left&&right&&solver.addConstraint(new Constraint(new Expression(getVar(right,"x"),[-1,getVar(left,"x")]),Operator.Eq,props.xDist,Strength.required))}else if("yDist"in props){let top=getIdFromSelector(props.top),bottom=getIdFromSelector(props.bottom);top&&bottom&&solver.addConstraint(new Constraint(new Expression(getVar(top,"y"),[-1,getVar(bottom,"y")]),Operator.Eq,props.yDist,Strength.required))}else if("sameX"in props&&Array.isArray(props.for)){let ids=props.for.map(s6=>getIdFromSelector(s6)).filter(s6=>!!s6);if(ids.length>1){let base=getVar(ids[0],"x");for(let i6=1;i6<ids.length;i6++)solver.addConstraint(new Constraint(new Expression(getVar(ids[i6],"x"),[-1,base]),Operator.Eq,0,Strength.required))}}else if("sameY"in props&&Array.isArray(props.for)){let ids=props.for.map(s6=>getIdFromSelector(s6)).filter(s6=>!!s6);if(ids.length>1){let base=getVar(ids[0],"y");for(let i6=1;i6<ids.length;i6++)solver.addConstraint(new Constraint(new Expression(getVar(ids[i6],"y"),[-1,base]),Operator.Eq,0,Strength.required))}}}solver.updateVariables();let positions={};for(let id3 of info.componentIds)positions[id3]={x:getVar(id3,"x").value(),y:getVar(id3,"y").value()};let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let id3 of info.componentIds){let comp=packCompById[id3],pos=positions[id3];if(comp)for(let pad2 of comp.pads){let ax3=pos.x+pad2.offset.x,ay3=pos.y+pad2.offset.y;minX=Math.min(minX,ax3-pad2.size.x/2),maxX=Math.max(maxX,ax3+pad2.size.x/2),minY=Math.min(minY,ay3-pad2.size.y/2),maxY=Math.max(maxY,ay3+pad2.size.y/2)}}let clusterCenter={x:(minX+maxX)/2,y:(minY+maxY)/2},mergedPads=[],relCenters={};for(let id3 of info.componentIds){let comp=packCompById[id3],pos=positions[id3];if(comp){relCenters[id3]={x:pos.x-clusterCenter.x,y:pos.y-clusterCenter.y};for(let pad2 of comp.pads)mergedPads.push({padId:pad2.padId,networkId:pad2.networkId,type:pad2.type,size:pad2.size,offset:{x:pos.x+pad2.offset.x-clusterCenter.x,y:pos.y+pad2.offset.y-clusterCenter.y}})}}packInput.components=packInput.components.filter(c3=>!info.componentIds.includes(c3.componentId)),packInput.components.push({componentId:info.componentIds[0],pads:mergedPads,availableRotationDegrees:[0]}),info.relativeCenters=relCenters,clusterMap[info.componentIds[0]]=info}return clusterMap},updateCadRotation=({db:db2,pcbComponentId,rotationDegrees,layer})=>{if(rotationDegrees==null||!db2?.cad_component?.list)return;let cadComponent=db2.cad_component.getWhere({pcb_component_id:pcbComponentId});if(!cadComponent)return;let delta=layer?.toLowerCase?.()==="bottom"?-rotationDegrees:rotationDegrees,currentRotationZ=cadComponent.rotation?.z??0,nextRotation={...cadComponent.rotation??{x:0,y:0,z:0},z:normalizeDegrees(currentRotationZ+delta)};db2.cad_component.update(cadComponent.cad_component_id,{rotation:nextRotation}),cadComponent.rotation=nextRotation},isDescendantGroup=(db2,groupId,ancestorId)=>{if(groupId===ancestorId)return!0;let group=db2.source_group.get(groupId);return!group||!group.parent_source_group_id?!1:isDescendantGroup(db2,group.parent_source_group_id,ancestorId)},applyPackOutput=(group,packOutput,clusterMap,initialPackOutput)=>{let{db:db2}=group.root;for(let packedComponent of packOutput.components){let{center:center2,componentId,ccwRotationOffset,ccwRotationDegrees}=packedComponent,cluster=clusterMap[componentId];if(cluster){let rotationDegrees2=ccwRotationDegrees??ccwRotationOffset??0,angleRad=rotationDegrees2*Math.PI/180;for(let memberId of cluster.componentIds){let rel=cluster.relativeCenters[memberId];if(!rel)continue;db2.pcb_component.update(memberId,{position_mode:"packed"});let rotatedRel={x:rel.x*Math.cos(angleRad)-rel.y*Math.sin(angleRad),y:rel.x*Math.sin(angleRad)+rel.y*Math.cos(angleRad)},member=db2.pcb_component.get(memberId);if(!member)continue;let originalCenter2=member.center,transformMatrix2=compose2(group._computePcbGlobalTransformBeforeLayout(),translate2(center2.x+rotatedRel.x,center2.y+rotatedRel.y),rotate2(angleRad),translate2(-originalCenter2.x,-originalCenter2.y)),related=db2.toArray().filter(elm=>"pcb_component_id"in elm&&elm.pcb_component_id===memberId);transformPCBElements(related,transformMatrix2),updateCadRotation({db:db2,pcbComponentId:memberId,rotationDegrees:rotationDegrees2,layer:member.layer})}continue}let pcbComponent=db2.pcb_component.get(componentId);if(pcbComponent){db2.pcb_component.update(componentId,{position_mode:"packed"});let currentGroupId=group.source_group_id,componentGroupId=db2.source_component.get(pcbComponent.source_component_id)?.source_group_id;if(componentGroupId!==void 0&&!isDescendantGroup(db2,componentGroupId,currentGroupId))continue;let originalCenter2=pcbComponent.center,rotationDegrees2=ccwRotationDegrees??ccwRotationOffset??0,transformMatrix2=compose2(group._computePcbGlobalTransformBeforeLayout(),translate2(center2.x,center2.y),rotate2(rotationDegrees2*Math.PI/180),translate2(-originalCenter2.x,-originalCenter2.y)),related=db2.toArray().filter(elm=>"pcb_component_id"in elm&&elm.pcb_component_id===componentId);transformPCBElements(related,transformMatrix2),updateCadRotation({db:db2,pcbComponentId:componentId,rotationDegrees:rotationDegrees2,layer:pcbComponent.layer});continue}let pcbGroup=db2.pcb_group.list().find(g4=>g4.source_group_id===componentId);if(!pcbGroup)continue;let originalCenter=initialPackOutput.components.find(component=>component.componentId===componentId)?.center??pcbGroup.center,rotationDegrees=ccwRotationDegrees??ccwRotationOffset??0,transformMatrix=compose2(group._computePcbGlobalTransformBeforeLayout(),translate2(center2.x,center2.y),rotate2(rotationDegrees*Math.PI/180),translate2(-originalCenter.x,-originalCenter.y)),relatedElements=db2.toArray().filter(elm=>{if("source_group_id"in elm&&elm.source_group_id&&(elm.source_group_id===componentId||isDescendantGroup(db2,elm.source_group_id,componentId)))return!0;if("source_component_id"in elm&&elm.source_component_id){let sourceComponent=db2.source_component.get(elm.source_component_id);if(sourceComponent?.source_group_id&&(sourceComponent.source_group_id===componentId||isDescendantGroup(db2,sourceComponent.source_group_id,componentId)))return!0}if("pcb_component_id"in elm&&elm.pcb_component_id){let pcbComp=db2.pcb_component.get(elm.pcb_component_id);if(pcbComp?.source_component_id){let sourceComp=db2.source_component.get(pcbComp.source_component_id);if(sourceComp?.source_group_id&&(sourceComp.source_group_id===componentId||isDescendantGroup(db2,sourceComp.source_group_id,componentId)))return!0}}return!1});for(let elm of relatedElements)elm.type==="pcb_component"&&db2.pcb_component.update(elm.pcb_component_id,{position_mode:"packed"});transformPCBElements(relatedElements,transformMatrix),db2.pcb_group.update(pcbGroup.pcb_group_id,{center:center2})}if(group.pcb_group_id){let groupPcbComponents=db2.pcb_component.list({pcb_group_id:group.pcb_group_id});group.calculatePcbGroupBounds(findBoundsAndCenter(groupPcbComponents))}},normalizeLayer=layer=>(layer??"top").toLowerCase(),getComponentLayer=(component,db2)=>{let layers=new Set,directPcbComponent=db2.pcb_component.get(component.componentId);directPcbComponent&&layers.add(normalizeLayer(directPcbComponent.layer));for(let pad2 of component.pads){let via=db2.pcb_via.get(pad2.padId),pcbComponentId=db2.pcb_smtpad.get(pad2.padId)?.pcb_component_id??db2.pcb_plated_hole.get(pad2.padId)?.pcb_component_id??via?.pcb_component_id;if(!pcbComponentId)continue;let pcbComponent=db2.pcb_component.get(pcbComponentId);pcbComponent&&layers.add(normalizeLayer(pcbComponent.layer))}return layers.size===1?layers.values().next().value:void 0},getPackInputsByPcbLayer=(packInput,db2)=>{let componentsByLayer=new Map;for(let component of packInput.components){let layer=getComponentLayer(component,db2);if(!layer)return[packInput];let components=componentsByLayer.get(layer)??[];components.push(component),componentsByLayer.set(layer,components)}if(componentsByLayer.size<=1)return[packInput];let layerPriority=layer=>layer==="top"?0:layer==="bottom"?1:2;return Array.from(componentsByLayer.entries()).sort(([layerA],[layerB])=>layerPriority(layerA)-layerPriority(layerB)||layerA.localeCompare(layerB)).map(([,components])=>({...packInput,components}))},DEFAULT_MIN_GAP="1mm",debug42=(0,import_debug12.default)("Group_doInitialPcbLayoutPack"),Group_doInitialPcbLayoutPack=group=>{let{db:db2}=group.root,{_parsedProps:props}=group;group.root?.emit("packing:start",{subcircuit_id:group.subcircuit_id,componentDisplayName:group.getString()});let{packOrderStrategy,packPlacementStrategy,gap:gapProp,pcbGap,pcbPackGap}=props,gap=pcbPackGap??pcbGap??gapProp,gapMm=length.parse(gap??DEFAULT_MIN_GAP),chipMarginsMap={},staticPcbComponentIds=new Set,collectMargins=comp=>{if(comp?.pcb_component_id&&comp?._parsedProps){let props2=comp._parsedProps,left=length.parse(props2.pcbMarginLeft??props2.pcbMarginX??0),right=length.parse(props2.pcbMarginRight??props2.pcbMarginX??0),top=length.parse(props2.pcbMarginTop??props2.pcbMarginY??0),bottom=length.parse(props2.pcbMarginBottom??props2.pcbMarginY??0);(left||right||top||bottom)&&(chipMarginsMap[comp.pcb_component_id]={left,right,top,bottom})}comp?.children&&comp.children.forEach(collectMargins)};collectMargins(group);let excludedPcbGroupIds=new Set;for(let child of group.children){let childIsGroupOrNormalComponent=child;childIsGroupOrNormalComponent._isNormalComponent&&childIsGroupOrNormalComponent.isRelativelyPositioned?.()&&(childIsGroupOrNormalComponent.pcb_component_id&&staticPcbComponentIds.add(childIsGroupOrNormalComponent.pcb_component_id),childIsGroupOrNormalComponent.pcb_group_id&&excludedPcbGroupIds.add(childIsGroupOrNormalComponent.pcb_group_id))}let isDescendantGroup2=(db22,groupId,ancestorId)=>{if(groupId===ancestorId)return!0;let group2=db22.source_group.get(groupId);return!group2||!group2.parent_source_group_id?!1:isDescendantGroup2(db22,group2.parent_source_group_id,ancestorId)};if(excludedPcbGroupIds.size>0)for(let element of db2.toArray()){if(element.type!=="pcb_component")continue;let sourceComponent=db2.source_component.get(element.source_component_id);if(sourceComponent?.source_group_id)for(let groupId of excludedPcbGroupIds)isDescendantGroup2(db2,sourceComponent.source_group_id,groupId)&&staticPcbComponentIds.add(element.pcb_component_id)}let filteredCircuitJson=db2.toArray(),bounds;if(props.width!==void 0&&props.height!==void 0){let widthMm=length.parse(props.width),heightMm=length.parse(props.height);bounds={minX:-widthMm/2,maxX:widthMm/2,minY:-heightMm/2,maxY:heightMm/2}}let initialPackOutput=convertCircuitJsonToPackOutput(filteredCircuitJson,{source_group_id:group.source_group_id,chipMarginsMap,staticPcbComponentIds:Array.from(staticPcbComponentIds)}),packInput={...convertPackOutputToPackInput(initialPackOutput),packOrderStrategy:packOrderStrategy??"largest_to_smallest",packPlacementStrategy:packPlacementStrategy??"minimum_sum_squared_distance_to_network",minGap:gapMm,bounds},clusterMap=applyComponentConstraintClusters(group,packInput);debug42.enabled&&(group.root?.emit("debug:logOutput",{type:"debug:logOutput",name:`packInput-circuitjson-${group.name}`,content:JSON.stringify(db2.toArray())}),group.root?.emit("debug:logOutput",{type:"debug:logOutput",name:`packInput-${group.name}`,content:packInput}));let packInputs=getPackInputsByPcbLayer(packInput,db2),packOutput={...packInput,components:[]},packingFailed=!1,reportPackingError=solverErrorMessage=>{let message=`Unable to pack all PCB components within the layout bounds: ${solverErrorMessage}`;db2.pcb_packing_error.insert({error_type:"pcb_packing_error",message,pcb_group_id:group.pcb_group_id??void 0,subcircuit_id:group.subcircuit_id??void 0}),group.root?.emit("packing:error",{subcircuit_id:group.subcircuit_id,componentDisplayName:group.getString(),error:{message}})};try{for(let layerPackInput of packInputs){let componentIdsForLayer=new Set(layerPackInput.components.map(component=>component.componentId)),networkReferenceComponents=packOutput.components.map(component=>({...component,componentId:`network_reference_${component.componentId}`,isStatic:!0,courtyard:{offsetFromCenter:{x:0,y:0},width:Number.EPSILON,height:Number.EPSILON}})),solverInput={...layerPackInput,components:[...networkReferenceComponents,...layerPackInput.components]},solver=new PackSolver2(solverInput),solverParams=solver.getConstructorParams();group.root?.emit("solver:started",{type:"solver:started",solverName:"PackSolver2",solverParams,solverConstructorArgs:[solverParams],componentName:group.getString()});let pcbPackSolverTimeoutMs=group.root?.platform?.pcbPackSolverTimeoutMs,{timedOut}=solvePackSolverWithTimeout(solver,pcbPackSolverTimeoutMs);if(timedOut&&(packingFailed=!0,reportPackingError(`PackSolver2 timed out after ${pcbPackSolverTimeoutMs}ms`)),solver.failed){packingFailed=!0;let solverErrorMessage=solver.error??solver.activeSubSolver?.error??"No valid packing solution found";reportPackingError(solverErrorMessage)}if(packOutput.components.push(...solver.packedComponents.filter(component=>componentIdsForLayer.has(component.componentId))),timedOut)break}}catch(error2){throw reportPackingError(error2 instanceof Error?error2.message:String(error2)),error2}if(debug42.enabled&&global?.debugGraphics){let graphics=getGraphicsFromPackOutput(packOutput);graphics.title=`packOutput-${group.name}`,global.debugGraphics?.push(graphics)}applyPackOutput(group,packOutput,clusterMap,initialPackOutput),!packingFailed&&group.root?.emit("packing:end",{subcircuit_id:group.subcircuit_id,componentDisplayName:group.getString()})},parsePinNumberFromPortName=name=>{if(!name)return null;let match2=name.match(/^pin(\d+)$/i)??name.match(/^(\d+)$/);if(!match2)return null;let pinNumber=Number(match2[1]);return Number.isFinite(pinNumber)&&pinNumber>0?pinNumber:null},getDirectGroupPorts=group=>group.children.filter(child=>child.componentName==="Port"),normalizeGroupSchematicBoxPorts=group=>{let{db:db2}=group.root,ports=getDirectGroupPorts(group);for(let port of ports){if(port._parsedProps.pinNumber!==void 0)continue;let pinNumber=parsePinNumberFromPortName(port._parsedProps.name);pinNumber!==null&&(port._parsedProps.pinNumber=pinNumber)}let usedPinNumbers=new Set(ports.map(port=>port._parsedProps.pinNumber).filter(pinNumber=>pinNumber!==void 0)),nextPinNumber=1;for(let port of ports){if(port._parsedProps.pinNumber===void 0){for(;usedPinNumbers.has(nextPinNumber);)nextPinNumber++;port._parsedProps.pinNumber=nextPinNumber,usedPinNumbers.add(nextPinNumber)}port.source_port_id&&db2.source_port.update(port.source_port_id,{pin_number:port._parsedProps.pinNumber,port_hints:port.getNameAndAliases()})}},getGroupSchematicBoxPinLabels=group=>{let pinLabels={};for(let port of getDirectGroupPorts(group)){let pinNumber=port._parsedProps.pinNumber,name=port._parsedProps.name;pinNumber===void 0||!name||name===`pin${pinNumber}`||name===String(pinNumber)||(pinLabels[`pin${pinNumber}`]=name)}return pinLabels},Group_doInitialSchematicBoxComponentRender=group=>{if(group.root?.schematicDisabled)return;let{db:db2}=group.root,props=group._parsedProps;props.schPinSpacing!==void 0&&db2.source_property_ignored_warning.insert({source_component_id:group.source_group_id??"",property_name:"schPinSpacing",error_type:"source_property_ignored_warning",message:"schPinSpacing is deprecated and will be ignored. Pin spacing is always 0.2."}),normalizeGroupSchematicBoxPorts(group);let dimensions=group._getSchematicBoxDimensions();if(!dimensions)return;let center2=group._getGlobalSchematicPositionBeforeLayout(),size3=dimensions.getSize(),portLabels=group._getPinLabelsFromPorts(),schPortArrangement=group._getSchematicPortArrangement(),schematicComponent=db2.schematic_component.insert({center:center2,size:size3,source_group_id:group.source_group_id,schematic_group_id:group.schematic_group_id??void 0,subcircuit_id:group.subcircuit_id??group.getSubcircuit()?.subcircuit_id??void 0,is_schematic_group:!0,is_box_with_pins:!0,port_arrangement:underscorifyPortArrangement(schPortArrangement),pin_spacing:.2,pin_styles:underscorifyPinStyles(props.schPinStyle,portLabels),port_labels:portLabels,schematic_sheet_id:group._resolveSchematicSheetId()});group.schematic_component_id=schematicComponent.schematic_component_id,group.schematic_group_id&&db2.schematic_group.update(group.schematic_group_id,{center:center2,width:size3.width,height:size3.height,schematic_component_ids:[schematicComponent.schematic_component_id]});let title=props.schTitle??props.name;title&&db2.schematic_text.insert({text:title,schematic_component_id:schematicComponent.schematic_component_id,anchor:"left",rotation:0,position:{x:center2.x-size3.width/2,y:center2.y+size3.height/2+.13},color:"#006464",font_size:.18,schematic_sheet_id:group._resolveSchematicSheetId()})},getSizeOfTreeNodeChild=(db2,child)=>{let{sourceComponent,sourceGroup}=child;if(child.nodeType==="component"){let schComponent=db2.schematic_component.getWhere({source_component_id:sourceComponent?.source_component_id});return schComponent?.size?{width:schComponent.size.width,height:schComponent.size.height}:null}if(child.nodeType==="group"){let schGroup=db2.schematic_group.getWhere({source_group_id:sourceGroup?.source_group_id});if(schGroup?.width&&schGroup?.height)return{width:schGroup.width,height:schGroup.height};let groupComponents=db2.schematic_component.list({schematic_group_id:schGroup?.schematic_group_id}),minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let comp of groupComponents)if(comp.center&&comp.size){let halfWidth=comp.size.width/2,halfHeight=comp.size.height/2;minX=Math.min(minX,comp.center.x-halfWidth),maxX=Math.max(maxX,comp.center.x+halfWidth),minY=Math.min(minY,comp.center.y-halfHeight),maxY=Math.max(maxY,comp.center.y+halfHeight)}let groupWidth=maxX-minX,groupHeight=maxY-minY;return{width:groupWidth,height:groupHeight}}return null},Group_doInitialSchematicLayoutFlex=group=>{let{db:db2}=group.root,props=group._parsedProps,tree=getCircuitJsonTree(db2.toArray(),{source_group_id:group.source_group_id}),rawJustify=props.schJustifyContent??props.justifyContent,rawAlign=props.schAlignItems??props.alignItems,rawGap=props.schFlexGap??props.schGap??props.gap,direction2=props.schFlexDirection??"row",justifyContent={start:"flex-start",end:"flex-end","flex-start":"flex-start","flex-end":"flex-end",stretch:"space-between","space-between":"space-between","space-around":"space-around","space-evenly":"space-evenly",center:"center"}[rawJustify??"space-between"],alignItems={start:"flex-start",end:"flex-end","flex-start":"flex-start","flex-end":"flex-end",stretch:"stretch",center:"center"}[rawAlign??"center"];if(!justifyContent)throw new Error(`Invalid justifyContent value: "${rawJustify}"`);if(!alignItems)throw new Error(`Invalid alignItems value: "${rawAlign}"`);let rowGap=0,columnGap=0;typeof rawGap=="object"?(rowGap=rawGap.y??0,columnGap=rawGap.x??0):typeof rawGap=="number"?(rowGap=rawGap,columnGap=rawGap):typeof rawGap=="string"&&(rowGap=length.parse(rawGap),columnGap=length.parse(rawGap));let minFlexContainer,width=props.width??props.schWidth??void 0,height=props.height??props.schHeight??void 0;(width===void 0||height===void 0)&&(minFlexContainer=getMinimumFlexContainer(tree.childNodes.map(child=>getSizeOfTreeNodeChild(db2,child)).filter(size3=>size3!==null),{alignItems,justifyContent,direction:direction2,rowGap,columnGap}),width=minFlexContainer.width,height=minFlexContainer.height);let flexBox=new RootFlexBox(width,height,{alignItems,justifyContent,direction:direction2,rowGap,columnGap});for(let child of tree.childNodes){let size3=getSizeOfTreeNodeChild(db2,child);flexBox.addChild({metadata:child,width:size3?.width??0,height:size3?.height??0,flexBasis:size3?direction2==="row"?size3.width:size3.height:void 0})}flexBox.build();let bounds={minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0,width:0,height:0};for(let child of flexBox.children)bounds.minX=Math.min(bounds.minX,child.position.x),bounds.minY=Math.min(bounds.minY,child.position.y),bounds.maxX=Math.max(bounds.maxX,child.position.x+child.size.width),bounds.maxY=Math.max(bounds.maxY,child.position.y+child.size.height);bounds.width=bounds.maxX-bounds.minX,bounds.height=bounds.maxY-bounds.minY;let offset={x:-(bounds.maxX+bounds.minX)/2,y:-(bounds.maxY+bounds.minY)/2},allCircuitJson=db2.toArray();for(let child of flexBox.children){let{sourceComponent,sourceGroup}=child.metadata;if(sourceComponent){let schComponent=db2.schematic_component.getWhere({source_component_id:sourceComponent.source_component_id});if(!schComponent)continue;repositionSchematicComponentTo(allCircuitJson,schComponent.schematic_component_id,{x:child.position.x+child.size.width/2+offset.x,y:child.position.y+child.size.height/2+offset.y})}if(sourceGroup){if(!db2.schematic_group.getWhere({source_group_id:sourceGroup.source_group_id}))continue;repositionSchematicGroupTo(allCircuitJson,sourceGroup.source_group_id,{x:child.position.x+child.size.width/2+offset.x,y:child.position.y+child.size.height/2+offset.y})}}group.schematic_group_id&&db2.schematic_group.update(group.schematic_group_id,{width:bounds.width,height:bounds.height})};function updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId,deltaX,deltaY}){let rects=db2.schematic_rect.list({schematic_component_id:schematicComponentId});for(let rect of rects)rect.center.x+=deltaX,rect.center.y+=deltaY;let lines=db2.schematic_line.list({schematic_component_id:schematicComponentId});for(let line2 of lines)line2.x1+=deltaX,line2.y1+=deltaY,line2.x2+=deltaX,line2.y2+=deltaY;let circles=db2.schematic_circle.list({schematic_component_id:schematicComponentId});for(let circle2 of circles)circle2.center.x+=deltaX,circle2.center.y+=deltaY;let arcs=db2.schematic_arc.list({schematic_component_id:schematicComponentId});for(let arc2 of arcs)arc2.center.x+=deltaX,arc2.center.y+=deltaY;let paths=db2.schematic_path.list({schematic_component_id:schematicComponentId});for(let path of paths)for(let point6 of path.points)point6.x+=deltaX,point6.y+=deltaY}function Group_doInitialSchematicLayoutGrid(group){let{db:db2}=group.root,props=group._parsedProps,schematicChildren=group.children.filter(child=>{let isExplicitlyPositioned=child._parsedProps?.schX!==void 0||child._parsedProps?.schY!==void 0;return child.schematic_component_id&&!isExplicitlyPositioned});if(schematicChildren.length===0)return;let maxCellWidth=0,maxCellHeight=0;for(let child of schematicChildren){let schComp=db2.schematic_component.get(child.schematic_component_id);schComp?.size&&(maxCellWidth=Math.max(maxCellWidth,schComp.size.width),maxCellHeight=Math.max(maxCellHeight,schComp.size.height))}maxCellWidth===0&&schematicChildren.length>0&&(maxCellWidth=1),maxCellHeight===0&&schematicChildren.length>0&&(maxCellHeight=1);let gridColsOption=props.gridCols,gridRowsOption,gridGapOption=props.gridGap,gridRowGapOption=props.gridRowGap,gridColumnGapOption=props.gridColumnGap;props.schLayout?.grid&&(gridColsOption=props.schLayout.grid.cols??gridColsOption,gridRowsOption=props.schLayout.grid.rows,gridGapOption=props.schLayout.gridGap??gridGapOption,gridRowGapOption=props.schLayout.gridRowGap??gridRowGapOption,gridColumnGapOption=props.schLayout.gridColumnGap??gridColumnGapOption);let numCols,numRows;gridColsOption!==void 0&&gridRowsOption!==void 0?(numCols=gridColsOption,numRows=gridRowsOption):gridColsOption!==void 0?(numCols=gridColsOption,numRows=Math.ceil(schematicChildren.length/numCols)):gridRowsOption!==void 0?(numRows=gridRowsOption,numCols=Math.ceil(schematicChildren.length/numRows)):(numCols=Math.ceil(Math.sqrt(schematicChildren.length)),numRows=Math.ceil(schematicChildren.length/numCols)),numCols===0&&schematicChildren.length>0&&(numCols=1),numRows===0&&schematicChildren.length>0&&(numRows=schematicChildren.length);let gridGapX,gridGapY,parseGap=val=>{if(val!==void 0)return typeof val=="number"?val:length.parse(val)};if(gridRowGapOption!==void 0||gridColumnGapOption!==void 0){let fallbackX=typeof gridGapOption=="object"&&gridGapOption!==null?gridGapOption.x:gridGapOption,fallbackY=typeof gridGapOption=="object"&&gridGapOption!==null?gridGapOption.y:gridGapOption;gridGapX=parseGap(gridColumnGapOption??fallbackX)??1,gridGapY=parseGap(gridRowGapOption??fallbackY)??1}else if(typeof gridGapOption=="number")gridGapX=gridGapOption,gridGapY=gridGapOption;else if(typeof gridGapOption=="string"){let parsed=length.parse(gridGapOption);gridGapX=parsed,gridGapY=parsed}else if(typeof gridGapOption=="object"&&gridGapOption!==null){let xRaw=gridGapOption.x,yRaw=gridGapOption.y;gridGapX=typeof xRaw=="number"?xRaw:length.parse(xRaw??"0mm"),gridGapY=typeof yRaw=="number"?yRaw:length.parse(yRaw??"0mm")}else gridGapX=1,gridGapY=1;let totalGridWidth=numCols*maxCellWidth+Math.max(0,numCols-1)*gridGapX,totalGridHeight=numRows*maxCellHeight+Math.max(0,numRows-1)*gridGapY,groupCenter=group._getGlobalSchematicPositionBeforeLayout(),firstCellCenterX=groupCenter.x-totalGridWidth/2+maxCellWidth/2,firstCellCenterY=groupCenter.y+totalGridHeight/2-maxCellHeight/2;for(let i6=0;i6<schematicChildren.length;i6++){let child=schematicChildren[i6];if(!child.schematic_component_id)continue;let row=Math.floor(i6/numCols),col=i6%numCols;if(row>=numRows||col>=numCols){console.warn(`Schematic grid layout: Child ${child.getString()} at index ${i6} (row ${row}, col ${col}) exceeds specified grid dimensions (${numRows}x${numCols}). Skipping placement.`);continue}let targetCellCenterX=firstCellCenterX+col*(maxCellWidth+gridGapX),targetCellCenterY=firstCellCenterY-row*(maxCellHeight+gridGapY),schComp=db2.schematic_component.get(child.schematic_component_id);if(schComp){let oldChildCenter=schComp.center,newChildCenter={x:targetCellCenterX,y:targetCellCenterY};db2.schematic_component.update(child.schematic_component_id,{center:newChildCenter});let deltaX=newChildCenter.x-oldChildCenter.x,deltaY=newChildCenter.y-oldChildCenter.y,schPorts=db2.schematic_port.list({schematic_component_id:child.schematic_component_id});for(let port of schPorts)db2.schematic_port.update(port.schematic_port_id,{center:{x:port.center.x+deltaX,y:port.center.y+deltaY}});let schTexts=db2.schematic_text.list({schematic_component_id:child.schematic_component_id});for(let text of schTexts)db2.schematic_text.update(text.schematic_text_id,{position:{x:text.position.x+deltaX,y:text.position.y+deltaY}});updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId:child.schematic_component_id,deltaX,deltaY})}}group.schematic_group_id&&db2.schematic_group.update(group.schematic_group_id,{width:totalGridWidth,height:totalGridHeight,center:groupCenter})}var debug52=(0,import_debug13.default)("Group_doInitialSchematicLayoutMatchAdapt");function Group_doInitialSchematicLayoutMatchAdapt(group){let{db:db2}=group.root,subtreeCircuitJson=buildSubtree(db2.toArray(),{source_group_id:group.source_group_id});if(subtreeCircuitJson.filter(item=>item.type==="source_component").length<=1)return;let floatingGraph=convertCircuitJsonToBpc(subtreeCircuitJson);debug52.enabled&&global?.debugGraphics&&global.debugGraphics?.push(getGraphicsForBpcGraph(floatingGraph,{title:`floatingBpcGraph-${group.name}`}));let floatingGraphNoNotConnected={boxes:floatingGraph.boxes,pins:floatingGraph.pins.map(p3=>({...p3,color:p3.color.replace("not_connected","normal")}))},{result:laidOutBpcGraph}=layoutSchematicGraphVariants([{variantName:"default",floatingGraph},{variantName:"noNotConnected",floatingGraph:floatingGraphNoNotConnected}],{singletonKeys:["vcc/2","gnd/2"],centerPinColors:["netlabel_center","component_center"],floatingBoxIdsWithMutablePinOffsets:new Set(floatingGraph.boxes.filter(box2=>floatingGraph.pins.filter(p3=>p3.boxId===box2.boxId).filter(bp3=>!bp3.color.includes("center")).length<=2).map(b6=>b6.boxId)),corpus:{}});debug52.enabled&&global?.debugGraphics&&global.debugGraphics?.push(getGraphicsForBpcGraph(laidOutBpcGraph,{title:`laidOutBpcGraph-${group.name}`}));let groupOffset=group._getGlobalSchematicPositionBeforeLayout();for(let box2 of laidOutBpcGraph.boxes){if(!box2.center)continue;let schematic_component22=db2.schematic_component.get(box2.boxId);if(schematic_component22){let newCenter={x:box2.center.x+groupOffset.x,y:box2.center.y+groupOffset.y},ports=db2.schematic_port.list({schematic_component_id:schematic_component22.schematic_component_id}),texts=db2.schematic_text.list({schematic_component_id:schematic_component22.schematic_component_id}),positionDelta={x:newCenter.x-schematic_component22.center.x,y:newCenter.y-schematic_component22.center.y};for(let port of ports)port.center.x+=positionDelta.x,port.center.y+=positionDelta.y;for(let text of texts)text.position.x+=positionDelta.x,text.position.y+=positionDelta.y;updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId:schematic_component22.schematic_component_id,deltaX:positionDelta.x,deltaY:positionDelta.y}),schematic_component22.center=newCenter;continue}let schematic_net_label3=db2.schematic_net_label.get(box2.boxId);if(schematic_net_label3){let pin=laidOutBpcGraph.pins.find(p3=>p3.boxId===box2.boxId&&p3.color==="netlabel_center");if(!pin)throw new Error(`No pin found for net label: ${box2.boxId}`);let finalCenter={x:box2.center.x+groupOffset.x,y:box2.center.y+groupOffset.y};schematic_net_label3.center=finalCenter,schematic_net_label3.anchor_position={x:finalCenter.x+pin.offset.x,y:finalCenter.y+pin.offset.y};continue}console.error(`No schematic element found for box: ${box2.boxId}. This is a bug in the matchAdapt binding with @tscircuit/core`)}}function getSchematicTextWidth({text,fontSize}){let charWidth=.12*(fontSize/.18);return text.length*charWidth}var SYMBOL_TEXT_FONT_SIZE=.18,TEXT_BOX_ENABLED_FTYPES=new Set(["simple_resistor","simple_capacitor","simple_inductor","simple_crystal","simple_resonator","simple_potentiometer","simple_fuse","simple_diode","simple_led","simple_transistor","simple_mosfet","simple_op_amp","simple_voltage_source","simple_test_point"]);function getTextBounds({text,position:position4,anchor,fontSize}){let width=getSchematicTextWidth({text,fontSize}),height=fontSize,relMinX,relMaxX;anchor.includes("left")?(relMinX=0,relMaxX=width):anchor.includes("right")?(relMinX=-width,relMaxX=0):(relMinX=-width/2,relMaxX=width/2);let relMinY,relMaxY;return anchor.includes("top")?(relMinY=-height,relMaxY=0):anchor.includes("bottom")?(relMinY=0,relMaxY=height):(relMinY=-height/2,relMaxY=height/2),{minX:position4.x+relMinX,maxX:position4.x+relMaxX,minY:position4.y+relMinY,maxY:position4.y+relMaxY}}function getSymbolTextBounds({schematicComponent,sourceComponent}){if(!schematicComponent.symbol_name)return[];let symbol=hc[schematicComponent.symbol_name];if(!symbol?.primitives||!symbol.center)return[];let textBounds=[];for(let primitive of symbol.primitives){if(primitive.type!=="text")continue;let value;primitive.text==="{REF}"?value=sourceComponent?.display_name??sourceComponent?.name??"":primitive.text==="{VAL}"?value=schematicComponent.symbol_display_value??"":value=primitive.text??"",value&&textBounds.push(getTextBounds({text:value,position:{x:primitive.x-symbol.center.x+schematicComponent.center.x,y:primitive.y-symbol.center.y+schematicComponent.center.y},anchor:primitive.anchor??"center",fontSize:SYMBOL_TEXT_FONT_SIZE}))}return textBounds}function getSymbolBoxBounds(schematicComponent){return getBoundFromCenteredRect({center:schematicComponent.center,width:schematicComponent.size.width,height:schematicComponent.size.height})}function getSchematicComponentTextInclusiveBounds(db2,schematicComponent){if(!schematicComponent.center||!schematicComponent.size)return null;let sourceComponent=schematicComponent.source_component_id?db2.source_component.get(schematicComponent.source_component_id):void 0;if(!sourceComponent||!TEXT_BOX_ENABLED_FTYPES.has(sourceComponent.ftype))return null;let textBounds=getSymbolTextBounds({schematicComponent,sourceComponent});if(textBounds.length===0)return null;let boxBounds=getSymbolBoxBounds(schematicComponent),bounds={...boxBounds};for(let textBound of textBounds)bounds.minX=Math.min(bounds.minX,textBound.minX),bounds.maxX=Math.max(bounds.maxX,textBound.maxX),bounds.minY=Math.min(bounds.minY,textBound.minY),bounds.maxY=Math.max(bounds.maxY,textBound.maxY);return bounds.minX===boxBounds.minX&&bounds.maxX===boxBounds.maxX&&bounds.minY===boxBounds.minY&&bounds.maxY===boxBounds.maxY?null:bounds}function getOrientedSchematicComponent(schematicComponent,ccwRotationDegrees){let size3=schematicComponent.size;return size3&&(size3=getRotatedSize2(size3,ccwRotationDegrees)),{...schematicComponent,symbol_name:getRotatedSymbolName(schematicComponent.symbol_name,ccwRotationDegrees),size:size3}}function getSchematicComponentWithTextBounds({db:db2,schematicComponent,ccwRotationDegrees=0}){let orientedComponent=getOrientedSchematicComponent(schematicComponent,ccwRotationDegrees),textBounds=getSchematicComponentTextInclusiveBounds(db2,orientedComponent);if(!textBounds)return null;let boxBounds=getSymbolBoxBounds(orientedComponent);if(orientedComponent.size.height>orientedComponent.size.width)return textBounds;let padLeft=Math.max(0,boxBounds.minX-textBounds.minX),padRight=Math.max(0,textBounds.maxX-boxBounds.maxX),padTop=Math.max(0,textBounds.maxY-boxBounds.maxY),padBottom=Math.max(0,boxBounds.minY-textBounds.minY),left=padLeft,right=padRight;padLeft>0&&padRight>0&&(left=Math.max(padLeft,padRight),right=left);let top=padTop,bottom=padBottom;return padTop>0&&padBottom>0&&(top=Math.max(padTop,padBottom),bottom=top),{minX:boxBounds.minX-left,maxX:boxBounds.maxX+right,minY:boxBounds.minY-bottom,maxY:boxBounds.maxY+top}}var debug62=(0,import_debug14.default)("Group_doInitialSchematicLayoutMatchpack"),DEFAULT_AVAILABLE_ROTATIONS=[0,90,180,270],ROTATION_TO_PLACE_SIDE_ON_TOP={"y+":0,"x+":90,"y-":180,"x-":270};function facingDirectionToSide(facingDirection){switch(facingDirection){case"up":return"y+";case"down":return"y-";case"left":return"x-";case"right":return"x+";default:return"y+"}}function getPowerGroundForcedRotation(db2,ports){if(ports.length!==2)return null;let powerGroundRotations=new Set;for(let port of ports){let connectivityKey=db2.source_port.get(port.source_port_id)?.subcircuit_connectivity_map_key;if(!connectivityKey)continue;let net=db2.source_net.getWhere({subcircuit_connectivity_map_key:connectivityKey});if(!net)continue;let isGround=net.is_ground??!1,isPositiveVoltageSource=net.is_power===!0||net.is_positive_voltage_source===!0;if(isPositiveVoltageSource===isGround)continue;let rotationToPlacePinOnTop=ROTATION_TO_PLACE_SIDE_ON_TOP[facingDirectionToSide(port.facing_direction)],rotation42=isPositiveVoltageSource?rotationToPlacePinOnTop:(rotationToPlacePinOnTop+180)%360;powerGroundRotations.add(rotation42)}return powerGroundRotations.size===1?powerGroundRotations.values().next().value:null}function getChipSize({db:db2,schematicComponent,component,ccwRotationDegrees}){let orientedSymbolSize=schematicComponent.size;orientedSymbolSize&&(orientedSymbolSize=getRotatedSize2(orientedSymbolSize,ccwRotationDegrees));let componentWithTextBounds=getSchematicComponentWithTextBounds({db:db2,schematicComponent,ccwRotationDegrees}),textPadLeft=0,textPadRight=0,textPadTop=0,textPadBottom=0;if(componentWithTextBounds&&schematicComponent.center){let halfWidth=(orientedSymbolSize?.width??0)/2,halfHeight=(orientedSymbolSize?.height??0)/2;textPadLeft=schematicComponent.center.x-halfWidth-componentWithTextBounds.minX,textPadRight=componentWithTextBounds.maxX-(schematicComponent.center.x+halfWidth),textPadTop=componentWithTextBounds.maxY-(schematicComponent.center.y+halfHeight),textPadBottom=schematicComponent.center.y-halfHeight-componentWithTextBounds.minY}let marginLeft=(component?._parsedProps?.schMarginLeft??component?._parsedProps?.schMarginX??0)+textPadLeft,marginRight=(component?._parsedProps?.schMarginRight??component?._parsedProps?.schMarginX??0)+textPadRight,marginTop=(component?._parsedProps?.schMarginTop??component?._parsedProps?.schMarginY??0)+textPadTop,marginBottom=(component?._parsedProps?.schMarginBottom??component?._parsedProps?.schMarginY??0)+textPadBottom;component?.config.shouldRenderAsSchematicBox&&(marginTop+=.4,marginBottom+=.4);let orientedFootprint={width:(orientedSymbolSize?.width||1)+marginLeft+marginRight,height:(orientedSymbolSize?.height||1)+marginTop+marginBottom},chipSize=getRotatedSize2(orientedFootprint,ccwRotationDegrees);return{x:chipSize.width,y:chipSize.height}}function getReservedChipSize({db:db2,schematicComponent,component,ccwRotationDegrees,chipGap}){let unrotatedSize=getChipSize({db:db2,schematicComponent,component,ccwRotationDegrees:0});if(!shouldSwapOrientation(ccwRotationDegrees))return unrotatedSize;let rotatedSize=getChipSize({db:db2,schematicComponent,component,ccwRotationDegrees});return rotatedSize.x-unrotatedSize.x>=chipGap||rotatedSize.y-unrotatedSize.y>=chipGap?rotatedSize:unrotatedSize}function getNestedGroupMatchpackProxy({db:db2,schematicGroup,groupComponents,groupInstance}){let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0,hasValidBounds=!1;for(let component of groupComponents){if(!component.center||!component.size)continue;hasValidBounds=!0;let componentBounds=getSchematicComponentWithTextBounds({db:db2,schematicComponent:component})??getBoundFromCenteredRect({center:component.center,width:component.size.width,height:component.size.height});minX=Math.min(minX,componentBounds.minX),maxX=Math.max(maxX,componentBounds.maxX),minY=Math.min(minY,componentBounds.minY),maxY=Math.max(maxY,componentBounds.maxY)}let marginLeft=groupInstance?._parsedProps?.schMarginLeft??groupInstance?._parsedProps?.schMarginX??0,marginRight=groupInstance?._parsedProps?.schMarginRight??groupInstance?._parsedProps?.schMarginX??0,marginTop=groupInstance?._parsedProps?.schMarginTop??groupInstance?._parsedProps?.schMarginY??0,marginBottom=groupInstance?._parsedProps?.schMarginBottom??groupInstance?._parsedProps?.schMarginY??0,contentCenter=hasValidBounds?{x:(minX+maxX)/2,y:(minY+maxY)/2}:schematicGroup.center??{x:0,y:0};return{center:{x:contentCenter.x+(marginRight-marginLeft)/2,y:contentCenter.y+(marginTop-marginBottom)/2},size:{x:(hasValidBounds?maxX-minX:2)+marginLeft+marginRight,y:(hasValidBounds?maxY-minY:2)+marginTop+marginBottom}}}function isTreeChildExplicitlyPositioned(treeChild,group){if(treeChild.nodeType==="component"&&treeChild.sourceComponent){let component=group.children.find(groupChild=>groupChild.source_component_id===treeChild.sourceComponent?.source_component_id);return component?._parsedProps?.schX!==void 0||component?._parsedProps?.schY!==void 0}if(treeChild.nodeType==="group"&&treeChild.sourceGroup){let nestedGroup=group.children.find(groupChild=>groupChild.source_group_id===treeChild.sourceGroup?.source_group_id);return nestedGroup?._parsedProps?.schX!==void 0||nestedGroup?._parsedProps?.schY!==void 0}return!1}function getTreeChildChipId(child,index){return child.nodeType==="component"&&child.sourceComponent?child.sourceComponent.name||`chip_${index}`:child.nodeType==="group"&&child.sourceGroup?child.sourceGroup.name||`group_${index}`:null}var getSchematicComponentForSourceComponent=({db:db2,sourceComponentId,schematicSheetId})=>db2.schematic_component.getWhere({source_component_id:sourceComponentId,...schematicSheetId?{schematic_sheet_id:schematicSheetId}:{}});function convertTreeToMatchPackInputProblem(tree,db2,group,opts={}){let problem={chipMap:{},chipPinMap:{},netMap:{},pinStrongConnMap:{},netConnMap:{},chipGap:.6,decouplingCapsGap:.4,partitionGap:1.2},nestedGroupMatchpackProxyMap={},groupOffset=group._getGlobalSchematicPositionBeforeLayout();debug62(`[${group.name}] Processing ${tree.childNodes.length} child nodes for input problem`),tree.childNodes.forEach((child,index)=>{let explicitlyPositioned=isTreeChildExplicitlyPositioned(child,group);if(debug62(explicitlyPositioned?`[${group.name}] Child ${index} explicitly positioned, including as fixed chip`:`[${group.name}] Processing child ${index}: nodeType=${child.nodeType}`),child.nodeType==="component"?debug62(`[${group.name}] - Component: ${child.sourceComponent?.name}`):child.nodeType==="group"&&debug62(`[${group.name}] - Group: ${child.sourceGroup?.name}`),child.nodeType==="component"&&child.sourceComponent){let chipId=getTreeChildChipId(child,index),schematicComponent=getSchematicComponentForSourceComponent({db:db2,sourceComponentId:child.sourceComponent.source_component_id,schematicSheetId:opts.schematicSheetId});if(!schematicComponent)return;let component=group.children.find(groupChild=>groupChild.source_component_id===child.sourceComponent?.source_component_id),ports=db2.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id}),availableRotations=[...DEFAULT_AVAILABLE_ROTATIONS];if(component?._parsedProps?.schOrientation&&(availableRotations=[0]),component?._parsedProps?.schRotation!==void 0&&(availableRotations=[0]),component?._parsedProps?.facingDirection&&(availableRotations=[0]),component?._parsedProps?.schFacingDirection&&(availableRotations=[0]),component?.componentName==="Chip"&&(availableRotations=[0]),availableRotations.length===DEFAULT_AVAILABLE_ROTATIONS.length){let forcedRotation=getPowerGroundForcedRotation(db2,ports);forcedRotation!==null&&(availableRotations=[forcedRotation])}let ccwRotationDegrees=availableRotations.length===1?availableRotations[0]:0;problem.chipMap[chipId]={chipId,pins:[],size:getReservedChipSize({db:db2,schematicComponent,component,ccwRotationDegrees,chipGap:problem.chipGap}),isCapacitor:child.sourceComponent.ftype==="simple_capacitor",isCrystal:child.sourceComponent.ftype==="simple_crystal",isResistor:child.sourceComponent.ftype==="simple_resistor",isTestPoint:child.sourceComponent.ftype==="simple_test_point",availableRotations,...explicitlyPositioned&&{fixedPosition:{x:schematicComponent.center.x-groupOffset.x,y:schematicComponent.center.y-groupOffset.y}}};for(let port of ports){let sourcePort=db2.source_port.get(port.source_port_id);if(!sourcePort)continue;let pinId=`${chipId}.${sourcePort.pin_number||sourcePort.name||port.schematic_port_id}`;problem.chipMap[chipId].pins.push(pinId);let side=facingDirectionToSide(port.facing_direction);problem.chipPinMap[pinId]={pinId,offset:{x:(port.center?.x||0)-(schematicComponent.center.x||0),y:(port.center?.y||0)-(schematicComponent.center.y||0)},side}}}else if(child.nodeType==="group"&&child.sourceGroup){let groupId=getTreeChildChipId(child,index);debug62(`[${group.name}] Processing nested group: ${groupId}`);let schematicGroup=db2.schematic_group?.getWhere?.({source_group_id:child.sourceGroup.source_group_id}),groupInstance=group.children.find(groupChild=>groupChild.source_group_id===child.sourceGroup?.source_group_id);if(debug62(`[${group.name}] Found schematic_group for ${groupId}:`,schematicGroup),schematicGroup){debug62(`[${group.name}] Treating group ${groupId} as composite chip`);let groupComponents=db2.schematic_component.list({schematic_group_id:schematicGroup.schematic_group_id});debug62(`[${group.name}] Group ${groupId} has ${groupComponents.length} components:`,groupComponents.map(c3=>c3.source_component_id));let matchpackProxy=getNestedGroupMatchpackProxy({db:db2,schematicGroup,groupComponents,groupInstance});nestedGroupMatchpackProxyMap[groupId]=matchpackProxy,debug62(`[${group.name}] Group ${groupId} computed proxy: ${matchpackProxy.size.x} x ${matchpackProxy.size.y} centered at (${matchpackProxy.center.x}, ${matchpackProxy.center.y})`);let groupPins=[];for(let comp of groupComponents){let ports=db2.schematic_port.list({schematic_component_id:comp.schematic_component_id});for(let port of ports){let sourcePort=db2.source_port.get(port.source_port_id);if(!sourcePort)continue;let pinId=`${groupId}.${sourcePort.pin_number||sourcePort.name||port.schematic_port_id}`;groupPins.push(pinId);let side=facingDirectionToSide(port.facing_direction);problem.chipPinMap[pinId]={pinId,offset:{x:(port.center?.x||0)-matchpackProxy.center.x,y:(port.center?.y||0)-matchpackProxy.center.y},side}}}debug62(`[${group.name}] Group ${groupId} has ${groupPins.length} pins:`,groupPins),problem.chipMap[groupId]={chipId:groupId,pins:groupPins,size:matchpackProxy.size},debug62(`[${group.name}] Added group ${groupId} to chipMap`)}else debug62(`[${group.name}] Warning: No schematic_group found for group ${groupId}`)}}),debug62(`[${group.name}] Creating connections using connectivity keys`);let connectivityGroups=new Map;for(let[chipId,chip]of Object.entries(problem.chipMap))for(let pinId of chip.pins){let pinNumber=pinId.split(".").pop(),treeNode=tree.childNodes.find(child=>getTreeChildChipId(child,tree.childNodes.indexOf(child))===chipId);if(treeNode?.nodeType==="group"&&treeNode.sourceGroup){let schematicGroup=db2.schematic_group?.getWhere?.({source_group_id:treeNode.sourceGroup.source_group_id});if(schematicGroup){let groupComponents=db2.schematic_component.list({schematic_group_id:schematicGroup.schematic_group_id});for(let comp of groupComponents){let sourcePorts=db2.source_port.list({source_component_id:comp.source_component_id});for(let sourcePort of sourcePorts){let portNumber=sourcePort.pin_number||sourcePort.name;if(String(portNumber)===String(pinNumber))if(sourcePort.subcircuit_connectivity_map_key){let connectivityKey=sourcePort.subcircuit_connectivity_map_key;connectivityGroups.has(connectivityKey)||connectivityGroups.set(connectivityKey,[]),connectivityGroups.get(connectivityKey).push(pinId),debug62(`[${group.name}] \u2713 Pin ${pinId} has connectivity key: ${connectivityKey}`)}else debug62(`[${group.name}] Pin ${pinId} has no connectivity key`)}}}}else if(treeNode?.nodeType==="component"&&treeNode.sourceComponent){let sourcePorts=db2.source_port.list({source_component_id:treeNode.sourceComponent.source_component_id});for(let sourcePort of sourcePorts){let portNumber=sourcePort.pin_number||sourcePort.name;if(String(portNumber)===String(pinNumber)&&sourcePort.subcircuit_connectivity_map_key){let connectivityKey=sourcePort.subcircuit_connectivity_map_key;connectivityGroups.has(connectivityKey)||connectivityGroups.set(connectivityKey,[]),connectivityGroups.get(connectivityKey).push(pinId),debug62(`[${group.name}] Pin ${pinId} has connectivity key: ${connectivityKey}`)}}}}debug62(`[${group.name}] Found ${connectivityGroups.size} connectivity groups:`,Array.from(connectivityGroups.entries()).map(([key,pins])=>({key,pins})));for(let[connectivityKey,pins]of connectivityGroups){let tracesWithThisKey=db2.source_trace.list().filter(trace=>trace.subcircuit_connectivity_map_key===connectivityKey),hasNetConnections=tracesWithThisKey.some(trace=>trace.connected_source_net_ids&&trace.connected_source_net_ids.length>0),hasDirectConnections=tracesWithThisKey.some(trace=>trace.connected_source_port_ids&&trace.connected_source_port_ids.length>=2);if(debug62(`[${group.name}] Connectivity ${connectivityKey}: hasNetConnections=${hasNetConnections}, hasDirectConnections=${hasDirectConnections}`),pins.length>=2&&hasDirectConnections){for(let trace of tracesWithThisKey)if(trace.connected_source_port_ids&&trace.connected_source_port_ids.length>=2){let directlyConnectedPins=[];for(let portId of trace.connected_source_port_ids)for(let pinId of pins){let pinNumber=pinId.split(".").pop(),sourcePort=db2.source_port.get(portId);if(sourcePort&&String(sourcePort.pin_number||sourcePort.name)===String(pinNumber)){let chipId=pinId.split(".")[0],treeNode=tree.childNodes.find(child=>getTreeChildChipId(child,tree.childNodes.indexOf(child))===chipId);treeNode?.nodeType==="component"&&treeNode.sourceComponent&&db2.source_port.list({source_component_id:treeNode.sourceComponent.source_component_id}).some(p3=>p3.source_port_id===portId)&&directlyConnectedPins.push(pinId)}}for(let i6=0;i6<directlyConnectedPins.length;i6++)for(let j6=i6+1;j6<directlyConnectedPins.length;j6++){let pin1=directlyConnectedPins[i6],pin2=directlyConnectedPins[j6];problem.pinStrongConnMap[`${pin1}-${pin2}`]=!0,problem.pinStrongConnMap[`${pin2}-${pin1}`]=!0,debug62(`[${group.name}] Created strong connection: ${pin1} <-> ${pin2}`)}}}if(hasNetConnections){let source_net3=db2.source_net.getWhere({subcircuit_connectivity_map_key:connectivityKey}),isGround=source_net3?.is_ground??!1,isPositiveVoltageSource=source_net3?.is_power===!0||source_net3?.is_positive_voltage_source===!0;problem.netMap[connectivityKey]={netId:connectivityKey,isGround,isPositiveVoltageSource};for(let pinId of pins)problem.netConnMap[`${pinId}-${connectivityKey}`]=!0;debug62(`[${group.name}] Created net ${connectivityKey} with ${pins.length} pins:`,pins)}}return{inputProblem:problem,nestedGroupMatchpackProxyMap}}function applySchematicMatchPackLayoutToTree(group,tree,opts={}){let{db:db2}=group.root;if(debug62(`[${group.name}] Starting matchpack layout with ${tree.childNodes.length} children`),debug62(`[${group.name}] Tree structure:`,JSON.stringify(tree,null,2)),tree.childNodes.length<=1){debug62(`[${group.name}] Only ${tree.childNodes.length} children, skipping layout`);return}debug62("Converting circuit tree to InputProblem...");let{inputProblem,nestedGroupMatchpackProxyMap}=convertTreeToMatchPackInputProblem(tree,db2,group,opts);debug62.enabled&&group.root?.emit("debug:logOutput",{type:"debug:logOutput",name:`matchpack-input-problem-${group.name}`,content:JSON.stringify(inputProblem,null,2)});let solver=new LayoutPipelineSolver(inputProblem);if(group.root?.emit("solver:started",{type:"solver:started",solverName:"LayoutPipelineSolver",solverParams:inputProblem,solverConstructorArgs:[inputProblem],componentName:group.getString()}),debug62("Starting LayoutPipelineSolver..."),debug62.enabled&&global?.debugGraphics){let initialViz=solver.visualize();global.debugGraphics.push({...initialViz,title:`matchpack-initial-${group.name}`})}if(solver.solve(),group.root?.emit("solver:ended",{type:"solver:ended",solverName:"LayoutPipelineSolver",componentName:group.getString(),solved:solver.solved,failed:solver.failed,iterations:solver.iterations,error:solver.error}),debug62(`Solver completed in ${solver.iterations} iterations`),debug62(`Solved: ${solver.solved}, Failed: ${solver.failed}`),solver.failed){let solverError=solver.error??"Unknown Matchpack failure";debug62(`Solver failed with error: ${solverError}`),db2.schematic_layout_error.insert({error_type:"schematic_layout_error",message:`Matchpack layout solver failed: ${solverError}`,is_fatal:!1,source_group_id:group.source_group_id,schematic_group_id:group.schematic_group_id,subcircuit_id:group.subcircuit_id??void 0});return}let outputLayout=solver.getOutputLayout();if(debug62("OutputLayout:",JSON.stringify(outputLayout,null,2)),debug62("Solver completed successfully:",!solver.failed),debug62.enabled&&global?.debugGraphics){let finalViz=solver.visualize();global.debugGraphics.push({...finalViz,title:`matchpack-final-${group.name}`})}let overlaps=solver.checkForOverlaps(outputLayout);if(overlaps.length>0){debug62(`Warning: Found ${overlaps.length} overlapping components:`);for(let overlap of overlaps)debug62(` ${overlap.chip1} overlaps ${overlap.chip2} (area: ${overlap.overlapArea})`)}let groupOffset=group._getGlobalSchematicPositionBeforeLayout();debug62(`Group offset: x=${groupOffset.x}, y=${groupOffset.y}`),debug62(`Applying layout results for ${Object.keys(outputLayout.chipPlacements).length} chip placements`);for(let[chipId,placement]of Object.entries(outputLayout.chipPlacements)){debug62(`Processing placement for chip: ${chipId} at (${placement.x}, ${placement.y})`);let treeNode=tree.childNodes.find(child=>{let expectedChipId=getTreeChildChipId(child,tree.childNodes.indexOf(child)),matches=expectedChipId===chipId;return debug62(` Checking child ${expectedChipId}: matches=${matches}`),matches});if(!treeNode){debug62(`Warning: No tree node found for chip: ${chipId}`),debug62("Available tree nodes:",tree.childNodes.map((child,idx)=>({type:child.nodeType,name:child.nodeType==="component"?child.sourceComponent?.name:child.sourceGroup?.name,expectedChipId:getTreeChildChipId(child,idx)})));continue}let newCenter={x:placement.x+groupOffset.x,y:placement.y+groupOffset.y};if(treeNode.nodeType==="component"&&treeNode.sourceComponent){let groupChild=group.children.find(c3=>c3.source_component_id===treeNode.sourceComponent?.source_component_id);if(groupChild?._parsedProps?.schX!==void 0||groupChild?._parsedProps?.schY!==void 0){debug62(`Skipping position update for fixed chip ${chipId}`);continue}let schematicComponent=getSchematicComponentForSourceComponent({db:db2,sourceComponentId:treeNode.sourceComponent.source_component_id,schematicSheetId:opts.schematicSheetId});if(schematicComponent){debug62(`Moving component ${chipId} to (${newCenter.x}, ${newCenter.y})`);let ports=db2.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id}),texts=db2.schematic_text.list({schematic_component_id:schematicComponent.schematic_component_id}),positionDelta={x:newCenter.x-schematicComponent.center.x,y:newCenter.y-schematicComponent.center.y};for(let port of ports)port.center.x+=positionDelta.x,port.center.y+=positionDelta.y;for(let text of texts)text.position.x+=positionDelta.x,text.position.y+=positionDelta.y;if(updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId:schematicComponent.schematic_component_id,deltaX:positionDelta.x,deltaY:positionDelta.y}),schematicComponent.center=newCenter,placement.ccwRotationDegrees!==0){debug62(`Component ${chipId} has rotation: ${placement.ccwRotationDegrees}\xB0`);let normalizedRotation=(Math.round(placement.ccwRotationDegrees)%360+360)%360;if((normalizedRotation===90||normalizedRotation===270)&&schematicComponent.size){let prevWidth=schematicComponent.size.width;schematicComponent.size.width=schematicComponent.size.height,schematicComponent.size.height=prevWidth}let angleRad=placement.ccwRotationDegrees*Math.PI/180,cos6=Math.cos(angleRad),sin6=Math.sin(angleRad);for(let port of ports){let dx3=port.center.x-newCenter.x,dy3=port.center.y-newCenter.y,rotatedDx=dx3*cos6-dy3*sin6,rotatedDy=dx3*sin6+dy3*cos6;port.center.x=newCenter.x+rotatedDx,port.center.y=newCenter.y+rotatedDy;let originalDirection=port.facing_direction||"right";port.facing_direction=rotateDirection2(originalDirection,placement.ccwRotationDegrees),port.side_of_component=(port.facing_direction==="up"?"top":port.facing_direction==="down"?"bottom":port.facing_direction)||port.side_of_component}for(let text of texts){let dx3=text.position.x-newCenter.x,dy3=text.position.y-newCenter.y,rotatedDx=dx3*cos6-dy3*sin6,rotatedDy=dx3*sin6+dy3*cos6;text.position.x=newCenter.x+rotatedDx,text.position.y=newCenter.y+rotatedDy}schematicComponent.symbol_name&&(schematicComponent.symbol_name=getRotatedSymbolName(schematicComponent.symbol_name,placement.ccwRotationDegrees))}}}else if(treeNode.nodeType==="group"&&treeNode.sourceGroup){let schematicGroup=db2.schematic_group?.getWhere?.({source_group_id:treeNode.sourceGroup.source_group_id});if(schematicGroup){debug62(`Moving group ${chipId} to (${newCenter.x}, ${newCenter.y}) from (${schematicGroup.center?.x}, ${schematicGroup.center?.y})`);let groupComponents=db2.schematic_component.list({schematic_group_id:schematicGroup.schematic_group_id});debug62(`Group ${chipId} has ${groupComponents.length} components to move`);let matchpackProxy=nestedGroupMatchpackProxyMap[chipId],oldCenter=matchpackProxy?.center??schematicGroup.center??{x:0,y:0},positionDelta={x:newCenter.x-oldCenter.x,y:newCenter.y-oldCenter.y};debug62(`Position delta for group ${chipId}: (${positionDelta.x}, ${positionDelta.y})`);for(let component of groupComponents)if(component.center){let oldComponentCenter={...component.center};component.center.x+=positionDelta.x,component.center.y+=positionDelta.y,debug62(`Moved component ${component.source_component_id} from (${oldComponentCenter.x}, ${oldComponentCenter.y}) to (${component.center.x}, ${component.center.y})`);let ports=db2.schematic_port.list({schematic_component_id:component.schematic_component_id}),texts=db2.schematic_text.list({schematic_component_id:component.schematic_component_id});for(let port of ports)port.center&&(port.center.x+=positionDelta.x,port.center.y+=positionDelta.y);for(let text of texts)text.position&&(text.position.x+=positionDelta.x,text.position.y+=positionDelta.y);updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId:component.schematic_component_id,deltaX:positionDelta.x,deltaY:positionDelta.y})}schematicGroup.center=newCenter,matchpackProxy&&(schematicGroup.width=matchpackProxy.size.x,schematicGroup.height=matchpackProxy.size.y),debug62(`Updated group ${chipId} center to (${newCenter.x}, ${newCenter.y})`)}}}debug62("Matchpack layout completed successfully")}function getSchematicSheetIdsBySourceGroupId({circuitJson,schematicSheetIdsBySourceComponentId}){let parentBySourceGroupId=new Map;for(let element of circuitJson)element.type==="source_group"&&parentBySourceGroupId.set(element.source_group_id,element.parent_source_group_id);let schematicSheetIdsBySourceGroupId=new Map;for(let element of circuitJson){if(element.type!=="source_component"||!element.source_group_id)continue;let schematicSheetIds=schematicSheetIdsBySourceComponentId.get(element.source_component_id);if(schematicSheetIds!==void 0)for(let schematicSheetId of schematicSheetIds){let sourceGroupId=element.source_group_id,visitedSourceGroupIds=new Set;for(;sourceGroupId&&!visitedSourceGroupIds.has(sourceGroupId);){visitedSourceGroupIds.add(sourceGroupId);let groupSchematicSheetIds=schematicSheetIdsBySourceGroupId.get(sourceGroupId)??new Set;groupSchematicSheetIds.add(schematicSheetId),schematicSheetIdsBySourceGroupId.set(sourceGroupId,groupSchematicSheetIds),sourceGroupId=parentBySourceGroupId.get(sourceGroupId)}}}return schematicSheetIdsBySourceGroupId}function getCircuitJsonScopedToSchematicSheet({circuitJson,schematicSheetId,rootSourceGroupId,schematicSheetIdsBySourceComponentId,schematicSheetIdsBySourceGroupId}){let isGroupOnSheet=sourceGroupId=>sourceGroupId===rootSourceGroupId||schematicSheetIdsBySourceGroupId.get(sourceGroupId)?.has(schematicSheetId)===!0;return circuitJson.filter(element=>element.type==="source_group"?isGroupOnSheet(element.source_group_id):element.type==="source_component"?schematicSheetIdsBySourceComponentId.get(element.source_component_id)?.has(schematicSheetId)!==!0?!1:element.source_group_id?isGroupOnSheet(element.source_group_id):!0:!0)}function getSchematicCircuitJsonTrees(circuitJson,opts){let{source_group_id}=opts,schematicSheetIdsBySourceComponentId=new Map;for(let element of circuitJson){if(element.type!=="schematic_component"||!element.source_component_id||!element.schematic_sheet_id)continue;let schematicSheetIds2=schematicSheetIdsBySourceComponentId.get(element.source_component_id)??new Set;schematicSheetIds2.add(element.schematic_sheet_id),schematicSheetIdsBySourceComponentId.set(element.source_component_id,schematicSheetIds2)}let schematicSheetIds=new Set;for(let componentSchematicSheetIds of schematicSheetIdsBySourceComponentId.values())for(let schematicSheetId of componentSchematicSheetIds)schematicSheetIds.add(schematicSheetId);if(schematicSheetIds.size<=1)return[{tree:getCircuitJsonTree(circuitJson,{source_group_id}),schematicSheetId:schematicSheetIds.values().next().value}];let schematicSheetIdsBySourceGroupId=getSchematicSheetIdsBySourceGroupId({circuitJson,schematicSheetIdsBySourceComponentId});return Array.from(schematicSheetIds).map(schematicSheetId=>({tree:getCircuitJsonTree(getCircuitJsonScopedToSchematicSheet({circuitJson,schematicSheetId,rootSourceGroupId:source_group_id,schematicSheetIdsBySourceComponentId,schematicSheetIdsBySourceGroupId}),{source_group_id}),schematicSheetId}))}function Group_doInitialSchematicLayoutMatchPack(group){let{db:db2}=group.root,trees=getSchematicCircuitJsonTrees(db2.toArray(),{source_group_id:group.source_group_id});for(let{tree,schematicSheetId}of trees)applySchematicMatchPackLayoutToTree(group,tree,{schematicSheetId})}var SECTION_GAP=1,MARGIN2=1.5;function computeSchematicSectionLayoutUsingRows({sectionBlocks,groupSchPositionBeforeLayout:groupOffset}){let totalArea=sectionBlocks.reduce((sum,block)=>{let paddedWidth=Math.max(block.size.x,.5)+MARGIN2*2,paddedHeight=Math.max(block.size.y,.5)+MARGIN2*2;return sum+paddedWidth*paddedHeight},0),targetRowWidth=Math.sqrt(totalArea)*2,computedSectionsMatrix=[],currentSectionRow=[],currentRowSectionWidth=0;for(let section of sectionBlocks){let paddedWidth=Math.max(section.size.x,.5)+MARGIN2*2,paddedHeight=Math.max(section.size.y,.5)+MARGIN2*2,neededWidth=currentRowSectionWidth>0?currentRowSectionWidth+SECTION_GAP+paddedWidth:paddedWidth;currentSectionRow.length>0&&neededWidth>targetRowWidth&&(computedSectionsMatrix.push(currentSectionRow),currentSectionRow=[],currentRowSectionWidth=0);let xOffsetInRow=currentRowSectionWidth>0?currentRowSectionWidth+SECTION_GAP:0;currentSectionRow.push({sectionName:section.sectionName,rowOffset:xOffsetInRow,width:paddedWidth,height:paddedHeight}),currentRowSectionWidth=xOffsetInRow+paddedWidth}currentSectionRow.length>0&&computedSectionsMatrix.push(currentSectionRow);let sectionPlacements=new Map,rowY=0;for(let sectionRow of computedSectionsMatrix){let rowHeight=Math.max(...sectionRow.map(rowEntry=>rowEntry.height)),rowCenteringOffsetX=-(sectionRow[sectionRow.length-1].rowOffset+sectionRow[sectionRow.length-1].width)/2;for(let section of sectionRow)sectionPlacements.set(section.sectionName,{x:rowCenteringOffsetX+section.rowOffset+section.width/2+groupOffset.x,y:rowY-rowHeight/2+groupOffset.y});rowY-=rowHeight+SECTION_GAP}return sectionPlacements}var debug7=(0,import_debug15.default)("Group_doInitialSchematicLayoutSections");function Group_doInitialSchematicLayoutSections(group){let{db:db2}=group.root,sectionNamesUsedByChildren=new Set,hasChildrenWithoutSection=!1;for(let child of group.children){if(!child.source_component_id)continue;let sectionName=child.getSchematicSectionName();sectionName!==null?sectionNamesUsedByChildren.add(sectionName):hasChildrenWithoutSection=!0}let sectionNamesToLayout=Array.from(sectionNamesUsedByChildren);if(hasChildrenWithoutSection&&sectionNamesToLayout.push(null),sectionNamesToLayout.length===0)return;for(let sectionName of sectionNamesToLayout){let sectionTree=getCircuitJsonTree(db2.toArray(),{source_group_id:group.source_group_id});sectionTree.childNodes=sectionTree.childNodes.filter(child=>child.nodeType!=="component"||!child.sourceComponent?!1:(group.children.find(c3=>c3.source_component_id===child.sourceComponent?.source_component_id)?.getSchematicSectionName()??null)===sectionName),applySchematicMatchPackLayoutToTree(group,sectionTree)}if(sectionNamesToLayout.length<=1)return;let sectionNameToBoundsWithChildren=new Map;for(let sectionName of sectionNamesToLayout){let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0,sourceCompIds=new Set;for(let child of group.children){let sourceComponentId=child.source_component_id;if(!sourceComponentId||child.getSchematicSectionName()!==sectionName)continue;let schComp=db2.schematic_component.getWhere({source_component_id:sourceComponentId});if(!schComp)continue;sourceCompIds.add(sourceComponentId);let hw2=schComp.size.width/2,hh3=schComp.size.height/2;minX=Math.min(minX,schComp.center.x-hw2),maxX=Math.max(maxX,schComp.center.x+hw2),minY=Math.min(minY,schComp.center.y-hh3),maxY=Math.max(maxY,schComp.center.y+hh3)}!Number.isFinite(minX)||sourceCompIds.size===0||sectionNameToBoundsWithChildren.set(sectionName,{sectionName,center:{x:(minX+maxX)/2,y:(minY+maxY)/2},size:{x:maxX-minX,y:maxY-minY},sourceCompIds})}if(sectionNameToBoundsWithChildren.size<=1)return;let anchoredSections=new Set;for(let child of group.children){if(!child.source_component_id)continue;let props=child._parsedProps;(props?.schX!==void 0||props?.schY!==void 0)&&anchoredSections.add(child.getSchematicSectionName())}let groupSchPositionBeforeLayout=group._getGlobalSchematicPositionBeforeLayout(),sectionPlacements=computeSchematicSectionLayoutUsingRows({sectionBlocks:Array.from(sectionNameToBoundsWithChildren.values()).map(bounds=>({sectionName:bounds.sectionName,size:bounds.size})),groupSchPositionBeforeLayout});for(let[sectionName,placement]of sectionPlacements){let boundsWithChildren=sectionNameToBoundsWithChildren.get(sectionName);if(!boundsWithChildren)continue;if(anchoredSections.has(sectionName)){debug7(`[${group.name}] Section "${sectionName}" anchored by manual position, skipping shift`);continue}let delta={x:placement.x-boundsWithChildren.center.x,y:placement.y-boundsWithChildren.center.y};for(let sourceComponentId of boundsWithChildren.sourceCompIds){let schComp=db2.schematic_component.getWhere({source_component_id:sourceComponentId});if(!schComp)continue;let ports=db2.schematic_port.list({schematic_component_id:schComp.schematic_component_id}),texts=db2.schematic_text.list({schematic_component_id:schComp.schematic_component_id});for(let port of ports)port.center.x+=delta.x,port.center.y+=delta.y;for(let text of texts)text.position.x+=delta.x,text.position.y+=delta.y;updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId:schComp.schematic_component_id,deltaX:delta.x,deltaY:delta.y}),schComp.center={x:schComp.center.x+delta.x,y:schComp.center.y+delta.y}}}}var MISSING_SCHEMATIC_SHEET_ISSUE_TYPE="missing_schematic_sheet",updateMissingSchematicSheetWarning=({db:db2,schematicDisabled})=>{let existingWarning=db2.schematic_component_styling_warning.list().find(warning=>warning.styling_issue_type===MISSING_SCHEMATIC_SHEET_ISSUE_TYPE),firstSchematicComponent=db2.schematic_component.list()[0];if(!(!schematicDisabled&&!!firstSchematicComponent&&db2.schematic_sheet.list().length===0)){existingWarning&&db2.schematic_component_styling_warning.delete(existingWarning.schematic_component_styling_warning_id);return}existingWarning||!firstSchematicComponent||db2.schematic_component_styling_warning.insert({warning_type:"schematic_component_styling_warning",message:"No <schematicsheet> was found. Add a <schematicsheet> to define the schematic drawing area.",schematic_component_id:firstSchematicComponent.schematic_component_id,source_component_id:firstSchematicComponent.source_component_id,subcircuit_id:firstSchematicComponent.subcircuit_id,styling_issue_type:MISSING_SCHEMATIC_SHEET_ISSUE_TYPE})},Group_doInitialSchematicSheetRender=group=>{let root=group.root;if(!root?.isRootCircuit)return;let isRootGroup=root.firstChild===group,isRootAssemblyChild=isAssemblyDeviceContainer(root.firstChild)&&group.parent===root.firstChild;!isRootGroup&&!isRootAssemblyChild||updateMissingSchematicSheetWarning({db:root.db,schematicDisabled:root.schematicDisabled})},Group_updateSchematicSheetRender=group=>{Group_doInitialSchematicSheetRender(group)},NetLabel=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"source_net_label_id");__publicField(this,"schematic_net_label_id")}get config(){return{componentName:"NetLabel",zodProps:netLabelProps}}_getAnchorSide(){let{_parsedProps:props}=this;if(props.anchorSide)return props.anchorSide;if(!this._resolveConnectsTo())return"right";let net=this.getSubcircuit().selectOne(`net.${this._getNetName()}`),sourceNet;if(net?.source_net_id&&(sourceNet=this.root?.db.source_net.get(net.source_net_id)),sourceNet?.is_ground)return"top";if(sourceNet?.is_power)return"bottom";let anchorPos=this._getGlobalSchematicPositionBeforeLayout(),connectedPorts=this._getConnectedPorts();if(connectedPorts.length===0)return"right";let port=connectedPorts[0];if(port.facingDirection)return getEnteringEdgeFromDirection(port.facingDirection);let connectedPortPosition=port._getGlobalSchematicPositionBeforeLayout(),dx3=connectedPortPosition.x-anchorPos.x,dy3=connectedPortPosition.y-anchorPos.y;if(Math.abs(dx3)>Math.abs(dy3)){if(dx3>0)return"right";if(dx3<0)return"left"}else{if(dy3>0)return"top";if(dy3<0)return"bottom"}return"right"}_getConnectedPorts(){let connectsTo=this._resolveConnectsTo();if(!connectsTo)return[];let connectedPorts=[];for(let connection of connectsTo){let port=this.getSubcircuit().selectOne(connection);port&&connectedPorts.push(port)}return connectedPorts}computeSchematicPropsTransform(){let{_parsedProps:props}=this;if(props.schX===void 0&&props.schY===void 0){let connectedPorts=this._getConnectedPorts();if(connectedPorts.length>0){let portPos=connectedPorts[0]._getGlobalSchematicPositionBeforeLayout(),parentCenter=applyToPoint2(this.parent?.computeSchematicGlobalTransform?.()??identity(),{x:0,y:0});return translate2(portPos.x-parentCenter.x,portPos.y-parentCenter.y)}}return super.computeSchematicPropsTransform()}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled||this.getCollapsedSchematicBoxAncestor())return;let{db:db2}=this.root,{_parsedProps:props}=this;if(props.inline&&this.root?._featureMspSchematicTraceRouting&&this._getConnectedPorts().length>0)return;let anchorPos=this._getGlobalSchematicPositionBeforeLayout(),net=this.getSubcircuit().selectOne(`net.${this._getNetName()}`),anchorSide=this._getAnchorSide(),center2=computeSchematicNetLabelCenter({anchor_position:anchorPos,anchor_side:anchorSide,text:props.net}),netLabel=db2.schematic_net_label.insert({text:props.net,source_net_id:net.source_net_id,anchor_position:anchorPos,center:center2,anchor_side:anchorSide,schematic_sheet_id:this._resolveSchematicSheetId()});this.source_net_label_id=netLabel.source_net_id,this.schematic_net_label_id=netLabel.schematic_net_label_id}_resolveConnectsTo(){let{_parsedProps:props}=this,connectsTo=props.connectsTo??props.connection;if(Array.isArray(connectsTo))return connectsTo;if(typeof connectsTo=="string")return[connectsTo]}_getNetName(){let{_parsedProps:props}=this;return props.net}doInitialCreateNetsFromProps(){let{_parsedProps:props}=this;props.net&&createNetsFromProps(this,[`net.${props.net}`])}doInitialCreateTracesFromNetLabels(){let connectsTo=this._resolveConnectsTo();if(connectsTo)for(let connection of connectsTo)this.add(new Trace({from:connection,to:`net.${this._getNetName()}`}))}doInitialSchematicTraceRender(){if(!this.root?._featureMspSchematicTraceRouting||this.root?.schematicDisabled||this.getCollapsedSchematicBoxAncestor()||this._parsedProps.inline)return;let{schX,schY}=this._parsedProps;if(schX===void 0&&schY===void 0)return;let{db:db2}=this.root,connectsTo=this._resolveConnectsTo();if(!connectsTo||connectsTo.length===0)return;let anchorPos=this._getGlobalSchematicPositionBeforeLayout(),anchorSide=this._getAnchorSide(),anchorFacing={left:"x-",right:"x+",top:"y+",bottom:"y-"}[anchorSide],net=this.getSubcircuit().selectOne(`net.${this._getNetName()}`);for(let connection of connectsTo){let port=this.getSubcircuit().selectOne(connection,{type:"port"});if(!port||!port.schematic_port_id)continue;let existingTraceForThisConnection=!1;if(net?.source_net_id){let candidateSourceTrace=db2.source_trace.list().find(st3=>st3.connected_source_net_ids?.includes(net.source_net_id)&&st3.connected_source_port_ids?.includes(port.source_port_id??""));if(candidateSourceTrace&&(existingTraceForThisConnection=db2.schematic_trace.list().some(t53=>t53.source_trace_id===candidateSourceTrace.source_trace_id)),existingTraceForThisConnection)continue}let portPos=port._getGlobalSchematicPositionAfterLayout(),portFacing=convertFacingDirectionToElbowDirection(port.facingDirection??"right")??"x+",path=calculateElbow({x:portPos.x,y:portPos.y,facingDirection:portFacing},{x:anchorPos.x,y:anchorPos.y,facingDirection:anchorFacing});if(!Array.isArray(path)||path.length<2)continue;let edges=[];for(let i6=0;i6<path.length-1;i6++)edges.push({from:{x:path[i6].x,y:path[i6].y},to:{x:path[i6+1].x,y:path[i6+1].y}});let source_trace_id,subcircuit_connectivity_map_key;if(net?.source_net_id&&port.source_port_id){let st3=db2.source_trace.list().find(s6=>s6.connected_source_net_ids?.includes(net.source_net_id)&&s6.connected_source_port_ids?.includes(port.source_port_id));source_trace_id=st3?.source_trace_id,subcircuit_connectivity_map_key=st3?.subcircuit_connectivity_map_key||db2.source_net.get(net.source_net_id)?.subcircuit_connectivity_map_key}db2.schematic_trace.insert({source_trace_id,edges,junctions:[],subcircuit_connectivity_map_key,schematic_sheet_id:this._resolveSchematicSheetId()}),db2.schematic_port.update(port.schematic_port_id,{is_connected:!0})}}},getNetNameFromPorts=ports=>{let directlyConnectedTraces=[...new Set(ports.flatMap(port=>port._getDirectlyConnectedTraces()))],displayLabel=directlyConnectedTraces.find(trace=>trace._parsedProps.schDisplayLabel)?._parsedProps.schDisplayLabel??directlyConnectedTraces.find(trace=>trace._parsedProps.displayName)?._parsedProps.displayName??directlyConnectedTraces.find(trace=>trace._parsedProps.name)?._parsedProps.name;if(displayLabel)return{name:displayLabel,wasAssignedDisplayLabel:!0};let db2=ports.find(port=>port.root)?.root?.db,sourcePortIds=ports.map(port=>port.source_port_id).filter(sourcePortId=>!!sourcePortId);return{name:(db2?getNetNameFromSourcePorts(db2,sourcePortIds):ports.map(port=>port._getNetLabelText()).filter(name=>!!name).sort((a6,b6)=>a6.localeCompare(b6,void 0,{numeric:!0,sensitivity:"base"}))[0])??"",wasAssignedDisplayLabel:!1}},appendToMap=(map,key,value)=>{let values=map.get(key);values?values.push(value):map.set(key,[value])},createCanonicalSchematicNetLabelTextResolver=group=>{let{db:db2}=group.root,sourceNetByConnectionKey=new Map,portsByConnectionKey=new Map,sourcePortIdsByConnectionKey=new Map,resolvedTextByConnectionKey=new Map;for(let sourceNet of db2.source_net.list())sourceNet.subcircuit_connectivity_map_key&&sourceNetByConnectionKey.set(sourceNet.subcircuit_connectivity_map_key,sourceNet);for(let port of group.selectAll("port")){let connectionKey=port._getSubcircuitConnectivityKey();connectionKey&&appendToMap(portsByConnectionKey,connectionKey,port)}for(let sourcePort of db2.source_port.list())sourcePort.subcircuit_connectivity_map_key&&appendToMap(sourcePortIdsByConnectionKey,sourcePort.subcircuit_connectivity_map_key,sourcePort.source_port_id);return({subcircuitConnectivityMapKey})=>{let cached=resolvedTextByConnectionKey.get(subcircuitConnectivityMapKey);if(cached)return cached;let resolvedSourceNet=sourceNetByConnectionKey.get(subcircuitConnectivityMapKey);if(resolvedSourceNet?.name){let result2={name:resolvedSourceNet.name,wasAssignedDisplayLabel:!0};return resolvedTextByConnectionKey.set(subcircuitConnectivityMapKey,result2),result2}let portLabel=getNetNameFromPorts(portsByConnectionKey.get(subcircuitConnectivityMapKey)??[]);if(portLabel.name)return resolvedTextByConnectionKey.set(subcircuitConnectivityMapKey,portLabel),portLabel;let result={name:getNetNameFromSourcePorts(db2,sourcePortIdsByConnectionKey.get(subcircuitConnectivityMapKey)??[])??"",wasAssignedDisplayLabel:!1};return resolvedTextByConnectionKey.set(subcircuitConnectivityMapKey,result),result}},asSchematicPortId=id3=>id3,asSourcePortId=id3=>id3,debug8=(0,import_debug17.default)("Group_doInitialSchematicTraceRender"),INLINE_NET_LABEL_COLOR="rgb(132, 0, 0)",VERTICAL_INLINE_NET_LABEL_ROTATION=-90;function applyInlineNetLabelPlacements(args){let{group,solver,userNetIdToConnKey,sourceTraceIdByPinPairKey}=args,{db:db2}=group.root,inlineNetLabelPlacements=solver.inlineNetLabelSolver?.getOutput().inlineNetLabelPlacements??[];if(inlineNetLabelPlacements.length===0)return;let resolveCanonicalNetLabelText=createCanonicalSchematicNetLabelTextResolver(group),globalConnMap=solver.mspConnectionPairSolver.globalConnMap;for(let placement of inlineNetLabelPlacements){let schematicPortIds=placement.pinIds.map(asSchematicPortId),placementUserNetId=globalConnMap.getIdsConnectedToNet(placement.globalConnNetId).find(id3=>userNetIdToConnKey.has(id3)),connKey=placementUserNetId?userNetIdToConnKey.get(placementUserNetId):void 0,text=connKey?resolveCanonicalNetLabelText({subcircuitConnectivityMapKey:connKey}).name:placement.netId??placement.globalConnNetId;if(!text){debug8(`skipping inline net label for "${placement.netId}" REASON:no resolvable text`);continue}let sourceTraceId=sourceTraceIdByPinPairKey.get([...schematicPortIds].sort().join("::"));if(!sourceTraceId&&connKey){let sourcePortIds=schematicPortIds.flatMap(schematicPortId=>{let sourcePortId=db2.schematic_port.get(schematicPortId)?.source_port_id;return sourcePortId?[sourcePortId]:[]});sourceTraceId=db2.source_trace.list().find(sourceTrace=>sourceTrace.subcircuit_connectivity_map_key===connKey&&sourcePortIds.some(sourcePortId=>sourceTrace.connected_source_port_ids.includes(sourcePortId)))?.source_trace_id}let schematicSheetId=group._resolveSchematicSheetId(),schematicPort=db2.schematic_port.get(schematicPortIds[0]);schematicPort?.schematic_sheet_id&&(schematicSheetId=schematicPort.schematic_sheet_id);let placementOffset={x:0,y:0},stubTracePath=placement.stubTracePath?.map(point6=>({...point6}));if(stubTracePath&&schematicPortIds.length===1){let portCenter=db2.schematic_port.get(schematicPortIds[0])?.center;portCenter&&(placementOffset={x:portCenter.x-stubTracePath[0].x,y:portCenter.y-stubTracePath[0].y},stubTracePath=stubTracePath.map(point6=>({x:point6.x+placementOffset.x,y:point6.y+placementOffset.y})))}let shiftedAnchorPoint={x:placement.anchorPoint.x+placementOffset.x,y:placement.anchorPoint.y+placementOffset.y},position4={x:placement.center.x+placementOffset.x,y:placement.center.y+placementOffset.y},textAnchor="center",halfHeight=placement.height/2;switch(placement.side){case"y+":position4.y=shiftedAnchorPoint.y+halfHeight;break;case"y-":position4.y=shiftedAnchorPoint.y-halfHeight;break;case"x+":position4.x=shiftedAnchorPoint.x+halfHeight;break;case"x-":position4.x=shiftedAnchorPoint.x-halfHeight;break}if(stubTracePath&&stubTracePath.length===2){let[start,end]=stubTracePath;if(placement.axis==="x"){let extendsRight=end.x>start.x;textAnchor=extendsRight?"left":"right",position4.x+=extendsRight?-placement.width/2:placement.width/2}else{let extendsUp=end.y>start.y;textAnchor=extendsUp?"left":"right",position4.y+=extendsUp?-placement.width/2:placement.width/2}}stubTracePath&&stubTracePath.length===2&&(db2.schematic_trace.insert({source_trace_id:sourceTraceId,edges:[{from:stubTracePath[0],to:stubTracePath[1]}],junctions:[],subcircuit_connectivity_map_key:connKey,schematic_sheet_id:schematicSheetId}),db2.schematic_port.update(schematicPortIds[0],{is_connected:!0})),db2.schematic_text.insert({text,source_trace_id:sourceTraceId,anchor:textAnchor,position:position4,rotation:placement.axis==="y"?VERTICAL_INLINE_NET_LABEL_ROTATION:0,font_size:placement.height,color:INLINE_NET_LABEL_COLOR,schematic_sheet_id:schematicSheetId})}}var NET_LABEL_TEXT_HEIGHT=.18,getNetLabelTextBounds=({center:center2,text})=>{let halfWidth=getSchematicNetLabelTextWidth2({text})/2,halfHeight=NET_LABEL_TEXT_HEIGHT/2;return{minX:center2.x-halfWidth,maxX:center2.x+halfWidth,minY:center2.y-halfHeight,maxY:center2.y+halfHeight}},oppositeSide2=input2=>{switch(input2){case"x+":return"left";case"x-":return"right";case"y+":return"bottom";case"y-":return"top";case"left":return"right";case"top":return"bottom";case"right":return"left";case"bottom":return"top"}},debug9=(0,import_debug18.default)("Group_doInitialSchematicTraceRender"),isSameNet=(label,sourceNet)=>label.schematicNetLabel.source_net_id!=null&&label.schematicNetLabel.source_net_id===sourceNet.source_net_id,isUserDefinedNetLabelRedundantWithPlacement=(label,solverPlacement)=>isSameNet(label,solverPlacement.sourceNet)?label.schematicPortIds.some(id3=>solverPlacement.schematicPortIds.has(id3))?!0:label.schematicNetLabel.center?doBoundsOverlap(getNetLabelTextBounds({center:label.schematicNetLabel.center,text:label.schematicNetLabel.text}),solverPlacement.bounds):!1:!1;function applyNetLabelPlacements(args){let{group,solver,connKeyToSourceNet,userNetIdToConnKey,crossSubcircuitTraceLabelBySchematicPortId,sourceTraceIdByPortOnlyLabelSchematicPortId,connKeysWithExplicitPortNetTraces,schematicPortIdsWithPreExistingNetLabels,schematicPortIdsWithRoutedTraces,netLabels}=args,{db:db2}=group.root,resolveCanonicalNetLabelText=createCanonicalSchematicNetLabelTextResolver(group),netLabelPlacements=solver.inlineNetLabelSolver?.getOutput().netLabelPlacements??solver.netLabelNetLabelCollisionSolver?.getOutput().netLabelPlacements??solver.netLabelTraceCollisionSolver?.getOutput().netLabelPlacements??solver.netLabelPlacementSolver?.netLabelPlacements??solver.traceLabelOverlapAvoidanceSolver?.getOutput().netLabelPlacements??[],dedupedNetLabelPlacements=[],netLabelPlacementKeys=new Set;for(let placement of netLabelPlacements){let pinIds=[...placement.pinIds??[]].sort(),key=`${placement.globalConnNetId}|${pinIds.join("::")}|${placement.netId??""}`;if(netLabelPlacementKeys.has(key)){debug9(`skipping duplicate placement for "${placement.netId}" REASON:identical net label placement`);continue}netLabelPlacementKeys.add(key),dedupedNetLabelPlacements.push(placement)}let netLabelPlacementCountByGlobalNetId=new Map,routedPairKeysByGlobalNetId=new Map,globalNetIdsWithPortOnlyPlacements=new Set;for(let placement of dedupedNetLabelPlacements)netLabelPlacementCountByGlobalNetId.set(placement.globalConnNetId,(netLabelPlacementCountByGlobalNetId.get(placement.globalConnNetId)??0)+1),(placement.pinIds?.length??0)>1&&(routedPairKeysByGlobalNetId.has(placement.globalConnNetId)||routedPairKeysByGlobalNetId.set(placement.globalConnNetId,new Set),routedPairKeysByGlobalNetId.get(placement.globalConnNetId).add(placement.pinIds.slice().sort().join("::"))),(placement.pinIds?.length??0)<=1&&globalNetIdsWithPortOnlyPlacements.add(placement.globalConnNetId);let globalConnMap=solver.mspConnectionPairSolver.globalConnMap,userDefinedNetLabels=netLabels.map(label=>{if(!label.schematic_net_label_id)return null;let dbLabel=db2.schematic_net_label.get(label.schematic_net_label_id);return dbLabel?{schematicNetLabel:dbLabel,schematicPortIds:label._getConnectedPorts().map(port=>port.schematic_port_id).filter(id3=>!!id3),shouldUseSchematicTraceSolver:label._parsedProps.schX===void 0&&label._parsedProps.schY===void 0}:null}).filter(label=>label!==null);for(let placement of dedupedNetLabelPlacements){debug9(`processing placement: ${placement.netId}`);let schPortIds=placement.pinIds.map(asSchematicPortId),crossSubcircuitTraceLabel=schPortIds.length===1?crossSubcircuitTraceLabelBySchematicPortId.get(schPortIds[0]):void 0,placementSourceTraceId=crossSubcircuitTraceLabel?.sourceTraceId??(schPortIds.length===1?sourceTraceIdByPortOnlyLabelSchematicPortId.get(schPortIds[0]):void 0),placementSourceTrace=placementSourceTraceId?db2.source_trace.get(placementSourceTraceId):void 0,placementUserNetId=globalConnMap.getIdsConnectedToNet(placement.globalConnNetId).find(id3=>userNetIdToConnKey.get(id3)),placementConnKey=placementSourceTrace?.subcircuit_connectivity_map_key??userNetIdToConnKey.get(placementUserNetId),orientation4=placement.orientation,anchor_side=oppositeSide2(orientation4),sourceNet;placementConnKey&&(sourceNet=connKeyToSourceNet.get(placementConnKey));let canonicalNetLabel=placementConnKey?crossSubcircuitTraceLabel?{name:crossSubcircuitTraceLabel.text,wasAssignedDisplayLabel:!1}:resolveCanonicalNetLabelText({subcircuitConnectivityMapKey:placementConnKey}):{name:placement.netId??placement.globalConnNetId,wasAssignedDisplayLabel:!1},schematicSheetId=group._resolveSchematicSheetId(),schematicPort=db2.schematic_port.get(schPortIds[0]);schematicPort?.schematic_sheet_id&&(schematicSheetId=schematicPort.schematic_sheet_id);let anchor_position=placement.anchorPoint;if(schPortIds.length===1&&schPortIds[0]){let anchorSchPort=db2.schematic_port.get(schPortIds[0]);anchorSchPort?.center&&!anchorSchPort.is_connected&&(anchor_position=anchorSchPort.center)}if(schPortIds.some(schPortId=>schematicPortIdsWithPreExistingNetLabels.has(schPortId))){debug9(`skipping net label placement for "${placement.netId}" REASON:schematic port has pre-existing net label`);continue}if(sourceNet){let isPowerOrGroundNet=sourceNet.is_ground||sourceNet.is_power,hasExplicitPortNetTrace=connKeysWithExplicitPortNetTraces.has(placementConnKey),hasRoutedTraceForPlacementPort=schPortIds.some(id3=>schematicPortIdsWithRoutedTraces.has(id3)),hasSingleLabelPlacement=(netLabelPlacementCountByGlobalNetId.get(placement.globalConnNetId)??0)<=1;if(!hasExplicitPortNetTrace&&!isPowerOrGroundNet&&hasRoutedTraceForPlacementPort&&hasSingleLabelPlacement){debug9(`skipping net label placement for "${placement.netId}" REASON:schematic port has routed trace`);continue}let text2=canonicalNetLabel.name,center22=computeSchematicNetLabelCenter({anchor_position,anchor_side,text:text2}),solverManagedUserNetLabel=userDefinedNetLabels.find(label=>label.shouldUseSchematicTraceSolver&&isSameNet(label,sourceNet)&&label.schematicPortIds.some(id3=>schPortIds.includes(id3)));if(solverManagedUserNetLabel){db2.schematic_net_label.update(solverManagedUserNetLabel.schematicNetLabel.schematic_net_label_id,{anchor_position,center:center22,anchor_side,schematic_sheet_id:schematicSheetId,source_trace_id:placementSourceTraceId});continue}if(!isPowerOrGroundNet){let solverPlacement={sourceNet,text:text2,schematicPortIds:new Set(schPortIds),bounds:getNetLabelTextBounds({center:center22,text:text2})};if(userDefinedNetLabels.some(label=>isUserDefinedNetLabelRedundantWithPlacement(label,solverPlacement)))continue}let netLabel2={text:text2,source_net_id:sourceNet.source_net_id,anchor_position,center:center22,anchor_side,schematic_sheet_id:schematicSheetId,source_trace_id:placementSourceTraceId};db2.schematic_net_label.insert(netLabel2);continue}let{name:text,wasAssignedDisplayLabel}=canonicalNetLabel,shouldKeepRoutedPairLabel=(placement.pinIds?.length??0)>1&&(globalNetIdsWithPortOnlyPlacements.has(placement.globalConnNetId)||(routedPairKeysByGlobalNetId.get(placement.globalConnNetId)?.size??0)>1);if(!wasAssignedDisplayLabel&&!shouldKeepRoutedPairLabel&&schPortIds.some(schPortId=>schematicPortIdsWithRoutedTraces.has(schPortId))){debug9(`skipping net label placement for "${placement.netId}" REASON:schematic port has routed traces and no display label`);continue}let center2=computeSchematicNetLabelCenter({anchor_position,anchor_side,text}),netLabel={text,source_net_id:placementConnKey??placement.netId??placement.globalConnNetId,anchor_position,center:center2,anchor_side,schematic_sheet_id:schematicSheetId,source_trace_id:placementSourceTraceId};db2.schematic_net_label.insert(netLabel)}}var cross22=(ax3,ay3,bx3,by3)=>ax3*by3-ay3*bx3;function segmentIntersection(p12,p22,q12,q22,tol){let r6={x:p22.x-p12.x,y:p22.y-p12.y},s6={x:q22.x-q12.x,y:q22.y-q12.y},rxs=cross22(r6.x,r6.y,s6.x,s6.y),q_p={x:q12.x-p12.x,y:q12.y-p12.y},q_pxr=cross22(q_p.x,q_p.y,r6.x,r6.y);if(Math.abs(rxs)<tol&&Math.abs(q_pxr)<tol||Math.abs(rxs)<tol&&Math.abs(q_pxr)>=tol)return null;let t53=cross22(q_p.x,q_p.y,s6.x,s6.y)/rxs,u6=cross22(q_p.x,q_p.y,r6.x,r6.y)/rxs;return t53<-tol||t53>1+tol||u6<-tol||u6>1+tol?null:{x:p12.x+t53*r6.x,y:p12.y+t53*r6.y}}var TOL4=1e-6;function isHorizontalEdge(edge){let dx3=Math.abs(edge.to.x-edge.from.x),dy3=Math.abs(edge.to.y-edge.from.y);return dx3>=dy3}function length6(a6,b6){return Math.hypot(b6.x-a6.x,b6.y-a6.y)}function pointAt(a6,b6,t53){return{x:a6.x+(b6.x-a6.x)*t53,y:a6.y+(b6.y-a6.y)*t53}}function paramAlong(a6,b6,p3){let L5=length6(a6,b6);if(L5<TOL4)return 0;let t53=((p3.x-a6.x)*(b6.x-a6.x)+(p3.y-a6.y)*(b6.y-a6.y))/((b6.x-a6.x)*(b6.x-a6.x)+(b6.y-a6.y)*(b6.y-a6.y));return Math.max(0,Math.min(1,t53))*L5}function mergeIntervals(intervals,tol=TOL4){if(intervals.length===0)return intervals;intervals.sort((a6,b6)=>a6.start-b6.start);let merged=[],cur={...intervals[0]};for(let i6=1;i6<intervals.length;i6++){let nxt=intervals[i6];nxt.start<=cur.end+tol?cur.end=Math.max(cur.end,nxt.end):(merged.push(cur),cur={...nxt})}return merged.push(cur),merged}function splitEdgeByCrossings(edge,crossingDistances,crossLen){let L5=length6(edge.from,edge.to);if(L5<TOL4||crossingDistances.length===0)return[edge];let half=crossLen/2,rawIntervals=crossingDistances.map(d3=>({start:Math.max(0,d3-half),end:Math.min(L5,d3+half)})).filter(iv2=>iv2.end-iv2.start>TOL4),intervals=mergeIntervals(rawIntervals),result=[],cursor=0,dir2={x:edge.to.x-edge.from.x,y:edge.to.y-edge.from.y},addSeg=(d03,d12,isCrossing)=>{if(d12-d03<=TOL4)return;let t03=d03/L5,t110=d12/L5;result.push({from:pointAt(edge.from,edge.to,t03),to:pointAt(edge.from,edge.to,t110),...isCrossing?{is_crossing:!0}:{}})};for(let iv2 of intervals)iv2.start-cursor>TOL4&&addSeg(cursor,iv2.start,!1),addSeg(iv2.start,iv2.end,!0),cursor=iv2.end;return L5-cursor>TOL4&&addSeg(cursor,L5,!1),result.length>0?result:[edge]}function computeCrossings(traces,opts={}){let crossLen=opts.crossSegmentLength??.075,tol=opts.tolerance??TOL4,crossingsByEdge=new Map,keyOf=ref=>`${ref.traceIdx}:${ref.edgeIdx}`,getEdge=ref=>traces[ref.traceIdx].edges[ref.edgeIdx];for(let ti3=0;ti3<traces.length;ti3++){let A4=traces[ti3];for(let ei3=0;ei3<A4.edges.length;ei3++){let eA2=A4.edges[ei3];for(let tj2=ti3;tj2<traces.length;tj2++){let B4=traces[tj2];for(let ej2=tj2===ti3?ei3+1:0;ej2<B4.edges.length;ej2++){let eB2=B4.edges[ej2];if(A4.connectivity_key!==void 0&&A4.connectivity_key===B4.connectivity_key)continue;let P6=segmentIntersection(eA2.from,eA2.to,eB2.from,eB2.to,tol);if(!P6)continue;let LA2=length6(eA2.from,eA2.to),LB2=length6(eB2.from,eB2.to);if(LA2<tol||LB2<tol)continue;let dA2=paramAlong(eA2.from,eA2.to,P6),dB2=paramAlong(eB2.from,eB2.to,P6),nearEndpointA=dA2<=tol||Math.abs(LA2-dA2)<=tol||Number.isNaN(dA2),nearEndpointB=dB2<=tol||Math.abs(LB2-dB2)<=tol||Number.isNaN(dB2);if(!nearEndpointA&&!nearEndpointB){let aIsHorizontal=isHorizontalEdge(eA2),bIsHorizontal=isHorizontalEdge(eB2),assignToA;if(aIsHorizontal!==bIsHorizontal)assignToA=aIsHorizontal;else{let ax3=Math.abs(eA2.to.x-eA2.from.x),ay3=Math.abs(eA2.to.y-eA2.from.y),bx3=Math.abs(eB2.to.x-eB2.from.x),by3=Math.abs(eB2.to.y-eB2.from.y),aScore=ax3-ay3,bScore=bx3-by3;assignToA=aScore===bScore?!0:aScore>bScore}let chosenKey=keyOf({traceIdx:assignToA?ti3:tj2,edgeIdx:assignToA?ei3:ej2}),chosenList=crossingsByEdge.get(chosenKey)??[];chosenList.push(assignToA?dA2:dB2),crossingsByEdge.set(chosenKey,chosenList)}}}}}let out=traces.map(t53=>({source_trace_id:t53.source_trace_id,connectivity_key:t53.connectivity_key,edges:[]}));for(let ti3=0;ti3<traces.length;ti3++){let trace=traces[ti3];for(let ei3=0;ei3<trace.edges.length;ei3++){let eRefKey=keyOf({traceIdx:ti3,edgeIdx:ei3}),splittingDistances=crossingsByEdge.get(eRefKey)??[];if(splittingDistances.length===0){out[ti3].edges.push(trace.edges[ei3]);continue}let uniqueSorted2=Array.from(new Set(splittingDistances.map(d3=>Number(d3.toFixed(6))))).sort((a6,b6)=>a6-b6),split=splitEdgeByCrossings(trace.edges[ei3],uniqueSorted2,crossLen);out[ti3].edges.push(...split)}}return out}var TOL22=1e-6;function nearlyEqual2(a6,b6,tol=TOL22){return Math.abs(a6-b6)<=tol}function pointEq(a6,b6,tol=TOL22){return nearlyEqual2(a6.x,b6.x,tol)&&nearlyEqual2(a6.y,b6.y,tol)}function onSegment4(p3,a6,b6,tol=TOL22){let minX=Math.min(a6.x,b6.x)-tol,maxX=Math.max(a6.x,b6.x)+tol,minY=Math.min(a6.y,b6.y)-tol,maxY=Math.max(a6.y,b6.y)+tol;return p3.x<minX||p3.x>maxX||p3.y<minY||p3.y>maxY?!1:Math.abs((b6.x-a6.x)*(p3.y-a6.y)-(b6.y-a6.y)*(p3.x-a6.x))<=tol}function dedupePoints(points,tol=TOL22){let map=new Map;for(let p3 of points){let key=`${p3.x.toFixed(6)},${p3.y.toFixed(6)}`;map.has(key)||map.set(key,p3)}return Array.from(map.values())}function edgeVec(e6){return{x:e6.to.x-e6.from.x,y:e6.to.y-e6.from.y}}function isEndpointOfEdge(p3,e6,tol=TOL22){return pointEq(p3,e6.from,tol)||pointEq(p3,e6.to,tol)}function isParallel(e12,e22,tol=TOL22){let v12=edgeVec(e12),v22=edgeVec(e22),L12=Math.hypot(v12.x,v12.y),L22=Math.hypot(v22.x,v22.y);if(L12<tol||L22<tol)return!0;let cross32=v12.x*v22.y-v12.y*v22.x;return Math.abs(cross32)<=tol*L12*L22}function incidentEdgesAtPoint(trace,p3,tol=TOL22){return trace.edges.filter(e6=>pointEq(e6.from,p3,tol)||pointEq(e6.to,p3,tol))}function nearestEndpointOnTrace(trace,p3,tol=TOL22){for(let e6 of trace.edges){if(pointEq(e6.from,p3,tol))return e6.from;if(pointEq(e6.to,p3,tol))return e6.to}return null}function edgeDirectionFromPoint(e6,p3,tol=TOL22){let other=pointEq(e6.from,p3,tol)||nearlyEqual2(e6.from.x,p3.x,tol)&&nearlyEqual2(e6.from.y,p3.y,tol)?e6.to:e6.from,dx3=other.x-p3.x,dy3=other.y-p3.y;return Math.abs(dx3)<tol&&Math.abs(dy3)<tol?null:Math.abs(dx3)>=Math.abs(dy3)?dx3>=0?"right":"left":dy3>=0?"up":"down"}function getCornerOrientationAtPoint(trace,p3,tol=TOL22){let incident=incidentEdgesAtPoint(trace,p3,tol);if(incident.length<2)return null;let dirs=incident.map(e6=>edgeDirectionFromPoint(e6,p3,tol)),hasUp=dirs.includes("up"),hasDown=dirs.includes("down"),hasLeft=dirs.includes("left"),hasRight=dirs.includes("right"),vertical=hasUp?"up":hasDown?"down":null,horizontal=hasRight?"right":hasLeft?"left":null;return vertical&&horizontal?`${vertical}-${horizontal}`:null}function computeJunctions(traces,opts={}){let tol=opts.tolerance??TOL22,result={};for(let t53 of traces)result[t53.source_trace_id]=[];let endpointsByTrace=traces.map(t53=>{let pts=[];for(let e6 of t53.edges)pts.push(e6.from,e6.to);return dedupePoints(pts,tol)});for(let i6=0;i6<traces.length;i6++){let A4=traces[i6],AEnds=endpointsByTrace[i6];for(let j6=i6+1;j6<traces.length;j6++){let B4=traces[j6],BEnds=endpointsByTrace[j6];if(A4.connectivity_key!==void 0&&A4.connectivity_key===B4.connectivity_key){for(let eA2 of A4.edges)for(let eB2 of B4.edges){let p3=segmentIntersection(eA2.from,eA2.to,eB2.from,eB2.to,tol);p3&&(isEndpointOfEdge(p3,eA2,tol)||isEndpointOfEdge(p3,eB2,tol)||(result[A4.source_trace_id].push(p3),A4.source_trace_id!==B4.source_trace_id&&result[B4.source_trace_id].push(p3)))}for(let pa3 of AEnds)for(let pb2 of BEnds)if(pointEq(pa3,pb2,tol)){let aEdgesAtP=incidentEdgesAtPoint(A4,pa3,tol),bEdgesAtP=incidentEdgesAtPoint(B4,pb2,tol),hasCorner=aEdgesAtP.some(eA2=>bEdgesAtP.some(eB2=>!isParallel(eA2,eB2,tol))),aCorner=getCornerOrientationAtPoint(A4,pa3,tol),bCorner=getCornerOrientationAtPoint(B4,pb2,tol);hasCorner&&!(aCorner!==null&&bCorner!==null&&aCorner===bCorner)&&(result[A4.source_trace_id].push(pa3),A4.source_trace_id!==B4.source_trace_id&&result[B4.source_trace_id].push(pb2))}for(let pa3 of AEnds)for(let eB2 of B4.edges)if(onSegment4(pa3,eB2.from,eB2.to,tol)){let hasCorner=incidentEdgesAtPoint(A4,pa3,tol).some(eA2=>!isParallel(eA2,eB2,tol)),aCorner=getCornerOrientationAtPoint(A4,pa3,tol),bEndpointNearPa=nearestEndpointOnTrace(B4,pa3,tol*1e3),bCorner=bEndpointNearPa?getCornerOrientationAtPoint(B4,bEndpointNearPa,tol):null;hasCorner&&!(aCorner!==null&&bCorner!==null&&aCorner===bCorner)&&(result[A4.source_trace_id].push(pa3),A4.source_trace_id!==B4.source_trace_id&&result[B4.source_trace_id].push(pa3))}for(let pb2 of BEnds)for(let eA2 of A4.edges)if(onSegment4(pb2,eA2.from,eA2.to,tol)){let hasCorner=incidentEdgesAtPoint(B4,pb2,tol).some(eB2=>!isParallel(eA2,eB2,tol)),bCorner=getCornerOrientationAtPoint(B4,pb2,tol),aEndpointNearPb=nearestEndpointOnTrace(A4,pb2,tol*1e3),aCorner=aEndpointNearPb?getCornerOrientationAtPoint(A4,aEndpointNearPb,tol):null;hasCorner&&!(aCorner!==null&&bCorner!==null&&aCorner===bCorner)&&(result[B4.source_trace_id].push(pb2),A4.source_trace_id!==B4.source_trace_id&&result[A4.source_trace_id].push(pb2))}}}}for(let id3 of Object.keys(result))result[id3]=dedupePoints(result[id3],tol);return result}var getPortForSchematicSymbolPort=port=>{let{schX,schY}=port._parsedProps;if(schX!==void 0&&schY!==void 0||!port.getParentNormalComponent()?.getSchematicSymbol())return port;let internallyConnectedPorts=port._getPortsInternallyConnectedToThisPort(),schematicSymbolPortDef=port.schematicSymbolPortDef??internallyConnectedPorts.find(connectedPort=>connectedPort.schematicSymbolPortDef)?.schematicSymbolPortDef;return schematicSymbolPortDef?internallyConnectedPorts.find(connectedPort=>connectedPort.schematicSymbolPortDef===schematicSymbolPortDef)??port:port},TOL32=1e-6;function isCollinear(a6,b6,tol=TOL32){let adx=a6.to.x-a6.from.x,ady=a6.to.y-a6.from.y,bdx=b6.to.x-b6.from.x,bdy=b6.to.y-b6.from.y,aLen=Math.hypot(adx,ady),bLen=Math.hypot(bdx,bdy);if(aLen<=tol||bLen<=tol)return!1;let directionCross=adx*bdy-ady*bdx;if(Math.abs(directionCross)>tol*aLen*bLen)return!1;let offsetCross=adx*(b6.from.y-a6.from.y)-ady*(b6.from.x-a6.from.x);return Math.abs(offsetCross)<=tol*aLen}function splitEdgeAroundIntervals(edge,intervals){let merged=mergeIntervals(intervals);if(merged.length===0)return[edge];let edgeLength=length6(edge.from,edge.to);if(edgeLength<=TOL32)return[edge];let result=[],cursor=0;for(let interval of merged)interval.start-cursor>TOL32&&result.push({from:pointAt(edge.from,edge.to,cursor/edgeLength),to:pointAt(edge.from,edge.to,interval.start/edgeLength)}),interval.end-interval.start>TOL32&&result.push({from:pointAt(edge.from,edge.to,interval.start/edgeLength),to:pointAt(edge.from,edge.to,interval.end/edgeLength),is_crossing:!0}),cursor=Math.max(cursor,interval.end);return edgeLength-cursor>TOL32&&result.push({from:pointAt(edge.from,edge.to,cursor/edgeLength),to:edge.to}),result}function removeOverlappingSameNetCrossingSegments(traces){let intervalsToRemove=new Map;for(let crossingTraceIndex=0;crossingTraceIndex<traces.length;crossingTraceIndex++){let crossingTrace=traces[crossingTraceIndex];if(crossingTrace.connectivity_key){for(let crossingEdge of crossingTrace.edges)if(!(!crossingEdge.is_crossing||length6(crossingEdge.from,crossingEdge.to)<=TOL32))for(let traceIndex=0;traceIndex<traces.length;traceIndex++){let candidateTrace=traces[traceIndex];if(!(traceIndex===crossingTraceIndex||candidateTrace.connectivity_key!==crossingTrace.connectivity_key))for(let edgeIndex=0;edgeIndex<candidateTrace.edges.length;edgeIndex++){let candidateEdge=candidateTrace.edges[edgeIndex],candidateLength=length6(candidateEdge.from,candidateEdge.to);if(candidateEdge.is_crossing||candidateLength<=TOL32||!isCollinear(candidateEdge,crossingEdge))continue;let start=Math.max(0,Math.min(paramAlong(candidateEdge.from,candidateEdge.to,crossingEdge.from),paramAlong(candidateEdge.from,candidateEdge.to,crossingEdge.to))),end=Math.min(candidateLength,Math.max(paramAlong(candidateEdge.from,candidateEdge.to,crossingEdge.from),paramAlong(candidateEdge.from,candidateEdge.to,crossingEdge.to)));if(end-start<=TOL32)continue;let key=`${traceIndex}:${edgeIndex}`,intervals=intervalsToRemove.get(key)??[];intervals.push({start,end}),intervalsToRemove.set(key,intervals)}}}}return intervalsToRemove.size===0?traces:traces.map((trace,traceIndex)=>({...trace,edges:trace.edges.flatMap((edge,edgeIndex)=>{let intervals=intervalsToRemove.get(`${traceIndex}:${edgeIndex}`);return intervals?splitEdgeAroundIntervals(edge,intervals):[edge]})}))}var debug10=(0,import_debug19.default)("Group_doInitialSchematicTraceRender"),MAX_PIN_SNAP_GAP=1.5;function extendTraceEndpointsToReachPinsInsideExpandedBoundingBox(params,db2){let{points,schematicPortIds,componentBoundsByPortId}=params,centers=schematicPortIds.map(id3=>{let center2=db2.schematic_port.get(id3)?.center,bounds=componentBoundsByPortId.get(id3);return!center2||!bounds?null:{center:center2,bounds}}).filter(port=>!!port);if(centers.length===0)return points;let result=points.map(p3=>({x:p3.x,y:p3.y})),d22=(a6,b6)=>(a6.x-b6.x)**2+(a6.y-b6.y)**2,usedCenters=new Set;for(let i6=0;i6<centers.length;i6++)result.some(p3=>d22(centers[i6].center,p3)<=1e-12)&&usedCenters.add(i6);let ALIGN_EPS=.001,endpoints=["start","end"],candidates=[];for(let endpoint of endpoints){let endpointPoint=endpoint==="start"?result[0]:result[result.length-1];for(let i6=0;i6<centers.length;i6++){if(usedCenters.has(i6))continue;let{center:center2,bounds}=centers[i6],dist=d22(center2,endpointPoint);Math.abs(center2.x-endpointPoint.x)>ALIGN_EPS&&Math.abs(center2.y-endpointPoint.y)>ALIGN_EPS||dist>MAX_PIN_SNAP_GAP**2&&pointToBoundsDistance(endpointPoint,bounds)>ALIGN_EPS||candidates.push({endpoint,centerIndex:i6,dist})}}candidates.sort((a6,b6)=>a6.dist-b6.dist);let usedEndpoints=new Set;for(let{endpoint,centerIndex,dist}of candidates){if(usedEndpoints.has(endpoint)||usedCenters.has(centerIndex)||(usedCenters.add(centerIndex),usedEndpoints.add(endpoint),dist<=1e-12))continue;let center2=centers[centerIndex].center;endpoint==="start"?result.unshift({x:center2.x,y:center2.y}):result.push({x:center2.x,y:center2.y})}return result}function applyTracesFromSolverOutput(args){let{group,solver,userNetIdToConnKey,schematicPortIdsWithPreExistingNetLabels}=args,{db:db2}=group.root,schematicPortIdsByRoutedSchematicPortId=new Map;for(let port of group.selectAll("port")){let routedSchematicPortIdValue=getPortForSchematicSymbolPort(port).schematic_port_id,schematicPortIdValue=port.schematic_port_id;if(!routedSchematicPortIdValue||!schematicPortIdValue)continue;let routedSchematicPortId=asSchematicPortId(routedSchematicPortIdValue),schematicPortId=asSchematicPortId(schematicPortIdValue),schematicPortIds=schematicPortIdsByRoutedSchematicPortId.get(routedSchematicPortId)??[];schematicPortIds.push(schematicPortId),schematicPortIdsByRoutedSchematicPortId.set(routedSchematicPortId,schematicPortIds)}let customSymbolPortIds=new Set(group.selectAll("port").filter(port=>{if(!port._getSymbolAncestor())return!1;let symbol=port.getParentNormalComponent()?._parsedProps.symbol;return(0,import_react6.isValidElement)(symbol)||isCircuitJsonSymbol(symbol)}).map(port=>port.schematic_port_id).filter(schematicPortId=>schematicPortId!=null).map(asSchematicPortId)),componentBoundsByPortId=new Map;for(let schematicComponent of db2.schematic_component.list()){let textInclusiveBounds=getSchematicComponentWithTextBounds({db:db2,schematicComponent}),componentBounds=getBoundFromCenteredRect({center:schematicComponent.center,width:schematicComponent.size.width,height:schematicComponent.size.height});for(let port of db2.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id})){let isInsideComponentBounds=port.center.x>componentBounds.minX&&port.center.x<componentBounds.maxX&&port.center.y>componentBounds.minY&&port.center.y<componentBounds.maxY,schematicPortId=asSchematicPortId(port.schematic_port_id);!textInclusiveBounds&&!customSymbolPortIds.has(schematicPortId)||!textInclusiveBounds&&isInsideComponentBounds||componentBoundsByPortId.set(schematicPortId,textInclusiveBounds??componentBounds)}}let traces=solver.inlineNetLabelSolver?.getOutput().traces??solver.sameNetJunctionAlignmentSolver?.getOutput().traces??solver.netLabelTraceCollisionSolver?.getOutput().traces??solver.traceCleanupSolver?.getOutput().traces??solver.traceLabelOverlapAvoidanceSolver?.getOutput().traces??solver.schematicTraceLinesSolver?.solvedTracePaths,pendingTraces=[];debug10(`Traces inside SchematicTraceSolver output: ${(traces??[]).length}`);for(let solvedTracePath of traces??[]){let solvedTraceSchematicPortIds=Array.from(new Set(solvedTracePath.pinIds??[])).map(asSchematicPortId);if(solvedTraceSchematicPortIds.length>0&&solvedTraceSchematicPortIds.every(id3=>schematicPortIdsWithPreExistingNetLabels.has(id3))){debug10(`Skipping solver netlabel-covered trace ${solvedTracePath?.mspPairId} because all schematic ports already have netlabels`);continue}let points=solvedTracePath?.tracePath;if(!Array.isArray(points)||points.length<2){debug10(`Skipping trace ${solvedTracePath?.pinIds.join(",")} because it has less than 2 points`);continue}let snappedPoints=extendTraceEndpointsToReachPinsInsideExpandedBoundingBox({points,schematicPortIds:solvedTraceSchematicPortIds,componentBoundsByPortId},db2),edges=[];for(let i6=0;i6<snappedPoints.length-1;i6++)edges.push({from:{x:snappedPoints[i6].x,y:snappedPoints[i6].y},to:{x:snappedPoints[i6+1].x,y:snappedPoints[i6+1].y}});let source_trace_id=String(solvedTracePath?.mspPairId),subcircuit_connectivity_map_key;if(Array.isArray(solvedTracePath?.pins)&&solvedTracePath.pins.length===2){let firstPinId=solvedTracePath.pins[0]?.pinId,secondPinId=solvedTracePath.pins[1]?.pinId,pA2=firstPinId?asSchematicPortId(firstPinId):void 0,pB2=secondPinId?asSchematicPortId(secondPinId):void 0;if(pA2&&pB2){let routedSchematicPortIds=new Set([pA2,pB2]);for(let routedSchematicPortId of routedSchematicPortIds){db2.schematic_port.update(routedSchematicPortId,{is_connected:!0});for(let schematicPortId of schematicPortIdsByRoutedSchematicPortId.get(routedSchematicPortId)??[])db2.schematic_port.update(schematicPortId,{is_connected:!0})}subcircuit_connectivity_map_key=userNetIdToConnKey.get(String(solvedTracePath.userNetId))}}if(subcircuit_connectivity_map_key||(subcircuit_connectivity_map_key=userNetIdToConnKey.get(String(solvedTracePath.userNetId))),!subcircuit_connectivity_map_key){let sourcePortConnKeys=solvedTraceSchematicPortIds.map(schematicPortId=>{let sourcePortId=db2.schematic_port.get(schematicPortId)?.source_port_id;if(sourcePortId)return db2.source_port.get(sourcePortId)?.subcircuit_connectivity_map_key}).filter(key=>!!key);new Set(sourcePortConnKeys).size===1&&(subcircuit_connectivity_map_key=sourcePortConnKeys[0])}let endpointSchematicSheetIds=new Set(solvedTraceSchematicPortIds.map(schematicPortId=>db2.schematic_port.get(schematicPortId)?.schematic_sheet_id).filter(sheetId=>!!sheetId)),schematicSheetId2;endpointSchematicSheetIds.size===1?schematicSheetId2=endpointSchematicSheetIds.values().next().value:endpointSchematicSheetIds.size===0&&(schematicSheetId2=group._resolveSchematicSheetId()),pendingTraces.push({source_trace_id,edges,subcircuit_connectivity_map_key,schematic_sheet_id:schematicSheetId2})}debug10(`Applying ${pendingTraces.length} traces from SchematicTraceSolver output`);let withCrossings=computeCrossings(pendingTraces.map(t53=>({source_trace_id:t53.source_trace_id,edges:t53.edges,connectivity_key:t53.subcircuit_connectivity_map_key}))),existingTracesForJunctions=[],schematicSheetId=group._resolveSchematicSheetId();for(let t53 of db2.schematic_trace.list()){if(t53.edges.length===0||t53.schematic_sheet_id!==schematicSheetId)continue;let sourceTrace=t53.source_trace_id?db2.source_trace.get(t53.source_trace_id):void 0;existingTracesForJunctions.push({schematic_trace_id:t53.schematic_trace_id,source_trace_id:t53.source_trace_id??t53.schematic_trace_id,edges:t53.edges,connectivity_key:t53.subcircuit_connectivity_map_key??sourceTrace?.subcircuit_connectivity_map_key})}let tracesWithTrimmedCrossingOverlaps=removeOverlappingSameNetCrossingSegments([...withCrossings,...existingTracesForJunctions]),visibleTraces=tracesWithTrimmedCrossingOverlaps.slice(0,withCrossings.length),visibleExistingTraces=tracesWithTrimmedCrossingOverlaps.slice(withCrossings.length);for(let trace of visibleExistingTraces)trace.schematic_trace_id&&db2.schematic_trace.update(trace.schematic_trace_id,{edges:trace.edges});let junctionsById=computeJunctions([...visibleTraces,...visibleExistingTraces]);for(let t53 of visibleTraces){let pendingTrace=pendingTraces.find(pendingTrace2=>pendingTrace2.source_trace_id===t53.source_trace_id),traceSchematicSheetId=schematicSheetId;pendingTrace?.schematic_sheet_id&&(traceSchematicSheetId=pendingTrace.schematic_sheet_id),db2.schematic_trace.insert({source_trace_id:t53.source_trace_id,edges:t53.edges,junctions:junctionsById[t53.source_trace_id]??[],subcircuit_connectivity_map_key:pendingTrace?.subcircuit_connectivity_map_key,schematic_sheet_id:traceSchematicSheetId})}}var INLINE_NET_LABEL_FONT_SIZE=.12,applyInlineNetLabelEligibility=({directConnections,netConnections,connKeyToSchematicPortIds,connKeyToSourceNet,connKeysWithExplicitPortNetTraces,schematicPortIdsWithExplicitNetLabels,schematicPortIdsWithInlineNetLabels,areSchematicPortsOnDifferentComponents,resolveCanonicalNetLabelText})=>{let markEligible=(connection,name)=>{connection.anchoredNetLabelWidth??(connection.anchoredNetLabelWidth=Number(getSchematicNetLabelTextWidth2({text:name}).toFixed(2))),connection.allowInlineNetLabel=!0,connection.inlineNetLabelHeight=INLINE_NET_LABEL_FONT_SIZE,connection.inlineNetLabelWidth=Number(getSchematicNetLabelTextWidth2({text:name,font_size:INLINE_NET_LABEL_FONT_SIZE}).toFixed(2))};for(let directConnection of directConnections){let{connKey}=directConnection;if(!connKey||connKeyToSchematicPortIds.get(connKey)?.length!==2)continue;let sourceNet=connKeyToSourceNet.get(connKey);if(sourceNet?.is_power||sourceNet?.is_ground)continue;let{name,wasAssignedDisplayLabel}=resolveCanonicalNetLabelText({subcircuitConnectivityMapKey:connKey});!name||!wasAssignedDisplayLabel||markEligible(directConnection,name)}for(let netConnection of netConnections){let{schematicPortIds}=netConnection,hasInlineNetLabel=schematicPortIds.some(schematicPortId=>schematicPortIdsWithInlineNetLabels.has(schematicPortId)),isSinglePort=schematicPortIds.length===1,isTwoPortChipToChip=schematicPortIds.length===2&&areSchematicPortsOnDifferentComponents(schematicPortIds);if(!hasInlineNetLabel&&!isSinglePort&&!isTwoPortChipToChip||!hasInlineNetLabel&&schematicPortIds.some(schematicPortId=>schematicPortIdsWithExplicitNetLabels.has(schematicPortId)))continue;let{connKey}=netConnection;if(!connKey||!connKeysWithExplicitPortNetTraces.has(connKey))continue;let sourceNet=connKeyToSourceNet.get(connKey);if(!hasInlineNetLabel&&(sourceNet?.is_power||sourceNet?.is_ground))continue;let{name,wasAssignedDisplayLabel}=resolveCanonicalNetLabelText({subcircuitConnectivityMapKey:connKey});!name||!hasInlineNetLabel&&!wasAssignedDisplayLabel||markEligible(netConnection,name)}},isDirectConnectionEndpointOutsideSchematicScope=({db:db2,sourcePortId,otherSourcePortId,sourcePortIdsInSchematicScope,schematicSheetId})=>{if(sourcePortIdsInSchematicScope.has(otherSourcePortId))return!1;let sourcePort=db2.source_port.get(sourcePortId),otherSourcePort=db2.source_port.get(otherSourcePortId);if(!sourcePort||!otherSourcePort)return!1;if(sourcePort.subcircuit_id!==otherSourcePort.subcircuit_id)return!0;if(!schematicSheetId)return!1;let otherEndpointSchematicPorts=db2.schematic_port.list({source_port_id:otherSourcePortId});return otherEndpointSchematicPorts.some(schematicPort=>schematicPort.schematic_sheet_id===schematicSheetId)?!1:otherEndpointSchematicPorts.some(schematicPort=>schematicPort.schematic_sheet_id!==void 0)},getDirectConnectionOutsideSchematicScopeSourcePortId=({db:db2,sourcePortId,sourcePortIdsInSchematicScope,schematicSheetId})=>{if(db2.source_port.get(sourcePortId))for(let sourceTrace of db2.source_trace.list()){let connectedSourcePortIds=(sourceTrace.connected_source_port_ids??[]).map(asSourcePortId);if(connectedSourcePortIds.length!==2||(sourceTrace.connected_source_net_ids??[]).length>0||!connectedSourcePortIds.includes(sourcePortId))continue;let otherSourcePortId=connectedSourcePortIds.find(portId=>portId!==sourcePortId);if(otherSourcePortId&&isDirectConnectionEndpointOutsideSchematicScope({db:db2,sourcePortId,otherSourcePortId,sourcePortIdsInSchematicScope,schematicSheetId}))return otherSourcePortId}},resolveNetLabelForPortMissingTrace=({group,sourcePortId,connectedSourcePortIdsForKey,sourcePortIdsInSchematicScope,schematicSheetId,connKey,sourceNet})=>{let{db:db2}=group.root,connectedPortsForKey=group.selectAll("port").filter(port=>port._getSubcircuitConnectivityKey()===connKey),{name:resolvedPortNetLabelText,wasAssignedDisplayLabel}=getNetNameFromPorts(connectedPortsForKey),assignedPortNetLabelText=wasAssignedDisplayLabel?resolvedPortNetLabelText:void 0,fallbackPortNetLabelText=wasAssignedDisplayLabel?void 0:resolvedPortNetLabelText||void 0,implicitPortLabelText=getNetNameFromSourcePorts(db2,connectedSourcePortIdsForKey),directConnectionOutsideSchematicScopeSourcePortId=getDirectConnectionOutsideSchematicScopeSourcePortId({db:db2,sourcePortId,sourcePortIdsInSchematicScope,schematicSheetId}),directConnectionOutsideSchematicScopeLabelText=directConnectionOutsideSchematicScopeSourcePortId?getSourcePortNetLabelText(db2,directConnectionOutsideSchematicScopeSourcePortId):void 0;return{text:sourceNet?.name||sourceNet?.source_net_id||assignedPortNetLabelText||directConnectionOutsideSchematicScopeLabelText||fallbackPortNetLabelText||implicitPortLabelText||connKey,wasAssignedDisplayLabel,directConnectionOutsideSchematicScopeSourcePortId}},DEFAULT_SCHEMATIC_TEXT_FONT_SIZE=.18;function getSchematicTextBounds(text){let fontSize=text.font_size??DEFAULT_SCHEMATIC_TEXT_FONT_SIZE,width=getSchematicTextWidth({text:text.text??"",fontSize}),height=fontSize,anchor=text.anchor??"center",minX,maxX;anchor.includes("left")?(minX=0,maxX=width):anchor.includes("right")?(minX=-width,maxX=0):(minX=-width/2,maxX=width/2);let minY,maxY;anchor.includes("top")?(minY=-height,maxY=0):anchor.includes("bottom")?(minY=0,maxY=height):(minY=-height/2,maxY=height/2);let rotation42=(text.rotation??0)*Math.PI/180,cos6=Math.cos(rotation42),sin6=Math.sin(rotation42),corners=[{x:minX,y:minY},{x:minX,y:maxY},{x:maxX,y:minY},{x:maxX,y:maxY}].map(corner=>({x:text.position.x+corner.x*cos6-corner.y*sin6,y:text.position.y+corner.x*sin6+corner.y*cos6}));return getBoundsFromPoints2(corners)}var REFDES_TEXT_BOX_CHIP_OVERLAP=.01,REFDES_TEXT_BOX_CLEARANCE=.06;function isReferenceDesignatorText(text,sourceComponent){return sourceComponent?text.text===sourceComponent.display_name||text.text===sourceComponent.name:!1}function schematicTextToTextBox(text,options={}){if(!text.text)return null;let bounds=getSchematicTextBounds(text);if(isReferenceDesignatorText(text,options.sourceComponent)&&options.schematicComponent?.center&&options.schematicComponent?.size){let componentBounds=getBoundFromCenteredRect({center:options.schematicComponent.center,width:options.schematicComponent.size.width,height:options.schematicComponent.size.height}),textHeight=bounds.maxY-bounds.minY;bounds.minY>componentBounds.maxY&&(bounds.minX-=REFDES_TEXT_BOX_CLEARANCE,bounds.maxX+=REFDES_TEXT_BOX_CLEARANCE,bounds.minY=componentBounds.maxY-REFDES_TEXT_BOX_CHIP_OVERLAP,bounds.maxY=componentBounds.maxY+textHeight+REFDES_TEXT_BOX_CLEARANCE)}return{chipId:text.schematic_component_id,center:getBoundsCenter2(bounds),width:bounds.maxX-bounds.minX,height:bounds.maxY-bounds.minY,text:text.text}}var DEFAULT_MAX_MSP_PAIR_DISTANCE2=2.4,SCHEMATIC_RAIL_NET_LABEL_HEIGHT=.42;function createSchematicTraceSolverInputProblem(group,opts={}){let{db:db2}=group.root,connKeyToSourceNet=new Map,childGroups=[],componentsToVisit=[...group.children].reverse();for(;componentsToVisit.length>0;){let child=componentsToVisit.pop();if(child instanceof Group5){if(child.isSubcircuit){child._parsedProps.showAsSchematicBox&&childGroups.push(child);continue}childGroups.push(child)}componentsToVisit.push(...[...child.children].reverse())}let allSchematicGroupIds=[group.schematic_group_id,...childGroups.map(a6=>a6.schematic_group_id)],schematicComponents=db2.schematic_component.list().filter(component=>allSchematicGroupIds.includes(component.schematic_group_id)).filter(component=>opts.schematicSheetId===void 0||component.schematic_sheet_id===opts.schematicSheetId),schematicComponentIds=new Set(schematicComponents.map(component=>component.schematic_component_id)),schematicComponentsById=new Map(schematicComponents.map(component=>[component.schematic_component_id,component])),textBoxes=db2.schematic_text.list().filter(text=>text.schematic_component_id&&schematicComponentIds.has(text.schematic_component_id)).map(text=>{let schematicComponent=schematicComponentsById.get(text.schematic_component_id);if(!schematicComponent)return;let sourceComponent=db2.source_component.get(schematicComponent.source_component_id);return schematicTextToTextBox(text,{schematicComponent,sourceComponent})}).filter(textBox=>!!textBox),sectionIdBySchematicComponentId=new Map;for(let component of group.getDescendants()){let schematicComponentId=component.schematic_component_id,sectionId=component.getSchematicSectionName();schematicComponentId&&sectionId&&sectionIdBySchematicComponentId.set(schematicComponentId,sectionId)}let chips=[];for(let schematicComponent of schematicComponents){let chipId=schematicComponent.schematic_component_id,pins=db2.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id}).map(schematicPort=>{let schematicPortId=asSchematicPortId(schematicPort.schematic_port_id),sourcePort=schematicPort.source_port_id?db2.source_port.get(schematicPort.source_port_id):void 0;return{pinId:schematicPortId,displayName:schematicPort.display_pin_label??schematicPort.pin_number?.toString()??sourcePort?.name,x:schematicPort.center.x,y:schematicPort.center.y,_facingDirection:convertFacingDirectionToElbowDirection(schematicPort.facing_direction??null)}}),sectionId=sectionIdBySchematicComponentId.get(schematicComponent.schematic_component_id),layoutBounds=getSchematicComponentWithTextBounds({db:db2,schematicComponent})??getBoundFromCenteredRect({center:schematicComponent.center,width:schematicComponent.size.width,height:schematicComponent.size.height});chips.push({chipId,center:getBoundsCenter2(layoutBounds),width:layoutBounds.maxX-layoutBounds.minX,height:layoutBounds.maxY-layoutBounds.minY,pins,sectionId})}let schematicPortIdsInScope=new Set,schPortIdToSourcePortId=new Map,sourcePortIdToSchPortId=new Map,userNetIdToConnKey=new Map,componentPortBySchematicPortId=new Map(group.selectAll("port").filter(port=>port.schematic_port_id).map(port=>[asSchematicPortId(port.schematic_port_id),port])),resolveCanonicalNetLabelText=createCanonicalSchematicNetLabelTextResolver(group);for(let sc3 of schematicComponents){let ports=db2.schematic_port.list({schematic_component_id:sc3.schematic_component_id});for(let sp3 of ports){let schematicPortId=asSchematicPortId(sp3.schematic_port_id);if(schematicPortIdsInScope.add(schematicPortId),sp3.source_port_id){let sourcePortId=asSourcePortId(sp3.source_port_id);schPortIdToSourcePortId.set(schematicPortId,sourcePortId),sourcePortIdToSchPortId.set(sourcePortId,schematicPortId)}}}let sourcePortIdsInSchematicScope=new Set(sourcePortIdToSchPortId.keys()),netLabelsInScope=(opts.netLabels??[]).filter(netLabel=>netLabel._getConnectedPorts().some(port=>port.schematic_port_id?schematicPortIdsInScope.has(asSchematicPortId(port.schematic_port_id)):!1)),schematicPortIdsWithExplicitNetLabels=new Set(netLabelsInScope.filter(netLabel=>!netLabel._parsedProps.inline).flatMap(netLabel=>netLabel._getConnectedPorts()).map(port=>port.schematic_port_id).filter(schematicPortId=>schematicPortId!=null).map(asSchematicPortId)),solverManagedNetLabelSchematicPortIds=new Set(netLabelsInScope.filter(netLabel=>netLabel._parsedProps.inline||netLabel._parsedProps.schX===void 0&&netLabel._parsedProps.schY===void 0).flatMap(netLabel=>netLabel._getConnectedPorts()).map(port=>port.schematic_port_id).filter(schematicPortId=>schematicPortId!=null).map(asSchematicPortId)),schematicPortIdsWithInlineNetLabels=new Set(netLabelsInScope.filter(netLabel=>netLabel._parsedProps.inline).flatMap(netLabel=>netLabel._getConnectedPorts()).map(port=>port.schematic_port_id).filter(schematicPortId=>schematicPortId!=null).map(asSchematicPortId)),allowedSubcircuitIds=new Set;group.subcircuit_id&&allowedSubcircuitIds.add(group.subcircuit_id);for(let cg2 of childGroups)cg2.subcircuit_id&&allowedSubcircuitIds.add(cg2.subcircuit_id);let tracesInScope=db2.source_trace.list().filter(st3=>{if(st3.subcircuit_id===group.subcircuit_id)return!0;for(let source_port_id of st3.connected_source_port_ids)if(sourcePortIdToSchPortId.has(asSourcePortId(source_port_id)))return!0;return!1}),schematicPortIdsWithExternallyRoutedRepresentations=new Set;for(let sourceTrace of tracesInScope)if(sourceTrace.subcircuit_id!==group.subcircuit_id&&sourceTrace.connected_source_net_ids.length!==0)for(let sourcePortId of sourceTrace.connected_source_port_ids){let typedSourcePortId=asSourcePortId(sourcePortId),schematicPortId=sourcePortIdToSchPortId.get(typedSourcePortId);!schematicPortId||solverManagedNetLabelSchematicPortIds.has(schematicPortId)||!db2.schematic_port.list({source_port_id:sourcePortId}).some(port=>port.schematic_port_id===schematicPortId?!1:(port.schematic_component_id?db2.schematic_component.get(port.schematic_component_id):void 0)?.schematic_sheet_id===opts.schematicSheetId)||schematicPortIdsWithExternallyRoutedRepresentations.add(schematicPortId)}let externalNetIds=tracesInScope.flatMap(st3=>st3.connected_source_net_ids);for(let netId of externalNetIds){let net=db2.source_net.get(netId);net?.subcircuit_id&&allowedSubcircuitIds.add(net.subcircuit_id)}for(let net of db2.source_net.list().filter(sourceNet=>!sourceNet.subcircuit_id||allowedSubcircuitIds.has(sourceNet.subcircuit_id)))net.subcircuit_connectivity_map_key&&connKeyToSourceNet.set(net.subcircuit_connectivity_map_key,net);let directConnections=[],singlePortTraceNetConnections=[],connectedPairKeys=new Set,crossSubcircuitTraceLabelBySchematicPortId=new Map,sourceTraceIdsByPortOnlyLabelSchematicPortId=new Map,sourceTraceIdByPinPairKey=new Map,connKeysWithExplicitPortNetTraces=new Set;for(let sourceTrace of tracesInScope)sourceTrace?.subcircuit_connectivity_map_key&&(sourceTrace.connected_source_port_ids?.length??0)>0&&(sourceTrace.connected_source_net_ids?.length??0)>0&&connKeysWithExplicitPortNetTraces.add(sourceTrace.subcircuit_connectivity_map_key);for(let st3 of tracesInScope){let connected=(st3.connected_source_port_ids??[]).map(sourcePortId=>sourcePortIdToSchPortId.get(asSourcePortId(sourcePortId))).filter(schematicPortId=>!!schematicPortId&&schematicPortIdsInScope.has(schematicPortId)),sourcePortIdForSingleConnectedEndpoint=connected.length===1?schPortIdToSourcePortId.get(connected[0]):void 0,otherSourcePortId=sourcePortIdForSingleConnectedEndpoint?st3.connected_source_port_ids.map(asSourcePortId).find(sourcePortId=>sourcePortId!==sourcePortIdForSingleConnectedEndpoint):void 0,crossesSchematicScopeBoundary=!!(sourcePortIdForSingleConnectedEndpoint&&otherSourcePortId&&isDirectConnectionEndpointOutsideSchematicScope({db:db2,sourcePortId:sourcePortIdForSingleConnectedEndpoint,otherSourcePortId,sourcePortIdsInSchematicScope,schematicSheetId:opts.schematicSheetId}));if(connected.length===1&&st3.connected_source_port_ids.length===2&&crossesSchematicScopeBoundary&&st3.connected_source_net_ids.length===0&&st3.subcircuit_connectivity_map_key){let schematicPortId=connected[0],sourcePortId=schPortIdToSourcePortId.get(schematicPortId);if(sourcePortId){let connKey=st3.subcircuit_connectivity_map_key,connectedSourcePortIdsForKey=Array.from(schematicPortIdsInScope).map(portId=>schPortIdToSourcePortId.get(portId)).filter(sourcePortId2=>sourcePortId2?db2.source_port.get(sourcePortId2)?.subcircuit_connectivity_map_key===connKey:!1),{text}=resolveNetLabelForPortMissingTrace({group,sourcePortId,connectedSourcePortIdsForKey,sourcePortIdsInSchematicScope,schematicSheetId:opts.schematicSheetId,connKey,sourceNet:connKeyToSourceNet.get(connKey)});text&&!crossSubcircuitTraceLabelBySchematicPortId.has(schematicPortId)&&(crossSubcircuitTraceLabelBySchematicPortId.set(schematicPortId,{text,sourceTraceId:st3.source_trace_id}),userNetIdToConnKey.set(text,connKey),singlePortTraceNetConnections.push({netId:text,schematicPortIds:[schematicPortId],netLabelWidth:Number(getSchematicNetLabelTextWidth2({text}).toFixed(2))}))}}else if(connected.length>=2){for(let schematicPortId of connected){let sourceTraceIds=sourceTraceIdsByPortOnlyLabelSchematicPortId.get(schematicPortId)??new Set;sourceTraceIds.add(st3.source_trace_id),sourceTraceIdsByPortOnlyLabelSchematicPortId.set(schematicPortId,sourceTraceIds)}let traceLabel=st3.name??st3.display_name,userNetId=traceLabel??st3.source_trace_id;st3.subcircuit_connectivity_map_key&&userNetIdToConnKey.set(userNetId,st3.subcircuit_connectivity_map_key);let maxMspDist=group._parsedProps.schMaxTraceDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE2,portsForConnection=connected.map(schematicPortId=>componentPortBySchematicPortId.get(schematicPortId)).filter(port=>!!port),renderedNetLabelText=st3.subcircuit_connectivity_map_key?resolveCanonicalNetLabelText({subcircuitConnectivityMapKey:st3.subcircuit_connectivity_map_key}).name:getNetNameFromPorts(portsForConnection).name||traceLabel,shouldRenderNetLabels=connected.slice(1).some((b6,index)=>{let a6=connected[index],portA=db2.schematic_port.get(a6),portB=db2.schematic_port.get(b6);return!portA||!portB?!1:Math.sqrt((portA.center.x-portB.center.x)**2+(portA.center.y-portB.center.y)**2)>maxMspDist}),netLabelWidth=renderedNetLabelText&&shouldRenderNetLabels?Number(getSchematicNetLabelTextWidth2({text:renderedNetLabelText}).toFixed(2)):void 0;for(let i6=0;i6<connected.length-1;i6++){let a6=connected[i6],b6=connected[i6+1],pairKey=[a6,b6].sort().join("::");connectedPairKeys.has(pairKey)||(connectedPairKeys.add(pairKey),sourceTraceIdByPinPairKey.set(pairKey,st3.source_trace_id),directConnections.push({schematicPortIds:[a6,b6],netId:userNetId,netLabelWidth,connKey:st3.subcircuit_connectivity_map_key}))}}}let netConnections=[...singlePortTraceNetConnections],connKeyToSchematicPortIds=new Map;for(let[schId,srcPortId]of schPortIdToSourcePortId){if(schematicPortIdsWithExternallyRoutedRepresentations.has(schId))continue;let sp3=db2.source_port.get(srcPortId);if(!sp3?.subcircuit_connectivity_map_key)continue;let connKey=sp3.subcircuit_connectivity_map_key;connKeyToSchematicPortIds.has(connKey)||connKeyToSchematicPortIds.set(connKey,[]),connKeyToSchematicPortIds.get(connKey).push(schId)}for(let[connKey,schematicPortIds]of connKeyToSchematicPortIds){let sourceNet=connKeyToSourceNet.get(connKey);if(sourceNet&&schematicPortIds.length>=1){let seenRoutedSchematicPortIds=new Set,uniqueSchematicPortIds=schematicPortIds.filter(schematicPortId=>{let componentPort=componentPortBySchematicPortId.get(schematicPortId),routedSchematicPortIdValue=componentPort?getPortForSchematicSymbolPort(componentPort).schematic_port_id:null,routedSchematicPortId=routedSchematicPortIdValue?asSchematicPortId(routedSchematicPortIdValue):schematicPortId;return seenRoutedSchematicPortIds.has(routedSchematicPortId)?!1:(seenRoutedSchematicPortIds.add(routedSchematicPortId),!0)}),userNetId=String(sourceNet.name||sourceNet.source_net_id||connKey);userNetIdToConnKey.set(userNetId,connKey);let netLabelTextWidth=Number(getSchematicNetLabelTextWidth2({text:String(userNetId)}).toFixed(2)),netLabelWidth=netLabelTextWidth,netLabelHeight;(sourceNet.is_ground||sourceNet.is_power)&&(netLabelWidth=SCHEMATIC_RAIL_NET_LABEL_HEIGHT,netLabelHeight=netLabelTextWidth),netConnections.push({netId:userNetId,schematicPortIds:uniqueSchematicPortIds,netLabelWidth,netLabelHeight,connKey})}}applyInlineNetLabelEligibility({directConnections,netConnections,connKeyToSchematicPortIds,connKeyToSourceNet,connKeysWithExplicitPortNetTraces,schematicPortIdsWithExplicitNetLabels,schematicPortIdsWithInlineNetLabels,areSchematicPortsOnDifferentComponents:schematicPortIds=>{let componentIds=schematicPortIds.map(schematicPortId=>db2.schematic_port.get(schematicPortId)?.schematic_component_id);return componentIds.every(componentId=>!!componentId)&&componentIds[0]!==componentIds[1]},resolveCanonicalNetLabelText});let availableNetLabelOrientations=(()=>{let netToAllowedOrientations={},presentNetIds=new Set(netConnections.map(nc3=>nc3.netId));for(let net of db2.source_net.list().filter(n3=>!n3.subcircuit_id||allowedSubcircuitIds.has(n3.subcircuit_id)))net.name&&presentNetIds.has(net.name)&&(net.is_ground?netToAllowedOrientations[net.name]=["y-"]:net.is_power?netToAllowedOrientations[net.name]=["y+"]:netToAllowedOrientations[net.name]=["x-","x+"]);for(let{netId}of singlePortTraceNetConnections)netToAllowedOrientations[netId]??(netToAllowedOrientations[netId]=["x-","x+"]);return netToAllowedOrientations})(),inputProblem={chips,directConnections:directConnections.map(({schematicPortIds,connKey,...connection})=>({...connection,pinIds:schematicPortIds})),netConnections:netConnections.map(({schematicPortIds,connKey,...connection})=>({...connection,pinIds:schematicPortIds})),textBoxes,availableNetLabelOrientations,maxMspPairDistance:group._parsedProps.schMaxTraceDistance??DEFAULT_MAX_MSP_PAIR_DISTANCE2},sourceTraceIdByPortOnlyLabelSchematicPortId=new Map(Array.from(sourceTraceIdsByPortOnlyLabelSchematicPortId).flatMap(([schematicPortId,sourceTraceIds])=>sourceTraceIds.size!==1?[]:[[schematicPortId,sourceTraceIds.values().next().value]]));return{inputProblem,connKeyToSourceNet,userNetIdToConnKey,crossSubcircuitTraceLabelBySchematicPortId,sourceTraceIdByPortOnlyLabelSchematicPortId,connKeysWithExplicitPortNetTraces,schematicPortIdsInScope,schematicPortIdsWithExternallyRoutedRepresentations,schPortIdToSourcePortId,netLabelsInScope,sourceTraceIdByPinPairKey}}var getSchematicPortIdsWithAssignedNetLabels=netLabels=>{let schematicPortIdsWithNetLabels=new Set;for(let netLabel of netLabels){let{inline,schX,schY}=netLabel._parsedProps;if(inline||schX===void 0&&schY===void 0)continue;let netLabelPorts=netLabel._getConnectedPorts();for(let port of netLabelPorts)port.schematic_port_id&&schematicPortIdsWithNetLabels.add(asSchematicPortId(port.schematic_port_id))}return schematicPortIdsWithNetLabels},getSchematicPortIdsWithRoutedTraces=({solver})=>{let solvedTraces=solver.traceCleanupSolver?.getOutput().traces??solver.traceLabelOverlapAvoidanceSolver?.getOutput().traces??solver.schematicTraceLinesSolver?.solvedTracePaths??[],schematicPortIdsWithRoutedTraces=new Set;for(let solvedTrace of solvedTraces){let points=solvedTrace?.tracePath;if(!Array.isArray(points)||points.length<2)continue;let pinIds=Array.isArray(solvedTrace.pins)?solvedTrace.pins.map(pin=>pin.pinId):solvedTrace.pinIds;for(let pinId of pinIds){let schPortId=asSchematicPortId(pinId);schPortId&&schematicPortIdsWithRoutedTraces.add(schPortId)}}return schematicPortIdsWithRoutedTraces},NEAR_EXISTING_NET_LABEL_DISTANCE=.5,SAME_ANCHOR_POSITION_DISTANCE=.1,doesSchematicNetLabelRepresentCurrentSourceConnection=args=>{let{nl:nl3,connKey,sourceNet,text}=args;return sourceNet?.source_net_id&&nl3.source_net_id?nl3.source_net_id===sourceNet.source_net_id:nl3.source_net_id?nl3.source_net_id===connKey:nl3.text===text},insertNetLabelsForPortsMissingTrace=({schematicPortIdsInScope,schematicPortIdsWithExternallyRoutedRepresentations,group,schPortIdToSourcePortId,connKeyToSourceNet})=>{let{db:db2}=group.root,sourcePortIdsInSchematicScope=new Set(Array.from(schematicPortIdsInScope).map(schematicPortId=>schPortIdToSourcePortId.get(schematicPortId)).filter(sourcePortId=>sourcePortId!==void 0));for(let schematicPortId of schematicPortIdsInScope){if(schematicPortIdsWithExternallyRoutedRepresentations.has(schematicPortId))continue;let schPort=db2.schematic_port.get(schematicPortId);if(!schPort||schPort.is_connected)continue;let srcPortId=schPortIdToSourcePortId.get(schematicPortId);if(!srcPortId)continue;let sourcePort=db2.source_port.get(srcPortId);if(group._parsedProps.showAsSchematicBox&&sourcePort?.subcircuit_id===group.subcircuit_id&&!sourcePort.source_component_id&&getDirectConnectionOutsideSchematicScopeSourcePortId({db:db2,sourcePortId:srcPortId,sourcePortIdsInSchematicScope,schematicSheetId:schPort.schematic_sheet_id}))continue;let connKey=sourcePort?.subcircuit_connectivity_map_key;if(!connKey)continue;let sourceNet=connKeyToSourceNet.get(connKey),schComponent=schPort.schematic_component_id?db2.schematic_component.get(schPort.schematic_component_id):void 0,portSchematicSheetId=schComponent?.schematic_sheet_id??group._resolveSchematicSheetId(),connectedSourcePortIdsForKey=Array.from(schematicPortIdsInScope).map(portId=>schPortIdToSourcePortId.get(portId)).filter(sourcePortId=>sourcePortId?db2.source_port.get(sourcePortId)?.subcircuit_connectivity_map_key===connKey:!1),{text,wasAssignedDisplayLabel,directConnectionOutsideSchematicScopeSourcePortId}=resolveNetLabelForPortMissingTrace({group,sourcePortId:srcPortId,connectedSourcePortIdsForKey,sourcePortIdsInSchematicScope,schematicSheetId:schPort.schematic_sheet_id,connKey,sourceNet}),shouldPreserveDirectConnectionEndpointLabels=directConnectionOutsideSchematicScopeSourcePortId?db2.schematic_port.list({source_port_id:directConnectionOutsideSchematicScopeSourcePortId}).some(port=>!port.is_connected):!1,isCollapsedBoxPort=schComponent?.is_box_with_pins&&sourcePort&&!sourcePort.source_component_id,hasExternalTrace=db2.source_trace.list().some(trace=>trace.connected_source_port_ids.includes(srcPortId)&&trace.subcircuit_id!==sourcePort?.subcircuit_id);if(isCollapsedBoxPort&&!hasExternalTrace&&!!!(sourceNet||wasAssignedDisplayLabel))continue;let connectedPortCountForKey=Array.from(schematicPortIdsInScope).filter(portId=>{let sourcePortId=schPortIdToSourcePortId.get(portId);return sourcePortId?db2.source_port.get(sourcePortId)?.subcircuit_connectivity_map_key===connKey:!1}).length,isGndNet=sourceNet?.is_ground??!1,isPowerNet=!isGndNet&&(sourceNet?.is_power??!1),side;isGndNet?side="top":isPowerNet?side="bottom":side=getEnteringEdgeFromDirection(schPort.facing_direction||"right")||"right";let center2=computeSchematicNetLabelCenter({anchor_position:schPort.center,anchor_side:side,text}),existingNetLabelForCurrentSourceConnection=db2.schematic_net_label.list().find(nl3=>nl3.schematic_sheet_id!==portSchematicSheetId?!1:doesSchematicNetLabelRepresentCurrentSourceConnection({nl:nl3,connKey,sourceNet,text}));if(existingNetLabelForCurrentSourceConnection&&connectedPortCountForKey<=1&&!shouldPreserveDirectConnectionEndpointLabels){db2.schematic_net_label.update(existingNetLabelForCurrentSourceConnection.schematic_net_label_id,{text,anchor_position:schPort.center,center:center2,anchor_side:side});continue}if(existingNetLabelForCurrentSourceConnection){let dx3=existingNetLabelForCurrentSourceConnection.anchor_position.x-schPort.center.x,dy3=existingNetLabelForCurrentSourceConnection.anchor_position.y-schPort.center.y;if(dx3*dx3+dy3*dy3<NEAR_EXISTING_NET_LABEL_DISTANCE*NEAR_EXISTING_NET_LABEL_DISTANCE){if(isGndNet){let anchor_side=existingNetLabelForCurrentSourceConnection.anchor_side??side;db2.schematic_net_label.update(existingNetLabelForCurrentSourceConnection.schematic_net_label_id,{text,anchor_position:schPort.center,center:computeSchematicNetLabelCenter({anchor_position:schPort.center,anchor_side,text}),anchor_side})}else if(!isPowerNet&&existingNetLabelForCurrentSourceConnection.text===text){let anchor_side=existingNetLabelForCurrentSourceConnection.anchor_side??side;db2.schematic_net_label.update(existingNetLabelForCurrentSourceConnection.schematic_net_label_id,{text,anchor_position:schPort.center,center:computeSchematicNetLabelCenter({anchor_position:schPort.center,anchor_side,text}),anchor_side})}continue}if(db2.schematic_net_label.list().some(nl3=>{if(nl3.schematic_sheet_id!==portSchematicSheetId)return!1;let dx22=nl3.anchor_position.x-schPort.center.x,dy22=nl3.anchor_position.y-schPort.center.y;return dx22*dx22+dy22*dy22>=SAME_ANCHOR_POSITION_DISTANCE*SAME_ANCHOR_POSITION_DISTANCE?!1:doesSchematicNetLabelRepresentCurrentSourceConnection({nl:nl3,connKey,sourceNet,text})}))continue}if(!sourceNet&&!shouldPreserveDirectConnectionEndpointLabels)for(let nl3 of db2.schematic_net_label.list()){if(nl3.source_net_id!==connKey||nl3.schematic_sheet_id!==portSchematicSheetId)continue;connectedSourcePortIdsForKey.some(sourcePortId=>{let schPortId=Array.from(schPortIdToSourcePortId.entries()).find(([,id3])=>id3===sourcePortId)?.[0],connectedSchPort;if(schPortId&&(connectedSchPort=db2.schematic_port.get(schPortId)),!connectedSchPort?.center||!nl3.anchor_position)return!1;let dx3=nl3.anchor_position.x-connectedSchPort.center.x,dy3=nl3.anchor_position.y-connectedSchPort.center.y;return dx3*dx3+dy3*dy3<SAME_ANCHOR_POSITION_DISTANCE*SAME_ANCHOR_POSITION_DISTANCE})||db2.schematic_net_label.delete(nl3.schematic_net_label_id)}let netLabel={text,source_net_id:sourceNet?.source_net_id??connKey,anchor_position:schPort.center,center:center2,anchor_side:side,schematic_sheet_id:portSchematicSheetId};db2.schematic_net_label.insert(netLabel)}},debug11=(0,import_debug16.default)("Group_doInitialSchematicTraceRender"),renderSchematicTracesForSheet=({group,schematicSheetId,netLabels})=>{let{inputProblem,connKeyToSourceNet,schematicPortIdsInScope,schematicPortIdsWithExternallyRoutedRepresentations,schPortIdToSourcePortId,userNetIdToConnKey,crossSubcircuitTraceLabelBySchematicPortId,sourceTraceIdByPortOnlyLabelSchematicPortId,connKeysWithExplicitPortNetTraces,netLabelsInScope,sourceTraceIdByPinPairKey}=createSchematicTraceSolverInputProblem(group,{schematicSheetId,netLabels});if(inputProblem.chips.length===0)return;let schematicPortIdsWithPreExistingNetLabels=getSchematicPortIdsWithAssignedNetLabels(netLabelsInScope);if(!(inputProblem.directConnections.length>0||inputProblem.netConnections.length>0)){insertNetLabelsForPortsMissingTrace({group,schematicPortIdsInScope,schematicPortIdsWithExternallyRoutedRepresentations,schPortIdToSourcePortId,connKeyToSourceNet});return}debug11.enabled&&group.root?.emit("debug:logOutput",{type:"debug:logOutput",name:"group-trace-render-input-problem",content:JSON.stringify(inputProblem,null,2)});let solver=new SchematicTracePipelineSolver(inputProblem),solverConstructorArgs=solver.getConstructorParams();group.root?.emit("solver:started",{type:"solver:started",solverName:"SchematicTracePipelineSolver",solverParams:solverConstructorArgs[0],solverConstructorArgs,componentName:group.getString()}),solver.solve();let schematicPortIdsWithRoutedTraces=getSchematicPortIdsWithRoutedTraces({solver});applyTracesFromSolverOutput({group,solver,userNetIdToConnKey,schematicPortIdsWithPreExistingNetLabels}),applyNetLabelPlacements({group,solver,connKeyToSourceNet,userNetIdToConnKey,crossSubcircuitTraceLabelBySchematicPortId,sourceTraceIdByPortOnlyLabelSchematicPortId,connKeysWithExplicitPortNetTraces,schematicPortIdsWithPreExistingNetLabels,schematicPortIdsWithRoutedTraces,netLabels:netLabelsInScope}),applyInlineNetLabelPlacements({group,solver,userNetIdToConnKey,sourceTraceIdByPinPairKey}),insertNetLabelsForPortsMissingTrace({group,schematicPortIdsInScope,schematicPortIdsWithExternallyRoutedRepresentations,schPortIdToSourcePortId,connKeyToSourceNet})},Group_doInitialSchematicTraceRender=group=>{if(!group.root?._featureMspSchematicTraceRouting||!group.isSubcircuit||group.root?.schematicDisabled)return;let netLabels=new Set,board=group._getBoard(),schematicScope=group;for(;schematicScope;){if(schematicScope instanceof Group5)for(let netLabel of schematicScope.selectAll("netlabel"))netLabels.add(netLabel);if(schematicScope===board)break;schematicScope=schematicScope.parent}let netLabelComponents=[...netLabels],schematicGroupIds=new Set([group,...group.getDescendants().filter(component=>component instanceof Group5)].map(schematicGroup=>schematicGroup.schematic_group_id).filter(schematicGroupId=>!!schematicGroupId)),schematicSheetIds=new Set(group.root.db.schematic_component.list().filter(schematicComponent=>schematicGroupIds.has(schematicComponent.schematic_group_id)).map(schematicComponent=>schematicComponent.schematic_sheet_id).filter(schematicSheetId=>!!schematicSheetId));if(schematicSheetIds.size===0){renderSchematicTracesForSheet({group,netLabels:netLabelComponents});return}for(let schematicSheetId of schematicSheetIds)renderSchematicTracesForSheet({group,schematicSheetId,netLabels:netLabelComponents})};function getTransientVoltageGraphNamesFromSpiceNetlist(spiceNetlist){let graphNames=[];for(let printStatement of spiceNetlist.printStatements){let match2=printStatement.match(/^\.PRINT\s+TRAN\s+(.+)$/i);if(match2)for(let voltageExpression of match2[1].match(/V\(([^)]+)\)/g)??[]){let nodeList=voltageExpression.slice(2,-1);graphNames.push(nodeList.replace(",","-"))}}return graphNames}var SIMULATION_COLOR_PALETTE=["rgb(0, 150, 0)","rgb(0, 0, 220)","rgb(220, 0, 0)","rgb(0, 160, 160)","rgb(180, 0, 180)","rgb(170, 140, 0)","rgb(220, 120, 0)","rgb(128, 128, 128)","rgb(100, 0, 180)","rgb(140, 70, 0)","rgb(220, 80, 120)","rgb(0, 120, 220)","rgb(0, 120, 120)","rgb(120, 0, 0)","rgb(0, 0, 132)","rgb(80, 80, 80)"],idToColorMap=new Map,colorIndex=0;function getSimulationColorForId(id3){if(idToColorMap.has(id3))return idToColorMap.get(id3);let color=SIMULATION_COLOR_PALETTE[colorIndex];return colorIndex=(colorIndex+1)%SIMULATION_COLOR_PALETTE.length,idToColorMap.set(id3,color),color}function resetSimulationColorState(){idToColorMap.clear(),colorIndex=0}var getSpiceyEngine=()=>({async simulate(spiceString){let simulation_experiment_id="spice-experiment-1",{circuit:parsedCircuit,tran}=simulate(spiceString);return{simulationResultCircuitJson:spiceyTranToVGraphs(tran,parsedCircuit,simulation_experiment_id)}}}),isCurrentGraph2=element=>element.type==="simulation_transient_current_graph",isSimulationCurrentResult=circuitElement=>circuitElement.type==="simulation_dc_operating_point_current"||circuitElement.type==="simulation_dc_sweep_current_graph"||circuitElement.type==="simulation_ac_sweep_current_graph",isSimulationVoltageResult=circuitElement=>circuitElement.type==="simulation_dc_operating_point_voltage"||circuitElement.type==="simulation_dc_sweep_voltage_graph"||circuitElement.type==="simulation_ac_sweep_voltage_graph",isVoltageGraph=element=>element.type==="simulation_transient_voltage_graph",isSimulationAnalysisResult2=circuitElement=>isVoltageGraph(circuitElement)||isCurrentGraph2(circuitElement)||isSimulationVoltageResult(circuitElement)||isSimulationCurrentResult(circuitElement),attachSweepCoordinateToSimulationResult=({simulationResult,simulationParameterSweepCoordinate})=>{if(!simulationParameterSweepCoordinate||!isSimulationAnalysisResult2(simulationResult))return simulationResult;let simulationResultWithSweepCoordinate={...simulationResult},simulationResultIdKey=`${simulationResultWithSweepCoordinate.type}_id`;return Reflect.deleteProperty(simulationResultWithSweepCoordinate,simulationResultIdKey),simulationResultWithSweepCoordinate.simulation_parameter_sweep_coordinate=simulationParameterSweepCoordinate,simulationResultWithSweepCoordinate},getSourceComponentOrThrow=({circuitJson,sourceComponentId,isMatchingSourceComponent})=>{let sourceComponent=circuitJson.find(circuitElement=>isMatchingSourceComponent(circuitElement)&&circuitElement.source_component_id===sourceComponentId);if(!sourceComponent)throw new Error(`Parameter sweep target ${sourceComponentId} was not found`);return sourceComponent},applyParameterSweepCoordinate=({circuitJson,parameterSweep,simulationParameterSweepCoordinate})=>{let sweptCircuitJson=structuredClone(circuitJson),parameterValue=simulationParameterSweepCoordinate.parameter_value;if(parameterSweep.parameter_type==="resistance"){let resistor=getSourceComponentOrThrow({circuitJson:sweptCircuitJson,sourceComponentId:parameterSweep.resistor_source_component_id,isMatchingSourceComponent:circuitElement=>circuitElement.type==="source_component"&&circuitElement.ftype==="simple_resistor"});return resistor.resistance=parameterValue,sweptCircuitJson}if(parameterSweep.parameter_type==="capacitance"){let capacitor=getSourceComponentOrThrow({circuitJson:sweptCircuitJson,sourceComponentId:parameterSweep.capacitor_source_component_id,isMatchingSourceComponent:circuitElement=>circuitElement.type==="source_component"&&circuitElement.ftype==="simple_capacitor"});return capacitor.capacitance=parameterValue,sweptCircuitJson}if(parameterSweep.parameter_type==="inductance"){let inductor=getSourceComponentOrThrow({circuitJson:sweptCircuitJson,sourceComponentId:parameterSweep.inductor_source_component_id,isMatchingSourceComponent:circuitElement=>circuitElement.type==="source_component"&&circuitElement.ftype==="simple_inductor"});return inductor.inductance=parameterValue,sweptCircuitJson}if(parameterSweep.parameter_type==="voltage"){let groundNet=sweptCircuitJson.find(circuitElement=>circuitElement.type==="source_net"&&circuitElement.name.toUpperCase()==="GND");if(!groundNet||groundNet.type!=="source_net")throw new Error("A voltage parameter sweep requires a GND net");let sweepVoltageSource={type:"simulation_voltage_source",simulation_voltage_source_id:`simulation_voltage_source_${simulationParameterSweepCoordinate.simulation_parameter_sweep_id}_${simulationParameterSweepCoordinate.sweep_index}`,is_dc_source:!0,positive_source_net_id:parameterSweep.source_net_id,negative_source_net_id:groundNet.source_net_id,voltage:parameterValue};return sweptCircuitJson.push(sweepVoltageSource),sweptCircuitJson}if(parameterSweep.parameter_type==="current"){let currentSourcePortIds=new Set(sweptCircuitJson.filter(circuitElement=>circuitElement.type==="source_port"&&circuitElement.source_component_id===parameterSweep.current_source_component_id).map(sourcePort=>sourcePort.source_port_id)),currentSource=sweptCircuitJson.find(circuitElement=>circuitElement.type==="simulation_current_source"&&(circuitElement.is_dc_source?!!(circuitElement.positive_source_port_id&&currentSourcePortIds.has(circuitElement.positive_source_port_id)):!!(circuitElement.terminal1_source_port_id&&currentSourcePortIds.has(circuitElement.terminal1_source_port_id))));if(!currentSource)throw new Error(`Current sweep target ${parameterSweep.current_source_component_id} has no simulation source`);return currentSource.current=parameterValue,sweptCircuitJson}throw new Error("Parameter sweep target is incomplete")},createSimulationRun=({circuitJson,simulationParameterSweepCoordinate})=>{let spiceNetlist=circuitJsonToSpice(circuitJson);return{spiceNetlist,spiceString:spiceNetlist.toSpiceString(),simulationParameterSweepCoordinate}},createSimulationRuns=({circuitJson,simulationExperimentId})=>{let parameterSweep=circuitJson.find(circuitElement=>circuitElement.type==="simulation_parameter_sweep"&&circuitElement.simulation_experiment_id===simulationExperimentId);return parameterSweep?parameterSweep.parameter_values.map((parameterValue,sweepIndex)=>{let simulationParameterSweepCoordinate={simulation_parameter_sweep_id:parameterSweep.simulation_parameter_sweep_id,sweep_index:sweepIndex,parameter_value:parameterValue,parameter_unit:parameterSweep.parameter_unit};return createSimulationRun({circuitJson:applyParameterSweepCoordinate({circuitJson,parameterSweep,simulationParameterSweepCoordinate}),simulationParameterSweepCoordinate})}):[createSimulationRun({circuitJson})]},SI_PREFIX_MULTIPLIERS={p:1e-12,n:1e-9,u:1e-6,\u00B5:1e-6,m:.001,"":1,k:1e3,K:1e3,M:1e6,G:1e9},parseSimulationGraphValue=value=>{if(value===void 0)return;if(typeof value=="number")return value;let match2=value.trim().match(/^([+-]?(?:\d+(?:\.\d*)?|\.\d+))\s*([pnumµkKMG]?)/);if(!match2)return;let numericValue=Number(match2[1]);if(Number.isFinite(numericValue))return numericValue*(SI_PREFIX_MULTIPLIERS[match2[2]??""]??1)},getVoltageProbeGraphDisplayOverrides=probe=>{let{graphDisplayName,graphCenter,graphVerticalOffset,graphVoltagePerDiv}=probe._parsedProps;return{displayName:graphDisplayName,color:probe.color??void 0,center:graphCenter,verticalOffset:parseSimulationGraphValue(graphVerticalOffset),valuePerDiv:parseSimulationGraphValue(graphVoltagePerDiv)}},getAmmeterGraphDisplayOverrides=ammeter=>{let{color,graphDisplayName,graphCenter,graphVerticalOffset,graphCurrentPerDiv}=ammeter._parsedProps;return{displayName:graphDisplayName,color,center:graphCenter,verticalOffset:parseSimulationGraphValue(graphVerticalOffset),valuePerDiv:parseSimulationGraphValue(graphCurrentPerDiv)}},getFiniteBounds=values=>{let min=Number.POSITIVE_INFINITY,max2=Number.NEGATIVE_INFINITY;for(let value of values)Number.isFinite(value)&&(min=Math.min(min,value),max2=Math.max(max2,value));return min===Number.POSITIVE_INFINITY||max2===Number.NEGATIVE_INFINITY?null:{min,max:max2}},getGraphLevels2=graph=>graph.type==="simulation_transient_current_graph"?graph.current_levels:graph.voltage_levels,DISPLAY_SECTION_HEIGHT_DIVS=2,DISPLAY_SECTION_DATA_FILL=.8,getAutoDisplayScale=({graph,index,graphCount})=>{let bounds=getFiniteBounds(getGraphLevels2(graph));if(!bounds)return null;let center2=(bounds.min+bounds.max)/2,span=bounds.max-bounds.min,valuePerDiv=span>0?span/(DISPLAY_SECTION_HEIGHT_DIVS*DISPLAY_SECTION_DATA_FILL):Math.max(Math.abs(center2)/10,Number.EPSILON);return{display_center_value:center2,display_center_offset_divs:((graphCount-1)/2-index)*DISPLAY_SECTION_HEIGHT_DIVS,value_per_div:valuePerDiv}},isDefinedString=value=>value!==void 0,getTraceByVoltageProbeId=traces=>{let traceByVoltageProbeId=new Map;for(let trace of traces)trace.simulation_voltage_probe_id&&traceByVoltageProbeId.set(trace.simulation_voltage_probe_id,trace);return traceByVoltageProbeId},getTraceByCurrentProbeId=traces=>{let traceByCurrentProbeId=new Map;for(let trace of traces)trace.simulation_current_probe_id&&traceByCurrentProbeId.set(trace.simulation_current_probe_id,trace);return traceByCurrentProbeId},insertIndependentAxisScopeTraces=({db:db2,graphs,graphDisplayOverridesByProbeId})=>{if(graphs.length===0)return;let existingScopeTraces=db2.simulation_oscilloscope_trace.list(),traceByVoltageProbeId=getTraceByVoltageProbeId(existingScopeTraces),traceByCurrentProbeId=getTraceByCurrentProbeId(existingScopeTraces),graphIdsWithTrace=new Set(existingScopeTraces.flatMap(trace=>[trace.simulation_transient_voltage_graph_id,trace.simulation_transient_current_graph_id]).filter(isDefinedString));for(let[index,{type,graph}]of graphs.entries()){let scale22=getAutoDisplayScale({graph,index,graphCount:graphs.length});if(!scale22)continue;let graphId=type==="voltage"?graph.simulation_transient_voltage_graph_id:graph.simulation_transient_current_graph_id;if(graphIdsWithTrace.has(graphId))continue;let sourceProbeId=graph.source_probe_id??void 0,probeTrace=sourceProbeId===void 0?void 0:type==="voltage"?traceByVoltageProbeId.get(sourceProbeId):traceByCurrentProbeId.get(sourceProbeId),overrides=sourceProbeId===void 0?void 0:graphDisplayOverridesByProbeId?.get(sourceProbeId),valuePerDiv=overrides?.valuePerDiv??scale22.value_per_div,displayCenter=overrides?.center??scale22.display_center_value,displayCenterOffsetDivs=overrides?.verticalOffset!==void 0&&valuePerDiv!==0?overrides.verticalOffset/valuePerDiv:probeTrace?.display_center_offset_divs??scale22.display_center_offset_divs;db2.simulation_oscilloscope_trace.insert({...type==="voltage"?{simulation_transient_voltage_graph_id:graph.simulation_transient_voltage_graph_id,volts_per_div:valuePerDiv}:{simulation_transient_current_graph_id:graph.simulation_transient_current_graph_id,amps_per_div:valuePerDiv},display_name:overrides?.displayName??probeTrace?.display_name,color:overrides?.color??probeTrace?.color??graph.color,display_center_value:displayCenter,display_center_offset_divs:displayCenterOffsetDivs})}},isCircuitElementInput=element=>!!(element&&typeof element=="object"&&"type"in element),debug12=(0,import_debug20.default)("tscircuit:core:Group_doInitialSimulationSpiceEngineRender"),getCircuitJsonForAnalogSimulation=({circuitJson,simulationExperimentId,voltageProbes,ammeters})=>{let voltageProbeIds=new Set(voltageProbes.map(voltageProbe=>voltageProbe.simulation_voltage_probe_id).filter(simulationVoltageProbeId=>!!simulationVoltageProbeId)),currentProbeIds=new Set(ammeters.map(ammeter=>ammeter.simulation_current_probe_id).filter(simulationCurrentProbeId=>!!simulationCurrentProbeId));return circuitJson.filter(element=>{if(element.type==="simulation_experiment")return element.simulation_experiment_id===simulationExperimentId;if(element.type==="simulation_voltage_probe")return voltageProbeIds.has(element.simulation_voltage_probe_id);if(element.type==="simulation_current_probe")return currentProbeIds.has(element.simulation_current_probe_id);if(element.type==="simulation_parameter_sweep")return element.simulation_experiment_id===simulationExperimentId;if(element.type==="simulation_oscilloscope_trace"){if(element.simulation_voltage_probe_id)return voltageProbeIds.has(element.simulation_voltage_probe_id);if(element.simulation_current_probe_id)return currentProbeIds.has(element.simulation_current_probe_id)}return!(element.type==="simulation_transient_voltage_graph"||element.type==="simulation_transient_current_graph"||element.type==="simulation_dc_operating_point_voltage"||element.type==="simulation_dc_operating_point_current"||element.type==="simulation_dc_sweep_voltage_graph"||element.type==="simulation_dc_sweep_current_graph"||element.type==="simulation_ac_sweep_voltage_graph"||element.type==="simulation_ac_sweep_current_graph"||element.type==="simulation_unknown_experiment_error")})};function Group_doInitialSimulationSpiceEngineRender(group){if(!group.isSubcircuit)return;let{root}=group;if(!root)return;let analogSimulations=[...group.selectAll("analogsimulation"),...group.selectAll("analogtransientsimulation"),...group.selectAll("analogdcoperatingpointsimulation"),...group.selectAll("analogdcsweepsimulation"),...group.selectAll("analogacsweepsimulation")];if(analogSimulations.length===0)return;resetSimulationColorState();let spiceEngineMap={...root.platform?.spiceEngineMap};spiceEngineMap.spicey||(spiceEngineMap.spicey=getSpiceyEngine());for(let analogSimulation of analogSimulations){let simulationExperimentId=analogSimulation.simulation_experiment_id;if(!simulationExperimentId){debug12("No simulation experiment id found, skipping simulation");continue}let simulationExperiment=root.db.simulation_experiment.get(simulationExperimentId);if(!simulationExperiment){debug12("No simulation experiment found, skipping simulation");continue}let simulationScope=analogSimulation.getGroup()??group,voltageProbes=simulationScope.selectAll("voltageprobe"),ammeters=simulationScope.selectAll("ammeter"),circuitJson=getCircuitJsonForAnalogSimulation({circuitJson:root.db.toArray(),simulationExperimentId,voltageProbes,ammeters}),simulationRuns;try{simulationRuns=createSimulationRuns({circuitJson,simulationExperimentId}),debug12(`Generated ${simulationRuns.length} SPICE run(s):
740
740
  ${simulationRuns.map(simulationRun=>simulationRun.spiceString).join(`
741
- `)}`)}catch(error2){debug12(`Failed to convert circuit JSON to SPICE: ${error2}`),root.db.simulation_unknown_experiment_error.insert({simulation_experiment_id:simulationExperimentId,error_type:"simulation_unknown_experiment_error",message:error2 instanceof Error?error2.message:String(error2)});continue}let voltageProbeByGraphName=new Map,voltageProbeById=new Map,graphDisplayOverridesByProbeId=new Map;for(let probe of voltageProbes)probe.finalProbeName&&voltageProbeByGraphName.set(probe.finalProbeName,probe),probe.simulation_voltage_probe_id&&(voltageProbeById.set(probe.simulation_voltage_probe_id,probe),graphDisplayOverridesByProbeId.set(probe.simulation_voltage_probe_id,getVoltageProbeGraphDisplayOverrides(probe)));for(let ammeter of ammeters)ammeter.simulation_current_probe_id&&graphDisplayOverridesByProbeId.set(ammeter.simulation_current_probe_id,getAmmeterGraphDisplayOverrides(ammeter));let scopedCurrentProbeIds=new Set(ammeters.map(ammeter=>ammeter.simulation_current_probe_id).filter(simulationCurrentProbeId=>!!simulationCurrentProbeId)),currentProbeById=new Map,currentProbeByName=new Map;for(let probe of root.db.simulation_current_probe.list().filter(probe2=>scopedCurrentProbeIds.has(probe2.simulation_current_probe_id)))currentProbeById.set(probe.simulation_current_probe_id,probe),probe.name!==void 0&&currentProbeByName.set(probe.name,probe);let orderedSimulationProbes=root.db.simulation_voltage_probe.list().filter(probe=>voltageProbeById.has(probe.simulation_voltage_probe_id)),firstSpiceNetlist=simulationRuns[0]?.spiceNetlist,graphNamesFromNetlist=firstSpiceNetlist?getTransientVoltageGraphNamesFromSpiceNetlist(firstSpiceNetlist):[];if(graphNamesFromNetlist.length===orderedSimulationProbes.length)for(let[simulationProbeIndex,simulationProbe]of orderedSimulationProbes.entries()){let probe=voltageProbeById.get(simulationProbe.simulation_voltage_probe_id),graphName=graphNamesFromNetlist[simulationProbeIndex];probe&&graphName&&voltageProbeByGraphName.set(graphName,probe)}else debug12(`Skipping probe-to-graph order mapping because counts differ: probes=${orderedSimulationProbes.length} graphNames=${graphNamesFromNetlist.length}`);let engineName=analogSimulation.getSpiceEngineName()??"spicey",spiceEngine2=spiceEngineMap[engineName];if(!spiceEngine2)throw new Error(`SPICE engine "${engineName}" not found in platform config. Available engines: ${JSON.stringify(Object.keys(spiceEngineMap).filter(spiceEngineName=>spiceEngineName!=="spicey"))}`);let effectId=`spice-simulation-${engineName}-${simulationExperimentId}`;debug12(`Queueing simulation for spice engine: ${engineName} (id: ${effectId})`),group._queueAsyncEffect(effectId,async()=>{try{let insertedVoltageGraphs=[],insertedCurrentGraphs=[];for(let simulationRun of simulationRuns){debug12(`Running simulation with engine: ${engineName}`);let simulationResult=await spiceEngine2.simulate(simulationRun.spiceString);debug12(`Simulation completed, received ${simulationResult.simulationResultCircuitJson.length} elements`);for(let simulationResultCircuitElement of simulationResult.simulationResultCircuitJson){if(!isCircuitElementInput(simulationResultCircuitElement)){debug12("Skipping invalid simulation result element");continue}let simulationResultWithSweepCoordinate=attachSweepCoordinateToSimulationResult({simulationResult:simulationResultCircuitElement,simulationParameterSweepCoordinate:simulationRun.simulationParameterSweepCoordinate});if(isVoltageGraph(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=simulationResultWithSweepCoordinate.name?voltageProbeByGraphName.get(simulationResultWithSweepCoordinate.name):void 0;probeMatch&&(simulationResultWithSweepCoordinate.color=probeMatch.color??void 0,simulationResultWithSweepCoordinate.source_probe_id=probeMatch.simulation_voltage_probe_id??void 0)}else if(isSimulationVoltageResult(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=voltageProbeById.get(simulationResultWithSweepCoordinate.simulation_voltage_probe_id)??(simulationResultWithSweepCoordinate.name?voltageProbeByGraphName.get(simulationResultWithSweepCoordinate.name):void 0);probeMatch?.simulation_voltage_probe_id&&(simulationResultWithSweepCoordinate.color=probeMatch.color??void 0,simulationResultWithSweepCoordinate.simulation_voltage_probe_id=probeMatch.simulation_voltage_probe_id)}if(isCurrentGraph2(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=(simulationResultWithSweepCoordinate.source_probe_id?currentProbeById.get(simulationResultWithSweepCoordinate.source_probe_id):void 0)??(simulationResultWithSweepCoordinate.name?currentProbeByName.get(simulationResultWithSweepCoordinate.name):void 0);probeMatch&&(simulationResultWithSweepCoordinate.color=probeMatch.color,simulationResultWithSweepCoordinate.source_probe_id=probeMatch.simulation_current_probe_id)}else if(isSimulationCurrentResult(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=currentProbeById.get(simulationResultWithSweepCoordinate.simulation_current_probe_id)??(simulationResultWithSweepCoordinate.name?currentProbeByName.get(simulationResultWithSweepCoordinate.name):void 0);probeMatch&&(simulationResultWithSweepCoordinate.color=probeMatch.color,simulationResultWithSweepCoordinate.simulation_current_probe_id=probeMatch.simulation_current_probe_id)}let insertedSimulationResult=root.db.insert(simulationResultWithSweepCoordinate);isVoltageGraph(insertedSimulationResult)&&insertedVoltageGraphs.push({type:"voltage",graph:insertedSimulationResult}),isCurrentGraph2(insertedSimulationResult)&&insertedCurrentGraphs.push({type:"current",graph:insertedSimulationResult}),debug12(`Inserted ${simulationResultWithSweepCoordinate.type} into database`)}}analogSimulation.usesIndependentGraphAxes()&&insertIndependentAxisScopeTraces({db:root.db,graphs:[...insertedVoltageGraphs,...insertedCurrentGraphs],graphDisplayOverridesByProbeId}),group._markDirty("SimulationSpiceEngineRender")}catch(error2){debug12(`Simulation failed for engine ${engineName}: ${error2}`),root.db.simulation_unknown_experiment_error.insert({simulation_experiment_id:simulationExperimentId,error_type:"simulation_unknown_experiment_error",message:error2 instanceof Error?error2.message:String(error2)})}})}}function Group_doInitialSourceAddConnectivityMapKey(group){if(!group.isSubcircuit)return;let{db:db2}=group.root,traces=group.selectAll("trace"),vias=group.selectAll("via"),nets=group.selectAll("net"),connMap=new ConnectivityMap({});connMap.addConnections(traces.map(t53=>{let source_trace3=db2.source_trace.get(t53.source_trace_id);return source_trace3?[source_trace3.source_trace_id,...source_trace3.connected_source_port_ids,...source_trace3.connected_source_net_ids]:null}).filter(c3=>c3!==null));let sourceNets=db2.source_net.list().filter(net=>net.subcircuit_id===group.subcircuit_id);for(let sourceNet of sourceNets)connMap.addConnections([[sourceNet.source_net_id]]);let{name:subcircuitName}=group._parsedProps;for(let trace of traces){if(!trace.source_trace_id)continue;let connNetId=connMap.getNetConnectedToId(trace.source_trace_id);connNetId&&(trace.subcircuit_connectivity_map_key=`${subcircuitName??`unnamedsubcircuit${group.subcircuit_id??group.source_group_id??group._renderId}`}_${connNetId}`,db2.source_trace.update(trace.source_trace_id,{subcircuit_connectivity_map_key:trace.subcircuit_connectivity_map_key}))}let allSourcePortIds=new Set;for(let trace of traces){if(!trace.source_trace_id)continue;let source_trace3=db2.source_trace.get(trace.source_trace_id);if(source_trace3)for(let id3 of source_trace3.connected_source_port_ids)allSourcePortIds.add(id3)}for(let portId of allSourcePortIds){let connNetId=connMap.getNetConnectedToId(portId);if(!connNetId)continue;let connectivityMapKey=`${subcircuitName??`unnamedsubcircuit${group.subcircuit_id??group.source_group_id??group._renderId}`}_${connNetId}`;db2.source_port.update(portId,{subcircuit_connectivity_map_key:connectivityMapKey})}let allSourceNetIds=new Set;for(let trace of traces){if(!trace.source_trace_id)continue;let source_trace3=db2.source_trace.get(trace.source_trace_id);if(source_trace3)for(let source_net_id of source_trace3.connected_source_net_ids)allSourceNetIds.add(source_net_id)}for(let sourceNet of sourceNets)allSourceNetIds.add(sourceNet.source_net_id);for(let netId of allSourceNetIds){let connNetId=connMap.getNetConnectedToId(netId);if(!connNetId)continue;let connectivityMapKey=`${subcircuitName??`unnamedsubcircuit${group.subcircuit_id??group.source_group_id??group._renderId}`}_${connNetId}`;db2.source_net.update(netId,{subcircuit_connectivity_map_key:connectivityMapKey});let netInstance=nets.find(n3=>n3.source_net_id===netId);netInstance&&(netInstance.subcircuit_connectivity_map_key=connectivityMapKey)}for(let via of vias){let connectedNetOrTrace=via._getConnectedNetOrTrace();connectedNetOrTrace&&connectedNetOrTrace.subcircuit_connectivity_map_key&&(via.subcircuit_connectivity_map_key=connectedNetOrTrace.subcircuit_connectivity_map_key)}}var Group_doInitialStandaloneSubcircuitPcbDesignRuleChecks=group=>{let isRootSubcircuit=group.root?.firstChild===group;if(!group.isSubcircuit||!isRootSubcircuit||group._getBoard())return;let routingDisabled=group.root?.pcbRoutingDisabled||group.getInheritedProperty("routingDisabled"),drcChecksDisabled=group.root?.platform?.drcChecksDisabled??group.getInheritedProperty("drcChecksDisabled"),routingDrcChecksDisabled=group.root?.platform?.routingDrcChecksDisabled??group.getInheritedProperty("routingDrcChecksDisabled");if(group.root?.pcbDisabled||routingDisabled||drcChecksDisabled||routingDrcChecksDisabled||group._hasIncompleteAsyncEffectsInSubtreeForPhase("PcbTraceRender")||group._hasTracesToRoute()&&!group._areChildSubcircuitsRouted()||group._standaloneSubcircuitDrcChecksComplete||group._standaloneSubcircuitDrcChecksInProgress)return;let{db:db2}=group.root,subcircuitCircuitJson=db2.subtree({subcircuit_id:group.subcircuit_id}).toArray();group._standaloneSubcircuitDrcChecksInProgress=!0,group._queueAsyncEffect("standalone-subcircuit:routing-drc-checks",async()=>{try{let results=await runAllRoutingChecks(subcircuitCircuitJson);db2.insertAll(dedupePcbDrcErrors(results)),group._standaloneSubcircuitDrcChecksComplete=!0}finally{group._standaloneSubcircuitDrcChecksInProgress=!1}})},addPourNetMap=(target,pourNetMap)=>{for(let[layer,netOrNets]of Object.entries(pourNetMap)){if(!netOrNets)continue;let nets=Array.isArray(netOrNets)?netOrNets:[netOrNets],layerNets=target.get(layer)??new Set;for(let net of nets)layerNets.add(net);target.set(layer,layerNets)}},toFanoutPourNetMap=netsByLayer=>Object.fromEntries(Array.from(netsByLayer,([layer,nets])=>[layer,nets.size===1?Array.from(nets)[0]:Array.from(nets)])),Group_getFanoutPourNetMap=(group,routingPhasePlans)=>{let explicitMaps=routingPhasePlans.map(plan=>plan.fanoutPourNetMap).filter(map=>map!==void 0),netsByLayer=new Map;if(explicitMaps.length>0){for(let explicitMap of explicitMaps)addPourNetMap(netsByLayer,explicitMap);return toFanoutPourNetMap(netsByLayer)}let scope=group;for(;scope;){if(scope.isSubcircuit){let subcircuit=scope,copperPours=subcircuit.selectAll("copperpour");for(let copperPour of copperPours){if(copperPour.getSubcircuit()!==subcircuit)continue;let{layer,connectsTo}=copperPour._parsedProps;addPourNetMap(netsByLayer,{[layer]:connectsTo})}}scope=scope.parent}return netsByLayer.size>0?toFanoutPourNetMap(netsByLayer):void 0},baseBreakoutPointProps=pcbLayoutProps.omit({pcbRotation:!0,layer:!0}),BaseBreakoutPoint=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_breakout_point_id",null);__publicField(this,"matchedPort",null);__publicField(this,"matchedNet",null);__publicField(this,"matchedSourceTraceId",null);__publicField(this,"isPcbPrimitive",!0)}_getSourceTraceIdForPort(port){let{db:db2}=this.root;return db2.source_trace.list().find(st3=>st3.connected_source_port_ids.includes(port.source_port_id))?.source_trace_id}_getSourceNetIdForPort(port){let{db:db2}=this.root;return db2.source_trace.list().find(st3=>st3.connected_source_port_ids.includes(port.source_port_id))?.connected_source_net_ids[0]}_renderPcbBreakoutPoint({layer}={}){if(this.pcb_breakout_point_id||this.root?.pcbDisabled)return;let{db:db2}=this.root,position4=this._getGlobalPcbPositionBeforeLayout(),group=this.parent?.getGroup(),subcircuit=this.getSubcircuit();if(!group||!group.pcb_group_id)return;let pcb_breakout_point3=db2.pcb_breakout_point.insert({pcb_group_id:group.pcb_group_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,source_port_id:this.matchedPort?.source_port_id??void 0,source_trace_id:this.matchedPort?this.matchedSourceTraceId??this._getSourceTraceIdForPort(this.matchedPort):void 0,source_net_id:this.matchedNet?this.matchedNet.source_net_id:this.matchedPort?this._getSourceNetIdForPort(this.matchedPort):void 0,layer,x:position4.x,y:position4.y});this.pcb_breakout_point_id=pcb_breakout_point3.pcb_breakout_point_id}_getPcbCircuitJsonBounds(){let position4=this._getGlobalPcbPositionBeforeLayout();return{center:{x:position4.x,y:position4.y},bounds:{left:position4.x,top:position4.y,right:position4.x,bottom:position4.y},width:0,height:0}}_setPositionFromLayout(newCenter){let{db:db2}=this.root;if(!this.pcb_breakout_point_id)return;let updatedProperties={x:newCenter.x,y:newCenter.y};this.matchedSourceTraceId&&(updatedProperties.source_trace_id=this.matchedSourceTraceId),db2.pcb_breakout_point.update(this.pcb_breakout_point_id,updatedProperties)}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db:db2}=this.root;if(!this.pcb_breakout_point_id)return;let point6=db2.pcb_breakout_point.get(this.pcb_breakout_point_id);point6&&db2.pcb_breakout_point.update(this.pcb_breakout_point_id,{x:point6.x+deltaX,y:point6.y+deltaY})}getPcbSize(){return{width:0,height:0}}},BreakoutPoint=class extends BaseBreakoutPoint{get config(){return{componentName:"BreakoutPoint",zodProps:breakoutPointProps}}_matchConnection(){if(this.matchedPort)return;let{connection}=this._parsedProps,subcircuit=this.getSubcircuit();subcircuit&&(this.matchedPort=subcircuit.selectOne(connection,{type:"port"}),this.matchedPort||(this.matchedNet=subcircuit.selectOne(connection,{type:"net"})),!this.matchedPort&&!this.matchedNet&&this.renderError(`Could not find connection target "${connection}"`))}doInitialPcbPrimitiveRender(){this._matchConnection(),this._renderPcbBreakoutPoint()}};function getPhaseSortValue(routingPhaseIndex){return routingPhaseIndex===null?Number.POSITIVE_INFINITY:routingPhaseIndex}function compareRoutingPhasePlans(a6,b6){return getPhaseSortValue(a6.routingPhaseIndex)-getPhaseSortValue(b6.routingPhaseIndex)}function getOrCreateRoutingPhasePlan(plansByPhaseIndex,routingPhaseIndex){let plan=plansByPhaseIndex.get(routingPhaseIndex);return plan||(plan={routingPhaseIndex,nets:[],traces:[]},plansByPhaseIndex.set(routingPhaseIndex,plan)),plan}function getNetRoutingPhaseIndex(net){return net.props.routingPhaseIndex??null}function getTraceRoutingPhaseIndex(trace,buses=[]){let busRoutingPhaseIndexes=new Set;for(let bus of buses){if(bus._parsedProps.routingPhaseIndex===void 0)continue;bus._parsedProps.connections.some(connection=>connection===trace.name||traceHasEndpointMatchingConnectionSelector(trace,convertPortSelectorToEndpointKey(connection)))&&busRoutingPhaseIndexes.add(bus._parsedProps.routingPhaseIndex)}if(busRoutingPhaseIndexes.size>1)throw new Error(`Trace "${trace.name}" belongs to buses with different routing phases`);let busRoutingPhaseIndex=busRoutingPhaseIndexes.values().next().value;if(busRoutingPhaseIndex!==void 0)return busRoutingPhaseIndex;let traceRoutingPhaseIndex=trace.props.routingPhaseIndex;if(traceRoutingPhaseIndex!==void 0)return traceRoutingPhaseIndex;let routingPhaseIndex=null,connectedNets=trace._findConnectedNets().nets;for(let net of connectedNets){let netRoutingPhaseIndex=getNetRoutingPhaseIndex(net);typeof netRoutingPhaseIndex=="number"&&(routingPhaseIndex===null||netRoutingPhaseIndex<routingPhaseIndex)&&(routingPhaseIndex=netRoutingPhaseIndex)}return routingPhaseIndex}function convertPortSelectorToEndpointKey(selector){return selector.trim().replace(/\s*>\s*/g,".").replace(/\s+/g,".").replace(/^\./,"").replace(/\.\./g,".")}function getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps){return[...phaseProps.connection?[phaseProps.connection]:[],...phaseProps.connections??[]]}function traceHasEndpointMatchingConnectionSelector(trace,connectionSelectorEndpointKey){return trace.getTracePortPathSelectors().some(selector=>convertPortSelectorToEndpointKey(selector)===connectionSelectorEndpointKey)}function getAutoroutersByPhaseIndex(group){let autoroutingPhases=group.selectAll("autoroutingphase"),autoroutersByPhaseIndex=new Map;for(let autoroutingPhase of autoroutingPhases){let{phaseIndex,autorouter}=autoroutingPhase._parsedProps;autorouter!==void 0&&autoroutersByPhaseIndex.set(phaseIndex??null,autorouter)}return autoroutersByPhaseIndex}function getAutoroutingPhasePropsByPhaseIndex(group){let autoroutingPhases=group.selectAll("autoroutingphase"),propsByPhaseIndex=new Map;for(let autoroutingPhase of autoroutingPhases){let props=autoroutingPhase._parsedProps;propsByPhaseIndex.set(props.phaseIndex??null,props)}return propsByPhaseIndex}function toParsedDistance(value){if(value!==void 0)return Number(value)}function getDrcTolerancesFromAutoroutingPhaseProps(phaseProps){let{minTraceWidth,minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance,minTraceToPadEdgeClearance,minPadEdgeToPadEdgeClearance,minBoardEdgeClearance,minViaEdgeToPadEdgeClearance,minViaHoleDiameter,minViaPadDiameter}=phaseProps;if(!(minTraceWidth===void 0&&minViaHoleEdgeToViaHoleEdgeClearance===void 0&&minPlatedHoleDrillEdgeToDrillEdgeClearance===void 0&&minTraceToPadEdgeClearance===void 0&&minPadEdgeToPadEdgeClearance===void 0&&minBoardEdgeClearance===void 0&&minViaEdgeToPadEdgeClearance===void 0&&minViaHoleDiameter===void 0&&minViaPadDiameter===void 0))return{minTraceWidth:toParsedDistance(minTraceWidth),minViaHoleEdgeToViaHoleEdgeClearance:toParsedDistance(minViaHoleEdgeToViaHoleEdgeClearance),minPlatedHoleDrillEdgeToDrillEdgeClearance:toParsedDistance(minPlatedHoleDrillEdgeToDrillEdgeClearance),minTraceToPadEdgeClearance:toParsedDistance(minTraceToPadEdgeClearance),minPadEdgeToPadEdgeClearance:toParsedDistance(minPadEdgeToPadEdgeClearance),minBoardEdgeClearance:toParsedDistance(minBoardEdgeClearance),minViaEdgeToPadEdgeClearance:toParsedDistance(minViaEdgeToPadEdgeClearance),minViaHoleDiameter:toParsedDistance(minViaHoleDiameter),minViaPadDiameter:toParsedDistance(minViaPadDiameter)}}function Group_getRoutingPhasePlans(group){let traces=group.selectAll("trace"),nets=group.selectAll("net"),buses=group.selectAll("bus"),breakouts=group.selectAll("group").filter(candidate=>candidate.isRoutingDirective),breakoutByTrace=new Map,breakoutByNet=new Map;for(let trace of traces){let ancestor=trace.parent;for(;ancestor&&ancestor!==group;){if(ancestor.isRoutingDirective){breakoutByTrace.set(trace,ancestor);break}ancestor=ancestor.parent}}for(let net of nets)net.parent?.isRoutingDirective&&breakouts.includes(net.parent)&&breakoutByNet.set(net,net.parent);let plansByPhaseIndex=new Map,autoroutersByPhaseIndex=getAutoroutersByPhaseIndex(group),phasePropsByPhaseIndex=getAutoroutingPhasePropsByPhaseIndex(group),groupFanoutProps=group._parsedProps,hasDirectRoutingTargets=traces.length>0||nets.length>0,hasReroutePhase=Array.from(phasePropsByPhaseIndex.values()).some(phaseProps=>phaseProps.reroute),hasConnectionTargetedPhase=Array.from(phasePropsByPhaseIndex.values()).some(phaseProps=>getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps).length>0);if(!hasDirectRoutingTargets&&!hasReroutePhase&&!hasConnectionTargetedPhase&&breakouts.length===0)return[];for(let net of nets){if(breakoutByNet.has(net))continue;let routingPhaseIndex=getNetRoutingPhaseIndex(net);getOrCreateRoutingPhasePlan(plansByPhaseIndex,routingPhaseIndex).nets.push(net)}for(let trace of traces){if(breakoutByTrace.has(trace))continue;let routingPhaseIndex=getTraceRoutingPhaseIndex(trace,buses);getOrCreateRoutingPhasePlan(plansByPhaseIndex,routingPhaseIndex).traces.push(trace)}for(let[phaseIndex,phaseProps]of phasePropsByPhaseIndex){let connectionSelectors=getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps);if(connectionSelectors.length>0){let plan=getOrCreateRoutingPhasePlan(plansByPhaseIndex,phaseIndex),connectionSelectorEndpointKeys=connectionSelectors.map(convertPortSelectorToEndpointKey);plan.connectionSelectors=connectionSelectors;for(let trace of traces)if(!breakoutByTrace.has(trace)&&connectionSelectorEndpointKeys.some(endpointKey=>traceHasEndpointMatchingConnectionSelector(trace,endpointKey))){if(!phaseProps.reroute)for(let existingPlan of plansByPhaseIndex.values())existingPlan!==plan&&(existingPlan.traces=existingPlan.traces.filter(existingTrace=>existingTrace!==trace));if(plan.traces.includes(trace))continue;plan.traces.push(trace)}}phaseProps.reroute&&getOrCreateRoutingPhasePlan(plansByPhaseIndex,phaseIndex)}let plans=Array.from(plansByPhaseIndex.values()).sort(compareRoutingPhasePlans);for(let plan of plans){plan.autorouter=autoroutersByPhaseIndex.get(plan.routingPhaseIndex);let phaseProps=phasePropsByPhaseIndex.get(plan.routingPhaseIndex);plan.phaseName=phaseProps?.name,plan.reroute=phaseProps?.reroute,plan.region=phaseProps?.region,plan.connectionSelectors=phaseProps?getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps):void 0,plan.busFanoutDirections=phaseProps?.busFanoutDirections??groupFanoutProps.busFanoutDirections,plan.fanoutBoundaryPadding=phaseProps?.fanoutBoundaryPadding??groupFanoutProps.fanoutBoundaryPadding;let fanoutRoutingLayers=phaseProps?.fanoutRoutingLayers??groupFanoutProps.fanoutRoutingLayers;plan.fanoutRoutingLayers=fanoutRoutingLayers?.map(layer=>typeof layer=="string"?layer:layer.name),plan.fanoutPourNetMap=phaseProps?.fanoutPourNetMap??groupFanoutProps.fanoutPourNetMap,plan.drcTolerances=phaseProps?getDrcTolerancesFromAutoroutingPhaseProps(phaseProps):void 0}let breakoutPlans=[];for(let breakout of breakouts){let breakoutProps2=breakout._parsedProps,shouldUseDefaultAutorouterForBreakoutPoints=breakout.children.some(child=>child instanceof BreakoutPoint)&&breakout.props.autorouter===void 0,breakoutTraces=traces.filter(trace=>breakoutByTrace.get(trace)===breakout),unroutedBreakoutTraces=breakoutTraces.filter(trace=>!trace.pcb_trace_id),pcbGroup=breakout.pcb_group_id?breakout.root?.db.pcb_group.get(breakout.pcb_group_id):null,outlineBounds=pcbGroup?.outline?getBoundsFromPoints2(pcbGroup.outline):null,routingWidth=pcbGroup?.width??(outlineBounds?outlineBounds.maxX-outlineBounds.minX:void 0),routingHeight=pcbGroup?.height??(outlineBounds?outlineBounds.maxY-outlineBounds.minY:void 0),routingBounds=pcbGroup&&routingWidth&&routingHeight?{minX:pcbGroup.center.x-routingWidth/2,maxX:pcbGroup.center.x+routingWidth/2,minY:pcbGroup.center.y-routingHeight/2,maxY:pcbGroup.center.y+routingHeight/2}:void 0,rawBreakoutProps=breakout.props,hasExplicitGeometry=rawBreakoutProps.width!==void 0||rawBreakoutProps.height!==void 0||!!rawBreakoutProps.outline?.length,hasExplicitFanoutBoundaryPadding=rawBreakoutProps.fanoutBoundaryPadding!==void 0,breakoutPlan={routingPhaseIndex:null,routingPcbGroupId:breakout.pcb_group_id??void 0,fanoutRegionPcbGroupId:breakout.pcb_group_id??void 0,routingBounds,fanoutBounds:hasExplicitGeometry?routingBounds:hasExplicitFanoutBoundaryPadding?void 0:routingBounds,autorouter:breakoutProps2.autorouter??"fanout",busFanoutDirections:breakoutProps2.busFanoutDirections,fanoutBoundaryPadding:breakoutProps2.fanoutBoundaryPadding,fanoutRoutingLayers:breakoutProps2.fanoutRoutingLayers?.map(layer=>typeof layer=="string"?layer:layer.name),fanoutPourNetMap:breakoutProps2.fanoutPourNetMap,nets:nets.filter(net=>breakoutByNet.get(net)===breakout),traces:breakoutTraces};if(!shouldUseDefaultAutorouterForBreakoutPoints){breakoutPlans.push(breakoutPlan);continue}if(breakoutPlans.push({...breakoutPlan,autorouter:"default",traces:[]}),unroutedBreakoutTraces.length>0){let automaticFanoutBusIds=new Set(buses.filter(bus=>unroutedBreakoutTraces.some(trace=>bus._parsedProps.connections.some(connection=>connection===trace.name||traceHasEndpointMatchingConnectionSelector(trace,convertPortSelectorToEndpointKey(connection))))).map(bus=>bus.name));for(let trace of unroutedBreakoutTraces)trace.name&&automaticFanoutBusIds.add(trace.name);let automaticBusFanoutDirections=breakoutProps2.busFanoutDirections?Object.fromEntries(Object.entries(breakoutProps2.busFanoutDirections).filter(([busId])=>automaticFanoutBusIds.has(busId))):void 0;breakoutPlans.push({...breakoutPlan,routingPcbGroupId:void 0,busFanoutDirections:automaticBusFanoutDirections,traces:unroutedBreakoutTraces})}}let defaultPhaseProps=phasePropsByPhaseIndex.get(null);if(hasDirectRoutingTargets&&phasePropsByPhaseIndex.size===1&&defaultPhaseProps?.reroute&&plans.length===1&&plans[0]?.routingPhaseIndex===null){let reroutePlan=plans[0];return[...breakoutPlans,{routingPhaseIndex:null,nets:[...reroutePlan.nets],traces:[...reroutePlan.traces]},reroutePlan]}return[...breakoutPlans,...plans]}var package_default3={name:"@tscircuit/core",type:"module",version:"0.0.1760",types:"dist/index.d.ts",main:"dist/index.js",module:"dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},files:["dist"],repository:{type:"git",url:"https://github.com/tscircuit/core"},scripts:{build:"tsup-node",format:"biome format . --write","measure-bundle":"howfat -r table .","pkg-pr-new-release":"bunx pkg-pr-new publish --comment=off --peerDeps","smoke-test:dist":"bun run scripts/smoke-tests/test-dist-simple-circuit.tsx","build:benchmarking":"bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist","build:benchmarking:watch":`chokidar "./{benchmarking,lib}/**/*.{ts,tsx}" -c 'bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist'`,"start:benchmarking":'concurrently "bun run build:benchmarking:watch" "live-server ./benchmarking-dist"',"generate-test-plan":"bun run scripts/generate-test-plan.ts"},devDependencies:{"@biomejs/biome":"^1.8.3","@resvg/resvg-js":"^2.6.2","@tsci/tscircuit.ti":"github:tscircuit/ti#57e314be4b2b06bc546d4def7453e619604d1157","@tscircuit/alphabet":"0.0.25","@tscircuit/capacity-autorouter":"^0.0.840","@tscircuit/checks":"^0.0.171","@tscircuit/circuit-json-util":"^0.0.106","@tscircuit/common":"^0.0.20","@tscircuit/copper-pour-solver":"^0.0.49","@tscircuit/create-fdm-enclosure":"0.0.4","@tscircuit/fanout-solver":"0.0.37","@tscircuit/footprinter":"^0.0.426","@tscircuit/image-utils":"^0.0.8","@tscircuit/infer-cable-insertion-point":"^0.0.4","@tscircuit/infgrid-ijump-astar":"^0.0.35","@tscircuit/jlcpcb-manufacturing-specs":"git+https://github.com/tscircuit/jlcpcb-manufacturing-specs#e08af159db01a37db007e33f0a7268d0e4a279a5","@tscircuit/krt-wasm":"^0.1.1","@tscircuit/log-soup":"^1.0.2","@tscircuit/matchpack":"^0.0.84","@tscircuit/math-utils":"^0.0.36","@tscircuit/miniflex":"^0.0.4","@tscircuit/ngspice-spice-engine":"^0.0.20","@tscircuit/props":"^0.0.635","@tscircuit/schematic-match-adapt":"^0.0.18","@tscircuit/schematic-trace-solver":"^0.0.153","@tscircuit/solver-utils":"^0.0.16","@tscircuit/soup-util":"^0.0.41","@tscircuit/winding-breakout-point-solver":"github:tscircuit/winding-breakout-point-solver#202dbe9eb0088633b6fa094120dba6f2f41f8803","@types/bun":"^1.2.16","@types/debug":"^4.1.12","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@types/react-reconciler":"^0.28.9","bpc-graph":"^0.0.57","bun-match-svg":"0.0.12","calculate-elbow":"^0.0.12","chokidar-cli":"^3.0.0","circuit-json":"^0.0.475","circuit-json-to-bpc":"^0.0.13","circuit-json-to-connectivity-map":"^0.0.27","circuit-json-to-gltf":"^0.0.118","circuit-json-to-spice":"^0.0.45","circuit-to-svg":"^0.0.407",concurrently:"^9.1.2","connectivity-map":"^1.0.0",debug:"^4.3.6",flatbush:"^4.5.0","graphics-debug":"^0.0.95",howfat:"^0.3.8","kicad-to-circuit-json":"^0.0.117",kicadts:"^0.0.53","live-server":"^1.2.2",minicssgrid:"^0.0.9","pkg-pr-new":"^0.0.37",poppygl:"^0.0.27",react:"^19.1.0","react-dom":"^19.1.0","schematic-symbols":"^0.0.239",spicets:"^0.0.4",spicey:"^0.0.14","stack-svgs":"^0.0.1","ts-expect":"^1.3.0",tsup:"^8.2.4"},peerDependencies:{"@tscircuit/capacity-autorouter":"*","@tscircuit/checks":"*","@tscircuit/circuit-json-util":"*","@tscircuit/create-fdm-enclosure":"*","@tscircuit/footprinter":"*","@tscircuit/infgrid-ijump-astar":"*","@tscircuit/math-utils":"*","@tscircuit/props":"*","@tscircuit/schematic-match-adapt":"*","circuit-json-to-bpc":"*","bpc-graph":"*","@tscircuit/matchpack":"*","circuit-json":"*","circuit-json-to-connectivity-map":"*","circuit-json-to-spice":"*","schematic-symbols":"*",spicets:"*",typescript:"^5.0.0"},dependencies:{"@flatten-js/core":"^1.6.2","@lume/kiwi":"^0.4.3","calculate-cell-boundaries":"^0.0.19","calculate-packing":"^0.0.86","css-select":"5.1.0","format-si-unit":"^0.0.12",nanoid:"^5.0.7","performance-now":"^2.1.0","react-reconciler":"^0.32.0","svg-path-commander":"^2.1.11","transformation-matrix":"^2.16.1",zod:"^3.25.67"},overrides:{"@tscircuit/circuit-json-util":"^0.0.106","@tscircuit/props":"^0.0.635","circuit-json":"^0.0.475"}},getFnv1aHash=value=>{let hash=2166136261;for(let i6=0;i6<value.length;i6++)hash^=value.charCodeAt(i6),hash=Math.imul(hash,16777619);return hash>>>0},getSrjHash=simpleRouteJson=>{let serializedSrj=JSON.stringify(simpleRouteJson),hash1=getFnv1aHash(serializedSrj),hash2=getFnv1aHash(`${serializedSrj}${hash1}`);return`${hash1.toString(16).padStart(8,"0")}${hash2.toString(16).padStart(8,"0")}`},getLocalAutoroutingCacheKey=simpleRouteJson=>`routes:core@${package_default3.version}:srj:${getSrjHash(simpleRouteJson)}`,getCachedLocalAutoroutingPhaseResult=async({cacheEngine,cacheKey})=>{if(!cacheEngine)return null;try{let cachedResult=await cacheEngine.getItem(cacheKey);if(!cachedResult)return null;let parsedResult=JSON.parse(cachedResult);return!parsedResult||!Array.isArray(parsedResult.traces)?null:parsedResult}catch{return null}},cacheLocalAutoroutingPhaseResult=async({cacheEngine,cacheKey,result})=>{if(cacheEngine)try{await cacheEngine.setItem(cacheKey,JSON.stringify(result))}catch{}};function connectionIsInRoutingPhase(connection,phasePlan){if(connection.routingPcbGroupId)return connection.routingPcbGroupId===phasePlan.routingPcbGroupId;for(let trace of phasePlan.traces)if(trace.source_trace_id&&(connection.source_trace_id===trace.source_trace_id||connection.name===trace.source_trace_id||connection.rootConnectionName===trace.source_trace_id||connection.mergedConnectionNames?.includes(trace.source_trace_id)))return!0;for(let net of phasePlan.nets)if(net.source_net_id&&connection.name===net.source_net_id)return!0;return!1}function Group_hasPhasedAutorouting(routingPhasePlans){for(let plan of routingPhasePlans)if(plan.routingPcbGroupId||plan.routingPhaseIndex!==null)return!0;return!1}var pointsReferToSameEndpoint=(first,second)=>first.pointId&&second.pointId?first.pointId===second.pointId:Math.abs(first.x-second.x)<=1e-6&&Math.abs(first.y-second.y)<=1e-6,getPairedExitTarget=(simpleRouteJson,connection)=>{if(!connection.routingPcbGroupId||!connection.source_trace_id)return;let globalConnection=simpleRouteJson.connections.find(candidate=>candidate.routingPcbGroupId!==connection.routingPcbGroupId&&candidate.source_trace_id===connection.source_trace_id&&candidate.pointsToConnect.some(globalPoint=>connection.pointsToConnect.some(localPoint=>pointsReferToSameEndpoint(globalPoint,localPoint))));if(!globalConnection)return;let pairedPoints=globalConnection.pointsToConnect.filter(globalPoint=>!connection.pointsToConnect.some(localPoint=>pointsReferToSameEndpoint(globalPoint,localPoint)));return pairedPoints.length===1?{x:pairedPoints[0].x,y:pairedPoints[0].y,layer:pairedPoints[0].layer}:void 0};function Group_filterSimpleRouteJsonForPhase(simpleRouteJson,phasePlan){let connections=[];for(let connection of simpleRouteJson.connections)connectionIsInRoutingPhase(connection,phasePlan)&&connections.push(connection);let includedConnectionNames=new Set;for(let connection of connections)includedConnectionNames.add(connection.name);let differentialPairs=[];for(let differentialPair of simpleRouteJson.differentialPairs??[]){let positiveConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[0]),negativeConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[1]);if(positiveConnectionIncluded!==negativeConnectionIncluded)throw new Error(`Differential pair "${differentialPair.connectionNames.join("/")}" cannot be split across autorouting phases`);positiveConnectionIncluded&&differentialPairs.push(differentialPair)}let connectionByName=new Map(connections.map(connection=>[connection.name,connection])),buses=(simpleRouteJson.buses??[]).map(bus=>{let connectionNames=bus.connectionNames.filter(connectionName=>includedConnectionNames.has(connectionName)),connectionExitTargets=Object.fromEntries(connectionNames.flatMap(connectionName=>{let connection=connectionByName.get(connectionName);if(!connection)return[];let pairedTarget=getPairedExitTarget(simpleRouteJson,connection);return pairedTarget?[[connectionName,pairedTarget]]:[]}));return{...bus,connectionNames,...Object.keys(connectionExitTargets).length>0?{connectionExitTargets}:{}}}).filter(bus=>bus.connectionNames.length>0),bounds=expandSrjBoundsToIncludeConnectionPoints({bounds:phasePlan.routingBounds??simpleRouteJson.bounds,connections});return{...simpleRouteJson,bounds,connections,differentialPairs:differentialPairs.length>0?differentialPairs:void 0,buses:buses.length>0?buses:void 0}}function hasDrcTolerances(drcTolerances){return drcTolerances?Object.values(drcTolerances).some(value=>value!==void 0):!1}function applyMinTraceWidthToConnections(connections,minTraceWidth){return minTraceWidth===void 0?connections:connections.map(connection=>({...connection,nominalTraceWidth:Math.max(connection.nominalTraceWidth??minTraceWidth,minTraceWidth),width:Math.max(connection.width??minTraceWidth,minTraceWidth)}))}function Group_applyDrcTolerancesToSimpleRouteJson(simpleRouteJson,drcTolerances){if(!hasDrcTolerances(drcTolerances))return simpleRouteJson;let minTraceWidth=drcTolerances.minTraceWidth??simpleRouteJson.minTraceWidth,minViaHoleDiameter=drcTolerances.minViaHoleDiameter??simpleRouteJson.minViaHoleDiameter,minViaPadDiameter=drcTolerances.minViaPadDiameter??simpleRouteJson.minViaPadDiameter,minTraceToPadEdgeClearance=drcTolerances.minTraceToPadEdgeClearance??simpleRouteJson.minTraceToPadEdgeClearance,minViaEdgeToPadEdgeClearance=drcTolerances.minViaEdgeToPadEdgeClearance??simpleRouteJson.minViaEdgeToPadEdgeClearance,minViaHoleEdgeToViaHoleEdgeClearance=drcTolerances.minViaHoleEdgeToViaHoleEdgeClearance??simpleRouteJson.minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance=drcTolerances.minPlatedHoleDrillEdgeToDrillEdgeClearance??simpleRouteJson.minPlatedHoleDrillEdgeToDrillEdgeClearance,minPadEdgeToPadEdgeClearance=drcTolerances.minPadEdgeToPadEdgeClearance??simpleRouteJson.minPadEdgeToPadEdgeClearance,minBoardEdgeClearance=drcTolerances.minBoardEdgeClearance??simpleRouteJson.minBoardEdgeClearance;return{...simpleRouteJson,connections:applyMinTraceWidthToConnections(simpleRouteJson.connections,drcTolerances.minTraceWidth),minTraceWidth,minViaDiameter:minViaPadDiameter,minViaHoleDiameter,minViaPadDiameter,min_via_hole_diameter:minViaHoleDiameter,min_via_pad_diameter:minViaPadDiameter,minTraceToPadEdgeClearance,minViaEdgeToPadEdgeClearance,minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance,minPadEdgeToPadEdgeClearance,minBoardEdgeClearance}}var POINT_MATCH_TOLERANCE=1e-6,pointsMatch3=(first,second)=>Math.abs(first.x-second.x)<=POINT_MATCH_TOLERANCE&&Math.abs(first.y-second.y)<=POINT_MATCH_TOLERANCE&&first.layer===second.layer,removeCompletedFanoutConnections=(simpleRouteJson,routingPcbGroupId)=>{let connections=simpleRouteJson.connections.filter(connection=>connection.routingPcbGroupId!==routingPcbGroupId),includedConnectionNames=new Set(connections.map(connection=>connection.name)),differentialPairs=[];for(let differentialPair of simpleRouteJson.differentialPairs??[]){let positiveConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[0]),negativeConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[1]);if(positiveConnectionIncluded!==negativeConnectionIncluded)throw new Error(`Differential pair "${differentialPair.connectionNames.join("/")}" cannot be split at a breakout boundary`);positiveConnectionIncluded&&differentialPairs.push(differentialPair)}let buses=(simpleRouteJson.buses??[]).map(bus=>({...bus,connectionNames:bus.connectionNames.filter(connectionName=>includedConnectionNames.has(connectionName))})).filter(bus=>bus.connectionNames.length>0);return{...simpleRouteJson,connections,differentialPairs:differentialPairs.length>0?differentialPairs:void 0,buses:buses.length>0?buses:void 0}};function Group_syncFanoutExitsWithGlobalConnections({fanoutInputSimpleRouteJson,fanoutOutputSimpleRouteJson,baseSimpleRouteJson,routingPhasePlan}){let routingPcbGroupId=routingPhasePlan.routingPcbGroupId;if(!routingPcbGroupId)return{downstreamSimpleRouteJson:fanoutOutputSimpleRouteJson,baseSimpleRouteJson,synchronizedBreakoutPoints:[]};let outputConnectionByName=new Map(fanoutOutputSimpleRouteJson.connections.map(connection=>[connection.name,connection])),baseConnections=baseSimpleRouteJson.connections.map(connection=>({...connection,pointsToConnect:connection.pointsToConnect.map(point6=>({...point6}))})),synchronizedBreakoutPoints=[];for(let inputConnection of fanoutInputSimpleRouteJson.connections){if(inputConnection.routingPcbGroupId!==routingPcbGroupId||!inputConnection.source_trace_id)continue;let outputConnection=outputConnectionByName.get(inputConnection.name);if(!outputConnection)continue;let globalConnection=baseConnections.find(connection=>connection.routingPcbGroupId!==routingPcbGroupId&&connection.source_trace_id===inputConnection.source_trace_id&&connection.pointsToConnect.some(globalPoint=>inputConnection.pointsToConnect.some(inputPoint=>pointsMatch3(globalPoint,inputPoint))));if(!globalConnection)continue;let previousGlobalPointIndex=globalConnection.pointsToConnect.findIndex(globalPoint=>inputConnection.pointsToConnect.some(inputPoint=>pointsMatch3(globalPoint,inputPoint)));if(previousGlobalPointIndex<0)continue;let previousPoint=globalConnection.pointsToConnect[previousGlobalPointIndex],changedPointIndex=outputConnection.pointsToConnect.findIndex((outputPoint,pointIndex)=>{let inputPoint=inputConnection.pointsToConnect[pointIndex];return inputPoint!==void 0&&!pointsMatch3(outputPoint,inputPoint)});if(changedPointIndex<0)continue;let fanoutExitPoint=outputConnection.pointsToConnect[changedPointIndex],{layers:_previousLayers,terminalVia:_previousTerminalVia,...previousPointWithoutLayerOverrides}=previousPoint,synchronizedGlobalPoint={...previousPointWithoutLayerOverrides,x:fanoutExitPoint.x,y:fanoutExitPoint.y,layer:fanoutExitPoint.layer,...fanoutExitPoint.layers?{layers:[...fanoutExitPoint.layers]}:{},...fanoutExitPoint.terminalVia?{terminalVia:{...fanoutExitPoint.terminalVia}}:{}};globalConnection.pointsToConnect[previousGlobalPointIndex]=synchronizedGlobalPoint,synchronizedBreakoutPoints.push({sourceTraceId:inputConnection.source_trace_id,routingPcbGroupId,previousPoint,fanoutExitPoint})}let newFanoutSourceKeepouts=fanoutOutputSimpleRouteJson.obstacles.filter(obstacle=>obstacle.isFanoutSourceKeepout===!0&&obstacle.componentId!==void 0),completedSourceComponentIds=new Set(newFanoutSourceKeepouts.flatMap(obstacle=>obstacle.componentId===void 0?[]:[obstacle.componentId])),retainedBaseObstacles=baseSimpleRouteJson.obstacles.filter(obstacle=>!obstacle.componentId||!completedSourceComponentIds.has(obstacle.componentId));return{downstreamSimpleRouteJson:removeCompletedFanoutConnections(fanoutOutputSimpleRouteJson,routingPcbGroupId),baseSimpleRouteJson:{...baseSimpleRouteJson,connections:baseConnections,obstacles:[...retainedBaseObstacles,...newFanoutSourceKeepouts]},synchronizedBreakoutPoints}}function getJumperPadInfos(db2){let padInfos=[],jumperSmtpads=db2.pcb_smtpad.list().filter(pad2=>{let component=db2.pcb_component.get(pad2.pcb_component_id);return component?db2.source_component.get(component.source_component_id)?.name?.startsWith("__autoplaced_jumper"):!1});for(let smtpad2 of jumperSmtpads)if(smtpad2.shape!=="polygon"&&smtpad2.pcb_port_id){if(smtpad2.shape==="rect"||smtpad2.shape==="rotated_rect"){let halfWidth=smtpad2.width/2,halfHeight=smtpad2.height/2;padInfos.push({pcb_port_id:smtpad2.pcb_port_id,x:smtpad2.x,y:smtpad2.y,minX:smtpad2.x-halfWidth,maxX:smtpad2.x+halfWidth,minY:smtpad2.y-halfHeight,maxY:smtpad2.y+halfHeight})}else if(smtpad2.shape==="circle"){let radius=smtpad2.radius;padInfos.push({pcb_port_id:smtpad2.pcb_port_id,x:smtpad2.x,y:smtpad2.y,minX:smtpad2.x-radius,maxX:smtpad2.x+radius,minY:smtpad2.y-radius,maxY:smtpad2.y+radius})}}return padInfos}function findJumperPortAtPosition(padInfos,x6,y2,tolerance=.01){for(let pad2 of padInfos)if(Math.abs(pad2.x-x6)<tolerance&&Math.abs(pad2.y-y2)<tolerance)return pad2.pcb_port_id}function findJumperPortContainingPoint(padInfos,x6,y2){for(let pad2 of padInfos)if(x6>=pad2.minX&&x6<=pad2.maxX&&y2>=pad2.minY&&y2<=pad2.maxY)return pad2}function splitRouteAtJumperPads(route,padInfos){if(route.length===0||padInfos.length===0)return[route];let segments=[],currentSegment=[];for(let i6=0;i6<route.length;i6++){let point6=route[i6];if(currentSegment.push(point6),point6.route_type==="wire"&&i6>0&&i6<route.length-1){let padInfo=findJumperPortContainingPoint(padInfos,point6.x,point6.y);if(padInfo){point6.end_pcb_port_id||(point6.end_pcb_port_id=padInfo.pcb_port_id),segments.push(currentSegment);let newStartPoint={...point6};delete newStartPoint.end_pcb_port_id,newStartPoint.start_pcb_port_id||(newStartPoint.start_pcb_port_id=padInfo.pcb_port_id),currentSegment=[newStartPoint]}}}return currentSegment.length>0&&segments.push(currentSegment),segments}function addPortIdsToTracesAtJumperPads(segments,db2){let padInfos=getJumperPadInfos(db2);if(padInfos.length===0)return segments;let result=[];for(let segment2 of segments){let subSegments=splitRouteAtJumperPads(segment2,padInfos);for(let subSegment of subSegments)if(subSegment.length>0){let firstPoint=subSegment[0],lastPoint=subSegment[subSegment.length-1];if(firstPoint.route_type==="wire"&&!firstPoint.start_pcb_port_id){let portId=findJumperPortAtPosition(padInfos,firstPoint.x,firstPoint.y);portId&&(firstPoint.start_pcb_port_id=portId)}if(lastPoint.route_type==="wire"&&!lastPoint.end_pcb_port_id){let portId=findJumperPortAtPosition(padInfos,lastPoint.x,lastPoint.y);portId&&(lastPoint.end_pcb_port_id=portId)}result.push(subSegment)}}return result}var claimSrjAssignablePcbViasTraversedByRoute=({db:db2,pcbTrace,routeWithSrjMetadata})=>{for(let routePoint of routeWithSrjMetadata){if(routePoint.route_type!=="through_pad")continue;let pcbViaId=routePoint.circuitJsonMetadata?.pcb_via_id;if(!pcbViaId)continue;let assignablePcbVia=db2.pcb_via.get(pcbViaId);!assignablePcbVia?.net_is_assignable||assignablePcbVia.net_assigned&&assignablePcbVia.pcb_trace_id!==pcbTrace.pcb_trace_id||db2.pcb_via.update(assignablePcbVia.pcb_via_id,{pcb_trace_id:pcbTrace.pcb_trace_id,net_assigned:!0})}},getAxisGap=(firstMinimum,firstMaximum,secondMinimum,secondMaximum)=>Math.max(secondMinimum-firstMaximum,firstMinimum-secondMaximum),findFanoutPhaseSeparationConflict=regions=>{for(let firstIndex=0;firstIndex<regions.length;firstIndex++){let firstRegion=regions[firstIndex];for(let secondIndex=firstIndex+1;secondIndex<regions.length;secondIndex++){let secondRegion=regions[secondIndex];if(firstRegion.regionId&&firstRegion.regionId===secondRegion.regionId)continue;let horizontalGap=getAxisGap(firstRegion.bounds.minX,firstRegion.bounds.maxX,secondRegion.bounds.minX,secondRegion.bounds.maxX),verticalGap=getAxisGap(firstRegion.bounds.minY,firstRegion.bounds.maxY,secondRegion.bounds.minY,secondRegion.bounds.maxY),availableGap=Math.max(horizontalGap,verticalGap),requiredGap=firstRegion.boundaryKeepaway+secondRegion.boundaryKeepaway;if(availableGap+1e-6<requiredGap)return{firstRegion,secondRegion,availableGap,requiredGap}}}};function getAccumulatedPcbTracesWithStageOutputReplacements({accumulatedPcbTraces,stageOutputPcbTraces}){let stageOutputPcbTraceIds=new Set(stageOutputPcbTraces.map(trace=>trace.pcb_trace_id));return[...accumulatedPcbTraces.filter(trace=>!stageOutputPcbTraceIds.has(trace.pcb_trace_id)),...stageOutputPcbTraces]}var POINT_EPSILON2=1e-6;function isPointOnWireSegment({point:point6,segmentStart,segmentEnd}){return point6.layer&&(segmentStart.layer!==point6.layer||segmentEnd.layer!==point6.layer)?!1:pointToSegmentDistance(point6,segmentStart,segmentEnd)<=POINT_EPSILON2}function isPointInSmtPad({point:point6,pad:pad2,traceWidth=0}){return pad2.shape==="rect"||pad2.shape==="rotated_rect"?Math.abs(point6.x-pad2.x)<=pad2.width/2+traceWidth/2&&Math.abs(point6.y-pad2.y)<=pad2.height/2+traceWidth/2:pad2.shape==="circle"?distance2(point6,pad2)<=pad2.radius+traceWidth/2:!1}function isPointInPlatedHole({point:point6,hole,traceWidth=0}){return distance2(point6,hole)<=(hole.outer_diameter??hole.hole_diameter??0)/2+traceWidth/2}function getEndpointSourcePortIdsFromGeometry(db2,trace){let sourcePortIds=new Set,route=trace.route,endpoints=[route[0],route[route.length-1]].filter(point6=>!!point6&&point6.route_type==="wire"&&point6.x!==void 0&&point6.y!==void 0);for(let endpoint of endpoints){for(let pcbPort of db2.pcb_port.list())pcbPort.source_port_id&&(endpoint.layer&&pcbPort.layers&&!pcbPort.layers.includes(endpoint.layer)||distance2(endpoint,pcbPort)<=.01&&sourcePortIds.add(pcbPort.source_port_id));for(let smtpad2 of db2.pcb_smtpad.list()){if(!smtpad2.pcb_port_id||endpoint.layer&&smtpad2.layer!==endpoint.layer||!isPointInSmtPad({point:endpoint,pad:smtpad2,traceWidth:endpoint.width}))continue;let sourcePortId=db2.pcb_port.get(smtpad2.pcb_port_id)?.source_port_id;sourcePortId&&sourcePortIds.add(sourcePortId)}for(let hole of db2.pcb_plated_hole.list()){if(!hole.pcb_port_id||!isPointInPlatedHole({point:endpoint,hole,traceWidth:endpoint.width}))continue;let sourcePortId=db2.pcb_port.get(hole.pcb_port_id)?.source_port_id;sourcePortId&&sourcePortIds.add(sourcePortId)}}return[...sourcePortIds]}function getWireRouteEndpoints(trace){let route=trace.route.filter(point6=>point6.route_type==="wire"&&point6.x!==void 0&&point6.y!==void 0);return[route[0],route[route.length-1]].filter(point6=>!!point6)}function getSourceIdsFromConnectedPcbTraces(db2,trace){let sourceIds=new Set,endpoints=getWireRouteEndpoints(trace);if(endpoints.length===0)return[];for(let existingTrace of db2.pcb_trace.list()){if(!existingTrace.source_trace_id||existingTrace.pcb_trace_id===trace.pcb_trace_id||!db2.source_trace.get(existingTrace.source_trace_id)&&!db2.source_net.get(existingTrace.source_trace_id))continue;let existingRoute=existingTrace.route.filter(point6=>point6.route_type==="wire");for(let i6=0;i6<existingRoute.length-1;i6++){let segmentStart=existingRoute[i6],segmentEnd=existingRoute[i6+1];if(!(!segmentStart||!segmentEnd))for(let endpoint of endpoints)isPointOnWireSegment({point:endpoint,segmentStart,segmentEnd})&&sourceIds.add(existingTrace.source_trace_id)}}return[...sourceIds]}function getSourcePortIdsFromRoutedTrace(db2,trace){let sourcePortIds=new Set;for(let point6 of trace.route)for(let pcbPortId of[point6.start_pcb_port_id,point6.end_pcb_port_id]){if(!pcbPortId)continue;let sourcePortId=db2.pcb_port.get(pcbPortId)?.source_port_id;sourcePortId&&sourcePortIds.add(sourcePortId)}return sourcePortIds.size>0?[...sourcePortIds]:getEndpointSourcePortIdsFromGeometry(db2,trace)}function buildSourceConnectivityMap(sourceTraces){let connMap=new ConnectivityMap({});return connMap.addConnections(sourceTraces.map(trace=>[trace.source_trace_id,...trace.connected_source_port_ids,...trace.connected_source_net_ids])),connMap}function getSourceTraceIdForRoutedTrace({db:db2,trace,subcircuit_id}){if(trace.source_trace_id&&(db2.source_trace.get(trace.source_trace_id)??db2.source_net.get(trace.source_trace_id)))return trace.source_trace_id;let sourcePortIds=getSourcePortIdsFromRoutedTrace(db2,trace);if(sourcePortIds.length===0)return getSourceIdsFromConnectedPcbTraces(db2,trace)[0];let sourceTraces=db2.source_trace.list(),connMap=buildSourceConnectivityMap(sourceTraces),endpointNetIds=sourcePortIds.map(sourcePortId=>connMap.getNetConnectedToId(sourcePortId)).filter(netId=>!!netId),exactSourceTrace=sourcePortIds.length>=2?sourceTraces.find(sourceTrace=>sourcePortIds.every(sourcePortId=>sourceTrace.connected_source_port_ids.includes(sourcePortId))):void 0;if(exactSourceTrace)return exactSourceTrace.source_trace_id;let sourceTracesInEndpointNets=sourceTraces.filter(sourceTrace=>{let sourceTraceNetId=connMap.getNetConnectedToId(sourceTrace.source_trace_id);return endpointNetIds.some(netId=>netId===sourceTraceNetId)}),connectedToEndpoint=sourceTracesInEndpointNets.filter(sourceTrace=>sourceTrace.connected_source_port_ids.some(sourcePortId=>sourcePortIds.includes(sourcePortId))),candidates=connectedToEndpoint.length>0?connectedToEndpoint:sourceTracesInEndpointNets;if(candidates.length!==0)return(candidates.find(sourceTrace=>sourceTrace.subcircuit_id===subcircuit_id)??candidates[0])?.source_trace_id}function groupPadsByInternalConnection(pads,orientation4){let groups=[];for(let pad2 of pads){let key=orientation4==="vertical"?pad2.center.y:pad2.center.x,foundGroup=!1;for(let group of groups){let groupKey=orientation4==="vertical"?group[0].center.y:group[0].center.x;if(Math.abs(key-groupKey)<.01){group.push(pad2),foundGroup=!0;break}}foundGroup||groups.push([pad2])}return groups.filter(g4=>g4.length>=2)}function insertAutoplacedJumpers(params){let{db:db2,output_jumpers,subcircuit_id}=params;for(let jumperIndex=0;jumperIndex<output_jumpers.length;jumperIndex++){let jumper=output_jumpers[jumperIndex],sourceComponent=db2.source_component.insert({ftype:"simple_chip",name:`__autoplaced_jumper_${jumperIndex}`,supplier_part_numbers:{}}),rotation42=jumper.orientation==="horizontal"?0:90,firstPadLayer=jumper.pads[0]?.layer||jumper.pads[0]?.layers?.[0]||"top",pcbComponent=db2.pcb_component.insert({source_component_id:sourceComponent.source_component_id,center:jumper.center,rotation:rotation42,layer:firstPadLayer,width:jumper.width||0,height:jumper.height||0,obstructs_within_bounds:!1}),padData=[];for(let padIndex=0;padIndex<jumper.pads.length;padIndex++){let pad2=jumper.pads[padIndex],pinNumber=padIndex+1,sourcePort=db2.source_port.insert({source_component_id:sourceComponent.source_component_id,name:`pin${pinNumber}`,pin_number:pinNumber}),padLayer=pad2.layer||pad2.layers?.[0]||"top",pcbPort=db2.pcb_port.insert({pcb_component_id:pcbComponent.pcb_component_id,source_port_id:sourcePort.source_port_id,x:pad2.center.x,y:pad2.center.y,layers:[padLayer]}),pcbSmtpad=db2.pcb_smtpad.insert({pcb_component_id:pcbComponent.pcb_component_id,pcb_port_id:pcbPort.pcb_port_id,shape:"rect",x:pad2.center.x,y:pad2.center.y,width:pad2.width,height:pad2.height,layer:padLayer});padData.push({pad:pad2,sourcePortId:sourcePort.source_port_id,pcbSmtpadId:pcbSmtpad.pcb_smtpad_id})}let internalGroups=groupPadsByInternalConnection(jumper.pads,jumper.orientation);for(let group of internalGroups){let sourcePortIds=[];for(let groupPad of group){let padInfo=padData.find(p3=>Math.abs(p3.pad.center.x-groupPad.center.x)<.01&&Math.abs(p3.pad.center.y-groupPad.center.y)<.01);padInfo&&sourcePortIds.push(padInfo.sourcePortId)}sourcePortIds.length>=2&&db2.source_component_internal_connection.insert({source_component_id:sourceComponent.source_component_id,subcircuit_id:subcircuit_id??void 0,source_port_ids:sourcePortIds})}}}function convertPcbTraceToSimplifiedPcbTrace(trace){return{...trace,type:"pcb_trace",pcb_trace_id:trace.pcb_trace_id,connection_name:trace.connection_name??trace.source_trace_id??trace.pcb_trace_id,route:trace.route.map(point6=>({...point6}))}}function getRelevantSubcircuitIdsForReroute(group){let relevantSubcircuitIds=new Set;if(!group.subcircuit_id)return relevantSubcircuitIds;relevantSubcircuitIds.add(group.subcircuit_id);let db2=group.root?.db;if(!db2)return relevantSubcircuitIds;for(let subcircuitId of getDescendantSubcircuitIds2(db2,group.subcircuit_id))relevantSubcircuitIds.add(subcircuitId);return relevantSubcircuitIds}function getExistingPcbTracesForReroute(group){let db2=group.root?.db;if(!db2)return[];let relevantSubcircuitIds=getRelevantSubcircuitIdsForReroute(group);return db2.pcb_trace.list().filter(trace=>!trace.route||trace.route.length<2?!1:group.subcircuit_id?!!(trace.subcircuit_id&&relevantSubcircuitIds.has(trace.subcircuit_id)):!0)}function getSourceTraceIdsFromRerouteName(value){return typeof value!="string"||value.length===0?[]:value.split("__").flatMap(connectionNamePart=>{if(connectionNamePart.length===0)return[];let sourceTraceIds=[connectionNamePart],rerouteSuffixIndex=connectionNamePart.indexOf("_reroute_");return rerouteSuffixIndex>0&&sourceTraceIds.push(connectionNamePart.slice(0,rerouteSuffixIndex)),sourceTraceIds})}function addPossibleReplacementSourceTraceId(sourceTraceIds,value){if(!(typeof value!="string"||value.length===0)){sourceTraceIds.add(value);for(let sourceTraceId of getSourceTraceIdsFromRerouteName(value))sourceTraceIds.add(sourceTraceId)}}function deleteExistingPcbTracesReplacedBy({group,outputPcbTraces,pcbTraceIdsToReplace=[]}){let db2=group.root?.db;if(!db2)return;let replacementPcbTraceIds=new Set(pcbTraceIdsToReplace),replacementSourceTraceIds=new Set;for(let trace of outputPcbTraces){if(trace.type!=="pcb_trace")continue;let replacementTrace=trace;replacementPcbTraceIds.add(replacementTrace.pcb_trace_id),addPossibleReplacementSourceTraceId(replacementSourceTraceIds,replacementTrace.source_trace_id),addPossibleReplacementSourceTraceId(replacementSourceTraceIds,replacementTrace.connection_name),addPossibleReplacementSourceTraceId(replacementSourceTraceIds,replacementTrace.rootConnectionName)}if(replacementPcbTraceIds.size===0&&replacementSourceTraceIds.size===0)return;let tracesToDelete=getExistingPcbTracesForReroute(group).filter(trace=>replacementPcbTraceIds.has(trace.pcb_trace_id)||!!(trace.source_trace_id&&trace.subcircuit_id===group.subcircuit_id&&replacementSourceTraceIds.has(trace.source_trace_id)));if(tracesToDelete.length===0)return;let deletedPcbTraceIds=new Set(tracesToDelete.map(trace=>trace.pcb_trace_id));for(let via of db2.pcb_via.list())via.pcb_trace_id&&deletedPcbTraceIds.has(via.pcb_trace_id)&&db2.pcb_via.delete(via.pcb_via_id);for(let trace of tracesToDelete)db2.pcb_trace.delete(trace.pcb_trace_id)}function getExistingSimplifiedPcbTracesForReroute(group){return getExistingPcbTracesForReroute(group).map(convertPcbTraceToSimplifiedPcbTrace)}function splitPcbTracesOnJumperSegments(route){let jumperRoutes=route.filter(p3=>p3.route_type==="jumper"),wireAndViaRoutes=route.filter(p3=>p3.route_type!=="jumper");if(jumperRoutes.length===0)return null;let splitRanges=[];for(let jumperRoute of jumperRoutes){let jumperStart=jumperRoute.start,jumperEnd=jumperRoute.end,startIdx=-1,endIdx=-1,minStartDist=1/0,minEndDist=1/0;for(let i6=0;i6<wireAndViaRoutes.length;i6++){let p3=wireAndViaRoutes[i6];if(p3.route_type!=="wire")continue;let distToStart=Math.hypot(p3.x-jumperStart.x,p3.y-jumperStart.y),distToEnd=Math.hypot(p3.x-jumperEnd.x,p3.y-jumperEnd.y);distToStart<minStartDist&&(minStartDist=distToStart,startIdx=i6),distToEnd<minEndDist&&(minEndDist=distToEnd,endIdx=i6)}startIdx>endIdx&&([startIdx,endIdx]=[endIdx,startIdx]),startIdx>=0&&endIdx>=0&&startIdx!==endIdx&&splitRanges.push({startIdx,endIdx})}splitRanges.sort((a6,b6)=>a6.startIdx-b6.startIdx);let segments=[],currentStart=0;for(let range2 of splitRanges)currentStart<range2.startIdx&&segments.push(wireAndViaRoutes.slice(currentStart,range2.startIdx+1)),currentStart=range2.endIdx;return currentStart<wireAndViaRoutes.length&&segments.push(wireAndViaRoutes.slice(currentStart)),segments}function computeCenterFromAnchorPosition(anchorPosition,ctx){let{width,height,pcbAnchorAlignment}=ctx;if(!pcbAnchorAlignment)return anchorPosition;let alignment=pcbAnchorAlignment;if(typeof width!="number"||typeof height!="number")return anchorPosition;let ax3=anchorPosition.x,ay3=anchorPosition.y;switch(alignment){case"top_left":return{x:ax3+width/2,y:ay3-height/2};case"top_center":return{x:ax3,y:ay3-height/2};case"top_right":return{x:ax3-width/2,y:ay3-height/2};case"center_left":return{x:ax3+width/2,y:ay3};case"center_right":return{x:ax3-width/2,y:ay3};case"bottom_left":return{x:ax3+width/2,y:ay3+height/2};case"bottom_center":return{x:ax3,y:ay3+height/2};case"bottom_right":return{x:ax3-width/2,y:ay3+height/2};default:return anchorPosition}}var getDistanceToPoint=(routePoint,targetPoint)=>{let position4=getRoutePointPosition2(routePoint);return Math.hypot(position4.x-targetPoint.x,position4.y-targetPoint.y)},removeSrjMetadataFromPcbTraceRoute=route=>route.map(routePoint=>{let{circuitJsonMetadata:_circuitJsonMetadata,...circuitJsonRoutePoint}=routePoint;return circuitJsonRoutePoint}),platformAllowsLegacyAutorouters=group=>{let platform=group.root?.platform;return platform!==void 0&&"allowLegacyAutorouters"in platform&&platform.allowLegacyAutorouters===!0},getDisabledLegacyGroupAutorouterPreset=group=>{if(platformAllowsLegacyAutorouters(group))return null;let resolvedGroupAutorouter=group._parsedProps.autorouter??group.getInheritedProperty("autorouter");return getLegacyAutorouterPreset(resolvedGroupAutorouter)},getDisabledLegacyAutorouterPreset=group=>{if(platformAllowsLegacyAutorouters(group))return null;let legacyGroupAutorouterPreset=getDisabledLegacyGroupAutorouterPreset(group);if(legacyGroupAutorouterPreset)return legacyGroupAutorouterPreset;let routingPhaseAutorouters=group.selectAll("autoroutingphase").map(autoroutingPhase=>autoroutingPhase._parsedProps.autorouter);for(let autorouter of routingPhaseAutorouters){let legacyAutorouterPreset=getLegacyAutorouterPreset(autorouter);if(legacyAutorouterPreset)return legacyAutorouterPreset}return null},ensureRouteStartsAtSourceTraceStart=({db:db2,route,routeThicknessMode,sourceTraceId})=>{if(!sourceTraceId||route.length<2)return route;let firstSourcePortId=db2.source_trace.get(sourceTraceId)?.connected_source_port_ids[0];if(!firstSourcePortId)return route;let firstPcbPort=db2.pcb_port.list().find(port=>port.source_port_id===firstSourcePortId);if(!firstPcbPort)return route;let firstPoint=route[0],lastPoint=route[route.length-1];return getDistanceToPoint(lastPoint,firstPcbPort)<getDistanceToPoint(firstPoint,firstPcbPort)?reversePcbTraceRoute(route,routeThicknessMode):route},Group5=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"pcb_group_id",null);__publicField(this,"schematic_group_id",null);__publicField(this,"subcircuit_id",null);__publicField(this,"_hasStartedAsyncAutorouting",!1);__publicField(this,"_pcbPlacementDrcErrorCount",null);__publicField(this,"_pcbPlacementDrcCheckError",null);__publicField(this,"_pcbPlacementDrcChecksPending",!1);__publicField(this,"_standaloneSubcircuitDrcChecksComplete",!1);__publicField(this,"_standaloneSubcircuitDrcChecksInProgress",!1);__publicField(this,"_isInflatedFromCircuitJson",!1);__publicField(this,"_isolatedCircuitJson",null);__publicField(this,"_normalComponentNameMap",null);__publicField(this,"_asyncAutoroutingResult",null);__publicField(this,"unnamedElementCounter",{})}get _isIsolatedSubcircuit(){return!!this.getInheritedProperty("_subcircuitCachingEnabled")}getNormalComponentNameMap(){if(this._normalComponentNameMap)return this._normalComponentNameMap;let nameMap=new Map,collectNamedComponents=component=>{if(component._isNormalComponent&&component.name){let componentsWithSameName=nameMap.get(component.name);componentsWithSameName?componentsWithSameName.push(component):nameMap.set(component.name,[component])}for(let child of component.children)child.isSubcircuit||collectNamedComponents(child)};for(let child of this.children)child.isSubcircuit||collectNamedComponents(child);return this._normalComponentNameMap=nameMap,nameMap}get config(){return{zodProps:groupProps,componentName:"Group"}}initPorts(opts={}){let schPinArrangement=this._getSchematicPortArrangement();this._parsedProps?.showAsSchematicBox&&!this._parsedProps.pinLabels&&schPinArrangement&&getPinsFromPortArrangement(schPinArrangement).some(pin=>typeof pin=="string")||super.initPorts(opts)}_getSchematicPortArrangementFromPortDirections(){if(!this._parsedProps?.showAsSchematicBox)return null;let sidePins={leftSide:[],rightSide:[],topSide:[],bottomSide:[]};for(let port of this.children){if(port.componentName!=="Port")continue;let direction2=port._parsedProps.direction;if(!direction2)continue;let pin=port._parsedProps.pinNumber??port._parsedProps.name??void 0;if(pin===void 0)continue;sidePins[direction2==="left"?"leftSide":direction2==="right"?"rightSide":direction2==="up"?"topSide":"bottomSide"].push(pin)}if(sidePins.leftSide.length===0&&sidePins.rightSide.length===0&&sidePins.topSide.length===0&&sidePins.bottomSide.length===0)return null;let arrangement={};return sidePins.leftSide.length>0&&(arrangement.leftSide={pins:sidePins.leftSide,direction:"top-to-bottom"}),sidePins.rightSide.length>0&&(arrangement.rightSide={pins:sidePins.rightSide,direction:"top-to-bottom"}),sidePins.topSide.length>0&&(arrangement.topSide={pins:sidePins.topSide,direction:"left-to-right"}),sidePins.bottomSide.length>0&&(arrangement.bottomSide={pins:sidePins.bottomSide,direction:"left-to-right"}),arrangement}_getSchematicPortArrangement(){return super._getSchematicPortArrangement()??this._getSchematicPortArrangementFromPortDirections()}_ensureSchematicBoxPortsFromConnections(){if(this._parsedProps?.showAsSchematicBox&&this._parsedProps?.connections)for(let[pinName,target]of Object.entries(this._parsedProps.connections)){if(this.children.find(child=>child.componentName==="Port"&&child.isMatchingAnyOf([pinName])))continue;let pinNumberMatch=pinName.match(/^pin(\d+)$/i)??pinName.match(/^(\d+)$/),pinNumber=pinNumberMatch?Number(pinNumberMatch[1]):void 0;this.add(new Port({name:pinName,pinNumber,connectsTo:target}))}}doInitialInitializePortsFromChildren(){super.doInitialInitializePortsFromChildren(),this._ensureSchematicBoxPortsFromConnections()}updateInitializePortsFromChildren(){super.updateInitializePortsFromChildren(),this._ensureSchematicBoxPortsFromConnections()}_getPrimaryPinCount(){let superPinCount=super._getPrimaryPinCount();if(!this._parsedProps?.showAsSchematicBox)return superPinCount;let directPortPinNumbers=this.children.filter(child=>child.componentName==="Port").map(port=>port._parsedProps.pinNumber).filter(pinNumber=>pinNumber!==void 0);return directPortPinNumbers.length===0?superPinCount:Math.max(superPinCount,...directPortPinNumbers)}_getPinLabelsFromPorts(){return this._parsedProps?.showAsSchematicBox?getGroupSchematicBoxPinLabels(this):super._getPinLabelsFromPorts()}doInitialSourceGroupRender(){let{db:db2}=this.root,hasExplicitName=typeof this._parsedProps.name=="string"&&this._parsedProps.name.length>0,source_group3=db2.source_group.insert({name:this.name,is_subcircuit:this.isSubcircuit,was_automatically_named:!hasExplicitName});this.source_group_id=source_group3.source_group_id,this.isSubcircuit&&(this.subcircuit_id=`subcircuit_${source_group3.source_group_id}`,db2.source_group.update(source_group3.source_group_id,{subcircuit_id:this.subcircuit_id}))}doInitialSourceRender(){let{db:db2}=this.root;for(let child of this.getDescendants())child.getGroup()?.source_group_id===this.source_group_id&&db2.source_component.update(child.source_component_id,{source_group_id:this.source_group_id});if(!this.isSubcircuit)return;let disabledLegacyAutorouterPreset=getDisabledLegacyAutorouterPreset(this);disabledLegacyAutorouterPreset&&db2.source_property_ignored_warning.insert({source_component_id:this.source_component_id??"",property_name:"autorouter",subcircuit_id:this.subcircuit_id??void 0,error_type:"source_property_ignored_warning",message:`The "${disabledLegacyAutorouterPreset}" autorouter is deprecated, so autorouting has been disabled for this subcircuit. Use the default autorouter and introduce <autoroutingphase /> or <fanout /> elements as needed.`})}doInitialSourceParentAttachment(){let{db:db2}=this.root,parentGroup=this.parent?.getGroup?.();if(parentGroup?.source_group_id&&db2.source_group.update(this.source_group_id,{parent_source_group_id:parentGroup.source_group_id}),!this.isSubcircuit||isAssemblyDeviceContainer(this.parent))return;let parent_subcircuit_id=this.parent?.getSubcircuit?.()?.subcircuit_id;parent_subcircuit_id&&db2.source_group.update(this.source_group_id,{parent_subcircuit_id})}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,groupProps2=props,hasOutline=groupProps2.outline&&groupProps2.outline.length>0,numericOutline=hasOutline?groupProps2.outline.map(point6=>({x:distance.parse(point6.x),y:distance.parse(point6.y)})):void 0,ctx=this.props,anchorPosition=this._getGlobalPcbPositionBeforeLayout(),center2=computeCenterFromAnchorPosition(anchorPosition,ctx),pcb_group3=db2.pcb_group.insert({is_subcircuit:this.isSubcircuit,subcircuit_id:this.subcircuit_id??this.getSubcircuit()?.subcircuit_id,name:this.name,anchor_position:anchorPosition,center:center2,...hasOutline?{outline:numericOutline}:{width:0,height:0},pcb_component_ids:[],source_group_id:this.source_group_id,autorouter_configuration:props.autorouter?{trace_clearance:props.autorouter.traceClearance}:void 0,anchor_alignment:props.pcbAnchorAlignment??null});this.pcb_group_id=pcb_group3.pcb_group_id;for(let child of this.children)db2.pcb_component.update(child.pcb_component_id,{pcb_group_id:pcb_group3.pcb_group_id})}doInitialPcbPrimitiveRender(){this.calculatePcbGroupBounds()}calculatePcbGroupBounds(pcbContentBounds){if(!this.pcb_group_id||this.root?.pcbDisabled)return;let{db:db2}=this.root,props=this._parsedProps,hasOutline=props.outline&&props.outline.length>0,hasExplicitPositioning=this._parsedProps.pcbX!==void 0||this._parsedProps.pcbY!==void 0;if(hasOutline){let numericOutline=props.outline.map(point6=>({x:distance.parse(point6.x),y:distance.parse(point6.y)})),outlineBounds=getBoundsFromPoints2(numericOutline);if(!outlineBounds)return;let centerX2=(outlineBounds.minX+outlineBounds.maxX)/2,centerY2=(outlineBounds.minY+outlineBounds.maxY)/2,center22=hasExplicitPositioning?db2.pcb_group.get(this.pcb_group_id)?.center??{x:centerX2,y:centerY2}:{x:centerX2,y:centerY2};db2.pcb_group.update(this.pcb_group_id,{center:center22});return}let contentBounds=pcbContentBounds;if(!contentBounds){let bounds=getBoundsOfPcbComponents(this.children);contentBounds={center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},width:bounds.width,height:bounds.height}}let{width,height}=contentBounds,{x:centerX,y:centerY}=contentBounds.center;if(this.isSubcircuit||this.isRoutingDirective){let{padLeft,padRight,padTop,padBottom}=this._resolvePcbPadding();width+=padLeft+padRight,height+=padTop+padBottom,centerX+=(padRight-padLeft)/2,centerY+=(padTop-padBottom)/2}let resolvedWidth=Number(props.width??width),resolvedHeight=Number(props.height??height),existingCenter=db2.pcb_group.get(this.pcb_group_id)?.center??{x:centerX,y:centerY},shouldUsePcbContentCenter=this.isSubcircuit||pcbContentBounds!==void 0,center2=hasExplicitPositioning?shouldUsePcbContentCenter?{x:props.width===void 0?centerX:existingCenter.x,y:props.height===void 0?centerY:existingCenter.y}:existingCenter:{x:centerX,y:centerY};if(hasExplicitPositioning&&props.pcbAnchorAlignment){let anchorPosition=this._getGlobalPcbPositionBeforeLayout(),anchorAlignedCenter=computeCenterFromAnchorPosition(anchorPosition,{...this.props,width:resolvedWidth,height:resolvedHeight});(Math.abs(anchorAlignedCenter.x-center2.x)>1e-6||Math.abs(anchorAlignedCenter.y-center2.y)>1e-6)&&this._repositionOnPcb(anchorAlignedCenter),center2=anchorAlignedCenter}db2.pcb_group.update(this.pcb_group_id,{width:resolvedWidth,height:resolvedHeight,center:center2})}updatePcbPrimitiveRender(){this.calculatePcbGroupBounds()}getNextAvailableName(elm){var _a527,_b4;return(_a527=this.unnamedElementCounter)[_b4=elm.lowercaseComponentName]??(_a527[_b4]=1),`unnamed_${elm.lowercaseComponentName}${this.unnamedElementCounter[elm.lowercaseComponentName]++}`}_resolvePcbPadding(){let props=this._parsedProps,layout=props.pcbLayout,getPaddingValue=key=>{let layoutValue=layout?.[key],propsValue=props[key];if(typeof layoutValue=="number")return layoutValue;if(typeof propsValue=="number")return propsValue},generalPadding=getPaddingValue("padding")??0,paddingX=getPaddingValue("paddingX"),paddingY=getPaddingValue("paddingY"),padLeft=getPaddingValue("paddingLeft")??paddingX??generalPadding,padRight=getPaddingValue("paddingRight")??paddingX??generalPadding,padTop=getPaddingValue("paddingTop")??paddingY??generalPadding,padBottom=getPaddingValue("paddingBottom")??paddingY??generalPadding;return{padLeft,padRight,padTop,padBottom}}doInitialCreateTraceHintsFromProps(){let{_parsedProps:props}=this,{db:db2}=this.root,groupProps2=props;if(!this.isSubcircuit)return;let manualTraceHints=groupProps2.manualEdits?.manual_trace_hints;if(manualTraceHints)for(let manualTraceHint of manualTraceHints)this.add(new TraceHint({for:manualTraceHint.pcb_port_selector,offsets:manualTraceHint.offsets}))}doInitialSourceAddConnectivityMapKey(){Group_doInitialSourceAddConnectivityMapKey(this),Group_doInitialAssignSchematicSheetToConnectedComponents(this)}_areChildSubcircuitsRouted(){let subcircuitChildren=this._findDirectChildSubcircuits();for(let subcircuitChild of subcircuitChildren)if(!subcircuitChild._isInflatedFromCircuitJson&&subcircuitChild._hasTracesToRoute()&&subcircuitChild._shouldRouteAsync()&&!subcircuitChild._asyncAutoroutingResult)return!1;return!0}_findDirectChildSubcircuits(){let result=[],visit=children=>{for(let child of children)child.isSubcircuit&&child!==this?result.push(child):visit(child.children)};return visit(this.children),result}_shouldRouteAsync(){if(this._isLegacyAutorouterDisabled())return!1;let autorouter=this._getAutorouterConfig();return autorouter.groupMode==="sequential-trace"?!1:!!(autorouter.local&&autorouter.groupMode==="subcircuit"||!autorouter.local)}_getRoutingPhasePlans(){return Group_getRoutingPhasePlans(this)}_hasTracesToRoute(){let debug132=(0,import_debug11.default)("tscircuit:core:_hasTracesToRoute"),routingPhasePlans=this._getRoutingPhasePlans(),traceCount=0,hasReroutePhaseWithRegion=!1;for(let routingPhasePlan of routingPhasePlans)traceCount+=routingPhasePlan.traces.length,hasReroutePhaseWithRegion||(hasReroutePhaseWithRegion=!!(routingPhasePlan.reroute&&routingPhasePlan.region));if(debug132(`[${this.getString()}] has ${traceCount} traces to route`),traceCount>0)return!0;if(hasReroutePhaseWithRegion){let existingTraceCount=getExistingPcbTracesForReroute(this).length;return debug132(`[${this.getString()}] has ${existingTraceCount} existing pcb traces available for reroute`),existingTraceCount>0}return!1}async _runEffectMakeHttpAutoroutingRequest(){let{db:db2}=this.root,debug132=(0,import_debug11.default)("tscircuit:core:_runEffectMakeHttpAutoroutingRequest"),props=this._parsedProps,autorouterConfig2=this._getAutorouterConfig(),serverUrl=autorouterConfig2.serverUrl,serverMode=autorouterConfig2.serverMode,fetchWithDebug=(url2,options)=>(debug132("fetching",url2),options.headers&&(options.headers["Tscircuit-Core-Version"]=this.root?.getCoreVersion()),fetch(url2,options)),pcbAndSourceCircuitJson=this.root.db.toArray().filter(element=>element.type.startsWith("source_")||element.type.startsWith("pcb_"));if(serverMode==="solve-endpoint"){if(this.props.autorouter?.inputFormat==="simplified"){let preferredTraceWidth=props.defaultTraceWidth??props.nominalTraceWidth,{simpleRouteJson}=getSimpleRouteJsonFromCircuitJson({db:db2,minTraceWidth:Number(props.minTraceWidth??.15),nominalTraceWidth:preferredTraceWidth!=null?Number(preferredTraceWidth):void 0,subcircuit_id:this.subcircuit_id,subcircuitComponent:this});simpleRouteJson.allowViaInPad=autorouterConfig2.allowViaInPad;let{autorouting_result:autorouting_result2}=await fetchWithDebug(`${serverUrl}/autorouting/solve`,{method:"POST",body:JSON.stringify({input_simple_route_json:simpleRouteJson,subcircuit_id:this.subcircuit_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());this._asyncAutoroutingResult=autorouting_result2,this._markDirty("PcbTraceRender");return}let{autorouting_result}=await fetchWithDebug(`${serverUrl}/autorouting/solve`,{method:"POST",body:JSON.stringify({input_circuit_json:pcbAndSourceCircuitJson,subcircuit_id:this.subcircuit_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());this._asyncAutoroutingResult=autorouting_result,this._markDirty("PcbTraceRender");return}let{autorouting_job}=await fetchWithDebug(`${serverUrl}/autorouting/jobs/create`,{method:"POST",body:JSON.stringify({input_circuit_json:pcbAndSourceCircuitJson,provider:"freerouting",autostart:!0,display_name:this.root?.name,subcircuit_id:this.subcircuit_id,server_cache_enabled:autorouterConfig2.serverCacheEnabled}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());for(;;){let{autorouting_job:job}=await fetchWithDebug(`${serverUrl}/autorouting/jobs/get`,{method:"POST",body:JSON.stringify({autorouting_job_id:autorouting_job.autorouting_job_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());if(job.is_finished){let{autorouting_job_output}=await fetchWithDebug(`${serverUrl}/autorouting/jobs/get_output`,{method:"POST",body:JSON.stringify({autorouting_job_id:autorouting_job.autorouting_job_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());this._asyncAutoroutingResult={output_pcb_traces:autorouting_job_output.output_pcb_traces},this._markDirty("PcbTraceRender");break}if(job.has_error){let err2=new AutorouterError(`Autorouting job failed: ${JSON.stringify(job.error)}`);throw db2.pcb_autorouting_error.insert({pcb_error_id:autorouting_job.autorouting_job_id,error_type:"pcb_autorouting_error",message:err2.message}),err2}await new Promise(resolve=>setTimeout(resolve,100))}}async _runLocalAutorouting(){let{db:db2}=this.root,props=this._parsedProps,debug132=(0,import_debug11.default)("tscircuit:core:_runLocalAutorouting");debug132(`[${this.getString()}] starting local autorouting`);let autorouterConfig2=this._getAutorouterConfig(),isLaserPrefabPreset=this._isLaserPrefabAutorouter(autorouterConfig2),isAutoJumperPreset=this._isAutoJumperAutorouter(autorouterConfig2),isSingleLayerBoard=this._getSubcircuitLayerCount()===1,minTraceWidth=Number(props.minTraceWidth??.15),nominalTraceWidth=Number(props.defaultTraceWidth??props.nominalTraceWidth??minTraceWidth),routingPhasePlans=this._getRoutingPhasePlans(),hasPhasedAutorouting=Group_hasPhasedAutorouting(routingPhasePlans),shouldEmitRoutingPhaseDebugObjects=routingPhasePlans.length>1,routingPhaseDisplayIndexes=new Map(routingPhasePlans.map((plan,index)=>[plan,index]));if(shouldEmitRoutingPhaseDebugObjects)for(let debugObject of db2.pcb_debug_object.list())debugObject.subcircuit_id===this.subcircuit_id&&(debugObject.label?.startsWith("Autorouting phase: ")||/^autorouting phase \d+(?: |$)/.test(debugObject.label??""))&&db2.pcb_debug_object.delete(debugObject.pcb_debug_object_id);let emitRoutingPhaseDebugObject=(routingPhasePlan,bounds)=>{if(!shouldEmitRoutingPhaseDebugObjects)return;let phaseIndex=routingPhaseDisplayIndexes.get(routingPhasePlan);if(phaseIndex===void 0)return;let phaseName=routingPhasePlan.phaseName?.trim();db2.pcb_debug_object.insert({shape:"rect",center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},size:{width:bounds.maxX-bounds.minX,height:bounds.maxY-bounds.minY},label:`autorouting phase ${phaseIndex}${phaseName?` ${phaseName}`:""}`,subcircuit_id:this.subcircuit_id??void 0})},routingStages=routingPhasePlans.flatMap(routingPhasePlan=>{let phaseAutorouterConfig=routingPhasePlan.autorouter?getPresetAutoroutingConfig(routingPhasePlan.autorouter,this.root?.platform):autorouterConfig2,stages=getLocalAutoroutingStages(phaseAutorouterConfig,this.root?.platform);return stages.map((stage,phaseStageIndex)=>({...stage,routingPhasePlan,phaseStageIndex,phaseStageCount:stages.length}))}),fanoutPourNetMap=routingStages.some(({autorouterConfig:autorouterConfig22})=>["fanout","single_layer_fanout"].includes(autorouterConfig22.preset??""))?Group_getFanoutPourNetMap(this,routingPhasePlans):void 0,{simpleRouteJson:baseSimpleRouteJson}=getSimpleRouteJsonFromCircuitJson({db:db2,minTraceWidth,nominalTraceWidth,subcircuit_id:this.subcircuit_id,subcircuitComponent:this,fanoutPourNetMap}),emitFanoutBoundsConflictWarning=routingPhasePlan=>{let fanoutRegionPcbGroupId=routingPhasePlan.fanoutRegionPcbGroupId;if(!fanoutRegionPcbGroupId)return;let pcbGroup=db2.pcb_group.get(fanoutRegionPcbGroupId),sourceComponentId=db2.pcb_component.list().find(component=>component.pcb_group_id===fanoutRegionPcbGroupId)?.source_component_id;if(!sourceComponentId)return;let message=`${pcbGroup?.name??"Breakout"} defines conflicting fanout bounds with explicit breakout geometry and fanoutBoundaryPadding. Explicit breakout geometry takes precedence, so fanoutBoundaryPadding is ignored.`;db2.source_property_ignored_warning.list().some(warning=>warning.source_component_id===sourceComponentId&&warning.property_name==="fanoutBoundaryPadding"&&warning.message===message)||db2.source_property_ignored_warning.insert({source_component_id:sourceComponentId,property_name:"fanoutBoundaryPadding",message,error_type:"source_property_ignored_warning",subcircuit_id:pcbGroup?.subcircuit_id})},fanoutConfigByPhasePlan=new Map;for(let routingStage of routingStages){let fanoutMode=routingStage.autorouterConfig.preset;(fanoutMode==="fanout"||fanoutMode==="single_layer_fanout")&&!fanoutConfigByPhasePlan.has(routingStage.routingPhasePlan)&&fanoutConfigByPhasePlan.set(routingStage.routingPhasePlan,routingStage.autorouterConfig)}let fanoutPhaseRegions=[];for(let[routingPhasePlan,phaseAutorouterConfig]of fanoutConfigByPhasePlan){let fanoutRegionPcbGroupId=routingPhasePlan.fanoutRegionPcbGroupId;if(!fanoutRegionPcbGroupId)continue;let phaseSimpleRouteJson=Group_filterSimpleRouteJsonForPhase(baseSimpleRouteJson,routingPhasePlan);if(phaseSimpleRouteJson.connections.length===0)continue;phaseSimpleRouteJson=Group_applyDrcTolerancesToSimpleRouteJson(phaseSimpleRouteJson,routingPhasePlan.drcTolerances);let breakoutPoints=db2.pcb_breakout_point.list().filter(point6=>point6.pcb_group_id===fanoutRegionPcbGroupId).map(point6=>({x:point6.x,y:point6.y})),fanoutMode=phaseAutorouterConfig.preset,fanoutBounds=FanoutAutorouter.resolveFanoutBounds(phaseSimpleRouteJson,{mode:fanoutMode,busFanoutDirections:routingPhasePlan.busFanoutDirections,fanoutBounds:routingPhasePlan.fanoutBounds,fanoutBoundaryPadding:routingPhasePlan.fanoutBoundaryPadding,fanoutRoutingLayers:routingPhasePlan.fanoutRoutingLayers,breakoutPoints,onFanoutBoundsConflict:()=>emitFanoutBoundsConflictWarning(routingPhasePlan)});if(routingPhasePlan.fanoutBounds=fanoutBounds,!fanoutBounds)continue;let pcbGroup=db2.pcb_group.get(fanoutRegionPcbGroupId),maximumTraceWidth=Math.max(phaseSimpleRouteJson.minTraceWidth,...phaseSimpleRouteJson.connections.map(connection=>connection.nominalTraceWidth??connection.width??phaseSimpleRouteJson.minTraceWidth)),viaPadDiameter=phaseSimpleRouteJson.minViaPadDiameter??phaseSimpleRouteJson.min_via_pad_diameter??phaseSimpleRouteJson.minViaDiameter,traceToPadClearance=phaseSimpleRouteJson.minTraceToPadEdgeClearance??phaseSimpleRouteJson.defaultObstacleMargin??maximumTraceWidth;fanoutPhaseRegions.push({regionId:fanoutRegionPcbGroupId,name:pcbGroup?.name??routingPhasePlan.phaseName??fanoutRegionPcbGroupId,bounds:fanoutBounds,boundaryKeepaway:getFanoutBoundaryPointSpacing({traceWidth:maximumTraceWidth,traceToPadClearance,viaPadDiameter})/2})}let fanoutSeparationConflict=findFanoutPhaseSeparationConflict(fanoutPhaseRegions);if(fanoutSeparationConflict){let{firstRegion,secondRegion,availableGap,requiredGap}=fanoutSeparationConflict,separationDescription=availableGap<0?`overlap by ${Math.abs(availableGap).toFixed(3)}mm`:`are only ${availableGap.toFixed(3)}mm apart`,message=`Fanout regions "${firstRegion.name}" and "${secondRegion.name}" ${separationDescription}, but at least ${requiredGap.toFixed(3)}mm of separation is required for a via-safe routing channel. Move the components farther apart or reduce their facing fanout padding.`;throw db2.pcb_autorouting_error.insert({pcb_error_id:`pcb_autorouter_error_subcircuit_${this.subcircuit_id}`,error_type:"pcb_autorouting_error",message}),this.root?.emit("autorouting:error",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),error:{message},simpleRouteJson:baseSimpleRouteJson}),new Error(message)}for(let{regionId,bounds}of fanoutPhaseRegions)db2.pcb_group.update(regionId,{center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},width:bounds.maxX-bounds.minX,height:bounds.maxY-bounds.minY});let outputTraces=[],outputJumpers=[],pcbTraceIdsToDelete=new Set,existingRerouteSeedTraces=getExistingSimplifiedPcbTracesForReroute(this),traceMatchesRoutingPhase=(trace,routingPhasePlan)=>{let connectionName=trace.connection_name??trace.pcb_trace_id,sourceTraceIds=new Set([connectionName,trace.pcb_trace_id,...getSourceTraceIdsFromRerouteName(connectionName),...getSourceTraceIdsFromRerouteName(trace.pcb_trace_id)]);return baseSimpleRouteJson.connections.some(connection=>connectionIsInRoutingPhase(connection,routingPhasePlan)?sourceTraceIds.has(connection.name)||(connection.source_trace_id?sourceTraceIds.has(connection.source_trace_id):!1)||(connection.rootConnectionName?sourceTraceIds.has(connection.rootConnectionName):!1)||connection.mergedConnectionNames?.some(name=>sourceTraceIds.has(name)):!1)},previousStageOutputSimpleRouteJson;for(let{routingPhasePlan,autorouterConfig:phaseAutorouterConfig,strategy:localAutorouterStrategy,usesPreviousStageOutput,phaseStageIndex,phaseStageCount}of routingStages){if(usesPreviousStageOutput||(previousStageOutputSimpleRouteJson=void 0),usesPreviousStageOutput&&previousStageOutputSimpleRouteJson===void 0)throw new Error("Autorouting follow-up stage is missing the preceding stage output");let simpleRouteJson=previousStageOutputSimpleRouteJson??baseSimpleRouteJson,isRegionReroutePhase=!!(routingPhasePlan.reroute&&routingPhasePlan.region),isConnectionReroutePhase=!!(routingPhasePlan.reroute&&!routingPhasePlan.region&&routingPhasePlan.traces.length>0),isReroutePhase=isRegionReroutePhase||isConnectionReroutePhase,rerouteOriginalSrj=isRegionReroutePhase?{...baseSimpleRouteJson,traces:[...existingRerouteSeedTraces,...outputTraces]}:null;if(!usesPreviousStageOutput&&isRegionReroutePhase&&rerouteOriginalSrj)simpleRouteJson=E32(rerouteOriginalSrj,{shape:"rect",...routingPhasePlan.region});else if(!usesPreviousStageOutput&&isConnectionReroutePhase){let phaseInput=Group_filterSimpleRouteJsonForPhase(baseSimpleRouteJson,routingPhasePlan);simpleRouteJson={...phaseInput,traces:[...phaseInput.traces??[],...outputTraces.filter(trace=>!traceMatchesRoutingPhase(trace,routingPhasePlan))]}}else if(!usesPreviousStageOutput&&hasPhasedAutorouting){let phaseInput=Group_filterSimpleRouteJsonForPhase(baseSimpleRouteJson,routingPhasePlan),activeCustomBreakoutRoutingGroupId=routingPhasePlan.routingPcbGroupId;if(activeCustomBreakoutRoutingGroupId){let activeGroupCopperPourObstacles=getSimpleRouteJsonFromCircuitJson({db:db2,minTraceWidth,nominalTraceWidth,subcircuit_id:this.subcircuit_id,subcircuitComponent:this,routingPcbGroupId:activeCustomBreakoutRoutingGroupId,fanoutPourNetMap}).simpleRouteJson.obstacles.filter(obstacle=>obstacle.isCopperPour),nonCopperPourObstacles=phaseInput.obstacles.filter(obstacle=>!obstacle.isCopperPour);phaseInput.obstacles=nonCopperPourObstacles.concat(activeGroupCopperPourObstacles)}simpleRouteJson={...phaseInput,traces:[...phaseInput.traces??[],...outputTraces]}}if(simpleRouteJson=Group_applyDrcTolerancesToSimpleRouteJson(simpleRouteJson,routingPhasePlan.drcTolerances),simpleRouteJson.allowViaInPad=phaseAutorouterConfig.allowViaInPad,(hasPhasedAutorouting||isReroutePhase)&&simpleRouteJson.connections.length===0){phaseStageIndex===0&&emitRoutingPhaseDebugObject(routingPhasePlan,simpleRouteJson.bounds),previousStageOutputSimpleRouteJson=simpleRouteJson;continue}let phaseIsAutoJumperPreset=routingPhasePlan.autorouter!==void 0?this._isAutoJumperAutorouter(phaseAutorouterConfig):isAutoJumperPreset,phaseIsLaserPrefabPreset=routingPhasePlan.autorouter!==void 0?this._isLaserPrefabAutorouter(phaseAutorouterConfig):isLaserPrefabPreset;phaseIsAutoJumperPreset&&(simpleRouteJson.allowJumpers=!0,phaseAutorouterConfig.availableJumperTypes&&(simpleRouteJson.availableJumperTypes=phaseAutorouterConfig.availableJumperTypes));let fanoutMode=phaseAutorouterConfig.preset;if((fanoutMode==="fanout"||fanoutMode==="single_layer_fanout")&&!routingPhasePlan.fanoutRegionPcbGroupId&&(routingPhasePlan.fanoutBounds=FanoutAutorouter.resolveFanoutBounds(simpleRouteJson,{mode:fanoutMode,busFanoutDirections:routingPhasePlan.busFanoutDirections,fanoutBounds:routingPhasePlan.fanoutBounds,fanoutBoundaryPadding:routingPhasePlan.fanoutBoundaryPadding,fanoutRoutingLayers:routingPhasePlan.fanoutRoutingLayers})),phaseStageIndex===0&&emitRoutingPhaseDebugObject(routingPhasePlan,routingPhasePlan.fanoutBounds??simpleRouteJson.bounds),debug132.enabled&&global.debugOutputArray?.push({name:`simpleroutejson-${this.props.name}.json`,obj:simpleRouteJson}),debug132.enabled){let graphicsObject=Fo2(simpleRouteJson);graphicsObject.title=`autorouting-${this.props.name}`,global.debugGraphics?.push(graphicsObject)}this.root?.emit("autorouting:start",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},simpleRouteJson});let cacheEngine=phaseAutorouterConfig.algorithmFn||!localAutorouterStrategy.cacheable?void 0:this.root?.platform?.localCacheEngine,cacheKey=cacheEngine?getLocalAutoroutingCacheKey(simpleRouteJson):void 0,cachedResult=cacheKey?await getCachedLocalAutoroutingPhaseResult({cacheEngine,cacheKey}):null,autorouter;try{let traces;if(cachedResult)debug132(`[${this.getString()}] using cached local autorouting result`),traces=cachedResult.traces;else{if(phaseAutorouterConfig.algorithmFn)autorouter=await phaseAutorouterConfig.algorithmFn(simpleRouteJson);else{let autorouterVersion22=phaseAutorouterConfig.autorouterVersion??this.props.autorouterVersion,effortLevel=this.props.autorouterEffortLevel,effort=effortLevel?Number.parseInt(effortLevel.replace("x",""),10):void 0,commonAutorouterOptions={capacityDepth:phaseAutorouterConfig.capacityDepth,targetMinCapacity:phaseAutorouterConfig.targetMinCapacity,platformConfig:this.root?.platform,useAssignableSolver:phaseIsLaserPrefabPreset||isSingleLayerBoard,useAutoJumperSolver:phaseIsAutoJumperPreset,useLaserPrefabSolver:phaseIsLaserPrefabPreset,autorouterVersion:autorouterVersion22,effort};autorouter=localAutorouterStrategy.create({simpleRouteJson,commonAutorouterOptions,busFanoutDirections:routingPhasePlan.busFanoutDirections,fanoutBounds:routingPhasePlan.fanoutBounds,fanoutRoutingLayers:routingPhasePlan.fanoutRoutingLayers,componentNamesById:getPcbComponentNamesById(db2),onSolverStarted:({solverName,solverParams,solverConstructorArgs})=>this.root?.emit("solver:started",{type:"solver:started",solverName,solverParams,solverConstructorArgs,componentName:this.getString()})})}if(!autorouter)throw new Error("Failed to create local autorouter");let activeAutorouter=autorouter,routingPromise=new Promise((resolve,reject)=>{activeAutorouter.on("complete",event=>{debug132(`[${this.getString()}] local autorouting complete`),resolve(event.traces)}),activeAutorouter.on("error",event=>{debug132(`[${this.getString()}] local autorouting error: ${event.error.message}`),reject(event.error)})});activeAutorouter.on("progress",event=>{this.root?.emit("autorouting:progress",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},...event})}),activeAutorouter.start(),traces=await routingPromise}let transformedSimpleRouteJson=autorouter?.getOutputSimpleRouteJson?.();if(transformedSimpleRouteJson&&!usesPreviousStageOutput&&["fanout","single_layer_fanout"].includes(phaseAutorouterConfig.preset??"")&&routingPhasePlan.routingPcbGroupId){let synchronizedFanout=Group_syncFanoutExitsWithGlobalConnections({fanoutInputSimpleRouteJson:simpleRouteJson,fanoutOutputSimpleRouteJson:transformedSimpleRouteJson,baseSimpleRouteJson,routingPhasePlan});baseSimpleRouteJson=synchronizedFanout.baseSimpleRouteJson,transformedSimpleRouteJson=synchronizedFanout.downstreamSimpleRouteJson;for(let synchronizedPoint of synchronizedFanout.synchronizedBreakoutPoints){let breakoutPoint=db2.pcb_breakout_point.list().find(point6=>point6.pcb_group_id===synchronizedPoint.routingPcbGroupId&&point6.source_trace_id===synchronizedPoint.sourceTraceId&&Math.abs(point6.x-synchronizedPoint.previousPoint.x)<=1e-6&&Math.abs(point6.y-synchronizedPoint.previousPoint.y)<=1e-6);breakoutPoint&&db2.pcb_breakout_point.update(breakoutPoint.pcb_breakout_point_id,{x:synchronizedPoint.fanoutExitPoint.x,y:synchronizedPoint.fanoutExitPoint.y})}}let stageOutputTraces=traces;transformedSimpleRouteJson?.traces?stageOutputTraces=transformedSimpleRouteJson.traces:usesPreviousStageOutput&&(stageOutputTraces=[...simpleRouteJson.traces??[],...traces]);let outputSimpleRouteJson={...transformedSimpleRouteJson??simpleRouteJson,traces:stageOutputTraces};if(previousStageOutputSimpleRouteJson=transformedSimpleRouteJson?outputSimpleRouteJson:void 0,!cachedResult&&cacheKey&&await cacheLocalAutoroutingPhaseResult({cacheEngine,cacheKey,result:{...simpleRouteJson,traces}}),this.root?.emit("autorouting:end",{type:"autorouting:end",subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},simpleRouteJson:outputSimpleRouteJson}),autorouter?.getConnectedOffboardObstacles){let connectedOffboardObstacles=autorouter.getConnectedOffboardObstacles();createSourceTracesFromOffboardConnections({db:db2,connectedOffboardObstacles,simpleRouteJson,subcircuit_id:this.subcircuit_id})}let solver=autorouter?.solver;if(solver?.getOutputJumpers&&outputJumpers.push(...solver.getOutputJumpers()||[]),isRegionReroutePhase&&rerouteOriginalSrj){for(let trace of rerouteOriginalSrj.traces??[])trace.type==="pcb_trace"&&pcbTraceIdsToDelete.add(trace.pcb_trace_id);let reconnectedSrj=A32(rerouteOriginalSrj,{...simpleRouteJson,traces:[...simpleRouteJson.traces??[],...traces]});outputTraces.splice(0,outputTraces.length,...reconnectedSrj.traces??[])}else if(isConnectionReroutePhase){let retainedPcbTraces=outputTraces.filter(trace=>!traceMatchesRoutingPhase(trace,routingPhasePlan));outputTraces.splice(0,outputTraces.length,...getAccumulatedPcbTracesWithStageOutputReplacements({accumulatedPcbTraces:retainedPcbTraces,stageOutputPcbTraces:stageOutputTraces}))}else outputTraces.splice(0,outputTraces.length,...getAccumulatedPcbTracesWithStageOutputReplacements({accumulatedPcbTraces:outputTraces,stageOutputPcbTraces:stageOutputTraces}))}catch(error2){let{db:db22}=this.root;throw db22.pcb_autorouting_error.insert({pcb_error_id:`pcb_autorouter_error_subcircuit_${this.subcircuit_id}`,error_type:"pcb_autorouting_error",message:error2 instanceof Error?error2.message:String(error2)}),this.root?.emit("autorouting:error",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},error:{message:error2 instanceof Error?error2.message:String(error2)},simpleRouteJson}),error2}finally{autorouter?.stop()}}this._asyncAutoroutingResult={output_pcb_traces:outputTraces,output_jumpers:outputJumpers,pcb_trace_ids_to_be_replaced:[...pcbTraceIdsToDelete]},this._markDirty("PcbTraceRender")}_startAsyncAutorouting(){this._hasStartedAsyncAutorouting||(this._hasStartedAsyncAutorouting=!0,this._getAutorouterConfig().local?this._queueAsyncEffect("autorouting",async()=>this._runLocalAutorouting()):this._queueAsyncEffect("make-http-autorouting-request",async()=>this._runEffectMakeHttpAutoroutingRequest()))}doInitialPcbTraceRender(){let debug132=(0,import_debug11.default)("tscircuit:core:doInitialPcbTraceRender");if(!this.isSubcircuit||this.root?.pcbDisabled||this.root?.pcbRoutingDisabled||this.getInheritedProperty("routingDisabled")||this._isInflatedFromCircuitJson||this._isLegacyAutorouterDisabled()||this._shouldUseTraceByTraceRouting())return;if(!this._areChildSubcircuitsRouted()){debug132(`[${this.getString()}] child subcircuits are not routed, skipping async autorouting until subcircuits routed`);return}if(debug132(`[${this.getString()}] no child subcircuits to wait for, initiating async routing`),!this._hasTracesToRoute())return;let shouldSkipBecauseOfPlacementErrors=shouldSkipAutoroutingBecauseOfPlacementErrors({component:this,subcircuit:this}),shouldSkipBecauseOfTraceLengthViolations=shouldSkipAutoroutingBecauseOfTraceLengthViolations({component:this,subcircuit:this});shouldSkipBecauseOfPlacementErrors||shouldSkipBecauseOfTraceLengthViolations||this._startAsyncAutorouting()}doInitialSchematicTraceRender(){this._parsedProps.showAsSchematicBox||Group_doInitialSchematicTraceRender(this)}doInitialSchematicSheetRender(){Group_doInitialSchematicSheetRender(this)}updateSchematicSheetRender(){Group_updateSchematicSheetRender(this)}updatePcbTraceRender(){let debug132=(0,import_debug11.default)("tscircuit:core:updatePcbTraceRender");if(debug132(`[${this.getString()}] updating...`),!this.isSubcircuit||this._isInflatedFromCircuitJson||this._isLegacyAutorouterDisabled())return;if(this._shouldRouteAsync()&&this._hasTracesToRoute()&&!this._hasStartedAsyncAutorouting){if(this._areChildSubcircuitsRouted()){let shouldSkipBecauseOfPlacementErrors=shouldSkipAutoroutingBecauseOfPlacementErrors({component:this,subcircuit:this}),shouldSkipBecauseOfTraceLengthViolations=shouldSkipAutoroutingBecauseOfTraceLengthViolations({component:this,subcircuit:this});if(shouldSkipBecauseOfPlacementErrors||shouldSkipBecauseOfTraceLengthViolations)return;debug132(`[${this.getString()}] child subcircuits are now routed, starting async autorouting`),this._startAsyncAutorouting()}return}if(!this._asyncAutoroutingResult||this._shouldUseTraceByTraceRouting())return;let{db:db2}=this.root;if(this._asyncAutoroutingResult.output_simple_route_json){debug132(`[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`),this._updatePcbTraceRenderFromSimpleRouteJson();return}if(this._asyncAutoroutingResult.output_pcb_traces){debug132(`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`),this._updatePcbTraceRenderFromPcbTraces();return}}_updatePcbTraceRenderFromSimpleRouteJson(){let{db:db2}=this.root,{traces:routedTraces}=this._asyncAutoroutingResult.output_simple_route_json;if(routedTraces)for(let routedTrace of routedTraces){let cjRoute=routedTrace.route.map(point6=>point6.route_type!=="through_obstacle"?point6:{route_type:"through_pad",start:point6.start,end:point6.end,start_layer:point6.from_layer,end_layer:point6.to_layer,width:point6.width,circuitJsonMetadata:point6.circuitJsonMetadata}),pcb_trace3=db2.pcb_trace.insert({subcircuit_id:this.subcircuit_id,route:removeSrjMetadataFromPcbTraceRoute(cjRoute)});claimSrjAssignablePcbViasTraversedByRoute({db:db2,pcbTrace:pcb_trace3,routeWithSrjMetadata:cjRoute})}}_updatePcbTraceRenderFromPcbTraces(){let{output_pcb_traces,output_jumpers,pcb_trace_ids_to_be_replaced}=this._asyncAutoroutingResult;if(!output_pcb_traces)return;let{db:db2}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{holeDiameter,padDiameter}=getViaDiameterDefaults(pcbStyle2),board=db2.pcb_board.list()[0],routedViaHoleDiameter=board?.min_via_hole_diameter??holeDiameter,routedViaPadDiameter=board?.min_via_pad_diameter??padDiameter;output_jumpers&&output_jumpers.length>0&&insertAutoplacedJumpers({db:db2,output_jumpers,subcircuit_id:this.subcircuit_id}),deleteExistingPcbTracesReplacedBy({group:this,outputPcbTraces:output_pcb_traces,pcbTraceIdsToReplace:pcb_trace_ids_to_be_replaced});for(let pcb_trace3 of output_pcb_traces){if(pcb_trace3.type!=="pcb_trace")continue;pcb_trace3.subcircuit_id??(pcb_trace3.subcircuit_id=this.subcircuit_id);let cjRoute=pcb_trace3.route.map(point6=>point6.route_type!=="through_obstacle"?point6:{route_type:"through_pad",start:point6.start,end:point6.end,start_layer:point6.from_layer,end_layer:point6.to_layer,width:point6.width,circuitJsonMetadata:point6.circuitJsonMetadata}),routeSourceTraceId=getSourceTraceIdForRoutedTrace({db:db2,trace:{...pcb_trace3,route:cjRoute},subcircuit_id:this.subcircuit_id});cjRoute=ensureRouteStartsAtSourceTraceStart({db:db2,route:cjRoute,routeThicknessMode:pcb_trace3.route_thickness_mode,sourceTraceId:routeSourceTraceId}),pcb_trace3.route=cjRoute;let segments=splitPcbTracesOnJumperSegments(cjRoute);segments===null&&(segments=[cjRoute]);let processedSegments=addPortIdsToTracesAtJumperPads(segments,db2);for(let segment2 of processedSegments)if(segment2.length>0){let circuitJsonSegment=removeSrjMetadataFromPcbTraceRoute(segment2),sourceTraceId=getSourceTraceIdForRoutedTrace({db:db2,trace:{...pcb_trace3,route:circuitJsonSegment},subcircuit_id:this.subcircuit_id}),insertedPcbTrace=db2.pcb_trace.insert({...pcb_trace3,source_trace_id:sourceTraceId,route:circuitJsonSegment});claimSrjAssignablePcbViasTraversedByRoute({db:db2,pcbTrace:insertedPcbTrace,routeWithSrjMetadata:segment2})}}for(let pcb_trace3 of output_pcb_traces)if(pcb_trace3.type!=="pcb_via"&&pcb_trace3.type==="pcb_trace"){let sourceTraceId=getSourceTraceIdForRoutedTrace({db:db2,trace:pcb_trace3,subcircuit_id:this.subcircuit_id}),{connection_name:inputConnectionName}=pcb_trace3,subcircuitConnectivityMapKey;if(sourceTraceId&&(subcircuitConnectivityMapKey=db2.source_trace.get(sourceTraceId)?.subcircuit_connectivity_map_key),!subcircuitConnectivityMapKey&&inputConnectionName){let sourceNet=db2.source_net.get(inputConnectionName);sourceNet&&(subcircuitConnectivityMapKey=sourceNet.subcircuit_connectivity_map_key)}for(let point6 of pcb_trace3.route)if(point6.route_type==="via"){let routedViaPoint=point6,fromLayer=point6.from_layer,toLayer=point6.to_layer;db2.pcb_via.insert({pcb_trace_id:pcb_trace3.pcb_trace_id,x:point6.x,y:point6.y,hole_diameter:routedViaPoint.via_hole_diameter??routedViaPoint.hole_diameter??routedViaHoleDiameter,outer_diameter:routedViaPoint.via_diameter??routedViaPoint.outer_diameter??routedViaPadDiameter,layers:getViaSpanLayers({fromLayer,toLayer,layerCount:this._getSubcircuitLayerCount()}),from_layer:fromLayer,to_layer:toLayer,subcircuit_id:this.subcircuit_id,pcb_group_id:this.pcb_group_id??void 0,subcircuit_connectivity_map_key:subcircuitConnectivityMapKey})}}}doInitialSchematicComponentRender(){if(this.root?.schematicDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,schematic_group3=db2.schematic_group.insert({is_subcircuit:this.isSubcircuit,subcircuit_id:this.subcircuit_id,name:this.name,center:this._getGlobalSchematicPositionBeforeLayout(),width:0,height:0,schematic_component_ids:[],source_group_id:this.source_group_id,show_as_schematic_box:props.showAsSchematicBox??!1});this.schematic_group_id=schematic_group3.schematic_group_id,props.showAsSchematicBox&&Group_doInitialSchematicBoxComponentRender(this);for(let child of this.getDescendants())child.getGroup()?.source_group_id===this.source_group_id&&(child._parsedProps?.showAsSchematicBox||child.schematic_component_id&&db2.schematic_component.update(child.schematic_component_id,{schematic_group_id:schematic_group3.schematic_group_id}))}_getSchematicLayoutMode(){let props=this._parsedProps,schAutoLayoutEnabled=props.schAutoLayoutEnabled??!1;if(props.schLayout?.layoutMode==="none"||props.schLayout?.layoutMode==="relative")return"relative";if(props.schLayout?.matchAdapt)return"match-adapt";if(props.schLayout?.flex)return"flex";if(props.schLayout?.grid)return"grid";if(props.schMatchAdapt)return"match-adapt";if(props.schFlex)return"flex";if(props.schGrid)return"grid";if(props.matchAdapt)return"match-adapt";if(props.flex)return"flex";if(props.grid)return"grid";if(props.relative||props.schRelative)return"relative";let anyLayoutChildHasSchCoords=this.children.some(child=>{let cProps=child._parsedProps;return(child.source_component_id!==null||child.source_group_id!==null)&&(cProps?.schX!==void 0||cProps?.schY!==void 0)}),hasManualEdits=(props.manualEdits?.schematic_placements?.length??0)>0;return schAutoLayoutEnabled&&!hasManualEdits||!anyLayoutChildHasSchCoords&&!hasManualEdits?"match-adapt":"relative"}doInitialSchematicLayout(){if(this._parsedProps.showAsSchematicBox){this._insertSchematicBorder();return}if(this.children.some(c3=>c3.source_component_id!==null&&c3._parsedProps?.schSectionName!==void 0)){this._doInitialSchematicLayoutSections(),this._insertSchematicBorder();return}let schematicLayoutMode=this._getSchematicLayoutMode();schematicLayoutMode==="match-adapt"&&this._doInitialSchematicLayoutMatchpack(),schematicLayoutMode==="grid"&&this._doInitialSchematicLayoutGrid(),schematicLayoutMode==="flex"&&this._doInitialSchematicLayoutFlex(),this._insertSchematicBorder()}_doInitialSchematicLayoutSections(){Group_doInitialSchematicLayoutSections(this)}_doInitialSchematicLayoutMatchAdapt(){Group_doInitialSchematicLayoutMatchAdapt(this)}_doInitialSchematicLayoutMatchpack(){Group_doInitialSchematicLayoutMatchPack(this)}_doInitialSchematicLayoutGrid(){Group_doInitialSchematicLayoutGrid(this)}_doInitialSchematicLayoutFlex(){Group_doInitialSchematicLayoutFlex(this)}_getPcbLayoutMode(){let props=this._parsedProps,rawProps=this.props;if(this._isInflatedFromCircuitJson||props.pcbRelative)return"none";if(props.pcbLayout?.matchAdapt)return"match-adapt";if(props.pcbLayout?.flex)return"flex";if(props.pcbLayout?.grid)return"grid";if(props.pcbLayout?.pack)return"pack";if(props.pcbFlex)return"flex";if(props.pcbGrid)return"grid";if(props.pcbPack||props.pack)return"pack";if(props.matchAdapt)return"match-adapt";if(props.flex)return"flex";if(props.grid)return"grid";let groupHasCoords=props.pcbX!==void 0||props.pcbY!==void 0||props.pcbLeftEdgeX!==void 0||props.pcbRightEdgeX!==void 0||props.pcbTopEdgeY!==void 0||props.pcbBottomEdgeY!==void 0||rawProps.pcbLeftEdgeX!==void 0||rawProps.pcbRightEdgeX!==void 0||rawProps.pcbTopEdgeY!==void 0||rawProps.pcbBottomEdgeY!==void 0,hasManualEdits=(props.manualEdits?.pcb_placements?.length??0)>0,unpositionedDirectChildrenCount=this.children.reduce((count,child)=>{if(!child.pcb_component_id&&!child.pcb_group_id)return count;let childProps=child._parsedProps,rawChildProps=child.props,hasCoords=childProps?.pcbX!==void 0||childProps?.pcbY!==void 0||childProps?.pcbLeftEdgeX!==void 0||childProps?.pcbRightEdgeX!==void 0||childProps?.pcbTopEdgeY!==void 0||childProps?.pcbBottomEdgeY!==void 0||rawChildProps?.pcbLeftEdgeX!==void 0||rawChildProps?.pcbRightEdgeX!==void 0||rawChildProps?.pcbTopEdgeY!==void 0||rawChildProps?.pcbBottomEdgeY!==void 0;return count+(hasCoords?0:1)},0);return!hasManualEdits&&unpositionedDirectChildrenCount>1?"pack":"none"}doInitialPcbLayout(){if(this.root?.pcbDisabled)return;if(this.pcb_group_id){let{db:db2}=this.root,props=this._parsedProps;if(props.pcbX!==void 0||props.pcbY!==void 0){let parentGroup=this.parent?.getGroup?.(),pcbParentGroupId=parentGroup?.pcb_group_id?db2.pcb_group.get(parentGroup.pcb_group_id)?.pcb_group_id:void 0,positionedRelativeToBoardId=pcbParentGroupId?void 0:this._getBoard()?.pcb_board_id??void 0;db2.pcb_group.update(this.pcb_group_id,{position_mode:"relative_to_group_anchor",positioned_relative_to_pcb_group_id:pcbParentGroupId,positioned_relative_to_pcb_board_id:positionedRelativeToBoardId,display_offset_x:props.pcbX,display_offset_y:props.pcbY})}}let pcbLayoutMode=this._getPcbLayoutMode();pcbLayoutMode==="grid"?this._doInitialPcbLayoutGrid():pcbLayoutMode==="pack"?this._doInitialPcbLayoutPack():pcbLayoutMode==="flex"&&this._doInitialPcbLayoutFlex()}_doInitialPcbLayoutGrid(){Group_doInitialPcbLayoutGrid(this)}_doInitialPcbLayoutPack(){Group_doInitialPcbLayoutPack(this)}_doInitialPcbLayoutFlex(){Group_doInitialPcbLayoutFlex(this)}_insertSchematicBorder(){if(this.root?.schematicDisabled)return;let{db:db2}=this.root,props=this._parsedProps;if(!props.border)return;let width=typeof props.schWidth=="number"?props.schWidth:void 0,height=typeof props.schHeight=="number"?props.schHeight:void 0,paddingGeneral=typeof props.schPadding=="number"?props.schPadding:0,paddingLeft=typeof props.schPaddingLeft=="number"?props.schPaddingLeft:paddingGeneral,paddingRight=typeof props.schPaddingRight=="number"?props.schPaddingRight:paddingGeneral,paddingTop=typeof props.schPaddingTop=="number"?props.schPaddingTop:paddingGeneral,paddingBottom=typeof props.schPaddingBottom=="number"?props.schPaddingBottom:paddingGeneral,schematicGroup=this.schematic_group_id?db2.schematic_group.get(this.schematic_group_id):null;if(schematicGroup&&(width===void 0&&typeof schematicGroup.width=="number"&&(width=schematicGroup.width),height===void 0&&typeof schematicGroup.height=="number"&&(height=schematicGroup.height)),width===void 0||height===void 0)return;let center2=schematicGroup?.center??this._getGlobalSchematicPositionBeforeLayout(),left=center2.x-width/2-paddingLeft,bottom=center2.y-height/2-paddingBottom,finalWidth=width+paddingLeft+paddingRight,finalHeight=height+paddingTop+paddingBottom;db2.schematic_box.insert({width:finalWidth,height:finalHeight,x:left,y:bottom,is_dashed:props.border?.dashed??!1})}_determineSideFromPosition(port,component){if(!port.center||!component.center)return"left";let dx3=port.center.x-component.center.x,dy3=port.center.y-component.center.y;return Math.abs(dx3)>Math.abs(dy3)?dx3>0?"right":"left":dy3>0?"bottom":"top"}_calculateSchematicBounds(boxes){if(boxes.length===0)return{minX:0,maxX:0,minY:0,maxY:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let box2 of boxes)minX=Math.min(minX,box2.centerX),maxX=Math.max(maxX,box2.centerX),minY=Math.min(minY,box2.centerY),maxY=Math.max(maxY,box2.centerY);let padding=2;return{minX:minX-padding,maxX:maxX+padding,minY:minY-padding,maxY:maxY+padding}}_getAutorouterConfig(){let autorouter=this._parsedProps.autorouter||this.getInheritedProperty("autorouter");return getPresetAutoroutingConfig(autorouter,this.root?.platform)}_isLegacyAutorouterDisabled(){return getDisabledLegacyAutorouterPreset(this)!==null}_isLaserPrefabAutorouter(autorouterConfig2=this._getAutorouterConfig()){let autorouterProp2=this.props.autorouter,normalize4=value=>value?.replace(/-/g,"_")??value;return autorouterConfig2.preset==="laser_prefab"?!0:typeof autorouterProp2=="string"?normalize4(autorouterProp2)==="laser_prefab":typeof autorouterProp2=="object"&&autorouterProp2?normalize4(autorouterProp2.preset)==="laser_prefab":!1}_isAutoJumperAutorouter(autorouterConfig2=this._getAutorouterConfig()){let autorouterProp2=this.props.autorouter,normalize4=value=>value?.replace(/-/g,"_")??value;return autorouterConfig2.preset==="auto_jumper"?!0:typeof autorouterProp2=="string"?normalize4(autorouterProp2)==="auto_jumper":typeof autorouterProp2=="object"&&autorouterProp2?normalize4(autorouterProp2.preset)==="auto_jumper":!1}_getSubcircuitLayerCount(){let layers=this.getInheritedProperty("layers");return typeof layers=="number"?layers:2}_shouldUseTraceByTraceRouting(){return getDisabledLegacyGroupAutorouterPreset(this)?!1:this._getAutorouterConfig().groupMode==="sequential-trace"}doInitialPcbDesignRuleChecks(){if(this.root?.pcbDisabled||this._isLegacyAutorouterDisabled()||this.root?.pcbRoutingDisabled||this.getInheritedProperty("routingDisabled"))return;let{db:db2}=this.root;if(this.isSubcircuit){let immediateChildrenByName=new Map;for(let child of this.children)if(!child.isSubcircuit&&child._parsedProps.name){let components=immediateChildrenByName.get(child._parsedProps.name)||[];components.push(child),immediateChildrenByName.set(child._parsedProps.name,components)}for(let[name,components]of immediateChildrenByName.entries()){if(components.length<=1)continue;let sameNamedTraces=components.filter(child=>child instanceof Trace),duplicateNameIsOnlyTraces=sameNamedTraces.length===components.length,mutuallyConnectedTraceKeys=sameNamedTraces.map(trace=>trace.subcircuit_connectivity_map_key),sameNamedTracesAreMutuallyConnected=duplicateNameIsOnlyTraces&&mutuallyConnectedTraceKeys.every(Boolean)&&new Set(mutuallyConnectedTraceKeys).size===1;if(!duplicateNameIsOnlyTraces||!sameNamedTracesAreMutuallyConnected){let displaySubcircuitName=this.name||"unnamed",message=duplicateNameIsOnlyTraces?`Trace "${name}" in subcircuit "${displaySubcircuitName}" shares a name with another trace, but the traces are not mutually connected. Same-named traces must have the same subcircuit connectivity map key.`:`Multiple immediate children found with name "${name}" in subcircuit "${displaySubcircuitName}". Names must be unique.`;db2.pcb_trace_error.insert({error_type:"pcb_trace_error",message,source_trace_id:"",pcb_trace_id:"",pcb_component_ids:components.map(c3=>c3.pcb_component_id).filter(Boolean),pcb_port_ids:[]})}}}Group_doInitialStandaloneSubcircuitPcbDesignRuleChecks(this)}doInitialSchematicReplaceNetLabelsWithSymbols(){if(this.root?.schematicDisabled||!this.isSubcircuit)return;let{db:db2}=this.root,subtree=db2;for(let nl3 of subtree.schematic_net_label.list()){let net=subtree.source_net.get(nl3.source_net_id),text=nl3.text||net?.name||"",isGroundNet=net?.is_ground||GROUND_NET_REGEX.test(text),isPowerNet=net?.is_power||POWER_NET_REGEX.test(text);if(nl3.anchor_side==="top"&&isGroundNet){subtree.schematic_net_label.update(nl3.schematic_net_label_id,{symbol_name:"rail_down"});continue}nl3.anchor_side==="bottom"&&isPowerNet&&subtree.schematic_net_label.update(nl3.schematic_net_label_id,{symbol_name:"rail_up"})}}doInitialSimulationSpiceEngineRender(){Group_doInitialSimulationSpiceEngineRender(this)}doInitialPcbComponentAnchorAlignment(){Group_doInitialPcbComponentAnchorAlignment(this)}updatePcbComponentAnchorAlignment(){this.doInitialPcbComponentAnchorAlignment()}doInitialPcbCalcPlacementResolution(){Group_doInitialPcbCalcPlacementResolution(this)}updatePcbCalcPlacementResolution(){this.doInitialPcbCalcPlacementResolution()}_getMinimumFlexContainerSize(){return super._getMinimumFlexContainerSize()}_repositionOnPcb(position4){return super._repositionOnPcb(position4)}};function inflateSourceGroup(sourceGroup,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbGroup=injectionDb.pcb_group.getWhere({source_group_id:sourceGroup.source_group_id}),groupProps2={name:sourceGroup.name??`inflated_group_${sourceGroup.source_group_id}`};if(pcbGroup?.position_mode==="relative_to_group_anchor"&&pcbGroup.anchor_position){let baseAnchor={x:0,y:0};if(sourceGroup.parent_source_group_id){let parentPcbGroup=injectionDb.pcb_group.getWhere({source_group_id:sourceGroup.parent_source_group_id});parentPcbGroup?.anchor_position&&(baseAnchor=parentPcbGroup.anchor_position)}groupProps2.pcbX=pcbGroup.anchor_position.x-baseAnchor.x,groupProps2.pcbY=pcbGroup.anchor_position.y-baseAnchor.y}pcbGroup?.anchor_alignment&&(groupProps2.pcbAnchorAlignment=pcbGroup.anchor_alignment);let group=new Group5(groupProps2);return group._isInflatedFromCircuitJson=!0,group.source_group_id=sourceGroup.source_group_id,groupsMap&&groupsMap.set(sourceGroup.source_group_id,group),sourceGroup.parent_source_group_id&&groupsMap?.has(sourceGroup.parent_source_group_id)?groupsMap.get(sourceGroup.parent_source_group_id).add(group):subcircuit.add(group),group}var Inductor2=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"_adjustSilkscreenTextAutomatically",!0)}get config(){return{componentName:"Inductor",schematicSymbolName:this.props.symbolName??"inductor",zodProps:inductorProps,sourceFtype:FTYPE.simple_inductor}}_getSchematicSymbolDisplayValue(){return`${formatSiUnit(this._parsedProps.inductance)}H`}initPorts(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["cathode","neg","right"]}})}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({name:this.name,ftype:FTYPE.simple_inductor,inductance:this.props.inductance,max_current_rating:props.maxCurrentRating===void 0?void 0:parseAndConvertSiUnit(props.maxCurrentRating,"A").value,display_inductance:this._getSchematicSymbolDisplayValue(),supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceInductor(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),inductor=new Inductor2({name:sourceElm.name,inductance:sourceElm.inductance,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:inductor});footprint&&inductor.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(inductor):subcircuit.add(inductor)}var Led=class extends NormalComponent3{get config(){let symbolMap={laser:"laser_diode"},variantSymbol=this.props.laser?"laser":null;return{schematicSymbolName:variantSymbol?symbolMap[variantSymbol]:this.props.symbolName??"led",componentName:"Led",zodProps:ledProps,sourceFtype:"simple_led"}}initPorts(){let hasFootprintChild=this.children.some(child=>child.componentName==="Footprint"),footprint=this.resolveFootprint(),hasPinLabels=!!this._resolvePinLabels(),shouldAddDefaultAliases=!hasPinLabels&&!hasFootprintChild&&(!footprint||isFootprinterString(footprint));super.initPorts({pinCount:2,ignoreSymbolPorts:!hasPinLabels&&!shouldAddDefaultAliases,additionalAliases:{pin1:shouldAddDefaultAliases?["anode","pos","left"]:[],pin2:shouldAddDefaultAliases?["cathode","neg","right"]:[]}})}_getSchematicSymbolDisplayValue(){return this._parsedProps.schDisplayValue||this._parsedProps.color||void 0}getFootprinterString(){let baseFootprint=super.getFootprinterString();return baseFootprint&&this.props.color?`${baseFootprint}_color(${this.props.color})`:baseFootprint}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_led",name:this.name,wave_length:props.wavelength,color:props.color,symbol_display_value:this._getSchematicSymbolDisplayValue(),manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!1,display_name:props.displayName});this.source_component_id=source_component.source_component_id}get pos(){return this.portMap.pos}get anode(){return this.portMap.anode}get neg(){return this.portMap.neg}get cathode(){return this.portMap.cathode}};function inflateSourceLed(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),led2=new Led({name:sourceElm.name,color:sourceElm.color,wavelength:sourceElm.wavelength??sourceElm.wave_length,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:led2});footprint&&led2.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(led2):subcircuit.add(led2)}var possibleOrientations=[{gate:"left",drain:"top",source:"bottom"},{gate:"left",drain:"bottom",source:"top"},{gate:"right",drain:"top",source:"bottom"},{gate:"right",drain:"bottom",source:"top"},{gate:"top",drain:"left",source:"right"},{gate:"top",drain:"right",source:"left"},{gate:"bottom",drain:"left",source:"right"},{gate:"bottom",drain:"right",source:"left"}],getBaselineOrientation=rotation42=>{let normalizedRotation=(rotation42%360+360)%360;if(normalizedRotation%90!==0)throw new Error(`Schematic rotation ${rotation42} is not supported for Mosfet`);return[{gate:"left",drain:"top",source:"bottom"},{gate:"top",drain:"right",source:"left"},{gate:"right",drain:"bottom",source:"top"},{gate:"bottom",drain:"left",source:"right"}][normalizedRotation/90]},getRequestedOrientation=props=>{let requestedSides={drain:props.symbolDrainSide,source:props.symbolSourceSide,gate:props.symbolGateSide},baseline=getBaselineOrientation(Number(props.schRotation??0)),matchingOrientations=possibleOrientations.filter(orientation4=>Object.keys(requestedSides).every(portName=>requestedSides[portName]===void 0||requestedSides[portName]===orientation4[portName]));if(matchingOrientations.length===0){let requestedDescription=Object.entries(requestedSides).filter(([,side])=>side!==void 0).map(([portName,side])=>`${portName}=${side}`).join(", ");throw new Error(`Invalid MOSFET symbol port side combination (${requestedDescription}). The gate must be perpendicular to the drain and source, and the drain and source must be opposite.`)}return matchingOrientations.sort((a6,b6)=>{let score=orientation4=>Object.keys(baseline).filter(portName=>orientation4[portName]!==baseline[portName]).length;return score(a6)-score(b6)})[0]},getMosfetSchematicSymbolName=props=>{let mosfetMode=props.mosfetMode==="depletion"?"d":"e",baseSymbolName=`${props.channelType}_channel_${mosfetMode}_mosfet_transistor`;if(!(props.symbolDrainSide!==void 0||props.symbolSourceSide!==void 0||props.symbolGateSide!==void 0))return baseSymbolName;let{gate,drain}=getRequestedOrientation(props);return`${baseSymbolName}_gate_${gate}_drain_${drain}`},Mosfet2=class extends NormalComponent3{get config(){return{componentName:"Mosfet",schematicSymbolName:this.props.symbolName??getMosfetSchematicSymbolName(this.props),zodProps:mosfetProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_mosfet",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,mosfet_mode:props.mosfetMode,channel_type:props.channelType,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceMosfet(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),mosfet=new Mosfet2({name:sourceElm.name,channelType:sourceElm.channel_type,mosfetMode:sourceElm.mosfet_mode,manufacturerPartNumber:sourceElm.manufacturer_part_number,supplierPartNumbers:sourceElm.supplier_part_numbers??void 0,displayName:sourceElm.display_name,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:mosfet});footprint&&mosfet.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(mosfet):subcircuit.add(mosfet)}function inflateSourcePort(sourcePort,inflatorContext){let{injectionDb,subcircuit}=inflatorContext;if(sourcePort.source_component_id!==null)return;let pcbPortFromInjection=injectionDb.pcb_port.getWhere({source_port_id:sourcePort.source_port_id}),port=new Port({name:sourcePort.name,pinNumber:sourcePort.pin_number});subcircuit.add(port),port.source_port_id=sourcePort.source_port_id;let root=subcircuit.root;if(root&&pcbPortFromInjection){let{db:db2}=root,pcb_port3=db2.pcb_port.insert({pcb_component_id:void 0,layers:pcbPortFromInjection.layers,subcircuit_id:subcircuit.subcircuit_id??void 0,pcb_group_id:subcircuit.getGroup()?.pcb_group_id??void 0,x:pcbPortFromInjection.x,y:pcbPortFromInjection.y,source_port_id:sourcePort.source_port_id,is_board_pinout:!1});port.pcb_port_id=pcb_port3.pcb_port_id}}var PushButton=class extends NormalComponent3{get config(){return{componentName:"PushButton",schematicSymbolName:this.props.symbolName??"push_button_normally_open_momentary",zodProps:pushButtonProps,sourceFtype:FTYPE.simple_push_button}}get defaultInternallyConnectedPinNames(){return[]}initPorts(){super.initPorts({pinCount:2,ignoreSymbolPorts:!0});let symbol=hc[this._getSchematicSymbolNameOrThrow()],symPort1=symbol.ports.find(p3=>p3.labels.includes("1")),symPort2=symbol.ports.find(p3=>p3.labels.includes("2")),ports=this.selectAll("port"),pin1Port=ports.find(p3=>p3.props.pinNumber===1),pin2Port=ports.find(p3=>p3.props.pinNumber===2),pin3Port=ports.find(p3=>p3.props.pinNumber===3),pin4Port=ports.find(p3=>p3.props.pinNumber===4),{internallyConnectedPins}=this._parsedProps;pin1Port.schematicSymbolPortDef=symPort1,(!internallyConnectedPins||internallyConnectedPins.length===0)&&(pin2Port.schematicSymbolPortDef=symPort2);for(let[pn3,port]of[[2,pin2Port],[3,pin3Port],[4,pin4Port]]){let internallyConnectedRow=internallyConnectedPins?.find(([pin1,pin2])=>pin1===`pin${pn3}`||pin2===`pin${pn3}`);if(!internallyConnectedRow){port.schematicSymbolPortDef=symPort2;break}(internallyConnectedRow?.[0]===`pin${pn3}`?internallyConnectedRow[1]:internallyConnectedRow?.[0])!=="pin1"&&(port.schematicSymbolPortDef=symPort2)}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({name:this.name,ftype:FTYPE.simple_push_button,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourcePushButton(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),pushButton=new PushButton({name:sourceElm.name,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:pushButton});footprint&&pushButton.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(pushButton):subcircuit.add(pushButton)}var Resistor2=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"_adjustSilkscreenTextAutomatically",!0)}get config(){return{componentName:"Resistor",schematicSymbolName:this.props.symbolName??"boxresistor",zodProps:resistorProps,sourceFtype:"simple_resistor"}}initPorts(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["cathode","neg","right"]}})}_getSchematicSymbolDisplayValue(){return`${formatSiUnit(this._parsedProps.resistance)}\u03A9`}doInitialCreateNetsFromProps(){this._createNetsFromProps([this.props.pullupFor,this.props.pullupTo,this.props.pulldownFor,this.props.pulldownTo,...this._getNetsFromConnectionsProp()])}doInitialCreateTracesFromProps(){this.props.pullupFor&&this.props.pullupTo&&(this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.pullupFor})),this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.pullupTo}))),this.props.pulldownFor&&this.props.pulldownTo&&(this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.pulldownFor})),this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.pulldownTo}))),this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_resistor",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,resistance:props.resistance,display_resistance:this._getSchematicSymbolDisplayValue(),are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceResistor(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),resistor=new Resistor2({name:sourceElm.name,resistance:sourceElm.resistance,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:resistor});footprint&&resistor.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(resistor):subcircuit.add(resistor)}function hasSimProps(props){return props.simSwitchFrequency!==void 0||props.simCloseAt!==void 0||props.simOpenAt!==void 0||props.simStartClosed!==void 0||props.simStartOpen!==void 0}var Switch=class extends NormalComponent3{_getSwitchType(){let props=this._parsedProps;return props?props.dpdt?"dpdt":props.spst?"spst":props.spdt?"spdt":props.dpst?"dpst":props.type??"spst":"spst"}get config(){let switchType=this._getSwitchType(),isNormallyClosed=this._parsedProps?.isNormallyClosed??!1,symbolMap={spst:isNormallyClosed?"spst_normally_closed_switch":"spst_switch",spdt:isNormallyClosed?"spdt_normally_closed_switch":"spdt_switch",dpst:isNormallyClosed?"dpst_normally_closed_switch":"dpst_switch",dpdt:isNormallyClosed?"dpdt_normally_closed_switch":"dpdt_switch"};return{componentName:"Switch",schematicSymbolName:this.props.symbolName??symbolMap[switchType],zodProps:switchProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db:db2}=this.root,props=this._parsedProps??{},source_component=db2.source_component.insert({ftype:"simple_switch",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:this._getSwitchType()==="spst",display_name:props?.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{_parsedProps:props}=this;if(!hasSimProps(props))return;let{db:db2}=this.root,simulationSwitch={type:"simulation_switch",source_component_id:this.source_component_id||""};props.simSwitchFrequency!==void 0&&(simulationSwitch.switching_frequency=frequency.parse(props.simSwitchFrequency)),props.simCloseAt!==void 0&&(simulationSwitch.closes_at=ms.parse(props.simCloseAt)),props.simOpenAt!==void 0&&(simulationSwitch.opens_at=ms.parse(props.simOpenAt)),props.simStartOpen!==void 0&&(simulationSwitch.starts_closed=!props.simStartOpen),props.simStartClosed!==void 0&&(simulationSwitch.starts_closed=props.simStartClosed),db2.simulation_switch.insert(simulationSwitch)}},getImportedSwitchProps=(sourceElm,inflatorContext)=>{let sourcePorts=inflatorContext.injectionDb.source_port.list().filter(port=>port.source_component_id===sourceElm.source_component_id),pinLabels={},highestPinNumber=0;for(let sourcePort of sourcePorts){let pinNumber=sourcePort.pin_number;if(pinNumber==null)continue;highestPinNumber=Math.max(highestPinNumber,pinNumber);let labels=Array.from(new Set([sourcePort.name,...sourcePort.port_hints??[]].filter(label=>typeof label=="string"&&label.length>0)));labels.length>0&&(pinLabels[`pin${pinNumber}`]=labels)}let type="spst";return highestPinNumber>=5?type="dpdt":highestPinNumber===4?type="dpst":highestPinNumber===3&&(type="spdt"),{type,pinLabels:Object.keys(pinLabels).length>0?pinLabels:void 0}};function inflateSourceSwitch(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),importedSwitchProps=getImportedSwitchProps(sourceElm,inflatorContext),switchComponent=new Switch({name:sourceElm.name,displayName:sourceElm.display_name,...importedSwitchProps,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:switchComponent});footprint&&switchComponent.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(switchComponent):subcircuit.add(switchComponent)}function pcbTraceRouteToPcbPath(route){if(route.length<=2)return[];let firstPoint=route[0],lastPoint=route[route.length-1];return route.slice(1,-1).filter(point6=>{let position4=getRoutePointPosition2(point6),firstPosition=getRoutePointPosition2(firstPoint),lastPosition=getRoutePointPosition2(lastPoint),isSameAsFirst=position4.x===firstPosition.x&&position4.y===firstPosition.y,isSameAsLast=position4.x===lastPosition.x&&position4.y===lastPosition.y;return!isSameAsFirst&&!isSameAsLast}).map(point6=>{if(point6.route_type==="via")return{x:point6.x,y:point6.y,via:!0,fromLayer:point6.from_layer,toLayer:point6.to_layer};let position4=getRoutePointPosition2(point6);return{x:position4.x,y:position4.y}})}var getSelectorPath=(component,inflatorContext)=>{let{injectionDb,subcircuit,groupsMap}=inflatorContext,path_parts=[],currentGroupId=component.source_group_id;for(;currentGroupId&&currentGroupId!==subcircuit.source_group_id;){let sourceGroup=injectionDb.source_group.get(currentGroupId),groupInstance=groupsMap?.get(currentGroupId);if(!sourceGroup||!groupInstance)break;let groupName=groupInstance.props.name??groupInstance.fallbackUnassignedName;path_parts.unshift(`.${groupName}`),currentGroupId=sourceGroup.parent_source_group_id}return path_parts.push(`.${component.name}`),path_parts.join(" > ")};function inflateSourceTrace(sourceTrace,inflatorContext){let{injectionDb,subcircuit}=inflatorContext,connectedSelectors=[];for(let sourcePortId of sourceTrace.connected_source_port_ids){let sourcePort=injectionDb.source_port.get(sourcePortId);if(!sourcePort)continue;let selector;if(sourcePort.source_component_id){let sourceComponent=injectionDb.source_component.get(sourcePort.source_component_id);sourceComponent&&(selector=`${getSelectorPath({name:sourceComponent.name,source_group_id:sourceComponent.source_group_id},inflatorContext)} > .${sourcePort.name}`)}else selector=`.${sourcePort.name}`;selector&&connectedSelectors.push(selector)}for(let sourceNetId of sourceTrace.connected_source_net_ids){let sourceNet=injectionDb.source_net.get(sourceNetId);sourceNet&&connectedSelectors.push(`net.${sourceNet.name}`)}if(connectedSelectors.length<2)return;let pcbTraces=injectionDb.pcb_trace.list().filter(trace2=>trace2.source_trace_id===sourceTrace.source_trace_id),pcbTrace=pcbTraces[0],pcbPath2;pcbTrace&&(pcbPath2=pcbTraceRouteToPcbPath(pcbTrace.route));let traceWidth=sourceTrace.min_trace_thickness;if(!traceWidth&&pcbTrace?.route){let wirePoint=pcbTrace.route.find(pt3=>pt3.route_type==="wire");wirePoint&&wirePoint.route_type==="wire"&&(traceWidth=wirePoint.width)}let traceProps2={path:connectedSelectors};traceWidth!==void 0&&(traceProps2.thickness=traceWidth),pcbPath2&&pcbPath2.length>0?traceProps2.pcbPath=pcbPath2:!pcbTrace&&sourceTrace.connected_source_port_ids.length===2&&sourceTrace.connected_source_net_ids.length===0&&(traceProps2.pcbStraightLine=!0);let trace=new Trace(traceProps2);trace._inflatedPcbTraces=pcbTraces.length>0?pcbTraces:void 0,trace._inflatedPcbVias=pcbTrace?injectionDb.pcb_via.list().filter(via=>pcbTraces.some(trace2=>via.pcb_trace_id===trace2.pcb_trace_id)):void 0,subcircuit.add(trace)}var SHORT_ALIASES={collector:["c"],base:["b"],emitter:["e"]},Transistor=class extends NormalComponent3{get config(){let baseSymbolName=this.props.type==="npn"?"npn_bipolar_transistor":"pnp_bipolar_transistor";return{componentName:"Transistor",schematicSymbolName:this.props.symbolName??baseSymbolName,zodProps:transistorProps,sourceFtype:"simple_transistor",shouldRenderAsSchematicBox:!1}}initPorts(){let additionalAliases={},symbol=this.getSchematicSymbol();for(let symPort of symbol?.ports??[]){let pinNumber=getPinNumberFromLabels(symPort.labels);if(pinNumber)for(let label of symPort.labels){let shortAliases=SHORT_ALIASES[label];shortAliases&&(additionalAliases[`pin${pinNumber}`]=shortAliases)}}super.initPorts({pinCount:3,additionalAliases})}get collector(){return this.portMap.collector}get base(){return this.portMap.base}get emitter(){return this.portMap.emitter}doInitialCreateNetsFromProps(){this._createNetsFromProps([...this._getNetsFromConnectionsProp()])}doInitialCreateTracesFromProps(){this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_transistor",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,transistor_type:props.type,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceTransistor(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),transistor=new Transistor({name:sourceElm.name,type:sourceElm.transistor_type,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:transistor});footprint&&transistor.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(transistor):subcircuit.add(transistor)}function inflateStandalonePcbPrimitives(inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,standalonePrimitiveTypes=["pcb_silkscreen_rect","pcb_silkscreen_circle","pcb_silkscreen_line","pcb_silkscreen_path","pcb_silkscreen_text","pcb_fabrication_note_text","pcb_fabrication_note_path","pcb_fabrication_note_rect","pcb_note_text","pcb_note_rect","pcb_note_path","pcb_note_line","pcb_via","pcb_hole","pcb_plated_hole","pcb_cutout"],standalonePrimitives=injectionDb.toArray().filter(elm=>{if(!standalonePrimitiveTypes.includes(elm.type))return!1;if(elm.type==="pcb_via"){if(!elm.pcb_trace_id)return!0;let pcbTrace=injectionDb.pcb_trace.get(elm.pcb_trace_id),sourceTraceId=pcbTrace?.source_trace_id;return!(sourceTraceId&&injectionDb.source_trace.get(sourceTraceId)&&pcbTrace?.route.some(point6=>point6.route_type==="via"&&Math.abs(point6.x-elm.x)<1e-4&&Math.abs(point6.y-elm.y)<1e-4))}return elm.type==="pcb_cutout"?!0:"pcb_component_id"in elm&&(elm.pcb_component_id===null||elm.pcb_component_id===void 0)});if(standalonePrimitives.length===0)return;let components=createComponentsFromCircuitJson({componentName:"",componentRotation:"0deg"},standalonePrimitives);for(let component of components)subcircuit.add(component)}var inflateCircuitJson=(target,circuitJson,children)=>{if(!circuitJson)return;let injectionDb=cju_default(circuitJson);if(circuitJson&&children?.length>0)throw new Error("Component cannot have both circuitJson and children");let inflationCtx={injectionDb,subcircuit:target,groupsMap:new Map},sourceGroups=injectionDb.source_group.list(),renderedGroupIds=new Set,groupsToRender=[...sourceGroups];for(;groupsToRender.length>0;){let groupIndex=groupsToRender.findIndex(g4=>!g4.parent_source_group_id||renderedGroupIds.has(g4.parent_source_group_id));if(groupIndex===-1){let remainingIds=groupsToRender.map(g4=>g4.source_group_id).join(", ");throw new Error(`Cannot inflate source_groups: cyclic dependency or missing parent detected. Remaining groups: ${remainingIds}`)}let groupToRender=groupsToRender[groupIndex];inflateSourceGroup(groupToRender,inflationCtx),renderedGroupIds.add(groupToRender.source_group_id),groupsToRender.splice(groupIndex,1)}let pcbBoards=injectionDb.pcb_board.list();for(let pcbBoard of pcbBoards)inflatePcbBoard(pcbBoard,inflationCtx);let sourceComponents=injectionDb.source_component.list();for(let sourceComponent of sourceComponents)switch(sourceComponent.ftype){case"simple_resistor":inflateSourceResistor(sourceComponent,inflationCtx);break;case"simple_capacitor":inflateSourceCapacitor(sourceComponent,inflationCtx);break;case"simple_inductor":inflateSourceInductor(sourceComponent,inflationCtx);break;case"simple_diode":inflateSourceDiode(sourceComponent,inflationCtx);break;case"simple_fiducial":inflateSourceFiducial(sourceComponent,inflationCtx);break;case"simple_led":inflateSourceLed(sourceComponent,inflationCtx);break;case"simple_chip":inflateSourceChip(sourceComponent,inflationCtx);break;case"simple_connector":inflateSourceConnector(sourceComponent,inflationCtx);break;case"simple_transistor":inflateSourceTransistor(sourceComponent,inflationCtx);break;case"simple_mosfet":inflateSourceMosfet(sourceComponent,inflationCtx);break;case"simple_push_button":inflateSourcePushButton(sourceComponent,inflationCtx);break;case"simple_switch":inflateSourceSwitch(sourceComponent,inflationCtx);break;default:throw new Error(`No inflator implemented for source component ftype: "${sourceComponent.ftype}"`)}let sourcePorts=injectionDb.source_port.list();for(let sourcePort of sourcePorts)inflateSourcePort(sourcePort,inflationCtx);let sourceTraces=injectionDb.source_trace.list();for(let sourceTrace of sourceTraces)inflateSourceTrace(sourceTrace,inflationCtx);inflateStandalonePcbPrimitives(inflationCtx)},isSelectionResultPort=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.getSourcePort=="function",isSelectionResultNet=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.getSourceNet=="function",isSelectionResultComponent=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.getPorts=="function",isCircuitJsonElement=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.type=="string",isNonEmptyString=value=>typeof value=="string"&&value.length>0,SelectionResultPortImpl=class{constructor(port){__publicField(this,"port");this.port=port}getPcbPort(){let pcbPortId=this.port.pcb_port_id;return pcbPortId?this.port.root?.db.pcb_port.get(pcbPortId)??null:null}getSourcePort(){let sourcePortId=this.port.source_port_id;return sourcePortId?this.port.root?.db.source_port.get(sourcePortId)??null:null}},SelectionResultNetImpl=class{constructor(net){__publicField(this,"net");this.net=net}getSourceNet(){let sourceNetId=this.net.source_net_id;return sourceNetId?this.net.root?.db.source_net.get(sourceNetId)??null:null}},SelectionResultComponentImpl=class{constructor(component){__publicField(this,"component");this.component=component}getPort(name){let port=this.component.selectOne(`port.${name}`,{type:"port"})??this.component.selectOne(`.${name}`,{type:"port"});return port?new SelectionResultPortImpl(port):null}getPorts(){return this.component.selectAll("port").map(port=>new SelectionResultPortImpl(port))}getPcbComponent(){let pcbComponentId=this.component.pcb_component_id;return pcbComponentId?this.component.root?.db.pcb_component.get(pcbComponentId)??null:null}getSourceComponent(){let sourceComponentId=this.component.source_component_id;return sourceComponentId?this.component.root?.db.source_component.get(sourceComponentId)??null:null}},DrcCheck=class extends PrimitiveComponent2{get config(){return{componentName:"DrcCheck",zodProps:drcCheckProps}}constructor(props){super(props)}async runCustomDrcCheck(circuitJson){let result=await this._parsedProps.checkFn(this.createCustomDrcCheckContext(circuitJson)),diagnostics=[];return Array.isArray(result)?diagnostics=result:result&&(diagnostics=[result]),diagnostics.map((diagnostic,index)=>this.createCircuitJsonDiagnostic(diagnostic,index)).filter(diagnostic=>!!diagnostic)}createCustomDrcCheckContext(circuitJson){return{select:this.selectCustomDrcElement.bind(this),selectAll:this.selectAllCustomDrcElements.bind(this),isConnected:(a6,b6)=>this.isConnected(a6,b6,circuitJson),isPulledUp:a6=>this.isConnected(a6,"net.VCC",circuitJson)||this.isConnected(a6,"net.VDD",circuitJson)||this.getResistanceBetween(a6,"net.VCC",circuitJson)!==null||this.getResistanceBetween(a6,"net.VDD",circuitJson)!==null,isPulledDown:a6=>this.isConnected(a6,"net.GND",circuitJson)||this.getResistanceBetween(a6,"net.GND",circuitJson)!==null,getResistanceBetween:(a6,b6)=>this.getResistanceBetween(a6,b6,circuitJson)}}selectCustomDrcElement(selector){return this.wrapSelectionResult(this.getSubcircuit().selectOne(selector))}selectAllCustomDrcElements(selector){let selectionResults=[];for(let component of this.getSubcircuit().selectAll(selector)){let selectionResult=this.wrapSelectionResult(component);selectionResult&&selectionResults.push(selectionResult)}return selectionResults}wrapSelectionResult(component){return component?component instanceof Port?new SelectionResultPortImpl(component):component instanceof Net?new SelectionResultNetImpl(component):new SelectionResultComponentImpl(component):null}createCircuitJsonDiagnostic(diagnostic,index){let diagnosticRecord=diagnostic,diagnosticType="source_component_misconfigured_error";typeof diagnosticRecord.error_type=="string"?diagnosticType=diagnosticRecord.error_type:typeof diagnosticRecord.warning_type=="string"&&(diagnosticType=diagnosticRecord.warning_type);let diagnosticWithCircuitJsonDefaults={...diagnostic};typeof diagnosticRecord.type=="string"?diagnosticWithCircuitJsonDefaults.type=diagnosticRecord.type:diagnosticWithCircuitJsonDefaults.type=diagnosticType,typeof diagnosticRecord.warning_type!="string"&&(typeof diagnosticRecord.error_type=="string"?diagnosticWithCircuitJsonDefaults.error_type=diagnosticRecord.error_type:diagnosticWithCircuitJsonDefaults.error_type=diagnosticType);let diagnosticIdField=`${diagnosticType}_id`;return diagnosticRecord[diagnosticIdField]?diagnosticWithCircuitJsonDefaults[diagnosticIdField]=diagnosticRecord[diagnosticIdField]:diagnosticWithCircuitJsonDefaults[diagnosticIdField]=`${diagnosticType}_${this._renderId}_${index}`,any_circuit_element.parse(diagnosticWithCircuitJsonDefaults)}isConnected(a6,b6,circuitJson){let aKeys=this.getConnectivityKeys(a6,circuitJson),bKeys=this.getConnectivityKeys(b6,circuitJson);return aKeys.some(key=>bKeys.includes(key))}getResistanceBetween(a6,b6,circuitJson){if(this.isConnected(a6,b6,circuitJson))return 0;let aKeys=this.getConnectivityKeys(a6,circuitJson),bKeys=this.getConnectivityKeys(b6,circuitJson);if(aKeys.length===0||bKeys.length===0)return null;let sourceResistors=circuitJson.filter(elm=>elm.type==="source_component"&&elm.ftype==="simple_resistor"),root=this.root;if(!root)return null;for(let resistor of sourceResistors){let resistorPorts=root.db.source_port.list({source_component_id:resistor.source_component_id});if(resistorPorts.length!==2)continue;let resistorKeys=resistorPorts.map(port=>port.subcircuit_connectivity_map_key),connectsA=resistorKeys.some(key=>key&&aKeys.includes(key)),connectsB=resistorKeys.some(key=>key&&bKeys.includes(key));if(connectsA&&connectsB)return resistor.resistance}return null}getConnectivityKeys(connectable,circuitJson){if(!connectable)return[];if(typeof connectable=="string"){let selected=this.selectCustomDrcElement(connectable);return selected?this.getConnectivityKeys(selected,circuitJson):[]}return isSelectionResultPort(connectable)?[connectable.getSourcePort()?.subcircuit_connectivity_map_key].filter(isNonEmptyString):isSelectionResultNet(connectable)?[connectable.getSourceNet()?.subcircuit_connectivity_map_key].filter(isNonEmptyString):isSelectionResultComponent(connectable)?connectable.getPorts().flatMap(port=>this.getConnectivityKeys(port,circuitJson)):isCircuitJsonElement(connectable)?this.getCircuitJsonElementConnectivityKeys(connectable,circuitJson):[]}getCircuitJsonElementConnectivityKeys(element,circuitJson){if(!element)return[];if(element.type==="source_port")return[element.subcircuit_connectivity_map_key].filter(isNonEmptyString);if(element.type==="source_net")return[element.subcircuit_connectivity_map_key].filter(isNonEmptyString);if(element.type==="pcb_port")return this.getConnectivityKeys(element.source_port_id,circuitJson);if(element.type==="source_component"){let root=this.root;return root?root.db.source_port.list({source_component_id:element.source_component_id}).map(port=>port.subcircuit_connectivity_map_key).filter(isNonEmptyString):[]}return[]}},IsolatedCircuit=class{constructor({platform,projectUrl,cachedSubcircuits,pendingSubcircuitRenders}={}){__publicField(this,"firstChild",null);__publicField(this,"children");__publicField(this,"db");__publicField(this,"root",null);__publicField(this,"isRootCircuit",!1);__publicField(this,"cachedSubcircuits");__publicField(this,"pendingSubcircuitRenders");__publicField(this,"_schematicDisabledOverride");__publicField(this,"pcbDisabled",!1);__publicField(this,"pcbRoutingDisabled",!1);__publicField(this,"_featureMspSchematicTraceRouting",!0);__publicField(this,"name");__publicField(this,"platform");__publicField(this,"projectUrl");__publicField(this,"_hasRenderedAtleastOnce",!1);__publicField(this,"_asyncEffectIdsByPhase",new Map);__publicField(this,"_asyncEffectPhaseById",new Map);__publicField(this,"_hasUnrenderedUpdatesFromAsyncEffects",!1);__publicField(this,"_runningAsyncEffectsById",new Map);__publicField(this,"_eventListeners",{});this.children=[],this.db=su2([]),this.platform=platform,this.projectUrl=projectUrl,this.pcbDisabled=platform?.pcbDisabled??!1,this.pcbRoutingDisabled=platform?.routingDisabled??!1,this.cachedSubcircuits=cachedSubcircuits,this.pendingSubcircuitRenders=pendingSubcircuitRenders,this.root=this}get schematicDisabled(){return this._schematicDisabledOverride!==void 0?this._schematicDisabledOverride:this.platform?.schematicDisabled!==void 0?this.platform.schematicDisabled:this._getBoard()?._parsedProps?.schematicDisabled??!1}set schematicDisabled(value){this._schematicDisabledOverride=value}add(componentOrElm){let component;(0,import_react7.isValidElement)(componentOrElm)?component=createInstanceFromReactElement(componentOrElm):component=componentOrElm,this.children.push(component)}setPlatform(platform){this.platform={...this.platform,...platform},platform.pcbDisabled!==void 0&&(this.pcbDisabled=platform.pcbDisabled),platform.routingDisabled!==void 0&&(this.pcbRoutingDisabled=platform.routingDisabled)}_getBoard(){let findBoard=components=>{for(let child of components){if(child.componentName==="Board")return child;if(isAssemblyDeviceContainer(child)){let nested=findBoard(child.children);if(nested)return nested}}};return findBoard(this.children)}_guessRootComponent(){if(this.firstChild)return;if(this.children.length===0)throw new Error("Not able to guess root component: IsolatedCircuit has no children (use circuit.add(...))");let panels=this.children.filter(child=>child.lowercaseComponentName==="panel");if(panels.length>1)throw new Error("Only one <panel> is allowed per circuit");if(panels.length===1){if(this.children.length!==1)throw new Error("<panel> must be the root element of the circuit");this.firstChild=panels[0];return}if(this.children.length===1&&(this.children[0].isGroup||isAssemblyDeviceContainer(this.children[0]))){this.firstChild=this.children[0];return}let group=new Group5({subcircuit:!0});group.parent=this,group.addAll(this.children),this.children=[group],this.firstChild=group}render(){this.firstChild||this._guessRootComponent();let{firstChild,db:db2}=this;if(!firstChild)throw new Error("IsolatedCircuit has no root component");firstChild.parent=this,firstChild.runRenderCycle(),this._hasUnrenderedUpdatesFromAsyncEffects=!1,this._hasRenderedAtleastOnce=!0}async renderUntilSettled(){for(this.db.source_project_metadata.list()?.[0]||this.db.source_project_metadata.insert({software_used_string:`@tscircuit/core@${this.getCoreVersion()}`,...this.projectUrl?{project_url:this.projectUrl}:{}}),this.render();!this.isDoneRendering();)await new Promise(resolve=>setTimeout(resolve,100)),this.render();this.emit("renderComplete")}isDoneRendering(){return this._hasRenderedAtleastOnce&&!this._hasIncompleteAsyncEffects()}_hasIncompleteAsyncEffects(){return this._asyncEffectPhaseById.size>0||this._hasUnrenderedUpdatesFromAsyncEffects?!0:this.children.some(child=>child._hasIncompleteAsyncEffects())}_hasIncompleteAsyncEffectsForPhase(phase){return(this._asyncEffectIdsByPhase.get(phase)?.size??0)>0}getRunningAsyncEffects(){return Array.from(this._runningAsyncEffectsById.values())}getCircuitJson(){return this._hasRenderedAtleastOnce||this.render(),this.db.toArray()}toJson(){return this.getCircuitJson()}async getSvg(options){let circuitToSvg=await Promise.resolve().then(()=>(init_dist9(),dist_exports3)).catch(e6=>{throw new Error(`To use circuit.getSvg, you must install the "circuit-to-svg" package.
741
+ `)}`)}catch(error2){debug12(`Failed to convert circuit JSON to SPICE: ${error2}`),root.db.simulation_unknown_experiment_error.insert({simulation_experiment_id:simulationExperimentId,error_type:"simulation_unknown_experiment_error",message:error2 instanceof Error?error2.message:String(error2)});continue}let voltageProbeByGraphName=new Map,voltageProbeById=new Map,graphDisplayOverridesByProbeId=new Map;for(let probe of voltageProbes)probe.finalProbeName&&voltageProbeByGraphName.set(probe.finalProbeName,probe),probe.simulation_voltage_probe_id&&(voltageProbeById.set(probe.simulation_voltage_probe_id,probe),graphDisplayOverridesByProbeId.set(probe.simulation_voltage_probe_id,getVoltageProbeGraphDisplayOverrides(probe)));for(let ammeter of ammeters)ammeter.simulation_current_probe_id&&graphDisplayOverridesByProbeId.set(ammeter.simulation_current_probe_id,getAmmeterGraphDisplayOverrides(ammeter));let scopedCurrentProbeIds=new Set(ammeters.map(ammeter=>ammeter.simulation_current_probe_id).filter(simulationCurrentProbeId=>!!simulationCurrentProbeId)),currentProbeById=new Map,currentProbeByName=new Map;for(let probe of root.db.simulation_current_probe.list().filter(probe2=>scopedCurrentProbeIds.has(probe2.simulation_current_probe_id)))currentProbeById.set(probe.simulation_current_probe_id,probe),probe.name!==void 0&&currentProbeByName.set(probe.name,probe);let orderedSimulationProbes=root.db.simulation_voltage_probe.list().filter(probe=>voltageProbeById.has(probe.simulation_voltage_probe_id)),firstSpiceNetlist=simulationRuns[0]?.spiceNetlist,graphNamesFromNetlist=firstSpiceNetlist?getTransientVoltageGraphNamesFromSpiceNetlist(firstSpiceNetlist):[];if(graphNamesFromNetlist.length===orderedSimulationProbes.length)for(let[simulationProbeIndex,simulationProbe]of orderedSimulationProbes.entries()){let probe=voltageProbeById.get(simulationProbe.simulation_voltage_probe_id),graphName=graphNamesFromNetlist[simulationProbeIndex];probe&&graphName&&voltageProbeByGraphName.set(graphName,probe)}else debug12(`Skipping probe-to-graph order mapping because counts differ: probes=${orderedSimulationProbes.length} graphNames=${graphNamesFromNetlist.length}`);let engineName=analogSimulation.getSpiceEngineName()??"spicey",spiceEngine2=spiceEngineMap[engineName];if(!spiceEngine2)throw new Error(`SPICE engine "${engineName}" not found in platform config. Available engines: ${JSON.stringify(Object.keys(spiceEngineMap).filter(spiceEngineName=>spiceEngineName!=="spicey"))}`);let effectId=`spice-simulation-${engineName}-${simulationExperimentId}`;debug12(`Queueing simulation for spice engine: ${engineName} (id: ${effectId})`),group._queueAsyncEffect(effectId,async()=>{try{let insertedVoltageGraphs=[],insertedCurrentGraphs=[];for(let simulationRun of simulationRuns){debug12(`Running simulation with engine: ${engineName}`);let simulationResult=await spiceEngine2.simulate(simulationRun.spiceString);debug12(`Simulation completed, received ${simulationResult.simulationResultCircuitJson.length} elements`);for(let simulationResultCircuitElement of simulationResult.simulationResultCircuitJson){if(!isCircuitElementInput(simulationResultCircuitElement)){debug12("Skipping invalid simulation result element");continue}let simulationResultWithSweepCoordinate=attachSweepCoordinateToSimulationResult({simulationResult:simulationResultCircuitElement,simulationParameterSweepCoordinate:simulationRun.simulationParameterSweepCoordinate});if(isVoltageGraph(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=simulationResultWithSweepCoordinate.name?voltageProbeByGraphName.get(simulationResultWithSweepCoordinate.name):void 0;probeMatch&&(simulationResultWithSweepCoordinate.color=probeMatch.color??void 0,simulationResultWithSweepCoordinate.source_probe_id=probeMatch.simulation_voltage_probe_id??void 0)}else if(isSimulationVoltageResult(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=voltageProbeById.get(simulationResultWithSweepCoordinate.simulation_voltage_probe_id)??(simulationResultWithSweepCoordinate.name?voltageProbeByGraphName.get(simulationResultWithSweepCoordinate.name):void 0);probeMatch?.simulation_voltage_probe_id&&(simulationResultWithSweepCoordinate.color=probeMatch.color??void 0,simulationResultWithSweepCoordinate.simulation_voltage_probe_id=probeMatch.simulation_voltage_probe_id)}if(isCurrentGraph2(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=(simulationResultWithSweepCoordinate.source_probe_id?currentProbeById.get(simulationResultWithSweepCoordinate.source_probe_id):void 0)??(simulationResultWithSweepCoordinate.name?currentProbeByName.get(simulationResultWithSweepCoordinate.name):void 0);probeMatch&&(simulationResultWithSweepCoordinate.color=probeMatch.color,simulationResultWithSweepCoordinate.source_probe_id=probeMatch.simulation_current_probe_id)}else if(isSimulationCurrentResult(simulationResultWithSweepCoordinate)){simulationResultWithSweepCoordinate.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=currentProbeById.get(simulationResultWithSweepCoordinate.simulation_current_probe_id)??(simulationResultWithSweepCoordinate.name?currentProbeByName.get(simulationResultWithSweepCoordinate.name):void 0);probeMatch&&(simulationResultWithSweepCoordinate.color=probeMatch.color,simulationResultWithSweepCoordinate.simulation_current_probe_id=probeMatch.simulation_current_probe_id)}let insertedSimulationResult=root.db.insert(simulationResultWithSweepCoordinate);isVoltageGraph(insertedSimulationResult)&&insertedVoltageGraphs.push({type:"voltage",graph:insertedSimulationResult}),isCurrentGraph2(insertedSimulationResult)&&insertedCurrentGraphs.push({type:"current",graph:insertedSimulationResult}),debug12(`Inserted ${simulationResultWithSweepCoordinate.type} into database`)}}analogSimulation.usesIndependentGraphAxes()&&insertIndependentAxisScopeTraces({db:root.db,graphs:[...insertedVoltageGraphs,...insertedCurrentGraphs],graphDisplayOverridesByProbeId}),group._markDirty("SimulationSpiceEngineRender")}catch(error2){debug12(`Simulation failed for engine ${engineName}: ${error2}`),root.db.simulation_unknown_experiment_error.insert({simulation_experiment_id:simulationExperimentId,error_type:"simulation_unknown_experiment_error",message:error2 instanceof Error?error2.message:String(error2)})}})}}function Group_doInitialSourceAddConnectivityMapKey(group){if(!group.isSubcircuit)return;let{db:db2}=group.root,traces=group.selectAll("trace"),vias=group.selectAll("via"),nets=group.selectAll("net"),connMap=new ConnectivityMap({});connMap.addConnections(traces.map(t53=>{let source_trace3=db2.source_trace.get(t53.source_trace_id);return source_trace3?[source_trace3.source_trace_id,...source_trace3.connected_source_port_ids,...source_trace3.connected_source_net_ids]:null}).filter(c3=>c3!==null));let sourceNets=db2.source_net.list().filter(net=>net.subcircuit_id===group.subcircuit_id);for(let sourceNet of sourceNets)connMap.addConnections([[sourceNet.source_net_id]]);let{name:subcircuitName}=group._parsedProps;for(let trace of traces){if(!trace.source_trace_id)continue;let connNetId=connMap.getNetConnectedToId(trace.source_trace_id);connNetId&&(trace.subcircuit_connectivity_map_key=`${subcircuitName??`unnamedsubcircuit${group.subcircuit_id??group.source_group_id??group._renderId}`}_${connNetId}`,db2.source_trace.update(trace.source_trace_id,{subcircuit_connectivity_map_key:trace.subcircuit_connectivity_map_key}))}let allSourcePortIds=new Set;for(let trace of traces){if(!trace.source_trace_id)continue;let source_trace3=db2.source_trace.get(trace.source_trace_id);if(source_trace3)for(let id3 of source_trace3.connected_source_port_ids)allSourcePortIds.add(id3)}for(let portId of allSourcePortIds){let connNetId=connMap.getNetConnectedToId(portId);if(!connNetId)continue;let connectivityMapKey=`${subcircuitName??`unnamedsubcircuit${group.subcircuit_id??group.source_group_id??group._renderId}`}_${connNetId}`;db2.source_port.update(portId,{subcircuit_connectivity_map_key:connectivityMapKey})}let allSourceNetIds=new Set;for(let trace of traces){if(!trace.source_trace_id)continue;let source_trace3=db2.source_trace.get(trace.source_trace_id);if(source_trace3)for(let source_net_id of source_trace3.connected_source_net_ids)allSourceNetIds.add(source_net_id)}for(let sourceNet of sourceNets)allSourceNetIds.add(sourceNet.source_net_id);for(let netId of allSourceNetIds){let connNetId=connMap.getNetConnectedToId(netId);if(!connNetId)continue;let connectivityMapKey=`${subcircuitName??`unnamedsubcircuit${group.subcircuit_id??group.source_group_id??group._renderId}`}_${connNetId}`;db2.source_net.update(netId,{subcircuit_connectivity_map_key:connectivityMapKey});let netInstance=nets.find(n3=>n3.source_net_id===netId);netInstance&&(netInstance.subcircuit_connectivity_map_key=connectivityMapKey)}for(let via of vias){let connectedNetOrTrace=via._getConnectedNetOrTrace();connectedNetOrTrace&&connectedNetOrTrace.subcircuit_connectivity_map_key&&(via.subcircuit_connectivity_map_key=connectedNetOrTrace.subcircuit_connectivity_map_key)}}var Group_doInitialStandaloneSubcircuitPcbDesignRuleChecks=group=>{let isRootSubcircuit=group.root?.firstChild===group;if(!group.isSubcircuit||!isRootSubcircuit||group._getBoard())return;let routingDisabled=group.root?.pcbRoutingDisabled||group.getInheritedProperty("routingDisabled"),drcChecksDisabled=group.root?.platform?.drcChecksDisabled??group.getInheritedProperty("drcChecksDisabled"),routingDrcChecksDisabled=group.root?.platform?.routingDrcChecksDisabled??group.getInheritedProperty("routingDrcChecksDisabled");if(group.root?.pcbDisabled||routingDisabled||drcChecksDisabled||routingDrcChecksDisabled||group._hasIncompleteAsyncEffectsInSubtreeForPhase("PcbTraceRender")||group._hasTracesToRoute()&&!group._areChildSubcircuitsRouted()||group._standaloneSubcircuitDrcChecksComplete||group._standaloneSubcircuitDrcChecksInProgress)return;let{db:db2}=group.root,subcircuitCircuitJson=db2.subtree({subcircuit_id:group.subcircuit_id}).toArray();group._standaloneSubcircuitDrcChecksInProgress=!0,group._queueAsyncEffect("standalone-subcircuit:routing-drc-checks",async()=>{try{let results=await runAllRoutingChecks(subcircuitCircuitJson);db2.insertAll(dedupePcbDrcErrors(results)),group._standaloneSubcircuitDrcChecksComplete=!0}finally{group._standaloneSubcircuitDrcChecksInProgress=!1}})},addPourNetMap=(target,pourNetMap)=>{for(let[layer,netOrNets]of Object.entries(pourNetMap)){if(!netOrNets)continue;let nets=Array.isArray(netOrNets)?netOrNets:[netOrNets],layerNets=target.get(layer)??new Set;for(let net of nets)layerNets.add(net);target.set(layer,layerNets)}},toFanoutPourNetMap=netsByLayer=>Object.fromEntries(Array.from(netsByLayer,([layer,nets])=>[layer,nets.size===1?Array.from(nets)[0]:Array.from(nets)])),Group_getFanoutPourNetMap=(group,routingPhasePlans)=>{let explicitMaps=routingPhasePlans.map(plan=>plan.fanoutPourNetMap).filter(map=>map!==void 0),netsByLayer=new Map;if(explicitMaps.length>0){for(let explicitMap of explicitMaps)addPourNetMap(netsByLayer,explicitMap);return toFanoutPourNetMap(netsByLayer)}let scope=group;for(;scope;){if(scope.isSubcircuit){let subcircuit=scope,copperPours=subcircuit.selectAll("copperpour");for(let copperPour of copperPours){if(copperPour.getSubcircuit()!==subcircuit)continue;let{layer,connectsTo}=copperPour._parsedProps;addPourNetMap(netsByLayer,{[layer]:connectsTo})}}scope=scope.parent}return netsByLayer.size>0?toFanoutPourNetMap(netsByLayer):void 0},baseBreakoutPointProps=pcbLayoutProps.omit({pcbRotation:!0,layer:!0}),BaseBreakoutPoint=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_breakout_point_id",null);__publicField(this,"matchedPort",null);__publicField(this,"matchedNet",null);__publicField(this,"matchedSourceTraceId",null);__publicField(this,"isPcbPrimitive",!0)}_getSourceTraceIdForPort(port){let{db:db2}=this.root;return db2.source_trace.list().find(st3=>st3.connected_source_port_ids.includes(port.source_port_id))?.source_trace_id}_getSourceNetIdForPort(port){let{db:db2}=this.root;return db2.source_trace.list().find(st3=>st3.connected_source_port_ids.includes(port.source_port_id))?.connected_source_net_ids[0]}_renderPcbBreakoutPoint({layer}={}){if(this.pcb_breakout_point_id||this.root?.pcbDisabled)return;let{db:db2}=this.root,position4=this._getGlobalPcbPositionBeforeLayout(),group=this.parent?.getGroup(),subcircuit=this.getSubcircuit();if(!group||!group.pcb_group_id)return;let pcb_breakout_point3=db2.pcb_breakout_point.insert({pcb_group_id:group.pcb_group_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,source_port_id:this.matchedPort?.source_port_id??void 0,source_trace_id:this.matchedPort?this.matchedSourceTraceId??this._getSourceTraceIdForPort(this.matchedPort):void 0,source_net_id:this.matchedNet?this.matchedNet.source_net_id:this.matchedPort?this._getSourceNetIdForPort(this.matchedPort):void 0,layer,x:position4.x,y:position4.y});this.pcb_breakout_point_id=pcb_breakout_point3.pcb_breakout_point_id}_getPcbCircuitJsonBounds(){let position4=this._getGlobalPcbPositionBeforeLayout();return{center:{x:position4.x,y:position4.y},bounds:{left:position4.x,top:position4.y,right:position4.x,bottom:position4.y},width:0,height:0}}_setPositionFromLayout(newCenter){let{db:db2}=this.root;if(!this.pcb_breakout_point_id)return;let updatedProperties={x:newCenter.x,y:newCenter.y};this.matchedSourceTraceId&&(updatedProperties.source_trace_id=this.matchedSourceTraceId),db2.pcb_breakout_point.update(this.pcb_breakout_point_id,updatedProperties)}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db:db2}=this.root;if(!this.pcb_breakout_point_id)return;let point6=db2.pcb_breakout_point.get(this.pcb_breakout_point_id);point6&&db2.pcb_breakout_point.update(this.pcb_breakout_point_id,{x:point6.x+deltaX,y:point6.y+deltaY})}getPcbSize(){return{width:0,height:0}}},BreakoutPoint=class extends BaseBreakoutPoint{get config(){return{componentName:"BreakoutPoint",zodProps:breakoutPointProps}}_matchConnection(){if(this.matchedPort)return;let{connection}=this._parsedProps,subcircuit=this.getSubcircuit();subcircuit&&(this.matchedPort=subcircuit.selectOne(connection,{type:"port"}),this.matchedPort||(this.matchedNet=subcircuit.selectOne(connection,{type:"net"})),!this.matchedPort&&!this.matchedNet&&this.renderError(`Could not find connection target "${connection}"`))}doInitialPcbPrimitiveRender(){this._matchConnection(),this._renderPcbBreakoutPoint()}};function getPhaseSortValue(routingPhaseIndex){return routingPhaseIndex===null?Number.POSITIVE_INFINITY:routingPhaseIndex}function compareRoutingPhasePlans(a6,b6){return getPhaseSortValue(a6.routingPhaseIndex)-getPhaseSortValue(b6.routingPhaseIndex)}function getOrCreateRoutingPhasePlan(plansByPhaseIndex,routingPhaseIndex){let plan=plansByPhaseIndex.get(routingPhaseIndex);return plan||(plan={routingPhaseIndex,nets:[],traces:[]},plansByPhaseIndex.set(routingPhaseIndex,plan)),plan}function getNetRoutingPhaseIndex(net){return net.props.routingPhaseIndex??null}function getTraceRoutingPhaseIndex(trace,buses=[]){let busRoutingPhaseIndexes=new Set;for(let bus of buses){if(bus._parsedProps.routingPhaseIndex===void 0)continue;bus._parsedProps.connections.some(connection=>connection===trace.name||traceHasEndpointMatchingConnectionSelector(trace,convertPortSelectorToEndpointKey(connection)))&&busRoutingPhaseIndexes.add(bus._parsedProps.routingPhaseIndex)}if(busRoutingPhaseIndexes.size>1)throw new Error(`Trace "${trace.name}" belongs to buses with different routing phases`);let busRoutingPhaseIndex=busRoutingPhaseIndexes.values().next().value;if(busRoutingPhaseIndex!==void 0)return busRoutingPhaseIndex;let traceRoutingPhaseIndex=trace.props.routingPhaseIndex;if(traceRoutingPhaseIndex!==void 0)return traceRoutingPhaseIndex;let routingPhaseIndex=null,connectedNets=trace._findConnectedNets().nets;for(let net of connectedNets){let netRoutingPhaseIndex=getNetRoutingPhaseIndex(net);typeof netRoutingPhaseIndex=="number"&&(routingPhaseIndex===null||netRoutingPhaseIndex<routingPhaseIndex)&&(routingPhaseIndex=netRoutingPhaseIndex)}return routingPhaseIndex}function convertPortSelectorToEndpointKey(selector){return selector.trim().replace(/\s*>\s*/g,".").replace(/\s+/g,".").replace(/^\./,"").replace(/\.\./g,".")}function getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps){return[...phaseProps.connection?[phaseProps.connection]:[],...phaseProps.connections??[]]}function traceHasEndpointMatchingConnectionSelector(trace,connectionSelectorEndpointKey){return trace.getTracePortPathSelectors().some(selector=>convertPortSelectorToEndpointKey(selector)===connectionSelectorEndpointKey)}function getAutoroutersByPhaseIndex(group){let autoroutingPhases=group.selectAll("autoroutingphase"),autoroutersByPhaseIndex=new Map;for(let autoroutingPhase of autoroutingPhases){let{phaseIndex,autorouter}=autoroutingPhase._parsedProps;autorouter!==void 0&&autoroutersByPhaseIndex.set(phaseIndex??null,autorouter)}return autoroutersByPhaseIndex}function getAutoroutingPhasePropsByPhaseIndex(group){let autoroutingPhases=group.selectAll("autoroutingphase"),propsByPhaseIndex=new Map;for(let autoroutingPhase of autoroutingPhases){let props=autoroutingPhase._parsedProps;propsByPhaseIndex.set(props.phaseIndex??null,props)}return propsByPhaseIndex}function toParsedDistance(value){if(value!==void 0)return Number(value)}function getDrcTolerancesFromAutoroutingPhaseProps(phaseProps){let{minTraceWidth,minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance,minTraceToPadEdgeClearance,minPadEdgeToPadEdgeClearance,minBoardEdgeClearance,minViaEdgeToPadEdgeClearance,minViaHoleDiameter,minViaPadDiameter}=phaseProps;if(!(minTraceWidth===void 0&&minViaHoleEdgeToViaHoleEdgeClearance===void 0&&minPlatedHoleDrillEdgeToDrillEdgeClearance===void 0&&minTraceToPadEdgeClearance===void 0&&minPadEdgeToPadEdgeClearance===void 0&&minBoardEdgeClearance===void 0&&minViaEdgeToPadEdgeClearance===void 0&&minViaHoleDiameter===void 0&&minViaPadDiameter===void 0))return{minTraceWidth:toParsedDistance(minTraceWidth),minViaHoleEdgeToViaHoleEdgeClearance:toParsedDistance(minViaHoleEdgeToViaHoleEdgeClearance),minPlatedHoleDrillEdgeToDrillEdgeClearance:toParsedDistance(minPlatedHoleDrillEdgeToDrillEdgeClearance),minTraceToPadEdgeClearance:toParsedDistance(minTraceToPadEdgeClearance),minPadEdgeToPadEdgeClearance:toParsedDistance(minPadEdgeToPadEdgeClearance),minBoardEdgeClearance:toParsedDistance(minBoardEdgeClearance),minViaEdgeToPadEdgeClearance:toParsedDistance(minViaEdgeToPadEdgeClearance),minViaHoleDiameter:toParsedDistance(minViaHoleDiameter),minViaPadDiameter:toParsedDistance(minViaPadDiameter)}}function Group_getRoutingPhasePlans(group){let traces=group.selectAll("trace"),nets=group.selectAll("net"),buses=group.selectAll("bus"),breakouts=group.selectAll("group").filter(candidate=>candidate.isRoutingDirective),breakoutByTrace=new Map,breakoutByNet=new Map;for(let trace of traces){let ancestor=trace.parent;for(;ancestor&&ancestor!==group;){if(ancestor.isRoutingDirective){breakoutByTrace.set(trace,ancestor);break}ancestor=ancestor.parent}}for(let net of nets)net.parent?.isRoutingDirective&&breakouts.includes(net.parent)&&breakoutByNet.set(net,net.parent);let plansByPhaseIndex=new Map,autoroutersByPhaseIndex=getAutoroutersByPhaseIndex(group),phasePropsByPhaseIndex=getAutoroutingPhasePropsByPhaseIndex(group),groupFanoutProps=group._parsedProps,hasDirectRoutingTargets=traces.length>0||nets.length>0,hasReroutePhase=Array.from(phasePropsByPhaseIndex.values()).some(phaseProps=>phaseProps.reroute),hasConnectionTargetedPhase=Array.from(phasePropsByPhaseIndex.values()).some(phaseProps=>getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps).length>0);if(!hasDirectRoutingTargets&&!hasReroutePhase&&!hasConnectionTargetedPhase&&breakouts.length===0)return[];for(let net of nets){if(breakoutByNet.has(net))continue;let routingPhaseIndex=getNetRoutingPhaseIndex(net);getOrCreateRoutingPhasePlan(plansByPhaseIndex,routingPhaseIndex).nets.push(net)}for(let trace of traces){if(breakoutByTrace.has(trace))continue;let routingPhaseIndex=getTraceRoutingPhaseIndex(trace,buses);getOrCreateRoutingPhasePlan(plansByPhaseIndex,routingPhaseIndex).traces.push(trace)}for(let[phaseIndex,phaseProps]of phasePropsByPhaseIndex){let connectionSelectors=getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps);if(connectionSelectors.length>0){let plan=getOrCreateRoutingPhasePlan(plansByPhaseIndex,phaseIndex),connectionSelectorEndpointKeys=connectionSelectors.map(convertPortSelectorToEndpointKey);plan.connectionSelectors=connectionSelectors;for(let trace of traces)if(!breakoutByTrace.has(trace)&&connectionSelectorEndpointKeys.some(endpointKey=>traceHasEndpointMatchingConnectionSelector(trace,endpointKey))){if(!phaseProps.reroute)for(let existingPlan of plansByPhaseIndex.values())existingPlan!==plan&&(existingPlan.traces=existingPlan.traces.filter(existingTrace=>existingTrace!==trace));if(plan.traces.includes(trace))continue;plan.traces.push(trace)}}phaseProps.reroute&&getOrCreateRoutingPhasePlan(plansByPhaseIndex,phaseIndex)}let plans=Array.from(plansByPhaseIndex.values()).sort(compareRoutingPhasePlans);for(let plan of plans){plan.autorouter=autoroutersByPhaseIndex.get(plan.routingPhaseIndex);let phaseProps=phasePropsByPhaseIndex.get(plan.routingPhaseIndex);plan.phaseName=phaseProps?.name,plan.reroute=phaseProps?.reroute,plan.region=phaseProps?.region,plan.connectionSelectors=phaseProps?getConnectionSelectorsFromAutoroutingPhaseProps(phaseProps):void 0,plan.busFanoutDirections=phaseProps?.busFanoutDirections??groupFanoutProps.busFanoutDirections,plan.fanoutBoundaryPadding=phaseProps?.fanoutBoundaryPadding??groupFanoutProps.fanoutBoundaryPadding;let fanoutRoutingLayers=phaseProps?.fanoutRoutingLayers??groupFanoutProps.fanoutRoutingLayers;plan.fanoutRoutingLayers=fanoutRoutingLayers?.map(layer=>typeof layer=="string"?layer:layer.name),plan.fanoutPourNetMap=phaseProps?.fanoutPourNetMap??groupFanoutProps.fanoutPourNetMap,plan.drcTolerances=phaseProps?getDrcTolerancesFromAutoroutingPhaseProps(phaseProps):void 0}let breakoutPlans=[];for(let breakout of breakouts){let breakoutProps2=breakout._parsedProps,shouldUseDefaultAutorouterForBreakoutPoints=breakout.children.some(child=>child instanceof BreakoutPoint)&&breakout.props.autorouter===void 0,breakoutTraces=traces.filter(trace=>breakoutByTrace.get(trace)===breakout),unroutedBreakoutTraces=breakoutTraces.filter(trace=>!trace.pcb_trace_id),pcbGroup=breakout.pcb_group_id?breakout.root?.db.pcb_group.get(breakout.pcb_group_id):null,outlineBounds=pcbGroup?.outline?getBoundsFromPoints2(pcbGroup.outline):null,routingWidth=pcbGroup?.width??(outlineBounds?outlineBounds.maxX-outlineBounds.minX:void 0),routingHeight=pcbGroup?.height??(outlineBounds?outlineBounds.maxY-outlineBounds.minY:void 0),routingBounds=pcbGroup&&routingWidth&&routingHeight?{minX:pcbGroup.center.x-routingWidth/2,maxX:pcbGroup.center.x+routingWidth/2,minY:pcbGroup.center.y-routingHeight/2,maxY:pcbGroup.center.y+routingHeight/2}:void 0,rawBreakoutProps=breakout.props,hasExplicitGeometry=rawBreakoutProps.width!==void 0||rawBreakoutProps.height!==void 0||!!rawBreakoutProps.outline?.length,hasExplicitFanoutBoundaryPadding=rawBreakoutProps.fanoutBoundaryPadding!==void 0,breakoutPlan={routingPhaseIndex:null,routingPcbGroupId:breakout.pcb_group_id??void 0,fanoutRegionPcbGroupId:breakout.pcb_group_id??void 0,routingBounds,fanoutBounds:hasExplicitGeometry?routingBounds:hasExplicitFanoutBoundaryPadding?void 0:routingBounds,autorouter:breakoutProps2.autorouter??"fanout",busFanoutDirections:breakoutProps2.busFanoutDirections,fanoutBoundaryPadding:breakoutProps2.fanoutBoundaryPadding,fanoutRoutingLayers:breakoutProps2.fanoutRoutingLayers?.map(layer=>typeof layer=="string"?layer:layer.name),fanoutPourNetMap:breakoutProps2.fanoutPourNetMap,nets:nets.filter(net=>breakoutByNet.get(net)===breakout),traces:breakoutTraces};if(!shouldUseDefaultAutorouterForBreakoutPoints){breakoutPlans.push(breakoutPlan);continue}if(breakoutPlans.push({...breakoutPlan,autorouter:"default",traces:[]}),unroutedBreakoutTraces.length>0){let automaticFanoutBusIds=new Set(buses.filter(bus=>unroutedBreakoutTraces.some(trace=>bus._parsedProps.connections.some(connection=>connection===trace.name||traceHasEndpointMatchingConnectionSelector(trace,convertPortSelectorToEndpointKey(connection))))).map(bus=>bus.name));for(let trace of unroutedBreakoutTraces)trace.name&&automaticFanoutBusIds.add(trace.name);let automaticBusFanoutDirections=breakoutProps2.busFanoutDirections?Object.fromEntries(Object.entries(breakoutProps2.busFanoutDirections).filter(([busId])=>automaticFanoutBusIds.has(busId))):void 0;breakoutPlans.push({...breakoutPlan,routingPcbGroupId:void 0,busFanoutDirections:automaticBusFanoutDirections,traces:unroutedBreakoutTraces})}}let defaultPhaseProps=phasePropsByPhaseIndex.get(null);if(hasDirectRoutingTargets&&phasePropsByPhaseIndex.size===1&&defaultPhaseProps?.reroute&&plans.length===1&&plans[0]?.routingPhaseIndex===null){let reroutePlan=plans[0];return[...breakoutPlans,{routingPhaseIndex:null,nets:[...reroutePlan.nets],traces:[...reroutePlan.traces]},reroutePlan]}return[...breakoutPlans,...plans]}var package_default3={name:"@tscircuit/core",type:"module",version:"0.0.1761",types:"dist/index.d.ts",main:"dist/index.js",module:"dist/index.js",exports:{".":{import:"./dist/index.js",types:"./dist/index.d.ts"}},files:["dist"],repository:{type:"git",url:"https://github.com/tscircuit/core"},scripts:{build:"tsup-node",format:"biome format . --write","measure-bundle":"howfat -r table .","pkg-pr-new-release":"bunx pkg-pr-new publish --comment=off --peerDeps","smoke-test:dist":"bun run scripts/smoke-tests/test-dist-simple-circuit.tsx","build:benchmarking":"bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist","build:benchmarking:watch":`chokidar "./{benchmarking,lib}/**/*.{ts,tsx}" -c 'bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist'`,"start:benchmarking":'concurrently "bun run build:benchmarking:watch" "live-server ./benchmarking-dist"',"generate-test-plan":"bun run scripts/generate-test-plan.ts"},devDependencies:{"@biomejs/biome":"^1.8.3","@resvg/resvg-js":"^2.6.2","@tsci/tscircuit.ti":"github:tscircuit/ti#57e314be4b2b06bc546d4def7453e619604d1157","@tscircuit/alphabet":"0.0.25","@tscircuit/capacity-autorouter":"^0.0.840","@tscircuit/checks":"^0.0.171","@tscircuit/circuit-json-util":"^0.0.106","@tscircuit/common":"^0.0.20","@tscircuit/copper-pour-solver":"^0.0.49","@tscircuit/create-fdm-enclosure":"0.0.4","@tscircuit/fanout-solver":"0.0.37","@tscircuit/footprinter":"^0.0.426","@tscircuit/image-utils":"^0.0.8","@tscircuit/infer-cable-insertion-point":"^0.0.4","@tscircuit/infgrid-ijump-astar":"^0.0.35","@tscircuit/jlcpcb-manufacturing-specs":"git+https://github.com/tscircuit/jlcpcb-manufacturing-specs#e08af159db01a37db007e33f0a7268d0e4a279a5","@tscircuit/krt-wasm":"^0.1.1","@tscircuit/log-soup":"^1.0.2","@tscircuit/matchpack":"^0.0.84","@tscircuit/math-utils":"^0.0.36","@tscircuit/miniflex":"^0.0.4","@tscircuit/ngspice-spice-engine":"^0.0.20","@tscircuit/props":"^0.0.635","@tscircuit/schematic-match-adapt":"^0.0.18","@tscircuit/schematic-trace-solver":"^0.0.156","@tscircuit/solver-utils":"^0.0.16","@tscircuit/soup-util":"^0.0.41","@tscircuit/winding-breakout-point-solver":"github:tscircuit/winding-breakout-point-solver#202dbe9eb0088633b6fa094120dba6f2f41f8803","@types/bun":"^1.2.16","@types/debug":"^4.1.12","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@types/react-reconciler":"^0.28.9","bpc-graph":"^0.0.57","bun-match-svg":"0.0.12","calculate-elbow":"^0.0.12","chokidar-cli":"^3.0.0","circuit-json":"^0.0.475","circuit-json-to-bpc":"^0.0.13","circuit-json-to-connectivity-map":"^0.0.27","circuit-json-to-gltf":"^0.0.118","circuit-json-to-spice":"^0.0.45","circuit-to-svg":"^0.0.407",concurrently:"^9.1.2","connectivity-map":"^1.0.0",debug:"^4.3.6",flatbush:"^4.5.0","graphics-debug":"^0.0.95",howfat:"^0.3.8","kicad-to-circuit-json":"^0.0.117",kicadts:"^0.0.53","live-server":"^1.2.2",minicssgrid:"^0.0.9","pkg-pr-new":"^0.0.37",poppygl:"^0.0.27",react:"^19.1.0","react-dom":"^19.1.0","schematic-symbols":"^0.0.239",spicets:"^0.0.4",spicey:"^0.0.14","stack-svgs":"^0.0.1","ts-expect":"^1.3.0",tsup:"^8.2.4"},peerDependencies:{"@tscircuit/capacity-autorouter":"*","@tscircuit/checks":"*","@tscircuit/circuit-json-util":"*","@tscircuit/create-fdm-enclosure":"*","@tscircuit/footprinter":"*","@tscircuit/infgrid-ijump-astar":"*","@tscircuit/math-utils":"*","@tscircuit/props":"*","@tscircuit/schematic-match-adapt":"*","circuit-json-to-bpc":"*","bpc-graph":"*","@tscircuit/matchpack":"*","circuit-json":"*","circuit-json-to-connectivity-map":"*","circuit-json-to-spice":"*","schematic-symbols":"*",spicets:"*",typescript:"^5.0.0"},dependencies:{"@flatten-js/core":"^1.6.2","@lume/kiwi":"^0.4.3","calculate-cell-boundaries":"^0.0.19","calculate-packing":"^0.0.86","css-select":"5.1.0","format-si-unit":"^0.0.12",nanoid:"^5.0.7","performance-now":"^2.1.0","react-reconciler":"^0.32.0","svg-path-commander":"^2.1.11","transformation-matrix":"^2.16.1",zod:"^3.25.67"},overrides:{"@tscircuit/circuit-json-util":"^0.0.106","@tscircuit/props":"^0.0.635","circuit-json":"^0.0.475"}},getFnv1aHash=value=>{let hash=2166136261;for(let i6=0;i6<value.length;i6++)hash^=value.charCodeAt(i6),hash=Math.imul(hash,16777619);return hash>>>0},getSrjHash=simpleRouteJson=>{let serializedSrj=JSON.stringify(simpleRouteJson),hash1=getFnv1aHash(serializedSrj),hash2=getFnv1aHash(`${serializedSrj}${hash1}`);return`${hash1.toString(16).padStart(8,"0")}${hash2.toString(16).padStart(8,"0")}`},getLocalAutoroutingCacheKey=simpleRouteJson=>`routes:core@${package_default3.version}:srj:${getSrjHash(simpleRouteJson)}`,getCachedLocalAutoroutingPhaseResult=async({cacheEngine,cacheKey})=>{if(!cacheEngine)return null;try{let cachedResult=await cacheEngine.getItem(cacheKey);if(!cachedResult)return null;let parsedResult=JSON.parse(cachedResult);return!parsedResult||!Array.isArray(parsedResult.traces)?null:parsedResult}catch{return null}},cacheLocalAutoroutingPhaseResult=async({cacheEngine,cacheKey,result})=>{if(cacheEngine)try{await cacheEngine.setItem(cacheKey,JSON.stringify(result))}catch{}};function connectionIsInRoutingPhase(connection,phasePlan){if(connection.routingPcbGroupId)return connection.routingPcbGroupId===phasePlan.routingPcbGroupId;for(let trace of phasePlan.traces)if(trace.source_trace_id&&(connection.source_trace_id===trace.source_trace_id||connection.name===trace.source_trace_id||connection.rootConnectionName===trace.source_trace_id||connection.mergedConnectionNames?.includes(trace.source_trace_id)))return!0;for(let net of phasePlan.nets)if(net.source_net_id&&connection.name===net.source_net_id)return!0;return!1}function Group_hasPhasedAutorouting(routingPhasePlans){for(let plan of routingPhasePlans)if(plan.routingPcbGroupId||plan.routingPhaseIndex!==null)return!0;return!1}var pointsReferToSameEndpoint=(first,second)=>first.pointId&&second.pointId?first.pointId===second.pointId:Math.abs(first.x-second.x)<=1e-6&&Math.abs(first.y-second.y)<=1e-6,getPairedExitTarget=(simpleRouteJson,connection)=>{if(!connection.routingPcbGroupId||!connection.source_trace_id)return;let globalConnection=simpleRouteJson.connections.find(candidate=>candidate.routingPcbGroupId!==connection.routingPcbGroupId&&candidate.source_trace_id===connection.source_trace_id&&candidate.pointsToConnect.some(globalPoint=>connection.pointsToConnect.some(localPoint=>pointsReferToSameEndpoint(globalPoint,localPoint))));if(!globalConnection)return;let pairedPoints=globalConnection.pointsToConnect.filter(globalPoint=>!connection.pointsToConnect.some(localPoint=>pointsReferToSameEndpoint(globalPoint,localPoint)));return pairedPoints.length===1?{x:pairedPoints[0].x,y:pairedPoints[0].y,layer:pairedPoints[0].layer}:void 0};function Group_filterSimpleRouteJsonForPhase(simpleRouteJson,phasePlan){let connections=[];for(let connection of simpleRouteJson.connections)connectionIsInRoutingPhase(connection,phasePlan)&&connections.push(connection);let includedConnectionNames=new Set;for(let connection of connections)includedConnectionNames.add(connection.name);let differentialPairs=[];for(let differentialPair of simpleRouteJson.differentialPairs??[]){let positiveConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[0]),negativeConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[1]);if(positiveConnectionIncluded!==negativeConnectionIncluded)throw new Error(`Differential pair "${differentialPair.connectionNames.join("/")}" cannot be split across autorouting phases`);positiveConnectionIncluded&&differentialPairs.push(differentialPair)}let connectionByName=new Map(connections.map(connection=>[connection.name,connection])),buses=(simpleRouteJson.buses??[]).map(bus=>{let connectionNames=bus.connectionNames.filter(connectionName=>includedConnectionNames.has(connectionName)),connectionExitTargets=Object.fromEntries(connectionNames.flatMap(connectionName=>{let connection=connectionByName.get(connectionName);if(!connection)return[];let pairedTarget=getPairedExitTarget(simpleRouteJson,connection);return pairedTarget?[[connectionName,pairedTarget]]:[]}));return{...bus,connectionNames,...Object.keys(connectionExitTargets).length>0?{connectionExitTargets}:{}}}).filter(bus=>bus.connectionNames.length>0),bounds=expandSrjBoundsToIncludeConnectionPoints({bounds:phasePlan.routingBounds??simpleRouteJson.bounds,connections});return{...simpleRouteJson,bounds,connections,differentialPairs:differentialPairs.length>0?differentialPairs:void 0,buses:buses.length>0?buses:void 0}}function hasDrcTolerances(drcTolerances){return drcTolerances?Object.values(drcTolerances).some(value=>value!==void 0):!1}function applyMinTraceWidthToConnections(connections,minTraceWidth){return minTraceWidth===void 0?connections:connections.map(connection=>({...connection,nominalTraceWidth:Math.max(connection.nominalTraceWidth??minTraceWidth,minTraceWidth),width:Math.max(connection.width??minTraceWidth,minTraceWidth)}))}function Group_applyDrcTolerancesToSimpleRouteJson(simpleRouteJson,drcTolerances){if(!hasDrcTolerances(drcTolerances))return simpleRouteJson;let minTraceWidth=drcTolerances.minTraceWidth??simpleRouteJson.minTraceWidth,minViaHoleDiameter=drcTolerances.minViaHoleDiameter??simpleRouteJson.minViaHoleDiameter,minViaPadDiameter=drcTolerances.minViaPadDiameter??simpleRouteJson.minViaPadDiameter,minTraceToPadEdgeClearance=drcTolerances.minTraceToPadEdgeClearance??simpleRouteJson.minTraceToPadEdgeClearance,minViaEdgeToPadEdgeClearance=drcTolerances.minViaEdgeToPadEdgeClearance??simpleRouteJson.minViaEdgeToPadEdgeClearance,minViaHoleEdgeToViaHoleEdgeClearance=drcTolerances.minViaHoleEdgeToViaHoleEdgeClearance??simpleRouteJson.minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance=drcTolerances.minPlatedHoleDrillEdgeToDrillEdgeClearance??simpleRouteJson.minPlatedHoleDrillEdgeToDrillEdgeClearance,minPadEdgeToPadEdgeClearance=drcTolerances.minPadEdgeToPadEdgeClearance??simpleRouteJson.minPadEdgeToPadEdgeClearance,minBoardEdgeClearance=drcTolerances.minBoardEdgeClearance??simpleRouteJson.minBoardEdgeClearance;return{...simpleRouteJson,connections:applyMinTraceWidthToConnections(simpleRouteJson.connections,drcTolerances.minTraceWidth),minTraceWidth,minViaDiameter:minViaPadDiameter,minViaHoleDiameter,minViaPadDiameter,min_via_hole_diameter:minViaHoleDiameter,min_via_pad_diameter:minViaPadDiameter,minTraceToPadEdgeClearance,minViaEdgeToPadEdgeClearance,minViaHoleEdgeToViaHoleEdgeClearance,minPlatedHoleDrillEdgeToDrillEdgeClearance,minPadEdgeToPadEdgeClearance,minBoardEdgeClearance}}var POINT_MATCH_TOLERANCE=1e-6,pointsMatch3=(first,second)=>Math.abs(first.x-second.x)<=POINT_MATCH_TOLERANCE&&Math.abs(first.y-second.y)<=POINT_MATCH_TOLERANCE&&first.layer===second.layer,removeCompletedFanoutConnections=(simpleRouteJson,routingPcbGroupId)=>{let connections=simpleRouteJson.connections.filter(connection=>connection.routingPcbGroupId!==routingPcbGroupId),includedConnectionNames=new Set(connections.map(connection=>connection.name)),differentialPairs=[];for(let differentialPair of simpleRouteJson.differentialPairs??[]){let positiveConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[0]),negativeConnectionIncluded=includedConnectionNames.has(differentialPair.connectionNames[1]);if(positiveConnectionIncluded!==negativeConnectionIncluded)throw new Error(`Differential pair "${differentialPair.connectionNames.join("/")}" cannot be split at a breakout boundary`);positiveConnectionIncluded&&differentialPairs.push(differentialPair)}let buses=(simpleRouteJson.buses??[]).map(bus=>({...bus,connectionNames:bus.connectionNames.filter(connectionName=>includedConnectionNames.has(connectionName))})).filter(bus=>bus.connectionNames.length>0);return{...simpleRouteJson,connections,differentialPairs:differentialPairs.length>0?differentialPairs:void 0,buses:buses.length>0?buses:void 0}};function Group_syncFanoutExitsWithGlobalConnections({fanoutInputSimpleRouteJson,fanoutOutputSimpleRouteJson,baseSimpleRouteJson,routingPhasePlan}){let routingPcbGroupId=routingPhasePlan.routingPcbGroupId;if(!routingPcbGroupId)return{downstreamSimpleRouteJson:fanoutOutputSimpleRouteJson,baseSimpleRouteJson,synchronizedBreakoutPoints:[]};let outputConnectionByName=new Map(fanoutOutputSimpleRouteJson.connections.map(connection=>[connection.name,connection])),baseConnections=baseSimpleRouteJson.connections.map(connection=>({...connection,pointsToConnect:connection.pointsToConnect.map(point6=>({...point6}))})),synchronizedBreakoutPoints=[];for(let inputConnection of fanoutInputSimpleRouteJson.connections){if(inputConnection.routingPcbGroupId!==routingPcbGroupId||!inputConnection.source_trace_id)continue;let outputConnection=outputConnectionByName.get(inputConnection.name);if(!outputConnection)continue;let globalConnection=baseConnections.find(connection=>connection.routingPcbGroupId!==routingPcbGroupId&&connection.source_trace_id===inputConnection.source_trace_id&&connection.pointsToConnect.some(globalPoint=>inputConnection.pointsToConnect.some(inputPoint=>pointsMatch3(globalPoint,inputPoint))));if(!globalConnection)continue;let previousGlobalPointIndex=globalConnection.pointsToConnect.findIndex(globalPoint=>inputConnection.pointsToConnect.some(inputPoint=>pointsMatch3(globalPoint,inputPoint)));if(previousGlobalPointIndex<0)continue;let previousPoint=globalConnection.pointsToConnect[previousGlobalPointIndex],changedPointIndex=outputConnection.pointsToConnect.findIndex((outputPoint,pointIndex)=>{let inputPoint=inputConnection.pointsToConnect[pointIndex];return inputPoint!==void 0&&!pointsMatch3(outputPoint,inputPoint)});if(changedPointIndex<0)continue;let fanoutExitPoint=outputConnection.pointsToConnect[changedPointIndex],{layers:_previousLayers,terminalVia:_previousTerminalVia,...previousPointWithoutLayerOverrides}=previousPoint,synchronizedGlobalPoint={...previousPointWithoutLayerOverrides,x:fanoutExitPoint.x,y:fanoutExitPoint.y,layer:fanoutExitPoint.layer,...fanoutExitPoint.layers?{layers:[...fanoutExitPoint.layers]}:{},...fanoutExitPoint.terminalVia?{terminalVia:{...fanoutExitPoint.terminalVia}}:{}};globalConnection.pointsToConnect[previousGlobalPointIndex]=synchronizedGlobalPoint,synchronizedBreakoutPoints.push({sourceTraceId:inputConnection.source_trace_id,routingPcbGroupId,previousPoint,fanoutExitPoint})}let newFanoutSourceKeepouts=fanoutOutputSimpleRouteJson.obstacles.filter(obstacle=>obstacle.isFanoutSourceKeepout===!0&&obstacle.componentId!==void 0),completedSourceComponentIds=new Set(newFanoutSourceKeepouts.flatMap(obstacle=>obstacle.componentId===void 0?[]:[obstacle.componentId])),retainedBaseObstacles=baseSimpleRouteJson.obstacles.filter(obstacle=>!obstacle.componentId||!completedSourceComponentIds.has(obstacle.componentId));return{downstreamSimpleRouteJson:removeCompletedFanoutConnections(fanoutOutputSimpleRouteJson,routingPcbGroupId),baseSimpleRouteJson:{...baseSimpleRouteJson,connections:baseConnections,obstacles:[...retainedBaseObstacles,...newFanoutSourceKeepouts]},synchronizedBreakoutPoints}}function getJumperPadInfos(db2){let padInfos=[],jumperSmtpads=db2.pcb_smtpad.list().filter(pad2=>{let component=db2.pcb_component.get(pad2.pcb_component_id);return component?db2.source_component.get(component.source_component_id)?.name?.startsWith("__autoplaced_jumper"):!1});for(let smtpad2 of jumperSmtpads)if(smtpad2.shape!=="polygon"&&smtpad2.pcb_port_id){if(smtpad2.shape==="rect"||smtpad2.shape==="rotated_rect"){let halfWidth=smtpad2.width/2,halfHeight=smtpad2.height/2;padInfos.push({pcb_port_id:smtpad2.pcb_port_id,x:smtpad2.x,y:smtpad2.y,minX:smtpad2.x-halfWidth,maxX:smtpad2.x+halfWidth,minY:smtpad2.y-halfHeight,maxY:smtpad2.y+halfHeight})}else if(smtpad2.shape==="circle"){let radius=smtpad2.radius;padInfos.push({pcb_port_id:smtpad2.pcb_port_id,x:smtpad2.x,y:smtpad2.y,minX:smtpad2.x-radius,maxX:smtpad2.x+radius,minY:smtpad2.y-radius,maxY:smtpad2.y+radius})}}return padInfos}function findJumperPortAtPosition(padInfos,x6,y2,tolerance=.01){for(let pad2 of padInfos)if(Math.abs(pad2.x-x6)<tolerance&&Math.abs(pad2.y-y2)<tolerance)return pad2.pcb_port_id}function findJumperPortContainingPoint(padInfos,x6,y2){for(let pad2 of padInfos)if(x6>=pad2.minX&&x6<=pad2.maxX&&y2>=pad2.minY&&y2<=pad2.maxY)return pad2}function splitRouteAtJumperPads(route,padInfos){if(route.length===0||padInfos.length===0)return[route];let segments=[],currentSegment=[];for(let i6=0;i6<route.length;i6++){let point6=route[i6];if(currentSegment.push(point6),point6.route_type==="wire"&&i6>0&&i6<route.length-1){let padInfo=findJumperPortContainingPoint(padInfos,point6.x,point6.y);if(padInfo){point6.end_pcb_port_id||(point6.end_pcb_port_id=padInfo.pcb_port_id),segments.push(currentSegment);let newStartPoint={...point6};delete newStartPoint.end_pcb_port_id,newStartPoint.start_pcb_port_id||(newStartPoint.start_pcb_port_id=padInfo.pcb_port_id),currentSegment=[newStartPoint]}}}return currentSegment.length>0&&segments.push(currentSegment),segments}function addPortIdsToTracesAtJumperPads(segments,db2){let padInfos=getJumperPadInfos(db2);if(padInfos.length===0)return segments;let result=[];for(let segment2 of segments){let subSegments=splitRouteAtJumperPads(segment2,padInfos);for(let subSegment of subSegments)if(subSegment.length>0){let firstPoint=subSegment[0],lastPoint=subSegment[subSegment.length-1];if(firstPoint.route_type==="wire"&&!firstPoint.start_pcb_port_id){let portId=findJumperPortAtPosition(padInfos,firstPoint.x,firstPoint.y);portId&&(firstPoint.start_pcb_port_id=portId)}if(lastPoint.route_type==="wire"&&!lastPoint.end_pcb_port_id){let portId=findJumperPortAtPosition(padInfos,lastPoint.x,lastPoint.y);portId&&(lastPoint.end_pcb_port_id=portId)}result.push(subSegment)}}return result}var claimSrjAssignablePcbViasTraversedByRoute=({db:db2,pcbTrace,routeWithSrjMetadata})=>{for(let routePoint of routeWithSrjMetadata){if(routePoint.route_type!=="through_pad")continue;let pcbViaId=routePoint.circuitJsonMetadata?.pcb_via_id;if(!pcbViaId)continue;let assignablePcbVia=db2.pcb_via.get(pcbViaId);!assignablePcbVia?.net_is_assignable||assignablePcbVia.net_assigned&&assignablePcbVia.pcb_trace_id!==pcbTrace.pcb_trace_id||db2.pcb_via.update(assignablePcbVia.pcb_via_id,{pcb_trace_id:pcbTrace.pcb_trace_id,net_assigned:!0})}},getAxisGap=(firstMinimum,firstMaximum,secondMinimum,secondMaximum)=>Math.max(secondMinimum-firstMaximum,firstMinimum-secondMaximum),findFanoutPhaseSeparationConflict=regions=>{for(let firstIndex=0;firstIndex<regions.length;firstIndex++){let firstRegion=regions[firstIndex];for(let secondIndex=firstIndex+1;secondIndex<regions.length;secondIndex++){let secondRegion=regions[secondIndex];if(firstRegion.regionId&&firstRegion.regionId===secondRegion.regionId)continue;let horizontalGap=getAxisGap(firstRegion.bounds.minX,firstRegion.bounds.maxX,secondRegion.bounds.minX,secondRegion.bounds.maxX),verticalGap=getAxisGap(firstRegion.bounds.minY,firstRegion.bounds.maxY,secondRegion.bounds.minY,secondRegion.bounds.maxY),availableGap=Math.max(horizontalGap,verticalGap),requiredGap=firstRegion.boundaryKeepaway+secondRegion.boundaryKeepaway;if(availableGap+1e-6<requiredGap)return{firstRegion,secondRegion,availableGap,requiredGap}}}};function getAccumulatedPcbTracesWithStageOutputReplacements({accumulatedPcbTraces,stageOutputPcbTraces}){let stageOutputPcbTraceIds=new Set(stageOutputPcbTraces.map(trace=>trace.pcb_trace_id));return[...accumulatedPcbTraces.filter(trace=>!stageOutputPcbTraceIds.has(trace.pcb_trace_id)),...stageOutputPcbTraces]}var POINT_EPSILON2=1e-6;function isPointOnWireSegment({point:point6,segmentStart,segmentEnd}){return point6.layer&&(segmentStart.layer!==point6.layer||segmentEnd.layer!==point6.layer)?!1:pointToSegmentDistance(point6,segmentStart,segmentEnd)<=POINT_EPSILON2}function isPointInSmtPad({point:point6,pad:pad2,traceWidth=0}){return pad2.shape==="rect"||pad2.shape==="rotated_rect"?Math.abs(point6.x-pad2.x)<=pad2.width/2+traceWidth/2&&Math.abs(point6.y-pad2.y)<=pad2.height/2+traceWidth/2:pad2.shape==="circle"?distance2(point6,pad2)<=pad2.radius+traceWidth/2:!1}function isPointInPlatedHole({point:point6,hole,traceWidth=0}){return distance2(point6,hole)<=(hole.outer_diameter??hole.hole_diameter??0)/2+traceWidth/2}function getEndpointSourcePortIdsFromGeometry(db2,trace){let sourcePortIds=new Set,route=trace.route,endpoints=[route[0],route[route.length-1]].filter(point6=>!!point6&&point6.route_type==="wire"&&point6.x!==void 0&&point6.y!==void 0);for(let endpoint of endpoints){for(let pcbPort of db2.pcb_port.list())pcbPort.source_port_id&&(endpoint.layer&&pcbPort.layers&&!pcbPort.layers.includes(endpoint.layer)||distance2(endpoint,pcbPort)<=.01&&sourcePortIds.add(pcbPort.source_port_id));for(let smtpad2 of db2.pcb_smtpad.list()){if(!smtpad2.pcb_port_id||endpoint.layer&&smtpad2.layer!==endpoint.layer||!isPointInSmtPad({point:endpoint,pad:smtpad2,traceWidth:endpoint.width}))continue;let sourcePortId=db2.pcb_port.get(smtpad2.pcb_port_id)?.source_port_id;sourcePortId&&sourcePortIds.add(sourcePortId)}for(let hole of db2.pcb_plated_hole.list()){if(!hole.pcb_port_id||!isPointInPlatedHole({point:endpoint,hole,traceWidth:endpoint.width}))continue;let sourcePortId=db2.pcb_port.get(hole.pcb_port_id)?.source_port_id;sourcePortId&&sourcePortIds.add(sourcePortId)}}return[...sourcePortIds]}function getWireRouteEndpoints(trace){let route=trace.route.filter(point6=>point6.route_type==="wire"&&point6.x!==void 0&&point6.y!==void 0);return[route[0],route[route.length-1]].filter(point6=>!!point6)}function getSourceIdsFromConnectedPcbTraces(db2,trace){let sourceIds=new Set,endpoints=getWireRouteEndpoints(trace);if(endpoints.length===0)return[];for(let existingTrace of db2.pcb_trace.list()){if(!existingTrace.source_trace_id||existingTrace.pcb_trace_id===trace.pcb_trace_id||!db2.source_trace.get(existingTrace.source_trace_id)&&!db2.source_net.get(existingTrace.source_trace_id))continue;let existingRoute=existingTrace.route.filter(point6=>point6.route_type==="wire");for(let i6=0;i6<existingRoute.length-1;i6++){let segmentStart=existingRoute[i6],segmentEnd=existingRoute[i6+1];if(!(!segmentStart||!segmentEnd))for(let endpoint of endpoints)isPointOnWireSegment({point:endpoint,segmentStart,segmentEnd})&&sourceIds.add(existingTrace.source_trace_id)}}return[...sourceIds]}function getSourcePortIdsFromRoutedTrace(db2,trace){let sourcePortIds=new Set;for(let point6 of trace.route)for(let pcbPortId of[point6.start_pcb_port_id,point6.end_pcb_port_id]){if(!pcbPortId)continue;let sourcePortId=db2.pcb_port.get(pcbPortId)?.source_port_id;sourcePortId&&sourcePortIds.add(sourcePortId)}return sourcePortIds.size>0?[...sourcePortIds]:getEndpointSourcePortIdsFromGeometry(db2,trace)}function buildSourceConnectivityMap(sourceTraces){let connMap=new ConnectivityMap({});return connMap.addConnections(sourceTraces.map(trace=>[trace.source_trace_id,...trace.connected_source_port_ids,...trace.connected_source_net_ids])),connMap}function getSourceTraceIdForRoutedTrace({db:db2,trace,subcircuit_id}){if(trace.source_trace_id&&(db2.source_trace.get(trace.source_trace_id)??db2.source_net.get(trace.source_trace_id)))return trace.source_trace_id;let sourcePortIds=getSourcePortIdsFromRoutedTrace(db2,trace);if(sourcePortIds.length===0)return getSourceIdsFromConnectedPcbTraces(db2,trace)[0];let sourceTraces=db2.source_trace.list(),connMap=buildSourceConnectivityMap(sourceTraces),endpointNetIds=sourcePortIds.map(sourcePortId=>connMap.getNetConnectedToId(sourcePortId)).filter(netId=>!!netId),exactSourceTrace=sourcePortIds.length>=2?sourceTraces.find(sourceTrace=>sourcePortIds.every(sourcePortId=>sourceTrace.connected_source_port_ids.includes(sourcePortId))):void 0;if(exactSourceTrace)return exactSourceTrace.source_trace_id;let sourceTracesInEndpointNets=sourceTraces.filter(sourceTrace=>{let sourceTraceNetId=connMap.getNetConnectedToId(sourceTrace.source_trace_id);return endpointNetIds.some(netId=>netId===sourceTraceNetId)}),connectedToEndpoint=sourceTracesInEndpointNets.filter(sourceTrace=>sourceTrace.connected_source_port_ids.some(sourcePortId=>sourcePortIds.includes(sourcePortId))),candidates=connectedToEndpoint.length>0?connectedToEndpoint:sourceTracesInEndpointNets;if(candidates.length!==0)return(candidates.find(sourceTrace=>sourceTrace.subcircuit_id===subcircuit_id)??candidates[0])?.source_trace_id}function groupPadsByInternalConnection(pads,orientation4){let groups=[];for(let pad2 of pads){let key=orientation4==="vertical"?pad2.center.y:pad2.center.x,foundGroup=!1;for(let group of groups){let groupKey=orientation4==="vertical"?group[0].center.y:group[0].center.x;if(Math.abs(key-groupKey)<.01){group.push(pad2),foundGroup=!0;break}}foundGroup||groups.push([pad2])}return groups.filter(g4=>g4.length>=2)}function insertAutoplacedJumpers(params){let{db:db2,output_jumpers,subcircuit_id}=params;for(let jumperIndex=0;jumperIndex<output_jumpers.length;jumperIndex++){let jumper=output_jumpers[jumperIndex],sourceComponent=db2.source_component.insert({ftype:"simple_chip",name:`__autoplaced_jumper_${jumperIndex}`,supplier_part_numbers:{}}),rotation42=jumper.orientation==="horizontal"?0:90,firstPadLayer=jumper.pads[0]?.layer||jumper.pads[0]?.layers?.[0]||"top",pcbComponent=db2.pcb_component.insert({source_component_id:sourceComponent.source_component_id,center:jumper.center,rotation:rotation42,layer:firstPadLayer,width:jumper.width||0,height:jumper.height||0,obstructs_within_bounds:!1}),padData=[];for(let padIndex=0;padIndex<jumper.pads.length;padIndex++){let pad2=jumper.pads[padIndex],pinNumber=padIndex+1,sourcePort=db2.source_port.insert({source_component_id:sourceComponent.source_component_id,name:`pin${pinNumber}`,pin_number:pinNumber}),padLayer=pad2.layer||pad2.layers?.[0]||"top",pcbPort=db2.pcb_port.insert({pcb_component_id:pcbComponent.pcb_component_id,source_port_id:sourcePort.source_port_id,x:pad2.center.x,y:pad2.center.y,layers:[padLayer]}),pcbSmtpad=db2.pcb_smtpad.insert({pcb_component_id:pcbComponent.pcb_component_id,pcb_port_id:pcbPort.pcb_port_id,shape:"rect",x:pad2.center.x,y:pad2.center.y,width:pad2.width,height:pad2.height,layer:padLayer});padData.push({pad:pad2,sourcePortId:sourcePort.source_port_id,pcbSmtpadId:pcbSmtpad.pcb_smtpad_id})}let internalGroups=groupPadsByInternalConnection(jumper.pads,jumper.orientation);for(let group of internalGroups){let sourcePortIds=[];for(let groupPad of group){let padInfo=padData.find(p3=>Math.abs(p3.pad.center.x-groupPad.center.x)<.01&&Math.abs(p3.pad.center.y-groupPad.center.y)<.01);padInfo&&sourcePortIds.push(padInfo.sourcePortId)}sourcePortIds.length>=2&&db2.source_component_internal_connection.insert({source_component_id:sourceComponent.source_component_id,subcircuit_id:subcircuit_id??void 0,source_port_ids:sourcePortIds})}}}function convertPcbTraceToSimplifiedPcbTrace(trace){return{...trace,type:"pcb_trace",pcb_trace_id:trace.pcb_trace_id,connection_name:trace.connection_name??trace.source_trace_id??trace.pcb_trace_id,route:trace.route.map(point6=>({...point6}))}}function getRelevantSubcircuitIdsForReroute(group){let relevantSubcircuitIds=new Set;if(!group.subcircuit_id)return relevantSubcircuitIds;relevantSubcircuitIds.add(group.subcircuit_id);let db2=group.root?.db;if(!db2)return relevantSubcircuitIds;for(let subcircuitId of getDescendantSubcircuitIds2(db2,group.subcircuit_id))relevantSubcircuitIds.add(subcircuitId);return relevantSubcircuitIds}function getExistingPcbTracesForReroute(group){let db2=group.root?.db;if(!db2)return[];let relevantSubcircuitIds=getRelevantSubcircuitIdsForReroute(group);return db2.pcb_trace.list().filter(trace=>!trace.route||trace.route.length<2?!1:group.subcircuit_id?!!(trace.subcircuit_id&&relevantSubcircuitIds.has(trace.subcircuit_id)):!0)}function getSourceTraceIdsFromRerouteName(value){return typeof value!="string"||value.length===0?[]:value.split("__").flatMap(connectionNamePart=>{if(connectionNamePart.length===0)return[];let sourceTraceIds=[connectionNamePart],rerouteSuffixIndex=connectionNamePart.indexOf("_reroute_");return rerouteSuffixIndex>0&&sourceTraceIds.push(connectionNamePart.slice(0,rerouteSuffixIndex)),sourceTraceIds})}function addPossibleReplacementSourceTraceId(sourceTraceIds,value){if(!(typeof value!="string"||value.length===0)){sourceTraceIds.add(value);for(let sourceTraceId of getSourceTraceIdsFromRerouteName(value))sourceTraceIds.add(sourceTraceId)}}function deleteExistingPcbTracesReplacedBy({group,outputPcbTraces,pcbTraceIdsToReplace=[]}){let db2=group.root?.db;if(!db2)return;let replacementPcbTraceIds=new Set(pcbTraceIdsToReplace),replacementSourceTraceIds=new Set;for(let trace of outputPcbTraces){if(trace.type!=="pcb_trace")continue;let replacementTrace=trace;replacementPcbTraceIds.add(replacementTrace.pcb_trace_id),addPossibleReplacementSourceTraceId(replacementSourceTraceIds,replacementTrace.source_trace_id),addPossibleReplacementSourceTraceId(replacementSourceTraceIds,replacementTrace.connection_name),addPossibleReplacementSourceTraceId(replacementSourceTraceIds,replacementTrace.rootConnectionName)}if(replacementPcbTraceIds.size===0&&replacementSourceTraceIds.size===0)return;let tracesToDelete=getExistingPcbTracesForReroute(group).filter(trace=>replacementPcbTraceIds.has(trace.pcb_trace_id)||!!(trace.source_trace_id&&trace.subcircuit_id===group.subcircuit_id&&replacementSourceTraceIds.has(trace.source_trace_id)));if(tracesToDelete.length===0)return;let deletedPcbTraceIds=new Set(tracesToDelete.map(trace=>trace.pcb_trace_id));for(let via of db2.pcb_via.list())via.pcb_trace_id&&deletedPcbTraceIds.has(via.pcb_trace_id)&&db2.pcb_via.delete(via.pcb_via_id);for(let trace of tracesToDelete)db2.pcb_trace.delete(trace.pcb_trace_id)}function getExistingSimplifiedPcbTracesForReroute(group){return getExistingPcbTracesForReroute(group).map(convertPcbTraceToSimplifiedPcbTrace)}function splitPcbTracesOnJumperSegments(route){let jumperRoutes=route.filter(p3=>p3.route_type==="jumper"),wireAndViaRoutes=route.filter(p3=>p3.route_type!=="jumper");if(jumperRoutes.length===0)return null;let splitRanges=[];for(let jumperRoute of jumperRoutes){let jumperStart=jumperRoute.start,jumperEnd=jumperRoute.end,startIdx=-1,endIdx=-1,minStartDist=1/0,minEndDist=1/0;for(let i6=0;i6<wireAndViaRoutes.length;i6++){let p3=wireAndViaRoutes[i6];if(p3.route_type!=="wire")continue;let distToStart=Math.hypot(p3.x-jumperStart.x,p3.y-jumperStart.y),distToEnd=Math.hypot(p3.x-jumperEnd.x,p3.y-jumperEnd.y);distToStart<minStartDist&&(minStartDist=distToStart,startIdx=i6),distToEnd<minEndDist&&(minEndDist=distToEnd,endIdx=i6)}startIdx>endIdx&&([startIdx,endIdx]=[endIdx,startIdx]),startIdx>=0&&endIdx>=0&&startIdx!==endIdx&&splitRanges.push({startIdx,endIdx})}splitRanges.sort((a6,b6)=>a6.startIdx-b6.startIdx);let segments=[],currentStart=0;for(let range2 of splitRanges)currentStart<range2.startIdx&&segments.push(wireAndViaRoutes.slice(currentStart,range2.startIdx+1)),currentStart=range2.endIdx;return currentStart<wireAndViaRoutes.length&&segments.push(wireAndViaRoutes.slice(currentStart)),segments}function computeCenterFromAnchorPosition(anchorPosition,ctx){let{width,height,pcbAnchorAlignment}=ctx;if(!pcbAnchorAlignment)return anchorPosition;let alignment=pcbAnchorAlignment;if(typeof width!="number"||typeof height!="number")return anchorPosition;let ax3=anchorPosition.x,ay3=anchorPosition.y;switch(alignment){case"top_left":return{x:ax3+width/2,y:ay3-height/2};case"top_center":return{x:ax3,y:ay3-height/2};case"top_right":return{x:ax3-width/2,y:ay3-height/2};case"center_left":return{x:ax3+width/2,y:ay3};case"center_right":return{x:ax3-width/2,y:ay3};case"bottom_left":return{x:ax3+width/2,y:ay3+height/2};case"bottom_center":return{x:ax3,y:ay3+height/2};case"bottom_right":return{x:ax3-width/2,y:ay3+height/2};default:return anchorPosition}}var getDistanceToPoint=(routePoint,targetPoint)=>{let position4=getRoutePointPosition2(routePoint);return Math.hypot(position4.x-targetPoint.x,position4.y-targetPoint.y)},removeSrjMetadataFromPcbTraceRoute=route=>route.map(routePoint=>{let{circuitJsonMetadata:_circuitJsonMetadata,...circuitJsonRoutePoint}=routePoint;return circuitJsonRoutePoint}),platformAllowsLegacyAutorouters=group=>{let platform=group.root?.platform;return platform!==void 0&&"allowLegacyAutorouters"in platform&&platform.allowLegacyAutorouters===!0},getDisabledLegacyGroupAutorouterPreset=group=>{if(platformAllowsLegacyAutorouters(group))return null;let resolvedGroupAutorouter=group._parsedProps.autorouter??group.getInheritedProperty("autorouter");return getLegacyAutorouterPreset(resolvedGroupAutorouter)},getDisabledLegacyAutorouterPreset=group=>{if(platformAllowsLegacyAutorouters(group))return null;let legacyGroupAutorouterPreset=getDisabledLegacyGroupAutorouterPreset(group);if(legacyGroupAutorouterPreset)return legacyGroupAutorouterPreset;let routingPhaseAutorouters=group.selectAll("autoroutingphase").map(autoroutingPhase=>autoroutingPhase._parsedProps.autorouter);for(let autorouter of routingPhaseAutorouters){let legacyAutorouterPreset=getLegacyAutorouterPreset(autorouter);if(legacyAutorouterPreset)return legacyAutorouterPreset}return null},ensureRouteStartsAtSourceTraceStart=({db:db2,route,routeThicknessMode,sourceTraceId})=>{if(!sourceTraceId||route.length<2)return route;let firstSourcePortId=db2.source_trace.get(sourceTraceId)?.connected_source_port_ids[0];if(!firstSourcePortId)return route;let firstPcbPort=db2.pcb_port.list().find(port=>port.source_port_id===firstSourcePortId);if(!firstPcbPort)return route;let firstPoint=route[0],lastPoint=route[route.length-1];return getDistanceToPoint(lastPoint,firstPcbPort)<getDistanceToPoint(firstPoint,firstPcbPort)?reversePcbTraceRoute(route,routeThicknessMode):route},Group5=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"pcb_group_id",null);__publicField(this,"schematic_group_id",null);__publicField(this,"subcircuit_id",null);__publicField(this,"_hasStartedAsyncAutorouting",!1);__publicField(this,"_pcbPlacementDrcErrorCount",null);__publicField(this,"_pcbPlacementDrcCheckError",null);__publicField(this,"_pcbPlacementDrcChecksPending",!1);__publicField(this,"_standaloneSubcircuitDrcChecksComplete",!1);__publicField(this,"_standaloneSubcircuitDrcChecksInProgress",!1);__publicField(this,"_isInflatedFromCircuitJson",!1);__publicField(this,"_isolatedCircuitJson",null);__publicField(this,"_normalComponentNameMap",null);__publicField(this,"_asyncAutoroutingResult",null);__publicField(this,"unnamedElementCounter",{})}get _isIsolatedSubcircuit(){return!!this.getInheritedProperty("_subcircuitCachingEnabled")}getNormalComponentNameMap(){if(this._normalComponentNameMap)return this._normalComponentNameMap;let nameMap=new Map,collectNamedComponents=component=>{if(component._isNormalComponent&&component.name){let componentsWithSameName=nameMap.get(component.name);componentsWithSameName?componentsWithSameName.push(component):nameMap.set(component.name,[component])}for(let child of component.children)child.isSubcircuit||collectNamedComponents(child)};for(let child of this.children)child.isSubcircuit||collectNamedComponents(child);return this._normalComponentNameMap=nameMap,nameMap}get config(){return{zodProps:groupProps,componentName:"Group"}}initPorts(opts={}){let schPinArrangement=this._getSchematicPortArrangement();this._parsedProps?.showAsSchematicBox&&!this._parsedProps.pinLabels&&schPinArrangement&&getPinsFromPortArrangement(schPinArrangement).some(pin=>typeof pin=="string")||super.initPorts(opts)}_getSchematicPortArrangementFromPortDirections(){if(!this._parsedProps?.showAsSchematicBox)return null;let sidePins={leftSide:[],rightSide:[],topSide:[],bottomSide:[]};for(let port of this.children){if(port.componentName!=="Port")continue;let direction2=port._parsedProps.direction;if(!direction2)continue;let pin=port._parsedProps.pinNumber??port._parsedProps.name??void 0;if(pin===void 0)continue;sidePins[direction2==="left"?"leftSide":direction2==="right"?"rightSide":direction2==="up"?"topSide":"bottomSide"].push(pin)}if(sidePins.leftSide.length===0&&sidePins.rightSide.length===0&&sidePins.topSide.length===0&&sidePins.bottomSide.length===0)return null;let arrangement={};return sidePins.leftSide.length>0&&(arrangement.leftSide={pins:sidePins.leftSide,direction:"top-to-bottom"}),sidePins.rightSide.length>0&&(arrangement.rightSide={pins:sidePins.rightSide,direction:"top-to-bottom"}),sidePins.topSide.length>0&&(arrangement.topSide={pins:sidePins.topSide,direction:"left-to-right"}),sidePins.bottomSide.length>0&&(arrangement.bottomSide={pins:sidePins.bottomSide,direction:"left-to-right"}),arrangement}_getSchematicPortArrangement(){return super._getSchematicPortArrangement()??this._getSchematicPortArrangementFromPortDirections()}_ensureSchematicBoxPortsFromConnections(){if(this._parsedProps?.showAsSchematicBox&&this._parsedProps?.connections)for(let[pinName,target]of Object.entries(this._parsedProps.connections)){if(this.children.find(child=>child.componentName==="Port"&&child.isMatchingAnyOf([pinName])))continue;let pinNumberMatch=pinName.match(/^pin(\d+)$/i)??pinName.match(/^(\d+)$/),pinNumber=pinNumberMatch?Number(pinNumberMatch[1]):void 0;this.add(new Port({name:pinName,pinNumber,connectsTo:target}))}}doInitialInitializePortsFromChildren(){super.doInitialInitializePortsFromChildren(),this._ensureSchematicBoxPortsFromConnections()}updateInitializePortsFromChildren(){super.updateInitializePortsFromChildren(),this._ensureSchematicBoxPortsFromConnections()}_getPrimaryPinCount(){let superPinCount=super._getPrimaryPinCount();if(!this._parsedProps?.showAsSchematicBox)return superPinCount;let directPortPinNumbers=this.children.filter(child=>child.componentName==="Port").map(port=>port._parsedProps.pinNumber).filter(pinNumber=>pinNumber!==void 0);return directPortPinNumbers.length===0?superPinCount:Math.max(superPinCount,...directPortPinNumbers)}_getPinLabelsFromPorts(){return this._parsedProps?.showAsSchematicBox?getGroupSchematicBoxPinLabels(this):super._getPinLabelsFromPorts()}doInitialSourceGroupRender(){let{db:db2}=this.root,hasExplicitName=typeof this._parsedProps.name=="string"&&this._parsedProps.name.length>0,source_group3=db2.source_group.insert({name:this.name,is_subcircuit:this.isSubcircuit,was_automatically_named:!hasExplicitName});this.source_group_id=source_group3.source_group_id,this.isSubcircuit&&(this.subcircuit_id=`subcircuit_${source_group3.source_group_id}`,db2.source_group.update(source_group3.source_group_id,{subcircuit_id:this.subcircuit_id}))}doInitialSourceRender(){let{db:db2}=this.root;for(let child of this.getDescendants())child.getGroup()?.source_group_id===this.source_group_id&&db2.source_component.update(child.source_component_id,{source_group_id:this.source_group_id});if(!this.isSubcircuit)return;let disabledLegacyAutorouterPreset=getDisabledLegacyAutorouterPreset(this);disabledLegacyAutorouterPreset&&db2.source_property_ignored_warning.insert({source_component_id:this.source_component_id??"",property_name:"autorouter",subcircuit_id:this.subcircuit_id??void 0,error_type:"source_property_ignored_warning",message:`The "${disabledLegacyAutorouterPreset}" autorouter is deprecated, so autorouting has been disabled for this subcircuit. Use the default autorouter and introduce <autoroutingphase /> or <fanout /> elements as needed.`})}doInitialSourceParentAttachment(){let{db:db2}=this.root,parentGroup=this.parent?.getGroup?.();if(parentGroup?.source_group_id&&db2.source_group.update(this.source_group_id,{parent_source_group_id:parentGroup.source_group_id}),!this.isSubcircuit||isAssemblyDeviceContainer(this.parent))return;let parent_subcircuit_id=this.parent?.getSubcircuit?.()?.subcircuit_id;parent_subcircuit_id&&db2.source_group.update(this.source_group_id,{parent_subcircuit_id})}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,groupProps2=props,hasOutline=groupProps2.outline&&groupProps2.outline.length>0,numericOutline=hasOutline?groupProps2.outline.map(point6=>({x:distance.parse(point6.x),y:distance.parse(point6.y)})):void 0,ctx=this.props,anchorPosition=this._getGlobalPcbPositionBeforeLayout(),center2=computeCenterFromAnchorPosition(anchorPosition,ctx),pcb_group3=db2.pcb_group.insert({is_subcircuit:this.isSubcircuit,subcircuit_id:this.subcircuit_id??this.getSubcircuit()?.subcircuit_id,name:this.name,anchor_position:anchorPosition,center:center2,...hasOutline?{outline:numericOutline}:{width:0,height:0},pcb_component_ids:[],source_group_id:this.source_group_id,autorouter_configuration:props.autorouter?{trace_clearance:props.autorouter.traceClearance}:void 0,anchor_alignment:props.pcbAnchorAlignment??null});this.pcb_group_id=pcb_group3.pcb_group_id;for(let child of this.children)db2.pcb_component.update(child.pcb_component_id,{pcb_group_id:pcb_group3.pcb_group_id})}doInitialPcbPrimitiveRender(){this.calculatePcbGroupBounds()}calculatePcbGroupBounds(pcbContentBounds){if(!this.pcb_group_id||this.root?.pcbDisabled)return;let{db:db2}=this.root,props=this._parsedProps,hasOutline=props.outline&&props.outline.length>0,hasExplicitPositioning=this._parsedProps.pcbX!==void 0||this._parsedProps.pcbY!==void 0;if(hasOutline){let numericOutline=props.outline.map(point6=>({x:distance.parse(point6.x),y:distance.parse(point6.y)})),outlineBounds=getBoundsFromPoints2(numericOutline);if(!outlineBounds)return;let centerX2=(outlineBounds.minX+outlineBounds.maxX)/2,centerY2=(outlineBounds.minY+outlineBounds.maxY)/2,center22=hasExplicitPositioning?db2.pcb_group.get(this.pcb_group_id)?.center??{x:centerX2,y:centerY2}:{x:centerX2,y:centerY2};db2.pcb_group.update(this.pcb_group_id,{center:center22});return}let contentBounds=pcbContentBounds;if(!contentBounds){let bounds=getBoundsOfPcbComponents(this.children);contentBounds={center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},width:bounds.width,height:bounds.height}}let{width,height}=contentBounds,{x:centerX,y:centerY}=contentBounds.center;if(this.isSubcircuit||this.isRoutingDirective){let{padLeft,padRight,padTop,padBottom}=this._resolvePcbPadding();width+=padLeft+padRight,height+=padTop+padBottom,centerX+=(padRight-padLeft)/2,centerY+=(padTop-padBottom)/2}let resolvedWidth=Number(props.width??width),resolvedHeight=Number(props.height??height),existingCenter=db2.pcb_group.get(this.pcb_group_id)?.center??{x:centerX,y:centerY},shouldUsePcbContentCenter=this.isSubcircuit||pcbContentBounds!==void 0,center2=hasExplicitPositioning?shouldUsePcbContentCenter?{x:props.width===void 0?centerX:existingCenter.x,y:props.height===void 0?centerY:existingCenter.y}:existingCenter:{x:centerX,y:centerY};if(hasExplicitPositioning&&props.pcbAnchorAlignment){let anchorPosition=this._getGlobalPcbPositionBeforeLayout(),anchorAlignedCenter=computeCenterFromAnchorPosition(anchorPosition,{...this.props,width:resolvedWidth,height:resolvedHeight});(Math.abs(anchorAlignedCenter.x-center2.x)>1e-6||Math.abs(anchorAlignedCenter.y-center2.y)>1e-6)&&this._repositionOnPcb(anchorAlignedCenter),center2=anchorAlignedCenter}db2.pcb_group.update(this.pcb_group_id,{width:resolvedWidth,height:resolvedHeight,center:center2})}updatePcbPrimitiveRender(){this.calculatePcbGroupBounds()}getNextAvailableName(elm){var _a527,_b4;return(_a527=this.unnamedElementCounter)[_b4=elm.lowercaseComponentName]??(_a527[_b4]=1),`unnamed_${elm.lowercaseComponentName}${this.unnamedElementCounter[elm.lowercaseComponentName]++}`}_resolvePcbPadding(){let props=this._parsedProps,layout=props.pcbLayout,getPaddingValue=key=>{let layoutValue=layout?.[key],propsValue=props[key];if(typeof layoutValue=="number")return layoutValue;if(typeof propsValue=="number")return propsValue},generalPadding=getPaddingValue("padding")??0,paddingX=getPaddingValue("paddingX"),paddingY=getPaddingValue("paddingY"),padLeft=getPaddingValue("paddingLeft")??paddingX??generalPadding,padRight=getPaddingValue("paddingRight")??paddingX??generalPadding,padTop=getPaddingValue("paddingTop")??paddingY??generalPadding,padBottom=getPaddingValue("paddingBottom")??paddingY??generalPadding;return{padLeft,padRight,padTop,padBottom}}doInitialCreateTraceHintsFromProps(){let{_parsedProps:props}=this,{db:db2}=this.root,groupProps2=props;if(!this.isSubcircuit)return;let manualTraceHints=groupProps2.manualEdits?.manual_trace_hints;if(manualTraceHints)for(let manualTraceHint of manualTraceHints)this.add(new TraceHint({for:manualTraceHint.pcb_port_selector,offsets:manualTraceHint.offsets}))}doInitialSourceAddConnectivityMapKey(){Group_doInitialSourceAddConnectivityMapKey(this),Group_doInitialAssignSchematicSheetToConnectedComponents(this)}_areChildSubcircuitsRouted(){let subcircuitChildren=this._findDirectChildSubcircuits();for(let subcircuitChild of subcircuitChildren)if(!subcircuitChild._isInflatedFromCircuitJson&&subcircuitChild._hasTracesToRoute()&&subcircuitChild._shouldRouteAsync()&&!subcircuitChild._asyncAutoroutingResult)return!1;return!0}_findDirectChildSubcircuits(){let result=[],visit=children=>{for(let child of children)child.isSubcircuit&&child!==this?result.push(child):visit(child.children)};return visit(this.children),result}_shouldRouteAsync(){if(this._isLegacyAutorouterDisabled())return!1;let autorouter=this._getAutorouterConfig();return autorouter.groupMode==="sequential-trace"?!1:!!(autorouter.local&&autorouter.groupMode==="subcircuit"||!autorouter.local)}_getRoutingPhasePlans(){return Group_getRoutingPhasePlans(this)}_hasTracesToRoute(){let debug132=(0,import_debug11.default)("tscircuit:core:_hasTracesToRoute"),routingPhasePlans=this._getRoutingPhasePlans(),traceCount=0,hasReroutePhaseWithRegion=!1;for(let routingPhasePlan of routingPhasePlans)traceCount+=routingPhasePlan.traces.length,hasReroutePhaseWithRegion||(hasReroutePhaseWithRegion=!!(routingPhasePlan.reroute&&routingPhasePlan.region));if(debug132(`[${this.getString()}] has ${traceCount} traces to route`),traceCount>0)return!0;if(hasReroutePhaseWithRegion){let existingTraceCount=getExistingPcbTracesForReroute(this).length;return debug132(`[${this.getString()}] has ${existingTraceCount} existing pcb traces available for reroute`),existingTraceCount>0}return!1}async _runEffectMakeHttpAutoroutingRequest(){let{db:db2}=this.root,debug132=(0,import_debug11.default)("tscircuit:core:_runEffectMakeHttpAutoroutingRequest"),props=this._parsedProps,autorouterConfig2=this._getAutorouterConfig(),serverUrl=autorouterConfig2.serverUrl,serverMode=autorouterConfig2.serverMode,fetchWithDebug=(url2,options)=>(debug132("fetching",url2),options.headers&&(options.headers["Tscircuit-Core-Version"]=this.root?.getCoreVersion()),fetch(url2,options)),pcbAndSourceCircuitJson=this.root.db.toArray().filter(element=>element.type.startsWith("source_")||element.type.startsWith("pcb_"));if(serverMode==="solve-endpoint"){if(this.props.autorouter?.inputFormat==="simplified"){let preferredTraceWidth=props.defaultTraceWidth??props.nominalTraceWidth,{simpleRouteJson}=getSimpleRouteJsonFromCircuitJson({db:db2,minTraceWidth:Number(props.minTraceWidth??.15),nominalTraceWidth:preferredTraceWidth!=null?Number(preferredTraceWidth):void 0,subcircuit_id:this.subcircuit_id,subcircuitComponent:this});simpleRouteJson.allowViaInPad=autorouterConfig2.allowViaInPad;let{autorouting_result:autorouting_result2}=await fetchWithDebug(`${serverUrl}/autorouting/solve`,{method:"POST",body:JSON.stringify({input_simple_route_json:simpleRouteJson,subcircuit_id:this.subcircuit_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());this._asyncAutoroutingResult=autorouting_result2,this._markDirty("PcbTraceRender");return}let{autorouting_result}=await fetchWithDebug(`${serverUrl}/autorouting/solve`,{method:"POST",body:JSON.stringify({input_circuit_json:pcbAndSourceCircuitJson,subcircuit_id:this.subcircuit_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());this._asyncAutoroutingResult=autorouting_result,this._markDirty("PcbTraceRender");return}let{autorouting_job}=await fetchWithDebug(`${serverUrl}/autorouting/jobs/create`,{method:"POST",body:JSON.stringify({input_circuit_json:pcbAndSourceCircuitJson,provider:"freerouting",autostart:!0,display_name:this.root?.name,subcircuit_id:this.subcircuit_id,server_cache_enabled:autorouterConfig2.serverCacheEnabled}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());for(;;){let{autorouting_job:job}=await fetchWithDebug(`${serverUrl}/autorouting/jobs/get`,{method:"POST",body:JSON.stringify({autorouting_job_id:autorouting_job.autorouting_job_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());if(job.is_finished){let{autorouting_job_output}=await fetchWithDebug(`${serverUrl}/autorouting/jobs/get_output`,{method:"POST",body:JSON.stringify({autorouting_job_id:autorouting_job.autorouting_job_id}),headers:{"Content-Type":"application/json"}}).then(r6=>r6.json());this._asyncAutoroutingResult={output_pcb_traces:autorouting_job_output.output_pcb_traces},this._markDirty("PcbTraceRender");break}if(job.has_error){let err2=new AutorouterError(`Autorouting job failed: ${JSON.stringify(job.error)}`);throw db2.pcb_autorouting_error.insert({pcb_error_id:autorouting_job.autorouting_job_id,error_type:"pcb_autorouting_error",message:err2.message}),err2}await new Promise(resolve=>setTimeout(resolve,100))}}async _runLocalAutorouting(){let{db:db2}=this.root,props=this._parsedProps,debug132=(0,import_debug11.default)("tscircuit:core:_runLocalAutorouting");debug132(`[${this.getString()}] starting local autorouting`);let autorouterConfig2=this._getAutorouterConfig(),isLaserPrefabPreset=this._isLaserPrefabAutorouter(autorouterConfig2),isAutoJumperPreset=this._isAutoJumperAutorouter(autorouterConfig2),isSingleLayerBoard=this._getSubcircuitLayerCount()===1,minTraceWidth=Number(props.minTraceWidth??.15),nominalTraceWidth=Number(props.defaultTraceWidth??props.nominalTraceWidth??minTraceWidth),routingPhasePlans=this._getRoutingPhasePlans(),hasPhasedAutorouting=Group_hasPhasedAutorouting(routingPhasePlans),shouldEmitRoutingPhaseDebugObjects=routingPhasePlans.length>1,routingPhaseDisplayIndexes=new Map(routingPhasePlans.map((plan,index)=>[plan,index]));if(shouldEmitRoutingPhaseDebugObjects)for(let debugObject of db2.pcb_debug_object.list())debugObject.subcircuit_id===this.subcircuit_id&&(debugObject.label?.startsWith("Autorouting phase: ")||/^autorouting phase \d+(?: |$)/.test(debugObject.label??""))&&db2.pcb_debug_object.delete(debugObject.pcb_debug_object_id);let emitRoutingPhaseDebugObject=(routingPhasePlan,bounds)=>{if(!shouldEmitRoutingPhaseDebugObjects)return;let phaseIndex=routingPhaseDisplayIndexes.get(routingPhasePlan);if(phaseIndex===void 0)return;let phaseName=routingPhasePlan.phaseName?.trim();db2.pcb_debug_object.insert({shape:"rect",center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},size:{width:bounds.maxX-bounds.minX,height:bounds.maxY-bounds.minY},label:`autorouting phase ${phaseIndex}${phaseName?` ${phaseName}`:""}`,subcircuit_id:this.subcircuit_id??void 0})},routingStages=routingPhasePlans.flatMap(routingPhasePlan=>{let phaseAutorouterConfig=routingPhasePlan.autorouter?getPresetAutoroutingConfig(routingPhasePlan.autorouter,this.root?.platform):autorouterConfig2,stages=getLocalAutoroutingStages(phaseAutorouterConfig,this.root?.platform);return stages.map((stage,phaseStageIndex)=>({...stage,routingPhasePlan,phaseStageIndex,phaseStageCount:stages.length}))}),fanoutPourNetMap=routingStages.some(({autorouterConfig:autorouterConfig22})=>["fanout","single_layer_fanout"].includes(autorouterConfig22.preset??""))?Group_getFanoutPourNetMap(this,routingPhasePlans):void 0,{simpleRouteJson:baseSimpleRouteJson}=getSimpleRouteJsonFromCircuitJson({db:db2,minTraceWidth,nominalTraceWidth,subcircuit_id:this.subcircuit_id,subcircuitComponent:this,fanoutPourNetMap}),emitFanoutBoundsConflictWarning=routingPhasePlan=>{let fanoutRegionPcbGroupId=routingPhasePlan.fanoutRegionPcbGroupId;if(!fanoutRegionPcbGroupId)return;let pcbGroup=db2.pcb_group.get(fanoutRegionPcbGroupId),sourceComponentId=db2.pcb_component.list().find(component=>component.pcb_group_id===fanoutRegionPcbGroupId)?.source_component_id;if(!sourceComponentId)return;let message=`${pcbGroup?.name??"Breakout"} defines conflicting fanout bounds with explicit breakout geometry and fanoutBoundaryPadding. Explicit breakout geometry takes precedence, so fanoutBoundaryPadding is ignored.`;db2.source_property_ignored_warning.list().some(warning=>warning.source_component_id===sourceComponentId&&warning.property_name==="fanoutBoundaryPadding"&&warning.message===message)||db2.source_property_ignored_warning.insert({source_component_id:sourceComponentId,property_name:"fanoutBoundaryPadding",message,error_type:"source_property_ignored_warning",subcircuit_id:pcbGroup?.subcircuit_id})},fanoutConfigByPhasePlan=new Map;for(let routingStage of routingStages){let fanoutMode=routingStage.autorouterConfig.preset;(fanoutMode==="fanout"||fanoutMode==="single_layer_fanout")&&!fanoutConfigByPhasePlan.has(routingStage.routingPhasePlan)&&fanoutConfigByPhasePlan.set(routingStage.routingPhasePlan,routingStage.autorouterConfig)}let fanoutPhaseRegions=[];for(let[routingPhasePlan,phaseAutorouterConfig]of fanoutConfigByPhasePlan){let fanoutRegionPcbGroupId=routingPhasePlan.fanoutRegionPcbGroupId;if(!fanoutRegionPcbGroupId)continue;let phaseSimpleRouteJson=Group_filterSimpleRouteJsonForPhase(baseSimpleRouteJson,routingPhasePlan);if(phaseSimpleRouteJson.connections.length===0)continue;phaseSimpleRouteJson=Group_applyDrcTolerancesToSimpleRouteJson(phaseSimpleRouteJson,routingPhasePlan.drcTolerances);let breakoutPoints=db2.pcb_breakout_point.list().filter(point6=>point6.pcb_group_id===fanoutRegionPcbGroupId).map(point6=>({x:point6.x,y:point6.y})),fanoutMode=phaseAutorouterConfig.preset,fanoutBounds=FanoutAutorouter.resolveFanoutBounds(phaseSimpleRouteJson,{mode:fanoutMode,busFanoutDirections:routingPhasePlan.busFanoutDirections,fanoutBounds:routingPhasePlan.fanoutBounds,fanoutBoundaryPadding:routingPhasePlan.fanoutBoundaryPadding,fanoutRoutingLayers:routingPhasePlan.fanoutRoutingLayers,breakoutPoints,onFanoutBoundsConflict:()=>emitFanoutBoundsConflictWarning(routingPhasePlan)});if(routingPhasePlan.fanoutBounds=fanoutBounds,!fanoutBounds)continue;let pcbGroup=db2.pcb_group.get(fanoutRegionPcbGroupId),maximumTraceWidth=Math.max(phaseSimpleRouteJson.minTraceWidth,...phaseSimpleRouteJson.connections.map(connection=>connection.nominalTraceWidth??connection.width??phaseSimpleRouteJson.minTraceWidth)),viaPadDiameter=phaseSimpleRouteJson.minViaPadDiameter??phaseSimpleRouteJson.min_via_pad_diameter??phaseSimpleRouteJson.minViaDiameter,traceToPadClearance=phaseSimpleRouteJson.minTraceToPadEdgeClearance??phaseSimpleRouteJson.defaultObstacleMargin??maximumTraceWidth;fanoutPhaseRegions.push({regionId:fanoutRegionPcbGroupId,name:pcbGroup?.name??routingPhasePlan.phaseName??fanoutRegionPcbGroupId,bounds:fanoutBounds,boundaryKeepaway:getFanoutBoundaryPointSpacing({traceWidth:maximumTraceWidth,traceToPadClearance,viaPadDiameter})/2})}let fanoutSeparationConflict=findFanoutPhaseSeparationConflict(fanoutPhaseRegions);if(fanoutSeparationConflict){let{firstRegion,secondRegion,availableGap,requiredGap}=fanoutSeparationConflict,separationDescription=availableGap<0?`overlap by ${Math.abs(availableGap).toFixed(3)}mm`:`are only ${availableGap.toFixed(3)}mm apart`,message=`Fanout regions "${firstRegion.name}" and "${secondRegion.name}" ${separationDescription}, but at least ${requiredGap.toFixed(3)}mm of separation is required for a via-safe routing channel. Move the components farther apart or reduce their facing fanout padding.`;throw db2.pcb_autorouting_error.insert({pcb_error_id:`pcb_autorouter_error_subcircuit_${this.subcircuit_id}`,error_type:"pcb_autorouting_error",message}),this.root?.emit("autorouting:error",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),error:{message},simpleRouteJson:baseSimpleRouteJson}),new Error(message)}for(let{regionId,bounds}of fanoutPhaseRegions)db2.pcb_group.update(regionId,{center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},width:bounds.maxX-bounds.minX,height:bounds.maxY-bounds.minY});let outputTraces=[],outputJumpers=[],pcbTraceIdsToDelete=new Set,existingRerouteSeedTraces=getExistingSimplifiedPcbTracesForReroute(this),traceMatchesRoutingPhase=(trace,routingPhasePlan)=>{let connectionName=trace.connection_name??trace.pcb_trace_id,sourceTraceIds=new Set([connectionName,trace.pcb_trace_id,...getSourceTraceIdsFromRerouteName(connectionName),...getSourceTraceIdsFromRerouteName(trace.pcb_trace_id)]);return baseSimpleRouteJson.connections.some(connection=>connectionIsInRoutingPhase(connection,routingPhasePlan)?sourceTraceIds.has(connection.name)||(connection.source_trace_id?sourceTraceIds.has(connection.source_trace_id):!1)||(connection.rootConnectionName?sourceTraceIds.has(connection.rootConnectionName):!1)||connection.mergedConnectionNames?.some(name=>sourceTraceIds.has(name)):!1)},previousStageOutputSimpleRouteJson;for(let{routingPhasePlan,autorouterConfig:phaseAutorouterConfig,strategy:localAutorouterStrategy,usesPreviousStageOutput,phaseStageIndex,phaseStageCount}of routingStages){if(usesPreviousStageOutput||(previousStageOutputSimpleRouteJson=void 0),usesPreviousStageOutput&&previousStageOutputSimpleRouteJson===void 0)throw new Error("Autorouting follow-up stage is missing the preceding stage output");let simpleRouteJson=previousStageOutputSimpleRouteJson??baseSimpleRouteJson,isRegionReroutePhase=!!(routingPhasePlan.reroute&&routingPhasePlan.region),isConnectionReroutePhase=!!(routingPhasePlan.reroute&&!routingPhasePlan.region&&routingPhasePlan.traces.length>0),isReroutePhase=isRegionReroutePhase||isConnectionReroutePhase,rerouteOriginalSrj=isRegionReroutePhase?{...baseSimpleRouteJson,traces:[...existingRerouteSeedTraces,...outputTraces]}:null;if(!usesPreviousStageOutput&&isRegionReroutePhase&&rerouteOriginalSrj)simpleRouteJson=E32(rerouteOriginalSrj,{shape:"rect",...routingPhasePlan.region});else if(!usesPreviousStageOutput&&isConnectionReroutePhase){let phaseInput=Group_filterSimpleRouteJsonForPhase(baseSimpleRouteJson,routingPhasePlan);simpleRouteJson={...phaseInput,traces:[...phaseInput.traces??[],...outputTraces.filter(trace=>!traceMatchesRoutingPhase(trace,routingPhasePlan))]}}else if(!usesPreviousStageOutput&&hasPhasedAutorouting){let phaseInput=Group_filterSimpleRouteJsonForPhase(baseSimpleRouteJson,routingPhasePlan),activeCustomBreakoutRoutingGroupId=routingPhasePlan.routingPcbGroupId;if(activeCustomBreakoutRoutingGroupId){let activeGroupCopperPourObstacles=getSimpleRouteJsonFromCircuitJson({db:db2,minTraceWidth,nominalTraceWidth,subcircuit_id:this.subcircuit_id,subcircuitComponent:this,routingPcbGroupId:activeCustomBreakoutRoutingGroupId,fanoutPourNetMap}).simpleRouteJson.obstacles.filter(obstacle=>obstacle.isCopperPour),nonCopperPourObstacles=phaseInput.obstacles.filter(obstacle=>!obstacle.isCopperPour);phaseInput.obstacles=nonCopperPourObstacles.concat(activeGroupCopperPourObstacles)}simpleRouteJson={...phaseInput,traces:[...phaseInput.traces??[],...outputTraces]}}if(simpleRouteJson=Group_applyDrcTolerancesToSimpleRouteJson(simpleRouteJson,routingPhasePlan.drcTolerances),simpleRouteJson.allowViaInPad=phaseAutorouterConfig.allowViaInPad,(hasPhasedAutorouting||isReroutePhase)&&simpleRouteJson.connections.length===0){phaseStageIndex===0&&emitRoutingPhaseDebugObject(routingPhasePlan,simpleRouteJson.bounds),previousStageOutputSimpleRouteJson=simpleRouteJson;continue}let phaseIsAutoJumperPreset=routingPhasePlan.autorouter!==void 0?this._isAutoJumperAutorouter(phaseAutorouterConfig):isAutoJumperPreset,phaseIsLaserPrefabPreset=routingPhasePlan.autorouter!==void 0?this._isLaserPrefabAutorouter(phaseAutorouterConfig):isLaserPrefabPreset;phaseIsAutoJumperPreset&&(simpleRouteJson.allowJumpers=!0,phaseAutorouterConfig.availableJumperTypes&&(simpleRouteJson.availableJumperTypes=phaseAutorouterConfig.availableJumperTypes));let fanoutMode=phaseAutorouterConfig.preset;if((fanoutMode==="fanout"||fanoutMode==="single_layer_fanout")&&!routingPhasePlan.fanoutRegionPcbGroupId&&(routingPhasePlan.fanoutBounds=FanoutAutorouter.resolveFanoutBounds(simpleRouteJson,{mode:fanoutMode,busFanoutDirections:routingPhasePlan.busFanoutDirections,fanoutBounds:routingPhasePlan.fanoutBounds,fanoutBoundaryPadding:routingPhasePlan.fanoutBoundaryPadding,fanoutRoutingLayers:routingPhasePlan.fanoutRoutingLayers})),phaseStageIndex===0&&emitRoutingPhaseDebugObject(routingPhasePlan,routingPhasePlan.fanoutBounds??simpleRouteJson.bounds),debug132.enabled&&global.debugOutputArray?.push({name:`simpleroutejson-${this.props.name}.json`,obj:simpleRouteJson}),debug132.enabled){let graphicsObject=Fo2(simpleRouteJson);graphicsObject.title=`autorouting-${this.props.name}`,global.debugGraphics?.push(graphicsObject)}this.root?.emit("autorouting:start",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},simpleRouteJson});let cacheEngine=phaseAutorouterConfig.algorithmFn||!localAutorouterStrategy.cacheable?void 0:this.root?.platform?.localCacheEngine,cacheKey=cacheEngine?getLocalAutoroutingCacheKey(simpleRouteJson):void 0,cachedResult=cacheKey?await getCachedLocalAutoroutingPhaseResult({cacheEngine,cacheKey}):null,autorouter;try{let traces;if(cachedResult)debug132(`[${this.getString()}] using cached local autorouting result`),traces=cachedResult.traces;else{if(phaseAutorouterConfig.algorithmFn)autorouter=await phaseAutorouterConfig.algorithmFn(simpleRouteJson);else{let autorouterVersion22=phaseAutorouterConfig.autorouterVersion??this.props.autorouterVersion,effortLevel=this.props.autorouterEffortLevel,effort=effortLevel?Number.parseInt(effortLevel.replace("x",""),10):void 0,commonAutorouterOptions={capacityDepth:phaseAutorouterConfig.capacityDepth,targetMinCapacity:phaseAutorouterConfig.targetMinCapacity,platformConfig:this.root?.platform,useAssignableSolver:phaseIsLaserPrefabPreset||isSingleLayerBoard,useAutoJumperSolver:phaseIsAutoJumperPreset,useLaserPrefabSolver:phaseIsLaserPrefabPreset,autorouterVersion:autorouterVersion22,effort};autorouter=localAutorouterStrategy.create({simpleRouteJson,commonAutorouterOptions,busFanoutDirections:routingPhasePlan.busFanoutDirections,fanoutBounds:routingPhasePlan.fanoutBounds,fanoutRoutingLayers:routingPhasePlan.fanoutRoutingLayers,componentNamesById:getPcbComponentNamesById(db2),onSolverStarted:({solverName,solverParams,solverConstructorArgs})=>this.root?.emit("solver:started",{type:"solver:started",solverName,solverParams,solverConstructorArgs,componentName:this.getString()})})}if(!autorouter)throw new Error("Failed to create local autorouter");let activeAutorouter=autorouter,routingPromise=new Promise((resolve,reject)=>{activeAutorouter.on("complete",event=>{debug132(`[${this.getString()}] local autorouting complete`),resolve(event.traces)}),activeAutorouter.on("error",event=>{debug132(`[${this.getString()}] local autorouting error: ${event.error.message}`),reject(event.error)})});activeAutorouter.on("progress",event=>{this.root?.emit("autorouting:progress",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},...event})}),activeAutorouter.start(),traces=await routingPromise}let transformedSimpleRouteJson=autorouter?.getOutputSimpleRouteJson?.();if(transformedSimpleRouteJson&&!usesPreviousStageOutput&&["fanout","single_layer_fanout"].includes(phaseAutorouterConfig.preset??"")&&routingPhasePlan.routingPcbGroupId){let synchronizedFanout=Group_syncFanoutExitsWithGlobalConnections({fanoutInputSimpleRouteJson:simpleRouteJson,fanoutOutputSimpleRouteJson:transformedSimpleRouteJson,baseSimpleRouteJson,routingPhasePlan});baseSimpleRouteJson=synchronizedFanout.baseSimpleRouteJson,transformedSimpleRouteJson=synchronizedFanout.downstreamSimpleRouteJson;for(let synchronizedPoint of synchronizedFanout.synchronizedBreakoutPoints){let breakoutPoint=db2.pcb_breakout_point.list().find(point6=>point6.pcb_group_id===synchronizedPoint.routingPcbGroupId&&point6.source_trace_id===synchronizedPoint.sourceTraceId&&Math.abs(point6.x-synchronizedPoint.previousPoint.x)<=1e-6&&Math.abs(point6.y-synchronizedPoint.previousPoint.y)<=1e-6);breakoutPoint&&db2.pcb_breakout_point.update(breakoutPoint.pcb_breakout_point_id,{x:synchronizedPoint.fanoutExitPoint.x,y:synchronizedPoint.fanoutExitPoint.y})}}let stageOutputTraces=traces;transformedSimpleRouteJson?.traces?stageOutputTraces=transformedSimpleRouteJson.traces:usesPreviousStageOutput&&(stageOutputTraces=[...simpleRouteJson.traces??[],...traces]);let outputSimpleRouteJson={...transformedSimpleRouteJson??simpleRouteJson,traces:stageOutputTraces};if(previousStageOutputSimpleRouteJson=transformedSimpleRouteJson?outputSimpleRouteJson:void 0,!cachedResult&&cacheKey&&await cacheLocalAutoroutingPhaseResult({cacheEngine,cacheKey,result:{...simpleRouteJson,traces}}),this.root?.emit("autorouting:end",{type:"autorouting:end",subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},simpleRouteJson:outputSimpleRouteJson}),autorouter?.getConnectedOffboardObstacles){let connectedOffboardObstacles=autorouter.getConnectedOffboardObstacles();createSourceTracesFromOffboardConnections({db:db2,connectedOffboardObstacles,simpleRouteJson,subcircuit_id:this.subcircuit_id})}let solver=autorouter?.solver;if(solver?.getOutputJumpers&&outputJumpers.push(...solver.getOutputJumpers()||[]),isRegionReroutePhase&&rerouteOriginalSrj){for(let trace of rerouteOriginalSrj.traces??[])trace.type==="pcb_trace"&&pcbTraceIdsToDelete.add(trace.pcb_trace_id);let reconnectedSrj=A32(rerouteOriginalSrj,{...simpleRouteJson,traces:[...simpleRouteJson.traces??[],...traces]});outputTraces.splice(0,outputTraces.length,...reconnectedSrj.traces??[])}else if(isConnectionReroutePhase){let retainedPcbTraces=outputTraces.filter(trace=>!traceMatchesRoutingPhase(trace,routingPhasePlan));outputTraces.splice(0,outputTraces.length,...getAccumulatedPcbTracesWithStageOutputReplacements({accumulatedPcbTraces:retainedPcbTraces,stageOutputPcbTraces:stageOutputTraces}))}else outputTraces.splice(0,outputTraces.length,...getAccumulatedPcbTracesWithStageOutputReplacements({accumulatedPcbTraces:outputTraces,stageOutputPcbTraces:stageOutputTraces}))}catch(error2){let{db:db22}=this.root;throw db22.pcb_autorouting_error.insert({pcb_error_id:`pcb_autorouter_error_subcircuit_${this.subcircuit_id}`,error_type:"pcb_autorouting_error",message:error2 instanceof Error?error2.message:String(error2)}),this.root?.emit("autorouting:error",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...routingPhasePlan.phaseName!==void 0?{phaseName:routingPhasePlan.phaseName,phaseStageIndex,phaseStageCount}:{},error:{message:error2 instanceof Error?error2.message:String(error2)},simpleRouteJson}),error2}finally{autorouter?.stop()}}this._asyncAutoroutingResult={output_pcb_traces:outputTraces,output_jumpers:outputJumpers,pcb_trace_ids_to_be_replaced:[...pcbTraceIdsToDelete]},this._markDirty("PcbTraceRender")}_startAsyncAutorouting(){this._hasStartedAsyncAutorouting||(this._hasStartedAsyncAutorouting=!0,this._getAutorouterConfig().local?this._queueAsyncEffect("autorouting",async()=>this._runLocalAutorouting()):this._queueAsyncEffect("make-http-autorouting-request",async()=>this._runEffectMakeHttpAutoroutingRequest()))}doInitialPcbTraceRender(){let debug132=(0,import_debug11.default)("tscircuit:core:doInitialPcbTraceRender");if(!this.isSubcircuit||this.root?.pcbDisabled||this.root?.pcbRoutingDisabled||this.getInheritedProperty("routingDisabled")||this._isInflatedFromCircuitJson||this._isLegacyAutorouterDisabled()||this._shouldUseTraceByTraceRouting())return;if(!this._areChildSubcircuitsRouted()){debug132(`[${this.getString()}] child subcircuits are not routed, skipping async autorouting until subcircuits routed`);return}if(debug132(`[${this.getString()}] no child subcircuits to wait for, initiating async routing`),!this._hasTracesToRoute())return;let shouldSkipBecauseOfPlacementErrors=shouldSkipAutoroutingBecauseOfPlacementErrors({component:this,subcircuit:this}),shouldSkipBecauseOfTraceLengthViolations=shouldSkipAutoroutingBecauseOfTraceLengthViolations({component:this,subcircuit:this});shouldSkipBecauseOfPlacementErrors||shouldSkipBecauseOfTraceLengthViolations||this._startAsyncAutorouting()}doInitialSchematicTraceRender(){this._parsedProps.showAsSchematicBox||Group_doInitialSchematicTraceRender(this)}doInitialSchematicSheetRender(){Group_doInitialSchematicSheetRender(this)}updateSchematicSheetRender(){Group_updateSchematicSheetRender(this)}updatePcbTraceRender(){let debug132=(0,import_debug11.default)("tscircuit:core:updatePcbTraceRender");if(debug132(`[${this.getString()}] updating...`),!this.isSubcircuit||this._isInflatedFromCircuitJson||this._isLegacyAutorouterDisabled())return;if(this._shouldRouteAsync()&&this._hasTracesToRoute()&&!this._hasStartedAsyncAutorouting){if(this._areChildSubcircuitsRouted()){let shouldSkipBecauseOfPlacementErrors=shouldSkipAutoroutingBecauseOfPlacementErrors({component:this,subcircuit:this}),shouldSkipBecauseOfTraceLengthViolations=shouldSkipAutoroutingBecauseOfTraceLengthViolations({component:this,subcircuit:this});if(shouldSkipBecauseOfPlacementErrors||shouldSkipBecauseOfTraceLengthViolations)return;debug132(`[${this.getString()}] child subcircuits are now routed, starting async autorouting`),this._startAsyncAutorouting()}return}if(!this._asyncAutoroutingResult||this._shouldUseTraceByTraceRouting())return;let{db:db2}=this.root;if(this._asyncAutoroutingResult.output_simple_route_json){debug132(`[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`),this._updatePcbTraceRenderFromSimpleRouteJson();return}if(this._asyncAutoroutingResult.output_pcb_traces){debug132(`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`),this._updatePcbTraceRenderFromPcbTraces();return}}_updatePcbTraceRenderFromSimpleRouteJson(){let{db:db2}=this.root,{traces:routedTraces}=this._asyncAutoroutingResult.output_simple_route_json;if(routedTraces)for(let routedTrace of routedTraces){let cjRoute=routedTrace.route.map(point6=>point6.route_type!=="through_obstacle"?point6:{route_type:"through_pad",start:point6.start,end:point6.end,start_layer:point6.from_layer,end_layer:point6.to_layer,width:point6.width,circuitJsonMetadata:point6.circuitJsonMetadata}),pcb_trace3=db2.pcb_trace.insert({subcircuit_id:this.subcircuit_id,route:removeSrjMetadataFromPcbTraceRoute(cjRoute)});claimSrjAssignablePcbViasTraversedByRoute({db:db2,pcbTrace:pcb_trace3,routeWithSrjMetadata:cjRoute})}}_updatePcbTraceRenderFromPcbTraces(){let{output_pcb_traces,output_jumpers,pcb_trace_ids_to_be_replaced}=this._asyncAutoroutingResult;if(!output_pcb_traces)return;let{db:db2}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{holeDiameter,padDiameter}=getViaDiameterDefaults(pcbStyle2),board=db2.pcb_board.list()[0],routedViaHoleDiameter=board?.min_via_hole_diameter??holeDiameter,routedViaPadDiameter=board?.min_via_pad_diameter??padDiameter;output_jumpers&&output_jumpers.length>0&&insertAutoplacedJumpers({db:db2,output_jumpers,subcircuit_id:this.subcircuit_id}),deleteExistingPcbTracesReplacedBy({group:this,outputPcbTraces:output_pcb_traces,pcbTraceIdsToReplace:pcb_trace_ids_to_be_replaced});for(let pcb_trace3 of output_pcb_traces){if(pcb_trace3.type!=="pcb_trace")continue;pcb_trace3.subcircuit_id??(pcb_trace3.subcircuit_id=this.subcircuit_id);let cjRoute=pcb_trace3.route.map(point6=>point6.route_type!=="through_obstacle"?point6:{route_type:"through_pad",start:point6.start,end:point6.end,start_layer:point6.from_layer,end_layer:point6.to_layer,width:point6.width,circuitJsonMetadata:point6.circuitJsonMetadata}),routeSourceTraceId=getSourceTraceIdForRoutedTrace({db:db2,trace:{...pcb_trace3,route:cjRoute},subcircuit_id:this.subcircuit_id});cjRoute=ensureRouteStartsAtSourceTraceStart({db:db2,route:cjRoute,routeThicknessMode:pcb_trace3.route_thickness_mode,sourceTraceId:routeSourceTraceId}),pcb_trace3.route=cjRoute;let segments=splitPcbTracesOnJumperSegments(cjRoute);segments===null&&(segments=[cjRoute]);let processedSegments=addPortIdsToTracesAtJumperPads(segments,db2);for(let segment2 of processedSegments)if(segment2.length>0){let circuitJsonSegment=removeSrjMetadataFromPcbTraceRoute(segment2),sourceTraceId=getSourceTraceIdForRoutedTrace({db:db2,trace:{...pcb_trace3,route:circuitJsonSegment},subcircuit_id:this.subcircuit_id}),insertedPcbTrace=db2.pcb_trace.insert({...pcb_trace3,source_trace_id:sourceTraceId,route:circuitJsonSegment});claimSrjAssignablePcbViasTraversedByRoute({db:db2,pcbTrace:insertedPcbTrace,routeWithSrjMetadata:segment2})}}for(let pcb_trace3 of output_pcb_traces)if(pcb_trace3.type!=="pcb_via"&&pcb_trace3.type==="pcb_trace"){let sourceTraceId=getSourceTraceIdForRoutedTrace({db:db2,trace:pcb_trace3,subcircuit_id:this.subcircuit_id}),{connection_name:inputConnectionName}=pcb_trace3,subcircuitConnectivityMapKey;if(sourceTraceId&&(subcircuitConnectivityMapKey=db2.source_trace.get(sourceTraceId)?.subcircuit_connectivity_map_key),!subcircuitConnectivityMapKey&&inputConnectionName){let sourceNet=db2.source_net.get(inputConnectionName);sourceNet&&(subcircuitConnectivityMapKey=sourceNet.subcircuit_connectivity_map_key)}for(let point6 of pcb_trace3.route)if(point6.route_type==="via"){let routedViaPoint=point6,fromLayer=point6.from_layer,toLayer=point6.to_layer;db2.pcb_via.insert({pcb_trace_id:pcb_trace3.pcb_trace_id,x:point6.x,y:point6.y,hole_diameter:routedViaPoint.via_hole_diameter??routedViaPoint.hole_diameter??routedViaHoleDiameter,outer_diameter:routedViaPoint.via_diameter??routedViaPoint.outer_diameter??routedViaPadDiameter,layers:getViaSpanLayers({fromLayer,toLayer,layerCount:this._getSubcircuitLayerCount()}),from_layer:fromLayer,to_layer:toLayer,subcircuit_id:this.subcircuit_id,pcb_group_id:this.pcb_group_id??void 0,subcircuit_connectivity_map_key:subcircuitConnectivityMapKey})}}}doInitialSchematicComponentRender(){if(this.root?.schematicDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,schematic_group3=db2.schematic_group.insert({is_subcircuit:this.isSubcircuit,subcircuit_id:this.subcircuit_id,name:this.name,center:this._getGlobalSchematicPositionBeforeLayout(),width:0,height:0,schematic_component_ids:[],source_group_id:this.source_group_id,show_as_schematic_box:props.showAsSchematicBox??!1});this.schematic_group_id=schematic_group3.schematic_group_id,props.showAsSchematicBox&&Group_doInitialSchematicBoxComponentRender(this);for(let child of this.getDescendants())child.getGroup()?.source_group_id===this.source_group_id&&(child._parsedProps?.showAsSchematicBox||child.schematic_component_id&&db2.schematic_component.update(child.schematic_component_id,{schematic_group_id:schematic_group3.schematic_group_id}))}_getSchematicLayoutMode(){let props=this._parsedProps,schAutoLayoutEnabled=props.schAutoLayoutEnabled??!1;if(props.schLayout?.layoutMode==="none"||props.schLayout?.layoutMode==="relative")return"relative";if(props.schLayout?.matchAdapt)return"match-adapt";if(props.schLayout?.flex)return"flex";if(props.schLayout?.grid)return"grid";if(props.schMatchAdapt)return"match-adapt";if(props.schFlex)return"flex";if(props.schGrid)return"grid";if(props.matchAdapt)return"match-adapt";if(props.flex)return"flex";if(props.grid)return"grid";if(props.relative||props.schRelative)return"relative";let anyLayoutChildHasSchCoords=this.children.some(child=>{let cProps=child._parsedProps;return(child.source_component_id!==null||child.source_group_id!==null)&&(cProps?.schX!==void 0||cProps?.schY!==void 0)}),hasManualEdits=(props.manualEdits?.schematic_placements?.length??0)>0;return schAutoLayoutEnabled&&!hasManualEdits||!anyLayoutChildHasSchCoords&&!hasManualEdits?"match-adapt":"relative"}doInitialSchematicLayout(){if(this._parsedProps.showAsSchematicBox){this._insertSchematicBorder();return}if(this.children.some(c3=>c3.source_component_id!==null&&c3._parsedProps?.schSectionName!==void 0)){this._doInitialSchematicLayoutSections(),this._insertSchematicBorder();return}let schematicLayoutMode=this._getSchematicLayoutMode();schematicLayoutMode==="match-adapt"&&this._doInitialSchematicLayoutMatchpack(),schematicLayoutMode==="grid"&&this._doInitialSchematicLayoutGrid(),schematicLayoutMode==="flex"&&this._doInitialSchematicLayoutFlex(),this._insertSchematicBorder()}_doInitialSchematicLayoutSections(){Group_doInitialSchematicLayoutSections(this)}_doInitialSchematicLayoutMatchAdapt(){Group_doInitialSchematicLayoutMatchAdapt(this)}_doInitialSchematicLayoutMatchpack(){Group_doInitialSchematicLayoutMatchPack(this)}_doInitialSchematicLayoutGrid(){Group_doInitialSchematicLayoutGrid(this)}_doInitialSchematicLayoutFlex(){Group_doInitialSchematicLayoutFlex(this)}_getPcbLayoutMode(){let props=this._parsedProps,rawProps=this.props;if(this._isInflatedFromCircuitJson||props.pcbRelative)return"none";if(props.pcbLayout?.matchAdapt)return"match-adapt";if(props.pcbLayout?.flex)return"flex";if(props.pcbLayout?.grid)return"grid";if(props.pcbLayout?.pack)return"pack";if(props.pcbFlex)return"flex";if(props.pcbGrid)return"grid";if(props.pcbPack||props.pack)return"pack";if(props.matchAdapt)return"match-adapt";if(props.flex)return"flex";if(props.grid)return"grid";let groupHasCoords=props.pcbX!==void 0||props.pcbY!==void 0||props.pcbLeftEdgeX!==void 0||props.pcbRightEdgeX!==void 0||props.pcbTopEdgeY!==void 0||props.pcbBottomEdgeY!==void 0||rawProps.pcbLeftEdgeX!==void 0||rawProps.pcbRightEdgeX!==void 0||rawProps.pcbTopEdgeY!==void 0||rawProps.pcbBottomEdgeY!==void 0,hasManualEdits=(props.manualEdits?.pcb_placements?.length??0)>0,unpositionedDirectChildrenCount=this.children.reduce((count,child)=>{if(!child.pcb_component_id&&!child.pcb_group_id)return count;let childProps=child._parsedProps,rawChildProps=child.props,hasCoords=childProps?.pcbX!==void 0||childProps?.pcbY!==void 0||childProps?.pcbLeftEdgeX!==void 0||childProps?.pcbRightEdgeX!==void 0||childProps?.pcbTopEdgeY!==void 0||childProps?.pcbBottomEdgeY!==void 0||rawChildProps?.pcbLeftEdgeX!==void 0||rawChildProps?.pcbRightEdgeX!==void 0||rawChildProps?.pcbTopEdgeY!==void 0||rawChildProps?.pcbBottomEdgeY!==void 0;return count+(hasCoords?0:1)},0);return!hasManualEdits&&unpositionedDirectChildrenCount>1?"pack":"none"}doInitialPcbLayout(){if(this.root?.pcbDisabled)return;if(this.pcb_group_id){let{db:db2}=this.root,props=this._parsedProps;if(props.pcbX!==void 0||props.pcbY!==void 0){let parentGroup=this.parent?.getGroup?.(),pcbParentGroupId=parentGroup?.pcb_group_id?db2.pcb_group.get(parentGroup.pcb_group_id)?.pcb_group_id:void 0,positionedRelativeToBoardId=pcbParentGroupId?void 0:this._getBoard()?.pcb_board_id??void 0;db2.pcb_group.update(this.pcb_group_id,{position_mode:"relative_to_group_anchor",positioned_relative_to_pcb_group_id:pcbParentGroupId,positioned_relative_to_pcb_board_id:positionedRelativeToBoardId,display_offset_x:props.pcbX,display_offset_y:props.pcbY})}}let pcbLayoutMode=this._getPcbLayoutMode();pcbLayoutMode==="grid"?this._doInitialPcbLayoutGrid():pcbLayoutMode==="pack"?this._doInitialPcbLayoutPack():pcbLayoutMode==="flex"&&this._doInitialPcbLayoutFlex()}_doInitialPcbLayoutGrid(){Group_doInitialPcbLayoutGrid(this)}_doInitialPcbLayoutPack(){Group_doInitialPcbLayoutPack(this)}_doInitialPcbLayoutFlex(){Group_doInitialPcbLayoutFlex(this)}_insertSchematicBorder(){if(this.root?.schematicDisabled)return;let{db:db2}=this.root,props=this._parsedProps;if(!props.border)return;let width=typeof props.schWidth=="number"?props.schWidth:void 0,height=typeof props.schHeight=="number"?props.schHeight:void 0,paddingGeneral=typeof props.schPadding=="number"?props.schPadding:0,paddingLeft=typeof props.schPaddingLeft=="number"?props.schPaddingLeft:paddingGeneral,paddingRight=typeof props.schPaddingRight=="number"?props.schPaddingRight:paddingGeneral,paddingTop=typeof props.schPaddingTop=="number"?props.schPaddingTop:paddingGeneral,paddingBottom=typeof props.schPaddingBottom=="number"?props.schPaddingBottom:paddingGeneral,schematicGroup=this.schematic_group_id?db2.schematic_group.get(this.schematic_group_id):null;if(schematicGroup&&(width===void 0&&typeof schematicGroup.width=="number"&&(width=schematicGroup.width),height===void 0&&typeof schematicGroup.height=="number"&&(height=schematicGroup.height)),width===void 0||height===void 0)return;let center2=schematicGroup?.center??this._getGlobalSchematicPositionBeforeLayout(),left=center2.x-width/2-paddingLeft,bottom=center2.y-height/2-paddingBottom,finalWidth=width+paddingLeft+paddingRight,finalHeight=height+paddingTop+paddingBottom;db2.schematic_box.insert({width:finalWidth,height:finalHeight,x:left,y:bottom,is_dashed:props.border?.dashed??!1})}_determineSideFromPosition(port,component){if(!port.center||!component.center)return"left";let dx3=port.center.x-component.center.x,dy3=port.center.y-component.center.y;return Math.abs(dx3)>Math.abs(dy3)?dx3>0?"right":"left":dy3>0?"bottom":"top"}_calculateSchematicBounds(boxes){if(boxes.length===0)return{minX:0,maxX:0,minY:0,maxY:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let box2 of boxes)minX=Math.min(minX,box2.centerX),maxX=Math.max(maxX,box2.centerX),minY=Math.min(minY,box2.centerY),maxY=Math.max(maxY,box2.centerY);let padding=2;return{minX:minX-padding,maxX:maxX+padding,minY:minY-padding,maxY:maxY+padding}}_getAutorouterConfig(){let autorouter=this._parsedProps.autorouter||this.getInheritedProperty("autorouter");return getPresetAutoroutingConfig(autorouter,this.root?.platform)}_isLegacyAutorouterDisabled(){return getDisabledLegacyAutorouterPreset(this)!==null}_isLaserPrefabAutorouter(autorouterConfig2=this._getAutorouterConfig()){let autorouterProp2=this.props.autorouter,normalize4=value=>value?.replace(/-/g,"_")??value;return autorouterConfig2.preset==="laser_prefab"?!0:typeof autorouterProp2=="string"?normalize4(autorouterProp2)==="laser_prefab":typeof autorouterProp2=="object"&&autorouterProp2?normalize4(autorouterProp2.preset)==="laser_prefab":!1}_isAutoJumperAutorouter(autorouterConfig2=this._getAutorouterConfig()){let autorouterProp2=this.props.autorouter,normalize4=value=>value?.replace(/-/g,"_")??value;return autorouterConfig2.preset==="auto_jumper"?!0:typeof autorouterProp2=="string"?normalize4(autorouterProp2)==="auto_jumper":typeof autorouterProp2=="object"&&autorouterProp2?normalize4(autorouterProp2.preset)==="auto_jumper":!1}_getSubcircuitLayerCount(){let layers=this.getInheritedProperty("layers");return typeof layers=="number"?layers:2}_shouldUseTraceByTraceRouting(){return getDisabledLegacyGroupAutorouterPreset(this)?!1:this._getAutorouterConfig().groupMode==="sequential-trace"}doInitialPcbDesignRuleChecks(){if(this.root?.pcbDisabled||this._isLegacyAutorouterDisabled()||this.root?.pcbRoutingDisabled||this.getInheritedProperty("routingDisabled"))return;let{db:db2}=this.root;if(this.isSubcircuit){let immediateChildrenByName=new Map;for(let child of this.children)if(!child.isSubcircuit&&child._parsedProps.name){let components=immediateChildrenByName.get(child._parsedProps.name)||[];components.push(child),immediateChildrenByName.set(child._parsedProps.name,components)}for(let[name,components]of immediateChildrenByName.entries()){if(components.length<=1)continue;let sameNamedTraces=components.filter(child=>child instanceof Trace),duplicateNameIsOnlyTraces=sameNamedTraces.length===components.length,mutuallyConnectedTraceKeys=sameNamedTraces.map(trace=>trace.subcircuit_connectivity_map_key),sameNamedTracesAreMutuallyConnected=duplicateNameIsOnlyTraces&&mutuallyConnectedTraceKeys.every(Boolean)&&new Set(mutuallyConnectedTraceKeys).size===1;if(!duplicateNameIsOnlyTraces||!sameNamedTracesAreMutuallyConnected){let displaySubcircuitName=this.name||"unnamed",message=duplicateNameIsOnlyTraces?`Trace "${name}" in subcircuit "${displaySubcircuitName}" shares a name with another trace, but the traces are not mutually connected. Same-named traces must have the same subcircuit connectivity map key.`:`Multiple immediate children found with name "${name}" in subcircuit "${displaySubcircuitName}". Names must be unique.`;db2.pcb_trace_error.insert({error_type:"pcb_trace_error",message,source_trace_id:"",pcb_trace_id:"",pcb_component_ids:components.map(c3=>c3.pcb_component_id).filter(Boolean),pcb_port_ids:[]})}}}Group_doInitialStandaloneSubcircuitPcbDesignRuleChecks(this)}doInitialSchematicReplaceNetLabelsWithSymbols(){if(this.root?.schematicDisabled||!this.isSubcircuit)return;let{db:db2}=this.root,subtree=db2;for(let nl3 of subtree.schematic_net_label.list()){let net=subtree.source_net.get(nl3.source_net_id),text=nl3.text||net?.name||"",isGroundNet=net?.is_ground||GROUND_NET_REGEX.test(text),isPowerNet=net?.is_power||POWER_NET_REGEX.test(text);if(nl3.anchor_side==="top"&&isGroundNet){subtree.schematic_net_label.update(nl3.schematic_net_label_id,{symbol_name:"rail_down"});continue}nl3.anchor_side==="bottom"&&isPowerNet&&subtree.schematic_net_label.update(nl3.schematic_net_label_id,{symbol_name:"rail_up"})}}doInitialSimulationSpiceEngineRender(){Group_doInitialSimulationSpiceEngineRender(this)}doInitialPcbComponentAnchorAlignment(){Group_doInitialPcbComponentAnchorAlignment(this)}updatePcbComponentAnchorAlignment(){this.doInitialPcbComponentAnchorAlignment()}doInitialPcbCalcPlacementResolution(){Group_doInitialPcbCalcPlacementResolution(this)}updatePcbCalcPlacementResolution(){this.doInitialPcbCalcPlacementResolution()}_getMinimumFlexContainerSize(){return super._getMinimumFlexContainerSize()}_repositionOnPcb(position4){return super._repositionOnPcb(position4)}};function inflateSourceGroup(sourceGroup,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbGroup=injectionDb.pcb_group.getWhere({source_group_id:sourceGroup.source_group_id}),groupProps2={name:sourceGroup.name??`inflated_group_${sourceGroup.source_group_id}`};if(pcbGroup?.position_mode==="relative_to_group_anchor"&&pcbGroup.anchor_position){let baseAnchor={x:0,y:0};if(sourceGroup.parent_source_group_id){let parentPcbGroup=injectionDb.pcb_group.getWhere({source_group_id:sourceGroup.parent_source_group_id});parentPcbGroup?.anchor_position&&(baseAnchor=parentPcbGroup.anchor_position)}groupProps2.pcbX=pcbGroup.anchor_position.x-baseAnchor.x,groupProps2.pcbY=pcbGroup.anchor_position.y-baseAnchor.y}pcbGroup?.anchor_alignment&&(groupProps2.pcbAnchorAlignment=pcbGroup.anchor_alignment);let group=new Group5(groupProps2);return group._isInflatedFromCircuitJson=!0,group.source_group_id=sourceGroup.source_group_id,groupsMap&&groupsMap.set(sourceGroup.source_group_id,group),sourceGroup.parent_source_group_id&&groupsMap?.has(sourceGroup.parent_source_group_id)?groupsMap.get(sourceGroup.parent_source_group_id).add(group):subcircuit.add(group),group}var Inductor2=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"_adjustSilkscreenTextAutomatically",!0)}get config(){return{componentName:"Inductor",schematicSymbolName:this.props.symbolName??"inductor",zodProps:inductorProps,sourceFtype:FTYPE.simple_inductor}}_getSchematicSymbolDisplayValue(){return`${formatSiUnit(this._parsedProps.inductance)}H`}initPorts(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["cathode","neg","right"]}})}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({name:this.name,ftype:FTYPE.simple_inductor,inductance:this.props.inductance,max_current_rating:props.maxCurrentRating===void 0?void 0:parseAndConvertSiUnit(props.maxCurrentRating,"A").value,display_inductance:this._getSchematicSymbolDisplayValue(),supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceInductor(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),inductor=new Inductor2({name:sourceElm.name,inductance:sourceElm.inductance,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:inductor});footprint&&inductor.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(inductor):subcircuit.add(inductor)}var Led=class extends NormalComponent3{get config(){let symbolMap={laser:"laser_diode"},variantSymbol=this.props.laser?"laser":null;return{schematicSymbolName:variantSymbol?symbolMap[variantSymbol]:this.props.symbolName??"led",componentName:"Led",zodProps:ledProps,sourceFtype:"simple_led"}}initPorts(){let hasFootprintChild=this.children.some(child=>child.componentName==="Footprint"),footprint=this.resolveFootprint(),hasPinLabels=!!this._resolvePinLabels(),shouldAddDefaultAliases=!hasPinLabels&&!hasFootprintChild&&(!footprint||isFootprinterString(footprint));super.initPorts({pinCount:2,ignoreSymbolPorts:!hasPinLabels&&!shouldAddDefaultAliases,additionalAliases:{pin1:shouldAddDefaultAliases?["anode","pos","left"]:[],pin2:shouldAddDefaultAliases?["cathode","neg","right"]:[]}})}_getSchematicSymbolDisplayValue(){return this._parsedProps.schDisplayValue||this._parsedProps.color||void 0}getFootprinterString(){let baseFootprint=super.getFootprinterString();return baseFootprint&&this.props.color?`${baseFootprint}_color(${this.props.color})`:baseFootprint}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_led",name:this.name,wave_length:props.wavelength,color:props.color,symbol_display_value:this._getSchematicSymbolDisplayValue(),manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!1,display_name:props.displayName});this.source_component_id=source_component.source_component_id}get pos(){return this.portMap.pos}get anode(){return this.portMap.anode}get neg(){return this.portMap.neg}get cathode(){return this.portMap.cathode}};function inflateSourceLed(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),led2=new Led({name:sourceElm.name,color:sourceElm.color,wavelength:sourceElm.wavelength??sourceElm.wave_length,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:led2});footprint&&led2.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(led2):subcircuit.add(led2)}var possibleOrientations=[{gate:"left",drain:"top",source:"bottom"},{gate:"left",drain:"bottom",source:"top"},{gate:"right",drain:"top",source:"bottom"},{gate:"right",drain:"bottom",source:"top"},{gate:"top",drain:"left",source:"right"},{gate:"top",drain:"right",source:"left"},{gate:"bottom",drain:"left",source:"right"},{gate:"bottom",drain:"right",source:"left"}],getBaselineOrientation=rotation42=>{let normalizedRotation=(rotation42%360+360)%360;if(normalizedRotation%90!==0)throw new Error(`Schematic rotation ${rotation42} is not supported for Mosfet`);return[{gate:"left",drain:"top",source:"bottom"},{gate:"top",drain:"right",source:"left"},{gate:"right",drain:"bottom",source:"top"},{gate:"bottom",drain:"left",source:"right"}][normalizedRotation/90]},getRequestedOrientation=props=>{let requestedSides={drain:props.symbolDrainSide,source:props.symbolSourceSide,gate:props.symbolGateSide},baseline=getBaselineOrientation(Number(props.schRotation??0)),matchingOrientations=possibleOrientations.filter(orientation4=>Object.keys(requestedSides).every(portName=>requestedSides[portName]===void 0||requestedSides[portName]===orientation4[portName]));if(matchingOrientations.length===0){let requestedDescription=Object.entries(requestedSides).filter(([,side])=>side!==void 0).map(([portName,side])=>`${portName}=${side}`).join(", ");throw new Error(`Invalid MOSFET symbol port side combination (${requestedDescription}). The gate must be perpendicular to the drain and source, and the drain and source must be opposite.`)}return matchingOrientations.sort((a6,b6)=>{let score=orientation4=>Object.keys(baseline).filter(portName=>orientation4[portName]!==baseline[portName]).length;return score(a6)-score(b6)})[0]},getMosfetSchematicSymbolName=props=>{let mosfetMode=props.mosfetMode==="depletion"?"d":"e",baseSymbolName=`${props.channelType}_channel_${mosfetMode}_mosfet_transistor`;if(!(props.symbolDrainSide!==void 0||props.symbolSourceSide!==void 0||props.symbolGateSide!==void 0))return baseSymbolName;let{gate,drain}=getRequestedOrientation(props);return`${baseSymbolName}_gate_${gate}_drain_${drain}`},Mosfet2=class extends NormalComponent3{get config(){return{componentName:"Mosfet",schematicSymbolName:this.props.symbolName??getMosfetSchematicSymbolName(this.props),zodProps:mosfetProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_mosfet",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,mosfet_mode:props.mosfetMode,channel_type:props.channelType,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceMosfet(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),mosfet=new Mosfet2({name:sourceElm.name,channelType:sourceElm.channel_type,mosfetMode:sourceElm.mosfet_mode,manufacturerPartNumber:sourceElm.manufacturer_part_number,supplierPartNumbers:sourceElm.supplier_part_numbers??void 0,displayName:sourceElm.display_name,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:mosfet});footprint&&mosfet.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(mosfet):subcircuit.add(mosfet)}function inflateSourcePort(sourcePort,inflatorContext){let{injectionDb,subcircuit}=inflatorContext;if(sourcePort.source_component_id!==null)return;let pcbPortFromInjection=injectionDb.pcb_port.getWhere({source_port_id:sourcePort.source_port_id}),port=new Port({name:sourcePort.name,pinNumber:sourcePort.pin_number});subcircuit.add(port),port.source_port_id=sourcePort.source_port_id;let root=subcircuit.root;if(root&&pcbPortFromInjection){let{db:db2}=root,pcb_port3=db2.pcb_port.insert({pcb_component_id:void 0,layers:pcbPortFromInjection.layers,subcircuit_id:subcircuit.subcircuit_id??void 0,pcb_group_id:subcircuit.getGroup()?.pcb_group_id??void 0,x:pcbPortFromInjection.x,y:pcbPortFromInjection.y,source_port_id:sourcePort.source_port_id,is_board_pinout:!1});port.pcb_port_id=pcb_port3.pcb_port_id}}var PushButton=class extends NormalComponent3{get config(){return{componentName:"PushButton",schematicSymbolName:this.props.symbolName??"push_button_normally_open_momentary",zodProps:pushButtonProps,sourceFtype:FTYPE.simple_push_button}}get defaultInternallyConnectedPinNames(){return[]}initPorts(){super.initPorts({pinCount:2,ignoreSymbolPorts:!0});let symbol=hc[this._getSchematicSymbolNameOrThrow()],symPort1=symbol.ports.find(p3=>p3.labels.includes("1")),symPort2=symbol.ports.find(p3=>p3.labels.includes("2")),ports=this.selectAll("port"),pin1Port=ports.find(p3=>p3.props.pinNumber===1),pin2Port=ports.find(p3=>p3.props.pinNumber===2),pin3Port=ports.find(p3=>p3.props.pinNumber===3),pin4Port=ports.find(p3=>p3.props.pinNumber===4),{internallyConnectedPins}=this._parsedProps;pin1Port.schematicSymbolPortDef=symPort1,(!internallyConnectedPins||internallyConnectedPins.length===0)&&(pin2Port.schematicSymbolPortDef=symPort2);for(let[pn3,port]of[[2,pin2Port],[3,pin3Port],[4,pin4Port]]){let internallyConnectedRow=internallyConnectedPins?.find(([pin1,pin2])=>pin1===`pin${pn3}`||pin2===`pin${pn3}`);if(!internallyConnectedRow){port.schematicSymbolPortDef=symPort2;break}(internallyConnectedRow?.[0]===`pin${pn3}`?internallyConnectedRow[1]:internallyConnectedRow?.[0])!=="pin1"&&(port.schematicSymbolPortDef=symPort2)}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({name:this.name,ftype:FTYPE.simple_push_button,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourcePushButton(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),pushButton=new PushButton({name:sourceElm.name,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:pushButton});footprint&&pushButton.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(pushButton):subcircuit.add(pushButton)}var Resistor2=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"_adjustSilkscreenTextAutomatically",!0)}get config(){return{componentName:"Resistor",schematicSymbolName:this.props.symbolName??"boxresistor",zodProps:resistorProps,sourceFtype:"simple_resistor"}}initPorts(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["cathode","neg","right"]}})}_getSchematicSymbolDisplayValue(){return`${formatSiUnit(this._parsedProps.resistance)}\u03A9`}doInitialCreateNetsFromProps(){this._createNetsFromProps([this.props.pullupFor,this.props.pullupTo,this.props.pulldownFor,this.props.pulldownTo,...this._getNetsFromConnectionsProp()])}doInitialCreateTracesFromProps(){this.props.pullupFor&&this.props.pullupTo&&(this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.pullupFor})),this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.pullupTo}))),this.props.pulldownFor&&this.props.pulldownTo&&(this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.pulldownFor})),this.add(new Trace({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.pulldownTo}))),this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_resistor",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,resistance:props.resistance,display_resistance:this._getSchematicSymbolDisplayValue(),are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceResistor(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),resistor=new Resistor2({name:sourceElm.name,resistance:sourceElm.resistance,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:resistor});footprint&&resistor.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(resistor):subcircuit.add(resistor)}function hasSimProps(props){return props.simSwitchFrequency!==void 0||props.simCloseAt!==void 0||props.simOpenAt!==void 0||props.simStartClosed!==void 0||props.simStartOpen!==void 0}var Switch=class extends NormalComponent3{_getSwitchType(){let props=this._parsedProps;return props?props.dpdt?"dpdt":props.spst?"spst":props.spdt?"spdt":props.dpst?"dpst":props.type??"spst":"spst"}get config(){let switchType=this._getSwitchType(),isNormallyClosed=this._parsedProps?.isNormallyClosed??!1,symbolMap={spst:isNormallyClosed?"spst_normally_closed_switch":"spst_switch",spdt:isNormallyClosed?"spdt_normally_closed_switch":"spdt_switch",dpst:isNormallyClosed?"dpst_normally_closed_switch":"dpst_switch",dpdt:isNormallyClosed?"dpdt_normally_closed_switch":"dpdt_switch"};return{componentName:"Switch",schematicSymbolName:this.props.symbolName??symbolMap[switchType],zodProps:switchProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db:db2}=this.root,props=this._parsedProps??{},source_component=db2.source_component.insert({ftype:"simple_switch",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:this._getSwitchType()==="spst",display_name:props?.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{_parsedProps:props}=this;if(!hasSimProps(props))return;let{db:db2}=this.root,simulationSwitch={type:"simulation_switch",source_component_id:this.source_component_id||""};props.simSwitchFrequency!==void 0&&(simulationSwitch.switching_frequency=frequency.parse(props.simSwitchFrequency)),props.simCloseAt!==void 0&&(simulationSwitch.closes_at=ms.parse(props.simCloseAt)),props.simOpenAt!==void 0&&(simulationSwitch.opens_at=ms.parse(props.simOpenAt)),props.simStartOpen!==void 0&&(simulationSwitch.starts_closed=!props.simStartOpen),props.simStartClosed!==void 0&&(simulationSwitch.starts_closed=props.simStartClosed),db2.simulation_switch.insert(simulationSwitch)}},getImportedSwitchProps=(sourceElm,inflatorContext)=>{let sourcePorts=inflatorContext.injectionDb.source_port.list().filter(port=>port.source_component_id===sourceElm.source_component_id),pinLabels={},highestPinNumber=0;for(let sourcePort of sourcePorts){let pinNumber=sourcePort.pin_number;if(pinNumber==null)continue;highestPinNumber=Math.max(highestPinNumber,pinNumber);let labels=Array.from(new Set([sourcePort.name,...sourcePort.port_hints??[]].filter(label=>typeof label=="string"&&label.length>0)));labels.length>0&&(pinLabels[`pin${pinNumber}`]=labels)}let type="spst";return highestPinNumber>=5?type="dpdt":highestPinNumber===4?type="dpst":highestPinNumber===3&&(type="spdt"),{type,pinLabels:Object.keys(pinLabels).length>0?pinLabels:void 0}};function inflateSourceSwitch(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),importedSwitchProps=getImportedSwitchProps(sourceElm,inflatorContext),switchComponent=new Switch({name:sourceElm.name,displayName:sourceElm.display_name,...importedSwitchProps,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:switchComponent});footprint&&switchComponent.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(switchComponent):subcircuit.add(switchComponent)}function pcbTraceRouteToPcbPath(route){if(route.length<=2)return[];let firstPoint=route[0],lastPoint=route[route.length-1];return route.slice(1,-1).filter(point6=>{let position4=getRoutePointPosition2(point6),firstPosition=getRoutePointPosition2(firstPoint),lastPosition=getRoutePointPosition2(lastPoint),isSameAsFirst=position4.x===firstPosition.x&&position4.y===firstPosition.y,isSameAsLast=position4.x===lastPosition.x&&position4.y===lastPosition.y;return!isSameAsFirst&&!isSameAsLast}).map(point6=>{if(point6.route_type==="via")return{x:point6.x,y:point6.y,via:!0,fromLayer:point6.from_layer,toLayer:point6.to_layer};let position4=getRoutePointPosition2(point6);return{x:position4.x,y:position4.y}})}var getSelectorPath=(component,inflatorContext)=>{let{injectionDb,subcircuit,groupsMap}=inflatorContext,path_parts=[],currentGroupId=component.source_group_id;for(;currentGroupId&&currentGroupId!==subcircuit.source_group_id;){let sourceGroup=injectionDb.source_group.get(currentGroupId),groupInstance=groupsMap?.get(currentGroupId);if(!sourceGroup||!groupInstance)break;let groupName=groupInstance.props.name??groupInstance.fallbackUnassignedName;path_parts.unshift(`.${groupName}`),currentGroupId=sourceGroup.parent_source_group_id}return path_parts.push(`.${component.name}`),path_parts.join(" > ")};function inflateSourceTrace(sourceTrace,inflatorContext){let{injectionDb,subcircuit}=inflatorContext,connectedSelectors=[];for(let sourcePortId of sourceTrace.connected_source_port_ids){let sourcePort=injectionDb.source_port.get(sourcePortId);if(!sourcePort)continue;let selector;if(sourcePort.source_component_id){let sourceComponent=injectionDb.source_component.get(sourcePort.source_component_id);sourceComponent&&(selector=`${getSelectorPath({name:sourceComponent.name,source_group_id:sourceComponent.source_group_id},inflatorContext)} > .${sourcePort.name}`)}else selector=`.${sourcePort.name}`;selector&&connectedSelectors.push(selector)}for(let sourceNetId of sourceTrace.connected_source_net_ids){let sourceNet=injectionDb.source_net.get(sourceNetId);sourceNet&&connectedSelectors.push(`net.${sourceNet.name}`)}if(connectedSelectors.length<2)return;let pcbTraces=injectionDb.pcb_trace.list().filter(trace2=>trace2.source_trace_id===sourceTrace.source_trace_id),pcbTrace=pcbTraces[0],pcbPath2;pcbTrace&&(pcbPath2=pcbTraceRouteToPcbPath(pcbTrace.route));let traceWidth=sourceTrace.min_trace_thickness;if(!traceWidth&&pcbTrace?.route){let wirePoint=pcbTrace.route.find(pt3=>pt3.route_type==="wire");wirePoint&&wirePoint.route_type==="wire"&&(traceWidth=wirePoint.width)}let traceProps2={path:connectedSelectors};traceWidth!==void 0&&(traceProps2.thickness=traceWidth),pcbPath2&&pcbPath2.length>0?traceProps2.pcbPath=pcbPath2:!pcbTrace&&sourceTrace.connected_source_port_ids.length===2&&sourceTrace.connected_source_net_ids.length===0&&(traceProps2.pcbStraightLine=!0);let trace=new Trace(traceProps2);trace._inflatedPcbTraces=pcbTraces.length>0?pcbTraces:void 0,trace._inflatedPcbVias=pcbTrace?injectionDb.pcb_via.list().filter(via=>pcbTraces.some(trace2=>via.pcb_trace_id===trace2.pcb_trace_id)):void 0,subcircuit.add(trace)}var SHORT_ALIASES={collector:["c"],base:["b"],emitter:["e"]},Transistor=class extends NormalComponent3{get config(){let baseSymbolName=this.props.type==="npn"?"npn_bipolar_transistor":"pnp_bipolar_transistor";return{componentName:"Transistor",schematicSymbolName:this.props.symbolName??baseSymbolName,zodProps:transistorProps,sourceFtype:"simple_transistor",shouldRenderAsSchematicBox:!1}}initPorts(){let additionalAliases={},symbol=this.getSchematicSymbol();for(let symPort of symbol?.ports??[]){let pinNumber=getPinNumberFromLabels(symPort.labels);if(pinNumber)for(let label of symPort.labels){let shortAliases=SHORT_ALIASES[label];shortAliases&&(additionalAliases[`pin${pinNumber}`]=shortAliases)}}super.initPorts({pinCount:3,additionalAliases})}get collector(){return this.portMap.collector}get base(){return this.portMap.base}get emitter(){return this.portMap.emitter}doInitialCreateNetsFromProps(){this._createNetsFromProps([...this._getNetsFromConnectionsProp()])}doInitialCreateTracesFromProps(){this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_transistor",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,transistor_type:props.type,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function inflateSourceTransistor(sourceElm,inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),{pcbX,pcbY}=getInflatedPcbPlacement({pcbComponent:pcbElm,sourceGroupId:sourceElm.source_group_id,inflatorContext}),transistor=new Transistor({name:sourceElm.name,type:sourceElm.transistor_type,layer:pcbElm?.layer,pcbX,pcbY,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});if(pcbElm){let footprint=inflateFootprintComponent(pcbElm,{...inflatorContext,normalComponent:transistor});footprint&&transistor.add(footprint)}sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(transistor):subcircuit.add(transistor)}function inflateStandalonePcbPrimitives(inflatorContext){let{injectionDb,subcircuit,groupsMap}=inflatorContext,standalonePrimitiveTypes=["pcb_silkscreen_rect","pcb_silkscreen_circle","pcb_silkscreen_line","pcb_silkscreen_path","pcb_silkscreen_text","pcb_fabrication_note_text","pcb_fabrication_note_path","pcb_fabrication_note_rect","pcb_note_text","pcb_note_rect","pcb_note_path","pcb_note_line","pcb_via","pcb_hole","pcb_plated_hole","pcb_cutout"],standalonePrimitives=injectionDb.toArray().filter(elm=>{if(!standalonePrimitiveTypes.includes(elm.type))return!1;if(elm.type==="pcb_via"){if(!elm.pcb_trace_id)return!0;let pcbTrace=injectionDb.pcb_trace.get(elm.pcb_trace_id),sourceTraceId=pcbTrace?.source_trace_id;return!(sourceTraceId&&injectionDb.source_trace.get(sourceTraceId)&&pcbTrace?.route.some(point6=>point6.route_type==="via"&&Math.abs(point6.x-elm.x)<1e-4&&Math.abs(point6.y-elm.y)<1e-4))}return elm.type==="pcb_cutout"?!0:"pcb_component_id"in elm&&(elm.pcb_component_id===null||elm.pcb_component_id===void 0)});if(standalonePrimitives.length===0)return;let components=createComponentsFromCircuitJson({componentName:"",componentRotation:"0deg"},standalonePrimitives);for(let component of components)subcircuit.add(component)}var inflateCircuitJson=(target,circuitJson,children)=>{if(!circuitJson)return;let injectionDb=cju_default(circuitJson);if(circuitJson&&children?.length>0)throw new Error("Component cannot have both circuitJson and children");let inflationCtx={injectionDb,subcircuit:target,groupsMap:new Map},sourceGroups=injectionDb.source_group.list(),renderedGroupIds=new Set,groupsToRender=[...sourceGroups];for(;groupsToRender.length>0;){let groupIndex=groupsToRender.findIndex(g4=>!g4.parent_source_group_id||renderedGroupIds.has(g4.parent_source_group_id));if(groupIndex===-1){let remainingIds=groupsToRender.map(g4=>g4.source_group_id).join(", ");throw new Error(`Cannot inflate source_groups: cyclic dependency or missing parent detected. Remaining groups: ${remainingIds}`)}let groupToRender=groupsToRender[groupIndex];inflateSourceGroup(groupToRender,inflationCtx),renderedGroupIds.add(groupToRender.source_group_id),groupsToRender.splice(groupIndex,1)}let pcbBoards=injectionDb.pcb_board.list();for(let pcbBoard of pcbBoards)inflatePcbBoard(pcbBoard,inflationCtx);let sourceComponents=injectionDb.source_component.list();for(let sourceComponent of sourceComponents)switch(sourceComponent.ftype){case"simple_resistor":inflateSourceResistor(sourceComponent,inflationCtx);break;case"simple_capacitor":inflateSourceCapacitor(sourceComponent,inflationCtx);break;case"simple_inductor":inflateSourceInductor(sourceComponent,inflationCtx);break;case"simple_diode":inflateSourceDiode(sourceComponent,inflationCtx);break;case"simple_fiducial":inflateSourceFiducial(sourceComponent,inflationCtx);break;case"simple_led":inflateSourceLed(sourceComponent,inflationCtx);break;case"simple_chip":inflateSourceChip(sourceComponent,inflationCtx);break;case"simple_connector":inflateSourceConnector(sourceComponent,inflationCtx);break;case"simple_transistor":inflateSourceTransistor(sourceComponent,inflationCtx);break;case"simple_mosfet":inflateSourceMosfet(sourceComponent,inflationCtx);break;case"simple_push_button":inflateSourcePushButton(sourceComponent,inflationCtx);break;case"simple_switch":inflateSourceSwitch(sourceComponent,inflationCtx);break;default:throw new Error(`No inflator implemented for source component ftype: "${sourceComponent.ftype}"`)}let sourcePorts=injectionDb.source_port.list();for(let sourcePort of sourcePorts)inflateSourcePort(sourcePort,inflationCtx);let sourceTraces=injectionDb.source_trace.list();for(let sourceTrace of sourceTraces)inflateSourceTrace(sourceTrace,inflationCtx);inflateStandalonePcbPrimitives(inflationCtx)},isSelectionResultPort=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.getSourcePort=="function",isSelectionResultNet=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.getSourceNet=="function",isSelectionResultComponent=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.getPorts=="function",isCircuitJsonElement=connectable=>!connectable||typeof connectable!="object"?!1:typeof connectable.type=="string",isNonEmptyString=value=>typeof value=="string"&&value.length>0,SelectionResultPortImpl=class{constructor(port){__publicField(this,"port");this.port=port}getPcbPort(){let pcbPortId=this.port.pcb_port_id;return pcbPortId?this.port.root?.db.pcb_port.get(pcbPortId)??null:null}getSourcePort(){let sourcePortId=this.port.source_port_id;return sourcePortId?this.port.root?.db.source_port.get(sourcePortId)??null:null}},SelectionResultNetImpl=class{constructor(net){__publicField(this,"net");this.net=net}getSourceNet(){let sourceNetId=this.net.source_net_id;return sourceNetId?this.net.root?.db.source_net.get(sourceNetId)??null:null}},SelectionResultComponentImpl=class{constructor(component){__publicField(this,"component");this.component=component}getPort(name){let port=this.component.selectOne(`port.${name}`,{type:"port"})??this.component.selectOne(`.${name}`,{type:"port"});return port?new SelectionResultPortImpl(port):null}getPorts(){return this.component.selectAll("port").map(port=>new SelectionResultPortImpl(port))}getPcbComponent(){let pcbComponentId=this.component.pcb_component_id;return pcbComponentId?this.component.root?.db.pcb_component.get(pcbComponentId)??null:null}getSourceComponent(){let sourceComponentId=this.component.source_component_id;return sourceComponentId?this.component.root?.db.source_component.get(sourceComponentId)??null:null}},DrcCheck=class extends PrimitiveComponent2{get config(){return{componentName:"DrcCheck",zodProps:drcCheckProps}}constructor(props){super(props)}async runCustomDrcCheck(circuitJson){let result=await this._parsedProps.checkFn(this.createCustomDrcCheckContext(circuitJson)),diagnostics=[];return Array.isArray(result)?diagnostics=result:result&&(diagnostics=[result]),diagnostics.map((diagnostic,index)=>this.createCircuitJsonDiagnostic(diagnostic,index)).filter(diagnostic=>!!diagnostic)}createCustomDrcCheckContext(circuitJson){return{select:this.selectCustomDrcElement.bind(this),selectAll:this.selectAllCustomDrcElements.bind(this),isConnected:(a6,b6)=>this.isConnected(a6,b6,circuitJson),isPulledUp:a6=>this.isConnected(a6,"net.VCC",circuitJson)||this.isConnected(a6,"net.VDD",circuitJson)||this.getResistanceBetween(a6,"net.VCC",circuitJson)!==null||this.getResistanceBetween(a6,"net.VDD",circuitJson)!==null,isPulledDown:a6=>this.isConnected(a6,"net.GND",circuitJson)||this.getResistanceBetween(a6,"net.GND",circuitJson)!==null,getResistanceBetween:(a6,b6)=>this.getResistanceBetween(a6,b6,circuitJson)}}selectCustomDrcElement(selector){return this.wrapSelectionResult(this.getSubcircuit().selectOne(selector))}selectAllCustomDrcElements(selector){let selectionResults=[];for(let component of this.getSubcircuit().selectAll(selector)){let selectionResult=this.wrapSelectionResult(component);selectionResult&&selectionResults.push(selectionResult)}return selectionResults}wrapSelectionResult(component){return component?component instanceof Port?new SelectionResultPortImpl(component):component instanceof Net?new SelectionResultNetImpl(component):new SelectionResultComponentImpl(component):null}createCircuitJsonDiagnostic(diagnostic,index){let diagnosticRecord=diagnostic,diagnosticType="source_component_misconfigured_error";typeof diagnosticRecord.error_type=="string"?diagnosticType=diagnosticRecord.error_type:typeof diagnosticRecord.warning_type=="string"&&(diagnosticType=diagnosticRecord.warning_type);let diagnosticWithCircuitJsonDefaults={...diagnostic};typeof diagnosticRecord.type=="string"?diagnosticWithCircuitJsonDefaults.type=diagnosticRecord.type:diagnosticWithCircuitJsonDefaults.type=diagnosticType,typeof diagnosticRecord.warning_type!="string"&&(typeof diagnosticRecord.error_type=="string"?diagnosticWithCircuitJsonDefaults.error_type=diagnosticRecord.error_type:diagnosticWithCircuitJsonDefaults.error_type=diagnosticType);let diagnosticIdField=`${diagnosticType}_id`;return diagnosticRecord[diagnosticIdField]?diagnosticWithCircuitJsonDefaults[diagnosticIdField]=diagnosticRecord[diagnosticIdField]:diagnosticWithCircuitJsonDefaults[diagnosticIdField]=`${diagnosticType}_${this._renderId}_${index}`,any_circuit_element.parse(diagnosticWithCircuitJsonDefaults)}isConnected(a6,b6,circuitJson){let aKeys=this.getConnectivityKeys(a6,circuitJson),bKeys=this.getConnectivityKeys(b6,circuitJson);return aKeys.some(key=>bKeys.includes(key))}getResistanceBetween(a6,b6,circuitJson){if(this.isConnected(a6,b6,circuitJson))return 0;let aKeys=this.getConnectivityKeys(a6,circuitJson),bKeys=this.getConnectivityKeys(b6,circuitJson);if(aKeys.length===0||bKeys.length===0)return null;let sourceResistors=circuitJson.filter(elm=>elm.type==="source_component"&&elm.ftype==="simple_resistor"),root=this.root;if(!root)return null;for(let resistor of sourceResistors){let resistorPorts=root.db.source_port.list({source_component_id:resistor.source_component_id});if(resistorPorts.length!==2)continue;let resistorKeys=resistorPorts.map(port=>port.subcircuit_connectivity_map_key),connectsA=resistorKeys.some(key=>key&&aKeys.includes(key)),connectsB=resistorKeys.some(key=>key&&bKeys.includes(key));if(connectsA&&connectsB)return resistor.resistance}return null}getConnectivityKeys(connectable,circuitJson){if(!connectable)return[];if(typeof connectable=="string"){let selected=this.selectCustomDrcElement(connectable);return selected?this.getConnectivityKeys(selected,circuitJson):[]}return isSelectionResultPort(connectable)?[connectable.getSourcePort()?.subcircuit_connectivity_map_key].filter(isNonEmptyString):isSelectionResultNet(connectable)?[connectable.getSourceNet()?.subcircuit_connectivity_map_key].filter(isNonEmptyString):isSelectionResultComponent(connectable)?connectable.getPorts().flatMap(port=>this.getConnectivityKeys(port,circuitJson)):isCircuitJsonElement(connectable)?this.getCircuitJsonElementConnectivityKeys(connectable,circuitJson):[]}getCircuitJsonElementConnectivityKeys(element,circuitJson){if(!element)return[];if(element.type==="source_port")return[element.subcircuit_connectivity_map_key].filter(isNonEmptyString);if(element.type==="source_net")return[element.subcircuit_connectivity_map_key].filter(isNonEmptyString);if(element.type==="pcb_port")return this.getConnectivityKeys(element.source_port_id,circuitJson);if(element.type==="source_component"){let root=this.root;return root?root.db.source_port.list({source_component_id:element.source_component_id}).map(port=>port.subcircuit_connectivity_map_key).filter(isNonEmptyString):[]}return[]}},IsolatedCircuit=class{constructor({platform,projectUrl,cachedSubcircuits,pendingSubcircuitRenders}={}){__publicField(this,"firstChild",null);__publicField(this,"children");__publicField(this,"db");__publicField(this,"root",null);__publicField(this,"isRootCircuit",!1);__publicField(this,"cachedSubcircuits");__publicField(this,"pendingSubcircuitRenders");__publicField(this,"_schematicDisabledOverride");__publicField(this,"pcbDisabled",!1);__publicField(this,"pcbRoutingDisabled",!1);__publicField(this,"_featureMspSchematicTraceRouting",!0);__publicField(this,"name");__publicField(this,"platform");__publicField(this,"projectUrl");__publicField(this,"_hasRenderedAtleastOnce",!1);__publicField(this,"_asyncEffectIdsByPhase",new Map);__publicField(this,"_asyncEffectPhaseById",new Map);__publicField(this,"_hasUnrenderedUpdatesFromAsyncEffects",!1);__publicField(this,"_runningAsyncEffectsById",new Map);__publicField(this,"_eventListeners",{});this.children=[],this.db=su2([]),this.platform=platform,this.projectUrl=projectUrl,this.pcbDisabled=platform?.pcbDisabled??!1,this.pcbRoutingDisabled=platform?.routingDisabled??!1,this.cachedSubcircuits=cachedSubcircuits,this.pendingSubcircuitRenders=pendingSubcircuitRenders,this.root=this}get schematicDisabled(){return this._schematicDisabledOverride!==void 0?this._schematicDisabledOverride:this.platform?.schematicDisabled!==void 0?this.platform.schematicDisabled:this._getBoard()?._parsedProps?.schematicDisabled??!1}set schematicDisabled(value){this._schematicDisabledOverride=value}add(componentOrElm){let component;(0,import_react7.isValidElement)(componentOrElm)?component=createInstanceFromReactElement(componentOrElm):component=componentOrElm,this.children.push(component)}setPlatform(platform){this.platform={...this.platform,...platform},platform.pcbDisabled!==void 0&&(this.pcbDisabled=platform.pcbDisabled),platform.routingDisabled!==void 0&&(this.pcbRoutingDisabled=platform.routingDisabled)}_getBoard(){let findBoard=components=>{for(let child of components){if(child.componentName==="Board")return child;if(isAssemblyDeviceContainer(child)){let nested=findBoard(child.children);if(nested)return nested}}};return findBoard(this.children)}_guessRootComponent(){if(this.firstChild)return;if(this.children.length===0)throw new Error("Not able to guess root component: IsolatedCircuit has no children (use circuit.add(...))");let panels=this.children.filter(child=>child.lowercaseComponentName==="panel");if(panels.length>1)throw new Error("Only one <panel> is allowed per circuit");if(panels.length===1){if(this.children.length!==1)throw new Error("<panel> must be the root element of the circuit");this.firstChild=panels[0];return}if(this.children.length===1&&(this.children[0].isGroup||isAssemblyDeviceContainer(this.children[0]))){this.firstChild=this.children[0];return}let group=new Group5({subcircuit:!0});group.parent=this,group.addAll(this.children),this.children=[group],this.firstChild=group}render(){this.firstChild||this._guessRootComponent();let{firstChild,db:db2}=this;if(!firstChild)throw new Error("IsolatedCircuit has no root component");firstChild.parent=this,firstChild.runRenderCycle(),this._hasUnrenderedUpdatesFromAsyncEffects=!1,this._hasRenderedAtleastOnce=!0}async renderUntilSettled(){for(this.db.source_project_metadata.list()?.[0]||this.db.source_project_metadata.insert({software_used_string:`@tscircuit/core@${this.getCoreVersion()}`,...this.projectUrl?{project_url:this.projectUrl}:{}}),this.render();!this.isDoneRendering();)await new Promise(resolve=>setTimeout(resolve,100)),this.render();this.emit("renderComplete")}isDoneRendering(){return this._hasRenderedAtleastOnce&&!this._hasIncompleteAsyncEffects()}_hasIncompleteAsyncEffects(){return this._asyncEffectPhaseById.size>0||this._hasUnrenderedUpdatesFromAsyncEffects?!0:this.children.some(child=>child._hasIncompleteAsyncEffects())}_hasIncompleteAsyncEffectsForPhase(phase){return(this._asyncEffectIdsByPhase.get(phase)?.size??0)>0}getRunningAsyncEffects(){return Array.from(this._runningAsyncEffectsById.values())}getCircuitJson(){return this._hasRenderedAtleastOnce||this.render(),this.db.toArray()}toJson(){return this.getCircuitJson()}async getSvg(options){let circuitToSvg=await Promise.resolve().then(()=>(init_dist9(),dist_exports3)).catch(e6=>{throw new Error(`To use circuit.getSvg, you must install the "circuit-to-svg" package.
742
742
 
743
743
  "${e6.message}"`)});if(options.view==="pcb")return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());if(options.view==="schematic")return circuitToSvg.convertCircuitJsonToSchematicSvg(this.getCircuitJson());throw new Error(`Invalid view: ${options.view}`)}getCoreVersion(){let[major,minor,patch]=package_default3.version.split(".").map(Number);return`${major}.${minor}.${patch+1}`}async preview(previewNameOrOpts){let previewOpts=typeof previewNameOrOpts=="object"?previewNameOrOpts:{previewName:previewNameOrOpts};throw new Error("project.preview is not yet implemented")}computeSchematicGlobalTransform(){return identity()}_computePcbGlobalTransformBeforeLayout(){return identity()}selectAll(selector){return this._guessRootComponent(),this.firstChild?.selectAll(selector)??[]}selectOne(selector,opts){return this._guessRootComponent(),this.firstChild?.selectOne(selector,opts)??null}emit(event,...args){if(event==="asyncEffect:start"?this._registerAsyncEffectStart(args[0]):event==="asyncEffect:end"&&this._registerAsyncEffectEnd(args[0]),!!this._eventListeners[event])for(let listener of this._eventListeners[event])listener(...args)}on(event,listener){this._eventListeners[event]||(this._eventListeners[event]=[]),this._eventListeners[event].push(listener)}removeListener(event,listener){this._eventListeners[event]&&(this._eventListeners[event]=this._eventListeners[event].filter(l6=>l6!==listener))}enableDebug(debug132){typeof debug132=="string"?import_debug21.default.enable(debug132):(debug132===null||debug132===!1)&&import_debug21.default.disable()}getClientOrigin(){return typeof window<"u"&&window.location?window.location.origin:typeof self<"u"&&self.location?self.location.origin:""}_registerAsyncEffectStart(payload){if(!payload?.asyncEffectId||!payload.phase)return;let{asyncEffectId,phase}=payload,existingPhase=this._asyncEffectPhaseById.get(asyncEffectId);existingPhase&&existingPhase!==phase&&this._asyncEffectIdsByPhase.get(existingPhase)?.delete(asyncEffectId),this._asyncEffectIdsByPhase.has(phase)||this._asyncEffectIdsByPhase.set(phase,new Set),this._asyncEffectIdsByPhase.get(phase).add(asyncEffectId),this._asyncEffectPhaseById.set(asyncEffectId,phase),this._runningAsyncEffectsById.set(asyncEffectId,{asyncEffectId,effectName:payload.effectName,componentDisplayName:payload.componentDisplayName,phase,error:payload.error})}_registerAsyncEffectEnd(payload){if(!payload?.asyncEffectId)return;let{asyncEffectId}=payload,phase=this._asyncEffectPhaseById.get(asyncEffectId)??payload.phase;if(phase){let phaseSet=this._asyncEffectIdsByPhase.get(phase);phaseSet?.delete(asyncEffectId),phaseSet&&phaseSet.size===0&&this._asyncEffectIdsByPhase.delete(phase)}this._asyncEffectPhaseById.delete(asyncEffectId),this._runningAsyncEffectsById.delete(asyncEffectId),this._hasUnrenderedUpdatesFromAsyncEffects=!0}};function Subcircuit_doInitialRenderIsolatedSubcircuits(subcircuit){if(!subcircuit._isIsolatedSubcircuit||subcircuit._isolatedCircuitJson||!subcircuit.getSubcircuitPropHash)return;let propHash=subcircuit.getSubcircuitPropHash(),cachedSubcircuits=subcircuit.root?.cachedSubcircuits,pendingSubcircuitRenders=subcircuit.root?.pendingSubcircuitRenders,cached=cachedSubcircuits?.get(propHash);if(cached){subcircuit._isolatedCircuitJson=cached,subcircuit.children=[],subcircuit._normalComponentNameMap=null;return}let childrenToRender=[...subcircuit.children];subcircuit.children=[],subcircuit._normalComponentNameMap=null;let parentRoot=subcircuit.root;subcircuit._queueAsyncEffect("render-isolated-subcircuit",async()=>{let cachedResult=cachedSubcircuits?.get(propHash);if(cachedResult){subcircuit._isolatedCircuitJson=cachedResult;return}let pendingRenderPromise=pendingSubcircuitRenders?.get(propHash);if(pendingRenderPromise){subcircuit._isolatedCircuitJson=await pendingRenderPromise;return}let resolveRender,rejectRender,renderPromise=new Promise((resolve,reject)=>{resolveRender=resolve,rejectRender=reject});pendingSubcircuitRenders?.set(propHash,renderPromise);try{let isolatedCircuit=new IsolatedCircuit({platform:{...parentRoot.platform,pcbDisabled:parentRoot.pcbDisabled,schematicDisabled:parentRoot.schematicDisabled},cachedSubcircuits,pendingSubcircuitRenders});for(let child of childrenToRender)isolatedCircuit.add(child);await isolatedCircuit.renderUntilSettled();let circuitJson=isolatedCircuit.getCircuitJson();cachedSubcircuits?.set(propHash,circuitJson),subcircuit._isolatedCircuitJson=circuitJson,resolveRender(circuitJson)}catch(error2){throw rejectRender(error2 instanceof Error?error2:new Error(String(error2))),error2}finally{pendingSubcircuitRenders?.delete(propHash)}})}var EXCLUDED_PROPS=new Set(["name","key","pcbX","pcbY","schX","schY","pcbLeftEdgeX","pcbRightEdgeX","pcbTopEdgeY","pcbBottomEdgeY","pcbRotation","schRotation"]);function safeSerialize(value,seen=new WeakSet){if(value===null)return"null";if(value===void 0)return"undefined";let type=typeof value;if(type==="string")return`"${value}"`;if(type==="number"||type==="boolean")return String(value);if(type==="function")return"[function]";if(type==="symbol")return"[symbol]";if(type==="object"){if(seen.has(value))return"[circular]";if(seen.add(value),value.$$typeof!==void 0){let elementType=typeof value.type=="string"?value.type:value.type?.name||"[component]",propsStr=value.props?safeSerialize(value.props,seen):"{}";return`ReactElement(${elementType},${propsStr})`}return Array.isArray(value)?`[${value.map(v6=>safeSerialize(v6,seen)).join(",")}]`:`{${Object.keys(value).sort().map(k7=>`${k7}:${safeSerialize(value[k7],seen)}`).join(",")}}`}return String(value)}function getHashableProps(props){let result={},keys=Object.keys(props).sort();for(let key of keys)!EXCLUDED_PROPS.has(key)&&props[key]!==void 0&&(result[key]=props[key]);return result}function getChildrenHashData(children){return children.map(child=>({componentName:child.componentName,props:getHashableProps(child.props??{}),children:getChildrenHashData(child.children)}))}function fnv1aHash(str){let hash=2166136261;for(let i6=0;i6<str.length;i6++)hash^=str.charCodeAt(i6),hash=Math.imul(hash,16777619);return hash>>>0}function computeHash(data){let serialized=safeSerialize(data),hash1=fnv1aHash(serialized),hash2=fnv1aHash(serialized+hash1.toString());return hash1.toString(16).padStart(8,"0")+hash2.toString(16).padStart(8,"0")}function Subcircuit_getSubcircuitPropHash(subcircuit){let hashableData={props:getHashableProps(subcircuit.props??{}),children:getChildrenHashData(subcircuit.children)};return computeHash(hashableData)}var resetPcbTraceRenderInSubtree=renderable=>{renderable._pcbTraceRenderWaitingForPlacementChecks&&(renderable.renderPhaseStates.PcbTraceRender.initialized=!1,renderable.renderPhaseStates.PcbTraceRender.dirty=!1,renderable._pcbTraceRenderWaitingForPlacementChecks=!1);for(let child of renderable.children)resetPcbTraceRenderInSubtree(child)},Board_doInitialPcbPlacementDesignRuleChecks=board=>{if(board.root?.pcbDisabled)return;let placementDrcChecksDisabled=board.root?.platform?.placementDrcChecksDisabled??board.getInheritedProperty("placementDrcChecksDisabled"),drcChecksDisabled=board.root?.platform?.drcChecksDisabled??board.getInheritedProperty("drcChecksDisabled");if(board._pcbPlacementDrcErrorCount=null,board._pcbPlacementDrcCheckError=null,board._pcbPlacementDrcChecksPending=!1,placementDrcChecksDisabled||drcChecksDisabled){board._pcbPlacementDrcErrorCount=0;return}let{db:db2}=board.root,subcircuitCircuitJson=db2.subtree({subcircuit_id:board.subcircuit_id}).toArray(),existingPlacementDiagnostics=db2.toArray();board._pcbPlacementDrcChecksPending=!0,board._queueAsyncEffect("board:pre-route-placement-checks",async()=>{try{let placementCheckResults=await runAllPlacementChecks(subcircuitCircuitJson),newPlacementDiagnostics=placementCheckResults.filter(result=>!existingPlacementDiagnostics.some(existing=>existing.type===result.type&&"message"in existing&&existing.message===result.message));db2.insertAll(newPlacementDiagnostics),board._pcbPlacementDrcErrorCount=placementCheckResults.filter(result=>result.type.endsWith("_error")).length}catch(error2){board._pcbPlacementDrcCheckError=error2 instanceof Error?error2.message:String(error2)}finally{board._pcbPlacementDrcChecksPending=!1,resetPcbTraceRenderInSubtree(board)}})},MIN_EFFECTIVE_BORDER_RADIUS_MM=.01,DEFAULT_VIA_PAD_DIAMETER_OVER_HOLE_DIAMETER_MM=.15,getRoundedRectOutline=(width,height,radius)=>{let w22=width/2,h22=height/2,r6=Math.min(radius,w22,h22);if(r6<MIN_EFFECTIVE_BORDER_RADIUS_MM)return[{x:-w22,y:-h22},{x:w22,y:-h22},{x:w22,y:h22},{x:-w22,y:h22}];let segments=Math.max(1,Math.ceil(Math.PI/2*r6/.1)),step=Math.PI/2/segments,outline=[];outline.push({x:-w22+r6,y:-h22}),outline.push({x:w22-r6,y:-h22});for(let i6=1;i6<=segments;i6++){let theta=-Math.PI/2+i6*step;outline.push({x:w22-r6+r6*Math.cos(theta),y:-h22+r6+r6*Math.sin(theta)})}outline.push({x:w22,y:h22-r6});for(let i6=1;i6<=segments;i6++){let theta=0+i6*step;outline.push({x:w22-r6+r6*Math.cos(theta),y:h22-r6+r6*Math.sin(theta)})}outline.push({x:-w22+r6,y:h22});for(let i6=1;i6<=segments;i6++){let theta=Math.PI/2+i6*step;outline.push({x:-w22+r6+r6*Math.cos(theta),y:h22-r6+r6*Math.sin(theta)})}outline.push({x:-w22,y:-h22+r6});for(let i6=1;i6<=segments;i6++){let theta=Math.PI+i6*step;outline.push({x:-w22+r6+r6*Math.cos(theta),y:-h22+r6+r6*Math.sin(theta)})}return outline},Board=class extends Group5{constructor(){super(...arguments);__publicField(this,"pcb_board_id",null);__publicField(this,"source_board_id",null);__publicField(this,"_drcChecksComplete",!1);__publicField(this,"_drcChecksInProgress",!1);__publicField(this,"_connectedSchematicPortPairs",new Set);__publicField(this,"_panelPositionOffset",null)}get isSubcircuit(){return!0}get isGroup(){return!0}get config(){return{componentName:"Board",zodProps:boardProps}}get boardThickness(){return this._parsedProps.thickness??1.4}get allLayers(){return getBoardAvailableLayers(this._parsedProps.layers??2)}_getSubcircuitLayerCount(){return this._parsedProps.layers??2}_computePcbGlobalTransformBeforeLayout(){if(this._panelPositionOffset){let parentTransform=this.parent?._computePcbGlobalTransformBeforeLayout?.()??{a:1,b:0,c:0,d:1,e:0,f:0};return compose2(parentTransform,translate2(this._panelPositionOffset.x,this._panelPositionOffset.y))}return super._computePcbGlobalTransformBeforeLayout()}_getBoardCalcVariables(){let{_parsedProps:props}=this;if((props.width==null||props.height==null)&&!props.outline)return{};let dbBoard=this.pcb_board_id?this.root?.db.pcb_board.get(this.pcb_board_id):null,width=dbBoard?.width??props.width,height=dbBoard?.height??props.height;if((width==null||height==null)&&props.outline?.length){let outlineBounds=getBoundsFromPoints2(props.outline);outlineBounds&&(width??(width=outlineBounds.maxX-outlineBounds.minX),height??(height=outlineBounds.maxY-outlineBounds.minY))}let{pcbX,pcbY}=this.getResolvedPcbPositionProp(),center2=dbBoard?.center??{x:pcbX+(props.outlineOffsetX??0),y:pcbY+(props.outlineOffsetY??0)},resolvedWidth=width??0,resolvedHeight=height??0;return{"board.minX":center2.x-resolvedWidth/2,"board.maxX":center2.x+resolvedWidth/2,"board.minY":center2.y-resolvedHeight/2,"board.maxY":center2.y+resolvedHeight/2}}doInitialPcbBoardAutoSize(){if(this.root?.pcbDisabled||!this.pcb_board_id)return;let{db:db2}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalPcbPositionBeforeLayout(),pcbBoard=db2.pcb_board.get(this.pcb_board_id);if(pcbBoard?.width&&pcbBoard?.height||pcbBoard?.outline&&pcbBoard.outline.length>0)return;let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0,descendantIds=getDescendantSubcircuitIds2(db2,this.subcircuit_id),allowedSubcircuitIds=new Set([this.subcircuit_id,...descendantIds]),allPcbComponents=db2.pcb_component.list().filter(c3=>c3.subcircuit_id&&allowedSubcircuitIds.has(c3.subcircuit_id)),allPcbGroups=db2.pcb_group.list().filter(g4=>g4.subcircuit_id&&allowedSubcircuitIds.has(g4.subcircuit_id)),hasComponents=!1,updateBounds=(center22,width,height)=>{width===0||height===0||(hasComponents=!0,minX=Math.min(minX,center22.x-width/2),minY=Math.min(minY,center22.y-height/2),maxX=Math.max(maxX,center22.x+width/2),maxY=Math.max(maxY,center22.y+height/2))};for(let pcbComponent of allPcbComponents)updateBounds(pcbComponent.center,pcbComponent.width,pcbComponent.height);for(let pcbGroup of allPcbGroups){let width=pcbGroup.width??0,height=pcbGroup.height??0;if(pcbGroup.outline&&pcbGroup.outline.length>0){let bounds=getBoundsFromPoints2(pcbGroup.outline);bounds&&(width=bounds.maxX-bounds.minX,height=bounds.maxY-bounds.minY)}updateBounds(pcbGroup.center,width,height)}if(props.boardAnchorPosition){let{x:x6,y:y2}=props.boardAnchorPosition;minX=Math.min(minX,x6),minY=Math.min(minY,y2),maxX=Math.max(maxX,x6),maxY=Math.max(maxY,y2)}let padding=2,computedWidth=hasComponents?maxX-minX+padding*2:0,computedHeight=hasComponents?maxY-minY+padding*2:0,center2={x:hasComponents?(minX+maxX)/2+(props.outlineOffsetX??0):(props.outlineOffsetX??0)+globalPos.x,y:hasComponents?(minY+maxY)/2+(props.outlineOffsetY??0):(props.outlineOffsetY??0)+globalPos.y},finalWidth=props.width??computedWidth,finalHeight=props.height??computedHeight,outline=props.outline;!outline&&props.borderRadius!=null&&finalWidth>0&&finalHeight>0&&(outline=getRoundedRectOutline(finalWidth,finalHeight,props.borderRadius));let update={width:finalWidth,height:finalHeight,center:center2};outline&&(update.outline=outline.map(point6=>({x:point6.x+(props.outlineOffsetX??0),y:point6.y+(props.outlineOffsetY??0)}))),db2.pcb_board.update(this.pcb_board_id,update)}updatePcbBoardAutoSize(){this.doInitialPcbBoardAutoSize()}_addBoardInformationToSilkscreen(){let platform=this.root?.platform;if(!platform?.printBoardInformationToSilkscreen)return;let pcbBoard=this.root.db.pcb_board.get(this.pcb_board_id);if(!pcbBoard)return;let boardInformation=[];if(platform.projectName&&boardInformation.push(platform.projectName),platform.version&&boardInformation.push(`v${platform.version}`),platform.url&&boardInformation.push(platform.url),boardInformation.length===0)return;let text=boardInformation.join(`
744
744
  `),position4={x:pcbBoard.center.x+pcbBoard.width/2-.25,y:pcbBoard.center.y-pcbBoard.height/2+1};this.root.db.pcb_silkscreen_text.insert({pcb_component_id:this.pcb_board_id,layer:"top",font:"tscircuit2024",font_size:.45,text,ccw_rotation:0,anchor_alignment:"bottom_right",anchor_position:position4})}doInitialSourceRender(){let nestedBoard=this.getDescendants().find(d3=>d3.lowercaseComponentName==="board");if(nestedBoard)throw new Error(`Nested boards are not supported: found board "${nestedBoard.name}" inside board "${this.name}"`);super.doInitialSourceRender();let{db:db2}=this.root,source_board3=db2.source_board.insert({source_group_id:this.source_group_id,title:this.props.title||this.props.name});this.source_board_id=source_board3.source_board_id}getSubcircuitPropHash(){return Subcircuit_getSubcircuitPropHash(this)}doInitialRenderIsolatedSubcircuits(){Subcircuit_doInitialRenderIsolatedSubcircuits(this)}doInitialInflateSubcircuitCircuitJson(){let isolatedJson=this._isolatedCircuitJson;if(isolatedJson){this._isInflatedFromCircuitJson=!0,this._isolatedCircuitJson=null,inflateCircuitJson(this,isolatedJson,[]);return}let{circuitJson,children}=this._parsedProps;circuitJson&&(this._isInflatedFromCircuitJson=!0),inflateCircuitJson(this,circuitJson,children)}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,pcbBoardFromCircuitJson=props.circuitJson?.find(elm=>elm.type==="pcb_board"),computedWidth=props.width??pcbBoardFromCircuitJson?.width??0,computedHeight=props.height??pcbBoardFromCircuitJson?.height??0,globalPos=this._getGlobalPcbPositionBeforeLayout(),center2={x:globalPos.x+(props.outlineOffsetX??0),y:globalPos.y+(props.outlineOffsetY??0)},{boardAnchorPosition,boardAnchorAlignment}=props;if(boardAnchorPosition&&(center2=getBoardCenterFromAnchor({boardAnchorPosition,boardAnchorAlignment:boardAnchorAlignment??"center",width:computedWidth,height:computedHeight})),props.outline){let xValues=props.outline.map(point6=>point6.x),yValues=props.outline.map(point6=>point6.y),minX=Math.min(...xValues),maxX=Math.max(...xValues),minY=Math.min(...yValues),maxY=Math.max(...yValues);computedWidth=maxX-minX,computedHeight=maxY-minY}let outline=props.outline;!outline&&props.borderRadius!=null&&computedWidth>0&&computedHeight>0&&(outline=getRoundedRectOutline(computedWidth,computedHeight,props.borderRadius));let outlineTranslation={x:0,y:0};if(outline&&outline.length>0&&(this.parent?.lowercaseComponentName==="panel"||this.parent?.lowercaseComponentName==="subpanel")){let outlineBounds=getBoundsFromPoints2(outline);if(outlineBounds){let outlineCenterX=(outlineBounds.minX+outlineBounds.maxX)/2,outlineCenterY=(outlineBounds.minY+outlineBounds.maxY)/2;outlineTranslation={x:center2.x-outlineCenterX,y:center2.y-outlineCenterY}}}let subcircuitProps2=this.getSubcircuit()._parsedProps,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),styledViaDimensions=getViaDiameterDefaults(pcbStyle2),configuredViaHoleDiameter=subcircuitProps2.minViaHoleDiameter??(pcbStyle2?.viaHoleDiameter!==void 0?styledViaDimensions.holeDiameter:void 0),resolvedMinViaHoleDiameter=configuredViaHoleDiameter??jlcMinTolerances2.min_via_hole_diameter,resolvedMinViaPadDiameter=subcircuitProps2.minViaPadDiameter??(pcbStyle2?.viaPadDiameter!==void 0?styledViaDimensions.padDiameter:configuredViaHoleDiameter!==void 0?configuredViaHoleDiameter+DEFAULT_VIA_PAD_DIAMETER_OVER_HOLE_DIAMETER_MM:jlcMinTolerances2.min_via_pad_diameter),pcb_board3=db2.pcb_board.insert({source_board_id:this.source_board_id,center:center2,thickness:this.boardThickness,num_layers:this.allLayers.length,width:computedWidth,height:computedHeight,outline:outline?.map(point6=>({x:point6.x+(props.outlineOffsetX??0)+outlineTranslation.x,y:point6.y+(props.outlineOffsetY??0)+outlineTranslation.y})),material:props.material,...props.isViaInPadAllowed!==void 0&&{is_via_in_pad_allowed:props.isViaInPadAllowed},...props.solderMaskColor!==void 0&&{solder_mask_color:props.solderMaskColor},...props.silkscreenColor!==void 0&&{silkscreen_color:props.silkscreenColor},min_trace_width:subcircuitProps2.minTraceWidth??jlcMinTolerances2.min_trace_width,min_via_hole_diameter:resolvedMinViaHoleDiameter,min_via_pad_diameter:resolvedMinViaPadDiameter,min_via_hole_edge_to_via_hole_edge_clearance:subcircuitProps2.minViaHoleEdgeToViaHoleEdgeClearance??jlcMinTolerances2.min_via_hole_edge_to_via_hole_edge_clearance,min_via_edge_to_pad_edge_clearance:subcircuitProps2.minViaEdgeToPadEdgeClearance??jlcMinTolerances2.min_via_edge_to_pad_edge_clearance,min_trace_to_pad_edge_clearance:subcircuitProps2.minTraceToPadEdgeClearance??jlcMinTolerances2.min_trace_to_pad_edge_clearance,min_pad_edge_to_pad_edge_clearance:subcircuitProps2.minPadEdgeToPadEdgeClearance??jlcMinTolerances2.min_pad_edge_to_pad_edge_clearance,min_plated_hole_drill_edge_to_drill_edge_clearance:subcircuitProps2.minPlatedHoleDrillEdgeToDrillEdgeClearance??jlcMinTolerances2.min_plated_hole_drill_edge_to_drill_edge_clearance,min_board_edge_clearance:subcircuitProps2.minBoardEdgeClearance??jlcMinTolerances2.min_board_edge_clearance});this.pcb_board_id=pcb_board3.pcb_board_id,this._addBoardInformationToSilkscreen()}removePcbComponentRender(){let{db:db2}=this.root;this.pcb_board_id&&(db2.pcb_board.delete(this.pcb_board_id),this.pcb_board_id=null)}doInitialPcbDesignRuleChecks(){this.root?.pcbDisabled||(super.doInitialPcbDesignRuleChecks(),this.updatePcbDesignRuleChecks())}doInitialPcbPlacementDesignRuleChecks(){Board_doInitialPcbPlacementDesignRuleChecks(this)}updatePcbDesignRuleChecks(){let{db:db2}=this.root,routingDisabled=this.root?.pcbRoutingDisabled||this.getInheritedProperty("routingDisabled"),pcbDisabled=this.root?.pcbDisabled,drcChecksDisabled=this.root?.platform?.drcChecksDisabled??this.getInheritedProperty("drcChecksDisabled"),netlistDrcChecksDisabled=this.root?.platform?.netlistDrcChecksDisabled??this.getInheritedProperty("netlistDrcChecksDisabled"),pinSpecificationDrcChecksDisabled=this.getInheritedProperty("pinSpecificationDrcChecksDisabled"),placementDrcChecksDisabled=this.root?.platform?.placementDrcChecksDisabled??this.getInheritedProperty("placementDrcChecksDisabled"),routingDrcChecksDisabled=this.root?.platform?.routingDrcChecksDisabled??this.getInheritedProperty("routingDrcChecksDisabled"),shouldRunNetlistChecks=!drcChecksDisabled&&!netlistDrcChecksDisabled,shouldRunPinSpecificationChecks=!drcChecksDisabled&&!pinSpecificationDrcChecksDisabled,shouldRunPlacementChecks=!drcChecksDisabled&&!pcbDisabled&&!placementDrcChecksDisabled,shouldRunRoutingChecks=!drcChecksDisabled&&!pcbDisabled&&!routingDisabled&&!routingDrcChecksDisabled;if(shouldRunRoutingChecks&&this._hasIncompleteAsyncEffectsInSubtreeForPhase("PcbTraceRender"))return;let hasTracesToRoute=this._hasTracesToRoute();if(shouldRunRoutingChecks&&hasTracesToRoute&&!this._areChildSubcircuitsRouted()||this._drcChecksComplete||this._drcChecksInProgress)return;let runDrcChecks=async circuitJson=>{let checksToRun=[];if(shouldRunRoutingChecks&&checksToRun.push(runAllRoutingChecks(circuitJson)),shouldRunPlacementChecks){let existingPlacementDiagnostics=db2.toArray();checksToRun.push(runAllPlacementChecks(circuitJson).then(results=>results.filter(result=>!existingPlacementDiagnostics.some(existing=>existing.type===result.type&&"message"in existing&&existing.message===result.message))))}if(shouldRunNetlistChecks&&checksToRun.push(runAllNetlistChecks(circuitJson)),shouldRunPinSpecificationChecks&&checksToRun.push(runAllPinSpecificationChecks(circuitJson)),!drcChecksDisabled)for(let drcCheck of this.selectAll("drccheck"))checksToRun.push(drcCheck.runCustomDrcCheck(circuitJson));let checkResults=await Promise.all(checksToRun);db2.insertAll(dedupePcbDrcErrors(checkResults.flat()))},subcircuitCircuitJson=db2.subtree({subcircuit_id:this.subcircuit_id}).toArray();this._drcChecksInProgress=!0,this._queueAsyncEffect("board:drc-checks",async()=>{try{await runDrcChecks(subcircuitCircuitJson),this._drcChecksComplete=!0}finally{this._drcChecksInProgress=!1}})}runRenderPhaseForChildren(phase){this.root?.emit("board:renderPhaseStarted",{renderId:this._renderId,phase}),super.runRenderPhaseForChildren(phase)}_repositionOnPcb(position4){let{db:db2}=this.root,pcbBoard=this.pcb_board_id?db2.pcb_board.get(this.pcb_board_id):null,oldPos=pcbBoard?.center;if(!oldPos){this.pcb_board_id&&db2.pcb_board.update(this.pcb_board_id,{center:position4});return}let deltaX=position4.x-oldPos.x,deltaY=position4.y-oldPos.y;if(!(Math.abs(deltaX)<1e-6&&Math.abs(deltaY)<1e-6)&&this.pcb_board_id&&(db2.pcb_board.update(this.pcb_board_id,{center:position4}),pcbBoard?.outline)){let outlineBounds=getBoundsFromPoints2(pcbBoard.outline);if(outlineBounds){let oldOutlineCenter={x:(outlineBounds.minX+outlineBounds.maxX)/2,y:(outlineBounds.minY+outlineBounds.maxY)/2},outlineDeltaX=position4.x-oldOutlineCenter.x,outlineDeltaY=position4.y-oldOutlineCenter.y,newOutline=pcbBoard.outline.map(p3=>({x:p3.x+outlineDeltaX,y:p3.y+outlineDeltaY}));db2.pcb_board.update(this.pcb_board_id,{outline:newOutline})}}}},Subcircuit=class extends Group5{constructor(props){super({...props,subcircuit:!0})}getSubcircuitPropHash(){return Subcircuit_getSubcircuitPropHash(this)}doInitialRenderIsolatedSubcircuits(){Subcircuit_doInitialRenderIsolatedSubcircuits(this)}doInitialCreateNetsFromProps(){super.doInitialCreateNetsFromProps(),this._createTracesForExposedConnections()}_createTracesForExposedConnections(){let exposedNets=this._getNetNamesToExpose();if(!exposedNets?.length)return;let parentSubcircuit=this.parent?.getSubcircuit?.();if(parentSubcircuit&&this.name)for(let exposedNetName of exposedNets){let netName=normalizeExposedNetName(exposedNetName),parentNetSelector=`> net.${netName}`,childNetSelector=`.${this.name} > net.${netName}`;if(parentSubcircuit.children.find(child=>child instanceof Net&&child._parsedProps.name===netName)||parentSubcircuit.add(new Net({name:netName})),parentSubcircuit.children.find(child=>{if(!(child instanceof Trace)||!child._exposesSubcircuitConnection)return!1;let childProps=child._parsedProps;return childProps.from===childNetSelector&&childProps.to===parentNetSelector}))continue;let trace=new Trace({from:childNetSelector,to:parentNetSelector,displayName:netName});trace._exposesSubcircuitConnection=!0,parentSubcircuit.add(trace)}}_getNetNamesToExpose(){let explicitExposedNets=this._parsedProps.exposedNets??[];if(!this._parsedProps.exposeNets)return explicitExposedNets;let childNetNames=this.selectAll("net").filter(net=>net instanceof Net&&net.getSubcircuit()===this).map(net=>net._parsedProps.name);return Array.from(new Set([...explicitExposedNets,...childNetNames]))}doInitialInflateSubcircuitCircuitJson(){let isolatedJson=this._isolatedCircuitJson;if(isolatedJson){this._isInflatedFromCircuitJson=!0,this._isolatedCircuitJson=null,inflateCircuitJson(this,isolatedJson,[]);return}let{circuitJson,children}=this._parsedProps;circuitJson&&(this._isInflatedFromCircuitJson=!0),inflateCircuitJson(this,circuitJson,children)}},normalizeExposedNetName=netName=>netName.startsWith("net.")?netName.slice(4):netName,MountedBoard=class extends Subcircuit{constructor(){super(...arguments);__publicField(this,"pcb_board_id",null);__publicField(this,"_connectedSchematicPortPairs",new Set)}get config(){return{componentName:"MountedBoard",zodProps:mountedboardProps}}get boardThickness(){return 1.4}get allLayers(){return["top","bottom"]}_getBoardCalcVariables(){return this._findCarrierBoard()?._getBoardCalcVariables()??{}}_findCarrierBoard(){let current3=this.parent;for(;current3;){if(current3 instanceof Board)return current3;current3=current3.parent}return null}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalPcbPositionBeforeLayout(),pcb_board3=db2.pcb_board.insert({center:{x:globalPos.x,y:globalPos.y},width:props.width??0,height:props.height??0,is_mounted_to_carrier_board:!0});this.pcb_board_id=pcb_board3.pcb_board_id}doInitialPcbBoardAutoSize(){if(!this.pcb_board_id||!this.root)return;let carrierBoard=this._findCarrierBoard();carrierBoard?.pcb_board_id&&this.root.db.pcb_board.update(this.pcb_board_id,{carrier_pcb_board_id:carrierBoard.pcb_board_id})}},DEFAULT_TAB_LENGTH=5,DEFAULT_TAB_WIDTH=2,generateCutoutsAndMousebitesForOutline=(outline,options)=>{let{gapLength,cutoutWidth,mouseBites,mouseBiteHoleDiameter,mouseBiteHoleSpacing}=options,tabCutouts=[],mouseBiteHoles=[];if(outline.length<2)return{tabCutouts,mouseBiteHoles};let outlinePolygon=new Polygon$1(outline.map(p3=>point4(p3.x,p3.y))),is_ccw;if(outline.length>2){let p03=point4(outline[0].x,outline[0].y),p12=point4(outline[1].x,outline[1].y),segmentDir=vector$1(p03,p12).normalize(),normalToLeft=segmentDir.rotate(Math.PI/2),testPoint=p03.translate(segmentDir.multiply(segment(p03,p12).length/2)).translate(normalToLeft.multiply(.01));is_ccw=outlinePolygon.contains(testPoint)}else is_ccw=outlinePolygon.area()>0;for(let i6=0;i6<outline.length;i6++){let p1_=outline[i6],p2_=outline[(i6+1)%outline.length];if(!p1_||!p2_)continue;let p12=point4(p1_.x,p1_.y),p22=point4(p2_.x,p2_.y),segment2=segment(p12,p22),segmentLength=segment2.length;if(segmentLength<1e-6)continue;let segmentVec=vector$1(p12,p22),segmentDir=segmentVec.normalize(),normalVec=segmentDir.rotate(Math.PI/2),testPoint=segment2.middle().translate(normalVec.multiply(.01));outlinePolygon.contains(testPoint)&&(normalVec=normalVec.multiply(-1));let numBitesInGap=2,totalBitesLength=numBitesInGap*mouseBiteHoleDiameter+(numBitesInGap-1)*mouseBiteHoleSpacing,effectiveGapLength;mouseBites?effectiveGapLength=totalBitesLength:effectiveGapLength=gapLength,effectiveGapLength=Math.min(effectiveGapLength,segmentLength*.9);let gapStartDist=(segmentLength-effectiveGapLength)/2,gapEndDist=gapStartDist+effectiveGapLength;if(mouseBites){let holeAndSpacing=mouseBiteHoleDiameter+mouseBiteHoleSpacing;if(effectiveGapLength>=totalBitesLength&&holeAndSpacing>0){let firstBiteCenterOffsetInGap=(effectiveGapLength-totalBitesLength)/2+mouseBiteHoleDiameter/2,firstBiteDistFromP1=gapStartDist+firstBiteCenterOffsetInGap;for(let k7=0;k7<numBitesInGap;k7++){let biteDist=firstBiteDistFromP1+k7*holeAndSpacing,pos=p12.translate(segmentDir.multiply(biteDist));mouseBiteHoles.push({x:pos.x,y:pos.y})}}}let p_prev_=outline[(i6-1+outline.length)%outline.length],p_next_=outline[(i6+2)%outline.length],start_ext=0,end_ext=0;if(p_prev_&&p_next_){let vec_in_p1=vector$1(point4(p_prev_.x,p_prev_.y),p12),p1_cross=vec_in_p1.cross(segmentVec),is_p1_convex=is_ccw?p1_cross>1e-9:p1_cross<-1e-9,vec_out_p2=vector$1(p22,point4(p_next_.x,p_next_.y)),p2_cross=segmentVec.cross(vec_out_p2),is_p2_convex=is_ccw?p2_cross>1e-9:p2_cross<-1e-9;if(is_p1_convex){let angle=vec_in_p1.angleTo(segmentVec);angle>Math.PI&&(angle=2*Math.PI-angle),start_ext=cutoutWidth*Math.tan(angle/2)}else start_ext=0;if(is_p2_convex){let angle=segmentVec.angleTo(vec_out_p2);angle>Math.PI&&(angle=2*Math.PI-angle),end_ext=cutoutWidth*Math.tan(angle/2)}else end_ext=0}let cutoutParts=effectiveGapLength<1e-6?[{start:0-start_ext,end:segmentLength+end_ext}]:[{start:0-start_ext,end:gapStartDist},{start:gapEndDist,end:segmentLength+end_ext}],extrusion=normalVec.multiply(cutoutWidth);for(let part of cutoutParts){let partLength=part.end-part.start;if(partLength<1e-6)continue;let center2=p12.translate(segmentDir.multiply(part.start+partLength/2)).translate(extrusion.multiply(.5)),width=partLength,height=cutoutWidth,rotationDeg=segmentDir.slope*180/Math.PI;tabCutouts.push({type:"pcb_cutout",shape:"rect",center:{x:center2.x,y:center2.y},width,height,rotation:rotationDeg,corner_radius:cutoutWidth/2})}}return{tabCutouts,mouseBiteHoles}};function generatePanelTabsAndMouseBites(boards,options){let finalTabCutouts=[],allMouseBites=[],{tabWidth,tabLength,mouseBites:useMouseBites}=options,boardDimensions=[];for(let board of boards)if(board.width&&board.height)boardDimensions.push(Math.min(board.width,board.height));else if(board.outline&&board.outline.length>0){let outlinePolygon=new Polygon$1(board.outline.map(p3=>point4(p3.x,p3.y))),area=Math.abs(outlinePolygon.area());area>0&&boardDimensions.push(Math.sqrt(area))}if(boardDimensions.length>0){let scaleFactor=Math.min(...boardDimensions)/20;tabWidth=Math.min(tabWidth,DEFAULT_TAB_WIDTH*Math.max(scaleFactor,.3)),tabLength=Math.min(tabLength,DEFAULT_TAB_LENGTH*Math.max(scaleFactor,.3))}let processedBoards=boards.map(board=>{if((!board.outline||board.outline.length===0)&&board.width&&board.height){let w22=board.width/2,h22=board.height/2;return{...board,outline:[{x:board.center.x-w22,y:board.center.y-h22},{x:board.center.x+w22,y:board.center.y-h22},{x:board.center.x+w22,y:board.center.y+h22},{x:board.center.x-w22,y:board.center.y+h22}]}}return board});for(let board of processedBoards)if(board.outline&&board.outline.length>0){let mouseBiteDiameter2=tabWidth*.45,mouseBiteSpacing=mouseBiteDiameter2*.1,generated=generateCutoutsAndMousebitesForOutline(board.outline,{gapLength:tabLength,cutoutWidth:tabWidth,mouseBites:useMouseBites,mouseBiteHoleDiameter:mouseBiteDiameter2,mouseBiteHoleSpacing:mouseBiteSpacing});finalTabCutouts.push(...generated.tabCutouts),allMouseBites.push(...generated.mouseBiteHoles)}let tabCutouts=finalTabCutouts.map((tab,index)=>({...tab,pcb_cutout_id:`panel_tab_${index}`})),mouseBiteDiameter=tabWidth*.45,mouseBiteHoles=allMouseBites.map((bite,index)=>({type:"pcb_hole",pcb_hole_id:`panel_mouse_bite_${index}`,hole_shape:"circle",hole_diameter:mouseBiteDiameter,x:bite.x,y:bite.y}));return{tabCutouts,mouseBiteHoles}}function generatePanelOutlineRoutingCutouts(boards,options){return boards.map(board=>{if((!board.outline||board.outline.length===0)&&board.width&&board.height){let halfWidth=board.width/2,halfHeight=board.height/2;return{...board,outline:[{x:board.center.x-halfWidth,y:board.center.y-halfHeight},{x:board.center.x+halfWidth,y:board.center.y-halfHeight},{x:board.center.x+halfWidth,y:board.center.y+halfHeight},{x:board.center.x-halfWidth,y:board.center.y+halfHeight}]}}return board}).flatMap(board=>{if(!board.outline||board.outline.length===0)return[];let{tabCutouts}=generateCutoutsAndMousebitesForOutline(board.outline,{gapLength:0,cutoutWidth:options.cutoutWidth,mouseBites:!1,mouseBiteHoleDiameter:0,mouseBiteHoleSpacing:0});return tabCutouts.map(cutout=>({...cutout,pcb_board_id:board.pcb_board_id}))}).map((cutout,outlineRoutingCutoutIndex)=>({...cutout,pcb_cutout_id:`panel_outline_routing_cutout_${outlineRoutingCutoutIndex}`}))}var getBoardDimensionsFromProps=board=>{let props=board._parsedProps,width=props.width!=null?distance.parse(props.width):void 0,height=props.height!=null?distance.parse(props.height):void 0;if((width===void 0||height===void 0)&&props.outline?.length){let outlineBounds=getBoundsFromPoints2(props.outline);outlineBounds&&(width??(width=outlineBounds.maxX-outlineBounds.minX),height??(height=outlineBounds.maxY-outlineBounds.minY))}if((width===void 0||height===void 0)&&props.circuitJson?.length){let pcbBoardFromJson=props.circuitJson.find(elm=>elm.type==="pcb_board");pcbBoardFromJson&&(width??(width=pcbBoardFromJson.width),height??(height=pcbBoardFromJson.height))}return{width:width??0,height:height??0}};function packIntoGrid({items,db:db2,row,col,cellWidth,cellHeight,boardGap,availablePanelWidth,availablePanelHeight}){let itemsWithDims=items.map(item=>{let dims=getItemDimensions(item,db2);return{item,width:dims.width,height:dims.height}}).filter(item=>!(item.width===0&&item.height===0));if(itemsWithDims.length===0)return{positions:[],gridWidth:0,gridHeight:0};let cols,rows,minCellWidth=cellWidth?distance.parse(cellWidth):0,minCellHeight=cellHeight?distance.parse(cellHeight):0;if(col!==void 0)cols=col,rows=row??Math.ceil(itemsWithDims.length/cols);else if(row!==void 0)rows=row,cols=Math.ceil(itemsWithDims.length/rows);else if(availablePanelWidth!==void 0&&availablePanelHeight!==void 0){let maxItemWidth=Math.max(...itemsWithDims.map(b6=>b6.width),minCellWidth),maxItemHeight=Math.max(...itemsWithDims.map(b6=>b6.height),minCellHeight),maxCols=Math.max(1,Math.floor((availablePanelWidth+boardGap)/(maxItemWidth+boardGap))),maxRows=Math.max(1,Math.floor((availablePanelHeight+boardGap)/(maxItemHeight+boardGap)));cols=maxCols,rows=Math.ceil(itemsWithDims.length/cols),rows>maxRows&&(rows=maxRows,cols=Math.ceil(itemsWithDims.length/rows),cols>maxCols&&(cols=maxCols,rows=Math.ceil(itemsWithDims.length/cols))),cols=Math.max(1,cols),rows=Math.max(1,rows)}else cols=Math.ceil(Math.sqrt(itemsWithDims.length)),rows=Math.ceil(itemsWithDims.length/cols);let colWidths=Array(cols).fill(0),rowHeights=Array(rows).fill(0);itemsWithDims.forEach((item,i6)=>{let colIdx=i6%cols,rowIdx=Math.floor(i6/cols);rowIdx<rowHeights.length&&item.height>rowHeights[rowIdx]&&(rowHeights[rowIdx]=item.height),colIdx<colWidths.length&&item.width>colWidths[colIdx]&&(colWidths[colIdx]=item.width)});for(let i6=0;i6<colWidths.length;i6++)colWidths[i6]=Math.max(colWidths[i6],minCellWidth);for(let i6=0;i6<rowHeights.length;i6++)rowHeights[i6]=Math.max(rowHeights[i6],minCellHeight);let gridWidth=colWidths.reduce((a6,b6)=>a6+b6,0)+(cols>1?(cols-1)*boardGap:0),gridHeight=rowHeights.reduce((a6,b6)=>a6+b6,0)+(rows>1?(rows-1)*boardGap:0),startX=-gridWidth/2,startY=-gridHeight/2,colXOffsets=[startX];for(let i6=1;i6<cols;i6++)colXOffsets.push(colXOffsets[i6-1]+colWidths[i6-1]+boardGap);let rowYOffsets=[startY];for(let i6=1;i6<rows;i6++)rowYOffsets.push(rowYOffsets[i6-1]+rowHeights[i6-1]+boardGap);let positions=[];return itemsWithDims.forEach((itemWithDims,i6)=>{let colIdx=i6%cols,rowIdx=Math.floor(i6/cols);if(rowIdx>=rowYOffsets.length||colIdx>=colXOffsets.length)return;let x6=colXOffsets[colIdx]+colWidths[colIdx]/2,y2=rowYOffsets[rowIdx]+rowHeights[rowIdx]/2;positions.push({item:itemWithDims.item,pos:{x:x6,y:y2}})}),{positions,gridWidth,gridHeight}}function getItemDimensions(item,db2){if(item.componentName==="Board"){let board=item;if(db2&&board.pcb_board_id){let pcbBoard=db2.pcb_board.get(board.pcb_board_id);if(pcbBoard?.width!==void 0&&pcbBoard?.height!==void 0)return{width:pcbBoard.width,height:pcbBoard.height}}return getBoardDimensionsFromProps(board)}if(item.componentName==="Subpanel"){let subpanel=item,props=subpanel._parsedProps;if(props.width!==void 0&&props.height!==void 0)return{width:distance.parse(props.width),height:distance.parse(props.height)};let directBoards=subpanel._getDirectBoardChildren();if(directBoards.length===0){let allBoards=subpanel._getAllBoardInstances();if(allBoards.length===0)return{width:0,height:0};let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let board of allBoards){let dims=getBoardDimensionsFromProps(board);if(dims.width===0||dims.height===0)continue;let offset=board._panelPositionOffset??{x:0,y:0};minX=Math.min(minX,offset.x-dims.width/2),maxX=Math.max(maxX,offset.x+dims.width/2),minY=Math.min(minY,offset.y-dims.height/2),maxY=Math.max(maxY,offset.y+dims.height/2)}return minX===1/0?{width:0,height:0}:{width:maxX-minX,height:maxY-minY}}if(directBoards.length===1)return getBoardDimensionsFromProps(directBoards[0]);if(subpanel._cachedGridWidth>0&&subpanel._cachedGridHeight>0){let edgePadding=distance.parse(props.edgePadding??5);return{width:subpanel._cachedGridWidth+edgePadding*2,height:subpanel._cachedGridHeight+edgePadding*2}}let totalWidth=0,totalHeight=0;for(let board of directBoards){let dims=getBoardDimensionsFromProps(board);totalWidth=Math.max(totalWidth,dims.width),totalHeight=Math.max(totalHeight,dims.height)}return{width:totalWidth,height:totalHeight}}return{width:0,height:0}}var Subpanel=class _Subpanel extends Group5{constructor(){super(...arguments);__publicField(this,"pcb_panel_id",null);__publicField(this,"_panelizationFeaturesGenerated",!1);__publicField(this,"_cachedGridWidth",0);__publicField(this,"_cachedGridHeight",0);__publicField(this,"_panelPositionOffset",null)}get config(){return{componentName:"Subpanel",zodProps:subpanelProps}}get _errorComponentName(){return this.componentName.toLowerCase()}get isGroup(){return!0}get isSubcircuit(){return!0}_getPcbLayoutMode(){return"none"}doInitialSchematicComponentRender(){}doInitialSchematicLayout(){}doInitialSchematicTraceRender(){}add(component){if(component.lowercaseComponentName!=="board"&&component.lowercaseComponentName!=="subpanel")throw new Error(`<${this._errorComponentName}> can only contain <board> or <subpanel> elements`);super.add(component)}_computePcbGlobalTransformBeforeLayout(){if(this._panelPositionOffset){let parentTransform=this.parent?._computePcbGlobalTransformBeforeLayout?.()??identity();return compose2(parentTransform,translate2(this._panelPositionOffset.x,this._panelPositionOffset.y))}return super._computePcbGlobalTransformBeforeLayout()}_getAllBoardInstances(){let boards=[];for(let child of this.children)child instanceof Board?boards.push(child):child instanceof _Subpanel&&boards.push(...child._getAllBoardInstances());return boards}_containsBoards(){for(let child of this.children)if(child.componentName==="Board"||child.componentName==="Subpanel"&&"_containsBoards"in child&&child._containsBoards())return!0;return!1}_getDirectBoardChildren(){return this.children.filter(c3=>c3 instanceof Board)}doInitialPanelBoardLayout(){if(this.root?.pcbDisabled)return;let layoutMode=this._parsedProps.layoutMode??"none",gridItems=this.children.filter(c3=>c3 instanceof Board||c3 instanceof _Subpanel);if(layoutMode!=="none")for(let child of gridItems)child instanceof Board&&child._hasUserDefinedPcbPosition()&&this.root.db.source_property_ignored_warning.insert({source_component_id:child.source_component_id,property_name:"pcbX/pcbY",message:`Board has manual positioning but ${this._errorComponentName} layout mode is "${layoutMode}". Manual positioning will be ignored.`,error_type:"source_property_ignored_warning"});if(layoutMode==="none"&&gridItems.length>1&&gridItems.filter(c3=>!c3._hasUserDefinedPcbPosition()).length>1&&this.root.db.pcb_placement_error.insert({error_type:"pcb_placement_error",message:`Multiple boards/subpanels in ${this._errorComponentName} without positions. When layoutMode="none", each item must have explicit positioning. Use layoutMode="grid" for automatic positioning.`}),layoutMode!=="grid")return;let tabWidth=this._parsedProps.tabWidth??DEFAULT_TAB_WIDTH,boardGap=this._parsedProps.boardGap??tabWidth,availablePanelWidth,availablePanelHeight,hasExplicitRowOrCol=this._parsedProps.row!==void 0||this._parsedProps.col!==void 0,hasExplicitWidth=this._parsedProps.width!==void 0,hasExplicitHeight=this._parsedProps.height!==void 0;if(!hasExplicitRowOrCol&&hasExplicitWidth&&hasExplicitHeight){let{edgePadding:edgePaddingProp,edgePaddingLeft:edgePaddingLeftProp,edgePaddingRight:edgePaddingRightProp,edgePaddingTop:edgePaddingTopProp,edgePaddingBottom:edgePaddingBottomProp}=this._parsedProps,edgePadding=distance.parse(edgePaddingProp??5),edgePaddingLeft=distance.parse(edgePaddingLeftProp??edgePadding),edgePaddingRight=distance.parse(edgePaddingRightProp??edgePadding),edgePaddingTop=distance.parse(edgePaddingTopProp??edgePadding),edgePaddingBottom=distance.parse(edgePaddingBottomProp??edgePadding),panelWidth=distance.parse(this._parsedProps.width),panelHeight=distance.parse(this._parsedProps.height);availablePanelWidth=panelWidth-edgePaddingLeft-edgePaddingRight,availablePanelHeight=panelHeight-edgePaddingTop-edgePaddingBottom}let{positions,gridWidth,gridHeight}=packIntoGrid({items:gridItems,row:this._parsedProps.row,col:this._parsedProps.col,cellWidth:this._parsedProps.cellWidth,cellHeight:this._parsedProps.cellHeight,boardGap,availablePanelHeight,availablePanelWidth});this._cachedGridWidth=gridWidth,this._cachedGridHeight=gridHeight;for(let{item,pos}of positions)item._panelPositionOffset=pos}doInitialPanelLayout(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root;if((this._parsedProps.layoutMode??"none")==="grid"){for(let child of this.children)if(child instanceof Board){if(!child.pcb_board_id||!child._panelPositionOffset)continue;db2.pcb_board.update(child.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${child._panelPositionOffset.x}mm`,display_offset_y:`${child._panelPositionOffset.y}mm`})}else if(child instanceof _Subpanel&&child._panelPositionOffset)for(let board of child._getAllBoardInstances()){if(!board.pcb_board_id)continue;let boardOffset=board._panelPositionOffset??{x:0,y:0};db2.pcb_board.update(board.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${child._panelPositionOffset.x+boardOffset.x}mm`,display_offset_y:`${child._panelPositionOffset.y+boardOffset.y}mm`})}this._updatePanelDimensions()}else{let panelGlobalPos=this._getGlobalPcbPositionBeforeLayout();for(let board of this._getDirectBoardChildren()){if(!board.pcb_board_id)continue;let boardDb=db2.pcb_board.get(board.pcb_board_id);if(!boardDb)continue;let relativeX=boardDb.center.x-panelGlobalPos.x,relativeY=boardDb.center.y-panelGlobalPos.y;db2.pcb_board.update(board.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${relativeX}mm`,display_offset_y:`${relativeY}mm`})}}this._generatePanelizationFeatures()}_updatePanelDimensions(){let{db:db2}=this.root,hasExplicitWidth=this._parsedProps.width!==void 0,hasExplicitHeight=this._parsedProps.height!==void 0,gridWidth=this._cachedGridWidth,gridHeight=this._cachedGridHeight;if(this.pcb_group_id){if(hasExplicitWidth&&hasExplicitHeight)db2.pcb_group.update(this.pcb_group_id,{width:distance.parse(this._parsedProps.width),height:distance.parse(this._parsedProps.height)});else if(gridWidth>0||gridHeight>0){let{edgePadding:edgePaddingProp,edgePaddingLeft:edgePaddingLeftProp,edgePaddingRight:edgePaddingRightProp,edgePaddingTop:edgePaddingTopProp,edgePaddingBottom:edgePaddingBottomProp}=this._parsedProps,edgePadding=distance.parse(edgePaddingProp??5),edgePaddingLeft=distance.parse(edgePaddingLeftProp??edgePadding),edgePaddingRight=distance.parse(edgePaddingRightProp??edgePadding),edgePaddingTop=distance.parse(edgePaddingTopProp??edgePadding),edgePaddingBottom=distance.parse(edgePaddingBottomProp??edgePadding);db2.pcb_group.update(this.pcb_group_id,{width:hasExplicitWidth?distance.parse(this._parsedProps.width):gridWidth+edgePaddingLeft+edgePaddingRight,height:hasExplicitHeight?distance.parse(this._parsedProps.height):gridHeight+edgePaddingTop+edgePaddingBottom})}}}_generatePanelizationFeatures(){if(this._panelizationFeaturesGenerated)return;let{db:db2}=this.root,props=this._parsedProps,panelizationMethod=props.panelizationMethod??"none",childBoardInstances=this._getAllBoardInstances();if(panelizationMethod!=="none"){let childBoardIds=childBoardInstances.map(c3=>c3.pcb_board_id).filter(id3=>!!id3),boardsInPanel=db2.pcb_board.list().filter(b6=>childBoardIds.includes(b6.pcb_board_id));if(boardsInPanel.length===0)return;let tabWidth=props.tabWidth??DEFAULT_TAB_WIDTH;if(panelizationMethod==="outline_routing"){let outlineRoutingCutouts=generatePanelOutlineRoutingCutouts(boardsInPanel,{cutoutWidth:tabWidth});for(let outlineRoutingCutout of outlineRoutingCutouts)db2.pcb_cutout.insert({...outlineRoutingCutout,pcb_group_id:this.pcb_group_id??void 0,pcb_panel_id:this.pcb_panel_id??void 0})}else{let boardGap=props.boardGap??tabWidth,{tabCutouts,mouseBiteHoles}=generatePanelTabsAndMouseBites(boardsInPanel,{boardGap,tabWidth,tabLength:props.tabLength??DEFAULT_TAB_LENGTH,mouseBites:props.mouseBites??!0});for(let tabCutout of tabCutouts)db2.pcb_cutout.insert(tabCutout);for(let mouseBiteHole of mouseBiteHoles)db2.pcb_hole.insert(mouseBiteHole)}}this._panelizationFeaturesGenerated=!0}doInitialPcbComponentRender(){if(!this.root?.pcbDisabled){if(!this._containsBoards())throw new Error(`<${this._errorComponentName}> must contain at least one <board>`);super.doInitialPcbComponentRender()}}},Panel=class extends Subpanel{get config(){return{componentName:"Panel",zodProps:panelProps}}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;if(!this._containsBoards())throw new Error(`<${this._errorComponentName}> must contain at least one <board>`);let{db:db2}=this.root,props=this._parsedProps,inserted=db2.pcb_panel.insert({width:props.width!==void 0?distance.parse(props.width):0,height:props.height!==void 0?distance.parse(props.height):0,thickness:1.6,center:this._getGlobalPcbPositionBeforeLayout(),covered_with_solder_mask:!(props.noSolderMask??!1)});this.pcb_panel_id=inserted.pcb_panel_id}_updatePanelDimensions(){let{db:db2}=this.root,hasExplicitWidth=this._parsedProps.width!==void 0,hasExplicitHeight=this._parsedProps.height!==void 0,gridWidth=this._cachedGridWidth,gridHeight=this._cachedGridHeight;if(this.pcb_panel_id){if(hasExplicitWidth&&hasExplicitHeight)db2.pcb_panel.update(this.pcb_panel_id,{width:distance.parse(this._parsedProps.width),height:distance.parse(this._parsedProps.height)});else if(gridWidth>0||gridHeight>0){let{edgePadding:edgePaddingProp,edgePaddingLeft:edgePaddingLeftProp,edgePaddingRight:edgePaddingRightProp,edgePaddingTop:edgePaddingTopProp,edgePaddingBottom:edgePaddingBottomProp}=this._parsedProps,edgePadding=distance.parse(edgePaddingProp??5),edgePaddingLeft=distance.parse(edgePaddingLeftProp??edgePadding),edgePaddingRight=distance.parse(edgePaddingRightProp??edgePadding),edgePaddingTop=distance.parse(edgePaddingTopProp??edgePadding),edgePaddingBottom=distance.parse(edgePaddingBottomProp??edgePadding);db2.pcb_panel.update(this.pcb_panel_id,{width:hasExplicitWidth?distance.parse(this._parsedProps.width):gridWidth+edgePaddingLeft+edgePaddingRight,height:hasExplicitHeight?distance.parse(this._parsedProps.height):gridHeight+edgePaddingTop+edgePaddingBottom})}}}updatePcbComponentRender(){if(this.root?.pcbDisabled||!this.pcb_panel_id)return;let{db:db2}=this.root,props=this._parsedProps,currentPanel=db2.pcb_panel.get(this.pcb_panel_id);db2.pcb_panel.update(this.pcb_panel_id,{width:props.width!==void 0?distance.parse(props.width):currentPanel?.width,height:props.height!==void 0?distance.parse(props.height):currentPanel?.height,center:this._getGlobalPcbPositionBeforeLayout(),covered_with_solder_mask:!(props.noSolderMask??!1)})}removePcbComponentRender(){this.pcb_panel_id&&(this.root?.db.pcb_panel.delete(this.pcb_panel_id),this.pcb_panel_id=null)}},Pinout=class extends Chip{constructor(props){super(props)}get config(){return{...super.config,componentName:"Pinout",zodProps:pinoutProps}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_pinout",name:this.name,manufacturer_part_number:props.manufacturerPartNumber,supplier_part_numbers:props.supplierPartNumbers,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},Fuse=class extends NormalComponent3{get config(){return{componentName:"fuse",schematicSymbolName:this.props.symbolName??"fuse",zodProps:fuseProps,sourceFtype:FTYPE.simple_fuse}}_getSchematicSymbolDisplayValue(){if(this._parsedProps.schShowRatings===!1)return"";let rawCurrent=this._parsedProps.currentRating,rawVoltage=this._parsedProps.voltageRating,current3=parseAndConvertSiUnit(rawCurrent,"A").value,voltage3=parseAndConvertSiUnit(rawVoltage,"V").value;return`${formatSiUnit(current3)}A / ${formatSiUnit(voltage3)}V`}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,currentRating=parseAndConvertSiUnit(props.currentRating,"A").value,voltageRating=parseAndConvertSiUnit(props.voltageRating,"V").value,display_current_rating,display_voltage_rating;props.schShowRatings!==!1&&(display_current_rating=`${formatSiUnit(currentRating)}A`,display_voltage_rating=`${formatSiUnit(voltageRating)}V`);let source_component=db2.source_component.insert({name:this.name,ftype:FTYPE.simple_fuse,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,...currentRating!=null?{current_rating_amps:currentRating}:{},...voltageRating!=null?{voltage_rating_volts:voltageRating}:{},display_current_rating,display_voltage_rating,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},Jumper=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"schematicDimensions",null)}get config(){return{schematicSymbolName:void 0,componentName:"Jumper",zodProps:jumperProps,shouldRenderAsSchematicBox:!0}}_getSchematicPortArrangement(){let arrangement=super._getSchematicPortArrangement();if(arrangement&&Object.keys(arrangement).length>0)return arrangement;let pinCount=this._parsedProps.pinCount??(Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels.length:this._parsedProps.pinLabels?Object.keys(this._parsedProps.pinLabels).length:this.getPortsFromFootprint().length),direction2=this._parsedProps.schDirection??"right";return{leftSize:direction2==="left"?pinCount:0,rightSize:direction2==="right"?pinCount:0}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db2.source_component.insert({ftype:"simple_chip",name:this.name,manufacturer_part_number:props.manufacturerPartNumber,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),globalTransformRotation=this.getGlobalTransformRotation(),pcb_component3=db2.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:props.layer??"top",rotation:normalizeDegrees(globalTransformRotation),insertion_direction:this._getPcbComponentInsertionDirection(props.layer??"top",globalTransformRotation),source_component_id:this.source_component_id,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0,do_not_place:props.doNotPlace??!1,obstructs_within_bounds:props.obstructsWithinBounds??!0,is_allowed_to_be_off_board:props.allowOffBoard??!1,metadata:props.kicadFootprintMetadata?{kicad_footprint:props.kicadFootprintMetadata}:void 0});this.pcb_component_id=pcb_component3.pcb_component_id}doInitialPcbPortAttachment(){let{db:db2}=this.root,pcb_ports=db2.pcb_port.list({pcb_component_id:this.pcb_component_id}),pinLabelToPortId={};for(let i6=0;i6<pcb_ports.length;i6++){let port=pcb_ports[i6],sourcePort=db2.source_port.get(port.source_port_id),pinLabel="";if(typeof sourcePort?.pin_number=="number")pinLabel=sourcePort.pin_number.toString();else if(Array.isArray(sourcePort?.port_hints)){let matchedHint=sourcePort.port_hints.find(h3=>/^(pin)?\d+$/.test(h3));matchedHint&&(/^pin\d+$/.test(matchedHint)?pinLabel=matchedHint.replace(/^pin/,""):pinLabel=matchedHint)}pinLabelToPortId[pinLabel]=port.pcb_port_id}let traces=db2.pcb_trace.list({pcb_component_id:this.pcb_component_id}),updatePortId=portId=>{if(portId&&typeof portId=="string"&&portId.startsWith("{PIN")){let pin=portId.replace("{PIN","").replace("}","");return pinLabelToPortId[pin]||portId}return portId};for(let trace of traces)if(trace.route)for(let segment2 of trace.route)segment2.route_type==="wire"&&(segment2.start_pcb_port_id=updatePortId(segment2.start_pcb_port_id),segment2.end_pcb_port_id=updatePortId(segment2.end_pcb_port_id))}},INTERCONNECT_STANDARD_FOOTPRINTS={"0402":"0402","0603":"0603","0805":"0805",1206:"1206"},Interconnect=class extends NormalComponent3{get config(){return{componentName:"Interconnect",zodProps:interconnectProps,shouldRenderAsSchematicBox:!0,sourceFtype:"interconnect"}}get defaultInternallyConnectedPinNames(){let{standard}=this._parsedProps;return standard&&INTERCONNECT_STANDARD_FOOTPRINTS[standard]?[["pin1","pin2"]]:[]}_getImpliedFootprintString(){let{standard}=this._parsedProps;return standard?INTERCONNECT_STANDARD_FOOTPRINTS[standard]??null:null}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"interconnect",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSourceParentAttachment(){let{db:db2}=this.root,internallyConnectedPorts=this._getInternallyConnectedPins();for(let ports of internallyConnectedPorts){let sourcePortIds=ports.map(port=>port.source_port_id).filter(id3=>id3!==null);sourcePortIds.length>=2&&db2.source_component_internal_connection.insert({source_component_id:this.source_component_id,subcircuit_id:this.getSubcircuit()?.subcircuit_id,source_port_ids:sourcePortIds})}}},SolderJumper=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"schematicDimensions",null)}_getPinCountFromFootprintString(footprint){let match2=footprint.match(/^solderjumper([23])(?:_|$)/);return match2?Number(match2[1]):null}_getPinNumberFromBridgedPinsProp(pinName){let numericPinMatch=pinName.match(/^(?:pin)?(\d+)$/i);if(numericPinMatch)return Number(numericPinMatch[1]);let pinLabels=this._parsedProps.pinLabels??this.props.pinLabels;if(Array.isArray(pinLabels)){let labelIndex=pinLabels.findIndex(label=>label===pinName);return labelIndex>=0?labelIndex+1:null}if(pinLabels&&typeof pinLabels=="object")for(let[pinKey,labelOrLabels]of Object.entries(pinLabels)){if(!(Array.isArray(labelOrLabels)?labelOrLabels:[labelOrLabels]).includes(pinName))continue;let pinNumberMatch=pinKey.match(/^(?:pin)?(\d+)$/i);return pinNumberMatch?Number(pinNumberMatch[1]):null}return null}_getBridgedPinNumbersForFootprint(pinCount){let props=this._parsedProps??this.props;return Array.isArray(props.bridgedPins)&&props.bridgedPins.length>0?Array.from(new Set(props.bridgedPins.flat().map(pinName=>this._getPinNumberFromBridgedPinsProp(pinName)).filter(pinNumber=>pinNumber!==null&&pinNumber>=1&&pinNumber<=pinCount))).sort((a6,b6)=>a6-b6):props.bridged?Array.from({length:pinCount},(_6,index)=>index+1):[]}resolveFootprint(){let footprint=super.resolveFootprint();if(typeof footprint!="string")return footprint;let pinCount=this._getPinCountFromFootprintString(footprint);if(!pinCount||/_bridged\d+/.test(footprint))return footprint;let bridgedPinNumbers=this._getBridgedPinNumbersForFootprint(pinCount);return bridgedPinNumbers.length===0?footprint:footprint.replace(/^solderjumper[23]/,`solderjumper${pinCount}_bridged${bridgedPinNumbers.join("")}`)}_getPinNumberFromBridgedPinName(pinName){return this.selectOne(`port.${pinName}`,{type:"port"})?._parsedProps.pinNumber??null}get defaultInternallyConnectedPinNames(){if(this._parsedProps.bridged){let pins=this.children.filter(c3=>c3.componentName==="Port").map(p3=>p3.name);return pins.length>0?[pins]:[]}return this._parsedProps.bridgedPins??[]}get config(){let props=this._parsedProps??this.props,resolvedPinCount=props.pinCount;if(props.pinCount==null&&!props.footprint&&(resolvedPinCount=2),props.pinCount==null){let nums=(props.bridgedPins??[]).flat().map(p_str=>this._getPinNumberFromBridgedPinName(p_str)).filter(n3=>n3!==null),maxPinFromBridged=nums.length>0?Math.max(...nums):0,pinCountFromLabels=props.pinLabels?Object.keys(props.pinLabels).length:0,finalPinCount=Math.max(maxPinFromBridged,pinCountFromLabels);(finalPinCount===2||finalPinCount===3)&&(resolvedPinCount=finalPinCount),resolvedPinCount==null&&props.footprint&&[2,3].includes(this.getPortsFromFootprint().length)&&(resolvedPinCount=this.getPortsFromFootprint().length)}let symbolName="";resolvedPinCount?symbolName+=`solderjumper${resolvedPinCount}`:symbolName="solderjumper";let bridgedPinNumbers=[];return Array.isArray(props.bridgedPins)&&props.bridgedPins.length>0?bridgedPinNumbers=Array.from(new Set(props.bridgedPins.flat().map(pinName=>this._getPinNumberFromBridgedPinName(pinName)).filter(n3=>n3!==null))).sort((a6,b6)=>a6-b6):props.bridged&&resolvedPinCount&&(bridgedPinNumbers=Array.from({length:resolvedPinCount},(_6,i6)=>i6+1)),bridgedPinNumbers.length>0&&(symbolName+=`_bridged${bridgedPinNumbers.join("")}`),{schematicSymbolName:props.symbolName??symbolName,componentName:"SolderJumper",zodProps:solderjumperProps,shouldRenderAsSchematicBox:!0}}_getSchematicPortArrangement(){let arrangement=super._getSchematicPortArrangement();if(arrangement&&Object.keys(arrangement).length>0)return arrangement;let pinCount=this._parsedProps.pinCount??(Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels.length:this._parsedProps.pinLabels?Object.keys(this._parsedProps.pinLabels).length:this.getPortsFromFootprint().length);pinCount==null&&!this._parsedProps.footprint&&(pinCount=2);let direction2=this._parsedProps.schDirection??"right";return{leftSize:direction2==="left"?pinCount:0,rightSize:direction2==="right"?pinCount:0}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db2.source_component.insert({ftype:"simple_chip",name:this.name,manufacturer_part_number:props.manufacturerPartNumber,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),globalTransformRotation=this.getGlobalTransformRotation(),pcb_component3=db2.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:props.layer??"top",rotation:normalizeDegrees(globalTransformRotation),insertion_direction:this._getPcbComponentInsertionDirection(props.layer??"top",globalTransformRotation),source_component_id:this.source_component_id,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0,do_not_place:props.doNotPlace??!1,obstructs_within_bounds:props.obstructsWithinBounds??!0,is_allowed_to_be_off_board:props.allowOffBoard??!1,metadata:props.kicadFootprintMetadata?{kicad_footprint:props.kicadFootprintMetadata}:void 0});this.pcb_component_id=pcb_component3.pcb_component_id}doInitialPcbPortAttachment(){let{db:db2}=this.root,pcb_ports=db2.pcb_port.list({pcb_component_id:this.pcb_component_id}),pinLabelToPortId={};for(let i6=0;i6<pcb_ports.length;i6++){let port=pcb_ports[i6],sourcePort=db2.source_port.get(port.source_port_id),pinLabel="";if(typeof sourcePort?.pin_number=="number")pinLabel=sourcePort.pin_number.toString();else if(Array.isArray(sourcePort?.port_hints)){let matchedHint=sourcePort.port_hints.find(h3=>/^(pin)?\d+$/.test(h3));matchedHint&&(/^pin\d+$/.test(matchedHint)?pinLabel=matchedHint.replace(/^pin/,""):pinLabel=matchedHint)}pinLabelToPortId[pinLabel]=port.pcb_port_id}let traces=db2.pcb_trace.list({pcb_component_id:this.pcb_component_id}),updatePortId=portId=>{if(portId&&typeof portId=="string"&&portId.startsWith("{PIN")){let pin=portId.replace("{PIN","").replace("}","");return pinLabelToPortId[pin]||portId}return portId};for(let trace of traces)if(trace.route)for(let segment2 of trace.route)segment2.route_type==="wire"&&(segment2.start_pcb_port_id=updatePortId(segment2.start_pcb_port_id),segment2.end_pcb_port_id=updatePortId(segment2.end_pcb_port_id))}},PowerSource=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"pos",this.portMap.pin1);__publicField(this,"positive",this.portMap.pin1);__publicField(this,"neg",this.portMap.pin2);__publicField(this,"negative",this.portMap.pin2)}get config(){return{schematicSymbolName:this.props.symbolName??"power_factor_meter_horz",componentName:"PowerSource",zodProps:powerSourceProps,sourceFtype:"simple_power_source"}}initPorts(){this.add(new Port({name:"pin1",pinNumber:1,aliases:["positive","pos"]})),this.add(new Port({name:"pin2",pinNumber:2,aliases:["negative","neg"]}))}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_power_source",name:this.name,voltage:props.voltage,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!1,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},VoltageSource2=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"simulation_voltage_source_id",null);__publicField(this,"terminal1",this.portMap.terminal1);__publicField(this,"terminal2",this.portMap.terminal2)}get config(){return{componentName:"VoltageSource",schematicSymbolName:this.props.waveShape==="square"?"square_wave":"ac_voltmeter",zodProps:voltageSourceProps,sourceFtype:"simple_voltage_source"}}runRenderPhaseForChildren(phase){if(!phase.startsWith("Pcb"))for(let child of this.children)child.runRenderPhaseForChildren(phase),child.runRenderPhase(phase)}doInitialPcbComponentRender(){let hasExplicitPcbPosition=this._hasUserDefinedPcbPosition();if(!this._parsedProps.footprint){if(!hasExplicitPcbPosition)return;throw new Error("VoltageSource requires a footprint when pcbX/pcbY or pcb edge position props are used")}super.doInitialPcbComponentRender()}initPorts(){super.initPorts({additionalAliases:{pin1:["terminal1"],pin2:["terminal2"]}})}_getSchematicSymbolDisplayValue(){let{voltage:voltage3,frequency:frequency22}=this._parsedProps,parts=[];return voltage3!==void 0&&parts.push(`${formatSiUnit(voltage3)}V`),frequency22!==void 0&&parts.push(`${formatSiUnit(frequency22)}Hz`),parts.length>0?parts.join(" "):void 0}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_voltage_source",name:this.name,voltage:props.voltage,frequency:props.frequency,peak_to_peak_voltage:props.peakToPeakVoltage,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle,pulse_delay:props.pulseDelay,rise_time:props.riseTime,fall_time:props.fallTime,pulse_width:props.pulseWidth,period:props.period,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db:db2}=this.root,{_parsedProps:props}=this,terminal1Port=this.portMap.terminal1,terminal2Port=this.portMap.terminal2,simulationVoltageSource=db2.simulation_voltage_source.insert({is_dc_source:!1,terminal1_source_port_id:terminal1Port.source_port_id??void 0,terminal2_source_port_id:terminal2Port.source_port_id??void 0,voltage:props.voltage,frequency:props.frequency,peak_to_peak_voltage:props.peakToPeakVoltage,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle,pulse_delay:props.pulseDelay,rise_time:props.riseTime,fall_time:props.fallTime,pulse_width:props.pulseWidth,period:props.period,ac_magnitude:props.acMagnitude,ac_phase:props.acPhase});this.simulation_voltage_source_id=simulationVoltageSource.simulation_voltage_source_id}},CurrentSource2=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"simulation_current_source_id",null);__publicField(this,"pos",this.portMap.pos);__publicField(this,"neg",this.portMap.neg)}get config(){return{componentName:"CurrentSource",schematicSymbolName:"current_source",zodProps:currentSourceProps,sourceFtype:"simple_current_source"}}runRenderPhaseForChildren(phase){if(!phase.startsWith("Pcb"))for(let child of this.children)child.runRenderPhaseForChildren(phase),child.runRenderPhase(phase)}doInitialPcbComponentRender(){let hasExplicitPcbPosition=this._hasUserDefinedPcbPosition();if(!this._parsedProps.footprint){if(!hasExplicitPcbPosition)return;throw new Error("CurrentSource requires a footprint when pcbX/pcbY or pcb edge position props are used")}super.doInitialPcbComponentRender()}initPorts(){super.initPorts({additionalAliases:{pin1:["pos"],pin2:["neg"]}})}_getSchematicSymbolDisplayValue(){let{current:current3,frequency:frequency22,peakToPeakCurrent}=this._parsedProps,parts=[];return current3!==void 0&&parts.push(`${formatSiUnit(current3)}A`),peakToPeakCurrent!==void 0&&parts.push(`${formatSiUnit(peakToPeakCurrent)}A p-p`),frequency22!==void 0&&parts.push(`${formatSiUnit(frequency22)}Hz`),parts.length>0?parts.join(" "):void 0}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_current_source",name:this.name,current:props.current,frequency:props.frequency,peak_to_peak_current:props.peakToPeakCurrent,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db:db2}=this.root,{_parsedProps:props}=this,isAc=props.frequency!==void 0||props.peakToPeakCurrent!==void 0||props.waveShape!==void 0||props.acMagnitude!==void 0||props.acPhase!==void 0,posPort=this.portMap.pos,negPort=this.portMap.neg;if(isAc){let simulationCurrentSource=db2.simulation_current_source.insert({is_dc_source:!1,terminal1_source_port_id:posPort.source_port_id??void 0,terminal2_source_port_id:negPort.source_port_id??void 0,current:props.current,frequency:props.frequency,peak_to_peak_current:props.peakToPeakCurrent,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle,ac_magnitude:props.acMagnitude,ac_phase:props.acPhase});this.simulation_current_source_id=simulationCurrentSource.simulation_current_source_id}else{if(props.current===void 0)return;let simulationCurrentSource=db2.simulation_current_source.insert({is_dc_source:!0,positive_source_port_id:posPort.source_port_id??void 0,negative_source_port_id:negPort.source_port_id??void 0,current:props.current,ac_magnitude:props.acMagnitude,ac_phase:props.acPhase});this.simulation_current_source_id=simulationCurrentSource.simulation_current_source_id}}},PLACEMENT_MARGIN=.25,rectForComponent=(component,margin)=>({left:component.center.x-component.size.width/2-margin,right:component.center.x+component.size.width/2+margin,bottom:component.center.y-component.size.height/2-margin,top:component.center.y+component.size.height/2+margin}),rectsOverlap5=(a6,b6)=>a6.left<b6.right&&a6.right>b6.left&&a6.bottom<b6.top&&a6.top>b6.bottom,getCandidateCenters=({baseCenter,size:size3})=>{let xStep=size3.width+PLACEMENT_MARGIN*2,yStep=size3.height+PLACEMENT_MARGIN*2;return[baseCenter,{x:baseCenter.x,y:baseCenter.y+yStep},{x:baseCenter.x,y:baseCenter.y-yStep},{x:baseCenter.x+xStep,y:baseCenter.y},{x:baseCenter.x-xStep,y:baseCenter.y},{x:baseCenter.x+xStep,y:baseCenter.y+yStep},{x:baseCenter.x-xStep,y:baseCenter.y+yStep},{x:baseCenter.x+xStep,y:baseCenter.y-yStep},{x:baseCenter.x-xStep,y:baseCenter.y-yStep},{x:baseCenter.x,y:baseCenter.y+yStep*2},{x:baseCenter.x,y:baseCenter.y-yStep*2}]},getConnectedSchematicPort=({ammeterSourcePortId,schematicPorts,sourceTraces})=>{for(let sourceTrace of sourceTraces){if(!sourceTrace.connected_source_port_ids.includes(ammeterSourcePortId))continue;let connectedSourcePortId=sourceTrace.connected_source_port_ids.find(sourcePortId=>sourcePortId!==ammeterSourcePortId);if(connectedSourcePortId===void 0)continue;let schematicPort=schematicPorts.find(port=>port.source_port_id===connectedSourcePortId);if(schematicPort)return schematicPort}return null},midpoint3=ports=>({x:ports.reduce((sum,port)=>sum+port.center.x,0)/ports.length,y:ports.reduce((sum,port)=>sum+port.center.y,0)/ports.length}),shiftAmmeterSchematicElements=({ammeter,db:db2,oldCenter,newCenter})=>{let schematicComponentId=ammeter.schematic_component_id;if(!schematicComponentId)return;let deltaX=newCenter.x-oldCenter.x,deltaY=newCenter.y-oldCenter.y;if(!(deltaX===0&&deltaY===0)){db2.schematic_component.update(schematicComponentId,{center:newCenter});for(let port of db2.schematic_port.list({schematic_component_id:schematicComponentId}))db2.schematic_port.update(port.schematic_port_id,{center:{x:port.center.x+deltaX,y:port.center.y+deltaY}});for(let text of db2.schematic_text.list({schematic_component_id:schematicComponentId}))db2.schematic_text.update(text.schematic_text_id,{position:{x:text.position.x+deltaX,y:text.position.y+deltaY}});updateSchematicPrimitivesForLayoutShift({db:db2,schematicComponentId,deltaX,deltaY})}},Ammeter_doInitialSchematicLayout=ammeter=>{let{root}=ammeter;if(!root||root.schematicDisabled||!ammeter.schematic_component_id||ammeter._parsedProps.schX!==void 0||ammeter._parsedProps.schY!==void 0||ammeter.getGroup()?._getSchematicLayoutMode()!=="relative")return;let{db:db2}=root,schematicComponent=db2.schematic_component.get(ammeter.schematic_component_id);if(!schematicComponent)return;let ammeterSourcePortIds=[ammeter.portMap.pos.source_port_id,ammeter.portMap.neg.source_port_id].filter(sourcePortId=>typeof sourcePortId=="string");if(ammeterSourcePortIds.length===0)return;let schematicPorts=db2.schematic_port.list(),sourceTraces=db2.source_trace.list(),connectedSchematicPorts=ammeterSourcePortIds.map(ammeterSourcePortId=>getConnectedSchematicPort({ammeterSourcePortId,schematicPorts,sourceTraces})).filter(port=>port!==null);if(connectedSchematicPorts.length===0)return;let baseCenter=midpoint3(connectedSchematicPorts),obstacles=db2.schematic_component.list().filter(component=>component.schematic_component_id!==schematicComponent.schematic_component_id&&!component.is_schematic_group&&component.schematic_sheet_id===schematicComponent.schematic_sheet_id).map(component=>rectForComponent(component,PLACEMENT_MARGIN)),bestCenter=getCandidateCenters({baseCenter,size:schematicComponent.size}).find(candidateCenter=>{let candidateRect=rectForComponent({...schematicComponent,center:candidateCenter},PLACEMENT_MARGIN);return!obstacles.some(obstacle=>rectsOverlap5(candidateRect,obstacle))})??baseCenter;shiftAmmeterSchematicElements({ammeter,db:db2,oldCenter:schematicComponent.center,newCenter:bestCenter})},Ammeter=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"simulation_current_probe_id",null);__publicField(this,"pos",this.portMap.pos);__publicField(this,"neg",this.portMap.neg)}get config(){return{componentName:"Ammeter",schematicSymbolName:"dc_ammeter",zodProps:ammeterProps,sourceFtype:"simple_ammeter"}}runRenderPhaseForChildren(phase){if(!phase.startsWith("Pcb"))for(let child of this.children)child.runRenderPhaseForChildren(phase),child.runRenderPhase(phase)}doInitialPcbComponentRender(){let hasExplicitPcbPosition=this._hasUserDefinedPcbPosition();if(!this._parsedProps.footprint){if(!hasExplicitPcbPosition)return;throw new Error("Ammeter requires a footprint when pcbX/pcbY or pcb edge position props are used")}super.doInitialPcbComponentRender()}initPorts(){super.initPorts({ignoreSymbolPorts:!0,pinCount:2,additionalAliases:{pin1:["pos"],pin2:["neg"]}});let symbol=hc[this._getSchematicSymbolNameOrThrow()];this.portMap.pos.schematicSymbolPortDef=symbol.ports.find(port=>port.labels.includes("1"))??null,this.portMap.neg.schematicSymbolPortDef=symbol.ports.find(port=>port.labels.includes("2"))??null}doInitialSourceRender(){let{db:db2}=this.root,{supplierPartNumbers,displayName}=this._parsedProps,source_component=db2.source_component.insert({ftype:"simple_ammeter",name:this.name,supplier_part_numbers:supplierPartNumbers,manufacturer_part_number:this._parsedProps.manufacturerPartNumber??this._parsedProps.mfn,display_name:displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db:db2}=this.root,{color,graphDisplayName,graphCenter,graphVerticalOffset,graphCurrentPerDiv}=this._parsedProps,posPort=this.portMap.pos,negPort=this.portMap.neg,{simulation_current_probe_id}=db2.simulation_current_probe.insert({type:"simulation_current_probe",name:this.name,source_component_id:this.source_component_id,positive_source_port_id:posPort.source_port_id,negative_source_port_id:negPort.source_port_id,subcircuit_id:this.getSubcircuit()?.subcircuit_id??void 0,color});if(this.simulation_current_probe_id=simulation_current_probe_id,graphDisplayName!==void 0||graphCenter!==void 0||graphVerticalOffset!==void 0||graphCurrentPerDiv!==void 0){let graphCurrentPerDivValue=parseSimulationGraphValue(graphCurrentPerDiv),graphVerticalOffsetValue=parseSimulationGraphValue(graphVerticalOffset);db2.simulation_oscilloscope_trace.insert({simulation_current_probe_id,display_name:graphDisplayName,color,display_center_value:graphCenter,amps_per_div:graphCurrentPerDivValue,display_center_offset_divs:graphVerticalOffsetValue!==void 0&&graphCurrentPerDivValue!==void 0&&graphCurrentPerDivValue!==0?graphVerticalOffsetValue/graphCurrentPerDivValue:void 0})}}doInitialSchematicLayout(){Ammeter_doInitialSchematicLayout(this)}},edgeSpecifiers=["leftedge","rightedge","topedge","bottomedge","center"],Constraint3=class extends PrimitiveComponent2{get config(){return{componentName:"Constraint",zodProps:constraintProps}}constructor(props){if(super(props),("xdist"in props||"ydist"in props)&&!("edgeToEdge"in props)&&!("centerToCenter"in props))throw new Error(`edgeToEdge, centerToCenter must be set for xDist or yDist for ${this}`);if("for"in props&&props.for.length<2)throw new Error(`"for" must have at least two selectors for ${this}`)}_getAllReferencedComponents(){let componentsWithSelectors=[],container=this.getPrimitiveContainer();function addComponentFromSelector(selector){let maybeEdge=selector.split(" ").pop(),edge=edgeSpecifiers.includes(maybeEdge)?maybeEdge:void 0,componentSelector=edge?selector.replace(` ${edge}`,""):selector,component=container.selectOne(componentSelector,{pcbPrimitive:!0});component&&componentsWithSelectors.push({selector,component,componentSelector,edge})}for(let key of["left","right","top","bottom"])key in this._parsedProps&&addComponentFromSelector(this._parsedProps[key]);if("for"in this._parsedProps)for(let selector of this._parsedProps.for)addComponentFromSelector(selector);return{componentsWithSelectors}}},AutoroutingPhase=class extends PrimitiveComponent2{get config(){return{componentName:"AutoroutingPhase",zodProps:autoroutingPhaseProps}}add(_component){throw new Error("<autoroutingphase> cannot contain children")}},FabricationNoteDimension=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"fabrication_note_dimension_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNoteDimension",zodProps:fabricationNoteDimensionProps}}_resolvePoint(input2,transform7){if(typeof input2=="string"){let target=this.getSubcircuit().selectOne(input2);return target?target._getGlobalPcbPositionBeforeLayout():(this.renderError(`FabricationNoteDimension could not find selector "${input2}"`),applyToPoint2(transform7,{x:0,y:0}))}let numericX=typeof input2.x=="string"?parseFloat(input2.x):input2.x,numericY=typeof input2.y=="string"?parseFloat(input2.y):input2.y;return applyToPoint2(transform7,{x:numericX,y:numericY})}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,transform7=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(props.from,transform7),to3=this._resolvePoint(props.to,transform7),subcircuit=this.getSubcircuit(),group=this.getGroup(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),layer=maybeFlipLayer(props.layer??"top");if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for FabricationNoteDimension. Must be "top" or "bottom".`);let pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,text=props.text??this._formatDistanceText({from,to:to3,units:props.units??"mm"}),fabrication_note_dimension=db2.pcb_fabrication_note_dimension.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,layer,from,to:to3,text,offset:props.offset,font:props.font??"tscircuit2024",font_size:props.fontSize??1,color:props.color,arrow_size:props.arrowSize??1});this.fabrication_note_dimension_id=fabrication_note_dimension.pcb_fabrication_note_dimension_id}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db:db2}=this.root;if(!this.fabrication_note_dimension_id)return;let dimension=db2.pcb_fabrication_note_dimension.get(this.fabrication_note_dimension_id);dimension&&db2.pcb_fabrication_note_dimension.update(this.fabrication_note_dimension_id,{from:{x:dimension.from.x+deltaX,y:dimension.from.y+deltaY},to:{x:dimension.to.x+deltaX,y:dimension.to.y+deltaY}})}getPcbSize(){let transform7=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform7),to3=this._resolvePoint(this._parsedProps.to,transform7);return{width:Math.abs(to3.x-from.x),height:Math.abs(to3.y-from.y)}}_formatDistanceText({from,to:to3,units}){let dx3=to3.x-from.x,dy3=to3.y-from.y,distanceInMillimeters=Math.sqrt(dx3*dx3+dy3*dy3),distanceInUnits=units==="in"?distanceInMillimeters/25.4:distanceInMillimeters,roundedDistance=Math.round(distanceInUnits);if(Math.abs(distanceInUnits-roundedDistance)<1e-9)return`${roundedDistance}${units}`;let decimalPlaces=units==="in"?3:2;return`${units==="in"?Number(distanceInUnits.toFixed(decimalPlaces)).toString():distanceInUnits.toFixed(decimalPlaces)}${units}`}},PcbNoteDimension=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_dimension_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteDimension",zodProps:pcbNoteDimensionProps}}_resolvePoint(input2,transform7){if(typeof input2=="string"){let target=this.getSubcircuit().selectOne(`.${input2}`);if(!target)return this.renderError(`PcbNoteDimension could not find selector "${input2}"`),applyToPoint2(transform7,{x:0,y:0});let targetPcbComponentId=target.pcb_component_id,root=this.root;if(targetPcbComponentId&&root){let pcbComponent=root.db.pcb_component.get(targetPcbComponentId);if(pcbComponent?.center)return{x:pcbComponent.center.x,y:pcbComponent.center.y}}return target._getGlobalPcbPositionBeforeLayout()}let numericX=typeof input2.x=="string"?parseFloat(input2.x):input2.x,numericY=typeof input2.y=="string"?parseFloat(input2.y):input2.y;return applyToPoint2(transform7,{x:numericX,y:numericY})}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,transform7=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(props.from,transform7),to3=this._resolvePoint(props.to,transform7),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,text=props.text??this._formatDistanceText({from,to:to3,units:props.units??"mm"}),pcb_note_dimension3=db2.pcb_note_dimension.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,from,to:to3,text,font:props.font??"tscircuit2024",font_size:props.fontSize??1,layer:props.layer==="bottom"?"bottom":"top",color:props.color,arrow_size:props.arrowSize??1});this.pcb_note_dimension_id=pcb_note_dimension3.pcb_note_dimension_id}doInitialPcbLayout(){let root=this.root;if(!root||root.pcbDisabled||!this.pcb_note_dimension_id)return;let{db:db2}=root,transform7=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform7),to3=this._resolvePoint(this._parsedProps.to,transform7);db2.pcb_note_dimension.update(this.pcb_note_dimension_id,{from,to:to3})}getPcbSize(){let transform7=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform7),to3=this._resolvePoint(this._parsedProps.to,transform7);return{width:Math.abs(to3.x-from.x),height:Math.abs(to3.y-from.y)}}_formatDistanceText({from,to:to3,units}){let dx3=to3.x-from.x,dy3=to3.y-from.y,distanceInMillimeters=Math.sqrt(dx3*dx3+dy3*dy3),distanceInUnits=units==="in"?distanceInMillimeters/25.4:distanceInMillimeters,roundedDistance=Math.round(distanceInUnits);if(Math.abs(distanceInUnits-roundedDistance)<1e-9)return`${roundedDistance}${units}`;let decimalPlaces=units==="in"?3:2;return`${units==="in"?Number(distanceInUnits.toFixed(decimalPlaces)).toString():distanceInUnits.toFixed(decimalPlaces)}${units}`}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db:db2}=this.root;if(!this.pcb_note_dimension_id)return;let dimension=db2.pcb_note_dimension.get(this.pcb_note_dimension_id);dimension&&db2.pcb_note_dimension.update(this.pcb_note_dimension_id,{from:{x:dimension.from.x+deltaX,y:dimension.from.y+deltaY},to:{x:dimension.to.x+deltaX,y:dimension.to.y+deltaY}})}},AutoplacedBreakoutPoint=class extends BaseBreakoutPoint{get config(){return{componentName:"AutoplacedBreakoutPoint",zodProps:baseBreakoutPointProps}}_applySolvedBreakoutPoint({sourceTraceId,layer,position:position4}){this.matchedSourceTraceId=sourceTraceId,this._renderPcbBreakoutPoint({layer:layer_ref.parse(layer)}),this._setPositionFromLayout(position4)}},DDR_BYTE0_PORTS=[{id:"DQ0",layer:"inner3",soc:{x:-6,y:-3},ram:{x:3.941917,y:-3.650917}},{id:"DQ1",layer:"inner6",fullLayer:"inner2",soc:{x:-5.5,y:-3},ram:{x:4.591917,y:-3.650917}},{id:"DQ2",layer:"inner5",fullLayer:"inner4",soc:{x:-4.5,y:-3},ram:{x:5.891917,y:-3.650917}},{id:"DQ3",layer:"inner2",fullLayer:"inner6",soc:{x:-4.5,y:-3.5},ram:{x:6.541917,y:-3.650917}},{id:"DQ4",layer:"inner3",fullLayer:"inner2",soc:{x:-6,y:-2.5},ram:{x:6.541917,y:-2.050917}},{id:"DQ5",layer:"inner2",fullLayer:"inner5",soc:{x:-6,y:-2},ram:{x:5.891917,y:-2.050917}},{id:"DQ6",layer:"inner5",fullLayer:"inner4",soc:{x:-5,y:-2},ram:{x:4.591917,y:-2.050917}},{id:"DQ7",layer:"inner4",fullLayer:"inner6",soc:{x:-5.5,y:-2},ram:{x:3.941917,y:-2.050917}},{id:"DM0",layer:"inner4",fullLayer:"inner5",soc:{x:-5,y:-3},ram:{x:4.591917,y:-2.850917}},{id:"DQS0",layer:"inner1",differentialPairId:"DQS0",soc:{x:-4.5,y:-2.5},ram:{x:5.241917,y:-2.850917}},{id:"DQS0_n",layer:"inner1",differentialPairId:"DQS0",soc:{x:-5,y:-2.5},ram:{x:5.891917,y:-2.850917}}],DDR_BYTE1_PORTS=[{id:"DQ8",layer:"inner6",fullLayer:"inner4",soc:{x:-6,y:3},ram:{x:3.941917,y:3.549083}},{id:"DQ9",layer:"inner3",fullLayer:"inner4",soc:{x:-5.5,y:2},ram:{x:4.591917,y:3.549083}},{id:"DQ10",layer:"inner3",fullLayer:"inner2",soc:{x:-4.5,y:2},ram:{x:5.891917,y:3.549083}},{id:"DQ11",layer:"inner6",fullLayer:"inner5",soc:{x:-4.5,y:2.5},ram:{x:6.541917,y:3.549083}},{id:"DQ12",layer:"inner5",fullLayer:"inner1",soc:{x:-6,y:2.5},ram:{x:6.541917,y:1.949083}},{id:"DQ13",layer:"inner2",fullLayer:"inner3",soc:{x:-6.5,y:3},ram:{x:5.891917,y:1.949083}},{id:"DQ14",layer:"inner5",fullLayer:"inner6",soc:{x:-5,y:2.5},ram:{x:4.591917,y:1.949083}},{id:"DQ15",layer:"inner4",fullLayer:"inner1",soc:{x:-4.5,y:3.5},ram:{x:3.941917,y:1.949083}},{id:"DM1",layer:"inner4",fullLayer:"inner5",soc:{x:-5,y:3.5},ram:{x:4.591917,y:2.749083}},{id:"DQS1",layer:"inner1",fullLayer:"bottom",differentialPairId:"DQS1",soc:{x:-4.5,y:3},ram:{x:5.241917,y:2.749083}},{id:"DQS1_n",layer:"inner1",fullLayer:"bottom",differentialPairId:"DQS1",soc:{x:-5,y:3},ram:{x:5.891917,y:2.749083}}],DDR_ADDR_CTRL_PORTS=[{id:"A0",layer:"bottom",soc:{x:-6.5,y:-.5},ram:{x:7.841917,y:-3.650917}},{id:"A1",layer:"inner3",soc:{x:-7,y:-2},ram:{x:8.491917,y:-3.650917}},{id:"A2",layer:"inner3",soc:{x:-7,y:-.5},ram:{x:7.841917,y:1.949083}},{id:"A3",layer:"inner6",soc:{x:-5,y:-1},ram:{x:7.841917,y:2.749083}},{id:"A4",layer:"inner4",soc:{x:-4.5,y:-1.5},ram:{x:7.841917,y:3.549083}},{id:"A5",layer:"inner2",soc:{x:-6.5,y:-2},ram:{x:8.491917,y:3.549083}},{id:"CS0_n",layer:"inner5",soc:{x:-5.5,y:-.5},ram:{x:7.841917,y:-2.050917}},{id:"CKE0",layer:"inner1",soc:{x:-4.5,y:-1},ram:{x:8.491917,y:-2.050917}},{id:"CK0",layer:"bottom",differentialPairId:"CK0",soc:{x:-4.5,y:1},ram:{x:8.491917,y:1.149083}},{id:"CK0_n",layer:"bottom",differentialPairId:"CK0",soc:{x:-5,y:1},ram:{x:8.491917,y:1.949083}},{id:"DDR_LINK_RESET0_n",layer:"inner6",soc:{x:-5,y:-1.5},ram:{x:13.041917,y:3.549083}}],createAm62lExample=options=>{let ports=options.buses.flatMap(bus=>bus.ports),addedPairIds=new Set,makeEndpoints=port=>[{regionId:"soc",position:port.soc},{regionId:"ram",position:port.ram}],connections=[];for(let port of ports){if(!port.differentialPairId){connections.push({id:port.id,endpoints:makeEndpoints(port)});continue}if(addedPairIds.has(port.differentialPairId))continue;addedPairIds.add(port.differentialPairId);let pair=ports.filter(candidate=>candidate.differentialPairId===port.differentialPairId);if(pair.length!==2)throw new Error(`Differential pair ${port.differentialPairId} must have two members`);let[first,second]=pair;connections.push({type:"differential",connections:[{id:first.id,endpoints:makeEndpoints(first)},{id:second.id,endpoints:makeEndpoints(second)}]})}let buses=options.buses.map(bus=>{let solverBus={id:bus.id,connectionIds:bus.ports.map(port=>port.id)};return bus.preferredLayer!==void 0&&(solverBus={...solverBus,preferredLayer:bus.preferredLayer}),bus.preferredLayers!==void 0&&(solverBus={...solverBus,preferredLayers:bus.preferredLayers}),solverBus});return{regions:[{id:"soc",bounds:{minX:-16.62808,maxX:-2.37192,minY:-10.62808,maxY:10.62808},edge:"right"},{id:"ram",bounds:{minX:1.091917,maxX:18.141917,minY:-9.650917,maxY:9.549083},edge:"left"}],connections,buses,boundaryPointSpacing:.48}},ddrByte0Example=createAm62lExample({buses:[{id:"DDR_BYTE0",ports:DDR_BYTE0_PORTS,preferredLayers:["inner1","inner4"]}]}),ddrByte1Example=createAm62lExample({buses:[{id:"DDR_BYTE1",ports:DDR_BYTE1_PORTS,preferredLayers:["inner2","inner5"]}]}),fullDdrExample=createAm62lExample({buses:[{id:"DDR_BYTE0",ports:DDR_BYTE0_PORTS,preferredLayers:["inner1","inner4"]},{id:"DDR_BYTE1",ports:DDR_BYTE1_PORTS,preferredLayers:["inner2","inner5"]},{id:"DDR_ADDR_CTRL",ports:DDR_ADDR_CTRL_PORTS,preferredLayers:["inner3","inner6"]}]}),controlBusExample=createAm62lExample({buses:[{id:"DDR_ADDR_CTRL",ports:DDR_ADDR_CTRL_PORTS,preferredLayers:["inner3","inner6"]}]}),WindingBreakoutInputError=class extends Error{constructor(){super(...arguments);__publicField(this,"name","WindingBreakoutInputError")}},WindingBreakoutInfeasibleError=class extends Error{constructor(){super(...arguments);__publicField(this,"name","WindingBreakoutInfeasibleError")}},WindingBreakoutInvariantError=class extends Error{constructor(){super(...arguments);__publicField(this,"name","WindingBreakoutInvariantError")}},WindingBreakoutOutputUnavailableError=class extends Error{constructor(){super(...arguments);__publicField(this,"name","WindingBreakoutOutputUnavailableError")}},getCanonicalConnections=input2=>{let connections=[];for(let entry of input2.connections)"type"in entry?connections.push(...entry.connections):connections.push(entry);return connections},getBusLayerCandidates=bus=>bus.preferredLayer!==void 0?[bus.preferredLayer]:bus.preferredLayers!==void 0?[...new Set(bus.preferredLayers)]:["top"],getLayerCandidatesByConnection=input2=>{let candidatesByConnection=new Map;for(let bus of input2.buses){let candidates=getBusLayerCandidates(bus);for(let connectionId of bus.connectionIds)candidatesByConnection.set(connectionId,candidates)}return Object.fromEntries(getCanonicalConnections(input2).map(connection=>[connection.id,candidatesByConnection.get(connection.id)??["top"]]))},fail=message=>{throw new WindingBreakoutInputError(`WindingBreakoutSolver: ${message}`)},isRecord=value=>typeof value=="object"&&value!==null&&!Array.isArray(value),requireRecord=(value,label)=>{isRecord(value)||fail(`${label} must be an object`)},requireId=(value,label)=>{(typeof value!="string"||value.trim().length===0)&&fail(`${label} must be a non-empty string`)},requireFinite=(value,label)=>{(typeof value!="number"||!Number.isFinite(value))&&fail(`${label} must be finite`)},requirePositive=(value,label)=>{requireFinite(value,label),value<=0&&fail(`${label} must be positive`)},requireArray=(value,message)=>Array.isArray(value)?value:fail(message),validatePoint=(value,label)=>(requireRecord(value,label),requireFinite(value.x,`${label}.x`),requireFinite(value.y,`${label}.y`),value),validateBounds=(value,label)=>(requireRecord(value,label),requireFinite(value.minX,`${label}.minX`),requireFinite(value.maxX,`${label}.maxX`),requireFinite(value.minY,`${label}.minY`),requireFinite(value.maxY,`${label}.maxY`),(value.minX>=value.maxX||value.minY>=value.maxY)&&fail(`${label} must have positive width and height`),{minX:value.minX,maxX:value.maxX,minY:value.minY,maxY:value.maxY}),pointIsInsideBounds3=(point6,bounds)=>point6.x>=bounds.minX&&point6.x<=bounds.maxX&&point6.y>=bounds.minY&&point6.y<=bounds.maxY,validateWindingBreakoutInput=input2=>{(!Array.isArray(input2.regions)||input2.regions.length===0)&&fail("at least one region is required"),requirePositive(input2.boundaryPointSpacing,"boundaryPointSpacing");let regionIds=new Set,regions=input2.regions.map((value,index)=>{requireRecord(value,`regions[${index}]`),requireId(value.id,`regions[${index}].id`),regionIds.has(value.id)&&fail(`duplicate region id "${value.id}"`),regionIds.add(value.id);let bounds=validateBounds(value.bounds,`region "${value.id}" bounds`);return(typeof value.edge!="string"||!new Set(["left","right","bottom","top"]).has(value.edge))&&fail(`region "${value.id}" has invalid edge`),{id:value.id,bounds,edge:value.edge,center:{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2}}}),vertical=regions.every(region=>region.edge==="left"||region.edge==="right"),horizontal=regions.every(region=>region.edge==="bottom"||region.edge==="top");!vertical&&!horizontal&&fail("all coordinated region edges must be parallel"),(!Array.isArray(input2.connections)||input2.connections.length===0)&&fail("at least one connection is required");let connections=[],connectionIds=new Set,atomicConnectionGroups=[],validateConnection=(value,label)=>{requireRecord(value,label),requireId(value.id,`${label}.id`),connectionIds.has(value.id)&&fail(`duplicate connection id "${value.id}"`),"layer"in value&&fail(`${label}.layer is not accepted; declare layer preferences on a bus`);let endpointValues=requireArray(value.endpoints,`${label}.endpoints must be an array`),endpointRegionIds=new Set,endpoints=endpointValues.map((endpointValue,endpointIndex)=>{let endpointLabel=`${label}.endpoints[${endpointIndex}]`;requireRecord(endpointValue,endpointLabel),requireId(endpointValue.regionId,`${endpointLabel}.regionId`),regionIds.has(endpointValue.regionId)||fail(`${endpointLabel} references unknown region "${endpointValue.regionId}"`),endpointRegionIds.has(endpointValue.regionId)&&fail(`${label} has duplicate endpoint for region "${endpointValue.regionId}"`),endpointRegionIds.add(endpointValue.regionId);let position4=validatePoint(endpointValue.position,`${endpointLabel}.position`),region=regions.find(candidate=>candidate.id===endpointValue.regionId);return pointIsInsideBounds3(position4,region.bounds)||fail(`${label} endpoint for region "${region.id}" is outside its bounds`),{regionId:endpointValue.regionId,position:position4}});for(let region of regions)endpointRegionIds.has(region.id)||fail(`${label} is missing endpoint for region "${region.id}"`);return endpoints.length!==regions.length&&fail(`${label} must contain exactly one endpoint for every region`),connectionIds.add(value.id),{id:value.id,endpoints}};for(let[index,value]of input2.connections.entries()){let label=`connections[${index}]`;if(requireRecord(value,label),"type"in value||"connections"in value){value.type!=="differential"&&fail(`${label} has invalid differential-pair type`),"layer"in value&&fail(`${label}.layer is not accepted; declare layer preferences on a bus`);let pairConnections=requireArray(value.connections,`${label}.connections must contain exactly two members`);pairConnections.length!==2&&fail(`${label}.connections must contain exactly two members`);let first=validateConnection(pairConnections[0],`${label}.connections[0]`),second=validateConnection(pairConnections[1],`${label}.connections[1]`);first.id===second.id&&fail(`${label} members must have distinct connection ids`),connections.push(first,second),atomicConnectionGroups.push([first.id,second.id])}else connections.push(validateConnection(value,label))}let busValues=requireArray(input2.buses,"buses must be an array"),busIds=new Set,busByConnection=new Map,buses=busValues.map((value,busIndex)=>{let label=`buses[${busIndex}]`;requireRecord(value,label),requireId(value.id,`${label}.id`);let busId=value.id;busIds.has(busId)&&fail(`duplicate bus id "${busId}"`),busIds.add(busId);let connectionIdValues=requireArray(value.connectionIds,`${label}.connectionIds must be a non-empty array`);connectionIdValues.length===0&&fail(`${label}.connectionIds must be a non-empty array`);let localConnectionIds=new Set,busConnectionIds=connectionIdValues.map((connectionId,connectionIndex)=>{requireId(connectionId,`${label}.connectionIds[${connectionIndex}]`),connectionIds.has(connectionId)||fail(`${label} references unknown connection "${connectionId}"`),localConnectionIds.has(connectionId)&&fail(`${label} contains duplicate connection "${connectionId}"`),localConnectionIds.add(connectionId);let previousBusId=busByConnection.get(connectionId);return previousBusId!==void 0&&fail(`connection "${connectionId}" belongs to multiple buses "${previousBusId}" and "${value.id}"`),busByConnection.set(connectionId,busId),connectionId}),preferredLayer;value.preferredLayer!==void 0&&(requireId(value.preferredLayer,`${label}.preferredLayer`),preferredLayer=value.preferredLayer);let preferredLayers;if(value.preferredLayers!==void 0){let preferredLayerValues=requireArray(value.preferredLayers,`${label}.preferredLayers must be a non-empty array`);preferredLayerValues.length===0&&fail(`${label}.preferredLayers must be a non-empty array`);let uniquePreferredLayers=new Set;preferredLayers=preferredLayerValues.map((layer,layerIndex)=>(requireId(layer,`${label}.preferredLayers[${layerIndex}]`),uniquePreferredLayers.has(layer)&&fail(`${label}.preferredLayers contains duplicate layer "${layer}"`),uniquePreferredLayers.add(layer),layer))}let validatedBus={id:busId,connectionIds:busConnectionIds};return preferredLayer!==void 0&&(validatedBus={...validatedBus,preferredLayer}),preferredLayers!==void 0&&(validatedBus={...validatedBus,preferredLayers}),validatedBus});for(let[firstConnectionId,secondConnectionId]of atomicConnectionGroups){let firstBusId=busByConnection.get(firstConnectionId),secondBusId=busByConnection.get(secondConnectionId);firstBusId!==secondBusId&&fail(`differential pair "${firstConnectionId}/${secondConnectionId}" must belong to the same bus`)}let layerNames=[...new Set([...buses.flatMap(bus=>getBusLayerCandidates(bus)),...connections.filter(connection=>!busByConnection.has(connection.id)).map(()=>"top")])].sort((first,second)=>first.localeCompare(second));return{regions,connections,buses,layerNames,atomicConnectionGroups}},GEOMETRY_EPSILON3=1e-9,isVerticalEdge=edge=>edge==="left"||edge==="right",getAxisMinimum=(region,vertical)=>vertical?region.bounds.minY:region.bounds.minX,getAxisMaximum=(region,vertical)=>vertical?region.bounds.maxY:region.bounds.maxX,getAxisPosition=(position4,vertical)=>vertical?position4.y:position4.x,deriveLayerOffsets=(layerNames,boundaryPointSpacing)=>{let staggerOffset=boundaryPointSpacing/2;return Object.fromEntries(layerNames.map((layer,index)=>[layer,(index-(layerNames.length-1)/2)*staggerOffset]))},makeAtomicLayerOrder=({referenceOrder,layer,layerByConnection,atomicGroups})=>{let candidates=referenceOrder.filter(connectionId=>layerByConnection[connectionId]===layer),groupByConnection=new Map(atomicGroups.flatMap(group=>group.map(connectionId=>[connectionId,group]))),addedGroups=new Set,result=[];for(let connectionId of candidates){let group=groupByConnection.get(connectionId);if(!group){result.push(connectionId);continue}addedGroups.has(group)||(addedGroups.add(group),result.push(...candidates.filter(candidate=>group.includes(candidate))))}return result},makeGateAxes=({regions,connections,spacing,count,layerOffsets})=>{let vertical=regions.every(region=>isVerticalEdge(region.edge)),minAxis=Math.max(...regions.map(region=>getAxisMinimum(region,vertical))),maxAxis=Math.min(...regions.map(region=>getAxisMaximum(region,vertical))),minimumOffset=Math.min(...Object.values(layerOffsets)),maximumOffset=Math.max(...Object.values(layerOffsets)),span=spacing*Math.max(0,count-1)+maximumOffset-minimumOffset;if(maxAxis-minAxis+GEOMETRY_EPSILON3<span)throw new WindingBreakoutInfeasibleError(`WindingBreakoutSolver: declared breakout edges need ${span.toFixed(2)}mm but expose only ${(maxAxis-minAxis).toFixed(2)}mm`);let meanAxis=regions.reduce((regionSum,region)=>{let positions=connections.map(connection=>connection.endpoints.find(endpoint=>endpoint.regionId===region.id).position);return regionSum+positions.reduce((sum,position4)=>sum+getAxisPosition(position4,vertical),0)/positions.length},0)/regions.length,start=Math.max(minAxis-minimumOffset,Math.min(maxAxis-spacing*Math.max(0,count-1)-maximumOffset,meanAxis-spacing*Math.max(0,count-1)/2));return{vertical,axes:Array.from({length:count},(_6,index)=>start+index*spacing)}},pointOnEdge=(region,axis,vertical)=>{if(vertical){let x6=region.bounds.maxX;return region.edge==="left"&&(x6=region.bounds.minX),{x:x6,y:axis}}let y2=region.bounds.maxY;return region.edge==="bottom"&&(y2=region.bounds.minY),{x:axis,y:y2}},placeBreakoutGates=({regions,connections,referenceOrder,layerNames,layerByConnection,boundaryPointSpacing,atomicGroups})=>{let layerOffsets=deriveLayerOffsets(layerNames,boundaryPointSpacing),gateOrderByLayer=Object.fromEntries(layerNames.map(layer=>[layer,makeAtomicLayerOrder({referenceOrder,layer,layerByConnection,atomicGroups})])),maxLayerNetCount=Math.max(...layerNames.map(layer=>connections.filter(connection=>layerByConnection[connection.id]===layer).length)),{vertical,axes}=makeGateAxes({regions,connections,spacing:boundaryPointSpacing,count:maxLayerNetCount,layerOffsets});return{breakoutPoints:regions.flatMap(region=>layerNames.flatMap(layer=>gateOrderByLayer[layer].map((connectionId,slotIndex)=>({regionId:region.id,connectionId,layer,...pointOnEdge(region,axes[slotIndex]+layerOffsets[layer],vertical)}))))}},getAtomicUnits=(connectionIds,atomicGroups)=>{let connectionSet=new Set(connectionIds),groupByConnection=new Map(atomicGroups.flatMap(group=>group.map(connectionId=>[connectionId,group]))),addedGroups=new Set,units=[];for(let connectionId of connectionIds){let group=groupByConnection.get(connectionId);if(!group){units.push([connectionId]);continue}addedGroups.has(group)||(addedGroups.add(group),units.push(group.filter(memberId=>connectionSet.has(memberId))))}return units},assignConnectionLayers=({validated,referenceOrder})=>{let assignments=new Map;for(let bus of validated.buses){let busConnectionSet=new Set(bus.connectionIds),orderedBusConnections=referenceOrder.filter(connectionId=>busConnectionSet.has(connectionId)),candidates=getBusLayerCandidates(bus),units=getAtomicUnits(orderedBusConnections,validated.atomicConnectionGroups);for(let[unitIndex,unit]of units.entries()){let layer=candidates[unitIndex%candidates.length];for(let connectionId of unit)assignments.set(connectionId,layer)}}for(let connectionId of referenceOrder)assignments.has(connectionId)||assignments.set(connectionId,"top");let layerByConnection=Object.fromEntries(referenceOrder.map(connectionId=>[connectionId,assignments.get(connectionId)])),layerNames=[...new Set(Object.values(layerByConnection))].sort((first,second)=>first.localeCompare(second));return{layerByConnection,layerNames}},getLayerNames=input2=>[...new Set(Object.values(getLayerCandidatesByConnection(input2)).flat())].sort((first,second)=>first.localeCompare(second)),CONNECTION_COLORS=["#2563eb","#dc2626","#059669","#7c3aed","#d97706","#0891b2","#db2777","#4f46e5","#65a30d","#c2410c","#0f766e","#9333ea"],getConnectionColor=connectionId=>{let hash=2166136261;for(let character of connectionId)hash^=character.charCodeAt(0),hash=Math.imul(hash,16777619);return CONNECTION_COLORS[(hash>>>0)%CONNECTION_COLORS.length]},getGraphicsLayer2=(input2,layerIds)=>{let signalLayerIds=getLayerNames(input2),indexes=[...new Set(layerIds)].map(layerId=>{let index=signalLayerIds.indexOf(layerId);if(index<0)throw new Error(`Cannot visualize unknown signal layer "${layerId}"`);return index});if(indexes.length===0)throw new Error("Cannot create graphics metadata without a signal layer");return indexes.sort((first,second)=>first-second),`z${indexes.join(",")}`},createInputGraphics=(input2,activeLayer)=>{let graphics={circles:[],rects:[],texts:[]},displayedLayers=getLayerNames(input2);activeLayer&&(displayedLayers=[activeLayer]);let visibleLayers=getGraphicsLayer2(input2,displayedLayers),connections=getCanonicalConnections(input2),layerCandidatesByConnection=getLayerCandidatesByConnection(input2),endpointRadius=Math.min(.12,input2.boundaryPointSpacing/4);for(let region of input2.regions){let center2={x:(region.bounds.minX+region.bounds.maxX)/2,y:(region.bounds.minY+region.bounds.maxY)/2};graphics.rects.push({center:center2,width:region.bounds.maxX-region.bounds.minX,height:region.bounds.maxY-region.bounds.minY,fill:"rgba(226, 232, 240, 0.035)",stroke:"rgba(71, 85, 105, 0.55)",layer:visibleLayers});for(let connection of connections){let layerCandidates=layerCandidatesByConnection[connection.id];if(activeLayer&&!layerCandidates.includes(activeLayer))continue;let endpoint=connection.endpoints.find(candidate=>candidate.regionId===region.id);if(!endpoint)continue;let color=getConnectionColor(connection.id);graphics.circles.push({center:endpoint.position,radius:endpointRadius,fill:`${color}70`,stroke:color,layer:getGraphicsLayer2(input2,layerCandidates)})}graphics.texts.push({x:center2.x,y:region.bounds.maxY+.35,text:region.id,anchorSide:"bottom_center",color:"#334155",fontSize:.34,layer:visibleLayers})}return graphics},createStateGraphics=(input2,state2,activeLayer)=>{let connections=getCanonicalConnections(input2),breakoutPoints=state2.breakoutPoints.filter(point6=>!activeLayer||point6.layer===activeLayer),sharedGateSlots=new Map;for(let point6 of state2.breakoutPoints){let key=`${point6.regionId}:${point6.x.toFixed(9)}:${point6.y.toFixed(9)}`,slot=sharedGateSlots.get(key)??{x:point6.x,y:point6.y,layers:new Set};slot.layers.add(point6.layer),sharedGateSlots.set(key,slot)}return{lines:state2.referenceOrder.flatMap(connectionId=>{let connection=connections.find(candidate=>candidate.id===connectionId);if(!connection)return[];let connectionBreakouts=breakoutPoints.filter(point6=>point6.connectionId===connectionId),layer=connectionBreakouts[0]?.layer;if(!layer||activeLayer&&layer!==activeLayer)return[];if(connectionBreakouts.length!==input2.regions.length)return[];let points=input2.regions.flatMap((region,regionIndex)=>{let endpoint=connection.endpoints.find(candidate=>candidate.regionId===region.id),breakout=connectionBreakouts.find(candidate=>candidate.regionId===region.id);return!endpoint||!breakout?[]:regionIndex===0?[endpoint.position,breakout]:[breakout,endpoint.position]});return points.length<2?[]:[{points,strokeColor:`${getConnectionColor(connectionId)}55`,strokeWidth:.012,strokeDash:[.025,.07],layer:getGraphicsLayer2(input2,[layer])}]}),circles:[...sharedGateSlots.values()].flatMap(slot=>{let layers=[...slot.layers].filter(layer=>!activeLayer||layer===activeLayer);return layers.length===0?[]:[{center:slot,radius:.11,fill:"rgba(15, 23, 42, 0.06)",stroke:"#475569",layer:getGraphicsLayer2(input2,layers)}]}),points:breakoutPoints.map(point6=>({x:point6.x,y:point6.y,color:getConnectionColor(point6.connectionId),label:`${point6.connectionId} \xB7 ${point6.layer}`,layer:getGraphicsLayer2(input2,[point6.layer])}))}},createSolverPhaseVisualization=({input:input2,phase,detail,activeLayer,referenceOrder,referenceRegionId,showReferenceNumbers=!1,state:state2})=>{let inputGraphics=createInputGraphics(input2,activeLayer),stateGraphics;state2&&(stateGraphics=createStateGraphics(input2,state2,activeLayer));let displayedLayers=getLayerNames(input2);activeLayer&&(displayedLayers=[activeLayer]);let textLayer=getGraphicsLayer2(input2,displayedLayers),maxY=Math.max(...input2.regions.map(region=>region.bounds.maxY)),minX=Math.min(...input2.regions.map(region=>region.bounds.minX)),texts=[...inputGraphics.texts??[],...stateGraphics?.texts??[],{x:minX,y:maxY+1.05,text:phase,anchorSide:"bottom_left",color:"#0f172a",fontSize:.42,layer:textLayer},{x:minX,y:maxY+.68,text:detail,anchorSide:"bottom_left",color:"#475569",fontSize:.25,layer:textLayer}],referenceLines=[],referenceCircles=[];if(showReferenceNumbers&&referenceOrder){let referenceRegion=input2.regions.find(region=>region.id===referenceRegionId)??input2.regions[0],connections=getCanonicalConnections(input2),layerCandidatesByConnection=getLayerCandidatesByConnection(input2),orderedPositions=[];for(let[index,connectionId]of referenceOrder.entries()){let connection=connections.find(candidate=>candidate.id===connectionId),layerCandidates=layerCandidatesByConnection[connectionId];if(!connection||!layerCandidates||activeLayer&&!layerCandidates.includes(activeLayer))continue;let endpoint=connection.endpoints.find(candidate=>candidate.regionId===referenceRegion.id);endpoint&&(orderedPositions.push(endpoint.position),texts.push({x:endpoint.position.x+.18,y:endpoint.position.y+.18,text:`${index+1} \xB7 ${connectionId}`,anchorSide:"bottom_left",color:getConnectionColor(connectionId),fontSize:.21,layer:getGraphicsLayer2(input2,layerCandidates)}))}let center2={x:(referenceRegion.bounds.minX+referenceRegion.bounds.maxX)/2,y:(referenceRegion.bounds.minY+referenceRegion.bounds.maxY)/2};referenceLines.push(...orderedPositions.map(position4=>({points:[center2,position4],strokeColor:"rgba(100, 116, 139, 0.35)",strokeWidth:.01,strokeDash:[.03,.05],layer:textLayer}))),orderedPositions.length>1&&referenceLines.push({points:orderedPositions,strokeColor:"rgba(15, 23, 42, 0.65)",strokeWidth:.018,strokeDash:[.04,.04],label:`${referenceRegion.id} angular winding order`,layer:textLayer}),referenceCircles.push({center:center2,radius:.07,fill:"#0f172a",stroke:"#ffffff",label:`${referenceRegion.id} angular reference center`,layer:textLayer})}return{title:phase,coordinateSystem:"cartesian",rects:inputGraphics.rects,polygons:inputGraphics.polygons,lines:[...stateGraphics?.lines??[],...referenceLines],circles:[...inputGraphics.circles??[],...stateGraphics?.circles??[],...referenceCircles],points:stateGraphics?.points,texts}},getSharedGateSlotCount=points=>new Set(points.map(point6=>`${point6.regionId}:${point6.x.toFixed(9)}:${point6.y.toFixed(9)}`)).size,GatePlacementSolver=class extends BaseSolver{constructor(params){super();__publicField(this,"params");__publicField(this,"batchIndex",0);__publicField(this,"output");__publicField(this,"plannedPlacement");__publicField(this,"placementBatches");__publicField(this,"visibleBreakoutPoints",[]);__publicField(this,"layerByConnection");__publicField(this,"visualizationLayer");this.params=params,this.visualizationLayer=params.visualizationLayer;let assignment=assignConnectionLayers({validated:params.validated,referenceOrder:params.ordering.referenceOrder});this.layerByConnection=assignment.layerByConnection,this.placementBatches=params.validated.regions.flatMap(region=>assignment.layerNames.map(layer=>({regionId:region.id,layer}))),this.MAX_ITERATIONS=this.placementBatches.length+2}setVisualizationLayer(layer){this.visualizationLayer=layer}_step(){if(!this.plannedPlacement){this.plannedPlacement=placeBreakoutGates({regions:this.params.validated.regions,connections:this.params.validated.connections,referenceOrder:this.params.ordering.referenceOrder,layerNames:[...new Set(Object.values(this.layerByConnection))].sort((first,second)=>first.localeCompare(second)),layerByConnection:this.layerByConnection,boundaryPointSpacing:this.params.input.boundaryPointSpacing,atomicGroups:this.params.validated.atomicConnectionGroups}),this.stats={phase:"plan-gate-grid",regionLayerBatches:this.placementBatches.length,placedBreakpoints:0};return}let batch=this.placementBatches[this.batchIndex];if(batch){this.visibleBreakoutPoints.push(...this.plannedPlacement.breakoutPoints.filter(point6=>point6.regionId===batch.regionId&&point6.layer===batch.layer)),this.batchIndex+=1,this.stats={phase:"place-region-layer-batch",regionId:batch.regionId,layer:batch.layer,completedBatches:this.batchIndex,totalBatches:this.placementBatches.length,placedBreakpoints:this.visibleBreakoutPoints.length};return}this.output=this.plannedPlacement,this.stats={phase:"finalize-shared-gate-slots",placedBreakpoints:this.output.breakoutPoints.length,sharedGateSlots:getSharedGateSlotCount(this.output.breakoutPoints)},this.solved=!0}computeProgress(){let completedMicrosteps=this.batchIndex;return this.plannedPlacement&&(completedMicrosteps+=1),this.output&&(completedMicrosteps+=1),completedMicrosteps/this.MAX_ITERATIONS}getConstructorParams(){return[this.params]}getOutput(){if(!this.solved||!this.output)throw new WindingBreakoutInvariantError("WindingBreakoutSolver: gate placement requested before placement completed");return this.output}visualize(){let detail="Next microstep: derive layer offsets, atomic gate orders, and the common boundary slot grid";if(this.plannedPlacement&&this.batchIndex===0)detail=`Gate grid planned \xB7 ${this.placementBatches.length} region/layer batches remain`;else if(this.plannedPlacement&&!this.output){let latestBatch=this.placementBatches[this.batchIndex-1];detail=`Placed region \u201C${latestBatch.regionId}\u201D on layer \u201C${latestBatch.layer}\u201D \xB7 ${this.batchIndex}/${this.placementBatches.length} batches`}else if(this.output){let sharedGateSlotCount=getSharedGateSlotCount(this.output.breakoutPoints);detail=`${this.output.breakoutPoints.length} gates placed; coincident layer positions form ${sharedGateSlotCount} shared slots`}let visualizationState;if(this.plannedPlacement){let breakoutPoints=this.visibleBreakoutPoints;this.output&&(breakoutPoints=this.output.breakoutPoints),visualizationState={referenceOrder:this.params.ordering.referenceOrder,breakoutPoints}}let graphics=createSolverPhaseVisualization({input:this.params.input,activeLayer:this.visualizationLayer,phase:"Step 2 \xB7 Place boundary gates",detail,state:visualizationState}),plannedSlotGuides=(this.plannedPlacement?.breakoutPoints??[]).filter(point6=>!this.visualizationLayer||point6.layer===this.visualizationLayer).map(point6=>({center:point6,radius:.065,fill:"rgba(255, 255, 255, 0.75)",stroke:"rgba(100, 116, 139, 0.5)",label:`planned slot ${point6.regionId} \xB7 ${point6.layer}`,layer:getGraphicsLayer2(this.params.input,[point6.layer])}));return{...graphics,circles:[...graphics.circles??[],...plannedSlotGuides]}}},getNaturalWindingOrder=(region,connections)=>connections.map(connection=>{let position4=connection.endpoints.find(endpoint=>endpoint.regionId===region.id).position;return{id:connection.id,angle:Math.atan2(position4.y-region.center.y,position4.x-region.center.x),radius:Math.hypot(position4.x-region.center.x,position4.y-region.center.y)}}).sort((first,second)=>first.angle-second.angle||second.radius-first.radius||first.id.localeCompare(second.id)).map(connection=>connection.id),getReferenceWindingOrder=(naturalOrder,atomicGroups,buses)=>{let groupByConnection=new Map(atomicGroups.flatMap(group=>group.map(connectionId=>[connectionId,group]))),addedGroups=new Set,result=[];for(let connectionId of naturalOrder){let group=groupByConnection.get(connectionId);if(!group){result.push(connectionId);continue}addedGroups.has(group)||(addedGroups.add(group),result.push(...naturalOrder.filter(candidate=>group.includes(candidate))))}let busByConnection=new Map(buses.flatMap(bus=>bus.connectionIds.map(connectionId=>[connectionId,bus]))),addedBuses=new Set,busContiguousResult=[];for(let connectionId of result){let bus=busByConnection.get(connectionId);if(!bus){busContiguousResult.push(connectionId);continue}if(addedBuses.has(bus))continue;addedBuses.add(bus);let busConnectionIds=new Set(bus.connectionIds);busContiguousResult.push(...result.filter(candidate=>busConnectionIds.has(candidate)))}return busContiguousResult},ReferenceOrderingSolver=class extends BaseSolver{constructor(params){super();__publicField(this,"params");__publicField(this,"naturalOrderByRegion",{});__publicField(this,"currentRegionIndex",0);__publicField(this,"output");__publicField(this,"visualizedOrder");__publicField(this,"visualizedRegionId");__publicField(this,"visualizationLayer");this.params=params,this.visualizationLayer=params.visualizationLayer,this.MAX_ITERATIONS=params.validated.regions.length+1}setVisualizationLayer(layer){this.visualizationLayer=layer}_step(){let region=this.params.validated.regions[this.currentRegionIndex];if(region){let naturalOrder=getNaturalWindingOrder(region,this.params.validated.connections);this.naturalOrderByRegion[region.id]=naturalOrder,this.visualizedRegionId=region.id,this.visualizedOrder=naturalOrder,this.currentRegionIndex+=1,this.stats={phase:"derive-natural-order",regionId:region.id,completedRegions:this.currentRegionIndex,totalRegions:this.params.validated.regions.length,naturalOrder};return}let firstRegion=this.params.validated.regions[0],referenceOrder=getReferenceWindingOrder(this.naturalOrderByRegion[firstRegion.id],this.params.validated.atomicConnectionGroups,this.params.validated.buses);this.output={naturalOrderByRegion:this.naturalOrderByRegion,referenceOrder},this.visualizedRegionId=firstRegion.id,this.visualizedOrder=referenceOrder,this.stats={phase:"atomicize-reference-order",referenceRegion:firstRegion.id,referenceOrder},this.solved=!0}computeProgress(){let completedMicrosteps=this.currentRegionIndex;return this.output&&(completedMicrosteps+=1),completedMicrosteps/this.MAX_ITERATIONS}getConstructorParams(){return[this.params]}getOutput(){if(!this.solved||!this.output)throw new WindingBreakoutInvariantError("WindingBreakoutSolver: reference order requested before ordering completed");return this.output}visualize(){let firstRegionId=this.params.validated.regions[0].id,detail=`Next microstep: derive natural order for region \u201C${firstRegionId}\u201D`;return this.visualizedRegionId&&!this.output&&(detail=`Natural order for region \u201C${this.visualizedRegionId}\u201D \xB7 ${this.currentRegionIndex}/${this.params.validated.regions.length} regions processed`),this.output&&(detail=`Reference region \u201C${firstRegionId}\u201D finalized; buses are contiguous and differential pairs are atomic`),createSolverPhaseVisualization({input:this.params.input,activeLayer:this.visualizationLayer,phase:"Step 1 \xB7 Derive reference order",detail,referenceOrder:this.visualizedOrder,referenceRegionId:this.visualizedRegionId,showReferenceNumbers:!0})}},validateBreakoutPoints=({points,connectionIds,regions,atomicGroups})=>{let regionIds=regions.map(region=>region.id),endpointCounts=new Map,layerByConnection=new Map,connectionLayersAreValid=!0;for(let point6 of points){let key=`${point6.regionId}:${point6.connectionId}`;endpointCounts.set(key,(endpointCounts.get(key)??0)+1);let previousLayer=layerByConnection.get(point6.connectionId);previousLayer!==void 0&&previousLayer!==point6.layer&&(connectionLayersAreValid=!1),layerByConnection.set(point6.connectionId,point6.layer)}let expected=regionIds.flatMap(regionId=>connectionIds.map(connectionId=>`${regionId}:${connectionId}`)),endpointsAreValid=endpointCounts.size===expected.length&&expected.every(endpoint=>endpointCounts.get(endpoint)===1),atomicGroupsAreValid=atomicGroups.every(group=>{let layer=layerByConnection.get(group[0]);return!layer||group.some(connectionId=>layerByConnection.get(connectionId)!==layer)?!1:regions.every(region=>{let layerPoints=points.filter(point6=>point6.regionId===region.id&&point6.layer===layer),vertical=region.edge==="left"||region.edge==="right",orderedConnectionIds=[...layerPoints].sort((first,second)=>vertical?first.y-second.y:first.x-second.x).map(point6=>point6.connectionId),firstIndex=orderedConnectionIds.indexOf(group[0]),secondIndex=orderedConnectionIds.indexOf(group[1]);return firstIndex!==-1&&secondIndex!==-1&&Math.abs(firstIndex-secondIndex)===1})});return endpointsAreValid&&connectionLayersAreValid&&atomicGroupsAreValid},finalizeWindingBreakoutOutput=({validated,placement})=>{if(!validateBreakoutPoints({points:placement.breakoutPoints,connectionIds:validated.connections.map(connection=>connection.id),regions:validated.regions,atomicGroups:validated.atomicConnectionGroups}))throw new WindingBreakoutInvariantError("WindingBreakoutSolver: generated invalid breakout points");return{breakoutPoints:placement.breakoutPoints}},PIPELINE_STAGE_NAMES=["referenceOrdering","gatePlacement"],WindingBreakoutSolver=class extends BasePipelineSolver{constructor(input2){super(input2);__publicField(this,"validatedInput");__publicField(this,"output");__publicField(this,"visualizationLayer");__publicField(this,"pipelineDef",[definePipelineStep("referenceOrdering",ReferenceOrderingSolver,pipeline=>[{input:pipeline.inputProblem,validated:pipeline.getValidatedInput(),visualizationLayer:pipeline.visualizationLayer}]),definePipelineStep("gatePlacement",GatePlacementSolver,pipeline=>[{input:pipeline.inputProblem,validated:pipeline.getValidatedInput(),ordering:pipeline.getRequiredStageOutput("referenceOrdering"),visualizationLayer:pipeline.visualizationLayer}])])}_setup(){this.validatedInput=validateWindingBreakoutInput(this.inputProblem),this.stats={phase:"setup-input-validation",regionCount:this.validatedInput.regions.length,connectionCount:this.validatedInput.connections.length,layerCount:this.validatedInput.layerNames.length}}getValidatedInput(){if(!this.validatedInput)throw new Error("WindingBreakoutSolver: input has not been validated");return this.validatedInput}_step(){super._step(),!this.output&&!this.activeSubSolver&&this.currentPipelineStageIndex>=this.pipelineDef.length&&(this.output=finalizeWindingBreakoutOutput({validated:this.getValidatedInput(),placement:this.getRequiredStageOutput("gatePlacement")}),this.solved=!0),this.stats={phase:this.getCurrentStageName(),completedStages:this.currentPipelineStageIndex,totalStages:this.pipelineDef.length},this.solved&&(this.stats.phase="finalize-output-validation"),this.output&&(this.stats.valid=!0,this.stats.breakoutPointCount=this.output.breakoutPoints.length)}getRequiredStageOutput(stageName){let output=this.getStageOutput(stageName);if(output===void 0)throw new Error(`WindingBreakoutSolver: pipeline stage \u201C${stageName}\u201D has no output`);return output}setVisualizationLayer(layer){this.visualizationLayer=layer;for(let stageName of PIPELINE_STAGE_NAMES){let solver=this.getSolver(stageName);solver&&"setVisualizationLayer"in solver&&solver.setVisualizationLayer(layer)}}getConstructorParams(){return[this.inputProblem]}getOutput(){if(!this.solved||!this.output)throw new WindingBreakoutOutputUnavailableError("WindingBreakoutSolver: getOutput() called before successful completion");return this.output}initialVisualize(){return createSolverPhaseVisualization({input:this.inputProblem,activeLayer:this.visualizationLayer,phase:"Input \xB7 Validated during setup",detail:"Region bounds, breakout edges, bus layer preferences, and canonical endpoints"})}finalVisualize(){if(!this.output)return null;let ordering=this.getRequiredStageOutput("referenceOrdering");return createSolverPhaseVisualization({input:this.inputProblem,activeLayer:this.visualizationLayer,phase:"Output \xB7 Validated after gate placement",detail:"Valid: one bus-constrained breakout point per connection and region; pairs are adjacent",state:{referenceOrder:ordering.referenceOrder,breakoutPoints:this.output.breakoutPoints}})}visualize(){return{...super.visualize(),title:"Winding breakout solver \xB7 step-by-step pipeline",coordinateSystem:"cartesian"}}},toWindingConnection=connection=>({id:connection.connectionId,endpoints:connection.endpoints}),defaultImplicitBreakoutPointSolverFn=input2=>{let windingInput={regions:input2.regions.map(region=>({id:region.regionId,bounds:region.bounds,edge:region.edge})),connections:input2.connections.map(connection=>"type"in connection?{type:"differential",connections:connection.connections.map(toWindingConnection)}:toWindingConnection(connection)),buses:input2.buses.map(bus=>({id:bus.busId,connectionIds:bus.connectionIds,preferredLayers:bus.targetLayers})),boundaryPointSpacing:input2.boundaryPointSpacing},solver=new WindingBreakoutSolver(windingInput);return solver.solve(),solver.getOutput()},getFanoutBounds=pcbGroup=>{let outlineBounds=pcbGroup.outline?getBoundsFromPoints2(pcbGroup.outline):null,width=pcbGroup.width??(outlineBounds?outlineBounds.maxX-outlineBounds.minX:void 0),height=pcbGroup.height??(outlineBounds?outlineBounds.maxY-outlineBounds.minY:void 0);return width===void 0||height===void 0?null:{minX:pcbGroup.center.x-width/2,maxX:pcbGroup.center.x+width/2,minY:pcbGroup.center.y-height/2,maxY:pcbGroup.center.y+height/2}},getAxisGap2=(firstMin,firstMax,secondMin,secondMax)=>Math.max(firstMin-secondMax,secondMin-firstMax,0),Breakout_doInitialPcbPlacementDesignRuleChecks=breakout=>{if(breakout.root?.pcbDisabled||!breakout.pcb_group_id)return;let root=breakout.root;if(!root)return;let siblingFanouts=breakout.parent?.children.filter(sibling=>sibling instanceof breakout.constructor);if(!siblingFanouts)return;let breakoutIndex=siblingFanouts.indexOf(breakout);if(breakoutIndex<0)return;let{db:db2}=root,pcbGroup=db2.pcb_group.get(breakout.pcb_group_id);if(!pcbGroup)return;let bounds=getFanoutBounds(pcbGroup);if(bounds)for(let otherFanout of siblingFanouts.slice(breakoutIndex+1)){if(!otherFanout.pcb_group_id)continue;let otherPcbGroup=db2.pcb_group.get(otherFanout.pcb_group_id);if(!otherPcbGroup)continue;let otherBounds=getFanoutBounds(otherPcbGroup);if(!otherBounds)continue;let breakoutMargin=breakout._parsedProps.fanoutMargin,otherFanoutMargin=otherFanout._parsedProps.fanoutMargin,requiredMargin=Math.max(typeof breakoutMargin=="number"?breakoutMargin:0,typeof otherFanoutMargin=="number"?otherFanoutMargin:0),horizontalGap=getAxisGap2(bounds.minX,bounds.maxX,otherBounds.minX,otherBounds.maxX),verticalGap=getAxisGap2(bounds.minY,bounds.maxY,otherBounds.minY,otherBounds.maxY),horizontalOverlap=Math.min(bounds.maxX,otherBounds.maxX)-Math.max(bounds.minX,otherBounds.minX),verticalOverlap=Math.min(bounds.maxY,otherBounds.maxY)-Math.max(bounds.minY,otherBounds.minY),boundariesOverlap=horizontalOverlap>0&&verticalOverlap>0,violatesMargin=requiredMargin>0&&horizontalGap<requiredMargin&&verticalGap<requiredMargin;if(!boundariesOverlap&&!violatesMargin)continue;let message=boundariesOverlap?`Fanout boundaries "${breakout.name}" and "${otherFanout.name}" overlap. Fanout boundaries may not overlap.`:`Fanout boundaries "${breakout.name}" and "${otherFanout.name}" do not maintain the required ${requiredMargin}mm fanoutMargin.`;db2.pcb_placement_error.list().some(error2=>error2.message===message)||db2.pcb_placement_error.insert({error_type:"pcb_placement_error",message,subcircuit_id:breakout.subcircuit_id??void 0})}},reportWindingBreakoutInfeasibleError=(breakout,error2)=>{if(!(error2 instanceof WindingBreakoutInfeasibleError)||!breakout.root||!breakout.pcb_group_id)return!1;let componentNames=breakout.root.db.pcb_component.list().filter(pcbComponent=>pcbComponent.pcb_group_id===breakout.pcb_group_id).map(pcbComponent=>pcbComponent.source_component_id?breakout.root.db.source_component.get(pcbComponent.source_component_id)?.name:void 0).filter(name=>!!name);return breakout.root.db.pcb_autorouting_error.insert({pcb_error_id:`pcb_autorouting_error_winding_breakout_${breakout.pcb_group_id}`,error_type:"pcb_autorouting_error",message:`Winding fanout failed for ${componentNames.join(", ")||breakout.name}: ${error2.message}. The connections could not escape to the breakout boundary. Give the fanout more room by increasing the breakout's padding, or by extending the breakout to include the parts crowding it (decoupling capacitors, series resistors).`}),!0},getRoutingScopeOrThrow=breakout=>{let routingScope=breakout.parent;if(!routingScope?.selectAll)throw new Error(`Automatic breakout "${breakout.name}" has no coordinated routing scope`);return routingScope},getAutomaticBreakouts=(routingScope,breakoutToSolve)=>{let automaticBreakouts=[];for(let group of routingScope.selectAll("group")){if(!group.isRoutingDirective||group.parent!==routingScope)continue;let breakout=group;breakout.children.some(child=>child instanceof AutoplacedBreakoutPoint)&&automaticBreakouts.push(breakout)}let getSourceTraceIds=breakout=>new Set(collectBreakoutRegionGeometry(breakout).endpointBySourceTraceId.keys()),sourceTraceIdsToSolve=getSourceTraceIds(breakoutToSolve);return automaticBreakouts.filter(automaticBreakout=>{let automaticBreakoutSourceTraceIds=getSourceTraceIds(automaticBreakout);return automaticBreakoutSourceTraceIds.size===sourceTraceIdsToSolve.size&&[...sourceTraceIdsToSolve].every(sourceTraceId=>automaticBreakoutSourceTraceIds.has(sourceTraceId))})},collectBreakoutRegionGeometry=breakout=>{if(!breakout.root||!breakout.pcb_group_id)throw new Error(`Automatic breakout "${breakout.name}" has no PCB region`);let pcbGroup=breakout.root.db.pcb_group.get(breakout.pcb_group_id);if(!pcbGroup||!pcbGroup.width||!pcbGroup.height)throw new Error(`Automatic breakout "${breakout.name}" has invalid PCB region bounds`);let bounds={minX:pcbGroup.center.x-pcbGroup.width/2,maxX:pcbGroup.center.x+pcbGroup.width/2,minY:pcbGroup.center.y-pcbGroup.height/2,maxY:pcbGroup.center.y+pcbGroup.height/2},center2={x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},endpointBySourceTraceId=new Map,sourcePortIdBySourceTraceId=new Map;for(let breakoutPoint of breakout.children.filter(child=>child instanceof AutoplacedBreakoutPoint)){let matchedPort=breakoutPoint.matchedPort;if(!matchedPort?.pcb_port_id||!matchedPort.source_port_id)throw new Error(`Automatic breakout "${breakout.name}" is missing a PCB endpoint`);let sourceTraceId=breakoutPoint.matchedSourceTraceId;if(!sourceTraceId){let matchingSourceTraces=breakout.root.db.source_trace.list().filter(sourceTrace=>sourceTrace.connected_source_port_ids.includes(matchedPort.source_port_id));if(matchingSourceTraces.length===0)throw new Error(`Automatic breakout "${breakout.name}" has a point without a source trace identity`);let boundaryCrossingSourceTraces=matchingSourceTraces.filter(sourceTrace=>sourceTrace.connected_source_port_ids.some(sourcePortId=>{if(sourcePortId===matchedPort.source_port_id)return!1;let pcbPort2=breakout.root.db.pcb_port.getWhere({source_port_id:sourcePortId});return!pcbPort2||pcbPort2.pcb_group_id===breakout.pcb_group_id?!1:!(pcbPort2.x>=bounds.minX&&pcbPort2.x<=bounds.maxX&&pcbPort2.y>=bounds.minY&&pcbPort2.y<=bounds.maxY)}));sourceTraceId=(boundaryCrossingSourceTraces.length>0?boundaryCrossingSourceTraces:matchingSourceTraces).slice().sort((first,second)=>first.source_trace_id.localeCompare(second.source_trace_id))[0].source_trace_id,breakoutPoint.matchedSourceTraceId=sourceTraceId}if(endpointBySourceTraceId.has(sourceTraceId))throw new Error(`Connection "${sourceTraceId}" has duplicate endpoint for region "${breakout.pcb_group_id}"`);let pcbPort=breakout.root.db.pcb_port.get(matchedPort.pcb_port_id);if(!pcbPort)throw new Error(`Connection "${sourceTraceId}" references unknown PCB endpoint "${matchedPort.pcb_port_id}"`);if(pcbPort.pcb_group_id!==breakout.pcb_group_id)throw new Error(`Connection "${sourceTraceId}" endpoint references unknown region "${pcbPort.pcb_group_id??"unassigned"}" instead of "${breakout.pcb_group_id}"`);if(pcbPort.x===void 0||pcbPort.y===void 0)throw new Error(`Connection "${sourceTraceId}" is missing endpoint coordinates for region "${breakout.pcb_group_id}"`);endpointBySourceTraceId.set(sourceTraceId,{regionId:breakout.pcb_group_id,position:{x:pcbPort.x,y:pcbPort.y}}),sourcePortIdBySourceTraceId.set(sourceTraceId,matchedPort.source_port_id)}return{breakout,pcbGroupId:breakout.pcb_group_id,bounds,center:center2,endpointBySourceTraceId,sourcePortIdBySourceTraceId}},sortRegionsByPlacement=regions=>{let xCoordinates=regions.map(region=>region.center.x),yCoordinates=regions.map(region=>region.center.y),xSpan=Math.max(...xCoordinates)-Math.min(...xCoordinates),ySpan=Math.max(...yCoordinates)-Math.min(...yCoordinates),horizontalPlacement=xSpan>=ySpan;return regions.sort((firstRegion,secondRegion)=>{if(horizontalPlacement){let xDifference=firstRegion.center.x-secondRegion.center.x;if(xDifference!==0)return xDifference;let yDifference=firstRegion.center.y-secondRegion.center.y;if(yDifference!==0)return yDifference}else{let yDifference=firstRegion.center.y-secondRegion.center.y;if(yDifference!==0)return yDifference;let xDifference=firstRegion.center.x-secondRegion.center.x;if(xDifference!==0)return xDifference}return firstRegion.breakout.name.localeCompare(secondRegion.breakout.name)}),{regions,horizontalPlacement}},getFacingEdge=({region,regionIndex,regions,horizontalPlacement,singleRegionPreferredEdge})=>{if(regions.length===1&&singleRegionPreferredEdge)return singleRegionPreferredEdge;let otherRegions=regions.filter(candidate=>candidate!==region),otherCenter=otherRegions.reduce((sum,candidate)=>({x:sum.x+candidate.center.x/otherRegions.length,y:sum.y+candidate.center.y/otherRegions.length}),{x:0,y:0});return horizontalPlacement?otherCenter.x>region.center.x?"right":otherCenter.x<region.center.x?"left":regionIndex<regions.length/2?"right":"left":otherCenter.y>region.center.y?"top":otherCenter.y<region.center.y?"bottom":regionIndex<regions.length/2?"top":"bottom"},getSingleRegionPreferredEdge=({region,sourceTraces})=>{let root=region.breakout.root;if(!root)return;let internalSourcePortIds=new Set(region.sourcePortIdBySourceTraceId.values()),externalPcbPorts=new Map;for(let sourceTrace of sourceTraces)if(sourceTrace.connected_source_port_ids.some(sourcePortId=>internalSourcePortIds.has(sourcePortId)))for(let sourcePortId of sourceTrace.connected_source_port_ids){if(internalSourcePortIds.has(sourcePortId))continue;let pcbPort=root.db.pcb_port.getWhere({source_port_id:sourcePortId});!pcbPort?.pcb_port_id||pcbPort.x===void 0||pcbPort.y===void 0||pcbPort.x>=region.bounds.minX&&pcbPort.x<=region.bounds.maxX&&pcbPort.y>=region.bounds.minY&&pcbPort.y<=region.bounds.maxY||externalPcbPorts.set(pcbPort.pcb_port_id,{x:pcbPort.x,y:pcbPort.y})}if(externalPcbPorts.size===0)return;let distanceToEdge=(target,edge)=>{let edgePoint=edge==="left"||edge==="right"?{x:edge==="left"?region.bounds.minX:region.bounds.maxX,y:Math.max(region.bounds.minY,Math.min(region.bounds.maxY,target.y))}:{x:Math.max(region.bounds.minX,Math.min(region.bounds.maxX,target.x)),y:edge==="bottom"?region.bounds.minY:region.bounds.maxY};return Math.hypot(target.x-edgePoint.x,target.y-edgePoint.y)},edges=["right","left","top","bottom"];return edges.reduce((bestEdge,edge)=>{let bestCost=[...externalPcbPorts.values()].reduce((sum,target)=>sum+distanceToEdge(target,bestEdge),0);return[...externalPcbPorts.values()].reduce((sum,target)=>sum+distanceToEdge(target,edge),0)<bestCost?edge:bestEdge},edges[0])},getSourceTraceForConnectionOrThrow=({connectionOwner,connectionOwnerLabel,connectionSelector,sourceTraces})=>{let matchingSourceTraces=sourceTraces.filter(sourceTrace=>sourceTrace.name===connectionSelector);if(matchingSourceTraces.length===0){let selectedPort=connectionOwner.getSubcircuit().selectOne(connectionSelector,{type:"port"});selectedPort?.source_port_id&&(matchingSourceTraces=sourceTraces.filter(sourceTrace=>sourceTrace.connected_source_port_ids.includes(selectedPort.source_port_id)))}if(matchingSourceTraces.length===0)throw new Error(`Could not resolve "${connectionSelector}" in ${connectionOwnerLabel}`);if(matchingSourceTraces.length>1)throw new Error(`Connection "${connectionSelector}" resolves to multiple source traces in ${connectionOwnerLabel}`);return matchingSourceTraces[0]},getImplicitBreakoutSolverBuses=({routingScope,sourceTraces,coordinatedSourceTraceIds,availableLayers})=>{let solverBuses=[],subcircuitId=routingScope.getSubcircuit().subcircuit_id;for(let bus of routingScope.selectAll("bus")){if(bus.getSubcircuit().subcircuit_id!==subcircuitId)continue;let connectionIds=[];for(let connectionSelector of bus._parsedProps.connections){let sourceTrace=getSourceTraceForConnectionOrThrow({connectionOwner:bus,connectionOwnerLabel:`bus "${bus.name}"`,connectionSelector,sourceTraces});coordinatedSourceTraceIds.has(sourceTrace.source_trace_id)&&connectionIds.push(sourceTrace.source_trace_id)}if(connectionIds.length===0)continue;let solverBus={busId:bus.name,connectionIds};if(bus._parsedProps.preferredLayer!==void 0)solverBus={...solverBus,targetLayers:[bus._parsedProps.preferredLayer]};else if(bus._parsedProps.preferredLayers!==void 0)solverBus={...solverBus,targetLayers:bus._parsedProps.preferredLayers};else{let targetLayers=bus._parsedProps.pcbAllowedLayers??availableLayers;solverBus={...solverBus,targetLayers:[...new Set(targetLayers)]}}solverBuses.push(solverBus)}return solverBuses},getDifferentialPairSourceTraces=({routingScope,sourceTraces})=>{let subcircuitId=routingScope.getSubcircuit().subcircuit_id,pairs32=[];for(let differentialPair of routingScope.selectAll("differentialpair")){if(differentialPair.getSubcircuit().subcircuit_id!==subcircuitId)continue;let positiveSourceTrace=getSourceTraceForConnectionOrThrow({connectionOwner:differentialPair,connectionOwnerLabel:`differential pair "${differentialPair.name}"`,connectionSelector:differentialPair._parsedProps.positiveConnection,sourceTraces}),negativeSourceTrace=getSourceTraceForConnectionOrThrow({connectionOwner:differentialPair,connectionOwnerLabel:`differential pair "${differentialPair.name}"`,connectionSelector:differentialPair._parsedProps.negativeConnection,sourceTraces});pairs32.push({differentialPair,positiveSourceTraceId:positiveSourceTrace.source_trace_id,negativeSourceTraceId:negativeSourceTrace.source_trace_id})}return pairs32},getBoundaryPointSpacing=breakout=>{let board=breakout.root?.db.pcb_board.list()[0],traceWidth=board?.min_trace_width??.15,traceToPadClearance=board?.min_trace_to_pad_edge_clearance??.2,viaPadDiameter=board?.min_via_pad_diameter??.3;return getFanoutBoundaryPointSpacing({traceWidth,traceToPadClearance,viaPadDiameter})},getCoordinatedFanoutLayers=({routingScope,automaticBreakouts})=>{let coordinatedLayers=getBoardAvailableLayers(routingScope._getSubcircuitLayerCount());for(let automaticBreakout of automaticBreakouts){let fanoutRoutingLayers=automaticBreakout._parsedProps.fanoutRoutingLayers?.map(String);if(!fanoutRoutingLayers)continue;let fanoutLayerSet=new Set(fanoutRoutingLayers);coordinatedLayers=coordinatedLayers.filter(layer=>fanoutLayerSet.has(layer))}if(coordinatedLayers.length===0)throw new Error(`Automatic breakouts in routing scope "${routingScope.name}" have no shared fanout routing layer`);return coordinatedLayers},createImplicitBreakoutPointSolverContext=breakout=>{if(!breakout.root)throw new Error(`Automatic breakout "${breakout.name}" has no circuit root`);let routingScope=getRoutingScopeOrThrow(breakout),automaticBreakouts=getAutomaticBreakouts(routingScope,breakout),regionIds=new Set,collectedRegions=automaticBreakouts.map(automaticBreakout=>{let region=collectBreakoutRegionGeometry(automaticBreakout);if(regionIds.has(region.pcbGroupId))throw new Error(`Duplicate automatic breakout region "${region.pcbGroupId}"`);return regionIds.add(region.pcbGroupId),region}),{regions,horizontalPlacement}=sortRegionsByPlacement(collectedRegions),sourceTraceIds=new Set;for(let region of regions)for(let sourceTraceId of region.endpointBySourceTraceId.keys())sourceTraceIds.add(sourceTraceId);let sourceTraces=breakout.root.db.source_trace.list().filter(sourceTrace=>sourceTrace.subcircuit_id===routingScope.getSubcircuit().subcircuit_id),sourceTraceById=new Map;for(let sourceTrace of sourceTraces){if(sourceTraceById.has(sourceTrace.source_trace_id))throw new Error(`Duplicate connection identity "${sourceTrace.source_trace_id}"`);sourceTraceById.set(sourceTrace.source_trace_id,sourceTrace)}let sortedSourceTraceIds=[...sourceTraceIds].sort((firstSourceTraceId,secondSourceTraceId)=>{let firstName=sourceTraceById.get(firstSourceTraceId)?.name??firstSourceTraceId,secondName=sourceTraceById.get(secondSourceTraceId)?.name??secondSourceTraceId,nameDifference=firstName.localeCompare(secondName);return nameDifference!==0?nameDifference:firstSourceTraceId.localeCompare(secondSourceTraceId)});for(let sourceTraceId of sortedSourceTraceIds){if(!sourceTraceById.has(sourceTraceId))throw new Error(`Unknown connection identity "${sourceTraceId}"`);for(let region of regions)if(!region.endpointBySourceTraceId.has(sourceTraceId))throw new Error(`Connection "${sourceTraceId}" is missing endpoint for region "${region.pcbGroupId}"`)}let buses=getImplicitBreakoutSolverBuses({routingScope,sourceTraces,coordinatedSourceTraceIds:sourceTraceIds,availableLayers:getCoordinatedFanoutLayers({routingScope,automaticBreakouts})}),endpointsBySourceTraceId=new Map;for(let sourceTraceId of sortedSourceTraceIds)endpointsBySourceTraceId.set(sourceTraceId,regions.map(region=>region.endpointBySourceTraceId.get(sourceTraceId)));let differentialPairBySourceTraceId=new Map;for(let pair of getDifferentialPairSourceTraces({routingScope,sourceTraces})){let positiveIsCoordinated=sourceTraceIds.has(pair.positiveSourceTraceId),negativeIsCoordinated=sourceTraceIds.has(pair.negativeSourceTraceId);if(positiveIsCoordinated!==negativeIsCoordinated)throw new Error(`Differential pair "${pair.differentialPair.name}" is missing one coordinated member`);if(positiveIsCoordinated){if(differentialPairBySourceTraceId.has(pair.positiveSourceTraceId)||differentialPairBySourceTraceId.has(pair.negativeSourceTraceId))throw new Error("A connection belongs to multiple differential pairs");differentialPairBySourceTraceId.set(pair.positiveSourceTraceId,pair),differentialPairBySourceTraceId.set(pair.negativeSourceTraceId,pair)}}let connections=[],addedDifferentialPairs=new Set;for(let sourceTraceId of sortedSourceTraceIds){let differentialPair=differentialPairBySourceTraceId.get(sourceTraceId);if(!differentialPair){connections.push({connectionId:sourceTraceId,endpoints:endpointsBySourceTraceId.get(sourceTraceId)});continue}addedDifferentialPairs.has(differentialPair.differentialPair)||(addedDifferentialPairs.add(differentialPair.differentialPair),connections.push({type:"differential",connections:[{connectionId:differentialPair.positiveSourceTraceId,endpoints:endpointsBySourceTraceId.get(differentialPair.positiveSourceTraceId)},{connectionId:differentialPair.negativeSourceTraceId,endpoints:endpointsBySourceTraceId.get(differentialPair.negativeSourceTraceId)}]}))}let sourcePortIdByConnectionIdByRegionId=new Map,singleRegionPreferredEdge=regions.length===1?getSingleRegionPreferredEdge({region:regions[0],sourceTraces}):void 0;return{input:{regions:regions.map((region,regionIndex)=>(sourcePortIdByConnectionIdByRegionId.set(region.pcbGroupId,region.sourcePortIdBySourceTraceId),{regionId:region.pcbGroupId,bounds:region.bounds,edge:getFacingEdge({region,regionIndex,regions,horizontalPlacement,singleRegionPreferredEdge})})),connections,buses,boundaryPointSpacing:getBoundaryPointSpacing(breakout)},sourcePortIdByConnectionIdByRegionId}},cachedSolutionsByRoutingScope=new WeakMap,solveScope=(breakout,solverFn)=>{let context=createImplicitBreakoutPointSolverContext(breakout),output=solverFn(context.input);if(output instanceof Promise)throw new Error("Implicit breakout point solvers must return synchronously during PCB layout");let expectedConnectionCount=0;for(let connection of context.input.connections){if("type"in connection){expectedConnectionCount+=connection.connections.length;continue}expectedConnectionCount+=1}let breakoutPointsByRegionId=new Map,outputPointKeys=new Set;for(let region of context.input.regions)breakoutPointsByRegionId.set(region.regionId,[]);for(let breakoutPoint of output.breakoutPoints){let regionBreakoutPoints=breakoutPointsByRegionId.get(breakoutPoint.regionId);if(!regionBreakoutPoints)throw new Error(`Implicit breakout point solver returned unknown region "${breakoutPoint.regionId}"`);let outputPointKey=`${breakoutPoint.regionId}:${breakoutPoint.connectionId}`;if(outputPointKeys.has(outputPointKey))throw new Error(`Implicit breakout point solver returned duplicate endpoint for connection "${breakoutPoint.connectionId}" in region "${breakoutPoint.regionId}"`);outputPointKeys.add(outputPointKey);let sourcePortId=context.sourcePortIdByConnectionIdByRegionId.get(breakoutPoint.regionId)?.get(breakoutPoint.connectionId);if(!sourcePortId)throw new Error(`Implicit breakout point solver returned unknown connection "${breakoutPoint.connectionId}" for region "${breakoutPoint.regionId}"`);regionBreakoutPoints.push({sourcePortId,sourceTraceId:breakoutPoint.connectionId,layer:breakoutPoint.layer,x:breakoutPoint.x,y:breakoutPoint.y})}for(let[regionId,regionBreakoutPoints]of breakoutPointsByRegionId)if(regionBreakoutPoints.length!==expectedConnectionCount)throw new Error(`Implicit breakout point solver output is missing endpoints for region "${regionId}"`);return{breakoutPointsByRegionId}},solveImplicitBreakoutPoints=(breakout,solverFn)=>{let routingScope=breakout.parent;if(!routingScope||!breakout.pcb_group_id)throw new Error(`Automatic breakout "${breakout.name}" has no coordinated PCB region`);let cachedSolutions=cachedSolutionsByRoutingScope.get(routingScope);(!cachedSolutions||cachedSolutions.solverFn!==solverFn)&&(cachedSolutions={solverFn,solutions:[]},cachedSolutionsByRoutingScope.set(routingScope,cachedSolutions));let solution=cachedSolutions.solutions.find(candidateSolution=>candidateSolution.breakoutPointsByRegionId.has(breakout.pcb_group_id));solution||(solution=solveScope(breakout,solverFn),cachedSolutions.solutions.push(solution));let breakoutPoints=solution.breakoutPointsByRegionId.get(breakout.pcb_group_id);if(!breakoutPoints)throw new Error(`Automatic breakout "${breakout.name}" references unknown implicit-breakout region "${breakout.pcb_group_id}"`);return breakoutPoints},Breakout=class extends Group5{get isRoutingDirective(){return!0}get config(){return{...super.config,zodProps:breakoutProps}}doInitialCreateAutoplacedBreakoutPoints(){let portsInBreakout=this.selectAll("port"),breakoutPortSet=new Set(portsInBreakout),manualBreakoutPoints=this.children.filter(c3=>c3 instanceof BreakoutPoint),manuallyMappedPorts=new Set(manualBreakoutPoints.map(bp3=>(bp3._matchConnection(),bp3.matchedPort)).filter(Boolean)),allTraces=this.getSubcircuit().selectAll("trace"),autoPlacedPorts=new Set;for(let trace of allTraces){let result=trace._findConnectedPorts();if(!(!result.allPortsFound||!result.ports))for(let port of result.ports){let isInside=breakoutPortSet.has(port),hasOutsidePort=result.ports.some(p3=>!breakoutPortSet.has(p3));if(!isInside||!hasOutsidePort||manuallyMappedPorts.has(port)||autoPlacedPorts.has(port))continue;autoPlacedPorts.add(port);let breakoutPoint=new AutoplacedBreakoutPoint({});breakoutPoint.matchedPort=port,breakoutPoint.matchedSourceTraceId=trace.source_trace_id,this.add(breakoutPoint)}}}doInitialPcbAutoplaceBreakoutPoints(){if(this.root?.pcbDisabled)return;let ownAutorouter=this.props.autorouter,inheritedAutorouter=ownAutorouter===void 0?this.parent?.getInheritedProperty("autorouter"):void 0,implicitBreakoutPointSolverFn=typeof ownAutorouter=="object"?ownAutorouter.implicitBreakoutPointSolverFn:typeof inheritedAutorouter=="object"?inheritedAutorouter.implicitBreakoutPointSolverFn:void 0,autoBreakoutPoints=this.children.filter(child=>child instanceof AutoplacedBreakoutPoint);if(autoBreakoutPoints.length===0||!this.root||!this.pcb_group_id)return;let pcbGroup=this.root.db.pcb_group.get(this.pcb_group_id);if(!pcbGroup?.width||!pcbGroup.height)return;let bounds={minX:pcbGroup.center.x-pcbGroup.width/2,maxX:pcbGroup.center.x+pcbGroup.width/2,minY:pcbGroup.center.y-pcbGroup.height/2,maxY:pcbGroup.center.y+pcbGroup.height/2},solvedBreakoutPoints;try{solvedBreakoutPoints=solveImplicitBreakoutPoints(this,implicitBreakoutPointSolverFn??defaultImplicitBreakoutPointSolverFn)}catch(error2){if(implicitBreakoutPointSolverFn||!reportWindingBreakoutInfeasibleError(this,error2))throw error2;return}let BOUNDARY_INSET_MM=1e-4,insetWithinBounds=(x6,y2)=>({x:Math.max(bounds.minX+BOUNDARY_INSET_MM,Math.min(bounds.maxX-BOUNDARY_INSET_MM,x6)),y:Math.max(bounds.minY+BOUNDARY_INSET_MM,Math.min(bounds.maxY-BOUNDARY_INSET_MM,y2))});for(let solvedPoint of solvedBreakoutPoints){let matchingBreakoutPoint=autoBreakoutPoints.find(child=>child.matchedPort?.source_port_id===solvedPoint.sourcePortId);if(matchingBreakoutPoint){let insetPoint=insetWithinBounds(solvedPoint.x,solvedPoint.y);matchingBreakoutPoint._applySolvedBreakoutPoint({sourceTraceId:solvedPoint.sourceTraceId,layer:solvedPoint.layer,position:insetPoint})}}}doInitialPcbPrimitiveRender(){super.doInitialPcbPrimitiveRender()}doInitialPcbPlacementDesignRuleChecks(){Breakout_doInitialPcbPlacementDesignRuleChecks(this)}},SilkscreenGraphic=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_graphic_id",null);__publicField(this,"pcb_silkscreen_graphic_ids",[]);__publicField(this,"pcb_silkscreen_path_ids",[]);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenGraphic",zodProps:silkscreenGraphicProps}}doInitialPcbPrimitiveRender(){this.root?.pcbDisabled||this._queueAsyncEffect("SilkscreenGraphicRender",async()=>{if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),layer=maybeFlipLayer(props.layer??"top");if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for SilkscreenGraphic. Must be "top" or "bottom".`);let sourceImage=await loadImageSource(props.imageUrl);if(sourceImage.mimetype!==SVG_MIMETYPE&&sourceImage.mimetype!==PNG_MIMETYPE)throw new Error(`Unsupported imageUrl for SilkscreenGraphic: "${props.imageUrl}". Expected an SVG or PNG image.`);let imageAsset={project_relative_path:sourceImage.projectRelativePath,url:sourceImage.dataUrl,mimetype:sourceImage.mimetype},brepShapes=sourceImage.mimetype===SVG_MIMETYPE?getSvgBRepShapes({svg:sourceImage.text,width:props.width,height:props.height,transform:this._computePcbGlobalTransformBeforeLayout()}):[this.getPlacementBoxBRepShape()],pcbComponentId=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??"";for(let brepShape of brepShapes){let graphic=db2.insert({type:"pcb_silkscreen_graphic",pcb_component_id:pcbComponentId,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,subcircuit_id:this.getSubcircuit()?.subcircuit_id??void 0,layer,shape:"brep",brep_shape:brepShape,image_asset:imageAsset});this.pcb_silkscreen_graphic_ids.push(graphic.pcb_silkscreen_graphic_id)}this.pcb_silkscreen_graphic_id=this.pcb_silkscreen_graphic_ids[0]??null,sourceImage.mimetype===SVG_MIMETYPE&&this.insertRenderableSilkscreenPaths(sourceImage.text,layer)})}insertRenderableSilkscreenPaths(svg,layer){let{db:db2}=this.root,{_parsedProps:props}=this,transform7=this._computePcbGlobalTransformBeforeLayout(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??"";for(let route of getTransformedSvgPathRoutes({svg,width:props.width,height:props.height,transform:transform7})){if(route.length<2)continue;let path=db2.pcb_silkscreen_path.insert({pcb_component_id,layer,route,stroke_width:Math.max(Math.min(props.width,props.height)/60,.05),subcircuit_id:this.getSubcircuit()?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_silkscreen_path_ids.push(path.pcb_silkscreen_path_id)}}getPcbSize(){let{_parsedProps:props}=this;return{width:props.width,height:props.height}}getPlacementBoxBRepShape(){let{_parsedProps:props}=this,halfWidth=props.width/2,halfHeight=props.height/2,transform7=this._computePcbGlobalTransformBeforeLayout();return{outer_ring:{vertices:ensureClockwise([{x:-halfWidth,y:halfHeight},{x:halfWidth,y:halfHeight},{x:halfWidth,y:-halfHeight},{x:-halfWidth,y:-halfHeight}]).map(point6=>applyToPoint2(transform7,point6))},inner_rings:[]}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,moveVertex=vertex=>({...vertex,x:vertex.x+deltaX,y:vertex.y+deltaY});for(let graphicId of this.pcb_silkscreen_graphic_ids){let graphic=db2.pcb_silkscreen_graphic.get(graphicId);graphic&&db2.pcb_silkscreen_graphic.update(graphicId,{brep_shape:{outer_ring:{vertices:graphic.brep_shape.outer_ring.vertices.map(moveVertex)},inner_rings:graphic.brep_shape.inner_rings.map(ring3=>({vertices:ring3.vertices.map(moveVertex)}))}})}for(let pathId of this.pcb_silkscreen_path_ids){let path=db2.pcb_silkscreen_path.get(pathId);path&&db2.pcb_silkscreen_path.update(pathId,{route:path.route.map(point6=>({...point6,x:point6.x+deltaX,y:point6.y+deltaY}))})}}},Fiducial=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_smtpad_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"Fiducial",zodProps:fiducialProps,sourceFtype:"simple_fiducial"}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,position4=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_smtpad3=db2.pcb_smtpad.insert({pcb_component_id,layer:maybeFlipLayer(props.layer||"top"),shape:"circle",x:position4.x,y:position4.y,radius:distance.parse(props.padDiameter)/2,soldermask_margin:props.soldermaskPullback?distance.parse(props.soldermaskPullback):distance.parse(props.padDiameter)/2,is_covered_with_solder_mask:!0});this.pcb_smtpad_id=pcb_smtpad3.pcb_smtpad_id}getPcbSize(){let{_parsedProps:props}=this,d3=distance.parse(props.padDiameter);return{width:d3,height:d3}}_setPositionFromLayout(newCenter){if(!this.pcb_smtpad_id)return;let{db:db2}=this.root;db2.pcb_smtpad.update(this.pcb_smtpad_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db:db2}=this.root;if(!this.pcb_smtpad_id)return;let pad2=db2.pcb_smtpad.get(this.pcb_smtpad_id);pad2&&(pad2.shape==="rect"||pad2.shape==="circle"||pad2.shape==="rotated_rect"||pad2.shape==="pill"?this._setPositionFromLayout({x:pad2.x+deltaX,y:pad2.y+deltaY}):pad2.shape==="polygon"&&db2.pcb_smtpad.update(this.pcb_smtpad_id,{points:pad2.points.map(p3=>({x:p3.x+deltaX,y:p3.y+deltaY}))}))}},EPSILON8=1e-9,isWireRoutePoint=routePoint=>routePoint.route_type==="wire",isPointOnSegment5=(p3,a6,b6)=>{let cross32=(p3.y-a6.y)*(b6.x-a6.x)-(p3.x-a6.x)*(b6.y-a6.y);if(Math.abs(cross32)>EPSILON8)return!1;let dot3=(p3.x-a6.x)*(b6.x-a6.x)+(p3.y-a6.y)*(b6.y-a6.y);if(dot3<-EPSILON8)return!1;let squaredLength=(b6.x-a6.x)**2+(b6.y-a6.y)**2;return!(dot3-squaredLength>EPSILON8)},isPointInRing=(point6,ring3)=>{if(ring3.length<3)return!1;let inside2=!1,previous=ring3[ring3.length-1];for(let current3 of ring3){if(isPointOnSegment5(point6,previous,current3))return!0;current3.y>point6.y!=previous.y>point6.y&&point6.x<(previous.x-current3.x)*(point6.y-current3.y)/(previous.y-current3.y)+current3.x&&(inside2=!inside2),previous=current3}return inside2},isPointInRectPour=(p3,pour)=>{let{center:center2,width,height}=pour,rotationRad=(pour.rotation??0)*Math.PI/180,cosR=Math.cos(-rotationRad),sinR=Math.sin(-rotationRad),dx3=p3.x-center2.x,dy3=p3.y-center2.y,localX=dx3*cosR-dy3*sinR,localY=dx3*sinR+dy3*cosR;return Math.abs(localX)<=width/2+EPSILON8&&Math.abs(localY)<=height/2+EPSILON8},isPointInBrepPour=(p3,pour)=>{let outerRing=pour.brep_shape.outer_ring.vertices.map(v6=>({x:v6.x,y:v6.y}));if(!isPointInRing(p3,outerRing))return!1;for(let innerRing of pour.brep_shape.inner_rings){let points=innerRing.vertices.map(v6=>({x:v6.x,y:v6.y}));if(isPointInRing(p3,points))return!1}return!0},isPointInCopperPour=(point6,pour)=>pour.shape==="rect"?isPointInRectPour(point6,pour):pour.shape==="brep"?isPointInBrepPour(point6,pour):!1,isTraceConnectedToSourceNet=(trace,sourceNetId,sourceTraceById)=>{if(trace.source_trace_id===sourceNetId)return!0;if(!trace.source_trace_id)return!1;let sourceTrace=sourceTraceById.get(trace.source_trace_id);return sourceTrace?sourceTrace.connected_source_net_ids.includes(sourceNetId):!1},isSegmentFullyInsideCopperPour=(start,end,pour)=>{let dx3=end.x-start.x,dy3=end.y-start.y;return Math.hypot(dx3,dy3)<=EPSILON8?!1:[0,.25,.5,.75,1].every(t53=>isPointInCopperPour({x:start.x+dx3*t53,y:start.y+dy3*t53},pour))},markTraceSegmentsInsideCopperPour=({db:db2,copperPour})=>{if(!copperPour.source_net_id)return;let sourceTraceById=new Map(db2.source_trace.list().map(sourceTrace=>[sourceTrace.source_trace_id,sourceTrace]));for(let trace of db2.pcb_trace.list()){if(!isTraceConnectedToSourceNet(trace,copperPour.source_net_id,sourceTraceById))continue;let routeChanged=!1,nextRoute=trace.route.map(routePoint=>({...routePoint}));for(let i6=0;i6<nextRoute.length-1;i6++){let fromRoutePoint=nextRoute[i6],toRoutePoint=nextRoute[i6+1];!fromRoutePoint||!toRoutePoint||!isWireRoutePoint(fromRoutePoint)||!isWireRoutePoint(toRoutePoint)||fromRoutePoint.layer!==copperPour.layer||toRoutePoint.layer!==copperPour.layer||isSegmentFullyInsideCopperPour({x:fromRoutePoint.x,y:fromRoutePoint.y},{x:toRoutePoint.x,y:toRoutePoint.y},copperPour)&&(fromRoutePoint.is_inside_copper_pour=!0,fromRoutePoint.copper_pour_id=copperPour.pcb_copper_pour_id,toRoutePoint.is_inside_copper_pour=!0,toRoutePoint.copper_pour_id=copperPour.pcb_copper_pour_id,routeChanged=!0)}routeChanged&&db2.pcb_trace.update(trace.pcb_trace_id,{route:nextRoute})}},pendingCopperPourRenders=new WeakMap,DEFAULT_THERMAL_RELIEF_SPOKE_WIDTH_MM=.3,renderAllCopperPoursForSubcircuit=async subcircuit=>{if(!subcircuit.root)return;let{db:db2}=subcircuit.root,copperPours=subcircuit.selectAll("copperpour").filter(copperPour=>copperPour.getSubcircuit()===subcircuit),resolvedCopperPours=[];for(let copperPour of copperPours){let{_parsedProps:props}=copperPour,sourceNetId=subcircuit.selectOne(props.connectsTo)?.source_net_id;if(!sourceNetId){copperPour.renderError(`Net "${props.connectsTo}" not found for copper pour`);continue}resolvedCopperPours.push({copperPour,sourceNetId})}if(resolvedCopperPours.length===0)return;let circuitJson=db2.toArray(),pcbBoard=circuitJson.find(element=>element.type==="pcb_board"),resolvedPcbBoardOutline=pcbBoard?.outline?.length?pcbBoard.outline:void 0;if(!resolvedPcbBoardOutline&&pcbBoard?.width!==void 0&&pcbBoard.height!==void 0){let{center:center2,width,height}=pcbBoard;resolvedPcbBoardOutline=[{x:center2.x-width/2,y:center2.y-height/2},{x:center2.x+width/2,y:center2.y-height/2},{x:center2.x+width/2,y:center2.y+height/2},{x:center2.x-width/2,y:center2.y+height/2}]}let inputProblem=convertCircuitJsonToInputProblem(circuitJson,resolvedCopperPours.map(({copperPour,sourceNetId})=>{let{_parsedProps:props}=copperPour,clearance=props.clearance??.2;return{layer:props.layer,subcircuit_id:subcircuit.subcircuit_id??void 0,source_net_id:sourceNetId,pad_margin:props.padMargin??clearance,trace_margin:props.traceMargin??clearance,pour_margin:clearance,board_edge_margin:props.boardEdgeMargin??clearance,cutout_margin:props.cutoutMargin??clearance,...props.useThermalReliefs?{use_thermal_reliefs:!0,thermal_relief_spoke_width:DEFAULT_THERMAL_RELIEF_SPOKE_WIDTH_MM}:{},outline:props.outline??resolvedPcbBoardOutline}}));await initializeManifoldGeometry();let solver=new CopperPourPipelineSolver(inputProblem);subcircuit.root.emit("solver:started",{type:"solver:started",solverName:"CopperPourPipelineSolver",solverParams:inputProblem,solverConstructorArgs:[inputProblem],componentName:subcircuit.getString()});let{brep_shapes_by_region}=solver.getOutput();for(let[regionIndex,{copperPour,sourceNetId}]of resolvedCopperPours.entries()){let{_parsedProps:props}=copperPour,coveredWithSolderMask=props.coveredWithSolderMask??!1;for(let brepShape of brep_shapes_by_region[regionIndex]??[]){let insertedPour=db2.pcb_copper_pour.insert({shape:"brep",layer:props.layer,brep_shape:brepShape,source_net_id:sourceNetId,subcircuit_id:subcircuit.subcircuit_id??void 0,covered_with_solder_mask:coveredWithSolderMask});markTraceSegmentsInsideCopperPour({db:db2,copperPour:insertedPour})}}};function CopperPour_doInitialPcbCopperPourRender(copperPour){copperPour.root?.pcbDisabled||copperPour._queueAsyncEffect("PcbCopperPourRender",async()=>{let subcircuit=copperPour.getSubcircuit(),pendingRender=pendingCopperPourRenders.get(subcircuit);if(pendingRender){await pendingRender;return}let renderPromise=renderAllCopperPoursForSubcircuit(subcircuit);pendingCopperPourRenders.set(subcircuit,renderPromise);try{await renderPromise}finally{pendingCopperPourRenders.delete(subcircuit)}})}var CopperPour=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"CopperPour",zodProps:copperPourProps}}getPcbSize(){return{width:0,height:0}}doInitialCreateNetsFromProps(){let{_parsedProps:props}=this;createNetsFromProps(this,[props.connectsTo])}doInitialPcbCopperPourRender(){CopperPour_doInitialPcbCopperPourRender(this)}},AssemblyDevice=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isAssemblyDeviceContainer",!0)}get config(){return{componentName:"AssemblyDevice",zodProps:assemblyDeviceProps}}doInitialAssignNameToUnnamedComponents(){}computeSchematicGlobalTransform(){return identity()}_computePcbGlobalTransformBeforeLayout(){return identity()}},getModelReachAboveOrigin=({cad,authoredModel})=>{let bounds=cad.model_bounds??authoredModel?.modelBounds,origin=cad.model_origin_position??authoredModel?.modelOriginPosition;if(!bounds?.min||!bounds?.max||!origin)return;let normal=cad.model_board_normal_direction??authoredModel?.modelBoardNormalDirection??"z+",axis=normal[0];if(axis!=="x"&&axis!=="y"&&axis!=="z")return;let min=bounds.min[axis],max2=bounds.max[axis],at3=origin[axis];if(min===void 0||max2===void 0||at3===void 0)return;let reach=normal.endsWith("-")?at3-min:max2-at3;return Number.isFinite(reach)&&reach>=0?reach:void 0},getComponentBody=({owner,pcbComponent,cadComponent,boardSurfaceZ})=>{let cadModelProp2=owner?._parsedProps?.cadModel,authoredModel=cadModelProp2&&typeof cadModelProp2=="object"?cadModelProp2:void 0,size3=cadComponent?.size??authoredModel?.size,x6=size3?.x,y2=size3?.y,z18=size3?.z,reach=cadComponent?getModelReachAboveOrigin({cad:cadComponent,authoredModel}):void 0,originZ=cadComponent?.position?.z,aboveBoardHeight=reach!==void 0&&originZ!==void 0?reach+Math.abs(originZ-boardSurfaceZ):void 0;return{size:x6!==void 0&&y2!==void 0?{x:x6,y:y2,z:z18}:void 0,aboveBoardHeight,rotation:cadComponent?.rotation?.z??pcbComponent.rotation??0,footprint:{width:pcbComponent.width,height:pcbComponent.height}}},getNearestBoardWall=({point:point6,board})=>{let halfWidth=(board.width??0)/2,halfHeight=(board.height??0)/2,distances=[["x_neg",Math.abs(point6.x-(board.center.x-halfWidth))],["x_pos",Math.abs(point6.x-(board.center.x+halfWidth))],["y_neg",Math.abs(point6.y-(board.center.y-halfHeight))],["y_pos",Math.abs(point6.y-(board.center.y+halfHeight))]];return distances.sort((a6,b6)=>a6[1]-b6[1]),distances[0][0]},getSolverWall=boardWall=>boardWall,INSERTION_DIRECTION_TO_BOARD_WALL={from_top:"y_pos",from_bottom:"y_neg",from_left:"x_neg",from_right:"x_pos"},getFdmEnclosureSolverInput=(apertureComponent,{board,pcbBoard})=>{let owner=apertureComponent.parent;for(;owner&&owner!==board&&!owner.pcb_component_id;)owner=owner.parent;let pcbComponent=owner?.pcb_component_id?apertureComponent.root?.db.pcb_component.get(owner.pcb_component_id):null;if(!pcbComponent)throw new Error("<enclosure.cutoutaperture /> must be nested inside a component with a PCB footprint");let aperture=apertureComponent._parsedProps,apertureAxisDirection=owner?._getEnclosureApertureAxisDirection?.(pcbComponent.layer,pcbComponent.rotation??0),apertureDirection=apertureAxisDirection?apertureAxisDirection.z!==0?apertureAxisDirection.z>0?"from_above":"from_below":Math.abs(apertureAxisDirection.x)>=Math.abs(apertureAxisDirection.y)?apertureAxisDirection.x>=0?"from_right":"from_left":apertureAxisDirection.y>=0?"from_top":"from_bottom":pcbComponent.insertion_direction,verticalFace=apertureDirection==="from_above"?"z_pos":apertureDirection==="from_below"?"z_neg":void 0,boardSide=pcbComponent.layer==="bottom"?"bottom":"top",face,center2;if(verticalFace)face=verticalFace,center2={x:pcbComponent.center.x-pcbBoard.center.x,y:pcbComponent.center.y-pcbBoard.center.y};else{let point6=pcbComponent.cable_insertion_center??pcbComponent.center,boardWall=INSERTION_DIRECTION_TO_BOARD_WALL[apertureDirection]??getNearestBoardWall({point:point6,board:pcbBoard}),cableDelta=pcbComponent.cable_insertion_center?{x:pcbComponent.cable_insertion_center.x-pcbComponent.center.x,y:pcbComponent.cable_insertion_center.y-pcbComponent.center.y}:null,cableProjectionMatchesWall=cableDelta!=null&&(boardWall==="x_neg"||boardWall==="x_pos"?Math.abs(cableDelta.x)>=Math.abs(cableDelta.y):Math.abs(cableDelta.y)>=Math.abs(cableDelta.x)),tangentPoint=apertureAxisDirection?pcbComponent.center:cableProjectionMatchesWall?point6:pcbComponent.center;face=getSolverWall(boardWall),center2={x:tangentPoint.x-pcbBoard.center.x,y:tangentPoint.y-pcbBoard.center.y}}let cadComponent=apertureComponent.root?.db.cad_component.getWhere({pcb_component_id:pcbComponent.pcb_component_id})??null,boardSurfaceZ=(boardSide==="bottom"?-1:1)*((pcbBoard.thickness??board.boardThickness)/2),componentBody=getComponentBody({owner,pcbComponent,cadComponent,boardSurfaceZ}),commonInput={face,center:center2,boardSide,apertureAxisDirection,rotation:pcbComponent.rotation??void 0,depth:aperture.depth,componentBody,widthDimensionOffset:aperture.widthDimensionOffset,heightDimensionOffset:aperture.heightDimensionOffset,margin:aperture.margin};switch(aperture.shape){case"pill":case"rect":return{...commonInput,shape:aperture.shape,width:aperture.width,height:aperture.height};case"circle":return{...commonInput,shape:"circle",radius:aperture.radius}}},EnclosureCutoutAperture=class extends PrimitiveComponent2{get config(){return{componentName:"EnclosureCutoutAperture",zodProps:enclosureCutoutApertureProps}}getFdmEnclosureSolverInput(params){return getFdmEnclosureSolverInput(this,params)}},getReferencedEnclosureBoard=(component,boardRef)=>{let rootComponent=component.root?.firstChild,selectedComponent=rootComponent?selectOne(boardRef,rootComponent,{adapter:cssSelectPrimitiveComponentAdapter}):null,board=selectedComponent instanceof Board?selectedComponent:[rootComponent,...rootComponent?.getDescendants()??[]].find(descendant=>descendant instanceof Board&&descendant.isMatchingNameOrAlias(boardRef));if(!(board instanceof Board))throw new Error(`Could not find a <board /> matching enclosure boardRef "${boardRef}"`);return board},EnclosureFdmBox_doInitialCadModelRender=component=>{let root=component.root;if(!root||root.pcbDisabled||!component.source_component_id||!component.pcb_component_id)return;let{db:db2}=root,props=component._parsedProps,board=getReferencedEnclosureBoard(component,props.boardRef),pcbBoard=board.pcb_board_id?db2.pcb_board.get(board.pcb_board_id):null;if(!pcbBoard?.width||!pcbBoard.height)throw new Error(`Could not resolve dimensions for boardRef "${props.boardRef}"`);let boardThickness=pcbBoard.thickness??board.boardThickness,inputProblem={board:{width:pcbBoard.width,height:pcbBoard.height,thickness:boardThickness},width:props.width,height:props.height,depth:props.depth,wallThickness:props.wallThickness,floorThickness:props.floorThickness,lidThickness:props.lidThickness,boardClearance:props.boardClearance,standoffHeight:props.standoffHeight,topHeadroom:props.topHeadroom,lidLipDepth:props.lidLipDepth,apertures:props.disableCutouts?[]:board.getDescendants().filter(descendant=>descendant instanceof EnclosureCutoutAperture).map(aperture=>aperture.getFdmEnclosureSolverInput({board,pcbBoard}))},solver=new CreateFdmEnclosureSolver(inputProblem),solverConstructorArgs=solver.getConstructorParams();if(root.emit("solver:started",{type:"solver:started",solverName:"CreateFdmEnclosureSolver",solverParams:solverConstructorArgs[0],solverConstructorArgs,componentName:component.getString()}),solver.solve(),solver.failed)throw new Error(solver.error??"Failed to create FDM enclosure");let output=solver.getOutput();db2.pcb_component.update(component.pcb_component_id,{center:pcbBoard.center,width:output.dimensions.width,height:output.dimensions.height});let position4={x:pcbBoard.center.x,y:pcbBoard.center.y,z:-boardThickness/2-output.dimensions.floorThickness-output.dimensions.standoffHeight},cadComponents=output.parts.map(part=>db2.cad_component.insert({position:position4,rotation:{x:0,y:0,z:0},pcb_component_id:component.pcb_component_id,source_component_id:component.source_component_id,model_jscad:part.jscadPlan,model_unit_to_mm_scale_factor:1,model_object_fit:"contain_within_bounds",model_origin_alignment:"bottom_center_of_component",anchor_alignment:"center",show_as_translucent_model:!1,show_hidden_edges:props.showHiddenEdges}));component.cad_component_id=cadComponents[0]?.cad_component_id??null},EnclosureFdmBox=class _EnclosureFdmBox extends PrimitiveComponent2{get config(){return{componentName:"EnclosureFdmBox",zodProps:enclosureFdmBoxProps}}doInitialAssignNameToUnnamedComponents(){if(this._parsedProps.name)return;let top=this;for(;top.parent instanceof PrimitiveComponent2;)top=top.parent;let index=[top,...top.getDescendants()].filter(component=>component instanceof _EnclosureFdmBox).indexOf(this);this.fallbackUnassignedName=`unnamed_enclosure_fdm_box_${index===-1?0:index+1}`}doInitialSourceRender(){let sourceComponent=this.root.db.source_component.insert({ftype:"simple_chip",name:this.name});this.source_component_id=sourceComponent.source_component_id}doInitialPcbComponentRender(){let root=this.root;if(!root||root.pcbDisabled||!this.source_component_id)return;let board=getReferencedEnclosureBoard(this,this._parsedProps.boardRef),center2=(board.pcb_board_id?root.db.pcb_board.get(board.pcb_board_id):null)?.center??board._getGlobalPcbPositionBeforeLayout(),pcbComponent=root.db.pcb_component.insert({center:center2,width:0,height:0,layer:"top",rotation:0,source_component_id:this.source_component_id,obstructs_within_bounds:!1,do_not_place:!0,is_allowed_to_be_off_board:!0});this.pcb_component_id=pcbComponent.pcb_component_id}doInitialCadModelRender(){EnclosureFdmBox_doInitialCadModelRender(this)}},Battery=class extends NormalComponent3{get config(){return{componentName:"Battery",schematicSymbolName:this.props.symbolName??"battery",zodProps:batteryProps,sourceFtype:"simple_power_source"}}initPorts(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["cathode","neg","right"]}})}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({name:this.name,ftype:"simple_power_source",capacity:props.capacity,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,are_pins_interchangeable:!1,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},PinHeader=class extends NormalComponent3{_getPcbRotationBeforeLayout(){let orientationRotation=this.props.pcbOrientation==="vertical"?-90:0;return(super._getPcbRotationBeforeLayout()??0)+orientationRotation}get config(){return{componentName:"PinHeader",zodProps:pinHeaderProps,shouldRenderAsSchematicBox:!0}}_getImpliedFootprintString(){let pinCount=this._parsedProps.pinCount??(Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels.length:this._parsedProps.pinLabels?Object.keys(this._parsedProps.pinLabels).length:0),holeDiameter=this._parsedProps.holeDiameter,platedDiameter=this._parsedProps.platedDiameter,pitch=this._parsedProps.pitch,showSilkscreenPinLabels=this._parsedProps.showSilkscreenPinLabels,rows=this._parsedProps.doubleRow?2:1,gender=this._parsedProps.gender;if(pinCount>0){let footprintString;if(pitch)!holeDiameter&&!platedDiameter?footprintString=`pinrow${pinCount}_p${pitch}`:footprintString=`pinrow${pinCount}_p${pitch}_id${holeDiameter}_od${platedDiameter}`;else if(!holeDiameter&&!platedDiameter)footprintString=`pinrow${pinCount}`;else return null;return showSilkscreenPinLabels!==!0&&(footprintString+="_nopinlabels"),gender==="female"&&(footprintString+="_female"),rows>1&&(footprintString+=`_rows${rows}`),footprintString}return null}initPorts(){let pinCount=this._parsedProps.pinCount??(Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels.length:this._parsedProps.pinLabels?Object.keys(this._parsedProps.pinLabels).length:1);for(let i6=1;i6<=pinCount;i6++){let rawLabel=Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels[i6-1]:this._parsedProps.pinLabels?.[`pin${i6}`];if(rawLabel){let primaryLabel=Array.isArray(rawLabel)?rawLabel[0]:rawLabel,otherLabels=Array.isArray(rawLabel)?rawLabel.slice(1):[];this.add(new Port({pinNumber:i6,name:primaryLabel,aliases:[`pin${i6}`,...otherLabels]}))}else this.add(new Port({pinNumber:i6,name:`pin${i6}`}))}}_getSchematicPortArrangement(){let pinCount=this._parsedProps.pinCount??1,facingDirection=this._parsedProps.schFacingDirection??this._parsedProps.facingDirection??"right",schPinArrangement=this._parsedProps.schPinArrangement,pins=Array.from({length:pinCount},(_6,i6)=>`pin${i6+1}`);return facingDirection==="left"?{leftSide:{direction:schPinArrangement?.leftSide?.direction??"top-to-bottom",pins:schPinArrangement?.leftSide?.pins??pins}}:facingDirection==="up"?{topSide:{direction:schPinArrangement?.topSide?.direction??"left-to-right",pins:schPinArrangement?.topSide?.pins??pins}}:facingDirection==="down"?{bottomSide:{direction:schPinArrangement?.bottomSide?.direction??"left-to-right",pins:schPinArrangement?.bottomSide?.pins??pins}}:{rightSide:{direction:schPinArrangement?.rightSide?.direction??"top-to-bottom",pins:schPinArrangement?.rightSide?.pins??pins}}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_pin_header",name:this.name,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,pin_count:props.pinCount,gender:props.gender,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}};function getResonatorSymbolName(variant){switch(variant){case"two_ground_pins":return"crystal_4pin";case"ground_pin":return"resonator";case"no_ground":return"crystal";default:return"crystal"}}var Resonator=class extends NormalComponent3{get config(){return{componentName:"Resonator",schematicSymbolName:this.props.symbolName??getResonatorSymbolName(this.props.pinVariant),zodProps:resonatorProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,pinVariant=props.pinVariant||"no_ground",source_component=db2.source_component.insert({ftype:"simple_resonator",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,frequency:props.frequency,load_capacitance:props.loadCapacitance,supplier_part_numbers:props.supplierPartNumbers,pin_variant:pinVariant,are_pins_interchangeable:pinVariant==="no_ground"||pinVariant==="ground_pin",display_name:props.displayName});this.source_component_id=source_component.source_component_id}_getSchematicSymbolDisplayValue(){let freqDisplay=`${formatSiUnit(this._parsedProps.frequency)}Hz`;return this._parsedProps.loadCapacitance?`${freqDisplay} / ${formatSiUnit(this._parsedProps.loadCapacitance)}F`:freqDisplay}};function getPotentiometerSymbolName(variant){switch(variant){case"three_pin":return"potentiometer3";case"two_pin":return"potentiometer2";default:return"potentiometer2"}}var Potentiometer=class extends NormalComponent3{get config(){return{componentName:"Potentiometer",schematicSymbolName:this.props.symbolName??getPotentiometerSymbolName(this.props.pinVariant),zodProps:potentiometerProps,shouldRenderAsSchematicBox:!1}}_getSchematicSymbolDisplayValue(){return`${formatSiUnit(this._parsedProps.maxResistance)}\u03A9`}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,pinVariant=props.pinVariant||"two_pin",source_component=db2.source_component.insert({ftype:"simple_potentiometer",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,max_resistance:props.maxResistance,pin_variant:pinVariant,are_pins_interchangeable:pinVariant==="two_pin",display_name:props.displayName,display_max_resistance:this._getSchematicSymbolDisplayValue()});this.source_component_id=source_component.source_component_id}},DEFAULT_CRYSTAL_MAX_TRACE_LENGTH_MM=10,DEFAULT_CRYSTAL_MAX_VIA_COUNT=0,Crystal=class extends NormalComponent3{get config(){return{schematicSymbolName:this.props.symbolName??(this.props.pinVariant==="four_pin"?"crystal_4pin":"crystal"),componentName:"Crystal",zodProps:crystalProps,sourceFtype:"simple_crystal"}}initPorts(){let additionalAliases=this.props.pinVariant==="four_pin"?{pin1:["left1","1","X1"],pin2:["top1","2","gnd1"],pin3:["right1","3","X2"],pin4:["bottom1","4","gnd2"]}:{pin1:["pos","left","X1"],pin2:["neg","right","X2"]};super.initPorts({additionalAliases})}_getSchematicSymbolDisplayValue(){let freqDisplay=`${formatSiUnit(this._parsedProps.frequency)}Hz`;return this._parsedProps.loadCapacitance?`${freqDisplay} / ${formatSiUnit(this._parsedProps.loadCapacitance)}F`:freqDisplay}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({name:this.name,ftype:"simple_crystal",manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,frequency:props.frequency,load_capacitance:props.loadCapacitance,pin_variant:props.pinVariant||"two_pin",are_pins_interchangeable:(props.pinVariant||"two_pin")==="two_pin",display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSourceDesignRuleChecks(){if(super.doInitialSourceDesignRuleChecks(),!this.source_component_id)return;let{db:db2}=this.root,maximumTraceLength=this._parsedProps.maxTraceLength??DEFAULT_CRYSTAL_MAX_TRACE_LENGTH_MM,crystalSignalSourcePortIds=new Set,crystalSignalConnectivityMapKeys=new Set;for(let signalPort of[this.portMap.X1,this.portMap.X2]){if(!signalPort.source_port_id)continue;let sourcePort=db2.source_port.get(signalPort.source_port_id);sourcePort&&(crystalSignalSourcePortIds.add(signalPort.source_port_id),sourcePort.subcircuit_connectivity_map_key&&crystalSignalConnectivityMapKeys.add(sourcePort.subcircuit_connectivity_map_key))}for(let sourceTrace of db2.source_trace.list()){let isDirectlyConnectedToCrystal=sourceTrace.connected_source_port_ids.some(sourcePortId=>crystalSignalSourcePortIds.has(sourcePortId)),isOnCrystalNet=sourceTrace.subcircuit_connectivity_map_key!==void 0&&crystalSignalConnectivityMapKeys.has(sourceTrace.subcircuit_connectivity_map_key);if(!isDirectlyConnectedToCrystal&&!isOnCrystalNet)continue;let needsMaximumTraceLength=typeof sourceTrace.max_length!="number"||sourceTrace.max_length>maximumTraceLength,needsMaximumViaCount=sourceTrace.max_via_count!==DEFAULT_CRYSTAL_MAX_VIA_COUNT;!needsMaximumTraceLength&&!needsMaximumViaCount||db2.source_trace.update(sourceTrace.source_trace_id,{...needsMaximumTraceLength?{max_length:maximumTraceLength}:{},...needsMaximumViaCount?{max_via_count:DEFAULT_CRYSTAL_MAX_VIA_COUNT}:{}})}}},OpAmp=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"inverting_input",this.portMap.inverting_input);__publicField(this,"non_inverting_input",this.portMap.non_inverting_input);__publicField(this,"output",this.portMap.output);__publicField(this,"positive_supply",this.portMap.positive_supply);__publicField(this,"negative_supply",this.portMap.negative_supply)}getSchematicSymbolName(){return this.props.symbolName?this.props.symbolName:this.props.connections?.positive_supply||this.props.connections?.negative_supply?"opamp_with_power":"opamp_no_power"}get config(){return{componentName:"OpAmp",schematicSymbolName:this.getSchematicSymbolName(),zodProps:opampProps,sourceFtype:"simple_op_amp"}}initPorts(){let additionalAliases={pin1:["non_inverting_input"],pin2:["inverting_input"]};this.getSchematicSymbolName()==="opamp_with_power"?Object.assign(additionalAliases,{pin4:["output"],pin5:["positive_supply","vcc","vdd"],pin3:["negative_supply","vee","vss","gnd"]}):Object.assign(additionalAliases,{pin3:["output"],pin4:["positive_supply","vcc","vdd"],pin5:["negative_supply","vee","vss","gnd"]}),super.initPorts({pinCount:5,additionalAliases})}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,source_component=db2.source_component.insert({ftype:"simple_op_amp",name:this.name,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db:db2}=this.root,invertingInputPort=this.portMap.inverting_input,nonInvertingInputPort=this.portMap.non_inverting_input,outputPort=this.portMap.output,positiveSupplyPort=this.portMap.positive_supply,negativeSupplyPort=this.portMap.negative_supply;!invertingInputPort?.source_port_id||!nonInvertingInputPort?.source_port_id||!outputPort?.source_port_id||!positiveSupplyPort?.source_port_id||!negativeSupplyPort?.source_port_id||db2.simulation_op_amp.insert({type:"simulation_op_amp",source_component_id:this.source_component_id,inverting_input_source_port_id:invertingInputPort.source_port_id,non_inverting_input_source_port_id:nonInvertingInputPort.source_port_id,output_source_port_id:outputPort.source_port_id,positive_supply_source_port_id:positiveSupplyPort.source_port_id,negative_supply_source_port_id:negativeSupplyPort.source_port_id})}},TESTPOINT_DEFAULTS={HOLE_DIAMETER:.5,SMT_CIRCLE_DIAMETER:1.2,SMT_RECT_SIZE:2},TestPoint=class extends NormalComponent3{get config(){return{componentName:"TestPoint",schematicSymbolName:this.props.symbolName??"testpoint",zodProps:testpointProps,sourceFtype:FTYPE.simple_test_point}}_getPropsWithDefaults(){let{padShape,holeDiameter,footprintVariant,padDiameter,width,height}=this._parsedProps;return!footprintVariant&&holeDiameter&&(footprintVariant="through_hole"),footprintVariant??(footprintVariant="through_hole"),padShape??(padShape="circle"),footprintVariant==="pad"?padShape==="circle"?padDiameter??(padDiameter=TESTPOINT_DEFAULTS.SMT_CIRCLE_DIAMETER):padShape==="rect"&&(width??(width=TESTPOINT_DEFAULTS.SMT_RECT_SIZE),height??(height=width)):footprintVariant==="through_hole"&&(holeDiameter??(holeDiameter=TESTPOINT_DEFAULTS.HOLE_DIAMETER)),{padShape,holeDiameter,footprintVariant,padDiameter,width,height}}_getImpliedFootprintString(){let{padShape,holeDiameter,footprintVariant,padDiameter,width,height}=this._getPropsWithDefaults();if(footprintVariant==="through_hole")return`platedhole_d${holeDiameter}`;if(footprintVariant==="pad"){if(padShape==="circle")return`smtpad_circle_d${padDiameter}`;if(padShape==="rect")return`smtpad_rect_w${width}_h${height}`}throw new Error(`Footprint variant "${footprintVariant}" with pad shape "${padShape}" not implemented`)}doInitialSourceRender(){let{db:db2}=this.root,{_parsedProps:props}=this,{padShape,holeDiameter,footprintVariant,padDiameter,width,height}=this._getPropsWithDefaults(),source_component=db2.source_component.insert({ftype:FTYPE.simple_test_point,name:this.name,supplier_part_numbers:props.supplierPartNumbers,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,footprint_variant:footprintVariant,pad_shape:padShape,pad_diameter:padDiameter,hole_diameter:holeDiameter,width,height,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},SchematicSymbol_doInitialSchematicComponentRender=schematicSymbol=>{if(schematicSymbol.root?.schematicDisabled||schematicSymbol.getCollapsedSchematicBoxAncestor())return;let{db:db2}=schematicSymbol.root,symbolName=schematicSymbol._getSchematicSymbolNameOrThrow(),symbol=hc[symbolName];if(!symbol)throw new Error(`No schematic symbol found for "${symbolName}"`);let center2=schematicSymbol._getGlobalSchematicPositionBeforeLayout(),schematicSheetId=schematicSymbol._resolveSchematicSheetId(),subcircuitId=schematicSymbol.getSubcircuit().subcircuit_id??void 0,schematicComponent=db2.schematic_component.insert({center:center2,size:{...symbol.size},is_box_with_pins:!0,symbol_name:symbolName,source_component_id:schematicSymbol.source_component_id??void 0,schematic_sheet_id:schematicSheetId});schematicSymbol.schematic_component_id=schematicComponent.schematic_component_id;for(let symbolPort of symbol.ports){let port=schematicSymbol.getPortForSymbolPort(symbolPort);if(!port?.source_port_id)throw new Error(`Missing source port for schematic symbol port "${symbolPort.labels.join("/")}" on ${schematicSymbol.getString()}`);let portCenter={x:center2.x+symbolPort.x-symbol.center.x,y:center2.y+symbolPort.y-symbol.center.y},schematicPort=db2.schematic_port.insert({schematic_component_id:schematicComponent.schematic_component_id,center:portCenter,source_port_id:port.source_port_id,facing_direction:getRelativeDirection(center2,portCenter),distance_from_component_edge:.4,pin_number:port._parsedProps.pinNumber,display_pin_label:port._parsedProps.aliases?.[0],is_connected:!1,schematic_sheet_id:schematicSheetId,subcircuit_id:subcircuitId});port.schematic_port_id=schematicPort.schematic_port_id}},getSingleConnectionTarget=(connectionName,target)=>{let targets=Array.isArray(target)?target:[target];if(targets.length!==1)throw new Error(`SchematicSymbol connection "${connectionName}" must select exactly one physical port`);return targets[0]},SchematicSymbol_doInitialPortMatching=schematicSymbol=>{let{db:db2}=schematicSymbol.root,{chipRef,connections}=schematicSymbol._parsedProps;if(chipRef&&!connections){db2.source_property_ignored_warning.insert({source_component_id:schematicSymbol.source_component_id,property_name:"chipRef",message:`${schematicSymbol.getString()} has chipRef "${chipRef}" without connections. chipRef will be ignored.`,error_type:"source_property_ignored_warning",subcircuit_id:schematicSymbol.getSubcircuit().subcircuit_id??void 0});return}if(connections&&!chipRef){db2.source_property_ignored_warning.insert({source_component_id:schematicSymbol.source_component_id,property_name:"connections",message:`${schematicSymbol.getString()} has connections without chipRef. connections will be ignored.`,error_type:"source_property_ignored_warning",subcircuit_id:schematicSymbol.getSubcircuit().subcircuit_id??void 0});return}if(!chipRef||!connections)return;let referencedChip=schematicSymbol.getSubcircuit().selectOne(chipRef);if(!referencedChip?.source_component_id)throw new Error(`Could not resolve chipRef "${chipRef}" for ${schematicSymbol.getString()}`);let usedConnectionNames=new Set;for(let schematicPort of schematicSymbol.ports){let symbolPort=schematicPort.schematicSymbolPortDef,matchingConnections=Object.entries(connections).filter(([connectionName2])=>schematicPort.isMatchingAnyOf([connectionName2]));if(matchingConnections.length===0)throw new Error(`${schematicSymbol.getString()} is missing an explicit connection for symbol port "${symbolPort.labels.join("/")}"`);if(matchingConnections.length>1)throw new Error(`${schematicSymbol.getString()} has multiple connections for symbol port "${symbolPort.labels.join("/")}"`);let[connectionName,connectionTarget4]=matchingConnections[0];usedConnectionNames.add(connectionName);let targetSelector=getSingleConnectionTarget(connectionName,connectionTarget4),physicalPort=schematicSymbol.getSubcircuit().selectOne(targetSelector,{type:"port"});if(!physicalPort?.source_port_id)throw new Error(`Could not resolve connection "${connectionName}" target "${targetSelector}" for ${schematicSymbol.getString()}`);if(db2.source_port.get(physicalPort.source_port_id)?.source_component_id!==referencedChip.source_component_id)throw new Error(`Connection "${connectionName}" target "${targetSelector}" does not belong to chipRef "${chipRef}"`);schematicPort.source_port_id=physicalPort.source_port_id,schematicPort.source_component_id=physicalPort.source_component_id}let unusedConnectionNames=Object.keys(connections).filter(connectionName=>!usedConnectionNames.has(connectionName));if(unusedConnectionNames.length>0)throw new Error(`${schematicSymbol.getString()} has connections that do not match symbol ports: ${unusedConnectionNames.join(", ")}`)},SchematicSymbol=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"isPrimitiveContainer",!0)}get config(){return{componentName:"SchematicSymbol",schematicSymbolName:this.props.symbolName,zodProps:schematicSymbolProps}}initPorts(){let symbol=hc[this._getSchematicSymbolNameOrThrow()],shouldCreateSourcePort=!(this._parsedProps.chipRef&&this._parsedProps.connections);for(let symbolPort of symbol.ports){let pinNumber=getPinNumberFromLabels(symbolPort.labels);if(!pinNumber)throw new Error(`Schematic symbol port must have a numeric pin label: ${symbolPort.labels.join("/")}`);let existingPort=this.ports.find(port2=>port2._parsedProps.pinNumber===pinNumber);if(existingPort){existingPort.schematicSymbolPortDef=symbolPort;continue}let aliases2=symbolPort.labels.filter(label=>label!==pinNumber.toString()&&label!==`pin${pinNumber}`),port=new Port({pinNumber,aliases:aliases2},{shouldCreateSourcePort});port.schematicSymbolPortDef=symbolPort,this.add(port)}}doInitialInitializePortsFromChildren(){this.initPorts()}updateInitializePortsFromChildren(){this.initPorts()}get ports(){return this.children.filter(child=>child instanceof Port)}getPortForSymbolPort(symbolPort){return this.ports.find(port=>port.schematicSymbolPortDef===symbolPort)??null}doInitialSourceRender(){let sourceComponent=this.root.db.source_component.insert({ftype:"simple_chip",name:this.name,display_name:this._parsedProps.displayName,are_pins_interchangeable:!1});this.source_component_id=sourceComponent.source_component_id}doInitialPortMatching(){SchematicSymbol_doInitialPortMatching(this)}doInitialSchematicComponentRender(){SchematicSymbol_doInitialSchematicComponentRender(this)}},SchematicSection=class _SchematicSection extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0)}get config(){return{componentName:"SchematicSection",zodProps:schematicSectionProps}}_computeSectionBounds(board,sectionName,schematicSheetId){let{db:db2}=this.root,members=board.getDescendants().filter(c3=>c3.getSchematicSectionName()===sectionName);if(members.length===0)return null;let positions=[];for(let member of members){let schematicComponentId=member.schematic_component_id;if(!schematicComponentId)continue;let schComp=db2.schematic_component.get(schematicComponentId);if(!schComp||schComp.schematic_sheet_id!==schematicSheetId)continue;let hw2=schComp.size.width/2,hh3=schComp.size.height/2;positions.push({minX:schComp.center.x-hw2,maxX:schComp.center.x+hw2,minY:schComp.center.y-hh3,maxY:schComp.center.y+hh3})}return positions.length===0?null:computeBoundsFromCellContents(positions)}doInitialSchematicSectionRender(){if(this.root?.schematicDisabled)return;let board=this.root?._getBoard();if(!board)return;let schematicSheetId=this._resolveSchematicSheetId(),allSections=board.getDescendants().filter(component=>component instanceof _SchematicSection&&component._resolveSchematicSheetId()===schematicSheetId);if(allSections[0]!==this)return;let{db:db2}=this.root,PADDING=.5,LABEL_PADDING=.2,STROKE_WIDTH=.02,TOL42=.001,namedSectionsWithBounds=allSections.map(section=>{let bounds=section._computeSectionBounds(board,section._parsedProps.name,schematicSheetId);return bounds?{displayName:section._parsedProps.displayName,sectionTitleFontSize:section._parsedProps.sectionTitleFontSize,rawBounds:bounds,cell:{minX:bounds.minX-PADDING,maxX:bounds.maxX+PADDING,minY:bounds.minY-PADDING,maxY:bounds.maxY+PADDING}}:null}).filter(s6=>s6!==null),unsectionedBounds=this._computeSectionBounds(board,null,schematicSheetId),allSectionsWithBounds=[...namedSectionsWithBounds];if(unsectionedBounds&&allSectionsWithBounds.push({displayName:void 0,sectionTitleFontSize:void 0,rawBounds:unsectionedBounds,cell:{minX:unsectionedBounds.minX-PADDING,maxX:unsectionedBounds.maxX+PADDING,minY:unsectionedBounds.minY-PADDING,maxY:unsectionedBounds.maxY+PADDING}}),allSectionsWithBounds.length===0)return;let allCells=allSectionsWithBounds.map(s6=>s6.cell),outer=computeBoundsFromCellContents(allCells),CELL_MARGIN=1,dividers=calculateCellBoundaries2(allSectionsWithBounds.map(s6=>({minX:s6.rawBounds.minX-CELL_MARGIN,maxX:s6.rawBounds.maxX+CELL_MARGIN,minY:s6.rawBounds.minY-CELL_MARGIN,maxY:s6.rawBounds.maxY+CELL_MARGIN})));for(let line2 of dividers)db2.schematic_line.insert({x1:line2.start.x,y1:line2.start.y,x2:line2.end.x,y2:line2.end.y,stroke_width:STROKE_WIDTH,color:"#000000",is_dashed:!0,schematic_sheet_id:schematicSheetId});let hDividers=dividers.filter(l6=>Math.abs(l6.start.y-l6.end.y)<TOL42),vDividers=dividers.filter(l6=>Math.abs(l6.start.x-l6.end.x)<TOL42);for(let{displayName,sectionTitleFontSize,rawBounds}of allSectionsWithBounds){if(!displayName)continue;let dividersAbove=hDividers.map(l6=>l6.start.y).filter(y2=>y2>rawBounds.maxY),topBoundary=dividersAbove.length>0?Math.min(...dividersAbove):outer.maxY,dividersToLeft=vDividers.map(l6=>l6.start.x).filter(x6=>x6<rawBounds.minX),leftBoundary=dividersToLeft.length>0?Math.max(...dividersToLeft):outer.minX;db2.schematic_text.insert({anchor:"top_left",text:displayName,font_size:sectionTitleFontSize??.18,color:"#000000",position:{x:leftBoundary+LABEL_PADDING,y:topBoundary-LABEL_PADDING},rotation:0,schematic_sheet_id:schematicSheetId})}}},SCHEMATIC_UNIT_TO_MM2=10.16/1.1,DEFAULT_SCHEMATIC_SHEET_WIDTH2=297/SCHEMATIC_UNIT_TO_MM2,DEFAULT_SCHEMATIC_SHEET_HEIGHT2=210/SCHEMATIC_UNIT_TO_MM2,SCHEMATIC_SHEET_INNER_MARGIN2=5/SCHEMATIC_UNIT_TO_MM2,BOUNDS_EPSILON=1e-6,getSchematicElementId=schematicElement=>{switch(schematicElement.type){case"schematic_component":return schematicElement.schematic_component_id;case"schematic_net_label":return schematicElement.schematic_net_label_id;case"schematic_trace":return schematicElement.schematic_trace_id}},insertSchematicElementOutsideSheetWarnings=({db:db2,schematicSheetId,schematicSheetName,schematicSheetCenter})=>{let sheetContentBounds={minX:schematicSheetCenter.x-DEFAULT_SCHEMATIC_SHEET_WIDTH2/2+SCHEMATIC_SHEET_INNER_MARGIN2,maxX:schematicSheetCenter.x+DEFAULT_SCHEMATIC_SHEET_WIDTH2/2-SCHEMATIC_SHEET_INNER_MARGIN2,minY:schematicSheetCenter.y-DEFAULT_SCHEMATIC_SHEET_HEIGHT2/2+SCHEMATIC_SHEET_INNER_MARGIN2,maxY:schematicSheetCenter.y+DEFAULT_SCHEMATIC_SHEET_HEIGHT2/2-SCHEMATIC_SHEET_INNER_MARGIN2},checkedElements=[...db2.schematic_component.list(),...db2.schematic_net_label.list(),...db2.schematic_trace.list()].filter(schematicElement=>schematicElement.schematic_sheet_id===schematicSheetId);for(let schematicElement of checkedElements){let elementBounds=getSchematicElementBounds(schematicElement);if(!elementBounds||!(elementBounds.minX<sheetContentBounds.minX-BOUNDS_EPSILON||elementBounds.maxX>sheetContentBounds.maxX+BOUNDS_EPSILON||elementBounds.minY<sheetContentBounds.minY-BOUNDS_EPSILON||elementBounds.maxY>sheetContentBounds.maxY+BOUNDS_EPSILON))continue;let schematicElementId=getSchematicElementId(schematicElement);db2.schematic_element_outside_sheet_warning.insert({warning_type:"schematic_element_outside_sheet_warning",message:`${schematicElement.type} ${schematicElementId} extends outside the drawing area of schematic sheet "${schematicSheetName}"`,schematic_sheet_id:schematicSheetId,schematic_element_type:schematicElement.type,schematic_element_id:schematicElementId})}},SchematicSheet=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0)}get config(){return{componentName:"SchematicSheet",zodProps:schematicSheetProps}}doInitialSourceGroupRender(){if(this.root?.schematicDisabled)return;let{db:db2}=this.root,{_parsedProps:props}=this,schematicSheet=db2.schematic_sheet.insert({name:props.name,display_name:props.displayName,sheet_index:props.sheetIndex,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_sheet_id=schematicSheet.schematic_sheet_id}doInitialSchematicSheetRender(){if(this.root?.schematicDisabled||!this.schematic_sheet_id)return;let{db:db2}=this.root,schematicElements=[...db2.schematic_component.list(),...db2.schematic_port.list(),...db2.schematic_text.list(),...db2.schematic_line.list(),...db2.schematic_rect.list(),...db2.schematic_circle.list(),...db2.schematic_arc.list(),...db2.schematic_path.list()].filter(element=>element.schematic_sheet_id===this.schematic_sheet_id),schematicSheetCenter={x:0,y:0};if(schematicElements.length>0){let bounds=getBoundsForSchematic(schematicElements);Number.isFinite(bounds.minX)&&Number.isFinite(bounds.maxX)&&Number.isFinite(bounds.minY)&&Number.isFinite(bounds.maxY)&&(schematicSheetCenter={x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2},db2.schematic_sheet.update(this.schematic_sheet_id,{center:schematicSheetCenter}))}insertSchematicElementOutsideSheetWarnings({db:db2,schematicSheetId:this.schematic_sheet_id,schematicSheetName:this._parsedProps.displayName,schematicSheetCenter})}},SchematicTable=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_table_id",null)}get config(){return{componentName:"SchematicTable",zodProps:schematicTableProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled||this.getCollapsedSchematicBoxAncestor())return;let{db:db2}=this.root,{_parsedProps:props}=this,rows=this.children.filter(c3=>c3.componentName==="SchematicRow");if(rows.length===0)return;let grid4=[],maxCols=0;for(let row of rows){let cells=row.children.filter(c3=>c3.componentName==="SchematicCell");maxCols=Math.max(maxCols,cells.length)}for(let i6=0;i6<rows.length;i6++)grid4[i6]=[];for(let i6=0;i6<rows.length;i6++){let cells=rows[i6].children.filter(c3=>c3.componentName==="SchematicCell"),k7=0;for(let j6=0;j6<cells.length;j6++){for(;grid4[i6][k7];)k7++;let cell=cells[j6],colSpan=cell._parsedProps.colSpan??1,rowSpan=cell._parsedProps.rowSpan??1;for(let r6=0;r6<rowSpan;r6++)for(let c3=0;c3<colSpan;c3++)grid4[i6+r6]||(grid4[i6+r6]=[]),grid4[i6+r6][k7+c3]=cell;k7+=colSpan}}maxCols=Math.max(0,...grid4.map(r6=>r6.length));let rowHeights=rows.map((row,i6)=>row._parsedProps.height??1),colWidths=Array.from({length:maxCols},(_6,j6)=>{let maxWidth=0;for(let i6=0;i6<rows.length;i6++){let cell=grid4[i6]?.[j6];if(cell){let text=cell._parsedProps.text??cell._parsedProps.children,cellWidth=cell._parsedProps.width??(text?.length??2)*.5;cellWidth>maxWidth&&(maxWidth=cellWidth)}}return maxWidth||10}),anchorPos=this._getGlobalSchematicPositionBeforeLayout(),table=db2.schematic_table.insert({anchor_position:anchorPos,column_widths:colWidths,row_heights:rowHeights,cell_padding:props.cellPadding,border_width:props.borderWidth,anchor:props.anchor,subcircuit_id:this.getSubcircuit()?.subcircuit_id||"",schematic_component_id:this.parent?.schematic_component_id||"",schematic_sheet_id:this._resolveSchematicSheetId()});this.schematic_table_id=table.schematic_table_id;let processedCells=new Set,yOffset=0;for(let i6=0;i6<rows.length;i6++){let xOffset=0;for(let j6=0;j6<maxCols;j6++){let cell=grid4[i6]?.[j6];if(cell&&!processedCells.has(cell)){processedCells.add(cell);let cellProps=cell._parsedProps,rowSpan=cellProps.rowSpan??1,colSpan=cellProps.colSpan??1,cellWidth=0;for(let c3=0;c3<colSpan;c3++)cellWidth+=colWidths[j6+c3];let cellHeight=0;for(let r6=0;r6<rowSpan;r6++)cellHeight+=rowHeights[i6+r6];db2.schematic_table_cell.insert({schematic_table_id:this.schematic_table_id,start_row_index:i6,end_row_index:i6+rowSpan-1,start_column_index:j6,end_column_index:j6+colSpan-1,text:cellProps.text??cellProps.children,center:{x:anchorPos.x+xOffset+cellWidth/2,y:anchorPos.y-yOffset-cellHeight/2},width:cellWidth,height:cellHeight,horizontal_align:cellProps.horizontalAlign,vertical_align:cellProps.verticalAlign,font_size:cellProps.fontSize??props.fontSize,subcircuit_id:this.getSubcircuit()?.subcircuit_id||""})}colWidths[j6]&&(xOffset+=colWidths[j6])}yOffset+=rowHeights[i6]}}},SchematicRow=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0)}get config(){return{componentName:"SchematicRow",zodProps:schematicRowProps}}},SchematicCell=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"canHaveTextChildren",!0)}get config(){return{componentName:"SchematicCell",zodProps:schematicCellProps}}},AnalogSimulation=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"simulation_experiment_id",null)}get config(){return{componentName:"AnalogSimulation",zodProps:analogSimulationProps}}getSpiceEngineName(){return this._parsedProps.spiceEngine}usesIndependentGraphAxes(){return this._parsedProps.graphIndependentAxes===!0}doInitialSimulationRender(){let{db:db2}=this.root,{duration,name,startTime,timePerStep,spiceOptions:spiceOptions2}=this._parsedProps,durationMs=duration||10,timePerStepMs=timePerStep||.01,simulationExperiment=db2.simulation_experiment.insert({name:name??"spice_transient_analysis",experiment_type:"spice_transient_analysis",end_time_ms:durationMs,start_time_ms:startTime,time_per_step:timePerStepMs,spice_options:spiceOptions2});this.simulation_experiment_id=simulationExperiment.simulation_experiment_id}},AnalogAnalysisSimulation=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"simulation_experiment_id",null)}getSpiceEngineName(){return typeof this.props.spiceEngine=="string"?this.props.spiceEngine:void 0}usesIndependentGraphAxes(){return this.props.graphIndependentAxes===!0}getOrCreateSimulationExperiment(){if(this.simulation_experiment_id)return this.root?.db.simulation_experiment.get(this.simulation_experiment_id)??null;if(this.children.filter(child=>child.componentName==="AnalogSweepParameter").length>1)return this.renderError("An analog simulation can contain at most one sweep parameter."),null;let simulationExperiment=this.insertSimulationExperiment();return this.simulation_experiment_id=simulationExperiment?.simulation_experiment_id??null,simulationExperiment}doInitialSimulationRender(){this.getOrCreateSimulationExperiment()}},AnalogTransientSimulation=class extends AnalogAnalysisSimulation{get config(){return{componentName:"AnalogTransientSimulation",zodProps:analogTransientSimulationProps}}insertSimulationExperiment(){let{db:db2}=this.root,{duration,name,startTime,timePerStep,spiceOptions:spiceOptions2}=this._parsedProps;return db2.simulation_experiment.insert({name:name??"spice_transient_analysis",experiment_type:"spice_transient_analysis",end_time_ms:duration,start_time_ms:startTime,time_per_step:timePerStep,spice_options:spiceOptions2})}},AnalogDcOperatingPointSimulation=class extends AnalogAnalysisSimulation{get config(){return{componentName:"AnalogDcOperatingPointSimulation",zodProps:analogDcOperatingPointSimulationProps}}insertSimulationExperiment(){let{name,spiceOptions:spiceOptions2}=this._parsedProps;return this.root.db.simulation_experiment.insert({name:name??"spice_dc_operating_point",experiment_type:"spice_dc_operating_point",spice_options:spiceOptions2})}},AnalogDcSweepSimulation=class extends AnalogAnalysisSimulation{get config(){return{componentName:"AnalogDcSweepSimulation",zodProps:analogDcSweepSimulationProps}}insertSimulationExperiment(){let{name,spiceOptions:spiceOptions2,sweepSource,sweepStart,sweepStop,sweepStep}=this._parsedProps,sweepSourceComponent=(this.getGroup()??this.getSubcircuit())?.selectOne(sweepSource),dcSweepSourceFields;if(sweepSourceComponent instanceof VoltageSource2){sweepSourceComponent.runRenderPhase("SimulationRender");let simulationVoltageSourceId=sweepSourceComponent.simulation_voltage_source_id;if(!simulationVoltageSourceId)return this.renderError(`DC sweep source "${sweepSource}" must resolve to one voltage or current source.`),null;dcSweepSourceFields={dc_sweep_voltage_source_id:simulationVoltageSourceId,dc_sweep_unit:"V"}}else if(sweepSourceComponent instanceof CurrentSource2){sweepSourceComponent.runRenderPhase("SimulationRender");let simulationCurrentSourceId=sweepSourceComponent.simulation_current_source_id;if(!simulationCurrentSourceId)return this.renderError(`DC sweep source "${sweepSource}" must resolve to one voltage or current source.`),null;dcSweepSourceFields={dc_sweep_current_source_id:simulationCurrentSourceId,dc_sweep_unit:"A"}}else return this.renderError(`DC sweep source "${sweepSource}" must resolve to one voltage or current source.`),null;return this.root.db.simulation_experiment.insert({name:name??"spice_dc_sweep",experiment_type:"spice_dc_sweep",spice_options:spiceOptions2,...dcSweepSourceFields,dc_sweep_start:sweepStart,dc_sweep_stop:sweepStop,dc_sweep_step:sweepStep})}},AnalogAcSweepSimulation=class extends AnalogAnalysisSimulation{get config(){return{componentName:"AnalogAcSweepSimulation",zodProps:analogAcSweepSimulationProps}}insertSimulationExperiment(){let{name,spiceOptions:spiceOptions2,sweepType,samplesPerInterval,sampleCount,startFrequency,stopFrequency}=this._parsedProps;return this.root.db.simulation_experiment.insert({name:name??"spice_ac_analysis",experiment_type:"spice_ac_analysis",spice_options:spiceOptions2,ac_sweep_type:sweepType,ac_samples_per_interval:samplesPerInterval,ac_sample_count:sampleCount,ac_start_frequency_hz:startFrequency,ac_stop_frequency_hz:stopFrequency})}},parameterUnits={resistance:"\u03A9",capacitance:"F",inductance:"H",voltage:"V",current:"A"},isParameterSweepCoordinateInRange=({parameterSweepCoordinate,stop,step})=>{let tolerance=Math.abs(step)*1e-9;return step>0?parameterSweepCoordinate<=stop+tolerance:parameterSweepCoordinate>=stop-tolerance},getGeneratedParameterSweepCoordinates=({start,stop,step})=>{let parameterSweepCoordinates=[];for(let parameterSweepCoordinate=start;isParameterSweepCoordinateInRange({parameterSweepCoordinate,stop,step});parameterSweepCoordinate=start+parameterSweepCoordinates.length*step)if(parameterSweepCoordinates.push(parameterSweepCoordinate),parameterSweepCoordinates.length>1e6)throw new Error("Parameter sweep exceeds 1,000,000 points");return parameterSweepCoordinates},getParameterSweepTargetSelector=props=>props.parameterType==="resistance"?props.resistorRef:props.parameterType==="capacitance"?props.capacitorRef:props.parameterType==="inductance"?props.inductorRef:props.parameterType==="voltage"?props.net:props.currentSourceRef,AnalogSweepParameter_doInitialSimulationRender=analogSweepParameter=>{if(!(analogSweepParameter.parent instanceof AnalogAnalysisSimulation)){analogSweepParameter.renderError("analog.sweepparameter must be nested directly in an analog simulation.");return}let simulationExperiment=analogSweepParameter.parent.getOrCreateSimulationExperiment();if(!simulationExperiment)return;let props=analogSweepParameter._parsedProps,parameterSweepCoordinates=props.values??getGeneratedParameterSweepCoordinates({start:props.start,stop:props.stop,step:props.step}),simulationScope=analogSweepParameter.parent.getGroup()??analogSweepParameter.parent.getSubcircuit(),targetSelector=getParameterSweepTargetSelector(props),parameterUnit=parameterUnits[props.parameterType],simulationParameterSweepTable=analogSweepParameter.root.db.simulation_parameter_sweep,simulationParameterSweepFields={simulation_experiment_id:simulationExperiment.simulation_experiment_id,name:props.name,parameter_type:props.parameterType,parameter_values:parameterSweepCoordinates,parameter_unit:parameterUnit},simulationParameterSweepId;if(props.parameterType==="voltage"){let sweepNet=simulationScope?.selectOne(targetSelector,{type:"net"});if(!sweepNet?.source_net_id){analogSweepParameter.renderError(`Voltage sweep net "${targetSelector}" could not be resolved.`);return}simulationParameterSweepId=simulationParameterSweepTable.insert({...simulationParameterSweepFields,parameter_type:"voltage",source_net_id:sweepNet.source_net_id}).simulation_parameter_sweep_id}else{let sourceComponentId=simulationScope?.selectOne(targetSelector)?.source_component_id;if(!sourceComponentId){analogSweepParameter.renderError(`Parameter sweep target "${targetSelector}" could not be resolved.`);return}props.parameterType==="resistance"?simulationParameterSweepId=simulationParameterSweepTable.insert({...simulationParameterSweepFields,parameter_type:"resistance",resistor_source_component_id:sourceComponentId}).simulation_parameter_sweep_id:props.parameterType==="capacitance"?simulationParameterSweepId=simulationParameterSweepTable.insert({...simulationParameterSweepFields,parameter_type:"capacitance",capacitor_source_component_id:sourceComponentId}).simulation_parameter_sweep_id:props.parameterType==="inductance"?simulationParameterSweepId=simulationParameterSweepTable.insert({...simulationParameterSweepFields,parameter_type:"inductance",inductor_source_component_id:sourceComponentId}).simulation_parameter_sweep_id:simulationParameterSweepId=simulationParameterSweepTable.insert({...simulationParameterSweepFields,parameter_type:"current",current_source_component_id:sourceComponentId}).simulation_parameter_sweep_id}analogSweepParameter.simulation_parameter_sweep_id=simulationParameterSweepId},AnalogSweepParameter=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"simulation_parameter_sweep_id",null)}get config(){return{componentName:"AnalogSweepParameter",zodProps:analogSweepParameterProps}}doInitialSimulationRender(){AnalogSweepParameter_doInitialSimulationRender(this)}};function getLabelBounds3(probePosition,labelText,alignment,labelOffset=.3){let labelWidth=Math.max(labelText.length*.1,.3),labelHeightWithPadding=.25+.2,anchorX=probePosition.x,anchorY=probePosition.y,offsetMultiplier=labelOffset+labelWidth/2;alignment.includes("top")?anchorY+=offsetMultiplier:alignment.includes("bottom")&&(anchorY-=offsetMultiplier),alignment.includes("right")?anchorX+=offsetMultiplier:alignment.includes("left")&&(anchorX-=offsetMultiplier);let minX,maxX,minY,maxY;return alignment.includes("left")?(minX=anchorX,maxX=anchorX+labelWidth):alignment.includes("right")?(minX=anchorX-labelWidth,maxX=anchorX):(minX=anchorX-labelWidth/2,maxX=anchorX+labelWidth/2),alignment.includes("top")?(minY=anchorY-labelHeightWithPadding,maxY=anchorY):alignment.includes("bottom")?(minY=anchorY,maxY=anchorY+labelHeightWithPadding):(minY=anchorY-labelHeightWithPadding/2,maxY=anchorY+labelHeightWithPadding/2),{minX,maxX,minY,maxY}}function getElementBounds(elm){let cx3,cy3,w4,h3;if(elm.type==="schematic_component")cx3=elm.center?.x,cy3=elm.center?.y,w4=elm.size?.width,h3=elm.size?.height;else if(elm.type==="schematic_text")cx3=elm.position?.x,cy3=elm.position?.y,w4=(elm.text?.length??0)*.1,h3=.2;else return null;return typeof cx3=="number"&&typeof cy3=="number"&&typeof w4=="number"&&typeof h3=="number"?{minX:cx3-w4/2,maxX:cx3+w4/2,minY:cy3-h3/2,maxY:cy3+h3/2}:null}function getOverlapArea(a6,b6){if(!doBoundsOverlap(a6,b6))return 0;let overlapWidth=Math.min(a6.maxX,b6.maxX)-Math.max(a6.minX,b6.minX),overlapHeight=Math.min(a6.maxY,b6.maxY)-Math.max(a6.minY,b6.minY);return overlapWidth*overlapHeight}function selectBestLabelAlignment({probePosition,labelText,schematicElements,defaultAlignment="top_right"}){let orderedAlignments=[defaultAlignment,...["top_right","top_left","bottom_right","bottom_left","top_center","bottom_center","center_right","center_left"].filter(a6=>a6!==defaultAlignment)],bestAlignment=defaultAlignment,minOverlapArea=1/0;for(let alignment of orderedAlignments){let labelBounds=getLabelBounds3(probePosition,labelText,alignment),totalOverlapArea=0;for(let element of schematicElements){let elementBounds=getElementBounds(element);elementBounds&&(totalOverlapArea+=getOverlapArea(labelBounds,elementBounds))}if(totalOverlapArea===0)return alignment;totalOverlapArea<minOverlapArea&&(minOverlapArea=totalOverlapArea,bestAlignment=alignment)}return bestAlignment}var VoltageProbe=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"simulation_voltage_probe_id",null);__publicField(this,"schematic_voltage_probe_id",null);__publicField(this,"finalProbeName",null);__publicField(this,"color",null)}get config(){return{componentName:"VoltageProbe",zodProps:voltageProbeProps}}doInitialSimulationRender(){let{db:db2}=this.root,{connectsTo,name,referenceTo,color,graphDisplayName,graphCenter,graphVerticalOffset,graphVoltagePerDiv}=this._parsedProps,subcircuit=this.getSubcircuit();if(!subcircuit){this.renderError("VoltageProbe must be inside a subcircuit");return}let targets=Array.isArray(connectsTo)?connectsTo:[connectsTo];if(targets.length!==1){this.renderError("VoltageProbe must connect to exactly one port or net");return}let targetSelector=targets[0],port=subcircuit.selectOne(targetSelector,{type:"port"}),net=port?null:subcircuit.selectOne(targetSelector,{type:"net"});if(net&&net.componentName!=="Net"){this.renderError(`VoltageProbe connection target "${targetSelector}" resolved to a non-net component "${net.componentName}".`);return}if(!port&&!net){this.renderError(`VoltageProbe could not find connection target "${targetSelector}"`);return}let connectedId=port?.source_port_id??net?.source_net_id;if(!connectedId){this.renderError("Could not identify connected source for VoltageProbe");return}let referencePort=null,referenceNet=null;if(referenceTo){let referenceTargets=Array.isArray(referenceTo)?referenceTo:[referenceTo];if(referenceTargets.length!==1){this.renderError("VoltageProbe must reference exactly one port or net");return}let referenceSelector=referenceTargets[0];if(referencePort=subcircuit.selectOne(referenceSelector,{type:"port"}),referenceNet=referencePort?null:subcircuit.selectOne(referenceSelector,{type:"net"}),referenceNet&&referenceNet.componentName!=="Net"){this.renderError(`VoltageProbe reference target "${referenceSelector}" resolved to a non-net component "${referenceNet.componentName}".`);return}if(!referencePort&&!referenceNet){this.renderError(`VoltageProbe could not find reference target "${referenceSelector}"`);return}}this.color=color??getSimulationColorForId(connectedId);let finalName=name;finalName||(finalName=targets[0].split(" > ").map(s6=>s6.replace(/^\./,"")).join(".")),this.finalProbeName=finalName??null;let{simulation_voltage_probe_id}=db2.simulation_voltage_probe.insert({name:finalName,signal_input_source_port_id:port?.source_port_id??void 0,signal_input_source_net_id:net?.source_net_id??void 0,reference_input_source_port_id:referencePort?.source_port_id??void 0,reference_input_source_net_id:referenceNet?.source_net_id??void 0,subcircuit_id:subcircuit.subcircuit_id||void 0,color:this.color});if(this.simulation_voltage_probe_id=simulation_voltage_probe_id,graphDisplayName!==void 0||graphCenter!==void 0||graphVerticalOffset!==void 0||graphVoltagePerDiv!==void 0){let graphVoltagePerDivValue=parseSimulationGraphValue(graphVoltagePerDiv),graphVerticalOffsetValue=parseSimulationGraphValue(graphVerticalOffset);db2.simulation_oscilloscope_trace.insert({simulation_voltage_probe_id,display_name:graphDisplayName,color:color??void 0,display_center_value:graphCenter,volts_per_div:graphVoltagePerDivValue,display_center_offset_divs:graphVerticalOffsetValue!==void 0&&graphVoltagePerDivValue!==void 0&&graphVoltagePerDivValue!==0?graphVerticalOffsetValue/graphVoltagePerDivValue:void 0})}}doInitialSchematicReplaceNetLabelsWithSymbols(){if(this.root?.schematicDisabled)return;let{db:db2}=this.root,{connectsTo,name}=this._parsedProps,subcircuit=this.getSubcircuit();if(!subcircuit)return;let targets=Array.isArray(connectsTo)?connectsTo:[connectsTo];if(targets.length!==1)return;let targetSelector=targets[0],port=subcircuit.selectOne(targetSelector,{type:"port"});if(!port||!port.schematic_port_id)return;let position4=port._getGlobalSchematicPositionAfterLayout(),targetTraceId=null;for(let trace of db2.schematic_trace.list()){for(let edge of trace.edges)if(Math.abs(edge.from.x-position4.x)<1e-6&&Math.abs(edge.from.y-position4.y)<1e-6||Math.abs(edge.to.x-position4.x)<1e-6&&Math.abs(edge.to.y-position4.y)<1e-6){targetTraceId=trace.schematic_trace_id;break}if(targetTraceId)break}if(!targetTraceId)return;let probeName=this.finalProbeName,labelAlignment=selectBestLabelAlignment({probePosition:position4,labelText:probeName,schematicElements:[...db2.schematic_component.list(),...db2.schematic_text.list()],defaultAlignment:"top_right"}),schematic_voltage_probe3=db2.schematic_voltage_probe.insert({name:probeName,position:position4,schematic_trace_id:targetTraceId,subcircuit_id:subcircuit.subcircuit_id||void 0,color:this.color??void 0,label_alignment:labelAlignment});this.schematic_voltage_probe_id=schematic_voltage_probe3.schematic_voltage_probe_id}},SpiceModel=class extends PrimitiveComponent2{get config(){return{componentName:"SpiceModel",zodProps:spicemodelProps}}doInitialSimulationRender(){let parent=this.parent;if(!parent)return;let parentSourceComponentId=parent.source_component_id;if(!parentSourceComponentId){this._insertSpiceModelError("spicemodel must be attached to a source component.",this._parsedProps);return}let{source,spicePinMapping}=this._parsedProps,subckt=parseSpiceNetlist(source).subckts[0]??null,spicePinNames=subckt?.pins.map(pin=>pin.name);if(!subckt||!spicePinNames||spicePinNames.length===0){this._insertSpiceModelError("spicemodel source must contain a .subckt declaration with a model name and pins.",source);return}let mapping=spicePinMapping??{};for(let spicePinName of Object.keys(mapping))if(!spicePinNames.includes(spicePinName)){this._insertSpiceModelError(`spicePinMapping references SPICE pin "${spicePinName}", but it is not present in .subckt ${subckt.name}.`,mapping);return}let spicePinToSourcePortMap={},seenSourcePortIds=new Set;for(let spicePinName of spicePinNames){let componentPinName=mapping[spicePinName]??spicePinName,matchingPorts=parent.selectAll("port").filter(port=>port instanceof Port&&port.isMatchingAnyOf([componentPinName]));if(matchingPorts.length!==1||!matchingPorts[0].source_port_id){this._insertSpiceModelError(`Could not resolve SPICE pin "${spicePinName}" to exactly one component port using "${componentPinName}".`,mapping);return}let sourcePortId=matchingPorts[0].source_port_id;if(seenSourcePortIds.has(sourcePortId)){this._insertSpiceModelError(`spicePinMapping maps more than one SPICE pin to component port "${componentPinName}".`,mapping);return}seenSourcePortIds.add(sourcePortId),spicePinToSourcePortMap[spicePinName]=sourcePortId}this.root.db.simulation_spice_subcircuit.insert({source_component_id:parentSourceComponentId,spice_pin_to_source_port_map:spicePinToSourcePortMap,subcircuit_source:source})}_insertSpiceModelError(message,propertyValue){this.root.db.source_invalid_component_property_error.insert({source_component_id:this.parent?.source_component_id||"",property_name:"spiceModel",property_value:propertyValue,message,error_type:"source_invalid_component_property_error"})}},createNamespacedElement=hostType=>{let Component2=props=>(0,import_react8.createElement)(hostType,props);return Component2.displayName=hostType,Component2},analog={transientsimulation:createNamespacedElement("analogtransientsimulation"),dcoperatingpointsimulation:createNamespacedElement("analogdcoperatingpointsimulation"),dcsweepsimulation:createNamespacedElement("analogdcsweepsimulation"),acsweepsimulation:createNamespacedElement("analogacsweepsimulation"),sweepparameter:createNamespacedElement("analogsweepparameter")},assembly={device:createNamespacedElement("assembly.device")},EnclosureFdmBoxElement=createNamespacedElement("enclosure.fdm.box"),enclosure={cutoutaperture:createNamespacedElement("enclosure.cutoutaperture"),fdm:{box:EnclosureFdmBoxElement,Box:EnclosureFdmBoxElement}},RootCircuit=class extends IsolatedCircuit{constructor({platform,projectUrl}={}){super({platform,projectUrl,cachedSubcircuits:new Map,pendingSubcircuitRenders:new Map});__publicField(this,"isRootCircuit",!0);this.root=this}},Project=RootCircuit,Circuit=RootCircuit,useRenderedCircuit=reactElements=>{let[isLoading,setIsLoading]=import_react9.default.useState(!0),[error2,setError]=import_react9.default.useState(null),[circuit,setCircuit]=import_react9.default.useState(),[circuitJson,setCircuitJson]=import_react9.default.useState();return import_react9.default.useEffect(()=>{setIsLoading(!0),setError(null),reactElements&&setTimeout(()=>{try{let circuit2=new RootCircuit;circuit2.add(reactElements),setCircuit(circuit2),setCircuitJson(circuit2.toJson())}catch(error22){setError(error22)}setIsLoading(!1)},1)},[reactElements]),{isLoading,error:error2,circuit,circuitJson}},createUseComponent=(Component2,pins)=>(name,props)=>{let pinLabelsFlatArray=[];Array.isArray(pins)?pinLabelsFlatArray.push(...pins.flat()):typeof pins=="object"&&pinLabelsFlatArray.push(...Object.values(pins).flat(),...Object.keys(pins));let R4=props2=>{if(props2?.name&&props2.name!==name)throw new Error(`Component name mismatch. Hook name: ${name}, Component prop name: ${props2.name}`);let combinedProps={...props,...props2,name},tracesToCreate=[];for(let portLabel of pinLabelsFlatArray)if(combinedProps[portLabel]){let from=`.${name} > .${portLabel}`,to3=combinedProps[portLabel];tracesToCreate.push({from,to:to3}),delete combinedProps[portLabel]}return(0,import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment,{children:[(0,import_jsx_runtime.jsx)(Component2,{...combinedProps}),tracesToCreate.map((trace,i6)=>(0,import_jsx_runtime.jsx)("trace",{...trace},i6))]})};for(let port of pinLabelsFlatArray)R4[port]=`.${name} > .${port}`;return R4},useCapacitor=createUseComponent(props=>(0,import_jsx_runtime2.jsx)("capacitor",{...props}),capacitorPins),useChip=pinLabels=>createUseComponent(props=>(0,import_jsx_runtime3.jsx)("chip",{pinLabels,...props}),pinLabels),useDiode=createUseComponent(props=>(0,import_jsx_runtime4.jsx)("diode",{...props}),diodePins),useLed=createUseComponent(props=>(0,import_jsx_runtime5.jsx)("led",{...props}),ledPins),useResistor=createUseComponent(props=>(0,import_jsx_runtime6.jsx)("resistor",{...props}),resistorPins),sel=new Proxy(refdes=>new Proxy({},{get:(_6,pin)=>`.${refdes} > .${pin}`}),{get:(_6,prop1)=>{let fn3=(...args)=>{let chipFnOrPinType=args[0];return new Proxy({},{get:(_22,pinName)=>`.${prop1} > .${pinName}`})};return new Proxy(fn3,{get:(_22,prop2)=>prop1==="net"?`net.${prop2}`:prop1==="subcircuit"?new Proxy({},{get:(_32,prop3)=>new Proxy({},{get:(_42,prop4)=>`subcircuit.${prop2} > .${prop3} > .${prop4}`})}):`.${prop1} > .${prop2}`,apply:(target,_22,args)=>prop1==="net"?new Proxy({},{get:(_32,netName)=>`net.${netName}`}):new Proxy({},{get:(_32,pinOrSubComponentName)=>{let pinResult=`.${prop1} > .${pinOrSubComponentName}`;return["U","J","CN"].some(p3=>prop1.startsWith(p3))?pinResult:new Proxy(new String(pinResult),{get:(_42,nestedProp)=>typeof nestedProp=="symbol"||nestedProp==="toString"?()=>pinResult:`.${prop1} > .${pinOrSubComponentName} > .${nestedProp}`})}})})}});extendCatalogue(components_exports);extendCatalogue({"assembly.device":AssemblyDevice,Bug:Chip,"enclosure.cutoutaperture":EnclosureCutoutAperture,"enclosure.fdm.box":EnclosureFdmBox,Fanout:Breakout,FanoutPoint:BreakoutPoint});var React3=__toESM(require_react(),1),ReactJsxRuntime=__toESM(require_jsx_runtime(),1);var dist_exports5={};__export(dist_exports5,{default:()=>mm_default2,mil2mm:()=>mil2mm,mm:()=>mm4,mmStr:()=>mmStr});var unitToMm2={in:25.4,inch:25.4,mil:.0254,mm:1,m:1e3,cm:10,ft:304.8,feet:304.8},mmNumberFormatter=new Intl.NumberFormat("en-US",{useGrouping:!1,notation:"standard",maximumFractionDigits:12}),mm4=n3=>{let unit=typeof n3=="number"?"mm":n3.replace(/^[^a-zA-Z]+/g,"").toLowerCase();unit||(unit="mm");let val=typeof n3=="number"?n3:Number.parseFloat(n3.split(unit)[0]);if(unit in unitToMm2)return val*unitToMm2[unit];throw new Error(`Unsupported unit: ${unit}`)},mmStr=n3=>`${mmNumberFormatter.format(mm4(n3))}mm`,mil2mm=mil=>typeof mil=="number"?mm4(`${mil}mil`):mil.match(/^\d+$/)?mm4(`${mil}mil`):mm4(mil),mm_default2=mm4;var __defProp5=Object.defineProperty,__export4=(target,all)=>{for(var name in all)__defProp5(target,name,{get:all[name],enumerable:!0})},dist_exports6={};__export4(dist_exports6,{all_layers:()=>all_layers2,any_circuit_element:()=>any_circuit_element2,any_soup_element:()=>any_soup_element2,any_source_component:()=>any_source_component2,asset:()=>asset2,base_circuit_json_error:()=>base_circuit_json_error2,battery_capacity:()=>battery_capacity2,brep_shape:()=>brep_shape2,cadModelDefaultDirectionMap:()=>cadModelDefaultDirectionMap2,cad_component:()=>cad_component2,cad_model_axis_directions:()=>cad_model_axis_directions2,cad_model_formats:()=>cad_model_formats2,capacitance:()=>capacitance2,circuit_json_footprint_load_error:()=>circuit_json_footprint_load_error2,current:()=>current2,distance:()=>distance7,duration_ms:()=>duration_ms2,experiment_type:()=>experiment_type2,external_footprint_load_error:()=>external_footprint_load_error2,frequency:()=>frequency2,getZodPrefixedIdWithDefault:()=>getZodPrefixedIdWithDefault2,inductance:()=>inductance2,kicadAt:()=>kicadAt3,kicadEffects:()=>kicadEffects3,kicadFont:()=>kicadFont3,kicadFootprintAttributes:()=>kicadFootprintAttributes3,kicadFootprintMetadata:()=>kicadFootprintMetadata3,kicadFootprintModel:()=>kicadFootprintModel3,kicadFootprintPad:()=>kicadFootprintPad3,kicadFootprintProperties:()=>kicadFootprintProperties3,kicadProperty:()=>kicadProperty3,kicadSymbolEffects:()=>kicadSymbolEffects3,kicadSymbolMetadata:()=>kicadSymbolMetadata3,kicadSymbolPinNames:()=>kicadSymbolPinNames3,kicadSymbolPinNumbers:()=>kicadSymbolPinNumbers3,kicadSymbolProperties:()=>kicadSymbolProperties3,kicadSymbolProperty:()=>kicadSymbolProperty3,layer_ref:()=>layer_ref2,layer_string:()=>layer_string2,length:()=>length3,manufacturing_drc_properties:()=>manufacturing_drc_properties2,ms:()=>ms4,ninePointAnchor:()=>ninePointAnchor3,parseAndConvertSiUnit:()=>parseAndConvertSiUnit2,pcbRenderLayer:()=>pcbRenderLayer2,pcb_autorouting_error:()=>pcb_autorouting_error2,pcb_board:()=>pcb_board2,pcb_breakout_point:()=>pcb_breakout_point2,pcb_component:()=>pcb_component2,pcb_component_invalid_layer_error:()=>pcb_component_invalid_layer_error2,pcb_component_not_on_board_edge_error:()=>pcb_component_not_on_board_edge_error2,pcb_component_outside_board_error:()=>pcb_component_outside_board_error2,pcb_connector_not_in_accessible_orientation_warning:()=>pcb_connector_not_in_accessible_orientation_warning2,pcb_copper_pour:()=>pcb_copper_pour2,pcb_copper_pour_brep:()=>pcb_copper_pour_brep2,pcb_copper_pour_polygon:()=>pcb_copper_pour_polygon2,pcb_copper_pour_rect:()=>pcb_copper_pour_rect2,pcb_copper_text:()=>pcb_copper_text2,pcb_courtyard_circle:()=>pcb_courtyard_circle2,pcb_courtyard_outline:()=>pcb_courtyard_outline2,pcb_courtyard_overlap_error:()=>pcb_courtyard_overlap_error2,pcb_courtyard_pill:()=>pcb_courtyard_pill2,pcb_courtyard_polygon:()=>pcb_courtyard_polygon2,pcb_courtyard_rect:()=>pcb_courtyard_rect2,pcb_cutout:()=>pcb_cutout2,pcb_cutout_circle:()=>pcb_cutout_circle2,pcb_cutout_path:()=>pcb_cutout_path2,pcb_cutout_polygon:()=>pcb_cutout_polygon2,pcb_cutout_rect:()=>pcb_cutout_rect2,pcb_fabrication_note_dimension:()=>pcb_fabrication_note_dimension2,pcb_fabrication_note_path:()=>pcb_fabrication_note_path2,pcb_fabrication_note_rect:()=>pcb_fabrication_note_rect2,pcb_fabrication_note_text:()=>pcb_fabrication_note_text2,pcb_footprint_overlap_error:()=>pcb_footprint_overlap_error2,pcb_ground_plane:()=>pcb_ground_plane2,pcb_ground_plane_region:()=>pcb_ground_plane_region2,pcb_group:()=>pcb_group2,pcb_hole:()=>pcb_hole2,pcb_hole_circle_or_square_shape:()=>pcb_hole_circle_or_square_shape2,pcb_hole_circle_shape:()=>pcb_hole_circle_shape2,pcb_hole_oval_shape:()=>pcb_hole_oval_shape2,pcb_hole_pill_shape:()=>pcb_hole_pill_shape2,pcb_hole_rect_shape:()=>pcb_hole_rect_shape2,pcb_hole_rotated_pill_shape:()=>pcb_hole_rotated_pill_shape2,pcb_keepout:()=>pcb_keepout2,pcb_manual_edit_conflict_warning:()=>pcb_manual_edit_conflict_warning2,pcb_missing_footprint_error:()=>pcb_missing_footprint_error2,pcb_net:()=>pcb_net2,pcb_note_dimension:()=>pcb_note_dimension2,pcb_note_line:()=>pcb_note_line2,pcb_note_path:()=>pcb_note_path2,pcb_note_rect:()=>pcb_note_rect2,pcb_note_text:()=>pcb_note_text2,pcb_pad_pad_clearance_error:()=>pcb_pad_pad_clearance_error2,pcb_pad_trace_clearance_error:()=>pcb_pad_trace_clearance_error2,pcb_panel:()=>pcb_panel2,pcb_panelization_placement_error:()=>pcb_panelization_placement_error2,pcb_placement_error:()=>pcb_placement_error2,pcb_plated_hole:()=>pcb_plated_hole2,pcb_port:()=>pcb_port2,pcb_port_not_connected_error:()=>pcb_port_not_connected_error2,pcb_port_not_matched_error:()=>pcb_port_not_matched_error2,pcb_route_hint:()=>pcb_route_hint2,pcb_route_hints:()=>pcb_route_hints2,pcb_silkscreen_circle:()=>pcb_silkscreen_circle2,pcb_silkscreen_graphic:()=>pcb_silkscreen_graphic2,pcb_silkscreen_graphic_brep:()=>pcb_silkscreen_graphic_brep2,pcb_silkscreen_line:()=>pcb_silkscreen_line2,pcb_silkscreen_oval:()=>pcb_silkscreen_oval2,pcb_silkscreen_path:()=>pcb_silkscreen_path2,pcb_silkscreen_pill:()=>pcb_silkscreen_pill2,pcb_silkscreen_rect:()=>pcb_silkscreen_rect2,pcb_silkscreen_text:()=>pcb_silkscreen_text2,pcb_smtpad:()=>pcb_smtpad2,pcb_smtpad_pill:()=>pcb_smtpad_pill2,pcb_solder_paste:()=>pcb_solder_paste2,pcb_text:()=>pcb_text2,pcb_thermal_spoke:()=>pcb_thermal_spoke2,pcb_trace:()=>pcb_trace2,pcb_trace_error:()=>pcb_trace_error2,pcb_trace_hint:()=>pcb_trace_hint2,pcb_trace_missing_error:()=>pcb_trace_missing_error2,pcb_trace_route_point:()=>pcb_trace_route_point2,pcb_trace_route_point_through_pad:()=>pcb_trace_route_point_through_pad2,pcb_trace_route_point_via:()=>pcb_trace_route_point_via2,pcb_trace_route_point_wire:()=>pcb_trace_route_point_wire2,pcb_trace_warning:()=>pcb_trace_warning2,pcb_via:()=>pcb_via2,pcb_via_clearance_error:()=>pcb_via_clearance_error2,pcb_via_trace_clearance_error:()=>pcb_via_trace_clearance_error2,point:()=>point5,point3:()=>point33,point_with_bulge:()=>point_with_bulge2,port_arrangement:()=>port_arrangement2,position:()=>position2,position3:()=>position32,resistance:()=>resistance2,ring:()=>ring2,rotation:()=>rotation4,route_hint_point:()=>route_hint_point2,schematic_arc:()=>schematic_arc2,schematic_box:()=>schematic_box2,schematic_circle:()=>schematic_circle2,schematic_component:()=>schematic_component2,schematic_component_port_arrangement_by_sides:()=>schematic_component_port_arrangement_by_sides2,schematic_component_port_arrangement_by_size:()=>schematic_component_port_arrangement_by_size2,schematic_debug_line:()=>schematic_debug_line2,schematic_debug_object:()=>schematic_debug_object2,schematic_debug_object_base:()=>schematic_debug_object_base2,schematic_debug_point:()=>schematic_debug_point2,schematic_debug_rect:()=>schematic_debug_rect2,schematic_error:()=>schematic_error2,schematic_group:()=>schematic_group2,schematic_layout_error:()=>schematic_layout_error2,schematic_line:()=>schematic_line2,schematic_manual_edit_conflict_warning:()=>schematic_manual_edit_conflict_warning2,schematic_net_label:()=>schematic_net_label2,schematic_path:()=>schematic_path2,schematic_pin_styles:()=>schematic_pin_styles2,schematic_port:()=>schematic_port2,schematic_rect:()=>schematic_rect2,schematic_sheet:()=>schematic_sheet2,schematic_symbol:()=>schematic_symbol2,schematic_table:()=>schematic_table2,schematic_table_cell:()=>schematic_table_cell2,schematic_text:()=>schematic_text2,schematic_trace:()=>schematic_trace2,schematic_voltage_probe:()=>schematic_voltage_probe2,simulation_ac_current_source:()=>simulation_ac_current_source2,simulation_ac_voltage_source:()=>simulation_ac_voltage_source2,simulation_current_probe:()=>simulation_current_probe2,simulation_current_source:()=>simulation_current_source2,simulation_dc_current_source:()=>simulation_dc_current_source2,simulation_dc_voltage_source:()=>simulation_dc_voltage_source2,simulation_experiment:()=>simulation_experiment2,simulation_op_amp:()=>simulation_op_amp2,simulation_oscilloscope_trace:()=>simulation_oscilloscope_trace2,simulation_spice_subcircuit:()=>simulation_spice_subcircuit2,simulation_switch:()=>simulation_switch2,simulation_transient_current_graph:()=>simulation_transient_current_graph2,simulation_transient_voltage_graph:()=>simulation_transient_voltage_graph2,simulation_unknown_experiment_error:()=>simulation_unknown_experiment_error2,simulation_voltage_probe:()=>simulation_voltage_probe2,simulation_voltage_source:()=>simulation_voltage_source2,size:()=>size2,source_ambiguous_port_reference:()=>source_ambiguous_port_reference2,source_board:()=>source_board2,source_component_base:()=>source_component_base2,source_component_internal_connection:()=>source_component_internal_connection2,source_component_misconfigured_error:()=>source_component_misconfigured_error2,source_component_pins_underspecified_warning:()=>source_component_pins_underspecified_warning2,source_failed_to_create_component_error:()=>source_failed_to_create_component_error2,source_group:()=>source_group2,source_i2c_misconfigured_error:()=>source_i2c_misconfigured_error2,source_interconnect:()=>source_interconnect2,source_invalid_component_property_error:()=>source_invalid_component_property_error2,source_manually_placed_via:()=>source_manually_placed_via2,source_missing_manufacturer_part_number_warning:()=>source_missing_manufacturer_part_number_warning2,source_missing_property_error:()=>source_missing_property_error2,source_net:()=>source_net2,source_no_ground_pin_defined_warning:()=>source_no_ground_pin_defined_warning2,source_no_power_pin_defined_warning:()=>source_no_power_pin_defined_warning2,source_part_not_found_warning:()=>source_part_not_found_warning2,source_pcb_ground_plane:()=>source_pcb_ground_plane2,source_pin_attributes:()=>source_pin_attributes2,source_pin_missing_trace_warning:()=>source_pin_missing_trace_warning2,source_pin_must_be_connected_error:()=>source_pin_must_be_connected_error2,source_port:()=>source_port2,source_project_metadata:()=>source_project_metadata2,source_property_ignored_warning:()=>source_property_ignored_warning2,source_refdes_convention_warning:()=>source_refdes_convention_warning2,source_simple_ammeter:()=>source_simple_ammeter2,source_simple_battery:()=>source_simple_battery2,source_simple_capacitor:()=>source_simple_capacitor2,source_simple_chip:()=>source_simple_chip2,source_simple_connector:()=>source_simple_connector2,source_simple_crystal:()=>source_simple_crystal2,source_simple_current_source:()=>source_simple_current_source2,source_simple_diode:()=>source_simple_diode2,source_simple_fiducial:()=>source_simple_fiducial2,source_simple_fuse:()=>source_simple_fuse2,source_simple_ground:()=>source_simple_ground2,source_simple_inductor:()=>source_simple_inductor2,source_simple_led:()=>source_simple_led2,source_simple_mosfet:()=>source_simple_mosfet2,source_simple_op_amp:()=>source_simple_op_amp2,source_simple_pin_header:()=>source_simple_pin_header2,source_simple_pinout:()=>source_simple_pinout2,source_simple_potentiometer:()=>source_simple_potentiometer2,source_simple_power_source:()=>source_simple_power_source2,source_simple_push_button:()=>source_simple_push_button2,source_simple_resistor:()=>source_simple_resistor2,source_simple_resonator:()=>source_simple_resonator2,source_simple_switch:()=>source_simple_switch2,source_simple_test_point:()=>source_simple_test_point2,source_simple_transistor:()=>source_simple_transistor2,source_simple_voltage_probe:()=>source_simple_voltage_probe2,source_simple_voltage_source:()=>source_simple_voltage_source2,source_trace:()=>source_trace2,source_trace_not_connected_error:()=>source_trace_not_connected_error2,source_unnamed_trace_warning:()=>source_unnamed_trace_warning2,spice_simulation_options:()=>spice_simulation_options2,supplier_footprint_mismatch_warning:()=>supplier_footprint_mismatch_warning2,supplier_name:()=>supplier_name2,time:()=>time2,timestamp:()=>timestamp2,unknown_error_finding_part:()=>unknown_error_finding_part2,visible_layer:()=>visible_layer2,voltage:()=>voltage2,wave_shape:()=>wave_shape2});var SI_PREFIX_VALUES2=new Map([["T",1e12],["G",1e9],["M",1e6],["K",1e3],["k",1e3],["",1],["m",.001],["\xB5",1e-6],["u",1e-6],["n",1e-9],["p",1e-12],["f",1e-15]]),SI_PREFIXES3=[...SI_PREFIX_VALUES2.keys()];function getSiPrefixMultiplier2(prefix){return SI_PREFIX_VALUES2.get(prefix)}var unitMappings2={Hz:{baseUnit:"Hz",variants:{MHz:1e6,kHz:1e3,Hz:1}},g:{baseUnit:"g",variants:{kg:1e3,g:1}},\u03A9:{baseUnit:"\u03A9",variants:{m\u03A9:.001,mohm:.001,mOhm:.001,milliohm:.001,\u03A9:1,ohm:1,Ohm:1,k\u03A9:1e3,K\u03A9:1e3,kohm:1e3,kOhm:1e3,KOhm:1e3,Kohm:1e3,M\u03A9:1e6,Mohm:1e6,MOhm:1e6,megohm:1e6,Megohm:1e6,G\u03A9:1e9,Gohm:1e9,GOhm:1e9,T\u03A9:1e12,Tohm:1e12,TOhm:1e12}},V:{baseUnit:"V",variants:{mV:.001,V:1,kV:1e3,KV:1e3,MV:1e6,GV:1e9,TV:1e12}},A:{baseUnit:"A",variants:{\u00B5A:1e-6,mA:.001,ma:.001,A:1,kA:1e3,MA:1e6}},F:{baseUnit:"F",variants:{pF:1e-12,nF:1e-9,\u00B5F:1e-6,uF:1e-6,mF:.001,F:1,kF:1e3,KF:1e3,MF:1e6}},H:{baseUnit:"H",variants:{pH:1e-12,nH:1e-9,\u00B5H:1e-6,uH:1e-6,mH:.001,H:1,kH:1e3,KH:1e3,MH:1e6}},ml:{baseUnit:"ml",variants:{ml:1,mL:1,l:1e3,L:1e3}},deg:{baseUnit:"deg",variants:{rad:180/Math.PI}},ms:{baseUnit:"ms",variants:{fs:1e-12,ps:1e-9,ns:1e-6,us:.001,\u00B5s:.001,ms:1,s:1e3}},mm:{baseUnit:"mm",variants:{nm:1e-6,\u00B5m:.001,um:.001,mm:1,cm:10,dm:100,m:1e3,km:1e6,in:25.4,ft:304.8,IN:25.4,FT:304.8,yd:914.4,mi:1609344,mil:.0254}}},unitMappingAndVariantSuffixes2=new Set;for(let[baseUnit,info]of Object.entries(unitMappings2)){unitMappingAndVariantSuffixes2.add(baseUnit);for(let variant of Object.keys(info.variants))unitMappingAndVariantSuffixes2.add(variant)}function getBaseTscircuitUnit2(unit){for(let info of Object.values(unitMappings2)){if(unit in info.variants)return{baseUnit:info.baseUnit,conversionFactor:info.variants[unit]};for(let[variant,conversionFactor]of Object.entries(info.variants)){if(!unit.endsWith(variant))continue;let prefix=unit.slice(0,-variant.length),prefixMultiplier=getSiPrefixMultiplier2(prefix);if(prefixMultiplier!=null)return{baseUnit:info.baseUnit,conversionFactor:prefixMultiplier*conversionFactor}}}return{baseUnit:unit,conversionFactor:1}}function parseAndConvertSiUnit2(v6,unitOfValue){if(v6==null)return{parsedUnit:null,unitOfValue:null,value:null};if(typeof v6=="string"&&v6.match(/^-?[\d.]+$/))return{value:Number.parseFloat(v6),parsedUnit:null,unitOfValue:null};if(typeof v6=="number")return{value:v6,parsedUnit:null,unitOfValue:null};if(typeof v6=="object"&&"x"in v6&&"y"in v6){let firstResult=parseAndConvertSiUnit2(v6.x,unitOfValue),xResult=parseAndConvertSiUnit2(v6.x,unitOfValue),yResult=parseAndConvertSiUnit2(v6.y,unitOfValue);return xResult.value===null||yResult.value===null?{parsedUnit:null,unitOfValue:null,value:null}:{parsedUnit:firstResult.parsedUnit,unitOfValue:firstResult.unitOfValue,value:{x:xResult.value,y:yResult.value}}}let unitReversed=v6.toString().split("").reverse().join("").match(/[^\d\s]+/)?.[0];if(!unitReversed)throw new Error(`Could not determine unit: "${v6}"`);let unit=unitReversed.split("").reverse().join(""),numberPart=v6.slice(0,-unit.length),bareSiPrefixMultiplier=getSiPrefixMultiplier2(unit);if(unitOfValue&&bareSiPrefixMultiplier!=null)return{parsedUnit:null,unitOfValue,value:Number.parseFloat(numberPart)*bareSiPrefixMultiplier};if(bareSiPrefixMultiplier!=null&&!unitMappingAndVariantSuffixes2.has(unit))return{parsedUnit:null,unitOfValue:null,value:Number.parseFloat(numberPart)*bareSiPrefixMultiplier};let{baseUnit,conversionFactor}=getBaseTscircuitUnit2(unit);return{parsedUnit:unit,unitOfValue:baseUnit,value:conversionFactor*Number.parseFloat(numberPart)}}var SI_PREFIX_PATTERN2=SI_PREFIXES3.filter(prefix=>prefix!=="").sort((a6,b6)=>b6.length-a6.length).map(prefix=>prefix.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|"),SI_UNIT_PATTERN2=new RegExp(`^([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)(?:(${SI_PREFIX_PATTERN2}))?$`),SI_PREFIXES22=[{value:1e12,symbol:"T"},{value:1e9,symbol:"G"},{value:1e6,symbol:"M"},{value:1e3,symbol:"k"},{value:1,symbol:""},{value:.001,symbol:"m"},{value:1e-6,symbol:"\xB5"},{value:1e-9,symbol:"n"},{value:1e-12,symbol:"p"}],FALLBACK_PREFIX2=SI_PREFIXES22[SI_PREFIXES22.length-1],external_exports2={};__export4(external_exports2,{BRAND:()=>BRAND2,DIRTY:()=>DIRTY2,EMPTY_PATH:()=>EMPTY_PATH2,INVALID:()=>INVALID2,NEVER:()=>NEVER2,OK:()=>OK3,ParseStatus:()=>ParseStatus2,Schema:()=>ZodType2,ZodAny:()=>ZodAny2,ZodArray:()=>ZodArray2,ZodBigInt:()=>ZodBigInt2,ZodBoolean:()=>ZodBoolean2,ZodBranded:()=>ZodBranded2,ZodCatch:()=>ZodCatch2,ZodDate:()=>ZodDate2,ZodDefault:()=>ZodDefault2,ZodDiscriminatedUnion:()=>ZodDiscriminatedUnion2,ZodEffects:()=>ZodEffects2,ZodEnum:()=>ZodEnum2,ZodError:()=>ZodError2,ZodFirstPartyTypeKind:()=>ZodFirstPartyTypeKind2,ZodFunction:()=>ZodFunction2,ZodIntersection:()=>ZodIntersection2,ZodIssueCode:()=>ZodIssueCode2,ZodLazy:()=>ZodLazy2,ZodLiteral:()=>ZodLiteral2,ZodMap:()=>ZodMap2,ZodNaN:()=>ZodNaN2,ZodNativeEnum:()=>ZodNativeEnum2,ZodNever:()=>ZodNever2,ZodNull:()=>ZodNull2,ZodNullable:()=>ZodNullable2,ZodNumber:()=>ZodNumber2,ZodObject:()=>ZodObject2,ZodOptional:()=>ZodOptional2,ZodParsedType:()=>ZodParsedType2,ZodPipeline:()=>ZodPipeline2,ZodPromise:()=>ZodPromise2,ZodReadonly:()=>ZodReadonly2,ZodRecord:()=>ZodRecord2,ZodSchema:()=>ZodType2,ZodSet:()=>ZodSet2,ZodString:()=>ZodString2,ZodSymbol:()=>ZodSymbol2,ZodTransformer:()=>ZodEffects2,ZodTuple:()=>ZodTuple2,ZodType:()=>ZodType2,ZodUndefined:()=>ZodUndefined2,ZodUnion:()=>ZodUnion2,ZodUnknown:()=>ZodUnknown2,ZodVoid:()=>ZodVoid2,addIssueToContext:()=>addIssueToContext2,any:()=>anyType2,array:()=>arrayType2,bigint:()=>bigIntType2,boolean:()=>booleanType2,coerce:()=>coerce2,custom:()=>custom2,date:()=>dateType2,datetimeRegex:()=>datetimeRegex2,defaultErrorMap:()=>en_default2,discriminatedUnion:()=>discriminatedUnionType2,effect:()=>effectsType2,enum:()=>enumType2,function:()=>functionType2,getErrorMap:()=>getErrorMap2,getParsedType:()=>getParsedType2,instanceof:()=>instanceOfType2,intersection:()=>intersectionType2,isAborted:()=>isAborted2,isAsync:()=>isAsync2,isDirty:()=>isDirty2,isValid:()=>isValid2,late:()=>late2,lazy:()=>lazyType2,literal:()=>literalType2,makeIssue:()=>makeIssue2,map:()=>mapType2,nan:()=>nanType2,nativeEnum:()=>nativeEnumType2,never:()=>neverType2,null:()=>nullType2,nullable:()=>nullableType2,number:()=>numberType2,object:()=>objectType2,objectUtil:()=>objectUtil2,oboolean:()=>oboolean2,onumber:()=>onumber2,optional:()=>optionalType2,ostring:()=>ostring2,pipeline:()=>pipelineType2,preprocess:()=>preprocessType2,promise:()=>promiseType2,quotelessJson:()=>quotelessJson2,record:()=>recordType2,set:()=>setType2,setErrorMap:()=>setErrorMap2,strictObject:()=>strictObjectType2,string:()=>stringType2,symbol:()=>symbolType2,transformer:()=>effectsType2,tuple:()=>tupleType2,undefined:()=>undefinedType2,union:()=>unionType2,unknown:()=>unknownType2,util:()=>util2,void:()=>voidType2});var util2;(function(util22){util22.assertEqual=_6=>{};function assertIs(_arg){}util22.assertIs=assertIs;function assertNever(_x3){throw new Error}util22.assertNever=assertNever,util22.arrayToEnum=items=>{let obj={};for(let item of items)obj[item]=item;return obj},util22.getValidEnumValues=obj=>{let validKeys=util22.objectKeys(obj).filter(k7=>typeof obj[obj[k7]]!="number"),filtered={};for(let k7 of validKeys)filtered[k7]=obj[k7];return util22.objectValues(filtered)},util22.objectValues=obj=>util22.objectKeys(obj).map(function(e6){return obj[e6]}),util22.objectKeys=typeof Object.keys=="function"?obj=>Object.keys(obj):object=>{let keys=[];for(let key in object)Object.prototype.hasOwnProperty.call(object,key)&&keys.push(key);return keys},util22.find=(arr,checker)=>{for(let item of arr)if(checker(item))return item},util22.isInteger=typeof Number.isInteger=="function"?val=>Number.isInteger(val):val=>typeof val=="number"&&Number.isFinite(val)&&Math.floor(val)===val;function joinValues(array2,separator=" | "){return array2.map(val=>typeof val=="string"?`'${val}'`:val).join(separator)}util22.joinValues=joinValues,util22.jsonStringifyReplacer=(_6,value)=>typeof value=="bigint"?value.toString():value})(util2||(util2={}));var objectUtil2;(function(objectUtil22){objectUtil22.mergeShapes=(first,second)=>({...first,...second})})(objectUtil2||(objectUtil2={}));var ZodParsedType2=util2.arrayToEnum(["string","nan","number","integer","float","boolean","date","bigint","symbol","function","undefined","null","array","object","unknown","promise","void","never","map","set"]),getParsedType2=data=>{switch(typeof data){case"undefined":return ZodParsedType2.undefined;case"string":return ZodParsedType2.string;case"number":return Number.isNaN(data)?ZodParsedType2.nan:ZodParsedType2.number;case"boolean":return ZodParsedType2.boolean;case"function":return ZodParsedType2.function;case"bigint":return ZodParsedType2.bigint;case"symbol":return ZodParsedType2.symbol;case"object":return Array.isArray(data)?ZodParsedType2.array:data===null?ZodParsedType2.null:data.then&&typeof data.then=="function"&&data.catch&&typeof data.catch=="function"?ZodParsedType2.promise:typeof Map<"u"&&data instanceof Map?ZodParsedType2.map:typeof Set<"u"&&data instanceof Set?ZodParsedType2.set:typeof Date<"u"&&data instanceof Date?ZodParsedType2.date:ZodParsedType2.object;default:return ZodParsedType2.unknown}},ZodIssueCode2=util2.arrayToEnum(["invalid_type","invalid_literal","custom","invalid_union","invalid_union_discriminator","invalid_enum_value","unrecognized_keys","invalid_arguments","invalid_return_type","invalid_date","invalid_string","too_small","too_big","invalid_intersection_types","not_multiple_of","not_finite"]),quotelessJson2=obj=>JSON.stringify(obj,null,2).replace(/"([^"]+)":/g,"$1:"),ZodError2=class _ZodError extends Error{get errors(){return this.issues}constructor(issues){super(),this.issues=[],this.addIssue=sub=>{this.issues=[...this.issues,sub]},this.addIssues=(subs=[])=>{this.issues=[...this.issues,...subs]};let actualProto=new.target.prototype;Object.setPrototypeOf?Object.setPrototypeOf(this,actualProto):this.__proto__=actualProto,this.name="ZodError",this.issues=issues}format(_mapper){let mapper=_mapper||function(issue){return issue.message},fieldErrors={_errors:[]},processError=error2=>{for(let issue of error2.issues)if(issue.code==="invalid_union")issue.unionErrors.map(processError);else if(issue.code==="invalid_return_type")processError(issue.returnTypeError);else if(issue.code==="invalid_arguments")processError(issue.argumentsError);else if(issue.path.length===0)fieldErrors._errors.push(mapper(issue));else{let curr=fieldErrors,i6=0;for(;i6<issue.path.length;){let el3=issue.path[i6];i6===issue.path.length-1?(curr[el3]=curr[el3]||{_errors:[]},curr[el3]._errors.push(mapper(issue))):curr[el3]=curr[el3]||{_errors:[]},curr=curr[el3],i6++}}};return processError(this),fieldErrors}static assert(value){if(!(value instanceof _ZodError))throw new Error(`Not a ZodError: ${value}`)}toString(){return this.message}get message(){return JSON.stringify(this.issues,util2.jsonStringifyReplacer,2)}get isEmpty(){return this.issues.length===0}flatten(mapper=issue=>issue.message){let fieldErrors={},formErrors=[];for(let sub of this.issues)if(sub.path.length>0){let firstEl=sub.path[0];fieldErrors[firstEl]=fieldErrors[firstEl]||[],fieldErrors[firstEl].push(mapper(sub))}else formErrors.push(mapper(sub));return{formErrors,fieldErrors}}get formErrors(){return this.flatten()}};ZodError2.create=issues=>new ZodError2(issues);var errorMap2=(issue,_ctx)=>{let message;switch(issue.code){case ZodIssueCode2.invalid_type:issue.received===ZodParsedType2.undefined?message="Required":message=`Expected ${issue.expected}, received ${issue.received}`;break;case ZodIssueCode2.invalid_literal:message=`Invalid literal value, expected ${JSON.stringify(issue.expected,util2.jsonStringifyReplacer)}`;break;case ZodIssueCode2.unrecognized_keys:message=`Unrecognized key(s) in object: ${util2.joinValues(issue.keys,", ")}`;break;case ZodIssueCode2.invalid_union:message="Invalid input";break;case ZodIssueCode2.invalid_union_discriminator:message=`Invalid discriminator value. Expected ${util2.joinValues(issue.options)}`;break;case ZodIssueCode2.invalid_enum_value:message=`Invalid enum value. Expected ${util2.joinValues(issue.options)}, received '${issue.received}'`;break;case ZodIssueCode2.invalid_arguments:message="Invalid function arguments";break;case ZodIssueCode2.invalid_return_type:message="Invalid function return type";break;case ZodIssueCode2.invalid_date:message="Invalid date";break;case ZodIssueCode2.invalid_string:typeof issue.validation=="object"?"includes"in issue.validation?(message=`Invalid input: must include "${issue.validation.includes}"`,typeof issue.validation.position=="number"&&(message=`${message} at one or more positions greater than or equal to ${issue.validation.position}`)):"startsWith"in issue.validation?message=`Invalid input: must start with "${issue.validation.startsWith}"`:"endsWith"in issue.validation?message=`Invalid input: must end with "${issue.validation.endsWith}"`:util2.assertNever(issue.validation):issue.validation!=="regex"?message=`Invalid ${issue.validation}`:message="Invalid";break;case ZodIssueCode2.too_small:issue.type==="array"?message=`Array must contain ${issue.exact?"exactly":issue.inclusive?"at least":"more than"} ${issue.minimum} element(s)`:issue.type==="string"?message=`String must contain ${issue.exact?"exactly":issue.inclusive?"at least":"over"} ${issue.minimum} character(s)`:issue.type==="number"?message=`Number must be ${issue.exact?"exactly equal to ":issue.inclusive?"greater than or equal to ":"greater than "}${issue.minimum}`:issue.type==="bigint"?message=`Number must be ${issue.exact?"exactly equal to ":issue.inclusive?"greater than or equal to ":"greater than "}${issue.minimum}`:issue.type==="date"?message=`Date must be ${issue.exact?"exactly equal to ":issue.inclusive?"greater than or equal to ":"greater than "}${new Date(Number(issue.minimum))}`:message="Invalid input";break;case ZodIssueCode2.too_big:issue.type==="array"?message=`Array must contain ${issue.exact?"exactly":issue.inclusive?"at most":"less than"} ${issue.maximum} element(s)`:issue.type==="string"?message=`String must contain ${issue.exact?"exactly":issue.inclusive?"at most":"under"} ${issue.maximum} character(s)`:issue.type==="number"?message=`Number must be ${issue.exact?"exactly":issue.inclusive?"less than or equal to":"less than"} ${issue.maximum}`:issue.type==="bigint"?message=`BigInt must be ${issue.exact?"exactly":issue.inclusive?"less than or equal to":"less than"} ${issue.maximum}`:issue.type==="date"?message=`Date must be ${issue.exact?"exactly":issue.inclusive?"smaller than or equal to":"smaller than"} ${new Date(Number(issue.maximum))}`:message="Invalid input";break;case ZodIssueCode2.custom:message="Invalid input";break;case ZodIssueCode2.invalid_intersection_types:message="Intersection results could not be merged";break;case ZodIssueCode2.not_multiple_of:message=`Number must be a multiple of ${issue.multipleOf}`;break;case ZodIssueCode2.not_finite:message="Number must be finite";break;default:message=_ctx.defaultError,util2.assertNever(issue)}return{message}},en_default2=errorMap2,overrideErrorMap2=en_default2;function setErrorMap2(map){overrideErrorMap2=map}function getErrorMap2(){return overrideErrorMap2}var makeIssue2=params=>{let{data,path,errorMaps,issueData}=params,fullPath=[...path,...issueData.path||[]],fullIssue={...issueData,path:fullPath};if(issueData.message!==void 0)return{...issueData,path:fullPath,message:issueData.message};let errorMessage="",maps=errorMaps.filter(m6=>!!m6).slice().reverse();for(let map of maps)errorMessage=map(fullIssue,{data,defaultError:errorMessage}).message;return{...issueData,path:fullPath,message:errorMessage}},EMPTY_PATH2=[];function addIssueToContext2(ctx,issueData){let overrideMap=getErrorMap2(),issue=makeIssue2({issueData,data:ctx.data,path:ctx.path,errorMaps:[ctx.common.contextualErrorMap,ctx.schemaErrorMap,overrideMap,overrideMap===en_default2?void 0:en_default2].filter(x6=>!!x6)});ctx.common.issues.push(issue)}var ParseStatus2=class _ParseStatus{constructor(){this.value="valid"}dirty(){this.value==="valid"&&(this.value="dirty")}abort(){this.value!=="aborted"&&(this.value="aborted")}static mergeArray(status,results){let arrayValue=[];for(let s6 of results){if(s6.status==="aborted")return INVALID2;s6.status==="dirty"&&status.dirty(),arrayValue.push(s6.value)}return{status:status.value,value:arrayValue}}static async mergeObjectAsync(status,pairs22){let syncPairs=[];for(let pair of pairs22){let key=await pair.key,value=await pair.value;syncPairs.push({key,value})}return _ParseStatus.mergeObjectSync(status,syncPairs)}static mergeObjectSync(status,pairs22){let finalObject={};for(let pair of pairs22){let{key,value}=pair;if(key.status==="aborted"||value.status==="aborted")return INVALID2;key.status==="dirty"&&status.dirty(),value.status==="dirty"&&status.dirty(),key.value!=="__proto__"&&(typeof value.value<"u"||pair.alwaysSet)&&(finalObject[key.value]=value.value)}return{status:status.value,value:finalObject}}},INVALID2=Object.freeze({status:"aborted"}),DIRTY2=value=>({status:"dirty",value}),OK3=value=>({status:"valid",value}),isAborted2=x6=>x6.status==="aborted",isDirty2=x6=>x6.status==="dirty",isValid2=x6=>x6.status==="valid",isAsync2=x6=>typeof Promise<"u"&&x6 instanceof Promise,errorUtil2;(function(errorUtil22){errorUtil22.errToObj=message=>typeof message=="string"?{message}:message||{},errorUtil22.toString=message=>typeof message=="string"?message:message?.message})(errorUtil2||(errorUtil2={}));var ParseInputLazyPath2=class{constructor(parent,value,path,key){this._cachedPath=[],this.parent=parent,this.data=value,this._path=path,this._key=key}get path(){return this._cachedPath.length||(Array.isArray(this._key)?this._cachedPath.push(...this._path,...this._key):this._cachedPath.push(...this._path,this._key)),this._cachedPath}},handleResult2=(ctx,result)=>{if(isValid2(result))return{success:!0,data:result.value};if(!ctx.common.issues.length)throw new Error("Validation failed but no issues detected.");return{success:!1,get error(){if(this._error)return this._error;let error2=new ZodError2(ctx.common.issues);return this._error=error2,this._error}}};function processCreateParams2(params){if(!params)return{};let{errorMap:errorMap22,invalid_type_error,required_error,description}=params;if(errorMap22&&(invalid_type_error||required_error))throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);return errorMap22?{errorMap:errorMap22,description}:{errorMap:(iss,ctx)=>{let{message}=params;return iss.code==="invalid_enum_value"?{message:message??ctx.defaultError}:typeof ctx.data>"u"?{message:message??required_error??ctx.defaultError}:iss.code!=="invalid_type"?{message:ctx.defaultError}:{message:message??invalid_type_error??ctx.defaultError}},description}}var ZodType2=class{get description(){return this._def.description}_getType(input2){return getParsedType2(input2.data)}_getOrReturnCtx(input2,ctx){return ctx||{common:input2.parent.common,data:input2.data,parsedType:getParsedType2(input2.data),schemaErrorMap:this._def.errorMap,path:input2.path,parent:input2.parent}}_processInputParams(input2){return{status:new ParseStatus2,ctx:{common:input2.parent.common,data:input2.data,parsedType:getParsedType2(input2.data),schemaErrorMap:this._def.errorMap,path:input2.path,parent:input2.parent}}}_parseSync(input2){let result=this._parse(input2);if(isAsync2(result))throw new Error("Synchronous parse encountered promise.");return result}_parseAsync(input2){let result=this._parse(input2);return Promise.resolve(result)}parse(data,params){let result=this.safeParse(data,params);if(result.success)return result.data;throw result.error}safeParse(data,params){let ctx={common:{issues:[],async:params?.async??!1,contextualErrorMap:params?.errorMap},path:params?.path||[],schemaErrorMap:this._def.errorMap,parent:null,data,parsedType:getParsedType2(data)},result=this._parseSync({data,path:ctx.path,parent:ctx});return handleResult2(ctx,result)}"~validate"(data){let ctx={common:{issues:[],async:!!this["~standard"].async},path:[],schemaErrorMap:this._def.errorMap,parent:null,data,parsedType:getParsedType2(data)};if(!this["~standard"].async)try{let result=this._parseSync({data,path:[],parent:ctx});return isValid2(result)?{value:result.value}:{issues:ctx.common.issues}}catch(err2){err2?.message?.toLowerCase()?.includes("encountered")&&(this["~standard"].async=!0),ctx.common={issues:[],async:!0}}return this._parseAsync({data,path:[],parent:ctx}).then(result=>isValid2(result)?{value:result.value}:{issues:ctx.common.issues})}async parseAsync(data,params){let result=await this.safeParseAsync(data,params);if(result.success)return result.data;throw result.error}async safeParseAsync(data,params){let ctx={common:{issues:[],contextualErrorMap:params?.errorMap,async:!0},path:params?.path||[],schemaErrorMap:this._def.errorMap,parent:null,data,parsedType:getParsedType2(data)},maybeAsyncResult=this._parse({data,path:ctx.path,parent:ctx}),result=await(isAsync2(maybeAsyncResult)?maybeAsyncResult:Promise.resolve(maybeAsyncResult));return handleResult2(ctx,result)}refine(check,message){let getIssueProperties=val=>typeof message=="string"||typeof message>"u"?{message}:typeof message=="function"?message(val):message;return this._refinement((val,ctx)=>{let result=check(val),setError=()=>ctx.addIssue({code:ZodIssueCode2.custom,...getIssueProperties(val)});return typeof Promise<"u"&&result instanceof Promise?result.then(data=>data?!0:(setError(),!1)):result?!0:(setError(),!1)})}refinement(check,refinementData){return this._refinement((val,ctx)=>check(val)?!0:(ctx.addIssue(typeof refinementData=="function"?refinementData(val,ctx):refinementData),!1))}_refinement(refinement){return new ZodEffects2({schema:this,typeName:ZodFirstPartyTypeKind2.ZodEffects,effect:{type:"refinement",refinement}})}superRefine(refinement){return this._refinement(refinement)}constructor(def){this.spa=this.safeParseAsync,this._def=def,this.parse=this.parse.bind(this),this.safeParse=this.safeParse.bind(this),this.parseAsync=this.parseAsync.bind(this),this.safeParseAsync=this.safeParseAsync.bind(this),this.spa=this.spa.bind(this),this.refine=this.refine.bind(this),this.refinement=this.refinement.bind(this),this.superRefine=this.superRefine.bind(this),this.optional=this.optional.bind(this),this.nullable=this.nullable.bind(this),this.nullish=this.nullish.bind(this),this.array=this.array.bind(this),this.promise=this.promise.bind(this),this.or=this.or.bind(this),this.and=this.and.bind(this),this.transform=this.transform.bind(this),this.brand=this.brand.bind(this),this.default=this.default.bind(this),this.catch=this.catch.bind(this),this.describe=this.describe.bind(this),this.pipe=this.pipe.bind(this),this.readonly=this.readonly.bind(this),this.isNullable=this.isNullable.bind(this),this.isOptional=this.isOptional.bind(this),this["~standard"]={version:1,vendor:"zod",validate:data=>this["~validate"](data)}}optional(){return ZodOptional2.create(this,this._def)}nullable(){return ZodNullable2.create(this,this._def)}nullish(){return this.nullable().optional()}array(){return ZodArray2.create(this)}promise(){return ZodPromise2.create(this,this._def)}or(option){return ZodUnion2.create([this,option],this._def)}and(incoming){return ZodIntersection2.create(this,incoming,this._def)}transform(transform22){return new ZodEffects2({...processCreateParams2(this._def),schema:this,typeName:ZodFirstPartyTypeKind2.ZodEffects,effect:{type:"transform",transform:transform22}})}default(def){let defaultValueFunc=typeof def=="function"?def:()=>def;return new ZodDefault2({...processCreateParams2(this._def),innerType:this,defaultValue:defaultValueFunc,typeName:ZodFirstPartyTypeKind2.ZodDefault})}brand(){return new ZodBranded2({typeName:ZodFirstPartyTypeKind2.ZodBranded,type:this,...processCreateParams2(this._def)})}catch(def){let catchValueFunc=typeof def=="function"?def:()=>def;return new ZodCatch2({...processCreateParams2(this._def),innerType:this,catchValue:catchValueFunc,typeName:ZodFirstPartyTypeKind2.ZodCatch})}describe(description){let This=this.constructor;return new This({...this._def,description})}pipe(target){return ZodPipeline2.create(this,target)}readonly(){return ZodReadonly2.create(this)}isOptional(){return this.safeParse(void 0).success}isNullable(){return this.safeParse(null).success}},cuidRegex2=/^c[^\s-]{8,}$/i,cuid2Regex2=/^[0-9a-z]+$/,ulidRegex2=/^[0-9A-HJKMNP-TV-Z]{26}$/i,uuidRegex2=/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i,nanoidRegex2=/^[a-z0-9_-]{21}$/i,jwtRegex2=/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/,durationRegex2=/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/,emailRegex2=/^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i,_emojiRegex2="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$",emojiRegex2,ipv4Regex2=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ipv4CidrRegex2=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/,ipv6Regex2=/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,ipv6CidrRegex2=/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,base64Regex2=/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/,base64urlRegex2=/^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/,dateRegexSource2="((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))",dateRegex2=new RegExp(`^${dateRegexSource2}$`);function timeRegexSource2(args){let secondsRegexSource="[0-5]\\d";args.precision?secondsRegexSource=`${secondsRegexSource}\\.\\d{${args.precision}}`:args.precision==null&&(secondsRegexSource=`${secondsRegexSource}(\\.\\d+)?`);let secondsQuantifier=args.precision?"+":"?";return`([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`}function timeRegex2(args){return new RegExp(`^${timeRegexSource2(args)}$`)}function datetimeRegex2(args){let regex=`${dateRegexSource2}T${timeRegexSource2(args)}`,opts=[];return opts.push(args.local?"Z?":"Z"),args.offset&&opts.push("([+-]\\d{2}:?\\d{2})"),regex=`${regex}(${opts.join("|")})`,new RegExp(`^${regex}$`)}function isValidIP2(ip3,version2){return!!((version2==="v4"||!version2)&&ipv4Regex2.test(ip3)||(version2==="v6"||!version2)&&ipv6Regex2.test(ip3))}function isValidJWT2(jwt,alg){if(!jwtRegex2.test(jwt))return!1;try{let[header]=jwt.split(".");if(!header)return!1;let base64=header.replace(/-/g,"+").replace(/_/g,"/").padEnd(header.length+(4-header.length%4)%4,"="),decoded=JSON.parse(atob(base64));return!(typeof decoded!="object"||decoded===null||"typ"in decoded&&decoded?.typ!=="JWT"||!decoded.alg||alg&&decoded.alg!==alg)}catch{return!1}}function isValidCidr2(ip3,version2){return!!((version2==="v4"||!version2)&&ipv4CidrRegex2.test(ip3)||(version2==="v6"||!version2)&&ipv6CidrRegex2.test(ip3))}var ZodString2=class _ZodString extends ZodType2{_parse(input2){if(this._def.coerce&&(input2.data=String(input2.data)),this._getType(input2)!==ZodParsedType2.string){let ctx2=this._getOrReturnCtx(input2);return addIssueToContext2(ctx2,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.string,received:ctx2.parsedType}),INVALID2}let status=new ParseStatus2,ctx;for(let check of this._def.checks)if(check.kind==="min")input2.data.length<check.value&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,minimum:check.value,type:"string",inclusive:!0,exact:!1,message:check.message}),status.dirty());else if(check.kind==="max")input2.data.length>check.value&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,maximum:check.value,type:"string",inclusive:!0,exact:!1,message:check.message}),status.dirty());else if(check.kind==="length"){let tooBig=input2.data.length>check.value,tooSmall=input2.data.length<check.value;(tooBig||tooSmall)&&(ctx=this._getOrReturnCtx(input2,ctx),tooBig?addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,maximum:check.value,type:"string",inclusive:!0,exact:!0,message:check.message}):tooSmall&&addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,minimum:check.value,type:"string",inclusive:!0,exact:!0,message:check.message}),status.dirty())}else if(check.kind==="email")emailRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"email",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="emoji")emojiRegex2||(emojiRegex2=new RegExp(_emojiRegex2,"u")),emojiRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"emoji",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="uuid")uuidRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"uuid",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="nanoid")nanoidRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"nanoid",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="cuid")cuidRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"cuid",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="cuid2")cuid2Regex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"cuid2",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="ulid")ulidRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"ulid",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty());else if(check.kind==="url")try{new URL(input2.data)}catch{ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"url",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()}else check.kind==="regex"?(check.regex.lastIndex=0,check.regex.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"regex",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty())):check.kind==="trim"?input2.data=input2.data.trim():check.kind==="includes"?input2.data.includes(check.value,check.position)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_string,validation:{includes:check.value,position:check.position},message:check.message}),status.dirty()):check.kind==="toLowerCase"?input2.data=input2.data.toLowerCase():check.kind==="toUpperCase"?input2.data=input2.data.toUpperCase():check.kind==="startsWith"?input2.data.startsWith(check.value)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_string,validation:{startsWith:check.value},message:check.message}),status.dirty()):check.kind==="endsWith"?input2.data.endsWith(check.value)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_string,validation:{endsWith:check.value},message:check.message}),status.dirty()):check.kind==="datetime"?datetimeRegex2(check).test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_string,validation:"datetime",message:check.message}),status.dirty()):check.kind==="date"?dateRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_string,validation:"date",message:check.message}),status.dirty()):check.kind==="time"?timeRegex2(check).test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_string,validation:"time",message:check.message}),status.dirty()):check.kind==="duration"?durationRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"duration",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()):check.kind==="ip"?isValidIP2(input2.data,check.version)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"ip",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()):check.kind==="jwt"?isValidJWT2(input2.data,check.alg)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"jwt",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()):check.kind==="cidr"?isValidCidr2(input2.data,check.version)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"cidr",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()):check.kind==="base64"?base64Regex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"base64",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()):check.kind==="base64url"?base64urlRegex2.test(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{validation:"base64url",code:ZodIssueCode2.invalid_string,message:check.message}),status.dirty()):util2.assertNever(check);return{status:status.value,value:input2.data}}_regex(regex,validation,message){return this.refinement(data=>regex.test(data),{validation,code:ZodIssueCode2.invalid_string,...errorUtil2.errToObj(message)})}_addCheck(check){return new _ZodString({...this._def,checks:[...this._def.checks,check]})}email(message){return this._addCheck({kind:"email",...errorUtil2.errToObj(message)})}url(message){return this._addCheck({kind:"url",...errorUtil2.errToObj(message)})}emoji(message){return this._addCheck({kind:"emoji",...errorUtil2.errToObj(message)})}uuid(message){return this._addCheck({kind:"uuid",...errorUtil2.errToObj(message)})}nanoid(message){return this._addCheck({kind:"nanoid",...errorUtil2.errToObj(message)})}cuid(message){return this._addCheck({kind:"cuid",...errorUtil2.errToObj(message)})}cuid2(message){return this._addCheck({kind:"cuid2",...errorUtil2.errToObj(message)})}ulid(message){return this._addCheck({kind:"ulid",...errorUtil2.errToObj(message)})}base64(message){return this._addCheck({kind:"base64",...errorUtil2.errToObj(message)})}base64url(message){return this._addCheck({kind:"base64url",...errorUtil2.errToObj(message)})}jwt(options){return this._addCheck({kind:"jwt",...errorUtil2.errToObj(options)})}ip(options){return this._addCheck({kind:"ip",...errorUtil2.errToObj(options)})}cidr(options){return this._addCheck({kind:"cidr",...errorUtil2.errToObj(options)})}datetime(options){return typeof options=="string"?this._addCheck({kind:"datetime",precision:null,offset:!1,local:!1,message:options}):this._addCheck({kind:"datetime",precision:typeof options?.precision>"u"?null:options?.precision,offset:options?.offset??!1,local:options?.local??!1,...errorUtil2.errToObj(options?.message)})}date(message){return this._addCheck({kind:"date",message})}time(options){return typeof options=="string"?this._addCheck({kind:"time",precision:null,message:options}):this._addCheck({kind:"time",precision:typeof options?.precision>"u"?null:options?.precision,...errorUtil2.errToObj(options?.message)})}duration(message){return this._addCheck({kind:"duration",...errorUtil2.errToObj(message)})}regex(regex,message){return this._addCheck({kind:"regex",regex,...errorUtil2.errToObj(message)})}includes(value,options){return this._addCheck({kind:"includes",value,position:options?.position,...errorUtil2.errToObj(options?.message)})}startsWith(value,message){return this._addCheck({kind:"startsWith",value,...errorUtil2.errToObj(message)})}endsWith(value,message){return this._addCheck({kind:"endsWith",value,...errorUtil2.errToObj(message)})}min(minLength,message){return this._addCheck({kind:"min",value:minLength,...errorUtil2.errToObj(message)})}max(maxLength,message){return this._addCheck({kind:"max",value:maxLength,...errorUtil2.errToObj(message)})}length(len,message){return this._addCheck({kind:"length",value:len,...errorUtil2.errToObj(message)})}nonempty(message){return this.min(1,errorUtil2.errToObj(message))}trim(){return new _ZodString({...this._def,checks:[...this._def.checks,{kind:"trim"}]})}toLowerCase(){return new _ZodString({...this._def,checks:[...this._def.checks,{kind:"toLowerCase"}]})}toUpperCase(){return new _ZodString({...this._def,checks:[...this._def.checks,{kind:"toUpperCase"}]})}get isDatetime(){return!!this._def.checks.find(ch2=>ch2.kind==="datetime")}get isDate(){return!!this._def.checks.find(ch2=>ch2.kind==="date")}get isTime(){return!!this._def.checks.find(ch2=>ch2.kind==="time")}get isDuration(){return!!this._def.checks.find(ch2=>ch2.kind==="duration")}get isEmail(){return!!this._def.checks.find(ch2=>ch2.kind==="email")}get isURL(){return!!this._def.checks.find(ch2=>ch2.kind==="url")}get isEmoji(){return!!this._def.checks.find(ch2=>ch2.kind==="emoji")}get isUUID(){return!!this._def.checks.find(ch2=>ch2.kind==="uuid")}get isNANOID(){return!!this._def.checks.find(ch2=>ch2.kind==="nanoid")}get isCUID(){return!!this._def.checks.find(ch2=>ch2.kind==="cuid")}get isCUID2(){return!!this._def.checks.find(ch2=>ch2.kind==="cuid2")}get isULID(){return!!this._def.checks.find(ch2=>ch2.kind==="ulid")}get isIP(){return!!this._def.checks.find(ch2=>ch2.kind==="ip")}get isCIDR(){return!!this._def.checks.find(ch2=>ch2.kind==="cidr")}get isBase64(){return!!this._def.checks.find(ch2=>ch2.kind==="base64")}get isBase64url(){return!!this._def.checks.find(ch2=>ch2.kind==="base64url")}get minLength(){let min=null;for(let ch2 of this._def.checks)ch2.kind==="min"&&(min===null||ch2.value>min)&&(min=ch2.value);return min}get maxLength(){let max2=null;for(let ch2 of this._def.checks)ch2.kind==="max"&&(max2===null||ch2.value<max2)&&(max2=ch2.value);return max2}};ZodString2.create=params=>new ZodString2({checks:[],typeName:ZodFirstPartyTypeKind2.ZodString,coerce:params?.coerce??!1,...processCreateParams2(params)});function floatSafeRemainder2(val,step){let valDecCount=(val.toString().split(".")[1]||"").length,stepDecCount=(step.toString().split(".")[1]||"").length,decCount=valDecCount>stepDecCount?valDecCount:stepDecCount,valInt=Number.parseInt(val.toFixed(decCount).replace(".","")),stepInt=Number.parseInt(step.toFixed(decCount).replace(".",""));return valInt%stepInt/10**decCount}var ZodNumber2=class _ZodNumber extends ZodType2{constructor(){super(...arguments),this.min=this.gte,this.max=this.lte,this.step=this.multipleOf}_parse(input2){if(this._def.coerce&&(input2.data=Number(input2.data)),this._getType(input2)!==ZodParsedType2.number){let ctx2=this._getOrReturnCtx(input2);return addIssueToContext2(ctx2,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.number,received:ctx2.parsedType}),INVALID2}let ctx,status=new ParseStatus2;for(let check of this._def.checks)check.kind==="int"?util2.isInteger(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:"integer",received:"float",message:check.message}),status.dirty()):check.kind==="min"?(check.inclusive?input2.data<check.value:input2.data<=check.value)&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,minimum:check.value,type:"number",inclusive:check.inclusive,exact:!1,message:check.message}),status.dirty()):check.kind==="max"?(check.inclusive?input2.data>check.value:input2.data>=check.value)&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,maximum:check.value,type:"number",inclusive:check.inclusive,exact:!1,message:check.message}),status.dirty()):check.kind==="multipleOf"?floatSafeRemainder2(input2.data,check.value)!==0&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.not_multiple_of,multipleOf:check.value,message:check.message}),status.dirty()):check.kind==="finite"?Number.isFinite(input2.data)||(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.not_finite,message:check.message}),status.dirty()):util2.assertNever(check);return{status:status.value,value:input2.data}}gte(value,message){return this.setLimit("min",value,!0,errorUtil2.toString(message))}gt(value,message){return this.setLimit("min",value,!1,errorUtil2.toString(message))}lte(value,message){return this.setLimit("max",value,!0,errorUtil2.toString(message))}lt(value,message){return this.setLimit("max",value,!1,errorUtil2.toString(message))}setLimit(kind,value,inclusive,message){return new _ZodNumber({...this._def,checks:[...this._def.checks,{kind,value,inclusive,message:errorUtil2.toString(message)}]})}_addCheck(check){return new _ZodNumber({...this._def,checks:[...this._def.checks,check]})}int(message){return this._addCheck({kind:"int",message:errorUtil2.toString(message)})}positive(message){return this._addCheck({kind:"min",value:0,inclusive:!1,message:errorUtil2.toString(message)})}negative(message){return this._addCheck({kind:"max",value:0,inclusive:!1,message:errorUtil2.toString(message)})}nonpositive(message){return this._addCheck({kind:"max",value:0,inclusive:!0,message:errorUtil2.toString(message)})}nonnegative(message){return this._addCheck({kind:"min",value:0,inclusive:!0,message:errorUtil2.toString(message)})}multipleOf(value,message){return this._addCheck({kind:"multipleOf",value,message:errorUtil2.toString(message)})}finite(message){return this._addCheck({kind:"finite",message:errorUtil2.toString(message)})}safe(message){return this._addCheck({kind:"min",inclusive:!0,value:Number.MIN_SAFE_INTEGER,message:errorUtil2.toString(message)})._addCheck({kind:"max",inclusive:!0,value:Number.MAX_SAFE_INTEGER,message:errorUtil2.toString(message)})}get minValue(){let min=null;for(let ch2 of this._def.checks)ch2.kind==="min"&&(min===null||ch2.value>min)&&(min=ch2.value);return min}get maxValue(){let max2=null;for(let ch2 of this._def.checks)ch2.kind==="max"&&(max2===null||ch2.value<max2)&&(max2=ch2.value);return max2}get isInt(){return!!this._def.checks.find(ch2=>ch2.kind==="int"||ch2.kind==="multipleOf"&&util2.isInteger(ch2.value))}get isFinite(){let max2=null,min=null;for(let ch2 of this._def.checks){if(ch2.kind==="finite"||ch2.kind==="int"||ch2.kind==="multipleOf")return!0;ch2.kind==="min"?(min===null||ch2.value>min)&&(min=ch2.value):ch2.kind==="max"&&(max2===null||ch2.value<max2)&&(max2=ch2.value)}return Number.isFinite(min)&&Number.isFinite(max2)}};ZodNumber2.create=params=>new ZodNumber2({checks:[],typeName:ZodFirstPartyTypeKind2.ZodNumber,coerce:params?.coerce||!1,...processCreateParams2(params)});var ZodBigInt2=class _ZodBigInt extends ZodType2{constructor(){super(...arguments),this.min=this.gte,this.max=this.lte}_parse(input2){if(this._def.coerce)try{input2.data=BigInt(input2.data)}catch{return this._getInvalidInput(input2)}if(this._getType(input2)!==ZodParsedType2.bigint)return this._getInvalidInput(input2);let ctx,status=new ParseStatus2;for(let check of this._def.checks)check.kind==="min"?(check.inclusive?input2.data<check.value:input2.data<=check.value)&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,type:"bigint",minimum:check.value,inclusive:check.inclusive,message:check.message}),status.dirty()):check.kind==="max"?(check.inclusive?input2.data>check.value:input2.data>=check.value)&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,type:"bigint",maximum:check.value,inclusive:check.inclusive,message:check.message}),status.dirty()):check.kind==="multipleOf"?input2.data%check.value!==BigInt(0)&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.not_multiple_of,multipleOf:check.value,message:check.message}),status.dirty()):util2.assertNever(check);return{status:status.value,value:input2.data}}_getInvalidInput(input2){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.bigint,received:ctx.parsedType}),INVALID2}gte(value,message){return this.setLimit("min",value,!0,errorUtil2.toString(message))}gt(value,message){return this.setLimit("min",value,!1,errorUtil2.toString(message))}lte(value,message){return this.setLimit("max",value,!0,errorUtil2.toString(message))}lt(value,message){return this.setLimit("max",value,!1,errorUtil2.toString(message))}setLimit(kind,value,inclusive,message){return new _ZodBigInt({...this._def,checks:[...this._def.checks,{kind,value,inclusive,message:errorUtil2.toString(message)}]})}_addCheck(check){return new _ZodBigInt({...this._def,checks:[...this._def.checks,check]})}positive(message){return this._addCheck({kind:"min",value:BigInt(0),inclusive:!1,message:errorUtil2.toString(message)})}negative(message){return this._addCheck({kind:"max",value:BigInt(0),inclusive:!1,message:errorUtil2.toString(message)})}nonpositive(message){return this._addCheck({kind:"max",value:BigInt(0),inclusive:!0,message:errorUtil2.toString(message)})}nonnegative(message){return this._addCheck({kind:"min",value:BigInt(0),inclusive:!0,message:errorUtil2.toString(message)})}multipleOf(value,message){return this._addCheck({kind:"multipleOf",value,message:errorUtil2.toString(message)})}get minValue(){let min=null;for(let ch2 of this._def.checks)ch2.kind==="min"&&(min===null||ch2.value>min)&&(min=ch2.value);return min}get maxValue(){let max2=null;for(let ch2 of this._def.checks)ch2.kind==="max"&&(max2===null||ch2.value<max2)&&(max2=ch2.value);return max2}};ZodBigInt2.create=params=>new ZodBigInt2({checks:[],typeName:ZodFirstPartyTypeKind2.ZodBigInt,coerce:params?.coerce??!1,...processCreateParams2(params)});var ZodBoolean2=class extends ZodType2{_parse(input2){if(this._def.coerce&&(input2.data=!!input2.data),this._getType(input2)!==ZodParsedType2.boolean){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.boolean,received:ctx.parsedType}),INVALID2}return OK3(input2.data)}};ZodBoolean2.create=params=>new ZodBoolean2({typeName:ZodFirstPartyTypeKind2.ZodBoolean,coerce:params?.coerce||!1,...processCreateParams2(params)});var ZodDate2=class _ZodDate extends ZodType2{_parse(input2){if(this._def.coerce&&(input2.data=new Date(input2.data)),this._getType(input2)!==ZodParsedType2.date){let ctx2=this._getOrReturnCtx(input2);return addIssueToContext2(ctx2,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.date,received:ctx2.parsedType}),INVALID2}if(Number.isNaN(input2.data.getTime())){let ctx2=this._getOrReturnCtx(input2);return addIssueToContext2(ctx2,{code:ZodIssueCode2.invalid_date}),INVALID2}let status=new ParseStatus2,ctx;for(let check of this._def.checks)check.kind==="min"?input2.data.getTime()<check.value&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,message:check.message,inclusive:!0,exact:!1,minimum:check.value,type:"date"}),status.dirty()):check.kind==="max"?input2.data.getTime()>check.value&&(ctx=this._getOrReturnCtx(input2,ctx),addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,message:check.message,inclusive:!0,exact:!1,maximum:check.value,type:"date"}),status.dirty()):util2.assertNever(check);return{status:status.value,value:new Date(input2.data.getTime())}}_addCheck(check){return new _ZodDate({...this._def,checks:[...this._def.checks,check]})}min(minDate,message){return this._addCheck({kind:"min",value:minDate.getTime(),message:errorUtil2.toString(message)})}max(maxDate,message){return this._addCheck({kind:"max",value:maxDate.getTime(),message:errorUtil2.toString(message)})}get minDate(){let min=null;for(let ch2 of this._def.checks)ch2.kind==="min"&&(min===null||ch2.value>min)&&(min=ch2.value);return min!=null?new Date(min):null}get maxDate(){let max2=null;for(let ch2 of this._def.checks)ch2.kind==="max"&&(max2===null||ch2.value<max2)&&(max2=ch2.value);return max2!=null?new Date(max2):null}};ZodDate2.create=params=>new ZodDate2({checks:[],coerce:params?.coerce||!1,typeName:ZodFirstPartyTypeKind2.ZodDate,...processCreateParams2(params)});var ZodSymbol2=class extends ZodType2{_parse(input2){if(this._getType(input2)!==ZodParsedType2.symbol){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.symbol,received:ctx.parsedType}),INVALID2}return OK3(input2.data)}};ZodSymbol2.create=params=>new ZodSymbol2({typeName:ZodFirstPartyTypeKind2.ZodSymbol,...processCreateParams2(params)});var ZodUndefined2=class extends ZodType2{_parse(input2){if(this._getType(input2)!==ZodParsedType2.undefined){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.undefined,received:ctx.parsedType}),INVALID2}return OK3(input2.data)}};ZodUndefined2.create=params=>new ZodUndefined2({typeName:ZodFirstPartyTypeKind2.ZodUndefined,...processCreateParams2(params)});var ZodNull2=class extends ZodType2{_parse(input2){if(this._getType(input2)!==ZodParsedType2.null){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.null,received:ctx.parsedType}),INVALID2}return OK3(input2.data)}};ZodNull2.create=params=>new ZodNull2({typeName:ZodFirstPartyTypeKind2.ZodNull,...processCreateParams2(params)});var ZodAny2=class extends ZodType2{constructor(){super(...arguments),this._any=!0}_parse(input2){return OK3(input2.data)}};ZodAny2.create=params=>new ZodAny2({typeName:ZodFirstPartyTypeKind2.ZodAny,...processCreateParams2(params)});var ZodUnknown2=class extends ZodType2{constructor(){super(...arguments),this._unknown=!0}_parse(input2){return OK3(input2.data)}};ZodUnknown2.create=params=>new ZodUnknown2({typeName:ZodFirstPartyTypeKind2.ZodUnknown,...processCreateParams2(params)});var ZodNever2=class extends ZodType2{_parse(input2){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.never,received:ctx.parsedType}),INVALID2}};ZodNever2.create=params=>new ZodNever2({typeName:ZodFirstPartyTypeKind2.ZodNever,...processCreateParams2(params)});var ZodVoid2=class extends ZodType2{_parse(input2){if(this._getType(input2)!==ZodParsedType2.undefined){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.void,received:ctx.parsedType}),INVALID2}return OK3(input2.data)}};ZodVoid2.create=params=>new ZodVoid2({typeName:ZodFirstPartyTypeKind2.ZodVoid,...processCreateParams2(params)});var ZodArray2=class _ZodArray extends ZodType2{_parse(input2){let{ctx,status}=this._processInputParams(input2),def=this._def;if(ctx.parsedType!==ZodParsedType2.array)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.array,received:ctx.parsedType}),INVALID2;if(def.exactLength!==null){let tooBig=ctx.data.length>def.exactLength.value,tooSmall=ctx.data.length<def.exactLength.value;(tooBig||tooSmall)&&(addIssueToContext2(ctx,{code:tooBig?ZodIssueCode2.too_big:ZodIssueCode2.too_small,minimum:tooSmall?def.exactLength.value:void 0,maximum:tooBig?def.exactLength.value:void 0,type:"array",inclusive:!0,exact:!0,message:def.exactLength.message}),status.dirty())}if(def.minLength!==null&&ctx.data.length<def.minLength.value&&(addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,minimum:def.minLength.value,type:"array",inclusive:!0,exact:!1,message:def.minLength.message}),status.dirty()),def.maxLength!==null&&ctx.data.length>def.maxLength.value&&(addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,maximum:def.maxLength.value,type:"array",inclusive:!0,exact:!1,message:def.maxLength.message}),status.dirty()),ctx.common.async)return Promise.all([...ctx.data].map((item,i6)=>def.type._parseAsync(new ParseInputLazyPath2(ctx,item,ctx.path,i6)))).then(result2=>ParseStatus2.mergeArray(status,result2));let result=[...ctx.data].map((item,i6)=>def.type._parseSync(new ParseInputLazyPath2(ctx,item,ctx.path,i6)));return ParseStatus2.mergeArray(status,result)}get element(){return this._def.type}min(minLength,message){return new _ZodArray({...this._def,minLength:{value:minLength,message:errorUtil2.toString(message)}})}max(maxLength,message){return new _ZodArray({...this._def,maxLength:{value:maxLength,message:errorUtil2.toString(message)}})}length(len,message){return new _ZodArray({...this._def,exactLength:{value:len,message:errorUtil2.toString(message)}})}nonempty(message){return this.min(1,message)}};ZodArray2.create=(schema,params)=>new ZodArray2({type:schema,minLength:null,maxLength:null,exactLength:null,typeName:ZodFirstPartyTypeKind2.ZodArray,...processCreateParams2(params)});function deepPartialify2(schema){if(schema instanceof ZodObject2){let newShape={};for(let key in schema.shape){let fieldSchema=schema.shape[key];newShape[key]=ZodOptional2.create(deepPartialify2(fieldSchema))}return new ZodObject2({...schema._def,shape:()=>newShape})}else return schema instanceof ZodArray2?new ZodArray2({...schema._def,type:deepPartialify2(schema.element)}):schema instanceof ZodOptional2?ZodOptional2.create(deepPartialify2(schema.unwrap())):schema instanceof ZodNullable2?ZodNullable2.create(deepPartialify2(schema.unwrap())):schema instanceof ZodTuple2?ZodTuple2.create(schema.items.map(item=>deepPartialify2(item))):schema}var ZodObject2=class _ZodObject extends ZodType2{constructor(){super(...arguments),this._cached=null,this.nonstrict=this.passthrough,this.augment=this.extend}_getCached(){if(this._cached!==null)return this._cached;let shape=this._def.shape(),keys=util2.objectKeys(shape);return this._cached={shape,keys},this._cached}_parse(input2){if(this._getType(input2)!==ZodParsedType2.object){let ctx2=this._getOrReturnCtx(input2);return addIssueToContext2(ctx2,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.object,received:ctx2.parsedType}),INVALID2}let{status,ctx}=this._processInputParams(input2),{shape,keys:shapeKeys}=this._getCached(),extraKeys=[];if(!(this._def.catchall instanceof ZodNever2&&this._def.unknownKeys==="strip"))for(let key in ctx.data)shapeKeys.includes(key)||extraKeys.push(key);let pairs22=[];for(let key of shapeKeys){let keyValidator=shape[key],value=ctx.data[key];pairs22.push({key:{status:"valid",value:key},value:keyValidator._parse(new ParseInputLazyPath2(ctx,value,ctx.path,key)),alwaysSet:key in ctx.data})}if(this._def.catchall instanceof ZodNever2){let unknownKeys=this._def.unknownKeys;if(unknownKeys==="passthrough")for(let key of extraKeys)pairs22.push({key:{status:"valid",value:key},value:{status:"valid",value:ctx.data[key]}});else if(unknownKeys==="strict")extraKeys.length>0&&(addIssueToContext2(ctx,{code:ZodIssueCode2.unrecognized_keys,keys:extraKeys}),status.dirty());else if(unknownKeys!=="strip")throw new Error("Internal ZodObject error: invalid unknownKeys value.")}else{let catchall=this._def.catchall;for(let key of extraKeys){let value=ctx.data[key];pairs22.push({key:{status:"valid",value:key},value:catchall._parse(new ParseInputLazyPath2(ctx,value,ctx.path,key)),alwaysSet:key in ctx.data})}}return ctx.common.async?Promise.resolve().then(async()=>{let syncPairs=[];for(let pair of pairs22){let key=await pair.key,value=await pair.value;syncPairs.push({key,value,alwaysSet:pair.alwaysSet})}return syncPairs}).then(syncPairs=>ParseStatus2.mergeObjectSync(status,syncPairs)):ParseStatus2.mergeObjectSync(status,pairs22)}get shape(){return this._def.shape()}strict(message){return errorUtil2.errToObj,new _ZodObject({...this._def,unknownKeys:"strict",...message!==void 0?{errorMap:(issue,ctx)=>{let defaultError=this._def.errorMap?.(issue,ctx).message??ctx.defaultError;return issue.code==="unrecognized_keys"?{message:errorUtil2.errToObj(message).message??defaultError}:{message:defaultError}}}:{}})}strip(){return new _ZodObject({...this._def,unknownKeys:"strip"})}passthrough(){return new _ZodObject({...this._def,unknownKeys:"passthrough"})}extend(augmentation){return new _ZodObject({...this._def,shape:()=>({...this._def.shape(),...augmentation})})}merge(merging){return new _ZodObject({unknownKeys:merging._def.unknownKeys,catchall:merging._def.catchall,shape:()=>({...this._def.shape(),...merging._def.shape()}),typeName:ZodFirstPartyTypeKind2.ZodObject})}setKey(key,schema){return this.augment({[key]:schema})}catchall(index){return new _ZodObject({...this._def,catchall:index})}pick(mask){let shape={};for(let key of util2.objectKeys(mask))mask[key]&&this.shape[key]&&(shape[key]=this.shape[key]);return new _ZodObject({...this._def,shape:()=>shape})}omit(mask){let shape={};for(let key of util2.objectKeys(this.shape))mask[key]||(shape[key]=this.shape[key]);return new _ZodObject({...this._def,shape:()=>shape})}deepPartial(){return deepPartialify2(this)}partial(mask){let newShape={};for(let key of util2.objectKeys(this.shape)){let fieldSchema=this.shape[key];mask&&!mask[key]?newShape[key]=fieldSchema:newShape[key]=fieldSchema.optional()}return new _ZodObject({...this._def,shape:()=>newShape})}required(mask){let newShape={};for(let key of util2.objectKeys(this.shape))if(mask&&!mask[key])newShape[key]=this.shape[key];else{let newField=this.shape[key];for(;newField instanceof ZodOptional2;)newField=newField._def.innerType;newShape[key]=newField}return new _ZodObject({...this._def,shape:()=>newShape})}keyof(){return createZodEnum2(util2.objectKeys(this.shape))}};ZodObject2.create=(shape,params)=>new ZodObject2({shape:()=>shape,unknownKeys:"strip",catchall:ZodNever2.create(),typeName:ZodFirstPartyTypeKind2.ZodObject,...processCreateParams2(params)});ZodObject2.strictCreate=(shape,params)=>new ZodObject2({shape:()=>shape,unknownKeys:"strict",catchall:ZodNever2.create(),typeName:ZodFirstPartyTypeKind2.ZodObject,...processCreateParams2(params)});ZodObject2.lazycreate=(shape,params)=>new ZodObject2({shape,unknownKeys:"strip",catchall:ZodNever2.create(),typeName:ZodFirstPartyTypeKind2.ZodObject,...processCreateParams2(params)});var ZodUnion2=class extends ZodType2{_parse(input2){let{ctx}=this._processInputParams(input2),options=this._def.options;function handleResults(results){for(let result of results)if(result.result.status==="valid")return result.result;for(let result of results)if(result.result.status==="dirty")return ctx.common.issues.push(...result.ctx.common.issues),result.result;let unionErrors=results.map(result=>new ZodError2(result.ctx.common.issues));return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_union,unionErrors}),INVALID2}if(ctx.common.async)return Promise.all(options.map(async option=>{let childCtx={...ctx,common:{...ctx.common,issues:[]},parent:null};return{result:await option._parseAsync({data:ctx.data,path:ctx.path,parent:childCtx}),ctx:childCtx}})).then(handleResults);{let dirty,issues=[];for(let option of options){let childCtx={...ctx,common:{...ctx.common,issues:[]},parent:null},result=option._parseSync({data:ctx.data,path:ctx.path,parent:childCtx});if(result.status==="valid")return result;result.status==="dirty"&&!dirty&&(dirty={result,ctx:childCtx}),childCtx.common.issues.length&&issues.push(childCtx.common.issues)}if(dirty)return ctx.common.issues.push(...dirty.ctx.common.issues),dirty.result;let unionErrors=issues.map(issues2=>new ZodError2(issues2));return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_union,unionErrors}),INVALID2}}get options(){return this._def.options}};ZodUnion2.create=(types,params)=>new ZodUnion2({options:types,typeName:ZodFirstPartyTypeKind2.ZodUnion,...processCreateParams2(params)});var getDiscriminator2=type=>type instanceof ZodLazy2?getDiscriminator2(type.schema):type instanceof ZodEffects2?getDiscriminator2(type.innerType()):type instanceof ZodLiteral2?[type.value]:type instanceof ZodEnum2?type.options:type instanceof ZodNativeEnum2?util2.objectValues(type.enum):type instanceof ZodDefault2?getDiscriminator2(type._def.innerType):type instanceof ZodUndefined2?[void 0]:type instanceof ZodNull2?[null]:type instanceof ZodOptional2?[void 0,...getDiscriminator2(type.unwrap())]:type instanceof ZodNullable2?[null,...getDiscriminator2(type.unwrap())]:type instanceof ZodBranded2||type instanceof ZodReadonly2?getDiscriminator2(type.unwrap()):type instanceof ZodCatch2?getDiscriminator2(type._def.innerType):[],ZodDiscriminatedUnion2=class _ZodDiscriminatedUnion extends ZodType2{_parse(input2){let{ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.object)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.object,received:ctx.parsedType}),INVALID2;let discriminator=this.discriminator,discriminatorValue=ctx.data[discriminator],option=this.optionsMap.get(discriminatorValue);return option?ctx.common.async?option._parseAsync({data:ctx.data,path:ctx.path,parent:ctx}):option._parseSync({data:ctx.data,path:ctx.path,parent:ctx}):(addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_union_discriminator,options:Array.from(this.optionsMap.keys()),path:[discriminator]}),INVALID2)}get discriminator(){return this._def.discriminator}get options(){return this._def.options}get optionsMap(){return this._def.optionsMap}static create(discriminator,options,params){let optionsMap=new Map;for(let type of options){let discriminatorValues=getDiscriminator2(type.shape[discriminator]);if(!discriminatorValues.length)throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);for(let value of discriminatorValues){if(optionsMap.has(value))throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);optionsMap.set(value,type)}}return new _ZodDiscriminatedUnion({typeName:ZodFirstPartyTypeKind2.ZodDiscriminatedUnion,discriminator,options,optionsMap,...processCreateParams2(params)})}};function mergeValues2(a6,b6){let aType=getParsedType2(a6),bType=getParsedType2(b6);if(a6===b6)return{valid:!0,data:a6};if(aType===ZodParsedType2.object&&bType===ZodParsedType2.object){let bKeys=util2.objectKeys(b6),sharedKeys=util2.objectKeys(a6).filter(key=>bKeys.indexOf(key)!==-1),newObj={...a6,...b6};for(let key of sharedKeys){let sharedValue=mergeValues2(a6[key],b6[key]);if(!sharedValue.valid)return{valid:!1};newObj[key]=sharedValue.data}return{valid:!0,data:newObj}}else if(aType===ZodParsedType2.array&&bType===ZodParsedType2.array){if(a6.length!==b6.length)return{valid:!1};let newArray=[];for(let index=0;index<a6.length;index++){let itemA=a6[index],itemB=b6[index],sharedValue=mergeValues2(itemA,itemB);if(!sharedValue.valid)return{valid:!1};newArray.push(sharedValue.data)}return{valid:!0,data:newArray}}else return aType===ZodParsedType2.date&&bType===ZodParsedType2.date&&+a6==+b6?{valid:!0,data:a6}:{valid:!1}}var ZodIntersection2=class extends ZodType2{_parse(input2){let{status,ctx}=this._processInputParams(input2),handleParsed=(parsedLeft,parsedRight)=>{if(isAborted2(parsedLeft)||isAborted2(parsedRight))return INVALID2;let merged=mergeValues2(parsedLeft.value,parsedRight.value);return merged.valid?((isDirty2(parsedLeft)||isDirty2(parsedRight))&&status.dirty(),{status:status.value,value:merged.data}):(addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_intersection_types}),INVALID2)};return ctx.common.async?Promise.all([this._def.left._parseAsync({data:ctx.data,path:ctx.path,parent:ctx}),this._def.right._parseAsync({data:ctx.data,path:ctx.path,parent:ctx})]).then(([left,right])=>handleParsed(left,right)):handleParsed(this._def.left._parseSync({data:ctx.data,path:ctx.path,parent:ctx}),this._def.right._parseSync({data:ctx.data,path:ctx.path,parent:ctx}))}};ZodIntersection2.create=(left,right,params)=>new ZodIntersection2({left,right,typeName:ZodFirstPartyTypeKind2.ZodIntersection,...processCreateParams2(params)});var ZodTuple2=class _ZodTuple extends ZodType2{_parse(input2){let{status,ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.array)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.array,received:ctx.parsedType}),INVALID2;if(ctx.data.length<this._def.items.length)return addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,minimum:this._def.items.length,inclusive:!0,exact:!1,type:"array"}),INVALID2;!this._def.rest&&ctx.data.length>this._def.items.length&&(addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,maximum:this._def.items.length,inclusive:!0,exact:!1,type:"array"}),status.dirty());let items=[...ctx.data].map((item,itemIndex)=>{let schema=this._def.items[itemIndex]||this._def.rest;return schema?schema._parse(new ParseInputLazyPath2(ctx,item,ctx.path,itemIndex)):null}).filter(x6=>!!x6);return ctx.common.async?Promise.all(items).then(results=>ParseStatus2.mergeArray(status,results)):ParseStatus2.mergeArray(status,items)}get items(){return this._def.items}rest(rest){return new _ZodTuple({...this._def,rest})}};ZodTuple2.create=(schemas,params)=>{if(!Array.isArray(schemas))throw new Error("You must pass an array of schemas to z.tuple([ ... ])");return new ZodTuple2({items:schemas,typeName:ZodFirstPartyTypeKind2.ZodTuple,rest:null,...processCreateParams2(params)})};var ZodRecord2=class _ZodRecord extends ZodType2{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(input2){let{status,ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.object)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.object,received:ctx.parsedType}),INVALID2;let pairs22=[],keyType=this._def.keyType,valueType=this._def.valueType;for(let key in ctx.data)pairs22.push({key:keyType._parse(new ParseInputLazyPath2(ctx,key,ctx.path,key)),value:valueType._parse(new ParseInputLazyPath2(ctx,ctx.data[key],ctx.path,key)),alwaysSet:key in ctx.data});return ctx.common.async?ParseStatus2.mergeObjectAsync(status,pairs22):ParseStatus2.mergeObjectSync(status,pairs22)}get element(){return this._def.valueType}static create(first,second,third){return second instanceof ZodType2?new _ZodRecord({keyType:first,valueType:second,typeName:ZodFirstPartyTypeKind2.ZodRecord,...processCreateParams2(third)}):new _ZodRecord({keyType:ZodString2.create(),valueType:first,typeName:ZodFirstPartyTypeKind2.ZodRecord,...processCreateParams2(second)})}},ZodMap2=class extends ZodType2{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(input2){let{status,ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.map)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.map,received:ctx.parsedType}),INVALID2;let keyType=this._def.keyType,valueType=this._def.valueType,pairs22=[...ctx.data.entries()].map(([key,value],index)=>({key:keyType._parse(new ParseInputLazyPath2(ctx,key,ctx.path,[index,"key"])),value:valueType._parse(new ParseInputLazyPath2(ctx,value,ctx.path,[index,"value"]))}));if(ctx.common.async){let finalMap=new Map;return Promise.resolve().then(async()=>{for(let pair of pairs22){let key=await pair.key,value=await pair.value;if(key.status==="aborted"||value.status==="aborted")return INVALID2;(key.status==="dirty"||value.status==="dirty")&&status.dirty(),finalMap.set(key.value,value.value)}return{status:status.value,value:finalMap}})}else{let finalMap=new Map;for(let pair of pairs22){let key=pair.key,value=pair.value;if(key.status==="aborted"||value.status==="aborted")return INVALID2;(key.status==="dirty"||value.status==="dirty")&&status.dirty(),finalMap.set(key.value,value.value)}return{status:status.value,value:finalMap}}}};ZodMap2.create=(keyType,valueType,params)=>new ZodMap2({valueType,keyType,typeName:ZodFirstPartyTypeKind2.ZodMap,...processCreateParams2(params)});var ZodSet2=class _ZodSet extends ZodType2{_parse(input2){let{status,ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.set)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.set,received:ctx.parsedType}),INVALID2;let def=this._def;def.minSize!==null&&ctx.data.size<def.minSize.value&&(addIssueToContext2(ctx,{code:ZodIssueCode2.too_small,minimum:def.minSize.value,type:"set",inclusive:!0,exact:!1,message:def.minSize.message}),status.dirty()),def.maxSize!==null&&ctx.data.size>def.maxSize.value&&(addIssueToContext2(ctx,{code:ZodIssueCode2.too_big,maximum:def.maxSize.value,type:"set",inclusive:!0,exact:!1,message:def.maxSize.message}),status.dirty());let valueType=this._def.valueType;function finalizeSet(elements2){let parsedSet=new Set;for(let element of elements2){if(element.status==="aborted")return INVALID2;element.status==="dirty"&&status.dirty(),parsedSet.add(element.value)}return{status:status.value,value:parsedSet}}let elements=[...ctx.data.values()].map((item,i6)=>valueType._parse(new ParseInputLazyPath2(ctx,item,ctx.path,i6)));return ctx.common.async?Promise.all(elements).then(elements2=>finalizeSet(elements2)):finalizeSet(elements)}min(minSize,message){return new _ZodSet({...this._def,minSize:{value:minSize,message:errorUtil2.toString(message)}})}max(maxSize,message){return new _ZodSet({...this._def,maxSize:{value:maxSize,message:errorUtil2.toString(message)}})}size(size22,message){return this.min(size22,message).max(size22,message)}nonempty(message){return this.min(1,message)}};ZodSet2.create=(valueType,params)=>new ZodSet2({valueType,minSize:null,maxSize:null,typeName:ZodFirstPartyTypeKind2.ZodSet,...processCreateParams2(params)});var ZodFunction2=class _ZodFunction extends ZodType2{constructor(){super(...arguments),this.validate=this.implement}_parse(input2){let{ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.function)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.function,received:ctx.parsedType}),INVALID2;function makeArgsIssue(args,error2){return makeIssue2({data:args,path:ctx.path,errorMaps:[ctx.common.contextualErrorMap,ctx.schemaErrorMap,getErrorMap2(),en_default2].filter(x6=>!!x6),issueData:{code:ZodIssueCode2.invalid_arguments,argumentsError:error2}})}function makeReturnsIssue(returns,error2){return makeIssue2({data:returns,path:ctx.path,errorMaps:[ctx.common.contextualErrorMap,ctx.schemaErrorMap,getErrorMap2(),en_default2].filter(x6=>!!x6),issueData:{code:ZodIssueCode2.invalid_return_type,returnTypeError:error2}})}let params={errorMap:ctx.common.contextualErrorMap},fn3=ctx.data;if(this._def.returns instanceof ZodPromise2){let me3=this;return OK3(async function(...args){let error2=new ZodError2([]),parsedArgs=await me3._def.args.parseAsync(args,params).catch(e6=>{throw error2.addIssue(makeArgsIssue(args,e6)),error2}),result=await Reflect.apply(fn3,this,parsedArgs);return await me3._def.returns._def.type.parseAsync(result,params).catch(e6=>{throw error2.addIssue(makeReturnsIssue(result,e6)),error2})})}else{let me3=this;return OK3(function(...args){let parsedArgs=me3._def.args.safeParse(args,params);if(!parsedArgs.success)throw new ZodError2([makeArgsIssue(args,parsedArgs.error)]);let result=Reflect.apply(fn3,this,parsedArgs.data),parsedReturns=me3._def.returns.safeParse(result,params);if(!parsedReturns.success)throw new ZodError2([makeReturnsIssue(result,parsedReturns.error)]);return parsedReturns.data})}}parameters(){return this._def.args}returnType(){return this._def.returns}args(...items){return new _ZodFunction({...this._def,args:ZodTuple2.create(items).rest(ZodUnknown2.create())})}returns(returnType){return new _ZodFunction({...this._def,returns:returnType})}implement(func){return this.parse(func)}strictImplement(func){return this.parse(func)}static create(args,returns,params){return new _ZodFunction({args:args||ZodTuple2.create([]).rest(ZodUnknown2.create()),returns:returns||ZodUnknown2.create(),typeName:ZodFirstPartyTypeKind2.ZodFunction,...processCreateParams2(params)})}},ZodLazy2=class extends ZodType2{get schema(){return this._def.getter()}_parse(input2){let{ctx}=this._processInputParams(input2);return this._def.getter()._parse({data:ctx.data,path:ctx.path,parent:ctx})}};ZodLazy2.create=(getter,params)=>new ZodLazy2({getter,typeName:ZodFirstPartyTypeKind2.ZodLazy,...processCreateParams2(params)});var ZodLiteral2=class extends ZodType2{_parse(input2){if(input2.data!==this._def.value){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{received:ctx.data,code:ZodIssueCode2.invalid_literal,expected:this._def.value}),INVALID2}return{status:"valid",value:input2.data}}get value(){return this._def.value}};ZodLiteral2.create=(value,params)=>new ZodLiteral2({value,typeName:ZodFirstPartyTypeKind2.ZodLiteral,...processCreateParams2(params)});function createZodEnum2(values,params){return new ZodEnum2({values,typeName:ZodFirstPartyTypeKind2.ZodEnum,...processCreateParams2(params)})}var ZodEnum2=class _ZodEnum extends ZodType2{_parse(input2){if(typeof input2.data!="string"){let ctx=this._getOrReturnCtx(input2),expectedValues=this._def.values;return addIssueToContext2(ctx,{expected:util2.joinValues(expectedValues),received:ctx.parsedType,code:ZodIssueCode2.invalid_type}),INVALID2}if(this._cache||(this._cache=new Set(this._def.values)),!this._cache.has(input2.data)){let ctx=this._getOrReturnCtx(input2),expectedValues=this._def.values;return addIssueToContext2(ctx,{received:ctx.data,code:ZodIssueCode2.invalid_enum_value,options:expectedValues}),INVALID2}return OK3(input2.data)}get options(){return this._def.values}get enum(){let enumValues={};for(let val of this._def.values)enumValues[val]=val;return enumValues}get Values(){let enumValues={};for(let val of this._def.values)enumValues[val]=val;return enumValues}get Enum(){let enumValues={};for(let val of this._def.values)enumValues[val]=val;return enumValues}extract(values,newDef=this._def){return _ZodEnum.create(values,{...this._def,...newDef})}exclude(values,newDef=this._def){return _ZodEnum.create(this.options.filter(opt2=>!values.includes(opt2)),{...this._def,...newDef})}};ZodEnum2.create=createZodEnum2;var ZodNativeEnum2=class extends ZodType2{_parse(input2){let nativeEnumValues=util2.getValidEnumValues(this._def.values),ctx=this._getOrReturnCtx(input2);if(ctx.parsedType!==ZodParsedType2.string&&ctx.parsedType!==ZodParsedType2.number){let expectedValues=util2.objectValues(nativeEnumValues);return addIssueToContext2(ctx,{expected:util2.joinValues(expectedValues),received:ctx.parsedType,code:ZodIssueCode2.invalid_type}),INVALID2}if(this._cache||(this._cache=new Set(util2.getValidEnumValues(this._def.values))),!this._cache.has(input2.data)){let expectedValues=util2.objectValues(nativeEnumValues);return addIssueToContext2(ctx,{received:ctx.data,code:ZodIssueCode2.invalid_enum_value,options:expectedValues}),INVALID2}return OK3(input2.data)}get enum(){return this._def.values}};ZodNativeEnum2.create=(values,params)=>new ZodNativeEnum2({values,typeName:ZodFirstPartyTypeKind2.ZodNativeEnum,...processCreateParams2(params)});var ZodPromise2=class extends ZodType2{unwrap(){return this._def.type}_parse(input2){let{ctx}=this._processInputParams(input2);if(ctx.parsedType!==ZodParsedType2.promise&&ctx.common.async===!1)return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.promise,received:ctx.parsedType}),INVALID2;let promisified=ctx.parsedType===ZodParsedType2.promise?ctx.data:Promise.resolve(ctx.data);return OK3(promisified.then(data=>this._def.type.parseAsync(data,{path:ctx.path,errorMap:ctx.common.contextualErrorMap})))}};ZodPromise2.create=(schema,params)=>new ZodPromise2({type:schema,typeName:ZodFirstPartyTypeKind2.ZodPromise,...processCreateParams2(params)});var ZodEffects2=class extends ZodType2{innerType(){return this._def.schema}sourceType(){return this._def.schema._def.typeName===ZodFirstPartyTypeKind2.ZodEffects?this._def.schema.sourceType():this._def.schema}_parse(input2){let{status,ctx}=this._processInputParams(input2),effect=this._def.effect||null,checkCtx={addIssue:arg=>{addIssueToContext2(ctx,arg),arg.fatal?status.abort():status.dirty()},get path(){return ctx.path}};if(checkCtx.addIssue=checkCtx.addIssue.bind(checkCtx),effect.type==="preprocess"){let processed=effect.transform(ctx.data,checkCtx);if(ctx.common.async)return Promise.resolve(processed).then(async processed2=>{if(status.value==="aborted")return INVALID2;let result=await this._def.schema._parseAsync({data:processed2,path:ctx.path,parent:ctx});return result.status==="aborted"?INVALID2:result.status==="dirty"||status.value==="dirty"?DIRTY2(result.value):result});{if(status.value==="aborted")return INVALID2;let result=this._def.schema._parseSync({data:processed,path:ctx.path,parent:ctx});return result.status==="aborted"?INVALID2:result.status==="dirty"||status.value==="dirty"?DIRTY2(result.value):result}}if(effect.type==="refinement"){let executeRefinement=acc=>{let result=effect.refinement(acc,checkCtx);if(ctx.common.async)return Promise.resolve(result);if(result instanceof Promise)throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");return acc};if(ctx.common.async===!1){let inner=this._def.schema._parseSync({data:ctx.data,path:ctx.path,parent:ctx});return inner.status==="aborted"?INVALID2:(inner.status==="dirty"&&status.dirty(),executeRefinement(inner.value),{status:status.value,value:inner.value})}else return this._def.schema._parseAsync({data:ctx.data,path:ctx.path,parent:ctx}).then(inner=>inner.status==="aborted"?INVALID2:(inner.status==="dirty"&&status.dirty(),executeRefinement(inner.value).then(()=>({status:status.value,value:inner.value}))))}if(effect.type==="transform")if(ctx.common.async===!1){let base=this._def.schema._parseSync({data:ctx.data,path:ctx.path,parent:ctx});if(!isValid2(base))return INVALID2;let result=effect.transform(base.value,checkCtx);if(result instanceof Promise)throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.");return{status:status.value,value:result}}else return this._def.schema._parseAsync({data:ctx.data,path:ctx.path,parent:ctx}).then(base=>isValid2(base)?Promise.resolve(effect.transform(base.value,checkCtx)).then(result=>({status:status.value,value:result})):INVALID2);util2.assertNever(effect)}};ZodEffects2.create=(schema,effect,params)=>new ZodEffects2({schema,typeName:ZodFirstPartyTypeKind2.ZodEffects,effect,...processCreateParams2(params)});ZodEffects2.createWithPreprocess=(preprocess,schema,params)=>new ZodEffects2({schema,effect:{type:"preprocess",transform:preprocess},typeName:ZodFirstPartyTypeKind2.ZodEffects,...processCreateParams2(params)});var ZodOptional2=class extends ZodType2{_parse(input2){return this._getType(input2)===ZodParsedType2.undefined?OK3(void 0):this._def.innerType._parse(input2)}unwrap(){return this._def.innerType}};ZodOptional2.create=(type,params)=>new ZodOptional2({innerType:type,typeName:ZodFirstPartyTypeKind2.ZodOptional,...processCreateParams2(params)});var ZodNullable2=class extends ZodType2{_parse(input2){return this._getType(input2)===ZodParsedType2.null?OK3(null):this._def.innerType._parse(input2)}unwrap(){return this._def.innerType}};ZodNullable2.create=(type,params)=>new ZodNullable2({innerType:type,typeName:ZodFirstPartyTypeKind2.ZodNullable,...processCreateParams2(params)});var ZodDefault2=class extends ZodType2{_parse(input2){let{ctx}=this._processInputParams(input2),data=ctx.data;return ctx.parsedType===ZodParsedType2.undefined&&(data=this._def.defaultValue()),this._def.innerType._parse({data,path:ctx.path,parent:ctx})}removeDefault(){return this._def.innerType}};ZodDefault2.create=(type,params)=>new ZodDefault2({innerType:type,typeName:ZodFirstPartyTypeKind2.ZodDefault,defaultValue:typeof params.default=="function"?params.default:()=>params.default,...processCreateParams2(params)});var ZodCatch2=class extends ZodType2{_parse(input2){let{ctx}=this._processInputParams(input2),newCtx={...ctx,common:{...ctx.common,issues:[]}},result=this._def.innerType._parse({data:newCtx.data,path:newCtx.path,parent:{...newCtx}});return isAsync2(result)?result.then(result2=>({status:"valid",value:result2.status==="valid"?result2.value:this._def.catchValue({get error(){return new ZodError2(newCtx.common.issues)},input:newCtx.data})})):{status:"valid",value:result.status==="valid"?result.value:this._def.catchValue({get error(){return new ZodError2(newCtx.common.issues)},input:newCtx.data})}}removeCatch(){return this._def.innerType}};ZodCatch2.create=(type,params)=>new ZodCatch2({innerType:type,typeName:ZodFirstPartyTypeKind2.ZodCatch,catchValue:typeof params.catch=="function"?params.catch:()=>params.catch,...processCreateParams2(params)});var ZodNaN2=class extends ZodType2{_parse(input2){if(this._getType(input2)!==ZodParsedType2.nan){let ctx=this._getOrReturnCtx(input2);return addIssueToContext2(ctx,{code:ZodIssueCode2.invalid_type,expected:ZodParsedType2.nan,received:ctx.parsedType}),INVALID2}return{status:"valid",value:input2.data}}};ZodNaN2.create=params=>new ZodNaN2({typeName:ZodFirstPartyTypeKind2.ZodNaN,...processCreateParams2(params)});var BRAND2=Symbol("zod_brand"),ZodBranded2=class extends ZodType2{_parse(input2){let{ctx}=this._processInputParams(input2),data=ctx.data;return this._def.type._parse({data,path:ctx.path,parent:ctx})}unwrap(){return this._def.type}},ZodPipeline2=class _ZodPipeline extends ZodType2{_parse(input2){let{status,ctx}=this._processInputParams(input2);if(ctx.common.async)return(async()=>{let inResult=await this._def.in._parseAsync({data:ctx.data,path:ctx.path,parent:ctx});return inResult.status==="aborted"?INVALID2:inResult.status==="dirty"?(status.dirty(),DIRTY2(inResult.value)):this._def.out._parseAsync({data:inResult.value,path:ctx.path,parent:ctx})})();{let inResult=this._def.in._parseSync({data:ctx.data,path:ctx.path,parent:ctx});return inResult.status==="aborted"?INVALID2:inResult.status==="dirty"?(status.dirty(),{status:"dirty",value:inResult.value}):this._def.out._parseSync({data:inResult.value,path:ctx.path,parent:ctx})}}static create(a6,b6){return new _ZodPipeline({in:a6,out:b6,typeName:ZodFirstPartyTypeKind2.ZodPipeline})}},ZodReadonly2=class extends ZodType2{_parse(input2){let result=this._def.innerType._parse(input2),freeze=data=>(isValid2(data)&&(data.value=Object.freeze(data.value)),data);return isAsync2(result)?result.then(data=>freeze(data)):freeze(result)}unwrap(){return this._def.innerType}};ZodReadonly2.create=(type,params)=>new ZodReadonly2({innerType:type,typeName:ZodFirstPartyTypeKind2.ZodReadonly,...processCreateParams2(params)});function cleanParams2(params,data){let p3=typeof params=="function"?params(data):typeof params=="string"?{message:params}:params;return typeof p3=="string"?{message:p3}:p3}function custom2(check,_params={},fatal){return check?ZodAny2.create().superRefine((data,ctx)=>{let r6=check(data);if(r6 instanceof Promise)return r6.then(r22=>{if(!r22){let params=cleanParams2(_params,data),_fatal=params.fatal??fatal??!0;ctx.addIssue({code:"custom",...params,fatal:_fatal})}});if(!r6){let params=cleanParams2(_params,data),_fatal=params.fatal??fatal??!0;ctx.addIssue({code:"custom",...params,fatal:_fatal})}}):ZodAny2.create()}var late2={object:ZodObject2.lazycreate},ZodFirstPartyTypeKind2;(function(ZodFirstPartyTypeKind22){ZodFirstPartyTypeKind22.ZodString="ZodString",ZodFirstPartyTypeKind22.ZodNumber="ZodNumber",ZodFirstPartyTypeKind22.ZodNaN="ZodNaN",ZodFirstPartyTypeKind22.ZodBigInt="ZodBigInt",ZodFirstPartyTypeKind22.ZodBoolean="ZodBoolean",ZodFirstPartyTypeKind22.ZodDate="ZodDate",ZodFirstPartyTypeKind22.ZodSymbol="ZodSymbol",ZodFirstPartyTypeKind22.ZodUndefined="ZodUndefined",ZodFirstPartyTypeKind22.ZodNull="ZodNull",ZodFirstPartyTypeKind22.ZodAny="ZodAny",ZodFirstPartyTypeKind22.ZodUnknown="ZodUnknown",ZodFirstPartyTypeKind22.ZodNever="ZodNever",ZodFirstPartyTypeKind22.ZodVoid="ZodVoid",ZodFirstPartyTypeKind22.ZodArray="ZodArray",ZodFirstPartyTypeKind22.ZodObject="ZodObject",ZodFirstPartyTypeKind22.ZodUnion="ZodUnion",ZodFirstPartyTypeKind22.ZodDiscriminatedUnion="ZodDiscriminatedUnion",ZodFirstPartyTypeKind22.ZodIntersection="ZodIntersection",ZodFirstPartyTypeKind22.ZodTuple="ZodTuple",ZodFirstPartyTypeKind22.ZodRecord="ZodRecord",ZodFirstPartyTypeKind22.ZodMap="ZodMap",ZodFirstPartyTypeKind22.ZodSet="ZodSet",ZodFirstPartyTypeKind22.ZodFunction="ZodFunction",ZodFirstPartyTypeKind22.ZodLazy="ZodLazy",ZodFirstPartyTypeKind22.ZodLiteral="ZodLiteral",ZodFirstPartyTypeKind22.ZodEnum="ZodEnum",ZodFirstPartyTypeKind22.ZodEffects="ZodEffects",ZodFirstPartyTypeKind22.ZodNativeEnum="ZodNativeEnum",ZodFirstPartyTypeKind22.ZodOptional="ZodOptional",ZodFirstPartyTypeKind22.ZodNullable="ZodNullable",ZodFirstPartyTypeKind22.ZodDefault="ZodDefault",ZodFirstPartyTypeKind22.ZodCatch="ZodCatch",ZodFirstPartyTypeKind22.ZodPromise="ZodPromise",ZodFirstPartyTypeKind22.ZodBranded="ZodBranded",ZodFirstPartyTypeKind22.ZodPipeline="ZodPipeline",ZodFirstPartyTypeKind22.ZodReadonly="ZodReadonly"})(ZodFirstPartyTypeKind2||(ZodFirstPartyTypeKind2={}));var instanceOfType2=(cls,params={message:`Input not instance of ${cls.name}`})=>custom2(data=>data instanceof cls,params),stringType2=ZodString2.create,numberType2=ZodNumber2.create,nanType2=ZodNaN2.create,bigIntType2=ZodBigInt2.create,booleanType2=ZodBoolean2.create,dateType2=ZodDate2.create,symbolType2=ZodSymbol2.create,undefinedType2=ZodUndefined2.create,nullType2=ZodNull2.create,anyType2=ZodAny2.create,unknownType2=ZodUnknown2.create,neverType2=ZodNever2.create,voidType2=ZodVoid2.create,arrayType2=ZodArray2.create,objectType2=ZodObject2.create,strictObjectType2=ZodObject2.strictCreate,unionType2=ZodUnion2.create,discriminatedUnionType2=ZodDiscriminatedUnion2.create,intersectionType2=ZodIntersection2.create,tupleType2=ZodTuple2.create,recordType2=ZodRecord2.create,mapType2=ZodMap2.create,setType2=ZodSet2.create,functionType2=ZodFunction2.create,lazyType2=ZodLazy2.create,literalType2=ZodLiteral2.create,enumType2=ZodEnum2.create,nativeEnumType2=ZodNativeEnum2.create,promiseType2=ZodPromise2.create,effectsType2=ZodEffects2.create,optionalType2=ZodOptional2.create,nullableType2=ZodNullable2.create,preprocessType2=ZodEffects2.createWithPreprocess,pipelineType2=ZodPipeline2.create,ostring2=()=>stringType2().optional(),onumber2=()=>numberType2().optional(),oboolean2=()=>booleanType2().optional(),coerce2={string:arg=>ZodString2.create({...arg,coerce:!0}),number:arg=>ZodNumber2.create({...arg,coerce:!0}),boolean:arg=>ZodBoolean2.create({...arg,coerce:!0}),bigint:arg=>ZodBigInt2.create({...arg,coerce:!0}),date:arg=>ZodDate2.create({...arg,coerce:!0})},NEVER2=INVALID2,resistance2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6,"\u03A9").value),capacitance2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6,"F").value).transform(value=>Number.parseFloat(value.toPrecision(12))),inductance2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6,"H").value),voltage2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6,"V").value),length3=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6).value),frequency2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6,"Hz").value),distance7=length3,current2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6,"A").value),duration_ms2=external_exports2.string().or(external_exports2.number()).transform(v6=>parseAndConvertSiUnit2(v6).value),time2=duration_ms2,ms4=duration_ms2,timestamp2=external_exports2.string().datetime(),rotation4=external_exports2.string().or(external_exports2.number()).transform(arg=>typeof arg=="number"?arg:arg.endsWith("deg")?Number.parseFloat(arg.split("deg")[0]):arg.endsWith("rad")?Number.parseFloat(arg.split("rad")[0])*180/Math.PI:Number.parseFloat(arg)),battery_capacity2=external_exports2.number().or(external_exports2.string().endsWith("mAh")).transform(v6=>{if(typeof v6=="string"){let valString=v6.replace("mAh",""),num=Number.parseFloat(valString);if(Number.isNaN(num))throw new Error("Invalid capacity");return num}return v6}).describe("Battery capacity in mAh"),expectTypesMatch3=shouldBe=>{};expectTypesMatch3("extra props b");expectTypesMatch3("missing props b");expectTypesMatch3(!0);expectTypesMatch3("mismatched prop types: a");var expectStringUnionsMatch2=shouldBe=>{};expectStringUnionsMatch2(!0);expectStringUnionsMatch2('T1 has extra: "c", T2 has extra: "d"');expectStringUnionsMatch2('T1 has extra: "c"');expectStringUnionsMatch2('T2 has extra: "c"');expectStringUnionsMatch2('T1 has extra: "d", T2 has extra: "c"');expectStringUnionsMatch2(!0);var point5=external_exports2.object({x:distance7,y:distance7}),position2=point5;expectTypesMatch3(!0);expectTypesMatch3(!0);var point33=external_exports2.object({x:distance7,y:distance7,z:distance7}),position32=point33;expectTypesMatch3(!0);var size2=external_exports2.object({width:external_exports2.number(),height:external_exports2.number()});expectTypesMatch3(!0);var randomId2=length4=>{let chars2="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";return Array.from({length:length4},()=>chars2[Math.floor(Math.random()*chars2.length)]).join("")},getZodPrefixedIdWithDefault2=prefix=>external_exports2.string().optional().default(()=>`${prefix}_${randomId2(10)}`),ninePointAnchor3=external_exports2.enum(["top_left","top_center","top_right","center_left","center","center_right","bottom_left","bottom_center","bottom_right"]);expectTypesMatch3(!0);var pcbRenderLayer2=external_exports2.enum(["top_silkscreen","bottom_silkscreen","top_copper","bottom_copper","top_soldermask","bottom_soldermask","top_fabrication_note","bottom_fabrication_note","top_user_note","bottom_user_note","top_courtyard","bottom_courtyard","inner1_copper","inner2_copper","inner3_copper","inner4_copper","inner5_copper","inner6_copper","edge_cuts","drill"]);expectTypesMatch3(!0);var asset2=external_exports2.object({project_relative_path:external_exports2.string(),url:external_exports2.string(),mimetype:external_exports2.string()});expectTypesMatch3(!0);var kicadAt3=point5.extend({rotation:rotation4.optional()});expectTypesMatch3(!0);var kicadFont3=external_exports2.object({size:point5.optional(),thickness:distance7.optional()});expectTypesMatch3(!0);var kicadEffects3=external_exports2.object({font:kicadFont3.optional()});expectTypesMatch3(!0);var kicadProperty3=external_exports2.object({value:external_exports2.string(),at:kicadAt3.optional(),layer:external_exports2.string().optional(),uuid:external_exports2.string().optional(),hide:external_exports2.boolean().optional(),effects:kicadEffects3.optional()});expectTypesMatch3(!0);var kicadFootprintProperties3=external_exports2.object({Reference:kicadProperty3.optional(),Value:kicadProperty3.optional(),Datasheet:kicadProperty3.optional(),Description:kicadProperty3.optional()});expectTypesMatch3(!0);var kicadFootprintAttributes3=external_exports2.object({through_hole:external_exports2.boolean().optional(),smd:external_exports2.boolean().optional(),exclude_from_pos_files:external_exports2.boolean().optional(),exclude_from_bom:external_exports2.boolean().optional()});expectTypesMatch3(!0);var kicadFootprintPad3=external_exports2.object({name:external_exports2.string(),type:external_exports2.string(),shape:external_exports2.string().optional(),at:kicadAt3.optional(),size:point5.optional(),drill:distance7.optional(),layers:external_exports2.array(external_exports2.string()).optional(),removeUnusedLayers:external_exports2.boolean().optional(),uuid:external_exports2.string().optional()});expectTypesMatch3(!0);var kicadFootprintModel3=external_exports2.object({path:external_exports2.string(),offset:point33.optional(),scale:point33.optional(),rotate:point33.optional()});expectTypesMatch3(!0);var kicadFootprintMetadata3=external_exports2.object({footprintName:external_exports2.string().optional(),version:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),generator:external_exports2.string().optional(),generatorVersion:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),layer:external_exports2.string().optional(),properties:kicadFootprintProperties3.optional(),attributes:kicadFootprintAttributes3.optional(),pads:external_exports2.array(kicadFootprintPad3).optional(),embeddedFonts:external_exports2.boolean().optional(),model:kicadFootprintModel3.optional()});expectTypesMatch3(!0);var kicadSymbolPinNumbers3=external_exports2.object({hide:external_exports2.boolean().optional()});expectTypesMatch3(!0);var kicadSymbolPinNames3=external_exports2.object({offset:distance7.optional(),hide:external_exports2.boolean().optional()});expectTypesMatch3(!0);var kicadSymbolEffects3=external_exports2.object({font:kicadFont3.optional(),justify:external_exports2.union([external_exports2.string(),external_exports2.array(external_exports2.string())]).optional(),hide:external_exports2.boolean().optional()});expectTypesMatch3(!0);var kicadSymbolProperty3=external_exports2.object({value:external_exports2.string(),id:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),at:kicadAt3.optional(),effects:kicadSymbolEffects3.optional()});expectTypesMatch3(!0);var kicadSymbolProperties3=external_exports2.object({Reference:kicadSymbolProperty3.optional(),Value:kicadSymbolProperty3.optional(),Footprint:kicadSymbolProperty3.optional(),Datasheet:kicadSymbolProperty3.optional(),Description:kicadSymbolProperty3.optional(),ki_keywords:kicadSymbolProperty3.optional(),ki_fp_filters:kicadSymbolProperty3.optional()});expectTypesMatch3(!0);var kicadSymbolMetadata3=external_exports2.object({symbolName:external_exports2.string().optional(),extends:external_exports2.string().optional(),pinNumbers:kicadSymbolPinNumbers3.optional(),pinNames:kicadSymbolPinNames3.optional(),excludeFromSim:external_exports2.boolean().optional(),inBom:external_exports2.boolean().optional(),onBoard:external_exports2.boolean().optional(),properties:kicadSymbolProperties3.optional(),embeddedFonts:external_exports2.boolean().optional()});expectTypesMatch3(!0);var base_circuit_json_error2=external_exports2.object({error_type:external_exports2.string(),message:external_exports2.string(),is_fatal:external_exports2.boolean().optional()});expectTypesMatch3(!0);var supplier_name2=external_exports2.enum(["jlcpcb","macrofab","pcbway","digikey","mouser","lcsc"]);expectTypesMatch3(!0);var source_component_base2=external_exports2.object({type:external_exports2.literal("source_component"),ftype:external_exports2.string().optional(),source_component_id:external_exports2.string(),name:external_exports2.string(),manufacturer_part_number:external_exports2.string().optional(),supplier_part_numbers:external_exports2.record(supplier_name2,external_exports2.array(external_exports2.string())).optional(),display_value:external_exports2.string().optional(),display_name:external_exports2.string().optional(),are_pins_interchangeable:external_exports2.boolean().optional(),internally_connected_source_port_ids:external_exports2.array(external_exports2.array(external_exports2.string())).optional(),source_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()});expectTypesMatch3(!0);var source_simple_capacitor2=source_component_base2.extend({ftype:external_exports2.literal("simple_capacitor"),capacitance:capacitance2,max_voltage_rating:voltage2.optional(),display_capacitance:external_exports2.string().optional(),max_decoupling_trace_length:distance7.optional()});expectTypesMatch3(!0);var source_simple_resistor2=source_component_base2.extend({ftype:external_exports2.literal("simple_resistor"),resistance:resistance2,display_resistance:external_exports2.string().optional()});expectTypesMatch3(!0);var source_simple_diode2=source_component_base2.extend({ftype:external_exports2.literal("simple_diode")});expectTypesMatch3(!0);var source_simple_fiducial2=source_component_base2.extend({ftype:external_exports2.literal("simple_fiducial")});expectTypesMatch3(!0);var source_simple_led2=source_simple_diode2.extend({ftype:external_exports2.literal("simple_led"),color:external_exports2.string().optional(),wavelength:external_exports2.string().optional()});expectTypesMatch3(!0);var source_simple_ground2=source_component_base2.extend({ftype:external_exports2.literal("simple_ground")});expectTypesMatch3(!0);var source_simple_chip2=source_component_base2.extend({ftype:external_exports2.literal("simple_chip")});expectTypesMatch3(!0);var source_simple_power_source2=source_component_base2.extend({ftype:external_exports2.literal("simple_power_source"),voltage:voltage2});expectTypesMatch3(!0);var source_simple_current_source2=source_component_base2.extend({ftype:external_exports2.literal("simple_current_source"),current:current2,frequency:frequency2.optional(),peak_to_peak_current:current2.optional(),wave_shape:external_exports2.enum(["sine","square","triangle","sawtooth","dc"]).optional().default("dc"),phase:external_exports2.number().optional(),duty_cycle:external_exports2.number().min(0).max(1).optional()});expectTypesMatch3(!0);var source_simple_fuse2=source_component_base2.extend({ftype:external_exports2.literal("simple_fuse"),current_rating_amps:external_exports2.number().describe("Nominal current in amps the fuse is rated for"),voltage_rating_volts:external_exports2.number().describe("Voltage rating in volts, e.g. \xB15V would be 5")});expectTypesMatch3(!0);var source_simple_ammeter2=source_component_base2.extend({ftype:external_exports2.literal("simple_ammeter")});expectTypesMatch3(!0);var source_pin_attributes2=external_exports2.object({must_be_connected:external_exports2.boolean().optional(),provides_power:external_exports2.boolean().optional(),requires_power:external_exports2.boolean().optional(),provides_ground:external_exports2.boolean().optional(),requires_ground:external_exports2.boolean().optional(),provides_voltage:external_exports2.union([external_exports2.string(),external_exports2.number()]).optional(),requires_voltage:external_exports2.union([external_exports2.string(),external_exports2.number()]).optional(),do_not_connect:external_exports2.boolean().optional(),include_in_board_pinout:external_exports2.boolean().optional(),can_use_internal_pullup:external_exports2.boolean().optional(),is_using_internal_pullup:external_exports2.boolean().optional(),needs_external_pullup:external_exports2.boolean().optional(),can_use_internal_pulldown:external_exports2.boolean().optional(),is_using_internal_pulldown:external_exports2.boolean().optional(),needs_external_pulldown:external_exports2.boolean().optional(),can_use_open_drain:external_exports2.boolean().optional(),is_using_open_drain:external_exports2.boolean().optional(),can_use_push_pull:external_exports2.boolean().optional(),is_using_push_pull:external_exports2.boolean().optional(),should_have_decoupling_capacitor:external_exports2.boolean().optional(),recommended_decoupling_capacitor_capacitance:external_exports2.union([external_exports2.string(),external_exports2.number()]).optional(),is_configured_for_i2c_sda:external_exports2.boolean().optional(),is_configured_for_i2c_scl:external_exports2.boolean().optional(),is_configured_for_spi_mosi:external_exports2.boolean().optional(),is_configured_for_spi_miso:external_exports2.boolean().optional(),is_configured_for_spi_sck:external_exports2.boolean().optional(),is_configured_for_spi_cs:external_exports2.boolean().optional(),is_configured_for_uart_tx:external_exports2.boolean().optional(),is_configured_for_uart_rx:external_exports2.boolean().optional(),supports_i2c_sda:external_exports2.boolean().optional(),supports_i2c_scl:external_exports2.boolean().optional(),supports_spi_mosi:external_exports2.boolean().optional(),supports_spi_miso:external_exports2.boolean().optional(),supports_spi_sck:external_exports2.boolean().optional(),supports_spi_cs:external_exports2.boolean().optional(),supports_uart_tx:external_exports2.boolean().optional(),supports_uart_rx:external_exports2.boolean().optional()});expectTypesMatch3(!0);var source_simple_battery2=source_component_base2.extend({ftype:external_exports2.literal("simple_battery"),capacity:battery_capacity2});expectTypesMatch3(!0);var source_simple_inductor2=source_component_base2.extend({ftype:external_exports2.literal("simple_inductor"),inductance:inductance2,display_inductance:external_exports2.string().optional(),max_current_rating:external_exports2.number().optional()});expectTypesMatch3(!0);var source_simple_push_button2=source_component_base2.extend({ftype:external_exports2.literal("simple_push_button")});expectTypesMatch3(!0);var source_simple_potentiometer2=source_component_base2.extend({ftype:external_exports2.literal("simple_potentiometer"),max_resistance:resistance2,display_max_resistance:external_exports2.string().optional()});expectTypesMatch3(!0);var source_simple_crystal2=source_component_base2.extend({ftype:external_exports2.literal("simple_crystal"),frequency:external_exports2.number().describe("Frequency in Hz"),load_capacitance:external_exports2.number().optional().describe("Load capacitance in pF"),pin_variant:external_exports2.enum(["two_pin","four_pin"]).optional()});expectTypesMatch3(!0);var source_simple_pin_header2=source_component_base2.extend({ftype:external_exports2.literal("simple_pin_header"),pin_count:external_exports2.number(),gender:external_exports2.enum(["male","female"]).optional().default("male")});expectTypesMatch3(!0);var source_simple_connector2=source_component_base2.extend({ftype:external_exports2.literal("simple_connector"),standard:external_exports2.enum(["usb_c","m2"]).optional()});expectTypesMatch3(!0);var source_simple_pinout2=source_component_base2.extend({ftype:external_exports2.literal("simple_pinout")});expectTypesMatch3(!0);var source_simple_resonator2=source_component_base2.extend({ftype:external_exports2.literal("simple_resonator"),load_capacitance:capacitance2,equivalent_series_resistance:resistance2.optional(),frequency:frequency2});expectTypesMatch3(!0);var source_simple_transistor2=source_component_base2.extend({ftype:external_exports2.literal("simple_transistor"),transistor_type:external_exports2.enum(["npn","pnp"])});expectTypesMatch3(!0);var source_simple_test_point2=source_component_base2.extend({ftype:external_exports2.literal("simple_test_point"),footprint_variant:external_exports2.enum(["pad","through_hole"]).optional(),pad_shape:external_exports2.enum(["rect","circle"]).optional(),pad_diameter:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),hole_diameter:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),width:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),height:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional()});expectTypesMatch3(!0);var source_simple_mosfet2=source_component_base2.extend({ftype:external_exports2.literal("simple_mosfet"),channel_type:external_exports2.enum(["n","p"]),mosfet_mode:external_exports2.enum(["enhancement","depletion"])});expectTypesMatch3(!0);var source_simple_op_amp2=source_component_base2.extend({ftype:external_exports2.literal("simple_op_amp")});expectTypesMatch3(!0);var source_simple_switch2=source_component_base2.extend({ftype:external_exports2.literal("simple_switch")});expectTypesMatch3(!0);var source_project_metadata2=external_exports2.object({type:external_exports2.literal("source_project_metadata"),name:external_exports2.string().optional(),software_used_string:external_exports2.string().optional(),project_url:external_exports2.string().optional(),created_at:timestamp2.optional()});expectTypesMatch3(!0);var source_missing_property_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_missing_property_error"),source_missing_property_error_id:getZodPrefixedIdWithDefault2("source_missing_property_error"),source_component_id:external_exports2.string(),property_name:external_exports2.string(),subcircuit_id:external_exports2.string().optional(),error_type:external_exports2.literal("source_missing_property_error").default("source_missing_property_error")}).describe("The source code is missing a property");expectTypesMatch3(!0);var source_failed_to_create_component_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_failed_to_create_component_error"),source_failed_to_create_component_error_id:getZodPrefixedIdWithDefault2("source_failed_to_create_component_error"),error_type:external_exports2.literal("source_failed_to_create_component_error").default("source_failed_to_create_component_error"),component_name:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),parent_source_component_id:external_exports2.string().optional(),pcb_center:external_exports2.object({x:external_exports2.number().optional(),y:external_exports2.number().optional()}).optional(),schematic_center:external_exports2.object({x:external_exports2.number().optional(),y:external_exports2.number().optional()}).optional()}).describe("Error emitted when a component fails to be constructed");expectTypesMatch3(!0);var source_invalid_component_property_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_invalid_component_property_error"),source_invalid_component_property_error_id:getZodPrefixedIdWithDefault2("source_invalid_component_property_error"),source_component_id:external_exports2.string(),property_name:external_exports2.string(),property_value:external_exports2.unknown().optional(),expected_format:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),error_type:external_exports2.literal("source_invalid_component_property_error").default("source_invalid_component_property_error")}).describe("The source component property is invalid");expectTypesMatch3(!0);var source_trace_not_connected_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_trace_not_connected_error"),source_trace_not_connected_error_id:getZodPrefixedIdWithDefault2("source_trace_not_connected_error"),error_type:external_exports2.literal("source_trace_not_connected_error").default("source_trace_not_connected_error"),subcircuit_id:external_exports2.string().optional(),source_group_id:external_exports2.string().optional(),source_trace_id:external_exports2.string().optional(),connected_source_port_ids:external_exports2.array(external_exports2.string()).optional(),selectors_not_found:external_exports2.array(external_exports2.string()).optional()}).describe("Occurs when a source trace selector does not match any ports");expectTypesMatch3(!0);var source_property_ignored_warning2=external_exports2.object({type:external_exports2.literal("source_property_ignored_warning"),source_property_ignored_warning_id:getZodPrefixedIdWithDefault2("source_property_ignored_warning"),source_component_id:external_exports2.string(),property_name:external_exports2.string(),subcircuit_id:external_exports2.string().optional(),error_type:external_exports2.literal("source_property_ignored_warning").default("source_property_ignored_warning"),message:external_exports2.string()}).describe("The source property was ignored");expectTypesMatch3(!0);var source_pin_missing_trace_warning2=external_exports2.object({type:external_exports2.literal("source_pin_missing_trace_warning"),source_pin_missing_trace_warning_id:getZodPrefixedIdWithDefault2("source_pin_missing_trace_warning"),warning_type:external_exports2.literal("source_pin_missing_trace_warning").default("source_pin_missing_trace_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),source_port_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a source component pin is missing a trace connection");expectTypesMatch3(!0);var source_missing_manufacturer_part_number_warning2=external_exports2.object({type:external_exports2.literal("source_missing_manufacturer_part_number_warning"),source_missing_manufacturer_part_number_warning_id:getZodPrefixedIdWithDefault2("source_missing_manufacturer_part_number_warning"),warning_type:external_exports2.literal("source_missing_manufacturer_part_number_warning").default("source_missing_manufacturer_part_number_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),standard:external_exports2.string(),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a standard connector is missing manufacturer part number");expectTypesMatch3(!0);var source_refdes_convention_warning2=external_exports2.object({type:external_exports2.literal("source_refdes_convention_warning"),source_refdes_convention_warning_id:getZodPrefixedIdWithDefault2("source_refdes_convention_warning"),warning_type:external_exports2.literal("source_refdes_convention_warning").default("source_refdes_convention_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),refdes:external_exports2.string(),source_component_ftype:external_exports2.string(),expected_prefixes:external_exports2.array(external_exports2.string()),actual_prefix:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a source component reference designator does not match the component type convention");expectTypesMatch3(!0);var source_simple_voltage_probe2=source_component_base2.extend({ftype:external_exports2.literal("simple_voltage_probe")});expectTypesMatch3(!0);var source_interconnect2=source_component_base2.extend({ftype:external_exports2.literal("interconnect")});expectTypesMatch3(!0);var source_i2c_misconfigured_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_i2c_misconfigured_error"),source_i2c_misconfigured_error_id:getZodPrefixedIdWithDefault2("source_i2c_misconfigured_error"),error_type:external_exports2.literal("source_i2c_misconfigured_error").default("source_i2c_misconfigured_error"),source_port_ids:external_exports2.array(external_exports2.string())}).describe("Error emitted when incompatible I2C pins (e.g. SDA and SCL) are connected to the same net");expectTypesMatch3(!0);var source_component_misconfigured_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_component_misconfigured_error"),source_component_misconfigured_error_id:getZodPrefixedIdWithDefault2("source_component_misconfigured_error"),error_type:external_exports2.literal("source_component_misconfigured_error").default("source_component_misconfigured_error"),source_component_ids:external_exports2.array(external_exports2.string()),source_port_ids:external_exports2.array(external_exports2.string()).optional()}).describe("Error emitted when one or more source components have an invalid or conflicting configuration");expectTypesMatch3(!0);var source_simple_voltage_source2=source_component_base2.extend({ftype:external_exports2.literal("simple_voltage_source"),voltage:voltage2,frequency:frequency2.optional(),peak_to_peak_voltage:voltage2.optional(),wave_shape:external_exports2.enum(["sinewave","square","triangle","sawtooth"]).optional(),phase:rotation4.optional(),duty_cycle:external_exports2.number().optional().describe("Duty cycle as a fraction (0 to 1)"),pulse_delay:ms4.optional(),rise_time:ms4.optional(),fall_time:ms4.optional(),pulse_width:ms4.optional(),period:ms4.optional()});expectTypesMatch3(!0);var any_source_component2=external_exports2.union([source_simple_resistor2,source_simple_capacitor2,source_simple_diode2,source_simple_fiducial2,source_simple_led2,source_simple_ground2,source_simple_chip2,source_simple_power_source2,source_simple_current_source2,source_simple_ammeter2,source_simple_battery2,source_simple_inductor2,source_simple_push_button2,source_simple_potentiometer2,source_simple_crystal2,source_simple_pin_header2,source_simple_connector2,source_simple_pinout2,source_simple_resonator2,source_simple_switch2,source_simple_transistor2,source_simple_test_point2,source_simple_mosfet2,source_simple_op_amp2,source_simple_fuse2,source_simple_voltage_probe2,source_interconnect2,source_simple_voltage_source2,source_project_metadata2,source_missing_property_error2,source_invalid_component_property_error2,source_failed_to_create_component_error2,source_trace_not_connected_error2,source_property_ignored_warning2,source_pin_missing_trace_warning2,source_missing_manufacturer_part_number_warning2,source_refdes_convention_warning2,source_i2c_misconfigured_error2,source_component_misconfigured_error2]);expectTypesMatch3(!0);var source_port2=external_exports2.object({type:external_exports2.literal("source_port"),pin_number:external_exports2.number().optional(),port_hints:external_exports2.array(external_exports2.string()).optional(),name:external_exports2.string(),source_port_id:external_exports2.string(),source_component_id:external_exports2.string().optional(),source_group_id:external_exports2.string().optional(),most_frequently_referenced_by_name:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional()}).merge(source_pin_attributes2);expectTypesMatch3(!0);var source_component_internal_connection2=external_exports2.object({type:external_exports2.literal("source_component_internal_connection"),source_component_internal_connection_id:external_exports2.string(),source_component_id:external_exports2.string(),source_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()});expectTypesMatch3(!0);var source_trace2=external_exports2.object({type:external_exports2.literal("source_trace"),source_trace_id:external_exports2.string(),connected_source_port_ids:external_exports2.array(external_exports2.string()),connected_source_net_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional(),max_length:external_exports2.number().optional(),name:external_exports2.string().optional(),min_trace_thickness:external_exports2.number().optional(),display_name:external_exports2.string().optional()});expectTypesMatch3(!0);var source_group2=external_exports2.object({type:external_exports2.literal("source_group"),source_group_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional(),parent_subcircuit_id:external_exports2.string().optional(),parent_source_group_id:external_exports2.string().optional(),is_subcircuit:external_exports2.boolean().optional(),show_as_schematic_box:external_exports2.boolean().optional(),name:external_exports2.string().optional(),was_automatically_named:external_exports2.boolean().optional()});expectTypesMatch3(!0);var source_net2=external_exports2.object({type:external_exports2.literal("source_net"),source_net_id:external_exports2.string(),name:external_exports2.string(),member_source_group_ids:external_exports2.array(external_exports2.string()),is_power:external_exports2.boolean().optional(),is_ground:external_exports2.boolean().optional(),is_digital_signal:external_exports2.boolean().optional(),is_analog_signal:external_exports2.boolean().optional(),is_positive_voltage_source:external_exports2.boolean().optional(),trace_width:external_exports2.number().optional(),subcircuit_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional()});expectTypesMatch3(!0);var source_board2=external_exports2.object({type:external_exports2.literal("source_board"),source_board_id:external_exports2.string(),source_group_id:external_exports2.string(),title:external_exports2.string().optional()}).describe("Defines a board in the source domain");expectTypesMatch3(!0);var source_ambiguous_port_reference2=base_circuit_json_error2.extend({type:external_exports2.literal("source_ambiguous_port_reference"),source_ambiguous_port_reference_id:getZodPrefixedIdWithDefault2("source_ambiguous_port_reference"),error_type:external_exports2.literal("source_ambiguous_port_reference").default("source_ambiguous_port_reference"),source_port_id:external_exports2.string().optional(),source_component_id:external_exports2.string().optional()}).describe("Error emitted when a port hint matches multiple non-overlapping pads, making the port reference ambiguous");expectTypesMatch3(!0);var source_pcb_ground_plane2=external_exports2.object({type:external_exports2.literal("source_pcb_ground_plane"),source_pcb_ground_plane_id:external_exports2.string(),source_group_id:external_exports2.string(),source_net_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional()}).describe("Defines a ground plane in the source domain");expectTypesMatch3(!0);var all_layers2=["top","bottom","inner1","inner2","inner3","inner4","inner5","inner6"],layer_string2=external_exports2.enum(all_layers2),layer_ref2=layer_string2.or(external_exports2.object({name:layer_string2})).transform(layer=>typeof layer=="string"?layer:layer.name);expectTypesMatch3(!0);var visible_layer2=external_exports2.enum(["top","bottom"]),source_manually_placed_via2=external_exports2.object({type:external_exports2.literal("source_manually_placed_via"),source_manually_placed_via_id:external_exports2.string(),source_group_id:external_exports2.string(),source_net_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional(),source_trace_id:external_exports2.string().optional()}).describe("Defines a via that is manually placed in the source domain");expectTypesMatch3(!0);var source_unnamed_trace_warning2=external_exports2.object({type:external_exports2.literal("source_unnamed_trace_warning"),source_unnamed_trace_warning_id:getZodPrefixedIdWithDefault2("source_unnamed_trace_warning"),warning_type:external_exports2.literal("source_unnamed_trace_warning").default("source_unnamed_trace_warning"),message:external_exports2.string(),source_trace_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a source trace is missing a name");expectTypesMatch3(!0);var source_no_power_pin_defined_warning2=external_exports2.object({type:external_exports2.literal("source_no_power_pin_defined_warning"),source_no_power_pin_defined_warning_id:getZodPrefixedIdWithDefault2("source_no_power_pin_defined_warning"),warning_type:external_exports2.literal("source_no_power_pin_defined_warning").default("source_no_power_pin_defined_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),source_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a chip has no source ports with requires_power=true");expectTypesMatch3(!0);var source_no_ground_pin_defined_warning2=external_exports2.object({type:external_exports2.literal("source_no_ground_pin_defined_warning"),source_no_ground_pin_defined_warning_id:getZodPrefixedIdWithDefault2("source_no_ground_pin_defined_warning"),warning_type:external_exports2.literal("source_no_ground_pin_defined_warning").default("source_no_ground_pin_defined_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),source_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a chip has no source ports marked as ground pins");expectTypesMatch3(!0);var source_component_pins_underspecified_warning2=external_exports2.object({type:external_exports2.literal("source_component_pins_underspecified_warning"),source_component_pins_underspecified_warning_id:getZodPrefixedIdWithDefault2("source_component_pins_underspecified_warning"),warning_type:external_exports2.literal("source_component_pins_underspecified_warning").default("source_component_pins_underspecified_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),source_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when all ports on a source component are underspecified");expectTypesMatch3(!0);var source_pin_must_be_connected_error2=base_circuit_json_error2.extend({type:external_exports2.literal("source_pin_must_be_connected_error"),source_pin_must_be_connected_error_id:getZodPrefixedIdWithDefault2("source_pin_must_be_connected_error"),error_type:external_exports2.literal("source_pin_must_be_connected_error").default("source_pin_must_be_connected_error"),source_component_id:external_exports2.string(),source_port_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when a pin with mustBeConnected attribute is not connected to any trace");expectTypesMatch3(!0);var unknown_error_finding_part2=base_circuit_json_error2.extend({type:external_exports2.literal("unknown_error_finding_part"),unknown_error_finding_part_id:getZodPrefixedIdWithDefault2("unknown_error_finding_part"),error_type:external_exports2.literal("unknown_error_finding_part").default("unknown_error_finding_part"),source_component_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when an unexpected error occurs while finding a part");expectTypesMatch3(!0);var source_part_not_found_warning2=external_exports2.object({type:external_exports2.literal("source_part_not_found_warning"),source_part_not_found_warning_id:getZodPrefixedIdWithDefault2("source_part_not_found_warning"),warning_type:external_exports2.literal("source_part_not_found_warning").default("source_part_not_found_warning"),message:external_exports2.string(),source_component_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),supplier_name:supplier_name2.optional(),manufacturer_part_number:external_exports2.string().optional(),supplier_part_number:external_exports2.string().optional(),part_name:external_exports2.string().optional()}).describe("Warning emitted when a requested part can not be found");expectTypesMatch3(!0);var schematic_box2=external_exports2.object({type:external_exports2.literal("schematic_box"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),width:distance7,height:distance7,is_dashed:external_exports2.boolean().default(!1),x:distance7,y:distance7,subcircuit_id:external_exports2.string().optional()}).describe("Draws a box on the schematic");expectTypesMatch3(!0);var schematic_path2=external_exports2.object({type:external_exports2.literal("schematic_path"),schematic_path_id:getZodPrefixedIdWithDefault2("schematic_path"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),fill_color:external_exports2.string().optional(),is_filled:external_exports2.boolean().optional(),is_dashed:external_exports2.boolean().default(!1),stroke_width:distance7.nullable().optional(),stroke_color:external_exports2.string().optional(),dash_length:distance7.optional(),dash_gap:distance7.optional(),points:external_exports2.array(point5),subcircuit_id:external_exports2.string().optional()});expectTypesMatch3(!0);var schematic_pin_styles2=external_exports2.record(external_exports2.object({left_margin:length3.optional(),right_margin:length3.optional(),top_margin:length3.optional(),bottom_margin:length3.optional()})),schematic_component_port_arrangement_by_size2=external_exports2.object({left_size:external_exports2.number(),right_size:external_exports2.number(),top_size:external_exports2.number().optional(),bottom_size:external_exports2.number().optional()});expectTypesMatch3(!0);var schematic_component_port_arrangement_by_sides2=external_exports2.object({left_side:external_exports2.object({pins:external_exports2.array(external_exports2.number()),direction:external_exports2.enum(["top-to-bottom","bottom-to-top"]).optional()}).optional(),right_side:external_exports2.object({pins:external_exports2.array(external_exports2.number()),direction:external_exports2.enum(["top-to-bottom","bottom-to-top"]).optional()}).optional(),top_side:external_exports2.object({pins:external_exports2.array(external_exports2.number()),direction:external_exports2.enum(["left-to-right","right-to-left"]).optional()}).optional(),bottom_side:external_exports2.object({pins:external_exports2.array(external_exports2.number()),direction:external_exports2.enum(["left-to-right","right-to-left"]).optional()}).optional()});expectTypesMatch3(!0);var port_arrangement2=external_exports2.union([schematic_component_port_arrangement_by_size2,schematic_component_port_arrangement_by_sides2]),schematic_component2=external_exports2.object({type:external_exports2.literal("schematic_component"),size:size2,center:point5,source_component_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string(),schematic_sheet_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),pin_spacing:length3.optional(),pin_styles:schematic_pin_styles2.optional(),box_width:length3.optional(),symbol_name:external_exports2.string().optional(),port_arrangement:port_arrangement2.optional(),port_labels:external_exports2.record(external_exports2.string()).optional(),symbol_display_value:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),schematic_group_id:external_exports2.string().optional(),is_schematic_group:external_exports2.boolean().optional(),source_group_id:external_exports2.string().optional(),is_box_with_pins:external_exports2.boolean().optional().default(!0)});expectTypesMatch3(!0);var schematicSymbolMetadata2=external_exports2.object({kicad_symbol:kicadSymbolMetadata3.optional()}).catchall(external_exports2.unknown()),schematic_symbol2=external_exports2.object({type:external_exports2.literal("schematic_symbol"),schematic_symbol_id:external_exports2.string(),name:external_exports2.string().optional(),metadata:schematicSymbolMetadata2.optional()}).describe("Defines a named schematic symbol that can be referenced by components.");expectTypesMatch3(!0);var schematic_line2=external_exports2.object({type:external_exports2.literal("schematic_line"),schematic_line_id:getZodPrefixedIdWithDefault2("schematic_line"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),x1:distance7,y1:distance7,x2:distance7,y2:distance7,stroke_width:distance7.nullable().optional(),color:external_exports2.string().default("#000000"),is_dashed:external_exports2.boolean().default(!1),dash_length:distance7.optional(),dash_gap:distance7.optional(),subcircuit_id:external_exports2.string().optional()}).describe("Draws a styled line on the schematic");expectTypesMatch3(!0);var schematic_rect2=external_exports2.object({type:external_exports2.literal("schematic_rect"),schematic_rect_id:getZodPrefixedIdWithDefault2("schematic_rect"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),center:point5,width:distance7,height:distance7,rotation:rotation4.default(0),stroke_width:distance7.nullable().optional(),color:external_exports2.string().default("#000000"),is_filled:external_exports2.boolean().default(!1),fill_color:external_exports2.string().optional(),is_dashed:external_exports2.boolean().default(!1),subcircuit_id:external_exports2.string().optional()}).describe("Draws a styled rectangle on the schematic");expectTypesMatch3(!0);var schematic_circle2=external_exports2.object({type:external_exports2.literal("schematic_circle"),schematic_circle_id:getZodPrefixedIdWithDefault2("schematic_circle"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),center:point5,radius:distance7,stroke_width:distance7.nullable().optional(),color:external_exports2.string().default("#000000"),is_filled:external_exports2.boolean().default(!1),fill_color:external_exports2.string().optional(),is_dashed:external_exports2.boolean().default(!1),subcircuit_id:external_exports2.string().optional()}).describe("Draws a styled circle on the schematic");expectTypesMatch3(!0);var schematic_arc2=external_exports2.object({type:external_exports2.literal("schematic_arc"),schematic_arc_id:getZodPrefixedIdWithDefault2("schematic_arc"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),center:point5,radius:distance7,start_angle_degrees:rotation4,end_angle_degrees:rotation4,direction:external_exports2.enum(["clockwise","counterclockwise"]).default("counterclockwise"),stroke_width:distance7.nullable().optional(),color:external_exports2.string().default("#000000"),is_dashed:external_exports2.boolean().default(!1),subcircuit_id:external_exports2.string().optional()}).describe("Draws a styled arc on the schematic");expectTypesMatch3(!0);var schematic_trace2=external_exports2.object({type:external_exports2.literal("schematic_trace"),schematic_trace_id:external_exports2.string(),schematic_sheet_id:external_exports2.string().optional(),source_trace_id:external_exports2.string().optional(),junctions:external_exports2.array(external_exports2.object({x:external_exports2.number(),y:external_exports2.number()})),edges:external_exports2.array(external_exports2.object({from:external_exports2.object({x:external_exports2.number(),y:external_exports2.number()}),to:external_exports2.object({x:external_exports2.number(),y:external_exports2.number()}),is_crossing:external_exports2.boolean().optional(),from_schematic_port_id:external_exports2.string().optional(),to_schematic_port_id:external_exports2.string().optional()})),subcircuit_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional()});expectTypesMatch3(!0);var fivePointAnchor3=external_exports2.enum(["center","left","right","top","bottom"]);expectTypesMatch3(!0);var schematic_text2=external_exports2.object({type:external_exports2.literal("schematic_text"),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),schematic_symbol_id:external_exports2.string().optional(),schematic_text_id:external_exports2.string(),text:external_exports2.string(),font_size:external_exports2.number().default(.18),position:external_exports2.object({x:distance7,y:distance7}),rotation:external_exports2.number().default(0),anchor:external_exports2.union([fivePointAnchor3.describe("legacy"),ninePointAnchor3]).default("center"),color:external_exports2.string().default("#000000"),subcircuit_id:external_exports2.string().optional()});expectTypesMatch3(!0);var schematic_port2=external_exports2.object({type:external_exports2.literal("schematic_port"),schematic_port_id:external_exports2.string(),source_port_id:external_exports2.string(),schematic_sheet_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),center:point5,facing_direction:external_exports2.enum(["up","down","left","right"]).optional(),distance_from_component_edge:external_exports2.number().optional(),side_of_component:external_exports2.enum(["top","bottom","left","right"]).optional(),true_ccw_index:external_exports2.number().optional(),pin_number:external_exports2.number().optional(),display_pin_label:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),is_connected:external_exports2.boolean().optional(),has_input_arrow:external_exports2.boolean().optional(),has_output_arrow:external_exports2.boolean().optional(),is_drawn_with_inversion_circle:external_exports2.boolean().optional()}).describe("Defines a port on a schematic component");expectTypesMatch3(!0);var schematic_net_label2=external_exports2.object({type:external_exports2.literal("schematic_net_label"),schematic_net_label_id:getZodPrefixedIdWithDefault2("schematic_net_label"),schematic_sheet_id:external_exports2.string().optional(),schematic_trace_id:external_exports2.string().optional(),source_trace_id:external_exports2.string().optional(),source_net_id:external_exports2.string(),center:point5,anchor_position:point5.optional(),anchor_side:external_exports2.enum(["top","bottom","left","right"]),text:external_exports2.string(),symbol_name:external_exports2.string().optional(),is_movable:external_exports2.boolean().optional(),subcircuit_id:external_exports2.string().optional()});expectTypesMatch3(!0);var schematic_error2=base_circuit_json_error2.extend({type:external_exports2.literal("schematic_error"),schematic_error_id:external_exports2.string(),error_type:external_exports2.literal("schematic_port_not_found").default("schematic_port_not_found"),subcircuit_id:external_exports2.string().optional()}).describe("Defines a schematic error on the schematic");expectTypesMatch3(!0);var schematic_layout_error2=base_circuit_json_error2.extend({type:external_exports2.literal("schematic_layout_error"),schematic_layout_error_id:getZodPrefixedIdWithDefault2("schematic_layout_error"),error_type:external_exports2.literal("schematic_layout_error").default("schematic_layout_error"),source_group_id:external_exports2.string(),schematic_group_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when schematic layout fails for a group");expectTypesMatch3(!0);var schematic_debug_object_base2=external_exports2.object({type:external_exports2.literal("schematic_debug_object"),label:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}),schematic_debug_rect2=schematic_debug_object_base2.extend({shape:external_exports2.literal("rect"),center:point5,size:size2}),schematic_debug_line2=schematic_debug_object_base2.extend({shape:external_exports2.literal("line"),start:point5,end:point5}),schematic_debug_point2=schematic_debug_object_base2.extend({shape:external_exports2.literal("point"),center:point5}),schematic_debug_object2=external_exports2.discriminatedUnion("shape",[schematic_debug_rect2,schematic_debug_line2,schematic_debug_point2]);expectTypesMatch3(!0);var schematic_voltage_probe2=external_exports2.object({type:external_exports2.literal("schematic_voltage_probe"),schematic_voltage_probe_id:external_exports2.string(),schematic_sheet_id:external_exports2.string().optional(),source_component_id:external_exports2.string().optional(),name:external_exports2.string().optional(),position:point5,schematic_trace_id:external_exports2.string(),voltage:voltage2.optional(),subcircuit_id:external_exports2.string().optional(),color:external_exports2.string().optional(),label_alignment:ninePointAnchor3.optional()}).describe("Defines a voltage probe measurement point on a schematic trace");expectTypesMatch3(!0);var schematic_manual_edit_conflict_warning2=external_exports2.object({type:external_exports2.literal("schematic_manual_edit_conflict_warning"),schematic_manual_edit_conflict_warning_id:getZodPrefixedIdWithDefault2("schematic_manual_edit_conflict_warning"),warning_type:external_exports2.literal("schematic_manual_edit_conflict_warning").default("schematic_manual_edit_conflict_warning"),message:external_exports2.string(),schematic_component_id:external_exports2.string(),schematic_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),source_component_id:external_exports2.string()}).describe("Warning emitted when a component has both manual placement and explicit schX/schY coordinates");expectTypesMatch3(!0);var schematic_group2=external_exports2.object({type:external_exports2.literal("schematic_group"),schematic_group_id:getZodPrefixedIdWithDefault2("schematic_group"),schematic_sheet_id:external_exports2.string().optional(),source_group_id:external_exports2.string(),is_subcircuit:external_exports2.boolean().optional(),subcircuit_id:external_exports2.string().optional(),width:length3,height:length3,center:point5,schematic_component_ids:external_exports2.array(external_exports2.string()),show_as_schematic_box:external_exports2.boolean().optional(),name:external_exports2.string().optional(),description:external_exports2.string().optional()}).describe("Defines a group of components on the schematic");expectTypesMatch3(!0);var schematic_table2=external_exports2.object({type:external_exports2.literal("schematic_table"),schematic_table_id:getZodPrefixedIdWithDefault2("schematic_table"),schematic_sheet_id:external_exports2.string().optional(),anchor_position:point5,column_widths:external_exports2.array(distance7),row_heights:external_exports2.array(distance7),cell_padding:distance7.optional(),border_width:distance7.optional(),subcircuit_id:external_exports2.string().optional(),schematic_component_id:external_exports2.string().optional(),anchor:ninePointAnchor3.optional()}).describe("Defines a table on the schematic");expectTypesMatch3(!0);var schematic_table_cell2=external_exports2.object({type:external_exports2.literal("schematic_table_cell"),schematic_table_cell_id:getZodPrefixedIdWithDefault2("schematic_table_cell"),schematic_sheet_id:external_exports2.string().optional(),schematic_table_id:external_exports2.string(),start_row_index:external_exports2.number(),end_row_index:external_exports2.number(),start_column_index:external_exports2.number(),end_column_index:external_exports2.number(),text:external_exports2.string().optional(),center:point5,width:distance7,height:distance7,horizontal_align:external_exports2.enum(["left","center","right"]).optional(),vertical_align:external_exports2.enum(["top","middle","bottom"]).optional(),font_size:distance7.optional(),subcircuit_id:external_exports2.string().optional()}).describe("Defines a cell within a schematic_table");expectTypesMatch3(!0);var schematic_sheet2=external_exports2.object({type:external_exports2.literal("schematic_sheet"),schematic_sheet_id:getZodPrefixedIdWithDefault2("schematic_sheet"),name:external_exports2.string().optional(),sheet_index:external_exports2.number().optional(),subcircuit_id:external_exports2.string().optional(),outline_color:external_exports2.string().optional()}).describe("Defines a schematic sheet or page that components can be placed on");expectTypesMatch3(!0);var point_with_bulge2=external_exports2.object({x:distance7,y:distance7,bulge:external_exports2.number().optional()});expectTypesMatch3(!0);var ring2=external_exports2.object({vertices:external_exports2.array(point_with_bulge2)});expectTypesMatch3(!0);var brep_shape2=external_exports2.object({outer_ring:ring2,inner_rings:external_exports2.array(ring2).default([])});expectTypesMatch3(!0);var pcb_route_hint2=external_exports2.object({x:distance7,y:distance7,via:external_exports2.boolean().optional(),via_to_layer:layer_ref2.optional()}),pcb_route_hints2=external_exports2.array(pcb_route_hint2);expectTypesMatch3(!0);expectTypesMatch3(!0);var route_hint_point2=external_exports2.object({x:distance7,y:distance7,via:external_exports2.boolean().optional(),to_layer:layer_ref2.optional(),trace_width:distance7.optional()});expectTypesMatch3(!0);var manufacturing_drc_properties2=external_exports2.object({min_trace_width:length3.optional(),min_board_edge_clearance:length3.optional(),min_via_hole_edge_to_via_hole_edge_clearance:length3.optional(),min_plated_hole_drill_edge_to_drill_edge_clearance:length3.optional(),min_trace_to_pad_edge_clearance:length3.optional(),min_pad_edge_to_pad_edge_clearance:length3.optional(),min_same_net_trace_edge_to_trace_edge_clearance:length3.optional(),min_different_net_trace_edge_to_trace_edge_clearance:length3.optional(),min_via_edge_to_pad_edge_clearance:length3.optional(),min_via_hole_diameter:length3.optional(),min_via_pad_diameter:length3.optional()}),pcb_component2=external_exports2.object({type:external_exports2.literal("pcb_component"),pcb_component_id:getZodPrefixedIdWithDefault2("pcb_component"),source_component_id:external_exports2.string(),center:point5,layer:layer_ref2,rotation:rotation4,display_offset_x:external_exports2.string().optional().describe("How to display the x offset for this part, usually corresponding with how the user specified it"),display_offset_y:external_exports2.string().optional().describe("How to display the y offset for this part, usually corresponding with how the user specified it"),width:length3,height:length3,do_not_place:external_exports2.boolean().optional(),is_allowed_to_be_off_board:external_exports2.boolean().optional(),subcircuit_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),position_mode:external_exports2.enum(["packed","relative_to_group_anchor","relative_to_another_component","none"]).optional(),anchor_position:point5.optional(),anchor_alignment:ninePointAnchor3.optional(),positioned_relative_to_pcb_group_id:external_exports2.string().optional(),positioned_relative_to_pcb_board_id:external_exports2.string().optional(),cable_insertion_center:point5.optional(),insertion_direction:external_exports2.enum(["from_above","from_left","from_right","from_front","from_back"]).optional(),metadata:external_exports2.object({kicad_footprint:kicadFootprintMetadata3.optional()}).optional(),obstructs_within_bounds:external_exports2.boolean().default(!0).describe("Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath")}).describe("Defines a component on the PCB");expectTypesMatch3(!0);var pcb_hole_circle2=external_exports2.object({type:external_exports2.literal("pcb_hole"),pcb_hole_id:getZodPrefixedIdWithDefault2("pcb_hole"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("circle"),hole_diameter:external_exports2.number(),x:distance7,y:distance7,is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_hole_circle_shape2=pcb_hole_circle2.describe("Defines a circular hole on the PCB");expectTypesMatch3(!0);var pcb_hole_rect2=external_exports2.object({type:external_exports2.literal("pcb_hole"),pcb_hole_id:getZodPrefixedIdWithDefault2("pcb_hole"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("rect"),hole_width:external_exports2.number(),hole_height:external_exports2.number(),x:distance7,y:distance7,is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_hole_rect_shape2=pcb_hole_rect2.describe("Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square.");expectTypesMatch3(!0);var pcb_hole_circle_or_square2=external_exports2.object({type:external_exports2.literal("pcb_hole"),pcb_hole_id:getZodPrefixedIdWithDefault2("pcb_hole"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),hole_shape:external_exports2.enum(["circle","square"]),hole_diameter:external_exports2.number(),x:distance7,y:distance7,is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_hole_circle_or_square_shape2=pcb_hole_circle_or_square2.describe("Defines a circular or square hole on the PCB");expectTypesMatch3(!0);var pcb_hole_oval2=external_exports2.object({type:external_exports2.literal("pcb_hole"),pcb_hole_id:getZodPrefixedIdWithDefault2("pcb_hole"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("oval"),hole_width:external_exports2.number(),hole_height:external_exports2.number(),x:distance7,y:distance7,is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_hole_oval_shape2=pcb_hole_oval2.describe("Defines an oval hole on the PCB");expectTypesMatch3(!0);var pcb_hole_pill2=external_exports2.object({type:external_exports2.literal("pcb_hole"),pcb_hole_id:getZodPrefixedIdWithDefault2("pcb_hole"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("pill"),hole_width:external_exports2.number(),hole_height:external_exports2.number(),x:distance7,y:distance7,is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_hole_pill_shape2=pcb_hole_pill2.describe("Defines a pill-shaped hole on the PCB");expectTypesMatch3(!0);var pcb_hole_rotated_pill2=external_exports2.object({type:external_exports2.literal("pcb_hole"),pcb_hole_id:getZodPrefixedIdWithDefault2("pcb_hole"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("rotated_pill"),hole_width:external_exports2.number(),hole_height:external_exports2.number(),x:distance7,y:distance7,ccw_rotation:rotation4,is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_hole_rotated_pill_shape2=pcb_hole_rotated_pill2.describe("Defines a rotated pill-shaped hole on the PCB");expectTypesMatch3(!0);var pcb_hole2=pcb_hole_circle_or_square2.or(pcb_hole_oval2).or(pcb_hole_pill2).or(pcb_hole_rotated_pill2).or(pcb_hole_circle2).or(pcb_hole_rect2),pcb_plated_hole_circle2=external_exports2.object({type:external_exports2.literal("pcb_plated_hole"),shape:external_exports2.literal("circle"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),outer_diameter:external_exports2.number(),hole_diameter:external_exports2.number(),is_covered_with_solder_mask:external_exports2.boolean().optional(),x:distance7,y:distance7,layers:external_exports2.array(layer_ref2),port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),pcb_plated_hole_id:getZodPrefixedIdWithDefault2("pcb_plated_hole"),soldermask_margin:external_exports2.number().optional()}),pcb_plated_hole_oval2=external_exports2.object({type:external_exports2.literal("pcb_plated_hole"),shape:external_exports2.enum(["oval","pill"]),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),outer_width:external_exports2.number(),outer_height:external_exports2.number(),hole_width:external_exports2.number(),hole_height:external_exports2.number(),is_covered_with_solder_mask:external_exports2.boolean().optional(),x:distance7,y:distance7,ccw_rotation:rotation4,layers:external_exports2.array(layer_ref2),port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),pcb_plated_hole_id:getZodPrefixedIdWithDefault2("pcb_plated_hole"),soldermask_margin:external_exports2.number().optional()}),pcb_circular_hole_with_rect_pad2=external_exports2.object({type:external_exports2.literal("pcb_plated_hole"),shape:external_exports2.literal("circular_hole_with_rect_pad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("circle"),pad_shape:external_exports2.literal("rect"),hole_diameter:external_exports2.number(),rect_pad_width:external_exports2.number(),rect_pad_height:external_exports2.number(),rect_border_radius:external_exports2.number().optional(),hole_offset_x:distance7.default(0),hole_offset_y:distance7.default(0),is_covered_with_solder_mask:external_exports2.boolean().optional(),x:distance7,y:distance7,layers:external_exports2.array(layer_ref2),port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),pcb_plated_hole_id:getZodPrefixedIdWithDefault2("pcb_plated_hole"),soldermask_margin:external_exports2.number().optional(),rect_ccw_rotation:rotation4.optional()}),pcb_pill_hole_with_rect_pad2=external_exports2.object({type:external_exports2.literal("pcb_plated_hole"),shape:external_exports2.literal("pill_hole_with_rect_pad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("pill"),pad_shape:external_exports2.literal("rect"),hole_width:external_exports2.number(),hole_height:external_exports2.number(),rect_pad_width:external_exports2.number(),rect_pad_height:external_exports2.number(),rect_border_radius:external_exports2.number().optional(),hole_offset_x:distance7.default(0),hole_offset_y:distance7.default(0),is_covered_with_solder_mask:external_exports2.boolean().optional(),x:distance7,y:distance7,layers:external_exports2.array(layer_ref2),port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),pcb_plated_hole_id:getZodPrefixedIdWithDefault2("pcb_plated_hole"),soldermask_margin:external_exports2.number().optional()}),pcb_rotated_pill_hole_with_rect_pad2=external_exports2.object({type:external_exports2.literal("pcb_plated_hole"),shape:external_exports2.literal("rotated_pill_hole_with_rect_pad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),hole_shape:external_exports2.literal("rotated_pill"),pad_shape:external_exports2.literal("rect"),hole_width:external_exports2.number(),hole_height:external_exports2.number(),hole_ccw_rotation:rotation4,rect_pad_width:external_exports2.number(),rect_pad_height:external_exports2.number(),rect_border_radius:external_exports2.number().optional(),rect_ccw_rotation:rotation4,hole_offset_x:distance7.default(0),hole_offset_y:distance7.default(0),is_covered_with_solder_mask:external_exports2.boolean().optional(),x:distance7,y:distance7,layers:external_exports2.array(layer_ref2),port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),pcb_plated_hole_id:getZodPrefixedIdWithDefault2("pcb_plated_hole"),soldermask_margin:external_exports2.number().optional()}),pcb_hole_with_polygon_pad2=external_exports2.object({type:external_exports2.literal("pcb_plated_hole"),shape:external_exports2.literal("hole_with_polygon_pad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),hole_shape:external_exports2.enum(["circle","oval","pill","rotated_pill"]),hole_diameter:external_exports2.number().optional(),hole_width:external_exports2.number().optional(),hole_height:external_exports2.number().optional(),pad_outline:external_exports2.array(external_exports2.object({x:distance7,y:distance7})).min(3),hole_offset_x:distance7.default(0),hole_offset_y:distance7.default(0),is_covered_with_solder_mask:external_exports2.boolean().optional(),x:distance7,y:distance7,layers:external_exports2.array(layer_ref2),port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),pcb_plated_hole_id:getZodPrefixedIdWithDefault2("pcb_plated_hole"),soldermask_margin:external_exports2.number().optional(),ccw_rotation:rotation4.optional()}),pcb_plated_hole2=external_exports2.union([pcb_plated_hole_circle2,pcb_plated_hole_oval2,pcb_circular_hole_with_rect_pad2,pcb_pill_hole_with_rect_pad2,pcb_rotated_pill_hole_with_rect_pad2,pcb_hole_with_polygon_pad2]);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);var pcb_port2=external_exports2.object({type:external_exports2.literal("pcb_port"),pcb_port_id:getZodPrefixedIdWithDefault2("pcb_port"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),source_port_id:external_exports2.string(),pcb_component_id:external_exports2.string().optional(),x:distance7,y:distance7,layers:external_exports2.array(layer_ref2),is_board_pinout:external_exports2.boolean().optional()}).describe("Defines a port on the PCB");expectTypesMatch3(!0);var pcb_smtpad_circle2=external_exports2.object({type:external_exports2.literal("pcb_smtpad"),shape:external_exports2.literal("circle"),pcb_smtpad_id:getZodPrefixedIdWithDefault2("pcb_smtpad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,radius:external_exports2.number(),layer:layer_ref2,port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_smtpad_rect2=external_exports2.object({type:external_exports2.literal("pcb_smtpad"),shape:external_exports2.literal("rect"),pcb_smtpad_id:getZodPrefixedIdWithDefault2("pcb_smtpad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),rect_border_radius:external_exports2.number().optional(),corner_radius:external_exports2.number().optional(),layer:layer_ref2,port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional(),soldermask_margin_left:external_exports2.number().optional(),soldermask_margin_top:external_exports2.number().optional(),soldermask_margin_right:external_exports2.number().optional(),soldermask_margin_bottom:external_exports2.number().optional()}),pcb_smtpad_rotated_rect2=external_exports2.object({type:external_exports2.literal("pcb_smtpad"),shape:external_exports2.literal("rotated_rect"),pcb_smtpad_id:getZodPrefixedIdWithDefault2("pcb_smtpad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),rect_border_radius:external_exports2.number().optional(),corner_radius:external_exports2.number().optional(),ccw_rotation:rotation4,layer:layer_ref2,port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional(),soldermask_margin_left:external_exports2.number().optional(),soldermask_margin_top:external_exports2.number().optional(),soldermask_margin_right:external_exports2.number().optional(),soldermask_margin_bottom:external_exports2.number().optional()}),pcb_smtpad_pill2=external_exports2.object({type:external_exports2.literal("pcb_smtpad"),shape:external_exports2.literal("pill"),pcb_smtpad_id:getZodPrefixedIdWithDefault2("pcb_smtpad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),radius:external_exports2.number(),layer:layer_ref2,port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_smtpad_rotated_pill2=external_exports2.object({type:external_exports2.literal("pcb_smtpad"),shape:external_exports2.literal("rotated_pill"),pcb_smtpad_id:getZodPrefixedIdWithDefault2("pcb_smtpad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),radius:external_exports2.number(),ccw_rotation:rotation4,layer:layer_ref2,port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_smtpad_polygon2=external_exports2.object({type:external_exports2.literal("pcb_smtpad"),shape:external_exports2.literal("polygon"),pcb_smtpad_id:getZodPrefixedIdWithDefault2("pcb_smtpad"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),points:external_exports2.array(point5),layer:layer_ref2,port_hints:external_exports2.array(external_exports2.string()).optional(),pcb_component_id:external_exports2.string().optional(),pcb_port_id:external_exports2.string().optional(),is_covered_with_solder_mask:external_exports2.boolean().optional(),soldermask_margin:external_exports2.number().optional()}),pcb_smtpad2=external_exports2.discriminatedUnion("shape",[pcb_smtpad_circle2,pcb_smtpad_rect2,pcb_smtpad_rotated_rect2,pcb_smtpad_rotated_pill2,pcb_smtpad_pill2,pcb_smtpad_polygon2]).describe("Defines an SMT pad on the PCB");expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);var pcb_solder_paste_circle2=external_exports2.object({type:external_exports2.literal("pcb_solder_paste"),shape:external_exports2.literal("circle"),pcb_solder_paste_id:getZodPrefixedIdWithDefault2("pcb_solder_paste"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,radius:external_exports2.number(),layer:layer_ref2,pcb_component_id:external_exports2.string().optional(),pcb_smtpad_id:external_exports2.string().optional()}),pcb_solder_paste_rect2=external_exports2.object({type:external_exports2.literal("pcb_solder_paste"),shape:external_exports2.literal("rect"),pcb_solder_paste_id:getZodPrefixedIdWithDefault2("pcb_solder_paste"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),layer:layer_ref2,pcb_component_id:external_exports2.string().optional(),pcb_smtpad_id:external_exports2.string().optional()}),pcb_solder_paste_pill2=external_exports2.object({type:external_exports2.literal("pcb_solder_paste"),shape:external_exports2.literal("pill"),pcb_solder_paste_id:getZodPrefixedIdWithDefault2("pcb_solder_paste"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),radius:external_exports2.number(),layer:layer_ref2,pcb_component_id:external_exports2.string().optional(),pcb_smtpad_id:external_exports2.string().optional()}),pcb_solder_paste_rotated_rect2=external_exports2.object({type:external_exports2.literal("pcb_solder_paste"),shape:external_exports2.literal("rotated_rect"),pcb_solder_paste_id:getZodPrefixedIdWithDefault2("pcb_solder_paste"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),ccw_rotation:distance7,layer:layer_ref2,pcb_component_id:external_exports2.string().optional(),pcb_smtpad_id:external_exports2.string().optional()}),pcb_solder_paste_oval2=external_exports2.object({type:external_exports2.literal("pcb_solder_paste"),shape:external_exports2.literal("oval"),pcb_solder_paste_id:getZodPrefixedIdWithDefault2("pcb_solder_paste"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),x:distance7,y:distance7,width:external_exports2.number(),height:external_exports2.number(),layer:layer_ref2,pcb_component_id:external_exports2.string().optional(),pcb_smtpad_id:external_exports2.string().optional()}),pcb_solder_paste2=external_exports2.union([pcb_solder_paste_circle2,pcb_solder_paste_rect2,pcb_solder_paste_pill2,pcb_solder_paste_rotated_rect2,pcb_solder_paste_oval2]).describe("Defines solderpaste on the PCB");expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);var pcb_text2=external_exports2.object({type:external_exports2.literal("pcb_text"),pcb_text_id:getZodPrefixedIdWithDefault2("pcb_text"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),text:external_exports2.string(),center:point5,layer:layer_ref2,width:length3,height:length3,lines:external_exports2.number(),align:external_exports2.enum(["bottom-left"])}).describe("Defines text on the PCB");expectTypesMatch3(!0);var pcb_trace_route_point_wire2=external_exports2.object({route_type:external_exports2.literal("wire"),x:distance7,y:distance7,width:distance7,copper_pour_id:external_exports2.string().optional(),is_inside_copper_pour:external_exports2.boolean().optional(),start_pcb_port_id:external_exports2.string().optional(),end_pcb_port_id:external_exports2.string().optional(),layer:layer_ref2}),pcb_trace_route_point_via2=external_exports2.object({route_type:external_exports2.literal("via"),x:distance7,y:distance7,copper_pour_id:external_exports2.string().optional(),is_inside_copper_pour:external_exports2.boolean().optional(),hole_diameter:distance7.optional(),outer_diameter:distance7.optional(),from_layer:layer_ref2,to_layer:layer_ref2}),pcb_trace_route_point_through_pad2=external_exports2.object({route_type:external_exports2.literal("through_pad"),start:point5,end:point5,width:distance7,start_layer:layer_ref2,end_layer:layer_ref2,pcb_smtpad_id:external_exports2.string().optional(),pcb_plated_hole_id:external_exports2.string().optional()}),pcb_trace_route_point2=external_exports2.union([pcb_trace_route_point_wire2,pcb_trace_route_point_via2,pcb_trace_route_point_through_pad2]),pcb_trace2=external_exports2.object({type:external_exports2.literal("pcb_trace"),source_trace_id:external_exports2.string().optional(),pcb_component_id:external_exports2.string().optional(),pcb_trace_id:getZodPrefixedIdWithDefault2("pcb_trace"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),route_thickness_mode:external_exports2.enum(["constant","interpolated"]).default("constant").optional(),route_order_index:external_exports2.number().optional(),should_round_corners:external_exports2.boolean().optional(),trace_length:external_exports2.number().optional(),highlight_color:external_exports2.string().optional(),route:external_exports2.array(pcb_trace_route_point2)}).describe("Defines a trace on the PCB");expectTypesMatch3(!0);expectTypesMatch3(!0);var pcb_trace_warning2=external_exports2.object({type:external_exports2.literal("pcb_trace_warning"),pcb_trace_warning_id:getZodPrefixedIdWithDefault2("pcb_trace_warning"),warning_type:external_exports2.literal("pcb_trace_warning").default("pcb_trace_warning"),message:external_exports2.string(),center:point5.optional(),pcb_trace_id:external_exports2.string(),source_trace_id:external_exports2.string(),pcb_component_ids:external_exports2.array(external_exports2.string()),pcb_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Defines a trace warning on the PCB");expectTypesMatch3(!0);var pcb_trace_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_trace_error"),pcb_trace_error_id:getZodPrefixedIdWithDefault2("pcb_trace_error"),error_type:external_exports2.literal("pcb_trace_error").default("pcb_trace_error"),center:point5.optional(),pcb_trace_id:external_exports2.string(),source_trace_id:external_exports2.string(),pcb_component_ids:external_exports2.array(external_exports2.string()),pcb_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Defines a trace error on the PCB");expectTypesMatch3(!0);var pcb_trace_missing_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_trace_missing_error"),pcb_trace_missing_error_id:getZodPrefixedIdWithDefault2("pcb_trace_missing_error"),error_type:external_exports2.literal("pcb_trace_missing_error").default("pcb_trace_missing_error"),center:point5.optional(),source_trace_id:external_exports2.string(),pcb_component_ids:external_exports2.array(external_exports2.string()),pcb_port_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Defines an error when a source trace has no corresponding PCB trace");expectTypesMatch3(!0);var pcb_port_not_matched_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_port_not_matched_error"),pcb_error_id:getZodPrefixedIdWithDefault2("pcb_error"),error_type:external_exports2.literal("pcb_port_not_matched_error").default("pcb_port_not_matched_error"),pcb_component_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Defines a trace error on the PCB where a port is not matched");expectTypesMatch3(!0);var pcb_port_not_connected_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_port_not_connected_error"),pcb_port_not_connected_error_id:getZodPrefixedIdWithDefault2("pcb_port_not_connected_error"),error_type:external_exports2.literal("pcb_port_not_connected_error").default("pcb_port_not_connected_error"),pcb_port_ids:external_exports2.array(external_exports2.string()),pcb_component_ids:external_exports2.array(external_exports2.string()),subcircuit_id:external_exports2.string().optional()}).describe("Defines an error when a pcb port is not connected to any trace");expectTypesMatch3(!0);var pcb_net2=external_exports2.object({type:external_exports2.literal("pcb_net"),pcb_net_id:getZodPrefixedIdWithDefault2("pcb_net"),source_net_id:external_exports2.string().optional(),highlight_color:external_exports2.string().optional()}).describe("Defines a net on the PCB");expectTypesMatch3(!0);var pcb_via2=external_exports2.object({type:external_exports2.literal("pcb_via"),pcb_via_id:getZodPrefixedIdWithDefault2("pcb_via"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional(),x:distance7,y:distance7,outer_diameter:distance7.default("0.6mm"),hole_diameter:distance7.default("0.25mm"),from_layer:layer_ref2.optional(),to_layer:layer_ref2.optional(),layers:external_exports2.array(layer_ref2),pcb_trace_id:external_exports2.string().optional(),net_is_assignable:external_exports2.boolean().optional(),net_assigned:external_exports2.boolean().optional(),is_tented:external_exports2.boolean().optional()}).describe("Defines a via on the PCB");expectTypesMatch3(!0);var pcb_board2=external_exports2.object({type:external_exports2.literal("pcb_board"),pcb_board_id:getZodPrefixedIdWithDefault2("pcb_board"),pcb_panel_id:external_exports2.string().optional(),carrier_pcb_board_id:external_exports2.string().optional(),is_subcircuit:external_exports2.boolean().optional(),subcircuit_id:external_exports2.string().optional(),is_mounted_to_carrier_board:external_exports2.boolean().optional(),width:length3.optional(),height:length3.optional(),center:point5,display_offset_x:external_exports2.string().optional().describe("How to display the x offset for this board, usually corresponding with how the user specified it"),display_offset_y:external_exports2.string().optional().describe("How to display the y offset for this board, usually corresponding with how the user specified it"),thickness:length3.optional().default(1.4),num_layers:external_exports2.number().optional().default(4),outline:external_exports2.array(point5).optional(),shape:external_exports2.enum(["rect","polygon"]).optional(),material:external_exports2.enum(["fr4","fr1"]).default("fr4"),solder_mask_color:external_exports2.string().optional(),silkscreen_color:external_exports2.string().optional(),anchor_position:point5.optional(),anchor_alignment:ninePointAnchor3.optional(),position_mode:external_exports2.enum(["relative_to_panel_anchor","none"]).optional()}).merge(manufacturing_drc_properties2).describe("Defines the board outline of the PCB");expectTypesMatch3(!0);var pcb_panel2=external_exports2.object({type:external_exports2.literal("pcb_panel"),pcb_panel_id:getZodPrefixedIdWithDefault2("pcb_panel"),width:length3,height:length3,center:point5,thickness:length3.optional().default(1.4),covered_with_solder_mask:external_exports2.boolean().optional().default(!0)}).describe("Defines a PCB panel that can contain multiple boards");expectTypesMatch3(!0);var pcb_placement_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_placement_error"),pcb_placement_error_id:getZodPrefixedIdWithDefault2("pcb_placement_error"),error_type:external_exports2.literal("pcb_placement_error").default("pcb_placement_error"),subcircuit_id:external_exports2.string().optional()}).describe("Defines a placement error on the PCB");expectTypesMatch3(!0);var pcb_panelization_placement_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_panelization_placement_error"),pcb_panelization_placement_error_id:getZodPrefixedIdWithDefault2("pcb_panelization_placement_error"),error_type:external_exports2.literal("pcb_panelization_placement_error").default("pcb_panelization_placement_error"),pcb_panel_id:external_exports2.string().optional(),pcb_board_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("Defines a panelization placement error on the PCB");expectTypesMatch3(!0);var pcb_trace_hint2=external_exports2.object({type:external_exports2.literal("pcb_trace_hint"),pcb_trace_hint_id:getZodPrefixedIdWithDefault2("pcb_trace_hint"),pcb_port_id:external_exports2.string(),pcb_component_id:external_exports2.string(),route:external_exports2.array(route_hint_point2),subcircuit_id:external_exports2.string().optional()}).describe("A hint that can be used during generation of a PCB trace");expectTypesMatch3(!0);var pcb_silkscreen_line2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_line"),pcb_silkscreen_line_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_line"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),stroke_width:distance7.default("0.1mm"),x1:distance7,y1:distance7,x2:distance7,y2:distance7,layer:visible_layer2}).describe("Defines a silkscreen line on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_path2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_path"),pcb_silkscreen_path_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_path"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:visible_layer2,route:external_exports2.array(point5),stroke_width:length3}).describe("Defines a silkscreen path on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_text2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_text"),pcb_silkscreen_text_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_text"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),font:external_exports2.literal("tscircuit2024").default("tscircuit2024"),font_size:distance7.default("0.2mm"),pcb_component_id:external_exports2.string(),text:external_exports2.string(),is_knockout:external_exports2.boolean().default(!1).optional(),knockout_padding:external_exports2.object({left:length3,top:length3,bottom:length3,right:length3}).default({left:"0.2mm",top:"0.2mm",bottom:"0.2mm",right:"0.2mm"}).optional(),ccw_rotation:external_exports2.number().optional(),layer:layer_ref2,is_mirrored:external_exports2.boolean().default(!1).optional(),anchor_position:point5.default({x:0,y:0}),anchor_alignment:ninePointAnchor3.default("center")}).describe("Defines silkscreen text on the PCB");expectTypesMatch3(!0);var pcb_copper_text2=external_exports2.object({type:external_exports2.literal("pcb_copper_text"),pcb_copper_text_id:getZodPrefixedIdWithDefault2("pcb_copper_text"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),font:external_exports2.literal("tscircuit2024").default("tscircuit2024"),font_size:distance7.default("0.2mm"),pcb_component_id:external_exports2.string(),text:external_exports2.string(),is_knockout:external_exports2.boolean().default(!1).optional(),knockout_padding:external_exports2.object({left:length3,top:length3,bottom:length3,right:length3}).default({left:"0.2mm",top:"0.2mm",bottom:"0.2mm",right:"0.2mm"}).optional(),ccw_rotation:external_exports2.number().optional(),layer:layer_ref2,is_mirrored:external_exports2.boolean().default(!1).optional(),anchor_position:point5.default({x:0,y:0}),anchor_alignment:ninePointAnchor3.default("center")}).describe("Defines copper text on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_rect2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_rect"),pcb_silkscreen_rect_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_rect"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,width:length3,height:length3,layer:layer_ref2,stroke_width:length3.default("1mm"),corner_radius:length3.optional(),is_filled:external_exports2.boolean().default(!0).optional(),has_stroke:external_exports2.boolean().optional(),is_stroke_dashed:external_exports2.boolean().optional(),ccw_rotation:external_exports2.number().optional()}).describe("Defines a silkscreen rect on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_circle2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_circle"),pcb_silkscreen_circle_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_circle"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,radius:length3,layer:visible_layer2,stroke_width:length3.default("1mm"),is_filled:external_exports2.boolean().optional()}).describe("Defines a silkscreen circle on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_oval2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_oval"),pcb_silkscreen_oval_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_oval"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,radius_x:distance7,radius_y:distance7,layer:visible_layer2,ccw_rotation:rotation4.optional()}).describe("Defines a silkscreen oval on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_graphic_base2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_graphic"),pcb_silkscreen_graphic_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_graphic"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:visible_layer2,image_asset:asset2.optional()}),pcb_silkscreen_graphic_brep2=pcb_silkscreen_graphic_base2.extend({shape:external_exports2.literal("brep"),brep_shape:brep_shape2}).describe("Defines a BRep silkscreen graphic on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_graphic2=external_exports2.discriminatedUnion("shape",[pcb_silkscreen_graphic_brep2]).describe("Defines a silkscreen graphic on the PCB");expectTypesMatch3(!0);var pcb_silkscreen_pill2=external_exports2.object({type:external_exports2.literal("pcb_silkscreen_pill"),pcb_silkscreen_pill_id:getZodPrefixedIdWithDefault2("pcb_silkscreen_pill"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,width:length3,height:length3,layer:layer_ref2,ccw_rotation:external_exports2.number().optional()}).describe("Defines a silkscreen pill on the PCB");expectTypesMatch3(!0);var pcb_fabrication_note_text2=external_exports2.object({type:external_exports2.literal("pcb_fabrication_note_text"),pcb_fabrication_note_text_id:getZodPrefixedIdWithDefault2("pcb_fabrication_note_text"),subcircuit_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),font:external_exports2.literal("tscircuit2024").default("tscircuit2024"),font_size:distance7.default("1mm"),pcb_component_id:external_exports2.string(),text:external_exports2.string(),ccw_rotation:external_exports2.number().optional(),layer:visible_layer2,anchor_position:point5.default({x:0,y:0}),anchor_alignment:external_exports2.enum(["center","top_left","top_right","bottom_left","bottom_right"]).default("center"),color:external_exports2.string().optional()}).describe("Defines a fabrication note in text on the PCB, useful for leaving notes for assemblers or fabricators");expectTypesMatch3(!0);var pcb_fabrication_note_path2=external_exports2.object({type:external_exports2.literal("pcb_fabrication_note_path"),pcb_fabrication_note_path_id:getZodPrefixedIdWithDefault2("pcb_fabrication_note_path"),pcb_component_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional(),layer:layer_ref2,route:external_exports2.array(point5),stroke_width:length3,color:external_exports2.string().optional()}).describe("Defines a fabrication path on the PCB for fabricators or assemblers");expectTypesMatch3(!0);var pcb_fabrication_note_rect2=external_exports2.object({type:external_exports2.literal("pcb_fabrication_note_rect"),pcb_fabrication_note_rect_id:getZodPrefixedIdWithDefault2("pcb_fabrication_note_rect"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,width:length3,height:length3,layer:visible_layer2,stroke_width:length3.default("0.1mm"),corner_radius:length3.optional(),is_filled:external_exports2.boolean().optional(),has_stroke:external_exports2.boolean().optional(),is_stroke_dashed:external_exports2.boolean().optional(),color:external_exports2.string().optional()}).describe("Defines a fabrication note rectangle on the PCB");expectTypesMatch3(!0);var pcb_fabrication_note_dimension2=external_exports2.object({type:external_exports2.literal("pcb_fabrication_note_dimension"),pcb_fabrication_note_dimension_id:getZodPrefixedIdWithDefault2("pcb_fabrication_note_dimension"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:visible_layer2,from:point5,to:point5,text:external_exports2.string().optional(),text_ccw_rotation:external_exports2.number().optional(),offset:length3.optional(),offset_distance:length3.optional(),offset_direction:external_exports2.object({x:external_exports2.number(),y:external_exports2.number()}).optional(),font:external_exports2.literal("tscircuit2024").default("tscircuit2024"),font_size:length3.default("1mm"),color:external_exports2.string().optional(),arrow_size:length3.default("1mm")}).describe("Defines a measurement annotation within PCB fabrication notes");expectTypesMatch3(!0);var pcb_note_text2=external_exports2.object({type:external_exports2.literal("pcb_note_text"),pcb_note_text_id:getZodPrefixedIdWithDefault2("pcb_note_text"),pcb_component_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),name:external_exports2.string().optional(),font:external_exports2.literal("tscircuit2024").default("tscircuit2024"),font_size:distance7.default("1mm"),text:external_exports2.string().optional(),anchor_position:point5.default({x:0,y:0}),anchor_alignment:external_exports2.enum(["center","top_left","top_right","bottom_left","bottom_right"]).default("center"),layer:visible_layer2.default("top"),is_mirrored_from_top_view:external_exports2.boolean().optional(),color:external_exports2.string().optional()}).describe("Defines a documentation note in text on the PCB");expectTypesMatch3(!0);var pcb_note_rect2=external_exports2.object({type:external_exports2.literal("pcb_note_rect"),pcb_note_rect_id:getZodPrefixedIdWithDefault2("pcb_note_rect"),pcb_component_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),name:external_exports2.string().optional(),text:external_exports2.string().optional(),center:point5,width:length3,height:length3,layer:visible_layer2.default("top"),stroke_width:length3.default("0.1mm"),corner_radius:length3.optional(),is_filled:external_exports2.boolean().optional(),has_stroke:external_exports2.boolean().optional(),is_stroke_dashed:external_exports2.boolean().optional(),color:external_exports2.string().optional()}).describe("Defines a rectangular documentation note on the PCB");expectTypesMatch3(!0);var pcb_note_path2=external_exports2.object({type:external_exports2.literal("pcb_note_path"),pcb_note_path_id:getZodPrefixedIdWithDefault2("pcb_note_path"),pcb_component_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),name:external_exports2.string().optional(),text:external_exports2.string().optional(),route:external_exports2.array(point5),layer:visible_layer2.default("top"),stroke_width:length3.default("0.1mm"),color:external_exports2.string().optional()}).describe("Defines a polyline documentation note on the PCB");expectTypesMatch3(!0);var pcb_note_line2=external_exports2.object({type:external_exports2.literal("pcb_note_line"),pcb_note_line_id:getZodPrefixedIdWithDefault2("pcb_note_line"),pcb_component_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),name:external_exports2.string().optional(),text:external_exports2.string().optional(),x1:distance7,y1:distance7,x2:distance7,y2:distance7,layer:visible_layer2.default("top"),stroke_width:distance7.default("0.1mm"),color:external_exports2.string().optional(),is_dashed:external_exports2.boolean().optional()}).describe("Defines a straight documentation note line on the PCB");expectTypesMatch3(!0);var pcb_note_dimension2=external_exports2.object({type:external_exports2.literal("pcb_note_dimension"),pcb_note_dimension_id:getZodPrefixedIdWithDefault2("pcb_note_dimension"),pcb_component_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),name:external_exports2.string().optional(),from:point5,to:point5,text:external_exports2.string().optional(),text_ccw_rotation:external_exports2.number().optional(),offset_distance:length3.optional(),offset_direction:external_exports2.object({x:external_exports2.number(),y:external_exports2.number()}).optional(),font:external_exports2.literal("tscircuit2024").default("tscircuit2024"),font_size:length3.default("1mm"),layer:visible_layer2.default("top"),color:external_exports2.string().optional(),arrow_size:length3.default("1mm")}).describe("Defines a measurement annotation within PCB documentation notes");expectTypesMatch3(!0);var pcb_footprint_overlap_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_footprint_overlap_error"),pcb_error_id:getZodPrefixedIdWithDefault2("pcb_error"),error_type:external_exports2.literal("pcb_footprint_overlap_error").default("pcb_footprint_overlap_error"),pcb_smtpad_ids:external_exports2.array(external_exports2.string()).optional(),pcb_plated_hole_ids:external_exports2.array(external_exports2.string()).optional(),pcb_hole_ids:external_exports2.array(external_exports2.string()).optional(),pcb_keepout_ids:external_exports2.array(external_exports2.string()).optional()}).describe("Error emitted when a pcb footprint overlaps with another element");expectTypesMatch3(!0);var pcb_courtyard_overlap_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_courtyard_overlap_error"),pcb_error_id:getZodPrefixedIdWithDefault2("pcb_error"),error_type:external_exports2.literal("pcb_courtyard_overlap_error").default("pcb_courtyard_overlap_error"),pcb_component_ids:external_exports2.tuple([external_exports2.string(),external_exports2.string()])}).describe("Error emitted when the courtyard (CrtYd) of one PCB component overlaps with the courtyard of another");expectTypesMatch3(!0);var pcb_keepout2=external_exports2.object({type:external_exports2.literal("pcb_keepout"),shape:external_exports2.literal("rect"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,width:distance7,height:distance7,pcb_keepout_id:external_exports2.string(),layers:external_exports2.array(external_exports2.string()),description:external_exports2.string().optional()}).or(external_exports2.object({type:external_exports2.literal("pcb_keepout"),shape:external_exports2.literal("circle"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,radius:distance7,pcb_keepout_id:external_exports2.string(),layers:external_exports2.array(external_exports2.string()),description:external_exports2.string().optional()}));expectTypesMatch3(!0);var pcb_cutout_base2=external_exports2.object({type:external_exports2.literal("pcb_cutout"),pcb_cutout_id:getZodPrefixedIdWithDefault2("pcb_cutout"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),pcb_board_id:external_exports2.string().optional(),pcb_panel_id:external_exports2.string().optional()}),pcb_cutout_rect2=pcb_cutout_base2.extend({shape:external_exports2.literal("rect"),center:point5,width:length3,height:length3,rotation:rotation4.optional(),corner_radius:length3.optional()});expectTypesMatch3(!0);var pcb_cutout_circle2=pcb_cutout_base2.extend({shape:external_exports2.literal("circle"),center:point5,radius:length3});expectTypesMatch3(!0);var pcb_cutout_polygon2=pcb_cutout_base2.extend({shape:external_exports2.literal("polygon"),points:external_exports2.array(point5)});expectTypesMatch3(!0);var pcb_cutout_path2=pcb_cutout_base2.extend({shape:external_exports2.literal("path"),route:external_exports2.array(point5),slot_width:length3,slot_length:length3.optional(),space_between_slots:length3.optional(),slot_corner_radius:length3.optional()});expectTypesMatch3(!0);var pcb_cutout2=external_exports2.discriminatedUnion("shape",[pcb_cutout_rect2,pcb_cutout_circle2,pcb_cutout_polygon2,pcb_cutout_path2]).describe("Defines a cutout on the PCB, removing board material.");expectTypesMatch3(!0);var pcb_missing_footprint_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_missing_footprint_error"),pcb_missing_footprint_error_id:getZodPrefixedIdWithDefault2("pcb_missing_footprint_error"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),error_type:external_exports2.literal("pcb_missing_footprint_error").default("pcb_missing_footprint_error"),source_component_id:external_exports2.string()}).describe("Defines a missing footprint error on the PCB");expectTypesMatch3(!0);var external_footprint_load_error2=base_circuit_json_error2.extend({type:external_exports2.literal("external_footprint_load_error"),external_footprint_load_error_id:getZodPrefixedIdWithDefault2("external_footprint_load_error"),pcb_component_id:external_exports2.string(),source_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),footprinter_string:external_exports2.string().optional(),error_type:external_exports2.literal("external_footprint_load_error").default("external_footprint_load_error")}).describe("Defines an error when an external footprint fails to load");expectTypesMatch3(!0);var circuit_json_footprint_load_error2=base_circuit_json_error2.extend({type:external_exports2.literal("circuit_json_footprint_load_error"),circuit_json_footprint_load_error_id:getZodPrefixedIdWithDefault2("circuit_json_footprint_load_error"),pcb_component_id:external_exports2.string(),source_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),error_type:external_exports2.literal("circuit_json_footprint_load_error").default("circuit_json_footprint_load_error"),circuit_json:external_exports2.array(external_exports2.any()).optional()}).describe("Defines an error when a circuit JSON footprint fails to load");expectTypesMatch3(!0);var pcb_group2=external_exports2.object({type:external_exports2.literal("pcb_group"),pcb_group_id:getZodPrefixedIdWithDefault2("pcb_group"),source_group_id:external_exports2.string(),is_subcircuit:external_exports2.boolean().optional(),subcircuit_id:external_exports2.string().optional(),width:length3.optional(),height:length3.optional(),center:point5,display_offset_x:external_exports2.string().optional().describe("How to display the x offset for this group, usually corresponding with how the user specified it"),display_offset_y:external_exports2.string().optional().describe("How to display the y offset for this group, usually corresponding with how the user specified it"),outline:external_exports2.array(point5).optional(),anchor_position:point5.optional(),anchor_alignment:ninePointAnchor3.default("center"),position_mode:external_exports2.enum(["packed","relative_to_group_anchor","none"]).optional(),positioned_relative_to_pcb_group_id:external_exports2.string().optional(),positioned_relative_to_pcb_board_id:external_exports2.string().optional(),pcb_component_ids:external_exports2.array(external_exports2.string()),child_layout_mode:external_exports2.enum(["packed","none"]).optional(),name:external_exports2.string().optional(),description:external_exports2.string().optional(),layout_mode:external_exports2.string().optional(),autorouter_configuration:external_exports2.object({trace_clearance:length3}).optional(),autorouter_used_string:external_exports2.string().optional()}).describe("Defines a group of components on the PCB");expectTypesMatch3(!0);var pcb_autorouting_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_autorouting_error"),pcb_error_id:getZodPrefixedIdWithDefault2("pcb_autorouting_error"),error_type:external_exports2.literal("pcb_autorouting_error").default("pcb_autorouting_error"),subcircuit_id:external_exports2.string().optional()}).describe("The autorouting has failed to route a portion of the board");expectTypesMatch3(!0);var pcb_manual_edit_conflict_warning2=external_exports2.object({type:external_exports2.literal("pcb_manual_edit_conflict_warning"),pcb_manual_edit_conflict_warning_id:getZodPrefixedIdWithDefault2("pcb_manual_edit_conflict_warning"),warning_type:external_exports2.literal("pcb_manual_edit_conflict_warning").default("pcb_manual_edit_conflict_warning"),message:external_exports2.string(),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),source_component_id:external_exports2.string()}).describe("Warning emitted when a component has both manual placement and explicit pcbX/pcbY coordinates");expectTypesMatch3(!0);var connectorOrientationDirection2=external_exports2.enum(["x-","x+","y+","y-"]),pcb_connector_not_in_accessible_orientation_warning2=external_exports2.object({type:external_exports2.literal("pcb_connector_not_in_accessible_orientation_warning"),pcb_connector_not_in_accessible_orientation_warning_id:getZodPrefixedIdWithDefault2("pcb_connector_not_in_accessible_orientation_warning"),warning_type:external_exports2.literal("pcb_connector_not_in_accessible_orientation_warning").default("pcb_connector_not_in_accessible_orientation_warning"),message:external_exports2.string(),pcb_component_id:external_exports2.string(),source_component_id:external_exports2.string().optional(),pcb_board_id:external_exports2.string().optional(),facing_direction:connectorOrientationDirection2,recommended_facing_direction:connectorOrientationDirection2,subcircuit_id:external_exports2.string().optional()}).describe("Warning emitted when a connector PCB component is facing inward toward the board and should be reoriented to an outward-facing direction");expectTypesMatch3(!0);var supplier_footprint_mismatch_warning2=external_exports2.object({type:external_exports2.literal("supplier_footprint_mismatch_warning"),supplier_footprint_mismatch_warning_id:getZodPrefixedIdWithDefault2("supplier_footprint_mismatch_warning"),warning_type:external_exports2.literal("supplier_footprint_mismatch_warning").default("supplier_footprint_mismatch_warning"),message:external_exports2.string(),source_component_id:external_exports2.string(),pcb_component_id:external_exports2.string().optional(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),supplier_name:supplier_name2.optional(),supplier_part_number:external_exports2.string().optional(),supplier_footprint_url:external_exports2.string().optional(),footprint_copper_intersection_over_union:external_exports2.number()}).describe("Warning emitted when a supplier part footprint does not match the expected footprint");expectTypesMatch3(!0);var pcb_breakout_point2=external_exports2.object({type:external_exports2.literal("pcb_breakout_point"),pcb_breakout_point_id:getZodPrefixedIdWithDefault2("pcb_breakout_point"),pcb_group_id:external_exports2.string(),subcircuit_id:external_exports2.string().optional(),source_trace_id:external_exports2.string().optional(),source_port_id:external_exports2.string().optional(),source_net_id:external_exports2.string().optional(),x:distance7,y:distance7}).describe("Defines a routing target within a pcb_group for a source_trace or source_net");expectTypesMatch3(!0);var pcb_ground_plane2=external_exports2.object({type:external_exports2.literal("pcb_ground_plane"),pcb_ground_plane_id:getZodPrefixedIdWithDefault2("pcb_ground_plane"),source_pcb_ground_plane_id:external_exports2.string(),source_net_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("Defines a ground plane on the PCB");expectTypesMatch3(!0);var pcb_ground_plane_region2=external_exports2.object({type:external_exports2.literal("pcb_ground_plane_region"),pcb_ground_plane_region_id:getZodPrefixedIdWithDefault2("pcb_ground_plane_region"),pcb_ground_plane_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:layer_ref2,points:external_exports2.array(point5)}).describe("Defines a polygon region of a ground plane");expectTypesMatch3(!0);var pcb_thermal_spoke2=external_exports2.object({type:external_exports2.literal("pcb_thermal_spoke"),pcb_thermal_spoke_id:getZodPrefixedIdWithDefault2("pcb_thermal_spoke"),pcb_ground_plane_id:external_exports2.string(),shape:external_exports2.string(),spoke_count:external_exports2.number(),spoke_thickness:distance7,spoke_inner_diameter:distance7,spoke_outer_diameter:distance7,pcb_plated_hole_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("Pattern for connecting a ground plane to a plated hole");expectTypesMatch3(!0);var pcb_copper_pour_base2=external_exports2.object({type:external_exports2.literal("pcb_copper_pour"),pcb_copper_pour_id:getZodPrefixedIdWithDefault2("pcb_copper_pour"),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:layer_ref2,source_net_id:external_exports2.string().optional(),covered_with_solder_mask:external_exports2.boolean().optional().default(!0)}),pcb_copper_pour_rect2=pcb_copper_pour_base2.extend({shape:external_exports2.literal("rect"),center:point5,width:length3,height:length3,rotation:rotation4.optional()});expectTypesMatch3(!0);var pcb_copper_pour_brep2=pcb_copper_pour_base2.extend({shape:external_exports2.literal("brep"),brep_shape:brep_shape2});expectTypesMatch3(!0);var pcb_copper_pour_polygon2=pcb_copper_pour_base2.extend({shape:external_exports2.literal("polygon"),points:external_exports2.array(point5)});expectTypesMatch3(!0);var pcb_copper_pour2=external_exports2.discriminatedUnion("shape",[pcb_copper_pour_rect2,pcb_copper_pour_brep2,pcb_copper_pour_polygon2]).describe("Defines a copper pour on the PCB.");expectTypesMatch3(!0);var pcb_component_outside_board_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_component_outside_board_error"),pcb_component_outside_board_error_id:getZodPrefixedIdWithDefault2("pcb_component_outside_board_error"),error_type:external_exports2.literal("pcb_component_outside_board_error").default("pcb_component_outside_board_error"),pcb_component_id:external_exports2.string(),pcb_board_id:external_exports2.string(),component_center:point5,component_bounds:external_exports2.object({min_x:external_exports2.number(),max_x:external_exports2.number(),min_y:external_exports2.number(),max_y:external_exports2.number()}),subcircuit_id:external_exports2.string().optional(),source_component_id:external_exports2.string().optional()}).describe("Error emitted when a PCB component is placed outside the board boundaries");expectTypesMatch3(!0);var pcb_component_not_on_board_edge_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_component_not_on_board_edge_error"),pcb_component_not_on_board_edge_error_id:getZodPrefixedIdWithDefault2("pcb_component_not_on_board_edge_error"),error_type:external_exports2.literal("pcb_component_not_on_board_edge_error").default("pcb_component_not_on_board_edge_error"),pcb_component_id:external_exports2.string(),pcb_board_id:external_exports2.string(),component_center:point5,pad_to_nearest_board_edge_distance:external_exports2.number(),source_component_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when a component that must be placed on the board edge is centered away from the edge");expectTypesMatch3(!0);var pcb_component_invalid_layer_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_component_invalid_layer_error"),pcb_component_invalid_layer_error_id:getZodPrefixedIdWithDefault2("pcb_component_invalid_layer_error"),error_type:external_exports2.literal("pcb_component_invalid_layer_error").default("pcb_component_invalid_layer_error"),pcb_component_id:external_exports2.string().optional(),source_component_id:external_exports2.string(),layer:layer_ref2,subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when a component is placed on an invalid layer (components can only be on 'top' or 'bottom' layers)");expectTypesMatch3(!0);var pcb_via_clearance_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_via_clearance_error"),pcb_error_id:getZodPrefixedIdWithDefault2("pcb_error"),error_type:external_exports2.literal("pcb_via_clearance_error").default("pcb_via_clearance_error"),pcb_via_ids:external_exports2.array(external_exports2.string()).min(2),minimum_clearance:distance7.optional(),actual_clearance:distance7.optional(),pcb_center:external_exports2.object({x:external_exports2.number().optional(),y:external_exports2.number().optional()}).optional(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when vias are closer than the allowed clearance");expectTypesMatch3(!0);var pcb_via_trace_clearance_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_via_trace_clearance_error"),pcb_via_trace_clearance_error_id:getZodPrefixedIdWithDefault2("pcb_via_trace_clearance_error"),error_type:external_exports2.literal("pcb_via_trace_clearance_error").default("pcb_via_trace_clearance_error"),pcb_via_id:external_exports2.string(),pcb_trace_id:external_exports2.string(),minimum_clearance:distance7.optional(),actual_clearance:distance7.optional(),center:external_exports2.object({x:external_exports2.number().optional(),y:external_exports2.number().optional()}).optional(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when a via and trace are closer than the allowed clearance");expectTypesMatch3(!0);var pcb_pad_pad_clearance_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_pad_pad_clearance_error"),pcb_pad_pad_clearance_error_id:getZodPrefixedIdWithDefault2("pcb_pad_pad_clearance_error"),error_type:external_exports2.literal("pcb_pad_pad_clearance_error").default("pcb_pad_pad_clearance_error"),pcb_pad_ids:external_exports2.array(external_exports2.string()).min(2),minimum_clearance:distance7.optional(),actual_clearance:distance7.optional(),center:external_exports2.object({x:external_exports2.number().optional(),y:external_exports2.number().optional()}).optional(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when pads are closer than the allowed clearance");expectTypesMatch3(!0);var pcb_pad_trace_clearance_error2=base_circuit_json_error2.extend({type:external_exports2.literal("pcb_pad_trace_clearance_error"),pcb_pad_trace_clearance_error_id:getZodPrefixedIdWithDefault2("pcb_pad_trace_clearance_error"),error_type:external_exports2.literal("pcb_pad_trace_clearance_error").default("pcb_pad_trace_clearance_error"),pcb_pad_id:external_exports2.string(),pcb_trace_id:external_exports2.string(),minimum_clearance:distance7.optional(),actual_clearance:distance7.optional(),center:external_exports2.object({x:external_exports2.number().optional(),y:external_exports2.number().optional()}).optional(),subcircuit_id:external_exports2.string().optional()}).describe("Error emitted when a pad and trace are closer than allowed clearance");expectTypesMatch3(!0);var pcb_courtyard_rect2=external_exports2.object({type:external_exports2.literal("pcb_courtyard_rect"),pcb_courtyard_rect_id:getZodPrefixedIdWithDefault2("pcb_courtyard_rect"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,width:length3,height:length3,layer:visible_layer2,ccw_rotation:rotation4.optional(),color:external_exports2.string().optional()}).describe("Defines a courtyard rectangle on the PCB");expectTypesMatch3(!0);var pcb_courtyard_outline2=external_exports2.object({type:external_exports2.literal("pcb_courtyard_outline"),pcb_courtyard_outline_id:getZodPrefixedIdWithDefault2("pcb_courtyard_outline"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:visible_layer2,outline:external_exports2.array(point5).min(2)}).describe("Defines a courtyard outline on the PCB");expectTypesMatch3(!0);var pcb_courtyard_polygon2=external_exports2.object({type:external_exports2.literal("pcb_courtyard_polygon"),pcb_courtyard_polygon_id:getZodPrefixedIdWithDefault2("pcb_courtyard_polygon"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),layer:visible_layer2,points:external_exports2.array(point5).min(3),color:external_exports2.string().optional()}).describe("Defines a courtyard polygon on the PCB");expectTypesMatch3(!0);var pcb_courtyard_circle2=external_exports2.object({type:external_exports2.literal("pcb_courtyard_circle"),pcb_courtyard_circle_id:getZodPrefixedIdWithDefault2("pcb_courtyard_circle"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,radius:length3,layer:visible_layer2,color:external_exports2.string().optional()}).describe("Defines a courtyard circle on the PCB");expectTypesMatch3(!0);var pcb_courtyard_pill2=external_exports2.object({type:external_exports2.literal("pcb_courtyard_pill"),pcb_courtyard_pill_id:getZodPrefixedIdWithDefault2("pcb_courtyard_pill"),pcb_component_id:external_exports2.string(),pcb_group_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),center:point5,width:length3,height:length3,radius:length3,layer:visible_layer2,color:external_exports2.string().optional()}).describe("Defines a courtyard pill on the PCB");expectTypesMatch3(!0);var cad_model_formats2=["obj","stl","3mf","gltf","glb","step","wrl"],cad_model_axis_directions2=["x+","x-","y+","y-","z+","z-"],cadModelDefaultDirectionMap2={obj:"z+",stl:"z+","3mf":"z+",gltf:"y+",glb:"y+",step:"z+",wrl:"y+"},cad_component2=external_exports2.object({type:external_exports2.literal("cad_component"),cad_component_id:external_exports2.string(),pcb_component_id:external_exports2.string(),source_component_id:external_exports2.string(),position:point33,rotation:point33.optional(),size:point33.optional(),layer:layer_ref2.optional(),subcircuit_id:external_exports2.string().optional(),footprinter_string:external_exports2.string().optional(),model_obj_url:external_exports2.string().optional(),model_stl_url:external_exports2.string().optional(),model_3mf_url:external_exports2.string().optional(),model_gltf_url:external_exports2.string().optional(),model_glb_url:external_exports2.string().optional(),model_step_url:external_exports2.string().optional(),model_wrl_url:external_exports2.string().optional(),model_asset:asset2.optional(),model_unit_to_mm_scale_factor:external_exports2.number().optional(),model_board_normal_direction:external_exports2.enum(cad_model_axis_directions2).optional().describe(`The direction in the model's coordinate space that is considered "up" or "coming out of the board surface"`),model_origin_position:point33.optional(),model_origin_alignment:external_exports2.enum(["unknown","center","center_of_component_on_board_surface","bottom_center_of_component"]).optional(),model_object_fit:external_exports2.enum(["contain_within_bounds","fill_bounds"]).optional().default("contain_within_bounds"),model_jscad:external_exports2.any().optional(),show_as_translucent_model:external_exports2.boolean().optional(),show_as_bounding_box:external_exports2.boolean().optional(),anchor_alignment:external_exports2.enum(["center","center_of_component_on_board_surface"]).optional().default("center")}).describe("Defines a component on the PCB");expectTypesMatch3(!0);var wave_shape2=external_exports2.enum(["sinewave","square","triangle","sawtooth"]),percentage4=external_exports2.union([external_exports2.string(),external_exports2.number()]).transform(val=>typeof val=="string"?val.endsWith("%")?parseFloat(val.slice(0,-1))/100:parseFloat(val):val).pipe(external_exports2.number().min(0,"Duty cycle must be non-negative").max(1,"Duty cycle cannot be greater than 100%")),simulation_dc_voltage_source2=external_exports2.object({type:external_exports2.literal("simulation_voltage_source"),simulation_voltage_source_id:getZodPrefixedIdWithDefault2("simulation_voltage_source"),is_dc_source:external_exports2.literal(!0).optional().default(!0),positive_source_port_id:external_exports2.string().optional(),negative_source_port_id:external_exports2.string().optional(),positive_source_net_id:external_exports2.string().optional(),negative_source_net_id:external_exports2.string().optional(),voltage:voltage2}).describe("Defines a DC voltage source for simulation"),simulation_ac_voltage_source2=external_exports2.object({type:external_exports2.literal("simulation_voltage_source"),simulation_voltage_source_id:getZodPrefixedIdWithDefault2("simulation_voltage_source"),is_dc_source:external_exports2.literal(!1),terminal1_source_port_id:external_exports2.string().optional(),terminal2_source_port_id:external_exports2.string().optional(),terminal1_source_net_id:external_exports2.string().optional(),terminal2_source_net_id:external_exports2.string().optional(),voltage:voltage2.optional(),frequency:frequency2.optional(),peak_to_peak_voltage:voltage2.optional(),wave_shape:wave_shape2.optional(),phase:rotation4.optional(),duty_cycle:percentage4.optional(),pulse_delay:ms4.optional(),rise_time:ms4.optional(),fall_time:ms4.optional(),pulse_width:ms4.optional(),period:ms4.optional()}).describe("Defines an AC voltage source for simulation"),simulation_voltage_source2=external_exports2.union([simulation_dc_voltage_source2,simulation_ac_voltage_source2]).describe("Defines a voltage source for simulation");expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);var percentage23=external_exports2.union([external_exports2.string(),external_exports2.number()]).transform(val=>typeof val=="string"?val.endsWith("%")?parseFloat(val.slice(0,-1))/100:parseFloat(val):val).pipe(external_exports2.number().min(0,"Duty cycle must be non-negative").max(1,"Duty cycle cannot be greater than 100%")),simulation_dc_current_source2=external_exports2.object({type:external_exports2.literal("simulation_current_source"),simulation_current_source_id:getZodPrefixedIdWithDefault2("simulation_current_source"),is_dc_source:external_exports2.literal(!0).optional().default(!0),positive_source_port_id:external_exports2.string().optional(),negative_source_port_id:external_exports2.string().optional(),positive_source_net_id:external_exports2.string().optional(),negative_source_net_id:external_exports2.string().optional(),current:current2}).describe("Defines a DC current source for simulation"),simulation_ac_current_source2=external_exports2.object({type:external_exports2.literal("simulation_current_source"),simulation_current_source_id:getZodPrefixedIdWithDefault2("simulation_current_source"),is_dc_source:external_exports2.literal(!1),terminal1_source_port_id:external_exports2.string().optional(),terminal2_source_port_id:external_exports2.string().optional(),terminal1_source_net_id:external_exports2.string().optional(),terminal2_source_net_id:external_exports2.string().optional(),current:current2.optional(),frequency:frequency2.optional(),peak_to_peak_current:current2.optional(),wave_shape:wave_shape2.optional(),phase:rotation4.optional(),duty_cycle:percentage23.optional()}).describe("Defines an AC current source for simulation"),simulation_current_source2=external_exports2.union([simulation_dc_current_source2,simulation_ac_current_source2]).describe("Defines a current source for simulation");expectTypesMatch3(!0);expectTypesMatch3(!0);expectTypesMatch3(!0);var experiment_type2=external_exports2.union([external_exports2.literal("spice_dc_sweep"),external_exports2.literal("spice_dc_operating_point"),external_exports2.literal("spice_transient_analysis"),external_exports2.literal("spice_ac_analysis")]),spice_simulation_options2=external_exports2.object({method:external_exports2.enum(["trap","gear"]).optional(),reltol:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),abstol:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional(),vntol:external_exports2.union([external_exports2.number(),external_exports2.string()]).optional()}).describe("SPICE solver options for a simulation experiment"),simulation_experiment2=external_exports2.object({type:external_exports2.literal("simulation_experiment"),simulation_experiment_id:getZodPrefixedIdWithDefault2("simulation_experiment"),name:external_exports2.string(),experiment_type:experiment_type2,time_per_step:duration_ms2.optional(),start_time_ms:ms4.optional(),end_time_ms:ms4.optional(),spice_options:spice_simulation_options2.optional()}).describe("Defines a simulation experiment configuration");expectTypesMatch3(!0);var simulation_transient_voltage_graph2=external_exports2.object({type:external_exports2.literal("simulation_transient_voltage_graph"),simulation_transient_voltage_graph_id:getZodPrefixedIdWithDefault2("simulation_transient_voltage_graph"),simulation_experiment_id:external_exports2.string(),timestamps_ms:external_exports2.array(external_exports2.number()).optional(),voltage_levels:external_exports2.array(external_exports2.number()),source_component_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional(),time_per_step:duration_ms2,start_time_ms:ms4,end_time_ms:ms4,name:external_exports2.string().optional(),color:external_exports2.string().optional()}).describe("Stores voltage measurements over time for a simulation");expectTypesMatch3(!0);var simulation_transient_current_graph2=external_exports2.object({type:external_exports2.literal("simulation_transient_current_graph"),simulation_transient_current_graph_id:getZodPrefixedIdWithDefault2("simulation_transient_current_graph"),simulation_experiment_id:external_exports2.string(),timestamps_ms:external_exports2.array(external_exports2.number()).optional(),current_levels:external_exports2.array(external_exports2.number()),source_component_id:external_exports2.string().optional(),subcircuit_connectivity_map_key:external_exports2.string().optional(),time_per_step:duration_ms2,start_time_ms:ms4,end_time_ms:ms4,name:external_exports2.string().optional(),color:external_exports2.string().optional()}).describe("Stores current measurements over time for a simulation");expectTypesMatch3(!0);var simulation_switch2=external_exports2.object({type:external_exports2.literal("simulation_switch"),simulation_switch_id:getZodPrefixedIdWithDefault2("simulation_switch"),source_component_id:external_exports2.string().optional(),closes_at:ms4.optional(),opens_at:ms4.optional(),starts_closed:external_exports2.boolean().optional(),switching_frequency:frequency2.optional()}).describe("Defines a switch for simulation timing control");expectTypesMatch3(!0);var simulation_voltage_probe2=external_exports2.object({type:external_exports2.literal("simulation_voltage_probe"),simulation_voltage_probe_id:getZodPrefixedIdWithDefault2("simulation_voltage_probe"),source_component_id:external_exports2.string().optional(),name:external_exports2.string().optional(),signal_input_source_port_id:external_exports2.string().optional(),signal_input_source_net_id:external_exports2.string().optional(),reference_input_source_port_id:external_exports2.string().optional(),reference_input_source_net_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),color:external_exports2.string().optional()}).describe("Defines a voltage probe for simulation. If a reference input is not provided, it measures against ground. If a reference input is provided, it measures the differential voltage between two points.").superRefine((data,ctx)=>{if(data.reference_input_source_port_id||data.reference_input_source_net_id){let has_ports=!!data.signal_input_source_port_id||!!data.reference_input_source_port_id,has_nets=!!data.signal_input_source_net_id||!!data.reference_input_source_net_id;has_ports&&has_nets?ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Cannot mix port and net connections in a differential probe."}):has_ports?(!data.signal_input_source_port_id||!data.reference_input_source_port_id)&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Differential port probe requires both signal_input_source_port_id and reference_input_source_port_id."}):has_nets&&(!data.signal_input_source_net_id||!data.reference_input_source_net_id)&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Differential net probe requires both signal_input_source_net_id and reference_input_source_net_id."})}else!!data.signal_input_source_port_id==!!data.signal_input_source_net_id&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"A voltage probe must have exactly one of signal_input_source_port_id or signal_input_source_net_id."})});expectTypesMatch3(!0);var simulation_current_probe2=external_exports2.object({type:external_exports2.literal("simulation_current_probe"),simulation_current_probe_id:getZodPrefixedIdWithDefault2("simulation_current_probe"),source_component_id:external_exports2.string().optional(),name:external_exports2.string().optional(),positive_source_port_id:external_exports2.string().optional(),negative_source_port_id:external_exports2.string().optional(),positive_source_net_id:external_exports2.string().optional(),negative_source_net_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional(),color:external_exports2.string().optional()}).describe("Defines a current probe for simulation. It measures current flowing from the positive endpoint to the negative endpoint.").superRefine((data,ctx)=>{let hasPositivePort=!!data.positive_source_port_id,hasNegativePort=!!data.negative_source_port_id,hasPositiveNet=!!data.positive_source_net_id,hasNegativeNet=!!data.negative_source_net_id,hasPorts=hasPositivePort||hasNegativePort,hasNets=hasPositiveNet||hasNegativeNet;if(hasPorts&&hasNets){ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Cannot mix port and net connections in a current probe."});return}if(hasPorts){(!hasPositivePort||!hasNegativePort)&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Current probe using source ports requires both positive_source_port_id and negative_source_port_id."});return}if(hasNets){(!hasPositiveNet||!hasNegativeNet)&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Current probe using source nets requires both positive_source_net_id and negative_source_net_id."});return}ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"A current probe must have either positive/negative source port ids or positive/negative source net ids."})});expectTypesMatch3(!0);var simulation_unknown_experiment_error2=base_circuit_json_error2.extend({type:external_exports2.literal("simulation_unknown_experiment_error"),simulation_unknown_experiment_error_id:getZodPrefixedIdWithDefault2("simulation_unknown_experiment_error"),error_type:external_exports2.literal("simulation_unknown_experiment_error").default("simulation_unknown_experiment_error"),simulation_experiment_id:external_exports2.string().optional(),subcircuit_id:external_exports2.string().optional()}).describe("An unknown error occurred during the simulation experiment.");expectTypesMatch3(!0);var simulation_op_amp2=external_exports2.object({type:external_exports2.literal("simulation_op_amp"),simulation_op_amp_id:getZodPrefixedIdWithDefault2("simulation_op_amp"),source_component_id:external_exports2.string().optional(),inverting_input_source_port_id:external_exports2.string(),non_inverting_input_source_port_id:external_exports2.string(),output_source_port_id:external_exports2.string(),positive_supply_source_port_id:external_exports2.string(),negative_supply_source_port_id:external_exports2.string()}).describe("Defines a simple ideal operational amplifier for simulation");expectTypesMatch3(!0);var simulation_spice_subcircuit2=external_exports2.object({type:external_exports2.literal("simulation_spice_subcircuit"),simulation_spice_subcircuit_id:getZodPrefixedIdWithDefault2("simulation_spice_subcircuit"),source_component_id:external_exports2.string(),spice_pin_to_source_port_map:external_exports2.record(external_exports2.string(),external_exports2.string()),subcircuit_source:external_exports2.string()}).describe("Defines a custom SPICE subcircuit model for simulation");expectTypesMatch3(!0);var hasValue2=value=>value!==void 0,simulation_oscilloscope_trace2=external_exports2.object({type:external_exports2.literal("simulation_oscilloscope_trace"),simulation_oscilloscope_trace_id:getZodPrefixedIdWithDefault2("simulation_oscilloscope_trace"),simulation_transient_voltage_graph_id:external_exports2.string().optional(),simulation_transient_current_graph_id:external_exports2.string().optional(),simulation_voltage_probe_id:external_exports2.string().optional(),simulation_current_probe_id:external_exports2.string().optional(),display_name:external_exports2.string().optional(),color:external_exports2.string().optional(),display_center_value:external_exports2.number().optional(),display_center_offset_divs:external_exports2.number().optional(),volts_per_div:external_exports2.number().positive().optional(),amps_per_div:external_exports2.number().positive().optional()}).describe("Defines how a simulation measurement is rendered as an oscilloscope-style trace.").superRefine((data,ctx)=>{let voltageReferences=[data.simulation_transient_voltage_graph_id,data.simulation_voltage_probe_id].filter(hasValue2).length,currentReferences=[data.simulation_transient_current_graph_id,data.simulation_current_probe_id].filter(hasValue2).length;voltageReferences+currentReferences!==1&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"An oscilloscope trace must reference exactly one voltage graph, current graph, voltage probe, or current probe."}),voltageReferences>0&&data.amps_per_div!==void 0&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Voltage oscilloscope traces must use volts_per_div, not amps_per_div."}),currentReferences>0&&data.volts_per_div!==void 0&&ctx.addIssue({code:external_exports2.ZodIssueCode.custom,message:"Current oscilloscope traces must use amps_per_div, not volts_per_div."})});expectTypesMatch3(!0);var any_circuit_element2=external_exports2.union([source_trace2,source_port2,source_component_internal_connection2,any_source_component2,source_net2,source_group2,source_simple_chip2,source_simple_capacitor2,source_simple_diode2,source_simple_led2,source_simple_resistor2,source_simple_power_source2,source_simple_battery2,source_simple_inductor2,source_simple_pin_header2,source_simple_pinout2,source_simple_resonator2,source_simple_switch2,source_simple_transistor2,source_simple_test_point2,source_simple_mosfet2,source_simple_op_amp2,source_simple_potentiometer2,source_simple_push_button2,source_pcb_ground_plane2,source_manually_placed_via2,source_board2,source_project_metadata2,source_invalid_component_property_error2,source_trace_not_connected_error2,source_pin_missing_trace_warning2,source_unnamed_trace_warning2,source_missing_manufacturer_part_number_warning2,source_refdes_convention_warning2,source_no_power_pin_defined_warning2,source_no_ground_pin_defined_warning2,source_component_pins_underspecified_warning2,source_pin_must_be_connected_error2,unknown_error_finding_part2,source_part_not_found_warning2,source_i2c_misconfigured_error2,source_component_misconfigured_error2,source_ambiguous_port_reference2,pcb_component2,pcb_hole2,pcb_missing_footprint_error2,external_footprint_load_error2,circuit_json_footprint_load_error2,pcb_manual_edit_conflict_warning2,pcb_connector_not_in_accessible_orientation_warning2,supplier_footprint_mismatch_warning2,pcb_plated_hole2,pcb_keepout2,pcb_port2,pcb_net2,pcb_text2,pcb_trace2,pcb_trace_warning2,pcb_via2,pcb_smtpad2,pcb_solder_paste2,pcb_board2,pcb_panel2,pcb_group2,pcb_trace_hint2,pcb_silkscreen_line2,pcb_silkscreen_path2,pcb_silkscreen_text2,pcb_silkscreen_pill2,pcb_copper_text2,pcb_silkscreen_rect2,pcb_silkscreen_circle2,pcb_silkscreen_oval2,pcb_silkscreen_graphic2,pcb_trace_error2,pcb_trace_missing_error2,pcb_placement_error2,pcb_panelization_placement_error2,pcb_port_not_matched_error2,pcb_port_not_connected_error2,pcb_via_clearance_error2,pcb_via_trace_clearance_error2,pcb_pad_pad_clearance_error2,pcb_pad_trace_clearance_error2,pcb_fabrication_note_path2,pcb_fabrication_note_text2,pcb_fabrication_note_rect2,pcb_fabrication_note_dimension2,pcb_note_text2,pcb_note_rect2,pcb_note_path2,pcb_note_line2,pcb_note_dimension2,pcb_autorouting_error2,pcb_footprint_overlap_error2,pcb_courtyard_overlap_error2,pcb_breakout_point2,pcb_cutout2,pcb_ground_plane2,pcb_ground_plane_region2,pcb_thermal_spoke2,pcb_copper_pour2,pcb_component_outside_board_error2,pcb_component_not_on_board_edge_error2,pcb_component_invalid_layer_error2,pcb_courtyard_rect2,pcb_courtyard_outline2,pcb_courtyard_polygon2,pcb_courtyard_circle2,pcb_courtyard_pill2,schematic_box2,schematic_text2,schematic_line2,schematic_rect2,schematic_circle2,schematic_arc2,schematic_component2,schematic_symbol2,schematic_port2,schematic_trace2,schematic_path2,schematic_error2,schematic_layout_error2,schematic_net_label2,schematic_debug_object2,schematic_voltage_probe2,schematic_manual_edit_conflict_warning2,schematic_group2,schematic_sheet2,schematic_table2,schematic_table_cell2,cad_component2,simulation_voltage_source2,simulation_current_source2,simulation_experiment2,simulation_transient_voltage_graph2,simulation_transient_current_graph2,simulation_switch2,simulation_voltage_probe2,simulation_current_probe2,simulation_oscilloscope_trace2,simulation_unknown_experiment_error2,simulation_op_amp2,simulation_spice_subcircuit2]),any_soup_element2=any_circuit_element2;expectTypesMatch3(!0);expectStringUnionsMatch2(!0);function applyToPoint5(matrix2,point22){return Array.isArray(point22)?[matrix2.a*point22[0]+matrix2.c*point22[1]+matrix2.e,matrix2.b*point22[0]+matrix2.d*point22[1]+matrix2.f]:{x:matrix2.a*point22.x+matrix2.c*point22.y+matrix2.e,y:matrix2.b*point22.x+matrix2.d*point22.y+matrix2.f}}function isUndefined5(val){return typeof val>"u"}function translate6(tx3,ty3=0){return{a:1,c:0,e:tx3,b:0,d:1,f:ty3}}function transform5(...matrices){matrices=Array.isArray(matrices[0])?matrices[0]:matrices;let multiply=(m12,m22)=>({a:m12.a*m22.a+m12.c*m22.b,c:m12.a*m22.c+m12.c*m22.d,e:m12.a*m22.e+m12.c*m22.f+m12.e,b:m12.b*m22.a+m12.d*m22.b,d:m12.b*m22.c+m12.d*m22.d,f:m12.b*m22.e+m12.d*m22.f+m12.f});switch(matrices.length){case 0:throw new Error("no matrices provided");case 1:return matrices[0];case 2:return multiply(matrices[0],matrices[1]);default:{let[m12,m22,...rest]=matrices,m6=multiply(m12,m22);return transform5(m6,...rest)}}}function compose5(...matrices){return transform5(...matrices)}var{cos:cos5,sin:sin5,PI:PI6}=Math;function scale5(sx3,sy3=void 0,cx3=void 0,cy3=void 0){isUndefined5(sy3)&&(sy3=sx3);let scaleMatrix={a:sx3,c:0,e:0,b:0,d:sy3,f:0};return isUndefined5(cx3)||isUndefined5(cy3)?scaleMatrix:transform5([translate6(cx3,cy3),scaleMatrix,translate6(-cx3,-cy3)])}var{tan:tan5}=Math;function peg$subclass4(child,parent){function C4(){this.constructor=child}C4.prototype=parent.prototype,child.prototype=new C4}function peg$SyntaxError4(message,expected,found,location){var self2=Error.call(this,message);return Object.setPrototypeOf&&Object.setPrototypeOf(self2,peg$SyntaxError4.prototype),self2.expected=expected,self2.found=found,self2.location=location,self2.name="SyntaxError",self2}peg$subclass4(peg$SyntaxError4,Error);function peg$padEnd4(str,targetLength,padString){return padString=padString||" ",str.length>targetLength?str:(targetLength-=str.length,padString+=padString.repeat(targetLength),str+padString.slice(0,targetLength))}peg$SyntaxError4.prototype.format=function(sources){var str="Error: "+this.message;if(this.location){var src=null,k7;for(k7=0;k7<sources.length;k7++)if(sources[k7].source===this.location.source){src=sources[k7].text.split(/\r\n|\n|\r/g);break}var s6=this.location.start,offset_s=this.location.source&&typeof this.location.source.offset=="function"?this.location.source.offset(s6):s6,loc=this.location.source+":"+offset_s.line+":"+offset_s.column;if(src){var e6=this.location.end,filler=peg$padEnd4("",offset_s.line.toString().length," "),line2=src[s6.line-1],last=s6.line===e6.line?e6.column:line2.length+1,hatLen=last-s6.column||1;str+=`