Skip to content

Commit 37417da

Browse files
Fix for #187. solid.utils.extrude_along_path() was generating polyhedron() code that looked OK in preview, but that failed to render correctly in CGAL. This was caused by reversed face order, which would have been revealed if I'd looked at generated polyhedra with OpenSCAD's F12 'Thrown Together' view, which highlights inverted faces. Everything seems to be working well now, tests passing and the example file rendering correctly (if very slowly) in CGAL.
Note that OpenSCAD can accept vertex lists for non-triangular faces, and then does its own triangulations from them. However, the direction of triangulation for a given quad isn't reliable, which can lead to some odd appearances. At the expense of some extra facets, specify our own, regular, triangulation. End caps for extruded shapes, though-- those I'm leaving to OpenSCAD to triangulate, since the existing centroid-based system added complexity without covering significantly more edge cases than OpenSCAD's native triangulation
1 parent fa7dc9f commit 37417da

File tree

3 files changed

+34
-57
lines changed

3 files changed

+34
-57
lines changed

solid/examples/path_extrude_example.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,24 +148,23 @@ def point_trans(point: Point3, path_norm:float, loop_norm: float) -> Point3:
148148
# Rotate the points sinusoidally up to max_rotation
149149
p = p.rotate_around(up, max_rotation*sin(tau*path_norm))
150150

151-
152151
# Oscillate z values sinusoidally, growing from
153-
# 0 magnitude to max_z_displacement
154-
max_z = lerp(path_norm, 0, 1, 0, max_z_displacement)
152+
# 0 magnitude to max_z_displacement, then decreasing to 0 magnitude at path_norm == 1
153+
max_z = sin(pi*path_norm) * max_z_displacement
155154
angle = lerp(loop_norm, 0, 1, 0, 10*tau)
156155
p.z += max_z*sin(angle)
157156
return p
158157

159158
no_trans = make_label('No Transform')
160159
no_trans += down(height/2)(
161-
extrude_along_path(shape, path, cap_ends=False)
160+
extrude_along_path(shape, path, cap_ends=True)
162161
)
163162

164163
# We can pass transforms a single function that will be called on all points,
165164
# or pass a list with a transform function for each point along path
166165
arb_trans = make_label('Arbitrary Transform')
167166
arb_trans += down(height/2)(
168-
extrude_along_path(shape, path, transforms=[point_trans], cap_ends=False)
167+
extrude_along_path(shape, path, transforms=[point_trans], cap_ends=True)
169168
)
170169

171170
return no_trans + right(3*path_rad)(arb_trans)

solid/extrude_along_path.py

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -104,29 +104,18 @@ def transform_func(p:Point3, path_norm:float, loop_norm:float): Point3
104104
polyhedron_pts += this_loop
105105

106106
if connect_ends:
107-
next_loop_start_index = len(polyhedron_pts) - shape_pt_count
108-
loop_facets = _loop_facet_indices(0, shape_pt_count, next_loop_start_index)
107+
connect_loop_start_index = len(polyhedron_pts) - shape_pt_count
108+
loop_facets = _loop_facet_indices(connect_loop_start_index, shape_pt_count, 0)
109109
facet_indices += loop_facets
110110

111111
elif cap_ends:
112-
# endcaps at start & end of extrusion
113-
# NOTE: this block adds points & indices to the polyhedron, so it's
114-
# very sensitive to the order this is happening in
115-
start_cap_index = len(polyhedron_pts)
116-
end_cap_index = start_cap_index + 1
112+
# OpenSCAD's polyhedron will automatically triangulate faces as needed.
113+
# So just include all points at each end of the tube
117114
last_loop_start_index = len(polyhedron_pts) - shape_pt_count
118-
119-
start_loop_pts = polyhedron_pts[:shape_pt_count]
120-
end_loop_pts = polyhedron_pts[last_loop_start_index:]
121-
122-
start_loop_indices = list(range(0, shape_pt_count))
123-
end_loop_indices = list(range(last_loop_start_index, last_loop_start_index + shape_pt_count))
124-
125-
start_centroid, start_facet_indices = _end_cap(start_cap_index, start_loop_pts, start_loop_indices)
126-
end_centroid, end_facet_indices = _end_cap(end_cap_index, end_loop_pts, end_loop_indices)
127-
polyhedron_pts += [start_centroid, end_centroid]
128-
facet_indices += start_facet_indices
129-
facet_indices += end_facet_indices
115+
start_loop_indices = list(reversed(range(shape_pt_count)))
116+
end_loop_indices = list(range(last_loop_start_index, last_loop_start_index + shape_pt_count))
117+
facet_indices.append(start_loop_indices)
118+
facet_indices.append(end_loop_indices)
130119

