#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2007 Jürgen Riegel # LGPL import os import sys import io import FreeCAD, unittest, Mesh import MeshEnums from FreeCAD import Base import time, tempfile, math # http://python-kurs.eu/threads.php try: import _thread as thread except Exception: import thread from os.path import join #--------------------------------------------------------------------------- # define the functions to test the FreeCAD mesh module #--------------------------------------------------------------------------- class MeshTopoTestCases(unittest.TestCase): def setUp(self): # set up a planar face with 18 triangles self.planarMesh = [] for x in range(3): for y in range(3): self.planarMesh.append( [0.0 + x, 0.0 + y,0.0000] ) self.planarMesh.append( [1.0 + x, 1.0 + y,0.0000] ) self.planarMesh.append( [0.0 + x, 1.0 + y,0.0000] ) self.planarMesh.append( [0.0 + x, 0.0 + y,0.0000] ) self.planarMesh.append( [1.0 + x, 0.0 + y,0.0000] ) self.planarMesh.append( [1.0 + x, 1.0 + y,0.0000] ) def testCollapseFacetsSingle(self): for i in range(18): planarMeshObject = Mesh.Mesh(self.planarMesh) planarMeshObject.collapseFacets([i]) def testCollapseFacetsMultible(self): planarMeshObject = Mesh.Mesh(self.planarMesh) planarMeshObject.collapseFacets(range(7)) def testCollapseFacetsAll(self): planarMeshObject = Mesh.Mesh(self.planarMesh) planarMeshObject.collapseFacets(range(18)) def testCorruptedFacet(self): v = FreeCAD.Vector mesh = Mesh.Mesh() mesh.addFacet( v(1.0e1, -1.0e1, 1.0e1), v(1.0e1, +1.0e1, 1.0e1), v(0.0e0, 0.0e0, 1.0e1)) mesh.addFacet( v(-1.0e1, -1.0e1, 1.0e1), v(-1.0e1, +1.0e1, 1.0e1), v(0e0, 0.0e0, 1.0e1)) mesh.addFacet( v(+1.0e1, +1.0e1, 1.0e1), v(-1.0e1, +1.0e1, 1.0e1), v(.0e0, 0.0e0, 1.0e1)) mesh.addFacet( v(+1.0e1, -1.0e1, 1.0e1), v(-1.0e1, -1.0e1, 1.0e1), v(.0e0, 0.0e0, 1.0e1)) mesh.addFacet( v(-1.0e1, +1.0e1, 1.0e1), v(+1.0e1, +1.0e1, 1.0e1), v(+1.0e1, +1.0e1, 1.0e1)) mesh.addFacet( v(+1.0e1, +1.0e1, 1.0e1), v(+1.0e1, 00.0e1, 1.0e1), v(+1.0e1, -1.0e1, 1.0e1)) self.assertEqual(mesh.CountFacets, 6) mesh.fixIndices() self.assertEqual(mesh.CountFacets, 5) class MeshSplitTestCases(unittest.TestCase): def setUp(self): self.mesh = Mesh.createBox(1.0, 1.0, 1.0) def testSplitFacetOnOneEdge(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, p1, (p2 + p3) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_21(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, (p1 + p3) / 2, (p2 + p3) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_12(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, (p2 + p3) / 2, (p1 + p3) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_01(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, (p1 + p2) / 2, (p2 + p3) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_10(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, (p2 + p3) / 2, (p1 + p2) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_02(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, (p1 + p2) / 2, (p1 + p3) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_20(self): p1 = self.mesh.Points[0].Vector p2 = self.mesh.Points[1].Vector p3 = self.mesh.Points[2].Vector self.mesh.splitFacet(0, (p1 + p3) / 2, (p1 + p2) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testSplitFacetOnTwoEdges_5teps(self): Vec3d = FreeCAD.Vector for i in range(5): f = self.mesh.Facets[0] p1 = Vec3d(f.Points[0]) p2 = Vec3d(f.Points[1]) p3 = Vec3d(f.Points[2]) self.mesh.splitFacet(0, (p1 + p3) / 2, (p2 + p3) / 2) self.assertFalse(self.mesh.hasNonManifolds()) self.assertFalse(self.mesh.hasInvalidNeighbourhood()) self.assertFalse(self.mesh.hasPointsOutOfRange()) self.assertFalse(self.mesh.hasFacetsOutOfRange()) self.assertFalse(self.mesh.hasCorruptedFacets()) self.assertTrue(self.mesh.isSolid()) def testFindNearest(self): self.assertEqual(len(self.mesh.nearestFacetOnRay((-2,2,-6),(0,0,1))), 0) self.assertEqual(len(self.mesh.nearestFacetOnRay((0.5,0.5,0.5),(0,0,1))), 1) self.assertEqual(len(self.mesh.nearestFacetOnRay((0.5,0.5,0.5),(0,0,1),-math.pi/2)), 0) self.assertEqual(len(self.mesh.nearestFacetOnRay((0.2,0.1,0.2),(0,0, 1))), len(self.mesh.nearestFacetOnRay((0.2,0.1,0.2),(0,0,-1)))) self.assertEqual(len(self.mesh.nearestFacetOnRay((0.2,0.1,0.2),(0,0, 1), math.pi/2)), len(self.mesh.nearestFacetOnRay((0.2,0.1,0.2),(0,0,-1), math.pi/2))) # Apply placement to mesh plm = Base.Placement(Base.Vector(1,2,3), Base.Rotation(1,1,1,1)) pnt = Base.Vector(0.5, 0.5, 0.5) vec = Base.Vector(0.0, 0.0, 1.0) self.mesh.Placement = plm self.assertEqual(len(self.mesh.nearestFacetOnRay(pnt,vec)), 0) # Apply the placement on the ray as well pnt = plm.multVec(pnt) vec = plm.Rotation.multVec(vec) self.assertEqual(len(self.mesh.nearestFacetOnRay(pnt,vec)), 1) def testForaminate(self): class FilterAngle: def __init__(self, mesh, vec, limit): self.myMesh = mesh self.vec = vec self.limit = limit def check_angle(self, item): angle = self.myMesh.Facets[item].Normal.getAngle(self.vec) return angle < self.limit results = self.mesh.foraminate((0.0, 0.0, 0.0), (0,1,1)) filtered_result = list(filter(FilterAngle(self.mesh, FreeCAD.Vector(0,1,1), math.pi/2).check_angle, results.keys())) self.assertEqual(filtered_result, list(self.mesh.foraminate((0.0, 0.0, 0.0), (0,1,1), math.pi/2).keys())) def testForaminatePlacement(self): pnt = Base.Vector(0.0, 0.0, 0.0) vec = Base.Vector(0.0, 1.0, 1.0) results = self.mesh.foraminate(pnt, vec) self.assertEqual(len(results), 4) # Apply placement to mesh plm = Base.Placement(Base.Vector(1,2,3), Base.Rotation(1,1,1,1)) self.mesh.Placement = plm self.assertEqual(len(self.mesh.foraminate(pnt, vec)), 0) # Apply the placement on the ray as well pnt = plm.multVec(pnt) vec = plm.Rotation.multVec(vec) results2 = self.mesh.foraminate(pnt, vec) self.assertEqual(len(results2), 4) self.assertEqual(list(results.keys()), list(results2.keys())) class MeshGeoTestCases(unittest.TestCase): def setUp(self): # set up a planar face with 2 triangles self.planarMesh = [] def testIntersection(self): self.planarMesh.append( [0.9961,1.5413,4.3943] ) self.planarMesh.append( [9.4796,10.024,-3.0937] ) self.planarMesh.append( [1.4308,11.3841,2.6829] ) self.planarMesh.append( [2.6493,2.2536,3.0679] ) self.planarMesh.append( [13.1126,0.4857,-4.4417] ) self.planarMesh.append( [10.2410,8.9040,-3.5002] ) planarMeshObject = Mesh.Mesh(self.planarMesh) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] res=f1.intersect(f2) self.assertTrue(len(res) == 0) def testIntersection2(self): self.planarMesh.append( [-16.097176,-29.891157,15.987688] ) self.planarMesh.append( [-16.176304,-29.859991,15.947966] ) self.planarMesh.append( [-16.071451,-29.900553,15.912505] ) self.planarMesh.append( [-16.092241,-29.893408,16.020439] ) self.planarMesh.append( [-16.007210,-29.926180,15.967641] ) self.planarMesh.append( [-16.064457,-29.904951,16.090832] ) planarMeshObject = Mesh.Mesh(self.planarMesh) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] # does definitely NOT intersect res=f1.intersect(f2) self.assertTrue(len(res) == 0) def testIntersectionOfTransformedMesh(self): self.planarMesh.append( [0.0,10.0,10.0] ) self.planarMesh.append( [10.0,0.0,10.0] ) self.planarMesh.append( [10.0,10.0,10.0] ) self.planarMesh.append( [6.0,8.0,10.0] ) self.planarMesh.append( [16.0,8.0,10.0] ) self.planarMesh.append( [6.0,18.0,10.0] ) planarMeshObject = Mesh.Mesh(self.planarMesh) mat = Base.Matrix() mat.rotateX(1.0) mat.rotateY(1.0) mat.rotateZ(1.0) planarMeshObject.transformGeometry(mat) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] res=f1.intersect(f2) self.assertEqual(len(res), 2) def testIntersectionOfParallelTriangles(self): self.planarMesh.append( [0.0,10.0,10.0] ) self.planarMesh.append( [10.0,0.0,10.0] ) self.planarMesh.append( [10.0,10.0,10.0] ) self.planarMesh.append( [6.0,8.0,10.1] ) self.planarMesh.append( [16.0,8.0,10.1] ) self.planarMesh.append( [6.0,18.0,10.1] ) planarMeshObject = Mesh.Mesh(self.planarMesh) mat = Base.Matrix() mat.rotateX(1.0) mat.rotateY(1.0) mat.rotateZ(1.0) planarMeshObject.transformGeometry(mat) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] res=f1.intersect(f2) self.assertTrue(len(res) == 0) def testIntersectionOnEdge(self): self.planarMesh.append( [5.0, -1.9371663331985474, 0.49737977981567383] ) self.planarMesh.append( [4.0, -1.9371663331985474, 0.49737977981567383] ) self.planarMesh.append( [5.0, -1.9842294454574585, 0.25066646933555603] ) self.planarMesh.append( [4.6488823890686035, -1.7827962636947632, 0.4577442705631256] ) self.planarMesh.append( [4.524135112762451, -2.0620131492614746, 0.5294350385665894] ) self.planarMesh.append( [4.6488823890686035, -1.8261089324951172, 0.23069120943546295] ) planarMeshObject = Mesh.Mesh(self.planarMesh) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] res = f1.intersect(f2) self.assertEqual(len(res), 2) def testIntersectionCoplanar(self): self.planarMesh.append( [0.,10.,10.] ) self.planarMesh.append( [10.,0.,10.] ) self.planarMesh.append( [10.,10.,10.] ) self.planarMesh.append( [6.,8.,10.] ) self.planarMesh.append( [16.,8.,10.] ) self.planarMesh.append( [6.,18.,10.] ) planarMeshObject = Mesh.Mesh(self.planarMesh) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] res = f1.intersect(f2) self.assertTrue(len(res) == 2) def testIntersectionOverlap(self): self.planarMesh.append( [0.,0.,0.] ) self.planarMesh.append( [5.,0.,0.] ) self.planarMesh.append( [8.,5.,0.] ) self.planarMesh.append( [4.,0.,0.] ) self.planarMesh.append( [10.,0.,0.] ) self.planarMesh.append( [9.,5.,0.] ) planarMeshObject = Mesh.Mesh(self.planarMesh) f1 = planarMeshObject.Facets[0] f2 = planarMeshObject.Facets[1] res = f1.intersect(f2) self.assertTrue(len(res) == 2) def testIntersectionOfIntersectingEdges(self): self.planarMesh.append( [0.,10.,10.] ) self.planarMesh.append( [10.,0.,10.] ) self.planarMesh.append( [10.,10.,10.] ) self.planarMesh.append( [6.,8.,10.] ) self.planarMesh.append( [16.,8.,10.] ) self.planarMesh.append( [6.,18.,10.] ) planarMeshObject = Mesh.Mesh(self.planarMesh) edge1 = planarMeshObject.Facets[0].getEdge(2) edge2 = planarMeshObject.Facets[1].getEdge(2) res = edge1.intersectWithEdge(edge2) self.assertTrue(len(res) == 1) self.assertEqual(res[0][0], 6.0) self.assertEqual(res[0][1], 10.0) self.assertEqual(res[0][2], 10.0) def testIntersectionOfParallelEdges(self): self.planarMesh.append( [0.,10.,10.] ) self.planarMesh.append( [10.,0.,10.] ) self.planarMesh.append( [10.,10.,10.] ) self.planarMesh.append( [6.,8.,10.] ) self.planarMesh.append( [16.,8.,10.] ) self.planarMesh.append( [6.,18.,10.] ) planarMeshObject = Mesh.Mesh(self.planarMesh) edge1 = planarMeshObject.Facets[0].getEdge(2) edge2 = planarMeshObject.Facets[1].getEdge(0) res = edge1.intersectWithEdge(edge2) self.assertTrue(len(res) == 0) def testIntersectionOfCollinearEdges(self): self.planarMesh.append( [0.,0.,0.] ) self.planarMesh.append( [6.,0.,0.] ) self.planarMesh.append( [3.,4.,0.] ) self.planarMesh.append( [7.,0.,0.] ) self.planarMesh.append( [13.,0.,0.] ) self.planarMesh.append( [10.,4.,0.] ) planarMeshObject = Mesh.Mesh(self.planarMesh) edge1 = planarMeshObject.Facets[0].getEdge(0) edge2 = planarMeshObject.Facets[1].getEdge(0) res = edge1.intersectWithEdge(edge2) self.assertTrue(len(res) == 0) def testIntersectionOfWarpedEdges(self): self.planarMesh.append( [0.,0.,0.] ) self.planarMesh.append( [6.,0.,0.] ) self.planarMesh.append( [3.,4.,0.] ) self.planarMesh.append( [2.,2.,1.] ) self.planarMesh.append( [8.,2.,1.] ) self.planarMesh.append( [5.,6.,1.] ) planarMeshObject = Mesh.Mesh(self.planarMesh) edge1 = planarMeshObject.Facets[0].getEdge(1) edge2 = planarMeshObject.Facets[1].getEdge(0) res = edge1.intersectWithEdge(edge2) self.assertTrue(len(res) == 0) def testSelfIntersection(self): s = b"""solid Simple facet normal 0.0e0 0.0e0 1.0e1 outer loop vertex 0.0e1 0.0e1 1.0e1 vertex 0.0e1 +1.0e1 1.0e1 vertex +1.0e1 0.0e1 1.0e1 endloop endfacet facet normal 0.0e0 0.0e0 1.0e1 outer loop vertex 0.0e1 +1.0e1 1.0e1 vertex +1.0e1 0.0e1 1.0e1 vertex 1.0e1 1.0e1 1.0e1 endloop endfacet facet normal 0.0e0 0.0e0 1.0e1 outer loop vertex 0.0e1 0.0e1 1.0e1 vertex 0.0e1 +1.0e1 1.0e1 vertex -1.0e1 1.0e1 1.0e1 endloop endfacet facet normal 0.0e0 0.0e0 1.0e1 outer loop vertex 0.0e1 0.0e1 1.0e1 vertex +1.0e1 0.0e1 1.0e1 vertex +1.0e1 -1.0e1 1.0e1 endloop endfacet facet normal 0.0e0 0.0e0 1.0e1 outer loop vertex 0.6e1 0.8e1 1.0e1 vertex +1.6e1 0.8e1 1.0e1 vertex +0.6e1 1.8e1 1.0e1 endloop endfacet endsolid Simple""" mesh = Mesh.Mesh() data = io.BytesIO(s) mesh.read(Stream=data, Format="AST") self.assertTrue(mesh.hasSelfIntersections()) class PivyTestCases(unittest.TestCase): def setUp(self): # set up a planar face with 2 triangles self.planarMesh = [] FreeCAD.newDocument("MeshTest") def testRayPick(self): if not FreeCAD.GuiUp: return self.planarMesh.append( [-16.097176,-29.891157,15.987688] ) self.planarMesh.append( [-16.176304,-29.859991,15.947966] ) self.planarMesh.append( [-16.071451,-29.900553,15.912505] ) self.planarMesh.append( [-16.092241,-29.893408,16.020439] ) self.planarMesh.append( [-16.007210,-29.926180,15.967641] ) self.planarMesh.append( [-16.064457,-29.904951,16.090832] ) planarMeshObject = Mesh.Mesh(self.planarMesh) from pivy import coin; import FreeCADGui Mesh.show(planarMeshObject) view=FreeCADGui.ActiveDocument.ActiveView.getViewer() rp=coin.SoRayPickAction(view.getSoRenderManager().getViewportRegion()) rp.setRay(coin.SbVec3f(-16.05,16.0,16.0),coin.SbVec3f(0,-1,0)) rp.apply(view.getSoRenderManager().getSceneGraph()) pp=rp.getPickedPoint() self.assertTrue(pp is not None) det=pp.getDetail() self.assertTrue(det.getTypeId() == coin.SoFaceDetail.getClassTypeId()) det=coin.cast(det, det.getTypeId().getName().getString()) self.assertTrue(det.getFaceIndex() == 1) def testPrimitiveCount(self): if not FreeCAD.GuiUp: return self.planarMesh.append( [-16.097176,-29.891157,15.987688] ) self.planarMesh.append( [-16.176304,-29.859991,15.947966] ) self.planarMesh.append( [-16.071451,-29.900553,15.912505] ) self.planarMesh.append( [-16.092241,-29.893408,16.020439] ) self.planarMesh.append( [-16.007210,-29.926180,15.967641] ) self.planarMesh.append( [-16.064457,-29.904951,16.090832] ) planarMeshObject = Mesh.Mesh(self.planarMesh) from pivy import coin; import FreeCADGui Mesh.show(planarMeshObject) view=FreeCADGui.ActiveDocument.ActiveView view.setAxisCross(False) pc=coin.SoGetPrimitiveCountAction() pc.apply(view.getSceneGraph()) self.assertTrue(pc.getTriangleCount() == 2) #self.assertTrue(pc.getPointCount() == 6) def tearDown(self): #closing doc FreeCAD.closeDocument("MeshTest") # Threads def loadFile(name): #lock.acquire() mesh=Mesh.Mesh() #FreeCAD.Console.PrintMessage("Create mesh instance\n") #lock.release() mesh.read(name) #FreeCAD.Console.PrintMessage("Mesh loaded successfully.\n") def createMesh(r,s): #FreeCAD.Console.PrintMessage("Create sphere (%s,%s)...\n"%(r,s)) mesh=Mesh.createSphere(r,s) #FreeCAD.Console.PrintMessage("... destroy sphere\n") class LoadMeshInThreadsCases(unittest.TestCase): def setUp(self): pass def testSphereMesh(self): for i in range(6,8): thread.start_new(createMesh,(10.0,(i+1)*20)) time.sleep(10) def testLoadMesh(self): mesh=Mesh.createSphere(10.0,100) # a fine sphere name=tempfile.gettempdir() + os.sep + "mesh.stl" mesh.write(name) #FreeCAD.Console.PrintMessage("Write mesh to %s\n"%(name)) #lock=thread.allocate_lock() for i in range(2): thread.start_new(loadFile,(name,)) time.sleep(1) def tearDown(self): pass class PolynomialFitCases(unittest.TestCase): def setUp(self): pass def testFitGood(self): # symmetric v=[] v.append(FreeCAD.Vector(0,0,0.0)) v.append(FreeCAD.Vector(1,0,0.5)) v.append(FreeCAD.Vector(2,0,0.0)) v.append(FreeCAD.Vector(0,1,0.5)) v.append(FreeCAD.Vector(1,1,1.0)) v.append(FreeCAD.Vector(2,1,0.5)) v.append(FreeCAD.Vector(0,2,0.0)) v.append(FreeCAD.Vector(1,2,0.5)) v.append(FreeCAD.Vector(2,2,0.0)) d = Mesh.polynomialFit(v) c = d["Coefficients"] #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])) for i in d["Residuals"]: self.assertTrue(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i)) def testFitExact(self): # symmetric v=[] v.append(FreeCAD.Vector(0,0,0.0)) v.append(FreeCAD.Vector(1,0,0.0)) v.append(FreeCAD.Vector(2,0,0.0)) v.append(FreeCAD.Vector(0,1,0.0)) v.append(FreeCAD.Vector(1,1,1.0)) v.append(FreeCAD.Vector(2,1,0.0)) d = Mesh.polynomialFit(v) c = d["Coefficients"] #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])) for i in d["Residuals"]: self.assertTrue(math.fabs(i) < 0.0001, "Too high residual %f" % math.fabs(i)) def testFitBad(self): # symmetric v=[] v.append(FreeCAD.Vector(0,0,0.0)) v.append(FreeCAD.Vector(1,0,0.0)) v.append(FreeCAD.Vector(2,0,0.0)) v.append(FreeCAD.Vector(0,1,0.0)) v.append(FreeCAD.Vector(1,1,1.0)) v.append(FreeCAD.Vector(2,1,0.0)) v.append(FreeCAD.Vector(0,2,0.0)) v.append(FreeCAD.Vector(1,2,0.0)) v.append(FreeCAD.Vector(2,2,0.0)) d = Mesh.polynomialFit(v) c = d["Coefficients"] #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])) for i in d["Residuals"]: self.assertFalse(math.fabs(i) < 0.0001, "Residual %f must be higher" % math.fabs(i)) def tearDown(self): pass class NastranReader(unittest.TestCase): def setUp(self): self.test_dir = join(FreeCAD.getHomePath(), "Mod", "Mesh", "App", "TestData") def testEightCharGRIDElement(self): m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRID_CQUAD4.bdf") self.assertEqual(m.CountPoints,10) self.assertEqual(m.CountFacets,8) # Quads split into two triangles def testDelimitedGRIDElement(self): m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_Delimited_GRID_CQUAD4.bdf") self.assertEqual(m.CountPoints,10) self.assertEqual(m.CountFacets,8) # Quads split into two triangles def testSixteenCharGRIDElement(self): m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRIDSTAR_CQUAD4.bdf") self.assertEqual(m.CountPoints,4) self.assertEqual(m.CountFacets,2) # Quads split into two triangles def testCTRIA3Element(self): m = Mesh.read(f"{self.test_dir}/NASTRAN_Test_GRID_CTRIA3.bdf") self.assertEqual(m.CountPoints,3) self.assertEqual(m.CountFacets,1) def tearDown(self): pass class MeshSubElement(unittest.TestCase): def setUp(self): self.mesh = Mesh.createBox(1.0, 1.0, 1.0) def testCenterOfGravity(self): c = self.mesh.CenterOfGravity self.assertEqual(c, Base.Vector(0.0, 0.0, 0.0)) def testSubElements(self): types = self.mesh.getElementTypes() self.assertIn("Mesh", types) self.assertIn("Segment", types) def testCountSubElements(self): self.assertEqual(self.mesh.countSubElements("Mesh"), 1) self.assertEqual(self.mesh.countSubElements("Segment"), 0) def testFacesFromSubElement(self): element = self.mesh.getFacesFromSubElement("Mesh", 0) self.assertIsInstance(element, tuple) self.assertEqual(len(element), 2) self.assertEqual(len(element[0]), 8) self.assertEqual(len(element[1]), 12) def testSegmentSubElement(self): self.mesh.addSegment([0, 2, 4, 6, 8]) self.assertEqual(self.mesh.countSegments(), 1) self.assertEqual(self.mesh.countSubElements("Segment"), 1) element = self.mesh.getFacesFromSubElement("Segment", 0) self.assertIsInstance(element, tuple) self.assertEqual(len(element), 2) self.assertEqual(len(element[0]), 7) self.assertEqual(len(element[1]), 5) segment = self.mesh.meshFromSegment(self.mesh.getSegment(0)) self.assertEqual(segment.CountPoints, 7) self.assertEqual(segment.CountFacets, 5) def tearDown(self): pass class MeshProperty(unittest.TestCase): def setUp(self): self.doc = FreeCAD.newDocument("MeshTest") def tearDown(self): FreeCAD.closeDocument(self.doc.Name) def testMaterial(self): mesh = self.doc.addObject("Mesh::Feature", "Sphere") mesh.Mesh = Mesh.createBox(1.0, 1.0, 1.0) len1 = int(mesh.Mesh.CountFacets / 2) len2 = int(mesh.Mesh.CountFacets - len1) material = {"transparency" : [0.2] * len1 + [0.8] * len2} material["binding"] = MeshEnums.Binding.PER_FACE material["ambientColor"] = [(1,0,0)] * (len1 + len2) material["diffuseColor"] = [(0,1,0)] * (len1 + len2) material["specularColor"] = [(0,0,1)] * (len1 + len2) material["emissiveColor"] = [(1,1,1)] * (len1 + len2) material["shininess"] = [0.3] * (len1 + len2) mesh.addProperty("Mesh::PropertyMaterial", "Material") mesh.Material = material TempPath = tempfile.gettempdir() SaveName = TempPath + os.sep + "mesh_with_material.FCStd" self.doc.saveAs(SaveName) FreeCAD.closeDocument(self.doc.Name) self.doc = FreeCAD.openDocument(SaveName) mesh2 = self.doc.Sphere material2 = mesh2.Material self.assertEqual(int(material2["binding"]), int(MeshEnums.Binding.PER_FACE)) self.assertEqual(len(material2["ambientColor"]), len1 + len2) self.assertEqual(len(material2["diffuseColor"]), len1 + len2) self.assertEqual(len(material2["specularColor"]), len1 + len2) self.assertEqual(len(material2["emissiveColor"]), len1 + len2) self.assertEqual(len(material2["shininess"]), len1 + len2) self.assertEqual(len(material2["transparency"]), len1 + len2)