1 // Created on: 2008-04-11
2 // Created by: Peter KURNEV
3 // Copyright (c) 2008-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <MeshTest.ixx>
17 #include <Draw_Interpretor.hxx>
18 #include <TColStd_MapOfAsciiString.hxx>
19 #include <BRepMesh_DiscretFactory.hxx>
20 #include <TCollection_AsciiString.hxx>
21 #include <TColStd_MapIteratorOfMapOfAsciiString.hxx>
22 #include <BRepMesh_FactoryError.hxx>
23 #include <BRepMesh_DiscretRoot.hxx>
24 #include <BRepMesh_IncrementalMesh.hxx>
25 #include <Bnd_Box.hxx>
26 #include <BRepMesh_PDiscretRoot.hxx>
29 #include <TopTools_IndexedMapOfShape.hxx>
31 #include <Poly_Triangulation.hxx>
33 #include <GProp_GProps.hxx>
34 #include <BRepGProp.hxx>
35 #include <DrawTrSurf.hxx>
36 #include <BRep_Tool.hxx>
38 #include <MeshTest_CheckTopology.hxx>
39 #include <TColgp_Array1OfPnt2d.hxx>
40 #include <Poly_Polygon3D.hxx>
41 #include <Poly_Polygon2D.hxx>
42 #include <Standard.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TColStd_Array1OfInteger.hxx>
45 #include <Poly_PolygonOnTriangulation.hxx>
46 #include <TopoDS_Face.hxx>
47 #include <BRepMesh_Edge.hxx>
48 #include <NCollection_Map.hxx>
50 static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer , const char** );
51 static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer , const char** );
52 static Standard_Integer mpgetdefaultname (Draw_Interpretor& , Standard_Integer , const char** );
53 static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer , const char** );
54 static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer , const char** );
55 static Standard_Integer mperror (Draw_Interpretor& , Standard_Integer , const char** );
56 static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer , const char** );
57 static Standard_Integer mpparallel (Draw_Interpretor& , Standard_Integer , const char** );
58 static Standard_Integer triarea (Draw_Interpretor& , Standard_Integer , const char** );
59 static Standard_Integer tricheck (Draw_Interpretor& , Standard_Integer , const char** );
61 //=======================================================================
62 //function : PluginCommands
64 //=======================================================================
65 void MeshTest::PluginCommands(Draw_Interpretor& theCommands)
67 static Standard_Boolean done = Standard_False;
73 const char* g = "Mesh Commands";
75 theCommands.Add("mpnames" , "use mpnames" , __FILE__, mpnames , g);
76 theCommands.Add("mpsetdefaultname" , "use mpsetdefaultname" , __FILE__, mpsetdefaultname , g);
77 theCommands.Add("mpgetdefaultname" , "use mpgetdefaultname" , __FILE__, mpgetdefaultname , g);
78 theCommands.Add("mpsetfunctionname", "use mpsetfunctionname", __FILE__, mpsetfunctionname , g);
79 theCommands.Add("mpgetfunctionname", "use mpgetfunctionname", __FILE__, mpgetfunctionname , g);
80 theCommands.Add("mperror" , "use mperror" , __FILE__, mperror , g);
81 theCommands.Add("mpincmesh" , "use mpincmesh" , __FILE__, mpincmesh , g);
82 theCommands.Add("mpparallel" , "mpparallel [toTurnOn] : show / set multi-threading flag for incremental mesh",
83 __FILE__, mpparallel, g);
84 theCommands.Add("triarea","shape [eps] (computes triangles and surface area)",__FILE__, triarea, g);
85 theCommands.Add("tricheck", "shape (checks triangulation of shape)", __FILE__, tricheck, g);
89 //=======================================================================
92 //=======================================================================
93 static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer n, const char** )
96 TColStd_MapIteratorOfMapOfAsciiString aIt;
99 printf(" use mpnames\n");
103 const TColStd_MapOfAsciiString& aMN=BRepMesh_DiscretFactory::Get().Names();
106 printf(" *no names found\n");
110 printf(" *available names:\n");
112 for (; aIt.More(); aIt.Next()) {
113 const TCollection_AsciiString& aName=aIt.Key();
114 printf(" %s\n", aName.ToCString());
119 //=======================================================================
120 //function : mpsetdefaultname
122 //=======================================================================
123 static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer n, const char**a )
125 TCollection_AsciiString aName;
128 printf(" use mpsetdefaultname name\n");
134 if (BRepMesh_DiscretFactory::Get().SetDefaultName (aName))
141 //=======================================================================
142 //function : mpgetdefaultname
144 //=======================================================================
145 static Standard_Integer mpgetdefaultname (Draw_Interpretor& , Standard_Integer n, const char** )
148 printf(" use mpgetdefaultname\n");
152 const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().DefaultName();
153 printf(" *default name: %s\n", aName.ToCString());
157 //=======================================================================
158 //function : mpsetfunctionname
160 //=======================================================================
161 static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer n, const char**a )
163 TCollection_AsciiString aName;
166 printf(" use mpsetfunctionname name\n");
172 if (BRepMesh_DiscretFactory::Get().SetFunctionName (aName))
179 //=======================================================================
180 //function : mpgetdefaultname
182 //=======================================================================
183 static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer n, const char** )
186 printf(" use mpgetfunctionname\n");
190 const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().FunctionName();
191 printf(" *function name: %s\n", aName.ToCString());
195 //=======================================================================
198 //=======================================================================
199 static Standard_Integer mperror (Draw_Interpretor& , Standard_Integer n, const char** )
201 BRepMesh_FactoryError aErr;
204 printf(" use mperror\n");
208 aErr=BRepMesh_DiscretFactory::Get().ErrorStatus();
209 printf(" *ErrorStatus: %d\n", (int)aErr);
214 //=======================================================================
215 //function :mpincmesh
217 //=======================================================================
218 static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer n, const char** a)
220 Standard_Real aDeflection, aAngle;
224 printf(" use mpincmesh s deflection [angle]\n");
230 printf(" null shapes is not allowed here\n");
234 aDeflection=Draw::Atof(a[2]);
237 aAngle=Draw::Atof(a[3]);
240 Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aS,
244 BRepMesh_FactoryError aErr = BRepMesh_DiscretFactory::Get().ErrorStatus();
245 if (aErr != BRepMesh_FE_NOERROR)
247 printf(" *Factory::Get().ErrorStatus()=%d\n", (int)aErr);
250 if (aMeshAlgo.IsNull())
252 printf(" *Can not create the algo\n");
256 aMeshAlgo->Perform();
257 if (!aMeshAlgo->IsDone())
259 printf(" *Not done\n");
265 //#######################################################################
266 static Standard_Integer triarea (Draw_Interpretor& di, int n, const char ** a)
271 TopoDS_Shape shape = DBRep::Get(a[1]);
272 if (shape.IsNull()) return 1;
273 Standard_Real anEps = -1.;
275 anEps = Draw::Atof(a[2]);
277 TopTools_IndexedMapOfShape aMapF;
278 TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
280 // detect if a shape has triangulation
281 Standard_Boolean hasPoly = Standard_False;
283 for (i=1; i <= aMapF.Extent(); i++) {
284 const TopoDS_Face& aFace = TopoDS::Face(aMapF(i));
285 TopLoc_Location aLoc;
286 Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
287 if (!aPoly.IsNull()) {
288 hasPoly = Standard_True;
293 // compute area by triangles
296 for (i=1; i <= aMapF.Extent(); i++) {
297 const TopoDS_Face& aFace = TopoDS::Face(aMapF(i));
298 TopLoc_Location aLoc;
299 Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
300 if (aPoly.IsNull()) {
301 cout << "face "<<i<<" has no triangulation"<<endl;
304 const Poly_Array1OfTriangle& triangles = aPoly->Triangles();
305 const TColgp_Array1OfPnt& nodes = aPoly->Nodes();
306 for (int j=triangles.Lower(); j <= triangles.Upper(); j++) {
307 const Poly_Triangle& tri = triangles(j);
309 tri.Get (n1, n2, n3);
310 const gp_Pnt& p1 = nodes(n1);
311 const gp_Pnt& p2 = nodes(n2);
312 const gp_Pnt& p3 = nodes(n3);
315 double ar = v1.CrossMagnitude(v2);
322 // compute area by geometry
325 BRepGProp::SurfaceProperties(shape, props);
327 BRepGProp::SurfaceProperties(shape, props, anEps);
328 double aGeomArea = props.Mass();
330 di << aTriArea << " " << aGeomArea << "\n";
334 //#######################################################################
335 Standard_Boolean IsEqual(const BRepMesh_Edge& theFirst, const BRepMesh_Edge& theSecond)
337 return theFirst.IsEqual(theSecond);
340 static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
344 TopoDS_Shape shape = DBRep::Get(a[1]);
345 if (shape.IsNull()) return 1;
347 TopTools_IndexedMapOfShape aMapF;
348 TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
349 Standard_CString name = ".";
352 MeshTest_CheckTopology aCheck(shape);
355 // dump info on free links inside the triangulation
356 Standard_Integer nbFree = 0;
357 Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k;
359 for (k=1; k <= nbFac; k++) {
360 Standard_Integer nbEdge = aCheck.NbFreeLinks(k);
361 Standard_Integer iF = aCheck.GetFaceNumWithFL(k);
363 di << "free links of face " << iF << "\n";
365 const TopoDS_Shape& aShape = aMapF.FindKey(iF);
366 const TopoDS_Face& aFace = TopoDS::Face(aShape);
367 TopLoc_Location aLoc;
368 Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
369 const TColgp_Array1OfPnt& aPoints = aT->Nodes();
370 const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
371 const gp_Trsf& trsf = aLoc.Transformation();
373 TColgp_Array1OfPnt pnts(1,2);
374 TColgp_Array1OfPnt2d pnts2d(1,2);
375 for (i=1; i <= nbEdge; i++) {
376 Standard_Integer n1, n2;
377 aCheck.GetFreeLink(k, i, n1, n2);
378 di << "{" << n1 << " " << n2 << "} ";
379 pnts(1) = aPoints(n1).Transformed(trsf);
380 pnts(2) = aPoints(n2).Transformed(trsf);
381 Handle(Poly_Polygon3D) poly = new Poly_Polygon3D (pnts);
382 DrawTrSurf::Set (name, poly);
383 DrawTrSurf::Set (name, pnts(1));
384 DrawTrSurf::Set (name, pnts(2));
385 pnts2d(1) = aPoints2d(n1);
386 pnts2d(2) = aPoints2d(n2);
387 Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
388 DrawTrSurf::Set (name, poly2d);
389 DrawTrSurf::Set (name, pnts2d(1));
390 DrawTrSurf::Set (name, pnts2d(2));
396 // dump info on cross face errors
397 Standard_Integer nbErr = aCheck.NbCrossFaceErrors();
399 di << "cross face errors: {face1, node1, face2, node2, distance}" << "\n";
400 for (i=1; i <= nbErr; i++) {
401 Standard_Integer iF1, n1, iF2, n2;
403 aCheck.GetCrossFaceError(i, iF1, n1, iF2, n2, aVal);
404 di << "{" << iF1 << " " << n1 << " " << iF2 << " " << n2 << " " << aVal << "} ";
409 // dump info on edges
410 Standard_Integer nbAsync = aCheck.NbAsyncEdges();
412 di << "async edges:" << "\n";
413 for (i=1; i <= nbAsync; i++) {
414 Standard_Integer ie = aCheck.GetAsyncEdgeNum(i);
420 // dump info on free nodes
421 Standard_Integer nbFreeNodes = aCheck.NbFreeNodes();
422 if (nbFreeNodes > 0) {
423 di << "free nodes (in pairs: face / node): " << "\n";
424 for (i=1; i <= nbFreeNodes; i++) {
425 Standard_Integer iface, inode;
426 aCheck.GetFreeNodeNum(i, iface, inode);
427 di << "{" << iface << " " << inode << "} ";
432 // output errors summary to DRAW
433 if ( nbFree > 0 || nbErr > 0 || nbAsync > 0 || nbFreeNodes > 0)
434 di << "Free_links " << nbFree
435 << " Cross_face_errors " << nbErr
436 << " Async_edges " << nbAsync
437 << " Free_nodes " << nbFreeNodes << "\n";
440 Standard_Integer aFaceId = 1;
441 TopExp_Explorer aFaceExp(shape, TopAbs_FACE);
442 for ( ; aFaceExp.More(); aFaceExp.Next(), ++aFaceId)
444 const TopoDS_Shape& aShape = aFaceExp.Current();
445 const TopoDS_Face& aFace = TopoDS::Face(aShape);
447 TopLoc_Location aLoc;
448 Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
450 // Iterate boundary edges
451 NCollection_Map<BRepMesh_Edge> aBoundaryEdgeMap;
452 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
453 for ( ; anExp.More(); anExp.Next() )
455 TopLoc_Location anEdgeLoc;
456 const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
457 Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLoc);
463 const TColStd_Array1OfInteger& anIndices = aPoly->Nodes();
464 Standard_Integer aLower = anIndices.Lower();
465 Standard_Integer anUpper = anIndices.Upper();
467 Standard_Integer aPrevNode = -1;
468 for (Standard_Integer i = aLower; i <= anUpper; ++i)
470 Standard_Integer aNodeIdx = anIndices.Value(i);
473 BRepMesh_Edge aLink(aPrevNode, aNodeIdx, BRepMesh_Frontier);
474 aBoundaryEdgeMap.Add(aLink);
476 aPrevNode = aNodeIdx;
480 if (aBoundaryEdgeMap.Size() == 0)
485 const Poly_Array1OfTriangle& aTris = aT->Triangles();
486 NCollection_Map<BRepMesh_Edge> aFreeEdgeMap;
487 Standard_Integer aTriNum = aTris.Length();
488 for ( Standard_Integer aTriIndx = 1; aTriIndx <= aTriNum; aTriIndx++ )
490 const Poly_Triangle& aTri = aTris(aTriIndx);
491 Standard_Integer aTriNodes[3] = { aTri.Value(1), aTri.Value(2), aTri.Value(3)};
493 for (Standard_Integer i = 1; i <= 3; ++i)
495 Standard_Integer aLastId = aTriNodes[i % 3];
496 Standard_Integer aFirstId = aTriNodes[i - 1];
498 BRepMesh_Edge aLink(aFirstId, aLastId, BRepMesh_Free);
499 if (!aBoundaryEdgeMap.Contains(aLink))
501 if (!aFreeEdgeMap.Add(aLink))
503 aFreeEdgeMap.Remove(aLink);
509 if (aFreeEdgeMap.Size() != 0)
511 di << "Not connected mesh inside face " << aFaceId << "\n";
517 //=======================================================================
518 //function : mpparallel
520 //=======================================================================
521 static int mpparallel (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
525 Standard_Boolean isParallelOn = Draw::Atoi (argv[1]) == 1;
526 BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn);
528 std::cout << "Incremental Mesh, multi-threading "
529 << (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n");