1# Copyright (c) 2018-2021 Manfred Moitzi 2# License: MIT License 3from ezdxf.render.forms import ( 4 circle, close_polygon, cube, extrude, cylinder, 5 cone, square, box, ngon, 6) 7from ezdxf.render.forms import open_arrow, arrow2 8from ezdxf.render.forms import ( 9 spline_interpolation, 10 spline_interpolated_profiles, 11) 12from ezdxf.render.forms import from_profiles_linear, from_profiles_spline 13from ezdxf.render.forms import rotation_form, ngon_to_triangles 14from ezdxf.render.forms import translate, rotate, scale 15from ezdxf.math import Vec3, close_vectors 16 17 18def test_circle_open(): 19 c = list(circle(8)) 20 assert len(c) == 8 21 22 23def test_circle_closed(): 24 c = list(circle(8, close=True)) 25 assert len(c) == 9 26 27 28def test_close_polygon(): 29 p = list(close_polygon([(1, 0), (2, 0), (3, 0), (4, 0)])) 30 assert len(p) == 5 31 assert p[4] == (1, 0) 32 33 34def test_close_polygon_without_doublets(): 35 p = list(close_polygon([(1, 0), (2, 0), (3, 0), (4, 0), (1, 0)])) 36 assert len(p) == 5 37 38 39def test_close_circle(): 40 assert len(list(circle(8, close=True))) == 9 41 assert len(list(close_polygon(circle(8, close=True)))) == 9 42 assert len(list(close_polygon(circle(8, close=False)))) == 9 43 44 45def test_square(): 46 sq = square(2) 47 assert len(sq) == 4 48 assert close_vectors(sq, [(0, 0), (2, 0), (2, 2), (0, 2)]) 49 50 51def test_box(): 52 b = box(3, 2) 53 assert len(b) == 4 54 assert close_vectors(b, [(0, 0), (3, 0), (3, 2), (0, 2)]) 55 56 57def test_open_arrow(): 58 a = open_arrow(3, 60) 59 assert len(a) == 3 60 assert close_vectors(a, [(-3, 1.5), (0, 0), (-3, -1.5)]) 61 62 63def test_closed_arrow(): 64 a = arrow2(3, 60, 45) 65 assert len(a) == 4 66 assert close_vectors(a, [(-3, 1.5), (0, 0), (-3, -1.5), (-1.5, 0)]) 67 68 69def test_cube(): 70 c = cube(center=True) 71 assert len(c.vertices) == 8 72 assert len(c.faces) == 6 73 74 c = cube(center=False) 75 assert len(c.vertices) == 8 76 assert len(c.faces) == 6 77 78 79def test_extrude(): 80 profile = [(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)] 81 path = ((0, 0, 0), (0, 0, 1)) 82 mesh = extrude(profile, path, close=True) 83 assert len(mesh.vertices) == 8 84 assert len(mesh.faces) == 4 85 86 87def test_from_profiles_linear(): 88 bottom = [(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)] 89 top = [(0, 0, 1), (1, 0, 1), (1, 1, 1), (0, 1, 1)] 90 mesh = from_profiles_linear([bottom, top], close=True, caps=True) 91 assert len(mesh.vertices) == 8 92 assert len(mesh.faces) == 6 93 94 mesh = from_profiles_linear([bottom, top], close=True, caps=False) 95 assert len(mesh.vertices) == 8 96 assert len(mesh.faces) == 4 97 98 99def in_vertices(v, vertices): 100 v = Vec3(v) 101 return any(v.isclose(v2) for v2 in vertices) 102 103 104def test_cylinder(): 105 mesh = cylinder(12) 106 assert len(mesh.faces) == 14 # 1x bottom, 1x top, 12x side 107 assert len(mesh.vertices) == 24 # 12x bottom, 12x top 108 109 mesh = cylinder(count=12, radius=3, top_radius=2, top_center=(1, 0, 3), 110 caps=False) 111 assert len(mesh.faces) == 12 112 assert len(mesh.vertices) == 24 113 assert in_vertices((3, 0, 3), mesh.vertices) 114 assert in_vertices((-1, 0, 3), mesh.vertices) 115 116 117def test_spline_interpolation(): 118 vertices = [(0., 0.), (1., 2.), (3., 1.), (5., 3.)] 119 result = spline_interpolation(vertices, method='uniform', subdivide=4) 120 assert len(result) == 13 # (len-1) * subdivide + 1 121 assert Vec3(0, 0, 0).isclose(result[0]), 'expected start point' 122 assert Vec3(5, 3, 0).isclose(result[-1]), 'expected end point' 123 assert Vec3(1, 2, 0).isclose(result[4]), 'expected 2. fit point' 124 assert Vec3(3, 1, 0).isclose(result[8]), 'expected 3. fit point' 125 126 127def test_spline_interpolated_profiles(): 128 p1 = circle(12, radius=2, elevation=0, close=True) 129 p2 = circle(12, radius=3, elevation=2, close=True) 130 p3 = circle(12, radius=1, elevation=4, close=True) 131 p4 = circle(12, radius=2, elevation=6, close=True) 132 profiles = list(spline_interpolated_profiles([p1, p2, p3, p4], subdivide=4)) 133 assert len(profiles) == 13 # 3*4 + 1 134 135 136def test_from_profiles_splines(): 137 p1 = circle(12, radius=2, elevation=0, close=True) 138 p2 = circle(12, radius=3, elevation=2, close=True) 139 p3 = circle(12, radius=1, elevation=4, close=True) 140 p4 = circle(12, radius=2, elevation=6, close=True) 141 mesh = from_profiles_spline([p1, p2, p3, p4], subdivide=4, caps=True) 142 assert len(mesh.vertices) == 156 # 12 (circle) * 13 (profiles) 143 assert len(mesh.faces) == 146 # 12 (circle) * 12 + 2 144 145 146def test_cone(): 147 mesh = cone(12, 2, apex=(0, 0, 3)) 148 assert len(mesh.vertices) == 13 149 assert len(mesh.faces) == 13 150 151 152def test_rotation_form(): 153 profile = [(0, 0.1), (1, 1), (3, 1.5), (5, 3)] # in xy-plane 154 mesh = rotation_form(count=16, profile=profile, 155 axis=(1, 0, 0)) # rotation axis is the x-axis 156 assert len(mesh.vertices) == 16 * 4 157 assert len(mesh.faces) == 16 * 3 158 159 160def test_translate(): 161 p = [(1, 2, 3), (4, 5, 6)] 162 r = list(translate(p, (3, 2, 1))) 163 assert r[0].isclose((4, 4, 4)) 164 assert r[1].isclose((7, 7, 7)) 165 166 167def test_scale(): 168 p = [(1, 2, 3), (4, 5, 6)] 169 r = list(scale(p, (3, 2, 1))) 170 assert r[0].isclose((3, 4, 3)) 171 assert r[1].isclose((12, 10, 6)) 172 173 174def test_rotate(): 175 p = [(1, 0, 3), (0, 1, 6)] 176 r = list(rotate(p, 90, deg=True)) 177 assert r[0].isclose((0, 1, 3)) 178 assert r[1].isclose((-1, 0, 6)) 179 180 181def test_square_by_radius(): 182 corners = list(ngon(4, radius=1)) 183 assert len(corners) == 4 184 assert corners[0].isclose((1, 0, 0)) 185 assert corners[1].isclose((0, 1, 0)) 186 assert corners[2].isclose((-1, 0, 0)) 187 assert corners[3].isclose((0, -1, 0)) 188 189 190def test_heptagon_by_edge_length(): 191 corners = list(ngon(7, length=10)) 192 assert len(corners) == 7 193 assert corners[0].isclose((11.523824354812433, 0, 0)) 194 assert corners[1].isclose((7.184986963636852, 9.009688679024192, 0)) 195 assert corners[2].isclose((-2.564292158181384, 11.234898018587335, 0)) 196 assert corners[3].isclose((-10.382606982861683, 5, 0)) 197 assert corners[4].isclose((-10.382606982861683, -5, 0)) 198 assert corners[5].isclose((-2.564292158181387, -11.234898018587335, 0)) 199 assert corners[6].isclose((7.18498696363685, -9.009688679024192, 0)) 200 201 202def test_ngons_to_triangles(): 203 open_square = square() 204 r = list(ngon_to_triangles(open_square)) 205 assert len(r) == 4 206 center = r[0][2] 207 assert center == (0.5, 0.5, 0) 208 209 closed_square = list(circle(4, elevation=2, close=True)) 210 assert len(closed_square) == 5 211 r = list(ngon_to_triangles(closed_square)) 212 assert len(r) == 4 213 center = r[0][2] 214 assert center.isclose((0, 0, 2)) 215 216 # also subdivide triangles 217 r = list(ngon_to_triangles([(0, 0), (1, 0), (1, 1)])) 218 assert len(r) == 3 219