1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2019 Hiroshi Murayama <opiopan@gmail.com>
import gerber.rs274x
from gerber.gerber_statements import ADParamStmt, CoordStmt
from gerberex.gerber_statements import AMParamStmt, AMParamStmtEx, ADParamStmtEx
from gerberex.utility import rotate
class GerberFile(gerber.rs274x.GerberFile):
@classmethod
def from_gerber_file(cls, gerber_file):
if not isinstance(gerber_file, gerber.rs274x.GerberFile):
raise Exception('only gerber.rs274x.GerberFile object is specified')
def swap_statement(statement):
if isinstance(statement, AMParamStmt) and not isinstance(statement, AMParamStmtEx):
return AMParamStmtEx.from_stmt(statement)
elif isinstance(statement, ADParamStmt) and not isinstance(statement, AMParamStmtEx):
return ADParamStmtEx.from_stmt(statement)
else:
return statement
statements = [swap_statement(statement) for statement in gerber_file.statements]
return cls(statements, gerber_file.settings, gerber_file.primitives,\
gerber_file.apertures, gerber_file.filename)
def __init__(self, statements, settings, primitives, apertures, filename=None):
super(GerberFile, self).__init__(statements, settings, primitives, apertures, filename)
def offset(self, x_offset=0, y_offset=0):
for statement in self.statements:
if isinstance(statement, CoordStmt):
if statement.x is not None:
statement.x += x_offset
if statement.y is not None:
statement.y += y_offset
else:
statement.offset(x_offset, y_offset)
for primitive in self.primitives:
primitive.offset(x_offset, y_offset)
def rotate(self, angle, center=(0,0)):
if angle % 360 == 0:
return
self._generalize_aperture()
last_x = 0
last_y = 0
last_rx = 0
last_ry = 0
for statement in self.statements:
if isinstance(statement, AMParamStmtEx):
statement.rotate(angle, center)
elif isinstance(statement, CoordStmt) and statement.x != None and statement.y != None:
if statement.i != None and statement.j != None:
cx = last_x + statement.i
cy = last_y + statement.j
cx, cy = rotate(cx, cy, angle, center)
statement.i = cx - last_rx
statement.j = cy - last_ry
last_x = statement.x
last_y = statement.y
last_rx, last_ry = rotate(statement.x, statement.y, angle, center)
statement.x = last_rx
statement.y = last_ry
def _generalize_aperture(self):
RECTANGLE = 0
LANDSCAPE_OBROUND = 1
PORTRATE_OBROUND = 2
POLYGON = 3
macro_defs = [
('MACR', AMParamStmtEx.rectangle),
('MACLO', AMParamStmtEx.landscape_obround),
('MACPO', AMParamStmtEx.portrate_obround),
('MACP', AMParamStmtEx.polygon)
]
need_to_change = False
insert_point = 0
last_aperture = 0
macros = {}
for idx in range(0, len(self.statements)):
statement = self.statements[idx]
if isinstance(statement, AMParamStmtEx):
macros[statement.name] = statement
if not need_to_change:
insert_point = idx + 1
if isinstance(statement, ADParamStmt) and statement.shape in ['R', 'O', 'P']:
need_to_change = True
last_aperture = idx
if need_to_change:
for idx in range(0, len(macro_defs)):
macro_def = macro_defs[idx]
name = macro_def[0]
num = 1
while name in macros:
name = '%s_%d' % (macro_def[0], num)
num += 1
self.statements.insert(insert_point, macro_def[1](name, self.units))
macro_defs[idx] = (name, macro_def[1])
for idx in range(insert_point, last_aperture + len(macro_defs) + 1):
statement = self.statements[idx]
if isinstance(statement, ADParamStmt):
if statement.shape == 'R':
statement.shape = macro_defs[RECTANGLE][0]
elif statement.shape == 'O':
x = statement.modifiers[0][0] \
if len(statement.modifiers[0]) > 0 else 0
y = statement.modifiers[0][1] \
if len(statement.modifiers[0]) > 1 else 0
statement.shape = macro_defs[LANDSCAPE_OBROUND][0] \
if x > y else macro_defs[PORTRATE_OBROUND][0]
elif statement.shape == 'P':
statement.shape = macro_defs[POLYGON][0]
|