-
Notifications
You must be signed in to change notification settings - Fork 0
/
geometry.py
107 lines (99 loc) · 3.21 KB
/
geometry.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
import numpy as np
from gdspy import Cell, Round, fast_boolean
from functools import partial
MAX_POINTS = 4094#8191 # same as LayoutEditor
ROUND_POINTS = 100
Cell = partial(Cell, exclude_from_current=True)
Round = partial(Round, number_of_points=ROUND_POINTS, max_points=MAX_POINTS)
fast_boolean = partial(fast_boolean, max_points=MAX_POINTS)
def polygon_orientation(polygon):
# SEE: https://en.wikipedia.org/wiki/Curve_orientation
polygon = np.array(polygon)
x_min = polygon[:,0].min()
y_min = polygon[polygon[:,0] == x_min,1].min()
idx_b = np.where((polygon[:,0] == x_min) & (polygon[:,1] == y_min))[0][0]
idx_a = (idx_b - 1) % len(polygon)
idx_c = (idx_b + 1) % len(polygon)
x_a, y_a = polygon[idx_a]
x_b, y_b = polygon[idx_b]
x_c, y_c = polygon[idx_c]
det = (x_b - x_a) * (y_c - y_a) - (x_c - x_a) * (y_b - y_c)
return det
def get_bounding_box(polygons):
all_points = np.concatenate(polygons).transpose()
bbox = np.array(((all_points[0].min(), all_points[1].min()),
(all_points[0].max(), all_points[1].max())))
return bbox
def mirror(polygons, axis='y'):
x = y = False
if axis == 'both':
x = y = True
elif axis == 'x':
x = True
elif axis == 'y':
y = True
else:
raise ValueError('bad axis specification')
factor = np.ones(2)
if x:
factor[0] = -1
if y:
factor[1] = -1
polygons[:] = [factor*poly for poly in polygons]
return polygons
def mirror_refs(refs, axis='x'):
x = y = False
if axis == 'both':
x = y = True
elif axis == 'x':
x = True
elif axis == 'y':
y = True
else:
raise ValueError('bad axis specification')
factor = np.ones(2)
if x:
factor[0] = -1
if y:
factor[1] = -1
for ref in refs:
if x:
ref.rotation += 180
ref.x_reflection = not ref.x_reflection
if y:
raise NotImplementedError
ref.origin *= factor
return refs
# TODO: right/left switched
def align(polygons, position=(0, 0), alignment='left'):
bbox = get_bounding_box(polygons)
if alignment == 'left':
offset = np.array([bbox[1,0],0])
elif alignment == 'centered':
offset = np.array([(bbox[0,0] + bbox[1,0])/2,0])
elif alignment == 'right':
offset = np.array([bbox[0,0],0])
else:
raise NotImplementedError
factor = np.array([-1,1])
position = np.array(position) + offset
polygons[:] = [position + factor*poly for poly in polygons]
return polygons
def align_refs(refs, position=(0, 0), alignment='left'):
position = np.array(position)
polygons = sum([ref.get_polygons() for ref in refs], [])
bbox = get_bounding_box(polygons)
if alignment == 'right':
offset = -np.array([bbox[1,0],0])
elif alignment == 'centered':
offset = -np.array([(bbox[0,0] + bbox[1,0])/2,0])
elif alignment == 'left':
offset = -np.array([bbox[0,0],0])
else:
raise NotImplementedError
# position = np.array(position) + offset
# polygons[:] = [position + factor*poly for poly in polygons]
# return polygons
for ref in refs:
ref.origin += position + offset
return refs