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
7581def 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