summaryrefslogtreecommitdiff
path: root/gerbonara/cad
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2023-07-06 22:42:39 +0200
committerjaseg <git@jaseg.de>2023-07-06 22:42:39 +0200
commit572486aa25711a432ff08ff8fad8ad91670661b7 (patch)
tree75dc09f1ea2def4185618fccaf7c07c50f8a0959 /gerbonara/cad
parent0799cc55adc096b488820ebac46fbb4c54b24e45 (diff)
downloadgerbonara-572486aa25711a432ff08ff8fad8ad91670661b7.tar.gz
gerbonara-572486aa25711a432ff08ff8fad8ad91670661b7.tar.bz2
gerbonara-572486aa25711a432ff08ff8fad8ad91670661b7.zip
kicad: Fix layers attribute handling and improve rotation API
Diffstat (limited to 'gerbonara/cad')
-rw-r--r--gerbonara/cad/kicad/base_types.py1
-rw-r--r--gerbonara/cad/kicad/footprints.py17
-rw-r--r--gerbonara/cad/kicad/pcb.py4
-rw-r--r--gerbonara/cad/kicad/primitives.py27
4 files changed, 45 insertions, 4 deletions
diff --git a/gerbonara/cad/kicad/base_types.py b/gerbonara/cad/kicad/base_types.py
index fafb802..2a6f196 100644
--- a/gerbonara/cad/kicad/base_types.py
+++ b/gerbonara/cad/kicad/base_types.py
@@ -202,7 +202,6 @@ class TextEffect:
hide: Flag() = False
justify: OmitDefault(Justify) = field(default_factory=Justify)
-
@sexp_type('tstamp')
class Timestamp:
value: str = field(default_factory=uuid.uuid4)
diff --git a/gerbonara/cad/kicad/footprints.py b/gerbonara/cad/kicad/footprints.py
index 9772b55..aedf9b8 100644
--- a/gerbonara/cad/kicad/footprints.py
+++ b/gerbonara/cad/kicad/footprints.py
@@ -389,6 +389,12 @@ class Pad:
_: SEXP_END = None
footprint: object = None
+ def __after_parse__(self, parent=None):
+ self.layers = unfuck_layers(self.layers)
+
+ def __before_sexp__(self):
+ self.layers = fuck_layers(self.layers)
+
def find_connected(self, **filters):
""" Find footprints connected to the same net as this pad """
return self.footprint.board.find_footprints(net=self.net.name, **filters)
@@ -677,12 +683,19 @@ class Footprint:
x, y = self.at.x-cx, self.at.y-cy
self.at.x = math.cos(angle)*x - math.sin(angle)*y + cx
self.at.y = math.sin(angle)*x + math.cos(angle)*y + cy
-
- self.at.rotation -= math.degrees(angle)
+ self.at.rotation -= math.degrees(angle)
for pad in self.pads:
pad.at.rotation -= math.degrees(angle)
+ def set_rotation(self, angle):
+ old_deg = self.at.rotation
+ new_deg = self.at.rotation = -math.degrees(angle)
+ delta = new_deg - old_deg
+
+ for pad in self.pads:
+ pad.at.rotation += delta
+
def objects(self, text=False, pads=True):
return chain(
(self.texts if text else []),
diff --git a/gerbonara/cad/kicad/pcb.py b/gerbonara/cad/kicad/pcb.py
index 2b28655..9ab00b3 100644
--- a/gerbonara/cad/kicad/pcb.py
+++ b/gerbonara/cad/kicad/pcb.py
@@ -251,6 +251,10 @@ class Board:
def __before_sexp__(self):
self.properties = [Property(key, value) for key, value in self.properties.items()]
+ def unfill_zones(self):
+ for zone in self.zones:
+ zone.unfill()
+
def find_pads(self, net=None):
for fp in self.footprints:
for pad in fp.pads:
diff --git a/gerbonara/cad/kicad/primitives.py b/gerbonara/cad/kicad/primitives.py
index 40cb22c..6e9f41d 100644
--- a/gerbonara/cad/kicad/primitives.py
+++ b/gerbonara/cad/kicad/primitives.py
@@ -1,10 +1,24 @@
import enum
+import re
from .sexp import *
from .base_types import *
+def unfuck_layers(layers):
+ if layers and layers[0] == 'F&B.Cu':
+ return ['F.Cu', 'B.Cu', *layers[1:]]
+ else:
+ return layers
+
+def fuck_layers(layers):
+ if layers and 'F.Cu' in layers and 'B.Cu' in layers and not any(re.match(r'^In[0-9]+\.Cu$', l) for l in layers):
+ return ['F&B.Cu', *(l for l in layers if l not in ('F.Cu', 'B.Cu'))]
+ else:
+ return layers
+
+
@sexp_type('hatch')
class Hatch:
style: AtomChoice(Atom.none, Atom.edge, Atom.full) = Atom.edge
@@ -81,12 +95,23 @@ class Zone:
connect_pads: PadConnection = field(default_factory=PadConnection)
min_thickness: Named(float) = 0.254
filled_areas_thickness: Named(YesNoAtom()) = True
- keepout: ZoneKeepout = field(default_factory=ZoneKeepout)
+ keepout: ZoneKeepout = None
fill: ZoneFill = field(default_factory=ZoneFill)
polygon: ZonePolygon = field(default_factory=ZonePolygon)
fill_polygons: List(FillPolygon) = field(default_factory=list)
fill_segments: List(FillSegment) = field(default_factory=list)
+ def __after_parse__(self, parent=None):
+ self.layers = unfuck_layers(self.layers)
+
+ def __before_sexp__(self):
+ self.layers = fuck_layers(self.layers)
+
+ def unfill(self):
+ self.fill.yes = False
+ self.fill_polygons = []
+ self.fill_segments = []
+
@sexp_type('polygon')
class RenderCachePolygon: