diff options
-rw-r--r-- | README.md | 39 | ||||
-rw-r--r-- | gerberex/composition.py | 22 | ||||
-rw-r--r-- | gerberex/dxf.py | 205 | ||||
-rw-r--r-- | test/data/base.txt | 370 | ||||
-rw-r--r-- | test/data/fill3.dxf | 552 | ||||
-rw-r--r-- | test/data/mousebite.dxf | 344 | ||||
-rw-r--r-- | test/data/mousebites.dxf | 652 | ||||
-rw-r--r-- | test/outline.GML | 626 | ||||
-rwxr-xr-x | test/test.py | 25 |
9 files changed, 2786 insertions, 49 deletions
@@ -1,9 +1,9 @@ -PCB tools extension +pcb-tools-extension === -PCB tools extension is a Python library to panelize gerber files. -This library is designed based on [PCB tools](https://github.com/curtacircuitos/pcb-tools) which provides cool functionality to handle PCB such as generationg PCB image from gerber files. +pcb-tools-extension is a Python library to panelize gerber files. +This library is designed based on [pcb-tools](https://github.com/curtacircuitos/pcb-tools) which provides cool functionality to handle PCB such as generationg PCB image from gerber files. -PCB tools extension adds following function to PCB tools. +pcb-tools-extension adds following function to pcb-tools. - Rotate PCB data - Write back loded PCB data (original PCB tools does not work completely) @@ -13,7 +13,7 @@ PCB tools extension adds following function to PCB tools. Only RS-274x format and Excellon drill format data can be handled by current version of this library. ## Install -PCB tools extension is not registerd to PyPI repository.<br> +pcb-tools-extension is not registerd to PyPI repository.<br> Please install from GitHub repository as below. ```shell $ pip install git+https://github.com/opiopan/pcb-tools-extension @@ -62,6 +62,8 @@ ctx.dump('panelized-board.txt') ``` ## DXF file translation + +### PCB Outline You can also load a dxf file and handle that as same as RX-274x gerber file.<br> This function is useful to generate outline data of pnanelized PCB boad. @@ -96,8 +98,33 @@ dxf.draw_mode = gerberex.DxfFile.DM_FILL dxf.write('outline.gml') ``` +### Mouse bites + +<img alt="mouse bites" src="https://raw.githubusercontent.com/wiki/opiopan/pcb-tools-extension/images/mousebites.png" width=200 align="right"> + + +If ```DM_MOUSE_BITES``` is specified for ```drawing_mode```, filled circles will arranged along a DXF line object at equal intervals. <br> +DXF file object in this state can be merged to excellon file also. That means you can arrange mouse bites easily. + +```python +import gerberex + +ctx = gerberex.DrillComposition() +drill = gerberex.read('drill.txt') +ctx.merge(drill) + +dxf = gerberex.read('mousebites.dxf') +dxf.draw_mode = gerberex.DxfFile.DM_MOUSE_BITES +dxf.to_metric() +dxf.width = 0.5 +dxf.pitch = 1 +ctx.merge(dxf) + +ctx.dump('merged_drill.txt') +``` + ## Panelized board image Example -This image is generated by original [PCB tools](https://github.com/curtacircuitos/pcb-tools) fucntion. +This image is generated by original [pcb-tools](https://github.com/curtacircuitos/pcb-tools) fucntion. <p align="center"> <img alt="description" src="https://raw.githubusercontent.com/wiki/opiopan/pcb-tools-extension/images/panelized.jpg" width=750> diff --git a/gerberex/composition.py b/gerberex/composition.py index afcaf97..73f5702 100644 --- a/gerberex/composition.py +++ b/gerberex/composition.py @@ -127,10 +127,13 @@ class DrillComposition(Composition): self.header2_statements = [] self.tools = [] self.hits = [] + self.dxf_statements = [] def merge(self, file): if isinstance(file, gerberex.excellon.ExcellonFileEx): self._merge_excellon(file) + elif isinstance(file, gerberex.DxfFile): + self._merge_dxf(file) else: raise Exception('unsupported file type') @@ -147,6 +150,9 @@ class DrillComposition(Composition): for h in self.hits: if h.tool.number == t.number: yield CoordinateStmt(*h.position).to_excellon(self.settings) + for num, statement in self.dxf_statements: + if num == t.number: + yield statement.to_excellon(self.settings) yield EndOfProgramStmt().to_excellon() with open(path, 'w') as f: @@ -186,6 +192,22 @@ class DrillComposition(Composition): hit.tool = tool_map[hit.tool.number] self.hits.append(hit) + def _merge_dxf(self, file): + if not self.settings: + self.settings = file.settings + else: + if self.settings.units == 'metric': + file.to_metric() + else: + file.to_inch() + + if not self.header1_statements: + self.header1_statements = file.header + self.header2_statements = file.header2 + + tool = self._register_tool(ExcellonTool(self.settings, number=1, diameter=file.width)) + self.dxf_statements.append((tool.number, file.statements)) + def _register_tool(self, tool): for existing in self.tools: if existing.equivalent(tool): diff --git a/gerberex/dxf.py b/gerberex/dxf.py index 11072b5..a2c26d0 100644 --- a/gerberex/dxf.py +++ b/gerberex/dxf.py @@ -8,13 +8,18 @@ from math import pi, cos, sin, tan, atan, atan2, acos, asin, sqrt from gerber.cam import CamFile, FileSettings from gerber.utils import inch, metric, write_gerber_value from gerber.gerber_statements import ADParamStmt +from gerber.excellon_statements import ExcellonTool +from gerber.excellon_statements import CoordinateStmt import dxfgrabber class DxfStatement(object): def __init__(self, entity): self.entity = entity - def to_gerber(self, settings=None): + def to_gerber(self, settings=None, pitch=0, width=0): + pass + + def to_excellon(self, settings=None, pitch=0, width=0): pass def to_inch(self): @@ -27,39 +32,77 @@ class DxfLineStatement(DxfStatement): def __init__(self, entity): super(DxfLineStatement, self).__init__(entity) - def to_gerber(self, settings=FileSettings): - x0 = self.entity.start[0] - y0 = self.entity.start[1] - x1 = self.entity.end[0] - y1 = self.entity.end[1] - return 'G01*\nX{0}Y{1}D02*\nX{2}Y{3}D01*'.format( - write_gerber_value(x0, settings.format, - settings.zero_suppression), - write_gerber_value(y0, settings.format, - settings.zero_suppression), - write_gerber_value(x1, settings.format, - settings.zero_suppression), - write_gerber_value(y1, settings.format, - settings.zero_suppression) - ) + def to_gerber(self, settings=FileSettings(), pitch=0, width=0): + if pitch == 0: + x0 = self.entity.start[0] + y0 = self.entity.start[1] + x1 = self.entity.end[0] + y1 = self.entity.end[1] + return 'G01*\nX{0}Y{1}D02*\nX{2}Y{3}D01*'.format( + write_gerber_value(x0, settings.format, + settings.zero_suppression), + write_gerber_value(y0, settings.format, + settings.zero_suppression), + write_gerber_value(x1, settings.format, + settings.zero_suppression), + write_gerber_value(y1, settings.format, + settings.zero_suppression) + ) + else: + gstr = "" + for p in self._dots(pitch, width): + gstr += 'X{0}Y{1}D03*\n'.format( + write_gerber_value(p[0], settings.format, + settings.zero_suppression), + write_gerber_value(p[1], settings.format, + settings.zero_suppression)) + return gstr + + def to_excellon(self, settings=FileSettings(), pitch=0, width=0): + if not pitch: + return + gstr = "" + for p in self._dots(pitch, width): + gstr += CoordinateStmt(x=p[0], y=p[1]).to_excellon(settings) + '\n' + return gstr def to_inch(self): - self.entity.start[idx] = ( - inch(self.entity.start[idx][0]), inch(self.entity.start[idx][1])) - self.entity.end[idx] = ( - inch(self.entity.end[idx][0]), inch(self.entity.end[idx][1])) + self.entity.start = ( + inch(self.entity.start[0]), inch(self.entity.start[1])) + self.entity.end = ( + inch(self.entity.end[0]), inch(self.entity.end[1])) def to_metric(self): - self.entity.start[idx] = ( - metric(self.entity.start[idx][0]), inch(self.entity.start[idx][1])) - self.entity.end[idx] = ( - metric(self.entity.end[idx][0]), inch(self.entity.end[idx][1])) + self.entity.start = ( + metric(self.entity.start[0]), inch(self.entity.start[1])) + self.entity.end = ( + metric(self.entity.end[0]), inch(self.entity.end[1])) + + def _dots(self, pitch, width): + x0 = self.entity.start[0] + y0 = self.entity.start[1] + x1 = self.entity.end[0] + y1 = self.entity.end[1] + xp = x1 - x0 + yp = y1 - y0 + l = sqrt(xp * xp + yp * yp) + xd = xp * pitch / l + yd = yp * pitch / l + + d = 0; + while d < l + width / 2: + yield (x0, y0) + x0 += xd + y0 += yd + d += pitch class DxfCircleStatement(DxfStatement): def __init__(self, entity): super(DxfCircleStatement, self).__init__(entity) - def to_gerber(self, settings=FileSettings): + def to_gerber(self, settings=FileSettings(), pitch=0, width=0): + if pitch: + return r = self.entity.radius x0 = self.entity.center[0] y0 = self.entity.center[1] @@ -82,19 +125,21 @@ class DxfCircleStatement(DxfStatement): def to_inch(self): self.entity.radius = inch(self.entity.radius) - self.entity.center[idx] = ( - inch(self.entity.center[idx][0]), inch(self.entity.center[idx][1])) + self.entity.center = ( + inch(self.entity.center[0]), inch(self.entity.center[1])) def to_metric(self): self.entity.radius = metric(self.entity.radius) - self.entity.center[idx] = ( - metric(self.entity.center[idx][0]), metric(self.entity.center[idx][1])) + self.entity.center = ( + metric(self.entity.center[0]), metric(self.entity.center[1])) class DxfArcStatement(DxfStatement): def __init__(self, entity): super(DxfArcStatement, self).__init__(entity) - def to_gerber(self, settings=FileSettings): + def to_gerber(self, settings=FileSettings(), pitch=0, width=0): + if pitch: + return deg0 = self.entity.start_angle deg1 = self.entity.end_angle r = self.entity.radius @@ -126,21 +171,23 @@ class DxfArcStatement(DxfStatement): self.entity.start_angle = inch(self.entity.start_angle) self.entity.end_angle = inch(self.entity.end_angle) self.entity.radius = inch(self.entity.radius) - self.entity.center[idx] = ( - inch(self.entity.center[idx][0]), inch(self.entity.center[idx][1])) + self.entity.center = ( + inch(self.entity.center[0]), inch(self.entity.center[1])) def to_metric(self): self.entity.start_angle = metric(self.entity.start_angle) self.entity.end_angle = metric(self.entity.end_angle) self.entity.radius = metric(self.entity.radius) - self.entity.center[idx] = ( - metric(self.entity.center[idx][0]), metric(self.entity.center[idx][1])) + self.entity.center = ( + metric(self.entity.center[0]), metric(self.entity.center[1])) class DxfPolylineStatement(DxfStatement): def __init__(self, entity): super(DxfPolylineStatement, self).__init__(entity) - def to_gerber(self, settings=FileSettings()): + def to_gerber(self, settings=FileSettings(), pitch=0, width=0): + if pitch: + return x0 = self.entity.points[0][0] y0 = self.entity.points[0][1] b = self.entity.bulge[0] @@ -214,6 +261,8 @@ class DxfStatements(object): self._units = units self.dcode = dcode self.draw_mode = draw_mode + self.pitch = inch(1) if self._units == 'unit' else 1 + self.width = 0 self.statements = [] for entity in entities: if entity.dxftype == 'LWPOLYLINE': @@ -241,19 +290,33 @@ class DxfStatements(object): yield 'G37*' else: for statement in self.statements: - yield statement.to_gerber(settings) + yield statement.to_gerber( + settings, + pitch=self.pitch if self.draw_mode == DxfFile.DM_MOUSE_BITES else 0, + width=self.width) return '\n'.join(gerbers()) + def to_excellon(self, settings=FileSettings()): + if not self.draw_mode == DxfFile.DM_MOUSE_BITES: + return + def drills(): + for statement in self.statements: + if isinstance(statement, DxfLineStatement): + yield statement.to_excellon(settings, pitch=self.pitch, width=self.width) + return '\n'.join(drills()) + def to_inch(self): if self._units == 'metric': self._units = 'inch' + self.pitch = inch(self.pitch) for statement in self.statements: statement.to_inch() def to_metric(self): if self._units == 'inch': self._units = 'metric' + self.pitch = metric(self.pitch) for statement in self.statements: statement.to_metric() @@ -270,6 +333,32 @@ class DxfHeaderStatement(object): settings.format[0], settings.format[1], settings.format[0], settings.format[1] ) + + def to_excellon(self, settings): + return 'M48\n'\ + 'FMAT,2\n'\ + 'ICI,{0}\n'\ + '{1},{2},{3}.{4}\n'\ + '{5}'.format( + 'ON' if settings.notation == 'incremental' else 'OFF', + 'INCH' if settings.units == 'inch' else 'METRIC', + 'TZ' if settings.zero_suppression == 'leading' else 'LZ', + '0' * settings.format[0], '0' * settings.format[1], + 'M72' if settings.units == 'inch' else 'M71' + ) + + def to_inch(self): + pass + + def to_metric(self): + pass + +class DxfHeader2Statement(object): + def to_gerber(self, settings): + pass + + def to_excellon(self, settings): + return '%' def to_inch(self): pass @@ -280,8 +369,15 @@ class DxfHeaderStatement(object): class DxfFile(CamFile): DM_LINE = 0 DM_FILL = 1 + DM_MOUSE_BITES = 2 + + 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') - def __init__(self, dxf, settings=FileSettings(), draw_mode=None, filename=None): if draw_mode == None: draw_mode = self.DM_LINE if dxf.header['$INSUNITS'] == 1: @@ -294,6 +390,8 @@ class DxfFile(CamFile): super(DxfFile, self).__init__(settings=settings, filename=filename) self._draw_mode = draw_mode self.header = DxfHeaderStatement() + + 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) @@ -313,6 +411,7 @@ class DxfFile(CamFile): @width.setter def width(self, value): self.aperture.modifiers = ([float(value),],) + self.statements.width = value @property def draw_mode(self): @@ -322,23 +421,42 @@ class DxfFile(CamFile): def draw_mode(self, value): self._draw_mode = value self.statements.draw_mode = value + + @property + def pitch(self): + return self.statements.pitch - def write(self, filename=None): + @pitch.setter + def pitch(self, value): + self.statements.pitch = value + + def write(self, filename=None, filetype=FT_RX274X): if self.settings.notation != 'absolute': raise Exception('DXF file\'s notation must be absolute ') - + filename = filename if filename is not None else self.filename with open(filename, 'w') as f: - f.write(self.header.to_gerber(self.settings) + '\n') - f.write(self.aperture.to_gerber(self.settings) + '\n') - f.write(self.statements.to_gerber(self.settings) + '\n') - f.write('M02*\n') + if filetype == self.FT_RX274X: + f.write(self.header.to_gerber(self.settings) + '\n') + f.write(self.aperture.to_gerber(self.settings) + '\n') + f.write(self.statements.to_gerber(self.settings) + '\n') + f.write('M02*\n') + else: + tool = ExcellonTool(self.settings, number=1, diameter=self.width) + f.write(self.header.to_excellon(self.settings) + '\n') + f.write(tool.to_excellon(self.settings) + '\n') + f.write(self.header2.to_excellon(self.settings) + '\n') + f.write('T01\n') + f.write(self.statements.to_excellon(self.settings) + '\n') + f.write('M30\n') + def to_inch(self): if self.units == 'metric': self.header.to_inch() self.aperture.to_inch() self.statements.to_inch() + self.pitch = inch(self.pitch) self.units = 'inch' def to_metric(self): @@ -346,6 +464,7 @@ class DxfFile(CamFile): self.header.to_metric() self.aperture.to_metric() self.statements.to_metric() + self.pitch = metric(self.pitch) self.units = 'metric' def offset(self, ofset_x, offset_y): diff --git a/test/data/base.txt b/test/data/base.txt new file mode 100644 index 0000000..726db40 --- /dev/null +++ b/test/data/base.txt @@ -0,0 +1,370 @@ +M48 +;GenerationSoftware,Autodesk,EAGLE,9.3.0*% +;CreationDate,2019-03-17T12:32:03Z*% +FMAT,2 +ICI,OFF +METRIC,TZ,000.000 +T01C0.350 +T02C0.850 +T03C1.000 +T04C1.150 +T05C2.750 +T06C0.508 +T07C0.800 +T08C0.930 +T09C1.200 +T10C0.400 +T11C0.500 +% +G90 +M71 +T01 +X40640Y8509 +X39243Y8509 +X35306Y8509 +X36576Y8509 +X37846Y8509 +X15748Y12700 +X17018Y12192 +X17018Y13462 +X19558Y12192 +X19558Y13462 +X18288Y12700 +X22098Y12192 +X22098Y13462 +X20828Y12700 +X23368Y12700 +X29718Y7620 +X29083Y8890 +X28448Y7620 +X27178Y7620 +X27813Y8890 +X28448Y10160 +X27178Y10160 +X27178Y11430 +X42164Y8509 +X34036Y8509 +X40640Y31009 +X39243Y31009 +X35306Y31009 +X36576Y31009 +X37846Y31009 +X15748Y35200 +X17018Y34692 +X17018Y35962 +X19558Y34692 +X19558Y35962 +X18288Y35200 +X22098Y34692 +X22098Y35962 +X20828Y35200 +X23368Y35200 +X29718Y30120 +X29083Y31390 +X28448Y30120 +X27178Y30120 +X27813Y31390 +X28448Y32660 +X27178Y32660 +X27178Y33930 +X42164Y31009 +X34036Y31009 +X4191Y75113 +X11557Y75494 +X7747Y77018 +X7747Y69017 +X4064Y87178 +X7112Y87178 +X8890Y86035 +X1651Y84892 +X6096Y82479 +X12700Y78796 +X13335Y78161 +X7747Y82225 +X7112Y83907 +X14450Y94250 +X24191Y75113 +X31557Y75494 +X27747Y77018 +X27747Y69017 +X24064Y87178 +X27112Y87178 +X28890Y86035 +X21651Y84892 +X26096Y82479 +X32700Y78796 +X33335Y78161 +X27747Y82225 +X27112Y83907 +X34450Y94250 +X44191Y75113 +X51557Y75494 +X47747Y77018 +X47747Y69017 +X44064Y87178 +X47112Y87178 +X48890Y86035 +X41651Y84892 +X46096Y82479 +X52700Y78796 +X53335Y78161 +X47747Y82225 +X47112Y83907 +X54450Y94250 +X85979Y27680 +X91725Y27275 +X88194Y31940 +X93028Y30858 +X87811Y26069 +X83184Y31830 +X69618Y77521 +X65808Y80442 +X65173Y79680 +X68602Y93904 +X69618Y93904 +X70761Y77394 +X69999Y76505 +X91618Y77521 +X87808Y80442 +X87173Y79680 +X90602Y93904 +X91618Y93904 +X92761Y77394 +X91999Y76505 +T02 +X11095Y5667 +X11095Y8207 +X11095Y10747 +X11095Y28167 +X11095Y30707 +X11095Y33247 +T03 +X56630Y18070 +X15990Y15530 +X56630Y15530 +X54090Y18070 +X54090Y15530 +X51550Y18070 +X51550Y15530 +X49010Y18070 +X49010Y15530 +X46470Y18070 +X46470Y15530 +X43930Y18070 +X43930Y15530 +X41390Y18070 +X41390Y15530 +X38850Y18070 +X38850Y15530 +X36310Y18070 +X36310Y15530 +X33770Y18070 +X33770Y15530 +X31230Y18070 +X31230Y15530 +X26150Y15530 +X23610Y18070 +X23610Y15530 +X28690Y18070 +X13450Y15530 +X8370Y15530 +X8370Y18070 +X10910Y15530 +X10910Y18070 +X28690Y15530 +X13450Y18070 +X26150Y18070 +X15990Y18070 +X18530Y15530 +X18530Y18070 +X21070Y15530 +X21070Y18070 +X56630Y40570 +X15990Y38030 +X56630Y38030 +X54090Y40570 +X54090Y38030 +X51550Y40570 +X51550Y38030 +X49010Y40570 +X49010Y38030 +X46470Y40570 +X46470Y38030 +X43930Y40570 +X43930Y38030 +X41390Y40570 +X41390Y38030 +X38850Y40570 +X38850Y38030 +X36310Y40570 +X36310Y38030 +X33770Y40570 +X33770Y38030 +X31230Y40570 +X31230Y38030 +X26150Y38030 +X23610Y40570 +X23610Y38030 +X28690Y40570 +X13450Y38030 +X8370Y38030 +X8370Y40570 +X10910Y38030 +X10910Y40570 +X28690Y38030 +X13450Y40570 +X26150Y40570 +X15990Y40570 +X18530Y38030 +X18530Y40570 +X21070Y38030 +X21070Y40570 +X90676Y52237 +X91118Y49736 +X91559Y47234 +X92000Y44733 +X2286Y50985 +X4826Y50985 +X7366Y50985 +X9906Y50985 +X72920Y60630 +X61490Y98730 +X70380Y60630 +X67840Y60630 +X65300Y60630 +X76730Y96190 +X61490Y60630 +X76730Y60630 +X76730Y63170 +X76730Y65710 +X76730Y68250 +X76730Y70790 +X76730Y73330 +X76730Y75870 +X76730Y78410 +X76730Y80950 +X76730Y83490 +X76730Y86030 +X76730Y88570 +X76730Y91110 +X76730Y93650 +X61490Y63170 +X76730Y98730 +X61490Y65710 +X61490Y96190 +X61490Y93650 +X61490Y91110 +X61490Y88570 +X61490Y86030 +X61490Y83490 +X61490Y80950 +X61490Y78410 +X61490Y75870 +X61490Y73330 +X61490Y70790 +X61490Y68250 +X94920Y60630 +X83490Y98730 +X92380Y60630 +X89840Y60630 +X87300Y60630 +X98730Y96190 +X83490Y60630 +X98730Y60630 +X98730Y63170 +X98730Y65710 +X98730Y68250 +X98730Y70790 +X98730Y73330 +X98730Y75870 +X98730Y78410 +X98730Y80950 +X98730Y83490 +X98730Y86030 +X98730Y88570 +X98730Y91110 +X98730Y93650 +X83490Y63170 +X98730Y98730 +X83490Y65710 +X83490Y96190 +X83490Y93650 +X83490Y91110 +X83490Y88570 +X83490Y86030 +X83490Y83490 +X83490Y80950 +X83490Y78410 +X83490Y75870 +X83490Y73330 +X83490Y70790 +X83490Y68250 +T04 +X8465Y5667 +X8465Y10747 +X8465Y28167 +X8465Y33247 +T05 +X61500Y16800 +X3500Y16800 +X61500Y39300 +X3500Y39300 +T06 +X2062Y66253 +X2062Y67503 +X2062Y68753 +X2062Y70003 +X22062Y66253 +X22062Y67503 +X22062Y68753 +X22062Y70003 +X42062Y66253 +X42062Y67503 +X42062Y68753 +X42062Y70003 +T07 +X5588Y85527 +X25588Y85527 +X45588Y85527 +X89268Y28776 +T08 +X11200Y64785 +X8700Y64785 +X6700Y64785 +X4200Y64785 +X31200Y64785 +X28700Y64785 +X26700Y64785 +X24200Y64785 +X51200Y64785 +X48700Y64785 +X46700Y64785 +X44200Y64785 +X76332Y46397 +X78794Y46831 +X80763Y47178 +X83225Y47612 +T09 +X5450Y62685 +X9950Y62685 +X25450Y62685 +X29950Y62685 +X45450Y62685 +X49950Y62685 +X81630Y49463 +X77198Y48682 +X67910Y98476 +X70310Y98476 +X89910Y98476 +X92310Y98476 +T10 +X71900Y43897 +X80287Y38025 +X83906Y37245 +T11 +X85936Y30123 +X66570Y88570 +X65173Y68377 +X88570Y88570 +X87173Y68377 +M30 diff --git a/test/data/fill3.dxf b/test/data/fill3.dxf new file mode 100644 index 0000000..8e40c5a --- /dev/null +++ b/test/data/fill3.dxf @@ -0,0 +1,552 @@ +0 +SECTION +2 +HEADER +9 +$INSUNITS +70 +4 +9 +$ACADVER +1 +AC1014 +9 +$HANDSEED +5 +FFFF +0 +ENDSEC +0 +SECTION +2 +TABLES +0 +TABLE +2 +VPORT +5 +8 +100 +AcDbSymbolTable +0 +ENDTAB +0 +TABLE +2 +LTYPE +5 +5 +100 +AcDbSymbolTable +0 +LTYPE +5 +14 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord +2 +BYBLOCK +70 +0 +0 +LTYPE +5 +15 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord +2 +BYLAYER +70 +0 +0 +ENDTAB +0 +TABLE +2 +LAYER +5 +2 +100 +AcDbSymbolTable +70 +2 +0 +LAYER +5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord +2 +0 +70 +0 +6 +CONTINUOUS +0 +ENDTAB +0 +TABLE +2 +STYLE +5 +3 +100 +AcDbSymbolTable +70 +1 +0 +STYLE +5 +11 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord +2 +STANDARD +70 +0 +0 +ENDTAB +0 +TABLE +2 +VIEW +5 +6 +100 +AcDbSymbolTable +70 +0 +0 +ENDTAB +0 +TABLE +2 +UCS +5 +7 +100 +AcDbSymbolTable +70 +0 +0 +ENDTAB +0 +TABLE +2 +APPID +5 +9 +100 +AcDbSymbolTable +70 +2 +0 +APPID +5 +12 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord +2 +ACAD +70 +0 +0 +ENDTAB +0 +TABLE +2 +DIMSTYLE +5 +A +100 +AcDbSymbolTable +70 +1 +0 +ENDTAB +0 +TABLE +2 +BLOCK_RECORD +5 +1 +100 +AcDbSymbolTable +70 +1 +0 +BLOCK_RECORD +5 +1F +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord +2 +*MODEL_SPACE +0 +BLOCK_RECORD +5 +1B +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord +2 +*PAPER_SPACE +0 +ENDTAB +0 +ENDSEC +0 +SECTION +2 +BLOCKS +0 +BLOCK +5 +20 +100 +AcDbEntity +100 +AcDbBlockBegin +2 +*MODEL_SPACE +0 +ENDBLK +5 +21 +100 +AcDbEntity +100 +AcDbBlockEnd +0 +BLOCK +5 +1C +100 +AcDbEntity +100 +AcDbBlockBegin +2 +*PAPER_SPACE +0 +ENDBLK +5 +1D +100 +AcDbEntity +100 +AcDbBlockEnd +0 +ENDSEC +0 +SECTION +2 +ENTITIES +0 +ARC +5 +100 +100 +AcDbEntity +8 +0 +100 +AcDbCircle +10 +73.465697644393032 +20 +48.416408867916559 +30 +0 +40 +0.5999999999999982 +100 +AcDbArc +50 +-169.99999999999946 +51 +10.000000000000746 +0 +ARC +5 +101 +100 +AcDbEntity +8 +0 +100 +AcDbCircle +10 +84.987948354635876 +20 +50.448092546619641 +30 +0 +40 +0.5999999999999982 +100 +AcDbArc +50 +-169.99999999999923 +51 +10.000000000000965 +0 +ARC +5 +102 +100 +AcDbEntity +8 +0 +100 +AcDbCircle +10 +73.239955013426027 +20 +49.696658946832429 +30 +0 +40 +0.59999999999999665 +100 +AcDbArc +50 +10.000000000000087 +51 +190.00000000000051 +0 +ARC +5 +103 +100 +AcDbEntity +8 +0 +100 +AcDbCircle +10 +3.0000000000000004 +20 +3.0000000000000004 +30 +0 +40 +3.0000000000000004 +100 +AcDbArc +50 +180 +51 +270 +0 +LINE +5 +104 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +72.874812992585703 +20 +48.312219961316394 +30 +0 +11 +72.649070361618698 +21 +49.592470040232264 +31 +0 +0 +ARC +5 +105 +100 +AcDbEntity +8 +0 +100 +AcDbCircle +10 +84.76220572366887 +20 +51.728342625535511 +30 +0 +40 +0.59999999999996168 +100 +AcDbArc +50 +10.000000000000307 +51 +190.00000000000006 +0 +LINE +5 +106 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +85.353090375476171 +20 +51.832531532135668 +30 +0 +11 +85.578833006443176 +21 +50.552281453219805 +31 +0 +0 +LINE +5 +107 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +0 +20 +0 +30 +0 +11 +0 +21 +3.0000000000000009 +31 +0 +0 +LINE +5 +108 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +73.830839665233341 +20 +49.800847853432586 +30 +0 +11 +74.056582296200347 +21 +48.520597774516723 +31 +0 +0 +LINE +5 +109 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +3.0000000000000004 +20 +0 +30 +0 +11 +0 +21 +0 +31 +0 +0 +LINE +5 +110 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +84.397063702828561 +20 +50.343903640019477 +30 +0 +11 +84.171321071861513 +21 +51.624153718935347 +31 +0 +0 +ENDSEC +0 +SECTION +2 +OBJECTS +0 +DICTIONARY +5 +C +100 +AcDbDictionary +3 +ACAD_GROUP +350 +D +3 +ACAD_MLINESTYLE +350 +17 +0 +DICTIONARY +5 +D +100 +AcDbDictionary +0 +DICTIONARY +5 +1A +330 +C +100 +AcDbDictionary +0 +DICTIONARY +5 +17 +100 +AcDbDictionary +0 +ENDSEC +0 +EOF diff --git a/test/data/mousebite.dxf b/test/data/mousebite.dxf new file mode 100644 index 0000000..f68a1d5 --- /dev/null +++ b/test/data/mousebite.dxf @@ -0,0 +1,344 @@ +0 +SECTION +2 +HEADER +9 +$INSUNITS +70 +4 +9 +$ACADVER +1 +AC1014 +9 +$HANDSEED +5 +FFFF +0 +ENDSEC +0 +SECTION +2 +TABLES +0 +TABLE +2 +VPORT +5 +8 +100 +AcDbSymbolTable +0 +ENDTAB +0 +TABLE +2 +LTYPE +5 +5 +100 +AcDbSymbolTable +0 +LTYPE +5 +14 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord +2 +BYBLOCK +70 +0 +0 +LTYPE +5 +15 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord +2 +BYLAYER +70 +0 +0 +ENDTAB +0 +TABLE +2 +LAYER +5 +2 +100 +AcDbSymbolTable +70 +2 +0 +LAYER +5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord +2 +0 +70 +0 +6 +CONTINUOUS +0 +ENDTAB +0 +TABLE +2 +STYLE +5 +3 +100 +AcDbSymbolTable +70 +1 +0 +STYLE +5 +11 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord +2 +STANDARD +70 +0 +0 +ENDTAB +0 +TABLE +2 +VIEW +5 +6 +100 +AcDbSymbolTable +70 +0 +0 +ENDTAB +0 +TABLE +2 +UCS +5 +7 +100 +AcDbSymbolTable +70 +0 +0 +ENDTAB +0 +TABLE +2 +APPID +5 +9 +100 +AcDbSymbolTable +70 +2 +0 +APPID +5 +12 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord +2 +ACAD +70 +0 +0 +ENDTAB +0 +TABLE +2 +DIMSTYLE +5 +A +100 +AcDbSymbolTable +70 +1 +0 +ENDTAB +0 +TABLE +2 +BLOCK_RECORD +5 +1 +100 +AcDbSymbolTable +70 +1 +0 +BLOCK_RECORD +5 +1F +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord +2 +*MODEL_SPACE +0 +BLOCK_RECORD +5 +1B +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord +2 +*PAPER_SPACE +0 +ENDTAB +0 +ENDSEC +0 +SECTION +2 +BLOCKS +0 +BLOCK +5 +20 +100 +AcDbEntity +100 +AcDbBlockBegin +2 +*MODEL_SPACE +0 +ENDBLK +5 +21 +100 +AcDbEntity +100 +AcDbBlockEnd +0 +BLOCK +5 +1C +100 +AcDbEntity +100 +AcDbBlockBegin +2 +*PAPER_SPACE +0 +ENDBLK +5 +1D +100 +AcDbEntity +100 +AcDbBlockEnd +0 +ENDSEC +0 +SECTION +2 +ENTITIES +0 +LINE +5 +100 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +0 +20 +0 +30 +0 +11 +10 +21 +0 +31 +0 +0 +LINE +5 +101 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +0 +20 +5.0798803480694392 +30 +0 +11 +6.9518511056354715 +21 +12.268187951746041 +31 +0 +0 +ENDSEC +0 +SECTION +2 +OBJECTS +0 +DICTIONARY +5 +C +100 +AcDbDictionary +3 +ACAD_GROUP +350 +D +3 +ACAD_MLINESTYLE +350 +17 +0 +DICTIONARY +5 +D +100 +AcDbDictionary +0 +DICTIONARY +5 +1A +330 +C +100 +AcDbDictionary +0 +DICTIONARY +5 +17 +100 +AcDbDictionary +0 +ENDSEC +0 +EOF diff --git a/test/data/mousebites.dxf b/test/data/mousebites.dxf new file mode 100644 index 0000000..7fb69b8 --- /dev/null +++ b/test/data/mousebites.dxf @@ -0,0 +1,652 @@ +0 +SECTION +2 +HEADER +9 +$INSUNITS +70 +4 +9 +$ACADVER +1 +AC1014 +9 +$HANDSEED +5 +FFFF +0 +ENDSEC +0 +SECTION +2 +TABLES +0 +TABLE +2 +VPORT +5 +8 +100 +AcDbSymbolTable +0 +ENDTAB +0 +TABLE +2 +LTYPE +5 +5 +100 +AcDbSymbolTable +0 +LTYPE +5 +14 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord +2 +BYBLOCK +70 +0 +0 +LTYPE +5 +15 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord +2 +BYLAYER +70 +0 +0 +ENDTAB +0 +TABLE +2 +LAYER +5 +2 +100 +AcDbSymbolTable +70 +2 +0 +LAYER +5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord +2 +0 +70 +0 +6 +CONTINUOUS +0 +ENDTAB +0 +TABLE +2 +STYLE +5 +3 +100 +AcDbSymbolTable +70 +1 +0 +STYLE +5 +11 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord +2 +STANDARD +70 +0 +0 +ENDTAB +0 +TABLE +2 +VIEW +5 +6 +100 +AcDbSymbolTable +70 +0 +0 +ENDTAB +0 +TABLE +2 +UCS +5 +7 +100 +AcDbSymbolTable +70 +0 +0 +ENDTAB +0 +TABLE +2 +APPID +5 +9 +100 +AcDbSymbolTable +70 +2 +0 +APPID +5 +12 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord +2 +ACAD +70 +0 +0 +ENDTAB +0 +TABLE +2 +DIMSTYLE +5 +A +100 +AcDbSymbolTable +70 +1 +0 +ENDTAB +0 +TABLE +2 +BLOCK_RECORD +5 +1 +100 +AcDbSymbolTable +70 +1 +0 +BLOCK_RECORD +5 +1F +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord +2 +*MODEL_SPACE +0 +BLOCK_RECORD +5 +1B +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord +2 +*PAPER_SPACE +0 +ENDTAB +0 +ENDSEC +0 +SECTION +2 +BLOCKS +0 +BLOCK +5 +20 +100 +AcDbEntity +100 +AcDbBlockBegin +2 +*MODEL_SPACE +0 +ENDBLK +5 +21 +100 +AcDbEntity +100 +AcDbBlockEnd +0 +BLOCK +5 +1C +100 +AcDbEntity +100 +AcDbBlockBegin +2 +*PAPER_SPACE +0 +ENDBLK +5 +1D +100 +AcDbEntity +100 +AcDbBlockEnd +0 +ENDSEC +0 +SECTION +2 +ENTITIES +0 +LINE +5 +100 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +22.5 +20 +21.400000000000002 +30 +0 +11 +42.5 +21 +21.400000000000002 +31 +0 +0 +LINE +5 +101 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +21 +20 +43.050000000000004 +30 +0 +11 +44 +21 +43.050000000000004 +31 +0 +0 +LINE +5 +102 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +1.9000000000000004 +20 +57.250000000000007 +30 +0 +11 +12.000000000000002 +21 +57.250000000000007 +31 +0 +0 +LINE +5 +103 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +1.9000000000000004 +20 +59.75 +30 +0 +11 +13.5 +21 +59.75 +31 +0 +0 +LINE +5 +104 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +22.200000000000003 +20 +59.75 +30 +0 +11 +33.199999999999996 +21 +59.75 +31 +0 +0 +LINE +5 +105 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +41.5 +20 +59.75 +30 +0 +11 +53.200000000000003 +21 +59.75 +31 +0 +0 +LINE +5 +106 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +81.970000000000027 +20 +88.5 +30 +0 +11 +81.970000000000013 +21 +71.5 +31 +0 +0 +LINE +5 +107 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +78.250000000000043 +20 +88.499999999999972 +30 +0 +11 +78.250000000000028 +21 +71.5 +31 +0 +0 +LINE +5 +108 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +59.970000000000006 +20 +88.499999999999972 +30 +0 +11 +59.970000000000013 +21 +71.5 +31 +0 +0 +LINE +5 +109 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +55.650000000000013 +20 +88.499999999999972 +30 +0 +11 +55.650000000000006 +21 +71.5 +31 +0 +0 +LINE +5 +110 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +39.749999999999993 +20 +88.499999999999972 +30 +0 +11 +39.75 +21 +71.5 +31 +0 +0 +LINE +5 +111 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +35.650000000000006 +20 +88.499999999999972 +30 +0 +11 +35.650000000000006 +21 +71.5 +31 +0 +0 +LINE +5 +112 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +19.749999999999993 +20 +88.499999999999972 +30 +0 +11 +19.749999999999996 +21 +71.5 +31 +0 +0 +LINE +5 +113 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +15.650000000000009 +20 +88.499999999999972 +30 +0 +11 +15.650000000000004 +21 +71.5 +31 +0 +0 +LINE +5 +114 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +65.25 +20 +16.500250410747213 +30 +0 +11 +65.25 +21 +3.5002504107472134 +31 +0 +0 +LINE +5 +115 +100 +AcDbEntity +8 +0 +100 +AcDbLine +10 +79.752051115713613 +20 +9.0215259002820929 +30 +0 +11 +92.554551904872312 +21 +11.278952209952195 +31 +0 +0 +ENDSEC +0 +SECTION +2 +OBJECTS +0 +DICTIONARY +5 +C +100 +AcDbDictionary +3 +ACAD_GROUP +350 +D +3 +ACAD_MLINESTYLE +350 +17 +0 +DICTIONARY +5 +D +100 +AcDbDictionary +0 +DICTIONARY +5 +1A +330 +C +100 +AcDbDictionary +0 +DICTIONARY +5 +17 +100 +AcDbDictionary +0 +ENDSEC +0 +EOF diff --git a/test/outline.GML b/test/outline.GML new file mode 100644 index 0000000..267119a --- /dev/null +++ b/test/outline.GML @@ -0,0 +1,626 @@ +G75* +%MOMM*% +%OFA0B0*% +%FSTAX34Y34*% +%IPPOS*% +%LPD*% +%ADD10C,0*% +D10* +G36* +G01* +X08455Y002812D02* +G75* +G03* +X08455Y002812I-0006J0D01* +G01* +X004875Y0168D02* +G75* +G03* +X004875Y0168I-001375J0D01* +G01* +X02245Y062035D02* +G75* +G02* +X02125Y062035I-0006J0D01* +G01* +X02125Y063335D01* +G02* +X02245Y063335I0006J0D01* +G01* +X02245Y062035D01* +G01* +X03295Y063335D02* +G75* +G02* +X03415Y063335I0006J0D01* +G01* +X03415Y062035D01* +G02* +X03295Y062035I-0006J0D01* +G01* +X03295Y063335D01* +G01* +X00245Y062035D02* +G75* +G01* +X00245Y063335D01* +G03* +X00125Y063335I-0006J0D01* +G01* +X00125Y062035D01* +G03* +X00245Y062035I0006J0D01* +G01* +X02605Y062685D02* +G75* +G03* +X02605Y062685I-0006J0D01* +G01* +X03055Y062685D02* +G75* +G03* +X03055Y062685I-0006J0D01* +G01* +X062875Y0393D02* +G75* +G03* +X062875Y0393I-001375J0D01* +G01* +X062Y0428D02* +G75* +G02* +X065Y0398I0J-003D01* +G01* +X065Y0357395D01* +G03* +X066Y0347395I001J0D01* +G01* +X0714Y0347395D01* +G03* +X0724Y0357395I0J001D01* +G01* +X0724Y0431D01* +G01* +X0835214Y0431D01* +G03* +X0845214Y0441I0J001D01* +G01* +X0845214Y046375D01* +G03* +X0835214Y047375I-001J0D01* +G01* +X0472842Y047375D01* +G03* +X0462842Y046375I0J-001D01* +G01* +X0462842Y0438D01* +G03* +X0472842Y0428I001J0D01* +G01* +X062Y0428D01* +G01* +X01415Y062035D02* +G75* +G01* +X01415Y063335D01* +G03* +X01295Y063335I-0006J0D01* +G01* +X01295Y062035D01* +G03* +X01415Y062035I0006J0D01* +G01* +X04245Y062035D02* +G75* +G02* +X04125Y062035I-0006J0D01* +G01* +X04125Y063335D01* +G02* +X04245Y063335I0006J0D01* +G01* +X04245Y062035D01* +G01* +X04Y1D02* +G75* +G01* +X0554Y1D01* +G01* +X0554Y0916665D01* +G03* +X0564Y0906665I001J0D01* +G01* +X05922Y0906665D01* +G03* +X06022Y0916665I0J001D01* +G01* +X06022Y1D01* +G01* +X078Y1D01* +G01* +X078Y0916665D01* +G03* +X079Y0906665I001J0D01* +G01* +X08122Y0906665D01* +G03* +X08222Y0916665I0J001D01* +G01* +X08222Y1D01* +G01* +X1Y1D01* +G01* +X1Y05936D01* +G01* +X09391Y05936D01* +G03* +X09291Y05836I0J-001D01* +G01* +X09291Y0571655D01* +G03* +X09391Y0561655I001J0D01* +G01* +X1Y0561655D01* +G01* +X1Y047375D01* +G01* +X0873214Y047375D01* +G03* +X0863214Y046375I0J-001D01* +G01* +X0863214Y0441D01* +G03* +X0873214Y0431I001J0D01* +G01* +X1Y0431D01* +G01* +X1Y0D01* +G01* +X0724Y0D01* +G01* +X0724Y0082125D01* +G03* +X0714Y0092125I-001J0D01* +G01* +X066Y0092125D01* +G03* +X065Y0082125I0J-001D01* +G01* +X065Y003D01* +G02* +X062Y0I-003J0D01* +G01* +X003Y0D01* +G02* +X0Y003I0J003D01* +G01* +X0Y0173D01* +G02* +X003Y0203I003J0D01* +G01* +X0137888Y0203D01* +G03* +X0147888Y0213I0J001D01* +G01* +X0147888Y0215D01* +G03* +X0137888Y0225I-001J0D01* +G01* +X003Y0225D01* +G02* +X0Y0255I0J003D01* +G01* +X0Y0398D01* +G02* +X003Y0428I003J0D01* +G01* +X0139638Y0428D01* +G03* +X0149638Y0438I0J001D01* +G01* +X0149638Y047375D01* +G01* +X0149638Y0484437D01* +G03* +X0139638Y0494437I-001J0D01* +G01* +X013Y0494437D01* +G03* +X012Y0484437I0J-001D01* +G01* +X012Y044D01* +G01* +X0Y044D01* +G01* +X0Y057D01* +G01* +X005Y057D01* +G03* +X006Y058I0J001D01* +G01* +X006Y059D01* +G03* +X005Y06I-001J0D01* +G01* +X0Y06D01* +G01* +X0Y1D01* +G01* +X0154Y1D01* +G01* +X0154Y0916665D01* +G03* +X0164Y0906665I001J0D01* +G01* +X019Y0906665D01* +G03* +X02Y0916665I0J001D01* +G01* +X02Y1D01* +G01* +X0354Y1D01* +G01* +X0354Y0916665D01* +G03* +X0364Y0906665I001J0D01* +G01* +X039Y0906665D01* +G03* +X04Y0916665I0J001D01* +G01* +X04Y1D01* +G01* +X05295Y063335D02* +G75* +G01* +X05295Y062035D01* +G03* +X05415Y062035I0006J0D01* +G01* +X05415Y063335D01* +G03* +X05295Y063335I-0006J0D01* +G01* +X09145Y003462D02* +G75* +G01* +X09145Y002162D01* +G03* +X09265Y002162I0006J0D01* +G01* +X09265Y003462D01* +G03* +X09145Y003462I-0006J0D01* +G01* +X08095Y002162D02* +G75* +G01* +X08095Y003462D01* +G03* +X07975Y003462I-0006J0D01* +G01* +X07975Y002162D01* +G03* +X08095Y002162I0006J0D01* +G01* +X062Y0203D02* +G75* +G02* +X065Y0173I0J-003D01* +G01* +X065Y0120125D01* +G03* +X066Y0110125I001J0D01* +G01* +X0714Y0110125D01* +G03* +X0724Y0120125I0J001D01* +G01* +X0724Y0319395D01* +G03* +X0714Y0329395I-001J0D01* +G01* +X066Y0329395D01* +G03* +X065Y0319395I0J-001D01* +G01* +X065Y0255D01* +G02* +X062Y0225I-003J0D01* +G01* +X0472842Y0225D01* +G03* +X0462842Y0215I0J-001D01* +G01* +X0462842Y0213D01* +G03* +X0472842Y0203I001J0D01* +G01* +X062Y0203D01* +G01* +X00605Y062685D02* +G75* +G03* +X00605Y062685I-0006J0D01* +G01* +X01055Y062685D02* +G75* +G03* +X01055Y062685I-0006J0D01* +G01* +X04605Y062685D02* +G75* +G03* +X04605Y062685I-0006J0D01* +G01* +X05055Y062685D02* +G75* +G03* +X05055Y062685I-0006J0D01* +G01* +X062875Y0168D02* +G75* +G03* +X062875Y0168I-001375J0D01* +G01* +X004875Y0393D02* +G75* +G03* +X004875Y0393I-001375J0D01* +G01* +X08905Y002812D02* +G75* +G03* +X08905Y002812I-0006J0D01* +G01* +X0165888Y0213D02* +G75* +G01* +X0165888Y0215D01* +G02* +X0175888Y0225I001J0D01* +G01* +X0434842Y0225D01* +G02* +X0444842Y0215I0J-001D01* +G01* +X0444842Y0213D01* +G02* +X0434842Y0203I-001J0D01* +G01* +X0175888Y0203D01* +G02* +X0165888Y0213I0J001D01* +G01* +X0167638Y0438D02* +G75* +G01* +X0167638Y046375D01* +G02* +X0177638Y047375I001J0D01* +G01* +X0434842Y047375D01* +G02* +X0444842Y046375I0J-001D01* +G01* +X0444842Y0438D01* +G02* +X0434842Y0428I-001J0D01* +G01* +X0177638Y0428D01* +G02* +X0167638Y0438I0J001D01* +G01* +X0078Y059D02* +G75* +G01* +X0078Y058D01* +G03* +X0088Y057I001J0D01* +G01* +X012Y057D01* +G01* +X012Y0522437D01* +G03* +X013Y0512437I001J0D01* +G01* +X0139638Y0512437D01* +G03* +X0149638Y0522437I0J001D01* +G01* +X0149638Y0561655D01* +G01* +X025598Y0561655D01* +G03* +X026598Y0571655I0J001D01* +G01* +X026598Y059D01* +G03* +X025598Y06I-001J0D01* +G01* +X02Y06D01* +G01* +X02Y0659907D01* +G03* +X019Y0669907I-001J0D01* +G01* +X0164Y0669907D01* +G03* +X0154Y0659907I0J-001D01* +G01* +X0154Y06D01* +G01* +X0088Y06D01* +G03* +X0078Y059I0J-001D01* +G01* +X028398Y0571655D02* +G75* +G01* +X028398Y059D01* +G02* +X029398Y06I001J0D01* +G01* +X0354Y06D01* +G01* +X0354Y0662142D01* +G02* +X0364Y0672142I001J0D01* +G01* +X039Y0672142D01* +G02* +X04Y0662142I0J-001D01* +G01* +X04Y06D01* +G01* +X0456478Y06D01* +G02* +X0466478Y059I0J-001D01* +G01* +X0466478Y0571655D01* +G02* +X0456478Y0561655I-001J0D01* +G01* +X029398Y0561655D01* +G02* +X028398Y0571655I0J001D01* +G01* +X0484478Y0571655D02* +G75* +G01* +X0484478Y059D01* +G02* +X0494478Y06I001J0D01* +G01* +X0554Y06D01* +G01* +X0554Y0662142D01* +G02* +X0564Y0672142I001J0D01* +G01* +X05922Y0672142D01* +G02* +X06022Y0662142I0J-001D01* +G01* +X06022Y05936D01* +G01* +X0668994Y05936D01* +G02* +X0678994Y05836I0J-001D01* +G01* +X0678994Y0571655D01* +G02* +X0668994Y0561655I-001J0D01* +G01* +X0494478Y0561655D01* +G02* +X0484478Y0571655I0J001D01* +G01* +X0696994Y0571655D02* +G75* +G01* +X0696994Y05836D01* +G02* +X0706994Y05936I001J0D01* +G01* +X078Y05936D01* +G01* +X078Y0662142D01* +G02* +X079Y0672142I001J0D01* +G01* +X08122Y0672142D01* +G02* +X08222Y0662142I0J-001D01* +G01* +X08222Y05936D01* +G01* +X09011Y05936D01* +G02* +X09111Y05836I0J-001D01* +G01* +X09111Y0571655D01* +G02* +X09011Y0561655I-001J0D01* +G01* +X0706994Y0561655D01* +G02* +X0696994Y0571655I0J001D01* +G01* +X0164Y0690142D02* +G75* +G01* +X019Y0690142D01* +G03* +X02Y0700142I0J001D01* +G01* +X02Y0878665D01* +G03* +X019Y0888665I-001J0D01* +G01* +X0164Y0888665D01* +G03* +X0154Y0878665I0J-001D01* +G01* +X0154Y0700142D01* +G03* +X0164Y0690142I001J0D01* +G01* +X0364Y0888665D02* +G75* +G01* +X039Y0888665D01* +G02* +X04Y0878665I0J-001D01* +G01* +X04Y0700142D01* +G02* +X039Y0690142I-001J0D01* +G01* +X0364Y0690142D01* +G02* +X0354Y0700142I0J001D01* +G01* +X0354Y0878665D01* +G02* +X0364Y0888665I001J0D01* +G01* +X0564Y0888665D02* +G75* +G01* +X05922Y0888665D01* +G02* +X06022Y0878665I0J-001D01* +G01* +X06022Y0700142D01* +G02* +X05922Y0690142I-001J0D01* +G01* +X0564Y0690142D01* +G02* +X0554Y0700142I0J001D01* +G01* +X0554Y0878665D01* +G02* +X0564Y0888665I001J0D01* +G01* +X079Y0888665D02* +G75* +G01* +X08122Y0888665D01* +G02* +X08222Y0878665I0J-001D01* +G01* +X08222Y0700142D01* +G02* +X08122Y0690142I-001J0D01* +G01* +X079Y0690142D01* +G02* +X078Y0700142I0J001D01* +G01* +X078Y0878665D01* +G02* +X079Y0888665I001J0D01* +G37* +M02* diff --git a/test/test.py b/test/test.py index ced478b..98da22f 100755 --- a/test/test.py +++ b/test/test.py @@ -49,6 +49,31 @@ os.chdir(os.path.dirname(__file__)) #merge2() +ctx = gerberex.DrillComposition() +base = gerberex.read('data/base.txt') +dxf = gerberex.read('data/mousebites.dxf') +dxf.draw_mode = DxfFile.DM_MOUSE_BITES +dxf.to_metric() +dxf.width = 0.5 +ctx.merge(base) +ctx.merge(dxf) +ctx.dump('outputs/merged.txt') + +dxf = gerberex.read('data/mousebite.dxf') +dxf.zero_suppression = 'leading' +dxf.write('outputs/a.gtl') +dxf.draw_mode = DxfFile.DM_MOUSE_BITES +dxf.width = 0.5 +dxf.write('outputs/b.gml') +dxf.format = (3,3) +dxf.write('outputs/b.txt', filetype=DxfFile.FT_EXCELLON) +top = gerber.load_layer('outputs/a.gtl') +drill = gerber.load_layer('outputs/b.txt') +ctx = GerberCairoContext(scale=50) +ctx.render_layer(top) +ctx.render_layer(drill) +ctx.dump('outputs/b.png') + file = gerberex.read('data/test.GTL') file.rotate(45) file.write('outputs/test_changed.GTL') |