-
Notifications
You must be signed in to change notification settings - Fork 2
/
device_geo.py
156 lines (130 loc) · 4.92 KB
/
device_geo.py
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import matplotlib.pyplot as plt
import numpy as np
from shapely.geometry import Polygon
from shapely.geometry.polygon import orient
import shapely.affinity as affine
import ezdxf
class Device:
'''
Devices consist of a collection of features which are healed together
'''
def __init__(self):
self.features = {}
def register_feature(self, feature, delx, dely, theta, layer, origin='center'):
'''
Register a feature to the device to the given layer
Requires translation and rotation arguments to place the Feature in the
Device coordinate system
'''
new_feature = feature.copy()
new_feature.rotate_and_translate(delx, dely, theta, origin)
if layer in self.features:
self.features[layer].append(new_feature)
else:
self.features[layer] = [new_feature]
def heal(self):
'''
heals all the polygons together in a given device layer
'''
for layer in self.features.keys():
healed = self.features[layer][0].copy()
for i, feature in enumerate(self.features[layer]):
if i != 0:
healed.poly = healed.poly.union(feature.poly)
self.features[layer] = [healed]
def scale(self, layer, xfact, yfact, origin='center'):
'''
Scales each feature in the given layer by xfact and yfact
Scale can take either center or centroid
'''
self.features[layer].scale(xfact, yfact, origin)
def gen_fig(self):
'''
Return a figure of the feature colored by layer
'''
fig = plt.figure()
for layer in self.features.keys():
for feature in self.features[layer]:
if type(feature.poly) == Polygon:
x, y = feature.poly.exterior.coords.xy
plt.plot(x, y, color='C'+str(layer))
else:
for poly in feature.poly:
x, y = poly.exterior.coords.xy
plt.plot(x, y, color='C'+str(layer))
return fig
def write_dxf(self, fname='output.dxf'):
'''
Return a dxf file. Writes layers to layers
'''
doc = ezdxf.new(dxfversion='R2010', setup=True)
msp = doc.modelspace()
for layer in self.features.keys():
if layer != 0:
doc.layers.new(name=str(layer), dxfattribs={'color': layer})
for feature in self.features[layer]:
if type(feature.poly) == Polygon:
msp.add_lwpolyline(list(feature.poly.exterior.coords),
dxfattribs={'layer': str(layer)})
else:
for poly in feature.poly:
msp.add_lwpolyline(list(poly.exterior.coords),
dxfattribs={'layer': str(layer)})
doc.saveas(fname)
class Feature:
'''
A feature should be considered a single polygon which can be combined with other
features to form a device
'''
def __init__(self, ps):
"""
Generates a shapely polygon for a given feature
ps: list of tuples of points for polygon
"""
self.update_shape(ps)
def update_shape(self, ps):
"""
updates the coordinates of the polygon and sets to be clockwise
"""
self.poly = Polygon(ps)
self.poly2cw()
def poly2cw(self):
'''
Forces verticies of polygon to be clockwise
'''
self.poly = orient(self.poly, -1)
def rotate_and_translate(self, delx, dely, theta, origin='center'):
'''
Rotate and translate the polygon
Rotate can take either center or centroid
'''
self.poly = affine.rotate(self.poly, theta, origin)
self.poly = affine.translate(self.poly, delx, dely)
def scale(self, xfact, yfact, origin='center'):
'''
Scale the feature by xfact and yfact
Scale can take either center or centroid
'''
self.poly = affine.scale(self.poly, xfact, yfact, 1, origin)
def union(self, ps):
'''
Union a new polygon with the feature to form a new combined feature
Returns an error if the polygons are disjoint
'''
new_poly = Polygon(ps)
new_poly = self.poly.union(new_poly)
if type(new_poly) != Polygon:
raise ValueError('Polygons are disjoint')
else:
self.poly = new_poly
self.poly2cw()
def gen_fig(self):
'''
Return a figure of the feature
'''
x, y = self.poly.exterior.coords.xy
fig = plt.figure()
plt.plot(x, y)
return fig
def copy(self):
return Feature(self.poly.exterior.coords)