← Commit history
C_0402_1005Metric_GRM1555C1H220JA01D.kicad_modadded+112
@@ -0,0 +1,112 @@+(footprint "C_0402_1005Metric_GRM1555C1H220JA01D"+	(version 20260206)+	(generator "kicad-footprint-generator")+	(layer "F.Cu")+	(descr "Capacitor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf)")+	(tags "capacitor")+	(property "Reference" "REF**"+		(at 0 -1.16 0)+		(layer "F.SilkS")+		(effects+			(font+				(size 1 1)+				(thickness 0.15)+			)+		)+	)+	(property "Value" "C_0402_1005Metric"+		(at 0 1.16 0)+		(layer "F.Fab")+		(effects+			(font+				(size 1 1)+				(thickness 0.15)+			)+		)+	)+	(property "KiLib_Generator" "SMD_2terminal_chip_molded"+		(at 0 0 0)+		(layer "F.SilkS")+		(hide yes)+		(effects+			(font+				(size 1 1)+				(thickness 0.15)+			)+		)+	)+	(attr smd)+	(duplicate_pad_numbers_are_jumpers no)+	(fp_line+		(start -0.107836 -0.36)+		(end 0.107836 -0.36)+		(stroke+			(width 0.12)+			(type solid)+		)+		(layer "F.SilkS")+	)+	(fp_line+		(start -0.107836 0.36)+		(end 0.107836 0.36)+		(stroke+			(width 0.12)+			(type solid)+		)+		(layer "F.SilkS")+	)+	(fp_rect+		(start -0.91 -0.46)+		(end 0.91 0.46)+		(stroke+			(width 0.05)+			(type solid)+		)+		(fill no)+		(layer "F.CrtYd")+	)+	(fp_rect+		(start -0.5 -0.25)+		(end 0.5 0.25)+		(stroke+			(width 0.1)+			(type solid)+		)+		(fill no)+		(layer "F.Fab")+	)+	(fp_text user "${REFERENCE}"+		(at 0 0 0)+		(layer "F.Fab")+		(effects+			(font+				(size 0.25 0.25)+				(thickness 0.04)+			)+		)+	)+	(pad "1" smd roundrect+		(at -0.48 0)+		(size 0.56 0.62)+		(layers "F.Cu" "F.Mask" "F.Paste")+		(roundrect_rratio 0.25)+	)+	(pad "2" smd roundrect+		(at 0.48 0)+		(size 0.56 0.62)+		(layers "F.Cu" "F.Mask" "F.Paste")+		(roundrect_rratio 0.25)+	)+	(embedded_fonts no)+	(model "${KIPRJMOD}/GRM1555C1H220JA01D.step"+		(offset+			(xyz 0 0 0)+		)+		(scale+			(xyz 1 1 1)+		)+		(rotate+			(xyz 0 0 0)+		)+	)+)
GRM1555C1H220JA01D.kicad_symadded+24
@@ -0,0 +1,24 @@+(kicad_symbol_lib (version 20241209) (generator "adom_passive_symbol")+  (symbol "GRM1555C1H220JA01D" (pin_numbers (hide yes)) (pin_names (offset 0.254) (hide yes)) (exclude_from_sim no) (in_bom yes) (on_board yes)+    (property "Reference" "C" (at 2.54 1.27 0) (effects (font (size 1.27 1.27)) (justify left)))+    (property "Value" "22pF" (at 2.54 -1.27 0) (effects (font (size 1.27 1.27)) (justify left)))+    (property "Footprint" "C_0402_1005Metric_GRM1555C1H220JA01D" (at 0 -7.62 0) (effects (font (size 1.27 1.27)) hide))+    (property "Datasheet" "https://search.murata.co.jp/Ceramy/image/img/A01X/G101/ENG/GRM1555C1H220JA01-01A.pdf" (at 0 -10.16 0) (effects (font (size 1.27 1.27)) hide))+    (property "Description" "MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)" (at 0 -12.7 0) (effects (font (size 1.27 1.27)) hide))+    (property "MPN" "GRM1555C1H220JA01D" (at 0 -15.24 0) (effects (font (size 1.27 1.27)) hide))+    (property "Manufacturer" "Murata" (at 0 -17.78 0) (effects (font (size 1.27 1.27)) hide))+    (property "Mouser" "81-GRM1555C1H220JA1D" (at 0 -20.32 0) (effects (font (size 1.27 1.27)) hide))+    (property "DigiKey" "490-5868-2-ND" (at 0 -22.86 0) (effects (font (size 1.27 1.27)) hide))+    (property "LCSC" "C76960" (at 0 -25.4 0) (effects (font (size 1.27 1.27)) hide))+    (property "Adom Wiki" "https://wiki.adom.inc/adom/grm1555c1h220ja01d" (at 0 -27.94 0) (effects (font (size 1.27 1.27)) hide))+    (property "ki_keywords" "capacitor 0402 GRM1555C1H220JA01D" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))+    (symbol "GRM1555C1H220JA01D_0_1"+      (polyline (pts (xy -2.032 -0.762) (xy 2.032 -0.762)) (stroke (width 0.508) (type default)) (fill (type none)))+      (polyline (pts (xy -2.032 0.762) (xy 2.032 0.762)) (stroke (width 0.508) (type default)) (fill (type none)))+    )+    (symbol "GRM1555C1H220JA01D_1_1"+      (pin passive line (at 0 2.54 270) (length 1.778) (name "~" (effects (font (size 1.27 1.27)))) (number "1" (effects (font (size 1.27 1.27)))))+      (pin passive line (at 0 -2.54 90) (length 1.778) (name "~" (effects (font (size 1.27 1.27)))) (number "2" (effects (font (size 1.27 1.27)))))+    )+  )+)
GRM1555C1H220JA01D.lbradded+110
@@ -0,0 +1,110 @@+<?xml version="1.0" encoding="utf-8"?>+<!DOCTYPE eagle SYSTEM "eagle.dtd">+<eagle version="9.6.2">+<drawing>+<settings><setting alwaysvectorfont="no"/></settings>+<grid distance="0.1" unitdist="inch" unit="inch" style="lines" multiple="1" display="no" altdistance="0.01" altunitdist="inch" altunit="inch"/>+<layers>+<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>+<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>+<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>+<layer number="18" name="Vias" color="2" fill="1" visible="yes" active="yes"/>+<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>+<layer number="20" name="Dimension" color="15" fill="1" visible="yes" active="yes"/>+<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>+<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>+<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>+<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>+<layer number="25" name="tNames" color="7" fill="1" visible="yes" active="yes"/>+<layer number="26" name="bNames" color="7" fill="1" visible="yes" active="yes"/>+<layer number="27" name="tValues" color="7" fill="1" visible="yes" active="yes"/>+<layer number="28" name="bValues" color="7" fill="1" visible="yes" active="yes"/>+<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>+<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>+<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>+<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>+<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>+<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>+<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>+<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>+<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>+<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>+<layer number="39" name="tKeepout" color="4" fill="11" visible="no" active="yes"/>+<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="yes"/>+<layer number="41" name="tRestrict" color="4" fill="10" visible="no" active="yes"/>+<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="yes"/>+<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="yes"/>+<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>+<layer number="45" name="Holes" color="7" fill="1" visible="no" active="yes"/>+<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>+<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>+<layer number="48" name="Document" color="7" fill="1" visible="yes" active="yes"/>+<layer number="49" name="Reference" color="7" fill="1" visible="yes" active="yes"/>+<layer number="91" name="Nets" color="2" fill="1" visible="yes" active="yes"/>+<layer number="92" name="Busses" color="1" fill="1" visible="yes" active="yes"/>+<layer number="93" name="Pins" color="2" fill="1" visible="no" active="yes"/>+<layer number="94" name="Symbols" color="4" fill="1" visible="yes" active="yes"/>+<layer number="95" name="Names" color="7" fill="1" visible="yes" active="yes"/>+<layer number="96" name="Values" color="7" fill="1" visible="yes" active="yes"/>+<layer number="97" name="Info" color="7" fill="1" visible="yes" active="yes"/>+<layer number="98" name="Guide" color="6" fill="1" visible="yes" active="yes"/>+</layers>+<library>+<description>MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)</description>+<packages>+<package name="C_0402_1005Metric_GRM1555C1H220JA01D">+  <description>2 pads, 1.5 x 0.6 mm. Capacitor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC-7351 nominal</description>+  <smd name="1" x="-0.4800" y="-0.0000" dx="0.5600" dy="0.6200" layer="1" roundness="50"/>+  <smd name="2" x="0.4800" y="-0.0000" dx="0.5600" dy="0.6200" layer="1" roundness="50"/>+  <wire x1="-0.5000" y1="0.2500" x2="0.5000" y2="0.2500" width="0.1000" layer="51"/>+  <wire x1="0.5000" y1="0.2500" x2="0.5000" y2="-0.2500" width="0.1000" layer="51"/>+  <wire x1="0.5000" y1="-0.2500" x2="-0.5000" y2="-0.2500" width="0.1000" layer="51"/>+  <wire x1="-0.5000" y1="-0.2500" x2="-0.5000" y2="0.2500" width="0.1000" layer="51"/>+  <wire x1="-0.1078" y1="0.3600" x2="0.1078" y2="0.3600" width="0.1200" layer="21"/>+  <wire x1="-0.1078" y1="-0.3600" x2="0.1078" y2="-0.3600" width="0.1200" layer="21"/>+  <text x="0" y="0.960" size="1.27" layer="25" align="bottom-center">&gt;NAME</text>+  <text x="0" y="-0.960" size="1.27" layer="27" align="top-center">&gt;VALUE</text>+</package>+</packages>+<symbols>+<symbol name="GRM1555C1H220JA01D">+  <description>MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)</description>+  <wire x1="-2.0320" y1="-0.7620" x2="2.0320" y2="-0.7620" width="0.5080" layer="94"/>+  <wire x1="-2.0320" y1="0.7620" x2="2.0320" y2="0.7620" width="0.5080" layer="94"/>+  <text x="2.5400" y="1.2700" size="1.27" layer="95" align="center">&gt;NAME</text>+  <text x="2.5400" y="-1.2700" size="1.27" layer="96" align="center">&gt;VALUE</text>+  <wire x1="0.0000" y1="2.5400" x2="0.0000" y2="0.7620" width="0.254" layer="94"/>+  <pin name="1" x="0" y="2.54" length="point" direction="pas" rot="R270" visible="pad"/>+  <wire x1="0.0000" y1="-2.5400" x2="0.0000" y2="-0.7620" width="0.254" layer="94"/>+  <pin name="2" x="0" y="-2.54" length="point" direction="pas" rot="R90" visible="pad"/>+</symbol>+</symbols>+<devicesets>+<deviceset name="GRM1555C1H220JA01D" prefix="C">+  <description>MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)</description>+  <gates>+    <gate name="G$1" symbol="GRM1555C1H220JA01D" x="0" y="0"/>+  </gates>+  <devices>+    <device name="" package="C_0402_1005Metric_GRM1555C1H220JA01D">+      <connects>+        <connect gate="G$1" pin="1" pad="1"/>+        <connect gate="G$1" pin="2" pad="2"/>+      </connects>+      <technologies>+        <technology name="">+          <attribute name="MPN" value="GRM1555C1H220JA01D" constant="no"/>+          <attribute name="MANUFACTURER" value="Murata" constant="no"/>+          <attribute name="ADOM_WIKI" value="https://wiki.adom.inc/adom/grm1555c1h220ja01d" constant="no"/>+          <attribute name="MOUSER_PN" value="81-GRM1555C1H220JA1D" constant="no"/>+          <attribute name="DIGIKEY_PN" value="490-5868-2-ND" constant="no"/>+          <attribute name="LCSC_PN" value="C76960" constant="no"/>+        </technology>+      </technologies>+    </device>+  </devices>+</deviceset>+</devicesets>+</library>+</drawing>+</eagle>\ No newline at end of file
GRM1555C1H220JA01D.stepadded+1123
@@ -0,0 +1,1123 @@+ISO-10303-21;+HEADER;+/* C_0402_1005Metric.step 3D STEP model for use in ECAD systems+ * Copyright (C) 2017, kicad StepUp+ * + * This work is licensed under the [Creative Commons CC-BY-SA 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/legalcode), + * with the following exception:+ * To the extent that the creation of electronic designs that use 'Licensed Material' can be considered to be 'Adapted Material', + * then the copyright holder waives article 3 of the license with respect to these designs and any generated files which use data provided + * as part of the 'Licensed Material'.+ * You are free to use the library data in your own projects without the obligation to share your project files under this or any other license agreement.+ * However, if you wish to redistribute these libraries, or parts thereof (including in modified form) as a collection then the exception above does not apply. + * Please refer to https://github.com/KiCad/kicad-packages3D/blob/master/LICENSE.md for further clarification of the exception.+ * Disclaimer of Warranties and Limitation of Liability.+ * These libraries are provided in the hope that they will be useful, but are provided without warranty of any kind, express or implied.+ * *USE 3D CAD DATA AT YOUR OWN RISK*+ * *DO NOT RELY UPON ANY INFORMATION FOUND HERE WITHOUT INDEPENDENT VERIFICATION.*+ * + */++FILE_DESCRIPTION(+/* description */ ('model of C_0402_1005Metric'),+/* implementation_level */ '2;1');++FILE_NAME(+/* name */ 'C_0402_1005Metric.step',+/* time_stamp */ '2017-12-10T01:08:42',+/* author */ ('kicad StepUp','ksu'),+/* organization */ ('FreeCAD'),+/* preprocessor_version */ 'OCC',+/* originating_system */ 'kicad StepUp',+/* authorisation */ '');++FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));+ENDSEC;++DATA;+#1 = APPLICATION_PROTOCOL_DEFINITION('international standard',+'automotive_design',2000,#2);+#2 = APPLICATION_CONTEXT(+'core data for automotive mechanical design processes');+#3 = SHAPE_DEFINITION_REPRESENTATION(#4,#10);+#4 = PRODUCT_DEFINITION_SHAPE('','',#5);+#5 = PRODUCT_DEFINITION('design','',#6,#9);+#6 = PRODUCT_DEFINITION_FORMATION('','',#7);+#7 = PRODUCT('C_0402_1005Metric','C_0402_1005Metric','',(#8));+#8 = PRODUCT_CONTEXT('',#2,'mechanical');+#9 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design');+#10 = ADVANCED_BREP_SHAPE_REPRESENTATION('',(#11,#15),#869);+#11 = AXIS2_PLACEMENT_3D('',#12,#13,#14);+#12 = CARTESIAN_POINT('',(0.,0.,0.));+#13 = DIRECTION('',(0.,0.,1.));+#14 = DIRECTION('',(1.,0.,-0.));+#15 = MANIFOLD_SOLID_BREP('',#16);+#16 = CLOSED_SHELL('',(#17,#93,#124,#149,#174,#198,#222,#247,#272,#289,+#375,#407,#431,#456,#480,#505,#529,#554,#571,#657,#688,#713,#738,+#762,#786,#811,#836,#853));+#17 = ADVANCED_FACE('',(#18),#88,.F.);+#18 = FACE_BOUND('',#19,.F.);+#19 = EDGE_LOOP('',(#20,#30,#39,#47,#56,#64,#73,#81));+#20 = ORIENTED_EDGE('',*,*,#21,.F.);+#21 = EDGE_CURVE('',#22,#24,#26,.T.);+#22 = VERTEX_POINT('',#23);+#23 = CARTESIAN_POINT('',(-0.5,-0.25,2.E-02));+#24 = VERTEX_POINT('',#25);+#25 = CARTESIAN_POINT('',(-0.5,-0.25,0.48));+#26 = LINE('',#27,#28);+#27 = CARTESIAN_POINT('',(-0.5,-0.25,0.));+#28 = VECTOR('',#29,1.);+#29 = DIRECTION('',(0.,0.,1.));+#30 = ORIENTED_EDGE('',*,*,#31,.T.);+#31 = EDGE_CURVE('',#22,#32,#34,.T.);+#32 = VERTEX_POINT('',#33);+#33 = CARTESIAN_POINT('',(-0.5,-0.23,0.));+#34 = CIRCLE('',#35,2.E-02);+#35 = AXIS2_PLACEMENT_3D('',#36,#37,#38);+#36 = CARTESIAN_POINT('',(-0.5,-0.23,2.E-02));+#37 = DIRECTION('',(1.,0.,-0.));+#38 = DIRECTION('',(0.,0.,1.));+#39 = ORIENTED_EDGE('',*,*,#40,.T.);+#40 = EDGE_CURVE('',#32,#41,#43,.T.);+#41 = VERTEX_POINT('',#42);+#42 = CARTESIAN_POINT('',(-0.5,0.23,0.));+#43 = LINE('',#44,#45);+#44 = CARTESIAN_POINT('',(-0.5,-0.25,0.));+#45 = VECTOR('',#46,1.);+#46 = DIRECTION('',(0.,1.,0.));+#47 = ORIENTED_EDGE('',*,*,#48,.F.);+#48 = EDGE_CURVE('',#49,#41,#51,.T.);+#49 = VERTEX_POINT('',#50);+#50 = CARTESIAN_POINT('',(-0.5,0.25,2.E-02));+#51 = CIRCLE('',#52,2.E-02);+#52 = AXIS2_PLACEMENT_3D('',#53,#54,#55);+#53 = CARTESIAN_POINT('',(-0.5,0.23,2.E-02));+#54 = DIRECTION('',(-1.,0.,0.));+#55 = DIRECTION('',(0.,0.,1.));+#56 = ORIENTED_EDGE('',*,*,#57,.T.);+#57 = EDGE_CURVE('',#49,#58,#60,.T.);+#58 = VERTEX_POINT('',#59);+#59 = CARTESIAN_POINT('',(-0.5,0.25,0.48));+#60 = LINE('',#61,#62);+#61 = CARTESIAN_POINT('',(-0.5,0.25,0.));+#62 = VECTOR('',#63,1.);+#63 = DIRECTION('',(0.,0.,1.));+#64 = ORIENTED_EDGE('',*,*,#65,.T.);+#65 = EDGE_CURVE('',#58,#66,#68,.T.);+#66 = VERTEX_POINT('',#67);+#67 = CARTESIAN_POINT('',(-0.5,0.23,0.5));+#68 = CIRCLE('',#69,2.E-02);+#69 = AXIS2_PLACEMENT_3D('',#70,#71,#72);+#70 = CARTESIAN_POINT('',(-0.5,0.23,0.48));+#71 = DIRECTION('',(1.,0.,-0.));+#72 = DIRECTION('',(0.,0.,1.));+#73 = ORIENTED_EDGE('',*,*,#74,.F.);+#74 = EDGE_CURVE('',#75,#66,#77,.T.);+#75 = VERTEX_POINT('',#76);+#76 = CARTESIAN_POINT('',(-0.5,-0.23,0.5));+#77 = LINE('',#78,#79);+#78 = CARTESIAN_POINT('',(-0.5,-0.25,0.5));+#79 = VECTOR('',#80,1.);+#80 = DIRECTION('',(0.,1.,0.));+#81 = ORIENTED_EDGE('',*,*,#82,.F.);+#82 = EDGE_CURVE('',#24,#75,#83,.T.);+#83 = CIRCLE('',#84,2.E-02);+#84 = AXIS2_PLACEMENT_3D('',#85,#86,#87);+#85 = CARTESIAN_POINT('',(-0.5,-0.23,0.48));+#86 = DIRECTION('',(-1.,0.,0.));+#87 = DIRECTION('',(0.,0.,1.));+#88 = PLANE('',#89);+#89 = AXIS2_PLACEMENT_3D('',#90,#91,#92);+#90 = CARTESIAN_POINT('',(-0.5,-0.25,0.));+#91 = DIRECTION('',(1.,0.,0.));+#92 = DIRECTION('',(0.,0.,1.));+#93 = ADVANCED_FACE('',(#94),#119,.F.);+#94 = FACE_BOUND('',#95,.F.);+#95 = EDGE_LOOP('',(#96,#106,#112,#113));+#96 = ORIENTED_EDGE('',*,*,#97,.F.);+#97 = EDGE_CURVE('',#98,#100,#102,.T.);+#98 = VERTEX_POINT('',#99);+#99 = CARTESIAN_POINT('',(-0.3,-0.25,2.E-02));+#100 = VERTEX_POINT('',#101);+#101 = CARTESIAN_POINT('',(-0.3,-0.25,0.48));+#102 = LINE('',#103,#104);+#103 = CARTESIAN_POINT('',(-0.3,-0.25,0.));+#104 = VECTOR('',#105,1.);+#105 = DIRECTION('',(0.,0.,1.));+#106 = ORIENTED_EDGE('',*,*,#107,.F.);+#107 = EDGE_CURVE('',#22,#98,#108,.T.);+#108 = LINE('',#109,#110);+#109 = CARTESIAN_POINT('',(-0.5,-0.25,2.E-02));+#110 = VECTOR('',#111,1.);+#111 = DIRECTION('',(1.,0.,0.));+#112 = ORIENTED_EDGE('',*,*,#21,.T.);+#113 = ORIENTED_EDGE('',*,*,#114,.T.);+#114 = EDGE_CURVE('',#24,#100,#115,.T.);+#115 = LINE('',#116,#117);+#116 = CARTESIAN_POINT('',(-0.5,-0.25,0.48));+#117 = VECTOR('',#118,1.);+#118 = DIRECTION('',(1.,0.,0.));+#119 = PLANE('',#120);+#120 = AXIS2_PLACEMENT_3D('',#121,#122,#123);+#121 = CARTESIAN_POINT('',(-0.5,-0.25,0.));+#122 = DIRECTION('',(0.,1.,0.));+#123 = DIRECTION('',(0.,0.,1.));+#124 = ADVANCED_FACE('',(#125),#144,.T.);+#125 = FACE_BOUND('',#126,.T.);+#126 = EDGE_LOOP('',(#127,#128,#136,#143));+#127 = ORIENTED_EDGE('',*,*,#31,.T.);+#128 = ORIENTED_EDGE('',*,*,#129,.T.);+#129 = EDGE_CURVE('',#32,#130,#132,.T.);+#130 = VERTEX_POINT('',#131);+#131 = CARTESIAN_POINT('',(-0.3,-0.23,0.));+#132 = LINE('',#133,#134);+#133 = CARTESIAN_POINT('',(-0.5,-0.23,0.));+#134 = VECTOR('',#135,1.);+#135 = DIRECTION('',(1.,0.,0.));+#136 = ORIENTED_EDGE('',*,*,#137,.F.);+#137 = EDGE_CURVE('',#98,#130,#138,.T.);+#138 = CIRCLE('',#139,2.E-02);+#139 = AXIS2_PLACEMENT_3D('',#140,#141,#142);+#140 = CARTESIAN_POINT('',(-0.3,-0.23,2.E-02));+#141 = DIRECTION('',(1.,0.,-0.));+#142 = DIRECTION('',(0.,0.,1.));+#143 = ORIENTED_EDGE('',*,*,#107,.F.);+#144 = CYLINDRICAL_SURFACE('',#145,2.E-02);+#145 = AXIS2_PLACEMENT_3D('',#146,#147,#148);+#146 = CARTESIAN_POINT('',(-0.5,-0.23,2.E-02));+#147 = DIRECTION('',(1.,0.,0.));+#148 = DIRECTION('',(0.,-1.,0.));+#149 = ADVANCED_FACE('',(#150),#169,.T.);+#150 = FACE_BOUND('',#151,.F.);+#151 = EDGE_LOOP('',(#152,#153,#161,#168));+#152 = ORIENTED_EDGE('',*,*,#82,.T.);+#153 = ORIENTED_EDGE('',*,*,#154,.T.);+#154 = EDGE_CURVE('',#75,#155,#157,.T.);+#155 = VERTEX_POINT('',#156);+#156 = CARTESIAN_POINT('',(-0.3,-0.23,0.5));+#157 = LINE('',#158,#159);+#158 = CARTESIAN_POINT('',(-0.5,-0.23,0.5));+#159 = VECTOR('',#160,1.);+#160 = DIRECTION('',(1.,0.,0.));+#161 = ORIENTED_EDGE('',*,*,#162,.F.);+#162 = EDGE_CURVE('',#100,#155,#163,.T.);+#163 = CIRCLE('',#164,2.E-02);+#164 = AXIS2_PLACEMENT_3D('',#165,#166,#167);+#165 = CARTESIAN_POINT('',(-0.3,-0.23,0.48));+#166 = DIRECTION('',(-1.,0.,0.));+#167 = DIRECTION('',(0.,0.,1.));+#168 = ORIENTED_EDGE('',*,*,#114,.F.);+#169 = CYLINDRICAL_SURFACE('',#170,2.E-02);+#170 = AXIS2_PLACEMENT_3D('',#171,#172,#173);+#171 = CARTESIAN_POINT('',(-0.5,-0.23,0.48));+#172 = DIRECTION('',(1.,0.,0.));+#173 = DIRECTION('',(0.,-1.,0.));+#174 = ADVANCED_FACE('',(#175),#193,.F.);+#175 = FACE_BOUND('',#176,.F.);+#176 = EDGE_LOOP('',(#177,#178,#179,#187));+#177 = ORIENTED_EDGE('',*,*,#40,.F.);+#178 = ORIENTED_EDGE('',*,*,#129,.T.);+#179 = ORIENTED_EDGE('',*,*,#180,.T.);+#180 = EDGE_CURVE('',#130,#181,#183,.T.);+#181 = VERTEX_POINT('',#182);+#182 = CARTESIAN_POINT('',(-0.3,0.23,0.));+#183 = LINE('',#184,#185);+#184 = CARTESIAN_POINT('',(-0.3,-0.25,0.));+#185 = VECTOR('',#186,1.);+#186 = DIRECTION('',(0.,1.,0.));+#187 = ORIENTED_EDGE('',*,*,#188,.F.);+#188 = EDGE_CURVE('',#41,#181,#189,.T.);+#189 = LINE('',#190,#191);+#190 = CARTESIAN_POINT('',(-0.5,0.23,0.));+#191 = VECTOR('',#192,1.);+#192 = DIRECTION('',(1.,0.,0.));+#193 = PLANE('',#194);+#194 = AXIS2_PLACEMENT_3D('',#195,#196,#197);+#195 = CARTESIAN_POINT('',(-0.5,-0.25,0.));+#196 = DIRECTION('',(0.,0.,1.));+#197 = DIRECTION('',(1.,0.,0.));+#198 = ADVANCED_FACE('',(#199),#217,.T.);+#199 = FACE_BOUND('',#200,.T.);+#200 = EDGE_LOOP('',(#201,#202,#203,#211));+#201 = ORIENTED_EDGE('',*,*,#74,.F.);+#202 = ORIENTED_EDGE('',*,*,#154,.T.);+#203 = ORIENTED_EDGE('',*,*,#204,.T.);+#204 = EDGE_CURVE('',#155,#205,#207,.T.);+#205 = VERTEX_POINT('',#206);+#206 = CARTESIAN_POINT('',(-0.3,0.23,0.5));+#207 = LINE('',#208,#209);+#208 = CARTESIAN_POINT('',(-0.3,-0.25,0.5));+#209 = VECTOR('',#210,1.);+#210 = DIRECTION('',(0.,1.,0.));+#211 = ORIENTED_EDGE('',*,*,#212,.F.);+#212 = EDGE_CURVE('',#66,#205,#213,.T.);+#213 = LINE('',#214,#215);+#214 = CARTESIAN_POINT('',(-0.5,0.23,0.5));+#215 = VECTOR('',#216,1.);+#216 = DIRECTION('',(1.,0.,0.));+#217 = PLANE('',#218);+#218 = AXIS2_PLACEMENT_3D('',#219,#220,#221);+#219 = CARTESIAN_POINT('',(-0.5,-0.25,0.5));+#220 = DIRECTION('',(0.,0.,1.));+#221 = DIRECTION('',(1.,0.,0.));+#222 = ADVANCED_FACE('',(#223),#242,.T.);+#223 = FACE_BOUND('',#224,.F.);+#224 = EDGE_LOOP('',(#225,#226,#227,#236));+#225 = ORIENTED_EDGE('',*,*,#48,.T.);+#226 = ORIENTED_EDGE('',*,*,#188,.T.);+#227 = ORIENTED_EDGE('',*,*,#228,.F.);+#228 = EDGE_CURVE('',#229,#181,#231,.T.);+#229 = VERTEX_POINT('',#230);+#230 = CARTESIAN_POINT('',(-0.3,0.25,2.E-02));+#231 = CIRCLE('',#232,2.E-02);+#232 = AXIS2_PLACEMENT_3D('',#233,#234,#235);+#233 = CARTESIAN_POINT('',(-0.3,0.23,2.E-02));+#234 = DIRECTION('',(-1.,0.,0.));+#235 = DIRECTION('',(0.,0.,1.));+#236 = ORIENTED_EDGE('',*,*,#237,.F.);+#237 = EDGE_CURVE('',#49,#229,#238,.T.);+#238 = LINE('',#239,#240);+#239 = CARTESIAN_POINT('',(-0.5,0.25,2.E-02));+#240 = VECTOR('',#241,1.);+#241 = DIRECTION('',(1.,0.,0.));+#242 = CYLINDRICAL_SURFACE('',#243,2.E-02);+#243 = AXIS2_PLACEMENT_3D('',#244,#245,#246);+#244 = CARTESIAN_POINT('',(-0.5,0.23,2.E-02));+#245 = DIRECTION('',(1.,0.,0.));+#246 = DIRECTION('',(0.,1.,0.));+#247 = ADVANCED_FACE('',(#248),#267,.T.);+#248 = FACE_BOUND('',#249,.T.);+#249 = EDGE_LOOP('',(#250,#251,#252,#261));+#250 = ORIENTED_EDGE('',*,*,#65,.T.);+#251 = ORIENTED_EDGE('',*,*,#212,.T.);+#252 = ORIENTED_EDGE('',*,*,#253,.F.);+#253 = EDGE_CURVE('',#254,#205,#256,.T.);+#254 = VERTEX_POINT('',#255);+#255 = CARTESIAN_POINT('',(-0.3,0.25,0.48));+#256 = CIRCLE('',#257,2.E-02);+#257 = AXIS2_PLACEMENT_3D('',#258,#259,#260);+#258 = CARTESIAN_POINT('',(-0.3,0.23,0.48));+#259 = DIRECTION('',(1.,0.,-0.));+#260 = DIRECTION('',(0.,0.,1.));+#261 = ORIENTED_EDGE('',*,*,#262,.F.);+#262 = EDGE_CURVE('',#58,#254,#263,.T.);+#263 = LINE('',#264,#265);+#264 = CARTESIAN_POINT('',(-0.5,0.25,0.48));+#265 = VECTOR('',#266,1.);+#266 = DIRECTION('',(1.,0.,0.));+#267 = CYLINDRICAL_SURFACE('',#268,2.E-02);+#268 = AXIS2_PLACEMENT_3D('',#269,#270,#271);+#269 = CARTESIAN_POINT('',(-0.5,0.23,0.48));+#270 = DIRECTION('',(1.,0.,0.));+#271 = DIRECTION('',(0.,1.,0.));+#272 = ADVANCED_FACE('',(#273),#284,.T.);+#273 = FACE_BOUND('',#274,.T.);+#274 = EDGE_LOOP('',(#275,#281,#282,#283));+#275 = ORIENTED_EDGE('',*,*,#276,.F.);+#276 = EDGE_CURVE('',#229,#254,#277,.T.);+#277 = LINE('',#278,#279);+#278 = CARTESIAN_POINT('',(-0.3,0.25,0.));+#279 = VECTOR('',#280,1.);+#280 = DIRECTION('',(0.,0.,1.));+#281 = ORIENTED_EDGE('',*,*,#237,.F.);+#282 = ORIENTED_EDGE('',*,*,#57,.T.);+#283 = ORIENTED_EDGE('',*,*,#262,.T.);+#284 = PLANE('',#285);+#285 = AXIS2_PLACEMENT_3D('',#286,#287,#288);+#286 = CARTESIAN_POINT('',(-0.5,0.25,0.));+#287 = DIRECTION('',(0.,1.,0.));+#288 = DIRECTION('',(0.,0.,1.));+#289 = ADVANCED_FACE('',(#290,#300),#370,.T.);+#290 = FACE_BOUND('',#291,.T.);+#291 = EDGE_LOOP('',(#292,#293,#294,#295,#296,#297,#298,#299));+#292 = ORIENTED_EDGE('',*,*,#97,.F.);+#293 = ORIENTED_EDGE('',*,*,#137,.T.);+#294 = ORIENTED_EDGE('',*,*,#180,.T.);+#295 = ORIENTED_EDGE('',*,*,#228,.F.);+#296 = ORIENTED_EDGE('',*,*,#276,.T.);+#297 = ORIENTED_EDGE('',*,*,#253,.T.);+#298 = ORIENTED_EDGE('',*,*,#204,.F.);+#299 = ORIENTED_EDGE('',*,*,#162,.F.);+#300 = FACE_BOUND('',#301,.T.);+#301 = EDGE_LOOP('',(#302,#313,#321,#330,#338,#347,#355,#364));+#302 = ORIENTED_EDGE('',*,*,#303,.F.);+#303 = EDGE_CURVE('',#304,#306,#308,.T.);+#304 = VERTEX_POINT('',#305);+#305 = CARTESIAN_POINT('',(-0.3,-0.23,4.E-02));+#306 = VERTEX_POINT('',#307);+#307 = CARTESIAN_POINT('',(-0.3,-0.21,2.E-02));+#308 = CIRCLE('',#309,2.E-02);+#309 = AXIS2_PLACEMENT_3D('',#310,#311,#312);+#310 = CARTESIAN_POINT('',(-0.3,-0.21,4.E-02));+#311 = DIRECTION('',(1.,0.,-0.));+#312 = DIRECTION('',(0.,0.,1.));+#313 = ORIENTED_EDGE('',*,*,#314,.T.);+#314 = EDGE_CURVE('',#304,#315,#317,.T.);+#315 = VERTEX_POINT('',#316);+#316 = CARTESIAN_POINT('',(-0.3,-0.23,0.46));+#317 = LINE('',#318,#319);+#318 = CARTESIAN_POINT('',(-0.3,-0.23,2.E-02));+#319 = VECTOR('',#320,1.);+#320 = DIRECTION('',(0.,0.,1.));+#321 = ORIENTED_EDGE('',*,*,#322,.T.);+#322 = EDGE_CURVE('',#315,#323,#325,.T.);+#323 = VERTEX_POINT('',#324);+#324 = CARTESIAN_POINT('',(-0.3,-0.21,0.48));+#325 = CIRCLE('',#326,2.E-02);+#326 = AXIS2_PLACEMENT_3D('',#327,#328,#329);+#327 = CARTESIAN_POINT('',(-0.3,-0.21,0.46));+#328 = DIRECTION('',(-1.,0.,0.));+#329 = DIRECTION('',(0.,0.,1.));+#330 = ORIENTED_EDGE('',*,*,#331,.T.);+#331 = EDGE_CURVE('',#323,#332,#334,.T.);+#332 = VERTEX_POINT('',#333);+#333 = CARTESIAN_POINT('',(-0.3,0.21,0.48));+#334 = LINE('',#335,#336);+#335 = CARTESIAN_POINT('',(-0.3,-0.23,0.48));+#336 = VECTOR('',#337,1.);+#337 = DIRECTION('',(0.,1.,0.));+#338 = ORIENTED_EDGE('',*,*,#339,.F.);+#339 = EDGE_CURVE('',#340,#332,#342,.T.);+#340 = VERTEX_POINT('',#341);+#341 = CARTESIAN_POINT('',(-0.3,0.23,0.46));+#342 = CIRCLE('',#343,2.E-02);+#343 = AXIS2_PLACEMENT_3D('',#344,#345,#346);+#344 = CARTESIAN_POINT('',(-0.3,0.21,0.46));+#345 = DIRECTION('',(1.,0.,-0.));+#346 = DIRECTION('',(0.,0.,1.));+#347 = ORIENTED_EDGE('',*,*,#348,.F.);+#348 = EDGE_CURVE('',#349,#340,#351,.T.);+#349 = VERTEX_POINT('',#350);+#350 = CARTESIAN_POINT('',(-0.3,0.23,4.E-02));+#351 = LINE('',#352,#353);+#352 = CARTESIAN_POINT('',(-0.3,0.23,2.E-02));+#353 = VECTOR('',#354,1.);+#354 = DIRECTION('',(0.,0.,1.));+#355 = ORIENTED_EDGE('',*,*,#356,.T.);+#356 = EDGE_CURVE('',#349,#357,#359,.T.);+#357 = VERTEX_POINT('',#358);+#358 = CARTESIAN_POINT('',(-0.3,0.21,2.E-02));+#359 = CIRCLE('',#360,2.E-02);+#360 = AXIS2_PLACEMENT_3D('',#361,#362,#363);+#361 = CARTESIAN_POINT('',(-0.3,0.21,4.E-02));+#362 = DIRECTION('',(-1.,0.,0.));+#363 = DIRECTION('',(0.,0.,1.));+#364 = ORIENTED_EDGE('',*,*,#365,.F.);+#365 = EDGE_CURVE('',#306,#357,#366,.T.);+#366 = LINE('',#367,#368);+#367 = CARTESIAN_POINT('',(-0.3,-0.23,2.E-02));+#368 = VECTOR('',#369,1.);+#369 = DIRECTION('',(0.,1.,0.));+#370 = PLANE('',#371);+#371 = AXIS2_PLACEMENT_3D('',#372,#373,#374);+#372 = CARTESIAN_POINT('',(-0.3,-0.25,0.));+#373 = DIRECTION('',(1.,0.,0.));+#374 = DIRECTION('',(0.,0.,1.));+#375 = ADVANCED_FACE('',(#376),#402,.T.);+#376 = FACE_BOUND('',#377,.T.);+#377 = EDGE_LOOP('',(#378,#379,#387,#396));+#378 = ORIENTED_EDGE('',*,*,#303,.T.);+#379 = ORIENTED_EDGE('',*,*,#380,.T.);+#380 = EDGE_CURVE('',#306,#381,#383,.T.);+#381 = VERTEX_POINT('',#382);+#382 = CARTESIAN_POINT('',(0.3,-0.21,2.E-02));+#383 = LINE('',#384,#385);+#384 = CARTESIAN_POINT('',(-0.3,-0.21,2.E-02));+#385 = VECTOR('',#386,1.);+#386 = DIRECTION('',(1.,0.,0.));+#387 = ORIENTED_EDGE('',*,*,#388,.F.);+#388 = EDGE_CURVE('',#389,#381,#391,.T.);+#389 = VERTEX_POINT('',#390);+#390 = CARTESIAN_POINT('',(0.3,-0.23,4.E-02));+#391 = CIRCLE('',#392,2.E-02);+#392 = AXIS2_PLACEMENT_3D('',#393,#394,#395);+#393 = CARTESIAN_POINT('',(0.3,-0.21,4.E-02));+#394 = DIRECTION('',(1.,0.,-0.));+#395 = DIRECTION('',(0.,0.,1.));+#396 = ORIENTED_EDGE('',*,*,#397,.F.);+#397 = EDGE_CURVE('',#304,#389,#398,.T.);+#398 = LINE('',#399,#400);+#399 = CARTESIAN_POINT('',(-0.3,-0.23,4.E-02));+#400 = VECTOR('',#401,1.);+#401 = DIRECTION('',(1.,0.,0.));+#402 = CYLINDRICAL_SURFACE('',#403,2.E-02);+#403 = AXIS2_PLACEMENT_3D('',#404,#405,#406);+#404 = CARTESIAN_POINT('',(-0.3,-0.21,4.E-02));+#405 = DIRECTION('',(1.,0.,0.));+#406 = DIRECTION('',(0.,-1.,0.));+#407 = ADVANCED_FACE('',(#408),#426,.F.);+#408 = FACE_BOUND('',#409,.F.);+#409 = EDGE_LOOP('',(#410,#411,#412,#420));+#410 = ORIENTED_EDGE('',*,*,#365,.F.);+#411 = ORIENTED_EDGE('',*,*,#380,.T.);+#412 = ORIENTED_EDGE('',*,*,#413,.T.);+#413 = EDGE_CURVE('',#381,#414,#416,.T.);+#414 = VERTEX_POINT('',#415);+#415 = CARTESIAN_POINT('',(0.3,0.21,2.E-02));+#416 = LINE('',#417,#418);+#417 = CARTESIAN_POINT('',(0.3,-0.23,2.E-02));+#418 = VECTOR('',#419,1.);+#419 = DIRECTION('',(0.,1.,0.));+#420 = ORIENTED_EDGE('',*,*,#421,.F.);+#421 = EDGE_CURVE('',#357,#414,#422,.T.);+#422 = LINE('',#423,#424);+#423 = CARTESIAN_POINT('',(-0.3,0.21,2.E-02));+#424 = VECTOR('',#425,1.);+#425 = DIRECTION('',(1.,0.,0.));+#426 = PLANE('',#427);+#427 = AXIS2_PLACEMENT_3D('',#428,#429,#430);+#428 = CARTESIAN_POINT('',(-0.3,-0.23,2.E-02));+#429 = DIRECTION('',(0.,0.,1.));+#430 = DIRECTION('',(1.,0.,0.));+#431 = ADVANCED_FACE('',(#432),#451,.T.);+#432 = FACE_BOUND('',#433,.F.);+#433 = EDGE_LOOP('',(#434,#435,#436,#445));+#434 = ORIENTED_EDGE('',*,*,#356,.T.);+#435 = ORIENTED_EDGE('',*,*,#421,.T.);+#436 = ORIENTED_EDGE('',*,*,#437,.F.);+#437 = EDGE_CURVE('',#438,#414,#440,.T.);+#438 = VERTEX_POINT('',#439);+#439 = CARTESIAN_POINT('',(0.3,0.23,4.E-02));+#440 = CIRCLE('',#441,2.E-02);+#441 = AXIS2_PLACEMENT_3D('',#442,#443,#444);+#442 = CARTESIAN_POINT('',(0.3,0.21,4.E-02));+#443 = DIRECTION('',(-1.,0.,0.));+#444 = DIRECTION('',(0.,0.,1.));+#445 = ORIENTED_EDGE('',*,*,#446,.F.);+#446 = EDGE_CURVE('',#349,#438,#447,.T.);+#447 = LINE('',#448,#449);+#448 = CARTESIAN_POINT('',(-0.3,0.23,4.E-02));+#449 = VECTOR('',#450,1.);+#450 = DIRECTION('',(1.,0.,0.));+#451 = CYLINDRICAL_SURFACE('',#452,2.E-02);+#452 = AXIS2_PLACEMENT_3D('',#453,#454,#455);+#453 = CARTESIAN_POINT('',(-0.3,0.21,4.E-02));+#454 = DIRECTION('',(1.,0.,0.));+#455 = DIRECTION('',(0.,1.,0.));+#456 = ADVANCED_FACE('',(#457),#475,.T.);+#457 = FACE_BOUND('',#458,.T.);+#458 = EDGE_LOOP('',(#459,#467,#468,#469));+#459 = ORIENTED_EDGE('',*,*,#460,.F.);+#460 = EDGE_CURVE('',#438,#461,#463,.T.);+#461 = VERTEX_POINT('',#462);+#462 = CARTESIAN_POINT('',(0.3,0.23,0.46));+#463 = LINE('',#464,#465);+#464 = CARTESIAN_POINT('',(0.3,0.23,2.E-02));+#465 = VECTOR('',#466,1.);+#466 = DIRECTION('',(0.,0.,1.));+#467 = ORIENTED_EDGE('',*,*,#446,.F.);+#468 = ORIENTED_EDGE('',*,*,#348,.T.);+#469 = ORIENTED_EDGE('',*,*,#470,.T.);+#470 = EDGE_CURVE('',#340,#461,#471,.T.);+#471 = LINE('',#472,#473);+#472 = CARTESIAN_POINT('',(-0.3,0.23,0.46));+#473 = VECTOR('',#474,1.);+#474 = DIRECTION('',(1.,0.,0.));+#475 = PLANE('',#476);+#476 = AXIS2_PLACEMENT_3D('',#477,#478,#479);+#477 = CARTESIAN_POINT('',(-0.3,0.23,2.E-02));+#478 = DIRECTION('',(0.,1.,0.));+#479 = DIRECTION('',(0.,0.,1.));+#480 = ADVANCED_FACE('',(#481),#500,.T.);+#481 = FACE_BOUND('',#482,.T.);+#482 = EDGE_LOOP('',(#483,#484,#492,#499));+#483 = ORIENTED_EDGE('',*,*,#339,.T.);+#484 = ORIENTED_EDGE('',*,*,#485,.T.);+#485 = EDGE_CURVE('',#332,#486,#488,.T.);+#486 = VERTEX_POINT('',#487);+#487 = CARTESIAN_POINT('',(0.3,0.21,0.48));+#488 = LINE('',#489,#490);+#489 = CARTESIAN_POINT('',(-0.3,0.21,0.48));+#490 = VECTOR('',#491,1.);+#491 = DIRECTION('',(1.,0.,0.));+#492 = ORIENTED_EDGE('',*,*,#493,.F.);+#493 = EDGE_CURVE('',#461,#486,#494,.T.);+#494 = CIRCLE('',#495,2.E-02);+#495 = AXIS2_PLACEMENT_3D('',#496,#497,#498);+#496 = CARTESIAN_POINT('',(0.3,0.21,0.46));+#497 = DIRECTION('',(1.,0.,-0.));+#498 = DIRECTION('',(0.,0.,1.));+#499 = ORIENTED_EDGE('',*,*,#470,.F.);+#500 = CYLINDRICAL_SURFACE('',#501,2.E-02);+#501 = AXIS2_PLACEMENT_3D('',#502,#503,#504);+#502 = CARTESIAN_POINT('',(-0.3,0.21,0.46));+#503 = DIRECTION('',(1.,0.,0.));+#504 = DIRECTION('',(0.,1.,0.));+#505 = ADVANCED_FACE('',(#506),#524,.T.);+#506 = FACE_BOUND('',#507,.T.);+#507 = EDGE_LOOP('',(#508,#509,#517,#523));+#508 = ORIENTED_EDGE('',*,*,#331,.F.);+#509 = ORIENTED_EDGE('',*,*,#510,.T.);+#510 = EDGE_CURVE('',#323,#511,#513,.T.);+#511 = VERTEX_POINT('',#512);+#512 = CARTESIAN_POINT('',(0.3,-0.21,0.48));+#513 = LINE('',#514,#515);+#514 = CARTESIAN_POINT('',(-0.3,-0.21,0.48));+#515 = VECTOR('',#516,1.);+#516 = DIRECTION('',(1.,0.,0.));+#517 = ORIENTED_EDGE('',*,*,#518,.T.);+#518 = EDGE_CURVE('',#511,#486,#519,.T.);+#519 = LINE('',#520,#521);+#520 = CARTESIAN_POINT('',(0.3,-0.23,0.48));+#521 = VECTOR('',#522,1.);+#522 = DIRECTION('',(0.,1.,0.));+#523 = ORIENTED_EDGE('',*,*,#485,.F.);+#524 = PLANE('',#525);+#525 = AXIS2_PLACEMENT_3D('',#526,#527,#528);+#526 = CARTESIAN_POINT('',(-0.3,-0.23,0.48));+#527 = DIRECTION('',(0.,0.,1.));+#528 = DIRECTION('',(1.,0.,0.));+#529 = ADVANCED_FACE('',(#530),#549,.T.);+#530 = FACE_BOUND('',#531,.F.);+#531 = EDGE_LOOP('',(#532,#533,#534,#543));+#532 = ORIENTED_EDGE('',*,*,#322,.T.);+#533 = ORIENTED_EDGE('',*,*,#510,.T.);+#534 = ORIENTED_EDGE('',*,*,#535,.F.);+#535 = EDGE_CURVE('',#536,#511,#538,.T.);+#536 = VERTEX_POINT('',#537);+#537 = CARTESIAN_POINT('',(0.3,-0.23,0.46));+#538 = CIRCLE('',#539,2.E-02);+#539 = AXIS2_PLACEMENT_3D('',#540,#541,#542);+#540 = CARTESIAN_POINT('',(0.3,-0.21,0.46));+#541 = DIRECTION('',(-1.,0.,0.));+#542 = DIRECTION('',(0.,0.,1.));+#543 = ORIENTED_EDGE('',*,*,#544,.F.);+#544 = EDGE_CURVE('',#315,#536,#545,.T.);+#545 = LINE('',#546,#547);+#546 = CARTESIAN_POINT('',(-0.3,-0.23,0.46));+#547 = VECTOR('',#548,1.);+#548 = DIRECTION('',(1.,0.,0.));+#549 = CYLINDRICAL_SURFACE('',#550,2.E-02);+#550 = AXIS2_PLACEMENT_3D('',#551,#552,#553);+#551 = CARTESIAN_POINT('',(-0.3,-0.21,0.46));+#552 = DIRECTION('',(1.,0.,0.));+#553 = DIRECTION('',(0.,-1.,0.));+#554 = ADVANCED_FACE('',(#555),#566,.F.);+#555 = FACE_BOUND('',#556,.F.);+#556 = EDGE_LOOP('',(#557,#563,#564,#565));+#557 = ORIENTED_EDGE('',*,*,#558,.F.);+#558 = EDGE_CURVE('',#389,#536,#559,.T.);+#559 = LINE('',#560,#561);+#560 = CARTESIAN_POINT('',(0.3,-0.23,2.E-02));+#561 = VECTOR('',#562,1.);+#562 = DIRECTION('',(0.,0.,1.));+#563 = ORIENTED_EDGE('',*,*,#397,.F.);+#564 = ORIENTED_EDGE('',*,*,#314,.T.);+#565 = ORIENTED_EDGE('',*,*,#544,.T.);+#566 = PLANE('',#567);+#567 = AXIS2_PLACEMENT_3D('',#568,#569,#570);+#568 = CARTESIAN_POINT('',(-0.3,-0.23,2.E-02));+#569 = DIRECTION('',(0.,1.,0.));+#570 = DIRECTION('',(0.,0.,1.));+#571 = ADVANCED_FACE('',(#572,#642),#652,.F.);+#572 = FACE_BOUND('',#573,.F.);+#573 = EDGE_LOOP('',(#574,#584,#593,#601,#610,#618,#627,#635));+#574 = ORIENTED_EDGE('',*,*,#575,.F.);+#575 = EDGE_CURVE('',#576,#578,#580,.T.);+#576 = VERTEX_POINT('',#577);+#577 = CARTESIAN_POINT('',(0.3,-0.25,2.E-02));+#578 = VERTEX_POINT('',#579);+#579 = CARTESIAN_POINT('',(0.3,-0.25,0.48));+#580 = LINE('',#581,#582);+#581 = CARTESIAN_POINT('',(0.3,-0.25,0.));+#582 = VECTOR('',#583,1.);+#583 = DIRECTION('',(0.,0.,1.));+#584 = ORIENTED_EDGE('',*,*,#585,.T.);+#585 = EDGE_CURVE('',#576,#586,#588,.T.);+#586 = VERTEX_POINT('',#587);+#587 = CARTESIAN_POINT('',(0.3,-0.23,0.));+#588 = CIRCLE('',#589,2.E-02);+#589 = AXIS2_PLACEMENT_3D('',#590,#591,#592);+#590 = CARTESIAN_POINT('',(0.3,-0.23,2.E-02));+#591 = DIRECTION('',(1.,0.,-0.));+#592 = DIRECTION('',(0.,0.,1.));+#593 = ORIENTED_EDGE('',*,*,#594,.T.);+#594 = EDGE_CURVE('',#586,#595,#597,.T.);+#595 = VERTEX_POINT('',#596);+#596 = CARTESIAN_POINT('',(0.3,0.23,0.));+#597 = LINE('',#598,#599);+#598 = CARTESIAN_POINT('',(0.3,-0.25,0.));+#599 = VECTOR('',#600,1.);+#600 = DIRECTION('',(0.,1.,0.));+#601 = ORIENTED_EDGE('',*,*,#602,.F.);+#602 = EDGE_CURVE('',#603,#595,#605,.T.);+#603 = VERTEX_POINT('',#604);+#604 = CARTESIAN_POINT('',(0.3,0.25,2.E-02));+#605 = CIRCLE('',#606,2.E-02);+#606 = AXIS2_PLACEMENT_3D('',#607,#608,#609);+#607 = CARTESIAN_POINT('',(0.3,0.23,2.E-02));+#608 = DIRECTION('',(-1.,0.,0.));+#609 = DIRECTION('',(0.,0.,1.));+#610 = ORIENTED_EDGE('',*,*,#611,.T.);+#611 = EDGE_CURVE('',#603,#612,#614,.T.);+#612 = VERTEX_POINT('',#613);+#613 = CARTESIAN_POINT('',(0.3,0.25,0.48));+#614 = LINE('',#615,#616);+#615 = CARTESIAN_POINT('',(0.3,0.25,0.));+#616 = VECTOR('',#617,1.);+#617 = DIRECTION('',(0.,0.,1.));+#618 = ORIENTED_EDGE('',*,*,#619,.T.);+#619 = EDGE_CURVE('',#612,#620,#622,.T.);+#620 = VERTEX_POINT('',#621);+#621 = CARTESIAN_POINT('',(0.3,0.23,0.5));+#622 = CIRCLE('',#623,2.E-02);+#623 = AXIS2_PLACEMENT_3D('',#624,#625,#626);+#624 = CARTESIAN_POINT('',(0.3,0.23,0.48));+#625 = DIRECTION('',(1.,0.,-0.));+#626 = DIRECTION('',(0.,0.,1.));+#627 = ORIENTED_EDGE('',*,*,#628,.F.);+#628 = EDGE_CURVE('',#629,#620,#631,.T.);+#629 = VERTEX_POINT('',#630);+#630 = CARTESIAN_POINT('',(0.3,-0.23,0.5));+#631 = LINE('',#632,#633);+#632 = CARTESIAN_POINT('',(0.3,-0.25,0.5));+#633 = VECTOR('',#634,1.);+#634 = DIRECTION('',(0.,1.,0.));+#635 = ORIENTED_EDGE('',*,*,#636,.F.);+#636 = EDGE_CURVE('',#578,#629,#637,.T.);+#637 = CIRCLE('',#638,2.E-02);+#638 = AXIS2_PLACEMENT_3D('',#639,#640,#641);+#639 = CARTESIAN_POINT('',(0.3,-0.23,0.48));+#640 = DIRECTION('',(-1.,0.,0.));+#641 = DIRECTION('',(0.,0.,1.));+#642 = FACE_BOUND('',#643,.F.);+#643 = EDGE_LOOP('',(#644,#645,#646,#647,#648,#649,#650,#651));+#644 = ORIENTED_EDGE('',*,*,#388,.F.);+#645 = ORIENTED_EDGE('',*,*,#558,.T.);+#646 = ORIENTED_EDGE('',*,*,#535,.T.);+#647 = ORIENTED_EDGE('',*,*,#518,.T.);+#648 = ORIENTED_EDGE('',*,*,#493,.F.);+#649 = ORIENTED_EDGE('',*,*,#460,.F.);+#650 = ORIENTED_EDGE('',*,*,#437,.T.);+#651 = ORIENTED_EDGE('',*,*,#413,.F.);+#652 = PLANE('',#653);+#653 = AXIS2_PLACEMENT_3D('',#654,#655,#656);+#654 = CARTESIAN_POINT('',(0.3,-0.25,0.));+#655 = DIRECTION('',(1.,0.,0.));+#656 = DIRECTION('',(0.,0.,1.));+#657 = ADVANCED_FACE('',(#658),#683,.F.);+#658 = FACE_BOUND('',#659,.F.);+#659 = EDGE_LOOP('',(#660,#670,#676,#677));+#660 = ORIENTED_EDGE('',*,*,#661,.F.);+#661 = EDGE_CURVE('',#662,#664,#666,.T.);+#662 = VERTEX_POINT('',#663);+#663 = CARTESIAN_POINT('',(0.5,-0.25,2.E-02));+#664 = VERTEX_POINT('',#665);+#665 = CARTESIAN_POINT('',(0.5,-0.25,0.48));+#666 = LINE('',#667,#668);+#667 = CARTESIAN_POINT('',(0.5,-0.25,0.));+#668 = VECTOR('',#669,1.);+#669 = DIRECTION('',(0.,0.,1.));+#670 = ORIENTED_EDGE('',*,*,#671,.F.);+#671 = EDGE_CURVE('',#576,#662,#672,.T.);+#672 = LINE('',#673,#674);+#673 = CARTESIAN_POINT('',(0.3,-0.25,2.E-02));+#674 = VECTOR('',#675,1.);+#675 = DIRECTION('',(1.,0.,0.));+#676 = ORIENTED_EDGE('',*,*,#575,.T.);+#677 = ORIENTED_EDGE('',*,*,#678,.T.);+#678 = EDGE_CURVE('',#578,#664,#679,.T.);+#679 = LINE('',#680,#681);+#680 = CARTESIAN_POINT('',(0.3,-0.25,0.48));+#681 = VECTOR('',#682,1.);+#682 = DIRECTION('',(1.,0.,0.));+#683 = PLANE('',#684);+#684 = AXIS2_PLACEMENT_3D('',#685,#686,#687);+#685 = CARTESIAN_POINT('',(0.3,-0.25,0.));+#686 = DIRECTION('',(0.,1.,0.));+#687 = DIRECTION('',(0.,0.,1.));+#688 = ADVANCED_FACE('',(#689),#708,.T.);+#689 = FACE_BOUND('',#690,.T.);+#690 = EDGE_LOOP('',(#691,#692,#700,#707));+#691 = ORIENTED_EDGE('',*,*,#585,.T.);+#692 = ORIENTED_EDGE('',*,*,#693,.T.);+#693 = EDGE_CURVE('',#586,#694,#696,.T.);+#694 = VERTEX_POINT('',#695);+#695 = CARTESIAN_POINT('',(0.5,-0.23,0.));+#696 = LINE('',#697,#698);+#697 = CARTESIAN_POINT('',(0.3,-0.23,0.));+#698 = VECTOR('',#699,1.);+#699 = DIRECTION('',(1.,0.,0.));+#700 = ORIENTED_EDGE('',*,*,#701,.F.);+#701 = EDGE_CURVE('',#662,#694,#702,.T.);+#702 = CIRCLE('',#703,2.E-02);+#703 = AXIS2_PLACEMENT_3D('',#704,#705,#706);+#704 = CARTESIAN_POINT('',(0.5,-0.23,2.E-02));+#705 = DIRECTION('',(1.,0.,-0.));+#706 = DIRECTION('',(0.,0.,1.));+#707 = ORIENTED_EDGE('',*,*,#671,.F.);+#708 = CYLINDRICAL_SURFACE('',#709,2.E-02);+#709 = AXIS2_PLACEMENT_3D('',#710,#711,#712);+#710 = CARTESIAN_POINT('',(0.3,-0.23,2.E-02));+#711 = DIRECTION('',(1.,0.,0.));+#712 = DIRECTION('',(0.,-1.,0.));+#713 = ADVANCED_FACE('',(#714),#733,.T.);+#714 = FACE_BOUND('',#715,.F.);+#715 = EDGE_LOOP('',(#716,#717,#725,#732));+#716 = ORIENTED_EDGE('',*,*,#636,.T.);+#717 = ORIENTED_EDGE('',*,*,#718,.T.);+#718 = EDGE_CURVE('',#629,#719,#721,.T.);+#719 = VERTEX_POINT('',#720);+#720 = CARTESIAN_POINT('',(0.5,-0.23,0.5));+#721 = LINE('',#722,#723);+#722 = CARTESIAN_POINT('',(0.3,-0.23,0.5));+#723 = VECTOR('',#724,1.);+#724 = DIRECTION('',(1.,0.,0.));+#725 = ORIENTED_EDGE('',*,*,#726,.F.);+#726 = EDGE_CURVE('',#664,#719,#727,.T.);+#727 = CIRCLE('',#728,2.E-02);+#728 = AXIS2_PLACEMENT_3D('',#729,#730,#731);+#729 = CARTESIAN_POINT('',(0.5,-0.23,0.48));+#730 = DIRECTION('',(-1.,0.,0.));+#731 = DIRECTION('',(0.,0.,1.));+#732 = ORIENTED_EDGE('',*,*,#678,.F.);+#733 = CYLINDRICAL_SURFACE('',#734,2.E-02);+#734 = AXIS2_PLACEMENT_3D('',#735,#736,#737);+#735 = CARTESIAN_POINT('',(0.3,-0.23,0.48));+#736 = DIRECTION('',(1.,0.,0.));+#737 = DIRECTION('',(0.,-1.,0.));+#738 = ADVANCED_FACE('',(#739),#757,.F.);+#739 = FACE_BOUND('',#740,.F.);+#740 = EDGE_LOOP('',(#741,#742,#743,#751));+#741 = ORIENTED_EDGE('',*,*,#594,.F.);+#742 = ORIENTED_EDGE('',*,*,#693,.T.);+#743 = ORIENTED_EDGE('',*,*,#744,.T.);+#744 = EDGE_CURVE('',#694,#745,#747,.T.);+#745 = VERTEX_POINT('',#746);+#746 = CARTESIAN_POINT('',(0.5,0.23,0.));+#747 = LINE('',#748,#749);+#748 = CARTESIAN_POINT('',(0.5,-0.25,0.));+#749 = VECTOR('',#750,1.);+#750 = DIRECTION('',(0.,1.,0.));+#751 = ORIENTED_EDGE('',*,*,#752,.F.);+#752 = EDGE_CURVE('',#595,#745,#753,.T.);+#753 = LINE('',#754,#755);+#754 = CARTESIAN_POINT('',(0.3,0.23,0.));+#755 = VECTOR('',#756,1.);+#756 = DIRECTION('',(1.,0.,0.));+#757 = PLANE('',#758);+#758 = AXIS2_PLACEMENT_3D('',#759,#760,#761);+#759 = CARTESIAN_POINT('',(0.3,-0.25,0.));+#760 = DIRECTION('',(0.,0.,1.));+#761 = DIRECTION('',(1.,0.,0.));+#762 = ADVANCED_FACE('',(#763),#781,.T.);+#763 = FACE_BOUND('',#764,.T.);+#764 = EDGE_LOOP('',(#765,#766,#767,#775));+#765 = ORIENTED_EDGE('',*,*,#628,.F.);+#766 = ORIENTED_EDGE('',*,*,#718,.T.);+#767 = ORIENTED_EDGE('',*,*,#768,.T.);+#768 = EDGE_CURVE('',#719,#769,#771,.T.);+#769 = VERTEX_POINT('',#770);+#770 = CARTESIAN_POINT('',(0.5,0.23,0.5));+#771 = LINE('',#772,#773);+#772 = CARTESIAN_POINT('',(0.5,-0.25,0.5));+#773 = VECTOR('',#774,1.);+#774 = DIRECTION('',(0.,1.,0.));+#775 = ORIENTED_EDGE('',*,*,#776,.F.);+#776 = EDGE_CURVE('',#620,#769,#777,.T.);+#777 = LINE('',#778,#779);+#778 = CARTESIAN_POINT('',(0.3,0.23,0.5));+#779 = VECTOR('',#780,1.);+#780 = DIRECTION('',(1.,0.,0.));+#781 = PLANE('',#782);+#782 = AXIS2_PLACEMENT_3D('',#783,#784,#785);+#783 = CARTESIAN_POINT('',(0.3,-0.25,0.5));+#784 = DIRECTION('',(0.,0.,1.));+#785 = DIRECTION('',(1.,0.,0.));+#786 = ADVANCED_FACE('',(#787),#806,.T.);+#787 = FACE_BOUND('',#788,.F.);+#788 = EDGE_LOOP('',(#789,#790,#791,#800));+#789 = ORIENTED_EDGE('',*,*,#602,.T.);+#790 = ORIENTED_EDGE('',*,*,#752,.T.);+#791 = ORIENTED_EDGE('',*,*,#792,.F.);+#792 = EDGE_CURVE('',#793,#745,#795,.T.);+#793 = VERTEX_POINT('',#794);+#794 = CARTESIAN_POINT('',(0.5,0.25,2.E-02));+#795 = CIRCLE('',#796,2.E-02);+#796 = AXIS2_PLACEMENT_3D('',#797,#798,#799);+#797 = CARTESIAN_POINT('',(0.5,0.23,2.E-02));+#798 = DIRECTION('',(-1.,0.,0.));+#799 = DIRECTION('',(0.,0.,1.));+#800 = ORIENTED_EDGE('',*,*,#801,.F.);+#801 = EDGE_CURVE('',#603,#793,#802,.T.);+#802 = LINE('',#803,#804);+#803 = CARTESIAN_POINT('',(0.3,0.25,2.E-02));+#804 = VECTOR('',#805,1.);+#805 = DIRECTION('',(1.,0.,0.));+#806 = CYLINDRICAL_SURFACE('',#807,2.E-02);+#807 = AXIS2_PLACEMENT_3D('',#808,#809,#810);+#808 = CARTESIAN_POINT('',(0.3,0.23,2.E-02));+#809 = DIRECTION('',(1.,0.,0.));+#810 = DIRECTION('',(0.,1.,0.));+#811 = ADVANCED_FACE('',(#812),#831,.T.);+#812 = FACE_BOUND('',#813,.T.);+#813 = EDGE_LOOP('',(#814,#815,#816,#825));+#814 = ORIENTED_EDGE('',*,*,#619,.T.);+#815 = ORIENTED_EDGE('',*,*,#776,.T.);+#816 = ORIENTED_EDGE('',*,*,#817,.F.);+#817 = EDGE_CURVE('',#818,#769,#820,.T.);+#818 = VERTEX_POINT('',#819);+#819 = CARTESIAN_POINT('',(0.5,0.25,0.48));+#820 = CIRCLE('',#821,2.E-02);+#821 = AXIS2_PLACEMENT_3D('',#822,#823,#824);+#822 = CARTESIAN_POINT('',(0.5,0.23,0.48));+#823 = DIRECTION('',(1.,0.,-0.));+#824 = DIRECTION('',(0.,0.,1.));+#825 = ORIENTED_EDGE('',*,*,#826,.F.);+#826 = EDGE_CURVE('',#612,#818,#827,.T.);+#827 = LINE('',#828,#829);+#828 = CARTESIAN_POINT('',(0.3,0.25,0.48));+#829 = VECTOR('',#830,1.);+#830 = DIRECTION('',(1.,0.,0.));+#831 = CYLINDRICAL_SURFACE('',#832,2.E-02);+#832 = AXIS2_PLACEMENT_3D('',#833,#834,#835);+#833 = CARTESIAN_POINT('',(0.3,0.23,0.48));+#834 = DIRECTION('',(1.,0.,0.));+#835 = DIRECTION('',(0.,1.,0.));+#836 = ADVANCED_FACE('',(#837),#848,.T.);+#837 = FACE_BOUND('',#838,.T.);+#838 = EDGE_LOOP('',(#839,#845,#846,#847));+#839 = ORIENTED_EDGE('',*,*,#840,.F.);+#840 = EDGE_CURVE('',#793,#818,#841,.T.);+#841 = LINE('',#842,#843);+#842 = CARTESIAN_POINT('',(0.5,0.25,0.));+#843 = VECTOR('',#844,1.);+#844 = DIRECTION('',(0.,0.,1.));+#845 = ORIENTED_EDGE('',*,*,#801,.F.);+#846 = ORIENTED_EDGE('',*,*,#611,.T.);+#847 = ORIENTED_EDGE('',*,*,#826,.T.);+#848 = PLANE('',#849);+#849 = AXIS2_PLACEMENT_3D('',#850,#851,#852);+#850 = CARTESIAN_POINT('',(0.3,0.25,0.));+#851 = DIRECTION('',(0.,1.,0.));+#852 = DIRECTION('',(0.,0.,1.));+#853 = ADVANCED_FACE('',(#854),#864,.T.);+#854 = FACE_BOUND('',#855,.T.);+#855 = EDGE_LOOP('',(#856,#857,#858,#859,#860,#861,#862,#863));+#856 = ORIENTED_EDGE('',*,*,#661,.F.);+#857 = ORIENTED_EDGE('',*,*,#701,.T.);+#858 = ORIENTED_EDGE('',*,*,#744,.T.);+#859 = ORIENTED_EDGE('',*,*,#792,.F.);+#860 = ORIENTED_EDGE('',*,*,#840,.T.);+#861 = ORIENTED_EDGE('',*,*,#817,.T.);+#862 = ORIENTED_EDGE('',*,*,#768,.F.);+#863 = ORIENTED_EDGE('',*,*,#726,.F.);+#864 = PLANE('',#865);+#865 = AXIS2_PLACEMENT_3D('',#866,#867,#868);+#866 = CARTESIAN_POINT('',(0.5,-0.25,0.));+#867 = DIRECTION('',(1.,0.,0.));+#868 = DIRECTION('',(0.,0.,1.));+#869 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3)+GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#873)) GLOBAL_UNIT_ASSIGNED_CONTEXT+((#870,#871,#872)) REPRESENTATION_CONTEXT('Context #1',+'3D Context with UNIT and UNCERTAINTY') );+#870 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );+#871 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) );+#872 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() );+#873 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#870,+'distance_accuracy_value','confusion accuracy');+#874 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#7));+#875 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#876,+#884,#891,#898,#905,#912,#919,#926,#933,#940,#947,#955,#962,#969,+#976,#983,#990,#997,#1004,#1011,#1018,#1025,#1032,#1039,#1046,#1053,+#1060,#1067),#869);+#876 = STYLED_ITEM('color',(#877),#17);+#877 = PRESENTATION_STYLE_ASSIGNMENT((#878));+#878 = SURFACE_STYLE_USAGE(.BOTH.,#879);+#879 = SURFACE_SIDE_STYLE('',(#880));+#880 = SURFACE_STYLE_FILL_AREA(#881);+#881 = FILL_AREA_STYLE('',(#882));+#882 = FILL_AREA_STYLE_COLOUR('',#883);+#883 = COLOUR_RGB('',0.824000000954,0.819999992847,0.78100001812);+#884 = STYLED_ITEM('color',(#885),#93);+#885 = PRESENTATION_STYLE_ASSIGNMENT((#886));+#886 = SURFACE_STYLE_USAGE(.BOTH.,#887);+#887 = SURFACE_SIDE_STYLE('',(#888));+#888 = SURFACE_STYLE_FILL_AREA(#889);+#889 = FILL_AREA_STYLE('',(#890));+#890 = FILL_AREA_STYLE_COLOUR('',#883);+#891 = STYLED_ITEM('color',(#892),#124);+#892 = PRESENTATION_STYLE_ASSIGNMENT((#893));+#893 = SURFACE_STYLE_USAGE(.BOTH.,#894);+#894 = SURFACE_SIDE_STYLE('',(#895));+#895 = SURFACE_STYLE_FILL_AREA(#896);+#896 = FILL_AREA_STYLE('',(#897));+#897 = FILL_AREA_STYLE_COLOUR('',#883);+#898 = STYLED_ITEM('color',(#899),#149);+#899 = PRESENTATION_STYLE_ASSIGNMENT((#900));+#900 = SURFACE_STYLE_USAGE(.BOTH.,#901);+#901 = SURFACE_SIDE_STYLE('',(#902));+#902 = SURFACE_STYLE_FILL_AREA(#903);+#903 = FILL_AREA_STYLE('',(#904));+#904 = FILL_AREA_STYLE_COLOUR('',#883);+#905 = STYLED_ITEM('color',(#906),#174);+#906 = PRESENTATION_STYLE_ASSIGNMENT((#907));+#907 = SURFACE_STYLE_USAGE(.BOTH.,#908);+#908 = SURFACE_SIDE_STYLE('',(#909));+#909 = SURFACE_STYLE_FILL_AREA(#910);+#910 = FILL_AREA_STYLE('',(#911));+#911 = FILL_AREA_STYLE_COLOUR('',#883);+#912 = STYLED_ITEM('color',(#913),#198);+#913 = PRESENTATION_STYLE_ASSIGNMENT((#914));+#914 = SURFACE_STYLE_USAGE(.BOTH.,#915);+#915 = SURFACE_SIDE_STYLE('',(#916));+#916 = SURFACE_STYLE_FILL_AREA(#917);+#917 = FILL_AREA_STYLE('',(#918));+#918 = FILL_AREA_STYLE_COLOUR('',#883);+#919 = STYLED_ITEM('color',(#920),#222);+#920 = PRESENTATION_STYLE_ASSIGNMENT((#921));+#921 = SURFACE_STYLE_USAGE(.BOTH.,#922);+#922 = SURFACE_SIDE_STYLE('',(#923));+#923 = SURFACE_STYLE_FILL_AREA(#924);+#924 = FILL_AREA_STYLE('',(#925));+#925 = FILL_AREA_STYLE_COLOUR('',#883);+#926 = STYLED_ITEM('color',(#927),#247);+#927 = PRESENTATION_STYLE_ASSIGNMENT((#928));+#928 = SURFACE_STYLE_USAGE(.BOTH.,#929);+#929 = SURFACE_SIDE_STYLE('',(#930));+#930 = SURFACE_STYLE_FILL_AREA(#931);+#931 = FILL_AREA_STYLE('',(#932));+#932 = FILL_AREA_STYLE_COLOUR('',#883);+#933 = STYLED_ITEM('color',(#934),#272);+#934 = PRESENTATION_STYLE_ASSIGNMENT((#935));+#935 = SURFACE_STYLE_USAGE(.BOTH.,#936);+#936 = SURFACE_SIDE_STYLE('',(#937));+#937 = SURFACE_STYLE_FILL_AREA(#938);+#938 = FILL_AREA_STYLE('',(#939));+#939 = FILL_AREA_STYLE_COLOUR('',#883);+#940 = STYLED_ITEM('color',(#941),#289);+#941 = PRESENTATION_STYLE_ASSIGNMENT((#942));+#942 = SURFACE_STYLE_USAGE(.BOTH.,#943);+#943 = SURFACE_SIDE_STYLE('',(#944));+#944 = SURFACE_STYLE_FILL_AREA(#945);+#945 = FILL_AREA_STYLE('',(#946));+#946 = FILL_AREA_STYLE_COLOUR('',#883);+#947 = STYLED_ITEM('color',(#948),#375);+#948 = PRESENTATION_STYLE_ASSIGNMENT((#949));+#949 = SURFACE_STYLE_USAGE(.BOTH.,#950);+#950 = SURFACE_SIDE_STYLE('',(#951));+#951 = SURFACE_STYLE_FILL_AREA(#952);+#952 = FILL_AREA_STYLE('',(#953));+#953 = FILL_AREA_STYLE_COLOUR('',#954);+#954 = COLOUR_RGB('',0.379000008106,0.270000010729,0.215000003576);+#955 = STYLED_ITEM('color',(#956),#407);+#956 = PRESENTATION_STYLE_ASSIGNMENT((#957));+#957 = SURFACE_STYLE_USAGE(.BOTH.,#958);+#958 = SURFACE_SIDE_STYLE('',(#959));+#959 = SURFACE_STYLE_FILL_AREA(#960);+#960 = FILL_AREA_STYLE('',(#961));+#961 = FILL_AREA_STYLE_COLOUR('',#954);+#962 = STYLED_ITEM('color',(#963),#431);+#963 = PRESENTATION_STYLE_ASSIGNMENT((#964));+#964 = SURFACE_STYLE_USAGE(.BOTH.,#965);+#965 = SURFACE_SIDE_STYLE('',(#966));+#966 = SURFACE_STYLE_FILL_AREA(#967);+#967 = FILL_AREA_STYLE('',(#968));+#968 = FILL_AREA_STYLE_COLOUR('',#954);+#969 = STYLED_ITEM('color',(#970),#456);+#970 = PRESENTATION_STYLE_ASSIGNMENT((#971));+#971 = SURFACE_STYLE_USAGE(.BOTH.,#972);+#972 = SURFACE_SIDE_STYLE('',(#973));+#973 = SURFACE_STYLE_FILL_AREA(#974);+#974 = FILL_AREA_STYLE('',(#975));+#975 = FILL_AREA_STYLE_COLOUR('',#954);+#976 = STYLED_ITEM('color',(#977),#480);+#977 = PRESENTATION_STYLE_ASSIGNMENT((#978));+#978 = SURFACE_STYLE_USAGE(.BOTH.,#979);+#979 = SURFACE_SIDE_STYLE('',(#980));+#980 = SURFACE_STYLE_FILL_AREA(#981);+#981 = FILL_AREA_STYLE('',(#982));+#982 = FILL_AREA_STYLE_COLOUR('',#954);+#983 = STYLED_ITEM('color',(#984),#505);+#984 = PRESENTATION_STYLE_ASSIGNMENT((#985));+#985 = SURFACE_STYLE_USAGE(.BOTH.,#986);+#986 = SURFACE_SIDE_STYLE('',(#987));+#987 = SURFACE_STYLE_FILL_AREA(#988);+#988 = FILL_AREA_STYLE('',(#989));+#989 = FILL_AREA_STYLE_COLOUR('',#954);+#990 = STYLED_ITEM('color',(#991),#529);+#991 = PRESENTATION_STYLE_ASSIGNMENT((#992));+#992 = SURFACE_STYLE_USAGE(.BOTH.,#993);+#993 = SURFACE_SIDE_STYLE('',(#994));+#994 = SURFACE_STYLE_FILL_AREA(#995);+#995 = FILL_AREA_STYLE('',(#996));+#996 = FILL_AREA_STYLE_COLOUR('',#954);+#997 = STYLED_ITEM('color',(#998),#554);+#998 = PRESENTATION_STYLE_ASSIGNMENT((#999));+#999 = SURFACE_STYLE_USAGE(.BOTH.,#1000);+#1000 = SURFACE_SIDE_STYLE('',(#1001));+#1001 = SURFACE_STYLE_FILL_AREA(#1002);+#1002 = FILL_AREA_STYLE('',(#1003));+#1003 = FILL_AREA_STYLE_COLOUR('',#954);+#1004 = STYLED_ITEM('color',(#1005),#571);+#1005 = PRESENTATION_STYLE_ASSIGNMENT((#1006));+#1006 = SURFACE_STYLE_USAGE(.BOTH.,#1007);+#1007 = SURFACE_SIDE_STYLE('',(#1008));+#1008 = SURFACE_STYLE_FILL_AREA(#1009);+#1009 = FILL_AREA_STYLE('',(#1010));+#1010 = FILL_AREA_STYLE_COLOUR('',#883);+#1011 = STYLED_ITEM('color',(#1012),#657);+#1012 = PRESENTATION_STYLE_ASSIGNMENT((#1013));+#1013 = SURFACE_STYLE_USAGE(.BOTH.,#1014);+#1014 = SURFACE_SIDE_STYLE('',(#1015));+#1015 = SURFACE_STYLE_FILL_AREA(#1016);+#1016 = FILL_AREA_STYLE('',(#1017));+#1017 = FILL_AREA_STYLE_COLOUR('',#883);+#1018 = STYLED_ITEM('color',(#1019),#688);+#1019 = PRESENTATION_STYLE_ASSIGNMENT((#1020));+#1020 = SURFACE_STYLE_USAGE(.BOTH.,#1021);+#1021 = SURFACE_SIDE_STYLE('',(#1022));+#1022 = SURFACE_STYLE_FILL_AREA(#1023);+#1023 = FILL_AREA_STYLE('',(#1024));+#1024 = FILL_AREA_STYLE_COLOUR('',#883);+#1025 = STYLED_ITEM('color',(#1026),#713);+#1026 = PRESENTATION_STYLE_ASSIGNMENT((#1027));+#1027 = SURFACE_STYLE_USAGE(.BOTH.,#1028);+#1028 = SURFACE_SIDE_STYLE('',(#1029));+#1029 = SURFACE_STYLE_FILL_AREA(#1030);+#1030 = FILL_AREA_STYLE('',(#1031));+#1031 = FILL_AREA_STYLE_COLOUR('',#883);+#1032 = STYLED_ITEM('color',(#1033),#738);+#1033 = PRESENTATION_STYLE_ASSIGNMENT((#1034));+#1034 = SURFACE_STYLE_USAGE(.BOTH.,#1035);+#1035 = SURFACE_SIDE_STYLE('',(#1036));+#1036 = SURFACE_STYLE_FILL_AREA(#1037);+#1037 = FILL_AREA_STYLE('',(#1038));+#1038 = FILL_AREA_STYLE_COLOUR('',#883);+#1039 = STYLED_ITEM('color',(#1040),#762);+#1040 = PRESENTATION_STYLE_ASSIGNMENT((#1041));+#1041 = SURFACE_STYLE_USAGE(.BOTH.,#1042);+#1042 = SURFACE_SIDE_STYLE('',(#1043));+#1043 = SURFACE_STYLE_FILL_AREA(#1044);+#1044 = FILL_AREA_STYLE('',(#1045));+#1045 = FILL_AREA_STYLE_COLOUR('',#883);+#1046 = STYLED_ITEM('color',(#1047),#786);+#1047 = PRESENTATION_STYLE_ASSIGNMENT((#1048));+#1048 = SURFACE_STYLE_USAGE(.BOTH.,#1049);+#1049 = SURFACE_SIDE_STYLE('',(#1050));+#1050 = SURFACE_STYLE_FILL_AREA(#1051);+#1051 = FILL_AREA_STYLE('',(#1052));+#1052 = FILL_AREA_STYLE_COLOUR('',#883);+#1053 = STYLED_ITEM('color',(#1054),#811);+#1054 = PRESENTATION_STYLE_ASSIGNMENT((#1055));+#1055 = SURFACE_STYLE_USAGE(.BOTH.,#1056);+#1056 = SURFACE_SIDE_STYLE('',(#1057));+#1057 = SURFACE_STYLE_FILL_AREA(#1058);+#1058 = FILL_AREA_STYLE('',(#1059));+#1059 = FILL_AREA_STYLE_COLOUR('',#883);+#1060 = STYLED_ITEM('color',(#1061),#836);+#1061 = PRESENTATION_STYLE_ASSIGNMENT((#1062));+#1062 = SURFACE_STYLE_USAGE(.BOTH.,#1063);+#1063 = SURFACE_SIDE_STYLE('',(#1064));+#1064 = SURFACE_STYLE_FILL_AREA(#1065);+#1065 = FILL_AREA_STYLE('',(#1066));+#1066 = FILL_AREA_STYLE_COLOUR('',#883);+#1067 = STYLED_ITEM('color',(#1068),#853);+#1068 = PRESENTATION_STYLE_ASSIGNMENT((#1069));+#1069 = SURFACE_STYLE_USAGE(.BOTH.,#1070);+#1070 = SURFACE_SIDE_STYLE('',(#1071));+#1071 = SURFACE_STYLE_FILL_AREA(#1072);+#1072 = FILL_AREA_STYLE('',(#1073));+#1073 = FILL_AREA_STYLE_COLOUR('',#883);+ENDSEC;+END-ISO-10303-21;
LICENSEadded+16
@@ -0,0 +1,16 @@+GRM1555C1H220JA01D component page++Original Adom content on this page (README text, the KiCad symbol GRM1555C1H220JA01D.kicad_sym, the+verification drawings, the hero artwork, the Fusion and Altium libraries generated+from them, the JSON records and the scripts in provenance/tools/; hero_glb.py and+hero_glyphs.json come from adom/component-hero)+is licensed under the Creative Commons Attribution 4.0 International License+(CC-BY-4.0): https://creativecommons.org/licenses/by/4.0/++Third-party files keep their own terms and are not relicensed by this page:+- C_0402_1005Metric_GRM1555C1H220JA01D.kicad_mod and GRM1555C1H220JA01D.step (and the GLB, hero and LOD files derived from it) are KiCad library+  content, CC-BY-SA 4.0 with the KiCad library exception+  (https://gitlab.com/kicad/libraries/kicad-footprints, https://gitlab.com/kicad/libraries/kicad-packages3D).+- The PDFs in docs/ are Murata documents, copyright of their publishers,+  included unchanged for reference; the PNG crops in docs/figures/ are excerpts of+  those PDFs, shown as citations.
README.md+160−2
@@ -1,3 +1,161 @@-# GRM1555C1H220JA01D - Murata+# GRM1555C1H220JA01D -MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)+Murata GRM1555C1H220JA01D: MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric).++::adom-verified{src="/adom/grm1555c1h220ja01d/render/verification.json"}++| Field | Value |+|---|---|+| Manufacturer | Murata Manufacturing |+| Manufacturer part number | GRM1555C1H220JA01D |+| Type | MLCC, Class 1 (C0G) |+| Value | 22 pF |+| Tolerance | +/-5 % (J) |+| Rated voltage | 50 V DC (1H) |+| Dielectric | C0G (EIA) / 5C, 0 +/-30 ppm/C |+| Operating temperature | -55 to 125 C |+| Package | 0402 (1005 metric) |+| Datasheet | [Murata reference sheet GRM1555C1H220JA01-01A, specifications as of Jun. 13, 2026](docs/grm1555c1h220ja01d-datasheet.pdf) |++## Key specifications++| Parameter | Value | Datasheet |+|---|---|---|+| Capacitance | 22 pF | p.2 Rated Value |+| Tolerance | +/-5 % (code J) | p.2 Rated Value |+| Rated voltage | 50 V DC (code 1H) | p.2 Rated Value |+| Temperature characteristic | C0G (EIA), Murata code 5C: 0 +/-30 ppm/C (25 to 125 C, ref. 25 C) | p.2 Rated Value |+| Q | Q >= 400 + 20C, C in pF (840 or more for 22 pF) at 1 MHz (0.5 to 5 Vrms) | p.3 item 7 |+| Operating temperature | -55 to 125 C | p.2 Rated Value |+| Insulation resistance | more than 10000 MOhm at rated voltage (room temperature, 2 min) | p.3 item 5 |+| Mounting | flow or reflow | p.2 Rated Value |+| Size | L 1.0 +/-0.05, W 0.5 +/-0.05, T 0.5 +/-0.05, e 0.15 to 0.35, g 0.3 min (mm) | p.2 Type & Dimension |+| Packaging (suffix D) | 180 mm reel, paper tape W8P2, 10000 pcs per reel | p.2 Package |++All page numbers refer to the PDF in [docs/](docs/grm1555c1h220ja01d-datasheet.pdf) unless stated otherwise.++## Datasheet pages cited++Crops of the reference sheet pages the tables above cite, rendered at 150 dpi from the PDF in docs/.++**p.2 header: part number, size, characteristic, capacitance, voltage and the 'as of' date**++![p.2 header: part number, size, characteristic, capacitance, voltage and the 'as of' date](docs/figures/grm1555c1h220ja01d-ds-p2-title.png)++**p.2 'Type & Dimension' and 'Rated Value'**++![p.2 'Type & Dimension' and 'Rated Value'](docs/figures/grm1555c1h220ja01d-ds-p2-dimension-rating.png)++**p.2 'Package': packaging codes and reel quantities**++![p.2 'Package': packaging codes and reel quantities](docs/figures/grm1555c1h220ja01d-ds-p2-package.png)++**p.3 'Specifications and Test Methods' items 1 to 7 (IR, capacitance, Q or DF)**++![p.3 'Specifications and Test Methods' items 1 to 7 (IR, capacitance, Q or DF)](docs/figures/grm1555c1h220ja01d-ds-p3-specs.png)++**p.27 '2. Land Dimensions', Tables 1 and 2**++![p.27 '2. Land Dimensions', Tables 1 and 2](docs/figures/grm1555c1h220ja01d-ds-p27-land.png)++## Notes++- C0G (class 1) capacitance does not change with DC bias or age to any practical degree; Murata gives 0 +/-30 ppm/C from 25 to 125 C.++## Ordering++| Distributor | Part number | Stock seen 2026-10-21 |+|---|---|---|+| Mouser | [81-GRM1555C1H220JA1D](https://www.mouser.com/ProductDetail/Murata-Electronics/GRM1555C1H220JA01D?qs=4k9rjS6ZRl6sPwaL%252BE1uDQ%3D%3D) | 336,981 |+| DigiKey | [490-5868-2-ND](https://www.digikey.com/en/products/detail/murata-electronics/GRM1555C1H220JA01D/3175187) | 334,755 |+| LCSC / JLCPCB | [C76960](https://www.lcsc.com/product-detail/C76960.html) | 218,107 |++Stock figures are a snapshot from the Adom parts search on 2026-10-21; check the distributor before ordering.++## Manufacturer and resources++| Resource | Link |+|---|---|+| Product page | https://pim.murata.com/en-us/pim/details/?partNum=GRM1555C1H220JA01%23 |+| Datasheet | Murata reference sheet GRM1555C1H220JA01-01A, specifications as of Jun. 13, 2026, [PDF](docs/grm1555c1h220ja01d-datasheet.pdf) ([source](https://search.murata.co.jp/Ceramy/image/img/A01X/G101/ENG/GRM1555C1H220JA01-01A.pdf)) |++## Pins++| Pin | Function |+|---|---|+| 1 | terminal (non-polar) |+| 2 | terminal (non-polar) |++A capacitor of this kind has no polarity and no pin 1 orientation: either terminal may face either way.++## Land pattern: KiCad footprint vs Murata++<table>+<tr>+<td width="104"><a href="land-pattern/README.md"><img src="land-pattern/land-pattern-icon.png" width="112" alt="Land pattern"></a><br><sub>&nbsp;&nbsp;&nbsp;&nbsp;Land&nbsp;pattern&nbsp;&nbsp;&nbsp;&nbsp;</sub></td>+<td>The footprint is KiCad's standard `C_0402_1005Metric`, and this guide lays its pads over the land pattern recommended by Murata, at true scale. The KiCad pads are a little larger than the maker asks for, and the guide shows by how much. Use it to decide whether to keep the KiCad pads or shrink them to the maker's numbers before layout.<br><br><a href="land-pattern/README.md">The comparison, with the numbers</a></td>+</tr>+</table>++## 3D model++Murata publishes no STEP for this exact part number that can be fetched over plain HTTP: its public product-data API+lists the reference sheet, S-parameters, a SPICE netlist and characteristics data for this part, but no 3D CAD file+(checked 2026-10-21). The page therefore uses KiCad's library model for the package, `C_0402_1005Metric.step`, with its bytes+unchanged, renamed `GRM1555C1H220JA01D.step`. It was checked against Murata's printed L, W, T and e limits before use (next section).+`package-reference.glb` is the same model converted with `step2glb convert`, with nothing added. The Murata reference sheet specifies no part marking: none of its 33 pages has a marking section, and the p.2 dimension sketch shows a plain body+(searched: GRM1555C1H220JA01-01A, all 33 pages searched; p.2), so the model shows a plain body and carries no added part-number etch.++The page viewer shows `grm1555c1h220ja01d-hero.glb`: the clean model plus nonphysical reference artwork drawn under it to the adom-hero 1.4+standard (adom/component-hero): the footprint's pads as teal dashed outlines at 50 % opacity, its silkscreen at+70 % transparency and the pad numbers 1 and 2 (the terminals have no names). The part is non-polar, so no pin-1 dot is+added. The artwork never goes into the STEP, `package-reference.glb` or the board LODs.++![Hero preview, top and oblique](docs/grm1555c1h220ja01d-hero-preview.png)++::adom-models{src="/adom/grm1555c1h220ja01d/render/models.json"}++## Model checked against the datasheet++The model was rendered in orthographic top, bottom, side and end views at true scale and laid over a drawing made at the+same scale from the printed table (nominal outline, tolerance limits, allowed terminal band). Every dimension is inside+the printed range: L 1.000 mm (datasheet 0.95 to 1.05), W 0.500 mm (datasheet 0.45 to 0.55), T/H 0.500 mm (datasheet 0.45 to 0.55), e (terminal band), top 0.200 mm (datasheet 0.15 to 0.35), e (terminal band), bottom 0.200 mm (datasheet 0.15 to 0.35). The model is Z-up, seated on z = 0, centred on the footprint origin, long axis on X.++![Model over the datasheet dimensions](docs/verify/grm1555c1h220ja01d-overlay.png)++Source: Murata reference sheet GRM1555C1H220JA01-01A, specifications as of Jun. 13, 2026, p.2 'Type & Dimension', size code 1005M(0402): L 1.0 +/-0.05, W 0.5 +/-0.05, T 0.5 +/-0.05, e 0.15 to 0.35, g 0.3 min (mm).++## Board levels of detail++Clean board-use GLBs (no footprint pads, outlines, labels or silkscreen; no marking) in four levels, all in the same+Z-up, metre, footprint-origin pose as the STEP. Previews are rendered from each GLB.++::adom-component-lod{src="/adom/grm1555c1h220ja01d/render/lod/manifest.json"}++## CAD files++| File | What it is |+|---|---|+| `GRM1555C1H220JA01D.kicad_sym` | KiCad symbol (standard capacitor graphic) with MPN, Manufacturer, Mouser, DigiKey and LCSC fields |+| `C_0402_1005Metric_GRM1555C1H220JA01D.kicad_mod` | KiCad footprint (KiCad library `C_0402_1005Metric`, renamed; model path `${KIPRJMOD}/GRM1555C1H220JA01D.step`) |+| `GRM1555C1H220JA01D.lbr` | Fusion / EAGLE library made from the KiCad symbol and footprint with `adom-lbr generate` (carries MPN, MANUFACTURER, MOUSER_PN, DIGIKEY_PN, LCSC_PN) |+| `GRM1555C1H220JA01D.step` | 3D package model, STEP |+| `package-reference.glb` | 3D package model, GLB, clean (no artwork) |+| `grm1555c1h220ja01d-hero.glb` | page-viewer hero: the clean model plus footprint artwork (adom-hero 1.4); `grm1555c1h220ja01d-hero.overlay.json` lists every pad and label |+| `altium/GRM1555C1H220JA01D.SchLib` | Altium schematic library, made with `adom-lbr import-kicad` and `export-altium` |+| `altium/GRM1555C1H220JA01D.PcbLib` | Altium PCB library, made with `adom-lbr import-kicad` and `export-altium` |+| `altium/GRM1555C1H220JA01D.adom-lbr.json` | Altium adom-lbr hub JSON (symbol, footprint, pin-to-pad map), made with `adom-lbr import-kicad` and `export-altium` |+| `lod/` | board-use GLBs in four levels of detail, with previews and manifest |++## Sources and license++- Murata: Murata reference sheet GRM1555C1H220JA01-01A, specifications as of Jun. 13, 2026 (https://search.murata.co.jp/Ceramy/image/img/A01X/G101/ENG/GRM1555C1H220JA01-01A.pdf)+- KiCad libraries: [Capacitor_SMD.pretty/C_0402_1005Metric.kicad_mod](https://gitlab.com/kicad/libraries/kicad-footprints/-/blob/master/Capacitor_SMD.pretty/C_0402_1005Metric.kicad_mod), [Capacitor_SMD.3dshapes/C_0402_1005Metric.step](https://gitlab.com/kicad/libraries/kicad-packages3D/-/blob/master/Capacitor_SMD.3dshapes/C_0402_1005Metric.step)+- Murata product data: https://pim.murata.com/en-us/pim/details/?partNum=GRM1555C1H220JA01%23 (public API pimapi.murata.com, queried 2026-10-21)+- Distributor numbers: Mouser, DigiKey and JLCPCB/LCSC through the Adom parts search, 2026-10-21++Original Adom content is CC-BY-4.0. The KiCad footprint and 3D files keep their upstream license (CC-BY-SA 4.0 with the+KiCad library exception) and the PDFs remain the publishers' documents; see [LICENSE](LICENSE).+[provenance.json](provenance.json) records every source and file hash; the scripts that built the checks are in `provenance/tools/`.++This is a catalog record for the part, not a manufacturing approval: check the maker's current datasheet for your design.
altium/GRM1555C1H220JA01D.PcbLibadded
⋯ 1 unchanged line ⋯
altium/GRM1555C1H220JA01D.SchLibadded
⋯ 1 unchanged line ⋯
altium/GRM1555C1H220JA01D.adom-lbr.jsonadded+237
@@ -0,0 +1,237 @@+{+  "schema_version": 2,+  "mpn": "GRM1555C1H220JA01D",+  "manufacturer": "Murata",+  "package": "",+  "value": "",+  "category": "",+  "symbol": {+    "name": "GRM1555C1H220JA01D",+    "pins": [+      {+        "number": "1",+        "name": "",+        "x": 0,+        "y": 100,+        "length": 70,+        "rotation": 270,+        "electrical_type": "passive"+      },+      {+        "number": "2",+        "name": "",+        "x": 0,+        "y": -100,+        "length": 70,+        "rotation": 90,+        "electrical_type": "passive"+      }+    ],+    "body": null,+    "graphics": [+      {+        "kind": "polyline",+        "points": [+          [+            -80.0,+            -30.0+          ],+          [+            80.0,+            -30.0+          ]+        ],+        "width": 20.0+      },+      {+        "kind": "polyline",+        "points": [+          [+            -80.0,+            30.0+          ],+          [+            80.0,+            30.0+          ]+        ],+        "width": 20.0+      }+    ],+    "designator_prefix": "C",+    "footprint": "C_0402_1005Metric_GRM1555C1H220JA01D",+    "parameters": [+      {+        "name": "Value",+        "value": "22pF",+        "visible": true+      },+      {+        "name": "Datasheet",+        "value": "https://search.murata.co.jp/Ceramy/image/img/A01X/G101/ENG/GRM1555C1H220JA01-01A.pdf",+        "visible": false+      },+      {+        "name": "Description",+        "value": "MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)",+        "visible": false+      },+      {+        "name": "MPN",+        "value": "GRM1555C1H220JA01D",+        "visible": false+      },+      {+        "name": "Manufacturer",+        "value": "Murata",+        "visible": false+      },+      {+        "name": "Mouser",+        "value": "81-GRM1555C1H220JA1D",+        "visible": false+      },+      {+        "name": "DigiKey",+        "value": "490-5868-2-ND",+        "visible": false+      },+      {+        "name": "LCSC",+        "value": "C76960",+        "visible": false+      },+      {+        "name": "Adom Wiki",+        "value": "https://wiki.adom.inc/adom/grm1555c1h220ja01d",+        "visible": false+      },+      {+        "name": "ki_keywords",+        "value": "capacitor 0402 GRM1555C1H220JA01D",+        "visible": false+      },+      {+        "name": "Supplier 1",+        "value": "Mouser",+        "visible": false+      },+      {+        "name": "Supplier Part Number 1",+        "value": "81-GRM1555C1H220JA1D",+        "visible": false+      },+      {+        "name": "Supplier 2",+        "value": "Digi-Key",+        "visible": false+      },+      {+        "name": "Supplier Part Number 2",+        "value": "490-5868-2-ND",+        "visible": false+      },+      {+        "name": "Supplier 3",+        "value": "LCSC",+        "visible": false+      },+      {+        "name": "Supplier Part Number 3",+        "value": "C76960",+        "visible": false+      },+      {+        "name": "Manufacturer Part Number",+        "value": "GRM1555C1H220JA01D",+        "visible": false+      }+    ],+    "pin_numbers_hidden": true,+    "pin_names_hidden": true+  },+  "footprint": {+    "name": "C_0402_1005Metric_GRM1555C1H220JA01D",+    "pads": [+      {+        "number": "1",+        "x_mm": -0.48,+        "y_mm": 0.0,+        "w_mm": 0.56,+        "h_mm": 0.62,+        "drill_mm": 0.0,+        "rotation": 0.0,+        "shape": "roundrect"+      },+      {+        "number": "2",+        "x_mm": 0.48,+        "y_mm": 0.0,+        "w_mm": 0.56,+        "h_mm": 0.62,+        "drill_mm": 0.0,+        "rotation": 0.0,+        "shape": "roundrect"+      }+    ],+    "graphics": [+      {+        "kind": "line",+        "layer": {+          "role": "silk"+        },+        "x1": -0.107836,+        "y1": -0.36,+        "x2": 0.107836,+        "y2": -0.36,+        "width": 0.12+      },+      {+        "kind": "line",+        "layer": {+          "role": "silk"+        },+        "x1": -0.107836,+        "y1": 0.36,+        "x2": 0.107836,+        "y2": 0.36,+        "width": 0.12+      },+      {+        "kind": "rect",+        "layer": {+          "role": "courtyard"+        },+        "x1": -0.91,+        "y1": -0.46,+        "x2": 0.91,+        "y2": 0.46,+        "width": 0.05+      },+      {+        "kind": "rect",+        "layer": {+          "role": "fab"+        },+        "x1": -0.5,+        "y1": -0.25,+        "x2": 0.5,+        "y2": 0.25,+        "width": 0.1+      }+    ]+  },+  "connect": [+    {+      "pin": "1",+      "pad": "1"+    },+    {+      "pin": "2",+      "pad": "2"+    }+  ],+  "provenance": {+    "source": "kicad_import"+  }+}\ No newline at end of file
docs/figures/figures.jsonadded+57
@@ -0,0 +1,57 @@+[+ {+  "file": "docs/figures/grm1555c1h220ja01d-ds-p2-title.png",+  "page": 2,+  "box_100dpi": [+   0,+   0,+   1170,+   140+  ],+  "caption": "p.2 header: part number, size, characteristic, capacitance, voltage and the 'as of' date"+ },+ {+  "file": "docs/figures/grm1555c1h220ja01d-ds-p2-dimension-rating.png",+  "page": 2,+  "box_100dpi": [+   0,+   215,+   1170,+   545+  ],+  "caption": "p.2 'Type & Dimension' and 'Rated Value'"+ },+ {+  "file": "docs/figures/grm1555c1h220ja01d-ds-p2-package.png",+  "page": 2,+  "box_100dpi": [+   0,+   545,+   1170,+   700+  ],+  "caption": "p.2 'Package': packaging codes and reel quantities"+ },+ {+  "file": "docs/figures/grm1555c1h220ja01d-ds-p3-specs.png",+  "page": 3,+  "box_100dpi": [+   0,+   40,+   1170,+   452+  ],+  "caption": "p.3 'Specifications and Test Methods' items 1 to 7 (IR, capacitance, Q or DF)"+ },+ {+  "file": "docs/figures/grm1555c1h220ja01d-ds-p27-land.png",+  "page": 27,+  "box_100dpi": [+   140,+   55,+   1000,+   690+  ],+  "caption": "p.27 '2. Land Dimensions', Tables 1 and 2"+ }+]\ No newline at end of file
docs/figures/grm1555c1h220ja01d-ds-p2-dimension-rating.pngadded
⋯ 1 unchanged line ⋯
docs/figures/grm1555c1h220ja01d-ds-p2-package.pngadded
⋯ 1 unchanged line ⋯
docs/figures/grm1555c1h220ja01d-ds-p2-title.pngadded
⋯ 1 unchanged line ⋯
docs/figures/grm1555c1h220ja01d-ds-p27-land.pngadded
⋯ 1 unchanged line ⋯
docs/figures/grm1555c1h220ja01d-ds-p3-specs.pngadded
⋯ 1 unchanged line ⋯
docs/grm1555c1h220ja01d-datasheet.pdfadded
⋯ 1 unchanged line ⋯
docs/grm1555c1h220ja01d-hero-preview.pngadded
⋯ 1 unchanged line ⋯
docs/hero.pngadded
⋯ 1 unchanged line ⋯
docs/models/package-reference-step.pngadded
⋯ 1 unchanged line ⋯
docs/verify/grm1555c1h220ja01d-check.jsonadded+51
@@ -0,0 +1,51 @@+{+ "step": "GRM1555C1H220JA01D.step",+ "bbox_mm": [+  -0.5,+  0.5,+  -0.25,+  0.25,+  0.0,+  0.5+ ],+ "checks": [+  {+   "dim": "L",+   "model_mm": 1.0,+   "datasheet_min": 0.95,+   "datasheet_max": 1.05,+   "pass": true+  },+  {+   "dim": "W",+   "model_mm": 0.5,+   "datasheet_min": 0.45,+   "datasheet_max": 0.55,+   "pass": true+  },+  {+   "dim": "T/H",+   "model_mm": 0.5,+   "datasheet_min": 0.45,+   "datasheet_max": 0.55,+   "pass": true+  },+  {+   "dim": "e (terminal band), top",+   "model_mm": 0.2,+   "datasheet_min": 0.15,+   "datasheet_max": 0.35,+   "pass": true+  },+  {+   "dim": "e (terminal band), bottom",+   "model_mm": 0.2,+   "datasheet_min": 0.15,+   "datasheet_max": 0.35,+   "pass": true+  }+ ],+ "z_up_seated_centred": true,+ "long_axis_x": true,+ "all_pass": true+}\ No newline at end of file
docs/verify/grm1555c1h220ja01d-overlay.pngadded
⋯ 1 unchanged line ⋯
grm1555c1h220ja01d-hero.glbadded
⋯ 1 unchanged line ⋯
grm1555c1h220ja01d-hero.overlay.jsonadded+125
@@ -0,0 +1,125 @@+{+ "spec": "adom-hero 1.4",+ "mpn": "GRM1555C1H220JA01D",+ "kind": "component + footprint reference art",+ "board_use": false,+ "plane_z_mm": -0.02,+ "units": "metre",+ "upAxis": "Z",+ "layers": {+  "pad_outlines": {+   "material": "Footprint pads - teal dashed outlines - 50 percent opacity",+   "rgba": [+    0.0,+    0.902,+    0.863,+    0.5+   ],+   "pads": 2,+   "span_mm": 1.52,+   "dash_mm": 0.12,+   "gap_mm": 0.072,+   "pad_stroke_mm": 0.03+  },+  "silkscreen": {+   "material": "Silkscreen reference lines - 30 percent opacity",+   "rgba": [+    0.92,+    0.96,+    1.0,+    0.3+   ],+   "footprint_items": 2,+   "pin1": null+  },+  "signal_names": {+   "material": "Signal names - 50 percent opacity",+   "rgba": [+    0.92,+    0.96,+    1.0,+    0.5+   ],+   "font": "DejaVu Sans Mono",+   "labels": 2,+   "sides": "top + mirrored underside (single-sided)",+   "omitted": null,+   "fallback_to_pad_number": 2+  }+ },+ "align": {+  "ok": true,+  "centre_offset_mm": 0.0,+  "tolerance_mm": 0.25,+  "orientation_flipped": false,+  "contacts_bbox_mm": [+   -0.5,+   0.5,+   -0.25,+   0.25+  ],+  "pads_bbox_mm": [+   -0.76,+   0.76,+   -0.31,+   0.31+  ],+  "seating_z_mm": -0.0+ },+ "sources": {+  "glb": "package-reference.glb",+  "glb_sha256": "100935c5c0d6f20a6c9bdfb6386f874dc8a4457bf0e4f3ace69f1ab090100773",+  "footprint": "C_0402_1005Metric_GRM1555C1H220JA01D.kicad_mod",+  "footprint_sha256": "d1c8fe6c3f9009d0e3dff657ccb5f1e1e5d579b69b61a04a8a530165a9960e4c",+  "pins": "page.json component.pins"+ },+ "generator": "factory/hero_glb.py",+ "labels": [+  {+   "pad": "1",+   "text": "1",+   "x": -0.86,+   "y": 0.0,+   "align": "right",+   "vertical": false,+   "h": 0.392+  },+  {+   "pad": "2",+   "text": "2",+   "x": 0.86,+   "y": 0.0,+   "align": "left",+   "vertical": false,+   "h": 0.392+  }+ ],+ "pads": [+  {+   "number": "1",+   "shape": "roundrect",+   "center_mm": [+    -0.48,+    0.0+   ],+   "size_mm": [+    0.56,+    0.62+   ],+   "rot": 0.0+  },+  {+   "number": "2",+   "shape": "roundrect",+   "center_mm": [+    0.48,+    0.0+   ],+   "size_mm": [+    0.56,+    0.62+   ],+   "rot": 0.0+  }+ ]+}\ No newline at end of file
land-pattern/README.mdadded+34
@@ -0,0 +1,34 @@+# Land pattern check: GRM1555C1H220JA01D++The footprint on this page is KiCad's standard library footprint `Capacitor_SMD:C_0402_1005Metric`, renamed to+`C_0402_1005Metric_GRM1555C1H220JA01D` so it can sit beside other parts in one library folder. The copper is unchanged.+This page compares those pads with the land pattern recommended by Murata.++![KiCad pads over the maker's land, true scale](land-pattern.png)++Grey is the part body at its datasheet nominal size, teal is the KiCad copper, the dashed amber outline is the maker's+land (middle of its printed range, or its printed nominal), and the amber bands show where the maker allows the inner+and outer pad edges when it prints a range.++## Numbers++| Dimension | KiCad footprint | Maker's range | Result |+|---|---|---|---|+| gap between lands | 0.40 mm | 0.30 to 0.50 mm | inside |+| land length | 0.56 mm | 0.35 to 0.45 mm | outside by +0.11 mm |+| land width | 0.62 mm | 0.40 to 0.60 mm | outside by +0.02 mm |+| overall length (a + 2b, derived) | 1.52 mm | 1.00 to 1.40 mm | outside by +0.12 mm |++Maker's letters: a = gap between lands, b = land length, c = land width.++Source: Murata reference sheet, p.27 '2. Land Dimensions', Table 2 Reflow Soldering Method, GRM 15, 1.0x0.5 (within +/-0.10).++![Murata reference sheet p.27, Land Dimensions](../docs/figures/grm1555c1h220ja01d-ds-p27-land.png)++## Result++The KiCad pads are larger than the maker's recommendation: land length by +0.11 mm, land width by +0.02 mm, overall length (a + 2b, derived) by +0.12 mm. The gap between the pads is inside the range. KiCad's footprint is generated to IPC-7351 nominal density (its own description says so), not to this maker's table. A design that wants the maker's land should shrink the pads to the numbers in the table.++KiCad pad centres are at +/-0.48 mm, pad size 0.56 x 0.62 mm,+rounded rectangle (corner ratio 0.25). The numbers are in [land-check.json](land-check.json); the drawing is made by+`provenance/tools/landcheck.py` from the footprint file and the maker's table.
land-pattern/land-check.jsonadded+53
@@ -0,0 +1,53 @@+{+ "footprint": "C_0402_1005Metric_GRM1555C1H220JA01D.kicad_mod",+ "kicad_library_footprint": "C_0402_1005Metric",+ "kicad": {+  "gap": 0.4,+  "len": 0.56,+  "wid": 0.62,+  "overall": 1.52+ },+ "maker_reference": {+  "gap": 0.4,+  "len": 0.4,+  "wid": 0.5,+  "overall": 1.2+ },+ "maker_source": "Murata reference sheet, p.27 '2. Land Dimensions', Table 2 Reflow Soldering Method, GRM 15, 1.0x0.5 (within +/-0.10)",+ "maker_letters": "a = gap between lands, b = land length, c = land width",+ "rows": [+  {+   "dim": "gap between lands",+   "kicad_mm": 0.4,+   "maker_min": 0.3,+   "maker_max": 0.5,+   "within": true,+   "outside_by_mm": 0+  },+  {+   "dim": "land length",+   "kicad_mm": 0.56,+   "maker_min": 0.35,+   "maker_max": 0.45,+   "within": false,+   "outside_by_mm": 0.11+  },+  {+   "dim": "land width",+   "kicad_mm": 0.62,+   "maker_min": 0.4,+   "maker_max": 0.6,+   "within": false,+   "outside_by_mm": 0.02+  },+  {+   "dim": "overall length (a + 2b, derived)",+   "kicad_mm": 1.52,+   "maker_min": 1.0,+   "maker_max": 1.4,+   "within": false,+   "outside_by_mm": 0.12+  }+ ],+ "all_within": false+}\ No newline at end of file
land-pattern/land-pattern-icon.pngadded
⋯ 1 unchanged line ⋯
land-pattern/land-pattern.pngadded
⋯ 1 unchanged line ⋯
lod/high.glbadded
⋯ 1 unchanged line ⋯
lod/high.pngadded
⋯ 1 unchanged line ⋯
lod/low.glbadded
⋯ 1 unchanged line ⋯
lod/low.pngadded
⋯ 1 unchanged line ⋯
lod/manifest.jsonadded+178
@@ -0,0 +1,178 @@+{+ "schema": "adom/component-lod@1",+ "mpn": "GRM1555C1H220JA01D",+ "upAxis": "Z",+ "units": "metres",+ "status": "candidate (AI-checked, not human-reviewed)",+ "purpose": "clean board-use component models: no footprint pads, outlines, labels or silkscreen; no marking (GRM1555C1H220JA01-01A, all 33 pages searched; p.2)",+ "source": {+  "path": "GRM1555C1H220JA01D.step",+  "sha256": "03e44c4b2b727b8d4b6b1fd598cbd12dd5e614f1dfeefa96a92a07e3a3b312a2"+ },+ "sourceToDisplay": "uniform scale 0.001 (mm to m); no rotation, no translation; origin = footprint origin, seat z = 0",+ "generator": "lod.py (capencoder passives, OCCT via cadquery-ocp)",+ "removedHelpers": [],+ "levels": [+  {+   "level": "high",+   "path": "lod/high.glb",+   "sha256": "0e3c59226f954cfc527d420961a2db88f5a644d0146ee779eaf93a84b64c86a1",+   "sizeBytes": 68412,+   "decodedBufferBytes": 66504,+   "triangles": 1580,+   "primitives": 2,+   "bounds": {+    "min": [+     -0.0005,+     -0.00025,+     0.0+    ],+    "max": [+     0.0005,+     0.00025,+     0.0005+    ]+   },+   "approximation": {+    "method": "OCCT BRepMesh_IncrementalMesh",+    "linearDeflectionMm": 0.0005,+    "angularDeflectionRad": 0.1+   },+   "detailVisibility": {+    "virtualMpn": false,+    "note": "no marking: the datasheet specifies none"+   },+   "review": "Candidate: rendered preview checked by AI (silhouette, terminals, seat z=0); not human-reviewed",+   "preview": {+    "path": "lod/high.png",+    "sha256": "81bd34c0b5d36898cad568fe7ec25ec6881c354cd5678749ecf65277066eb2ed",+    "sizeBytes": 8635,+    "width": 400,+    "height": 300,+    "view": "iso",+    "sourceLevelSha256": "0e3c59226f954cfc527d420961a2db88f5a644d0146ee779eaf93a84b64c86a1"+   }+  },+  {+   "level": "medium",+   "path": "lod/medium.glb",+   "sha256": "b20243cf5204049e8062d1aee8894a95f683f2e17b93106256d4ca5e36d5fcef",+   "sizeBytes": 22040,+   "decodedBufferBytes": 20136,+   "triangles": 476,+   "primitives": 2,+   "bounds": {+    "min": [+     -0.0005,+     -0.00025,+     0.0+    ],+    "max": [+     0.0005,+     0.00025,+     0.0005+    ]+   },+   "approximation": {+    "method": "OCCT BRepMesh_IncrementalMesh",+    "linearDeflectionMm": 0.004,+    "angularDeflectionRad": 0.35+   },+   "detailVisibility": {+    "virtualMpn": false,+    "note": "no marking: the datasheet specifies none"+   },+   "review": "Candidate: rendered preview checked by AI (silhouette, terminals, seat z=0); not human-reviewed",+   "preview": {+    "path": "lod/medium.png",+    "sha256": "e71ddd5e4d23bfb20d68d259e27eb26a6710554657a4c63437f8de96d049350d",+    "sizeBytes": 8478,+    "width": 400,+    "height": 300,+    "view": "iso",+    "sourceLevelSha256": "b20243cf5204049e8062d1aee8894a95f683f2e17b93106256d4ca5e36d5fcef"+   }+  },+  {+   "level": "low",+   "path": "lod/low.glb",+   "sha256": "70542a64b4c81b59c766313f6c02c7d525dc0ff667e4996a782dcef8e249d8f8",+   "sizeBytes": 11952,+   "decodedBufferBytes": 10056,+   "triangles": 236,+   "primitives": 2,+   "bounds": {+    "min": [+     -0.0005,+     -0.00025,+     0.0+    ],+    "max": [+     0.0005,+     0.00025,+     0.0005+    ]+   },+   "approximation": {+    "method": "OCCT BRepMesh_IncrementalMesh",+    "linearDeflectionMm": 0.02,+    "angularDeflectionRad": 0.9+   },+   "detailVisibility": {+    "virtualMpn": false,+    "note": "no marking: the datasheet specifies none"+   },+   "review": "Candidate: rendered preview checked by AI (silhouette, terminals, seat z=0); not human-reviewed",+   "preview": {+    "path": "lod/low.png",+    "sha256": "c46cde4b30d0d030e0ee435556541e215155c825bcdcf5fd2344687cc83c49f5",+    "sizeBytes": 8551,+    "width": 400,+    "height": 300,+    "view": "iso",+    "sourceLevelSha256": "70542a64b4c81b59c766313f6c02c7d525dc0ff667e4996a782dcef8e249d8f8"+   }+  },+  {+   "level": "super-low",+   "path": "lod/super-low.glb",+   "sha256": "c058869375d943c45afb94ab17fdba6445a03d8d56356590b5a844673a53e8b3",+   "sizeBytes": 3828,+   "decodedBufferBytes": 1944,+   "triangles": 36,+   "primitives": 2,+   "bounds": {+    "min": [+     -0.0005,+     -0.00025,+     0.0+    ],+    "max": [+     0.0005,+     0.00025,+     0.0005+    ]+   },+   "approximation": {+    "method": "per-material bounding boxes split at the part centre (terminals, body, overcoat)"+   },+   "detailVisibility": {+    "virtualMpn": false,+    "note": "no marking: the datasheet specifies none"+   },+   "review": "Candidate: rendered preview checked by AI (silhouette, terminals, seat z=0); not human-reviewed",+   "preview": {+    "path": "lod/super-low.png",+    "sha256": "e9c1f448878cdfb09bb08dd62222cb224dab0177841ff7f459af55a1eca73eb3",+    "sizeBytes": 7245,+    "width": 400,+    "height": 300,+    "view": "iso",+    "sourceLevelSha256": "c058869375d943c45afb94ab17fdba6445a03d8d56356590b5a844673a53e8b3"+   }+  }+ ],+ "hints": [+  "All four levels share pose and units; super-low is boxes per material group, chosen for board overviews."+ ]+}\ No newline at end of file
lod/medium.glbadded
⋯ 1 unchanged line ⋯
lod/medium.pngadded
⋯ 1 unchanged line ⋯
lod/super-low.glbadded
⋯ 1 unchanged line ⋯
lod/super-low.pngadded
⋯ 1 unchanged line ⋯
models.jsonadded+146
@@ -0,0 +1,146 @@+{+ "schema": "adom/models@1",+ "part": "GRM1555C1H220JA01D",+ "models": [+  {+   "path": "GRM1555C1H220JA01D.step",+   "format": "step",+   "title": "Package model (STEP)",+   "status": "current",+   "slot": "step",+   "variant": "plain",+   "role": "derived",+   "use": [+    "board-cad"+   ],+   "marking": null,+   "unique": "The board CAD model: KiCad library package geometry (bytes unchanged), checked against the datasheet table, no marking (the part has none)",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "03e44c4b2b727b8d4b6b1fd598cbd12dd5e614f1dfeefa96a92a07e3a3b312a2",+   "git_blob": "a5725e143e2db0a0a1e499bd95c9c9da94a4f82b",+   "bytes": 43502,+   "thumb": "docs/models/package-reference-step.png"+  },+  {+   "path": "package-reference.glb",+   "format": "glb",+   "title": "Package model (GLB)",+   "status": "current",+   "slot": "model_3d_plain",+   "variant": "plain",+   "role": "derived",+   "use": [+    "render",+    "board-insertion"+   ],+   "marking": null,+   "derived_from": "GRM1555C1H220JA01D.step",+   "unique": "The clean model as a GLB (step2glb), no artwork: the download for viewers and assemblies",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "100935c5c0d6f20a6c9bdfb6386f874dc8a4457bf0e4f3ace69f1ab090100773",+   "git_blob": "be1969cc5b4bde9fe0ba1de99674dbb12e76fd76",+   "bytes": 15944+  },+  {+   "path": "grm1555c1h220ja01d-hero.glb",+   "format": "glb",+   "title": "Hero (page viewer)",+   "status": "current",+   "slot": "model_3d",+   "variant": "hero",+   "role": "derived",+   "use": [+    "wiki-hero"+   ],+   "marking": null,+   "derived_from": "package-reference.glb",+   "unique": "The clean model plus nonphysical footprint artwork (adom-hero 1.4): teal dashed pad outlines, silkscreen, pad numbers 1 and 2; not for board use",+   "thumb": "docs/grm1555c1h220ja01d-hero-preview.png",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "111d061a49b3221122a73fca145d49eef61b339df603e76f83905a1ae8da3fba",+   "git_blob": "3b7d71e2a618106f5fb115e80d699d3984f7c564",+   "bytes": 36756+  },+  {+   "path": "lod/high.glb",+   "format": "glb",+   "title": "Board LOD, high",+   "status": "current",+   "variant": "lod",+   "role": "derived",+   "use": [+    "board-insertion",+    "render"+   ],+   "marking": null,+   "derived_from": "GRM1555C1H220JA01D.step",+   "unique": "high detail for board and scaffold viewers: 1580 triangles, 2 primitives",+   "thumb": "lod/high.png",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "0e3c59226f954cfc527d420961a2db88f5a644d0146ee779eaf93a84b64c86a1",+   "git_blob": "e99dae9d779e8d2e1b0be5f96bd34cfec50f88ba",+   "bytes": 68412+  },+  {+   "path": "lod/medium.glb",+   "format": "glb",+   "title": "Board LOD, medium",+   "status": "current",+   "variant": "lod",+   "role": "derived",+   "use": [+    "board-insertion",+    "render"+   ],+   "marking": null,+   "derived_from": "GRM1555C1H220JA01D.step",+   "unique": "medium detail for board and scaffold viewers: 476 triangles, 2 primitives",+   "thumb": "lod/medium.png",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "b20243cf5204049e8062d1aee8894a95f683f2e17b93106256d4ca5e36d5fcef",+   "git_blob": "d96027e1e13723d5017f85abe54cfb81b37f24ef",+   "bytes": 22040+  },+  {+   "path": "lod/low.glb",+   "format": "glb",+   "title": "Board LOD, low",+   "status": "current",+   "variant": "lod",+   "role": "derived",+   "use": [+    "board-insertion",+    "render"+   ],+   "marking": null,+   "derived_from": "GRM1555C1H220JA01D.step",+   "unique": "low detail for board and scaffold viewers: 236 triangles, 2 primitives",+   "thumb": "lod/low.png",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "70542a64b4c81b59c766313f6c02c7d525dc0ff667e4996a782dcef8e249d8f8",+   "git_blob": "0ad9c34198b30706ee720347b4c45660d510a346",+   "bytes": 11952+  },+  {+   "path": "lod/super-low.glb",+   "format": "glb",+   "title": "Board LOD, super-low",+   "status": "current",+   "variant": "lod",+   "role": "derived",+   "use": [+    "board-insertion",+    "render"+   ],+   "marking": null,+   "derived_from": "GRM1555C1H220JA01D.step",+   "unique": "super-low detail for board and scaffold viewers: 36 triangles, 2 primitives",+   "thumb": "lod/super-low.png",+   "source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+   "sha256": "c058869375d943c45afb94ab17fdba6445a03d8d56356590b5a844673a53e8b3",+   "git_blob": "c895cd17d4e1cbb85dbef48a078c2472b006b57c",+   "bytes": 3828+  }+ ],+ "updated": "2026-10-21"+}\ No newline at end of file
package-reference.glbadded
⋯ 1 unchanged line ⋯
package.jsonadded+10
@@ -0,0 +1,10 @@+{+ "name": "grm1555c1h220ja01d",+ "title": "GRM1555C1H220JA01D - Murata",+ "version": "0.1.0",+ "description": "MLCC 22 pF +/-5 %, 50 V, C0G, 0402 (1005 metric)",+ "type": "hardware",+ "kind": "component",+ "license": "CC-BY-4.0",+ "files": []+}\ No newline at end of file
provenance.jsonadded+221
@@ -0,0 +1,221 @@+{+ "manufacturer_reference": "https://pim.murata.com/en-us/pim/details/?partNum=GRM1555C1H220JA01%23",+ "symbol_source": "Original, written for this page (standard capacitor graphic, non-polar). CC-BY-4.0.",+ "footprint_source": "KiCad standard library Capacitor_SMD:C_0402_1005Metric (CC-BY-SA 4.0 with the KiCad library exception); renamed C_0402_1005Metric -> C_0402_1005Metric_GRM1555C1H220JA01D, model path set to ${KIPRJMOD}/GRM1555C1H220JA01D.step; copper unchanged",+ "footprint_upstream_sha256": "0403382fc4583ed510b461b1fa4a36dfaec6f4c0d9b1a67e6b0027837a54e1b5",+ "footprint_upstream_url": "https://gitlab.com/kicad/libraries/kicad-footprints/-/raw/master/Capacitor_SMD.pretty/C_0402_1005Metric.kicad_mod",+ "package_source": "KiCad packages3D Capacitor_SMD.3dshapes/C_0402_1005Metric.step (CC-BY-SA 4.0 with the KiCad library exception)",+ "package_upstream_url": "https://gitlab.com/kicad/libraries/kicad-packages3D/-/raw/master/Capacitor_SMD.3dshapes/C_0402_1005Metric.step",+ "package_bytes_unchanged": true,+ "manufacturer_step": {+  "found": false,+  "searched": "2026-10-21",+  "method": "plain HTTP only (curl), no browser",+  "note": "Murata's public product-data API (pimapi.murata.com/public/api/pim/v1/products/search, queried 2026-10-21 for GRM1555C1H220JA01#) lists the reference sheet, reliability data, S-parameters, SPICE netlist and characteristics data for this part but no STEP or other 3D CAD asset; the product page (pim.murata.com) is a script-built page with no static CAD link, and guessed static paths returned 404. No browser session was used, so KiCad's library model was used and checked against Murata's printed dimensions."+ },+ "datasheet_figures": [+  {+   "file": "docs/figures/grm1555c1h220ja01d-ds-p2-title.png",+   "page": 2,+   "box_100dpi": [+    0,+    0,+    1170,+    140+   ],+   "caption": "p.2 header: part number, size, characteristic, capacitance, voltage and the 'as of' date"+  },+  {+   "file": "docs/figures/grm1555c1h220ja01d-ds-p2-dimension-rating.png",+   "page": 2,+   "box_100dpi": [+    0,+    215,+    1170,+    545+   ],+   "caption": "p.2 'Type & Dimension' and 'Rated Value'"+  },+  {+   "file": "docs/figures/grm1555c1h220ja01d-ds-p2-package.png",+   "page": 2,+   "box_100dpi": [+    0,+    545,+    1170,+    700+   ],+   "caption": "p.2 'Package': packaging codes and reel quantities"+  },+  {+   "file": "docs/figures/grm1555c1h220ja01d-ds-p3-specs.png",+   "page": 3,+   "box_100dpi": [+    0,+    40,+    1170,+    452+   ],+   "caption": "p.3 'Specifications and Test Methods' items 1 to 7 (IR, capacitance, Q or DF)"+  },+  {+   "file": "docs/figures/grm1555c1h220ja01d-ds-p27-land.png",+   "page": 27,+   "box_100dpi": [+    140,+    55,+    1000,+    690+   ],+   "caption": "p.27 '2. Land Dimensions', Tables 1 and 2"+  }+ ],+ "hero_glb": {+  "file": "grm1555c1h220ja01d-hero.glb",+  "sidecar": "grm1555c1h220ja01d-hero.overlay.json",+  "tool": "hero_glb.py (adom/component-hero, adom-hero 1.4), copied into provenance/tools/",+  "inputs": [+   "package-reference.glb",+   "C_0402_1005Metric_GRM1555C1H220JA01D.kicad_mod",+   "component.pins (1 and 2, unnamed)"+  ],+  "result": "pads 2, silk items 2, pin1 none, labels 2; align OK (offset 0.0 mm)"+ },+ "altium": {+  "files": [+   "altium/GRM1555C1H220JA01D.SchLib",+   "altium/GRM1555C1H220JA01D.PcbLib",+   "altium/GRM1555C1H220JA01D.adom-lbr.json"+  ],+  "tool": "adom-lbr import-kicad --sym --fp --mpn, then adom-lbr export-altium"+ },+ "geometry_status": "KiCad library package geometry, every printed dimension checked against the datasheet (docs/verify). Not manufacturer-issued CAD.",+ "frame": {+  "units": "mm (STEP), metres (GLB)",+  "up_axis": "Z",+  "seat_z": 0,+  "origin": "footprint origin",+  "transform": "none"+ },+ "glb": {+  "tool": "step2glb convert",+  "exit": 0,+  "stderr_tail": "Large file queued for async conversion (job 5b98f4b5fba8d201). Polling...\nJob 5b98f4b5fba8d201 complete (4s). Downloading GLB...\n"+ },+ "hero": {+  "tool": "step2glb thumbnail --width 800 --height 600 (iso)",+  "path": "docs/hero.png"+ },+ "fusion_lbr": {+  "file": "GRM1555C1H220JA01D.lbr",+  "tool": "adom-lbr generate --sym --fp --part-metadata page.json",+  "lint": "passed, 0 errors, 0 warnings"+ },+ "datasheet": {+  "file": "docs/grm1555c1h220ja01d-datasheet.pdf",+  "sha256": "25192d46bc6ca4a47fecc3204bb16207213d5329ea3b090f243ab2f20a65fc4d",+  "url": "https://search.murata.co.jp/Ceramy/image/img/A01X/G101/ENG/GRM1555C1H220JA01-01A.pdf",+  "title": "Murata reference sheet GRM1555C1H220JA01-01A, specifications as of Jun. 13, 2026",+  "retrieved": "2026-10-21"+ },+ "supporting_documents": [],+ "datasheet_check": {+  "overlay": "docs/verify/grm1555c1h220ja01d-overlay.png",+  "numbers": "docs/verify/grm1555c1h220ja01d-check.json",+  "tools": "provenance/tools/ (ortho.py, overlay_chip.py, spec json)",+  "result": "PASS"+ },+ "land_pattern_check": {+  "readme": "land-pattern/README.md",+  "numbers": "land-pattern/land-check.json",+  "source": "Murata reference sheet, p.27 '2. Land Dimensions', Table 2 Reflow Soldering Method, GRM 15, 1.0x0.5 (within +/-0.10)",+  "result": "larger than maker"+ },+ "marking": {+  "real_marking": null,+  "statement": "The Murata reference sheet specifies no part marking: none of its 33 pages has a marking section, and the p.2 dimension sketch shows a plain body",+  "source": "GRM1555C1H220JA01-01A, all 33 pages searched; p.2"+ },+ "distributors": {+  "tool": "adom-parts-search search GRM1555C1H220JA01D",+  "date": "2026-10-21",+  "mouser": {+   "part": "81-GRM1555C1H220JA1D",+   "url": "https://www.mouser.com/ProductDetail/Murata-Electronics/GRM1555C1H220JA01D?qs=4k9rjS6ZRl6sPwaL%252BE1uDQ%3D%3D",+   "stock": 336981+  },+  "digikey": {+   "part": "490-5868-2-ND",+   "url": "https://www.digikey.com/en/products/detail/murata-electronics/GRM1555C1H220JA01D/3175187",+   "stock": 334755+  },+  "lcsc": {+   "part": "C76960",+   "url": "https://www.lcsc.com/product-detail/C76960.html",+   "stock": 218107+  }+ },+ "lod": {+  "manifest": "lod/manifest.json",+  "generator": "provenance/tools/lod.py",+  "source_sha256": "03e44c4b2b727b8d4b6b1fd598cbd12dd5e614f1dfeefa96a92a07e3a3b312a2"+ },+ "tools_note": "lod.py, ortho.py and overlay_chip.py come from the GRM155R71C104KA88D component page; build.py, parts.py, landcheck.py, records.py and push.sh are the scripts used for the GRM1555C1H100JA01D and GRM155R71H103KA88D pages, extended here with datasheet figure crops, the adom-hero 1.4 hero and the Altium lane.",+ "files": {+  "grm1555c1h220ja01d-hero.overlay.json": "751922d54cf0a9666fa92fcedb236559df54ec6e2539a53637ea913b8d209515",+  "verification.json": "aaddc84cd4a39b11eea2e1082731ce2ba52279a715ff44dd1bce547e54fb7fe4",+  "GRM1555C1H220JA01D.lbr": "cc5f8e670edb222111e2e9cbcceaff22fb6151853a33c097768012ed1831aa77",+  "package-reference.glb": "100935c5c0d6f20a6c9bdfb6386f874dc8a4457bf0e4f3ace69f1ab090100773",+  "GRM1555C1H220JA01D.step": "03e44c4b2b727b8d4b6b1fd598cbd12dd5e614f1dfeefa96a92a07e3a3b312a2",+  "package.json": "346f92d23b76958d8f0b9b6aa10e63a19edacf11750dd5a210b142939bdd9591",+  "GRM1555C1H220JA01D.kicad_sym": "d1e77b57b159a46907255e23e80f1a4ecc1461f670fc8f3b7101752478ddee0b",+  "C_0402_1005Metric_GRM1555C1H220JA01D.kicad_mod": "d1c8fe6c3f9009d0e3dff657ccb5f1e1e5d579b69b61a04a8a530165a9960e4c",+  "grm1555c1h220ja01d-hero.glb": "111d061a49b3221122a73fca145d49eef61b339df603e76f83905a1ae8da3fba",+  "models.json": "4ec16a13b9c96112a37112d6bf6125ab1abfe5d2caa68bb86c047066e53bb238",+  "LICENSE": "ba709bfbe20a3d6f848456fc1ff3befb391fe4aaf892473967ecc0b4e667f51d",+  "page.json": "d5f7c8272979e9ec932d30a1b61ed2def06a191e7cc333e81e707bb837eeda34",+  "README.md": "00b880481c2202dc4d8573039048e747ce4ec41362d6eb1d58a284e1bae7f8f4",+  "provenance/tools/hero_glb.py": "429e437a3f2e5f1dc3544fe65843ea4e019637f0a6163060cda2ae210f3af7bc",+  "provenance/tools/grm1555c1h220ja01d-overlay-spec.json": "c2b9a74a45cbf39ca06fa32ee868cde404eabcc8297b55d730ba0505e03c7e30",+  "provenance/tools/parts.py": "ffe7f5c9262d136c962c6d8b0bcaeb41d6c5b326c6d47064b8a3d918e6fb0dd5",+  "provenance/tools/hero_glyphs.json": "00627c28f7b197084289f3f9283c41670cec673e3c3ba861bb70e48c76362799",+  "provenance/tools/records.py": "b24d7ac31b72d393545e35090561fca659d350c1e3ed1f66489bd654398bc3da",+  "provenance/tools/landcheck.py": "a6141dcaa4992652e0caf3a7fdd51dcf8451fd630b7de7b873d1b910ae4a1d41",+  "provenance/tools/overlay_chip.py": "52617a63c9504e020e574ec63f39f518734032fcda7b14ad158e3f8907b31723",+  "provenance/tools/ortho.py": "c5a44e74fa447e1ece13190840c90d453cbb004f6c4608efb6e8cdb1ba2cbb6d",+  "provenance/tools/lod.py": "fc3eb9db56947d002d1dda328a6ee53032eae39f700521d00d18477f9915135c",+  "provenance/tools/push.sh": "54cfc61a0954adc41fd629d651840128fb99aa8914975f1ce718091d07cc92d8",+  "provenance/tools/build.py": "a7eaa369936589d0e7de1058c0cefd8776bba31ff219021d94b38e1440737f07",+  "lod/low.png": "c46cde4b30d0d030e0ee435556541e215155c825bcdcf5fd2344687cc83c49f5",+  "lod/super-low.png": "e9c1f448878cdfb09bb08dd62222cb224dab0177841ff7f459af55a1eca73eb3",+  "lod/low.glb": "70542a64b4c81b59c766313f6c02c7d525dc0ff667e4996a782dcef8e249d8f8",+  "lod/high.png": "81bd34c0b5d36898cad568fe7ec25ec6881c354cd5678749ecf65277066eb2ed",+  "lod/manifest.json": "6803270b49b897f7eba9cd13c9d2d94da80b7c237bc86208544263bd5cf3f5b3",+  "lod/super-low.glb": "c058869375d943c45afb94ab17fdba6445a03d8d56356590b5a844673a53e8b3",+  "lod/medium.glb": "b20243cf5204049e8062d1aee8894a95f683f2e17b93106256d4ca5e36d5fcef",+  "lod/high.glb": "0e3c59226f954cfc527d420961a2db88f5a644d0146ee779eaf93a84b64c86a1",+  "lod/medium.png": "e71ddd5e4d23bfb20d68d259e27eb26a6710554657a4c63437f8de96d049350d",+  "docs/grm1555c1h220ja01d-datasheet.pdf": "25192d46bc6ca4a47fecc3204bb16207213d5329ea3b090f243ab2f20a65fc4d",+  "docs/grm1555c1h220ja01d-hero-preview.png": "9442955641bf3afcc432f352f0208d00d48f1d6c0d1947eaae1ed99efb644033",+  "docs/hero.png": "34a02e001910c6a31ed4200be9d459c17d0415447226703b3ce431e9bb86e6ef",+  "docs/models/package-reference-step.png": "a526b37a89a21d5bb34c5d9022e6690dfcf5c130a02bfbfd27fa926247c92369",+  "docs/verify/grm1555c1h220ja01d-overlay.png": "862788a5aea06937558f796f495f780d6fb102e39aae7a2fd13a9c8e7ab02625",+  "docs/verify/grm1555c1h220ja01d-check.json": "9f6c439ef01e62314a89a66c34feea056d1bca924067edadad4be7e8ffc2c6dc",+  "docs/figures/grm1555c1h220ja01d-ds-p2-title.png": "a561353c8bc74aefe64443459f1e6f418f92fe86f0e9e462c0cd136424a5d6dd",+  "docs/figures/grm1555c1h220ja01d-ds-p2-dimension-rating.png": "8d022497ff2ffba01326398ea882e3071a3f5a615fe1a96da3b65bde9e00ac68",+  "docs/figures/grm1555c1h220ja01d-ds-p3-specs.png": "c0f5e79b02fa029216ce88e36bf241483a4870576c18613b953b1922f16eb47c",+  "docs/figures/grm1555c1h220ja01d-ds-p2-package.png": "f9678a713e85d6e586f1ffc5a3a3e36b333ef952b47353e10cf1ed6a9940bf3b",+  "docs/figures/figures.json": "b4e47578f6bf7ed1c964b9d6dd199afb0e91cf32299071ef0c6aac27dd349fc5",+  "docs/figures/grm1555c1h220ja01d-ds-p27-land.png": "ba5d5b957d104a2a8ec3989aeabf97bcccae39a812047823adb025400e25b95d",+  "land-pattern/land-check.json": "0fbcb372b68f3158f5bbd1307faca84b31dd44dc904e47a4060fd92dfd4bb1d9",+  "land-pattern/land-pattern-icon.png": "52f4491d18e1a10a65cb50ef1a08bbd0391c6d9bdb930cbd2b68f9b066921eb0",+  "land-pattern/land-pattern.png": "6e9e0acb1be94782d2c6e3e61c46569dabeb4f5c1057cc6d5398f1b23beee726",+  "land-pattern/README.md": "78e9a234971ee319a5a87e5def7ab89bb6d38906e7d0607c1f012b04555b5744",+  "altium/GRM1555C1H220JA01D.SchLib": "797ff9839a08d371ac838d7e6e025985a8e3872f433dd8aca8170d8b194fabbf",+  "altium/GRM1555C1H220JA01D.PcbLib": "f10519cd74a37b348dd21df3009b0dc5600fee5b8871576df314ed5ea64b984d",+  "altium/GRM1555C1H220JA01D.adom-lbr.json": "d2ea60297c682ffd0584998001f7190b61c2a7fb99695954a65ac8397874f69b"+ },+ "files_note": "provenance.json itself is not listed.",+ "built_by": "Claude (AI agent) for John Lauer",+ "date": "2026-10-21"+}\ No newline at end of file
provenance/tools/build.pyadded+178
@@ -0,0 +1,178 @@+"""Build one component page tree per part in parts.PARTS.++usage: build.py <slug> [--skip-remote]+Writes /tmp/claude-1001/mlcc5/pages/<slug>/ . Downloads are read from+/tmp/claude-1001/mlcc5/dl (never executed); scripts live in this folder.+"""+import sys, os, json, shutil, subprocess, hashlib, re+import numpy as np+from PIL import Image, ImageDraw, ImageFont++ROOT = "/tmp/claude-1001/mlcc5"+TOOLS = os.path.join(ROOT, "tools")+DL = os.path.join(ROOT, "dl")+PY = "/home/adom/.venvs/cq/bin/python"+sys.path.insert(0, TOOLS)+from parts import PARTS, TODAY++slug = sys.argv[1]+P = next(p for p in PARTS if p["slug"] == slug)+OUT = os.path.join(ROOT, "pages", slug)+os.makedirs(OUT, exist_ok=True)+MPN = P["mpn"]+sha = lambda f: hashlib.sha256(open(f, "rb").read()).hexdigest()+def gitblob(f):+    b = open(f, "rb").read()+    return hashlib.sha1(b"blob %d\0" % len(b) + b).hexdigest()+def run(cmd, **kw):+    r = subprocess.run(cmd, capture_output=True, text=True, **kw)+    if r.returncode != 0:+        print("FAILED", cmd, r.stdout[-2000:], r.stderr[-2000:]); sys.exit(1)+    return r+F = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"+FB = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"++for d in ("docs/verify", "docs/models", "lod", "provenance/tools", "land-pattern", "docs/figures"):+    os.makedirs(os.path.join(OUT, d), exist_ok=True)++# ---------- STEP (KiCad library bytes, unchanged) ----------+src_step = os.path.join(DL, "kicad", P["fp"] + ".step")+step_name = f"{MPN}.step"+step_path = os.path.join(OUT, step_name)+shutil.copyfile(src_step, step_path)+assert sha(step_path) == sha(src_step)++# ---------- footprint (KiCad library geometry, renamed + local model path) ----------+fp_name = f"{P['fp']}_{MPN}"+src_fp = open(os.path.join(DL, "kicad", P["fp"] + ".kicad_mod")).read()+fp = src_fp.replace(f'(footprint "{P["fp"]}"', f'(footprint "{fp_name}"', 1)+fp = re.sub(r'\(model "[^"]+"', f'(model "${{KIPRJMOD}}/{step_name}"', fp)+assert fp.count(fp_name) == 1 and "${KIPRJMOD}/" + step_name in fp+fp_file = f"{fp_name}.kicad_mod"+open(os.path.join(OUT, fp_file), "w").write(fp)+pads = [(float(a), float(b), float(c), float(d)) for a, b, c, d in+        re.findall(r'\(pad "\d" smd roundrect\s*\(at ([-\d.]+) ([-\d.]+)\)\s*\(size ([\d.]+) ([\d.]+)\)', fp)]+assert len(pads) == 2, pads++# ---------- symbol (original, conventional passive graphics) ----------+d = P["dist"]+def prop(name, val, y, hide=True):+    h = " hide" if hide else ""+    return f'    (property "{name}" "{val}" (at 0 {y} 0) (effects (font (size 1.27 1.27)){h}))\n'+ref = P["kind"]+desc = P["brief"]+props = (prop("Reference", ref, 0 if False else 0, False).replace("(at 0 0 0)", "(at 2.54 1.27 0)").replace("(font (size 1.27 1.27))", "(font (size 1.27 1.27)) (justify left)")+         + prop("Value", P["value_sym"], 0, False).replace("(at 0 0 0)", "(at 2.54 -1.27 0)").replace("(font (size 1.27 1.27))", "(font (size 1.27 1.27)) (justify left)")+         + prop("Footprint", fp_name, -7.62) + prop("Datasheet", P["ds"]["url"], -10.16) + prop("Description", desc, -12.7)+         + prop("MPN", MPN, -15.24) + prop("Manufacturer", P["mfr"], -17.78)+         + prop("Mouser", d["mouser"][0], -20.32) + prop("DigiKey", d["digikey"][0], -22.86) + prop("LCSC", d["lcsc"][0], -25.4) + prop("Adom Wiki", f"https://wiki.adom.inc/adom/{slug}", -27.94))+if ref == "C":+    body = ('      (polyline (pts (xy -2.032 -0.762) (xy 2.032 -0.762)) (stroke (width 0.508) (type default)) (fill (type none)))\n'+            '      (polyline (pts (xy -2.032 0.762) (xy 2.032 0.762)) (stroke (width 0.508) (type default)) (fill (type none)))\n')+    plen = 1.778  # pin ends on the 2.54 mm grid (0, +/-2.54); plates at +/-0.762+else:+    body = '      (rectangle (start -1.016 -2.54) (end 1.016 2.54) (stroke (width 0.254) (type default)) (fill (type none)))\n'+    plen = 1.27+sym = f'''(kicad_symbol_lib (version 20241209) (generator "adom_passive_symbol")+  (symbol "{MPN}" (pin_numbers (hide yes)) (pin_names (offset 0.254) (hide yes)) (exclude_from_sim no) (in_bom yes) (on_board yes)+{props}    (property "ki_keywords" "{P['category'].lower()} {P['package'].split()[0]} {MPN}" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))+    (symbol "{MPN}_0_1"+{body}    )+    (symbol "{MPN}_1_1"+      (pin passive line (at 0 2.54 270) (length {plen}) (name "~" (effects (font (size 1.27 1.27)))) (number "1" (effects (font (size 1.27 1.27)))))+      (pin passive line (at 0 -2.54 90) (length {plen}) (name "~" (effects (font (size 1.27 1.27)))) (number "2" (effects (font (size 1.27 1.27)))))+    )+  )+)+'''+sym_file = f"{MPN}.kicad_sym"+open(os.path.join(OUT, sym_file), "w").write(sym)++# ---------- datasheets ----------+shutil.copyfile(os.path.join(DL, P["ds"]["local"]), os.path.join(OUT, P["ds"]["file"]))+for x in P["extra_docs"]:+    shutil.copyfile(os.path.join(DL, x["local"]), os.path.join(OUT, x["file"]))++# ---------- tools copied into provenance ----------+for t in ("lod.py", "ortho.py", "overlay_chip.py", "build.py", "parts.py", "landcheck.py", "records.py", "hero_glb.py", "hero_glyphs.json", "push.sh"):+    if os.path.exists(os.path.join(TOOLS, t)):+        shutil.copyfile(os.path.join(TOOLS, t), os.path.join(OUT, "provenance/tools", t))++# ---------- overlay proof against the datasheet table ----------+ov = dict(P["overlay"])+crop_png, box = ov.pop("crop")+spec = {"label": MPN, "mpn": MPN, **ov, "crops": [[os.path.join(ROOT, "work/crops", crop_png), box]],+        "marking": "none specified (" + P["marking_src"] + ")"}+spec_path = os.path.join(OUT, f"provenance/tools/{slug}-overlay-spec.json")+spec_pub = dict(spec); spec_pub["crops"] = [[f"datasheet page render ({crop_png}, 100 dpi)", box]]+json.dump(spec_pub, open(spec_path, "w"), indent=1)+tmp_spec = os.path.join(ROOT, "work", f"{slug}-spec.json"); json.dump(spec, open(tmp_spec, "w"))+r = run([PY, "-I", os.path.join(TOOLS, "overlay_chip.py"), tmp_spec, step_path, os.path.join(OUT, f"docs/verify/{slug}-overlay.png")], cwd=TOOLS)+check = json.loads(r.stdout.strip().splitlines()[-1]); check["step"] = step_name+json.dump(check, open(os.path.join(OUT, f"docs/verify/{slug}-check.json"), "w"), indent=1)+print("overlay all_pass:", check["all_pass"])+if not check["all_pass"]:+    print(json.dumps(check, indent=1)); sys.exit(2)++# ---------- land pattern comparison (KiCad pads vs maker's recommendation) ----------+r = run([PY, "-I", os.path.join(TOOLS, "landcheck.py"), slug, os.path.join(OUT, "land-pattern")], cwd=TOOLS)+land = json.loads(r.stdout.strip().splitlines()[-1])+json.dump(land, open(os.path.join(OUT, "land-pattern/land-check.json"), "w"), indent=1)++# ---------- GLB (step2glb) ----------+glb_path = os.path.join(OUT, "package-reference.glb")+g = subprocess.run(["step2glb", "convert", step_path, "-o", glb_path], capture_output=True, text=True)+print("step2glb exit", g.returncode, g.stderr[-300:])+assert g.returncode == 0 and os.path.getsize(glb_path) > 1000++# ---------- thumbnails (service render of the STEP) ----------+def thumb(out, wh=None):+    extra = ["--width", str(wh[0]), "--height", str(wh[1])] if wh else []+    t = subprocess.run(["step2glb", "thumbnail", step_path, "-o", out] + extra, capture_output=True, text=True)+    return t.returncode, (t.stdout + t.stderr)[-300:]+hero_rc = thumb(os.path.join(OUT, "docs/hero.png"), (800, 600))+th_rc = thumb(os.path.join(OUT, "docs/models/package-reference-step.png"))+print("thumbs", hero_rc, th_rc)++# ---------- cited datasheet figures (100 dpi page renders, cropped) ----------+stem = MPN[:-1]+pdf = os.path.join(DL, P["ds"]["local"])+FIG = []+def fig(page, box, name, caption):+    tmp = os.path.join(ROOT, "work", f"{slug}-p{page}")+    run(["pdftoppm", "-r", "150", "-f", str(page), "-l", str(page), "-png", "-singlefile", pdf, tmp])+    im = Image.open(tmp + ".png").convert("RGB")+    s_ = 1.5  # boxes are given at 100 dpi+    im.crop(tuple(int(v * s_) for v in box)).save(os.path.join(OUT, "docs/figures", name), optimize=True)+    FIG.append({"file": f"docs/figures/{name}", "page": page, "box_100dpi": box, "caption": caption})+fig(2, [0, 0, 1170, 140], f"{slug}-ds-p2-title.png", "p.2 header: part number, size, characteristic, capacitance, voltage and the 'as of' date")+fig(2, [0, 215, 1170, 545], f"{slug}-ds-p2-dimension-rating.png", "p.2 'Type & Dimension' and 'Rated Value'")+fig(2, [0, 545, 1170, 700], f"{slug}-ds-p2-package.png", "p.2 'Package': packaging codes and reel quantities")+fig(3, [0, 40, 1170, 452], f"{slug}-ds-p3-specs.png", "p.3 'Specifications and Test Methods' items 1 to 7 (IR, capacitance, Q or DF)")+fig(27, [140, 55, 1000, 690], f"{slug}-ds-p27-land.png", "p.27 '2. Land Dimensions', Tables 1 and 2")+json.dump(FIG, open(os.path.join(OUT, "docs/figures/figures.json"), "w"), indent=1)++# ---------- hero GLB (adom-hero 1.4 generator from adom/component-hero) ----------+pins_doc = os.path.join(ROOT, "work", f"{slug}-hero-pins.json")+json.dump({"slug": slug, "component": {"mpn": MPN, "pins": [{"number": "1", "name": "~"}, {"number": "2", "name": "~"}]}}, open(pins_doc, "w"))+hero_glb = os.path.join(OUT, f"{slug}-hero.glb")+r = run([PY, "-I", os.path.join(TOOLS, "hero_glb.py"), glb_path, os.path.join(OUT, fp_file), pins_doc, hero_glb,+         "--png", os.path.join(OUT, f"docs/{slug}-hero-preview.png")], cwd=TOOLS)+hero_line = r.stdout.strip().splitlines()[-1]+print("hero:", hero_line)+assert "align OK" in hero_line, hero_line++# ---------- LODs ----------+run([PY, "-I", os.path.join(TOOLS, "lod.py"), step_path, MPN, OUT, step_name], cwd=TOOLS)+man = json.load(open(os.path.join(OUT, "lod/manifest.json")))+man["source"]["path"] = step_name+man["purpose"] = "clean board-use component models: no footprint pads, outlines, labels or silkscreen; no marking (" + P["marking_src"] + ")"+for lv in man["levels"]:+    lv["detailVisibility"]["note"] = "no marking: the datasheet specifies none"+json.dump(man, open(os.path.join(OUT, "lod/manifest.json"), "w"), indent=1)++json.dump({"step": step_name, "fp": fp_file, "sym": sym_file, "check": check, "land": land,+           "hero_rc": hero_rc, "thumb_rc": th_rc, "glb_stderr": g.stderr[-300:],+           "figures": FIG, "hero_glb": f"{slug}-hero.glb", "hero_line": hero_line},+          open(os.path.join(ROOT, "work", f"{slug}-build.json"), "w"), indent=1)+print("built", OUT)
provenance/tools/grm1555c1h220ja01d-overlay-spec.jsonadded+39
@@ -0,0 +1,39 @@+{+ "label": "GRM1555C1H220JA01D",+ "mpn": "GRM1555C1H220JA01D",+ "L": [+  1.0,+  0.05+ ],+ "W": [+  0.5,+  0.05+ ],+ "T": [+  0.5,+  0.05+ ],+ "band_top": [+  0.15,+  0.35+ ],+ "band_bot": [+  0.15,+  0.35+ ],+ "band_top_name": "e (terminal band), top",+ "band_bot_name": "e (terminal band), bottom",+ "source": "Murata GRM1555C1H220JA01-01A reference sheet p.2 'Type & Dimension' (1005M/0402)",+ "crops": [+  [+   "datasheet page render (GRM1555C1H220JA01-02.png, 100 dpi)",+   [+    60,+    225,+    760,+    540+   ]+  ]+ ],+ "marking": "none specified (GRM1555C1H220JA01-01A, all 33 pages searched; p.2)"+}\ No newline at end of file
provenance/tools/hero_glb.pyadded+643
@@ -0,0 +1,643 @@+#!/usr/bin/env python3+"""Build a component page's annotated hero GLB: the physical chip plus Adom's nonphysical reference artwork.++The convention (unified 2026-09-30 from the 45 hand-built "style A" heroes on the wiki, the wiki-component+skill's table and John's request) is fixed here so nobody's AI has to reconstruct it from prose:++  root 1   the physical model, untouched (our etched GLB: manufacturer/KiCad body + Adom.LaserEtch.MPN)+  root 2   "Adom reference artwork (nonphysical)", three flat meshes at z = -0.02 mm (below the seating+           plane, so they never z-fight the chip underside), all KHR_materials_unlit, BLEND, double-sided:+    "Footprint pads - teal dashed outlines - 50 percent opacity"  copper perimeter of every pad, dashed+                                                                  rgb(0, .902, .863)  alpha 0.50+    "Silkscreen reference lines - 30 percent opacity"             F.SilkS strokes/fills + a pin-1 dot+                                                                  rgb(.92, .96, 1)    alpha 0.30+    "Signal names - 50 percent opacity"                           pad signal names outside the pads+                                                                  rgb(.92, .96, 1)    alpha 0.50+  asset.extras.adomHero = {spec, mpn, board_use: false, layers, sources...}++The hero is presentation only (board_use false). Board-use downloads stay clean: the page declares the hero as+component.parts.model_3d and the clean model as model_3d_plain.++Coordinates: glTF x = KiCad x, y = -KiCad y, Z up, metres (KiCad footprint origin = model origin; checked+per part against the chip's lowest geometry, see align_check).++Usage: hero_glb.py <etched.glb> <footprint.kicad_mod> <page.json> <out-hero.glb> [--mpn MPN] [--png preview.png]+"""+import argparse, hashlib, json, math, os, re, struct, sys+import numpy as np+from pygltflib import GLTF2, Accessor, BufferView, Material, Mesh, Node, Primitive, Attributes, PbrMetallicRoughness++SPEC = 'adom-hero 1.4'+Z = -0.02                                   # mm, artwork plane+PAD_MAT = ('Footprint pads - teal dashed outlines - 50 percent opacity', [0.0, 0.902, 0.863, 0.5])+SILK_MAT = ('Silkscreen reference lines - 30 percent opacity', [0.92, 0.96, 1.0, 0.3])+NAME_MAT = ('Signal names - 50 percent opacity', [0.92, 0.96, 1.0, 0.5])+ROOT = 'Adom reference artwork (nonphysical)'+POLAR_PAD = re.compile(r'^(K|KA|CATHODE|\+|POS|PLUS)$', re.I)+++# ---------------------------------------------------------------- KiCad footprint parsing (s-expressions)+def sexp(text):+    toks = re.findall(r'\(|\)|"(?:\\.|[^"\\])*"|[^\s()]+', text)+    stack = [[]]+    for t in toks:+        if t == '(': stack.append([])+        elif t == ')':+            x = stack.pop(); stack[-1].append(x)+        else: stack[-1].append(t[1:-1].replace('\\"', '"') if t.startswith('"') else t)+    return stack[0][0]+++def child(node, key):+    return next((c for c in node if isinstance(c, list) and c and c[0] == key), None)+++def children(node, key):+    return [c for c in node if isinstance(c, list) and c and c[0] == key]+++def num(v): return float(v)+++def xy(node): return (num(node[1]), num(node[2]))+++def stroke_w(node, default=0.12):+    s = child(node, 'stroke')+    if s and child(s, 'width'): return num(child(s, 'width')[1])+    if child(node, 'width'): return num(child(node, 'width')[1])+    return default+++def on_layer(node, layer):+    ly = child(node, 'layer') or child(node, 'layers')+    return bool(ly) and any(l == layer or (l.startswith('*.') and layer.endswith(l[1:])) for l in ly[1:])+++def parse_footprint(path):+    fp = sexp(open(path).read())+    pads, silk = [], []+    for p in children(fp, 'pad'):+        number, kind, shape = p[1], p[2], p[3]+        if kind == 'np_thru_hole': continue+        ly = child(p, 'layers')+        if not ly or not any(l in ('F.Cu', '*.Cu') for l in ly[1:]): continue+        at = child(p, 'at'); size = child(p, 'size')+        rr = child(p, 'roundrect_rratio')+        prims = []+        if shape == 'custom' and child(p, 'primitives'):+            for gp in children(child(p, 'primitives'), 'gr_poly'):+                pts = child(gp, 'pts')+                if pts: prims.append([xy(q) for q in children(pts, 'xy')])+        pads.append(dict(number=number, kind=kind, shape=shape, x=num(at[1]), y=num(at[2]),+                         rot=num(at[3]) if len(at) > 3 else 0.0, w=num(size[1]), h=num(size[2]),+                         rratio=num(rr[1]) if rr else 0.25, prims=prims))+    for g in fp:+        if not (isinstance(g, list) and g and g[0] in ('fp_line', 'fp_arc', 'fp_circle', 'fp_rect', 'fp_poly')): continue+        if not on_layer(g, 'F.SilkS'): continue+        w = stroke_w(g); fill = child(g, 'fill'); filled = bool(fill) and fill[1] in ('solid', 'yes')+        if g[0] == 'fp_line': silk.append(('path', [xy(child(g, 'start')), xy(child(g, 'end'))], w))+        elif g[0] == 'fp_rect':+            (x1, y1), (x2, y2) = xy(child(g, 'start')), xy(child(g, 'end'))+            poly = [(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)]+            silk.append(('fill' if filled else 'path', poly, w))+        elif g[0] == 'fp_circle':+            (cx, cy), (ex, ey) = xy(child(g, 'center')), xy(child(g, 'end'))+            r = math.hypot(ex - cx, ey - cy)+            poly = [(cx + r * math.cos(t), cy + r * math.sin(t)) for t in np.linspace(0, 2 * math.pi, arc_n(r, 360) + 1)]+            silk.append(('fill' if filled else 'path', poly, w))+        elif g[0] == 'fp_arc':+            if child(g, 'mid'):+                a, m, b = xy(child(g, 'start')), xy(child(g, 'mid')), xy(child(g, 'end'))+                silk.append(('path', arc3(a, m, b), w))+            else:   # KiCad 5: (start centre) (end point) (angle deg)+                c, s = xy(child(g, 'start')), xy(child(g, 'end')); ang = num(child(g, 'angle')[1])+                r = math.hypot(s[0] - c[0], s[1] - c[1]); t0 = math.atan2(s[1] - c[1], s[0] - c[0])+                silk.append(('path', [(c[0] + r * math.cos(t0 + math.radians(ang) * k / 24), c[1] + r * math.sin(t0 + math.radians(ang) * k / 24)) for k in range(25)], w))+        elif g[0] == 'fp_poly':+            pts = [xy(q) for q in children(child(g, 'pts'), 'xy')]+            silk.append(('fill' if (filled or not fill) else 'path', pts + [pts[0]], w))+    model = child(fp, 'model')+    mdl = None+    if model:+        mdl = dict(offset=[num(v) for v in child(child(model, 'offset'), 'xyz')[1:]] if child(model, 'offset') else [0, 0, 0],+                   rotate=[num(v) for v in child(child(model, 'rotate'), 'xyz')[1:]] if child(model, 'rotate') else [0, 0, 0])+    return pads, silk, mdl+++def arc3(a, m, b, n=None):+    ax, ay = a; bx, by = m; cx, cy = b+    d = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by))+    if abs(d) < 1e-12: return [a, b]+    ux = ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d+    uy = ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d+    r = math.hypot(ax - ux, ay - uy)+    t0, tm, t1 = (math.atan2(p[1] - uy, p[0] - ux) for p in (a, m, b))+    def norm(t): return (t - t0) % (2 * math.pi)+    sweep = norm(t1) if norm(tm) < norm(t1) else norm(t1) - 2 * math.pi+    n = n or arc_n(r, math.degrees(sweep))+    return [(ux + r * math.cos(t0 + sweep * k / n), uy + r * math.sin(t0 + sweep * k / n)) for k in range(n + 1)]+++# ---------------------------------------------------------------- geometry+def arc_n(r, sweep_deg, chord=0.005):+    """Segments for an arc so no straight piece is longer than `chord` mm (smooth at any zoom)."""+    return int(min(max(math.ceil(abs(math.radians(sweep_deg)) * r / chord), 8), 240))+++def pad_outline(p):+    """Closed polyline of the copper perimeter in footprint coordinates."""+    w, h = p['w'], p['h']+    if p['shape'] == 'circle':+        n = arc_n(w / 2, 360); loc = [(w / 2 * math.cos(t), w / 2 * math.sin(t)) for t in np.linspace(0, 2 * math.pi, n + 1)]+    elif p['shape'] == 'oval':+        r = min(w, h) / 2; L = (max(w, h) - 2 * r) / 2; loc = []+        for cx, a0 in ((L, -90), (-L, 90)):+            n = arc_n(r, 180); loc += [(cx + r * math.cos(math.radians(a0 + k * 180 / n)), r * math.sin(math.radians(a0 + k * 180 / n))) for k in range(n + 1)]+        if h > w: loc = [(y, x) for x, y in loc]+        loc.append(loc[0])+    elif p['shape'] in ('roundrect', 'rect', 'trapezoid', 'custom'):+        r = p['rratio'] * min(w, h) if p['shape'] == 'roundrect' else 0.0+        if p['shape'] == 'custom' and p['prims']:+            loc = p['prims'][0] + [p['prims'][0][0]]+        elif r <= 1e-6:+            loc = [(-w / 2, -h / 2), (w / 2, -h / 2), (w / 2, h / 2), (-w / 2, h / 2), (-w / 2, -h / 2)]+        else:+            loc = []+            for cx, cy, a0 in ((w / 2 - r, -h / 2 + r, -90), (w / 2 - r, h / 2 - r, 0), (-w / 2 + r, h / 2 - r, 90), (-w / 2 + r, -h / 2 + r, 180)):+                n = arc_n(r, 90); loc += [(cx + r * math.cos(math.radians(a0 + k * 90 / n)), cy + r * math.sin(math.radians(a0 + k * 90 / n))) for k in range(n + 1)]+            loc.append(loc[0])+    else:+        loc = [(-w / 2, -h / 2), (w / 2, -h / 2), (w / 2, h / 2), (-w / 2, h / 2), (-w / 2, -h / 2)]+    # KiCad pad rotation is counter-clockwise on screen, where y points down: rotate by -angle in math axes+    t = math.radians(-p['rot']); c, s = math.cos(t), math.sin(t)+    return [(p['x'] + x * c - y * s, p['y'] + x * s + y * c) for x, y in loc]+++def stroke_quads(poly, width):+    """One continuous ribbon along a polyline: offset both sides with mitred joins, so bends have no gaps+    and no overlapping triangles (overlaps double the alpha and show as bright seams)."""+    pts = [poly[0]] + [q for a, q in zip(poly, poly[1:]) if math.hypot(q[0] - a[0], q[1] - a[1]) > 1e-9]+    if len(pts) < 2: return []+    closed = len(pts) > 2 and math.hypot(pts[0][0] - pts[-1][0], pts[0][1] - pts[-1][1]) < 1e-9+    if closed: pts = pts[:-1]+    n = len(pts); hw = width / 2+    def seg_normal(i, j):+        dx, dy = pts[j][0] - pts[i][0], pts[j][1] - pts[i][1]; L = math.hypot(dx, dy)+        return (-dy / L, dx / L)+    left, right = [], []+    for i in range(n):+        prv = (i - 1) % n if (closed or i > 0) else None+        nxt = (i + 1) % n if (closed or i < n - 1) else None+        if prv is None: nx, ny = seg_normal(i, nxt)+        elif nxt is None: nx, ny = seg_normal(prv, i)+        else:+            a, b = seg_normal(prv, i), seg_normal(i, nxt)+            mx, my = a[0] + b[0], a[1] + b[1]; ml = math.hypot(mx, my)+            if ml < 1e-6: nx, ny = b+            else:+                mx, my = mx / ml, my / ml; cosh = max(mx * b[0] + my * b[1], 0.25)   # mitre limit 4x+                nx, ny = mx / cosh, my / cosh+        left.append((pts[i][0] + nx * hw, pts[i][1] + ny * hw)); right.append((pts[i][0] - nx * hw, pts[i][1] - ny * hw))+    idx = list(range(n)) + ([0] if closed else [])+    tris = []+    for i, j in zip(idx, idx[1:]):+        tris += [(left[i], left[j], right[j]), (left[i], right[j], right[i])]+    return tris+++def dashes(poly, dash, gap):+    """Split a closed polyline into dash pieces (each a short polyline, corners kept)."""+    segs = list(zip(poly, poly[1:])); out = []; cur = []; on = True; left = dash+    for (x1, y1), (x2, y2) in segs:+        L = math.hypot(x2 - x1, y2 - y1); pos = 0.0+        if L < 1e-12: continue+        while pos < L - 1e-12:+            step = min(left, L - pos); t0, t1 = pos / L, (pos + step) / L+            p0 = (x1 + (x2 - x1) * t0, y1 + (y2 - y1) * t0); p1 = (x1 + (x2 - x1) * t1, y1 + (y2 - y1) * t1)+            if on:+                if not cur: cur = [p0]+                cur.append(p1)+            pos += step; left -= step+            if left <= 1e-12:+                if on and len(cur) > 1: out.append(cur)+                cur = []; on = not on; left = dash if on else gap+    if on and len(cur) > 1: out.append(cur)+    return out+++def fill_tris(rings):+    """Triangulate a polygon (outer ring + holes) with earcut."""+    import mapbox_earcut as earcut+    verts = np.array([p for r in rings for p in r], dtype=np.float64).reshape(-1, 2)+    ends = np.cumsum([len(r) for r in rings]).astype(np.uint32)+    idx = earcut.triangulate_float64(verts, ends)+    return [tuple(map(tuple, verts[idx[k:k + 3]])) for k in range(0, len(idx), 3)]+++# ---------------------------------------------------------------- text (DejaVu Sans Mono, pre-triangulated glyph table)+_GLYPHS = None+++def glyphs():+    """DejaVu Sans Mono, pre-triangulated at font size 1 (hero_glyphs.json, shared with the Rust port), so text+    needs no font library at run time and both implementations draw identical glyphs."""+    global _GLYPHS+    if _GLYPHS is None:+        _GLYPHS = json.load(open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'hero_glyphs.json')))+    return _GLYPHS+++def text_tris(txt, height, x, y, align='left', vertical=False):+    """Filled text triangles, baseline-centred on (x, y) in footprint coordinates (y down). Overbars for ~{..}."""+    G = glyphs(); table = G['glyphs']+    plain, bars = '', []+    for m in re.finditer(r'~\{([^}]*)\}|([^~]+|~)', txt):+        if m.group(1) is not None:+            bars.append((len(plain), len(plain) + len(m.group(1)))); plain += m.group(1)+        else: plain += m.group(2)+    if not plain.strip(): return []+    adv = G['advance'] * height; W = adv * len(plain)+    tris = []+    for i, ch in enumerate(plain):+        gl = table.get(ch) or table['?']+        v = gl['v']; t = gl['t']+        for k in range(0, len(t), 3):+            tris.append(tuple((i * adv + v[2 * j] * height, v[2 * j + 1] * height) for j in t[k:k + 3]))+    for a, b in bars:   # overbar just above the cap height+        y0, y1 = 0.80 * height, 0.87 * height+        tris += [((a * adv, y0), (b * adv, y0), (b * adv, y1)), ((a * adv, y0), (b * adv, y1), (a * adv, y1))]+    # local text coords: x right, y UP, baseline at 0; centre vertically on cap height, align horizontally+    ox = {'left': 0.0, 'right': -W, 'center': -W / 2}[align]; oy = -0.36 * height+    out = []+    for t in tris:+        q = []+        for tx, ty in t:+            lx, ly = tx + ox, ty + oy+            if vertical: lx, ly = -ly, lx          # rotate 90 degrees CCW (reads bottom-to-top)+            q.append((x + lx, y - ly))             # footprint y is down+        out.append(tuple(q))+    return out+++def mirror_label(tris):+    """Seen from below (orbiting the model over toward you, as the wiki viewer does), a label reads upside+    down: the view flips top-to-bottom. Mirror the underside copy across the label's own horizontal centre+    line, so it reads correctly from below and stays in place (Colby, 2026-09-30: "WODE", "ΛIN")."""+    if not tris: return []+    ys = [v[1] for t in tris for v in t]; cy = (min(ys) + max(ys)) / 2+    return [tuple((vx, 2 * cy - vy) for vx, vy in t) for t in tris]+++# ---------------------------------------------------------------- layout decisions+def scale_params(pads):+    xs = [p['x'] for p in pads]; ys = [p['y'] for p in pads]+    span = max(max(xs) - min(xs) + max(p['w'] for p in pads), max(ys) - min(ys) + max(p['h'] for p in pads), 1.0)+    # 1.1 (2026-09-30): bolder. At 0.015 mm the outlines vanished at the wiki viewer's default zoom and the+    # 30% silkscreen read as "the footprint" (Colby). The footprint must read first.+    # 1.2: between the two -- 1.1 read as heavy to Colby ("I like that it's subtle"), 1.0 vanished (Ray chose the middle)+    dash = min(max(0.025 * span, 0.12), 0.45)+    return dict(span_mm=round(span, 3), dash_mm=round(dash, 4), gap_mm=round(0.6 * dash, 4),+                pad_stroke_mm=round(min(max(0.006 * span, 0.03), 0.09), 4))+++def is_grid(pads):+    """BGA/LGA-style ball grid: many pads with many distinct rows AND columns."""+    xs = {round(p['x'], 2) for p in pads}; ys = {round(p['y'], 2) for p in pads}+    return len(pads) >= 16 and len(xs) >= 4 and len(ys) >= 4 and len(pads) > 0.6 * len(xs) * len(ys)+++def label_box(lb):+    W = 0.602 * lb['h'] * len(re.sub(r'~\{([^}]*)\}', r'\1', lb['text'])); H = lb['h']+    x, y = lb['x'], lb['y']+    if not lb['vertical']:+        x0 = x - W if lb['align'] == 'right' else x+        return (x0, x0 + W, y - H / 2, y + H / 2)+    y0 = y if lb['align'] == 'right' else y - W        # vertical text runs up the screen (footprint -y)+    return (x - H / 2, x + H / 2, y0, y0 + W)+++def overlaps(a, b): return a[0] < b[1] and b[0] < a[1] and a[2] < b[3] and b[2] < a[3]+++def label_plan(pads, names, obstacles=()):+    """Per labelled pad: text, anchor, alignment, orientation, height. Interior pads get none."""+    sig = [p for p in pads if not (p['number'] in ('', '~') or thermal_like(p, pads))]+    if not sig or is_grid(sig): return [], ('ball grid: labels omitted (they would sit under the body)' if sig else 'no signal pads')+    xs = [p['x'] for p in sig]; ys = [p['y'] for p in sig]+    cx, cy = (min(xs) + max(xs)) / 2, (min(ys) + max(ys)) / 2+    hx, hy = (max(xs) - min(xs)) / 2 or 1e-6, (max(ys) - min(ys)) / 2 or 1e-6+    plan, seen = [], set()+    for p in sig:+        if p['number'] in seen: continue        # multi-pad numbers (split EP, shield legs) labelled once+        seen.add(p['number'])+        # side = the extreme it sits closest to (normalised), so a 2-row part splits left/right or top/bottom+        dxn, dyn = (p['x'] - cx) / hx, (p['y'] - cy) / hy+        if len(sig) == 2 or abs(dxn) >= abs(dyn): side = 'R' if p['x'] >= cx else 'L'+        else: side = 'B' if p['y'] >= cy else 'T'+        same = [q for q in sig if q is not p and ((side in 'LR' and abs(q['x'] - p['x']) < 0.3) or (side in 'TB' and abs(q['y'] - p['y']) < 0.3))]+        pitch = min([abs((q['y'] - p['y']) if side in 'LR' else (q['x'] - p['x'])) for q in same] or [99])+        o = pad_outline(p); ex = [v[0] for v in o]; ey = [v[1] for v in o]+        short = min(p['w'], p['h'])+        h = min(max(min(0.5 * pitch, 0.7 * short if len(sig) == 2 else 0.5 * pitch), 0.12), 0.6)+        gap = max(0.25 * h, 0.1)+        text = names.get(p['number']) or p['number']+        if text in ('~', ''): text = p['number']+        if side == 'L': plan.append(dict(pad=p['number'], text=text, x=min(ex) - gap, y=p['y'], align='right', vertical=False, h=h))+        if side == 'R': plan.append(dict(pad=p['number'], text=text, x=max(ex) + gap, y=p['y'], align='left', vertical=False, h=h))+        if side == 'T': plan.append(dict(pad=p['number'], text=text, x=p['x'], y=min(ey) - gap, align='left', vertical=True, h=h))+        if side == 'B': plan.append(dict(pad=p['number'], text=text, x=p['x'], y=max(ey) + gap, align='right', vertical=True, h=h))+        lb = plan[-1]+        for _ in range(4):     # step outward past a silkscreen shape (the footprint's pin-1 triangle, our dot)+            hit = next((ob for ob in obstacles if overlaps(label_box(lb), ob)), None)+            if not hit: break+            if side == 'L': lb['x'] = hit[0] - gap+            if side == 'R': lb['x'] = hit[1] + gap+            if side == 'T': lb['y'] = hit[2] - gap+            if side == 'B': lb['y'] = hit[3] + gap+    return plan, None+++def thermal_like(p, pads):+    """Exposed/thermal pad: named EP/PAD, or a pad much larger than the median sitting inside the others."""+    if re.match(r'^(EP|PAD|TAB|0)$', p['number'], re.I): return True+    areas = sorted(q['w'] * q['h'] for q in pads)+    med = areas[len(areas) // 2]+    if len(pads) >= 5 and p['w'] * p['h'] > 4 * med:+        xs = [q['x'] for q in pads]; ys = [q['y'] for q in pads]+        return min(xs) < p['x'] < max(xs) and min(ys) < p['y'] < max(ys)+    return False+++def silk_marks_pin1(silk, p1, pads):+    """The footprint already carries a pin-1 mark: a filled silk shape (KiCad's triangle / dot) whose centroid+    is nearer pad 1 than any other pad and within 2.5 mm of it."""+    for kind, pts, _ in silk:+        if kind != 'fill' or len(pts) < 3: continue+        cx = np.mean([q[0] for q in pts]); cy = np.mean([q[1] for q in pts])+        dist = lambda p: math.hypot(p['x'] - cx, p['y'] - cy)+        if dist(p1) <= 2.5 and dist(p1) <= min(dist(q) for q in pads) + 1e-6: return True+    return False+++def pin1_dot(pads, names, silk=()):+    """(x, y, r) of the pin-1 dot, outside pad 1, or None when the part has no orientation to show or the+    footprint's own silkscreen already marks pin 1."""+    sig = [p for p in pads if not thermal_like(p, pads)]+    p1 = None+    if len(sig) >= 3:+        p1 = next((p for p in sig if p['number'] in ('1', 'A1')), None)+    elif len(sig) == 2:   # a 2-pin part shows polarity only when a pin says so (cathode / +)+        p1 = next((p for p in sig if POLAR_PAD.match((names.get(p['number']) or '').strip())), None)+    if not p1: return None+    if silk_marks_pin1(silk, p1, sig): return ('existing', p1['number'])+    xs = [p['x'] for p in sig]; ys = [p['y'] for p in sig]+    cx, cy = (min(xs) + max(xs)) / 2, (min(ys) + max(ys)) / 2+    dx, dy = p1['x'] - cx, p1['y'] - cy+    if len(sig) >= 3 and not is_grid(sig):+        # outward along the pad's own row axis: beyond pad 1's END of the row (the classic dot position)+        same_col = [q for q in sig if abs(q['x'] - p1['x']) < 0.3]+        if len(same_col) > 1: dx, dy = 0.0, (p1['y'] - np.mean([q['y'] for q in same_col])) or -1.0+        else: dx, dy = (p1['x'] - np.mean([q['x'] for q in sig if abs(q['y'] - p1['y']) < 0.3])) or -1.0, 0.0+    L = math.hypot(dx, dy) or 1.0; ux, uy = dx / L, dy / L+    r = min(max(0.22 * min(p1['w'], p1['h']), 0.1), 0.35)+    o = pad_outline(p1); reach = max((v[0] - p1['x']) * ux + (v[1] - p1['y']) * uy for v in o)+    d = reach + 0.2 + r+    return (p1['x'] + ux * d, p1['y'] + uy * d, r, p1['number'])+++# ---------------------------------------------------------------- GLB assembly+def tris_to_arrays(tris):+    """Indexed mesh: shared vertices stored once (the ribbons and glyphs share most corners), ~3x smaller."""+    P = np.array([[x / 1000.0, -y / 1000.0, Z / 1000.0] for t in tris for (x, y) in t], dtype=np.float32)+    key = np.round(P.astype(np.float64) * 1e7).astype(np.int64)+    _, first, inv = np.unique(key, axis=0, return_index=True, return_inverse=True)+    return P[first], inv.reshape(-1).astype(np.uint32)+++def facing(tris, up):+    """Force each triangle's winding in glTF space (x, -y): counter-clockwise from above for up=True, from below+    for up=False. A single-sided material then shows the top copy only from above and the bottom copy only+    from below."""+    out = []+    for t in tris:+        (x0, y0), (x1, y1), (x2, y2) = t+        area = (x1 - x0) * (-(y2 - y0)) - (x2 - x0) * (-(y1 - y0))     # signed area with glTF y = -footprint y+        out.append(t if (area > 0) == up else (t[0], t[2], t[1]))+    return out+++def add_mesh(g, blob, name, prims):+    """One node + mesh named `name`; prims = [(material_index, tris), ...], one primitive each."""+    gl_prims = []+    for mat_idx, tris in prims:+        if not tris: continue+        P, I = tris_to_arrays(tris)+        pb, ib = P.tobytes(), I.tobytes()+        off = len(blob); blob += pb + b'\x00' * ((4 - len(pb) % 4) % 4)+        g.bufferViews.append(BufferView(buffer=0, byteOffset=off, byteLength=len(pb), target=34962))+        g.accessors.append(Accessor(bufferView=len(g.bufferViews) - 1, componentType=5126, count=len(P), type='VEC3',+                                    min=P.min(0).tolist(), max=P.max(0).tolist()))+        pa = len(g.accessors) - 1+        off = len(blob); blob += ib+        g.bufferViews.append(BufferView(buffer=0, byteOffset=off, byteLength=len(ib), target=34963))+        g.accessors.append(Accessor(bufferView=len(g.bufferViews) - 1, componentType=5125, count=len(I), type='SCALAR'))+        gl_prims.append(Primitive(attributes=Attributes(POSITION=pa), indices=len(g.accessors) - 1, material=mat_idx))+    if not gl_prims: return None, blob+    g.meshes.append(Mesh(name=name, primitives=gl_prims))+    g.nodes.append(Node(name=name, mesh=len(g.meshes) - 1))+    return len(g.nodes) - 1, blob+++def world_points(g):+    """All physical vertices in world metres (for the alignment check)."""+    blob = g.binary_blob()+    CT = {5126: ('f', 4), 5123: ('H', 2), 5125: ('I', 4), 5121: ('B', 1), 5122: ('h', 2), 5120: ('b', 1)}+    NC = {'SCALAR': 1, 'VEC2': 2, 'VEC3': 3, 'VEC4': 4}+    def acc(i):+        a = g.accessors[i]; bv = g.bufferViews[a.bufferView]; t, sz = CT[a.componentType]; nc = NC[a.type]+        st = bv.byteStride or sz * nc; o = (bv.byteOffset or 0) + (a.byteOffset or 0)+        v = np.array([struct.unpack_from('<' + t * nc, blob, o + k * st) for k in range(a.count)], dtype=float)+        if a.normalized: v = v / {5122: 32767, 5120: 127, 5123: 65535, 5121: 255}[a.componentType]+        return v+    def mat(nd):+        if nd.matrix: return np.array(nd.matrix).reshape(4, 4).T+        T = np.eye(4); R = np.eye(4); S = np.eye(4)+        if nd.translation: T[:3, 3] = nd.translation+        if nd.rotation:+            x, y, z, w = nd.rotation+            R[:3, :3] = [[1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)], [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)], [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)]]+        if nd.scale: S[:3, :3] = np.diag(nd.scale)+        return T @ R @ S+    out = []+    def walk(i, M):+        nd = g.nodes[i]; M2 = M @ mat(nd)+        if nd.mesh is not None:+            for p in g.meshes[nd.mesh].primitives:+                P = acc(p.attributes.POSITION); out.append((M2 @ np.c_[P, np.ones(len(P))].T).T[:, :3])+        for c in nd.children or []: walk(c, M2)+    for r in g.scenes[g.scene or 0].nodes: walk(r, np.eye(4))+    return np.vstack(out) if out else np.zeros((0, 3))+++def align_check(g, pads):+    """The chip's lowest geometry (its contacts) must sit over the pads: compare extents in both axes."""+    W = world_points(g) * 1000.0+    if not len(W): return dict(ok=False, why='no physical geometry')+    zmin = W[:, 2].min(); low = W[W[:, 2] < zmin + max(0.08, 0.05 * (W[:, 2].max() - zmin))]+    px = [v[0] for p in pads for v in pad_outline(p)]; py = [-v[1] for p in pads for v in pad_outline(p)]+    pad_box = (min(px), max(px), min(py), max(py)); c_box = (low[:, 0].min(), low[:, 0].max(), low[:, 1].min(), low[:, 1].max())+    # contacts centred on the pad field and not wider than it (+ tolerance); a rotated model fails both+    cx_p, cy_p = (pad_box[0] + pad_box[1]) / 2, (pad_box[2] + pad_box[3]) / 2+    cx_c, cy_c = (c_box[0] + c_box[1]) / 2, (c_box[2] + c_box[3]) / 2+    tol = max(0.25, 0.08 * max(pad_box[1] - pad_box[0], pad_box[3] - pad_box[2]))+    # Orientation: a model turned 90 degrees swaps the long axis of its contacts against the pad field. A+    # leadless body (QFN/WSON) rests its whole underside on the seating plane, so width alone proves nothing.+    pw, ph = pad_box[1] - pad_box[0], pad_box[3] - pad_box[2]; cw, ch = c_box[1] - c_box[0], c_box[3] - c_box[2]+    flipped = (pw > 1.25 * ph and ch > 1.25 * cw) or (ph > 1.25 * pw and cw > 1.25 * ch)+    off = math.hypot(cx_c - cx_p, cy_c - cy_p)+    return dict(ok=bool(off <= tol and not flipped), centre_offset_mm=round(off, 3), tolerance_mm=round(tol, 3), orientation_flipped=bool(flipped),+                contacts_bbox_mm=[round(v, 3) for v in c_box], pads_bbox_mm=[round(v, 3) for v in pad_box], seating_z_mm=round(float(zmin), 3))+++def sha(path): return hashlib.sha256(open(path, 'rb').read()).hexdigest()+++def build(src_glb, kmod, page_json, out, mpn=None, png=None):+    pads, silk, mdl = parse_footprint(kmod)+    if not pads: raise SystemExit(f'{kmod}: no copper pads')+    pj = json.load(open(page_json)); comp = pj.get('component') or {}+    names = {str(p.get('number')): (p.get('name') or '').strip() for p in comp.get('pins') or []}+    mpn = mpn or comp.get('mpn') or os.path.basename(out).replace('-hero.glb', '').upper()+    prm = scale_params(pads)+    g = GLTF2().load(src_glb)+    chk = align_check(g, pads)+    if mdl and (any(abs(v) > 1e-6 for v in mdl['rotate']) or any(abs(v) > 1e-6 for v in mdl['offset'])):+        chk['model_transform_in_footprint'] = mdl+    # --- artwork+    pad_tris = []+    for p in pads:+        o = pad_outline(p); per = sum(math.hypot(b[0] - a[0], b[1] - a[1]) for a, b in zip(o, o[1:]))+        dsh = min(prm['dash_mm'], max(per / 6, 0.05)); w = min(prm['pad_stroke_mm'], max(per / 25, 0.02))+        for d in dashes(o, dsh, 0.6 * dsh): pad_tris += stroke_quads(d, w)+    silk_tris = []+    for kind, pts, w in silk:+        if 'REF' in str(pts): continue+        silk_tris += fill_tris([pts[:-1] if pts[0] == pts[-1] else pts]) if kind == 'fill' and len(pts) >= 4 else stroke_quads(pts, w)+    dot = pin1_dot(pads, names, silk)+    existing_mark = bool(dot) and dot[0] == 'existing'+    if dot and not existing_mark:+        x, y, r, _ = dot+        ring = [(x + r * math.cos(t), y + r * math.sin(t)) for t in np.linspace(0, 2 * math.pi, 33)[:-1]]+        silk_tris += fill_tris([ring])+    obstacles = [(min(q[0] for q in pts), max(q[0] for q in pts), min(q[1] for q in pts), max(q[1] for q in pts)) for kind, pts, _ in silk if kind == 'fill']+    if dot and not existing_mark: obstacles.append((dot[0] - dot[2], dot[0] + dot[2], dot[1] - dot[2], dot[1] + dot[2]))+    plan, why_no_labels = label_plan(pads, names, obstacles)+    name_up, name_down = [], []+    for lb in plan:+        t = text_tris(lb['text'], lb['h'], lb['x'], lb['y'], lb['align'], lb['vertical'])+        name_up += t; name_down += mirror_label(t)+    name_up, name_down = facing(name_up, True), facing(name_down, False)+    # --- materials, meshes, root node+    blob = bytearray(g.binary_blob() or b'')+    blob += b'\x00' * ((4 - len(blob) % 4) % 4)+    mats = []+    for nm, col in (PAD_MAT, SILK_MAT, NAME_MAT):+        # Names are single-sided: an upward copy and a mirrored downward copy, so they read from either side.+        g.materials.append(Material(name=nm, pbrMetallicRoughness=PbrMetallicRoughness(baseColorFactor=col, metallicFactor=0.0, roughnessFactor=1.0),+                                    alphaMode='BLEND', doubleSided=(nm != NAME_MAT[0]), extensions={'KHR_materials_unlit': {}}))+        mats.append(len(g.materials) - 1)+    kids = []+    for (nm, _), prims in zip((PAD_MAT, SILK_MAT, NAME_MAT),+                              ([(mats[0], pad_tris)], [(mats[1], silk_tris)], [(mats[2], name_up), (mats[2], name_down)])):+        ni, blob = add_mesh(g, blob, nm, prims)+        if ni is not None: kids.append(ni)+    g.nodes.append(Node(name=ROOT, children=kids)); g.scenes[g.scene or 0].nodes.append(len(g.nodes) - 1)+    g.buffers[0].byteLength = len(blob); g.set_binary_blob(bytes(blob))+    if 'KHR_materials_unlit' not in (g.extensionsUsed or []): g.extensionsUsed = (g.extensionsUsed or []) + ['KHR_materials_unlit']+    layers = dict(pad_outlines=dict(material=PAD_MAT[0], rgba=PAD_MAT[1], pads=len(pads), **prm),+                  silkscreen=dict(material=SILK_MAT[0], rgba=SILK_MAT[1], footprint_items=len(silk),+                                  pin1=(dict(source='footprint silkscreen', pad=dot[1]) if existing_mark else+                                        dict(source='added dot (AI)', pad=dot[3], center_mm=[round(dot[0], 3), round(dot[1], 3)], r_mm=round(dot[2], 3)) if dot else None)),+                  signal_names=dict(material=NAME_MAT[0], rgba=NAME_MAT[1], font='DejaVu Sans Mono', labels=len(plan), sides='top + mirrored underside (single-sided)',+                                    omitted=why_no_labels, fallback_to_pad_number=sum(1 for lb in plan if lb['text'] == lb['pad'])))+    hero = dict(spec=SPEC, mpn=mpn, kind='component + footprint reference art', board_use=False, plane_z_mm=Z, units='metre', upAxis='Z',+                layers=layers, align=chk, sources=dict(glb=os.path.basename(src_glb), glb_sha256=sha(src_glb),+                footprint=os.path.basename(kmod), footprint_sha256=sha(kmod), pins='page.json component.pins'), generator='factory/hero_glb.py')+    ex = g.asset.extras if isinstance(g.asset.extras, dict) else {}+    ex['adomHero'] = hero; g.asset.extras = ex+    g.save_binary(out)+    side = dict(hero, labels=[{k: (round(v, 3) if isinstance(v, float) else v) for k, v in lb.items()} for lb in plan],+                pads=[dict(number=p['number'], shape=p['shape'], center_mm=[p['x'], p['y']], size_mm=[p['w'], p['h']], rot=p['rot']) for p in pads])+    json.dump(side, open(out.replace('.glb', '.overlay.json'), 'w'), indent=1)+    if png: preview(out, png, pads, plan, dot)+    return hero+++# ---------------------------------------------------------------- quick preview (top + oblique) for review+def preview(glb, png, pads, plan, dot):+    import matplotlib; matplotlib.use('Agg')+    import matplotlib.pyplot as plt+    from matplotlib.collections import PolyCollection+    from mpl_toolkits.mplot3d.art3d import Poly3DCollection+    g = GLTF2().load(glb)+    blob = g.binary_blob()+    CT = {5126: ('f', 4), 5123: ('H', 2), 5125: ('I', 4), 5121: ('B', 1), 5122: ('h', 2), 5120: ('b', 1)}+    NC = {'SCALAR': 1, 'VEC2': 2, 'VEC3': 3, 'VEC4': 4}+    def acc(i):+        a = g.accessors[i]; bv = g.bufferViews[a.bufferView]; t, sz = CT[a.componentType]; nc = NC[a.type]+        st = bv.byteStride or sz * nc; o = (bv.byteOffset or 0) + (a.byteOffset or 0)+        v = np.array([struct.unpack_from('<' + t * nc, blob, o + k * st) for k in range(a.count)], dtype=float)+        if a.normalized: v = v / {5122: 32767, 5120: 127, 5123: 65535, 5121: 255}[a.componentType]+        return v+    def mat(nd):+        if nd.matrix: return np.array(nd.matrix).reshape(4, 4).T+        T = np.eye(4); R = np.eye(4); S = np.eye(4)+        if nd.translation: T[:3, 3] = nd.translation+        if nd.rotation:+            x, y, z, w = nd.rotation+            R[:3, :3] = [[1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)], [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)], [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)]]+        if nd.scale: S[:3, :3] = np.diag(nd.scale)+        return T @ R @ S+    tris = []   # (3x3 mm, rgba)+    def walk(i, M):+        nd = g.nodes[i]; M2 = M @ mat(nd)+        if nd.mesh is not None:+            for p in g.meshes[nd.mesh].primitives:+                P = acc(p.attributes.POSITION) ; P = (M2 @ np.c_[P, np.ones(len(P))].T).T[:, :3] * 1000+                I = acc(p.indices).astype(int).reshape(-1, 3) if p.indices is not None else np.arange(len(P)).reshape(-1, 3)+                m = g.materials[p.material] if p.material is not None else None+                col = list(m.pbrMetallicRoughness.baseColorFactor) if m and m.pbrMetallicRoughness and m.pbrMetallicRoughness.baseColorFactor else [.6, .6, .6, 1]+                for t in I: tris.append((P[t], col))+        for c in nd.children or []: walk(c, M2)+    for r in g.scenes[g.scene or 0].nodes: walk(r, np.eye(4))+    fig = plt.figure(figsize=(14, 7), facecolor='#1b1e24')+    ax = fig.add_subplot(1, 2, 1); ax.set_facecolor('#2a2e36'); ax.set_aspect('equal')+    phys = [(t, c) for t, c in tris if c[3] >= 0.99]; art = [(t, c) for t, c in tris if c[3] < 0.99]+    # top view: physical first (light shading by height), artwork drawn on top so the review sees both+    zs = np.array([t[:, 2].mean() for t, _ in phys]) if phys else np.array([0])+    order = np.argsort(zs)+    ax.add_collection(PolyCollection([phys[i][0][:, :2] for i in order], facecolors=[tuple(np.array(phys[i][1][:3]) * 0.7) + (0.55,) for i in order], edgecolors='none'))+    ax.add_collection(PolyCollection([t[:, :2] for t, _ in art], facecolors=[tuple(c[:3]) + (min(1, c[3] + 0.35),) for _, c in art], edgecolors='none'))+    allp = np.vstack([t for t, _ in tris]); pad = 0.6+    ax.set_xlim(allp[:, 0].min() - pad, allp[:, 0].max() + pad); ax.set_ylim(allp[:, 1].min() - pad, allp[:, 1].max() + pad)+    ax.set_title('top (artwork over a translucent body)', color='w', fontsize=10); ax.tick_params(colors='#888')+    ax3 = fig.add_subplot(1, 2, 2, projection='3d'); ax3.set_facecolor('#2a2e36')+    ax3.add_collection3d(Poly3DCollection([t for t, _ in tris], facecolors=[tuple(c[:3]) + (c[3],) for _, c in tris], edgecolors='none'))+    rng = allp.max(0) - allp.min(0); mid = (allp.max(0) + allp.min(0)) / 2; R = rng.max() / 2+    ax3.set_xlim(mid[0] - R, mid[0] + R); ax3.set_ylim(mid[1] - R, mid[1] + R); ax3.set_zlim(mid[2] - R * 0.6, mid[2] + R * 0.6)+    ax3.view_init(elev=38, azim=-60); ax3.set_axis_off(); ax3.set_title('oblique', color='w', fontsize=10)+    fig.suptitle(os.path.basename(glb), color='w'); fig.tight_layout(); fig.savefig(png, dpi=110); plt.close(fig)+++if __name__ == '__main__':+    ap = argparse.ArgumentParser()+    ap.add_argument('glb'); ap.add_argument('kicad_mod'); ap.add_argument('page_json'); ap.add_argument('out')+    ap.add_argument('--mpn'); ap.add_argument('--png')+    a = ap.parse_args()+    h = build(a.glb, a.kicad_mod, a.page_json, a.out, a.mpn, a.png)+    L = h['layers']+    print(f"OK {a.out}: pads {L['pad_outlines']['pads']}, silk items {L['silkscreen']['footprint_items']}, "+          f"pin1 {(L['silkscreen']['pin1'] or {}).get('source', 'none')}, labels {L['signal_names']['labels']}"+          f"{' (' + L['signal_names']['omitted'] + ')' if L['signal_names']['omitted'] else ''}; "+          f"align {'OK' if h['align']['ok'] else 'FAIL'} (offset {h['align'].get('centre_offset_mm')} mm)")