1# Copyright (c) 2018-2020, Manfred Moitzi
2# License: MIT License
3import pytest
4from math import radians
5from ezdxf.math import Vec3, BoundingBox
6from ezdxf.render.forms import cube
7from ezdxf.render.mesh import MeshVertexMerger, MeshBuilder, MeshTransformer, MeshAverageVertexMerger
8from ezdxf.addons import SierpinskyPyramid
9from ezdxf.layouts import VirtualLayout
10
11
12def test_vertex_merger_indices():
13    merger = MeshVertexMerger()
14    indices = merger.add_vertices([(1, 2, 3), (4, 5, 6)])
15    indices2 = merger.add_vertices([(1, 2, 3), (4, 5, 6)])
16    assert indices == indices2
17
18
19def test_vertex_merger_vertices():
20    merger = MeshVertexMerger()
21    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
22    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
23    assert merger.vertices == [(1, 2, 3), (4, 5, 6)]
24
25
26def test_vertex_merger_index_of():
27    merger = MeshVertexMerger()
28    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
29    assert merger.index((1, 2, 3)) == 0
30    assert merger.index((4, 5, 6)) == 1
31    with pytest.raises(IndexError):
32        merger.index((7, 8, 9))
33
34
35def test_average_vertex_merger_indices():
36    merger = MeshAverageVertexMerger()
37    indices = merger.add_vertices([(1, 2, 3), (4, 5, 6)])
38    indices2 = merger.add_vertices([(1, 2, 3), (4, 5, 6)])
39    assert indices == indices2
40
41
42def test_average_vertex_merger_vertices():
43    merger = MeshAverageVertexMerger()
44    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
45    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
46    assert merger.vertices == [(1, 2, 3), (4, 5, 6)]
47
48
49def test_average_vertex_merger_index_of():
50    merger = MeshAverageVertexMerger()
51    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
52    assert merger.index((1, 2, 3)) == 0
53    assert merger.index((4, 5, 6)) == 1
54    with pytest.raises(IndexError):
55        merger.index((7, 8, 9))
56
57
58def test_mesh_builder(msp):
59    pyramid = SierpinskyPyramid(level=4, sides=3)
60    pyramid.render(msp, merge=False)
61    meshes = msp.query('MESH')
62    assert len(meshes) == 256
63
64
65def test_vertex_merger():
66    pyramid = SierpinskyPyramid(level=4, sides=3)
67    faces = pyramid.faces()
68    mesh = MeshVertexMerger()
69    for vertices in pyramid:
70        mesh.add_mesh(vertices=vertices, faces=faces)
71    assert len(mesh.vertices) == 514
72    assert len(mesh.faces) == 1024
73
74
75def test_average_vertex_merger():
76    pyramid = SierpinskyPyramid(level=4, sides=3)
77    faces = pyramid.faces()
78    mesh = MeshAverageVertexMerger()
79    for vertices in pyramid:
80        mesh.add_mesh(vertices=vertices, faces=faces)
81    assert len(mesh.vertices) == 514
82    assert len(mesh.faces) == 1024
83
84
85REGULAR_FACE = Vec3.list([(0, 0, 0), (1, 0, 1), (1, 1, 1), (0, 1, 0)])
86IRREGULAR_FACE = Vec3.list([(0, 0, 0), (1, 0, 1), (1, 1, 0), (0, 1, 0)])
87
88
89def test_has_none_planar_faces():
90    mesh = MeshBuilder()
91    mesh.add_face(REGULAR_FACE)
92    assert mesh.has_none_planar_faces() is False
93    mesh.add_face(IRREGULAR_FACE)
94    assert mesh.has_none_planar_faces() is True
95
96
97def test_scale_mesh():
98    mesh = cube(center=False)
99    mesh.scale(2, 3, 4)
100    bbox = BoundingBox(mesh.vertices)
101    assert bbox.extmin.isclose((0, 0, 0))
102    assert bbox.extmax.isclose((2, 3, 4))
103
104
105def test_rotate_x():
106    mesh = cube(center=False)
107    mesh.rotate_x(radians(90))
108    bbox = BoundingBox(mesh.vertices)
109    assert bbox.extmin.isclose((0, -1, 0))
110    assert bbox.extmax.isclose((1, 0, 1))
111
112
113@pytest.fixture
114def msp():
115    return VirtualLayout()
116
117
118@pytest.fixture(scope='module')
119def cube_polyface():
120    layout = VirtualLayout()
121    p = layout.add_polyface()
122    p.append_faces(cube().faces_as_vertices())
123    return p
124
125
126def test_from_empty_polyface(msp):
127    empty_polyface = msp.add_polyface()
128    b = MeshBuilder.from_polyface(empty_polyface)
129    assert len(b.vertices) == 0
130    assert len(b.faces) == 0
131
132
133def test_from_cube_polyface(cube_polyface):
134    b = MeshBuilder.from_polyface(cube_polyface)
135    assert len(b.vertices) == 24  # unoptimized mesh builder
136    assert len(b.faces) == 6
137
138
139def test_render_polyface(cube_polyface, msp):
140    t = MeshTransformer.from_polyface(cube_polyface)
141    assert len(t.vertices) == 24  # unoptimized mesh builder
142    assert len(t.faces) == 6
143    t.render_polyface(msp)
144    new_polyface = msp[-1]
145    assert new_polyface.dxftype() == 'POLYLINE'
146    assert new_polyface.is_poly_face_mesh is True
147    assert len(new_polyface.vertices) == 8 + 6
148    assert new_polyface.vertices[0] is not cube_polyface.vertices[0]
149
150
151def test_from_polymesh(msp):
152    polymesh = msp.add_polymesh(size=(4, 4))
153    b = MeshBuilder.from_polyface(polymesh)
154    n = polymesh.dxf.n_count
155    m = polymesh.dxf.m_count
156    nfaces = (n - 1) * (m - 1)
157    assert len(b.vertices) == nfaces * 4  # unoptimized mesh builder
158    assert len(b.faces) == nfaces
159
160
161def test_from_polyface_type_error(msp):
162    polyline = msp.add_polyline3d([(0, 0, 0), (1, 0, 0)])
163    with pytest.raises(TypeError):
164        MeshBuilder.from_polyface(polyline)
165
166    line = msp.add_line(start=(0, 0, 0), end=(1, 0, 0))
167    with pytest.raises(TypeError):
168        MeshBuilder.from_polyface(line)
169
170
171@pytest.fixture
172def polyface_181_1(msp):
173    e = msp.new_entity(
174        'POLYLINE',
175        dxfattribs={
176            'flags': 48,
177            'm_count': 2,
178            'n_count': 6,
179        },
180    )
181    e.append_vertex((25041.94191089287, 29272.95055566061, 0.0), dxfattribs={'flags': 64})
182    e.append_vertex((25020.29127589287, 29285.45055566061, 0.0), dxfattribs={'flags': 64})
183    e.append_vertex((25020.29127589287, 29310.45055566061, 0.0), dxfattribs={'flags': 64})
184    e.append_vertex((25041.94191089287, 29322.95055566061, 0.0), dxfattribs={'flags': 64})
185    e.append_vertex((25063.59254589287, 29310.45055566061, 0.0), dxfattribs={'flags': 64})
186    e.append_vertex((25063.59254589287, 29285.45055566061, 0.0), dxfattribs={'flags': 64})
187    e.append_vertex((25041.94191089287, 29272.95055566061, 50.0), dxfattribs={'flags': 64})
188    e.append_vertex((25020.29127589287, 29285.45055566061, 50.0), dxfattribs={'flags': 64})
189    e.append_vertex((25020.29127589287, 29310.45055566061, 50.0), dxfattribs={'flags': 64})
190    e.append_vertex((25041.94191089287, 29322.95055566061, 50.0), dxfattribs={'flags': 64})
191    e.append_vertex((25063.59254589287, 29310.45055566061, 50.0), dxfattribs={'flags': 64})
192    e.append_vertex((25063.59254589287, 29285.45055566061, 50.0), dxfattribs={'flags': 64})
193    return e
194
195
196def test_from_polyface_182_1(polyface_181_1):
197    mesh = MeshVertexMerger.from_polyface(polyface_181_1)
198    assert len(mesh.vertices) == 12
199
200
201@pytest.fixture
202def polyface_181_2(msp):
203    e = msp.new_entity(
204        'POLYLINE',
205        dxfattribs={
206            'flags': 16,
207            'm_count': 6,
208            'n_count': 3,
209        },
210    )
211    e.append_vertex((16606.65151901649, 81.88147523282441, 2099.9999999999995), dxfattribs={'flags': 64})
212    e.append_vertex((16606.65151901649, 81.88147523282441, 1199.9999999999998), dxfattribs={'flags': 64})
213    e.append_vertex((16606.65151901649, 81.88147523282441, 1199.9999999999998), dxfattribs={'flags': 64})
214    e.append_vertex((16606.65151901649, 1281.8814752328244, 2099.9999999999995), dxfattribs={'flags': 64})
215    e.append_vertex((16606.65151901649, 1281.8814752328244, 1199.9999999999998), dxfattribs={'flags': 64})
216    e.append_vertex((16606.65151901649, 1281.8814752328244, 1199.9999999999998), dxfattribs={'flags': 64})
217    e.append_vertex((16626.65151901649, 1281.8814752328244, 2099.9999999999995), dxfattribs={'flags': 64})
218    e.append_vertex((16626.65151901649, 1281.8814752328244, 1199.9999999999998), dxfattribs={'flags': 64})
219    e.append_vertex((16606.65151901649, 1281.8814752328244, 1199.9999999999998), dxfattribs={'flags': 64})
220    e.append_vertex((16626.65151901649, 81.88147523282441, 2099.9999999999995), dxfattribs={'flags': 64})
221    e.append_vertex((16626.65151901649, 81.88147523282441, 1199.9999999999998), dxfattribs={'flags': 64})
222    e.append_vertex((16606.65151901649, 81.88147523282441, 1199.9999999999998), dxfattribs={'flags': 64})
223    e.append_vertex((16626.65151901649, 81.88147523282441, 2099.9999999999995), dxfattribs={'flags': 64})
224    e.append_vertex((16626.65151901649, 81.88147523282441, 2099.9999999999995), dxfattribs={'flags': 64})
225    e.append_vertex((16606.65151901649, 81.88147523282441, 2099.9999999999995), dxfattribs={'flags': 64})
226    e.append_vertex((16626.65151901649, 1281.8814752328244, 2099.9999999999995), dxfattribs={'flags': 64})
227    e.append_vertex((16626.65151901649, 1281.8814752328244, 2099.9999999999995), dxfattribs={'flags': 64})
228    e.append_vertex((16606.65151901649, 1281.8814752328244, 2099.9999999999995), dxfattribs={'flags': 64})
229    return e
230
231
232def test_from_polyface_182_2(polyface_181_2):
233    mesh = MeshVertexMerger.from_polyface(polyface_181_2)
234    assert len(mesh.vertices) == 8
235