Compare commits

..

2 Commits

Author SHA1 Message Date
cpu
ed1c4c4fd6 added export to pm4n 2026-06-08 00:45:38 +02:00
cpu
0cac6e76b6 preparing for MSLA exposure 2026-06-07 23:04:34 +02:00
9 changed files with 1078 additions and 48 deletions

View File

@@ -5942,6 +5942,396 @@
(net 15)
(uuid "e4f05a23-17c7-49d3-83b3-feda00e54574")
)
(zone
(net 1)
(net_name "GND")
(layer "F.Cu")
(uuid "2d17122f-408e-48d2-bc1c-935230b355ff")
(hatch edge 0.5)
(connect_pads
(clearance 0.5)
)
(min_thickness 0.25)
(filled_areas_thickness no)
(fill yes
(thermal_gap 0.5)
(thermal_bridge_width 0.5)
)
(polygon
(pts
(xy 132.15 42) (xy 182.15 42) (xy 182.15 92) (xy 132.15 92)
)
)
(filled_polygon
(layer "F.Cu")
(pts
(xy 181.592539 42.520185) (xy 181.638294 42.572989) (xy 181.6495 42.6245) (xy 181.6495 91.3755)
(xy 181.629815 91.442539) (xy 181.577011 91.488294) (xy 181.5255 91.4995) (xy 132.7745 91.4995)
(xy 132.707461 91.479815) (xy 132.661706 91.427011) (xy 132.6505 91.3755) (xy 132.6505 88.874038)
(xy 133.5495 88.874038) (xy 133.5495 89.125961) (xy 133.58891 89.374785) (xy 133.66676 89.614383)
(xy 133.781132 89.838848) (xy 133.929201 90.042649) (xy 133.929205 90.042654) (xy 134.107345 90.220794)
(xy 134.10735 90.220798) (xy 134.285117 90.349952) (xy 134.311155 90.36887) (xy 134.454184 90.441747)
(xy 134.535616 90.483239) (xy 134.535618 90.483239) (xy 134.535621 90.483241) (xy 134.775215 90.56109)
(xy 135.024038 90.6005) (xy 135.024039 90.6005) (xy 135.275961 90.6005) (xy 135.275962 90.6005)
(xy 135.524785 90.56109) (xy 135.764379 90.483241) (xy 135.988845 90.36887) (xy 136.192656 90.220793)
(xy 136.370793 90.042656) (xy 136.51887 89.838845) (xy 136.633241 89.614379) (xy 136.71109 89.374785)
(xy 136.7505 89.125962) (xy 136.7505 88.874038) (xy 177.5495 88.874038) (xy 177.5495 89.125961)
(xy 177.58891 89.374785) (xy 177.66676 89.614383) (xy 177.781132 89.838848) (xy 177.929201 90.042649)
(xy 177.929205 90.042654) (xy 178.107345 90.220794) (xy 178.10735 90.220798) (xy 178.285117 90.349952)
(xy 178.311155 90.36887) (xy 178.454184 90.441747) (xy 178.535616 90.483239) (xy 178.535618 90.483239)
(xy 178.535621 90.483241) (xy 178.775215 90.56109) (xy 179.024038 90.6005) (xy 179.024039 90.6005)
(xy 179.275961 90.6005) (xy 179.275962 90.6005) (xy 179.524785 90.56109) (xy 179.764379 90.483241)
(xy 179.988845 90.36887) (xy 180.192656 90.220793) (xy 180.370793 90.042656) (xy 180.51887 89.838845)
(xy 180.633241 89.614379) (xy 180.71109 89.374785) (xy 180.7505 89.125962) (xy 180.7505 88.874038)
(xy 180.71109 88.625215) (xy 180.633241 88.385621) (xy 180.633239 88.385618) (xy 180.633239 88.385616)
(xy 180.591747 88.304184) (xy 180.51887 88.161155) (xy 180.388031 87.98107) (xy 180.370798 87.95735)
(xy 180.370794 87.957345) (xy 180.192654 87.779205) (xy 180.192649 87.779201) (xy 179.988848 87.631132)
(xy 179.988847 87.631131) (xy 179.988845 87.63113) (xy 179.918747 87.595413) (xy 179.764383 87.51676)
(xy 179.524785 87.43891) (xy 179.275962 87.3995) (xy 179.024038 87.3995) (xy 178.899626 87.419205)
(xy 178.775214 87.43891) (xy 178.535616 87.51676) (xy 178.311151 87.631132) (xy 178.10735 87.779201)
(xy 178.107345 87.779205) (xy 177.929205 87.957345) (xy 177.929201 87.95735) (xy 177.781132 88.161151)
(xy 177.66676 88.385616) (xy 177.58891 88.625214) (xy 177.5495 88.874038) (xy 136.7505 88.874038)
(xy 136.71109 88.625215) (xy 136.633241 88.385621) (xy 136.633239 88.385618) (xy 136.633239 88.385616)
(xy 136.591747 88.304184) (xy 136.51887 88.161155) (xy 136.388031 87.98107) (xy 136.370798 87.95735)
(xy 136.370794 87.957345) (xy 136.192654 87.779205) (xy 136.192649 87.779201) (xy 135.988848 87.631132)
(xy 135.988847 87.631131) (xy 135.988845 87.63113) (xy 135.918747 87.595413) (xy 135.764383 87.51676)
(xy 135.524785 87.43891) (xy 135.275962 87.3995) (xy 135.024038 87.3995) (xy 134.899626 87.419205)
(xy 134.775214 87.43891) (xy 134.535616 87.51676) (xy 134.311151 87.631132) (xy 134.10735 87.779201)
(xy 134.107345 87.779205) (xy 133.929205 87.957345) (xy 133.929201 87.95735) (xy 133.781132 88.161151)
(xy 133.66676 88.385616) (xy 133.58891 88.625214) (xy 133.5495 88.874038) (xy 132.6505 88.874038)
(xy 132.6505 86.743075) (xy 138.6985 86.743075) (xy 138.6985 86.951724) (xy 138.731137 87.157789)
(xy 138.795612 87.35622) (xy 138.89033 87.542114) (xy 139.012965 87.710905) (xy 139.160495 87.858435)
(xy 139.329286 87.98107) (xy 139.417116 88.025821) (xy 139.515179 88.075787) (xy 139.515181 88.075787)
(xy 139.515184 88.075789) (xy 139.621545 88.110348) (xy 139.71361 88.140262) (xy 139.919676 88.1729)
(xy 139.919681 88.1729) (xy 140.128324 88.1729) (xy 140.334389 88.140262) (xy 140.532816 88.075789)
(xy 140.718714 87.98107) (xy 140.887505 87.858435) (xy 141.035035 87.710905) (xy 141.15767 87.542114)
(xy 141.252389 87.356216) (xy 141.316862 87.157789) (xy 141.320885 87.132389) (xy 141.3495 86.951724)
(xy 141.3495 86.743078) (xy 141.347778 86.732204) (xy 141.347778 86.732202) (xy 141.345477 86.717675)
(xy 161.5585 86.717675) (xy 161.5585 86.926324) (xy 161.591137 87.132389) (xy 161.655612 87.33082)
(xy 161.710687 87.43891) (xy 161.75033 87.516714) (xy 161.872965 87.685505) (xy 162.020495 87.833035)
(xy 162.189286 87.95567) (xy 162.239135 87.981069) (xy 162.375179 88.050387) (xy 162.375181 88.050387)
(xy 162.375184 88.050389) (xy 162.453351 88.075787) (xy 162.57361 88.114862) (xy 162.779676 88.1475)
(xy 162.779681 88.1475) (xy 162.988324 88.1475) (xy 163.194389 88.114862) (xy 163.392816 88.050389)
(xy 163.578714 87.95567) (xy 163.747505 87.833035) (xy 163.895035 87.685505) (xy 164.01767 87.516714)
(xy 164.112389 87.330816) (xy 164.176862 87.132389) (xy 164.2095 86.926324) (xy 164.2095 86.717675)
(xy 164.176862 86.51161) (xy 164.112387 86.313179) (xy 164.062421 86.215116) (xy 164.01767 86.127286)
(xy 163.895035 85.958495) (xy 163.747505 85.810965) (xy 163.578714 85.68833) (xy 163.39282 85.593612)
(xy 163.194389 85.529137) (xy 162.988324 85.4965) (xy 162.988319 85.4965) (xy 162.779681 85.4965)
(xy 162.779676 85.4965) (xy 162.57361 85.529137) (xy 162.375179 85.593612) (xy 162.189285 85.68833)
(xy 162.020493 85.810966) (xy 161.872966 85.958493) (xy 161.75033 86.127285) (xy 161.655612 86.313179)
(xy 161.591137 86.51161) (xy 161.5585 86.717675) (xy 141.345477 86.717675) (xy 141.316862 86.53701)
(xy 141.252387 86.338579) (xy 141.157669 86.152685) (xy 141.035035 85.983895) (xy 140.887505 85.836365)
(xy 140.718714 85.71373) (xy 140.53282 85.619012) (xy 140.334389 85.554537) (xy 140.128324 85.5219)
(xy 140.128319 85.5219) (xy 139.919681 85.5219) (xy 139.919676 85.5219) (xy 139.71361 85.554537)
(xy 139.515179 85.619012) (xy 139.329285 85.71373) (xy 139.160493 85.836366) (xy 139.012966 85.983893)
(xy 138.89033 86.152685) (xy 138.795612 86.338579) (xy 138.731137 86.53701) (xy 138.6985 86.743075)
(xy 132.6505 86.743075) (xy 132.6505 79.817294) (xy 151.065483 79.817294) (xy 157.751569 79.817294)
(xy 157.751569 76.975741) (xy 151.065483 76.975741) (xy 151.065483 79.817294) (xy 132.6505 79.817294)
(xy 132.6505 58.013713) (xy 138.1655 58.013713) (xy 138.1655 58.226287) (xy 138.198754 58.436243)
(xy 138.213145 58.480535) (xy 138.264444 58.638414) (xy 138.360951 58.82782) (xy 138.48589 58.999786)
(xy 138.636213 59.150109) (xy 138.808182 59.27505) (xy 138.816946 59.279516) (xy 138.867742 59.327491)
(xy 138.884536 59.395312) (xy 138.861998 59.461447) (xy 138.816946 59.500484) (xy 138.808182 59.504949)
(xy 138.636213 59.62989) (xy 138.48589 59.780213) (xy 138.360951 59.952179) (xy 138.264444 60.141585)
(xy 138.198753 60.34376) (xy 138.1655 60.553713) (xy 138.1655 60.766286) (xy 138.198753 60.976239)
(xy 138.264444 61.178414) (xy 138.360951 61.36782) (xy 138.48589 61.539786) (xy 138.636213 61.690109)
(xy 138.808182 61.81505) (xy 138.816946 61.819516) (xy 138.867742 61.867491) (xy 138.884536 61.935312)
(xy 138.861998 62.001447) (xy 138.816946 62.040484) (xy 138.808182 62.044949) (xy 138.636213 62.16989)
(xy 138.48589 62.320213) (xy 138.360951 62.492179) (xy 138.264444 62.681585) (xy 138.198753 62.88376)
(xy 138.1655 63.093713) (xy 138.1655 63.306286) (xy 138.198753 63.516239) (xy 138.264444 63.718414)
(xy 138.360951 63.90782) (xy 138.48589 64.079786) (xy 138.636213 64.230109) (xy 138.808182 64.35505)
(xy 138.816946 64.359516) (xy 138.867742 64.407491) (xy 138.884536 64.475312) (xy 138.861998 64.541447)
(xy 138.816946 64.580484) (xy 138.808182 64.584949) (xy 138.636213 64.70989) (xy 138.48589 64.860213)
(xy 138.360951 65.032179) (xy 138.264444 65.221585) (xy 138.198753 65.42376) (xy 138.1655 65.633713)
(xy 138.1655 65.846286) (xy 138.198753 66.056239) (xy 138.264444 66.258414) (xy 138.360951 66.44782)
(xy 138.48589 66.619786) (xy 138.636213 66.770109) (xy 138.808182 66.89505) (xy 138.816946 66.899516)
(xy 138.867742 66.947491) (xy 138.884536 67.015312) (xy 138.861998 67.081447) (xy 138.816946 67.120484)
(xy 138.808182 67.124949) (xy 138.636213 67.24989) (xy 138.48589 67.400213) (xy 138.360951 67.572179)
(xy 138.264444 67.761585) (xy 138.198753 67.96376) (xy 138.194162 67.992748) (xy 138.1655 68.173713)
(xy 138.1655 68.386287) (xy 138.198754 68.596243) (xy 138.239042 68.720237) (xy 138.264444 68.798414)
(xy 138.360951 68.98782) (xy 138.48589 69.159786) (xy 138.636213 69.310109) (xy 138.808182 69.43505)
(xy 138.816946 69.439516) (xy 138.867742 69.487491) (xy 138.884536 69.555312) (xy 138.861998 69.621447)
(xy 138.816946 69.660484) (xy 138.808182 69.664949) (xy 138.636213 69.78989) (xy 138.48589 69.940213)
(xy 138.360951 70.112179) (xy 138.264444 70.301585) (xy 138.198753 70.50376) (xy 138.1655 70.713713)
(xy 138.1655 70.926286) (xy 138.198753 71.136239) (xy 138.264444 71.338414) (xy 138.360951 71.52782)
(xy 138.48589 71.699786) (xy 138.636213 71.850109) (xy 138.808182 71.97505) (xy 138.816946 71.979516)
(xy 138.867742 72.027491) (xy 138.884536 72.095312) (xy 138.861998 72.161447) (xy 138.816946 72.200484)
(xy 138.808182 72.204949) (xy 138.636213 72.32989) (xy 138.48589 72.480213) (xy 138.360951 72.652179)
(xy 138.264444 72.841585) (xy 138.198753 73.04376) (xy 138.1655 73.253713) (xy 138.1655 73.466286)
(xy 138.198753 73.676239) (xy 138.264444 73.878414) (xy 138.360951 74.06782) (xy 138.48589 74.239786)
(xy 138.599818 74.353714) (xy 138.633303 74.415037) (xy 138.628319 74.484729) (xy 138.586447 74.540662)
(xy 138.555471 74.557577) (xy 138.423912 74.606646) (xy 138.423906 74.606649) (xy 138.308812 74.692809)
(xy 138.308809 74.692812) (xy 138.222649 74.807906) (xy 138.222645 74.807913) (xy 138.172403 74.94262)
(xy 138.172401 74.942627) (xy 138.166 75.002155) (xy 138.166 75.65) (xy 139.082988 75.65) (xy 139.050075 75.707007)
(xy 139.016 75.834174) (xy 139.016 75.965826) (xy 139.050075 76.092993) (xy 139.082988 76.15) (xy 138.166 76.15)
(xy 138.166 76.797844) (xy 138.172401 76.857372) (xy 138.172403 76.857379) (xy 138.222645 76.992086)
(xy 138.222649 76.992093) (xy 138.308809 77.107187) (xy 138.308812 77.10719) (xy 138.423906 77.19335)
(xy 138.423913 77.193354) (xy 138.55862 77.243596) (xy 138.558627 77.243598) (xy 138.618155 77.249999)
(xy 138.618172 77.25) (xy 139.266 77.25) (xy 139.266 76.333012) (xy 139.323007 76.365925) (xy 139.450174 76.4)
(xy 139.581826 76.4) (xy 139.708993 76.365925) (xy 139.766 76.333012) (xy 139.766 77.25) (xy 140.413828 77.25)
(xy 140.413844 77.249999) (xy 140.473372 77.243598) (xy 140.473379 77.243596) (xy 140.608086 77.193354)
(xy 140.608093 77.19335) (xy 140.723187 77.10719) (xy 140.72319 77.107187) (xy 140.80935 76.992093)
(xy 140.809354 76.992086) (xy 140.85077 76.881046) (xy 140.859596 76.85738) (xy 140.859598 76.857372)
(xy 140.865999 76.797844) (xy 140.866 76.797827) (xy 140.866 76.15) (xy 139.949012 76.15) (xy 139.981925 76.092993)
(xy 140.016 75.965826) (xy 140.016 75.834174) (xy 139.991761 75.743713) (xy 175.2745 75.743713)
(xy 175.2745 75.956286) (xy 175.307753 76.166239) (xy 175.373444 76.368414) (xy 175.469951 76.55782)
(xy 175.59489 76.729786) (xy 175.745209 76.880105) (xy 175.745214 76.880109) (xy 175.910218 76.999991)
(xy 175.952884 77.05532) (xy 175.958863 77.124934) (xy 175.926258 77.186729) (xy 175.910218 77.200627)
(xy 175.74554 77.320272) (xy 175.745535 77.320276) (xy 175.595276 77.470535) (xy 175.595272 77.47054)
(xy 175.470379 77.642442) (xy 175.373904 77.831782) (xy 175.308242 78.03387) (xy 175.308242 78.033873)
(xy 175.297769 78.1) (xy 176.345854 78.1) (xy 176.30737 78.166657) (xy 176.275 78.287465) (xy 176.275 78.412535)
(xy 176.30737 78.533343) (xy 176.345854 78.6) (xy 175.297769 78.6) (xy 175.308242 78.666126) (xy 175.308242 78.666129)
(xy 175.373904 78.868217) (xy 175.470379 79.057557) (xy 175.595272 79.229459) (xy 175.595276 79.229464)
(xy 175.734143 79.368331) (xy 175.767628 79.429654) (xy 175.762644 79.499346) (xy 175.720772 79.555279)
(xy 175.711559 79.561551) (xy 175.556342 79.657289) (xy 175.432289 79.781342) (xy 175.340187 79.930663)
(xy 175.340186 79.930666) (xy 175.285001 80.097203) (xy 175.285001 80.097204) (xy 175.285 80.097204)
(xy 175.2745 80.199983) (xy 175.2745 81.500001) (xy 175.274501 81.500018) (xy 175.285 81.602796)
(xy 175.285001 81.602799) (xy 175.340185 81.769331) (xy 175.340186 81.769334) (xy 175.432288 81.918656)
(xy 175.556344 82.042712) (xy 175.705666 82.134814) (xy 175.872203 82.189999) (xy 175.974991 82.2005)
(xy 177.525008 82.200499) (xy 177.627797 82.189999) (xy 177.794334 82.134814) (xy 177.943656 82.042712)
(xy 178.067712 81.918656) (xy 178.159814 81.769334) (xy 178.214999 81.602797) (xy 178.2255 81.500009)
(xy 178.225499 80.199992) (xy 178.214999 80.097203) (xy 178.159814 79.930666) (xy 178.067712 79.781344)
(xy 177.943656 79.657288) (xy 177.794334 79.565186) (xy 177.794332 79.565185) (xy 177.78844 79.561551)
(xy 177.741716 79.509603) (xy 177.730493 79.440641) (xy 177.758337 79.376558) (xy 177.765856 79.36833)
(xy 177.904728 79.229458) (xy 178.02962 79.057557) (xy 178.126095 78.868217) (xy 178.191757 78.666129)
(xy 178.191757 78.666126) (xy 178.202231 78.6) (xy 177.154146 78.6) (xy 177.19263 78.533343) (xy 177.225 78.412535)
(xy 177.225 78.287465) (xy 177.19263 78.166657) (xy 177.154146 78.1) (xy 178.202231 78.1) (xy 178.191757 78.033873)
(xy 178.191757 78.03387) (xy 178.126095 77.831782) (xy 178.02962 77.642442) (xy 177.904727 77.47054)
(xy 177.904723 77.470535) (xy 177.754464 77.320276) (xy 177.754459 77.320272) (xy 177.589781 77.200627)
(xy 177.547115 77.145297) (xy 177.541136 77.075684) (xy 177.573741 77.013889) (xy 177.589776 76.999994)
(xy 177.754792 76.880104) (xy 177.905104 76.729792) (xy 177.905106 76.729788) (xy 177.905109 76.729786)
(xy 178.030048 76.55782) (xy 178.030047 76.55782) (xy 178.030051 76.557816) (xy 178.126557 76.368412)
(xy 178.192246 76.166243) (xy 178.2255 75.956287) (xy 178.2255 75.743713) (xy 178.192246 75.533757)
(xy 178.126557 75.331588) (xy 178.030051 75.142184) (xy 178.030049 75.142181) (xy 178.030048 75.142179)
(xy 177.905109 74.970213) (xy 177.754786 74.81989) (xy 177.58282 74.694951) (xy 177.393414 74.598444)
(xy 177.393413 74.598443) (xy 177.393412 74.598443) (xy 177.191243 74.532754) (xy 177.191241 74.532753)
(xy 177.19124 74.532753) (xy 177.029957 74.507208) (xy 176.981287 74.4995) (xy 176.518713 74.4995)
(xy 176.470042 74.507208) (xy 176.30876 74.532753) (xy 176.106585 74.598444) (xy 175.917179 74.694951)
(xy 175.745213 74.81989) (xy 175.59489 74.970213) (xy 175.469951 75.142179) (xy 175.373444 75.331585)
(xy 175.307753 75.53376) (xy 175.2745 75.743713) (xy 139.991761 75.743713) (xy 139.981925 75.707007)
(xy 139.949012 75.65) (xy 140.866 75.65) (xy 140.866 75.002172) (xy 140.865999 75.002155) (xy 140.859598 74.942627)
(xy 140.859596 74.94262) (xy 140.809354 74.807913) (xy 140.80935 74.807906) (xy 140.72319 74.692812)
(xy 140.723187 74.692809) (xy 140.608093 74.606649) (xy 140.608088 74.606646) (xy 140.476528 74.557577)
(xy 140.420595 74.515705) (xy 140.396178 74.450241) (xy 140.41103 74.381968) (xy 140.432175 74.35372)
(xy 140.546104 74.239792) (xy 140.671051 74.067816) (xy 140.767557 73.878412) (xy 140.833246 73.676243)
(xy 140.8665 73.466287) (xy 140.8665 73.253713) (xy 140.833246 73.043757) (xy 140.767557 72.841588)
(xy 140.671051 72.652184) (xy 140.671049 72.652181) (xy 140.671048 72.652179) (xy 140.546109 72.480213)
(xy 140.395786 72.32989) (xy 140.22382 72.204951) (xy 140.223115 72.204591) (xy 140.215054 72.200485)
(xy 140.164259 72.152512) (xy 140.147463 72.084692) (xy 140.169999 72.018556) (xy 140.215054 71.979515)
(xy 140.223816 71.975051) (xy 140.245789 71.959086) (xy 140.395786 71.850109) (xy 140.395788 71.850106)
(xy 140.395792 71.850104) (xy 140.546104 71.699792) (xy 140.546106 71.699788) (xy 140.546109 71.699786)
(xy 140.671048 71.52782) (xy 140.671047 71.52782) (xy 140.671051 71.527816) (xy 140.767557 71.338412)
(xy 140.833246 71.136243) (xy 140.8665 70.926287) (xy 140.8665 70.713713) (xy 140.861379 70.681379)
(xy 148.9745 70.681379) (xy 148.9745 70.86862) (xy 149.011025 71.052243) (xy 149.011027 71.052251)
(xy 149.082676 71.225228) (xy 149.082681 71.225237) (xy 149.186697 71.380907) (xy 149.1867 71.380911)
(xy 149.319088 71.513299) (xy 149.319092 71.513302) (xy 149.474762 71.617318) (xy 149.474768 71.617321)
(xy 149.474769 71.617322) (xy 149.647749 71.688973) (xy 149.831379 71.725499) (xy 149.831383 71.7255)
(xy 149.831384 71.7255) (xy 150.018617 71.7255) (xy 150.018618 71.725499) (xy 150.202251 71.688973)
(xy 150.375231 71.617322) (xy 150.530908 71.513302) (xy 150.663302 71.380908) (xy 150.767322 71.225231)
(xy 150.838973 71.052251) (xy 150.8755 70.868616) (xy 150.8755 70.681384) (xy 150.838973 70.497749)
(xy 150.767322 70.324769) (xy 150.767321 70.324768) (xy 150.767318 70.324762) (xy 150.663302 70.169092)
(xy 150.663299 70.169088) (xy 150.661819 70.167608) (xy 150.661291 70.166641) (xy 150.659437 70.164382)
(xy 150.659865 70.16403) (xy 150.628334 70.106285) (xy 150.6255 70.079927) (xy 150.6255 68.970072)
(xy 150.645185 68.903033) (xy 150.661823 68.882387) (xy 150.668301 68.875909) (xy 150.668302 68.875908)
(xy 150.772322 68.720231) (xy 150.843973 68.547251) (xy 150.8805 68.363616) (xy 150.8805 68.176384)
(xy 150.843973 67.992749) (xy 150.772322 67.819769) (xy 150.772321 67.819768) (xy 150.772318 67.819762)
(xy 150.668302 67.664092) (xy 150.668299 67.664088) (xy 150.535911 67.5317) (xy 150.535907 67.531697)
(xy 150.380237 67.427681) (xy 150.380228 67.427676) (xy 150.207251 67.356027) (xy 150.207243 67.356025)
(xy 150.02362 67.3195) (xy 150.023616 67.3195) (xy 149.836384 67.3195) (xy 149.836379 67.3195) (xy 149.652756 67.356025)
(xy 149.652748 67.356027) (xy 149.479771 67.427676) (xy 149.479762 67.427681) (xy 149.324092 67.531697)
(xy 149.324088 67.5317) (xy 149.1917 67.664088) (xy 149.191697 67.664092) (xy 149.087681 67.819762)
(xy 149.087676 67.819771) (xy 149.016027 67.992748) (xy 149.016025 67.992756) (xy 148.9795 68.176379)
(xy 148.9795 68.36362) (xy 149.016025 68.547243) (xy 149.016027 68.547251) (xy 149.087676 68.720228)
(xy 149.087681 68.720237) (xy 149.191697 68.875907) (xy 149.195563 68.880618) (xy 149.193556 68.882264)
(xy 149.22165 68.933637) (xy 149.2245 68.960072) (xy 149.2245 70.079927) (xy 149.204815 70.146966)
(xy 149.188181 70.167608) (xy 149.1867 70.169088) (xy 149.186697 70.169092) (xy 149.082681 70.324762)
(xy 149.082676 70.324771) (xy 149.011027 70.497748) (xy 149.011025 70.497756) (xy 148.9745 70.681379)
(xy 140.861379 70.681379) (xy 140.833246 70.503757) (xy 140.767557 70.301588) (xy 140.671051 70.112184)
(xy 140.671049 70.112181) (xy 140.671048 70.112179) (xy 140.546109 69.940213) (xy 140.395786 69.78989)
(xy 140.22382 69.664951) (xy 140.223115 69.664591) (xy 140.215054 69.660485) (xy 140.164259 69.612512)
(xy 140.147463 69.544692) (xy 140.169999 69.478556) (xy 140.215054 69.439515) (xy 140.223816 69.435051)
(xy 140.245789 69.419086) (xy 140.395786 69.310109) (xy 140.395788 69.310106) (xy 140.395792 69.310104)
(xy 140.546104 69.159792) (xy 140.546106 69.159788) (xy 140.546109 69.159786) (xy 140.671048 68.98782)
(xy 140.671047 68.98782) (xy 140.671051 68.987816) (xy 140.767557 68.798412) (xy 140.833246 68.596243)
(xy 140.8665 68.386287) (xy 140.8665 68.173713) (xy 140.833246 67.963757) (xy 140.767557 67.761588)
(xy 140.671051 67.572184) (xy 140.671049 67.572181) (xy 140.671048 67.572179) (xy 140.546109 67.400213)
(xy 140.395786 67.24989) (xy 140.22382 67.124951) (xy 140.223115 67.124591) (xy 140.215054 67.120485)
(xy 140.164259 67.072512) (xy 140.147463 67.004692) (xy 140.169999 66.938556) (xy 140.215054 66.899515)
(xy 140.223816 66.895051) (xy 140.245789 66.879086) (xy 140.395786 66.770109) (xy 140.395788 66.770106)
(xy 140.395792 66.770104) (xy 140.546104 66.619792) (xy 140.546106 66.619788) (xy 140.546109 66.619786)
(xy 140.671048 66.44782) (xy 140.671047 66.44782) (xy 140.671051 66.447816) (xy 140.767557 66.258412)
(xy 140.833246 66.056243) (xy 140.8665 65.846287) (xy 140.8665 65.633713) (xy 140.833246 65.423757)
(xy 140.767557 65.221588) (xy 140.671051 65.032184) (xy 140.671049 65.032181) (xy 140.671048 65.032179)
(xy 140.546109 64.860213) (xy 140.395786 64.70989) (xy 140.22382 64.584951) (xy 140.223115 64.584591)
(xy 140.215054 64.580485) (xy 140.164259 64.532512) (xy 140.147463 64.464692) (xy 140.169999 64.398556)
(xy 140.215054 64.359515) (xy 140.223816 64.355051) (xy 140.245789 64.339086) (xy 140.395786 64.230109)
(xy 140.395788 64.230106) (xy 140.395792 64.230104) (xy 140.546104 64.079792) (xy 140.546106 64.079788)
(xy 140.546109 64.079786) (xy 140.671048 63.90782) (xy 140.671047 63.90782) (xy 140.671051 63.907816)
(xy 140.767557 63.718412) (xy 140.833246 63.516243) (xy 140.8665 63.306287) (xy 140.8665 63.093713)
(xy 140.833246 62.883757) (xy 140.767557 62.681588) (xy 140.671051 62.492184) (xy 140.671049 62.492181)
(xy 140.671048 62.492179) (xy 140.546109 62.320213) (xy 140.395786 62.16989) (xy 140.22382 62.044951)
(xy 140.223115 62.044591) (xy 140.215054 62.040485) (xy 140.164259 61.992512) (xy 140.147463 61.924692)
(xy 140.169999 61.858556) (xy 140.215054 61.819515) (xy 140.223816 61.815051) (xy 140.245789 61.799086)
(xy 140.395786 61.690109) (xy 140.395788 61.690106) (xy 140.395792 61.690104) (xy 140.546104 61.539792)
(xy 140.546106 61.539788) (xy 140.546109 61.539786) (xy 140.671048 61.36782) (xy 140.671047 61.36782)
(xy 140.671051 61.367816) (xy 140.767557 61.178412) (xy 140.833246 60.976243) (xy 140.8665 60.766287)
(xy 140.8665 60.553713) (xy 140.833246 60.343757) (xy 140.767557 60.141588) (xy 140.671051 59.952184)
(xy 140.671049 59.952181) (xy 140.671048 59.952179) (xy 140.546109 59.780213) (xy 140.395786 59.62989)
(xy 140.22382 59.504951) (xy 140.223115 59.504591) (xy 140.215054 59.500485) (xy 140.164259 59.452512)
(xy 140.147463 59.384692) (xy 140.169999 59.318556) (xy 140.215054 59.279515) (xy 140.223816 59.275051)
(xy 140.359245 59.176657) (xy 140.395786 59.150109) (xy 140.395788 59.150106) (xy 140.395792 59.150104)
(xy 140.546104 58.999792) (xy 140.546106 58.999788) (xy 140.546109 58.999786) (xy 140.671048 58.82782)
(xy 140.671047 58.82782) (xy 140.671051 58.827816) (xy 140.767557 58.638412) (xy 140.833246 58.436243)
(xy 140.8665 58.226287) (xy 140.8665 58.013713) (xy 140.833246 57.803757) (xy 140.767557 57.601588)
(xy 140.671051 57.412184) (xy 140.671049 57.412181) (xy 140.671048 57.412179) (xy 140.546109 57.240213)
(xy 140.395786 57.08989) (xy 140.22382 56.964951) (xy 140.034412 56.868443) (xy 140.029269 56.866772)
(xy 139.832243 56.802754) (xy 139.832241 56.802753) (xy 139.83224 56.802753) (xy 139.670957 56.777208)
(xy 139.622287 56.7695) (xy 139.409713 56.7695) (xy 139.361042 56.777208) (xy 139.19976 56.802753)
(xy 138.997585 56.868444) (xy 138.808179 56.964951) (xy 138.636213 57.08989) (xy 138.48589 57.240213)
(xy 138.360951 57.412179) (xy 138.264444 57.601585) (xy 138.198753 57.80376) (xy 138.185077 57.890109)
(xy 138.1655 58.013713) (xy 132.6505 58.013713) (xy 132.6505 56.753713) (xy 175.2645 56.753713)
(xy 175.2645 56.966287) (xy 175.297754 57.176243) (xy 175.318539 57.240213) (xy 175.363444 57.378414)
(xy 175.459951 57.56782) (xy 175.58489 57.739786) (xy 175.735209 57.890105) (xy 175.735214 57.890109)
(xy 175.900218 58.009991) (xy 175.942884 58.06532) (xy 175.948863 58.134934) (xy 175.916258 58.196729)
(xy 175.900218 58.210627) (xy 175.73554 58.330272) (xy 175.735535 58.330276) (xy 175.585276 58.480535)
(xy 175.585272 58.48054) (xy 175.460379 58.652442) (xy 175.363904 58.841782) (xy 175.298242 59.04387)
(xy 175.298242 59.043873) (xy 175.287769 59.11) (xy 176.335854 59.11) (xy 176.29737 59.176657) (xy 176.265 59.297465)
(xy 176.265 59.422535) (xy 176.29737 59.543343) (xy 176.335854 59.61) (xy 175.287769 59.61) (xy 175.298242 59.676126)
(xy 175.298242 59.676129) (xy 175.363904 59.878217) (xy 175.460379 60.067557) (xy 175.585272 60.239459)
(xy 175.585276 60.239464) (xy 175.724143 60.378331) (xy 175.757628 60.439654) (xy 175.752644 60.509346)
(xy 175.710772 60.565279) (xy 175.701559 60.571551) (xy 175.546342 60.667289) (xy 175.422289 60.791342)
(xy 175.330187 60.940663) (xy 175.330186 60.940666) (xy 175.275001 61.107203) (xy 175.275001 61.107204)
(xy 175.275 61.107204) (xy 175.2645 61.209983) (xy 175.2645 62.510001) (xy 175.264501 62.510018)
(xy 175.275 62.612796) (xy 175.275001 62.612799) (xy 175.297795 62.681585) (xy 175.330186 62.779334)
(xy 175.422288 62.928656) (xy 175.546344 63.052712) (xy 175.695666 63.144814) (xy 175.862203 63.199999)
(xy 175.964991 63.2105) (xy 177.515008 63.210499) (xy 177.617797 63.199999) (xy 177.784334 63.144814)
(xy 177.933656 63.052712) (xy 178.057712 62.928656) (xy 178.149814 62.779334) (xy 178.204999 62.612797)
(xy 178.2155 62.510009) (xy 178.215499 61.209992) (xy 178.204999 61.107203) (xy 178.149814 60.940666)
(xy 178.057712 60.791344) (xy 177.933656 60.667288) (xy 177.784334 60.575186) (xy 177.784332 60.575185)
(xy 177.77844 60.571551) (xy 177.731716 60.519603) (xy 177.720493 60.450641) (xy 177.748337 60.386558)
(xy 177.755856 60.37833) (xy 177.894728 60.239458) (xy 178.01962 60.067557) (xy 178.116095 59.878217)
(xy 178.181757 59.676129) (xy 178.181757 59.676126) (xy 178.192231 59.61) (xy 177.144146 59.61)
(xy 177.18263 59.543343) (xy 177.215 59.422535) (xy 177.215 59.297465) (xy 177.18263 59.176657)
(xy 177.144146 59.11) (xy 178.192231 59.11) (xy 178.181757 59.043873) (xy 178.181757 59.04387) (xy 178.116095 58.841782)
(xy 178.01962 58.652442) (xy 177.894727 58.48054) (xy 177.894723 58.480535) (xy 177.744464 58.330276)
(xy 177.744459 58.330272) (xy 177.579781 58.210627) (xy 177.537115 58.155297) (xy 177.531136 58.085684)
(xy 177.563741 58.023889) (xy 177.579776 58.009994) (xy 177.744792 57.890104) (xy 177.895104 57.739792)
(xy 177.895106 57.739788) (xy 177.895109 57.739786) (xy 178.020048 57.56782) (xy 178.020047 57.56782)
(xy 178.020051 57.567816) (xy 178.116557 57.378412) (xy 178.182246 57.176243) (xy 178.2155 56.966287)
(xy 178.2155 56.753713) (xy 178.182246 56.543757) (xy 178.116557 56.341588) (xy 178.020051 56.152184)
(xy 178.020049 56.152181) (xy 178.020048 56.152179) (xy 177.895109 55.980213) (xy 177.744786 55.82989)
(xy 177.57282 55.704951) (xy 177.383414 55.608444) (xy 177.383413 55.608443) (xy 177.383412 55.608443)
(xy 177.181243 55.542754) (xy 177.181241 55.542753) (xy 177.18124 55.542753) (xy 177.019957 55.517208)
(xy 176.971287 55.5095) (xy 176.508713 55.5095) (xy 176.460042 55.517208) (xy 176.29876 55.542753)
(xy 176.096585 55.608444) (xy 175.907179 55.704951) (xy 175.735213 55.82989) (xy 175.58489 55.980213)
(xy 175.459951 56.152179) (xy 175.363444 56.341585) (xy 175.297753 56.54376) (xy 175.2645 56.753713)
(xy 132.6505 56.753713) (xy 132.6505 47.074875) (xy 138.6223 47.074875) (xy 138.6223 47.283524)
(xy 138.654937 47.489589) (xy 138.719412 47.68802) (xy 138.797825 47.841914) (xy 138.81413 47.873914)
(xy 138.936765 48.042705) (xy 139.084295 48.190235) (xy 139.253086 48.31287) (xy 139.340916 48.357621)
(xy 139.438979 48.407587) (xy 139.438981 48.407587) (xy 139.438984 48.407589) (xy 139.538925 48.440062)
(xy 139.63741 48.472062) (xy 139.843476 48.5047) (xy 139.843481 48.5047) (xy 140.052124 48.5047)
(xy 140.258189 48.472062) (xy 140.456616 48.407589) (xy 140.642514 48.31287) (xy 140.811305 48.190235)
(xy 140.958835 48.042705) (xy 141.08147 47.873914) (xy 141.176189 47.688016) (xy 141.240662 47.489589)
(xy 141.24573 47.457589) (xy 141.2733 47.283524) (xy 141.2733 47.074876) (xy 141.270533 47.057408)
(xy 141.270533 47.057407) (xy 141.268231 47.042875) (xy 161.5077 47.042875) (xy 161.5077 47.251524)
(xy 161.540337 47.457589) (xy 161.604812 47.65602) (xy 161.69953 47.841914) (xy 161.822165 48.010705)
(xy 161.969695 48.158235) (xy 162.138486 48.28087) (xy 162.201288 48.312869) (xy 162.324379 48.375587)
(xy 162.324381 48.375587) (xy 162.324384 48.375589) (xy 162.42287 48.407589) (xy 162.52281 48.440062)
(xy 162.728876 48.4727) (xy 162.728881 48.4727) (xy 162.937524 48.4727) (xy 163.143589 48.440062)
(xy 163.162015 48.434075) (xy 163.342016 48.375589) (xy 163.527914 48.28087) (xy 163.696705 48.158235)
(xy 163.844235 48.010705) (xy 163.96687 47.841914) (xy 164.061589 47.656016) (xy 164.126062 47.457589)
(xy 164.126895 47.452328) (xy 164.1587 47.251524) (xy 164.1587 47.042875) (xy 164.126062 46.83681)
(xy 164.061587 46.638379) (xy 164.011621 46.540316) (xy 163.96687 46.452486) (xy 163.844235 46.283695)
(xy 163.696705 46.136165) (xy 163.527914 46.01353) (xy 163.34202 45.918812) (xy 163.143589 45.854337)
(xy 162.937524 45.8217) (xy 162.937519 45.8217) (xy 162.728881 45.8217) (xy 162.728876 45.8217)
(xy 162.52281 45.854337) (xy 162.324379 45.918812) (xy 162.138485 46.01353) (xy 161.969693 46.136166)
(xy 161.822166 46.283693) (xy 161.69953 46.452485) (xy 161.604812 46.638379) (xy 161.540337 46.83681)
(xy 161.5077 47.042875) (xy 141.268231 47.042875) (xy 141.240662 46.86881) (xy 141.176187 46.670379)
(xy 141.081469 46.484485) (xy 141.05822 46.452486) (xy 140.958835 46.315695) (xy 140.811305 46.168165)
(xy 140.642514 46.04553) (xy 140.636873 46.042656) (xy 140.45662 45.950812) (xy 140.258189 45.886337)
(xy 140.052124 45.8537) (xy 140.052119 45.8537) (xy 139.843481 45.8537) (xy 139.843476 45.8537)
(xy 139.63741 45.886337) (xy 139.438979 45.950812) (xy 139.253085 46.04553) (xy 139.084293 46.168166)
(xy 138.936766 46.315693) (xy 138.81413 46.484485) (xy 138.719412 46.670379) (xy 138.654937 46.86881)
(xy 138.6223 47.074875) (xy 132.6505 47.074875) (xy 132.6505 44.874038) (xy 133.5495 44.874038)
(xy 133.5495 45.125961) (xy 133.58891 45.374785) (xy 133.66676 45.614383) (xy 133.745413 45.768747)
(xy 133.772394 45.8217) (xy 133.781132 45.838848) (xy 133.929201 46.042649) (xy 133.929205 46.042654)
(xy 134.107345 46.220794) (xy 134.10735 46.220798) (xy 134.285117 46.349952) (xy 134.311155 46.36887)
(xy 134.454184 46.441747) (xy 134.535616 46.483239) (xy 134.535618 46.483239) (xy 134.535621 46.483241)
(xy 134.775215 46.56109) (xy 135.024038 46.6005) (xy 135.024039 46.6005) (xy 135.275961 46.6005)
(xy 135.275962 46.6005) (xy 135.524785 46.56109) (xy 135.764379 46.483241) (xy 135.988845 46.36887)
(xy 136.192656 46.220793) (xy 136.370793 46.042656) (xy 136.51887 45.838845) (xy 136.633241 45.614379)
(xy 136.682708 45.462135) (xy 167.6895 45.462135) (xy 167.6895 47.25787) (xy 167.689501 47.257876)
(xy 167.695908 47.317483) (xy 167.746202 47.452328) (xy 167.746206 47.452335) (xy 167.832452 47.567544)
(xy 167.832455 47.567547) (xy 167.947664 47.653793) (xy 167.947671 47.653797) (xy 167.992618 47.670561)
(xy 168.082517 47.704091) (xy 168.142127 47.7105) (xy 168.152685 47.710499) (xy 168.219723 47.730179)
(xy 168.240372 47.746818) (xy 168.910591 48.417037) (xy 168.847007 48.434075) (xy 168.732993 48.499901)
(xy 168.639901 48.592993) (xy 168.574075 48.707007) (xy 168.557037 48.770591) (xy 167.924728 48.138282)
(xy 167.924727 48.138282) (xy 167.88538 48.192439) (xy 167.788904 48.381782) (xy 167.723242 48.583869)
(xy 167.723242 48.583872) (xy 167.69 48.793753) (xy 167.69 49.006246) (xy 167.723242 49.216127)
(xy 167.723242 49.21613) (xy 167.788904 49.418217) (xy 167.885375 49.60755) (xy 167.924728 49.661716)
(xy 168.557037 49.029408) (xy 168.574075 49.092993) (xy 168.639901 49.207007) (xy 168.732993 49.300099)
(xy 168.847007 49.365925) (xy 168.91059 49.382962) (xy 168.278282 50.015269) (xy 168.278282 50.01527)
(xy 168.332452 50.054626) (xy 168.332451 50.054626) (xy 168.341495 50.059234) (xy 168.392292 50.107208)
(xy 168.409087 50.175029) (xy 168.38655 50.241164) (xy 168.341499 50.280202) (xy 168.332182 50.284949)
(xy 168.160213 50.40989) (xy 168.00989 50.560213) (xy 167.884951 50.732179) (xy 167.788444 50.921585)
(xy 167.722753 51.12376) (xy 167.6895 51.333713) (xy 167.6895 51.546286) (xy 167.722753 51.756239)
(xy 167.788444 51.958414) (xy 167.884951 52.14782) (xy 168.00989 52.319786) (xy 168.160213 52.470109)
(xy 168.332179 52.595048) (xy 168.332181 52.595049) (xy 168.332184 52.595051) (xy 168.521588 52.691557)
(xy 168.723757 52.757246) (xy 168.933713 52.7905) (xy 168.933714 52.7905) (xy 169.146286 52.7905)
(xy 169.146287 52.7905) (xy 169.356243 52.757246) (xy 169.558412 52.691557) (xy 169.747816 52.595051)
(xy 169.769789 52.579086) (xy 169.919786 52.470109) (xy 169.919788 52.470106) (xy 169.919792 52.470104)
(xy 170.070104 52.319792) (xy 170.070106 52.319788) (xy 170.070109 52.319786) (xy 170.195048 52.14782)
(xy 170.195047 52.14782) (xy 170.195051 52.147816) (xy 170.291557 51.958412) (xy 170.357246 51.756243)
(xy 170.3905 51.546287) (xy 170.3905 51.333713) (xy 170.357246 51.123757) (xy 170.291557 50.921588)
(xy 170.195051 50.732184) (xy 170.195049 50.732181) (xy 170.195048 50.732179) (xy 170.070109 50.560213)
(xy 169.919786 50.40989) (xy 169.747817 50.284949) (xy 169.738504 50.280204) (xy 169.687707 50.23223)
(xy 169.670912 50.164409) (xy 169.693449 50.098274) (xy 169.738507 50.059232) (xy 169.747555 50.054622)
(xy 169.801716 50.01527) (xy 169.801717 50.01527) (xy 169.169408 49.382962) (xy 169.232993 49.365925)
(xy 169.347007 49.300099) (xy 169.440099 49.207007) (xy 169.505925 49.092993) (xy 169.522962 49.029408)
(xy 170.15527 49.661717) (xy 170.15527 49.661716) (xy 170.194622 49.607554) (xy 170.291095 49.418217)
(xy 170.356757 49.21613) (xy 170.356757 49.216127) (xy 170.39 49.006246) (xy 170.39 48.793753) (xy 170.356757 48.583872)
(xy 170.356757 48.583869) (xy 170.291095 48.381782) (xy 170.194624 48.192449) (xy 170.15527 48.138282)
(xy 170.155269 48.138282) (xy 169.522962 48.77059) (xy 169.505925 48.707007) (xy 169.440099 48.592993)
(xy 169.347007 48.499901) (xy 169.232993 48.434075) (xy 169.169409 48.417037) (xy 169.839627 47.746818)
(xy 169.90095 47.713333) (xy 169.927307 47.710499) (xy 169.937872 47.710499) (xy 169.997483 47.704091)
(xy 170.132331 47.653796) (xy 170.247546 47.567546) (xy 170.333796 47.452331) (xy 170.384091 47.317483)
(xy 170.3905 47.257873) (xy 170.390499 45.462128) (xy 170.384091 45.402517) (xy 170.333796 45.267669)
(xy 170.333795 45.267668) (xy 170.333793 45.267664) (xy 170.247547 45.152455) (xy 170.247544 45.152452)
(xy 170.132335 45.066206) (xy 170.132328 45.066202) (xy 169.997482 45.015908) (xy 169.997483 45.015908)
(xy 169.937883 45.009501) (xy 169.937881 45.0095) (xy 169.937873 45.0095) (xy 169.937864 45.0095)
(xy 168.142129 45.0095) (xy 168.142123 45.009501) (xy 168.082516 45.015908) (xy 167.947671 45.066202)
(xy 167.947664 45.066206) (xy 167.832455 45.152452) (xy 167.832452 45.152455) (xy 167.746206 45.267664)
(xy 167.746202 45.267671) (xy 167.695908 45.402517) (xy 167.689501 45.462116) (xy 167.689501 45.462123)
(xy 167.6895 45.462135) (xy 136.682708 45.462135) (xy 136.68271 45.462129) (xy 136.696241 45.420487)
(xy 136.696241 45.420486) (xy 136.711089 45.374789) (xy 136.711089 45.374788) (xy 136.71109 45.374785)
(xy 136.7505 45.125962) (xy 136.7505 44.874038) (xy 177.5495 44.874038) (xy 177.5495 45.125961)
(xy 177.58891 45.374785) (xy 177.66676 45.614383) (xy 177.745413 45.768747) (xy 177.772394 45.8217)
(xy 177.781132 45.838848) (xy 177.929201 46.042649) (xy 177.929205 46.042654) (xy 178.107345 46.220794)
(xy 178.10735 46.220798) (xy 178.285117 46.349952) (xy 178.311155 46.36887) (xy 178.454184 46.441747)
(xy 178.535616 46.483239) (xy 178.535618 46.483239) (xy 178.535621 46.483241) (xy 178.775215 46.56109)
(xy 179.024038 46.6005) (xy 179.024039 46.6005) (xy 179.275961 46.6005) (xy 179.275962 46.6005)
(xy 179.524785 46.56109) (xy 179.764379 46.483241) (xy 179.988845 46.36887) (xy 180.192656 46.220793)
(xy 180.370793 46.042656) (xy 180.51887 45.838845) (xy 180.633241 45.614379) (xy 180.71109 45.374785)
(xy 180.7505 45.125962) (xy 180.7505 44.874038) (xy 180.71109 44.625215) (xy 180.633241 44.385621)
(xy 180.633239 44.385618) (xy 180.633239 44.385616) (xy 180.591747 44.304184) (xy 180.51887 44.161155)
(xy 180.499952 44.135117) (xy 180.370798 43.95735) (xy 180.370794 43.957345) (xy 180.192654 43.779205)
(xy 180.192649 43.779201) (xy 179.988848 43.631132) (xy 179.988847 43.631131) (xy 179.988845 43.63113)
(xy 179.918747 43.595413) (xy 179.764383 43.51676) (xy 179.524785 43.43891) (xy 179.275962 43.3995)
(xy 179.024038 43.3995) (xy 178.899626 43.419205) (xy 178.775214 43.43891) (xy 178.535616 43.51676)
(xy 178.311151 43.631132) (xy 178.10735 43.779201) (xy 178.107345 43.779205) (xy 177.929205 43.957345)
(xy 177.929201 43.95735) (xy 177.781132 44.161151) (xy 177.66676 44.385616) (xy 177.58891 44.625214)
(xy 177.5495 44.874038) (xy 136.7505 44.874038) (xy 136.71109 44.625215) (xy 136.633241 44.385621)
(xy 136.633239 44.385618) (xy 136.633239 44.385616) (xy 136.591747 44.304184) (xy 136.51887 44.161155)
(xy 136.499952 44.135117) (xy 136.370798 43.95735) (xy 136.370794 43.957345) (xy 136.192654 43.779205)
(xy 136.192649 43.779201) (xy 135.988848 43.631132) (xy 135.988847 43.631131) (xy 135.988845 43.63113)
(xy 135.918747 43.595413) (xy 135.764383 43.51676) (xy 135.524785 43.43891) (xy 135.275962 43.3995)
(xy 135.024038 43.3995) (xy 134.899626 43.419205) (xy 134.775214 43.43891) (xy 134.535616 43.51676)
(xy 134.311151 43.631132) (xy 134.10735 43.779201) (xy 134.107345 43.779205) (xy 133.929205 43.957345)
(xy 133.929201 43.95735) (xy 133.781132 44.161151) (xy 133.66676 44.385616) (xy 133.58891 44.625214)
(xy 133.5495 44.874038) (xy 132.6505 44.874038) (xy 132.6505 42.6245) (xy 132.670185 42.557461)
(xy 132.722989 42.511706) (xy 132.7745 42.5005) (xy 181.5255 42.5005)
)
)
)
(zone
(net 1)
(net_name "GND")

3
scripts/.gitignore vendored
View File

@@ -1,4 +1,5 @@
__pycache__/
panel/
gerbers/
output/
gcode/
.venv/

BIN
scripts/Dummy.pm4n Normal file

Binary file not shown.

View File

@@ -57,7 +57,11 @@ nano millproject
Run the export by providing the `.kicad_pcb` file as a first argument:
```bash
./export.sh panel/Flow_Controller_Panel.kicad_pcb
# Input layers/filenames and all milling/drilling parameters are taken from the config file: 'millproject'.
docker run --rm -i -t \
-u "$(id -u):$(id -g)" \
-v "$(pwd):/data" \
ptodorov/pcb2gcode
```
The script will first generate gerber files in the `gerbers` directory and then generate gcode files in the `gcode` directory.
@@ -75,3 +79,174 @@ Set up the entire back side as one big GND pour. Then, increase the thermal spok
![Thermal spoke width](../images/spoke_width.png)
# MSLA PCB Exposure: KiCad → Photon Mono 4
Convert KiCad PCB layers to `.pm4n` files for direct UV exposure on an **Anycubic Photon Mono 4** (9024×5120 px, 17 µm/px).
---
## Files
| File | Purpose |
|---|---|
| `export.sh` | Main entry point — exports Gerbers from KiCad, converts to `.pm4n` |
| `gerber_to_pm4n.py` | Python converter (Gerber → RLE → pm4n binary surgery) |
| `Dummy.pm4n` | Template file for your specific printer. |
---
## Setup
### 1. Create the Dummy.pm4n
Open **CHITUBOX_Basic** slicer, select printer **Anycubic Photon Mono 4**, slice any tiny STL (a 1×1×0.05 mm box), and save as `Dummy.pm4n` in the same directory as `export.sh`.
This file is reused for every job — it carries the correct LCD resolution metadata.
### 2. Install dependencies
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install pygerber Pillow numpy
```
Or activate the venv once and put `source .venv/bin/activate` in your shell profile.
---
## Usage
```
./export.sh [OPTIONS] <path/to/board.kicad_pcb>
```
### Options
| Option | Default | Description |
|---|---|---|
| `--layers L,L,...` | `Front,F.Mask` | KiCad layer names to process |
| `--invert L,L,...` | *(none)* | Layers to invert the image for |
| `--mirror L,L,...` | *(none)* | Layers to mirror X for |
| `--exposure N` | `60` | Exposure time in seconds |
| `--dummy FILE` | `./Dummy.pm4n` | Path to dummy template |
| `--out DIR` | `./output` | Output directory |
| `--dpmm N` | `58.824` | Render resolution (native = 17 µm/px) |
| `--pos X,Y` | centred | Board position in mm from top-left |
---
## Examples
### Typical: top copper, positive-working resist (Bungard standard)
```bash
./export.sh \
--layers Front \
--invert Front \
--mirror Front \
--exposure 60 \
panel/Flow_Controller_Panel.kicad_pcb
```
`--invert`: Bungard presensitized is positive-working — UV removes resist, so the background must be exposed (white) and traces must block UV (dark). The Gerber is positive (copper=white), so inversion is needed.
`--mirror`: the board sits copper-side-down on the FEP, so the image must be flipped so the pattern reads correctly through the board.
### Multiple layers (e.g. copper + soldermask)
```bash
./export.sh \
--layers Front,F.Mask \
--invert Front,F.Mask \
--mirror Front,F.Mask \
--exposure 60 \
panel/Flow_Controller_Panel.kicad_pcb
```
### Quick test at lower resolution (faster render)
```bash
./export.sh --dpmm 30 --layers Front --invert Front --mirror Front panel/Flow_Controller_Panel.kicad_pcb
```
### Using gerber_to_pm4n.py directly
```bash
python3 gerber_to_pm4n.py Dummy.pm4n output/gerbers/Flow_Controller_Panel-Front.gbr \
--invert --mirror --exposure 60
```
---
## Output structure
```
output/
├── gerbers/
│ ├── Flow_Controller_Panel-Front.gbr
│ └── Flow_Controller_Panel-F_Mask.gbr
└── pm4n/
├── Flow_Controller_Panel-Front.pm4n ← copy to USB, print on Mono 4
├── Flow_Controller_Panel-Front.preview.png ← visual check before printing
├── Flow_Controller_Panel-F_Mask.pm4n
└── Flow_Controller_Panel-F_Mask.preview.png
```
---
## Invert and mirror logic
| Setting | When to use |
|---|---|
| `--invert` | Positive-working resist (standard Bungard): UV removes resist → background must be white (exposed), traces black (masked) |
| no `--invert` | Negative-working resist: UV hardens resist → traces must be white |
| `--mirror` | Board placed **copper-side down** on FEP (normal for this workflow) |
| no `--mirror` | Board placed copper-side up |
When in doubt: check the `.preview.png` before printing. Traces should appear **dark** on a white background for standard Bungard positive-working boards.
---
## Exposure calibration
Start at **60 s** and bracket in ±15 s steps. Typical range for Bungard presensitized at 405 nm is 30120 s depending on board age and storage conditions.
A correctly exposed board after development will show:
- Clear copper traces (resist intact, blue/green tint)
- Bare copper in etched areas (resist removed, shiny copper)
---
## Troubleshooting
**`kicad-cli: command not found`** — add KiCad to PATH:
```bash
export PATH="/usr/lib/kicad/bin:$PATH"
```
Or on Flatpak:
```bash
alias kicad-cli='flatpak run --command=kicad-cli org.kicad.KiCad'
```
**Expected Gerber not found** — KiCad's layer→filename mapping:
| Layer | Filename stem |
|---|---|
| `F.Cu` | `Front` |
| `B.Cu` | `Back` |
| `F.Mask` | `F_Mask` |
| `B.Mask` | `B_Mask` |
| `F.SilkS` | `F_Silkscreen` |
**Image looks wrong in preview** — check invert/mirror flags. Open `.preview.png`: for positive-working resist, traces = dark, background = white.
**UVtools PCB Exposure freezes on per-item invert checkbox** — known v6 bug at 46 MP. Use the global invert checkbox at the bottom of the dialog instead, or use this script pipeline entirely.
---
First print checklist
Open the `.pm4n` in Chitubox to visually verify before printing.
Check the `.preview.png` — traces should appear black on white background (background = UV exposed = resist removed = etched away; traces = dark = resist kept = copper stays)
Start with `--exposure 60` and bracket from there — Bungard presensitized at 405nm typically lands between 30120s depending on board vintage and storage.

62
scripts/diagnose_pm4n.py Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Run this on your machine: python3 diagnose_pm4n.py Dummy.pm4n"""
import struct, sys
path = sys.argv[1] if len(sys.argv) > 1 else 'Dummy.pm4n'
data = open(path, 'rb').read()
fsize = len(data)
print(f"File: {path} ({fsize} bytes)")
print()
# Parse ANYCUBIC header
magic = data[0:8]
version = struct.unpack_from('<I', data, 8)[0]
n_sections = struct.unpack_from('<I', data, 12)[0]
header_size = struct.unpack_from('<I', data, 16)[0]
print(f"Magic: {magic}")
print(f"Bytes 8-11: {data[8:12].hex()} (={version})")
print(f"Section count: {n_sections}")
print(f"Header size: {header_size} (0x{header_size:X})")
print()
# Section table: n_sections entries of (offset:u32, length:u32) starting at byte 20
print(f"Section table ({n_sections} entries from offset 20):")
sections = []
for i in range(n_sections):
base = 20 + i * 8
if base + 8 > fsize:
break
off = struct.unpack_from('<I', data, base)[0]
ln = struct.unpack_from('<I', data, base+4)[0]
sections.append((off, ln))
for idx, (off, ln) in enumerate(sections):
tag = data[off:off+4] if off + 4 <= fsize else b'????'
tag_str = tag.decode('ascii', errors='replace')
print(f" [{idx:2d}] offset=0x{off:06X} ({off:7d}) length={ln:7d} tag@offset={tag_str!r}")
print()
# Also peek at each section start for tag-like content
print("Content at each section offset (first 32 bytes):")
for idx, (off, ln) in enumerate(sections):
if off + 16 <= fsize:
chunk = data[off:off+32]
# Try to find sub-tags
for sub_off in range(0, min(32, len(chunk))-3):
sub_tag = chunk[sub_off:sub_off+4]
if all(32 <= b < 127 for b in sub_tag):
sub_len = struct.unpack_from('<I', chunk, sub_off+4)[0] if sub_off+8 <= len(chunk) else 0
print(f" section[{idx}]+0x{sub_off:02X} tag={sub_tag.decode()!r} next_u32={sub_len}")
break
else:
print(f" section[{idx}] hex: {chunk[:16].hex()}")
print()
# Look for exposure-like floats (1.0 to 600.0) across the whole file
print("Float values in range [1.0 .. 600.0] across whole file:")
for off in range(0, fsize - 3, 4):
v = struct.unpack_from('<f', data, off)[0]
if 1.0 <= v <= 600.0 and v == round(v, 1):
# Show context
section_hint = next((f"sec[{i}]+{off-s:d}" for i,(s,l) in enumerate(sections) if s <= off < s+l), "outside")
print(f" 0x{off:06X} {v:.1f} ({section_hint})")

View File

@@ -1,35 +1,156 @@
#!/bin/bash
#!/usr/bin/env bash
# export.sh — KiCad Gerber export + pm4n generation for Anycubic Photon Mono 4
#
# Usage:
# ./export.sh [OPTIONS] <path/to/board.kicad_pcb>
#
# Options:
# --layers LAYER,LAYER,... KiCad layer names to export (default: F.Cu)
# --invert LAYER,LAYER,... Layers to invert (comma-separated, e.g. F.Cu,B.Mask)
# --mirror LAYER,LAYER,... Layers to mirror (comma-separated, e.g. F.Cu,F.Mask)
# --exposure SECONDS Exposure time in seconds (default: 60)
# --dummy FILE Dummy .pm4n template (default: Dummy.pm4n beside this script)
# --out DIR Output directory (default: ./output)
# --dpmm N Render resolution in dots/mm (default: native 58.824)
# --pos X,Y Board position on LCD in mm (default: centred)
# -h, --help Show this help
#
# Example:
# ./export.sh --invert F.Cu,B.Mask --mirror F.Cu,F.Mask panel/Flow_Controller_Panel.kicad_pcb
#
# Layer name → Gerber filename mapping (KiCad default):
# F.Cu → <board>-F_Cu.gbr
# B.Cu → <board>-B_Cu.gbr
# F.Mask → <board>-F_Mask.gbr
# B.Mask → <board>-B_Mask.gbr
# F.SilkS → <board>-F_Silkscreen.gbr
# (etc.)
set -euo pipefail
GERBERS_DIR="gerbers"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PYTHON="${PYTHON:-python3}"
CONVERTER="$SCRIPT_DIR/gerber_to_pm4n.py"
# ---- defaults ----
LAYERS="F.Cu"
INVERT_LAYERS=""
MIRROR_LAYERS=""
EXPOSURE="60"
DUMMY="$SCRIPT_DIR/Dummy.pm4n"
OUT_DIR="./output"
DPMM=""
POS=""
# ---- helpers ----
usage() {
echo "Usage: $0 <kicad_pcb_file>"
exit 1
sed -n '/^# Usage/,/^[^#]/{ /^#/{ s/^# \{0,1\}//; p } }' "$0"
exit 0
}
PCB_FILE="$1"
contains() { # contains <list> <item> — comma-separated list membership
local list="$1" item="$2"
echo "$list" | tr ',' '\n' | grep -qx "$item"
}
mkdir -p "$GERBERS_DIR"
layer_to_filename() { # KiCad layer name → Gerber filename stem
local layer="$1"
echo "$layer" | sed 's/\./_/g'
}
# Export drill, front and back layers as gerber files.
echo "Exporting gerbers..."
kicad-cli pcb export drill -o "$GERBERS_DIR" "$PCB_FILE"
kicad-cli pcb export gerbers -o "$GERBERS_DIR" -l Front "$PCB_FILE"
kicad-cli pcb export gerbers -o "$GERBERS_DIR" -l Back "$PCB_FILE"
kicad-cli pcb export gerbers -o "$GERBERS_DIR" -l Edge.Cuts "$PCB_FILE"
# ---- parse arguments ----
PCB_FILE=""
while [[ $# -gt 0 ]]; do
case "$1" in
--layers) LAYERS="$2"; shift 2 ;;
--invert) INVERT_LAYERS="$2"; shift 2 ;;
--mirror) MIRROR_LAYERS="$2"; shift 2 ;;
--exposure) EXPOSURE="$2"; shift 2 ;;
--dummy) DUMMY="$2"; shift 2 ;;
--out) OUT_DIR="$2"; shift 2 ;;
--dpmm) DPMM="$2"; shift 2 ;;
--pos) POS="$2"; shift 2 ;;
-h|--help) usage ;;
-*) echo "Unknown option: $1"; exit 1 ;;
*) PCB_FILE="$1"; shift ;;
esac
done
# Export outlines of the penelized board i.e. use the layer 'User.Eco1'.
echo "Exporting panelized outlines from layer 'User.Eco1'..."
python3 export_panel_outlines_gerber.py \
--layers User.Eco1 \
if [[ -z "$PCB_FILE" ]]; then
echo "ERROR: no .kicad_pcb file specified"
echo "Usage: $0 [OPTIONS] <board.kicad_pcb>"
exit 1
fi
if [[ ! -f "$PCB_FILE" ]]; then
echo "ERROR: file not found: $PCB_FILE"
exit 1
fi
if [[ ! -f "$DUMMY" ]]; then
echo "ERROR: dummy .pm4n not found: $DUMMY"
echo "Place Dummy.pm4n next to export.sh, or pass --dummy <path>"
exit 1
fi
# ---- derive names ----
BOARD_NAME="$(basename "$PCB_FILE" .kicad_pcb)"
GERBERS_DIR="$OUT_DIR/gerbers"
PM4N_DIR="$OUT_DIR/pm4n"
mkdir -p "$GERBERS_DIR" "$PM4N_DIR"
# ---- Step 1: export Gerbers via kicad-cli ----
echo "=== Exporting Gerbers from KiCad ==="
echo " Board: $PCB_FILE"
echo " Layers: $LAYERS"
echo " Output: $GERBERS_DIR"
echo ""
kicad-cli pcb export gerbers \
--output "$GERBERS_DIR" \
--layers "$LAYERS" \
--no-protel-ext \
--subtract-soldermask \
"$PCB_FILE"
# Input layers/filenames and all milling/drilling parameters are taken from the config file: 'millproject'.
echo "Exporting Gcode..."
docker run --rm -i -t \
-u "$(id -u):$(id -g)" \
-v "$(pwd):/data" \
ptodorov/pcb2gcode
echo ""
# ---- Step 2: convert each layer to .pm4n ----
echo "=== Converting Gerbers to .pm4n ==="
IFS=',' read -ra LAYER_LIST <<< "$LAYERS"
for LAYER in "${LAYER_LIST[@]}"; do
LAYER_STEM="$(layer_to_filename "$LAYER")"
GBR_FILE="$GERBERS_DIR/${BOARD_NAME}-${LAYER_STEM}.gbr"
if [[ ! -f "$GBR_FILE" ]]; then
echo " WARNING: expected Gerber not found: $GBR_FILE — skipping"
continue
fi
OUT_PM4N="$PM4N_DIR/${BOARD_NAME}-${LAYER_STEM}.pm4n"
# Build flags
FLAGS=()
if contains "$INVERT_LAYERS" "$LAYER"; then FLAGS+=(--invert); fi
if contains "$MIRROR_LAYERS" "$LAYER"; then FLAGS+=(--mirror); fi
[[ -n "$DPMM" ]] && FLAGS+=(--dpmm "$DPMM")
[[ -n "$POS" ]] && FLAGS+=(--pos "$POS")
echo " Layer: $LAYER"
echo " Gerber: $GBR_FILE"
echo " pm4n: $OUT_PM4N"
echo " Flags: ${FLAGS[*]:-<none>} exposure=${EXPOSURE}s"
"$PYTHON" "$CONVERTER" \
"$DUMMY" \
"$GBR_FILE" \
--output "$OUT_PM4N" \
--exposure "$EXPOSURE" \
"${FLAGS[@]}"
echo ""
done
echo "=== Done ==="
echo "pm4n files in: $PM4N_DIR"

287
scripts/gerber_to_pm4n.py Executable file
View File

@@ -0,0 +1,287 @@
#!/usr/bin/env python3
"""
gerber_to_pm4n.py - Anycubic Photon Mono 4 PCB exposure file generator
Usage:
python3 gerber_to_pm4n.py <dummy.pm4n> <board.gbr> [options]
Options:
-o OUTPUT Output file path [default: <board>.pm4n]
--invert Invert the image (for positive-working resist like Bungard standard)
--mirror Mirror X axis (for copper-side-down placement on FEP)
--exposure SEC Layer exposure time in seconds [default: 60]
--dpmm N Render resolution in dots/mm [default: 58.824, native 17µm/px]
--pos X,Y Place board at X,Y mm from top-left (default: centred on LCD)
--help Show this message
Photon Mono 4 specs: 9024 x 5120 px | 153.408 x 87.040 mm | 17.001 µm/px
"""
import argparse
import struct
import sys
import io
from pathlib import Path
from PIL import Image, ImageOps
# ---------------------------------------------------------------------------
# Printer constants
# ---------------------------------------------------------------------------
LCD_W_PX = 9024
LCD_H_PX = 5120
LCD_W_MM = 153.408
LCD_H_MM = 87.040
NATIVE_DPMM = LCD_W_PX / LCD_W_MM # 58.824 dpmm (1 px ≈ 17.001 µm)
# ---------------------------------------------------------------------------
# Photon Workshop RLE (BW — 2 bytes per run)
#
# Byte0 [7:4] = colour nibble (0x0 = black, 0xF = white)
# Byte0 [3:0] = high 4 bits of run length (bits 11:8)
# Byte1 = low 8 bits of run length (bits 7:0)
# Run length encodes (n-1): 0x000 = 1 pixel, 0xFFF = 4096 pixels
# ---------------------------------------------------------------------------
MAX_RUN = 4096
def encode_rle(pixels: bytes) -> bytes:
"""Encode flat 0x00/0xFF bytes → Photon Workshop BW RLE."""
out = bytearray()
i = 0
n = len(pixels)
while i < n:
colour = pixels[i]
nibble = 0xF if colour >= 0x80 else 0x0
j = i + 1
while j < n and pixels[j] == colour and (j - i) < MAX_RUN:
j += 1
run = j - i
encoded = run - 1
out.append((nibble << 4) | ((encoded >> 8) & 0x0F))
out.append(encoded & 0xFF)
i = j
return bytes(out)
def decode_rle(data: bytes, expected_pixels: int) -> bytes:
"""Decode PW RLE → raw pixel bytes (used for verification)."""
out = bytearray()
i = 0
while i + 1 < len(data):
b0, b1 = data[i], data[i + 1]
nibble = (b0 >> 4) & 0x0F
colour = 0xFF if nibble == 0xF else 0x00
run = (((b0 & 0x0F) << 8) | b1) + 1
out.extend([colour] * run)
i += 2
return bytes(out[:expected_pixels])
# ---------------------------------------------------------------------------
# pm4n binary surgery
#
# Photon Workshop file = sequence of tagged sections:
# tag:4 length:4 payload:length
#
# Sections we care about:
# HEAD contains exposure time as a float somewhere in a packed struct
# LAYE layer definition table: count:u32 then N × entry(28 bytes)
# entry[0:4] = absolute file offset of RLE blob
# entry[4:8] = RLE blob length in bytes
# After the sections: raw RLE layer image blobs (referenced by LAYE offsets)
# ---------------------------------------------------------------------------
SECTION_HDR = 8 # 4-byte tag + 4-byte length
def read_sections(data: bytes) -> list:
sections = []
i = 0
while i + SECTION_HDR <= len(data):
tag = data[i:i+4]
length = struct.unpack_from('<I', data, i+4)[0]
sections.append((tag, i + SECTION_HDR, length))
i += SECTION_HDR + length
return sections
def find_section(data: bytes, tag: bytes) -> tuple:
for t, off, ln in read_sections(data):
if t == tag:
return off, ln
raise ValueError(f"Section {tag!r} not found in file")
def patch_u32(data: bytearray, offset: int, value: int):
struct.pack_into('<I', data, offset, value)
def patch_f32(data: bytearray, offset: int, value: float):
struct.pack_into('<f', data, offset, value)
# ---------------------------------------------------------------------------
# Gerber → PIL Image
# ---------------------------------------------------------------------------
def render_gerber(gbr_path: Path, dpmm: float,
invert: bool, mirror: bool,
pos_mm: tuple | None) -> Image.Image:
"""
Render a Gerber file to a binary PIL image sized to the Photon Mono 4 LCD.
copper = white on black background before any transforms.
"""
try:
from pygerber.gerberx3.api.v2 import (
GerberFile, ColorScheme, PixelFormatEnum, ImageFormatEnum
)
except ImportError:
sys.exit(
"ERROR: pygerber not found.\n"
"Activate the venv first: source .venv/bin/activate\n"
"Or install: pip install pygerber Pillow numpy"
)
buf = io.BytesIO()
(GerberFile
.from_file(str(gbr_path))
.parse()
.render_raster(
buf,
dpmm=int(round(dpmm)),
color_scheme=ColorScheme.DEFAULT_GRAYSCALE,
pixel_format=PixelFormatEnum.RGB,
image_format=ImageFormatEnum.PNG,
)
)
buf.seek(0)
layer_img = Image.open(buf).convert('L')
# Place onto full LCD canvas
cw, ch = layer_img.size
canvas = Image.new('L', (LCD_W_PX, LCD_H_PX), 0)
if pos_mm is not None:
px = int(round(pos_mm[0] * dpmm))
py = int(round(pos_mm[1] * dpmm))
else:
px = (LCD_W_PX - cw) // 2
py = (LCD_H_PX - ch) // 2
canvas.paste(layer_img, (max(0, px), max(0, py)))
if mirror:
canvas = ImageOps.mirror(canvas)
if invert:
canvas = ImageOps.invert(canvas)
# Hard-binarise: no antialiasing artefacts in the RLE stream
canvas = canvas.point(lambda v: 255 if v >= 128 else 0)
return canvas
# ---------------------------------------------------------------------------
# pm4n surgery
# ---------------------------------------------------------------------------
def patch_pm4n(dummy_path: Path, image: Image.Image,
exposure_sec: float, output_path: Path):
"""Replace layer RLE + exposure time in a dummy .pm4n, write output."""
raw = bytearray(dummy_path.read_bytes())
# Encode new layer image
pixels = image.convert('L').tobytes()
new_rle = encode_rle(pixels)
# Patch exposure time: scan HEAD for any float in 0.5600 s range
hdr_off, hdr_len = find_section(raw, b'HEAD')
for off in range(hdr_off, hdr_off + hdr_len - 3):
val = struct.unpack_from('<f', raw, off)[0]
if 0.5 <= val <= 600.0:
patch_f32(raw, off, exposure_sec)
# Locate layer image via LAYERDEF
ld_off, _ = find_section(raw, b'LAYE')
layer_count = struct.unpack_from('<I', raw, ld_off)[0]
if layer_count != 1:
print(f"WARNING: dummy has {layer_count} layers; only layer 0 will be replaced.")
entry_off = ld_off + 4
img_offset = struct.unpack_from('<I', raw, entry_off)[0]
img_len = struct.unpack_from('<I', raw, entry_off + 4)[0]
print(f" Dummy RLE: offset=0x{img_offset:08X} {img_len} bytes")
print(f" New RLE: {len(new_rle)} bytes")
# Splice new RLE in place
old_end = img_offset + img_len
raw[img_offset:old_end] = new_rle
# Update LAYERDEF length field
patch_u32(raw, entry_off + 4, len(new_rle))
# Update any enclosing section's length field
for tag, sec_off, sec_len in read_sections(bytes(raw)):
if tag not in (b'HEAD', b'LAYE', b'PREV') and sec_off <= img_offset < sec_off + sec_len:
patch_u32(raw, sec_off - 4, sec_len + len(new_rle) - img_len)
break
output_path.write_bytes(raw)
print(f" Written: {output_path} ({len(raw):,} bytes)")
# ---------------------------------------------------------------------------
# CLI
# ---------------------------------------------------------------------------
def parse_args():
p = argparse.ArgumentParser(
description='Convert Gerber → Anycubic Photon Mono 4 .pm4n PCB exposure file',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
p.add_argument('dummy', help='Dummy .pm4n template (from Photon Workshop)')
p.add_argument('gerber', help='Input Gerber file')
p.add_argument('-o', '--output', default=None, help='Output .pm4n path')
p.add_argument('--invert', action='store_true', help='Invert image (positive-working resist)')
p.add_argument('--mirror', action='store_true', help='Mirror X axis (copper-side-down placement)')
p.add_argument('--exposure', type=float, default=60.0, help='Exposure seconds (default: 60)')
p.add_argument('--dpmm', type=float, default=NATIVE_DPMM, help=f'Dots/mm (default: {NATIVE_DPMM:.3f})')
p.add_argument('--pos', default=None, help='Board position X,Y mm from top-left')
return p.parse_args()
def main():
args = parse_args()
dummy = Path(args.dummy)
gbr = Path(args.gerber)
for p, label in [(dummy, 'dummy'), (gbr, 'gerber')]:
if not p.exists():
sys.exit(f"ERROR: {label} file not found: {p}")
out = Path(args.output) if args.output else gbr.with_suffix('.pm4n')
pos_mm = None
if args.pos:
try:
x, y = map(float, args.pos.split(','))
pos_mm = (x, y)
except Exception:
sys.exit("ERROR: --pos must be X,Y e.g. --pos 10.5,8.0")
print(f"Gerber: {gbr}")
print(f"Dummy: {dummy}")
print(f"Output: {out}")
print(f"Invert: {args.invert} Mirror: {args.mirror} Exposure: {args.exposure}s dpmm: {args.dpmm:.3f}")
print()
print("Rendering Gerber...")
img = render_gerber(gbr, dpmm=args.dpmm, invert=args.invert,
mirror=args.mirror, pos_mm=pos_mm)
print(f"Canvas: {img.size[0]}×{img.size[1]} px")
preview = out.with_suffix('.preview.png')
img.resize((img.size[0] // 4, img.size[1] // 4), Image.NEAREST).save(preview)
print(f"Preview: {preview}")
print("Patching .pm4n...")
patch_pm4n(dummy, img, args.exposure, out)
print("Done.")
if __name__ == '__main__':
main()

View File

@@ -1,10 +1,10 @@
front=gerbers/Flow_Controller_Panel-Front.gtl
back=gerbers/Flow_Controller_Panel-Back.gbl
drill=gerbers/Flow_Controller_Panel.drl
front=output/gerbers/Flow_Controller_Panel-Front.gtl
back=output/gerbers/Flow_Controller_Panel-Back.gbl
drill=output/gerbers/Flow_Controller_Panel.drl
# Use the 'User-Eco1' layer instead as it contains panelized board's slot outlines only.
outline=gerbers/Flow_Controller_Panel-User-Eco1.gbr
outline=output/gerbers/Flow_Controller_Panel-User-Eco1.gbr
# Do not use the 'Edge_Cuts' layer as it contains also the panel outline.
#outline=gerbers/Flow_Controller_Panel-Edge_Cuts.gm1
#outline=output/gerbers/Flow_Controller_Panel-Edge_Cuts.gm1
# Generic
metric=true # use metric units for parameters

View File

@@ -24,32 +24,26 @@
"type": "tightframe",
"copperFill": true,
"slotwidth": "2.1mm",
"mintotalheight": "100mm",
"mintotalwidth": "160mm",
"maxtotalheight": "100mm",
"maxtotalwidth": "160mm"
"mintotalheight": "87mm",
"mintotalwidth": "153.4mm",
"maxtotalheight": "87mm",
"maxtotalwidth": "153.4mm"
},
"tooling": {
"type": "plugin",
"code": "tooling_plugin.py.CustomTooling",
"arg": ""
},
"fiducials": {
"type": "4fid",
"type": "3hole",
"layout": "3hole",
"hoffset": "6mm",
"voffset": "9.2mm",
"coppersize": "2mm",
"opening": "1mm",
"voffset": "6mm",
"size": "2mm",
"paste": true,
"code": "none",
"arg": ""
"soldermaskmargin": "0mm"
},
"text": {
"type": "simple",
"text": "Front",
"anchor": "mt",
"hoffset": "0mm",
"voffset": "15mm",
"voffset": "10mm",
"orientation": "0deg",
"width": "3.5mm",
"height": "3.5mm",
@@ -63,7 +57,7 @@
"text": "Back",
"anchor": "mt",
"hoffset": "0mm",
"voffset": "15mm",
"voffset": "10mm",
"orientation": "0deg",
"width": "3.5mm",
"height": "3.5mm",
@@ -76,7 +70,7 @@
"type": "solid",
"clearance": "0.5mm",
"edgeclearance": "0.5mm",
"layers": "B.Cu"
"layers": "F.Cu,B.Cu"
},
"post": {
"type": "auto",