FreeCAD

Форк
0
/
MeshTestsApp.py 
749 строк · 28.4 Кб
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3

4
#  Copyright (c) 2007 Jürgen Riegel <juergen.riegel@web.de>
5
#  LGPL
6

7
import os
8
import sys
9
import io
10
import FreeCAD, unittest, Mesh
11
import MeshEnums
12
from FreeCAD import Base
13
import time, tempfile, math
14

15
# http://python-kurs.eu/threads.php
16
try:
17
    import _thread as thread
18
except Exception:
19
    import thread
20

21
from os.path import join
22

23
# ---------------------------------------------------------------------------
24
# define the functions to test the FreeCAD mesh module
25
# ---------------------------------------------------------------------------
26

27

28
class MeshTopoTestCases(unittest.TestCase):
29
    def setUp(self):
30
        # set up a planar face with 18 triangles
31
        self.planarMesh = []
32
        for x in range(3):
33
            for y in range(3):
34
                self.planarMesh.append([0.0 + x, 0.0 + y, 0.0000])
35
                self.planarMesh.append([1.0 + x, 1.0 + y, 0.0000])
36
                self.planarMesh.append([0.0 + x, 1.0 + y, 0.0000])
37
                self.planarMesh.append([0.0 + x, 0.0 + y, 0.0000])
38
                self.planarMesh.append([1.0 + x, 0.0 + y, 0.0000])
39
                self.planarMesh.append([1.0 + x, 1.0 + y, 0.0000])
40

41
    def testCollapseFacetsSingle(self):
42
        for i in range(18):
43
            planarMeshObject = Mesh.Mesh(self.planarMesh)
44
            planarMeshObject.collapseFacets([i])
45

46
    def testCollapseFacetsMultible(self):
47
        planarMeshObject = Mesh.Mesh(self.planarMesh)
48
        planarMeshObject.collapseFacets(range(7))
49

50
    def testCollapseFacetsAll(self):
51
        planarMeshObject = Mesh.Mesh(self.planarMesh)
52
        planarMeshObject.collapseFacets(range(18))
53

54
    # fmt: off
55
    def testCorruptedFacet(self):
56
        v = FreeCAD.Vector
57
        mesh = Mesh.Mesh()
58
        mesh.addFacet(
59
        v(1.0e1, -1.0e1, 1.0e1),
60
        v(1.0e1, +1.0e1, 1.0e1),
61
        v(0.0e0, 0.0e0, 1.0e1))
62

63
        mesh.addFacet(
64
        v(-1.0e1, -1.0e1, 1.0e1),
65
        v(-1.0e1, +1.0e1, 1.0e1),
66
        v(0e0, 0.0e0, 1.0e1))
67

68
        mesh.addFacet(
69
        v(+1.0e1, +1.0e1, 1.0e1),
70
        v(-1.0e1, +1.0e1, 1.0e1),
71
        v(.0e0, 0.0e0, 1.0e1))
72

73
        mesh.addFacet(
74
        v(+1.0e1, -1.0e1, 1.0e1),
75
        v(-1.0e1, -1.0e1, 1.0e1),
76
        v(.0e0, 0.0e0, 1.0e1))
77

78
        mesh.addFacet(
79
        v(-1.0e1, +1.0e1, 1.0e1),
80
        v(+1.0e1, +1.0e1, 1.0e1),
81
        v(+1.0e1, +1.0e1, 1.0e1))
82

83
        mesh.addFacet(
84
        v(+1.0e1, +1.0e1, 1.0e1),
85
        v(+1.0e1, 00.0e1, 1.0e1),
86
        v(+1.0e1, -1.0e1, 1.0e1))
87

88
        self.assertEqual(mesh.CountFacets, 6)
89
        mesh.fixIndices()
90
        self.assertEqual(mesh.CountFacets, 5)
91

92

93
# fmt: on
94

95

96
class MeshSplitTestCases(unittest.TestCase):
97
    def setUp(self):
98
        self.mesh = Mesh.createBox(1.0, 1.0, 1.0)
99

100
    def testSplitFacetOnOneEdge(self):
101
        p1 = self.mesh.Points[0].Vector
102
        p2 = self.mesh.Points[1].Vector
103
        p3 = self.mesh.Points[2].Vector
104
        self.mesh.splitFacet(0, p1, (p2 + p3) / 2)
105
        self.assertFalse(self.mesh.hasNonManifolds())
106
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
107
        self.assertFalse(self.mesh.hasPointsOutOfRange())
108
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
109
        self.assertFalse(self.mesh.hasCorruptedFacets())
110
        self.assertTrue(self.mesh.isSolid())
111

112
    def testSplitFacetOnTwoEdges_21(self):
