summaryrefslogtreecommitdiff
path: root/gerbonara
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2023-04-29 11:28:38 +0200
committerjaseg <git@jaseg.de>2023-04-29 11:28:38 +0200
commit8d5403260b72115cfd9f401289dfd0f894e272ea (patch)
tree0f7ac51c4072477018fec6f8d153d00365735f34 /gerbonara
parent778e81974580d910eac5e3f977acf79744d3e085 (diff)
downloadgerbonara-8d5403260b72115cfd9f401289dfd0f894e272ea.tar.gz
gerbonara-8d5403260b72115cfd9f401289dfd0f894e272ea.tar.bz2
gerbonara-8d5403260b72115cfd9f401289dfd0f894e272ea.zip
Fix aperture macro rotation issue and add missing data files
Diffstat (limited to 'gerbonara')
-rw-r--r--gerbonara/aperture_macros/expression.py2
-rw-r--r--gerbonara/aperture_macros/parse.py4
-rw-r--r--gerbonara/aperture_macros/primitive.py18
-rw-r--r--gerbonara/apertures.py4
-rw-r--r--gerbonara/cad/data/center-pad-spikes.kicad_mod16
-rw-r--r--gerbonara/cad/data/pad-between-spiked.kicad_mod24
-rw-r--r--gerbonara/cad/data/tht-0.8.kicad_mod16
-rw-r--r--gerbonara/cad/protoboard.py1
8 files changed, 77 insertions, 8 deletions
diff --git a/gerbonara/aperture_macros/expression.py b/gerbonara/aperture_macros/expression.py
index 63f1e42..44abf51 100644
--- a/gerbonara/aperture_macros/expression.py
+++ b/gerbonara/aperture_macros/expression.py
@@ -123,7 +123,7 @@ class UnitExpression(Expression):
raise ValueError('Unit mismatch: Can only add/subtract UnitExpression from UnitExpression, not scalar.')
def __sub__(self, other):
- return (self + (-other)).optimize()
+ return (self + (-other)).optimized()
def __rsub__(self, other):
# see __radd__ above
diff --git a/gerbonara/aperture_macros/parse.py b/gerbonara/aperture_macros/parse.py
index 72703ae..b8970ff 100644
--- a/gerbonara/aperture_macros/parse.py
+++ b/gerbonara/aperture_macros/parse.py
@@ -55,9 +55,9 @@ class ApertureMacro:
comments: tuple = ()
def __post_init__(self):
- if self.name is None:
+ if self.name is None or re.match(r'GNX[0-9A-F]{16}', self.name):
# We can't use field(default_factory=...) here because that factory doesn't get a reference to the instance.
- object.__setattr__(self, 'name', f'gn_{hash(self):x}')
+ object.__setattr__(self, 'name', f'GNX{hash(self)&0xffffffffffffffff:016X}')
@classmethod
def parse_macro(cls, name, body, unit):
diff --git a/gerbonara/aperture_macros/primitive.py b/gerbonara/aperture_macros/primitive.py
index 5700743..356da9f 100644
--- a/gerbonara/aperture_macros/primitive.py
+++ b/gerbonara/aperture_macros/primitive.py
@@ -13,7 +13,7 @@ from .expression import Expression, UnitExpression, ConstantExpression, expr
from .. import graphic_primitives as gp
from .. import graphic_objects as go
-from ..utils import rotate_point, LengthUnit
+from ..utils import rotate_point, LengthUnit, MM
def point_distance(a, b):
@@ -277,8 +277,20 @@ class Outline(Primitive):
return f'<Outline {len(self.coords)} points>'
def to_gerber(self, unit=None):
- coords = ','.join(coord.to_gerber(unit) for coord in self.coords)
- return f'{self.code},{self.exposure.to_gerber()},{len(self.coords)-1},{coords},{self.rotation.to_gerber()}'
+ # Calculate out rotation since at least gerbv mis-renders Outlines with rotation other than zero.
+ rotation = self.rotation.optimized()
+ coords = self.coords
+ if isinstance(rotation, ConstantExpression):
+ rotation = math.radians(rotation.value)
+ # This will work even with variables in x and y, we just need to pass in cx and cy as UnitExpressions
+ unit_zero = UnitExpression(expr(0), MM)
+ coords = [ rotate_point(x, y, -rotation, cx=unit_zero, cy=unit_zero) for x, y in self.points ]
+ coords = [ e for point in coords for e in point ]
+
+ rotation = ConstantExpression(0)
+
+ coords = ','.join(coord.to_gerber(unit) for coord in coords)
+ return f'{self.code},{self.exposure.to_gerber()},{len(self.coords)-1},{coords},{rotation.to_gerber()}'
def to_graphic_primitives(self, offset, rotation, variable_binding={}, unit=None, polarity_dark=True):
with self.Calculator(self, variable_binding, unit) as calc:
diff --git a/gerbonara/apertures.py b/gerbonara/apertures.py
index 512b4dd..d901765 100644
--- a/gerbonara/apertures.py
+++ b/gerbonara/apertures.py
@@ -421,13 +421,13 @@ class ApertureMacroInstance(Aperture):
return replace(self, macro=self.macro.dilated(offset, unit))
@lru_cache()
- def rotated(self, angle=0):
+ def rotated(self, angle=0.0):
if math.isclose(angle % (2*math.pi), 0):
return self
else:
return self.to_macro(angle)
- def to_macro(self, rotation=0):
+ def to_macro(self, rotation=0.0):
return replace(self, macro=self.macro.rotated(rotation))
def scaled(self, scale):
diff --git a/gerbonara/cad/data/center-pad-spikes.kicad_mod b/gerbonara/cad/data/center-pad-spikes.kicad_mod
new file mode 100644
index 0000000..e996861
--- /dev/null
+++ b/gerbonara/cad/data/center-pad-spikes.kicad_mod
@@ -0,0 +1,16 @@
+(module center-pad-spikes (layer F.Cu) (tedit 5B6B1C50)
+ (fp_text reference REF** (at 0 -1.4) (layer F.SilkS) hide
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (fp_text value center-pad (at 0.1 -2.7) (layer F.Fab) hide
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (pad 1 smd custom (at -0.06 -0.085) (size 0.47 0.52) (layers *.Cu *.Mask)
+ (options (clearance outline) (anchor rect))
+ (primitives
+ (gr_poly (pts
+ (xy -0.585 0.085) (xy 0.06 -0.56) (xy 0.357 -0.263) (xy 0.583 -0.263) (xy 0.235 0.085)
+ (xy 0.582 0.432) (xy 0.407 0.432) (xy 0.407 0.607) (xy 0.06 0.26) (xy -0.288 0.608)
+ (xy -0.288 0.382)) (width 0.001))
+ ))
+)
diff --git a/gerbonara/cad/data/pad-between-spiked.kicad_mod b/gerbonara/cad/data/pad-between-spiked.kicad_mod
new file mode 100644
index 0000000..205101e
--- /dev/null
+++ b/gerbonara/cad/data/pad-between-spiked.kicad_mod
@@ -0,0 +1,24 @@
+(module pad-between-spiked (layer F.Cu) (tedit 5B6B1D89)
+ (descr "Through hole pin header")
+ (tags "pin header")
+ (fp_text reference REF** (at 0 -5.1) (layer F.SilkS) hide
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (fp_text value pad-between (at 0 -3.1) (layer F.Fab) hide
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (pad 1 smd custom (at 0 -0.06) (size 0.7 0.85) (layers *.Cu *.Mask)
+ (options (clearance outline) (anchor rect))
+ (primitives
+ (gr_poly (pts
+ (xy -0.55 -0.44) (xy -0.325 -0.44) (xy 0 -0.765) (xy 0.325 -0.44) (xy 0.55 -0.44)
+ (xy 0.35 -0.24) (xy 0.35 0.36) (xy 0.55 0.56) (xy 0.338 0.56) (xy 0.338 0.763)
+ (xy 0 0.425) (xy -0.01 0.425) (xy -0.348 0.763) (xy -0.348 0.56) (xy -0.55 0.56)
+ (xy -0.35 0.36) (xy -0.35 -0.24)) (width 0.001))
+ ))
+ (model Pin_Headers.3dshapes/Pin_Header_Straight_1x01.wrl
+ (at (xyz 0 0 0))
+ (scale (xyz 1 1 1))
+ (rotate (xyz 0 0 90))
+ )
+)
diff --git a/gerbonara/cad/data/tht-0.8.kicad_mod b/gerbonara/cad/data/tht-0.8.kicad_mod
new file mode 100644
index 0000000..3092f23
--- /dev/null
+++ b/gerbonara/cad/data/tht-0.8.kicad_mod
@@ -0,0 +1,16 @@
+(module tht-0.8 (layer F.Cu) (tedit 58D96FE6)
+ (descr "Through hole pin header")
+ (tags "pin header")
+ (fp_text reference REF** (at 0 -5.1) (layer F.SilkS) hide
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (fp_text value tht-0.8 (at 0 -3.1) (layer F.Fab) hide
+ (effects (font (size 1 1) (thickness 0.15)))
+ )
+ (pad 1 thru_hole circle (at 0 0) (size 1.4 1.4) (drill 0.8) (layers *.Cu *.Mask))
+ (model Pin_Headers.3dshapes/Pin_Header_Straight_1x01.wrl
+ (at (xyz 0 0 0))
+ (scale (xyz 1 1 1))
+ (rotate (xyz 0 0 90))
+ )
+)
diff --git a/gerbonara/cad/protoboard.py b/gerbonara/cad/protoboard.py
index 741d8a9..02cbb65 100644
--- a/gerbonara/cad/protoboard.py
+++ b/gerbonara/cad/protoboard.py
@@ -550,6 +550,7 @@ def _demo():
#pattern = PatternProtoArea(2.54, obj=THTPad.circle(0, 0, 0.9, 1.8, paste=False))
#pattern = PatternProtoArea(2.54, obj=PoweredProto())
pb = ProtoBoard(50, 50, pattern1, mounting_hole_dia=3.2, mounting_hole_offset=5)
+ #pb = ProtoBoard(10, 10, pattern1)
print(pb.pretty_svg())
pb.layer_stack().save_to_directory('/tmp/testdir')