summaryrefslogtreecommitdiff
path: root/gerbonara/gerber/aperture_macros
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2021-12-29 19:58:20 +0100
committerjaseg <git@jaseg.de>2021-12-29 19:58:20 +0100
commit3fb26e6940b5ae752308d8a33f2608d266795153 (patch)
treea563b0cf512e5661b2a450ebf73eafe655ac18b2 /gerbonara/gerber/aperture_macros
parent30dabef9ee83021067957854187b9bbf245c14cf (diff)
downloadgerbonara-3fb26e6940b5ae752308d8a33f2608d266795153.tar.gz
gerbonara-3fb26e6940b5ae752308d8a33f2608d266795153.tar.bz2
gerbonara-3fb26e6940b5ae752308d8a33f2608d266795153.zip
Basic round-trip works
Diffstat (limited to 'gerbonara/gerber/aperture_macros')
-rw-r--r--gerbonara/gerber/aperture_macros/expression.py15
-rw-r--r--gerbonara/gerber/aperture_macros/parse.py51
-rw-r--r--gerbonara/gerber/aperture_macros/primitive.py11
3 files changed, 40 insertions, 37 deletions
diff --git a/gerbonara/gerber/aperture_macros/expression.py b/gerbonara/gerber/aperture_macros/expression.py
index ddd8d53..73a2a36 100644
--- a/gerbonara/gerber/aperture_macros/expression.py
+++ b/gerbonara/gerber/aperture_macros/expression.py
@@ -8,15 +8,14 @@ import re
import ast
+MILLIMETERS_PER_INCH = 25.4
+
+
def expr(obj):
return obj if isinstance(obj, Expression) else ConstantExpression(obj)
-class Expression(object):
- @property
- def value(self):
- return self
-
+class Expression:
def optimized(self, variable_binding={}):
return self
@@ -79,17 +78,17 @@ class UnitExpression(Expression):
return f'<{self._expr.to_gerber()} {self.unit}>'
def converted(self, unit):
- if unit is None or self.unit == unit:
+ if self.unit is None or unit is None or self.unit == unit:
return self._expr
elif unit == 'mm':
return self._expr * MILLIMETERS_PER_INCH
elif unit == 'inch':
- return self._expr / MILLIMETERS_PER_INCH)
+ return self._expr / MILLIMETERS_PER_INCH
else:
- raise ValueError('invalid unit, must be "inch" or "mm".')
+ raise ValueError(f'invalid unit {unit}, must be "inch" or "mm".')
class ConstantExpression(Expression):
diff --git a/gerbonara/gerber/aperture_macros/parse.py b/gerbonara/gerber/aperture_macros/parse.py
index 2f578ee..35cb6c2 100644
--- a/gerbonara/gerber/aperture_macros/parse.py
+++ b/gerbonara/gerber/aperture_macros/parse.py
@@ -9,10 +9,8 @@ import ast
import copy
import math
-import primitive as ap
-from expression import *
-
-from .. import apertures
+from . import primitive as ap
+from .expression import *
def rad_to_deg(x):
return (x / math.pi) * 180
@@ -54,10 +52,10 @@ class ApertureMacro:
self.primitives = primitives or []
@classmethod
- def parse_macro(cls, name, macro, unit):
+ def parse_macro(cls, name, body, unit):
macro = cls(name)
- blocks = re.sub(r'\s', '', macro).split('*')
+ blocks = re.sub(r'\s', '', body).split('*')
for block in blocks:
if not (block := block.strip()): # empty block
continue
@@ -74,14 +72,14 @@ class ApertureMacro:
else: # primitive
primitive, *args = block.split(',')
- args = [_parse_expression(arg) for arg in args]
- primitive = ap.PRIMITIVE_CLASSES[int(primitive)](unit=unit, args=args
+ args = [ _parse_expression(arg) for arg in args ]
+ primitive = ap.PRIMITIVE_CLASSES[int(primitive)](unit=unit, args=args)
macro.primitives.append(primitive)
@property
def name(self):
- if self.name is not None:
- return self.name
+ if self._name is not None:
+ return self._name
else:
return f'gn_{hash(self)}'
@@ -120,31 +118,34 @@ class ApertureMacro:
return copy
+cons, var = ConstantExpression, VariableExpression
+deg_per_rad = 180 / math.pi
+
class GenericMacros:
- deg_per_rad = 180 / math.pi
- cons, var = VariableExpression
+
_generic_hole = lambda n: [
- ap.Circle(exposure=0, diameter=var(n), x=0, y=0),
- ap.Rectangle(exposure=0, w=var(n), h=var(n+1), x=0, y=0, rotation=var(n+2) * deg_per_rad)]
+ ap.Circle(None, [0, var(n), 0, 0]),
+ ap.CenterLine(None, [0, var(n), var(n+1), 0, 0, var(n+2) * deg_per_rad])]
- circle = ApertureMacro([
- ap.Circle(exposure=1, diameter=var(1), x=0, y=0, rotation=var(4) * deg_per_rad),
+ # Initialize all these with "None" units so they inherit file units, and do not convert their arguments.
+ circle = ApertureMacro('GNC', [
+ ap.Circle(None, [1, var(1), 0, 0, var(4) * deg_per_rad]),
*_generic_hole(2)])
- rect = ApertureMacro([
- ap.Rectangle(exposure=1, w=var(1), h=var(2), x=0, y=0, rotation=var(5) * deg_per_rad),
+ rect = ApertureMacro('GNR', [
+ ap.CenterLine(None, [1, var(1), var(2), 0, 0, var(5) * deg_per_rad]),
*_generic_hole(3) ])
# w must be larger than h
- obround = ApertureMacro([
- ap.Rectangle(exposure=1, w=var(1), h=var(2), x=0, y=0, rotation=var(5) * deg_per_rad),
- ap.Circle(exposure=1, diameter=var(2), x=+var(1)/2, y=0, rotation=var(5) * deg_per_rad),
- ap.Circle(exposure=1, diameter=var(2), x=-var(1)/2, y=0, rotation=var(5) * deg_per_rad),
+ obround = ApertureMacro('GNO', [
+ ap.CenterLine(None, [1, var(1), var(2), 0, 0, var(5) * deg_per_rad]),
+ ap.Circle(None, [1, var(2), +var(1)/2, 0, var(5) * deg_per_rad]),
+ ap.Circle(None, [1, var(2), -var(1)/2, 0, var(5) * deg_per_rad]),
*_generic_hole(3) ])
- polygon = ApertureMacro([
- ap.Polygon(exposure=1, n_vertices=var(2), x=0, y=0, diameter=var(1), rotation=var(3) * deg_per_rad),
- pa.Circle(exposure=0, diameter=var(4), x=0, y=0)])
+ polygon = ApertureMacro('GNP', [
+ ap.Polygon(None, [1, var(2), 0, 0, var(1), var(3) * deg_per_rad]),
+ ap.Circle(None, [0, var(4), 0, 0])])
if __name__ == '__main__':
diff --git a/gerbonara/gerber/aperture_macros/primitive.py b/gerbonara/gerber/aperture_macros/primitive.py
index aeb38c4..4d3e597 100644
--- a/gerbonara/gerber/aperture_macros/primitive.py
+++ b/gerbonara/gerber/aperture_macros/primitive.py
@@ -7,9 +7,9 @@
import contextlib
import math
-from expression import Expression, UnitExpression, ConstantExpression, expr
+from .expression import Expression, UnitExpression, ConstantExpression, expr
-from .. import graphic_primitivese as gp
+from .. import graphic_primitives as gp
def point_distance(a, b):
@@ -41,7 +41,7 @@ class Primitive:
raise ValueError(f'Too few arguments ({len(args)}) for aperture macro primitive {self.code} ({type(self)})')
def to_gerber(self, unit=None):
- return self.code + ',' + ','.join(
+ return f'{self.code},' + ','.join(
getattr(self, name).to_gerber(unit) for name in type(self).__annotations__) + '*'
def __str__(self):
@@ -149,6 +149,7 @@ class Polygon(Primitive):
class Thermal(Primitive):
code = 7
+ exposure : Expression
# center x/y
x : UnitExpression
y : UnitExpression
@@ -216,6 +217,8 @@ class Outline(Primitive):
class Comment:
+ code = 0
+
def __init__(self, comment):
self.comment = comment
@@ -233,6 +236,6 @@ PRIMITIVE_CLASSES = {
Thermal,
]},
# alternative codes
- 2: VectorLinePrimitive,
+ 2: VectorLine,
}