summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarret Fick <garret@ficksworkshop.com>2016-03-27 14:24:11 +0800
committerGarret Fick <garret@ficksworkshop.com>2016-03-27 14:24:11 +0800
commit288f49955ecc1a811752aa4b1e713f9954e3033b (patch)
tree5617650d75b731bb4ecf79e14bfcd777a452cd73
parent25515b8ec7016698431b74e5beac8ff2d6691f0b (diff)
downloadgerbonara-288f49955ecc1a811752aa4b1e713f9954e3033b.tar.gz
gerbonara-288f49955ecc1a811752aa4b1e713f9954e3033b.tar.bz2
gerbonara-288f49955ecc1a811752aa4b1e713f9954e3033b.zip
Actually fix the rout rendering to be correct
-rwxr-xr-xgerber/excellon.py10
-rw-r--r--gerber/excellon_statements.py8
-rw-r--r--gerber/render/excellon_backend.py98
3 files changed, 102 insertions, 14 deletions
diff --git a/gerber/excellon.py b/gerber/excellon.py
index 02709fd..72cf75c 100755
--- a/gerber/excellon.py
+++ b/gerber/excellon.py
@@ -111,10 +111,14 @@ class DrillSlot(object):
A slot is created between two points. The way the slot is created depends on the statement used to create it
"""
- def __init__(self, tool, start, end):
+ TYPE_ROUT = 1
+ TYPE_G85 = 2
+
+ def __init__(self, tool, start, end, slot_type):
self.tool = tool
self.start = start
self.end = end
+ self.slot_type = slot_type
def to_inch(self):
if self.tool.units == 'metric':
@@ -520,7 +524,7 @@ class ExcellonParser(object):
if not self.active_tool:
self.active_tool = self._get_tool(1)
- self.hits.append(DrillSlot(self.active_tool, start, end))
+ self.hits.append(DrillSlot(self.active_tool, start, end, DrillSlot.TYPE_ROUT))
self.active_tool._hit()
elif line[:3] == 'G05':
@@ -641,7 +645,7 @@ class ExcellonParser(object):
if not self.active_tool:
self.active_tool = self._get_tool(1)
- self.hits.append(DrillSlot(self.active_tool, (stmt.x_start, stmt.y_start), (stmt.x_end, stmt.y_end)))
+ self.hits.append(DrillSlot(self.active_tool, (stmt.x_start, stmt.y_start), (stmt.x_end, stmt.y_end), DrillSlot.TYPE_G85))
self.active_tool._hit()
else:
stmt = CoordinateStmt.from_excellon(line, self._settings())
diff --git a/gerber/excellon_statements.py b/gerber/excellon_statements.py
index a6a5a5e..c9367b4 100644
--- a/gerber/excellon_statements.py
+++ b/gerber/excellon_statements.py
@@ -367,8 +367,12 @@ class ZAxisInfeedRateStmt(ExcellonStatement):
class CoordinateStmt(ExcellonStatement):
@classmethod
- def from_point(cls, point):
- return cls(point[0], point[1])
+ def from_point(cls, point, mode=None):
+
+ stmt = cls(point[0], point[1])
+ if mode:
+ stmt.mode = mode
+ return stmt
@classmethod
def from_excellon(cls, line, settings, **kwargs):
diff --git a/gerber/render/excellon_backend.py b/gerber/render/excellon_backend.py
index eb79f1b..b2c213f 100644
--- a/gerber/render/excellon_backend.py
+++ b/gerber/render/excellon_backend.py
@@ -1,21 +1,29 @@
from .render import GerberContext
+from ..excellon import DrillSlot
from ..excellon_statements import *
class ExcellonContext(GerberContext):
+ MODE_DRILL = 1
+ MODE_SLOT =2
+
def __init__(self, settings):
GerberContext.__init__(self)
+
+ # Statements that we write
self.comments = []
self.header = []
self.tool_def = []
self.body_start = [RewindStopStmt()]
self.body = []
self.start = [HeaderBeginStmt()]
- self.end = [EndOfProgramStmt()]
+ # Current tool and position
self.handled_tools = set()
self.cur_tool = None
+ self.drill_mode = ExcellonContext.MODE_DRILL
+ self.drill_down = False
self._pos = (None, None)
self.settings = settings
@@ -33,9 +41,22 @@ class ExcellonContext(GerberContext):
# Write the digits used - this isn't valid Excellon statement, so we write as a comment
self.comments.append(CommentStmt('FILE_FORMAT=%d:%d' % (self.settings.format[0], self.settings.format[1])))
+ def _get_end(self):
+ """How we end depends on our mode"""
+
+ end = []
+
+ if self.drill_down:
+ end.append(RetractWithClampingStmt())
+ end.append(RetractWithoutClampingStmt())
+
+ end.append(EndOfProgramStmt())
+
+ return end
+
@property
def statements(self):
- return self.start + self.comments + self.header + self.body_start + self.body + self.end
+ return self.start + self.comments + self.header + self.body_start + self.body + self._get_end()
def set_bounds(self, bounds):
pass
@@ -71,6 +92,9 @@ class ExcellonContext(GerberContext):
def _render_drill(self, drill, color):
+ if self.drill_mode != ExcellonContext.MODE_DRILL:
+ self._start_drill_mode()
+
tool = drill.hit.tool
if not tool in self.handled_tools:
self.handled_tools.add(tool)
@@ -84,20 +108,76 @@ class ExcellonContext(GerberContext):
self._pos = drill.position
self.body.append(CoordinateStmt.from_point(point))
+ def _start_drill_mode(self):
+ """
+ If we are not in drill mode, then end the ROUT so we can do basic drilling
+ """
+
+ if self.drill_mode == ExcellonContext.MODE_SLOT:
+
+ # Make sure we are retracted before changing modes
+ last_cmd = self.body[-1]
+ if self.drill_down:
+ self.body.append(RetractWithClampingStmt())
+ self.body.append(RetractWithoutClampingStmt())
+ self.drill_down = False
+
+ # Switch to drill mode
+ self.body.append(DrillModeStmt())
+ self.drill_mode = ExcellonContext.MODE_DRILL
+
+ else:
+ raise ValueError('Should be in slot mode')
+
def _render_slot(self, slot, color):
+ # Set the tool first, before we might go into drill mode
tool = slot.hit.tool
if not tool in self.handled_tools:
self.handled_tools.add(tool)
self.header.append(ExcellonTool.from_tool(tool))
-
- if tool != self.cur_tool:
- self.body.append(ToolSelectionStmt(tool.number))
- self.cur_tool = tool
- # Slots don't use simplified points
- self._pos = slot.end
- self.body.append(SlotStmt.from_points(slot.start, slot.end))
+ if tool != self.cur_tool:
+ self.body.append(ToolSelectionStmt(tool.number))
+ self.cur_tool = tool
+
+ # Two types of drilling - normal drill and slots
+ if slot.hit.slot_type == DrillSlot.TYPE_ROUT:
+
+ # For ROUT, setting the mode is part of the actual command.
+
+ # Are we in the right position?
+ if slot.start != self._pos:
+ if self.drill_down:
+ # We need to move into the right position, so retract
+ self.body.append(RetractWithClampingStmt())
+ self.drill_down = False
+
+ # Move to the right spot
+ point = self._simplify_point(slot.start)
+ self._pos = slot.start
+ self.body.append(CoordinateStmt.from_point(point, mode="ROUT"))
+
+ # Now we are in the right spot, so drill down
+ if not self.drill_down:
+ self.body.append(ZAxisRoutPositionStmt())
+ self.drill_down = True
+
+ # Do a linear move from our current position to the end position
+ point = self._simplify_point(slot.end)
+ self._pos = slot.end
+ self.body.append(CoordinateStmt.from_point(point, mode="LINEAR"))
+
+ self.drill_down = ExcellonContext.MODE_SLOT
+
+ else:
+ # This is a G85 slot, so do this in normally drilling mode
+ if self.drill_mode != ExcellonContext.MODE_DRILL:
+ self._start_drill_mode()
+
+ # Slots don't use simplified points
+ self._pos = slot.end
+ self.body.append(SlotStmt.from_points(slot.start, slot.end))
def _render_inverted_layer(self):
pass