113
        p1 = self.mesh.Points[0].Vector
114
        p2 = self.mesh.Points[1].Vector
115
        p3 = self.mesh.Points[2].Vector
116
        self.mesh.splitFacet(0, (p1 + p3) / 2, (p2 + p3) / 2)
117
        self.assertFalse(self.mesh.hasNonManifolds())
118
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
119
        self.assertFalse(self.mesh.hasPointsOutOfRange())
120
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
121
        self.assertFalse(self.mesh.hasCorruptedFacets())
122
        self.assertTrue(self.mesh.isSolid())
123

124
    def testSplitFacetOnTwoEdges_12(self):
125
        p1 = self.mesh.Points[0].Vector
126
        p2 = self.mesh.Points[1].Vector
127
        p3 = self.mesh.Points[2].Vector
128
        self.mesh.splitFacet(0, (p2 + p3) / 2, (p1 + p3) / 2)
129
        self.assertFalse(self.mesh.hasNonManifolds())
130
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
131
        self.assertFalse(self.mesh.hasPointsOutOfRange())
132
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
133
        self.assertFalse(self.mesh.hasCorruptedFacets())
134
        self.assertTrue(self.mesh.isSolid())
135

136
    def testSplitFacetOnTwoEdges_01(self):
137
        p1 = self.mesh.Points[0].Vector
138
        p2 = self.mesh.Points[1].Vector
139
        p3 = self.mesh.Points[2].Vector
140
        self.mesh.splitFacet(0, (p1 + p2) / 2, (p2 + p3) / 2)
141
        self.assertFalse(self.mesh.hasNonManifolds())
142
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
143
        self.assertFalse(self.mesh.hasPointsOutOfRange())
144
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
145
        self.assertFalse(self.mesh.hasCorruptedFacets())
146
        self.assertTrue(self.mesh.isSolid())
147

148
    def testSplitFacetOnTwoEdges_10(self):
149
        p1 = self.mesh.Points[0].Vector
150
        p2 = self.mesh.Points[1].Vector
151
        p3 = self.mesh.Points[2].Vector
152
        self.mesh.splitFacet(0, (p2 + p3) / 2, (p1 + p2) / 2)
153
        self.assertFalse(self.mesh.hasNonManifolds())
154
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
155
        self.assertFalse(self.mesh.hasPointsOutOfRange())
156
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
157
        self.assertFalse(self.mesh.hasCorruptedFacets())
158
        self.assertTrue(self.mesh.isSolid())
159

160
    def testSplitFacetOnTwoEdges_02(self):
161
        p1 = self.mesh.Points[0].Vector
162
        p2 = self.mesh.Points[1].Vector
163
        p3 = self.mesh.Points[2].Vector
164
        self.mesh.splitFacet(0, (p1 + p2) / 2, (p1 + p3) / 2)
165
        self.assertFalse(self.mesh.hasNonManifolds())
166
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
167
        self.assertFalse(self.mesh.hasPointsOutOfRange())
168
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
169
        self.assertFalse(self.mesh.hasCorruptedFacets())
170
        self.assertTrue(self.mesh.isSolid())
171

172
    def testSplitFacetOnTwoEdges_20(self):
173
        p1 = self.mesh.Points[0].Vector
174
        p2 = self.mesh.Points[1].Vector
175
        p3 = self.mesh.Points[2].Vector
176
        self.mesh.splitFacet(0, (p1 + p3) / 2, (p1 + p2) / 2)
177
        self.assertFalse(self.mesh.hasNonManifolds())
178
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
179
        self.assertFalse(self.mesh.hasPointsOutOfRange())
180
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
181
        self.assertFalse(self.mesh.hasCorruptedFacets())
182
        self.assertTrue(self.mesh.isSolid())
183

184
    def testSplitFacetOnTwoEdges_5teps(self):
185
        Vec3d = FreeCAD.Vector
186
        for i in range(5):
187
            f = self.mesh.Facets[0]
188
            p1 = Vec3d(f.Points[0])
189
            p2 = Vec3d(f.Points[1])
190
            p3 = Vec3d(f.Points[2])
191
            self.mesh.splitFacet(0, (p1 + p3) / 2, (p2 + p3) / 2)
192

193
        self.assertFalse(self.mesh.hasNonManifolds())
194
        self.assertFalse(self.mesh.hasInvalidNeighbourhood())
195
        self.assertFalse(self.mesh.hasPointsOutOfRange())
196
        self.assertFalse(self.mesh.hasFacetsOutOfRange())
197
        self.assertFalse(self.mesh.hasCorruptedFacets())
198
        self.assertTrue(self.mesh.isSolid())
199