131120
return polyhedron(points=euc_to_arr(polyhedron_pts), faces=facet_indices) # type: ignore
132121

@@ -139,13 +128,18 @@ def _loop_facet_indices(loop_start_index:int, loop_pt_count:int, next_loop_start
139128
next_loop_indices = list(range(next_loop_start_index, loop_pt_count + next_loop_start_index )) + [next_loop_start_index]
140129

141130
for i, (a, b) in enumerate(zip(loop_indices[:-1], loop_indices[1:])):
131+
c, d = next_loop_indices[i: i+2]
132+
# OpenSCAD's polyhedron will accept quads and do its own triangulation with them,
133+
# so we could just append (a,b,d,c).
134+
# However, this lets OpenSCAD (Or CGAL?) do its own triangulation, leading
135+
# to some strange outcomes. Prefer to do our own triangulation.
142136
# c--d
143137
# |\ |
144138
# | \|
145139
# a--b
146-
c, d = next_loop_indices[i: i+2]
147-
facet_indices.append((a,c,b))
148-
facet_indices.append((b,c,d))
140+
# facet_indices.append((a,b,d,c))
141+
facet_indices.append((a,b,c))
142+
facet_indices.append((b,d,c))
149143
return facet_indices
150144

151145
def _rotate_loop(points:Sequence[Point3], rotation_degrees:float=None) -> List[Point3]:
@@ -178,22 +172,3 @@ def _transform_loop(points:Sequence[Point3], transform_func:Point3Transform = No
178172
result.append(new_p)
179173
return result
180174

181-
def _end_cap(new_point_index:int, points:Sequence[Point3], vertex_indices: Sequence[int]) -> Tuple[Point3, List[FacetIndices]]:
182-
# Assume points are a basically planar, basically convex polygon with polyhedron
183-
# indices `vertex_indices`.
184-
# Return a new point that is the centroid of the polygon and a list of
185-
# vertex triangle indices that covers the whole polygon.
186-
# (We can actually accept relatively non-planar and non-convex polygons,
187-
# but not anything pathological. Stars are fine, internal pockets would
188-
# cause incorrect faceting)
189-
190-
# NOTE: In order to deal with moderately-concave polygons, we add a point
191-
# to the center of the end cap. This will have a new index that we require
192-
# as an argument.
193-
194-
new_point = centroid(points)
195-
new_facets = []
196-
second_indices = vertex_indices[1:] + [vertex_indices[0]]
197-
new_facets = [(new_point_index, a, b) for a, b in zip(vertex_indices, second_indices)]
198-
199-
return (new_point, new_facets)

solid/test/test_extrude_along_path.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,65 +28,68 @@ def test_extrude_along_path(self):
2828
path = [[0, 0, 0], [0, 20, 0]]
2929
# basic test
3030
actual = extrude_along_path(tri, path)
31-
expected = 'polyhedron(faces = [[0, 3, 1], [1, 3, 4], [1, 4, 2], [2, 4, 5], [2, 5, 0], [0, 5, 3], [6, 0, 1], [6, 1, 2], [6, 2, 0], [7, 3, 4], [7, 4, 5], [7, 5, 3]], points = [[0.0000000000, 0.0000000000, 0.0000000000], [10.0000000000, 0.0000000000, 0.0000000000], [0.0000000000, 0.0000000000, 10.0000000000], [0.0000000000, 20.0000000000, 0.0000000000], [10.0000000000, 20.0000000000, 0.0000000000], [0.0000000000, 20.0000000000, 10.0000000000], [3.3333333333, 0.0000000000, 3.3333333333], [3.3333333333, 20.0000000000, 3.3333333333]]);'
31+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[10.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[10.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,10.0000000000]]);'
3232
self.assertEqualOpenScadObject(expected, actual)
3333

3434
def test_extrude_along_path_vertical(self):
3535
# make sure we still look good extruding along z axis; gimbal lock can mess us up
3636
vert_path = [[0, 0, 0], [0, 0, 20]]
3737
actual = extrude_along_path(tri, vert_path)
38-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[6,0,1],[6,1,2],[6,2,0],[7,3,4],[7,4,5],[7,5,3]],points=[[0.0000000000,0.0000000000,0.0000000000],[-10.0000000000,0.0000000000,0.0000000000],[0.0000000000,10.0000000000,0.0000000000],[0.0000000000,0.0000000000,20.0000000000],[-10.0000000000,0.0000000000,20.0000000000],[0.0000000000,10.0000000000,20.0000000000],[-3.3333333333,3.3333333333,0.0000000000],[-3.3333333333,3.3333333333,20.0000000000]]);'
38+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[-10.0000000000,0.0000000000,0.0000000000],[0.0000000000,10.0000000000,0.0000000000],[0.0000000000,0.0000000000,20.0000000000],[-10.0000000000,0.0000000000,20.0000000000],[0.0000000000,10.0000000000,20.0000000000]]); '
3939
self.assertEqualOpenScadObject(expected, actual)
4040

