0024428: Implementation of LGPL license
[occt.git] / src / MeshTest / MeshTest_PluginCommands.cxx
1 // Created on: 2008-04-11
2 // Created by: Peter KURNEV
3 // Copyright (c) 2008-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
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>
27 #include <Draw.hxx>
28 #include <DBRep.hxx>
29 #include <TopTools_IndexedMapOfShape.hxx>
30 #include <TopExp.hxx>
31 #include <Poly_Triangulation.hxx>
32 #include <gp_Vec.hxx>
33 #include <GProp_GProps.hxx>
34 #include <BRepGProp.hxx>
35 #include <DrawTrSurf.hxx>
36 #include <BRep_Tool.hxx>
37 #include <TopoDS.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>
49
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** );
60
61 //=======================================================================
62 //function : PluginCommands
63 //purpose  : 
64 //=======================================================================
65 void MeshTest::PluginCommands(Draw_Interpretor& theCommands)
66 {
67   static Standard_Boolean done = Standard_False;
68   if (done) {
69     return;
70   }
71   done = Standard_True;
72   //
73   const char* g = "Mesh Commands";
74   // 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);
86   
87 }
88
89 //=======================================================================
90 //function : mpnames
91 //purpose  : 
92 //=======================================================================
93 static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer n, const char** )
94 {
95   Standard_Integer aNb;
96   TColStd_MapIteratorOfMapOfAsciiString aIt;
97   //
98   if (n!=1) {
99     printf(" use mpnames\n");
100     return 0;
101   }
102   //
103   const TColStd_MapOfAsciiString& aMN=BRepMesh_DiscretFactory::Get().Names();
104   aNb=aMN.Extent();
105   if (!aNb) {
106     printf(" *no names found\n");
107     return 0;
108   }
109   //
110   printf(" *available names:\n");
111   aIt.Initialize(aMN);
112   for (; aIt.More(); aIt.Next()) {
113     const TCollection_AsciiString& aName=aIt.Key();
114     printf("  %s\n", aName.ToCString());
115   }
116   //
117   return 0;
118 }
119 //=======================================================================
120 //function : mpsetdefaultname
121 //purpose  : 
122 //=======================================================================
123 static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer n, const char**a )
124 {
125   TCollection_AsciiString aName;
126   //
127   if (n!=2) {
128     printf(" use mpsetdefaultname name\n");
129     return 0;
130   }
131   //
132   aName=a[1];
133   //
134   if (BRepMesh_DiscretFactory::Get().SetDefaultName (aName))
135     printf(" *ready\n");
136   else
137     printf(" *fault\n");
138   //
139   return 0;
140 }
141 //=======================================================================
142 //function : mpgetdefaultname
143 //purpose  : 
144 //=======================================================================
145 static Standard_Integer mpgetdefaultname (Draw_Interpretor& , Standard_Integer n, const char** )
146 {
147   if (n!=1) {
148     printf(" use mpgetdefaultname\n");
149     return 0;
150   }
151   //
152   const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().DefaultName();
153   printf(" *default name: %s\n", aName.ToCString());
154   //
155   return 0;
156 }
157 //=======================================================================
158 //function : mpsetfunctionname
159 //purpose  : 
160 //=======================================================================
161 static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer n, const char**a )
162 {
163   TCollection_AsciiString aName;
164   //
165   if (n!=2) {
166     printf(" use mpsetfunctionname name\n");
167     return 0;
168   }
169   //
170   aName=a[1];
171   //
172   if (BRepMesh_DiscretFactory::Get().SetFunctionName (aName))
173     printf(" *ready\n");
174   else
175     printf(" *fault\n");
176   //
177   return 0;
178 }
179 //=======================================================================
180 //function : mpgetdefaultname
181 //purpose  : 
182 //=======================================================================
183 static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer n, const char** )
184 {
185   if (n!=1) {
186     printf(" use mpgetfunctionname\n");
187     return 0;
188   }
189   //
190   const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().FunctionName();
191   printf(" *function name: %s\n", aName.ToCString());
192   //
193   return 0;
194 }
195 //=======================================================================
196 //function : mperror
197 //purpose  : 
198 //=======================================================================
199 static Standard_Integer mperror (Draw_Interpretor& , Standard_Integer n, const char** )
200 {
201   BRepMesh_FactoryError aErr;
202   //
203   if (n!=1) {
204     printf(" use mperror\n");
205     return 0;
206   }
207   //
208   aErr=BRepMesh_DiscretFactory::Get().ErrorStatus();
209   printf(" *ErrorStatus: %d\n", (int)aErr);
210   //
211   return 0;
212 }
213
214 //=======================================================================
215 //function :mpincmesh
216 //purpose  : 
217 //=======================================================================
218 static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer n, const char** a)
219 {
220   Standard_Real aDeflection, aAngle;
221   TopoDS_Shape aS;
222   //
223   if (n<3) {
224     printf(" use mpincmesh s deflection [angle]\n");
225     return 0;
226   }
227   //
228   aS=DBRep::Get(a[1]);
229   if (aS.IsNull()) {
230     printf(" null shapes is not allowed here\n");
231     return 0;
232   }
233   //
234   aDeflection=Draw::Atof(a[2]);
235   aAngle=0.5;
236   if (n>3) {
237     aAngle=Draw::Atof(a[3]);
238   }
239   //
240   Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aS,
241                                                                                    aDeflection,
242                                                                                    aAngle);
243   //
244   BRepMesh_FactoryError aErr = BRepMesh_DiscretFactory::Get().ErrorStatus();
245   if (aErr != BRepMesh_FE_NOERROR)
246   {
247     printf(" *Factory::Get().ErrorStatus()=%d\n", (int)aErr);
248   }
249   //
250   if (aMeshAlgo.IsNull())
251   {
252     printf(" *Can not create the algo\n");
253     return 0;
254   }
255   //
256   aMeshAlgo->Perform();
257   if (!aMeshAlgo->IsDone())
258   {
259     printf(" *Not done\n");
260   }
261   //
262   return 0;
263 }
264
265 //#######################################################################
266 static Standard_Integer triarea (Draw_Interpretor& di, int n, const char ** a)
267 {
268
269   if (n < 2) return 1;
270
271   TopoDS_Shape shape = DBRep::Get(a[1]);
272   if (shape.IsNull()) return 1;
273   Standard_Real anEps = -1.;
274   if (n > 2)
275     anEps = Draw::Atof(a[2]);
276
277   TopTools_IndexedMapOfShape aMapF;
278   TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
279
280   // detect if a shape has triangulation
281   Standard_Boolean hasPoly = Standard_False;
282   int i;
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;
289       break;
290     }
291   }
292
293   // compute area by triangles
294   double aTriArea=0;
295   if (hasPoly) {
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;
302         continue;
303       }
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);
308         int n1, n2, n3;
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);
313         gp_Vec v1(p1, p2);
314         gp_Vec v2(p1, p3);
315         double ar = v1.CrossMagnitude(v2);
316         aTriArea += ar;
317       }
318     }
319     aTriArea /= 2;
320   }
321
322   // compute area by geometry
323   GProp_GProps props;
324   if (anEps <= 0.)
325     BRepGProp::SurfaceProperties(shape, props);
326   else
327     BRepGProp::SurfaceProperties(shape, props, anEps);
328   double aGeomArea = props.Mass();
329
330   di << aTriArea << " " << aGeomArea << "\n";
331   return 0;
332 }
333
334 //#######################################################################
335 Standard_Boolean IsEqual(const BRepMesh_Edge& theFirst, const BRepMesh_Edge& theSecond) 
336 {
337   return theFirst.IsEqual(theSecond);
338 }
339
340 static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
341 {
342   if (n < 2) return 1;
343
344   TopoDS_Shape shape = DBRep::Get(a[1]);
345   if (shape.IsNull()) return 1;
346
347   TopTools_IndexedMapOfShape aMapF;
348   TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
349   Standard_CString name = ".";
350
351   // execute check
352   MeshTest_CheckTopology aCheck(shape);
353   aCheck.Perform(di);
354
355   // dump info on free links inside the triangulation
356   Standard_Integer nbFree = 0;
357   Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k;
358   if (nbFac > 0) {
359     for (k=1; k <= nbFac; k++) {
360       Standard_Integer nbEdge = aCheck.NbFreeLinks(k);
361       Standard_Integer iF = aCheck.GetFaceNumWithFL(k);
362       nbFree += nbEdge;
363       di << "free links of face " << iF << "\n";
364
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();
372
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));
391       }
392       di << "\n";
393     }
394   }
395
396   // dump info on cross face errors
397   Standard_Integer nbErr = aCheck.NbCrossFaceErrors();
398   if (nbErr > 0) {
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;
402       Standard_Real aVal;
403       aCheck.GetCrossFaceError(i, iF1, n1, iF2, n2, aVal);
404       di << "{" << iF1 << " " << n1 << " " << iF2 << " " << n2 << " " << aVal << "} ";
405     }
406     di << "\n";
407   }
408
409   // dump info on edges
410   Standard_Integer nbAsync = aCheck.NbAsyncEdges();
411   if (nbAsync > 0) {
412     di << "async edges:" << "\n";
413     for (i=1; i <= nbAsync; i++) {
414       Standard_Integer ie = aCheck.GetAsyncEdgeNum(i);
415       di << ie << " ";
416     }
417     di << "\n";
418   }
419
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 << "} ";
428     }
429     di << "\n";
430   }
431
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";
438
439
440   Standard_Integer aFaceId = 1;
441   TopExp_Explorer aFaceExp(shape, TopAbs_FACE);
442   for ( ; aFaceExp.More(); aFaceExp.Next(), ++aFaceId)
443   {
444     const TopoDS_Shape& aShape = aFaceExp.Current();
445     const TopoDS_Face& aFace = TopoDS::Face(aShape);
446
447     TopLoc_Location aLoc;
448     Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
449
450     // Iterate boundary edges
451     NCollection_Map<BRepMesh_Edge> aBoundaryEdgeMap;
452     TopExp_Explorer anExp(aShape, TopAbs_EDGE);
453     for ( ; anExp.More(); anExp.Next() )
454     {
455       TopLoc_Location anEdgeLoc;
456       const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
457       Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLoc);
458       if (aPoly.IsNull())
459       {
460         continue;
461       }
462
463       const TColStd_Array1OfInteger& anIndices = aPoly->Nodes();
464       Standard_Integer aLower  = anIndices.Lower(); 
465       Standard_Integer anUpper = anIndices.Upper();
466
467       Standard_Integer aPrevNode = -1;
468       for (Standard_Integer i = aLower; i <= anUpper; ++i)
469       {
470         Standard_Integer aNodeIdx = anIndices.Value(i);
471         if (i != aLower)
472         {
473           BRepMesh_Edge aLink(aPrevNode, aNodeIdx, BRepMesh_Frontier);
474           aBoundaryEdgeMap.Add(aLink);
475         }
476         aPrevNode = aNodeIdx;
477       }
478     }
479
480     if (aBoundaryEdgeMap.Size() == 0)
481     {
482       break;
483     }
484
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++ )
489     {
490       const Poly_Triangle& aTri = aTris(aTriIndx);
491       Standard_Integer aTriNodes[3] = { aTri.Value(1), aTri.Value(2), aTri.Value(3)};
492
493       for (Standard_Integer i = 1; i <= 3; ++i)
494       {
495         Standard_Integer aLastId  = aTriNodes[i % 3];
496         Standard_Integer aFirstId = aTriNodes[i - 1];
497
498         BRepMesh_Edge aLink(aFirstId, aLastId, BRepMesh_Free);
499         if (!aBoundaryEdgeMap.Contains(aLink))
500         {
501           if (!aFreeEdgeMap.Add(aLink))
502           {
503             aFreeEdgeMap.Remove(aLink);
504           }
505         }
506       }
507     }
508
509     if (aFreeEdgeMap.Size() != 0)
510     {
511       di << "Not connected mesh inside face " << aFaceId << "\n";
512     }
513   }
514   return 0;
515 }
516
517 //=======================================================================
518 //function : mpparallel
519 //purpose  :
520 //=======================================================================
521 static int mpparallel (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
522 {
523   if (argc == 2)
524   {
525     Standard_Boolean isParallelOn = Draw::Atoi (argv[1]) == 1;
526     BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn);
527   }
528   std::cout << "Incremental Mesh, multi-threading "
529             << (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n");
530   return 0;
531 }