200
    def testFindNearest(self):
201
        self.assertEqual(len(self.mesh.nearestFacetOnRay((-2, 2, -6), (0, 0, 1))), 0)
202
        self.assertEqual(len(self.mesh.nearestFacetOnRay((0.5, 0.5, 0.5), (0, 0, 1))), 1)
203
        self.assertEqual(
204
            len(self.mesh.nearestFacetOnRay((0.5, 0.5, 0.5), (0, 0, 1), -math.pi / 2)), 0
205
        )
206
        self.assertEqual(
207
            len(self.mesh.nearestFacetOnRay((0.2, 0.1, 0.2), (0, 0, 1))),
208
            len(self.mesh.nearestFacetOnRay((0.2, 0.1, 0.2), (0, 0, -1))),
209
        )
210
        self.assertEqual(
211
            len(self.mesh.nearestFacetOnRay((0.2, 0.1, 0.2), (0, 0, 1), math.pi / 2)),
212
            len(self.mesh.nearestFacetOnRay((0.2, 0.1, 0.2), (0, 0, -1), math.pi / 2)),
213
        )
214
        # Apply placement to mesh
215
        plm = Base.Placement(Base.Vector(1, 2, 3), Base.Rotation(1, 1, 1, 1))
216
        pnt = Base.Vector(0.5, 0.5, 0.5)
217
        vec = Base.Vector(0.0, 0.0, 1.0)
218

219
        self.mesh.Placement = plm
220
        self.assertEqual(len(self.mesh.nearestFacetOnRay(pnt, vec)), 0)
221

222
        # Apply the placement on the ray as well
223
        pnt = plm.multVec(pnt)
224
        vec = plm.Rotation.multVec(vec)
225
        self.assertEqual(len(self.mesh.nearestFacetOnRay(pnt, vec)), 1)
226

227
    def testForaminate(self):
228
        class FilterAngle:
229
            def __init__(self, mesh, vec, limit):
230
                self.myMesh = mesh
231
                self.vec = vec
232
                self.limit = limit
233

234
            def check_angle(self, item):
235
                angle = self.myMesh.Facets[item].Normal.getAngle(self.vec)
236
                return angle < self.limit
237

238
        results = self.mesh.foraminate((0.0, 0.0, 0.0), (0, 1, 1))
239
        filtered_result = list(
240
            filter(
241
                FilterAngle(self.mesh, FreeCAD.Vector(0, 1, 1), math.pi / 2).check_angle,
242
                results.keys(),
243
            )
244
        )
245

246
        self.assertEqual(
247
            filtered_result, list(self.mesh.foraminate((0.0, 0.0, 0.0), (0, 1, 1), math.pi / 2))
248
        )
249

250
    def testForaminatePlacement(self):
251
        pnt = Base.Vector(0.0, 0.0, 0.0)
252
        vec = Base.Vector(0.0, 1.0, 1.0)
253
        results = self.mesh.foraminate(pnt, vec)
254
        self.assertEqual(len(results), 4)
255

256
        # Apply placement to mesh
257
        plm = Base.Placement(Base.Vector(1, 2, 3), Base.Rotation(1, 1, 1, 1))
258
        self.mesh.Placement = plm
259
        self.assertEqual(len(self.mesh.foraminate(pnt, vec)), 0)
260

261
        # Apply the placement on the ray as well
262
        pnt = plm.multVec(pnt)
263
        vec = plm.Rotation.multVec(vec)
264
        results2 = self.mesh.foraminate(pnt, vec)
265
        self.assertEqual(len(results2), 4)
266
        self.assertEqual(list(results), list(results2))
267

268

269
class MeshGeoTestCases(unittest.TestCase):
270
    def setUp(self):
271
        # set up a planar face with 2 triangles
272
        self.planarMesh = []
273

274
    def testIntersection(self):
275
        self.planarMesh.append([0.9961, 1.5413, 4.3943])
276
        self.planarMesh.append([9.4796, 10.024, -3.0937])
277
        self.planarMesh.append([1.4308, 11.3841, 2.6829])
278
        self.planarMesh.append([2.6493, 2.2536, 3.0679])
279
        self.planarMesh.append([13.1126, 0.4857, -4.4417])
280
        self.planarMesh.append([10.2410, 8.9040, -3.5002])
281
        planarMeshObject = Mesh.Mesh(self.planarMesh)
282
        f1 = planarMeshObject.Facets[0]
283
        f2 = planarMeshObject.Facets[1]
284
        res = f1.intersect(f2)
285
        self.assertTrue(len(res) == 0)
286

287
    def testIntersection2(self):
288
        self.planarMesh.append([-16.097176, -29.891157, 15.987688])
