forked from mozman/ezdxf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_531_acis_entities.py
403 lines (300 loc) · 11.7 KB
/
test_531_acis_entities.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# Copyright (c) 2022-2024, Manfred Moitzi
# License: MIT License
import pytest
from ezdxf.acis.api import load, export_sat, export_sab, ExportError
from ezdxf.acis import sat, sab, entities, hdr, const, mesh
from ezdxf.math import Matrix44
import math
def test_load_any_format(any_cube):
bodies = load(any_cube)
assert len(bodies) == 1
@pytest.fixture(scope="module")
def body(any_cube):
return load(any_cube)[0]
class TestBody:
def test_type_type(self, body):
assert body.type == "body"
def test_has_transform_attribute(self, body):
assert body.transform.is_none is False
def test_transform_attribute_was_loaded(self, body):
m = body.transform.matrix
assert m.get_row(3) == (388.5, 388.5, 388.5, 1.0)
def test_has_wire_attribute(self, body):
assert body.wire.is_none is True
def test_get_all_lumps_as_a_list(self, body):
bodies = body.lumps()
assert len(bodies) == 1
assert isinstance(bodies[0], entities.Lump)
def test_append_lumps(self):
body = entities.Body()
assert len(body.lumps()) == 0
body.append_lump(entities.Lump())
assert len(body.lumps()) == 1
body.append_lump(entities.Lump())
assert len(body.lumps()) == 2
class TestLump:
def test_lump_type(self, body):
assert body.lump.type == "lump"
def test_back_pointer_to_body(self, body):
assert body.lump.body is body
def test_has_no_next_lump(self, body):
assert body.lump.next_lump.is_none is True
def test_has_attribute_to_first_shell(self, body):
assert body.lump.shell.is_none is False
def test_get_all_shells_as_a_list(self, body):
shells = body.lump.shells()
assert len(shells) == 1
assert isinstance(shells[0], entities.Shell)
def test_append_shells(self):
body = entities.Body()
lump = entities.Lump()
body.append_lump(lump)
assert len(lump.shells()) == 0
lump.append_shell(entities.Shell())
assert len(lump.shells()) == 1
lump.append_shell(entities.Shell())
assert len(lump.shells()) == 2
class TestShell:
@pytest.fixture(scope="class")
def shell(self, body):
return body.lump.shell
def test_shell_type(self, shell):
assert shell.type == "shell"
def test_back_pointer_to_lump(self, shell):
assert shell.lump.shell is shell
def test_has_no_next_shell(self, shell):
assert shell.next_shell.is_none is True
def test_get_all_faces_as_a_list(self, shell):
faces = shell.faces()
assert len(faces) == 6
assert isinstance(faces[0], entities.Face)
def test_append_faces(self):
body = entities.Body()
lump = entities.Lump()
shell = entities.Shell()
body.append_lump(lump)
lump.append_shell(shell)
assert len(shell.faces()) == 0
shell.append_face(entities.Face())
assert len(shell.faces()) == 1
shell.append_face(entities.Face())
assert len(shell.faces()) == 2
class TestFace:
@pytest.fixture(scope="class")
def face(self, body):
return body.lump.shell.face
def test_face_type(self, face):
assert face.type == "face"
def test_back_pointer_to_shell(self, body, face):
assert face.shell is body.lump.shell
def test_has_attribute_surface(self, face):
assert face.surface.type == "plane-surface"
def test_face_features(self, face):
assert face.sense is False # forward
assert face.double_sided is False # single
assert face.containment is False
def test_traverse_all_six_cube_faces(self, face):
count = 1
while not face.next_face.is_none:
count += 1
face = face.next_face
assert count == 6
class TestPolyhedronFaceBuilder:
@pytest.fixture(scope="class")
def cube(self):
from ezdxf.render.forms import cube
return mesh.PolyhedronFaceBuilder(cube())
def test_creates_six_faces(self, cube):
faces = list(cube.acis_faces())
assert len(faces) == 6
def test_each_face_defines_a_plane_surface(self, cube):
for face in cube.acis_faces():
assert face.surface.type == "plane-surface"
class TestPlane:
@pytest.fixture(scope="class")
def plane(self, body):
return body.lump.shell.face.surface
def test_plane_type(self, plane):
assert plane.type == "plane-surface"
def test_plane_location(self, plane):
assert plane.origin.isclose((0, 0, 388.5))
def test_plane_normal(self, plane):
assert plane.normal.isclose((0, 0, 1))
def test_plane_u_dir(self, plane):
assert plane.u_dir.isclose((1, 0, 0))
def test_plane_has_infinite_bounds(self, plane):
assert math.isinf(plane.u_bounds[0])
assert math.isinf(plane.u_bounds[1])
assert math.isinf(plane.v_bounds[0])
assert math.isinf(plane.v_bounds[1])
class TestLoop:
@pytest.fixture(scope="class")
def loop(self, body):
return body.lump.shell.face.loop
def test_loop_type(self, loop):
assert loop.type == "loop"
def test_cube_face_has_only_one_loop(self, loop):
assert loop.next_loop.is_none is True
def test_loop_references_the_parent_face(self, loop):
assert loop.face.loop is loop
def test_set_closed_coedges(self):
loop = entities.Loop()
coedges = [entities.Coedge() for _ in range(3)]
loop.set_coedges(coedges, close=True)
result = loop.coedges()
assert result == coedges
def test_set_open_coedges(self):
loop = entities.Loop()
coedges = [entities.Coedge() for _ in range(3)]
loop.set_coedges(coedges, close=False)
assert loop.coedge.prev_coedge.is_none is True
result = loop.coedges()
assert result == coedges
class TestCoedge:
@pytest.fixture(scope="class")
def coedge(self, body):
return body.lump.shell.face.loop.coedge
def test_co_edge_type(self, coedge):
assert coedge.type == "coedge"
def test_co_edges_are_organized_as_a_forward_linked_list(self, coedge):
next = coedge.next_coedge
co_edges = [next]
while next is not coedge:
next = next.next_coedge
co_edges.append(next)
assert len(co_edges) == 4
def test_co_edges_are_organized_as_a_reverse_linked_list(self, coedge):
prev = coedge.prev_coedge
co_edges = [prev]
while prev is not coedge:
prev = prev.prev_coedge
co_edges.append(prev)
assert len(co_edges) == 4
def test_partner_co_edge_count_is_two(self, coedge):
assert len(coedge.partner_coedges()) == 1
def test_co_edges_have_partner_co_edges_other_faces(self, coedge):
assert coedge.partner_coedge.partner_coedge is coedge
def test_sense_of_co_edge_is_forward(self, coedge):
assert coedge.sense is False
def test_co_edge_references_the_parent_loop(self, coedge):
assert coedge.loop.coedge is coedge
def test_default_partner_co_edge_count_is_two():
coedge = entities.Coedge()
assert len(coedge.partner_coedges()) == 0
class TestEdge:
@pytest.fixture(scope="class")
def edge(self, body):
return body.lump.shell.face.loop.coedge.edge
def test_edge_type(self, edge):
assert edge.type == "edge"
def test_edge_has_a_start_vertex(self, edge):
assert edge.start_vertex.is_none is False
def test_edge_has_an_end_vertex(self, edge):
assert edge.end_vertex.is_none is False
# start- and end parameter do not exist in ACIS-400
def test_sense_of_edge_is_forward(self, edge):
assert edge.sense is False
def test_underlying_curve_of_edge(self, edge):
assert edge.curve.type == "straight-curve"
def test_edge_is_referenced_by_two_parent_co_edges(self, edge):
parent = edge.coedge
assert parent.edge is edge
assert parent.partner_coedge.edge is edge
class TestVertex:
@pytest.fixture(scope="class")
def vertex(self, body):
return body.lump.shell.face.loop.coedge.edge.start_vertex
def test_vertex_type(self, vertex):
assert vertex.type == "vertex"
def test_vertex_references_parent_edge(self, vertex):
assert vertex.edge.start_vertex is vertex
class TestPoint:
@pytest.fixture(scope="class")
def point(self, body):
return body.lump.shell.face.loop.coedge.edge.start_vertex.point
def test_point_type(self, point):
assert point.type == "point"
def test_point_location(self, point):
assert point.location.isclose((388.5, -388.5, 388.5))
def test_get_all_points(self, body):
face = body.lump.shell.face
vertices = set()
while not face.is_none:
first_coedge = face.loop.coedge
coedge = first_coedge
while True:
vertices.add(coedge.edge.start_vertex.point.location)
coedge = coedge.next_coedge
if coedge is first_coedge:
break
face = face.next_face
assert len(vertices) == 8
@pytest.fixture(scope="module")
def prism700(prism_sat):
return load(prism_sat)
class TestExportSat:
def test_export_rejects_unsupported_acis_versions(self, prism700):
with pytest.raises(ExportError):
export_sat(prism700, version=400)
def test_export_acis_700(self, prism700):
data = export_sat(prism700)
assert len(data) == 117 # includes header
assert data[-1] == "End-of-ACIS-data " # an extra space at the end!
class TestExportSab21800:
def test_export_rejects_unsupported_acis_versions(self, prism700):
with pytest.raises(ExportError):
export_sab(prism700, version=400)
def test_reload_records_from_acis_export(self, prism700):
data = export_sab(prism700)
decoder = sab.Decoder(data)
header = decoder.read_header()
assert header.version == 21800
records = list(decoder.read_records())
# 115 = excludes header
assert len(records) == 115
assert records[-1][0].value == "End-of-ASM-data"
def test_load_mesh_from_exported_sat_data(prism700):
bodies = load(export_sat(prism700))
m = mesh.mesh_from_body(bodies[0])[0]
assert len(m.vertices) == 8
assert len(m.faces) == 10
def test_load_mesh_from_exported_sab_data(prism700):
bodies = load(export_sab(prism700))
m = mesh.mesh_from_body(bodies[0])[0]
assert len(m.vertices) == 8
assert len(m.faces) == 10
class TestExportTransform:
@pytest.fixture(scope="class")
def header(self):
header = hdr.AcisHeader()
header.version = 700
return header
@pytest.fixture(scope="class")
def sat_exporter(self, header):
return sat.SatExporter(header)
@pytest.fixture(scope="class")
def sab_exporter(self, header):
return sab.SabExporter(header)
def test_export_sat_identity_matrix(self, sat_exporter):
data = []
exporter = sat.SatDataExporter(sat_exporter, data)
t = entities.Transform()
t.matrix = Matrix44()
t.export(exporter)
assert (
" ".join(data)
== "1 0 0 0 1 0 0 0 1 0 0 0 1 no_rotate no_reflect no_shear"
)
def test_export_sab_identity_matrix(self, sab_exporter):
data = []
exporter = sab.SabDataExporter(sab_exporter, data)
t = entities.Transform()
t.matrix = Matrix44()
t.export(exporter)
assert data[0] == (
const.Tags.LITERAL_STR,
# The last space is important!
"1 0 0 0 1 0 0 0 1 0 0 0 1 no_rotate no_reflect no_shear ",
)
if __name__ == "__main__":
pytest.main([__file__])