4141
def test_extrude_along_path_1d_scale(self):
4242
# verify that we can apply scalar scaling
4343
path = [[0, 0, 0], [0, 20, 0]]
4444
scales_1d = [1.5, 0.5]
4545
actual = extrude_along_path(tri, path, scales=scales_1d)
46-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[6,0,1],[6,1,2],[6,2,0],[7,3,4],[7,4,5],[7,5,3]],points=[[0.0000000000,0.0000000000,0.0000000000],[15.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,15.0000000000],[0.0000000000,20.0000000000,0.0000000000],[5.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,5.0000000000],[5.0000000000,0.0000000000,5.0000000000],[1.6666666667,20.0000000000,1.6666666667]]);'
46+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[15.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,15.0000000000],[0.0000000000,20.0000000000,0.0000000000],[5.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,5.0000000000]]);'
47+
print('test_extrude_along_path_1d_scale')
48+
4749
self.assertEqualOpenScadObject(expected, actual)
4850

4951
def test_extrude_along_path_2d_scale(self):
5052
# verify that we can apply differential x & y scaling
5153
path = [[0, 0, 0], [0, 20, 0], [0, 40, 0]]
5254
scales_2d = [Point2(1,1), Point2(0.5, 1.5), Point2(1.5, 0.5), ]
5355
actual = extrude_along_path(tri, path, scales=scales_2d)
54-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[3,6,4],[4,6,7],[4,7,5],[5,7,8],[5,8,3],[3,8,6],[9,0,1],[9,1,2],[9,2,0],[10,6,7],[10,7,8],[10,8,6]],points=[[0.0000000000,0.0000000000,0.0000000000],[10.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[5.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,15.0000000000],[0.0000000000,40.0000000000,0.0000000000],[15.0000000000,40.0000000000,0.0000000000],[0.0000000000,40.0000000000,5.0000000000],[3.3333333333,0.0000000000,3.3333333333],[5.0000000000,40.0000000000,1.6666666667]]);'
56+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[3,4,6],[4,7,6],[4,5,7],[5,8,7],[5,3,8],[3,6,8],[2,1,0],[6,7,8]],points=[[0.0000000000,0.0000000000,0.0000000000],[10.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[5.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,15.0000000000],[0.0000000000,40.0000000000,0.0000000000],[15.0000000000,40.0000000000,0.0000000000],[0.0000000000,40.0000000000,5.0000000000]]);'
5557
self.assertEqualOpenScadObject(expected, actual)
5658

5759
def test_extrude_along_path_2d_scale_list_input(self):
5860
# verify that we can apply differential x & y scaling
5961
path = [[0, 0, 0], [0, 20, 0], [0, 40, 0]]
6062
scales_2d = [(1,1), (0.5, 1.5), (1.5, 0.5), ]
6163
actual = extrude_along_path(tri, path, scales=scales_2d)
62-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[3,6,4],[4,6,7],[4,7,5],[5,7,8],[5,8,3],[3,8,6],[9,0,1],[9,1,2],[9,2,0],[10,6,7],[10,7,8],[10,8,6]],points=[[0.0000000000,0.0000000000,0.0000000000],[10.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[5.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,15.0000000000],[0.0000000000,40.0000000000,0.0000000000],[15.0000000000,40.0000000000,0.0000000000],[0.0000000000,40.0000000000,5.0000000000],[3.3333333333,0.0000000000,3.3333333333],[5.0000000000,40.0000000000,1.6666666667]]);'
64+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[3,4,6],[4,7,6],[4,5,7],[5,8,7],[5,3,8],[3,6,8],[2,1,0],[6,7,8]],points=[[0.0000000000,0.0000000000,0.0000000000],[10.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[5.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,15.0000000000],[0.0000000000,40.0000000000,0.0000000000],[15.0000000000,40.0000000000,0.0000000000],[0.0000000000,40.0000000000,5.0000000000]]);'
6365
self.assertEqualOpenScadObject(expected, actual)
6466