289
        self.planarMesh.append([-16.176304, -29.859991, 15.947966])
290
        self.planarMesh.append([-16.071451, -29.900553, 15.912505])
291
        self.planarMesh.append([-16.092241, -29.893408, 16.020439])
292
        self.planarMesh.append([-16.007210, -29.926180, 15.967641])
293
        self.planarMesh.append([-16.064457, -29.904951, 16.090832])
294
        planarMeshObject = Mesh.Mesh(self.planarMesh)
295
        f1 = planarMeshObject.Facets[0]
296
        f2 = planarMeshObject.Facets[1]
297
        # does definitely NOT intersect
298
        res = f1.intersect(f2)
299
        self.assertTrue(len(res) == 0)
300

301
    def testIntersectionOfTransformedMesh(self):
302
        self.planarMesh.append([0.0, 10.0, 10.0])
303
        self.planarMesh.append([10.0, 0.0, 10.0])
304
        self.planarMesh.append([10.0, 10.0, 10.0])
305
        self.planarMesh.append([6.0, 8.0, 10.0])
306
        self.planarMesh.append([16.0, 8.0, 10.0])
307
        self.planarMesh.append([6.0, 18.0, 10.0])
308
        planarMeshObject = Mesh.Mesh(self.planarMesh)
309

310
        mat = Base.Matrix()
311
        mat.rotateX(1.0)
312
        mat.rotateY(1.0)
313
        mat.rotateZ(1.0)
314
        planarMeshObject.transformGeometry(mat)
315

316
        f1 = planarMeshObject.Facets[0]
317
        f2 = planarMeshObject.Facets[1]
318
        res = f1.intersect(f2)
319
        self.assertEqual(len(res), 2)
320

321
    def testIntersectionOfParallelTriangles(self):
322
        self.planarMesh.append([0.0, 10.0, 10.0])
323
        self.planarMesh.append([10.0, 0.0, 10.0])
324
        self.planarMesh.append([10.0, 10.0, 10.0])
325
        self.planarMesh.append([6.0, 8.0, 10.1])
326
        self.planarMesh.append([16.0, 8.0, 10.1])
327
        self.planarMesh.append([6.0, 18.0, 10.1])
328
        planarMeshObject = Mesh.Mesh(self.planarMesh)
329

330
        mat = Base.Matrix()
331
        mat.rotateX(1.0)
332
        mat.rotateY(1.0)
333
        mat.rotateZ(1.0)
334
        planarMeshObject.transformGeometry(mat)
335

336
        f1 = planarMeshObject.Facets[0]
337
        f2 = planarMeshObject.Facets[1]
338
        res = f1.intersect(f2)
339
        self.assertTrue(len(res) == 0)
340

341
    def testIntersectionOnEdge(self):
342
        self.planarMesh.append([5.0, -1.9371663331985474, 0.49737977981567383])
343
        self.planarMesh.append([4.0, -1.9371663331985474, 0.49737977981567383])
344
        self.planarMesh.append([5.0, -1.9842294454574585, 0.25066646933555603])
345
        self.planarMesh.append([4.6488823890686035, -1.7827962636947632, 0.4577442705631256])
346
        self.planarMesh.append([4.524135112762451, -2.0620131492614746, 0.5294350385665894])
347
        self.planarMesh.append([4.6488823890686035, -1.8261089324951172, 0.23069120943546295])
348
        planarMeshObject = Mesh.Mesh(self.planarMesh)
349
        f1 = planarMeshObject.Facets[0]
350
        f2 = planarMeshObject.Facets[1]
351
        res = f1.intersect(f2)
352
        self.assertEqual(len(res), 2)
353

354
    def testIntersectionCoplanar(self):
355
        self.planarMesh.append([0.0, 10.0, 10.0])
356
        self.planarMesh.append([10.0, 0.0, 10.0])
357
        self.planarMesh.append([10.0, 10.0, 10.0])
358
        self.planarMesh.append([6.0, 8.0, 10.0])
359
        self.planarMesh.append([16.0, 8.0, 10.0])
360
        self.planarMesh.append([6.0, 18.0, 10.0])
361
        planarMeshObject = Mesh.Mesh(self.planarMesh)
362
        f1 = planarMeshObject.Facets[0]
363
        f2 = planarMeshObject.Facets[1]
364
        res = f1.intersect(f2)
365
        self.assertTrue(len(res) == 2)
366

367
    def testIntersectionOverlap(self):
368
        self.planarMesh.append([0.0, 0.0, 0.0])
369
        self.planarMesh.append([5.0, 0.0, 0.0])
370
        self.planarMesh.append([8.0, 5.0, 0.0])
