summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gerber/am_statements.py83
-rw-r--r--gerber/primitives.py5
2 files changed, 84 insertions, 4 deletions
diff --git a/gerber/am_statements.py b/gerber/am_statements.py
index b448139..2bca6e6 100644
--- a/gerber/am_statements.py
+++ b/gerber/am_statements.py
@@ -19,6 +19,7 @@
import math
from .utils import validate_coordinates, inch, metric, rotate_point
from .primitives import Circle, Line, Outline, Polygon, Rectangle
+from math import asin
# TODO: Add support for aperture macro variables
@@ -649,9 +650,10 @@ class AMThermalPrimitive(AMPrimitive):
outer_diameter = float(modifiers[3])
inner_diameter= float(modifiers[4])
gap = float(modifiers[5])
- return cls(code, position, outer_diameter, inner_diameter, gap)
+ rotation = float(modifiers[6])
+ return cls(code, position, outer_diameter, inner_diameter, gap, rotation)
- def __init__(self, code, position, outer_diameter, inner_diameter, gap):
+ def __init__(self, code, position, outer_diameter, inner_diameter, gap, rotation):
if code != 7:
raise ValueError('ThermalPrimitive code is 7')
super(AMThermalPrimitive, self).__init__(code, 'on')
@@ -660,6 +662,7 @@ class AMThermalPrimitive(AMPrimitive):
self.outer_diameter = outer_diameter
self.inner_diameter = inner_diameter
self.gap = gap
+ self.rotation = rotation
def to_inch(self):
self.position = tuple([inch(x) for x in self.position])
@@ -684,9 +687,83 @@ class AMThermalPrimitive(AMPrimitive):
)
fmt = "{code},{position},{outer_diameter},{inner_diameter},{gap}*"
return fmt.format(**data)
+
+ def _approximate_arc_cw(self, start_angle, end_angle, radius, center):
+ """
+ Get an arc as a series of points
+
+ Parameters
+ ----------
+ start_angle : The start angle in radians
+ end_angle : The end angle in radians
+ radius`: Radius of the arc
+ center : The center point of the arc (x, y) tuple
+
+ Returns
+ -------
+ array of point tuples
+ """
+
+ # The total sweep
+ sweep_angle = end_angle - start_angle
+ num_steps = 10
+
+ angle_step = sweep_angle / num_steps
+
+ radius = radius
+ center = center
+
+ points = []
+
+ for i in range(num_steps + 1):
+ current_angle = start_angle + (angle_step * i)
+
+ nextx = (center[0] + math.cos(current_angle) * radius)
+ nexty = (center[1] + math.sin(current_angle) * radius)
+
+ points.append((nextx, nexty))
+
+ return points
def to_primitive(self, units):
- raise NotImplementedError()
+
+ # We start with calculating the top right section, then duplicate it
+
+ inner_radius = self.inner_diameter / 2.0
+ outer_radius = self.outer_diameter / 2.0
+
+ # Calculate the start angle relative to the horizontal axis
+ inner_offset_angle = asin(self.gap / 2.0 / inner_radius)
+ outer_offset_angle = asin(self.gap / 2.0 / outer_radius)
+
+ rotation_rad = math.radians(self.rotation)
+ inner_start_angle = inner_offset_angle + rotation_rad
+ inner_end_angle = math.pi / 2 - inner_offset_angle + rotation_rad
+
+ outer_start_angle = outer_offset_angle + rotation_rad
+ outer_end_angle = math.pi / 2 - outer_offset_angle + rotation_rad
+
+ outlines = []
+ aperture = Circle((0, 0), 0)
+
+ points = (self._approximate_arc_cw(inner_start_angle, inner_end_angle, inner_radius, self.position)
+ + list(reversed(self._approximate_arc_cw(outer_start_angle, outer_end_angle, outer_radius, self.position))))
+
+ # There are four outlines at rotated sections
+ for rotation in [0, 90.0, 180.0, 270.0]:
+
+ lines = []
+ prev_point = rotate_point(points[0], rotation, self.position)
+ for point in points[1:]:
+ cur_point = rotate_point(point, rotation, self.position)
+
+ lines.append(Line(prev_point, cur_point, aperture))
+
+ prev_point = cur_point
+
+ outlines.append(Outline(lines, units=units))
+
+ return outlines
class AMCenterLinePrimitive(AMPrimitive):
diff --git a/gerber/primitives.py b/gerber/primitives.py
index 944e34a..84115a6 100644
--- a/gerber/primitives.py
+++ b/gerber/primitives.py
@@ -730,7 +730,10 @@ class AMGroup(Primitive):
self.primitives = []
for amprim in amprimitives:
prim = amprim.to_primitive(self.units)
- if prim:
+ if isinstance(prim, list):
+ for p in prim:
+ self.primitives.append(p)
+ elif prim:
self.primitives.append(prim)
self._position = None
self._to_convert = ['arimitives']