@tscircuit/eval 0.0.618 → 0.0.619
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blob-url.js +1 -1
- package/dist/webworker/entrypoint.js +6 -6
- package/package.json +7 -6
|
@@ -268,7 +268,7 @@ React keys must be passed directly to JSX without using spread:
|
|
|
268
268
|
`+filler+` |
|
|
269
269
|
`+offset_s.line+" | "+line2+`
|
|
270
270
|
`+filler+" | "+peg$padEnd2("",s2.column-1," ")+peg$padEnd2("",hatLen,"^")}else str+=`
|
|
271
|
-
at `+loc}return str};peg$SyntaxError2.buildMessage=function(expected,found){var DESCRIBE_EXPECTATION_FNS={literal:function(expectation){return'"'+literalEscape(expectation.text)+'"'},class:function(expectation){var escapedParts=expectation.parts.map(function(part){return Array.isArray(part)?classEscape(part[0])+"-"+classEscape(part[1]):classEscape(part)});return"["+(expectation.inverted?"^":"")+escapedParts.join("")+"]"},any:function(){return"any character"},end:function(){return"end of input"},other:function(expectation){return expectation.description}};function hex(ch2){return ch2.charCodeAt(0).toString(16).toUpperCase()}function literalEscape(s2){return s2.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(ch2){return"\\x0"+hex(ch2)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(ch2){return"\\x"+hex(ch2)})}function classEscape(s2){return s2.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(ch2){return"\\x0"+hex(ch2)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(ch2){return"\\x"+hex(ch2)})}function describeExpectation(expectation){return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation)}function describeExpected(expected2){var descriptions=expected2.map(describeExpectation),i2,j4;if(descriptions.sort(),descriptions.length>0){for(i2=1,j4=1;i2<descriptions.length;i2++)descriptions[i2-1]!==descriptions[i2]&&(descriptions[j4]=descriptions[i2],j4++);descriptions.length=j4}switch(descriptions.length){case 1:return descriptions[0];case 2:return descriptions[0]+" or "+descriptions[1];default:return descriptions.slice(0,-1).join(", ")+", or "+descriptions[descriptions.length-1]}}function describeFound(found2){return found2?'"'+literalEscape(found2)+'"':"end of input"}return"Expected "+describeExpected(expected)+" but "+describeFound(found)+" found."}}});var init_fromTransformAttribute2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/fromTransformAttribute.js"(){"use strict";init_fromTransformAttribute_autogenerated2()}});var init_decompose2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/decompose.js"(){"use strict";init_scale2();init_transform2()}});var init_flip2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/flip.js"(){"use strict"}});var init_fromMovingPoints2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/fromMovingPoints.js"(){"use strict";init_translate2();init_applyToPoint2();init_rotate2();init_scale2();init_transform2()}});var init_src2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/index.js"(){"use strict";init_applyToPoint2();init_fromObject2();init_fromString2();init_identity2();init_inverse2();init_isAffineMatrix2();init_rotate2();init_scale2();init_shear2();init_skew2();init_toString2();init_transform2();init_translate2();init_fromTriangles2();init_smoothMatrix2();init_fromDefinition2();init_fromTransformAttribute2();init_decompose2();init_flip2();init_fromMovingPoints2()}});var svgAlphabet,lineAlphabet,init_dist7=__esm({"node_modules/@tscircuit/alphabet/dist/index.js"(){"use strict";svgAlphabet={0:"M0.4544564813877358 0L0.2723441540828736 0.03592830447352719L0.1086847233315459 0.14528754990019965L0.020630545837255005 0.3040632652221331L0 0.5395277421960205L0.049259221760993496 0.7369487828466779L0.18080513776237842 0.9005494166306564L0.37036887043974215 0.9872116270037247L0.5864663759301132 1L0.8148695622827444 0.9332890276148733L0.9326583645506394 0.8113052246023419L1 0.4031281830668562L0.833288960385582 0.09886798567812842L0.6801767918233781 0.02483708485091681L0.4544564813877358 0",1:"M 0.16 0.27 L 0.5 0 L 0.5 1",2:"M0.069593147751606 0.19461498231706575L0.1039380353319058 0.1224291500164194L0.20543361884368308 0.05510832064153169L0.3717712794432549 0.009452970962689482L0.4785344452623127 0L0.663238590738758 0.008714098643339864L0.8017933618843684 0.04769189395915288L0.8775637379550322 0.10746757678258442L0.9047778372591005 0.17693069668193287L0.9029710920770878 0.2231347105796246L0.8704496788008566 0.30047744598157516L0.7292906538577354 0.4508486051631194L0.3737955032119913 0.7369006417749693L0 1L1 1",3:"M0.03917438899874637 0.19855364635107545L0.15510940508963084 0.06745632622133718L0.37598645522339846 0L0.8486391893813088 0.0652271323161611L0.9782182415054349 0.21747394183735683L0.9213133780517754 0.3547560290117714L0.6504271515903481 0.4543436297681271L0.22975249764129613 0.48476611625264143L0.7659038682744629 0.5411919558122493L0.9258712987734741 0.6203185665660985L1 0.7458360609169667L0.8938813281118737 0.9059190913045964L0.6166890258875837 1L0.261528440153542 0.9874861530507921L0 0.8837289530851273",4:"M0.7328897338403042 0L0 0.6684672518568535L1 0.6684672518568535M0.7243346007604563 0.4530722484807562L0.7243346007604563 1",5:"M 0 0 L 0 0.4973 L 0.4262 0.4319 L 0.7305 0.4565 L 0.8516 0.5009 L 0.9357 0.5639 L 1 0.7356 L 0.9696 0.8248 L 0.8898 0.895 L 0.733 0.9602 L 0.5518 0.9945 L 0.3814 1 L 0.2379 0.9821 L 0.1219 0.947 L 0 0.8748 M 0 0 L 1 0",6:"M0.6964601700926856 0L0.3639239026215478 0.0743562375769351L0.1415931962925719 0.21735490179786915L0.009977939399608712 0.46336322325406004L0.00029622007592593224 0.7083131475173043L0.09408885043224748 0.8746809149767036L0.3379247445101846 0.9876686500961888L0.7109203869569624 1L0.9260852957913362 0.9103558029693921L1 0.7716571969091733L0.9824294723385016 0.6390635485705886L0.7446504992867332 0.4733643097729175L0.31028858071607296 0.47578021640899115L0.1208702146816024 0.5481452483973847L0 0.6616669755788906",7:"M0 0L1 0L0.9246479649697582 0.030539772727272752L0.8850302419354837 0.05075757575757579L0.7922946068548385 0.11079545454545457L0.7419268208165322 0.15213068181818185L0.6907258064516127 0.20202020202020204L0.6400666267641127 0.26122159090909086L0.5913243447580644 0.33049242424242414L0.5458740234374998 0.4105902777777778L0.5050907258064514 0.5022727272727272L0.4703495148689514 0.6062973484848484L0.43257456133442534 0.787133049242424L0.41612903225806447 1",8:"M0.5143001078924863 0L0.16007477667923162 0.10731570786949331L0.14924628550868277 0.3146018498698755L0.2939585848842112 0.41617921794558677L0.8648302624811545 0.5385163833653317L1 0.7775820770511038L0.8180842915260376 0.9505845566922285L0.41968938540525413 1L0.08062381919779889 0.882831681184498L0 0.6936376947135333L0.17150171673893433 0.5188652309607817L0.6529263782780712 0.4242818653203618L0.8650205888491803 0.29644027376796367L0.8702067371119496 0.09910067291661573L0.5143001078924863 0",9:"M1 0.25379591792994305L0.9514789771111742 0.11679361536614272L0.8702482473521467 0.05711741614054847L0.7327445265851579 0.015213872471965633L0.525248180711544 0L0.3292056884418538 0.012928195113745608L0.15997632037247655 0.058762870026191856L0.05266940041228321 0.12882439350476L0 0.2562067822770946L0.11316462894512366 0.4121335905917837L0.2403060136479954 0.4603365890068938L0.4097241967586011 0.4745978388276783L0.8642414300184816 0.420815170259988L0.9732054796346318 0.34537434075898393L1 0.25379591792994305M0.9647426784191072 0.35488595400360495L0.4756895081034974 1",A:"M0 1L0.4808333333333333 0L1 1M0.24250000000000002 0.6099439775910365L0.7341666666666666 0.6099439775910365",B:"M0 1L0 0.0117369978777208L0.30665717153513444 0L0.5874522807082946 0.03451403469442413L0.7766202217193218 0.15033936404895643L0.7471969743588041 0.31967962568332936L0.5246013359741988 0.4102978954282461L0.04378745314885416 0.44918617613783574L0.5112949594180156 0.469692928091109L0.8540266515643348 0.5552749498651879L1 0.6868463175009967L0.9880091196159324 0.8570018204672155L0.922301719975498 0.9321708046604659L0.7584266951758925 0.9932594737131338L0 1",C:"M1 0.23038928858890784L0.9328355511865092 0.12426412616785204L0.8096380839483327 0.04912601676267708L0.5763225801788256 0L0.4039037709527492 0.015028068281399815L0.2519579390951737 0.06533979308999706L0.10359458463139784 0.18146243506591617L0 0.4862728453971315L0.08129580872733055 0.792689266886982L0.20257034847159672 0.9160822255736587L0.3286572892798542 0.9738230826074175L0.5742878414421707 1L0.7883510303801312 0.9665431511195721L0.946851033994232 0.8689071500976585L1 0.7311049027121912",D:"M0 1L0.015604366822624637 0.020770988281483303L0.22564758265176144 0L0.3865476147957666 0.0024153386496795644L0.6479126635475078 0.051745644338731314L0.841191887805517 0.15827717679529366L0.9517008345536152 0.30172260586872185L0.9957536578687336 0.4504541551987709L1 0.5624359222498485L0.9798483279164735 0.6584121775234548L0.9386273319285215 0.7395945263504481L0.806292129480815 0.8624239259880274L0.6296239151398265 0.9406169638094516L0.3397492767598845 0.9954164354263132L0 1",E:"M0 0L0 1M0 0L1 0M0 0.5L0.7 0.5M0 1L1 1",F:"M0 0L0 1M0.011363636363636364 0.006802721088435374L1 0.006802721088435374M0.011363636363636364 0.4965986394557823L0.8409090909090909 0.4965986394557823",G:"M0.902666857540557 0.03860785012651126L0.6504261864675637 0L0.3838947267237336 0.015442305268228053L0.21293332876776194 0.07706794377239819L0.07799659974941617 0.1994951236187481L0 0.46380381528937314L0.04159964421546915 0.7502491408002389L0.13176692977834842 0.8535497868383203L0.2709176262273927 0.936767572377719L0.4386472596876406 0.9891638569283179L0.6145513562841309 1L0.7782254421419019 0.9585373611026471L0.9092650433859927 0.8540372997461425L1 0.5556012645283437L0.5583959277303046 0.55491741080559",H:"M0 0L0 1M0 0.4788732394366197L0.989010989010989 0.4788732394366197M1 0L1 1",I:"M0.5 0L0.5 1",J:"M0.9976457238788704 0L1 0.7396412315872798L0.9773931362096968 0.8322033314977973L0.9345115952458736 0.882296255506608L0.8743862896259549 0.9221331222466961L0.8024024079884948 0.9526431718061675L0.6443996712151668 0.9893997797356828L0.5035848940343224 1L0.3127211130319937 0.9877004749449337L0.17201910858386513 0.9539509911894274L0.10357419806379677 0.9212555066079295L0.053656568662899015 0.8816079295154184L0.020759483663648916 0.8360407488986785L0.003376206348523566 0.7855864537444934L0 0.7312775330396476",K:"M0 0L0 1M0.8787878787878788 0.06666666666666667L0 0.6148148148148148M0.3333333333333333 0.45925925925925926L1 0.9777777777777777",L:"M0 0L0 1L1 1",M:"M0 1L0 0L0.5 0.6512L1 0L1 1",N:"M0 1L0 0L1 1L0.9803729146221786 0",O:"M0.4718499217948183 1L0.2896765846490613 0.9606979309189402L0.12315162147934663 0.8411184486080473L0 0.4352399966492615L0.11730398524516283 0.13145645436014852L0.2612197451988078 0.04493357858878059L0.5104071592772554 0L0.7450113425917159 0.05393013710105273L0.882367950645524 0.15242300282020502L1 0.5224527406249126L0.9414597290654386 0.7560662329321755L0.8371289514446183 0.8910800547287298L0.6518259868433511 0.9830452628933628L0.4718499217948183 1",P:"M0 1L0 0.018871774228013626L0.29609603495819875 0L0.5609840637427541 0.011794858892508529L0.7332142696692472 0.04353904702296349L0.8102258645858864 0.0691965055027166L0.9330504315465442 0.14445061754775845L0.9876391714147118 0.22527816445836535L1 0.3434414070631638L0.9510549958116356 0.41772808046663146L0.8746646891596713 0.45879131862541683L0.7528523813396283 0.49171525113425024L0.5766919939969619 0.5153253033973054L0.33725744877712827 0.5284469008187558L0.025622667325582785 0.529905468802775",Q:"M0.4618887943546369 0.9755918167206952L0.28356128136544534 0.9372490397450218L0.12055179272160406 0.8205882753548176L0 0.4246165790405623L0.1148276047430244 0.12824784112887844L0.25570518844754375 0.043836831567190586L0.49963205786237674 0L0.7292835601228574 0.0526138004304122L0.8637404608452104 0.14870263423138746L0.9788892040030622 0.5097006183769648L0.9215847647858059 0.7376120297474734L0.8194564929275405 0.869330409436378L0.6380654214095985 0.9590509139448092L0.4618887943546369 0.9755918167206952M0.5824181120212351 0.6861805006946525L1 1",R:"M0 0.9928375167236815L0 0.02590227442068435L0.3611517274211098 0L0.6146286724700761 0.008660554424468435L0.7675462459194776 0.035269459580494614L0.831839975516866 0.056961676692569484L0.8847592491838954 0.08519560521497332L0.9238557535364527 0.120683646438422L0.9583303225312839 0.21691797435320384L0.955092470586235 0.3022616904894429L0.9198097669001631 0.3640573439322699L0.8564862239866702 0.40639258627024005L0.7691258543593579 0.43335506909190874L0.601775027203482 0.4539166070813109L0.023939064200217658 0.46997623755243123M0.5038084874863982 0.5108023922274467L1 1",S:"M0.8886929689221953 0.15146982162688968L0.7276173683050475 0.013780286031594946L0.34582323121005076 0L0.1318235250900008 0.09920162734298861L0.0444543935052531 0.2811287071349243L0.08064065829108809 0.3709571405906485L0.21603115127470426 0.4485505768228281L0.7525409135992945 0.5111160926769565L0.9330263665417677 0.5850732219351329L1 0.7129938124702524L0.9117772389978691 0.9130572743138187L0.6423187128058188 1L0.29586019579751677 0.9935291584506244L0.10638454191462794 0.9229845198431584L0 0.7570771288048773",T:"M0 0L1 0M0.5148514851485149 0L0.5148514851485149 1",U:"M0 0L0.0023103778751369115 0.5467447428390111L0.01823032542100219 0.6954785891481812L0.05895528135268338 0.8056480226151669L0.13703402031421133 0.8894445726483398L0.23918400876232196 0.9448524533417946L0.3917887458926616 0.9848674531975652L0.584341627875137 1L0.7194816196604602 0.9848501456716763L0.8303268115073934 0.9449411544119768L0.8966613970084885 0.898186315516197L0.9251437568455642 0.867453197565408L0.9687114937020809 0.7890904895145239L0.9890470974808324 0.6852857184065537L1 0.0014769088758762145",V:"M0 0L0.5348837209302325 1L1 0",W:"M0 0L0.23300090661831369 0.9873417721518988L0.49954669084315495 0.30081906180193585L0.7851314596554849 1L1 0.0215934475055845",X:"M0 0L0.9893617021276596 1M1 0L0.010638297872340425 1",Y:"M0 0L0.4860515021459227 0.44712562100780695M1 0.0014194464158977947L0.48927038626609437 0.44996451383960256L0.5075107296137339 1",Z:"M0 0L1 0L0 1L1 1",a:"M0.900 0.517L0.900 1.000M0.900 0.620L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",b:"M0.100 0.275L0.100 1.000M0.100 0.620L0.234 0.551L0.366 0.517L0.566 0.517L0.700 0.551L0.834 0.620L0.900 0.724L0.900 0.793L0.834 0.896L0.700 0.965L0.566 1.000L0.366 1.000L0.234 0.965L0.100 0.896",c:"M0.900 0.620L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",d:"M0.900 0.275L0.900 1.000M0.900 0.620L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",e:"M0.100 0.724L0.900 0.724M0.900 0.655L0.834 0.586L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",f:"M0.900 0.275L0.700 0.275L0.500 0.310L0.400 0.413L0.400 1.000M0.100 0.517L0.800 0.517",g:"M0.900 0.516L0.900 1.068L0.834 1.171L0.766 1.206L0.634 1.240L0.434 1.240L0.300 1.206L0.166 1.137L0.100 1.033M0.900 0.619L0.766 0.550L0.634 0.516L0.434 0.516L0.300 0.550L0.166 0.619L0.100 0.723L0.100 0.792L0.166 0.895L0.300 0.964L0.434 0.999L0.634 0.999L0.766 0.964L0.900 0.895",h:"M0.100 0.275L0.100 1.000M0.100 0.655L0.318 0.551L0.464 0.517L0.682 0.517L0.827 0.551L0.900 0.655L0.900 1.000",i:"M0.466 0.275L0.534 0.275M0.500 0.517L0.500 1.000",j:"M0.634 0.274L0.766 0.274M0.700 0.516L0.700 1.102L0.634 1.206L0.366 1.240L0.166 1.206",k:"M0.100 0.275L0.100 1.000M0.827 0.517L0.100 0.862M0.391 0.724L0.900 1.000",l:"M0.5 0.275L0.5 1.000",m:"M0.100 0.517L0.100 1.000M0.100 0.655L0.209 0.551L0.282 0.517L0.418 0.517L0.491 0.551L0.564 0.655L0.564 1.000M0.564 0.655L0.673 0.551L0.745 0.517L0.882 0.517L0.955 0.551L0.955 1.000",n:"M0.100 0.517L0.100 1.000M0.100 0.655L0.318 0.551L0.464 0.517L0.682 0.517L0.827 0.551L0.900 0.655L0.900 1.000",o:"M0.408 0.517L0.285 0.551L0.162 0.620L0.100 0.724L0.100 0.793L0.162 0.896L0.285 0.965L0.408 1.000L0.592 1.000L0.715 0.965L0.838 0.896L0.900 0.793L0.900 0.724L0.838 0.620L0.715 0.551L0.592 0.517L0.408 0.517",p:"M0.100 0.516L0.100 1.240M0.100 0.619L0.234 0.550L0.366 0.516L0.566 0.516L0.700 0.550L0.834 0.619L0.900 0.723L0.900 0.792L0.834 0.895L0.700 0.964L0.566 0.999L0.366 0.999L0.234 0.964L0.100 0.895",q:"M0.900 0.516L0.900 1.240M0.900 0.619L0.766 0.550L0.634 0.516L0.434 0.516L0.300 0.550L0.166 0.619L0.100 0.723L0.100 0.792L0.166 0.895L0.300 0.964L0.434 0.999L0.634 0.999L0.766 0.964L0.900 0.895",r:"M0.100 0.517L0.100 1.000M0.100 0.724L0.200 0.620L0.400 0.551L0.600 0.517L0.900 0.517",s:"M0.850 0.551L0.700 0.517L0.450 0.517L0.250 0.551L0.100 0.620L0.100 0.689L0.250 0.724L0.500 0.724L0.750 0.793L0.900 0.862L0.900 0.931L0.750 0.965L0.550 1.000L0.300 1.000L0.150 0.965L0.100 0.896",t:"M0.400 0.275L0.400 0.862L0.500 0.965L0.700 1.000L0.900 1.000M0.100 0.517L0.800 0.517",u:"M0.100 0.517L0.100 0.862L0.173 0.965L0.318 1.000L0.536 1.000L0.682 0.965L0.900 0.862M0.900 0.517L0.900 1.000",v:"M0.100 0.517L0.500 1.000M0.900 0.517L0.500 1.000",w:"M0.100 0.517L0.300 1.000M0.500 0.517L0.300 1.000M0.500 0.517L0.700 1.000M0.900 0.517L0.700 1.000",x:"M0.100 0.517L0.900 1.000M0.900 0.517L0.100 1.000",y:"M0.162 0.516L0.530 0.999M0.900 0.516L0.530 0.999L0.408 1.137L0.285 1.206L0.162 1.240L0.100 1.240",z:"M0.900 0.517L0.100 1.000M0.100 0.517L0.900 0.517M0.100 1.000L0.900 1.000",".":"M 0.49 1 L 0.41 1","!":"M0.5 0L0.5 0.6M0.49 0.85L0.51 0.85",",":"M0.55 0.85L0.45 0.95L0.5 1","*":"M0.5 0.15L0.5 0.35M0.5 0.15L0.69 0.22M0.5 0.15L0.62 -0.03M0.5 0.15L0.38 -0.03M0.5 0.15L0.31 0.22","(":"M0.84 0.01L0.80 0.06L0.76 0.12L0.72 0.19L0.68 0.27L0.65 0.35L0.63 0.43L0.62 0.50L0.63 0.57L0.65 0.65L0.68 0.73L0.72 0.81L0.76 0.88L0.80 0.94L0.84 0.99",")":"M0.16 0.01L0.20 0.06L0.24 0.12L0.28 0.19L0.32 0.27L0.35 0.35L0.37 0.43L0.38 0.50L0.37 0.57L0.35 0.65L0.32 0.73L0.28 0.81L0.24 0.88L0.20 0.94L0.16 0.99","-":"M0.2 0.5L0.8 0.5","+":"M0.2 0.5L0.8 0.5M0.5 0.2L0.5 0.8","=":"M0 0.25L1 0.25M0 0.75L1 0.75",_:"M0 1 L1 1","[":"M0.75 0L0.25 0L0.25 1L0.75 1","]":"M0.25 0L0.75 0L0.75 1L0.25 1","<":"M0.75 0L0.25 0.5L0.25 0.5L0.75 1",">":"M0.25 0L0.75 0.5L0.75 0.5L0.25 1","'":"M 0.5 0 L 0.5 0.5",'"':"M 0.25 0 L 0.25 0.5 M 0.75 0 L 0.75 0.5","/":"M0 1L1 0","\\":"M0 0L1 1","#":"M0.38 0.05L0.28 0.95M0.78 0.05L0.68 0.95M0.10 0.38L1.00 0.28M0.05 0.78L0.95 0.68",$:"M0.50 0.02L0.50 0.98M0.80 0.22L0.66 0.12L0.38 0.10L0.22 0.20L0.16 0.34L0.20 0.42L0.32 0.48L0.70 0.54L0.82 0.60L0.86 0.70L0.78 0.84L0.58 0.90L0.32 0.88L0.18 0.82L0.12 0.70","^":"M0.25 0.45L0.5 0.05L0.75 0.45"},lineAlphabet={};for(let letter in svgAlphabet){lineAlphabet[letter]=[];let segs=svgAlphabet[letter].split("M").slice(1).map(seg=>seg.split("L").map(pr4=>pr4.trim().split(" ").map(parseFloat)));for(let seg of segs)for(let i2=0;i2<seg.length-1;i2++)lineAlphabet[letter].push({x1:seg[i2][0],y1:1-seg[i2][1],x2:seg[i2+1][0],y2:1-seg[i2+1][1]})}}});var dist_exports3={};__export(dist_exports3,{CIRCUIT_TO_SVG_VERSION:()=>CIRCUIT_TO_SVG_VERSION,circuitJsonToPcbSvg:()=>circuitJsonToPcbSvg,circuitJsonToSchematicSvg:()=>circuitJsonToSchematicSvg,convertCircuitJsonToAssemblySvg:()=>convertCircuitJsonToAssemblySvg,convertCircuitJsonToPcbSvg:()=>convertCircuitJsonToPcbSvg,convertCircuitJsonToPinoutSvg:()=>convertCircuitJsonToPinoutSvg,convertCircuitJsonToSchematicSimulationSvg:()=>convertCircuitJsonToSchematicSimulationSvg,convertCircuitJsonToSchematicSvg:()=>convertCircuitJsonToSchematicSvg,convertCircuitJsonToSimulationGraphSvg:()=>convertCircuitJsonToSimulationGraphSvg,convertCircuitJsonToSolderPasteMask:()=>convertCircuitJsonToSolderPasteMask,createErrorTextOverlay:()=>createErrorTextOverlay,createSvgObjectsForSchComponentPortHovers:()=>createSvgObjectsForSchComponentPortHovers,getSoftwareUsedString:()=>getSoftwareUsedString,isSimulationExperiment:()=>isSimulationExperiment,isSimulationTransientVoltageGraph:()=>isSimulationTransientVoltageGraph,isSimulationVoltageProbe:()=>isSimulationVoltageProbe});function createSvgObjectsFromPcbTraceError(pcbTraceError,circuitJson,ctx){let{transform:transform5,shouldDrawErrors}=ctx;if(!shouldDrawErrors)return[];let{pcb_port_ids}=pcbTraceError,port1=circuitJson.find(el2=>el2.type==="pcb_port"&&el2.pcb_port_id===pcb_port_ids?.[0]),port2=circuitJson.find(el2=>el2.type==="pcb_port"&&el2.pcb_port_id===pcb_port_ids?.[1]);if(!port1||!port2){let viaId=pcbTraceError.message?.match(/pcb_via\[#?(pcb_via_\d+)\]/)?.[1],via=circuitJson.find(el2=>el2.type==="pcb_via"&&el2.pcb_via_id===viaId);if(via&&via.type==="pcb_via")return createSvgObjectsForViaTraceError(pcbTraceError,via,ctx);if(pcbTraceError.center){let screenCenter=applyToPoint3(transform5,{x:pcbTraceError.center.x,y:pcbTraceError.center.y});return annotateTraceErrorSvgObjects([{name:"rect",type:"element",attributes:{x:(screenCenter.x-5).toString(),y:(screenCenter.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${screenCenter.x} ${screenCenter.y})`},children:[],value:""},{name:"text",type:"element",attributes:{x:screenCenter.x.toString(),y:(screenCenter.y-15).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:pcbTraceError.message||"Pcb Trace Error",name:"",attributes:{},children:[]}],value:""}])}else return[]}let screenPort1=applyToPoint3(transform5,{x:port1.x,y:port1.y}),screenPort2=applyToPoint3(transform5,{x:port2.x,y:port2.y}),errorCenter={x:(screenPort1.x+screenPort2.x)/2,y:(screenPort1.y+screenPort2.y)/2};if(isNaN(screenPort1.x)||isNaN(screenPort1.y)||isNaN(screenPort2.x)||isNaN(screenPort2.y)||isNaN(errorCenter.x)||isNaN(errorCenter.y))return[];let svgObjects=[{name:"line",type:"element",attributes:{x1:screenPort1.x.toString(),y1:screenPort1.y.toString(),x2:errorCenter.x.toString(),y2:errorCenter.y.toString(),stroke:"red","stroke-width":"1.5","stroke-dasharray":"2,2"},children:[],value:""},{name:"line",type:"element",attributes:{x1:errorCenter.x.toString(),y1:errorCenter.y.toString(),x2:screenPort2.x.toString(),y2:screenPort2.y.toString(),stroke:"red","stroke-width":"1.5","stroke-dasharray":"2,2"},children:[],value:""},{name:"rect",type:"element",attributes:{x:(errorCenter.x-5).toString(),y:(errorCenter.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${errorCenter.x} ${errorCenter.y})`},children:[],value:""},{name:"text",type:"element",attributes:{x:errorCenter.x.toString(),y:(errorCenter.y-15).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:pcbTraceError.message||"Pcb Trace Error",name:"",attributes:{},children:[]}],value:""}];return annotateTraceErrorSvgObjects(svgObjects)}function createSvgObjectsForViaTraceError(pcbTraceError,via,ctx){let{transform:transform5}=ctx;if(pcbTraceError.center&&via){let screenCenter=applyToPoint3(transform5,{x:pcbTraceError.center.x,y:pcbTraceError.center.y}),screenVia=applyToPoint3(transform5,{x:via.x,y:via.y}),dx2=screenVia.x-screenCenter.x,dy2=screenVia.y-screenCenter.y,dist=Math.sqrt(dx2*dx2+dy2*dy2),angle=Math.atan2(dy2,dx2)*180/Math.PI,boxWidth=dist+10*2,boxHeight=20,midX=(screenCenter.x+screenVia.x)/2,midY=(screenCenter.y+screenVia.y)/2;return annotateTraceErrorSvgObjects([{name:"rect",type:"element",attributes:{x:(midX-boxWidth/2).toString(),y:(midY-boxHeight/2).toString(),width:boxWidth.toString(),height:boxHeight.toString(),fill:"none",stroke:"red","stroke-width":"1","stroke-dasharray":"3,2",transform:`rotate(${angle} ${midX} ${midY})`},children:[],value:""},{name:"rect",type:"element",attributes:{x:(midX-5).toString(),y:(midY-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${midX} ${midY})`},children:[],value:""},{name:"text",type:"element",attributes:{x:midX.toString(),y:(midY-boxHeight/2-5).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:pcbTraceError.message||"Pcb Trace Error",name:"",attributes:{},children:[]}],value:""}])}return[]}function annotateTraceErrorSvgObjects(objects){return objects.map(object=>({...object,attributes:{...object.attributes??{},"data-type":object.attributes?.["data-type"]??"pcb_trace_error","data-pcb-layer":object.attributes?.["data-pcb-layer"]??"overlay"},children:(object.children??[]).map(child=>child?.type==="element"?{...child,attributes:{...child.attributes??{},"data-type":child.attributes?.["data-type"]??"pcb_trace_error","data-pcb-layer":child.attributes?.["data-pcb-layer"]??"overlay"}}:child)}))}function annotateFootprintErrorSvgObjects(objects){return objects.map(object=>({...object,attributes:{...object.attributes??{},"data-type":object.attributes?.["data-type"]??"pcb_footprint_overlap_error","data-pcb-layer":object.attributes?.["data-pcb-layer"]??"overlay"},children:(object.children??[]).map(child=>child?.type==="element"?{...child,attributes:{...child.attributes??{},"data-type":child.attributes?.["data-type"]??"pcb_footprint_overlap_error","data-pcb-layer":child.attributes?.["data-pcb-layer"]??"overlay"}}:child)}))}function createSvgObjectsFromPcbFootprintOverlapError(error,circuitJson,ctx){let{transform:transform5,shouldDrawErrors}=ctx;if(!shouldDrawErrors)return[];let svgObjects=[],referencedElements=[],padPortIds=[];if(error.pcb_smtpad_ids)for(let padId of error.pcb_smtpad_ids){let pad2=circuitJson.find(el2=>el2.type==="pcb_smtpad"&&el2.pcb_smtpad_id===padId);pad2&&(referencedElements.push({x:pad2.x,y:pad2.y,type:"pcb_smtpad",id:padId,pcb_port_id:pad2.pcb_port_id}),pad2.pcb_port_id&&padPortIds.push(pad2.pcb_port_id))}let allPadsSamePort=padPortIds.length>1&&padPortIds.every(id=>id===padPortIds[0]),filteredReferencedElements=referencedElements;if(allPadsSamePort&&(filteredReferencedElements=referencedElements.filter(e4=>e4.type!=="pcb_smtpad")),error.pcb_plated_hole_ids)for(let holeId of error.pcb_plated_hole_ids){let hole=circuitJson.find(el2=>el2.type==="pcb_plated_hole"&&el2.pcb_plated_hole_id===holeId);hole&&filteredReferencedElements.push({x:hole.x,y:hole.y,type:"pcb_plated_hole",id:holeId})}if(error.pcb_hole_ids)for(let holeId of error.pcb_hole_ids){let hole=circuitJson.find(el2=>el2.type==="pcb_hole"&&el2.pcb_hole_id===holeId);hole&&filteredReferencedElements.push({x:hole.x,y:hole.y,type:"pcb_hole",id:holeId})}if(filteredReferencedElements.length>0){let centerX=filteredReferencedElements.reduce((sum,el2)=>sum+el2.x,0)/filteredReferencedElements.length,centerY=filteredReferencedElements.reduce((sum,el2)=>sum+el2.y,0)/filteredReferencedElements.length,screenCenter=applyToPoint3(transform5,{x:centerX,y:centerY});svgObjects.push({name:"rect",type:"element",attributes:{x:(screenCenter.x-5).toString(),y:(screenCenter.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${screenCenter.x} ${screenCenter.y})`},children:[],value:""}),svgObjects.push({name:"text",type:"element",attributes:{x:screenCenter.x.toString(),y:(screenCenter.y-15).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:error.message||"PCB Footprint Overlap Error",name:"",attributes:{},children:[]}],value:""});for(let element of filteredReferencedElements){let screenPos=applyToPoint3(transform5,{x:element.x,y:element.y});svgObjects.push({name:"rect",type:"element",attributes:{x:(screenPos.x-5).toString(),y:(screenPos.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${screenPos.x} ${screenPos.y})`},children:[],value:""}),filteredReferencedElements.length>1&&svgObjects.push({name:"line",type:"element",attributes:{x1:screenCenter.x.toString(),y1:screenCenter.y.toString(),x2:screenPos.x.toString(),y2:screenPos.y.toString(),stroke:"red","stroke-width":"1.5","stroke-dasharray":"2,2"},children:[],value:""})}}return annotateFootprintErrorSvgObjects(svgObjects)}function createSvgObjectsFromPcbFabricationNotePath(fabNotePath,ctx){let{transform:transform5,layer:layerFilter}=ctx;if(!fabNotePath.route||!Array.isArray(fabNotePath.route))return[];let firstPoint=fabNotePath.route[0],lastPoint=fabNotePath.route[fabNotePath.route.length-1],isClosed=firstPoint.x===lastPoint.x&&firstPoint.y===lastPoint.y,path=fabNotePath.route.slice(0,isClosed?-1:void 0).map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" ")+(isClosed?" Z":"");return[{name:"path",type:"element",attributes:{class:"pcb-fabrication-note-path",stroke:fabNotePath.color||"rgba(255,255,255,0.5)",fill:"none",d:path,"stroke-width":(fabNotePath.stroke_width*Math.abs(transform5.a)).toString(),"data-pcb-component-id":fabNotePath.pcb_component_id,"data-pcb-fabrication-note-path-id":fabNotePath.pcb_fabrication_note_path_id,"data-type":"pcb_fabrication_note_path","data-pcb-layer":"overlay"},value:"",children:[]}]}function createSvgObjectsFromPcbFabricationNoteText(pcbFabNoteText,ctx){let{transform:transform5,layer:layerFilter}=ctx,{anchor_position,anchor_alignment,text,font_size=1,layer="top",color}=pcbFabNoteText;if(layerFilter&&layer!==layerFilter)return[];if(!anchor_position||typeof anchor_position.x!="number"||typeof anchor_position.y!="number")return console.error("Invalid anchor_position:",anchor_position),[];let[transformedX,transformedY]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),transformedFontSize=font_size*Math.abs(transform5.a),textTransform=compose3(translate3(transformedX,transformedY),rotate3(Math.PI/180));return[{name:"text",type:"element",attributes:{x:"0",y:"0","font-family":"Arial, sans-serif","font-size":transformedFontSize.toString(),"text-anchor":"middle","dominant-baseline":"central",transform:toString(textTransform),class:"pcb-fabrication-note-text",fill:color||"rgba(255,255,255,0.5)","data-type":"pcb_fabrication_note_text","data-pcb-layer":"overlay"},children:[{type:"text",value:text,name:"",attributes:{},children:[]}],value:""}]}function createSvgObjectsFromPcbFabricationNoteRect(fabricationNoteRect,ctx){let{transform:transform5,layer:layerFilter}=ctx,{center:center2,width,height,stroke_width,is_filled,has_stroke,is_stroke_dashed,color,layer="top",pcb_component_id,pcb_fabrication_note_rect_id,corner_radius}=fabricationNoteRect;if(layerFilter&&layer!==layerFilter)return[];if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid pcb_fabrication_note_rect data",{center:center2,width,height}),[];let halfWidth=width/2,halfHeight=height/2,[topLeftX,topLeftY]=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]),[bottomRightX,bottomRightY]=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),rectX=Math.min(topLeftX,bottomRightX),rectY=Math.min(topLeftY,bottomRightY),rectWidth=Math.abs(bottomRightX-topLeftX),rectHeight=Math.abs(bottomRightY-topLeftY),transformedStrokeWidth=(typeof stroke_width=="number"?stroke_width:0)*Math.abs(transform5.a),overlayStrokeColor=color??DEFAULT_OVERLAY_STROKE_COLOR,baseCornerRadius=typeof corner_radius=="number"&&corner_radius>0?corner_radius:0,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),attributes2={x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),class:"pcb-fabrication-note-rect","data-type":"pcb_fabrication_note_rect","data-pcb-fabrication-note-rect-id":pcb_fabrication_note_rect_id,"data-pcb-layer":"overlay"};if(pcb_component_id!==void 0&&(attributes2["data-pcb-component-id"]=pcb_component_id),transformedCornerRadiusX>0&&(attributes2.rx=transformedCornerRadiusX.toString()),transformedCornerRadiusY>0&&(attributes2.ry=transformedCornerRadiusY.toString()),is_filled?attributes2.fill=color??DEFAULT_OVERLAY_FILL_COLOR:attributes2.fill="none",has_stroke??transformedStrokeWidth>0){if(attributes2.stroke=overlayStrokeColor,attributes2["stroke-width"]=transformedStrokeWidth.toString(),is_stroke_dashed){let dash=.2*Math.abs(transform5.a),gap=.1*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dash} ${gap}`}}else attributes2.stroke="none";return[{name:"rect",type:"element",value:"",attributes:attributes2,children:[]}]}function normalize(vector2){let length3=Math.hypot(vector2.x,vector2.y)||1;return{x:vector2.x/length3,y:vector2.y/length3}}function toPath(points){return points.map((point6,index)=>index===0?`M ${point6.x} ${point6.y}`:`L ${point6.x} ${point6.y}`).join(" ")}function createSvgObjectsFromPcbFabricationNoteDimension(dimension,ctx){let{transform:transform5,layer:layerFilter}=ctx,{from,to:to3,text,font_size=1,color,arrow_size,layer,pcb_component_id,pcb_fabrication_note_dimension_id,offset_distance,offset_direction,text_ccw_rotation}=dimension;if(layerFilter&&layer&&layer!==layerFilter)return[];if(!from||!to3||typeof from!="object"||typeof to3!="object")return console.error("Invalid pcb_fabrication_note_dimension endpoints",{from,to:to3}),[];if(typeof from.x!="number"||typeof from.y!="number"||typeof to3.x!="number"||typeof to3.y!="number")return console.error("Invalid pcb_fabrication_note_dimension point values",{from,to:to3}),[];let numericArrowSize=typeof arrow_size=="number"?arrow_size:void 0;if(numericArrowSize===void 0||!Number.isFinite(numericArrowSize)||numericArrowSize<=0)return console.error("Invalid pcb_fabrication_note_dimension arrow_size",arrow_size),[];let arrowSize=numericArrowSize,direction2=normalize({x:to3.x-from.x,y:to3.y-from.y});if(Number.isNaN(direction2.x)||Number.isNaN(direction2.y))return[];let perpendicular={x:-direction2.y,y:direction2.x},hasOffsetDirection=offset_direction&&typeof offset_direction.x=="number"&&typeof offset_direction.y=="number",normalizedOffsetDirection=hasOffsetDirection?normalize({x:offset_direction.x,y:offset_direction.y}):{x:0,y:0},offsetMagnitude=typeof offset_distance=="number"?offset_distance:0,offsetVector={x:normalizedOffsetDirection.x*offsetMagnitude,y:normalizedOffsetDirection.y*offsetMagnitude},applyOffset=point6=>({x:point6.x+offsetVector.x,y:point6.y+offsetVector.y}),fromOffset=applyOffset(from),toOffset=applyOffset(to3),arrowHalfWidth=arrowSize/2,fromBase={x:fromOffset.x+direction2.x*arrowSize,y:fromOffset.y+direction2.y*arrowSize},toBase={x:toOffset.x-direction2.x*arrowSize,y:toOffset.y-direction2.y*arrowSize},fromTriangle=[toScreen(fromOffset),toScreen({x:fromBase.x+perpendicular.x*arrowHalfWidth,y:fromBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:fromBase.x-perpendicular.x*arrowHalfWidth,y:fromBase.y-perpendicular.y*arrowHalfWidth})],toTriangle=[toScreen(toOffset),toScreen({x:toBase.x+perpendicular.x*arrowHalfWidth,y:toBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:toBase.x-perpendicular.x*arrowHalfWidth,y:toBase.y-perpendicular.y*arrowHalfWidth})],[lineStartX,lineStartY]=applyToPoint3(transform5,[fromBase.x,fromBase.y]),[lineEndX,lineEndY]=applyToPoint3(transform5,[toBase.x,toBase.y]),strokeWidth=arrowSize/5*Math.abs(transform5.a),lineColor=color||"rgba(255,255,255,0.5)",extensionDirection=hasOffsetDirection&&(Math.abs(normalizedOffsetDirection.x)>Number.EPSILON||Math.abs(normalizedOffsetDirection.y)>Number.EPSILON)?normalizedOffsetDirection:perpendicular,extensionLength=offsetMagnitude+arrowSize,createExtensionLine=anchor=>{let endPoint={x:anchor.x+extensionDirection.x*extensionLength,y:anchor.y+extensionDirection.y*extensionLength},[startX,startY]=applyToPoint3(transform5,[anchor.x,anchor.y]),[endX,endY]=applyToPoint3(transform5,[endPoint.x,endPoint.y]);return{name:"path",type:"element",value:"",attributes:{d:`M ${startX} ${startY} L ${endX} ${endY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-fabrication-note-dimension-extension"},children:[]}},extensionSegments=[createExtensionLine(from),createExtensionLine(to3)],midPoint={x:(from.x+to3.x)/2+offsetVector.x,y:(from.y+to3.y)/2+offsetVector.y},[screenFromX,screenFromY]=applyToPoint3(transform5,[fromOffset.x,fromOffset.y]),[screenToX,screenToY]=applyToPoint3(transform5,[toOffset.x,toOffset.y]),screenDirection=normalize({x:screenToX-screenFromX,y:screenToY-screenFromY}),textAngle=Math.atan2(screenDirection.y,screenDirection.x)*180/Math.PI;(textAngle>90||textAngle<-90)&&(textAngle+=180);let finalTextAngle=typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)?textAngle-text_ccw_rotation:textAngle,additionalOffset=0;if(text&&typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)){let textWidth=text.length*font_size*CHARACTER_WIDTH_MULTIPLIER,textHeight=font_size,rotationRad=text_ccw_rotation*Math.PI/180,sinRot=Math.abs(Math.sin(rotationRad)),cosRot=Math.abs(Math.cos(rotationRad)),halfWidth=textWidth/2,halfHeight=textHeight/2;additionalOffset=halfWidth*sinRot+halfHeight*cosRot+font_size*TEXT_INTERSECTION_PADDING_MULTIPLIER}let textOffset=arrowSize*TEXT_OFFSET_MULTIPLIER+additionalOffset,textPoint={x:midPoint.x+perpendicular.x*textOffset,y:midPoint.y+perpendicular.y*textOffset},[textX,textY]=applyToPoint3(transform5,[textPoint.x,textPoint.y]),transformedFontSize=font_size*Math.abs(transform5.a),children=[...extensionSegments,{name:"path",type:"element",value:"",attributes:{d:`M ${lineStartX} ${lineStartY} L ${lineEndX} ${lineEndY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-fabrication-note-dimension-line"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath(fromTriangle)} Z`,fill:lineColor,class:"pcb-fabrication-note-dimension-arrow"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath(toTriangle)} Z`,fill:lineColor,class:"pcb-fabrication-note-dimension-arrow"},children:[]}];text&&children.push({name:"text",type:"element",value:"",attributes:{x:textX.toString(),y:textY.toString(),fill:lineColor,"font-size":transformedFontSize.toString(),"font-family":"Arial, sans-serif","text-anchor":"middle","dominant-baseline":"central",class:"pcb-fabrication-note-dimension-text",transform:`rotate(${finalTextAngle} ${textX} ${textY})`},children:[{type:"text",name:"",value:text,attributes:{},children:[]}]});let attributes2={class:"pcb-fabrication-note-dimension","data-type":"pcb_fabrication_note_dimension","data-pcb-fabrication-note-dimension-id":pcb_fabrication_note_dimension_id,"data-pcb-layer":layer??"overlay"};return pcb_component_id!==void 0&&(attributes2["data-pcb-component-id"]=pcb_component_id),[{name:"g",type:"element",value:"",attributes:attributes2,children}];function toScreen(point6){let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return{x:x5,y:y5}}}function normalize2(vector2){let length3=Math.hypot(vector2.x,vector2.y)||1;return{x:vector2.x/length3,y:vector2.y/length3}}function toPath2(points){return points.map((point6,index)=>index===0?`M ${point6.x} ${point6.y}`:`L ${point6.x} ${point6.y}`).join(" ")}function createSvgObjectsFromPcbNoteDimension(dimension,ctx){let{transform:transform5}=ctx,{from,to:to3,text,font_size=1,color,arrow_size,offset_distance,offset_direction,text_ccw_rotation}=dimension;if(!from||!to3)return console.error("Invalid pcb_note_dimension endpoints",{from,to:to3}),[];if(!Number.isFinite(arrow_size)||arrow_size<=0)return console.error("Invalid pcb_note_dimension arrow_size",arrow_size),[];let direction2=normalize2({x:to3.x-from.x,y:to3.y-from.y});if(Number.isNaN(direction2.x)||Number.isNaN(direction2.y))return[];let perpendicular={x:-direction2.y,y:direction2.x},hasOffsetDirection=offset_direction&&typeof offset_direction.x=="number"&&typeof offset_direction.y=="number",normalizedOffsetDirection=hasOffsetDirection?normalize2({x:offset_direction.x,y:offset_direction.y}):{x:0,y:0},offsetMagnitude=typeof offset_distance=="number"?offset_distance:0,offsetVector={x:normalizedOffsetDirection.x*offsetMagnitude,y:normalizedOffsetDirection.y*offsetMagnitude},applyOffset=point6=>({x:point6.x+offsetVector.x,y:point6.y+offsetVector.y}),fromOffset=applyOffset(from),toOffset=applyOffset(to3),arrowHalfWidth=arrow_size/2,fromBase={x:fromOffset.x+direction2.x*arrow_size,y:fromOffset.y+direction2.y*arrow_size},toBase={x:toOffset.x-direction2.x*arrow_size,y:toOffset.y-direction2.y*arrow_size},fromTriangle=[toScreen(fromOffset),toScreen({x:fromBase.x+perpendicular.x*arrowHalfWidth,y:fromBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:fromBase.x-perpendicular.x*arrowHalfWidth,y:fromBase.y-perpendicular.y*arrowHalfWidth})],toTriangle=[toScreen(toOffset),toScreen({x:toBase.x+perpendicular.x*arrowHalfWidth,y:toBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:toBase.x-perpendicular.x*arrowHalfWidth,y:toBase.y-perpendicular.y*arrowHalfWidth})],[lineStartX,lineStartY]=applyToPoint3(transform5,[fromBase.x,fromBase.y]),[lineEndX,lineEndY]=applyToPoint3(transform5,[toBase.x,toBase.y]),strokeWidth=arrow_size/5*Math.abs(transform5.a),lineColor=color||colorMap.board.user_2,extensionDirection=hasOffsetDirection&&(Math.abs(normalizedOffsetDirection.x)>Number.EPSILON||Math.abs(normalizedOffsetDirection.y)>Number.EPSILON)?normalizedOffsetDirection:perpendicular,extensionLength=offsetMagnitude+arrow_size,createExtensionLine=anchor=>{let endPoint={x:anchor.x+extensionDirection.x*extensionLength,y:anchor.y+extensionDirection.y*extensionLength},[startX,startY]=applyToPoint3(transform5,[anchor.x,anchor.y]),[endX,endY]=applyToPoint3(transform5,[endPoint.x,endPoint.y]);return{name:"path",type:"element",value:"",attributes:{d:`M ${startX} ${startY} L ${endX} ${endY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-note-dimension-extension"},children:[]}},extensionSegments=[createExtensionLine(from),createExtensionLine(to3)],midPoint={x:(from.x+to3.x)/2+offsetVector.x,y:(from.y+to3.y)/2+offsetVector.y},[screenFromX,screenFromY]=applyToPoint3(transform5,[fromOffset.x,fromOffset.y]),[screenToX,screenToY]=applyToPoint3(transform5,[toOffset.x,toOffset.y]),screenDirection=normalize2({x:screenToX-screenFromX,y:screenToY-screenFromY}),textAngle=Math.atan2(screenDirection.y,screenDirection.x)*180/Math.PI;(textAngle>90||textAngle<-90)&&(textAngle+=180);let finalTextAngle=typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)?textAngle-text_ccw_rotation:textAngle,additionalOffset=0;if(text&&typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)){let textWidth=text.length*font_size*.6,textHeight=font_size,rotationRad=text_ccw_rotation*Math.PI/180,sinRot=Math.abs(Math.sin(rotationRad)),cosRot=Math.abs(Math.cos(rotationRad)),halfWidth=textWidth/2,halfHeight=textHeight/2;additionalOffset=halfWidth*sinRot+halfHeight*cosRot+font_size*.3}let textOffset=arrow_size*1.5+additionalOffset,textPoint={x:midPoint.x+perpendicular.x*textOffset,y:midPoint.y+perpendicular.y*textOffset},[textX,textY]=applyToPoint3(transform5,[textPoint.x,textPoint.y]),transformedFontSize=font_size*Math.abs(transform5.a),children=[...extensionSegments,{name:"path",type:"element",value:"",attributes:{d:`M ${lineStartX} ${lineStartY} L ${lineEndX} ${lineEndY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-note-dimension-line"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath2(fromTriangle)} Z`,fill:lineColor,class:"pcb-note-dimension-arrow"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath2(toTriangle)} Z`,fill:lineColor,class:"pcb-note-dimension-arrow"},children:[]}];return text&&children.push({name:"text",type:"element",value:"",attributes:{x:textX.toString(),y:textY.toString(),fill:lineColor,"font-size":transformedFontSize.toString(),"font-family":"Arial, sans-serif","text-anchor":"middle","dominant-baseline":"central",class:"pcb-note-dimension-text",transform:`rotate(${finalTextAngle} ${textX} ${textY})`},children:[{type:"text",name:"",value:text,attributes:{},children:[]}]}),[{name:"g",type:"element",value:"",attributes:{class:"pcb-note-dimension","data-type":"pcb_note_dimension","data-pcb-note-dimension-id":dimension.pcb_note_dimension_id,"data-pcb-layer":"overlay"},children}];function toScreen(point6){let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return{x:x5,y:y5}}}function createSvgObjectsFromPcbNoteText(note,ctx){let{transform:transform5}=ctx,{anchor_position,text,font_size=1,anchor_alignment="center",color}=note;if(!anchor_position||typeof anchor_position.x!="number"||typeof anchor_position.y!="number")return console.error("Invalid pcb_note_text anchor_position",anchor_position),[];if(typeof text!="string"||text.length===0)return console.error("Invalid pcb_note_text text",text),[];let[x5,y5]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),transformedFontSize=font_size*Math.abs(transform5.a),textAnchor="middle",dominantBaseline="central";switch(anchor_alignment){case"top_left":textAnchor="start",dominantBaseline="text-before-edge";break;case"top_right":textAnchor="end",dominantBaseline="text-before-edge";break;case"bottom_left":textAnchor="start",dominantBaseline="text-after-edge";break;case"bottom_right":textAnchor="end",dominantBaseline="text-after-edge";break;default:textAnchor="middle",dominantBaseline="central";break}return[{name:"text",type:"element",value:"",attributes:{x:x5.toString(),y:y5.toString(),fill:color??DEFAULT_OVERLAY_COLOR,"font-family":"Arial, sans-serif","font-size":transformedFontSize.toString(),"text-anchor":textAnchor,"dominant-baseline":dominantBaseline,class:"pcb-note-text","data-type":"pcb_note_text","data-pcb-note-text-id":note.pcb_note_text_id,"data-pcb-layer":"overlay"},children:[{type:"text",name:"",value:text,attributes:{},children:[]}]}]}function createSvgObjectsFromPcbNoteRect(noteRect,ctx){let{transform:transform5}=ctx,{center:center2,width,height,stroke_width,is_filled,has_stroke,is_stroke_dashed,color,corner_radius}=noteRect;if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid pcb_note_rect data",{center:center2,width,height}),[];let halfWidth=width/2,halfHeight=height/2,[topLeftX,topLeftY]=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]),[bottomRightX,bottomRightY]=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),rectX=Math.min(topLeftX,bottomRightX),rectY=Math.min(topLeftY,bottomRightY),rectWidth=Math.abs(bottomRightX-topLeftX),rectHeight=Math.abs(bottomRightY-topLeftY),transformedStrokeWidth=(typeof stroke_width=="number"?stroke_width:0)*Math.abs(transform5.a),baseCornerRadius=typeof corner_radius=="number"&&corner_radius>0?corner_radius:0,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),overlayColor=color??DEFAULT_OVERLAY_COLOR2,attributes2={x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),class:"pcb-note-rect","data-type":"pcb_note_rect","data-pcb-note-rect-id":noteRect.pcb_note_rect_id,"data-pcb-layer":"overlay"};if(transformedCornerRadiusX>0&&(attributes2.rx=transformedCornerRadiusX.toString()),transformedCornerRadiusY>0&&(attributes2.ry=transformedCornerRadiusY.toString()),is_filled?attributes2.fill=color??DEFAULT_FILL_COLOR:attributes2.fill="none",has_stroke??transformedStrokeWidth>0){if(attributes2.stroke=overlayColor,attributes2["stroke-width"]=transformedStrokeWidth.toString(),is_stroke_dashed){let dash=.2*Math.abs(transform5.a),gap=.1*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dash} ${gap}`}}else attributes2.stroke="none";return[{name:"rect",type:"element",value:"",attributes:attributes2,children:[]}]}function createSvgObjectsFromPcbNotePath(notePath,ctx){let{transform:transform5}=ctx;if(!Array.isArray(notePath.route)||notePath.route.length===0)return console.error("Invalid pcb_note_path route",notePath.route),[];for(let point6 of notePath.route)if(typeof point6.x!="number"||typeof point6.y!="number")return console.error("Invalid point in pcb_note_path",point6),[];let pathD=notePath.route.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" "),strokeWidth=notePath.stroke_width*Math.abs(transform5.a);return[{name:"path",type:"element",value:"",attributes:{d:pathD,stroke:notePath.color??DEFAULT_OVERLAY_COLOR3,fill:"none","stroke-width":strokeWidth.toString(),class:"pcb-note-path","data-type":"pcb_note_path","data-pcb-note-path-id":notePath.pcb_note_path_id,"data-pcb-layer":"overlay"},children:[]}]}function createSvgObjectsFromPcbNoteLine(noteLine,ctx){let{transform:transform5}=ctx,{x1:x12,y1:y12,x2:x22,y2:y22,stroke_width,color,is_dashed}=noteLine;if(typeof x12!="number"||typeof y12!="number"||typeof x22!="number"||typeof y22!="number")return console.error("Invalid pcb_note_line coordinates",{x1:x12,y1:y12,x2:x22,y2:y22}),[];let[startX,startY]=applyToPoint3(transform5,[x12,y12]),[endX,endY]=applyToPoint3(transform5,[x22,y22]),transformedStrokeWidth=(typeof stroke_width=="number"?stroke_width:0)*Math.abs(transform5.a),attributes2={x1:startX.toString(),y1:startY.toString(),x2:endX.toString(),y2:endY.toString(),stroke:color??DEFAULT_OVERLAY_COLOR4,"stroke-width":transformedStrokeWidth.toString(),"stroke-linecap":"round",class:"pcb-note-line","data-type":"pcb_note_line","data-pcb-note-line-id":noteLine.pcb_note_line_id,"data-pcb-layer":"overlay"};if(is_dashed){let dash=.2*Math.abs(transform5.a),gap=.1*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dash} ${gap}`}return[{name:"line",type:"element",value:"",attributes:attributes2,children:[]}]}function createSvgObjectsFromPcbPlatedHole(hole,ctx){let{transform:transform5,colorMap:colorMap2,showSolderMask}=ctx,[x5,y5]=applyToPoint3(transform5,[hole.x,hole.y]),layer=Array.isArray(hole.layers)&&hole.layers[0]||hole.layer||"top",maskLayer=layer,isCoveredWithSolderMask=!!hole.is_covered_with_solder_mask,soldermaskMargin=(hole.soldermask_margin??0)*Math.abs(transform5.a),shouldShowSolderMask=showSolderMask&&isCoveredWithSolderMask&&soldermaskMargin!==0,solderMaskColor=colorMap2.soldermaskWithCopperUnderneath.top;if(hole.shape==="pill"){let scaledOuterWidth=hole.outer_width*Math.abs(transform5.a),scaledOuterHeight=hole.outer_height*Math.abs(transform5.a),scaledHoleWidth=hole.hole_width*Math.abs(transform5.a),scaledHoleHeight=hole.hole_height*Math.abs(transform5.a),rotation4=hole.ccw_rotation||0,outerTransform=rotation4?`translate(${x5} ${y5}) rotate(${-rotation4})`:`translate(${x5} ${y5})`,innerTransform=rotation4?`translate(${x5} ${y5}) rotate(${-rotation4})`:`translate(${x5} ${y5})`,createPillPath=(width,height)=>{if(width>height){let radius=height/2,straightLength=width-2*radius;return`M${-width/2+radius},${-radius} h${straightLength} a${radius},${radius} 0 0 1 0,${height} h${-straightLength} a${radius},${radius} 0 0 1 0,${-height} z`}else if(height>width){let radius=width/2,straightLength=height-2*radius;return`M${radius},${-height/2+radius} v${straightLength} a${radius},${radius} 0 0 1 ${-width},0 v${-straightLength} a${radius},${radius} 0 0 1 ${width},0 z`}else{let radius=width/2;return`M${-radius},0 a${radius},${radius} 0 0 1 ${width},0 a${radius},${radius} 0 0 1 ${-width},0 z`}},children=[{name:"path",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,d:createPillPath(scaledOuterWidth,scaledOuterHeight),transform:outerTransform,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"path",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,d:createPillPath(scaledHoleWidth,scaledHoleHeight),transform:innerTransform,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledOuterWidth+2*soldermaskMargin,maskHeight=scaledOuterHeight+2*soldermaskMargin;soldermaskMargin<0?children=[{name:"path",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,d:createPillPath(scaledOuterWidth,scaledOuterHeight),transform:outerTransform,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"path",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,d:createPillPath(maskWidth,maskHeight),transform:outerTransform,"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"path",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,d:createPillPath(maskWidth,maskHeight),transform:outerTransform,"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="oval"){let scaledOuterWidth=hole.outer_width*Math.abs(transform5.a),scaledOuterHeight=hole.outer_height*Math.abs(transform5.a),scaledHoleWidth=hole.hole_width*Math.abs(transform5.a),scaledHoleHeight=hole.hole_height*Math.abs(transform5.a),rotation4=hole.ccw_rotation||0,transformStr=rotation4?`translate(${x5} ${y5}) rotate(${-rotation4})`:`translate(${x5} ${y5})`,children=[{name:"ellipse",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,cx:"0",cy:"0",rx:(scaledOuterWidth/2).toString(),ry:(scaledOuterHeight/2).toString(),transform:transformStr,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"ellipse",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:"0",cy:"0",rx:(scaledHoleWidth/2).toString(),ry:(scaledHoleHeight/2).toString(),transform:transformStr,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="circle"){let scaledOuterWidth=hole.outer_diameter*Math.abs(transform5.a),scaledOuterHeight=hole.outer_diameter*Math.abs(transform5.a),scaledHoleWidth=hole.hole_diameter*Math.abs(transform5.a),scaledHoleHeight=hole.hole_diameter*Math.abs(transform5.a),outerRadius=Math.min(scaledOuterWidth,scaledOuterHeight)/2,innerRadius=Math.min(scaledHoleWidth,scaledHoleHeight)/2,children=[{name:"circle",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,cx:x5.toString(),cy:y5.toString(),r:outerRadius.toString(),"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:x5.toString(),cy:y5.toString(),r:innerRadius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskRadius=outerRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"circle",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,cx:x5.toString(),cy:y5.toString(),r:outerRadius.toString(),"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"circle",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="circular_hole_with_rect_pad"){let h4=hole,scaledHoleDiameter=hole.hole_diameter*Math.abs(transform5.a),scaledRectPadWidth=hole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=hole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(hole.rect_border_radius??0)*Math.abs(transform5.a),holeRadius=scaledHoleDiameter/2,[holeCx,holeCy]=applyToPoint3(transform5,[h4.x+(h4.hole_offset_x??0),h4.y+(h4.hole_offset_y??0)]),children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:holeCx.toString(),cy:holeCy.toString(),r:holeRadius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledRectPadWidth+2*soldermaskMargin,maskHeight=scaledRectPadHeight+2*soldermaskMargin,maskBorderRadius=scaledRectBorderRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"rect",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...scaledRectBorderRadius?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="pill_hole_with_rect_pad"){let pillHole=hole,scaledRectPadWidth=pillHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=pillHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(pillHole.rect_border_radius??0)*Math.abs(transform5.a),scaledHoleHeight=pillHole.hole_height*Math.abs(transform5.a),scaledHoleWidth=pillHole.hole_width*Math.abs(transform5.a),pillHoleWithOffsets=pillHole,holeOffsetX=pillHoleWithOffsets.hole_offset_x??0,holeOffsetY=pillHoleWithOffsets.hole_offset_y??0,[holeCenterX,holeCenterY]=applyToPoint3(transform5,[pillHole.x+holeOffsetX,pillHole.y+holeOffsetY]),holeRadius=Math.min(scaledHoleHeight,scaledHoleWidth)/2,children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,x:(holeCenterX-scaledHoleWidth/2).toString(),y:(holeCenterY-scaledHoleHeight/2).toString(),width:scaledHoleWidth.toString(),height:scaledHoleHeight.toString(),rx:holeRadius.toString(),ry:holeRadius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledRectPadWidth+2*soldermaskMargin,maskHeight=scaledRectPadHeight+2*soldermaskMargin,maskBorderRadius=scaledRectBorderRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"rect",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...scaledRectBorderRadius?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="rotated_pill_hole_with_rect_pad"){let rotatedHole=hole,scaledRectPadWidth=rotatedHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=rotatedHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(rotatedHole.rect_border_radius??0)*Math.abs(transform5.a),scaledHoleHeight=rotatedHole.hole_height*Math.abs(transform5.a),scaledHoleWidth=rotatedHole.hole_width*Math.abs(transform5.a),rotatedHoleWithOffsets=rotatedHole,holeOffsetX=rotatedHoleWithOffsets.hole_offset_x??0,holeOffsetY=rotatedHoleWithOffsets.hole_offset_y??0,[holeCenterX,holeCenterY]=applyToPoint3(transform5,[rotatedHole.x+holeOffsetX,rotatedHole.y+holeOffsetY]),holeRadius=Math.min(scaledHoleHeight,scaledHoleWidth)/2,children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,x:(-scaledRectPadWidth/2).toString(),y:(-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,x:(-scaledHoleWidth/2).toString(),y:(-scaledHoleHeight/2).toString(),width:scaledHoleWidth.toString(),height:scaledHoleHeight.toString(),rx:holeRadius.toString(),ry:holeRadius.toString(),transform:`translate(${holeCenterX} ${holeCenterY}) rotate(${-rotatedHole.hole_ccw_rotation})`,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledRectPadWidth+2*soldermaskMargin,maskHeight=scaledRectPadHeight+2*soldermaskMargin,maskBorderRadius=scaledRectBorderRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,x:(-scaledRectPadWidth/2).toString(),y:(-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,x:(-maskWidth/2).toString(),y:(-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.push({name:"rect",type:"element",attributes:{class:"pcb-solder-mask",fill:solderMaskColor,x:(-maskWidth/2).toString(),y:(-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="hole_with_polygon_pad"){let polygonHole=hole,padOutline=polygonHole.pad_outline||[],holeX=polygonHole.x??0,holeY=polygonHole.y??0,padPointsString=padOutline.map(point6=>applyToPoint3(transform5,[holeX+point6.x,holeY+point6.y])).map(p4=>p4.join(",")).join(" "),[holeCenterX,holeCenterY]=applyToPoint3(transform5,[holeX+polygonHole.hole_offset_x,holeY+polygonHole.hole_offset_y]),createHoleSvgObject=()=>{if(polygonHole.hole_shape==="circle"){let radius=(polygonHole.hole_diameter??0)*Math.abs(transform5.a)/2;return{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:holeCenterX.toString(),cy:holeCenterY.toString(),r:radius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}}if(polygonHole.hole_shape==="oval"){let scaledWidth=(polygonHole.hole_width??0)*Math.abs(transform5.a),scaledHeight=(polygonHole.hole_height??0)*Math.abs(transform5.a),rx2=scaledWidth/2,ry2=scaledHeight/2;return{name:"ellipse",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:holeCenterX.toString(),cy:holeCenterY.toString(),rx:rx2.toString(),ry:ry2.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}}if(polygonHole.hole_shape==="pill"||polygonHole.hole_shape==="rotated_pill"){let scaledWidth=(polygonHole.hole_width??0)*Math.abs(transform5.a),scaledHeight=(polygonHole.hole_height??0)*Math.abs(transform5.a),isHorizontal2=scaledWidth>scaledHeight,radius=Math.min(scaledWidth,scaledHeight)/2,straightLength=Math.abs(isHorizontal2?scaledWidth-scaledHeight:scaledHeight-scaledWidth),pathD=isHorizontal2?`M${-straightLength/2},${-radius} h${straightLength} a${radius},${radius} 0 0 1 0,${scaledHeight} h-${straightLength} a${radius},${radius} 0 0 1 0,-${scaledHeight} z`:`M${-radius},${-straightLength/2} v${straightLength} a${radius},${radius} 0 0 0 ${scaledWidth},0 v-${straightLength} a${radius},${radius} 0 0 0 -${scaledWidth},0 z`;return{name:"path",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,d:pathD,transform:`translate(${holeCenterX} ${holeCenterY})`,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}}return{name:"g",type:"element",attributes:{},value:"",children:[]}};return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children:[{name:"polygon",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,points:padPointsString,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},createHoleSvgObject()],value:""}]}return[]}function createSvgObjectsFromPcbSilkscreenPath(silkscreenPath,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx;if(!silkscreenPath.route||!Array.isArray(silkscreenPath.route))return[];let path=silkscreenPath.route.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" "),firstPoint=silkscreenPath.route[0],lastPoint=silkscreenPath.route[silkscreenPath.route.length-1];firstPoint&&lastPoint&&firstPoint.x===lastPoint.x&&firstPoint.y===lastPoint.y&&(path+=" Z");let layer=silkscreenPath.layer||"top";if(layerFilter&&layer!==layerFilter)return[];let color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top;return[{name:"path",type:"element",attributes:{class:`pcb-silkscreen pcb-silkscreen-${layer}`,d:path,fill:"none",stroke:color,"stroke-width":(silkscreenPath.stroke_width*Math.abs(transform5.a)).toString(),"stroke-linecap":"round","stroke-linejoin":"round","data-pcb-component-id":silkscreenPath.pcb_component_id,"data-pcb-silkscreen-path-id":silkscreenPath.pcb_silkscreen_path_id,"data-type":"pcb_silkscreen_path","data-pcb-layer":layer},value:"",children:[]}]}function createSvgObjectsFromPcbSilkscreenText(pcbSilkscreenText,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2,circuitJson}=ctx,{anchor_position,text,font_size=1,layer="top",ccw_rotation=0,anchor_alignment="center"}=pcbSilkscreenText;if(layerFilter&&layer!==layerFilter)return[];if(!anchor_position||typeof anchor_position.x!="number"||typeof anchor_position.y!="number")return console.error("Invalid anchor_position:",anchor_position),[];let[transformedX,transformedY]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),transformedFontSize=font_size*Math.abs(transform5.a),textAnchor="middle",dominantBaseline="central",dx2=0,dy2=0;switch(anchor_alignment){case"top_left":textAnchor="start",dominantBaseline="text-before-edge";break;case"top_center":textAnchor="middle",dominantBaseline="text-before-edge";break;case"top_right":textAnchor="end",dominantBaseline="text-before-edge";break;case"center_left":textAnchor="start",dominantBaseline="central";break;case"center_right":textAnchor="end",dominantBaseline="central";break;case"bottom_left":textAnchor="start",dominantBaseline="text-after-edge";break;case"bottom_center":textAnchor="middle",dominantBaseline="text-after-edge";break;case"bottom_right":textAnchor="end",dominantBaseline="text-after-edge";break;default:textAnchor="middle",dominantBaseline="central";break}let textTransform=compose3(translate3(transformedX,transformedY),rotate3(-ccw_rotation*Math.PI/180),...layer==="bottom"?[scale3(-1,1)]:[]),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top,lines=text.split(`
|
|
271
|
+
at `+loc}return str};peg$SyntaxError2.buildMessage=function(expected,found){var DESCRIBE_EXPECTATION_FNS={literal:function(expectation){return'"'+literalEscape(expectation.text)+'"'},class:function(expectation){var escapedParts=expectation.parts.map(function(part){return Array.isArray(part)?classEscape(part[0])+"-"+classEscape(part[1]):classEscape(part)});return"["+(expectation.inverted?"^":"")+escapedParts.join("")+"]"},any:function(){return"any character"},end:function(){return"end of input"},other:function(expectation){return expectation.description}};function hex(ch2){return ch2.charCodeAt(0).toString(16).toUpperCase()}function literalEscape(s2){return s2.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(ch2){return"\\x0"+hex(ch2)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(ch2){return"\\x"+hex(ch2)})}function classEscape(s2){return s2.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(ch2){return"\\x0"+hex(ch2)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(ch2){return"\\x"+hex(ch2)})}function describeExpectation(expectation){return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation)}function describeExpected(expected2){var descriptions=expected2.map(describeExpectation),i2,j4;if(descriptions.sort(),descriptions.length>0){for(i2=1,j4=1;i2<descriptions.length;i2++)descriptions[i2-1]!==descriptions[i2]&&(descriptions[j4]=descriptions[i2],j4++);descriptions.length=j4}switch(descriptions.length){case 1:return descriptions[0];case 2:return descriptions[0]+" or "+descriptions[1];default:return descriptions.slice(0,-1).join(", ")+", or "+descriptions[descriptions.length-1]}}function describeFound(found2){return found2?'"'+literalEscape(found2)+'"':"end of input"}return"Expected "+describeExpected(expected)+" but "+describeFound(found)+" found."}}});var init_fromTransformAttribute2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/fromTransformAttribute.js"(){"use strict";init_fromTransformAttribute_autogenerated2()}});var init_decompose2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/decompose.js"(){"use strict";init_scale2();init_transform2()}});var init_flip2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/flip.js"(){"use strict"}});var init_fromMovingPoints2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/fromMovingPoints.js"(){"use strict";init_translate2();init_applyToPoint2();init_rotate2();init_scale2();init_transform2()}});var init_src2=__esm({"node_modules/circuit-to-svg/node_modules/transformation-matrix/src/index.js"(){"use strict";init_applyToPoint2();init_fromObject2();init_fromString2();init_identity2();init_inverse2();init_isAffineMatrix2();init_rotate2();init_scale2();init_shear2();init_skew2();init_toString2();init_transform2();init_translate2();init_fromTriangles2();init_smoothMatrix2();init_fromDefinition2();init_fromTransformAttribute2();init_decompose2();init_flip2();init_fromMovingPoints2()}});var svgAlphabet,lineAlphabet,init_dist7=__esm({"node_modules/@tscircuit/alphabet/dist/index.js"(){"use strict";svgAlphabet={0:"M0.4544564813877358 0L0.2723441540828736 0.03592830447352719L0.1086847233315459 0.14528754990019965L0.020630545837255005 0.3040632652221331L0 0.5395277421960205L0.049259221760993496 0.7369487828466779L0.18080513776237842 0.9005494166306564L0.37036887043974215 0.9872116270037247L0.5864663759301132 1L0.8148695622827444 0.9332890276148733L0.9326583645506394 0.8113052246023419L1 0.4031281830668562L0.833288960385582 0.09886798567812842L0.6801767918233781 0.02483708485091681L0.4544564813877358 0",1:"M 0.16 0.27 L 0.5 0 L 0.5 1",2:"M0.069593147751606 0.19461498231706575L0.1039380353319058 0.1224291500164194L0.20543361884368308 0.05510832064153169L0.3717712794432549 0.009452970962689482L0.4785344452623127 0L0.663238590738758 0.008714098643339864L0.8017933618843684 0.04769189395915288L0.8775637379550322 0.10746757678258442L0.9047778372591005 0.17693069668193287L0.9029710920770878 0.2231347105796246L0.8704496788008566 0.30047744598157516L0.7292906538577354 0.4508486051631194L0.3737955032119913 0.7369006417749693L0 1L1 1",3:"M0.03917438899874637 0.19855364635107545L0.15510940508963084 0.06745632622133718L0.37598645522339846 0L0.8486391893813088 0.0652271323161611L0.9782182415054349 0.21747394183735683L0.9213133780517754 0.3547560290117714L0.6504271515903481 0.4543436297681271L0.22975249764129613 0.48476611625264143L0.7659038682744629 0.5411919558122493L0.9258712987734741 0.6203185665660985L1 0.7458360609169667L0.8938813281118737 0.9059190913045964L0.6166890258875837 1L0.261528440153542 0.9874861530507921L0 0.8837289530851273",4:"M0.7328897338403042 0L0 0.6684672518568535L1 0.6684672518568535M0.7243346007604563 0.4530722484807562L0.7243346007604563 1",5:"M 0 0 L 0 0.4973 L 0.4262 0.4319 L 0.7305 0.4565 L 0.8516 0.5009 L 0.9357 0.5639 L 1 0.7356 L 0.9696 0.8248 L 0.8898 0.895 L 0.733 0.9602 L 0.5518 0.9945 L 0.3814 1 L 0.2379 0.9821 L 0.1219 0.947 L 0 0.8748 M 0 0 L 1 0",6:"M0.6964601700926856 0L0.3639239026215478 0.0743562375769351L0.1415931962925719 0.21735490179786915L0.009977939399608712 0.46336322325406004L0.00029622007592593224 0.7083131475173043L0.09408885043224748 0.8746809149767036L0.3379247445101846 0.9876686500961888L0.7109203869569624 1L0.9260852957913362 0.9103558029693921L1 0.7716571969091733L0.9824294723385016 0.6390635485705886L0.7446504992867332 0.4733643097729175L0.31028858071607296 0.47578021640899115L0.1208702146816024 0.5481452483973847L0 0.6616669755788906",7:"M0 0L1 0L0.9246479649697582 0.030539772727272752L0.8850302419354837 0.05075757575757579L0.7922946068548385 0.11079545454545457L0.7419268208165322 0.15213068181818185L0.6907258064516127 0.20202020202020204L0.6400666267641127 0.26122159090909086L0.5913243447580644 0.33049242424242414L0.5458740234374998 0.4105902777777778L0.5050907258064514 0.5022727272727272L0.4703495148689514 0.6062973484848484L0.43257456133442534 0.787133049242424L0.41612903225806447 1",8:"M0.5143001078924863 0L0.16007477667923162 0.10731570786949331L0.14924628550868277 0.3146018498698755L0.2939585848842112 0.41617921794558677L0.8648302624811545 0.5385163833653317L1 0.7775820770511038L0.8180842915260376 0.9505845566922285L0.41968938540525413 1L0.08062381919779889 0.882831681184498L0 0.6936376947135333L0.17150171673893433 0.5188652309607817L0.6529263782780712 0.4242818653203618L0.8650205888491803 0.29644027376796367L0.8702067371119496 0.09910067291661573L0.5143001078924863 0",9:"M1 0.25379591792994305L0.9514789771111742 0.11679361536614272L0.8702482473521467 0.05711741614054847L0.7327445265851579 0.015213872471965633L0.525248180711544 0L0.3292056884418538 0.012928195113745608L0.15997632037247655 0.058762870026191856L0.05266940041228321 0.12882439350476L0 0.2562067822770946L0.11316462894512366 0.4121335905917837L0.2403060136479954 0.4603365890068938L0.4097241967586011 0.4745978388276783L0.8642414300184816 0.420815170259988L0.9732054796346318 0.34537434075898393L1 0.25379591792994305M0.9647426784191072 0.35488595400360495L0.4756895081034974 1",A:"M0 1L0.4808333333333333 0L1 1M0.24250000000000002 0.6099439775910365L0.7341666666666666 0.6099439775910365",B:"M0 1L0 0.0117369978777208L0.30665717153513444 0L0.5874522807082946 0.03451403469442413L0.7766202217193218 0.15033936404895643L0.7471969743588041 0.31967962568332936L0.5246013359741988 0.4102978954282461L0.04378745314885416 0.44918617613783574L0.5112949594180156 0.469692928091109L0.8540266515643348 0.5552749498651879L1 0.6868463175009967L0.9880091196159324 0.8570018204672155L0.922301719975498 0.9321708046604659L0.7584266951758925 0.9932594737131338L0 1",C:"M1 0.23038928858890784L0.9328355511865092 0.12426412616785204L0.8096380839483327 0.04912601676267708L0.5763225801788256 0L0.4039037709527492 0.015028068281399815L0.2519579390951737 0.06533979308999706L0.10359458463139784 0.18146243506591617L0 0.4862728453971315L0.08129580872733055 0.792689266886982L0.20257034847159672 0.9160822255736587L0.3286572892798542 0.9738230826074175L0.5742878414421707 1L0.7883510303801312 0.9665431511195721L0.946851033994232 0.8689071500976585L1 0.7311049027121912",D:"M0 1L0.015604366822624637 0.020770988281483303L0.22564758265176144 0L0.3865476147957666 0.0024153386496795644L0.6479126635475078 0.051745644338731314L0.841191887805517 0.15827717679529366L0.9517008345536152 0.30172260586872185L0.9957536578687336 0.4504541551987709L1 0.5624359222498485L0.9798483279164735 0.6584121775234548L0.9386273319285215 0.7395945263504481L0.806292129480815 0.8624239259880274L0.6296239151398265 0.9406169638094516L0.3397492767598845 0.9954164354263132L0 1",E:"M0 0L0 1M0 0L1 0M0 0.5L0.7 0.5M0 1L1 1",F:"M0 0L0 1M0.011363636363636364 0.006802721088435374L1 0.006802721088435374M0.011363636363636364 0.4965986394557823L0.8409090909090909 0.4965986394557823",G:"M0.902666857540557 0.03860785012651126L0.6504261864675637 0L0.3838947267237336 0.015442305268228053L0.21293332876776194 0.07706794377239819L0.07799659974941617 0.1994951236187481L0 0.46380381528937314L0.04159964421546915 0.7502491408002389L0.13176692977834842 0.8535497868383203L0.2709176262273927 0.936767572377719L0.4386472596876406 0.9891638569283179L0.6145513562841309 1L0.7782254421419019 0.9585373611026471L0.9092650433859927 0.8540372997461425L1 0.5556012645283437L0.5583959277303046 0.55491741080559",H:"M0 0L0 1M0 0.4788732394366197L0.989010989010989 0.4788732394366197M1 0L1 1",I:"M0.5 0L0.5 1",J:"M0.9976457238788704 0L1 0.7396412315872798L0.9773931362096968 0.8322033314977973L0.9345115952458736 0.882296255506608L0.8743862896259549 0.9221331222466961L0.8024024079884948 0.9526431718061675L0.6443996712151668 0.9893997797356828L0.5035848940343224 1L0.3127211130319937 0.9877004749449337L0.17201910858386513 0.9539509911894274L0.10357419806379677 0.9212555066079295L0.053656568662899015 0.8816079295154184L0.020759483663648916 0.8360407488986785L0.003376206348523566 0.7855864537444934L0 0.7312775330396476",K:"M0 0L0 1M0.8787878787878788 0.06666666666666667L0 0.6148148148148148M0.3333333333333333 0.45925925925925926L1 0.9777777777777777",L:"M0 0L0 1L1 1",M:"M0 1L0 0L0.5 0.6512L1 0L1 1",N:"M0 1L0 0L1 1L0.9803729146221786 0",O:"M0.4718499217948183 1L0.2896765846490613 0.9606979309189402L0.12315162147934663 0.8411184486080473L0 0.4352399966492615L0.11730398524516283 0.13145645436014852L0.2612197451988078 0.04493357858878059L0.5104071592772554 0L0.7450113425917159 0.05393013710105273L0.882367950645524 0.15242300282020502L1 0.5224527406249126L0.9414597290654386 0.7560662329321755L0.8371289514446183 0.8910800547287298L0.6518259868433511 0.9830452628933628L0.4718499217948183 1",P:"M0 1L0 0.018871774228013626L0.29609603495819875 0L0.5609840637427541 0.011794858892508529L0.7332142696692472 0.04353904702296349L0.8102258645858864 0.0691965055027166L0.9330504315465442 0.14445061754775845L0.9876391714147118 0.22527816445836535L1 0.3434414070631638L0.9510549958116356 0.41772808046663146L0.8746646891596713 0.45879131862541683L0.7528523813396283 0.49171525113425024L0.5766919939969619 0.5153253033973054L0.33725744877712827 0.5284469008187558L0.025622667325582785 0.529905468802775",Q:"M0.4618887943546369 0.9755918167206952L0.28356128136544534 0.9372490397450218L0.12055179272160406 0.8205882753548176L0 0.4246165790405623L0.1148276047430244 0.12824784112887844L0.25570518844754375 0.043836831567190586L0.49963205786237674 0L0.7292835601228574 0.0526138004304122L0.8637404608452104 0.14870263423138746L0.9788892040030622 0.5097006183769648L0.9215847647858059 0.7376120297474734L0.8194564929275405 0.869330409436378L0.6380654214095985 0.9590509139448092L0.4618887943546369 0.9755918167206952M0.5824181120212351 0.6861805006946525L1 1",R:"M0 0.9928375167236815L0 0.02590227442068435L0.3611517274211098 0L0.6146286724700761 0.008660554424468435L0.7675462459194776 0.035269459580494614L0.831839975516866 0.056961676692569484L0.8847592491838954 0.08519560521497332L0.9238557535364527 0.120683646438422L0.9583303225312839 0.21691797435320384L0.955092470586235 0.3022616904894429L0.9198097669001631 0.3640573439322699L0.8564862239866702 0.40639258627024005L0.7691258543593579 0.43335506909190874L0.601775027203482 0.4539166070813109L0.023939064200217658 0.46997623755243123M0.5038084874863982 0.5108023922274467L1 1",S:"M0.8886929689221953 0.15146982162688968L0.7276173683050475 0.013780286031594946L0.34582323121005076 0L0.1318235250900008 0.09920162734298861L0.0444543935052531 0.2811287071349243L0.08064065829108809 0.3709571405906485L0.21603115127470426 0.4485505768228281L0.7525409135992945 0.5111160926769565L0.9330263665417677 0.5850732219351329L1 0.7129938124702524L0.9117772389978691 0.9130572743138187L0.6423187128058188 1L0.29586019579751677 0.9935291584506244L0.10638454191462794 0.9229845198431584L0 0.7570771288048773",T:"M0 0L1 0M0.5148514851485149 0L0.5148514851485149 1",U:"M0 0L0.0023103778751369115 0.5467447428390111L0.01823032542100219 0.6954785891481812L0.05895528135268338 0.8056480226151669L0.13703402031421133 0.8894445726483398L0.23918400876232196 0.9448524533417946L0.3917887458926616 0.9848674531975652L0.584341627875137 1L0.7194816196604602 0.9848501456716763L0.8303268115073934 0.9449411544119768L0.8966613970084885 0.898186315516197L0.9251437568455642 0.867453197565408L0.9687114937020809 0.7890904895145239L0.9890470974808324 0.6852857184065537L1 0.0014769088758762145",V:"M0 0L0.5348837209302325 1L1 0",W:"M0 0L0.23300090661831369 0.9873417721518988L0.49954669084315495 0.30081906180193585L0.7851314596554849 1L1 0.0215934475055845",X:"M0 0L0.9893617021276596 1M1 0L0.010638297872340425 1",Y:"M0 0L0.4860515021459227 0.44712562100780695M1 0.0014194464158977947L0.48927038626609437 0.44996451383960256L0.5075107296137339 1",Z:"M0 0L1 0L0 1L1 1",a:"M0.900 0.517L0.900 1.000M0.900 0.620L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",b:"M0.100 0.275L0.100 1.000M0.100 0.620L0.234 0.551L0.366 0.517L0.566 0.517L0.700 0.551L0.834 0.620L0.900 0.724L0.900 0.793L0.834 0.896L0.700 0.965L0.566 1.000L0.366 1.000L0.234 0.965L0.100 0.896",c:"M0.900 0.620L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",d:"M0.900 0.275L0.900 1.000M0.900 0.620L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",e:"M0.100 0.724L0.900 0.724M0.900 0.655L0.834 0.586L0.766 0.551L0.634 0.517L0.434 0.517L0.300 0.551L0.166 0.620L0.100 0.724L0.100 0.793L0.166 0.896L0.300 0.965L0.434 1.000L0.634 1.000L0.766 0.965L0.900 0.896",f:"M0.900 0.275L0.700 0.275L0.500 0.310L0.400 0.413L0.400 1.000M0.100 0.517L0.800 0.517",g:"M0.900 0.516L0.900 1.068L0.834 1.171L0.766 1.206L0.634 1.240L0.434 1.240L0.300 1.206L0.166 1.137L0.100 1.033M0.900 0.619L0.766 0.550L0.634 0.516L0.434 0.516L0.300 0.550L0.166 0.619L0.100 0.723L0.100 0.792L0.166 0.895L0.300 0.964L0.434 0.999L0.634 0.999L0.766 0.964L0.900 0.895",h:"M0.100 0.275L0.100 1.000M0.100 0.655L0.318 0.551L0.464 0.517L0.682 0.517L0.827 0.551L0.900 0.655L0.900 1.000",i:"M0.466 0.275L0.534 0.275M0.500 0.517L0.500 1.000",j:"M0.634 0.274L0.766 0.274M0.700 0.516L0.700 1.102L0.634 1.206L0.366 1.240L0.166 1.206",k:"M0.100 0.275L0.100 1.000M0.827 0.517L0.100 0.862M0.391 0.724L0.900 1.000",l:"M0.5 0.275L0.5 1.000",m:"M0.100 0.517L0.100 1.000M0.100 0.655L0.209 0.551L0.282 0.517L0.418 0.517L0.491 0.551L0.564 0.655L0.564 1.000M0.564 0.655L0.673 0.551L0.745 0.517L0.882 0.517L0.955 0.551L0.955 1.000",n:"M0.100 0.517L0.100 1.000M0.100 0.655L0.318 0.551L0.464 0.517L0.682 0.517L0.827 0.551L0.900 0.655L0.900 1.000",o:"M0.408 0.517L0.285 0.551L0.162 0.620L0.100 0.724L0.100 0.793L0.162 0.896L0.285 0.965L0.408 1.000L0.592 1.000L0.715 0.965L0.838 0.896L0.900 0.793L0.900 0.724L0.838 0.620L0.715 0.551L0.592 0.517L0.408 0.517",p:"M0.100 0.516L0.100 1.240M0.100 0.619L0.234 0.550L0.366 0.516L0.566 0.516L0.700 0.550L0.834 0.619L0.900 0.723L0.900 0.792L0.834 0.895L0.700 0.964L0.566 0.999L0.366 0.999L0.234 0.964L0.100 0.895",q:"M0.900 0.516L0.900 1.240M0.900 0.619L0.766 0.550L0.634 0.516L0.434 0.516L0.300 0.550L0.166 0.619L0.100 0.723L0.100 0.792L0.166 0.895L0.300 0.964L0.434 0.999L0.634 0.999L0.766 0.964L0.900 0.895",r:"M0.100 0.517L0.100 1.000M0.100 0.724L0.200 0.620L0.400 0.551L0.600 0.517L0.900 0.517",s:"M0.850 0.551L0.700 0.517L0.450 0.517L0.250 0.551L0.100 0.620L0.100 0.689L0.250 0.724L0.500 0.724L0.750 0.793L0.900 0.862L0.900 0.931L0.750 0.965L0.550 1.000L0.300 1.000L0.150 0.965L0.100 0.896",t:"M0.400 0.275L0.400 0.862L0.500 0.965L0.700 1.000L0.900 1.000M0.100 0.517L0.800 0.517",u:"M0.100 0.517L0.100 0.862L0.173 0.965L0.318 1.000L0.536 1.000L0.682 0.965L0.900 0.862M0.900 0.517L0.900 1.000",v:"M0.100 0.517L0.500 1.000M0.900 0.517L0.500 1.000",w:"M0.100 0.517L0.300 1.000M0.500 0.517L0.300 1.000M0.500 0.517L0.700 1.000M0.900 0.517L0.700 1.000",x:"M0.100 0.517L0.900 1.000M0.900 0.517L0.100 1.000",y:"M0.162 0.516L0.530 0.999M0.900 0.516L0.530 0.999L0.408 1.137L0.285 1.206L0.162 1.240L0.100 1.240",z:"M0.900 0.517L0.100 1.000M0.100 0.517L0.900 0.517M0.100 1.000L0.900 1.000",".":"M 0.49 1 L 0.41 1","!":"M0.5 0L0.5 0.6M0.49 0.85L0.51 0.85",",":"M0.55 0.85L0.45 0.95L0.5 1","*":"M0.5 0.15L0.5 0.35M0.5 0.15L0.69 0.22M0.5 0.15L0.62 -0.03M0.5 0.15L0.38 -0.03M0.5 0.15L0.31 0.22","(":"M0.84 0.01L0.80 0.06L0.76 0.12L0.72 0.19L0.68 0.27L0.65 0.35L0.63 0.43L0.62 0.50L0.63 0.57L0.65 0.65L0.68 0.73L0.72 0.81L0.76 0.88L0.80 0.94L0.84 0.99",")":"M0.16 0.01L0.20 0.06L0.24 0.12L0.28 0.19L0.32 0.27L0.35 0.35L0.37 0.43L0.38 0.50L0.37 0.57L0.35 0.65L0.32 0.73L0.28 0.81L0.24 0.88L0.20 0.94L0.16 0.99","-":"M0.2 0.5L0.8 0.5","+":"M0.2 0.5L0.8 0.5M0.5 0.2L0.5 0.8","=":"M0 0.25L1 0.25M0 0.75L1 0.75",_:"M0 1 L1 1","[":"M0.75 0L0.25 0L0.25 1L0.75 1","]":"M0.25 0L0.75 0L0.75 1L0.25 1","<":"M0.75 0L0.25 0.5L0.25 0.5L0.75 1",">":"M0.25 0L0.75 0.5L0.75 0.5L0.25 1","'":"M 0.5 0 L 0.5 0.5",'"':"M 0.25 0 L 0.25 0.5 M 0.75 0 L 0.75 0.5","/":"M0 1L1 0","\\":"M0 0L1 1","#":"M0.38 0.05L0.28 0.95M0.78 0.05L0.68 0.95M0.10 0.38L1.00 0.28M0.05 0.78L0.95 0.68",$:"M0.50 0.02L0.50 0.98M0.80 0.22L0.66 0.12L0.38 0.10L0.22 0.20L0.16 0.34L0.20 0.42L0.32 0.48L0.70 0.54L0.82 0.60L0.86 0.70L0.78 0.84L0.58 0.90L0.32 0.88L0.18 0.82L0.12 0.70","^":"M0.25 0.45L0.5 0.05L0.75 0.45"},lineAlphabet={};for(let letter in svgAlphabet){lineAlphabet[letter]=[];let segs=svgAlphabet[letter].split("M").slice(1).map(seg=>seg.split("L").map(pr4=>pr4.trim().split(" ").map(parseFloat)));for(let seg of segs)for(let i2=0;i2<seg.length-1;i2++)lineAlphabet[letter].push({x1:seg[i2][0],y1:1-seg[i2][1],x2:seg[i2+1][0],y2:1-seg[i2+1][1]})}}});var dist_exports3={};__export(dist_exports3,{CIRCUIT_TO_SVG_VERSION:()=>CIRCUIT_TO_SVG_VERSION,circuitJsonToPcbSvg:()=>circuitJsonToPcbSvg,circuitJsonToSchematicSvg:()=>circuitJsonToSchematicSvg,convertCircuitJsonToAssemblySvg:()=>convertCircuitJsonToAssemblySvg,convertCircuitJsonToPcbSvg:()=>convertCircuitJsonToPcbSvg,convertCircuitJsonToPinoutSvg:()=>convertCircuitJsonToPinoutSvg,convertCircuitJsonToSchematicSimulationSvg:()=>convertCircuitJsonToSchematicSimulationSvg,convertCircuitJsonToSchematicSvg:()=>convertCircuitJsonToSchematicSvg,convertCircuitJsonToSimulationGraphSvg:()=>convertCircuitJsonToSimulationGraphSvg,convertCircuitJsonToSolderPasteMask:()=>convertCircuitJsonToSolderPasteMask,createErrorTextOverlay:()=>createErrorTextOverlay,createSvgObjectsForSchComponentPortHovers:()=>createSvgObjectsForSchComponentPortHovers,getSoftwareUsedString:()=>getSoftwareUsedString,isSimulationExperiment:()=>isSimulationExperiment,isSimulationTransientVoltageGraph:()=>isSimulationTransientVoltageGraph,isSimulationVoltageProbe:()=>isSimulationVoltageProbe});function createSvgObjectsFromPcbTraceError(pcbTraceError,circuitJson,ctx){let{transform:transform5,shouldDrawErrors}=ctx;if(!shouldDrawErrors)return[];let{pcb_port_ids}=pcbTraceError,port1=circuitJson.find(el2=>el2.type==="pcb_port"&&el2.pcb_port_id===pcb_port_ids?.[0]),port2=circuitJson.find(el2=>el2.type==="pcb_port"&&el2.pcb_port_id===pcb_port_ids?.[1]);if(!port1||!port2){let viaId=pcbTraceError.message?.match(/pcb_via\[#?(pcb_via_\d+)\]/)?.[1],via=circuitJson.find(el2=>el2.type==="pcb_via"&&el2.pcb_via_id===viaId);if(via&&via.type==="pcb_via")return createSvgObjectsForViaTraceError(pcbTraceError,via,ctx);if(pcbTraceError.center){let screenCenter=applyToPoint3(transform5,{x:pcbTraceError.center.x,y:pcbTraceError.center.y});return annotateTraceErrorSvgObjects([{name:"rect",type:"element",attributes:{x:(screenCenter.x-5).toString(),y:(screenCenter.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${screenCenter.x} ${screenCenter.y})`},children:[],value:""},{name:"text",type:"element",attributes:{x:screenCenter.x.toString(),y:(screenCenter.y-15).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:pcbTraceError.message||"Pcb Trace Error",name:"",attributes:{},children:[]}],value:""}])}else return[]}let screenPort1=applyToPoint3(transform5,{x:port1.x,y:port1.y}),screenPort2=applyToPoint3(transform5,{x:port2.x,y:port2.y}),errorCenter={x:(screenPort1.x+screenPort2.x)/2,y:(screenPort1.y+screenPort2.y)/2};if(isNaN(screenPort1.x)||isNaN(screenPort1.y)||isNaN(screenPort2.x)||isNaN(screenPort2.y)||isNaN(errorCenter.x)||isNaN(errorCenter.y))return[];let svgObjects=[{name:"line",type:"element",attributes:{x1:screenPort1.x.toString(),y1:screenPort1.y.toString(),x2:errorCenter.x.toString(),y2:errorCenter.y.toString(),stroke:"red","stroke-width":"1.5","stroke-dasharray":"2,2"},children:[],value:""},{name:"line",type:"element",attributes:{x1:errorCenter.x.toString(),y1:errorCenter.y.toString(),x2:screenPort2.x.toString(),y2:screenPort2.y.toString(),stroke:"red","stroke-width":"1.5","stroke-dasharray":"2,2"},children:[],value:""},{name:"rect",type:"element",attributes:{x:(errorCenter.x-5).toString(),y:(errorCenter.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${errorCenter.x} ${errorCenter.y})`},children:[],value:""},{name:"text",type:"element",attributes:{x:errorCenter.x.toString(),y:(errorCenter.y-15).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:pcbTraceError.message||"Pcb Trace Error",name:"",attributes:{},children:[]}],value:""}];return annotateTraceErrorSvgObjects(svgObjects)}function createSvgObjectsForViaTraceError(pcbTraceError,via,ctx){let{transform:transform5}=ctx;if(pcbTraceError.center&&via){let screenCenter=applyToPoint3(transform5,{x:pcbTraceError.center.x,y:pcbTraceError.center.y}),screenVia=applyToPoint3(transform5,{x:via.x,y:via.y}),dx2=screenVia.x-screenCenter.x,dy2=screenVia.y-screenCenter.y,dist=Math.sqrt(dx2*dx2+dy2*dy2),angle=Math.atan2(dy2,dx2)*180/Math.PI,boxWidth=dist+10*2,boxHeight=20,midX=(screenCenter.x+screenVia.x)/2,midY=(screenCenter.y+screenVia.y)/2;return annotateTraceErrorSvgObjects([{name:"rect",type:"element",attributes:{x:(midX-boxWidth/2).toString(),y:(midY-boxHeight/2).toString(),width:boxWidth.toString(),height:boxHeight.toString(),fill:"none",stroke:"red","stroke-width":"1","stroke-dasharray":"3,2",transform:`rotate(${angle} ${midX} ${midY})`},children:[],value:""},{name:"rect",type:"element",attributes:{x:(midX-5).toString(),y:(midY-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${midX} ${midY})`},children:[],value:""},{name:"text",type:"element",attributes:{x:midX.toString(),y:(midY-boxHeight/2-5).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:pcbTraceError.message||"Pcb Trace Error",name:"",attributes:{},children:[]}],value:""}])}return[]}function annotateTraceErrorSvgObjects(objects){return objects.map(object=>({...object,attributes:{...object.attributes??{},"data-type":object.attributes?.["data-type"]??"pcb_trace_error","data-pcb-layer":object.attributes?.["data-pcb-layer"]??"overlay"},children:(object.children??[]).map(child=>child?.type==="element"?{...child,attributes:{...child.attributes??{},"data-type":child.attributes?.["data-type"]??"pcb_trace_error","data-pcb-layer":child.attributes?.["data-pcb-layer"]??"overlay"}}:child)}))}function annotateFootprintErrorSvgObjects(objects){return objects.map(object=>({...object,attributes:{...object.attributes??{},"data-type":object.attributes?.["data-type"]??"pcb_footprint_overlap_error","data-pcb-layer":object.attributes?.["data-pcb-layer"]??"overlay"},children:(object.children??[]).map(child=>child?.type==="element"?{...child,attributes:{...child.attributes??{},"data-type":child.attributes?.["data-type"]??"pcb_footprint_overlap_error","data-pcb-layer":child.attributes?.["data-pcb-layer"]??"overlay"}}:child)}))}function createSvgObjectsFromPcbFootprintOverlapError(error,circuitJson,ctx){let{transform:transform5,shouldDrawErrors}=ctx;if(!shouldDrawErrors)return[];let svgObjects=[],referencedElements=[],padPortIds=[];if(error.pcb_smtpad_ids)for(let padId of error.pcb_smtpad_ids){let pad2=circuitJson.find(el2=>el2.type==="pcb_smtpad"&&el2.pcb_smtpad_id===padId);pad2&&(referencedElements.push({x:pad2.x,y:pad2.y,type:"pcb_smtpad",id:padId,pcb_port_id:pad2.pcb_port_id}),pad2.pcb_port_id&&padPortIds.push(pad2.pcb_port_id))}let allPadsSamePort=padPortIds.length>1&&padPortIds.every(id=>id===padPortIds[0]),filteredReferencedElements=referencedElements;if(allPadsSamePort&&(filteredReferencedElements=referencedElements.filter(e4=>e4.type!=="pcb_smtpad")),error.pcb_plated_hole_ids)for(let holeId of error.pcb_plated_hole_ids){let hole=circuitJson.find(el2=>el2.type==="pcb_plated_hole"&&el2.pcb_plated_hole_id===holeId);hole&&filteredReferencedElements.push({x:hole.x,y:hole.y,type:"pcb_plated_hole",id:holeId})}if(error.pcb_hole_ids)for(let holeId of error.pcb_hole_ids){let hole=circuitJson.find(el2=>el2.type==="pcb_hole"&&el2.pcb_hole_id===holeId);hole&&filteredReferencedElements.push({x:hole.x,y:hole.y,type:"pcb_hole",id:holeId})}if(filteredReferencedElements.length>0){let centerX=filteredReferencedElements.reduce((sum,el2)=>sum+el2.x,0)/filteredReferencedElements.length,centerY=filteredReferencedElements.reduce((sum,el2)=>sum+el2.y,0)/filteredReferencedElements.length,screenCenter=applyToPoint3(transform5,{x:centerX,y:centerY});svgObjects.push({name:"rect",type:"element",attributes:{x:(screenCenter.x-5).toString(),y:(screenCenter.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${screenCenter.x} ${screenCenter.y})`},children:[],value:""}),svgObjects.push({name:"text",type:"element",attributes:{x:screenCenter.x.toString(),y:(screenCenter.y-15).toString(),fill:"red","font-family":"sans-serif","font-size":"12","text-anchor":"middle"},children:[{type:"text",value:error.message||"PCB Footprint Overlap Error",name:"",attributes:{},children:[]}],value:""});for(let element of filteredReferencedElements){let screenPos=applyToPoint3(transform5,{x:element.x,y:element.y});svgObjects.push({name:"rect",type:"element",attributes:{x:(screenPos.x-5).toString(),y:(screenPos.y-5).toString(),width:"10",height:"10",fill:"red",transform:`rotate(45 ${screenPos.x} ${screenPos.y})`},children:[],value:""}),filteredReferencedElements.length>1&&svgObjects.push({name:"line",type:"element",attributes:{x1:screenCenter.x.toString(),y1:screenCenter.y.toString(),x2:screenPos.x.toString(),y2:screenPos.y.toString(),stroke:"red","stroke-width":"1.5","stroke-dasharray":"2,2"},children:[],value:""})}}return annotateFootprintErrorSvgObjects(svgObjects)}function createSvgObjectsFromPcbFabricationNotePath(fabNotePath,ctx){let{transform:transform5,layer:layerFilter}=ctx;if(!fabNotePath.route||!Array.isArray(fabNotePath.route))return[];let firstPoint=fabNotePath.route[0],lastPoint=fabNotePath.route[fabNotePath.route.length-1],isClosed=firstPoint.x===lastPoint.x&&firstPoint.y===lastPoint.y,path=fabNotePath.route.slice(0,isClosed?-1:void 0).map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" ")+(isClosed?" Z":"");return[{name:"path",type:"element",attributes:{class:"pcb-fabrication-note-path",stroke:fabNotePath.color||"rgba(255,255,255,0.5)",fill:"none",d:path,"stroke-width":(fabNotePath.stroke_width*Math.abs(transform5.a)).toString(),"data-pcb-component-id":fabNotePath.pcb_component_id,"data-pcb-fabrication-note-path-id":fabNotePath.pcb_fabrication_note_path_id,"data-type":"pcb_fabrication_note_path","data-pcb-layer":"overlay"},value:"",children:[]}]}function createSvgObjectsFromPcbFabricationNoteText(pcbFabNoteText,ctx){let{transform:transform5,layer:layerFilter}=ctx,{anchor_position,anchor_alignment="center",text,font_size=1,layer="top",color}=pcbFabNoteText;if(layerFilter&&layer!==layerFilter)return[];if(!anchor_position||typeof anchor_position.x!="number"||typeof anchor_position.y!="number")return console.error("Invalid anchor_position:",anchor_position),[];let[transformedX,transformedY]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),transformedFontSize=font_size*Math.abs(transform5.a),textAnchor="middle",dominantBaseline="central";switch(anchor_alignment){case"top_left":textAnchor="start",dominantBaseline="text-before-edge";break;case"top_right":textAnchor="end",dominantBaseline="text-before-edge";break;case"bottom_left":textAnchor="start",dominantBaseline="text-after-edge";break;case"bottom_right":textAnchor="end",dominantBaseline="text-after-edge";break}let textTransform=compose3(translate3(transformedX,transformedY),rotate3(Math.PI/180));return[{name:"text",type:"element",attributes:{x:"0",y:"0","font-family":"Arial, sans-serif","font-size":transformedFontSize.toString(),"text-anchor":textAnchor,"dominant-baseline":dominantBaseline,transform:toString(textTransform),class:"pcb-fabrication-note-text",fill:color||"rgba(255,255,255,0.5)","data-type":"pcb_fabrication_note_text","data-pcb-layer":"overlay"},children:[{type:"text",value:text,name:"",attributes:{},children:[]}],value:""}]}function createSvgObjectsFromPcbFabricationNoteRect(fabricationNoteRect,ctx){let{transform:transform5,layer:layerFilter}=ctx,{center:center2,width,height,stroke_width,is_filled,has_stroke,is_stroke_dashed,color,layer="top",pcb_component_id,pcb_fabrication_note_rect_id,corner_radius}=fabricationNoteRect;if(layerFilter&&layer!==layerFilter)return[];if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid pcb_fabrication_note_rect data",{center:center2,width,height}),[];let halfWidth=width/2,halfHeight=height/2,[topLeftX,topLeftY]=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]),[bottomRightX,bottomRightY]=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),rectX=Math.min(topLeftX,bottomRightX),rectY=Math.min(topLeftY,bottomRightY),rectWidth=Math.abs(bottomRightX-topLeftX),rectHeight=Math.abs(bottomRightY-topLeftY),transformedStrokeWidth=(typeof stroke_width=="number"?stroke_width:0)*Math.abs(transform5.a),overlayStrokeColor=color??DEFAULT_OVERLAY_STROKE_COLOR,baseCornerRadius=typeof corner_radius=="number"&&corner_radius>0?corner_radius:0,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),attributes2={x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),class:"pcb-fabrication-note-rect","data-type":"pcb_fabrication_note_rect","data-pcb-fabrication-note-rect-id":pcb_fabrication_note_rect_id,"data-pcb-layer":"overlay"};if(pcb_component_id!==void 0&&(attributes2["data-pcb-component-id"]=pcb_component_id),transformedCornerRadiusX>0&&(attributes2.rx=transformedCornerRadiusX.toString()),transformedCornerRadiusY>0&&(attributes2.ry=transformedCornerRadiusY.toString()),is_filled?attributes2.fill=color??DEFAULT_OVERLAY_FILL_COLOR:attributes2.fill="none",has_stroke??transformedStrokeWidth>0){if(attributes2.stroke=overlayStrokeColor,attributes2["stroke-width"]=transformedStrokeWidth.toString(),is_stroke_dashed){let dash=.2*Math.abs(transform5.a),gap=.1*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dash} ${gap}`}}else attributes2.stroke="none";return[{name:"rect",type:"element",value:"",attributes:attributes2,children:[]}]}function normalize(vector2){let length3=Math.hypot(vector2.x,vector2.y)||1;return{x:vector2.x/length3,y:vector2.y/length3}}function toPath(points){return points.map((point6,index)=>index===0?`M ${point6.x} ${point6.y}`:`L ${point6.x} ${point6.y}`).join(" ")}function createSvgObjectsFromPcbFabricationNoteDimension(dimension,ctx){let{transform:transform5,layer:layerFilter}=ctx,{from,to:to3,text,font_size=1,color,arrow_size,layer,pcb_component_id,pcb_fabrication_note_dimension_id,offset_distance,offset_direction,text_ccw_rotation}=dimension;if(layerFilter&&layer&&layer!==layerFilter)return[];if(!from||!to3||typeof from!="object"||typeof to3!="object")return console.error("Invalid pcb_fabrication_note_dimension endpoints",{from,to:to3}),[];if(typeof from.x!="number"||typeof from.y!="number"||typeof to3.x!="number"||typeof to3.y!="number")return console.error("Invalid pcb_fabrication_note_dimension point values",{from,to:to3}),[];let numericArrowSize=typeof arrow_size=="number"?arrow_size:void 0;if(numericArrowSize===void 0||!Number.isFinite(numericArrowSize)||numericArrowSize<=0)return console.error("Invalid pcb_fabrication_note_dimension arrow_size",arrow_size),[];let arrowSize=numericArrowSize,direction2=normalize({x:to3.x-from.x,y:to3.y-from.y});if(Number.isNaN(direction2.x)||Number.isNaN(direction2.y))return[];let perpendicular={x:-direction2.y,y:direction2.x},hasOffsetDirection=offset_direction&&typeof offset_direction.x=="number"&&typeof offset_direction.y=="number",normalizedOffsetDirection=hasOffsetDirection?normalize({x:offset_direction.x,y:offset_direction.y}):{x:0,y:0},offsetMagnitude=typeof offset_distance=="number"?offset_distance:0,offsetVector={x:normalizedOffsetDirection.x*offsetMagnitude,y:normalizedOffsetDirection.y*offsetMagnitude},applyOffset=point6=>({x:point6.x+offsetVector.x,y:point6.y+offsetVector.y}),fromOffset=applyOffset(from),toOffset=applyOffset(to3),arrowHalfWidth=arrowSize/2,fromBase={x:fromOffset.x+direction2.x*arrowSize,y:fromOffset.y+direction2.y*arrowSize},toBase={x:toOffset.x-direction2.x*arrowSize,y:toOffset.y-direction2.y*arrowSize},fromTriangle=[toScreen(fromOffset),toScreen({x:fromBase.x+perpendicular.x*arrowHalfWidth,y:fromBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:fromBase.x-perpendicular.x*arrowHalfWidth,y:fromBase.y-perpendicular.y*arrowHalfWidth})],toTriangle=[toScreen(toOffset),toScreen({x:toBase.x+perpendicular.x*arrowHalfWidth,y:toBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:toBase.x-perpendicular.x*arrowHalfWidth,y:toBase.y-perpendicular.y*arrowHalfWidth})],[lineStartX,lineStartY]=applyToPoint3(transform5,[fromBase.x,fromBase.y]),[lineEndX,lineEndY]=applyToPoint3(transform5,[toBase.x,toBase.y]),strokeWidth=arrowSize/5*Math.abs(transform5.a),lineColor=color||"rgba(255,255,255,0.5)",extensionDirection=hasOffsetDirection&&(Math.abs(normalizedOffsetDirection.x)>Number.EPSILON||Math.abs(normalizedOffsetDirection.y)>Number.EPSILON)?normalizedOffsetDirection:perpendicular,extensionLength=offsetMagnitude+arrowSize,createExtensionLine=anchor=>{let endPoint={x:anchor.x+extensionDirection.x*extensionLength,y:anchor.y+extensionDirection.y*extensionLength},[startX,startY]=applyToPoint3(transform5,[anchor.x,anchor.y]),[endX,endY]=applyToPoint3(transform5,[endPoint.x,endPoint.y]);return{name:"path",type:"element",value:"",attributes:{d:`M ${startX} ${startY} L ${endX} ${endY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-fabrication-note-dimension-extension"},children:[]}},extensionSegments=[createExtensionLine(from),createExtensionLine(to3)],midPoint={x:(from.x+to3.x)/2+offsetVector.x,y:(from.y+to3.y)/2+offsetVector.y},[screenFromX,screenFromY]=applyToPoint3(transform5,[fromOffset.x,fromOffset.y]),[screenToX,screenToY]=applyToPoint3(transform5,[toOffset.x,toOffset.y]),screenDirection=normalize({x:screenToX-screenFromX,y:screenToY-screenFromY}),textAngle=Math.atan2(screenDirection.y,screenDirection.x)*180/Math.PI;(textAngle>90||textAngle<-90)&&(textAngle+=180);let finalTextAngle=typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)?textAngle-text_ccw_rotation:textAngle,additionalOffset=0;if(text&&typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)){let textWidth=text.length*font_size*CHARACTER_WIDTH_MULTIPLIER,textHeight=font_size,rotationRad=text_ccw_rotation*Math.PI/180,sinRot=Math.abs(Math.sin(rotationRad)),cosRot=Math.abs(Math.cos(rotationRad)),halfWidth=textWidth/2,halfHeight=textHeight/2;additionalOffset=halfWidth*sinRot+halfHeight*cosRot+font_size*TEXT_INTERSECTION_PADDING_MULTIPLIER}let textOffset=arrowSize*TEXT_OFFSET_MULTIPLIER+additionalOffset,textPoint={x:midPoint.x+perpendicular.x*textOffset,y:midPoint.y+perpendicular.y*textOffset},[textX,textY]=applyToPoint3(transform5,[textPoint.x,textPoint.y]),transformedFontSize=font_size*Math.abs(transform5.a),children=[...extensionSegments,{name:"path",type:"element",value:"",attributes:{d:`M ${lineStartX} ${lineStartY} L ${lineEndX} ${lineEndY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-fabrication-note-dimension-line"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath(fromTriangle)} Z`,fill:lineColor,class:"pcb-fabrication-note-dimension-arrow"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath(toTriangle)} Z`,fill:lineColor,class:"pcb-fabrication-note-dimension-arrow"},children:[]}];text&&children.push({name:"text",type:"element",value:"",attributes:{x:textX.toString(),y:textY.toString(),fill:lineColor,"font-size":transformedFontSize.toString(),"font-family":"Arial, sans-serif","text-anchor":"middle","dominant-baseline":"central",class:"pcb-fabrication-note-dimension-text",transform:`rotate(${finalTextAngle} ${textX} ${textY})`},children:[{type:"text",name:"",value:text,attributes:{},children:[]}]});let attributes2={class:"pcb-fabrication-note-dimension","data-type":"pcb_fabrication_note_dimension","data-pcb-fabrication-note-dimension-id":pcb_fabrication_note_dimension_id,"data-pcb-layer":layer??"overlay"};return pcb_component_id!==void 0&&(attributes2["data-pcb-component-id"]=pcb_component_id),[{name:"g",type:"element",value:"",attributes:attributes2,children}];function toScreen(point6){let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return{x:x5,y:y5}}}function normalize2(vector2){let length3=Math.hypot(vector2.x,vector2.y)||1;return{x:vector2.x/length3,y:vector2.y/length3}}function toPath2(points){return points.map((point6,index)=>index===0?`M ${point6.x} ${point6.y}`:`L ${point6.x} ${point6.y}`).join(" ")}function createSvgObjectsFromPcbNoteDimension(dimension,ctx){let{transform:transform5}=ctx,{from,to:to3,text,font_size=1,color,arrow_size,offset_distance,offset_direction,text_ccw_rotation}=dimension;if(!from||!to3)return console.error("Invalid pcb_note_dimension endpoints",{from,to:to3}),[];if(!Number.isFinite(arrow_size)||arrow_size<=0)return console.error("Invalid pcb_note_dimension arrow_size",arrow_size),[];let direction2=normalize2({x:to3.x-from.x,y:to3.y-from.y});if(Number.isNaN(direction2.x)||Number.isNaN(direction2.y))return[];let perpendicular={x:-direction2.y,y:direction2.x},hasOffsetDirection=offset_direction&&typeof offset_direction.x=="number"&&typeof offset_direction.y=="number",normalizedOffsetDirection=hasOffsetDirection?normalize2({x:offset_direction.x,y:offset_direction.y}):{x:0,y:0},offsetMagnitude=typeof offset_distance=="number"?offset_distance:0,offsetVector={x:normalizedOffsetDirection.x*offsetMagnitude,y:normalizedOffsetDirection.y*offsetMagnitude},applyOffset=point6=>({x:point6.x+offsetVector.x,y:point6.y+offsetVector.y}),fromOffset=applyOffset(from),toOffset=applyOffset(to3),arrowHalfWidth=arrow_size/2,fromBase={x:fromOffset.x+direction2.x*arrow_size,y:fromOffset.y+direction2.y*arrow_size},toBase={x:toOffset.x-direction2.x*arrow_size,y:toOffset.y-direction2.y*arrow_size},fromTriangle=[toScreen(fromOffset),toScreen({x:fromBase.x+perpendicular.x*arrowHalfWidth,y:fromBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:fromBase.x-perpendicular.x*arrowHalfWidth,y:fromBase.y-perpendicular.y*arrowHalfWidth})],toTriangle=[toScreen(toOffset),toScreen({x:toBase.x+perpendicular.x*arrowHalfWidth,y:toBase.y+perpendicular.y*arrowHalfWidth}),toScreen({x:toBase.x-perpendicular.x*arrowHalfWidth,y:toBase.y-perpendicular.y*arrowHalfWidth})],[lineStartX,lineStartY]=applyToPoint3(transform5,[fromBase.x,fromBase.y]),[lineEndX,lineEndY]=applyToPoint3(transform5,[toBase.x,toBase.y]),strokeWidth=arrow_size/5*Math.abs(transform5.a),lineColor=color||colorMap.board.user_2,extensionDirection=hasOffsetDirection&&(Math.abs(normalizedOffsetDirection.x)>Number.EPSILON||Math.abs(normalizedOffsetDirection.y)>Number.EPSILON)?normalizedOffsetDirection:perpendicular,extensionLength=offsetMagnitude+arrow_size,createExtensionLine=anchor=>{let endPoint={x:anchor.x+extensionDirection.x*extensionLength,y:anchor.y+extensionDirection.y*extensionLength},[startX,startY]=applyToPoint3(transform5,[anchor.x,anchor.y]),[endX,endY]=applyToPoint3(transform5,[endPoint.x,endPoint.y]);return{name:"path",type:"element",value:"",attributes:{d:`M ${startX} ${startY} L ${endX} ${endY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-note-dimension-extension"},children:[]}},extensionSegments=[createExtensionLine(from),createExtensionLine(to3)],midPoint={x:(from.x+to3.x)/2+offsetVector.x,y:(from.y+to3.y)/2+offsetVector.y},[screenFromX,screenFromY]=applyToPoint3(transform5,[fromOffset.x,fromOffset.y]),[screenToX,screenToY]=applyToPoint3(transform5,[toOffset.x,toOffset.y]),screenDirection=normalize2({x:screenToX-screenFromX,y:screenToY-screenFromY}),textAngle=Math.atan2(screenDirection.y,screenDirection.x)*180/Math.PI;(textAngle>90||textAngle<-90)&&(textAngle+=180);let finalTextAngle=typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)?textAngle-text_ccw_rotation:textAngle,additionalOffset=0;if(text&&typeof text_ccw_rotation=="number"&&Number.isFinite(text_ccw_rotation)){let textWidth=text.length*font_size*.6,textHeight=font_size,rotationRad=text_ccw_rotation*Math.PI/180,sinRot=Math.abs(Math.sin(rotationRad)),cosRot=Math.abs(Math.cos(rotationRad)),halfWidth=textWidth/2,halfHeight=textHeight/2;additionalOffset=halfWidth*sinRot+halfHeight*cosRot+font_size*.3}let textOffset=arrow_size*1.5+additionalOffset,textPoint={x:midPoint.x+perpendicular.x*textOffset,y:midPoint.y+perpendicular.y*textOffset},[textX,textY]=applyToPoint3(transform5,[textPoint.x,textPoint.y]),transformedFontSize=font_size*Math.abs(transform5.a),children=[...extensionSegments,{name:"path",type:"element",value:"",attributes:{d:`M ${lineStartX} ${lineStartY} L ${lineEndX} ${lineEndY}`,stroke:lineColor,fill:"none","stroke-width":strokeWidth.toString(),"stroke-linecap":"round",class:"pcb-note-dimension-line"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath2(fromTriangle)} Z`,fill:lineColor,class:"pcb-note-dimension-arrow"},children:[]},{name:"path",type:"element",value:"",attributes:{d:`${toPath2(toTriangle)} Z`,fill:lineColor,class:"pcb-note-dimension-arrow"},children:[]}];return text&&children.push({name:"text",type:"element",value:"",attributes:{x:textX.toString(),y:textY.toString(),fill:lineColor,"font-size":transformedFontSize.toString(),"font-family":"Arial, sans-serif","text-anchor":"middle","dominant-baseline":"central",class:"pcb-note-dimension-text",transform:`rotate(${finalTextAngle} ${textX} ${textY})`},children:[{type:"text",name:"",value:text,attributes:{},children:[]}]}),[{name:"g",type:"element",value:"",attributes:{class:"pcb-note-dimension","data-type":"pcb_note_dimension","data-pcb-note-dimension-id":dimension.pcb_note_dimension_id,"data-pcb-layer":"overlay"},children}];function toScreen(point6){let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return{x:x5,y:y5}}}function createSvgObjectsFromPcbNoteText(note,ctx){let{transform:transform5}=ctx,{anchor_position,text,font_size=1,anchor_alignment="center",color}=note;if(!anchor_position||typeof anchor_position.x!="number"||typeof anchor_position.y!="number")return console.error("Invalid pcb_note_text anchor_position",anchor_position),[];if(typeof text!="string"||text.length===0)return console.error("Invalid pcb_note_text text",text),[];let[x5,y5]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),transformedFontSize=font_size*Math.abs(transform5.a),textAnchor="middle",dominantBaseline="central";switch(anchor_alignment){case"top_left":textAnchor="start",dominantBaseline="text-before-edge";break;case"top_right":textAnchor="end",dominantBaseline="text-before-edge";break;case"bottom_left":textAnchor="start",dominantBaseline="text-after-edge";break;case"bottom_right":textAnchor="end",dominantBaseline="text-after-edge";break;default:textAnchor="middle",dominantBaseline="central";break}return[{name:"text",type:"element",value:"",attributes:{x:x5.toString(),y:y5.toString(),fill:color??DEFAULT_OVERLAY_COLOR,"font-family":"Arial, sans-serif","font-size":transformedFontSize.toString(),"text-anchor":textAnchor,"dominant-baseline":dominantBaseline,class:"pcb-note-text","data-type":"pcb_note_text","data-pcb-note-text-id":note.pcb_note_text_id,"data-pcb-layer":"overlay"},children:[{type:"text",name:"",value:text,attributes:{},children:[]}]}]}function createSvgObjectsFromPcbNoteRect(noteRect,ctx){let{transform:transform5}=ctx,{center:center2,width,height,stroke_width,is_filled,has_stroke,is_stroke_dashed,color,corner_radius}=noteRect;if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid pcb_note_rect data",{center:center2,width,height}),[];let halfWidth=width/2,halfHeight=height/2,[topLeftX,topLeftY]=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]),[bottomRightX,bottomRightY]=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),rectX=Math.min(topLeftX,bottomRightX),rectY=Math.min(topLeftY,bottomRightY),rectWidth=Math.abs(bottomRightX-topLeftX),rectHeight=Math.abs(bottomRightY-topLeftY),transformedStrokeWidth=(typeof stroke_width=="number"?stroke_width:0)*Math.abs(transform5.a),baseCornerRadius=typeof corner_radius=="number"&&corner_radius>0?corner_radius:0,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),overlayColor=color??DEFAULT_OVERLAY_COLOR2,attributes2={x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),class:"pcb-note-rect","data-type":"pcb_note_rect","data-pcb-note-rect-id":noteRect.pcb_note_rect_id,"data-pcb-layer":"overlay"};if(transformedCornerRadiusX>0&&(attributes2.rx=transformedCornerRadiusX.toString()),transformedCornerRadiusY>0&&(attributes2.ry=transformedCornerRadiusY.toString()),is_filled?attributes2.fill=color??DEFAULT_FILL_COLOR:attributes2.fill="none",has_stroke??transformedStrokeWidth>0){if(attributes2.stroke=overlayColor,attributes2["stroke-width"]=transformedStrokeWidth.toString(),is_stroke_dashed){let dash=.2*Math.abs(transform5.a),gap=.1*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dash} ${gap}`}}else attributes2.stroke="none";return[{name:"rect",type:"element",value:"",attributes:attributes2,children:[]}]}function createSvgObjectsFromPcbNotePath(notePath,ctx){let{transform:transform5}=ctx;if(!Array.isArray(notePath.route)||notePath.route.length===0)return console.error("Invalid pcb_note_path route",notePath.route),[];for(let point6 of notePath.route)if(typeof point6.x!="number"||typeof point6.y!="number")return console.error("Invalid point in pcb_note_path",point6),[];let pathD=notePath.route.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" "),strokeWidth=notePath.stroke_width*Math.abs(transform5.a);return[{name:"path",type:"element",value:"",attributes:{d:pathD,stroke:notePath.color??DEFAULT_OVERLAY_COLOR3,fill:"none","stroke-width":strokeWidth.toString(),class:"pcb-note-path","data-type":"pcb_note_path","data-pcb-note-path-id":notePath.pcb_note_path_id,"data-pcb-layer":"overlay"},children:[]}]}function createSvgObjectsFromPcbNoteLine(noteLine,ctx){let{transform:transform5}=ctx,{x1:x12,y1:y12,x2:x22,y2:y22,stroke_width,color,is_dashed}=noteLine;if(typeof x12!="number"||typeof y12!="number"||typeof x22!="number"||typeof y22!="number")return console.error("Invalid pcb_note_line coordinates",{x1:x12,y1:y12,x2:x22,y2:y22}),[];let[startX,startY]=applyToPoint3(transform5,[x12,y12]),[endX,endY]=applyToPoint3(transform5,[x22,y22]),transformedStrokeWidth=(typeof stroke_width=="number"?stroke_width:0)*Math.abs(transform5.a),attributes2={x1:startX.toString(),y1:startY.toString(),x2:endX.toString(),y2:endY.toString(),stroke:color??DEFAULT_OVERLAY_COLOR4,"stroke-width":transformedStrokeWidth.toString(),"stroke-linecap":"round",class:"pcb-note-line","data-type":"pcb_note_line","data-pcb-note-line-id":noteLine.pcb_note_line_id,"data-pcb-layer":"overlay"};if(is_dashed){let dash=.2*Math.abs(transform5.a),gap=.1*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dash} ${gap}`}return[{name:"line",type:"element",value:"",attributes:attributes2,children:[]}]}function createSvgObjectsFromPcbPlatedHole(hole,ctx){let{transform:transform5,colorMap:colorMap2,showSolderMask}=ctx,[x5,y5]=applyToPoint3(transform5,[hole.x,hole.y]),layer=Array.isArray(hole.layers)&&hole.layers[0]||hole.layer||"top",maskLayer=layer,isCoveredWithSolderMask=!!hole.is_covered_with_solder_mask,soldermaskMargin=(hole.soldermask_margin??0)*Math.abs(transform5.a),shouldShowSolderMask=showSolderMask&&isCoveredWithSolderMask&&soldermaskMargin!==0,solderMaskColor=colorMap2.soldermaskWithCopperUnderneath.top;if(hole.shape==="pill"){let scaledOuterWidth=hole.outer_width*Math.abs(transform5.a),scaledOuterHeight=hole.outer_height*Math.abs(transform5.a),scaledHoleWidth=hole.hole_width*Math.abs(transform5.a),scaledHoleHeight=hole.hole_height*Math.abs(transform5.a),rotation4=hole.ccw_rotation||0,outerTransform=rotation4?`translate(${x5} ${y5}) rotate(${-rotation4})`:`translate(${x5} ${y5})`,innerTransform=rotation4?`translate(${x5} ${y5}) rotate(${-rotation4})`:`translate(${x5} ${y5})`,createPillPath=(width,height)=>{if(width>height){let radius=height/2,straightLength=width-2*radius;return`M${-width/2+radius},${-radius} h${straightLength} a${radius},${radius} 0 0 1 0,${height} h${-straightLength} a${radius},${radius} 0 0 1 0,${-height} z`}else if(height>width){let radius=width/2,straightLength=height-2*radius;return`M${radius},${-height/2+radius} v${straightLength} a${radius},${radius} 0 0 1 ${-width},0 v${-straightLength} a${radius},${radius} 0 0 1 ${width},0 z`}else{let radius=width/2;return`M${-radius},0 a${radius},${radius} 0 0 1 ${width},0 a${radius},${radius} 0 0 1 ${-width},0 z`}},children=[{name:"path",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,d:createPillPath(scaledOuterWidth,scaledOuterHeight),transform:outerTransform,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"path",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,d:createPillPath(scaledHoleWidth,scaledHoleHeight),transform:innerTransform,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledOuterWidth+2*soldermaskMargin,maskHeight=scaledOuterHeight+2*soldermaskMargin;soldermaskMargin<0?children=[{name:"path",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,d:createPillPath(scaledOuterWidth,scaledOuterHeight),transform:outerTransform,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"path",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,d:createPillPath(maskWidth,maskHeight),transform:outerTransform,"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"path",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,d:createPillPath(maskWidth,maskHeight),transform:outerTransform,"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="oval"){let scaledOuterWidth=hole.outer_width*Math.abs(transform5.a),scaledOuterHeight=hole.outer_height*Math.abs(transform5.a),scaledHoleWidth=hole.hole_width*Math.abs(transform5.a),scaledHoleHeight=hole.hole_height*Math.abs(transform5.a),rotation4=hole.ccw_rotation||0,transformStr=rotation4?`translate(${x5} ${y5}) rotate(${-rotation4})`:`translate(${x5} ${y5})`,children=[{name:"ellipse",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,cx:"0",cy:"0",rx:(scaledOuterWidth/2).toString(),ry:(scaledOuterHeight/2).toString(),transform:transformStr,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"ellipse",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:"0",cy:"0",rx:(scaledHoleWidth/2).toString(),ry:(scaledHoleHeight/2).toString(),transform:transformStr,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="circle"){let scaledOuterWidth=hole.outer_diameter*Math.abs(transform5.a),scaledOuterHeight=hole.outer_diameter*Math.abs(transform5.a),scaledHoleWidth=hole.hole_diameter*Math.abs(transform5.a),scaledHoleHeight=hole.hole_diameter*Math.abs(transform5.a),outerRadius=Math.min(scaledOuterWidth,scaledOuterHeight)/2,innerRadius=Math.min(scaledHoleWidth,scaledHoleHeight)/2,children=[{name:"circle",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,cx:x5.toString(),cy:y5.toString(),r:outerRadius.toString(),"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:x5.toString(),cy:y5.toString(),r:innerRadius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskRadius=outerRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"circle",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,cx:x5.toString(),cy:y5.toString(),r:outerRadius.toString(),"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"circle",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="circular_hole_with_rect_pad"){let h4=hole,scaledHoleDiameter=hole.hole_diameter*Math.abs(transform5.a),scaledRectPadWidth=hole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=hole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(hole.rect_border_radius??0)*Math.abs(transform5.a),holeRadius=scaledHoleDiameter/2,[holeCx,holeCy]=applyToPoint3(transform5,[h4.x+(h4.hole_offset_x??0),h4.y+(h4.hole_offset_y??0)]),children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:holeCx.toString(),cy:holeCy.toString(),r:holeRadius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledRectPadWidth+2*soldermaskMargin,maskHeight=scaledRectPadHeight+2*soldermaskMargin,maskBorderRadius=scaledRectBorderRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"rect",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...scaledRectBorderRadius?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="pill_hole_with_rect_pad"){let pillHole=hole,scaledRectPadWidth=pillHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=pillHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(pillHole.rect_border_radius??0)*Math.abs(transform5.a),scaledHoleHeight=pillHole.hole_height*Math.abs(transform5.a),scaledHoleWidth=pillHole.hole_width*Math.abs(transform5.a),pillHoleWithOffsets=pillHole,holeOffsetX=pillHoleWithOffsets.hole_offset_x??0,holeOffsetY=pillHoleWithOffsets.hole_offset_y??0,[holeCenterX,holeCenterY]=applyToPoint3(transform5,[pillHole.x+holeOffsetX,pillHole.y+holeOffsetY]),holeRadius=Math.min(scaledHoleHeight,scaledHoleWidth)/2,children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,x:(holeCenterX-scaledHoleWidth/2).toString(),y:(holeCenterY-scaledHoleHeight/2).toString(),width:scaledHoleWidth.toString(),height:scaledHoleHeight.toString(),rx:holeRadius.toString(),ry:holeRadius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledRectPadWidth+2*soldermaskMargin,maskHeight=scaledRectPadHeight+2*soldermaskMargin,maskBorderRadius=scaledRectBorderRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.unshift({name:"rect",type:"element",attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...scaledRectBorderRadius?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask_opening","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="rotated_pill_hole_with_rect_pad"){let rotatedHole=hole,scaledRectPadWidth=rotatedHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=rotatedHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(rotatedHole.rect_border_radius??0)*Math.abs(transform5.a),scaledHoleHeight=rotatedHole.hole_height*Math.abs(transform5.a),scaledHoleWidth=rotatedHole.hole_width*Math.abs(transform5.a),rotatedHoleWithOffsets=rotatedHole,holeOffsetX=rotatedHoleWithOffsets.hole_offset_x??0,holeOffsetY=rotatedHoleWithOffsets.hole_offset_y??0,[holeCenterX,holeCenterY]=applyToPoint3(transform5,[rotatedHole.x+holeOffsetX,rotatedHole.y+holeOffsetY]),holeRadius=Math.min(scaledHoleHeight,scaledHoleWidth)/2,children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,x:(-scaledRectPadWidth/2).toString(),y:(-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,x:(-scaledHoleWidth/2).toString(),y:(-scaledHoleHeight/2).toString(),width:scaledHoleWidth.toString(),height:scaledHoleHeight.toString(),rx:holeRadius.toString(),ry:holeRadius.toString(),transform:`translate(${holeCenterX} ${holeCenterY}) rotate(${-rotatedHole.hole_ccw_rotation})`,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}];if(shouldShowSolderMask){let maskWidth=scaledRectPadWidth+2*soldermaskMargin,maskHeight=scaledRectPadHeight+2*soldermaskMargin,maskBorderRadius=scaledRectBorderRadius+soldermaskMargin;soldermaskMargin<0?children=[{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-covered",fill:solderMaskColor,x:(-scaledRectPadWidth/2).toString(),y:(-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{},"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"pcb-hole-outer-exposed",fill:colorMap2.copper.top,x:(-maskWidth/2).toString(),y:(-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]},children[1]]:children.push({name:"rect",type:"element",attributes:{class:"pcb-solder-mask",fill:solderMaskColor,x:(-maskWidth/2).toString(),y:(-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask","data-pcb-layer":maskLayer},value:"",children:[]})}return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children,value:""}]}if(hole.shape==="hole_with_polygon_pad"){let polygonHole=hole,padOutline=polygonHole.pad_outline||[],holeX=polygonHole.x??0,holeY=polygonHole.y??0,padPointsString=padOutline.map(point6=>applyToPoint3(transform5,[holeX+point6.x,holeY+point6.y])).map(p4=>p4.join(",")).join(" "),[holeCenterX,holeCenterY]=applyToPoint3(transform5,[holeX+polygonHole.hole_offset_x,holeY+polygonHole.hole_offset_y]),createHoleSvgObject=()=>{if(polygonHole.hole_shape==="circle"){let radius=(polygonHole.hole_diameter??0)*Math.abs(transform5.a)/2;return{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:holeCenterX.toString(),cy:holeCenterY.toString(),r:radius.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}}if(polygonHole.hole_shape==="oval"){let scaledWidth=(polygonHole.hole_width??0)*Math.abs(transform5.a),scaledHeight=(polygonHole.hole_height??0)*Math.abs(transform5.a),rx2=scaledWidth/2,ry2=scaledHeight/2;return{name:"ellipse",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:holeCenterX.toString(),cy:holeCenterY.toString(),rx:rx2.toString(),ry:ry2.toString(),"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}}if(polygonHole.hole_shape==="pill"||polygonHole.hole_shape==="rotated_pill"){let scaledWidth=(polygonHole.hole_width??0)*Math.abs(transform5.a),scaledHeight=(polygonHole.hole_height??0)*Math.abs(transform5.a),isHorizontal2=scaledWidth>scaledHeight,radius=Math.min(scaledWidth,scaledHeight)/2,straightLength=Math.abs(isHorizontal2?scaledWidth-scaledHeight:scaledHeight-scaledWidth),pathD=isHorizontal2?`M${-straightLength/2},${-radius} h${straightLength} a${radius},${radius} 0 0 1 0,${scaledHeight} h-${straightLength} a${radius},${radius} 0 0 1 0,-${scaledHeight} z`:`M${-radius},${-straightLength/2} v${straightLength} a${radius},${radius} 0 0 0 ${scaledWidth},0 v-${straightLength} a${radius},${radius} 0 0 0 -${scaledWidth},0 z`;return{name:"path",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,d:pathD,transform:`translate(${holeCenterX} ${holeCenterY})`,"data-type":"pcb_plated_hole_drill","data-pcb-layer":"drill"},value:"",children:[]}}return{name:"g",type:"element",attributes:{},value:"",children:[]}};return[{name:"g",type:"element",attributes:{"data-type":"pcb_plated_hole","data-pcb-layer":"through"},children:[{name:"polygon",type:"element",attributes:{class:"pcb-hole-outer-pad",fill:colorMap2.copper.top,points:padPointsString,"data-type":"pcb_plated_hole","data-pcb-layer":layer},value:"",children:[]},createHoleSvgObject()],value:""}]}return[]}function createSvgObjectsFromPcbSilkscreenPath(silkscreenPath,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx;if(!silkscreenPath.route||!Array.isArray(silkscreenPath.route))return[];let path=silkscreenPath.route.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" "),firstPoint=silkscreenPath.route[0],lastPoint=silkscreenPath.route[silkscreenPath.route.length-1];firstPoint&&lastPoint&&firstPoint.x===lastPoint.x&&firstPoint.y===lastPoint.y&&(path+=" Z");let layer=silkscreenPath.layer||"top";if(layerFilter&&layer!==layerFilter)return[];let color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top;return[{name:"path",type:"element",attributes:{class:`pcb-silkscreen pcb-silkscreen-${layer}`,d:path,fill:"none",stroke:color,"stroke-width":(silkscreenPath.stroke_width*Math.abs(transform5.a)).toString(),"stroke-linecap":"round","stroke-linejoin":"round","data-pcb-component-id":silkscreenPath.pcb_component_id,"data-pcb-silkscreen-path-id":silkscreenPath.pcb_silkscreen_path_id,"data-type":"pcb_silkscreen_path","data-pcb-layer":layer},value:"",children:[]}]}function createSvgObjectsFromPcbSilkscreenText(pcbSilkscreenText,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2,circuitJson}=ctx,{anchor_position,text,font_size=1,layer="top",ccw_rotation=0,anchor_alignment="center"}=pcbSilkscreenText;if(layerFilter&&layer!==layerFilter)return[];if(!anchor_position||typeof anchor_position.x!="number"||typeof anchor_position.y!="number")return console.error("Invalid anchor_position:",anchor_position),[];let[transformedX,transformedY]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),transformedFontSize=font_size*Math.abs(transform5.a),textAnchor="middle",dominantBaseline="central",dx2=0,dy2=0;switch(anchor_alignment){case"top_left":textAnchor="start",dominantBaseline="text-before-edge";break;case"top_center":textAnchor="middle",dominantBaseline="text-before-edge";break;case"top_right":textAnchor="end",dominantBaseline="text-before-edge";break;case"center_left":textAnchor="start",dominantBaseline="central";break;case"center_right":textAnchor="end",dominantBaseline="central";break;case"bottom_left":textAnchor="start",dominantBaseline="text-after-edge";break;case"bottom_center":textAnchor="middle",dominantBaseline="text-after-edge";break;case"bottom_right":textAnchor="end",dominantBaseline="text-after-edge";break;default:textAnchor="middle",dominantBaseline="central";break}let textTransform=compose3(translate3(transformedX,transformedY),rotate3(-ccw_rotation*Math.PI/180),...layer==="bottom"?[scale3(-1,1)]:[]),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top,lines=text.split(`
|
|
272
272
|
`),children=lines.length===1?[{type:"text",value:text,name:"",attributes:{},children:[]}]:lines.map((line2,idx)=>({type:"element",name:"tspan",value:"",attributes:{x:"0",...idx>0?{dy:transformedFontSize.toString()}:{}},children:[{type:"text",value:line2,name:"",attributes:{},children:[]}]}));return[{name:"text",type:"element",attributes:{x:"0",y:"0",dx:dx2.toString(),dy:dy2.toString(),fill:color,"font-family":"Arial, sans-serif","font-size":transformedFontSize.toString(),"text-anchor":textAnchor,"dominant-baseline":dominantBaseline,transform:toString(textTransform),class:`pcb-silkscreen-text pcb-silkscreen-${layer}`,"data-pcb-silkscreen-text-id":pcbSilkscreenText.pcb_component_id,stroke:"none","data-type":"pcb_silkscreen_text","data-pcb-layer":layer},children,value:""}]}function createSvgObjectsFromPcbSilkscreenRect(pcbSilkscreenRect,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{center:center2,width,height,layer="top",pcb_silkscreen_rect_id,stroke_width,is_filled,has_stroke,is_stroke_dashed,corner_radius,ccw_rotation=0}=pcbSilkscreenRect;if(layerFilter&&layer!==layerFilter)return[];if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid rectangle data:",{center:center2,width,height}),[];let[transformedX,transformedY]=applyToPoint3(transform5,[center2.x,center2.y]),baseCornerRadius=typeof corner_radius=="number"&&corner_radius>0?corner_radius:0,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),transformedWidth=width*Math.abs(transform5.a),transformedHeight=height*Math.abs(transform5.d),transformedStrokeWidth=stroke_width*Math.abs(transform5.a),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top,attributes2={x:(-transformedWidth/2).toString(),y:(-transformedHeight/2).toString(),width:transformedWidth.toString(),height:transformedHeight.toString(),class:`pcb-silkscreen-rect pcb-silkscreen-${layer}`,"data-pcb-silkscreen-rect-id":pcb_silkscreen_rect_id,"data-type":"pcb_silkscreen_rect","data-pcb-layer":layer};typeof ccw_rotation=="number"&&ccw_rotation!==0?attributes2.transform=`translate(${transformedX} ${transformedY}) rotate(${-ccw_rotation})`:(attributes2.x=(transformedX-transformedWidth/2).toString(),attributes2.y=(transformedY-transformedHeight/2).toString()),transformedCornerRadiusX>0&&(attributes2.rx=transformedCornerRadiusX.toString()),transformedCornerRadiusY>0&&(attributes2.ry=transformedCornerRadiusY.toString()),attributes2.fill=is_filled?color:"none";let actualHasStroke;if(has_stroke===void 0?actualHasStroke=transformedStrokeWidth>0:actualHasStroke=has_stroke,actualHasStroke){if(attributes2.stroke=color,attributes2["stroke-width"]=transformedStrokeWidth.toString(),is_stroke_dashed){let dashLength=.1*Math.abs(transform5.a),gapLength=.05*Math.abs(transform5.a);attributes2["stroke-dasharray"]=`${dashLength} ${gapLength}`}}else attributes2.stroke="none";return[{name:"rect",type:"element",attributes:attributes2,value:"",children:[]}]}function layerNameToColor(layerName,colorMap2=DEFAULT_PCB_COLOR_MAP){return colorMap2.copper[layerName]??"white"}function solderPasteLayerNameToColor(layerName){return SOLDER_PASTE_LAYER_NAME_TO_COLOR[layerName]??"rgb(105, 105, 105)"}function linesToPathData(lines,offsetX,offsetY,charScale,baselineAdjust=0){return lines.map(line2=>{let x12=offsetX+line2.x1*charScale,y12=offsetY+(1-line2.y1+baselineAdjust)*charScale,x22=offsetX+line2.x2*charScale,y22=offsetY+(1-line2.y2+baselineAdjust)*charScale;return`M${x12} ${y12}L${x22} ${y22}`}).join(" ")}function textToAlphabetPath(text,fontSize){let paths=[],charAdvance=(CHAR_WIDTH+CHAR_SPACING)*fontSize,x5=0;for(let char of text){if(char===" "){x5+=charAdvance*.6;continue}let lines=lineAlphabet[char];lines&&paths.push(linesToPathData(lines,x5,0,fontSize)),x5+=charAdvance}let width=x5>0?x5-CHAR_SPACING*fontSize:0;return{pathData:paths.join(" "),width}}function textToCenteredAlphabetPaths(text,fontSize){let textLines=text.split(`
|
|
273
273
|
`),lineHeight=fontSize*LINE_HEIGHT,totalHeight=textLines.length*lineHeight,lineWidths=[],maxWidth=0;for(let line2 of textLines){let{width}=textToAlphabetPath(line2,fontSize);lineWidths.push(width),width>maxWidth&&(maxWidth=width)}let paths=[],y5=-totalHeight/2;for(let i2=0;i2<textLines.length;i2++){let line2=textLines[i2],lineWidth=lineWidths[i2],charAdvance=(CHAR_WIDTH+CHAR_SPACING)*fontSize,x5=-lineWidth/2;for(let char of line2){if(char===" "){x5+=charAdvance*.6;continue}let charLines=lineAlphabet[char];charLines&&paths.push(linesToPathData(charLines,x5,y5,fontSize)),x5+=charAdvance}y5+=lineHeight}return{pathData:paths.join(" "),width:maxWidth,height:totalHeight}}function createSvgObjectsFromPcbCopperText(pcbCopperText,ctx){let{transform:transform5,layer:filterLayer,colorMap:colorMap2}=ctx,{anchor_position,text,font_size="0.2mm",layer,ccw_rotation=0,anchor_alignment="center",is_knockout=!1,knockout_padding,is_mirrored=!1}=pcbCopperText,layerName=layer??"top";if(filterLayer&&filterLayer!==layerName)return[];if(!anchor_position)return[];let[ax2,ay2]=applyToPoint3(transform5,[anchor_position.x,anchor_position.y]),fontSizeNum=distance.parse(font_size)??.2,scaleFactor=Math.abs(transform5.a),copperColor=layerNameToColor(layerName,colorMap2),applyMirror=layerName==="bottom"?!0:is_mirrored===!0;if(is_knockout){let scaledFontSize2=fontSizeNum*FONT_SCALE,{pathData:pathData2,width:width2,height:height2}=textToCenteredAlphabetPaths(text,scaledFontSize2),padX=knockout_padding?.left??scaledFontSize2*.5,padY=knockout_padding?.top??scaledFontSize2*.3,rectW=width2+padX*2,rectH=height2+padY*2,strokeWidth2=scaledFontSize2*.15,knockoutTransform=toString(compose3(translate3(ax2,ay2),rotate3(-ccw_rotation*Math.PI/180),...applyMirror?[scale3(-1,1)]:[],scale3(scaleFactor,scaleFactor))),maskId=`knockout-mask-${pcbCopperText.pcb_copper_text_id}-${maskIdCounter++}`;return[{name:"defs",type:"element",value:"",children:[{name:"mask",type:"element",value:"",attributes:{id:maskId},children:[{name:"rect",type:"element",value:"",attributes:{x:(-rectW/2).toString(),y:(-rectH/2).toString(),width:rectW.toString(),height:rectH.toString(),fill:"white"},children:[]},{name:"path",type:"element",value:"",attributes:{d:pathData2,fill:"none",stroke:"black","stroke-width":strokeWidth2.toString(),"stroke-linecap":"round","stroke-linejoin":"round"},children:[]}]}],attributes:{}},{name:"rect",type:"element",value:"",children:[],attributes:{x:(-rectW/2).toString(),y:(-rectH/2).toString(),width:rectW.toString(),height:rectH.toString(),fill:copperColor,mask:`url(#${maskId})`,transform:knockoutTransform,class:`pcb-copper-text-knockout pcb-copper-${layerName}`,"data-type":"pcb_copper_text","data-pcb-copper-text-id":pcbCopperText.pcb_copper_text_id}}]}let scaledFontSize=fontSizeNum*FONT_SCALE,{pathData,width,height}=textToCenteredAlphabetPaths(text,scaledFontSize),offsetX=0,offsetY=0;switch(anchor_alignment){case"top_left":offsetX=width/2,offsetY=height/2;break;case"top_center":offsetY=height/2;break;case"top_right":offsetX=-width/2,offsetY=height/2;break;case"center_left":offsetX=width/2;break;case"center_right":offsetX=-width/2;break;case"bottom_left":offsetX=width/2,offsetY=-height/2;break;case"bottom_center":offsetY=-height/2;break;case"bottom_right":offsetX=-width/2,offsetY=-height/2;break}let textTransform=toString(compose3(translate3(ax2,ay2),rotate3(-ccw_rotation*Math.PI/180),...applyMirror?[scale3(-1,1)]:[],translate3(offsetX,offsetY),scale3(scaleFactor,scaleFactor))),strokeWidth=scaledFontSize*.15;return[{name:"path",type:"element",attributes:{d:pathData,fill:"none",stroke:copperColor,"stroke-width":strokeWidth.toString(),"stroke-linecap":"round","stroke-linejoin":"round",transform:textTransform,class:`pcb-copper-text pcb-copper-${layerName}`,"data-type":"pcb_copper_text","data-pcb-copper-text-id":pcbCopperText.pcb_copper_text_id},children:[],value:""}]}function createSvgObjectsFromPcbSilkscreenCircle(pcbSilkscreenCircle,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{center:center2,radius,layer="top",pcb_silkscreen_circle_id,stroke_width=1}=pcbSilkscreenCircle;if(layerFilter&&layer!==layerFilter)return[];if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof radius!="number")return console.error("Invalid PCB Silkscreen Circle data:",{center:center2,radius}),[];let[transformedX,transformedY]=applyToPoint3(transform5,[center2.x,center2.y]),transformedRadius=radius*Math.abs(transform5.a),transformedStrokeWidth=stroke_width*Math.abs(transform5.a),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top;return[{name:"circle",type:"element",attributes:{cx:transformedX.toString(),cy:transformedY.toString(),r:transformedRadius.toString(),class:`pcb-silkscreen-circle pcb-silkscreen-${layer}`,stroke:color,"stroke-width":transformedStrokeWidth.toString(),"data-pcb-silkscreen-circle-id":pcb_silkscreen_circle_id,"data-type":"pcb_silkscreen_circle","data-pcb-layer":layer},value:"",children:[]}]}function createSvgObjectsFromPcbSilkscreenLine(pcbSilkscreenLine,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{x1:x12,y1:y12,x2:x22,y2:y22,stroke_width,layer="top",pcb_silkscreen_line_id}=pcbSilkscreenLine;if(layerFilter&&layer!==layerFilter)return[];if(typeof x12!="number"||typeof y12!="number"||typeof x22!="number"||typeof y22!="number")return console.error("Invalid coordinates:",{x1:x12,y1:y12,x2:x22,y2:y22}),[];let[transformedX1,transformedY1]=applyToPoint3(transform5,[x12,y12]),[transformedX2,transformedY2]=applyToPoint3(transform5,[x22,y22]),transformedStrokeWidth=stroke_width*Math.abs(transform5.a),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top;return[{name:"line",type:"element",attributes:{x1:transformedX1.toString(),y1:transformedY1.toString(),x2:transformedX2.toString(),y2:transformedY2.toString(),stroke:color,"stroke-width":transformedStrokeWidth.toString(),class:`pcb-silkscreen-line pcb-silkscreen-${layer}`,"data-pcb-silkscreen-line-id":pcb_silkscreen_line_id,"data-type":"pcb_silkscreen_line","data-pcb-layer":layer},value:"",children:[]}]}function createSvgObjectsFromPcbSilkscreenPill(pcbSilkscreenPill,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{center:center2,width,height,layer="top",pcb_silkscreen_pill_id}=pcbSilkscreenPill;if(layerFilter&&layer!==layerFilter)return[];let[transformedX,transformedY]=applyToPoint3(transform5,[center2.x,center2.y]),transformedWidth=width*Math.abs(transform5.a),transformedHeight=height*Math.abs(transform5.d),baseCornerRadius=Math.min(width,height)/2,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top;return[{name:"rect",type:"element",attributes:{x:(transformedX-transformedWidth/2).toString(),y:(transformedY-transformedHeight/2).toString(),width:transformedWidth.toString(),height:transformedHeight.toString(),rx:transformedCornerRadiusX.toString(),ry:transformedCornerRadiusY.toString(),fill:"none",stroke:color,"stroke-width":(.1*Math.abs(transform5.a)).toString(),class:`pcb-silkscreen-pill pcb-silkscreen-${layer}`,"data-pcb-silkscreen-pill-id":pcb_silkscreen_pill_id,"data-type":"pcb_silkscreen_pill","data-pcb-layer":layer},value:"",children:[]}]}function createSvgObjectsFromPcbSilkscreenOval(pcbSilkscreenOval,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{center:center2,radius_x,radius_y,layer="top",pcb_silkscreen_oval_id,ccw_rotation=0}=pcbSilkscreenOval;if(layerFilter&&layer!==layerFilter)return[];if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof radius_x!="number"||typeof radius_y!="number")return console.error("Invalid PCB Silkscreen Oval data:",{center:center2,radius_x,radius_y}),[];let[transformedX,transformedY]=applyToPoint3(transform5,[center2.x,center2.y]),transformedRadiusX=radius_x*Math.abs(transform5.a),transformedRadiusY=radius_y*Math.abs(transform5.d),color=layer==="bottom"?colorMap2.silkscreen.bottom:colorMap2.silkscreen.top;return[{name:"ellipse",type:"element",attributes:{cx:transformedX.toString(),cy:transformedY.toString(),rx:transformedRadiusX.toString(),ry:transformedRadiusY.toString(),fill:"none",stroke:color,"stroke-width":(.1*Math.abs(transform5.a)).toString(),class:`pcb-silkscreen-oval pcb-silkscreen-${layer}`,"data-pcb-silkscreen-oval-id":pcb_silkscreen_oval_id,"data-type":"pcb_silkscreen_oval","data-pcb-layer":layer,...ccw_rotation!==0&&{transform:`rotate(${-ccw_rotation} ${transformedX} ${transformedY})`}},value:"",children:[]}]}function createSvgObjectsFromPcbCourtyardRect(pcbCourtyardRect,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{center:center2,width,height,layer="top",pcb_courtyard_rect_id}=pcbCourtyardRect;if(layerFilter&&layer!==layerFilter)return[];if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid courtyard rectangle data:",{center:center2,width,height}),[];let[transformedX,transformedY]=applyToPoint3(transform5,[center2.x,center2.y]),transformedWidth=width*Math.abs(transform5.a),transformedHeight=height*Math.abs(transform5.d),transformedStrokeWidth=.05*Math.abs(transform5.a),color=colorMap2.courtyard,attributes2={x:(transformedX-transformedWidth/2).toString(),y:(transformedY-transformedHeight/2).toString(),width:transformedWidth.toString(),height:transformedHeight.toString(),class:`pcb-courtyard-rect pcb-courtyard-${layer}`,"data-pcb-courtyard-rect-id":pcb_courtyard_rect_id,"data-type":"pcb_courtyard_rect","data-pcb-layer":layer};return attributes2.fill="none",attributes2.stroke=color,attributes2["stroke-width"]=transformedStrokeWidth.toString(),[{name:"rect",type:"element",attributes:attributes2,value:"",children:[]}]}function createSvgObjectsFromPcbCourtyardPolygon(pcbCourtyardPolygon,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx,{layer="top",pcb_courtyard_polygon_id,points,color}=pcbCourtyardPolygon;if(layerFilter&&layer!==layerFilter)return[];if(!points||points.length===0)return console.error("Invalid courtyard polygon data: no points",{pcb_courtyard_polygon_id}),[];let pointsString=points.map(p4=>applyToPoint3(transform5,[p4.x,p4.y])).map(p4=>`${p4[0]},${p4[1]}`).join(" "),transformedStrokeWidth=.05*Math.abs(transform5.a),strokeColor=color??colorMap2.courtyard;return[{name:"polygon",type:"element",attributes:{points:pointsString,class:`pcb-courtyard-polygon pcb-courtyard-${layer}`,"data-pcb-courtyard-polygon-id":pcb_courtyard_polygon_id,"data-type":"pcb_courtyard_polygon","data-pcb-layer":layer,fill:"none",stroke:strokeColor,"stroke-width":transformedStrokeWidth.toString()},value:"",children:[]}]}function pairs(arr){let result=[];for(let i2=0;i2<arr.length-1;i2++)result.push([arr[i2],arr[i2+1]]);return result}function createSvgObjectsFromPcbTrace(trace,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2,showSolderMask}=ctx;if(!trace.route||!Array.isArray(trace.route)||trace.route.length<2)return[];let segments=pairs(trace.route),svgObjects=[];for(let[start,end]of segments){let startPoint=applyToPoint3(transform5,[start.x,start.y]),endPoint=applyToPoint3(transform5,[end.x,end.y]),layer="layer"in start?start.layer:"layer"in end?end.layer:null;if(!layer||layerFilter&&layer!==layerFilter)continue;let maskLayer=layer,copperColor=layerNameToColor(layer,colorMap2),maskColor=colorMap2.soldermaskWithCopperUnderneath[layer],traceWidth="width"in start?start.width:"width"in end?end.width:null,width=traceWidth?(traceWidth*Math.abs(transform5.a)).toString():"0.3";if(showSolderMask){let maskObject={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask",stroke:maskColor,fill:"none",d:`M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,"stroke-width":width,"stroke-linecap":"round","stroke-linejoin":"round","shape-rendering":"crispEdges","data-type":"pcb_trace_soldermask","data-pcb-layer":layer}};svgObjects.push(maskObject)}else{let maskOnlyObject={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-trace",stroke:copperColor,fill:"none",d:`M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,"stroke-width":width,"stroke-linecap":"round","stroke-linejoin":"round","shape-rendering":"crispEdges","data-type":showSolderMask?"pcb_soldermask":"pcb_trace","data-pcb-layer":layer}};svgObjects.push(maskOnlyObject)}}return svgObjects}function createSvgObjectsFromSmtPad(pad2,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2,showSolderMask}=ctx;if(layerFilter&&pad2.layer!==layerFilter)return[];let isCoveredWithSolderMask=!!pad2?.is_covered_with_solder_mask,shouldShowSolderMask=showSolderMask&&isCoveredWithSolderMask,soldermaskWithCopperUnderneathColor=colorMap2.soldermaskWithCopperUnderneath[pad2.layer]??colorMap2.soldermaskWithCopperUnderneath.top,soldermaskMargin=(pad2.soldermask_margin??0)*Math.abs(transform5.a);if(pad2.shape==="rect"||pad2.shape==="rotated_rect"){let width=pad2.width*Math.abs(transform5.a),height=pad2.height*Math.abs(transform5.d),[x5,y5]=applyToPoint3(transform5,[pad2.x,pad2.y]),scaledBorderRadius=(pad2.corner_radius??pad2.rect_border_radius??0)*Math.abs(transform5.a),m3={left:(pad2.soldermask_margin_left??pad2.soldermask_margin??0)*Math.abs(transform5.a),right:(pad2.soldermask_margin_right??pad2.soldermask_margin??0)*Math.abs(transform5.a),top:(pad2.soldermask_margin_top??pad2.soldermask_margin??0)*Math.abs(transform5.a),bottom:(pad2.soldermask_margin_bottom??pad2.soldermask_margin??0)*Math.abs(transform5.a)},isNegativeMargin=m3.left<0||m3.right<0||m3.top<0||m3.bottom<0,isZeroMargin=m3.left===0&&m3.right===0&&m3.top===0&&m3.bottom===0;if(pad2.shape==="rotated_rect"&&pad2.ccw_rotation){let padElement2={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad",fill:layerNameToColor(pad2.layer,colorMap2),x:(-width/2).toString(),y:(-height/2).toString(),width:width.toString(),height:height.toString(),transform:`translate(${x5} ${y5}) rotate(${-pad2.ccw_rotation})`,"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}}};if(!shouldShowSolderMask)return[padElement2];let maskWidth2=width+m3.left+m3.right,maskHeight2=height+m3.top+m3.bottom,maskBorderRadius2=scaledBorderRadius?scaledBorderRadius+soldermaskMargin:0;if(isNegativeMargin){let coveredPadElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,x:(-width/2).toString(),y:(-height/2).toString(),width:width.toString(),height:height.toString(),transform:`translate(${x5} ${y5}) rotate(${-pad2.ccw_rotation})`,"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}}},exposedOpeningElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-exposed",fill:layerNameToColor(pad2.layer,colorMap2),x:(-width/2-m3.left).toString(),y:(-height/2-m3.top).toString(),width:maskWidth2.toString(),height:maskHeight2.toString(),transform:`translate(${x5} ${y5}) rotate(${-pad2.ccw_rotation})`,"data-type":"pcb_soldermask","data-pcb-layer":pad2.layer,...maskBorderRadius2>0?{rx:maskBorderRadius2.toString(),ry:maskBorderRadius2.toString()}:{}}};return[coveredPadElement,exposedOpeningElement]}return isZeroMargin?[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,x:(-width/2).toString(),y:(-height/2).toString(),width:width.toString(),height:height.toString(),transform:`translate(${x5} ${y5}) rotate(${-pad2.ccw_rotation})`,"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}}}]:[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(-width/2-m3.left).toString(),y:(-height/2-m3.top).toString(),width:maskWidth2.toString(),height:maskHeight2.toString(),transform:`translate(${x5} ${y5}) rotate(${-pad2.ccw_rotation})`,...maskBorderRadius2>0?{rx:maskBorderRadius2.toString(),ry:maskBorderRadius2.toString()}:{},"data-type":"pcb_soldermask_opening","data-pcb-layer":pad2.layer}},padElement2]}let padElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad",fill:layerNameToColor(pad2.layer,colorMap2),x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}}};if(!shouldShowSolderMask)return[padElement];let maskWidth=width+m3.left+m3.right,maskHeight=height+m3.top+m3.bottom,maskBorderRadius=scaledBorderRadius?scaledBorderRadius+soldermaskMargin:0;if(isNegativeMargin){let coveredPadElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}}},exposedOpeningElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-exposed",fill:layerNameToColor(pad2.layer,colorMap2),x:(x5-width/2-m3.left).toString(),y:(y5-height/2-m3.top).toString(),width:maskWidth.toString(),height:maskHeight.toString(),"data-type":"pcb_soldermask","data-pcb-layer":pad2.layer,...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{}}};return[coveredPadElement,exposedOpeningElement]}return isZeroMargin?[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),...maskBorderRadius>0?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{},"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}}]:[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-width/2-m3.left).toString(),y:(y5-height/2-m3.top).toString(),width:maskWidth.toString(),height:maskHeight.toString(),...maskBorderRadius>0?{rx:maskBorderRadius.toString(),ry:maskBorderRadius.toString()}:{},"data-type":"pcb_soldermask_opening","data-pcb-layer":pad2.layer}},padElement]}if(pad2.shape==="pill"||pad2.shape==="rotated_pill"){let isRotated=pad2.shape==="rotated_pill",width=pad2.width*Math.abs(transform5.a),height=pad2.height*Math.abs(transform5.d),radius=pad2.radius*Math.abs(transform5.a),[x5,y5]=applyToPoint3(transform5,[pad2.x,pad2.y]),rotationTransformAttributes=isRotated?{transform:`translate(${x5} ${y5}) rotate(${-(pad2.ccw_rotation??0)})`}:void 0,baseAttributes={class:"pcb-pad",fill:layerNameToColor(pad2.layer,colorMap2),x:isRotated?(-width/2).toString():(x5-width/2).toString(),y:isRotated?(-height/2).toString():(y5-height/2).toString(),width:width.toString(),height:height.toString(),rx:radius.toString(),ry:radius.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...rotationTransformAttributes??{}},padElement={name:"rect",type:"element",value:"",children:[],attributes:baseAttributes};if(!shouldShowSolderMask)return[padElement];let maskWidth=width+2*soldermaskMargin,maskHeight=height+2*soldermaskMargin,maskRadius=radius+soldermaskMargin;if(soldermaskMargin<0){let coveredPadElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,x:isRotated?(-width/2).toString():(x5-width/2).toString(),y:isRotated?(-height/2).toString():(y5-height/2).toString(),width:width.toString(),height:height.toString(),rx:radius.toString(),ry:radius.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...rotationTransformAttributes??{}}},exposedAttributes={class:"pcb-pad-exposed",fill:layerNameToColor(pad2.layer,colorMap2),x:isRotated?(-maskWidth/2).toString():(x5-maskWidth/2).toString(),y:isRotated?(-maskHeight/2).toString():(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),rx:maskRadius.toString(),ry:maskRadius.toString(),"data-type":"pcb_soldermask","data-pcb-layer":pad2.layer,...rotationTransformAttributes??{}};return[coveredPadElement,{name:"rect",type:"element",value:"",children:[],attributes:exposedAttributes}]}if(soldermaskMargin===0)return[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,x:isRotated?(-width/2).toString():(x5-width/2).toString(),y:isRotated?(-height/2).toString():(y5-height/2).toString(),width:width.toString(),height:height.toString(),rx:radius.toString(),ry:radius.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer,...rotationTransformAttributes??{}}}];let substrateAttributes={class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:isRotated?(-maskWidth/2).toString():(x5-maskWidth/2).toString(),y:isRotated?(-maskHeight/2).toString():(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),rx:maskRadius.toString(),ry:maskRadius.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":pad2.layer,...rotationTransformAttributes??{}};return[{name:"rect",type:"element",value:"",children:[],attributes:substrateAttributes},padElement]}if(pad2.shape==="circle"){let radius=pad2.radius*Math.abs(transform5.a),[x5,y5]=applyToPoint3(transform5,[pad2.x,pad2.y]),padElement={name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-pad",fill:layerNameToColor(pad2.layer,colorMap2),cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}};if(!shouldShowSolderMask)return[padElement];let maskRadius=radius+soldermaskMargin;if(soldermaskMargin<0){let coveredPadElement={name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}},exposedOpeningElement={name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-pad-exposed",fill:layerNameToColor(pad2.layer,colorMap2),cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask","data-pcb-layer":pad2.layer}};return[coveredPadElement,exposedOpeningElement]}return soldermaskMargin===0?[{name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}}]:[{name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":pad2.layer}},padElement]}if(pad2.shape==="polygon"){let points=(pad2.points??[]).map(point6=>applyToPoint3(transform5,[point6.x,point6.y])),padElement={name:"polygon",type:"element",value:"",children:[],attributes:{class:"pcb-pad",fill:layerNameToColor(pad2.layer,colorMap2),points:points.map(p4=>p4.join(",")).join(" "),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}};if(!shouldShowSolderMask)return[padElement];let maskPoints=points;if(soldermaskMargin!==0){let centroidX=points.reduce((sum,p4)=>sum+p4[0],0)/points.length,centroidY=points.reduce((sum,p4)=>sum+p4[1],0)/points.length;maskPoints=points.map(([px2,py2])=>{let dx2=px2-centroidX,dy2=py2-centroidY,distance62=Math.sqrt(dx2*dx2+dy2*dy2);if(distance62===0)return[px2,py2];let normalizedDx=dx2/distance62,normalizedDy=dy2/distance62;return[px2+normalizedDx*soldermaskMargin,py2+normalizedDy*soldermaskMargin]})}if(soldermaskMargin<0){let coveredPadElement={name:"polygon",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,points:points.map(p4=>p4.join(",")).join(" "),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}},exposedOpeningElement={name:"polygon",type:"element",value:"",children:[],attributes:{class:"pcb-pad-exposed",fill:layerNameToColor(pad2.layer,colorMap2),points:maskPoints.map(p4=>p4.join(",")).join(" "),"data-type":"pcb_soldermask","data-pcb-layer":pad2.layer}};return[coveredPadElement,exposedOpeningElement]}return soldermaskMargin===0?[{name:"polygon",type:"element",value:"",children:[],attributes:{class:"pcb-pad-covered",fill:soldermaskWithCopperUnderneathColor,points:points.map(p4=>p4.join(",")).join(" "),"data-type":"pcb_smtpad","data-pcb-layer":pad2.layer}}]:[{name:"polygon",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,points:maskPoints.map(p4=>p4.join(",")).join(" "),"data-type":"pcb_soldermask_opening","data-pcb-layer":pad2.layer}},padElement]}return[]}function createAnchorOffsetIndicators(params){let{groupAnchorPosition,componentPosition,transform:transform5,componentWidth=0,componentHeight=0,displayXOffset,displayYOffset}=params,objects=[],[screenGroupAnchorX,screenGroupAnchorY]=applyToPoint3(transform5,[groupAnchorPosition.x,groupAnchorPosition.y]),[screenComponentX,screenComponentY]=applyToPoint3(transform5,[componentPosition.x,componentPosition.y]),offsetX=componentPosition.x-groupAnchorPosition.x,offsetY=componentPosition.y-groupAnchorPosition.y,scale10=Math.abs(transform5.a),screenComponentWidth=componentWidth*scale10,screenComponentHeight=componentHeight*scale10;objects.push(createAnchorMarker(screenGroupAnchorX,screenGroupAnchorY));let trimmedConnector=getTrimmedConnectorLine(screenGroupAnchorX,screenGroupAnchorY,screenComponentX,screenComponentY);objects.push({name:"line",type:"element",attributes:{x1:trimmedConnector.x1.toString(),y1:trimmedConnector.y1.toString(),x2:trimmedConnector.x2.toString(),y2:trimmedConnector.y2.toString(),stroke:"#ffffff","stroke-width":"0.5","stroke-dasharray":"3,3",opacity:"0.5",class:"anchor-offset-connector"},children:[],value:""}),objects.push({name:"circle",type:"element",attributes:{cx:screenComponentX.toString(),cy:screenComponentY.toString(),r:COMPONENT_ANCHOR_MARKER_RADIUS_PX.toString(),fill:"#ffffff",opacity:"0.7",class:"anchor-offset-component-marker"},children:[],value:""});let yDistance=Math.abs(screenComponentY-screenGroupAnchorY),xDistance=Math.abs(screenComponentX-screenGroupAnchorX),totalDistance=Math.sqrt(xDistance*xDistance+yDistance*yDistance),componentHeightOffset=screenComponentHeight/2+COMPONENT_GAP_PX,dynamicOffset=Math.max(componentHeightOffset,Math.min(MAX_OFFSET_PX,totalDistance*DISTANCE_MULTIPLIER)),horizontalLineY=offsetY>0?screenComponentY-dynamicOffset:screenComponentY+dynamicOffset,componentWidthOffset=screenComponentWidth/2+COMPONENT_SIDE_GAP_PX,verticalLineX=offsetX>0?screenComponentX+componentWidthOffset:screenComponentX-componentWidthOffset;if(isTooCloseToAnchor(horizontalLineY,screenGroupAnchorY)||isTooCloseToAnchor(horizontalLineY,screenComponentY)){let minY=Math.min(screenGroupAnchorY,screenComponentY),maxY=Math.max(screenGroupAnchorY,screenComponentY),candidateAbove=minY-DIMENSION_ANCHOR_CLEARANCE_PX,candidateBelow=maxY+DIMENSION_ANCHOR_CLEARANCE_PX;horizontalLineY=Math.abs(horizontalLineY-candidateAbove)<Math.abs(horizontalLineY-candidateBelow)?candidateAbove:candidateBelow}if(isTooCloseToAnchor(verticalLineX,screenGroupAnchorX)||isTooCloseToAnchor(verticalLineX,screenComponentX)){let minX=Math.min(screenGroupAnchorX,screenComponentX),maxX=Math.max(screenGroupAnchorX,screenComponentX),candidateLeft=minX-DIMENSION_ANCHOR_CLEARANCE_PX,candidateRight=maxX+DIMENSION_ANCHOR_CLEARANCE_PX;verticalLineX=Math.abs(verticalLineX-candidateLeft)<Math.abs(verticalLineX-candidateRight)?candidateLeft:candidateRight}return Math.abs(offsetX)>OFFSET_THRESHOLD_MM&&objects.push(...createHorizontalDimension({startX:screenGroupAnchorX,endX:screenComponentX,y:horizontalLineY,offsetMm:offsetX,offsetY,displayOffset:displayXOffset})),Math.abs(offsetY)>OFFSET_THRESHOLD_MM&&objects.push(...createVerticalDimension({x:verticalLineX,startY:screenGroupAnchorY,endY:screenComponentY,offsetMm:offsetY,offsetX,displayOffset:displayYOffset})),objects}function getTrimmedConnectorLine(x12,y12,x22,y22){let dx2=x22-x12,dy2=y22-y12,distance62=Math.hypot(dx2,dy2),totalTrim=CONNECTOR_GROUP_GAP_PX+CONNECTOR_COMPONENT_GAP_PX;if(!(distance62>totalTrim))return{x1:x12,y1:y12,x2:x22,y2:y22};let ux2=dx2/distance62,uy2=dy2/distance62;return{x1:x12+ux2*CONNECTOR_GROUP_GAP_PX,y1:y12+uy2*CONNECTOR_GROUP_GAP_PX,x2:x22-ux2*CONNECTOR_COMPONENT_GAP_PX,y2:y22-uy2*CONNECTOR_COMPONENT_GAP_PX}}function isTooCloseToAnchor(value,anchorValue){return Math.abs(value-anchorValue)<DIMENSION_ANCHOR_CLEARANCE_PX}function createAnchorMarker(x5,y5){return{name:"g",type:"element",attributes:{class:"anchor-offset-marker","data-type":"anchor_offset_marker"},children:[{name:"line",type:"element",attributes:{x1:x5.toString(),y1:(y5-ANCHOR_MARKER_SIZE_PX).toString(),x2:x5.toString(),y2:(y5+ANCHOR_MARKER_SIZE_PX).toString(),stroke:"#ffffff","stroke-width":ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),"stroke-linecap":"round"},children:[],value:""},{name:"line",type:"element",attributes:{x1:(x5-ANCHOR_MARKER_SIZE_PX).toString(),y1:y5.toString(),x2:(x5+ANCHOR_MARKER_SIZE_PX).toString(),y2:y5.toString(),stroke:"#ffffff","stroke-width":ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),"stroke-linecap":"round"},children:[],value:""}],value:""}}function createHorizontalDimension({startX,endX,y:y5,offsetMm,offsetY,displayOffset}){let objects=[];objects.push({name:"line",type:"element",attributes:{x1:startX.toString(),y1:y5.toString(),x2:endX.toString(),y2:y5.toString(),stroke:"#ffffff","stroke-width":STROKE_WIDTH_PX.toString(),class:"anchor-offset-dimension-x"},children:[],value:""}),objects.push({name:"line",type:"element",attributes:{x1:startX.toString(),y1:(y5-TICK_SIZE_PX).toString(),x2:startX.toString(),y2:(y5+TICK_SIZE_PX).toString(),stroke:"#ffffff","stroke-width":STROKE_WIDTH_PX.toString()},children:[],value:""}),objects.push({name:"line",type:"element",attributes:{x1:endX.toString(),y1:(y5-TICK_SIZE_PX).toString(),x2:endX.toString(),y2:(y5+TICK_SIZE_PX).toString(),stroke:"#ffffff","stroke-width":STROKE_WIDTH_PX.toString()},children:[],value:""});let midX=(startX+endX)/2,labelY=offsetY>0?y5-TICK_SIZE_PX-LABEL_GAP_PX:y5+TICK_SIZE_PX+LABEL_GAP_PX;return objects.push({name:"text",type:"element",attributes:{x:midX.toString(),y:labelY.toString(),fill:"#ffffff","font-size":LABEL_FONT_SIZE_PX.toString(),"font-family":"Arial, sans-serif","text-anchor":"middle","dominant-baseline":offsetY>0?"baseline":"hanging",class:"anchor-offset-label"},children:[{type:"text",value:formatOffsetLabel("X",offsetMm,displayOffset),name:"",attributes:{},children:[]}],value:""}),objects}function createVerticalDimension({x:x5,startY,endY,offsetMm,offsetX,displayOffset}){let objects=[];objects.push({name:"line",type:"element",attributes:{x1:x5.toString(),y1:startY.toString(),x2:x5.toString(),y2:endY.toString(),stroke:"#ffffff","stroke-width":STROKE_WIDTH_PX.toString(),class:"anchor-offset-dimension-y"},children:[],value:""}),objects.push({name:"line",type:"element",attributes:{x1:(x5-TICK_SIZE_PX).toString(),y1:startY.toString(),x2:(x5+TICK_SIZE_PX).toString(),y2:startY.toString(),stroke:"#ffffff","stroke-width":STROKE_WIDTH_PX.toString()},children:[],value:""}),objects.push({name:"line",type:"element",attributes:{x1:(x5-TICK_SIZE_PX).toString(),y1:endY.toString(),x2:(x5+TICK_SIZE_PX).toString(),y2:endY.toString(),stroke:"#ffffff","stroke-width":STROKE_WIDTH_PX.toString()},children:[],value:""});let midY=(startY+endY)/2,labelX=offsetX<0?x5-TICK_SIZE_PX-4:x5+TICK_SIZE_PX+4;return objects.push({name:"text",type:"element",attributes:{x:labelX.toString(),y:midY.toString(),fill:"#ffffff","font-size":LABEL_FONT_SIZE_PX.toString(),"font-family":"Arial, sans-serif","text-anchor":offsetX<0?"end":"start","dominant-baseline":"middle",class:"anchor-offset-label"},children:[{type:"text",value:formatOffsetLabel("Y",offsetMm,displayOffset),name:"",attributes:{},children:[]}],value:""}),objects}function formatOffsetLabel(axis,offsetMm,displayOffset){let valueStr=typeof displayOffset=="string"?displayOffset:offsetMm.toFixed(2),unitSuffix=typeof valueStr=="string"&&valueStr.trim().endsWith("mm")?"":"mm";return`${axis}: ${valueStr}${unitSuffix}`}function getPointFromElm(elm){let candidate=elm?.anchor_position??elm?.center;if(candidate&&typeof candidate.x=="number"&&typeof candidate.y=="number")return{x:candidate.x,y:candidate.y}}function createSvgObjectsFromPcbBoard(pcbBoard,ctx){let{transform:transform5,colorMap:colorMap2,showSolderMask,circuitJson}=ctx,{width,height,center:center2,outline,position_mode,anchor_position:boardAnchorPosition,display_offset_x,display_offset_y}=pcbBoard,path;if(outline&&Array.isArray(outline)&&outline.length>=3)path=outline.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" ");else{let halfWidth=width/2,halfHeight=height/2,topLeft=applyToPoint3(transform5,[center2.x-halfWidth,center2.y-halfHeight]),topRight=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),bottomRight=applyToPoint3(transform5,[center2.x+halfWidth,center2.y+halfHeight]),bottomLeft=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]);path=`M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`}path+=" Z";let svgObjects=[];if(showSolderMask){let maskLayer=(ctx.layer??"top")==="bottom"?"soldermask-bottom":"soldermask-top";svgObjects.push({name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-board-soldermask",d:path,fill:colorMap2.soldermask.top,"fill-opacity":"0.8",stroke:"none","data-type":"pcb_soldermask","data-pcb-layer":maskLayer}})}if(svgObjects.push({name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-board",d:path,fill:"none",stroke:colorMap2.boardOutline,"stroke-width":(.1*Math.abs(transform5.a)).toString(),"data-type":"pcb_board","data-pcb-layer":"board"}}),ctx.showAnchorOffsets&&circuitJson&&position_mode==="relative_to_panel_anchor"){let panel=circuitJson.find(elm=>elm.type==="pcb_panel");if(panel){let panelAnchorPosition=getPointFromElm(panel);panelAnchorPosition&&svgObjects.push(...createAnchorOffsetIndicators({groupAnchorPosition:panelAnchorPosition,componentPosition:boardAnchorPosition??center2,transform:transform5,componentWidth:width,componentHeight:height,displayXOffset:display_offset_x,displayYOffset:display_offset_y}))}}return svgObjects}function createSvgObjectsFromPcbPanel(pcbPanel,ctx){let{transform:transform5,colorMap:colorMap2,showSolderMask}=ctx,width=Number(pcbPanel.width),height=Number(pcbPanel.height),center2=pcbPanel.center??{x:width/2,y:height/2},halfWidth=width/2,halfHeight=height/2,topLeft=applyToPoint3(transform5,[center2.x-halfWidth,center2.y-halfHeight]),topRight=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),bottomRight=applyToPoint3(transform5,[center2.x+halfWidth,center2.y+halfHeight]),bottomLeft=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]),path=`M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]} Z`,isCoveredWithSolderMask=pcbPanel.covered_with_solder_mask!==!1,shouldShowSolderMask=!!(showSolderMask&&isCoveredWithSolderMask);return[{name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-panel",d:path,fill:"none",stroke:colorMap2.boardOutline,"stroke-width":(.1*Math.abs(transform5.a)).toString(),"data-type":"pcb_panel","data-pcb-layer":"board"}}]}function createSvgObjectsFromPcbVia(hole,ctx){let{transform:transform5,colorMap:colorMap2}=ctx,[x5,y5]=applyToPoint3(transform5,[hole.x,hole.y]),scaledOuterWidth=hole.outer_diameter*Math.abs(transform5.a),scaledOuterHeight=hole.outer_diameter*Math.abs(transform5.a),scaledHoleWidth=hole.hole_diameter*Math.abs(transform5.a),scaledHoleHeight=hole.hole_diameter*Math.abs(transform5.a),outerRadius=Math.min(scaledOuterWidth,scaledOuterHeight)/2,innerRadius=Math.min(scaledHoleWidth,scaledHoleHeight)/2;return{name:"g",type:"element",attributes:{"data-type":"pcb_via","data-pcb-layer":"through"},children:[{name:"circle",type:"element",attributes:{class:"pcb-hole-outer",fill:colorMap2.copper.top,cx:x5.toString(),cy:y5.toString(),r:outerRadius.toString(),"data-type":"pcb_via","data-pcb-layer":"top"}},{name:"circle",type:"element",attributes:{class:"pcb-hole-inner",fill:colorMap2.drill,cx:x5.toString(),cy:y5.toString(),r:innerRadius.toString(),"data-type":"pcb_via","data-pcb-layer":"drill"}}]}}function createSvgObjectsFromPcbHole(hole,ctx){let{transform:transform5,colorMap:colorMap2,showSolderMask}=ctx,layer=ctx.layer??"top",[x5,y5]=applyToPoint3(transform5,[hole.x,hole.y]),isCoveredWithSolderMask=!!hole.is_covered_with_solder_mask,soldermaskMargin=(hole.soldermask_margin??0)*Math.abs(transform5.a),shouldShowSolderMask=showSolderMask&&isCoveredWithSolderMask&&soldermaskMargin!==0,solderMaskColor=colorMap2.soldermask.top;if(hole.hole_shape==="circle"||hole.hole_shape==="square"){let scaledDiameter=hole.hole_diameter*Math.abs(transform5.a),radius=scaledDiameter/2;if(hole.hole_shape==="circle"){let holeElement2={name:"circle",type:"element",attributes:{class:"pcb-hole",cx:x5.toString(),cy:y5.toString(),r:radius.toString(),fill:colorMap2.drill,"data-type":"pcb_hole","data-pcb-layer":"drill"},children:[],value:""};if(!shouldShowSolderMask)return[holeElement2];let maskRadius=radius+soldermaskMargin;if(soldermaskMargin<0){let coveredElement={name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-hole-covered",fill:solderMaskColor,cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-type":"pcb_hole","data-pcb-layer":"drill"}},exposedElement={name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-hole-exposed",fill:colorMap2.drill,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask","data-pcb-layer":"drill"}};return[coveredElement,exposedElement]}return[{name:"circle",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,cx:x5.toString(),cy:y5.toString(),r:maskRadius.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":layer}},holeElement2]}let holeElement={name:"rect",type:"element",attributes:{class:"pcb-hole",x:(x5-radius).toString(),y:(y5-radius).toString(),width:scaledDiameter.toString(),height:scaledDiameter.toString(),fill:colorMap2.drill,"data-type":"pcb_hole","data-pcb-layer":"drill"},children:[],value:""};if(!shouldShowSolderMask)return[holeElement];let maskDiameter=scaledDiameter+2*soldermaskMargin;if(soldermaskMargin<0){let coveredElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-hole-covered",fill:solderMaskColor,x:(x5-radius).toString(),y:(y5-radius).toString(),width:scaledDiameter.toString(),height:scaledDiameter.toString(),"data-type":"pcb_hole","data-pcb-layer":"drill"}},exposedElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-hole-exposed",fill:colorMap2.drill,x:(x5-maskDiameter/2).toString(),y:(y5-maskDiameter/2).toString(),width:maskDiameter.toString(),height:maskDiameter.toString(),"data-type":"pcb_soldermask","data-pcb-layer":"drill"}};return[coveredElement,exposedElement]}return[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-maskDiameter/2).toString(),y:(y5-maskDiameter/2).toString(),width:maskDiameter.toString(),height:maskDiameter.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":layer}},holeElement]}if(hole.hole_shape==="oval"){let scaledWidth=hole.hole_width*Math.abs(transform5.a),scaledHeight=hole.hole_height*Math.abs(transform5.a),rx2=scaledWidth/2,ry2=scaledHeight/2,holeElement={name:"ellipse",type:"element",attributes:{class:"pcb-hole",cx:x5.toString(),cy:y5.toString(),rx:rx2.toString(),ry:ry2.toString(),fill:colorMap2.drill,"data-type":"pcb_hole","data-pcb-layer":"drill"},children:[],value:""};if(!shouldShowSolderMask)return[holeElement];let maskRx=rx2+soldermaskMargin,maskRy=ry2+soldermaskMargin;if(soldermaskMargin<0){let coveredElement={name:"ellipse",type:"element",value:"",children:[],attributes:{class:"pcb-hole-covered",fill:solderMaskColor,cx:x5.toString(),cy:y5.toString(),rx:rx2.toString(),ry:ry2.toString(),"data-type":"pcb_hole","data-pcb-layer":"drill"}},exposedElement={name:"ellipse",type:"element",value:"",children:[],attributes:{class:"pcb-hole-exposed",fill:colorMap2.drill,cx:x5.toString(),cy:y5.toString(),rx:maskRx.toString(),ry:maskRy.toString(),"data-type":"pcb_soldermask","data-pcb-layer":"drill"}};return[coveredElement,exposedElement]}return[{name:"ellipse",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,cx:x5.toString(),cy:y5.toString(),rx:maskRx.toString(),ry:maskRy.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":layer}},holeElement]}if(hole.hole_shape==="rect"){let scaledWidth=hole.hole_width*Math.abs(transform5.a),scaledHeight=hole.hole_height*Math.abs(transform5.a),holeElement={name:"rect",type:"element",attributes:{class:"pcb-hole",x:(x5-scaledWidth/2).toString(),y:(y5-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),fill:colorMap2.drill,"data-type":"pcb_hole","data-pcb-layer":"drill"},children:[],value:""};if(!shouldShowSolderMask)return[holeElement];let maskWidth=scaledWidth+2*soldermaskMargin,maskHeight=scaledHeight+2*soldermaskMargin;if(soldermaskMargin<0){let coveredElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-hole-covered",fill:solderMaskColor,x:(x5-scaledWidth/2).toString(),y:(y5-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),"data-type":"pcb_hole","data-pcb-layer":"drill"}},exposedElement={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-hole-exposed",fill:colorMap2.drill,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),"data-type":"pcb_soldermask","data-pcb-layer":"drill"}};return[coveredElement,exposedElement]}return[{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,x:(x5-maskWidth/2).toString(),y:(y5-maskHeight/2).toString(),width:maskWidth.toString(),height:maskHeight.toString(),"data-type":"pcb_soldermask_opening","data-pcb-layer":layer}},holeElement]}if(hole.hole_shape==="pill"){let scaledWidth=hole.hole_width*Math.abs(transform5.a),scaledHeight=hole.hole_height*Math.abs(transform5.a),isHorizontal2=scaledWidth>scaledHeight,radius=Math.min(scaledWidth,scaledHeight)/2,straightLength=Math.abs(isHorizontal2?scaledWidth-scaledHeight:scaledHeight-scaledWidth),pathD=isHorizontal2?`M${x5-straightLength/2},${y5-radius} h${straightLength} a${radius},${radius} 0 0 1 0,${scaledHeight} h-${straightLength} a${radius},${radius} 0 0 1 0,-${scaledHeight} z`:`M${x5-radius},${y5-straightLength/2} v${straightLength} a${radius},${radius} 0 0 0 ${scaledWidth},0 v-${straightLength} a${radius},${radius} 0 0 0 -${scaledWidth},0 z`,holeElement={name:"path",type:"element",attributes:{class:"pcb-hole",fill:colorMap2.drill,d:pathD,"data-type":"pcb_hole","data-pcb-layer":"drill"},children:[],value:""};if(!shouldShowSolderMask)return[holeElement];let maskWidth=scaledWidth+2*soldermaskMargin,maskHeight=scaledHeight+2*soldermaskMargin,maskIsHorizontal=maskWidth>maskHeight,maskRadius=Math.min(maskWidth,maskHeight)/2,maskStraightLength=Math.abs(maskIsHorizontal?maskWidth-maskHeight:maskHeight-maskWidth),maskPathD=maskIsHorizontal?`M${x5-maskStraightLength/2},${y5-maskRadius} h${maskStraightLength} a${maskRadius},${maskRadius} 0 0 1 0,${maskHeight} h-${maskStraightLength} a${maskRadius},${maskRadius} 0 0 1 0,-${maskHeight} z`:`M${x5-maskRadius},${y5-maskStraightLength/2} v${maskStraightLength} a${maskRadius},${maskRadius} 0 0 0 ${maskWidth},0 v-${maskStraightLength} a${maskRadius},${maskRadius} 0 0 0 -${maskWidth},0 z`;if(soldermaskMargin<0){let coveredElement={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-hole-covered",fill:solderMaskColor,d:pathD,"data-type":"pcb_hole","data-pcb-layer":"drill"}},exposedElement={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-hole-exposed",fill:colorMap2.drill,d:maskPathD,"data-type":"pcb_soldermask","data-pcb-layer":"drill"}};return[coveredElement,exposedElement]}return[{name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,d:maskPathD,"data-type":"pcb_soldermask_opening","data-pcb-layer":layer}},holeElement]}if(hole.hole_shape==="rotated_pill"){let scaledWidth=hole.hole_width*Math.abs(transform5.a),scaledHeight=hole.hole_height*Math.abs(transform5.a),rotation4="ccw_rotation"in hole?hole.ccw_rotation??0:0,isHorizontal2=scaledWidth>scaledHeight,radius=Math.min(scaledWidth,scaledHeight)/2,straightLength=Math.abs(isHorizontal2?scaledWidth-scaledHeight:scaledHeight-scaledWidth),pathD=isHorizontal2?`M${-straightLength/2},${-radius} h${straightLength} a${radius},${radius} 0 0 1 0,${scaledHeight} h-${straightLength} a${radius},${radius} 0 0 1 0,-${scaledHeight} z`:`M${-radius},${-straightLength/2} v${straightLength} a${radius},${radius} 0 0 0 ${scaledWidth},0 v-${straightLength} a${radius},${radius} 0 0 0 -${scaledWidth},0 z`,holeElement={name:"path",type:"element",attributes:{class:"pcb-hole",fill:colorMap2.drill,d:pathD,transform:`translate(${x5} ${y5}) rotate(${-rotation4})`,"data-type":"pcb_hole","data-pcb-layer":"drill"},children:[],value:""};if(!shouldShowSolderMask)return[holeElement];let maskWidth=scaledWidth+2*soldermaskMargin,maskHeight=scaledHeight+2*soldermaskMargin,maskIsHorizontal=maskWidth>maskHeight,maskRadius=Math.min(maskWidth,maskHeight)/2,maskStraightLength=Math.abs(maskIsHorizontal?maskWidth-maskHeight:maskHeight-maskWidth),maskPathD=maskIsHorizontal?`M${-maskStraightLength/2},${-maskRadius} h${maskStraightLength} a${maskRadius},${maskRadius} 0 0 1 0,${maskHeight} h-${maskStraightLength} a${maskRadius},${maskRadius} 0 0 1 0,-${maskHeight} z`:`M${-maskRadius},${-maskStraightLength/2} v${maskStraightLength} a${maskRadius},${maskRadius} 0 0 0 ${maskWidth},0 v-${maskStraightLength} a${maskRadius},${maskRadius} 0 0 0 -${maskWidth},0 z`;if(soldermaskMargin<0){let coveredElement={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-hole-covered",fill:solderMaskColor,d:pathD,transform:`translate(${x5} ${y5}) rotate(${-rotation4})`,"data-type":"pcb_hole","data-pcb-layer":"drill"}},exposedElement={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-hole-exposed",fill:colorMap2.drill,d:maskPathD,transform:`translate(${x5} ${y5}) rotate(${-rotation4})`,"data-type":"pcb_soldermask","data-pcb-layer":"drill"}};return[coveredElement,exposedElement]}return[{name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-soldermask-cutout",fill:colorMap2.substrate,d:maskPathD,"data-type":"pcb_soldermask_opening","data-pcb-layer":layer}},holeElement]}return[]}function createSvgObjectsForRatsNest(circuitJson,ctx){let{transform:transform5}=ctx,connectivity=getFullConnectivityMapFromCircuitJson(circuitJson),pcbPorts=circuitJson.filter(elm=>elm.type==="pcb_port"),sourceTraces=circuitJson.filter(elm=>elm.type==="source_trace"),ratsNestLines=[];pcbPorts.forEach((port,index)=>{let portId=port.pcb_port_id;if(!portId)return;let netId=connectivity.getNetConnectedToId(portId);if(!netId)return;let isInNet=!1,sourcePort=su2(circuitJson).source_port.getWhere({pcb_port_id:portId});if(sourcePort&&sourcePort.source_port_id){let sourcePortId=sourcePort.source_port_id;for(let trace of sourceTraces)if(Array.isArray(trace.connected_source_port_ids)&&trace.connected_source_port_ids.includes(sourcePortId)&&Array.isArray(trace.connected_source_net_ids)&&trace.connected_source_net_ids.length>0){isInNet=!0;break}}let startPoint={x:port.x,y:port.y},nearestPoint=findNearestPointInNet(startPoint,netId,connectivity,circuitJson);nearestPoint&&ratsNestLines.push({key:`${portId}-${index}`,startPoint,endPoint:nearestPoint,isInNet})});let svgObjects=[];for(let line2 of ratsNestLines){let transformedStart=applyToPoint3(transform5,[line2.startPoint.x,line2.startPoint.y]),transformedEnd=applyToPoint3(transform5,[line2.endPoint.x,line2.endPoint.y]),attributes2={x1:transformedStart[0].toString(),y1:transformedStart[1].toString(),x2:transformedEnd[0].toString(),y2:transformedEnd[1].toString(),stroke:"white","stroke-width":"1","stroke-dasharray":"6,6","data-type":"pcb_rats_nest","data-pcb-layer":"overlay"};svgObjects.push({name:"line",type:"element",attributes:attributes2,value:"",children:[]})}return svgObjects}function createSvgObjectsFromPcbCutout(cutout,ctx){let{transform:transform5,colorMap:colorMap2}=ctx;if(cutout.shape==="rect"){let rectCutout=cutout,[cx2,cy2]=applyToPoint3(transform5,[rectCutout.center.x,rectCutout.center.y]),scaledWidth=rectCutout.width*Math.abs(transform5.a),scaledHeight=rectCutout.height*Math.abs(transform5.d),svgRotation=-(rectCutout.rotation??0),{corner_radius}=rectCutout,baseCornerRadius=typeof corner_radius=="number"&&corner_radius>0?corner_radius:0,transformedCornerRadiusX=baseCornerRadius*Math.abs(transform5.a),transformedCornerRadiusY=baseCornerRadius*Math.abs(transform5.d),attributes2={class:"pcb-cutout pcb-cutout-rect",x:(-scaledWidth/2).toString(),y:(-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),fill:colorMap2.drill,transform:toString(compose3(translate3(cx2,cy2),rotate3(svgRotation*Math.PI/180))),"data-type":"pcb_cutout","data-pcb-layer":"drill"};return transformedCornerRadiusX>0&&(attributes2.rx=transformedCornerRadiusX.toString()),transformedCornerRadiusY>0&&(attributes2.ry=transformedCornerRadiusY.toString()),[{name:"rect",type:"element",attributes:attributes2,children:[],value:""}]}if(cutout.shape==="circle"){let circleCutout=cutout,[cx2,cy2]=applyToPoint3(transform5,[circleCutout.center.x,circleCutout.center.y]),scaledRadius=circleCutout.radius*Math.abs(transform5.a);return[{name:"circle",type:"element",attributes:{class:"pcb-cutout pcb-cutout-circle",cx:cx2.toString(),cy:cy2.toString(),r:scaledRadius.toString(),fill:colorMap2.drill,"data-type":"pcb_cutout","data-pcb-layer":"drill"},children:[],value:""}]}if(cutout.shape==="polygon"){let polygonCutout=cutout;return!polygonCutout.points||polygonCutout.points.length===0?[]:[{name:"polygon",type:"element",attributes:{class:"pcb-cutout pcb-cutout-polygon",points:polygonCutout.points.map(p4=>applyToPoint3(transform5,[p4.x,p4.y])).map(p4=>`${p4[0]},${p4[1]}`).join(" "),fill:colorMap2.drill,"data-type":"pcb_cutout","data-pcb-layer":"drill"},children:[],value:""}]}return[]}function createSvgObjectsFromPcbCutoutPath(cutoutPath,ctx){let{transform:transform5,colorMap:colorMap2}=ctx;if(!cutoutPath.route||!Array.isArray(cutoutPath.route))return[];let firstPoint=cutoutPath.route[0],lastPoint=cutoutPath.route[cutoutPath.route.length-1],isClosed=firstPoint&&lastPoint&&firstPoint.x===lastPoint.x&&firstPoint.y===lastPoint.y;return[{name:"path",type:"element",attributes:{class:"pcb-cutout pcb-cutout-path",d:cutoutPath.route.slice(0,isClosed?-1:void 0).map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" ")+(isClosed?" Z":""),fill:colorMap2.drill,"data-type":"pcb_cutout_path","data-pcb-cutout-id":cutoutPath.pcb_cutout_id,"data-pcb-layer":"drill"},value:"",children:[]}]}function createKeepoutPatternLines(keepoutColor){let patternLines=[];for(let i2=-KEEPOUT_PATTERN_SIZE;i2<=KEEPOUT_PATTERN_SIZE;i2+=KEEPOUT_LINE_SPACING)patternLines.push({name:"line",type:"element",value:"",attributes:{x1:i2.toString(),y1:"0",x2:(i2+KEEPOUT_PATTERN_SIZE).toString(),y2:KEEPOUT_PATTERN_SIZE.toString(),stroke:keepoutColor,"stroke-width":"1"},children:[]});return patternLines}function createKeepoutPatternDefs(keepoutColor){return{name:"defs",type:"element",value:"",attributes:{},children:[{name:"pattern",type:"element",value:"",attributes:{id:KEEPOUT_PATTERN_ID,width:KEEPOUT_PATTERN_SIZE.toString(),height:KEEPOUT_PATTERN_SIZE.toString(),patternUnits:"userSpaceOnUse"},children:createKeepoutPatternLines(keepoutColor)}]}}function createKeepoutBaseAttributes(keepoutId,layer,shapeClass,description){let attributes2={class:`pcb-keepout ${shapeClass} pcb-keepout-background`,"data-type":"pcb_keepout","data-pcb-layer":layer,"data-pcb-keepout-id":keepoutId,stroke:"none"};return description&&(attributes2["data-description"]=description),attributes2}function createKeepoutPatternAttributes(keepoutId,layer,shapeClass,description){let attributes2={class:`pcb-keepout ${shapeClass} pcb-keepout-pattern`,fill:`url(#${KEEPOUT_PATTERN_ID})`,"data-type":"pcb_keepout","data-pcb-layer":layer,"data-pcb-keepout-id":keepoutId,stroke:"none"};return description&&(attributes2["data-description"]=description),attributes2}function createSvgObjectsFromPcbKeepout(keepout,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2}=ctx;if(layerFilter&&!keepout.layers.includes(layerFilter))return[];let svgObjects=[],keepoutColor=colorMap2.keepout;for(let layer of keepout.layers)if(!(layerFilter&&layer!==layerFilter)){if(keepout.shape==="rect"){let rectKeepout=keepout,[cx2,cy2]=applyToPoint3(transform5,[rectKeepout.center.x,rectKeepout.center.y]),scaledWidth=rectKeepout.width*Math.abs(transform5.a),scaledHeight=rectKeepout.height*Math.abs(transform5.d),baseTransform=toString(compose3(translate3(cx2,cy2))),backgroundAttributes={...createKeepoutBaseAttributes(rectKeepout.pcb_keepout_id,layer,"pcb-keepout-rect",rectKeepout.description),x:(-scaledWidth/2).toString(),y:(-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),fill:KEEPOUT_BACKGROUND_COLOR,transform:baseTransform},patternAttributes={...createKeepoutPatternAttributes(rectKeepout.pcb_keepout_id,layer,"pcb-keepout-rect",rectKeepout.description),x:(-scaledWidth/2).toString(),y:(-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),transform:baseTransform};svgObjects.push({name:"rect",type:"element",attributes:backgroundAttributes,children:[],value:""},{name:"rect",type:"element",attributes:patternAttributes,children:[],value:""})}else if(keepout.shape==="circle"){let circleKeepout=keepout,[cx2,cy2]=applyToPoint3(transform5,[circleKeepout.center.x,circleKeepout.center.y]),scaledRadius=circleKeepout.radius*Math.abs(transform5.a),backgroundAttributes={...createKeepoutBaseAttributes(circleKeepout.pcb_keepout_id,layer,"pcb-keepout-circle",circleKeepout.description),cx:cx2.toString(),cy:cy2.toString(),r:scaledRadius.toString(),fill:KEEPOUT_BACKGROUND_COLOR},patternAttributes={...createKeepoutPatternAttributes(circleKeepout.pcb_keepout_id,layer,"pcb-keepout-circle",circleKeepout.description),cx:cx2.toString(),cy:cy2.toString(),r:scaledRadius.toString()};svgObjects.push({name:"circle",type:"element",attributes:backgroundAttributes,children:[],value:""},{name:"circle",type:"element",attributes:patternAttributes,children:[],value:""})}}return svgObjects}function ringToPathD(vertices,transform5){if(vertices.length===0)return"";let transformedVertices=vertices.map(v5=>{let[x5,y5]=applyToPoint3(transform5,[v5.x,v5.y]);return{...v5,x:x5,y:y5}}),d3=`M ${transformedVertices[0].x} ${transformedVertices[0].y}`;for(let i2=0;i2<transformedVertices.length;i2++){let start=transformedVertices[i2],end=transformedVertices[(i2+1)%transformedVertices.length];if(start.bulge){if(Math.hypot(end.x-start.x,end.y-start.y)<1e-9)continue;let bulge=start.bulge,dx2=end.x-start.x,dy2=end.y-start.y,dist=Math.hypot(dx2,dy2),radius=Math.abs(dist/4/bulge*(bulge*bulge+1)),sweepFlag=bulge<0?1:0,largeArcFlag=Math.abs(bulge)>1?1:0;d3+=` A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${end.x} ${end.y}`}else d3+=` L ${end.x} ${end.y}`}return d3+=" Z",d3}function createSoldermaskCutoutElement({elementType,shapeAttributes,layer,colorMap:colorMap2,additionalAttributes}){let baseAttributes={class:"pcb-soldermask-cutout",fill:colorMap2.substrate,"data-type":"pcb_soldermask_opening","data-pcb-layer":layer,...shapeAttributes,...additionalAttributes};return{name:elementType,type:"element",value:"",children:[],attributes:baseAttributes}}function createSoldermaskOverlayElement({elementType,shapeAttributes,layer,fillColor,fillOpacity,className,additionalAttributes}){let baseAttributes={class:className,fill:fillColor,"fill-opacity":fillOpacity,"data-type":"pcb_soldermask","data-pcb-layer":layer,...shapeAttributes,...additionalAttributes};return{name:elementType,type:"element",value:"",children:[],attributes:baseAttributes}}function createSvgObjectsFromPcbCopperPour(pour,ctx){let{transform:transform5,layer:layerFilter,colorMap:colorMap2,showSolderMask}=ctx,{layer}=pour;if(layerFilter&&layer!==layerFilter)return[];let color=layerNameToColor(layer,colorMap2),opacity="0.5",isCoveredWithSolderMask=pour.covered_with_solder_mask!==!1,maskOverlayColor=layer==="bottom"?colorMap2.soldermaskOverCopper.bottom:colorMap2.soldermaskOverCopper.top,maskOverlayOpacity="0.9";if(pour.shape==="rect"){let[cx2,cy2]=applyToPoint3(transform5,[pour.center.x,pour.center.y]),scaledWidth=pour.width*Math.abs(transform5.a),scaledHeight=pour.height*Math.abs(transform5.d),svgRotation=-(pour.rotation??0),rectAttributes={x:(-scaledWidth/2).toString(),y:(-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),transform:toString(compose3(translate3(cx2,cy2),rotate3(svgRotation*Math.PI/180)))},copperRect={name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-copper-pour pcb-copper-pour-rect",...rectAttributes,fill:color,"fill-opacity":opacity,"data-type":"pcb_copper_pour","data-pcb-layer":layer}},maskRect=showSolderMask?isCoveredWithSolderMask?createSoldermaskOverlayElement({elementType:"rect",shapeAttributes:rectAttributes,layer,fillColor:maskOverlayColor,fillOpacity:maskOverlayOpacity,className:"pcb-soldermask-covered-pour"}):createSoldermaskCutoutElement({elementType:"rect",shapeAttributes:rectAttributes,layer,colorMap:colorMap2}):null;return maskRect?!isCoveredWithSolderMask&&pour.pcb_copper_pour_id?.includes("substrate_only")?[maskRect]:[copperRect,maskRect]:[copperRect]}if(pour.shape==="polygon"){if(!pour.points||pour.points.length===0)return[];let pointsString=pour.points.map(p4=>applyToPoint3(transform5,[p4.x,p4.y])).map(p4=>`${p4[0]},${p4[1]}`).join(" "),copperPolygon={name:"polygon",type:"element",value:"",children:[],attributes:{class:"pcb-copper-pour pcb-copper-pour-polygon",points:pointsString,fill:color,"fill-opacity":opacity,"data-type":"pcb_copper_pour","data-pcb-layer":layer}},maskPolygon=showSolderMask?isCoveredWithSolderMask?createSoldermaskOverlayElement({elementType:"polygon",shapeAttributes:{points:pointsString},layer,fillColor:maskOverlayColor,fillOpacity:maskOverlayOpacity,className:"pcb-soldermask-covered-pour"}):createSoldermaskCutoutElement({elementType:"polygon",shapeAttributes:{points:pointsString},layer,colorMap:colorMap2}):null;return maskPolygon?!isCoveredWithSolderMask&&pour.pcb_copper_pour_id?.includes("substrate_only")?[maskPolygon]:[copperPolygon,maskPolygon]:[copperPolygon]}if(pour.shape==="brep"){let{brep_shape:brep_shape2}=pour,d3=ringToPathD(brep_shape2.outer_ring.vertices,transform5);for(let inner_ring of brep_shape2.inner_rings??[])d3+=` ${ringToPathD(inner_ring.vertices,transform5)}`;let copperPath={name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-copper-pour pcb-copper-pour-brep",d:d3,fill:color,"fill-rule":"evenodd","fill-opacity":opacity,"data-type":"pcb_copper_pour","data-pcb-layer":layer}},maskPath=showSolderMask?isCoveredWithSolderMask?createSoldermaskOverlayElement({elementType:"path",shapeAttributes:{d:d3,"fill-rule":"evenodd"},layer,fillColor:maskOverlayColor,fillOpacity:maskOverlayOpacity,className:"pcb-soldermask-covered-pour"}):createSoldermaskCutoutElement({elementType:"path",shapeAttributes:{d:d3,"fill-rule":"evenodd"},layer,colorMap:colorMap2}):null;return maskPath?!isCoveredWithSolderMask&&pour.pcb_copper_pour_id?.includes("substrate_only")?[maskPath]:[copperPath,maskPath]:[copperPath]}return[]}function createSvgObjectsForPcbGrid({grid:grid4,svgWidth,svgHeight}){if(!grid4)return{};let gridLineColor=grid4.lineColor??DEFAULT_GRID_LINE_COLOR,gridCellSize=grid4.cellSize,majorCellSize=grid4.majorCellSize,majorLineColor=grid4.majorLineColor??gridLineColor;if(majorCellSize!==void 0){if(!gridCellSize||gridCellSize<=0)throw new Error("grid.majorCellSize requires a positive grid.cellSize");if(majorCellSize<=0)throw new Error("grid.majorCellSize must be a positive multiple of grid.cellSize");let ratio=majorCellSize/gridCellSize,nearestInteger=Math.round(ratio);if(!Number.isFinite(ratio)||Math.abs(ratio-nearestInteger)>1e-6)throw new Error("grid.majorCellSize must be a positive multiple of grid.cellSize")}if(!gridCellSize||gridCellSize<=0)return{};let hasMajorGrid=majorCellSize!==void 0,patternChildren=hasMajorGrid?createMajorGridPatternChildren(gridCellSize,majorCellSize,gridLineColor,majorLineColor):[{name:"path",type:"element",value:"",attributes:{d:`M ${gridCellSize} 0 L 0 0 0 ${gridCellSize}`,fill:"none",stroke:gridLineColor,"stroke-width":"1","shape-rendering":"crispEdges"},children:[]}],defs={name:"defs",type:"element",value:"",attributes:{},children:[{name:"pattern",type:"element",value:"",attributes:{id:GRID_PATTERN_ID,width:hasMajorGrid?majorCellSize.toString():gridCellSize.toString(),height:hasMajorGrid?majorCellSize.toString():gridCellSize.toString(),patternUnits:"userSpaceOnUse"},children:patternChildren}]},rect={name:"rect",type:"element",value:"",attributes:{x:"0",y:"0",width:svgWidth.toString(),height:svgHeight.toString(),fill:`url(#${GRID_PATTERN_ID})`,"pointer-events":"none","data-type":"pcb_grid","data-pcb-layer":"global"},children:[]};return{defs,rect}}function createMajorGridPatternChildren(cellSize,majorCellSize,lineColor,majorLineColor){let children=[],steps=Math.round(majorCellSize/cellSize);for(let step=0;step<steps;step+=1){let offsetString=Number((step*cellSize).toFixed(6)).toString(),color=step===0?majorLineColor:lineColor,majorSizeString=majorCellSize.toString();children.push({name:"line",type:"element",value:"",attributes:{x1:offsetString,y1:"0",x2:offsetString,y2:majorSizeString,stroke:color,"stroke-width":"1","shape-rendering":"crispEdges"},children:[]}),children.push({name:"line",type:"element",value:"",attributes:{x1:"0",y1:offsetString,x2:majorSizeString,y2:offsetString,stroke:color,"stroke-width":"1","shape-rendering":"crispEdges"},children:[]})}return children}function createSvgObjectsFromPcbComponent(component,ctx){let{transform:transform5,circuitJson}=ctx,{center:center2,width,height,rotation:rotation4=0}=component,[x5,y5]=applyToPoint3(transform5,[center2.x,center2.y]),scaledWidth=width*Math.abs(transform5.a),scaledHeight=height*Math.abs(transform5.d),transformStr=`translate(${x5}, ${y5}) rotate(${-rotation4}) scale(1, -1)`,svgObjects=[];if(ctx.showAnchorOffsets&&circuitJson&&component.position_mode==="relative_to_group_anchor"&&(component.positioned_relative_to_pcb_group_id||component.positioned_relative_to_pcb_board_id)){let parentAnchorPosition=getParentAnchorPosition(component,circuitJson);parentAnchorPosition&&svgObjects.push(...createAnchorOffsetIndicators({groupAnchorPosition:parentAnchorPosition,componentPosition:center2,transform:transform5,componentWidth:width,componentHeight:height,displayXOffset:component.display_offset_x,displayYOffset:component.display_offset_y}))}return!ctx.colorMap.debugComponent?.fill&&!ctx.colorMap.debugComponent?.stroke||svgObjects.push({name:"g",type:"element",attributes:{transform:transformStr,"data-type":"pcb_component","data-pcb-layer":component.layer??"top"},children:[{name:"rect",type:"element",attributes:{class:"pcb-component",x:(-scaledWidth/2).toString(),y:(-scaledHeight/2).toString(),width:scaledWidth.toString(),height:scaledHeight.toString(),fill:ctx.colorMap.debugComponent.fill??"transparent",stroke:ctx.colorMap.debugComponent.stroke??"transparent","data-type":"pcb_component","data-pcb-layer":component.layer??"top"}}],value:""}),svgObjects}function getParentAnchorPosition(component,circuitJson){if(component.positioned_relative_to_pcb_group_id){let pcbGroup=circuitJson.find(elm=>elm.type==="pcb_group"&&elm.pcb_group_id===component.positioned_relative_to_pcb_group_id),point6=getPointFromElm(pcbGroup);if(point6)return point6}if(component.positioned_relative_to_pcb_board_id){let pcbBoard=circuitJson.find(elm=>elm.type==="pcb_board"&&elm.pcb_board_id===component.positioned_relative_to_pcb_board_id),point6=getPointFromElm(pcbBoard);if(point6)return point6}}function createSvgObjectsFromPcbGroup(pcbGroup,ctx){let{transform:transform5,circuitJson}=ctx,{center:center2,width,height}=pcbGroup,svgObjects=[];if(ctx.showAnchorOffsets&&pcbGroup.position_mode==="relative_to_group_anchor"&&circuitJson){let parentAnchorPosition=getParentAnchorPosition2(pcbGroup,circuitJson);parentAnchorPosition&&svgObjects.push(...createAnchorOffsetIndicators({groupAnchorPosition:parentAnchorPosition,componentPosition:pcbGroup.anchor_position??pcbGroup.center,transform:transform5,componentWidth:pcbGroup.width,componentHeight:pcbGroup.height,displayXOffset:pcbGroup.display_offset_x,displayYOffset:pcbGroup.display_offset_y}))}let outline=Array.isArray(pcbGroup.outline)?pcbGroup.outline:void 0,transformedStrokeWidth=DEFAULT_STROKE_WIDTH*Math.abs(transform5.a),dashLength=.3*Math.abs(transform5.a),gapLength=.15*Math.abs(transform5.a),baseAttributes={class:"pcb-group",fill:"none",stroke:DEFAULT_GROUP_COLOR,"stroke-width":transformedStrokeWidth.toString(),"stroke-dasharray":`${dashLength} ${gapLength}`,"data-type":"pcb_group","data-pcb-group-id":pcbGroup.pcb_group_id,"data-pcb-layer":"overlay"};if(pcbGroup.name&&(baseAttributes["data-group-name"]=pcbGroup.name),outline&&outline.length>=3&&outline.every(point6=>point6&&typeof point6.x=="number"&&typeof point6.y=="number")){let path=outline.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" ");return svgObjects.push({name:"path",type:"element",value:"",children:[],attributes:{...baseAttributes,d:`${path} Z`}}),svgObjects}if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof width!="number"||typeof height!="number")return console.error("Invalid pcb_group data",{center:center2,width,height}),svgObjects;let halfWidth=width/2,halfHeight=height/2,[topLeftX,topLeftY]=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]),[bottomRightX,bottomRightY]=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),rectX=Math.min(topLeftX,bottomRightX),rectY=Math.min(topLeftY,bottomRightY),rectWidth=Math.abs(bottomRightX-topLeftX),rectHeight=Math.abs(bottomRightY-topLeftY),svgObject={name:"rect",type:"element",value:"",attributes:{...baseAttributes,x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString()},children:[]};return svgObjects.push(svgObject),svgObjects}function getParentAnchorPosition2(group,circuitJson){if(group.positioned_relative_to_pcb_group_id){let pcbGroup=circuitJson.find(elm=>elm.type==="pcb_group"&&elm.pcb_group_id===group.positioned_relative_to_pcb_group_id),point6=getPointFromElm(pcbGroup);if(point6)return point6}if(group.positioned_relative_to_pcb_board_id){let pcbBoard=circuitJson.find(elm=>elm.type==="pcb_board"&&elm.pcb_board_id===group.positioned_relative_to_pcb_board_id),point6=getPointFromElm(pcbBoard);if(point6)return point6}}function getSoftwareUsedString(circuitJson){return circuitJson.find(e4=>e4.type==="project_software_metadata"||e4.type==="source_project_metadata")?.software_used_string}function sortSvgObjectsByPcbLayer(objects){return objects.map((object,index)=>({object,index,layerPriority:getLayerPriority(object.attributes?.["data-pcb-layer"]??void 0),typePriority:getTypePriority(object.attributes?.["data-type"]??void 0)})).sort((a2,b3)=>a2.layerPriority!==b3.layerPriority?a2.layerPriority-b3.layerPriority:a2.typePriority!==b3.typePriority?a2.typePriority-b3.typePriority:a2.index-b3.index).map(({object})=>object)}function getLayerPriority(layer){if(!layer)return 500;let normalized=layer.toLowerCase();if(normalized==="global")return-100;if(normalized==="bottom")return 4;if(normalized==="board")return 2;if(normalized==="soldermask-top"||normalized==="soldermask-bottom")return 3;if(normalized.startsWith("inner")){let match2=normalized.match(/\d+/);return 5+(match2?Number.parseInt(match2[0],10):0)}return normalized==="through"?18:normalized==="top"?17:normalized==="drill"?30:normalized==="overlay"?40:10}function getTypePriority(type){return type?TYPE_PRIORITY[type]??DEFAULT_TYPE_PRIORITY:DEFAULT_TYPE_PRIORITY}function createErrorTextOverlay(circuitJson,dataType="error_text_overlay"){let errorElms=circuitJson.filter(elm=>elm.type.endsWith("_error"));if(errorElms.length===0)return null;let errorMessages=errorElms.map(e4=>e4.message).filter(m3=>!!m3);return errorMessages.length===0?null:{name:"text",type:"element",value:"",attributes:{x:"10",y:"20",fill:"red","font-family":"monospace","font-size":"12px","data-type":dataType,"data-layer":"global"},children:errorMessages.map((msg,i2)=>({name:"tspan",type:"element",value:"",attributes:{x:"10",dy:i2===0?"0":"1.2em"},children:[{type:"text",value:msg,name:"",attributes:{},children:[]}]}))}}function getPcbBoundsFromCircuitJson(circuitJson){let minX=Number.POSITIVE_INFINITY,minY=Number.POSITIVE_INFINITY,maxX=Number.NEGATIVE_INFINITY,maxY=Number.NEGATIVE_INFINITY,hasBounds=!1,boardMinX=Number.POSITIVE_INFINITY,boardMinY=Number.POSITIVE_INFINITY,boardMaxX=Number.NEGATIVE_INFINITY,boardMaxY=Number.NEGATIVE_INFINITY,hasBoardBounds=!1;for(let circuitJsonElm of circuitJson)if(circuitJsonElm.type==="pcb_panel"){let panel=circuitJsonElm,width=distance.parse(panel.width),height=distance.parse(panel.height);if(width===void 0||height===void 0)continue;let center2=panel.center??{x:width/2,y:height/2};updateBounds({center:center2,width,height})}else if(circuitJsonElm.type==="pcb_board")circuitJsonElm.outline&&Array.isArray(circuitJsonElm.outline)&&circuitJsonElm.outline.length>=3?(updateBoundsToIncludeOutline(circuitJsonElm.outline),updateBoardBoundsToIncludeOutline(circuitJsonElm.outline)):"center"in circuitJsonElm&&"width"in circuitJsonElm&&"height"in circuitJsonElm&&(updateBounds({center:circuitJsonElm.center,width:circuitJsonElm.width,height:circuitJsonElm.height}),updateBoardBounds({center:circuitJsonElm.center,width:circuitJsonElm.width,height:circuitJsonElm.height}));else if(circuitJsonElm.type==="pcb_smtpad"){let pad2=circuitJsonElm;if(pad2.shape==="rect"||pad2.shape==="rotated_rect"||pad2.shape==="pill")updateBounds({center:{x:pad2.x,y:pad2.y},width:pad2.width,height:pad2.height});else if(pad2.shape==="circle"){let radius=distance.parse(pad2.radius);radius!==void 0&&updateBounds({center:{x:pad2.x,y:pad2.y},width:radius*2,height:radius*2})}else pad2.shape==="polygon"&&updateTraceBounds(pad2.points)}else if("x"in circuitJsonElm&&"y"in circuitJsonElm)updateBounds({center:{x:circuitJsonElm.x,y:circuitJsonElm.y},width:0,height:0});else if("route"in circuitJsonElm)updateTraceBounds(circuitJsonElm.route);else if(circuitJsonElm.type==="pcb_note_rect"||circuitJsonElm.type==="pcb_fabrication_note_rect")updateBounds({center:circuitJsonElm.center,width:circuitJsonElm.width,height:circuitJsonElm.height});else if(circuitJsonElm.type==="pcb_note_dimension"||circuitJsonElm.type==="pcb_fabrication_note_dimension"){let dimension=circuitJsonElm,{from,to:to3,text,font_size=1,arrow_size,offset_distance,offset_direction}=dimension;if(!from||!to3||!arrow_size)continue;updateBounds({center:from,width:0,height:0}),updateBounds({center:to3,width:0,height:0});let normalize3=v5=>{let l3=Math.hypot(v5.x,v5.y)||1;return{x:v5.x/l3,y:v5.y/l3}},direction2=normalize3({x:to3.x-from.x,y:to3.y-from.y});if(Number.isNaN(direction2.x)||Number.isNaN(direction2.y))continue;let perpendicular={x:-direction2.y,y:direction2.x},hasOffsetDirection=offset_direction&&typeof offset_direction.x=="number"&&typeof offset_direction.y=="number",normalizedOffsetDirection=hasOffsetDirection?normalize3(offset_direction):{x:0,y:0},offsetMagnitude=typeof offset_distance=="number"?offset_distance:0,offsetVector={x:normalizedOffsetDirection.x*offsetMagnitude,y:normalizedOffsetDirection.y*offsetMagnitude},fromOffset={x:from.x+offsetVector.x,y:from.y+offsetVector.y},toOffset={x:to3.x+offsetVector.x,y:to3.y+offsetVector.y};updateBounds({center:fromOffset,width:0,height:0}),updateBounds({center:toOffset,width:0,height:0});let extensionDirection=hasOffsetDirection&&(Math.abs(normalizedOffsetDirection.x)>Number.EPSILON||Math.abs(normalizedOffsetDirection.y)>Number.EPSILON)?normalizedOffsetDirection:perpendicular,extensionLength=offsetMagnitude+arrow_size,fromExtEnd={x:from.x+extensionDirection.x*extensionLength,y:from.y+extensionDirection.y*extensionLength},toExtEnd={x:to3.x+extensionDirection.x*extensionLength,y:to3.y+extensionDirection.y*extensionLength};updateBounds({center:fromExtEnd,width:0,height:0}),updateBounds({center:toExtEnd,width:0,height:0});let arrowHalfWidth=arrow_size/2,fromBase={x:fromOffset.x+direction2.x*arrow_size,y:fromOffset.y+direction2.y*arrow_size},toBase={x:toOffset.x-direction2.x*arrow_size,y:toOffset.y-direction2.y*arrow_size},fromArrowP2={x:fromBase.x+perpendicular.x*arrowHalfWidth,y:fromBase.y+perpendicular.y*arrowHalfWidth},fromArrowP3={x:fromBase.x-perpendicular.x*arrowHalfWidth,y:fromBase.y-perpendicular.y*arrowHalfWidth};updateBounds({center:fromArrowP2,width:0,height:0}),updateBounds({center:fromArrowP3,width:0,height:0});let toArrowP2={x:toBase.x+perpendicular.x*arrowHalfWidth,y:toBase.y+perpendicular.y*arrowHalfWidth},toArrowP3={x:toBase.x-perpendicular.x*arrowHalfWidth,y:toBase.y-perpendicular.y*arrowHalfWidth};if(updateBounds({center:toArrowP2,width:0,height:0}),updateBounds({center:toArrowP3,width:0,height:0}),text){let midPoint={x:(from.x+to3.x)/2+offsetVector.x,y:(from.y+to3.y)/2+offsetVector.y},textOffset=arrow_size*1.5,textPoint={x:midPoint.x+perpendicular.x*textOffset,y:midPoint.y+perpendicular.y*textOffset},textWidth=text.length*font_size*.6;updateBounds({center:textPoint,width:textWidth,height:font_size})}}else if(circuitJsonElm.type==="pcb_cutout"){let cutout=circuitJsonElm;if(cutout.shape==="rect")updateBounds({center:cutout.center,width:cutout.width,height:cutout.height});else if(cutout.shape==="circle"){let radius=distance.parse(cutout.radius);radius!==void 0&&updateBounds({center:cutout.center,width:radius*2,height:radius*2})}else if(cutout.shape==="polygon")updateTraceBounds(cutout.points);else if(cutout.shape==="path"){let cutoutPath=cutout;cutoutPath.route&&Array.isArray(cutoutPath.route)&&updateTraceBounds(cutoutPath.route)}}else if(circuitJsonElm.type==="pcb_keepout"){let keepout=circuitJsonElm;if(keepout.shape==="rect")updateBounds({center:keepout.center,width:keepout.width,height:keepout.height});else if(keepout.shape==="circle"){let radius=typeof keepout.radius=="number"?keepout.radius:distance.parse(keepout.radius)??0;radius>0&&updateBounds({center:keepout.center,width:radius*2,height:radius*2})}}else circuitJsonElm.type==="pcb_silkscreen_text"||circuitJsonElm.type==="pcb_silkscreen_rect"||circuitJsonElm.type==="pcb_silkscreen_circle"||circuitJsonElm.type==="pcb_silkscreen_line"||circuitJsonElm.type==="pcb_silkscreen_oval"?updateSilkscreenBounds(circuitJsonElm):circuitJsonElm.type==="pcb_copper_text"?updateBounds({center:circuitJsonElm.anchor_position,width:0,height:0}):circuitJsonElm.type==="pcb_copper_pour"&&(circuitJsonElm.shape==="rect"?updateBounds({center:circuitJsonElm.center,width:circuitJsonElm.width,height:circuitJsonElm.height}):circuitJsonElm.shape==="polygon"&&updateTraceBounds(circuitJsonElm.points));return{minX,minY,maxX,maxY,boardMinX,boardMinY,boardMaxX,boardMaxY,hasBounds,hasBoardBounds};function updateBounds({center:center2,width,height}){if(!center2)return;let centerX=distance.parse(center2.x),centerY=distance.parse(center2.y);if(centerX===void 0||centerY===void 0)return;let numericWidth=distance.parse(width)??0,numericHeight=distance.parse(height)??0,halfWidth=numericWidth/2,halfHeight=numericHeight/2;minX=Math.min(minX,centerX-halfWidth),minY=Math.min(minY,centerY-halfHeight),maxX=Math.max(maxX,centerX+halfWidth),maxY=Math.max(maxY,centerY+halfHeight),hasBounds=!0}function updateBoardBounds({center:center2,width,height}){if(!center2)return;let centerX=distance.parse(center2.x),centerY=distance.parse(center2.y);if(centerX===void 0||centerY===void 0)return;let numericWidth=distance.parse(width)??0,numericHeight=distance.parse(height)??0,halfWidth=numericWidth/2,halfHeight=numericHeight/2;boardMinX=Math.min(boardMinX,centerX-halfWidth),boardMinY=Math.min(boardMinY,centerY-halfHeight),boardMaxX=Math.max(boardMaxX,centerX+halfWidth),boardMaxY=Math.max(boardMaxY,centerY+halfHeight),hasBounds=!0,hasBoardBounds=!0}function updateBoundsToIncludeOutline(outline){let updated=!1;for(let point6 of outline){let x5=distance.parse(point6.x),y5=distance.parse(point6.y);x5===void 0||y5===void 0||(minX=Math.min(minX,x5),minY=Math.min(minY,y5),maxX=Math.max(maxX,x5),maxY=Math.max(maxY,y5),updated=!0)}updated&&(hasBounds=!0)}function updateBoardBoundsToIncludeOutline(outline){let updated=!1;for(let point6 of outline){let x5=distance.parse(point6.x),y5=distance.parse(point6.y);x5===void 0||y5===void 0||(boardMinX=Math.min(boardMinX,x5),boardMinY=Math.min(boardMinY,y5),boardMaxX=Math.max(boardMaxX,x5),boardMaxY=Math.max(boardMaxY,y5),updated=!0)}updated&&(hasBounds=!0,hasBoardBounds=!0)}function updateTraceBounds(route){let updated=!1;for(let point6 of route){let x5=distance.parse(point6?.x),y5=distance.parse(point6?.y);x5===void 0||y5===void 0||(minX=Math.min(minX,x5),minY=Math.min(minY,y5),maxX=Math.max(maxX,x5),maxY=Math.max(maxY,y5),updated=!0)}updated&&(hasBounds=!0)}function updateSilkscreenBounds(item){if(item.type==="pcb_silkscreen_text")updateBounds({center:item.anchor_position,width:0,height:0});else if(item.type==="pcb_silkscreen_path")updateTraceBounds(item.route);else if(item.type==="pcb_silkscreen_rect")updateBounds({center:item.center,width:item.width,height:item.height});else if(item.type==="pcb_silkscreen_circle"){let radius=distance.parse(item.radius);radius!==void 0&&updateBounds({center:item.center,width:radius*2,height:radius*2})}else if(item.type==="pcb_silkscreen_line")updateBounds({center:{x:item.x1,y:item.y1},width:0,height:0}),updateBounds({center:{x:item.x2,y:item.y2},width:0,height:0});else if(item.type==="pcb_silkscreen_oval"){let radiusX=distance.parse(item.radius_x),radiusY=distance.parse(item.radius_y);radiusX!==void 0&&radiusY!==void 0&&updateBounds({center:item.center,width:radiusX*2,height:radiusY*2})}else if(item.type==="pcb_cutout"){let cutout=item;if(cutout.shape==="rect")updateBounds({center:cutout.center,width:cutout.width,height:cutout.height});else if(cutout.shape==="circle"){let radius=distance.parse(cutout.radius);radius!==void 0&&updateBounds({center:cutout.center,width:radius*2,height:radius*2})}else if(cutout.shape==="polygon")updateTraceBounds(cutout.points);else if(cutout.shape==="path"){let cutoutPath=cutout;cutoutPath.route&&Array.isArray(cutoutPath.route)&&updateTraceBounds(cutoutPath.route)}}}}function rectBounds(center2,width,height){if(!center2||width===void 0||height===void 0)return;let cx2=distance.parse(center2.x),cy2=distance.parse(center2.y);if(cx2===void 0||cy2===void 0)return;let numericWidth=distance.parse(width),numericHeight=distance.parse(height);if(numericWidth===void 0||numericHeight===void 0)return;let halfW=numericWidth/2,halfH=numericHeight/2;return{minX:cx2-halfW,minY:cy2-halfH,maxX:cx2+halfW,maxY:cy2+halfH}}function getOutlineBounds(outline){if(!outline||outline.length<3)return;let minX=Number.POSITIVE_INFINITY,minY=Number.POSITIVE_INFINITY,maxX=Number.NEGATIVE_INFINITY,maxY=Number.NEGATIVE_INFINITY;for(let pt4 of outline){let x5=distance.parse(pt4.x),y5=distance.parse(pt4.y);x5===void 0||y5===void 0||(minX=Math.min(minX,x5),minY=Math.min(minY,y5),maxX=Math.max(maxX,x5),maxY=Math.max(maxY,y5))}if(!(!Number.isFinite(minX)||!Number.isFinite(minY))&&!(!Number.isFinite(maxX)||!Number.isFinite(maxY)))return{minX,minY,maxX,maxY}}function convertCircuitJsonToPcbSvg(circuitJson,options){let drawPaddingOutsideBoard=options?.drawPaddingOutsideBoard??!0,layer=options?.layer,colorOverrides=options?.colorOverrides,copperColors={...DEFAULT_PCB_COLOR_MAP.copper};if(colorOverrides?.copper)for(let[layerName,color]of Object.entries(colorOverrides.copper))color!==void 0&&(copperColors[layerName]=color);let colorMap2={copper:copperColors,drill:colorOverrides?.drill??DEFAULT_PCB_COLOR_MAP.drill,silkscreen:{top:colorOverrides?.silkscreen?.top??DEFAULT_PCB_COLOR_MAP.silkscreen.top,bottom:colorOverrides?.silkscreen?.bottom??DEFAULT_PCB_COLOR_MAP.silkscreen.bottom},boardOutline:colorOverrides?.boardOutline??DEFAULT_PCB_COLOR_MAP.boardOutline,soldermask:{top:colorOverrides?.soldermask?.top??DEFAULT_PCB_COLOR_MAP.soldermask.top,bottom:colorOverrides?.soldermask?.bottom??DEFAULT_PCB_COLOR_MAP.soldermask.bottom},soldermaskOverCopper:{top:colorOverrides?.soldermaskOverCopper?.top??DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.top,bottom:colorOverrides?.soldermaskOverCopper?.bottom??DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.bottom},soldermaskWithCopperUnderneath:{top:colorOverrides?.soldermaskWithCopperUnderneath?.top??DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.top,bottom:colorOverrides?.soldermaskWithCopperUnderneath?.bottom??DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.bottom},substrate:colorOverrides?.substrate??DEFAULT_PCB_COLOR_MAP.substrate,courtyard:colorOverrides?.courtyard??DEFAULT_PCB_COLOR_MAP.courtyard,keepout:colorOverrides?.keepout??DEFAULT_PCB_COLOR_MAP.keepout,debugComponent:{fill:colorOverrides?.debugComponent?.fill??DEFAULT_PCB_COLOR_MAP.debugComponent.fill,stroke:colorOverrides?.debugComponent?.stroke??DEFAULT_PCB_COLOR_MAP.debugComponent.stroke}},{minX,minY,maxX,maxY,boardMinX,boardMinY,boardMaxX,boardMaxY,hasBoardBounds}=getPcbBoundsFromCircuitJson(circuitJson),{boundsMinX,boundsMinY,boundsMaxX,boundsMaxY,padding}=getViewportBounds({circuitJson,drawPaddingOutsideBoard,baseBounds:{minX,minY,maxX,maxY,boardMinX,boardMinY,boardMaxX,boardMaxY,hasBoardBounds},viewportOptions:{viewport:options?.viewport,viewportTarget:options?.viewportTarget}}),circuitWidth=boundsMaxX-boundsMinX+2*padding,circuitHeight=boundsMaxY-boundsMinY+2*padding,svgWidth=options?.width??800,svgHeight=options?.height??600;if(options?.matchBoardAspectRatio){let viewportWidth=boundsMaxX-boundsMinX,viewportHeight=boundsMaxY-boundsMinY;if(viewportWidth>0&&viewportHeight>0){let aspect=viewportWidth/viewportHeight;options?.width&&!options?.height?svgHeight=options.width/aspect:options?.height&&!options?.width?svgWidth=options.height*aspect:svgHeight=svgWidth/aspect}}let paths=[];for(let circuitJsonElm of circuitJson)"route"in circuitJsonElm&&circuitJsonElm.route!==void 0&&paths.push(circuitJsonElm.route);let scaleX=svgWidth/circuitWidth,scaleY=svgHeight/circuitHeight,scaleFactor=Math.min(scaleX,scaleY),offsetX=(svgWidth-circuitWidth*scaleFactor)/2,offsetY=(svgHeight-circuitHeight*scaleFactor)/2,transform5=compose3(translate3(offsetX-boundsMinX*scaleFactor+padding*scaleFactor,svgHeight-offsetY+boundsMinY*scaleFactor-padding*scaleFactor),scale3(scaleFactor,-scaleFactor)),ctx={transform:transform5,layer,shouldDrawErrors:options?.shouldDrawErrors,showCourtyards:options?.showCourtyards,showPcbGroups:options?.showPcbGroups,drawPaddingOutsideBoard,colorMap:colorMap2,showSolderMask:options?.showSolderMask,showAnchorOffsets:options?.showAnchorOffsets,circuitJson},unsortedSvgObjects=circuitJson.flatMap(elm=>createSvgObjects({elm,circuitJson,ctx})),strokeWidth=String(.05*scaleFactor);for(let element of circuitJson)if("stroke_width"in element){strokeWidth=String(scaleFactor*element.stroke_width);break}if(options?.shouldDrawRatsNest){let ratsNestObjects=createSvgObjectsForRatsNest(circuitJson,ctx);unsortedSvgObjects=[...unsortedSvgObjects,...ratsNestObjects]}let svgObjects=sortSvgObjectsByPcbLayer(unsortedSvgObjects),children=[{name:"style",type:"element",value:"",attributes:{},children:[{type:"text",value:"",name:"",attributes:{},children:[]}]}],gridObjects=createSvgObjectsForPcbGrid({grid:options?.grid,svgWidth,svgHeight});if(gridObjects.defs&&children.push(gridObjects.defs),circuitJson.some(elm=>elm.type==="pcb_keepout")&&children.push(createKeepoutPatternDefs(colorMap2.keepout??DEFAULT_PCB_COLOR_MAP.keepout)),children.push({name:"rect",type:"element",value:"",attributes:{class:"boundary",x:"0",y:"0",fill:options?.backgroundColor??"#000",width:svgWidth.toString(),height:svgHeight.toString(),"data-type":"pcb_background","data-pcb-layer":"global"},children:[]}),drawPaddingOutsideBoard&&children.push(createSvgObjectFromPcbBoundary(transform5,minX,minY,maxX,maxY)),children.push(...svgObjects),gridObjects.rect&&children.push(gridObjects.rect),options?.showErrorsInTextOverlay){let errorOverlay=createErrorTextOverlay(circuitJson,"pcb_error_text_overlay");errorOverlay&&children.push(errorOverlay)}let softwareUsedString=getSoftwareUsedString(circuitJson),version=CIRCUIT_TO_SVG_VERSION,svgObject={name:"svg",type:"element",attributes:{xmlns:"http://www.w3.org/2000/svg",width:svgWidth.toString(),height:svgHeight.toString(),...softwareUsedString&&{"data-software-used-string":softwareUsedString},...options?.includeVersion&&{"data-circuit-to-svg-version":version}},value:"",children:children.filter(child=>child!==null)};try{return(0,import_svgson2.stringify)(svgObject)}catch(error){throw console.error("Error stringifying SVG object:",error),error}}function createSvgObjects({elm,circuitJson,ctx}){switch(elm.type){case"pcb_trace_error":return createSvgObjectsFromPcbTraceError(elm,circuitJson,ctx).filter(Boolean);case"pcb_footprint_overlap_error":return createSvgObjectsFromPcbFootprintOverlapError(elm,circuitJson,ctx).filter(Boolean);case"pcb_component":return createSvgObjectsFromPcbComponent(elm,ctx).filter(Boolean);case"pcb_trace":return createSvgObjectsFromPcbTrace(elm,ctx);case"pcb_copper_pour":return createSvgObjectsFromPcbCopperPour(elm,ctx);case"pcb_plated_hole":return createSvgObjectsFromPcbPlatedHole(elm,ctx).filter(Boolean);case"pcb_hole":return createSvgObjectsFromPcbHole(elm,ctx);case"pcb_smtpad":return createSvgObjectsFromSmtPad(elm,ctx);case"pcb_silkscreen_text":return createSvgObjectsFromPcbSilkscreenText(elm,ctx);case"pcb_silkscreen_rect":return createSvgObjectsFromPcbSilkscreenRect(elm,ctx);case"pcb_silkscreen_circle":return createSvgObjectsFromPcbSilkscreenCircle(elm,ctx);case"pcb_silkscreen_line":return createSvgObjectsFromPcbSilkscreenLine(elm,ctx);case"pcb_silkscreen_pill":return createSvgObjectsFromPcbSilkscreenPill(elm,ctx);case"pcb_silkscreen_oval":return createSvgObjectsFromPcbSilkscreenOval(elm,ctx);case"pcb_copper_text":return createSvgObjectsFromPcbCopperText(elm,ctx);case"pcb_courtyard_rect":return ctx.showCourtyards?createSvgObjectsFromPcbCourtyardRect(elm,ctx):[];case"pcb_courtyard_polygon":return ctx.showCourtyards?createSvgObjectsFromPcbCourtyardPolygon(elm,ctx):[];case"pcb_fabrication_note_path":return createSvgObjectsFromPcbFabricationNotePath(elm,ctx);case"pcb_fabrication_note_text":return createSvgObjectsFromPcbFabricationNoteText(elm,ctx);case"pcb_fabrication_note_rect":return createSvgObjectsFromPcbFabricationNoteRect(elm,ctx);case"pcb_fabrication_note_dimension":return createSvgObjectsFromPcbFabricationNoteDimension(elm,ctx);case"pcb_note_dimension":return createSvgObjectsFromPcbNoteDimension(elm,ctx);case"pcb_note_text":return createSvgObjectsFromPcbNoteText(elm,ctx);case"pcb_note_rect":return createSvgObjectsFromPcbNoteRect(elm,ctx);case"pcb_note_path":return createSvgObjectsFromPcbNotePath(elm,ctx);case"pcb_note_line":return createSvgObjectsFromPcbNoteLine(elm,ctx);case"pcb_silkscreen_path":return createSvgObjectsFromPcbSilkscreenPath(elm,ctx);case"pcb_panel":return ctx.drawPaddingOutsideBoard?createSvgObjectsFromPcbPanel(elm,ctx):[];case"pcb_board":return ctx.drawPaddingOutsideBoard?createSvgObjectsFromPcbBoard(elm,ctx):[];case"pcb_via":return createSvgObjectsFromPcbVia(elm,ctx);case"pcb_cutout":let cutout=elm;return cutout.shape==="path"?createSvgObjectsFromPcbCutoutPath(cutout,ctx):createSvgObjectsFromPcbCutout(elm,ctx);case"pcb_keepout":return createSvgObjectsFromPcbKeepout(elm,ctx);case"pcb_group":return ctx.showPcbGroups?createSvgObjectsFromPcbGroup(elm,ctx):[];default:return[]}}function createSvgObjectFromPcbBoundary(transform5,minX,minY,maxX,maxY){let[x12,y12]=applyToPoint3(transform5,[minX,minY]),[x22,y22]=applyToPoint3(transform5,[maxX,maxY]),width=Math.abs(x22-x12),height=Math.abs(y22-y12),x5=Math.min(x12,x22),y5=Math.min(y12,y22);return{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-boundary",fill:"none",stroke:"#fff","stroke-width":"0.3",x:x5.toString(),y:y5.toString(),width:width.toString(),height:height.toString(),"data-type":"pcb_boundary","data-pcb-layer":"global"}}}function createSvgObjectsFromAssemblyBoard(pcbBoard,transform5,style={}){let{width,height,center:center2,outline}=pcbBoard,path;if(outline&&Array.isArray(outline)&&outline.length>=3)path=outline.map((point6,index)=>{let[x5,y5]=applyToPoint3(transform5,[point6.x,point6.y]);return index===0?`M ${x5} ${y5}`:`L ${x5} ${y5}`}).join(" ");else{let halfWidth=width/2,halfHeight=height/2,topLeft=applyToPoint3(transform5,[center2.x-halfWidth,center2.y-halfHeight]),topRight=applyToPoint3(transform5,[center2.x+halfWidth,center2.y-halfHeight]),bottomRight=applyToPoint3(transform5,[center2.x+halfWidth,center2.y+halfHeight]),bottomLeft=applyToPoint3(transform5,[center2.x-halfWidth,center2.y+halfHeight]);path=`M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`}return path+=" Z",[{name:"path",type:"element",value:"",children:[],attributes:{class:"pcb-board",d:path,fill:style.fill??DEFAULT_BOARD_STYLE.fill,stroke:style.stroke??DEFAULT_BOARD_STYLE.stroke,"stroke-opacity":style.strokeOpacity??DEFAULT_BOARD_STYLE.strokeOpacity,"stroke-width":((style.strokeWidthFactor??DEFAULT_BOARD_STYLE.strokeWidthFactor)*Math.abs(transform5.a)).toString()}}]}function createSvgObjectsFromAssemblyComponent(params,ctx){let{elm,portPosition,name,arePinsInterchangeable}=params,{transform:transform5}=ctx,{center:center2,width,height,rotation:rotation4=0,layer="top"}=elm;if(!center2||typeof width!="number"||typeof height!="number")return null;let[x5,y5]=applyToPoint3(transform5,[center2.x,center2.y]),[pinX,pinY]=applyToPoint3(transform5,[portPosition.x,portPosition.y]),scaledWidth=width*Math.abs(transform5.a),scaledHeight=height*Math.abs(transform5.d),isTopLayer=layer==="top",isPinTop=pinY>y5,isPinLeft=pinX<x5,children=[createComponentPath(scaledWidth,scaledHeight,rotation4,layer),createComponentLabel(scaledWidth,scaledHeight,name??"",transform5)];return arePinsInterchangeable||children.push(createPin1Indicator(scaledWidth,scaledHeight,rotation4,layer,isPinTop,isPinLeft)),{name:"g",type:"element",value:"",attributes:{transform:`translate(${x5}, ${y5}) scale(1, -1)`},children}}function createComponentPath(scaledWidth,scaledHeight,rotation4,layer){let w4=scaledWidth/2,h4=scaledHeight/2;return{name:"path",type:"element",attributes:{class:"assembly-component",d:getRectPathData(w4,h4,rotation4),"stroke-width":.8.toFixed(2),transform:`rotate(${-rotation4})`,"stroke-dasharray":layer==="bottom"?"2,2":""},value:"",children:[]}}function createComponentLabel(scaledWidth,scaledHeight,name,transform5){let size2=Math.min(scaledWidth,scaledHeight),fontSize=Math.min(58,Math.max(3,size2*.8)),isTall=scaledHeight>scaledWidth;return{name:"text",type:"element",attributes:{x:"0",y:"0",class:"assembly-component-label","text-anchor":"middle",dy:".10em",style:"pointer-events: none","font-size":`${fontSize.toFixed(1)}px`,transform:isTall?"rotate(90) scale(1, -1)":"scale(1, -1)"},children:[{type:"text",value:name||"",name:"",attributes:{},children:[]}],value:""}}function createPin1Indicator(scaledWidth,scaledHeight,rotation4,layer,isPinTop,isPinLeft){let w4=scaledWidth/2,h4=scaledHeight/2,indicatorSize=Math.min(w4,h4)*.5,points;return isPinTop&&isPinLeft?points=[[-w4,-h4],[-w4+indicatorSize,-h4],[-w4,-h4+indicatorSize]]:isPinTop&&!isPinLeft?points=[[w4,-h4],[w4-indicatorSize,-h4],[w4,-h4+indicatorSize]]:!isPinTop&&isPinLeft?points=[[-w4,h4],[-w4+indicatorSize,h4],[-w4,h4-indicatorSize]]:points=[[w4,h4],[w4-indicatorSize,h4],[w4,h4-indicatorSize]],{name:"polygon",type:"element",attributes:{class:"assembly-pin1-indicator",points:points.map(p4=>p4.join(",")).join(" "),fill:"#333",stroke:"none",transform:`rotate(${-rotation4})`},value:"",children:[]}}function getRectPathData(w4,h4,rotation4){let rotatePoint5=(x5,y5,angle)=>{let rad=Math.PI/180*angle,cos4=Math.cos(rad),sin4=Math.sin(rad);return[x5*cos4-y5*sin4,x5*sin4+y5*cos4]};return`${[[-w4,-h4],[w4,-h4],[w4,h4],[-w4,h4]].map(([x5,y5])=>rotatePoint5(x5,y5,rotation4)).map(([x5,y5],i2)=>i2===0?`M${x5},${y5}`:`L${x5},${y5}`).join(" ")} Z`}function createSvgObjectsFromAssemblyHole(hole,ctx){let{transform:transform5}=ctx,[x5,y5]=applyToPoint3(transform5,[hole.x,hole.y]);if(hole.hole_shape==="circle"||hole.hole_shape==="square"){let scaledDiameter=hole.hole_diameter*Math.abs(transform5.a),radius=scaledDiameter/2;return hole.hole_shape==="circle"?[{name:"circle",type:"element",attributes:{class:"assembly-hole",cx:x5.toString(),cy:y5.toString(),r:radius.toString(),fill:HOLE_COLOR2},children:[],value:""}]:[{name:"rect",type:"element",attributes:{class:"assembly-hole",x:(x5-radius).toString(),y:(y5-radius).toString(),width:scaledDiameter.toString(),height:scaledDiameter.toString(),fill:HOLE_COLOR2},children:[],value:""}]}if(hole.hole_shape==="oval"){let scaledWidth=hole.hole_width*Math.abs(transform5.a),scaledHeight=hole.hole_height*Math.abs(transform5.a),rx2=scaledWidth/2,ry2=scaledHeight/2;return[{name:"ellipse",type:"element",attributes:{class:"assembly-hole",cx:x5.toString(),cy:y5.toString(),rx:rx2.toString(),ry:ry2.toString(),fill:HOLE_COLOR2},children:[],value:""}]}return[]}function createSvgObjectsFromAssemblyPlatedHole(hole,ctx){let{transform:transform5}=ctx,[x5,y5]=applyToPoint3(transform5,[hole.x,hole.y]);if(hole.shape==="pill"){let scaledOuterWidth=hole.outer_width*Math.abs(transform5.a),scaledOuterHeight=hole.outer_height*Math.abs(transform5.a),scaledHoleWidth=hole.hole_width*Math.abs(transform5.a),scaledHoleHeight=hole.hole_height*Math.abs(transform5.a),outerRadiusX=scaledOuterWidth/2,straightLength=scaledOuterHeight-scaledOuterWidth,innerRadiusX=scaledHoleWidth/2;return[{name:"g",type:"element",children:[{name:"path",type:"element",attributes:{class:"assembly-hole-outer",fill:PAD_COLOR,d:`M${x5-outerRadiusX},${y5-straightLength/2} v${straightLength} a${outerRadiusX},${outerRadiusX} 0 0 0 ${scaledOuterWidth},0 v-${straightLength} a${outerRadiusX},${outerRadiusX} 0 0 0 -${scaledOuterWidth},0 z`},value:"",children:[]},{name:"path",type:"element",attributes:{class:"assembly-hole-inner",fill:HOLE_COLOR3,d:`M${x5-innerRadiusX},${y5-(scaledHoleHeight-scaledHoleWidth)/2} v${scaledHoleHeight-scaledHoleWidth} a${innerRadiusX},${innerRadiusX} 0 0 0 ${scaledHoleWidth},0 v-${scaledHoleHeight-scaledHoleWidth} a${innerRadiusX},${innerRadiusX} 0 0 0 -${scaledHoleWidth},0 z`},value:"",children:[]}],value:"",attributes:{}}]}if(hole.shape==="circle"){let scaledOuterWidth=hole.outer_diameter*Math.abs(transform5.a),scaledOuterHeight=hole.outer_diameter*Math.abs(transform5.a),scaledHoleWidth=hole.hole_diameter*Math.abs(transform5.a),scaledHoleHeight=hole.hole_diameter*Math.abs(transform5.a),outerRadius=Math.min(scaledOuterWidth,scaledOuterHeight)/2,innerRadius=Math.min(scaledHoleWidth,scaledHoleHeight)/2;return[{name:"g",type:"element",children:[{name:"circle",type:"element",attributes:{class:"assembly-hole-outer",fill:PAD_COLOR,cx:x5.toString(),cy:y5.toString(),r:outerRadius.toString()},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"assembly-hole-inner",fill:HOLE_COLOR3,cx:x5.toString(),cy:y5.toString(),r:innerRadius.toString()},value:"",children:[]}],value:"",attributes:{}}]}if(hole.shape==="circular_hole_with_rect_pad"){let circularHole=hole,scaledHoleDiameter=circularHole.hole_diameter*Math.abs(transform5.a),scaledRectPadWidth=circularHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=circularHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(circularHole.rect_border_radius??0)*Math.abs(transform5.a),holeRadius=scaledHoleDiameter/2,[holeCx,holeCy]=applyToPoint3(transform5,[circularHole.x+circularHole.hole_offset_x,circularHole.y+circularHole.hole_offset_y]);return[{name:"g",type:"element",children:[{name:"rect",type:"element",attributes:{class:"assembly-hole-outer-pad",fill:PAD_COLOR,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{}},value:"",children:[]},{name:"circle",type:"element",attributes:{class:"assembly-hole-inner",fill:HOLE_COLOR3,cx:holeCx.toString(),cy:holeCy.toString(),r:holeRadius.toString()},value:"",children:[]}],value:"",attributes:{}}]}if(hole.shape==="pill_hole_with_rect_pad"){let pillHole=hole,scaledRectPadWidth=pillHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=pillHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(pillHole.rect_border_radius??0)*Math.abs(transform5.a),scaledHoleHeight=pillHole.hole_height*Math.abs(transform5.a),scaledHoleWidth=pillHole.hole_width*Math.abs(transform5.a),pillHoleWithOffsets=pillHole,holeOffsetX=pillHoleWithOffsets.hole_offset_x??0,holeOffsetY=pillHoleWithOffsets.hole_offset_y??0,[holeCenterX,holeCenterY]=applyToPoint3(transform5,[pillHole.x+holeOffsetX,pillHole.y+holeOffsetY]),holeRadius=Math.min(scaledHoleHeight,scaledHoleWidth)/2;return[{name:"g",type:"element",children:[{name:"rect",type:"element",attributes:{class:"assembly-hole-outer-pad",fill:PAD_COLOR,x:(x5-scaledRectPadWidth/2).toString(),y:(y5-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{}},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"assembly-hole-inner",fill:HOLE_COLOR3,x:(holeCenterX-scaledHoleWidth/2).toString(),y:(holeCenterY-scaledHoleHeight/2).toString(),width:scaledHoleWidth.toString(),height:scaledHoleHeight.toString(),rx:holeRadius.toString(),ry:holeRadius.toString()},value:"",children:[]}],value:"",attributes:{}}]}if(hole.shape==="rotated_pill_hole_with_rect_pad"){let rotatedHole=hole,scaledRectPadWidth=rotatedHole.rect_pad_width*Math.abs(transform5.a),scaledRectPadHeight=rotatedHole.rect_pad_height*Math.abs(transform5.a),scaledRectBorderRadius=(rotatedHole.rect_border_radius??0)*Math.abs(transform5.a),scaledHoleHeight=rotatedHole.hole_height*Math.abs(transform5.a),scaledHoleWidth=rotatedHole.hole_width*Math.abs(transform5.a),rotatedHoleWithOffsets=rotatedHole,holeOffsetX=rotatedHoleWithOffsets.hole_offset_x??0,holeOffsetY=rotatedHoleWithOffsets.hole_offset_y??0,[holeCenterX,holeCenterY]=applyToPoint3(transform5,[rotatedHole.x+holeOffsetX,rotatedHole.y+holeOffsetY]),holeRadius=Math.min(scaledHoleHeight,scaledHoleWidth)/2;return[{name:"g",type:"element",children:[{name:"rect",type:"element",attributes:{class:"assembly-hole-outer-pad",fill:PAD_COLOR,x:(-scaledRectPadWidth/2).toString(),y:(-scaledRectPadHeight/2).toString(),width:scaledRectPadWidth.toString(),height:scaledRectPadHeight.toString(),transform:`translate(${x5} ${y5}) rotate(${-rotatedHole.rect_ccw_rotation})`,...scaledRectBorderRadius?{rx:scaledRectBorderRadius.toString(),ry:scaledRectBorderRadius.toString()}:{}},value:"",children:[]},{name:"rect",type:"element",attributes:{class:"assembly-hole-inner",fill:HOLE_COLOR3,x:(-scaledHoleWidth/2).toString(),y:(-scaledHoleHeight/2).toString(),width:scaledHoleWidth.toString(),height:scaledHoleHeight.toString(),rx:holeRadius.toString(),ry:holeRadius.toString(),transform:`translate(${holeCenterX} ${holeCenterY}) rotate(${-rotatedHole.hole_ccw_rotation})`},value:"",children:[]}],value:"",attributes:{}}]}return[]}function createSvgObjectsFromAssemblySmtPad(pad2,ctx){let{transform:transform5}=ctx;if(pad2.shape==="rect"||pad2.shape==="rotated_rect"){let width=pad2.width*Math.abs(transform5.a),height=pad2.height*Math.abs(transform5.d),[x5,y5]=applyToPoint3(transform5,[pad2.x,pad2.y]),scaledBorderRadius=(pad2.rect_border_radius??0)*Math.abs(transform5.a);return pad2.shape==="rotated_rect"&&pad2.ccw_rotation?[{name:"rect",type:"element",attributes:{class:"assembly-pad",fill:PAD_COLOR2,x:(-width/2).toString(),y:(-height/2).toString(),width:width.toString(),height:height.toString(),transform:`translate(${x5} ${y5}) rotate(${-pad2.ccw_rotation})`,"data-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}},value:"",children:[]}]:[{name:"rect",type:"element",attributes:{class:"assembly-pad",fill:PAD_COLOR2,x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),"data-layer":pad2.layer,...scaledBorderRadius?{rx:scaledBorderRadius.toString(),ry:scaledBorderRadius.toString()}:{}},value:"",children:[]}]}if(pad2.shape==="pill"){let width=pad2.width*Math.abs(transform5.a),height=pad2.height*Math.abs(transform5.d),radius=pad2.radius*Math.abs(transform5.a),[x5,y5]=applyToPoint3(transform5,[pad2.x,pad2.y]);return[{name:"rect",type:"element",attributes:{class:"assembly-pad",fill:PAD_COLOR2,x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),rx:radius.toString(),ry:radius.toString(),"data-layer":pad2.layer},value:"",children:[]}]}if(pad2.shape==="circle"){let radius=pad2.radius*Math.abs(transform5.a),[x5,y5]=applyToPoint3(transform5,[pad2.x,pad2.y]);return[{name:"circle",type:"element",attributes:{class:"assembly-pad",fill:PAD_COLOR2,cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-layer":pad2.layer},value:"",children:[]}]}if(pad2.shape==="polygon"){let points=(pad2.points??[]).map(point6=>applyToPoint3(transform5,[point6.x,point6.y]));return[{name:"polygon",type:"element",attributes:{class:"assembly-pad",fill:PAD_COLOR2,points:points.map(p4=>p4.join(",")).join(" "),"data-layer":pad2.layer},value:"",children:[]}]}return[]}function convertCircuitJsonToAssemblySvg(soup,options){let minX=Number.POSITIVE_INFINITY,minY=Number.POSITIVE_INFINITY,maxX=Number.NEGATIVE_INFINITY,maxY=Number.NEGATIVE_INFINITY;for(let item of soup)if(item.type==="pcb_board"){let center2=item.center,width=item.width||0,height=item.height||0;minX=Math.min(minX,center2.x-width/2),minY=Math.min(minY,center2.y-height/2),maxX=Math.max(maxX,center2.x+width/2),maxY=Math.max(maxY,center2.y+height/2)}let padding=1,circuitWidth=maxX-minX+2*padding,circuitHeight=maxY-minY+2*padding,svgWidth=options?.width??800,svgHeight=options?.height??600,scaleX=svgWidth/circuitWidth,scaleY=svgHeight/circuitHeight,scaleFactor=Math.min(scaleX,scaleY),offsetX=(svgWidth-circuitWidth*scaleFactor)/2,offsetY=(svgHeight-circuitHeight*scaleFactor)/2,transform5=compose3(translate3(offsetX-minX*scaleFactor+padding*scaleFactor,svgHeight-offsetY+minY*scaleFactor-padding*scaleFactor),scale3(scaleFactor,-scaleFactor)),ctx={transform:transform5},svgObjects=soup.sort((a2,b3)=>(OBJECT_ORDER.indexOf(b3.type)??9999)-(OBJECT_ORDER.indexOf(a2.type)??9999)).flatMap(item=>createSvgObjects2(item,ctx,soup)),softwareUsedString=getSoftwareUsedString(soup),version=CIRCUIT_TO_SVG_VERSION,children=[{name:"style",type:"element",children:[{type:"text",value:`
|
|
274
274
|
.assembly-component {
|
|
@@ -332,7 +332,7 @@ svg { font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif; }
|
|
|
332
332
|
.simulation-line { fill: none; stroke-width: 2.5; }
|
|
333
333
|
.simulation-point { stroke-width: 0; }
|
|
334
334
|
.chart-title { fill: rgba(0, 0, 0, 0.85); font-size: 18px; font-weight: 600; }
|
|
335
|
-
`;return svgElement("style",{},[textNode(content)])}function createBackgroundRect(width,height){return svgElement("rect",{class:"background",x:"0",y:"0",width:formatNumber(width),height:formatNumber(height)})}function createDefsNode(clipPathId,plotWidth,plotHeight){return svgElement("defs",{},[svgElement("clipPath",{id:clipPathId},[svgElement("rect",{x:formatNumber(MARGIN.left),y:formatNumber(MARGIN.top),width:formatNumber(plotWidth),height:formatNumber(plotHeight)})])])}function createPlotBackground(plotWidth,plotHeight){return svgElement("rect",{class:"plot-background",x:formatNumber(MARGIN.left),y:formatNumber(MARGIN.top),width:formatNumber(plotWidth),height:formatNumber(plotHeight)})}function createGridLines({timeAxis,voltageAxis,scaleX,scaleY,plotWidth,plotHeight}){let top=MARGIN.top,bottom=MARGIN.top+plotHeight,left=MARGIN.left,right=MARGIN.left+plotWidth,children=[];for(let tick of timeAxis.ticks){let x5=formatNumber(scaleX(tick));children.push(svgElement("line",{class:"grid-line grid-line-x",x1:x5,y1:formatNumber(top),x2:x5,y2:formatNumber(bottom)}))}for(let tick of voltageAxis.ticks){let y5=formatNumber(scaleY(tick));children.push(svgElement("line",{class:"grid-line grid-line-y",x1:formatNumber(left),y1:y5,x2:formatNumber(right),y2:y5}))}return svgElement("g",{class:"grid"},children)}function createAxes({timeAxis,voltageAxis,scaleX,scaleY,plotWidth,plotHeight}){let bottom=MARGIN.top+plotHeight,left=MARGIN.left,right=MARGIN.left+plotWidth,children=[svgElement("line",{class:"axis axis-x",x1:formatNumber(left),y1:formatNumber(bottom),x2:formatNumber(right),y2:formatNumber(bottom)}),svgElement("line",{class:"axis axis-y",x1:formatNumber(left),y1:formatNumber(MARGIN.top),x2:formatNumber(left),y2:formatNumber(bottom)})];for(let tick of timeAxis.ticks){let x5=formatNumber(scaleX(tick));children.push(svgElement("line",{class:"axis-tick axis-tick-x",x1:x5,y1:formatNumber(bottom),x2:x5,y2:formatNumber(bottom+6)})),children.push(svgElement("text",{class:"axis-label axis-label-x",x:x5,y:formatNumber(bottom+22),"text-anchor":"middle"},[textNode(formatTickLabel(tick,timeAxis.ticks))]))}for(let tick of voltageAxis.ticks){let y5=formatNumber(scaleY(tick));children.push(svgElement("line",{class:"axis-tick axis-tick-y",x1:formatNumber(left-6),y1:y5,x2:formatNumber(left),y2:y5})),children.push(svgElement("text",{class:"axis-label axis-label-y",x:formatNumber(left-10),y:y5,"text-anchor":"end","dominant-baseline":"middle"},[textNode(formatTickLabel(tick,voltageAxis.ticks))]))}return children.push(svgElement("text",{class:"axis-title axis-title-x",x:formatNumber(left+plotWidth/2),y:formatNumber(bottom+48),"text-anchor":"middle"},[textNode("Time (ms)")]),svgElement("text",{class:"axis-title axis-title-y",x:formatNumber(left-64),y:formatNumber(MARGIN.top+plotHeight/2),transform:`rotate(-90 ${formatNumber(left-64)} ${formatNumber(MARGIN.top+plotHeight/2)})`,"text-anchor":"middle"},[textNode("Voltage (V)")])),svgElement("g",{class:"axes"},children)}function createLegend(graphs,width){let currentY=MARGIN.top,children=graphs.map(entry=>{let x5=width-MARGIN.right+10,lines=wrapLegendText(entry.label),legendItem=createLegendItem(entry,x5,currentY,lines),itemHeight=lines.length*LEGEND_LINE_HEIGHT;return currentY+=Math.max(itemHeight,LEGEND_MIN_SPACING),legendItem});return svgElement("g",{class:"legend"},children)}function wrapLegendText(label){let parts=label.split("_");if(parts.length<=1)return[label];let lines=[],currentLine=parts[0]??"";for(let i2=1;i2<parts.length;i2++){let part=parts[i2]??"",testLine=currentLine+"_"+part;testLine.length>MAX_LEGEND_LINE_LENGTH?(lines.push(currentLine),currentLine=part):currentLine=testLine}return currentLine&&lines.push(currentLine),lines}function createLegendItem(entry,x5,y5,lines){let textChildren=lines.map((line2,index)=>svgElement("tspan",{x:"20",dy:index===0?"0":String(LEGEND_LINE_HEIGHT)},[textNode(line2)]));return svgElement("g",{class:"legend-item",transform:`translate(${formatNumber(x5)} ${formatNumber(y5)})`},[svgElement("line",{class:"legend-line",x1:"0",y1:"0",x2:"16",y2:"0",stroke:entry.color}),svgElement("text",{class:"legend-label",x:"20",y:"0","dominant-baseline":"middle"},textChildren)])}function createDataGroup(graphs,clipPathId,scaleX,scaleY){let DASH_PATTERN=[4,8],dashArrayString=DASH_PATTERN.map(value=>formatNumber(value)).join(" "),dashOffsetStep=DASH_PATTERN.reduce((sum,value)=>sum+value,0)/3,processedGraphs=[];graphs.forEach((entry,graphIndex)=>{if(entry.points.length===0)return;let commands=[];entry.points.forEach((point6,index)=>{let x5=formatNumber(scaleX(point6.timeMs)),y5=formatNumber(scaleY(point6.voltage));commands.push(`${index===0?"M":"L"} ${x5} ${y5}`)});let baseAttributes={class:"simulation-line",d:commands.join(" "),stroke:entry.color,"clip-path":`url(#${clipPathId})`,"data-simulation-transient-voltage-graph-id":entry.graph.simulation_transient_voltage_graph_id};entry.graph.source_component_id&&(baseAttributes["data-source-component-id"]=entry.graph.source_component_id),entry.graph.subcircuit_connectivity_map_key&&(baseAttributes["data-subcircuit-connectivity-map-key"]=entry.graph.subcircuit_connectivity_map_key);let pointElements2=entry.points.map(point6=>{let cx2=formatNumber(scaleX(point6.timeMs)),cy2=formatNumber(scaleY(point6.voltage));return svgElement("circle",{class:"simulation-point",cx:cx2,cy:cy2,r:"2.5",fill:entry.color,"clip-path":`url(#${clipPathId})`})});processedGraphs.push({entry,graphIndex,pathAttributes:baseAttributes,pointElements:pointElements2})});let lineElements=[];for(let cycle=0;cycle<3;cycle++)processedGraphs.forEach(graphInfo=>{let offsetIndex=(graphInfo.graphIndex+cycle)%3,dashOffset=formatNumber(offsetIndex*dashOffsetStep);lineElements.push(svgElement("path",{...graphInfo.pathAttributes,"stroke-dasharray":dashArrayString,"stroke-dashoffset":dashOffset}))});let pointElements=processedGraphs.flatMap(graphInfo=>graphInfo.pointElements);return svgElement("g",{class:"data-series"},[...lineElements,...pointElements])}function createTitleNode(experiment,width){return experiment?.name?svgElement("text",{class:"chart-title",x:formatNumber(width/2),y:formatNumber(MARGIN.top-40),"text-anchor":"middle"},[textNode(experiment.name)]):null}function createClipPathId(simulationExperimentId){return`simulation-graph-${simulationExperimentId.replace(/[^a-zA-Z0-9_-]+/g,"-")}`}function formatNumber(value){if(!Number.isFinite(value))return"0";let rounded=Number.parseFloat(value.toFixed(6));return Number.isInteger(rounded),rounded.toString()}function formatTickLabel(value,ticks){if(ticks.length<=1)return formatNumber(value);let span=ticks[ticks.length-1]-ticks[0];if(!Number.isFinite(span)||span===0)return formatNumber(value);let precision=span>=100?0:span>=10?1:span>=1?2:3,factor=Math.pow(10,precision);return(Math.round(value*factor)/factor).toFixed(precision).replace(/\.0+$/,"").replace(/(\.\d*?)0+$/,"$1").replace(/\.$/,"")}function svgElement(name,attributes2,children=[]){return{name,type:"element",value:"",attributes:attributes2,children}}function textNode(value){return{name:"",type:"text",value,attributes:{},children:[]}}function convertCircuitJsonToSchematicSimulationSvg({circuitJson,simulation_experiment_id,simulation_transient_voltage_graph_ids,width=DEFAULT_WIDTH2,height=DEFAULT_HEIGHT2,schematicHeightRatio=DEFAULT_SCHEMATIC_RATIO,schematicOptions,includeVersion,graphAboveSchematic=!1,showErrorsInTextOverlay}){let schematicElements=circuitJson.filter(element=>!isSimulationExperiment(element)&&!isSimulationTransientVoltageGraph(element)),clampedRatio=clamp01(schematicHeightRatio),rawSchematicHeight=Math.max(1,height*clampedRatio),rawSimulationHeight=Math.max(1,height-rawSchematicHeight),totalRawHeight=rawSchematicHeight+rawSimulationHeight,scale10=totalRawHeight===0?1:height/totalRawHeight,schematicHeight=rawSchematicHeight*scale10,simulationHeight=rawSimulationHeight*scale10,schematicSvg=convertCircuitJsonToSchematicSvg(schematicElements,{...schematicOptions,width,height:schematicHeight,includeVersion:!1,showErrorsInTextOverlay}),simulationSvg=convertCircuitJsonToSimulationGraphSvg({circuitJson,simulation_experiment_id,simulation_transient_voltage_graph_ids,width,height:simulationHeight,includeVersion:!1}),schematicNode=ensureElementNode((0,import_svgson10.parseSync)(schematicSvg)),simulationNode=ensureElementNode((0,import_svgson10.parseSync)(simulationSvg)),combinedChildren=[];graphAboveSchematic?(combinedChildren.push(translateNestedSvg(simulationNode,0,0,width,simulationHeight)),combinedChildren.push(translateNestedSvg(schematicNode,0,simulationHeight,width,schematicHeight))):(combinedChildren.push(translateNestedSvg(schematicNode,0,0,width,schematicHeight)),combinedChildren.push(translateNestedSvg(simulationNode,0,schematicHeight,width,simulationHeight)));let softwareUsedString=getSoftwareUsedString(schematicElements),svgObject={name:"svg",type:"element",value:"",attributes:{xmlns:"http://www.w3.org/2000/svg",width:formatNumber2(width),height:formatNumber2(height),viewBox:`0 0 ${formatNumber2(width)} ${formatNumber2(height)}`,"data-simulation-experiment-id":simulation_experiment_id,...softwareUsedString&&{"data-software-used-string":softwareUsedString},...includeVersion&&{"data-circuit-to-svg-version":CIRCUIT_TO_SVG_VERSION}},children:combinedChildren};return(0,import_svgson10.stringify)(svgObject)}function translateNestedSvg(node,x5,y5,width,height){let clone=cloneSvgObject(node);return clone.attributes={...clone.attributes,x:formatNumber2(x5),y:formatNumber2(y5),width:formatNumber2(width),height:formatNumber2(height)},delete clone.attributes.xmlns,clone}function ensureElementNode(node){if(node.type!=="element")throw new Error("Expected SVG root element to be of type 'element'");return node}function cloneSvgObject(node){return{...node,attributes:{...node.attributes??{}},children:node.children?.map(cloneSvgObject)??[]}}function clamp01(value){return Number.isFinite(value)?value<=0?0:value>=1?1:value:DEFAULT_SCHEMATIC_RATIO}function formatNumber2(value){if(!Number.isFinite(value))return"0";let rounded=Number.parseFloat(value.toFixed(6));return Number.isInteger(rounded),rounded.toString()}function createSvgObjectsFromSolderPaste(solderPaste,ctx){let{transform:transform5,layer:layerFilter}=ctx;if(layerFilter&&solderPaste.layer!==layerFilter)return[];let[x5,y5]=applyToPoint3(transform5,[solderPaste.x,solderPaste.y]);if(solderPaste.shape==="rect"||solderPaste.shape==="rotated_rect"){let width=solderPaste.width*Math.abs(transform5.a),height=solderPaste.height*Math.abs(transform5.d);return solderPaste.shape==="rotated_rect"&&solderPaste.ccw_rotation?[{name:"rect",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),x:(-width/2).toString(),y:(-height/2).toString(),width:width.toString(),height:height.toString(),transform:`translate(${x5} ${y5}) rotate(${-solderPaste.ccw_rotation})`,"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]:[{name:"rect",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]}if(solderPaste.shape==="pill"){let width=solderPaste.width*Math.abs(transform5.a),height=solderPaste.height*Math.abs(transform5.d),radius=solderPaste.radius*Math.abs(transform5.a);return[{name:"rect",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),rx:radius.toString(),"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]}if(solderPaste.shape==="circle"){let radius=solderPaste.radius*Math.abs(transform5.a);return[{name:"circle",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]}}function convertCircuitJsonToSolderPasteMask(circuitJson,options){let minX=Number.POSITIVE_INFINITY,minY=Number.POSITIVE_INFINITY,maxX=Number.NEGATIVE_INFINITY,maxY=Number.NEGATIVE_INFINITY,filteredCircuitJson=circuitJson.filter(elm=>elm.type==="pcb_board"||elm.type==="pcb_panel"||elm.type==="pcb_solder_paste"&&elm.layer===options.layer);for(let item of filteredCircuitJson)if(item.type==="pcb_board")item.outline&&Array.isArray(item.outline)&&item.outline.length>=3?updateBoundsToIncludeOutline(item.outline):"center"in item&&"width"in item&&"height"in item&&updateBounds(item.center,item.width,item.height);else if(item.type==="pcb_panel"){let panel=item,width=distance.parse(panel.width),height=distance.parse(panel.height);if(width!==void 0&&height!==void 0){let center2=panel.center??{x:width/2,y:height/2};updateBounds(center2,width,height)}}else item.type==="pcb_solder_paste"&&"x"in item&&"y"in item&&updateBounds({x:item.x,y:item.y},0,0);let padding=1,circuitWidth=maxX-minX+2*padding,circuitHeight=maxY-minY+2*padding,svgWidth=options.width??800,svgHeight=options.height??600,scaleX=svgWidth/circuitWidth,scaleY=svgHeight/circuitHeight,scaleFactor=Math.min(scaleX,scaleY),offsetX=(svgWidth-circuitWidth*scaleFactor)/2,offsetY=(svgHeight-circuitHeight*scaleFactor)/2,transform5=compose3(translate3(offsetX-minX*scaleFactor+padding*scaleFactor,svgHeight-offsetY+minY*scaleFactor-padding*scaleFactor),scale3(scaleFactor,-scaleFactor)),ctx={transform:transform5,layer:options.layer,colorMap:DEFAULT_PCB_COLOR_MAP},svgObjects=filteredCircuitJson.sort((a2,b3)=>(OBJECT_ORDER3.indexOf(b3.type)??9999)-(OBJECT_ORDER3.indexOf(a2.type)??9999)).flatMap(item=>createSvgObjects4({elm:item,ctx})),softwareUsedString=getSoftwareUsedString(circuitJson),version=CIRCUIT_TO_SVG_VERSION,children=[{name:"style",type:"element",children:[{type:"text",value:""}]},{name:"rect",type:"element",attributes:{class:"boundary",x:"0",y:"0",fill:"#000",width:svgWidth.toString(),height:svgHeight.toString()}},createSvgObjectFromPcbBoundary2(transform5,minX,minY,maxX,maxY),...svgObjects].filter(child=>child!==null);if(options?.showErrorsInTextOverlay){let errorOverlay=createErrorTextOverlay(circuitJson);errorOverlay&&children.push(errorOverlay)}let svgObject={name:"svg",type:"element",attributes:{xmlns:"http://www.w3.org/2000/svg",width:svgWidth.toString(),height:svgHeight.toString(),...softwareUsedString&&{"data-software-used-string":softwareUsedString},...options.includeVersion&&{"data-circuit-to-svg-version":version}},value:"",children};try{return(0,import_svgson12.stringify)(svgObject)}catch(error){throw console.error("Error stringifying SVG object:",error),error}function updateBounds(center2,width,height){let halfWidth=width/2,halfHeight=height/2;minX=Math.min(minX,center2.x-halfWidth),minY=Math.min(minY,center2.y-halfHeight),maxX=Math.max(maxX,center2.x+halfWidth),maxY=Math.max(maxY,center2.y+halfHeight)}function updateBoundsToIncludeOutline(outline){for(let point6 of outline)minX=Math.min(minX,point6.x),minY=Math.min(minY,point6.y),maxX=Math.max(maxX,point6.x),maxY=Math.max(maxY,point6.y)}}function createSvgObjects4({elm,ctx}){let{transform:transform5}=ctx;switch(elm.type){case"pcb_board":return createSvgObjectsFromPcbBoard(elm,ctx);case"pcb_solder_paste":return createSvgObjectsFromSolderPaste(elm,ctx);default:return[]}}function createSvgObjectFromPcbBoundary2(transform5,minX,minY,maxX,maxY){let[x12,y12]=applyToPoint3(transform5,[minX,minY]),[x22,y22]=applyToPoint3(transform5,[maxX,maxY]),width=Math.abs(x22-x12),height=Math.abs(y22-y12),x5=Math.min(x12,x22),y5=Math.min(y12,y22);return{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-boundary",fill:"none",stroke:"#fff","stroke-width":"0.3",x:x5.toString(),y:y5.toString(),width:width.toString(),height:height.toString()}}}var import_svgson2,import_svgson3,import_svgson4,import_svgson5,import_svgson6,import_svgson7,import_svgson8,import_svgson9,import_svgson10,import_svgson11,import_svgson12,DEFAULT_OVERLAY_STROKE_COLOR,DEFAULT_OVERLAY_FILL_COLOR,TEXT_OFFSET_MULTIPLIER,CHARACTER_WIDTH_MULTIPLIER,TEXT_INTERSECTION_PADDING_MULTIPLIER,colorMap,DEFAULT_OVERLAY_COLOR,DEFAULT_OVERLAY_COLOR2,DEFAULT_FILL_COLOR,DEFAULT_OVERLAY_COLOR3,DEFAULT_OVERLAY_COLOR4,DEFAULT_PCB_COLOR_MAP,HOLE_COLOR,SILKSCREEN_TOP_COLOR,SILKSCREEN_BOTTOM_COLOR,LAYER_NAME_TO_COLOR,SOLDER_PASTE_LAYER_NAME_TO_COLOR,CHAR_WIDTH,CHAR_SPACING,LINE_HEIGHT,FONT_SCALE,maskIdCounter,OFFSET_THRESHOLD_MM,TICK_SIZE_PX,LABEL_GAP_PX,LABEL_FONT_SIZE_PX,STROKE_WIDTH_PX,ANCHOR_MARKER_SIZE_PX,ANCHOR_MARKER_STROKE_WIDTH_PX,COMPONENT_ANCHOR_MARKER_RADIUS_PX,CONNECTOR_GROUP_GAP_PX,CONNECTOR_COMPONENT_GAP_PX,DIMENSION_ANCHOR_CLEARANCE_PX,COMPONENT_GAP_PX,COMPONENT_SIDE_GAP_PX,DISTANCE_MULTIPLIER,MAX_OFFSET_PX,getElementPosition,findNearestPointInNet,KEEPOUT_PATTERN_ID,KEEPOUT_PATTERN_SIZE,KEEPOUT_LINE_SPACING,KEEPOUT_BACKGROUND_COLOR,DEFAULT_GRID_LINE_COLOR,GRID_PATTERN_ID,DEFAULT_GROUP_COLOR,DEFAULT_STROKE_WIDTH,package_default2,CIRCUIT_TO_SVG_VERSION,TYPE_PRIORITY,DEFAULT_TYPE_PRIORITY,getViewportBounds,circuitJsonToPcbSvg,DEFAULT_BOARD_STYLE,fontSizeMap,getSchMmFontSize,getSchScreenFontSize,HOLE_COLOR2,PAD_COLOR,HOLE_COLOR3,PAD_COLOR2,OBJECT_ORDER,BOARD_FILL_COLOR,BOARD_STROKE_COLOR,COMPONENT_FILL_COLOR,COMPONENT_LABEL_COLOR,HOLE_COLOR4,PAD_COLOR3,HOLE_COLOR5,PAD_COLOR4,LABEL_COLOR,LABEL_BACKGROUND,LINE_COLOR,PIN_NUMBER_BACKGROUND,PIN_NUMBER_COLOR,LABEL_RECT_HEIGHT_BASE_MM,FONT_HEIGHT_RATIO,CHAR_WIDTH_FACTOR,STAGGER_OFFSET_MIN,STAGGER_OFFSET_PER_PIN,STAGGER_OFFSET_STEP,ALIGNED_OFFSET_MARGIN,GROUP_SEPARATION_MM,calculateLabelPositions,OBJECT_ORDER2,arialTextMetrics,estimateTextWidth,getTableDimensions,getUnitVectorFromOutsideToEdge,ARROW_POINT_WIDTH_FSR,END_PADDING_FSR,END_PADDING_EXTRA_PER_CHARACTER_FSR,ninePointAnchorToTextAnchor,ninePointAnchorToDominantBaseline,getSchStrokeSize,getAngularDifference,matchSchPortsToSymbolPorts,createSvgSchErrorText,isSourcePortConnected,ninePointAnchorToTextAnchor2,createSvgObjectsFromSchematicComponentWithSymbol,PIN_CIRCLE_RADIUS_MM,createArrow,createSvgObjectsForSchPortBoxLine,createSvgObjectsForSchPortPinNumberText,LABEL_DIST_FROM_EDGE_MM,createSvgObjectsForSchPortPinLabel,createSvgObjectsFromSchPortOnBox,createSvgSchText,createSvgObjectsFromSchematicComponentWithBox,createSvgObjectsForSchNetLabelWithSymbol,createSvgObjectsForSchNetLabel,createSvgObjectsFromSchematicBox,createSvgObjectsFromSchematicTable,PIN_CIRCLE_RADIUS_MM2,createSvgObjectsForSchPortHover,createSvgObjectsForSchComponentPortHovers,circuitJsonToSchematicSvg,DEFAULT_WIDTH,DEFAULT_HEIGHT,MARGIN,FALLBACK_LINE_COLOR,MAX_LEGEND_LINE_LENGTH,LEGEND_LINE_HEIGHT,LEGEND_MIN_SPACING,DEFAULT_WIDTH2,DEFAULT_HEIGHT2,DEFAULT_SCHEMATIC_RATIO,OBJECT_ORDER3,init_dist8=__esm({"node_modules/circuit-to-svg/dist/index.js"(){"use strict";init_dist();import_svgson2=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist();init_dist7();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist4();import_svgson3=__toESM(require_svgson_umd(),1);init_src2();init_dist6();init_dist4();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();import_svgson4=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_dist();init_dist();import_svgson5=__toESM(require_svgson_umd(),1);init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();import_svgson6=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_dist6();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist5();init_src2();init_dist6();import_svgson7=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_src2();init_src2();init_dist2();init_svg_path_commander();init_dist6();init_dist2();import_svgson8=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_src2();init_dist6();init_dist2();import_svgson9=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_dist6();init_src2();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist2();init_src2();init_src2();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();import_svgson10=__toESM(require_svgson_umd(),1),import_svgson11=__toESM(require_svgson_umd(),1);init_dist();import_svgson12=__toESM(require_svgson_umd(),1);init_src2();init_src2();DEFAULT_OVERLAY_STROKE_COLOR="rgba(255,255,255,0.5)",DEFAULT_OVERLAY_FILL_COLOR="rgba(255,255,255,0.2)";TEXT_OFFSET_MULTIPLIER=1.5,CHARACTER_WIDTH_MULTIPLIER=.6,TEXT_INTERSECTION_PADDING_MULTIPLIER=.3;colorMap={"3d_viewer":{background_bottom:"rgb(102, 102, 128)",background_top:"rgb(204, 204, 230)",board:"rgb(51, 43, 23)",copper:"rgb(179, 156, 0)",silkscreen_bottom:"rgb(230, 230, 230)",silkscreen_top:"rgb(230, 230, 230)",soldermask:"rgb(20, 51, 36)",solderpaste:"rgb(128, 128, 128)"},board:{anchor:"rgb(255, 38, 226)",aux_items:"rgb(255, 255, 255)",b_adhes:"rgb(0, 0, 132)",b_crtyd:"rgb(255, 38, 226)",b_fab:"rgb(88, 93, 132)",b_mask:"rgba(2, 255, 238, 0.400)",b_paste:"rgb(0, 194, 194)",b_silks:"rgb(232, 178, 167)",background:"rgb(0, 16, 35)",cmts_user:"rgb(89, 148, 220)",copper:{b:"rgb(77, 127, 196)",f:"rgb(200, 52, 52)",in1:"rgb(127, 200, 127)",in10:"rgb(237, 124, 51)",in11:"rgb(91, 195, 235)",in12:"rgb(247, 111, 142)",in13:"rgb(167, 165, 198)",in14:"rgb(40, 204, 217)",in15:"rgb(232, 178, 167)",in16:"rgb(242, 237, 161)",in17:"rgb(237, 124, 51)",in18:"rgb(91, 195, 235)",in19:"rgb(247, 111, 142)",in2:"rgb(206, 125, 44)",in20:"rgb(167, 165, 198)",in21:"rgb(40, 204, 217)",in22:"rgb(232, 178, 167)",in23:"rgb(242, 237, 161)",in24:"rgb(237, 124, 51)",in25:"rgb(91, 195, 235)",in26:"rgb(247, 111, 142)",in27:"rgb(167, 165, 198)",in28:"rgb(40, 204, 217)",in29:"rgb(232, 178, 167)",in3:"rgb(79, 203, 203)",in30:"rgb(242, 237, 161)",in4:"rgb(219, 98, 139)",in5:"rgb(167, 165, 198)",in6:"rgb(40, 204, 217)",in7:"rgb(232, 178, 167)",in8:"rgb(242, 237, 161)",in9:"rgb(141, 203, 129)"},cursor:"rgb(255, 255, 255)",drc:"rgb(194, 194, 194)",drc_error:"rgba(215, 91, 107, 0.800)",drc_exclusion:"rgb(255, 255, 255)",drc_warning:"rgba(255, 208, 66, 0.902)",dwgs_user:"rgb(194, 194, 194)",eco1_user:"rgb(180, 219, 210)",eco2_user:"rgb(216, 200, 82)",edge_cuts:"rgb(208, 210, 205)",f_adhes:"rgb(132, 0, 132)",f_crtyd:"rgb(255, 0, 245)",f_fab:"rgb(175, 175, 175)",f_mask:"rgba(216, 100, 255, 0.400)",f_paste:"rgba(180, 160, 154, 0.902)",f_silks:"rgb(242, 237, 161)",footprint_text_back:"rgb(0, 0, 132)",footprint_text_front:"rgb(194, 194, 194)",footprint_text_invisible:"rgb(132, 132, 132)",grid:"rgb(132, 132, 132)",grid_axes:"rgb(194, 194, 194)",margin:"rgb(255, 38, 226)",microvia:"rgb(0, 132, 132)",no_connect:"rgb(0, 0, 132)",pad_back:"rgb(77, 127, 196)",pad_front:"rgb(200, 52, 52)",pad_plated_hole:"rgb(194, 194, 0)",pad_through_hole:"rgb(227, 183, 46)",plated_hole:"rgb(26, 196, 210)",ratsnest:"rgba(245, 255, 213, 0.702)",select_overlay:"rgb(4, 255, 67)",through_via:"rgb(236, 236, 236)",user_1:"rgb(194, 194, 194)",user_2:"rgb(89, 148, 220)",user_3:"rgb(180, 219, 210)",user_4:"rgb(216, 200, 82)",user_5:"rgb(194, 194, 194)",user_6:"rgb(89, 148, 220)",user_7:"rgb(180, 219, 210)",user_8:"rgb(216, 200, 82)",user_9:"rgb(232, 178, 167)",via_blind_buried:"rgb(187, 151, 38)",via_hole:"rgb(227, 183, 46)",via_micro:"rgb(0, 132, 132)",via_through:"rgb(236, 236, 236)",worksheet:"rgb(200, 114, 171)"},gerbview:{axes:"rgb(0, 0, 132)",background:"rgb(0, 0, 0)",dcodes:"rgb(255, 255, 255)",grid:"rgb(132, 132, 132)",layers:["rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)","rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)","rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)","rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)"],negative_objects:"rgb(132, 132, 132)",worksheet:"rgb(0, 0, 132)"},meta:{filename:"kicad_2020",name:"KiCad 2020",version:2},palette:["rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)"],schematic:{aux_items:"rgb(46, 46, 46)",background:"rgb(245, 241, 237)",brightened:"rgb(255, 0, 255)",bus:"rgb(0, 0, 132)",bus_junction:"rgb(0, 0, 132)",component_body:"rgb(255, 255, 194)",component_outline:"rgb(132, 0, 0)",cursor:"rgb(15, 15, 15)",erc_error:"rgba(230, 9, 13, 0.800)",erc_warning:"rgba(209, 146, 0, 0.800)",fields:"rgb(132, 0, 132)",grid:"rgb(181, 181, 181)",grid_axes:"rgb(0, 0, 132)",hidden:"rgb(194, 194, 194)",junction:"rgb(0, 150, 0)",label_global:"rgb(132, 0, 0)",label_background:"rgba(255, 255, 255, 0.6)",label_hier:"rgb(114, 86, 0)",label_local:"rgb(15, 15, 15)",net_name:"rgb(132, 132, 132)",no_connect:"rgb(0, 0, 132)",note:"rgb(0, 0, 194)",override_item_colors:!1,pin:"rgb(132, 0, 0)",pin_name:"rgb(0, 100, 100)",pin_number:"rgb(169, 0, 0)",reference:"rgb(0, 100, 100)",shadow:"rgba(102, 179, 255, 0.800)",sheet:"rgb(132, 0, 0)",sheet_background:"rgba(253, 255, 231, 0.000)",sheet_fields:"rgb(132, 0, 132)",sheet_filename:"rgb(114, 86, 0)",sheet_label:"rgb(0, 100, 100)",sheet_name:"rgb(0, 100, 100)",table:"rgb(102, 102, 102)",value:"rgb(0, 100, 100)",wire:"rgb(0, 150, 0)",wire_crossing:"rgb(30, 180, 30)",worksheet:"rgb(132, 0, 0)"}};DEFAULT_OVERLAY_COLOR=colorMap.board.user_2;DEFAULT_OVERLAY_COLOR2=colorMap.board.user_2,DEFAULT_FILL_COLOR=colorMap.board.user_2;DEFAULT_OVERLAY_COLOR3=colorMap.board.user_2;DEFAULT_OVERLAY_COLOR4=colorMap.board.user_2;DEFAULT_PCB_COLOR_MAP={copper:{top:"rgb(200, 52, 52)",inner1:"rgb(255, 140, 0)",inner2:"rgb(255, 215, 0)",inner3:"rgb(50, 205, 50)",inner4:"rgb(64, 224, 208)",inner5:"rgb(138, 43, 226)",inner6:"rgb(255, 105, 180)",bottom:"rgb(77, 127, 196)"},soldermaskWithCopperUnderneath:{top:"rgb(18, 82, 50)",bottom:"rgb(77, 127, 196)"},soldermask:{top:"rgb(12, 55, 33)",bottom:"rgb(12, 55, 33)"},soldermaskOverCopper:{top:"rgb(52, 135, 73)",bottom:"rgb(52, 135, 73)"},substrate:"rgb(201, 162, 110)",drill:"#FF26E2",silkscreen:{top:"#f2eda1",bottom:"#5da9e9"},boardOutline:"rgba(255, 255, 255, 0.5)",courtyard:"#FF00FF",keepout:"#FF6B6B",debugComponent:{fill:null,stroke:null}},HOLE_COLOR=DEFAULT_PCB_COLOR_MAP.drill,SILKSCREEN_TOP_COLOR=DEFAULT_PCB_COLOR_MAP.silkscreen.top,SILKSCREEN_BOTTOM_COLOR=DEFAULT_PCB_COLOR_MAP.silkscreen.bottom,LAYER_NAME_TO_COLOR={...DEFAULT_PCB_COLOR_MAP.copper};SOLDER_PASTE_LAYER_NAME_TO_COLOR={bottom:"rgb(105, 105, 105)",top:"rgb(105, 105, 105)"};CHAR_WIDTH=1,CHAR_SPACING=.2,LINE_HEIGHT=1.4,FONT_SCALE=.53;maskIdCounter=0;OFFSET_THRESHOLD_MM=.05,TICK_SIZE_PX=4,LABEL_GAP_PX=8,LABEL_FONT_SIZE_PX=11,STROKE_WIDTH_PX=1,ANCHOR_MARKER_SIZE_PX=5,ANCHOR_MARKER_STROKE_WIDTH_PX=1.5,COMPONENT_ANCHOR_MARKER_RADIUS_PX=2,CONNECTOR_GROUP_GAP_PX=ANCHOR_MARKER_SIZE_PX+2,CONNECTOR_COMPONENT_GAP_PX=COMPONENT_ANCHOR_MARKER_RADIUS_PX+2,DIMENSION_ANCHOR_CLEARANCE_PX=ANCHOR_MARKER_SIZE_PX+TICK_SIZE_PX+6,COMPONENT_GAP_PX=15,COMPONENT_SIDE_GAP_PX=10,DISTANCE_MULTIPLIER=.2,MAX_OFFSET_PX=50;getElementPosition=(id,circuitJson)=>{let pcbSmtpad=su2(circuitJson).pcb_smtpad.get(id);if(pcbSmtpad&&"x"in pcbSmtpad&&"y"in pcbSmtpad)return{x:pcbSmtpad.x,y:pcbSmtpad.y};let pcbPlatedHole=su2(circuitJson).pcb_plated_hole.get(id);return pcbPlatedHole&&"x"in pcbPlatedHole&&"y"in pcbPlatedHole?{x:pcbPlatedHole.x,y:pcbPlatedHole.y}:null},findNearestPointInNet=(sourcePoint,netId,connectivity,circuitJson)=>{let connectedIds=connectivity.getIdsConnectedToNet(netId),nearestPoint=null,minDistance=1/0;for(let id of connectedIds){let pos=getElementPosition(id,circuitJson);if(pos){let dx2=sourcePoint.x-pos.x,dy2=sourcePoint.y-pos.y,distance62=Math.sqrt(dx2*dx2+dy2*dy2);distance62>0&&distance62<minDistance&&(minDistance=distance62,nearestPoint=pos)}}return nearestPoint};KEEPOUT_PATTERN_ID="pcb-keepout-pattern",KEEPOUT_PATTERN_SIZE=20,KEEPOUT_LINE_SPACING=5,KEEPOUT_BACKGROUND_COLOR="rgba(255, 107, 107, 0.2)";DEFAULT_GRID_LINE_COLOR="rgba(255, 255, 255, 0.5)",GRID_PATTERN_ID="pcb-grid-pattern";DEFAULT_GROUP_COLOR="rgba(100, 200, 255, 0.6)",DEFAULT_STROKE_WIDTH=.1;package_default2={name:"circuit-to-svg",type:"module",version:"0.0.318",description:"Convert Circuit JSON to SVG",main:"dist/index.js",files:["dist"],scripts:{start:"cosmos",prepublish:"npm run build",build:"tsup-node ./lib/index.ts --format esm --dts --sourcemap --external tscircuit",format:"biome format . --write","format:check":"biome format .",cosmos:"cosmos","cosmos-export":"cosmos-export"},license:"ISC",devDependencies:{"@biomejs/biome":"^1.9.4","@tscircuit/alphabet":"^0.0.17","@types/bun":"^1.2.8","@vitejs/plugin-react":"5.0.0",biome:"^0.3.3","bun-match-svg":"^0.0.12","circuit-json":"^0.0.363",esbuild:"^0.20.2","performance-now":"^2.1.0",react:"19.1.0","react-cosmos":"7.0.0","react-cosmos-plugin-vite":"7.0.0","react-dom":"19.1.0",tscircuit:"^0.0.1059",tsup:"^8.0.2",typescript:"^5.4.5","vite-tsconfig-paths":"^5.0.1"},peerDependencies:{"@tscircuit/alphabet":"*"},dependencies:{"@types/node":"^22.5.5","bun-types":"^1.1.40","calculate-elbow":"0.0.12","svg-path-commander":"^2.1.11",svgson:"^5.3.1","transformation-matrix":"^2.16.1"}},CIRCUIT_TO_SVG_VERSION=package_default2.version,TYPE_PRIORITY={pcb_background:0,pcb_boundary:1,pcb_panel:5,pcb_board:10,pcb_cutout:15,pcb_cutout_path:15,pcb_keepout:16,pcb_hole:18,pcb_plated_hole_drill:19,pcb_plated_hole:20,pcb_trace_soldermask:25,pcb_trace:30,pcb_smtpad:30,pcb_copper_pour:35,pcb_via:36,pcb_soldermask:40,pcb_soldermask_opening:25,pcb_solder_paste:45,pcb_silkscreen_text:50,pcb_silkscreen_path:50,pcb_silkscreen_rect:50,pcb_silkscreen_circle:50,pcb_silkscreen_line:50,pcb_silkscreen_oval:50,pcb_silkscreen_pill:50,pcb_component:60,pcb_fabrication_note_text:70,pcb_fabrication_note_path:70,pcb_fabrication_note_rect:70,pcb_fabrication_note_dimension:70,pcb_note_dimension:70,pcb_note_text:70,pcb_note_rect:70,pcb_note_path:70,pcb_note_line:70,pcb_trace_error:80,pcb_rats_nest:85},DEFAULT_TYPE_PRIORITY=100;getViewportBounds=({circuitJson,drawPaddingOutsideBoard,baseBounds,viewportOptions})=>{let padding=drawPaddingOutsideBoard?1:0,boundsMinX=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.minX:baseBounds.boardMinX,boundsMinY=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.minY:baseBounds.boardMinY,boundsMaxX=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.maxX:baseBounds.boardMaxX,boundsMaxY=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.maxY:baseBounds.boardMaxY,hasPanelBounds=!1,panelMinX=Number.POSITIVE_INFINITY,panelMinY=Number.POSITIVE_INFINITY,panelMaxX=Number.NEGATIVE_INFINITY,panelMaxY=Number.NEGATIVE_INFINITY,panelBoundsById=new Map,boardBoundsById=new Map;for(let elm of circuitJson)if(elm.type==="pcb_panel"){let panel=elm,panelBounds=rectBounds(panel.center,panel.width,panel.height);if(!panelBounds)continue;panelMinX=Math.min(panelMinX,panelBounds.minX),panelMinY=Math.min(panelMinY,panelBounds.minY),panelMaxX=Math.max(panelMaxX,panelBounds.maxX),panelMaxY=Math.max(panelMaxY,panelBounds.maxY),hasPanelBounds=!0,panel.pcb_panel_id&&panelBoundsById.set(panel.pcb_panel_id,panelBounds)}else if(elm.type==="pcb_board"){let board=elm,boardBounds=getOutlineBounds(board.outline)??rectBounds(board.center,board.width,board.height);boardBounds&&board.pcb_board_id&&boardBoundsById.set(board.pcb_board_id,boardBounds)}if(viewportOptions?.viewport){let{minX,minY,maxX,maxY}=viewportOptions.viewport;boundsMinX=minX,boundsMinY=minY,boundsMaxX=maxX,boundsMaxY=maxY,padding=0}else if(viewportOptions?.viewportTarget?.pcb_panel_id){let panelBounds=panelBoundsById.get(viewportOptions.viewportTarget.pcb_panel_id);if(!panelBounds)throw new Error(`Viewport target panel '${viewportOptions.viewportTarget.pcb_panel_id}' not found`);boundsMinX=panelBounds.minX,boundsMinY=panelBounds.minY,boundsMaxX=panelBounds.maxX,boundsMaxY=panelBounds.maxY,padding=0}else if(viewportOptions?.viewportTarget?.pcb_board_id){let boardBounds=boardBoundsById.get(viewportOptions.viewportTarget.pcb_board_id);if(!boardBounds)throw new Error(`Viewport target board '${viewportOptions.viewportTarget.pcb_board_id}' not found`);boundsMinX=boardBounds.minX,boundsMinY=boardBounds.minY,boundsMaxX=boardBounds.maxX,boundsMaxY=boardBounds.maxY,padding=0}else hasPanelBounds&&(boundsMinX=panelMinX,boundsMinY=panelMinY,boundsMaxX=panelMaxX,boundsMaxY=panelMaxY);return{boundsMinX,boundsMinY,boundsMaxX,boundsMaxY,padding}};circuitJsonToPcbSvg=convertCircuitJsonToPcbSvg,DEFAULT_BOARD_STYLE={fill:"none",stroke:"rgb(0,0,0)",strokeOpacity:"0.8",strokeWidthFactor:.2};fontSizeMap={pin_number:.15,negated_pin_number:.15*.8,reference_designator:.18,manufacturer_number:.18,net_label:.18,error:.05},getSchMmFontSize=(textType,fontSize)=>fontSize??fontSizeMap[textType],getSchScreenFontSize=(transform5,textType,fontSize)=>Math.abs(transform5.a)*getSchMmFontSize(textType,fontSize);HOLE_COLOR2="rgb(190, 190, 190)";PAD_COLOR="rgb(210, 210, 210)",HOLE_COLOR3="rgb(190, 190, 190)";PAD_COLOR2="rgb(210, 210, 210)";OBJECT_ORDER=["pcb_component","pcb_smtpad","pcb_hole","pcb_plated_hole","pcb_board"];BOARD_FILL_COLOR="rgb(26, 115, 143)",BOARD_STROKE_COLOR="rgba(0,0,0,0.9)";COMPONENT_FILL_COLOR="rgba(120, 120, 120, 0.6)",COMPONENT_LABEL_COLOR="rgba(255, 255, 255, 0.9)";HOLE_COLOR4="rgb(50, 50, 50)";PAD_COLOR3="rgb(218, 165, 32)",HOLE_COLOR5="rgb(40, 40, 40)";PAD_COLOR4="rgb(218, 165, 32)";LABEL_COLOR="rgb(255, 255, 255)",LABEL_BACKGROUND="rgb(0, 0, 0)",LINE_COLOR="rgba(0, 0, 0, 0.6)",PIN_NUMBER_BACKGROUND="rgb(200, 200, 200)",PIN_NUMBER_COLOR="rgb(0, 0, 0)";LABEL_RECT_HEIGHT_BASE_MM=1.6,FONT_HEIGHT_RATIO=11/21,CHAR_WIDTH_FACTOR=.6,STAGGER_OFFSET_MIN=.1,STAGGER_OFFSET_PER_PIN=.1,STAGGER_OFFSET_STEP=3,ALIGNED_OFFSET_MARGIN=.1,GROUP_SEPARATION_MM=.8;calculateLabelPositions=({left_labels,right_labels,transform:transform5,soup,board_bounds,svgWidth,svgHeight,styleScale})=>{let label_positions=new Map,shared_params={transform:transform5,soup,board_bounds};return calculateVerticalEdgeLabels("left",left_labels,{...shared_params,svgHeight,styleScale},label_positions),calculateVerticalEdgeLabels("right",right_labels,{...shared_params,svgHeight,styleScale},label_positions),label_positions};OBJECT_ORDER2=["pcb_board","pcb_smtpad","pcb_hole","pcb_plated_hole","pcb_component","pcb_port"];arialTextMetrics={0:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},1:{width:13,height:27,ascent:22,descent:5,left:-3,right:9},2:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},3:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},4:{width:13,height:27,ascent:22,descent:5,left:0,right:12},5:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},6:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},7:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},8:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},9:{width:13,height:27,ascent:22,descent:5,left:-1,right:12}," ":{width:7,height:27,ascent:22,descent:5,left:0,right:0},"!":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},'"':{width:9,height:27,ascent:22,descent:5,left:-1,right:7},"#":{width:13,height:27,ascent:22,descent:5,left:0,right:13},$:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},"%":{width:21,height:27,ascent:22,descent:5,left:-1,right:20},"&":{width:16,height:27,ascent:22,descent:5,left:-1,right:15},"'":{width:5,height:27,ascent:22,descent:5,left:-1,right:3},"(":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},")":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},"*":{width:9,height:27,ascent:22,descent:5,left:-1,right:8},"+":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},",":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},"-":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},".":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},"/":{width:7,height:27,ascent:22,descent:5,left:0,right:7},":":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},";":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},"<":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},"=":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},">":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},"?":{width:13,height:27,ascent:22,descent:5,left:-1,right:12},"@":{width:24,height:27,ascent:22,descent:5,left:-1,right:23},A:{width:16,height:27,ascent:22,descent:5,left:0,right:16},B:{width:16,height:27,ascent:22,descent:5,left:-2,right:15},C:{width:17,height:27,ascent:22,descent:5,left:-1,right:16},D:{width:17,height:27,ascent:22,descent:5,left:-2,right:16},E:{width:16,height:27,ascent:22,descent:5,left:-2,right:15},F:{width:15,height:27,ascent:22,descent:5,left:-2,right:14},G:{width:19,height:27,ascent:22,descent:5,left:-1,right:17},H:{width:17,height:27,ascent:22,descent:5,left:-2,right:15},I:{width:7,height:27,ascent:22,descent:5,left:-2,right:5},J:{width:12,height:27,ascent:22,descent:5,left:-1,right:10},K:{width:16,height:27,ascent:22,descent:5,left:-2,right:16},L:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},M:{width:20,height:27,ascent:22,descent:5,left:-2,right:18},N:{width:17,height:27,ascent:22,descent:5,left:-2,right:15},O:{width:19,height:27,ascent:22,descent:5,left:-1,right:18},P:{width:16,height:27,ascent:22,descent:5,left:-2,right:15},Q:{width:19,height:27,ascent:22,descent:5,left:-1,right:18},R:{width:17,height:27,ascent:22,descent:5,left:-2,right:17},S:{width:16,height:27,ascent:22,descent:5,left:-1,right:15},T:{width:15,height:27,ascent:22,descent:5,left:-1,right:14},U:{width:17,height:27,ascent:22,descent:5,left:-2,right:15},V:{width:16,height:27,ascent:22,descent:5,left:0,right:16},W:{width:23,height:27,ascent:22,descent:5,left:0,right:22},X:{width:16,height:27,ascent:22,descent:5,left:0,right:16},Y:{width:16,height:27,ascent:22,descent:5,left:0,right:16},Z:{width:15,height:27,ascent:22,descent:5,left:0,right:14},"[":{width:7,height:27,ascent:22,descent:5,left:-2,right:6},"\\":{width:7,height:27,ascent:22,descent:5,left:0,right:7},"]":{width:7,height:27,ascent:22,descent:5,left:0,right:5},"^":{width:11,height:27,ascent:22,descent:5,left:-1,right:11},_:{width:13,height:27,ascent:22,descent:5,left:0,right:14},"`":{width:8,height:27,ascent:22,descent:5,left:-1,right:5},a:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},b:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},c:{width:12,height:27,ascent:22,descent:5,left:-1,right:12},d:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},e:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},f:{width:7,height:27,ascent:22,descent:5,left:0,right:8},g:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},h:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},i:{width:5,height:27,ascent:22,descent:5,left:-2,right:4},j:{width:5,height:27,ascent:22,descent:5,left:1,right:4},k:{width:12,height:27,ascent:22,descent:5,left:-2,right:12},l:{width:5,height:27,ascent:22,descent:5,left:-2,right:4},m:{width:20,height:27,ascent:22,descent:5,left:-2,right:18},n:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},o:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},p:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},q:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},r:{width:8,height:27,ascent:22,descent:5,left:-2,right:8},s:{width:12,height:27,ascent:22,descent:5,left:-1,right:11},t:{width:7,height:27,ascent:22,descent:5,left:0,right:6},u:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},v:{width:12,height:27,ascent:22,descent:5,left:0,right:12},w:{width:17,height:27,ascent:22,descent:5,left:0,right:17},x:{width:12,height:27,ascent:22,descent:5,left:0,right:12},y:{width:12,height:27,ascent:22,descent:5,left:0,right:12},z:{width:12,height:27,ascent:22,descent:5,left:0,right:11},"{":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},"|":{width:6,height:27,ascent:22,descent:5,left:-2,right:4},"}":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},"~":{width:14,height:27,ascent:22,descent:5,left:-1,right:13}},estimateTextWidth=text=>{if(!text)return 0;let totalWidth=0;for(let char of text){let metrics=arialTextMetrics[char];metrics?totalWidth+=metrics.width:totalWidth+=arialTextMetrics["?"].width}return totalWidth/27},getTableDimensions=(schematicTable,circuitJson)=>{if(schematicTable.column_widths&&schematicTable.column_widths.length>0&&schematicTable.row_heights&&schematicTable.row_heights.length>0){let unitToMm2=v5=>typeof v5=="number"?v5:v5.endsWith("mm")?parseFloat(v5):v5.endsWith("in")?parseFloat(v5)*25.4:parseFloat(v5);return{column_widths:schematicTable.column_widths.map(unitToMm2),row_heights:schematicTable.row_heights.map(unitToMm2)}}let cells=circuitJson.filter(elm=>elm.type==="schematic_table_cell"&&elm.schematic_table_id===schematicTable.schematic_table_id);if(cells.length===0)return{column_widths:[],row_heights:[]};let numColumns=cells.reduce((max,c3)=>Math.max(max,c3.end_column_index),-1)+1,numRows=cells.reduce((max,c3)=>Math.max(max,c3.end_row_index),-1)+1,{cell_padding=.2}=schematicTable,column_widths=new Array(numColumns).fill(0),row_heights=new Array(numRows).fill(0),cell_widths={},cell_heights={};for(let cell of cells){let fontSizeMm=getSchMmFontSize("reference_designator",cell.font_size),requiredWidth=estimateTextWidth(cell.text??"")*fontSizeMm+2*cell_padding,requiredHeight=fontSizeMm*1.2+2*cell_padding,key=`${cell.start_row_index}-${cell.start_column_index}`;cell_widths[key]=requiredWidth,cell_heights[key]=requiredHeight}for(let i2=0;i2<numRows;i2++)for(let j4=0;j4<numColumns;j4++){let key=`${i2}-${j4}`;cell_widths[key]&&cell_widths[key]>column_widths[j4]&&(column_widths[j4]=cell_widths[key]),cell_heights[key]&&cell_heights[key]>row_heights[i2]&&(row_heights[i2]=cell_heights[key])}for(let cell of cells){if(cell.start_column_index===cell.end_column_index&&cell.start_row_index===cell.end_row_index)continue;let key=`${cell.start_row_index}-${cell.start_column_index}`,requiredWidth=cell_widths[key],requiredHeight=cell_heights[key];if(requiredWidth===void 0||requiredHeight===void 0)continue;let currentWidth=0;for(let i2=cell.start_column_index;i2<=cell.end_column_index;i2++)currentWidth+=column_widths[i2];if(requiredWidth>currentWidth){let extraPerColumn=(requiredWidth-currentWidth)/(cell.end_column_index-cell.start_column_index+1);for(let i2=cell.start_column_index;i2<=cell.end_column_index;i2++)column_widths[i2]+=extraPerColumn}let currentHeight=0;for(let i2=cell.start_row_index;i2<=cell.end_row_index;i2++)currentHeight+=row_heights[i2];if(requiredHeight>currentHeight){let extraPerRow=(requiredHeight-currentHeight)/(cell.end_row_index-cell.start_row_index+1);for(let i2=cell.start_row_index;i2<=cell.end_row_index;i2++)row_heights[i2]+=extraPerRow}}return{column_widths,row_heights}},getUnitVectorFromOutsideToEdge=side=>{switch(side){case"top":return{x:0,y:-1};case"bottom":return{x:0,y:1};case"left":return{x:1,y:0};case"right":return{x:-1,y:0}}throw new Error(`Invalid side: ${side}`)},ARROW_POINT_WIDTH_FSR=.3,END_PADDING_FSR=.3,END_PADDING_EXTRA_PER_CHARACTER_FSR=.06,ninePointAnchorToTextAnchor={top_left:"start",top_right:"end",middle_left:"start",middle_right:"end",bottom_left:"start",bottom_right:"end",center:"middle",middle_top:"middle",middle_bottom:"middle"},ninePointAnchorToDominantBaseline={top_left:"hanging",top_right:"hanging",bottom_left:"ideographic",bottom_right:"ideographic",center:"middle",middle_left:"middle",middle_right:"middle",middle_top:"hanging",middle_bottom:"ideographic"};getSchStrokeSize=transform5=>Math.abs(transform5.a)*.02,getAngularDifference=(angle1,angle2)=>{let a12=angle1<0?angle1+2*Math.PI:angle1,a2=angle2<0?angle2+2*Math.PI:angle2,diff=Math.abs(a12-a2);return diff>Math.PI&&(diff=2*Math.PI-diff),diff},matchSchPortsToSymbolPorts=({schPorts,symbol,schComponent})=>{let schPortAngles=schPorts.map(port=>{let dx2=port.center.x-schComponent.center.x,dy2=port.center.y-schComponent.center.y;return{port,angle:Math.atan2(dy2,dx2)}}),symbolPortAngles=symbol.ports.map(port=>{let dx2=port.x-symbol.center.x,dy2=port.y-symbol.center.y;return{port,angle:Math.atan2(dy2,dx2)}});schPortAngles.sort((a2,b3)=>a2.angle-b3.angle),symbolPortAngles.sort((a2,b3)=>a2.angle-b3.angle);let matches=[],usedSymbolPorts=new Set;for(let schPortAngle of schPortAngles){let bestMatch=null;for(let symbolPortAngle of symbolPortAngles){if(usedSymbolPorts.has(symbolPortAngle.port))continue;let angleDiff=getAngularDifference(schPortAngle.angle,symbolPortAngle.angle);(bestMatch===null||angleDiff<bestMatch.angleDiff)&&(bestMatch={symbolPort:symbolPortAngle.port,angleDiff})}bestMatch&&bestMatch.angleDiff<Math.PI/4&&(matches.push({schPort:schPortAngle.port,symbolPort:bestMatch.symbolPort}),usedSymbolPorts.add(bestMatch.symbolPort))}return matches};createSvgSchErrorText=({text,realCenter,realToScreenTransform})=>{let screenCenter=applyToPoint3(realToScreenTransform,realCenter);return{type:"element",name:"text",value:"",attributes:{x:screenCenter.x.toString(),y:screenCenter.y.toString(),fill:"red","text-anchor":"middle","dominant-baseline":"middle","font-family":"sans-serif","font-size":`${getSchScreenFontSize(realToScreenTransform,"error")}px`},children:[{type:"text",value:text,name:"",attributes:{},children:[]}]}},isSourcePortConnected=(circuitJson,sourcePortId)=>{for(let elm of circuitJson){if(elm.type!=="source_trace")continue;let trace=elm;if(Array.isArray(trace.connected_source_port_ids)&&trace.connected_source_port_ids.includes(sourcePortId))return!0}return!1},ninePointAnchorToTextAnchor2={top_left:"start",top_right:"end",middle_left:"start",middle_right:"end",bottom_left:"start",bottom_right:"end",center:"middle",middle_top:"middle",middle_bottom:"middle"},createSvgObjectsFromSchematicComponentWithSymbol=({component:schComponent,transform:realToScreenTransform,circuitJson,colorMap:colorMap2})=>{let svgObjects=[],symbol=Vf[schComponent.symbol_name];if(!symbol)return[createSvgSchErrorText({text:`Symbol not found: ${schComponent.symbol_name}`,realCenter:schComponent.center,realToScreenTransform})];let schPorts=su2(circuitJson).schematic_port.list({schematic_component_id:schComponent.schematic_component_id}),srcComponent=su2(circuitJson).source_component.get(schComponent.source_component_id),schPortsWithSymbolPorts=matchSchPortsToSymbolPorts({schPorts,symbol,schComponent});if(!schPortsWithSymbolPorts[0])return[createSvgSchErrorText({text:`Could not match ports for symbol ${schComponent.symbol_name}`,realCenter:schComponent.center,realToScreenTransform})];let transformFromSymbolToReal=pointPairsToMatrix(schPortsWithSymbolPorts[1]?.symbolPort??symbol.center,schPortsWithSymbolPorts[1]?.schPort.center??schComponent.center,schPortsWithSymbolPorts[0].symbolPort,schPortsWithSymbolPorts[0].schPort.center),paths=symbol.primitives.filter(p4=>p4.type==="path"),texts=symbol.primitives.filter(p4=>p4.type==="text"),circles=symbol.primitives.filter(p4=>p4.type==="circle"),boxes=symbol.primitives.filter(p4=>p4.type==="box"),connectedSymbolPorts=new Set;for(let match2 of schPortsWithSymbolPorts)isSourcePortConnected(circuitJson,match2.schPort.source_port_id)&&connectedSymbolPorts.add(match2.symbolPort);let bounds={minX:Math.min(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.x))),maxX:Math.max(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.x))),minY:Math.min(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.y))),maxY:Math.max(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.y)))},[screenMinX,screenMinY]=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),[bounds.minX,bounds.minY]),[screenMaxX,screenMaxY]=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),[bounds.maxX,bounds.maxY]),rectHeight=Math.abs(screenMaxY-screenMinY),rectY=Math.min(screenMinY,screenMaxY),rectWidth=Math.abs(screenMaxX-screenMinX),rectX=Math.min(screenMinX,screenMaxX);svgObjects.push({name:"rect",type:"element",value:"",attributes:{class:"component-overlay",x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),fill:"transparent"},children:[]});for(let path of paths){let{points,color,closed,fill}=path;svgObjects.push({type:"element",name:"path",attributes:{d:points.map((p4,i2)=>{let[x5,y5]=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),[p4.x,p4.y]);return`${i2===0?"M":"L"} ${x5} ${y5}`}).join(" ")+(closed?" Z":""),stroke:colorMap2.schematic.component_outline,fill:"none","stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,"stroke-linecap":"round"},value:"",children:[]})}for(let text of texts){let screenTextPos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),text),textValue="";text.text==="{REF}"?textValue=srcComponent?.display_name??srcComponent?.name??"":text.text==="{VAL}"&&(textValue=schComponent.symbol_display_value??"");let baseOffset=Math.abs(bounds.maxY-bounds.minY)*.1,transformScale=Math.abs(transformFromSymbolToReal.a),verticalOffset=0;text.anchor.includes("bottom")?verticalOffset=baseOffset*transformScale:text.anchor.includes("top")&&(verticalOffset=-baseOffset*transformScale);let dominantBaseline=text.anchor.includes("bottom")?"auto":text.anchor.includes("top")?"hanging":"middle",isReferenceText=text.text==="{REF}";svgObjects.push({name:"text",type:"element",attributes:{x:screenTextPos.x.toString(),y:(screenTextPos.y+verticalOffset).toString(),...isReferenceText?{stroke:colorMap2.schematic.background,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,"paint-order":"stroke"}:{},fill:colorMap2.schematic.label_local,"font-family":"sans-serif","text-anchor":ninePointAnchorToTextAnchor2[text.anchor],"dominant-baseline":dominantBaseline,"font-size":`${getSchScreenFontSize(realToScreenTransform,"reference_designator")}px`},value:"",children:[{type:"text",value:textValue,name:"",attributes:{},children:[]}]})}for(let box2 of boxes){let screenBoxPos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),box2),symbolToScreenScale=compose3(realToScreenTransform,transformFromSymbolToReal).a;svgObjects.push({name:"rect",type:"element",attributes:{x:screenBoxPos.x.toString(),y:screenBoxPos.y.toString(),width:(box2.width*symbolToScreenScale).toString(),height:(box2.height*symbolToScreenScale).toString(),fill:"red"},value:"",children:[]})}for(let port of symbol.ports){if(connectedSymbolPorts.has(port))continue;let screenPortPos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),port);svgObjects.push({type:"element",name:"circle",attributes:{cx:screenPortPos.x.toString(),cy:screenPortPos.y.toString(),r:`${Math.abs(realToScreenTransform.a)*.02}px`,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,fill:"none",stroke:colorMap2.schematic.component_outline},value:"",children:[]})}for(let circle2 of circles){let screenCirclePos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),circle2),screenRadius=Math.abs(circle2.radius*realToScreenTransform.a);svgObjects.push({type:"element",name:"circle",attributes:{cx:screenCirclePos.x.toString(),cy:screenCirclePos.y.toString(),r:`${screenRadius}px`,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,fill:"none",stroke:colorMap2.schematic.component_outline},value:"",children:[]})}return svgObjects},PIN_CIRCLE_RADIUS_MM=.02,createArrow=(tip,angle,size2,color,strokeWidth)=>{let arrowAngle=Math.PI/6,p12={x:tip.x-size2*Math.cos(angle-arrowAngle),y:tip.y-size2*Math.sin(angle-arrowAngle)},p22={x:tip.x-size2*Math.cos(angle+arrowAngle),y:tip.y-size2*Math.sin(angle+arrowAngle)};return{name:"polygon",type:"element",attributes:{points:`${tip.x},${tip.y} ${p12.x},${p12.y} ${p22.x},${p22.y}`,fill:"white",stroke:color,"stroke-width":`${strokeWidth}px`},value:"",children:[]}},createSvgObjectsForSchPortBoxLine=({schPort,schComponent,transform:transform5,circuitJson})=>{let svgObjects=[],srcPort=su2(circuitJson).source_port.get(schPort.source_port_id),realEdgePos={x:schPort.center.x,y:schPort.center.y},realPinLineLength=schPort.distance_from_component_edge??.4;switch(schPort.side_of_component){case"left":realEdgePos.x+=realPinLineLength;break;case"right":realEdgePos.x-=realPinLineLength;break;case"top":realEdgePos.y-=realPinLineLength;break;case"bottom":realEdgePos.y+=realPinLineLength;break}let screenSchPortPos=applyToPoint3(transform5,schPort.center),screenRealEdgePos=applyToPoint3(transform5,realEdgePos),isConnected=isSourcePortConnected(circuitJson,schPort.source_port_id),is_drawn_with_inversion_circle=schPort.is_drawn_with_inversion_circle??!1,BUBBLE_RADIUS_MM=.06,realLineEnd={...schPort.center};if(!isConnected)switch(schPort.side_of_component){case"left":realLineEnd.x+=PIN_CIRCLE_RADIUS_MM;break;case"right":realLineEnd.x-=PIN_CIRCLE_RADIUS_MM;break;case"top":realLineEnd.y-=PIN_CIRCLE_RADIUS_MM;break;case"bottom":realLineEnd.y+=PIN_CIRCLE_RADIUS_MM;break}let screenLineEnd=applyToPoint3(transform5,realLineEnd);if(is_drawn_with_inversion_circle){let bubbleRadiusPx=Math.abs(transform5.a)*BUBBLE_RADIUS_MM,bubbleCenter={...screenRealEdgePos};switch(schPort.side_of_component){case"left":bubbleCenter.x-=bubbleRadiusPx,screenRealEdgePos.x-=bubbleRadiusPx*2;break;case"right":bubbleCenter.x+=bubbleRadiusPx,screenRealEdgePos.x+=bubbleRadiusPx*2;break;case"top":bubbleCenter.y-=bubbleRadiusPx,screenRealEdgePos.y-=bubbleRadiusPx*2;break;case"bottom":bubbleCenter.y+=bubbleRadiusPx,screenRealEdgePos.y+=bubbleRadiusPx*2;break}svgObjects.push({name:"circle",type:"element",attributes:{class:"component-pin",cx:bubbleCenter.x.toString(),cy:bubbleCenter.y.toString(),r:bubbleRadiusPx.toString(),fill:"white",stroke:colorMap.schematic.component_outline,"stroke-width":`${getSchStrokeSize(transform5)}px`},value:"",children:[]})}svgObjects.push({name:"line",type:"element",attributes:{class:"component-pin",x1:screenRealEdgePos.x.toString(),y1:screenRealEdgePos.y.toString(),x2:screenLineEnd.x.toString(),y2:screenLineEnd.y.toString(),"stroke-width":`${getSchStrokeSize(transform5)}px`},value:"",children:[]});let pinRadiusPx=Math.abs(transform5.a)*PIN_CIRCLE_RADIUS_MM,pinChildren=[];isConnected||pinChildren.push({name:"circle",type:"element",attributes:{class:"component-pin",cx:screenSchPortPos.x.toString(),cy:screenSchPortPos.y.toString(),r:pinRadiusPx.toString(),"stroke-width":`${getSchStrokeSize(transform5)}px`},value:"",children:[]}),pinChildren.push({name:"rect",type:"element",attributes:{x:(screenSchPortPos.x-pinRadiusPx).toString(),y:(screenSchPortPos.y-pinRadiusPx).toString(),width:(pinRadiusPx*2).toString(),height:(pinRadiusPx*2).toString(),opacity:"0"},value:"",children:[]}),svgObjects.push({name:"g",type:"element",value:"",attributes:{"data-schematic-port-id":schPort.source_port_id},children:pinChildren});let{has_input_arrow,has_output_arrow}=schPort;if((has_input_arrow||has_output_arrow)&&schPort.side_of_component){let arrowSize=Math.abs(transform5.a)*.1,arrowColor=colorMap.schematic.component_outline,arrowAxialLength=arrowSize*Math.cos(Math.PI/6),strokeWidth=getSchStrokeSize(transform5)/3,inputAngleRads=0,outputAngleRads=0;schPort.side_of_component==="left"?(inputAngleRads=0,outputAngleRads=Math.PI):schPort.side_of_component==="right"?(inputAngleRads=Math.PI,outputAngleRads=0):schPort.side_of_component==="top"?(inputAngleRads=Math.PI/2,outputAngleRads=-Math.PI/2):schPort.side_of_component==="bottom"&&(inputAngleRads=-Math.PI/2,outputAngleRads=Math.PI/2);let both=has_input_arrow&&has_output_arrow,inputArrowTip={...screenRealEdgePos},outputArrowBase={...screenRealEdgePos};if(both){let offset=arrowAxialLength;schPort.side_of_component==="left"?outputArrowBase.x-=offset:schPort.side_of_component==="right"?outputArrowBase.x+=offset:schPort.side_of_component==="top"?outputArrowBase.y-=offset:schPort.side_of_component==="bottom"&&(outputArrowBase.y+=offset)}if(has_input_arrow&&svgObjects.push(createArrow(inputArrowTip,inputAngleRads,arrowSize,arrowColor,strokeWidth)),has_output_arrow){let outputArrowTip={x:outputArrowBase.x+arrowSize*Math.cos(outputAngleRads),y:outputArrowBase.y+arrowSize*Math.sin(outputAngleRads)};svgObjects.push(createArrow(outputArrowTip,outputAngleRads,arrowSize,arrowColor,strokeWidth))}}return svgObjects},createSvgObjectsForSchPortPinNumberText=params=>{let svgObjects=[],{schPort,schComponent,transform:transform5,circuitJson}=params,realPinNumberPos={x:schPort.center.x,y:schPort.center.y};if(!schPort.side_of_component)return[];let vecToEdge=getUnitVectorFromOutsideToEdge(schPort.side_of_component),realPinEdgeDistance=schPort.distance_from_component_edge??.4;realPinNumberPos.x+=vecToEdge.x*realPinEdgeDistance/2,realPinNumberPos.y+=vecToEdge.y*realPinEdgeDistance/2,schPort.side_of_component==="top"||schPort.side_of_component==="bottom"?realPinNumberPos.x-=.02:realPinNumberPos.y+=.02;let screenPinNumberTextPos=applyToPoint3(transform5,realPinNumberPos);return svgObjects.push({name:"text",type:"element",attributes:{class:"pin-number",x:screenPinNumberTextPos.x.toString(),y:screenPinNumberTextPos.y.toString(),style:"font-family: sans-serif;",fill:colorMap.schematic.pin_number,"text-anchor":"middle","dominant-baseline":"auto","font-size":`${getSchScreenFontSize(transform5,"pin_number")}px`,transform:schPort.side_of_component==="top"||schPort.side_of_component==="bottom"?`rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})`:""},children:[{type:"text",value:schPort.pin_number?.toString()||"",name:"",attributes:{},children:[]}],value:""}),svgObjects},LABEL_DIST_FROM_EDGE_MM=.1,createSvgObjectsForSchPortPinLabel=params=>{let svgObjects=[],{schPort,schComponent,transform:transform5,circuitJson}=params,realPinNumberPos={x:schPort.center.x,y:schPort.center.y};if(!schPort.side_of_component)return[];let vecToEdge=getUnitVectorFromOutsideToEdge(schPort.side_of_component),realPinEdgeDistance=schPort.distance_from_component_edge??.4;realPinNumberPos.x+=vecToEdge.x*(realPinEdgeDistance+LABEL_DIST_FROM_EDGE_MM),realPinNumberPos.y+=vecToEdge.y*(realPinEdgeDistance+LABEL_DIST_FROM_EDGE_MM);let screenPinNumberTextPos=applyToPoint3(transform5,realPinNumberPos),label=schPort.display_pin_label??schComponent.port_labels?.[`${schPort.pin_number}`];if(!label)return[];let isNegated=label.startsWith("N_"),displayLabel=isNegated?label.slice(2):label,is_drawn_with_inversion_circle=schPort.is_drawn_with_inversion_circle??!1,fontSizePx=getSchScreenFontSize(transform5,isNegated||is_drawn_with_inversion_circle?"negated_pin_number":"pin_number");return svgObjects.push({name:"text",type:"element",attributes:{class:"pin-number",x:screenPinNumberTextPos.x.toString(),y:screenPinNumberTextPos.y.toString(),style:`font-family: sans-serif;${isNegated?" text-decoration: overline;":""}`,fill:colorMap.schematic.pin_number,"text-anchor":schPort.side_of_component==="left"||schPort.side_of_component==="bottom"?"start":"end","dominant-baseline":"middle","font-size":`${fontSizePx}px`,transform:schPort.side_of_component==="top"||schPort.side_of_component==="bottom"?`rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})`:""},children:[{type:"text",value:displayLabel||"",name:"",attributes:{},children:[]}],value:""}),svgObjects},createSvgObjectsFromSchPortOnBox=params=>{let svgObjects=[],{schPort,schComponent,transform:transform5,circuitJson}=params;return svgObjects.push(...createSvgObjectsForSchPortBoxLine(params)),svgObjects.push(...createSvgObjectsForSchPortPinNumberText(params)),svgObjects.push(...createSvgObjectsForSchPortPinLabel(params)),svgObjects},createSvgSchText=({elm,transform:transform5,colorMap:colorMap2})=>{let center2=applyToPoint3(transform5,elm.position),textAnchorMap={center:"middle",center_right:"end",bottom_left:"start",bottom_center:"middle",bottom_right:"end",left:"start",right:"end",top:"middle",bottom:"middle",top_left:"start",top_center:"middle",top_right:"end",center_left:"start"},dominantBaselineMap={center:"middle",center_right:"middle",bottom_left:"ideographic",bottom_center:"ideographic",bottom_right:"ideographic",left:"middle",right:"middle",top:"hanging",bottom:"ideographic",top_left:"hanging",top_center:"hanging",top_right:"hanging",center_left:"middle"},lines=elm.text.split(`
|
|
335
|
+
`;return svgElement("style",{},[textNode(content)])}function createBackgroundRect(width,height){return svgElement("rect",{class:"background",x:"0",y:"0",width:formatNumber(width),height:formatNumber(height)})}function createDefsNode(clipPathId,plotWidth,plotHeight){return svgElement("defs",{},[svgElement("clipPath",{id:clipPathId},[svgElement("rect",{x:formatNumber(MARGIN.left),y:formatNumber(MARGIN.top),width:formatNumber(plotWidth),height:formatNumber(plotHeight)})])])}function createPlotBackground(plotWidth,plotHeight){return svgElement("rect",{class:"plot-background",x:formatNumber(MARGIN.left),y:formatNumber(MARGIN.top),width:formatNumber(plotWidth),height:formatNumber(plotHeight)})}function createGridLines({timeAxis,voltageAxis,scaleX,scaleY,plotWidth,plotHeight}){let top=MARGIN.top,bottom=MARGIN.top+plotHeight,left=MARGIN.left,right=MARGIN.left+plotWidth,children=[];for(let tick of timeAxis.ticks){let x5=formatNumber(scaleX(tick));children.push(svgElement("line",{class:"grid-line grid-line-x",x1:x5,y1:formatNumber(top),x2:x5,y2:formatNumber(bottom)}))}for(let tick of voltageAxis.ticks){let y5=formatNumber(scaleY(tick));children.push(svgElement("line",{class:"grid-line grid-line-y",x1:formatNumber(left),y1:y5,x2:formatNumber(right),y2:y5}))}return svgElement("g",{class:"grid"},children)}function createAxes({timeAxis,voltageAxis,scaleX,scaleY,plotWidth,plotHeight}){let bottom=MARGIN.top+plotHeight,left=MARGIN.left,right=MARGIN.left+plotWidth,children=[svgElement("line",{class:"axis axis-x",x1:formatNumber(left),y1:formatNumber(bottom),x2:formatNumber(right),y2:formatNumber(bottom)}),svgElement("line",{class:"axis axis-y",x1:formatNumber(left),y1:formatNumber(MARGIN.top),x2:formatNumber(left),y2:formatNumber(bottom)})];for(let tick of timeAxis.ticks){let x5=formatNumber(scaleX(tick));children.push(svgElement("line",{class:"axis-tick axis-tick-x",x1:x5,y1:formatNumber(bottom),x2:x5,y2:formatNumber(bottom+6)})),children.push(svgElement("text",{class:"axis-label axis-label-x",x:x5,y:formatNumber(bottom+22),"text-anchor":"middle"},[textNode(formatTickLabel(tick,timeAxis.ticks))]))}for(let tick of voltageAxis.ticks){let y5=formatNumber(scaleY(tick));children.push(svgElement("line",{class:"axis-tick axis-tick-y",x1:formatNumber(left-6),y1:y5,x2:formatNumber(left),y2:y5})),children.push(svgElement("text",{class:"axis-label axis-label-y",x:formatNumber(left-10),y:y5,"text-anchor":"end","dominant-baseline":"middle"},[textNode(formatTickLabel(tick,voltageAxis.ticks))]))}return children.push(svgElement("text",{class:"axis-title axis-title-x",x:formatNumber(left+plotWidth/2),y:formatNumber(bottom+48),"text-anchor":"middle"},[textNode("Time (ms)")]),svgElement("text",{class:"axis-title axis-title-y",x:formatNumber(left-64),y:formatNumber(MARGIN.top+plotHeight/2),transform:`rotate(-90 ${formatNumber(left-64)} ${formatNumber(MARGIN.top+plotHeight/2)})`,"text-anchor":"middle"},[textNode("Voltage (V)")])),svgElement("g",{class:"axes"},children)}function createLegend(graphs,width){let currentY=MARGIN.top,children=graphs.map(entry=>{let x5=width-MARGIN.right+10,lines=wrapLegendText(entry.label),legendItem=createLegendItem(entry,x5,currentY,lines),itemHeight=lines.length*LEGEND_LINE_HEIGHT;return currentY+=Math.max(itemHeight,LEGEND_MIN_SPACING),legendItem});return svgElement("g",{class:"legend"},children)}function wrapLegendText(label){let parts=label.split("_");if(parts.length<=1)return[label];let lines=[],currentLine=parts[0]??"";for(let i2=1;i2<parts.length;i2++){let part=parts[i2]??"",testLine=currentLine+"_"+part;testLine.length>MAX_LEGEND_LINE_LENGTH?(lines.push(currentLine),currentLine=part):currentLine=testLine}return currentLine&&lines.push(currentLine),lines}function createLegendItem(entry,x5,y5,lines){let textChildren=lines.map((line2,index)=>svgElement("tspan",{x:"20",dy:index===0?"0":String(LEGEND_LINE_HEIGHT)},[textNode(line2)]));return svgElement("g",{class:"legend-item",transform:`translate(${formatNumber(x5)} ${formatNumber(y5)})`},[svgElement("line",{class:"legend-line",x1:"0",y1:"0",x2:"16",y2:"0",stroke:entry.color}),svgElement("text",{class:"legend-label",x:"20",y:"0","dominant-baseline":"middle"},textChildren)])}function createDataGroup(graphs,clipPathId,scaleX,scaleY){let DASH_PATTERN=[4,8],dashArrayString=DASH_PATTERN.map(value=>formatNumber(value)).join(" "),dashOffsetStep=DASH_PATTERN.reduce((sum,value)=>sum+value,0)/3,processedGraphs=[];graphs.forEach((entry,graphIndex)=>{if(entry.points.length===0)return;let commands=[];entry.points.forEach((point6,index)=>{let x5=formatNumber(scaleX(point6.timeMs)),y5=formatNumber(scaleY(point6.voltage));commands.push(`${index===0?"M":"L"} ${x5} ${y5}`)});let baseAttributes={class:"simulation-line",d:commands.join(" "),stroke:entry.color,"clip-path":`url(#${clipPathId})`,"data-simulation-transient-voltage-graph-id":entry.graph.simulation_transient_voltage_graph_id};entry.graph.source_component_id&&(baseAttributes["data-source-component-id"]=entry.graph.source_component_id),entry.graph.subcircuit_connectivity_map_key&&(baseAttributes["data-subcircuit-connectivity-map-key"]=entry.graph.subcircuit_connectivity_map_key);let pointElements2=entry.points.map(point6=>{let cx2=formatNumber(scaleX(point6.timeMs)),cy2=formatNumber(scaleY(point6.voltage));return svgElement("circle",{class:"simulation-point",cx:cx2,cy:cy2,r:"2.5",fill:entry.color,"clip-path":`url(#${clipPathId})`})});processedGraphs.push({entry,graphIndex,pathAttributes:baseAttributes,pointElements:pointElements2})});let lineElements=[];for(let cycle=0;cycle<3;cycle++)processedGraphs.forEach(graphInfo=>{let offsetIndex=(graphInfo.graphIndex+cycle)%3,dashOffset=formatNumber(offsetIndex*dashOffsetStep);lineElements.push(svgElement("path",{...graphInfo.pathAttributes,"stroke-dasharray":dashArrayString,"stroke-dashoffset":dashOffset}))});let pointElements=processedGraphs.flatMap(graphInfo=>graphInfo.pointElements);return svgElement("g",{class:"data-series"},[...lineElements,...pointElements])}function createTitleNode(experiment,width){return experiment?.name?svgElement("text",{class:"chart-title",x:formatNumber(width/2),y:formatNumber(MARGIN.top-40),"text-anchor":"middle"},[textNode(experiment.name)]):null}function createClipPathId(simulationExperimentId){return`simulation-graph-${simulationExperimentId.replace(/[^a-zA-Z0-9_-]+/g,"-")}`}function formatNumber(value){if(!Number.isFinite(value))return"0";let rounded=Number.parseFloat(value.toFixed(6));return Number.isInteger(rounded),rounded.toString()}function formatTickLabel(value,ticks){if(ticks.length<=1)return formatNumber(value);let span=ticks[ticks.length-1]-ticks[0];if(!Number.isFinite(span)||span===0)return formatNumber(value);let precision=span>=100?0:span>=10?1:span>=1?2:3,factor=Math.pow(10,precision);return(Math.round(value*factor)/factor).toFixed(precision).replace(/\.0+$/,"").replace(/(\.\d*?)0+$/,"$1").replace(/\.$/,"")}function svgElement(name,attributes2,children=[]){return{name,type:"element",value:"",attributes:attributes2,children}}function textNode(value){return{name:"",type:"text",value,attributes:{},children:[]}}function convertCircuitJsonToSchematicSimulationSvg({circuitJson,simulation_experiment_id,simulation_transient_voltage_graph_ids,width=DEFAULT_WIDTH2,height=DEFAULT_HEIGHT2,schematicHeightRatio=DEFAULT_SCHEMATIC_RATIO,schematicOptions,includeVersion,graphAboveSchematic=!1,showErrorsInTextOverlay}){let schematicElements=circuitJson.filter(element=>!isSimulationExperiment(element)&&!isSimulationTransientVoltageGraph(element)),clampedRatio=clamp01(schematicHeightRatio),rawSchematicHeight=Math.max(1,height*clampedRatio),rawSimulationHeight=Math.max(1,height-rawSchematicHeight),totalRawHeight=rawSchematicHeight+rawSimulationHeight,scale10=totalRawHeight===0?1:height/totalRawHeight,schematicHeight=rawSchematicHeight*scale10,simulationHeight=rawSimulationHeight*scale10,schematicSvg=convertCircuitJsonToSchematicSvg(schematicElements,{...schematicOptions,width,height:schematicHeight,includeVersion:!1,showErrorsInTextOverlay}),simulationSvg=convertCircuitJsonToSimulationGraphSvg({circuitJson,simulation_experiment_id,simulation_transient_voltage_graph_ids,width,height:simulationHeight,includeVersion:!1}),schematicNode=ensureElementNode((0,import_svgson10.parseSync)(schematicSvg)),simulationNode=ensureElementNode((0,import_svgson10.parseSync)(simulationSvg)),combinedChildren=[];graphAboveSchematic?(combinedChildren.push(translateNestedSvg(simulationNode,0,0,width,simulationHeight)),combinedChildren.push(translateNestedSvg(schematicNode,0,simulationHeight,width,schematicHeight))):(combinedChildren.push(translateNestedSvg(schematicNode,0,0,width,schematicHeight)),combinedChildren.push(translateNestedSvg(simulationNode,0,schematicHeight,width,simulationHeight)));let softwareUsedString=getSoftwareUsedString(schematicElements),svgObject={name:"svg",type:"element",value:"",attributes:{xmlns:"http://www.w3.org/2000/svg",width:formatNumber2(width),height:formatNumber2(height),viewBox:`0 0 ${formatNumber2(width)} ${formatNumber2(height)}`,"data-simulation-experiment-id":simulation_experiment_id,...softwareUsedString&&{"data-software-used-string":softwareUsedString},...includeVersion&&{"data-circuit-to-svg-version":CIRCUIT_TO_SVG_VERSION}},children:combinedChildren};return(0,import_svgson10.stringify)(svgObject)}function translateNestedSvg(node,x5,y5,width,height){let clone=cloneSvgObject(node);return clone.attributes={...clone.attributes,x:formatNumber2(x5),y:formatNumber2(y5),width:formatNumber2(width),height:formatNumber2(height)},delete clone.attributes.xmlns,clone}function ensureElementNode(node){if(node.type!=="element")throw new Error("Expected SVG root element to be of type 'element'");return node}function cloneSvgObject(node){return{...node,attributes:{...node.attributes??{}},children:node.children?.map(cloneSvgObject)??[]}}function clamp01(value){return Number.isFinite(value)?value<=0?0:value>=1?1:value:DEFAULT_SCHEMATIC_RATIO}function formatNumber2(value){if(!Number.isFinite(value))return"0";let rounded=Number.parseFloat(value.toFixed(6));return Number.isInteger(rounded),rounded.toString()}function createSvgObjectsFromSolderPaste(solderPaste,ctx){let{transform:transform5,layer:layerFilter}=ctx;if(layerFilter&&solderPaste.layer!==layerFilter)return[];let[x5,y5]=applyToPoint3(transform5,[solderPaste.x,solderPaste.y]);if(solderPaste.shape==="rect"||solderPaste.shape==="rotated_rect"){let width=solderPaste.width*Math.abs(transform5.a),height=solderPaste.height*Math.abs(transform5.d);return solderPaste.shape==="rotated_rect"&&solderPaste.ccw_rotation?[{name:"rect",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),x:(-width/2).toString(),y:(-height/2).toString(),width:width.toString(),height:height.toString(),transform:`translate(${x5} ${y5}) rotate(${-solderPaste.ccw_rotation})`,"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]:[{name:"rect",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]}if(solderPaste.shape==="pill"){let width=solderPaste.width*Math.abs(transform5.a),height=solderPaste.height*Math.abs(transform5.d),radius=solderPaste.radius*Math.abs(transform5.a);return[{name:"rect",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),x:(x5-width/2).toString(),y:(y5-height/2).toString(),width:width.toString(),height:height.toString(),rx:radius.toString(),"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]}if(solderPaste.shape==="circle"){let radius=solderPaste.radius*Math.abs(transform5.a);return[{name:"circle",type:"element",attributes:{class:"pcb-solder-paste",fill:solderPasteLayerNameToColor(solderPaste.layer),cx:x5.toString(),cy:y5.toString(),r:radius.toString(),"data-type":"pcb_solder_paste","data-pcb-layer":solderPaste.layer}}]}}function convertCircuitJsonToSolderPasteMask(circuitJson,options){let minX=Number.POSITIVE_INFINITY,minY=Number.POSITIVE_INFINITY,maxX=Number.NEGATIVE_INFINITY,maxY=Number.NEGATIVE_INFINITY,filteredCircuitJson=circuitJson.filter(elm=>elm.type==="pcb_board"||elm.type==="pcb_panel"||elm.type==="pcb_solder_paste"&&elm.layer===options.layer);for(let item of filteredCircuitJson)if(item.type==="pcb_board")item.outline&&Array.isArray(item.outline)&&item.outline.length>=3?updateBoundsToIncludeOutline(item.outline):"center"in item&&"width"in item&&"height"in item&&updateBounds(item.center,item.width,item.height);else if(item.type==="pcb_panel"){let panel=item,width=distance.parse(panel.width),height=distance.parse(panel.height);if(width!==void 0&&height!==void 0){let center2=panel.center??{x:width/2,y:height/2};updateBounds(center2,width,height)}}else item.type==="pcb_solder_paste"&&"x"in item&&"y"in item&&updateBounds({x:item.x,y:item.y},0,0);let padding=1,circuitWidth=maxX-minX+2*padding,circuitHeight=maxY-minY+2*padding,svgWidth=options.width??800,svgHeight=options.height??600,scaleX=svgWidth/circuitWidth,scaleY=svgHeight/circuitHeight,scaleFactor=Math.min(scaleX,scaleY),offsetX=(svgWidth-circuitWidth*scaleFactor)/2,offsetY=(svgHeight-circuitHeight*scaleFactor)/2,transform5=compose3(translate3(offsetX-minX*scaleFactor+padding*scaleFactor,svgHeight-offsetY+minY*scaleFactor-padding*scaleFactor),scale3(scaleFactor,-scaleFactor)),ctx={transform:transform5,layer:options.layer,colorMap:DEFAULT_PCB_COLOR_MAP},svgObjects=filteredCircuitJson.sort((a2,b3)=>(OBJECT_ORDER3.indexOf(b3.type)??9999)-(OBJECT_ORDER3.indexOf(a2.type)??9999)).flatMap(item=>createSvgObjects4({elm:item,ctx})),softwareUsedString=getSoftwareUsedString(circuitJson),version=CIRCUIT_TO_SVG_VERSION,children=[{name:"style",type:"element",children:[{type:"text",value:""}]},{name:"rect",type:"element",attributes:{class:"boundary",x:"0",y:"0",fill:"#000",width:svgWidth.toString(),height:svgHeight.toString()}},createSvgObjectFromPcbBoundary2(transform5,minX,minY,maxX,maxY),...svgObjects].filter(child=>child!==null);if(options?.showErrorsInTextOverlay){let errorOverlay=createErrorTextOverlay(circuitJson);errorOverlay&&children.push(errorOverlay)}let svgObject={name:"svg",type:"element",attributes:{xmlns:"http://www.w3.org/2000/svg",width:svgWidth.toString(),height:svgHeight.toString(),...softwareUsedString&&{"data-software-used-string":softwareUsedString},...options.includeVersion&&{"data-circuit-to-svg-version":version}},value:"",children};try{return(0,import_svgson12.stringify)(svgObject)}catch(error){throw console.error("Error stringifying SVG object:",error),error}function updateBounds(center2,width,height){let halfWidth=width/2,halfHeight=height/2;minX=Math.min(minX,center2.x-halfWidth),minY=Math.min(minY,center2.y-halfHeight),maxX=Math.max(maxX,center2.x+halfWidth),maxY=Math.max(maxY,center2.y+halfHeight)}function updateBoundsToIncludeOutline(outline){for(let point6 of outline)minX=Math.min(minX,point6.x),minY=Math.min(minY,point6.y),maxX=Math.max(maxX,point6.x),maxY=Math.max(maxY,point6.y)}}function createSvgObjects4({elm,ctx}){let{transform:transform5}=ctx;switch(elm.type){case"pcb_board":return createSvgObjectsFromPcbBoard(elm,ctx);case"pcb_solder_paste":return createSvgObjectsFromSolderPaste(elm,ctx);default:return[]}}function createSvgObjectFromPcbBoundary2(transform5,minX,minY,maxX,maxY){let[x12,y12]=applyToPoint3(transform5,[minX,minY]),[x22,y22]=applyToPoint3(transform5,[maxX,maxY]),width=Math.abs(x22-x12),height=Math.abs(y22-y12),x5=Math.min(x12,x22),y5=Math.min(y12,y22);return{name:"rect",type:"element",value:"",children:[],attributes:{class:"pcb-boundary",fill:"none",stroke:"#fff","stroke-width":"0.3",x:x5.toString(),y:y5.toString(),width:width.toString(),height:height.toString()}}}var import_svgson2,import_svgson3,import_svgson4,import_svgson5,import_svgson6,import_svgson7,import_svgson8,import_svgson9,import_svgson10,import_svgson11,import_svgson12,DEFAULT_OVERLAY_STROKE_COLOR,DEFAULT_OVERLAY_FILL_COLOR,TEXT_OFFSET_MULTIPLIER,CHARACTER_WIDTH_MULTIPLIER,TEXT_INTERSECTION_PADDING_MULTIPLIER,colorMap,DEFAULT_OVERLAY_COLOR,DEFAULT_OVERLAY_COLOR2,DEFAULT_FILL_COLOR,DEFAULT_OVERLAY_COLOR3,DEFAULT_OVERLAY_COLOR4,DEFAULT_PCB_COLOR_MAP,HOLE_COLOR,SILKSCREEN_TOP_COLOR,SILKSCREEN_BOTTOM_COLOR,LAYER_NAME_TO_COLOR,SOLDER_PASTE_LAYER_NAME_TO_COLOR,CHAR_WIDTH,CHAR_SPACING,LINE_HEIGHT,FONT_SCALE,maskIdCounter,OFFSET_THRESHOLD_MM,TICK_SIZE_PX,LABEL_GAP_PX,LABEL_FONT_SIZE_PX,STROKE_WIDTH_PX,ANCHOR_MARKER_SIZE_PX,ANCHOR_MARKER_STROKE_WIDTH_PX,COMPONENT_ANCHOR_MARKER_RADIUS_PX,CONNECTOR_GROUP_GAP_PX,CONNECTOR_COMPONENT_GAP_PX,DIMENSION_ANCHOR_CLEARANCE_PX,COMPONENT_GAP_PX,COMPONENT_SIDE_GAP_PX,DISTANCE_MULTIPLIER,MAX_OFFSET_PX,getElementPosition,findNearestPointInNet,KEEPOUT_PATTERN_ID,KEEPOUT_PATTERN_SIZE,KEEPOUT_LINE_SPACING,KEEPOUT_BACKGROUND_COLOR,DEFAULT_GRID_LINE_COLOR,GRID_PATTERN_ID,DEFAULT_GROUP_COLOR,DEFAULT_STROKE_WIDTH,package_default2,CIRCUIT_TO_SVG_VERSION,TYPE_PRIORITY,DEFAULT_TYPE_PRIORITY,getViewportBounds,circuitJsonToPcbSvg,DEFAULT_BOARD_STYLE,fontSizeMap,getSchMmFontSize,getSchScreenFontSize,HOLE_COLOR2,PAD_COLOR,HOLE_COLOR3,PAD_COLOR2,OBJECT_ORDER,BOARD_FILL_COLOR,BOARD_STROKE_COLOR,COMPONENT_FILL_COLOR,COMPONENT_LABEL_COLOR,HOLE_COLOR4,PAD_COLOR3,HOLE_COLOR5,PAD_COLOR4,LABEL_COLOR,LABEL_BACKGROUND,LINE_COLOR,PIN_NUMBER_BACKGROUND,PIN_NUMBER_COLOR,LABEL_RECT_HEIGHT_BASE_MM,FONT_HEIGHT_RATIO,CHAR_WIDTH_FACTOR,STAGGER_OFFSET_MIN,STAGGER_OFFSET_PER_PIN,STAGGER_OFFSET_STEP,ALIGNED_OFFSET_MARGIN,GROUP_SEPARATION_MM,calculateLabelPositions,OBJECT_ORDER2,arialTextMetrics,estimateTextWidth,getTableDimensions,getUnitVectorFromOutsideToEdge,ARROW_POINT_WIDTH_FSR,END_PADDING_FSR,END_PADDING_EXTRA_PER_CHARACTER_FSR,ninePointAnchorToTextAnchor,ninePointAnchorToDominantBaseline,getSchStrokeSize,getAngularDifference,matchSchPortsToSymbolPorts,createSvgSchErrorText,isSourcePortConnected,ninePointAnchorToTextAnchor2,createSvgObjectsFromSchematicComponentWithSymbol,PIN_CIRCLE_RADIUS_MM,createArrow,createSvgObjectsForSchPortBoxLine,createSvgObjectsForSchPortPinNumberText,LABEL_DIST_FROM_EDGE_MM,createSvgObjectsForSchPortPinLabel,createSvgObjectsFromSchPortOnBox,createSvgSchText,createSvgObjectsFromSchematicComponentWithBox,createSvgObjectsForSchNetLabelWithSymbol,createSvgObjectsForSchNetLabel,createSvgObjectsFromSchematicBox,createSvgObjectsFromSchematicTable,PIN_CIRCLE_RADIUS_MM2,createSvgObjectsForSchPortHover,createSvgObjectsForSchComponentPortHovers,circuitJsonToSchematicSvg,DEFAULT_WIDTH,DEFAULT_HEIGHT,MARGIN,FALLBACK_LINE_COLOR,MAX_LEGEND_LINE_LENGTH,LEGEND_LINE_HEIGHT,LEGEND_MIN_SPACING,DEFAULT_WIDTH2,DEFAULT_HEIGHT2,DEFAULT_SCHEMATIC_RATIO,OBJECT_ORDER3,init_dist8=__esm({"node_modules/circuit-to-svg/dist/index.js"(){"use strict";init_dist();import_svgson2=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist();init_dist7();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist4();import_svgson3=__toESM(require_svgson_umd(),1);init_src2();init_dist6();init_dist4();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();import_svgson4=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_dist();init_dist();import_svgson5=__toESM(require_svgson_umd(),1);init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();import_svgson6=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_dist6();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist5();init_src2();init_dist6();import_svgson7=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_src2();init_src2();init_dist2();init_svg_path_commander();init_dist6();init_dist2();import_svgson8=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_src2();init_dist6();init_dist2();import_svgson9=__toESM(require_svgson_umd(),1);init_src2();init_src2();init_dist6();init_src2();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();init_dist2();init_src2();init_src2();init_dist6();init_src2();init_src2();init_src2();init_src2();init_src2();init_src2();import_svgson10=__toESM(require_svgson_umd(),1),import_svgson11=__toESM(require_svgson_umd(),1);init_dist();import_svgson12=__toESM(require_svgson_umd(),1);init_src2();init_src2();DEFAULT_OVERLAY_STROKE_COLOR="rgba(255,255,255,0.5)",DEFAULT_OVERLAY_FILL_COLOR="rgba(255,255,255,0.2)";TEXT_OFFSET_MULTIPLIER=1.5,CHARACTER_WIDTH_MULTIPLIER=.6,TEXT_INTERSECTION_PADDING_MULTIPLIER=.3;colorMap={"3d_viewer":{background_bottom:"rgb(102, 102, 128)",background_top:"rgb(204, 204, 230)",board:"rgb(51, 43, 23)",copper:"rgb(179, 156, 0)",silkscreen_bottom:"rgb(230, 230, 230)",silkscreen_top:"rgb(230, 230, 230)",soldermask:"rgb(20, 51, 36)",solderpaste:"rgb(128, 128, 128)"},board:{anchor:"rgb(255, 38, 226)",aux_items:"rgb(255, 255, 255)",b_adhes:"rgb(0, 0, 132)",b_crtyd:"rgb(255, 38, 226)",b_fab:"rgb(88, 93, 132)",b_mask:"rgba(2, 255, 238, 0.400)",b_paste:"rgb(0, 194, 194)",b_silks:"rgb(232, 178, 167)",background:"rgb(0, 16, 35)",cmts_user:"rgb(89, 148, 220)",copper:{b:"rgb(77, 127, 196)",f:"rgb(200, 52, 52)",in1:"rgb(127, 200, 127)",in10:"rgb(237, 124, 51)",in11:"rgb(91, 195, 235)",in12:"rgb(247, 111, 142)",in13:"rgb(167, 165, 198)",in14:"rgb(40, 204, 217)",in15:"rgb(232, 178, 167)",in16:"rgb(242, 237, 161)",in17:"rgb(237, 124, 51)",in18:"rgb(91, 195, 235)",in19:"rgb(247, 111, 142)",in2:"rgb(206, 125, 44)",in20:"rgb(167, 165, 198)",in21:"rgb(40, 204, 217)",in22:"rgb(232, 178, 167)",in23:"rgb(242, 237, 161)",in24:"rgb(237, 124, 51)",in25:"rgb(91, 195, 235)",in26:"rgb(247, 111, 142)",in27:"rgb(167, 165, 198)",in28:"rgb(40, 204, 217)",in29:"rgb(232, 178, 167)",in3:"rgb(79, 203, 203)",in30:"rgb(242, 237, 161)",in4:"rgb(219, 98, 139)",in5:"rgb(167, 165, 198)",in6:"rgb(40, 204, 217)",in7:"rgb(232, 178, 167)",in8:"rgb(242, 237, 161)",in9:"rgb(141, 203, 129)"},cursor:"rgb(255, 255, 255)",drc:"rgb(194, 194, 194)",drc_error:"rgba(215, 91, 107, 0.800)",drc_exclusion:"rgb(255, 255, 255)",drc_warning:"rgba(255, 208, 66, 0.902)",dwgs_user:"rgb(194, 194, 194)",eco1_user:"rgb(180, 219, 210)",eco2_user:"rgb(216, 200, 82)",edge_cuts:"rgb(208, 210, 205)",f_adhes:"rgb(132, 0, 132)",f_crtyd:"rgb(255, 0, 245)",f_fab:"rgb(175, 175, 175)",f_mask:"rgba(216, 100, 255, 0.400)",f_paste:"rgba(180, 160, 154, 0.902)",f_silks:"rgb(242, 237, 161)",footprint_text_back:"rgb(0, 0, 132)",footprint_text_front:"rgb(194, 194, 194)",footprint_text_invisible:"rgb(132, 132, 132)",grid:"rgb(132, 132, 132)",grid_axes:"rgb(194, 194, 194)",margin:"rgb(255, 38, 226)",microvia:"rgb(0, 132, 132)",no_connect:"rgb(0, 0, 132)",pad_back:"rgb(77, 127, 196)",pad_front:"rgb(200, 52, 52)",pad_plated_hole:"rgb(194, 194, 0)",pad_through_hole:"rgb(227, 183, 46)",plated_hole:"rgb(26, 196, 210)",ratsnest:"rgba(245, 255, 213, 0.702)",select_overlay:"rgb(4, 255, 67)",through_via:"rgb(236, 236, 236)",user_1:"rgb(194, 194, 194)",user_2:"rgb(89, 148, 220)",user_3:"rgb(180, 219, 210)",user_4:"rgb(216, 200, 82)",user_5:"rgb(194, 194, 194)",user_6:"rgb(89, 148, 220)",user_7:"rgb(180, 219, 210)",user_8:"rgb(216, 200, 82)",user_9:"rgb(232, 178, 167)",via_blind_buried:"rgb(187, 151, 38)",via_hole:"rgb(227, 183, 46)",via_micro:"rgb(0, 132, 132)",via_through:"rgb(236, 236, 236)",worksheet:"rgb(200, 114, 171)"},gerbview:{axes:"rgb(0, 0, 132)",background:"rgb(0, 0, 0)",dcodes:"rgb(255, 255, 255)",grid:"rgb(132, 132, 132)",layers:["rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)","rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)","rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)","rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)"],negative_objects:"rgb(132, 132, 132)",worksheet:"rgb(0, 0, 132)"},meta:{filename:"kicad_2020",name:"KiCad 2020",version:2},palette:["rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)"],schematic:{aux_items:"rgb(46, 46, 46)",background:"rgb(245, 241, 237)",brightened:"rgb(255, 0, 255)",bus:"rgb(0, 0, 132)",bus_junction:"rgb(0, 0, 132)",component_body:"rgb(255, 255, 194)",component_outline:"rgb(132, 0, 0)",cursor:"rgb(15, 15, 15)",erc_error:"rgba(230, 9, 13, 0.800)",erc_warning:"rgba(209, 146, 0, 0.800)",fields:"rgb(132, 0, 132)",grid:"rgb(181, 181, 181)",grid_axes:"rgb(0, 0, 132)",hidden:"rgb(194, 194, 194)",junction:"rgb(0, 150, 0)",label_global:"rgb(132, 0, 0)",label_background:"rgba(255, 255, 255, 0.6)",label_hier:"rgb(114, 86, 0)",label_local:"rgb(15, 15, 15)",net_name:"rgb(132, 132, 132)",no_connect:"rgb(0, 0, 132)",note:"rgb(0, 0, 194)",override_item_colors:!1,pin:"rgb(132, 0, 0)",pin_name:"rgb(0, 100, 100)",pin_number:"rgb(169, 0, 0)",reference:"rgb(0, 100, 100)",shadow:"rgba(102, 179, 255, 0.800)",sheet:"rgb(132, 0, 0)",sheet_background:"rgba(253, 255, 231, 0.000)",sheet_fields:"rgb(132, 0, 132)",sheet_filename:"rgb(114, 86, 0)",sheet_label:"rgb(0, 100, 100)",sheet_name:"rgb(0, 100, 100)",table:"rgb(102, 102, 102)",value:"rgb(0, 100, 100)",wire:"rgb(0, 150, 0)",wire_crossing:"rgb(30, 180, 30)",worksheet:"rgb(132, 0, 0)"}};DEFAULT_OVERLAY_COLOR=colorMap.board.user_2;DEFAULT_OVERLAY_COLOR2=colorMap.board.user_2,DEFAULT_FILL_COLOR=colorMap.board.user_2;DEFAULT_OVERLAY_COLOR3=colorMap.board.user_2;DEFAULT_OVERLAY_COLOR4=colorMap.board.user_2;DEFAULT_PCB_COLOR_MAP={copper:{top:"rgb(200, 52, 52)",inner1:"rgb(255, 140, 0)",inner2:"rgb(255, 215, 0)",inner3:"rgb(50, 205, 50)",inner4:"rgb(64, 224, 208)",inner5:"rgb(138, 43, 226)",inner6:"rgb(255, 105, 180)",bottom:"rgb(77, 127, 196)"},soldermaskWithCopperUnderneath:{top:"rgb(18, 82, 50)",bottom:"rgb(77, 127, 196)"},soldermask:{top:"rgb(12, 55, 33)",bottom:"rgb(12, 55, 33)"},soldermaskOverCopper:{top:"rgb(52, 135, 73)",bottom:"rgb(52, 135, 73)"},substrate:"rgb(201, 162, 110)",drill:"#FF26E2",silkscreen:{top:"#f2eda1",bottom:"#5da9e9"},boardOutline:"rgba(255, 255, 255, 0.5)",courtyard:"#FF00FF",keepout:"#FF6B6B",debugComponent:{fill:null,stroke:null}},HOLE_COLOR=DEFAULT_PCB_COLOR_MAP.drill,SILKSCREEN_TOP_COLOR=DEFAULT_PCB_COLOR_MAP.silkscreen.top,SILKSCREEN_BOTTOM_COLOR=DEFAULT_PCB_COLOR_MAP.silkscreen.bottom,LAYER_NAME_TO_COLOR={...DEFAULT_PCB_COLOR_MAP.copper};SOLDER_PASTE_LAYER_NAME_TO_COLOR={bottom:"rgb(105, 105, 105)",top:"rgb(105, 105, 105)"};CHAR_WIDTH=1,CHAR_SPACING=.2,LINE_HEIGHT=1.4,FONT_SCALE=.53;maskIdCounter=0;OFFSET_THRESHOLD_MM=.05,TICK_SIZE_PX=4,LABEL_GAP_PX=8,LABEL_FONT_SIZE_PX=11,STROKE_WIDTH_PX=1,ANCHOR_MARKER_SIZE_PX=5,ANCHOR_MARKER_STROKE_WIDTH_PX=1.5,COMPONENT_ANCHOR_MARKER_RADIUS_PX=2,CONNECTOR_GROUP_GAP_PX=ANCHOR_MARKER_SIZE_PX+2,CONNECTOR_COMPONENT_GAP_PX=COMPONENT_ANCHOR_MARKER_RADIUS_PX+2,DIMENSION_ANCHOR_CLEARANCE_PX=ANCHOR_MARKER_SIZE_PX+TICK_SIZE_PX+6,COMPONENT_GAP_PX=15,COMPONENT_SIDE_GAP_PX=10,DISTANCE_MULTIPLIER=.2,MAX_OFFSET_PX=50;getElementPosition=(id,circuitJson)=>{let pcbSmtpad=su2(circuitJson).pcb_smtpad.get(id);if(pcbSmtpad&&"x"in pcbSmtpad&&"y"in pcbSmtpad)return{x:pcbSmtpad.x,y:pcbSmtpad.y};let pcbPlatedHole=su2(circuitJson).pcb_plated_hole.get(id);return pcbPlatedHole&&"x"in pcbPlatedHole&&"y"in pcbPlatedHole?{x:pcbPlatedHole.x,y:pcbPlatedHole.y}:null},findNearestPointInNet=(sourcePoint,netId,connectivity,circuitJson)=>{let connectedIds=connectivity.getIdsConnectedToNet(netId),nearestPoint=null,minDistance=1/0;for(let id of connectedIds){let pos=getElementPosition(id,circuitJson);if(pos){let dx2=sourcePoint.x-pos.x,dy2=sourcePoint.y-pos.y,distance62=Math.sqrt(dx2*dx2+dy2*dy2);distance62>0&&distance62<minDistance&&(minDistance=distance62,nearestPoint=pos)}}return nearestPoint};KEEPOUT_PATTERN_ID="pcb-keepout-pattern",KEEPOUT_PATTERN_SIZE=20,KEEPOUT_LINE_SPACING=5,KEEPOUT_BACKGROUND_COLOR="rgba(255, 107, 107, 0.2)";DEFAULT_GRID_LINE_COLOR="rgba(255, 255, 255, 0.5)",GRID_PATTERN_ID="pcb-grid-pattern";DEFAULT_GROUP_COLOR="rgba(100, 200, 255, 0.6)",DEFAULT_STROKE_WIDTH=.1;package_default2={name:"circuit-to-svg",type:"module",version:"0.0.320",description:"Convert Circuit JSON to SVG",main:"dist/index.js",files:["dist"],scripts:{start:"cosmos",prepublish:"npm run build",build:"tsup-node ./lib/index.ts --format esm --dts --sourcemap --external tscircuit",format:"biome format . --write","format:check":"biome format .",cosmos:"cosmos","cosmos-export":"cosmos-export"},license:"ISC",devDependencies:{"@biomejs/biome":"^1.9.4","@tscircuit/alphabet":"^0.0.17","@types/bun":"^1.2.8","@vitejs/plugin-react":"5.0.0",biome:"^0.3.3","bun-match-svg":"^0.0.12","circuit-json":"^0.0.363",esbuild:"^0.20.2","performance-now":"^2.1.0",react:"19.1.0","react-cosmos":"7.0.0","react-cosmos-plugin-vite":"7.0.0","react-dom":"19.1.0",tscircuit:"^0.0.1248",tsup:"^8.0.2",typescript:"^5.4.5","vite-tsconfig-paths":"^5.0.1"},peerDependencies:{"@tscircuit/alphabet":"*"},dependencies:{"@types/node":"^22.5.5","bun-types":"^1.1.40","calculate-elbow":"0.0.12","svg-path-commander":"^2.1.11",svgson:"^5.3.1","transformation-matrix":"^2.16.1"}},CIRCUIT_TO_SVG_VERSION=package_default2.version,TYPE_PRIORITY={pcb_background:0,pcb_boundary:1,pcb_panel:5,pcb_board:10,pcb_cutout:15,pcb_cutout_path:15,pcb_keepout:16,pcb_hole:18,pcb_plated_hole_drill:19,pcb_plated_hole:20,pcb_trace_soldermask:25,pcb_trace:30,pcb_smtpad:30,pcb_copper_pour:35,pcb_via:36,pcb_soldermask:40,pcb_soldermask_opening:25,pcb_solder_paste:45,pcb_silkscreen_text:50,pcb_silkscreen_path:50,pcb_silkscreen_rect:50,pcb_silkscreen_circle:50,pcb_silkscreen_line:50,pcb_silkscreen_oval:50,pcb_silkscreen_pill:50,pcb_component:60,pcb_fabrication_note_text:70,pcb_fabrication_note_path:70,pcb_fabrication_note_rect:70,pcb_fabrication_note_dimension:70,pcb_note_dimension:70,pcb_note_text:70,pcb_note_rect:70,pcb_note_path:70,pcb_note_line:70,pcb_trace_error:80,pcb_rats_nest:85},DEFAULT_TYPE_PRIORITY=100;getViewportBounds=({circuitJson,drawPaddingOutsideBoard,baseBounds,viewportOptions})=>{let padding=drawPaddingOutsideBoard?1:0,boundsMinX=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.minX:baseBounds.boardMinX,boundsMinY=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.minY:baseBounds.boardMinY,boundsMaxX=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.maxX:baseBounds.boardMaxX,boundsMaxY=drawPaddingOutsideBoard||!baseBounds.hasBoardBounds?baseBounds.maxY:baseBounds.boardMaxY,hasPanelBounds=!1,panelMinX=Number.POSITIVE_INFINITY,panelMinY=Number.POSITIVE_INFINITY,panelMaxX=Number.NEGATIVE_INFINITY,panelMaxY=Number.NEGATIVE_INFINITY,panelBoundsById=new Map,boardBoundsById=new Map;for(let elm of circuitJson)if(elm.type==="pcb_panel"){let panel=elm,panelBounds=rectBounds(panel.center,panel.width,panel.height);if(!panelBounds)continue;panelMinX=Math.min(panelMinX,panelBounds.minX),panelMinY=Math.min(panelMinY,panelBounds.minY),panelMaxX=Math.max(panelMaxX,panelBounds.maxX),panelMaxY=Math.max(panelMaxY,panelBounds.maxY),hasPanelBounds=!0,panel.pcb_panel_id&&panelBoundsById.set(panel.pcb_panel_id,panelBounds)}else if(elm.type==="pcb_board"){let board=elm,boardBounds=getOutlineBounds(board.outline)??rectBounds(board.center,board.width,board.height);boardBounds&&board.pcb_board_id&&boardBoundsById.set(board.pcb_board_id,boardBounds)}if(viewportOptions?.viewport){let{minX,minY,maxX,maxY}=viewportOptions.viewport;boundsMinX=minX,boundsMinY=minY,boundsMaxX=maxX,boundsMaxY=maxY,padding=0}else if(viewportOptions?.viewportTarget?.pcb_panel_id){let panelBounds=panelBoundsById.get(viewportOptions.viewportTarget.pcb_panel_id);if(!panelBounds)throw new Error(`Viewport target panel '${viewportOptions.viewportTarget.pcb_panel_id}' not found`);boundsMinX=panelBounds.minX,boundsMinY=panelBounds.minY,boundsMaxX=panelBounds.maxX,boundsMaxY=panelBounds.maxY,padding=0}else if(viewportOptions?.viewportTarget?.pcb_board_id){let boardBounds=boardBoundsById.get(viewportOptions.viewportTarget.pcb_board_id);if(!boardBounds)throw new Error(`Viewport target board '${viewportOptions.viewportTarget.pcb_board_id}' not found`);boundsMinX=boardBounds.minX,boundsMinY=boardBounds.minY,boundsMaxX=boardBounds.maxX,boundsMaxY=boardBounds.maxY,padding=0}else hasPanelBounds&&(boundsMinX=panelMinX,boundsMinY=panelMinY,boundsMaxX=panelMaxX,boundsMaxY=panelMaxY);return{boundsMinX,boundsMinY,boundsMaxX,boundsMaxY,padding}};circuitJsonToPcbSvg=convertCircuitJsonToPcbSvg,DEFAULT_BOARD_STYLE={fill:"none",stroke:"rgb(0,0,0)",strokeOpacity:"0.8",strokeWidthFactor:.2};fontSizeMap={pin_number:.15,negated_pin_number:.15*.8,reference_designator:.18,manufacturer_number:.18,net_label:.18,error:.05},getSchMmFontSize=(textType,fontSize)=>fontSize??fontSizeMap[textType],getSchScreenFontSize=(transform5,textType,fontSize)=>Math.abs(transform5.a)*getSchMmFontSize(textType,fontSize);HOLE_COLOR2="rgb(190, 190, 190)";PAD_COLOR="rgb(210, 210, 210)",HOLE_COLOR3="rgb(190, 190, 190)";PAD_COLOR2="rgb(210, 210, 210)";OBJECT_ORDER=["pcb_component","pcb_smtpad","pcb_hole","pcb_plated_hole","pcb_board"];BOARD_FILL_COLOR="rgb(26, 115, 143)",BOARD_STROKE_COLOR="rgba(0,0,0,0.9)";COMPONENT_FILL_COLOR="rgba(120, 120, 120, 0.6)",COMPONENT_LABEL_COLOR="rgba(255, 255, 255, 0.9)";HOLE_COLOR4="rgb(50, 50, 50)";PAD_COLOR3="rgb(218, 165, 32)",HOLE_COLOR5="rgb(40, 40, 40)";PAD_COLOR4="rgb(218, 165, 32)";LABEL_COLOR="rgb(255, 255, 255)",LABEL_BACKGROUND="rgb(0, 0, 0)",LINE_COLOR="rgba(0, 0, 0, 0.6)",PIN_NUMBER_BACKGROUND="rgb(200, 200, 200)",PIN_NUMBER_COLOR="rgb(0, 0, 0)";LABEL_RECT_HEIGHT_BASE_MM=1.6,FONT_HEIGHT_RATIO=11/21,CHAR_WIDTH_FACTOR=.6,STAGGER_OFFSET_MIN=.1,STAGGER_OFFSET_PER_PIN=.1,STAGGER_OFFSET_STEP=3,ALIGNED_OFFSET_MARGIN=.1,GROUP_SEPARATION_MM=.8;calculateLabelPositions=({left_labels,right_labels,transform:transform5,soup,board_bounds,svgWidth,svgHeight,styleScale})=>{let label_positions=new Map,shared_params={transform:transform5,soup,board_bounds};return calculateVerticalEdgeLabels("left",left_labels,{...shared_params,svgHeight,styleScale},label_positions),calculateVerticalEdgeLabels("right",right_labels,{...shared_params,svgHeight,styleScale},label_positions),label_positions};OBJECT_ORDER2=["pcb_board","pcb_smtpad","pcb_hole","pcb_plated_hole","pcb_component","pcb_port"];arialTextMetrics={0:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},1:{width:13,height:27,ascent:22,descent:5,left:-3,right:9},2:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},3:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},4:{width:13,height:27,ascent:22,descent:5,left:0,right:12},5:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},6:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},7:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},8:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},9:{width:13,height:27,ascent:22,descent:5,left:-1,right:12}," ":{width:7,height:27,ascent:22,descent:5,left:0,right:0},"!":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},'"':{width:9,height:27,ascent:22,descent:5,left:-1,right:7},"#":{width:13,height:27,ascent:22,descent:5,left:0,right:13},$:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},"%":{width:21,height:27,ascent:22,descent:5,left:-1,right:20},"&":{width:16,height:27,ascent:22,descent:5,left:-1,right:15},"'":{width:5,height:27,ascent:22,descent:5,left:-1,right:3},"(":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},")":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},"*":{width:9,height:27,ascent:22,descent:5,left:-1,right:8},"+":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},",":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},"-":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},".":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},"/":{width:7,height:27,ascent:22,descent:5,left:0,right:7},":":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},";":{width:7,height:27,ascent:22,descent:5,left:-2,right:5},"<":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},"=":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},">":{width:14,height:27,ascent:22,descent:5,left:-1,right:13},"?":{width:13,height:27,ascent:22,descent:5,left:-1,right:12},"@":{width:24,height:27,ascent:22,descent:5,left:-1,right:23},A:{width:16,height:27,ascent:22,descent:5,left:0,right:16},B:{width:16,height:27,ascent:22,descent:5,left:-2,right:15},C:{width:17,height:27,ascent:22,descent:5,left:-1,right:16},D:{width:17,height:27,ascent:22,descent:5,left:-2,right:16},E:{width:16,height:27,ascent:22,descent:5,left:-2,right:15},F:{width:15,height:27,ascent:22,descent:5,left:-2,right:14},G:{width:19,height:27,ascent:22,descent:5,left:-1,right:17},H:{width:17,height:27,ascent:22,descent:5,left:-2,right:15},I:{width:7,height:27,ascent:22,descent:5,left:-2,right:5},J:{width:12,height:27,ascent:22,descent:5,left:-1,right:10},K:{width:16,height:27,ascent:22,descent:5,left:-2,right:16},L:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},M:{width:20,height:27,ascent:22,descent:5,left:-2,right:18},N:{width:17,height:27,ascent:22,descent:5,left:-2,right:15},O:{width:19,height:27,ascent:22,descent:5,left:-1,right:18},P:{width:16,height:27,ascent:22,descent:5,left:-2,right:15},Q:{width:19,height:27,ascent:22,descent:5,left:-1,right:18},R:{width:17,height:27,ascent:22,descent:5,left:-2,right:17},S:{width:16,height:27,ascent:22,descent:5,left:-1,right:15},T:{width:15,height:27,ascent:22,descent:5,left:-1,right:14},U:{width:17,height:27,ascent:22,descent:5,left:-2,right:15},V:{width:16,height:27,ascent:22,descent:5,left:0,right:16},W:{width:23,height:27,ascent:22,descent:5,left:0,right:22},X:{width:16,height:27,ascent:22,descent:5,left:0,right:16},Y:{width:16,height:27,ascent:22,descent:5,left:0,right:16},Z:{width:15,height:27,ascent:22,descent:5,left:0,right:14},"[":{width:7,height:27,ascent:22,descent:5,left:-2,right:6},"\\":{width:7,height:27,ascent:22,descent:5,left:0,right:7},"]":{width:7,height:27,ascent:22,descent:5,left:0,right:5},"^":{width:11,height:27,ascent:22,descent:5,left:-1,right:11},_:{width:13,height:27,ascent:22,descent:5,left:0,right:14},"`":{width:8,height:27,ascent:22,descent:5,left:-1,right:5},a:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},b:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},c:{width:12,height:27,ascent:22,descent:5,left:-1,right:12},d:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},e:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},f:{width:7,height:27,ascent:22,descent:5,left:0,right:8},g:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},h:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},i:{width:5,height:27,ascent:22,descent:5,left:-2,right:4},j:{width:5,height:27,ascent:22,descent:5,left:1,right:4},k:{width:12,height:27,ascent:22,descent:5,left:-2,right:12},l:{width:5,height:27,ascent:22,descent:5,left:-2,right:4},m:{width:20,height:27,ascent:22,descent:5,left:-2,right:18},n:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},o:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},p:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},q:{width:13,height:27,ascent:22,descent:5,left:-1,right:12},r:{width:8,height:27,ascent:22,descent:5,left:-2,right:8},s:{width:12,height:27,ascent:22,descent:5,left:-1,right:11},t:{width:7,height:27,ascent:22,descent:5,left:0,right:6},u:{width:13,height:27,ascent:22,descent:5,left:-2,right:12},v:{width:12,height:27,ascent:22,descent:5,left:0,right:12},w:{width:17,height:27,ascent:22,descent:5,left:0,right:17},x:{width:12,height:27,ascent:22,descent:5,left:0,right:12},y:{width:12,height:27,ascent:22,descent:5,left:0,right:12},z:{width:12,height:27,ascent:22,descent:5,left:0,right:11},"{":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},"|":{width:6,height:27,ascent:22,descent:5,left:-2,right:4},"}":{width:8,height:27,ascent:22,descent:5,left:-1,right:7},"~":{width:14,height:27,ascent:22,descent:5,left:-1,right:13}},estimateTextWidth=text=>{if(!text)return 0;let totalWidth=0;for(let char of text){let metrics=arialTextMetrics[char];metrics?totalWidth+=metrics.width:totalWidth+=arialTextMetrics["?"].width}return totalWidth/27},getTableDimensions=(schematicTable,circuitJson)=>{if(schematicTable.column_widths&&schematicTable.column_widths.length>0&&schematicTable.row_heights&&schematicTable.row_heights.length>0){let unitToMm2=v5=>typeof v5=="number"?v5:v5.endsWith("mm")?parseFloat(v5):v5.endsWith("in")?parseFloat(v5)*25.4:parseFloat(v5);return{column_widths:schematicTable.column_widths.map(unitToMm2),row_heights:schematicTable.row_heights.map(unitToMm2)}}let cells=circuitJson.filter(elm=>elm.type==="schematic_table_cell"&&elm.schematic_table_id===schematicTable.schematic_table_id);if(cells.length===0)return{column_widths:[],row_heights:[]};let numColumns=cells.reduce((max,c3)=>Math.max(max,c3.end_column_index),-1)+1,numRows=cells.reduce((max,c3)=>Math.max(max,c3.end_row_index),-1)+1,{cell_padding=.2}=schematicTable,column_widths=new Array(numColumns).fill(0),row_heights=new Array(numRows).fill(0),cell_widths={},cell_heights={};for(let cell of cells){let fontSizeMm=getSchMmFontSize("reference_designator",cell.font_size),requiredWidth=estimateTextWidth(cell.text??"")*fontSizeMm+2*cell_padding,requiredHeight=fontSizeMm*1.2+2*cell_padding,key=`${cell.start_row_index}-${cell.start_column_index}`;cell_widths[key]=requiredWidth,cell_heights[key]=requiredHeight}for(let i2=0;i2<numRows;i2++)for(let j4=0;j4<numColumns;j4++){let key=`${i2}-${j4}`;cell_widths[key]&&cell_widths[key]>column_widths[j4]&&(column_widths[j4]=cell_widths[key]),cell_heights[key]&&cell_heights[key]>row_heights[i2]&&(row_heights[i2]=cell_heights[key])}for(let cell of cells){if(cell.start_column_index===cell.end_column_index&&cell.start_row_index===cell.end_row_index)continue;let key=`${cell.start_row_index}-${cell.start_column_index}`,requiredWidth=cell_widths[key],requiredHeight=cell_heights[key];if(requiredWidth===void 0||requiredHeight===void 0)continue;let currentWidth=0;for(let i2=cell.start_column_index;i2<=cell.end_column_index;i2++)currentWidth+=column_widths[i2];if(requiredWidth>currentWidth){let extraPerColumn=(requiredWidth-currentWidth)/(cell.end_column_index-cell.start_column_index+1);for(let i2=cell.start_column_index;i2<=cell.end_column_index;i2++)column_widths[i2]+=extraPerColumn}let currentHeight=0;for(let i2=cell.start_row_index;i2<=cell.end_row_index;i2++)currentHeight+=row_heights[i2];if(requiredHeight>currentHeight){let extraPerRow=(requiredHeight-currentHeight)/(cell.end_row_index-cell.start_row_index+1);for(let i2=cell.start_row_index;i2<=cell.end_row_index;i2++)row_heights[i2]+=extraPerRow}}return{column_widths,row_heights}},getUnitVectorFromOutsideToEdge=side=>{switch(side){case"top":return{x:0,y:-1};case"bottom":return{x:0,y:1};case"left":return{x:1,y:0};case"right":return{x:-1,y:0}}throw new Error(`Invalid side: ${side}`)},ARROW_POINT_WIDTH_FSR=.3,END_PADDING_FSR=.3,END_PADDING_EXTRA_PER_CHARACTER_FSR=.06,ninePointAnchorToTextAnchor={top_left:"start",top_right:"end",middle_left:"start",middle_right:"end",bottom_left:"start",bottom_right:"end",center:"middle",middle_top:"middle",middle_bottom:"middle"},ninePointAnchorToDominantBaseline={top_left:"hanging",top_right:"hanging",bottom_left:"ideographic",bottom_right:"ideographic",center:"middle",middle_left:"middle",middle_right:"middle",middle_top:"hanging",middle_bottom:"ideographic"};getSchStrokeSize=transform5=>Math.abs(transform5.a)*.02,getAngularDifference=(angle1,angle2)=>{let a12=angle1<0?angle1+2*Math.PI:angle1,a2=angle2<0?angle2+2*Math.PI:angle2,diff=Math.abs(a12-a2);return diff>Math.PI&&(diff=2*Math.PI-diff),diff},matchSchPortsToSymbolPorts=({schPorts,symbol,schComponent})=>{let schPortAngles=schPorts.map(port=>{let dx2=port.center.x-schComponent.center.x,dy2=port.center.y-schComponent.center.y;return{port,angle:Math.atan2(dy2,dx2)}}),symbolPortAngles=symbol.ports.map(port=>{let dx2=port.x-symbol.center.x,dy2=port.y-symbol.center.y;return{port,angle:Math.atan2(dy2,dx2)}});schPortAngles.sort((a2,b3)=>a2.angle-b3.angle),symbolPortAngles.sort((a2,b3)=>a2.angle-b3.angle);let matches=[],usedSymbolPorts=new Set;for(let schPortAngle of schPortAngles){let bestMatch=null;for(let symbolPortAngle of symbolPortAngles){if(usedSymbolPorts.has(symbolPortAngle.port))continue;let angleDiff=getAngularDifference(schPortAngle.angle,symbolPortAngle.angle);(bestMatch===null||angleDiff<bestMatch.angleDiff)&&(bestMatch={symbolPort:symbolPortAngle.port,angleDiff})}bestMatch&&bestMatch.angleDiff<Math.PI/4&&(matches.push({schPort:schPortAngle.port,symbolPort:bestMatch.symbolPort}),usedSymbolPorts.add(bestMatch.symbolPort))}return matches};createSvgSchErrorText=({text,realCenter,realToScreenTransform})=>{let screenCenter=applyToPoint3(realToScreenTransform,realCenter);return{type:"element",name:"text",value:"",attributes:{x:screenCenter.x.toString(),y:screenCenter.y.toString(),fill:"red","text-anchor":"middle","dominant-baseline":"middle","font-family":"sans-serif","font-size":`${getSchScreenFontSize(realToScreenTransform,"error")}px`},children:[{type:"text",value:text,name:"",attributes:{},children:[]}]}},isSourcePortConnected=(circuitJson,sourcePortId)=>{for(let elm of circuitJson){if(elm.type!=="source_trace")continue;let trace=elm;if(Array.isArray(trace.connected_source_port_ids)&&trace.connected_source_port_ids.includes(sourcePortId))return!0}return!1},ninePointAnchorToTextAnchor2={top_left:"start",top_right:"end",middle_left:"start",middle_right:"end",bottom_left:"start",bottom_right:"end",center:"middle",middle_top:"middle",middle_bottom:"middle"},createSvgObjectsFromSchematicComponentWithSymbol=({component:schComponent,transform:realToScreenTransform,circuitJson,colorMap:colorMap2})=>{let svgObjects=[],symbol=Vf[schComponent.symbol_name];if(!symbol)return[createSvgSchErrorText({text:`Symbol not found: ${schComponent.symbol_name}`,realCenter:schComponent.center,realToScreenTransform})];let schPorts=su2(circuitJson).schematic_port.list({schematic_component_id:schComponent.schematic_component_id}),srcComponent=su2(circuitJson).source_component.get(schComponent.source_component_id),schPortsWithSymbolPorts=matchSchPortsToSymbolPorts({schPorts,symbol,schComponent});if(!schPortsWithSymbolPorts[0])return[createSvgSchErrorText({text:`Could not match ports for symbol ${schComponent.symbol_name}`,realCenter:schComponent.center,realToScreenTransform})];let transformFromSymbolToReal=pointPairsToMatrix(schPortsWithSymbolPorts[1]?.symbolPort??symbol.center,schPortsWithSymbolPorts[1]?.schPort.center??schComponent.center,schPortsWithSymbolPorts[0].symbolPort,schPortsWithSymbolPorts[0].schPort.center),paths=symbol.primitives.filter(p4=>p4.type==="path"),texts=symbol.primitives.filter(p4=>p4.type==="text"),circles=symbol.primitives.filter(p4=>p4.type==="circle"),boxes=symbol.primitives.filter(p4=>p4.type==="box"),connectedSymbolPorts=new Set;for(let match2 of schPortsWithSymbolPorts)isSourcePortConnected(circuitJson,match2.schPort.source_port_id)&&connectedSymbolPorts.add(match2.symbolPort);let bounds={minX:Math.min(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.x))),maxX:Math.max(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.x))),minY:Math.min(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.y))),maxY:Math.max(...paths.flatMap(p4=>p4.points.map(pt4=>pt4.y)))},[screenMinX,screenMinY]=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),[bounds.minX,bounds.minY]),[screenMaxX,screenMaxY]=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),[bounds.maxX,bounds.maxY]),rectHeight=Math.abs(screenMaxY-screenMinY),rectY=Math.min(screenMinY,screenMaxY),rectWidth=Math.abs(screenMaxX-screenMinX),rectX=Math.min(screenMinX,screenMaxX);svgObjects.push({name:"rect",type:"element",value:"",attributes:{class:"component-overlay",x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),fill:"transparent"},children:[]});for(let path of paths){let{points,color,closed,fill}=path;svgObjects.push({type:"element",name:"path",attributes:{d:points.map((p4,i2)=>{let[x5,y5]=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),[p4.x,p4.y]);return`${i2===0?"M":"L"} ${x5} ${y5}`}).join(" ")+(closed?" Z":""),stroke:colorMap2.schematic.component_outline,fill:"none","stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,"stroke-linecap":"round"},value:"",children:[]})}for(let text of texts){let screenTextPos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),text),textValue="";text.text==="{REF}"?textValue=srcComponent?.display_name??srcComponent?.name??"":text.text==="{VAL}"&&(textValue=schComponent.symbol_display_value??"");let baseOffset=Math.abs(bounds.maxY-bounds.minY)*.1,transformScale=Math.abs(transformFromSymbolToReal.a),verticalOffset=0;text.anchor.includes("bottom")?verticalOffset=baseOffset*transformScale:text.anchor.includes("top")&&(verticalOffset=-baseOffset*transformScale);let dominantBaseline=text.anchor.includes("bottom")?"auto":text.anchor.includes("top")?"hanging":"middle",isReferenceText=text.text==="{REF}";svgObjects.push({name:"text",type:"element",attributes:{x:screenTextPos.x.toString(),y:(screenTextPos.y+verticalOffset).toString(),...isReferenceText?{stroke:colorMap2.schematic.background,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,"paint-order":"stroke"}:{},fill:colorMap2.schematic.label_local,"font-family":"sans-serif","text-anchor":ninePointAnchorToTextAnchor2[text.anchor],"dominant-baseline":dominantBaseline,"font-size":`${getSchScreenFontSize(realToScreenTransform,"reference_designator")}px`},value:"",children:[{type:"text",value:textValue,name:"",attributes:{},children:[]}]})}for(let box2 of boxes){let screenBoxPos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),box2),symbolToScreenScale=compose3(realToScreenTransform,transformFromSymbolToReal).a;svgObjects.push({name:"rect",type:"element",attributes:{x:screenBoxPos.x.toString(),y:screenBoxPos.y.toString(),width:(box2.width*symbolToScreenScale).toString(),height:(box2.height*symbolToScreenScale).toString(),fill:"red"},value:"",children:[]})}for(let port of symbol.ports){if(connectedSymbolPorts.has(port))continue;let screenPortPos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),port);svgObjects.push({type:"element",name:"circle",attributes:{cx:screenPortPos.x.toString(),cy:screenPortPos.y.toString(),r:`${Math.abs(realToScreenTransform.a)*.02}px`,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,fill:"none",stroke:colorMap2.schematic.component_outline},value:"",children:[]})}for(let circle2 of circles){let screenCirclePos=applyToPoint3(compose3(realToScreenTransform,transformFromSymbolToReal),circle2),screenRadius=Math.abs(circle2.radius*realToScreenTransform.a);svgObjects.push({type:"element",name:"circle",attributes:{cx:screenCirclePos.x.toString(),cy:screenCirclePos.y.toString(),r:`${screenRadius}px`,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,fill:"none",stroke:colorMap2.schematic.component_outline},value:"",children:[]})}return svgObjects},PIN_CIRCLE_RADIUS_MM=.02,createArrow=(tip,angle,size2,color,strokeWidth)=>{let arrowAngle=Math.PI/6,p12={x:tip.x-size2*Math.cos(angle-arrowAngle),y:tip.y-size2*Math.sin(angle-arrowAngle)},p22={x:tip.x-size2*Math.cos(angle+arrowAngle),y:tip.y-size2*Math.sin(angle+arrowAngle)};return{name:"polygon",type:"element",attributes:{points:`${tip.x},${tip.y} ${p12.x},${p12.y} ${p22.x},${p22.y}`,fill:"white",stroke:color,"stroke-width":`${strokeWidth}px`},value:"",children:[]}},createSvgObjectsForSchPortBoxLine=({schPort,schComponent,transform:transform5,circuitJson})=>{let svgObjects=[],srcPort=su2(circuitJson).source_port.get(schPort.source_port_id),realEdgePos={x:schPort.center.x,y:schPort.center.y},realPinLineLength=schPort.distance_from_component_edge??.4;switch(schPort.side_of_component){case"left":realEdgePos.x+=realPinLineLength;break;case"right":realEdgePos.x-=realPinLineLength;break;case"top":realEdgePos.y-=realPinLineLength;break;case"bottom":realEdgePos.y+=realPinLineLength;break}let screenSchPortPos=applyToPoint3(transform5,schPort.center),screenRealEdgePos=applyToPoint3(transform5,realEdgePos),isConnected=isSourcePortConnected(circuitJson,schPort.source_port_id),is_drawn_with_inversion_circle=schPort.is_drawn_with_inversion_circle??!1,BUBBLE_RADIUS_MM=.06,realLineEnd={...schPort.center};if(!isConnected)switch(schPort.side_of_component){case"left":realLineEnd.x+=PIN_CIRCLE_RADIUS_MM;break;case"right":realLineEnd.x-=PIN_CIRCLE_RADIUS_MM;break;case"top":realLineEnd.y-=PIN_CIRCLE_RADIUS_MM;break;case"bottom":realLineEnd.y+=PIN_CIRCLE_RADIUS_MM;break}let screenLineEnd=applyToPoint3(transform5,realLineEnd);if(is_drawn_with_inversion_circle){let bubbleRadiusPx=Math.abs(transform5.a)*BUBBLE_RADIUS_MM,bubbleCenter={...screenRealEdgePos};switch(schPort.side_of_component){case"left":bubbleCenter.x-=bubbleRadiusPx,screenRealEdgePos.x-=bubbleRadiusPx*2;break;case"right":bubbleCenter.x+=bubbleRadiusPx,screenRealEdgePos.x+=bubbleRadiusPx*2;break;case"top":bubbleCenter.y-=bubbleRadiusPx,screenRealEdgePos.y-=bubbleRadiusPx*2;break;case"bottom":bubbleCenter.y+=bubbleRadiusPx,screenRealEdgePos.y+=bubbleRadiusPx*2;break}svgObjects.push({name:"circle",type:"element",attributes:{class:"component-pin",cx:bubbleCenter.x.toString(),cy:bubbleCenter.y.toString(),r:bubbleRadiusPx.toString(),fill:"white",stroke:colorMap.schematic.component_outline,"stroke-width":`${getSchStrokeSize(transform5)}px`},value:"",children:[]})}svgObjects.push({name:"line",type:"element",attributes:{class:"component-pin",x1:screenRealEdgePos.x.toString(),y1:screenRealEdgePos.y.toString(),x2:screenLineEnd.x.toString(),y2:screenLineEnd.y.toString(),"stroke-width":`${getSchStrokeSize(transform5)}px`},value:"",children:[]});let pinRadiusPx=Math.abs(transform5.a)*PIN_CIRCLE_RADIUS_MM,pinChildren=[];isConnected||pinChildren.push({name:"circle",type:"element",attributes:{class:"component-pin",cx:screenSchPortPos.x.toString(),cy:screenSchPortPos.y.toString(),r:pinRadiusPx.toString(),"stroke-width":`${getSchStrokeSize(transform5)}px`},value:"",children:[]}),pinChildren.push({name:"rect",type:"element",attributes:{x:(screenSchPortPos.x-pinRadiusPx).toString(),y:(screenSchPortPos.y-pinRadiusPx).toString(),width:(pinRadiusPx*2).toString(),height:(pinRadiusPx*2).toString(),opacity:"0"},value:"",children:[]}),svgObjects.push({name:"g",type:"element",value:"",attributes:{"data-schematic-port-id":schPort.source_port_id},children:pinChildren});let{has_input_arrow,has_output_arrow}=schPort;if((has_input_arrow||has_output_arrow)&&schPort.side_of_component){let arrowSize=Math.abs(transform5.a)*.1,arrowColor=colorMap.schematic.component_outline,arrowAxialLength=arrowSize*Math.cos(Math.PI/6),strokeWidth=getSchStrokeSize(transform5)/3,inputAngleRads=0,outputAngleRads=0;schPort.side_of_component==="left"?(inputAngleRads=0,outputAngleRads=Math.PI):schPort.side_of_component==="right"?(inputAngleRads=Math.PI,outputAngleRads=0):schPort.side_of_component==="top"?(inputAngleRads=Math.PI/2,outputAngleRads=-Math.PI/2):schPort.side_of_component==="bottom"&&(inputAngleRads=-Math.PI/2,outputAngleRads=Math.PI/2);let both=has_input_arrow&&has_output_arrow,inputArrowTip={...screenRealEdgePos},outputArrowBase={...screenRealEdgePos};if(both){let offset=arrowAxialLength;schPort.side_of_component==="left"?outputArrowBase.x-=offset:schPort.side_of_component==="right"?outputArrowBase.x+=offset:schPort.side_of_component==="top"?outputArrowBase.y-=offset:schPort.side_of_component==="bottom"&&(outputArrowBase.y+=offset)}if(has_input_arrow&&svgObjects.push(createArrow(inputArrowTip,inputAngleRads,arrowSize,arrowColor,strokeWidth)),has_output_arrow){let outputArrowTip={x:outputArrowBase.x+arrowSize*Math.cos(outputAngleRads),y:outputArrowBase.y+arrowSize*Math.sin(outputAngleRads)};svgObjects.push(createArrow(outputArrowTip,outputAngleRads,arrowSize,arrowColor,strokeWidth))}}return svgObjects},createSvgObjectsForSchPortPinNumberText=params=>{let svgObjects=[],{schPort,schComponent,transform:transform5,circuitJson}=params,realPinNumberPos={x:schPort.center.x,y:schPort.center.y};if(!schPort.side_of_component)return[];let vecToEdge=getUnitVectorFromOutsideToEdge(schPort.side_of_component),realPinEdgeDistance=schPort.distance_from_component_edge??.4;realPinNumberPos.x+=vecToEdge.x*realPinEdgeDistance/2,realPinNumberPos.y+=vecToEdge.y*realPinEdgeDistance/2,schPort.side_of_component==="top"||schPort.side_of_component==="bottom"?realPinNumberPos.x-=.02:realPinNumberPos.y+=.02;let screenPinNumberTextPos=applyToPoint3(transform5,realPinNumberPos);return svgObjects.push({name:"text",type:"element",attributes:{class:"pin-number",x:screenPinNumberTextPos.x.toString(),y:screenPinNumberTextPos.y.toString(),style:"font-family: sans-serif;",fill:colorMap.schematic.pin_number,"text-anchor":"middle","dominant-baseline":"auto","font-size":`${getSchScreenFontSize(transform5,"pin_number")}px`,transform:schPort.side_of_component==="top"||schPort.side_of_component==="bottom"?`rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})`:""},children:[{type:"text",value:schPort.pin_number?.toString()||"",name:"",attributes:{},children:[]}],value:""}),svgObjects},LABEL_DIST_FROM_EDGE_MM=.1,createSvgObjectsForSchPortPinLabel=params=>{let svgObjects=[],{schPort,schComponent,transform:transform5,circuitJson}=params,realPinNumberPos={x:schPort.center.x,y:schPort.center.y};if(!schPort.side_of_component)return[];let vecToEdge=getUnitVectorFromOutsideToEdge(schPort.side_of_component),realPinEdgeDistance=schPort.distance_from_component_edge??.4;realPinNumberPos.x+=vecToEdge.x*(realPinEdgeDistance+LABEL_DIST_FROM_EDGE_MM),realPinNumberPos.y+=vecToEdge.y*(realPinEdgeDistance+LABEL_DIST_FROM_EDGE_MM);let screenPinNumberTextPos=applyToPoint3(transform5,realPinNumberPos),label=schPort.display_pin_label??schComponent.port_labels?.[`${schPort.pin_number}`];if(!label)return[];let isNegated=label.startsWith("N_"),displayLabel=isNegated?label.slice(2):label,is_drawn_with_inversion_circle=schPort.is_drawn_with_inversion_circle??!1,fontSizePx=getSchScreenFontSize(transform5,isNegated||is_drawn_with_inversion_circle?"negated_pin_number":"pin_number");return svgObjects.push({name:"text",type:"element",attributes:{class:"pin-number",x:screenPinNumberTextPos.x.toString(),y:screenPinNumberTextPos.y.toString(),style:`font-family: sans-serif;${isNegated?" text-decoration: overline;":""}`,fill:colorMap.schematic.pin_number,"text-anchor":schPort.side_of_component==="left"||schPort.side_of_component==="bottom"?"start":"end","dominant-baseline":"middle","font-size":`${fontSizePx}px`,transform:schPort.side_of_component==="top"||schPort.side_of_component==="bottom"?`rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})`:""},children:[{type:"text",value:displayLabel||"",name:"",attributes:{},children:[]}],value:""}),svgObjects},createSvgObjectsFromSchPortOnBox=params=>{let svgObjects=[],{schPort,schComponent,transform:transform5,circuitJson}=params;return svgObjects.push(...createSvgObjectsForSchPortBoxLine(params)),svgObjects.push(...createSvgObjectsForSchPortPinNumberText(params)),svgObjects.push(...createSvgObjectsForSchPortPinLabel(params)),svgObjects},createSvgSchText=({elm,transform:transform5,colorMap:colorMap2})=>{let center2=applyToPoint3(transform5,elm.position),textAnchorMap={center:"middle",center_right:"end",bottom_left:"start",bottom_center:"middle",bottom_right:"end",left:"start",right:"end",top:"middle",bottom:"middle",top_left:"start",top_center:"middle",top_right:"end",center_left:"start"},dominantBaselineMap={center:"middle",center_right:"middle",bottom_left:"ideographic",bottom_center:"ideographic",bottom_right:"ideographic",left:"middle",right:"middle",top:"hanging",bottom:"ideographic",top_left:"hanging",top_center:"hanging",top_right:"hanging",center_left:"middle"},lines=elm.text.split(`
|
|
336
336
|
`),children=lines.length===1?[{type:"text",value:elm.text,name:elm.schematic_text_id,attributes:{},children:[]}]:lines.map((line2,idx)=>({type:"element",name:"tspan",value:"",attributes:{x:center2.x.toString(),...idx>0?{dy:"1em"}:{}},children:[{type:"text",value:line2,name:idx===0?elm.schematic_text_id:"",attributes:{},children:[]}]}));return{type:"element",name:"text",value:"",attributes:{x:center2.x.toString(),y:center2.y.toString(),fill:elm.color??colorMap2.schematic.sheet_label,"text-anchor":textAnchorMap[elm.anchor],"dominant-baseline":dominantBaselineMap[elm.anchor],"font-family":"sans-serif","font-size":`${getSchScreenFontSize(transform5,"reference_designator",elm.font_size)}px`,transform:`rotate(${elm.rotation}, ${center2.x}, ${center2.y})`},children}},createSvgObjectsFromSchematicComponentWithBox=({component:schComponent,transform:transform5,circuitJson,colorMap:colorMap2})=>{let svgObjects=[],componentScreenTopLeft=applyToPoint3(transform5,{x:schComponent.center.x-schComponent.size.width/2,y:schComponent.center.y+schComponent.size.height/2}),componentScreenBottomRight=applyToPoint3(transform5,{x:schComponent.center.x+schComponent.size.width/2,y:schComponent.center.y-schComponent.size.height/2}),componentScreenWidth=componentScreenBottomRight.x-componentScreenTopLeft.x,componentScreenHeight=componentScreenBottomRight.y-componentScreenTopLeft.y;svgObjects.push({name:"rect",type:"element",value:"",attributes:{class:"component chip",x:componentScreenTopLeft.x.toString(),y:componentScreenTopLeft.y.toString(),width:componentScreenWidth.toString(),height:componentScreenHeight.toString(),"stroke-width":`${getSchStrokeSize(transform5)}px`,fill:colorMap2.schematic.component_body,stroke:colorMap2.schematic.component_outline},children:[]}),svgObjects.push({name:"rect",type:"element",value:"",attributes:{class:"component-overlay",x:componentScreenTopLeft.x.toString(),y:componentScreenTopLeft.y.toString(),width:componentScreenWidth.toString(),height:componentScreenHeight.toString(),fill:"transparent"},children:[]});let schTexts=su2(circuitJson).schematic_text.list();for(let schText of schTexts)schText.schematic_component_id===schComponent.schematic_component_id&&svgObjects.push(createSvgSchText({elm:schText,transform:transform5,colorMap:colorMap2}));let schematicPorts=su2(circuitJson).schematic_port.list({schematic_component_id:schComponent.schematic_component_id});for(let schPort of schematicPorts)svgObjects.push(...createSvgObjectsFromSchPortOnBox({schPort,schComponent,transform:transform5,circuitJson}));return svgObjects};createSvgObjectsForSchNetLabelWithSymbol=({schNetLabel,realToScreenTransform,colorMap:colorMap2})=>{if(!schNetLabel.text)return[];let isNegated=schNetLabel.text.startsWith("N_"),labelText=isNegated?schNetLabel.text.slice(2):schNetLabel.text,svgObjects=[],symbol=Vf[schNetLabel.symbol_name];if(!symbol)return svgObjects.push(createSvgSchErrorText({text:`Symbol not found: ${schNetLabel.symbol_name}`,realCenter:schNetLabel.center,realToScreenTransform})),svgObjects;let symbolPaths=symbol.primitives.filter(p4=>p4.type==="path"),symbolTexts=symbol.primitives.filter(p4=>p4.type==="text"),symbolCircles=symbol.primitives.filter(p4=>p4.type==="circle"),symbolBoxes=symbol.primitives.filter(p4=>p4.type==="box"),bounds={minX:Math.min(...symbolPaths.flatMap(p4=>p4.points.map(pt4=>pt4.x))),maxX:Math.max(...symbolPaths.flatMap(p4=>p4.points.map(pt4=>pt4.x))),minY:Math.min(...symbolPaths.flatMap(p4=>p4.points.map(pt4=>pt4.y))),maxY:Math.max(...symbolPaths.flatMap(p4=>p4.points.map(pt4=>pt4.y)))},fontSizeMm=getSchMmFontSize("net_label"),fullWidthFsr=estimateTextWidth(labelText||"")+ARROW_POINT_WIDTH_FSR*2+END_PADDING_EXTRA_PER_CHARACTER_FSR*labelText.length+END_PADDING_FSR,realTextGrowthVec=getUnitVectorFromOutsideToEdge(schNetLabel.anchor_side),realAnchorPosition=schNetLabel.anchor_position??{x:schNetLabel.center.x-realTextGrowthVec.x*fullWidthFsr*fontSizeMm/2,y:schNetLabel.center.y-realTextGrowthVec.y*fullWidthFsr*fontSizeMm/2},rotationMatrix=rotate3(0/180*Math.PI),symbolBounds={minX:Math.min(...symbol.primitives.flatMap(p4=>p4.type==="path"?p4.points.map(pt4=>pt4.x):[])),maxX:Math.max(...symbol.primitives.flatMap(p4=>p4.type==="path"?p4.points.map(pt4=>pt4.x):[])),minY:Math.min(...symbol.primitives.flatMap(p4=>p4.type==="path"?p4.points.map(pt4=>pt4.y):[])),maxY:Math.max(...symbol.primitives.flatMap(p4=>p4.type==="path"?p4.points.map(pt4=>pt4.y):[]))},symbolEndPoint=symbol.ports?.[0]?{x:symbol.ports[0].x,y:symbol.ports[0].y}:{x:symbolBounds.minX,y:(symbolBounds.minY+symbolBounds.maxY)/2},rotatedSymbolEnd=applyToPoint3(rotationMatrix,symbolEndPoint),symbolToRealTransform=compose3(translate3(realAnchorPosition.x-rotatedSymbolEnd.x,realAnchorPosition.y-rotatedSymbolEnd.y),rotationMatrix,scale3(1)),[screenMinX,screenMinY]=applyToPoint3(compose3(realToScreenTransform,symbolToRealTransform),[bounds.minX,bounds.minY]),[screenMaxX,screenMaxY]=applyToPoint3(compose3(realToScreenTransform,symbolToRealTransform),[bounds.maxX,bounds.maxY]),rectHeight=Math.abs(screenMaxY-screenMinY),rectY=Math.min(screenMinY,screenMaxY),rectWidth=Math.abs(screenMaxX-screenMinX),rectX=Math.min(screenMinX,screenMaxX);svgObjects.push({name:"rect",type:"element",value:"",attributes:{class:"component-overlay",x:rectX.toString(),y:rectY.toString(),width:rectWidth.toString(),height:rectHeight.toString(),fill:"transparent"},children:[]});for(let path of symbolPaths){let symbolPath=path.points.map((p4,i2)=>{let[x5,y5]=applyToPoint3(compose3(realToScreenTransform,symbolToRealTransform),[p4.x,p4.y]);return`${i2===0?"M":"L"} ${x5} ${y5}`}).join(" ");svgObjects.push({name:"path",type:"element",attributes:{d:symbolPath+(path.closed?" Z":""),stroke:colorMap2.schematic.component_outline,fill:"none","stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`,"stroke-linecap":"round"},value:"",children:[]})}for(let text of symbolTexts){let screenTextPos=applyToPoint3(compose3(realToScreenTransform,symbolToRealTransform),text),textValue=text.text;textValue==="{REF}"?textValue=labelText||"":textValue==="{VAL}"&&(textValue="");let baseOffset=Math.abs(realToScreenTransform.a)*.1,offsetScreenPos={x:screenTextPos.x,y:screenTextPos.y};svgObjects.push({name:"text",type:"element",attributes:{x:offsetScreenPos.x.toString(),y:offsetScreenPos.y.toString(),fill:colorMap2.schematic.label_local,"font-family":"sans-serif","text-anchor":ninePointAnchorToTextAnchor[text.anchor],"dominant-baseline":ninePointAnchorToDominantBaseline[text.anchor],"font-size":`${getSchScreenFontSize(realToScreenTransform,"reference_designator")}px`,...isNegated&&textValue===labelText?{style:"text-decoration: overline;"}:{}},children:[{type:"text",value:textValue,name:"",attributes:{},children:[]}],value:""})}for(let box2 of symbolBoxes){let screenBoxPos=applyToPoint3(compose3(realToScreenTransform,symbolToRealTransform),box2),symbolToScreenScale=compose3(realToScreenTransform,symbolToRealTransform).a;svgObjects.push({name:"rect",type:"element",attributes:{x:screenBoxPos.x.toString(),y:screenBoxPos.y.toString(),width:(box2.width*symbolToScreenScale).toString(),height:(box2.height*symbolToScreenScale).toString(),fill:"red"},value:"",children:[]})}for(let circle2 of symbolCircles){let screenCirclePos=applyToPoint3(compose3(realToScreenTransform,symbolToRealTransform),circle2),symbolToScreenScale=compose3(realToScreenTransform,symbolToRealTransform).a;svgObjects.push({name:"circle",type:"element",attributes:{cx:screenCirclePos.x.toString(),cy:screenCirclePos.y.toString(),r:(circle2.radius*symbolToScreenScale).toString(),fill:"none",stroke:colorMap2.schematic.component_outline,"stroke-width":`${getSchStrokeSize(realToScreenTransform)}px`},value:"",children:[]})}return svgObjects},createSvgObjectsForSchNetLabel=({schNetLabel,realToScreenTransform,colorMap:colorMap2})=>{if(!schNetLabel.text)return[];let labelText=schNetLabel.text;if(schNetLabel.symbol_name)return createSvgObjectsForSchNetLabelWithSymbol({schNetLabel,realToScreenTransform,colorMap:colorMap2});let svgObjects=[],fontSizePx=getSchScreenFontSize(realToScreenTransform,"net_label"),fontSizeMm=getSchMmFontSize("net_label"),textWidthFSR=estimateTextWidth(labelText||""),screenCenter=applyToPoint3(realToScreenTransform,schNetLabel.center),realTextGrowthVec=getUnitVectorFromOutsideToEdge(schNetLabel.anchor_side),screenTextGrowthVec={...realTextGrowthVec};screenTextGrowthVec.y*=-1;let fullWidthFsr=textWidthFSR+ARROW_POINT_WIDTH_FSR*2+END_PADDING_EXTRA_PER_CHARACTER_FSR*labelText.length+END_PADDING_FSR,screenAnchorPosition=schNetLabel.anchor_position?applyToPoint3(realToScreenTransform,schNetLabel.anchor_position):{x:screenCenter.x-screenTextGrowthVec.x*fullWidthFsr*fontSizePx/2,y:screenCenter.y-screenTextGrowthVec.y*fullWidthFsr*fontSizePx/2},realAnchorPosition=schNetLabel.anchor_position??{x:schNetLabel.center.x-realTextGrowthVec.x*fullWidthFsr*fontSizeMm/2,y:schNetLabel.center.y-realTextGrowthVec.y*fullWidthFsr*fontSizeMm/2},pathRotation={left:0,top:-90,bottom:90,right:180}[schNetLabel.anchor_side],screenOutlinePoints=[{x:0,y:0},{x:ARROW_POINT_WIDTH_FSR,y:.6},{x:ARROW_POINT_WIDTH_FSR*2+END_PADDING_FSR+END_PADDING_EXTRA_PER_CHARACTER_FSR*labelText.length+textWidthFSR,y:.6},{x:ARROW_POINT_WIDTH_FSR*2+END_PADDING_FSR+END_PADDING_EXTRA_PER_CHARACTER_FSR*labelText.length+textWidthFSR,y:-.6},{x:ARROW_POINT_WIDTH_FSR,y:-.6}].map(fontRelativePoint=>applyToPoint3(compose3(realToScreenTransform,translate3(realAnchorPosition.x,realAnchorPosition.y),scale3(fontSizeMm),rotate3(pathRotation/180*Math.PI)),fontRelativePoint)),pathD=`
|
|
337
337
|
M ${screenOutlinePoints[0].x},${screenOutlinePoints[0].y}
|
|
338
338
|
L ${screenOutlinePoints[1].x},${screenOutlinePoints[1].y}
|
|
@@ -605,7 +605,7 @@ ${n4.width}x${n4.height}
|
|
|
605
605
|
`)})}return t5}},Da2=class extends y{constructor(t5){super();__publicField(this,"unsolvedRoutes");__publicField(this,"mergedHdRoutes",[]);__publicField(this,"colorMap",{});__publicField(this,"defaultTraceThickness");__publicField(this,"defaultViaDiameter");this.colorMap=t5.colorMap??{};let e4=t5.hdRoutes[0];this.defaultTraceThickness=e4?.traceThickness??.15,this.defaultViaDiameter=e4?.viaDiameter??t5.defaultViaDiameter??.6;let n3=new Map;for(let e5 of t5.connectionPathResults)n3.set(e5.connection.name,e5);let s2=new Map;for(let e5 of t5.hdRoutes){let t6=s2.get(e5.connectionName);t6?t6.push(e5):s2.set(e5.connectionName,[e5])}this.unsolvedRoutes=[];for(let[e5,o3]of s2.entries()){let s3=t5.connections.find(t6=>t6.name===e5);if(!s3)continue;let i2=n3.get(e5),r4=[];i2?.path&&(r4=i2.path.map(t6=>t6.currentNodeId));let a2={...s3.pointsToConnect[0],z:Xe2(Ue2(s3.pointsToConnect[0]),t5.layerCount)},c3={...s3.pointsToConnect[1],z:Xe2(Ue2(s3.pointsToConnect[1]),t5.layerCount)};this.unsolvedRoutes.push({connectionName:e5,hdRoutes:o3,nodeOrder:r4,start:a2,end:c3})}this.MAX_ITERATIONS=1e5}_step(){let t5=this.unsolvedRoutes.pop();if(!t5)return void(this.solved=!0);let e4=this.stitchOrderedRoutes(t5);this.mergedHdRoutes.push(e4)}stitchOrderedRoutes(t5){let{connectionName:e4,hdRoutes:n3,nodeOrder:s2,start:o3,end:i2}=t5;if(n3.length===0)return{connectionName:e4,traceThickness:this.defaultTraceThickness,viaDiameter:this.defaultViaDiameter,route:[o3,i2],vias:[],jumpers:[]};let r4;r4=s2.length>0?this.orderRoutesByNodePath(n3,s2,o3,e4):this.orderRoutesByProximity(n3,o3);let a2=[],c3=[],h4=[];a2.push({x:o3.x,y:o3.y,z:o3.z});for(let t6=0;t6<r4.length;t6++){let e5=r4[t6],n4=a2[a2.length-1],s3=e5.route[0],o4=e5.route[e5.route.length-1],i3=St2(n4,s3),d4=St2(n4,o4),l3=Math.min(i3,d4);if(t6>0&&l3>1)continue;let u4;u4=i3<=d4?[...e5.route]:[...e5.route].reverse(),u4.length>0&&St2(n4,u4[0])<.001&&(u4=u4.slice(1)),a2.push(...u4),c3.push(...e5.vias),e5.jumpers&&h4.push(...e5.jumpers)}let d3=St2(a2[a2.length-1],i2);return d3>.001&&d3<5&&a2.push({x:i2.x,y:i2.y,z:i2.z}),{connectionName:e4,rootConnectionName:n3[0]?.rootConnectionName,traceThickness:n3[0]?.traceThickness??this.defaultTraceThickness,viaDiameter:n3[0]?.viaDiameter??this.defaultViaDiameter,route:a2,vias:c3,jumpers:h4}}orderRoutesByNodePath(t5,e4,n3,s2){if(t5.length===0)return[];let o3=new Set(t5),i2=null,r4=1/0;for(let t6 of o3){let e5=t6.route[0],s3=t6.route[t6.route.length-1],o4=Math.min(St2(n3,e5),St2(n3,s3));o4<r4&&(r4=o4,i2=t6)}if(!i2)return[];o3.delete(i2);let a2=i2.route[0],c3=i2.route[i2.route.length-1],h4,d3;St2(n3,a2)<=St2(n3,c3)?(h4=a2,d3=c3):(h4=c3,d3=a2);let l3=(t6,e5)=>{let n4=0;for(let s3 of o3){if(s3===e5)continue;let o4=s3.route[0],i3=s3.route[s3.route.length-1];(St2(t6,o4)<10||St2(t6,i3)<10)&&n4++}return n4},u4=[i2],p4=d3;for(;o3.size>0;){let t6=null,e5=1/0,n4=-1;for(let s3 of o3){let o4=s3.route[0],i3=s3.route[s3.route.length-1],r5=St2(p4,o4),a3=St2(p4,i3),c4=Math.min(r5,a3);if(c4>=10)continue;let h6=l3(r5<=a3?i3:o4,s3),d4=h6===0,u5=n4===0,m4=c4-e5,f3=!1;f3=t6===null||!!(!d4&&u5&&m4<5)||!(d4&&!u5&&m4>-5)&&c4<e5,f3&&(e5=c4,t6=s3,n4=h6)}if(!t6)break;{u4.push(t6),o3.delete(t6);let e6=t6.route[0],n5=t6.route[t6.route.length-1];p4=St2(p4,e6)<=St2(p4,n5)?n5:e6}}let m3=[];for(p4=h4;o3.size>0;){let t6=null,e5=1/0,s3=-1,i3=St2(p4,n3);for(let r5 of o3){let o4=r5.route[0],a3=r5.route[r5.route.length-1],c4=St2(p4,o4),h6=St2(p4,a3),d4=Math.min(c4,h6);if(d4>=10)continue;let u5=c4<=h6?a3:o4;if(St2(u5,n3)>i3+2)continue;let m4=l3(u5,r5),f3=m4===0,g7=s3===0,y5=d4-e5,x5=!1;x5=t6===null||!!(!f3&&g7&&y5<5)||!(f3&&!g7&&y5>-5)&&d4<e5,x5&&(e5=d4,t6=r5,s3=m4)}if(!t6)break;{m3.unshift(t6),o3.delete(t6);let e6=t6.route[0],n4=t6.route[t6.route.length-1];p4=St2(p4,e6)<=St2(p4,n4)?n4:e6}}let f2=[...m3,...u4];if(o3.size>0){let e5=[...o3].map(t6=>{let e6=t6.route[0],n4=t6.route[t6.route.length-1];return`start=(${e6.x.toFixed(2)},${e6.y.toFixed(2)}) end=(${n4.x.toFixed(2)},${n4.y.toFixed(2)})`});console.warn(`[StitchSolver] Skipped ${o3.size} routes for connection ${t5[0]?.connectionName??"?"}, skipped routes: ${e5.join("; ")}`)}return f2}orderRoutesByProximity(t5,e4){let n3=new Set(t5),s2=[],o3=e4;for(;n3.size>0;){let t6=null,e5=1/0,i2=!1;for(let s3 of n3){let n4=s3.route[0],r4=s3.route[s3.route.length-1],a2=St2(o3,n4),c3=St2(o3,r4);a2<e5&&(e5=a2,t6=s3,i2=!1),c3<e5&&(e5=c3,t6=s3,i2=!0)}if(!t6)break;{s2.push(t6),n3.delete(t6);let e6=t6.route[0],r4=t6.route[t6.route.length-1];o3=i2?e6:r4}}return s2}visualize(){let t5={points:[],lines:[],circles:[],rects:[],title:"Multiple High Density Route Stitch Solver 2"};for(let[e4,n3]of this.mergedHdRoutes.entries()){let s2=this.colorMap[n3.connectionName]??`hsl(120, 100%, ${40+10*e4%40}%)`;for(let e5=0;e5<n3.route.length-1;e5++){let o3=n3.route[e5],i2=n3.route[e5+1],r4=o3.z!==0?it2(s2,.5):s2;t5.lines?.push({points:[{x:o3.x,y:o3.y},{x:i2.x,y:i2.y}],strokeColor:r4,strokeWidth:n3.traceThickness})}for(let e5 of n3.route){let n4=e5.z!==0?it2(s2,.5):s2;t5.points?.push({x:e5.x,y:e5.y,color:n4})}for(let e5 of n3.vias)t5.circles?.push({center:{x:e5.x,y:e5.y},radius:n3.viaDiameter/2,fill:s2});if(n3.jumpers&&n3.jumpers.length>0){let e5=Je2(n3.jumpers,{color:s2,label:n3.connectionName});t5.rects.push(...e5.rects??[]),t5.lines.push(...e5.lines??[])}}for(let e4 of this.unsolvedRoutes){let n3=this.colorMap[e4.connectionName]??"gray";t5.points?.push({x:e4.start.x,y:e4.start.y,color:n3,label:`${e4.connectionName} Start`},{x:e4.end.x,y:e4.end.y,color:n3,label:`${e4.connectionName} End`});for(let s2=0;s2<e4.hdRoutes.length;s2++){let o3=e4.hdRoutes[s2];if(o3.route.length>1&&t5.lines?.push({points:o3.route.map(t6=>({x:t6.x,y:t6.y})),strokeColor:it2(n3,.5),strokeDash:"10 5",label:`segment ${s2}`}),o3.jumpers&&o3.jumpers.length>0){let e5=Je2(o3.jumpers,{color:n3,label:o3.connectionName});t5.rects.push(...e5.rects??[]),t5.lines.push(...e5.lines??[])}}}return t5}};function La2(t5,e4,n3,s2={}){return{solverName:t5,solverClass:e4,getConstructorParams:n3,onSolved:s2.onSolved}}var Fa2=class extends y{constructor(t5,e4={}){super();__publicField(this,"netToPointPairsSolver");__publicField(this,"traceKeepoutSolver");__publicField(this,"nodeSolver");__publicField(this,"nodeTargetMerger");__publicField(this,"edgeSolver");__publicField(this,"relateNodesToOffBoardConnections");__publicField(this,"colorMap");__publicField(this,"highDensityRouteSolver");__publicField(this,"simpleHighDensityRouteSolver");__publicField(this,"highDensitySolver");__publicField(this,"highDensityStitchSolver");__publicField(this,"singleLayerNodeMerger");__publicField(this,"offboardPathFragmentSolver");__publicField(this,"strawSolver");__publicField(this,"deadEndSolver");__publicField(this,"traceSimplificationSolver");__publicField(this,"traceWidthSolver");__publicField(this,"availableSegmentPointSolver");__publicField(this,"portPointPathingSolver");__publicField(this,"multiSectionPortPointOptimizer");__publicField(this,"viaDiameter");__publicField(this,"minTraceWidth");__publicField(this,"effort");__publicField(this,"startTimeOfPhase");__publicField(this,"endTimeOfPhase");__publicField(this,"timeSpentOnPhase");__publicField(this,"activeSubSolver",null);__publicField(this,"connMap");__publicField(this,"srjWithPointPairs");__publicField(this,"capacityNodes",null);__publicField(this,"capacityEdges",null);__publicField(this,"cacheProvider",null);__publicField(this,"pipelineDef",[La2("netToPointPairsSolver",fn2,t5=>[t5.srj,t5.colorMap],{onSolved:t5=>{t5.srjWithPointPairs=t5.netToPointPairsSolver?.getNewSimpleRouteJson(),t5.colorMap=ot2(t5.srjWithPointPairs,this.connMap),t5.connMap=$e2(t5.srjWithPointPairs)}}),La2("nodeSolver",Js2,t5=>[{simpleRouteJson:t5.srjWithPointPairs}],{onSolved:t5=>{t5.capacityNodes=t5.nodeSolver?.getOutput().meshNodes??[]}}),La2("relateNodesToOffBoardConnections",vr2,t5=>[{capacityMeshNodes:t5.capacityNodes,srj:t5.srj}],{onSolved:t5=>{t5.capacityNodes=t5.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),La2("edgeSolver",cn2,t5=>[t5.capacityNodes],{onSolved:t5=>{t5.capacityEdges=t5.edgeSolver?.edges}}),La2("availableSegmentPointSolver",Io2,t5=>[{nodes:t5.capacityNodes,edges:t5.capacityEdges||[],traceWidth:t5.minTraceWidth,colorMap:t5.colorMap}]),La2("portPointPathingSolver",Zo2,t5=>{let e4=t5.capacityNodes.map(t6=>({capacityMeshNodeId:t6.capacityMeshNodeId,center:t6.center,width:t6.width,height:t6.height,portPoints:[],availableZ:t6.availableZ,_containsTarget:t6._containsTarget,_containsObstacle:t6._containsObstacle,_offBoardConnectionId:t6._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t6._offBoardConnectedCapacityMeshNodeIds})),n3=new Map(e4.map(t6=>[t6.capacityMeshNodeId,t6])),s2=t5.availableSegmentPointSolver;for(let t6 of s2.sharedEdgeSegments)for(let e5 of t6.portPoints){let[s3,o3]=e5.nodeIds,i2={portPointId:e5.segmentPortPointId,x:e5.x,y:e5.y,z:e5.availableZ[0]??0,connectionNodeIds:[s3,o3],distToCentermostPortOnZ:e5.distToCentermostPortOnZ,connectsToOffBoardNode:t6.nodeIds.some(t7=>n3.get(t7)?._offBoardConnectionId)},r4=n3.get(s3);r4&&r4.portPoints.push(i2)}return[{simpleRouteJson:t5.srjWithPointPairs,inputNodes:e4,capacityMeshNodes:t5.capacityNodes,colorMap:t5.colorMap,numShuffleSeeds:10*t5.effort,hyperParameters:{JUMPER_PF_FN_ENABLED:!0,NODE_PF_FACTOR:100,MAX_RIPS:100*t5.effort,RIPPING_ENABLED:!0,MAX_RIPPING_PF_THRESHOLD:.9,MIN_RIPPING_PF_THRESHOLD:.1,RANDOM_RIP_FRACTION:.05,NODE_PF_MAX_PENALTY:1e3,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:0,CENTER_OFFSET_DIST_PENALTY_FACTOR:0,FORCE_CENTER_FIRST:!0}}]},{onSolved:t5=>{let e4=t5.portPointPathingSolver;e4&&Sr2({connMap:t5.connMap,connectionsWithResults:e4.connectionsWithResults,inputNodes:e4.inputNodes,obstacles:t5.srj.obstacles})}}),La2("highDensitySolver",za2,t5=>[{nodePortPoints:t5.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t5.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t5.colorMap,viaDiameter:t5.viaDiameter,traceWidth:t5.minTraceWidth,connMap:t5.connMap,capacityMeshNodes:t5.capacityNodes??[],capacityMeshEdges:t5.capacityEdges??[]}]),La2("highDensityStitchSolver",Da2,t5=>[{connections:t5.srjWithPointPairs.connections,hdRoutes:t5.highDensitySolver.routes,connectionPathResults:t5.multiSectionPortPointOptimizer?.connectionResults??t5.portPointPathingSolver?.connectionsWithResults??[],colorMap:t5.colorMap,layerCount:t5.srj.layerCount,defaultViaDiameter:t5.viaDiameter}]),La2("traceKeepoutSolver",xr2,t5=>[{hdRoutes:t5.traceSimplificationSolver?.simplifiedHdRoutes??t5.highDensityStitchSolver?.mergedHdRoutes??[],obstacles:t5.srj.obstacles,jumpers:t5.highDensitySolver?.getOutputJumpers()??[],connMap:t5.connMap,colorMap:t5.colorMap,srj:t5.srj}])]);__publicField(this,"currentPipelineStepIndex",0);if(this.srj=t5,this.opts=e4,this.MAX_ITERATIONS=1e8,this.viaDiameter=t5.minViaDiameter??.6,this.minTraceWidth=t5.minTraceWidth,this.effort=e4.effort??1,e4.capacityDepth===void 0){let n3=t5.bounds.maxX-t5.bounds.minX,s2=t5.bounds.maxY-t5.bounds.minY,o3=Math.max(n3,s2),i2=e4.targetMinCapacity??.5;e4.capacityDepth=ke2(o3,i2)}this.connMap=$e2(t5),this.colorMap=ot2(t5,this.connMap),this.cacheProvider=e4.cacheProvider===void 0?ut2():e4.cacheProvider===null?null:e4.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getConstructorParams(){return[this.srj,this.opts]}_step(){let t5=this.pipelineDef[this.currentPipelineStepIndex];if(!t5)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t5.solverName]=performance.now(),this.timeSpentOnPhase[t5.solverName]=this.endTimeOfPhase[t5.solverName]-this.startTimeOfPhase[t5.solverName],t5.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));let e4=t5.getConstructorParams(this);this.activeSubSolver=new t5.solverClass(...e4),this[t5.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t5.solverName]=0,this.startTimeOfPhase[t5.solverName]=performance.now()}solveUntilPhase(t5){for(;this.getCurrentPhase()!==t5;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();let t5=this.netToPointPairsSolver?.visualize(),e4=this.nodeSolver?.visualize(),n3=this.nodeTargetMerger?.visualize(),s2=this.singleLayerNodeMerger?.visualize(),o3=this.strawSolver?.visualize(),i2=this.edgeSolver?.visualize(),r4=this.traceKeepoutSolver?.visualize(),a2=this.deadEndSolver?.visualize(),c3=this.availableSegmentPointSolver?.visualize(),h4=this.offboardPathFragmentSolver?.visualize(),d3=this.portPointPathingSolver?.visualize(),l3=this.multiSectionPortPointOptimizer?.visualize(),u4=this.highDensityRouteSolver?.visualize(),p4=this.highDensitySolver?.visualize(),m3=this.simpleHighDensityRouteSolver?.visualize(),f2=this.highDensityStitchSolver?.visualize(),y5=this.traceSimplificationSolver?.visualize(),x5=this.traceWidthSolver?.visualize(),v5=this.srj.outline,S3=[];if(S3.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),v5&&v5.length>=2){let t6=v5.map(t7=>({x:t7.x,y:t7.y}));t6.push({...t6[0]}),S3.push({points:t6,strokeColor:"rgba(0, 136, 255, 0.95)"})}let P5={points:[...this.srj.connections.flatMap(t6=>t6.pointsToConnect.map(e5=>({...e5,label:`${t6.name} ${e5.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t6=>({...t6,fill:t6.layers?.includes("top")?"rgba(255,0,0,0.25)":t6.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:["obstacle",t6.offBoardConnectsTo?`offboardConnections: ${t6.offBoardConnectsTo?.join(", ")}`:"",t6.layers?.join(", ")].filter(Boolean).join(`
|
|
606
606
|
`)}))],lines:S3},b3=[P5,t5,e4,n3,s2,o3,i2,a2,c3,h4,d3,l3,u4?g4(P5,u4):null,p4?g4(P5,p4):null,m3?g4(P5,m3):null,f2,y5,r4,x5,this.solved?g4(P5,sn2(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g4(...b3)}preview(){let t5=this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes;if(t5){let e4=[];for(let n3=t5.length-1;n3>=0;n3--){let s2=t5[n3];if(e4.push({points:s2.route.map(t6=>({x:t6.x,y:t6.y})),strokeColor:this.colorMap[s2.connectionName]}),e4.length>200)break}return{lines:e4}}if(this.portPointPathingSolver){let t6=[];for(let e4 of this.portPointPathingSolver.connectionsWithResults)e4.path&&t6.push({points:e4.path.map(t7=>({x:t7.point.x,y:t7.point.y})),strokeColor:this.colorMap[e4.connection.name]});return{lines:t6}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceWidthSolver?.hdRoutesWithWidths??this.traceKeepoutSolver?.redrawnHdRoutes??this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver?.mergedHdRoutes??this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes}getConnectedOffboardObstacles(){let t5={},e4=new Set(this.srj.connections.map(t6=>t6.rootConnectionName??t6.name));for(let[n3,s2]of this.srj.obstacles.entries()){if(!s2.offBoardConnectsTo?.length)continue;let o3=s2.obstacleId??`__obs${n3}`;s2.obstacleId=o3;let i2=this.connMap.getNetConnectedToId(o3);if(!i2)continue;let r4=this.connMap.getIdsConnectedToNet(i2).find(t6=>e4.has(t6));r4&&(t5[o3]=r4)}return t5}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver&&!this.simpleHighDensityRouteSolver&&!this.highDensitySolver)throw new Error("Cannot get output before solving is complete");let t5=[],e4=this._getOutputHdRoutes();for(let n3 of this.netToPointPairsSolver?.newConnections??[]){let s2=n3.netConnectionName??this.srj.connections.find(t6=>t6.name===n3.name)?.netConnectionName,o3=e4.filter(t6=>t6.connectionName===n3.name);for(let e5=0;e5<o3.length;e5++){let i2=o3[e5],r4={type:"pcb_trace",pcb_trace_id:`${n3.name}_${e5}`,connection_name:s2??n3.rootConnectionName??n3.name,route:We2(i2,this.srj.layerCount)};t5.push(r4)}}return t5}getOutputJumpers(){return this.highDensitySolver?this.highDensitySolver.getOutputJumpers():[]}getOutputSimpleRouteJson(){let t5=this.getOutputJumpers();return{...this.srj,traces:this.getOutputSimplifiedPcbTraces(),jumpers:t5.length>0?t5:void 0}}};var BaseSolver=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",{});__publicField(this,"_setupDone",!1)}setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(e4){throw this.error=`${this.constructor.name} error: ${e4}`,console.error(this.error),this.failed=!0,e4}!this.solved&&this.iterations>=this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>=this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){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:[]}}};var BasePipelineSolver=class extends BaseSolver{constructor(inputProblem){super();__publicField(this,"startTimeOfPhase",{});__publicField(this,"endTimeOfPhase",{});__publicField(this,"timeSpentOnPhase",{});__publicField(this,"firstIterationOfPhase",{});__publicField(this,"currentPipelineStepIndex",0);__publicField(this,"inputProblem");__publicField(this,"pipelineOutputs",{});this.inputProblem=inputProblem,this.MAX_ITERATIONS=1e6}_step(){let pipelineStepDef=this.pipelineDef[this.currentPipelineStepIndex];if(!pipelineStepDef){this.solved=!0;return}if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){this.endTimeOfPhase[pipelineStepDef.solverName]=performance.now(),this.timeSpentOnPhase[pipelineStepDef.solverName]=this.endTimeOfPhase[pipelineStepDef.solverName]-this.startTimeOfPhase[pipelineStepDef.solverName];let output=this.activeSubSolver.getOutput();output!==null&&(this.pipelineOutputs[pipelineStepDef.solverName]=output),pipelineStepDef.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++}else 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().toLowerCase()!==phase.toLowerCase()&&(this.step(),!(this.failed||this.solved)););}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}getPhaseProgress(){let totalPhases=this.pipelineDef.length;if(totalPhases===0)return 1;let currentPhaseProgress=this.activeSubSolver?.progress??0;return(this.currentPipelineStepIndex+currentPhaseProgress)/totalPhases}getPhaseStats(){let stats={};for(let step of this.pipelineDef){let timeSpent=this.timeSpentOnPhase[step.solverName]||0,firstIteration=this.firstIterationOfPhase[step.solverName]||0,currentIteration=this.iterations,iterations=step.solverName===this.getCurrentPhase()?currentIteration-firstIteration:0,completed=this.currentPipelineStepIndex>this.pipelineDef.findIndex(s2=>s2.solverName===step.solverName);stats[step.solverName]={timeSpent,iterations,completed}}return stats}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();let visualizations=this.pipelineDef.map((step,stepIndex)=>{let viz=this[step.solverName]?.visualize();if(!viz)return null;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}).filter(Boolean);return visualizations.length===0?{points:[],rects:[],lines:[],circles:[],texts:[]}:visualizations.length===1?visualizations[0]:{points:visualizations.flatMap(v5=>v5.points||[]),rects:visualizations.flatMap(v5=>v5.rects||[]),lines:visualizations.flatMap(v5=>v5.lines||[]),circles:visualizations.flatMap(v5=>v5.circles||[]),texts:visualizations.flatMap(v5=>v5.texts||[])}}preview(){return this.activeSubSolver?this.activeSubSolver.preview():super.preview()}computeProgress(){return this.getPhaseProgress()}getStepOutput(stepName){return this.pipelineOutputs[stepName]}getAllOutputs(){return{...this.pipelineOutputs}}hasStepOutput(stepName){return stepName in this.pipelineOutputs}getSolver(stepName){return this[stepName]}};init_dist6();var rotatePoint=(point6,angle,origin={x:0,y:0})=>{let cos4=Math.cos(angle),sin4=Math.sin(angle),dx2=point6.x-origin.x,dy2=point6.y-origin.y;return{x:origin.x+dx2*cos4-dy2*sin4,y:origin.y+dx2*sin4+dy2*cos4}},setPackedComponentPadCenters=packedComponent=>{packedComponent.pads=packedComponent.pads.map(pad2=>{let rotated=rotatePoint(pad2.offset,packedComponent.ccwRotationOffset*Math.PI/180),normalizedRotation=(packedComponent.ccwRotationOffset%360+360)%360;return{...pad2,size:normalizedRotation===90||normalizedRotation===270?{x:pad2.size.y,y:pad2.size.x}:pad2.size,absoluteCenter:{x:packedComponent.center.x+rotated.x,y:packedComponent.center.y+rotated.y}}})};function sortComponentQueue({components,packOrderStrategy,packFirst=[]}){let packFirstMap=new Map;return packFirst.forEach((componentId,index)=>{packFirstMap.set(componentId,index)}),[...components].sort((a2,b3)=>{let aPackFirstIndex=packFirstMap.get(a2.componentId),bPackFirstIndex=packFirstMap.get(b3.componentId);return aPackFirstIndex!==void 0&&bPackFirstIndex!==void 0?aPackFirstIndex-bPackFirstIndex:aPackFirstIndex!==void 0?-1:bPackFirstIndex!==void 0?1:packOrderStrategy==="largest_to_smallest"?b3.pads.length-a2.pads.length:a2.pads.length-b3.pads.length})}var combineBounds=bounds=>{let minX=Math.min(...bounds.map(b3=>b3.minX)),minY=Math.min(...bounds.map(b3=>b3.minY)),maxX=Math.max(...bounds.map(b3=>b3.maxX)),maxY=Math.max(...bounds.map(b3=>b3.maxY));return{minX,minY,maxX,maxY}},getComponentBounds=(component,minGap=0)=>{let bounds={minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0};return component.pads.forEach(pad2=>{let hw2=pad2.size.x/2,hh2=pad2.size.y/2;[{x:pad2.offset.x-hw2,y:pad2.offset.y-hh2},{x:pad2.offset.x+hw2,y:pad2.offset.y-hh2},{x:pad2.offset.x+hw2,y:pad2.offset.y+hh2},{x:pad2.offset.x-hw2,y:pad2.offset.y+hh2}].forEach(corner=>{let world=rotatePoint(corner,component.ccwRotationOffset*Math.PI/180),x5=world.x+component.center.x,y5=world.y+component.center.y;bounds.minX=Math.min(bounds.minX,x5),bounds.maxX=Math.max(bounds.maxX,x5),bounds.minY=Math.min(bounds.minY,y5),bounds.maxY=Math.max(bounds.maxY,y5)})}),{minX:bounds.minX-minGap,maxX:bounds.maxX+minGap,minY:bounds.minY-minGap,maxY:bounds.maxY+minGap}},cross=(O5,A4,B5)=>(A4.x-O5.x)*(B5.y-O5.y)-(A4.y-O5.y)*(B5.x-O5.x);function simplifyCollinearSegments(outline,tolerance=1e-10){if(outline.length<=1)return outline;let simplified=[],currentSegmentStart=outline[0][0],currentSegmentEnd=outline[0][1];for(let i2=1;i2<outline.length;i2++){let nextSegment=outline[i2],[nextStart,nextEnd]=nextSegment,connectionTolerance=1e-9;if(!(Math.abs(currentSegmentEnd.x-nextStart.x)<connectionTolerance&&Math.abs(currentSegmentEnd.y-nextStart.y)<connectionTolerance)){simplified.push([currentSegmentStart,currentSegmentEnd]),currentSegmentStart=nextStart,currentSegmentEnd=nextEnd;continue}let crossProduct=cross(currentSegmentStart,currentSegmentEnd,nextEnd),segLen1=Math.hypot(currentSegmentEnd.x-currentSegmentStart.x,currentSegmentEnd.y-currentSegmentStart.y),segLen2=Math.hypot(nextEnd.x-currentSegmentEnd.x,nextEnd.y-currentSegmentEnd.y),scaledTolerance=Math.max(tolerance,tolerance*segLen1*segLen2);Math.abs(crossProduct)<scaledTolerance||(simplified.push([currentSegmentStart,currentSegmentEnd]),currentSegmentStart=nextStart),currentSegmentEnd=nextEnd}if(outline.length>2){let firstSegment=simplified[0],lastSegmentCandidate=[currentSegmentStart,currentSegmentEnd];if(firstSegment&&simplified.length>0)if(Math.abs(currentSegmentEnd.x-firstSegment[0].x)<1e-9&&Math.abs(currentSegmentEnd.y-firstSegment[0].y)<1e-9){let crossProduct=cross(currentSegmentStart,currentSegmentEnd,firstSegment[1]),segLen1=Math.hypot(currentSegmentEnd.x-currentSegmentStart.x,currentSegmentEnd.y-currentSegmentStart.y),segLen2=Math.hypot(firstSegment[1].x-currentSegmentEnd.x,firstSegment[1].y-currentSegmentEnd.y),scaledTolerance=Math.max(tolerance,tolerance*segLen1*segLen2);Math.abs(crossProduct)<scaledTolerance?simplified[0]=[currentSegmentStart,firstSegment[1]]:simplified.push(lastSegmentCandidate)}else simplified.push(lastSegmentCandidate);else simplified.push(lastSegmentCandidate)}else simplified.push([currentSegmentStart,currentSegmentEnd]);return simplified}function signedArea(points){let area=0;for(let i2=0;i2<points.length;i2++){let j4=(i2+1)%points.length,pi3=points[i2],pj=points[j4];area+=pi3.x*pj.y,area-=pj.x*pi3.y}return area/2}function extractFacePoints(face){let points=[],edge=face.first;if(!edge)return points;do{let shp=edge.shape,ps3=shp.start??shp.ps;points.push({x:ps3.x,y:ps3.y}),edge=edge.next}while(edge!==face.first);return points}function parseFlattenPolygonLoops(polygon2){let obstacleFreeLoops=[],obstacleContainingLoops=[],faces=Array.from(polygon2.faces);for(let face of faces){let points=extractFacePoints(face);if(points.length<3)continue;let area=signedArea(points);area>0?obstacleFreeLoops.push(points):area<0&&obstacleContainingLoops.push(points)}return{obstacleFreeLoops,obstacleContainingLoops}}function pointsToSegments(points){let segments=[];for(let i2=0;i2<points.length;i2++){let p12=points[i2],p22=points[(i2+1)%points.length];segments.push([p12,p22])}return segments}function parseFlattenPolygonSegments(polygon2){let loops=parseFlattenPolygonLoops(polygon2);return{obstacleFreeLoops:loops.obstacleFreeLoops.map(pointsToSegments),obstacleContainingLoops:loops.obstacleContainingLoops.map(pointsToSegments)}}var createPadPolygons=(component,minGap)=>component.pads.map(pad2=>{let hw2=pad2.size.x/2+minGap,hh2=pad2.size.y/2+minGap,worldCorners=[{x:pad2.offset.x-hw2,y:pad2.offset.y-hh2},{x:pad2.offset.x+hw2,y:pad2.offset.y-hh2},{x:pad2.offset.x+hw2,y:pad2.offset.y+hh2},{x:pad2.offset.x-hw2,y:pad2.offset.y+hh2}].map(corner=>{let rotated=rotatePoint(corner,component.ccwRotationOffset*Math.PI/180);return{x:rotated.x+component.center.x,y:rotated.y+component.center.y}}),arr=worldCorners.map(({x:x5,y:y5})=>[x5,y5]),poly=new Flatten.Polygon(arr),xs3=worldCorners.map(p4=>p4.x),ys3=worldCorners.map(p4=>p4.y),bbox={minX:Math.min(...xs3),minY:Math.min(...ys3),maxX:Math.max(...xs3),maxY:Math.max(...ys3)};return{poly,bbox}}),createObstaclePolygons=(obstacles,minGap)=>obstacles.map(obs=>{let hw2=obs.width/2+minGap,hh2=obs.height/2+minGap,cx2=obs.absoluteCenter.x,cy2=obs.absoluteCenter.y,worldCorners=[{x:cx2-hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2+hh2},{x:cx2-hw2,y:cy2+hh2}],arr=worldCorners.map(({x:x5,y:y5})=>[x5,y5]),poly=new Flatten.Polygon(arr),xs3=worldCorners.map(p4=>p4.x),ys3=worldCorners.map(p4=>p4.y),bbox={minX:Math.min(...xs3),minY:Math.min(...ys3),maxX:Math.max(...xs3),maxY:Math.max(...ys3)};return{poly,bbox}}),constructOutlinesFromPackedComponents=(components,opts={})=>{let{minGap=0,obstacles=[]}=opts;if(components.length===0&&obstacles.length===0)return[];let componentBounds=components.map(c3=>getComponentBounds(c3,minGap)),obstacleBounds=obstacles.map(o3=>({minX:o3.absoluteCenter.x-o3.width/2-minGap,minY:o3.absoluteCenter.y-o3.height/2-minGap,maxX:o3.absoluteCenter.x+o3.width/2+minGap,maxY:o3.absoluteCenter.y+o3.height/2+minGap})),bounds=combineBounds([...componentBounds,...obstacleBounds]),allPadShapes=[];for(let component of components){let padShapes=createPadPolygons(component,minGap);allPadShapes.push(...padShapes)}let obstacleShapes=createObstaclePolygons(obstacles,minGap);if(allPadShapes.push(...obstacleShapes),allPadShapes.length===0)return[];let keptPadPolys=filterPadShapes(allPadShapes).map(s2=>s2.poly),A4=new Flatten.Polygon(new Flatten.Box(bounds.minX,bounds.minY,bounds.maxX,bounds.maxY)),B5=A4.clone();for(let poly of keptPadPolys)try{A4=Flatten.BooleanOperations.subtract(A4,poly)}catch{}let union2=null;try{union2=Flatten.BooleanOperations.subtract(B5,A4)}catch{try{if(keptPadPolys.length>0){let U4=keptPadPolys[0];for(let i2=1;i2<keptPadPolys.length;i2++)try{U4=Flatten.BooleanOperations.unify(U4,keptPadPolys[i2])}catch{}union2=U4}}catch{union2=null}}if(!union2)return[];let parsed=parseFlattenPolygonSegments(union2);return[...parsed.obstacleFreeLoops.map(outline=>simplifyCollinearSegments(outline)),...parsed.obstacleContainingLoops.map(outline=>simplifyCollinearSegments(outline))].filter(outline=>outline.length>=3)};function filterPadShapes(allPadShapes){let areaOfBox=b3=>Math.max(0,b3.maxX-b3.minX)*Math.max(0,b3.maxY-b3.minY),containsBox=(outer,inner,eps=1e-9)=>outer.minX-eps<=inner.minX&&outer.minY-eps<=inner.minY&&outer.maxX+eps>=inner.maxX&&outer.maxY+eps>=inner.maxY,sortedByAreaDesc=[...allPadShapes].sort((a2,b3)=>areaOfBox(b3.bbox)-areaOfBox(a2.bbox)),filtered=[];for(let shape of sortedByAreaDesc){let w4=shape.bbox.maxX-shape.bbox.minX,h4=shape.bbox.maxY-shape.bbox.minY;if(!(w4>1e-12&&h4>1e-12))continue;let contained=!1;for(let kept of filtered)if(containsBox(kept.bbox,shape.bbox)){contained=!0;break}contained||filtered.push(shape)}return filtered}var makeNumbersRounded=obj=>typeof obj=="number"?Math.round(obj*100)/100:typeof obj=="object"?Object.fromEntries(Object.entries(obj).map(([key,value])=>[key,makeNumbersRounded(value)])):obj,BaseSolver2=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",{});__publicField(this,"_setupDone",!1)}setup(){this._setupDone||(this._setup(),this._setupDone=!0)}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(e4){throw this.error=`${this.constructor.name} error: ${e4}`,console.error(this.error),this.failed=!0,e4}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_setup(){}_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(){}getOutput(){return null}preview(){return{lines:[],points:[],rects:[],circles:[]}}noisySolve(){let startTime=Date.now();for(;!this.solved&&!this.failed;)this.step(),console.log(JSON.stringify(makeNumbersRounded(this.visualize())));let endTime=Date.now();this.timeToSolve=endTime-startTime}},MultiOffsetIrlsSolver=class extends BaseSolver2{constructor(params){super();__publicField(this,"offsetPadPoints");__publicField(this,"targetPointMap");__publicField(this,"currentPosition");__publicField(this,"constraintFn");__publicField(this,"epsilon");__publicField(this,"useSquaredDistance");__publicField(this,"optimalPosition");__publicField(this,"initialPosition");this.offsetPadPoints=[...params.offsetPadPoints],this.targetPointMap=new Map(params.targetPointMap),this.initialPosition={...params.initialPosition},this.currentPosition={...params.initialPosition},this.constraintFn=params.constraintFn,this.epsilon=params.epsilon??1e-6,this.useSquaredDistance=params.useSquaredDistance??!1,this.MAX_ITERATIONS=params.maxIterations??100}getConstructorParams(){return{offsetPadPoints:this.offsetPadPoints.map(pad2=>({...pad2})),targetPointMap:new Map(this.targetPointMap),initialPosition:this.initialPosition,constraintFn:this.constraintFn,epsilon:this.epsilon,useSquaredDistance:this.useSquaredDistance,maxIterations:this.MAX_ITERATIONS}}_setup(){this.currentPosition={...this.initialPosition},this.optimalPosition=void 0,(!Array.from(this.targetPointMap.values()).some(targets=>targets.length>0)||this.offsetPadPoints.length===0)&&(this.optimalPosition={...this.currentPosition},this.solved=!0)}_step(){if(this.offsetPadPoints.length===0)return;let{x:currentX,y:currentY}=this.currentPosition,weightedSumX=0,weightedSumY=0,totalWeight=0;for(let pad2 of this.offsetPadPoints){let targetPoints=this.targetPointMap.get(pad2.id)||[];if(targetPoints.length===0)continue;let padX=currentX+pad2.offsetX,padY=currentY+pad2.offsetY;for(let targetPoint of targetPoints){let dx22=padX-targetPoint.x,dy22=padY-targetPoint.y,distance8=Math.sqrt(dx22*dx22+dy22*dy22),weight;this.useSquaredDistance?weight=1:weight=distance8<this.epsilon?1e6:1/distance8;let targetForCurrentPos={x:targetPoint.x-pad2.offsetX,y:targetPoint.y-pad2.offsetY};weightedSumX+=weight*targetForCurrentPos.x,weightedSumY+=weight*targetForCurrentPos.y,totalWeight+=weight}}let newPosition={x:totalWeight>0?weightedSumX/totalWeight:currentX,y:totalWeight>0?weightedSumY/totalWeight:currentY},constrainedPosition=this.constraintFn?this.constraintFn(newPosition):newPosition,dx2=constrainedPosition.x-currentX,dy2=constrainedPosition.y-currentY;if(Math.sqrt(dx2*dx2+dy2*dy2)<this.epsilon){this.optimalPosition={...constrainedPosition},this.solved=!0;return}this.currentPosition=constrainedPosition}getBestPosition(){return this.optimalPosition||this.currentPosition}getOffsetPadPositions(){let currentPos=this.getBestPosition(),padPositions=new Map;for(let pad2 of this.offsetPadPoints)padPositions.set(pad2.id,{x:currentPos.x+pad2.offsetX,y:currentPos.y+pad2.offsetY});return padPositions}getOffsetPadPosition(padId){return this.getOffsetPadPositions().get(padId)}getTotalDistance(position2){let pos=position2||this.getBestPosition(),totalDistance=0;for(let pad2 of this.offsetPadPoints){let padPosition={x:pos.x+pad2.offsetX,y:pos.y+pad2.offsetY},targetPoints=this.targetPointMap.get(pad2.id)||[];for(let target of targetPoints){let dx2=padPosition.x-target.x,dy2=padPosition.y-target.y;this.useSquaredDistance?totalDistance+=dx2*dx2+dy2*dy2:totalDistance+=Math.sqrt(dx2*dx2+dy2*dy2)}}return totalDistance}getDistanceForPad(padId,position2){let pos=position2||this.getBestPosition(),pad2=this.offsetPadPoints.find(p4=>p4.id===padId);if(!pad2)return 0;let padPosition={x:pos.x+pad2.offsetX,y:pos.y+pad2.offsetY};return(this.targetPointMap.get(padId)||[]).reduce((sum,target)=>{let dx2=padPosition.x-target.x,dy2=padPosition.y-target.y;return this.useSquaredDistance?sum+(dx2*dx2+dy2*dy2):sum+Math.sqrt(dx2*dx2+dy2*dy2)},0)}computeProgress(){if(this.offsetPadPoints.length===0)return 1;let initialDistance=this.getTotalDistance(this.initialPosition),currentDistance=this.getTotalDistance();if(initialDistance===0)return 1;let improvement=Math.max(0,initialDistance-currentDistance);return Math.min(1,improvement/initialDistance)}visualize(){let graphics={lines:[],points:[],rects:[],circles:[]},colors=["#4CAF50","#2196F3","#FF9800","#9C27B0","#F44336","#607D8B"],currentPos=this.getBestPosition();for(let i2=0;i2<this.offsetPadPoints.length;i2++){let pad2=this.offsetPadPoints[i2];if(!pad2)continue;let color=colors[i2%colors.length],targetPoints=this.targetPointMap.get(pad2.id)||[],padPosition={x:currentPos.x+pad2.offsetX,y:currentPos.y+pad2.offsetY};for(let point6 of targetPoints)graphics.points.push({...point6,color});for(let point6 of targetPoints)graphics.lines.push({points:[padPosition,point6],strokeColor:color});graphics.points.push({x:padPosition.x,y:padPosition.y,color})}return graphics.points.push({...this.currentPosition,color:"#f44336"}),this.optimalPosition&&graphics.points.push({...this.optimalPosition,color:"rgba(76, 175, 80, 0.3)"}),graphics}getOutput(){return this.optimalPosition??this.currentPosition}},TwoPhaseIrlsSolver=class extends BaseSolver2{constructor(params){super();__publicField(this,"offsetPadPoints");__publicField(this,"targetPointMap");__publicField(this,"constraintFn");__publicField(this,"currentPosition");__publicField(this,"optimalPosition");__publicField(this,"initialPosition");__publicField(this,"phase1Epsilon");__publicField(this,"phase2Epsilon");__publicField(this,"maxIterations");__publicField(this,"phase1Solver");__publicField(this,"phase2Solver");__publicField(this,"currentPhase",1);__publicField(this,"phase1Position");__publicField(this,"closestTargetPadId");__publicField(this,"closestTargetPoint");this.offsetPadPoints=[...params.offsetPadPoints],this.targetPointMap=new Map(params.targetPointMap),this.initialPosition={...params.initialPosition},this.currentPosition={...params.initialPosition},this.constraintFn=params.constraintFn,this.phase1Epsilon=params.phase1Epsilon??params.epsilon??1e-6,this.phase2Epsilon=params.phase2Epsilon??params.epsilon??1e-6,this.maxIterations=params.maxIterations??100}getConstructorParams(){return{offsetPadPoints:this.offsetPadPoints.map(pad2=>({...pad2})),targetPointMap:new Map(this.targetPointMap),initialPosition:this.initialPosition,constraintFn:this.constraintFn,phase1Epsilon:this.phase1Epsilon,phase2Epsilon:this.phase2Epsilon,maxIterations:this.maxIterations}}_setup(){if(this.currentPosition={...this.initialPosition},this.optimalPosition=void 0,this.currentPhase=1,this.phase1Position=void 0,this.closestTargetPadId=void 0,this.closestTargetPoint=void 0,!Array.from(this.targetPointMap.values()).some(targets=>targets.length>0)||this.offsetPadPoints.length===0){this.optimalPosition={...this.currentPosition},this.solved=!0;return}this.phase1Solver=new MultiOffsetIrlsSolver({offsetPadPoints:this.offsetPadPoints,targetPointMap:this.targetPointMap,initialPosition:this.initialPosition,constraintFn:this.constraintFn,epsilon:this.phase1Epsilon,maxIterations:this.maxIterations,useSquaredDistance:!0}),this.phase1Solver.setup()}_step(){this.currentPhase===1?this.stepPhase1():this.stepPhase2()}stepPhase1(){this.phase1Solver&&(this.phase1Solver.step(),this.currentPosition=this.phase1Solver.getBestPosition(),this.phase1Solver.solved?(this.phase1Position=this.phase1Solver.getBestPosition(),this.setupPhase2()):this.phase1Solver.failed&&(this.failed=!0,this.error=`Phase 1 failed: ${this.phase1Solver.error}`))}setupPhase2(){if(!this.phase1Position)return;let minDistance=1/0,closestPadId,closestTarget;for(let pad2 of this.offsetPadPoints){let targetPoints=this.targetPointMap.get(pad2.id)||[];if(targetPoints.length===0)continue;let padX=this.phase1Position.x+pad2.offsetX,padY=this.phase1Position.y+pad2.offsetY;for(let targetPoint of targetPoints){let dx2=padX-targetPoint.x,dy2=padY-targetPoint.y,distance8=Math.sqrt(dx2*dx2+dy2*dy2);distance8<minDistance&&(minDistance=distance8,closestPadId=pad2.id,closestTarget=targetPoint)}}if(this.closestTargetPadId=closestPadId,this.closestTargetPoint=closestTarget,!closestPadId||!closestTarget){this.optimalPosition=this.phase1Position,this.solved=!0;return}let phase2TargetMap=new Map;phase2TargetMap.set(closestPadId,[closestTarget]),this.phase2Solver=new MultiOffsetIrlsSolver({offsetPadPoints:this.offsetPadPoints,targetPointMap:phase2TargetMap,initialPosition:this.phase1Position,constraintFn:this.constraintFn,epsilon:this.phase2Epsilon,maxIterations:this.maxIterations,useSquaredDistance:!1}),this.phase2Solver.setup(),this.currentPhase=2}stepPhase2(){this.phase2Solver&&(this.phase2Solver.step(),this.currentPosition=this.phase2Solver.getBestPosition(),this.phase2Solver.solved?(this.optimalPosition=this.phase2Solver.getBestPosition(),this.solved=!0):this.phase2Solver.failed&&(this.failed=!0,this.error=`Phase 2 failed: ${this.phase2Solver.error}`))}getBestPosition(){return this.optimalPosition||this.currentPosition}getOffsetPadPositions(){let currentPos=this.getBestPosition(),padPositions=new Map;for(let pad2 of this.offsetPadPoints)padPositions.set(pad2.id,{x:currentPos.x+pad2.offsetX,y:currentPos.y+pad2.offsetY});return padPositions}getTotalDistance(position2){let pos=position2||this.getBestPosition(),totalDistance=0;for(let pad2 of this.offsetPadPoints){let padPosition={x:pos.x+pad2.offsetX,y:pos.y+pad2.offsetY},targetPoints=this.targetPointMap.get(pad2.id)||[];for(let target of targetPoints){let dx2=padPosition.x-target.x,dy2=padPosition.y-target.y;totalDistance+=dx2*dx2+dy2*dy2}}return totalDistance}visualize(){let graphics={lines:[],points:[],rects:[],circles:[]};if(graphics.points.push({...this.currentPosition,color:this.currentPhase===1?"#FF6B6B":"#4ECDC4",label:`Phase ${this.currentPhase}`}),this.phase1Position&&this.currentPhase===2&&graphics.points.push({...this.phase1Position,color:"rgba(255, 107, 107, 0.5)",label:"Phase 1 result"}),this.closestTargetPoint&&this.closestTargetPadId){graphics.points.push({...this.closestTargetPoint,color:"#FFA500",label:`Closest target (${this.closestTargetPadId})`});let closestPad=this.offsetPadPoints.find(p4=>p4.id===this.closestTargetPadId);if(closestPad){let currentPos=this.getBestPosition(),padPos={x:currentPos.x+closestPad.offsetX,y:currentPos.y+closestPad.offsetY};graphics.lines.push({points:[padPos,this.closestTargetPoint],strokeColor:"#FFA500"})}}let activeSolver=this.currentPhase===1?this.phase1Solver:this.phase2Solver;if(activeSolver){let solverViz=activeSolver.visualize(),phaseColor=this.currentPhase===1?"rgba(255, 107, 107, 0.7)":"rgba(76, 205, 196, 0.7)";if(solverViz.lines){let modifiedLines=solverViz.lines.map(line2=>({...line2,strokeColor:phaseColor}));graphics.lines.push(...modifiedLines)}solverViz.points&&graphics.points.push(...solverViz.points),solverViz.rects&&graphics.rects.push(...solverViz.rects),solverViz.circles&&graphics.circles.push(...solverViz.circles)}return this.optimalPosition&&graphics.points.push({...this.optimalPosition,color:"rgba(76, 175, 80, 0.8)",label:"Final optimal position"}),graphics}getOutput(){return this.optimalPosition??this.currentPosition}};function isStrongConnection(pad1Id,pad2Id,weightedConnections){return!weightedConnections||weightedConnections.length===0?!0:weightedConnections.some(wc2=>wc2.padIds.includes(pad1Id)&&wc2.padIds.includes(pad2Id))}var createColorMapFromStrings=strings=>{let colorMap2={};for(let i2=0;i2<strings.length;i2++)colorMap2[strings[i2]]=`hsl(${i2*300/strings.length}, 100%, 50%)`;return colorMap2},getColorForString=(string,alpha=1)=>`hsl(${string.split("").reduce((acc,char)=>acc*31+char.charCodeAt(0),0)%360}, 100%, 50%, ${alpha})`;function getOutwardNormal(outlineSegment,ccwFullOutline){let[p12,p22]=outlineSegment,dx2=p22.x-p12.x,dy2=p22.y-p12.y,len=Math.hypot(dx2,dy2);if(len===0)return{x:0,y:1};let dirX=dx2/len,dirY=dy2/len,left={x:-dirY,y:dirX},right={x:dirY,y:-dirX},verts=[];if(ccwFullOutline.length>0){verts.push(ccwFullOutline[0][0]);for(let seg of ccwFullOutline)verts.push(seg[1])}let signedArea2=(()=>{let a2=0;for(let i2=0;i2<verts.length;i2++){let v12=verts[i2],v22=verts[(i2+1)%verts.length];a2+=v12.x*v22.y-v22.x*v12.y}return a2/2})(),geometricOutward=signedArea2>0?right:left;return signedArea2<0?{x:-geometricOutward.x,y:-geometricOutward.y}:geometricOutward}var LargestRectOutsideOutlineFromPointSolver=class extends BaseSolver{constructor(params){super();__publicField(this,"ccwFullOutline");__publicField(this,"origin");__publicField(this,"globalBounds");__publicField(this,"largestRect",null);__publicField(this,"mode");this.ccwFullOutline=params.ccwFullOutline,this.origin=params.origin,this.globalBounds=params.globalBounds,this.mode=params.mode??"outside"}getConstructorParams(){return{ccwFullOutline:this.ccwFullOutline,origin:this.origin,globalBounds:this.globalBounds,mode:this.mode}}_setup(){}_step(){this.largestRect=this.computeLargestRect(),this.solved=!0}computeLargestRect(){let edges=this.makeEdges(this.ccwFullOutline),bounds={x:this.globalBounds.minX,y:this.globalBounds.minY,w:this.globalBounds.maxX-this.globalBounds.minX,h:this.globalBounds.maxY-this.globalBounds.minY};return this.largestRectContainingPointRegion(edges,this.origin,bounds,this.mode)}almostEqual(a2,b3,eps=1e-9){return Math.abs(a2-b3)<=eps}makeEdges(poly){let edges=[];for(let i2=0;i2<poly.length;i2++){let a2=poly[i2],b3=poly[(i2+1)%poly.length];!a2||!b3||this.almostEqual(a2.x,b3.x)&&this.almostEqual(a2.y,b3.y)||edges.push([a2,b3])}return edges}isVertical(e4){return this.almostEqual(e4[0].x,e4[1].x)}isHorizontal(e4){return this.almostEqual(e4[0].y,e4[1].y)}scanlineIntervalsAtY(edges,y02){let xs3=[];for(let e4 of edges){if(!this.isVertical(e4))continue;let y12=e4[0].y,y22=e4[1].y,x5=e4[0].x,ymin=Math.min(y12,y22),ymax=Math.max(y12,y22);ymin<=y02&&y02<ymax&&xs3.push(x5)}xs3.sort((a2,b3)=>a2-b3);let intervals=[];for(let i2=0;i2+1<xs3.length;i2+=2){let x12=xs3[i2],x22=xs3[i2+1];x12!==void 0&&x22!==void 0&&intervals.push([x12,x22])}return intervals}clipIntervals(intervals,a2,b3){let out=[];for(let[L4,R5]of intervals){let l3=Math.max(a2,L4),r4=Math.min(b3,R5);r4>l3&&out.push([l3,r4])}return out}regionIntervalsAtY(edges,y02,bx1,bx2,mode){let inside2=this.clipIntervals(this.scanlineIntervalsAtY(edges,y02),bx1,bx2);if(mode==="inside")return inside2;let outs=[],prev=bx1;for(let[L4,R5]of inside2)L4>prev&&outs.push([prev,L4]),prev=Math.max(prev,R5);return prev<bx2&&outs.push([prev,bx2]),outs}largestRectContainingPointRegion(edges,p4,bounds,mode){let BX1=bounds.x,BX2=bounds.x+bounds.w,BY1=bounds.y,BY2=bounds.y+bounds.h,interval=this.regionIntervalsAtY(edges,p4.y,BX1,BX2,mode).find(([xL,xR])=>xL-1e-9<=p4.x&&p4.x<=xR+1e-9);if(!interval)return null;let[X_L,X_R]=interval,xset=new Set([X_L,X_R]);for(let e4 of edges){if(!this.isVertical(e4))continue;let x5=e4[0].x;X_L<x5&&x5<X_R&&xset.add(x5)}let xs3=Array.from(xset).sort((a2,b3)=>a2-b3),m3=xs3.length-1;if(m3<=0)return null;let top=Array(m3).fill(-1/0),bot=Array(m3).fill(1/0);for(let i2=0;i2<m3;i2++){let xi3=xs3[i2],xi1=xs3[i2+1];if(xi3===void 0||xi1===void 0)continue;let xm2=.5*(xi3+xi1);xset.has(xm2)&&(xm2+=1e-6);let minAbove=BY2,maxBelow=BY1;for(let e4 of edges){if(!this.isHorizontal(e4))continue;let y5=e4[0].y,x12=Math.min(e4[0].x,e4[1].x),x22=Math.max(e4[0].x,e4[1].x);x12-1e-9<=xm2&&xm2<=x22+1e-9&&(y5>p4.y&&(minAbove=Math.min(minAbove,y5)),y5<p4.y&&(maxBelow=Math.max(maxBelow,y5)))}maxBelow<minAbove?(top[i2]=minAbove,bot[i2]=maxBelow):(top[i2]=-1/0,bot[i2]=1/0)}let s02=-1;for(let i2=0;i2<m3;i2++){let xi3=xs3[i2],xi1=xs3[i2+1];if(!(xi3===void 0||xi1===void 0)&&xi3-1e-9<=p4.x&&p4.x<=xi1+1e-9){s02=i2;break}}if(s02===-1)return null;let best=null,bestArea=-1;for(let i2=0;i2<=s02;i2++){let minTop=1/0,maxBot=-1/0;for(let j4=i2;j4<m3;j4++){let topJ=top[j4],botJ=bot[j4];if(topJ===void 0||botJ===void 0||(minTop=Math.min(minTop,topJ),maxBot=Math.max(maxBot,botJ),j4<s02))continue;let height=Math.max(0,minTop-maxBot);if(height<=0)continue;let xi3=xs3[i2],xj1=xs3[j4+1];if(xi3===void 0||xj1===void 0)continue;let width=xj1-xi3,area=width*height;area>bestArea&&(bestArea=area,best={x:xi3,y:maxBot,w:width,h:height})}}return best}getLargestRect(){return this.solved||this.solve(),this.largestRect}getLargestRectBounds(){return this.solved||this.solve(),this.largestRect?{minX:this.largestRect.x,minY:this.largestRect.y,maxX:this.largestRect.x+this.largestRect.w,maxY:this.largestRect.y+this.largestRect.h}:{minX:0,minY:0,maxX:0,maxY:0}}visualize(){let graphics={lines:[],points:[],rects:[],circles:[]};for(let i2=0;i2<this.ccwFullOutline.length;i2++){let p12=this.ccwFullOutline[i2],p22=this.ccwFullOutline[(i2+1)%this.ccwFullOutline.length];p12&&p22&&graphics.lines.push({points:[p12,p22],strokeColor:"rgba(0,0,0,0.5)"})}return graphics.lines.push({points:[...this.ccwFullOutline,this.ccwFullOutline[0]],strokeColor:"rgba(200, 200, 200, 0.5)",strokeDash:[10,5]}),graphics.circles.push({center:this.origin,radius:.05,fill:"#f44336",label:"Origin"}),this.largestRect&&graphics.rects.push({center:{x:this.largestRect.x+this.largestRect.w/2,y:this.largestRect.y+this.largestRect.h/2},width:this.largestRect.w,height:this.largestRect.h,fill:"rgba(0, 255, 0, 0.3)",stroke:"#4CAF50",label:`Largest Rectangle (Area: ${(this.largestRect.w*this.largestRect.h).toFixed(3)})`}),graphics}getOutput(){return this.largestRect??null}},getInputComponentBounds=(component,{rotationDegrees=0})=>{let bounds={minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0};for(let pad2 of component.pads){let hw2=pad2.size.x/2,hh2=pad2.size.y/2,localCorners=[{x:pad2.offset.x-hw2,y:pad2.offset.y-hh2},{x:pad2.offset.x+hw2,y:pad2.offset.y-hh2},{x:pad2.offset.x+hw2,y:pad2.offset.y+hh2},{x:pad2.offset.x-hw2,y:pad2.offset.y+hh2}];for(let corner of localCorners){let world=rotatePoint(corner,rotationDegrees*Math.PI/180),x5=world.x,y5=world.y;bounds.minX=Math.min(bounds.minX,x5),bounds.maxX=Math.max(bounds.maxX,x5),bounds.minY=Math.min(bounds.minY,y5),bounds.maxY=Math.max(bounds.maxY,y5)}}return{minX:bounds.minX,maxX:bounds.maxX,minY:bounds.minY,maxY:bounds.maxY}},expandSegment=(segment2,amount)=>{let[p12,p22]=segment2,direction2={x:p22.x-p12.x,y:p22.y-p12.y},normalizedDirection=normalizeVector(direction2);return[{x:p12.x-normalizedDirection.x*amount,y:p12.y-normalizedDirection.y*amount},{x:p22.x+normalizedDirection.x*amount,y:p22.y+normalizedDirection.y*amount}]};function normalizeVector(direction2){let length3=Math.hypot(direction2.x,direction2.y);return{x:direction2.x/length3,y:direction2.y/length3}}function isPointInPolygon(point6,polygon2){if(polygon2.length<3)return!1;let inside2=!1,n3=polygon2.length,poly=[...polygon2];(poly[0].x!==poly[n3-1].x||poly[0].y!==poly[n3-1].y)&&poly.push({...poly[0]});for(let i2=0,j4=poly.length-1;i2<poly.length;j4=i2++){let xi3=poly[i2].x,yi3=poly[i2].y,xj=poly[j4].x,yj=poly[j4].y;yi3>point6.y!=yj>point6.y&&point6.x<(xj-xi3)*(point6.y-yi3)/(yj-yi3)+xi3&&(inside2=!inside2)}return inside2}var OutlineSegmentCandidatePointSolver=class extends BaseSolver{constructor(params){super();__publicField(this,"outlineSegment");__publicField(this,"viableOutlineSegment",null);__publicField(this,"ccwFullOutline");__publicField(this,"componentRotationDegrees");__publicField(this,"packStrategy");__publicField(this,"minGap");__publicField(this,"obstacles");__publicField(this,"packedComponents");__publicField(this,"componentToPack");__publicField(this,"viableBounds");__publicField(this,"globalBounds");__publicField(this,"boundaryOutline");__publicField(this,"weightedConnections");__publicField(this,"optimalPosition");__publicField(this,"irlsSolver");__publicField(this,"twoPhaseIrlsSolver");__publicField(this,"largestRectBounds");__publicField(this,"largestRectMidPoint");__publicField(this,"largestRectOrigin");this.outlineSegment=params.outlineSegment,this.ccwFullOutline=params.ccwFullOutline,this.componentRotationDegrees=params.componentRotationDegrees,this.packStrategy=params.packStrategy,this.minGap=params.minGap,this.packedComponents=params.packedComponents,this.componentToPack=params.componentToPack,this.obstacles=params.obstacles??[],this.globalBounds=params.globalBounds,this.boundaryOutline=params.boundaryOutline,this.weightedConnections=params.weightedConnections}getConstructorParams(){return{outlineSegment:this.outlineSegment,ccwFullOutline:this.ccwFullOutline,componentRotationDegrees:this.componentRotationDegrees,packStrategy:this.packStrategy,minGap:this.minGap,packedComponents:this.packedComponents,componentToPack:this.componentToPack,obstacles:this.obstacles,globalBounds:this.globalBounds,boundaryOutline:this.boundaryOutline,weightedConnections:this.weightedConnections}}_getOutlineBoundsWithMargin(params={}){let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let[p12,p22]of this.ccwFullOutline)minX=Math.min(minX,p12.x,p22.x),minY=Math.min(minY,p12.y,p22.y),maxX=Math.max(maxX,p12.x,p22.x),maxY=Math.max(maxY,p12.y,p22.y);let margin=params.margin??0;return{minX:minX-margin,minY:minY-margin,maxX:maxX+margin,maxY:maxY+margin}}_setup(){let{offsetPadPoints,targetPointMap}=this.getNetworkTargetPointMappings(),[p12,p22]=this.outlineSegment,constraintFn=point6=>{let projectedPoint=this.projectPointOntoSegment(point6,this.viableOutlineSegment);return this.adjustPositionForOutlineCollision(projectedPoint)},outwardNormal=getOutwardNormal(this.outlineSegment,this.ccwFullOutline),componentBounds=getInputComponentBounds(this.componentToPack,{rotationDegrees:this.componentRotationDegrees}),packedComponentBoundsWithMargin=this._getOutlineBoundsWithMargin({margin:Math.max(componentBounds.maxX-componentBounds.minX,componentBounds.maxY-componentBounds.minY)*2+this.minGap*2});this.largestRectMidPoint={x:(p12.x+p22.x)/2,y:(p12.y+p22.y)/2},this.largestRectOrigin={x:this.largestRectMidPoint.x+outwardNormal.x*1e-4,y:this.largestRectMidPoint.y+outwardNormal.y*1e-4};let outlinePoints=this.ccwFullOutline.flatMap(([p4])=>p4),signedArea2=0;for(let i2=0;i2<outlinePoints.length;i2++){let p122=outlinePoints[i2],p222=outlinePoints[(i2+1)%outlinePoints.length];signedArea2+=p122.x*p222.y-p222.x*p122.y}signedArea2/=2;let rectSearchMode=signedArea2<0?"inside":"outside",largestRectSolverParams={ccwFullOutline:outlinePoints,globalBounds:packedComponentBoundsWithMargin,origin:this.largestRectOrigin,mode:rectSearchMode},largestRectSolver=new LargestRectOutsideOutlineFromPointSolver(largestRectSolverParams);largestRectSolver.solve();let largestRectBounds=largestRectSolver.getLargestRectBounds();this.largestRectBounds=largestRectBounds;let segmentNormAbs={x:Math.abs(Math.sign(this.outlineSegment[1].x-this.outlineSegment[0].x)),y:Math.abs(Math.sign(this.outlineSegment[1].y-this.outlineSegment[0].y))},viableBounds={minX:largestRectBounds.minX-componentBounds.minX*segmentNormAbs.x,minY:largestRectBounds.minY-componentBounds.minY*segmentNormAbs.y,maxX:largestRectBounds.maxX-componentBounds.maxX*segmentNormAbs.x,maxY:largestRectBounds.maxY-componentBounds.maxY*segmentNormAbs.y};if(this.boundaryOutline&&this.boundaryOutline.length>=3){let boundaryMinX=1/0,boundaryMinY=1/0,boundaryMaxX=-1/0,boundaryMaxY=-1/0;for(let point6 of this.boundaryOutline)boundaryMinX=Math.min(boundaryMinX,point6.x),boundaryMinY=Math.min(boundaryMinY,point6.y),boundaryMaxX=Math.max(boundaryMaxX,point6.x),boundaryMaxY=Math.max(boundaryMaxY,point6.y);viableBounds={minX:Math.max(viableBounds.minX,boundaryMinX-componentBounds.minX),minY:Math.max(viableBounds.minY,boundaryMinY-componentBounds.minY),maxX:Math.min(viableBounds.maxX,boundaryMaxX-componentBounds.maxX),maxY:Math.min(viableBounds.maxY,boundaryMaxY-componentBounds.maxY)}}this.viableBounds=viableBounds;let viableBoundsWidth=viableBounds.maxX-viableBounds.minX,viableBoundsHeight=viableBounds.maxY-viableBounds.minY,componentBoundsWidth=componentBounds.maxX-componentBounds.minX,componentBoundsHeight=componentBounds.maxY-componentBounds.minY;if(viableBoundsWidth<componentBoundsWidth||viableBoundsHeight<componentBoundsHeight){this.failed=!0,this.error="There is nowhere for the component to fit along this outline section";return}let segmentLength=Math.hypot(p22.x-p12.x,p22.y-p12.y),expandedOutlineSegment=expandSegment(this.outlineSegment,segmentLength),[s12,s2]=expandedOutlineSegment;this.viableOutlineSegment=[{x:clamp2(s12.x,viableBounds.minX,viableBounds.maxX),y:clamp2(s12.y,viableBounds.minY,viableBounds.maxY)},{x:clamp2(s2.x,viableBounds.minX,viableBounds.maxX),y:clamp2(s2.y,viableBounds.minY,viableBounds.maxY)}];let[vp1,vp2]=this.viableOutlineSegment,initialPosition=this.adjustPositionForOutlineCollision({x:(vp1.x+vp2.x)/2,y:(vp1.y+vp2.y)/2});this.packStrategy==="minimum_closest_sum_squared_distance"?this.twoPhaseIrlsSolver=new TwoPhaseIrlsSolver({offsetPadPoints,targetPointMap,initialPosition,constraintFn,epsilon:1e-6,maxIterations:50}):this.irlsSolver=new MultiOffsetIrlsSolver({offsetPadPoints,targetPointMap,initialPosition,constraintFn,epsilon:1e-6,maxIterations:50,useSquaredDistance:this.packStrategy==="minimum_sum_squared_distance_to_network"})}_step(){let activeSolver=this.irlsSolver||this.twoPhaseIrlsSolver;if(!activeSolver){this.solved=!0;return}if(activeSolver.step(),activeSolver.solved){let rawPosition=activeSolver.getBestPosition();this.optimalPosition=rawPosition,this.solved=!0}else activeSolver.failed&&(this.failed=!0,this.error=activeSolver.error)}getNetworkTargetPointMappings(){let rotatedPads=this.getRotatedComponentPads(),offsetPadPoints=rotatedPads.map(pad2=>({id:pad2.padId,offsetX:pad2.offset.x,offsetY:pad2.offset.y})),targetPointMap=new Map;for(let pad2 of rotatedPads){let targetPoints=[];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;targetPoints.push({...packedPad.absoluteCenter,networkId:packedPad.networkId})}targetPointMap.set(pad2.padId,targetPoints)}return{offsetPadPoints,targetPointMap}}projectPointOntoSegment(point6,segment2){let[p12,p22]=segment2,segmentX=p22.x-p12.x,segmentY=p22.y-p12.y,pointX=point6.x-p12.x,pointY=point6.y-p12.y,segmentLengthSq=segmentX*segmentX+segmentY*segmentY;if(segmentLengthSq===0)return{x:p12.x,y:p12.y};let t5=Math.max(0,Math.min(1,(pointX*segmentX+pointY*segmentY)/segmentLengthSq));return{x:p12.x+t5*segmentX,y:p12.y+t5*segmentY}}getRotatedComponentPads(){let rotationRadians=this.componentRotationDegrees*Math.PI/180;return this.componentToPack.pads.map(pad2=>({...pad2,size:(this.componentRotationDegrees+90)%180===0?{x:pad2.size.y,y:pad2.size.x}:pad2.size,offset:rotatePoint(pad2.offset,rotationRadians)}))}createTemporaryPackedComponent(center2){let rotationRadians=this.componentRotationDegrees*Math.PI/180,flipWidthHeight=(this.componentRotationDegrees+90)%180===0;return{componentId:this.componentToPack.componentId,center:center2,ccwRotationOffset:this.componentRotationDegrees,pads:this.componentToPack.pads.map(pad2=>{let rotatedOffset=rotatePoint(pad2.offset,rotationRadians);return{...pad2,size:{x:flipWidthHeight?pad2.size.y:pad2.size.x,y:flipWidthHeight?pad2.size.x:pad2.size.y},absoluteCenter:{x:center2.x+rotatedOffset.x,y:center2.y+rotatedOffset.y}}})}}adjustPositionForOutlineCollision(center2){let tempComponent=this.createTemporaryPackedComponent(center2),bounds=getComponentBounds(tempComponent,0),outwardNormal=getOutwardNormal(this.outlineSegment,this.ccwFullOutline),isHorizontalNormal=Math.abs(outwardNormal.x)>Math.abs(outwardNormal.y),isVerticalNormal=!isHorizontalNormal,adjustedCenter=center2;if(isHorizontalNormal){let isXPlusFacing=outwardNormal.x>0;isXPlusFacing?adjustedCenter={x:bounds.maxX,y:center2.y}:!isXPlusFacing&&(adjustedCenter={x:bounds.minX,y:center2.y})}else if(isVerticalNormal){let isYPlusFacing=outwardNormal.y>0;isYPlusFacing?adjustedCenter={x:center2.x,y:bounds.maxY}:!isYPlusFacing&&(adjustedCenter={x:center2.x,y:bounds.minY})}if(this.boundaryOutline&&this.boundaryOutline.length>=3){let adjustedComponent=this.createTemporaryPackedComponent(adjustedCenter),adjustedBounds=getComponentBounds(adjustedComponent,0),allPadsInside=adjustedComponent.pads.every(pad2=>isPointInPolygon(pad2.absoluteCenter,this.boundaryOutline)),cornersInside=[{x:adjustedBounds.minX,y:adjustedBounds.minY},{x:adjustedBounds.minX,y:adjustedBounds.maxY},{x:adjustedBounds.maxX,y:adjustedBounds.minY},{x:adjustedBounds.maxX,y:adjustedBounds.maxY}].every(corner=>isPointInPolygon(corner,this.boundaryOutline));(!allPadsInside||!cornersInside)&&this.viableBounds&&(adjustedCenter={x:clamp2(adjustedCenter.x,this.viableBounds.minX,this.viableBounds.maxX),y:clamp2(adjustedCenter.y,this.viableBounds.minY,this.viableBounds.maxY)})}return adjustedCenter}visualize(){let graphics={lines:[],points:[],rects:[],circles:[]};if(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.globalBounds&&graphics.lines.push({points:[{x:this.globalBounds.minX,y:this.globalBounds.minY},{x:this.globalBounds.minX,y:this.globalBounds.maxY},{x:this.globalBounds.maxX,y:this.globalBounds.maxY},{x:this.globalBounds.maxX,y:this.globalBounds.minY},{x:this.globalBounds.minX,y:this.globalBounds.minY}],strokeColor:"rgba(255,0,255,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"})}if(this.viableBounds&&graphics.rects.push({center:{x:(this.viableBounds.minX+this.viableBounds.maxX)/2,y:(this.viableBounds.minY+this.viableBounds.maxY)/2},width:this.viableBounds.maxX-this.viableBounds.minX,height:this.viableBounds.maxY-this.viableBounds.minY,fill:"rgba(0,255,0,0.1)",label:"Viable Bounds"}),this.largestRectBounds&&graphics.rects.push({center:{x:(this.largestRectBounds.minX+this.largestRectBounds.maxX)/2,y:(this.largestRectBounds.minY+this.largestRectBounds.maxY)/2},width:this.largestRectBounds.maxX-this.largestRectBounds.minX,height:this.largestRectBounds.maxY-this.largestRectBounds.minY,fill:"rgba(255,0,255,0.4)"}),this.largestRectMidPoint&&graphics.points.push({...this.largestRectMidPoint,label:"Largest Rect Mid Point",color:"rgba(128,0,255,1)"}),this.largestRectOrigin&&graphics.points.push({...this.largestRectOrigin,label:"Largest Rect Origin",color:"rgba(255,0,128,1)"}),this.viableOutlineSegment){let[p12,p22]=this.viableOutlineSegment;graphics.lines.push({points:[p12,p22],strokeColor:"#2196F3"})}let[osp1,osp2]=this.outlineSegment;graphics.lines.push({points:[osp1,osp2],strokeColor:"rgba(255,0,0,1)",strokeDash:"3 3"});for(let[p12,p22]of this.ccwFullOutline)graphics.lines.push({points:[p12,p22],strokeColor:"rgba(0,0,0,0.5)",strokeDash:"4 4"});for(let component of this.packedComponents)for(let pad2 of component.pads)graphics.rects.push({center:pad2.absoluteCenter,width:pad2.size.x,height:pad2.size.y,fill:getColorForString(pad2.networkId,.5),stroke:"#333",label:`${pad2.padId} (${pad2.networkId})`});let pos=this.optimalPosition??this.irlsSolver?.currentPosition??this.twoPhaseIrlsSolver?.currentPosition??{x:0,y:0},rotatedPads=this.getRotatedComponentPads();for(let pad2 of rotatedPads){let padPos={x:pos.x+pad2.offset.x,y:pos.y+pad2.offset.y};graphics.rects.push({center:padPos,width:pad2.size.x,height:pad2.size.y,fill:this.failed?"rgba(255,0,0,0.5)":getColorForString(pad2.networkId,.5),label:`${pad2.padId} (${pad2.networkId})`});for(let packedComponent of this.packedComponents)for(let packedPad of packedComponent.pads)if(packedPad.networkId===pad2.networkId){let isStrong=isStrongConnection(pad2.padId,packedPad.padId,this.weightedConnections);graphics.lines.push({points:[padPos,packedPad.absoluteCenter],strokeColor:pad2.networkId==="VCC"?"#FF6B6B":"#4ECDC4",strokeDash:isStrong?void 0:"4 2",label:`${pad2.networkId} ${isStrong?"strong":"weak"}`})}}let activeSolver=this.irlsSolver||this.twoPhaseIrlsSolver;if(activeSolver){let currentPos=activeSolver.currentPosition;graphics.points.push({...currentPos,color:"#f44336"});let solverViz=activeSolver.visualize();solverViz.lines&&graphics.lines.push(...solverViz.lines),solverViz.circles&&graphics.circles.push(...solverViz.circles),solverViz.rects&&graphics.rects.push(...solverViz.rects),solverViz.points&&graphics.points.push(...solverViz.points)}return this.optimalPosition&&graphics.points.push({...this.optimalPosition,color:"rgba(76, 175, 80, 0.3)"}),graphics}getOutput(){return this.optimalPosition??null}},getGraphicsFromPackOutput=packOutput=>{let rects=[],lines=[];if(packOutput.boundaryOutline&&packOutput.boundaryOutline.length){let outlinePoints=[...packOutput.boundaryOutline];outlinePoints.length>0&&(outlinePoints[0].x!==outlinePoints[outlinePoints.length-1].x||outlinePoints[0].y!==outlinePoints[outlinePoints.length-1].y)&&outlinePoints.push({...outlinePoints[0]}),lines.push({points:outlinePoints,strokeColor:"rgba(0, 0, 255, 0.5)",strokeDash:"4 2"})}let allNetworkIds=Array.from(new Set(packOutput.components.flatMap(c3=>c3.pads.map(p4=>p4.networkId)))),colorMap2=createColorMapFromStrings(allNetworkIds);if(packOutput.obstacles&&packOutput.obstacles.length>0)for(let obstacle of packOutput.obstacles)rects.push({center:{x:obstacle.absoluteCenter.x,y:obstacle.absoluteCenter.y},width:obstacle.width,height:obstacle.height,fill:"rgba(0,0,0,0.1)",stroke:"#555",label:obstacle.obstacleId});for(let component of packOutput.components){let bounds=getComponentBounds(component),width=bounds.maxX-bounds.minX,height=bounds.maxY-bounds.minY,isStatic=!!component.isStatic,rect={center:{x:component.center.x,y:component.center.y},width,height,fill:isStatic?"rgba(33, 150, 243, 0.25)":"rgba(0,0,0,0.25)",stroke:isStatic?"rgba(33, 150, 243, 0.6)":void 0,label:[component.componentId,`ccwRotationOffset: ${component.ccwRotationOffset.toFixed(1)}\xB0`].join(`
|
|
607
607
|
`)};rects.push(rect);for(let pad2 of component.pads){let{absoluteCenter,size:size2,padId,networkId}=pad2,padRect={center:{x:absoluteCenter.x,y:absoluteCenter.y},width:size2.x,height:size2.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(p4=>p4.networkId===netId));for(let i2=0;i2<padsOnNet.length;i2++)for(let j4=i2+1;j4<padsOnNet.length;j4++){let pad1=padsOnNet[i2],pad2=padsOnNet[j4],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 checkOverlapWithPackedComponents({component,packedComponents,minGap}){let allPackedPadBoxes=packedComponents.flatMap(c3=>c3.pads.map(p4=>({center:{x:p4.absoluteCenter.x,y:p4.absoluteCenter.y},width:p4.size.x,height:p4.size.y}))),newComponentPadBoxes=component.pads.map(p4=>({center:{x:p4.absoluteCenter.x,y:p4.absoluteCenter.y},width:p4.size.x,height:p4.size.y}));for(let newComponentPadBox of newComponentPadBoxes)for(let packedPadBox of allPackedPadBoxes){let{distance:boxDist}=computeDistanceBetweenBoxes2(newComponentPadBox,packedPadBox);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}_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],position2={x:0,y:0},rotation4=availableRotations2[0]??0,candidate=this.createPackedComponent(position2,rotation4);if(!(this.obstacles??[]).some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return candidate.pads.some(p4=>{let padBox={center:{x:p4.absoluteCenter.x,y:p4.absoluteCenter.y},width:p4.size.x,height:p4.size.y},{distance:distance8}=computeDistanceBetweenBoxes2(padBox,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 i2=0;i2<outline.length;i2++){let segment2=outline[i2];this.queuedOutlineSegments.push({segment:segment2,availableRotations:[...availableRotations],segmentIndex:segmentIndex*1e3+i2,ccwFullOutline:outline})}}if(this.boundaryOutline&&this.boundaryOutline.length>=3){let boundarySegments=[];for(let i2=0;i2<this.boundaryOutline.length;i2++){let p12=this.boundaryOutline[i2],p22=this.boundaryOutline[(i2+1)%this.boundaryOutline.length];boundarySegments.push([p12,p22])}let boundaryOutlineIndex=this.outlines.length;for(let i2=0;i2<boundarySegments.length;i2++){let segment2=boundarySegments[i2];this.queuedOutlineSegments.push({segment:segment2,availableRotations:[...availableRotations],segmentIndex:boundaryOutlineIndex*1e3+i2,ccwFullOutline:boundarySegments})}}let obstacleOutlineIndex=this.outlines.length+1;for(let obstacle of this.obstacles){let hw2=obstacle.width/2+this.minGap,hh2=obstacle.height/2+this.minGap,cx2=obstacle.absoluteCenter.x,cy2=obstacle.absoluteCenter.y,obstacleCorners=[{x:cx2-hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2+hh2},{x:cx2-hw2,y:cy2+hh2}],obstacleSegments=[[obstacleCorners[0],obstacleCorners[1]],[obstacleCorners[1],obstacleCorners[2]],[obstacleCorners[2],obstacleCorners[3]],[obstacleCorners[3],obstacleCorners[0]]];for(let i2=0;i2<obstacleSegments.length;i2++){let segment2=obstacleSegments[i2];this.queuedOutlineSegments.push({segment:segment2,availableRotations:[...availableRotations],segmentIndex:obstacleOutlineIndex*1e3+i2,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],rotation4=queuedSegment.availableRotations[this.currentRotationIndex],distance8=1/0,optimalPosition;if(this.activeSubSolver.solved&&this.activeSubSolver.optimalPosition){optimalPosition=this.activeSubSolver.optimalPosition;let candidateComponent=this.createPackedComponent(optimalPosition,rotation4),{hasOverlap,gapDistance}=checkOverlapWithPackedComponents({component:candidateComponent,packedComponents:this.packedComponents,minGap:this.minGap}),minObstacleGapDistance=1/0,tooCloseToObstacles=(this.obstacles??[]).some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return candidateComponent.pads.some(p4=>{let padBox={center:{x:p4.absoluteCenter.x,y:p4.absoluteCenter.y},width:p4.size.x,height:p4.size.y},{distance:distance23}=computeDistanceBetweenBoxes2(padBox,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=>isPointInPolygon(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=>isPointInPolygon(corner,this.boundaryOutline));outsideBoundaryOutline=!allPadsInside||!cornersInside}distance8=this.calculateDistance(optimalPosition,rotation4),hasOverlap?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation4,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance}):tooCloseToObstacles?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation4,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance:minObstacleGapDistance}):outsideBounds?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation4,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance:-1}):outsideBoundaryOutline?this.rejectedCandidates.push({segment:queuedSegment.segment,rotation:rotation4,optimalPosition,distance:distance8,segmentIndex:queuedSegment.segmentIndex,rotationIndex:this.currentRotationIndex,gapDistance:-1}):this.candidateResults.push({segment:queuedSegment.segment,rotation:rotation4,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 rotation4=queuedSegment.availableRotations[this.currentRotationIndex];this.activeSubSolver=new OutlineSegmentCandidatePointSolver({outlineSegment:queuedSegment.segment,ccwFullOutline:queuedSegment.ccwFullOutline,componentRotationDegrees:rotation4,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((a2,b3)=>a2.distance-b3.distance),this.bestCandidate=this.candidateResults[0],this.bestCandidate.optimalPosition&&(this.outputPackedComponent=this.createPackedComponent(this.bestCandidate.optimalPosition,this.bestCandidate.rotation)),this.solved=!0}calculateDistance(position2,rotation4){let tempComponent=this.createPackedComponent(position2,rotation4),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 dx2=pad2.absoluteCenter.x-packedPad.absoluteCenter.x,dy2=pad2.absoluteCenter.y-packedPad.absoluteCenter.y,dist=Math.sqrt(dx2*dx2+dy2*dy2);minDistanceToNetwork=Math.min(minDistanceToNetwork,dist)}minDistanceToNetwork<1/0&&(totalDistance+=useSquaredDistance?minDistanceToNetwork*minDistanceToNetwork:minDistanceToNetwork)}return totalDistance}createPackedComponent(position2,rotation4){let component={...this.componentToPack,center:position2,ccwRotationOffset:rotation4,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 i2=0;i2<this.outlines.length;i2++){let outline=this.outlines[i2];for(let u4=0;u4<outline.length;u4++){let[p12,p22]=outline[u4];graphics.points.push({x:p12.x,y:p12.y,label:`outlines [${i2}] [${u4}]`,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 i2=0;i2<this.candidateResults.length;i2++){let candidate=this.candidateResults[i2];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${i2}, d=${candidate.distance.toFixed(3)}`,color:"rgba(255,165,0,0.8)"})}}}visualizeEvaluatePhase(graphics){this.visualizeOutlinePhase(graphics);for(let i2=0;i2<this.candidateResults.length;i2++){let candidate=this.candidateResults[i2];if(!candidate.optimalPosition)continue;let step=i2,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 i2=0;i2<this.rejectedCandidates.length;i2++){let candidate=this.rejectedCandidates[i2];candidate.optimalPosition&&graphics.points.push({x:candidate.optimalPosition.x,y:candidate.optimalPosition.y,label:`rejected, d=${candidate.distance.toFixed(3)}
|
|
608
|
-
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,p4)=>sum+p4.x,0),sumY=points.reduce((sum,p4)=>sum+p4.y,0);return{x:sumX/points.length,y:sumY/points.length}}let signedArea2=0,cx2=0,cy2=0;for(let i2=0;i2<points.length;i2++){let p12=points[i2],p22=points[(i2+1)%points.length],crossProduct=p12.x*p22.y-p22.x*p12.y;signedArea2+=crossProduct,cx2+=(p12.x+p22.x)*crossProduct,cy2+=(p12.y+p22.y)*crossProduct}if(signedArea2*=.5,Math.abs(signedArea2)<1e-10){let sumX=points.reduce((sum,p4)=>sum+p4.x,0),sumY=points.reduce((sum,p4)=>sum+p4.y,0);return{x:sumX/points.length,y:sumY/points.length}}return cx2/=6*signedArea2,cy2/=6*signedArea2,{x:cx2,y:cy2}}var PackSolver2=class extends BaseSolver{constructor(packInput){super();__publicField(this,"packInput");__publicField(this,"unpackedComponentQueue",[]);__publicField(this,"packedComponents",[]);__publicField(this,"componentToPack");this.packInput=packInput}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??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:0,pads:firstComponentToPack.pads.map(p4=>({...p4,absoluteCenter:{x:0,y:0}}))};setPackedComponentPadCenters(newPackedComponent);let obstacles=this.packInput.obstacles??[],tooCloseToObstacles=obstacles.some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return newPackedComponent.pads.some(p4=>{let padBox={center:{x:p4.absoluteCenter.x,y:p4.absoluteCenter.y},width:p4.size.x,height:p4.size.y},{distance:distance8}=computeDistanceBetweenBoxes2(padBox,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=>isPointInPolygon(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=>isPointInPolygon(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:0,pads:this.componentToPack.pads.map(p4=>({...p4,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 i2=0;i2<pads.length;i2++)for(let j4=i2+1;j4<pads.length;j4++){let pad1=pads[i2],pad2=pads[j4];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}},extractPadInfos=(pcbComponent,db,getNetworkId)=>{let out=[],pushPad=({padId,pcbPortId,sx:sx2,sy:sy2,x:x5,y:y5})=>out.push({padId,networkId:getNetworkId(pcbPortId),size:{x:sx2,y:sy2},absoluteCenter:{x:x5,y:y5},pcbPortId});for(let via of db.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 ph2 of db.pcb_plated_hole.list({pcb_component_id:pcbComponent.pcb_component_id}))switch(ph2.shape){case"circle":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.outer_diameter??ph2.hole_diameter??0,sy:ph2.outer_diameter??ph2.hole_diameter??0,x:ph2.x,y:ph2.y});break}case"oval":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.outer_width,sy:ph2.outer_height,x:ph2.x,y:ph2.y});break}case"circular_hole_with_rect_pad":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.rect_pad_width,sy:ph2.rect_pad_height,x:ph2.x,y:ph2.y});break}case"pill":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.outer_width,sy:ph2.outer_height,x:ph2.x,y:ph2.y});break}case"pill_hole_with_rect_pad":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.rect_pad_width,sy:ph2.rect_pad_height,x:ph2.x,y:ph2.y});break}default:{console.warn(`Unsupported plated hole shape ${ph2.shape}`);break}}for(let sp2 of db.pcb_smtpad.list({pcb_component_id:pcbComponent.pcb_component_id}))switch(sp2.shape){case"rect":{pushPad({padId:sp2.pcb_smtpad_id,pcbPortId:sp2.pcb_port_id,sx:sp2.width??0,sy:sp2.height??0,x:sp2.x,y:sp2.y});break}case"circle":{pushPad({padId:sp2.pcb_smtpad_id,pcbPortId:sp2.pcb_port_id,sx:sp2.radius*2,sy:sp2.radius*2,x:sp2.x,y:sp2.y});break}case"polygon":{if(sp2.points&&sp2.points.length>0){let{minX,maxX,minY,maxY}=getPolygonBoundingBox(sp2.points),width=maxX-minX,height=maxY-minY,centerX=(minX+maxX)/2,centerY=(minY+maxY)/2;pushPad({padId:sp2.pcb_smtpad_id,pcbPortId:sp2.pcb_port_id,sx:width,sy:height,x:centerX,y:centerY})}else console.warn(`Polygon pad ${sp2.pcb_smtpad_id} has no points`);break}}return out},getElementOutsideTree=(db,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 ph2 of db.pcb_plated_hole.list({})){if(!("pcb_component_id"in ph2)||!ph2.pcb_component_id){outside.push(ph2);continue}componentIdsInTree.has(ph2.pcb_component_id)||outside.push(ph2)}return outside},buildPackedComponent=(pcbComponents,componentId,db,getNetworkId,shouldAddInnerObstacles,sourcePortToPadIds=new Map,chipMarginsMap={},isStatic=!1)=>{let padInfos=pcbComponents.flatMap(pc2=>{let pads2=extractPadInfos(pc2,db,getNetworkId),margins=chipMarginsMap[pc2.pcb_component_id];return margins?pads2.map(p4=>({...p4,size:{x:p4.size.x+margins.left+margins.right,y:p4.size.y+margins.top+margins.bottom},absoluteCenter:{x:p4.absoluteCenter.x+(margins.right-margins.left)/2,y:p4.absoluteCenter.y+(margins.top-margins.bottom)/2}})):pads2}),minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let p4 of padInfos)minX=Math.min(minX,p4.absoluteCenter.x-p4.size.x/2),maxX=Math.max(maxX,p4.absoluteCenter.x+p4.size.x/2),minY=Math.min(minY,p4.absoluteCenter.y-p4.size.y/2),maxY=Math.max(maxY,p4.absoluteCenter.y+p4.size.y/2);let center2={x:(minX+maxX)/2,y:(minY+maxY)/2},pads=padInfos.map(p4=>({padId:p4.padId,networkId:p4.networkId,type:"rect",size:p4.size,absoluteCenter:p4.absoluteCenter,offset:{x:p4.absoluteCenter.x-center2.x,y:p4.absoluteCenter.y-center2.y}}));for(let padInfo of padInfos){if(!padInfo.pcbPortId)continue;let sourcePortId=db.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)}return{componentId,isStatic,center:center2,ccwRotationOffset:0,pads}},collectPcbComponents=(node,db)=>{if(node.nodeType==="component"){let pcbId=node.otherChildElements[0]?.pcb_component_id;return pcbId?[db.pcb_component.get(pcbId)]:[]}return node.childNodes.flatMap(n3=>collectPcbComponents(n3,db))},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}),db=cju_default(circuitJson),unnamedCounter=0,sourcePortToPadIds=new Map,elementsOutsideTree=getElementOutsideTree(db,tree),pcbBoard=circuitJson.find(item=>item.type==="pcb_board");pcbBoard&&pcbBoard.outline&&(packOutput.boundaryOutline=pcbBoard.outline);let getNetworkId=pcbPortId=>{if(pcbPortId){let pcbPort=db.pcb_port.get(pcbPortId);if(pcbPort){let sourcePort=db.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(e4=>e4.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??[]);for(let node of topLevelNodes)if(node.nodeType==="component"){let pcbComponent=node.otherChildElements.find(e4=>e4.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,db,getNetworkId,shouldAddInnerObstaclesForComp,sourcePortToPadIds,opts.chipMarginsMap,staticComponentIds.has(pcbComponent.pcb_component_id)))}else if(node.nodeType==="group"){let pcbComps=collectPcbComponents(node,db);if(!pcbComps.length)continue;let compId=node.sourceGroup?.source_group_id??node.sourceGroup?.name??`group_${packOutput.components.length}`;packOutput.components.push(buildPackedComponent(pcbComps,compId,db,getNetworkId,void 0,sourcePortToPadIds,opts.chipMarginsMap,staticComponentIds.has(compId)))}let relativeComponents=topLevelNodes.flatMap(node=>collectRelativeToGroupAnchorComponents(node));for(let pcbComponent of relativeComponents){let padInfos=extractPadInfos(pcbComponent,db,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)if(element.type==="pcb_plated_hole"&&element.shape==="circular_hole_with_rect_pad"){let{rect_pad_height,rect_pad_width,x:x5,y:y5}=element;packOutput.obstacles.push({obstacleId:element.pcb_plated_hole_id,absoluteCenter:{x:x5,y:y5},width:rect_pad_width,height:rect_pad_height})}let weightedConnections=[],seenConnections=new Set,sourceTraces=typeof db.source_trace.list=="function"?db.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(pc2=>({...pc2.isStatic?{...pc2,pads:pc2.pads.map(pad2=>({...pad2}))}:{componentId:pc2.componentId,availableRotationDegrees:pc2.availableRotationDegrees,pads:pc2.pads.map(({absoluteCenter:_ac,...rest})=>rest)}}));return{...packed,components:strippedComponents}};var getBoardPolygon=region=>{let board_edge_margin=region.board_edge_margin??0;if(region.outline&®ion.outline.length>0){let polygon2=new Flatten.Polygon(region.outline.map(p4=>Flatten.point(p4.x,p4.y)));return polygon2.orientation()===Flatten.ORIENTATION.CW&&polygon2.reverse(),polygon2}let{bounds}=region,newBounds={minX:bounds.minX+board_edge_margin,minY:bounds.minY+board_edge_margin,maxX:bounds.maxX-board_edge_margin,maxY:bounds.maxY-board_edge_margin};return newBounds.minX>=newBounds.maxX||newBounds.minY>=newBounds.maxY?new Flatten.Polygon:new Flatten.Polygon(new Flatten.Box(newBounds.minX,newBounds.minY,newBounds.maxX,newBounds.maxY).toPoints())},circleToPolygon=(circle2,numSegments=32)=>{let points=[];for(let i2=0;i2<numSegments;i2++){let angle=i2/numSegments*2*Math.PI;points.push(new Flatten.Point(circle2.center.x+circle2.r*Math.cos(angle),circle2.center.y+circle2.r*Math.sin(angle)))}return new Flatten.Polygon(points)},isRectPad=pad2=>pad2.shape==="rect",isTracePad=pad2=>pad2.shape==="trace",isCircularPad=pad2=>pad2.shape==="circle",isPolygonPad=pad2=>pad2.shape==="polygon",processObstaclesForPour=(pads,pourConnectivityKey,margins,boardOutline)=>{let polygonsToSubtract=[],{padMargin,traceMargin,board_edge_margin,cutoutMargin}=margins;if(boardOutline&&boardOutline.length>0&&board_edge_margin&&board_edge_margin>0){let boardPoly=new Flatten.Polygon(boardOutline.map(p4=>Flatten.point(p4.x,p4.y)));boardPoly.area()<0&&boardPoly.reverse();let vertices=boardPoly.vertices;for(let i2=0;i2<vertices.length;i2++){let p12=vertices[i2===0?vertices.length-1:i2-1],p22=vertices[i2],p32=vertices[(i2+1)%vertices.length];if(!p12||!p22||!p32)continue;let v12=new Flatten.Vector(p12,p22),v22=new Flatten.Vector(p22,p32),crossProduct=v12.cross(v22),circle2=new Flatten.Circle(p22,board_edge_margin);if(polygonsToSubtract.push(circleToPolygon(circle2)),crossProduct<0){let box2=new Flatten.Box(p22.x-board_edge_margin,p22.y-board_edge_margin,p22.x+board_edge_margin,p22.y+board_edge_margin);polygonsToSubtract.push(new Flatten.Polygon(box2.toPoints()))}}for(let i2=0;i2<vertices.length;i2++){let p12=vertices[i2],p22=vertices[(i2+1)%vertices.length];if(!p12||!p22)continue;let segmentLength=Math.hypot(p12.x-p22.x,p12.y-p22.y);if(segmentLength===0)continue;let enlargedWidth=board_edge_margin*2,centerX=(p12.x+p22.x)/2,centerY=(p12.y+p22.y)/2,rotationDeg=Math.atan2(p22.y-p12.y,p22.x-p12.x)*180/Math.PI,w22=segmentLength/2,h22=enlargedWidth/2,angleRad=rotationDeg*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),rotatedCorners=[{x:-w22,y:-h22},{x:w22,y:-h22},{x:w22,y:h22},{x:-w22,y:h22}].map(p4=>({x:centerX+p4.x*cosAngle-p4.y*sinAngle,y:centerY+p4.x*sinAngle+p4.y*cosAngle}));polygonsToSubtract.push(new Flatten.Polygon(rotatedCorners.map(p4=>Flatten.point(p4.x,p4.y))))}}for(let pad2 of pads){if(pad2.connectivityKey===pourConnectivityKey)continue;let isHoleOrCutout=pad2.connectivityKey.startsWith("hole:")||pad2.connectivityKey.startsWith("cutout:");if(isCircularPad(pad2)){let margin=isHoleOrCutout?cutoutMargin??0:padMargin,circle2=new Flatten.Circle(new Flatten.Point(pad2.x,pad2.y),pad2.radius+margin);polygonsToSubtract.push(circleToPolygon(circle2));continue}if(isRectPad(pad2)){let margin=isHoleOrCutout?cutoutMargin??0:padMargin,{bounds}=pad2,b3=new Flatten.Box(bounds.minX-margin,bounds.minY-margin,bounds.maxX+margin,bounds.maxY+margin);polygonsToSubtract.push(new Flatten.Polygon(b3.toPoints()));continue}if(isPolygonPad(pad2)){let margin=isHoleOrCutout?cutoutMargin??0:0,seen=new Set,uniquePoints=pad2.points.filter(p4=>{let key=`${p4.x},${p4.y}`;return seen.has(key)?!1:(seen.add(key),!0)});if(uniquePoints.length<3)continue;let polygon2=new Flatten.Polygon(uniquePoints.map(p4=>Flatten.point(p4.x,p4.y)));if(Math.abs(polygon2.area())<1e-9)continue;if(margin<=0){polygonsToSubtract.push(polygon2);continue}polygon2.area()>0&&polygon2.reverse();let offsetLines=[],polygonVertices=polygon2.vertices;for(let i2=0;i2<polygonVertices.length;i2++){let p12=polygonVertices[i2],p22=polygonVertices[(i2+1)%polygonVertices.length],segment2=Flatten.segment(p12,p22);if(segment2.length===0)continue;let line2=Flatten.line(segment2.start,segment2.end),norm=line2.norm,offsetLine=line2.translate(norm.multiply(-margin));offsetLines.push(offsetLine)}let newPolygonPoints=[];for(let i2=0;i2<offsetLines.length;i2++){let line1=offsetLines[i2],line2=offsetLines[(i2+1)%offsetLines.length],ip2=line1.intersect(line2);ip2.length>0&&newPolygonPoints.push(ip2[0])}newPolygonPoints.length>=3&&polygonsToSubtract.push(new Flatten.Polygon(newPolygonPoints));continue}if(isTracePad(pad2)){for(let segment2 of pad2.segments){let circle2=new Flatten.Circle(new Flatten.Point(segment2.x,segment2.y),pad2.width/2+traceMargin);polygonsToSubtract.push(circleToPolygon(circle2))}for(let i2=0;i2<pad2.segments.length-1;i2++){let p12=pad2.segments[i2],p22=pad2.segments[i2+1];if(!p12||!p22)continue;let segmentLength=Math.hypot(p12.x-p22.x,p12.y-p22.y);if(segmentLength===0)continue;let enlargedWidth=pad2.width+traceMargin*2,centerX=(p12.x+p22.x)/2,centerY=(p12.y+p22.y)/2,rotationDeg=Math.atan2(p22.y-p12.y,p22.x-p12.x)*180/Math.PI,w22=segmentLength/2,h22=enlargedWidth/2,angleRad=rotationDeg*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),rotatedCorners=[{x:-w22,y:-h22},{x:w22,y:-h22},{x:w22,y:h22},{x:-w22,y:h22}].map(p4=>({x:centerX+p4.x*cosAngle-p4.y*sinAngle,y:centerY+p4.x*sinAngle+p4.y*cosAngle}));polygonsToSubtract.push(new Flatten.Polygon(rotatedCorners.map(p4=>Flatten.point(p4.x,p4.y))))}continue}}return{polygonsToSubtract}},faceToVertices=face=>face.edges.map(e4=>{let pt4={x:e4.start.x,y:e4.start.y};if(e4.isArc){let bulge=Math.tan(e4.shape.sweep/4);Math.abs(bulge)>1e-9&&(pt4.bulge=bulge)}return pt4}),generateBRep=pourPolygons=>{let brep_shapes=[],polygons=Array.isArray(pourPolygons)?pourPolygons:[pourPolygons];for(let p4 of polygons){let islands=p4.splitToIslands();for(let island of islands){if(island.isEmpty())continue;let faces=[...island.faces],outer_face_ccw=faces.find(f2=>f2.orientation()===Flatten.ORIENTATION.CCW),inner_faces_cw=faces.filter(f2=>f2.orientation()===Flatten.ORIENTATION.CW);if(!outer_face_ccw)continue;outer_face_ccw.reverse();let outer_ring_vertices=faceToVertices(outer_face_ccw),inner_rings=inner_faces_cw.map(f2=>(f2.reverse(),{vertices:faceToVertices(f2)}));brep_shapes.push({outer_ring:{vertices:outer_ring_vertices},inner_rings})}}return brep_shapes},CopperPourPipelineSolver=class extends BasePipelineSolver{constructor(input2){super(input2);__publicField(this,"pipelineDef",[]);this.input=input2}getOutput(){let brep_shapes=[];for(let region of this.input.regionsForPour){let boardPolygon=getBoardPolygon(region),padsForLayer=this.input.pads.filter(p4=>p4.layer===region.layer),{polygonsToSubtract}=processObstaclesForPour(padsForLayer,region.connectivityKey,{padMargin:region.padMargin,traceMargin:region.traceMargin,board_edge_margin:region.board_edge_margin,cutoutMargin:region.cutout_margin},region.outline),pourPolygons=boardPolygon;for(let poly of polygonsToSubtract){let currentPolys=Array.isArray(pourPolygons)?pourPolygons:[pourPolygons],nextPolys=[];for(let p4 of currentPolys){let result=Flatten.BooleanOperations.subtract(p4,poly);result&&(Array.isArray(result)?nextPolys.push(...result.filter(r4=>!r4.isEmpty())):result.isEmpty()||nextPolys.push(result))}pourPolygons=nextPolys}let new_breps=generateBRep(pourPolygons);brep_shapes.push(...new_breps)}return{brep_shapes}}},convertCircuitJsonToInputProblem=(circuitJson,options)=>{let source_ports=circuitJson.filter(e4=>e4.type==="source_port"),pcb_ports=circuitJson.filter(e4=>e4.type==="pcb_port"),source_traces=circuitJson.filter(e4=>e4.type==="source_trace"),pcb_traces=circuitJson.filter(e4=>e4.type==="pcb_trace"),source_nets=circuitJson.filter(e4=>e4.type==="source_net"),pcb_board2=circuitJson.find(e4=>e4.type==="pcb_board");if(!pcb_board2)throw new Error("No pcb_board found in circuit json");let sourcePortIdToConnectivityKey=Object.fromEntries(source_ports.map(sp2=>[sp2.source_port_id,sp2.subcircuit_connectivity_map_key])),pcbPortIdToConnectivityKey=Object.fromEntries(pcb_ports.map(pp2=>[pp2.pcb_port_id,sourcePortIdToConnectivityKey[pp2.source_port_id]])),pcbPlatedHoleIdToConnectivityKey={};for(let pcb_port2 of pcb_ports)pcb_port2.pcb_port_id&&(pcbPlatedHoleIdToConnectivityKey[pcb_port2.pcb_port_id]=pcbPortIdToConnectivityKey[pcb_port2.pcb_port_id]);let sourceTraceIdToConnectivityKey=Object.fromEntries(source_traces.map(st4=>[st4.source_trace_id,st4.subcircuit_connectivity_map_key])),sourceNetIdToConnectivityKey=Object.fromEntries(source_nets.map(sn4=>[sn4.source_net_id,sn4.subcircuit_connectivity_map_key])),idToConnectivityKey={...sourceTraceIdToConnectivityKey,...sourceNetIdToConnectivityKey},pcbTraceIdToConnectivityKey=Object.fromEntries(pcb_traces.map(trace=>[trace.pcb_trace_id,trace.source_trace_id?idToConnectivityKey[trace.source_trace_id]:void 0]).filter(entry=>!!entry[1])),pads=[];for(let elm of circuitJson)if(elm.type==="pcb_smtpad"){let smtpad2=elm;if(smtpad2.layer!==options.layer)continue;let connectivityKey;smtpad2.pcb_port_id&&(connectivityKey=pcbPortIdToConnectivityKey[smtpad2.pcb_port_id]),connectivityKey||(connectivityKey=`unconnected:${smtpad2.pcb_smtpad_id}`),smtpad2.shape==="rect"?pads.push({shape:"rect",padId:smtpad2.pcb_smtpad_id,layer:smtpad2.layer,connectivityKey,bounds:{minX:smtpad2.x-smtpad2.width/2,minY:smtpad2.y-smtpad2.height/2,maxX:smtpad2.x+smtpad2.width/2,maxY:smtpad2.y+smtpad2.height/2}}):smtpad2.shape==="circle"&&pads.push({shape:"circle",padId:smtpad2.pcb_smtpad_id,layer:smtpad2.layer,connectivityKey,x:smtpad2.x,y:smtpad2.y,radius:smtpad2.radius})}else if(elm.type==="pcb_plated_hole"){let platedHole=elm;if(platedHole.shape!=="circle"||!platedHole.layers.includes(options.layer))continue;let connectivityKey=pcbPlatedHoleIdToConnectivityKey[platedHole.pcb_plated_hole_id];connectivityKey||(connectivityKey=`unconnected-plated-hole:${platedHole.pcb_plated_hole_id}`),pads.push({shape:"circle",padId:platedHole.pcb_plated_hole_id,layer:options.layer,connectivityKey,x:platedHole.x,y:platedHole.y,radius:platedHole.outer_diameter/2})}else if(elm.type==="pcb_hole"){let hole=elm;if(hole.hole_shape!=="circle")continue;pads.push({shape:"circle",padId:hole.pcb_hole_id,layer:options.layer,connectivityKey:`hole:${hole.pcb_hole_id}`,x:hole.x,y:hole.y,radius:hole.hole_diameter/2})}else if(elm.type==="pcb_cutout"){let cutout=elm;cutout.shape==="rect"?pads.push({shape:"rect",padId:cutout.pcb_cutout_id,layer:options.layer,connectivityKey:`cutout:${cutout.pcb_cutout_id}`,bounds:{minX:cutout.center.x-cutout.width/2,minY:cutout.center.y-cutout.height/2,maxX:cutout.center.x+cutout.width/2,maxY:cutout.center.y+cutout.height/2}}):cutout.shape==="circle"?pads.push({shape:"circle",padId:cutout.pcb_cutout_id,layer:options.layer,connectivityKey:`cutout:${cutout.pcb_cutout_id}`,x:cutout.center.x,y:cutout.center.y,radius:cutout.radius}):cutout.shape==="polygon"&&pads.push({shape:"polygon",padId:cutout.pcb_cutout_id,layer:options.layer,connectivityKey:`cutout:${cutout.pcb_cutout_id}`,points:cutout.points})}else if(elm.type==="pcb_via"){let via=elm;if(!via.layers.includes(options.layer))continue;let connectivityKey=via.subcircuit_connectivity_map_key??pcbTraceIdToConnectivityKey[via.pcb_trace_id??""]??`unconnected-via:${via.pcb_via_id}`;pads.push({shape:"circle",padId:via.pcb_via_id,layer:options.layer,connectivityKey,x:via.x,y:via.y,radius:via.outer_diameter/2})}else if(elm.type==="pcb_trace"){let trace=elm;if(!trace.source_trace_id)continue;let connectivityKey=idToConnectivityKey[trace.source_trace_id];if(!connectivityKey)continue;let currentSegmentGroup=[],currentWidth=null,commitGroup=()=>{currentSegmentGroup.length>1&&pads.push({shape:"trace",padId:`${trace.pcb_trace_id}-${pads.length}`,layer:options.layer,connectivityKey,segments:currentSegmentGroup,width:currentWidth}),currentSegmentGroup=[],currentWidth=null};for(let r4 of trace.route){let ri3=r4;ri3.route_type==="wire"&&ri3.layer===options.layer?(currentWidth===null&&(currentWidth=ri3.width),currentSegmentGroup.push({x:ri3.x,y:ri3.y})):commitGroup()}commitGroup()}let{width,height}=pcb_board2,regionsForPour=[{shape:"rect",layer:options.layer,bounds:{minX:-width/2,minY:-height/2,maxX:width/2,maxY:height/2},outline:pcb_board2.outline,connectivityKey:options.pour_connectivity_key,padMargin:options.pad_margin,traceMargin:options.trace_margin,board_edge_margin:options.board_edge_margin??0,cutout_margin:options.cutout_margin}];return{pads,regionsForPour}};init_dist();var import_debug10=__toESM(require_browser(),1);init_dist6();init_dist6();init_dist6();init_dist6();init_dist6();init_dist4();init_dist6();init_dist6();init_dist6();var __defProp3=Object.defineProperty,__getOwnPropSymbols=Object.getOwnPropertySymbols,__hasOwnProp2=Object.prototype.hasOwnProperty,__propIsEnum=Object.prototype.propertyIsEnumerable,__defNormalProp2=(obj,key,value)=>key in obj?__defProp3(obj,key,{enumerable:!0,configurable:!0,writable:!0,value}):obj[key]=value,__spreadValues=(a2,b3)=>{for(var prop in b3||(b3={}))__hasOwnProp2.call(b3,prop)&&__defNormalProp2(a2,prop,b3[prop]);if(__getOwnPropSymbols)for(var prop of __getOwnPropSymbols(b3))__propIsEnum.call(b3,prop)&&__defNormalProp2(a2,prop,b3[prop]);return a2},getUnitVecFromAnchorSide=anchorSide=>{switch(anchorSide){case"left":return{x:-1,y:0};case"right":return{x:1,y:0};case"top":return{x:0,y:1};case"bottom":return{x:0,y:-1}}},getReadableIdMap=circuitJson=>{var _a360,_b2;let schComps=cju_default(circuitJson).schematic_component.list(),schLabels=cju_default(circuitJson).schematic_net_label.list(),schPorts=cju_default(circuitJson).schematic_port.list(),readableIdMap={};for(let schComp of schComps){let srcComp=cju_default(circuitJson).source_component.get(schComp.source_component_id);readableIdMap[schComp.schematic_component_id]=srcComp?.name}for(let schLabel of schLabels){let srcNet=cju_default(circuitJson).source_net.get(schLabel.source_net_id);if(!srcNet?.name)continue;let index=0;for(;Object.values(readableIdMap).includes(`NL_${srcNet.name}${index}`);)index++;readableIdMap[schLabel.schematic_net_label_id]=`NL_${srcNet.name}${index}`}for(let schPort of schPorts){let srcPort=cju_default(circuitJson).source_port.get(schPort.source_port_id);if(!srcPort)continue;let srcComp=cju_default(circuitJson).source_component.get(srcPort.source_component_id);if(!srcComp?.name)continue;let readableName=`${srcComp.name}_${(_b2=(_a360=srcPort?.name)!=null?_a360:srcPort?.pin_number)!=null?_b2:""}`;readableIdMap[schPort.schematic_port_id]=readableName}return readableIdMap},generateImplicitNetLabels=circuitJson=>{var _a360;let db=cju_default(circuitJson),existingLabels=new Set(db.schematic_net_label.list().map(nl2=>{var _a2100,_b2,_c2,_d2;return`${(_b2=(_a2100=nl2.anchor_position)==null?void 0:_a2100.x)!=null?_b2:nl2.center.x},${(_d2=(_c2=nl2.anchor_position)==null?void 0:_c2.y)!=null?_d2:nl2.center.y}`})),newLabels=[];for(let sp2 of db.schematic_port.list()){let key=`${sp2.center.x},${sp2.center.y}`;if(existingLabels.has(key))continue;let srcPort=db.source_port.get(sp2.source_port_id);if(!srcPort)continue;let srcNet=db.source_net.getWhere({subcircuit_connectivity_map_key:srcPort.subcircuit_connectivity_map_key});if(!srcNet)continue;let srcTrace=db.source_trace.list().find(st4=>{var _a2100;return(_a2100=st4.connected_source_port_ids)==null?void 0:_a2100.includes(sp2.source_port_id)}),schTrace=db.schematic_trace.getWhere({source_trace_id:srcTrace?.source_trace_id}),schematic_net_label2={type:"schematic_net_label",schematic_net_label_id:`netlabel_for_${sp2.schematic_port_id}`,schematic_port_id:sp2.schematic_port_id,text:srcNet.name,source_net_id:srcNet.source_net_id,source_trace_id:srcTrace?.source_trace_id,schematic_trace_id:schTrace?.schematic_trace_id,anchor_position:__spreadValues({},sp2.center),center:__spreadValues({},sp2.center),anchor_side:oppositeSide((_a360=sp2.facing_direction)!=null?_a360:"right")};newLabels.push(schematic_net_label2)}return newLabels},convertCircuitJsonToBpc=(circuitJson,opts={})=>{let g7={boxes:[],pins:[]},schComps=cju_default(circuitJson).schematic_component.list(),schLabels=cju_default(circuitJson).schematic_net_label.list();opts.inferNetLabels&&(schLabels=schLabels.concat(generateImplicitNetLabels(circuitJson)));let readableIdMap=opts.useReadableIds?getReadableIdMap(circuitJson):{},maybeMakeIdReadable=id=>opts.useReadableIds&&readableIdMap[id]?readableIdMap[id]:id,disconnectedCounter=0;for(let schComp of schComps){let box2={boxId:maybeMakeIdReadable(schComp.schematic_component_id),kind:"floating",center:schComp.center};g7.boxes.push(box2);let centerPin={pinId:`${maybeMakeIdReadable(schComp.schematic_component_id)}_center`,color:"component_center",networkId:`center_${schComp.schematic_component_id}`,offset:{x:0,y:0},boxId:maybeMakeIdReadable(schComp.schematic_component_id)};g7.pins.push(centerPin);let schPorts=cju_default(circuitJson).schematic_port.list({schematic_component_id:schComp.schematic_component_id});for(let schPort of schPorts){let srcPort=cju_default(circuitJson).source_port.get(schPort.source_port_id),networkId=srcPort?.subcircuit_connectivity_map_key,color="normal";if(networkId){let srcNet=cju_default(circuitJson).source_net.getWhere({subcircuit_connectivity_map_key:srcPort?.subcircuit_connectivity_map_key});srcNet&&(srcNet.is_power||srcNet.name.startsWith("V"))&&(color="vcc"),srcNet&&(srcNet.is_ground||srcNet.name.startsWith("GND"))&&(color="gnd")}else networkId=`disconnected-${disconnectedCounter++}`,color="not_connected";let pin={pinId:maybeMakeIdReadable(schPort.schematic_port_id),color,networkId,offset:{x:schPort.center.x-box2.center.x,y:schPort.center.y-box2.center.y},boxId:maybeMakeIdReadable(schComp.schematic_component_id)};g7.pins.push(pin)}}for(let schLabel of schLabels){let srcNet=cju_default(circuitJson).source_net.get(schLabel.source_net_id),networkId=srcNet?.subcircuit_connectivity_map_key,color="normal";networkId?(srcNet&&(srcNet.is_power||srcNet.name.startsWith("V"))&&(color="vcc"),srcNet&&(srcNet.is_ground||srcNet.name.startsWith("GND"))&&(color="gnd")):(networkId=`disconnected-${disconnectedCounter++}`,color="not_connected");let netLabelDir=getUnitVecFromAnchorSide(schLabel.anchor_side),netLabelCenter={x:schLabel.anchor_position.x-netLabelDir.x*schLabel.text.length*.18*.5,y:schLabel.anchor_position.y-netLabelDir.y*.18},offset={x:0,y:0};schLabel.anchor_position&&(offset={x:schLabel.anchor_position.x-netLabelCenter.x,y:schLabel.anchor_position.y-netLabelCenter.y});let box2={boxId:maybeMakeIdReadable(schLabel.schematic_net_label_id),kind:"fixed",center:netLabelCenter,boxAttributes:{is_net_label:!0,source_net_id:schLabel.source_net_id,source_trace_id:schLabel.source_trace_id}};g7.boxes.push(box2);let pin={pinId:`${maybeMakeIdReadable(schLabel.schematic_net_label_id)}_pin`,boxId:maybeMakeIdReadable(schLabel.schematic_net_label_id),networkId,color,offset};g7.pins.push(pin),g7.pins.push({pinId:`${maybeMakeIdReadable(schLabel.schematic_net_label_id)}_center`,boxId:maybeMakeIdReadable(schLabel.schematic_net_label_id),networkId:`${maybeMakeIdReadable(schLabel.schematic_net_label_id)}_center`,color:"netlabel_center",offset:{x:0,y:0}})}return g7};var FONT_SIZE_WIDTH_RATIO=.6,FONT_SIZE_HEIGHT_RATIO=1;init_src();var import_svgson=__toESM(require_svgson_umd(),1),import_pretty=__toESM(require_pretty(),1);function translateGraphics(graphics,dx2,dy2){return{...graphics,points:graphics.points?.map(p4=>({...p4,x:p4.x+dx2,y:p4.y+dy2})),lines:graphics.lines?.map(line2=>({...line2,points:line2.points.map(pt4=>({x:pt4.x+dx2,y:pt4.y+dy2}))})),rects:graphics.rects?.map(rect=>({...rect,center:{x:rect.center.x+dx2,y:rect.center.y+dy2}})),circles:graphics.circles?.map(circle2=>({...circle2,center:{x:circle2.center.x+dx2,y:circle2.center.y+dy2}})),texts:graphics.texts?.map(text=>({...text,x:text.x+dx2,y:text.y+dy2}))}}init_src();function getBounds(graphics){let points=[...graphics.points||[],...(graphics.lines||[]).flatMap(line2=>line2.points),...(graphics.rects||[]).flatMap(rect=>{let halfWidth=rect.width/2,halfHeight=rect.height/2;return[{x:rect.center.x-halfWidth,y:rect.center.y-halfHeight},{x:rect.center.x+halfWidth,y:rect.center.y-halfHeight},{x:rect.center.x-halfWidth,y:rect.center.y+halfHeight},{x:rect.center.x+halfWidth,y:rect.center.y+halfHeight}]}),...(graphics.circles||[]).flatMap(circle2=>[{x:circle2.center.x-circle2.radius,y:circle2.center.y},{x:circle2.center.x+circle2.radius,y:circle2.center.y},{x:circle2.center.x,y:circle2.center.y-circle2.radius},{x:circle2.center.x,y:circle2.center.y+circle2.radius}]),...(graphics.texts||[]).flatMap(text=>{let fontSize=text.fontSize??12,width=text.text.length*fontSize*FONT_SIZE_WIDTH_RATIO,height=fontSize*FONT_SIZE_HEIGHT_RATIO,anchor=text.anchorSide??"center",offsetMap={top_left:{dx:0,dy:0},top_center:{dx:-width/2,dy:0},top_right:{dx:-width,dy:0},center_left:{dx:0,dy:-height/2},center:{dx:-width/2,dy:-height/2},center_right:{dx:-width,dy:-height/2},bottom_left:{dx:0,dy:-height},bottom_center:{dx:-width/2,dy:-height},bottom_right:{dx:-width,dy:-height}},{dx:dx2,dy:dy2}=offsetMap[anchor],x02=text.x+dx2,y02=text.y+dy2;return[{x:x02,y:y02},{x:x02+width,y:y02+height}]})];return points.length===0?{minX:-1,maxX:1,minY:-1,maxY:1}:points.reduce((bounds,point6)=>({minX:Math.min(bounds.minX,point6.x),maxX:Math.max(bounds.maxX,point6.x),minY:Math.min(bounds.minY,point6.y),maxY:Math.max(bounds.maxY,point6.y)}),{minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0})}var mergeGraphics=(graphics1,graphics2)=>({...graphics1,rects:[...graphics1.rects??[],...graphics2.rects??[]],points:[...graphics1.points??[],...graphics2.points??[]],lines:[...graphics1.lines??[],...graphics2.lines??[]],circles:[...graphics1.circles??[],...graphics2.circles??[]],texts:[...graphics1.texts??[],...graphics2.texts??[]]});function stackGraphicsHorizontally(graphicsList,opts={}){if(graphicsList.length===0)return{};let giantG=graphicsList[0],prevBounds=getBounds(giantG),baseMinY=prevBounds.minY,boundsList=[prevBounds];for(let i2=1;i2<graphicsList.length;i2++){let newG=graphicsList[i2],bounds=getBounds(newG),prevWidth=prevBounds.maxX-prevBounds.minX,width=bounds.maxX-bounds.minX,padding=(prevWidth+width)/8,dx2=prevBounds.maxX+padding-bounds.minX,dy2=baseMinY-bounds.minY,shifted=translateGraphics(newG,dx2,dy2);giantG=mergeGraphics(giantG,shifted),prevBounds=getBounds(shifted),boundsList.push(prevBounds)}if(opts.titles&&opts.titles.length>0){let overall=getBounds(giantG),fontSize=(overall.maxX-overall.minX)*.025,texts=opts.titles.slice(0,boundsList.length).map((title,idx)=>{let b3=boundsList[idx];return{x:(b3.minX+b3.maxX)/2,y:b3.maxY+fontSize,text:title,fontSize,anchorSide:"bottom_center"}});giantG=mergeGraphics(giantG,{texts})}return giantG}function stackGraphicsVertically(graphicsList,opts={}){if(graphicsList.length===0)return{};let result=graphicsList[0],prevBounds=getBounds(result),baseMinX=prevBounds.minX,boundsList=[prevBounds];for(let i2=1;i2<graphicsList.length;i2++){let g7=graphicsList[i2],bounds=getBounds(g7),prevHeight=prevBounds.maxY-prevBounds.minY,height=bounds.maxY-bounds.minY,padding=(prevHeight+height)/8,dx2=baseMinX-bounds.minX,dy2=prevBounds.minY-padding-bounds.maxY,shifted=translateGraphics(g7,dx2,dy2);result=mergeGraphics(result,shifted),prevBounds=getBounds(shifted),boundsList.push(prevBounds)}if(opts.titles&&opts.titles.length>0){let overall=getBounds(result),fontSize=(overall.maxY-overall.minY)*.025,texts=opts.titles.slice(0,boundsList.length).map((title,idx)=>{let b3=boundsList[idx];return{x:b3.minX-fontSize,y:b3.maxY,text:title,fontSize,anchorSide:"top_right"}});result=mergeGraphics(result,{texts})}return result}var import_debug4=__toESM(require_browser(),1);var center=obj=>obj?"x"in obj&&"y"in obj?obj:"center"in obj?obj.center:{x:(obj.minX+obj.maxX)/2,y:(obj.minY+obj.maxY)/2}:{x:0,y:0},getBoundsOfBpcBox=(graph,boxId)=>{let box2=graph.boxes.find(b3=>b3.boxId===boxId),pins=graph.pins.filter(p4=>p4.boxId===boxId);if(!box2)throw new Error(`Box "${boxId}" not found`);let boxCenter=box2.center??{x:0,y:0},minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let pin of pins)minX=Math.min(minX,pin.offset.x+boxCenter.x),minY=Math.min(minY,pin.offset.y+boxCenter.y),maxX=Math.max(maxX,pin.offset.x+boxCenter.x),maxY=Math.max(maxY,pin.offset.y+boxCenter.y);return{minX,minY,maxX,maxY}},getColorByIndex=(index,total,opacity)=>`hsl(${index*360/total}, 100%, 50%, ${opacity??1})`;var getGraphNetworkIds=g7=>{let networkIds=new Set;for(let pin of g7.pins)networkIds.add(pin.networkId);return Array.from(networkIds)},COLOR_MAPPINGS={not_connected:"rgba(0, 0, 0, 0.2)",normal:"blue",vcc:"orange",gnd:"purple",component_center:"gray"},COMMON_COLORS=["red","green","blue","yellow","purple","orange","brown","gray","black","white"];function hashString(str){let hash=0;for(let i2=0;i2<str.length;i2++)hash=(hash<<5)-hash+str.charCodeAt(i2);return hash}var translateColor=color=>color.startsWith("rgb")||color.startsWith("hsl")||color.startsWith("#")||COMMON_COLORS.includes(color)?color:color in COLOR_MAPPINGS?COLOR_MAPPINGS[color]:getColorByIndex(hashString(color)%50,50),getGraphicsForBpcGraph=(g7,opts)=>{let graphics={points:[],lines:[],rects:[],circles:[],texts:[],coordinateSystem:"cartesian",title:"BPC Graph Graphics"},pinPositions=new Map,positionGroups=new Map;for(let box2 of g7.boxes){let bounds2=getBoundsOfBpcBox(g7,box2.boxId),boundsCenter=center(bounds2);graphics.rects.push({label:box2.boxId,center:boundsCenter,width:bounds2.maxX-bounds2.minX+.1,height:bounds2.maxY-bounds2.minY+.1,fill:"rgba(0, 0, 0, 0.2)"});let boxPins=g7.pins.filter(p4=>p4.boxId===box2.boxId),boxCenter=box2.center??{x:0,y:0};for(let pin of boxPins){let pinPosition={x:pin.offset.x+boxCenter.x,y:pin.offset.y+boxCenter.y},positionKey=`${pinPosition.x.toFixed(6)},${pinPosition.y.toFixed(6)}`;positionGroups.has(positionKey)||positionGroups.set(positionKey,[]),positionGroups.get(positionKey).push({box:box2,pin}),pinPositions.set(`${box2.boxId}.${pin.pinId}`,pinPosition)}}for(let[positionKey,items]of positionGroups){let coordinates=positionKey.split(",").map(Number),baseX=coordinates[0],baseY=coordinates[1];for(let i2=0;i2<items.length;i2++){let item=items[i2],{box:box2,pin}=item,adjustedPosition={x:baseX,y:baseY};if(items.length>1){let boxCenter=box2.center??{x:0,y:0},directionX=boxCenter.x-baseX,directionY=boxCenter.y-baseY,distance8=Math.sqrt(directionX*directionX+directionY*directionY),unitX=0,unitY=0;if(distance8>0)unitX=directionX/distance8,unitY=directionY/distance8;else{let offsetAngle=i2*2*Math.PI/items.length;unitX=Math.cos(offsetAngle),unitY=Math.sin(offsetAngle)}adjustedPosition={x:baseX+.01*unitX,y:baseY+.01*unitY}}pinPositions.set(`${box2.boxId}.${pin.pinId}`,adjustedPosition),graphics.points.push({...adjustedPosition,label:[pin.pinId,pin.color,pin.networkId].join(`
|
|
608
|
+
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,p4)=>sum+p4.x,0),sumY=points.reduce((sum,p4)=>sum+p4.y,0);return{x:sumX/points.length,y:sumY/points.length}}let signedArea2=0,cx2=0,cy2=0;for(let i2=0;i2<points.length;i2++){let p12=points[i2],p22=points[(i2+1)%points.length],crossProduct=p12.x*p22.y-p22.x*p12.y;signedArea2+=crossProduct,cx2+=(p12.x+p22.x)*crossProduct,cy2+=(p12.y+p22.y)*crossProduct}if(signedArea2*=.5,Math.abs(signedArea2)<1e-10){let sumX=points.reduce((sum,p4)=>sum+p4.x,0),sumY=points.reduce((sum,p4)=>sum+p4.y,0);return{x:sumX/points.length,y:sumY/points.length}}return cx2/=6*signedArea2,cy2/=6*signedArea2,{x:cx2,y:cy2}}var PackSolver2=class extends BaseSolver{constructor(packInput){super();__publicField(this,"packInput");__publicField(this,"unpackedComponentQueue",[]);__publicField(this,"packedComponents",[]);__publicField(this,"componentToPack");this.packInput=packInput}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??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:0,pads:firstComponentToPack.pads.map(p4=>({...p4,absoluteCenter:{x:0,y:0}}))};setPackedComponentPadCenters(newPackedComponent);let obstacles=this.packInput.obstacles??[],tooCloseToObstacles=obstacles.some(obs=>{let obsBox={center:{x:obs.absoluteCenter.x,y:obs.absoluteCenter.y},width:obs.width,height:obs.height};return newPackedComponent.pads.some(p4=>{let padBox={center:{x:p4.absoluteCenter.x,y:p4.absoluteCenter.y},width:p4.size.x,height:p4.size.y},{distance:distance8}=computeDistanceBetweenBoxes2(padBox,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=>isPointInPolygon(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=>isPointInPolygon(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:0,pads:this.componentToPack.pads.map(p4=>({...p4,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 i2=0;i2<pads.length;i2++)for(let j4=i2+1;j4<pads.length;j4++){let pad1=pads[i2],pad2=pads[j4];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}},extractPadInfos=(pcbComponent,db,getNetworkId)=>{let out=[],pushPad=({padId,pcbPortId,sx:sx2,sy:sy2,x:x5,y:y5})=>out.push({padId,networkId:getNetworkId(pcbPortId),size:{x:sx2,y:sy2},absoluteCenter:{x:x5,y:y5},pcbPortId});for(let via of db.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 ph2 of db.pcb_plated_hole.list({pcb_component_id:pcbComponent.pcb_component_id}))switch(ph2.shape){case"circle":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.outer_diameter??ph2.hole_diameter??0,sy:ph2.outer_diameter??ph2.hole_diameter??0,x:ph2.x,y:ph2.y});break}case"oval":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.outer_width,sy:ph2.outer_height,x:ph2.x,y:ph2.y});break}case"circular_hole_with_rect_pad":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.rect_pad_width,sy:ph2.rect_pad_height,x:ph2.x,y:ph2.y});break}case"pill":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.outer_width,sy:ph2.outer_height,x:ph2.x,y:ph2.y});break}case"pill_hole_with_rect_pad":{pushPad({padId:ph2.pcb_plated_hole_id,pcbPortId:ph2.pcb_port_id,sx:ph2.rect_pad_width,sy:ph2.rect_pad_height,x:ph2.x,y:ph2.y});break}default:{console.warn(`Unsupported plated hole shape ${ph2.shape}`);break}}for(let sp2 of db.pcb_smtpad.list({pcb_component_id:pcbComponent.pcb_component_id}))switch(sp2.shape){case"rect":{pushPad({padId:sp2.pcb_smtpad_id,pcbPortId:sp2.pcb_port_id,sx:sp2.width??0,sy:sp2.height??0,x:sp2.x,y:sp2.y});break}case"circle":{pushPad({padId:sp2.pcb_smtpad_id,pcbPortId:sp2.pcb_port_id,sx:sp2.radius*2,sy:sp2.radius*2,x:sp2.x,y:sp2.y});break}case"polygon":{if(sp2.points&&sp2.points.length>0){let{minX,maxX,minY,maxY}=getPolygonBoundingBox(sp2.points),width=maxX-minX,height=maxY-minY,centerX=(minX+maxX)/2,centerY=(minY+maxY)/2;pushPad({padId:sp2.pcb_smtpad_id,pcbPortId:sp2.pcb_port_id,sx:width,sy:height,x:centerX,y:centerY})}else console.warn(`Polygon pad ${sp2.pcb_smtpad_id} has no points`);break}}return out},getElementOutsideTree=(db,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 ph2 of db.pcb_plated_hole.list({})){if(!("pcb_component_id"in ph2)||!ph2.pcb_component_id){outside.push(ph2);continue}componentIdsInTree.has(ph2.pcb_component_id)||outside.push(ph2)}return outside},buildPackedComponent=(pcbComponents,componentId,db,getNetworkId,shouldAddInnerObstacles,sourcePortToPadIds=new Map,chipMarginsMap={},isStatic=!1)=>{let padInfos=pcbComponents.flatMap(pc2=>{let pads2=extractPadInfos(pc2,db,getNetworkId),margins=chipMarginsMap[pc2.pcb_component_id];return margins?pads2.map(p4=>({...p4,size:{x:p4.size.x+margins.left+margins.right,y:p4.size.y+margins.top+margins.bottom},absoluteCenter:{x:p4.absoluteCenter.x+(margins.right-margins.left)/2,y:p4.absoluteCenter.y+(margins.top-margins.bottom)/2}})):pads2}),minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let p4 of padInfos)minX=Math.min(minX,p4.absoluteCenter.x-p4.size.x/2),maxX=Math.max(maxX,p4.absoluteCenter.x+p4.size.x/2),minY=Math.min(minY,p4.absoluteCenter.y-p4.size.y/2),maxY=Math.max(maxY,p4.absoluteCenter.y+p4.size.y/2);let center2={x:(minX+maxX)/2,y:(minY+maxY)/2},pads=padInfos.map(p4=>({padId:p4.padId,networkId:p4.networkId,type:"rect",size:p4.size,absoluteCenter:p4.absoluteCenter,offset:{x:p4.absoluteCenter.x-center2.x,y:p4.absoluteCenter.y-center2.y}}));for(let padInfo of padInfos){if(!padInfo.pcbPortId)continue;let sourcePortId=db.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)}return{componentId,isStatic,center:center2,ccwRotationOffset:0,pads}},collectPcbComponents=(node,db)=>{if(node.nodeType==="component"){let pcbId=node.otherChildElements[0]?.pcb_component_id;return pcbId?[db.pcb_component.get(pcbId)]:[]}return node.childNodes.flatMap(n3=>collectPcbComponents(n3,db))},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}),db=cju_default(circuitJson),unnamedCounter=0,sourcePortToPadIds=new Map,elementsOutsideTree=getElementOutsideTree(db,tree),pcbBoard=circuitJson.find(item=>item.type==="pcb_board");pcbBoard&&pcbBoard.outline&&(packOutput.boundaryOutline=pcbBoard.outline);let getNetworkId=pcbPortId=>{if(pcbPortId){let pcbPort=db.pcb_port.get(pcbPortId);if(pcbPort){let sourcePort=db.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(e4=>e4.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??[]);for(let node of topLevelNodes)if(node.nodeType==="component"){let pcbComponent=node.otherChildElements.find(e4=>e4.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,db,getNetworkId,shouldAddInnerObstaclesForComp,sourcePortToPadIds,opts.chipMarginsMap,staticComponentIds.has(pcbComponent.pcb_component_id)))}else if(node.nodeType==="group"){let pcbComps=collectPcbComponents(node,db);if(!pcbComps.length)continue;let compId=node.sourceGroup?.source_group_id??node.sourceGroup?.name??`group_${packOutput.components.length}`;packOutput.components.push(buildPackedComponent(pcbComps,compId,db,getNetworkId,void 0,sourcePortToPadIds,opts.chipMarginsMap,staticComponentIds.has(compId)))}let relativeComponents=topLevelNodes.flatMap(node=>collectRelativeToGroupAnchorComponents(node));for(let pcbComponent of relativeComponents){let padInfos=extractPadInfos(pcbComponent,db,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)if(element.type==="pcb_plated_hole"&&element.shape==="circular_hole_with_rect_pad"){let{rect_pad_height,rect_pad_width,x:x5,y:y5}=element;packOutput.obstacles.push({obstacleId:element.pcb_plated_hole_id,absoluteCenter:{x:x5,y:y5},width:rect_pad_width,height:rect_pad_height})}let weightedConnections=[],seenConnections=new Set,sourceTraces=typeof db.source_trace.list=="function"?db.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(pc2=>({...pc2.isStatic?{...pc2,pads:pc2.pads.map(pad2=>({...pad2}))}:{componentId:pc2.componentId,availableRotationDegrees:pc2.availableRotationDegrees,pads:pc2.pads.map(({absoluteCenter:_ac,...rest})=>rest)}}));return{...packed,components:strippedComponents}};init_dist4();var getBoardPolygon=region=>{let board_edge_margin=region.board_edge_margin??0;if(region.outline&®ion.outline.length>0){let polygon2=new Flatten.Polygon(region.outline.map(p4=>Flatten.point(p4.x,p4.y)));return polygon2.orientation()===Flatten.ORIENTATION.CW&&polygon2.reverse(),polygon2}let{bounds}=region,newBounds={minX:bounds.minX+board_edge_margin,minY:bounds.minY+board_edge_margin,maxX:bounds.maxX-board_edge_margin,maxY:bounds.maxY-board_edge_margin};return newBounds.minX>=newBounds.maxX||newBounds.minY>=newBounds.maxY?new Flatten.Polygon:new Flatten.Polygon(new Flatten.Box(newBounds.minX,newBounds.minY,newBounds.maxX,newBounds.maxY).toPoints())},circleToPolygon=(circle2,numSegments=32)=>{let points=[];for(let i2=0;i2<numSegments;i2++){let angle=i2/numSegments*2*Math.PI;points.push(new Flatten.Point(circle2.center.x+circle2.r*Math.cos(angle),circle2.center.y+circle2.r*Math.sin(angle)))}return new Flatten.Polygon(points)},isRectPad=pad2=>pad2.shape==="rect",isTracePad=pad2=>pad2.shape==="trace",isCircularPad=pad2=>pad2.shape==="circle",isPolygonPad=pad2=>pad2.shape==="polygon",processObstaclesForPour=(pads,pourConnectivityKey,margins,boardOutline)=>{let polygonsToSubtract=[],{padMargin,traceMargin,board_edge_margin,cutoutMargin}=margins;if(boardOutline&&boardOutline.length>0&&board_edge_margin&&board_edge_margin>0){let boardPoly=new Flatten.Polygon(boardOutline.map(p4=>Flatten.point(p4.x,p4.y)));boardPoly.area()<0&&boardPoly.reverse();let vertices=boardPoly.vertices;for(let i2=0;i2<vertices.length;i2++){let p12=vertices[i2===0?vertices.length-1:i2-1],p22=vertices[i2],p32=vertices[(i2+1)%vertices.length];if(!p12||!p22||!p32)continue;let v12=new Flatten.Vector(p12,p22),v22=new Flatten.Vector(p22,p32),crossProduct=v12.cross(v22),circle2=new Flatten.Circle(p22,board_edge_margin);if(polygonsToSubtract.push(circleToPolygon(circle2)),crossProduct<0){let box2=new Flatten.Box(p22.x-board_edge_margin,p22.y-board_edge_margin,p22.x+board_edge_margin,p22.y+board_edge_margin);polygonsToSubtract.push(new Flatten.Polygon(box2.toPoints()))}}for(let i2=0;i2<vertices.length;i2++){let p12=vertices[i2],p22=vertices[(i2+1)%vertices.length];if(!p12||!p22)continue;let segmentLength=Math.hypot(p12.x-p22.x,p12.y-p22.y);if(segmentLength===0)continue;let enlargedWidth=board_edge_margin*2,centerX=(p12.x+p22.x)/2,centerY=(p12.y+p22.y)/2,rotationDeg=Math.atan2(p22.y-p12.y,p22.x-p12.x)*180/Math.PI,w22=segmentLength/2,h22=enlargedWidth/2,angleRad=rotationDeg*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),rotatedCorners=[{x:-w22,y:-h22},{x:w22,y:-h22},{x:w22,y:h22},{x:-w22,y:h22}].map(p4=>({x:centerX+p4.x*cosAngle-p4.y*sinAngle,y:centerY+p4.x*sinAngle+p4.y*cosAngle}));polygonsToSubtract.push(new Flatten.Polygon(rotatedCorners.map(p4=>Flatten.point(p4.x,p4.y))))}}for(let pad2 of pads){if(pad2.connectivityKey===pourConnectivityKey)continue;let isHoleOrCutout=pad2.connectivityKey.startsWith("hole:")||pad2.connectivityKey.startsWith("cutout:");if(isCircularPad(pad2)){let margin=isHoleOrCutout?cutoutMargin??0:padMargin,circle2=new Flatten.Circle(new Flatten.Point(pad2.x,pad2.y),pad2.radius+margin);polygonsToSubtract.push(circleToPolygon(circle2));continue}if(isRectPad(pad2)){let margin=isHoleOrCutout?cutoutMargin??0:padMargin,{bounds}=pad2,b3=new Flatten.Box(bounds.minX-margin,bounds.minY-margin,bounds.maxX+margin,bounds.maxY+margin);polygonsToSubtract.push(new Flatten.Polygon(b3.toPoints()));continue}if(isPolygonPad(pad2)){let margin=isHoleOrCutout?cutoutMargin??0:0,seen=new Set,uniquePoints=pad2.points.filter(p4=>{let key=`${p4.x},${p4.y}`;return seen.has(key)?!1:(seen.add(key),!0)});if(uniquePoints.length<3)continue;let polygon2=new Flatten.Polygon(uniquePoints.map(p4=>Flatten.point(p4.x,p4.y)));if(Math.abs(polygon2.area())<1e-9)continue;if(margin<=0){polygonsToSubtract.push(polygon2);continue}polygon2.area()>0&&polygon2.reverse();let offsetLines=[],polygonVertices=polygon2.vertices;for(let i2=0;i2<polygonVertices.length;i2++){let p12=polygonVertices[i2],p22=polygonVertices[(i2+1)%polygonVertices.length],segment2=Flatten.segment(p12,p22);if(segment2.length===0)continue;let line2=Flatten.line(segment2.start,segment2.end),norm=line2.norm,offsetLine=line2.translate(norm.multiply(-margin));offsetLines.push(offsetLine)}let newPolygonPoints=[];for(let i2=0;i2<offsetLines.length;i2++){let line1=offsetLines[i2],line2=offsetLines[(i2+1)%offsetLines.length],ip2=line1.intersect(line2);ip2.length>0&&newPolygonPoints.push(ip2[0])}newPolygonPoints.length>=3&&polygonsToSubtract.push(new Flatten.Polygon(newPolygonPoints));continue}if(isTracePad(pad2)){for(let segment2 of pad2.segments){let circle2=new Flatten.Circle(new Flatten.Point(segment2.x,segment2.y),pad2.width/2+traceMargin);polygonsToSubtract.push(circleToPolygon(circle2))}for(let i2=0;i2<pad2.segments.length-1;i2++){let p12=pad2.segments[i2],p22=pad2.segments[i2+1];if(!p12||!p22)continue;let segmentLength=Math.hypot(p12.x-p22.x,p12.y-p22.y);if(segmentLength===0)continue;let enlargedWidth=pad2.width+traceMargin*2,centerX=(p12.x+p22.x)/2,centerY=(p12.y+p22.y)/2,rotationDeg=Math.atan2(p22.y-p12.y,p22.x-p12.x)*180/Math.PI,w22=segmentLength/2,h22=enlargedWidth/2,angleRad=rotationDeg*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),rotatedCorners=[{x:-w22,y:-h22},{x:w22,y:-h22},{x:w22,y:h22},{x:-w22,y:h22}].map(p4=>({x:centerX+p4.x*cosAngle-p4.y*sinAngle,y:centerY+p4.x*sinAngle+p4.y*cosAngle}));polygonsToSubtract.push(new Flatten.Polygon(rotatedCorners.map(p4=>Flatten.point(p4.x,p4.y))))}}}return{polygonsToSubtract}},faceToVertices=face=>face.edges.map(e4=>{let pt4={x:e4.start.x,y:e4.start.y};if(e4.isArc){let bulge=Math.tan(e4.shape.sweep/4);Math.abs(bulge)>1e-9&&(pt4.bulge=bulge)}return pt4}),generateBRep=pourPolygons=>{let brep_shapes=[],polygons=Array.isArray(pourPolygons)?pourPolygons:[pourPolygons];for(let p4 of polygons){let islands=p4.splitToIslands();for(let island of islands){if(island.isEmpty())continue;let faces=[...island.faces],outer_face_ccw=faces.find(f2=>f2.orientation()===Flatten.ORIENTATION.CCW),inner_faces_cw=faces.filter(f2=>f2.orientation()===Flatten.ORIENTATION.CW);if(!outer_face_ccw)continue;outer_face_ccw.reverse();let outer_ring_vertices=faceToVertices(outer_face_ccw),inner_rings=inner_faces_cw.map(f2=>(f2.reverse(),{vertices:faceToVertices(f2)}));brep_shapes.push({outer_ring:{vertices:outer_ring_vertices},inner_rings})}}return brep_shapes},CopperPourPipelineSolver=class extends BasePipelineSolver{constructor(input2){super(input2);__publicField(this,"pipelineDef",[]);this.input=input2}getSolverName(){return"CopperPourPipelineSolver"}getOutput(){let brep_shapes=[];for(let region of this.input.regionsForPour){let boardPolygon=getBoardPolygon(region),padsForLayer=this.input.pads.filter(p4=>p4.layer===region.layer),{polygonsToSubtract}=processObstaclesForPour(padsForLayer,region.connectivityKey,{padMargin:region.padMargin,traceMargin:region.traceMargin,board_edge_margin:region.board_edge_margin,cutoutMargin:region.cutout_margin},region.outline),pourPolygons=boardPolygon;for(let poly of polygonsToSubtract){let currentPolys=Array.isArray(pourPolygons)?pourPolygons:[pourPolygons],nextPolys=[];for(let p4 of currentPolys){let result=Flatten.BooleanOperations.subtract(p4,poly);result&&(Array.isArray(result)?nextPolys.push(...result.filter(r4=>!r4.isEmpty())):result.isEmpty()||nextPolys.push(result))}pourPolygons=nextPolys}let new_breps=generateBRep(pourPolygons);brep_shapes.push(...new_breps)}return{brep_shapes}}},convertCircuitJsonToInputProblem=(circuitJson,options)=>{let pcb_board2=circuitJson.find(e4=>e4.type==="pcb_board");if(!pcb_board2)throw new Error("No pcb_board found in circuit json");let connectivityMap=getFullConnectivityMapFromCircuitJson(circuitJson),pads=[];for(let elm of circuitJson)if(elm.type==="pcb_smtpad"){let smtpad2=elm;if(smtpad2.layer!==options.layer)continue;let connectivityKey;connectivityKey=connectivityMap.getNetConnectedToId(smtpad2.pcb_smtpad_id),connectivityKey||(connectivityKey=`unconnected:${smtpad2.pcb_smtpad_id}`),smtpad2.shape==="rect"?pads.push({shape:"rect",padId:smtpad2.pcb_smtpad_id,layer:smtpad2.layer,connectivityKey,bounds:{minX:smtpad2.x-smtpad2.width/2,minY:smtpad2.y-smtpad2.height/2,maxX:smtpad2.x+smtpad2.width/2,maxY:smtpad2.y+smtpad2.height/2}}):smtpad2.shape==="circle"&&pads.push({shape:"circle",padId:smtpad2.pcb_smtpad_id,layer:smtpad2.layer,connectivityKey,x:smtpad2.x,y:smtpad2.y,radius:smtpad2.radius})}else if(elm.type==="pcb_plated_hole"){let platedHole=elm;if(platedHole.shape!=="circle"||!platedHole.layers.includes(options.layer))continue;let connectivityKey=connectivityMap.getNetConnectedToId(platedHole.pcb_plated_hole_id);connectivityKey||(connectivityKey=`unconnected-plated-hole:${platedHole.pcb_plated_hole_id}`),pads.push({shape:"circle",padId:platedHole.pcb_plated_hole_id,layer:options.layer,connectivityKey,x:platedHole.x,y:platedHole.y,radius:platedHole.outer_diameter/2})}else if(elm.type==="pcb_hole"){let hole=elm;if(hole.hole_shape!=="circle")continue;pads.push({shape:"circle",padId:hole.pcb_hole_id,layer:options.layer,connectivityKey:`hole:${hole.pcb_hole_id}`,x:hole.x,y:hole.y,radius:hole.hole_diameter/2})}else if(elm.type==="pcb_cutout"){let cutout=elm;cutout.shape==="rect"?pads.push({shape:"rect",padId:cutout.pcb_cutout_id,layer:options.layer,connectivityKey:`cutout:${cutout.pcb_cutout_id}`,bounds:{minX:cutout.center.x-cutout.width/2,minY:cutout.center.y-cutout.height/2,maxX:cutout.center.x+cutout.width/2,maxY:cutout.center.y+cutout.height/2}}):cutout.shape==="circle"?pads.push({shape:"circle",padId:cutout.pcb_cutout_id,layer:options.layer,connectivityKey:`cutout:${cutout.pcb_cutout_id}`,x:cutout.center.x,y:cutout.center.y,radius:cutout.radius}):cutout.shape==="polygon"&&pads.push({shape:"polygon",padId:cutout.pcb_cutout_id,layer:options.layer,connectivityKey:`cutout:${cutout.pcb_cutout_id}`,points:cutout.points})}else if(elm.type==="pcb_via"){let via=elm;if(!via.layers.includes(options.layer))continue;let connectivityKey=connectivityMap.getNetConnectedToId(via.pcb_via_id)??`unconnected-via:${via.pcb_via_id}`;pads.push({shape:"circle",padId:via.pcb_via_id,layer:options.layer,connectivityKey,x:via.x,y:via.y,radius:via.outer_diameter/2})}else if(elm.type==="pcb_trace"){let trace=elm,connectivityKey=connectivityMap.getNetConnectedToId(trace.pcb_trace_id);if(!connectivityKey)continue;let currentSegmentGroup=[],currentWidth=null,commitGroup=()=>{currentSegmentGroup.length>1&&pads.push({shape:"trace",padId:`${trace.pcb_trace_id}-${pads.length}`,layer:options.layer,connectivityKey,segments:currentSegmentGroup,width:currentWidth}),currentSegmentGroup=[],currentWidth=null};for(let r4 of trace.route){let ri3=r4;ri3.route_type==="wire"&&ri3.layer===options.layer?(currentWidth===null&&(currentWidth=ri3.width),currentSegmentGroup.push({x:ri3.x,y:ri3.y})):commitGroup()}commitGroup()}let{width,height}=pcb_board2,outline=options.outline??pcb_board2.outline,bounds;if(outline&&outline.length>0){let xs3=outline.map(p4=>p4.x),ys3=outline.map(p4=>p4.y);bounds={minX:Math.min(...xs3),minY:Math.min(...ys3),maxX:Math.max(...xs3),maxY:Math.max(...ys3)}}else bounds={minX:-width/2,minY:-height/2,maxX:width/2,maxY:height/2};let regionsForPour=[{shape:"rect",layer:options.layer,bounds,outline,connectivityKey:options.pour_connectivity_key,padMargin:options.pad_margin,traceMargin:options.trace_margin,board_edge_margin:options.board_edge_margin??0,cutout_margin:options.cutout_margin}];return{pads,regionsForPour}};init_dist();var import_debug10=__toESM(require_browser(),1);init_dist6();init_dist6();init_dist6();init_dist6();init_dist6();init_dist4();init_dist6();init_dist6();init_dist6();var __defProp3=Object.defineProperty,__getOwnPropSymbols=Object.getOwnPropertySymbols,__hasOwnProp2=Object.prototype.hasOwnProperty,__propIsEnum=Object.prototype.propertyIsEnumerable,__defNormalProp2=(obj,key,value)=>key in obj?__defProp3(obj,key,{enumerable:!0,configurable:!0,writable:!0,value}):obj[key]=value,__spreadValues=(a2,b3)=>{for(var prop in b3||(b3={}))__hasOwnProp2.call(b3,prop)&&__defNormalProp2(a2,prop,b3[prop]);if(__getOwnPropSymbols)for(var prop of __getOwnPropSymbols(b3))__propIsEnum.call(b3,prop)&&__defNormalProp2(a2,prop,b3[prop]);return a2},getUnitVecFromAnchorSide=anchorSide=>{switch(anchorSide){case"left":return{x:-1,y:0};case"right":return{x:1,y:0};case"top":return{x:0,y:1};case"bottom":return{x:0,y:-1}}},getReadableIdMap=circuitJson=>{var _a360,_b2;let schComps=cju_default(circuitJson).schematic_component.list(),schLabels=cju_default(circuitJson).schematic_net_label.list(),schPorts=cju_default(circuitJson).schematic_port.list(),readableIdMap={};for(let schComp of schComps){let srcComp=cju_default(circuitJson).source_component.get(schComp.source_component_id);readableIdMap[schComp.schematic_component_id]=srcComp?.name}for(let schLabel of schLabels){let srcNet=cju_default(circuitJson).source_net.get(schLabel.source_net_id);if(!srcNet?.name)continue;let index=0;for(;Object.values(readableIdMap).includes(`NL_${srcNet.name}${index}`);)index++;readableIdMap[schLabel.schematic_net_label_id]=`NL_${srcNet.name}${index}`}for(let schPort of schPorts){let srcPort=cju_default(circuitJson).source_port.get(schPort.source_port_id);if(!srcPort)continue;let srcComp=cju_default(circuitJson).source_component.get(srcPort.source_component_id);if(!srcComp?.name)continue;let readableName=`${srcComp.name}_${(_b2=(_a360=srcPort?.name)!=null?_a360:srcPort?.pin_number)!=null?_b2:""}`;readableIdMap[schPort.schematic_port_id]=readableName}return readableIdMap},generateImplicitNetLabels=circuitJson=>{var _a360;let db=cju_default(circuitJson),existingLabels=new Set(db.schematic_net_label.list().map(nl2=>{var _a2100,_b2,_c2,_d2;return`${(_b2=(_a2100=nl2.anchor_position)==null?void 0:_a2100.x)!=null?_b2:nl2.center.x},${(_d2=(_c2=nl2.anchor_position)==null?void 0:_c2.y)!=null?_d2:nl2.center.y}`})),newLabels=[];for(let sp2 of db.schematic_port.list()){let key=`${sp2.center.x},${sp2.center.y}`;if(existingLabels.has(key))continue;let srcPort=db.source_port.get(sp2.source_port_id);if(!srcPort)continue;let srcNet=db.source_net.getWhere({subcircuit_connectivity_map_key:srcPort.subcircuit_connectivity_map_key});if(!srcNet)continue;let srcTrace=db.source_trace.list().find(st4=>{var _a2100;return(_a2100=st4.connected_source_port_ids)==null?void 0:_a2100.includes(sp2.source_port_id)}),schTrace=db.schematic_trace.getWhere({source_trace_id:srcTrace?.source_trace_id}),schematic_net_label2={type:"schematic_net_label",schematic_net_label_id:`netlabel_for_${sp2.schematic_port_id}`,schematic_port_id:sp2.schematic_port_id,text:srcNet.name,source_net_id:srcNet.source_net_id,source_trace_id:srcTrace?.source_trace_id,schematic_trace_id:schTrace?.schematic_trace_id,anchor_position:__spreadValues({},sp2.center),center:__spreadValues({},sp2.center),anchor_side:oppositeSide((_a360=sp2.facing_direction)!=null?_a360:"right")};newLabels.push(schematic_net_label2)}return newLabels},convertCircuitJsonToBpc=(circuitJson,opts={})=>{let g7={boxes:[],pins:[]},schComps=cju_default(circuitJson).schematic_component.list(),schLabels=cju_default(circuitJson).schematic_net_label.list();opts.inferNetLabels&&(schLabels=schLabels.concat(generateImplicitNetLabels(circuitJson)));let readableIdMap=opts.useReadableIds?getReadableIdMap(circuitJson):{},maybeMakeIdReadable=id=>opts.useReadableIds&&readableIdMap[id]?readableIdMap[id]:id,disconnectedCounter=0;for(let schComp of schComps){let box2={boxId:maybeMakeIdReadable(schComp.schematic_component_id),kind:"floating",center:schComp.center};g7.boxes.push(box2);let centerPin={pinId:`${maybeMakeIdReadable(schComp.schematic_component_id)}_center`,color:"component_center",networkId:`center_${schComp.schematic_component_id}`,offset:{x:0,y:0},boxId:maybeMakeIdReadable(schComp.schematic_component_id)};g7.pins.push(centerPin);let schPorts=cju_default(circuitJson).schematic_port.list({schematic_component_id:schComp.schematic_component_id});for(let schPort of schPorts){let srcPort=cju_default(circuitJson).source_port.get(schPort.source_port_id),networkId=srcPort?.subcircuit_connectivity_map_key,color="normal";if(networkId){let srcNet=cju_default(circuitJson).source_net.getWhere({subcircuit_connectivity_map_key:srcPort?.subcircuit_connectivity_map_key});srcNet&&(srcNet.is_power||srcNet.name.startsWith("V"))&&(color="vcc"),srcNet&&(srcNet.is_ground||srcNet.name.startsWith("GND"))&&(color="gnd")}else networkId=`disconnected-${disconnectedCounter++}`,color="not_connected";let pin={pinId:maybeMakeIdReadable(schPort.schematic_port_id),color,networkId,offset:{x:schPort.center.x-box2.center.x,y:schPort.center.y-box2.center.y},boxId:maybeMakeIdReadable(schComp.schematic_component_id)};g7.pins.push(pin)}}for(let schLabel of schLabels){let srcNet=cju_default(circuitJson).source_net.get(schLabel.source_net_id),networkId=srcNet?.subcircuit_connectivity_map_key,color="normal";networkId?(srcNet&&(srcNet.is_power||srcNet.name.startsWith("V"))&&(color="vcc"),srcNet&&(srcNet.is_ground||srcNet.name.startsWith("GND"))&&(color="gnd")):(networkId=`disconnected-${disconnectedCounter++}`,color="not_connected");let netLabelDir=getUnitVecFromAnchorSide(schLabel.anchor_side),netLabelCenter={x:schLabel.anchor_position.x-netLabelDir.x*schLabel.text.length*.18*.5,y:schLabel.anchor_position.y-netLabelDir.y*.18},offset={x:0,y:0};schLabel.anchor_position&&(offset={x:schLabel.anchor_position.x-netLabelCenter.x,y:schLabel.anchor_position.y-netLabelCenter.y});let box2={boxId:maybeMakeIdReadable(schLabel.schematic_net_label_id),kind:"fixed",center:netLabelCenter,boxAttributes:{is_net_label:!0,source_net_id:schLabel.source_net_id,source_trace_id:schLabel.source_trace_id}};g7.boxes.push(box2);let pin={pinId:`${maybeMakeIdReadable(schLabel.schematic_net_label_id)}_pin`,boxId:maybeMakeIdReadable(schLabel.schematic_net_label_id),networkId,color,offset};g7.pins.push(pin),g7.pins.push({pinId:`${maybeMakeIdReadable(schLabel.schematic_net_label_id)}_center`,boxId:maybeMakeIdReadable(schLabel.schematic_net_label_id),networkId:`${maybeMakeIdReadable(schLabel.schematic_net_label_id)}_center`,color:"netlabel_center",offset:{x:0,y:0}})}return g7};var FONT_SIZE_WIDTH_RATIO=.6,FONT_SIZE_HEIGHT_RATIO=1;init_src();var import_svgson=__toESM(require_svgson_umd(),1),import_pretty=__toESM(require_pretty(),1);function translateGraphics(graphics,dx2,dy2){return{...graphics,points:graphics.points?.map(p4=>({...p4,x:p4.x+dx2,y:p4.y+dy2})),lines:graphics.lines?.map(line2=>({...line2,points:line2.points.map(pt4=>({x:pt4.x+dx2,y:pt4.y+dy2}))})),rects:graphics.rects?.map(rect=>({...rect,center:{x:rect.center.x+dx2,y:rect.center.y+dy2}})),circles:graphics.circles?.map(circle2=>({...circle2,center:{x:circle2.center.x+dx2,y:circle2.center.y+dy2}})),texts:graphics.texts?.map(text=>({...text,x:text.x+dx2,y:text.y+dy2}))}}init_src();function getBounds(graphics){let points=[...graphics.points||[],...(graphics.lines||[]).flatMap(line2=>line2.points),...(graphics.rects||[]).flatMap(rect=>{let halfWidth=rect.width/2,halfHeight=rect.height/2;return[{x:rect.center.x-halfWidth,y:rect.center.y-halfHeight},{x:rect.center.x+halfWidth,y:rect.center.y-halfHeight},{x:rect.center.x-halfWidth,y:rect.center.y+halfHeight},{x:rect.center.x+halfWidth,y:rect.center.y+halfHeight}]}),...(graphics.circles||[]).flatMap(circle2=>[{x:circle2.center.x-circle2.radius,y:circle2.center.y},{x:circle2.center.x+circle2.radius,y:circle2.center.y},{x:circle2.center.x,y:circle2.center.y-circle2.radius},{x:circle2.center.x,y:circle2.center.y+circle2.radius}]),...(graphics.texts||[]).flatMap(text=>{let fontSize=text.fontSize??12,width=text.text.length*fontSize*FONT_SIZE_WIDTH_RATIO,height=fontSize*FONT_SIZE_HEIGHT_RATIO,anchor=text.anchorSide??"center",offsetMap={top_left:{dx:0,dy:0},top_center:{dx:-width/2,dy:0},top_right:{dx:-width,dy:0},center_left:{dx:0,dy:-height/2},center:{dx:-width/2,dy:-height/2},center_right:{dx:-width,dy:-height/2},bottom_left:{dx:0,dy:-height},bottom_center:{dx:-width/2,dy:-height},bottom_right:{dx:-width,dy:-height}},{dx:dx2,dy:dy2}=offsetMap[anchor],x02=text.x+dx2,y02=text.y+dy2;return[{x:x02,y:y02},{x:x02+width,y:y02+height}]})];return points.length===0?{minX:-1,maxX:1,minY:-1,maxY:1}:points.reduce((bounds,point6)=>({minX:Math.min(bounds.minX,point6.x),maxX:Math.max(bounds.maxX,point6.x),minY:Math.min(bounds.minY,point6.y),maxY:Math.max(bounds.maxY,point6.y)}),{minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0})}var mergeGraphics=(graphics1,graphics2)=>({...graphics1,rects:[...graphics1.rects??[],...graphics2.rects??[]],points:[...graphics1.points??[],...graphics2.points??[]],lines:[...graphics1.lines??[],...graphics2.lines??[]],circles:[...graphics1.circles??[],...graphics2.circles??[]],texts:[...graphics1.texts??[],...graphics2.texts??[]]});function stackGraphicsHorizontally(graphicsList,opts={}){if(graphicsList.length===0)return{};let giantG=graphicsList[0],prevBounds=getBounds(giantG),baseMinY=prevBounds.minY,boundsList=[prevBounds];for(let i2=1;i2<graphicsList.length;i2++){let newG=graphicsList[i2],bounds=getBounds(newG),prevWidth=prevBounds.maxX-prevBounds.minX,width=bounds.maxX-bounds.minX,padding=(prevWidth+width)/8,dx2=prevBounds.maxX+padding-bounds.minX,dy2=baseMinY-bounds.minY,shifted=translateGraphics(newG,dx2,dy2);giantG=mergeGraphics(giantG,shifted),prevBounds=getBounds(shifted),boundsList.push(prevBounds)}if(opts.titles&&opts.titles.length>0){let overall=getBounds(giantG),fontSize=(overall.maxX-overall.minX)*.025,texts=opts.titles.slice(0,boundsList.length).map((title,idx)=>{let b3=boundsList[idx];return{x:(b3.minX+b3.maxX)/2,y:b3.maxY+fontSize,text:title,fontSize,anchorSide:"bottom_center"}});giantG=mergeGraphics(giantG,{texts})}return giantG}function stackGraphicsVertically(graphicsList,opts={}){if(graphicsList.length===0)return{};let result=graphicsList[0],prevBounds=getBounds(result),baseMinX=prevBounds.minX,boundsList=[prevBounds];for(let i2=1;i2<graphicsList.length;i2++){let g7=graphicsList[i2],bounds=getBounds(g7),prevHeight=prevBounds.maxY-prevBounds.minY,height=bounds.maxY-bounds.minY,padding=(prevHeight+height)/8,dx2=baseMinX-bounds.minX,dy2=prevBounds.minY-padding-bounds.maxY,shifted=translateGraphics(g7,dx2,dy2);result=mergeGraphics(result,shifted),prevBounds=getBounds(shifted),boundsList.push(prevBounds)}if(opts.titles&&opts.titles.length>0){let overall=getBounds(result),fontSize=(overall.maxY-overall.minY)*.025,texts=opts.titles.slice(0,boundsList.length).map((title,idx)=>{let b3=boundsList[idx];return{x:b3.minX-fontSize,y:b3.maxY,text:title,fontSize,anchorSide:"top_right"}});result=mergeGraphics(result,{texts})}return result}var import_debug4=__toESM(require_browser(),1);var center=obj=>obj?"x"in obj&&"y"in obj?obj:"center"in obj?obj.center:{x:(obj.minX+obj.maxX)/2,y:(obj.minY+obj.maxY)/2}:{x:0,y:0},getBoundsOfBpcBox=(graph,boxId)=>{let box2=graph.boxes.find(b3=>b3.boxId===boxId),pins=graph.pins.filter(p4=>p4.boxId===boxId);if(!box2)throw new Error(`Box "${boxId}" not found`);let boxCenter=box2.center??{x:0,y:0},minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let pin of pins)minX=Math.min(minX,pin.offset.x+boxCenter.x),minY=Math.min(minY,pin.offset.y+boxCenter.y),maxX=Math.max(maxX,pin.offset.x+boxCenter.x),maxY=Math.max(maxY,pin.offset.y+boxCenter.y);return{minX,minY,maxX,maxY}},getColorByIndex=(index,total,opacity)=>`hsl(${index*360/total}, 100%, 50%, ${opacity??1})`;var getGraphNetworkIds=g7=>{let networkIds=new Set;for(let pin of g7.pins)networkIds.add(pin.networkId);return Array.from(networkIds)},COLOR_MAPPINGS={not_connected:"rgba(0, 0, 0, 0.2)",normal:"blue",vcc:"orange",gnd:"purple",component_center:"gray"},COMMON_COLORS=["red","green","blue","yellow","purple","orange","brown","gray","black","white"];function hashString(str){let hash=0;for(let i2=0;i2<str.length;i2++)hash=(hash<<5)-hash+str.charCodeAt(i2);return hash}var translateColor=color=>color.startsWith("rgb")||color.startsWith("hsl")||color.startsWith("#")||COMMON_COLORS.includes(color)?color:color in COLOR_MAPPINGS?COLOR_MAPPINGS[color]:getColorByIndex(hashString(color)%50,50),getGraphicsForBpcGraph=(g7,opts)=>{let graphics={points:[],lines:[],rects:[],circles:[],texts:[],coordinateSystem:"cartesian",title:"BPC Graph Graphics"},pinPositions=new Map,positionGroups=new Map;for(let box2 of g7.boxes){let bounds2=getBoundsOfBpcBox(g7,box2.boxId),boundsCenter=center(bounds2);graphics.rects.push({label:box2.boxId,center:boundsCenter,width:bounds2.maxX-bounds2.minX+.1,height:bounds2.maxY-bounds2.minY+.1,fill:"rgba(0, 0, 0, 0.2)"});let boxPins=g7.pins.filter(p4=>p4.boxId===box2.boxId),boxCenter=box2.center??{x:0,y:0};for(let pin of boxPins){let pinPosition={x:pin.offset.x+boxCenter.x,y:pin.offset.y+boxCenter.y},positionKey=`${pinPosition.x.toFixed(6)},${pinPosition.y.toFixed(6)}`;positionGroups.has(positionKey)||positionGroups.set(positionKey,[]),positionGroups.get(positionKey).push({box:box2,pin}),pinPositions.set(`${box2.boxId}.${pin.pinId}`,pinPosition)}}for(let[positionKey,items]of positionGroups){let coordinates=positionKey.split(",").map(Number),baseX=coordinates[0],baseY=coordinates[1];for(let i2=0;i2<items.length;i2++){let item=items[i2],{box:box2,pin}=item,adjustedPosition={x:baseX,y:baseY};if(items.length>1){let boxCenter=box2.center??{x:0,y:0},directionX=boxCenter.x-baseX,directionY=boxCenter.y-baseY,distance8=Math.sqrt(directionX*directionX+directionY*directionY),unitX=0,unitY=0;if(distance8>0)unitX=directionX/distance8,unitY=directionY/distance8;else{let offsetAngle=i2*2*Math.PI/items.length;unitX=Math.cos(offsetAngle),unitY=Math.sin(offsetAngle)}adjustedPosition={x:baseX+.01*unitX,y:baseY+.01*unitY}}pinPositions.set(`${box2.boxId}.${pin.pinId}`,adjustedPosition),graphics.points.push({...adjustedPosition,label:[pin.pinId,pin.color,pin.networkId].join(`
|
|
609
609
|
`),color:translateColor(pin.color)})}}let networks=getGraphNetworkIds(g7);for(let ni3=0;ni3<networks.length;ni3++){let networkId=networks[ni3],networkColor=getColorByIndex(ni3,networks.length,.5),pinsInNetworkWithPosition=g7.pins.filter(p4=>p4.networkId===networkId).map(pin=>({pin,position:pinPositions.get(`${pin.boxId}.${pin.pinId}`)}));for(let i2=0;i2<pinsInNetworkWithPosition.length;i2++){let{position:pos1}=pinsInNetworkWithPosition[i2];for(let j4=i2+1;j4<pinsInNetworkWithPosition.length;j4++){let{position:pos2}=pinsInNetworkWithPosition[j4];graphics.lines.push({points:[pos1,pos2],strokeColor:opts?.grayNetworks?"rgba(0, 0, 0, 0.05)":networkColor})}}}let bounds=getBounds(graphics);return opts?.title&&(graphics.title=opts.title,graphics.texts.push({text:opts.title,x:bounds.minX,y:bounds.maxY,fontSize:(bounds.maxY-bounds.minY)*.05,anchorSide:"bottom_left"})),opts?.caption&&graphics.texts.push({text:opts.caption,x:bounds.minX,y:bounds.minY,fontSize:(bounds.maxY-bounds.minY)*.05,anchorSide:"top_left"}),graphics},getPinPosition=(g7,boxId,pinId)=>{let pin=g7.pins.find(p4=>p4.pinId===pinId&&p4.boxId===boxId);if(!pin)throw new Error(`Pin "${pinId}" not found`);let box2=g7.boxes.find(b3=>b3.boxId===pin.boxId);if(!box2)throw new Error(`Box "${pin.boxId}" not found`);let boxCenter=box2.center??{x:0,y:0};return{x:pin.offset.x+boxCenter.x,y:pin.offset.y+boxCenter.y}},getPinDirectionOrThrow=(g7,boxIdOrBox,pinIdOrPin)=>{let pin=typeof pinIdOrPin=="string"?g7.pins.find(p4=>p4.pinId===pinIdOrPin&&p4.boxId===boxIdOrBox):pinIdOrPin;if(!pin)throw new Error(`Pin not found "${pinIdOrPin}"`);if(!(typeof boxIdOrBox=="string"?g7.boxes.find(b3=>b3.boxId===boxIdOrBox):boxIdOrBox))throw new Error(`Box not found for pin "${pinIdOrPin}" (looked for "${pin.boxId}")`);let bounds=getBoundsOfBpcBox(g7,pin.boxId),pinPosition=getPinPosition(g7,pin.boxId,pin.pinId),width=bounds.maxX-bounds.minX,height=bounds.maxY-bounds.minY;if(width===0&&height===0)return Math.abs(pin.offset.x)>Math.abs(pin.offset.y)?pin.offset.x>0?"x+":"x-":pin.offset.y>0?"y+":"y-";if(width===0){if(Math.abs(pinPosition.y-bounds.minY)<1e-4)return"y-";if(Math.abs(pinPosition.y-bounds.maxY)<1e-4)return"y+"}if(height===0){if(Math.abs(pinPosition.x-bounds.minX)<1e-4)return"x-";if(Math.abs(pinPosition.x-bounds.maxX)<1e-4)return"x+"}let onLeftEdge=Math.abs(pinPosition.x-bounds.minX)<1e-4,onRightEdge=Math.abs(pinPosition.x-bounds.maxX)<1e-4,onBottomEdge=Math.abs(pinPosition.y-bounds.minY)<1e-4,onTopEdge=Math.abs(pinPosition.y-bounds.maxY)<1e-4;if((onLeftEdge||onRightEdge)&&(onBottomEdge||onTopEdge))return pin.offset.x>0?"x+":"x-";if(onLeftEdge)return"x-";if(onRightEdge)return"x+";if(onBottomEdge)return"y-";if(onTopEdge)return"y+";throw new Error(`Pin "${pin.pinId}" not on the edge of the box "${pin.boxId}" so we couldn't determine the direction`)},getPinDirection=(g7,boxIdOrBox,pinIdOrPin)=>{try{return getPinDirectionOrThrow(g7,boxIdOrBox,pinIdOrPin)}catch{return null}};var getAdjacencyMatrixFromFlatBpcGraph=flatBpcGraph=>{let nodeIdToIndex=new Map,indexMapping=[];flatBpcGraph.nodes.forEach((node,idx)=>{nodeIdToIndex.set(node.id,idx),indexMapping.push(node.id)});let N6=flatBpcGraph.nodes.length,matrix2=Array.from({length:N6},()=>Array.from({length:N6},()=>0));for(let[id1,id2]of flatBpcGraph.undirectedEdges){let i2=nodeIdToIndex.get(id1),j4=nodeIdToIndex.get(id2);i2!==void 0&&j4!==void 0&&i2!==j4&&(matrix2[i2][j4]=1,matrix2[j4][i2]=1)}for(let i2=0;i2<N6;++i2)matrix2[i2][i2]=1;return{matrix:matrix2,mapping:nodeIdToIndex,indexMapping}};var convertToFlatBpcGraph=mixed=>{var _a360;let nodes=[],undirectedEdges=[],boxCenterMap=new Map;for(let box2 of mixed.boxes)box2.kind,boxCenterMap.set(box2.boxId,box2.center),nodes.push({id:box2.boxId,boxId:box2.boxId,color:"box",x:box2.center?.x,y:box2.center?.y});let pinsByNetwork={};for(let pin of mixed.pins){let nodeId=`${pin.boxId}-${pin.pinId}`,bCenter=boxCenterMap.get(pin.boxId);nodes.push({id:nodeId,boxId:pin.boxId,pinId:pin.pinId,color:pin.color,x:bCenter?bCenter.x+pin.offset.x:void 0,y:bCenter?bCenter.y+pin.offset.y:void 0}),pinsByNetwork[_a360=pin.networkId]??(pinsByNetwork[_a360]=[]),pinsByNetwork[pin.networkId].push(nodeId)}for(let nodeIds of Object.values(pinsByNetwork))for(let i2=0;i2<nodeIds.length;i2++)for(let j4=i2+1;j4<nodeIds.length;j4++)undirectedEdges.push([nodeIds[i2],nodeIds[j4]]);for(let box2 of mixed.boxes)for(let pin of mixed.pins)pin.boxId===box2.boxId&&undirectedEdges.push([box2.boxId,`${box2.boxId}-${pin.pinId}`]);return{nodes,undirectedEdges}},wlFeatureVec=(adjMatrix,K4,opts={})=>{let n3=adjMatrix.length;if(adjMatrix.some(row=>row.length!==n3))throw new Error("adjMatrix must be square");let colors=(opts.nodeInitialColors??Array.from({length:n3},()=>"_")).slice(),getCounts=cols=>{let counts={};for(let c3 of cols)counts[c3]=(counts[c3]??0)+1;return counts},countsArr=[];countsArr.push(getCounts(colors));for(let step=0;step<K4;step++){let next2=Array(n3);for(let v5=0;v5<n3;v5++){let neigh=[];for(let u4=0;u4<n3;u4++)adjMatrix[v5][u4]&&neigh.push(colors[u4]);neigh.sort(),next2[v5]=`${colors[v5]}|${neigh.join(",")}`}colors=next2,countsArr.push(getCounts(colors))}return countsArr},wlVecWeightedJaccardSimilarity=(wlFeatureVec1,wlFeatureVec2)=>{let total=0,len=Math.min(wlFeatureVec1.length,wlFeatureVec2.length);for(let i2=0;i2<len;i2++){let rec1=wlFeatureVec1[i2],rec2=wlFeatureVec2[i2],allKeys=new Set([...Object.keys(rec1),...Object.keys(rec2)]),sumMin=0,sumMax=0;for(let k4 of allKeys){let v12=rec1[k4]??0,v22=rec2[k4]??0;sumMin+=Math.min(v12,v22),sumMax+=Math.max(v12,v22)}total+=sumMax===0?0:sumMin/sumMax}return total};var getWlDotProduct=wlVecWeightedJaccardSimilarity,DEFAULT_WL_DEGREES=2,getWlFeatureVecs=(g7,wlDegrees=DEFAULT_WL_DEGREES)=>{let flatBpc=convertToFlatBpcGraph(g7),{matrix:matrix2,indexMapping}=getAdjacencyMatrixFromFlatBpcGraph(flatBpc);return wlFeatureVec(matrix2,wlDegrees,{nodeInitialColors:indexMapping.map(id=>flatBpc.nodes.find(n3=>n3.id===id)?.color??"_")})},getBpcGraphWlDistance=(g12,g22,{wlDegrees=DEFAULT_WL_DEGREES}={})=>{let wlVec1=getWlFeatureVecs(g12,wlDegrees),wlVec2=getWlFeatureVecs(g22,wlDegrees);return(DEFAULT_WL_DEGREES+1-getWlDotProduct(wlVec1,wlVec2))/(DEFAULT_WL_DEGREES+1)},hashStringToNumber=str=>{let hash=0;for(let i2=0;i2<str.length;i2++)hash=(hash<<5)-hash+str.charCodeAt(i2);return Math.abs(hash)},convertFlatBpcToGraphics=(flat,opts={})=>{let gfx={points:[],lines:[],rects:[],circles:[],texts:[],coordinateSystem:"cartesian",title:"Flat-BPC Graphics"},pos=new Map;for(let n3 of flat.nodes){if(n3.x===void 0||n3.y===void 0)continue;let p4={x:n3.x,y:n3.y};pos.set(n3.id,p4),gfx.points.push({...p4,color:translateColor(n3.color),label:n3.id})}for(let[a2,b3]of flat.undirectedEdges){let pa3=pos.get(a2),pb=pos.get(b3);pa3&&pb&&gfx.lines.push({points:[pa3,pb],strokeColor:"rgba(0,0,0,0.3)"})}let bounds=getBounds(gfx);return opts.title&&gfx.texts.push({text:opts.title,x:bounds.minX,y:bounds.maxY,fontSize:(bounds.maxY-bounds.minY)*.05,anchorSide:"bottom_left"}),opts.caption&&gfx.texts.push({text:opts.caption,x:bounds.minX,y:bounds.minY,fontSize:(bounds.maxY-bounds.minY)*.05,anchorSide:"top_left"}),gfx};var getTotalNetworkLength=g7=>{let networkPins=new Map;for(let pin of g7.pins){let box2=g7.boxes.find(b3=>b3.boxId===pin.boxId);if(!box2||!box2.center)throw new Error(`Expected fixed graph \u2013 box "${pin.boxId}" missing or has no center`);let pos={x:box2.center.x+pin.offset.x,y:box2.center.y+pin.offset.y};networkPins.has(pin.networkId)||networkPins.set(pin.networkId,[]),networkPins.get(pin.networkId).push(pos)}let networkLengths=new Map,totalNetworkLength=0;for(let[netId,positions]of networkPins){if(positions.length===0){networkLengths.set(netId,0);continue}let centre=positions.reduce((acc,p4)=>({x:acc.x+p4.x,y:acc.y+p4.y}),{x:0,y:0});centre.x/=positions.length,centre.y/=positions.length;let len=positions.reduce((sum,p4)=>{let dx2=p4.x-centre.x,dy2=p4.y-centre.y;return sum+Math.sqrt(dx2*dx2+dy2*dy2)},0);networkLengths.set(netId,len),totalNetworkLength+=len}return{totalNetworkLength,networkLengths}},computeBagOfAnglesForNetwork=(g7,networkId)=>{let pins=g7.pins.filter(p4=>p4.networkId===networkId),angles=[];for(let pin of pins){let pinAngle=Math.atan2(pin.offset.y,pin.offset.x);angles.push(pinAngle)}return angles},computeGraphNetworkBagOfAnglesMap=g7=>{let map=new Map,networks=Array.from(new Set(g7.pins.map(p4=>p4.networkId)));for(let networkId of networks){let angles=computeBagOfAnglesForNetwork(g7,networkId);map.set(networkId,angles)}return map},circularDistance=(a2,b3)=>{let TAU=2*Math.PI,normA=(a2%TAU+TAU)%TAU,normB=(b3%TAU+TAU)%TAU,diff=Math.abs(normA-normB);return Math.min(diff,TAU-diff)},computeBagOfAnglesDistance=(bag1,bag2)=>{if(bag1.length===0&&bag2.length===0)return 0;if(bag1.length===0||bag2.length===0)return Math.PI;let avgNearest=(src,tgt)=>{let sum=0;for(let a2 of src){let best=1/0;for(let b3 of tgt){let d3=circularDistance(a2,b3);d3<best&&(best=d3)}sum+=best}return sum/src.length};return(avgNearest(bag1,bag2)+avgNearest(bag2,bag1))/2},computeNetworkMappingFromBagsOfAngles=(bag1,bag2)=>{let networkMapping=new Map,bag1Entries=Array.from(bag1.entries()),bag2Entries=Array.from(bag2.entries()),n12=bag1Entries.length,n22=bag2Entries.length,distanceMatrix=Array.from({length:n12},()=>new Array(n22).fill(0));for(let i2=0;i2<n12;i2++){let[,angles1]=bag1Entries[i2];for(let j4=0;j4<n22;j4++){let[,angles2]=bag2Entries[j4];distanceMatrix[i2][j4]=computeBagOfAnglesDistance(angles1,angles2)}}let unmapped1=new Set(Array.from({length:n12},(_5,i2)=>i2)),unmapped2=new Set(Array.from({length:n22},(_5,i2)=>i2)),totalDistance=0;for(;unmapped1.size&&unmapped2.size;){let bestI=-1,bestJ=-1,bestD=1/0;for(let i2 of unmapped1)for(let j4 of unmapped2){let d3=distanceMatrix[i2][j4];d3<bestD&&(bestD=d3,bestI=i2,bestJ=j4)}let[net1]=bag1Entries[bestI],[net2]=bag2Entries[bestJ];networkMapping.set(net1,net2),totalDistance+=bestD,unmapped1.delete(bestI),unmapped2.delete(bestJ)}let UNMATCHED_PENALTY=Math.PI;return totalDistance+=(unmapped1.size+unmapped2.size)*UNMATCHED_PENALTY,{networkMapping,distance:totalDistance}},getBoundsOfPinList=pins=>{let minX=Math.min(...pins.map(p4=>p4.offset.x)),maxX=Math.max(...pins.map(p4=>p4.offset.x)),minY=Math.min(...pins.map(p4=>p4.offset.y)),maxY=Math.max(...pins.map(p4=>p4.offset.y));return{minX,maxX,minY,maxY}},getNormalizedPerimeterDistance=(A4,B5)=>{let posToScalar=p4=>{switch(p4.side){case"x+":return p4.cwDistanceFromCorner;case"y-":return 1+p4.cwDistanceFromCorner;case"x-":return 2+p4.cwDistanceFromCorner;case"y+":return 3+p4.cwDistanceFromCorner}},a2=posToScalar(A4)%4,b3=posToScalar(B5)%4,cwDistance=(b3-a2+4)%4,ccwDistance=(a2-b3+4)%4,minDistance=Math.min(cwDistance,ccwDistance);return{cwDistance,ccwDistance,minDistance}},EPS=1e-6,getNormalizedPerimeterPosition=(bounds,position2)=>{let{minX,minY,maxX,maxY}=bounds,near=(a2,b3)=>Math.abs(a2-b3)<EPS,side,cwDistanceFromCorner;if(near(position2.x,maxX)&&position2.y>=minY-EPS&&position2.y<=maxY+EPS)side="x+",cwDistanceFromCorner=(maxY-position2.y)/(maxY-minY);else if(near(position2.y,maxY)&&position2.x<=maxX+EPS&&position2.x>=minX-EPS)side="y+",cwDistanceFromCorner=(position2.x-minX)/(maxX-minX);else if(near(position2.x,minX)&&position2.y<=maxY+EPS&&position2.y>=minY-EPS)side="x-",cwDistanceFromCorner=(position2.y-minY)/(maxY-minY);else if(near(position2.y,minY)&&position2.x>=minX-EPS&&position2.x<=maxX+EPS)side="y-",cwDistanceFromCorner=(maxX-position2.x)/(maxX-minX);else return null;return cwDistanceFromCorner=Math.min(1,Math.max(0,cwDistanceFromCorner)),{side,cwDistanceFromCorner}},matchPins=(pinList1,pinList2)=>{let matchedPins=[],unmatchedPin1Ids=new Set,unmatchedPin2Ids=new Set,matchedPin1Ids=new Set,matchedPin2Ids=new Set,bounds1=getBoundsOfPinList(pinList1),bounds2=getBoundsOfPinList(pinList2);for(let pin1 of pinList1){let matchingPinsByColor=pinList2.filter(p22=>p22.color===pin1.color).filter(p22=>!matchedPin2Ids.has(p22.pinId));if(matchingPinsByColor.length===0){unmatchedPin1Ids.add(pin1.pinId);continue}let normalizedPerimeterPosition1=getNormalizedPerimeterPosition(bounds1,pin1.offset);if(normalizedPerimeterPosition1===null){unmatchedPin1Ids.add(pin1.pinId);continue}let bestPerimeterDistance=1/0,bestMatchingPin2=matchingPinsByColor[0];for(let pin2 of matchingPinsByColor){let normalizedPerimeterPosition2=getNormalizedPerimeterPosition(bounds2,pin2.offset);if(normalizedPerimeterPosition2===null)continue;let{minDistance}=getNormalizedPerimeterDistance(normalizedPerimeterPosition1,normalizedPerimeterPosition2);minDistance<bestPerimeterDistance&&(bestPerimeterDistance=minDistance,bestMatchingPin2=pin2)}matchedPins.push([pin1,bestMatchingPin2]),matchedPin1Ids.add(pin1.pinId),matchedPin2Ids.add(bestMatchingPin2.pinId)}for(let pin2 of pinList2)matchedPin2Ids.has(pin2.pinId)||unmatchedPin2Ids.add(pin2.pinId);return{matchedPins,unmatchedPin1Ids,unmatchedPin2Ids}},AssignmentSolver2=class{constructor(floatingGraph,fixedGraph){__publicField(this,"wipGraph");__publicField(this,"iterations",0);__publicField(this,"solved",!1);__publicField(this,"acceptedFloatingBoxIds",new Set);__publicField(this,"rejectedFloatingBoxIds",new Set);__publicField(this,"acceptedFixedBoxIds",new Set);__publicField(this,"assignment",new Map);__publicField(this,"lastAcceptedEvaluation",null);__publicField(this,"fixedToFloatingNetworkMap");__publicField(this,"floatingToFixedNetworkMap");__publicField(this,"lastComputedEvaluations",[]);this.floatingGraph=floatingGraph,this.fixedGraph=fixedGraph,this.wipGraph={pins:[],boxes:[]},this.fixedToFloatingNetworkMap=this.computeFixedToFloatingNetworkMap(),this.floatingToFixedNetworkMap=new Map(Array.from(this.fixedToFloatingNetworkMap.entries()).map(([k4,v5])=>[v5,k4]))}computeFixedToFloatingNetworkMap(){let floatingBagOfAnglesMap=computeGraphNetworkBagOfAnglesMap(this.floatingGraph),fixedBagOfAnglesMap=computeGraphNetworkBagOfAnglesMap(this.fixedGraph),{networkMapping}=computeNetworkMappingFromBagsOfAngles(fixedBagOfAnglesMap,floatingBagOfAnglesMap);return networkMapping}getNextFloatingBoxId(){let remainingFloatingBoxIds=this.floatingGraph.boxes.map(b3=>b3.boxId).filter(b3=>!this.acceptedFloatingBoxIds.has(b3)&&!this.rejectedFloatingBoxIds.has(b3));if(!remainingFloatingBoxIds.length)throw new Error("No remaining floating box ids");let bestFloatingBoxId=remainingFloatingBoxIds[0],bestFloatingBoxPinCount=0;for(let floatingBoxId of remainingFloatingBoxIds){let floatingBoxPins=this.floatingGraph.pins.filter(p4=>p4.boxId===floatingBoxId);floatingBoxPins.length>bestFloatingBoxPinCount&&(bestFloatingBoxId=floatingBoxId,bestFloatingBoxPinCount=floatingBoxPins.length)}return bestFloatingBoxId}getRemainingFloatingBoxIds(){return this.floatingGraph.boxes.map(b3=>b3.boxId).filter(b3=>!this.acceptedFloatingBoxIds.has(b3)&&!this.rejectedFloatingBoxIds.has(b3))}getPartialFloatingGraph(nextFloatingBoxId){let g7={pins:[],boxes:[]};for(let box2 of this.floatingGraph.boxes)(this.acceptedFloatingBoxIds.has(box2.boxId)||box2.boxId===nextFloatingBoxId)&&(g7.boxes.push(box2),g7.pins.push(...this.floatingGraph.pins.filter(p4=>p4.boxId===box2.boxId)));return g7}evaluateFloatingBoxAssignment(nextFloatingBoxId){let partialFloatingGraph=this.getPartialFloatingGraph(nextFloatingBoxId),currentWlDist=getBpcGraphWlDistance(partialFloatingGraph,this.wipGraph),bestFixedBoxId=null,bestNewWipGraph=null,dEval={floatingBoxId:nextFloatingBoxId,originalWipGraph:this.wipGraph,partialFloatingGraph,currentWlDist,networkLengths:new Map,wlDistances:new Map,wlVecs:new Map,wipGraphsWithAddedFixedBoxId:new Map},bestDist=currentWlDist,bestWlDist=currentWlDist,bestTotalNetworkLength=1/0,floatingBoxWlVec=getWlFeatureVecs(partialFloatingGraph);for(let fixedBoxId of this.fixedGraph.boxes.map(b3=>b3.boxId)){if(this.acceptedFixedBoxIds.has(fixedBoxId))continue;let wipGraphWithAddedFixedBoxId=this.getWipGraphWithAddedFixedBoxIdForFloatingAssignment(fixedBoxId,nextFloatingBoxId),wlDist=getBpcGraphWlDistance(partialFloatingGraph,wipGraphWithAddedFixedBoxId),debug_wlVec=getWlFeatureVecs(wipGraphWithAddedFixedBoxId),{totalNetworkLength}=getTotalNetworkLength(wipGraphWithAddedFixedBoxId);dEval.wipGraphsWithAddedFixedBoxId.set(fixedBoxId,wipGraphWithAddedFixedBoxId),dEval.wlVecs.set(fixedBoxId,debug_wlVec),dEval.wlDistances.set(fixedBoxId,wlDist),dEval.networkLengths.set(fixedBoxId,totalNetworkLength);let dist=wlDist+totalNetworkLength/100;dist<bestDist&&(bestDist=dist,bestWlDist=wlDist,bestTotalNetworkLength=totalNetworkLength,bestNewWipGraph=wipGraphWithAddedFixedBoxId,bestFixedBoxId=fixedBoxId)}return{bestFixedBoxId,bestNewWipGraph,bestDist,bestWlDist,bestTotalNetworkLength,lastDistanceEvaluation:dEval,nextFloatingBoxId,partialFloatingGraph,floatingBoxWlVec}}getPinAssignment(){let pinAssignment={},fixedToFloatingBoxAssignment={};for(let[floatingBoxId,fixedBoxId]of this.assignment)pinAssignment[floatingBoxId]={},fixedToFloatingBoxAssignment[fixedBoxId]=floatingBoxId;for(let pin of this.wipGraph.pins){let fixedBoxId=pin.boxId,floatingBoxId=fixedToFloatingBoxAssignment[fixedBoxId],floatingPinId=pin._floatingPinId,fixedPinId=pin._fixedPinId;pinAssignment[floatingBoxId][floatingPinId]=fixedPinId}return pinAssignment}step(){if(this.solved)return;if(this.iterations>1e3)throw new Error("Too many iterations");if(this.iterations++,this.iterations===1){let nextFloatingBoxId=this.getNextFloatingBoxId(),evalResult=this.evaluateFloatingBoxAssignment(nextFloatingBoxId);this.lastComputedEvaluations=[evalResult],this.acceptEvaluationResult(evalResult);return}let remainingFloatingBoxIds=this.getRemainingFloatingBoxIds();if(remainingFloatingBoxIds.length===0){this.solved=!0;return}let bestEvalDist=1/0,bestEvalResult=null;this.lastComputedEvaluations=[];for(let floatingBoxId of remainingFloatingBoxIds){let evalResult=this.evaluateFloatingBoxAssignment(floatingBoxId);this.lastComputedEvaluations.push(evalResult),evalResult.bestDist<bestEvalDist&&(bestEvalDist=evalResult.bestDist,bestEvalResult=evalResult)}bestEvalResult&&this.acceptEvaluationResult(bestEvalResult)}acceptEvaluationResult(evalResult){let{bestFixedBoxId,bestNewWipGraph,nextFloatingBoxId}=evalResult;if(bestFixedBoxId===null){this.rejectedFloatingBoxIds.add(nextFloatingBoxId);return}this.acceptedFloatingBoxIds.add(nextFloatingBoxId),this.assignment.set(nextFloatingBoxId,bestFixedBoxId),this.acceptedFixedBoxIds.add(bestFixedBoxId),this.wipGraph=bestNewWipGraph,this.lastAcceptedEvaluation=evalResult.lastDistanceEvaluation}getWipGraphWithAddedFixedBoxIdForFloatingAssignment(fixedBoxId,floatingBoxId){let g7=structuredClone(this.wipGraph),boxToAdd=this.fixedGraph.boxes.find(b3=>b3.boxId===fixedBoxId);g7.boxes.push(boxToAdd);let floatingBoxPins=this.floatingGraph.pins.filter(p4=>p4.boxId===floatingBoxId),fixedBoxPins=this.fixedGraph.pins.filter(p4=>p4.boxId===fixedBoxId),{matchedPins}=matchPins(floatingBoxPins,fixedBoxPins);return g7.pins.push(...matchedPins.map(p4=>{let[floatingPin,fixedPin]=p4;return{...fixedPin,networkId:this.floatingToFixedNetworkMap.get(floatingPin.networkId),_floatingPinId:floatingPin.pinId,_fixedPinId:fixedPin.pinId}})),g7}visualize(){let floatingGraphics=getGraphicsForBpcGraph(this.floatingGraph,{title:"Floating"}),wipGraphics=getGraphicsForBpcGraph(this.wipGraph,{title:"WIP"}),fixedGraphics=getGraphicsForBpcGraph(this.fixedGraph,{title:"Fixed"}),floatingPartialGraphics=getGraphicsForBpcGraph(this.getPartialFloatingGraph(),{title:"Partial Floating"}),colorByFloatingId=new Map,fixedToFloating=new Map;for(let[floatId,fixedId]of this.assignment){let colour=getColorByIndex(hashStringToNumber(floatId)*47%100,100,.5);colorByFloatingId.set(floatId,colour),fixedToFloating.set(fixedId,floatId)}function decorateRect(rect,floatId,fixedId){let colour=colorByFloatingId.get(floatId);rect.fill=colour,rect.label=`${floatId}\u2192${fixedId}`}for(let rect of floatingGraphics.rects??[]){let floatId=rect.label;if(!floatId)continue;let fixedId=this.assignment.get(floatId);fixedId&&decorateRect(rect,floatId,fixedId)}for(let rect of floatingPartialGraphics.rects??[]){let floatId=rect.label;if(!floatId)continue;let fixedId=this.assignment.get(floatId);fixedId&&decorateRect(rect,floatId,fixedId)}let targetGraphics=[wipGraphics,fixedGraphics];for(let g7 of targetGraphics)for(let rect of g7.rects??[]){let fixedId=rect.label;if(!fixedId)continue;let floatId=fixedToFloating.get(fixedId);floatId&&decorateRect(rect,floatId,fixedId)}let floatingFlatG=convertToFlatBpcGraph(this.floatingGraph),wipFlatG=convertToFlatBpcGraph(this.wipGraph),fixedFlatG=convertToFlatBpcGraph(this.fixedGraph),floatingFlatGraphics=convertFlatBpcToGraphics(floatingFlatG,{title:"Floating Flat"}),wipFlatGraphics=convertFlatBpcToGraphics(wipFlatG,{title:"WIP Flat"}),fixedFlatGraphics=convertFlatBpcToGraphics(fixedFlatG,{title:"Fixed Flat"});return stackGraphicsHorizontally([stackGraphicsVertically([floatingGraphics,floatingFlatGraphics,floatingPartialGraphics]),stackGraphicsVertically([wipGraphics,wipFlatGraphics]),stackGraphicsVertically([fixedGraphics,fixedFlatGraphics])])}},getApproximateAssignments2=(floatingGraph,fixedGraph)=>{let solver=new AssignmentSolver2(floatingGraph,fixedGraph);for(;!solver.solved&&solver.iterations<1e3;)solver.step();let boxAssignment={};for(let[floatingBoxId,fixedBoxId]of solver.assignment.entries())boxAssignment[floatingBoxId]=fixedBoxId;let networkAssignment={};for(let[floatingNetId,fixedNetId]of solver.floatingToFixedNetworkMap.entries())networkAssignment[floatingNetId]=fixedNetId;let pinAssignment=solver.getPinAssignment();return{floatingToFixedBoxAssignment:boxAssignment,floatingToFixedNetworkAssignment:networkAssignment,floatingToFixedPinAssignment:pinAssignment}};var mergeBoxSideSubgraphs=(graphs,{renetworkedNetworkIdMap}={})=>{if(renetworkedNetworkIdMap??(renetworkedNetworkIdMap={}),graphs.length===1)return graphs[0];let merged={boxes:[],pins:[]},boxMap=new Map,pinMap=new Map,partitionedBoxIds=Object.entries(graphs.flatMap(g7=>Array.from(new Set(g7.boxes.map(b3=>b3.boxId)))).reduce((acc,str)=>(acc[str]=(acc[str]||0)+1,acc),{})).filter(([_5,count])=>count===graphs.length).map(([str])=>str);if(partitionedBoxIds.length>1)throw new Error(`Expected at most one shared box across all partitions, the following box ids are shared across all graphs: ${partitionedBoxIds.join(", ")}`);let partitionedBoxId=partitionedBoxIds[0];for(let g7 of graphs){let offset=g7.boxes.find(b3=>b3.boxId===partitionedBoxId)?.center;for(let box2 of g7.boxes){if(boxMap.has(box2.boxId))continue;let modifiedBox=structuredClone(box2);modifiedBox.center&&offset&&(modifiedBox.center={x:modifiedBox.center.x-offset.x,y:modifiedBox.center.y-offset.y}),boxMap.set(box2.boxId,modifiedBox)}for(let pin of g7.pins)pinMap.has(`${pin.boxId}-${pin.pinId}`)||pinMap.set(`${pin.boxId}-${pin.pinId}`,structuredClone(pin))}return merged.boxes=Array.from(boxMap.values()),merged.pins=Array.from(pinMap.values()),merged};var reflectGraph=({graph,axis,centerBoxId})=>{let newGraph=structuredClone(graph),centreBox=newGraph.boxes.find(b3=>b3.boxId===centerBoxId);if(!centreBox||!centreBox.center)throw new Error(`Center box "${centerBoxId}" not found or has no center`);let{x:cx2,y:cy2}=centreBox.center;for(let box2 of newGraph.boxes)box2.center&&(axis==="x"?box2.center.x=2*cx2-box2.center.x:box2.center.y=2*cy2-box2.center.y);for(let pin of newGraph.pins)axis==="x"?pin.offset.x=-pin.offset.x:pin.offset.y=-pin.offset.y;return newGraph},getCanonicalRightFacingGraph=g7=>{let largestLeftRightBox=null,largestLeftRightBoxPins=-1/0;for(let box2 of g7.boxes){let lrPins2=g7.pins.filter(p4=>p4.boxId===box2.boxId).filter(p4=>["x-","x+"].includes(getPinDirection(g7,box2,p4)??"none"));lrPins2.length>largestLeftRightBoxPins&&lrPins2.length>1&&(largestLeftRightBox=box2,largestLeftRightBoxPins=lrPins2.length)}if(!largestLeftRightBox)return{g:g7,reflected:!1,centerBoxId:null};let largestBoxLRPinDirections=g7.pins.filter(p4=>p4.boxId===largestLeftRightBox.boxId).map(p4=>getPinDirection(g7,largestLeftRightBox,p4)),dirCounts={"x+":0,"x-":0,"y+":0,"y-":0};for(let dir of largestBoxLRPinDirections)dir&&dirCounts[dir]++;return dirCounts["x+"]>=dirCounts["x-"]?{g:g7,reflected:!1,centerBoxId:largestLeftRightBox.boxId}:{g:reflectGraph({graph:g7,axis:"x",centerBoxId:largestLeftRightBox.boxId}),reflected:!0,centerBoxId:largestLeftRightBox.boxId}},debug4=(0,import_debug4.default)("schematic-partition-processor"),SchematicPartitionProcessor=class{constructor(initialGraph,opts={}){__publicField(this,"lastGraph");__publicField(this,"lastExploredPin");__publicField(this,"solved",!1);__publicField(this,"iteration",0);__publicField(this,"wipPartitions");__publicField(this,"unexploredPins",[]);__publicField(this,"boxSingletonKeys");__publicField(this,"exploredPins");__publicField(this,"addedPins");__publicField(this,"allAcceptedPins",new Set);__publicField(this,"pinConnectionCount");__publicField(this,"networkSize");__publicField(this,"pinNetworkSize");__publicField(this,"splitBoxIds");__publicField(this,"acceptedBoxPartitionMap",new Map);__publicField(this,"singletonKeys");__publicField(this,"centerPinColors");this.initialGraph=initialGraph,this.lastGraph=initialGraph,this.singletonKeys=opts.singletonKeys??[],this.centerPinColors=opts.centerPinColors??[];let partitionInit=this.initializeWipPartitions();this.wipPartitions=partitionInit.wipPartitions,this.splitBoxIds=partitionInit.splitBoxIds,this.addedPins=partitionInit.addedPins,this.exploredPins=new Set,this.unexploredPins=this.wipPartitions.flatMap(part=>part.pins.map(p4=>({...p4,partitionId:part.partitionId}))),this.boxSingletonKeys=this.initializeBoxSingletonKeys(),this.pinConnectionCount=(()=>{let counts={};for(let pin of this.initialGraph.pins)counts[`${pin.boxId}:${pin.pinId}`]=this.getNeighbors(pin).length;return counts})();let netCounts={};for(let p4 of this.initialGraph.pins)netCounts[p4.networkId]=(netCounts[p4.networkId]??0)+1;this.networkSize=netCounts;let pNetSize={};for(let p4 of this.initialGraph.pins)pNetSize[`${p4.boxId}:${p4.pinId}`]=netCounts[p4.networkId];this.pinNetworkSize=pNetSize}initializeBoxSingletonKeys(){let boxSingletonKeys={};for(let box2 of this.initialGraph.boxes){let boxPins=this.initialGraph.pins.filter(p4=>p4.boxId===box2.boxId),boxPinCount=boxPins.length,singletonKeysForBox=boxPins.map(p4=>`${p4.color}/${boxPinCount}`).filter(k4=>this.singletonKeys.includes(k4));boxSingletonKeys[box2.boxId]=new Set(singletonKeysForBox)}return boxSingletonKeys}initializeWipPartitions(){let wipPartitions=[],addedPins=new Set,splitBoxIds=new Set,partitionId=0;for(let box2 of this.initialGraph.boxes){let pins=this.initialGraph.pins.filter(p4=>p4.boxId===box2.boxId).filter(p4=>getPinDirection(this.initialGraph,box2,p4)).filter(p4=>!this.centerPinColors.includes(p4.color));if(pins.length<4)continue;let uniqueDirections=new Set(pins.map(p4=>getPinDirection(this.initialGraph,box2,p4)));uniqueDirections.size>1&&splitBoxIds.add(box2.boxId);for(let direction2 of uniqueDirections){let partition={partitionId:`partition${partitionId++}`,filledSingletonSlots:new Set,pins:[]};for(let pin of pins)getPinDirection(this.initialGraph,box2,pin)===direction2&&(partition.pins.push({boxId:box2.boxId,pinId:pin.pinId}),addedPins.add(`${box2.boxId}:${pin.pinId}`));wipPartitions.push(partition)}}return wipPartitions.length===0&&(wipPartitions.push(this.createWipPartitionFromEntireGraph()),this.solved=!0),debug4(`splitBoxIds = ${Array.from(splitBoxIds).join(", ")}`),debug4(`wipPartitions = ${wipPartitions.map(p4=>p4.partitionId).join(", ")}`),{wipPartitions,splitBoxIds,addedPins}}createWipPartitionFromEntireGraph(){return{partitionId:"entire-graph",filledSingletonSlots:new Set,pins:this.initialGraph.pins.map(p4=>({boxId:p4.boxId,pinId:p4.pinId}))}}step(){if(this.solved)return;if(this.iteration++,debug4(`
|
|
610
610
|
\u2500\u2500 Iteration ${this.iteration} \u2500\u2500 unexplored=${this.unexploredPins.length} explored=${this.exploredPins.size}`),this.unexploredPins.sort((a2,b3)=>{let aKey=`${a2.boxId}:${a2.pinId}`,bKey=`${b3.boxId}:${b3.pinId}`,netDiff=this.pinNetworkSize[aKey]-this.pinNetworkSize[bKey];return netDiff!==0?netDiff:this.pinConnectionCount[aKey]-this.pinConnectionCount[bKey]}),this.unexploredPins.length===0){this.solved=!0;return}let current2=this.unexploredPins.shift(),currentPinKey=`${current2.boxId}:${current2.pinId}`;debug4(`Exploring pin ${current2.boxId}:${current2.pinId} for partition "${current2.partitionId}"`),this.lastExploredPin={...current2,partitionId:current2.partitionId};let currentPinPartitionKey=`${current2.partitionId}[${currentPinKey}]`,currentPin=this.initialGraph.pins.find(p4=>p4.boxId===current2.boxId&&p4.pinId===current2.pinId);if(!currentPin||this.exploredPins.has(currentPinPartitionKey))return;let currentPartition=this.wipPartitions.find(p4=>p4.partitionId===current2.partitionId);if(!currentPartition)return;let pinAlreadyAcceptedIntoPartitionId=this.acceptedBoxPartitionMap.get(current2.boxId);if(pinAlreadyAcceptedIntoPartitionId&&pinAlreadyAcceptedIntoPartitionId!==current2.partitionId&&!this.splitBoxIds.has(current2.boxId)){debug4(` \u21B3 rejected (box ${current2.boxId} for partition ${current2.partitionId} already in partition ${this.acceptedBoxPartitionMap.get(current2.boxId)})`),this.exploredPins.add(currentPinPartitionKey);return}let singletonKeysForBox=this.boxSingletonKeys[current2.boxId];if(Array.from(singletonKeysForBox).some(k4=>currentPartition.filledSingletonSlots.has(k4))){debug4(` \u21B3 rejected (singleton already in partition "${current2.partitionId}")`),this.exploredPins.add(currentPinPartitionKey);return}for(let k4 of singletonKeysForBox)currentPartition.filledSingletonSlots.add(k4);currentPartition.pins.push({boxId:current2.boxId,pinId:current2.pinId}),this.allAcceptedPins.add(currentPinKey),this.addedPins.add(currentPinKey),this.splitBoxIds.has(current2.boxId)||this.acceptedBoxPartitionMap.set(current2.boxId,current2.partitionId),this.exploredPins.add(currentPinPartitionKey),debug4(` \u21B3 accepted \u2192 pins in partition now = ${currentPartition.pins.length}`);let neighbors=this.getNeighbors(currentPin);for(let neighbor of neighbors){let neighborPinKey=`${neighbor.boxId}:${neighbor.pinId}`;this.addedPins.has(neighborPinKey)||this.centerPinColors.includes(neighbor.color)||this.exploredPins.has(`${current2.partitionId}[${neighborPinKey}]`)||this.unexploredPins.push({boxId:neighbor.boxId,pinId:neighbor.pinId,partitionId:current2.partitionId})}this.unexploredPins.length===0&&(this.solved=!0),this.solved&&debug4(`Solver finished in ${this.iteration} iterations, partitions=${this.getPartitions().length}`)}getNeighbors(pin){let neighbors=[];for(let pinInNetwork of this.initialGraph.pins)pinInNetwork.networkId===pin.networkId&&(pin.boxId===pinInNetwork.boxId&&pinInNetwork.pinId===pin.pinId||neighbors.push(pinInNetwork));for(let pinInBox of this.initialGraph.pins)pinInBox.boxId===pin.boxId&&neighbors.push(pinInBox);return neighbors}solve(){for(;!this.solved&&this.iteration<1e3;)this.step()}getPartitions(){if(!this.solved)throw new Error("Graph not solved");let partitions=[];for(let part of this.wipPartitions){if(part.pins.length===0)continue;let partBoxIds=new Set(part.pins.map(p4=>p4.boxId)),partBoxes=this.initialGraph.boxes.filter(b3=>partBoxIds.has(b3.boxId));partitions.push({boxes:partBoxes,pins:this.initialGraph.pins.filter(p4=>part.pins.some(pp2=>pp2.pinId===p4.pinId&&pp2.boxId===p4.boxId)||this.centerPinColors.includes(p4.color)&&partBoxIds.has(p4.boxId))})}return partitions}getGraphicsForLastGraph(){let graphics=getGraphicsForBpcGraph(this.lastGraph,{title:`Iteration ${this.iteration}`}),total=this.wipPartitions.length,PIN_RECT_SIZE=.4;if(this.wipPartitions.forEach((part,idx)=>{if(part.pins.length===0)return;let fill=getColorByIndex(idx,total,.25);for(let{boxId,pinId}of part.pins){let{x:x5,y:y5}=getPinPosition(this.lastGraph,boxId,pinId);graphics.rects.push({center:{x:x5,y:y5},width:PIN_RECT_SIZE,height:PIN_RECT_SIZE,fill})}}),this.lastExploredPin){let{boxId,pinId,color}=this.lastExploredPin,pos=getPinPosition(this.lastGraph,boxId,pinId),size2=.25;graphics.rects.push({center:{x:pos.x,y:pos.y},width:size2,height:size2,fill:this.lastExploredPin.partitionId?getColorByIndex(this.wipPartitions.findIndex(p4=>p4.partitionId===this.lastExploredPin.partitionId),this.wipPartitions.length,1):"black"}),graphics.texts.push({x:pos.x,y:pos.y,text:`${boxId}:${pinId}-${Array.from(this.boxSingletonKeys[boxId]??[]).join(",")}`,fontSize:.1})}let unexploredRectBaseSize=PIN_RECT_SIZE;for(let pin of this.unexploredPins){let{boxId,pinId,partitionId}=pin,partitionIdx=this.wipPartitions.findIndex(p4=>p4.partitionId===partitionId);if(partitionIdx===-1)continue;let stroke=getColorByIndex(partitionIdx,this.wipPartitions.length,1),{x:x5,y:y5}=getPinPosition(this.lastGraph,boxId,pinId),scale4=1+.1*partitionIdx;graphics.rects.push({center:{x:x5,y:y5},width:unexploredRectBaseSize*scale4,height:unexploredRectBaseSize*scale4,fill:"none",stroke})}return graphics}},matchGraph=(g7,corpus,opts={})=>{opts.similarityMethod??(opts.similarityMethod="wl-distance");let distanceFn=getBpcGraphWlDistance,corpusScores=Object.fromEntries(Object.entries(corpus).map(([k4,v5])=>[k4,distanceFn(g7,v5)])),bestMatch=Object.entries(corpusScores).reduce((best,[k4,d3])=>d3<best[1]?[k4,d3]:best);return{graphName:bestMatch[0],graph:corpus[bestMatch[0]],distance:bestMatch[1],corpusScores}},getDirectionFromVec2=vec2=>vec2.x>0?"x+":vec2.x<0?"x-":vec2.y>0?"y+":vec2.y<0?"y-":null,getDirectionVec2=direction2=>{switch(direction2){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}}},getDominantPinSide=(g7,boxId)=>{let box2=g7.boxes.find(b3=>b3.boxId===boxId);if(!box2)throw new Error(`Box ${boxId} not found`);let pinDirections=g7.pins.filter(p4=>p4.boxId===boxId).map(p4=>getPinDirection(g7,box2,p4)),sideCounts={"x-":0,"x+":0,"y-":0,"y+":0};for(let dir of pinDirections)dir&&sideCounts[dir]++;let maxSideCount=Math.max(...Object.values(sideCounts));for(let key of Object.keys(sideCounts))if(sideCounts[key]===maxSideCount)return key;return null},pushFloatingBoxesAdjustingForFixedSizeDelta=(adaptedFloatingBpcGraph,fixedGraph,{floatingToFixedBoxAssignment,floatingBoxIdsWithMutablePinOffsets})=>{for(let floatingBox of adaptedFloatingBpcGraph.boxes){let fixedBoxId=floatingToFixedBoxAssignment[floatingBox.boxId];if(!fixedBoxId||!floatingBox.center||floatingBoxIdsWithMutablePinOffsets?.has(floatingBox.boxId))continue;let fixedBoxBounds=getBoundsOfBpcBox(fixedGraph,fixedBoxId),floatingBoxBounds=getBoundsOfBpcBox(adaptedFloatingBpcGraph,floatingBox.boxId),fixedDominantPinSide=getDominantPinSide(fixedGraph,fixedBoxId),floatingDominantPinSide=getDominantPinSide(adaptedFloatingBpcGraph,floatingBox.boxId);if(fixedDominantPinSide===null||floatingDominantPinSide===null||fixedDominantPinSide!==floatingDominantPinSide)continue;let shiftVec=getDirectionVec2(fixedDominantPinSide),fixedWidth=fixedBoxBounds.maxX-fixedBoxBounds.minX,floatingWidth=floatingBoxBounds.maxX-floatingBoxBounds.minX,fixedHeight=fixedBoxBounds.maxY-fixedBoxBounds.minY,floatingHeight=floatingBoxBounds.maxY-floatingBoxBounds.minY,deltaWidth=floatingWidth-fixedWidth,deltaHeight=floatingHeight-fixedHeight;if(!(deltaWidth<.001&&deltaHeight<.001))for(let otherBox of adaptedFloatingBpcGraph.boxes){if(otherBox.boxId===floatingBox.boxId||!otherBox.center)continue;let deltaPos={x:otherBox.center.x-floatingBox.center.x,y:otherBox.center.y-floatingBox.center.y};getDirectionFromVec2({x:deltaPos.x*Math.abs(shiftVec.x),y:deltaPos.y*Math.abs(shiftVec.y)})===fixedDominantPinSide&&(otherBox.center.x+=shiftVec.x*deltaWidth,otherBox.center.y+=shiftVec.y*deltaHeight)}}},netAdaptBpcGraph2=(floatingGraph,fixedGraph,opts={})=>{let{floatingBoxIdsWithMutablePinOffsets=new Set}=opts,{floatingToFixedBoxAssignment,floatingToFixedPinAssignment}=getApproximateAssignments2(floatingGraph,fixedGraph),adaptedBpcGraph=structuredClone(floatingGraph);for(let floatingPin of adaptedBpcGraph.pins)if(floatingBoxIdsWithMutablePinOffsets.has(floatingPin.boxId)&&floatingToFixedPinAssignment[floatingPin.boxId]?.[floatingPin.pinId]){let fixedPinId=floatingToFixedPinAssignment[floatingPin.boxId]?.[floatingPin.pinId],fixedBoxId=floatingToFixedBoxAssignment[floatingPin.boxId],fixedPin=fixedGraph.pins.find(p4=>p4.boxId===fixedBoxId&&p4.pinId===fixedPinId);fixedPin&&(floatingPin.offset=fixedPin.offset)}for(let box2 of adaptedBpcGraph.boxes)if(floatingToFixedBoxAssignment[box2.boxId]){let fixedBoxId=floatingToFixedBoxAssignment[box2.boxId],fixedBox=fixedGraph.boxes.find(b3=>b3.boxId===fixedBoxId);fixedBox&&(box2.center=fixedBox.center,box2.kind="fixed")}return opts.pushBoxesAsBoxesChangeSize&&pushFloatingBoxesAdjustingForFixedSizeDelta(adaptedBpcGraph,fixedGraph,{floatingToFixedBoxAssignment,floatingBoxIdsWithMutablePinOffsets}),adaptedBpcGraph},layoutSchematicGraph=(g7,{corpus,singletonKeys,centerPinColors,floatingBoxIdsWithMutablePinOffsets})=>{let processor=new SchematicPartitionProcessor(g7,{singletonKeys,centerPinColors});for(;!processor.solved&&processor.iteration<1e3;)processor.step();let adaptedGraphs=processor.getPartitions().map(getCanonicalRightFacingGraph).map(part=>{let{graph:corpusSource,distance:distance8}=matchGraph(part.g,corpus);return{adaptedBpcGraph:netAdaptBpcGraph2(structuredClone(part.g),corpusSource,{floatingBoxIdsWithMutablePinOffsets,pushBoxesAsBoxesChangeSize:!0}),reflected:part.reflected,centerBoxId:part.centerBoxId,distance:distance8}}),adaptedUnreflectedGraphs=adaptedGraphs.map(({adaptedBpcGraph,reflected,centerBoxId})=>reflected?reflectGraph({graph:adaptedBpcGraph,axis:"x",centerBoxId}):adaptedBpcGraph),remergedGraph=mergeBoxSideSubgraphs(adaptedUnreflectedGraphs),totalDistance=adaptedGraphs.reduce((sum,ag)=>sum+(ag.distance||0),0);return{fixedGraph:remergedGraph,distance:totalDistance}},layoutSchematicGraphVariants=(variants,{corpus,singletonKeys,centerPinColors,floatingBoxIdsWithMutablePinOffsets})=>{let variantResults=[],bestVariant=null;for(let variant of variants){let{fixedGraph,distance:distance8}=layoutSchematicGraph(variant.floatingGraph,{corpus,singletonKeys,centerPinColors,floatingBoxIdsWithMutablePinOffsets});variantResults.push({variantName:variant.variantName,distance:distance8}),(!bestVariant||distance8<bestVariant.distance)&&(bestVariant={variantName:variant.variantName,result:fixedGraph,distance:distance8})}return{result:bestVariant.result,selectedVariantName:bestVariant.variantName,variantResults}};var import_debug11=__toESM(require_browser(),1);init_dist6();init_dist6();var BaseSolver3=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(e4){throw this.error=`${this.constructor.name} error: ${e4}`,this.failed=!0,e4}!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 rotatePoint2(point6,angleDegrees){let angleRad=angleDegrees*Math.PI/180,cos4=Math.cos(angleRad),sin4=Math.sin(angleRad);return{x:point6.x*cos4-point6.y*sin4,y:point6.x*sin4+point6.y*cos4}}function getRotatedDimensions(width,height,rotation4){let normalizedRotation=(rotation4%360+360)%360;return Math.round((normalizedRotation+90)%180)===0?{width:height,height:width}:{width,height}}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(p4=>inputProblem.chipPinMap[p4]),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(p4=>p4.offset.x),ys3=chipPins.map(p4=>p4.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);inputViz.rects.push({center:{x:chipCenterX,y:chipCenterY},width:rotatedDims.width,height:rotatedDims.height,label:chipId}),inputViz.texts.push({x:chipCenterX,y:chipCenterY,text:chipId});for(let pin of chipPins){let rotatedOffset=rotatePoint2(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=rotatePoint2(chipPin.offset,placement.ccwRotationDegrees);return{x:placement.x+rotatedOffset.x,y:placement.y+rotatedOffset.y}}}return chipPin.offset}return null}).filter(Boolean);for(let i2=0;i2<pinPositions.length;i2++)for(let j4=i2+1;j4<pinPositions.length;j4++)inputViz.lines.push({points:[pinPositions[i2],pinPositions[j4]],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=rotatePoint2(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}}});return pads.push({padId:`${chipId}-body`,networkId:chipId,type:"rect",offset:{x:0,y:0},size:{x:chip.size.x,y:chip.size.y}}),{componentId:chipId,pads}}),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 ChipPartitionsSolver=class extends BaseSolver3{constructor({inputProblem,decouplingCapGroups}){super();__publicField(this,"inputProblem");__publicField(this,"partitions",[]);__publicField(this,"decouplingCapGroups");this.inputProblem=inputProblem,this.decouplingCapGroups=decouplingCapGroups}_step(){this.partitions=this.createPartitions(this.inputProblem),this.solved=!0}createPartitions(inputProblem){let chipIds=Object.keys(inputProblem.chipMap),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]&&capsOnly.push(capId);if(capsOnly.length>=2){decapGroupPartitions.push(capsOnly);for(let capId of capsOnly)decapChipIdSet.add(capId)}}let nonDecapChipIds=chipIds.filter(id=>!decapChipIdSet.has(id)),adjacencyMap=new Map;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=this.findPinOwner(pin1Id,inputProblem),owner2=this.findPinOwner(pin2Id,inputProblem);owner1&&owner2&&owner1!==owner2&&!decapChipIdSet.has(owner1)&&!decapChipIdSet.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[...decapGroupPartitions.map(partition=>this.createInputProblemFromPartition(partition,inputProblem,{partitionType:"decoupling_caps"})),...nonDecapPartitions.map(partition=>this.createInputProblemFromPartition(partition,inputProblem))]}findPinOwner(pinId,inputProblem){if(inputProblem.chipPinMap[pinId]){for(let[chipId,chip]of Object.entries(inputProblem.chipMap))if(chip.pins.includes(pinId))return chipId}return null}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}}visualize(){if(this.partitions.length===0)return super.visualize();let partitionVisualizations=this.partitions.map(partition=>{let layout=doBasicInputProblemLayout(partition);return visualizeInputProblem(partition,layout)}),titles=this.partitions.map((_5,index)=>`partition${index}`);return stackGraphicsHorizontally(partitionVisualizations,{titles})}},getColorFromString=(string,alpha=1)=>{let hash=0;for(let i2=0;i2<string.length;i2++){let char=string.charCodeAt(i2);hash=(hash<<5)-hash+char,hash=hash&hash}return`hsl(${Math.abs(hash)%360}, 70%, 50%, ${alpha})`},IdentifyDecouplingCapsSolver=class extends BaseSolver3{constructor(inputProblem){super();__publicField(this,"inputProblem");__publicField(this,"queuedChips");__publicField(this,"outputDecouplingCapGroups",[]);__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.every(r4=>allowed.has(r4))}pinsOnOppositeYSides(chip){if(chip.pins.length!==2)return!1;let[p12,p22]=chip.pins,cp1=this.inputProblem.chipPinMap[p12],cp2=this.inputProblem.chipPinMap[p22];if(!cp1||!cp2)return!1;let sides=new Set([cp1.side,cp2.side]);return sides.has("y+")&&sides.has("y-")}getStronglyConnectedNeighborChips(pinId){let neighbors=new Set;for(let[connKey,connected]of Object.entries(this.inputProblem.pinStrongConnMap)){if(!connected)continue;let[a2,b3]=connKey.split("-");if(a2===pinId){let otherChipId=b3.split(".")[0];neighbors.add(otherChipId)}else if(b3===pinId){let otherChipId=a2.split(".")[0];neighbors.add(otherChipId)}}return neighbors}findMainChipIdForCap(capChip){let strongNeighbors=new Map;for(let pinId of capChip.pins){let neighbors=this.getStronglyConnectedNeighborChips(pinId);for(let n3 of neighbors)n3!==capChip.chipId&&strongNeighbors.set(n3,(strongNeighbors.get(n3)||0)+1)}if(strongNeighbors.size===0)return null;let best=null;for(let[id,score]of strongNeighbors.entries())(!best||score>best.score||score===best.score&&id<best.id)&&(best={id,score});return best?best.id:null}getNetIdsForPin(pinId){let nets=new Set;for(let[connKey,connected]of Object.entries(this.inputProblem.netConnMap)){if(!connected)continue;let[p4,n3]=connKey.split("-");p4===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[a2,b3]=Array.from(nets).sort();return[a2,b3]}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,netPair:[n12,n22],decouplingCapChipIds:[]},this.groupsByMainChipId.set(groupKey,group),this.outputDecouplingCapGroups.push(group)),group.decouplingCapChipIds.includes(capChipId)||group.decouplingCapChipIds.push(capChipId)}_step(){let currentChip=this.queuedChips.shift();if(this.lastChip=currentChip??null,!currentChip){this.solved=!0;return}if(!(this.isTwoPinRestrictedRotation(currentChip)&&this.pinsOnOppositeYSides(currentChip)))return;let mainChipId=this.findMainChipIdForCap(currentChip);if(!mainChipId)return;let netPair=this.getNormalizedNetPair(currentChip);if(!netPair)return;let[n12,n22]=netPair,net1=this.inputProblem.netMap[n12],net2=this.inputProblem.netMap[n22];(net1?.isGround&&net2?.isPositiveVoltageSource||net2?.isGround&&net1?.isPositiveVoltageSource)&&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}
|
|
611
611
|
${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))}};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(p4=>[p4.offset.x-p4.size.x/2,p4.offset.x+p4.size.x/2]),ys3=pads.flatMap(p4=>[p4.offset.y-p4.size.y/2,p4.offset.y+p4.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}},PIN_SIZE=.1,SingleInnerPartitionPackingSolver=class extends BaseSolver3{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 packInput=this.createPackInput();this.activeSubSolver=new PackSolver2(packInput),this.activeSubSolver=this.activeSubSolver}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(){let pinToNetworkMap=createFilteredNetworkMapping({inputProblem:this.partitionInputProblem,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}).pinToNetworkMap,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};return 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)}}),{componentId:chipId,pads,availableRotationDegrees:chip.availableRotations||[0,90,180,270]}}),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.ccwRotationOffset||packedComponent.ccwRotationDegrees||0}}return{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]}},PackInnerPartitionsSolver=class extends BaseSolver3{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];this.activeSolver=new SingleInnerPartitionPackingSolver({partitionInputProblem:currentPartition,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}),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)return super.visualize();let partitionVisualizations=this.completedSolvers.map(solver=>solver.visualize()),titles=this.completedSolvers.map((_5,index)=>`packed_partition_${index}`);return stackGraphicsHorizontally(partitionVisualizations,{titles})}getConstructorParams(){return[this.partitions]}},PartitionPackingSolver=class extends BaseSolver3{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}_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(error){this.failed=!0,this.error=`Failed to pack partitions: ${error}`}}organizePackedPartitions(){let partitionGroups=[];for(let i2=0;i2<this.packedPartitions.length;i2++){let packedPartition=this.packedPartitions[i2],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)}let bounds={minX,maxX,minY,maxY};partitionGroups.push({partitionIndex:i2,chipIds:partitionChipIds,bounds})}}return partitionGroups}createPackInput(partitionGroups){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{components:partitionGroups.map(group=>{let packedPartition=this.packedPartitions[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,pinPositions=new Map;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 transformedOffset={x:chipPin.offset.x,y:chipPin.offset.y},rotation4=chipPlacement.ccwRotationDegrees||0;rotation4===90?transformedOffset={x:-chipPin.offset.y,y:chipPin.offset.x}:rotation4===180?transformedOffset={x:-chipPin.offset.x,y:-chipPin.offset.y}:rotation4===270&&(transformedOffset={x:chipPin.offset.y,y:-chipPin.offset.x});let absolutePinX=chipPlacement.x+transformedOffset.x,absolutePinY=chipPlacement.y+transformedOffset.y;pinPositions.set(pinId,{x:absolutePinX,y:absolutePinY});let networkId=pinToNetworkMap.get(pinId)||`${pinId}_disconnected`;if(!addedNetworks.has(networkId)){addedNetworks.add(networkId);let padOffsetX=absolutePinX-centerX,padOffsetY=absolutePinY-centerY;pads.push({padId:`${group.partitionIndex}_pin_${pinId}`,networkId,type:"rect",offset:{x:padOffsetX,y:padOffsetY},size:{x:.01,y:.01}})}}}return{componentId:`partition_${group.partitionIndex}`,pads,availableRotationDegrees:[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(g7=>g7.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:{}}}visualize(){if(this.packSolver2&&!this.solved)return this.packSolver2.visualize();if(!this.finalLayout)return super.visualize();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 visualizeInputProblem(combinedProblem,this.finalLayout)}getConstructorParams(){return{packedPartitions:this.packedPartitions,inputProblem:this.inputProblem}}},getPinIdToStronglyConnectedPinsObj=inputProblem=>{let pinIdToStronglyConnectedPins={},pinIds=Object.keys(inputProblem.chipPinMap);for(let i2=0;i2<pinIds.length;i2++)for(let j4=i2+1;j4<pinIds.length;j4++){let pinId1=pinIds[i2],pinId2=pinIds[j4];(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};function definePipelineStep(solverName,solverClass,getConstructorParams,opts={}){return{solverName,solverClass,getConstructorParams,onSolved:opts.onSolved}}var LayoutPipelineSolver=class extends BaseSolver3{constructor(inputProblem){super();__publicField(this,"identifyDecouplingCapsSolver");__publicField(this,"chipPartitionsSolver");__publicField(this,"packInnerPartitionsSolver");__publicField(this,"partitionPackingSolver");__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",[definePipelineStep("identifyDecouplingCapsSolver",IdentifyDecouplingCapsSolver,()=>[this.inputProblem],{onSolved:_layoutSolver=>{}}),definePipelineStep("chipPartitionsSolver",ChipPartitionsSolver,()=>[{inputProblem:this.inputProblem,decouplingCapGroups:this.identifyDecouplingCapsSolver?.outputDecouplingCapGroups}],{onSolved:_layoutSolver=>{this.chipPartitions=this.chipPartitionsSolver.partitions}}),definePipelineStep("packInnerPartitionsSolver",PackInnerPartitionsSolver,()=>[{partitions:this.chipPartitions,pinIdToStronglyConnectedPins:this.pinIdToStronglyConnectedPins}],{onSolved:_solver=>{this.packedPartitions=this.packInnerPartitionsSolver.packedPartitions}}),definePipelineStep("partitionPackingSolver",PartitionPackingSolver,()=>[{packedPartitions:this.packedPartitions||[],inputProblem:this.inputProblem}],{onSolved:_solver=>{}})]);__publicField(this,"currentPipelineStepIndex",0);this.inputProblem=inputProblem,this.MAX_ITERATIONS=1e6,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={},this.firstIterationOfPhase={},this.pinIdToStronglyConnectedPins=getPinIdToStronglyConnectedPinsObj(inputProblem)}_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.partitionPackingSolver?.solved)return this.partitionPackingSolver.visualize();let identifyDecouplingCapsViz=this.identifyDecouplingCapsSolver?.visualize(),chipPartitionsViz=this.chipPartitionsSolver?.visualize(),packInnerPartitionsViz=this.packInnerPartitionsSolver?.visualize(),partitionPackingViz=this.partitionPackingSolver?.visualize(),basicLayout=doBasicInputProblemLayout(this.inputProblem),visualizations=[visualizeInputProblem(this.inputProblem,basicLayout),identifyDecouplingCapsViz,chipPartitionsViz,packInnerPartitionsViz,partitionPackingViz].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(v5=>v5.points||[]),rects:visualizations.flatMap(v5=>v5.rects||[]),lines:visualizations.flatMap(v5=>v5.lines||[]),circles:visualizations.flatMap(v5=>v5.circles||[]),texts:visualizations.flatMap(v5=>v5.texts||[])}}preview(){return this.activeSubSolver?this.activeSubSolver.preview():this.partitionPackingSolver?.solved?this.partitionPackingSolver.visualize():this.packInnerPartitionsSolver?.solved?this.packInnerPartitionsSolver.visualize():this.chipPartitionsSolver?.solved?this.chipPartitionsSolver.visualize():this.identifyDecouplingCapsSolver?.solved?this.identifyDecouplingCapsSolver.visualize():super.preview()}checkForOverlaps(layout){let overlaps=[],chipIds=Object.keys(layout.chipPlacements);for(let i2=0;i2<chipIds.length;i2++)for(let j4=i2+1;j4<chipIds.length;j4++){let chip1Id=chipIds[i2],chip2Id=chipIds[j4],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,size2){let halfWidth=size2.x/2,halfHeight=size2.y/2,angleRad=placement.ccwRotationDegrees*Math.PI/180,cos4=Math.abs(Math.cos(angleRad)),sin4=Math.abs(Math.sin(angleRad)),rotatedWidth=halfWidth*cos4+halfHeight*sin4,rotatedHeight=halfWidth*sin4+halfHeight*cos4;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.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 import_debug12=__toESM(require_browser(),1);init_dist4();init_dist();init_dist6();var defaultStyle={flexGrow:0,flexShrink:1,flexBasis:0,alignSelf:"auto",width:void 0,height:void 0},FlexNode=class{constructor(style={}){__publicField(this,"id");__publicField(this,"metadata");__publicField(this,"size",{width:0,height:0});__publicField(this,"position",{x:0,y:0});__publicField(this,"style");this.style={...defaultStyle,...style},this.id=style.id,this.metadata=style.metadata}},FlexElement=class extends FlexNode{build(){}},FlexBox=class _FlexBox extends FlexNode{constructor(width,height,opts={}){super({});__publicField(this,"children",[]);__publicField(this,"direction","row");__publicField(this,"columnGap",0);__publicField(this,"rowGap",0);__publicField(this,"justifyContent","flex-start");__publicField(this,"alignItems","stretch");this.size.width=width,this.size.height=height,this.id=opts.id,Object.assign(this,opts)}addChild(arg1,arg2){if(arg1 instanceof _FlexBox){let box2=arg1;return arg2&&(box2.style={...defaultStyle,...arg2}),this.children.push(box2),box2}let elem=new FlexElement(arg1);return this.children.push(elem),elem}build(){let horizontal=this.direction.startsWith("row"),mainProp=horizontal?"width":"height",crossProp=horizontal?"height":"width",mainGap=horizontal?this.columnGap:this.rowGap,crossGap=horizontal?this.rowGap:this.columnGap,gapTotal=mainGap*Math.max(0,this.children.length-1),containerMain=this.size[mainProp],containerCross=this.size[crossProp],totalBasis=0,totalGrow=0,totalShrink=0;for(let child of this.children)totalBasis+=child.style.flexBasis,totalGrow+=child.style.flexGrow,totalShrink+=child.style.flexShrink;let freeSpace=containerMain-totalBasis-gapTotal;for(let child of this.children){let main=child.style.flexBasis;freeSpace>0&&totalGrow>0?main+=freeSpace*child.style.flexGrow/totalGrow:freeSpace<0&&totalShrink>0&&(main+=freeSpace*child.style.flexShrink/totalShrink,main<0&&(main=0)),child.size[mainProp]=main;let alignSelf=child.style.alignSelf!=="auto"?child.style.alignSelf:this.alignItems,explicitCrossSize=horizontal?child.style.height:child.style.width;explicitCrossSize!==void 0?child.size[crossProp]=explicitCrossSize:alignSelf==="stretch"&&(child.size[crossProp]=containerCross)}let occupied=this.children.reduce((sum,c3)=>sum+c3.size[mainProp],0)+gapTotal,remaining=containerMain-occupied,leading=0,between=mainGap,n3=this.children.length;switch(this.justifyContent){case"flex-start":break;case"flex-end":leading=remaining;break;case"center":leading=remaining/2;break;case"space-between":between=n3>1?mainGap+remaining/(n3-1):0;break;case"space-around":between=mainGap+remaining/n3,leading=between/2;break;case"space-evenly":between=mainGap+remaining/(n3+1),leading=between;break}let ordered=this.direction.endsWith("reverse")?[...this.children].reverse():this.children,cursor=leading;for(let child of ordered)horizontal?(child.position.x=this.direction==="row"?cursor:containerMain-cursor-child.size.width,child.position.y=computeCross(child,crossProp,containerCross,this.alignItems)):(child.position.y=this.direction==="column"?cursor:containerMain-cursor-child.size.height,child.position.x=computeCross(child,crossProp,containerCross,this.alignItems)),cursor+=child.size[mainProp]+between;for(let child of this.children)child instanceof _FlexBox&&child.build();function computeCross(child,prop,containerCross2,alignItems){switch(child.style.alignSelf!=="auto"?child.style.alignSelf:alignItems){case"flex-start":return 0;case"flex-end":return containerCross2-child.size[prop];case"center":return(containerCross2-child.size[prop])/2;default:return 0}}}},RootFlexBox=class extends FlexBox{constructor(width,height,opts={}){super(width,height,opts)}getLayout(){this.build();let layoutMap={};return this._collectLayout(this,layoutMap),layoutMap}_collectLayout(box2,map,counterRef={counter:0}){for(let child of box2.children){let id=child.id??`_$$${counterRef.counter++}`;map[id]={position:child.position,size:child.size},child instanceof FlexBox&&this._collectLayout(child,map,counterRef)}}};init_dist();init_dist6();init_dist();var COLORS=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20].map(i2=>`hsl(${i2*360/21}deg, 100%, 50%)`),stringHash2=str=>{let hash=0;for(let i2=0;i2<str.length;i2++)hash=(hash<<5)-hash+str.charCodeAt(i2);return hash},getColor=str=>COLORS[Math.abs(stringHash2(str))%COLORS.length],CssGrid_convertToHtml=grid4=>{let stringifyTemplate=tpl=>tpl?typeof tpl=="string"?tpl:tpl.join(" "):void 0,s2=["display:grid","background-color:gray"],{gridTemplateRows,gridTemplateColumns,gap,justifyItems,alignItems,containerWidth,containerHeight}=grid4.opts,tRows=stringifyTemplate(gridTemplateRows);tRows&&s2.push(`grid-template-rows:${tRows}`);let tCols=stringifyTemplate(gridTemplateColumns);if(tCols&&s2.push(`grid-template-columns:${tCols}`),gap!==void 0)if(typeof gap=="number")s2.push(`gap:${gap}px`);else{let[rowGap,colGap]=gap;s2.push(`row-gap:${rowGap}px`,`column-gap:${colGap}px`)}justifyItems&&s2.push(`justify-items:${justifyItems}`),alignItems&&s2.push(`align-items:${alignItems}`),containerWidth!=null&&s2.push(`width:${containerWidth}px`),containerHeight!=null&&s2.push(`height:${containerHeight}px`);let containerStyle=s2.join(";"),childDivs=grid4.opts.children.map(c3=>{let cs3=["display:flex",`background-color:${getColor(c3.key)}`];if(c3.area)cs3.push(`grid-area:${c3.area}`);else{if(typeof c3.row=="string"&&c3.row.includes("/"))cs3.push(`grid-row:${c3.row}`);else{let start=c3.rowStart??c3.row,end=c3.rowEnd,span=c3.rowSpan;start!==void 0||end!==void 0?start!==void 0&&end!==void 0?cs3.push(`grid-row:${start} / ${end}`):start!==void 0?span!==void 0?cs3.push(`grid-row:${start} / span ${span}`):cs3.push(`grid-row-start:${start}`):cs3.push(`grid-row-end:${end}`):span!==void 0&&cs3.push(`grid-row:auto / span ${span}`)}if(typeof c3.column=="string"&&c3.column.includes("/"))cs3.push(`grid-column:${c3.column}`);else{let start=c3.columnStart??c3.column,end=c3.columnEnd,span=c3.columnSpan;start!==void 0||end!==void 0?start!==void 0&&end!==void 0?cs3.push(`grid-column:${start} / ${end}`):start!==void 0?span!==void 0?cs3.push(`grid-column:${start} / span ${span}`):cs3.push(`grid-column-start:${start}`):cs3.push(`grid-column-end:${end}`):span!==void 0&&cs3.push(`grid-column:auto / span ${span}`)}}let childStyle=cs3.join(";"),innerStyles=["font-size: 7px"];if(c3.contentWidth!==void 0){let width=typeof c3.contentWidth=="string"?c3.contentWidth:`${c3.contentWidth}px`;innerStyles.push(`width:${width}`)}else innerStyles.push(`width:${c3.key.length*5}px`);if(c3.contentHeight!==void 0){let height=typeof c3.contentHeight=="string"?c3.contentHeight:`${c3.contentHeight}px`;innerStyles.push(`height:${height}`)}let innerStyle=innerStyles.join(";");return` <div id="${c3.key}" style="${childStyle}"><div style="${innerStyle}">${c3.key}</div></div>`});return`<div style="${containerStyle}">
|
|
@@ -614,12 +614,12 @@ ${childDivs.join(`
|
|
|
614
614
|
</div>`},CssGrid_visualize=grid4=>{let layout=grid4.layout(),go3={title:"CssGrid",coordinateSystem:"screen",lines:[],circles:[],points:[],rects:[],texts:[]},{cells}=layout;for(let cell of cells){let{x:x5,y:y5,width,height,key}=cell;go3.rects.push({center:{x:x5+width/2,y:y5+height/2},width,height,fill:getColor(key),label:key})}return go3};function expandRepeat(templateStr){return templateStr.replace(/repeat\((\d+),\s*([^)]+)\)/g,(_5,count,val)=>Array(Number(count)).fill(val.trim()).join(" "))}function tokenize(templateStr){return templateStr.trim().split(/\s+/).filter(Boolean)}function countTracks(tpl){return tpl?tokenize(expandRepeat(tpl)).length:0}function pxFromToken(token,containerSize){if(token==="auto")return{fr:1};if(token.endsWith("%")){let n22=parseFloat(token);return containerSize!=null?containerSize*n22/100:0}if(token.endsWith("px"))return parseFloat(token);if(token.endsWith("em"))return parseFloat(token)*16;if(token.endsWith("fr"))return{fr:parseFloat(token)};let n3=parseFloat(token);return Number.isNaN(n3)?0:n3}function resolveNegativeLine(idx,trackCnt){return idx>0?idx:trackCnt+2+idx}var CssGrid_layout=grid4=>{let opts=grid4.opts,children=opts.children,rowsTpl,colsTpl;if("gridTemplate"in opts&&typeof opts.gridTemplate=="string"){let[rows,cols]=opts.gridTemplate.split("/");rowsTpl=rows?.trim(),colsTpl=cols?.trim()}else rowsTpl=typeof opts.gridTemplateRows=="string"?opts.gridTemplateRows:void 0,colsTpl=typeof opts.gridTemplateColumns=="string"?opts.gridTemplateColumns:void 0;let columnTrackCountDeclared=countTracks(colsTpl),rowTrackCountDeclared=countTracks(rowsTpl);function calculateMinimumContainerSize(tpl,children2,isWidth,gap){if(!tpl)return 0;let expanded=expandRepeat(tpl),tokens=tokenize(expanded),trackCount=tokens.length,minContentSize=0,hasFlexibleTracks=!1;for(let i2=0;i2<tokens.length;i2++){let token=tokens[i2];if(token.endsWith("px"))minContentSize+=parseFloat(token);else if(token.endsWith("em"))minContentSize+=parseFloat(token)*16;else if(token.endsWith("fr")||token==="auto"){hasFlexibleTracks=!0;let maxContentInTrack=0;for(let child of children2){let childStart=isWidth?child.columnStart||child.column:child.rowStart||child.row,childSpan=isWidth?child.columnSpan||1:child.rowSpan||1,contentSize=isWidth?child.contentWidth:child.contentHeight,startIdx=(typeof childStart=="number"?childStart:parseInt(childStart||"1"))-1,span=typeof childSpan=="number"?childSpan:parseInt(childSpan.toString());if(startIdx<=i2&&i2<startIdx+span&&contentSize){let size2=typeof contentSize=="string"&&contentSize.endsWith("px")?parseFloat(contentSize):typeof contentSize=="number"?contentSize:0;maxContentInTrack=Math.max(maxContentInTrack,size2/span)}}minContentSize+=maxContentInTrack}}let totalGaps=gap*(trackCount-1);return minContentSize+totalGaps}function buildTrackSizes(tpl,containerSize,gap,isWidth=!0,crossTrackCount=1){if(!tpl)return[];if(containerSize==null){let expanded2=expandRepeat(tpl),tokens2=tokenize(expanded2),trackCnt=tokens2.length,toPx=v5=>v5===void 0?0:typeof v5=="number"?v5:(v5.endsWith("px"),parseFloat(v5)),sizes2=new Array(trackCnt).fill(0),autoCursor=0;for(let child of children){let span=isWidth?typeof child.columnSpan=="number"?child.columnSpan:child.columnSpan?parseInt(child.columnSpan.toString()):1:typeof child.rowSpan=="number"?child.rowSpan:child.rowSpan?parseInt(child.rowSpan.toString()):1,rawSize=isWidth?child.contentWidth:child.contentHeight,sizePerTrack=toPx(rawSize)/span,startIdx;isWidth?(child.columnStart!==void 0||child.column!==void 0)&&(startIdx=parseInt(child.columnStart??child.column)-1):(child.rowStart!==void 0||child.row!==void 0)&&(startIdx=parseInt(child.rowStart??child.row)-1),(startIdx===void 0||Number.isNaN(startIdx))&&(isWidth?startIdx=autoCursor%trackCnt:startIdx=Math.floor(autoCursor/crossTrackCount),autoCursor+=span);for(let i2=0;i2<span&&startIdx+i2<trackCnt;i2++)sizes2[startIdx+i2]=Math.max(sizes2[startIdx+i2],sizePerTrack)}return tokens2.forEach((tok,idx)=>{let px2=pxFromToken(tok,void 0);typeof px2=="number"&&(sizes2[idx]=px2)}),sizes2}let expanded=expandRepeat(tpl),tokens=tokenize(expanded),trackCount=tokens.length,effectiveContainerSize=containerSize;effectiveContainerSize==null&&(effectiveContainerSize=calculateMinimumContainerSize(tpl,children,isWidth,gap));let sizeForTracks=effectiveContainerSize-gap*(trackCount-1),sumFixed=0,totalFr=0,frTokens=[],sizes=[];tokens.forEach((token,i2)=>{let px2=pxFromToken(token,sizeForTracks);typeof px2=="number"?(sizes.push(px2),sumFixed+=px2):px2&&typeof px2=="object"&&"fr"in px2?(sizes.push(px2),totalFr+=px2.fr,frTokens.push({idx:i2,fr:px2.fr})):(sizes.push(0),sumFixed+=0)});let free=Math.max(sizeForTracks-sumFixed,0);return sizes.map(v5=>typeof v5=="number"?v5:totalFr>0?free/totalFr*v5.fr:0)}let rowGap=typeof opts.gap=="number"?opts.gap:Array.isArray(opts.gap)?opts.gap[0]:0,columnGap=typeof opts.gap=="number"?opts.gap:Array.isArray(opts.gap)?opts.gap[1]:0,rowSizes=buildTrackSizes(rowsTpl,opts.containerHeight,rowGap,!1,columnTrackCountDeclared||1),columnSizes=buildTrackSizes(colsTpl,opts.containerWidth,columnGap,!0,rowTrackCountDeclared||1),rowCount=rowSizes.length,colCount=columnSizes.length;colCount===0&&children.length>0&&(colCount=1);let cells=[],nextAutoCell=0;for(let child of children){let rowStart=child.rowStart!==void 0?child.rowStart:child.row,colStart=child.columnStart!==void 0?child.columnStart:child.column,rowSpan=child.rowSpan!==void 0?typeof child.rowSpan=="string"?parseInt(child.rowSpan):child.rowSpan:1,colSpan=child.columnSpan!==void 0?typeof child.columnSpan=="string"?parseInt(child.columnSpan):child.columnSpan:1;if(child.rowEnd!==void 0){let end=typeof child.rowEnd=="string"?parseInt(child.rowEnd):child.rowEnd;rowStart!==void 0?rowSpan=end-(typeof rowStart=="string"?parseInt(rowStart):rowStart):rowStart=end-rowSpan}if(child.columnEnd!==void 0){let end=typeof child.columnEnd=="string"?parseInt(child.columnEnd):child.columnEnd;colStart!==void 0?colSpan=end-(typeof colStart=="string"?parseInt(colStart):colStart):colStart=end-colSpan}if(typeof rowStart=="string"&&(rowStart=parseInt(rowStart)),typeof colStart=="string"&&(colStart=parseInt(colStart)),typeof rowStart=="number"&&rowStart<0&&(rowStart=resolveNegativeLine(rowStart,rowCount)),typeof colStart=="number"&&colStart<0&&(colStart=resolveNegativeLine(colStart,colCount)),rowStart===void 0&&colStart!==void 0)rowStart=1;else if(colStart===void 0&&rowStart!==void 0)colStart=1;else if(rowStart===void 0&&colStart===void 0){let idx=nextAutoCell;rowStart=Math.floor(idx/colCount)+1,colStart=idx%colCount+1}let row=rowStart-1,column=colStart-1;rowSpan=Math.max(1,rowSpan),colSpan=Math.max(1,colSpan),cells.push({key:child.key,row,column,rowSpan,columnSpan:colSpan,x:0,y:0,width:0,height:0}),nextAutoCell+=colSpan}let maxRow=rowSizes.length,maxCol=columnSizes.length;for(let cell of cells)cell.row+cell.rowSpan>maxRow&&(maxRow=cell.row+cell.rowSpan),cell.column+cell.columnSpan>maxCol&&(maxCol=cell.column+cell.columnSpan);if(rowSizes.length===0&&maxRow>0&&opts.containerHeight){let implicitRowCount=maxRow,implicitRowHeight=(opts.containerHeight-rowGap*(implicitRowCount-1))/implicitRowCount;for(let i2=0;i2<implicitRowCount;i2++)rowSizes.push(implicitRowHeight)}else for(;rowSizes.length<maxRow;)rowSizes.push(0);if(columnSizes.length===0&&maxCol>0&&opts.containerWidth){let implicitColCount=maxCol,implicitColWidth=(opts.containerWidth-columnGap*(implicitColCount-1))/implicitColCount;for(let i2=0;i2<implicitColCount;i2++)columnSizes.push(implicitColWidth)}else if(columnSizes.length===0&&children.length>0&&opts.containerWidth)columnSizes.push(opts.containerWidth);else for(;columnSizes.length<maxCol;)columnSizes.push(0);let getPositionFromTracks=(trackIndex,trackSizes,gap)=>{let position2=0;for(let i2=0;i2<trackIndex;i2++)position2+=trackSizes[i2]||0,position2+=gap;return position2},getSizeFromSpan=(trackIndex,span,trackSizes,gap)=>{let size2=0;for(let i2=trackIndex;i2<trackIndex+span;i2++)size2+=trackSizes[i2]||0,i2>trackIndex&&(size2+=gap);return size2},itemCoordinates={};for(let cell of cells){let child=children.find(c3=>c3.key===cell.key),cellX=getPositionFromTracks(cell.column,columnSizes,columnGap),cellY=getPositionFromTracks(cell.row,rowSizes,rowGap),cellWidth=getSizeFromSpan(cell.column,cell.columnSpan,columnSizes,columnGap),cellHeight=getSizeFromSpan(cell.row,cell.rowSpan,rowSizes,rowGap),getContentDimension=value=>value===void 0?0:typeof value=="string"?value.endsWith("px")?parseFloat(value):value.endsWith("%")?0:parseFloat(value):value,contentWidth=getContentDimension(child?.contentWidth),contentHeight=getContentDimension(child?.contentHeight),itemWidth=cellWidth,itemHeight=cellHeight,itemX=cellX,itemY=cellY;if(contentWidth>0)switch(itemWidth=contentWidth,opts.justifyItems||"stretch"){case"start":itemX=cellX;break;case"end":itemX=cellX+cellWidth-itemWidth;break;case"center":itemX=cellX+(cellWidth-itemWidth)/2;break;case"stretch":itemWidth=cellWidth,itemX=cellX;break}if(contentHeight>0)switch(itemHeight=contentHeight,opts.alignItems||"stretch"){case"start":itemY=cellY;break;case"end":itemY=cellY+cellHeight-itemHeight;break;case"center":itemY=cellY+(cellHeight-itemHeight)/2;break;case"stretch":itemHeight=cellHeight,itemY=cellY;break}cell.x=itemX,cell.y=itemY,cell.width=itemWidth,cell.height=itemHeight,itemCoordinates[cell.key]={x:itemX,y:itemY,width:itemWidth,height:itemHeight}}return{cells,rowSizes,columnSizes,rowGap,columnGap,itemCoordinates}},CssGrid=class{constructor(opts){__publicField(this,"opts");this.opts=opts}layout(){return CssGrid_layout(this)}convertToHtml(){return CssGrid_convertToHtml(this)}visualize(){return CssGrid_visualize(this)}};init_dist();var import_debug13=__toESM(require_browser(),1);init_dist6();init_dist6();init_dist();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 id of ids)this.idToNetMap[id]=netId}addConnections(connections){for(let connection of connections){let existingNets=new Set;for(let id of connection){let existingNetId=this.idToNetMap[id];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 id of targetNet)this.idToNetMap[id]=targetNetId}}}for(let id of connection){let targetNet=this.netMap[targetNetId];targetNet&&!targetNet.includes(id)&&targetNet.push(id),this.idToNetMap[id]=targetNetId}}}getIdsConnectedToNet(netId){return this.netMap[netId]||[]}getNetConnectedToId(id){return this.idToNetMap[id]}areIdsConnected(id1,id2){if(id1===id2)return!0;let netId1=this.getNetConnectedToId(id1);if(!netId1)return!1;let netId2=this.getNetConnectedToId(id2);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 id of ids){let nextNetId=this.getNetConnectedToId(id);if(nextNetId===void 0||nextNetId!==netId)return!1}return!0}};init_dist5();var FlatQueue=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(item,priority){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 id=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]=id,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(){this.ids.length=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||data.buffer)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 version=versionAndType>>4;if(version!==VERSION)throw new Error(`Got v${version} 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}.`);if(data)this.data=data,this._boxes=new ArrayType(data,byteOffset+8,numNodes*4),this._indices=new this.IndexArrayType(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 ArrayType(data2,8,numNodes*4),this._indices=new this.IndexArrayType(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 index=this._pos>>2,boxes=this._boxes;return this._indices[index]=index,boxes[this._pos++]=minX,boxes[this._pos++]=minY,boxes[this._pos++]=maxX,boxes[this._pos++]=maxY,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 width=this.maxX-this.minX||1,height=this.maxY-this.minY||1,hilbertValues=new Uint32Array(this.numItems),hilbertMax=65535;for(let i2=0,pos=0;i2<this.numItems;i2++){let minX=boxes[pos++],minY=boxes[pos++],maxX=boxes[pos++],maxY=boxes[pos++],x5=Math.floor(hilbertMax*((minX+maxX)/2-this.minX)/width),y5=Math.floor(hilbertMax*((minY+maxY)/2-this.minY)/height);hilbertValues[i2]=hilbert(x5,y5)}sort(hilbertValues,boxes,this._indices,0,this.numItems-1,this.nodeSize);for(let i2=0,pos=0;i2<this._levelBounds.length-1;i2++){let end=this._levelBounds[i2];for(;pos<end;){let nodeIndex=pos,nodeMinX=boxes[pos++],nodeMinY=boxes[pos++],nodeMaxX=boxes[pos++],nodeMaxY=boxes[pos++];for(let j4=1;j4<this.nodeSize&&pos<end;j4++)nodeMinX=Math.min(nodeMinX,boxes[pos++]),nodeMinY=Math.min(nodeMinY,boxes[pos++]),nodeMaxX=Math.max(nodeMaxX,boxes[pos++]),nodeMaxY=Math.max(nodeMaxY,boxes[pos++]);this._indices[this._pos>>2]=nodeIndex,boxes[this._pos++]=nodeMinX,boxes[this._pos++]=nodeMinY,boxes[this._pos++]=nodeMaxX,boxes[this._pos++]=nodeMaxY}}}search(minX,minY,maxX,maxY,filterFn){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let nodeIndex=this._boxes.length-4,queue=[],results=[];for(;nodeIndex!==void 0;){let end=Math.min(nodeIndex+this.nodeSize*4,upperBound(nodeIndex,this._levelBounds));for(let pos=nodeIndex;pos<end;pos+=4){let x02=this._boxes[pos];if(maxX<x02)continue;let y02=this._boxes[pos+1];if(maxY<y02)continue;let x12=this._boxes[pos+2];if(minX>x12)continue;let y12=this._boxes[pos+3];if(minY>y12)continue;let index=this._indices[pos>>2]|0;nodeIndex>=this.numItems*4?queue.push(index):(filterFn===void 0||filterFn(index,x02,y02,x12,y12))&&results.push(index)}nodeIndex=queue.pop()}return results}neighbors(x5,y5,maxResults=1/0,maxDistance=1/0,filterFn){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let nodeIndex=this._boxes.length-4,q4=this._queue,results=[],maxDistSquared=maxDistance*maxDistance;outer:for(;nodeIndex!==void 0;){let end=Math.min(nodeIndex+this.nodeSize*4,upperBound(nodeIndex,this._levelBounds));for(let pos=nodeIndex;pos<end;pos+=4){let index=this._indices[pos>>2]|0,minX=this._boxes[pos],minY=this._boxes[pos+1],maxX=this._boxes[pos+2],maxY=this._boxes[pos+3],dx2=x5<minX?minX-x5:x5>maxX?x5-maxX:0,dy2=y5<minY?minY-y5:y5>maxY?y5-maxY:0,dist=dx2*dx2+dy2*dy2;dist>maxDistSquared||(nodeIndex>=this.numItems*4?q4.push(index<<1,dist):(filterFn===void 0||filterFn(index))&&q4.push((index<<1)+1,dist))}for(;q4.length&&q4.peek()&1;)if(q4.peekValue()>maxDistSquared||(results.push(q4.pop()>>1),results.length===maxResults))break outer;nodeIndex=q4.length?q4.pop()>>1:void 0}return q4.clear(),results}};function upperBound(value,arr){let i2=0,j4=arr.length-1;for(;i2<j4;){let m3=i2+j4>>1;arr[m3]>value?j4=m3:i2=m3+1}return arr[i2]}function sort(values,boxes,indices,left,right,nodeSize){if(Math.floor(left/nodeSize)>=Math.floor(right/nodeSize))return;let start=values[left],mid=values[left+right>>1],end=values[right],pivot=end,x5=Math.max(start,mid);end>x5?pivot=x5:x5===start?pivot=Math.max(mid,end):x5===mid&&(pivot=Math.max(start,end));let i2=left-1,j4=right+1;for(;;){do i2++;while(values[i2]<pivot);do j4--;while(values[j4]>pivot);if(i2>=j4)break;swap(values,boxes,indices,i2,j4)}sort(values,boxes,indices,left,j4,nodeSize),sort(values,boxes,indices,j4+1,right,nodeSize)}function swap(values,boxes,indices,i2,j4){let temp=values[i2];values[i2]=values[j4],values[j4]=temp;let k4=4*i2,m3=4*j4,a2=boxes[k4],b3=boxes[k4+1],c3=boxes[k4+2],d3=boxes[k4+3];boxes[k4]=boxes[m3],boxes[k4+1]=boxes[m3+1],boxes[k4+2]=boxes[m3+2],boxes[k4+3]=boxes[m3+3],boxes[m3]=a2,boxes[m3+1]=b3,boxes[m3+2]=c3,boxes[m3+3]=d3;let e4=indices[i2];indices[i2]=indices[j4],indices[j4]=e4}function hilbert(x5,y5){let a2=x5^y5,b3=65535^a2,c3=65535^(x5|y5),d3=x5&(y5^65535),A4=a2|b3>>1,B5=a2>>1^a2,C4=c3>>1^b3&d3>>1^c3,D6=a2&c3>>1^d3>>1^d3;a2=A4,b3=B5,c3=C4,d3=D6,A4=a2&a2>>2^b3&b3>>2,B5=a2&b3>>2^b3&(a2^b3)>>2,C4^=a2&c3>>2^b3&d3>>2,D6^=b3&c3>>2^(a2^b3)&d3>>2,a2=A4,b3=B5,c3=C4,d3=D6,A4=a2&a2>>4^b3&b3>>4,B5=a2&b3>>4^b3&(a2^b3)>>4,C4^=a2&c3>>4^b3&d3>>4,D6^=b3&c3>>4^(a2^b3)&d3>>4,a2=A4,b3=B5,c3=C4,d3=D6,C4^=a2&c3>>8^b3&d3>>8,D6^=b3&c3>>8^(a2^b3)&d3>>8,a2=C4^C4>>1,b3=D6^D6>>1;let i02=x5^y5,i12=b3|65535^(i02|a2);return i02=(i02|i02<<8)&16711935,i02=(i02|i02<<4)&252645135,i02=(i02|i02<<2)&858993459,i02=(i02|i02<<1)&1431655765,i12=(i12|i12<<8)&16711935,i12=(i12|i12<<4)&252645135,i12=(i12|i12<<2)&858993459,i12=(i12|i12<<1)&1431655765,(i12<<1|i02)>>>0}var BaseSolver4=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(e4){throw this.error=`${this.constructor.name} error: ${e4}`,this.failed=!0,e4}!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:[]}}},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 p4 of pins){if(seen.has(p4.pinId))throw new Error(`Duplicate pinId detected: "${p4.pinId}"`);seen.add(p4.pinId)}}let manhattan=(a2,b3)=>Math.abs(a2.x-b3.x)+Math.abs(a2.y-b3.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 i2=1;i2<n3;i2++)pins[i2].pinId<pins[startIndex].pinId&&(startIndex=i2);bestDist[startIndex]=0;let edges=[];for(let iter=0;iter<n3;iter++){let u4=-1,best=Number.POSITIVE_INFINITY,bestId="";for(let i2=0;i2<n3;i2++)if(!inTree[i2]){let d3=bestDist[i2];(d3<best||d3===best&&(bestId===""||pins[i2].pinId<bestId))&&(best=d3,bestId=pins[i2].pinId,u4=i2)}inTree[u4]=!0,parent[u4]!==-1&&edges.push([pins[u4].pinId,pins[parent[u4]].pinId]);for(let v5=0;v5<n3;v5++)if(!inTree[v5]){let d02=manhattan(pins[u4],pins[v5]),isForbidden=opts?.forbidEdge?.(pins[u4],pins[v5])??!1,d3=d02>maxDistance||isForbidden?Number.POSITIVE_INFINITY:d02;(d3<bestDist[v5]||d3===bestDist[v5]&&pins[u4].pinId<pins[parent[v5]]?.pinId)&&(bestDist[v5]=d3,parent[v5]=u4)}}return edges}var getPinDirection2=(pin,chip)=>{let{x:x5,y:y5}=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-y5,yMinusDistance=y5-yMinusEdge,xPlusDistance=xPlusEdge-x5,xMinusDistance=x5-xMinusEdge,minDistance=Math.min(yPlusDistance,yMinusDistance,xPlusDistance,xMinusDistance);return minDistance===yPlusDistance?"y+":minDistance===yMinusDistance?"y-":minDistance===xPlusDistance?"x+":"x-"},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 p4 of dc2.pinIds)visited.has(p4)||(visited.add(p4),queue.push(p4))}return visited},p02=pins[0].pinId,p12=pins[1].pinId,relatedPinIds=new Set([...findAllDirectlyConnectedPins(p02),...findAllDirectlyConnectedPins(p12)]),restrictedCenterLines=new Map,chipFacingMap=new Map,chipsOfFacingPins=new Set(pins.map(p4=>p4.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??getPinDirection2(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 cp of chip.pins){let cpFacing=cp._facingDirection??getPinDirection2(cp,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 EPS52=1e-9,crossesSegment=(a2,b3)=>{for(let[,rcl]of restrictedCenterLines)if(rcl.axes.has("x")&&typeof rcl.x=="number"&&(a2.x-rcl.x)*(b3.x-rcl.x)<-EPS52||rcl.axes.has("y")&&typeof rcl.y=="number"&&(a2.y-rcl.y)*(b3.y-rcl.y)<-EPS52)return!0;return!1};if(Math.abs(p12.x-p22.x)<EPS52||Math.abs(p12.y-p22.y)<EPS52)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},getColorFromString2=(string,alpha=1)=>`hsl(${string.split("").reduce((acc,char)=>acc*31+char.charCodeAt(0),0)%360}, 100%, 50%, ${alpha})`,visualizeInputProblem2=(inputProblem,opts={})=>{let{connectionAlpha=.8,chipAlpha=.8}=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.pinId}
|
|
615
615
|
${pin._facingDirection??getPinDirection2(pin,chip)}`,x:pin.x,y:pin.y,color:getColorFromString2(pin.pinId,.8)})}for(let directConn of inputProblem.directConnections){let[pinId1,pinId2]=directConn.pinIds,pin1=pinIdMap.get(pinId1),pin2=pinIdMap.get(pinId2);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 i2=0;i2<pins.length-1;i2++)for(let j4=i2+1;j4<pins.length;j4++){let pin1=pins[i2],pin2=pins[j4];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},MspConnectionPairSolver=class extends BaseSolver4{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");this.inputProblem=inputProblem,this.maxMspPairDistance=inputProblem.maxMspPairDistance??1;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={};for(let dc2 of inputProblem.directConnections)if(dc2.netId){let[a2,b3]=dc2.pinIds;this.userNetIdByPinId[a2]=dc2.netId,this.userNetIdByPinId[b3]=dc2.netId}for(let nc2 of inputProblem.netConnections)for(let pid of nc2.pinIds)this.userNetIdByPinId[pid]=nc2.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(id=>!!this.pinMap[id]);if(directlyConnectedPins.length<=1)return;if(directlyConnectedPins.length===2){let[pin1,pin2]=directlyConnectedPins,p12=this.pinMap[pin1],p22=this.pinMap[pin2];if(Math.abs(p12.x-p22.x)+Math.abs(p12.y-p22.y)>this.maxMspPairDistance)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];this.mspConnectionPairs.push({mspPairId:`${pin1}-${pin2}`,dcConnNetId:dcNetId,globalConnNetId,userNetId,pins:[p12,p22]});return}let pinIdMap=new Map(Object.entries(this.pinMap)),msp=getOrthogonalMinimumSpanningTree(directlyConnectedPins.map(p4=>this.pinMap[p4]).filter(Boolean),{maxDistance:this.maxMspPairDistance,forbidEdge:(a2,b3)=>doesPairCrossRestrictedCenterLines({inputProblem:this.inputProblem,chipMap:this.chipMap,pinIdMap,p1:a2,p2:b3})});for(let[pin1,pin2]of msp){let p1Obj=this.pinMap[pin1],p2Obj=this.pinMap[pin2];if(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}};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 chipToRect=chip=>{let b3=getInputChipBounds(chip);return{chipId:chip.chipId,...b3}},getObstacleRects=problem=>problem.chips.map(chipToRect),EPS2=1e-9,isVertical=(a2,b3,eps=EPS2)=>Math.abs(a2.x-b3.x)<eps,isHorizontal=(a2,b3,eps=EPS2)=>Math.abs(a2.y-b3.y)<eps,segmentIntersectsRect=(a2,b3,r4,eps=EPS2)=>{let vert=isVertical(a2,b3,eps),horz=isHorizontal(a2,b3,eps);if(!vert&&!horz)return!1;if(vert){let x5=a2.x;if(x5<r4.minX-eps||x5>r4.maxX+eps)return!1;let segMinY=Math.min(a2.y,b3.y),segMaxY=Math.max(a2.y,b3.y);return Math.min(segMaxY,r4.maxY)-Math.max(segMinY,r4.minY)>eps}else{let y5=a2.y;if(y5<r4.minY-eps||y5>r4.maxY+eps)return!1;let segMinX=Math.min(a2.x,b3.x),segMaxX=Math.max(a2.x,b3.x);return Math.min(segMaxX,r4.maxX)-Math.max(segMinX,r4.minX)>eps}},findFirstCollision=(pts,rects,opts={})=>{for(let i2=0;i2<pts.length-1;i2++){let a2=pts[i2],b3=pts[i2+1],excluded=opts.excludeRectIdsForSegment?.(i2)??new Set;for(let r4 of rects)if(!excluded.has(r4.chipId)&&segmentIntersectsRect(a2,b3,r4))return{segIndex:i2,rect:r4}}return null},isPathCollidingWithObstacles=(path,obstacles)=>{for(let i2=0;i2<path.length-1;i2++)for(let obstacle of obstacles)if(segmentIntersectsRect(path[i2],path[i2+1],obstacle))return!0;return!1},EPS22=1e-9,aabbFromPoints=(a2,b3)=>({minX:Math.min(a2.x,b3.x),maxX:Math.max(a2.x,b3.x),minY:Math.min(a2.y,b3.y),maxY:Math.max(a2.y,b3.y)}),midBetweenPointAndRect=(axis,p4,r4,eps=EPS22)=>axis==="x"?p4.x<r4.minX-eps?[(p4.x+r4.minX)/2]:p4.x>r4.maxX+eps?[(p4.x+r4.maxX)/2]:[r4.minX-.2,r4.maxX+.2]:p4.y<r4.minY-eps?[(p4.y+r4.minY)/2]:p4.y>r4.maxY+eps?[(p4.y+r4.maxY)/2]:[r4.minY-.2,r4.maxY+.2],candidateMidsFromSet=(axis,colliding,rectsById,collisionRectIds,aabb,eps=EPS22)=>{let setRects=[...collisionRectIds].map(id=>rectsById.get(id)).filter(r4=>!!r4);if(axis==="x"){let leftBoundaries=[aabb.minX,...setRects.map(r4=>r4.maxX)].filter(v5=>v5<colliding.minX-eps),rightBoundaries=[aabb.maxX,...setRects.map(r4=>r4.minX)].filter(v5=>v5>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),rightNeighbor!==void 0&&out.push((colliding.maxX+rightNeighbor)/2),out}else{let bottomBoundaries=[aabb.minY,...setRects.map(r4=>r4.maxY)].filter(v5=>v5<colliding.minY-eps),topBoundaries=[aabb.maxY,...setRects.map(r4=>r4.minY)].filter(v5=>v5>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),topNeighbor!==void 0&&out.push((colliding.maxY+topNeighbor)/2),out}},EPS3=1e-9,shiftSegmentOrth=(pts,segIndex,axis,newCoord,eps=EPS3)=>{if(segIndex<0||segIndex>=pts.length-1)return null;let a2=pts[segIndex],b3=pts[segIndex+1],vert=isVertical(a2,b3,eps),horz=isHorizontal(a2,b3,eps);if(!vert&&!horz||vert&&axis!=="x"||horz&&axis!=="y")return null;let out=pts.map(p4=>({...p4}));if(axis==="x"){if(Math.abs(a2.x-newCoord)<eps&&Math.abs(b3.x-newCoord)<eps)return null;out[segIndex]={...out[segIndex],x:newCoord},out[segIndex+1]={...out[segIndex+1],x:newCoord}}else{if(Math.abs(a2.y-newCoord)<eps&&Math.abs(b3.y-newCoord)<eps)return null;out[segIndex]={...out[segIndex],y:newCoord},out[segIndex+1]={...out[segIndex+1],y:newCoord}}if(segIndex-1>=0){let p4=out[segIndex-1],q4=out[segIndex];if(Math.abs(p4.x-q4.x)+Math.abs(p4.y-q4.y)<eps)return null}if(segIndex+2<=out.length-1){let p4=out[segIndex+1],q4=out[segIndex+2];if(Math.abs(p4.x-q4.x)+Math.abs(p4.y-q4.y)<eps)return null}for(let i2=0;i2<out.length-1;i2++){let u4=out[i2],v5=out[i2+1];if(!isHorizontal(u4,v5,eps)&&!isVertical(u4,v5,eps))return null}return out},pathKey=(pts,decimals=6)=>pts.map(p4=>`${p4.x.toFixed(decimals)},${p4.y.toFixed(decimals)}`).join("|"),SchematicTraceSingleLineSolver2=class extends BaseSolver4{constructor(params){super();__publicField(this,"pins");__publicField(this,"inputProblem");__publicField(this,"chipMap");__publicField(this,"obstacles");__publicField(this,"rectById");__publicField(this,"aabb");__publicField(this,"baseElbow");__publicField(this,"solvedTracePath",null);__publicField(this,"queue",[]);__publicField(this,"visited",new Set);this.pins=params.pins,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=getPinDirection2(pin,chip)}this.obstacles=getObstacleRects(this.inputProblem),this.rectById=new Map(this.obstacles.map(r4=>[r4.chipId,r4]));let[pin1,pin2]=this.pins;this.baseElbow=calculateElbow({x:pin1.x,y:pin1.y,facingDirection:pin1._facingDirection},{x:pin2.x,y:pin2.y,facingDirection:pin2._facingDirection},{overshoot:.2}),this.aabb=aabbFromPoints({x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}),this.queue.push({path:this.baseElbow,collisionChipIds:new Set}),this.visited.add(pathKey(this.baseElbow))}getConstructorParams(){return{chipMap:this.chipMap,pins:this.pins,inputProblem:this.inputProblem}}axisOfSegment(a2,b3){return isVertical(a2,b3)?"x":isHorizontal(a2,b3)?"y":null}pathLength(pts){let sum=0;for(let i2=0;i2<pts.length-1;i2++)sum+=Math.abs(pts[i2+1].x-pts[i2].x)+Math.abs(pts[i2+1].y-pts[i2].y);return sum}_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,collisionChipIds}=state2,[PA,PB]=this.pins,collision=findFirstCollision(path,this.obstacles);if(!collision){let first=path[0],last=path[path.length-1],EPS52=1e-9,samePoint=(p4,q4)=>Math.abs(p4.x-q4.x)<EPS52&&Math.abs(p4.y-q4.y)<EPS52;samePoint(first,{x:PA.x,y:PA.y})&&samePoint(last,{x:PB.x,y:PB.y})&&(this.solvedTracePath=path,this.solved=!0);return}let{segIndex,rect}=collision,isFirstSegment=segIndex===0,isLastSegment=segIndex===path.length-2;if(isFirstSegment){if(path.length<3)return;segIndex=1}else if(isLastSegment){if(path.length<3)return;segIndex=path.length-3}let a2=path[segIndex],b3=path[segIndex+1],axis=this.axisOfSegment(a2,b3);if(!axis)return;let candidates=[];if(collisionChipIds.size===0){let m12=midBetweenPointAndRect(axis,{x:PA.x,y:PA.y},rect),m22=midBetweenPointAndRect(axis,{x:PB.x,y:PB.y},rect),allCandidates=[...m12,...m22],uniqueCandidates=[...new Set(allCandidates)];candidates.push(...uniqueCandidates)}else{let mids=candidateMidsFromSet(axis,rect,this.rectById,collisionChipIds,this.aabb);candidates.push(...mids)}let newStates=[];for(let coord of candidates){let newPath=shiftSegmentOrth(path,segIndex,axis,coord);if(!newPath)continue;let key=pathKey(newPath);if(this.visited.has(key))continue;this.visited.add(key);let nextSet=new Set(collisionChipIds);nextSet.add(rect.chipId);let len=this.pathLength(newPath);newStates.push({path:newPath,collisionRectIds:nextSet,len})}newStates.sort((a22,b22)=>a22.len-b22.len);for(let st4 of newStates)this.queue.push({path:st4.path,collisionChipIds:st4.collisionRectIds})}visualize(){let g7=visualizeInputProblem2(this.inputProblem,{chipAlpha:.1,connectionAlpha:.1});g7.lines.push({points:this.baseElbow,strokeColor:"red",strokeDash:"4 4"});let[pin1,pin2]=this.pins;g7.lines.push({points:[{x:pin1.x,y:pin1.y},{x:pin2.x,y:pin2.y}],strokeColor:"blue",strokeDash:"5 5"});for(let{path,collisionChipIds:collisionRectIds}of this.queue)g7.lines.push({points:path,strokeColor:"teal",strokeDash:"2 2"});return this.solvedTracePath?g7.lines.push({points:this.solvedTracePath,strokeColor:"green"}):this.queue.length>0&&g7.lines.push({points:this.queue[0].path,strokeColor:"orange"}),g7}},SchematicTraceLinesSolver=class extends BaseSolver4{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,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:si2,offset,JOG_SIZE,EPS:EPS52=1e-6})=>{if(si2!==0&&si2!==pts.length-2)return;let start=pts[si2],end=pts[si2+1],isVertical3=Math.abs(start.x-end.x)<EPS52,isHorizontal2=Math.abs(start.y-end.y)<EPS52;if(!isVertical3&&!isHorizontal2)return;let segDir=isVertical3?end.y>start.y?1:-1:end.x>start.x?1:-1;if(si2===0)if(isVertical3){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(isVertical3){let jogY=end.y-segDir*JOG_SIZE;pts.splice(si2,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(si2,1,{x:start.x,y:start.y+offset},{x:jogX,y:end.y+offset},{x:jogX,y:end.y})}},TraceOverlapIssueSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"overlappingTraceSegments");__publicField(this,"traceNetIslands");__publicField(this,"SHIFT_DISTANCE",.1);__publicField(this,"correctedTraceMap",{});this.overlappingTraceSegments=params.overlappingTraceSegments,this.traceNetIslands=params.traceNetIslands;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 offsets=this.overlappingTraceSegments.map((_5,idx)=>{let n3=Math.floor(idx/2)+1;return(idx%2===0?-n3:n3)*this.SHIFT_DISTANCE}),eq=(a2,b3)=>Math.abs(a2-b3)<1e-6,samePoint=(p4,q4)=>!!p4&&!!q4&&eq(p4.x,q4.x)&&eq(p4.y,q4.y);this.overlappingTraceSegments.forEach((group,gidx)=>{let offset=offsets[gidx],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],current2=this.correctedTraceMap[original.mspPairId]??original,pts=current2.tracePath.map(p4=>({...p4})),segIdxs=Array.from(segIdxSet).sort((a2,b3)=>a2-b3),segIdxsRev=Array.from(segIdxSet).sort((a2,b3)=>a2-b3).reverse(),JOG_SIZE=this.SHIFT_DISTANCE;for(let si2 of segIdxsRev)if(!(si2<0||si2>=pts.length-1))if(si2===0||si2===pts.length-2)applyJogToTerminalSegment({pts,segmentIndex:si2,offset,JOG_SIZE,EPS:1e-6});else{let start=pts[si2],end=pts[si2+1],isVertical3=Math.abs(start.x-end.x)<1e-6,isHorizontal2=Math.abs(start.y-end.y)<1e-6;if(!isVertical3&&!isHorizontal2)continue;isVertical3?(start.x+=offset,end.x+=offset):(start.y+=offset,end.y+=offset)}let cleaned=[];for(let p4 of pts)(cleaned.length===0||!samePoint(cleaned[cleaned.length-1],p4))&&cleaned.push(p4);this.correctedTraceMap[original.mspPairId]={...current2,tracePath:cleaned}}}),this.solved=!0}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}},TraceOverlapShiftSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTracePaths");__publicField(this,"globalConnMap");__publicField(this,"traceNetIslands",{});__publicField(this,"correctedTraceMap",{});__publicField(this,"cleanupPhase",null);this.inputProblem=params.inputProblem,this.inputTracePaths=params.inputTracePaths,this.globalConnMap=params.globalConnMap;for(let tracePath of this.inputTracePaths){let{mspPairId}=tracePath;this.correctedTraceMap[mspPairId]=tracePath}this.traceNetIslands=this.computeTraceNetIslands()}getConstructorParams(){return{inputProblem:this.inputProblem,inputTracePaths:this.inputTracePaths,globalConnMap:this.globalConnMap}}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 i2=0;i2<netIds.length;i2++)for(let j4=i2+1;j4<netIds.length;j4++){let netA=netIds[i2],netB=netIds[j4],pathsA=this.traceNetIslands[netA]||[],pathsB=this.traceNetIslands[netB]||[],overlapsA=[],overlapsB=[],seenA=new Set,seenB=new Set,overlaps1D=(a12,a2,b12,b22)=>{let minA=Math.min(a12,a2),maxA=Math.max(a12,a2),minB=Math.min(b12,b22),maxB=Math.max(b12,b22);return Math.min(maxA,maxB)-Math.max(minA,minB)>.002};for(let pa3=0;pa3<pathsA.length;pa3++){let ptsA=pathsA[pa3].tracePath;for(let sa3=0;sa3<ptsA.length-1;sa3++){let a12=ptsA[sa3],a2=ptsA[sa3+1],aVert=Math.abs(a12.x-a2.x)<.002,aHorz=Math.abs(a12.y-a2.y)<.002;if(!(!aVert&&!aHorz))for(let pb=0;pb<pathsB.length;pb++){let ptsB=pathsB[pb].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;if(!(!bVert&&!bHorz)){if(aVert&&bVert){if(Math.abs(a12.x-b12.x)<.002&&overlaps1D(a12.y,a2.y,b12.y,b22.y)){let keyA=`${pa3}:${sa3}`,keyB=`${pb}:${sb2}`;seenA.has(keyA)||(overlapsA.push({solvedTracePathIndex:pa3,traceSegmentIndex:sa3}),seenA.add(keyA)),seenB.has(keyB)||(overlapsB.push({solvedTracePathIndex:pb,traceSegmentIndex:sb2}),seenB.add(keyB))}}else if(aHorz&&bHorz&&Math.abs(a12.y-b12.y)<.002&&overlaps1D(a12.x,a2.x,b12.x,b22.x)){let keyA=`${pa3}:${sa3}`,keyB=`${pb}:${sb2}`;seenA.has(keyA)||(overlapsA.push({solvedTracePathIndex:pa3,traceSegmentIndex:sa3}),seenA.add(keyA)),seenB.has(keyB)||(overlapsB.push({solvedTracePathIndex:pb,traceSegmentIndex:sb2}),seenB.add(keyB))}}}}}}if(overlapsA.length>0&&overlapsB.length>0)return{overlappingTraceSegments:[{connNetId:netA,pathsWithOverlap:overlapsA},{connNetId:netB,pathsWithOverlap:overlapsB}]}}return null}findNextDiagonalSegment(){for(let mspPairId in this.correctedTraceMap){let tracePath=this.correctedTraceMap[mspPairId].tracePath;for(let i2=0;i2<tracePath.length-1;i2++){let p12=tracePath[i2],p22=tracePath[i2+1],isHorizontal2=Math.abs(p12.y-p22.y)<.002,isVertical3=Math.abs(p12.x-p22.x)<.002;if(!isHorizontal2&&!isVertical3)return{mspPairId,tracePath,i:i2,p1:p12,p2:p22}}}return null}findAndFixNextDiagonalSegment(){let diagonalInfo=this.findNextDiagonalSegment();if(!diagonalInfo)return!1;let{mspPairId,tracePath,i:i2,p1:p12,p2:p22}=diagonalInfo,EPS52=.002,p02=i2>0?tracePath[i2-1]:null,p32=i2+2<tracePath.length?tracePath[i2+2]:null,prevIsVertical=p02?Math.abs(p02.x-p12.x)<EPS52:!1,prevIsHorizontal=p02?Math.abs(p02.y-p12.y)<EPS52:!1,nextIsVertical=p32?Math.abs(p22.x-p32.x)<EPS52:!1,nextIsHorizontal=p32?Math.abs(p22.y-p32.y)<EPS52:!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(i2+1,0,elbowPoint),!0}_step(){if(this.activeSubSolver?.solved){for(let[mspPairId,newTrace]of Object.entries(this.activeSubSolver.correctedTraceMap))this.correctedTraceMap[mspPairId]=newTrace;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{overlappingTraceSegments}=overlapIssue;this.activeSubSolver=new TraceOverlapIssueSolver({overlappingTraceSegments,traceNetIslands:this.traceNetIslands})}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(id=>this.spatialIndexIdToChip.get(id))}doesOrthogonalLineIntersectChip(line2,opts={}){let excludeChipIds=opts.excludeChipIds??[],[p12,p22]=line2,{x:x12,y:y12}=p12,{x:x22,y:y22}=p22;return this.getChipsInBounds({minX:Math.min(x12,x22),minY:Math.min(y12,y22),maxX:Math.max(x12,x22),maxY:Math.max(y12,y22)}).filter(chip=>!excludeChipIds.includes(chip.chipId)).length>0}},NET_LABEL_HORIZONTAL_WIDTH=.45,NET_LABEL_HORIZONTAL_HEIGHT=.2;function getDimsForOrientation(params){let{orientation:orientation4,netLabelWidth}=params,horizWidth=typeof netLabelWidth=="number"?netLabelWidth:NET_LABEL_HORIZONTAL_WIDTH;return orientation4==="y+"||orientation4==="y-"?{width:NET_LABEL_HORIZONTAL_HEIGHT,height:horizWidth}:{width:horizWidth,height:NET_LABEL_HORIZONTAL_HEIGHT}}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,h4){return{minX:center2.x-w4/2,minY:center2.y-h4/2,maxX:center2.x+w4/2,maxY:center2.y+h4/2}}function segmentIntersectsRect2(p12,p22,rect,EPS52=1e-9){let isVert=Math.abs(p12.x-p22.x)<EPS52,isHorz=Math.abs(p12.y-p22.y)<EPS52;if(!isVert&&!isHorz)return!1;if(isVert){let x5=p12.x;if(x5<rect.minX-EPS52||x5>rect.maxX+EPS52)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)>EPS52}else{let y5=p12.y;if(y5<rect.minY-EPS52||y5>rect.maxY+EPS52)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)>EPS52}}function rectIntersectsAnyTrace(bounds,inputTraceMap,hostPathId,hostSegIndex){for(let[pairId,solved]of Object.entries(inputTraceMap)){let pts=solved.tracePath;for(let i2=0;i2<pts.length-1;i2++)if(!(pairId===hostPathId&&i2===hostSegIndex)&&segmentIntersectsRect2(pts[i2],pts[i2+1],bounds))return{hasIntersection:!0,mspPairId:pairId,segIndex:i2}}return{hasIntersection:!1}}function lengthOfTrace(path){let sum=0,pts=path.tracePath;for(let i2=0;i2<pts.length-1;i2++)sum+=Math.abs(pts[i2+1].x-pts[i2].x)+Math.abs(pts[i2+1].y-pts[i2].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(t5=>t5.globalConnNetId===globalConnNetId);if(mspConnectionPairIds&&mspConnectionPairIds.length>0){let idSet=new Set(mspConnectionPairIds);groupTraces=groupTraces.filter(t5=>t5.mspConnectionPairIds.some(id=>idSet.has(id)))}let chipIdsInGroup=new Set;for(let t5 of groupTraces)chipIdsInGroup.add(t5.pins[0].chipId),chipIdsInGroup.add(t5.pins[1].chipId);let largestChipId=null,largestPinCount=-1;for(let id of chipIdsInGroup){let count=chipsById[id]?.pins?.length??0;count>largestPinCount&&(largestPinCount=count,largestChipId=id)}let hostCandidates=largestChipId==null?[]:groupTraces.filter(t5=>t5.pins[0].chipId===largestChipId||t5.pins[1].chipId===largestChipId);return hostCandidates.length>0?hostCandidates.reduce((a2,b3)=>lengthOfTrace(a2)>=lengthOfTrace(b3)?a2:b3):fallbackTrace}function anchorsForSegment(a2,b3){return[{x:a2.x,y:a2.y},{x:(a2.x+b3.x)/2,y:(a2.y+b3.y)/2},{x:b3.x,y:b3.y}]}function solveNetLabelPlacementForPortOnlyPin(params){let{inputProblem,inputTraceMap,chipObstacleSpatialIndex,overlappingSameNetTraceGroup,availableOrientations,netLabelWidth}=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 p4=chip.pins.find(pp2=>pp2.pinId===pinId);if(p4){pin={x:p4.x,y:p4.y},pinFacingDirection=p4._facingDirection||getPinDirection2(p4,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=o3=>o3==="x+"?{x:1,y:0}:o3==="x-"?{x:-1,y:0}:o3==="y+"?{x:0,y:1}:{x:0,y:-1},testedCandidates=[];for(let orientation4 of orientations){let{width:width2,height:height2}=getDimsForOrientation({orientation:orientation4,netLabelWidth}),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(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,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,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)":"rgba(120, 120, 120, 0.15)",stroke=c3.status==="ok"?"green":c3.status==="chip-collision"?"red":c3.status==="trace-collision"?"orange":"gray";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}),graphics.points.push({x:c3.anchor.x,y:c3.anchor.y,color:stroke})}if(solver.netLabelPlacement){let p4=solver.netLabelPlacement;graphics.rects.push({center:p4.center,width:p4.width,height:p4.height,fill:"rgba(0, 128, 255, 0.35)",strokeColor:"blue"}),graphics.points.push({x:p4.anchorPoint.x,y:p4.anchorPoint.y,color:"blue"})}return graphics}var SingleNetLabelPlacementSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTraceMap");__publicField(this,"overlappingSameNetTraceGroup");__publicField(this,"availableOrientations");__publicField(this,"chipObstacleSpatialIndex");__publicField(this,"netLabelWidth");__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.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}}_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});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(t5=>t5.globalConnNetId===groupId&&(traceIdSet.size===0||t5.mspConnectionPairIds.some(id=>traceIdSet.has(id)))),tracesToScan=this.availableOrientations.length===1?[host,...tracesToScanBase.filter(t5=>t5.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,EPS52=1e-6;for(let curr of tracesToScan){let pts=curr.tracePath.slice();for(let si2=0;si2<pts.length-1;si2++){let a2=pts[si2],b3=pts[si2+1],isH=Math.abs(a2.y-b3.y)<EPS52,isV=Math.abs(a2.x-b3.x)<EPS52;if(!isH&&!isV)continue;let segmentAllowed=isH?["y+","y-"]:["x+","x-"],candidateOrients=orientations.filter(o3=>segmentAllowed.includes(o3));if(candidateOrients.length===0)continue;let anchors=anchorsForSegment(a2,b3);for(let anchor of anchors)for(let orientation4 of candidateOrients){let{width,height}=getDimsForOrientation({orientation:orientation4,netLabelWidth:this.netLabelWidth}),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:si2});continue}if(rectIntersectsAnyTrace(bounds,this.inputTraceMap,curr.mspPairId,si2).hasIntersection){this.testedCandidates.push({center:testCenter,width,height,bounds,anchor,orientation:orientation4,status:"trace-collision",hostSegIndex:si2});continue}if(this.testedCandidates.push({center:testCenter,width,height,bounds,anchor,orientation:orientation4,status:"ok",hostSegIndex:si2}),singleOrientationMode){let s2=scoreFor(orientation4,anchor);s2>bestScore+1e-9&&(bestScore=s2,bestCandidate={anchor,orientation:orientation4,width,height,center:center2,hostSegIndex:si2,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,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,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 BaseSolver4{constructor(params){super();__publicField(this,"inputProblem");__publicField(this,"inputTraceMap");__publicField(this,"overlappingSameNetTraceGroups");__publicField(this,"queuedOverlappingSameNetTraceGroups");__publicField(this,"netLabelPlacements",[]);__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={};for(let dc2 of this.inputProblem.directConnections)if(dc2.netId){let[a2,b3]=dc2.pinIds;userNetIdByPinId[a2]=dc2.netId,userNetIdByPinId[b3]=dc2.netId}for(let nc2 of this.inputProblem.netConnections)for(let pid of nc2.pinIds)userNetIdByPinId[pid]=nc2.netId;let groups=[],allPinIds=this.inputProblem.chips.flatMap(c3=>c3.pins.map(p4=>p4.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(id=>pinIdToPinMap.has(id)),adj={};for(let pid of pinsInNet)adj[pid]=new Set;for(let t5 of byGlobal[globalConnNetId]??[]){let a2=t5.pins[0].pinId,b3=t5.pins[1].pinId;adj[a2]&&adj[b3]&&(adj[a2].add(b3),adj[b3].add(a2))}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 u4=stack.pop();component.add(u4);for(let v5 of adj[u4]??[])visited.has(v5)||(visited.add(v5),stack.push(v5))}let compTraces=(byGlobal[globalConnNetId]??[]).filter(t5=>component.has(t5.pins[0].pinId)&&component.has(t5.pins[1].pinId));if(compTraces.length>0){let lengthOf=path=>{let sum=0,pts=path.tracePath;for(let i2=0;i2<pts.length-1;i2++)sum+=Math.abs(pts[i2+1].x-pts[i2].x)+Math.abs(pts[i2+1].y-pts[i2].y);return sum},rep=compTraces[0],repLen=lengthOf(rep);for(let i2=1;i2<compTraces.length;i2++){let len=lengthOf(compTraces[i2]);len>repLen&&(rep=compTraces[i2],repLen=len)}let userNetId=compTraces.find(t5=>t5.userNetId!=null)?.userNetId;if(!userNetId){for(let p4 of component)if(userNetIdByPinId[p4]){userNetId=userNetIdByPinId[p4];break}}let mspConnectionPairIds=Array.from(new Set(compTraces.flatMap(t5=>t5.mspConnectionPairIds??[t5.mspPairId]))),group={globalConnNetId,netId:userNetId,overlappingTraces:rep,mspConnectionPairIds};groups.push(group)}else for(let p4 of component){let userNetId=userNetIdByPinId[p4];userNetId&&groups.push({globalConnNetId,netId:userNetId,portOnlyPinId:p4})}}}return groups}_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(o3=>currOrients.includes(o3));if(!this.triedAnyOrientationFallbackForCurrentGroup&&!isAlreadyFull&&this.currentGroup){this.triedAnyOrientationFallbackForCurrentGroup=!0;let netLabelWidth2=this.currentGroup.netId?this.inputProblem.netConnections.find(nc2=>nc2.netId===this.currentGroup.netId)?.netLabelWidth:void 0;this.activeSubSolver=new SingleNetLabelPlacementSolver({inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,overlappingSameNetTraceGroup:this.currentGroup,availableOrientations:fullOrients,netLabelWidth:netLabelWidth2});return}this.failed=!0,this.error=this.activeSubSolver.error;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.currentGroup.netId?this.inputProblem.netConnections.find(nc2=>nc2.netId===this.currentGroup.netId)?.netLabelWidth:void 0;this.activeSubSolver=new SingleNetLabelPlacementSolver({inputProblem:this.inputProblem,inputTraceMap:this.inputTraceMap,overlappingSameNetTraceGroup:nextOverlappingSameNetTraceGroup,availableOrientations:this.inputProblem.availableNetLabelOrientations[netId]??["x+","x-","y+","y-"],netLabelWidth})}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 p4 of this.netLabelPlacements)graphics.rects.push({center:p4.center,width:p4.width,height:p4.height,fill:getColorFromString2(p4.globalConnNetId,.35),strokeColor:getColorFromString2(p4.globalConnNetId,.9)}),graphics.points.push({x:p4.anchorPoint.x,y:p4.anchorPoint.y,color:getColorFromString2(p4.globalConnNetId,.9)});return graphics}},MergedNetLabelObstacleSolver=class extends BaseSolver4{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"output");__publicField(this,"inputProblem");__publicField(this,"traces");this.input=solverInput,this.inputProblem=solverInput.inputProblem,this.traces=solverInput.traces,this.output={netLabelPlacements:solverInput.netLabelPlacements,mergedLabelNetIdMap:{}}}_step(){let originalLabels=this.input.netLabelPlacements,mergedLabelNetIdMap={};if(!originalLabels||originalLabels.length===0){this.output={netLabelPlacements:[],mergedLabelNetIdMap:{}},this.solved=!0;return}let labelGroups={};for(let p4 of originalLabels){if(p4.pinIds.length===0)continue;let chipId=p4.pinIds[0].split(".")[0];if(!chipId)continue;let key=`${chipId}-${p4.orientation}`;key in labelGroups||(labelGroups[key]=[]),labelGroups[key].push(p4)}let finalPlacements=[];for(let[key,group]of Object.entries(labelGroups)){if(group.length<=1){finalPlacements.push(...group);continue}let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let p4 of group){let bounds=getRectBounds(p4.center,p4.width,p4.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)}let newWidth=maxX-minX,newHeight=maxY-minY,template=group[0],syntheticId=`merged-group-${key}`,originalNetIds=new Set(group.map(p4=>p4.globalConnNetId));mergedLabelNetIdMap[syntheticId]=originalNetIds,finalPlacements.push({...template,globalConnNetId:syntheticId,width:newWidth,height:newHeight,center:{x:minX+newWidth/2,y:minY+newHeight/2},pinIds:[...new Set(group.flatMap(p4=>p4.pinIds))],mspConnectionPairIds:[...new Set(group.flatMap(p4=>p4.mspConnectionPairIds))]})}this.output={netLabelPlacements:finalPlacements,mergedLabelNetIdMap},this.solved=!0}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(p4=>({x:p4.x,y:p4.y})),strokeColor:"blue"};graphics.lines.push(line2)}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},p32={x:bounds.maxX,y:bounds.maxY},p4={x:bounds.minX,y:bounds.maxY};graphics.lines.push({points:[p12,p22,p32,p4,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 i2=0;i2<trace.tracePath.length-1;i2++){let p12=trace.tracePath[i2],p22=trace.tracePath[i2+1];if(segmentIntersectsRect2(p12,p22,labelBounds)){if(trace.globalConnNetId===label.globalConnNetId)break;overlaps.push({trace,label});break}}}return overlaps},findTraceViolationZone=(path,labelBounds)=>{let isPointInside=p4=>p4.x>labelBounds.minX&&p4.x<labelBounds.maxX&&p4.y>labelBounds.minY&&p4.y<labelBounds.maxY,firstInsideIndex=-1,lastInsideIndex=-1;for(let i2=0;i2<path.length;i2++)isPointInside(path[i2])&&(firstInsideIndex===-1&&(firstInsideIndex=i2),lastInsideIndex=i2);return{firstInsideIndex,lastInsideIndex}},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 collidingSegIndex=-1;for(let i2=0;i2<initialTrace.tracePath.length-1;i2++)if(segmentIntersectsRect(initialTrace.tracePath[i2],initialTrace.tracePath[i2+1],labelBounds)){collidingSegIndex=i2;break}if(collidingSegIndex===-1)return[];let pA=initialTrace.tracePath[collidingSegIndex],pB=initialTrace.tracePath[collidingSegIndex+1];if(!pA||!pB)return[];let candidateDetours=[],paddedLabelBounds=getRectBounds(label.center,label.width,label.height),effectivePadding=paddingBuffer+detourCount*paddingBuffer;if(isVertical(pA,pB)){let xCandidates=[paddedLabelBounds.maxX+effectivePadding,paddedLabelBounds.minX-effectivePadding];for(let newX of xCandidates)candidateDetours.push(pB.y>pA.y?[{x:pA.x,y:paddedLabelBounds.minY-effectivePadding},{x:newX,y:paddedLabelBounds.minY-effectivePadding},{x:newX,y:paddedLabelBounds.maxY+effectivePadding},{x:pB.x,y:paddedLabelBounds.maxY+effectivePadding}]:[{x:pA.x,y:paddedLabelBounds.maxY+effectivePadding},{x:newX,y:paddedLabelBounds.maxY+effectivePadding},{x:newX,y:paddedLabelBounds.minY-effectivePadding},{x:pB.x,y:paddedLabelBounds.minY-effectivePadding}])}else{let yCandidates=[paddedLabelBounds.maxY+effectivePadding,paddedLabelBounds.minY-effectivePadding];for(let newY of yCandidates)candidateDetours.push(pB.x>pA.x?[{x:paddedLabelBounds.minX-effectivePadding,y:pA.y},{x:paddedLabelBounds.minX-effectivePadding,y:newY},{x:paddedLabelBounds.maxX+effectivePadding,y:newY},{x:paddedLabelBounds.maxX+effectivePadding,y:pB.y}]:[{x:paddedLabelBounds.maxX+effectivePadding,y:pA.y},{x:paddedLabelBounds.maxX+effectivePadding,y:newY},{x:paddedLabelBounds.minX-effectivePadding,y:newY},{x:paddedLabelBounds.minX-effectivePadding,y:pB.y}])}return candidateDetours.map(detourPoints=>[...initialTrace.tracePath.slice(0,collidingSegIndex+1),...detourPoints,...initialTrace.tracePath.slice(collidingSegIndex+1)])},simplifyPath=path=>{if(path.length<3)return path;let newPath=[path[0]];for(let i2=1;i2<path.length-1;i2++){let p12=newPath[newPath.length-1],p22=path[i2],p32=path[i2+1];isVertical(p12,p22)&&isVertical(p22,p32)||isHorizontal(p12,p22)&&isHorizontal(p22,p32)||newPath.push(p22)}if(newPath.push(path[path.length-1]),newPath.length<3)return newPath;let finalPath=[newPath[0]];for(let i2=1;i2<newPath.length-1;i2++){let p12=finalPath[finalPath.length-1],p22=newPath[i2],p32=newPath[i2+1];isVertical(p12,p22)&&isVertical(p22,p32)||isHorizontal(p12,p22)&&isHorizontal(p22,p32)||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 labelPadding=paddingBuffer,labelBoundsRaw=getRectBounds(label.center,label.width,label.height),labelBounds={minX:labelBoundsRaw.minX-labelPadding,minY:labelBoundsRaw.minY-labelPadding,maxX:labelBoundsRaw.maxX+labelPadding,maxY:labelBoundsRaw.maxY+labelPadding,chipId:`netlabel-${label.netId}`},fourPointCandidates=generateFourPointDetourCandidates({initialTrace,label,labelBounds,paddingBuffer,detourCount}),{firstInsideIndex,lastInsideIndex}=findTraceViolationZone(initialTrace.tracePath,labelBounds),snipReconnectCandidates=generateSnipAndReconnectCandidates({initialTrace,firstInsideIndex,lastInsideIndex,labelBounds,paddingBuffer,detourCount});return[...fourPointCandidates,...snipReconnectCandidates]},SingleOverlapSolver=class extends BaseSolver4{constructor(solverInput){super();__publicField(this,"queuedCandidatePaths");__publicField(this,"solvedTracePath",null);__publicField(this,"initialTrace");__publicField(this,"problem");__publicField(this,"obstacles");__publicField(this,"label");this.initialTrace=solverInput.trace,this.problem=solverInput.problem,this.label=solverInput.label;let candidates=generateRerouteCandidates({...solverInput}),getPathLength=pts=>{let len=0;for(let i2=0;i2<pts.length-1;i2++){let dx2=pts[i2+1].x-pts[i2].x,dy2=pts[i2+1].y-pts[i2].y;len+=Math.sqrt(dx2*dx2+dy2*dy2)}return len};this.queuedCandidatePaths=candidates.sort((a2,b3)=>getPathLength(a2)-getPathLength(b3)),this.obstacles=getObstacleRects(this.problem)}_step(){if(this.queuedCandidatePaths.length===0){this.failed=!0;return}let nextCandidatePath=this.queuedCandidatePaths.shift(),simplifiedPath=simplifyPath(nextCandidatePath);isPathCollidingWithObstacles(simplifiedPath,this.obstacles)||(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.queuedCandidatePaths.length>0&&graphics.lines.push({points:this.queuedCandidatePaths[0],strokeColor:"orange"}),this.solvedTracePath&&graphics.lines.push({points:this.solvedTracePath,strokeColor:"green"}),graphics}},OverlapAvoidanceStepSolver=class extends BaseSolver4{constructor(solverInput){super();__publicField(this,"inputProblem");__publicField(this,"netLabelPlacements");__publicField(this,"mergedLabelNetIdMap");__publicField(this,"allTraces");__publicField(this,"modifiedTraces",[]);__publicField(this,"detourCountByLabel",{});__publicField(this,"PADDING_BUFFER",.1);__publicField(this,"activeSubSolver",null);__publicField(this,"overlapQueue",[]);__publicField(this,"recentlyFailed",new Set);this.inputProblem=solverInput.inputProblem,this.netLabelPlacements=solverInput.netLabelPlacements,this.mergedLabelNetIdMap=solverInput.mergedLabelNetIdMap,this.allTraces=[...solverInput.traces]}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){let solvedPath=this.activeSubSolver.solvedTracePath;if(solvedPath){let traceIndex=this.allTraces.findIndex(t5=>t5.mspPairId===this.activeSubSolver.initialTrace.mspPairId);traceIndex!==-1&&(this.allTraces[traceIndex].tracePath=solvedPath,this.modifiedTraces.push(this.allTraces[traceIndex]))}this.activeSubSolver=null,this.recentlyFailed.clear()}else if(this.activeSubSolver.failed){let overlapId=`${this.activeSubSolver.initialTrace.mspPairId}-${this.activeSubSolver.label.globalConnNetId}`;this.recentlyFailed.add(overlapId),this.activeSubSolver=null}return}let overlaps=detectTraceLabelOverlap(this.allTraces,this.netLabelPlacements).filter(o3=>{let originalNetIds=this.mergedLabelNetIdMap[o3.label.globalConnNetId];return originalNetIds?!originalNetIds.has(o3.trace.globalConnNetId):o3.trace.globalConnNetId!==o3.label.globalConnNetId});if(overlaps.length===0){this.solved=!0;return}let nonFailedOverlaps=overlaps.filter(o3=>{let overlapId=`${o3.trace.mspPairId}-${o3.label.globalConnNetId}`;return!this.recentlyFailed.has(overlapId)});if(nonFailedOverlaps.length===0){this.solved=!0;return}this.overlapQueue=nonFailedOverlaps;let nextOverlap=this.overlapQueue.shift();if(nextOverlap){let traceToFix=this.allTraces.find(t5=>t5.mspPairId===nextOverlap.trace.mspPairId);if(traceToFix){let labelId=nextOverlap.label.globalConnNetId,detourCount=this.detourCountByLabel[labelId]||0;this.detourCountByLabel[labelId]=detourCount+1,this.activeSubSolver=new SingleOverlapSolver({trace:traceToFix,label:nextOverlap.label,problem:this.inputProblem,paddingBuffer:this.PADDING_BUFFER,detourCount})}}}getOutput(){return{allTraces:this.allTraces,modifiedTraces:this.modifiedTraces}}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"});return graphics}},TraceLabelOverlapAvoidanceSolver=class extends BaseSolver4{constructor(solverInput){super();__publicField(this,"inputProblem");__publicField(this,"traces");__publicField(this,"netLabelPlacements");__publicField(this,"labelMergingSolver");__publicField(this,"overlapAvoidanceSolver");__publicField(this,"pipelineStepIndex",0);this.inputProblem=solverInput.inputProblem,this.traces=solverInput.traces,this.netLabelPlacements=solverInput.netLabelPlacements}_step(){if(this.activeSubSolver){this.activeSubSolver.step(),this.activeSubSolver.solved?(this.activeSubSolver=null,this.pipelineStepIndex++):this.activeSubSolver.failed&&(this.failed=!0,this.activeSubSolver=null);return}switch(this.pipelineStepIndex){case 0:this.labelMergingSolver=new MergedNetLabelObstacleSolver({netLabelPlacements:this.netLabelPlacements,inputProblem:this.inputProblem,traces:this.traces}),this.activeSubSolver=this.labelMergingSolver;break;case 1:this.overlapAvoidanceSolver=new OverlapAvoidanceStepSolver({inputProblem:this.inputProblem,traces:this.traces,netLabelPlacements:this.labelMergingSolver.getOutput().netLabelPlacements,mergedLabelNetIdMap:this.labelMergingSolver.getOutput().mergedLabelNetIdMap}),this.activeSubSolver=this.overlapAvoidanceSolver;break;default:this.solved=!0;break}}getOutput(){return{traces:this.overlapAvoidanceSolver?.getOutput().allTraces??this.traces,netLabelPlacements:this.labelMergingSolver?.getOutput().netLabelPlacements??this.netLabelPlacements}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();let graphics=visualizeInputProblem2(this.inputProblem);graphics.lines||(graphics.lines=[]),graphics.rects||(graphics.rects=[]);let output=this.getOutput();for(let trace of output.traces)graphics.lines.push({points:trace.tracePath,strokeColor:"purple"});for(let label of output.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;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 dx2=Math.abs(pin.x-chip.center.x),dy2=Math.abs(pin.y-chip.center.y);dx2>maxDx&&(maxDx=dx2),dy2>maxDy&&(maxDy=dy2)}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 i2=0;i2<newTracePath.length-1;i2++){let newSegmentP1=newTracePath[i2],newSegmentP2=newTracePath[i2+1];for(let existingTrace of existingTraces)for(let j4=0;j4<existingTrace.tracePath.length-1;j4++){let existingSegmentP1=existingTrace.tracePath[j4],existingSegmentP2=existingTrace.tracePath[j4+1];if(doSegmentsIntersect2(newSegmentP1,newSegmentP2,existingSegmentP1,existingSegmentP2))return!0}}return!1}var NEAREST_NEIGHBOR_COUNT=3,distance5=(p12,p22)=>Math.sqrt(Math.pow(p12.x-p22.x,2)+Math.pow(p12.y-p22.y,2)),LongDistancePairSolver=class extends BaseSolver4{constructor(params){super();__publicField(this,"solvedLongDistanceTraces",[]);__publicField(this,"queuedCandidatePairs",[]);__publicField(this,"currentCandidatePair",null);__publicField(this,"subSolver",null);__publicField(this,"chipMap",{});__publicField(this,"inputProblem");__publicField(this,"netConnMap");__publicField(this,"newlyConnectedPinIds",new Set);__publicField(this,"allSolvedTraces",[]);this.params=params;let{inputProblem,primaryMspConnectionPairs,alreadySolvedTraces}=this.params;this.inputProblem=inputProblem,this.allSolvedTraces=[...alreadySolvedTraces];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})}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?[{pin:targetPin,distance:distance5(sourcePin,targetPin)}]:[]}).sort((a2,b3)=>a2.distance-b3.distance).slice(0,NEAREST_NEIGHBOR_COUNT);for(let neighbor of neighbors){let pair=[sourcePin,neighbor.pin],pairKey=pair.map(p4=>p4.pinId).sort().join("--");addedPairKeys.has(pairKey)||(candidatePairs.push(pair),addedPairKeys.add(pairKey))}}}this.queuedCandidatePairs=candidatePairs}getConstructorParams(){return this.params}_step(){if(this.subSolver?.solved){let newTracePath=this.subSolver.solvedTracePath;if(newTracePath&&this.currentCandidatePair&&!doesTraceOverlapWithExistingTraces(newTracePath,this.allSolvedTraces)){let[p12,p22]=this.currentCandidatePair,globalConnNetId=this.netConnMap.getNetConnectedToId(p12.pinId),mspPairId=`${p12.pinId}-${p22.pinId}`,newSolvedTrace={mspPairId,dcConnNetId:globalConnNetId,globalConnNetId,pins:[p12,p22],tracePath:newTracePath,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);if(this.subSolver){this.subSolver.step();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 i2=0;i2<pathSegments.length-1;i2++){let p12=pathSegments[i2],p22=pathSegments[i2+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 i2=1;i2<points.length-1;i2++){let prev=points[i2-1],curr=points[i2],next2=points[i2+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 i2=0;i2<pathSegments.length-1;i2++){let p12=pathSegments[i2],p22=pathSegments[i2+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 i2=startIdx;i2<pathToCheck.length-2&&i2<startIdx+10&&!(i2+2>=pathToCheck.length);i2++){let p12=pathToCheck[i2],p22=pathToCheck[i2+1],p32=pathToCheck[i2+2],seg1Vertical=p12.x===p22.x,seg2Vertical=p22.x===p32.x;if(seg1Vertical===seg2Vertical)break;let seg1Direction=Math.sign(seg1Vertical?p22.y-p12.y:p22.x-p12.x);if(i2>startIdx){let prevP=pathToCheck[i2-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=i2+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 i2=0;i2<optimizedPath.length-2;i2++){let p12=optimizedPath[i2],p22=optimizedPath[i2+1],p32=optimizedPath[i2+2];if(isSegmentAnEndpointSegment(p12,p22,originalPath)||isSegmentAnEndpointSegment(p22,p32,originalPath))continue;let allVertical=p12.x===p22.x&&p22.x===p32.x,allHorizontal=p12.y===p22.y&&p22.y===p32.y;if(allVertical||allHorizontal){let testPath=[...optimizedPath.slice(0,i2+1),...optimizedPath.slice(i2+2)],collidesWithObstacles=hasCollisions([p12,p32],obstacles),collidesWithLabels=hasCollisionsWithLabels([p12,p32],labelBounds);if(!collidesWithObstacles&&!collidesWithLabels){optimizedPath=testPath,improved=!0;break}}}}return simplifyPath(optimizedPath)},minimizeTurnsWithFilteredLabels=({targetMspConnectionPairId,traces,inputProblem,allLabelPlacements,mergedLabelNetIdMap,paddingBuffer})=>{let targetTrace=traces.find(t5=>t5.mspPairId===targetMspConnectionPairId);if(!targetTrace)throw new Error(`Target trace ${targetMspConnectionPairId} not found`);let obstacleTraces=traces.filter(t5=>t5.mspPairId!==targetMspConnectionPairId),TRACE_WIDTH=.01,traceObstacles=obstacleTraces.flatMap((trace,i2)=>trace.tracePath.slice(0,-1).map((p12,pi3)=>{let p22=trace.tracePath[pi3+1];return{chipId:`trace-obstacle-${i2}-${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,combinedObstacles=[...staticObstaclesRaw.map(obs=>({...obs,minX:obs.minX-PADDING,minY:obs.minY-PADDING,maxX:obs.maxX+PADDING,maxY:obs.maxY+PADDING})),...traceObstacles],originalPath=targetTrace.tracePath,labelBounds=allLabelPlacements.filter(label=>{let originalNetIds=mergedLabelNetIdMap[label.globalConnNetId];return originalNetIds?!originalNetIds.has(targetTrace.globalConnNetId):label.globalConnNetId!==targetTrace.globalConnNetId}).map(nl2=>({minX:nl2.center.x-nl2.width/2-paddingBuffer,maxX:nl2.center.x+nl2.width/2+paddingBuffer,minY:nl2.center.y-nl2.height/2-paddingBuffer,maxY:nl2.center.y+nl2.height/2+paddingBuffer})),newPath=minimizeTurns({path:originalPath,obstacles:combinedObstacles,labelBounds,originalPath});return{...targetTrace,tracePath:newPath}},balanceZShapes=({targetMspConnectionPairId,traces,inputProblem,allLabelPlacements,mergedLabelNetIdMap,paddingBuffer})=>{let targetTrace=traces.find(t5=>t5.mspPairId===targetMspConnectionPairId);if(!targetTrace)throw new Error(`Target trace ${targetMspConnectionPairId} not found`);let TOLERANCE2=1e-5,obstacleTraces=traces.filter(t5=>t5.mspPairId!==targetMspConnectionPairId),TRACE_WIDTH=.01,traceObstacles=obstacleTraces.flatMap((trace,i2)=>trace.tracePath.slice(0,-1).map((p12,pi3)=>{let p22=trace.tracePath[pi3+1];return{chipId:`trace-obstacle-${i2}-${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(nl2=>({minX:nl2.center.x-nl2.width/2+TOLERANCE2,maxX:nl2.center.x+nl2.width/2-TOLERANCE2,minY:nl2.center.y-nl2.height/2+TOLERANCE2,maxY:nl2.center.y+nl2.height/2-TOLERANCE2})),newPath=[...targetTrace.tracePath];if(newPath.length<4)return{...targetTrace};if(newPath.length===4){let[p02,p12,p22,p32]=newPath,p1New,p2New;if(p02.y===p12.y&&p12.x===p22.x&&p22.y===p32.y){let idealX=(p02.x+p32.x)/2;p1New={x:idealX,y:p12.y},p2New={x:idealX,y:p22.y}}else{let idealY=(p02.y+p32.y)/2;p1New={x:p12.x,y:idealY},p2New={x:p22.x,y:idealY}}return segmentIntersectsAnyRect(p02,p1New,combinedObstacles)||segmentIntersectsAnyRect(p1New,p2New,combinedObstacles)||segmentIntersectsAnyRect(p2New,p32,combinedObstacles)||segmentIntersectsAnyRect(p02,p1New,labelBounds)||segmentIntersectsAnyRect(p1New,p2New,labelBounds)||segmentIntersectsAnyRect(p2New,p32,labelBounds)||(newPath[1]=p1New,newPath[2]=p2New),{...targetTrace,tracePath:simplifyPath(newPath)}}for(let i2=1;i2<newPath.length-4;i2++){let p12=newPath[i2],p22=newPath[i2+1],p32=newPath[i2+2],p4=newPath[i2+3],isHVHZShape=p12.y===p22.y&&p22.x===p32.x&&p32.y===p4.y,isVHVZShape=p12.x===p22.x&&p22.y===p32.y&&p32.x===p4.x,isCollinearHorizontal=p12.y===p22.y&&p22.y===p32.y&&p32.y===p4.y,isCollinearVertical=p12.x===p22.x&&p22.x===p32.x&&p32.x===p4.x,isCollinear=isCollinearHorizontal||isCollinearVertical,isSameDirection=!1;if(isHVHZShape?isSameDirection=Math.sign(p22.x-p12.x)===Math.sign(p4.x-p32.x):isVHVZShape&&(isSameDirection=Math.sign(p22.y-p12.y)===Math.sign(p4.y-p32.y)),!((isHVHZShape||isVHVZShape)&&!isCollinear&&isSameDirection))continue;let p2New,p3New,len1Original=Math.abs(isHVHZShape?p12.x-p22.x:p12.y-p22.y),len2Original=Math.abs(isHVHZShape?p32.x-p4.x:p32.y-p4.y);if(Math.abs(len1Original-len2Original)<.001)continue;if(isHVHZShape){let idealX=(p12.x+p4.x)/2;p2New={x:idealX,y:p22.y},p3New={x:idealX,y:p32.y}}else{let idealY=(p12.y+p4.y)/2;p2New={x:p22.x,y:idealY},p3New={x:p32.x,y:idealY}}segmentIntersectsAnyRect(p12,p2New,combinedObstacles)||segmentIntersectsAnyRect(p2New,p3New,combinedObstacles)||segmentIntersectsAnyRect(p3New,p4,combinedObstacles)||segmentIntersectsAnyRect(p12,p2New,labelBounds)||segmentIntersectsAnyRect(p2New,p3New,labelBounds)||segmentIntersectsAnyRect(p3New,p4,labelBounds)||(newPath[i2+1]=p2New,newPath[i2+2]=p3New,i2=0)}let finalSimplifiedPath=simplifyPath(newPath);return{...targetTrace,tracePath:finalSimplifiedPath}},findAllLShapedTurns=tracePath=>{let lShapes=[];if(tracePath.length<3)return lShapes;for(let i2=0;i2<tracePath.length-2;i2++){let p12=tracePath[i2],p22=tracePath[i2+1],p32=tracePath[i2+2],dx1=p22.x-p12.x,dy1=p22.y-p12.y,dx2=p32.x-p22.x,dy2=p32.y-p22.y;(dx1===0&&dy2===0&&dy1!==0&&dx2!==0||dy1===0&&dx2===0&&dx1!==0&&dy2!==0)&&dx1*dx1+dy1*dy1>=.25&&dx2*dx2+dy2*dy2>=.25&&lShapes.push({p1:p12,p2:p22,p3:p32})}return lShapes},getTraceObstacles=(allTraces,excludeTraceId)=>{let obstacles=[];for(let trace of allTraces)trace.mspPairId!==excludeTraceId&&obstacles.push({points:trace.tracePath});return obstacles},findIntersectionsWithObstacles=(p12,p22,obstacles)=>{let intersections=[];for(let obstacle of obstacles){let obstaclePath=obstacle.points;for(let i2=0;i2<obstaclePath.length-1;i2++){let o12=obstaclePath[i2],o22=obstaclePath[i2+1];if(!o12||!o22)continue;let intersection=getSegmentIntersection(p12,p22,o12,o22);intersection&&intersections.push(intersection)}}return intersections},EPS4=1e-6,isVertical2=(a2,b3,eps=EPS4)=>Math.abs(a2.x-b3.x)<eps,generateLShapeRerouteCandidates=({lShape,rectangle,padding=.5,interactionPoint1,interactionPoint2})=>{let{p1:p12,p2:p22,p3:p32}=lShape,{x:x5,y:y5,width,height}=rectangle,c22,i1_padded=interactionPoint1,i2_padded=interactionPoint2;if(Math.abs(p22.x-x5)<EPS4&&Math.abs(p22.y-(y5+height))<EPS4)c22={x:x5+width+padding,y:y5-padding},isVertical2(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y-padding}:i1_padded={x:interactionPoint1.x+padding,y:interactionPoint1.y},isVertical2(p22,p32)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y-padding}:i2_padded={x:interactionPoint2.x+padding,y:interactionPoint2.y};else if(Math.abs(p22.x-(x5+width))<EPS4&&Math.abs(p22.y-(y5+height))<EPS4)c22={x:x5-padding,y:y5-padding},isVertical2(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y-padding}:i1_padded={x:interactionPoint1.x-padding,y:interactionPoint1.y},isVertical2(p22,p32)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y-padding}:i2_padded={x:interactionPoint2.x-padding,y:interactionPoint2.y};else if(Math.abs(p22.x-x5)<EPS4&&Math.abs(p22.y-y5)<EPS4)c22={x:x5+width+padding,y:y5+height+padding},isVertical2(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y+padding}:i1_padded={x:interactionPoint1.x+padding,y:interactionPoint1.y},isVertical2(p22,p32)?i2_padded={x:interactionPoint2.x,y:interactionPoint2.y+padding}:i2_padded={x:interactionPoint2.x+padding,y:interactionPoint2.y};else if(Math.abs(p22.x-(x5+width))<EPS4&&Math.abs(p22.y-y5)<EPS4)c22={x:x5-padding,y:y5+height+padding},isVertical2(p12,p22)?i1_padded={x:interactionPoint1.x,y:interactionPoint1.y+padding}:i1_padded={x:interactionPoint1.x-padding,y:interactionPoint1.y},isVertical2(p22,p32)?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]]},isPathColliding=(path,allTraces,traceIdToExclude)=>{if(path.length<2)return{isColliding:!1};for(let i2=0;i2<path.length-1;i2++){let pathSegP1=path[i2],pathSegQ1=path[i2+1];for(let existingTrace of allTraces)if(existingTrace.mspPairId!==traceIdToExclude)for(let j4=0;j4<existingTrace.tracePath.length-1;j4++){let existingSegP2=existingTrace.tracePath[j4],existingSegQ2=existingTrace.tracePath[j4+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 BaseSolver4{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"lShapesToProcess",[]);__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";for(let trace of this.input.allTraces){let lShapes=findAllLShapedTurns(trace.tracePath);this.lShapesToProcess.push(...lShapes.map(l3=>({...l3,traceId:trace.mspPairId})))}}_step(){if(this.isInitialStep){this.isInitialStep=!1;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}}_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}=this.rectangleCandidates[this.currentRectangleIndex];this.tightRectangle=rect,this.candidates=generateLShapeRerouteCandidates({lShape:this.currentLShape,rectangle:this.tightRectangle,padding:2*this.input.paddingBuffer,interactionPoint1:i12,interactionPoint2:i2}),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);collisionResult?.isColliding?(this.lastCollision=collisionResult,this.collidingCandidate=currentCandidate,this.currentCandidateIndex++):(this.bestRouteFound=currentCandidate,this.lastCollision=null,this.collidingCandidate=null)}_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(p4=>p4.x===this.currentLShape.p2.x&&p4.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(l3=>l3.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 i2=0;i2<trace.tracePath.length-1;i2++)allTracesGraphics2.lines.push({points:[trace.tracePath[i2],trace.tracePath[i2+1]],strokeColor:isUpdatedTrace?"green":"#ccc"})}return allTracesGraphics2}let allTracesGraphics={lines:[]};for(let trace of this.input.allTraces)for(let i2=0;i2<trace.tracePath.length-1;i2++)allTracesGraphics.lines.push({points:[trace.tracePath[i2],trace.tracePath[i2+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{}}}},is4PointRectangle=path=>{if(path.length!==4)return!1;let[p02,p12,p22,p32]=path,isHVHC=p02.y===p12.y&&p12.x===p22.x&&p22.y===p32.y&&p02.x===p32.x,isVHVC=p02.x===p12.x&&p12.y===p22.y&&p22.x===p32.x&&p02.y===p32.y;return isHVHC||isVHVC},TraceCleanupSolver=class extends BaseSolver4{constructor(solverInput){super();__publicField(this,"input");__publicField(this,"outputTraces");__publicField(this,"traceIdQueue");__publicField(this,"tracesMap");__publicField(this,"pipelineStep","untangling_traces");__publicField(this,"activeTraceId",null);__publicField(this,"activeSubSolver",null);this.input=solverInput,this.outputTraces=[...solverInput.allTraces],this.tracesMap=new Map(this.outputTraces.map(t5=>[t5.mspPairId,t5])),this.traceIdQueue=Array.from(solverInput.allTraces.map(e4=>e4.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(t5=>[t5.mspPairId,t5])),this.activeSubSolver=null,this.pipelineStep="minimizing_turns"}else this.activeSubSolver.failed&&(this.activeSubSolver=null,this.pipelineStep="minimizing_turns");return}switch(this.pipelineStep){case"untangling_traces":this._runUntangleTracesStep();break;case"minimizing_turns":this._runMinimizeTurnsStep();break;case"balancing_l_shapes":this._runBalanceLShapesStep();break}}_runUntangleTracesStep(){this.activeSubSolver=new UntangleTraceSubsolver({...this.input,allTraces:Array.from(this.tracesMap.values())})}_runMinimizeTurnsStep(){if(this.traceIdQueue.length===0){this.pipelineStep="balancing_l_shapes",this.traceIdQueue=Array.from(this.input.allTraces.map(e4=>e4.mspPairId));return}this._processTrace("minimizing_turns")}_runBalanceLShapesStep(){if(this.traceIdQueue.length===0){this.solved=!0;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())}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(p4=>({x:p4.x,y:p4.y})),strokeColor:trace.mspPairId===this.activeTraceId?"red":"blue"};graphics.lines.push(line2)}return graphics}};function definePipelineStep2(solverName,solverClass,getConstructorParams,opts={}){return{solverName,solverClass,getConstructorParams,onSolved:opts.onSolved,shouldSkip:opts.shouldSkip}}var SchematicTracePipelineSolver=class extends BaseSolver4{constructor(inputProblem){super();__publicField(this,"mspConnectionPairSolver");__publicField(this,"schematicTraceLinesSolver");__publicField(this,"longDistancePairSolver");__publicField(this,"traceOverlapShiftSolver");__publicField(this,"netLabelPlacementSolver");__publicField(this,"labelMergingSolver");__publicField(this,"traceLabelOverlapAvoidanceSolver");__publicField(this,"traceCleanupSolver");__publicField(this,"startTimeOfPhase");__publicField(this,"endTimeOfPhase");__publicField(this,"timeSpentOnPhase");__publicField(this,"firstIterationOfPhase");__publicField(this,"inputProblem");__publicField(this,"pipelineDef",[definePipelineStep2("mspConnectionPairSolver",MspConnectionPairSolver,()=>[{inputProblem:this.inputProblem}],{onSolved:mspSolver=>{}}),definePipelineStep2("schematicTraceLinesSolver",SchematicTraceLinesSolver,()=>[{mspConnectionPairs:this.mspConnectionPairSolver.mspConnectionPairs,dcConnMap:this.mspConnectionPairSolver.dcConnMap,globalConnMap:this.mspConnectionPairSolver.globalConnMap,inputProblem:this.inputProblem,chipMap:this.mspConnectionPairSolver.chipMap}]),definePipelineStep2("longDistancePairSolver",LongDistancePairSolver,instance=>[{inputProblem:instance.inputProblem,primaryMspConnectionPairs:instance.mspConnectionPairSolver.mspConnectionPairs,alreadySolvedTraces:instance.schematicTraceLinesSolver.solvedTracePaths}],{onSolved:schematicTraceLinesSolver=>{}}),definePipelineStep2("traceOverlapShiftSolver",TraceOverlapShiftSolver,()=>[{inputProblem:this.inputProblem,inputTracePaths:this.longDistancePairSolver?.getOutput().allTracesMerged,globalConnMap:this.mspConnectionPairSolver.globalConnMap}],{onSolved:_solver=>{}}),definePipelineStep2("netLabelPlacementSolver",NetLabelPlacementSolver,()=>[{inputProblem:this.inputProblem,inputTraceMap:this.traceOverlapShiftSolver?.correctedTraceMap??Object.fromEntries(this.longDistancePairSolver.getOutput().allTracesMerged.map(p4=>[p4.mspPairId,p4]))}],{onSolved:_solver=>{}}),definePipelineStep2("traceLabelOverlapAvoidanceSolver",TraceLabelOverlapAvoidanceSolver,instance=>{let traceMap=instance.traceOverlapShiftSolver?.correctedTraceMap??Object.fromEntries(instance.longDistancePairSolver.getOutput().allTracesMerged.map(p4=>[p4.mspPairId,p4])),traces=Object.values(traceMap),netLabelPlacements=instance.netLabelPlacementSolver.netLabelPlacements;return[{inputProblem:instance.inputProblem,traces,netLabelPlacements}]}),definePipelineStep2("traceCleanupSolver",TraceCleanupSolver,instance=>{let traces=instance.traceLabelOverlapAvoidanceSolver.getOutput().traces,labelMergingOutput=instance.traceLabelOverlapAvoidanceSolver.labelMergingSolver.getOutput();return[{inputProblem:instance.inputProblem,allTraces:traces,allLabelPlacements:labelMergingOutput.netLabelPlacements,mergedLabelNetIdMap:labelMergingOutput.mergedLabelNetIdMap,paddingBuffer:.1}]}),definePipelineStep2("netLabelPlacementSolver",NetLabelPlacementSolver,instance=>{let traces=instance.traceCleanupSolver?.getOutput().traces??instance.traceLabelOverlapAvoidanceSolver.getOutput().traces;return[{inputProblem:instance.inputProblem,inputTraceMap:Object.fromEntries(traces.map(trace=>[trace.mspPairId,trace]))}]})]);__publicField(this,"currentPipelineStepIndex",0);this.inputProblem=this.cloneAndCorrectInputProblem(inputProblem),this.MAX_ITERATIONS=1e6,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={},this.firstIterationOfPhase={}}getConstructorParams(){return this.inputProblem}cloneAndCorrectInputProblem(original){let cloned=structuredClone({...original,_chipObstacleSpatialIndex:void 0});return expandChipsToFitPins(cloned),correctPinsInsideChips(cloned),cloned}_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().toLowerCase()!==phase.toLowerCase();)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();let visualizations=[visualizeInputProblem2(this.inputProblem),...this.pipelineDef.map(p4=>this[p4.solverName]?.visualize()).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(v5=>v5.points||[]),rects:visualizations.flatMap(v5=>v5.rects||[]),lines:visualizations.flatMap(v5=>v5.lines||[]),circles:visualizations.flatMap(v5=>v5.circles||[]),texts:visualizations.flatMap(v5=>v5.texts||[])}}preview(){return this.activeSubSolver?this.activeSubSolver.preview():super.preview()}};var import_debug14=__toESM(require_browser(),1);var import_debug15=__toESM(require_browser(),1);var import_debug16=__toESM(require_browser(),1);function findConnectedNetworks2(connections){let networks=new Map,netCounter=0;function getOrCreateNetwork(nodeId){for(let[,network]of networks)if(network.has(nodeId))return network;let newNetwork=new Set;return networks.set(`connectivity_net${netCounter++}`,newNetwork),newNetwork}for(let connection of connections){let network=null;for(let nodeId of connection){if(!network)network=getOrCreateNetwork(nodeId);else if(!network.has(nodeId)){let existingNetwork=getOrCreateNetwork(nodeId);if(existingNetwork!==network){for(let node of existingNetwork)network.add(node);networks.delete(Array.from(networks.entries()).find(([,net])=>net===existingNetwork)[0])}}network.add(nodeId)}}return Object.fromEntries(Array.from(networks.entries()).map(([netId,connectedNodes])=>[netId,Array.from(connectedNodes)]))}var ConnectivityMap3=class{constructor(netMap){__publicField(this,"netMap");__publicField(this,"idToNetMap");this.netMap=netMap,this.idToNetMap={};for(let[netId,ids]of Object.entries(netMap))for(let id of ids)this.idToNetMap[id]=netId}addConnections(connections){for(let connection of connections){let existingNets=new Set;for(let id of connection){let existingNetId=this.idToNetMap[id];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){this.netMap[targetNetId].push(...this.netMap[netId]),this.netMap[netId]=this.netMap[targetNetId];for(let id of this.netMap[targetNetId])this.idToNetMap[id]=targetNetId}}for(let id of connection)this.netMap[targetNetId].includes(id)||this.netMap[targetNetId].push(id),this.idToNetMap[id]=targetNetId}}getIdsConnectedToNet(netId){return this.netMap[netId]||[]}getNetConnectedToId(id){return this.idToNetMap[id]}areIdsConnected(id1,id2){if(id1===id2)return!0;let netId1=this.getNetConnectedToId(id1);if(!netId1)return!1;let netId2=this.getNetConnectedToId(id2);return netId2?netId1===netId2||netId2===id1||netId2===id1:!1}areAllIdsConnected(ids){let netId=this.getNetConnectedToId(ids[0]);for(let id of ids){let nextNetId=this.getNetConnectedToId(id);if(nextNetId===void 0||nextNetId!==netId)return!1}return!0}},getSourcePortConnectivityMapFromCircuitJson=circuitJson=>{let connections=[];for(let element of circuitJson)if(element.type==="source_trace")connections.push([...element.connected_source_port_ids??[],...element.connected_source_net_ids??[]]);else if(element.type==="source_component"&&element.internally_connected_source_port_ids)for(let portGroup of element.internally_connected_source_port_ids)connections.push(portGroup);let netMap=findConnectedNetworks2(connections);return new ConnectivityMap3(netMap)};init_dist6();var convertSpiceNetlistToString=netlist=>{let lines=[];lines.push(netlist.title),netlist.models.size>0&&lines.push(...Array.from(netlist.models.values()));for(let component of netlist.components)lines.push(component.toSpiceString());for(let subcircuit of netlist.subcircuits)lines.push(subcircuit.toSpiceString());return netlist.printStatements.length>0&&lines.push(...netlist.printStatements),netlist.controls.length>0&&(lines.push(".control"),lines.push(...netlist.controls),lines.push(".endc")),netlist.tranCommand&&!lines.some(l3=>l3.trim().toLowerCase().startsWith(".tran"))&&lines.push(netlist.tranCommand),lines.push(".END"),lines.join(`
|
|
616
616
|
`)},SpiceNetlist=class{constructor(title="Circuit Netlist"){__publicField(this,"title");__publicField(this,"components");__publicField(this,"nodes");__publicField(this,"controls");__publicField(this,"subcircuits");__publicField(this,"models");__publicField(this,"tranCommand");__publicField(this,"printStatements");this.title=title,this.components=[],this.nodes=new Set,this.controls=[],this.subcircuits=[],this.models=new Map,this.tranCommand=null,this.printStatements=[]}addComponent(component){this.components.push(component);for(let node of component.nodes)this.nodes.add(node)}addSubcircuit(subcircuit){this.subcircuits.find(s2=>s2.name===subcircuit.name)||this.subcircuits.push(subcircuit)}toSpiceString(){return convertSpiceNetlistToString(this)}},SpiceComponent=class{constructor(name,command,nodes){__publicField(this,"name");__publicField(this,"command");__publicField(this,"nodes");this.name=name,this.command=command,this.nodes=nodes}toSpiceString(){return this.command.toSpiceString()}},BJTCommand=class{constructor(props){__publicField(this,"commandName","bjt");__publicField(this,"props");this.props=props}toSpiceString(){let{name,collector,base,emitter,substrate,model,area}=this.props,spiceString=`Q${name} ${collector} ${base} ${emitter}`;return substrate&&(spiceString+=` ${substrate}`),spiceString+=` ${model}`,area&&(spiceString+=` ${area}`),spiceString}},CapacitorCommand=class{constructor(props){__publicField(this,"commandName","capacitor");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,modelName,value,initialCondition}=this.props,spiceString=`C${name} ${positiveNode} ${negativeNode}`;return modelName&&(spiceString+=` ${modelName}`),spiceString+=` ${value}`,initialCondition&&(spiceString+=` IC=${initialCondition}`),spiceString}},CurrentSourceCommand=class{constructor(props){__publicField(this,"commandName","current_source");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,value,acMagnitude,acPhase}=this.props,spiceString=`I${name} ${positiveNode} ${negativeNode}`;return value&&(spiceString+=` ${value}`),acMagnitude&&(spiceString+=` AC ${acMagnitude}`,acPhase&&(spiceString+=` ${acPhase}`)),spiceString}},DiodeCommand=class{constructor(props){__publicField(this,"commandName","diode");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,model,area}=this.props,spiceString=`D${name} ${positiveNode} ${negativeNode} ${model}`;return area&&(spiceString+=` ${area}`),spiceString}},InductorCommand=class{constructor(props){__publicField(this,"commandName","inductor");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,model,value,initialCondition}=this.props,spiceString=`L${name} ${positiveNode} ${negativeNode}`;return model&&(spiceString+=` ${model}`),spiceString+=` ${value}`,initialCondition&&(spiceString+=` IC=${initialCondition}`),spiceString}};var MOSFETCommand=class{constructor(props){__publicField(this,"commandName","mosfet");__publicField(this,"props");this.props=props}toSpiceString(){let{name,drain,gate,source,substrate,model,length:length3,width,drainArea,sourceArea,drainPerimeter,sourcePerimeter,drainResistance,sourceResistance}=this.props,spiceString=`M${name} ${drain} ${gate} ${source} ${substrate} ${model}`;return Object.entries({L:length3,W:width,AD:drainArea,AS:sourceArea,PD:drainPerimeter,PS:sourcePerimeter,NRD:drainResistance,NRS:sourceResistance}).forEach(([key,value])=>{value&&(spiceString+=` ${key}=${value}`)}),spiceString}},ResistorCommand=class{constructor(props){__publicField(this,"commandName","resistor");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,model,value}=this.props,spiceString=`R${name} ${positiveNode} ${negativeNode}`;return model&&(spiceString+=` ${model}`),spiceString+=` ${value}`,spiceString}};var VoltageControlledSwitchCommand=class{constructor(props){__publicField(this,"commandName","voltage_controlled_switch");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,positiveControl,negativeControl,model}=this.props;return`S${name} ${positiveNode} ${negativeNode} ${positiveControl} ${negativeControl} ${model}`}},VoltageSourceCommand=class{constructor(props){__publicField(this,"commandName","voltage_source");__publicField(this,"props");this.props=props}toSpiceString(){let{name,positiveNode,negativeNode,value,acMagnitude,acPhase}=this.props,spiceString=`V${name} ${positiveNode} ${negativeNode}`;return value&&(spiceString+=` ${value}`),acMagnitude&&(spiceString+=` AC ${acMagnitude}`,acPhase&&(spiceString+=` ${acPhase}`)),spiceString}};function formatResistance(resistance2){return resistance2>=1e6?`${resistance2/1e6}MEG`:resistance2>=1e3?`${resistance2/1e3}K`:resistance2.toString()}function formatCapacitance(capacitance2){return capacitance2>=.001?`${capacitance2*1e3}M`:capacitance2>=1e-6?`${capacitance2*1e6}U`:capacitance2>=1e-9?`${capacitance2*1e9}N`:capacitance2>=1e-12?`${capacitance2*1e12}P`:capacitance2.toString()}function formatInductance(inductance2){return inductance2>=1?inductance2.toString():inductance2>=.001?`${inductance2*1e3}m`:inductance2>=1e-6?`${inductance2*1e6}u`:inductance2>=1e-9?`${inductance2*1e9}n`:inductance2>=1e-12?`${inductance2*1e12}p`:inductance2.toString()}function sanitizeIdentifier(value,prefix){if(!value)return prefix;let sanitized=value.replace(/[^A-Za-z0-9_]/g,"_");return sanitized?/^[0-9]/.test(sanitized)?`${prefix}_${sanitized}`:sanitized:prefix}function buildSimulationSwitchControlValue(simulationSwitch){if(!simulationSwitch)return"DC 0";let startsClosed=simulationSwitch.starts_closed??!1,closesAt=simulationSwitch.closes_at??0,opensAt=simulationSwitch.opens_at,switchingFrequency=simulationSwitch.switching_frequency,[initialVoltage,pulsedVoltage]=startsClosed?[5,0]:[0,5];if(switchingFrequency&&switchingFrequency>0){let period=1/switchingFrequency,widthFromOpenClose=opensAt&&opensAt>closesAt?Math.min(opensAt-closesAt,period):0,pulseWidth=widthFromOpenClose>0?widthFromOpenClose:Math.max(period/2,1e-9);return`PULSE(${formatNumberForSpice(initialVoltage)} ${formatNumberForSpice(pulsedVoltage)} ${formatNumberForSpice(closesAt)} 1n 1n ${formatNumberForSpice(pulseWidth)} ${formatNumberForSpice(period)})`}if(opensAt!==void 0&&opensAt>closesAt){let pulseWidth=Math.max(opensAt-closesAt,1e-9),period=closesAt+pulseWidth*2;return`PULSE(${formatNumberForSpice(initialVoltage)} ${formatNumberForSpice(pulsedVoltage)} ${formatNumberForSpice(closesAt)} 1n 1n ${formatNumberForSpice(pulseWidth)} ${formatNumberForSpice(period)})`}if(closesAt>0){let period=closesAt*2,pulseWidth=Math.max(period/2,1e-9);return`PULSE(${formatNumberForSpice(initialVoltage)} ${formatNumberForSpice(pulsedVoltage)} ${formatNumberForSpice(closesAt)} 1n 1n ${formatNumberForSpice(pulseWidth)} ${formatNumberForSpice(period)})`}return`DC ${startsClosed?5:0}`}function formatNumberForSpice(value){if(!Number.isFinite(value))return`${value}`;if(value===0)return"0";let absValue=Math.abs(value);return absValue>=1e3||absValue<=.001?Number(value.toExponential(6)).toString():Number(value.toPrecision(6)).toString()}var processSimpleResistor=({component,nodes})=>{if("resistance"in component&&"name"in component){let resistorCmd=new ResistorCommand({name:component.name,positiveNode:nodes[0]||"0",negativeNode:nodes[1]||"0",value:formatResistance(component.resistance)});return new SpiceComponent(component.name,resistorCmd,nodes)}return null},processSimpleSwitch=({netlist,component,nodes,simulationSwitchMap})=>{let sanitizedBase=sanitizeIdentifier(component.name??component.source_component_id,"SW"),positiveNode=nodes[0]||"0",negativeNode=nodes[1]||"0",controlNode=`NCTRL_${sanitizedBase}`,modelName=`SW_${sanitizedBase}`,associatedSimulationSwitch=simulationSwitchMap.get(component.source_component_id),controlValue=buildSimulationSwitchControlValue(associatedSimulationSwitch),switchCmd=new VoltageControlledSwitchCommand({name:sanitizedBase,positiveNode,negativeNode,positiveControl:controlNode,negativeControl:"0",model:modelName});netlist.models.has(modelName)||netlist.models.set(modelName,`.MODEL ${modelName} SW(Ron=0.1 Roff=1e9 Vt=2.5 Vh=0.1)`);let controlSourceName=`CTRL_${sanitizedBase}`,controlSourceCmd=new VoltageSourceCommand({name:controlSourceName,positiveNode:controlNode,negativeNode:"0",value:controlValue}),controlComponent=new SpiceComponent(controlSourceName,controlSourceCmd,[controlNode,"0"]);return netlist.addComponent(controlComponent),new SpiceComponent(sanitizedBase,switchCmd,[positiveNode,negativeNode,controlNode,"0"])},processSimpleCapacitor=({component,nodes})=>{if("capacitance"in component&&"name"in component){let capacitorCmd=new CapacitorCommand({name:component.name,positiveNode:nodes[0]||"0",negativeNode:nodes[1]||"0",value:formatCapacitance(component.capacitance)});return new SpiceComponent(component.name,capacitorCmd,nodes)}return null},processSimpleDiode=({netlist,component,componentPorts,nodeMap})=>{if("name"in component){let anodePort=componentPorts.find(p4=>p4.name?.toLowerCase()==="anode"||p4.port_hints?.includes("anode")),cathodePort=componentPorts.find(p4=>p4.name?.toLowerCase()==="cathode"||p4.port_hints?.includes("cathode")),positiveNode=nodeMap.get(anodePort?.source_port_id??"")||"0",negativeNode=nodeMap.get(cathodePort?.source_port_id??"")||"0",modelName="D",diodeCmd=new DiodeCommand({name:component.name,positiveNode,negativeNode,model:modelName});return netlist.models.set(modelName,`.MODEL ${modelName} D`),new SpiceComponent(component.name,diodeCmd,[positiveNode,negativeNode])}return null},processSimpleInductor=({component,nodes})=>{if("inductance"in component&&"name"in component){let inductorCmd=new InductorCommand({name:component.name,positiveNode:nodes[0]||"0",negativeNode:nodes[1]||"0",value:formatInductance(component.inductance)});return new SpiceComponent(component.name,inductorCmd,nodes)}return null},processSimpleMosfet=({netlist,component,componentPorts,nodeMap})=>{if("name"in component){let drainPort=componentPorts.find(p4=>p4.name?.toLowerCase()==="drain"||p4.port_hints?.includes("drain")),gatePort=componentPorts.find(p4=>p4.name?.toLowerCase()==="gate"||p4.port_hints?.includes("gate")),sourcePort=componentPorts.find(p4=>p4.name?.toLowerCase()==="source"||p4.port_hints?.includes("source")),drainNode=nodeMap.get(drainPort?.source_port_id??"")||"0",gateNode=nodeMap.get(gatePort?.source_port_id??"")||"0",sourceNode=nodeMap.get(sourcePort?.source_port_id??"")||"0",substrateNode=sourceNode,channel_type=component.channel_type??"n",mosfet_mode=component.mosfet_mode??"enhancement",modelType=`${channel_type.toUpperCase()}MOS`,modelName=`${modelType}_${mosfet_mode.toUpperCase()}`;if(!netlist.models.has(modelName))if(mosfet_mode==="enhancement"){let vto=channel_type==="p"?-1:1;netlist.models.set(modelName,`.MODEL ${modelName} ${modelType} (VTO=${vto} KP=0.1)`)}else netlist.models.set(modelName,`.MODEL ${modelName} ${modelType} (KP=0.1)`);let mosfetCmd=new MOSFETCommand({name:component.name,drain:drainNode,gate:gateNode,source:sourceNode,substrate:substrateNode,model:modelName});return new SpiceComponent(component.name,mosfetCmd,[drainNode,gateNode,sourceNode])}return null},processSimpleTransistor=({netlist,component,componentPorts,nodeMap})=>{if("name"in component){let collectorPort=componentPorts.find(p4=>p4.name?.toLowerCase()==="collector"||p4.port_hints?.includes("collector")),basePort=componentPorts.find(p4=>p4.name?.toLowerCase()==="base"||p4.port_hints?.includes("base")),emitterPort=componentPorts.find(p4=>p4.name?.toLowerCase()==="emitter"||p4.port_hints?.includes("emitter"));if(!collectorPort||!basePort||!emitterPort)throw new Error(`Transistor ${component.name} is missing required ports (collector, base, emitter)`);let collectorNode=nodeMap.get(collectorPort.source_port_id)||"0",baseNode=nodeMap.get(basePort.source_port_id)||"0",emitterNode=nodeMap.get(emitterPort.source_port_id)||"0",transistor_type=component.transistor_type??"npn",modelName=transistor_type.toUpperCase();netlist.models.has(modelName)||netlist.models.set(modelName,`.MODEL ${modelName} ${transistor_type.toUpperCase()}`);let bjtCmd=new BJTCommand({name:component.name,collector:collectorNode,base:baseNode,emitter:emitterNode,model:modelName});return new SpiceComponent(component.name,bjtCmd,[collectorNode,baseNode,emitterNode])}return null},processSimulationVoltageSources=(netlist,simulationVoltageSources,nodeMap)=>{for(let simSource of simulationVoltageSources)if(simSource.type==="simulation_voltage_source")if(simSource.is_dc_source===!1){if("terminal1_source_port_id"in simSource&&"terminal2_source_port_id"in simSource&&simSource.terminal1_source_port_id&&simSource.terminal2_source_port_id){let positiveNode=nodeMap.get(simSource.terminal1_source_port_id)||"0",negativeNode=nodeMap.get(simSource.terminal2_source_port_id)||"0",value="",wave_shape2=simSource.wave_shape;if(wave_shape2==="sinewave"){let v_peak=simSource.voltage??0,freq=simSource.frequency??0,delay=0,damping_factor=0,phase=simSource.phase??0;freq>0?value=`SIN(0 ${v_peak} ${freq} ${delay} ${damping_factor} ${phase})`:value=`DC ${simSource.voltage??0}`}else if(wave_shape2==="square"){let v_pulsed=simSource.voltage??0,freq=simSource.frequency??0,period=freq===0?1/0:1/freq,duty_cycle=simSource.duty_cycle??.5,pulse_width=period*duty_cycle;value=`PULSE(0 ${v_pulsed} 0 1n 1n ${pulse_width} ${period})`}else simSource.voltage!==void 0&&(value=`DC ${simSource.voltage}`);if(value){let voltageSourceCmd=new VoltageSourceCommand({name:simSource.simulation_voltage_source_id,positiveNode,negativeNode,value}),spiceComponent=new SpiceComponent(simSource.simulation_voltage_source_id,voltageSourceCmd,[positiveNode,negativeNode]);netlist.addComponent(spiceComponent)}}}else{let positivePortId=simSource.positive_source_port_id,negativePortId=simSource.negative_source_port_id;if(positivePortId&&negativePortId&&"voltage"in simSource&&simSource.voltage!==void 0){let positiveNode=nodeMap.get(positivePortId)||"0",negativeNode=nodeMap.get(negativePortId)||"0",voltageSourceCmd=new VoltageSourceCommand({name:simSource.simulation_voltage_source_id,positiveNode,negativeNode,value:`DC ${simSource.voltage}`}),spiceComponent=new SpiceComponent(simSource.simulation_voltage_source_id,voltageSourceCmd,[positiveNode,negativeNode]);netlist.addComponent(spiceComponent)}}},processSimulationCurrentSources=(netlist,simulationCurrentSources,nodeMap)=>{for(let simSource of simulationCurrentSources)if(simSource.type==="simulation_current_source")if(simSource.is_dc_source===!1){let positivePortId=simSource.terminal1_source_port_id,negativePortId=simSource.terminal2_source_port_id;if(positivePortId&&negativePortId){let positiveNode=nodeMap.get(positivePortId)||"0",negativeNode=nodeMap.get(negativePortId)||"0",value="",wave_shape2=simSource.wave_shape;if(wave_shape2==="sinewave"){let i_peak=(simSource.peak_to_peak_current??0)/2,freq=simSource.frequency??0,delay=0,damping_factor=0,phase=simSource.phase??0;freq>0?value=`SIN(0 ${i_peak} ${freq} ${delay} ${damping_factor} ${phase})`:value=`DC ${i_peak}`}else if(wave_shape2==="square"){let i_pulsed=simSource.peak_to_peak_current??0,freq=simSource.frequency??0,period=freq===0?1/0:1/freq,duty_cycle=simSource.duty_cycle??.5,pulse_width=period*duty_cycle;value=`PULSE(0 ${i_pulsed} 0 1n 1n ${pulse_width} ${period})`}if(value){let currentSourceCmd=new CurrentSourceCommand({name:simSource.simulation_current_source_id,positiveNode,negativeNode,value}),spiceComponent=new SpiceComponent(simSource.simulation_current_source_id,currentSourceCmd,[positiveNode,negativeNode]);netlist.addComponent(spiceComponent)}}}else{let positivePortId=simSource.positive_source_port_id,negativePortId=simSource.negative_source_port_id;if(positivePortId&&negativePortId&&"current"in simSource&&simSource.current!==void 0){let positiveNode=nodeMap.get(positivePortId)||"0",negativeNode=nodeMap.get(negativePortId)||"0",currentSourceCmd=new CurrentSourceCommand({name:simSource.simulation_current_source_id,positiveNode,negativeNode,value:`DC ${simSource.current}`}),spiceComponent=new SpiceComponent(simSource.simulation_current_source_id,currentSourceCmd,[positiveNode,negativeNode]);netlist.addComponent(spiceComponent)}}},processSimulationExperiment=(netlist,simExperiment,simulationProbes,sourceTraces,nodeMap)=>{if(!simExperiment)return;if(simulationProbes.length>0){let nodesToProbe=new Set,getPortIdFromNetId=netId=>sourceTraces.find(t5=>t5.connected_source_net_ids.includes(netId))?.connected_source_port_ids[0];for(let probe of simulationProbes){let signalPortId=probe.signal_input_source_port_id;if(!signalPortId){let signalNetId=probe.signal_input_source_net_id;signalNetId&&(signalPortId=getPortIdFromNetId(signalNetId))}if(!signalPortId)continue;let signalNodeName=nodeMap.get(signalPortId);if(!signalNodeName)continue;let referencePortId=probe.reference_input_source_port_id;if(!referencePortId&&probe.reference_input_source_net_id&&(referencePortId=getPortIdFromNetId(probe.reference_input_source_net_id)),referencePortId){let referenceNodeName=nodeMap.get(referencePortId);referenceNodeName&&referenceNodeName!=="0"?nodesToProbe.add(`V(${signalNodeName},${referenceNodeName})`):signalNodeName!=="0"&&nodesToProbe.add(`V(${signalNodeName})`)}else signalNodeName!=="0"&&nodesToProbe.add(`V(${signalNodeName})`)}nodesToProbe.size>0&&simExperiment.experiment_type?.includes("transient")&&netlist.printStatements.push(`.PRINT TRAN ${[...nodesToProbe].join(" ")}`)}let timePerStep=simExperiment.time_per_step,endTime=simExperiment.end_time_ms,startTimeMs=simExperiment.start_time_ms;if(timePerStep&&endTime){let startTime=(startTimeMs??0)/1e3,tranCmd=`.tran ${formatNumberForSpice(timePerStep/1e3)} ${formatNumberForSpice(endTime/1e3)}`;startTime>0&&(tranCmd+=` ${formatNumberForSpice(startTime)}`),tranCmd+=" UIC",netlist.tranCommand=tranCmd}};function circuitJsonToSpice(circuitJson){let netlist=new SpiceNetlist("* Circuit JSON to SPICE Netlist"),sourceComponents=su2(circuitJson).source_component.list(),sourcePorts=su2(circuitJson).source_port.list(),sourceTraces=su2(circuitJson).source_trace.list(),simulationProbes=circuitJson.filter(elm=>elm.type==="simulation_voltage_probe"),simulationSwitches=circuitJson.filter(element=>element.type==="simulation_switch").map(element=>element),simulationSwitchMap=new Map;for(let simSwitch of simulationSwitches)simSwitch.source_component_id&&simulationSwitchMap.set(simSwitch.source_component_id,simSwitch);let connMap=getSourcePortConnectivityMapFromCircuitJson(circuitJson),nodeMap=new Map,netToNodeName=new Map,nodeCounter=1,probeNames=new Set;if(simulationProbes.length>0)for(let probe of simulationProbes)probe.name&&probeNames.add(probe.name);let numericProbeNames=[...probeNames].map(name=>/^N(\d+)$/i.exec(name)).filter(m3=>m3!==null).map(m3=>parseInt(m3[1],10));numericProbeNames.length>0&&(nodeCounter=Math.max(...numericProbeNames)+1);let groundNets=new Set,gndSourceNetIds=new Set(su2(circuitJson).source_net.list().filter(sn4=>sn4.name?.toLowerCase().includes("gnd")).map(sn4=>sn4.source_net_id));if(gndSourceNetIds.size>0){for(let trace of su2(circuitJson).source_trace.list())if(trace.connected_source_port_ids.length>0&&trace.connected_source_net_ids.some(netId=>gndSourceNetIds.has(netId))){let aPortOnGnd=trace.connected_source_port_ids[0],gndNet=connMap.getNetConnectedToId(aPortOnGnd);gndNet&&groundNets.add(gndNet)}}let groundPorts=sourcePorts.filter(p4=>p4.name?.toLowerCase()==="gnd");for(let groundPort of groundPorts){let groundNet=connMap.getNetConnectedToId(groundPort.source_port_id);groundNet&&groundNets.add(groundNet)}for(let simSource of su2(circuitJson).simulation_voltage_source.list()){let neg_port_id=simSource.negative_source_port_id??simSource.terminal2_source_port_id;if(neg_port_id){let gnd_net=connMap.getNetConnectedToId(neg_port_id);gnd_net&&groundNets.add(gnd_net)}}for(let groundNet of groundNets)netToNodeName.set(groundNet,"0");if(simulationProbes.length>0)for(let probe of simulationProbes){if(!probe.name||probe.reference_input_source_port_id||probe.reference_input_source_net_id)continue;let net,signal_port_id=probe.signal_input_source_port_id,signal_net_id=probe.signal_input_source_net_id;if(signal_port_id)net=connMap.getNetConnectedToId(signal_port_id);else if(signal_net_id){let trace=sourceTraces.find(t5=>t5.connected_source_net_ids.includes(signal_net_id));if(trace&&trace.connected_source_port_ids.length>0){let portId=trace.connected_source_port_ids[0];net=connMap.getNetConnectedToId(portId)}}net?netToNodeName.has(net)||netToNodeName.set(net,probe.name):signal_port_id&&probe.name&&nodeMap.set(signal_port_id,probe.name)}for(let port of sourcePorts){let portId=port.source_port_id,net=connMap.getNetConnectedToId(portId);net&&(netToNodeName.has(net)||netToNodeName.set(net,`N${nodeCounter++}`),nodeMap.set(portId,netToNodeName.get(net)))}for(let port of sourcePorts){let portId=port.source_port_id;nodeMap.has(portId)||nodeMap.set(portId,`N${nodeCounter++}`)}for(let component of sourceComponents){if(component.type!=="source_component")continue;let componentPorts=su2(circuitJson).source_port.list({source_component_id:component.source_component_id}).sort((a2,b3)=>(a2.pin_number??0)-(b3.pin_number??0)),nodes=componentPorts.map(port=>nodeMap.get(port.source_port_id)||"0");if("ftype"in component){let spiceComponent=null;switch(component.ftype){case"simple_resistor":{spiceComponent=processSimpleResistor({component,nodes});break}case"simple_switch":{spiceComponent=processSimpleSwitch({netlist,component,nodes,simulationSwitchMap});break}case"simple_capacitor":{spiceComponent=processSimpleCapacitor({component,nodes});break}case"simple_diode":{spiceComponent=processSimpleDiode({netlist,component,componentPorts,nodeMap});break}case"simple_inductor":{spiceComponent=processSimpleInductor({component,nodes});break}case"simple_mosfet":{spiceComponent=processSimpleMosfet({netlist,component,componentPorts,nodeMap});break}case"simple_transistor":{spiceComponent=processSimpleTransistor({netlist,component,componentPorts,nodeMap});break}}spiceComponent&&netlist.addComponent(spiceComponent)}}processSimulationVoltageSources(netlist,su2(circuitJson).simulation_voltage_source.list(),nodeMap),processSimulationCurrentSources(netlist,su2(circuitJson).simulation_current_source.list(),nodeMap);let simulationExperiment=circuitJson.find(elm=>elm.type==="simulation_experiment");return simulationExperiment&&processSimulationExperiment(netlist,simulationExperiment,simulationProbes,sourceTraces,nodeMap),netlist}var import_debug17=__toESM(require_browser(),1);var EPS5=1e-15,NodeIndex=class{constructor(){__publicField(this,"map");__publicField(this,"rev");this.map=new Map([["0",0]]),this.rev=["0"]}getOrCreate(name){let origName=String(name),key=origName.toUpperCase();if(this.map.has(key))return this.map.get(key);let idx=this.rev.length;return this.map.set(key,idx),this.rev.push(origName),idx}get(name){return this.map.get(String(name).toUpperCase())}count(){return this.rev.length}matrixIndexOfNode(nodeId){return nodeId===0?-1:nodeId-1}};function parseNumberWithUnits(raw){if(raw==null)return NaN;let s2=String(raw).trim();if(s2==="")return NaN;if(/^[+-]?\d*\.?\d+(?:[eE][+-]?\d+)?$/.test(s2))return parseFloat(s2);let unitMul={t:1e12,g:1e9,meg:1e6,k:1e3,m:.001,u:1e-6,n:1e-9,p:1e-12,f:1e-15},m3=s2.match(/^([+-]?\d*\.?\d+(?:[eE][+-]?\d+)?)([a-zA-Z]+)$/);if(!m3)return parseFloat(s2);let[,numberPart,suffixPart]=m3;if(numberPart==null)return parseFloat(s2);let val=parseFloat(numberPart),suf=(suffixPart??"").toLowerCase();return suf=suf.replace(/(ohm|v|a|s|h|f)$/g,""),suf==="meg"?val*unitMul.meg:suf.length===1&&suf in unitMul?val*unitMul[suf]:val}function parsePulseArgs(token){let parts=token.trim().replace(/^pulse\s*\(/i,"(").replace(/^\(/,"").replace(/\)$/,"").trim().split(/[\s,]+/).filter(x5=>x5.length);if(parts.length<7)throw new Error("PULSE(...) requires 7 or 8 args");let vals=parts.map(value=>parseNumberWithUnits(value));if(vals.some(v5=>Number.isNaN(v5)))throw new Error("Invalid PULSE() numeric value");return{v1:vals[0],v2:vals[1],td:vals[2],tr:vals[3],tf:vals[4],ton:vals[5],period:vals[6],ncycles:parts[7]!=null?vals[7]:1/0}}function parsePwlArgs(token){let parts=token.trim().replace(/^pwl\s*\(/i,"(").replace(/^\(/,"").replace(/\)$/,"").trim().split(/[\s,]+/).filter(x5=>x5.length);if(parts.length===0||parts.length%2!==0)throw new Error("PWL(...) requires an even number of time/value pairs");let pairs3=[];for(let i2=0;i2<parts.length;i2+=2){let t5=parseNumberWithUnits(parts[i2]),v5=parseNumberWithUnits(parts[i2+1]);if(Number.isNaN(t5)||Number.isNaN(v5))throw new Error("Invalid PWL() numeric value");pairs3.push({t:t5,v:v5})}return pairs3}function pulseValue(p4,t5){if(t5<p4.td)return p4.v1;let tt4=t5-p4.td,cyclesDone=Math.floor(tt4/p4.period);if(cyclesDone>=p4.ncycles)return p4.v1;let tc2=tt4-cyclesDone*p4.period;if(tc2<p4.tr){let a2=tc2/Math.max(p4.tr,EPS5);return p4.v1+(p4.v2-p4.v1)*a2}if(tc2<p4.tr+p4.ton)return p4.v2;if(tc2<p4.tr+p4.ton+p4.tf){let a2=(tc2-(p4.tr+p4.ton))/Math.max(p4.tf,EPS5);return p4.v2+(p4.v1-p4.v2)*a2}return p4.v1}function pwlValue(pairs3,t5){if(pairs3.length===0)return 0;if(t5<=pairs3[0].t)return pairs3[0].v;for(let i2=1;i2<pairs3.length;i2++){let prev=pairs3[i2-1],curr=pairs3[i2];if(t5<=curr.t){let dt4=Math.max(curr.t-prev.t,EPS5),a2=(t5-prev.t)/dt4;return prev.v+(curr.v-prev.v)*a2}}return pairs3[pairs3.length-1].v}function smartTokens(line2){let re4=/"[^"]*"|\w+\s*\([^)]*\)|\([^()]*\)|\S+/g,out=[],m3;for(;(m3=re4.exec(line2))!==null;)out.push(m3[0]);return out}function requireToken(tokens,index,context){let token=tokens[index];if(token==null)throw new Error(context);return token}function parseNetlist(text){let vswitchModels=new Map,diodeModels=new Map,ckt={nodes:new NodeIndex,R:[],C:[],L:[],V:[],S:[],D:[],analyses:{ac:null,tran:null},probes:{tran:[]},skipped:[],models:{vswitch:vswitchModels,diode:diodeModels}},lines=text.split(/\r?\n/),seenTitle=!1;for(let raw of lines){let line2=raw.trim();if(!line2||/^\*/.test(line2))continue;if(/^\s*\.end\b/i.test(line2))break;line2=line2.replace(/\/\/.*$/,""),line2=line2.replace(/;.*$/,"");let tokens=smartTokens(line2);if(tokens.length===0)continue;let first=tokens[0];if(first.length===0)continue;if(!seenTitle&&!/^[rclvgsmiqd]\w*$/i.test(first)&&!/^\./.test(first)){seenTitle=!0;continue}if(/^\./.test(first)){let dir=first.toLowerCase();if(dir===".ac"){let mode=requireToken(tokens,1,".ac missing mode").toLowerCase();if(mode!=="dec"&&mode!=="lin")throw new Error(".ac supports 'dec' or 'lin'");let N6=parseInt(requireToken(tokens,2,".ac missing point count"),10),f12=parseNumberWithUnits(requireToken(tokens,3,".ac missing start frequency")),f2=parseNumberWithUnits(requireToken(tokens,4,".ac missing stop frequency"));ckt.analyses.ac={mode,N:N6,f1:f12,f2}}else if(dir===".tran"){let dt4=parseNumberWithUnits(requireToken(tokens,1,".tran missing timestep")),tstop=parseNumberWithUnits(requireToken(tokens,2,".tran missing stop time"));ckt.analyses.tran={dt:dt4,tstop}}else if(dir===".print")if(requireToken(tokens,1,".print missing analysis type").toLowerCase()==="tran"){let probeTokens=tokens.slice(2);for(let token of probeTokens){let match2=token.match(/^v\(([^)]+)\)$/i);if(match2&&match2[1]){let nodeName2=match2[1];ckt.probes.tran.some(p4=>p4.toUpperCase()===nodeName2.toUpperCase())||ckt.probes.tran.push(nodeName2)}}}else ckt.skipped.push(line2);else if(dir===".model"){let nameToken=requireToken(tokens,1,".model missing name"),type=requireToken(tokens,2,".model missing type"),paramsStr="";if(type.includes("(")){let idx=type.indexOf("(");paramsStr=type.slice(idx+1),type=type.slice(0,idx)}if(!paramsStr)paramsStr=tokens.slice(3).join(" ").replace(/^\(/,"").replace(/\)$/,"");else{let rest=tokens.slice(3).join(" ").replace(/\)$/,"");paramsStr=`${paramsStr} ${rest}`.trim()}paramsStr=paramsStr.replace(/^\(/,"").replace(/\)$/,"").trim();let typeLower=type.toLowerCase();if(typeLower==="vswitch"||typeLower==="sw"){let model={name:nameToken,Ron:1,Roff:1e12,Von:0,Voff:0},vt4,vh2;if(paramsStr.length>0){let assignments=paramsStr.split(/[\s,]+/).filter(Boolean);for(let assignment of assignments){let[keyRaw,valueRaw]=assignment.split("=");if(!keyRaw||valueRaw==null)continue;let key=keyRaw.toLowerCase(),value=parseNumberWithUnits(valueRaw);Number.isNaN(value)||(key==="ron"?model.Ron=value:key==="roff"?model.Roff=value:key==="von"?model.Von=value:key==="voff"?model.Voff=value:key==="vt"?vt4=value:key==="vh"&&(vh2=value))}}if(vt4!==void 0){let Vh2=vh2??0;model.Von=vt4+Vh2/2,model.Voff=vt4-Vh2/2}vswitchModels.set(nameToken.toLowerCase(),model)}else if(typeLower==="d"){let model={name:nameToken,Is:1e-14,N:1};if(paramsStr.length>0){let assignments=paramsStr.split(/[\s,]+/).filter(Boolean);for(let assignment of assignments){let[keyRaw,valueRaw]=assignment.split("=");if(!keyRaw||valueRaw==null)continue;let key=keyRaw.toLowerCase(),value=parseNumberWithUnits(valueRaw);Number.isNaN(value)||(key==="is"?model.Is=value:key==="n"&&(model.N=value))}}diodeModels.set(nameToken.toLowerCase(),model)}else ckt.skipped.push(line2)}else ckt.skipped.push(line2);continue}let typeChar=first.charAt(0).toLowerCase(),name=first;try{if(typeChar==="r"){let n12=ckt.nodes.getOrCreate(requireToken(tokens,1,"Resistor missing node")),n22=ckt.nodes.getOrCreate(requireToken(tokens,2,"Resistor missing node")),val=parseNumberWithUnits(requireToken(tokens,3,"Resistor missing value"));ckt.R.push({name,n1:n12,n2:n22,R:val})}else if(typeChar==="c"){let n12=ckt.nodes.getOrCreate(requireToken(tokens,1,"Capacitor missing node")),n22=ckt.nodes.getOrCreate(requireToken(tokens,2,"Capacitor missing node")),val=parseNumberWithUnits(requireToken(tokens,3,"Capacitor missing value"));ckt.C.push({name,n1:n12,n2:n22,C:val,vPrev:0})}else if(typeChar==="l"){let n12=ckt.nodes.getOrCreate(requireToken(tokens,1,"Inductor missing node")),n22=ckt.nodes.getOrCreate(requireToken(tokens,2,"Inductor missing node")),val=parseNumberWithUnits(requireToken(tokens,3,"Inductor missing value"));ckt.L.push({name,n1:n12,n2:n22,L:val,iPrev:0})}else if(typeChar==="v"){let n12=ckt.nodes.getOrCreate(requireToken(tokens,1,"Voltage source missing node")),n22=ckt.nodes.getOrCreate(requireToken(tokens,2,"Voltage source missing node")),spec={dc:0,acMag:0,acPhaseDeg:0,waveform:null,index:-1},i2=3;for(i2<tokens.length&&!/^[a-zA-Z]/.test(tokens[i2])&&(spec.dc=parseNumberWithUnits(tokens[i2]),i2++);i2<tokens.length;){let key=tokens[i2].toLowerCase();if(key==="dc"){let valueToken=requireToken(tokens,i2+1,"DC value missing");spec.dc=parseNumberWithUnits(valueToken),i2+=2}else if(key==="ac"){let magToken=requireToken(tokens,i2+1,"AC magnitude missing");spec.acMag=parseNumberWithUnits(magToken);let phaseToken=tokens[i2+2];phaseToken!=null&&/^[+-]?\d/.test(phaseToken)?(spec.acPhaseDeg=parseNumberWithUnits(phaseToken),i2+=3):i2+=2}else if(key.startsWith("pulse")){let argToken=key.includes("(")?key:requireToken(tokens,i2+1,"PULSE() missing arguments");if(!argToken||!/\(.*\)/.test(argToken))throw new Error("Malformed PULSE() specification");let p4=parsePulseArgs(argToken);spec.waveform=t5=>pulseValue(p4,t5),i2+=key.includes("(")?1:2}else if(key.startsWith("pwl")){let argToken=key.includes("(")?key:requireToken(tokens,i2+1,"PWL() missing arguments");if(!argToken||!/\(.*\)/.test(argToken))throw new Error("Malformed PWL() specification");let pairs3=parsePwlArgs(argToken);spec.waveform=t5=>pwlValue(pairs3,t5),i2+=key.includes("(")?1:2}else/^\(.*\)$/.test(key),i2++}ckt.V.push({name,n1:n12,n2:n22,dc:spec.dc,acMag:spec.acMag,acPhaseDeg:spec.acPhaseDeg,waveform:spec.waveform,index:spec.index??-1})}else if(typeChar==="s"){let n12=ckt.nodes.getOrCreate(requireToken(tokens,1,"Switch missing node")),n22=ckt.nodes.getOrCreate(requireToken(tokens,2,"Switch missing node")),ncPos=ckt.nodes.getOrCreate(requireToken(tokens,3,"Switch missing control node")),ncNeg=ckt.nodes.getOrCreate(requireToken(tokens,4,"Switch missing control node")),modelName=requireToken(tokens,5,"Switch missing model");ckt.S.push({name,n1:n12,n2:n22,ncPos,ncNeg,modelName:modelName.toLowerCase(),model:null,isOn:!1})}else if(typeChar==="d")if(tokens.length===4){let nPlus=ckt.nodes.getOrCreate(requireToken(tokens,1,"Diode missing node")),nMinus=ckt.nodes.getOrCreate(requireToken(tokens,2,"Diode missing node")),modelName=requireToken(tokens,3,"Diode missing model");ckt.D.push({name,nPlus,nMinus,modelName:modelName.toLowerCase(),model:null,vdPrev:0})}else ckt.skipped.push(line2);else ckt.skipped.push(line2)}catch(err){throw err instanceof Error?new Error(`Parse error on line: "${line2}"
|
|
617
|
-
${err.message}`):err}}let nNodes=ckt.nodes.count()-1;for(let i2=0;i2<ckt.V.length;i2++){let vs3=ckt.V[i2];vs3&&(vs3.index=nNodes+i2)}for(let sw of ckt.S){let model=vswitchModels.get(sw.modelName);if(!model)throw new Error(`Unknown .model ${sw.modelName} referenced by switch ${sw.name}`);sw.model=model,sw.isOn=!1}for(let d3 of ckt.D){let model=diodeModels.get(d3.modelName);if(!model)throw new Error(`Unknown .model ${d3.modelName} referenced by diode ${d3.name}`);d3.model=model}return ckt}var Complex=class _Complex{constructor(re4=0,im2=0){__publicField(this,"re");__publicField(this,"im");this.re=re4,this.im=im2}static from(re4,im2=0){return new _Complex(re4,im2)}static fromPolar(mag,deg=0){let ph2=deg*Math.PI/180;return new _Complex(mag*Math.cos(ph2),mag*Math.sin(ph2))}clone(){return new _Complex(this.re,this.im)}add(b3){return new _Complex(this.re+b3.re,this.im+b3.im)}sub(b3){return new _Complex(this.re-b3.re,this.im-b3.im)}mul(b3){return new _Complex(this.re*b3.re-this.im*b3.im,this.re*b3.im+this.im*b3.re)}div(b3){let d3=b3.re*b3.re+b3.im*b3.im;if(d3<EPS5)throw new Error("Complex divide by ~0");return new _Complex((this.re*b3.re+this.im*b3.im)/d3,(this.im*b3.re-this.re*b3.im)/d3)}inv(){let d3=this.re*this.re+this.im*this.im;if(d3<EPS5)throw new Error("Complex invert by ~0");return new _Complex(this.re/d3,-this.im/d3)}abs(){return Math.hypot(this.re,this.im)}phaseDeg(){return Math.atan2(this.im,this.re)*180/Math.PI}};function solveComplex(A4,b3){let n3=A4.length;for(let i2=0;i2<n3;i2++){let row=A4[i2],bi3=b3[i2];if(!row||!bi3)throw new Error("Matrix dimensions mismatch");let copy=row.map(z5=>z5.clone());copy.push(bi3.clone()),A4[i2]=copy}for(let k4=0;k4<n3;k4++){let imax=k4,pivotRow=A4[k4];if(!pivotRow)throw new Error("Matrix row missing");let vmax=pivotRow[k4]?.abs()??0;for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let v5=row[k4]?.abs()??0;v5>vmax&&(vmax=v5,imax=i2)}if(vmax<EPS5)throw new Error("Singular matrix (complex)");if(imax!==k4){let tmp=A4[k4];A4[k4]=A4[imax],A4[imax]=tmp}let pivotRowUpdated=A4[k4];if(!pivotRowUpdated)throw new Error("Pivot row missing");let pivot=pivotRowUpdated[k4];if(!pivot)throw new Error("Zero pivot encountered");for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let entry=row[k4];if(!entry)continue;let f2=entry.div(pivot);if(!(f2.abs()<EPS5))for(let j4=k4;j4<=n3;j4++){let target=row[j4],source=pivotRowUpdated[j4];!target||!source||(row[j4]=target.sub(f2.mul(source)))}}}let x5=new Array(n3);for(let i2=n3-1;i2>=0;i2--){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let s2=row[n3];if(!s2)throw new Error("Augmented column missing");for(let j4=i2+1;j4<n3;j4++){let coeff=row[j4],sol=x5[j4];!coeff||!sol||(s2=s2.sub(coeff.mul(sol)))}let pivot=row[i2];if(!pivot)throw new Error("Zero pivot on back-substitution");x5[i2]=s2.div(pivot)}return x5}function logspace(f12,f2,pointsPerDecade){if(f12<=0||f2<=0)throw new Error(".ac frequencies must be > 0");f2<f12&&([f12,f2]=[f2,f12]);let decades=Math.log10(f2/f12),n3=Math.max(1,Math.ceil(decades*pointsPerDecade)),arr=[];for(let i2=0;i2<=n3;i2++)arr.push(f12*Math.pow(10,i2/pointsPerDecade));let last=arr[arr.length-1];return(last==null||last<f2*(1-EPS5))&&arr.push(f2),arr}function stampAdmittanceComplex(A4,nidx,n12,n22,Y6){let i12=nidx.matrixIndexOfNode(n12),i2=nidx.matrixIndexOfNode(n22);if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping");row1[i12]=row1[i12]?.add(Y6)??Y6}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping");row2[i2]=row2[i2]?.add(Y6)??Y6}if(i12>=0&&i2>=0){let row1=A4[i12],row2=A4[i2];if(!row1||!row2)throw new Error("Matrix row missing while stamping");row1[i2]=row1[i2]?.sub(Y6)??Complex.from(0,0).sub(Y6),row2[i12]=row2[i12]?.sub(Y6)??Complex.from(0,0).sub(Y6)}}function stampVoltageSourceComplex(A4,b3,nidx,source,voltage2){let i12=nidx.matrixIndexOfNode(source.n1),i2=nidx.matrixIndexOfNode(source.n2),j4=source.index,one=Complex.from(1,0),negOne=Complex.from(-1,0);if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping voltage source");row1[j4]=row1[j4]?.add(one)??one}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping voltage source");row2[j4]=row2[j4]?.sub(one)??negOne}let branchRow=A4[j4];if(!branchRow)throw new Error("Branch row missing while stamping voltage source");i12>=0&&(branchRow[i12]=branchRow[i12]?.add(one)??one),i2>=0&&(branchRow[i2]=branchRow[i2]?.sub(one)??negOne),b3[j4]=(b3[j4]??Complex.from(0,0)).add(voltage2)}function buildFrequencyArray(params){let{mode,N:N6,f1:f12,f2}=params;if(mode==="dec")return logspace(f12,f2,N6);let arr=[],npts=Math.max(2,N6),step=(f2-f12)/(npts-1);for(let i2=0;i2<npts;i2++)arr.push(f12+i2*step);return arr}function buildLinearSystemForAC(ckt,f2,Nvar){let A4=Array.from({length:Nvar},()=>Array.from({length:Nvar},()=>Complex.from(0,0))),b3=Array.from({length:Nvar},()=>Complex.from(0,0)),twoPi=2*Math.PI;for(let r4 of ckt.R){if(r4.R<=0)throw new Error(`R ${r4.name} must be > 0`);let Y6=Complex.from(1/r4.R,0);stampAdmittanceComplex(A4,ckt.nodes,r4.n1,r4.n2,Y6)}for(let c3 of ckt.C){let Y6=Complex.from(0,twoPi*f2*c3.C);stampAdmittanceComplex(A4,ckt.nodes,c3.n1,c3.n2,Y6)}for(let l3 of ckt.L){let denom=Complex.from(0,twoPi*f2*l3.L),Y6=denom.abs()<EPS5?Complex.from(0,0):Complex.from(1,0).div(denom);stampAdmittanceComplex(A4,ckt.nodes,l3.n1,l3.n2,Y6)}for(let vs3 of ckt.V){let Vph=Complex.fromPolar(vs3.acMag||0,vs3.acPhaseDeg||0);stampVoltageSourceComplex(A4,b3,ckt.nodes,vs3,Vph)}return{A:A4,b:b3}}function simulateAC(ckt){var _a360,_b2,_c2,_d2;if(!ckt.analyses.ac)return null;let{mode,N:N6,f1:f12,f2}=ckt.analyses.ac,nNodeVars=ckt.nodes.count()-1,nVsrc=ckt.V.length,Nvar=nNodeVars+nVsrc,freqs=buildFrequencyArray({mode,N:N6,f1:f12,f2}),nodeVoltages={};ckt.nodes.rev.forEach((name,id)=>{id!==0&&(nodeVoltages[name]=[])});let elementCurrents={},twoPi=2*Math.PI;for(let f3 of freqs){let{A:A4,b:b3}=buildLinearSystemForAC(ckt,f3,Nvar),x5=solveComplex(A4,b3);for(let id=1;id<ckt.nodes.count();id++){let idx=id-1,nodeName2=ckt.nodes.rev[id];if(!nodeName2)continue;let series=nodeVoltages[nodeName2];series&&series.push(x5[idx]??Complex.from(0,0))}for(let r4 of ckt.R){let v12=r4.n1===0?Complex.from(0,0):x5[r4.n1-1]??Complex.from(0,0),v22=r4.n2===0?Complex.from(0,0):x5[r4.n2-1]??Complex.from(0,0),i2=Complex.from(1/r4.R,0).mul(v12.sub(v22));(elementCurrents[_a360=r4.name]||(elementCurrents[_a360]=[])).push(i2)}for(let c3 of ckt.C){let v12=c3.n1===0?Complex.from(0,0):x5[c3.n1-1]??Complex.from(0,0),v22=c3.n2===0?Complex.from(0,0):x5[c3.n2-1]??Complex.from(0,0),i2=Complex.from(0,twoPi*f3*c3.C).mul(v12.sub(v22));(elementCurrents[_b2=c3.name]||(elementCurrents[_b2]=[])).push(i2)}for(let l3 of ckt.L){let v12=l3.n1===0?Complex.from(0,0):x5[l3.n1-1]??Complex.from(0,0),v22=l3.n2===0?Complex.from(0,0):x5[l3.n2-1]??Complex.from(0,0),denom=Complex.from(0,twoPi*f3*l3.L),i2=(denom.abs()<EPS5?Complex.from(0,0):Complex.from(1,0).div(denom)).mul(v12.sub(v22));(elementCurrents[_c2=l3.name]||(elementCurrents[_c2]=[])).push(i2)}for(let vs3 of ckt.V){let i2=x5[vs3.index]??Complex.from(0,0);(elementCurrents[_d2=vs3.name]||(elementCurrents[_d2]=[])).push(i2)}}return{freqs,nodeVoltages,elementCurrents}}var VT_300K=.02585;function solveReal(A4,b3){let n3=A4.length;for(let i2=0;i2<n3;i2++){let row=A4[i2],bi3=b3[i2];if(!row||bi3==null)throw new Error("Matrix dimensions mismatch");let copy=row.slice();copy.push(bi3),A4[i2]=copy}for(let k4=0;k4<n3;k4++){let imax=k4,pivotRow=A4[k4];if(!pivotRow)throw new Error("Matrix row missing");let vmax=Math.abs(pivotRow[k4]??0);for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let v5=Math.abs(row[k4]??0);v5>vmax&&(vmax=v5,imax=i2)}if(vmax<EPS5)throw new Error("Singular matrix (real)");if(imax!==k4){let tmp=A4[k4];A4[k4]=A4[imax],A4[imax]=tmp}let pivotRowUpdated=A4[k4];if(!pivotRowUpdated)throw new Error("Pivot row missing");let pivot=pivotRowUpdated[k4];if(pivot==null)throw new Error("Zero pivot encountered");for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let entry=row[k4];if(entry==null)continue;let f2=entry/pivot;if(!(Math.abs(f2)<EPS5))for(let j4=k4;j4<=n3;j4++){let target=row[j4],source=pivotRowUpdated[j4];target==null||source==null||(row[j4]=target-f2*source)}}}let x5=new Array(n3).fill(0);for(let i2=n3-1;i2>=0;i2--){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let s2=row[n3];if(s2==null)throw new Error("Augmented column missing");for(let j4=i2+1;j4<n3;j4++){let coeff=row[j4],sol=x5[j4];coeff==null||sol==null||(s2-=coeff*sol)}let pivot=row[i2];if(pivot==null)throw new Error("Zero pivot on back-substitution");x5[i2]=s2/pivot}return x5}function stampAdmittanceReal(A4,nidx,n12,n22,Y6){let i12=nidx.matrixIndexOfNode(n12),i2=nidx.matrixIndexOfNode(n22);if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping");row1[i12]=(row1[i12]??0)+Y6}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping");row2[i2]=(row2[i2]??0)+Y6}if(i12>=0&&i2>=0){let row1=A4[i12],row2=A4[i2];if(!row1||!row2)throw new Error("Matrix row missing while stamping");row1[i2]=(row1[i2]??0)-Y6,row2[i12]=(row2[i12]??0)-Y6}}function stampCurrentReal(b3,nidx,nPlus,nMinus,current2){let iPlus=nidx.matrixIndexOfNode(nPlus),iMinus=nidx.matrixIndexOfNode(nMinus);iPlus>=0&&(b3[iPlus]=(b3[iPlus]??0)-current2),iMinus>=0&&(b3[iMinus]=(b3[iMinus]??0)+current2)}function stampVoltageSourceReal(A4,b3,nidx,source,voltage2){let i12=nidx.matrixIndexOfNode(source.n1),i2=nidx.matrixIndexOfNode(source.n2),j4=source.index;if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping voltage source");row1[j4]=(row1[j4]??0)+1}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping voltage source");row2[j4]=(row2[j4]??0)-1}let branchRow=A4[j4];if(!branchRow)throw new Error("Branch row missing while stamping voltage source");i12>=0&&(branchRow[i12]=(branchRow[i12]??0)+1),i2>=0&&(branchRow[i2]=(branchRow[i2]??0)-1),b3[j4]=(b3[j4]??0)+voltage2}function computeEffectiveTimeStep(dtRequested,tstop){let dtEff=dtRequested>EPS5?dtRequested:Math.max(tstop/1e3,EPS5),steps=Math.max(1,Math.ceil(tstop/Math.max(dtEff,EPS5)));return{dt:steps>0?tstop/steps:tstop,steps}}function stampAllElementsAtTime(A4,b3,ckt,t5,dt4,x5,iter){for(let r4 of ckt.R){let G5=1/r4.R;stampAdmittanceReal(A4,ckt.nodes,r4.n1,r4.n2,G5)}for(let c3 of ckt.C){let Gc2=c3.C/Math.max(dt4,EPS5);stampAdmittanceReal(A4,ckt.nodes,c3.n1,c3.n2,Gc2);let Ieq=-Gc2*c3.vPrev;stampCurrentReal(b3,ckt.nodes,c3.n1,c3.n2,Ieq)}for(let l3 of ckt.L){let Gl2=Math.max(dt4,EPS5)/l3.L;stampAdmittanceReal(A4,ckt.nodes,l3.n1,l3.n2,Gl2),stampCurrentReal(b3,ckt.nodes,l3.n1,l3.n2,l3.iPrev)}for(let sw of ckt.S){let model=sw.model;if(!model)continue;let Rvalue=sw.isOn?model.Ron:model.Roff,G5=1/Math.max(Math.abs(Rvalue),EPS5);stampAdmittanceReal(A4,ckt.nodes,sw.n1,sw.n2,G5)}for(let vs3 of ckt.V){let Vt4=vs3.waveform?vs3.waveform(t5):vs3.dc||0;stampVoltageSourceReal(A4,b3,ckt.nodes,vs3,Vt4)}for(let d3 of ckt.D){let model=d3.model;if(!model)continue;let{nPlus,nMinus}=d3,vp_idx=ckt.nodes.matrixIndexOfNode(nPlus),vn_idx=ckt.nodes.matrixIndexOfNode(nMinus),v_plus_prev_iter=nPlus===0?0:x5[vp_idx]??0,v_minus_prev_iter=nMinus===0?0:x5[vn_idx]??0,vd_prev_iter=v_plus_prev_iter-v_minus_prev_iter,vd2=iter===0?d3.vdPrev:vd_prev_iter,v_thermal=model.N*VT_300K,vd_limited=vd2;vd2>.8&&(vd_limited=.8),vd2<-1&&(vd_limited=-1);let exp_val=Math.exp(vd_limited/v_thermal),id=model.Is*(exp_val-1),gd2=Math.max(model.Is/v_thermal*exp_val,1e-12),ieq=id-gd2*vd_limited;stampAdmittanceReal(A4,ckt.nodes,nPlus,nMinus,gd2),stampCurrentReal(b3,ckt.nodes,nPlus,nMinus,ieq)}}function updateSwitchStatesFromSolution(ckt,x5){let switched=!1;for(let sw of ckt.S){let model=sw.model;if(!model)continue;let vp2=sw.ncPos===0?0:x5[sw.ncPos-1]??0,vn3=sw.ncNeg===0?0:x5[sw.ncNeg-1]??0,vctrl=vp2-vn3,nextState=sw.isOn;sw.isOn?vctrl<model.Voff&&(nextState=!1):vctrl>model.Von&&(nextState=!0),nextState!==sw.isOn&&(sw.isOn=nextState,switched=!0)}return switched}function simulateTRAN(ckt){var _a360,_b2,_c2,_d2,_e4,_f2;if(!ckt.analyses.tran)return null;let{dt:dtRequested,tstop}=ckt.analyses.tran,{dt:dt4,steps}=computeEffectiveTimeStep(dtRequested,tstop),nNodeVars=ckt.nodes.count()-1,nVsrc=ckt.V.length,Nvar=nNodeVars+nVsrc,times=[],nodeVoltages={};ckt.nodes.rev.forEach((name,id)=>{id!==0&&(nodeVoltages[name]=[])});let elementCurrents={},t5=0;for(let step=0;step<=steps;step++,t5=step*dt4){times.push(t5);let x5=new Array(Nvar).fill(0);for(let iter=0;iter<20;iter++){let A4=Array.from({length:Nvar},()=>new Array(Nvar).fill(0)),b3=new Array(Nvar).fill(0);if(stampAllElementsAtTime(A4,b3,ckt,t5,dt4,x5,iter),x5=solveReal(A4,b3),!updateSwitchStatesFromSolution(ckt,x5)||iter===19)break}for(let id=1;id<ckt.nodes.count();id++){let idx=id-1,nodeName2=ckt.nodes.rev[id];if(!nodeName2)continue;let series=nodeVoltages[nodeName2];series&&series.push(x5[idx]??0)}for(let r4 of ckt.R){let v12=r4.n1===0?0:x5[r4.n1-1]??0,v22=r4.n2===0?0:x5[r4.n2-1]??0,i2=(v12-v22)/r4.R;(elementCurrents[_a360=r4.name]||(elementCurrents[_a360]=[])).push(i2)}for(let c3 of ckt.C){let v12=c3.n1===0?0:x5[c3.n1-1]??0,v22=c3.n2===0?0:x5[c3.n2-1]??0,i2=c3.C*(v12-v22-c3.vPrev)/Math.max(dt4,EPS5);(elementCurrents[_b2=c3.name]||(elementCurrents[_b2]=[])).push(i2)}for(let l3 of ckt.L){let v12=l3.n1===0?0:x5[l3.n1-1]??0,v22=l3.n2===0?0:x5[l3.n2-1]??0,i2=Math.max(dt4,EPS5)/l3.L*(v12-v22)+l3.iPrev;(elementCurrents[_c2=l3.name]||(elementCurrents[_c2]=[])).push(i2)}for(let vs3 of ckt.V){let i2=x5[vs3.index]??0;(elementCurrents[_d2=vs3.name]||(elementCurrents[_d2]=[])).push(i2)}for(let sw of ckt.S){let model=sw.model;if(!model)continue;let v12=sw.n1===0?0:x5[sw.n1-1]??0,v22=sw.n2===0?0:x5[sw.n2-1]??0,Rvalue=sw.isOn?model.Ron:model.Roff,Rclamped=Math.max(Math.abs(Rvalue),EPS5),i2=(v12-v22)/Rclamped;(elementCurrents[_e4=sw.name]||(elementCurrents[_e4]=[])).push(i2)}for(let d3 of ckt.D){if(!d3.model)continue;let{nPlus,nMinus,model}=d3,v12=nPlus===0?0:x5[nPlus-1]??0,v22=nMinus===0?0:x5[nMinus-1]??0,vd2=v12-v22,v_thermal=model.N*VT_300K,exp_val=Math.exp(vd2/v_thermal),id=model.Is*(exp_val-1);(elementCurrents[_f2=d3.name]||(elementCurrents[_f2]=[])).push(id)}for(let c3 of ckt.C){let v12=c3.n1===0?0:x5[c3.n1-1]??0,v22=c3.n2===0?0:x5[c3.n2-1]??0;c3.vPrev=v12-v22}for(let l3 of ckt.L){let v12=l3.n1===0?0:x5[l3.n1-1]??0,v22=l3.n2===0?0:x5[l3.n2-1]??0,Gl2=Math.max(dt4,EPS5)/l3.L;l3.iPrev=Gl2*(v12-v22)+l3.iPrev}for(let d3 of ckt.D){let v12=d3.nPlus===0?0:x5[d3.nPlus-1]??0,v22=d3.nMinus===0?0:x5[d3.nMinus-1]??0;d3.vdPrev=v12-v22}}if(ckt.probes.tran.length>0){let probedVoltages={},upperProbes=ckt.probes.tran.map(p4=>p4.toUpperCase());for(let nodeName2 in nodeVoltages)upperProbes.includes(nodeName2.toUpperCase())&&(probedVoltages[nodeName2]=nodeVoltages[nodeName2]);return{times,nodeVoltages:probedVoltages,elementCurrents}}return{times,nodeVoltages,elementCurrents}}function simulate(netlistText){let circuit=parseNetlist(netlistText),ac2=simulateAC(circuit),tran=simulateTRAN(circuit);return{circuit,ac:ac2,tran}}function spiceyTranToVGraphs(tranResult,ckt,simulation_experiment_id){if(!tranResult||!ckt.analyses.tran)return[];let{dt:dt4,tstop}=ckt.analyses.tran,{times,nodeVoltages}=tranResult,graphs=[];for(let nodeName2 in nodeVoltages){let voltage_levels=nodeVoltages[nodeName2];graphs.push({type:"simulation_transient_voltage_graph",simulation_transient_voltage_graph_id:`stvg_${simulation_experiment_id}_${nodeName2}`,simulation_experiment_id,timestamps_ms:times.map(t5=>t5*1e3),voltage_levels,time_per_step:dt4*1e3,start_time_ms:0,end_time_ms:tstop*1e3,name:`${nodeName2}`})}return graphs}init_dist6();var SI_PREFIXES=[{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"}];function formatSiUnit(value){if(value==null)return"";if(value===0)return"0";let absValue=Math.abs(value),prefix=SI_PREFIXES.find(p4=>{let scaled2=absValue/p4.value;return scaled2>=1&&scaled2<1e3})||SI_PREFIXES[SI_PREFIXES.length-1],formatted=(value/prefix.value).toPrecision(3);return formatted.includes(".")&&!/\.0+$/.test(formatted)&&(formatted=formatted.replace(/0+$/,"")),formatted=formatted.replace(/\.0+$/,""),`${formatted}${prefix.symbol}`}init_dist6();init_dist();init_dist4();init_dist6();init_dist4();init_dist6();init_dist6();init_dist();init_dist6();init_dist6();init_src();init_dist6();init_dist4();init_dist6();init_dist4();init_dist6();init_dist6();init_dist4();init_dist6();function distance7(x12,y12,x22,y22){return Math.sqrt((x22-x12)**2+(y22-y12)**2)}var addStartAndEndPortIdsIfMissing=soup=>{let pcbPorts=soup.filter(item=>item.type==="pcb_port"),pcbSmtPads=soup.filter(item=>item.type==="pcb_smtpad"),pcbTraces=soup.filter(item=>item.type==="pcb_trace");function findPortIdOverlappingPoint(point6,options={}){let traceWidth=options.traceWidth||0,directPort=pcbPorts.find(port=>distance7(port.x,port.y,point6.x,point6.y)<.01);if(directPort)return directPort.pcb_port_id;if(options.isFirstOrLastPoint){let smtPad=pcbSmtPads.find(pad2=>{if(pad2.shape==="rect")return Math.abs(point6.x-pad2.x)<pad2.width/2+traceWidth/2&&Math.abs(point6.y-pad2.y)<pad2.height/2+traceWidth/2;if(pad2.shape==="circle")return distance7(point6.x,point6.y,pad2.x,pad2.y)<pad2.radius});if(smtPad)return smtPad.pcb_port_id??null}return null}for(let trace of pcbTraces)for(let index=0;index<trace.route.length;index++){let segment2=trace.route[index],isFirstOrLastPoint=index===0||index===trace.route.length-1;if(segment2.route_type==="wire"){if(!segment2.start_pcb_port_id&&index===0){let startPortId=findPortIdOverlappingPoint(segment2,{isFirstOrLastPoint,traceWidth:segment2.width});startPortId&&(segment2.start_pcb_port_id=startPortId)}if(!segment2.end_pcb_port_id&&index===trace.route.length-1){let endPortId=findPortIdOverlappingPoint(segment2,{isFirstOrLastPoint,traceWidth:segment2.width});endPortId&&(segment2.end_pcb_port_id=endPortId)}}}};function checkEachPcbPortConnectedToPcbTraces(circuitJson){addStartAndEndPortIdsIfMissing(circuitJson);let sourceTraces=circuitJson.filter(item=>item.type==="source_trace"),pcbPorts=circuitJson.filter(item=>item.type==="pcb_port"),errors=[],connectivityMap=getFullConnectivityMapFromCircuitJson(circuitJson),sourcePortToPcbPort=new Map;for(let pcbPort of pcbPorts)sourcePortToPcbPort.set(pcbPort.source_port_id,pcbPort);for(let sourceTrace of sourceTraces){let connectedSourcePortIds=sourceTrace.connected_source_port_ids;if(connectedSourcePortIds.length<2)continue;let pcbPortsInTrace=[],missingPcbPorts=[];for(let sourcePortId of connectedSourcePortIds){let pcbPort=sourcePortToPcbPort.get(sourcePortId);pcbPort?pcbPortsInTrace.push(pcbPort):missingPcbPorts.push(sourcePortId)}if(pcbPortsInTrace.length<2)continue;let firstPcbPort=pcbPortsInTrace[0],referenceNetId=connectivityMap.getNetConnectedToId(firstPcbPort.pcb_port_id);connectivityMap.getIdsConnectedToNet(referenceNetId).filter(id=>circuitJson.some(element=>element.type==="pcb_trace"&&("pcb_trace_id"in element&&element.pcb_trace_id===id||"route_id"in element&&element.route_id===id))).length===0&&new Set(pcbPortsInTrace.map(p4=>p4.pcb_component_id)).size>1&&errors.push({type:"pcb_port_not_connected_error",message:`pcb_port_not_connected_error: Pcb ports [${pcbPortsInTrace.map(p4=>p4.pcb_port_id).join(", ")}] are not connected together through the same net.`,error_type:"pcb_port_not_connected_error",pcb_port_ids:pcbPortsInTrace.map(p4=>p4.pcb_port_id),pcb_component_ids:pcbPortsInTrace.map(p4=>p4.pcb_component_id).filter(id=>id!==void 0),pcb_port_not_connected_error_id:`pcb_port_not_connected_error_trace_${sourceTrace.source_trace_id}`})}return errors}var SpatialObjectIndex=class{constructor({objects,getBounds:getBounds3,getId,CELL_SIZE}){__publicField(this,"buckets");__publicField(this,"objectsById");__publicField(this,"getBounds");__publicField(this,"getId");__publicField(this,"CELL_SIZE",.4);__publicField(this,"_idCounter",0);this.buckets=new Map,this.objectsById=new Map,this.getBounds=getBounds3,this.getId=getId??(()=>this._getNextId()),this.CELL_SIZE=CELL_SIZE??this.CELL_SIZE;for(let obj of objects)this.addObject(obj)}_getNextId(){return`${this._idCounter++}`}addObject(obj){let bounds=this.getBounds(obj),spatialIndexId=this.getId(obj),objWithId={...obj,spatialIndexId};this.objectsById.set(spatialIndexId,objWithId);let minBucketX=Math.floor(bounds.minX/this.CELL_SIZE),minBucketY=Math.floor(bounds.minY/this.CELL_SIZE),maxBucketX=Math.floor(bounds.maxX/this.CELL_SIZE),maxBucketY=Math.floor(bounds.maxY/this.CELL_SIZE);for(let bx2=minBucketX;bx2<=maxBucketX;bx2++)for(let by2=minBucketY;by2<=maxBucketY;by2++){let bucketKey=`${bx2}x${by2}`,bucket=this.buckets.get(bucketKey);bucket?bucket.push(objWithId):this.buckets.set(bucketKey,[objWithId])}}removeObject(id){let obj=this.objectsById.get(id);if(!obj)return!1;this.objectsById.delete(id);let bounds=this.getBounds(obj),minBucketX=Math.floor(bounds.minX/this.CELL_SIZE),minBucketY=Math.floor(bounds.minY/this.CELL_SIZE),maxBucketX=Math.floor(bounds.maxX/this.CELL_SIZE),maxBucketY=Math.floor(bounds.maxY/this.CELL_SIZE);for(let bx2=minBucketX;bx2<=maxBucketX;bx2++)for(let by2=minBucketY;by2<=maxBucketY;by2++){let bucketKey=`${bx2}x${by2}`,bucket=this.buckets.get(bucketKey);if(bucket){let index=bucket.findIndex(item=>item.spatialIndexId===id);index!==-1&&(bucket.splice(index,1),bucket.length===0&&this.buckets.delete(bucketKey))}}return!0}getBucketKey(x5,y5){return`${Math.floor(x5/this.CELL_SIZE)}x${Math.floor(y5/this.CELL_SIZE)}`}getObjectsInBounds(bounds,margin=0){let objects=[],addedIds=new Set,minBucketX=Math.floor((bounds.minX-margin)/this.CELL_SIZE),minBucketY=Math.floor((bounds.minY-margin)/this.CELL_SIZE),maxBucketX=Math.floor((bounds.maxX+margin)/this.CELL_SIZE),maxBucketY=Math.floor((bounds.maxY+margin)/this.CELL_SIZE);for(let bx2=minBucketX;bx2<=maxBucketX;bx2++)for(let by2=minBucketY;by2<=maxBucketY;by2++){let bucketKey=`${bx2}x${by2}`,bucket=this.buckets.get(bucketKey)||[];for(let obj of bucket){let id=obj.spatialIndexId;addedIds.has(id)||(addedIds.add(id),objects.push(obj))}}return objects}},getCollidableBounds=collidable=>collidable.type==="pcb_trace_segment"?{minX:Math.min(collidable.x1,collidable.x2),minY:Math.min(collidable.y1,collidable.y2),maxX:Math.max(collidable.x1,collidable.x2),maxY:Math.max(collidable.y1,collidable.y2)}:getBoundsOfPcbElements([collidable]),DEFAULT_TRACE_MARGIN=.1,DEFAULT_TRACE_THICKNESS=.15;var DEFAULT_SAME_NET_VIA_MARGIN=.2,DEFAULT_DIFFERENT_NET_VIA_MARGIN=.3,EPSILON=.005;function getPcbPortIdsConnectedToTrace(trace){let connectedPcbPorts=new Set;for(let segment2 of trace.route)segment2.route_type==="wire"&&(segment2.start_pcb_port_id&&connectedPcbPorts.add(segment2.start_pcb_port_id),segment2.end_pcb_port_id&&connectedPcbPorts.add(segment2.end_pcb_port_id));return Array.from(connectedPcbPorts)}function getPcbPortIdsConnectedToTraces(traces){let connectedPorts=new Set;for(let trace of traces)for(let portId of getPcbPortIdsConnectedToTrace(trace))connectedPorts.add(portId);return Array.from(connectedPorts)}var getClosestPointBetweenSegments=(segmentA,segmentB)=>{let a12={x:segmentA.x1,y:segmentA.y1},a2={x:segmentA.x2,y:segmentA.y2},b12={x:segmentB.x1,y:segmentB.y1},b22={x:segmentB.x2,y:segmentB.y2},va3={x:a2.x-a12.x,y:a2.y-a12.y},vb2={x:b22.x-b12.x,y:b22.y-b12.y},lenSqrA=va3.x*va3.x+va3.y*va3.y,lenSqrB=vb2.x*vb2.x+vb2.y*vb2.y;if(lenSqrA===0||lenSqrB===0){if(lenSqrA===0&&lenSqrB===0)return{x:(a12.x+b12.x)/2,y:(a12.y+b12.y)/2};if(lenSqrA===0){let t22=clamp4(((a12.x-b12.x)*vb2.x+(a12.y-b12.y)*vb2.y)/lenSqrB,0,1),closestOnB2={x:b12.x+t22*vb2.x,y:b12.y+t22*vb2.y};return{x:(a12.x+closestOnB2.x)/2,y:(a12.y+closestOnB2.y)/2}}let t5=clamp4(((b12.x-a12.x)*va3.x+(b12.y-a12.y)*va3.y)/lenSqrA,0,1),closestOnA2={x:a12.x+t5*va3.x,y:a12.y+t5*va3.y};return{x:(closestOnA2.x+b12.x)/2,y:(closestOnA2.y+b12.y)/2}}let w4={x:a12.x-b12.x,y:a12.y-b12.y},dotAA=va3.x*va3.x+va3.y*va3.y,dotAB=va3.x*vb2.x+va3.y*vb2.y,dotAW=va3.x*w4.x+va3.y*w4.y,dotBB=vb2.x*vb2.x+vb2.y*vb2.y,dotBW=vb2.x*w4.x+vb2.y*w4.y,denominator=dotAA*dotBB-dotAB*dotAB;if(denominator<1e-10)return closestPointsParallelSegments(a12,a2,b12,b22,va3,vb2,lenSqrA,lenSqrB);let tA=(dotAB*dotBW-dotBB*dotAW)/denominator,tB=(dotAA*dotBW-dotAB*dotAW)/denominator;tA=clamp4(tA,0,1),tB=clamp4(tB,0,1),tB=(tA*dotAB+dotBW)/dotBB,tB=clamp4(tB,0,1),tA=(tB*dotAB-dotAW)/dotAA,tA=clamp4(tA,0,1);let closestOnA={x:a12.x+tA*va3.x,y:a12.y+tA*va3.y},closestOnB={x:b12.x+tB*vb2.x,y:b12.y+tB*vb2.y},dx2=closestOnA.x-closestOnB.x,dy2=closestOnA.y-closestOnB.y,distance52=Math.sqrt(dx2*dx2+dy2*dy2);return{x:(closestOnA.x+closestOnB.x)/2,y:(closestOnA.y+closestOnB.y)/2}},closestPointsParallelSegments=(a12,a2,b12,b22,va3,vb2,lenSqrA,lenSqrB)=>{let tA=((b12.x-a12.x)*va3.x+(b12.y-a12.y)*va3.y)/lenSqrA;tA=clamp4(tA,0,1);let pointOnA1={x:a12.x+tA*va3.x,y:a12.y+tA*va3.y},tA2=((b22.x-a12.x)*va3.x+(b22.y-a12.y)*va3.y)/lenSqrA;tA2=clamp4(tA2,0,1);let pointOnA2={x:a12.x+tA2*va3.x,y:a12.y+tA2*va3.y},tB=((a12.x-b12.x)*vb2.x+(a12.y-b12.y)*vb2.y)/lenSqrB;tB=clamp4(tB,0,1);let pointOnB1={x:b12.x+tB*vb2.x,y:b12.y+tB*vb2.y},tB2=((a2.x-b12.x)*vb2.x+(a2.y-b12.y)*vb2.y)/lenSqrB;tB2=clamp4(tB2,0,1);let pointOnB2={x:b12.x+tB2*vb2.x,y:b12.y+tB2*vb2.y},closestPair=[{pointA:pointOnA1,pointB:b12,distance:Math.sqrt((pointOnA1.x-b12.x)**2+(pointOnA1.y-b12.y)**2)},{pointA:pointOnA2,pointB:b22,distance:Math.sqrt((pointOnA2.x-b22.x)**2+(pointOnA2.y-b22.y)**2)},{pointA:a12,pointB:pointOnB1,distance:Math.sqrt((a12.x-pointOnB1.x)**2+(a12.y-pointOnB1.y)**2)},{pointA:a2,pointB:pointOnB2,distance:Math.sqrt((a2.x-pointOnB2.x)**2+(a2.y-pointOnB2.y)**2)}].reduce((closest,current2)=>current2.distance<closest.distance?current2:closest);return{x:(closestPair.pointA.x+closestPair.pointB.x)/2,y:(closestPair.pointA.y+closestPair.pointB.y)/2}},clamp4=(value,min,max)=>Math.max(min,Math.min(max,value)),getRadiusOfCircuitJsonElement=obj=>{if(obj.type==="pcb_via"||obj.type==="pcb_plated_hole"&&obj.shape==="circle")return obj.outer_diameter/2;if(obj.type==="pcb_hole"&&obj.hole_shape==="circle")return obj.hole_diameter/2;if(obj.type==="pcb_smtpad"&&obj.shape==="circle")return obj.radius;throw new Error(`Could not determine radius of element: ${JSON.stringify(obj)}`)},getClosestPointBetweenSegmentAndBounds=(segment2,bounds)=>{let p12={x:segment2.x1,y:segment2.y1},p22={x:segment2.x2,y:segment2.y2},minX=bounds.minX,minY=bounds.minY,maxX=bounds.maxX,maxY=bounds.maxY;if(p12.x===p22.x&&p12.y===p22.y){let closestX=Math.max(minX,Math.min(maxX,p12.x)),closestY=Math.max(minY,Math.min(maxY,p12.y));return closestX===p12.x&&closestY===p12.y?{x:p12.x,y:p12.y}:{x:closestX,y:closestY}}let dx2=p22.x-p12.x,dy2=p22.y-p12.y,tMinX=dx2!==0?(minX-p12.x)/dx2:Number.NEGATIVE_INFINITY,tMaxX=dx2!==0?(maxX-p12.x)/dx2:Number.POSITIVE_INFINITY,tMinY=dy2!==0?(minY-p12.y)/dy2:Number.NEGATIVE_INFINITY,tMaxY=dy2!==0?(maxY-p12.y)/dy2:Number.POSITIVE_INFINITY,tEnter=Math.max(Math.min(tMinX,tMaxX),Math.min(tMinY,tMaxY)),tExit=Math.min(Math.max(tMinX,tMaxX),Math.max(tMinY,tMaxY));if(tEnter<=tExit&&tExit>=0&&tEnter<=1){let t5=Math.max(0,Math.min(1,tEnter));return{x:p12.x+t5*dx2,y:p12.y+t5*dy2}}let closestToP1={x:Math.max(minX,Math.min(maxX,p12.x)),y:Math.max(minY,Math.min(maxY,p12.y))},closestToP2={x:Math.max(minX,Math.min(maxX,p22.x)),y:Math.max(minY,Math.min(maxY,p22.y))},distToP1Squared=(closestToP1.x-p12.x)**2+(closestToP1.y-p12.y)**2,distToP2Squared=(closestToP2.x-p22.x)**2+(closestToP2.y-p22.y)**2,edges=[{start:{x:minX,y:minY},end:{x:maxX,y:minY}},{start:{x:maxX,y:minY},end:{x:maxX,y:maxY}},{start:{x:maxX,y:maxY},end:{x:minX,y:maxY}},{start:{x:minX,y:maxY},end:{x:minX,y:minY}}],minDistance=Math.min(distToP1Squared,distToP2Squared),closestPoint=distToP1Squared<=distToP2Squared?closestToP1:closestToP2,clamp22=(value,min,max)=>Math.max(min,Math.min(max,value));for(let edge of edges){let va3={x:p22.x-p12.x,y:p22.y-p12.y},vb2={x:edge.end.x-edge.start.x,y:edge.end.y-edge.start.y},w4={x:p12.x-edge.start.x,y:p12.y-edge.start.y},dotAA=va3.x*va3.x+va3.y*va3.y,dotAB=va3.x*vb2.x+va3.y*vb2.y,dotAW=va3.x*w4.x+va3.y*w4.y,dotBB=vb2.x*vb2.x+vb2.y*vb2.y,dotBW=vb2.x*w4.x+vb2.y*w4.y,denominator=dotAA*dotBB-dotAB*dotAB;if(Math.abs(denominator)<1e-10)continue;let tA=(dotAB*dotBW-dotBB*dotAW)/denominator,tB=(dotAA*dotBW-dotAB*dotAW)/denominator;tA=clamp22(tA,0,1),tB=clamp22(tB,0,1);let closestOnSegment={x:p12.x+tA*va3.x,y:p12.y+tA*va3.y},closestOnEdge={x:edge.start.x+tB*vb2.x,y:edge.start.y+tB*vb2.y},dx22=closestOnSegment.x-closestOnEdge.x,dy22=closestOnSegment.y-closestOnEdge.y,distSquared=dx22*dx22+dy22*dy22;distSquared<minDistance&&(minDistance=distSquared,closestPoint={x:(closestOnSegment.x+closestOnEdge.x)/2,y:(closestOnSegment.y+closestOnEdge.y)/2})}return closestPoint};function getLayersOfPcbElement(obj){return obj.type==="pcb_trace_segment"?[obj.layer]:obj.type==="pcb_smtpad"?[obj.layer]:obj.type==="pcb_plated_hole"?Array.isArray(obj.layers)?obj.layers:[...all_layers]:obj.type==="pcb_hole"?[...all_layers]:obj.type==="pcb_via"?Array.isArray(obj.layers)?obj.layers:[...all_layers]:obj.type==="pcb_keepout"?Array.isArray(obj.layers)?obj.layers:[]:[]}function checkEachPcbTraceNonOverlapping(circuitJson,{connMap}={}){let errors=[];connMap??(connMap=getFullConnectivityMapFromCircuitJson(circuitJson));let pcbTraceSegments=cju_default(circuitJson).pcb_trace.list().flatMap(pcbTrace=>{let segments=[];for(let i2=0;i2<pcbTrace.route.length-1;i2++){let p12=pcbTrace.route[i2],p22=pcbTrace.route[i2+1];p12.route_type==="wire"&&p22.route_type==="wire"&&p12.layer===p22.layer&&segments.push({type:"pcb_trace_segment",pcb_trace_id:pcbTrace.pcb_trace_id,_pcbTrace:pcbTrace,thickness:"width"in p12?p12.width:"width"in p22?p22.width:DEFAULT_TRACE_THICKNESS,layer:p12.layer,x1:p12.x,y1:p12.y,x2:p22.x,y2:p22.y})}return segments}),pcbSmtPads=cju_default(circuitJson).pcb_smtpad.list(),pcbPlatedHoles=cju_default(circuitJson).pcb_plated_hole.list(),pcbHoles=cju_default(circuitJson).pcb_hole.list(),pcbVias=cju_default(circuitJson).pcb_via.list(),pcbKeepouts=cju_default(circuitJson).pcb_keepout.list(),allObjects=[...pcbTraceSegments,...pcbSmtPads,...pcbPlatedHoles,...pcbHoles,...pcbVias,...pcbKeepouts],spatialIndex=new SpatialObjectIndex({objects:allObjects,getBounds:getCollidableBounds}),getReadableName=id=>getReadableNameForElement(circuitJson,id),errorIds=new Set;for(let segmentA of pcbTraceSegments){let requiredMargin=DEFAULT_TRACE_MARGIN,bounds=getCollidableBounds(segmentA),nearbyObjects=spatialIndex.getObjectsInBounds(bounds,requiredMargin+segmentA.thickness/2);if(!(segmentA.x1===segmentA.x2&&segmentA.y1===segmentA.y2))for(let obj of nearbyObjects){if(!getLayersOfPcbElement(obj).includes(segmentA.layer))continue;if(obj.type==="pcb_trace_segment"){let segmentB=obj;if(segmentA.layer!==segmentB.layer||connMap.areIdsConnected(segmentA.pcb_trace_id,segmentB.pcb_trace_id))continue;let gap2=segmentToSegmentMinDistance({x:segmentA.x1,y:segmentA.y1},{x:segmentA.x2,y:segmentA.y2},{x:segmentB.x1,y:segmentB.y1},{x:segmentB.x2,y:segmentB.y2})-segmentA.thickness/2-segmentB.thickness/2;if(gap2>DEFAULT_TRACE_MARGIN-EPSILON)continue;let pcb_trace_error_id=`overlap_${segmentA.pcb_trace_id}_${segmentB.pcb_trace_id}`,pcb_trace_error_id_reverse=`overlap_${segmentB.pcb_trace_id}_${segmentA.pcb_trace_id}`;if(errorIds.has(pcb_trace_error_id)||errorIds.has(pcb_trace_error_id_reverse))continue;errorIds.add(pcb_trace_error_id),errors.push({type:"pcb_trace_error",error_type:"pcb_trace_error",message:`PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${getReadableName(segmentB.pcb_trace_id)} ${gap2<0?"(accidental contact)":`(gap: ${gap2.toFixed(3)}mm)`}`,pcb_trace_id:segmentA.pcb_trace_id,source_trace_id:"",pcb_trace_error_id,pcb_component_ids:[],center:getClosestPointBetweenSegments(segmentA,segmentB),pcb_port_ids:getPcbPortIdsConnectedToTraces([segmentA._pcbTrace,segmentB._pcbTrace])});continue}let primaryObjId=getPrimaryId(obj);if(connMap.areIdsConnected(segmentA.pcb_trace_id,"pcb_trace_id"in obj?obj.pcb_trace_id:primaryObjId))continue;if(obj.type==="pcb_via"||obj.type==="pcb_plated_hole"&&obj.shape==="circle"||obj.type==="pcb_hole"||obj.type==="pcb_smtpad"&&obj.shape==="circle"){let radius=getRadiusOfCircuitJsonElement(obj),gap2=segmentToCircleMinDistance({x:segmentA.x1,y:segmentA.y1},{x:segmentA.x2,y:segmentA.y2},{x:obj.x,y:obj.y,radius})-segmentA.thickness/2;if(gap2>DEFAULT_TRACE_MARGIN-EPSILON)continue;let pcb_trace_error_id=`overlap_${segmentA.pcb_trace_id}_${primaryObjId}`;if(errorIds.has(pcb_trace_error_id))continue;errorIds.add(pcb_trace_error_id),errors.push({type:"pcb_trace_error",error_type:"pcb_trace_error",message:`PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${obj.type} "${getReadableName(getPrimaryId(obj))}" ${gap2<0?"(accidental contact)":`(gap: ${gap2.toFixed(3)}mm)`}`,pcb_trace_id:segmentA.pcb_trace_id,center:getClosestPointBetweenSegmentAndBounds(segmentA,getCollidableBounds(obj)),source_trace_id:"",pcb_trace_error_id,pcb_component_ids:["pcb_component_id"in obj?obj.pcb_component_id:void 0].filter(Boolean),pcb_port_ids:[...getPcbPortIdsConnectedToTraces([segmentA._pcbTrace]),"pcb_port_id"in obj?obj.pcb_port_id:void 0].filter(Boolean)})}let gap=segmentToBoundsMinDistance({x:segmentA.x1,y:segmentA.y1},{x:segmentA.x2,y:segmentA.y2},getCollidableBounds(obj))-segmentA.thickness/2;if(gap+EPSILON<requiredMargin){let pcb_trace_error_id=`overlap_${segmentA.pcb_trace_id}_${primaryObjId}`;if(errorIds.has(pcb_trace_error_id))continue;errorIds.add(pcb_trace_error_id),errors.push({type:"pcb_trace_error",error_type:"pcb_trace_error",message:`PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${obj.type} "${getReadableName(getPrimaryId(obj))}" ${gap<0?"(accidental contact)":`(gap: ${gap.toFixed(3)}mm)`}`,pcb_trace_id:segmentA.pcb_trace_id,source_trace_id:"",pcb_trace_error_id,pcb_component_ids:["pcb_component_id"in obj?obj.pcb_component_id:void 0].filter(Boolean),center:getClosestPointBetweenSegmentAndBounds(segmentA,getCollidableBounds(obj)),pcb_port_ids:[...getPcbPortIdsConnectedToTraces([segmentA._pcbTrace]),"pcb_port_id"in obj?obj.pcb_port_id:void 0].filter(Boolean)})}}}return errors}function isPolygonCCW(poly){return poly.area()>=0}function rectanglePolygon({center:center2,size:size2,rotationDeg=0}){let cx2=center2.x,cy2=center2.y,hw2=size2.width/2,hh2=size2.height/2,corners=[new Point$3(cx2-hw2,cy2-hh2),new Point$3(cx2+hw2,cy2-hh2),new Point$3(cx2+hw2,cy2+hh2),new Point$3(cx2-hw2,cy2+hh2)],poly=new Polygon$1(corners);if(rotationDeg){let matrix2=rotateDEG2(rotationDeg,cx2,cy2),rotatedCorners=corners.map(pt4=>{let p4=applyToPoint2(matrix2,{x:pt4.x,y:pt4.y});return new Point$3(p4.x,p4.y)});poly=new Polygon$1(rotatedCorners)}return isPolygonCCW(poly)||poly.reverse(),poly}function boardToPolygon({board}){if(board.outline&&board.outline.length>0){let points=board.outline.map(p4=>new Point$3(p4.x,p4.y)),poly=new Polygon$1(points);return isPolygonCCW(poly)||poly.reverse(),poly}return board.center&&typeof board.width=="number"&&typeof board.height=="number"?rectanglePolygon({center:board.center,size:{width:board.width,height:board.height},rotationDeg:0}):null}function getComponentName({circuitJson,component}){if(component.source_component_id){let sourceComponent=circuitJson.find(el2=>el2.type==="source_component"&&el2.source_component_id===component.source_component_id);if(sourceComponent&&"name"in sourceComponent&&sourceComponent.name)return sourceComponent.name}return getReadableNameForElement(circuitJson,component.pcb_component_id)||"Unknown"}function computeOverlapDistance(compPoly,boardPoly,componentCenter,componentWidth,componentHeight,rotationDeg){let centerPoint=new Point$3(componentCenter.x,componentCenter.y);if(!boardPoly.contains(centerPoint)){let dist=boardPoly.distanceTo(centerPoint);return Array.isArray(dist)?dist[0]:Number(dist)||0}let hw2=componentWidth/2,hh2=componentHeight/2,corners=[{x:componentCenter.x-hw2,y:componentCenter.y-hh2},{x:componentCenter.x+hw2,y:componentCenter.y-hh2},{x:componentCenter.x+hw2,y:componentCenter.y+hh2},{x:componentCenter.x-hw2,y:componentCenter.y+hh2}],midpoints=[];for(let i2=0;i2<4;i2++){let next2=(i2+1)%4;midpoints.push({x:(corners[i2].x+corners[next2].x)/2,y:(corners[i2].y+corners[next2].y)/2})}let matrix2=rotateDEG2(rotationDeg,componentCenter.x,componentCenter.y),rotatePoint5=pt4=>{let p4=applyToPoint2(matrix2,pt4);return new Point$3(p4.x,p4.y)},rotatedPoints=corners.concat(midpoints).map(rotatePoint5),maxDistance=0;for(let pt4 of rotatedPoints)if(!boardPoly.contains(pt4)){let dist=boardPoly.distanceTo(pt4),d3=Array.isArray(dist)?dist[0]:Number(dist)||0;d3>maxDistance&&(maxDistance=d3)}if(maxDistance>0)return maxDistance;try{let intersection=BooleanOperations.intersect(compPoly,boardPoly),intersectionArea=0;intersection?Array.isArray(intersection)?intersectionArea=intersection.reduce((sum,p4)=>sum+(typeof p4.area=="function"?p4.area():0),0):typeof intersection.area=="function"?intersectionArea=intersection.area():intersectionArea=0:intersectionArea=0;let compArea=compPoly.area();if(intersectionArea>0&&intersectionArea<compArea){let overlapRatio=1-intersectionArea/compArea,compWidth=Math.abs(componentWidth),compHeight=Math.abs(componentHeight);return Math.min(compWidth,compHeight)*overlapRatio}else return .1}catch{return .1}}function checkPcbComponentsOutOfBoard(circuitJson){let board=circuitJson.find(el2=>el2.type==="pcb_board");if(!board)return[];let boardPoly=boardToPolygon({board});if(!boardPoly)return[];let components=circuitJson.filter(el2=>el2.type==="pcb_component");if(components.length===0)return[];let errors=[];for(let c3 of components){if(!c3.center||typeof c3.width!="number"||typeof c3.height!="number"||c3.width<=0||c3.height<=0)continue;let compPoly=rectanglePolygon({center:c3.center,size:{width:c3.width,height:c3.height},rotationDeg:c3.rotation||0});if(compPoly.area()===0||boardPoly.contains(compPoly))continue;let overlapDistance=computeOverlapDistance(compPoly,boardPoly,c3.center,c3.width,c3.height,c3.rotation||0),compName=getComponentName({circuitJson,component:c3}),overlapDistanceMm=Math.round(overlapDistance*100)/100;errors.push({type:"pcb_component_outside_board_error",error_type:"pcb_component_outside_board_error",pcb_component_outside_board_error_id:`pcb_component_outside_board_${c3.pcb_component_id}`,message:`Component ${compName} (${c3.pcb_component_id}) extends outside board boundaries by ${overlapDistanceMm}mm`,pcb_component_id:c3.pcb_component_id,pcb_board_id:board.pcb_board_id,component_center:c3.center,component_bounds:{min_x:compPoly.box.xmin,max_x:compPoly.box.xmax,min_y:compPoly.box.ymin,max_y:compPoly.box.ymax},subcircuit_id:c3.subcircuit_id,source_component_id:c3.source_component_id})}return errors}function distance22(a2,b3){return Math.hypot(a2.x-b3.x,a2.y-b3.y)}function checkSameNetViaSpacing(circuitJson,{connMap,minSpacing=DEFAULT_SAME_NET_VIA_MARGIN}={}){let vias=circuitJson.filter(el2=>el2.type==="pcb_via");if(vias.length<2)return[];connMap??(connMap=getFullConnectivityMapFromCircuitJson(circuitJson));let errors=[],reported=new Set;for(let i2=0;i2<vias.length;i2++)for(let j4=i2+1;j4<vias.length;j4++){let viaA=vias[i2],viaB=vias[j4];if(!connMap.areIdsConnected(viaA.pcb_via_id,viaB.pcb_via_id))continue;let gap=distance22(viaA,viaB)-viaA.outer_diameter/2-viaB.outer_diameter/2;if(gap+EPSILON>=minSpacing)continue;let pairId=[viaA.pcb_via_id,viaB.pcb_via_id].sort().join("_");reported.has(pairId)||(reported.add(pairId),errors.push({type:"pcb_via_clearance_error",pcb_error_id:`same_net_vias_close_${pairId}`,message:`Vias ${getReadableNameForElement(circuitJson,viaA.pcb_via_id)} and ${getReadableNameForElement(circuitJson,viaB.pcb_via_id)} are too close together (gap: ${gap.toFixed(3)}mm)`,error_type:"pcb_via_clearance_error",pcb_via_ids:[viaA.pcb_via_id,viaB.pcb_via_id],minimum_clearance:minSpacing,actual_clearance:gap,pcb_center:{x:(viaA.x+viaB.x)/2,y:(viaA.y+viaB.y)/2}}))}return errors}function distance32(a2,b3){return Math.hypot(a2.x-b3.x,a2.y-b3.y)}function checkDifferentNetViaSpacing(circuitJson,{connMap,minSpacing=DEFAULT_DIFFERENT_NET_VIA_MARGIN}={}){let vias=circuitJson.filter(el2=>el2.type==="pcb_via");if(vias.length<2)return[];connMap??(connMap=getFullConnectivityMapFromCircuitJson(circuitJson));let errors=[],reported=new Set;for(let i2=0;i2<vias.length;i2++)for(let j4=i2+1;j4<vias.length;j4++){let viaA=vias[i2],viaB=vias[j4];if(connMap.areIdsConnected(viaA.pcb_via_id,viaB.pcb_via_id))continue;let gap=distance32(viaA,viaB)-viaA.outer_diameter/2-viaB.outer_diameter/2;if(gap+EPSILON>=minSpacing)continue;let pairId=[viaA.pcb_via_id,viaB.pcb_via_id].sort().join("_");reported.has(pairId)||(reported.add(pairId),errors.push({type:"pcb_via_clearance_error",pcb_error_id:`different_net_vias_close_${pairId}`,message:`Vias ${getReadableNameForElement(circuitJson,viaA.pcb_via_id)} and ${getReadableNameForElement(circuitJson,viaB.pcb_via_id)} from different nets are too close together (gap: ${gap.toFixed(3)}mm)`,error_type:"pcb_via_clearance_error",pcb_via_ids:[viaA.pcb_via_id,viaB.pcb_via_id],minimum_clearance:minSpacing,actual_clearance:gap,pcb_center:{x:(viaA.x+viaB.x)/2,y:(viaA.y+viaB.y)/2}}))}return errors}var DEFAULT_BOARD_MARGIN=.2;function getBoardPolygonPoints(board){if(board.outline&&board.outline.length>0)return board.outline.map(p4=>({x:p4.x,y:p4.y}));if(board.center&&typeof board.width=="number"&&typeof board.height=="number"){let cx2=board.center.x,cy2=board.center.y,hw2=board.width/2,hh2=board.height/2;return[{x:cx2-hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2+hh2},{x:cx2-hw2,y:cy2+hh2}]}return null}function checkPcbTracesOutOfBoard(circuitJson,config={}){let errors=[],margin=config.margin??DEFAULT_BOARD_MARGIN,board=circuitJson.find(el2=>el2.type==="pcb_board");if(!board)return errors;let boardPoints=getBoardPolygonPoints(board);if(!boardPoints)return errors;let pcbTraces=cju_default(circuitJson).pcb_trace.list();for(let trace of pcbTraces)if(!(trace.route.length<2))for(let i2=0;i2<trace.route.length-1;i2++){let p12=trace.route[i2],p22=trace.route[i2+1];if(p12.route_type!=="wire"||p22.route_type!=="wire")continue;let traceWidth="width"in p12?p12.width:"width"in p22?p22.width:.1,segmentStart={x:p12.x,y:p12.y},segmentEnd={x:p22.x,y:p22.y},minDistance=1/0;for(let j4=0;j4<boardPoints.length;j4++){let edgeStart=boardPoints[j4],edgeEnd=boardPoints[(j4+1)%boardPoints.length],distance52=segmentToSegmentMinDistance(segmentStart,segmentEnd,edgeStart,edgeEnd);distance52<minDistance&&(minDistance=distance52)}let minimumDistance=traceWidth/2+margin;if(minDistance<minimumDistance){let error={type:"pcb_trace_error",error_type:"pcb_trace_error",pcb_trace_error_id:`trace_too_close_to_board_${trace.pcb_trace_id}_segment_${i2}`,message:`Trace too close to board edge (${minDistance.toFixed(3)}mm < ${minimumDistance.toFixed(3)}mm required, margin: ${margin}mm)`,pcb_trace_id:trace.pcb_trace_id,source_trace_id:trace.source_trace_id||"",center:{x:(segmentStart.x+segmentEnd.x)/2,y:(segmentStart.y+segmentEnd.y)/2},pcb_component_ids:[],pcb_port_ids:[]};errors.push(error)}}return errors}function doPcbElementsOverlap(elem1,elem2){let bounds1=getBoundsOfPcbElements([elem1]),bounds2=getBoundsOfPcbElements([elem2]);return doBoundsOverlap(bounds1,bounds2)}function checkPcbComponentOverlap(circuitJson){let errors=[],connMap=getFullConnectivityMapFromCircuitJson(circuitJson),smtPads=cju_default(circuitJson).pcb_smtpad.list(),platedHoles=cju_default(circuitJson).pcb_plated_hole.list(),holes=cju_default(circuitJson).pcb_hole.list(),componentMap=new Map;for(let pad2 of smtPads){let componentId=pad2.pcb_component_id||`standalone_pad_${getPrimaryId(pad2)}`;componentMap.has(componentId)||componentMap.set(componentId,{component_id:componentId,elements:[],bounds:{minX:0,minY:0,maxX:0,maxY:0}}),componentMap.get(componentId).elements.push(pad2)}for(let hole of platedHoles){let componentId=hole.pcb_component_id||`standalone_plated_hole_${getPrimaryId(hole)}`;componentMap.has(componentId)||componentMap.set(componentId,{component_id:componentId,elements:[],bounds:{minX:0,minY:0,maxX:0,maxY:0}}),componentMap.get(componentId).elements.push(hole)}for(let hole of holes){let componentId=`standalone_hole_${getPrimaryId(hole)}`;componentMap.set(componentId,{component_id:componentId,elements:[hole],bounds:{minX:0,minY:0,maxX:0,maxY:0}})}for(let[componentId,componentData]of componentMap)componentData.elements.length>0&&(componentData.bounds=getBoundsOfPcbElements(componentData.elements));let componentsWithElements=Array.from(componentMap.values());for(let i2=0;i2<componentsWithElements.length;i2++)for(let j4=i2+1;j4<componentsWithElements.length;j4++){let comp1=componentsWithElements[i2],comp2=componentsWithElements[j4];if(doBoundsOverlap(comp1.bounds,comp2.bounds))for(let elem1 of comp1.elements)for(let elem2 of comp2.elements){let id1=getPrimaryId(elem1),id2=getPrimaryId(elem2);if(!(elem1.type==="pcb_smtpad"&&elem2.type==="pcb_smtpad"&&connMap.areIdsConnected(id1,id2))&&doPcbElementsOverlap(elem1,elem2)){let error={type:"pcb_footprint_overlap_error",pcb_error_id:`pcb_footprint_overlap_${id1}_${id2}`,error_type:"pcb_footprint_overlap_error",message:`PCB component ${elem1.type} "${id1}" overlaps with ${elem2.type} "${id2}"`};(elem1.type==="pcb_smtpad"||elem2.type==="pcb_smtpad")&&(error.pcb_smtpad_ids=[],elem1.type==="pcb_smtpad"&&error.pcb_smtpad_ids.push(id1),elem2.type==="pcb_smtpad"&&error.pcb_smtpad_ids.push(id2)),(elem1.type==="pcb_plated_hole"||elem2.type==="pcb_plated_hole")&&(error.pcb_plated_hole_ids=[],elem1.type==="pcb_plated_hole"&&error.pcb_plated_hole_ids.push(id1),elem2.type==="pcb_plated_hole"&&error.pcb_plated_hole_ids.push(id2)),(elem1.type==="pcb_hole"||elem2.type==="pcb_hole")&&(error.pcb_hole_ids=[],elem1.type==="pcb_hole"&&error.pcb_hole_ids.push(id1),elem2.type==="pcb_hole"&&error.pcb_hole_ids.push(id2)),errors.push(error)}}}return errors}function checkPinMustBeConnected(circuitJson){let errors=[],sourceComponents=circuitJson.filter(el2=>"source_component_id"in el2&&(el2.type==="source_component"||el2.type.startsWith("source_simple_"))),sourcePorts=circuitJson.filter(el2=>el2.type==="source_port"),sourceTraces=circuitJson.filter(el2=>el2.type==="source_trace"),connectedPortIds=new Set;for(let trace of sourceTraces)for(let portId of trace.connected_source_port_ids??[])connectedPortIds.add(portId);let componentInternalConnections=new Map;for(let component of sourceComponents)"internally_connected_source_port_ids"in component&&component.internally_connected_source_port_ids&&componentInternalConnections.set(component.source_component_id,component.internally_connected_source_port_ids);for(let internalGroups of componentInternalConnections.values())for(let group of internalGroups)if(group.some(portId=>connectedPortIds.has(portId)))for(let portId of group)connectedPortIds.add(portId);for(let port of sourcePorts)if(port.must_be_connected===!0&&!connectedPortIds.has(port.source_port_id)){let componentName=sourceComponents.find(c3=>c3.source_component_id===port.source_component_id)?.name??"Unknown";errors.push({type:"source_pin_must_be_connected_error",source_pin_must_be_connected_error_id:`source_pin_must_be_connected_error_${port.source_port_id}`,error_type:"source_pin_must_be_connected_error",message:`Port ${port.name} on ${componentName} must be connected but is floating`,source_component_id:port.source_component_id??"",source_port_id:port.source_port_id,subcircuit_id:port.subcircuit_id})}return errors}init_dist();init_dist();init_dist();init_dist();init_dist5();init_dist();init_dist2();init_dist();init_svg_path_commander();init_dist6();var import_react4=__toESM(require_react(),1);var import_debug18=__toESM(require_browser(),1),import_react5=__toESM(require_react(),1),import_react6=__toESM(require_react(),1);var import_jsx_runtime=__toESM(require_jsx_runtime(),1);var import_jsx_runtime2=__toESM(require_jsx_runtime(),1),import_jsx_runtime3=__toESM(require_jsx_runtime(),1);var import_jsx_runtime4=__toESM(require_jsx_runtime(),1);var import_jsx_runtime5=__toESM(require_jsx_runtime(),1);var import_jsx_runtime6=__toESM(require_jsx_runtime(),1),import_react7=__toESM(require_react(),1);var __defProp4=Object.defineProperty,__export3=(target,all)=>{for(var name in all)__defProp4(target,name,{get:all[name],enumerable:!0})},components_exports={};__export3(components_exports,{AnalogSimulation:()=>AnalogSimulation,Battery:()=>Battery,Board:()=>Board,Breakout:()=>Breakout,BreakoutPoint:()=>BreakoutPoint,CadAssembly:()=>CadAssembly,CadModel:()=>CadModel,Capacitor:()=>Capacitor,Chip:()=>Chip,Constraint:()=>Constraint3,CopperPour:()=>CopperPour,CopperText:()=>CopperText,Crystal:()=>Crystal,CurrentSource:()=>CurrentSource,Cutout:()=>Cutout,Diode:()=>Diode,FabricationNoteDimension:()=>FabricationNoteDimension,FabricationNotePath:()=>FabricationNotePath,FabricationNoteRect:()=>FabricationNoteRect,FabricationNoteText:()=>FabricationNoteText,Fiducial:()=>Fiducial,Footprint:()=>Footprint,Fuse:()=>Fuse,Group:()=>Group6,Hole:()=>Hole,Inductor:()=>Inductor,Interconnect:()=>Interconnect,Jumper:()=>Jumper,Keepout:()=>Keepout,Led:()=>Led,Mosfet:()=>Mosfet,Net:()=>Net,NetLabel:()=>NetLabel,NormalComponent:()=>NormalComponent3,OpAmp:()=>OpAmp,Panel:()=>Panel,PcbNoteDimension:()=>PcbNoteDimension,PcbNoteLine:()=>PcbNoteLine,PcbNotePath:()=>PcbNotePath,PcbNoteRect:()=>PcbNoteRect,PcbNoteText:()=>PcbNoteText,PcbTrace:()=>PcbTrace,PinHeader:()=>PinHeader,Pinout:()=>Pinout,PlatedHole:()=>PlatedHole,Port:()=>Port,Potentiometer:()=>Potentiometer,PowerSource:()=>PowerSource,PrimitiveComponent:()=>PrimitiveComponent2,PushButton:()=>PushButton,Renderable:()=>Renderable,Resistor:()=>Resistor,Resonator:()=>Resonator,SchematicArc:()=>SchematicArc,SchematicBox:()=>SchematicBox,SchematicCell:()=>SchematicCell,SchematicCircle:()=>SchematicCircle,SchematicLine:()=>SchematicLine,SchematicPath:()=>SchematicPath,SchematicRect:()=>SchematicRect,SchematicRow:()=>SchematicRow,SchematicTable:()=>SchematicTable,SchematicText:()=>SchematicText,SilkscreenCircle:()=>SilkscreenCircle,SilkscreenLine:()=>SilkscreenLine,SilkscreenPath:()=>SilkscreenPath,SilkscreenRect:()=>SilkscreenRect,SilkscreenText:()=>SilkscreenText,SmtPad:()=>SmtPad,SolderJumper:()=>SolderJumper,Subcircuit:()=>Subcircuit,Subpanel:()=>Subpanel,Switch:()=>Switch,Symbol:()=>SymbolComponent,TestPoint:()=>TestPoint,Trace:()=>Trace3,TraceHint:()=>TraceHint,Transistor:()=>Transistor,Via:()=>Via,VoltageProbe:()=>VoltageProbe,VoltageSource:()=>VoltageSource});var debug5=(0,import_debug6.default)("tscircuit:renderable"),orderedRenderPhases=["ReactSubtreesRender","InflateSubcircuitCircuitJson","SourceNameDuplicateComponentRemoval","PcbFootprintStringRender","InitializePortsFromChildren","CreateNetsFromProps","AssignFallbackProps","CreateTracesFromProps","CreateTracesFromNetLabels","CreateTraceHintsFromProps","SourceGroupRender","AssignNameToUnnamedComponents","SourceRender","SourceParentAttachment","PortMatching","OptimizeSelectorCache","SourceTraceRender","SourceAddConnectivityMapKey","SourceDesignRuleChecks","SimulationRender","SchematicComponentRender","SchematicPortRender","SymbolContainerRender","SchematicPrimitiveRender","SchematicSymbolResize","SchematicComponentSizeCalculation","SchematicLayout","SchematicTraceRender","SchematicReplaceNetLabelsWithSymbols","PanelBoardLayout","PcbComponentRender","PcbPrimitiveRender","PcbFootprintLayout","PcbPortRender","PcbPortAttachment","PcbComponentSizeCalculation","PcbComponentAnchorAlignment","PcbLayout","PcbBoardAutoSize","PanelLayout","PcbTraceHintRender","PcbManualTraceRender","PcbTraceRender","PcbRouteNetIslands","PcbCopperPourRender","PcbDesignRuleChecks","SilkscreenOverlapAdjustment","CadModelRender","PartsEngineRender","SimulationSpiceEngineRender"],renderPhaseIndexMap=new Map(orderedRenderPhases.map((phase,index)=>[phase,index])),asyncPhaseDependencies={PcbFootprintLayout:["PcbFootprintStringRender"],PcbComponentSizeCalculation:["PcbFootprintStringRender"],PcbLayout:["PcbFootprintStringRender"],PcbBoardAutoSize:["PcbFootprintStringRender"],PcbTraceHintRender:["PcbFootprintStringRender"],PcbManualTraceRender:["PcbFootprintStringRender"],PcbCopperPourRender:["PcbFootprintStringRender","PcbTraceRender","PcbRouteNetIslands"],PcbTraceRender:["PcbFootprintStringRender"],PcbRouteNetIslands:["PcbFootprintStringRender"],PcbDesignRuleChecks:["PcbFootprintStringRender"],SilkscreenOverlapAdjustment:["PcbFootprintStringRender"],CadModelRender:["PcbFootprintStringRender"],PartsEngineRender:["PcbFootprintStringRender"],PcbComponentAnchorAlignment:["PcbFootprintStringRender"]},globalRenderCounter=0,globalAsyncEffectCounter=0,Renderable=class _Renderable{constructor(props){__publicField(this,"renderPhaseStates");__publicField(this,"shouldBeRemoved",!1);__publicField(this,"children");__publicField(this,"isPcbPrimitive",!1);__publicField(this,"isSchematicPrimitive",!1);__publicField(this,"_renderId");__publicField(this,"_currentRenderPhase",null);__publicField(this,"_asyncEffects",[]);__publicField(this,"parent",null);this._renderId=`${globalRenderCounter++}`,this.children=[],this.renderPhaseStates={};for(let phase of orderedRenderPhases)this.renderPhaseStates[phase]={initialized:!1,dirty:!1}}_markDirty(phase){this.renderPhaseStates[phase].dirty=!0;let phaseIndex=renderPhaseIndexMap.get(phase);for(let i2=phaseIndex+1;i2<orderedRenderPhases.length;i2++)this.renderPhaseStates[orderedRenderPhases[i2]].dirty=!0;this.parent?._markDirty&&this.parent._markDirty(phase)}_queueAsyncEffect(effectName,effect){let asyncEffectId=`${this._renderId}:${globalAsyncEffectCounter++}`,asyncEffect={asyncEffectId,promise:effect(),phase:this._currentRenderPhase,effectName,complete:!1};this._asyncEffects.push(asyncEffect);let root=this._getRootCircuit();root&&root.emit("asyncEffect:start",{asyncEffectId,effectName,componentDisplayName:this.getString(),phase:asyncEffect.phase}),asyncEffect.promise.then(()=>{asyncEffect.complete=!0;let root2=this._getRootCircuit();root2&&root2.emit("asyncEffect:end",{asyncEffectId,effectName,componentDisplayName:this.getString(),phase:asyncEffect.phase})}).catch(error=>{console.error(`Async effect error in ${asyncEffect.phase} "${effectName}":
|
|
617
|
+
${err.message}`):err}}let nNodes=ckt.nodes.count()-1;for(let i2=0;i2<ckt.V.length;i2++){let vs3=ckt.V[i2];vs3&&(vs3.index=nNodes+i2)}for(let sw of ckt.S){let model=vswitchModels.get(sw.modelName);if(!model)throw new Error(`Unknown .model ${sw.modelName} referenced by switch ${sw.name}`);sw.model=model,sw.isOn=!1}for(let d3 of ckt.D){let model=diodeModels.get(d3.modelName);if(!model)throw new Error(`Unknown .model ${d3.modelName} referenced by diode ${d3.name}`);d3.model=model}return ckt}var Complex=class _Complex{constructor(re4=0,im2=0){__publicField(this,"re");__publicField(this,"im");this.re=re4,this.im=im2}static from(re4,im2=0){return new _Complex(re4,im2)}static fromPolar(mag,deg=0){let ph2=deg*Math.PI/180;return new _Complex(mag*Math.cos(ph2),mag*Math.sin(ph2))}clone(){return new _Complex(this.re,this.im)}add(b3){return new _Complex(this.re+b3.re,this.im+b3.im)}sub(b3){return new _Complex(this.re-b3.re,this.im-b3.im)}mul(b3){return new _Complex(this.re*b3.re-this.im*b3.im,this.re*b3.im+this.im*b3.re)}div(b3){let d3=b3.re*b3.re+b3.im*b3.im;if(d3<EPS5)throw new Error("Complex divide by ~0");return new _Complex((this.re*b3.re+this.im*b3.im)/d3,(this.im*b3.re-this.re*b3.im)/d3)}inv(){let d3=this.re*this.re+this.im*this.im;if(d3<EPS5)throw new Error("Complex invert by ~0");return new _Complex(this.re/d3,-this.im/d3)}abs(){return Math.hypot(this.re,this.im)}phaseDeg(){return Math.atan2(this.im,this.re)*180/Math.PI}};function solveComplex(A4,b3){let n3=A4.length;for(let i2=0;i2<n3;i2++){let row=A4[i2],bi3=b3[i2];if(!row||!bi3)throw new Error("Matrix dimensions mismatch");let copy=row.map(z5=>z5.clone());copy.push(bi3.clone()),A4[i2]=copy}for(let k4=0;k4<n3;k4++){let imax=k4,pivotRow=A4[k4];if(!pivotRow)throw new Error("Matrix row missing");let vmax=pivotRow[k4]?.abs()??0;for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let v5=row[k4]?.abs()??0;v5>vmax&&(vmax=v5,imax=i2)}if(vmax<EPS5)throw new Error("Singular matrix (complex)");if(imax!==k4){let tmp=A4[k4];A4[k4]=A4[imax],A4[imax]=tmp}let pivotRowUpdated=A4[k4];if(!pivotRowUpdated)throw new Error("Pivot row missing");let pivot=pivotRowUpdated[k4];if(!pivot)throw new Error("Zero pivot encountered");for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let entry=row[k4];if(!entry)continue;let f2=entry.div(pivot);if(!(f2.abs()<EPS5))for(let j4=k4;j4<=n3;j4++){let target=row[j4],source=pivotRowUpdated[j4];!target||!source||(row[j4]=target.sub(f2.mul(source)))}}}let x5=new Array(n3);for(let i2=n3-1;i2>=0;i2--){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let s2=row[n3];if(!s2)throw new Error("Augmented column missing");for(let j4=i2+1;j4<n3;j4++){let coeff=row[j4],sol=x5[j4];!coeff||!sol||(s2=s2.sub(coeff.mul(sol)))}let pivot=row[i2];if(!pivot)throw new Error("Zero pivot on back-substitution");x5[i2]=s2.div(pivot)}return x5}function logspace(f12,f2,pointsPerDecade){if(f12<=0||f2<=0)throw new Error(".ac frequencies must be > 0");f2<f12&&([f12,f2]=[f2,f12]);let decades=Math.log10(f2/f12),n3=Math.max(1,Math.ceil(decades*pointsPerDecade)),arr=[];for(let i2=0;i2<=n3;i2++)arr.push(f12*Math.pow(10,i2/pointsPerDecade));let last=arr[arr.length-1];return(last==null||last<f2*(1-EPS5))&&arr.push(f2),arr}function stampAdmittanceComplex(A4,nidx,n12,n22,Y6){let i12=nidx.matrixIndexOfNode(n12),i2=nidx.matrixIndexOfNode(n22);if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping");row1[i12]=row1[i12]?.add(Y6)??Y6}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping");row2[i2]=row2[i2]?.add(Y6)??Y6}if(i12>=0&&i2>=0){let row1=A4[i12],row2=A4[i2];if(!row1||!row2)throw new Error("Matrix row missing while stamping");row1[i2]=row1[i2]?.sub(Y6)??Complex.from(0,0).sub(Y6),row2[i12]=row2[i12]?.sub(Y6)??Complex.from(0,0).sub(Y6)}}function stampVoltageSourceComplex(A4,b3,nidx,source,voltage2){let i12=nidx.matrixIndexOfNode(source.n1),i2=nidx.matrixIndexOfNode(source.n2),j4=source.index,one=Complex.from(1,0),negOne=Complex.from(-1,0);if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping voltage source");row1[j4]=row1[j4]?.add(one)??one}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping voltage source");row2[j4]=row2[j4]?.sub(one)??negOne}let branchRow=A4[j4];if(!branchRow)throw new Error("Branch row missing while stamping voltage source");i12>=0&&(branchRow[i12]=branchRow[i12]?.add(one)??one),i2>=0&&(branchRow[i2]=branchRow[i2]?.sub(one)??negOne),b3[j4]=(b3[j4]??Complex.from(0,0)).add(voltage2)}function buildFrequencyArray(params){let{mode,N:N6,f1:f12,f2}=params;if(mode==="dec")return logspace(f12,f2,N6);let arr=[],npts=Math.max(2,N6),step=(f2-f12)/(npts-1);for(let i2=0;i2<npts;i2++)arr.push(f12+i2*step);return arr}function buildLinearSystemForAC(ckt,f2,Nvar){let A4=Array.from({length:Nvar},()=>Array.from({length:Nvar},()=>Complex.from(0,0))),b3=Array.from({length:Nvar},()=>Complex.from(0,0)),twoPi=2*Math.PI;for(let r4 of ckt.R){if(r4.R<=0)throw new Error(`R ${r4.name} must be > 0`);let Y6=Complex.from(1/r4.R,0);stampAdmittanceComplex(A4,ckt.nodes,r4.n1,r4.n2,Y6)}for(let c3 of ckt.C){let Y6=Complex.from(0,twoPi*f2*c3.C);stampAdmittanceComplex(A4,ckt.nodes,c3.n1,c3.n2,Y6)}for(let l3 of ckt.L){let denom=Complex.from(0,twoPi*f2*l3.L),Y6=denom.abs()<EPS5?Complex.from(0,0):Complex.from(1,0).div(denom);stampAdmittanceComplex(A4,ckt.nodes,l3.n1,l3.n2,Y6)}for(let vs3 of ckt.V){let Vph=Complex.fromPolar(vs3.acMag||0,vs3.acPhaseDeg||0);stampVoltageSourceComplex(A4,b3,ckt.nodes,vs3,Vph)}return{A:A4,b:b3}}function simulateAC(ckt){var _a360,_b2,_c2,_d2;if(!ckt.analyses.ac)return null;let{mode,N:N6,f1:f12,f2}=ckt.analyses.ac,nNodeVars=ckt.nodes.count()-1,nVsrc=ckt.V.length,Nvar=nNodeVars+nVsrc,freqs=buildFrequencyArray({mode,N:N6,f1:f12,f2}),nodeVoltages={};ckt.nodes.rev.forEach((name,id)=>{id!==0&&(nodeVoltages[name]=[])});let elementCurrents={},twoPi=2*Math.PI;for(let f3 of freqs){let{A:A4,b:b3}=buildLinearSystemForAC(ckt,f3,Nvar),x5=solveComplex(A4,b3);for(let id=1;id<ckt.nodes.count();id++){let idx=id-1,nodeName2=ckt.nodes.rev[id];if(!nodeName2)continue;let series=nodeVoltages[nodeName2];series&&series.push(x5[idx]??Complex.from(0,0))}for(let r4 of ckt.R){let v12=r4.n1===0?Complex.from(0,0):x5[r4.n1-1]??Complex.from(0,0),v22=r4.n2===0?Complex.from(0,0):x5[r4.n2-1]??Complex.from(0,0),i2=Complex.from(1/r4.R,0).mul(v12.sub(v22));(elementCurrents[_a360=r4.name]||(elementCurrents[_a360]=[])).push(i2)}for(let c3 of ckt.C){let v12=c3.n1===0?Complex.from(0,0):x5[c3.n1-1]??Complex.from(0,0),v22=c3.n2===0?Complex.from(0,0):x5[c3.n2-1]??Complex.from(0,0),i2=Complex.from(0,twoPi*f3*c3.C).mul(v12.sub(v22));(elementCurrents[_b2=c3.name]||(elementCurrents[_b2]=[])).push(i2)}for(let l3 of ckt.L){let v12=l3.n1===0?Complex.from(0,0):x5[l3.n1-1]??Complex.from(0,0),v22=l3.n2===0?Complex.from(0,0):x5[l3.n2-1]??Complex.from(0,0),denom=Complex.from(0,twoPi*f3*l3.L),i2=(denom.abs()<EPS5?Complex.from(0,0):Complex.from(1,0).div(denom)).mul(v12.sub(v22));(elementCurrents[_c2=l3.name]||(elementCurrents[_c2]=[])).push(i2)}for(let vs3 of ckt.V){let i2=x5[vs3.index]??Complex.from(0,0);(elementCurrents[_d2=vs3.name]||(elementCurrents[_d2]=[])).push(i2)}}return{freqs,nodeVoltages,elementCurrents}}var VT_300K=.02585;function solveReal(A4,b3){let n3=A4.length;for(let i2=0;i2<n3;i2++){let row=A4[i2],bi3=b3[i2];if(!row||bi3==null)throw new Error("Matrix dimensions mismatch");let copy=row.slice();copy.push(bi3),A4[i2]=copy}for(let k4=0;k4<n3;k4++){let imax=k4,pivotRow=A4[k4];if(!pivotRow)throw new Error("Matrix row missing");let vmax=Math.abs(pivotRow[k4]??0);for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let v5=Math.abs(row[k4]??0);v5>vmax&&(vmax=v5,imax=i2)}if(vmax<EPS5)throw new Error("Singular matrix (real)");if(imax!==k4){let tmp=A4[k4];A4[k4]=A4[imax],A4[imax]=tmp}let pivotRowUpdated=A4[k4];if(!pivotRowUpdated)throw new Error("Pivot row missing");let pivot=pivotRowUpdated[k4];if(pivot==null)throw new Error("Zero pivot encountered");for(let i2=k4+1;i2<n3;i2++){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let entry=row[k4];if(entry==null)continue;let f2=entry/pivot;if(!(Math.abs(f2)<EPS5))for(let j4=k4;j4<=n3;j4++){let target=row[j4],source=pivotRowUpdated[j4];target==null||source==null||(row[j4]=target-f2*source)}}}let x5=new Array(n3).fill(0);for(let i2=n3-1;i2>=0;i2--){let row=A4[i2];if(!row)throw new Error("Matrix row missing");let s2=row[n3];if(s2==null)throw new Error("Augmented column missing");for(let j4=i2+1;j4<n3;j4++){let coeff=row[j4],sol=x5[j4];coeff==null||sol==null||(s2-=coeff*sol)}let pivot=row[i2];if(pivot==null)throw new Error("Zero pivot on back-substitution");x5[i2]=s2/pivot}return x5}function stampAdmittanceReal(A4,nidx,n12,n22,Y6){let i12=nidx.matrixIndexOfNode(n12),i2=nidx.matrixIndexOfNode(n22);if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping");row1[i12]=(row1[i12]??0)+Y6}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping");row2[i2]=(row2[i2]??0)+Y6}if(i12>=0&&i2>=0){let row1=A4[i12],row2=A4[i2];if(!row1||!row2)throw new Error("Matrix row missing while stamping");row1[i2]=(row1[i2]??0)-Y6,row2[i12]=(row2[i12]??0)-Y6}}function stampCurrentReal(b3,nidx,nPlus,nMinus,current2){let iPlus=nidx.matrixIndexOfNode(nPlus),iMinus=nidx.matrixIndexOfNode(nMinus);iPlus>=0&&(b3[iPlus]=(b3[iPlus]??0)-current2),iMinus>=0&&(b3[iMinus]=(b3[iMinus]??0)+current2)}function stampVoltageSourceReal(A4,b3,nidx,source,voltage2){let i12=nidx.matrixIndexOfNode(source.n1),i2=nidx.matrixIndexOfNode(source.n2),j4=source.index;if(i12>=0){let row1=A4[i12];if(!row1)throw new Error("Matrix row missing while stamping voltage source");row1[j4]=(row1[j4]??0)+1}if(i2>=0){let row2=A4[i2];if(!row2)throw new Error("Matrix row missing while stamping voltage source");row2[j4]=(row2[j4]??0)-1}let branchRow=A4[j4];if(!branchRow)throw new Error("Branch row missing while stamping voltage source");i12>=0&&(branchRow[i12]=(branchRow[i12]??0)+1),i2>=0&&(branchRow[i2]=(branchRow[i2]??0)-1),b3[j4]=(b3[j4]??0)+voltage2}function computeEffectiveTimeStep(dtRequested,tstop){let dtEff=dtRequested>EPS5?dtRequested:Math.max(tstop/1e3,EPS5),steps=Math.max(1,Math.ceil(tstop/Math.max(dtEff,EPS5)));return{dt:steps>0?tstop/steps:tstop,steps}}function stampAllElementsAtTime(A4,b3,ckt,t5,dt4,x5,iter){for(let r4 of ckt.R){let G5=1/r4.R;stampAdmittanceReal(A4,ckt.nodes,r4.n1,r4.n2,G5)}for(let c3 of ckt.C){let Gc2=c3.C/Math.max(dt4,EPS5);stampAdmittanceReal(A4,ckt.nodes,c3.n1,c3.n2,Gc2);let Ieq=-Gc2*c3.vPrev;stampCurrentReal(b3,ckt.nodes,c3.n1,c3.n2,Ieq)}for(let l3 of ckt.L){let Gl2=Math.max(dt4,EPS5)/l3.L;stampAdmittanceReal(A4,ckt.nodes,l3.n1,l3.n2,Gl2),stampCurrentReal(b3,ckt.nodes,l3.n1,l3.n2,l3.iPrev)}for(let sw of ckt.S){let model=sw.model;if(!model)continue;let Rvalue=sw.isOn?model.Ron:model.Roff,G5=1/Math.max(Math.abs(Rvalue),EPS5);stampAdmittanceReal(A4,ckt.nodes,sw.n1,sw.n2,G5)}for(let vs3 of ckt.V){let Vt4=vs3.waveform?vs3.waveform(t5):vs3.dc||0;stampVoltageSourceReal(A4,b3,ckt.nodes,vs3,Vt4)}for(let d3 of ckt.D){let model=d3.model;if(!model)continue;let{nPlus,nMinus}=d3,vp_idx=ckt.nodes.matrixIndexOfNode(nPlus),vn_idx=ckt.nodes.matrixIndexOfNode(nMinus),v_plus_prev_iter=nPlus===0?0:x5[vp_idx]??0,v_minus_prev_iter=nMinus===0?0:x5[vn_idx]??0,vd_prev_iter=v_plus_prev_iter-v_minus_prev_iter,vd2=iter===0?d3.vdPrev:vd_prev_iter,v_thermal=model.N*VT_300K,vd_limited=vd2;vd2>.8&&(vd_limited=.8),vd2<-1&&(vd_limited=-1);let exp_val=Math.exp(vd_limited/v_thermal),id=model.Is*(exp_val-1),gd2=Math.max(model.Is/v_thermal*exp_val,1e-12),ieq=id-gd2*vd_limited;stampAdmittanceReal(A4,ckt.nodes,nPlus,nMinus,gd2),stampCurrentReal(b3,ckt.nodes,nPlus,nMinus,ieq)}}function updateSwitchStatesFromSolution(ckt,x5){let switched=!1;for(let sw of ckt.S){let model=sw.model;if(!model)continue;let vp2=sw.ncPos===0?0:x5[sw.ncPos-1]??0,vn3=sw.ncNeg===0?0:x5[sw.ncNeg-1]??0,vctrl=vp2-vn3,nextState=sw.isOn;sw.isOn?vctrl<model.Voff&&(nextState=!1):vctrl>model.Von&&(nextState=!0),nextState!==sw.isOn&&(sw.isOn=nextState,switched=!0)}return switched}function simulateTRAN(ckt){var _a360,_b2,_c2,_d2,_e4,_f2;if(!ckt.analyses.tran)return null;let{dt:dtRequested,tstop}=ckt.analyses.tran,{dt:dt4,steps}=computeEffectiveTimeStep(dtRequested,tstop),nNodeVars=ckt.nodes.count()-1,nVsrc=ckt.V.length,Nvar=nNodeVars+nVsrc,times=[],nodeVoltages={};ckt.nodes.rev.forEach((name,id)=>{id!==0&&(nodeVoltages[name]=[])});let elementCurrents={},t5=0;for(let step=0;step<=steps;step++,t5=step*dt4){times.push(t5);let x5=new Array(Nvar).fill(0);for(let iter=0;iter<20;iter++){let A4=Array.from({length:Nvar},()=>new Array(Nvar).fill(0)),b3=new Array(Nvar).fill(0);if(stampAllElementsAtTime(A4,b3,ckt,t5,dt4,x5,iter),x5=solveReal(A4,b3),!updateSwitchStatesFromSolution(ckt,x5)||iter===19)break}for(let id=1;id<ckt.nodes.count();id++){let idx=id-1,nodeName2=ckt.nodes.rev[id];if(!nodeName2)continue;let series=nodeVoltages[nodeName2];series&&series.push(x5[idx]??0)}for(let r4 of ckt.R){let v12=r4.n1===0?0:x5[r4.n1-1]??0,v22=r4.n2===0?0:x5[r4.n2-1]??0,i2=(v12-v22)/r4.R;(elementCurrents[_a360=r4.name]||(elementCurrents[_a360]=[])).push(i2)}for(let c3 of ckt.C){let v12=c3.n1===0?0:x5[c3.n1-1]??0,v22=c3.n2===0?0:x5[c3.n2-1]??0,i2=c3.C*(v12-v22-c3.vPrev)/Math.max(dt4,EPS5);(elementCurrents[_b2=c3.name]||(elementCurrents[_b2]=[])).push(i2)}for(let l3 of ckt.L){let v12=l3.n1===0?0:x5[l3.n1-1]??0,v22=l3.n2===0?0:x5[l3.n2-1]??0,i2=Math.max(dt4,EPS5)/l3.L*(v12-v22)+l3.iPrev;(elementCurrents[_c2=l3.name]||(elementCurrents[_c2]=[])).push(i2)}for(let vs3 of ckt.V){let i2=x5[vs3.index]??0;(elementCurrents[_d2=vs3.name]||(elementCurrents[_d2]=[])).push(i2)}for(let sw of ckt.S){let model=sw.model;if(!model)continue;let v12=sw.n1===0?0:x5[sw.n1-1]??0,v22=sw.n2===0?0:x5[sw.n2-1]??0,Rvalue=sw.isOn?model.Ron:model.Roff,Rclamped=Math.max(Math.abs(Rvalue),EPS5),i2=(v12-v22)/Rclamped;(elementCurrents[_e4=sw.name]||(elementCurrents[_e4]=[])).push(i2)}for(let d3 of ckt.D){if(!d3.model)continue;let{nPlus,nMinus,model}=d3,v12=nPlus===0?0:x5[nPlus-1]??0,v22=nMinus===0?0:x5[nMinus-1]??0,vd2=v12-v22,v_thermal=model.N*VT_300K,exp_val=Math.exp(vd2/v_thermal),id=model.Is*(exp_val-1);(elementCurrents[_f2=d3.name]||(elementCurrents[_f2]=[])).push(id)}for(let c3 of ckt.C){let v12=c3.n1===0?0:x5[c3.n1-1]??0,v22=c3.n2===0?0:x5[c3.n2-1]??0;c3.vPrev=v12-v22}for(let l3 of ckt.L){let v12=l3.n1===0?0:x5[l3.n1-1]??0,v22=l3.n2===0?0:x5[l3.n2-1]??0,Gl2=Math.max(dt4,EPS5)/l3.L;l3.iPrev=Gl2*(v12-v22)+l3.iPrev}for(let d3 of ckt.D){let v12=d3.nPlus===0?0:x5[d3.nPlus-1]??0,v22=d3.nMinus===0?0:x5[d3.nMinus-1]??0;d3.vdPrev=v12-v22}}if(ckt.probes.tran.length>0){let probedVoltages={},upperProbes=ckt.probes.tran.map(p4=>p4.toUpperCase());for(let nodeName2 in nodeVoltages)upperProbes.includes(nodeName2.toUpperCase())&&(probedVoltages[nodeName2]=nodeVoltages[nodeName2]);return{times,nodeVoltages:probedVoltages,elementCurrents}}return{times,nodeVoltages,elementCurrents}}function simulate(netlistText){let circuit=parseNetlist(netlistText),ac2=simulateAC(circuit),tran=simulateTRAN(circuit);return{circuit,ac:ac2,tran}}function spiceyTranToVGraphs(tranResult,ckt,simulation_experiment_id){if(!tranResult||!ckt.analyses.tran)return[];let{dt:dt4,tstop}=ckt.analyses.tran,{times,nodeVoltages}=tranResult,graphs=[];for(let nodeName2 in nodeVoltages){let voltage_levels=nodeVoltages[nodeName2];graphs.push({type:"simulation_transient_voltage_graph",simulation_transient_voltage_graph_id:`stvg_${simulation_experiment_id}_${nodeName2}`,simulation_experiment_id,timestamps_ms:times.map(t5=>t5*1e3),voltage_levels,time_per_step:dt4*1e3,start_time_ms:0,end_time_ms:tstop*1e3,name:`${nodeName2}`})}return graphs}init_dist6();var SI_PREFIXES=[{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"}];function formatSiUnit(value){if(value==null)return"";if(value===0)return"0";let absValue=Math.abs(value),prefix=SI_PREFIXES.find(p4=>{let scaled2=absValue/p4.value;return scaled2>=1&&scaled2<1e3})||SI_PREFIXES[SI_PREFIXES.length-1],formatted=(value/prefix.value).toPrecision(3);return formatted.includes(".")&&!/\.0+$/.test(formatted)&&(formatted=formatted.replace(/0+$/,"")),formatted=formatted.replace(/\.0+$/,""),`${formatted}${prefix.symbol}`}init_dist6();init_dist();init_dist4();init_dist6();init_dist4();init_dist6();init_dist6();init_dist();init_dist6();init_dist6();init_src();init_dist6();init_dist4();init_dist6();init_dist4();init_dist6();init_dist6();init_dist4();init_dist6();function distance7(x12,y12,x22,y22){return Math.sqrt((x22-x12)**2+(y22-y12)**2)}var addStartAndEndPortIdsIfMissing=soup=>{let pcbPorts=soup.filter(item=>item.type==="pcb_port"),pcbSmtPads=soup.filter(item=>item.type==="pcb_smtpad"),pcbTraces=soup.filter(item=>item.type==="pcb_trace");function findPortIdOverlappingPoint(point6,options={}){let traceWidth=options.traceWidth||0,directPort=pcbPorts.find(port=>distance7(port.x,port.y,point6.x,point6.y)<.01);if(directPort)return directPort.pcb_port_id;if(options.isFirstOrLastPoint){let smtPad=pcbSmtPads.find(pad2=>{if(pad2.shape==="rect")return Math.abs(point6.x-pad2.x)<pad2.width/2+traceWidth/2&&Math.abs(point6.y-pad2.y)<pad2.height/2+traceWidth/2;if(pad2.shape==="circle")return distance7(point6.x,point6.y,pad2.x,pad2.y)<pad2.radius});if(smtPad)return smtPad.pcb_port_id??null}return null}for(let trace of pcbTraces)for(let index=0;index<trace.route.length;index++){let segment2=trace.route[index],isFirstOrLastPoint=index===0||index===trace.route.length-1;if(segment2.route_type==="wire"){if(!segment2.start_pcb_port_id&&index===0){let startPortId=findPortIdOverlappingPoint(segment2,{isFirstOrLastPoint,traceWidth:segment2.width});startPortId&&(segment2.start_pcb_port_id=startPortId)}if(!segment2.end_pcb_port_id&&index===trace.route.length-1){let endPortId=findPortIdOverlappingPoint(segment2,{isFirstOrLastPoint,traceWidth:segment2.width});endPortId&&(segment2.end_pcb_port_id=endPortId)}}}};function checkEachPcbPortConnectedToPcbTraces(circuitJson){addStartAndEndPortIdsIfMissing(circuitJson);let sourceTraces=circuitJson.filter(item=>item.type==="source_trace"),pcbPorts=circuitJson.filter(item=>item.type==="pcb_port"),errors=[],connectivityMap=getFullConnectivityMapFromCircuitJson(circuitJson),sourcePortToPcbPort=new Map;for(let pcbPort of pcbPorts)sourcePortToPcbPort.set(pcbPort.source_port_id,pcbPort);for(let sourceTrace of sourceTraces){let connectedSourcePortIds=sourceTrace.connected_source_port_ids;if(connectedSourcePortIds.length<2)continue;let pcbPortsInTrace=[],missingPcbPorts=[];for(let sourcePortId of connectedSourcePortIds){let pcbPort=sourcePortToPcbPort.get(sourcePortId);pcbPort?pcbPortsInTrace.push(pcbPort):missingPcbPorts.push(sourcePortId)}if(pcbPortsInTrace.length<2)continue;let firstPcbPort=pcbPortsInTrace[0],referenceNetId=connectivityMap.getNetConnectedToId(firstPcbPort.pcb_port_id);connectivityMap.getIdsConnectedToNet(referenceNetId).filter(id=>circuitJson.some(element=>element.type==="pcb_trace"&&("pcb_trace_id"in element&&element.pcb_trace_id===id||"route_id"in element&&element.route_id===id))).length===0&&new Set(pcbPortsInTrace.map(p4=>p4.pcb_component_id)).size>1&&errors.push({type:"pcb_port_not_connected_error",message:`pcb_port_not_connected_error: Pcb ports [${pcbPortsInTrace.map(p4=>p4.pcb_port_id).join(", ")}] are not connected together through the same net.`,error_type:"pcb_port_not_connected_error",pcb_port_ids:pcbPortsInTrace.map(p4=>p4.pcb_port_id),pcb_component_ids:pcbPortsInTrace.map(p4=>p4.pcb_component_id).filter(id=>id!==void 0),pcb_port_not_connected_error_id:`pcb_port_not_connected_error_trace_${sourceTrace.source_trace_id}`})}return errors}var SpatialObjectIndex=class{constructor({objects,getBounds:getBounds3,getId,CELL_SIZE}){__publicField(this,"buckets");__publicField(this,"objectsById");__publicField(this,"getBounds");__publicField(this,"getId");__publicField(this,"CELL_SIZE",.4);__publicField(this,"_idCounter",0);this.buckets=new Map,this.objectsById=new Map,this.getBounds=getBounds3,this.getId=getId??(()=>this._getNextId()),this.CELL_SIZE=CELL_SIZE??this.CELL_SIZE;for(let obj of objects)this.addObject(obj)}_getNextId(){return`${this._idCounter++}`}addObject(obj){let bounds=this.getBounds(obj),spatialIndexId=this.getId(obj),objWithId={...obj,spatialIndexId};this.objectsById.set(spatialIndexId,objWithId);let minBucketX=Math.floor(bounds.minX/this.CELL_SIZE),minBucketY=Math.floor(bounds.minY/this.CELL_SIZE),maxBucketX=Math.floor(bounds.maxX/this.CELL_SIZE),maxBucketY=Math.floor(bounds.maxY/this.CELL_SIZE);for(let bx2=minBucketX;bx2<=maxBucketX;bx2++)for(let by2=minBucketY;by2<=maxBucketY;by2++){let bucketKey=`${bx2}x${by2}`,bucket=this.buckets.get(bucketKey);bucket?bucket.push(objWithId):this.buckets.set(bucketKey,[objWithId])}}removeObject(id){let obj=this.objectsById.get(id);if(!obj)return!1;this.objectsById.delete(id);let bounds=this.getBounds(obj),minBucketX=Math.floor(bounds.minX/this.CELL_SIZE),minBucketY=Math.floor(bounds.minY/this.CELL_SIZE),maxBucketX=Math.floor(bounds.maxX/this.CELL_SIZE),maxBucketY=Math.floor(bounds.maxY/this.CELL_SIZE);for(let bx2=minBucketX;bx2<=maxBucketX;bx2++)for(let by2=minBucketY;by2<=maxBucketY;by2++){let bucketKey=`${bx2}x${by2}`,bucket=this.buckets.get(bucketKey);if(bucket){let index=bucket.findIndex(item=>item.spatialIndexId===id);index!==-1&&(bucket.splice(index,1),bucket.length===0&&this.buckets.delete(bucketKey))}}return!0}getBucketKey(x5,y5){return`${Math.floor(x5/this.CELL_SIZE)}x${Math.floor(y5/this.CELL_SIZE)}`}getObjectsInBounds(bounds,margin=0){let objects=[],addedIds=new Set,minBucketX=Math.floor((bounds.minX-margin)/this.CELL_SIZE),minBucketY=Math.floor((bounds.minY-margin)/this.CELL_SIZE),maxBucketX=Math.floor((bounds.maxX+margin)/this.CELL_SIZE),maxBucketY=Math.floor((bounds.maxY+margin)/this.CELL_SIZE);for(let bx2=minBucketX;bx2<=maxBucketX;bx2++)for(let by2=minBucketY;by2<=maxBucketY;by2++){let bucketKey=`${bx2}x${by2}`,bucket=this.buckets.get(bucketKey)||[];for(let obj of bucket){let id=obj.spatialIndexId;addedIds.has(id)||(addedIds.add(id),objects.push(obj))}}return objects}},getCollidableBounds=collidable=>collidable.type==="pcb_trace_segment"?{minX:Math.min(collidable.x1,collidable.x2),minY:Math.min(collidable.y1,collidable.y2),maxX:Math.max(collidable.x1,collidable.x2),maxY:Math.max(collidable.y1,collidable.y2)}:getBoundsOfPcbElements([collidable]),DEFAULT_TRACE_MARGIN=.1,DEFAULT_TRACE_THICKNESS=.15;var DEFAULT_SAME_NET_VIA_MARGIN=.2,DEFAULT_DIFFERENT_NET_VIA_MARGIN=.3,EPSILON=.005;function getPcbPortIdsConnectedToTrace(trace){let connectedPcbPorts=new Set;for(let segment2 of trace.route)segment2.route_type==="wire"&&(segment2.start_pcb_port_id&&connectedPcbPorts.add(segment2.start_pcb_port_id),segment2.end_pcb_port_id&&connectedPcbPorts.add(segment2.end_pcb_port_id));return Array.from(connectedPcbPorts)}function getPcbPortIdsConnectedToTraces(traces){let connectedPorts=new Set;for(let trace of traces)for(let portId of getPcbPortIdsConnectedToTrace(trace))connectedPorts.add(portId);return Array.from(connectedPorts)}var getClosestPointBetweenSegments=(segmentA,segmentB)=>{let a12={x:segmentA.x1,y:segmentA.y1},a2={x:segmentA.x2,y:segmentA.y2},b12={x:segmentB.x1,y:segmentB.y1},b22={x:segmentB.x2,y:segmentB.y2},va3={x:a2.x-a12.x,y:a2.y-a12.y},vb2={x:b22.x-b12.x,y:b22.y-b12.y},lenSqrA=va3.x*va3.x+va3.y*va3.y,lenSqrB=vb2.x*vb2.x+vb2.y*vb2.y;if(lenSqrA===0||lenSqrB===0){if(lenSqrA===0&&lenSqrB===0)return{x:(a12.x+b12.x)/2,y:(a12.y+b12.y)/2};if(lenSqrA===0){let t22=clamp4(((a12.x-b12.x)*vb2.x+(a12.y-b12.y)*vb2.y)/lenSqrB,0,1),closestOnB2={x:b12.x+t22*vb2.x,y:b12.y+t22*vb2.y};return{x:(a12.x+closestOnB2.x)/2,y:(a12.y+closestOnB2.y)/2}}let t5=clamp4(((b12.x-a12.x)*va3.x+(b12.y-a12.y)*va3.y)/lenSqrA,0,1),closestOnA2={x:a12.x+t5*va3.x,y:a12.y+t5*va3.y};return{x:(closestOnA2.x+b12.x)/2,y:(closestOnA2.y+b12.y)/2}}let w4={x:a12.x-b12.x,y:a12.y-b12.y},dotAA=va3.x*va3.x+va3.y*va3.y,dotAB=va3.x*vb2.x+va3.y*vb2.y,dotAW=va3.x*w4.x+va3.y*w4.y,dotBB=vb2.x*vb2.x+vb2.y*vb2.y,dotBW=vb2.x*w4.x+vb2.y*w4.y,denominator=dotAA*dotBB-dotAB*dotAB;if(denominator<1e-10)return closestPointsParallelSegments(a12,a2,b12,b22,va3,vb2,lenSqrA,lenSqrB);let tA=(dotAB*dotBW-dotBB*dotAW)/denominator,tB=(dotAA*dotBW-dotAB*dotAW)/denominator;tA=clamp4(tA,0,1),tB=clamp4(tB,0,1),tB=(tA*dotAB+dotBW)/dotBB,tB=clamp4(tB,0,1),tA=(tB*dotAB-dotAW)/dotAA,tA=clamp4(tA,0,1);let closestOnA={x:a12.x+tA*va3.x,y:a12.y+tA*va3.y},closestOnB={x:b12.x+tB*vb2.x,y:b12.y+tB*vb2.y},dx2=closestOnA.x-closestOnB.x,dy2=closestOnA.y-closestOnB.y,distance52=Math.sqrt(dx2*dx2+dy2*dy2);return{x:(closestOnA.x+closestOnB.x)/2,y:(closestOnA.y+closestOnB.y)/2}},closestPointsParallelSegments=(a12,a2,b12,b22,va3,vb2,lenSqrA,lenSqrB)=>{let tA=((b12.x-a12.x)*va3.x+(b12.y-a12.y)*va3.y)/lenSqrA;tA=clamp4(tA,0,1);let pointOnA1={x:a12.x+tA*va3.x,y:a12.y+tA*va3.y},tA2=((b22.x-a12.x)*va3.x+(b22.y-a12.y)*va3.y)/lenSqrA;tA2=clamp4(tA2,0,1);let pointOnA2={x:a12.x+tA2*va3.x,y:a12.y+tA2*va3.y},tB=((a12.x-b12.x)*vb2.x+(a12.y-b12.y)*vb2.y)/lenSqrB;tB=clamp4(tB,0,1);let pointOnB1={x:b12.x+tB*vb2.x,y:b12.y+tB*vb2.y},tB2=((a2.x-b12.x)*vb2.x+(a2.y-b12.y)*vb2.y)/lenSqrB;tB2=clamp4(tB2,0,1);let pointOnB2={x:b12.x+tB2*vb2.x,y:b12.y+tB2*vb2.y},closestPair=[{pointA:pointOnA1,pointB:b12,distance:Math.sqrt((pointOnA1.x-b12.x)**2+(pointOnA1.y-b12.y)**2)},{pointA:pointOnA2,pointB:b22,distance:Math.sqrt((pointOnA2.x-b22.x)**2+(pointOnA2.y-b22.y)**2)},{pointA:a12,pointB:pointOnB1,distance:Math.sqrt((a12.x-pointOnB1.x)**2+(a12.y-pointOnB1.y)**2)},{pointA:a2,pointB:pointOnB2,distance:Math.sqrt((a2.x-pointOnB2.x)**2+(a2.y-pointOnB2.y)**2)}].reduce((closest,current2)=>current2.distance<closest.distance?current2:closest);return{x:(closestPair.pointA.x+closestPair.pointB.x)/2,y:(closestPair.pointA.y+closestPair.pointB.y)/2}},clamp4=(value,min,max)=>Math.max(min,Math.min(max,value)),getRadiusOfCircuitJsonElement=obj=>{if(obj.type==="pcb_via"||obj.type==="pcb_plated_hole"&&obj.shape==="circle")return obj.outer_diameter/2;if(obj.type==="pcb_hole"&&obj.hole_shape==="circle")return obj.hole_diameter/2;if(obj.type==="pcb_smtpad"&&obj.shape==="circle")return obj.radius;throw new Error(`Could not determine radius of element: ${JSON.stringify(obj)}`)},getClosestPointBetweenSegmentAndBounds=(segment2,bounds)=>{let p12={x:segment2.x1,y:segment2.y1},p22={x:segment2.x2,y:segment2.y2},minX=bounds.minX,minY=bounds.minY,maxX=bounds.maxX,maxY=bounds.maxY;if(p12.x===p22.x&&p12.y===p22.y){let closestX=Math.max(minX,Math.min(maxX,p12.x)),closestY=Math.max(minY,Math.min(maxY,p12.y));return closestX===p12.x&&closestY===p12.y?{x:p12.x,y:p12.y}:{x:closestX,y:closestY}}let dx2=p22.x-p12.x,dy2=p22.y-p12.y,tMinX=dx2!==0?(minX-p12.x)/dx2:Number.NEGATIVE_INFINITY,tMaxX=dx2!==0?(maxX-p12.x)/dx2:Number.POSITIVE_INFINITY,tMinY=dy2!==0?(minY-p12.y)/dy2:Number.NEGATIVE_INFINITY,tMaxY=dy2!==0?(maxY-p12.y)/dy2:Number.POSITIVE_INFINITY,tEnter=Math.max(Math.min(tMinX,tMaxX),Math.min(tMinY,tMaxY)),tExit=Math.min(Math.max(tMinX,tMaxX),Math.max(tMinY,tMaxY));if(tEnter<=tExit&&tExit>=0&&tEnter<=1){let t5=Math.max(0,Math.min(1,tEnter));return{x:p12.x+t5*dx2,y:p12.y+t5*dy2}}let closestToP1={x:Math.max(minX,Math.min(maxX,p12.x)),y:Math.max(minY,Math.min(maxY,p12.y))},closestToP2={x:Math.max(minX,Math.min(maxX,p22.x)),y:Math.max(minY,Math.min(maxY,p22.y))},distToP1Squared=(closestToP1.x-p12.x)**2+(closestToP1.y-p12.y)**2,distToP2Squared=(closestToP2.x-p22.x)**2+(closestToP2.y-p22.y)**2,edges=[{start:{x:minX,y:minY},end:{x:maxX,y:minY}},{start:{x:maxX,y:minY},end:{x:maxX,y:maxY}},{start:{x:maxX,y:maxY},end:{x:minX,y:maxY}},{start:{x:minX,y:maxY},end:{x:minX,y:minY}}],minDistance=Math.min(distToP1Squared,distToP2Squared),closestPoint=distToP1Squared<=distToP2Squared?closestToP1:closestToP2,clamp22=(value,min,max)=>Math.max(min,Math.min(max,value));for(let edge of edges){let va3={x:p22.x-p12.x,y:p22.y-p12.y},vb2={x:edge.end.x-edge.start.x,y:edge.end.y-edge.start.y},w4={x:p12.x-edge.start.x,y:p12.y-edge.start.y},dotAA=va3.x*va3.x+va3.y*va3.y,dotAB=va3.x*vb2.x+va3.y*vb2.y,dotAW=va3.x*w4.x+va3.y*w4.y,dotBB=vb2.x*vb2.x+vb2.y*vb2.y,dotBW=vb2.x*w4.x+vb2.y*w4.y,denominator=dotAA*dotBB-dotAB*dotAB;if(Math.abs(denominator)<1e-10)continue;let tA=(dotAB*dotBW-dotBB*dotAW)/denominator,tB=(dotAA*dotBW-dotAB*dotAW)/denominator;tA=clamp22(tA,0,1),tB=clamp22(tB,0,1);let closestOnSegment={x:p12.x+tA*va3.x,y:p12.y+tA*va3.y},closestOnEdge={x:edge.start.x+tB*vb2.x,y:edge.start.y+tB*vb2.y},dx22=closestOnSegment.x-closestOnEdge.x,dy22=closestOnSegment.y-closestOnEdge.y,distSquared=dx22*dx22+dy22*dy22;distSquared<minDistance&&(minDistance=distSquared,closestPoint={x:(closestOnSegment.x+closestOnEdge.x)/2,y:(closestOnSegment.y+closestOnEdge.y)/2})}return closestPoint};function getLayersOfPcbElement(obj){return obj.type==="pcb_trace_segment"?[obj.layer]:obj.type==="pcb_smtpad"?[obj.layer]:obj.type==="pcb_plated_hole"?Array.isArray(obj.layers)?obj.layers:[...all_layers]:obj.type==="pcb_hole"?[...all_layers]:obj.type==="pcb_via"?Array.isArray(obj.layers)?obj.layers:[...all_layers]:obj.type==="pcb_keepout"?Array.isArray(obj.layers)?obj.layers:[]:[]}function checkEachPcbTraceNonOverlapping(circuitJson,{connMap}={}){let errors=[];connMap??(connMap=getFullConnectivityMapFromCircuitJson(circuitJson));let pcbTraceSegments=cju_default(circuitJson).pcb_trace.list().flatMap(pcbTrace=>{let segments=[];for(let i2=0;i2<pcbTrace.route.length-1;i2++){let p12=pcbTrace.route[i2],p22=pcbTrace.route[i2+1];p12.route_type==="wire"&&p22.route_type==="wire"&&p12.layer===p22.layer&&segments.push({type:"pcb_trace_segment",pcb_trace_id:pcbTrace.pcb_trace_id,_pcbTrace:pcbTrace,thickness:"width"in p12?p12.width:"width"in p22?p22.width:DEFAULT_TRACE_THICKNESS,layer:p12.layer,x1:p12.x,y1:p12.y,x2:p22.x,y2:p22.y})}return segments}),pcbSmtPads=cju_default(circuitJson).pcb_smtpad.list(),pcbPlatedHoles=cju_default(circuitJson).pcb_plated_hole.list(),pcbHoles=cju_default(circuitJson).pcb_hole.list(),pcbVias=cju_default(circuitJson).pcb_via.list(),pcbKeepouts=cju_default(circuitJson).pcb_keepout.list(),allObjects=[...pcbTraceSegments,...pcbSmtPads,...pcbPlatedHoles,...pcbHoles,...pcbVias,...pcbKeepouts],spatialIndex=new SpatialObjectIndex({objects:allObjects,getBounds:getCollidableBounds}),getReadableName=id=>getReadableNameForElement(circuitJson,id),errorIds=new Set;for(let segmentA of pcbTraceSegments){let requiredMargin=DEFAULT_TRACE_MARGIN,bounds=getCollidableBounds(segmentA),nearbyObjects=spatialIndex.getObjectsInBounds(bounds,requiredMargin+segmentA.thickness/2);if(!(segmentA.x1===segmentA.x2&&segmentA.y1===segmentA.y2))for(let obj of nearbyObjects){if(!getLayersOfPcbElement(obj).includes(segmentA.layer))continue;if(obj.type==="pcb_trace_segment"){let segmentB=obj;if(segmentA.layer!==segmentB.layer||connMap.areIdsConnected(segmentA.pcb_trace_id,segmentB.pcb_trace_id))continue;let gap2=segmentToSegmentMinDistance({x:segmentA.x1,y:segmentA.y1},{x:segmentA.x2,y:segmentA.y2},{x:segmentB.x1,y:segmentB.y1},{x:segmentB.x2,y:segmentB.y2})-segmentA.thickness/2-segmentB.thickness/2;if(gap2>DEFAULT_TRACE_MARGIN-EPSILON)continue;let pcb_trace_error_id=`overlap_${segmentA.pcb_trace_id}_${segmentB.pcb_trace_id}`,pcb_trace_error_id_reverse=`overlap_${segmentB.pcb_trace_id}_${segmentA.pcb_trace_id}`;if(errorIds.has(pcb_trace_error_id)||errorIds.has(pcb_trace_error_id_reverse))continue;errorIds.add(pcb_trace_error_id),errors.push({type:"pcb_trace_error",error_type:"pcb_trace_error",message:`PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${getReadableName(segmentB.pcb_trace_id)} ${gap2<0?"(accidental contact)":`(gap: ${gap2.toFixed(3)}mm)`}`,pcb_trace_id:segmentA.pcb_trace_id,source_trace_id:"",pcb_trace_error_id,pcb_component_ids:[],center:getClosestPointBetweenSegments(segmentA,segmentB),pcb_port_ids:getPcbPortIdsConnectedToTraces([segmentA._pcbTrace,segmentB._pcbTrace])});continue}let primaryObjId=getPrimaryId(obj);if(connMap.areIdsConnected(segmentA.pcb_trace_id,"pcb_trace_id"in obj?obj.pcb_trace_id:primaryObjId))continue;if(obj.type==="pcb_via"||obj.type==="pcb_plated_hole"&&obj.shape==="circle"||obj.type==="pcb_hole"||obj.type==="pcb_smtpad"&&obj.shape==="circle"){let radius=getRadiusOfCircuitJsonElement(obj),gap2=segmentToCircleMinDistance({x:segmentA.x1,y:segmentA.y1},{x:segmentA.x2,y:segmentA.y2},{x:obj.x,y:obj.y,radius})-segmentA.thickness/2;if(gap2>DEFAULT_TRACE_MARGIN-EPSILON)continue;let pcb_trace_error_id=`overlap_${segmentA.pcb_trace_id}_${primaryObjId}`;if(errorIds.has(pcb_trace_error_id))continue;errorIds.add(pcb_trace_error_id),errors.push({type:"pcb_trace_error",error_type:"pcb_trace_error",message:`PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${obj.type} "${getReadableName(getPrimaryId(obj))}" ${gap2<0?"(accidental contact)":`(gap: ${gap2.toFixed(3)}mm)`}`,pcb_trace_id:segmentA.pcb_trace_id,center:getClosestPointBetweenSegmentAndBounds(segmentA,getCollidableBounds(obj)),source_trace_id:"",pcb_trace_error_id,pcb_component_ids:["pcb_component_id"in obj?obj.pcb_component_id:void 0].filter(Boolean),pcb_port_ids:[...getPcbPortIdsConnectedToTraces([segmentA._pcbTrace]),"pcb_port_id"in obj?obj.pcb_port_id:void 0].filter(Boolean)})}let gap=segmentToBoundsMinDistance({x:segmentA.x1,y:segmentA.y1},{x:segmentA.x2,y:segmentA.y2},getCollidableBounds(obj))-segmentA.thickness/2;if(gap+EPSILON<requiredMargin){let pcb_trace_error_id=`overlap_${segmentA.pcb_trace_id}_${primaryObjId}`;if(errorIds.has(pcb_trace_error_id))continue;errorIds.add(pcb_trace_error_id),errors.push({type:"pcb_trace_error",error_type:"pcb_trace_error",message:`PCB trace ${getReadableName(segmentA.pcb_trace_id)} overlaps with ${obj.type} "${getReadableName(getPrimaryId(obj))}" ${gap<0?"(accidental contact)":`(gap: ${gap.toFixed(3)}mm)`}`,pcb_trace_id:segmentA.pcb_trace_id,source_trace_id:"",pcb_trace_error_id,pcb_component_ids:["pcb_component_id"in obj?obj.pcb_component_id:void 0].filter(Boolean),center:getClosestPointBetweenSegmentAndBounds(segmentA,getCollidableBounds(obj)),pcb_port_ids:[...getPcbPortIdsConnectedToTraces([segmentA._pcbTrace]),"pcb_port_id"in obj?obj.pcb_port_id:void 0].filter(Boolean)})}}}return errors}function isPolygonCCW(poly){return poly.area()>=0}function rectanglePolygon({center:center2,size:size2,rotationDeg=0}){let cx2=center2.x,cy2=center2.y,hw2=size2.width/2,hh2=size2.height/2,corners=[new Point$3(cx2-hw2,cy2-hh2),new Point$3(cx2+hw2,cy2-hh2),new Point$3(cx2+hw2,cy2+hh2),new Point$3(cx2-hw2,cy2+hh2)],poly=new Polygon$1(corners);if(rotationDeg){let matrix2=rotateDEG2(rotationDeg,cx2,cy2),rotatedCorners=corners.map(pt4=>{let p4=applyToPoint2(matrix2,{x:pt4.x,y:pt4.y});return new Point$3(p4.x,p4.y)});poly=new Polygon$1(rotatedCorners)}return isPolygonCCW(poly)||poly.reverse(),poly}function boardToPolygon({board}){if(board.outline&&board.outline.length>0){let points=board.outline.map(p4=>new Point$3(p4.x,p4.y)),poly=new Polygon$1(points);return isPolygonCCW(poly)||poly.reverse(),poly}return board.center&&typeof board.width=="number"&&typeof board.height=="number"?rectanglePolygon({center:board.center,size:{width:board.width,height:board.height},rotationDeg:0}):null}function getComponentName({circuitJson,component}){if(component.source_component_id){let sourceComponent=circuitJson.find(el2=>el2.type==="source_component"&&el2.source_component_id===component.source_component_id);if(sourceComponent&&"name"in sourceComponent&&sourceComponent.name)return sourceComponent.name}return getReadableNameForElement(circuitJson,component.pcb_component_id)||"Unknown"}function computeOverlapDistance(compPoly,boardPoly,componentCenter,componentWidth,componentHeight,rotationDeg){let centerPoint=new Point$3(componentCenter.x,componentCenter.y);if(!boardPoly.contains(centerPoint)){let dist=boardPoly.distanceTo(centerPoint);return Array.isArray(dist)?dist[0]:Number(dist)||0}let hw2=componentWidth/2,hh2=componentHeight/2,corners=[{x:componentCenter.x-hw2,y:componentCenter.y-hh2},{x:componentCenter.x+hw2,y:componentCenter.y-hh2},{x:componentCenter.x+hw2,y:componentCenter.y+hh2},{x:componentCenter.x-hw2,y:componentCenter.y+hh2}],midpoints=[];for(let i2=0;i2<4;i2++){let next2=(i2+1)%4;midpoints.push({x:(corners[i2].x+corners[next2].x)/2,y:(corners[i2].y+corners[next2].y)/2})}let matrix2=rotateDEG2(rotationDeg,componentCenter.x,componentCenter.y),rotatePoint5=pt4=>{let p4=applyToPoint2(matrix2,pt4);return new Point$3(p4.x,p4.y)},rotatedPoints=corners.concat(midpoints).map(rotatePoint5),maxDistance=0;for(let pt4 of rotatedPoints)if(!boardPoly.contains(pt4)){let dist=boardPoly.distanceTo(pt4),d3=Array.isArray(dist)?dist[0]:Number(dist)||0;d3>maxDistance&&(maxDistance=d3)}if(maxDistance>0)return maxDistance;try{let intersection=BooleanOperations.intersect(compPoly,boardPoly),intersectionArea=0;intersection?Array.isArray(intersection)?intersectionArea=intersection.reduce((sum,p4)=>sum+(typeof p4.area=="function"?p4.area():0),0):typeof intersection.area=="function"?intersectionArea=intersection.area():intersectionArea=0:intersectionArea=0;let compArea=compPoly.area();if(intersectionArea>0&&intersectionArea<compArea){let overlapRatio=1-intersectionArea/compArea,compWidth=Math.abs(componentWidth),compHeight=Math.abs(componentHeight);return Math.min(compWidth,compHeight)*overlapRatio}else return .1}catch{return .1}}function checkPcbComponentsOutOfBoard(circuitJson){let board=circuitJson.find(el2=>el2.type==="pcb_board");if(!board)return[];let boardPoly=boardToPolygon({board});if(!boardPoly)return[];let components=circuitJson.filter(el2=>el2.type==="pcb_component");if(components.length===0)return[];let errors=[];for(let c3 of components){if(!c3.center||typeof c3.width!="number"||typeof c3.height!="number"||c3.width<=0||c3.height<=0)continue;let compPoly=rectanglePolygon({center:c3.center,size:{width:c3.width,height:c3.height},rotationDeg:c3.rotation||0});if(compPoly.area()===0||boardPoly.contains(compPoly))continue;let overlapDistance=computeOverlapDistance(compPoly,boardPoly,c3.center,c3.width,c3.height,c3.rotation||0),compName=getComponentName({circuitJson,component:c3}),overlapDistanceMm=Math.round(overlapDistance*100)/100;errors.push({type:"pcb_component_outside_board_error",error_type:"pcb_component_outside_board_error",pcb_component_outside_board_error_id:`pcb_component_outside_board_${c3.pcb_component_id}`,message:`Component ${compName} (${c3.pcb_component_id}) extends outside board boundaries by ${overlapDistanceMm}mm`,pcb_component_id:c3.pcb_component_id,pcb_board_id:board.pcb_board_id,component_center:c3.center,component_bounds:{min_x:compPoly.box.xmin,max_x:compPoly.box.xmax,min_y:compPoly.box.ymin,max_y:compPoly.box.ymax},subcircuit_id:c3.subcircuit_id,source_component_id:c3.source_component_id})}return errors}function distance22(a2,b3){return Math.hypot(a2.x-b3.x,a2.y-b3.y)}function checkSameNetViaSpacing(circuitJson,{connMap,minSpacing=DEFAULT_SAME_NET_VIA_MARGIN}={}){let vias=circuitJson.filter(el2=>el2.type==="pcb_via");if(vias.length<2)return[];connMap??(connMap=getFullConnectivityMapFromCircuitJson(circuitJson));let errors=[],reported=new Set;for(let i2=0;i2<vias.length;i2++)for(let j4=i2+1;j4<vias.length;j4++){let viaA=vias[i2],viaB=vias[j4];if(!connMap.areIdsConnected(viaA.pcb_via_id,viaB.pcb_via_id))continue;let gap=distance22(viaA,viaB)-viaA.outer_diameter/2-viaB.outer_diameter/2;if(gap+EPSILON>=minSpacing)continue;let pairId=[viaA.pcb_via_id,viaB.pcb_via_id].sort().join("_");reported.has(pairId)||(reported.add(pairId),errors.push({type:"pcb_via_clearance_error",pcb_error_id:`same_net_vias_close_${pairId}`,message:`Vias ${getReadableNameForElement(circuitJson,viaA.pcb_via_id)} and ${getReadableNameForElement(circuitJson,viaB.pcb_via_id)} are too close together (gap: ${gap.toFixed(3)}mm)`,error_type:"pcb_via_clearance_error",pcb_via_ids:[viaA.pcb_via_id,viaB.pcb_via_id],minimum_clearance:minSpacing,actual_clearance:gap,pcb_center:{x:(viaA.x+viaB.x)/2,y:(viaA.y+viaB.y)/2}}))}return errors}function distance32(a2,b3){return Math.hypot(a2.x-b3.x,a2.y-b3.y)}function checkDifferentNetViaSpacing(circuitJson,{connMap,minSpacing=DEFAULT_DIFFERENT_NET_VIA_MARGIN}={}){let vias=circuitJson.filter(el2=>el2.type==="pcb_via");if(vias.length<2)return[];connMap??(connMap=getFullConnectivityMapFromCircuitJson(circuitJson));let errors=[],reported=new Set;for(let i2=0;i2<vias.length;i2++)for(let j4=i2+1;j4<vias.length;j4++){let viaA=vias[i2],viaB=vias[j4];if(connMap.areIdsConnected(viaA.pcb_via_id,viaB.pcb_via_id))continue;let gap=distance32(viaA,viaB)-viaA.outer_diameter/2-viaB.outer_diameter/2;if(gap+EPSILON>=minSpacing)continue;let pairId=[viaA.pcb_via_id,viaB.pcb_via_id].sort().join("_");reported.has(pairId)||(reported.add(pairId),errors.push({type:"pcb_via_clearance_error",pcb_error_id:`different_net_vias_close_${pairId}`,message:`Vias ${getReadableNameForElement(circuitJson,viaA.pcb_via_id)} and ${getReadableNameForElement(circuitJson,viaB.pcb_via_id)} from different nets are too close together (gap: ${gap.toFixed(3)}mm)`,error_type:"pcb_via_clearance_error",pcb_via_ids:[viaA.pcb_via_id,viaB.pcb_via_id],minimum_clearance:minSpacing,actual_clearance:gap,pcb_center:{x:(viaA.x+viaB.x)/2,y:(viaA.y+viaB.y)/2}}))}return errors}var DEFAULT_BOARD_MARGIN=.2;function getBoardPolygonPoints(board){if(board.outline&&board.outline.length>0)return board.outline.map(p4=>({x:p4.x,y:p4.y}));if(board.center&&typeof board.width=="number"&&typeof board.height=="number"){let cx2=board.center.x,cy2=board.center.y,hw2=board.width/2,hh2=board.height/2;return[{x:cx2-hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2-hh2},{x:cx2+hw2,y:cy2+hh2},{x:cx2-hw2,y:cy2+hh2}]}return null}function checkPcbTracesOutOfBoard(circuitJson,config={}){let errors=[],margin=config.margin??DEFAULT_BOARD_MARGIN,board=circuitJson.find(el2=>el2.type==="pcb_board");if(!board)return errors;let boardPoints=getBoardPolygonPoints(board);if(!boardPoints)return errors;let pcbTraces=cju_default(circuitJson).pcb_trace.list();for(let trace of pcbTraces)if(!(trace.route.length<2))for(let i2=0;i2<trace.route.length-1;i2++){let p12=trace.route[i2],p22=trace.route[i2+1];if(p12.route_type!=="wire"||p22.route_type!=="wire")continue;let traceWidth="width"in p12?p12.width:"width"in p22?p22.width:.1,segmentStart={x:p12.x,y:p12.y},segmentEnd={x:p22.x,y:p22.y},minDistance=1/0;for(let j4=0;j4<boardPoints.length;j4++){let edgeStart=boardPoints[j4],edgeEnd=boardPoints[(j4+1)%boardPoints.length],distance52=segmentToSegmentMinDistance(segmentStart,segmentEnd,edgeStart,edgeEnd);distance52<minDistance&&(minDistance=distance52)}let minimumDistance=traceWidth/2+margin;if(minDistance<minimumDistance){let error={type:"pcb_trace_error",error_type:"pcb_trace_error",pcb_trace_error_id:`trace_too_close_to_board_${trace.pcb_trace_id}_segment_${i2}`,message:`Trace too close to board edge (${minDistance.toFixed(3)}mm < ${minimumDistance.toFixed(3)}mm required, margin: ${margin}mm)`,pcb_trace_id:trace.pcb_trace_id,source_trace_id:trace.source_trace_id||"",center:{x:(segmentStart.x+segmentEnd.x)/2,y:(segmentStart.y+segmentEnd.y)/2},pcb_component_ids:[],pcb_port_ids:[]};errors.push(error)}}return errors}function doPcbElementsOverlap(elem1,elem2){let bounds1=getBoundsOfPcbElements([elem1]),bounds2=getBoundsOfPcbElements([elem2]);return doBoundsOverlap(bounds1,bounds2)}function checkPcbComponentOverlap(circuitJson){let errors=[],connMap=getFullConnectivityMapFromCircuitJson(circuitJson),smtPads=cju_default(circuitJson).pcb_smtpad.list(),platedHoles=cju_default(circuitJson).pcb_plated_hole.list(),holes=cju_default(circuitJson).pcb_hole.list(),componentMap=new Map;for(let pad2 of smtPads){let componentId=pad2.pcb_component_id||`standalone_pad_${getPrimaryId(pad2)}`;componentMap.has(componentId)||componentMap.set(componentId,{component_id:componentId,elements:[],bounds:{minX:0,minY:0,maxX:0,maxY:0}}),componentMap.get(componentId).elements.push(pad2)}for(let hole of platedHoles){let componentId=hole.pcb_component_id||`standalone_plated_hole_${getPrimaryId(hole)}`;componentMap.has(componentId)||componentMap.set(componentId,{component_id:componentId,elements:[],bounds:{minX:0,minY:0,maxX:0,maxY:0}}),componentMap.get(componentId).elements.push(hole)}for(let hole of holes){let componentId=`standalone_hole_${getPrimaryId(hole)}`;componentMap.set(componentId,{component_id:componentId,elements:[hole],bounds:{minX:0,minY:0,maxX:0,maxY:0}})}for(let[componentId,componentData]of componentMap)componentData.elements.length>0&&(componentData.bounds=getBoundsOfPcbElements(componentData.elements));let componentsWithElements=Array.from(componentMap.values());for(let i2=0;i2<componentsWithElements.length;i2++)for(let j4=i2+1;j4<componentsWithElements.length;j4++){let comp1=componentsWithElements[i2],comp2=componentsWithElements[j4];if(doBoundsOverlap(comp1.bounds,comp2.bounds))for(let elem1 of comp1.elements)for(let elem2 of comp2.elements){let id1=getPrimaryId(elem1),id2=getPrimaryId(elem2);if(!(elem1.type==="pcb_smtpad"&&elem2.type==="pcb_smtpad"&&connMap.areIdsConnected(id1,id2))&&doPcbElementsOverlap(elem1,elem2)){let error={type:"pcb_footprint_overlap_error",pcb_error_id:`pcb_footprint_overlap_${id1}_${id2}`,error_type:"pcb_footprint_overlap_error",message:`PCB component ${elem1.type} "${id1}" overlaps with ${elem2.type} "${id2}"`};(elem1.type==="pcb_smtpad"||elem2.type==="pcb_smtpad")&&(error.pcb_smtpad_ids=[],elem1.type==="pcb_smtpad"&&error.pcb_smtpad_ids.push(id1),elem2.type==="pcb_smtpad"&&error.pcb_smtpad_ids.push(id2)),(elem1.type==="pcb_plated_hole"||elem2.type==="pcb_plated_hole")&&(error.pcb_plated_hole_ids=[],elem1.type==="pcb_plated_hole"&&error.pcb_plated_hole_ids.push(id1),elem2.type==="pcb_plated_hole"&&error.pcb_plated_hole_ids.push(id2)),(elem1.type==="pcb_hole"||elem2.type==="pcb_hole")&&(error.pcb_hole_ids=[],elem1.type==="pcb_hole"&&error.pcb_hole_ids.push(id1),elem2.type==="pcb_hole"&&error.pcb_hole_ids.push(id2)),errors.push(error)}}}return errors}function checkPinMustBeConnected(circuitJson){let errors=[],sourceComponents=circuitJson.filter(el2=>"source_component_id"in el2&&(el2.type==="source_component"||el2.type.startsWith("source_simple_"))),sourcePorts=circuitJson.filter(el2=>el2.type==="source_port"),sourceTraces=circuitJson.filter(el2=>el2.type==="source_trace"),connectedPortIds=new Set;for(let trace of sourceTraces)for(let portId of trace.connected_source_port_ids??[])connectedPortIds.add(portId);let componentInternalConnections=new Map;for(let component of sourceComponents)"internally_connected_source_port_ids"in component&&component.internally_connected_source_port_ids&&componentInternalConnections.set(component.source_component_id,component.internally_connected_source_port_ids);for(let internalGroups of componentInternalConnections.values())for(let group of internalGroups)if(group.some(portId=>connectedPortIds.has(portId)))for(let portId of group)connectedPortIds.add(portId);for(let port of sourcePorts)if(port.must_be_connected===!0&&!connectedPortIds.has(port.source_port_id)){let componentName=sourceComponents.find(c3=>c3.source_component_id===port.source_component_id)?.name??"Unknown";errors.push({type:"source_pin_must_be_connected_error",source_pin_must_be_connected_error_id:`source_pin_must_be_connected_error_${port.source_port_id}`,error_type:"source_pin_must_be_connected_error",message:`Port ${port.name} on ${componentName} must be connected but is floating`,source_component_id:port.source_component_id??"",source_port_id:port.source_port_id,subcircuit_id:port.subcircuit_id})}return errors}init_dist();init_dist();init_dist();init_dist();init_dist5();init_dist();init_dist4();init_dist2();init_dist();init_svg_path_commander();init_dist6();var import_react4=__toESM(require_react(),1);var import_debug18=__toESM(require_browser(),1),import_react5=__toESM(require_react(),1),import_react6=__toESM(require_react(),1);var import_jsx_runtime=__toESM(require_jsx_runtime(),1);var import_jsx_runtime2=__toESM(require_jsx_runtime(),1),import_jsx_runtime3=__toESM(require_jsx_runtime(),1);var import_jsx_runtime4=__toESM(require_jsx_runtime(),1);var import_jsx_runtime5=__toESM(require_jsx_runtime(),1);var import_jsx_runtime6=__toESM(require_jsx_runtime(),1),import_react7=__toESM(require_react(),1);var __defProp4=Object.defineProperty,__export3=(target,all)=>{for(var name in all)__defProp4(target,name,{get:all[name],enumerable:!0})},components_exports={};__export3(components_exports,{AnalogSimulation:()=>AnalogSimulation,Battery:()=>Battery,Board:()=>Board,Breakout:()=>Breakout,BreakoutPoint:()=>BreakoutPoint,CadAssembly:()=>CadAssembly,CadModel:()=>CadModel,Capacitor:()=>Capacitor,Chip:()=>Chip,Constraint:()=>Constraint3,CopperPour:()=>CopperPour,CopperText:()=>CopperText,Crystal:()=>Crystal,CurrentSource:()=>CurrentSource,Cutout:()=>Cutout,Diode:()=>Diode,FabricationNoteDimension:()=>FabricationNoteDimension,FabricationNotePath:()=>FabricationNotePath,FabricationNoteRect:()=>FabricationNoteRect,FabricationNoteText:()=>FabricationNoteText,Fiducial:()=>Fiducial,Footprint:()=>Footprint,Fuse:()=>Fuse,Group:()=>Group6,Hole:()=>Hole,Inductor:()=>Inductor,Interconnect:()=>Interconnect,Jumper:()=>Jumper,Keepout:()=>Keepout,Led:()=>Led,Mosfet:()=>Mosfet,Net:()=>Net,NetLabel:()=>NetLabel,NormalComponent:()=>NormalComponent3,OpAmp:()=>OpAmp,Panel:()=>Panel,PcbNoteDimension:()=>PcbNoteDimension,PcbNoteLine:()=>PcbNoteLine,PcbNotePath:()=>PcbNotePath,PcbNoteRect:()=>PcbNoteRect,PcbNoteText:()=>PcbNoteText,PcbTrace:()=>PcbTrace,PinHeader:()=>PinHeader,Pinout:()=>Pinout,PlatedHole:()=>PlatedHole,Port:()=>Port,Potentiometer:()=>Potentiometer,PowerSource:()=>PowerSource,PrimitiveComponent:()=>PrimitiveComponent2,PushButton:()=>PushButton,Renderable:()=>Renderable,Resistor:()=>Resistor,Resonator:()=>Resonator,SchematicArc:()=>SchematicArc,SchematicBox:()=>SchematicBox,SchematicCell:()=>SchematicCell,SchematicCircle:()=>SchematicCircle,SchematicLine:()=>SchematicLine,SchematicPath:()=>SchematicPath,SchematicRect:()=>SchematicRect,SchematicRow:()=>SchematicRow,SchematicTable:()=>SchematicTable,SchematicText:()=>SchematicText,SilkscreenCircle:()=>SilkscreenCircle,SilkscreenLine:()=>SilkscreenLine,SilkscreenPath:()=>SilkscreenPath,SilkscreenRect:()=>SilkscreenRect,SilkscreenText:()=>SilkscreenText,SmtPad:()=>SmtPad,SolderJumper:()=>SolderJumper,Subcircuit:()=>Subcircuit,Subpanel:()=>Subpanel,Switch:()=>Switch,Symbol:()=>SymbolComponent,TestPoint:()=>TestPoint,Trace:()=>Trace3,TraceHint:()=>TraceHint,Transistor:()=>Transistor,Via:()=>Via,VoltageProbe:()=>VoltageProbe,VoltageSource:()=>VoltageSource});var debug5=(0,import_debug6.default)("tscircuit:renderable"),orderedRenderPhases=["ReactSubtreesRender","InflateSubcircuitCircuitJson","SourceNameDuplicateComponentRemoval","PcbFootprintStringRender","InitializePortsFromChildren","CreateNetsFromProps","AssignFallbackProps","CreateTracesFromProps","CreateTracesFromNetLabels","CreateTraceHintsFromProps","SourceGroupRender","AssignNameToUnnamedComponents","SourceRender","SourceParentAttachment","PortMatching","OptimizeSelectorCache","SourceTraceRender","SourceAddConnectivityMapKey","SourceDesignRuleChecks","SimulationRender","SchematicComponentRender","SchematicPortRender","SymbolContainerRender","SchematicPrimitiveRender","SchematicSymbolResize","SchematicComponentSizeCalculation","SchematicLayout","SchematicTraceRender","SchematicReplaceNetLabelsWithSymbols","PanelBoardLayout","PcbComponentRender","PcbPrimitiveRender","PcbFootprintLayout","PcbPortRender","PcbPortAttachment","PcbComponentSizeCalculation","PcbComponentAnchorAlignment","PcbLayout","PcbBoardAutoSize","PanelLayout","PcbTraceHintRender","PcbManualTraceRender","PcbTraceRender","PcbRouteNetIslands","PcbCopperPourRender","PcbDesignRuleChecks","SilkscreenOverlapAdjustment","CadModelRender","PartsEngineRender","SimulationSpiceEngineRender"],renderPhaseIndexMap=new Map(orderedRenderPhases.map((phase,index)=>[phase,index])),asyncPhaseDependencies={PcbFootprintLayout:["PcbFootprintStringRender"],PcbComponentSizeCalculation:["PcbFootprintStringRender"],PcbLayout:["PcbFootprintStringRender"],PcbBoardAutoSize:["PcbFootprintStringRender"],PcbTraceHintRender:["PcbFootprintStringRender"],PcbManualTraceRender:["PcbFootprintStringRender"],PcbCopperPourRender:["PcbFootprintStringRender","PcbTraceRender","PcbRouteNetIslands"],PcbTraceRender:["PcbFootprintStringRender"],PcbRouteNetIslands:["PcbFootprintStringRender"],PcbDesignRuleChecks:["PcbFootprintStringRender"],SilkscreenOverlapAdjustment:["PcbFootprintStringRender"],CadModelRender:["PcbFootprintStringRender"],PartsEngineRender:["PcbFootprintStringRender"],PcbComponentAnchorAlignment:["PcbFootprintStringRender"]},globalRenderCounter=0,globalAsyncEffectCounter=0,Renderable=class _Renderable{constructor(props){__publicField(this,"renderPhaseStates");__publicField(this,"shouldBeRemoved",!1);__publicField(this,"children");__publicField(this,"isPcbPrimitive",!1);__publicField(this,"isSchematicPrimitive",!1);__publicField(this,"_renderId");__publicField(this,"_currentRenderPhase",null);__publicField(this,"_asyncEffects",[]);__publicField(this,"parent",null);this._renderId=`${globalRenderCounter++}`,this.children=[],this.renderPhaseStates={};for(let phase of orderedRenderPhases)this.renderPhaseStates[phase]={initialized:!1,dirty:!1}}_markDirty(phase){this.renderPhaseStates[phase].dirty=!0;let phaseIndex=renderPhaseIndexMap.get(phase);for(let i2=phaseIndex+1;i2<orderedRenderPhases.length;i2++)this.renderPhaseStates[orderedRenderPhases[i2]].dirty=!0;this.parent?._markDirty&&this.parent._markDirty(phase)}_queueAsyncEffect(effectName,effect){let asyncEffectId=`${this._renderId}:${globalAsyncEffectCounter++}`,asyncEffect={asyncEffectId,promise:effect(),phase:this._currentRenderPhase,effectName,complete:!1};this._asyncEffects.push(asyncEffect);let root=this._getRootCircuit();root&&root.emit("asyncEffect:start",{asyncEffectId,effectName,componentDisplayName:this.getString(),phase:asyncEffect.phase}),asyncEffect.promise.then(()=>{asyncEffect.complete=!0;let root2=this._getRootCircuit();root2&&root2.emit("asyncEffect:end",{asyncEffectId,effectName,componentDisplayName:this.getString(),phase:asyncEffect.phase})}).catch(error=>{console.error(`Async effect error in ${asyncEffect.phase} "${effectName}":
|
|
618
618
|
${error.stack}`),asyncEffect.complete=!0;let root2=this._getRootCircuit();root2&&root2.emit("asyncEffect:end",{asyncEffectId,effectName,componentDisplayName:this.getString(),phase:asyncEffect.phase,error:error.toString()})})}_emitRenderLifecycleEvent(phase,startOrEnd){debug5(`${phase}:${startOrEnd} ${this.getString()}`);let granular_event_type=`renderable:renderLifecycle:${phase}:${startOrEnd}`,eventPayload={renderId:this._renderId,componentDisplayName:this.getString(),type:granular_event_type},root=this._getRootCircuit();root&&(root.emit(granular_event_type,eventPayload),root.emit("renderable:renderLifecycle:anyEvent",{...eventPayload,type:granular_event_type}))}getString(){return this.constructor.name}_hasIncompleteAsyncEffects(){return this._asyncEffects.some(effect=>!effect.complete)?!0:this.children.some(child=>typeof child._hasIncompleteAsyncEffects=="function"?child._hasIncompleteAsyncEffects():!1)}_hasIncompleteAsyncEffectsInSubtreeForPhase(phase){for(let e4 of this._asyncEffects)if(!e4.complete&&e4.phase===phase)return!0;for(let child of this.children)if(child._hasIncompleteAsyncEffectsInSubtreeForPhase(phase))return!0;return!1}_hasIncompleteAsyncEffectsForPhase(phase){let root=this._getRootCircuit();return root?._hasIncompleteAsyncEffectsForPhase?root._hasIncompleteAsyncEffectsForPhase(phase):this._hasIncompleteAsyncEffectsInSubtreeForPhase(phase)}getCurrentRenderPhase(){return this._currentRenderPhase}getRenderGraph(){return{id:this._renderId,currentPhase:this._currentRenderPhase,renderPhaseStates:this.renderPhaseStates,shouldBeRemoved:this.shouldBeRemoved,children:this.children.map(child=>child.getRenderGraph())}}getTopLevelRenderable(){let current2=this;for(;current2.parent&¤t2.parent instanceof _Renderable;)current2=current2.parent;return current2}runRenderCycle(){for(let renderPhase of orderedRenderPhases)this.runRenderPhaseForChildren(renderPhase),this.runRenderPhase(renderPhase)}runRenderPhase(phase){this._currentRenderPhase=phase;let phaseState=this.renderPhaseStates[phase],isInitialized=phaseState.initialized,isDirty2=phaseState.dirty;if(!isInitialized&&this.shouldBeRemoved)return;if(this.shouldBeRemoved&&isInitialized){this._emitRenderLifecycleEvent(phase,"start"),this?.[`remove${phase}`]?.(),phaseState.initialized=!1,phaseState.dirty=!1,this._emitRenderLifecycleEvent(phase,"end");return}let prevPhaseIndex=renderPhaseIndexMap.get(phase)-1;if(prevPhaseIndex>=0){let prevPhase=orderedRenderPhases[prevPhaseIndex];if(this._asyncEffects.filter(e4=>e4.phase===prevPhase).some(e4=>!e4.complete))return}let deps=asyncPhaseDependencies[phase]||[];if(deps.length>0){for(let depPhase of deps)if(this._hasIncompleteAsyncEffectsForPhase(depPhase))return}if(this._emitRenderLifecycleEvent(phase,"start"),isInitialized){isDirty2&&(this?.[`update${phase}`]?.(),phaseState.dirty=!1),this._emitRenderLifecycleEvent(phase,"end");return}phaseState.dirty=!1,this?.[`doInitial${phase}`]?.(),phaseState.initialized=!0,this._emitRenderLifecycleEvent(phase,"end")}runRenderPhaseForChildren(phase){for(let child of this.children)child.runRenderPhaseForChildren(phase),child.runRenderPhase(phase)}_getRootCircuit(){return"root"in this?this.root??null:null}renderError(message){throw typeof message=="string"?new Error(message):new Error(JSON.stringify(message,null,2))}},catalogue={},extendCatalogue=objects=>{let altKeys=Object.fromEntries(Object.entries(objects).map(([key,v5])=>[key.toLowerCase(),v5]));Object.assign(catalogue,objects),Object.assign(catalogue,altKeys)},InvalidProps=class extends Error{constructor(componentName,originalProps,formattedError){let message,propsWithError=Object.keys(formattedError).filter(k4=>k4!=="_errors"),invalidPinLabelMessages=[],pinLabels=originalProps.pinLabels;if(pinLabels)for(let[pin,labelOrLabels]of Object.entries(pinLabels)){let labels=Array.isArray(labelOrLabels)?labelOrLabels:[labelOrLabels];for(let label of labels)typeof label=="string"&&(label.startsWith(" ")||label.endsWith(" "))&&invalidPinLabelMessages.push(`pinLabels.${pin} ("${label}" has leading or trailing spaces)`)}let propMessage=propsWithError.map(k4=>k4==="pinLabels"&&invalidPinLabelMessages.length>0?invalidPinLabelMessages.join(", "):formattedError[k4]._errors[0]?`${k4} (${formattedError[k4]._errors[0]})`:`${k4} (${JSON.stringify(formattedError[k4])})`).join(", ");"name"in originalProps?message=`Invalid props for ${componentName} "${originalProps.name}": ${propMessage}`:"footprint"in originalProps&&typeof originalProps.footprint=="string"?message=`Invalid props for ${componentName} (unnamed ${originalProps.footprint} component): ${propMessage}`:message=`Invalid props for ${componentName} (unnamed): ${propMessage}`,super(message),this.componentName=componentName,this.originalProps=originalProps,this.formattedError=formattedError}};function isMatchingSelector(component,selector){let idMatch=selector.match(/^#(\w+)/);if(idMatch)return component.props.id===idMatch[1];let classMatch=selector.match(/^\.(\w+)/);if(classMatch)return component.isMatchingNameOrAlias(classMatch[1]);let[type,...conditions]=selector.split(/(?=[#.[])/);return type==="pin"&&(type="port"),type&&type!=="*"&&component.lowercaseComponentName!==type.toLowerCase()?!1:conditions.every(condition=>{if(condition.startsWith("#"))return component.props.id===condition.slice(1);if(condition.startsWith("."))return component.isMatchingNameOrAlias(condition.slice(1));let match2=condition.match(/\[(\w+)=['"]?(.+?)['"]?\]/);if(!match2)return!0;let[,prop,value]=match2;return component.props[prop].toString()===value})}var defaultUnits={mm:1};function evaluateCalcString(input2,options){let{knownVariables,units:userUnits}=options,units={...defaultUnits,...userUnits??{}},expr=extractExpression(input2),tokens=tokenize2(expr,units);return parseExpression(tokens,knownVariables)}function extractExpression(raw){let trimmed=raw.trim();if(!trimmed.toLowerCase().startsWith("calc"))return trimmed;let match2=trimmed.match(/^calc\s*\((.*)\)$/is);if(!match2)throw new Error(`Invalid calc() expression: "${raw}"`);return match2[1].trim()}function tokenize2(expr,units){let tokens=[],i2=0,isDigit=ch2=>ch2>="0"&&ch2<="9",isIdentStart=ch2=>ch2>="A"&&ch2<="Z"||ch2>="a"&&ch2<="z"||ch2==="_",isIdentChar=ch2=>isIdentStart(ch2)||isDigit(ch2)||ch2===".";for(;i2<expr.length;){let ch2=expr[i2];if(ch2===" "||ch2===" "||ch2===`
|
|
619
|
-
`||ch2==="\r"){i2++;continue}if(isDigit(ch2)||ch2==="."&&i2+1<expr.length&&isDigit(expr[i2+1])){let start=i2;for(i2++;i2<expr.length;){let c3=expr[i2];if(isDigit(c3)||c3===".")i2++;else break}let numberText=expr.slice(start,i2),num=Number(numberText);if(Number.isNaN(num))throw new Error(`Invalid number: "${numberText}"`);let unitStart=i2;for(;i2<expr.length&&/[A-Za-z]/.test(expr[i2]);)i2++;if(i2>unitStart){let unitText=expr.slice(unitStart,i2),factor=units[unitText];if(factor==null)throw new Error(`Unknown unit: "${unitText}"`);num*=factor}tokens.push({type:"number",value:num});continue}if(isIdentStart(ch2)){let start=i2;for(i2++;i2<expr.length&&isIdentChar(expr[i2]);)i2++;let ident=expr.slice(start,i2);tokens.push({type:"identifier",value:ident});continue}if(ch2==="("||ch2===")"){tokens.push({type:"paren",value:ch2}),i2++;continue}if(ch2==="+"||ch2==="-"||ch2==="*"||ch2==="/"){tokens.push({type:"operator",value:ch2}),i2++;continue}throw new Error(`Unexpected character "${ch2}" in expression "${expr}"`)}return tokens}function parseExpression(tokens,vars){let index=0,peek=()=>tokens[index],consume=()=>tokens[index++],parsePrimary=()=>{let token=peek();if(!token)throw new Error("Unexpected end of expression");if(token.type==="number")return consume(),token.value;if(token.type==="identifier"){consume();let value=vars[token.value];if(value==null)throw new Error(`Unknown variable: "${token.value}"`);return value}if(token.type==="paren"&&token.value==="("){consume();let value=parseExpr(),next2=peek();if(!next2||next2.type!=="paren"||next2.value!==")")throw new Error('Expected ")"');return consume(),value}throw new Error(`Unexpected token "${token.value}"`)},parseFactor=()=>{let token=peek();if(token&&token.type==="operator"&&(token.value==="+"||token.value==="-")){consume();let value=parseFactor();return token.value==="+"?value:-value}return parsePrimary()},parseTerm=()=>{let value=parseFactor();for(;;){let token=peek();if(!token||token.type!=="operator"||token.value!=="*"&&token.value!=="/")break;consume();let rhs=parseFactor();token.value==="*"?value*=rhs:value/=rhs}return value},parseExpr=()=>{let value=parseTerm();for(;;){let token=peek();if(!token||token.type!=="operator"||token.value!=="+"&&token.value!=="-")break;consume();let rhs=parseTerm();token.value==="+"?value+=rhs:value-=rhs}return value},result=parseExpr();if(index<tokens.length){let leftover=tokens.slice(index).map(t5=>"value"in t5?t5.value:"?").join(" ");throw new Error(`Unexpected tokens at end of expression: ${leftover}`)}return result}var cssSelectPrimitiveComponentAdapter={isTag:node=>!0,getParent:node=>node.parent,getChildren:node=>node.children,getName:node=>node.lowercaseComponentName,getAttributeValue:(node,name)=>{if(name==="class"&&"getNameAndAliases"in node)return node.getNameAndAliases().join(" ");if(name==="name"&&node._parsedProps?.name)return node._parsedProps.name;if(node._parsedProps&&name in node._parsedProps){let value=node._parsedProps[name];return typeof value=="string"?value:value!=null?String(value):null}if(name in node){let value=node[name];return typeof value=="string"?value:value!=null?String(value):null}let reverseMap=node._attributeLowerToCamelNameMap;if(reverseMap){let camelCaseName=reverseMap[name];if(camelCaseName&&camelCaseName in node){let value=node[camelCaseName];return typeof value=="string"?value:value!=null?String(value):null}}return null},hasAttrib:(node,name)=>{if(name==="class")return!!node._parsedProps?.name;if(node._parsedProps&&name in node._parsedProps||name in node)return!0;let reverseMap=node._attributeLowerToCamelNameMap;if(reverseMap){let camelCaseName=reverseMap[name];if(camelCaseName&&camelCaseName in node)return!0}return!1},getSiblings:node=>node.parent?node.parent.children:[],prevElementSibling:node=>{if(!node.parent)return null;let siblings=node.parent.children,idx=siblings.indexOf(node);return idx>0?siblings[idx-1]:null},getText:()=>"",removeSubsets:nodes=>nodes.filter((node,i2)=>!nodes.some((other,j4)=>i2!==j4&&other!==node&&other.getDescendants().includes(node))),existsOne:(test,nodes)=>nodes.some(test),findAll:(test,nodes)=>{let result=[],recurse=node=>{test(node)&&result.push(node);for(let child of node.children)recurse(child)};for(let node of nodes)recurse(node);return result},findOne:(test,nodes)=>{for(let node of nodes){if(test(node))return node;let children=node.children;if(children.length>0){let result=cssSelectPrimitiveComponentAdapter.findOne(test,children);if(result)return result}}return null},equals:(a2,b3)=>a2._renderId===b3._renderId,isHovered:elem=>!1,isVisited:elem=>!1,isActive:elem=>!1},cssSelectPrimitiveComponentAdapterWithoutSubcircuits={...cssSelectPrimitiveComponentAdapter,getChildren:node=>node.children.filter(c3=>!c3.isSubcircuit)},cssSelectPrimitiveComponentAdapterOnlySubcircuits={...cssSelectPrimitiveComponentAdapter,getChildren:node=>node.children.filter(c3=>c3.isSubcircuit)},buildPlusMinusNetErrorMessage=(selector,component)=>{let netName=selector.split("net.")[1]?.split(/[ >]/)[0]??selector;return`Net names cannot contain "+" or "-" (component "${component?.componentName??"Unknown component"}" received "${netName}" via "${selector}"). Try using underscores instead, e.g. VCC_P`},preprocessSelector=(selector,component)=>{if(/net\.[^\s>]*\./.test(selector))throw new Error('Net names cannot contain a period, try using "sel.net..." to autocomplete with conventional net names, e.g. V3_3');if(/net\.[^\s>]*[+-]/.test(selector))throw new Error(buildPlusMinusNetErrorMessage(selector,component));if(/net\.[0-9]/.test(selector)){let match2=selector.match(/net\.([^ >]+)/),netName=match2?match2[1]:"";throw new Error(`Net name "${netName}" cannot start with a number, try using a prefix like "VBUS1"`)}return selector.replace(/ pin(?=[\d.])/g," port").replace(/ subcircuit\./g," group[isSubcircuit=true]").replace(/([^ ])\>([^ ])/g,"$1 > $2").replace(/(^|[ >])(?!pin\.)(?!port\.)(?!net\.)([A-Z][A-Za-z0-9_-]*)\.([A-Za-z0-9_-]+)/g,(_5,sep,name,pin)=>{let pinPart=/^\d+$/.test(pin)?`pin${pin}`:pin;return`${sep}.${name} > .${pinPart}`}).trim()},cssSelectOptionsInsideSubcircuit={adapter:cssSelectPrimitiveComponentAdapterWithoutSubcircuits,cacheResults:!0},PrimitiveComponent2=class extends Renderable{constructor(props){super(props);__publicField(this,"parent",null);__publicField(this,"children");__publicField(this,"childrenPendingRemoval");__publicField(this,"props");__publicField(this,"_parsedProps");__publicField(this,"externallyAddedAliases");__publicField(this,"isPrimitiveContainer",!1);__publicField(this,"canHaveTextChildren",!1);__publicField(this,"source_group_id",null);__publicField(this,"source_component_id",null);__publicField(this,"schematic_component_id",null);__publicField(this,"pcb_component_id",null);__publicField(this,"cad_component_id",null);__publicField(this,"fallbackUnassignedName");__publicField(this,"_cachedSelectAllQueries",new Map);__publicField(this,"_cachedSelectOneQueries",new Map);this.children=[],this.childrenPendingRemoval=[],this.props=props??{},this.externallyAddedAliases=[];let parsePropsResult=("partial"in this.config.zodProps?this.config.zodProps.partial({name:!0}):this.config.zodProps).safeParse(props??{});if(parsePropsResult.success)this._parsedProps=parsePropsResult.data;else throw new InvalidProps(this.lowercaseComponentName,this.props,parsePropsResult.error.format())}get config(){return{componentName:"",zodProps:external_exports.object({}).passthrough()}}get componentName(){return this.config.componentName}getInheritedProperty(propertyName){let current2=this;for(;current2;){if(current2._parsedProps&&propertyName in current2._parsedProps)return current2._parsedProps[propertyName];current2=current2.parent}if(this.root?.platform&&propertyName in this.root.platform)return this.root.platform[propertyName]}getInheritedMergedProperty(propertyName){let parentPropertyObject=this.parent?.getInheritedMergedProperty?.(propertyName),myPropertyObject=this._parsedProps?.[propertyName];return{...parentPropertyObject,...myPropertyObject}}get lowercaseComponentName(){return this.componentName.toLowerCase()}get isSubcircuit(){return!!this.props.subcircuit||this.lowercaseComponentName==="group"&&this?.parent?.isRoot}get isGroup(){return this.lowercaseComponentName==="group"}get name(){return this._parsedProps.name??this.fallbackUnassignedName}setProps(props){let newProps=this.config.zodProps.parse({...this.props,...props}),oldProps=this.props;this.props=newProps,this._parsedProps=this.config.zodProps.parse(props),this.onPropsChange({oldProps,newProps,changedProps:Object.keys(props)}),this.parent?.onChildChanged?.(this)}_getPcbRotationBeforeLayout(){let{pcbRotation}=this.props;return typeof pcbRotation=="string"?parseFloat(pcbRotation):pcbRotation??null}getResolvedPcbPositionProp(){return{pcbX:this._resolvePcbCoordinate(this._parsedProps.pcbX,"pcbX"),pcbY:this._resolvePcbCoordinate(this._parsedProps.pcbY,"pcbY")}}_resolvePcbCoordinate(rawValue,axis,options={}){if(rawValue==null)return 0;if(typeof rawValue=="number")return rawValue;if(typeof rawValue!="string")throw new Error(`Invalid ${axis} value for ${this.componentName}: ${String(rawValue)}`);let allowBoardVariables=options.allowBoardVariables??this._isNormalComponent===!0,includesBoardVariable=rawValue.includes("board."),knownVariables={};if(allowBoardVariables){let board=this._getBoard(),boardVariables=board?._getBoardCalcVariables()??{};if(includesBoardVariable&&!board)throw new Error(`Cannot resolve ${axis} for ${this.componentName}: no board found for board.* variables`);if(includesBoardVariable&&board&&Object.keys(boardVariables).length===0)throw new Error("Cannot do calculations based on board size when the board is auto-sized");Object.assign(knownVariables,boardVariables)}try{return evaluateCalcString(rawValue,{knownVariables})}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(`Invalid ${axis} value for ${this.componentName}: ${message}`)}}computePcbPropsTransform(){let rotation4=this._getPcbRotationBeforeLayout()??0,{pcbX,pcbY}=this.getResolvedPcbPositionProp();return compose(translate(pcbX,pcbY),rotate(rotation4*Math.PI/180))}_computePcbGlobalTransformBeforeLayout(){let manualPlacement=this.getSubcircuit()._getPcbManualPlacementForComponent(this);if(manualPlacement&&this.props.pcbX===void 0&&this.props.pcbY===void 0){let rotation4=this._getPcbRotationBeforeLayout()??0;return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),compose(translate(manualPlacement.x,manualPlacement.y),rotate(rotation4*Math.PI/180)))}if(this.isPcbPrimitive){let primitiveContainer=this.getPrimitiveContainer();if(primitiveContainer&&primitiveContainer._parsedProps.layer==="bottom")return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),flipY(),this.computePcbPropsTransform())}return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),this.computePcbPropsTransform())}getPrimitiveContainer(){return this.isPrimitiveContainer?this:this.parent?.getPrimitiveContainer?.()??null}_getSymbolAncestor(){let container=this.getPrimitiveContainer();return container?.componentName==="Symbol"?container:null}getParentNormalComponent(){let current2=this.parent;for(;current2;){if(current2.isPrimitiveContainer&¤t2.doInitialPcbComponentRender)return current2;current2=current2.parent}return null}emitSolderMaskMarginWarning(isCoveredWithSolderMask,solderMaskMargin){if(isCoveredWithSolderMask&&solderMaskMargin!==void 0){let parentNormalComponent=this.getParentNormalComponent();parentNormalComponent?.source_component_id&&this.root.db.source_property_ignored_warning.insert({source_component_id:parentNormalComponent.source_component_id,property_name:"solderMaskMargin",message:"solderMaskMargin is set but coveredWithSolderMask is true. When a component is fully covered with solder mask, a margin doesn't apply.",error_type:"source_property_ignored_warning"})}}_getPcbCircuitJsonBounds(){return{center:{x:0,y:0},bounds:{left:0,top:0,right:0,bottom:0},width:0,height:0}}_getPcbPrimitiveFlippedHelpers(){let container=this.getPrimitiveContainer(),isFlipped=container?container._parsedProps.layer==="bottom":!1;return{isFlipped,maybeFlipLayer:layer=>isFlipped?layer==="top"?"bottom":"top":layer}}_setPositionFromLayout(newCenter){throw new Error(`_setPositionFromLayout not implemented for ${this.componentName}`)}computeSchematicPropsTransform(){let{_parsedProps:props}=this;return compose(translate(props.schX??0,props.schY??0))}computeSchematicGlobalTransform(){let manualPlacementTransform=this._getSchematicGlobalManualPlacementTransform(this);return manualPlacementTransform||compose(this.parent?.computeSchematicGlobalTransform?.()??identity(),this.computeSchematicPropsTransform())}_getSchematicSymbolName(){let{_parsedProps:props}=this,base_symbol_name=this.config.schematicSymbolName,orientationRotationMap={horizontal:0,pos_left:0,neg_right:0,pos_right:180,neg_left:180,pos_top:270,neg_bottom:90,vertical:270,pos_bottom:90,neg_top:90},normalizedRotation=props.schOrientation!==void 0?orientationRotationMap[props.schOrientation]:props.schRotation;if(normalizedRotation===void 0&&(normalizedRotation=0),normalizedRotation=normalizedRotation%360,normalizedRotation<0&&(normalizedRotation+=360),props.schRotation!==void 0&&normalizedRotation%90!==0)throw new Error(`Schematic rotation ${props.schRotation} is not supported for ${this.componentName}`);let symbol_name_horz=`${base_symbol_name}_horz`,symbol_name_vert=`${base_symbol_name}_vert`,symbol_name_up=`${base_symbol_name}_up`,symbol_name_down=`${base_symbol_name}_down`,symbol_name_left=`${base_symbol_name}_left`,symbol_name_right=`${base_symbol_name}_right`;if(symbol_name_right in Vf&&normalizedRotation===0)return symbol_name_right;if(symbol_name_up in Vf&&normalizedRotation===90)return symbol_name_up;if(symbol_name_left in Vf&&normalizedRotation===180)return symbol_name_left;if(symbol_name_down in Vf&&normalizedRotation===270)return symbol_name_down;if(symbol_name_horz in Vf&&(normalizedRotation===0||normalizedRotation===180))return symbol_name_horz;if(symbol_name_vert in Vf&&(normalizedRotation===90||normalizedRotation===270))return symbol_name_vert;if(base_symbol_name in Vf)return base_symbol_name}_getSchematicSymbolNameOrThrow(){let symbol_name=this._getSchematicSymbolName();if(!symbol_name)throw new Error(`No schematic symbol found (given: "${this.config.schematicSymbolName}")`);return symbol_name}getSchematicSymbol(){let symbol_name=this._getSchematicSymbolName();return symbol_name?Vf[symbol_name]??null:null}_getPcbManualPlacementForComponent(component){if(!this.isSubcircuit)return null;let manualEdits=this.props.manualEdits;if(!manualEdits)return null;let placementConfigPositions=manualEdits?.pcb_placements;if(!placementConfigPositions)return null;for(let position2 of placementConfigPositions)if(isMatchingSelector(component,position2.selector)||component.props.name===position2.selector)return applyToPoint(this._computePcbGlobalTransformBeforeLayout(),position2.center);return null}_getSchematicManualPlacementForComponent(component){if(!this.isSubcircuit)return null;let manualEdits=this.props.manualEdits;if(!manualEdits)return null;let placementConfigPositions=manualEdits.schematic_placements;if(!placementConfigPositions)return null;for(let position2 of placementConfigPositions)if(isMatchingSelector(component,position2.selector)||component.props.name===position2.selector)return applyToPoint(this.computeSchematicGlobalTransform(),position2.center);return null}_getSchematicGlobalManualPlacementTransform(component){let manualEdits=this.getSubcircuit()?._parsedProps.manualEdits;if(!manualEdits)return null;for(let position2 of manualEdits.schematic_placements??[])if((isMatchingSelector(component,position2.selector)||component.props.name===position2.selector)&&position2.relative_to==="group_center")return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),translate(position2.center.x,position2.center.y));return null}_getGlobalPcbPositionBeforeLayout(){return applyToPoint(this._computePcbGlobalTransformBeforeLayout(),{x:0,y:0})}_getGlobalSchematicPositionBeforeLayout(){return applyToPoint(this.computeSchematicGlobalTransform(),{x:0,y:0})}_getBoard(){let current2=this;for(;current2;){let maybePrimitive=current2;if(maybePrimitive.componentName==="Board")return maybePrimitive;current2=current2.parent??null}return this.root?._getBoard()}get root(){return this.parent?.root??null}onAddToParent(parent){this.parent=parent}onPropsChange(params){}onChildChanged(child){this.parent?.onChildChanged?.(child)}add(component){let textContent2=component.__text;if(typeof textContent2=="string"){if(this.canHaveTextChildren||textContent2.trim()==="")return;throw new Error(`Invalid JSX Element: Expected a React component but received text "${textContent2}"`)}if(Object.keys(component).length!==0){if(component.lowercaseComponentName==="panel")throw new Error("<panel> must be a root-level element");if(!component.onAddToParent)throw new Error(`Invalid JSX Element: Expected a React component but received "${JSON.stringify(component)}"`);component.onAddToParent(this),component.parent=this,this.children.push(component)}}addAll(components){for(let component of components)this.add(component)}remove(component){this.children=this.children.filter(c3=>c3!==component),this.childrenPendingRemoval.push(component),component.shouldBeRemoved=!0}getSubcircuitSelector(){let name=this.name,endPart=name?`${this.lowercaseComponentName}.${name}`:this.lowercaseComponentName;return!this.parent||this.parent.isSubcircuit?endPart:`${this.parent.getSubcircuitSelector()} > ${endPart}`}getFullPathSelector(){let name=this.name,endPart=name?`${this.lowercaseComponentName}.${name}`:this.lowercaseComponentName,parentSelector=this.parent?.getFullPathSelector?.();return parentSelector?`${parentSelector} > ${endPart}`:endPart}getNameAndAliases(){return[this.name,...this._parsedProps.portHints??[]].filter(Boolean)}isMatchingNameOrAlias(name){return this.getNameAndAliases().includes(name)}isMatchingAnyOf(aliases2){return this.getNameAndAliases().some(a2=>aliases2.map(a22=>a22.toString()).includes(a2))}getPcbSize(){throw new Error(`getPcbSize not implemented for ${this.componentName}`)}doesSelectorMatch(selector){let myTypeNames=[this.componentName,this.lowercaseComponentName],myClassNames=[this.name].filter(Boolean),parts=selector.trim().split(/\> /)[0],firstPart=parts[0];return parts.length>1?!1:!!(selector==="*"||selector[0]==="#"&&selector.slice(1)===this.props.id||selector[0]==="."&&myClassNames.includes(selector.slice(1))||/^[a-zA-Z0-9_]/.test(firstPart)&&myTypeNames.includes(firstPart))}getSubcircuit(){if(this.isSubcircuit)return this;let group=this.parent?.getSubcircuit?.();if(!group)throw new Error("Component is not inside an opaque group (no board?)");return group}getGroup(){return this.isGroup?this:this.parent?.getGroup?.()??null}doInitialAssignNameToUnnamedComponents(){this._parsedProps.name||(this.fallbackUnassignedName=this.getSubcircuit().getNextAvailableName(this))}doInitialOptimizeSelectorCache(){if(!this.isSubcircuit)return;let ports=this.selectAll("port");for(let port of ports){let parentAliases=(port.getParentNormalComponent?.()??port.parent)?.getNameAndAliases(),portAliases=port.getNameAndAliases();if(parentAliases)for(let parentAlias of parentAliases)for(let portAlias of portAliases){let selectors=[`.${parentAlias} > .${portAlias}`,`.${parentAlias} .${portAlias}`];for(let selector of selectors){let ar4=this._cachedSelectAllQueries.get(selector);ar4?ar4.push(port):this._cachedSelectAllQueries.set(selector,[port])}}}for(let[selector,ports2]of this._cachedSelectAllQueries.entries())ports2.length===1&&this._cachedSelectOneQueries.set(selector,ports2[0])}selectAll(selectorRaw){if(this._cachedSelectAllQueries.has(selectorRaw))return this._cachedSelectAllQueries.get(selectorRaw);let selector=preprocessSelector(selectorRaw,this),result=selectAll(selector,this,cssSelectOptionsInsideSubcircuit);if(result.length>0)return this._cachedSelectAllQueries.set(selectorRaw,result),result;let[firstpart,...rest]=selector.split(" "),subcircuit=selectOne(firstpart,this,{adapter:cssSelectPrimitiveComponentAdapterOnlySubcircuits});if(!subcircuit)return[];let result2=subcircuit.selectAll(rest.join(" "));return this._cachedSelectAllQueries.set(selectorRaw,result2),result2}selectOne(selectorRaw,options){if(this._cachedSelectOneQueries.has(selectorRaw))return this._cachedSelectOneQueries.get(selectorRaw);let selector=preprocessSelector(selectorRaw,this);options?.port&&(options.type="port");let result=null;if(options?.type&&(result=selectAll(selector,this,cssSelectOptionsInsideSubcircuit).find(n3=>n3.lowercaseComponentName===options.type)),result??(result=selectOne(selector,this,cssSelectOptionsInsideSubcircuit)),result)return this._cachedSelectOneQueries.set(selectorRaw,result),result;let[firstpart,...rest]=selector.split(" "),subcircuit=selectOne(firstpart,this,{adapter:cssSelectPrimitiveComponentAdapterOnlySubcircuits});return subcircuit?(result=subcircuit.selectOne(rest.join(" "),options),this._cachedSelectOneQueries.set(selectorRaw,result),result):null}getAvailablePcbLayers(){if(this.isPcbPrimitive){let{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers();return"layer"in this._parsedProps||this.componentName==="SmtPad"?[maybeFlipLayer(this._parsedProps.layer??"top")]:"layers"in this._parsedProps?this._parsedProps.layers:this.componentName==="PlatedHole"?[...this.root?._getBoard()?.allLayers??["top","bottom"]]:[]}return[]}getDescendants(){let descendants=[];for(let child of this.children)descendants.push(child),descendants.push(...child.getDescendants());return descendants}getSelectableDescendants(){let descendants=[];for(let child of this.children)child.isSubcircuit?descendants.push(child):(descendants.push(child),descendants.push(...child.getSelectableDescendants()));return descendants}_getPinCount(){return 0}_getSchematicBoxDimensions(){return null}_getSchematicBoxComponentDimensions(){if(this.getSchematicSymbol()||!this.config.shouldRenderAsSchematicBox)return null;let{_parsedProps:props}=this;return{schWidth:props.schWidth,schHeight:props.schHeight}}renderError(message){if(typeof message=="string")return super.renderError(message);switch(message.type){case"pcb_placement_error":this.root?.db.pcb_placement_error.insert(message);break;case"pcb_via_clearance_error":this.root?.db.pcb_via_clearance_error.insert(message);break;case"pcb_trace_error":this.root?.db.pcb_trace_error.insert(message);break;case"pcb_manual_edit_conflict_warning":this.root?.db.pcb_manual_edit_conflict_warning.insert(message);break;default:this.root?.db.pcb_placement_error.insert(message)}}getString(){let{lowercaseComponentName:cname,_parsedProps:props,parent}=this;return props?.pinNumber!==void 0&&parent?.props?.name&&props?.name?`<${cname}#${this._renderId}(pin:${props.pinNumber} .${parent?.props.name}>.${props.name}) />`:parent?.props?.name&&props?.name?`<${cname}#${this._renderId}(.${parent?.props.name}>.${props?.name}) />`:props?.from&&props?.to?`<${cname}#${this._renderId}(from:${props.from} to:${props?.to}) />`:props?.name?`<${cname}#${this._renderId} name=".${props?.name}" />`:props?.portHints?`<${cname}#${this._renderId}(${props.portHints.map(ph2=>`.${ph2}`).join(", ")}) />`:`<${cname}#${this._renderId} />`}get[Symbol.toStringTag](){return this.getString()}[Symbol.for("nodejs.util.inspect.custom")](){return this.getString()}},ErrorPlaceholderComponent=class extends PrimitiveComponent2{constructor(props,error){super(props);let resolveCoordinate=(value,axis)=>{if(typeof value=="number")return value;if(typeof value=="string")try{return this._resolvePcbCoordinate(value,axis,{allowBoardVariables:!1})}catch{return 0}return 0};this._parsedProps={...props,error,type:props.type||"unknown",component_name:props.name,error_type:"source_failed_to_create_component_error",message:error instanceof Error?error.message:String(error),pcbX:resolveCoordinate(props.pcbX,"pcbX"),pcbY:resolveCoordinate(props.pcbY,"pcbY"),schX:props.schX,schY:props.schY}}get config(){return{componentName:"ErrorPlaceholder",zodProps:external_exports.object({}).passthrough()}}doInitialSourceRender(){if(this.root?.db){let pcbPosition2=this._getGlobalPcbPositionBeforeLayout(),schematicPosition=this._getGlobalSchematicPositionBeforeLayout();this.root.db.source_failed_to_create_component_error.insert({component_name:this._parsedProps.component_name,error_type:"source_failed_to_create_component_error",message:`Could not create ${this._parsedProps.componentType??"component"}${this._parsedProps.name?` "${this._parsedProps.name}"`:""}. ${this._parsedProps.error?.formattedError?._errors?.join("; ")||this._parsedProps.message}`,pcb_center:pcbPosition2,schematic_center:schematicPosition})}}};function createErrorPlaceholderComponent(props,error){return new ErrorPlaceholderComponent(props,error)}function prepare(object,state2){let instance=object;return instance.__tsci={...state2},object}var hostConfig={supportsMutation:!0,createInstance(type,props){let target=catalogue[type];if(!target)throw Object.keys(catalogue).length===0?new Error("No components registered in catalogue, did you forget to import lib/register-catalogue in your test file?"):new Error(`Unsupported component type "${type}". No element with this name is registered in the @tscircuit/core catalogue. Check for typos or see https://docs.tscircuit.com/category/built-in-elements for a list of valid components. To add your own component, see docs/CREATING_NEW_COMPONENTS.md`);try{return prepare(new target(props),{})}catch(error){return createErrorPlaceholderComponent({...props,componentType:type},error)}},createTextInstance(text){return{__text:text}},appendInitialChild(parentInstance,child){parentInstance.add(child)},appendChild(parentInstance,child){parentInstance.add(child)},appendChildToContainer(container,child){container.add(child)},finalizeInitialChildren(){return!1},prepareUpdate(){return null},shouldSetTextContent(){return!1},getRootHostContext(){return{}},getChildHostContext(){return{}},prepareForCommit(){return null},resetAfterCommit(){},commitMount(){},commitUpdate(){},removeChild(){},clearContainer(){},supportsPersistence:!1,getPublicInstance(instance){return instance},preparePortalMount(containerInfo){throw new Error("Function not implemented.")},scheduleTimeout(fn3,delay){throw new Error("Function not implemented.")},cancelTimeout(id){throw new Error("Function not implemented.")},noTimeout:void 0,isPrimaryRenderer:!1,getInstanceFromNode(node){throw new Error("Function not implemented.")},beforeActiveInstanceBlur(){throw new Error("Function not implemented.")},afterActiveInstanceBlur(){throw new Error("Function not implemented.")},prepareScopeUpdate:(scopeInstance,instance)=>{throw new Error("Function not implemented.")},getInstanceFromScope:scopeInstance=>{throw new Error("Function not implemented.")},detachDeletedInstance:node=>{throw new Error("Function not implemented.")},getCurrentEventPriority:()=>import_constants.DefaultEventPriority,getCurrentUpdatePriority:()=>import_constants.DefaultEventPriority,resolveUpdatePriority:()=>import_constants.DefaultEventPriority,setCurrentUpdatePriority:()=>{},maySuspendCommit:()=>!1,supportsHydration:!1},reconciler=(0,import_react_reconciler.default)(hostConfig),createInstanceFromReactElement=reactElm=>{let rootContainer={children:[],props:{name:"$root"},add(instance){instance.parent=this,this.children.push(instance)},computePcbGlobalTransform(){return identity()}},containerErrors=[],container=reconciler.createContainer(rootContainer,0,null,!1,null,"tsci",error=>{console.log("Error in createContainer"),console.error(error),containerErrors.push(error)},null);if(reconciler.updateContainerSync(reactElm,container,null,()=>{}),reconciler.flushSyncWork(),containerErrors.length>0)throw containerErrors[0];let rootInstance=reconciler.getPublicRootInstance(container);return rootInstance||rootContainer.children[0]},parsePinNumberFromLabelsOrThrow=(pinNumberOrLabel,pinLabels)=>{if(typeof pinNumberOrLabel=="number")return pinNumberOrLabel;if(pinNumberOrLabel.startsWith("pin"))return Number(pinNumberOrLabel.slice(3));if(!pinLabels)throw new Error(`No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`);for(let pinNumberKey in pinLabels)if((Array.isArray(pinLabels[pinNumberKey])?pinLabels[pinNumberKey]:[pinLabels[pinNumberKey]]).includes(pinNumberOrLabel))return Number(pinNumberKey.replace("pin",""));throw new Error(`No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`)},underscorifyPinStyles=(pinStyles,pinLabels)=>{if(!pinStyles)return;let underscorePinStyles={},mergedStyles={};for(let[pinNameOrLabel,pinStyle]of Object.entries(pinStyles)){let pinNumber=parsePinNumberFromLabelsOrThrow(pinNameOrLabel,pinLabels);mergedStyles[pinNumber]={...mergedStyles[pinNumber],...pinStyle}}for(let[pinNumber,pinStyle]of Object.entries(mergedStyles)){let pinKey=`pin${pinNumber}`;underscorePinStyles[pinKey]={bottom_margin:pinStyle.bottomMargin,left_margin:pinStyle.leftMargin,right_margin:pinStyle.rightMargin,top_margin:pinStyle.topMargin}}return underscorePinStyles},underscorifyPortArrangement=portArrangement=>{if(portArrangement){if("leftSide"in portArrangement||"rightSide"in portArrangement||"topSide"in portArrangement||"bottomSide"in portArrangement)return{left_side:portArrangement.leftSide,right_side:portArrangement.rightSide,top_side:portArrangement.topSide,bottom_side:portArrangement.bottomSide};if("leftPinCount"in portArrangement||"rightPinCount"in portArrangement||"topPinCount"in portArrangement||"bottomPinCount"in portArrangement)return{left_size:portArrangement.leftPinCount,right_size:portArrangement.rightPinCount,top_size:portArrangement.topPinCount,bottom_size:portArrangement.bottomPinCount};if("leftSize"in portArrangement||"rightSize"in portArrangement||"topSize"in portArrangement||"bottomSize"in portArrangement)return{left_size:portArrangement.leftSize,right_size:portArrangement.rightSize,top_size:portArrangement.topSize,bottom_size:portArrangement.bottomSize}}};function pairs2(arr){let result=[];for(let i2=0;i2<arr.length-1;i2++)result.push([arr[i2],arr[i2+1]]);return result}var netProps2=external_exports.object({name:external_exports.string().refine(val=>!/[+-]/.test(val),val=>({message:`Net names cannot contain "+" or "-" (component "Net" received "${val}"). Try using underscores instead, e.g. VCC_P`}))}),Net=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"source_net_id");__publicField(this,"subcircuit_connectivity_map_key",null)}get config(){return{componentName:"Net",zodProps:netProps2}}getPortSelector(){return`net.${this.props.name}`}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,isGround=props.name.startsWith("GND"),isPositiveVoltageSource=props.name.startsWith("V"),net=db.source_net.insert({name:props.name,member_source_group_ids:[],is_ground:isGround,is_power:isPositiveVoltageSource,is_positive_voltage_source:isPositiveVoltageSource});this.source_net_id=net.source_net_id}doInitialSourceParentAttachment(){let subcircuit=this.getSubcircuit();if(!subcircuit)return;let{db}=this.root;db.source_net.update(this.source_net_id,{subcircuit_id:subcircuit.subcircuit_id})}getAllConnectedPorts(){let allPorts=this.getSubcircuit().selectAll("port"),connectedPorts=[];for(let port of allPorts){let traces=port._getDirectlyConnectedTraces();for(let trace of traces)if(trace._isExplicitlyConnectedToNet(this)){connectedPorts.push(port);break}}return connectedPorts}_getAllDirectlyConnectedTraces(){let allTraces=this.getSubcircuit().selectAll("trace"),connectedTraces=[];for(let trace of allTraces)trace._isExplicitlyConnectedToNet(this)&&connectedTraces.push(trace);return connectedTraces}doInitialPcbRouteNetIslands(){if(this.root?.pcbDisabled||this.getSubcircuit()._parsedProps.routingDisabled||this.getSubcircuit()._getAutorouterConfig().groupMode!=="sequential-trace")return;let{db}=this.root,{_parsedProps:props}=this,traces=this._getAllDirectlyConnectedTraces().filter(trace=>(trace._portsRoutedOnPcb?.length??0)>0),islands=[];for(let trace of traces){let tracePorts=trace._portsRoutedOnPcb,traceIsland=islands.find(island=>tracePorts.some(port=>island.ports.includes(port)));if(!traceIsland){islands.push({ports:[...tracePorts],traces:[trace]});continue}traceIsland.traces.push(trace),traceIsland.ports.push(...tracePorts)}if(islands.length===0)return;let islandPairs=pairs2(islands);for(let[A4,B5]of islandPairs){let Apositions=A4.ports.map(port=>port._getGlobalPcbPositionBeforeLayout()),Bpositions=B5.ports.map(port=>port._getGlobalPcbPositionBeforeLayout()),closestDist=1/0,closestPair=[-1,-1];for(let i2=0;i2<Apositions.length;i2++){let Apos=Apositions[i2];for(let j4=0;j4<Bpositions.length;j4++){let Bpos=Bpositions[j4],dist=Math.sqrt((Apos.x-Bpos.x)**2+(Apos.y-Bpos.y)**2);dist<closestDist&&(closestDist=dist,closestPair=[i2,j4])}}let Aport=A4.ports[closestPair[0]],Bport=B5.ports[closestPair[1]],pcbElements=db.toArray().filter(elm=>elm.type==="pcb_smtpad"||elm.type==="pcb_trace"||elm.type==="pcb_plated_hole"||elm.type==="pcb_hole"||elm.type==="source_port"||elm.type==="pcb_port"),{solution}=autoroute2(pcbElements.concat([{type:"source_trace",source_trace_id:"__net_trace_tmp",connected_source_port_ids:[Aport.source_port_id,Bport.source_port_id]}])),trace=solution[0];if(!trace){this.renderError({pcb_trace_error_id:"",pcb_trace_id:"__net_trace_tmp",pcb_component_ids:[Aport.pcb_component_id,Bport.pcb_component_id].filter(Boolean),pcb_port_ids:[Aport.pcb_port_id,Bport.pcb_port_id].filter(Boolean),type:"pcb_trace_error",error_type:"pcb_trace_error",message:`Failed to route net islands for "${this.getString()}"`,source_trace_id:"__net_trace_tmp"});return}db.pcb_trace.insert(trace)}}renderError(message){if(typeof message=="string")return super.renderError(message);this.root?.db.pcb_trace_error.insert(message)}},createNetsFromProps=(component,props)=>{for(let prop of props)if(typeof prop=="string"&&prop.startsWith("net.")){if(/net\.[^\s>]*\./.test(prop))throw new Error('Net names cannot contain a period, try using "sel.net..." to autocomplete with conventional net names, e.g. V3_3');if(/net\.[^\s>]*[+-]/.test(prop)){let netName=prop.split("net.")[1],message=`Net names cannot contain "+" or "-" (component "${component.componentName}" received "${netName}" via "${prop}"). Try using underscores instead, e.g. VCC_P`;throw new Error(message)}if(/net\.[0-9]/.test(prop)){let netName=prop.split("net.")[1];throw new Error(`Net name "${netName}" cannot start with a number, try using a prefix like "VBUS1"`)}let subcircuit=component.getSubcircuit();if(!subcircuit.selectOne(prop)){let net=new Net({name:prop.split("net.")[1]});subcircuit.add(net)}}},SmtPad=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_smtpad_id",null);__publicField(this,"matchedPort",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SmtPad",zodProps:smtPadProps}}getPcbSize(){let{_parsedProps:props}=this;if(props.shape==="circle")return{width:props.radius*2,height:props.radius*2};if(props.shape==="rect")return{width:props.width,height:props.height};if(props.shape==="rotated_rect"){let angleRad=(props.ccwRotation??0)*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),width=Math.abs(props.width*cosAngle)+Math.abs(props.height*sinAngle),height=Math.abs(props.width*sinAngle)+Math.abs(props.height*cosAngle);return{width,height}}if(props.shape==="polygon"){let points=props.points,xs3=points.map(p4=>p4.x),ys3=points.map(p4=>p4.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}if(props.shape==="pill")return{width:props.width,height:props.height};throw new Error(`getPcbSize for shape "${props.shape}" not implemented for ${this.componentName}`)}doInitialPortMatching(){let parentPorts=this.getPrimitiveContainer()?.selectAll("port");if(this.props.portHints){for(let port of parentPorts)if(port.isMatchingAnyOf(this.props.portHints)){this.matchedPort=port,port.registerMatch(this);return}}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,isCoveredWithSolderMask=props.coveredWithSolderMask??!1,shouldCreateSolderPaste=!isCoveredWithSolderMask,soldermaskMargin=props.solderMaskMargin;this.emitSolderMaskMarginWarning(isCoveredWithSolderMask,soldermaskMargin);let subcircuit=this.getSubcircuit(),position2=this._getGlobalPcbPositionBeforeLayout(),globalTransform=this._computePcbGlobalTransformBeforeLayout(),normalizedRotationDegrees=(decomposeTSR(this._computePcbGlobalTransformBeforeLayout()).rotation.angle*180/Math.PI%360+360)%360,rotationTolerance=.01,isAxisAligned=Math.abs(normalizedRotationDegrees)<rotationTolerance||Math.abs(normalizedRotationDegrees-180)<rotationTolerance||Math.abs(normalizedRotationDegrees-360)<rotationTolerance,isRotated90Degrees=Math.abs(normalizedRotationDegrees-90)<rotationTolerance||Math.abs(normalizedRotationDegrees-270)<rotationTolerance,finalRotationDegrees=Math.abs(normalizedRotationDegrees-360)<rotationTolerance?0:normalizedRotationDegrees,transformRotationBeforeFlip=finalRotationDegrees,{maybeFlipLayer,isFlipped}=this._getPcbPrimitiveFlippedHelpers();isFlipped&&(finalRotationDegrees=(360-finalRotationDegrees+360)%360);let portHints2=props.portHints?.map(ph2=>ph2.toString())??[],pcb_smtpad2=null,pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id;if(props.shape==="circle")pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"circle",radius:props.radius,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0}),shouldCreateSolderPaste&&db.pcb_solder_paste.insert({layer:pcb_smtpad2.layer,shape:"circle",radius:pcb_smtpad2.radius*.7,x:pcb_smtpad2.x,y:pcb_smtpad2.y,pcb_component_id:pcb_smtpad2.pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});else if(props.shape==="rect")!isAxisAligned&&!isRotated90Degrees?pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:props.width,height:props.height,corner_radius:props.cornerRadius??void 0,x:position2.x,y:position2.y,ccw_rotation:finalRotationDegrees,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}):pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"rect",width:isRotated90Degrees?props.height:props.width,height:isRotated90Degrees?props.width:props.height,corner_radius:props.cornerRadius??void 0,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),shouldCreateSolderPaste&&(pcb_smtpad2.shape==="rect"?db.pcb_solder_paste.insert({layer:maybeFlipLayer(props.layer??"top"),shape:"rect",width:pcb_smtpad2.width*.7,height:pcb_smtpad2.height*.7,x:pcb_smtpad2.x,y:pcb_smtpad2.y,pcb_component_id:pcb_smtpad2.pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}):pcb_smtpad2.shape==="rotated_rect"&&db.pcb_solder_paste.insert({layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:pcb_smtpad2.width*.7,height:pcb_smtpad2.height*.7,x:pcb_smtpad2.x,y:pcb_smtpad2.y,ccw_rotation:pcb_smtpad2.ccw_rotation,pcb_component_id:pcb_smtpad2.pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}));else if(props.shape==="rotated_rect"){let baseRotation=props.ccwRotation??0,combinedRotationBeforeFlip=(transformRotationBeforeFlip+baseRotation+360)%360,padRotation=isFlipped?(360-combinedRotationBeforeFlip+360)%360:combinedRotationBeforeFlip;pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:props.width,height:props.height,corner_radius:props.cornerRadius??void 0,x:position2.x,y:position2.y,ccw_rotation:padRotation,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),shouldCreateSolderPaste&&db.pcb_solder_paste.insert({layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:pcb_smtpad2.width*.7,height:pcb_smtpad2.height*.7,x:position2.x,y:position2.y,ccw_rotation:padRotation,pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else if(props.shape==="polygon"){let transformedPoints=props.points.map(point6=>{let transformed=applyToPoint(globalTransform,{x:distance.parse(point6.x),y:distance.parse(point6.y)});return{x:transformed.x,y:transformed.y}});pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"polygon",points:transformedPoints,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else props.shape==="pill"&&(pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"pill",x:position2.x,y:position2.y,radius:props.radius,height:props.height,width:props.width,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}));pcb_smtpad2&&(this.pcb_smtpad_id=pcb_smtpad2.pcb_smtpad_id)}doInitialPcbPortAttachment(){if(this.root?.pcbDisabled)return;let{db}=this.root;db.pcb_smtpad.update(this.pcb_smtpad_id,{pcb_port_id:this.matchedPort?.pcb_port_id})}_getPcbCircuitJsonBounds(){let{db}=this.root,smtpad2=db.pcb_smtpad.get(this.pcb_smtpad_id);if(smtpad2.shape==="rect")return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-smtpad2.width/2,top:smtpad2.y+smtpad2.height/2,right:smtpad2.x+smtpad2.width/2,bottom:smtpad2.y-smtpad2.height/2},width:smtpad2.width,height:smtpad2.height};if(smtpad2.shape==="rotated_rect"){let angleRad=smtpad2.ccw_rotation*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),w22=smtpad2.width/2,h22=smtpad2.height/2,xExtent=Math.abs(w22*cosAngle)+Math.abs(h22*sinAngle),yExtent=Math.abs(w22*sinAngle)+Math.abs(h22*cosAngle);return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-xExtent,right:smtpad2.x+xExtent,top:smtpad2.y-yExtent,bottom:smtpad2.y+yExtent},width:xExtent*2,height:yExtent*2}}if(smtpad2.shape==="circle")return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-smtpad2.radius,top:smtpad2.y-smtpad2.radius,right:smtpad2.x+smtpad2.radius,bottom:smtpad2.y+smtpad2.radius},width:smtpad2.radius*2,height:smtpad2.radius*2};if(smtpad2.shape==="polygon"){let points=smtpad2.points,xs3=points.map(p4=>p4.x),ys3=points.map(p4=>p4.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{center:{x:(minX+maxX)/2,y:(minY+maxY)/2},bounds:{left:minX,top:maxY,right:maxX,bottom:minY},width:maxX-minX,height:maxY-minY}}if(smtpad2.shape==="pill"){let halfWidth=smtpad2.width/2,halfHeight=smtpad2.height/2;return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-halfWidth,top:smtpad2.y-halfHeight,right:smtpad2.x+halfWidth,bottom:smtpad2.y+halfHeight},width:smtpad2.width,height:smtpad2.height}}throw new Error(`circuitJson bounds calculation not implemented for shape "${smtpad2.shape}"`)}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_smtpad.update(this.pcb_smtpad_id,{x:newCenter.x,y:newCenter.y});let solderPaste=db.pcb_solder_paste.list().find(elm=>elm.pcb_smtpad_id===this.pcb_smtpad_id);solderPaste&&db.pcb_solder_paste.update(solderPaste.pcb_solder_paste_id,{x:newCenter.x,y:newCenter.y}),this.matchedPort?._setPositionFromLayout(newCenter)}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_smtpad_id)return;let pad2=db.pcb_smtpad.get(this.pcb_smtpad_id);if(pad2.shape==="rect"||pad2.shape==="circle"||pad2.shape==="rotated_rect"||pad2.shape==="pill")this._setPositionFromLayout({x:pad2.x+deltaX,y:pad2.y+deltaY});else if(pad2.shape==="polygon"){db.pcb_smtpad.update(this.pcb_smtpad_id,{points:pad2.points.map(p4=>({x:p4.x+deltaX,y:p4.y+deltaY}))});let newCenter={x:this._getPcbCircuitJsonBounds().center.x+deltaX/2,y:this._getPcbCircuitJsonBounds().center.y+deltaY/2};this.matchedPort?._setPositionFromLayout(newCenter)}}},SilkscreenPath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_path_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenPath",zodProps:silkscreenPathProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=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 SilkscreenPath. Must be "top" or "bottom".`);let transform5=this._computePcbGlobalTransformBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_path2=db.pcb_silkscreen_path.insert({pcb_component_id,layer,route:props.route.map(p4=>{let transformedPosition=applyToPoint(transform5,{x:p4.x,y:p4.y});return{...p4,x:transformedPosition.x,y:transformedPosition.y}}),stroke_width:props.strokeWidth??.1,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_silkscreen_path_id=pcb_silkscreen_path2.pcb_silkscreen_path_id}_setPositionFromLayout(newCenter){let{db}=this.root,{_parsedProps:props}=this,currentPath=db.pcb_silkscreen_path.get(this.pcb_silkscreen_path_id);if(!currentPath)return;let currentCenterX=0,currentCenterY=0;for(let point6 of currentPath.route)currentCenterX+=point6.x,currentCenterY+=point6.y;currentCenterX/=currentPath.route.length,currentCenterY/=currentPath.route.length;let offsetX=newCenter.x-currentCenterX,offsetY=newCenter.y-currentCenterY,newRoute=currentPath.route.map(point6=>({...point6,x:point6.x+offsetX,y:point6.y+offsetY}));db.pcb_silkscreen_path.update(this.pcb_silkscreen_path_id,{route:newRoute})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_path_id)return;let path=db.pcb_silkscreen_path.get(this.pcb_silkscreen_path_id);path&&db.pcb_silkscreen_path.update(this.pcb_silkscreen_path_id,{route:path.route.map(p4=>({...p4,x:p4.x+deltaX,y:p4.y+deltaY}))})}getPcbSize(){let{_parsedProps:props}=this;if(!props.route||props.route.length===0)return{width:0,height:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of props.route)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{width:maxX-minX,height:maxY-minY}}},pcbTraceProps2=external_exports.object({route:external_exports.array(pcb_trace_route_point),source_trace_id:external_exports.string().optional()}),PcbTrace=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_trace_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbTrace",zodProps:pcbTraceProps2}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,container=this.getPrimitiveContainer(),subcircuit=this.getSubcircuit(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),parentTransform=this._computePcbGlobalTransformBeforeLayout(),transformedRoute=props.route.map(point6=>{let{x:x5,y:y5,...restOfPoint}=point6,transformedPoint=applyToPoint(parentTransform,{x:x5,y:y5});return point6.route_type==="wire"&&point6.layer?{...transformedPoint,...restOfPoint,layer:maybeFlipLayer(point6.layer)}:{...transformedPoint,...restOfPoint}}),pcb_trace2=db.pcb_trace.insert({pcb_component_id:container.pcb_component_id,source_trace_id:props.source_trace_id,route:transformedRoute,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_trace_id=pcb_trace2.pcb_trace_id}getPcbSize(){let{_parsedProps:props}=this;if(!props.route||props.route.length===0)return{width:0,height:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of props.route)minX=Math.min(minX,point6.x),maxX=Math.max(maxX,point6.x),minY=Math.min(minY,point6.y),maxY=Math.max(maxY,point6.y),point6.route_type==="wire"&&(minX=Math.min(minX,point6.x-point6.width/2),maxX=Math.max(maxX,point6.x+point6.width/2),minY=Math.min(minY,point6.y-point6.width/2),maxY=Math.max(maxY,point6.y+point6.width/2));return minX===1/0||maxX===-1/0||minY===1/0||maxY===-1/0?{width:0,height:0}:{width:maxX-minX,height:maxY-minY}}},PlatedHole=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_plated_hole_id",null);__publicField(this,"matchedPort",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PlatedHole",zodProps:platedHoleProps}}getAvailablePcbLayers(){return["top","inner1","inner2","bottom"]}getPcbSize(){let{_parsedProps:props}=this;if(props.shape==="circle")return{width:props.outerDiameter,height:props.outerDiameter};if(props.shape==="oval"||props.shape==="pill")return{width:props.outerWidth,height:props.outerHeight};if(props.shape==="circular_hole_with_rect_pad")return{width:props.rectPadWidth,height:props.rectPadHeight};if(props.shape==="pill_hole_with_rect_pad")return{width:props.rectPadWidth,height:props.rectPadHeight};if(props.shape==="hole_with_polygon_pad"){if(!props.padOutline||props.padOutline.length===0)throw new Error("padOutline is required for hole_with_polygon_pad shape");let xs3=props.padOutline.map(p4=>typeof p4.x=="number"?p4.x:parseFloat(String(p4.x))),ys3=props.padOutline.map(p4=>typeof p4.y=="number"?p4.y:parseFloat(String(p4.y))),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}throw new Error(`getPcbSize for shape "${props.shape}" not implemented for ${this.componentName}`)}_getPcbCircuitJsonBounds(){let{db}=this.root,platedHole=db.pcb_plated_hole.get(this.pcb_plated_hole_id),size2=this.getPcbSize();return{center:{x:platedHole.x,y:platedHole.y},bounds:{left:platedHole.x-size2.width/2,top:platedHole.y+size2.height/2,right:platedHole.x+size2.width/2,bottom:platedHole.y-size2.height/2},width:size2.width,height:size2.height}}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_plated_hole.update(this.pcb_plated_hole_id,{x:newCenter.x,y:newCenter.y}),this.matchedPort?._setPositionFromLayout(newCenter)}doInitialPortMatching(){let parentPorts=this.getPrimitiveContainer()?.selectAll("port");if(this.props.portHints){for(let port of parentPorts)if(port.isMatchingAnyOf(this.props.portHints)){this.matchedPort=port,port.registerMatch(this);return}}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,subcircuit=this.getSubcircuit(),soldermaskMargin=props.solderMaskMargin,isCoveredWithSolderMask=props.coveredWithSolderMask??!1;if(this.emitSolderMaskMarginWarning(isCoveredWithSolderMask,soldermaskMargin),props.shape==="circle"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,outer_diameter:props.outerDiameter,hole_diameter:props.holeDiameter,shape:"circle",port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id,db.pcb_solder_paste.insert({layer:"top",shape:"circle",radius:props.outerDiameter/2,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),db.pcb_solder_paste.insert({layer:"bottom",shape:"circle",radius:props.outerDiameter/2,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else if(props.shape==="pill"&&props.rectPad){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,outer_width:props.outerWidth,outer_height:props.outerHeight,hole_width:props.holeWidth,hole_height:props.holeHeight,shape:"rotated_pill_hole_with_rect_pad",type:"pcb_plated_hole",port_hints:this.getNameAndAliases(),pcb_plated_hole_id:this.pcb_plated_hole_id,x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,hole_shape:"rotated_pill",pad_shape:"rect",hole_ccw_rotation:props.pcbRotation??0,rect_ccw_rotation:props.pcbRotation??0,rect_pad_width:props.outerWidth,rect_pad_height:props.outerHeight,hole_offset_x:props.holeOffsetX,hole_offset_y:props.holeOffsetY});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}else if(props.shape==="pill"||props.shape==="oval"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,outer_width:props.outerWidth,outer_height:props.outerHeight,hole_width:props.holeWidth,hole_height:props.holeHeight,shape:props.shape,port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,ccw_rotation:props.pcbRotation??0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id,db.pcb_solder_paste.insert({layer:"top",shape:props.shape,width:props.outerWidth,height:props.outerHeight,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),db.pcb_solder_paste.insert({layer:"bottom",shape:props.shape,width:props.outerWidth,height:props.outerHeight,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else if(props.shape==="circular_hole_with_rect_pad"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,hole_diameter:props.holeDiameter,rect_pad_width:props.rectPadWidth,rect_pad_height:props.rectPadHeight,shape:"circular_hole_with_rect_pad",port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,hole_offset_x:props.holeOffsetX,hole_offset_y:props.holeOffsetY,rect_border_radius:props.rectBorderRadius??0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}else if(props.shape==="pill_hole_with_rect_pad"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,hole_width:props.holeWidth,hole_height:props.holeHeight,rect_pad_width:props.rectPadWidth,rect_pad_height:props.rectPadHeight,hole_offset_x:props.holeOffsetX,hole_offset_y:props.holeOffsetY,shape:"pill_hole_with_rect_pad",port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}else if(props.shape==="hole_with_polygon_pad"){let padOutline=(props.padOutline||[]).map(point6=>{let x5=typeof point6.x=="number"?point6.x:parseFloat(String(point6.x)),y5=typeof point6.y=="number"?point6.y:parseFloat(String(point6.y));return{x:x5,y:y5}}),pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,shape:"hole_with_polygon_pad",hole_shape:props.holeShape||"circle",hole_diameter:props.holeDiameter,hole_width:props.holeWidth,hole_height:props.holeHeight,pad_outline:padOutline,hole_offset_x:typeof props.holeOffsetX=="number"?props.holeOffsetX:parseFloat(String(props.holeOffsetX||0)),hole_offset_y:typeof props.holeOffsetY=="number"?props.holeOffsetY:parseFloat(String(props.holeOffsetY||0)),port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}}doInitialPcbPortAttachment(){if(this.root?.pcbDisabled)return;let{db}=this.root;db.pcb_plated_hole.update(this.pcb_plated_hole_id,{pcb_port_id:this.matchedPort?.pcb_port_id})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_plated_hole_id)return;let hole=db.pcb_plated_hole.get(this.pcb_plated_hole_id);if(hole){let newCenter={x:hole.x+deltaX,y:hole.y+deltaY};this._setPositionFromLayout(newCenter)}}},Keepout=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_keepout_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"Keepout",zodProps:pcbKeepoutProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let subcircuit=this.getSubcircuit(),{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),decomposedMat=decomposeTSR(this._computePcbGlobalTransformBeforeLayout()),isRotated90=Math.abs(decomposedMat.rotation.angle*(180/Math.PI)-90)%180<.01,pcb_keepout2=null;props.shape==="circle"?pcb_keepout2=db.pcb_keepout.insert({layers:["top"],shape:"circle",radius:props.radius,center:{x:position2.x,y:position2.y},subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0}):props.shape==="rect"&&(pcb_keepout2=db.pcb_keepout.insert({layers:["top"],shape:"rect",...isRotated90?{width:props.height,height:props.width}:{width:props.width,height:props.height},center:{x:position2.x,y:position2.y},subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0})),pcb_keepout2&&(this.pcb_keepout_id=pcb_keepout2.pcb_keepout_id)}},Hole=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_hole_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"Hole",zodProps:holeProps}}getPcbSize(){let{_parsedProps:props}=this,isPill=props.shape==="pill",isRect=props.shape==="rect";return isPill?{width:props.width,height:props.height}:isRect?{width:props.width,height:props.height}:{width:props.diameter,height:props.diameter}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,subcircuit=this.getSubcircuit(),position2=this._getGlobalPcbPositionBeforeLayout(),soldermaskMargin=props.solderMaskMargin,isCoveredWithSolderMask=props.coveredWithSolderMask??!1,pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id;if(this.emitSolderMaskMarginWarning(isCoveredWithSolderMask,soldermaskMargin),props.shape==="pill")if(props.pcbRotation&&props.pcbRotation!==0){let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"rotated_pill",hole_width:props.width,hole_height:props.height,x:position2.x,y:position2.y,ccw_rotation:props.pcbRotation,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}else{let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"pill",hole_width:props.width,hole_height:props.height,x:position2.x,y:position2.y,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}else if(props.shape==="rect"){let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"rect",hole_width:props.width,hole_height:props.height,x:position2.x,y:position2.y,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}else{let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"circle",hole_diameter:props.diameter,x:position2.x,y:position2.y,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}}_getPcbCircuitJsonBounds(){let{db}=this.root,hole=db.pcb_hole.get(this.pcb_hole_id),size2=this.getPcbSize();return{center:{x:hole.x,y:hole.y},bounds:{left:hole.x-size2.width/2,top:hole.y-size2.height/2,right:hole.x+size2.width/2,bottom:hole.y+size2.height/2},width:size2.width,height:size2.height}}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_hole.update(this.pcb_hole_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_hole_id)return;let hole=db.pcb_hole.get(this.pcb_hole_id);hole&&db.pcb_hole.update(this.pcb_hole_id,{x:hole.x+deltaX,y:hole.y+deltaY})}};function normalizeTextForCircuitJson(text){return text.replace(/\\n/g,`
|
|
619
|
+
`||ch2==="\r"){i2++;continue}if(isDigit(ch2)||ch2==="."&&i2+1<expr.length&&isDigit(expr[i2+1])){let start=i2;for(i2++;i2<expr.length;){let c3=expr[i2];if(isDigit(c3)||c3===".")i2++;else break}let numberText=expr.slice(start,i2),num=Number(numberText);if(Number.isNaN(num))throw new Error(`Invalid number: "${numberText}"`);let unitStart=i2;for(;i2<expr.length&&/[A-Za-z]/.test(expr[i2]);)i2++;if(i2>unitStart){let unitText=expr.slice(unitStart,i2),factor=units[unitText];if(factor==null)throw new Error(`Unknown unit: "${unitText}"`);num*=factor}tokens.push({type:"number",value:num});continue}if(isIdentStart(ch2)){let start=i2;for(i2++;i2<expr.length&&isIdentChar(expr[i2]);)i2++;let ident=expr.slice(start,i2);tokens.push({type:"identifier",value:ident});continue}if(ch2==="("||ch2===")"){tokens.push({type:"paren",value:ch2}),i2++;continue}if(ch2==="+"||ch2==="-"||ch2==="*"||ch2==="/"){tokens.push({type:"operator",value:ch2}),i2++;continue}throw new Error(`Unexpected character "${ch2}" in expression "${expr}"`)}return tokens}function parseExpression(tokens,vars){let index=0,peek=()=>tokens[index],consume=()=>tokens[index++],parsePrimary=()=>{let token=peek();if(!token)throw new Error("Unexpected end of expression");if(token.type==="number")return consume(),token.value;if(token.type==="identifier"){consume();let value=vars[token.value];if(value==null)throw new Error(`Unknown variable: "${token.value}"`);return value}if(token.type==="paren"&&token.value==="("){consume();let value=parseExpr(),next2=peek();if(!next2||next2.type!=="paren"||next2.value!==")")throw new Error('Expected ")"');return consume(),value}throw new Error(`Unexpected token "${token.value}"`)},parseFactor=()=>{let token=peek();if(token&&token.type==="operator"&&(token.value==="+"||token.value==="-")){consume();let value=parseFactor();return token.value==="+"?value:-value}return parsePrimary()},parseTerm=()=>{let value=parseFactor();for(;;){let token=peek();if(!token||token.type!=="operator"||token.value!=="*"&&token.value!=="/")break;consume();let rhs=parseFactor();token.value==="*"?value*=rhs:value/=rhs}return value},parseExpr=()=>{let value=parseTerm();for(;;){let token=peek();if(!token||token.type!=="operator"||token.value!=="+"&&token.value!=="-")break;consume();let rhs=parseTerm();token.value==="+"?value+=rhs:value-=rhs}return value},result=parseExpr();if(index<tokens.length){let leftover=tokens.slice(index).map(t5=>"value"in t5?t5.value:"?").join(" ");throw new Error(`Unexpected tokens at end of expression: ${leftover}`)}return result}var cssSelectPrimitiveComponentAdapter={isTag:node=>!0,getParent:node=>node.parent,getChildren:node=>node.children,getName:node=>node.lowercaseComponentName,getAttributeValue:(node,name)=>{if(name==="class"&&"getNameAndAliases"in node)return node.getNameAndAliases().join(" ");if(name==="name"&&node._parsedProps?.name)return node._parsedProps.name;if(node._parsedProps&&name in node._parsedProps){let value=node._parsedProps[name];return typeof value=="string"?value:value!=null?String(value):null}if(name in node){let value=node[name];return typeof value=="string"?value:value!=null?String(value):null}let reverseMap=node._attributeLowerToCamelNameMap;if(reverseMap){let camelCaseName=reverseMap[name];if(camelCaseName&&camelCaseName in node){let value=node[camelCaseName];return typeof value=="string"?value:value!=null?String(value):null}}return null},hasAttrib:(node,name)=>{if(name==="class")return!!node._parsedProps?.name;if(node._parsedProps&&name in node._parsedProps||name in node)return!0;let reverseMap=node._attributeLowerToCamelNameMap;if(reverseMap){let camelCaseName=reverseMap[name];if(camelCaseName&&camelCaseName in node)return!0}return!1},getSiblings:node=>node.parent?node.parent.children:[],prevElementSibling:node=>{if(!node.parent)return null;let siblings=node.parent.children,idx=siblings.indexOf(node);return idx>0?siblings[idx-1]:null},getText:()=>"",removeSubsets:nodes=>nodes.filter((node,i2)=>!nodes.some((other,j4)=>i2!==j4&&other!==node&&other.getDescendants().includes(node))),existsOne:(test,nodes)=>nodes.some(test),findAll:(test,nodes)=>{let result=[],recurse=node=>{test(node)&&result.push(node);for(let child of node.children)recurse(child)};for(let node of nodes)recurse(node);return result},findOne:(test,nodes)=>{for(let node of nodes){if(test(node))return node;let children=node.children;if(children.length>0){let result=cssSelectPrimitiveComponentAdapter.findOne(test,children);if(result)return result}}return null},equals:(a2,b3)=>a2._renderId===b3._renderId,isHovered:elem=>!1,isVisited:elem=>!1,isActive:elem=>!1},cssSelectPrimitiveComponentAdapterWithoutSubcircuits={...cssSelectPrimitiveComponentAdapter,getChildren:node=>node.children.filter(c3=>!c3.isSubcircuit)},cssSelectPrimitiveComponentAdapterOnlySubcircuits={...cssSelectPrimitiveComponentAdapter,getChildren:node=>node.children.filter(c3=>c3.isSubcircuit)},buildPlusMinusNetErrorMessage=(selector,component)=>{let netName=selector.split("net.")[1]?.split(/[ >]/)[0]??selector;return`Net names cannot contain "+" or "-" (component "${component?.componentName??"Unknown component"}" received "${netName}" via "${selector}"). Try using underscores instead, e.g. VCC_P`},preprocessSelector=(selector,component)=>{if(/net\.[^\s>]*\./.test(selector))throw new Error('Net names cannot contain a period, try using "sel.net..." to autocomplete with conventional net names, e.g. V3_3');if(/net\.[^\s>]*[+-]/.test(selector))throw new Error(buildPlusMinusNetErrorMessage(selector,component));if(/net\.[0-9]/.test(selector)){let match2=selector.match(/net\.([^ >]+)/),netName=match2?match2[1]:"";throw new Error(`Net name "${netName}" cannot start with a number, try using a prefix like "VBUS1"`)}return selector.replace(/ pin(?=[\d.])/g," port").replace(/ subcircuit\./g," group[isSubcircuit=true]").replace(/([^ ])\>([^ ])/g,"$1 > $2").replace(/(^|[ >])(?!pin\.)(?!port\.)(?!net\.)([A-Z][A-Za-z0-9_-]*)\.([A-Za-z0-9_-]+)/g,(_5,sep,name,pin)=>{let pinPart=/^\d+$/.test(pin)?`pin${pin}`:pin;return`${sep}.${name} > .${pinPart}`}).trim()},cssSelectOptionsInsideSubcircuit={adapter:cssSelectPrimitiveComponentAdapterWithoutSubcircuits,cacheResults:!0},PrimitiveComponent2=class extends Renderable{constructor(props){super(props);__publicField(this,"parent",null);__publicField(this,"children");__publicField(this,"childrenPendingRemoval");__publicField(this,"props");__publicField(this,"_parsedProps");__publicField(this,"externallyAddedAliases");__publicField(this,"isPrimitiveContainer",!1);__publicField(this,"canHaveTextChildren",!1);__publicField(this,"source_group_id",null);__publicField(this,"source_component_id",null);__publicField(this,"schematic_component_id",null);__publicField(this,"pcb_component_id",null);__publicField(this,"cad_component_id",null);__publicField(this,"fallbackUnassignedName");__publicField(this,"_cachedSelectAllQueries",new Map);__publicField(this,"_cachedSelectOneQueries",new Map);this.children=[],this.childrenPendingRemoval=[],this.props=props??{},this.externallyAddedAliases=[];let parsePropsResult=("partial"in this.config.zodProps?this.config.zodProps.partial({name:!0}):this.config.zodProps).safeParse(props??{});if(parsePropsResult.success)this._parsedProps=parsePropsResult.data;else throw new InvalidProps(this.lowercaseComponentName,this.props,parsePropsResult.error.format())}get config(){return{componentName:"",zodProps:external_exports.object({}).passthrough()}}get componentName(){return this.config.componentName}getInheritedProperty(propertyName){let current2=this;for(;current2;){if(current2._parsedProps&&propertyName in current2._parsedProps)return current2._parsedProps[propertyName];current2=current2.parent}if(this.root?.platform&&propertyName in this.root.platform)return this.root.platform[propertyName]}getInheritedMergedProperty(propertyName){let parentPropertyObject=this.parent?.getInheritedMergedProperty?.(propertyName),myPropertyObject=this._parsedProps?.[propertyName];return{...parentPropertyObject,...myPropertyObject}}get lowercaseComponentName(){return this.componentName.toLowerCase()}get isSubcircuit(){return!!this.props.subcircuit||this.lowercaseComponentName==="group"&&this?.parent?.isRoot}get isGroup(){return this.lowercaseComponentName==="group"}get name(){return this._parsedProps.name??this.fallbackUnassignedName}setProps(props){let newProps=this.config.zodProps.parse({...this.props,...props}),oldProps=this.props;this.props=newProps,this._parsedProps=this.config.zodProps.parse(props),this.onPropsChange({oldProps,newProps,changedProps:Object.keys(props)}),this.parent?.onChildChanged?.(this)}_getPcbRotationBeforeLayout(){let{pcbRotation}=this.props;return typeof pcbRotation=="string"?parseFloat(pcbRotation):pcbRotation??null}getResolvedPcbPositionProp(){return{pcbX:this._resolvePcbCoordinate(this._parsedProps.pcbX,"pcbX"),pcbY:this._resolvePcbCoordinate(this._parsedProps.pcbY,"pcbY")}}_resolvePcbCoordinate(rawValue,axis,options={}){if(rawValue==null)return 0;if(typeof rawValue=="number")return rawValue;if(typeof rawValue!="string")throw new Error(`Invalid ${axis} value for ${this.componentName}: ${String(rawValue)}`);let allowBoardVariables=options.allowBoardVariables??this._isNormalComponent===!0,includesBoardVariable=rawValue.includes("board."),knownVariables={};if(allowBoardVariables){let board=this._getBoard(),boardVariables=board?._getBoardCalcVariables()??{};if(includesBoardVariable&&!board)throw new Error(`Cannot resolve ${axis} for ${this.componentName}: no board found for board.* variables`);if(includesBoardVariable&&board&&Object.keys(boardVariables).length===0)throw new Error("Cannot do calculations based on board size when the board is auto-sized");Object.assign(knownVariables,boardVariables)}try{return evaluateCalcString(rawValue,{knownVariables})}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(`Invalid ${axis} value for ${this.componentName}: ${message}`)}}computePcbPropsTransform(){let rotation4=this._getPcbRotationBeforeLayout()??0,{pcbX,pcbY}=this.getResolvedPcbPositionProp();return compose(translate(pcbX,pcbY),rotate(rotation4*Math.PI/180))}_computePcbGlobalTransformBeforeLayout(){let manualPlacement=this.getSubcircuit()._getPcbManualPlacementForComponent(this);if(manualPlacement&&this.props.pcbX===void 0&&this.props.pcbY===void 0){let rotation4=this._getPcbRotationBeforeLayout()??0;return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),compose(translate(manualPlacement.x,manualPlacement.y),rotate(rotation4*Math.PI/180)))}if(this.isPcbPrimitive){let primitiveContainer=this.getPrimitiveContainer();if(primitiveContainer&&primitiveContainer._parsedProps.layer==="bottom")return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),flipY(),this.computePcbPropsTransform())}return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),this.computePcbPropsTransform())}getPrimitiveContainer(){return this.isPrimitiveContainer?this:this.parent?.getPrimitiveContainer?.()??null}_getSymbolAncestor(){let container=this.getPrimitiveContainer();return container?.componentName==="Symbol"?container:null}getParentNormalComponent(){let current2=this.parent;for(;current2;){if(current2.isPrimitiveContainer&¤t2.doInitialPcbComponentRender)return current2;current2=current2.parent}return null}emitSolderMaskMarginWarning(isCoveredWithSolderMask,solderMaskMargin){if(isCoveredWithSolderMask&&solderMaskMargin!==void 0){let parentNormalComponent=this.getParentNormalComponent();parentNormalComponent?.source_component_id&&this.root.db.source_property_ignored_warning.insert({source_component_id:parentNormalComponent.source_component_id,property_name:"solderMaskMargin",message:"solderMaskMargin is set but coveredWithSolderMask is true. When a component is fully covered with solder mask, a margin doesn't apply.",error_type:"source_property_ignored_warning"})}}_getPcbCircuitJsonBounds(){return{center:{x:0,y:0},bounds:{left:0,top:0,right:0,bottom:0},width:0,height:0}}_getPcbPrimitiveFlippedHelpers(){let container=this.getPrimitiveContainer(),isFlipped=container?container._parsedProps.layer==="bottom":!1;return{isFlipped,maybeFlipLayer:layer=>isFlipped?layer==="top"?"bottom":"top":layer}}_setPositionFromLayout(newCenter){throw new Error(`_setPositionFromLayout not implemented for ${this.componentName}`)}computeSchematicPropsTransform(){let{_parsedProps:props}=this;return compose(translate(props.schX??0,props.schY??0))}computeSchematicGlobalTransform(){let manualPlacementTransform=this._getSchematicGlobalManualPlacementTransform(this);return manualPlacementTransform||compose(this.parent?.computeSchematicGlobalTransform?.()??identity(),this.computeSchematicPropsTransform())}_getSchematicSymbolName(){let{_parsedProps:props}=this,base_symbol_name=this.config.schematicSymbolName,orientationRotationMap={horizontal:0,pos_left:0,neg_right:0,pos_right:180,neg_left:180,pos_top:270,neg_bottom:90,vertical:270,pos_bottom:90,neg_top:90},normalizedRotation=props.schOrientation!==void 0?orientationRotationMap[props.schOrientation]:props.schRotation;if(normalizedRotation===void 0&&(normalizedRotation=0),normalizedRotation=normalizedRotation%360,normalizedRotation<0&&(normalizedRotation+=360),props.schRotation!==void 0&&normalizedRotation%90!==0)throw new Error(`Schematic rotation ${props.schRotation} is not supported for ${this.componentName}`);let symbol_name_horz=`${base_symbol_name}_horz`,symbol_name_vert=`${base_symbol_name}_vert`,symbol_name_up=`${base_symbol_name}_up`,symbol_name_down=`${base_symbol_name}_down`,symbol_name_left=`${base_symbol_name}_left`,symbol_name_right=`${base_symbol_name}_right`;if(symbol_name_right in Vf&&normalizedRotation===0)return symbol_name_right;if(symbol_name_up in Vf&&normalizedRotation===90)return symbol_name_up;if(symbol_name_left in Vf&&normalizedRotation===180)return symbol_name_left;if(symbol_name_down in Vf&&normalizedRotation===270)return symbol_name_down;if(symbol_name_horz in Vf&&(normalizedRotation===0||normalizedRotation===180))return symbol_name_horz;if(symbol_name_vert in Vf&&(normalizedRotation===90||normalizedRotation===270))return symbol_name_vert;if(base_symbol_name in Vf)return base_symbol_name}_getSchematicSymbolNameOrThrow(){let symbol_name=this._getSchematicSymbolName();if(!symbol_name)throw new Error(`No schematic symbol found (given: "${this.config.schematicSymbolName}")`);return symbol_name}getSchematicSymbol(){let symbol_name=this._getSchematicSymbolName();return symbol_name?Vf[symbol_name]??null:null}_getPcbManualPlacementForComponent(component){if(!this.isSubcircuit)return null;let manualEdits=this.props.manualEdits;if(!manualEdits)return null;let placementConfigPositions=manualEdits?.pcb_placements;if(!placementConfigPositions)return null;for(let position2 of placementConfigPositions)if(isMatchingSelector(component,position2.selector)||component.props.name===position2.selector)return applyToPoint(this._computePcbGlobalTransformBeforeLayout(),position2.center);return null}_getSchematicManualPlacementForComponent(component){if(!this.isSubcircuit)return null;let manualEdits=this.props.manualEdits;if(!manualEdits)return null;let placementConfigPositions=manualEdits.schematic_placements;if(!placementConfigPositions)return null;for(let position2 of placementConfigPositions)if(isMatchingSelector(component,position2.selector)||component.props.name===position2.selector)return applyToPoint(this.computeSchematicGlobalTransform(),position2.center);return null}_getSchematicGlobalManualPlacementTransform(component){let manualEdits=this.getSubcircuit()?._parsedProps.manualEdits;if(!manualEdits)return null;for(let position2 of manualEdits.schematic_placements??[])if((isMatchingSelector(component,position2.selector)||component.props.name===position2.selector)&&position2.relative_to==="group_center")return compose(this.parent?._computePcbGlobalTransformBeforeLayout()??identity(),translate(position2.center.x,position2.center.y));return null}_getGlobalPcbPositionBeforeLayout(){return applyToPoint(this._computePcbGlobalTransformBeforeLayout(),{x:0,y:0})}_getGlobalSchematicPositionBeforeLayout(){return applyToPoint(this.computeSchematicGlobalTransform(),{x:0,y:0})}_getBoard(){let current2=this;for(;current2;){let maybePrimitive=current2;if(maybePrimitive.componentName==="Board")return maybePrimitive;current2=current2.parent??null}return this.root?._getBoard()}get root(){return this.parent?.root??null}onAddToParent(parent){this.parent=parent}onPropsChange(params){}onChildChanged(child){this.parent?.onChildChanged?.(child)}add(component){let textContent2=component.__text;if(typeof textContent2=="string"){if(this.canHaveTextChildren||textContent2.trim()==="")return;throw new Error(`Invalid JSX Element: Expected a React component but received text "${textContent2}"`)}if(Object.keys(component).length!==0){if(component.lowercaseComponentName==="panel")throw new Error("<panel> must be a root-level element");if(!component.onAddToParent)throw new Error(`Invalid JSX Element: Expected a React component but received "${JSON.stringify(component)}"`);component.onAddToParent(this),component.parent=this,this.children.push(component)}}addAll(components){for(let component of components)this.add(component)}remove(component){this.children=this.children.filter(c3=>c3!==component),this.childrenPendingRemoval.push(component),component.shouldBeRemoved=!0}getSubcircuitSelector(){let name=this.name,endPart=name?`${this.lowercaseComponentName}.${name}`:this.lowercaseComponentName;return!this.parent||this.parent.isSubcircuit?endPart:`${this.parent.getSubcircuitSelector()} > ${endPart}`}getFullPathSelector(){let name=this.name,endPart=name?`${this.lowercaseComponentName}.${name}`:this.lowercaseComponentName,parentSelector=this.parent?.getFullPathSelector?.();return parentSelector?`${parentSelector} > ${endPart}`:endPart}getNameAndAliases(){return[this.name,...this._parsedProps.portHints??[]].filter(Boolean)}isMatchingNameOrAlias(name){return this.getNameAndAliases().includes(name)}isMatchingAnyOf(aliases2){return this.getNameAndAliases().some(a2=>aliases2.map(a22=>a22.toString()).includes(a2))}getPcbSize(){throw new Error(`getPcbSize not implemented for ${this.componentName}`)}doesSelectorMatch(selector){let myTypeNames=[this.componentName,this.lowercaseComponentName],myClassNames=[this.name].filter(Boolean),parts=selector.trim().split(/\> /)[0],firstPart=parts[0];return parts.length>1?!1:!!(selector==="*"||selector[0]==="#"&&selector.slice(1)===this.props.id||selector[0]==="."&&myClassNames.includes(selector.slice(1))||/^[a-zA-Z0-9_]/.test(firstPart)&&myTypeNames.includes(firstPart))}getSubcircuit(){if(this.isSubcircuit)return this;let group=this.parent?.getSubcircuit?.();if(!group)throw new Error("Component is not inside an opaque group (no board?)");return group}getGroup(){return this.isGroup?this:this.parent?.getGroup?.()??null}doInitialAssignNameToUnnamedComponents(){this._parsedProps.name||(this.fallbackUnassignedName=this.getSubcircuit().getNextAvailableName(this))}doInitialOptimizeSelectorCache(){if(!this.isSubcircuit)return;let ports=this.selectAll("port");for(let port of ports){let parentAliases=(port.getParentNormalComponent?.()??port.parent)?.getNameAndAliases(),portAliases=port.getNameAndAliases();if(parentAliases)for(let parentAlias of parentAliases)for(let portAlias of portAliases){let selectors=[`.${parentAlias} > .${portAlias}`,`.${parentAlias} .${portAlias}`];for(let selector of selectors){let ar4=this._cachedSelectAllQueries.get(selector);ar4?ar4.push(port):this._cachedSelectAllQueries.set(selector,[port])}}}for(let[selector,ports2]of this._cachedSelectAllQueries.entries())ports2.length===1&&this._cachedSelectOneQueries.set(selector,ports2[0])}selectAll(selectorRaw){if(this._cachedSelectAllQueries.has(selectorRaw))return this._cachedSelectAllQueries.get(selectorRaw);let selector=preprocessSelector(selectorRaw,this),result=selectAll(selector,this,cssSelectOptionsInsideSubcircuit);if(result.length>0)return this._cachedSelectAllQueries.set(selectorRaw,result),result;let[firstpart,...rest]=selector.split(" "),subcircuit=selectOne(firstpart,this,{adapter:cssSelectPrimitiveComponentAdapterOnlySubcircuits});if(!subcircuit)return[];let result2=subcircuit.selectAll(rest.join(" "));return this._cachedSelectAllQueries.set(selectorRaw,result2),result2}selectOne(selectorRaw,options){if(this._cachedSelectOneQueries.has(selectorRaw))return this._cachedSelectOneQueries.get(selectorRaw);let selector=preprocessSelector(selectorRaw,this);options?.port&&(options.type="port");let result=null;if(options?.type&&(result=selectAll(selector,this,cssSelectOptionsInsideSubcircuit).find(n3=>n3.lowercaseComponentName===options.type)),result??(result=selectOne(selector,this,cssSelectOptionsInsideSubcircuit)),result)return this._cachedSelectOneQueries.set(selectorRaw,result),result;let[firstpart,...rest]=selector.split(" "),subcircuit=selectOne(firstpart,this,{adapter:cssSelectPrimitiveComponentAdapterOnlySubcircuits});return subcircuit?(result=subcircuit.selectOne(rest.join(" "),options),this._cachedSelectOneQueries.set(selectorRaw,result),result):null}getAvailablePcbLayers(){if(this.isPcbPrimitive){let{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers();return"layer"in this._parsedProps||this.componentName==="SmtPad"?[maybeFlipLayer(this._parsedProps.layer??"top")]:"layers"in this._parsedProps?this._parsedProps.layers:this.componentName==="PlatedHole"?[...this.root?._getBoard()?.allLayers??["top","bottom"]]:[]}return[]}getDescendants(){let descendants=[];for(let child of this.children)descendants.push(child),descendants.push(...child.getDescendants());return descendants}getSelectableDescendants(){let descendants=[];for(let child of this.children)child.isSubcircuit?descendants.push(child):(descendants.push(child),descendants.push(...child.getSelectableDescendants()));return descendants}_getPinCount(){return 0}_getSchematicBoxDimensions(){return null}_getSchematicBoxComponentDimensions(){if(this.getSchematicSymbol()||!this.config.shouldRenderAsSchematicBox)return null;let{_parsedProps:props}=this;return{schWidth:props.schWidth,schHeight:props.schHeight}}renderError(message){if(typeof message=="string")return super.renderError(message);switch(message.type){case"pcb_placement_error":this.root?.db.pcb_placement_error.insert(message);break;case"pcb_via_clearance_error":this.root?.db.pcb_via_clearance_error.insert(message);break;case"pcb_trace_error":this.root?.db.pcb_trace_error.insert(message);break;case"pcb_manual_edit_conflict_warning":this.root?.db.pcb_manual_edit_conflict_warning.insert(message);break;default:this.root?.db.pcb_placement_error.insert(message)}}getString(){let{lowercaseComponentName:cname,_parsedProps:props,parent}=this;return props?.pinNumber!==void 0&&parent?.props?.name&&props?.name?`<${cname}#${this._renderId}(pin:${props.pinNumber} .${parent?.props.name}>.${props.name}) />`:parent?.props?.name&&props?.name?`<${cname}#${this._renderId}(.${parent?.props.name}>.${props?.name}) />`:props?.from&&props?.to?`<${cname}#${this._renderId}(from:${props.from} to:${props?.to}) />`:props?.name?`<${cname}#${this._renderId} name=".${props?.name}" />`:props?.portHints?`<${cname}#${this._renderId}(${props.portHints.map(ph2=>`.${ph2}`).join(", ")}) />`:`<${cname}#${this._renderId} />`}get[Symbol.toStringTag](){return this.getString()}[Symbol.for("nodejs.util.inspect.custom")](){return this.getString()}},ErrorPlaceholderComponent=class extends PrimitiveComponent2{constructor(props,error){super(props);let resolveCoordinate=(value,axis)=>{if(typeof value=="number")return value;if(typeof value=="string")try{return this._resolvePcbCoordinate(value,axis,{allowBoardVariables:!1})}catch{return 0}return 0};this._parsedProps={...props,error,type:props.type||"unknown",component_name:props.name,error_type:"source_failed_to_create_component_error",message:error instanceof Error?error.message:String(error),pcbX:resolveCoordinate(props.pcbX,"pcbX"),pcbY:resolveCoordinate(props.pcbY,"pcbY"),schX:props.schX,schY:props.schY}}formatErrorDetails(){let selectorValue=this._parsedProps.selector??this._parsedProps.selectors??this._parsedProps.in??this._parsedProps.within,selectorText=selectorValue===void 0?void 0:typeof selectorValue=="string"?selectorValue:this.safeStringify(selectorValue),propsText=this.safeStringify(this._parsedProps);return{selectorText,propsText}}safeStringify(value){let seen=new WeakSet,json=JSON.stringify(value,(_key,item)=>{if(typeof item=="bigint")return item.toString();if(typeof item=="function")return`[Function ${item.name||"anonymous"}]`;if(typeof item=="symbol")return item.toString();if(typeof item=="object"&&item!==null){if(seen.has(item))return"[Circular]";seen.add(item)}return item},2);return json?json.length>2e3?`${json.slice(0,2e3)}\u2026`:json:"undefined"}get config(){return{componentName:"ErrorPlaceholder",zodProps:external_exports.object({}).passthrough()}}doInitialSourceRender(){if(this.root?.db){let pcbPosition2=this._getGlobalPcbPositionBeforeLayout(),schematicPosition=this._getGlobalSchematicPositionBeforeLayout(),{selectorText,propsText}=this.formatErrorDetails(),messageDetails=[selectorText?`Within selector: ${selectorText}`:null,`Props: ${propsText}`].filter(Boolean).join(" "),baseMessage=`Could not create ${this._parsedProps.componentType??"component"}${this._parsedProps.name?` "${this._parsedProps.name}"`:""}. ${this._parsedProps.error?.formattedError?._errors?.join("; ")||this._parsedProps.message}`;this.root.db.source_failed_to_create_component_error.insert({component_name:this._parsedProps.component_name,error_type:"source_failed_to_create_component_error",message:`${baseMessage}${messageDetails?` Details: ${messageDetails}`:""}`,pcb_center:pcbPosition2,schematic_center:schematicPosition})}}};function createErrorPlaceholderComponent(props,error){return new ErrorPlaceholderComponent(props,error)}function prepare(object,state2){let instance=object;return instance.__tsci={...state2},object}var hostConfig={supportsMutation:!0,createInstance(type,props){let target=catalogue[type];if(!target)throw Object.keys(catalogue).length===0?new Error("No components registered in catalogue, did you forget to import lib/register-catalogue in your test file?"):new Error(`Unsupported component type "${type}". No element with this name is registered in the @tscircuit/core catalogue. Check for typos or see https://docs.tscircuit.com/category/built-in-elements for a list of valid components. To add your own component, see docs/CREATING_NEW_COMPONENTS.md`);try{return prepare(new target(props),{})}catch(error){return createErrorPlaceholderComponent({...props,componentType:type},error)}},createTextInstance(text){return{__text:text}},appendInitialChild(parentInstance,child){parentInstance.add(child)},appendChild(parentInstance,child){parentInstance.add(child)},appendChildToContainer(container,child){container.add(child)},finalizeInitialChildren(){return!1},prepareUpdate(){return null},shouldSetTextContent(){return!1},getRootHostContext(){return{}},getChildHostContext(){return{}},prepareForCommit(){return null},resetAfterCommit(){},commitMount(){},commitUpdate(){},removeChild(){},clearContainer(){},supportsPersistence:!1,getPublicInstance(instance){return instance},preparePortalMount(containerInfo){throw new Error("Function not implemented.")},scheduleTimeout(fn3,delay){throw new Error("Function not implemented.")},cancelTimeout(id){throw new Error("Function not implemented.")},noTimeout:void 0,isPrimaryRenderer:!1,getInstanceFromNode(node){throw new Error("Function not implemented.")},beforeActiveInstanceBlur(){throw new Error("Function not implemented.")},afterActiveInstanceBlur(){throw new Error("Function not implemented.")},prepareScopeUpdate:(scopeInstance,instance)=>{throw new Error("Function not implemented.")},getInstanceFromScope:scopeInstance=>{throw new Error("Function not implemented.")},detachDeletedInstance:node=>{throw new Error("Function not implemented.")},getCurrentEventPriority:()=>import_constants.DefaultEventPriority,getCurrentUpdatePriority:()=>import_constants.DefaultEventPriority,resolveUpdatePriority:()=>import_constants.DefaultEventPriority,setCurrentUpdatePriority:()=>{},maySuspendCommit:()=>!1,supportsHydration:!1},reconciler=(0,import_react_reconciler.default)(hostConfig),createInstanceFromReactElement=reactElm=>{let rootContainer={children:[],props:{name:"$root"},add(instance){instance.parent=this,this.children.push(instance)},computePcbGlobalTransform(){return identity()}},containerErrors=[],container=reconciler.createContainer(rootContainer,0,null,!1,null,"tsci",error=>{console.log("Error in createContainer"),console.error(error),containerErrors.push(error)},null);if(reconciler.updateContainerSync(reactElm,container,null,()=>{}),reconciler.flushSyncWork(),containerErrors.length>0)throw containerErrors[0];let rootInstance=reconciler.getPublicRootInstance(container);return rootInstance||rootContainer.children[0]},parsePinNumberFromLabelsOrThrow=(pinNumberOrLabel,pinLabels)=>{if(typeof pinNumberOrLabel=="number")return pinNumberOrLabel;if(pinNumberOrLabel.startsWith("pin"))return Number(pinNumberOrLabel.slice(3));if(!pinLabels)throw new Error(`No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`);for(let pinNumberKey in pinLabels)if((Array.isArray(pinLabels[pinNumberKey])?pinLabels[pinNumberKey]:[pinLabels[pinNumberKey]]).includes(pinNumberOrLabel))return Number(pinNumberKey.replace("pin",""));throw new Error(`No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`)},underscorifyPinStyles=(pinStyles,pinLabels)=>{if(!pinStyles)return;let underscorePinStyles={},mergedStyles={};for(let[pinNameOrLabel,pinStyle]of Object.entries(pinStyles)){let pinNumber=parsePinNumberFromLabelsOrThrow(pinNameOrLabel,pinLabels);mergedStyles[pinNumber]={...mergedStyles[pinNumber],...pinStyle}}for(let[pinNumber,pinStyle]of Object.entries(mergedStyles)){let pinKey=`pin${pinNumber}`;underscorePinStyles[pinKey]={bottom_margin:pinStyle.bottomMargin,left_margin:pinStyle.leftMargin,right_margin:pinStyle.rightMargin,top_margin:pinStyle.topMargin}}return underscorePinStyles},underscorifyPortArrangement=portArrangement=>{if(portArrangement){if("leftSide"in portArrangement||"rightSide"in portArrangement||"topSide"in portArrangement||"bottomSide"in portArrangement)return{left_side:portArrangement.leftSide,right_side:portArrangement.rightSide,top_side:portArrangement.topSide,bottom_side:portArrangement.bottomSide};if("leftPinCount"in portArrangement||"rightPinCount"in portArrangement||"topPinCount"in portArrangement||"bottomPinCount"in portArrangement)return{left_size:portArrangement.leftPinCount,right_size:portArrangement.rightPinCount,top_size:portArrangement.topPinCount,bottom_size:portArrangement.bottomPinCount};if("leftSize"in portArrangement||"rightSize"in portArrangement||"topSize"in portArrangement||"bottomSize"in portArrangement)return{left_size:portArrangement.leftSize,right_size:portArrangement.rightSize,top_size:portArrangement.topSize,bottom_size:portArrangement.bottomSize}}};function pairs2(arr){let result=[];for(let i2=0;i2<arr.length-1;i2++)result.push([arr[i2],arr[i2+1]]);return result}var netProps2=external_exports.object({name:external_exports.string().refine(val=>!/[+-]/.test(val),val=>({message:`Net names cannot contain "+" or "-" (component "Net" received "${val}"). Try using underscores instead, e.g. VCC_P`}))}),Net=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"source_net_id");__publicField(this,"subcircuit_connectivity_map_key",null)}get config(){return{componentName:"Net",zodProps:netProps2}}getPortSelector(){return`net.${this.props.name}`}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,isGround=props.name.startsWith("GND"),isPositiveVoltageSource=props.name.startsWith("V"),net=db.source_net.insert({name:props.name,member_source_group_ids:[],is_ground:isGround,is_power:isPositiveVoltageSource,is_positive_voltage_source:isPositiveVoltageSource});this.source_net_id=net.source_net_id}doInitialSourceParentAttachment(){let subcircuit=this.getSubcircuit();if(!subcircuit)return;let{db}=this.root;db.source_net.update(this.source_net_id,{subcircuit_id:subcircuit.subcircuit_id})}getAllConnectedPorts(){let allPorts=this.getSubcircuit().selectAll("port"),connectedPorts=[];for(let port of allPorts){let traces=port._getDirectlyConnectedTraces();for(let trace of traces)if(trace._isExplicitlyConnectedToNet(this)){connectedPorts.push(port);break}}return connectedPorts}_getAllDirectlyConnectedTraces(){let allTraces=this.getSubcircuit().selectAll("trace"),connectedTraces=[];for(let trace of allTraces)trace._isExplicitlyConnectedToNet(this)&&connectedTraces.push(trace);return connectedTraces}doInitialPcbRouteNetIslands(){if(this.root?.pcbDisabled||this.getSubcircuit()._parsedProps.routingDisabled||this.getSubcircuit()._getAutorouterConfig().groupMode!=="sequential-trace")return;let{db}=this.root,{_parsedProps:props}=this,traces=this._getAllDirectlyConnectedTraces().filter(trace=>(trace._portsRoutedOnPcb?.length??0)>0),islands=[];for(let trace of traces){let tracePorts=trace._portsRoutedOnPcb,traceIsland=islands.find(island=>tracePorts.some(port=>island.ports.includes(port)));if(!traceIsland){islands.push({ports:[...tracePorts],traces:[trace]});continue}traceIsland.traces.push(trace),traceIsland.ports.push(...tracePorts)}if(islands.length===0)return;let islandPairs=pairs2(islands);for(let[A4,B5]of islandPairs){let Apositions=A4.ports.map(port=>port._getGlobalPcbPositionBeforeLayout()),Bpositions=B5.ports.map(port=>port._getGlobalPcbPositionBeforeLayout()),closestDist=1/0,closestPair=[-1,-1];for(let i2=0;i2<Apositions.length;i2++){let Apos=Apositions[i2];for(let j4=0;j4<Bpositions.length;j4++){let Bpos=Bpositions[j4],dist=Math.sqrt((Apos.x-Bpos.x)**2+(Apos.y-Bpos.y)**2);dist<closestDist&&(closestDist=dist,closestPair=[i2,j4])}}let Aport=A4.ports[closestPair[0]],Bport=B5.ports[closestPair[1]],pcbElements=db.toArray().filter(elm=>elm.type==="pcb_smtpad"||elm.type==="pcb_trace"||elm.type==="pcb_plated_hole"||elm.type==="pcb_hole"||elm.type==="source_port"||elm.type==="pcb_port"),{solution}=autoroute2(pcbElements.concat([{type:"source_trace",source_trace_id:"__net_trace_tmp",connected_source_port_ids:[Aport.source_port_id,Bport.source_port_id]}])),trace=solution[0];if(!trace){this.renderError({pcb_trace_error_id:"",pcb_trace_id:"__net_trace_tmp",pcb_component_ids:[Aport.pcb_component_id,Bport.pcb_component_id].filter(Boolean),pcb_port_ids:[Aport.pcb_port_id,Bport.pcb_port_id].filter(Boolean),type:"pcb_trace_error",error_type:"pcb_trace_error",message:`Failed to route net islands for "${this.getString()}"`,source_trace_id:"__net_trace_tmp"});return}db.pcb_trace.insert(trace)}}renderError(message){if(typeof message=="string")return super.renderError(message);this.root?.db.pcb_trace_error.insert(message)}},createNetsFromProps=(component,props)=>{for(let prop of props)if(typeof prop=="string"&&prop.startsWith("net.")){if(/net\.[^\s>]*\./.test(prop))throw new Error('Net names cannot contain a period, try using "sel.net..." to autocomplete with conventional net names, e.g. V3_3');if(/net\.[^\s>]*[+-]/.test(prop)){let netName=prop.split("net.")[1],message=`Net names cannot contain "+" or "-" (component "${component.componentName}" received "${netName}" via "${prop}"). Try using underscores instead, e.g. VCC_P`;throw new Error(message)}if(/net\.[0-9]/.test(prop)){let netName=prop.split("net.")[1];throw new Error(`Net name "${netName}" cannot start with a number, try using a prefix like "VBUS1"`)}let subcircuit=component.getSubcircuit();if(!subcircuit.selectOne(prop)){let net=new Net({name:prop.split("net.")[1]});subcircuit.add(net)}}},SmtPad=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_smtpad_id",null);__publicField(this,"matchedPort",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SmtPad",zodProps:smtPadProps}}getPcbSize(){let{_parsedProps:props}=this;if(props.shape==="circle")return{width:props.radius*2,height:props.radius*2};if(props.shape==="rect")return{width:props.width,height:props.height};if(props.shape==="rotated_rect"){let angleRad=(props.ccwRotation??0)*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),width=Math.abs(props.width*cosAngle)+Math.abs(props.height*sinAngle),height=Math.abs(props.width*sinAngle)+Math.abs(props.height*cosAngle);return{width,height}}if(props.shape==="polygon"){let points=props.points,xs3=points.map(p4=>p4.x),ys3=points.map(p4=>p4.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}if(props.shape==="pill")return{width:props.width,height:props.height};throw new Error(`getPcbSize for shape "${props.shape}" not implemented for ${this.componentName}`)}doInitialPortMatching(){let parentPorts=this.getPrimitiveContainer()?.selectAll("port");if(this.props.portHints){for(let port of parentPorts)if(port.isMatchingAnyOf(this.props.portHints)){this.matchedPort=port,port.registerMatch(this);return}}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,isCoveredWithSolderMask=props.coveredWithSolderMask??!1,shouldCreateSolderPaste=!isCoveredWithSolderMask,soldermaskMargin=props.solderMaskMargin;this.emitSolderMaskMarginWarning(isCoveredWithSolderMask,soldermaskMargin);let subcircuit=this.getSubcircuit(),position2=this._getGlobalPcbPositionBeforeLayout(),globalTransform=this._computePcbGlobalTransformBeforeLayout(),normalizedRotationDegrees=(decomposeTSR(this._computePcbGlobalTransformBeforeLayout()).rotation.angle*180/Math.PI%360+360)%360,rotationTolerance=.01,isAxisAligned=Math.abs(normalizedRotationDegrees)<rotationTolerance||Math.abs(normalizedRotationDegrees-180)<rotationTolerance||Math.abs(normalizedRotationDegrees-360)<rotationTolerance,isRotated90Degrees=Math.abs(normalizedRotationDegrees-90)<rotationTolerance||Math.abs(normalizedRotationDegrees-270)<rotationTolerance,finalRotationDegrees=Math.abs(normalizedRotationDegrees-360)<rotationTolerance?0:normalizedRotationDegrees,transformRotationBeforeFlip=finalRotationDegrees,{maybeFlipLayer,isFlipped}=this._getPcbPrimitiveFlippedHelpers();isFlipped&&(finalRotationDegrees=(360-finalRotationDegrees+360)%360);let portHints2=props.portHints?.map(ph2=>ph2.toString())??[],pcb_smtpad2=null,pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id;if(props.shape==="circle")pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"circle",radius:props.radius,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0}),shouldCreateSolderPaste&&db.pcb_solder_paste.insert({layer:pcb_smtpad2.layer,shape:"circle",radius:pcb_smtpad2.radius*.7,x:pcb_smtpad2.x,y:pcb_smtpad2.y,pcb_component_id:pcb_smtpad2.pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});else if(props.shape==="rect")!isAxisAligned&&!isRotated90Degrees?pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:props.width,height:props.height,corner_radius:props.cornerRadius??void 0,x:position2.x,y:position2.y,ccw_rotation:finalRotationDegrees,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}):pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"rect",width:isRotated90Degrees?props.height:props.width,height:isRotated90Degrees?props.width:props.height,corner_radius:props.cornerRadius??void 0,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),shouldCreateSolderPaste&&(pcb_smtpad2.shape==="rect"?db.pcb_solder_paste.insert({layer:maybeFlipLayer(props.layer??"top"),shape:"rect",width:pcb_smtpad2.width*.7,height:pcb_smtpad2.height*.7,x:pcb_smtpad2.x,y:pcb_smtpad2.y,pcb_component_id:pcb_smtpad2.pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}):pcb_smtpad2.shape==="rotated_rect"&&db.pcb_solder_paste.insert({layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:pcb_smtpad2.width*.7,height:pcb_smtpad2.height*.7,x:pcb_smtpad2.x,y:pcb_smtpad2.y,ccw_rotation:pcb_smtpad2.ccw_rotation,pcb_component_id:pcb_smtpad2.pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}));else if(props.shape==="rotated_rect"){let baseRotation=props.ccwRotation??0,combinedRotationBeforeFlip=(transformRotationBeforeFlip+baseRotation+360)%360,padRotation=isFlipped?(360-combinedRotationBeforeFlip+360)%360:combinedRotationBeforeFlip;pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:props.width,height:props.height,corner_radius:props.cornerRadius??void 0,x:position2.x,y:position2.y,ccw_rotation:padRotation,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),shouldCreateSolderPaste&&db.pcb_solder_paste.insert({layer:maybeFlipLayer(props.layer??"top"),shape:"rotated_rect",width:pcb_smtpad2.width*.7,height:pcb_smtpad2.height*.7,x:position2.x,y:position2.y,ccw_rotation:padRotation,pcb_component_id,pcb_smtpad_id:pcb_smtpad2.pcb_smtpad_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else if(props.shape==="polygon"){let transformedPoints=props.points.map(point6=>{let transformed=applyToPoint(globalTransform,{x:distance.parse(point6.x),y:distance.parse(point6.y)});return{x:transformed.x,y:transformed.y}});pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"polygon",points:transformedPoints,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else props.shape==="pill"&&(pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,layer:maybeFlipLayer(props.layer??"top"),shape:"pill",x:position2.x,y:position2.y,radius:props.radius,height:props.height,width:props.width,port_hints:portHints2,is_covered_with_solder_mask:isCoveredWithSolderMask,soldermask_margin:soldermaskMargin,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}));pcb_smtpad2&&(this.pcb_smtpad_id=pcb_smtpad2.pcb_smtpad_id)}doInitialPcbPortAttachment(){if(this.root?.pcbDisabled)return;let{db}=this.root;db.pcb_smtpad.update(this.pcb_smtpad_id,{pcb_port_id:this.matchedPort?.pcb_port_id})}_getPcbCircuitJsonBounds(){let{db}=this.root,smtpad2=db.pcb_smtpad.get(this.pcb_smtpad_id);if(smtpad2.shape==="rect")return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-smtpad2.width/2,top:smtpad2.y+smtpad2.height/2,right:smtpad2.x+smtpad2.width/2,bottom:smtpad2.y-smtpad2.height/2},width:smtpad2.width,height:smtpad2.height};if(smtpad2.shape==="rotated_rect"){let angleRad=smtpad2.ccw_rotation*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),w22=smtpad2.width/2,h22=smtpad2.height/2,xExtent=Math.abs(w22*cosAngle)+Math.abs(h22*sinAngle),yExtent=Math.abs(w22*sinAngle)+Math.abs(h22*cosAngle);return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-xExtent,right:smtpad2.x+xExtent,top:smtpad2.y-yExtent,bottom:smtpad2.y+yExtent},width:xExtent*2,height:yExtent*2}}if(smtpad2.shape==="circle")return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-smtpad2.radius,top:smtpad2.y-smtpad2.radius,right:smtpad2.x+smtpad2.radius,bottom:smtpad2.y+smtpad2.radius},width:smtpad2.radius*2,height:smtpad2.radius*2};if(smtpad2.shape==="polygon"){let points=smtpad2.points,xs3=points.map(p4=>p4.x),ys3=points.map(p4=>p4.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{center:{x:(minX+maxX)/2,y:(minY+maxY)/2},bounds:{left:minX,top:maxY,right:maxX,bottom:minY},width:maxX-minX,height:maxY-minY}}if(smtpad2.shape==="pill"){let halfWidth=smtpad2.width/2,halfHeight=smtpad2.height/2;return{center:{x:smtpad2.x,y:smtpad2.y},bounds:{left:smtpad2.x-halfWidth,top:smtpad2.y-halfHeight,right:smtpad2.x+halfWidth,bottom:smtpad2.y+halfHeight},width:smtpad2.width,height:smtpad2.height}}throw new Error(`circuitJson bounds calculation not implemented for shape "${smtpad2.shape}"`)}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_smtpad.update(this.pcb_smtpad_id,{x:newCenter.x,y:newCenter.y});let solderPaste=db.pcb_solder_paste.list().find(elm=>elm.pcb_smtpad_id===this.pcb_smtpad_id);solderPaste&&db.pcb_solder_paste.update(solderPaste.pcb_solder_paste_id,{x:newCenter.x,y:newCenter.y}),this.matchedPort?._setPositionFromLayout(newCenter)}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_smtpad_id)return;let pad2=db.pcb_smtpad.get(this.pcb_smtpad_id);if(pad2.shape==="rect"||pad2.shape==="circle"||pad2.shape==="rotated_rect"||pad2.shape==="pill")this._setPositionFromLayout({x:pad2.x+deltaX,y:pad2.y+deltaY});else if(pad2.shape==="polygon"){db.pcb_smtpad.update(this.pcb_smtpad_id,{points:pad2.points.map(p4=>({x:p4.x+deltaX,y:p4.y+deltaY}))});let newCenter={x:this._getPcbCircuitJsonBounds().center.x+deltaX/2,y:this._getPcbCircuitJsonBounds().center.y+deltaY/2};this.matchedPort?._setPositionFromLayout(newCenter)}}},SilkscreenPath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_path_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenPath",zodProps:silkscreenPathProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=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 SilkscreenPath. Must be "top" or "bottom".`);let transform5=this._computePcbGlobalTransformBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_path2=db.pcb_silkscreen_path.insert({pcb_component_id,layer,route:props.route.map(p4=>{let transformedPosition=applyToPoint(transform5,{x:p4.x,y:p4.y});return{...p4,x:transformedPosition.x,y:transformedPosition.y}}),stroke_width:props.strokeWidth??.1,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_silkscreen_path_id=pcb_silkscreen_path2.pcb_silkscreen_path_id}_setPositionFromLayout(newCenter){let{db}=this.root,{_parsedProps:props}=this,currentPath=db.pcb_silkscreen_path.get(this.pcb_silkscreen_path_id);if(!currentPath)return;let currentCenterX=0,currentCenterY=0;for(let point6 of currentPath.route)currentCenterX+=point6.x,currentCenterY+=point6.y;currentCenterX/=currentPath.route.length,currentCenterY/=currentPath.route.length;let offsetX=newCenter.x-currentCenterX,offsetY=newCenter.y-currentCenterY,newRoute=currentPath.route.map(point6=>({...point6,x:point6.x+offsetX,y:point6.y+offsetY}));db.pcb_silkscreen_path.update(this.pcb_silkscreen_path_id,{route:newRoute})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_path_id)return;let path=db.pcb_silkscreen_path.get(this.pcb_silkscreen_path_id);path&&db.pcb_silkscreen_path.update(this.pcb_silkscreen_path_id,{route:path.route.map(p4=>({...p4,x:p4.x+deltaX,y:p4.y+deltaY}))})}getPcbSize(){let{_parsedProps:props}=this;if(!props.route||props.route.length===0)return{width:0,height:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of props.route)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{width:maxX-minX,height:maxY-minY}}},pcbTraceProps2=external_exports.object({route:external_exports.array(pcb_trace_route_point),source_trace_id:external_exports.string().optional()}),PcbTrace=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_trace_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbTrace",zodProps:pcbTraceProps2}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,container=this.getPrimitiveContainer(),subcircuit=this.getSubcircuit(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),parentTransform=this._computePcbGlobalTransformBeforeLayout(),transformedRoute=props.route.map(point6=>{let{x:x5,y:y5,...restOfPoint}=point6,transformedPoint=applyToPoint(parentTransform,{x:x5,y:y5});return point6.route_type==="wire"&&point6.layer?{...transformedPoint,...restOfPoint,layer:maybeFlipLayer(point6.layer)}:{...transformedPoint,...restOfPoint}}),pcb_trace2=db.pcb_trace.insert({pcb_component_id:container.pcb_component_id,source_trace_id:props.source_trace_id,route:transformedRoute,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_trace_id=pcb_trace2.pcb_trace_id}getPcbSize(){let{_parsedProps:props}=this;if(!props.route||props.route.length===0)return{width:0,height:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of props.route)minX=Math.min(minX,point6.x),maxX=Math.max(maxX,point6.x),minY=Math.min(minY,point6.y),maxY=Math.max(maxY,point6.y),point6.route_type==="wire"&&(minX=Math.min(minX,point6.x-point6.width/2),maxX=Math.max(maxX,point6.x+point6.width/2),minY=Math.min(minY,point6.y-point6.width/2),maxY=Math.max(maxY,point6.y+point6.width/2));return minX===1/0||maxX===-1/0||minY===1/0||maxY===-1/0?{width:0,height:0}:{width:maxX-minX,height:maxY-minY}}},PlatedHole=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_plated_hole_id",null);__publicField(this,"matchedPort",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PlatedHole",zodProps:platedHoleProps}}getAvailablePcbLayers(){return["top","inner1","inner2","bottom"]}getPcbSize(){let{_parsedProps:props}=this;if(props.shape==="circle")return{width:props.outerDiameter,height:props.outerDiameter};if(props.shape==="oval"||props.shape==="pill")return{width:props.outerWidth,height:props.outerHeight};if(props.shape==="circular_hole_with_rect_pad")return{width:props.rectPadWidth,height:props.rectPadHeight};if(props.shape==="pill_hole_with_rect_pad")return{width:props.rectPadWidth,height:props.rectPadHeight};if(props.shape==="hole_with_polygon_pad"){if(!props.padOutline||props.padOutline.length===0)throw new Error("padOutline is required for hole_with_polygon_pad shape");let xs3=props.padOutline.map(p4=>typeof p4.x=="number"?p4.x:parseFloat(String(p4.x))),ys3=props.padOutline.map(p4=>typeof p4.y=="number"?p4.y:parseFloat(String(p4.y))),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}throw new Error(`getPcbSize for shape "${props.shape}" not implemented for ${this.componentName}`)}_getPcbCircuitJsonBounds(){let{db}=this.root,platedHole=db.pcb_plated_hole.get(this.pcb_plated_hole_id),size2=this.getPcbSize();return{center:{x:platedHole.x,y:platedHole.y},bounds:{left:platedHole.x-size2.width/2,top:platedHole.y+size2.height/2,right:platedHole.x+size2.width/2,bottom:platedHole.y-size2.height/2},width:size2.width,height:size2.height}}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_plated_hole.update(this.pcb_plated_hole_id,{x:newCenter.x,y:newCenter.y}),this.matchedPort?._setPositionFromLayout(newCenter)}doInitialPortMatching(){let parentPorts=this.getPrimitiveContainer()?.selectAll("port");if(this.props.portHints){for(let port of parentPorts)if(port.isMatchingAnyOf(this.props.portHints)){this.matchedPort=port,port.registerMatch(this);return}}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,subcircuit=this.getSubcircuit(),soldermaskMargin=props.solderMaskMargin,isCoveredWithSolderMask=props.coveredWithSolderMask??!1;if(this.emitSolderMaskMarginWarning(isCoveredWithSolderMask,soldermaskMargin),props.shape==="circle"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,outer_diameter:props.outerDiameter,hole_diameter:props.holeDiameter,shape:"circle",port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id,db.pcb_solder_paste.insert({layer:"top",shape:"circle",radius:props.outerDiameter/2,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),db.pcb_solder_paste.insert({layer:"bottom",shape:"circle",radius:props.outerDiameter/2,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else if(props.shape==="pill"&&props.rectPad){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,outer_width:props.outerWidth,outer_height:props.outerHeight,hole_width:props.holeWidth,hole_height:props.holeHeight,shape:"rotated_pill_hole_with_rect_pad",type:"pcb_plated_hole",port_hints:this.getNameAndAliases(),pcb_plated_hole_id:this.pcb_plated_hole_id,x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,hole_shape:"rotated_pill",pad_shape:"rect",hole_ccw_rotation:props.pcbRotation??0,rect_ccw_rotation:props.pcbRotation??0,rect_pad_width:props.outerWidth,rect_pad_height:props.outerHeight,hole_offset_x:props.holeOffsetX,hole_offset_y:props.holeOffsetY});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}else if(props.shape==="pill"||props.shape==="oval"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,outer_width:props.outerWidth,outer_height:props.outerHeight,hole_width:props.holeWidth,hole_height:props.holeHeight,shape:props.shape,port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,ccw_rotation:props.pcbRotation??0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id,db.pcb_solder_paste.insert({layer:"top",shape:props.shape,width:props.outerWidth,height:props.outerHeight,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0}),db.pcb_solder_paste.insert({layer:"bottom",shape:props.shape,width:props.outerWidth,height:props.outerHeight,x:position2.x,y:position2.y,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0})}else if(props.shape==="circular_hole_with_rect_pad"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,hole_diameter:props.holeDiameter,rect_pad_width:props.rectPadWidth,rect_pad_height:props.rectPadHeight,shape:"circular_hole_with_rect_pad",port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,hole_offset_x:props.holeOffsetX,hole_offset_y:props.holeOffsetY,rect_border_radius:props.rectBorderRadius??0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}else if(props.shape==="pill_hole_with_rect_pad"){let pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,hole_width:props.holeWidth,hole_height:props.holeHeight,rect_pad_width:props.rectPadWidth,rect_pad_height:props.rectPadHeight,hole_offset_x:props.holeOffsetX,hole_offset_y:props.holeOffsetY,shape:"pill_hole_with_rect_pad",port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}else if(props.shape==="hole_with_polygon_pad"){let padOutline=(props.padOutline||[]).map(point6=>{let x5=typeof point6.x=="number"?point6.x:parseFloat(String(point6.x)),y5=typeof point6.y=="number"?point6.y:parseFloat(String(point6.y));return{x:x5,y:y5}}),pcb_plated_hole2=db.pcb_plated_hole.insert({pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,shape:"hole_with_polygon_pad",hole_shape:props.holeShape||"circle",hole_diameter:props.holeDiameter,hole_width:props.holeWidth,hole_height:props.holeHeight,pad_outline:padOutline,hole_offset_x:typeof props.holeOffsetX=="number"?props.holeOffsetX:parseFloat(String(props.holeOffsetX||0)),hole_offset_y:typeof props.holeOffsetY=="number"?props.holeOffsetY:parseFloat(String(props.holeOffsetY||0)),port_hints:this.getNameAndAliases(),x:position2.x,y:position2.y,layers:["top","bottom"],soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_plated_hole_id=pcb_plated_hole2.pcb_plated_hole_id}}doInitialPcbPortAttachment(){if(this.root?.pcbDisabled)return;let{db}=this.root;db.pcb_plated_hole.update(this.pcb_plated_hole_id,{pcb_port_id:this.matchedPort?.pcb_port_id})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_plated_hole_id)return;let hole=db.pcb_plated_hole.get(this.pcb_plated_hole_id);if(hole){let newCenter={x:hole.x+deltaX,y:hole.y+deltaY};this._setPositionFromLayout(newCenter)}}},Keepout=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_keepout_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"Keepout",zodProps:pcbKeepoutProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let subcircuit=this.getSubcircuit(),{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),decomposedMat=decomposeTSR(this._computePcbGlobalTransformBeforeLayout()),isRotated90=Math.abs(decomposedMat.rotation.angle*(180/Math.PI)-90)%180<.01,pcb_keepout2=null;props.shape==="circle"?pcb_keepout2=db.pcb_keepout.insert({layers:["top"],shape:"circle",radius:props.radius,center:{x:position2.x,y:position2.y},subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0}):props.shape==="rect"&&(pcb_keepout2=db.pcb_keepout.insert({layers:["top"],shape:"rect",...isRotated90?{width:props.height,height:props.width}:{width:props.width,height:props.height},center:{x:position2.x,y:position2.y},subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0})),pcb_keepout2&&(this.pcb_keepout_id=pcb_keepout2.pcb_keepout_id)}},Hole=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_hole_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"Hole",zodProps:holeProps}}getPcbSize(){let{_parsedProps:props}=this,isPill=props.shape==="pill",isRect=props.shape==="rect";return isPill?{width:props.width,height:props.height}:isRect?{width:props.width,height:props.height}:{width:props.diameter,height:props.diameter}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,subcircuit=this.getSubcircuit(),position2=this._getGlobalPcbPositionBeforeLayout(),soldermaskMargin=props.solderMaskMargin,isCoveredWithSolderMask=props.coveredWithSolderMask??!1,pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id;if(this.emitSolderMaskMarginWarning(isCoveredWithSolderMask,soldermaskMargin),props.shape==="pill")if(props.pcbRotation&&props.pcbRotation!==0){let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"rotated_pill",hole_width:props.width,hole_height:props.height,x:position2.x,y:position2.y,ccw_rotation:props.pcbRotation,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}else{let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"pill",hole_width:props.width,hole_height:props.height,x:position2.x,y:position2.y,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}else if(props.shape==="rect"){let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"rect",hole_width:props.width,hole_height:props.height,x:position2.x,y:position2.y,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}else{let inserted_hole=db.pcb_hole.insert({pcb_component_id,type:"pcb_hole",hole_shape:"circle",hole_diameter:props.diameter,x:position2.x,y:position2.y,soldermask_margin:soldermaskMargin,is_covered_with_solder_mask:isCoveredWithSolderMask,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_hole_id=inserted_hole.pcb_hole_id}}_getPcbCircuitJsonBounds(){let{db}=this.root,hole=db.pcb_hole.get(this.pcb_hole_id),size2=this.getPcbSize();return{center:{x:hole.x,y:hole.y},bounds:{left:hole.x-size2.width/2,top:hole.y-size2.height/2,right:hole.x+size2.width/2,bottom:hole.y+size2.height/2},width:size2.width,height:size2.height}}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_hole.update(this.pcb_hole_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_hole_id)return;let hole=db.pcb_hole.get(this.pcb_hole_id);hole&&db.pcb_hole.update(this.pcb_hole_id,{x:hole.x+deltaX,y:hole.y+deltaY})}};function normalizeTextForCircuitJson(text){return text.replace(/\\n/g,`
|
|
620
620
|
`)}var SilkscreenText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_text_ids",[]);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenText",zodProps:silkscreenTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,container=this.getPrimitiveContainer(),position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer,isFlipped}=this._getPcbPrimitiveFlippedHelpers(),subcircuit=this.getSubcircuit(),rotation4=0;if(props.pcbRotation!==void 0&&props.pcbRotation!==0)rotation4=props.pcbRotation;else{let globalTransform=this._computePcbGlobalTransformBeforeLayout();rotation4=decomposeTSR(globalTransform).rotation.angle*180/Math.PI}isFlipped&&(rotation4=(rotation4+180)%360);let uniqueLayers=new Set(props.layers);props.layer&&uniqueLayers.add(props.layer);let targetLayers=uniqueLayers.size>0?Array.from(uniqueLayers):["top"],fontSize=props.fontSize??this.getInheritedProperty("pcbStyle")?.silkscreenFontSize??1;for(let layer of targetLayers){let pcb_silkscreen_text2=db.pcb_silkscreen_text.insert({anchor_alignment:props.anchorAlignment,anchor_position:{x:position2.x,y:position2.y},font:props.font??"tscircuit2024",font_size:fontSize,layer:maybeFlipLayer(layer),text:normalizeTextForCircuitJson(props.text??""),ccw_rotation:rotation4,pcb_component_id:container.pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_silkscreen_text_ids.push(pcb_silkscreen_text2.pcb_silkscreen_text_id)}}getPcbSize(){let{_parsedProps:props}=this,fontSize=props.fontSize??this.getInheritedProperty("pcbStyle")?.silkscreenFontSize??1,textWidth=(props.text??"").length*fontSize,textHeight=fontSize;return{width:textWidth*fontSize,height:textHeight*fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;for(let id of this.pcb_silkscreen_text_ids){let text=db.pcb_silkscreen_text.get(id);text&&db.pcb_silkscreen_text.update(id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}}},Cutout=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_cutout_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"Cutout",zodProps:cutoutProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,subcircuit=this.getSubcircuit(),pcb_group_id=this.getGroup()?.pcb_group_id??void 0,globalPosition=this._getGlobalPcbPositionBeforeLayout(),parentRotation=this.getPrimitiveContainer()?._parsedProps.pcbRotation??0,inserted_pcb_cutout;if(props.shape==="rect"){let rotationDeg=typeof parentRotation=="string"?parseInt(parentRotation.replace("deg",""),10):parentRotation,isRotated90=Math.abs(rotationDeg%180)===90,rectData={shape:"rect",center:globalPosition,width:isRotated90?props.height:props.width,height:isRotated90?props.width:props.height,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id};inserted_pcb_cutout=db.pcb_cutout.insert(rectData)}else if(props.shape==="circle"){let circleData={shape:"circle",center:globalPosition,radius:props.radius,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id};inserted_pcb_cutout=db.pcb_cutout.insert(circleData)}else if(props.shape==="polygon"){let transform5=this._computePcbGlobalTransformBeforeLayout(),polygonData={shape:"polygon",points:props.points.map(p4=>applyToPoint(transform5,p4)),subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id};inserted_pcb_cutout=db.pcb_cutout.insert(polygonData)}inserted_pcb_cutout&&(this.pcb_cutout_id=inserted_pcb_cutout.pcb_cutout_id)}getPcbSize(){let{_parsedProps:props}=this;if(props.shape==="rect")return{width:props.width,height:props.height};if(props.shape==="circle")return{width:props.radius*2,height:props.radius*2};if(props.shape==="polygon"){if(props.points.length===0)return{width:0,height:0};let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of props.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{width:maxX-minX,height:maxY-minY}}return{width:0,height:0}}_getPcbCircuitJsonBounds(){if(!this.pcb_cutout_id)return super._getPcbCircuitJsonBounds();let{db}=this.root,cutout=db.pcb_cutout.get(this.pcb_cutout_id);if(!cutout)return super._getPcbCircuitJsonBounds();if(cutout.shape==="rect")return{center:cutout.center,bounds:{left:cutout.center.x-cutout.width/2,top:cutout.center.y+cutout.height/2,right:cutout.center.x+cutout.width/2,bottom:cutout.center.y-cutout.height/2},width:cutout.width,height:cutout.height};if(cutout.shape==="circle")return{center:cutout.center,bounds:{left:cutout.center.x-cutout.radius,top:cutout.center.y+cutout.radius,right:cutout.center.x+cutout.radius,bottom:cutout.center.y-cutout.radius},width:cutout.radius*2,height:cutout.radius*2};if(cutout.shape==="polygon"){if(cutout.points.length===0)return super._getPcbCircuitJsonBounds();let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0;for(let point6 of cutout.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{center:{x:(minX+maxX)/2,y:(minY+maxY)/2},bounds:{left:minX,top:maxY,right:maxX,bottom:minY},width:maxX-minX,height:maxY-minY}}return super._getPcbCircuitJsonBounds()}_setPositionFromLayout(newCenter){if(!this.pcb_cutout_id)return;let{db}=this.root,cutout=db.pcb_cutout.get(this.pcb_cutout_id);if(cutout){if(cutout.shape==="rect"||cutout.shape==="circle")db.pcb_cutout.update(this.pcb_cutout_id,{...cutout,center:newCenter});else if(cutout.shape==="polygon"){let oldCenter=this._getPcbCircuitJsonBounds().center,dx2=newCenter.x-oldCenter.x,dy2=newCenter.y-oldCenter.y,newPoints=cutout.points.map(p4=>({x:p4.x+dx2,y:p4.y+dy2}));db.pcb_cutout.update(this.pcb_cutout_id,{...cutout,points:newPoints})}}}_moveCircuitJsonElements({deltaX,deltaY}){if(!this.pcb_cutout_id)return;let{db}=this.root,cutout=db.pcb_cutout.get(this.pcb_cutout_id);cutout&&(cutout.shape==="rect"||cutout.shape==="circle"?db.pcb_cutout.update(this.pcb_cutout_id,{center:{x:cutout.center.x+deltaX,y:cutout.center.y+deltaY}}):cutout.shape==="polygon"&&db.pcb_cutout.update(this.pcb_cutout_id,{points:cutout.points.map(p4=>({x:p4.x+deltaX,y:p4.y+deltaY}))}))}},createPinrowSilkscreenText=({elm,pinLabels,layer,readableRotation,anchorAlignment})=>{let pinNum=elm.text.replace(/[{}]/g,"").toLowerCase(),label=pinNum;if(Array.isArray(pinLabels)){let index=parseInt(pinNum.replace(/[^\d]/g,""),10)-1;label=String(pinLabels[index]??pinNum)}else typeof pinLabels=="object"&&(label=String(pinLabels[pinNum]??pinNum));return new SilkscreenText({anchorAlignment:anchorAlignment||"center",text:label??pinNum,layer:layer||"top",fontSize:elm.font_size+.2,pcbX:isNaN(elm.anchor_position.x)?0:elm.anchor_position.x,pcbY:elm.anchor_position.y,pcbRotation:readableRotation??0})},calculateCcwRotation=(componentRotationStr,elementCcwRotation)=>{let componentAngle=parseInt(componentRotationStr||"0",10),totalRotation;return elementCcwRotation!=null?totalRotation=elementCcwRotation-componentAngle:totalRotation=componentAngle,(totalRotation%360+360)%360},createComponentsFromCircuitJson=({componentName,componentRotation,footprinterString,pinLabels,pcbPinLabels},circuitJson)=>{let components=[];for(let elm of circuitJson)if(elm.type==="pcb_smtpad"&&elm.shape==="rect")components.push(new SmtPad({pcbX:elm.x,pcbY:elm.y,layer:elm.layer,shape:"rect",height:elm.height,width:elm.width,portHints:elm.port_hints,rectBorderRadius:elm.rect_border_radius}));else if(elm.type==="pcb_smtpad"&&elm.shape==="circle")components.push(new SmtPad({pcbX:elm.x,pcbY:elm.y,layer:elm.layer,shape:"circle",radius:elm.radius,portHints:elm.port_hints}));else if(elm.type==="pcb_smtpad"&&elm.shape==="pill")components.push(new SmtPad({shape:"pill",height:elm.height,width:elm.width,radius:elm.radius,portHints:elm.port_hints,pcbX:elm.x,pcbY:elm.y,layer:elm.layer}));else if(elm.type==="pcb_silkscreen_path")components.push(new SilkscreenPath({layer:elm.layer,route:elm.route,strokeWidth:elm.stroke_width}));else if(elm.type==="pcb_plated_hole")elm.shape==="circle"?components.push(new PlatedHole({pcbX:elm.x,pcbY:elm.y,shape:"circle",holeDiameter:elm.hole_diameter,outerDiameter:elm.outer_diameter,portHints:elm.port_hints})):elm.shape==="circular_hole_with_rect_pad"?components.push(new PlatedHole({pcbX:elm.x,pcbY:elm.y,shape:"circular_hole_with_rect_pad",holeDiameter:elm.hole_diameter,rectPadHeight:elm.rect_pad_height,rectPadWidth:elm.rect_pad_width,portHints:elm.port_hints,rectBorderRadius:elm.rect_border_radius,holeOffsetX:elm.hole_offset_x,holeOffsetY:elm.hole_offset_y})):elm.shape==="pill"||elm.shape==="oval"?components.push(new PlatedHole({pcbX:elm.x,pcbY:elm.y,shape:elm.shape,holeWidth:elm.hole_width,holeHeight:elm.hole_height,outerWidth:elm.outer_width,outerHeight:elm.outer_height,portHints:elm.port_hints})):elm.shape==="pill_hole_with_rect_pad"?components.push(new PlatedHole({pcbX:elm.x,pcbY:elm.y,shape:"pill_hole_with_rect_pad",holeShape:"pill",padShape:"rect",holeWidth:elm.hole_width,holeHeight:elm.hole_height,rectPadWidth:elm.rect_pad_width,rectPadHeight:elm.rect_pad_height,portHints:elm.port_hints,holeOffsetX:elm.hole_offset_x,holeOffsetY:elm.hole_offset_y})):elm.shape==="hole_with_polygon_pad"&&components.push(new PlatedHole({pcbX:elm.x,pcbY:elm.y,shape:"hole_with_polygon_pad",holeShape:elm.hole_shape||"circle",holeDiameter:elm.hole_diameter,holeWidth:elm.hole_width,holeHeight:elm.hole_height,padOutline:elm.pad_outline||[],holeOffsetX:elm.hole_offset_x,holeOffsetY:elm.hole_offset_y,portHints:elm.port_hints}));else if(elm.type==="pcb_keepout"&&elm.shape==="circle")components.push(new Keepout({pcbX:elm.center.x,pcbY:elm.center.y,shape:"circle",radius:elm.radius}));else if(elm.type==="pcb_keepout"&&elm.shape==="rect")components.push(new Keepout({pcbX:elm.center.x,pcbY:elm.center.y,shape:"rect",width:elm.width,height:elm.height}));else if(elm.type==="pcb_hole"&&elm.hole_shape==="circle")components.push(new Hole({pcbX:elm.x,pcbY:elm.y,diameter:elm.hole_diameter}));else if(elm.type==="pcb_hole"&&elm.hole_shape==="rect")components.push(new Hole({pcbX:elm.x,pcbY:elm.y,shape:"rect",width:elm.hole_width,height:elm.hole_height}));else if(elm.type==="pcb_hole"&&elm.hole_shape==="pill")components.push(new Hole({pcbX:elm.x,pcbY:elm.y,shape:"pill",width:elm.hole_width,height:elm.hole_height}));else if(elm.type==="pcb_hole"&&elm.hole_shape==="rotated_pill")components.push(new Hole({pcbX:elm.x,pcbY:elm.y,shape:"pill",width:elm.hole_width,height:elm.hole_height,pcbRotation:elm.ccw_rotation}));else if(elm.type==="pcb_cutout")elm.shape==="rect"?components.push(new Cutout({pcbX:elm.center.x,pcbY:elm.center.y,shape:"rect",width:elm.width,height:elm.height})):elm.shape==="circle"?components.push(new Cutout({pcbX:elm.center.x,pcbY:elm.center.y,shape:"circle",radius:elm.radius})):elm.shape==="polygon"&&components.push(new Cutout({shape:"polygon",points:elm.points}));else if(elm.type==="pcb_silkscreen_text"){let ccwRotation=calculateCcwRotation(componentRotation,elm.ccw_rotation);footprinterString?.includes("pinrow")&&elm.text.includes("PIN")?components.push(createPinrowSilkscreenText({elm,pinLabels:pcbPinLabels??pinLabels??{},layer:elm.layer,readableRotation:ccwRotation,anchorAlignment:elm.anchor_alignment})):components.push(new SilkscreenText({anchorAlignment:elm.anchor_alignment||"center",text:componentName||elm.text,fontSize:elm.font_size+.2,pcbX:Number.isNaN(elm.anchor_position.x)?0:elm.anchor_position.x,pcbY:elm.anchor_position.y,pcbRotation:ccwRotation??0}))}else elm.type==="pcb_trace"&&components.push(new PcbTrace({route:elm.route}));return components};function getBoundsOfPcbComponents(components){let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0,hasValidComponents=!1;for(let child of components)if(child.isPcbPrimitive&&!child.componentName.startsWith("Silkscreen")&&!child.componentName.startsWith("PcbNote")){let{x:x5,y:y5}=child._getGlobalPcbPositionBeforeLayout(),{width:width2,height:height2}=child.getPcbSize();minX=Math.min(minX,x5-width2/2),minY=Math.min(minY,y5-height2/2),maxX=Math.max(maxX,x5+width2/2),maxY=Math.max(maxY,y5+height2/2),hasValidComponents=!0}else if(child.children.length>0){let childBounds=getBoundsOfPcbComponents(child.children);(childBounds.width>0||childBounds.height>0)&&(minX=Math.min(minX,childBounds.minX),minY=Math.min(minY,childBounds.minY),maxX=Math.max(maxX,childBounds.maxX),maxY=Math.max(maxY,childBounds.maxY),hasValidComponents=!0)}if(!hasValidComponents)return{minX:0,minY:0,maxX:0,maxY:0,width:0,height:0};let width=maxX-minX,height=maxY-minY;return width<0&&(width=0),height<0&&(height=0),{minX,minY,maxX,maxY,width,height}}function normalizeAngle(angle){let normalized=angle%360;return normalized<0?normalized+360:normalized}function isAngleBetween(angle,start,end,direction2){return direction2==="counterclockwise"?end>=start?angle>=start&&angle<=end:angle>=start||angle<=end:end<=start?angle<=start&&angle>=end:angle<=start||angle>=end}function getArcBounds(elm){let center2=elm.center,radius=elm.radius,startAngle=elm.start_angle_degrees,endAngle=elm.end_angle_degrees,direction2=elm.direction??"counterclockwise";if(!center2||typeof center2.x!="number"||typeof center2.y!="number"||typeof radius!="number"||typeof startAngle!="number"||typeof endAngle!="number")return null;let start=normalizeAngle(startAngle),end=normalizeAngle(endAngle),consideredAngles=new Set([start,end]),cardinalAngles=[0,90,180,270];for(let cardinal of cardinalAngles)isAngleBetween(cardinal,start,end,direction2)&&consideredAngles.add(cardinal);let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let angle of consideredAngles){let radians=angle*Math.PI/180,x5=center2.x+radius*Math.cos(radians),y5=center2.y+radius*Math.sin(radians);minX=Math.min(minX,x5),maxX=Math.max(maxX,x5),minY=Math.min(minY,y5),maxY=Math.max(maxY,y5)}return!Number.isFinite(minX)||!Number.isFinite(minY)?null:{minX,maxX,minY,maxY}}function getBoundsForSchematic(db){let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let elm of db){let cx2,cy2,w4,h4;if(elm.type==="schematic_component")cx2=elm.center?.x,cy2=elm.center?.y,w4=elm.size?.width,h4=elm.size?.height;else if(elm.type==="schematic_box")cx2=elm.x,cy2=elm.y,w4=elm.width,h4=elm.height;else if(elm.type==="schematic_port")cx2=elm.center?.x,cy2=elm.center?.y,w4=.2,h4=.2;else if(elm.type==="schematic_text")cx2=elm.position?.x,cy2=elm.position?.y,w4=(elm.text?.length??0)*.1,h4=.2;else if(elm.type==="schematic_line"){let x12=elm.x1??0,y12=elm.y1??0,x22=elm.x2??0,y22=elm.y2??0;cx2=(x12+x22)/2,cy2=(y12+y22)/2,w4=Math.abs(x22-x12),h4=Math.abs(y22-y12)}else if(elm.type==="schematic_rect")cx2=elm.center?.x,cy2=elm.center?.y,w4=elm.width,h4=elm.height;else if(elm.type==="schematic_circle"){cx2=elm.center?.x,cy2=elm.center?.y;let radius=elm.radius;typeof radius=="number"&&(w4=radius*2,h4=radius*2)}else if(elm.type==="schematic_arc"){let bounds=getArcBounds(elm);bounds&&(minX=Math.min(minX,bounds.minX),maxX=Math.max(maxX,bounds.maxX),minY=Math.min(minY,bounds.minY),maxY=Math.max(maxY,bounds.maxY));continue}else if(elm.type==="schematic_path"){let points=elm.points;if(Array.isArray(points))for(let point6 of points)typeof point6.x=="number"&&typeof point6.y=="number"&&(minX=Math.min(minX,point6.x),maxX=Math.max(maxX,point6.x),minY=Math.min(minY,point6.y),maxY=Math.max(maxY,point6.y));continue}typeof cx2=="number"&&typeof cy2=="number"&&typeof w4=="number"&&typeof h4=="number"&&(minX=Math.min(minX,cx2-w4/2),maxX=Math.max(maxX,cx2+w4/2),minY=Math.min(minY,cy2-h4/2),maxY=Math.max(maxY,cy2+h4/2))}return{minX,maxX,minY,maxY}}function getRelativeDirection(pointA,pointB){let dx2=pointB.x-pointA.x,dy2=pointB.y-pointA.y;return Math.abs(dx2)>Math.abs(dy2)?dx2>=0?"right":"left":dy2>=0?"up":"down"}var areAllPcbPrimitivesOverlapping=pcbPrimitives=>{if(pcbPrimitives.length<=1)return!0;let bounds=pcbPrimitives.map(p4=>{let circuitBounds=p4._getPcbCircuitJsonBounds();return{left:circuitBounds.bounds.left,right:circuitBounds.bounds.right,top:circuitBounds.bounds.top,bottom:circuitBounds.bounds.bottom}}),overlaps=Array(bounds.length).fill(!1).map(()=>Array(bounds.length).fill(!1));for(let i2=0;i2<bounds.length;i2++)for(let j4=i2+1;j4<bounds.length;j4++){let a2=bounds[i2],b3=bounds[j4];overlaps[i2][j4]=overlaps[j4][i2]=!(a2.right<b3.left||a2.left>b3.right||a2.bottom>b3.top||a2.top<b3.bottom)}let visited=new Set,dfs=node=>{visited.add(node);for(let i2=0;i2<bounds.length;i2++)overlaps[node][i2]&&!visited.has(i2)&&dfs(i2)};return dfs(0),visited.size===bounds.length},getCenterOfPcbPrimitives=pcbPrimitives=>{if(pcbPrimitives.length===0)throw new Error("Cannot get center of empty PCB primitives array");let positions=pcbPrimitives.map(p4=>p4._getPcbCircuitJsonBounds().center).filter(Boolean),sumX=positions.reduce((sum,pos)=>sum+pos.x,0),sumY=positions.reduce((sum,pos)=>sum+pos.y,0);return{x:sumX/positions.length,y:sumY/positions.length}},portProps2=external_exports.object({name:external_exports.string().optional(),pinNumber:external_exports.number().optional(),aliases:external_exports.array(external_exports.string()).optional(),layer:external_exports.string().optional(),layers:external_exports.array(external_exports.string()).optional(),schX:external_exports.number().optional(),schY:external_exports.number().optional(),direction:external_exports.enum(["up","down","left","right"]).optional(),connectsTo:external_exports.union([external_exports.string(),external_exports.array(external_exports.string())]).optional()}),Port=class extends PrimitiveComponent2{constructor(props,opts={}){if(!props.name&&props.pinNumber!==void 0&&(props.name=`pin${props.pinNumber}`),!props.name)throw new Error("Port must have a name or a pinNumber");super(props);__publicField(this,"source_port_id",null);__publicField(this,"pcb_port_id",null);__publicField(this,"schematic_port_id",null);__publicField(this,"schematicSymbolPortDef",null);__publicField(this,"matchedComponents");__publicField(this,"facingDirection",null);__publicField(this,"originDescription",null);opts.originDescription&&(this.originDescription=opts.originDescription),this.matchedComponents=[]}get config(){return{componentName:"Port",zodProps:portProps2}}isGroupPort(){return this.parent?.componentName==="Group"}isComponentPort(){return!this.isGroupPort()}_getConnectedPortsFromConnectsTo(){let{_parsedProps:props}=this,connectsTo=props.connectsTo;if(!connectsTo)return[];let connectedPorts=[],connectsToArray=Array.isArray(connectsTo)?connectsTo:[connectsTo];for(let connection of connectsToArray){let port=this.getSubcircuit().selectOne(connection,{type:"port"});port&&connectedPorts.push(port)}return connectedPorts}_isBoardPinoutFromAttributes(){let parent=this.parent;if(parent?._parsedProps?.pinAttributes){let pinAttributes=parent._parsedProps.pinAttributes;for(let alias of this.getNameAndAliases())if(pinAttributes[alias]?.includeInBoardPinout)return!0}}_getGlobalPcbPositionBeforeLayout(){let matchedPcbElm=this.matchedComponents.find(c3=>c3.isPcbPrimitive),parentComponent=this.parent;if(parentComponent&&!parentComponent.props.footprint)throw new Error(`${parentComponent.componentName} "${parentComponent.props.name}" does not have a footprint. Add a footprint prop, e.g. <${parentComponent.componentName.toLowerCase()} footprint="..." />`);if(!matchedPcbElm)throw new Error(`Port ${this} has no matching PCB primitives. This often means the footprint's pads lack matching port hints.`);return matchedPcbElm?._getGlobalPcbPositionBeforeLayout()??{x:0,y:0}}_getPcbCircuitJsonBounds(){if(!this.pcb_port_id)return super._getPcbCircuitJsonBounds();let{db}=this.root,pcb_port2=db.pcb_port.get(this.pcb_port_id);return{center:{x:pcb_port2.x,y:pcb_port2.y},bounds:{left:0,top:0,right:0,bottom:0},width:0,height:0}}_getGlobalPcbPositionAfterLayout(){return this._getPcbCircuitJsonBounds().center}_getPortsInternallyConnectedToThisPort(){let parent=this.parent;if(!parent||!parent._getInternallyConnectedPins)return[];let internallyConnectedPorts=parent._getInternallyConnectedPins();for(let ports of internallyConnectedPorts)if(ports.some(port=>port===this))return ports;return[]}_hasSchematicPort(){let{schX,schY}=this._parsedProps;if(schX!==void 0&&schY!==void 0)return!0;let parentNormalComponent=this.getParentNormalComponent();if(parentNormalComponent?.getSchematicSymbol())return!!(this.schematicSymbolPortDef||this._getPortsInternallyConnectedToThisPort().some(p4=>p4.schematicSymbolPortDef));let parentBoxDim=parentNormalComponent?._getSchematicBoxDimensions();return!!(parentBoxDim&&this.props.pinNumber!==void 0&&parentBoxDim.getPortPositionByPinNumber(this.props.pinNumber))}_getGlobalSchematicPositionBeforeLayout(){let{schX,schY}=this._parsedProps;if(schX!==void 0&&schY!==void 0)return{x:schX,y:schY};let parentNormalComponent=this.getParentNormalComponent(),symbol=parentNormalComponent?.getSchematicSymbol();if(symbol){let schematicSymbolPortDef=this.schematicSymbolPortDef;if(!schematicSymbolPortDef&&(schematicSymbolPortDef=this._getPortsInternallyConnectedToThisPort().find(p4=>p4.schematicSymbolPortDef)?.schematicSymbolPortDef??null,!schematicSymbolPortDef))throw new Error(`Couldn't find schematicSymbolPortDef for port ${this.getString()}, searched internally connected ports and none had a schematicSymbolPortDef. Why are we trying to get the schematic position of this port?`);let transform5=compose(parentNormalComponent.computeSchematicGlobalTransform(),translate(-symbol.center.x,-symbol.center.y));return applyToPoint(transform5,schematicSymbolPortDef)}let parentBoxDim=parentNormalComponent?._getSchematicBoxDimensions();if(parentBoxDim&&this.props.pinNumber!==void 0){let localPortPosition=parentBoxDim.getPortPositionByPinNumber(this.props.pinNumber);if(!localPortPosition)throw new Error(`Couldn't find position for schematic_port for port ${this.getString()} inside of the schematic box`);return applyToPoint(parentNormalComponent.computeSchematicGlobalTransform(),localPortPosition)}throw new Error(`Couldn't find position for schematic_port for port ${this.getString()}`)}_getGlobalSchematicPositionAfterLayout(){let{db}=this.root;if(!this.schematic_port_id)throw new Error(`Can't get schematic port position after layout for "${this.getString()}", no schematic_port_id`);let schematic_port2=db.schematic_port.get(this.schematic_port_id);if(!schematic_port2)throw new Error(`Schematic port not found when trying to get post-layout position: ${this.schematic_port_id}`);return schematic_port2.center}registerMatch(component){this.matchedComponents.push(component)}getNameAndAliases(){let{_parsedProps:props}=this;return Array.from(new Set([...props.name?[props.name]:[],...props.aliases??[],...typeof props.pinNumber=="number"?[`pin${props.pinNumber}`,props.pinNumber.toString()]:[],...this.externallyAddedAliases??[]]))}_getMatchingPinAttributes(){let pinAttributes=this.parent?._parsedProps?.pinAttributes;if(!pinAttributes)return[];let matches=[];for(let alias of this.getNameAndAliases()){let attributes2=pinAttributes[alias];attributes2&&matches.push(attributes2)}return matches}_shouldIncludeInBoardPinout(){return this._getMatchingPinAttributes().some(attributes2=>attributes2.includeInBoardPinout===!0)}isMatchingPort(port){return this.isMatchingAnyOf(port.getNameAndAliases())}getPortSelector(){return`.${(this.getParentNormalComponent()??this.parent)?.props.name} > port.${this.props.name}`}getAvailablePcbLayers(){let{layer,layers}=this._parsedProps;return layers||(layer?[layer]:Array.from(new Set(this.matchedComponents.flatMap(c3=>c3.getAvailablePcbLayers()))))}_getDirectlyConnectedTraces(){return this.getSubcircuit().selectAll("trace").filter(trace=>!trace._couldNotFindPort).filter(trace=>trace._isExplicitlyConnectedToPort(this))}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,port_hints=this.getNameAndAliases(),parentNormalComponent=this.getParentNormalComponent(),source_component_id=(this.parent?.source_component_id?this.parent:parentNormalComponent)?.source_component_id??null,pinAttributes=this._getMatchingPinAttributes(),portAttributesFromParent={};for(let attributes2 of pinAttributes)attributes2.mustBeConnected!==void 0&&(portAttributesFromParent.must_be_connected=attributes2.mustBeConnected);let source_port2=db.source_port.insert({name:props.name,pin_number:props.pinNumber,port_hints,source_component_id,subcircuit_id:this.getSubcircuit()?.subcircuit_id,...portAttributesFromParent});this.source_port_id=source_port2.source_port_id}doInitialSourceParentAttachment(){let{db}=this.root,parentNormalComponent=this.getParentNormalComponent(),parentWithSourceId=this.parent?.source_component_id?this.parent:parentNormalComponent;if(this.isGroupPort()){db.source_port.update(this.source_port_id,{source_component_id:null,subcircuit_id:this.getSubcircuit()?.subcircuit_id});return}if(!parentWithSourceId?.source_component_id)throw new Error(`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`);db.source_port.update(this.source_port_id,{source_component_id:parentWithSourceId.source_component_id,subcircuit_id:this.getSubcircuit()?.subcircuit_id}),this.source_component_id=parentWithSourceId.source_component_id}doInitialPcbPortRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{matchedComponents}=this;if(this.isGroupPort()){let connectedPorts=this._getConnectedPortsFromConnectsTo();if(connectedPorts.length===0)return;let connectedPort=connectedPorts[0];if(!connectedPort.pcb_port_id)return;let connectedPcbPort=db.pcb_port.get(connectedPort.pcb_port_id),matchCenter2={x:connectedPcbPort.x,y:connectedPcbPort.y},subcircuit=this.getSubcircuit(),pcb_port2=db.pcb_port.insert({pcb_component_id:void 0,layers:connectedPort.getAvailablePcbLayers(),subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,...matchCenter2,source_port_id:this.source_port_id,is_board_pinout:!1});this.pcb_port_id=pcb_port2.pcb_port_id;return}let parentNormalComponent=this.getParentNormalComponent(),parentWithPcbComponentId=this.parent?.pcb_component_id?this.parent:parentNormalComponent;if(!parentWithPcbComponentId?.pcb_component_id)throw new Error(`${this.getString()} has no parent pcb component, cannot render pcb_port (parent: ${this.parent?.getString()}, parentNormalComponent: ${parentNormalComponent?.getString()})`);let pcbMatches=matchedComponents.filter(c3=>c3.isPcbPrimitive);if(pcbMatches.length===0)return;let matchCenter=null;if(pcbMatches.length===1&&(matchCenter=pcbMatches[0]._getPcbCircuitJsonBounds().center),pcbMatches.length>1){if(!areAllPcbPrimitivesOverlapping(pcbMatches))throw new Error(`${this.getString()} has multiple non-overlapping pcb matches, unclear how to place pcb_port: ${pcbMatches.map(c3=>c3.getString()).join(", ")}. (Note: tscircuit core does not currently allow you to specify internally connected pcb primitives with the same port hints, try giving them different port hints and specifying they are connected externally- or file an issue)`);matchCenter=getCenterOfPcbPrimitives(pcbMatches)}if(matchCenter){let subcircuit=this.getSubcircuit(),isBoardPinout=this._shouldIncludeInBoardPinout(),pcb_port2=db.pcb_port.insert({pcb_component_id:parentWithPcbComponentId.pcb_component_id,layers:this.getAvailablePcbLayers(),subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,...isBoardPinout?{is_board_pinout:!0}:{},...matchCenter,source_port_id:this.source_port_id,is_board_pinout:this._isBoardPinoutFromAttributes()});this.pcb_port_id=pcb_port2.pcb_port_id}else{let pcbMatch=pcbMatches[0];throw new Error(`${pcbMatch.getString()} does not have a center or _getGlobalPcbPositionBeforeLayout method (needed for pcb_port placement)`)}}updatePcbPortRender(){if(this.root?.pcbDisabled)return;let{db}=this.root;if(this.pcb_port_id)return;if(this.isGroupPort()){let connectedPorts=this._getConnectedPortsFromConnectsTo();if(connectedPorts.length===0)return;let connectedPort=connectedPorts[0];if(!connectedPort.pcb_port_id)return;let connectedPcbPort=db.pcb_port.get(connectedPort.pcb_port_id),matchCenter2={x:connectedPcbPort.x,y:connectedPcbPort.y},subcircuit2=this.getSubcircuit(),pcb_port22=db.pcb_port.insert({pcb_component_id:void 0,layers:connectedPort.getAvailablePcbLayers(),subcircuit_id:subcircuit2?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,...matchCenter2,source_port_id:this.source_port_id,is_board_pinout:!1});this.pcb_port_id=pcb_port22.pcb_port_id;return}let pcbMatches=this.matchedComponents.filter(c3=>c3.isPcbPrimitive);if(pcbMatches.length===0)return;let matchCenter=null;if(pcbMatches.length===1&&(matchCenter=pcbMatches[0]._getPcbCircuitJsonBounds().center),pcbMatches.length>1)try{areAllPcbPrimitivesOverlapping(pcbMatches)&&(matchCenter=getCenterOfPcbPrimitives(pcbMatches))}catch{}if(!matchCenter)return;let parentNormalComponent=this.getParentNormalComponent(),parentWithPcbComponentId=this.parent?.pcb_component_id?this.parent:parentNormalComponent,subcircuit=this.getSubcircuit(),isBoardPinout=this._shouldIncludeInBoardPinout(),pcb_port2=db.pcb_port.insert({pcb_component_id:parentWithPcbComponentId?.pcb_component_id,layers:this.getAvailablePcbLayers(),subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,...isBoardPinout?{is_board_pinout:!0}:{},...matchCenter,source_port_id:this.source_port_id,is_board_pinout:this._isBoardPinoutFromAttributes()});this.pcb_port_id=pcb_port2.pcb_port_id}_getBestDisplayPinLabel(){let{db}=this.root,sourcePort=db.source_port.get(this.source_port_id),labelHints=[];for(let portHint of sourcePort?.port_hints??[])portHint.match(/^(pin)?\d+$/)||portHint.match(/^(left|right)/)&&!sourcePort?.name.match(/^(left|right)/)||labelHints.push(portHint);if(this.getParentNormalComponent()?.props?.showPinAliases&&labelHints.length>0)return labelHints.join("/");if(labelHints.length>0)return labelHints[0]}doInitialSchematicPortRender(){let{db}=this.root,{_parsedProps:props}=this,{schX,schY}=props,container=schX!==void 0&&schY!==void 0?this.getParentNormalComponent():this.getPrimitiveContainer();if(!container||!this._hasSchematicPort())return;let containerCenter=container._getGlobalSchematicPositionBeforeLayout(),portCenter=this._getGlobalSchematicPositionBeforeLayout(),localPortInfo=null,containerDims=container._getSchematicBoxDimensions();containerDims&&props.pinNumber!==void 0&&(localPortInfo=containerDims.getPortPositionByPinNumber(props.pinNumber)),this.getSubcircuit().props._schDebugObjectsEnabled&&db.schematic_debug_object.insert({shape:"rect",center:portCenter,size:{width:.1,height:.1},label:"obstacle"}),localPortInfo?.side?this.facingDirection={left:"left",right:"right",top:"up",bottom:"down"}[localPortInfo.side]:this.facingDirection=getRelativeDirection(containerCenter,portCenter);let bestDisplayPinLabel=this._getBestDisplayPinLabel(),schematicPortInsertProps={type:"schematic_port",schematic_component_id:this.getParentNormalComponent()?.schematic_component_id,center:portCenter,source_port_id:this.source_port_id,facing_direction:this.facingDirection,distance_from_component_edge:.4,side_of_component:localPortInfo?.side,pin_number:props.pinNumber,true_ccw_index:localPortInfo?.trueIndex,display_pin_label:bestDisplayPinLabel,is_connected:!1};for(let attributes2 of this._getMatchingPinAttributes())attributes2.requiresPower&&(schematicPortInsertProps.has_input_arrow=!0),attributes2.providesPower&&(schematicPortInsertProps.has_output_arrow=!0);let schematic_port2=db.schematic_port.insert(schematicPortInsertProps);this.schematic_port_id=schematic_port2.schematic_port_id}_getSubcircuitConnectivityKey(){return this.root?.db.source_port.get(this.source_port_id)?.subcircuit_connectivity_map_key}_setPositionFromLayout(newCenter){let{db}=this.root;this.pcb_port_id&&db.pcb_port.update(this.pcb_port_id,{x:newCenter.x,y:newCenter.y})}_hasMatchedPcbPrimitive(){return this.matchedComponents.some(c3=>c3.isPcbPrimitive)}_getNetLabelText(){return`${this.parent?.props.name}_${this.props.name}`}},getPinNumberFromLabels=labels=>{let pinNumber=labels.find(p4=>/^(pin)?\d+$/.test(p4));return pinNumber?Number.parseInt(pinNumber.replace(/^pin/,"")):null};function getPortFromHints(hints,opts){let pinNumber=getPinNumberFromLabels(hints);if(!pinNumber)return null;let aliases2=[...hints.filter(p4=>p4.toString()!==pinNumber.toString()&&p4!==`pin${pinNumber}`),...opts?.additionalAliases?.[`pin${pinNumber}`]??[]];return new Port({pinNumber,aliases:aliases2})}var hasExplicitPinMapping=pa3=>{for(let side of["leftSide","rightSide","topSide","bottomSide"])if(side in pa3&&typeof pa3[side]=="number")throw new Error(`A number was specified for "${side}", you probably meant to use "size" not "side"`);return"leftSide"in pa3||"rightSide"in pa3||"topSide"in pa3||"bottomSide"in pa3},getSizeOfSidesFromPortArrangement=pa3=>{if(hasExplicitPinMapping(pa3))return{leftSize:pa3.leftSide?.pins.length??0,rightSize:pa3.rightSide?.pins.length??0,topSize:pa3.topSide?.pins.length??0,bottomSize:pa3.bottomSide?.pins.length??0};let{leftSize=0,rightSize=0,topSize=0,bottomSize=0}=pa3;return{leftSize,rightSize,topSize,bottomSize}},DEFAULT_SCHEMATIC_BOX_PADDING_MM=.4;function isExplicitPinMappingArrangement(arrangement){let a2=arrangement;return a2.leftSide!==void 0||a2.rightSide!==void 0||a2.topSide!==void 0||a2.bottomSide!==void 0}var getAllDimensionsForSchematicBox=params=>{let portDistanceFromEdge=params.portDistanceFromEdge??.4,sidePinCounts=params.schPortArrangement?getSizeOfSidesFromPortArrangement(params.schPortArrangement):null,sideLengths={left:0,right:0,top:0,bottom:0},pinCount=params.pinCount??null;if(pinCount===null)if(sidePinCounts)pinCount=sidePinCounts.leftSize+sidePinCounts.rightSize+sidePinCounts.topSize;else throw new Error("Could not determine pin count for the schematic box");if(pinCount&&!sidePinCounts){let rightSize=Math.floor(pinCount/2);sidePinCounts={leftSize:pinCount-rightSize,rightSize,topSize:0,bottomSize:0}}sidePinCounts||(sidePinCounts={leftSize:0,rightSize:0,topSize:0,bottomSize:0});let getPinNumberUsingSideIndex=({side,sideIndex,truePinIndex:truePinIndex2})=>{if(!params.schPortArrangement||!isExplicitPinMappingArrangement(params.schPortArrangement))return truePinIndex2+1;let normalCcwDirection={left:"top-to-bottom",bottom:"left-to-right",right:"bottom-to-top",top:"right-to-left"}[side],directionAlongSide=params.schPortArrangement?.[`${side}Side`]?.direction??normalCcwDirection,pinsDefinitionForSide=params.schPortArrangement?.[`${side}Side`]?.pins,sideIndexWithDirectionCorrection=sideIndex;return directionAlongSide!==normalCcwDirection&&(sideIndexWithDirectionCorrection=pinsDefinitionForSide.length-sideIndex-1),parsePinNumberFromLabelsOrThrow(pinsDefinitionForSide[sideIndexWithDirectionCorrection],params.pinLabels)},orderedTruePorts=[],currentDistanceFromEdge=0,truePinIndex=0;for(let sideIndex=0;sideIndex<sidePinCounts.leftSize;sideIndex++){let pinNumber=getPinNumberUsingSideIndex({side:"left",sideIndex,truePinIndex}),pinStyle=params.numericSchPinStyle?.[`pin${pinNumber}`]??params.numericSchPinStyle?.[pinNumber];pinStyle?.topMargin&&(currentDistanceFromEdge+=pinStyle.topMargin),orderedTruePorts.push({trueIndex:truePinIndex,pinNumber,side:"left",distanceFromOrthogonalEdge:currentDistanceFromEdge}),pinStyle?.bottomMargin&&(currentDistanceFromEdge+=pinStyle.bottomMargin),sideIndex===sidePinCounts.leftSize-1?sideLengths.left=currentDistanceFromEdge:currentDistanceFromEdge+=params.schPinSpacing,truePinIndex++}currentDistanceFromEdge=0;for(let sideIndex=0;sideIndex<sidePinCounts.bottomSize;sideIndex++){let pinNumber=getPinNumberUsingSideIndex({side:"bottom",sideIndex,truePinIndex}),pinStyle=params.numericSchPinStyle?.[`pin${pinNumber}`]??params.numericSchPinStyle?.[pinNumber];pinStyle?.leftMargin&&(currentDistanceFromEdge+=pinStyle.leftMargin),orderedTruePorts.push({trueIndex:truePinIndex,pinNumber,side:"bottom",distanceFromOrthogonalEdge:currentDistanceFromEdge}),pinStyle?.rightMargin&&(currentDistanceFromEdge+=pinStyle.rightMargin),sideIndex===sidePinCounts.bottomSize-1?sideLengths.bottom=currentDistanceFromEdge:currentDistanceFromEdge+=params.schPinSpacing,truePinIndex++}currentDistanceFromEdge=0;for(let sideIndex=0;sideIndex<sidePinCounts.rightSize;sideIndex++){let pinNumber=getPinNumberUsingSideIndex({side:"right",sideIndex,truePinIndex}),pinStyle=params.numericSchPinStyle?.[`pin${pinNumber}`]??params.numericSchPinStyle?.[pinNumber];pinStyle?.bottomMargin&&(currentDistanceFromEdge+=pinStyle.bottomMargin),orderedTruePorts.push({trueIndex:truePinIndex,pinNumber,side:"right",distanceFromOrthogonalEdge:currentDistanceFromEdge}),pinStyle?.topMargin&&(currentDistanceFromEdge+=pinStyle.topMargin),sideIndex===sidePinCounts.rightSize-1?sideLengths.right=currentDistanceFromEdge:currentDistanceFromEdge+=params.schPinSpacing,truePinIndex++}currentDistanceFromEdge=0;for(let sideIndex=0;sideIndex<sidePinCounts.topSize;sideIndex++){let pinNumber=getPinNumberUsingSideIndex({side:"top",sideIndex,truePinIndex}),pinStyle=params.numericSchPinStyle?.[`pin${pinNumber}`]??params.numericSchPinStyle?.[pinNumber];pinStyle?.rightMargin&&(currentDistanceFromEdge+=pinStyle.rightMargin),orderedTruePorts.push({trueIndex:truePinIndex,pinNumber,side:"top",distanceFromOrthogonalEdge:currentDistanceFromEdge}),pinStyle?.leftMargin&&(currentDistanceFromEdge+=pinStyle.leftMargin),sideIndex===sidePinCounts.topSize-1?sideLengths.top=currentDistanceFromEdge:currentDistanceFromEdge+=params.schPinSpacing,truePinIndex++}let resolvedSchWidth=params.schWidth;if(resolvedSchWidth===void 0){resolvedSchWidth=Math.max(sideLengths.top+DEFAULT_SCHEMATIC_BOX_PADDING_MM,sideLengths.bottom+DEFAULT_SCHEMATIC_BOX_PADDING_MM),params.pinLabels&&orderedTruePorts.filter(p4=>p4.side==="left"||p4.side==="right").some(p4=>params.pinLabels?.[`pin${p4.pinNumber}`]||params.pinLabels?.[p4.pinNumber])&&(resolvedSchWidth=Math.max(resolvedSchWidth,.5));let labelWidth=params.pinLabels?Math.max(...Object.values(params.pinLabels).map(label=>label.length*.1)):0,LABEL_PADDING=labelWidth>0?1.1:0;resolvedSchWidth=Math.max(resolvedSchWidth,labelWidth+LABEL_PADDING)}let schHeight=params.schHeight;schHeight||(schHeight=Math.max(sideLengths.left+DEFAULT_SCHEMATIC_BOX_PADDING_MM,sideLengths.right+DEFAULT_SCHEMATIC_BOX_PADDING_MM));let trueEdgePositions={left:{x:-resolvedSchWidth/2-portDistanceFromEdge,y:sideLengths.left/2},bottom:{x:-sideLengths.bottom/2,y:-schHeight/2-portDistanceFromEdge},right:{x:resolvedSchWidth/2+portDistanceFromEdge,y:-sideLengths.right/2},top:{x:sideLengths.top/2,y:schHeight/2+portDistanceFromEdge}},trueEdgeTraversalDirections={left:{x:0,y:-1},right:{x:0,y:1},top:{x:-1,y:0},bottom:{x:1,y:0}},truePortsWithPositions=orderedTruePorts.map(p4=>{let{distanceFromOrthogonalEdge,side}=p4,edgePos=trueEdgePositions[side],edgeDir=trueEdgeTraversalDirections[side];return{x:edgePos.x+distanceFromOrthogonalEdge*edgeDir.x,y:edgePos.y+distanceFromOrthogonalEdge*edgeDir.y,...p4}});return{getPortPositionByPinNumber(pinNumber){let port=truePortsWithPositions.find(p4=>p4.pinNumber.toString()===pinNumber.toString());return port||null},getSize(){return{width:resolvedSchWidth,height:schHeight}},getSizeIncludingPins(){return{width:resolvedSchWidth+(sidePinCounts.leftSize||sidePinCounts.rightSize?.4:0),height:schHeight+(sidePinCounts.topSize||sidePinCounts.bottomSize?.4:0)}},pinCount}},debug22=(0,import_debug8.default)("tscircuit:core:footprint"),Footprint=class extends PrimitiveComponent2{get config(){return{componentName:"Footprint",zodProps:footprintProps}}doInitialPcbFootprintLayout(){if(this.root?.pcbDisabled)return;let constraints=this.children.filter(child=>child.componentName==="Constraint");if(constraints.length===0)return;let{isFlipped}=this._getPcbPrimitiveFlippedHelpers(),maybeFlipLeftRight=props=>isFlipped&&"left"in props&&"right"in props?{...props,left:props.right,right:props.left}:props,involvedComponents=constraints.flatMap(constraint=>constraint._getAllReferencedComponents().componentsWithSelectors).map(({component,selector,componentSelector,edge})=>({component,selector,componentSelector,edge,bounds:component._getPcbCircuitJsonBounds()}));if(involvedComponents.some(c3=>c3.edge))throw new Error("edge constraints not implemented yet for footprint layout, contributions welcome!");function getComponentDetails(selector){return involvedComponents.find(({selector:s2})=>s2===selector)}let solver=new Solver,kVars={};function getKVar(name){return name in kVars||(kVars[name]=new Variable(name),solver.addEditVariable(kVars[name],Strength.weak)),kVars[name]}for(let{selector,bounds:bounds2}of involvedComponents){let kvx=getKVar(`${selector}_x`),kvy=getKVar(`${selector}_y`);solver.suggestValue(kvx,bounds2.center.x),solver.suggestValue(kvy,bounds2.center.y)}for(let constraint of constraints){let props=constraint._parsedProps;if("xDist"in props){let{xDist,left,right,edgeToEdge,centerToCenter}=maybeFlipLeftRight(props),leftVar=getKVar(`${left}_x`),rightVar=getKVar(`${right}_x`),leftBounds=getComponentDetails(left)?.bounds,rightBounds=getComponentDetails(right)?.bounds;if(centerToCenter){let expr=new Expression(rightVar,[-1,leftVar]);solver.addConstraint(new Constraint(expr,Operator.Eq,props.xDist,Strength.required))}else if(edgeToEdge){let expr=new Expression(rightVar,-rightBounds.width/2,[-1,leftVar],-leftBounds.width/2);solver.addConstraint(new Constraint(expr,Operator.Eq,props.xDist,Strength.required))}}else if("yDist"in props){let{yDist,top,bottom,edgeToEdge,centerToCenter}=props,topVar=getKVar(`${top}_y`),bottomVar=getKVar(`${bottom}_y`),topBounds=getComponentDetails(top)?.bounds,bottomBounds=getComponentDetails(bottom)?.bounds;if(centerToCenter){let expr=new Expression(topVar,[-1,bottomVar]);solver.addConstraint(new Constraint(expr,Operator.Eq,props.yDist,Strength.required))}else if(edgeToEdge){let expr=new Expression(topVar,topBounds.height/2,[-1,bottomVar],-bottomBounds.height/2);solver.addConstraint(new Constraint(expr,Operator.Eq,props.yDist,Strength.required))}}else if("sameY"in props){let{for:selectors}=props;if(selectors.length<2)continue;let vars=selectors.map(selector=>getKVar(`${selector}_y`)),expr=new Expression(...vars.slice(1));solver.addConstraint(new Constraint(expr,Operator.Eq,vars[0],Strength.required))}else if("sameX"in props){let{for:selectors}=props;if(selectors.length<2)continue;let vars=selectors.map(selector=>getKVar(`${selector}_x`)),expr=new Expression(...vars.slice(1));solver.addConstraint(new Constraint(expr,Operator.Eq,vars[0],Strength.required))}}solver.updateVariables(),debug22.enabled&&(console.log("Solution to layout constraints:"),console.table(Object.entries(kVars).map(([key,kvar])=>({var:key,val:kvar.value()}))));let bounds={left:1/0,right:-1/0,top:-1/0,bottom:1/0};for(let{selector,bounds:{width,height}}of involvedComponents){let kvx=getKVar(`${selector}_x`),kvy=getKVar(`${selector}_y`),newLeft=kvx.value()-width/2,newRight=kvx.value()+width/2,newTop=kvy.value()+height/2,newBottom=kvy.value()-height/2;bounds.left=Math.min(bounds.left,newLeft),bounds.right=Math.max(bounds.right,newRight),bounds.top=Math.max(bounds.top,newTop),bounds.bottom=Math.min(bounds.bottom,newBottom)}let globalOffset={x:-(bounds.right+bounds.left)/2,y:-(bounds.top+bounds.bottom)/2},containerPos=this.getPrimitiveContainer()._getGlobalPcbPositionBeforeLayout();globalOffset.x+=containerPos.x,globalOffset.y+=containerPos.y;for(let{component,selector}of involvedComponents){let kvx=getKVar(`${selector}_x`),kvy=getKVar(`${selector}_y`);component._setPositionFromLayout({x:kvx.value()+globalOffset.x,y:kvy.value()+globalOffset.y})}}},getFileExtension=filename=>{if(!filename)return null;let fragmentMatch=filename.match(/#ext=(\w+)$/);if(fragmentMatch)return fragmentMatch[1].toLowerCase();let sanitized=filename.split("?")[0].split("#")[0],lastSegment=sanitized.split("/").pop()??sanitized;return lastSegment.includes(".")?lastSegment.split(".").pop()?.toLowerCase()??null:null},joinUrlPath=(base,path)=>{let trimmedBase=base.replace(/\/+$/,""),trimmedPath=path.replace(/^\/+/,"");return`${trimmedBase}/${trimmedPath}`},constructAssetUrl=(targetUrl,baseUrl)=>{if(!baseUrl||!targetUrl.startsWith("/"))return targetUrl;try{let baseUrlObj=new URL(baseUrl);return baseUrlObj.pathname!=="/"&&targetUrl.startsWith(baseUrlObj.pathname)?new URL(targetUrl,baseUrlObj.origin).toString():joinUrlPath(baseUrl,targetUrl)}catch{return targetUrl}},rotation2=external_exports.union([external_exports.number(),external_exports.string()]),rotation3=external_exports.object({x:rotation2,y:rotation2,z:rotation2}),CadModel=class extends PrimitiveComponent2{get config(){return{componentName:"CadModel",zodProps:cadmodelProps}}doInitialCadModelRender(){let parent=this._findParentWithPcbComponent();if(!parent||!parent.pcb_component_id)return;let{db}=this.root,{boardThickness=0}=this.root?._getBoard()??{},bounds=parent._getPcbCircuitJsonBounds(),pcb_component2=db.pcb_component.get(parent.pcb_component_id),props=this._parsedProps;if(!props||typeof props.modelUrl!="string"&&typeof props.stepUrl!="string")return;let parentTransform=parent._computePcbGlobalTransformBeforeLayout(),accumulatedRotation=decomposeTSR(parentTransform).rotation.angle*180/Math.PI,rotationOffset=rotation3.parse({x:0,y:0,z:0});if(typeof props.rotationOffset=="number")rotationOffset.z=Number(props.rotationOffset);else if(typeof props.rotationOffset=="object"){let parsed=rotation3.parse(props.rotationOffset);rotationOffset.x=Number(parsed.x),rotationOffset.y=Number(parsed.y),rotationOffset.z=Number(parsed.z)}let{pcbX,pcbY}=this.getResolvedPcbPositionProp(),positionOffset=point32.parse({x:pcbX,y:pcbY,z:props.pcbZ??0,...typeof props.positionOffset=="object"?props.positionOffset:{}}),zOffsetFromSurface=props.zOffsetFromSurface!==void 0?distance.parse(props.zOffsetFromSurface):0,layer=parent.props.layer==="bottom"?"bottom":"top",ext=props.modelUrl?getFileExtension(props.modelUrl):void 0,modelUrlWithoutExtFragment=props.modelUrl?.replace(/#ext=\w+$/,""),urlProps={};if(ext==="stl"?urlProps.model_stl_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment):ext==="obj"?urlProps.model_obj_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment):ext==="gltf"?urlProps.model_gltf_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment):ext==="glb"?urlProps.model_glb_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment):ext==="step"||ext==="stp"?urlProps.model_step_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment):ext==="wrl"||ext==="vrml"?urlProps.model_wrl_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment):urlProps.model_stl_url=this._addCachebustToModelUrl(modelUrlWithoutExtFragment),props.stepUrl){let transformed=this._addCachebustToModelUrl(props.stepUrl);transformed&&(urlProps.model_step_url=transformed)}let cad=db.cad_component.insert({position:{x:bounds.center.x+Number(positionOffset.x),y:bounds.center.y+Number(positionOffset.y),z:(layer==="bottom"?-boardThickness/2:boardThickness/2)+(layer==="bottom"?-zOffsetFromSurface:zOffsetFromSurface)+Number(positionOffset.z)},rotation:{x:Number(rotationOffset.x),y:(layer==="top"?0:180)+Number(rotationOffset.y),z:layer==="bottom"?-(accumulatedRotation+Number(rotationOffset.z))+180:accumulatedRotation+Number(rotationOffset.z)},pcb_component_id:parent.pcb_component_id,source_component_id:parent.source_component_id,model_unit_to_mm_scale_factor:typeof props.modelUnitToMmScale=="number"?props.modelUnitToMmScale:void 0,show_as_translucent_model:parent._parsedProps.showAsTranslucentModel,...urlProps});this.cad_component_id=cad.cad_component_id}_findParentWithPcbComponent(){let p4=this.parent;for(;p4&&!p4.pcb_component_id;)p4=p4.parent;return p4}_addCachebustToModelUrl(url){if(!url)return url;let baseUrl=this.root?.platform?.projectBaseUrl,transformedUrl=constructAssetUrl(url,baseUrl);if(!transformedUrl.includes("modelcdn.tscircuit.com"))return transformedUrl;let origin=this.root?.getClientOrigin()??"";return`${transformedUrl}${transformedUrl.includes("?")?"&":"?"}cachebust_origin=${encodeURIComponent(origin)}`}},CadAssembly=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isPrimitiveContainer",!0)}get config(){return{componentName:"CadAssembly",zodProps:cadassemblyProps}}},getNumericSchPinStyle=(pinStyles,pinLabels)=>{if(!pinStyles)return;let numericPinStyles={};for(let[pinNameOrLabel,pinStyle]of Object.entries(pinStyles)){let pinNumber=parsePinNumberFromLabelsOrThrow(pinNameOrLabel,pinLabels),pinStyleWithSideFirst={leftMargin:pinStyle.marginLeft??pinStyle.leftMargin,rightMargin:pinStyle.marginRight??pinStyle.rightMargin,topMargin:pinStyle.marginTop??pinStyle.topMargin,bottomMargin:pinStyle.marginBottom??pinStyle.bottomMargin};numericPinStyles[`pin${pinNumber}`]={...numericPinStyles[`pin${pinNumber}`],...pinStyleWithSideFirst}}return numericPinStyles},DirectLineRouter=class{constructor({input:input2}){__publicField(this,"input");this.input=input2}solveAndMapToTraces(){let traces=[];for(let connection of this.input.connections){if(connection.pointsToConnect.length!==2)continue;let[start,end]=connection.pointsToConnect,trace={type:"pcb_trace",pcb_trace_id:"",connection_name:connection.name,route:[{route_type:"wire",x:start.x,y:start.y,layer:"top",width:.1},{route_type:"wire",x:end.x,y:end.y,layer:"top",width:.1}]};traces.push(trace)}return traces}},computeObstacleBounds=obstacles=>{let minX=Math.min(...obstacles.map(o3=>o3.center.x)),maxX=Math.max(...obstacles.map(o3=>o3.center.x)),minY=Math.min(...obstacles.map(o3=>o3.center.y)),maxY=Math.max(...obstacles.map(o3=>o3.center.y));return{minX,maxX,minY,maxY}},LAYER_SELECTION_PREFERENCE=["top","bottom","inner1","inner2"],findPossibleTraceLayerCombinations=(hints,layer_path=[])=>{let candidates=[];if(layer_path.length===0){let starting_layers=hints[0].layers;for(let layer of starting_layers)candidates.push(...findPossibleTraceLayerCombinations(hints.slice(1),[layer]));return candidates}if(hints.length===0)return[];let current_hint=hints[0],is_possibly_via=current_hint.via||current_hint.optional_via,last_layer=layer_path[layer_path.length-1];if(hints.length===1){let last_hint=current_hint;return last_hint.layers&&is_possibly_via?last_hint.layers.map(layer=>({layer_path:[...layer_path,layer]})):last_hint.layers?.includes(last_layer)?[{layer_path:[...layer_path,last_layer]}]:[]}if(!is_possibly_via)return current_hint.layers&&!current_hint.layers.includes(last_layer)?[]:findPossibleTraceLayerCombinations(hints.slice(1),layer_path.concat([last_layer]));let candidate_next_layers=(current_hint.optional_via?LAYER_SELECTION_PREFERENCE:LAYER_SELECTION_PREFERENCE.filter(layer=>layer!==last_layer)).filter(layer=>!current_hint.layers||current_hint.layers?.includes(layer));for(let candidate_next_layer of candidate_next_layers)candidates.push(...findPossibleTraceLayerCombinations(hints.slice(1),layer_path.concat(candidate_next_layer)));return candidates};function getDominantDirection(edge){let delta={x:edge.to.x-edge.from.x,y:edge.to.y-edge.from.y},absX=Math.abs(delta.x),absY=Math.abs(delta.y);return absX>absY?delta.x>0?"right":"left":delta.y>0?"down":"up"}function pdist(a2,b3){return Math.hypot(a2.x-b3.x,a2.y-b3.y)}var mergeRoutes=routes=>{if(routes.length===1)return routes[0];if(routes.some(r4=>r4.length===0))throw new Error("Cannot merge routes with zero length");let merged=[],first_route_fp=routes[0][0],first_route_lp=routes[0][routes[0].length-1],second_route_fp=routes[1][0],second_route_lp=routes[1][routes[1].length-1],best_reverse_dist=Math.min(pdist(first_route_fp,second_route_fp),pdist(first_route_fp,second_route_lp)),best_normal_dist=Math.min(pdist(first_route_lp,second_route_fp),pdist(first_route_lp,second_route_lp));best_reverse_dist<best_normal_dist?merged.push(...routes[0].reverse()):merged.push(...routes[0]);for(let i2=1;i2<routes.length;i2++){let last_merged_point=merged[merged.length-1],next_route=routes[i2],next_first_point=next_route[0],next_last_point=next_route[next_route.length-1],distance_to_first=pdist(last_merged_point,next_first_point),distance_to_last=pdist(last_merged_point,next_last_point);distance_to_first<distance_to_last?merged.push(...next_route):merged.push(...next_route.reverse())}for(let i2=1;i2<merged.length-1;i2++){let lastPoint=merged[i2-1],currentPoint=merged[i2];lastPoint.route_type==="wire"&¤tPoint.route_type==="wire"&&lastPoint.layer!==currentPoint.layer&&merged.splice(i2,0,{x:lastPoint.x,y:lastPoint.y,from_layer:lastPoint.layer,to_layer:currentPoint.layer,route_type:"via"})}return merged},getDistance=(a2,b3)=>{let aPos="_getGlobalPcbPositionBeforeLayout"in a2?a2._getGlobalPcbPositionBeforeLayout():a2,bPos="_getGlobalPcbPositionBeforeLayout"in b3?b3._getGlobalPcbPositionBeforeLayout():b3;return Math.sqrt((aPos.x-bPos.x)**2+(aPos.y-bPos.y)**2)};function getClosest(point6,candidates){if(candidates.length===0)throw new Error("No candidates given to getClosest method");let closest=candidates[0],closestDist=1/0;for(let candidate of candidates){let dist=getDistance(point6,candidate);dist<closestDist&&(closest=candidate,closestDist=dist)}return closest}var countComplexElements=(junctions,edges)=>{let count=0;count+=junctions.length??0,count+=edges.filter(edge=>edge.is_crossing).length;for(let i2=1;i2<edges.length;i2++){let prev=edges[i2-1],curr=edges[i2],prevVertical=Math.abs(prev.from.x-prev.to.x)<.01,currVertical=Math.abs(curr.from.x-curr.to.x)<.01;prevVertical!==currVertical&&count++}return count},getEnteringEdgeFromDirection=direction2=>({up:"bottom",down:"top",left:"right",right:"left"})[direction2]??null,getStubEdges=({firstEdge,firstEdgePort,firstDominantDirection,lastEdge,lastEdgePort,lastDominantDirection})=>{if(firstEdge&&firstEdgePort)return getStubEdges({lastEdge:{from:firstEdge.to,to:firstEdge.from},lastEdgePort:firstEdgePort,lastDominantDirection:firstDominantDirection}).reverse().map(e4=>({from:e4.to,to:e4.from}));let edges=[];if(lastEdge&&lastEdgePort){let intermediatePoint={x:lastEdge.to.x,y:lastEdge.to.y};lastDominantDirection==="left"||lastDominantDirection==="right"?(intermediatePoint.x=lastEdgePort.position.x,edges.push({from:lastEdge.to,to:{...intermediatePoint}}),edges.push({from:intermediatePoint,to:{...lastEdgePort.position}})):(intermediatePoint.y=lastEdgePort.position.y,edges.push({from:lastEdge.to,to:{...intermediatePoint}}),edges.push({from:intermediatePoint,to:{...lastEdgePort.position}}))}return edges=edges.filter(e4=>distance4(e4.from,e4.to)>.01),edges};function tryNow(fn3){try{return[fn3(),null]}catch(e4){return[null,e4]}}var getMaxLengthFromConnectedCapacitors=(ports,{db})=>{let capacitorMaxLengths=ports.map(port=>{let sourcePort=db.source_port.get(port.source_port_id);if(!sourcePort?.source_component_id)return null;let sourceComponent=db.source_component.get(sourcePort.source_component_id);return sourceComponent?.ftype==="simple_capacitor"?sourceComponent.max_decoupling_trace_length:null}).filter(length7=>length7!==null);if(capacitorMaxLengths.length!==0)return Math.min(...capacitorMaxLengths)};function getTraceDisplayName({ports,nets}){if(ports.length>=2)return`${ports[0]?.selector} to ${ports[1]?.selector}`;if(ports.length===1&&nets.length===1)return`${ports[0]?.selector} to net.${nets[0]._parsedProps.name}`}var getPcbBoardOutlinePolygon=pcbBoard=>pcbBoard.outline&&pcbBoard.outline.length>0?new Polygon$1(pcbBoard.outline.map(p4=>point4(p4.x,p4.y))):new Polygon$1(new Box(pcbBoard.center.x-pcbBoard.width/2,pcbBoard.center.y-pcbBoard.height/2,pcbBoard.center.x+pcbBoard.width/2,pcbBoard.center.y+pcbBoard.height/2).toPoints()),isRouteOutsideBoard=({mergedRoute,db,pcbBoardId})=>{let pcbBoard=db.pcb_board.get(pcbBoardId);if(!pcbBoard)return!1;let boardOutlinePolygon=getPcbBoardOutlinePolygon(pcbBoard);return!mergedRoute.flat().every(routePoint=>boardOutlinePolygon.contains(point4(routePoint.x,routePoint.y)))},isCloseTo2=(a2,b3)=>Math.abs(a2-b3)<1e-4,getObstaclesFromRoute2=(route,source_trace_id,{viaDiameter=.5}={})=>{let obstacles=[];for(let i2=0;i2<route.length-1;i2++){let[start,end]=[route[i2],route[i2+1]],prev=i2-1>=0?route[i2-1]:null,isHorz=isCloseTo2(start.y,end.y),isVert=isCloseTo2(start.x,end.x);if(!isHorz&&!isVert)throw new Error(`getObstaclesFromTrace currently only supports horizontal and vertical traces (not diagonals) Conflicting trace: ${source_trace_id}, start: (${start.x}, ${start.y}), end: (${end.x}, ${end.y})`);let obstacle={type:"rect",layers:[start.layer],center:{x:(start.x+end.x)/2,y:(start.y+end.y)/2},width:isHorz?Math.abs(start.x-end.x):.1,height:isVert?Math.abs(start.y-end.y):.1,connectedTo:[source_trace_id]};if(obstacles.push(obstacle),prev&&prev.layer===start.layer&&start.layer!==end.layer){let via={type:"rect",layers:[start.layer,end.layer],center:{x:start.x,y:start.y},connectedTo:[source_trace_id],width:viaDiameter,height:viaDiameter};obstacles.push(via)}}return obstacles};function generateApproximatingRects2(rotatedRect,numRects=2){let{center:center2,width,height,rotation:rotation4}=rotatedRect,rects=[],angleRad=rotation4*Math.PI/180,cosAngle=Math.cos(angleRad),sinAngle=Math.sin(angleRad),normalizedRotation=(rotation4%360+360)%360;if(height<=width?normalizedRotation>=45&&normalizedRotation<135||normalizedRotation>=225&&normalizedRotation<315:normalizedRotation>=135&&normalizedRotation<225||normalizedRotation>=315||normalizedRotation<45){let sliceWidth=width/numRects;for(let i2=0;i2<numRects;i2++){let x5=(i2-numRects/2+.5)*sliceWidth,rotatedX=-x5*cosAngle,rotatedY=-x5*sinAngle,coverageWidth=sliceWidth*1.1,coverageHeight=Math.abs(height*cosAngle)+Math.abs(sliceWidth*sinAngle);rects.push({center:{x:center2.x+rotatedX,y:center2.y+rotatedY},width:coverageWidth,height:coverageHeight})}}else{let sliceHeight=height/numRects;for(let i2=0;i2<numRects;i2++){let y5=(i2-numRects/2+.5)*sliceHeight,rotatedX=-y5*sinAngle,rotatedY=y5*cosAngle,coverageWidth=Math.abs(width*cosAngle)+Math.abs(sliceHeight*sinAngle),coverageHeight=sliceHeight*1.1;rects.push({center:{x:center2.x+rotatedX,y:center2.y+rotatedY},width:coverageWidth,height:coverageHeight})}}return rects}function fillPolygonWithRects(polygon2,options={}){if(polygon2.length<3)return[];let{rectHeight=.1}=options,rects=[],yCoords=polygon2.map(p4=>p4.y),minY=Math.min(...yCoords),maxY=Math.max(...yCoords);for(let y5=minY;y5<maxY;y5+=rectHeight){let scanlineY=y5+rectHeight/2,intersections=[];for(let i2=0;i2<polygon2.length;i2++){let p12=polygon2[i2],p22=polygon2[(i2+1)%polygon2.length];if(p12.y<=scanlineY&&p22.y>scanlineY||p22.y<=scanlineY&&p12.y>scanlineY){let x5=(scanlineY-p12.y)*(p22.x-p12.x)/(p22.y-p12.y)+p12.x;intersections.push(x5)}}intersections.sort((a2,b3)=>a2-b3);for(let i2=0;i2<intersections.length;i2+=2)if(i2+1<intersections.length){let x12=intersections[i2],width=intersections[i2+1]-x12;width>1e-6&&rects.push({center:{x:x12+width/2,y:scanlineY},width,height:rectHeight})}}return rects}function fillCircleWithRects(circle2,options={}){let{center:center2,radius}=circle2,{rectHeight=.1}=options,rects=[],numSlices=Math.ceil(radius*2/rectHeight);for(let i2=0;i2<numSlices;i2++){let y5=center2.y-radius+(i2+.5)*rectHeight,dy2=y5-center2.y,halfWidth=Math.sqrt(radius*radius-dy2*dy2);halfWidth>0&&rects.push({center:{x:center2.x,y:y5},width:halfWidth*2,height:rectHeight})}return rects}var EVERY_LAYER2=["top","inner1","inner2","bottom"],getObstaclesFromCircuitJson2=(soup,connMap)=>{let withNetId=idList=>connMap?idList.concat(idList.map(id=>connMap?.getNetConnectedToId(id)).filter(Boolean)):idList,obstacles=[];for(let element of soup)if(element.type==="pcb_smtpad"){if(element.shape==="circle")obstacles.push({type:"oval",layers:[element.layer],center:{x:element.x,y:element.y},width:element.radius*2,height:element.radius*2,connectedTo:withNetId([element.pcb_smtpad_id])});else if(element.shape==="rect")obstacles.push({type:"rect",layers:[element.layer],center:{x:element.x,y:element.y},width:element.width,height:element.height,connectedTo:withNetId([element.pcb_smtpad_id])});else if(element.shape==="rotated_rect"){let rotatedRect={center:{x:element.x,y:element.y},width:element.width,height:element.height,rotation:element.ccw_rotation},approximatingRects=generateApproximatingRects2(rotatedRect);for(let rect of approximatingRects)obstacles.push({type:"rect",layers:[element.layer],center:rect.center,width:rect.width,height:rect.height,connectedTo:withNetId([element.pcb_smtpad_id])})}}else if(element.type==="pcb_keepout")element.shape==="circle"?obstacles.push({type:"oval",layers:element.layers,center:{x:element.center.x,y:element.center.y},width:element.radius*2,height:element.radius*2,connectedTo:[]}):element.shape==="rect"&&obstacles.push({type:"rect",layers:element.layers,center:{x:element.center.x,y:element.center.y},width:element.width,height:element.height,connectedTo:[]});else if(element.type==="pcb_cutout"){if(element.shape==="rect")obstacles.push({type:"rect",layers:EVERY_LAYER2,center:{x:element.center.x,y:element.center.y},width:element.width,height:element.height,connectedTo:[]});else if(element.shape==="circle"){let approximatingRects=fillCircleWithRects({center:element.center,radius:element.radius},{rectHeight:.6});for(let rect of approximatingRects)obstacles.push({type:"rect",layers:EVERY_LAYER2,center:rect.center,width:rect.width,height:rect.height,connectedTo:[]})}else if(element.shape==="polygon"){let approximatingRects=fillPolygonWithRects(element.points,{rectHeight:.6});for(let rect of approximatingRects)obstacles.push({type:"rect",layers:EVERY_LAYER2,center:rect.center,width:rect.width,height:rect.height,connectedTo:[]})}}else if(element.type==="pcb_hole")element.hole_shape==="oval"?obstacles.push({type:"oval",center:{x:element.x,y:element.y},width:element.hole_width,height:element.hole_height,connectedTo:[]}):element.hole_shape==="rect"?obstacles.push({type:"rect",layers:EVERY_LAYER2,center:{x:element.x,y:element.y},width:element.hole_width,height:element.hole_height,connectedTo:[]}):element.hole_shape==="square"?obstacles.push({type:"rect",layers:EVERY_LAYER2,center:{x:element.x,y:element.y},width:element.hole_diameter,height:element.hole_diameter,connectedTo:[]}):(element.hole_shape==="round"||element.hole_shape==="circle")&&obstacles.push({type:"rect",layers:EVERY_LAYER2,center:{x:element.x,y:element.y},width:element.hole_diameter,height:element.hole_diameter,connectedTo:[]});else if(element.type==="pcb_plated_hole"){if(element.shape==="circle")obstacles.push({type:"oval",layers:EVERY_LAYER2,center:{x:element.x,y:element.y},width:element.outer_diameter,height:element.outer_diameter,connectedTo:withNetId([element.pcb_plated_hole_id])});else if(element.shape==="circular_hole_with_rect_pad")obstacles.push({type:"rect",layers:EVERY_LAYER2,center:{x:element.x,y:element.y},width:element.rect_pad_width,height:element.rect_pad_height,connectedTo:withNetId([element.pcb_plated_hole_id])});else if(element.shape==="oval"||element.shape==="pill")obstacles.push({type:"oval",layers:EVERY_LAYER2,center:{x:element.x,y:element.y},width:element.outer_width,height:element.outer_height,connectedTo:withNetId([element.pcb_plated_hole_id])});else if(element.shape==="hole_with_polygon_pad"&&"pad_outline"in element&&element.pad_outline&&element.pad_outline.length>0){let xs3=element.pad_outline.map(p4=>element.x+p4.x),ys3=element.pad_outline.map(p4=>element.y+p4.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3),centerX=(minX+maxX)/2,centerY=(minY+maxY)/2;obstacles.push({type:"rect",layers:EVERY_LAYER2,center:{x:centerX,y:centerY},width:maxX-minX,height:maxY-minY,connectedTo:withNetId([element.pcb_plated_hole_id])})}}else if(element.type==="pcb_trace"){let traceObstacles=getObstaclesFromRoute2(element.route.map(rp2=>({x:rp2.x,y:rp2.y,layer:"layer"in rp2?rp2.layer:rp2.from_layer})),element.source_trace_id);obstacles.push(...traceObstacles)}else if(element.type==="pcb_via"){let netIsAssignable=!!(element.net_is_assignable??element.netIsAssignable);obstacles.push({type:"rect",layers:element.layers,center:{x:element.x,y:element.y},connectedTo:[],width:element.outer_diameter,height:element.outer_diameter,netIsAssignable:netIsAssignable||void 0})}return obstacles},computeSchematicNetLabelCenter=({anchor_position,anchor_side,text,font_size=.18})=>{let charWidth=.1*(font_size/.18),width=text.length*charWidth,height=font_size,center2={...anchor_position};switch(anchor_side){case"right":center2.x-=width/2;break;case"left":center2.x+=width/2;break;case"top":center2.y-=height/2;break;case"bottom":center2.y+=height/2;break}return center2},getOtherSchematicTraces=({db,source_trace_id,sameNetOnly,differentNetOnly})=>{!sameNetOnly&&!differentNetOnly&&(differentNetOnly=!0);let mySourceTrace=db.source_trace.get(source_trace_id),traces=[];for(let otherSchematicTrace of db.schematic_trace.list()){if(otherSchematicTrace.source_trace_id===source_trace_id)continue;let isSameNet=db.source_trace.get(otherSchematicTrace.source_trace_id)?.subcircuit_connectivity_map_key===mySourceTrace.subcircuit_connectivity_map_key;differentNetOnly&&isSameNet||sameNetOnly&&!isSameNet||traces.push(otherSchematicTrace)}return traces},createSchematicTraceCrossingSegments=({edges:inputEdges,otherEdges})=>{let edges=[...inputEdges];for(let i2=0;i2<edges.length;i2++){if(i2>2e3)throw new Error("Over 2000 iterations spent inside createSchematicTraceCrossingSegments, you have triggered an infinite loop, please report this!");let edge=edges[i2],edgeOrientation=Math.abs(edge.from.x-edge.to.x)<.01?"vertical":edge.from.y===edge.to.y?"horizontal":"not-orthogonal";if(edgeOrientation==="not-orthogonal")continue;let otherEdgesIntersections=[];for(let otherEdge of otherEdges){let otherOrientation=otherEdge.from.x===otherEdge.to.x?"vertical":otherEdge.from.y===otherEdge.to.y?"horizontal":"not-orthogonal";if(otherOrientation==="not-orthogonal"||edgeOrientation===otherOrientation)continue;if(doesLineIntersectLine2([edge.from,edge.to],[otherEdge.from,otherEdge.to],{lineThickness:.01})){let intersectX=edgeOrientation==="vertical"?edge.from.x:otherEdge.from.x,intersectY=edgeOrientation==="vertical"?otherEdge.from.y:edge.from.y,crossingPoint2={x:intersectX,y:intersectY};otherEdgesIntersections.push({otherEdge,crossingPoint:crossingPoint2,distanceFromEdgeFrom:distance4(edge.from,crossingPoint2)})}}if(otherEdgesIntersections.length===0)continue;let closestIntersection=otherEdgesIntersections[0];for(let intersection of otherEdgesIntersections)intersection.distanceFromEdgeFrom<closestIntersection.distanceFromEdgeFrom&&(closestIntersection=intersection);let crossingPoint=closestIntersection.crossingPoint,crossingSegmentLength=.075;if(crossingPoint.x===edge.from.x&&crossingPoint.y===edge.from.y)continue;let crossingUnitVec=getUnitVectorFromPointAToB2(edge.from,crossingPoint),beforeCrossing={x:crossingPoint.x-crossingUnitVec.x*crossingSegmentLength/2,y:crossingPoint.y-crossingUnitVec.y*crossingSegmentLength/2},afterCrossing={x:crossingPoint.x+crossingUnitVec.x*crossingSegmentLength/2,y:crossingPoint.y+crossingUnitVec.y*crossingSegmentLength/2},overshot=distance4(afterCrossing,edge.to)<crossingSegmentLength,newEdges=[{from:edge.from,to:beforeCrossing},{from:beforeCrossing,to:afterCrossing,is_crossing:!0},{from:afterCrossing,to:edge.to}];edges.splice(i2,1,...newEdges),i2+=newEdges.length-2,overshot&&i2++}return edges},TOLERANCE=.001,isPointWithinEdge=(point6,edge)=>{let minX=Math.min(edge.from.x,edge.to.x),maxX=Math.max(edge.from.x,edge.to.x),minY=Math.min(edge.from.y,edge.to.y),maxY=Math.max(edge.from.y,edge.to.y);return point6.x>=minX&&point6.x<=maxX&&point6.y>=minY&&point6.y<=maxY},getEdgeOrientation=edge=>{let isVertical3=Math.abs(edge.from.x-edge.to.x)<TOLERANCE,isHorizontal2=Math.abs(edge.from.y-edge.to.y)<TOLERANCE;return isVertical3?"vertical":isHorizontal2?"horizontal":"diagonal"},getIntersectionPoint=(edge1,edge2)=>{let orientation1=getEdgeOrientation(edge1),orientation22=getEdgeOrientation(edge2);if(orientation1===orientation22)return null;if(orientation1==="vertical"&&orientation22==="horizontal"||orientation1==="horizontal"&&orientation22==="vertical"){let verticalEdge=orientation1==="vertical"?edge1:edge2,horizontalEdge=orientation1==="horizontal"?edge1:edge2,x22=verticalEdge.from.x,y22=horizontalEdge.from.y,intersection2={x:x22,y:y22};return isPointWithinEdge(intersection2,edge1)&&isPointWithinEdge(intersection2,edge2)?intersection2:null}if(orientation1==="vertical"||orientation22==="vertical"){let verticalEdge=orientation1==="vertical"?edge1:edge2,diagonalEdge=orientation1==="vertical"?edge2:edge1,x22=verticalEdge.from.x,m3=(diagonalEdge.to.y-diagonalEdge.from.y)/(diagonalEdge.to.x-diagonalEdge.from.x),b3=diagonalEdge.from.y-m3*diagonalEdge.from.x,y22=m3*x22+b3,intersection2={x:x22,y:y22};return isPointWithinEdge(intersection2,edge1)&&isPointWithinEdge(intersection2,edge2)?intersection2:null}let m12=(edge1.to.y-edge1.from.y)/(edge1.to.x-edge1.from.x),b12=edge1.from.y-m12*edge1.from.x,m22=(edge2.to.y-edge2.from.y)/(edge2.to.x-edge2.from.x),b22=edge2.from.y-m22*edge2.from.x;if(Math.abs(m12-m22)<TOLERANCE)return null;let x5=(b22-b12)/(m12-m22),y5=m12*x5+b12,intersection={x:x5,y:y5};return isPointWithinEdge(intersection,edge1)&&isPointWithinEdge(intersection,edge2)?intersection:null},createSchematicTraceJunctions=({edges:myEdges,db,source_trace_id})=>{let otherEdges=getOtherSchematicTraces({db,source_trace_id,sameNetOnly:!0}).flatMap(t5=>t5.edges),junctions=new Map;for(let myEdge of myEdges)for(let otherEdge of otherEdges){let intersection=getIntersectionPoint(myEdge,otherEdge);if(intersection){let key=`${intersection.x.toFixed(6)},${intersection.y.toFixed(6)}`;junctions.has(key)||junctions.set(key,intersection)}}return Array.from(junctions.values())};function getObstaclesFromBounds(bounds,opts={}){let{minX,maxX,minY,maxY}=bounds,PADDING=opts.padding??1;if(!isFinite(minX)||!isFinite(maxX)||!isFinite(minY)||!isFinite(maxY))return[];let left=minX-PADDING,right=maxX+PADDING,top=maxY+PADDING,bottom=minY-PADDING,thickness=.01;return[{type:"rect",layers:["top"],center:{x:(left+right)/2,y:top},width:right-left,height:thickness,connectedTo:[]},{type:"rect",layers:["top"],center:{x:(left+right)/2,y:bottom},width:right-left,height:thickness,connectedTo:[]},{type:"rect",layers:["top"],center:{x:left,y:(top+bottom)/2},width:thickness,height:top-bottom,connectedTo:[]},{type:"rect",layers:["top"],center:{x:right,y:(top+bottom)/2},width:thickness,height:top-bottom,connectedTo:[]}]}var getSchematicObstaclesForTrace=trace=>{let db=trace.root.db,connectedPorts=trace._findConnectedPorts().ports??[],connectedPortIds=new Set(connectedPorts.map(p4=>p4.schematic_port_id)),obstacles=[];for(let elm of db.toArray()){if(elm.type==="schematic_component"){let isSymbol3=!!elm.symbol_name,dominateAxis=elm.size.width>elm.size.height?"horz":"vert";obstacles.push({type:"rect",layers:["top"],center:elm.center,width:elm.size.width+(isSymbol3&&dominateAxis==="horz"?-.5:0),height:elm.size.height+(isSymbol3&&dominateAxis==="vert"?-.5:0),connectedTo:[]})}if(elm.type==="schematic_port"){if(connectedPortIds.has(elm.schematic_port_id))continue;let dirVec=elm.facing_direction?getUnitVectorFromDirection2(elm.facing_direction):{x:0,y:0};obstacles.push({type:"rect",layers:["top"],center:{x:elm.center.x-dirVec.x*.1,y:elm.center.y-dirVec.y*.1},width:.1+Math.abs(dirVec.x)*.3,height:.1+Math.abs(dirVec.y)*.3,connectedTo:[]})}elm.type==="schematic_text"&&obstacles.push({type:"rect",layers:["top"],center:elm.position,width:(elm.text?.length??0)*.1,height:.2,connectedTo:[]}),elm.type==="schematic_box"&&obstacles.push({type:"rect",layers:["top"],center:{x:elm.x,y:elm.y},width:elm.width,height:elm.height,connectedTo:[]})}let bounds=getBoundsForSchematic(db.toArray());return obstacles.push(...getObstaclesFromBounds(bounds,{padding:1})),obstacles},pushEdgesOfSchematicTraceToPreventOverlap=({edges,db,source_trace_id})=>{let mySourceTrace=db.source_trace.get(source_trace_id),otherEdges=getOtherSchematicTraces({db,source_trace_id,differentNetOnly:!0}).flatMap(t5=>t5.edges),edgeOrientation=edge=>{let{from,to:to3}=edge;return from.x===to3.x?"vertical":"horizontal"};for(let mySegment of edges){let mySegmentOrientation=edgeOrientation(mySegment),findOverlappingParallelSegment=()=>otherEdges.find(otherEdge=>edgeOrientation(otherEdge)===mySegmentOrientation&&doesLineIntersectLine2([mySegment.from,mySegment.to],[otherEdge.from,otherEdge.to],{lineThickness:.05})),overlappingParallelSegmentFromOtherTrace=findOverlappingParallelSegment();for(;overlappingParallelSegmentFromOtherTrace;)mySegmentOrientation==="horizontal"?(mySegment.from.y+=.1,mySegment.to.y+=.1):(mySegment.from.x+=.1,mySegment.to.x+=.1),overlappingParallelSegmentFromOtherTrace=findOverlappingParallelSegment()}},convertFacingDirectionToElbowDirection=facingDirection=>{switch(facingDirection){case"up":return"y+";case"down":return"y-";case"left":return"x-";case"right":return"x+";default:}},autorouterVersion=package_default.version??"unknown",AutorouterError=class extends Error{constructor(message){super(`${message} (capacity-autorouter@${autorouterVersion})`),this.name="AutorouterError"}},TraceConnectionError=class extends Error{constructor(errorData){super(errorData.message),this.errorData=errorData,this.name="TraceConnectionError"}},Trace_doInitialSchematicTraceRender=trace=>{if(trace.root?._featureMspSchematicTraceRouting||trace._couldNotFindPort||trace.root?.schematicDisabled)return;let{db}=trace.root,{_parsedProps:props,parent}=trace;if(!parent)throw new Error("Trace has no parent");let allPortsFound,connectedPorts;try{let result=trace._findConnectedPorts();allPortsFound=result.allPortsFound,connectedPorts=result.portsWithSelectors??[]}catch(error){if(error instanceof TraceConnectionError){db.source_trace_not_connected_error.insert({...error.errorData,error_type:"source_trace_not_connected_error"});return}throw error}let{netsWithSelectors}=trace._findConnectedNets();if(!allPortsFound)return;let portPairKey=connectedPorts.map(p4=>p4.port.schematic_port_id).sort().join(","),board=trace.root?._getBoard();if(board?._connectedSchematicPortPairs&&board._connectedSchematicPortPairs.has(portPairKey))return;let connection={name:trace.source_trace_id,pointsToConnect:[]},obstacles=getSchematicObstaclesForTrace(trace),portsWithPosition=connectedPorts.filter(({port})=>port.schematic_port_id!==null).map(({port})=>({port,position:port._getGlobalSchematicPositionAfterLayout(),schematic_port_id:port.schematic_port_id??void 0,facingDirection:port.facingDirection}));if(portsWithPosition.length===1&&netsWithSelectors.length===1){let net=netsWithSelectors[0].net,{port,position:anchorPos}=portsWithPosition[0],connectedNetLabel=trace.getSubcircuit().selectAll("netlabel").find(nl2=>{let conn=nl2._parsedProps.connection??nl2._parsedProps.connectsTo;return conn?Array.isArray(conn)?conn.some(selector=>trace.getSubcircuit().selectOne(selector,{port:!0})===port):trace.getSubcircuit().selectOne(conn,{port:!0})===port:!1});if(!connectedNetLabel){let dbNetLabel=db.schematic_net_label.getWhere({source_trace_id:trace.source_trace_id});dbNetLabel&&(connectedNetLabel=dbNetLabel)}if(connectedNetLabel){let labelPos="_getGlobalSchematicPositionBeforeLayout"in connectedNetLabel?connectedNetLabel._getGlobalSchematicPositionBeforeLayout():connectedNetLabel.anchor_position,edges2=[];anchorPos.x===labelPos.x||anchorPos.y===labelPos.y?edges2.push({from:anchorPos,to:labelPos}):(edges2.push({from:anchorPos,to:{x:labelPos.x,y:anchorPos.y}}),edges2.push({from:{x:labelPos.x,y:anchorPos.y},to:labelPos}));let dbTrace2=db.schematic_trace.insert({source_trace_id:trace.source_trace_id,edges:edges2,junctions:[],subcircuit_connectivity_map_key:trace.subcircuit_connectivity_map_key??void 0});trace.schematic_trace_id=dbTrace2.schematic_trace_id;return}if(trace.props.schDisplayLabel){let side2=getEnteringEdgeFromDirection(port.facingDirection)??"bottom";db.schematic_net_label.insert({text:trace.props.schDisplayLabel,source_net_id:net.source_net_id,anchor_position:anchorPos,center:computeSchematicNetLabelCenter({anchor_position:anchorPos,anchor_side:side2,text:trace.props.schDisplayLabel}),anchor_side:side2});return}let side=getEnteringEdgeFromDirection(port.facingDirection)??"bottom",netLabel=db.schematic_net_label.insert({text:net._parsedProps.name,source_net_id:net.source_net_id,anchor_position:anchorPos,center:computeSchematicNetLabelCenter({anchor_position:anchorPos,anchor_side:side,text:net._parsedProps.name}),anchor_side:side});return}if(trace.props.schDisplayLabel&&("from"in trace.props&&"to"in trace.props||"path"in trace.props)){trace._doInitialSchematicTraceRenderWithDisplayLabel();return}if(portsWithPosition.length<2)return;let edges=(()=>{let elbowEdges=[];for(let i2=0;i2<portsWithPosition.length-1;i2++){let start=portsWithPosition[i2],end=portsWithPosition[i2+1],path=calculateElbow({x:start.position.x,y:start.position.y,facingDirection:convertFacingDirectionToElbowDirection(start.facingDirection)},{x:end.position.x,y:end.position.y,facingDirection:convertFacingDirectionToElbowDirection(end.facingDirection)});for(let j4=0;j4<path.length-1;j4++)elbowEdges.push({from:path[j4],to:path[j4+1]})}let doesSegmentIntersectRect2=(edge,rect)=>{let halfW=rect.width/2,halfH=rect.height/2,left=rect.center.x-halfW,right=rect.center.x+halfW,top=rect.center.y-halfH,bottom=rect.center.y+halfH,inRect=p4=>p4.x>=left&&p4.x<=right&&p4.y>=top&&p4.y<=bottom;return inRect(edge.from)||inRect(edge.to)?!0:[[{x:left,y:top},{x:right,y:top}],[{x:right,y:top},{x:right,y:bottom}],[{x:right,y:bottom},{x:left,y:bottom}],[{x:left,y:bottom},{x:left,y:top}]].some(r4=>doesLineIntersectLine2([edge.from,edge.to],r4,{lineThickness:0}))};for(let edge of elbowEdges)for(let obstacle of obstacles)if(doesSegmentIntersectRect2(edge,obstacle))return null;return elbowEdges})();edges&&edges.length===0&&(edges=null),connection.pointsToConnect=portsWithPosition.map(({position:position2})=>({...position2,layer:"top"}));let bounds=computeObstacleBounds(obstacles),BOUNDS_MARGIN=2,simpleRouteJsonInput={minTraceWidth:.1,obstacles,connections:[connection],bounds:{minX:bounds.minX-BOUNDS_MARGIN,maxX:bounds.maxX+BOUNDS_MARGIN,minY:bounds.minY-BOUNDS_MARGIN,maxY:bounds.maxY+BOUNDS_MARGIN},layerCount:1},Autorouter=MultilayerIjump,skipOtherTraceInteraction=!1;if(trace.getSubcircuit().props._schDirectLineRoutingEnabled&&(Autorouter=DirectLineRouter,skipOtherTraceInteraction=!0),!edges){let results=new Autorouter({input:simpleRouteJsonInput,MAX_ITERATIONS:100,OBSTACLE_MARGIN:.1,isRemovePathLoopsEnabled:!0,isShortenPathWithShortcutsEnabled:!0,marginsWithCosts:[{margin:1,enterCost:0,travelCostFactor:1},{margin:.3,enterCost:0,travelCostFactor:1},{margin:.2,enterCost:0,travelCostFactor:2},{margin:.1,enterCost:0,travelCostFactor:3}]}).solveAndMapToTraces();if(results.length===0){if(trace._isSymbolToChipConnection()||trace._isSymbolToSymbolConnection()||trace._isChipToChipConnection()){trace._doInitialSchematicTraceRenderWithDisplayLabel();return}results=new DirectLineRouter({input:simpleRouteJsonInput}).solveAndMapToTraces(),skipOtherTraceInteraction=!0}let[{route}]=results;edges=[];let wireAndViaRoutes=route.filter(r4=>r4.route_type==="wire"||r4.route_type==="via");for(let i2=0;i2<wireAndViaRoutes.length-1;i2++)edges.push({from:wireAndViaRoutes[i2],to:wireAndViaRoutes[i2+1]})}let source_trace_id=trace.source_trace_id,junctions=[];if(!skipOtherTraceInteraction){pushEdgesOfSchematicTraceToPreventOverlap({edges,db,source_trace_id});let otherEdges=getOtherSchematicTraces({db,source_trace_id,differentNetOnly:!0}).flatMap(t5=>t5.edges);edges=createSchematicTraceCrossingSegments({edges,otherEdges}),junctions=createSchematicTraceJunctions({edges,db,source_trace_id:trace.source_trace_id})}if(!edges||edges.length===0)return;let lastEdge=edges[edges.length-1],lastEdgePort=portsWithPosition[portsWithPosition.length-1],lastDominantDirection=getDominantDirection(lastEdge);edges.push(...getStubEdges({lastEdge,lastEdgePort,lastDominantDirection}));let firstEdge=edges[0],firstEdgePort=portsWithPosition[0],firstDominantDirection=getDominantDirection(firstEdge);if(edges.unshift(...getStubEdges({firstEdge,firstEdgePort,firstDominantDirection})),!trace.source_trace_id)throw new Error("Missing source_trace_id for schematic trace insertion.");if(trace.getSubcircuit()._parsedProps.schTraceAutoLabelEnabled&&countComplexElements(junctions,edges)>=5&&(trace._isSymbolToChipConnection()||trace._isSymbolToSymbolConnection()||trace._isChipToChipConnection())){trace._doInitialSchematicTraceRenderWithDisplayLabel();return}let dbTrace=db.schematic_trace.insert({source_trace_id:trace.source_trace_id,edges,junctions,subcircuit_connectivity_map_key:trace.subcircuit_connectivity_map_key??void 0});trace.schematic_trace_id=dbTrace.schematic_trace_id;for(let{port}of connectedPorts)port.schematic_port_id&&db.schematic_port.update(port.schematic_port_id,{is_connected:!0});board?._connectedSchematicPortPairs&&board._connectedSchematicPortPairs.add(portPairKey)};function getTraceLength(route){let totalLength=0;for(let i2=0;i2<route.length;i2++){let point6=route[i2];if(point6.route_type==="wire"){let nextPoint=route[i2+1];if(nextPoint){let dx2=nextPoint.x-point6.x,dy2=nextPoint.y-point6.y;totalLength+=Math.sqrt(dx2*dx2+dy2*dy2)}}else point6.route_type==="via"&&(totalLength+=1.6)}return totalLength}var DEFAULT_VIA_HOLE_DIAMETER=.3,DEFAULT_VIA_PAD_DIAMETER=.6,parseDistance=(value,fallback)=>{if(value===void 0)return fallback;if(typeof value=="number")return value;let parsed=parseFloat(value);return Number.isFinite(parsed)?parsed:fallback},getViaDiameterDefaults=pcbStyle2=>({holeDiameter:parseDistance(pcbStyle2?.viaHoleDiameter,DEFAULT_VIA_HOLE_DIAMETER),padDiameter:parseDistance(pcbStyle2?.viaPadDiameter,DEFAULT_VIA_PAD_DIAMETER)}),getViaDiameterDefaultsWithOverrides=(overrides,pcbStyle2)=>{let defaults=getViaDiameterDefaults(pcbStyle2);return{holeDiameter:overrides.holeDiameter??defaults.holeDiameter,padDiameter:overrides.padDiameter??defaults.padDiameter}},portToObjective=port=>({...port._getGlobalPcbPositionAfterLayout(),layers:port.getAvailablePcbLayers()}),SHOULD_USE_SINGLE_LAYER_ROUTING=!1;function Trace_doInitialPcbTraceRender(trace){if(trace.root?.pcbDisabled)return;let{db}=trace.root,{_parsedProps:props,parent}=trace,subcircuit=trace.getSubcircuit();if(!parent)throw new Error("Trace has no parent");if(subcircuit._parsedProps.routingDisabled)return;let cachedRoute=subcircuit._parsedProps.pcbRouteCache?.pcbTraces;if(cachedRoute){let pcb_trace22=db.pcb_trace.insert({route:cachedRoute.flatMap(trace2=>trace2.route),source_trace_id:trace.source_trace_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:trace.getGroup()?.pcb_group_id??void 0});trace.pcb_trace_id=pcb_trace22.pcb_trace_id;return}if(props.pcbPath&&props.pcbPath.length>0||props.pcbStraightLine||!subcircuit._shouldUseTraceByTraceRouting())return;let{allPortsFound,ports}=trace._findConnectedPorts(),portsConnectedOnPcbViaNet=[];if(!allPortsFound)return;let portsWithoutMatchedPcbPrimitive=[];for(let port of ports)port._hasMatchedPcbPrimitive()||portsWithoutMatchedPcbPrimitive.push(port);if(portsWithoutMatchedPcbPrimitive.length>0){db.pcb_trace_error.insert({error_type:"pcb_trace_error",source_trace_id:trace.source_trace_id,message:`Some ports did not have a matching PCB primitive (e.g. a pad or plated hole), this can happen if a footprint is missing. As a result, ${trace} wasn't routed. Missing ports: ${portsWithoutMatchedPcbPrimitive.map(p4=>p4.getString()).join(", ")}`,pcb_trace_id:trace.pcb_trace_id,pcb_component_ids:[],pcb_port_ids:portsWithoutMatchedPcbPrimitive.map(p4=>p4.pcb_port_id).filter(Boolean)});return}let nets=trace._findConnectedNets().netsWithSelectors;if(ports.length===0&&nets.length===2){trace.renderError("Trace connects two nets, we haven't implemented a way to route this yet");return}else if(ports.length===1&&nets.length===1){let port=ports[0],otherPortsInNet=nets[0].net.getAllConnectedPorts().filter(p4=>p4!==port);if(otherPortsInNet.length===0){console.log("Nothing to connect this port to, the net is empty. TODO should emit a warning!");return}let closestPortInNet=getClosest(port,otherPortsInNet);portsConnectedOnPcbViaNet.push(closestPortInNet),ports.push(closestPortInNet)}else if(ports.length>1&&nets.length>=1){trace.renderError("Trace has more than one port and one or more nets, we don't currently support this type of complex trace routing");return}let hints=ports.flatMap(port=>port.matchedComponents.filter(c3=>c3.componentName==="TraceHint")),pcbRouteHints=(trace._parsedProps.pcbRouteHints??[]).concat(hints.flatMap(h4=>h4.getPcbRouteHints()));if(ports.length>2){trace.renderError(`Trace has more than two ports (${ports.map(p4=>p4.getString()).join(", ")}), routing between more than two ports for a single trace is not implemented`);return}if(trace.getSubcircuit().selectAll("trace").filter(trace2=>trace2.renderPhaseStates.PcbTraceRender.initialized).some(trace2=>trace2._portsRoutedOnPcb.length===ports.length&&trace2._portsRoutedOnPcb.every(portRoutedByOtherTrace=>ports.includes(portRoutedByOtherTrace))))return;let orderedRouteObjectives=[];pcbRouteHints.length===0?orderedRouteObjectives=[portToObjective(ports[0]),portToObjective(ports[1])]:orderedRouteObjectives=[portToObjective(ports[0]),...pcbRouteHints,portToObjective(ports[1])];let candidateLayerCombinations=findPossibleTraceLayerCombinations(orderedRouteObjectives);if(SHOULD_USE_SINGLE_LAYER_ROUTING&&candidateLayerCombinations.length===0){trace.renderError(`Could not find a common layer (using hints) for trace ${trace.getString()}`);return}let connMap=getFullConnectivityMapFromCircuitJson(trace.root.db.toArray()),[obstacles,errGettingObstacles]=tryNow(()=>getObstaclesFromCircuitJson2(trace.root.db.toArray()));if(errGettingObstacles){trace.renderError({type:"pcb_trace_error",error_type:"pcb_trace_error",pcb_trace_error_id:trace.pcb_trace_id,message:`Error getting obstacles for autorouting: ${errGettingObstacles.message}`,source_trace_id:trace.source_trace_id,center:{x:0,y:0},pcb_port_ids:ports.map(p4=>p4.pcb_port_id),pcb_trace_id:trace.pcb_trace_id,pcb_component_ids:[]});return}for(let obstacle of obstacles)if(obstacle.connectedTo.length>0){let netId=connMap.getNetConnectedToId(obstacle.connectedTo[0]);netId&&obstacle.connectedTo.push(netId)}let orderedRoutePoints=[];if(candidateLayerCombinations.length===0)orderedRoutePoints=orderedRouteObjectives;else{let candidateLayerSelections=candidateLayerCombinations[0].layer_path;orderedRoutePoints=orderedRouteObjectives.map((t5,idx)=>t5.via?{...t5,via_to_layer:candidateLayerSelections[idx]}:{...t5,layers:[candidateLayerSelections[idx]]})}orderedRoutePoints[0].pcb_port_id=ports[0].pcb_port_id,orderedRoutePoints[orderedRoutePoints.length-1].pcb_port_id=ports[1].pcb_port_id;let routes=[];for(let[a2,b3]of pairs2(orderedRoutePoints)){let dominantLayer="via_to_layer"in a2?a2.via_to_layer:null,BOUNDS_MARGIN=2,aLayer="layers"in a2&&a2.layers.length===1?a2.layers[0]:dominantLayer??"top",bLayer="layers"in b3&&b3.layers.length===1?b3.layers[0]:dominantLayer??"top",pcbPortA="pcb_port_id"in a2?a2.pcb_port_id:null,pcbPortB="pcb_port_id"in b3?b3.pcb_port_id:null,minTraceWidth=trace._getExplicitTraceThickness()??trace.getSubcircuit()._parsedProps.minTraceWidth??.16,ijump=new MultilayerIjump({OBSTACLE_MARGIN:minTraceWidth*2,isRemovePathLoopsEnabled:!0,optimizeWithGoalBoxes:!!(pcbPortA&&pcbPortB),connMap,input:{obstacles,minTraceWidth,connections:[{name:trace.source_trace_id,pointsToConnect:[{...a2,layer:aLayer,pcb_port_id:pcbPortA},{...b3,layer:bLayer,pcb_port_id:pcbPortB}]}],layerCount:trace.getSubcircuit()._getSubcircuitLayerCount(),bounds:{minX:Math.min(a2.x,b3.x)-BOUNDS_MARGIN,maxX:Math.max(a2.x,b3.x)+BOUNDS_MARGIN,minY:Math.min(a2.y,b3.y)-BOUNDS_MARGIN,maxY:Math.max(a2.y,b3.y)+BOUNDS_MARGIN}}}),traces=null;try{traces=ijump.solveAndMapToTraces()}catch(e4){trace.renderError({type:"pcb_trace_error",pcb_trace_error_id:trace.source_trace_id,error_type:"pcb_trace_error",message:`error solving route: ${e4.message}`,source_trace_id:trace.pcb_trace_id,center:{x:(a2.x+b3.x)/2,y:(a2.y+b3.y)/2},pcb_port_ids:ports.map(p4=>p4.pcb_port_id),pcb_trace_id:trace.pcb_trace_id,pcb_component_ids:ports.map(p4=>p4.pcb_component_id)})}if(!traces)return;if(traces.length===0){trace.renderError({type:"pcb_trace_error",error_type:"pcb_trace_error",pcb_trace_error_id:trace.pcb_trace_id,message:`Could not find a route for ${trace}`,source_trace_id:trace.source_trace_id,center:{x:(a2.x+b3.x)/2,y:(a2.y+b3.y)/2},pcb_port_ids:ports.map(p4=>p4.pcb_port_id),pcb_trace_id:trace.pcb_trace_id,pcb_component_ids:ports.map(p4=>p4.pcb_component_id)});return}let[autoroutedTrace]=traces;dominantLayer&&(autoroutedTrace.route=autoroutedTrace.route.map(p4=>(p4.route_type==="wire"&&!p4.layer&&(p4.layer=dominantLayer),p4))),pcbPortA&&autoroutedTrace.route[0].route_type==="wire"&&(autoroutedTrace.route[0].start_pcb_port_id=pcbPortA);let lastRoutePoint=autoroutedTrace.route[autoroutedTrace.route.length-1];pcbPortB&&lastRoutePoint.route_type==="wire"&&(lastRoutePoint.end_pcb_port_id=pcbPortB),routes.push(autoroutedTrace.route)}let mergedRoute=mergeRoutes(routes),traceLength=getTraceLength(mergedRoute),pcbStyle2=trace.getInheritedMergedProperty("pcbStyle"),{holeDiameter,padDiameter}=getViaDiameterDefaults(pcbStyle2),pcb_trace2=db.pcb_trace.insert({route:mergedRoute,source_trace_id:trace.source_trace_id,subcircuit_id:trace.getSubcircuit()?.subcircuit_id,trace_length:traceLength});trace._portsRoutedOnPcb=ports,trace.pcb_trace_id=pcb_trace2.pcb_trace_id;for(let point6 of mergedRoute)point6.route_type==="via"&&db.pcb_via.insert({pcb_trace_id:pcb_trace2.pcb_trace_id,x:point6.x,y:point6.y,hole_diameter:holeDiameter,outer_diameter:padDiameter,layers:[point6.from_layer,point6.to_layer],from_layer:point6.from_layer,to_layer:point6.to_layer});trace._insertErrorIfTraceIsOutsideBoard(mergedRoute,ports)}function computeLineRectIntersection(params){let{lineStart,lineEnd,rectCenter,rectWidth,rectHeight}=params,left=rectCenter.x-rectWidth/2,right=rectCenter.x+rectWidth/2,top=rectCenter.y+rectHeight/2,bottom=rectCenter.y-rectHeight/2,dx2=lineEnd.x-lineStart.x,dy2=lineEnd.y-lineStart.y,intersections=[];if(dx2!==0){let t5=(left-lineStart.x)/dx2;if(t5>=0&&t5<=1){let y5=lineStart.y+t5*dy2;y5>=bottom&&y5<=top&&intersections.push({x:left,y:y5,t:t5})}}if(dx2!==0){let t5=(right-lineStart.x)/dx2;if(t5>=0&&t5<=1){let y5=lineStart.y+t5*dy2;y5>=bottom&&y5<=top&&intersections.push({x:right,y:y5,t:t5})}}if(dy2!==0){let t5=(bottom-lineStart.y)/dy2;if(t5>=0&&t5<=1){let x5=lineStart.x+t5*dx2;x5>=left&&x5<=right&&intersections.push({x:x5,y:bottom,t:t5})}}if(dy2!==0){let t5=(top-lineStart.y)/dy2;if(t5>=0&&t5<=1){let x5=lineStart.x+t5*dx2;x5>=left&&x5<=right&&intersections.push({x:x5,y:top,t:t5})}}return intersections.length===0?null:(intersections.sort((a2,b3)=>a2.t-b3.t),{x:intersections[0].x,y:intersections[0].y})}function computeLineCircleIntersection(params){let{lineStart,lineEnd,circleCenter,circleRadius}=params,x12=lineStart.x-circleCenter.x,y12=lineStart.y-circleCenter.y,x22=lineEnd.x-circleCenter.x,y22=lineEnd.y-circleCenter.y,dx2=x22-x12,dy2=y22-y12,a2=dx2*dx2+dy2*dy2,b3=2*(x12*dx2+y12*dy2),c3=x12*x12+y12*y12-circleRadius*circleRadius,discriminant=b3*b3-4*a2*c3;if(discriminant<0)return null;let sqrtDisc=Math.sqrt(discriminant),t12=(-b3-sqrtDisc)/(2*a2),t22=(-b3+sqrtDisc)/(2*a2),t5=null;return t12>=0&&t12<=1?t5=t12:t22>=0&&t22<=1&&(t5=t22),t5===null?null:{x:lineStart.x+t5*dx2,y:lineStart.y+t5*dy2}}function clipTraceEndAtPad(params){let{traceStart,traceEnd,traceWidth,port}=params,pcbPrimitive=port.matchedComponents.find(c3=>c3.isPcbPrimitive);if(!pcbPrimitive)return traceEnd;let padBounds=pcbPrimitive._getPcbCircuitJsonBounds(),padWidth=padBounds.width,padHeight=padBounds.height,padCenter=padBounds.center,smallestPadDimension=Math.min(padWidth,padHeight);if(traceWidth<=smallestPadDimension/2)return traceEnd;let clippedPoint=null;if(pcbPrimitive.componentName==="SmtPad"){let smtPad=pcbPrimitive,padShape=smtPad._parsedProps.shape;if(padShape==="circle"){let radius=smtPad._parsedProps.radius;clippedPoint=computeLineCircleIntersection({lineStart:traceStart,lineEnd:traceEnd,circleCenter:padCenter,circleRadius:radius})}else(padShape==="rect"||padShape==="rotated_rect"||padShape==="pill"||padShape==="polygon")&&(clippedPoint=computeLineRectIntersection({lineStart:traceStart,lineEnd:traceEnd,rectCenter:padCenter,rectWidth:padWidth,rectHeight:padHeight}))}else if(pcbPrimitive.componentName==="PlatedHole"){let platedHole=pcbPrimitive;if(platedHole._parsedProps.shape==="circle"){let outerDiameter=platedHole._parsedProps.outerDiameter;clippedPoint=computeLineCircleIntersection({lineStart:traceStart,lineEnd:traceEnd,circleCenter:padCenter,circleRadius:outerDiameter/2})}else clippedPoint=computeLineRectIntersection({lineStart:traceStart,lineEnd:traceEnd,rectCenter:padCenter,rectWidth:padWidth,rectHeight:padHeight})}return clippedPoint??traceEnd}function Trace_doInitialPcbManualTraceRender(trace){if(trace.root?.pcbDisabled)return;let{db}=trace.root,{_parsedProps:props}=trace,subcircuit=trace.getSubcircuit(),hasPcbPath=props.pcbPath!==void 0,wantsStraightLine=!!props.pcbStraightLine;if(!hasPcbPath&&!wantsStraightLine)return;let{allPortsFound,ports,portsWithSelectors}=trace._findConnectedPorts();if(!allPortsFound)return;let portsWithoutMatchedPcbPrimitive=[];for(let port of ports)port._hasMatchedPcbPrimitive()||portsWithoutMatchedPcbPrimitive.push(port);if(portsWithoutMatchedPcbPrimitive.length>0){db.pcb_trace_error.insert({error_type:"pcb_trace_error",source_trace_id:trace.source_trace_id,message:`Some ports did not have a matching PCB primitive (e.g. a pad or plated hole), this can happen if a footprint is missing. As a result, ${trace} wasn't routed. Missing ports: ${portsWithoutMatchedPcbPrimitive.map(p4=>p4.getString()).join(", ")}`,pcb_trace_id:trace.pcb_trace_id,pcb_component_ids:[],pcb_port_ids:portsWithoutMatchedPcbPrimitive.map(p4=>p4.pcb_port_id).filter(Boolean)});return}let width=trace._getExplicitTraceThickness()??trace.getSubcircuit()._parsedProps.minTraceWidth??.16;if(wantsStraightLine&&!hasPcbPath){if(!ports||ports.length<2){trace.renderError("pcbStraightLine requires exactly two connected ports");return}let[startPort,endPort]=ports,startLayers=startPort.getAvailablePcbLayers(),endLayers=endPort.getAvailablePcbLayers(),layer2=startLayers.find(layer3=>endLayers.includes(layer3))??startLayers[0]??endLayers[0]??"top",startPos=startPort._getGlobalPcbPositionAfterLayout(),endPos=endPort._getGlobalPcbPositionAfterLayout(),clippedStartPos=clipTraceEndAtPad({traceStart:endPos,traceEnd:startPos,traceWidth:width,port:startPort}),clippedEndPos=clipTraceEndAtPad({traceStart:startPos,traceEnd:endPos,traceWidth:width,port:endPort}),route2=[{route_type:"wire",x:clippedStartPos.x,y:clippedStartPos.y,width,layer:layer2,start_pcb_port_id:startPort.pcb_port_id},{route_type:"wire",x:clippedEndPos.x,y:clippedEndPos.y,width,layer:layer2,end_pcb_port_id:endPort.pcb_port_id}],traceLength2=getTraceLength(route2),pcb_trace22=db.pcb_trace.insert({route:route2,source_trace_id:trace.source_trace_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:trace.getGroup()?.pcb_group_id??void 0,trace_length:traceLength2});trace._portsRoutedOnPcb=ports,trace.pcb_trace_id=pcb_trace22.pcb_trace_id,trace._insertErrorIfTraceIsOutsideBoard(route2,ports);return}if(!props.pcbPath)return;let anchorPort;props.pcbPathRelativeTo&&(anchorPort=portsWithSelectors.find(p4=>p4.selector===props.pcbPathRelativeTo)?.port,anchorPort||(anchorPort=trace.getSubcircuit().selectOne(props.pcbPathRelativeTo))),anchorPort||(anchorPort=ports[0]);let otherPort=ports.find(p4=>p4!==anchorPort)??ports[1],layer=anchorPort.getAvailablePcbLayers()[0]||"top",anchorPos=anchorPort._getGlobalPcbPositionAfterLayout(),otherPos=otherPort._getGlobalPcbPositionAfterLayout(),route=[];route.push({route_type:"wire",x:anchorPos.x,y:anchorPos.y,width,layer,start_pcb_port_id:anchorPort.pcb_port_id});let transform5=anchorPort?._computePcbGlobalTransformBeforeLayout?.()||identity();for(let pt4 of props.pcbPath){let coordinates,isGlobalPosition=!1;if(typeof pt4=="string"){let resolvedPort=trace.getSubcircuit().selectOne(pt4,{type:"port"});if(!resolvedPort){db.pcb_trace_error.insert({error_type:"pcb_trace_error",source_trace_id:trace.source_trace_id,message:`Could not resolve pcbPath selector "${pt4}" for ${trace}`,pcb_trace_id:trace.pcb_trace_id,pcb_component_ids:[],pcb_port_ids:[]});continue}let portPos=resolvedPort._getGlobalPcbPositionAfterLayout();coordinates={x:portPos.x,y:portPos.y},isGlobalPosition=!0}else coordinates={x:pt4.x,y:pt4.y},isGlobalPosition=!1;let finalCoordinates=isGlobalPosition?coordinates:applyToPoint(transform5,coordinates);route.push({route_type:"wire",x:finalCoordinates.x,y:finalCoordinates.y,width,layer})}route.push({route_type:"wire",x:otherPos.x,y:otherPos.y,width,layer,end_pcb_port_id:otherPort.pcb_port_id});let traceLength=getTraceLength(route),pcb_trace2=db.pcb_trace.insert({route,source_trace_id:trace.source_trace_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:trace.getGroup()?.pcb_group_id??void 0,trace_length:traceLength});trace._portsRoutedOnPcb=ports,trace.pcb_trace_id=pcb_trace2.pcb_trace_id,trace._insertErrorIfTraceIsOutsideBoard(route,ports)}function Trace__doInitialSchematicTraceRenderWithDisplayLabel(trace){if(trace.root?.schematicDisabled)return;let{db}=trace.root,{_parsedProps:props,parent}=trace;if(!parent)throw new Error("Trace has no parent");let{allPortsFound,portsWithSelectors:connectedPorts}=trace._findConnectedPorts();if(!allPortsFound)return;let portsWithPosition=connectedPorts.map(({port})=>({port,position:port._getGlobalSchematicPositionAfterLayout(),schematic_port_id:port.schematic_port_id,facingDirection:port.facingDirection}));if(portsWithPosition.length<2)throw new Error("Expected at least two ports in portsWithPosition.");let fromPortName,toPortName,fromAnchorPos=portsWithPosition[0].position,fromPort=portsWithPosition[0].port;if("path"in trace.props){if(trace.props.path.length!==2)throw new Error("Invalid 'path': Must contain exactly two elements.");[fromPortName,toPortName]=trace.props.path}else{if(!("from"in trace.props&&"to"in trace.props))throw new Error("Missing 'from' or 'to' properties in props.");fromPortName=trace.props.from,toPortName=trace.props.to}if(!fromPort.source_port_id)throw new Error(`Missing source_port_id for the 'from' port (${fromPortName}).`);let toAnchorPos=portsWithPosition[1].position,toPort=portsWithPosition[1].port;if(!toPort.source_port_id)throw new Error(`Missing source_port_id for the 'to' port (${toPortName}).`);let existingFromNetLabel=db.schematic_net_label.list().find(label=>label.source_net_id===fromPort.source_port_id),existingToNetLabel=db.schematic_net_label.list().find(label=>label.source_net_id===toPort.source_port_id),[firstPort,secondPort]=connectedPorts.map(({port})=>port),pinFullName=firstPort.parent?.config.shouldRenderAsSchematicBox?`${firstPort?.parent?.props.name}_${firstPort?.props.name}`:`${secondPort?.parent?.props.name}_${secondPort?.props.name}`,netLabelText=trace.props.schDisplayLabel??pinFullName;if(existingFromNetLabel&&existingFromNetLabel.text!==netLabelText&&(existingFromNetLabel.text=`${netLabelText} / ${existingFromNetLabel.text}`),existingToNetLabel&&existingToNetLabel?.text!==netLabelText&&(existingToNetLabel.text=`${netLabelText} / ${existingToNetLabel.text}`),!existingToNetLabel){let toSide=getEnteringEdgeFromDirection(toPort.facingDirection)??"bottom";db.schematic_net_label.insert({text:trace.props.schDisplayLabel??pinFullName,source_net_id:toPort.source_port_id,anchor_position:toAnchorPos,center:computeSchematicNetLabelCenter({anchor_position:toAnchorPos,anchor_side:toSide,text:trace.props.schDisplayLabel??pinFullName}),anchor_side:toSide})}if(!existingFromNetLabel){let fromSide=getEnteringEdgeFromDirection(fromPort.facingDirection)??"bottom";db.schematic_net_label.insert({text:trace.props.schDisplayLabel??pinFullName,source_net_id:fromPort.source_port_id,anchor_position:fromAnchorPos,center:computeSchematicNetLabelCenter({anchor_position:fromAnchorPos,anchor_side:fromSide,text:trace.props.schDisplayLabel??pinFullName}),anchor_side:fromSide})}}function Trace__findConnectedPorts(trace){let{_parsedProps:props,parent}=trace;if(!parent)throw new Error("Trace has no parent");let portsWithSelectors=trace.getTracePortPathSelectors().map(selector=>({selector,port:trace.getSubcircuit().selectOne(selector,{type:"port"})??null}));for(let{selector,port}of portsWithSelectors)if(!port){let parentSelector,portToken,dotIndex=selector.lastIndexOf(".");if(dotIndex!==-1&&dotIndex>selector.lastIndexOf(" "))parentSelector=selector.slice(0,dotIndex),portToken=selector.slice(dotIndex+1);else{let match2=selector.match(/^(.*[ >])?([^ >]+)$/);parentSelector=match2?.[1]?.trim()??"",portToken=match2?.[2]??selector}let targetComponent=parentSelector?trace.getSubcircuit().selectOne(parentSelector):null;if(!targetComponent&&parentSelector&&!/[.#\[]/.test(parentSelector)&&(targetComponent=trace.getSubcircuit().selectOne(`.${parentSelector}`)),!targetComponent){let errorMessage2=parentSelector?`Could not find port for selector "${selector}". Component "${parentSelector}" not found`:`Could not find port for selector "${selector}"`,subcircuit2=trace.getSubcircuit(),sourceGroup2=subcircuit2.getGroup();throw new TraceConnectionError({error_type:"source_trace_not_connected_error",message:errorMessage2,subcircuit_id:subcircuit2.subcircuit_id??void 0,source_group_id:sourceGroup2?.source_group_id??void 0,source_trace_id:trace.source_trace_id??void 0,selectors_not_found:[selector]})}let ports=targetComponent.children.filter(c3=>c3.componentName==="Port"),portLabel=portToken.includes(".")?portToken.split(".").pop()??"":portToken,portNames=ports.flatMap(c3=>c3.getNameAndAliases()),hasCustomLabels=portNames.some(n3=>!/^(pin\d+|\d+)$/.test(n3)),labelList=Array.from(new Set(portNames)).join(", "),detail;ports.length===0?detail="It has no ports":hasCustomLabels?detail=`It has [${labelList}]`:detail=`It has ${ports.length} pins and no pinLabels (consider adding pinLabels)`;let errorMessage=`Could not find port for selector "${selector}". Component "${targetComponent.props.name??parentSelector}" found, but does not have pin "${portLabel}". ${detail}`,subcircuit=trace.getSubcircuit(),sourceGroup=subcircuit.getGroup();throw new TraceConnectionError({error_type:"source_trace_not_connected_error",message:errorMessage,subcircuit_id:subcircuit.subcircuit_id??void 0,source_group_id:sourceGroup?.source_group_id??void 0,source_trace_id:trace.source_trace_id??void 0,selectors_not_found:[selector]})}return portsWithSelectors.some(p4=>!p4.port)?{allPortsFound:!1}:{allPortsFound:!0,portsWithSelectors,ports:portsWithSelectors.map(({port})=>port)}}var Trace3=class extends PrimitiveComponent2{constructor(props){super(props);__publicField(this,"source_trace_id",null);__publicField(this,"pcb_trace_id",null);__publicField(this,"schematic_trace_id",null);__publicField(this,"_portsRoutedOnPcb");__publicField(this,"subcircuit_connectivity_map_key",null);__publicField(this,"_traceConnectionHash",null);__publicField(this,"_couldNotFindPort");this._portsRoutedOnPcb=[]}_getExplicitTraceThickness(){return this._parsedProps.thickness??this._parsedProps.width}get config(){return{zodProps:traceProps,componentName:"Trace"}}_getTracePortOrNetSelectorListFromProps(){return"from"in this.props&&"to"in this.props?[typeof this.props.from=="string"?this.props.from:this.props.from.getPortSelector(),typeof this.props.to=="string"?this.props.to:this.props.to.getPortSelector()]:"path"in this.props?this.props.path.map(p4=>typeof p4=="string"?p4:p4.getPortSelector()):[]}getTracePortPathSelectors(){return this._getTracePortOrNetSelectorListFromProps().filter(selector=>!selector.includes("net."))}getTracePathNetSelectors(){return this._getTracePortOrNetSelectorListFromProps().filter(selector=>selector.includes("net."))}_findConnectedPorts(){return Trace__findConnectedPorts(this)}_resolveNet(selector){let direct=this.getSubcircuit().selectOne(selector,{type:"net"});if(direct)return direct;let match2=selector.match(/^net\.(.+)$/),netName=match2?match2[1]:null;if(!netName)return null;let board=this.root?._getBoard();return board?board.getDescendants().find(d3=>d3.componentName==="Net"&&d3._parsedProps.name===netName)||null:(this.renderError(`Could not find a <board> ancestor for ${this}, so net "${selector}" cannot be resolved`),null)}_findConnectedNets(){let netsWithSelectors=this.getTracePathNetSelectors().map(selector=>({selector,net:this._resolveNet(selector)})),undefinedNets=netsWithSelectors.filter(n3=>!n3.net);return undefinedNets.length>0&&this.renderError(`Could not find net for selector "${undefinedNets[0].selector}" inside ${this}`),{netsWithSelectors,nets:netsWithSelectors.map(n3=>n3.net)}}_getAllTracesConnectedToSameNet(){let traces=this.getSubcircuit().selectAll("trace"),myNets=this._findConnectedNets().nets,myPorts=this._findConnectedPorts().ports??[];return traces.filter(t5=>{if(t5===this)return!1;let tNets=t5._findConnectedNets().nets,tPorts=t5._findConnectedPorts().ports??[];return tNets.some(n3=>myNets.includes(n3))||tPorts.some(p4=>myPorts.includes(p4))})}_isExplicitlyConnectedToPort(port){let{allPortsFound,portsWithSelectors:portsWithMetadata}=this._findConnectedPorts();return allPortsFound?portsWithMetadata.map(p4=>p4.port).includes(port):!1}_isExplicitlyConnectedToNet(net){return this._findConnectedNets().nets.includes(net)}doInitialCreateNetsFromProps(){createNetsFromProps(this,this.getTracePathNetSelectors())}_computeTraceConnectionHash(){let{allPortsFound,ports}=this._findConnectedPorts();return!allPortsFound||!ports?null:[...ports].sort((a2,b3)=>(a2.pcb_port_id||"").localeCompare(b3.pcb_port_id||"")).map(p4=>p4.pcb_port_id).join(",")}doInitialSourceTraceRender(){let{db}=this.root,{_parsedProps:props,parent}=this;if(!parent){this.renderError("Trace has no parent");return}let allPortsFound,ports;try{let result=this._findConnectedPorts();allPortsFound=result.allPortsFound,ports=result.portsWithSelectors??[]}catch(error){if(error instanceof TraceConnectionError){db.source_trace_not_connected_error.insert({...error.errorData,error_type:"source_trace_not_connected_error"}),this._couldNotFindPort=!0;return}throw error}if(!allPortsFound)return;this._traceConnectionHash=this._computeTraceConnectionHash();let existingTrace=db.source_trace.list().find(t5=>t5.subcircuit_connectivity_map_key===this.subcircuit_connectivity_map_key&&t5.connected_source_port_ids.sort().join(",")===this._traceConnectionHash);if(existingTrace){this.source_trace_id=existingTrace.source_trace_id;return}let nets=this._findConnectedNets().nets,displayName=getTraceDisplayName({ports,nets}),trace=db.source_trace.insert({connected_source_port_ids:ports.map(p4=>p4.port.source_port_id),connected_source_net_ids:nets.map(n3=>n3.source_net_id),subcircuit_id:this.getSubcircuit()?.subcircuit_id,max_length:getMaxLengthFromConnectedCapacitors(ports.map(p4=>p4.port),{db})??props.maxLength,display_name:displayName,min_trace_thickness:this._getExplicitTraceThickness()});this.source_trace_id=trace.source_trace_id}_insertErrorIfTraceIsOutsideBoard(mergedRoute,ports){let{db}=this.root,board=this._getBoard();if(!board)return;let pcbBoardId=board.pcb_board_id;if(!pcbBoardId)return;isRouteOutsideBoard({mergedRoute,db,pcbBoardId})&&db.pcb_trace_error.insert({error_type:"pcb_trace_error",source_trace_id:this.source_trace_id,message:`Trace ${this.getString()} routed outside the board boundaries.`,pcb_trace_id:this.pcb_trace_id,pcb_component_ids:[],pcb_port_ids:ports.map(p4=>p4.pcb_port_id)})}doInitialPcbManualTraceRender(){Trace_doInitialPcbManualTraceRender(this)}doInitialPcbTraceRender(){Trace_doInitialPcbTraceRender(this)}_doInitialSchematicTraceRenderWithDisplayLabel(){Trace__doInitialSchematicTraceRenderWithDisplayLabel(this)}_isSymbolToChipConnection(){let{allPortsFound,ports}=this._findConnectedPorts();if(!allPortsFound||ports.length!==2)return!1;let[port1,port2]=ports;if(!port1?.parent||!port2?.parent)return!1;let isPort1Chip=port1.parent.config.shouldRenderAsSchematicBox,isPort2Chip=port2.parent.config.shouldRenderAsSchematicBox;return isPort1Chip&&!isPort2Chip||!isPort1Chip&&isPort2Chip}_isSymbolToSymbolConnection(){let{allPortsFound,ports}=this._findConnectedPorts();if(!allPortsFound||ports.length!==2)return!1;let[port1,port2]=ports;if(!port1?.parent||!port2?.parent)return!1;let isPort1Symbol=!port1.parent.config.shouldRenderAsSchematicBox,isPort2Symbol=!port2.parent.config.shouldRenderAsSchematicBox;return isPort1Symbol&&isPort2Symbol}_isChipToChipConnection(){let{allPortsFound,ports}=this._findConnectedPorts();if(!allPortsFound||ports.length!==2)return!1;let[port1,port2]=ports;if(!port1?.parent||!port2?.parent)return!1;let isPort1Chip=port1.parent.config.shouldRenderAsSchematicBox,isPort2Chip=port2.parent.config.shouldRenderAsSchematicBox;return isPort1Chip&&isPort2Chip}doInitialSchematicTraceRender(){Trace_doInitialSchematicTraceRender(this)}},NormalComponent__getMinimumFlexContainerSize=component=>{let{db}=component.root;if(component.pcb_component_id){let pcbComponent=db.pcb_component.get(component.pcb_component_id);return pcbComponent?{width:pcbComponent.width,height:pcbComponent.height}:null}if(component.pcb_group_id){let pcbGroup=db.pcb_group.get(component.pcb_group_id);if(!pcbGroup)return null;if(pcbGroup.outline&&pcbGroup.outline.length>0){let bounds=getBoundsFromPoints(pcbGroup.outline);return bounds?{width:bounds.maxX-bounds.minX,height:bounds.maxY-bounds.minY}:null}return{width:pcbGroup.width??0,height:pcbGroup.height??0}}return null},NormalComponent__repositionOnPcb=(component,position2)=>{let{db}=component.root,allCircuitJson=db.toArray();if(component.pcb_component_id){repositionPcbComponentTo(allCircuitJson,component.pcb_component_id,position2);return}if(component.source_group_id){repositionPcbGroupTo(allCircuitJson,component.source_group_id,position2);return}throw new Error(`Cannot reposition component ${component.getString()}: no pcb_component_id or source_group_id`)},NormalComponent_doInitialSourceDesignRuleChecks=component=>{let{db}=component.root;if(!component.source_component_id)return;let ports=component.selectAll("port"),traces=db.source_trace.list(),connected=new Set;for(let trace of traces)for(let id of trace.connected_source_port_ids)connected.add(id);let internalGroups=component._getInternallyConnectedPins();for(let group of internalGroups)if(group.some(p4=>p4.source_port_id&&connected.has(p4.source_port_id)))for(let p4 of group)p4.source_port_id&&connected.add(p4.source_port_id);for(let port of ports)port.source_port_id&&shouldCheckPortForMissingTrace(component,port)&&(connected.has(port.source_port_id)||db.source_pin_missing_trace_warning.insert({message:`Port ${port.getNameAndAliases()[0]} on ${component.props.name} is missing a trace`,source_component_id:component.source_component_id,source_port_id:port.source_port_id,subcircuit_id:component.getSubcircuit().subcircuit_id??void 0,warning_type:"source_pin_missing_trace_warning"}))},shouldCheckPortForMissingTrace=(component,port)=>{if(component.config.componentName==="Interconnect")return!1;if(component.config.componentName==="Chip"){let pinAttributes=component.props.pinAttributes;if(!pinAttributes)return!1;for(let alias of port.getNameAndAliases()){let attrs=pinAttributes[alias];if(attrs?.requiresPower||attrs?.requiresGround||attrs?.requiresVoltage!==void 0)return!0}return!1}return!0};function getPcbTextBounds(text){let fontSize=text.font_size,textWidth=text.text.length*fontSize*.6,textHeight=fontSize,anchorAlignment=text.anchor_alignment||"center",centerX=text.anchor_position.x,centerY=text.anchor_position.y;switch(anchorAlignment){case"top_left":centerX=text.anchor_position.x+textWidth/2,centerY=text.anchor_position.y+textHeight/2;break;case"top_center":centerX=text.anchor_position.x,centerY=text.anchor_position.y+textHeight/2;break;case"top_right":centerX=text.anchor_position.x-textWidth/2,centerY=text.anchor_position.y+textHeight/2;break;case"center_left":centerX=text.anchor_position.x+textWidth/2,centerY=text.anchor_position.y;break;case"center":centerX=text.anchor_position.x,centerY=text.anchor_position.y;break;case"center_right":centerX=text.anchor_position.x-textWidth/2,centerY=text.anchor_position.y;break;case"bottom_left":centerX=text.anchor_position.x+textWidth/2,centerY=text.anchor_position.y-textHeight/2;break;case"bottom_center":centerX=text.anchor_position.x,centerY=text.anchor_position.y-textHeight/2;break;case"bottom_right":centerX=text.anchor_position.x-textWidth/2,centerY=text.anchor_position.y-textHeight/2;break;default:centerX=text.anchor_position.x,centerY=text.anchor_position.y;break}return{x:centerX-textWidth/2,y:centerY-textHeight/2,width:textWidth,height:textHeight}}function NormalComponent_doInitialSilkscreenOverlapAdjustment(component){if(!component._adjustSilkscreenTextAutomatically||component.root?.pcbDisabled||!component.pcb_component_id)return;let{db}=component.root,componentCenter=component._getPcbCircuitJsonBounds().center,silkscreenTexts=db.pcb_silkscreen_text.list({pcb_component_id:component.pcb_component_id}).filter(text=>text.text===component.name);if(silkscreenTexts.length===0)return;let obstacleBounds=component.getSubcircuit().selectAll("[_isNormalComponent=true]").filter(comp=>comp!==component&&comp.pcb_component_id).map(comp=>{let bounds=comp._getPcbCircuitJsonBounds(),box2={center:bounds.center,width:bounds.width,height:bounds.height};return getBoundingBox2(box2)});for(let silkscreenText of silkscreenTexts){let currentPosition=silkscreenText.anchor_position,textBounds=getPcbTextBounds(silkscreenText),textBox={center:{x:textBounds.x+textBounds.width/2,y:textBounds.y+textBounds.height/2},width:textBounds.width,height:textBounds.height},textBoundsBox=getBoundingBox2(textBox);if(!obstacleBounds.some(obstacle=>doBoundsOverlap(textBoundsBox,obstacle)))continue;let flippedX=2*componentCenter.x-currentPosition.x,flippedY=2*componentCenter.y-currentPosition.y,flippedTextBox={center:{x:flippedX,y:flippedY},width:textBounds.width,height:textBounds.height},flippedTextBounds=getBoundingBox2(flippedTextBox);obstacleBounds.some(obstacle=>doBoundsOverlap(flippedTextBounds,obstacle))||db.pcb_silkscreen_text.update(silkscreenText.pcb_silkscreen_text_id,{anchor_position:{x:flippedX,y:flippedY}})}}function filterPinLabels(pinLabels){if(!pinLabels)return{validPinLabels:pinLabels,invalidPinLabelsMessages:[]};let validPinLabels={},invalidPinLabelsMessages=[];for(let[pin,labelOrLabels]of Object.entries(pinLabels)){let labels=Array.isArray(labelOrLabels)?labelOrLabels.slice():[labelOrLabels],validLabels=[];for(let label of labels)isValidPinLabel(pin,label)?validLabels.push(label):invalidPinLabelsMessages.push(`Invalid pin label: ${pin} = '${label}' - excluding from component. Please use a valid pin label.`);validLabels.length>0&&(validPinLabels[pin]=Array.isArray(labelOrLabels)?validLabels:validLabels[0])}return{validPinLabels:Object.keys(validPinLabels).length>0?validPinLabels:void 0,invalidPinLabelsMessages}}function isValidPinLabel(pin,label){try{let testProps={name:"test",footprint:"test",pinLabels:{[pin]:label}};return chipProps.safeParse(testProps).success}catch{return!1}}var isHttpUrl=s2=>s2.startsWith("http://")||s2.startsWith("https://"),parseLibraryFootprintRef=s2=>{if(isHttpUrl(s2))return null;let idx=s2.indexOf(":");if(idx<=0)return null;let footprintLib=s2.slice(0,idx),footprintName=s2.slice(idx+1);return!footprintLib||!footprintName?null:{footprintLib,footprintName}},isStaticAssetPath=s2=>s2.startsWith("/")||s2.startsWith("./"),resolveStaticFileImportDebug=(0,import_debug9.default)("tscircuit:core:resolveStaticFileImport");async function resolveStaticFileImport(path,platform){if(!path)return path;let normalizedPath=path.startsWith("./")?path.slice(1):path,resolver=platform?.resolveProjectStaticFileImportUrl;if(resolver&&(path.startsWith("/")||path.startsWith("./")))try{let resolved=await resolver(normalizedPath);if(resolved)return resolved}catch(error){resolveStaticFileImportDebug("failed to resolve static file via platform resolver",error)}return constructAssetUrl(normalizedPath,platform?.projectBaseUrl)}function NormalComponent_doInitialPcbFootprintStringRender(component,queueAsyncEffect){let{footprint}=component.props;if(footprint??(footprint=component._getImpliedFootprintString?.()),!footprint)return;let{pcbRotation,pinLabels,pcbPinLabels}=component.props,fileExtension=getFileExtension(String(footprint)),footprintParser=fileExtension?component.root?.platform?.footprintFileParserMap?.[fileExtension]:null;if(typeof footprint=="string"&&(isHttpUrl(footprint)||isStaticAssetPath(footprint))&&footprintParser){if(component._hasStartedFootprintUrlLoad)return;component._hasStartedFootprintUrlLoad=!0,queueAsyncEffect("load-footprint-from-platform-file-parser",async()=>{let footprintUrl=isHttpUrl(footprint)?footprint:await resolveStaticFileImport(footprint,component.root?.platform);try{let result=await footprintParser.loadFromUrl(footprintUrl),fpComponents=createComponentsFromCircuitJson({componentName:component.name,componentRotation:pcbRotation,footprinterString:footprintUrl,pinLabels,pcbPinLabels},result.footprintCircuitJson);component.addAll(fpComponents),component._markDirty("InitializePortsFromChildren")}catch(err){let db=component.root?.db;if(db&&component.source_component_id&&component.pcb_component_id){let subcircuit=component.getSubcircuit(),errorMsg=`${component.getString()} failed to load footprint "${footprintUrl}": `+(err instanceof Error?err.message:String(err)),errorObj=external_footprint_load_error.parse({type:"external_footprint_load_error",message:errorMsg,pcb_component_id:component.pcb_component_id,source_component_id:component.source_component_id,subcircuit_id:subcircuit.subcircuit_id??void 0,pcb_group_id:component.getGroup()?.pcb_group_id??void 0,footprinter_string:footprintUrl});db.external_footprint_load_error.insert(errorObj)}throw err}});return}if(typeof footprint=="string"&&isHttpUrl(footprint)){if(component._hasStartedFootprintUrlLoad)return;component._hasStartedFootprintUrlLoad=!0;let url=footprint;queueAsyncEffect("load-footprint-url",async()=>{try{let res2=await fetch(url);if(!res2.ok)throw new Error(`Failed to fetch footprint: ${res2.status}`);let soup=await res2.json(),fpComponents=createComponentsFromCircuitJson({componentName:component.name,componentRotation:pcbRotation,footprinterString:url,pinLabels,pcbPinLabels},soup);component.addAll(fpComponents),component._markDirty("InitializePortsFromChildren")}catch(err){let db=component.root?.db;if(db&&component.source_component_id&&component.pcb_component_id){let subcircuit=component.getSubcircuit(),errorMsg=`${component.getString()} failed to load external footprint "${url}": `+(err instanceof Error?err.message:String(err)),errorObj=external_footprint_load_error.parse({type:"external_footprint_load_error",message:errorMsg,pcb_component_id:component.pcb_component_id,source_component_id:component.source_component_id,subcircuit_id:subcircuit.subcircuit_id??void 0,pcb_group_id:component.getGroup()?.pcb_group_id??void 0,footprinter_string:url});db.external_footprint_load_error.insert(errorObj)}throw err}});return}if(typeof footprint=="string"){let libRef=parseLibraryFootprintRef(footprint);if(!libRef||component._hasStartedFootprintUrlLoad)return;component._hasStartedFootprintUrlLoad=!0;let libMap=component.root?.platform?.footprintLibraryMap?.[libRef.footprintLib],resolverFn;if(typeof libMap=="function"&&(resolverFn=libMap),!resolverFn)return;let resolvedPcbStyle=component.getInheritedMergedProperty("pcbStyle");queueAsyncEffect("load-lib-footprint",async()=>{try{let result=await resolverFn(libRef.footprintName,{resolvedPcbStyle}),circuitJson=null;if(Array.isArray(result)?circuitJson=result:Array.isArray(result.footprintCircuitJson)&&(circuitJson=result.footprintCircuitJson),!circuitJson)return;let fpComponents=createComponentsFromCircuitJson({componentName:component.name,componentRotation:pcbRotation,footprinterString:footprint,pinLabels,pcbPinLabels},circuitJson);component.addAll(fpComponents),!Array.isArray(result)&&result.cadModel&&(component._asyncFootprintCadModel=result.cadModel);for(let child of component.children)child.componentName==="Port"&&child._markDirty?.("PcbPortRender");component._markDirty("InitializePortsFromChildren")}catch(err){let db=component.root?.db;if(db&&component.source_component_id&&component.pcb_component_id){let subcircuit=component.getSubcircuit(),errorMsg=`${component.getString()} failed to load external footprint "${footprint}": `+(err instanceof Error?err.message:String(err)),errorObj=external_footprint_load_error.parse({type:"external_footprint_load_error",message:errorMsg,pcb_component_id:component.pcb_component_id,source_component_id:component.source_component_id,subcircuit_id:subcircuit.subcircuit_id??void 0,pcb_group_id:component.getGroup()?.pcb_group_id??void 0,footprinter_string:footprint});db.external_footprint_load_error.insert(errorObj)}throw err}});return}if(!(0,import_react3.isValidElement)(footprint)&&footprint.componentName==="Footprint"&&component.add(footprint),Array.isArray(footprint)&&!(0,import_react3.isValidElement)(footprint)&&footprint.length>0){try{let fpComponents=createComponentsFromCircuitJson({componentName:component.name,componentRotation:pcbRotation,footprinterString:"",pinLabels,pcbPinLabels},footprint);component.addAll(fpComponents)}catch(err){let db=component.root?.db;if(db&&component.source_component_id&&component.pcb_component_id){let subcircuit=component.getSubcircuit(),errorMsg=`${component.getString()} failed to load json footprint: `+(err instanceof Error?err.message:String(err)),errorObj=circuit_json_footprint_load_error.parse({type:"circuit_json_footprint_load_error",message:errorMsg,pcb_component_id:component.pcb_component_id,source_component_id:component.source_component_id,subcircuit_id:subcircuit.subcircuit_id??void 0,pcb_group_id:component.getGroup()?.pcb_group_id??void 0});db.circuit_json_footprint_load_error.insert(errorObj)}throw err}return}}function NormalComponent_doInitialPcbComponentAnchorAlignment(component){if(component.root?.pcbDisabled||!component.pcb_component_id)return;let{pcbX,pcbY}=component._parsedProps,pcbPositionAnchor=component.props?.pcbPositionAnchor;if(!pcbPositionAnchor||pcbX===void 0&&pcbY===void 0)return;let bounds=getBoundsOfPcbComponents(component.children);if(bounds.width===0||bounds.height===0)return;let currentCenter={...{x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2}},anchorPos=null;if(new Set(["center","top_left","top_center","top_right","center_left","center_right","bottom_left","bottom_center","bottom_right"]).has(pcbPositionAnchor)){let b3={left:bounds.minX,right:bounds.maxX,top:bounds.minY,bottom:bounds.maxY};switch(pcbPositionAnchor){case"center":anchorPos=currentCenter;break;case"top_left":anchorPos={x:b3.left,y:b3.top};break;case"top_center":anchorPos={x:currentCenter.x,y:b3.top};break;case"top_right":anchorPos={x:b3.right,y:b3.top};break;case"center_left":anchorPos={x:b3.left,y:currentCenter.y};break;case"center_right":anchorPos={x:b3.right,y:currentCenter.y};break;case"bottom_left":anchorPos={x:b3.left,y:b3.bottom};break;case"bottom_center":anchorPos={x:currentCenter.x,y:b3.bottom};break;case"bottom_right":anchorPos={x:b3.right,y:b3.bottom};break}}else try{let port=component.portMap[pcbPositionAnchor];port&&(anchorPos=port._getGlobalPcbPositionBeforeLayout())}catch{}if(!anchorPos)return;let newCenter={...currentCenter};pcbX!==void 0&&(newCenter.x+=pcbX-anchorPos.x),pcbY!==void 0&&(newCenter.y+=pcbY-anchorPos.y),(Math.abs(newCenter.x-currentCenter.x)>1e-6||Math.abs(newCenter.y-currentCenter.y)>1e-6)&&component._repositionOnPcb(newCenter)}var debug32=(0,import_debug5.default)("tscircuit:core"),rotation32=external_exports.object({x:rotation,y:rotation,z:rotation}),NormalComponent3=class extends PrimitiveComponent2{constructor(props){let filteredProps={...props},invalidPinLabelsMessages=[];if(filteredProps.pinLabels&&!Array.isArray(filteredProps.pinLabels)){let{validPinLabels,invalidPinLabelsMessages:messages}=filterPinLabels(filteredProps.pinLabels);filteredProps.pinLabels=validPinLabels,invalidPinLabelsMessages=messages}super(filteredProps);__publicField(this,"reactSubtrees",[]);__publicField(this,"_impliedFootprint");__publicField(this,"isPrimitiveContainer",!0);__publicField(this,"_isNormalComponent",!0);__publicField(this,"_attributeLowerToCamelNameMap",{_isnormalcomponent:"_isNormalComponent"});__publicField(this,"_asyncSupplierPartNumbers");__publicField(this,"_asyncFootprintCadModel");__publicField(this,"_isCadModelChild");__publicField(this,"pcb_missing_footprint_error_id");__publicField(this,"_hasStartedFootprintUrlLoad",!1);__publicField(this,"_invalidPinLabelMessages",[]);__publicField(this,"_adjustSilkscreenTextAutomatically",!1);this._invalidPinLabelMessages=invalidPinLabelsMessages,this._addChildrenFromStringFootprint(),this.initPorts()}get defaultInternallyConnectedPinNames(){return[]}get internallyConnectedPinNames(){return(this._parsedProps.internallyConnectedPins??this.defaultInternallyConnectedPinNames).map(pinGroup=>pinGroup.map(pin=>typeof pin=="number"?`pin${pin}`:pin))}doInitialSourceNameDuplicateComponentRemoval(){if(!this.name)return;let root=this.root;if((this.getSubcircuit().getNormalComponentNameMap?.()?.get(this.props.name)??[]).filter(component=>component!==this&&component.renderPhaseStates.SourceNameDuplicateComponentRemoval.initialized).length>0){let pcbPosition2=this._getGlobalPcbPositionBeforeLayout(),schematicPosition=this._getGlobalSchematicPositionBeforeLayout();root.db.source_failed_to_create_component_error.insert({component_name:this.name,error_type:"source_failed_to_create_component_error",message:`Cannot create component "${this.name}": A component with the same name already exists`,pcb_center:pcbPosition2,schematic_center:schematicPosition}),this.shouldBeRemoved=!0;let childrenToRemove=[...this.children];for(let child of childrenToRemove)this.remove(child)}}initPorts(opts={}){if(this.root?.schematicDisabled)return;let{config}=this,portsToCreate=[],schPortArrangement=this._getSchematicPortArrangement();if(schPortArrangement&&!this._parsedProps.pinLabels){for(let side in schPortArrangement){let pins=schPortArrangement[side].pins;if(Array.isArray(pins))for(let pinNumberOrLabel of pins){let pinNumber=parsePinNumberFromLabelsOrThrow(pinNumberOrLabel,this._parsedProps.pinLabels);portsToCreate.push(new Port({pinNumber,aliases:opts.additionalAliases?.[`pin${pinNumber}`]??[]},{originDescription:`schPortArrangement:${side}`}))}}let sides=["left","right","top","bottom"],pinNum=1;for(let side of sides){let size2=schPortArrangement[`${side}Size`];for(let i2=0;i2<size2;i2++)portsToCreate.push(new Port({pinNumber:pinNum++,aliases:opts.additionalAliases?.[`pin${pinNum}`]??[]},{originDescription:`schPortArrangement:${side}`}))}}let pinLabels=this._parsedProps.pinLabels;if(pinLabels)for(let[pinNumber,label]of Object.entries(pinLabels)){pinNumber=pinNumber.replace("pin","");let existingPort=portsToCreate.find(p4=>p4._parsedProps.pinNumber===Number(pinNumber)),primaryLabel=Array.isArray(label)?label[0]:label,otherLabels=Array.isArray(label)?label.slice(1):[];existingPort?(existingPort.externallyAddedAliases.push(primaryLabel,...otherLabels),existingPort.props.name=primaryLabel):(existingPort=new Port({pinNumber:parseInt(pinNumber),name:primaryLabel,aliases:[...otherLabels,...opts.additionalAliases?.[`pin${parseInt(pinNumber)}`]??[]]},{originDescription:`pinLabels:pin${pinNumber}`}),portsToCreate.push(existingPort))}if(config.schematicSymbolName&&!opts.ignoreSymbolPorts){let sym=Vf[this._getSchematicSymbolNameOrThrow()];if(!sym)return;for(let symPort of sym.ports){let pinNumber=getPinNumberFromLabels(symPort.labels);if(!pinNumber)continue;let existingPort=portsToCreate.find(p4=>p4._parsedProps.pinNumber===Number(pinNumber));if(existingPort)existingPort.schematicSymbolPortDef=symPort;else{let port=getPortFromHints(symPort.labels.concat(opts.additionalAliases?.[`pin${pinNumber}`]??[]));port&&(port.originDescription=`schematicSymbol:labels[0]:${symPort.labels[0]}`,port.schematicSymbolPortDef=symPort,portsToCreate.push(port))}}this.addAll(portsToCreate)}if(!this._getSchematicPortArrangement()){let portsFromFootprint=this.getPortsFromFootprint(opts);for(let port of portsFromFootprint)portsToCreate.some(p4=>p4.isMatchingAnyOf(port.getNameAndAliases()))||portsToCreate.push(port)}let requiredPinCount=opts.pinCount??this._getPinCount()??0;for(let pn3=1;pn3<=requiredPinCount;pn3++){if(portsToCreate.find(p4=>p4._parsedProps.pinNumber===pn3))continue;if(!schPortArrangement){portsToCreate.push(new Port({pinNumber:pn3,aliases:opts.additionalAliases?.[`pin${pn3}`]??[]}));continue}let explicitlyListedPinNumbersInSchPortArrangement=[...schPortArrangement.leftSide?.pins??[],...schPortArrangement.rightSide?.pins??[],...schPortArrangement.topSide?.pins??[],...schPortArrangement.bottomSide?.pins??[]].map(pn22=>parsePinNumberFromLabelsOrThrow(pn22,this._parsedProps.pinLabels));["leftSize","rightSize","topSize","bottomSize","leftPinCount","rightPinCount","topPinCount","bottomPinCount"].some(key=>key in schPortArrangement)&&(explicitlyListedPinNumbersInSchPortArrangement=Array.from({length:this._getPinCount()},(_5,i2)=>i2+1)),explicitlyListedPinNumbersInSchPortArrangement.includes(pn3)&&portsToCreate.push(new Port({pinNumber:pn3,aliases:opts.additionalAliases?.[`pin${pn3}`]??[]},{originDescription:`notOtherwiseAddedButDeducedFromPinCount:${pn3}`}))}portsToCreate.length>0&&this.addAll(portsToCreate)}_getImpliedFootprintString(){return null}_addChildrenFromStringFootprint(){let{pcbRotation,pinLabels,pcbPinLabels}=this.props,{footprint}=this.props;if(footprint??(footprint=this._getImpliedFootprintString?.()),!!footprint&&typeof footprint=="string"){if(isHttpUrl(footprint)||isStaticAssetPath(footprint)||parseLibraryFootprintRef(footprint))return;let fpSoup=fp.string(footprint).soup(),fpComponents=createComponentsFromCircuitJson({componentName:this.name??this.componentName,componentRotation:pcbRotation,footprinterString:footprint,pinLabels,pcbPinLabels},fpSoup);this.addAll(fpComponents)}}get portMap(){return new Proxy({},{get:(target,prop)=>{let port=this.children.find(c3=>c3.componentName==="Port"&&c3.isMatchingNameOrAlias(prop));if(!port)throw new Error(`There was an issue finding the port "${prop.toString()}" inside of a ${this.componentName} component with name: "${this.props.name}". This is a bug in @tscircuit/core`);return port}})}getInstanceForReactElement(element){for(let subtree of this.reactSubtrees)if(subtree.element===element)return subtree.component;return null}doInitialSourceRender(){let ftype=this.config.sourceFtype;if(!ftype)return;let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype,name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSchematicComponentRender(){if(this.root?.schematicDisabled)return;let{db}=this.root;if(this._invalidPinLabelMessages?.length&&this.root?.db)for(let message of this._invalidPinLabelMessages){let property_name="pinLabels",match2=message.match(/^Invalid pin label:\s*([^=]+)=\s*'([^']+)'/);match2&&(property_name=`pinLabels['${match2[2]}']`),this.root.db.source_property_ignored_warning.insert({source_component_id:this.source_component_id,property_name,message,error_type:"source_property_ignored_warning"})}let{schematicSymbolName}=this.config,{_parsedProps:props}=this;props.symbol&&(0,import_react2.isValidElement)(props.symbol)?this._doInitialSchematicComponentRenderWithReactSymbol(props.symbol):schematicSymbolName?this._doInitialSchematicComponentRenderWithSymbol():this._getSchematicBoxDimensions()&&this._doInitialSchematicComponentRenderWithSchematicBoxDimensions();let manualPlacement=this.getSubcircuit()?._getSchematicManualPlacementForComponent(this);if(this.schematic_component_id&&(this.props.schX!==void 0||this.props.schY!==void 0)&&manualPlacement){if(!this.schematic_component_id)return;let warning=schematic_manual_edit_conflict_warning.parse({type:"schematic_manual_edit_conflict_warning",schematic_manual_edit_conflict_warning_id:`schematic_manual_edit_conflict_${this.source_component_id}`,message:`${this.getString()} has both manual placement and prop coordinates. schX and schY will be used. Remove schX/schY or clear the manual placement.`,schematic_component_id:this.schematic_component_id,source_component_id:this.source_component_id,subcircuit_id:this.getSubcircuit()?.subcircuit_id});db.schematic_manual_edit_conflict_warning.insert(warning)}}_getSchematicSymbolDisplayValue(){}_getInternallyConnectedPins(){if(this.internallyConnectedPinNames.length===0)return[];let internallyConnectedPorts=[];for(let netPortNames of this.internallyConnectedPinNames){let ports=[];for(let portName of netPortNames)ports.push(this.portMap[portName]);internallyConnectedPorts.push(ports)}return internallyConnectedPorts}_doInitialSchematicComponentRenderWithSymbol(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,symbol_name=this._getSchematicSymbolNameOrThrow(),symbol=Vf[symbol_name],center2=this._getGlobalSchematicPositionBeforeLayout();if(symbol){let schematic_component2=db.schematic_component.insert({center:center2,size:symbol.size,source_component_id:this.source_component_id,is_box_with_pins:!0,symbol_name,symbol_display_value:this._getSchematicSymbolDisplayValue()});this.schematic_component_id=schematic_component2.schematic_component_id}}_doInitialSchematicComponentRenderWithReactSymbol(symbolElement){if(this.root?.schematicDisabled)return;let{db}=this.root,center2=this._getGlobalSchematicPositionBeforeLayout(),schematic_component2=db.schematic_component.insert({center:center2,size:{width:0,height:0},source_component_id:this.source_component_id,symbol_display_value:this._getSchematicSymbolDisplayValue(),is_box_with_pins:!1});this.schematic_component_id=schematic_component2.schematic_component_id}_doInitialSchematicComponentRenderWithSchematicBoxDimensions(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,dimensions=this._getSchematicBoxDimensions(),primaryPortLabels={};if(Array.isArray(props.pinLabels))props.pinLabels.forEach((label,index)=>{primaryPortLabels[String(index+1)]=label});else for(let[port,label]of Object.entries(props.pinLabels??{}))primaryPortLabels[port]=Array.isArray(label)?label[0]:label;let center2=this._getGlobalSchematicPositionBeforeLayout(),schPortArrangement=this._getSchematicPortArrangement(),schematic_component2=db.schematic_component.insert({center:center2,rotation:props.schRotation??0,size:dimensions.getSize(),port_arrangement:underscorifyPortArrangement(schPortArrangement),pin_spacing:props.schPinSpacing??.2,pin_styles:underscorifyPinStyles(props.schPinStyle,props.pinLabels),port_labels:primaryPortLabels,source_component_id:this.source_component_id}),hasTopOrBottomPins=schPortArrangement?.topSide!==void 0||schPortArrangement?.bottomSide!==void 0,schematic_box_width=dimensions?.getSize().width,schematic_box_height=dimensions?.getSize().height,manufacturer_part_number_schematic_text=db.schematic_text.insert({text:props.manufacturerPartNumber??"",schematic_component_id:schematic_component2.schematic_component_id,anchor:"left",rotation:0,position:{x:hasTopOrBottomPins?center2.x+(schematic_box_width??0)/2+.1:center2.x-(schematic_box_width??0)/2,y:hasTopOrBottomPins?center2.y+(schematic_box_height??0)/2+.35:center2.y-(schematic_box_height??0)/2-.13},color:"#006464",font_size:.18}),component_name_text=db.schematic_text.insert({text:props.displayName??props.name??"",schematic_component_id:schematic_component2.schematic_component_id,anchor:"left",rotation:0,position:{x:hasTopOrBottomPins?center2.x+(schematic_box_width??0)/2+.1:center2.x-(schematic_box_width??0)/2,y:hasTopOrBottomPins?center2.y+(schematic_box_height??0)/2+.55:center2.y+(schematic_box_height??0)/2+.13},color:"#006464",font_size:.18});this.schematic_component_id=schematic_component2.schematic_component_id}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,subcircuit=this.getSubcircuit(),componentLayer=props.layer??"top";if(componentLayer!=="top"&&componentLayer!=="bottom"){let error=pcb_component_invalid_layer_error.parse({type:"pcb_component_invalid_layer_error",message:`Component cannot be placed on layer '${componentLayer}'. Components can only be placed on 'top' or 'bottom' layers.`,source_component_id:this.source_component_id,layer:componentLayer,subcircuit_id:subcircuit.subcircuit_id??void 0});db.pcb_component_invalid_layer_error.insert(error)}let globalTransform=this._computePcbGlobalTransformBeforeLayout(),accumulatedRotation=decomposeTSR(globalTransform).rotation.angle*180/Math.PI,pcb_component2=db.pcb_component.insert({center:this._getGlobalPcbPositionBeforeLayout(),width:0,height:0,layer:componentLayer==="top"||componentLayer==="bottom"?componentLayer:"top",rotation:props.pcbRotation??accumulatedRotation,source_component_id:this.source_component_id,subcircuit_id:subcircuit.subcircuit_id??void 0,do_not_place:props.doNotPlace??!1,obstructs_within_bounds:props.obstructsWithinBounds??!0});if(!(props.footprint??this._getImpliedFootprintString())&&!this.isGroup){let footprint_error=db.pcb_missing_footprint_error.insert({message:`No footprint found for component: ${this.getString()}`,source_component_id:`${this.source_component_id}`,error_type:"pcb_missing_footprint_error"});this.pcb_missing_footprint_error_id=footprint_error.pcb_missing_footprint_error_id}this.pcb_component_id=pcb_component2.pcb_component_id;let manualPlacement=this.getSubcircuit()._getPcbManualPlacementForComponent(this);if((this.props.pcbX!==void 0||this.props.pcbY!==void 0)&&manualPlacement){let warning=pcb_manual_edit_conflict_warning.parse({type:"pcb_manual_edit_conflict_warning",pcb_manual_edit_conflict_warning_id:`pcb_manual_edit_conflict_${this.source_component_id}`,message:`${this.getString()} has both manual placement and prop coordinates. pcbX and pcbY will be used. Remove pcbX/pcbY or clear the manual placement.`,pcb_component_id:this.pcb_component_id,source_component_id:this.source_component_id,subcircuit_id:subcircuit.subcircuit_id??void 0});db.pcb_manual_edit_conflict_warning.insert(warning)}}doInitialPcbComponentSizeCalculation(){if(this.root?.pcbDisabled||!this.pcb_component_id)return;let{db}=this.root,{_parsedProps:props}=this,bounds=getBoundsOfPcbComponents(this.children);if(bounds.width===0||bounds.height===0)return;let center2={x:(bounds.minX+bounds.maxX)/2,y:(bounds.minY+bounds.maxY)/2};db.pcb_component.update(this.pcb_component_id,{center:center2,width:bounds.width,height:bounds.height})}updatePcbComponentSizeCalculation(){this.doInitialPcbComponentSizeCalculation()}doInitialSchematicComponentSizeCalculation(){if(this.root?.schematicDisabled||!this.schematic_component_id)return;let{db}=this.root;if(!db.schematic_component.get(this.schematic_component_id))return;let schematicElements=[],collectSchematicPrimitives=children=>{for(let child of children){if(child.isSchematicPrimitive&&child.componentName==="SchematicLine"){let line2=db.schematic_line.get(child.schematic_line_id);line2&&schematicElements.push(line2)}if(child.isSchematicPrimitive&&child.componentName==="SchematicRect"){let rect=db.schematic_rect.get(child.schematic_rect_id);rect&&schematicElements.push(rect)}if(child.isSchematicPrimitive&&child.componentName==="SchematicCircle"){let circle2=db.schematic_circle.get(child.schematic_circle_id);circle2&&schematicElements.push(circle2)}if(child.isSchematicPrimitive&&child.componentName==="SchematicArc"){let arc2=db.schematic_arc.get(child.schematic_arc_id);arc2&&schematicElements.push(arc2)}if(child.isSchematicPrimitive&&child.componentName==="SchematicText"){let text=db.schematic_text.get(child.schematic_text_id);text&&schematicElements.push(text)}child.children&&child.children.length>0&&collectSchematicPrimitives(child.children)}};if(collectSchematicPrimitives(this.children),schematicElements.length===0)return;let bounds=getBoundsForSchematic(schematicElements),width=Math.abs(bounds.maxX-bounds.minX),height=Math.abs(bounds.maxY-bounds.minY);if(width===0&&height===0)return;let centerX=(bounds.minX+bounds.maxX)/2,centerY=(bounds.minY+bounds.maxY)/2;db.schematic_component.update(this.schematic_component_id,{center:{x:centerX,y:centerY},size:{width,height}})}updateSchematicComponentSizeCalculation(){this.doInitialSchematicComponentSizeCalculation()}doInitialPcbComponentAnchorAlignment(){NormalComponent_doInitialPcbComponentAnchorAlignment(this)}updatePcbComponentAnchorAlignment(){this.doInitialPcbComponentAnchorAlignment()}_renderReactSubtree(element){let component=createInstanceFromReactElement(element);return{element,component}}doInitialInitializePortsFromChildren(){this.initPorts()}doInitialReactSubtreesRender(){let fpElm=this.props.footprint;(0,import_react2.isValidElement)(fpElm)&&(this.children.some(c3=>c3.componentName==="Footprint")||this.add(fpElm));let symElm=this.props.symbol;(0,import_react2.isValidElement)(symElm)&&(this.children.some(c3=>c3.componentName==="Symbol")||this.add(symElm));let cmElm=this.props.cadModel;if((0,import_react2.isValidElement)(cmElm)){this._isCadModelChild=!0;let hasCadAssemblyChild=this.children.some(c3=>c3.componentName==="CadAssembly"),hasCadModelChild=this.children.some(c3=>c3.componentName==="CadModel");!hasCadAssemblyChild&&!hasCadModelChild&&this.add(cmElm)}}doInitialPcbFootprintStringRender(){NormalComponent_doInitialPcbFootprintStringRender(this,(name,effect)=>this._queueAsyncEffect(name,effect))}_hasExistingPortExactly(port1){return this.children.filter(c3=>c3.componentName==="Port").some(port2=>{let aliases1=port1.getNameAndAliases(),aliases2=port2.getNameAndAliases();return aliases1.length===aliases2.length&&aliases1.every(alias=>aliases2.includes(alias))})}add(componentOrElm){let component;if((0,import_react2.isValidElement)(componentOrElm)){let subtree=this._renderReactSubtree(componentOrElm);this.reactSubtrees.push(subtree),component=subtree.component}else component=componentOrElm;if(component.componentName==="Port"){if(this._hasExistingPortExactly(component))return;let conflictingPort=this.children.filter(c3=>c3.componentName==="Port").find(p4=>p4.isMatchingAnyOf(component.getNameAndAliases()));conflictingPort&&debug32(`Similar ports added. Port 1: ${conflictingPort}, Port 2: ${component}`)}super.add(component)}getPortsFromFootprint(opts){let{footprint}=this.props;if((!footprint||(0,import_react2.isValidElement)(footprint))&&(footprint=this.children.find(c3=>c3.componentName==="Footprint")),typeof footprint=="string"){if(isHttpUrl(footprint))return[];if(isStaticAssetPath(footprint))return[];if(parseLibraryFootprintRef(footprint))return[];let fpSoup=fp.string(footprint).soup(),newPorts2=[];for(let elm of fpSoup)if("port_hints"in elm&&elm.port_hints){let newPort=getPortFromHints(elm.port_hints,opts);if(!newPort)continue;newPort.originDescription=`footprint:string:${footprint}:port_hints[0]:${elm.port_hints[0]}`,newPorts2.push(newPort)}return newPorts2}if(!(0,import_react2.isValidElement)(footprint)&&footprint&&footprint.componentName==="Footprint"){let fp2=footprint,pinNumber=1,newPorts2=[];for(let fpChild of fp2.children){if(!fpChild.props.portHints)continue;let portHintsList=fpChild.props.portHints;portHintsList.some(hint=>hint.startsWith("pin"))||(portHintsList=[...portHintsList,`pin${pinNumber}`]),pinNumber++;let newPort=getPortFromHints(portHintsList);newPort&&(newPort.originDescription=`footprint:${footprint}`,newPorts2.push(newPort))}return newPorts2}let newPorts=[];if(!footprint){for(let child of this.children)if(child.props.portHints&&child.isPcbPrimitive){let port=getPortFromHints(child.props.portHints);port&&newPorts.push(port)}}return newPorts}getPortsFromSchematicSymbol(){if(this.root?.schematicDisabled)return[];let{config}=this;if(!config.schematicSymbolName)return[];let symbol=Vf[config.schematicSymbolName];if(!symbol)return[];let newPorts=[];for(let symbolPort of symbol.ports){let port=getPortFromHints(symbolPort.labels);port&&(port.schematicSymbolPortDef=symbolPort,newPorts.push(port))}return newPorts}doInitialCreateNetsFromProps(){this._createNetsFromProps(this._getNetsFromConnectionsProp())}_getNetsFromConnectionsProp(){let{_parsedProps:props}=this,propsWithConnections=[];if(props.connections)for(let[pinName,target]of Object.entries(props.connections)){let targets=Array.isArray(target)?target:[target];for(let targetPath of targets)propsWithConnections.push(String(targetPath))}return propsWithConnections}_createNetsFromProps(propsWithConnections){createNetsFromProps(this,propsWithConnections)}_getPcbCircuitJsonBounds(){let{db}=this.root;if(!this.pcb_component_id)return super._getPcbCircuitJsonBounds();let pcb_component2=db.pcb_component.get(this.pcb_component_id);return{center:{x:pcb_component2.center.x,y:pcb_component2.center.y},bounds:{left:pcb_component2.center.x-pcb_component2.width/2,top:pcb_component2.center.y-pcb_component2.height/2,right:pcb_component2.center.x+pcb_component2.width/2,bottom:pcb_component2.center.y+pcb_component2.height/2},width:pcb_component2.width,height:pcb_component2.height}}_getPinCountFromSchematicPortArrangement(){let schPortArrangement=this._getSchematicPortArrangement();if(!schPortArrangement)return 0;if(!isExplicitPinMappingArrangement(schPortArrangement))return(schPortArrangement.leftSize??schPortArrangement.leftPinCount??0)+(schPortArrangement.rightSize??schPortArrangement.rightPinCount??0)+(schPortArrangement.topSize??schPortArrangement.topPinCount??0)+(schPortArrangement.bottomSize??schPortArrangement.bottomPinCount??0);let{leftSide,rightSide,topSide,bottomSide}=schPortArrangement;return Math.max(...leftSide?.pins??[],...rightSide?.pins??[],...topSide?.pins??[],...bottomSide?.pins??[])}_getPinCount(){if(this._getSchematicPortArrangement())return this._getPinCountFromSchematicPortArrangement();let portsFromFootprint=this.getPortsFromFootprint();if(portsFromFootprint.length>0)return portsFromFootprint.length;let{pinLabels}=this._parsedProps;if(pinLabels){if(Array.isArray(pinLabels))return pinLabels.length;let pinNumbers=Object.keys(pinLabels).map(k4=>k4.startsWith("pin")?parseInt(k4.slice(3)):parseInt(k4)).filter(n3=>!Number.isNaN(n3));return pinNumbers.length>0?Math.max(...pinNumbers):Object.keys(pinLabels).length}return 0}_getSchematicPortArrangement(){return this._parsedProps.schPinArrangement??this._parsedProps.schPortArrangement}_getPinLabelsFromPorts(){let ports=this.selectAll("port"),pinLabels={};for(let port of ports){let pinNumber=port.props.pinNumber;if(pinNumber!==void 0){let bestLabel=port._getBestDisplayPinLabel();bestLabel&&(pinLabels[`pin${pinNumber}`]=bestLabel)}}return pinLabels}_getSchematicBoxDimensions(){if(this.getSchematicSymbol()||!this.config.shouldRenderAsSchematicBox)return null;let{_parsedProps:props}=this,pinCount=this._getPinCount(),pinSpacing=props.schPinSpacing??.2,allPinLabels={...this._getPinLabelsFromPorts(),...props.pinLabels};return getAllDimensionsForSchematicBox({schWidth:props.schWidth,schHeight:props.schHeight,schPinSpacing:pinSpacing,numericSchPinStyle:getNumericSchPinStyle(props.schPinStyle,allPinLabels),pinCount,schPortArrangement:this._getSchematicPortArrangement(),pinLabels:allPinLabels})}getFootprinterString(){return typeof this._parsedProps.footprint=="string"?this._parsedProps.footprint:null}doInitialCadModelRender(){if(this._isCadModelChild||this.props.doNotPlace)return;let{db}=this.root,{boardThickness=0}=this.root?._getBoard()??{},cadModelProp2=this._parsedProps.cadModel,cadModel=cadModelProp2===void 0?this._asyncFootprintCadModel:cadModelProp2,footprint=this.getFootprinterString()??this._getImpliedFootprintString();if(!this.pcb_component_id||!cadModel&&!footprint||cadModel===null)return;let bounds=this._getPcbCircuitJsonBounds();if(typeof cadModel=="string")throw new Error("String cadModel not yet implemented");let rotationOffset=rotation32.parse({x:0,y:0,z:typeof cadModel?.rotationOffset=="number"?cadModel.rotationOffset:0,...typeof cadModel?.rotationOffset=="object"?cadModel.rotationOffset??{}:{}}),positionOffset=point3.parse({x:0,y:0,z:0,...typeof cadModel?.positionOffset=="object"?cadModel.positionOffset:{}}),zOffsetFromSurface=cadModel&&typeof cadModel=="object"&&"zOffsetFromSurface"in cadModel&&cadModel.zOffsetFromSurface!==void 0?distance.parse(cadModel.zOffsetFromSurface):0,computedLayer=this.props.layer==="bottom"?"bottom":"top",globalTransform=this._computePcbGlobalTransformBeforeLayout(),totalRotation=decomposeTSR(globalTransform).rotation.angle*180/Math.PI,isBottomLayer=computedLayer==="bottom",rotationWithOffset=totalRotation+(rotationOffset.z??0),cadRotationZ=normalizeDegrees(rotationWithOffset),cad_model=db.cad_component.insert({position:{x:bounds.center.x+positionOffset.x,y:bounds.center.y+positionOffset.y,z:(computedLayer==="bottom"?-boardThickness/2:boardThickness/2)+(computedLayer==="bottom"?-zOffsetFromSurface:zOffsetFromSurface)+positionOffset.z},rotation:{x:rotationOffset.x,y:rotationOffset.y+(isBottomLayer?180:0),z:normalizeDegrees(isBottomLayer?-cadRotationZ:cadRotationZ)},pcb_component_id:this.pcb_component_id,source_component_id:this.source_component_id,model_stl_url:"stlUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.stlUrl):void 0,model_obj_url:"objUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.objUrl):void 0,model_mtl_url:"mtlUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.mtlUrl):void 0,model_gltf_url:"gltfUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.gltfUrl):void 0,model_glb_url:"glbUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.glbUrl):void 0,model_step_url:"stepUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.stepUrl):void 0,model_wrl_url:"wrlUrl"in(cadModel??{})?this._addCachebustToModelUrl(cadModel.wrlUrl):void 0,model_jscad:"jscad"in(cadModel??{})?cadModel.jscad:void 0,model_unit_to_mm_scale_factor:typeof cadModel?.modelUnitToMmScale=="number"?cadModel.modelUnitToMmScale:void 0,footprinter_string:typeof footprint=="string"&&!cadModel?footprint:void 0,show_as_translucent_model:this._parsedProps.showAsTranslucentModel});this.cad_component_id=cad_model.cad_component_id}_addCachebustToModelUrl(url){if(!url||!url.includes("modelcdn.tscircuit.com"))return url;let origin=this.root?.getClientOrigin()??"";return`${url}${url.includes("?")?"&":"?"}cachebust_origin=${encodeURIComponent(origin)}`}_getPartsEngineCacheKey(source_component,footprinterString){return JSON.stringify({ftype:source_component.ftype,name:source_component.name,manufacturer_part_number:source_component.manufacturer_part_number,footprinterString})}async _getSupplierPartNumbers(partsEngine2,source_component,footprinterString){if(this.props.doNotPlace)return{};let cacheEngine=this.root?.platform?.localCacheEngine,cacheKey=this._getPartsEngineCacheKey(source_component,footprinterString);if(cacheEngine){let cached=await cacheEngine.getItem(cacheKey);if(cached)try{return JSON.parse(cached)}catch{}}let result=await Promise.resolve(partsEngine2.findPart({sourceComponent:source_component,footprinterString}));if(typeof result=="string"){if(result.includes("<!DOCTYPE")||result.includes("<html"))throw new Error(`Failed to fetch supplier part numbers: Received HTML response instead of JSON. Response starts with: ${result.substring(0,100)}`);if(result==="Not found")return{};throw new Error(`Invalid supplier part numbers format: Expected object but got string: "${result}"`)}if(!result||Array.isArray(result)||typeof result!="object"){let actualType=result===null?"null":Array.isArray(result)?"array":typeof result;throw new Error(`Invalid supplier part numbers format: Expected object but got ${actualType}`)}let supplierPartNumbers=result;if(cacheEngine)try{await cacheEngine.setItem(cacheKey,JSON.stringify(supplierPartNumbers))}catch{}return supplierPartNumbers}doInitialPartsEngineRender(){if(this.props.doNotPlace||this.getInheritedProperty("bomDisabled")||this.getInheritedProperty("partsEngineDisabled"))return;let partsEngine2=this.getInheritedProperty("partsEngine");if(!partsEngine2)return;let{db}=this.root,source_component=db.source_component.get(this.source_component_id);if(!source_component||source_component.supplier_part_numbers)return;let footprinterString;this.props.footprint&&typeof this.props.footprint=="string"&&(footprinterString=this.props.footprint);let supplierPartNumbersMaybePromise=this._getSupplierPartNumbers(partsEngine2,source_component,footprinterString);if(!(supplierPartNumbersMaybePromise instanceof Promise)){db.source_component.update(this.source_component_id,{supplier_part_numbers:supplierPartNumbersMaybePromise});return}this._queueAsyncEffect("get-supplier-part-numbers",async()=>{await supplierPartNumbersMaybePromise.then(supplierPartNumbers=>{this._asyncSupplierPartNumbers=supplierPartNumbers,this._markDirty("PartsEngineRender")}).catch(error=>{this._asyncSupplierPartNumbers={};let errorObj=unknown_error_finding_part.parse({type:"unknown_error_finding_part",message:`Failed to fetch supplier part numbers for ${this.getString()}: ${error.message}`,source_component_id:this.source_component_id,subcircuit_id:this.getSubcircuit()?.subcircuit_id});db.unknown_error_finding_part.insert(errorObj),this._markDirty("PartsEngineRender")})})}updatePartsEngineRender(){if(this.props.doNotPlace||this.getInheritedProperty("bomDisabled")||this.getInheritedProperty("partsEngineDisabled"))return;let{db}=this.root,source_component=db.source_component.get(this.source_component_id);if(source_component&&!source_component.supplier_part_numbers&&this._asyncSupplierPartNumbers){db.source_component.update(this.source_component_id,{supplier_part_numbers:this._asyncSupplierPartNumbers});return}}doInitialAssignFallbackProps(){let{_parsedProps:props}=this;props.connections&&!this.name&&(this.fallbackUnassignedName=this.getSubcircuit().getNextAvailableName(this))}doInitialCreateTracesFromProps(){this._createTracesFromConnectionsProp()}_createTracesFromConnectionsProp(){let{_parsedProps:props}=this;if(props.connections)for(let[pinName,target]of Object.entries(props.connections)){let targets=Array.isArray(target)?target:[target];for(let targetPath of targets)this.add(new Trace3({from:`.${this.name} > .${pinName}`,to:String(targetPath)}))}}doInitialSourceDesignRuleChecks(){NormalComponent_doInitialSourceDesignRuleChecks(this)}doInitialPcbLayout(){if(this.root?.pcbDisabled||!this.pcb_component_id)return;let{db}=this.root,props=this._parsedProps;if(!(props.pcbX!==void 0||props.pcbY!==void 0))return;let positionedRelativeToGroupId=this.getGroup()?.pcb_group_id??void 0,positionedRelativeToBoardId=positionedRelativeToGroupId?void 0:this._getBoard()?.pcb_board_id??void 0;db.pcb_component.update(this.pcb_component_id,{position_mode:"relative_to_group_anchor",positioned_relative_to_pcb_group_id:positionedRelativeToGroupId,positioned_relative_to_pcb_board_id:positionedRelativeToBoardId,display_offset_x:props.pcbX,display_offset_y:props.pcbY})}_getMinimumFlexContainerSize(){return NormalComponent__getMinimumFlexContainerSize(this)}_repositionOnPcb(position2){return NormalComponent__repositionOnPcb(this,position2)}doInitialSilkscreenOverlapAdjustment(){return NormalComponent_doInitialSilkscreenOverlapAdjustment(this)}isRelativelyPositioned(){return this._parsedProps.pcbX!==void 0||this._parsedProps.pcbY!==void 0}},getBoardCenterFromAnchor=({boardAnchorPosition,boardAnchorAlignment,width,height})=>{let{x:ax2,y:ay2}=boardAnchorPosition,cx2=ax2,cy2=ay2;switch(boardAnchorAlignment){case"top_left":cx2=ax2+width/2,cy2=ay2-height/2;break;case"top_right":cx2=ax2-width/2,cy2=ay2-height/2;break;case"bottom_left":cx2=ax2+width/2,cy2=ay2+height/2;break;case"bottom_right":cx2=ax2-width/2,cy2=ay2+height/2;break;case"top":cx2=ax2,cy2=ay2-height/2;break;case"bottom":cx2=ax2,cy2=ay2+height/2;break;case"left":cx2=ax2+width/2,cy2=ay2;break;case"right":cx2=ax2-width/2,cy2=ay2;break;default:break}return{x:cx2,y:cy2}},SOLVERS={PackSolver2,AutoroutingPipelineSolver:ni2,AssignableAutoroutingPipeline2:br2,AssignableAutoroutingPipeline3:Fa2,AutoroutingPipeline1_OriginalUnravel:Zi2,CopperPourPipelineSolver},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:autorouterVersion2,effort,onSolverStarted}=options,solverName;autorouterVersion2==="v1"?solverName="AutoroutingPipeline1_OriginalUnravel":useAutoJumperSolver?solverName="AssignableAutoroutingPipeline3":useAssignableSolver?solverName="AssignableAutoroutingPipeline2":solverName="AutoroutingPipelineSolver";let SolverClass=SOLVERS[solverName];this.solver=new SolverClass(input2,{capacityDepth,targetMinCapacity,cacheProvider:null,effort}),onSolverStarted?.({solverName,solverParams:{input:input2,options:{capacityDepth,targetMinCapacity,cacheProvider:null,effort}}}),this.stepDelay=stepDelay}start(){this.isRouting||(this.isRouting=!0,this.cycleCount=0,this.runCycleAndQueueNextCycle())}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;)this.solver.step();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(error){this.emitEvent({type:"error",error:error instanceof Error?new AutorouterError(error.message):new AutorouterError(String(error))}),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():{}}},TraceHint=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"matchedPort",null)}get config(){return{componentName:"TraceHint",zodProps:traceHintProps}}doInitialPortMatching(){let{db}=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=>({...applyToPoint(globalTransform,offset),via:offset.via,to_layer:offset.to_layer,trace_width:offset.trace_width}))}doInitialPcbTraceHintRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this;db.pcb_trace_hint.insert({pcb_component_id:this.matchedPort?.pcb_component_id,pcb_port_id:this.matchedPort?.pcb_port_id,route:this.getPcbRouteHints()})}},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_component2=su2(circuitJson).pcb_component.get(pcb_component_id);if(!pcb_component2)continue;let source_component=su2(circuitJson).source_component.get(pcb_component2.source_component_id);if(!source_component)continue;let existingPlacementIndex=updatedManualEditsFile.pcb_placements?.findIndex(p4=>p4.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_component2=su2(circuitJson).schematic_component.get(schematic_component_id);if(!schematic_component2||!schematic_component2.source_component_id)continue;let source_component=su2(circuitJson).source_component.get(schematic_component2.source_component_id);if(!source_component)continue;let existingPlacementIndex=updatedManualEditsFile.schematic_placements?.findIndex(p4=>p4.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(e4=>e4.pcb_trace_hint_id===edit_event.pcb_trace_hint_id?{...e4,route:edit_event.route}:e4);else{let pcbPort=su2(circuitJson).pcb_port.get(edit_event.pcb_port_id);circuitJson=circuitJson.filter(e4=>!(e4.type==="pcb_trace_hint"&&e4.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(e4=>e4.type==="pcb_component"&&e4.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=translate(editEvent.new_center.x-editEvent.original_center.x,editEvent.new_center.y-editEvent.original_center.y);circuitJson=circuitJson.map(e4=>e4.pcb_component_id!==editEvent.pcb_component_id?e4:transformPCBElement(e4,mat))}}else editEvent.edit_event_type==="edit_schematic_component_location"?circuitJson=circuitJson.map(e4=>e4.type==="schematic_component"&&e4.schematic_component_id===editEvent.schematic_component_id?{...e4,center:editEvent.new_center}:e4):editEvent.edit_event_type==="edit_pcb_trace_hint"&&(circuitJson=applyTraceHintEditEvent(circuitJson,editEvent));return circuitJson},getDescendantSubcircuitIds=(db,root_subcircuit_id)=>{let groups=db.source_group.list(),result=[],findDescendants=parentId=>{let children=groups.filter(group=>group.parent_subcircuit_id===parentId);for(let child of children)child.subcircuit_id&&(result.push(child.subcircuit_id),findDescendants(child.subcircuit_id))};return findDescendants(root_subcircuit_id),result},getSimpleRouteJsonFromCircuitJson=({db,circuitJson,subcircuit_id,minTraceWidth=.1,nominalTraceWidth})=>{if(!db&&circuitJson&&(db=su2(circuitJson)),!db)throw new Error("db or circuitJson is required");let traceHints=db.pcb_trace_hint.list(),relevantSubcircuitIds=subcircuit_id?new Set([subcircuit_id]):null;if(subcircuit_id){let descendantSubcircuitIds=getDescendantSubcircuitIds(db,subcircuit_id);for(let id of descendantSubcircuitIds)relevantSubcircuitIds.add(id)}let subcircuitElements=(circuitJson??db.toArray()).filter(e4=>!subcircuit_id||"subcircuit_id"in e4&&relevantSubcircuitIds.has(e4.subcircuit_id)),board=null;if(subcircuit_id){let source_group_id=subcircuit_id.replace(/^subcircuit_/,""),source_board2=db.source_board.getWhere({source_group_id});source_board2&&(board=db.pcb_board.getWhere({source_board_id:source_board2.source_board_id}))}board||(board=db.pcb_board.list()[0]),db=su2(subcircuitElements);let connMap=getFullConnectivityMapFromCircuitJson(subcircuitElements),obstacles=getObstaclesFromCircuitJson2([...db.pcb_component.list(),...db.pcb_smtpad.list(),...db.pcb_plated_hole.list(),...db.pcb_hole.list(),...db.pcb_via.list(),...db.pcb_cutout.list()].filter(e4=>!subcircuit_id||relevantSubcircuitIds?.has(e4.subcircuit_id)),connMap);for(let obstacle of obstacles){let additionalIds=obstacle.connectedTo.flatMap(id=>connMap.getIdsConnectedToNet(id));obstacle.connectedTo.push(...additionalIds)}let internalConnections=db.source_component_internal_connection.list(),sourcePortIdToInternalConnectionId=new Map;for(let ic2 of internalConnections)for(let sourcePortId of ic2.source_port_ids)sourcePortIdToInternalConnectionId.set(sourcePortId,ic2.source_component_internal_connection_id);let pcbElementIdToSourcePortId=new Map;for(let pcbPort of db.pcb_port.list())if(pcbPort.source_port_id){let smtpad2=db.pcb_smtpad.getWhere({pcb_port_id:pcbPort.pcb_port_id});smtpad2&&pcbElementIdToSourcePortId.set(smtpad2.pcb_smtpad_id,pcbPort.source_port_id);let platedHole=db.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(o3=>[{x:o3.center.x-o3.width/2,y:o3.center.y-o3.height/2},{x:o3.center.x+o3.width/2,y:o3.center.y+o3.height/2}]).concat(board?.outline??[]),bounds;if(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(p4=>p4.x))-1,maxX:Math.max(...allPoints.map(p4=>p4.x))+1,minY:Math.min(...allPoints.map(p4=>p4.y))-1,maxY:Math.max(...allPoints.map(p4=>p4.y))+1},subcircuit_id){let group=db.pcb_group.getWhere({subcircuit_id});if(group?.width&&group.height){let groupBounds={minX:group.center.x-group.width/2,maxX:group.center.x+group.width/2,minY:group.center.y-group.height/2,maxY:group.center.y+group.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 routedTraceIds=new Set(db.pcb_trace.list().map(t5=>t5.source_trace_id).filter(id=>!!id)),directTraceConnections=db.source_trace.list().filter(trace=>!routedTraceIds.has(trace.source_trace_id)).map(trace=>{let connectedPorts=trace.connected_source_port_ids.map(id=>{let source_port2=db.source_port.get(id),pcb_port2=db.pcb_port.getWhere({source_port_id:id});return{...source_port2,...pcb_port2}});if(connectedPorts.length<2)return null;let[portA,portB]=connectedPorts;if(portA.x===void 0||portA.y===void 0)return console.error(`(source_port_id: ${portA.source_port_id}) for trace ${trace.source_trace_id} does not have x/y coordinates. Skipping this trace.`),null;if(portB.x===void 0||portB.y===void 0)return console.error(`(source_port_id: ${portB.source_port_id}) for trace ${trace.source_trace_id} does not have x/y coordinates. Skipping this trace.`),null;let layerA=portA.layers?.[0]??"top",layerB=portB.layers?.[0]??"top",matchingHints=traceHints.filter(hint=>hint.pcb_port_id===portA.pcb_port_id||hint.pcb_port_id===portB.pcb_port_id),hintPoints=[];for(let hint of matchingHints){let layer=db.pcb_port.get(hint.pcb_port_id)?.layers?.[0]??"top";for(let pt4 of hint.route)hintPoints.push({x:pt4.x,y:pt4.y,layer})}return{name:trace.source_trace_id??connMap.getNetConnectedToId(trace.source_trace_id)??"",source_trace_id:trace.source_trace_id,width:trace.min_trace_thickness,pointsToConnect:[{x:portA.x,y:portA.y,layer:layerA,pointId:portA.pcb_port_id,pcb_port_id:portA.pcb_port_id},...hintPoints,{x:portB.x,y:portB.y,layer:layerB,pointId:portB.pcb_port_id,pcb_port_id:portB.pcb_port_id}]}}).filter(c3=>c3!==null),directTraceConnectionsById=new Map(directTraceConnections.map(c3=>[c3.source_trace_id,c3])),source_nets=db.source_net.list().filter(e4=>!subcircuit_id||relevantSubcircuitIds?.has(e4.subcircuit_id)),connectionsFromNets=[];for(let net of source_nets){let connectedSourceTraces=db.source_trace.list().filter(st4=>st4.connected_source_net_ids?.includes(net.source_net_id));connectionsFromNets.push({name:net.source_net_id??connMap.getNetConnectedToId(net.source_net_id),pointsToConnect:connectedSourceTraces.flatMap(st4=>db.pcb_port.list().filter(p4=>st4.connected_source_port_ids.includes(p4.source_port_id)).map(p4=>({x:p4.x,y:p4.y,layer:p4.layers?.[0]??"top",pointId:p4.pcb_port_id,pcb_port_id:p4.pcb_port_id})))})}let breakoutPoints=db.pcb_breakout_point.list().filter(bp2=>!subcircuit_id||relevantSubcircuitIds?.has(bp2.subcircuit_id)),connectionsFromBreakoutPoints=[],breakoutTraceConnectionsById=new Map;for(let bp2 of breakoutPoints){let pt4={x:bp2.x,y:bp2.y,layer:"top"};if(bp2.source_trace_id){let conn=directTraceConnectionsById.get(bp2.source_trace_id)??breakoutTraceConnectionsById.get(bp2.source_trace_id);if(conn)conn.pointsToConnect.push(pt4);else{let newConn={name:bp2.source_trace_id,source_trace_id:bp2.source_trace_id,pointsToConnect:[pt4]};connectionsFromBreakoutPoints.push(newConn),breakoutTraceConnectionsById.set(bp2.source_trace_id,newConn)}}else if(bp2.source_net_id){let conn=connectionsFromNets.find(c3=>c3.name===bp2.source_net_id);conn?conn.pointsToConnect.push(pt4):connectionsFromBreakoutPoints.push({name:bp2.source_net_id,pointsToConnect:[pt4]})}else if(bp2.source_port_id){let pcb_port2=db.pcb_port.getWhere({source_port_id:bp2.source_port_id});pcb_port2&&connectionsFromBreakoutPoints.push({name:bp2.source_port_id,source_trace_id:void 0,pointsToConnect:[{x:pcb_port2.x,y:pcb_port2.y,layer:pcb_port2.layers?.[0]??"top",pointId:pcb_port2.pcb_port_id,pcb_port_id:pcb_port2.pcb_port_id},pt4]})}}let allConns=[...directTraceConnections,...connectionsFromNets,...connectionsFromBreakoutPoints],pointIdToConn=new Map;for(let conn of allConns)for(let pt4 of conn.pointsToConnect)pt4.pointId&&pointIdToConn.set(pt4.pointId,conn);let existingTraces=db.pcb_trace.list().filter(t5=>!subcircuit_id||relevantSubcircuitIds?.has(t5.subcircuit_id));for(let tr4 of existingTraces){let tracePortIds=new Set;for(let seg of tr4.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]))}return{simpleRouteJson:{bounds,obstacles,connections:allConns,layerCount:board?.num_layers??2,minTraceWidth,nominalTraceWidth,outline:board?.outline?.map(point6=>({...point6}))},connMap}},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 i2=0;i2<unqInputPinLabels.length;i2++)for(let label of unqInputPinLabels[i2])if(/^\d+$/.test(label)){desiredNumbers[i2]=Number.parseInt(label);break}let highestPinNumber=0,alreadyAcceptedDesiredNumbers=new Set;for(let i2=0;i2<desiredNumbers.length;i2++){let desiredNumber=desiredNumbers[i2];if(desiredNumber===null||desiredNumber<1)continue;if(!alreadyAcceptedDesiredNumbers.has(desiredNumber)){alreadyAcceptedDesiredNumbers.add(desiredNumber),result[i2].push(`pin${desiredNumber}`),highestPinNumber=Math.max(highestPinNumber,desiredNumber);continue}let existingAltsForPin=0;for(let label of result[i2])label.startsWith(`pin${desiredNumber}_alt`)&&existingAltsForPin++;result[i2].push(`pin${desiredNumber}_alt${existingAltsForPin+1}`)}for(let i2=0;i2<result.length;i2++)result[i2][0]?.includes("_alt")&&(highestPinNumber++,result[i2].unshift(`pin${highestPinNumber}`));for(let i2=0;i2<result.length;i2++)result[i2].length===0&&(highestPinNumber++,result[i2].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 i2=0;i2<unqInputPinLabels.length;i2++){let inputLabels=unqInputPinLabels[i2];for(let label of inputLabels)/^\d+$/.test(label)||(totalLabelCounts[label]===1?result[i2].push(label):(incrementalLabelCounts[label]=(incrementalLabelCounts[label]??0)+1,result[i2].push(`${label}${incrementalLabelCounts[label]}`)))}return result};function updateSchematicPrimitivesForLayoutShift({db,schematicComponentId,deltaX,deltaY}){let rects=db.schematic_rect.list({schematic_component_id:schematicComponentId});for(let rect of rects)rect.center.x+=deltaX,rect.center.y+=deltaY;let lines=db.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=db.schematic_circle.list({schematic_component_id:schematicComponentId});for(let circle2 of circles)circle2.center.x+=deltaX,circle2.center.y+=deltaY;let arcs=db.schematic_arc.list({schematic_component_id:schematicComponentId});for(let arc2 of arcs)arc2.center.x+=deltaX,arc2.center.y+=deltaY}var debug42=(0,import_debug11.default)("Group_doInitialSchematicLayoutMatchAdapt");function Group_doInitialSchematicLayoutMatchAdapt(group){let{db}=group.root,subtreeCircuitJson=buildSubtree(db.toArray(),{source_group_id:group.source_group_id}),bpcGraphBeforeGeneratedNetLabels=convertCircuitJsonToBpc(subtreeCircuitJson);debug42.enabled&&global?.debugGraphics&&global.debugGraphics?.push(getGraphicsForBpcGraph(bpcGraphBeforeGeneratedNetLabels,{title:`floatingBpcGraph-${group.name}`}));let floatingGraph=convertCircuitJsonToBpc(subtreeCircuitJson),floatingGraphNoNotConnected={boxes:floatingGraph.boxes,pins:floatingGraph.pins.map(p4=>({...p4,color:p4.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(p4=>p4.boxId===box2.boxId).filter(bp2=>!bp2.color.includes("center")).length<=2).map(b3=>b3.boxId)),corpus:{}});debug42.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_component2=db.schematic_component.get(box2.boxId);if(schematic_component2){let newCenter={x:box2.center.x+groupOffset.x,y:box2.center.y+groupOffset.y},ports=db.schematic_port.list({schematic_component_id:schematic_component2.schematic_component_id}),texts=db.schematic_text.list({schematic_component_id:schematic_component2.schematic_component_id}),positionDelta={x:newCenter.x-schematic_component2.center.x,y:newCenter.y-schematic_component2.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,schematicComponentId:schematic_component2.schematic_component_id,deltaX:positionDelta.x,deltaY:positionDelta.y}),schematic_component2.center=newCenter;continue}let schematic_net_label2=db.schematic_net_label.get(box2.boxId);if(schematic_net_label2){let pin=laidOutBpcGraph.pins.find(p4=>p4.boxId===box2.boxId&&p4.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_label2.center=finalCenter,schematic_net_label2.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`)}}var debug52=(0,import_debug12.default)("Group_doInitialSchematicLayoutMatchpack");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 rotateDirection2(direction2,degrees){let directions=["right","up","left","down"],currentIndex=directions.indexOf(direction2);if(currentIndex===-1)return direction2;let steps=Math.round(degrees/90),newIndex=(currentIndex+steps)%4;return directions[newIndex<0?newIndex+4:newIndex]}function convertTreeToInputProblem(tree,db,group){let problem={chipMap:{},chipPinMap:{},netMap:{},pinStrongConnMap:{},netConnMap:{},chipGap:.6,decouplingCapsGap:.4,partitionGap:1.2};debug52(`[${group.name}] Processing ${tree.childNodes.length} child nodes for input problem`),tree.childNodes.forEach((child,index)=>{if(debug52(`[${group.name}] Processing child ${index}: nodeType=${child.nodeType}`),child.nodeType==="component"?debug52(`[${group.name}] - Component: ${child.sourceComponent?.name}`):child.nodeType==="group"&&debug52(`[${group.name}] - Group: ${child.sourceGroup?.name}`),child.nodeType==="component"&&child.sourceComponent){let chipId=child.sourceComponent.name||`chip_${index}`,schematicComponent=db.schematic_component.getWhere({source_component_id:child.sourceComponent.source_component_id});if(!schematicComponent)return;let component=group.children.find(groupChild=>groupChild.source_component_id===child.sourceComponent?.source_component_id),availableRotations=[0,90,180,270];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]);let marginLeft=component?._parsedProps?.schMarginLeft??component?._parsedProps?.schMarginX??0,marginRight=component?._parsedProps?.schMarginRight??component?._parsedProps?.schMarginX??0,marginTop=component?._parsedProps?.schMarginTop??component?._parsedProps?.schMarginY??0,marginBottom=component?._parsedProps?.schMarginBottom??component?._parsedProps?.schMarginY??0;component?.config.shouldRenderAsSchematicBox&&(marginTop+=.4,marginBottom+=.4);let marginXShift=(marginRight-marginLeft)/2,marginYShift=(marginTop-marginBottom)/2;problem.chipMap[chipId]={chipId,pins:[],size:{x:(schematicComponent.size?.width||1)+marginLeft+marginRight,y:(schematicComponent.size?.height||1)+marginTop+marginBottom},availableRotations};let ports=db.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id});for(let port of ports){let sourcePort=db.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)+marginXShift,y:(port.center?.y||0)-(schematicComponent.center.y||0)+marginYShift},side}}}else if(child.nodeType==="group"&&child.sourceGroup){let groupId=child.sourceGroup.name||`group_${index}`;debug52(`[${group.name}] Processing nested group: ${groupId}`);let schematicGroup=db.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(debug52(`[${group.name}] Found schematic_group for ${groupId}:`,schematicGroup),schematicGroup){debug52(`[${group.name}] Treating group ${groupId} as composite chip`);let groupComponents=db.schematic_component.list({schematic_group_id:schematicGroup.schematic_group_id});debug52(`[${group.name}] Group ${groupId} has ${groupComponents.length} components:`,groupComponents.map(c3=>c3.source_component_id));let minX=1/0,maxX=-1/0,minY=1/0,maxY=-1/0,hasValidBounds=!1;for(let comp of groupComponents)if(comp.center&&comp.size){hasValidBounds=!0;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 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,marginXShift=(marginRight-marginLeft)/2,marginYShift=(marginTop-marginBottom)/2,groupWidth=(hasValidBounds?maxX-minX:2)+marginLeft+marginRight,groupHeight=(hasValidBounds?maxY-minY:2)+marginTop+marginBottom;debug52(`[${group.name}] Group ${groupId} computed size: ${groupWidth} x ${groupHeight}`);let groupPins=[];for(let comp of groupComponents){let ports=db.schematic_port.list({schematic_component_id:comp.schematic_component_id});for(let port of ports){let sourcePort=db.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 groupCenter=schematicGroup.center||{x:0,y:0},side=facingDirectionToSide(port.facing_direction);problem.chipPinMap[pinId]={pinId,offset:{x:(port.center?.x||0)-groupCenter.x+marginXShift,y:(port.center?.y||0)-groupCenter.y+marginYShift},side}}}debug52(`[${group.name}] Group ${groupId} has ${groupPins.length} pins:`,groupPins),problem.chipMap[groupId]={chipId:groupId,pins:groupPins,size:{x:groupWidth,y:groupHeight}},debug52(`[${group.name}] Added group ${groupId} to chipMap`)}else debug52(`[${group.name}] Warning: No schematic_group found for group ${groupId}`)}}),debug52(`[${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=>child.nodeType==="component"&&child.sourceComponent?child.sourceComponent.name===chipId:child.nodeType==="group"&&child.sourceGroup?`group_${tree.childNodes.indexOf(child)}`===chipId:!1);if(treeNode?.nodeType==="group"&&treeNode.sourceGroup){let schematicGroup=db.schematic_group?.getWhere?.({source_group_id:treeNode.sourceGroup.source_group_id});if(schematicGroup){let groupComponents=db.schematic_component.list({schematic_group_id:schematicGroup.schematic_group_id});for(let comp of groupComponents){let sourcePorts=db.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),debug52(`[${group.name}] \u2713 Pin ${pinId} has connectivity key: ${connectivityKey}`)}else debug52(`[${group.name}] Pin ${pinId} has no connectivity key`)}}}}else if(treeNode?.nodeType==="component"&&treeNode.sourceComponent){let sourcePorts=db.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),debug52(`[${group.name}] Pin ${pinId} has connectivity key: ${connectivityKey}`)}}}}debug52(`[${group.name}] Found ${connectivityGroups.size} connectivity groups:`,Array.from(connectivityGroups.entries()).map(([key,pins])=>({key,pins})));for(let[connectivityKey,pins]of connectivityGroups)if(pins.length>=2){let tracesWithThisKey=db.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(debug52(`[${group.name}] Connectivity ${connectivityKey}: hasNetConnections=${hasNetConnections}, hasDirectConnections=${hasDirectConnections}`),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=db.source_port.get(portId);if(sourcePort&&String(sourcePort.pin_number||sourcePort.name)===String(pinNumber)){let chipId=pinId.split(".")[0],treeNode=tree.childNodes.find(child=>child.nodeType==="component"&&child.sourceComponent?child.sourceComponent.name===chipId:child.nodeType==="group"&&child.sourceGroup?`group_${tree.childNodes.indexOf(child)}`===chipId:!1);treeNode?.nodeType==="component"&&treeNode.sourceComponent&&db.source_port.list({source_component_id:treeNode.sourceComponent.source_component_id}).some(p4=>p4.source_port_id===portId)&&directlyConnectedPins.push(pinId)}}for(let i2=0;i2<directlyConnectedPins.length;i2++)for(let j4=i2+1;j4<directlyConnectedPins.length;j4++){let pin1=directlyConnectedPins[i2],pin2=directlyConnectedPins[j4];problem.pinStrongConnMap[`${pin1}-${pin2}`]=!0,problem.pinStrongConnMap[`${pin2}-${pin1}`]=!0,debug52(`[${group.name}] Created strong connection: ${pin1} <-> ${pin2}`)}}}if(hasNetConnections){let source_net2=db.source_net.getWhere({subcircuit_connectivity_map_key:connectivityKey}),isGround=source_net2?.is_ground??!1,isPositiveVoltageSource=source_net2?.is_power??!1;problem.netMap[connectivityKey]={netId:connectivityKey,isGround,isPositiveVoltageSource};for(let pinId of pins)problem.netConnMap[`${pinId}-${connectivityKey}`]=!0;debug52(`[${group.name}] Created net ${connectivityKey} with ${pins.length} pins:`,pins)}}return problem}function Group_doInitialSchematicLayoutMatchPack(group){let{db}=group.root,tree=getCircuitJsonTree(db.toArray(),{source_group_id:group.source_group_id});if(debug52(`[${group.name}] Starting matchpack layout with ${tree.childNodes.length} children`),debug52(`[${group.name}] Tree structure:`,JSON.stringify(tree,null,2)),tree.childNodes.length<=1){debug52(`[${group.name}] Only ${tree.childNodes.length} children, skipping layout`);return}debug52("Converting circuit tree to InputProblem...");let inputProblem=convertTreeToInputProblem(tree,db,group);debug52.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(debug52("Starting LayoutPipelineSolver..."),debug52.enabled&&global?.debugGraphics){let initialViz=solver.visualize();global.debugGraphics.push({...initialViz,title:`matchpack-initial-${group.name}`})}if(solver.solve(),debug52(`Solver completed in ${solver.iterations} iterations`),debug52(`Solved: ${solver.solved}, Failed: ${solver.failed}`),solver.failed)throw debug52(`Solver failed with error: ${solver.error}`),new Error(`Matchpack layout solver failed: ${solver.error}`);let outputLayout=solver.getOutputLayout();if(debug52("OutputLayout:",JSON.stringify(outputLayout,null,2)),debug52("Solver completed successfully:",!solver.failed),debug52.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){debug52(`Warning: Found ${overlaps.length} overlapping components:`);for(let overlap of overlaps)debug52(` ${overlap.chip1} overlaps ${overlap.chip2} (area: ${overlap.overlapArea})`)}let groupOffset=group._getGlobalSchematicPositionBeforeLayout();debug52(`Group offset: x=${groupOffset.x}, y=${groupOffset.y}`),debug52(`Applying layout results for ${Object.keys(outputLayout.chipPlacements).length} chip placements`);for(let[chipId,placement]of Object.entries(outputLayout.chipPlacements)){debug52(`Processing placement for chip: ${chipId} at (${placement.x}, ${placement.y})`);let treeNode=tree.childNodes.find(child=>{if(child.nodeType==="component"&&child.sourceComponent){let matches=child.sourceComponent.name===chipId;return debug52(` Checking component ${child.sourceComponent.name}: matches=${matches}`),matches}if(child.nodeType==="group"&&child.sourceGroup){let groupName=child.sourceGroup.name,expectedChipId=`group_${tree.childNodes.indexOf(child)}`,matches=expectedChipId===chipId;return debug52(` Checking group ${groupName} (expected chipId: ${expectedChipId}): matches=${matches}`),matches}return!1});if(!treeNode){debug52(`Warning: No tree node found for chip: ${chipId}`),debug52("Available tree nodes:",tree.childNodes.map((child,idx)=>({type:child.nodeType,name:child.nodeType==="component"?child.sourceComponent?.name:child.sourceGroup?.name,expectedChipId:child.nodeType==="group"?`group_${idx}`:child.sourceComponent?.name})));continue}let newCenter={x:placement.x+groupOffset.x,y:placement.y+groupOffset.y};if(treeNode.nodeType==="component"&&treeNode.sourceComponent){let schematicComponent=db.schematic_component.getWhere({source_component_id:treeNode.sourceComponent.source_component_id});if(schematicComponent){debug52(`Moving component ${chipId} to (${newCenter.x}, ${newCenter.y})`);let ports=db.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id}),texts=db.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,schematicComponentId:schematicComponent.schematic_component_id,deltaX:positionDelta.x,deltaY:positionDelta.y}),schematicComponent.center=newCenter,placement.ccwRotationDegrees!==0){debug52(`Component ${chipId} has rotation: ${placement.ccwRotationDegrees}\xB0`);let angleRad=placement.ccwRotationDegrees*Math.PI/180,cos4=Math.cos(angleRad),sin4=Math.sin(angleRad);for(let port of ports){let dx2=port.center.x-newCenter.x,dy2=port.center.y-newCenter.y,rotatedDx=dx2*cos4-dy2*sin4,rotatedDy=dx2*sin4+dy2*cos4;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 dx2=text.position.x-newCenter.x,dy2=text.position.y-newCenter.y,rotatedDx=dx2*cos4-dy2*sin4,rotatedDy=dx2*sin4+dy2*cos4;text.position.x=newCenter.x+rotatedDx,text.position.y=newCenter.y+rotatedDy}if(schematicComponent.symbol_name){let schematicSymbolDirection=schematicComponent.symbol_name.match(/_(right|left|up|down)$/);schematicSymbolDirection&&(schematicComponent.symbol_name=schematicComponent.symbol_name.replace(schematicSymbolDirection[0],`_${rotateDirection2(schematicSymbolDirection[1],placement.ccwRotationDegrees)}`))}}}}else if(treeNode.nodeType==="group"&&treeNode.sourceGroup){let schematicGroup=db.schematic_group?.getWhere?.({source_group_id:treeNode.sourceGroup.source_group_id});if(schematicGroup){debug52(`Moving group ${chipId} to (${newCenter.x}, ${newCenter.y}) from (${schematicGroup.center?.x}, ${schematicGroup.center?.y})`);let groupComponents=db.schematic_component.list({schematic_group_id:schematicGroup.schematic_group_id});debug52(`Group ${chipId} has ${groupComponents.length} components to move`);let oldCenter=schematicGroup.center||{x:0,y:0},positionDelta={x:newCenter.x-oldCenter.x,y:newCenter.y-oldCenter.y};debug52(`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,debug52(`Moved component ${component.source_component_id} from (${oldComponentCenter.x}, ${oldComponentCenter.y}) to (${component.center.x}, ${component.center.y})`);let ports=db.schematic_port.list({schematic_component_id:component.schematic_component_id}),texts=db.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)}schematicGroup.center=newCenter,debug52(`Updated group ${chipId} center to (${newCenter.x}, ${newCenter.y})`)}}}debug52("Matchpack layout completed successfully")}function Group_doInitialSourceAddConnectivityMapKey(group){if(!group.isSubcircuit)return;let{db}=group.root,traces=group.selectAll("trace"),vias=group.selectAll("via"),nets=group.selectAll("net"),connMap=new ConnectivityMap({});connMap.addConnections(traces.map(t5=>{let source_trace2=db.source_trace.get(t5.source_trace_id);return source_trace2?[source_trace2.source_trace_id,...source_trace2.connected_source_port_ids,...source_trace2.connected_source_net_ids]:null}).filter(c3=>c3!==null));let sourceNets=db.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._renderId}`}_${connNetId}`,db.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_trace2=db.source_trace.get(trace.source_trace_id);if(source_trace2)for(let id of source_trace2.connected_source_port_ids)allSourcePortIds.add(id)}for(let portId of allSourcePortIds){let connNetId=connMap.getNetConnectedToId(portId);if(!connNetId)continue;let connectivityMapKey=`${subcircuitName??`unnamedsubcircuit${group._renderId}`}_${connNetId}`;db.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_trace2=db.source_trace.get(trace.source_trace_id);if(source_trace2)for(let source_net_id of source_trace2.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._renderId}`}_${connNetId}`;db.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)}}function Group_doInitialSchematicLayoutGrid(group){let{db}=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=db.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 i2=0;i2<schematicChildren.length;i2++){let child=schematicChildren[i2];if(!child.schematic_component_id)continue;let row=Math.floor(i2/numCols),col=i2%numCols;if(row>=numRows||col>=numCols){console.warn(`Schematic grid layout: Child ${child.getString()} at index ${i2} (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=db.schematic_component.get(child.schematic_component_id);if(schComp){let oldChildCenter=schComp.center,newChildCenter={x:targetCellCenterX,y:targetCellCenterY};db.schematic_component.update(child.schematic_component_id,{center:newChildCenter});let deltaX=newChildCenter.x-oldChildCenter.x,deltaY=newChildCenter.y-oldChildCenter.y,schPorts=db.schematic_port.list({schematic_component_id:child.schematic_component_id});for(let port of schPorts)db.schematic_port.update(port.schematic_port_id,{center:{x:port.center.x+deltaX,y:port.center.y+deltaY}});let schTexts=db.schematic_text.list({schematic_component_id:child.schematic_component_id});for(let text of schTexts)db.schematic_text.update(text.schematic_text_id,{position:{x:text.position.x+deltaX,y:text.position.y+deltaY}});updateSchematicPrimitivesForLayoutShift({db,schematicComponentId:child.schematic_component_id,deltaX,deltaY})}}group.schematic_group_id&&db.schematic_group.update(group.schematic_group_id,{width:totalGridWidth,height:totalGridHeight,center:groupCenter})}var getSizeOfTreeNodeChild=(db,child)=>{let{sourceComponent,sourceGroup}=child;if(child.nodeType==="component"){let schComponent=db.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=db.schematic_group.getWhere({source_group_id:sourceGroup?.source_group_id});if(schGroup?.width&&schGroup?.height)return{width:schGroup.width,height:schGroup.height};let groupComponents=db.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}=group.root,props=group._parsedProps,tree=getCircuitJsonTree(db.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(db,child)).filter(size2=>size2!==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 size2=getSizeOfTreeNodeChild(db,child);flexBox.addChild({metadata:child,width:size2?.width??0,height:size2?.height??0,flexBasis:size2?direction2==="row"?size2.width:size2.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=db.toArray();for(let child of flexBox.children){let{sourceComponent,sourceGroup}=child.metadata;if(sourceComponent){let schComponent=db.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(!db.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&&db.schematic_group.update(group.schematic_group_id,{width:bounds.width,height:bounds.height})},MIN_GAP=1;function Group_doInitialPcbLayoutGrid(group){let{db}=group.root,props=group._parsedProps,pcbChildren=getPcbChildren(group);if(pcbChildren.length===0)return;let childDimensions=calculateChildDimensions({db,pcbChildren}),gridConfig=parseGridConfiguration(props),gridLayout=createGridLayout({props,pcbChildren,childDimensions,gridConfig}),cssGrid=createCssGrid({pcbChildren,childDimensions,gridLayout,gridConfig}),{itemCoordinates}=cssGrid.layout();positionChildren({db,group,pcbChildren,itemCoordinates,gridLayout}),updateGroupDimensions({db,group,props,gridLayout})}function getPcbChildren(group){return group.children.filter(child=>child.pcb_component_id||child.pcb_group_id)}function calculateChildDimensions(params){let{db,pcbChildren}=params,maxWidth=0,maxHeight=0;for(let child of pcbChildren){let width=0,height=0;if(child.pcb_group_id){let pcbGroup=db.pcb_group.get(child.pcb_group_id);width=pcbGroup?.width??0,height=pcbGroup?.height??0}else if(child.pcb_component_id){let pcbComp=db.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,group,pcbChildren,itemCoordinates,gridLayout}=params,groupCenter=group._getGlobalPcbPositionBeforeLayout(),allCircuitJson=db.toArray();for(let i2=0;i2<pcbChildren.length;i2++){let child=pcbChildren[i2],childKey=child.getString()||`child-${i2}`,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,group,props,gridLayout}=params;if(group.pcb_group_id){let groupCenter=group._getGlobalPcbPositionBeforeLayout();db.pcb_group.update(group.pcb_group_id,{width:props.width??gridLayout.containerWidth,height:props.height??gridLayout.containerHeight,center:groupCenter})}}function getPresetAutoroutingConfig(autorouterConfig2){let defaults={serverUrl:"https://registry-api.tscircuit.com",serverMode:"job",serverCacheEnabled:!0};if(typeof autorouterConfig2=="object"&&!autorouterConfig2.preset)return{local:!(autorouterConfig2.serverUrl||autorouterConfig2.serverMode||autorouterConfig2.serverCacheEnabled),...defaults,...autorouterConfig2};let preset=typeof autorouterConfig2=="object"?autorouterConfig2.preset:autorouterConfig2,providedConfig=typeof autorouterConfig2=="object"?autorouterConfig2:{};switch(typeof preset=="string"?preset.replace(/_/g,"-"):preset){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"auto-cloud":{let{preset:_preset,local:_local,groupMode:_groupMode,...rest}=providedConfig;return{local:!1,groupMode:"subcircuit",...defaults,...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 applyComponentConstraintClusters=(group,packInput)=>{let constraints=group.children.filter(c3=>c3.componentName==="Constraint"&&c3._parsedProps.pcb),clusterByRoot=new Map,parent={},find2=x5=>(parent[x5]!==x5&&(parent[x5]=find2(parent[x5])),parent[x5]),union2=(a2,b3)=>{let ra3=find2(a2),rb=find2(b3);ra3!==rb&&(parent[rb]=ra3)},makeSet=x5=>{x5 in parent||(parent[x5]=x5)},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 a2=getIdFromSelector(props.left),b3=getIdFromSelector(props.right);a2&&b3&&(makeSet(a2),makeSet(b3),union2(a2,b3))}else if("top"in props&&"bottom"in props){let a2=getIdFromSelector(props.top),b3=getIdFromSelector(props.bottom);a2&&b3&&(makeSet(a2),makeSet(b3),union2(a2,b3))}else if("for"in props&&Array.isArray(props.for)){let ids=props.for.map(s2=>getIdFromSelector(s2)).filter(s2=>!!s2);for(let id of ids)makeSet(id);for(let i2=1;i2<ids.length;i2++)union2(ids[0],ids[i2])}}for(let id of Object.keys(parent)){let rootId=find2(id);clusterByRoot.has(rootId)||clusterByRoot.set(rootId,{componentIds:[],constraints:[]}),clusterByRoot.get(rootId).componentIds.push(id)}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=(id,axis)=>{let key=`${id}_${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(s2=>getIdFromSelector(s2)).filter(s2=>!!s2);if(ids.length>1){let base=getVar(ids[0],"x");for(let i2=1;i2<ids.length;i2++)solver.addConstraint(new Constraint(new Expression(getVar(ids[i2],"x"),[-1,base]),Operator.Eq,0,Strength.required))}}else if("sameY"in props&&Array.isArray(props.for)){let ids=props.for.map(s2=>getIdFromSelector(s2)).filter(s2=>!!s2);if(ids.length>1){let base=getVar(ids[0],"y");for(let i2=1;i2<ids.length;i2++)solver.addConstraint(new Constraint(new Expression(getVar(ids[i2],"y"),[-1,base]),Operator.Eq,0,Strength.required))}}}solver.updateVariables();let positions={};for(let id of info.componentIds)positions[id]={x:getVar(id,"x").value(),y:getVar(id,"y").value()};let minX=1/0,minY=1/0,maxX=-1/0,maxY=-1/0;for(let id of info.componentIds){let comp=packCompById[id],pos=positions[id];if(comp)for(let pad2 of comp.pads){let ax2=pos.x+pad2.offset.x,ay2=pos.y+pad2.offset.y;minX=Math.min(minX,ax2-pad2.size.x/2),maxX=Math.max(maxX,ax2+pad2.size.x/2),minY=Math.min(minY,ay2-pad2.size.y/2),maxY=Math.max(maxY,ay2+pad2.size.y/2)}}let clusterCenter={x:(minX+maxX)/2,y:(minY+maxY)/2},mergedPads=[],relCenters={};for(let id of info.componentIds){let comp=packCompById[id],pos=positions[id];if(comp){relCenters[id]={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,pcbComponentId,rotationDegrees,layer})=>{if(rotationDegrees==null||!db?.cad_component?.list)return;let cadComponent=db.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)};db.cad_component.update(cadComponent.cad_component_id,{rotation:nextRotation}),cadComponent.rotation=nextRotation},isDescendantGroup=(db,groupId,ancestorId)=>{if(groupId===ancestorId)return!0;let group=db.source_group.get(groupId);return!group||!group.parent_source_group_id?!1:isDescendantGroup(db,group.parent_source_group_id,ancestorId)},applyPackOutput=(group,packOutput,clusterMap)=>{let{db}=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;db.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=db.pcb_component.get(memberId);if(!member)continue;let originalCenter2=member.center,transformMatrix2=compose(group._computePcbGlobalTransformBeforeLayout(),translate(center2.x+rotatedRel.x,center2.y+rotatedRel.y),rotate(angleRad),translate(-originalCenter2.x,-originalCenter2.y)),related=db.toArray().filter(elm=>"pcb_component_id"in elm&&elm.pcb_component_id===memberId);transformPCBElements(related,transformMatrix2),updateCadRotation({db,pcbComponentId:memberId,rotationDegrees:rotationDegrees2,layer:member.layer})}continue}let pcbComponent=db.pcb_component.get(componentId);if(pcbComponent){db.pcb_component.update(componentId,{position_mode:"packed"});let currentGroupId=group.source_group_id,componentGroupId=db.source_component.get(pcbComponent.source_component_id)?.source_group_id;if(componentGroupId!==void 0&&!isDescendantGroup(db,componentGroupId,currentGroupId))continue;let originalCenter2=pcbComponent.center,rotationDegrees2=ccwRotationDegrees??ccwRotationOffset??0,transformMatrix2=compose(group._computePcbGlobalTransformBeforeLayout(),translate(center2.x,center2.y),rotate(rotationDegrees2*Math.PI/180),translate(-originalCenter2.x,-originalCenter2.y)),related=db.toArray().filter(elm=>"pcb_component_id"in elm&&elm.pcb_component_id===componentId);transformPCBElements(related,transformMatrix2),updateCadRotation({db,pcbComponentId:componentId,rotationDegrees:rotationDegrees2,layer:pcbComponent.layer});continue}let pcbGroup=db.pcb_group.list().find(g7=>g7.source_group_id===componentId);if(!pcbGroup)continue;let originalCenter=pcbGroup.center,rotationDegrees=ccwRotationDegrees??ccwRotationOffset??0,transformMatrix=compose(group._computePcbGlobalTransformBeforeLayout(),translate(center2.x,center2.y),rotate(rotationDegrees*Math.PI/180),translate(-originalCenter.x,-originalCenter.y)),relatedElements=db.toArray().filter(elm=>{if("source_group_id"in elm&&elm.source_group_id&&(elm.source_group_id===componentId||isDescendantGroup(db,elm.source_group_id,componentId)))return!0;if("source_component_id"in elm&&elm.source_component_id){let sourceComponent=db.source_component.get(elm.source_component_id);if(sourceComponent?.source_group_id&&(sourceComponent.source_group_id===componentId||isDescendantGroup(db,sourceComponent.source_group_id,componentId)))return!0}if("pcb_component_id"in elm&&elm.pcb_component_id){let pcbComp=db.pcb_component.get(elm.pcb_component_id);if(pcbComp?.source_component_id){let sourceComp=db.source_component.get(pcbComp.source_component_id);if(sourceComp?.source_group_id&&(sourceComp.source_group_id===componentId||isDescendantGroup(db,sourceComp.source_group_id,componentId)))return!0}}return!1});for(let elm of relatedElements)elm.type==="pcb_component"&&db.pcb_component.update(elm.pcb_component_id,{position_mode:"packed"});transformPCBElements(relatedElements,transformMatrix),db.pcb_group.update(pcbGroup.pcb_group_id,{center:center2})}},DEFAULT_MIN_GAP="1mm",debug6=(0,import_debug13.default)("Group_doInitialPcbLayoutPack"),Group_doInitialPcbLayoutPack=group=>{let{db}=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=(db2,groupId,ancestorId)=>{if(groupId===ancestorId)return!0;let group2=db2.source_group.get(groupId);return!group2||!group2.parent_source_group_id?!1:isDescendantGroup2(db2,group2.parent_source_group_id,ancestorId)};if(excludedPcbGroupIds.size>0)for(let element of db.toArray()){if(element.type!=="pcb_component")continue;let sourceComponent=db.source_component.get(element.source_component_id);if(sourceComponent?.source_group_id)for(let groupId of excludedPcbGroupIds)isDescendantGroup2(db,sourceComponent.source_group_id,groupId)&&staticPcbComponentIds.add(element.pcb_component_id)}let filteredCircuitJson=db.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 packInput={...convertPackOutputToPackInput(convertCircuitJsonToPackOutput(filteredCircuitJson,{source_group_id:group.source_group_id,chipMarginsMap,staticPcbComponentIds:Array.from(staticPcbComponentIds)})),orderStrategy:packOrderStrategy??"largest_to_smallest",placementStrategy:packPlacementStrategy??"minimum_sum_squared_distance_to_network",minGap:gapMm,bounds},clusterMap=applyComponentConstraintClusters(group,packInput);debug6.enabled&&(group.root?.emit("debug:logOutput",{type:"debug:logOutput",name:`packInput-circuitjson-${group.name}`,content:JSON.stringify(db.toArray())}),group.root?.emit("debug:logOutput",{type:"debug:logOutput",name:`packInput-${group.name}`,content:packInput}));let packOutput;try{let solver=new PackSolver2(packInput);group.root?.emit("solver:started",{type:"solver:started",solverName:"PackSolver2",solverParams:solver.getConstructorParams(),componentName:group.getString()}),solver.solve(),packOutput={...packInput,components:solver.packedComponents}}catch(error){throw group.root?.emit("packing:error",{subcircuit_id:group.subcircuit_id,componentDisplayName:group.getString(),error:{message:error instanceof Error?error.message:String(error)}}),error}if(debug6.enabled&&global?.debugGraphics){let graphics=getGraphicsFromPackOutput(packOutput);graphics.title=`packOutput-${group.name}`,global.debugGraphics?.push(graphics)}applyPackOutput(group,packOutput,clusterMap),group.root?.emit("packing:end",{subcircuit_id:group.subcircuit_id,componentDisplayName:group.getString()})},Group_doInitialPcbLayoutFlex=group=>{let{db}=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(size2=>size2!==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 size2=child._getMinimumFlexContainerSize();flexBox.addChild({metadata:child,width:size2?.width??0,height:size2?.height??0,flexBasis:size2?direction2==="row"?size2.width:size2.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});db.pcb_group.update(group.pcb_group_id,{width:bounds.width,height:bounds.height,center:groupCenter})},createSourceTracesFromOffboardConnections=({db,connectedOffboardObstacles,simpleRouteJson,subcircuit_id})=>{if(Object.keys(connectedOffboardObstacles).length===0)return;let pcbElementIdToSourcePortId=new Map;for(let pcbPort of db.pcb_port.list())if(pcbPort.source_port_id){let smtpad2=db.pcb_smtpad.getWhere({pcb_port_id:pcbPort.pcb_port_id});smtpad2&&pcbElementIdToSourcePortId.set(smtpad2.pcb_smtpad_id,pcbPort.source_port_id);let platedHole=db.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);db.source_trace.list().some(trace=>{let tracePortIds=new Set(trace.connected_source_port_ids);return sourcePortIdArray.every(id=>tracePortIds.has(id))})||db.source_trace.insert({connected_source_port_ids:sourcePortIdArray,connected_source_net_ids:[],subcircuit_id:subcircuit_id??void 0,display_name:`offboard_${rootConnectionName}`})}};function createSchematicTraceSolverInputProblem(group){let{db}=group.root,sckToSourceNet=new Map,sckToUserNetId=new Map,allScks=new Set,displayLabelTraces=group.selectAll("trace").filter(t5=>t5._parsedProps?.schDisplayLabel),childGroups=group.selectAll("group"),allSchematicGroupIds=[group.schematic_group_id,...childGroups.map(a2=>a2.schematic_group_id)],schematicComponents=db.schematic_component.list().filter(a2=>allSchematicGroupIds.includes(a2.schematic_group_id)),chips=[],pinIdToSchematicPortId=new Map,schematicPortIdToPinId=new Map;for(let schematicComponent of schematicComponents){let chipId=schematicComponent.schematic_component_id,pins=[],sourceComponent=db.source_component.getWhere({source_component_id:schematicComponent.source_component_id}),schematicPorts=db.schematic_port.list({schematic_component_id:schematicComponent.schematic_component_id});for(let schematicPort of schematicPorts){let pinId=`${sourceComponent?.name??schematicComponent.schematic_component_id}.${schematicPort.pin_number}`;pinIdToSchematicPortId.set(pinId,schematicPort.schematic_port_id),schematicPortIdToPinId.set(schematicPort.schematic_port_id,pinId)}for(let schematicPort of schematicPorts){let pinId=schematicPortIdToPinId.get(schematicPort.schematic_port_id);pins.push({pinId,x:schematicPort.center.x,y:schematicPort.center.y})}chips.push({chipId,center:schematicComponent.center,width:schematicComponent.size.width,height:schematicComponent.size.height,pins})}let allSourceAndSchematicPortIdsInScope=new Set,schPortIdToSourcePortId=new Map,sourcePortIdToSchPortId=new Map,userNetIdToSck=new Map;for(let sc of schematicComponents){let ports=db.schematic_port.list({schematic_component_id:sc.schematic_component_id});for(let sp2 of ports)allSourceAndSchematicPortIdsInScope.add(sp2.schematic_port_id),sp2.source_port_id&&(schPortIdToSourcePortId.set(sp2.schematic_port_id,sp2.source_port_id),sourcePortIdToSchPortId.set(sp2.source_port_id,sp2.schematic_port_id))}let 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 externalNetIds=db.source_trace.list().filter(st4=>{if(st4.subcircuit_id===group.subcircuit_id)return!0;for(let source_port_id of st4.connected_source_port_ids)if(sourcePortIdToSchPortId.has(source_port_id))return!0;return!1}).flatMap(st4=>st4.connected_source_net_ids);for(let netId of externalNetIds){let net=db.source_net.get(netId);net?.subcircuit_id&&allowedSubcircuitIds.add(net.subcircuit_id)}let directConnections=[],pairKeyToSourceTraceId=new Map;for(let st4 of db.source_trace.list()){if(st4.subcircuit_id&&!allowedSubcircuitIds.has(st4.subcircuit_id))continue;let connected=(st4.connected_source_port_ids??[]).map(srcId=>sourcePortIdToSchPortId.get(srcId)).filter(sourcePortId=>!!sourcePortId&&allSourceAndSchematicPortIdsInScope.has(sourcePortId));if(connected.length>=2){let[a2,b3]=connected.slice(0,2),pairKey=[a2,b3].sort().join("::");if(!pairKeyToSourceTraceId.has(pairKey)){pairKeyToSourceTraceId.set(pairKey,st4.source_trace_id);let userNetId=st4.display_name??st4.source_trace_id;st4.subcircuit_connectivity_map_key&&(allScks.add(st4.subcircuit_connectivity_map_key),userNetIdToSck.set(userNetId,st4.subcircuit_connectivity_map_key),sckToUserNetId.set(st4.subcircuit_connectivity_map_key,userNetId)),directConnections.push({pinIds:[a2,b3].map(id=>schematicPortIdToPinId.get(id)),netId:userNetId})}}}let netConnections=[];for(let net of db.source_net.list().filter(n3=>!n3.subcircuit_id||allowedSubcircuitIds.has(n3.subcircuit_id)))net.subcircuit_connectivity_map_key&&(allScks.add(net.subcircuit_connectivity_map_key),sckToSourceNet.set(net.subcircuit_connectivity_map_key,net));let sckToPinIds=new Map;for(let[schId,srcPortId]of schPortIdToSourcePortId){let sp2=db.source_port.get(srcPortId);if(!sp2?.subcircuit_connectivity_map_key)continue;let sck=sp2.subcircuit_connectivity_map_key;allScks.add(sck),sckToPinIds.has(sck)||sckToPinIds.set(sck,[]),sckToPinIds.get(sck).push(schId)}for(let[subcircuitConnectivityKey,schematicPortIds]of sckToPinIds){let sourceNet=sckToSourceNet.get(subcircuitConnectivityKey);if(sourceNet&&schematicPortIds.length>=2){let userNetId=String(sourceNet.name||sourceNet.source_net_id||subcircuitConnectivityKey);userNetIdToSck.set(userNetId,subcircuitConnectivityKey),sckToUserNetId.set(subcircuitConnectivityKey,userNetId);let charWidth=.1*(.18/.18),netLabelWidth=Number((String(userNetId).length*charWidth).toFixed(2));netConnections.push({netId:userNetId,pinIds:schematicPortIds.map(portId=>schematicPortIdToPinId.get(portId)),netLabelWidth})}}let availableNetLabelOrientations=(()=>{let netToAllowedOrientations={},presentNetIds=new Set(netConnections.map(nc2=>nc2.netId));for(let net of db.source_net.list().filter(n3=>!n3.subcircuit_id||allowedSubcircuitIds.has(n3.subcircuit_id)))net.name&&presentNetIds.has(net.name)&&(net.is_ground||net.name.toLowerCase().startsWith("gnd")?netToAllowedOrientations[net.name]=["y-"]:net.is_power||net.name.toLowerCase().startsWith("v")?netToAllowedOrientations[net.name]=["y+"]:netToAllowedOrientations[net.name]=["x-","x+"]);return netToAllowedOrientations})();return{inputProblem:{chips,directConnections,netConnections,availableNetLabelOrientations,maxMspPairDistance:group._parsedProps.schMaxTraceDistance??2.4},pinIdToSchematicPortId,pairKeyToSourceTraceId,sckToSourceNet,sckToUserNetId,userNetIdToSck,allSourceAndSchematicPortIdsInScope,schPortIdToSourcePortId,displayLabelTraces,allScks}}var TOL=1e-6;function isHorizontalEdge(edge){let dx2=Math.abs(edge.to.x-edge.from.x),dy2=Math.abs(edge.to.y-edge.from.y);return dx2>=dy2}function length6(a2,b3){return Math.hypot(b3.x-a2.x,b3.y-a2.y)}function pointAt(a2,b3,t5){return{x:a2.x+(b3.x-a2.x)*t5,y:a2.y+(b3.y-a2.y)*t5}}function paramAlong(a2,b3,p4){let L4=length6(a2,b3);if(L4<TOL)return 0;let t5=((p4.x-a2.x)*(b3.x-a2.x)+(p4.y-a2.y)*(b3.y-a2.y))/((b3.x-a2.x)*(b3.x-a2.x)+(b3.y-a2.y)*(b3.y-a2.y));return Math.max(0,Math.min(1,t5))*L4}function cross2(ax2,ay2,bx2,by2){return ax2*by2-ay2*bx2}function segmentIntersection(p12,p22,q12,q22){let r4={x:p22.x-p12.x,y:p22.y-p12.y},s2={x:q22.x-q12.x,y:q22.y-q12.y},rxs=cross2(r4.x,r4.y,s2.x,s2.y),q_p={x:q12.x-p12.x,y:q12.y-p12.y},q_pxr=cross2(q_p.x,q_p.y,r4.x,r4.y);if(Math.abs(rxs)<TOL&&Math.abs(q_pxr)<TOL||Math.abs(rxs)<TOL&&Math.abs(q_pxr)>=TOL)return null;let t5=cross2(q_p.x,q_p.y,s2.x,s2.y)/rxs,u4=cross2(q_p.x,q_p.y,r4.x,r4.y)/rxs;return t5<-TOL||t5>1+TOL||u4<-TOL||u4>1+TOL?null:{x:p12.x+t5*r4.x,y:p12.y+t5*r4.y}}function mergeIntervals(intervals,tol=TOL){if(intervals.length===0)return intervals;intervals.sort((a2,b3)=>a2.start-b3.start);let merged=[],cur={...intervals[0]};for(let i2=1;i2<intervals.length;i2++){let nxt=intervals[i2];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 L4=length6(edge.from,edge.to);if(L4<TOL||crossingDistances.length===0)return[edge];let half=crossLen/2,rawIntervals=crossingDistances.map(d3=>({start:Math.max(0,d3-half),end:Math.min(L4,d3+half)})).filter(iv=>iv.end-iv.start>TOL),intervals=mergeIntervals(rawIntervals),result=[],cursor=0,dir={x:edge.to.x-edge.from.x,y:edge.to.y-edge.from.y},addSeg=(d02,d12,isCrossing)=>{if(d12-d02<=TOL)return;let t02=d02/L4,t12=d12/L4;result.push({from:pointAt(edge.from,edge.to,t02),to:pointAt(edge.from,edge.to,t12),...isCrossing?{is_crossing:!0}:{}})};for(let iv of intervals)iv.start-cursor>TOL&&addSeg(cursor,iv.start,!1),addSeg(iv.start,iv.end,!0),cursor=iv.end;return L4-cursor>TOL&&addSeg(cursor,L4,!1),result.length>0?result:[edge]}function computeCrossings(traces,opts={}){let crossLen=opts.crossSegmentLength??.075,tol=opts.tolerance??TOL,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 eA=A4.edges[ei3];for(let tj=ti3;tj<traces.length;tj++){let B5=traces[tj];for(let ej=tj===ti3?ei3+1:0;ej<B5.edges.length;ej++){let eB=B5.edges[ej],P5=segmentIntersection(eA.from,eA.to,eB.from,eB.to);if(!P5)continue;let LA=length6(eA.from,eA.to),LB=length6(eB.from,eB.to);if(LA<tol||LB<tol)continue;let dA=paramAlong(eA.from,eA.to,P5),dB=paramAlong(eB.from,eB.to,P5),nearEndpointA=dA<=tol||Math.abs(LA-dA)<=tol||Number.isNaN(dA),nearEndpointB=dB<=tol||Math.abs(LB-dB)<=tol||Number.isNaN(dB);if(!nearEndpointA&&!nearEndpointB){let aIsHorizontal=isHorizontalEdge(eA),bIsHorizontal=isHorizontalEdge(eB),assignToA;if(aIsHorizontal!==bIsHorizontal)assignToA=aIsHorizontal;else{let ax2=Math.abs(eA.to.x-eA.from.x),ay2=Math.abs(eA.to.y-eA.from.y),bx2=Math.abs(eB.to.x-eB.from.x),by2=Math.abs(eB.to.y-eB.from.y),aScore=ax2-ay2,bScore=bx2-by2;assignToA=aScore===bScore?!0:aScore>bScore}let chosenKey=keyOf({traceIdx:assignToA?ti3:tj,edgeIdx:assignToA?ei3:ej}),chosenList=crossingsByEdge.get(chosenKey)??[];chosenList.push(assignToA?dA:dB),crossingsByEdge.set(chosenKey,chosenList)}}}}}let out=traces.map(t5=>({source_trace_id:t5.source_trace_id,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 uniqueSorted=Array.from(new Set(splittingDistances.map(d3=>Number(d3.toFixed(6))))).sort((a2,b3)=>a2-b3),split=splitEdgeByCrossings(trace.edges[ei3],uniqueSorted,crossLen);out[ti3].edges.push(...split)}}return out}var TOL2=1e-6;function nearlyEqual(a2,b3,tol=TOL2){return Math.abs(a2-b3)<=tol}function pointEq(a2,b3,tol=TOL2){return nearlyEqual(a2.x,b3.x,tol)&&nearlyEqual(a2.y,b3.y,tol)}function onSegment4(p4,a2,b3,tol=TOL2){let minX=Math.min(a2.x,b3.x)-tol,maxX=Math.max(a2.x,b3.x)+tol,minY=Math.min(a2.y,b3.y)-tol,maxY=Math.max(a2.y,b3.y)+tol;return p4.x<minX||p4.x>maxX||p4.y<minY||p4.y>maxY?!1:Math.abs((b3.x-a2.x)*(p4.y-a2.y)-(b3.y-a2.y)*(p4.x-a2.x))<=tol}function dedupePoints(points,tol=TOL2){let map=new Map;for(let p4 of points){let key=`${p4.x.toFixed(6)},${p4.y.toFixed(6)}`;map.has(key)||map.set(key,p4)}return Array.from(map.values())}function edgeVec(e4){return{x:e4.to.x-e4.from.x,y:e4.to.y-e4.from.y}}function isParallel(e12,e22,tol=TOL2){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 cross22=v12.x*v22.y-v12.y*v22.x;return Math.abs(cross22)<=tol*L12*L22}function incidentEdgesAtPoint(trace,p4,tol=TOL2){return trace.edges.filter(e4=>pointEq(e4.from,p4,tol)||pointEq(e4.to,p4,tol))}function nearestEndpointOnTrace(trace,p4,tol=TOL2){for(let e4 of trace.edges){if(pointEq(e4.from,p4,tol))return e4.from;if(pointEq(e4.to,p4,tol))return e4.to}return null}function edgeDirectionFromPoint(e4,p4,tol=TOL2){let other=pointEq(e4.from,p4,tol)||nearlyEqual(e4.from.x,p4.x,tol)&&nearlyEqual(e4.from.y,p4.y,tol)?e4.to:e4.from,dx2=other.x-p4.x,dy2=other.y-p4.y;return Math.abs(dx2)<tol&&Math.abs(dy2)<tol?null:Math.abs(dx2)>=Math.abs(dy2)?dx2>=0?"right":"left":dy2>=0?"up":"down"}function getCornerOrientationAtPoint(trace,p4,tol=TOL2){let incident=incidentEdgesAtPoint(trace,p4,tol);if(incident.length<2)return null;let dirs=incident.map(e4=>edgeDirectionFromPoint(e4,p4,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??TOL2,result={};for(let t5 of traces)result[t5.source_trace_id]=[];let endpointsByTrace=traces.map(t5=>{let pts=[];for(let e4 of t5.edges)pts.push(e4.from,e4.to);return dedupePoints(pts,tol)});for(let i2=0;i2<traces.length;i2++){let A4=traces[i2],AEnds=endpointsByTrace[i2];for(let j4=i2+1;j4<traces.length;j4++){let B5=traces[j4],BEnds=endpointsByTrace[j4];for(let pa3 of AEnds)for(let pb of BEnds)if(pointEq(pa3,pb,tol)){let aEdgesAtP=incidentEdgesAtPoint(A4,pa3,tol),bEdgesAtP=incidentEdgesAtPoint(B5,pb,tol),hasCorner=aEdgesAtP.some(eA=>bEdgesAtP.some(eB=>!isParallel(eA,eB,tol))),aCorner=getCornerOrientationAtPoint(A4,pa3,tol),bCorner=getCornerOrientationAtPoint(B5,pb,tol);hasCorner&&!(aCorner!==null&&bCorner!==null&&aCorner===bCorner)&&(result[A4.source_trace_id].push(pa3),A4.source_trace_id!==B5.source_trace_id&&result[B5.source_trace_id].push(pb))}for(let pa3 of AEnds)for(let eB of B5.edges)if(onSegment4(pa3,eB.from,eB.to,tol)){let hasCorner=incidentEdgesAtPoint(A4,pa3,tol).some(eA=>!isParallel(eA,eB,tol)),aCorner=getCornerOrientationAtPoint(A4,pa3,tol),bEndpointNearPa=nearestEndpointOnTrace(B5,pa3,tol*1e3),bCorner=bEndpointNearPa?getCornerOrientationAtPoint(B5,bEndpointNearPa,tol):null;hasCorner&&!(aCorner!==null&&bCorner!==null&&aCorner===bCorner)&&(result[A4.source_trace_id].push(pa3),A4.source_trace_id!==B5.source_trace_id&&result[B5.source_trace_id].push(pa3))}for(let pb of BEnds)for(let eA of A4.edges)if(onSegment4(pb,eA.from,eA.to,tol)){let hasCorner=incidentEdgesAtPoint(B5,pb,tol).some(eB=>!isParallel(eA,eB,tol)),bCorner=getCornerOrientationAtPoint(B5,pb,tol),aEndpointNearPb=nearestEndpointOnTrace(A4,pb,tol*1e3),aCorner=aEndpointNearPb?getCornerOrientationAtPoint(A4,aEndpointNearPb,tol):null;hasCorner&&!(aCorner!==null&&bCorner!==null&&aCorner===bCorner)&&(result[B5.source_trace_id].push(pb),A4.source_trace_id!==B5.source_trace_id&&result[A4.source_trace_id].push(pb))}}}for(let id of Object.keys(result))result[id]=dedupePoints(result[id],tol);return result}var debug7=(0,import_debug15.default)("Group_doInitialSchematicTraceRender");function applyTracesFromSolverOutput(args){let{group,solver,pinIdToSchematicPortId,userNetIdToSck}=args,{db}=group.root,traces=solver.traceCleanupSolver?.getOutput().traces??solver.traceLabelOverlapAvoidanceSolver?.getOutput().traces??solver.schematicTraceLinesSolver?.solvedTracePaths,pendingTraces=[];debug7(`Traces inside SchematicTraceSolver output: ${(traces??[]).length}`);for(let solvedTracePath of traces??[]){let points=solvedTracePath?.tracePath;if(!Array.isArray(points)||points.length<2){debug7(`Skipping trace ${solvedTracePath?.pinIds.join(",")} because it has less than 2 points`);continue}let edges=[];for(let i2=0;i2<points.length-1;i2++)edges.push({from:{x:points[i2].x,y:points[i2].y},to:{x:points[i2+1].x,y:points[i2+1].y}});let source_trace_id=null,subcircuit_connectivity_map_key;if(Array.isArray(solvedTracePath?.pins)&&solvedTracePath.pins.length===2){let pA=pinIdToSchematicPortId.get(solvedTracePath.pins[0]?.pinId),pB=pinIdToSchematicPortId.get(solvedTracePath.pins[1]?.pinId);if(pA&&pB){for(let schPid of[pA,pB])db.schematic_port.get(schPid)&&db.schematic_port.update(schPid,{is_connected:!0});subcircuit_connectivity_map_key=userNetIdToSck.get(String(solvedTracePath.userNetId))}}source_trace_id||(source_trace_id=`solver_${solvedTracePath?.mspPairId}`,subcircuit_connectivity_map_key=userNetIdToSck.get(String(solvedTracePath.userNetId))),pendingTraces.push({source_trace_id,edges,subcircuit_connectivity_map_key})}debug7(`Applying ${pendingTraces.length} traces from SchematicTraceSolver output`);let withCrossings=computeCrossings(pendingTraces.map(t5=>({source_trace_id:t5.source_trace_id,edges:t5.edges}))),junctionsById=computeJunctions(withCrossings);for(let t5 of withCrossings)db.schematic_trace.insert({source_trace_id:t5.source_trace_id,edges:t5.edges,junctions:junctionsById[t5.source_trace_id]??[],subcircuit_connectivity_map_key:pendingTraces.find(p4=>p4.source_trace_id===t5.source_trace_id)?.subcircuit_connectivity_map_key})}var 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"}},getNetNameFromPorts=ports=>{for(let port of ports){let traces=port._getDirectlyConnectedTraces();for(let trace of traces){let displayLabel=trace._parsedProps.schDisplayLabel;if(displayLabel)return{name:displayLabel,wasAssignedDisplayLabel:!0}}}return{name:ports.map(p4=>p4._getNetLabelText()).join("/"),wasAssignedDisplayLabel:!1}},debug8=(0,import_debug16.default)("Group_doInitialSchematicTraceRender");function applyNetLabelPlacements(args){let{group,solver,sckToSourceNet,allScks,allSourceAndSchematicPortIdsInScope,schPortIdToSourcePortId,userNetIdToSck,pinIdToSchematicPortId,schematicPortIdsWithPreExistingNetLabels,schematicPortIdsWithRoutedTraces}=args,{db}=group.root,netLabelPlacements=solver.netLabelPlacementSolver?.netLabelPlacements??solver.traceLabelOverlapAvoidanceSolver?.getOutput().netLabelPlacements??[],globalConnMap=solver.mspConnectionPairSolver.globalConnMap;for(let placement of netLabelPlacements){debug8(`processing placement: ${placement.netId}`);let placementUserNetId=globalConnMap.getIdsConnectedToNet(placement.globalConnNetId).find(id=>userNetIdToSck.get(id)),placementSck=userNetIdToSck.get(placementUserNetId),anchor_position=placement.anchorPoint,orientation4=placement.orientation,anchor_side=oppositeSide2(orientation4),sourceNet=placementSck?sckToSourceNet.get(placementSck):void 0,schPortIds=placement.pinIds.map(pinId=>pinIdToSchematicPortId.get(pinId));if(schPortIds.some(schPortId=>schematicPortIdsWithPreExistingNetLabels.has(schPortId))){debug8(`skipping net label placement for "${placement.netId}" REASON:schematic port has pre-existing net label`);continue}if(sourceNet){let text2=sourceNet.name,center22=computeSchematicNetLabelCenter({anchor_position,anchor_side,text:text2});db.schematic_net_label.insert({text:text2,anchor_position,center:center22,anchor_side,...sourceNet?.source_net_id?{source_net_id:sourceNet.source_net_id}:{}});continue}let ports=group.selectAll("port").filter(p4=>p4._getSubcircuitConnectivityKey()===placementSck),{name:text,wasAssignedDisplayLabel}=getNetNameFromPorts(ports);if(!wasAssignedDisplayLabel&&schPortIds.some(schPortId=>schematicPortIdsWithRoutedTraces.has(schPortId))){debug8(`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});db.schematic_net_label.insert({text,anchor_position,center:center2,anchor_side})}}var insertNetLabelsForPortsMissingTrace=({allSourceAndSchematicPortIdsInScope,group,schPortIdToSourcePortId,sckToSourceNet:connKeyToNet,pinIdToSchematicPortId,schematicPortIdsWithPreExistingNetLabels})=>{let{db}=group.root;for(let schOrSrcPortId of Array.from(allSourceAndSchematicPortIdsInScope)){let schPort=db.schematic_port.get(schOrSrcPortId);if(!schPort||schPort.is_connected)continue;let srcPortId=schPortIdToSourcePortId.get(schOrSrcPortId);if(!srcPortId)continue;let key=db.source_port.get(srcPortId)?.subcircuit_connectivity_map_key;if(!key)continue;let sourceNet=connKeyToNet.get(key);if(!sourceNet||db.schematic_net_label.list().some(nl2=>Math.abs(nl2.anchor_position.x-schPort.center.x)<.1&&Math.abs(nl2.anchor_position.y-schPort.center.y)<.1?sourceNet.source_net_id&&nl2.source_net_id?nl2.source_net_id===sourceNet.source_net_id:nl2.text===(sourceNet.name||key):!1))continue;let text=sourceNet.name||sourceNet.source_net_id||key,side=getEnteringEdgeFromDirection(schPort.facing_direction||"right")||"right",center2=computeSchematicNetLabelCenter({anchor_position:schPort.center,anchor_side:side,text});db.schematic_net_label.insert({text,anchor_position:schPort.center,center:center2,anchor_side:side,...sourceNet.source_net_id?{source_net_id:sourceNet.source_net_id}:{}})}},getSchematicPortIdsWithAssignedNetLabels=group=>{let schematicPortIdsWithNetLabels=new Set,netLabels=group.selectAll("netlabel");for(let netLabel of netLabels){let netLabelPorts=netLabel._getConnectedPorts();for(let port of netLabelPorts)port.schematic_port_id&&schematicPortIdsWithNetLabels.add(port.schematic_port_id)}return schematicPortIdsWithNetLabels},getSchematicPortIdsWithRoutedTraces=({solver,pinIdToSchematicPortId})=>{let solvedTraces=solver.schematicTraceLinesSolver.solvedTracePaths,schematicPortIdsWithRoutedTraces=new Set;for(let solvedTrace of solvedTraces)for(let pinId of solvedTrace.pinIds){let schPortId=pinIdToSchematicPortId.get(pinId);schPortId&&schematicPortIdsWithRoutedTraces.add(schPortId)}return schematicPortIdsWithRoutedTraces},debug9=(0,import_debug14.default)("Group_doInitialSchematicTraceRender"),Group_doInitialSchematicTraceRender=group=>{if(!group.root?._featureMspSchematicTraceRouting||!group.isSubcircuit||group.root?.schematicDisabled)return;let{inputProblem,pinIdToSchematicPortId,pairKeyToSourceTraceId,sckToSourceNet,allSourceAndSchematicPortIdsInScope,schPortIdToSourcePortId,displayLabelTraces,allScks,userNetIdToSck}=createSchematicTraceSolverInputProblem(group),schematicPortIdsWithPreExistingNetLabels=getSchematicPortIdsWithAssignedNetLabels(group);debug9.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);solver.solve();let schematicPortIdsWithRoutedTraces=getSchematicPortIdsWithRoutedTraces({solver,pinIdToSchematicPortId});applyTracesFromSolverOutput({group,solver,pinIdToSchematicPortId,userNetIdToSck}),applyNetLabelPlacements({group,solver,sckToSourceNet,allSourceAndSchematicPortIdsInScope,schPortIdToSourcePortId,pinIdToSchematicPortId,allScks,userNetIdToSck,schematicPortIdsWithPreExistingNetLabels,schematicPortIdsWithRoutedTraces}),insertNetLabelsForPortsMissingTrace({group,allSourceAndSchematicPortIdsInScope,schPortIdToSourcePortId,sckToSourceNet,pinIdToSchematicPortId,schematicPortIdsWithPreExistingNetLabels})},getSpiceyEngine=()=>({async simulate(spiceString){let simulation_experiment_id="spice-experiment-1",{circuit:parsedCircuit,tran}=simulate(spiceString);return{simulationResultCircuitJson:spiceyTranToVGraphs(tran,parsedCircuit,simulation_experiment_id)}}}),SIMULATION_COLOR_PALETTE=["rgb(132, 0, 0)","rgb(194, 194, 0)","rgb(194, 0, 194)","rgb(194, 0, 0)","rgb(0, 132, 132)","rgb(0, 132, 0)","rgb(0, 0, 132)","rgb(132, 132, 132)","rgb(132, 0, 132)","rgb(194, 194, 194)","rgb(132, 0, 132)","rgb(132, 0, 0)","rgb(132, 132, 0)","rgb(194, 194, 194)","rgb(0, 0, 132)","rgb(0, 132, 0)"],idToColorMap=new Map,colorIndex=0;function getSimulationColorForId(id){if(idToColorMap.has(id))return idToColorMap.get(id);let color=SIMULATION_COLOR_PALETTE[colorIndex];return colorIndex=(colorIndex+1)%SIMULATION_COLOR_PALETTE.length,idToColorMap.set(id,color),color}function resetSimulationColorState(){idToColorMap.clear(),colorIndex=0}var debug10=(0,import_debug17.default)("tscircuit:core:Group_doInitialSimulationSpiceEngineRender");function Group_doInitialSimulationSpiceEngineRender(group){if(!group.isSubcircuit)return;let{root}=group;if(!root)return;let analogSims=group.selectAll("analogsimulation");if(analogSims.length===0)return;let voltageProbes=group.selectAll("voltageprobe");resetSimulationColorState();let spiceEngineMap={...root.platform?.spiceEngineMap};spiceEngineMap.spicey||(spiceEngineMap.spicey=getSpiceyEngine());let circuitJson=root.db.toArray(),spiceString,spiceNetlist;try{spiceNetlist=circuitJsonToSpice(circuitJson),spiceString=spiceNetlist.toSpiceString(),debug10(`Generated SPICE string:
|
|
621
621
|
${spiceString}`)}catch(error){debug10(`Failed to convert circuit JSON to SPICE: ${error}`);return}for(let analogSim of analogSims){let engineName=analogSim._parsedProps.spiceEngine??"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(k4=>k4!=="spicey"))}`);let effectId=`spice-simulation-${engineName}-${analogSim.source_component_id}`;debug10(`Queueing simulation for spice engine: ${engineName} (id: ${effectId})`),group._queueAsyncEffect(effectId,async()=>{try{debug10(`Running simulation with engine: ${engineName}`);let result=await spiceEngine2.simulate(spiceString);debug10(`Simulation completed, received ${result.simulationResultCircuitJson.length} elements`);let simulationExperiment=root.db.simulation_experiment.list()[0];if(!simulationExperiment){debug10("No simulation experiment found, skipping result insertion");return}for(let element of result.simulationResultCircuitJson){if(element.type==="simulation_transient_voltage_graph"){element.simulation_experiment_id=simulationExperiment.simulation_experiment_id;let probeMatch=voltageProbes.find(p4=>p4.finalProbeName===element.name);probeMatch&&(element.color=probeMatch.color)}let elementType=element.type;elementType&&root.db[elementType]?(root.db[elementType].insert(element),debug10(`Inserted ${elementType} into database`)):(debug10(`Warning: Unknown element type ${elementType}, adding to raw db`),root.db._addElement(element))}group._markDirty("SimulationSpiceEngineRender")}catch(error){debug10(`Simulation failed for engine ${engineName}: ${error}`);let simulationExperiment=root.db.simulation_experiment.list()[0];root.db.simulation_unknown_experiment_error.insert({simulation_experiment_id:simulationExperiment?.simulation_experiment_id,error_type:"simulation_unknown_experiment_error",message:error instanceof Error?error.message:String(error)})}})}}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}=group.root,pcbGroup=db.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=getBoundsFromPoints(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),db.pcb_group.update(group.pcb_group_id,{center:newCenter})),db.pcb_group.update(group.pcb_group_id,{anchor_position:targetPosition,anchor_alignment:pcbPositionAnchor,display_offset_x:pcbX,display_offset_y:pcbY})}function computeCenterFromAnchorPosition(anchorPosition,ctx){let{width,height,pcbAnchorAlignment}=ctx;if(!pcbAnchorAlignment)return anchorPosition;let alignment=pcbAnchorAlignment;if(typeof width!="number"||typeof height!="number")return console.log("width or height is not a number"),anchorPosition;let ax2=anchorPosition.x,ay2=anchorPosition.y;switch(alignment){case"top_left":return{x:ax2+width/2,y:ay2-height/2};case"top_center":return{x:ax2,y:ay2-height/2};case"top_right":return{x:ax2-width/2,y:ay2-height/2};case"center_left":return{x:ax2+width/2,y:ay2};case"center_right":return{x:ax2-width/2,y:ay2};case"bottom_left":return{x:ax2+width/2,y:ay2+height/2};case"bottom_center":return{x:ax2,y:ay2+height/2};case"bottom_right":return{x:ax2-width/2,y:ay2+height/2};default:return anchorPosition}}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(g7=>g7.length>=2)}function insertAutoplacedJumpers(params){let{db,output_jumpers,subcircuit_id}=params;for(let jumperIndex=0;jumperIndex<output_jumpers.length;jumperIndex++){let jumper=output_jumpers[jumperIndex],sourceComponent=db.source_component.insert({ftype:"simple_chip",name:`__autoplaced_jumper_${jumperIndex}`,supplier_part_numbers:{}}),rotation4=jumper.orientation==="horizontal"?0:90,firstPadLayer=jumper.pads[0]?.layer||jumper.pads[0]?.layers?.[0]||"top",pcbComponent=db.pcb_component.insert({source_component_id:sourceComponent.source_component_id,center:jumper.center,rotation:rotation4,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=db.source_port.insert({source_component_id:sourceComponent.source_component_id,name:`pin${pinNumber}`,pin_number:pinNumber}),padLayer=pad2.layer||pad2.layers?.[0]||"top",pcbPort=db.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=db.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(p4=>Math.abs(p4.pad.center.x-groupPad.center.x)<.01&&Math.abs(p4.pad.center.y-groupPad.center.y)<.01);padInfo&&sourcePortIds.push(padInfo.sourcePortId)}sourcePortIds.length>=2&&db.source_component_internal_connection.insert({source_component_id:sourceComponent.source_component_id,subcircuit_id:subcircuit_id??void 0,source_port_ids:sourcePortIds})}}}function splitPcbTracesOnJumperSegments(route){let jumperRoutes=route.filter(p4=>p4.route_type==="jumper"),wireAndViaRoutes=route.filter(p4=>p4.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 i2=0;i2<wireAndViaRoutes.length;i2++){let p4=wireAndViaRoutes[i2];if(p4.route_type!=="wire")continue;let distToStart=Math.hypot(p4.x-jumperStart.x,p4.y-jumperStart.y),distToEnd=Math.hypot(p4.x-jumperEnd.x,p4.y-jumperEnd.y);distToStart<minStartDist&&(minStartDist=distToStart,startIdx=i2),distToEnd<minEndDist&&(minEndDist=distToEnd,endIdx=i2)}startIdx>endIdx&&([startIdx,endIdx]=[endIdx,startIdx]),startIdx>=0&&endIdx>=0&&startIdx!==endIdx&&splitRanges.push({startIdx,endIdx})}splitRanges.sort((a2,b3)=>a2.startIdx-b3.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 getJumperPadInfos(db){let padInfos=[],jumperSmtpads=db.pcb_smtpad.list().filter(pad2=>{let component=db.pcb_component.get(pad2.pcb_component_id);return component?db.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,x5,y5,tolerance=.01){for(let pad2 of padInfos)if(Math.abs(pad2.x-x5)<tolerance&&Math.abs(pad2.y-y5)<tolerance)return pad2.pcb_port_id}function findJumperPortContainingPoint(padInfos,x5,y5){for(let pad2 of padInfos)if(x5>=pad2.minX&&x5<=pad2.maxX&&y5>=pad2.minY&&y5<=pad2.maxY)return pad2}function splitRouteAtJumperPads(route,padInfos){if(route.length===0||padInfos.length===0)return[route];let segments=[],currentSegment=[];for(let i2=0;i2<route.length;i2++){let point6=route[i2];if(currentSegment.push(point6),point6.route_type==="wire"&&i2>0&&i2<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,db){let padInfos=getJumperPadInfos(db);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 Group6=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,"_normalComponentNameMap",null);__publicField(this,"_asyncAutoroutingResult",null);__publicField(this,"unnamedElementCounter",{})}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"}}doInitialSourceGroupRender(){let{db}=this.root,hasExplicitName=typeof this._parsedProps.name=="string"&&this._parsedProps.name.length>0,source_group2=db.source_group.insert({name:this.name,is_subcircuit:this.isSubcircuit,was_automatically_named:!hasExplicitName});this.source_group_id=source_group2.source_group_id,this.isSubcircuit&&(this.subcircuit_id=`subcircuit_${source_group2.source_group_id}`,db.source_group.update(source_group2.source_group_id,{subcircuit_id:this.subcircuit_id}))}doInitialSourceRender(){let{db}=this.root;for(let child of this.children)db.source_component.update(child.source_component_id,{source_group_id:this.source_group_id})}doInitialSourceParentAttachment(){let{db}=this.root,parentGroup=this.parent?.getGroup?.();if(parentGroup?.source_group_id&&db.source_group.update(this.source_group_id,{parent_source_group_id:parentGroup.source_group_id}),!this.isSubcircuit)return;let parent_subcircuit_id=this.parent?.getSubcircuit?.()?.subcircuit_id;parent_subcircuit_id&&db.source_group.update(this.source_group_id,{parent_subcircuit_id})}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=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_group2=db.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_group2.pcb_group_id;for(let child of this.children)db.pcb_component.update(child.pcb_component_id,{pcb_group_id:pcb_group2.pcb_group_id})}doInitialPcbPrimitiveRender(){this.calculatePcbGroupBounds()}calculatePcbGroupBounds(){if(!this.pcb_group_id||this.root?.pcbDisabled)return;let{db}=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=getBoundsFromPoints(numericOutline);if(!outlineBounds)return;let centerX2=(outlineBounds.minX+outlineBounds.maxX)/2,centerY2=(outlineBounds.minY+outlineBounds.maxY)/2,center22=hasExplicitPositioning?db.pcb_group.get(this.pcb_group_id)?.center??{x:centerX2,y:centerY2}:{x:centerX2,y:centerY2};db.pcb_group.update(this.pcb_group_id,{center:center22});return}let bounds=getBoundsOfPcbComponents(this.children),width=bounds.width,height=bounds.height,centerX=(bounds.minX+bounds.maxX)/2,centerY=(bounds.minY+bounds.maxY)/2;if(this.isSubcircuit){let{padLeft,padRight,padTop,padBottom}=this._resolvePcbPadding();width+=padLeft+padRight,height+=padTop+padBottom,centerX+=(padRight-padLeft)/2,centerY+=(padTop-padBottom)/2}let center2=hasExplicitPositioning?db.pcb_group.get(this.pcb_group_id)?.center??{x:centerX,y:centerY}:{x:centerX,y:centerY};db.pcb_group.update(this.pcb_group_id,{width:Number(props.width??width),height:Number(props.height??height),center:center2})}updatePcbPrimitiveRender(){this.calculatePcbGroupBounds()}getNextAvailableName(elm){var _a360,_b2;return(_a360=this.unnamedElementCounter)[_b2=elm.lowercaseComponentName]??(_a360[_b2]=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}=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)}_areChildSubcircuitsRouted(){let subcircuitChildren=this.selectAll("group").filter(g7=>g7.isSubcircuit);for(let subcircuitChild of subcircuitChildren)if(subcircuitChild._shouldRouteAsync()&&!subcircuitChild._asyncAutoroutingResult)return!1;return!0}_shouldRouteAsync(){let autorouter=this._getAutorouterConfig();return autorouter.groupMode==="sequential-trace"?!1:!!(autorouter.local&&autorouter.groupMode==="subcircuit"||!autorouter.local)}_hasTracesToRoute(){let debug112=(0,import_debug10.default)("tscircuit:core:_hasTracesToRoute"),traces=this.selectAll("trace");return debug112(`[${this.getString()}] has ${traces.length} traces to route`),traces.length>0}async _runEffectMakeHttpAutoroutingRequest(){let{db}=this.root,debug112=(0,import_debug10.default)("tscircuit:core:_runEffectMakeHttpAutoroutingRequest"),props=this._parsedProps,autorouterConfig2=this._getAutorouterConfig(),serverUrl=autorouterConfig2.serverUrl,serverMode=autorouterConfig2.serverMode,fetchWithDebug=(url,options)=>(debug112("fetching",url),options.headers&&(options.headers["Tscircuit-Core-Version"]=this.root?.getCoreVersion()),fetch(url,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{autorouting_result:autorouting_result2}=await fetchWithDebug(`${serverUrl}/autorouting/solve`,{method:"POST",body:JSON.stringify({input_simple_route_json:getSimpleRouteJsonFromCircuitJson({db,minTraceWidth:this.props.autorouter?.minTraceWidth??.15,nominalTraceWidth:this.props.nominalTraceWidth,subcircuit_id:this.subcircuit_id}).simpleRouteJson,subcircuit_id:this.subcircuit_id}),headers:{"Content-Type":"application/json"}}).then(r4=>r4.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(r4=>r4.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(r4=>r4.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(r4=>r4.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(r4=>r4.json());this._asyncAutoroutingResult={output_pcb_traces:autorouting_job_output.output_pcb_traces},this._markDirty("PcbTraceRender");break}if(job.has_error){let err=new AutorouterError(`Autorouting job failed: ${JSON.stringify(job.error)}`);throw db.pcb_autorouting_error.insert({pcb_error_id:autorouting_job.autorouting_job_id,error_type:"pcb_autorouting_error",message:err.message}),err}await new Promise(resolve=>setTimeout(resolve,100))}}async _runLocalAutorouting(){let{db}=this.root,props=this._parsedProps,debug112=(0,import_debug10.default)("tscircuit:core:_runLocalAutorouting");debug112(`[${this.getString()}] starting local autorouting`);let autorouterConfig2=this._getAutorouterConfig(),isLaserPrefabPreset=this._isLaserPrefabAutorouter(autorouterConfig2),isAutoJumperPreset=this._isAutoJumperAutorouter(autorouterConfig2),isSingleLayerBoard=this._getSubcircuitLayerCount()===1,{simpleRouteJson}=getSimpleRouteJsonFromCircuitJson({db,minTraceWidth:this.props.autorouter?.minTraceWidth??.15,nominalTraceWidth:this.props.nominalTraceWidth,subcircuit_id:this.subcircuit_id});if(isAutoJumperPreset&&(simpleRouteJson.allowJumpers=!0),debug112.enabled&&global.debugOutputArray?.push({name:`simpleroutejson-${this.props.name}.json`,obj:simpleRouteJson}),debug112.enabled){let graphicsObject=sn2(simpleRouteJson);graphicsObject.title=`autorouting-${this.props.name}`,global.debugGraphics?.push(graphicsObject)}this.root?.emit("autorouting:start",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),simpleRouteJson});let autorouter;if(autorouterConfig2.algorithmFn)autorouter=await autorouterConfig2.algorithmFn(simpleRouteJson);else{let autorouterVersion2=this.props.autorouterVersion,effortLevel=this.props.autorouterEffortLevel,effort=effortLevel?Number.parseInt(effortLevel.replace("x",""),10):void 0;autorouter=new TscircuitAutorouter(simpleRouteJson,{capacityDepth:this.props.autorouter?.capacityDepth,targetMinCapacity:this.props.autorouter?.targetMinCapacity,useAssignableSolver:isLaserPrefabPreset||isSingleLayerBoard,useAutoJumperSolver:isAutoJumperPreset,autorouterVersion:autorouterVersion2,effort,onSolverStarted:({solverName,solverParams})=>this.root?.emit("solver:started",{type:"solver:started",solverName,solverParams,componentName:this.getString()})})}let routingPromise=new Promise((resolve,reject)=>{autorouter.on("complete",event=>{debug112(`[${this.getString()}] local autorouting complete`),resolve(event.traces)}),autorouter.on("error",event=>{debug112(`[${this.getString()}] local autorouting error: ${event.error.message}`),reject(event.error)})});autorouter.on("progress",event=>{this.root?.emit("autorouting:progress",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),...event})}),autorouter.start();try{let traces=await routingPromise;if(autorouter.getConnectedOffboardObstacles){let connectedOffboardObstacles=autorouter.getConnectedOffboardObstacles();createSourceTracesFromOffboardConnections({db,connectedOffboardObstacles,simpleRouteJson,subcircuit_id:this.subcircuit_id})}let outputJumpers=[],solver=autorouter.solver;solver?.getOutputJumpers&&(outputJumpers=solver.getOutputJumpers()||[]),this._asyncAutoroutingResult={output_pcb_traces:traces,output_jumpers:outputJumpers},this._markDirty("PcbTraceRender")}catch(error){let{db:db2}=this.root;throw db2.pcb_autorouting_error.insert({pcb_error_id:`pcb_autorouter_error_subcircuit_${this.subcircuit_id}`,error_type:"pcb_autorouting_error",message:error instanceof Error?error.message:String(error)}),this.root?.emit("autorouting:error",{subcircuit_id:this.subcircuit_id,componentDisplayName:this.getString(),error:{message:error instanceof Error?error.message:String(error)},simpleRouteJson}),error}finally{autorouter.stop()}}_startAsyncAutorouting(){this._hasStartedAsyncAutorouting||(this._hasStartedAsyncAutorouting=!0,this._getAutorouterConfig().local?this._queueAsyncEffect("capacity-mesh-autorouting",async()=>this._runLocalAutorouting()):this._queueAsyncEffect("make-http-autorouting-request",async()=>this._runEffectMakeHttpAutoroutingRequest()))}doInitialPcbTraceRender(){let debug112=(0,import_debug10.default)("tscircuit:core:doInitialPcbTraceRender");if(this.isSubcircuit&&!this.root?.pcbDisabled&&!this.getInheritedProperty("routingDisabled")&&!this._shouldUseTraceByTraceRouting()){if(!this._areChildSubcircuitsRouted()){debug112(`[${this.getString()}] child subcircuits are not routed, skipping async autorouting until subcircuits routed`);return}debug112(`[${this.getString()}] no child subcircuits to wait for, initiating async routing`),this._hasTracesToRoute()&&this._startAsyncAutorouting()}}doInitialSchematicTraceRender(){Group_doInitialSchematicTraceRender(this)}updatePcbTraceRender(){let debug112=(0,import_debug10.default)("tscircuit:core:updatePcbTraceRender");if(debug112(`[${this.getString()}] updating...`),!this.isSubcircuit)return;if(this._shouldRouteAsync()&&this._hasTracesToRoute()&&!this._hasStartedAsyncAutorouting){this._areChildSubcircuitsRouted()&&(debug112(`[${this.getString()}] child subcircuits are now routed, starting async autorouting`),this._startAsyncAutorouting());return}if(!this._asyncAutoroutingResult||this._shouldUseTraceByTraceRouting())return;let{db}=this.root;if(this._asyncAutoroutingResult.output_simple_route_json){debug112(`[${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){debug112(`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`),this._updatePcbTraceRenderFromPcbTraces();return}}_updatePcbTraceRenderFromSimpleRouteJson(){let{db}=this.root,{traces:routedTraces}=this._asyncAutoroutingResult.output_simple_route_json;if(routedTraces)for(let routedTrace of routedTraces){let pcb_trace2=db.pcb_trace.insert({subcircuit_id:this.subcircuit_id,route:routedTrace.route})}}_updatePcbTraceRenderFromPcbTraces(){let{output_pcb_traces,output_jumpers}=this._asyncAutoroutingResult;if(!output_pcb_traces)return;let{db}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{holeDiameter,padDiameter}=getViaDiameterDefaults(pcbStyle2);output_jumpers&&output_jumpers.length>0&&insertAutoplacedJumpers({db,output_jumpers,subcircuit_id:this.subcircuit_id});for(let pcb_trace2 of output_pcb_traces){if(pcb_trace2.type!=="pcb_trace")continue;if(pcb_trace2.subcircuit_id=this.subcircuit_id,pcb_trace2.connection_name){let sourceTraceId=pcb_trace2.connection_name;pcb_trace2.source_trace_id=sourceTraceId}let segments=splitPcbTracesOnJumperSegments(pcb_trace2.route);segments===null&&(segments=[pcb_trace2.route]);let processedSegments=addPortIdsToTracesAtJumperPads(segments,db);for(let segment2 of processedSegments)segment2.length>0&&db.pcb_trace.insert({...pcb_trace2,route:segment2})}for(let pcb_trace2 of output_pcb_traces)if(pcb_trace2.type!=="pcb_via"&&pcb_trace2.type==="pcb_trace")for(let point6 of pcb_trace2.route)point6.route_type==="via"&&db.pcb_via.insert({pcb_trace_id:pcb_trace2.pcb_trace_id,x:point6.x,y:point6.y,hole_diameter:holeDiameter,outer_diameter:padDiameter,layers:[point6.from_layer,point6.to_layer],from_layer:point6.from_layer,to_layer:point6.to_layer})}doInitialSchematicComponentRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,schematic_group2=db.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});this.schematic_group_id=schematic_group2.schematic_group_id;for(let child of this.children)child.schematic_component_id&&db.schematic_component.update(child.schematic_component_id,{schematic_group_id:schematic_group2.schematic_group_id})}_getSchematicLayoutMode(){let props=this._parsedProps;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 anyChildHasSchCoords=this.children.some(child=>{let cProps=child._parsedProps;return cProps?.schX!==void 0||cProps?.schY!==void 0}),hasManualEdits=(props.manualEdits?.schematic_placements?.length??0)>0;return!anyChildHasSchCoords&&!hasManualEdits?"match-adapt":"relative"}doInitialSchematicLayout(){let schematicLayoutMode=this._getSchematicLayoutMode();schematicLayoutMode==="match-adapt"&&this._doInitialSchematicLayoutMatchpack(),schematicLayoutMode==="grid"&&this._doInitialSchematicLayoutGrid(),schematicLayoutMode==="flex"&&this._doInitialSchematicLayoutFlex(),this._insertSchematicBorder()}_doInitialSchematicLayoutMatchAdapt(){Group_doInitialSchematicLayoutMatchAdapt(this)}_doInitialSchematicLayoutMatchpack(){Group_doInitialSchematicLayoutMatchPack(this)}_doInitialSchematicLayoutGrid(){Group_doInitialSchematicLayoutGrid(this)}_doInitialSchematicLayoutFlex(){Group_doInitialSchematicLayoutFlex(this)}_getPcbLayoutMode(){let props=this._parsedProps;if(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,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,hasCoords=childProps?.pcbX!==void 0||childProps?.pcbY!==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}=this.root,props=this._parsedProps;if(props.pcbX!==void 0||props.pcbY!==void 0){let parentGroup=this.parent?.getGroup?.(),pcbParentGroupId=parentGroup?.pcb_group_id?db.pcb_group.get(parentGroup.pcb_group_id)?.pcb_group_id:void 0,positionedRelativeToBoardId=pcbParentGroupId?void 0:this._getBoard()?.pcb_board_id??void 0;db.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}=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?db.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;db.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 dx2=port.center.x-component.center.x,dy2=port.center.y-component.center.y;return Math.abs(dx2)>Math.abs(dy2)?dx2>0?"right":"left":dy2>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)}_isLaserPrefabAutorouter(autorouterConfig2=this._getAutorouterConfig()){let autorouterProp2=this.props.autorouter,normalize3=value=>value?.replace(/-/g,"_")??value;return autorouterConfig2.preset==="laser_prefab"?!0:typeof autorouterProp2=="string"?normalize3(autorouterProp2)==="laser_prefab":typeof autorouterProp2=="object"&&autorouterProp2?normalize3(autorouterProp2.preset)==="laser_prefab":!1}_isAutoJumperAutorouter(autorouterConfig2=this._getAutorouterConfig()){let autorouterProp2=this.props.autorouter,normalize3=value=>value?.replace(/-/g,"_")??value;return autorouterConfig2.preset==="auto_jumper"?!0:typeof autorouterProp2=="string"?normalize3(autorouterProp2)==="auto_jumper":typeof autorouterProp2=="object"&&autorouterProp2?normalize3(autorouterProp2.preset)==="auto_jumper":!1}_getSubcircuitLayerCount(){let layers=this.getInheritedProperty("layers");return typeof layers=="number"?layers:2}_shouldUseTraceByTraceRouting(){return this._getAutorouterConfig().groupMode==="sequential-trace"}doInitialPcbDesignRuleChecks(){if(this.root?.pcbDisabled||this.getInheritedProperty("routingDisabled"))return;let{db}=this.root;if(this.isSubcircuit){let subcircuitComponentsByName=new Map;for(let child of this.children)if(!child.isSubcircuit&&child._parsedProps.name){let components=subcircuitComponentsByName.get(child._parsedProps.name)||[];components.push(child),subcircuitComponentsByName.set(child._parsedProps.name,components)}for(let[name,components]of subcircuitComponentsByName.entries())components.length>1&&db.pcb_trace_error.insert({error_type:"pcb_trace_error",message:`Multiple components found with name "${name}" in subcircuit "${this.name||"unnamed"}". Component names must be unique within a subcircuit.`,source_trace_id:"",pcb_trace_id:"",pcb_component_ids:components.map(c3=>c3.pcb_component_id).filter(Boolean),pcb_port_ids:[]})}}doInitialSchematicReplaceNetLabelsWithSymbols(){if(this.root?.schematicDisabled||!this.isSubcircuit)return;let{db}=this.root,subtree=db;for(let nl2 of subtree.schematic_net_label.list()){let net=subtree.source_net.get(nl2.source_net_id),text=nl2.text||net?.name||"";if(nl2.anchor_side==="top"&&/^gnd/i.test(text)){subtree.schematic_net_label.update(nl2.schematic_net_label_id,{symbol_name:"rail_down"});continue}nl2.anchor_side==="bottom"&&/^v/i.test(text)&&subtree.schematic_net_label.update(nl2.schematic_net_label_id,{symbol_name:"rail_up"})}}doInitialSimulationSpiceEngineRender(){Group_doInitialSimulationSpiceEngineRender(this)}doInitialPcbComponentAnchorAlignment(){Group_doInitialPcbComponentAnchorAlignment(this)}updatePcbComponentAnchorAlignment(){this.doInitialPcbComponentAnchorAlignment()}_getMinimumFlexContainerSize(){return super._getMinimumFlexContainerSize()}_repositionOnPcb(position2){return super._repositionOnPcb(position2)}};function inflatePcbBoard(pcbBoard,inflatorContext){let{subcircuit}=inflatorContext;if(subcircuit.lowercaseComponentName==="board"||subcircuit.parent?.lowercaseComponentName==="board")return;let boardProps2={name:"inflated_board"};pcbBoard.width&&(boardProps2.width=pcbBoard.width),pcbBoard.height&&(boardProps2.height=pcbBoard.height),pcbBoard.center&&(boardProps2.pcbX=pcbBoard.center.x,boardProps2.pcbY=pcbBoard.center.y),pcbBoard.outline&&(boardProps2.outline=pcbBoard.outline),pcbBoard.thickness&&(boardProps2.thickness=pcbBoard.thickness),pcbBoard.material&&(boardProps2.material=pcbBoard.material);let board=new Board(boardProps2);return board.pcb_board_id=pcbBoard.pcb_board_id,subcircuit.add(board),board}var stringProxy=new Proxy({},{get:(target,prop)=>prop}),FTYPE=stringProxy,SCHEMATIC_COMPONENT_OUTLINE_COLOR="rgba(132, 0, 0)",SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH=.12,Capacitor=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"_adjustSilkscreenTextAutomatically",!0)}get config(){return{componentName:"Capacitor",schematicSymbolName:this.props.polarized?"capacitor_polarized":this.props.symbolName??"capacitor",zodProps:capacitorProps,sourceFtype:FTYPE.simple_capacitor}}initPorts(){typeof this.props.footprint=="string"?super.initPorts({additionalAliases:{pin1:["anode","pos"],pin2:["cathode","neg"]}}):super.initPorts()}_getSchematicSymbolDisplayValue(){let inputCapacitance=this.props.capacitance,capacitanceDisplay=typeof inputCapacitance=="string"?inputCapacitance:`${formatSiUnit(this._parsedProps.capacitance)}F`;return this._parsedProps.schShowRatings&&this._parsedProps.maxVoltageRating?`${capacitanceDisplay}/${formatSiUnit(this._parsedProps.maxVoltageRating)}V`:capacitanceDisplay}doInitialCreateNetsFromProps(){this._createNetsFromProps([this.props.decouplingFor,this.props.decouplingTo,...this._getNetsFromConnectionsProp()])}doInitialCreateTracesFromProps(){this.props.decouplingFor&&this.props.decouplingTo&&(this.add(new Trace3({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.decouplingFor})),this.add(new Trace3({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.decouplingTo}))),this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_capacitor",name:this.name,manufacturer_part_number:props.manufacturerPartNumber??props.mfn,supplier_part_numbers:props.supplierPartNumbers,capacitance:props.capacitance,max_voltage_rating:props.maxVoltageRating,max_decoupling_trace_length:props.maxDecouplingTraceLength,display_capacitance:this._getSchematicSymbolDisplayValue(),are_pins_interchangeable:!props.polarized,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},inflatePcbComponent=(pcbElm,inflatorContext)=>{let{injectionDb,normalComponent}=inflatorContext;if(!normalComponent)return;let componentCenter=pcbElm.center||{x:0,y:0},componentRotation=pcbElm.rotation||0,absoluteToComponentRelativeTransform=inverse(compose(translate(componentCenter.x,componentCenter.y),rotate(componentRotation*Math.PI/180))),relativeElements=injectionDb.toArray().filter(elm=>"pcb_component_id"in elm&&elm.pcb_component_id===pcbElm.pcb_component_id),clonedRelativeElements=structuredClone(relativeElements);transformPCBElements(clonedRelativeElements,absoluteToComponentRelativeTransform);let components=createComponentsFromCircuitJson({componentName:normalComponent.name,componentRotation:"0deg"},clonedRelativeElements);normalComponent.addAll(components)};function inflateSourceCapacitor(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}),capacitor=new Capacitor({name:sourceElm.name,capacitance:sourceElm.capacitance,layer:pcbElm?.layer,pcbX:pcbElm?.center?.x,pcbY:pcbElm?.center?.y,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});pcbElm&&inflatePcbComponent(pcbElm,{...inflatorContext,normalComponent:capacitor}),sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(capacitor):subcircuit.add(capacitor)}var Chip=class extends NormalComponent3{constructor(props){super(props);__publicField(this,"schematicBoxDimensions",null)}get config(){return{componentName:"Chip",zodProps:chipProps,shouldRenderAsSchematicBox:!0}}initPorts(opts={}){super.initPorts(opts);let{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp();if(props.externallyConnectedPins){let requiredPorts=new Set;for(let[pin1,pin2]of props.externallyConnectedPins)requiredPorts.add(pin1),requiredPorts.add(pin2);for(let pinIdentifier of requiredPorts)if(!this.children.find(child=>child instanceof Port&&child.isMatchingAnyOf([pinIdentifier]))){let pinMatch=pinIdentifier.match(/^pin(\d+)$/);if(pinMatch){let pinNumber=parseInt(pinMatch[1]);this.add(new Port({pinNumber,aliases:[pinIdentifier]}))}else this.add(new Port({name:pinIdentifier,aliases:[pinIdentifier]}))}}}doInitialSchematicComponentRender(){let{_parsedProps:props}=this;props?.noSchematicRepresentation!==!0&&super.doInitialSchematicComponentRender()}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db.source_component.insert({ftype:"simple_chip",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}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),componentLayer=props.layer??"top";if(componentLayer!=="top"&&componentLayer!=="bottom"){let subcircuit=this.getSubcircuit(),error=pcb_component_invalid_layer_error.parse({type:"pcb_component_invalid_layer_error",message:`Component cannot be placed on layer '${componentLayer}'. Components can only be placed on 'top' or 'bottom' layers.`,source_component_id:this.source_component_id,layer:componentLayer,subcircuit_id:subcircuit.subcircuit_id??void 0});db.pcb_component_invalid_layer_error.insert(error)}let pcb_component2=db.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:componentLayer==="top"||componentLayer==="bottom"?componentLayer:"top",rotation:props.pcbRotation??0,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});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialCreateTracesFromProps(){let{_parsedProps:props}=this;if(props.externallyConnectedPins)for(let[pin1,pin2]of props.externallyConnectedPins)this.add(new Trace3({from:`${this.getSubcircuitSelector()} > port.${pin1}`,to:`${this.getSubcircuitSelector()} > port.${pin2}`}));this._createTracesFromConnectionsProp()}doInitialSimulationRender(){let{db}=this.root,{pinAttributes}=this.props;if(!pinAttributes)return;let powerPort=null,groundPort=null,voltage2,ports=this.selectAll("port");for(let port of ports)for(let alias of port.getNameAndAliases())if(pinAttributes[alias]){let attributes2=pinAttributes[alias];attributes2.providesPower&&(powerPort=port,voltage2=attributes2.providesVoltage),attributes2.providesGround&&(groundPort=port)}if(!powerPort||!groundPort||voltage2===void 0)return;let powerSourcePort=db.source_port.get(powerPort.source_port_id);if(!powerSourcePort?.subcircuit_connectivity_map_key)return;let groundSourcePort=db.source_port.get(groundPort.source_port_id);if(!groundSourcePort?.subcircuit_connectivity_map_key)return;let powerNet=db.source_net.getWhere({subcircuit_connectivity_map_key:powerSourcePort.subcircuit_connectivity_map_key}),groundNet=db.source_net.getWhere({subcircuit_connectivity_map_key:groundSourcePort.subcircuit_connectivity_map_key});!powerNet||!groundNet||db.simulation_voltage_source.insert({type:"simulation_voltage_source",positive_source_port_id:powerPort.source_port_id,positive_source_net_id:powerNet.source_net_id,negative_source_port_id:groundPort.source_port_id,negative_source_net_id:groundNet.source_net_id,voltage:voltage2})}},mapInternallyConnectedSourcePortIdsToPinLabels=(sourcePortIds,inflatorContext)=>{if(!sourcePortIds||sourcePortIds.length===0)return;let{injectionDb}=inflatorContext,mapped=sourcePortIds.map(group=>group.map(sourcePortId=>{let port=injectionDb.source_port.get(sourcePortId);return port?port.pin_number!==void 0&&port.pin_number!==null?`pin${port.pin_number}`:port.name:null}).filter(value=>value!==null)).filter(group=>group.length>0);return mapped.length>0?mapped:void 0},inflateSourceChip=(sourceElm,inflatorContext)=>{let{injectionDb,subcircuit,groupsMap}=inflatorContext,pcbElm=injectionDb.pcb_component.getWhere({source_component_id:sourceElm.source_component_id}),schematicElm=injectionDb.schematic_component.getWhere({source_component_id:sourceElm.source_component_id}),cadElm=injectionDb.cad_component.getWhere({source_component_id:sourceElm.source_component_id}),internallyConnectedPins=mapInternallyConnectedSourcePortIdsToPinLabels(sourceElm.internally_connected_source_port_ids,inflatorContext),chip=new Chip({name:sourceElm.name,manufacturerPartNumber:sourceElm.manufacturer_part_number,supplierPartNumbers:sourceElm.supplier_part_numbers??void 0,pinLabels:schematicElm?.port_labels??void 0,schWidth:schematicElm?.size?.width,schHeight:schematicElm?.size?.height,schPinSpacing:schematicElm?.pin_spacing,schX:schematicElm?.center?.x,schY:schematicElm?.center?.y,layer:pcbElm?.layer,pcbX:pcbElm?.center?.x,pcbY:pcbElm?.center?.y,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds,internallyConnectedPins}),footprint=cadElm?.footprinter_string??null;footprint&&(Object.assign(chip.props,{footprint}),Object.assign(chip._parsedProps,{footprint}),cadElm||chip._addChildrenFromStringFootprint?.()),pcbElm&&inflatePcbComponent(pcbElm,{...inflatorContext,normalComponent:chip}),sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(chip):subcircuit.add(chip)},Diode=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"pos",this.portMap.pin1);__publicField(this,"anode",this.portMap.pin1);__publicField(this,"neg",this.portMap.pin2);__publicField(this,"cathode",this.portMap.pin2)}get config(){let symbolMap={schottky:"schottky_diode",avalanche:"avalanche_diode",zener:"zener_diode",photodiode:"photodiode"},variantSymbol=this.props.schottky?"schottky":this.props.avalanche?"avalanche":this.props.zener?"zener":this.props.photo?"photodiode":null;return{schematicSymbolName:variantSymbol?symbolMap[variantSymbol]:this.props.symbolName??"diode",componentName:"Diode",zodProps:diodeProps,sourceFtype:"simple_diode"}}initPorts(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["cathode","neg","right"]}})}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_diode",name:this.name,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}};function inflateSourceDiode(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}),diode2=new Diode({name:sourceElm.name,layer:pcbElm?.layer,pcbX:pcbElm?.center?.x,pcbY:pcbElm?.center?.y,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});pcbElm&&inflatePcbComponent(pcbElm,{...inflatorContext,normalComponent:diode2}),sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(diode2):subcircuit.add(diode2)}function inflateSourceGroup(sourceGroup,inflatorContext){let{subcircuit,groupsMap}=inflatorContext,group=new Group6({name:sourceGroup.name??`inflated_group_${sourceGroup.source_group_id}`});return 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 Inductor=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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:FTYPE.simple_inductor,inductance:this.props.inductance,display_inductance:this._getSchematicSymbolDisplayValue(),supplier_part_numbers:props.supplierPartNumbers,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}),inductor=new Inductor({name:sourceElm.name,inductance:sourceElm.inductance,layer:pcbElm?.layer,pcbX:pcbElm?.center?.x,pcbY:pcbElm?.center?.y,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});pcbElm&&inflatePcbComponent(pcbElm,{...inflatorContext,normalComponent:inductor}),sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(inductor):subcircuit.add(inductor)}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}=root,pcb_port2=db.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_port2.pcb_port_id}}var Resistor=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 Trace3({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.pullupFor})),this.add(new Trace3({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.pullupTo}))),this.props.pulldownFor&&this.props.pulldownTo&&(this.add(new Trace3({from:`${this.getSubcircuitSelector()} > port.1`,to:this.props.pulldownFor})),this.add(new Trace3({from:`${this.getSubcircuitSelector()} > port.2`,to:this.props.pulldownTo}))),this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.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}),resistor=new Resistor({name:sourceElm.name,resistance:sourceElm.resistance,layer:pcbElm?.layer,pcbX:pcbElm?.center?.x,pcbY:pcbElm?.center?.y,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});pcbElm&&inflatePcbComponent(pcbElm,{...inflatorContext,normalComponent:resistor}),sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(resistor):subcircuit.add(resistor)}var getSelectorPath=(component,inflatorContext)=>{let{injectionDb,subcircuit,groupsMap}=inflatorContext,path_parts=[],currentGroupId=component.source_group_id;for(;currentGroupId&¤tGroupId!==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 trace=new Trace3({path:connectedSelectors});trace.source_trace_id=sourceTrace.source_trace_id,subcircuit.add(trace)}var Transistor=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"emitter",this.portMap.pin1);__publicField(this,"collector",this.portMap.pin2);__publicField(this,"base",this.portMap.pin3)}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 pinAliases={pin1:["collector","c"],pin2:["emitter","e"],pin3:["base","b"]};super.initPorts({pinCount:3,additionalAliases:pinAliases})}doInitialCreateNetsFromProps(){this._createNetsFromProps([...this._getNetsFromConnectionsProp()])}doInitialCreateTracesFromProps(){this._createTracesFromConnectionsProp()}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_transistor",name:this.name,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}),transistor=new Transistor({name:sourceElm.name,type:sourceElm.transistor_type,layer:pcbElm?.layer,pcbX:pcbElm?.center?.x,pcbY:pcbElm?.center?.y,pcbRotation:pcbElm?.rotation,doNotPlace:pcbElm?.do_not_place,obstructsWithinBounds:pcbElm?.obstructs_within_bounds});pcbElm&&inflatePcbComponent(pcbElm,{...inflatorContext,normalComponent:transistor}),sourceElm.source_group_id&&groupsMap?.has(sourceElm.source_group_id)?groupsMap.get(sourceElm.source_group_id).add(transistor):subcircuit.add(transistor)}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();for(let sourceGroup of sourceGroups)inflateSourceGroup(sourceGroup,inflationCtx);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_chip":inflateSourceChip(sourceComponent,inflationCtx);break;case"simple_transistor":inflateSourceTransistor(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)},MIN_EFFECTIVE_BORDER_RADIUS_MM=.01,getRoundedRectOutline=(width,height,radius)=>{let w22=width/2,h22=height/2,r4=Math.min(radius,w22,h22);if(r4<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*r4/.1)),step=Math.PI/2/segments,outline=[];outline.push({x:-w22+r4,y:-h22}),outline.push({x:w22-r4,y:-h22});for(let i2=1;i2<=segments;i2++){let theta=-Math.PI/2+i2*step;outline.push({x:w22-r4+r4*Math.cos(theta),y:-h22+r4+r4*Math.sin(theta)})}outline.push({x:w22,y:h22-r4});for(let i2=1;i2<=segments;i2++){let theta=0+i2*step;outline.push({x:w22-r4+r4*Math.cos(theta),y:h22-r4+r4*Math.sin(theta)})}outline.push({x:-w22+r4,y:h22});for(let i2=1;i2<=segments;i2++){let theta=Math.PI/2+i2*step;outline.push({x:-w22+r4+r4*Math.cos(theta),y:h22-r4+r4*Math.sin(theta)})}outline.push({x:-w22,y:-h22+r4});for(let i2=1;i2<=segments;i2++){let theta=Math.PI+i2*step;outline.push({x:-w22+r4+r4*Math.cos(theta),y:-h22+r4+r4*Math.sin(theta)})}return outline},Board=class extends Group6{constructor(){super(...arguments);__publicField(this,"pcb_board_id",null);__publicField(this,"source_board_id",null);__publicField(this,"_drcChecksComplete",!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(){let layerCount=this._parsedProps.layers??2;return layerCount===1?["top"]:layerCount===4?["top","bottom","inner1","inner2"]:["top","bottom"]}_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 compose(parentTransform,translate(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=getBoundsFromPoints(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}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalPcbPositionBeforeLayout(),pcbBoard=db.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=getDescendantSubcircuitIds(db,this.subcircuit_id),allowedSubcircuitIds=new Set([this.subcircuit_id,...descendantIds]),allPcbComponents=db.pcb_component.list().filter(c3=>c3.subcircuit_id&&allowedSubcircuitIds.has(c3.subcircuit_id)),allPcbGroups=db.pcb_group.list().filter(g7=>g7.subcircuit_id&&allowedSubcircuitIds.has(g7.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=getBoundsFromPoints(pcbGroup.outline);bounds&&(width=bounds.maxX-bounds.minX,height=bounds.maxY-bounds.minY)}updateBounds(pcbGroup.center,width,height)}if(props.boardAnchorPosition){let{x:x5,y:y5}=props.boardAnchorPosition;minX=Math.min(minX,x5),minY=Math.min(minY,y5),maxX=Math.max(maxX,x5),maxY=Math.max(maxY,y5)}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)}))),db.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(`
|
|
622
|
-
`),position2={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:position2})}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}=this.root,source_board2=db.source_board.insert({source_group_id:this.source_group_id,title:this.props.title||this.props.name});this.source_board_id=source_board2.source_board_id}doInitialInflateSubcircuitCircuitJson(){let{circuitJson,children}=this._parsedProps;inflateCircuitJson(this,circuitJson,children)}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=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"){let outlineBounds=getBoundsFromPoints(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 pcb_board2=db.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});this.pcb_board_id=pcb_board2.pcb_board_id,this._addBoardInformationToSilkscreen()}removePcbComponentRender(){let{db}=this.root;this.pcb_board_id&&(db.pcb_board.delete(this.pcb_board_id),this.pcb_board_id=null)}doInitialPcbDesignRuleChecks(){this.root?.pcbDisabled||this.getInheritedProperty("routingDisabled")||super.doInitialPcbDesignRuleChecks()}updatePcbDesignRuleChecks(){if(this.root?.pcbDisabled||this.getInheritedProperty("routingDisabled"))return;let{db}=this.root;if(!this._areChildSubcircuitsRouted()||this._drcChecksComplete)return;let runDrcChecks=circuitJson=>{let pcbTraceOverlappingErrors=checkEachPcbTraceNonOverlapping(circuitJson);for(let error of pcbTraceOverlappingErrors)db.pcb_trace_error.insert(error);let pcbPortNotConnectedErrors=checkEachPcbPortConnectedToPcbTraces(circuitJson);for(let error of pcbPortNotConnectedErrors)db.pcb_port_not_connected_error.insert(error);let pcbComponentOutsideErrors=checkPcbComponentsOutOfBoard(circuitJson);for(let error of pcbComponentOutsideErrors)db.pcb_component_outside_board_error.insert(error);let pcbTracesOutOfBoardErrors=checkPcbTracesOutOfBoard(circuitJson);for(let error of pcbTracesOutOfBoardErrors)db.pcb_trace_error.insert(error);let differentNetViaErrors=checkDifferentNetViaSpacing(circuitJson);for(let error of differentNetViaErrors)db.pcb_via_clearance_error.insert(error);let sameNetViaErrors=checkSameNetViaSpacing(circuitJson);for(let error of sameNetViaErrors)db.pcb_via_clearance_error.insert(error);let pcbComponentOverlapErrors=checkPcbComponentOverlap(circuitJson);for(let error of pcbComponentOverlapErrors)db.pcb_footprint_overlap_error.insert(error);let sourcePinMustBeConnectedErrors=checkPinMustBeConnected(circuitJson);for(let error of sourcePinMustBeConnectedErrors)db.source_pin_must_be_connected_error.insert(error)},subcircuitCircuitJson=db.subtree({subcircuit_id:this.subcircuit_id}).toArray();runDrcChecks(subcircuitCircuitJson),this._drcChecksComplete=!0}_emitRenderLifecycleEvent(phase,startOrEnd){super._emitRenderLifecycleEvent(phase,startOrEnd),startOrEnd==="start"&&this.root?.emit("board:renderPhaseStarted",{renderId:this._renderId,phase})}_repositionOnPcb(position2){let{db}=this.root,pcbBoard=this.pcb_board_id?db.pcb_board.get(this.pcb_board_id):null,oldPos=pcbBoard?.center;if(!oldPos){this.pcb_board_id&&db.pcb_board.update(this.pcb_board_id,{center:position2});return}let deltaX=position2.x-oldPos.x,deltaY=position2.y-oldPos.y;if(!(Math.abs(deltaX)<1e-6&&Math.abs(deltaY)<1e-6)&&this.pcb_board_id&&(db.pcb_board.update(this.pcb_board_id,{center:position2}),pcbBoard?.outline)){let outlineBounds=getBoundsFromPoints(pcbBoard.outline);if(outlineBounds){let oldOutlineCenter={x:(outlineBounds.minX+outlineBounds.maxX)/2,y:(outlineBounds.minY+outlineBounds.maxY)/2},outlineDeltaX=position2.x-oldOutlineCenter.x,outlineDeltaY=position2.y-oldOutlineCenter.y,newOutline=pcbBoard.outline.map(p4=>({x:p4.x+outlineDeltaX,y:p4.y+outlineDeltaY}));db.pcb_board.update(this.pcb_board_id,{outline:newOutline})}}}},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(p4=>point4(p4.x,p4.y))),is_ccw;if(outline.length>2){let p02=point4(outline[0].x,outline[0].y),p12=point4(outline[1].x,outline[1].y),segmentDir=vector$1(p02,p12).normalize(),normalToLeft=segmentDir.rotate(Math.PI/2),testPoint=p02.translate(segmentDir.multiply(segment(p02,p12).length/2)).translate(normalToLeft.multiply(.01));is_ccw=outlinePolygon.contains(testPoint)}else is_ccw=outlinePolygon.area()>0;for(let i2=0;i2<outline.length;i2++){let p1_=outline[i2],p2_=outline[(i2+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 k4=0;k4<numBitesInGap;k4++){let biteDist=firstBiteDistFromP1+k4*holeAndSpacing,pos=p12.translate(segmentDir.multiply(biteDist));mouseBiteHoles.push({x:pos.x,y:pos.y})}}}let p_prev_=outline[(i2-1+outline.length)%outline.length],p_next_=outline[(i2+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=[{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(p4=>point4(p4.x,p4.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}}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=getBoundsFromPoints(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}},packBoardsIntoGrid=({boards,db,row,col,cellWidth,cellHeight,boardGap})=>{let boardsWithDims=boards.map(board=>{let width,height;if(db&&board.pcb_board_id){let pcbBoard=db.pcb_board.get(board.pcb_board_id);pcbBoard?.width!==void 0&&pcbBoard?.height!==void 0&&(width=pcbBoard.width,height=pcbBoard.height)}if(width===void 0||height===void 0){let propsDims=getBoardDimensionsFromProps(board);width=propsDims.width,height=propsDims.height}return width===0&&height===0?null:{board,width,height}}).filter(b3=>b3!==null);if(boardsWithDims.length===0)return{positions:[],gridWidth:0,gridHeight:0};let explicitRow=row,cols=col??Math.ceil(explicitRow?boardsWithDims.length/explicitRow:Math.sqrt(boardsWithDims.length)),rows=explicitRow??Math.ceil(boardsWithDims.length/cols),colWidths=Array(cols).fill(0),rowHeights=Array(rows).fill(0);boardsWithDims.forEach((b3,i2)=>{let colIdx=i2%cols,rowIdx=Math.floor(i2/cols);rowIdx<rowHeights.length&&b3.height>rowHeights[rowIdx]&&(rowHeights[rowIdx]=b3.height),colIdx<colWidths.length&&b3.width>colWidths[colIdx]&&(colWidths[colIdx]=b3.width)});let minCellWidth=cellWidth?distance.parse(cellWidth):0,minCellHeight=cellHeight?distance.parse(cellHeight):0;for(let i2=0;i2<colWidths.length;i2++)colWidths[i2]=Math.max(colWidths[i2],minCellWidth);for(let i2=0;i2<rowHeights.length;i2++)rowHeights[i2]=Math.max(rowHeights[i2],minCellHeight);let totalGridWidth=colWidths.reduce((a2,b3)=>a2+b3,0)+(cols>1?(cols-1)*boardGap:0),totalGridHeight=rowHeights.reduce((a2,b3)=>a2+b3,0)+(rows>1?(rows-1)*boardGap:0),startX=-totalGridWidth/2,rowYOffsets=[-totalGridHeight/2];for(let i2=1;i2<rows;i2++)rowYOffsets.push(rowYOffsets[i2-1]+rowHeights[i2-1]+boardGap);let colXOffsets=[startX];for(let i2=1;i2<cols;i2++)colXOffsets.push(colXOffsets[i2-1]+colWidths[i2-1]+boardGap);let positions=[];return boardsWithDims.forEach((b3,i2)=>{let colIdx=i2%cols,rowIdx=Math.floor(i2/cols);if(rowIdx>=rowYOffsets.length||colIdx>=colXOffsets.length)return;let cellX=colXOffsets[colIdx],cellY=rowYOffsets[rowIdx],currentCellWidth=colWidths[colIdx],currentCellHeight=rowHeights[rowIdx],boardX=cellX+currentCellWidth/2,boardY=cellY+currentCellHeight/2;positions.push({board:b3.board,pos:{x:boardX,y:boardY}})}),{positions,gridWidth:totalGridWidth,gridHeight:totalGridHeight}},Subpanel=class _Subpanel extends Group6{constructor(){super(...arguments);__publicField(this,"pcb_panel_id",null);__publicField(this,"_tabsAndMouseBitesGenerated",!1);__publicField(this,"_cachedGridWidth",0);__publicField(this,"_cachedGridHeight",0)}get config(){return{componentName:"Subpanel",zodProps:subpanelProps}}get _errorComponentName(){return this.componentName.toLowerCase()}get isGroup(){return!0}get isSubcircuit(){return!0}add(component){if(component.lowercaseComponentName!=="board"&&component.lowercaseComponentName!=="subpanel")throw new Error(`<${this._errorComponentName}> can only contain <board> or <subpanel> elements`);super.add(component)}_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",childBoardInstances=this._getDirectBoardChildren();if(layoutMode!=="none")for(let board of childBoardInstances){let hasPcbX=board._parsedProps.pcbX!==void 0,hasPcbY=board._parsedProps.pcbY!==void 0;if(hasPcbX||hasPcbY){let properties=[];hasPcbX&&properties.push("pcbX"),hasPcbY&&properties.push("pcbY");let propertyNames=properties.join(" and ");this.root.db.source_property_ignored_warning.insert({source_component_id:board.source_component_id,property_name:propertyNames,message:`Board has manual positioning (${propertyNames}) but ${this._errorComponentName} layout mode is "${layoutMode}". Manual positioning will be ignored.`,error_type:"source_property_ignored_warning"})}}if(layoutMode==="none"&&childBoardInstances.length>1&&childBoardInstances.filter(board=>{let hasPcbX=board._parsedProps.pcbX!==void 0,hasPcbY=board._parsedProps.pcbY!==void 0;return!hasPcbX&&!hasPcbY}).length>1&&this.root.db.pcb_placement_error.insert({error_type:"pcb_placement_error",message:`Multiple boards in ${this._errorComponentName} without pcbX/pcbY positions. When layoutMode="none", each board must have explicit pcbX and pcbY coordinates to avoid overlapping. Either set pcbX/pcbY on each board, or use layoutMode="grid" for automatic positioning.`}),layoutMode!=="grid")return;let tabWidth=this._parsedProps.tabWidth??DEFAULT_TAB_WIDTH,boardGap=this._parsedProps.boardGap??tabWidth,{positions,gridWidth,gridHeight}=packBoardsIntoGrid({boards:childBoardInstances,row:this._parsedProps.row,col:this._parsedProps.col,cellWidth:this._parsedProps.cellWidth,cellHeight:this._parsedProps.cellHeight,boardGap});this._cachedGridWidth=gridWidth,this._cachedGridHeight=gridHeight;for(let{board,pos}of positions)board._panelPositionOffset=pos}doInitialPanelLayout(){if(this.root?.pcbDisabled)return;let{db}=this.root,childBoardInstances=this._getDirectBoardChildren();if((this._parsedProps.layoutMode??"none")==="grid"){for(let board of childBoardInstances)!board.pcb_board_id||!board._panelPositionOffset||db.pcb_board.update(board.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${board._panelPositionOffset.x}mm`,display_offset_y:`${board._panelPositionOffset.y}mm`});this._updatePanelDimensions()}else{let panelGlobalPos=this._getGlobalPcbPositionBeforeLayout();for(let board of childBoardInstances){let boardDb=db.pcb_board.get(board.pcb_board_id);if(!boardDb)continue;let relativeX=boardDb.center.x-panelGlobalPos.x,relativeY=boardDb.center.y-panelGlobalPos.y;db.pcb_board.update(board.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${relativeX}mm`,display_offset_y:`${relativeY}mm`})}}this._generateTabsAndMouseBites()}_updatePanelDimensions(){let{db}=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)db.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);db.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})}}}_generateTabsAndMouseBites(){if(this._tabsAndMouseBitesGenerated)return;let{db}=this.root,props=this._parsedProps,panelizationMethod=props.panelizationMethod??"none",childBoardInstances=this._getDirectBoardChildren();if(panelizationMethod!=="none"){let childBoardIds=childBoardInstances.map(c3=>c3.pcb_board_id).filter(id=>!!id),boardsInPanel=db.pcb_board.list().filter(b3=>childBoardIds.includes(b3.pcb_board_id));if(boardsInPanel.length===0)return;let tabWidth=props.tabWidth??DEFAULT_TAB_WIDTH,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)db.pcb_cutout.insert(tabCutout);for(let mouseBiteHole of mouseBiteHoles)db.pcb_hole.insert(mouseBiteHole)}this._tabsAndMouseBitesGenerated=!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}=this.root,props=this._parsedProps,inserted=db.pcb_panel.insert({width:props.width!==void 0?distance.parse(props.width):0,height:props.height!==void 0?distance.parse(props.height):0,center:this._getGlobalPcbPositionBeforeLayout(),covered_with_solder_mask:!(props.noSolderMask??!1)});this.pcb_panel_id=inserted.pcb_panel_id}_updatePanelDimensions(){let{db}=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)db.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);db.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}=this.root,props=this._parsedProps,currentPanel=db.pcb_panel.get(this.pcb_panel_id);db.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}=this.root,{_parsedProps:props}=this,source_component=db.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(){let rawCurrent=this._parsedProps.currentRating,rawVoltage=this._parsedProps.voltageRating,current2=typeof rawCurrent=="string"?parseFloat(rawCurrent):rawCurrent,voltage2=typeof rawVoltage=="string"?parseFloat(rawVoltage):rawVoltage;return`${formatSiUnit(current2)}A / ${formatSiUnit(voltage2)}V`}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,currentRating=typeof props.currentRating=="string"?parseFloat(props.currentRating):props.currentRating,voltageRating=typeof props.voltageRating=="string"?parseFloat(props.voltageRating):props.voltageRating,source_component=db.source_component.insert({name:this.name,ftype:FTYPE.simple_fuse,current_rating_amps:currentRating,voltage_rating_volts:voltageRating,display_current_rating:`${formatSiUnit(currentRating)}A`,display_voltage_rating:`${formatSiUnit(voltageRating)}V`,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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db.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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),pcb_component2=db.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:props.layer??"top",rotation:props.pcbRotation??0,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});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialPcbTraceRender(){let{db}=this.root,pcb_ports=db.pcb_port.list({pcb_component_id:this.pcb_component_id}),pinLabelToPortId={};for(let i2=0;i2<pcb_ports.length;i2++){let port=pcb_ports[i2],sourcePort=db.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(h4=>/^(pin)?\d+$/.test(h4));matchedHint&&(/^pin\d+$/.test(matchedHint)?pinLabel=matchedHint.replace(/^pin/,""):pinLabel=matchedHint)}pinLabelToPortId[pinLabel]=port.pcb_port_id}let traces=db.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}=this.root,source_component=db.source_component.insert({ftype:"interconnect",name:this.name,are_pins_interchangeable:!0,display_name:this._parsedProps.displayName});this.source_component_id=source_component.source_component_id}doInitialSourceParentAttachment(){let{db}=this.root,internallyConnectedPorts=this._getInternallyConnectedPins();for(let ports of internallyConnectedPorts){let sourcePortIds=ports.map(port=>port.source_port_id).filter(id=>id!==null);sourcePortIds.length>=2&&db.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)}_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(p4=>p4.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((a2,b3)=>a2-b3):props.bridged&&resolvedPinCount&&(bridgedPinNumbers=Array.from({length:resolvedPinCount},(_5,i2)=>i2+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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db.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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),pcb_component2=db.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:props.layer??"top",rotation:props.pcbRotation??0,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});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialPcbTraceRender(){let{db}=this.root,pcb_ports=db.pcb_port.list({pcb_component_id:this.pcb_component_id}),pinLabelToPortId={};for(let i2=0;i2<pcb_ports.length;i2++){let port=pcb_ports[i2],sourcePort=db.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(h4=>/^(pin)?\d+$/.test(h4));matchedHint&&(/^pin\d+$/.test(matchedHint)?pinLabel=matchedHint.replace(/^pin/,""):pinLabel=matchedHint)}pinLabelToPortId[pinLabel]=port.pcb_port_id}let traces=db.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))}},Led=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"pos",this.portMap.pin1);__publicField(this,"anode",this.portMap.pin1);__publicField(this,"neg",this.portMap.pin2);__publicField(this,"cathode",this.portMap.pin2)}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(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["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}=this.root,{_parsedProps:props}=this,source_component=db.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}},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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_power_source",name:this.name,voltage:props.voltage,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!1,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},VoltageSource=class extends NormalComponent3{constructor(){super(...arguments);__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(){}initPorts(){super.initPorts({additionalAliases:{pin1:["terminal1"],pin2:["terminal2"]}})}_getSchematicSymbolDisplayValue(){let{voltage:voltage2,frequency:frequency2}=this._parsedProps,parts=[];return voltage2!==void 0&&parts.push(`${formatSiUnit(voltage2)}V`),frequency2!==void 0&&parts.push(`${formatSiUnit(frequency2)}Hz`),parts.length>0?parts.join(" "):void 0}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.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,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db}=this.root,{_parsedProps:props}=this,terminal1Port=this.portMap.terminal1,terminal2Port=this.portMap.terminal2;db.simulation_voltage_source.insert({type:"simulation_voltage_source",is_dc_source:!1,terminal1_source_port_id:terminal1Port.source_port_id,terminal2_source_port_id:terminal2Port.source_port_id,voltage:props.voltage,frequency:props.frequency,peak_to_peak_voltage:props.peakToPeakVoltage,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle})}},CurrentSource=class extends NormalComponent3{constructor(){super(...arguments);__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(){}initPorts(){super.initPorts({additionalAliases:{pin1:["pos"],pin2:["neg"]}})}_getSchematicSymbolDisplayValue(){let{current:current2,frequency:frequency2,peakToPeakCurrent}=this._parsedProps,parts=[];return current2!==void 0&&parts.push(`${formatSiUnit(current2)}A`),peakToPeakCurrent!==void 0&&parts.push(`${formatSiUnit(peakToPeakCurrent)}A p-p`),frequency2!==void 0&&parts.push(`${formatSiUnit(frequency2)}Hz`),parts.length>0?parts.join(" "):void 0}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.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,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db}=this.root,{_parsedProps:props}=this,isAc=props.frequency!==void 0||props.peakToPeakCurrent!==void 0||props.waveShape!==void 0,posPort=this.portMap.pos,negPort=this.portMap.neg;if(isAc)db.simulation_current_source.insert({type:"simulation_current_source",is_dc_source:!1,terminal1_source_port_id:posPort.source_port_id,terminal2_source_port_id:negPort.source_port_id,current:props.current,frequency:props.frequency,peak_to_peak_current:props.peakToPeakCurrent,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle});else{if(props.current===void 0)return;db.simulation_current_source.insert({type:"simulation_current_source",is_dc_source:!0,positive_source_port_id:posPort.source_port_id,negative_source_port_id:negPort.source_port_id,current:props.current})}}},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}}},FabricationNoteRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"fabrication_note_rect_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNoteRect",zodProps:fabricationNoteRectProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),layer=maybeFlipLayer(props.layer??"top");if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for FabricationNoteRect. Must be "top" or "bottom".`);let pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,subcircuit=this.getSubcircuit(),hasStroke=props.hasStroke??(props.strokeWidth!==void 0&&props.strokeWidth!==null),fabrication_note_rect=db.pcb_fabrication_note_rect.insert({pcb_component_id,layer,color:props.color,center:{x:position2.x,y:position2.y},width:props.width,height:props.height,stroke_width:props.strokeWidth??1,is_filled:props.isFilled??!1,has_stroke:hasStroke,is_stroke_dashed:props.isStrokeDashed??!1,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,corner_radius:props.cornerRadius??void 0});this.fabrication_note_rect_id=fabrication_note_rect.pcb_fabrication_note_rect_id}getPcbSize(){let{_parsedProps:props}=this;return{width:props.width,height:props.height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.fabrication_note_rect_id)return;let rect=db.pcb_fabrication_note_rect.get(this.fabrication_note_rect_id);rect&&db.pcb_fabrication_note_rect.update(this.fabrication_note_rect_id,{center:{x:rect.center.x+deltaX,y:rect.center.y+deltaY}})}},FabricationNotePath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"fabrication_note_path_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNotePath",zodProps:fabricationNotePathProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,subcircuit=this.getSubcircuit(),{_parsedProps:props}=this,layer=props.layer??"top";if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for SilkscreenPath. Must be "top" or "bottom".`);let transform5=this._computePcbGlobalTransformBeforeLayout(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,fabrication_note_path=db.pcb_fabrication_note_path.insert({pcb_component_id,layer,color:props.color,route:props.route.map(p4=>{let transformedPosition=applyToPoint(transform5,{x:p4.x,y:p4.y});return{...p4,x:transformedPosition.x,y:transformedPosition.y}}),stroke_width:props.strokeWidth??.1,subcircuit_id:subcircuit?.subcircuit_id??void 0});this.fabrication_note_path_id=fabrication_note_path.pcb_fabrication_note_path_id}getPcbSize(){let{_parsedProps:props}=this;if(props.route.length===0)return{width:0,height:0};let xs3=props.route.map(point6=>typeof point6.x=="string"?parseFloat(point6.x):point6.x),ys3=props.route.map(point6=>typeof point6.y=="string"?parseFloat(point6.y):point6.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.fabrication_note_path_id)return;let path=db.pcb_fabrication_note_path.get(this.fabrication_note_path_id);path&&db.pcb_fabrication_note_path.update(this.fabrication_note_path_id,{route:path.route.map(p4=>({...p4,x:p4.x+deltaX,y:p4.y+deltaY}))})}},FabricationNoteText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_fabrication_note_text_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNoteText",zodProps:fabricationNoteTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),container=this.getPrimitiveContainer(),subcircuit=this.getSubcircuit(),pcb_fabrication_note_text2=db.pcb_fabrication_note_text.insert({anchor_alignment:props.anchorAlignment,anchor_position:{x:position2.x,y:position2.y},font:props.font??"tscircuit2024",font_size:props.fontSize??1,layer:"top",color:props.color,text:normalizeTextForCircuitJson(props.text??""),pcb_component_id:container.pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_fabrication_note_text_id=pcb_fabrication_note_text2.pcb_fabrication_note_text_id}getPcbSize(){let{_parsedProps:props}=this,fontSize=typeof props.fontSize=="string"?parseFloat(props.fontSize):props.fontSize??1,charWidth=fontSize*.6;return{width:(props.text??"").length*charWidth,height:fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(this.pcb_fabrication_note_text_id){let text=db.pcb_fabrication_note_text.get(this.pcb_fabrication_note_text_id);text&&db.pcb_fabrication_note_text.update(this.pcb_fabrication_note_text_id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}}},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,transform5){if(typeof input2=="string"){let target=this.getSubcircuit().selectOne(input2);return target?target._getGlobalPcbPositionBeforeLayout():(this.renderError(`FabricationNoteDimension could not find selector "${input2}"`),applyToPoint(transform5,{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 applyToPoint(transform5,{x:numericX,y:numericY})}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(props.from,transform5),to3=this._resolvePoint(props.to,transform5),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=db.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}=this.root;if(!this.fabrication_note_dimension_id)return;let dimension=db.pcb_fabrication_note_dimension.get(this.fabrication_note_dimension_id);dimension&&db.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 transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform5),to3=this._resolvePoint(this._parsedProps.to,transform5);return{width:Math.abs(to3.x-from.x),height:Math.abs(to3.y-from.y)}}_formatDistanceText({from,to:to3,units}){let dx2=to3.x-from.x,dy2=to3.y-from.y,distanceInMillimeters=Math.sqrt(dx2*dx2+dy2*dy2),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}`}},PcbNoteLine=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_line_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteLine",zodProps:pcbNoteLineProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,subcircuit=this.getSubcircuit(),group=this.getGroup(),transform5=this._computePcbGlobalTransformBeforeLayout(),start=applyToPoint(transform5,{x:props.x1,y:props.y1}),end=applyToPoint(transform5,{x:props.x2,y:props.y2}),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,pcb_note_line2=db.pcb_note_line.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,x1:start.x,y1:start.y,x2:end.x,y2:end.y,stroke_width:props.strokeWidth??.1,color:props.color,is_dashed:props.isDashed});this.pcb_note_line_id=pcb_note_line2.pcb_note_line_id}getPcbSize(){let{_parsedProps:props}=this;return{width:Math.abs(props.x2-props.x1),height:Math.abs(props.y2-props.y1)}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_line_id)return;let line2=db.pcb_note_line.get(this.pcb_note_line_id);line2&&db.pcb_note_line.update(this.pcb_note_line_id,{x1:line2.x1+deltaX,y1:line2.y1+deltaY,x2:line2.x2+deltaX,y2:line2.y2+deltaY})}},PcbNoteRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_rect_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteRect",zodProps:pcbNoteRectProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),center2=applyToPoint(transform5,{x:0,y:0}),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,pcb_note_rect2=db.pcb_note_rect.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,center:center2,width:props.width,height:props.height,stroke_width:props.strokeWidth??.1,is_filled:props.isFilled??!1,has_stroke:props.hasStroke??!0,is_stroke_dashed:props.isStrokeDashed??!1,color:props.color,corner_radius:props.cornerRadius??void 0});this.pcb_note_rect_id=pcb_note_rect2.pcb_note_rect_id}getPcbSize(){let{_parsedProps:props}=this,width=typeof props.width=="string"?parseFloat(props.width):props.width,height=typeof props.height=="string"?parseFloat(props.height):props.height;return{width,height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_rect_id)return;let rect=db.pcb_note_rect.get(this.pcb_note_rect_id);rect&&db.pcb_note_rect.update(this.pcb_note_rect_id,{center:{x:rect.center.x+deltaX,y:rect.center.y+deltaY}})}},PcbNoteText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_text_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteText",zodProps:pcbNoteTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),anchorPosition=applyToPoint(transform5,{x:0,y:0}),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,pcb_note_text2=db.pcb_note_text.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,font:props.font??"tscircuit2024",font_size:props.fontSize??1,text:normalizeTextForCircuitJson(props.text),anchor_position:anchorPosition,anchor_alignment:props.anchorAlignment??"center",color:props.color});this.pcb_note_text_id=pcb_note_text2.pcb_note_text_id}getPcbSize(){let{_parsedProps:props}=this,fontSize=typeof props.fontSize=="string"?parseFloat(props.fontSize):props.fontSize??1,charWidth=fontSize*.6;return{width:props.text.length*charWidth,height:fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_text_id)return;let text=db.pcb_note_text.get(this.pcb_note_text_id);text&&db.pcb_note_text.update(this.pcb_note_text_id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}},PcbNotePath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_path_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNotePath",zodProps:pcbNotePathProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,transformedRoute=props.route.map(point6=>{let{x:x5,y:y5,...rest}=point6,numericX=typeof x5=="string"?parseFloat(x5):x5,numericY=typeof y5=="string"?parseFloat(y5):y5,transformed=applyToPoint(transform5,{x:numericX,y:numericY});return{...rest,x:transformed.x,y:transformed.y}}),pcb_note_path2=db.pcb_note_path.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,route:transformedRoute,stroke_width:props.strokeWidth??.1,color:props.color});this.pcb_note_path_id=pcb_note_path2.pcb_note_path_id}getPcbSize(){let{_parsedProps:props}=this;if(props.route.length===0)return{width:0,height:0};let xs3=props.route.map(point6=>typeof point6.x=="string"?parseFloat(point6.x):point6.x),ys3=props.route.map(point6=>typeof point6.y=="string"?parseFloat(point6.y):point6.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_path_id)return;let path=db.pcb_note_path.get(this.pcb_note_path_id);path&&db.pcb_note_path.update(this.pcb_note_path_id,{route:path.route.map(p4=>({...p4,x:p4.x+deltaX,y:p4.y+deltaY}))})}},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,transform5){if(typeof input2=="string"){let target=this.getSubcircuit().selectOne(`.${input2}`);return target?target._getGlobalPcbPositionBeforeLayout():(this.renderError(`PcbNoteDimension could not find selector "${input2}"`),applyToPoint(transform5,{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 applyToPoint(transform5,{x:numericX,y:numericY})}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(props.from,transform5),to3=this._resolvePoint(props.to,transform5),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_dimension2=db.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,color:props.color,arrow_size:props.arrowSize??1});this.pcb_note_dimension_id=pcb_note_dimension2.pcb_note_dimension_id}getPcbSize(){let transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform5),to3=this._resolvePoint(this._parsedProps.to,transform5);return{width:Math.abs(to3.x-from.x),height:Math.abs(to3.y-from.y)}}_formatDistanceText({from,to:to3,units}){let dx2=to3.x-from.x,dy2=to3.y-from.y,distanceInMillimeters=Math.sqrt(dx2*dx2+dy2*dy2),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}=this.root;if(!this.pcb_note_dimension_id)return;let dimension=db.pcb_note_dimension.get(this.pcb_note_dimension_id);dimension&&db.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}})}},Subcircuit=class extends Group6{constructor(props){super({...props,subcircuit:!0})}doInitialInflateSubcircuitCircuitJson(){let{circuitJson,children}=this._parsedProps;inflateCircuitJson(this,circuitJson,children)}},Breakout=class extends Group6{constructor(props){super({...props,subcircuit:!0})}doInitialPcbPrimitiveRender(){if(super.doInitialPcbPrimitiveRender(),this.root?.pcbDisabled)return;let{db}=this.root,props=this._parsedProps;if(!this.pcb_group_id)return;let pcb_group2=db.pcb_group.get(this.pcb_group_id),padLeft=props.paddingLeft??props.padding??0,padRight=props.paddingRight??props.padding??0,padTop=props.paddingTop??props.padding??0,padBottom=props.paddingBottom??props.padding??0;db.pcb_group.update(this.pcb_group_id,{width:(pcb_group2.width??0)+padLeft+padRight,height:(pcb_group2.height??0)+padTop+padBottom,center:{x:pcb_group2.center.x+(padRight-padLeft)/2,y:pcb_group2.center.y+(padTop-padBottom)/2}})}},BreakoutPoint=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_breakout_point_id",null);__publicField(this,"matchedPort",null);__publicField(this,"matchedNet",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"BreakoutPoint",zodProps:breakoutPointProps}}_matchConnection(){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}"`))}_getSourceTraceIdForPort(port){let{db}=this.root;return db.source_trace.list().find(st4=>st4.connected_source_port_ids.includes(port.source_port_id))?.source_trace_id}_getSourceNetIdForPort(port){let{db}=this.root;return db.source_trace.list().find(st4=>st4.connected_source_port_ids.includes(port.source_port_id))?.connected_source_net_ids[0]}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root;this._matchConnection();let position2=this._getGlobalPcbPositionBeforeLayout(),group=this.parent?.getGroup(),subcircuit=this.getSubcircuit();if(!group||!group.pcb_group_id)return;let pcb_breakout_point2=db.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._getSourceTraceIdForPort(this.matchedPort):void 0,source_net_id:this.matchedNet?this.matchedNet.source_net_id:this.matchedPort?this._getSourceNetIdForPort(this.matchedPort):void 0,x:position2.x,y:position2.y});this.pcb_breakout_point_id=pcb_breakout_point2.pcb_breakout_point_id}_getPcbCircuitJsonBounds(){let position2=this._getGlobalPcbPositionBeforeLayout();return{center:{x:position2.x,y:position2.y},bounds:{left:position2.x,top:position2.y,right:position2.x,bottom:position2.y},width:0,height:0}}_setPositionFromLayout(newCenter){let{db}=this.root;this.pcb_breakout_point_id&&db.pcb_breakout_point.update(this.pcb_breakout_point_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_breakout_point_id)return;let point6=db.pcb_breakout_point.get(this.pcb_breakout_point_id);point6&&db.pcb_breakout_point.update(this.pcb_breakout_point_id,{x:point6.x+deltaX,y:point6.y+deltaY})}getPcbSize(){return{width:0,height:0}}},NetLabel=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"source_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 anchorPos=this._getGlobalSchematicPositionBeforeLayout(),connectedPorts=this._getConnectedPorts();if(connectedPorts.length===0)return"right";let connectedPortPosition=connectedPorts[0]._getGlobalSchematicPositionBeforeLayout(),dx2=connectedPortPosition.x-anchorPos.x,dy2=connectedPortPosition.y-anchorPos.y;if(Math.abs(dx2)>Math.abs(dy2)){if(dx2>0)return"right";if(dx2<0)return"left"}else{if(dy2>0)return"top";if(dy2<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=applyToPoint(this.parent?.computeSchematicGlobalTransform?.()??identity(),{x:0,y:0});return translate(portPos.x-parentCenter.x,portPos.y-parentCenter.y)}}return super.computeSchematicPropsTransform()}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,anchorPos=this._getGlobalSchematicPositionBeforeLayout(),net=this.getSubcircuit().selectOne(`net.${this._getNetName()}`),anchorSide=props.anchorSide??"right",center2=computeSchematicNetLabelCenter({anchor_position:anchorPos,anchor_side:anchorSide,text:props.net}),netLabel=db.schematic_net_label.insert({text:props.net,source_net_id:net.source_net_id,anchor_position:anchorPos,center:center2,anchor_side:this._getAnchorSide()});this.source_net_label_id=netLabel.source_net_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(){if(this.root?.schematicDisabled)return;let connectsTo=this._resolveConnectsTo();if(connectsTo)for(let connection of connectsTo)this.add(new Trace3({from:connection,to:`net.${this._getNetName()}`}))}doInitialSchematicTraceRender(){if(!this.root?._featureMspSchematicTraceRouting||this.root?.schematicDisabled)return;let{db}=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=db.source_trace.list().find(st4=>st4.connected_source_net_ids?.includes(net.source_net_id)&&st4.connected_source_port_ids?.includes(port.source_port_id??""));if(candidateSourceTrace&&(existingTraceForThisConnection=db.schematic_trace.list().some(t5=>t5.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 i2=0;i2<path.length-1;i2++)edges.push({from:{x:path[i2].x,y:path[i2].y},to:{x:path[i2+1].x,y:path[i2+1].y}});let source_trace_id,subcircuit_connectivity_map_key;if(net?.source_net_id&&port.source_port_id){let st4=db.source_trace.list().find(s2=>s2.connected_source_net_ids?.includes(net.source_net_id)&&s2.connected_source_port_ids?.includes(port.source_port_id));source_trace_id=st4?.source_trace_id,subcircuit_connectivity_map_key=st4?.subcircuit_connectivity_map_key||db.source_net.get(net.source_net_id)?.subcircuit_connectivity_map_key}db.schematic_trace.insert({source_trace_id,edges,junctions:[],subcircuit_connectivity_map_key}),db.schematic_port.update(port.schematic_port_id,{is_connected:!0})}}},SilkscreenCircle=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_circle_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenCircle",zodProps:silkscreenCircleProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),layer=maybeFlipLayer(props.layer??"top");if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for SilkscreenCircle. Must be "top" or "bottom".`);let subcircuit=this.getSubcircuit(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_circle2=db.pcb_silkscreen_circle.insert({pcb_component_id,layer,center:{x:position2.x,y:position2.y},radius:props.radius,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,stroke_width:props.strokeWidth??.1});this.pcb_silkscreen_circle_id=pcb_silkscreen_circle2.pcb_silkscreen_circle_id}getPcbSize(){let{_parsedProps:props}=this,diameter=props.radius*2;return{width:diameter,height:diameter}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_circle_id)return;let circle2=db.pcb_silkscreen_circle.get(this.pcb_silkscreen_circle_id);circle2&&db.pcb_silkscreen_circle.update(this.pcb_silkscreen_circle_id,{center:{x:circle2.center.x+deltaX,y:circle2.center.y+deltaY}})}},SilkscreenRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_rect_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenRect",zodProps:silkscreenRectProps}}_isRotated90Degrees(){let globalTransform=this._computePcbGlobalTransformBeforeLayout(),normalizedRotationDegrees=(decomposeTSR(globalTransform).rotation.angle*180/Math.PI%360+360)%360,rotationTolerance=.01;return Math.abs(normalizedRotationDegrees-90)<rotationTolerance||Math.abs(normalizedRotationDegrees-270)<rotationTolerance}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=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 SilkscreenRect. Must be "top" or "bottom".`);let subcircuit=this.getSubcircuit(),position2=this._getGlobalPcbPositionBeforeLayout(),isRotated90Degrees=this._isRotated90Degrees(),finalWidth=isRotated90Degrees?props.height:props.width,finalHeight=isRotated90Degrees?props.width:props.height,pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_rect2=db.pcb_silkscreen_rect.insert({pcb_component_id,layer,center:{x:position2.x,y:position2.y},width:finalWidth,height:finalHeight,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this?.getGroup()?.pcb_group_id??void 0,stroke_width:props.strokeWidth??.1,is_filled:props.filled??!1,corner_radius:props.cornerRadius??void 0});this.pcb_silkscreen_rect_id=pcb_silkscreen_rect2.pcb_silkscreen_rect_id}getPcbSize(){let{_parsedProps:props}=this;return this._isRotated90Degrees()?{width:props.height,height:props.width}:{width:props.width,height:props.height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_rect_id)return;let rect=db.pcb_silkscreen_rect.get(this.pcb_silkscreen_rect_id);rect&&db.pcb_silkscreen_rect.update(this.pcb_silkscreen_rect_id,{center:{x:rect.center.x+deltaX,y:rect.center.y+deltaY}})}},SilkscreenLine=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_line_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenLine",zodProps:silkscreenLineProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=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 SilkscreenLine. Must be "top" or "bottom".`);let subcircuit=this.getSubcircuit(),transform5=this._computePcbGlobalTransformBeforeLayout(),p12=applyToPoint(transform5,{x:props.x1,y:props.y1}),p22=applyToPoint(transform5,{x:props.x2,y:props.y2}),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_line2=db.pcb_silkscreen_line.insert({pcb_component_id,layer,x1:p12.x,y1:p12.y,x2:p22.x,y2:p22.y,stroke_width:props.strokeWidth??.1,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_silkscreen_line_id=pcb_silkscreen_line2.pcb_silkscreen_line_id}getPcbSize(){let{_parsedProps:props}=this,width=Math.abs(props.x2-props.x1),height=Math.abs(props.y2-props.y1);return{width,height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_line_id)return;let line2=db.pcb_silkscreen_line.get(this.pcb_silkscreen_line_id);line2&&db.pcb_silkscreen_line.update(this.pcb_silkscreen_line_id,{x1:line2.x1+deltaX,y1:line2.y1+deltaY,x2:line2.x2+deltaX,y2:line2.y2+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}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,layer:maybeFlipLayer(props.layer||"top"),shape:"circle",x:position2.x,y:position2.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_smtpad2.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}=this.root;db.pcb_smtpad.update(this.pcb_smtpad_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_smtpad_id)return;let pad2=db.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"&&db.pcb_smtpad.update(this.pcb_smtpad_id,{points:pad2.points.map(p4=>({x:p4.x+deltaX,y:p4.y+deltaY}))}))}},Via=class extends PrimitiveComponent2{constructor(props){super(props);__publicField(this,"pcb_via_id",null);__publicField(this,"matchedPort",null);__publicField(this,"isPcbPrimitive",!0);__publicField(this,"source_manually_placed_via_id",null);__publicField(this,"subcircuit_connectivity_map_key",null);let layers=this._getLayers();this._parsedProps.layers=layers,this.initPorts()}get config(){return{componentName:"Via",zodProps:viaProps}}getAvailablePcbLayers(){return["top","inner1","inner2","bottom"]}_getResolvedViaDiameters(pcbStyle2){return getViaDiameterDefaultsWithOverrides({holeDiameter:this._parsedProps.holeDiameter,padDiameter:this._parsedProps.outerDiameter},pcbStyle2)}getPcbSize(){let pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{padDiameter}=this._getResolvedViaDiameters(pcbStyle2);return{width:padDiameter,height:padDiameter}}_getPcbCircuitJsonBounds(){let{db}=this.root,via=db.pcb_via.get(this.pcb_via_id),size2=this.getPcbSize();return{center:{x:via.x,y:via.y},bounds:{left:via.x-size2.width/2,top:via.y-size2.height/2,right:via.x+size2.width/2,bottom:via.y+size2.height/2},width:size2.width,height:size2.height}}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_via.update(this.pcb_via_id,{x:newCenter.x,y:newCenter.y})}_getLayers(){let{fromLayer="top",toLayer="bottom"}=this._parsedProps;return fromLayer===toLayer?[fromLayer]:[fromLayer,toLayer]}initPorts(){let layers=this._parsedProps.layers;for(let layer of layers){let port2=new Port({name:layer,layer});port2.registerMatch(this),this.add(port2)}let port=new Port({name:"pin1"});port.registerMatch(this),this.add(port)}_getConnectedNetOrTrace(){let connectsTo=this._parsedProps.connectsTo;if(!connectsTo)return null;let subcircuit=this.getSubcircuit(),selectors=Array.isArray(connectsTo)?connectsTo:[connectsTo];for(let selector of selectors)if(selector.startsWith("net.")){let net=subcircuit.selectOne(selector,{type:"net"});if(net)return net}return null}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{padDiameter}=this._getResolvedViaDiameters(pcbStyle2),position2=this._getGlobalPcbPositionBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_component2=db.pcb_component.insert({center:position2,width:padDiameter,height:padDiameter,layer:this._parsedProps.fromLayer??"top",rotation:0,source_component_id:this.source_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,obstructs_within_bounds:!0});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,group=this.getGroup(),subcircuit=this.getSubcircuit(),source_via=db.source_manually_placed_via.insert({source_group_id:group?.source_group_id,source_net_id:props.net??"",subcircuit_id:subcircuit?.subcircuit_id??void 0});this.source_component_id=source_via.source_manually_placed_via_id}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{holeDiameter,padDiameter}=this._getResolvedViaDiameters(pcbStyle2),position2=this._getGlobalPcbPositionBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_via2=db.pcb_via.insert({x:position2.x,y:position2.y,hole_diameter:holeDiameter,outer_diameter:padDiameter,layers:["bottom","top"],from_layer:this._parsedProps.fromLayer||"bottom",to_layer:this._parsedProps.toLayer||"top",subcircuit_id:subcircuit?.subcircuit_id??void 0,subcircuit_connectivity_map_key:this.subcircuit_connectivity_map_key??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,net_is_assignable:this._parsedProps.netIsAssignable??void 0});this.pcb_via_id=pcb_via2.pcb_via_id}},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(){this.root?.pcbDisabled||this._queueAsyncEffect("PcbCopperPourRender",async()=>{let{db}=this.root,{_parsedProps:props}=this,net=this.getSubcircuit().selectOne(props.connectsTo);if(!net||!net.source_net_id){this.renderError(`Net "${props.connectsTo}" not found for copper pour`);return}let subcircuit=this.getSubcircuit(),sourceNet=db.toArray().filter(elm=>elm.type==="source_net"&&elm.name===net.name)[0]||"",clearance=props.clearance??.2,inputProblem=convertCircuitJsonToInputProblem(db.toArray(),{layer:props.layer,pour_connectivity_key:sourceNet.subcircuit_connectivity_map_key||"",pad_margin:props.padMargin??clearance,trace_margin:props.traceMargin??clearance,board_edge_margin:props.boardEdgeMargin??clearance,cutout_margin:props.cutoutMargin??clearance}),solver=new CopperPourPipelineSolver(inputProblem);this.root.emit("solver:started",{solverName:"CopperPourPipelineSolver",solverParams:inputProblem,componentName:this.props.name});let{brep_shapes}=solver.getOutput(),coveredWithSolderMask=props.coveredWithSolderMask??!1;for(let brep_shape2 of brep_shapes)db.pcb_copper_pour.insert({shape:"brep",layer:props.layer,brep_shape:brep_shape2,source_net_id:net.source_net_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,covered_with_solder_mask:coveredWithSolderMask})})}},CopperText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isPcbPrimitive",!0);__publicField(this,"pcb_copper_text_id",null)}get config(){return{componentName:"CopperText",zodProps:copperTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,container=this.getPrimitiveContainer(),position2=this._getGlobalPcbPositionBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_copper_text2=db.pcb_copper_text.insert({anchor_alignment:props.anchorAlignment,anchor_position:{x:position2.x,y:position2.y},font:"tscircuit2024",font_size:props.fontSize,layer:props.layer??"top",text:normalizeTextForCircuitJson(props.text),ccw_rotation:props.pcbRotation,is_mirrored:props.mirrored,is_knockout:props.knockout,pcb_component_id:container.pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_copper_text_id=pcb_copper_text2.pcb_copper_text_id}getPcbSize(){let{_parsedProps:props}=this,fontSize=props.fontSize??1,textWidth=(props.text??"").length*fontSize,textHeight=fontSize;return{width:textWidth*fontSize,height:textHeight*fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_copper_text_id)return;let text=db.pcb_copper_text.get(this.pcb_copper_text_id);text&&db.pcb_copper_text.update(this.pcb_copper_text_id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}},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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:"simple_power_source",capacity:props.capacity,supplier_part_numbers:props.supplierPartNumbers,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;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"),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 i2=1;i2<=pinCount;i2++){let rawLabel=Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels[i2-1]:this._parsedProps.pinLabels?.[`pin${i2}`];if(rawLabel){let primaryLabel=Array.isArray(rawLabel)?rawLabel[0]:rawLabel,otherLabels=Array.isArray(rawLabel)?rawLabel.slice(1):[];this.add(new Port({pinNumber:i2,name:primaryLabel,aliases:[`pin${i2}`,...otherLabels]}))}else this.add(new Port({pinNumber:i2,name:`pin${i2}`}))}}_getSchematicPortArrangement(){let pinCount=this._parsedProps.pinCount??1,facingDirection=this._parsedProps.schFacingDirection??this._parsedProps.facingDirection??"right",schPinArrangement=this._parsedProps.schPinArrangement;return facingDirection==="left"?{leftSide:{direction:schPinArrangement?.leftSide?.direction??"top-to-bottom",pins:schPinArrangement?.leftSide?.pins??Array.from({length:pinCount},(_5,i2)=>`pin${i2+1}`)}}:{rightSide:{direction:schPinArrangement?.rightSide?.direction??"top-to-bottom",pins:schPinArrangement?.rightSide?.pins??Array.from({length:pinCount},(_5,i2)=>`pin${i2+1}`)}}}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_pin_header",name:this.name,supplier_part_numbers:props.supplierPartNumbers,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}=this.root,{_parsedProps:props}=this,pinVariant=props.pinVariant||"no_ground",source_component=db.source_component.insert({ftype:"simple_resonator",name:this.name,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}=this.root,{_parsedProps:props}=this,pinVariant=props.pinVariant||"two_pin",source_component=db.source_component.insert({ftype:"simple_potentiometer",name:this.name,max_resistance:props.maxResistance,pin_variant:pinVariant,are_pins_interchangeable:pinVariant==="two_pin",display_name:props.displayName});this.source_component_id=source_component.source_component_id}},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=Vf[this._getSchematicSymbolNameOrThrow()],symPort1=symbol.ports.find(p4=>p4.labels.includes("1")),symPort2=symbol.ports.find(p4=>p4.labels.includes("2")),ports=this.selectAll("port"),pin1Port=ports.find(p4=>p4.props.pinNumber===1),pin2Port=ports.find(p4=>p4.props.pinNumber===2),pin3Port=ports.find(p4=>p4.props.pinNumber===3),pin4Port=ports.find(p4=>p4.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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:FTYPE.simple_push_button,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},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"],pin2:["top1","2","gnd1"],pin3:["right1","3"],pin4:["bottom1","4","gnd2"]}:{pin1:["pos","left"],pin2:["neg","right"]};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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:"simple_crystal",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}},Mosfet=class extends NormalComponent3{get config(){let mosfetMode=this.props.mosfetMode==="depletion"?"d":"e",baseSymbolName=`${this.props.channelType}_channel_${mosfetMode}_mosfet_transistor`;return{componentName:"Mosfet",schematicSymbolName:this.props.symbolName??baseSymbolName,zodProps:mosfetProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_mosfet",name:this.name,mosfet_mode:props.mosfetMode,channel_type:props.channelType,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},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)}get config(){let hasPowerConnections=this.props.connections?.positive_supply||this.props.connections?.negative_supply;return{componentName:"OpAmp",schematicSymbolName:this.props.symbolName?this.props.symbolName:hasPowerConnections?"opamp_with_power":"opamp_no_power",zodProps:opampProps,sourceFtype:"simple_op_amp"}}initPorts(){super.initPorts({pinCount:5,additionalAliases:{pin1:["non_inverting_input"],pin2:["inverting_input"],pin3:["output"],pin4:["positive_supply","vcc","vdd"],pin5:["negative_supply","vee","vss","gnd"]}})}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_op_amp",name:this.name,supplier_part_numbers:props.supplierPartNumbers,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db}=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||db.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})}};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}=this.root,props=this._parsedProps??{},source_component=db.source_component.insert({ftype:"simple_switch",name:this.name,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}=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),db.simulation_switch.insert(simulationSwitch)}},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}=this.root,{_parsedProps:props}=this,{padShape,holeDiameter,footprintVariant,padDiameter,width,height}=this._getPropsWithDefaults(),source_component=db.source_component.insert({ftype:FTYPE.simple_test_point,name:this.name,supplier_part_numbers:props.supplierPartNumbers,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}},SchematicText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_text_id")}get config(){return{componentName:"SchematicText",zodProps:schematicTextProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_text2=db.schematic_text.insert({schematic_symbol_id,anchor:props.anchor??"center",text:normalizeTextForCircuitJson(props.text),font_size:props.fontSize,color:props.color||"#000000",position:{x:globalPos.x,y:globalPos.y},rotation:props.schRotation??0});this.schematic_text_id=schematic_text2.schematic_text_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_text_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,text=db.schematic_text.get(this.schematic_text_id);if(!text)return;let newPosition=applyToPoint(transform5,text.position);db.schematic_text.update(this.schematic_text_id,{position:{x:newPosition.x,y:newPosition.y}})}},SchematicLine=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_line_id")}get config(){return{componentName:"SchematicLine",zodProps:schematicLineProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_line2=db.schematic_line.insert({schematic_component_id,schematic_symbol_id,x1:props.x1+globalPos.x,y1:props.y1+globalPos.y,x2:props.x2+globalPos.x,y2:props.y2+globalPos.y,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_dashed:!1,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_line_id=schematic_line2.schematic_line_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_line_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,line2=db.schematic_line.get(this.schematic_line_id);if(!line2)return;let p12=applyToPoint(transform5,{x:line2.x1,y:line2.y1}),p22=applyToPoint(transform5,{x:line2.x2,y:line2.y2});db.schematic_line.update(this.schematic_line_id,{x1:p12.x,y1:p12.y,x2:p22.x,y2:p22.y})}},SchematicRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_rect_id")}get config(){return{componentName:"SchematicRect",zodProps:schematicRectProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_rect2=db.schematic_rect.insert({schematic_symbol_id,center:{x:globalPos.x,y:globalPos.y},width:props.width,height:props.height,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_filled:props.isFilled,schematic_component_id,is_dashed:props.isDashed,rotation:props.rotation??0,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_rect_id=schematic_rect2.schematic_rect_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_rect_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,rect=db.schematic_rect.get(this.schematic_rect_id);if(!rect)return;let topLeft=applyToPoint(transform5,{x:rect.center.x-rect.width/2,y:rect.center.y+rect.height/2}),bottomRight=applyToPoint(transform5,{x:rect.center.x+rect.width/2,y:rect.center.y-rect.height/2}),newWidth=Math.abs(bottomRight.x-topLeft.x),newHeight=Math.abs(topLeft.y-bottomRight.y),newCenter={x:(topLeft.x+bottomRight.x)/2,y:(topLeft.y+bottomRight.y)/2};db.schematic_rect.update(this.schematic_rect_id,{center:newCenter,width:newWidth,height:newHeight})}},SchematicArc=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_arc_id")}get config(){return{componentName:"SchematicArc",zodProps:schematicArcProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_arc2=db.schematic_arc.insert({schematic_component_id,schematic_symbol_id,center:{x:props.center.x+globalPos.x,y:props.center.y+globalPos.y},radius:props.radius,start_angle_degrees:props.startAngleDegrees,end_angle_degrees:props.endAngleDegrees,direction:props.direction,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_dashed:props.isDashed,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_arc_id=schematic_arc2.schematic_arc_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_arc_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,arc2=db.schematic_arc.get(this.schematic_arc_id);if(!arc2)return;let newCenter=applyToPoint(transform5,arc2.center),edgePoint=applyToPoint(transform5,{x:arc2.center.x+arc2.radius,y:arc2.center.y}),newRadius=Math.abs(edgePoint.x-newCenter.x);db.schematic_arc.update(this.schematic_arc_id,{center:{x:newCenter.x,y:newCenter.y},radius:newRadius})}},SchematicCircle=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_circle_id")}get config(){return{componentName:"SchematicCircle",zodProps:schematicCircleProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_circle2=db.schematic_circle.insert({schematic_component_id,schematic_symbol_id,center:{x:props.center.x+globalPos.x,y:props.center.y+globalPos.y},radius:props.radius,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_filled:props.isFilled,fill_color:props.fillColor,is_dashed:props.isDashed,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_circle_id=schematic_circle2.schematic_circle_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_circle_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,circle2=db.schematic_circle.get(this.schematic_circle_id);if(!circle2)return;let newCenter=applyToPoint(transform5,circle2.center),edgePoint=applyToPoint(transform5,{x:circle2.center.x+circle2.radius,y:circle2.center.y}),newRadius=Math.abs(edgePoint.x-newCenter.x);db.schematic_circle.update(this.schematic_circle_id,{center:{x:newCenter.x,y:newCenter.y},radius:newRadius})}};function sampleCurveSegment(segmentPath,samplesPerUnit){let commander=new Ci3(segmentPath),length7=commander.getTotalLength(),numSamples=Math.max(2,Math.ceil(length7*samplesPerUnit)),points=[];for(let i2=1;i2<=numSamples;i2++){let t5=i2/numSamples*length7,point6=commander.getPointAtLength(t5);points.push({x:point6.x,y:point6.y})}return points}function svgPathToPoints(svgPath,samplesPerUnit=10){let pathCommander=new Ci3(svgPath);pathCommander.toAbsolute();let segments=pathCommander.segments,result=[],currentPoints=[],currentX=0,currentY=0,subpathStartX=0,subpathStartY=0;for(let segment2 of segments)switch(segment2[0]){case"M":{currentPoints.length>0&&result.push(currentPoints),currentX=segment2[1],currentY=segment2[2],subpathStartX=currentX,subpathStartY=currentY,currentPoints=[{x:currentX,y:currentY}];break}case"L":{currentX=segment2[1],currentY=segment2[2],currentPoints.push({x:currentX,y:currentY});break}case"H":{currentX=segment2[1],currentPoints.push({x:currentX,y:currentY});break}case"V":{currentY=segment2[1],currentPoints.push({x:currentX,y:currentY});break}case"Z":{(currentX!==subpathStartX||currentY!==subpathStartY)&¤tPoints.push({x:subpathStartX,y:subpathStartY}),currentX=subpathStartX,currentY=subpathStartY;break}case"C":{let endX=segment2[5],endY=segment2[6],segmentPath=`M ${currentX} ${currentY} C ${segment2[1]} ${segment2[2]} ${segment2[3]} ${segment2[4]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"S":{let endX=segment2[3],endY=segment2[4],segmentPath=`M ${currentX} ${currentY} S ${segment2[1]} ${segment2[2]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"Q":{let endX=segment2[3],endY=segment2[4],segmentPath=`M ${currentX} ${currentY} Q ${segment2[1]} ${segment2[2]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"T":{let endX=segment2[1],endY=segment2[2],segmentPath=`M ${currentX} ${currentY} T ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"A":{let endX=segment2[6],endY=segment2[7],segmentPath=`M ${currentX} ${currentY} A ${segment2[1]} ${segment2[2]} ${segment2[3]} ${segment2[4]} ${segment2[5]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}}return currentPoints.length>0&&result.push(currentPoints),result.map(points=>{let deduped=[];for(let point6 of points)(deduped.length===0||Math.abs(deduped[deduped.length-1].x-point6.x)>1e-9||Math.abs(deduped[deduped.length-1].y-point6.y)>1e-9)&&deduped.push(point6);return deduped})}var SchematicPath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_path_ids",[])}get config(){return{componentName:"SchematicPath",zodProps:schematicPathProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,subcircuit_id=this.getSubcircuit().subcircuit_id??void 0;if(this.schematic_path_ids=[],props.svgPath){let subpaths=svgPathToPoints(props.svgPath);for(let subpathPoints of subpaths){let schematic_path2=db.schematic_path.insert({schematic_component_id,schematic_symbol_id,points:subpathPoints.map(point6=>({x:point6.x+globalPos.x,y:point6.y+globalPos.y})),is_filled:props.isFilled,fill_color:props.fillColor,stroke_color:props.strokeColor,stroke_width:props.strokeWidth,subcircuit_id});this.schematic_path_ids.push(schematic_path2.schematic_path_id)}}else if(props.points&&props.points.length>0){let schematic_path2=db.schematic_path.insert({schematic_component_id,schematic_symbol_id,points:props.points.map(point6=>({x:point6.x+globalPos.x,y:point6.y+globalPos.y})),is_filled:props.isFilled,fill_color:props.fillColor,stroke_color:props.strokeColor,stroke_width:props.strokeWidth,subcircuit_id});this.schematic_path_ids.push(schematic_path2.schematic_path_id)}}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||this.schematic_path_ids.length===0)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root;for(let pathId of this.schematic_path_ids){let path=db.schematic_path.get(pathId);if(!path)continue;let newPoints=path.points.map(point6=>{let transformed=applyToPoint(transform5,point6);return{x:transformed.x,y:transformed.y}});db.schematic_path.update(pathId,{points:newPoints})}}};function getTitleAnchorAndPosition({anchor,x:x5,y:y5,width,height,isInside}){switch(anchor){case"top_left":return{x:x5,y:y5+height,textAnchor:isInside?"top_left":"bottom_left"};case"top_center":return{x:x5+width/2,y:y5+height,textAnchor:isInside?"top_center":"bottom_center"};case"top_right":return{x:x5+width,y:y5+height,textAnchor:isInside?"top_right":"bottom_right"};case"center_left":return{x:x5,y:y5+height/2,textAnchor:isInside?"center_left":"center_right"};case"center":return{x:x5+width/2,y:y5+height/2,textAnchor:"center"};case"center_right":return{x:x5+width,y:y5+height/2,textAnchor:isInside?"center_right":"center_left"};case"bottom_left":return{x:x5,y:y5,textAnchor:isInside?"bottom_left":"top_left"};case"bottom_center":return{x:x5+width/2,y:y5,textAnchor:isInside?"bottom_center":"top_center"};case"bottom_right":return{x:x5+width,y:y5,textAnchor:isInside?"bottom_right":"top_right"};default:return{x:x5+width/2,y:y5+height,textAnchor:"center"}}}var SchematicBox=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0)}get config(){return{componentName:"SchematicBox",zodProps:schematicBoxProps,shouldRenderAsSchematicBox:!0}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,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,x5,y5,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(p4=>p4.position.x),ys3=portsWithPosition.map(p4=>p4.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,x5=left+(props.schX??0),y5=top+(props.schY??0),centerX=x5+width/2,centerY=y5+height/2}else if(hasFixedSize){width=props.width,height=props.height;let center2=this._getGlobalSchematicPositionBeforeLayout();centerX=center2.x,centerY=center2.y,x5=centerX-width/2,y5=centerY-height/2}else return;if(db.schematic_box.insert({height,width,x:x5,y:y5,is_dashed:props.strokeStyle==="dashed"}),props.title){let isInside=props.titleInside,TITLE_PADDING=.1,anchor=props.titleAlignment,anchorPos=getTitleAnchorAndPosition({anchor,x:x5,y:y5,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;db.schematic_text.insert({anchor:textAnchor,text:props.title,font_size:props.titleFontSize??.18,color:props.titleColor??"#000000",position:{x:titleX,y:titleY},rotation:0})}}},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)return;let{db}=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 i2=0;i2<rows.length;i2++)grid4[i2]=[];for(let i2=0;i2<rows.length;i2++){let cells=rows[i2].children.filter(c3=>c3.componentName==="SchematicCell"),k4=0;for(let j4=0;j4<cells.length;j4++){for(;grid4[i2][k4];)k4++;let cell=cells[j4],colSpan=cell._parsedProps.colSpan??1,rowSpan=cell._parsedProps.rowSpan??1;for(let r4=0;r4<rowSpan;r4++)for(let c3=0;c3<colSpan;c3++)grid4[i2+r4]||(grid4[i2+r4]=[]),grid4[i2+r4][k4+c3]=cell;k4+=colSpan}}maxCols=Math.max(0,...grid4.map(r4=>r4.length));let rowHeights=rows.map((row,i2)=>row._parsedProps.height??1),colWidths=Array.from({length:maxCols},(_5,j4)=>{let maxWidth=0;for(let i2=0;i2<rows.length;i2++){let cell=grid4[i2]?.[j4];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=db.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||""});this.schematic_table_id=table.schematic_table_id;let processedCells=new Set,yOffset=0;for(let i2=0;i2<rows.length;i2++){let xOffset=0;for(let j4=0;j4<maxCols;j4++){let cell=grid4[i2]?.[j4];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[j4+c3];let cellHeight=0;for(let r4=0;r4<rowSpan;r4++)cellHeight+=rowHeights[i2+r4];db.schematic_table_cell.insert({schematic_table_id:this.schematic_table_id,start_row_index:i2,end_row_index:i2+rowSpan-1,start_column_index:j4,end_column_index:j4+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[j4]&&(xOffset+=colWidths[j4])}yOffset+=rowHeights[i2]}}},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}}},SymbolComponent=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isPrimitiveContainer",!0);__publicField(this,"schematic_symbol_id");__publicField(this,"userCoordinateToResizedSymbolTransformMat");__publicField(this,"schematicSymbolBoundsInUserCoordinates")}get config(){return{componentName:"Symbol",zodProps:symbolProps}}hasExplicitSize(){let{_parsedProps:props}=this;return props.width!==void 0||props.height!==void 0}doInitialSymbolContainerRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,schematic_symbol2=db.schematic_symbol.insert({name:props.name});this.schematic_symbol_id=schematic_symbol2.schematic_symbol_id}getSchematicSymbolBounds(){return this.schematicSymbolBoundsInUserCoordinates?this.schematicSymbolBoundsInUserCoordinates:(this._computeSchematicSymbolBounds(),this.schematicSymbolBoundsInUserCoordinates??null)}getUserCoordinateToResizedSymbolTransform(){return this.hasExplicitSize()?this.userCoordinateToResizedSymbolTransformMat?this.userCoordinateToResizedSymbolTransformMat:(this._computeUserCoordinateToResizedSymbolTransform(),this.userCoordinateToResizedSymbolTransformMat??null):null}_computeSchematicSymbolBounds(){if(this.root?.schematicDisabled)return;let{db}=this.root,schematicElements=[];for(let child of this.children)if(child.isSchematicPrimitive){if(child.componentName==="SchematicLine"){let line2=db.schematic_line.get(child.schematic_line_id);line2&&schematicElements.push(line2)}else if(child.componentName==="SchematicRect"){let rect=db.schematic_rect.get(child.schematic_rect_id);rect&&schematicElements.push(rect)}else if(child.componentName==="SchematicCircle"){let circle2=db.schematic_circle.get(child.schematic_circle_id);circle2&&schematicElements.push(circle2)}else if(child.componentName==="SchematicArc"){let arc2=db.schematic_arc.get(child.schematic_arc_id);arc2&&schematicElements.push(arc2)}else if(child.componentName==="SchematicText"){let text=db.schematic_text.get(child.schematic_text_id);text&&schematicElements.push(text)}else if(child.componentName==="SchematicPath"){let pathIds=child.schematic_path_ids;if(pathIds)for(let pathId of pathIds){let path=db.schematic_path.get(pathId);path&&schematicElements.push(path)}}}if(schematicElements.length===0)return;let bounds=getBoundsForSchematic(schematicElements);this.schematicSymbolBoundsInUserCoordinates=bounds}_computeUserCoordinateToResizedSymbolTransform(){let bounds=this.getSchematicSymbolBounds();if(!bounds)return;let{_parsedProps:props}=this,targetWidth=props.width,targetHeight=props.height;if(targetWidth===void 0&&targetHeight===void 0)return;let currentWidth=bounds.maxX-bounds.minX,currentHeight=bounds.maxY-bounds.minY;if(currentWidth===0&¤tHeight===0)return;let currentCenterX=(bounds.minX+bounds.maxX)/2,currentCenterY=(bounds.minY+bounds.maxY)/2,scaleX=targetWidth!==void 0&¤tWidth>0?targetWidth/currentWidth:1,scaleY=targetHeight!==void 0&¤tHeight>0?targetHeight/currentHeight:1,globalPos=this._getGlobalSchematicPositionBeforeLayout();this.userCoordinateToResizedSymbolTransformMat=compose(translate(globalPos.x,globalPos.y),scale(scaleX,scaleY),translate(-currentCenterX,-currentCenterY))}},AnalogSimulation=class extends PrimitiveComponent2{get config(){return{componentName:"AnalogSimulation",zodProps:analogSimulationProps}}doInitialSimulationRender(){let{db}=this.root,{duration,timePerStep}=this._parsedProps,durationMs=duration||10,timePerStepMs=timePerStep||.01;db.simulation_experiment.insert({name:"spice_transient_analysis",experiment_type:"spice_transient_analysis",end_time_ms:durationMs,time_per_step:timePerStepMs})}};function getLabelBounds(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 cx2,cy2,w4,h4;if(elm.type==="schematic_component")cx2=elm.center?.x,cy2=elm.center?.y,w4=elm.size?.width,h4=elm.size?.height;else if(elm.type==="schematic_text")cx2=elm.position?.x,cy2=elm.position?.y,w4=(elm.text?.length??0)*.1,h4=.2;else return null;return typeof cx2=="number"&&typeof cy2=="number"&&typeof w4=="number"&&typeof h4=="number"?{minX:cx2-w4/2,maxX:cx2+w4/2,minY:cy2-h4/2,maxY:cy2+h4/2}:null}function getOverlapArea(a2,b3){if(!doBoundsOverlap(a2,b3))return 0;let overlapWidth=Math.min(a2.maxX,b3.maxX)-Math.max(a2.minX,b3.minX),overlapHeight=Math.min(a2.maxY,b3.maxY)-Math.max(a2.minY,b3.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(a2=>a2!==defaultAlignment)],bestAlignment=defaultAlignment,minOverlapArea=1/0;for(let alignment of orderedAlignments){let labelBounds=getLabelBounds(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}=this.root,{connectsTo,name,referenceTo,color}=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(s2=>s2.replace(/^\./,"")).join(".")),this.finalProbeName=finalName??null;let{simulation_voltage_probe_id}=db.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});this.simulation_voltage_probe_id=simulation_voltage_probe_id}doInitialSchematicReplaceNetLabelsWithSymbols(){if(this.root?.schematicDisabled)return;let{db}=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 position2=port._getGlobalSchematicPositionAfterLayout(),targetTraceId=null;for(let trace of db.schematic_trace.list()){for(let edge of trace.edges)if(Math.abs(edge.from.x-position2.x)<1e-6&&Math.abs(edge.from.y-position2.y)<1e-6||Math.abs(edge.to.x-position2.x)<1e-6&&Math.abs(edge.to.y-position2.y)<1e-6){targetTraceId=trace.schematic_trace_id;break}if(targetTraceId)break}if(!targetTraceId)return;let probeName=this.finalProbeName,labelAlignment=selectBestLabelAlignment({probePosition:position2,labelText:probeName,schematicElements:[...db.schematic_component.list(),...db.schematic_text.list()],defaultAlignment:"top_right"}),schematic_voltage_probe2=db.schematic_voltage_probe.insert({name:probeName,position:position2,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_probe2.schematic_voltage_probe_id}},package_default3={name:"@tscircuit/core",type:"module",version:"0.0.1000",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 index.ts --format esm --dts",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","@tscircuit/capacity-autorouter":"^0.0.264","@tscircuit/checks":"^0.0.87","@tscircuit/circuit-json-util":"^0.0.77","@tscircuit/common":"^0.0.20","@tscircuit/copper-pour-solver":"^0.0.14","@tscircuit/footprinter":"^0.0.288","@tscircuit/infgrid-ijump-astar":"^0.0.35","@tscircuit/log-soup":"^1.0.2","@tscircuit/matchpack":"^0.0.16","@tscircuit/math-utils":"^0.0.29","@tscircuit/miniflex":"^0.0.4","@tscircuit/ngspice-spice-engine":"^0.0.8","@tscircuit/props":"^0.0.457","@tscircuit/schematic-match-adapt":"^0.0.16","@tscircuit/schematic-trace-solver":"^v0.0.45","@tscircuit/solver-utils":"^0.0.3","@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.371","circuit-json-to-bpc":"^0.0.13","circuit-json-to-connectivity-map":"^0.0.23","circuit-json-to-gltf":"^0.0.62","circuit-json-to-simple-3d":"^0.0.9","circuit-json-to-spice":"^0.0.33","circuit-to-svg":"^0.0.319",concurrently:"^9.1.2","connectivity-map":"^1.0.0",debug:"^4.3.6","eecircuit-engine":"^1.5.6",flatbush:"^4.5.0","graphics-debug":"^0.0.60",howfat:"^0.3.8","live-server":"^1.2.2","looks-same":"^9.0.1",minicssgrid:"^0.0.9","pkg-pr-new":"^0.0.37",poppygl:"^0.0.16",react:"^19.1.0","react-dom":"^19.1.0","schematic-symbols":"^0.0.208",spicey:"^0.0.14","ts-expect":"^1.3.0",tsup:"^8.2.4","@tscircuit/soup-util":"^0.0.41"},peerDependencies:{"@tscircuit/capacity-autorouter":"*","@tscircuit/checks":"*","@tscircuit/circuit-json-util":"*","@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":"*","schematic-symbols":"*",typescript:"^5.0.0"},dependencies:{"@flatten-js/core":"^1.6.2","@lume/kiwi":"^0.4.3","calculate-packing":"0.0.68","css-select":"5.1.0","format-si-unit":"^0.0.3",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"}},RootCircuit=class{constructor({platform,projectUrl}={}){__publicField(this,"firstChild",null);__publicField(this,"children");__publicField(this,"db");__publicField(this,"root",null);__publicField(this,"isRoot",!0);__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,"_eventListeners",{});this.children=[],this.db=su2([]),this.root=this,this.platform=platform,this.projectUrl=projectUrl,this.pcbDisabled=platform?.pcbDisabled??!1}get schematicDisabled(){return this._schematicDisabledOverride!==void 0?this._schematicDisabledOverride:this._getBoard()?._parsedProps?.schematicDisabled??!1}set schematicDisabled(value){this._schematicDisabledOverride=value}add(componentOrElm){let component;(0,import_react4.isValidElement)(componentOrElm)?component=createInstanceFromReactElement(componentOrElm):component=componentOrElm,this.children.push(component)}setPlatform(platform){this.platform={...this.platform,...platform}}_getBoard(){let directBoard=this.children.find(c3=>c3.componentName==="Board");if(directBoard)return directBoard}_guessRootComponent(){if(this.firstChild)return;if(this.children.length===0)throw new Error("Not able to guess root component: RootCircuit 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){this.firstChild=this.children[0];return}let group=new Group6({subcircuit:!0});group.parent=this,group.addAll(this.children),this.children=[group],this.firstChild=group}render(){this.firstChild||this._guessRootComponent();let{firstChild,db}=this;if(!firstChild)throw new Error("RootCircuit has no root component");firstChild.parent=this,firstChild.runRenderCycle(),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._hasIncompleteAsyncEffects();)await new Promise(resolve=>setTimeout(resolve,100)),this.render();this.emit("renderComplete")}_hasIncompleteAsyncEffects(){return this._asyncEffectPhaseById.size>0?!0:this.children.some(child=>child._hasIncompleteAsyncEffects())}_hasIncompleteAsyncEffectsForPhase(phase){return(this._asyncEffectIdsByPhase.get(phase)?.size??0)>0}getCircuitJson(){return this._hasRenderedAtleastOnce||this.render(),this.db.toArray()}toJson(){return this.getCircuitJson()}async getSvg(options){let circuitToSvg=await Promise.resolve().then(()=>(init_dist8(),dist_exports3)).catch(e4=>{throw new Error(`To use circuit.getSvg, you must install the "circuit-to-svg" package.
|
|
622
|
+
`),position2={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:position2})}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}=this.root,source_board2=db.source_board.insert({source_group_id:this.source_group_id,title:this.props.title||this.props.name});this.source_board_id=source_board2.source_board_id}doInitialInflateSubcircuitCircuitJson(){let{circuitJson,children}=this._parsedProps;inflateCircuitJson(this,circuitJson,children)}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=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"){let outlineBounds=getBoundsFromPoints(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 pcb_board2=db.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});this.pcb_board_id=pcb_board2.pcb_board_id,this._addBoardInformationToSilkscreen()}removePcbComponentRender(){let{db}=this.root;this.pcb_board_id&&(db.pcb_board.delete(this.pcb_board_id),this.pcb_board_id=null)}doInitialPcbDesignRuleChecks(){this.root?.pcbDisabled||this.getInheritedProperty("routingDisabled")||super.doInitialPcbDesignRuleChecks()}updatePcbDesignRuleChecks(){if(this.root?.pcbDisabled||this.getInheritedProperty("routingDisabled"))return;let{db}=this.root;if(!this._areChildSubcircuitsRouted()||this._drcChecksComplete)return;let runDrcChecks=circuitJson=>{let pcbTraceOverlappingErrors=checkEachPcbTraceNonOverlapping(circuitJson);for(let error of pcbTraceOverlappingErrors)db.pcb_trace_error.insert(error);let pcbPortNotConnectedErrors=checkEachPcbPortConnectedToPcbTraces(circuitJson);for(let error of pcbPortNotConnectedErrors)db.pcb_port_not_connected_error.insert(error);let pcbComponentOutsideErrors=checkPcbComponentsOutOfBoard(circuitJson);for(let error of pcbComponentOutsideErrors)db.pcb_component_outside_board_error.insert(error);let pcbTracesOutOfBoardErrors=checkPcbTracesOutOfBoard(circuitJson);for(let error of pcbTracesOutOfBoardErrors)db.pcb_trace_error.insert(error);let differentNetViaErrors=checkDifferentNetViaSpacing(circuitJson);for(let error of differentNetViaErrors)db.pcb_via_clearance_error.insert(error);let sameNetViaErrors=checkSameNetViaSpacing(circuitJson);for(let error of sameNetViaErrors)db.pcb_via_clearance_error.insert(error);let pcbComponentOverlapErrors=checkPcbComponentOverlap(circuitJson);for(let error of pcbComponentOverlapErrors)db.pcb_footprint_overlap_error.insert(error);let sourcePinMustBeConnectedErrors=checkPinMustBeConnected(circuitJson);for(let error of sourcePinMustBeConnectedErrors)db.source_pin_must_be_connected_error.insert(error)},subcircuitCircuitJson=db.subtree({subcircuit_id:this.subcircuit_id}).toArray();runDrcChecks(subcircuitCircuitJson),this._drcChecksComplete=!0}_emitRenderLifecycleEvent(phase,startOrEnd){super._emitRenderLifecycleEvent(phase,startOrEnd),startOrEnd==="start"&&this.root?.emit("board:renderPhaseStarted",{renderId:this._renderId,phase})}_repositionOnPcb(position2){let{db}=this.root,pcbBoard=this.pcb_board_id?db.pcb_board.get(this.pcb_board_id):null,oldPos=pcbBoard?.center;if(!oldPos){this.pcb_board_id&&db.pcb_board.update(this.pcb_board_id,{center:position2});return}let deltaX=position2.x-oldPos.x,deltaY=position2.y-oldPos.y;if(!(Math.abs(deltaX)<1e-6&&Math.abs(deltaY)<1e-6)&&this.pcb_board_id&&(db.pcb_board.update(this.pcb_board_id,{center:position2}),pcbBoard?.outline)){let outlineBounds=getBoundsFromPoints(pcbBoard.outline);if(outlineBounds){let oldOutlineCenter={x:(outlineBounds.minX+outlineBounds.maxX)/2,y:(outlineBounds.minY+outlineBounds.maxY)/2},outlineDeltaX=position2.x-oldOutlineCenter.x,outlineDeltaY=position2.y-oldOutlineCenter.y,newOutline=pcbBoard.outline.map(p4=>({x:p4.x+outlineDeltaX,y:p4.y+outlineDeltaY}));db.pcb_board.update(this.pcb_board_id,{outline:newOutline})}}}},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(p4=>point4(p4.x,p4.y))),is_ccw;if(outline.length>2){let p02=point4(outline[0].x,outline[0].y),p12=point4(outline[1].x,outline[1].y),segmentDir=vector$1(p02,p12).normalize(),normalToLeft=segmentDir.rotate(Math.PI/2),testPoint=p02.translate(segmentDir.multiply(segment(p02,p12).length/2)).translate(normalToLeft.multiply(.01));is_ccw=outlinePolygon.contains(testPoint)}else is_ccw=outlinePolygon.area()>0;for(let i2=0;i2<outline.length;i2++){let p1_=outline[i2],p2_=outline[(i2+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 k4=0;k4<numBitesInGap;k4++){let biteDist=firstBiteDistFromP1+k4*holeAndSpacing,pos=p12.translate(segmentDir.multiply(biteDist));mouseBiteHoles.push({x:pos.x,y:pos.y})}}}let p_prev_=outline[(i2-1+outline.length)%outline.length],p_next_=outline[(i2+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=[{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(p4=>point4(p4.x,p4.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}}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=getBoundsFromPoints(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 calculateOptimalGrid({boardsWithDims,availableWidth,availableHeight,boardGap,minCellWidth,minCellHeight}){let boardCount=boardsWithDims.length;if(boardCount===0)return{rows:0,cols:0};let maxBoardWidth=Math.max(...boardsWithDims.map(b3=>b3.width),minCellWidth),maxBoardHeight=Math.max(...boardsWithDims.map(b3=>b3.height),minCellHeight),maxCols=Math.max(1,Math.floor((availableWidth+boardGap)/(maxBoardWidth+boardGap))),maxRows=Math.max(1,Math.floor((availableHeight+boardGap)/(maxBoardHeight+boardGap))),bestCols=maxCols,bestRows=Math.ceil(boardCount/bestCols);return bestRows>maxRows&&(bestRows=maxRows,bestCols=Math.ceil(boardCount/bestRows),bestCols>maxCols&&(bestCols=maxCols,bestRows=Math.ceil(boardCount/bestCols))),{rows:Math.max(1,bestRows),cols:Math.max(1,bestCols)}}var packBoardsIntoGrid=({boards,db,row,col,cellWidth,cellHeight,boardGap,availablePanelWidth,availablePanelHeight})=>{let boardsWithDims=boards.map(board=>{let width,height;if(db&&board.pcb_board_id){let pcbBoard=db.pcb_board.get(board.pcb_board_id);pcbBoard?.width!==void 0&&pcbBoard?.height!==void 0&&(width=pcbBoard.width,height=pcbBoard.height)}if(width===void 0||height===void 0){let propsDims=getBoardDimensionsFromProps(board);width=propsDims.width,height=propsDims.height}return width===0&&height===0?null:{board,width,height}}).filter(b3=>b3!==null);if(boardsWithDims.length===0)return{positions:[],gridWidth:0,gridHeight:0};let explicitRow=row,explicitCol=col,cols,rows;if(explicitCol!==void 0)cols=explicitCol,rows=explicitRow??Math.ceil(boardsWithDims.length/cols);else if(explicitRow!==void 0)rows=explicitRow,cols=Math.ceil(boardsWithDims.length/rows);else if(availablePanelWidth!==void 0&&availablePanelHeight!==void 0){let result=calculateOptimalGrid({boardsWithDims,availableWidth:availablePanelWidth,availableHeight:availablePanelHeight,boardGap,minCellWidth:cellWidth?distance.parse(cellWidth):0,minCellHeight:cellHeight?distance.parse(cellHeight):0});cols=result.cols,rows=result.rows}else cols=Math.ceil(Math.sqrt(boardsWithDims.length)),rows=Math.ceil(boardsWithDims.length/cols);let colWidths=Array(cols).fill(0),rowHeights=Array(rows).fill(0);boardsWithDims.forEach((b3,i2)=>{let colIdx=i2%cols,rowIdx=Math.floor(i2/cols);rowIdx<rowHeights.length&&b3.height>rowHeights[rowIdx]&&(rowHeights[rowIdx]=b3.height),colIdx<colWidths.length&&b3.width>colWidths[colIdx]&&(colWidths[colIdx]=b3.width)});let minCellWidth=cellWidth?distance.parse(cellWidth):0,minCellHeight=cellHeight?distance.parse(cellHeight):0;for(let i2=0;i2<colWidths.length;i2++)colWidths[i2]=Math.max(colWidths[i2],minCellWidth);for(let i2=0;i2<rowHeights.length;i2++)rowHeights[i2]=Math.max(rowHeights[i2],minCellHeight);let totalGridWidth=colWidths.reduce((a2,b3)=>a2+b3,0)+(cols>1?(cols-1)*boardGap:0),totalGridHeight=rowHeights.reduce((a2,b3)=>a2+b3,0)+(rows>1?(rows-1)*boardGap:0),startX=-totalGridWidth/2,rowYOffsets=[-totalGridHeight/2];for(let i2=1;i2<rows;i2++)rowYOffsets.push(rowYOffsets[i2-1]+rowHeights[i2-1]+boardGap);let colXOffsets=[startX];for(let i2=1;i2<cols;i2++)colXOffsets.push(colXOffsets[i2-1]+colWidths[i2-1]+boardGap);let positions=[];return boardsWithDims.forEach((b3,i2)=>{let colIdx=i2%cols,rowIdx=Math.floor(i2/cols);if(rowIdx>=rowYOffsets.length||colIdx>=colXOffsets.length)return;let cellX=colXOffsets[colIdx],cellY=rowYOffsets[rowIdx],currentCellWidth=colWidths[colIdx],currentCellHeight=rowHeights[rowIdx],boardX=cellX+currentCellWidth/2,boardY=cellY+currentCellHeight/2;positions.push({board:b3.board,pos:{x:boardX,y:boardY}})}),{positions,gridWidth:totalGridWidth,gridHeight:totalGridHeight}},Subpanel=class _Subpanel extends Group6{constructor(){super(...arguments);__publicField(this,"pcb_panel_id",null);__publicField(this,"_tabsAndMouseBitesGenerated",!1);__publicField(this,"_cachedGridWidth",0);__publicField(this,"_cachedGridHeight",0)}get config(){return{componentName:"Subpanel",zodProps:subpanelProps}}get _errorComponentName(){return this.componentName.toLowerCase()}get isGroup(){return!0}get isSubcircuit(){return!0}add(component){if(component.lowercaseComponentName!=="board"&&component.lowercaseComponentName!=="subpanel")throw new Error(`<${this._errorComponentName}> can only contain <board> or <subpanel> elements`);super.add(component)}_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",childBoardInstances=this._getDirectBoardChildren();if(layoutMode!=="none")for(let board of childBoardInstances){let hasPcbX=board._parsedProps.pcbX!==void 0,hasPcbY=board._parsedProps.pcbY!==void 0;if(hasPcbX||hasPcbY){let properties=[];hasPcbX&&properties.push("pcbX"),hasPcbY&&properties.push("pcbY");let propertyNames=properties.join(" and ");this.root.db.source_property_ignored_warning.insert({source_component_id:board.source_component_id,property_name:propertyNames,message:`Board has manual positioning (${propertyNames}) but ${this._errorComponentName} layout mode is "${layoutMode}". Manual positioning will be ignored.`,error_type:"source_property_ignored_warning"})}}if(layoutMode==="none"&&childBoardInstances.length>1&&childBoardInstances.filter(board=>{let hasPcbX=board._parsedProps.pcbX!==void 0,hasPcbY=board._parsedProps.pcbY!==void 0;return!hasPcbX&&!hasPcbY}).length>1&&this.root.db.pcb_placement_error.insert({error_type:"pcb_placement_error",message:`Multiple boards in ${this._errorComponentName} without pcbX/pcbY positions. When layoutMode="none", each board must have explicit pcbX and pcbY coordinates to avoid overlapping. Either set pcbX/pcbY on each board, or 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}=packBoardsIntoGrid({boards:childBoardInstances,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{board,pos}of positions)board._panelPositionOffset=pos}doInitialPanelLayout(){if(this.root?.pcbDisabled)return;let{db}=this.root,childBoardInstances=this._getDirectBoardChildren();if((this._parsedProps.layoutMode??"none")==="grid"){for(let board of childBoardInstances)!board.pcb_board_id||!board._panelPositionOffset||db.pcb_board.update(board.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${board._panelPositionOffset.x}mm`,display_offset_y:`${board._panelPositionOffset.y}mm`});this._updatePanelDimensions()}else{let panelGlobalPos=this._getGlobalPcbPositionBeforeLayout();for(let board of childBoardInstances){let boardDb=db.pcb_board.get(board.pcb_board_id);if(!boardDb)continue;let relativeX=boardDb.center.x-panelGlobalPos.x,relativeY=boardDb.center.y-panelGlobalPos.y;db.pcb_board.update(board.pcb_board_id,{position_mode:"relative_to_panel_anchor",display_offset_x:`${relativeX}mm`,display_offset_y:`${relativeY}mm`})}}this._generateTabsAndMouseBites()}_updatePanelDimensions(){let{db}=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)db.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);db.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})}}}_generateTabsAndMouseBites(){if(this._tabsAndMouseBitesGenerated)return;let{db}=this.root,props=this._parsedProps,panelizationMethod=props.panelizationMethod??"none",childBoardInstances=this._getDirectBoardChildren();if(panelizationMethod!=="none"){let childBoardIds=childBoardInstances.map(c3=>c3.pcb_board_id).filter(id=>!!id),boardsInPanel=db.pcb_board.list().filter(b3=>childBoardIds.includes(b3.pcb_board_id));if(boardsInPanel.length===0)return;let tabWidth=props.tabWidth??DEFAULT_TAB_WIDTH,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)db.pcb_cutout.insert(tabCutout);for(let mouseBiteHole of mouseBiteHoles)db.pcb_hole.insert(mouseBiteHole)}this._tabsAndMouseBitesGenerated=!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}=this.root,props=this._parsedProps,inserted=db.pcb_panel.insert({width:props.width!==void 0?distance.parse(props.width):0,height:props.height!==void 0?distance.parse(props.height):0,center:this._getGlobalPcbPositionBeforeLayout(),covered_with_solder_mask:!(props.noSolderMask??!1)});this.pcb_panel_id=inserted.pcb_panel_id}_updatePanelDimensions(){let{db}=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)db.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);db.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}=this.root,props=this._parsedProps,currentPanel=db.pcb_panel.get(this.pcb_panel_id);db.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}=this.root,{_parsedProps:props}=this,source_component=db.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(){let rawCurrent=this._parsedProps.currentRating,rawVoltage=this._parsedProps.voltageRating,current2=typeof rawCurrent=="string"?parseFloat(rawCurrent):rawCurrent,voltage2=typeof rawVoltage=="string"?parseFloat(rawVoltage):rawVoltage;return`${formatSiUnit(current2)}A / ${formatSiUnit(voltage2)}V`}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,currentRating=typeof props.currentRating=="string"?parseFloat(props.currentRating):props.currentRating,voltageRating=typeof props.voltageRating=="string"?parseFloat(props.voltageRating):props.voltageRating,source_component=db.source_component.insert({name:this.name,ftype:FTYPE.simple_fuse,current_rating_amps:currentRating,voltage_rating_volts:voltageRating,display_current_rating:`${formatSiUnit(currentRating)}A`,display_voltage_rating:`${formatSiUnit(voltageRating)}V`,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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db.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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),pcb_component2=db.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:props.layer??"top",rotation:props.pcbRotation??0,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});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialPcbTraceRender(){let{db}=this.root,pcb_ports=db.pcb_port.list({pcb_component_id:this.pcb_component_id}),pinLabelToPortId={};for(let i2=0;i2<pcb_ports.length;i2++){let port=pcb_ports[i2],sourcePort=db.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(h4=>/^(pin)?\d+$/.test(h4));matchedHint&&(/^pin\d+$/.test(matchedHint)?pinLabel=matchedHint.replace(/^pin/,""):pinLabel=matchedHint)}pinLabelToPortId[pinLabel]=port.pcb_port_id}let traces=db.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}=this.root,source_component=db.source_component.insert({ftype:"interconnect",name:this.name,are_pins_interchangeable:!0,display_name:this._parsedProps.displayName});this.source_component_id=source_component.source_component_id}doInitialSourceParentAttachment(){let{db}=this.root,internallyConnectedPorts=this._getInternallyConnectedPins();for(let ports of internallyConnectedPorts){let sourcePortIds=ports.map(port=>port.source_port_id).filter(id=>id!==null);sourcePortIds.length>=2&&db.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)}_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(p4=>p4.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((a2,b3)=>a2-b3):props.bridged&&resolvedPinCount&&(bridgedPinNumbers=Array.from({length:resolvedPinCount},(_5,i2)=>i2+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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),source_component=db.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}=this.root,{_parsedProps:props}=this,{pcbX,pcbY}=this.getResolvedPcbPositionProp(),pcb_component2=db.pcb_component.insert({center:{x:pcbX,y:pcbY},width:2,height:3,layer:props.layer??"top",rotation:props.pcbRotation??0,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});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialPcbTraceRender(){let{db}=this.root,pcb_ports=db.pcb_port.list({pcb_component_id:this.pcb_component_id}),pinLabelToPortId={};for(let i2=0;i2<pcb_ports.length;i2++){let port=pcb_ports[i2],sourcePort=db.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(h4=>/^(pin)?\d+$/.test(h4));matchedHint&&(/^pin\d+$/.test(matchedHint)?pinLabel=matchedHint.replace(/^pin/,""):pinLabel=matchedHint)}pinLabelToPortId[pinLabel]=port.pcb_port_id}let traces=db.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))}},Led=class extends NormalComponent3{constructor(){super(...arguments);__publicField(this,"pos",this.portMap.pin1);__publicField(this,"anode",this.portMap.pin1);__publicField(this,"neg",this.portMap.pin2);__publicField(this,"cathode",this.portMap.pin2)}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(){super.initPorts({additionalAliases:{pin1:["anode","pos","left"],pin2:["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}=this.root,{_parsedProps:props}=this,source_component=db.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}},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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_power_source",name:this.name,voltage:props.voltage,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!1,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},VoltageSource=class extends NormalComponent3{constructor(){super(...arguments);__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(){}initPorts(){super.initPorts({additionalAliases:{pin1:["terminal1"],pin2:["terminal2"]}})}_getSchematicSymbolDisplayValue(){let{voltage:voltage2,frequency:frequency2}=this._parsedProps,parts=[];return voltage2!==void 0&&parts.push(`${formatSiUnit(voltage2)}V`),frequency2!==void 0&&parts.push(`${formatSiUnit(frequency2)}Hz`),parts.length>0?parts.join(" "):void 0}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.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,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db}=this.root,{_parsedProps:props}=this,terminal1Port=this.portMap.terminal1,terminal2Port=this.portMap.terminal2;db.simulation_voltage_source.insert({type:"simulation_voltage_source",is_dc_source:!1,terminal1_source_port_id:terminal1Port.source_port_id,terminal2_source_port_id:terminal2Port.source_port_id,voltage:props.voltage,frequency:props.frequency,peak_to_peak_voltage:props.peakToPeakVoltage,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle})}},CurrentSource=class extends NormalComponent3{constructor(){super(...arguments);__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(){}initPorts(){super.initPorts({additionalAliases:{pin1:["pos"],pin2:["neg"]}})}_getSchematicSymbolDisplayValue(){let{current:current2,frequency:frequency2,peakToPeakCurrent}=this._parsedProps,parts=[];return current2!==void 0&&parts.push(`${formatSiUnit(current2)}A`),peakToPeakCurrent!==void 0&&parts.push(`${formatSiUnit(peakToPeakCurrent)}A p-p`),frequency2!==void 0&&parts.push(`${formatSiUnit(frequency2)}Hz`),parts.length>0?parts.join(" "):void 0}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.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,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db}=this.root,{_parsedProps:props}=this,isAc=props.frequency!==void 0||props.peakToPeakCurrent!==void 0||props.waveShape!==void 0,posPort=this.portMap.pos,negPort=this.portMap.neg;if(isAc)db.simulation_current_source.insert({type:"simulation_current_source",is_dc_source:!1,terminal1_source_port_id:posPort.source_port_id,terminal2_source_port_id:negPort.source_port_id,current:props.current,frequency:props.frequency,peak_to_peak_current:props.peakToPeakCurrent,wave_shape:props.waveShape,phase:props.phase,duty_cycle:props.dutyCycle});else{if(props.current===void 0)return;db.simulation_current_source.insert({type:"simulation_current_source",is_dc_source:!0,positive_source_port_id:posPort.source_port_id,negative_source_port_id:negPort.source_port_id,current:props.current})}}},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}}},FabricationNoteRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"fabrication_note_rect_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNoteRect",zodProps:fabricationNoteRectProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),layer=maybeFlipLayer(props.layer??"top");if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for FabricationNoteRect. Must be "top" or "bottom".`);let pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,subcircuit=this.getSubcircuit(),hasStroke=props.hasStroke??(props.strokeWidth!==void 0&&props.strokeWidth!==null),fabrication_note_rect=db.pcb_fabrication_note_rect.insert({pcb_component_id,layer,color:props.color,center:{x:position2.x,y:position2.y},width:props.width,height:props.height,stroke_width:props.strokeWidth??1,is_filled:props.isFilled??!1,has_stroke:hasStroke,is_stroke_dashed:props.isStrokeDashed??!1,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,corner_radius:props.cornerRadius??void 0});this.fabrication_note_rect_id=fabrication_note_rect.pcb_fabrication_note_rect_id}getPcbSize(){let{_parsedProps:props}=this;return{width:props.width,height:props.height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.fabrication_note_rect_id)return;let rect=db.pcb_fabrication_note_rect.get(this.fabrication_note_rect_id);rect&&db.pcb_fabrication_note_rect.update(this.fabrication_note_rect_id,{center:{x:rect.center.x+deltaX,y:rect.center.y+deltaY}})}},FabricationNotePath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"fabrication_note_path_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNotePath",zodProps:fabricationNotePathProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,subcircuit=this.getSubcircuit(),{_parsedProps:props}=this,layer=props.layer??"top";if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for SilkscreenPath. Must be "top" or "bottom".`);let transform5=this._computePcbGlobalTransformBeforeLayout(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,fabrication_note_path=db.pcb_fabrication_note_path.insert({pcb_component_id,layer,color:props.color,route:props.route.map(p4=>{let transformedPosition=applyToPoint(transform5,{x:p4.x,y:p4.y});return{...p4,x:transformedPosition.x,y:transformedPosition.y}}),stroke_width:props.strokeWidth??.1,subcircuit_id:subcircuit?.subcircuit_id??void 0});this.fabrication_note_path_id=fabrication_note_path.pcb_fabrication_note_path_id}getPcbSize(){let{_parsedProps:props}=this;if(props.route.length===0)return{width:0,height:0};let xs3=props.route.map(point6=>typeof point6.x=="string"?parseFloat(point6.x):point6.x),ys3=props.route.map(point6=>typeof point6.y=="string"?parseFloat(point6.y):point6.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.fabrication_note_path_id)return;let path=db.pcb_fabrication_note_path.get(this.fabrication_note_path_id);path&&db.pcb_fabrication_note_path.update(this.fabrication_note_path_id,{route:path.route.map(p4=>({...p4,x:p4.x+deltaX,y:p4.y+deltaY}))})}},FabricationNoteText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_fabrication_note_text_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"FabricationNoteText",zodProps:fabricationNoteTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),container=this.getPrimitiveContainer(),subcircuit=this.getSubcircuit(),pcb_fabrication_note_text2=db.pcb_fabrication_note_text.insert({anchor_alignment:props.anchorAlignment,anchor_position:{x:position2.x,y:position2.y},font:props.font??"tscircuit2024",font_size:props.fontSize??1,layer:"top",color:props.color,text:normalizeTextForCircuitJson(props.text??""),pcb_component_id:container.pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_fabrication_note_text_id=pcb_fabrication_note_text2.pcb_fabrication_note_text_id}getPcbSize(){let{_parsedProps:props}=this,fontSize=typeof props.fontSize=="string"?parseFloat(props.fontSize):props.fontSize??1,charWidth=fontSize*.6;return{width:(props.text??"").length*charWidth,height:fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(this.pcb_fabrication_note_text_id){let text=db.pcb_fabrication_note_text.get(this.pcb_fabrication_note_text_id);text&&db.pcb_fabrication_note_text.update(this.pcb_fabrication_note_text_id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}}},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,transform5){if(typeof input2=="string"){let target=this.getSubcircuit().selectOne(input2);return target?target._getGlobalPcbPositionBeforeLayout():(this.renderError(`FabricationNoteDimension could not find selector "${input2}"`),applyToPoint(transform5,{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 applyToPoint(transform5,{x:numericX,y:numericY})}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(props.from,transform5),to3=this._resolvePoint(props.to,transform5),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=db.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}=this.root;if(!this.fabrication_note_dimension_id)return;let dimension=db.pcb_fabrication_note_dimension.get(this.fabrication_note_dimension_id);dimension&&db.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 transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform5),to3=this._resolvePoint(this._parsedProps.to,transform5);return{width:Math.abs(to3.x-from.x),height:Math.abs(to3.y-from.y)}}_formatDistanceText({from,to:to3,units}){let dx2=to3.x-from.x,dy2=to3.y-from.y,distanceInMillimeters=Math.sqrt(dx2*dx2+dy2*dy2),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}`}},PcbNoteLine=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_line_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteLine",zodProps:pcbNoteLineProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,subcircuit=this.getSubcircuit(),group=this.getGroup(),transform5=this._computePcbGlobalTransformBeforeLayout(),start=applyToPoint(transform5,{x:props.x1,y:props.y1}),end=applyToPoint(transform5,{x:props.x2,y:props.y2}),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,pcb_note_line2=db.pcb_note_line.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,x1:start.x,y1:start.y,x2:end.x,y2:end.y,stroke_width:props.strokeWidth??.1,color:props.color,is_dashed:props.isDashed});this.pcb_note_line_id=pcb_note_line2.pcb_note_line_id}getPcbSize(){let{_parsedProps:props}=this;return{width:Math.abs(props.x2-props.x1),height:Math.abs(props.y2-props.y1)}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_line_id)return;let line2=db.pcb_note_line.get(this.pcb_note_line_id);line2&&db.pcb_note_line.update(this.pcb_note_line_id,{x1:line2.x1+deltaX,y1:line2.y1+deltaY,x2:line2.x2+deltaX,y2:line2.y2+deltaY})}},PcbNoteRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_rect_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteRect",zodProps:pcbNoteRectProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),center2=applyToPoint(transform5,{x:0,y:0}),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,pcb_note_rect2=db.pcb_note_rect.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,center:center2,width:props.width,height:props.height,stroke_width:props.strokeWidth??.1,is_filled:props.isFilled??!1,has_stroke:props.hasStroke??!0,is_stroke_dashed:props.isStrokeDashed??!1,color:props.color,corner_radius:props.cornerRadius??void 0});this.pcb_note_rect_id=pcb_note_rect2.pcb_note_rect_id}getPcbSize(){let{_parsedProps:props}=this,width=typeof props.width=="string"?parseFloat(props.width):props.width,height=typeof props.height=="string"?parseFloat(props.height):props.height;return{width,height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_rect_id)return;let rect=db.pcb_note_rect.get(this.pcb_note_rect_id);rect&&db.pcb_note_rect.update(this.pcb_note_rect_id,{center:{x:rect.center.x+deltaX,y:rect.center.y+deltaY}})}},PcbNoteText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_text_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNoteText",zodProps:pcbNoteTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),anchorPosition=applyToPoint(transform5,{x:0,y:0}),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,pcb_note_text2=db.pcb_note_text.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,font:props.font??"tscircuit2024",font_size:props.fontSize??1,text:normalizeTextForCircuitJson(props.text),anchor_position:anchorPosition,anchor_alignment:props.anchorAlignment??"center",color:props.color});this.pcb_note_text_id=pcb_note_text2.pcb_note_text_id}getPcbSize(){let{_parsedProps:props}=this,fontSize=typeof props.fontSize=="string"?parseFloat(props.fontSize):props.fontSize??1,charWidth=fontSize*.6;return{width:props.text.length*charWidth,height:fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_text_id)return;let text=db.pcb_note_text.get(this.pcb_note_text_id);text&&db.pcb_note_text.update(this.pcb_note_text_id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}},PcbNotePath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_note_path_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"PcbNotePath",zodProps:pcbNotePathProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),subcircuit=this.getSubcircuit(),group=this.getGroup(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id??void 0,transformedRoute=props.route.map(point6=>{let{x:x5,y:y5,...rest}=point6,numericX=typeof x5=="string"?parseFloat(x5):x5,numericY=typeof y5=="string"?parseFloat(y5):y5,transformed=applyToPoint(transform5,{x:numericX,y:numericY});return{...rest,x:transformed.x,y:transformed.y}}),pcb_note_path2=db.pcb_note_path.insert({pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:group?.pcb_group_id??void 0,route:transformedRoute,stroke_width:props.strokeWidth??.1,color:props.color});this.pcb_note_path_id=pcb_note_path2.pcb_note_path_id}getPcbSize(){let{_parsedProps:props}=this;if(props.route.length===0)return{width:0,height:0};let xs3=props.route.map(point6=>typeof point6.x=="string"?parseFloat(point6.x):point6.x),ys3=props.route.map(point6=>typeof point6.y=="string"?parseFloat(point6.y):point6.y),minX=Math.min(...xs3),maxX=Math.max(...xs3),minY=Math.min(...ys3),maxY=Math.max(...ys3);return{width:maxX-minX,height:maxY-minY}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_note_path_id)return;let path=db.pcb_note_path.get(this.pcb_note_path_id);path&&db.pcb_note_path.update(this.pcb_note_path_id,{route:path.route.map(p4=>({...p4,x:p4.x+deltaX,y:p4.y+deltaY}))})}},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,transform5){if(typeof input2=="string"){let target=this.getSubcircuit().selectOne(`.${input2}`);return target?target._getGlobalPcbPositionBeforeLayout():(this.renderError(`PcbNoteDimension could not find selector "${input2}"`),applyToPoint(transform5,{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 applyToPoint(transform5,{x:numericX,y:numericY})}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(props.from,transform5),to3=this._resolvePoint(props.to,transform5),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_dimension2=db.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,color:props.color,arrow_size:props.arrowSize??1});this.pcb_note_dimension_id=pcb_note_dimension2.pcb_note_dimension_id}getPcbSize(){let transform5=this._computePcbGlobalTransformBeforeLayout(),from=this._resolvePoint(this._parsedProps.from,transform5),to3=this._resolvePoint(this._parsedProps.to,transform5);return{width:Math.abs(to3.x-from.x),height:Math.abs(to3.y-from.y)}}_formatDistanceText({from,to:to3,units}){let dx2=to3.x-from.x,dy2=to3.y-from.y,distanceInMillimeters=Math.sqrt(dx2*dx2+dy2*dy2),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}=this.root;if(!this.pcb_note_dimension_id)return;let dimension=db.pcb_note_dimension.get(this.pcb_note_dimension_id);dimension&&db.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}})}},Subcircuit=class extends Group6{constructor(props){super({...props,subcircuit:!0})}doInitialInflateSubcircuitCircuitJson(){let{circuitJson,children}=this._parsedProps;inflateCircuitJson(this,circuitJson,children)}},Breakout=class extends Group6{constructor(props){super({...props,subcircuit:!0})}doInitialPcbPrimitiveRender(){if(super.doInitialPcbPrimitiveRender(),this.root?.pcbDisabled)return;let{db}=this.root,props=this._parsedProps;if(!this.pcb_group_id)return;let pcb_group2=db.pcb_group.get(this.pcb_group_id),padLeft=props.paddingLeft??props.padding??0,padRight=props.paddingRight??props.padding??0,padTop=props.paddingTop??props.padding??0,padBottom=props.paddingBottom??props.padding??0;db.pcb_group.update(this.pcb_group_id,{width:(pcb_group2.width??0)+padLeft+padRight,height:(pcb_group2.height??0)+padTop+padBottom,center:{x:pcb_group2.center.x+(padRight-padLeft)/2,y:pcb_group2.center.y+(padTop-padBottom)/2}})}},BreakoutPoint=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_breakout_point_id",null);__publicField(this,"matchedPort",null);__publicField(this,"matchedNet",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"BreakoutPoint",zodProps:breakoutPointProps}}_matchConnection(){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}"`))}_getSourceTraceIdForPort(port){let{db}=this.root;return db.source_trace.list().find(st4=>st4.connected_source_port_ids.includes(port.source_port_id))?.source_trace_id}_getSourceNetIdForPort(port){let{db}=this.root;return db.source_trace.list().find(st4=>st4.connected_source_port_ids.includes(port.source_port_id))?.connected_source_net_ids[0]}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root;this._matchConnection();let position2=this._getGlobalPcbPositionBeforeLayout(),group=this.parent?.getGroup(),subcircuit=this.getSubcircuit();if(!group||!group.pcb_group_id)return;let pcb_breakout_point2=db.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._getSourceTraceIdForPort(this.matchedPort):void 0,source_net_id:this.matchedNet?this.matchedNet.source_net_id:this.matchedPort?this._getSourceNetIdForPort(this.matchedPort):void 0,x:position2.x,y:position2.y});this.pcb_breakout_point_id=pcb_breakout_point2.pcb_breakout_point_id}_getPcbCircuitJsonBounds(){let position2=this._getGlobalPcbPositionBeforeLayout();return{center:{x:position2.x,y:position2.y},bounds:{left:position2.x,top:position2.y,right:position2.x,bottom:position2.y},width:0,height:0}}_setPositionFromLayout(newCenter){let{db}=this.root;this.pcb_breakout_point_id&&db.pcb_breakout_point.update(this.pcb_breakout_point_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_breakout_point_id)return;let point6=db.pcb_breakout_point.get(this.pcb_breakout_point_id);point6&&db.pcb_breakout_point.update(this.pcb_breakout_point_id,{x:point6.x+deltaX,y:point6.y+deltaY})}getPcbSize(){return{width:0,height:0}}},NetLabel=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"source_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 anchorPos=this._getGlobalSchematicPositionBeforeLayout(),connectedPorts=this._getConnectedPorts();if(connectedPorts.length===0)return"right";let connectedPortPosition=connectedPorts[0]._getGlobalSchematicPositionBeforeLayout(),dx2=connectedPortPosition.x-anchorPos.x,dy2=connectedPortPosition.y-anchorPos.y;if(Math.abs(dx2)>Math.abs(dy2)){if(dx2>0)return"right";if(dx2<0)return"left"}else{if(dy2>0)return"top";if(dy2<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=applyToPoint(this.parent?.computeSchematicGlobalTransform?.()??identity(),{x:0,y:0});return translate(portPos.x-parentCenter.x,portPos.y-parentCenter.y)}}return super.computeSchematicPropsTransform()}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,anchorPos=this._getGlobalSchematicPositionBeforeLayout(),net=this.getSubcircuit().selectOne(`net.${this._getNetName()}`),anchorSide=props.anchorSide??"right",center2=computeSchematicNetLabelCenter({anchor_position:anchorPos,anchor_side:anchorSide,text:props.net}),netLabel=db.schematic_net_label.insert({text:props.net,source_net_id:net.source_net_id,anchor_position:anchorPos,center:center2,anchor_side:this._getAnchorSide()});this.source_net_label_id=netLabel.source_net_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(){if(this.root?.schematicDisabled)return;let connectsTo=this._resolveConnectsTo();if(connectsTo)for(let connection of connectsTo)this.add(new Trace3({from:connection,to:`net.${this._getNetName()}`}))}doInitialSchematicTraceRender(){if(!this.root?._featureMspSchematicTraceRouting||this.root?.schematicDisabled)return;let{db}=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=db.source_trace.list().find(st4=>st4.connected_source_net_ids?.includes(net.source_net_id)&&st4.connected_source_port_ids?.includes(port.source_port_id??""));if(candidateSourceTrace&&(existingTraceForThisConnection=db.schematic_trace.list().some(t5=>t5.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 i2=0;i2<path.length-1;i2++)edges.push({from:{x:path[i2].x,y:path[i2].y},to:{x:path[i2+1].x,y:path[i2+1].y}});let source_trace_id,subcircuit_connectivity_map_key;if(net?.source_net_id&&port.source_port_id){let st4=db.source_trace.list().find(s2=>s2.connected_source_net_ids?.includes(net.source_net_id)&&s2.connected_source_port_ids?.includes(port.source_port_id));source_trace_id=st4?.source_trace_id,subcircuit_connectivity_map_key=st4?.subcircuit_connectivity_map_key||db.source_net.get(net.source_net_id)?.subcircuit_connectivity_map_key}db.schematic_trace.insert({source_trace_id,edges,junctions:[],subcircuit_connectivity_map_key}),db.schematic_port.update(port.schematic_port_id,{is_connected:!0})}}},SilkscreenCircle=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_circle_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenCircle",zodProps:silkscreenCircleProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),layer=maybeFlipLayer(props.layer??"top");if(layer!=="top"&&layer!=="bottom")throw new Error(`Invalid layer "${layer}" for SilkscreenCircle. Must be "top" or "bottom".`);let subcircuit=this.getSubcircuit(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_circle2=db.pcb_silkscreen_circle.insert({pcb_component_id,layer,center:{x:position2.x,y:position2.y},radius:props.radius,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,stroke_width:props.strokeWidth??.1});this.pcb_silkscreen_circle_id=pcb_silkscreen_circle2.pcb_silkscreen_circle_id}getPcbSize(){let{_parsedProps:props}=this,diameter=props.radius*2;return{width:diameter,height:diameter}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_circle_id)return;let circle2=db.pcb_silkscreen_circle.get(this.pcb_silkscreen_circle_id);circle2&&db.pcb_silkscreen_circle.update(this.pcb_silkscreen_circle_id,{center:{x:circle2.center.x+deltaX,y:circle2.center.y+deltaY}})}},SilkscreenRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_rect_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenRect",zodProps:silkscreenRectProps}}_isRotated90Degrees(){let globalTransform=this._computePcbGlobalTransformBeforeLayout(),normalizedRotationDegrees=(decomposeTSR(globalTransform).rotation.angle*180/Math.PI%360+360)%360,rotationTolerance=.01;return Math.abs(normalizedRotationDegrees-90)<rotationTolerance||Math.abs(normalizedRotationDegrees-270)<rotationTolerance}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=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 SilkscreenRect. Must be "top" or "bottom".`);let subcircuit=this.getSubcircuit(),position2=this._getGlobalPcbPositionBeforeLayout(),isRotated90Degrees=this._isRotated90Degrees(),finalWidth=isRotated90Degrees?props.height:props.width,finalHeight=isRotated90Degrees?props.width:props.height,pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_rect2=db.pcb_silkscreen_rect.insert({pcb_component_id,layer,center:{x:position2.x,y:position2.y},width:finalWidth,height:finalHeight,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this?.getGroup()?.pcb_group_id??void 0,stroke_width:props.strokeWidth??.1,is_filled:props.filled??!1,corner_radius:props.cornerRadius??void 0});this.pcb_silkscreen_rect_id=pcb_silkscreen_rect2.pcb_silkscreen_rect_id}getPcbSize(){let{_parsedProps:props}=this;return this._isRotated90Degrees()?{width:props.height,height:props.width}:{width:props.width,height:props.height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_rect_id)return;let rect=db.pcb_silkscreen_rect.get(this.pcb_silkscreen_rect_id);rect&&db.pcb_silkscreen_rect.update(this.pcb_silkscreen_rect_id,{center:{x:rect.center.x+deltaX,y:rect.center.y+deltaY}})}},SilkscreenLine=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"pcb_silkscreen_line_id",null);__publicField(this,"isPcbPrimitive",!0)}get config(){return{componentName:"SilkscreenLine",zodProps:silkscreenLineProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=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 SilkscreenLine. Must be "top" or "bottom".`);let subcircuit=this.getSubcircuit(),transform5=this._computePcbGlobalTransformBeforeLayout(),p12=applyToPoint(transform5,{x:props.x1,y:props.y1}),p22=applyToPoint(transform5,{x:props.x2,y:props.y2}),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_silkscreen_line2=db.pcb_silkscreen_line.insert({pcb_component_id,layer,x1:p12.x,y1:p12.y,x2:p22.x,y2:p22.y,stroke_width:props.strokeWidth??.1,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:subcircuit?.getGroup()?.pcb_group_id??void 0});this.pcb_silkscreen_line_id=pcb_silkscreen_line2.pcb_silkscreen_line_id}getPcbSize(){let{_parsedProps:props}=this,width=Math.abs(props.x2-props.x1),height=Math.abs(props.y2-props.y1);return{width,height}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_silkscreen_line_id)return;let line2=db.pcb_silkscreen_line.get(this.pcb_silkscreen_line_id);line2&&db.pcb_silkscreen_line.update(this.pcb_silkscreen_line_id,{x1:line2.x1+deltaX,y1:line2.y1+deltaY,x2:line2.x2+deltaX,y2:line2.y2+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}=this.root,{_parsedProps:props}=this,position2=this._getGlobalPcbPositionBeforeLayout(),{maybeFlipLayer}=this._getPcbPrimitiveFlippedHelpers(),pcb_component_id=this.parent?.pcb_component_id??this.getPrimitiveContainer()?.pcb_component_id,pcb_smtpad2=db.pcb_smtpad.insert({pcb_component_id,layer:maybeFlipLayer(props.layer||"top"),shape:"circle",x:position2.x,y:position2.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_smtpad2.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}=this.root;db.pcb_smtpad.update(this.pcb_smtpad_id,{x:newCenter.x,y:newCenter.y})}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_smtpad_id)return;let pad2=db.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"&&db.pcb_smtpad.update(this.pcb_smtpad_id,{points:pad2.points.map(p4=>({x:p4.x+deltaX,y:p4.y+deltaY}))}))}},Via=class extends PrimitiveComponent2{constructor(props){super(props);__publicField(this,"pcb_via_id",null);__publicField(this,"matchedPort",null);__publicField(this,"isPcbPrimitive",!0);__publicField(this,"source_manually_placed_via_id",null);__publicField(this,"subcircuit_connectivity_map_key",null);let layers=this._getLayers();this._parsedProps.layers=layers,this.initPorts()}get config(){return{componentName:"Via",zodProps:viaProps}}getAvailablePcbLayers(){return["top","inner1","inner2","bottom"]}_getResolvedViaDiameters(pcbStyle2){return getViaDiameterDefaultsWithOverrides({holeDiameter:this._parsedProps.holeDiameter,padDiameter:this._parsedProps.outerDiameter},pcbStyle2)}getPcbSize(){let pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{padDiameter}=this._getResolvedViaDiameters(pcbStyle2);return{width:padDiameter,height:padDiameter}}_getPcbCircuitJsonBounds(){let{db}=this.root,via=db.pcb_via.get(this.pcb_via_id),size2=this.getPcbSize();return{center:{x:via.x,y:via.y},bounds:{left:via.x-size2.width/2,top:via.y-size2.height/2,right:via.x+size2.width/2,bottom:via.y+size2.height/2},width:size2.width,height:size2.height}}_setPositionFromLayout(newCenter){let{db}=this.root;db.pcb_via.update(this.pcb_via_id,{x:newCenter.x,y:newCenter.y})}_getLayers(){let{fromLayer="top",toLayer="bottom"}=this._parsedProps;return fromLayer===toLayer?[fromLayer]:[fromLayer,toLayer]}initPorts(){let layers=this._parsedProps.layers;for(let layer of layers){let port2=new Port({name:layer,layer});port2.registerMatch(this),this.add(port2)}let port=new Port({name:"pin1"});port.registerMatch(this),this.add(port)}_getConnectedNetOrTrace(){let connectsTo=this._parsedProps.connectsTo;if(!connectsTo)return null;let subcircuit=this.getSubcircuit(),selectors=Array.isArray(connectsTo)?connectsTo:[connectsTo];for(let selector of selectors)if(selector.startsWith("net.")){let net=subcircuit.selectOne(selector,{type:"net"});if(net)return net}return null}doInitialPcbComponentRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{padDiameter}=this._getResolvedViaDiameters(pcbStyle2),position2=this._getGlobalPcbPositionBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_component2=db.pcb_component.insert({center:position2,width:padDiameter,height:padDiameter,layer:this._parsedProps.fromLayer??"top",rotation:0,source_component_id:this.source_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,obstructs_within_bounds:!0});this.pcb_component_id=pcb_component2.pcb_component_id}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,group=this.getGroup(),subcircuit=this.getSubcircuit(),source_via=db.source_manually_placed_via.insert({source_group_id:group?.source_group_id,source_net_id:props.net??"",subcircuit_id:subcircuit?.subcircuit_id??void 0});this.source_component_id=source_via.source_manually_placed_via_id}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,pcbStyle2=this.getInheritedMergedProperty("pcbStyle"),{holeDiameter,padDiameter}=this._getResolvedViaDiameters(pcbStyle2),position2=this._getGlobalPcbPositionBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_via2=db.pcb_via.insert({x:position2.x,y:position2.y,hole_diameter:holeDiameter,outer_diameter:padDiameter,layers:["bottom","top"],from_layer:this._parsedProps.fromLayer||"bottom",to_layer:this._parsedProps.toLayer||"top",subcircuit_id:subcircuit?.subcircuit_id??void 0,subcircuit_connectivity_map_key:this.subcircuit_connectivity_map_key??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0,net_is_assignable:this._parsedProps.netIsAssignable??void 0});this.pcb_via_id=pcb_via2.pcb_via_id;let connected=this._getConnectedNetOrTrace();connected&&"source_net_id"in connected&&connected.source_net_id&&db.pcb_via.update(this.pcb_via_id,{pcb_trace_id:connected.source_net_id})}},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(){this.root?.pcbDisabled||this._queueAsyncEffect("PcbCopperPourRender",async()=>{let{db}=this.root,{_parsedProps:props}=this,net=this.getSubcircuit().selectOne(props.connectsTo);if(!net||!net.source_net_id){this.renderError(`Net "${props.connectsTo}" not found for copper pour`);return}let subcircuit=this.getSubcircuit(),circuitJson=db.toArray(),sourceNet=circuitJson.find(elm=>elm.type==="source_net"&&elm.name===net.name),connectivityMap=getFullConnectivityMapFromCircuitJson(circuitJson),connectedNetId=sourceNet?.source_net_id??net.source_net_id,pourConnectivityKey=(connectedNetId?connectivityMap.getNetConnectedToId(connectedNetId):void 0)||sourceNet?.subcircuit_connectivity_map_key||"",clearance=props.clearance??.2,inputProblem=convertCircuitJsonToInputProblem(circuitJson,{layer:props.layer,pour_connectivity_key:pourConnectivityKey,pad_margin:props.padMargin??clearance,trace_margin:props.traceMargin??clearance,board_edge_margin:props.boardEdgeMargin??clearance,cutout_margin:props.cutoutMargin??clearance,outline:props.outline}),solver=new CopperPourPipelineSolver(inputProblem);this.root.emit("solver:started",{solverName:"CopperPourPipelineSolver",solverParams:inputProblem,componentName:this.props.name});let{brep_shapes}=solver.getOutput(),coveredWithSolderMask=props.coveredWithSolderMask??!1;for(let brep_shape2 of brep_shapes)db.pcb_copper_pour.insert({shape:"brep",layer:props.layer,brep_shape:brep_shape2,source_net_id:net.source_net_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,covered_with_solder_mask:coveredWithSolderMask})})}},CopperText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isPcbPrimitive",!0);__publicField(this,"pcb_copper_text_id",null)}get config(){return{componentName:"CopperText",zodProps:copperTextProps}}doInitialPcbPrimitiveRender(){if(this.root?.pcbDisabled)return;let{db}=this.root,{_parsedProps:props}=this,container=this.getPrimitiveContainer(),position2=this._getGlobalPcbPositionBeforeLayout(),subcircuit=this.getSubcircuit(),pcb_copper_text2=db.pcb_copper_text.insert({anchor_alignment:props.anchorAlignment,anchor_position:{x:position2.x,y:position2.y},font:"tscircuit2024",font_size:props.fontSize,layer:props.layer??"top",text:normalizeTextForCircuitJson(props.text),ccw_rotation:props.pcbRotation,is_mirrored:props.mirrored,is_knockout:props.knockout,pcb_component_id:container.pcb_component_id,subcircuit_id:subcircuit?.subcircuit_id??void 0,pcb_group_id:this.getGroup()?.pcb_group_id??void 0});this.pcb_copper_text_id=pcb_copper_text2.pcb_copper_text_id}getPcbSize(){let{_parsedProps:props}=this,fontSize=props.fontSize??1,textWidth=(props.text??"").length*fontSize,textHeight=fontSize;return{width:textWidth*fontSize,height:textHeight*fontSize}}_moveCircuitJsonElements({deltaX,deltaY}){if(this.root?.pcbDisabled)return;let{db}=this.root;if(!this.pcb_copper_text_id)return;let text=db.pcb_copper_text.get(this.pcb_copper_text_id);text&&db.pcb_copper_text.update(this.pcb_copper_text_id,{anchor_position:{x:text.anchor_position.x+deltaX,y:text.anchor_position.y+deltaY}})}},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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:"simple_power_source",capacity:props.capacity,supplier_part_numbers:props.supplierPartNumbers,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;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"),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 i2=1;i2<=pinCount;i2++){let rawLabel=Array.isArray(this._parsedProps.pinLabels)?this._parsedProps.pinLabels[i2-1]:this._parsedProps.pinLabels?.[`pin${i2}`];if(rawLabel){let primaryLabel=Array.isArray(rawLabel)?rawLabel[0]:rawLabel,otherLabels=Array.isArray(rawLabel)?rawLabel.slice(1):[];this.add(new Port({pinNumber:i2,name:primaryLabel,aliases:[`pin${i2}`,...otherLabels]}))}else this.add(new Port({pinNumber:i2,name:`pin${i2}`}))}}_getSchematicPortArrangement(){let pinCount=this._parsedProps.pinCount??1,facingDirection=this._parsedProps.schFacingDirection??this._parsedProps.facingDirection??"right",schPinArrangement=this._parsedProps.schPinArrangement;return facingDirection==="left"?{leftSide:{direction:schPinArrangement?.leftSide?.direction??"top-to-bottom",pins:schPinArrangement?.leftSide?.pins??Array.from({length:pinCount},(_5,i2)=>`pin${i2+1}`)}}:{rightSide:{direction:schPinArrangement?.rightSide?.direction??"top-to-bottom",pins:schPinArrangement?.rightSide?.pins??Array.from({length:pinCount},(_5,i2)=>`pin${i2+1}`)}}}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_pin_header",name:this.name,supplier_part_numbers:props.supplierPartNumbers,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}=this.root,{_parsedProps:props}=this,pinVariant=props.pinVariant||"no_ground",source_component=db.source_component.insert({ftype:"simple_resonator",name:this.name,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}=this.root,{_parsedProps:props}=this,pinVariant=props.pinVariant||"two_pin",source_component=db.source_component.insert({ftype:"simple_potentiometer",name:this.name,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}},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=Vf[this._getSchematicSymbolNameOrThrow()],symPort1=symbol.ports.find(p4=>p4.labels.includes("1")),symPort2=symbol.ports.find(p4=>p4.labels.includes("2")),ports=this.selectAll("port"),pin1Port=ports.find(p4=>p4.props.pinNumber===1),pin2Port=ports.find(p4=>p4.props.pinNumber===2),pin3Port=ports.find(p4=>p4.props.pinNumber===3),pin4Port=ports.find(p4=>p4.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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:FTYPE.simple_push_button,supplier_part_numbers:props.supplierPartNumbers,are_pins_interchangeable:!0,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},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"],pin2:["top1","2","gnd1"],pin3:["right1","3"],pin4:["bottom1","4","gnd2"]}:{pin1:["pos","left"],pin2:["neg","right"]};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}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({name:this.name,ftype:"simple_crystal",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}},Mosfet=class extends NormalComponent3{get config(){let mosfetMode=this.props.mosfetMode==="depletion"?"d":"e",baseSymbolName=`${this.props.channelType}_channel_${mosfetMode}_mosfet_transistor`;return{componentName:"Mosfet",schematicSymbolName:this.props.symbolName??baseSymbolName,zodProps:mosfetProps,shouldRenderAsSchematicBox:!1}}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_mosfet",name:this.name,mosfet_mode:props.mosfetMode,channel_type:props.channelType,display_name:props.displayName});this.source_component_id=source_component.source_component_id}},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)}get config(){let hasPowerConnections=this.props.connections?.positive_supply||this.props.connections?.negative_supply;return{componentName:"OpAmp",schematicSymbolName:this.props.symbolName?this.props.symbolName:hasPowerConnections?"opamp_with_power":"opamp_no_power",zodProps:opampProps,sourceFtype:"simple_op_amp"}}initPorts(){super.initPorts({pinCount:5,additionalAliases:{pin1:["non_inverting_input"],pin2:["inverting_input"],pin3:["output"],pin4:["positive_supply","vcc","vdd"],pin5:["negative_supply","vee","vss","gnd"]}})}doInitialSourceRender(){let{db}=this.root,{_parsedProps:props}=this,source_component=db.source_component.insert({ftype:"simple_op_amp",name:this.name,supplier_part_numbers:props.supplierPartNumbers,display_name:props.displayName});this.source_component_id=source_component.source_component_id}doInitialSimulationRender(){let{db}=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||db.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})}};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}=this.root,props=this._parsedProps??{},source_component=db.source_component.insert({ftype:"simple_switch",name:this.name,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}=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),db.simulation_switch.insert(simulationSwitch)}},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}=this.root,{_parsedProps:props}=this,{padShape,holeDiameter,footprintVariant,padDiameter,width,height}=this._getPropsWithDefaults(),source_component=db.source_component.insert({ftype:FTYPE.simple_test_point,name:this.name,supplier_part_numbers:props.supplierPartNumbers,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}},SchematicText=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_text_id")}get config(){return{componentName:"SchematicText",zodProps:schematicTextProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_text2=db.schematic_text.insert({schematic_symbol_id,anchor:props.anchor??"center",text:normalizeTextForCircuitJson(props.text),font_size:props.fontSize,color:props.color||"#000000",position:{x:globalPos.x,y:globalPos.y},rotation:props.schRotation??0});this.schematic_text_id=schematic_text2.schematic_text_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_text_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,text=db.schematic_text.get(this.schematic_text_id);if(!text)return;let newPosition=applyToPoint(transform5,text.position);db.schematic_text.update(this.schematic_text_id,{position:{x:newPosition.x,y:newPosition.y}})}},SchematicLine=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_line_id")}get config(){return{componentName:"SchematicLine",zodProps:schematicLineProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_line2=db.schematic_line.insert({schematic_component_id,schematic_symbol_id,x1:props.x1+globalPos.x,y1:props.y1+globalPos.y,x2:props.x2+globalPos.x,y2:props.y2+globalPos.y,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_dashed:!1,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_line_id=schematic_line2.schematic_line_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_line_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,line2=db.schematic_line.get(this.schematic_line_id);if(!line2)return;let p12=applyToPoint(transform5,{x:line2.x1,y:line2.y1}),p22=applyToPoint(transform5,{x:line2.x2,y:line2.y2});db.schematic_line.update(this.schematic_line_id,{x1:p12.x,y1:p12.y,x2:p22.x,y2:p22.y})}},SchematicRect=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_rect_id")}get config(){return{componentName:"SchematicRect",zodProps:schematicRectProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_rect2=db.schematic_rect.insert({schematic_symbol_id,center:{x:globalPos.x,y:globalPos.y},width:props.width,height:props.height,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_filled:props.isFilled,schematic_component_id,is_dashed:props.isDashed,rotation:props.rotation??0,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_rect_id=schematic_rect2.schematic_rect_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_rect_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,rect=db.schematic_rect.get(this.schematic_rect_id);if(!rect)return;let topLeft=applyToPoint(transform5,{x:rect.center.x-rect.width/2,y:rect.center.y+rect.height/2}),bottomRight=applyToPoint(transform5,{x:rect.center.x+rect.width/2,y:rect.center.y-rect.height/2}),newWidth=Math.abs(bottomRight.x-topLeft.x),newHeight=Math.abs(topLeft.y-bottomRight.y),newCenter={x:(topLeft.x+bottomRight.x)/2,y:(topLeft.y+bottomRight.y)/2};db.schematic_rect.update(this.schematic_rect_id,{center:newCenter,width:newWidth,height:newHeight})}},SchematicArc=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_arc_id")}get config(){return{componentName:"SchematicArc",zodProps:schematicArcProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_arc2=db.schematic_arc.insert({schematic_component_id,schematic_symbol_id,center:{x:props.center.x+globalPos.x,y:props.center.y+globalPos.y},radius:props.radius,start_angle_degrees:props.startAngleDegrees,end_angle_degrees:props.endAngleDegrees,direction:props.direction,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_dashed:props.isDashed,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_arc_id=schematic_arc2.schematic_arc_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_arc_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,arc2=db.schematic_arc.get(this.schematic_arc_id);if(!arc2)return;let newCenter=applyToPoint(transform5,arc2.center),edgePoint=applyToPoint(transform5,{x:arc2.center.x+arc2.radius,y:arc2.center.y}),newRadius=Math.abs(edgePoint.x-newCenter.x);db.schematic_arc.update(this.schematic_arc_id,{center:{x:newCenter.x,y:newCenter.y},radius:newRadius})}},SchematicCircle=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_circle_id")}get config(){return{componentName:"SchematicCircle",zodProps:schematicCircleProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,schematic_circle2=db.schematic_circle.insert({schematic_component_id,schematic_symbol_id,center:{x:props.center.x+globalPos.x,y:props.center.y+globalPos.y},radius:props.radius,stroke_width:props.strokeWidth??SCHEMATIC_COMPONENT_OUTLINE_STROKE_WIDTH,color:props.color??SCHEMATIC_COMPONENT_OUTLINE_COLOR,is_filled:props.isFilled,fill_color:props.fillColor,is_dashed:props.isDashed,subcircuit_id:this.getSubcircuit().subcircuit_id??void 0});this.schematic_circle_id=schematic_circle2.schematic_circle_id}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||!this.schematic_circle_id)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root,circle2=db.schematic_circle.get(this.schematic_circle_id);if(!circle2)return;let newCenter=applyToPoint(transform5,circle2.center),edgePoint=applyToPoint(transform5,{x:circle2.center.x+circle2.radius,y:circle2.center.y}),newRadius=Math.abs(edgePoint.x-newCenter.x);db.schematic_circle.update(this.schematic_circle_id,{center:{x:newCenter.x,y:newCenter.y},radius:newRadius})}};function sampleCurveSegment(segmentPath,samplesPerUnit){let commander=new Ci3(segmentPath),length7=commander.getTotalLength(),numSamples=Math.max(2,Math.ceil(length7*samplesPerUnit)),points=[];for(let i2=1;i2<=numSamples;i2++){let t5=i2/numSamples*length7,point6=commander.getPointAtLength(t5);points.push({x:point6.x,y:point6.y})}return points}function svgPathToPoints(svgPath,samplesPerUnit=10){let pathCommander=new Ci3(svgPath);pathCommander.toAbsolute();let segments=pathCommander.segments,result=[],currentPoints=[],currentX=0,currentY=0,subpathStartX=0,subpathStartY=0;for(let segment2 of segments)switch(segment2[0]){case"M":{currentPoints.length>0&&result.push(currentPoints),currentX=segment2[1],currentY=segment2[2],subpathStartX=currentX,subpathStartY=currentY,currentPoints=[{x:currentX,y:currentY}];break}case"L":{currentX=segment2[1],currentY=segment2[2],currentPoints.push({x:currentX,y:currentY});break}case"H":{currentX=segment2[1],currentPoints.push({x:currentX,y:currentY});break}case"V":{currentY=segment2[1],currentPoints.push({x:currentX,y:currentY});break}case"Z":{(currentX!==subpathStartX||currentY!==subpathStartY)&¤tPoints.push({x:subpathStartX,y:subpathStartY}),currentX=subpathStartX,currentY=subpathStartY;break}case"C":{let endX=segment2[5],endY=segment2[6],segmentPath=`M ${currentX} ${currentY} C ${segment2[1]} ${segment2[2]} ${segment2[3]} ${segment2[4]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"S":{let endX=segment2[3],endY=segment2[4],segmentPath=`M ${currentX} ${currentY} S ${segment2[1]} ${segment2[2]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"Q":{let endX=segment2[3],endY=segment2[4],segmentPath=`M ${currentX} ${currentY} Q ${segment2[1]} ${segment2[2]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"T":{let endX=segment2[1],endY=segment2[2],segmentPath=`M ${currentX} ${currentY} T ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}case"A":{let endX=segment2[6],endY=segment2[7],segmentPath=`M ${currentX} ${currentY} A ${segment2[1]} ${segment2[2]} ${segment2[3]} ${segment2[4]} ${segment2[5]} ${endX} ${endY}`,sampledPoints=sampleCurveSegment(segmentPath,samplesPerUnit);currentPoints.push(...sampledPoints),currentX=endX,currentY=endY;break}}return currentPoints.length>0&&result.push(currentPoints),result.map(points=>{let deduped=[];for(let point6 of points)(deduped.length===0||Math.abs(deduped[deduped.length-1].x-point6.x)>1e-9||Math.abs(deduped[deduped.length-1].y-point6.y)>1e-9)&&deduped.push(point6);return deduped})}var SchematicPath=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0);__publicField(this,"schematic_path_ids",[])}get config(){return{componentName:"SchematicPath",zodProps:schematicPathProps}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,globalPos=this._getGlobalSchematicPositionBeforeLayout(),schematic_component_id=this.getPrimitiveContainer()?.parent?.schematic_component_id,schematic_symbol_id=this._getSymbolAncestor()?.schematic_symbol_id,subcircuit_id=this.getSubcircuit().subcircuit_id??void 0;if(this.schematic_path_ids=[],props.svgPath){let subpaths=svgPathToPoints(props.svgPath);for(let subpathPoints of subpaths){let schematic_path2=db.schematic_path.insert({schematic_component_id,schematic_symbol_id,points:subpathPoints.map(point6=>({x:point6.x+globalPos.x,y:point6.y+globalPos.y})),is_filled:props.isFilled,fill_color:props.fillColor,stroke_color:props.strokeColor,stroke_width:props.strokeWidth,subcircuit_id});this.schematic_path_ids.push(schematic_path2.schematic_path_id)}}else if(props.points&&props.points.length>0){let schematic_path2=db.schematic_path.insert({schematic_component_id,schematic_symbol_id,points:props.points.map(point6=>({x:point6.x+globalPos.x,y:point6.y+globalPos.y})),is_filled:props.isFilled,fill_color:props.fillColor,stroke_color:props.strokeColor,stroke_width:props.strokeWidth,subcircuit_id});this.schematic_path_ids.push(schematic_path2.schematic_path_id)}}doInitialSchematicSymbolResize(){if(this.root?.schematicDisabled||this.schematic_path_ids.length===0)return;let transform5=this._getSymbolAncestor()?.getUserCoordinateToResizedSymbolTransform();if(!transform5)return;let{db}=this.root;for(let pathId of this.schematic_path_ids){let path=db.schematic_path.get(pathId);if(!path)continue;let newPoints=path.points.map(point6=>{let transformed=applyToPoint(transform5,point6);return{x:transformed.x,y:transformed.y}});db.schematic_path.update(pathId,{points:newPoints})}}};function getTitleAnchorAndPosition({anchor,x:x5,y:y5,width,height,isInside}){switch(anchor){case"top_left":return{x:x5,y:y5+height,textAnchor:isInside?"top_left":"bottom_left"};case"top_center":return{x:x5+width/2,y:y5+height,textAnchor:isInside?"top_center":"bottom_center"};case"top_right":return{x:x5+width,y:y5+height,textAnchor:isInside?"top_right":"bottom_right"};case"center_left":return{x:x5,y:y5+height/2,textAnchor:isInside?"center_left":"center_right"};case"center":return{x:x5+width/2,y:y5+height/2,textAnchor:"center"};case"center_right":return{x:x5+width,y:y5+height/2,textAnchor:isInside?"center_right":"center_left"};case"bottom_left":return{x:x5,y:y5,textAnchor:isInside?"bottom_left":"top_left"};case"bottom_center":return{x:x5+width/2,y:y5,textAnchor:isInside?"bottom_center":"top_center"};case"bottom_right":return{x:x5+width,y:y5,textAnchor:isInside?"bottom_right":"top_right"};default:return{x:x5+width/2,y:y5+height,textAnchor:"center"}}}var SchematicBox=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isSchematicPrimitive",!0)}get config(){return{componentName:"SchematicBox",zodProps:schematicBoxProps,shouldRenderAsSchematicBox:!0}}doInitialSchematicPrimitiveRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,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,x5,y5,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(p4=>p4.position.x),ys3=portsWithPosition.map(p4=>p4.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,x5=left+(props.schX??0),y5=top+(props.schY??0),centerX=x5+width/2,centerY=y5+height/2}else if(hasFixedSize){width=props.width,height=props.height;let center2=this._getGlobalSchematicPositionBeforeLayout();centerX=center2.x,centerY=center2.y,x5=centerX-width/2,y5=centerY-height/2}else return;if(db.schematic_box.insert({height,width,x:x5,y:y5,is_dashed:props.strokeStyle==="dashed"}),props.title){let isInside=props.titleInside,TITLE_PADDING=.1,anchor=props.titleAlignment,anchorPos=getTitleAnchorAndPosition({anchor,x:x5,y:y5,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;db.schematic_text.insert({anchor:textAnchor,text:props.title,font_size:props.titleFontSize??.18,color:props.titleColor??"#000000",position:{x:titleX,y:titleY},rotation:0})}}},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)return;let{db}=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 i2=0;i2<rows.length;i2++)grid4[i2]=[];for(let i2=0;i2<rows.length;i2++){let cells=rows[i2].children.filter(c3=>c3.componentName==="SchematicCell"),k4=0;for(let j4=0;j4<cells.length;j4++){for(;grid4[i2][k4];)k4++;let cell=cells[j4],colSpan=cell._parsedProps.colSpan??1,rowSpan=cell._parsedProps.rowSpan??1;for(let r4=0;r4<rowSpan;r4++)for(let c3=0;c3<colSpan;c3++)grid4[i2+r4]||(grid4[i2+r4]=[]),grid4[i2+r4][k4+c3]=cell;k4+=colSpan}}maxCols=Math.max(0,...grid4.map(r4=>r4.length));let rowHeights=rows.map((row,i2)=>row._parsedProps.height??1),colWidths=Array.from({length:maxCols},(_5,j4)=>{let maxWidth=0;for(let i2=0;i2<rows.length;i2++){let cell=grid4[i2]?.[j4];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=db.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||""});this.schematic_table_id=table.schematic_table_id;let processedCells=new Set,yOffset=0;for(let i2=0;i2<rows.length;i2++){let xOffset=0;for(let j4=0;j4<maxCols;j4++){let cell=grid4[i2]?.[j4];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[j4+c3];let cellHeight=0;for(let r4=0;r4<rowSpan;r4++)cellHeight+=rowHeights[i2+r4];db.schematic_table_cell.insert({schematic_table_id:this.schematic_table_id,start_row_index:i2,end_row_index:i2+rowSpan-1,start_column_index:j4,end_column_index:j4+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[j4]&&(xOffset+=colWidths[j4])}yOffset+=rowHeights[i2]}}},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}}},SymbolComponent=class extends PrimitiveComponent2{constructor(){super(...arguments);__publicField(this,"isPrimitiveContainer",!0);__publicField(this,"schematic_symbol_id");__publicField(this,"userCoordinateToResizedSymbolTransformMat");__publicField(this,"schematicSymbolBoundsInUserCoordinates")}get config(){return{componentName:"Symbol",zodProps:symbolProps}}hasExplicitSize(){let{_parsedProps:props}=this;return props.width!==void 0||props.height!==void 0}doInitialSymbolContainerRender(){if(this.root?.schematicDisabled)return;let{db}=this.root,{_parsedProps:props}=this,schematic_symbol2=db.schematic_symbol.insert({name:props.name});this.schematic_symbol_id=schematic_symbol2.schematic_symbol_id}getSchematicSymbolBounds(){return this.schematicSymbolBoundsInUserCoordinates?this.schematicSymbolBoundsInUserCoordinates:(this._computeSchematicSymbolBounds(),this.schematicSymbolBoundsInUserCoordinates??null)}getUserCoordinateToResizedSymbolTransform(){return this.hasExplicitSize()?this.userCoordinateToResizedSymbolTransformMat?this.userCoordinateToResizedSymbolTransformMat:(this._computeUserCoordinateToResizedSymbolTransform(),this.userCoordinateToResizedSymbolTransformMat??null):null}_computeSchematicSymbolBounds(){if(this.root?.schematicDisabled)return;let{db}=this.root,schematicElements=[];for(let child of this.children)if(child.isSchematicPrimitive){if(child.componentName==="SchematicLine"){let line2=db.schematic_line.get(child.schematic_line_id);line2&&schematicElements.push(line2)}else if(child.componentName==="SchematicRect"){let rect=db.schematic_rect.get(child.schematic_rect_id);rect&&schematicElements.push(rect)}else if(child.componentName==="SchematicCircle"){let circle2=db.schematic_circle.get(child.schematic_circle_id);circle2&&schematicElements.push(circle2)}else if(child.componentName==="SchematicArc"){let arc2=db.schematic_arc.get(child.schematic_arc_id);arc2&&schematicElements.push(arc2)}else if(child.componentName==="SchematicText"){let text=db.schematic_text.get(child.schematic_text_id);text&&schematicElements.push(text)}else if(child.componentName==="SchematicPath"){let pathIds=child.schematic_path_ids;if(pathIds)for(let pathId of pathIds){let path=db.schematic_path.get(pathId);path&&schematicElements.push(path)}}}if(schematicElements.length===0)return;let bounds=getBoundsForSchematic(schematicElements);this.schematicSymbolBoundsInUserCoordinates=bounds}_computeUserCoordinateToResizedSymbolTransform(){let bounds=this.getSchematicSymbolBounds();if(!bounds)return;let{_parsedProps:props}=this,targetWidth=props.width,targetHeight=props.height;if(targetWidth===void 0&&targetHeight===void 0)return;let currentWidth=bounds.maxX-bounds.minX,currentHeight=bounds.maxY-bounds.minY;if(currentWidth===0&¤tHeight===0)return;let currentCenterX=(bounds.minX+bounds.maxX)/2,currentCenterY=(bounds.minY+bounds.maxY)/2,scaleX=targetWidth!==void 0&¤tWidth>0?targetWidth/currentWidth:1,scaleY=targetHeight!==void 0&¤tHeight>0?targetHeight/currentHeight:1,globalPos=this._getGlobalSchematicPositionBeforeLayout();this.userCoordinateToResizedSymbolTransformMat=compose(translate(globalPos.x,globalPos.y),scale(scaleX,scaleY),translate(-currentCenterX,-currentCenterY))}},AnalogSimulation=class extends PrimitiveComponent2{get config(){return{componentName:"AnalogSimulation",zodProps:analogSimulationProps}}doInitialSimulationRender(){let{db}=this.root,{duration,timePerStep}=this._parsedProps,durationMs=duration||10,timePerStepMs=timePerStep||.01;db.simulation_experiment.insert({name:"spice_transient_analysis",experiment_type:"spice_transient_analysis",end_time_ms:durationMs,time_per_step:timePerStepMs})}};function getLabelBounds(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 cx2,cy2,w4,h4;if(elm.type==="schematic_component")cx2=elm.center?.x,cy2=elm.center?.y,w4=elm.size?.width,h4=elm.size?.height;else if(elm.type==="schematic_text")cx2=elm.position?.x,cy2=elm.position?.y,w4=(elm.text?.length??0)*.1,h4=.2;else return null;return typeof cx2=="number"&&typeof cy2=="number"&&typeof w4=="number"&&typeof h4=="number"?{minX:cx2-w4/2,maxX:cx2+w4/2,minY:cy2-h4/2,maxY:cy2+h4/2}:null}function getOverlapArea(a2,b3){if(!doBoundsOverlap(a2,b3))return 0;let overlapWidth=Math.min(a2.maxX,b3.maxX)-Math.max(a2.minX,b3.minX),overlapHeight=Math.min(a2.maxY,b3.maxY)-Math.max(a2.minY,b3.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(a2=>a2!==defaultAlignment)],bestAlignment=defaultAlignment,minOverlapArea=1/0;for(let alignment of orderedAlignments){let labelBounds=getLabelBounds(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}=this.root,{connectsTo,name,referenceTo,color}=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(s2=>s2.replace(/^\./,"")).join(".")),this.finalProbeName=finalName??null;let{simulation_voltage_probe_id}=db.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});this.simulation_voltage_probe_id=simulation_voltage_probe_id}doInitialSchematicReplaceNetLabelsWithSymbols(){if(this.root?.schematicDisabled)return;let{db}=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 position2=port._getGlobalSchematicPositionAfterLayout(),targetTraceId=null;for(let trace of db.schematic_trace.list()){for(let edge of trace.edges)if(Math.abs(edge.from.x-position2.x)<1e-6&&Math.abs(edge.from.y-position2.y)<1e-6||Math.abs(edge.to.x-position2.x)<1e-6&&Math.abs(edge.to.y-position2.y)<1e-6){targetTraceId=trace.schematic_trace_id;break}if(targetTraceId)break}if(!targetTraceId)return;let probeName=this.finalProbeName,labelAlignment=selectBestLabelAlignment({probePosition:position2,labelText:probeName,schematicElements:[...db.schematic_component.list(),...db.schematic_text.list()],defaultAlignment:"top_right"}),schematic_voltage_probe2=db.schematic_voltage_probe.insert({name:probeName,position:position2,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_probe2.schematic_voltage_probe_id}},package_default3={name:"@tscircuit/core",type:"module",version:"0.0.1005",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 index.ts --format esm --dts",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","@tscircuit/alphabet":"0.0.18","@tscircuit/capacity-autorouter":"^0.0.264","@tscircuit/checks":"^0.0.87","@tscircuit/circuit-json-util":"^0.0.77","@tscircuit/common":"^0.0.20","@tscircuit/copper-pour-solver":"^0.0.20","@tscircuit/footprinter":"^0.0.288","@tscircuit/infgrid-ijump-astar":"^0.0.35","@tscircuit/log-soup":"^1.0.2","@tscircuit/matchpack":"^0.0.16","@tscircuit/math-utils":"^0.0.29","@tscircuit/miniflex":"^0.0.4","@tscircuit/ngspice-spice-engine":"^0.0.8","@tscircuit/props":"^0.0.457","@tscircuit/schematic-match-adapt":"^0.0.16","@tscircuit/schematic-trace-solver":"^v0.0.45","@tscircuit/solver-utils":"^0.0.3","@tscircuit/soup-util":"^0.0.41","@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.372","circuit-json-to-bpc":"^0.0.13","circuit-json-to-connectivity-map":"^0.0.23","circuit-json-to-gltf":"^0.0.62","circuit-json-to-simple-3d":"^0.0.9","circuit-json-to-spice":"^0.0.33","circuit-to-svg":"^0.0.321",concurrently:"^9.1.2","connectivity-map":"^1.0.0",debug:"^4.3.6","eecircuit-engine":"^1.5.6",flatbush:"^4.5.0","graphics-debug":"^0.0.60",howfat:"^0.3.8","live-server":"^1.2.2","looks-same":"^9.0.1",minicssgrid:"^0.0.9","pkg-pr-new":"^0.0.37",poppygl:"^0.0.16",react:"^19.1.0","react-dom":"^19.1.0","schematic-symbols":"^0.0.208",spicey:"^0.0.14","ts-expect":"^1.3.0",tsup:"^8.2.4"},peerDependencies:{"@tscircuit/capacity-autorouter":"*","@tscircuit/checks":"*","@tscircuit/circuit-json-util":"*","@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":"*","schematic-symbols":"*",typescript:"^5.0.0"},dependencies:{"@flatten-js/core":"^1.6.2","@lume/kiwi":"^0.4.3","calculate-packing":"0.0.68","css-select":"5.1.0","format-si-unit":"^0.0.3",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"}},RootCircuit=class{constructor({platform,projectUrl}={}){__publicField(this,"firstChild",null);__publicField(this,"children");__publicField(this,"db");__publicField(this,"root",null);__publicField(this,"isRoot",!0);__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,"_eventListeners",{});this.children=[],this.db=su2([]),this.root=this,this.platform=platform,this.projectUrl=projectUrl,this.pcbDisabled=platform?.pcbDisabled??!1}get schematicDisabled(){return this._schematicDisabledOverride!==void 0?this._schematicDisabledOverride:this._getBoard()?._parsedProps?.schematicDisabled??!1}set schematicDisabled(value){this._schematicDisabledOverride=value}add(componentOrElm){let component;(0,import_react4.isValidElement)(componentOrElm)?component=createInstanceFromReactElement(componentOrElm):component=componentOrElm,this.children.push(component)}setPlatform(platform){this.platform={...this.platform,...platform}}_getBoard(){let directBoard=this.children.find(c3=>c3.componentName==="Board");if(directBoard)return directBoard}_guessRootComponent(){if(this.firstChild)return;if(this.children.length===0)throw new Error("Not able to guess root component: RootCircuit 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){this.firstChild=this.children[0];return}let group=new Group6({subcircuit:!0});group.parent=this,group.addAll(this.children),this.children=[group],this.firstChild=group}render(){this.firstChild||this._guessRootComponent();let{firstChild,db}=this;if(!firstChild)throw new Error("RootCircuit has no root component");firstChild.parent=this,firstChild.runRenderCycle(),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._hasIncompleteAsyncEffects();)await new Promise(resolve=>setTimeout(resolve,100)),this.render();this.emit("renderComplete")}_hasIncompleteAsyncEffects(){return this._asyncEffectPhaseById.size>0?!0:this.children.some(child=>child._hasIncompleteAsyncEffects())}_hasIncompleteAsyncEffectsForPhase(phase){return(this._asyncEffectIdsByPhase.get(phase)?.size??0)>0}getCircuitJson(){return this._hasRenderedAtleastOnce||this.render(),this.db.toArray()}toJson(){return this.getCircuitJson()}async getSvg(options){let circuitToSvg=await Promise.resolve().then(()=>(init_dist8(),dist_exports3)).catch(e4=>{throw new Error(`To use circuit.getSvg, you must install the "circuit-to-svg" package.
|
|
623
623
|
|
|
624
624
|
"${e4.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(l3=>l3!==listener))}enableDebug(debug112){typeof debug112=="string"?import_debug18.default.enable(debug112):(debug112===null||debug112===!1)&&import_debug18.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)}_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)}},Project=RootCircuit,Circuit=RootCircuit,useRenderedCircuit=reactElements=>{let[isLoading,setIsLoading]=import_react5.default.useState(!0),[error,setError]=import_react5.default.useState(null),[circuit,setCircuit]=import_react5.default.useState(),[circuitJson,setCircuitJson]=import_react5.default.useState();return import_react5.default.useEffect(()=>{setIsLoading(!0),setError(null),reactElements&&setTimeout(()=>{try{let circuit2=new RootCircuit;circuit2.add(reactElements),setCircuit(circuit2),setCircuitJson(circuit2.toJson())}catch(error2){setError(error2)}setIsLoading(!1)},1)},[reactElements]),{isLoading,error,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 R5=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,i2)=>(0,import_jsx_runtime.jsx)("trace",{...trace},i2))]})};for(let port of pinLabelsFlatArray)R5[port]=`.${name} > .${port}`;return R5},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:(_5,pin)=>`.${refdes} > .${pin}`}),{get:(_5,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(p4=>prop1.startsWith(p4))?pinResult:new Proxy(new String(pinResult),{get:(_42,nestedProp)=>typeof nestedProp=="symbol"||nestedProp==="toString"?()=>pinResult:`.${prop1} > .${pinOrSubComponentName} > .${nestedProp}`})}})})}});extendCatalogue(components_exports);extendCatalogue({Bug:Chip});var React=__toESM(require_react(),1),ReactJsxRuntime=__toESM(require_jsx_runtime(),1);var getFootprinterStringFromKicad=kicadFootprint=>{let match2=kicadFootprint.match(/:[RC]_(\d{4})_/);if(match2||(match2=kicadFootprint.match(/:(SOIC-\d+|SOT-\d+|SOD-\d+|SSOP-\d+|TSSOP-\d+|QFP-\d+|QFN-\d+)/),match2))return match2[1]};var getJlcPackageFromFootprinterString=footprinterString=>footprinterString.includes("cap")?footprinterString.replace(/cap/g,""):footprinterString;var getJlcpcbPackageName=footprint=>{if(footprint){if(footprint.startsWith("kicad:")){let footprinterString=getFootprinterStringFromKicad(footprint);return footprinterString?getJlcPackageFromFootprinterString(footprinterString):footprint}return getJlcPackageFromFootprinterString(footprint)}};var cache=new Map,getJlcPartsCached=async(name,params)=>{let paramString=new URLSearchParams({...params,json:"true"}).toString();if(cache.has(paramString))return cache.get(paramString);let responseJson=await(await fetch(`https://jlcsearch.tscircuit.com/${name}/list?${paramString}`)).json();return cache.set(paramString,responseJson),responseJson},withBasicPartPreference=parts=>parts?[...parts].sort((a2,b3)=>Number(b3.is_basic??!1)-Number(a2.is_basic??!1)):[],jlcPartsEngine={findPart:async({sourceComponent,footprinterString})=>{let jlcpcbPackage=getJlcpcbPackageName(footprinterString);if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_resistor"){let{resistors}=await getJlcPartsCached("resistors",{resistance:sourceComponent.resistance,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(resistors).map(r4=>`C${r4.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_capacitor"){let{capacitors}=await getJlcPartsCached("capacitors",{capacitance:sourceComponent.capacitance,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(capacitors).map(c3=>`C${c3.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_pin_header"){let pitch;footprinterString?.includes("_p")&&(pitch=Number(footprinterString.split("_p")[1]));let{headers}=await getJlcPartsCached("headers",pitch?{pitch,num_pins:sourceComponent.pin_count,gender:sourceComponent.gender}:{num_pins:sourceComponent.pin_count,gender:sourceComponent.gender});return{jlcpcb:withBasicPartPreference(headers).map(h4=>`C${h4.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_potentiometer"){let{potentiometers}=await getJlcPartsCached("potentiometers",{resistance:sourceComponent.max_resistance,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(potentiometers).map(p4=>`C${p4.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_diode"){let{diodes}=await getJlcPartsCached("diodes",{package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(diodes).map(d3=>`C${d3.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_chip"){if(!jlcpcbPackage||!footprinterString)return{};let{chips}=await getJlcPartsCached("chips",{package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(chips).map(c3=>`C${c3.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_transistor"){let{transistors}=await getJlcPartsCached("transistors",{package:jlcpcbPackage,transistor_type:sourceComponent.transistor_type});return{jlcpcb:withBasicPartPreference(transistors).map(t5=>`C${t5.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_power_source"){let{power_sources}=await getJlcPartsCached("power_sources",{voltage:sourceComponent.voltage,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(power_sources).map(p4=>`C${p4.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_inductor"){let{inductors}=await getJlcPartsCached("inductors",{inductance:sourceComponent.inductance,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(inductors).map(i2=>`C${i2.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_crystal"){let{crystals}=await getJlcPartsCached("crystals",{frequency:sourceComponent.frequency,load_capacitance:sourceComponent.load_capacitance,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(crystals).map(c3=>`C${c3.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_mosfet"){let{mosfets}=await getJlcPartsCached("mosfets",{package:jlcpcbPackage,mosfet_mode:sourceComponent.mosfet_mode,channel_type:sourceComponent.channel_type});return{jlcpcb:withBasicPartPreference(mosfets).map(m3=>`C${m3.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_resonator"){let{resonators}=await getJlcPartsCached("resonators",{frequency:sourceComponent.frequency,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(resonators).map(r4=>`C${r4.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_switch"){let{switches}=await getJlcPartsCached("switches",{switch_type:sourceComponent.type,package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(switches).map(s2=>`C${s2.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_led"){let{leds}=await getJlcPartsCached("leds",{package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(leds).map(l3=>`C${l3.lcsc}`).slice(0,3)}}else if(sourceComponent.type==="source_component"&&sourceComponent.ftype==="simple_fuse"){let{fuses}=await getJlcPartsCached("fuses",{package:jlcpcbPackage});return{jlcpcb:withBasicPartPreference(fuses).map(l3=>`C${l3.lcsc}`).slice(0,3)}}return{}}};var import_s_expression=__toESM(require_s_expression(),1);init_zod();var import_debug19=__toESM(require_browser(),1),import_debug20=__toESM(require_browser(),1),point22=external_exports.tuple([external_exports.coerce.number(),external_exports.coerce.number()]),point33=external_exports.tuple([external_exports.number(),external_exports.number(),external_exports.number()]),point5=external_exports.union([point22,point33]),fp_poly_arc_segment_def=external_exports.object({kind:external_exports.literal("arc"),start:point22,mid:point22,end:point22}),fp_poly_point_def=external_exports.union([point22,fp_poly_arc_segment_def]),attributes_def=external_exports.object({at:point5,size:point22,layer:external_exports.string(),layers:external_exports.array(external_exports.string()),roundrect_rratio:external_exports.number(),uuid:external_exports.string()}).partial(),property_def=external_exports.object({key:external_exports.string(),val:external_exports.string(),attributes:attributes_def}),drill_def=external_exports.object({oval:external_exports.boolean().default(!1),width:external_exports.number().optional(),height:external_exports.number().optional(),offset:point22.optional()}),hole_def=external_exports.object({name:external_exports.string(),pad_type:external_exports.enum(["thru_hole","smd","np_thru_hole","connect"]),pad_shape:external_exports.enum(["roundrect","circle","rect","oval","trapezoid","custom"]),at:point5,drill:external_exports.union([external_exports.number(),external_exports.array(external_exports.any()),drill_def]).transform(a2=>typeof a2=="number"?{oval:!1,width:a2,height:a2}:"oval"in a2?a2:a2.length===2?{oval:!1,width:Number.parseFloat(a2[0]),height:Number.parseFloat(a2[0]),offset:point22.parse(a2[1].slice(1))}:a2.length===3||a2.length===4?{oval:a2[0]==="oval",width:Number.parseFloat(a2[1]),height:Number.parseFloat(a2[2]),offset:a2[3]?point22.parse(a2[3].slice(1)):void 0}:a2).pipe(drill_def),size:external_exports.union([external_exports.array(external_exports.number()).length(2).transform(([w4,h4])=>({width:w4,height:h4})),external_exports.object({width:external_exports.number(),height:external_exports.number()})]),layers:external_exports.array(external_exports.string()).optional(),roundrect_rratio:external_exports.number().optional(),uuid:external_exports.string().optional()}),pad_def2=external_exports.object({name:external_exports.string(),pad_type:external_exports.enum(["thru_hole","smd","np_thru_hole","connect"]),pad_shape:external_exports.enum(["roundrect","circle","rect","oval","trapezoid","custom"]),at:point5,size:point22,drill:external_exports.union([external_exports.number(),external_exports.array(external_exports.any()),drill_def]).transform(a2=>typeof a2=="number"?{oval:!1,width:a2,height:a2}:"oval"in a2?a2:a2.length===2?{oval:!1,width:Number.parseFloat(a2[0]),height:Number.parseFloat(a2[0]),offset:point22.parse(a2[1].slice(1))}:a2.length===3||a2.length===4?{oval:a2[0]==="oval",width:Number.parseFloat(a2[1]),height:Number.parseFloat(a2[2]),offset:a2[3]?point22.parse(a2[3].slice(1)):void 0}:a2).pipe(drill_def).optional(),layers:external_exports.array(external_exports.string()).optional(),roundrect_rratio:external_exports.number().optional(),chamfer_ratio:external_exports.number().optional(),solder_paste_margin:external_exports.number().optional(),solder_paste_margin_ratio:external_exports.number().optional(),clearance:external_exports.number().optional(),zone_connection:external_exports.union([external_exports.literal(0).describe("Pad is not connect to zone"),external_exports.literal(1).describe("Pad is connected to zone using thermal relief"),external_exports.literal(2).describe("Pad is connected to zone using solid fill")]).optional(),thermal_width:external_exports.number().optional(),thermal_gap:external_exports.number().optional(),uuid:external_exports.string().optional()}),effects_def=external_exports.object({font:external_exports.object({size:point22,thickness:external_exports.number().optional()})}).partial(),fp_text_def=external_exports.object({fp_text_type:external_exports.literal("user"),text:external_exports.string(),at:point5,layer:external_exports.string(),uuid:external_exports.string().optional(),effects:effects_def.partial()}),fp_arc_def=external_exports.object({start:point22,mid:point22,end:point22,stroke:external_exports.object({width:external_exports.number(),type:external_exports.string()}),layer:external_exports.string(),uuid:external_exports.string().optional()}),fp_circle_def=external_exports.object({center:point22,end:point22,stroke:external_exports.object({width:external_exports.number(),type:external_exports.string()}),fill:external_exports.string().optional(),layer:external_exports.string(),uuid:external_exports.string().optional()}),fp_poly_def=external_exports.object({pts:external_exports.array(fp_poly_point_def),stroke:external_exports.object({width:external_exports.number(),type:external_exports.string()}).optional(),width:external_exports.number().optional(),layer:external_exports.string(),uuid:external_exports.string().optional(),fill:external_exports.string().optional()}).transform(data=>({...data,width:void 0,stroke:data.stroke??{width:data.width}})),fp_line=external_exports.object({start:point22,end:point22,stroke:external_exports.object({width:external_exports.number(),type:external_exports.string()}).optional(),width:external_exports.number().optional(),layer:external_exports.string(),uuid:external_exports.string().optional()}).transform(data=>({...data,width:void 0,stroke:data.stroke??{width:data.width}})),kicad_mod_json_def=external_exports.object({footprint_name:external_exports.string(),version:external_exports.string().optional(),generator:external_exports.string().optional(),generator_version:external_exports.string().optional(),layer:external_exports.string(),descr:external_exports.string().default(""),tags:external_exports.array(external_exports.string()).optional(),properties:external_exports.array(property_def),fp_lines:external_exports.array(fp_line),fp_texts:external_exports.array(fp_text_def),fp_arcs:external_exports.array(fp_arc_def),fp_circles:external_exports.array(fp_circle_def).optional(),fp_polys:external_exports.array(fp_poly_def).optional(),pads:external_exports.array(pad_def2),holes:external_exports.array(hole_def).optional()}),formatAttr=(val,attrKey)=>{if(attrKey==="effects"&&Array.isArray(val)){let effectsObj={};for(let elm of val)if(elm[0]==="font"){let fontObj={};for(let fontElm of elm.slice(1))fontElm.length===2?fontObj[fontElm[0].valueOf()]=Number.parseFloat(fontElm[1].valueOf()):fontObj[fontElm[0].valueOf()]=fontElm.slice(1).map(n3=>Number.parseFloat(n3.valueOf()));effectsObj.font=fontObj}return effects_def.parse(effectsObj)}if(attrKey==="pts")return val.map(segment2=>{let segmentType=segment2[0]?.valueOf?.()??segment2[0];if(segmentType==="xy")return segment2.slice(1).map(n3=>Number.parseFloat(n3.valueOf()));if(segmentType==="arc"){let arcObj={kind:"arc"};for(let arcAttr of segment2.slice(1)){let key=arcAttr[0].valueOf();arcObj[key]=arcAttr.slice(1).map(n3=>Number.parseFloat(n3.valueOf()))}return arcObj}return segment2});if(attrKey==="stroke"){let strokeObj={};for(let strokeElm of val){let strokePropKey=strokeElm[0].valueOf();strokeObj[strokePropKey]=formatAttr(strokeElm.slice(1),strokePropKey)}return strokeObj}return attrKey==="at"||attrKey==="size"||attrKey==="start"||attrKey==="mid"||attrKey==="end"?(Array.isArray(val)?val:[val]).map(n3=>n3?.valueOf?.()??n3).filter(v5=>typeof v5=="number"||typeof v5=="string"&&/^[-+]?\d*\.?\d+(e[-+]?\d+)?$/i.test(v5)).map(v5=>typeof v5=="number"?v5:Number.parseFloat(v5)):attrKey==="tags"?val.map(n3=>n3.valueOf()):attrKey==="generator_version"||attrKey==="version"?val[0].valueOf():val.length===2?val.valueOf():attrKey==="uuid"?Array.isArray(val)?val[0].valueOf():val.valueOf():/^[\d\.]+$/.test(val)&&!Number.isNaN(Number.parseFloat(val))?Number.parseFloat(val):Array.isArray(val)&&val.length===1?val[0].valueOf():Array.isArray(val)?val.map(s2=>s2.valueOf()):val},getAttr=(s2,key)=>{for(let elm of s2)if(Array.isArray(elm)&&elm[0]===key)return formatAttr(elm.slice(1),key)},debug11=(0,import_debug19.default)("kicad-mod-converter"),parseKicadModToKicadJson=fileContent=>{let kicadSExpr=(0,import_s_expression.default)(fileContent),footprintName=kicadSExpr[1].valueOf(),topLevelAttributes={},simpleTopLevelAttributes=Object.entries(kicad_mod_json_def.shape).filter(([attributeKey,def])=>def._def.typeName==="ZodString"||attributeKey==="tags").map(([attributeKey])=>attributeKey);for(let kicadSExprRow of kicadSExpr.slice(2)){if(!simpleTopLevelAttributes.includes(kicadSExprRow[0]))continue;let key=kicadSExprRow[0].valueOf(),val=formatAttr(kicadSExprRow.slice(1),key);topLevelAttributes[key]=val}let properties=kicadSExpr.slice(2).filter(row=>row[0]==="property").map(row=>{let key=row[1].valueOf(),val=row[2].valueOf(),attributes2=attributes_def.parse(row.slice(3).reduce((acc,attrAr)=>{let attrKey=attrAr[0].valueOf();return acc[attrKey]=formatAttr(attrAr.slice(1),attrKey),acc},{}));return{key,val,attributes:attributes2}}),padRows=kicadSExpr.slice(2).filter(row=>row[0]==="pad"),pads=[];for(let row of padRows){let at4=getAttr(row,"at"),size2=getAttr(row,"size"),drill=getAttr(row,"drill"),layers=getAttr(row,"layers");if(Array.isArray(layers)?layers=layers.map(layer=>layer.valueOf()):typeof layers=="string"?layers=[layers]:layers||(layers=[]),!layers.includes("F.Cu")){debug11(`Skipping pad without F.Cu layer: layers=${layers.join(", ")}`);continue}let roundrect_rratio=getAttr(row,"roundrect_rratio"),uuid=getAttr(row,"uuid"),padRaw={name:row[1].valueOf(),pad_type:row[2].valueOf(),pad_shape:row[3].valueOf(),at:at4,drill,size:size2,layers,roundrect_rratio,uuid};debug11(`attempting to parse pad: ${JSON.stringify(padRaw,null," ")}`),pads.push(pad_def2.parse(padRaw))}let fp_texts_rows=kicadSExpr.slice(2).filter(row=>row[0]==="fp_text"),fp_texts=[];for(let fp_text_row of fp_texts_rows){let text=fp_text_row[2].valueOf(),at4=getAttr(fp_text_row,"at"),layer=getAttr(fp_text_row,"layer"),uuid=getAttr(fp_text_row,"uuid"),effects=getAttr(fp_text_row,"effects");fp_texts.push({fp_text_type:"user",text,at:at4,layer,uuid,effects})}let fp_lines=[],fp_lines_rows=kicadSExpr.slice(2).filter(row=>row[0]==="fp_line");for(let fp_line_row of fp_lines_rows){let start=getAttr(fp_line_row,"start"),end=getAttr(fp_line_row,"end"),stroke=getAttr(fp_line_row,"stroke"),layer=getAttr(fp_line_row,"layer"),uuid=getAttr(fp_line_row,"uuid");fp_lines.push({start,end,stroke,layer,uuid})}let fp_arcs=[],fp_arcs_rows=kicadSExpr.slice(2).filter(row=>row[0]==="fp_arc");for(let fp_arc_row of fp_arcs_rows){let start=getAttr(fp_arc_row,"start"),mid=getAttr(fp_arc_row,"mid"),end=getAttr(fp_arc_row,"end"),stroke=getAttr(fp_arc_row,"stroke"),layer=getAttr(fp_arc_row,"layer"),uuid=getAttr(fp_arc_row,"uuid");!start||!end||!mid||!stroke||!layer||fp_arcs.push({start,mid,end,stroke,layer,uuid})}let fp_circles=[],fp_circles_rows=kicadSExpr.slice(2).filter(row=>row[0]==="fp_circle");for(let fp_circle_row of fp_circles_rows){let center2=getAttr(fp_circle_row,"center"),end=getAttr(fp_circle_row,"end"),stroke=getAttr(fp_circle_row,"stroke"),fill=getAttr(fp_circle_row,"fill"),layer=getAttr(fp_circle_row,"layer"),uuid=getAttr(fp_circle_row,"uuid");!center2||!end||!stroke||!layer||fp_circles.push({center:center2,end,stroke,fill,layer,uuid})}let fp_polys=[],fp_polys_rows=kicadSExpr.slice(2).filter(row=>row[0]==="fp_poly");for(let fp_poly_row of fp_polys_rows){let pts=getAttr(fp_poly_row,"pts"),stroke=getAttr(fp_poly_row,"stroke"),width=getAttr(fp_poly_row,"width"),layer=getAttr(fp_poly_row,"layer"),uuid=getAttr(fp_poly_row,"uuid"),fill=getAttr(fp_poly_row,"fill"),normalizedStroke=stroke;!normalizedStroke&&typeof width=="number"?normalizedStroke={width,type:"solid"}:normalizedStroke&&typeof normalizedStroke=="object"&&typeof width=="number"&&normalizedStroke.width===void 0&&(normalizedStroke={...normalizedStroke,width}),fp_polys.push({pts,stroke:normalizedStroke,layer,uuid,fill})}let holes=[];for(let row of kicadSExpr.slice(2)){if(row[0]!=="pad"||row[2]?.valueOf?.()!=="thru_hole")continue;let name=row[1]?.valueOf?.(),pad_type=row[2]?.valueOf?.(),pad_shape=row[3]?.valueOf?.(),at4=getAttr(row,"at"),drill=getAttr(row,"drill"),size2=getAttr(row,"size");Array.isArray(size2)&&(size2[0]==="size"&&(size2=size2.slice(1)),size2={width:Number(size2[0]),height:Number(size2[1])});let uuid=getAttr(row,"uuid"),roundrect_rratio=getAttr(row,"roundrect_rratio"),layers=getAttr(row,"layers");Array.isArray(layers)?layers=layers.map(layer=>layer.valueOf()):typeof layers=="string"?layers=[layers]:layers||(layers=[]);let holeRaw={name,pad_type,pad_shape,at:at4,drill,size:size2,layers,roundrect_rratio,uuid};debug11(`attempting to parse holes: ${JSON.stringify(holeRaw,null,2)}`),holes.push(hole_def.parse(holeRaw))}return kicad_mod_json_def.parse({footprint_name:footprintName,...topLevelAttributes,properties,fp_lines,fp_texts,fp_arcs,fp_circles,pads,holes,fp_polys})},TWO_PI=Math.PI*2,normalizeAngle2=angle=>{let result=angle%TWO_PI;return result<0&&(result+=TWO_PI),result},directedAngleCCW=(start,target)=>{let startNorm=normalizeAngle2(start),delta=normalizeAngle2(target)-startNorm;return delta<0&&(delta+=TWO_PI),delta};function calculateCenter(start,mid,end){let mid1={x:(start.x+mid.x)/2,y:(start.y+mid.y)/2},mid2={x:(mid.x+end.x)/2,y:(mid.y+end.y)/2},slope1=-(start.x-mid.x)/(start.y-mid.y),slope2=-(mid.x-end.x)/(mid.y-end.y),centerX=(mid1.y-mid2.y+slope2*mid2.x-slope1*mid1.x)/(slope2-slope1),centerY=mid1.y+slope1*(centerX-mid1.x);return{x:centerX,y:centerY}}function calculateRadius(center2,point42){return Math.sqrt((center2.x-point42.x)**2+(center2.y-point42.y)**2)}function calculateAngle(center2,point42){return Math.atan2(point42.y-center2.y,point42.x-center2.x)}var getArcLength=(start,mid,end)=>{let center2=calculateCenter(start,mid,end),radius=calculateRadius(center2,start),angleStart=calculateAngle(center2,start),angleMid=calculateAngle(center2,mid),angleEnd=calculateAngle(center2,end),ccwToMid=directedAngleCCW(angleStart,angleMid),ccwToEnd=directedAngleCCW(angleStart,angleEnd),angleDelta=ccwToEnd;return ccwToMid>ccwToEnd&&(angleDelta=ccwToEnd-TWO_PI),Math.abs(radius*angleDelta)};function generateArcPath(start,mid,end,numPoints){let center2=calculateCenter(start,mid,end),radius=calculateRadius(center2,start),angleStart=calculateAngle(center2,start),angleMid=calculateAngle(center2,mid),angleEnd=calculateAngle(center2,end),ccwToMid=directedAngleCCW(angleStart,angleMid),ccwToEnd=directedAngleCCW(angleStart,angleEnd),angleDelta=ccwToEnd;ccwToMid>ccwToEnd&&(angleDelta=ccwToEnd-TWO_PI);let path=[];for(let i2=0;i2<=numPoints;i2++){let angle=angleStart+i2/numPoints*angleDelta,x5=center2.x+radius*Math.cos(angle),y5=center2.y+radius*Math.sin(angle);path.push({x:x5,y:y5})}return path}var makePoint=p4=>Array.isArray(p4)?{x:p4[0],y:p4[1]}:p4,pointsEqual=(p12,p22,tolerance=1e-4)=>Math.abs(p12.x-p22.x)<tolerance&&Math.abs(p12.y-p22.y)<tolerance,findClosedPolygons=segments=>{let polygons=[],used=new Set;for(let i2=0;i2<segments.length;i2++){if(used.has(i2))continue;let polygon2=[segments[i2]];used.add(i2);let currentEnd=segments[i2].end,foundNext=!0;for(;foundNext;){if(foundNext=!1,polygon2.length>1&&pointsEqual(currentEnd,polygon2[0].start)){polygons.push(polygon2);break}for(let j4=0;j4<segments.length;j4++)if(!used.has(j4)){if(pointsEqual(currentEnd,segments[j4].start)){polygon2.push(segments[j4]),used.add(j4),currentEnd=segments[j4].end,foundNext=!0;break}else if(pointsEqual(currentEnd,segments[j4].end)){segments[j4].type==="arc"?polygon2.push({...segments[j4],reversed:!0}):polygon2.push({...segments[j4],start:segments[j4].end,end:segments[j4].start}),used.add(j4),currentEnd=segments[j4].start,foundNext=!0;break}}if(!foundNext){for(let k4=polygon2.length-1;k4>=0;k4--){let idx=segments.indexOf(polygon2[k4]);idx!==-1&&used.delete(idx)}break}}}return polygons},polygonToPoints=polygon2=>{let points=[];for(let segment2 of polygon2)if(segment2.type==="line")points.push(segment2.start);else if(segment2.type==="arc"&&segment2.mid){let arcLength=getArcLength(segment2.start,segment2.mid,segment2.end),numPoints=Math.max(3,Math.ceil(arcLength)),arcPoints=generateArcPath(segment2.start,segment2.mid,segment2.end,numPoints);segment2.reversed&&(arcPoints=arcPoints.reverse()),points.push(...arcPoints.slice(0,-1))}return points};function getSilkscreenFontSizeFromFpTexts(fp_texts){if(!Array.isArray(fp_texts))return null;let refText=fp_texts.find(t5=>t5.layer?.toLowerCase()==="f.silks"&&(t5.text?.includes("${REFERENCE}")||t5.fp_text_type?.toLowerCase()==="reference"||t5.text?.match(/^R\d+|C\d+|U\d+/))),fallbackText=refText||fp_texts.find(t5=>t5.layer?.toLowerCase()==="f.fab"&&(t5.text?.includes("${REFERENCE}")||t5.fp_text_type?.toLowerCase()==="reference")),target=refText||fallbackText;if(!target?.effects?.font?.size)return null;let[width,height]=target.effects.font.size;return height??width??1}var degToRad=deg=>deg*Math.PI/180,rotatePoint3=(x5,y5,deg)=>{let r4=degToRad(deg),cos4=Math.cos(r4),sin4=Math.sin(r4);return{x:x5*cos4-y5*sin4,y:x5*sin4+y5*cos4}},getAxisAlignedRectFromPoints=points=>{let uniquePoints=[...new Map(points.map(p4=>[`${p4.x},${p4.y}`,p4])).values()];if(uniquePoints.length!==4)return null;let xs3=uniquePoints.map(p4=>p4.x),ys3=uniquePoints.map(p4=>p4.y),uniqueXs=[...new Set(xs3)],uniqueYs=[...new Set(ys3)];if(uniqueXs.length!==2||uniqueYs.length!==2)return null;let[minX,maxX]=uniqueXs.sort((a2,b3)=>a2-b3),[minY,maxY]=uniqueYs.sort((a2,b3)=>a2-b3);return minX===void 0||maxX===void 0||minY===void 0||maxY===void 0?null:{x:(minX+maxX)/2,y:(minY+maxY)/2,width:maxX-minX,height:maxY-minY}},fpPolyHasFill=fill=>{if(!fill)return!1;let normalized=fill.toLowerCase();return normalized!=="no"&&normalized!=="none"&&normalized!=="outline"},getRotationDeg=at4=>at4&&Array.isArray(at4)&&at4.length>=3&&typeof at4[2]=="number"?at4[2]:0,isNinetyLike=deg=>{let n3=(deg%360+360)%360;return n3===90||n3===270},normalizePortName=name=>{if(name!=null)return`${name}`},getPinNumber=name=>{let normalized=normalizePortName(name),parsed=normalized!==void 0?Number(normalized):NaN;return Number.isFinite(parsed)?parsed:void 0},debug23=(0,import_debug20.default)("kicad-mod-converter"),convertKicadLayerToTscircuitLayer=kicadLayer=>{switch(kicadLayer.toLowerCase()){case"f.cu":case"f.fab":case"f.silks":case"edge.cuts":return"top";case"b.cu":case"b.fab":case"b.silks":return"bottom"}},convertKicadJsonToTsCircuitSoup=async kicadJson=>{let{fp_lines,fp_texts,fp_arcs,fp_circles,pads,properties,holes,fp_polys}=kicadJson,circuitJson=[];circuitJson.push({type:"source_component",source_component_id:"source_component_0",supplier_part_numbers:{}}),circuitJson.push({type:"schematic_component",schematic_component_id:"schematic_component_0",source_component_id:"source_component_0",center:{x:0,y:0},rotation:0,size:{width:0,height:0}});let portNames=new Set,portNameToPinNumber=new Map;for(let pad2 of pads){let portName=normalizePortName(pad2.name);if(portName){portNames.add(portName);let pinNumber=getPinNumber(pad2.name);pinNumber!==void 0&&portNameToPinNumber.set(portName,pinNumber)}}if(holes)for(let hole of holes){let portName=normalizePortName(hole.name);if(portName){portNames.add(portName);let pinNumber=getPinNumber(hole.name);pinNumber!==void 0&&portNameToPinNumber.set(portName,pinNumber)}}let sourcePortId=0,portNameToSourcePortId=new Map;for(let portName of portNames){let source_port_id=`source_port_${sourcePortId++}`;portNameToSourcePortId.set(portName,source_port_id);let pinNumber=portNameToPinNumber.get(portName);circuitJson.push({type:"source_port",source_port_id,source_component_id:"source_component_0",name:portName,port_hints:[portName],pin_number:pinNumber,pin_label:pinNumber!==void 0?`pin${pinNumber}`:void 0}),circuitJson.push({type:"schematic_port",schematic_port_id:`schematic_port_${sourcePortId++}`,source_port_id,schematic_component_id:"schematic_component_0",center:{x:0,y:0}})}let minX=Number.POSITIVE_INFINITY,maxX=Number.NEGATIVE_INFINITY,minY=Number.POSITIVE_INFINITY,maxY=Number.NEGATIVE_INFINITY;for(let pad2 of pads){let x5=pad2.at[0],y5=-pad2.at[1],w4=pad2.size[0],h4=pad2.size[1];minX=Math.min(minX,x5-w4/2),maxX=Math.max(maxX,x5+w4/2),minY=Math.min(minY,y5-h4/2),maxY=Math.max(maxY,y5+h4/2)}let pcb_component_id="pcb_component_0";circuitJson.push({type:"pcb_component",source_component_id:"source_component_0",pcb_component_id,layer:"top",center:{x:0,y:0},rotation:0,width:Number.isFinite(minX)?maxX-minX:0,height:Number.isFinite(minY)?maxY-minY:0});let pcbPortId=0,portNameToPcbPortId=new Map;for(let portName of portNames){let pcb_port_id=`pcb_port_${pcbPortId++}`,source_port_id=portNameToSourcePortId.get(portName);portNameToPcbPortId.set(portName,pcb_port_id);let x5=0,y5=0,layers=["top","bottom"],pad2=pads.find(p4=>normalizePortName(p4.name)===portName);if(pad2)x5=pad2.at[0],y5=-pad2.at[1],layers=pad2.layers?pad2.layers.map(l3=>convertKicadLayerToTscircuitLayer(l3)).filter(Boolean):["top","bottom"];else if(holes){let hole=holes.find(h4=>normalizePortName(h4.name)===portName);hole&&(x5=hole.at[0],y5=-hole.at[1],layers=hole.layers?hole.layers.map(l3=>convertKicadLayerToTscircuitLayer(l3)).filter(Boolean):["top","bottom"])}circuitJson.push({type:"pcb_port",pcb_port_id,source_port_id,pcb_component_id,x:x5,y:y5,layers})}let smtpadId=0,platedHoleId=0,holeId=0;for(let pad2 of pads){let portName=normalizePortName(pad2.name),pinNumber=portName?portNameToPinNumber.get(portName):void 0;if(pad2.pad_type==="smd"){let rotation4=getRotationDeg(pad2.at),width=isNinetyLike(rotation4)?pad2.size[1]:pad2.size[0],height=isNinetyLike(rotation4)?pad2.size[0]:pad2.size[1],pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0,pinLabel=pinNumber!==void 0?`pin${pinNumber}`:void 0;circuitJson.push({type:"pcb_smtpad",pcb_smtpad_id:`pcb_smtpad_${smtpadId++}`,shape:"rect",x:pad2.at[0],y:-pad2.at[1],width,height,layer:convertKicadLayerToTscircuitLayer(pad2.layers?.[0]??"F.Cu"),pcb_component_id,port_hints:pinLabel?[pinLabel]:portName?[portName]:[],pcb_port_id,pin_number:pinNumber,pin_label:pinLabel})}else if(pad2.pad_type==="thru_hole"){if(pad2.pad_shape==="rect"){let rotation4=getRotationDeg(pad2.at),width=isNinetyLike(rotation4)?pad2.size[1]:pad2.size[0],height=isNinetyLike(rotation4)?pad2.size[0]:pad2.size[1],offX=pad2.drill?.offset?.[0]??0,offY=pad2.drill?.offset?.[1]??0,rotOff=rotatePoint3(offX,offY,rotation4),pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0,pinLabel=pinNumber!==void 0?`pin${pinNumber}`:void 0;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"circular_hole_with_rect_pad",hole_shape:"circle",pad_shape:"rect",x:pad2.at[0],y:-pad2.at[1],hole_offset_x:-rotOff.x,hole_offset_y:-rotOff.y,hole_diameter:pad2.drill?.width,rect_pad_width:width,rect_pad_height:height,layers:["top","bottom"],pcb_component_id,port_hints:pinLabel?[pinLabel]:portName?[portName]:[],pcb_port_id,pin_number:pinNumber,pin_label:pinLabel})}else if(pad2.pad_shape==="circle"){let pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0,pinLabel=pinNumber!==void 0?`pin${pinNumber}`:void 0;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"circle",x:pad2.at[0],y:-pad2.at[1],outer_diameter:pad2.size[0],hole_diameter:pad2.drill?.width,layers:["top","bottom"],pcb_component_id,port_hints:pinLabel?[pinLabel]:portName?[portName]:[],pcb_port_id,pin_number:pinNumber,pin_label:pinLabel})}else if(pad2.pad_shape==="oval"){let pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0,pinLabel=pinNumber!==void 0?`pin${pinNumber}`:void 0;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"pill",x:pad2.at[0],y:-pad2.at[1],outer_width:pad2.size[0],outer_height:pad2.size[1],hole_width:pad2.drill?.width,hole_height:pad2.drill?.height,layers:["top","bottom"],pcb_component_id,port_hints:pinLabel?[pinLabel]:portName?[portName]:[],pcb_port_id,pin_number:pinNumber,pin_label:pinLabel})}}else pad2.pad_type==="np_thru_hole"&&circuitJson.push({type:"pcb_hole",pcb_hole_id:`pcb_hole_${holeId++}`,x:pad2.at[0],y:-pad2.at[1],hole_diameter:pad2.drill?.width,pcb_component_id})}if(holes)for(let hole of holes){let portName=normalizePortName(hole.name),pinNumber=portName?portNameToPinNumber.get(portName):void 0,hasCuLayer=hole.layers?.some(l3=>l3.endsWith(".Cu")||l3==="*.Cu"),rotation4=getRotationDeg(hole.at),offX=hole.drill?.offset?.[0]??0,offY=hole.drill?.offset?.[1]??0,rotOff=rotatePoint3(offX,offY,rotation4),x5=hole.at[0]+rotOff.x,y5=-(hole.at[1]+rotOff.y),holeDiameter=hole.drill?.width??0,outerDiameter=hole.size?.width??holeDiameter,rr4=hole.roundrect_rratio??0,rectBorderRadius=rr4>0?Math.min(isNinetyLike(rotation4)?hole.size?.height??outerDiameter:hole.size?.width??outerDiameter,isNinetyLike(rotation4)?hole.size?.width??outerDiameter:hole.size?.height??outerDiameter)/2*rr4:0;if(hasCuLayer)if(hole.pad_shape==="rect"){let pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"circular_hole_with_rect_pad",hole_shape:"circle",pad_shape:"rect",x:hole.at[0],y:-hole.at[1],hole_offset_x:-rotOff.x,hole_offset_y:-rotOff.y,hole_diameter:holeDiameter,rect_pad_width:isNinetyLike(rotation4)?hole.size?.height??outerDiameter:hole.size?.width??outerDiameter,rect_pad_height:isNinetyLike(rotation4)?hole.size?.width??outerDiameter:hole.size?.height??outerDiameter,rect_border_radius:rectBorderRadius,port_hints:pinNumber!==void 0?[`pin${pinNumber}`]:portName?[portName]:[],layers:["top","bottom"],pcb_component_id,pcb_port_id,pin_number:pinNumber,pin_label:pinNumber!==void 0?`pin${pinNumber}`:void 0})}else if(hole.pad_shape==="oval"){let pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"pill",x:x5,y:y5,outer_width:isNinetyLike(rotation4)?hole.size?.height??outerDiameter:hole.size?.width??outerDiameter,outer_height:isNinetyLike(rotation4)?hole.size?.width??outerDiameter:hole.size?.height??outerDiameter,hole_width:isNinetyLike(rotation4)?hole.drill?.height??holeDiameter:hole.drill?.width??holeDiameter,hole_height:isNinetyLike(rotation4)?hole.drill?.width??holeDiameter:hole.drill?.height??holeDiameter,port_hints:pinNumber!==void 0?[`pin${pinNumber}`]:portName?[portName]:[],layers:["top","bottom"],pcb_component_id,pcb_port_id,pin_number:pinNumber,pin_label:pinNumber!==void 0?`pin${pinNumber}`:void 0})}else if(hole.pad_shape==="roundrect"){let pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0,offX2=hole.drill?.offset?.[0]??0,offY2=hole.drill?.offset?.[1]??0,rotOff2=rotatePoint3(offX2,offY2,rotation4),width=isNinetyLike(rotation4)?hole.size?.height??outerDiameter:hole.size?.width??outerDiameter,height=isNinetyLike(rotation4)?hole.size?.width??outerDiameter:hole.size?.height??outerDiameter;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"circular_hole_with_rect_pad",hole_shape:"circle",pad_shape:"rect",x:x5,y:y5,hole_offset_x:-rotOff2.x,hole_offset_y:rotOff2.y,hole_diameter:holeDiameter,rect_pad_width:width,rect_pad_height:height,rect_border_radius:rectBorderRadius,port_hints:pinNumber!==void 0?[`pin${pinNumber}`]:portName?[portName]:[],layers:["top","bottom"],pcb_component_id,pcb_port_id,pin_number:pinNumber,pin_label:pinNumber!==void 0?`pin${pinNumber}`:void 0})}else{let pcb_port_id=portName?portNameToPcbPortId.get(portName):void 0;circuitJson.push({type:"pcb_plated_hole",pcb_plated_hole_id:`pcb_plated_hole_${platedHoleId++}`,shape:"circle",x:x5,y:y5,outer_diameter:outerDiameter,hole_diameter:holeDiameter,port_hints:pinNumber!==void 0?[`pin${pinNumber}`]:portName?[portName]:[],layers:["top","bottom"],pcb_component_id,pcb_port_id,pin_number:pinNumber,pin_label:pinNumber!==void 0?`pin${pinNumber}`:void 0})}else circuitJson.push({type:"pcb_hole",pcb_hole_id:`pcb_hole_${holeId++}`,x:x5,y:y5,hole_diameter:outerDiameter,hole_shape:"circle",pcb_component_id})}let edgeCutSegments=[];for(let fp_line2 of fp_lines)fp_line2.layer.toLowerCase()==="edge.cuts"&&edgeCutSegments.push({type:"line",start:{x:fp_line2.start[0],y:fp_line2.start[1]},end:{x:fp_line2.end[0],y:fp_line2.end[1]},strokeWidth:fp_line2.stroke.width});for(let fp_arc of fp_arcs)fp_arc.layer.toLowerCase()==="edge.cuts"&&edgeCutSegments.push({type:"arc",start:{x:fp_arc.start[0],y:fp_arc.start[1]},mid:{x:fp_arc.mid[0],y:fp_arc.mid[1]},end:{x:fp_arc.end[0],y:fp_arc.end[1]},strokeWidth:fp_arc.stroke.width});let closedPolygons=findClosedPolygons(edgeCutSegments),cutoutId=0;for(let polygon2 of closedPolygons){let points=polygonToPoints(polygon2);points.length>=3&&circuitJson.push({type:"pcb_cutout",pcb_cutout_id:`pcb_cutout_${cutoutId++}`,shape:"polygon",points:points.map(p4=>({x:p4.x,y:-p4.y})),pcb_component_id})}let traceId=0,silkPathId=0,fabPathId=0,noteLineId=0;for(let fp_line2 of fp_lines){let route=[{x:fp_line2.start[0],y:-fp_line2.start[1]},{x:fp_line2.end[0],y:-fp_line2.end[1]}],lowerLayer=fp_line2.layer.toLowerCase();lowerLayer==="f.cu"?circuitJson.push({type:"pcb_trace",pcb_trace_id:`pcb_trace_${traceId++}`,pcb_component_id,layer:convertKicadLayerToTscircuitLayer(fp_line2.layer),route,thickness:fp_line2.stroke.width}):lowerLayer==="f.silks"?circuitJson.push({type:"pcb_silkscreen_path",pcb_silkscreen_path_id:`pcb_silkscreen_path_${silkPathId++}`,pcb_component_id,layer:"top",route,stroke_width:fp_line2.stroke.width}):lowerLayer==="edge.cuts"?debug23("Skipping Edge.Cuts fp_line (converted to pcb_cutout)",fp_line2.layer):lowerLayer==="f.fab"?circuitJson.push({type:"pcb_fabrication_note_path",fabrication_note_path_id:`fabrication_note_path_${fabPathId++}`,pcb_component_id,layer:"top",route,stroke_width:fp_line2.stroke.width,port_hints:[]}):lowerLayer.startsWith("user.")?circuitJson.push({type:"pcb_note_line",pcb_note_line_id:`pcb_note_line_${noteLineId++}`,pcb_component_id,x1:fp_line2.start[0],y1:-fp_line2.start[1],x2:fp_line2.end[0],y2:-fp_line2.end[1],stroke_width:fp_line2.stroke.width}):debug23("Unhandled layer for fp_line",fp_line2.layer)}if(fp_polys)for(let fp_poly of fp_polys){let route=[],pushRoutePoint=point42=>{!Number.isFinite(point42.x)||!Number.isFinite(point42.y)||route.push(point42)};for(let segment2 of fp_poly.pts){if(Array.isArray(segment2)){pushRoutePoint({x:segment2[0],y:-segment2[1]});continue}if(segment2&&typeof segment2=="object"&&"kind"in segment2){if(segment2.kind==="arc"){let start=makePoint(segment2.start),mid=makePoint(segment2.mid),end=makePoint(segment2.end),arcLength=getArcLength(start,mid,end),numPoints=Math.max(8,Math.ceil(arcLength)),adjustedNumPoints=Math.max(2,Math.ceil(arcLength/.1)),arcPoints=generateArcPath(start,mid,end,adjustedNumPoints).map(p4=>({x:p4.x,y:-p4.y}));for(let point42 of arcPoints)pushRoutePoint(point42)}continue}}let routePoints=route,polygonPoints=routePoints.length>2&&routePoints[0].x===routePoints[routePoints.length-1].x&&routePoints[0].y===routePoints[routePoints.length-1].y?routePoints.slice(0,-1):routePoints;if(routePoints.length===0)continue;let strokeWidth=fp_poly.stroke?.width??0;if(fp_poly.layer.endsWith(".Cu")){let rect=getAxisAlignedRectFromPoints(polygonPoints);rect?circuitJson.push({type:"pcb_smtpad",pcb_smtpad_id:`pcb_smtpad_${smtpadId++}`,shape:"rect",x:rect.x,y:rect.y,width:rect.width,height:rect.height,layer:convertKicadLayerToTscircuitLayer(fp_poly.layer),pcb_component_id}):fpPolyHasFill(fp_poly.fill)?polygonPoints.length>=3?circuitJson.push({type:"pcb_smtpad",pcb_smtpad_id:`pcb_smtpad_${smtpadId++}`,shape:"polygon",points:polygonPoints,layer:convertKicadLayerToTscircuitLayer(fp_poly.layer),pcb_component_id}):polygonPoints.length>=2&&circuitJson.push({type:"pcb_trace",pcb_trace_id:`pcb_trace_${traceId++}`,pcb_component_id,layer:convertKicadLayerToTscircuitLayer(fp_poly.layer),route:polygonPoints,thickness:strokeWidth}):polygonPoints.length>=2&&circuitJson.push({type:"pcb_trace",pcb_trace_id:`pcb_trace_${traceId++}`,pcb_component_id,layer:convertKicadLayerToTscircuitLayer(fp_poly.layer),route:polygonPoints,thickness:strokeWidth})}else fp_poly.layer.endsWith(".SilkS")?circuitJson.push({type:"pcb_silkscreen_path",pcb_silkscreen_path_id:`pcb_silkscreen_path_${silkPathId++}`,pcb_component_id,layer:convertKicadLayerToTscircuitLayer(fp_poly.layer),route:routePoints,stroke_width:strokeWidth}):fp_poly.layer.endsWith(".Fab")?circuitJson.push({type:"pcb_fabrication_note_path",fabrication_note_path_id:`fabrication_note_path_${fabPathId++}`,pcb_component_id,layer:convertKicadLayerToTscircuitLayer(fp_poly.layer),route:polygonPoints,stroke_width:strokeWidth,port_hints:[]}):debug23("Unhandled layer for fp_poly",fp_poly.layer)}let notePathId=0;for(let fp_arc of fp_arcs){let lowerLayer=fp_arc.layer.toLowerCase();if(lowerLayer==="edge.cuts"){debug23("Skipping Edge.Cuts fp_arc (converted to pcb_cutout)",fp_arc.layer);continue}let start=makePoint(fp_arc.start),mid=makePoint(fp_arc.mid),end=makePoint(fp_arc.end),arcLength=getArcLength(start,mid,end),arcPoints=generateArcPath(start,mid,end,Math.ceil(arcLength));if(lowerLayer.startsWith("user.")){circuitJson.push({type:"pcb_note_path",pcb_note_path_id:`pcb_note_path_${notePathId++}`,pcb_component_id,route:arcPoints.map(p4=>({x:p4.x,y:-p4.y})),stroke_width:fp_arc.stroke.width});continue}let tscircuitLayer=convertKicadLayerToTscircuitLayer(fp_arc.layer);if(!tscircuitLayer){debug23("Unable to convert layer for fp_arc",fp_arc.layer);continue}circuitJson.push({type:"pcb_silkscreen_path",pcb_silkscreen_path_id:`pcb_silkscreen_path_${silkPathId++}`,layer:tscircuitLayer,pcb_component_id,route:arcPoints.map(p4=>({x:p4.x,y:-p4.y})),stroke_width:fp_arc.stroke.width})}if(fp_circles)for(let fp_circle of fp_circles){let lowerLayer=fp_circle.layer.toLowerCase(),center2=makePoint(fp_circle.center),endPoint=makePoint(fp_circle.end),radius=Math.sqrt((endPoint.x-center2.x)**2+(endPoint.y-center2.y)**2),numPoints=Math.max(16,Math.ceil(2*Math.PI*radius)),circlePoints=[];for(let i2=0;i2<=numPoints;i2++){let angle=i2/numPoints*2*Math.PI;circlePoints.push({x:center2.x+radius*Math.cos(angle),y:center2.y+radius*Math.sin(angle)})}lowerLayer.startsWith("user.")&&circuitJson.push({type:"pcb_note_path",pcb_note_path_id:`pcb_note_path_${notePathId++}`,pcb_component_id,route:circlePoints.map(p4=>({x:p4.x,y:-p4.y})),stroke_width:fp_circle.stroke.width})}for(let fp_text of fp_texts){let layerRef=convertKicadLayerToTscircuitLayer(fp_text.layer);fp_text.layer.endsWith(".SilkS")?circuitJson.push({type:"pcb_silkscreen_text",layer:layerRef,font:"tscircuit2024",font_size:fp_text.effects?.font?.size[0]??1,pcb_component_id,anchor_position:{x:fp_text.at[0],y:-fp_text.at[1]},anchor_alignment:"center",text:fp_text.text}):fp_text.layer.endsWith(".Fab")?circuitJson.push({type:"pcb_fabrication_note_text",layer:layerRef,font:"tscircuit2024",font_size:fp_text.effects?.font?.size[0]??1,pcb_component_id,anchor_position:{x:fp_text.at[0],y:-fp_text.at[1]},anchor_alignment:"center",text:fp_text.text}):debug23("Unhandled layer for fp_text",fp_text.layer)}let refProp=properties.find(prop=>prop.key==="Reference"),valProp=properties.find(prop=>prop.key==="Value"),propFabTexts=[refProp,valProp].filter(p4=>p4&&!!p4.val);for(let propFab of propFabTexts){let at4=propFab.attributes.at;if(!at4)continue;let isFabLayer=propFab.attributes.layer?.toLowerCase()?.endsWith(".fab"),font_size=getSilkscreenFontSizeFromFpTexts(fp_texts);circuitJson.push({type:isFabLayer?"pcb_fabrication_note_text":"pcb_silkscreen_text",layer:"top",font:"tscircuit2024",font_size,pcb_component_id,anchor_position:{x:at4[0],y:-at4[1]},anchor_alignment:"center",text:propFab.val})}return circuitJson},parseKicadModToCircuitJson=async kicadMod=>{let kicadJson=parseKicadModToKicadJson(kicadMod);return await convertKicadJsonToTsCircuitSoup(kicadJson)};var transformJsDelivrImports=code=>code.replace(/from\s*["']\/npm\//g,'from "https://cdn.jsdelivr.net/npm/').replace(/import\s*\(\s*["']\/npm\//g,'import("https://cdn.jsdelivr.net/npm/'),dynamicallyLoadDependencyWithCdnBackup=async packageName=>{try{return(await import(packageName)).default}catch{console.log(`Failed to load ${packageName} locally, trying CDN fallback...`);try{let res2=await fetch(`https://cdn.jsdelivr.net/npm/${packageName}/+esm`);if(!res2.ok)throw new Error(`Failed to fetch ${packageName} from CDN: ${res2.statusText}`);let code=await res2.text();code=transformJsDelivrImports(code);let blob=new Blob([code],{type:"application/javascript"}),url=URL.createObjectURL(blob);try{let{default:loadedModule}=await import(url);return loadedModule}finally{URL.revokeObjectURL(url)}}catch(cdnError){throw console.error(`CDN fallback for ${packageName} also failed:`,cdnError),cdnError}}};var import_debug21=__toESM(require_browser(),1),debug12=(0,import_debug21.default)("tscircuit-eval:utils:partsEngineWithFileSystemCache");function createPartsEngineCacheKey(params){let{sourceComponent,footprinterString}=params;return{type:sourceComponent.type,ftype:sourceComponent.ftype,...sourceComponent.resistance&&{resistance:sourceComponent.resistance},...sourceComponent.capacitance&&{capacitance:sourceComponent.capacitance},...sourceComponent.inductance&&{inductance:sourceComponent.inductance},...sourceComponent.frequency&&{frequency:sourceComponent.frequency},...sourceComponent.load_capacitance&&{load_capacitance:sourceComponent.load_capacitance},...sourceComponent.voltage&&{voltage:sourceComponent.voltage},...sourceComponent.max_resistance&&{max_resistance:sourceComponent.max_resistance},...sourceComponent.pin_count&&{pin_count:sourceComponent.pin_count},...sourceComponent.gender&&{gender:sourceComponent.gender},...sourceComponent.transistor_type&&{transistor_type:sourceComponent.transistor_type},...sourceComponent.mosfet_mode&&{mosfet_mode:sourceComponent.mosfet_mode},...sourceComponent.channel_type&&{channel_type:sourceComponent.channel_type},...footprinterString&&{footprinterString}}}function partsEngineWithFilesystemCache(baseEngine,cacheEngine){return cacheEngine?{findPart:async params=>{let cacheKey=createPartsEngineCacheKey(params);try{let cached=await cacheEngine.get(JSON.stringify(cacheKey));if(cached)return JSON.parse(cached)}catch{}let result=await baseEngine.findPart(params);debug12("found part",{cacheKey,result});try{await cacheEngine.set(JSON.stringify(cacheKey),JSON.stringify(result))}catch{}return result}}:baseEngine}var KICAD_FOOTPRINT_CACHE_URL="https://kicad-mod-cache.tscircuit.com",ngspiceEngineCache=null,getPlatformConfig=(options={})=>({partsEngine:partsEngineWithFilesystemCache(jlcPartsEngine,options.filesystemCache),spiceEngineMap:{ngspice:{simulate:async spice=>{if(!ngspiceEngineCache){let createNgspiceSpiceEngine=await dynamicallyLoadDependencyWithCdnBackup("@tscircuit/ngspice-spice-engine").catch(error=>{throw new Error("Could not load ngspice engine from local node_modules or CDN fallback.",{cause:error})});createNgspiceSpiceEngine&&(ngspiceEngineCache=await createNgspiceSpiceEngine())}if(!ngspiceEngineCache)throw new Error("Could not load ngspice engine from local node_modules or CDN fallback.");return ngspiceEngineCache.simulate(spice)}}},footprintLibraryMap:{kicad:async footprintName=>{let baseUrl=`${KICAD_FOOTPRINT_CACHE_URL}/${footprintName}`,circuitJsonUrl=`${baseUrl}.circuit.json`,raw=await(await fetch(circuitJsonUrl)).json(),filtered=Array.isArray(raw)?raw.filter(el2=>el2?.type==="pcb_silkscreen_text"?el2?.text==="REF**":!0):raw,wrlUrl=`${baseUrl}.wrl`;return{footprintCircuitJson:filtered,cadModel:{wrlUrl,modelUnitToMmScale:2.54}}}},footprintFileParserMap:{kicad_mod:{loadFromUrl:async url=>{let kicadContent=await fetch(url).then(res2=>res2.text()),kicadJson=await parseKicadModToCircuitJson(kicadContent);return{footprintCircuitJson:Array.isArray(kicadJson)?kicadJson:[kicadJson]}}}}});var tslib_es6_exports={};__export(tslib_es6_exports,{__addDisposableResource:()=>__addDisposableResource,__assign:()=>__assign,__asyncDelegator:()=>__asyncDelegator,__asyncGenerator:()=>__asyncGenerator,__asyncValues:()=>__asyncValues,__await:()=>__await,__awaiter:()=>__awaiter,__classPrivateFieldGet:()=>__classPrivateFieldGet,__classPrivateFieldIn:()=>__classPrivateFieldIn,__classPrivateFieldSet:()=>__classPrivateFieldSet,__createBinding:()=>__createBinding,__decorate:()=>__decorate,__disposeResources:()=>__disposeResources,__esDecorate:()=>__esDecorate,__exportStar:()=>__exportStar,__extends:()=>__extends,__generator:()=>__generator,__importDefault:()=>__importDefault,__importStar:()=>__importStar,__makeTemplateObject:()=>__makeTemplateObject,__metadata:()=>__metadata,__param:()=>__param,__propKey:()=>__propKey,__read:()=>__read,__rest:()=>__rest,__rewriteRelativeImportExtension:()=>__rewriteRelativeImportExtension,__runInitializers:()=>__runInitializers,__setFunctionName:()=>__setFunctionName,__spread:()=>__spread,__spreadArray:()=>__spreadArray,__spreadArrays:()=>__spreadArrays,__values:()=>__values,default:()=>tslib_es6_default});var extendStatics=function(d3,b3){return extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d4,b4){d4.__proto__=b4}||function(d4,b4){for(var p4 in b4)Object.prototype.hasOwnProperty.call(b4,p4)&&(d4[p4]=b4[p4])},extendStatics(d3,b3)};function __extends(d3,b3){if(typeof b3!="function"&&b3!==null)throw new TypeError("Class extends value "+String(b3)+" is not a constructor or null");extendStatics(d3,b3);function __(){this.constructor=d3}d3.prototype=b3===null?Object.create(b3):(__.prototype=b3.prototype,new __)}var __assign=function(){return __assign=Object.assign||function(t5){for(var s2,i2=1,n3=arguments.length;i2<n3;i2++){s2=arguments[i2];for(var p4 in s2)Object.prototype.hasOwnProperty.call(s2,p4)&&(t5[p4]=s2[p4])}return t5},__assign.apply(this,arguments)};function __rest(s2,e4){var t5={};for(var p4 in s2)Object.prototype.hasOwnProperty.call(s2,p4)&&e4.indexOf(p4)<0&&(t5[p4]=s2[p4]);if(s2!=null&&typeof Object.getOwnPropertySymbols=="function")for(var i2=0,p4=Object.getOwnPropertySymbols(s2);i2<p4.length;i2++)e4.indexOf(p4[i2])<0&&Object.prototype.propertyIsEnumerable.call(s2,p4[i2])&&(t5[p4[i2]]=s2[p4[i2]]);return t5}function __decorate(decorators,target,key,desc){var c3=arguments.length,r4=c3<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d3;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r4=Reflect.decorate(decorators,target,key,desc);else for(var i2=decorators.length-1;i2>=0;i2--)(d3=decorators[i2])&&(r4=(c3<3?d3(r4):c3>3?d3(target,key,r4):d3(target,key))||r4);return c3>3&&r4&&Object.defineProperty(target,key,r4),r4}function __param(paramIndex,decorator){return function(target,key){decorator(target,key,paramIndex)}}function __esDecorate(ctor,descriptorIn,decorators,contextIn,initializers,extraInitializers){function accept(f2){if(f2!==void 0&&typeof f2!="function")throw new TypeError("Function expected");return f2}for(var kind=contextIn.kind,key=kind==="getter"?"get":kind==="setter"?"set":"value",target=!descriptorIn&&ctor?contextIn.static?ctor:ctor.prototype:null,descriptor=descriptorIn||(target?Object.getOwnPropertyDescriptor(target,contextIn.name):{}),_5,done=!1,i2=decorators.length-1;i2>=0;i2--){var context={};for(var p4 in contextIn)context[p4]=p4==="access"?{}:contextIn[p4];for(var p4 in contextIn.access)context.access[p4]=contextIn.access[p4];context.addInitializer=function(f2){if(done)throw new TypeError("Cannot add initializers after decoration has completed");extraInitializers.push(accept(f2||null))};var result=(0,decorators[i2])(kind==="accessor"?{get:descriptor.get,set:descriptor.set}:descriptor[key],context);if(kind==="accessor"){if(result===void 0)continue;if(result===null||typeof result!="object")throw new TypeError("Object expected");(_5=accept(result.get))&&(descriptor.get=_5),(_5=accept(result.set))&&(descriptor.set=_5),(_5=accept(result.init))&&initializers.unshift(_5)}else(_5=accept(result))&&(kind==="field"?initializers.unshift(_5):descriptor[key]=_5)}target&&Object.defineProperty(target,contextIn.name,descriptor),done=!0}function __runInitializers(thisArg,initializers,value){for(var useValue=arguments.length>2,i2=0;i2<initializers.length;i2++)value=useValue?initializers[i2].call(thisArg,value):initializers[i2].call(thisArg);return useValue?value:void 0}function __propKey(x5){return typeof x5=="symbol"?x5:"".concat(x5)}function __setFunctionName(f2,name,prefix){return typeof name=="symbol"&&(name=name.description?"[".concat(name.description,"]"):""),Object.defineProperty(f2,"name",{configurable:!0,value:prefix?"".concat(prefix," ",name):name})}function __metadata(metadataKey,metadataValue){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(metadataKey,metadataValue)}function __awaiter(thisArg,_arguments,P5,generator){function adopt(value){return value instanceof P5?value:new P5(function(resolve){resolve(value)})}return new(P5||(P5=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e4){reject(e4)}}function rejected(value){try{step(generator.throw(value))}catch(e4){reject(e4)}}function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})}function __generator(thisArg,body){var _5={label:0,sent:function(){if(t5[0]&1)throw t5[1];return t5[1]},trys:[],ops:[]},f2,y5,t5,g7=Object.create((typeof Iterator=="function"?Iterator:Object).prototype);return g7.next=verb(0),g7.throw=verb(1),g7.return=verb(2),typeof Symbol=="function"&&(g7[Symbol.iterator]=function(){return this}),g7;function verb(n3){return function(v5){return step([n3,v5])}}function step(op2){if(f2)throw new TypeError("Generator is already executing.");for(;g7&&(g7=0,op2[0]&&(_5=0)),_5;)try{if(f2=1,y5&&(t5=op2[0]&2?y5.return:op2[0]?y5.throw||((t5=y5.return)&&t5.call(y5),0):y5.next)&&!(t5=t5.call(y5,op2[1])).done)return t5;switch(y5=0,t5&&(op2=[op2[0]&2,t5.value]),op2[0]){case 0:case 1:t5=op2;break;case 4:return _5.label++,{value:op2[1],done:!1};case 5:_5.label++,y5=op2[1],op2=[0];continue;case 7:op2=_5.ops.pop(),_5.trys.pop();continue;default:if(t5=_5.trys,!(t5=t5.length>0&&t5[t5.length-1])&&(op2[0]===6||op2[0]===2)){_5=0;continue}if(op2[0]===3&&(!t5||op2[1]>t5[0]&&op2[1]<t5[3])){_5.label=op2[1];break}if(op2[0]===6&&_5.label<t5[1]){_5.label=t5[1],t5=op2;break}if(t5&&_5.label<t5[2]){_5.label=t5[2],_5.ops.push(op2);break}t5[2]&&_5.ops.pop(),_5.trys.pop();continue}op2=body.call(thisArg,_5)}catch(e4){op2=[6,e4],y5=0}finally{f2=t5=0}if(op2[0]&5)throw op2[1];return{value:op2[0]?op2[1]:void 0,done:!0}}}var __createBinding=Object.create?(function(o3,m3,k4,k22){k22===void 0&&(k22=k4);var desc=Object.getOwnPropertyDescriptor(m3,k4);(!desc||("get"in desc?!m3.__esModule:desc.writable||desc.configurable))&&(desc={enumerable:!0,get:function(){return m3[k4]}}),Object.defineProperty(o3,k22,desc)}):(function(o3,m3,k4,k22){k22===void 0&&(k22=k4),o3[k22]=m3[k4]});function __exportStar(m3,o3){for(var p4 in m3)p4!=="default"&&!Object.prototype.hasOwnProperty.call(o3,p4)&&__createBinding(o3,m3,p4)}function __values(o3){var s2=typeof Symbol=="function"&&Symbol.iterator,m3=s2&&o3[s2],i2=0;if(m3)return m3.call(o3);if(o3&&typeof o3.length=="number")return{next:function(){return o3&&i2>=o3.length&&(o3=void 0),{value:o3&&o3[i2++],done:!o3}}};throw new TypeError(s2?"Object is not iterable.":"Symbol.iterator is not defined.")}function __read(o3,n3){var m3=typeof Symbol=="function"&&o3[Symbol.iterator];if(!m3)return o3;var i2=m3.call(o3),r4,ar4=[],e4;try{for(;(n3===void 0||n3-- >0)&&!(r4=i2.next()).done;)ar4.push(r4.value)}catch(error){e4={error}}finally{try{r4&&!r4.done&&(m3=i2.return)&&m3.call(i2)}finally{if(e4)throw e4.error}}return ar4}function __spread(){for(var ar4=[],i2=0;i2<arguments.length;i2++)ar4=ar4.concat(__read(arguments[i2]));return ar4}function __spreadArrays(){for(var s2=0,i2=0,il2=arguments.length;i2<il2;i2++)s2+=arguments[i2].length;for(var r4=Array(s2),k4=0,i2=0;i2<il2;i2++)for(var a2=arguments[i2],j4=0,jl2=a2.length;j4<jl2;j4++,k4++)r4[k4]=a2[j4];return r4}function __spreadArray(to3,from,pack2){if(pack2||arguments.length===2)for(var i2=0,l3=from.length,ar4;i2<l3;i2++)(ar4||!(i2 in from))&&(ar4||(ar4=Array.prototype.slice.call(from,0,i2)),ar4[i2]=from[i2]);return to3.concat(ar4||Array.prototype.slice.call(from))}function __await(v5){return this instanceof __await?(this.v=v5,this):new __await(v5)}function __asyncGenerator(thisArg,_arguments,generator){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var g7=generator.apply(thisArg,_arguments||[]),i2,q4=[];return i2=Object.create((typeof AsyncIterator=="function"?AsyncIterator:Object).prototype),verb("next"),verb("throw"),verb("return",awaitReturn),i2[Symbol.asyncIterator]=function(){return this},i2;function awaitReturn(f2){return function(v5){return Promise.resolve(v5).then(f2,reject)}}function verb(n3,f2){g7[n3]&&(i2[n3]=function(v5){return new Promise(function(a2,b3){q4.push([n3,v5,a2,b3])>1||resume(n3,v5)})},f2&&(i2[n3]=f2(i2[n3])))}function resume(n3,v5){try{step(g7[n3](v5))}catch(e4){settle(q4[0][3],e4)}}function step(r4){r4.value instanceof __await?Promise.resolve(r4.value.v).then(fulfill,reject):settle(q4[0][2],r4)}function fulfill(value){resume("next",value)}function reject(value){resume("throw",value)}function settle(f2,v5){f2(v5),q4.shift(),q4.length&&resume(q4[0][0],q4[0][1])}}function __asyncDelegator(o3){var i2,p4;return i2={},verb("next"),verb("throw",function(e4){throw e4}),verb("return"),i2[Symbol.iterator]=function(){return this},i2;function verb(n3,f2){i2[n3]=o3[n3]?function(v5){return(p4=!p4)?{value:__await(o3[n3](v5)),done:!1}:f2?f2(v5):v5}:f2}}function __asyncValues(o3){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var m3=o3[Symbol.asyncIterator],i2;return m3?m3.call(o3):(o3=typeof __values=="function"?__values(o3):o3[Symbol.iterator](),i2={},verb("next"),verb("throw"),verb("return"),i2[Symbol.asyncIterator]=function(){return this},i2);function verb(n3){i2[n3]=o3[n3]&&function(v5){return new Promise(function(resolve,reject){v5=o3[n3](v5),settle(resolve,reject,v5.done,v5.value)})}}function settle(resolve,reject,d3,v5){Promise.resolve(v5).then(function(v7){resolve({value:v7,done:d3})},reject)}}function __makeTemplateObject(cooked,raw){return Object.defineProperty?Object.defineProperty(cooked,"raw",{value:raw}):cooked.raw=raw,cooked}var __setModuleDefault=Object.create?(function(o3,v5){Object.defineProperty(o3,"default",{enumerable:!0,value:v5})}):function(o3,v5){o3.default=v5},ownKeys=function(o3){return ownKeys=Object.getOwnPropertyNames||function(o4){var ar4=[];for(var k4 in o4)Object.prototype.hasOwnProperty.call(o4,k4)&&(ar4[ar4.length]=k4);return ar4},ownKeys(o3)};function __importStar(mod){if(mod&&mod.__esModule)return mod;var result={};if(mod!=null)for(var k4=ownKeys(mod),i2=0;i2<k4.length;i2++)k4[i2]!=="default"&&__createBinding(result,mod,k4[i2]);return __setModuleDefault(result,mod),result}function __importDefault(mod){return mod&&mod.__esModule?mod:{default:mod}}function __classPrivateFieldGet(receiver,state2,kind,f2){if(kind==="a"&&!f2)throw new TypeError("Private accessor was defined without a getter");if(typeof state2=="function"?receiver!==state2||!f2:!state2.has(receiver))throw new TypeError("Cannot read private member from an object whose class did not declare it");return kind==="m"?f2:kind==="a"?f2.call(receiver):f2?f2.value:state2.get(receiver)}function __classPrivateFieldSet(receiver,state2,value,kind,f2){if(kind==="m")throw new TypeError("Private method is not writable");if(kind==="a"&&!f2)throw new TypeError("Private accessor was defined without a setter");if(typeof state2=="function"?receiver!==state2||!f2:!state2.has(receiver))throw new TypeError("Cannot write private member to an object whose class did not declare it");return kind==="a"?f2.call(receiver,value):f2?f2.value=value:state2.set(receiver,value),value}function __classPrivateFieldIn(state2,receiver){if(receiver===null||typeof receiver!="object"&&typeof receiver!="function")throw new TypeError("Cannot use 'in' operator on non-object");return typeof state2=="function"?receiver===state2:state2.has(receiver)}function __addDisposableResource(env,value,async){if(value!=null){if(typeof value!="object"&&typeof value!="function")throw new TypeError("Object expected.");var dispose,inner;if(async){if(!Symbol.asyncDispose)throw new TypeError("Symbol.asyncDispose is not defined.");dispose=value[Symbol.asyncDispose]}if(dispose===void 0){if(!Symbol.dispose)throw new TypeError("Symbol.dispose is not defined.");dispose=value[Symbol.dispose],async&&(inner=dispose)}if(typeof dispose!="function")throw new TypeError("Object not disposable.");inner&&(dispose=function(){try{inner.call(this)}catch(e4){return Promise.reject(e4)}}),env.stack.push({value,dispose,async})}else async&&env.stack.push({async:!0});return value}var _SuppressedError=typeof SuppressedError=="function"?SuppressedError:function(error,suppressed,message){var e4=new Error(message);return e4.name="SuppressedError",e4.error=error,e4.suppressed=suppressed,e4};function __disposeResources(env){function fail(e4){env.error=env.hasError?new _SuppressedError(e4,env.error,"An error was suppressed during disposal."):e4,env.hasError=!0}var r4,s2=0;function next2(){for(;r4=env.stack.pop();)try{if(!r4.async&&s2===1)return s2=0,env.stack.push(r4),Promise.resolve().then(next2);if(r4.dispose){var result=r4.dispose.call(r4.value);if(r4.async)return s2|=2,Promise.resolve(result).then(next2,function(e4){return fail(e4),next2()})}else s2|=1}catch(e4){fail(e4)}if(s2===1)return env.hasError?Promise.reject(env.error):Promise.resolve();if(env.hasError)throw env.error}return next2()}function __rewriteRelativeImportExtension(path,preserveJsx){return typeof path=="string"&&/^\.\.?\//.test(path)?path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(m3,tsx,d3,ext,cm2){return tsx?preserveJsx?".jsx":".js":d3&&(!ext||!cm2)?m3:d3+ext+"."+cm2.toLowerCase()+"js"}):path}var tslib_es6_default={__extends,__assign,__rest,__decorate,__param,__esDecorate,__runInitializers,__propKey,__setFunctionName,__metadata,__awaiter,__generator,__createBinding,__exportStar,__values,__read,__spread,__spreadArrays,__spreadArray,__await,__asyncGenerator,__asyncDelegator,__asyncValues,__makeTemplateObject,__importStar,__importDefault,__classPrivateFieldGet,__classPrivateFieldSet,__classPrivateFieldIn,__addDisposableResource,__disposeResources,__rewriteRelativeImportExtension};var import_debug22=__toESM(require_browser(),1),debug13=(0,import_debug22.default)("tsci:eval:execution-context");function createExecutionContext(webWorkerConfiguration,opts={}){globalThis.React=React;let basePlatform=opts.platform||getPlatformConfig(),platform=opts.projectConfig?{...basePlatform,...opts.projectConfig}:basePlatform;platform.partsEngineDisabled&&(platform.partsEngine=void 0);let circuit=new RootCircuit({platform});opts.name&&(circuit.name=opts.name),opts.debugNamespace&&circuit.enableDebug(opts.debugNamespace);let logs=[];return{fsMap:{},entrypoint:"",logger:{info:message=>{logs.push({msg:message})},getLogs:()=>logs,stringifyLogs:()=>logs.map(log=>log.msg).join(`
|
|
625
625
|
`)},preSuppliedImports:{"@tscircuit/core":dist_exports4,tscircuit:dist_exports4,"@tscircuit/math-utils":dist_exports2,react:React,"react/jsx-runtime":ReactJsxRuntime,debug:import_debug22.default,tslib:tslib_es6_exports,"@tscircuit/props":{}},circuit,tsConfig:null,importStack:[],currentlyImporting:new Set,...webWorkerConfiguration}}function normalizeFilePath(filePath){let normFilePath=filePath;return normFilePath=normFilePath.replace(/\\/g,"/"),normFilePath=normFilePath.trim(),normFilePath.startsWith("./")&&(normFilePath=normFilePath.slice(2)),normFilePath.startsWith("/")&&(normFilePath=normFilePath.slice(1)),normFilePath}function normalizeFsMap(fsMap){let normalizedFsMap={};for(let[fsPath,fileContent]of Object.entries(fsMap))normalizedFsMap[normalizeFilePath(fsPath)]=fileContent;return normalizedFsMap}function dirname(path){if(!path)return".";let cleanPath=path.replace(/\\/g,"/").replace(/\/+$/,"");return cleanPath.indexOf("/")===-1?".":cleanPath.substring(0,cleanPath.lastIndexOf("/"))||"/"}function resolveRelativePath(importPath,cwd){if(importPath.startsWith("../")){let parentDir=dirname(cwd);return resolveRelativePath(importPath.slice(3),parentDir)}return importPath.startsWith("./")?resolveRelativePath(importPath.slice(2),cwd):importPath.startsWith("/")?importPath.slice(1):`${cwd}/${importPath}`}function getTsConfig(fsMapOrAllFilePaths){if(Array.isArray(fsMapOrAllFilePaths))return null;let tsconfigContent=fsMapOrAllFilePaths["tsconfig.json"];if(!tsconfigContent)return null;try{let sanitizedContent=tsconfigContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,"");return JSON.parse(sanitizedContent)}catch(e4){throw new Error(`Failed to parse tsconfig.json: ${e4.message}`)}}function resolveWithTsconfigPaths(opts){let{importPath,normalizedFilePathMap,extensions,tsConfig,tsconfigDir}=opts,paths=tsConfig?.compilerOptions?.paths;if(!paths)return null;let baseUrl=tsConfig?.compilerOptions?.baseUrl||".",tryResolveCandidate=candidate=>{let normalizedCandidate=normalizeFilePath(candidate);if(normalizedFilePathMap.has(normalizedCandidate))return normalizedFilePathMap.get(normalizedCandidate);for(let ext of extensions){let withExt=`${normalizedCandidate}.${ext}`;if(normalizedFilePathMap.has(withExt))return normalizedFilePathMap.get(withExt)}return null};for(let[alias,targets]of Object.entries(paths))if(alias.includes("*")){let[prefix,suffix]=alias.split("*");if(!importPath.startsWith(prefix)||!importPath.endsWith(suffix||""))continue;let starMatch=importPath.slice(prefix.length,importPath.length-(suffix?suffix.length:0));for(let target of targets){let replaced=target.replace("*",starMatch),candidate=baseUrl&&!replaced.startsWith("./")&&!replaced.startsWith("/")?`${baseUrl}/${replaced}`:replaced,resolved=tryResolveCandidate(candidate);if(resolved)return resolved}}else{if(importPath!==alias)continue;for(let target of targets){let candidate=baseUrl&&!target.startsWith("./")&&!target.startsWith("/")?`${baseUrl}/${target}`:target,resolved=tryResolveCandidate(candidate);if(resolved)return resolved}}let resolvedPathFromBaseUrl=resolveWithBaseUrl({importPath,normalizedFilePathMap,extensions,tsConfig,tsconfigDir});return resolvedPathFromBaseUrl||null}function resolveWithBaseUrl(opts){let{importPath,normalizedFilePathMap,extensions,tsConfig,tsconfigDir}=opts,baseUrl=tsConfig?.compilerOptions?.baseUrl;if(!baseUrl)return null;let filePathToResolve=`${tsconfigDir||"."}/${baseUrl}/${importPath}`;filePathToResolve=filePathToResolve.replace(/\/+/g,"/"),filePathToResolve=filePathToResolve.replace(/\/\.\//g,"/");let normalizedFilePath=normalizeFilePath(filePathToResolve);if(normalizedFilePathMap.has(normalizedFilePath))return normalizedFilePathMap.get(normalizedFilePath);for(let ext of extensions){let withExt=`${normalizedFilePath}.${ext}`;if(normalizedFilePathMap.has(withExt))return normalizedFilePathMap.get(withExt)}return null}function matchesTsconfigPathPattern(importPath,tsConfig){let paths=tsConfig?.compilerOptions?.paths;if(!paths)return!1;for(let[alias]of Object.entries(paths))if(alias.includes("*")){let[prefix,suffix]=alias.split("*");if(importPath.startsWith(prefix)&&importPath.endsWith(suffix||""))return!0}else if(importPath===alias)return!0;return!1}var FILE_EXTENSIONS=["tsx","ts","json","js","jsx","obj","gltf","glb","stl","step","stp"],resolveFilePath=(unknownFilePath,fsMapOrAllFilePaths,cwd,opts={})=>{let tsConfig=opts.tsConfig??null,isRelativeImport=unknownFilePath.startsWith("./")||unknownFilePath.startsWith("../"),hasBaseUrl=!!tsConfig?.compilerOptions?.baseUrl,resolvedPath=cwd&&(isRelativeImport||!hasBaseUrl)?resolveRelativePath(unknownFilePath,cwd):unknownFilePath,filePaths=new Set(Array.isArray(fsMapOrAllFilePaths)?fsMapOrAllFilePaths:Object.keys(fsMapOrAllFilePaths));if(filePaths.has(resolvedPath))return resolvedPath;let normalizedFilePathMap=new Map;for(let filePath of filePaths)normalizedFilePathMap.set(normalizeFilePath(filePath),filePath);let normalizedResolvedPath=normalizeFilePath(resolvedPath);if(isRelativeImport||!hasBaseUrl){if(normalizedFilePathMap.has(normalizedResolvedPath))return normalizedFilePathMap.get(normalizedResolvedPath);for(let ext of FILE_EXTENSIONS){let possibleFilePath=`${normalizedResolvedPath}.${ext}`;if(normalizedFilePathMap.has(possibleFilePath))return normalizedFilePathMap.get(possibleFilePath)}}if(!isRelativeImport){let resolvedPathFromPaths=resolveWithTsconfigPaths({importPath:unknownFilePath,normalizedFilePathMap,extensions:FILE_EXTENSIONS,tsConfig,tsconfigDir:opts.tsconfigDir});if(resolvedPathFromPaths)return resolvedPathFromPaths;let resolvedPathFromBaseUrl=resolveWithBaseUrl({importPath:unknownFilePath,normalizedFilePathMap,extensions:FILE_EXTENSIONS,tsConfig,tsconfigDir:opts.tsconfigDir});if(resolvedPathFromBaseUrl)return resolvedPathFromBaseUrl}if(!isRelativeImport&&!hasBaseUrl){let normalizedUnknownFilePath=normalizeFilePath(unknownFilePath);if(normalizedFilePathMap.has(normalizedUnknownFilePath))return normalizedFilePathMap.get(normalizedUnknownFilePath);for(let ext of FILE_EXTENSIONS){let possibleFilePath=`${normalizedUnknownFilePath}.${ext}`;if(normalizedFilePathMap.has(possibleFilePath))return normalizedFilePathMap.get(possibleFilePath)}}return null},resolveFilePathOrThrow=(unknownFilePath,fsMapOrAllFilePaths,cwd,opts={})=>{let resolvedFilePath=resolveFilePath(unknownFilePath,fsMapOrAllFilePaths,cwd,opts);if(!resolvedFilePath)throw new Error(`File not found "${unknownFilePath}", available paths:
|