371
        self.planarMesh.append([4.0, 0.0, 0.0])
372
        self.planarMesh.append([10.0, 0.0, 0.0])
373
        self.planarMesh.append([9.0, 5.0, 0.0])
374
        planarMeshObject = Mesh.Mesh(self.planarMesh)
375
        f1 = planarMeshObject.Facets[0]
376
        f2 = planarMeshObject.Facets[1]
377
        res = f1.intersect(f2)
378
        self.assertTrue(len(res) == 2)
379

380
    def testIntersectionOfIntersectingEdges(self):
381
        self.planarMesh.append([0.0, 10.0, 10.0])
382
        self.planarMesh.append([10.0, 0.0, 10.0])
383
        self.planarMesh.append([10.0, 10.0, 10.0])
384
        self.planarMesh.append([6.0, 8.0, 10.0])
385
        self.planarMesh.append([16.0, 8.0, 10.0])
386
        self.planarMesh.append([6.0, 18.0, 10.0])
387
        planarMeshObject = Mesh.Mesh(self.planarMesh)
388

389
        edge1 = planarMeshObject.Facets[0].getEdge(2)
390
        edge2 = planarMeshObject.Facets[1].getEdge(2)
391
        res = edge1.intersectWithEdge(edge2)
392
        self.assertTrue(len(res) == 1)
393
        self.assertEqual(res[0][0], 6.0)
394
        self.assertEqual(res[0][1], 10.0)
395
        self.assertEqual(res[0][2], 10.0)
396

397
    def testIntersectionOfParallelEdges(self):
398
        self.planarMesh.append([0.0, 10.0, 10.0])
399
        self.planarMesh.append([10.0, 0.0, 10.0])
400
        self.planarMesh.append([10.0, 10.0, 10.0])
401
        self.planarMesh.append([6.0, 8.0, 10.0])
402
        self.planarMesh.append([16.0, 8.0, 10.0])
403
        self.planarMesh.append([6.0, 18.0, 10.0])
404
        planarMeshObject = Mesh.Mesh(self.planarMesh)
405

406
        edge1 = planarMeshObject.Facets[0].getEdge(2)
407
        edge2 = planarMeshObject.Facets[1].getEdge(0)
408
        res = edge1.intersectWithEdge(edge2)
409
        self.assertTrue(len(res) == 0)
410

411
    def testIntersectionOfCollinearEdges(self):
412
        self.planarMesh.append([0.0, 0.0, 0.0])
413
        self.planarMesh.append([6.0, 0.0, 0.0])
414
        self.planarMesh.append([3.0, 4.0, 0.0])
415
        self.planarMesh.append([7.0, 0.0, 0.0])
416
        self.planarMesh.append([13.0, 0.0, 0.0])
417
        self.planarMesh.append([10.0, 4.0, 0.0])
418
        planarMeshObject = Mesh.Mesh(self.planarMesh)
419

420
        edge1 = planarMeshObject.Facets[0].getEdge(0)
421
        edge2 = planarMeshObject.Facets[1].getEdge(0)
422
        res = edge1.intersectWithEdge(edge2)
423
        self.assertTrue(len(res) == 0)
424

425
    def testIntersectionOfWarpedEdges(self):
426
        self.planarMesh.append([0.0, 0.0, 0.0])
427
        self.planarMesh.append([6.0, 0.0, 0.0])
428
        self.planarMesh.append([3.0, 4.0, 0.0])
429
        self.planarMesh.append([2.0, 2.0, 1.0])
430
        self.planarMesh.append([8.0, 2.0, 1.0])
431
        self.planarMesh.append([5.0, 6.0, 1.0])
432
        planarMeshObject = Mesh.Mesh(self.planarMesh)
433

434
        edge1 = planarMeshObject.Facets[0].getEdge(1)
435
        edge2 = planarMeshObject.Facets[1].getEdge(0)
436
        res = edge1.intersectWithEdge(edge2)
437
        self.assertTrue(len(res) == 0)
438

439
    def testSelfIntersection(self):