6567
def test_extrude_along_path_end_caps(self):
6668
path = [[0, 0, 0], [0, 20, 0]]
6769
actual = scad_render(extrude_along_path(tri, path, connect_ends=False))
68-
expected = 'polyhedron(faces = [[0, 3, 1], [1, 3, 4], [1, 4, 2], [2, 4, 5], [2, 5, 0], [0, 5, 3], [6, 0, 1], [6, 1, 2], [6, 2, 0], [7, 3, 4], [7, 4, 5], [7, 5, 3]], points = [[0.0000000000, 0.0000000000, 0.0000000000], [10.0000000000, 0.0000000000, 0.0000000000], [0.0000000000, 0.0000000000, 10.0000000000], [0.0000000000, 20.0000000000, 0.0000000000], [10.0000000000, 20.0000000000, 0.0000000000], [0.0000000000, 20.0000000000, 10.0000000000], [3.3333333333, 0.0000000000, 3.3333333333], [3.3333333333, 20.0000000000, 3.3333333333]]);'
70+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[10.0000000000,0.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[10.0000000000,20.0000000000,0.0000000000],[0.0000000000,20.0000000000,10.0000000000]]); '
6971
self.assertEqualNoWhitespace(expected, actual)
7072

7173
def test_extrude_along_path_connect_ends(self):
7274
path = [[0, 0, 0], [20, 0, 0], [20,20,0], [0,20, 0]]
7375
actual = extrude_along_path(tri, path, connect_ends=True)
74-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[3,6,4],[4,6,7],[4,7,5],[5,7,8],[5,8,3],[3,8,6],[6,9,7],[7,9,10],[7,10,8],[8,10,11],[8,11,6],[6,11,9],[0,9,1],[1,9,10],[1,10,2],[2,10,11],[2,11,0],[0,11,9]],points=[[0.0000000000,0.0000000000,0.0000000000],[-7.0710678119,-7.0710678119,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[20.0000000000,0.0000000000,0.0000000000],[27.0710678119,-7.0710678119,0.0000000000],[20.0000000000,0.0000000000,10.0000000000],[20.0000000000,20.0000000000,0.0000000000],[27.0710678119,27.0710678119,0.0000000000],[20.0000000000,20.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[-7.0710678119,27.0710678119,0.0000000000],[0.0000000000,20.0000000000,10.0000000000]]);'
76+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[3,4,6],[4,7,6],[4,5,7],[5,8,7],[5,3,8],[3,6,8],[6,7,9],[7,10,9],[7,8,10],[8,11,10],[8,6,11],[6,9,11],[9,10,0],[10,1,0],[10,11,1],[11,2,1],[11,9,2],[9,0,2]],points=[[0.0000000000,0.0000000000,0.0000000000],[-7.0710678119,-7.0710678119,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[20.0000000000,0.0000000000,0.0000000000],[27.0710678119,-7.0710678119,0.0000000000],[20.0000000000,0.0000000000,10.0000000000],[20.0000000000,20.0000000000,0.0000000000],[27.0710678119,27.0710678119,0.0000000000],[20.0000000000,20.0000000000,10.0000000000],[0.0000000000,20.0000000000,0.0000000000],[-7.0710678119,27.0710678119,0.0000000000],[0.0000000000,20.0000000000,10.0000000000]]); '
7577
self.assertEqualOpenScadObject(expected, actual)
7678

