1# Copyright (c) 2011-2020, Manfred Moitzi
2# License: MIT License
3import pytest
4
5from ezdxf.lldxf.const import VTX_3D_POLYLINE_VERTEX
6from ezdxf import DXFIndexError
7from ezdxf.layouts import VirtualLayout
8
9
10@pytest.fixture
11def msp():
12    return VirtualLayout()
13
14
15def test_create_polyline2D(msp):
16    polyline = msp.add_polyline2d([(0, 0), (1, 1)])
17    assert (0., 0.) == polyline[0].dxf.location
18    assert (1., 1.) == polyline[1].dxf.location
19    assert 'AcDb2dPolyline' == polyline.get_mode()
20
21
22def test_create_polyline3D(msp):
23    polyline = msp.add_polyline3d([(1, 2, 3), (4, 5, 6)])
24    assert (1., 2., 3.) == polyline[0].dxf.location
25    assert (4., 5., 6.) == polyline[1].dxf.location
26    assert VTX_3D_POLYLINE_VERTEX == polyline[0].dxf.flags
27    assert 'AcDb3dPolyline' == polyline.get_mode()
28
29
30def test_polyline3d_vertex_layer(msp):
31    attribs = {'layer': 'polyline_layer'}
32    polyline = msp.add_polyline3d([(1, 2, 3), (4, 5, 6)], dxfattribs=attribs)
33    for vertex in polyline.vertices:
34        assert 'polyline_layer' == vertex.dxf.layer, "VERTEX entity not on the same layer as the POLYLINE entity."
35
36
37def test_polyline3d_change_polyline_layer(msp):
38    attribs = {'layer': 'polyline_layer'}
39    polyline = msp.add_polyline3d([(1, 2, 3), (4, 5, 6)], dxfattribs=attribs)
40    polyline.dxf.layer = "changed_layer"
41    for vertex in polyline.vertices:
42        assert 'changed_layer' == vertex.dxf.layer, "VERTEX entity not on the same layer as the POLYLINE entity."
43
44
45def test_polyline2d_set_vertex(msp):
46    polyline = msp.add_polyline2d([(0, 0), (1, 1), (2, 2), (3, 3)])
47    polyline[2].dxf.location = (7, 7)
48    assert (7., 7.) == polyline[2].dxf.location
49
50
51def test_polyline2d_points(msp):
52    points = [(0, 0), (1, 1), (2, 2), (3, 3)]
53    polyline = msp.add_polyline2d(points)
54    assert points == list(polyline.points())
55
56
57def test_polyline2d_point_slicing(msp):
58    points = [(0, 0), (1, 1), (2, 2), (3, 3)]
59    polyline = msp.add_polyline2d(points)
60    assert [(1, 1), (2, 2)] == list(polyline.points())[1:3]
61
62
63def test_poyline2d_append_vertices(msp):
64    polyline = msp.add_polyline2d([(0, 0), (1, 1)])
65    polyline.append_vertices([(7, 7), (8, 8)])
66    assert (7., 7.) == polyline[2].dxf.location
67    assert 4 == len(polyline)
68
69
70def test_polyline2d_insert_vertices(msp):
71    polyline = msp.add_polyline2d([(0, 0), (1, 1)])
72    polyline.insert_vertices(0, [(7, 7), (8, 8)])
73    assert (7, 7) == polyline[0].dxf.location
74    assert (1, 1) == polyline[3].dxf.location
75    assert 4 == len(polyline)
76
77
78def test_polyline2d_delete_one_vertex(msp):
79    polyline = msp.add_polyline2d([(0, 0), (1, 1), (2, 2), (3, 3)])
80    del polyline.vertices[0]
81    assert (1, 1) == polyline[0].dxf.location
82    assert 3 == len(polyline)
83
84
85def test_polyline2d_delete_two_vertices(msp):
86    polyline = msp.add_polyline2d([(0, 0), (1, 1), (2, 2), (3, 3)])
87    del polyline.vertices[0:2]
88    assert (2, 2) == polyline[0].dxf.location
89    assert 2 == len(polyline)
90
91
92def test_polymesh_create_mesh(msp):
93    msp.add_polymesh((4, 4))
94    assert True
95
96
97def test_polymesh_set_vertex(msp):
98    mesh = msp.add_polymesh((4, 4))
99    mesh.set_mesh_vertex((1, 1), (1, 2, 3))
100    result = mesh.get_mesh_vertex((1, 1)).dxf.location
101    assert (1, 2, 3) == result
102
103
104def test_polymesh_error_nindex(msp):
105    mesh = msp.add_polymesh((4, 4))
106    with pytest.raises(DXFIndexError):
107        mesh.get_mesh_vertex((0, 4))
108
109
110def test_polymesh_error_mindex(msp):
111    mesh = msp.add_polymesh((4, 4))
112    with pytest.raises(DXFIndexError):
113        mesh.get_mesh_vertex((4, 0))
114
115
116def test_polymesh_mesh_cache(msp):
117    pos = (2, 1)
118    mesh = msp.add_polymesh((4, 4))
119    cache = mesh.get_mesh_vertex_cache()
120    cache[pos] = (1, 2, 3)
121    vertex = mesh.get_mesh_vertex(pos)
122    assert vertex.dxf.location == cache[pos]
123    with pytest.raises(DXFIndexError):
124        cache[4, 0]
125
126
127def test_polyface_create_face(msp):
128    face = msp.add_polyface()
129    assert 0 == len(face)
130
131
132def test_polyface_add_face(msp):
133    face = msp.add_polyface()
134    face.append_face([(0, 0), (1, 1), (2, 2), (3, 3)])
135    assert [(0, 0), (1, 1), (2, 2), (3, 3), (0, 0, 0)] == list(face.points())
136
137
138def test_polyface_face_indices(msp):
139    face = msp.add_polyface()
140    face.append_face([(0, 0), (1, 1), (2, 2), (3, 3)])
141    face_record = face[4]
142    assert 1 == face_record.dxf.vtx0
143    assert 2 == face_record.dxf.vtx1
144    assert 3 == face_record.dxf.vtx2
145    assert 4 == face_record.dxf.vtx3
146
147
148def test_polyface_add_two_face_indices(msp):
149    face = msp.add_polyface()
150    face.append_face([(0, 0), (1, 1), (2, 2), (3, 3)])
151    # second face has same vertices as the first face
152    face.append_face([(0, 0), (1, 1), (2, 2)])
153    face_record = face[5]  # second face
154    assert 1 == face_record.dxf.vtx0
155    assert 2 == face_record.dxf.vtx1
156    assert 3 == face_record.dxf.vtx2
157    assert 4 == face.dxf.m_count  # vertices count
158    assert 2 == face.dxf.n_count  # faces count
159
160
161def test_polyface_faces(msp):
162    face = msp.add_polyface()
163    face.append_face([(0, 0), (1, 1), (2, 2), (3, 3)])
164    face.append_face([(0, 0), (1, 1), (2, 2)])
165    result = list(face.faces())
166    assert 2 == len(result)
167    points1 = [vertex.dxf.location for vertex in result[0]]
168    # the last vertex is the face_record and is always (0, 0, 0)
169    # the face_record contains indices to the face building vertices
170    assert [(0, 0, 0), (1, 1, 0), (2, 2, 0), (3, 3, 0), (0, 0, 0)] == points1
171
172
173def test_polyface_optimized_cube(msp):
174    face = msp.add_polyface()
175    # a cube consist of 6 faces and 24 vertices
176    # duplicated vertices should be removed
177    face.append_faces(cube_faces())
178    assert 8 == face.dxf.m_count  # vertices count
179    assert 6 == face.dxf.n_count  # faces count
180
181
182def cube_faces():
183    # cube corner points
184    p1 = (0, 0, 0)
185    p2 = (0, 0, 1)
186    p3 = (0, 1, 0)
187    p4 = (0, 1, 1)
188    p5 = (1, 0, 0)
189    p6 = (1, 0, 1)
190    p7 = (1, 1, 0)
191    p8 = (1, 1, 1)
192
193    # define the 6 cube faces
194    # look into -x direction
195    # Every add_face adds 4 vertices 6x4 = 24 vertices
196    return [
197        [p1, p5, p7, p3],
198        [p1, p5, p6, p2],
199        [p5, p7, p8, p6],
200        [p7, p8, p4, p3],
201        [p1, p3, p4, p2],
202        [p2, p6, p8, p4],
203    ]
204