440
        s = b"""solid Simple
441
facet normal 0.0e0 0.0e0 1.0e1
442
    outer loop
443
        vertex 0.0e1 0.0e1 1.0e1
444
        vertex 0.0e1 +1.0e1 1.0e1
445
        vertex +1.0e1 0.0e1 1.0e1
446
    endloop
447
endfacet
448
facet normal 0.0e0 0.0e0 1.0e1
449
    outer loop
450
        vertex 0.0e1 +1.0e1 1.0e1
451
        vertex +1.0e1 0.0e1 1.0e1
452
        vertex 1.0e1 1.0e1 1.0e1
453
    endloop
454
endfacet
455
facet normal 0.0e0 0.0e0 1.0e1
456
    outer loop
457
        vertex 0.0e1 0.0e1 1.0e1
458
        vertex 0.0e1 +1.0e1 1.0e1
459
        vertex -1.0e1 1.0e1 1.0e1
460
    endloop
461
endfacet
462
facet normal 0.0e0 0.0e0 1.0e1
463
    outer loop
464
        vertex 0.0e1 0.0e1 1.0e1
465
        vertex +1.0e1 0.0e1 1.0e1
466
        vertex +1.0e1 -1.0e1 1.0e1
467
    endloop
468
endfacet
469
facet normal 0.0e0 0.0e0 1.0e1
470
    outer loop
471
        vertex 0.6e1 0.8e1 1.0e1
472
        vertex +1.6e1 0.8e1 1.0e1
473
        vertex +0.6e1 1.8e1 1.0e1
474
    endloop
475
endfacet
476
endsolid Simple"""
477
        mesh = Mesh.Mesh()
478
        data = io.BytesIO(s)
479
        mesh.read(Stream=data, Format="AST")
480
        self.assertTrue(mesh.hasSelfIntersections())
481

482

483
class PivyTestCases(unittest.TestCase):
484
    def setUp(self):
485
        # set up a planar face with 2 triangles
486
        self.planarMesh = []
487
        FreeCAD.newDocument("MeshTest")
488

489
    def testRayPick(self):
490
        if not FreeCAD.GuiUp:
491
            return
492
        self.planarMesh.append([-16.097176, -29.891157, 15.987688])
493
        self.planarMesh.append([-16.176304, -29.859991, 15.947966])
494
        self.planarMesh.append([-16.071451, -29.900553, 15.912505])
495
        self.planarMesh.append([-16.092241, -29.893408, 16.020439])
496
        self.planarMesh.append([-16.007210, -29.926180, 15.967641])
497
        self.planarMesh.append([-16.064457, -29.904951, 16.090832])
498
        planarMeshObject = Mesh.Mesh(self.planarMesh)
499

500
        from pivy import coin
501
        import FreeCADGui
502

503
        Mesh.show(planarMeshObject)
504
        view = FreeCADGui.ActiveDocument.ActiveView.getViewer()
505
        rp = coin.SoRayPickAction(view.getSoRenderManager().getViewportRegion())
506
        rp.setRay(coin.SbVec3f(-16.05, 16.0, 16.0), coin.SbVec3f(0, -1, 0))
507
        rp.apply(view.getSoRenderManager().getSceneGraph())
508
        pp = rp.getPickedPoint()
509
        self.assertTrue(pp is not None)
510
        det = pp.getDetail()
511
        self.assertTrue(det.getTypeId() == coin.SoFaceDetail.getClassTypeId())
512
        det = coin.cast(det, det.getTypeId().getName().getString())
513
        self.assertTrue(det.getFaceIndex() == 1)
514

515
    def testPrimitiveCount(self):
516
        if not FreeCAD.GuiUp:
517
            return
518
        self.planarMesh.append([-16.097176, -29.891157, 15.987688])
519
        self.planarMesh.append([-16.176304, -29.859991, 15.947966])
520
        self.planarMesh.append([-16.071451, -29.900553, 15.912505])
521
        self.planarMesh.append([-16.092241, -29.893408, 16.020439])
522
        self.planarMesh.append([-16.007210, -29.926180, 15.967641])
523
        self.planarMesh.append([-16.064457, -29.904951, 16.090832])
524
        planarMeshObject = Mesh.Mesh(self.planarMesh)
525

526
        from pivy import coin
527
        import FreeCADGui
528

529
        Mesh.show(planarMeshObject)
530
        view = FreeCADGui.ActiveDocument.ActiveView
531
        view.setAxisCross(False)
532
        pc = coin.SoGetPrimitiveCountAction()
533
        pc.apply(view.getSceneGraph())
534
        self.assertTrue(pc.getTriangleCount() == 2)
535
        # self.assertTrue(pc.getPointCount() == 6)
536

537
    def tearDown(self):
538
        # closing doc
539
        FreeCAD.closeDocument("MeshTest")
540

541

542
# Threads
543

544

545
def loadFile(name):
546
    # lock.acquire()
547
    mesh = Mesh.Mesh()
548
    # FreeCAD.Console.PrintMessage("Create mesh instance\n")
549
    # lock.release()
550
    mesh.read(name)
551
    # FreeCAD.Console.PrintMessage("Mesh loaded successfully.\n")
552

553

554
def createMesh(r, s):
555
    # FreeCAD.Console.PrintMessage("Create sphere (%s,%s)...\n"%(r,s))