7779
def test_extrude_along_path_rotations(self):
80+
7881
# confirm we can rotate for each point in path
7982
path = [[0,0,0], [20, 0,0 ]]
8083
rotations = [-45, 45]
8184
actual = extrude_along_path(tri, path, rotations=rotations)
82-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[6,0,1],[6,1,2],[6,2,0],[7,3,4],[7,4,5],[7,5,3]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-7.0710678119,-7.0710678119],[0.0000000000,-7.0710678119,7.0710678119],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-7.0710678119,7.0710678119],[20.0000000000,7.0710678119,7.0710678119],[0.0000000000,-4.7140452079,0.0000000000],[20.0000000000,-0.0000000000,4.7140452079]]);'
85+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-7.0710678119,-7.0710678119],[0.0000000000,-7.0710678119,7.0710678119],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-7.0710678119,7.0710678119],[20.0000000000,7.0710678119,7.0710678119]]); '
8386
self.assertEqualOpenScadObject(expected, actual)
8487

8588
# confirm we can rotate with a single supplied value
8689
path = [[0,0,0], [20, 0,0 ]]
8790
rotations = [45]
8891
actual = extrude_along_path(tri, path, rotations=rotations)
89-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[6,0,1],[6,1,2],[6,2,0],[7,3,4],[7,4,5],[7,5,3]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-10.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-7.0710678119,7.0710678119],[20.0000000000,7.0710678119,7.0710678119],[0.0000000000,-3.3333333333,3.3333333333],[20.0000000000,-0.0000000000,4.7140452079]]);'
92+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-10.0000000000,0.0000000000],[0.0000000000,0.0000000000,10.0000000000],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-7.0710678119,7.0710678119],[20.0000000000,7.0710678119,7.0710678119]]); '
9093
self.assertEqualOpenScadObject(expected, actual)
9194

9295
def test_extrude_along_path_transforms(self):
@@ -95,13 +98,13 @@ def test_extrude_along_path_transforms(self):
9598
# Make sure we can take a transform function for each point in path
9699
transforms = [lambda p, path, loop: 2*p, lambda p, path, loop: 0.5*p]
97100
actual = extrude_along_path(tri, path, transforms=transforms)
98-
expected = 'polyhedron(faces=[[0,3,1],[1,3,4],[1,4,2],[2,4,5],[2,5,0],[0,5,3],[6,0,1],[6,1,2],[6,2,0],[7,3,4],[7,4,5],[7,5,3]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-20.0000000000,0.0000000000],[0.0000000000,0.0000000000,20.0000000000],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-5.0000000000,0.0000000000],[20.0000000000,0.0000000000,5.0000000000],[0.0000000000,-6.6666666667,6.6666666667],[20.0000000000,-1.6666666667,1.6666666667]]);'
101+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-20.0000000000,0.0000000000],[0.0000000000,0.0000000000,20.0000000000],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-5.0000000000,0.0000000000],[20.0000000000,0.0000000000,5.0000000000]]); '
99102
self.assertEqualOpenScadObject(expected, actual)
100103

101104
# Make sure we can take a single transform function for all points
102105
transforms = [lambda p, path, loop: 2*p]
103106
actual = extrude_along_path(tri, path, transforms=transforms)
104-
expected = 'polyhedron(faces = [[0, 3, 1], [1, 3, 4], [1, 4, 2], [2, 4, 5], [2, 5, 0], [0, 5, 3], [6, 0, 1], [6, 1, 2], [6, 2, 0], [7, 3, 4], [7, 4, 5], [7, 5, 3]], points = [[0.0000000000, 0.0000000000, 0.0000000000], [0.0000000000, -20.0000000000, 0.0000000000], [0.0000000000, 0.0000000000, 20.0000000000], [20.0000000000, 0.0000000000, 0.0000000000], [20.0000000000, -20.0000000000, 0.0000000000], [20.0000000000, 0.0000000000, 20.0000000000], [0.0000000000, -6.6666666667, 6.6666666667], [20.0000000000, -6.6666666667, 6.6666666667]]);'
107+
expected = 'polyhedron(faces=[[0,1,3],[1,4,3],[1,2,4],[2,5,4],[2,0,5],[0,3,5],[2,1,0],[3,4,5]],points=[[0.0000000000,0.0000000000,0.0000000000],[0.0000000000,-20.0000000000,0.0000000000],[0.0000000000,0.0000000000,20.0000000000],[20.0000000000,0.0000000000,0.0000000000],[20.0000000000,-20.0000000000,0.0000000000],[20.0000000000,0.0000000000,20.0000000000]]);'
105108
self.assertEqualOpenScadObject(expected, actual)
106109

107110
def test_extrude_along_path_numpy(self):

0 commit comments

Comments
 (0)