From edaf246b9dcfbb87a636d538536ae6c89f7ca956 Mon Sep 17 00:00:00 2001 From: jaseg Date: Wed, 17 Jul 2024 10:20:35 +0200 Subject: Update KiCad PCB format support to 8.99 --- gerbonara/cad/kicad/footprints.py | 3 +- gerbonara/cad/kicad/graphical_primitives.py | 9 ++++ gerbonara/cad/kicad/pcb.py | 68 ++++++++++++++++------------- gerbonara/utils.py | 2 +- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/gerbonara/cad/kicad/footprints.py b/gerbonara/cad/kicad/footprints.py index cb7b69d..127eef5 100644 --- a/gerbonara/cad/kicad/footprints.py +++ b/gerbonara/cad/kicad/footprints.py @@ -55,7 +55,7 @@ class Text: type: AtomChoice(Atom.reference, Atom.value, Atom.user) = Atom.user text: str = "" at: AtPos = field(default_factory=AtPos) - unlocked: Flag() = False + unlocked: OmitDefault(Named(YesNoAtom())) = False layer: Named(str) = None uuid: UUID = field(default_factory=UUID) hide: Flag() = False @@ -619,6 +619,7 @@ SUPPORTED_FILE_FORMAT_VERSIONS = [20210108, 20211014, 20221018, 20230517] class Footprint: name: str = None _version: Named(int, name='version') = 20221018 + uuid: UUID = field(default_factory=UUID) generator: Named(str) = Atom.gerbonara generator_version: Named(str) = __version__ locked: Flag() = False diff --git a/gerbonara/cad/kicad/graphical_primitives.py b/gerbonara/cad/kicad/graphical_primitives.py index 94a61a4..a4f0f51 100644 --- a/gerbonara/cad/kicad/graphical_primitives.py +++ b/gerbonara/cad/kicad/graphical_primitives.py @@ -22,6 +22,7 @@ class Text(TextMixin): text: str = '' at: AtPos = field(default_factory=AtPos) layer: TextLayer = field(default_factory=TextLayer) + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None effects: TextEffect = field(default_factory=TextEffect) render_cache: RenderCache = None @@ -39,6 +40,7 @@ class TextBox: pts: PointList = field(default_factory=PointList) angle: OmitDefault(Named(float)) = 0.0 layer: Named(str) = "" + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None effects: TextEffect = field(default_factory=TextEffect) stroke: Stroke = field(default_factory=Stroke) @@ -76,6 +78,7 @@ class Line: layer: Named(str) = None width: Named(float) = None stroke: Stroke = field(default_factory=Stroke) + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None def rotate(self, angle, cx=None, cy=None): @@ -120,6 +123,7 @@ class Rectangle: width: Named(float) = None stroke: Stroke = field(default_factory=Stroke) fill: FillMode = False + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None def render(self, variables=None): @@ -152,6 +156,7 @@ class Circle: width: Named(float) = None stroke: Stroke = field(default_factory=Stroke) fill: FillMode = False + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None def render(self, variables=None): @@ -179,6 +184,7 @@ class Arc: layer: Named(str) = None width: Named(float) = None stroke: Stroke = field(default_factory=Stroke) + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None _: SEXP_END = None center: XYCoord = None @@ -221,6 +227,7 @@ class Polygon: width: Named(float) = None stroke: Stroke = field(default_factory=Stroke) fill: FillMode = True + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None def render(self, variables=None): @@ -258,6 +265,7 @@ class Curve: pts: PointList = field(default_factory=PointList) layer: Named(str) = None width: Named(float) = None + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = None def render(self, variables=None): @@ -319,6 +327,7 @@ class Dimension: locked: Flag() = False dimension_type: Named(AtomChoice(Atom.aligned, Atom.leader, Atom.center, Atom.orthogonal, Atom.radial), name='type') = Atom.aligned layer: Named(str) = 'Dwgs.User' + uuid: UUID = field(default_factory=UUID) tstamp: Timestamp = field(default_factory=Timestamp) pts: PointList = field(default_factory=PointList) height: Named(float) = None diff --git a/gerbonara/cad/kicad/pcb.py b/gerbonara/cad/kicad/pcb.py index 767b763..e3c9ede 100644 --- a/gerbonara/cad/kicad/pcb.py +++ b/gerbonara/cad/kicad/pcb.py @@ -59,6 +59,7 @@ def gn_layer_to_kicad(layer, flip=False): @sexp_type('general') class GeneralSection: thickness: Named(float) = 1.60 + legacy_teardrops: Named(YesNoAtom()) = False @sexp_type('layers') @@ -92,43 +93,44 @@ class StackupSettings: edge_plating: Named(YesNoAtom()) = None -TFBool = YesNoAtom(yes=Atom.true, no=Atom.false) - @sexp_type('pcbplotparams') class ExportSettings: layerselection: Named(Atom) = None plot_on_all_layers_selection: Named(Atom) = None - disableapertmacros: Named(TFBool) = False - usegerberextensions: Named(TFBool) = True - usegerberattributes: Named(TFBool) = True - usegerberadvancedattributes: Named(TFBool) = True - creategerberjobfile: Named(TFBool) = True + disableapertmacros: Named(YesNoAtom()) = False + usegerberextensions: Named(YesNoAtom()) = True + usegerberattributes: Named(YesNoAtom()) = True + usegerberadvancedattributes: Named(YesNoAtom()) = True + creategerberjobfile: Named(YesNoAtom()) = True dashed_line_dash_ratio: Named(float) = 12.0 dashed_line_gap_ratio: Named(float) = 3.0 - svguseinch: Named(TFBool) = False + svguseinch: Named(YesNoAtom()) = False svgprecision: Named(float) = 4 - excludeedgelayer: Named(TFBool) = False - plotframeref: Named(TFBool) = False - viasonmask: Named(TFBool) = False + excludeedgelayer: Named(YesNoAtom()) = False + plotframeref: Named(YesNoAtom()) = False + viasonmask: Named(YesNoAtom()) = False mode: Named(int) = 1 - useauxorigin: Named(TFBool) = False + useauxorigin: Named(YesNoAtom()) = False hpglpennumber: Named(int) = 1 hpglpenspeed: Named(int) = 20 hpglpendiameter: Named(float) = 15.0 - pdf_front_fp_property_popups: Named(TFBool) = True - pdf_back_fp_property_popups: Named(TFBool) = True - dxfpolygonmode: Named(TFBool) = True - dxfimperialunits: Named(TFBool) = False - dxfusepcbnewfont: Named(TFBool) = True - psnegative: Named(TFBool) = False - psa4output: Named(TFBool) = False - plotreference: Named(TFBool) = True - plotvalue: Named(TFBool) = True - plotinvisibletext: Named(TFBool) = False - sketchpadsonfab: Named(TFBool) = False - subtractmaskfromsilk: Named(TFBool) = False + pdf_front_fp_property_popups: Named(YesNoAtom()) = True + pdf_back_fp_property_popups: Named(YesNoAtom()) = True + pdf_metadata: Named(YesNoAtom()) = True + dxfpolygonmode: Named(YesNoAtom()) = True + dxfimperialunits: Named(YesNoAtom()) = False + dxfusepcbnewfont: Named(YesNoAtom()) = True + psnegative: Named(YesNoAtom()) = False + psa4output: Named(YesNoAtom()) = False + plotreference: Named(YesNoAtom()) = True + plotvalue: Named(YesNoAtom()) = True + plotfptext: Named(YesNoAtom()) = True + plotinvisibletext: Named(YesNoAtom()) = False + sketchpadsonfab: Named(YesNoAtom()) = False + plotpadnumbers: Named(YesNoAtom()) = False + subtractmaskfromsilk: Named(YesNoAtom()) = False outputformat: Named(int) = 1 - mirror: Named(TFBool) = False + mirror: Named(YesNoAtom()) = False drillshape: Named(int) = 0 scaleselection: Named(int) = 1 outputdirectory: Named(str) = "gerber" @@ -141,6 +143,8 @@ class BoardSetup: solder_mask_min_width: Named(float) = None pad_to_past_clearance: Named(float) = None pad_to_paste_clearance_ratio: Named(float) = None + allow_soldermask_bridges_in_footprints: Named(YesNoAtom()) = False + tenting: Named(Array(AtomChoice(Atom.front, Atom.back))) = field(default_factory=lambda: [Atom.front, Atom.back]) aux_axis_origin: Rename(XYCoord) = None grid_origin: Rename(XYCoord) = None export_settings: ExportSettings = field(default_factory=ExportSettings) @@ -160,7 +164,8 @@ class TrackSegment: layer: Named(str) = 'F.Cu' locked: Flag() = False net: Named(int) = 0 - tstamp: Timestamp = field(default_factory=Timestamp) + uuid: UUID = field(default_factory=UUID) + tstamp: Timestamp = None @classmethod def from_footprint_line(kls, line, flip=False): @@ -203,14 +208,15 @@ class TrackArc: layer: Named(str) = 'F.Cu' locked: Flag() = False net: Named(int) = 0 - tstamp: Timestamp = field(default_factory=Timestamp) + uuid: UUID = field(default_factory=UUID) + tstamp: Timestamp = None _: SEXP_END = None center: XYCoord = None def __post_init__(self): self.start = XYCoord(self.start) self.end = XYCoord(self.end) - self.mid = XYCoord(self.mid) if self.mid else center_arc_to_kicad_mid(XYCoord(self.center), self.start, self.end) + self.mid = XYCoord(self.mid) if self.center is None else center_arc_to_kicad_mid(XYCoord(self.center), self.start, self.end) self.center = None @property @@ -250,7 +256,8 @@ class Via: keep_end_layers: Flag() = False free: Named(YesNoAtom()) = False net: Named(int) = 0 - tstamp: Timestamp = field(default_factory=Timestamp) + uuid: UUID = field(default_factory=UUID) + tstamp: Timestamp = None @classmethod def from_pad(kls, pad): @@ -307,7 +314,8 @@ SUPPORTED_FILE_FORMAT_VERSIONS = [20210108, 20211014, 20221018, 20230517] @sexp_type('kicad_pcb') class Board: _version: Named(int, name='version') = 20230517 - generator: Named(Atom) = Atom.gerbonara + generator: Named(str) = Atom.gerbonara + generator_version: Named(str) = Atom.gerbonara general: GeneralSection = None page: PageSettings = None layers: Named(Array(Untagged(LayerSettings))) = field(default_factory=list) diff --git a/gerbonara/utils.py b/gerbonara/utils.py index 6d8445d..83a7d93 100644 --- a/gerbonara/utils.py +++ b/gerbonara/utils.py @@ -542,7 +542,7 @@ def svg_rotation(angle_rad, cx=0, cy=0): return {'transform': f'rotate({float(math.degrees(angle_rad)):.4} {float(cx):.6} {float(cy):.6})'} def setup_svg(tags, bounds, margin=0, arg_unit=MM, svg_unit=MM, pagecolor='white', tag=Tag, inkscape=False): - (min_x, min_y), (max_x, max_y) = bounds + (min_x, min_y), (max_x, max_y) = svg_unit.convert_bounds_from(arg_unit, bounds) if margin: margin = svg_unit(margin, arg_unit) -- cgit