556
    mesh = Mesh.createSphere(r, s)
557
    # FreeCAD.Console.PrintMessage("... destroy sphere\n")
558

559

560
class LoadMeshInThreadsCases(unittest.TestCase):
561
    def setUp(self):
562
        pass
563

564
    def testSphereMesh(self):
565
        for i in range(6, 8):
566
            thread.start_new(createMesh, (10.0, (i + 1) * 20))
567
        time.sleep(10)
568

569
    def testLoadMesh(self):
570
        mesh = Mesh.createSphere(10.0, 100)  # a fine sphere
571
        name = tempfile.gettempdir() + os.sep + "mesh.stl"
572
        mesh.write(name)
573
        # FreeCAD.Console.PrintMessage("Write mesh to %s\n"%(name))
574
        # lock=thread.allocate_lock()
575
        for i in range(2):
576
            thread.start_new(loadFile, (name,))
577
        time.sleep(1)
578

579
    def tearDown(self):
580
        pass
581

582

583
class PolynomialFitCases(unittest.TestCase):
584
    def setUp(self):
585
        pass
586

587
    def testFitGood(self):
588
        # symmetric
589
        v = []
590
        v.append(FreeCAD.Vector(0, 0, 0.0))
591
        v.append(FreeCAD.Vector(1, 0, 0.5))
592
        v.append(FreeCAD.Vector(2, 0, 0.0))
593
        v.append(FreeCAD.Vector(0, 1, 0.5))
594
        v.append(FreeCAD.Vector(1, 1, 1.0))
595
        v.append(FreeCAD.Vector(2, 1, 0.5))
596
        v.append(FreeCAD.Vector(0, 2, 0.0))
597
        v.append(FreeCAD.Vector(1, 2, 0.5))
598
        v.append(FreeCAD.Vector(2, 2, 0.0))
599
        d = Mesh.polynomialFit(v)
600
        c = d["Coefficients"]
601
        # print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
602
        for i in d["Residuals"]:
603
            self.assertTrue(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i))
604

605
    def testFitExact(self):
606
        # symmetric
607
        v = []
608
        v.append(FreeCAD.Vector(0, 0, 0.0))
609
        v.append(FreeCAD.Vector(1, 0, 0.0))
610
        v.append(FreeCAD.Vector(2, 0, 0.0))
611
        v.append(FreeCAD.Vector(0, 1, 0.0))
612
        v.append(FreeCAD.Vector(1, 1, 1.0))
613
        v.append(FreeCAD.Vector(2, 1, 0.0))
614
        d = Mesh.polynomialFit(v)
615
        c = d["Coefficients"]
616
        # print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
617
        for i in d["Residuals"]:
618
            self.assertTrue(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i))
619

620
    def testFitBad(self):
621
        # symmetric
622
        v = []
623
        v.append(FreeCAD.Vector(0, 0, 0.0))
624
        v.append(FreeCAD.Vector(1, 0, 0.0))
625
        v.append(FreeCAD.Vector(2, 0, 0.0))
626
        v.append(FreeCAD.Vector(0, 1, 0.0))
627
        v.append(FreeCAD.Vector(1, 1, 1.0))
628
        v.append(FreeCAD.Vector(2, 1, 0.0))
629
        v.append(FreeCAD.Vector(0, 2, 0.0))
630
        v.append(FreeCAD.Vector(1, 2, 0.0))
631
        v.append(FreeCAD.Vector(2, 2, 0.0))
632
        d = Mesh.polynomialFit(v)
633
        c = d["Coefficients"]
634
        # print ("Polynomial: f(x,y)=%f*x^2%+f*y^2%+f*x*y%+f*x%+f*y%+f" % (c[0],c[1],c[2],c[3],c[4],c[5]))
635
        for i in d["Residuals"]:
636
            self.assertFalse(math.fabs(i) < 0.0001, "Residual %f must be higher" % math.fabs(i))
637

638
    def tearDown(self):
639
        pass
640

641

642
class NastranReader(unittest.TestCase):
643
    def setUp(self):
644
        self.test_dir = join(FreeCAD.getHomePath(), "Mod", "Mesh", "App", "TestData")
645

646
    def testEightCharGRIDElement(self):
647
        m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRID_CQUAD4.bdf")
648
        self.assertEqual(m.CountPoints, 10)
649
        self.assertEqual(m.CountFacets, 8)  # Quads split into two triangles
650

651
    def testDelimitedGRIDElement(self):
652
        m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_Delimited_GRID_CQUAD4.bdf")
653
        self.assertEqual(m.CountPoints, 10)
654
        self.assertEqual(m.CountFacets, 8)  # Quads split into two triangles
655

