auto detection closed paths in the collection of DXF arc object and line object, then fill these closed path

This commit is contained in:
opiopan 2019-03-31 13:30:15 +09:00
parent fcd704e1ee
commit 900d992fa3
17 changed files with 345 additions and 14744 deletions

2
.gitignore vendored
View file

@ -3,4 +3,4 @@
*.pyc
__pycache__
pcb_tools_extension.egg-info
test/outputs
test

View file

@ -103,7 +103,7 @@ dxf.write('outline.gml')
<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>
If ```DM_MOUSE_BITES``` is specified for ```drawing_mode```, filled circles are 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

View file

@ -5,16 +5,29 @@
import io
from math import pi, cos, sin, tan, atan, atan2, acos, asin, sqrt
import dxfgrabber
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
from gerberex.dxf_path import generate_closed_paths
ACCEPTABLE_ERROR = 0.001
def is_equal_value(a, b, error_range=0):
return a - b <= error_range and a - b >= -error_range
def is_equal_point(a, b, error_range=0):
return is_equal_value(a[0], b[0], error_range) and \
is_equal_value(a[1], b[1], error_range)
class DxfStatement(object):
def __init__(self, entity):
self.entity = entity
self.start = None
self.end = None
self.is_closed = False
def to_gerber(self, settings=None, pitch=0, width=0):
pass
@ -28,16 +41,22 @@ class DxfStatement(object):
def to_metric(self):
pass
def is_equal_to(self, target, error_range=0):
return False
def reverse(self):
raise Exception('Not implemented')
class DxfLineStatement(DxfStatement):
def __init__(self, entity):
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])
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]
x0, y0 = self.start
x1, y1 = self.end
return 'G01*\nX{0}Y{1}D02*\nX{2}Y{3}D01*'.format(
write_gerber_value(x0, settings.format,
settings.zero_suppression),
@ -67,22 +86,34 @@ class DxfLineStatement(DxfStatement):
return gstr
def to_inch(self):
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]))
self.start = (
inch(self.start[0]), inch(self.start[1]))
self.end = (
inch(self.end[0]), inch(self.end[1]))
def to_metric(self):
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]))
self.start = (
metric(self.start[0]), inch(self.start[1]))
self.end = (
metric(self.end[0]), inch(self.end[1]))
def is_equal_to(self, target, error_range=0):
if not isinstance(target, DxfLineStatement):
return False
return (is_equal_point(self.start, target.start, error_range) and \
is_equal_point(self.end, target.end, error_range)) or \
(is_equal_point(self.start, target.end, error_range) and \
is_equal_point(self.end, target.start, error_range))
def reverse(self):
pt = self.start
self.start = self.end
self.end = pt
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]
x0, y0 = self.start
x1, y1 = self.end
y1 = self.end[1]
xp = x1 - x0
yp = y1 - y0
l = sqrt(xp * xp + yp * yp)
@ -99,13 +130,17 @@ class DxfLineStatement(DxfStatement):
class DxfCircleStatement(DxfStatement):
def __init__(self, entity):
super(DxfCircleStatement, self).__init__(entity)
self.radius = self.entity.radius
self.center = (self.entity.center[0], self.entity.center[1])
self.start = (self.center[0] + self.radius, self.center[1])
self.end = self.start
self.is_closed = True
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]
r = self.radius
x0, y0 = self.center
return 'G01*\nX{0}Y{1}D02*\n' \
'G75*\nG03*\nX{2}Y{3}I{4}J{5}D01*'.format(
write_gerber_value(x0 + r, settings.format,
@ -124,66 +159,107 @@ class DxfCircleStatement(DxfStatement):
)
def to_inch(self):
self.entity.radius = inch(self.entity.radius)
self.entity.center = (
inch(self.entity.center[0]), inch(self.entity.center[1]))
self.radius = inch(self.radius)
self.center = (
inch(self.center[0]), inch(self.center[1]))
def to_metric(self):
self.entity.radius = metric(self.entity.radius)
self.entity.center = (
metric(self.entity.center[0]), metric(self.entity.center[1]))
self.radius = metric(self.radius)
self.center = (
metric(self.center[0]), metric(self.center[1]))
def is_equal_to(self, target, error_range=0):
if not isinstance(target, DxfCircleStatement):
return False
return is_equal_point(self.center, target.enter, error_range) and \
is_equal_value(self.radius, target.radius)
def reverse(self):
pass
class DxfArcStatement(DxfStatement):
def __init__(self, entity):
super(DxfArcStatement, self).__init__(entity)
self.start_angle = self.entity.start_angle
self.end_angle = self.entity.end_angle
self.radius = self.entity.radius
self.center = (self.entity.center[0], self.entity.center[1])
self.start = (
self.center[0] + self.radius * cos(self.start_angle / 180. * pi),
self.center[1] + self.radius * sin(self.start_angle / 180. * pi),
)
self.end = (
self.center[0] + self.radius * cos(self.end_angle / 180. * pi),
self.center[1] + self.radius * sin(self.end_angle / 180. * pi),
)
angle = self.end_angle - self.start_angle
self.is_closed = angle >= 360 or angle <= -360
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
x0 = self.entity.center[0]
y0 = self.entity.center[1]
begin_x = x0 + r * cos(deg0 / 180. * pi)
begin_y = y0 + r * sin(deg0 / 180. * pi)
end_x = x0 + r * cos(deg1 / 180. * pi)
end_y = y0 + r * sin(deg1 / 180. * pi)
x0 = self.center[0]
y0 = self.center[1]
start_x, start_y = self.start
end_x, end_y = self.end
return 'G01*\nX{0}Y{1}D02*\n' \
'G75*\nG{2}*\nX{3}Y{4}I{5}J{6}D01*'.format(
write_gerber_value(begin_x, settings.format,
write_gerber_value(start_x, settings.format,
settings.zero_suppression),
write_gerber_value(begin_y, settings.format,
write_gerber_value(start_y, settings.format,
settings.zero_suppression),
'03',
'02' if self.start_angle > self.end_angle else '03',
write_gerber_value(end_x, settings.format,
settings.zero_suppression),
write_gerber_value(end_y, settings.format,
settings.zero_suppression),
write_gerber_value(x0 - begin_x, settings.format,
write_gerber_value(x0 - start_x, settings.format,
settings.zero_suppression),
write_gerber_value(y0 - begin_y, settings.format,
write_gerber_value(y0 - start_y, settings.format,
settings.zero_suppression)
)
def to_inch(self):
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 = (
inch(self.entity.center[0]), inch(self.entity.center[1]))
self.radius = inch(self.radius)
self.center = (inch(self.center[0]), inch(self.center[1]))
self.start = (inch(self.start[0]), inch(self.start[1]))
self.end = (inch(self.end[0]), inch(self.end[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 = (
metric(self.entity.center[0]), metric(self.entity.center[1]))
self.radius = metric(self.radius)
self.center = (metric(self.center[0]), metric(self.center[1]))
self.start = (metric(self.start[0]), metric(self.start[1]))
self.end = (metric(self.end[0]), metric(self.end[1]))
def is_equal_to(self, target, error_range=0):
if not isinstance(target, DxfArcStatement):
return False
aerror_range = error_range / pi * self.radius * 180
return is_equal_point(self.center, target.center, error_range) and \
is_equal_value(self.radius, target.radius, error_range) and \
((is_equal_value(self.start_angle, target.start_angle, aerror_range) and
is_equal_value(self.end_angle, target.end_angle, aerror_range)) or
(is_equal_value(self.start_angle, target.end_angle, aerror_range) and
is_equal_value(self.end_angle, target.end_angle, aerror_range)))
def reverse(self):
tmp = self.start_angle
self.start_angle = self.end_angle
self.end_angle = tmp
tmp = self.start
self.start = self.end
self.end = tmp
class DxfPolylineStatement(DxfStatement):
def __init__(self, entity):
super(DxfPolylineStatement, self).__init__(entity)
self.start = (self.entity.points[0][0], self.entity.points[0][1])
self.is_closed = self.entity.is_closed
if self.is_closed:
self.end = self.start
else:
self.start = (self.entity.points[-1][0], self.entity.points[-1][1])
def to_gerber(self, settings=FileSettings(), pitch=0, width=0):
if pitch:
@ -243,12 +319,16 @@ class DxfPolylineStatement(DxfStatement):
return gerber
def to_inch(self):
self.start = (inch(self.start[0]), inch(self.start[1]))
self.end = (inch(self.end[0]), inch(self.end[1]))
for idx in range(0, len(self.entity.points)):
self.entity.points[idx] = (
inch(self.entity.points[idx][0]), inch(self.entity.points[idx][1]))
self.entity.bulge[idx] = inch(self.entity.bulge[idx])
def to_metric(self):
self.start = (metric(self.start[0]), metric(self.start[1]))
self.end = (metric(self.end[0]), metric(self.end[1]))
for idx in range(0, len(self.entity.points)):
self.entity.points[idx] = (
metric(self.entity.points[idx][0]), metric(self.entity.points[idx][1]))
@ -261,8 +341,9 @@ 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.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':
@ -273,6 +354,7 @@ class DxfStatements(object):
self.statements.append(DxfCircleStatement(entity))
elif entity.dxftype == 'ARC':
self.statements.append(DxfArcStatement(entity))
self.paths = generate_closed_paths(self.statements, self.error_range)
@property
def units(self):
@ -282,12 +364,16 @@ class DxfStatements(object):
def gerbers():
yield 'D{0}*'.format(self.dcode)
if self.draw_mode == DxfFile.DM_FILL:
yield 'G36*'
for statement in self.statements:
yield 'G36*'
if isinstance(statement, DxfCircleStatement) or \
(isinstance(statement, DxfPolylineStatement) and statement.entity.is_closed):
yield statement.to_gerber(settings)
yield 'G37*'
yield 'G37*'
for path in self.paths:
yield 'G36*'
yield path.to_gerber(settings)
yield 'G37*'
else:
for statement in self.statements:
yield statement.to_gerber(
@ -310,15 +396,21 @@ class DxfStatements(object):
if self._units == 'metric':
self._units = 'inch'
self.pitch = inch(self.pitch)
self.error_range = inch(self.error_range)
for statement in self.statements:
statement.to_inch()
for path in self.paths:
path.to_inch()
def to_metric(self):
if self._units == 'inch':
self._units = 'metric'
self.pitch = metric(self.pitch)
self.error_range = metric(self.error_range)
for statement in self.statements:
statement.to_metric()
for path in self.paths:
path.to_metric()
class DxfHeaderStatement(object):
def to_gerber(self, settings):

197
gerberex/dxf_path.py Normal file
View file

@ -0,0 +1,197 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2019 Hiroshi Murayama <opiopan@gmail.com>
from gerber.utils import inch, metric, write_gerber_value
from gerber.cam import FileSettings
class DxfPath(object):
def __init__(self, statement, error_range=0):
self.statements = [statement]
self.error_range = error_range
@property
def start(self):
return self.statements[0].start
@property
def end(self):
return self.statements[-1].end
@property
def is_closed(self):
from gerberex.dxf import is_equal_point
return len(self.statements) > 1 and \
is_equal_point(self.start, self.end, self.error_range)
def is_equal_to(self, target, error_range=0):
from gerberex.dxf import is_equal_point
if not isinstance(target, DxfPath):
return False
if len(self.statements) != len(target.statements):
return False
if is_equal_point(self.start, target.start, error_range) and \
is_equal_point(self.end, target.end, error_range):
for i in range(0, len(self.statements)):
if not self.statements[i].is_equal_to(target.statements[i], error_range):
return False
return True
elif is_equal_point(self.start, target.end, error_range) and \
is_equal_point(self.end, target.start, error_range):
for i in range(0, len(self.statements)):
if not self.statements[i].is_equal_to(target.statements[-1 - i], error_range):
return False
return True
return False
def to_inch(self):
self.error_range = inch(self.error_range)
def to_metric(self):
self.error_range = metric(self.error_range)
def reverse(self):
rlist = []
for statement in reversed(self.statements):
statement.reverse()
rlist.append(statement)
self.statements = rlist
def merge(self, element, error_range=0):
from gerberex.dxf import is_equal_point
if self.is_closed or element.is_closed:
return False
if not error_range:
error_range = self.error_range
if is_equal_point(self.end, element.start, error_range):
return self._append_at_end(element, error_range)
elif is_equal_point(self.end, element.end, error_range):
element.reverse()
return self._append_at_end(element, error_range)
elif is_equal_point(self.start, element.end, error_range):
return self._insert_on_top(element, error_range)
elif is_equal_point(self.start, element.start, error_range):
element.reverse()
return self._insert_on_top(element, error_range)
else:
return False
def _append_at_end(self, element, error_range=0):
if isinstance(element, DxfPath):
if self.is_equal_to(element, error_range):
return False
for i in range(0, min(len(self.statements), len(element.statements))):
if not self.statements[-1 - i].is_equal_to(element.statements[i]):
break
for j in range(0, min(len(self.statements), len(element.statements))):
if not self.statements[j].is_equal_to(element.statements[-1 - j]):
break
if i + j >= len(element.statements):
return False
mergee = list(element.statements)
if i > 0:
del mergee[0:i]
del self.statements[-i]
if j > 0:
del mergee[-j]
del self.statements[0:j]
self.statements.extend(mergee)
return True
else:
if self.statements[-1].is_equal_to(element, error_range) or \
self.statements[0].is_equal_to(element, error_range):
return False
self.statements.appen(element)
return True
def _insert_on_top(self, element, error_range=0):
if isinstance(element, DxfPath):
if self.is_equal_to(element, error_range):
return False
for i in range(0, min(len(self.statements), len(element.statements))):
if not self.statements[-1 - i].is_equal_to(element.statements[i]):
break
for j in range(0, min(len(self.statements), len(element.statements))):
if not self.statements[j].is_equal_to(element.statements[-1 - j]):
break
if i + j >= len(element.statements):
return False
mergee = list(element.statements)
if i > 0:
del mergee[0:i]
del self.statements[-i]
if j > 0:
del mergee[-j]
del self.statements[0:j]
self.statements[0:0] = mergee
return True
else:
if self.statements[-1].is_equal_to(element, error_range) or \
self.statements[0].is_equal_to(element, error_range):
return False
self.statements.insert(0, element)
return True
def to_gerber(self, settings=FileSettings(), pitch=0, width=0):
from gerberex.dxf import DxfArcStatement
if pitch:
return
x0, y0 = self.statements[0].start
gerber = 'G01*\nX{0}Y{1}D02*\nG75*'.format(
write_gerber_value(x0, settings.format,
settings.zero_suppression),
write_gerber_value(y0, settings.format,
settings.zero_suppression),
)
for statement in self.statements:
x0, y0 = statement.start
x1, y1 = statement.end
if isinstance(statement, DxfArcStatement):
xc, yc = statement.center
gerber += '\nG{0}*\nX{1}Y{2}I{3}J{4}D01*'.format(
'03' if statement.end_angle > statement.start_angle else '02',
write_gerber_value(x1, settings.format,
settings.zero_suppression),
write_gerber_value(y1, settings.format,
settings.zero_suppression),
write_gerber_value(xc - x0, settings.format,
settings.zero_suppression),
write_gerber_value(yc - y0, settings.format,
settings.zero_suppression)
)
else:
gerber += '\nG01*\nX{0}Y{1}D01*'.format(
write_gerber_value(x1, settings.format,
settings.zero_suppression),
write_gerber_value(y1, settings.format,
settings.zero_suppression),
)
return gerber
def generate_closed_paths(statements, error_range=0):
from gerberex.dxf import DxfLineStatement, DxfArcStatement
paths = [DxfPath(s, error_range) \
for s in filter(lambda s: isinstance(s, DxfLineStatement) or \
isinstance(s, DxfArcStatement), statements)]
prev_paths_num = 0
while prev_paths_num != len(paths):
working = []
for i in range(len(paths)):
mergee = paths[i]
for j in range(i + 1, len(paths) - 1):
target = paths[j]
if target.merge(mergee, error_range):
break
else:
working.append(mergee)
prev_paths_num = len(paths)
paths = working
return list(filter(lambda p: p.is_closed, paths))

View file

@ -14,7 +14,7 @@ def read(fname):
METADATA = {
'name': 'pcb-tools-extension',
'version': "0.1.1",
'version': "0.1.2",
'author': 'Hiroshi Murayama <opiopan@gmail.com>',
'author_email': "opiopan@gmail.com",
'description': ("Extension for pcb-tools package to panelize gerber files"),

View file

@ -1,370 +0,0 @@
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

File diff suppressed because it is too large Load diff

View file

@ -1,552 +0,0 @@
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

View file

@ -1,51 +0,0 @@
#!/usr/bin/env python
import os
import gerberex
from gerberex.dxf import DxfFile
exts = ['GTL', 'GTO', 'GTP', 'GTS', 'GBL', 'GBO', 'GBP', 'GBS', 'TXT']
boards=[
('../../sonopi-digi/pcb/CAMOutputs/sonopi-digi.', 0, 0),
('../../sonopi-digi/pcb/CAMOutputs/sonopi-digi.', 0, 22.5),
('../../rcstick-f/pcb/small/CAMOutputs/rcstick-f-small.', 0, 60),
('../../rcstick-f/pcb/small/CAMOutputs/rcstick-f-small.', 20, 60),
('../../rcstick-f/pcb/small/CAMOutputs/rcstick-f-small.', 40, 60),
('../../rcstick-f/pcb/large/CAMOutputs/rcstick-f.', 72.4, 0),
('../../rcstick-f/pcb/jig/CAMOutputs/rcstick-jig.', 0, 44),
('../../stm32breakout/pcb/CAMOutputs/stm32breakout.', 78.0, 59.36),
('../../stm32breakout/pcb/CAMOutputs/stm32breakout.', 100.0, 59.36),
]
outline = 'outline.dxf'
fill = 'fill.dxf'
outputs = 'outputs/elecrow-panelized'
os.chdir(os.path.dirname(__file__))
for ext in exts:
print('merging %s: ' % ext ,end='', flush=True)
if ext == 'TXT':
ctx = gerberex.DrillComposition()
else:
ctx = gerberex.GerberComposition()
for board in boards:
file = gerberex.read(board[0] + ext)
file.to_metric()
file.offset(board[1], board[2])
ctx.merge(file)
print('.', end='', flush=True)
if ext != 'TXT':
file = gerberex.read(outline)
ctx.merge(file)
ctx.dump(outputs + '.' + ext)
print(' end', flush=True)
print('generating GML: ', end='', flush=True)
file = gerberex.read(outline)
file.write(outputs + '.GML')
print('.', end='', flush=True)
file = gerberex.read(fill)
file.to_metric()
file.draw_mode = DxfFile.DM_FILL
file.write(outputs + '-fill.GML')
print('. end', flush=True)

View file

@ -1,344 +0,0 @@
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

View file

@ -1,652 +0,0 @@
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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,45 +0,0 @@
M48
;GenerationSoftware,Autodesk,EAGLE,9.3.0*%
;CreationDate,2019-03-17T14:26:03Z*%
FMAT,2
ICI,OFF
METRIC,TZ,000.000
T5C0.350
T4C0.508
T3C0.800
T2C0.930
T1C1.200
%
G90
M71
T1
X5450Y2685
X9950Y2685
T2
X11200Y4785
X8700Y4785
X6700Y4785
X4200Y4785
T3
X5588Y25527
T4
X2062Y6253
X2062Y7503
X2062Y8753
X2062Y10003
T5
X4191Y15113
X11557Y15494
X7747Y17018
X7747Y9017
X4064Y27178
X7112Y27178
X8890Y26035
X1651Y24892
X6096Y22479
X12700Y18796
X13335Y18161
X7747Y22225
X7112Y23907
X14450Y34250
M30

View file

@ -1,626 +0,0 @@
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*

View file

@ -1,38 +0,0 @@
#!/usr/bin/env python
from gerber import load_layer
from gerber.render import RenderSettings, theme
from gerber.render.cairo_backend import GerberCairoContext
print('loading ', end='', flush=True)
copper = load_layer('panelized.GTL')
print('.', end='', flush=True)
mask = load_layer('panelized.GTS')
print('.', end='', flush=True)
silk = load_layer('panelized.GTO')
print('.', end='', flush=True)
drill = load_layer('panelized.TXT')
print('.', end='', flush=True)
outline = load_layer('panelized-fill.GML')
print('.', end='', flush=True)
print('. end', flush=True)
print('panelizing ', end='', flush=True)
ctx = GerberCairoContext(scale=30)
print('.', end='', flush=True)
ctx.render_layer(copper)
print('.', end='', flush=True)
ctx.render_layer(mask)
print('.', end='', flush=True)
our_settings = RenderSettings(color=theme.COLORS['white'], alpha=0.85)
ctx.render_layer(silk, settings=our_settings)
print('.', end='', flush=True)
ctx.render_layer(outline)
print('.', end='', flush=True)
ctx.render_layer(drill)
print('.', end='', flush=True)
print('. end', flush=True)
print('dumping top...')
ctx.dump('panelized.png')

View file

@ -1,98 +0,0 @@
import os
import gerberex
from gerberex.dxf import DxfFile
import gerber
from gerber.render.cairo_backend import GerberCairoContext
def merge():
ctx = gerberex.GerberComposition()
a = gerberex.read('test.GTL')
a.to_metric()
ctx.merge(a)
b = gerberex.read('test.GTL')
b.to_metric()
b.offset(0, 25)
ctx.merge(b)
c = gerberex.read('test2.GTL')
c.to_metric()
c.offset(0, 60)
ctx.merge(c)
c = gerberex.read('test.GML')
c.to_metric()
ctx.merge(c)
ctx.dump('test-merged.GTL')
def merge2():
ctx = gerberex.DrillComposition()
a = gerberex.read('test.TXT')
a.to_metric()
ctx.merge(a)
b = gerberex.read('test.TXT')
b.to_metric()
b.offset(0, 25)
ctx.merge(b)
c = gerberex.read('test2.TXT')
c.to_metric()
c.offset(0, 60)
ctx.merge(c)
ctx.dump('test-merged.TXT')
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')
file = gerberex.read('data/test.TXT')
file.rotate(45)
file.write('outputs/test_changed.TXT')
file = gerberex.read('data/outline.dxf')
file.to_metric()
w = file.width
file.draw_mode = DxfFile.DM_FILL
file.write('outline.GML')
copper = gerber.load_layer('test-merged.GTL')
ctx = GerberCairoContext(scale=10)
ctx.render_layer(copper)
outline = gerber.load_layer('test.GML')
outline.cam_source.to_metric()
ctx.render_layer(outline)
drill = gerber.load_layer('test-merged.TXT')
ctx.render_layer(drill)
ctx.dump('test.png')