From 6b4603af21839c94a33d3804c364ff1b809eb341 Mon Sep 17 00:00:00 2001 From: opiopan Date: Wed, 3 Apr 2019 12:17:59 +0900 Subject: add rectangle generator --- gerberex/__init__.py | 4 +-- gerberex/common.py | 5 ++++ gerberex/dxf.py | 82 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/gerberex/__init__.py b/gerberex/__init__.py index cef11ab..f379c1c 100644 --- a/gerberex/__init__.py +++ b/gerberex/__init__.py @@ -10,6 +10,6 @@ gerber-tools-extension is a extention package for gerber-tools. This package provide panelizing of PCB fucntion. """ -from gerberex.common import (read, loads) -from gerberex.composition import (GerberComposition, DrillComposition) +from gerberex.common import read, loads, rectangle +from gerberex.composition import GerberComposition, DrillComposition from gerberex.dxf import DxfFile diff --git a/gerberex/common.py b/gerberex/common.py index 4a85bd4..47bc6b3 100644 --- a/gerberex/common.py +++ b/gerberex/common.py @@ -33,3 +33,8 @@ def loads(data, filename=None, format=None): return ipc356.loads(data, filename=filename) else: raise ParseError('Unable to detect file format') + + +def rectangle(width, height, left=0, bottom=0, units='metric', draw_mode=None, filename=None): + return gerberex.dxf.DxfFile.rectangle( + width, height, left, bottom, units, draw_mode, filename) diff --git a/gerberex/dxf.py b/gerberex/dxf.py index 39d256b..9a2186c 100644 --- a/gerberex/dxf.py +++ b/gerberex/dxf.py @@ -42,10 +42,16 @@ class DxfStatement(object): raise Exception('Not implemented') class DxfLineStatement(DxfStatement): - def __init__(self, entity): + @classmethod + def from_entity(cls, entity): + start = (entity.start[0], entity.start[1]) + end = (entity.end[0], entity.end[1]) + return cls(entity, start, end) + + def __init__(self, entity, start, end): super(DxfLineStatement, self).__init__(entity) - self.start = (self.entity.start[0], self.entity.start[1]) - self.end = (self.entity.end[0], self.entity.end[1]) + self.start = start + self.end = end def to_gerber(self, settings=FileSettings(), pitch=0, width=0): if pitch == 0: @@ -329,7 +335,7 @@ class DxfPolylineStatement(DxfStatement): self.entity.bulge[idx] = metric(self.entity.bulge[idx]) class DxfStatements(object): - def __init__(self, entities, units, dcode=10, draw_mode=None): + def __init__(self, statements, units, dcode=10, draw_mode=None): if draw_mode == None: draw_mode = DxfFile.DM_LINE self._units = units @@ -338,16 +344,7 @@ class DxfStatements(object): self.pitch = inch(1) if self._units == 'inch' else 1 self.width = 0 self.error_range = inch(ACCEPTABLE_ERROR) if self._units == 'inch' else ACCEPTABLE_ERROR - self.statements = [] - for entity in entities: - if entity.dxftype == 'LWPOLYLINE': - self.statements.append(DxfPolylineStatement(entity)) - elif entity.dxftype == 'LINE': - self.statements.append(DxfLineStatement(entity)) - elif entity.dxftype == 'CIRCLE': - self.statements.append(DxfCircleStatement(entity)) - elif entity.dxftype == 'ARC': - self.statements.append(DxfArcStatement(entity)) + self.statements = statements self.paths = generate_closed_paths(self.statements, self.error_range) @property @@ -458,18 +455,52 @@ class DxfFile(CamFile): FT_RX274X = 0 FT_EXCELLON = 1 - def __init__(self, dxf, settings=None, draw_mode=None, filename=None): - if not settings: - settings = FileSettings(zero_suppression='leading') + @classmethod + def from_dxf(cls, dxf, settings=None, draw_mode=None, filename=None): + fsettings = settings if settings else \ + FileSettings(zero_suppression='leading') - if draw_mode == None: - draw_mode = self.DM_LINE if dxf.header['$INSUNITS'] == 1: - settings.units = 'inch' - settings.format = (2, 5) + fsettings.units = 'inch' + if not settings: + fsettings.format = (2, 5) + else: + fsettings.units = 'metric' + if not settings: + fsettings.format = (3, 4) + + statements = [] + for entity in dxf.entities: + if entity.dxftype == 'LWPOLYLINE': + statements.append(DxfPolylineStatement(entity)) + elif entity.dxftype == 'LINE': + statements.append(DxfLineStatement.from_entity(entity)) + elif entity.dxftype == 'CIRCLE': + statements.append(DxfCircleStatement(entity)) + elif entity.dxftype == 'ARC': + statements.append(DxfArcStatement(entity)) + + return cls(statements, fsettings, draw_mode, filename) + + @classmethod + def rectangle(cls, width, height, left=0, bottom=0, units='metric', draw_mode=None, filename=None): + if units == 'metric': + settings = FileSettings(units=units, zero_suppression='leading', format=(3,4)) else: - settings.units = 'metric' - settings.format = (3, 4) + settings = FileSettings(units=units, zero_suppression='leading', format=(2,5)) + statements = [ + DxfLineStatement(None, (left, bottom), (left + width, bottom)), + DxfLineStatement(None, (left + width, bottom), (left + width, bottom + height)), + DxfLineStatement(None, (left + width, bottom + height), (left, bottom + height)), + DxfLineStatement(None, (left, bottom + height), (left, bottom)), + ] + return cls(statements, settings, draw_mode, filename) + + def __init__(self, statements, settings=None, draw_mode=None, filename=None): + if not settings: + settings = FileSettings(units='metric', format=(3,4), zero_suppression='leading') + if draw_mode == None: + draw_mode = self.DM_LINE super(DxfFile, self).__init__(settings=settings, filename=filename) self._draw_mode = draw_mode @@ -477,7 +508,8 @@ class DxfFile(CamFile): self.header2 = DxfHeader2Statement() self.aperture = ADParamStmt.circle(dcode=10, diameter=0.0) - self.statements = DxfStatements(dxf.entities, self.units, dcode=self.aperture.d, draw_mode=self.draw_mode) + self.statements = DxfStatements( + statements, self.units, dcode=self.aperture.d, draw_mode=self.draw_mode) @property def dcode(self): @@ -559,4 +591,4 @@ def loads(data, filename=None): data = unicode(data) stream = io.StringIO(data) dxf = dxfgrabber.read(stream) - return DxfFile(dxf) + return DxfFile.from_dxf(dxf) -- cgit