656
    def testSixteenCharGRIDElement(self):
657
        m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRIDSTAR_CQUAD4.bdf")
658
        self.assertEqual(m.CountPoints, 4)
659
        self.assertEqual(m.CountFacets, 2)  # Quads split into two triangles
660

661
    def testCTRIA3Element(self):
662
        m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRID_CTRIA3.bdf")
663
        self.assertEqual(m.CountPoints, 3)
664
        self.assertEqual(m.CountFacets, 1)
665

666
    def tearDown(self):
667
        pass
668

669

670
class MeshSubElement(unittest.TestCase):
671
    def setUp(self):
672
        self.mesh = Mesh.createBox(1.0, 1.0, 1.0)
673

674
    def testCenterOfGravity(self):
675
        c = self.mesh.CenterOfGravity
676
        self.assertEqual(c, Base.Vector(0.0, 0.0, 0.0))
677

678
    def testSubElements(self):
679
        types = self.mesh.getElementTypes()
680
        self.assertIn("Mesh", types)
681
        self.assertIn("Segment", types)
682

683
    def testCountSubElements(self):
684
        self.assertEqual(self.mesh.countSubElements("Mesh"), 1)
685
        self.assertEqual(self.mesh.countSubElements("Segment"), 0)
686

687
    def testFacesFromSubElement(self):
688
        element = self.mesh.getFacesFromSubElement("Mesh", 0)
689
        self.assertIsInstance(element, tuple)
690
        self.assertEqual(len(element), 2)
691
        self.assertEqual(len(element[0]), 8)
692
        self.assertEqual(len(element[1]), 12)
693

694
    def testSegmentSubElement(self):
695
        self.mesh.addSegment([0, 2, 4, 6, 8])
696
        self.assertEqual(self.mesh.countSegments(), 1)
697
        self.assertEqual(self.mesh.countSubElements("Segment"), 1)
698
        element = self.mesh.getFacesFromSubElement("Segment", 0)
699
        self.assertIsInstance(element, tuple)
700
        self.assertEqual(len(element), 2)
701
        self.assertEqual(len(element[0]), 7)
702
        self.assertEqual(len(element[1]), 5)
703
        segment = self.mesh.meshFromSegment(self.mesh.getSegment(0))
704
        self.assertEqual(segment.CountPoints, 7)
705
        self.assertEqual(segment.CountFacets, 5)
706

707
    def tearDown(self):
708
        pass
709

710

711
class MeshProperty(unittest.TestCase):
712
    def setUp(self):
713
        self.doc = FreeCAD.newDocument("MeshTest")
714

715
    def tearDown(self):
716
        FreeCAD.closeDocument(self.doc.Name)
717

718
    def testMaterial(self):
719
        mesh = self.doc.addObject("Mesh::Feature", "Sphere")
720
        mesh.Mesh = Mesh.createBox(1.0, 1.0, 1.0)
721
        len1 = int(mesh.Mesh.CountFacets / 2)
722
        len2 = int(mesh.Mesh.CountFacets - len1)
723
        material = {"transparency": [0.2] * len1 + [0.8] * len2}
724
        material["binding"] = MeshEnums.Binding.PER_FACE
725
        material["ambientColor"] = [(1, 0, 0)] * (len1 + len2)
726
        material["diffuseColor"] = [(0, 1, 0)] * (len1 + len2)
727
        material["specularColor"] = [(0, 0, 1)] * (len1 + len2)
728
        material["emissiveColor"] = [(1, 1, 1)] * (len1 + len2)
729
        material["shininess"] = [0.3] * (len1 + len2)
730

731
        mesh.addProperty("Mesh::PropertyMaterial", "Material")
732
        mesh.Material = material
733

734
        TempPath = tempfile.gettempdir()
735
        SaveName = TempPath + os.sep + "mesh_with_material.FCStd"
736
        self.doc.saveAs(SaveName)
737
        FreeCAD.closeDocument(self.doc.Name)
738

739
        self.doc = FreeCAD.openDocument(SaveName)
740
        mesh2 = self.doc.Sphere
741
        material2 = mesh2.Material
742

743
        self.assertEqual(int(material2["binding"]), int(MeshEnums.Binding.PER_FACE))
744
        self.assertEqual(len(material2["ambientColor"]), len1 + len2)
745
        self.assertEqual(len(material2["diffuseColor"]), len1 + len2)
746
        self.assertEqual(len(material2["specularColor"]), len1 + len2)
747
        self.assertEqual(len(material2["emissiveColor"]), len1 + len2)
748
        self.assertEqual(len(material2["shininess"]), len1 + len2)
749
        self.assertEqual(len(material2["transparency"]), len1 + len2)
750

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.