Skip to content

Commit 338522d

Browse files
committed
offsets cleaned up
1 parent 9e0c891 commit 338522d

File tree

1 file changed

+47
-36
lines changed

1 file changed

+47
-36
lines changed

src/compas/geometry/offset/offset.py

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,32 @@
2121
]
2222

2323

24-
def offset_line(line, distance, normal=[0., 0., 1.]):
24+
def offset_line(line, distance, normal=[0.0, 0.0, 1.0]):
2525
"""Offset a line by a distance.
2626
2727
Parameters
2828
----------
2929
line : tuple
3030
Two points defining the line.
31-
distances : float or tuples of floats
31+
distances : float or list of floats
3232
The offset distance as float.
3333
A single value determines a constant offset. Alternatively, two
3434
offset values for the start and end point of the line can be used to
3535
a create variable offset.
36-
normal : tuple
36+
normal : vector
3737
The normal of the offset plane.
3838
3939
Returns
4040
-------
41-
offset line (tuple)
41+
offset line : tuple
4242
Two points defining the offset line.
4343
44+
Notes
45+
-----
46+
The offset direction is chosen such that if the line were along the positve
47+
X axis and the normal of the offset plane is along the positive Z axis, the
48+
offset line is in the direction of the postive Y axis.
49+
4450
Examples
4551
--------
4652
.. code-block:: python
@@ -56,20 +62,20 @@ def offset_line(line, distance, normal=[0., 0., 1.]):
5662
print(line_offset)
5763
5864
"""
59-
pt1, pt2 = line[0], line[1]
60-
vec = subtract_vectors(pt1, pt2)
61-
dir_vec = normalize_vector(cross_vectors(vec, normal))
65+
a, b = line
66+
ab = subtract_vectors(b, a)
67+
direction = normalize_vector(cross_vectors(normal, ab))
6268

63-
if isinstance(distance, list) or isinstance(distance, tuple):
69+
if isinstance(distance, (list, tuple)):
6470
distances = distance
6571
else:
6672
distances = [distance, distance]
6773

68-
vec_pt1 = scale_vector(dir_vec, distances[0])
69-
vec_pt2 = scale_vector(dir_vec, distances[1])
70-
pt1_new = add_vectors(pt1, vec_pt1)
71-
pt2_new = add_vectors(pt2, vec_pt2)
72-
return pt1_new, pt2_new
74+
u = scale_vector(direction, distances[0])
75+
v = scale_vector(direction, distances[1])
76+
c = add_vectors(a, u)
77+
d = add_vectors(b, v)
78+
return c, d
7379

7480

7581
def offset_polygon(polygon, distance):
@@ -80,7 +86,7 @@ def offset_polygon(polygon, distance):
8086
polygon : list of point
8187
The XYZ coordinates of the corners of the polygon.
8288
The first and last coordinates must not be identical.
83-
distance : float or list of tuples of floats
89+
distance : float or list of float
8490
The offset distance as float.
8591
A single value determines a constant offset globally.
8692
Alternatively, pairs of local offset values per line segment can be used to create variable offsets.
@@ -95,6 +101,10 @@ def offset_polygon(polygon, distance):
95101
Notes
96102
-----
97103
The offset direction is determined by the normal of the polygon.
104+
If the polygon is in the XY plane and the normal is along the positive Z axis,
105+
positive offset distances will result in an offset towards the inside of the
106+
polygon.
107+
98108
The algorithm works also for spatial polygons that do not perfectly fit a plane.
99109
100110
Examples
@@ -133,7 +143,6 @@ def offset_polygon(polygon, distance):
133143
distances = [distance] * p
134144

135145
d = len(distances)
136-
137146
if d < p:
138147
distances.extend(distances[-1:] * (p - d))
139148

@@ -154,7 +163,7 @@ def offset_polygon(polygon, distance):
154163
return points
155164

156165

157-
def offset_polyline(polyline, distance, normal=[0., 0., 1.]):
166+
def offset_polyline(polyline, distance, normal=[0.0, 0.0, 1.0]):
158167
"""Offset a polyline by a distance.
159168
160169
Parameters
@@ -166,7 +175,7 @@ def offset_polyline(polyline, distance, normal=[0., 0., 1.]):
166175
A single value determines a constant offset globally.
167176
Alternatively, pairs of local offset values per line segment can be used to create variable offsets.
168177
Distance > 0: offset to the "left", distance < 0: offset to the "right".
169-
normal : tuple
178+
normal : vector
170179
The normal of the offset plane.
171180
172181
Returns
@@ -176,29 +185,31 @@ def offset_polyline(polyline, distance, normal=[0., 0., 1.]):
176185
177186
"""
178187

179-
if isinstance(distance, list) or isinstance(distance, tuple):
188+
p = len(polyline)
189+
190+
if isinstance(distance, (list, tuple)):
180191
distances = distance
181-
if len(distances) < len(polyline):
182-
distances = distances + [distances[-1]] * (len(polyline) - len(distances) - 1)
183192
else:
184-
distances = [[distance, distance]] * len(polyline)
193+
distances = [distance] * p
185194

186-
lines = [polyline[i:i + 2] for i in range(len(polyline[:-1]))]
187-
lines_offset = []
188-
for i, line in enumerate(lines):
189-
lines_offset.append(offset_line(line, distances[i], normal))
195+
d = len(distances)
196+
if d < p:
197+
distances.extend(distances[-1:] * (p - d))
190198

191-
polyline_offset = []
192-
polyline_offset.append(lines_offset[0][0])
193-
for i in range(len(lines_offset[:-1])):
194-
intx_pt1, intx_pt2 = intersection_line_line(lines_offset[i], lines_offset[i + 1])
199+
offset = []
200+
for line, distance in zip(pairwise(polyline), distances):
201+
offset.append(offset_line(line, distance, normal))
195202

196-
if intx_pt1 and intx_pt2:
197-
polyline_offset.append(centroid_points([intx_pt1, intx_pt2]))
203+
points = [offset[0][0]]
204+
for l1, l2 in pairwise(offset):
205+
x1, x2 = intersection_line_line(l1, l2)
206+
if x1 and x2:
207+
points.append(centroid_points([x1, x2]))
198208
else:
199-
polyline_offset.append(lines_offset[i][0])
200-
polyline_offset.append(lines_offset[-1][1])
201-
return polyline_offset
209+
points.append(x1)
210+
points.append(offset[-1][1])
211+
212+
return points
202213

203214

204215
# ==============================================================================
@@ -218,7 +229,7 @@ def offset_polyline(polyline, distance, normal=[0., 0., 1.]):
218229
lines = []
219230
for fkey in mesh.faces():
220231
points = mesh.face_coordinates(fkey)
221-
offset = offset_polygon(points, 0.1)
232+
offset = offset_polyline(points, 0.1)
222233
polygons.append({
223234
'points': offset,
224235
'edgecolor': '#ff0000'
@@ -232,6 +243,6 @@ def offset_polyline(polyline, distance, normal=[0., 0., 1.]):
232243

233244
plotter = MeshPlotter(mesh)
234245
plotter.draw_faces()
235-
plotter.draw_polygons(polygons)
246+
plotter.draw_polylines(polygons)
236247
plotter.draw_lines(lines)
237248
plotter.show()

0 commit comments

Comments
 (0)