0022735: Data races in BRepMesh working in parallel mode
[occt.git] / src / MeshTest / MeshTest_PluginCommands.cxx
1 // File:        MeshTest_PluginCommands.cxx
2 // Created:     Fri Apr 11 15:41:24 2008
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6 #include <MeshTest.ixx>
7 #include <Draw_Interpretor.hxx>
8 #include <TColStd_MapOfAsciiString.hxx>
9 #include <BRepMesh_DiscretFactory.hxx>
10 #include <TCollection_AsciiString.hxx>
11 #include <TColStd_MapIteratorOfMapOfAsciiString.hxx>
12 #include <BRepMesh_FactoryError.hxx>
13 #include <BRepMesh_DiscretRoot.hxx>
14 #include <BRepMesh_IncrementalMesh.hxx>
15 #include <Bnd_Box.hxx>
16 #include <BRepMesh_PDiscretRoot.hxx>
17 #include <DBRep.hxx>
18 #include <TopTools_IndexedMapOfShape.hxx>
19 #include <TopExp.hxx>
20 #include <Poly_Triangulation.hxx>
21 #include <gp_Vec.hxx>
22 #include <GProp_GProps.hxx>
23 #include <BRepGProp.hxx>
24 #include <DrawTrSurf.hxx>
25 #include <BRep_Tool.hxx>
26 #include <TopoDS.hxx>
27 #include <MeshTest_CheckTopology.hxx>
28 #include <TColgp_Array1OfPnt2d.hxx>
29 #include <Poly_Polygon3D.hxx>
30 #include <Poly_Polygon2D.hxx>
31 #include <Standard.hxx>
32
33 static Standard_Integer mpnames           (Draw_Interpretor& , Standard_Integer , const char** );
34 static Standard_Integer mpsetdefaultname  (Draw_Interpretor& , Standard_Integer , const char** );
35 static Standard_Integer mpgetdefaultname  (Draw_Interpretor& , Standard_Integer , const char** );
36 static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer , const char** );
37 static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer , const char** );
38 static Standard_Integer mperror           (Draw_Interpretor& , Standard_Integer , const char** );
39 static Standard_Integer mpincmesh         (Draw_Interpretor& , Standard_Integer , const char** );
40 static Standard_Integer mpparallel        (Draw_Interpretor& , Standard_Integer , const char** );
41 static Standard_Integer triarea           (Draw_Interpretor& , Standard_Integer , const char** );
42 static Standard_Integer tricheck          (Draw_Interpretor& , Standard_Integer , const char** );
43
44 //=======================================================================
45 //function : PluginCommands
46 //purpose  : 
47 //=======================================================================
48 void MeshTest::PluginCommands(Draw_Interpretor& theCommands)
49 {
50   static Standard_Boolean done = Standard_False;
51   if (done) {
52     return;
53   }
54   done = Standard_True;
55   //
56   const char* g = "Mesh Commands";
57   // Commands
58   theCommands.Add("mpnames"          , "use mpnames"          , __FILE__, mpnames    , g);
59   theCommands.Add("mpsetdefaultname" , "use mpsetdefaultname" , __FILE__, mpsetdefaultname     , g);
60   theCommands.Add("mpgetdefaultname" , "use mpgetdefaultname" , __FILE__, mpgetdefaultname     , g);
61   theCommands.Add("mpsetfunctionname", "use mpsetfunctionname", __FILE__, mpsetfunctionname     , g);
62   theCommands.Add("mpgetfunctionname", "use mpgetfunctionname", __FILE__, mpgetfunctionname     , g);
63   theCommands.Add("mperror"          , "use mperror"          , __FILE__, mperror     , g);
64   theCommands.Add("mpincmesh"        , "use mpincmesh"        , __FILE__, mpincmesh      , g);
65   theCommands.Add("mpparallel"       , "mpparallel [toTurnOn] : show / set multi-threading flag for incremental mesh",
66     __FILE__, mpparallel, g);
67   theCommands.Add("triarea","shape [eps]  (computes triangles and surface area)",__FILE__, triarea, g);
68   theCommands.Add("tricheck", "shape   (checks triangulation of shape)", __FILE__, tricheck, g);
69   
70 }
71
72 //=======================================================================
73 //function : mpnames
74 //purpose  : 
75 //=======================================================================
76 static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer n, const char** )
77 {
78   Standard_Integer aNb;
79   TColStd_MapIteratorOfMapOfAsciiString aIt;
80   //
81   if (n!=1) {
82     printf(" use mpnames\n");
83     return 0;
84   }
85   //
86   const TColStd_MapOfAsciiString& aMN=BRepMesh_DiscretFactory::Get().Names();
87   aNb=aMN.Extent();
88   if (!aNb) {
89     printf(" *no names found\n");
90     return 0;
91   }
92   //
93   printf(" *available names:\n");
94   aIt.Initialize(aMN);
95   for (; aIt.More(); aIt.Next()) {
96     const TCollection_AsciiString& aName=aIt.Key();
97     printf("  %s\n", aName.ToCString());
98   }
99   //
100   return 0;
101 }
102 //=======================================================================
103 //function : mpsetdefaultname
104 //purpose  : 
105 //=======================================================================
106 static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer n, const char**a )
107 {
108   TCollection_AsciiString aName;
109   //
110   if (n!=2) {
111     printf(" use mpsetdefaultname name\n");
112     return 0;
113   }
114   //
115   aName=a[1];
116   //
117   if (BRepMesh_DiscretFactory::Get().SetDefaultName (aName))
118     printf(" *ready\n");
119   else
120     printf(" *fault\n");
121   //
122   return 0;
123 }
124 //=======================================================================
125 //function : mpgetdefaultname
126 //purpose  : 
127 //=======================================================================
128 static Standard_Integer mpgetdefaultname (Draw_Interpretor& , Standard_Integer n, const char** )
129 {
130   if (n!=1) {
131     printf(" use mpgetdefaultname\n");
132     return 0;
133   }
134   //
135   const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().DefaultName();
136   printf(" *default name: %s\n", aName.ToCString());
137   //
138   return 0;
139 }
140 //=======================================================================
141 //function : mpsetfunctionname
142 //purpose  : 
143 //=======================================================================
144 static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer n, const char**a )
145 {
146   TCollection_AsciiString aName;
147   //
148   if (n!=2) {
149     printf(" use mpsetfunctionname name\n");
150     return 0;
151   }
152   //
153   aName=a[1];
154   //
155   if (BRepMesh_DiscretFactory::Get().SetFunctionName (aName))
156     printf(" *ready\n");
157   else
158     printf(" *fault\n");
159   //
160   return 0;
161 }
162 //=======================================================================
163 //function : mpgetdefaultname
164 //purpose  : 
165 //=======================================================================
166 static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer n, const char** )
167 {
168   if (n!=1) {
169     printf(" use mpgetfunctionname\n");
170     return 0;
171   }
172   //
173   const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().FunctionName();
174   printf(" *function name: %s\n", aName.ToCString());
175   //
176   return 0;
177 }
178 //=======================================================================
179 //function : mperror
180 //purpose  : 
181 //=======================================================================
182 static Standard_Integer mperror (Draw_Interpretor& , Standard_Integer n, const char** )
183 {
184   BRepMesh_FactoryError aErr;
185   //
186   if (n!=1) {
187     printf(" use mperror\n");
188     return 0;
189   }
190   //
191   aErr=BRepMesh_DiscretFactory::Get().ErrorStatus();
192   printf(" *ErrorStatus: %d\n", (int)aErr);
193   //
194   return 0;
195 }
196
197 //=======================================================================
198 //function :mpincmesh
199 //purpose  : 
200 //=======================================================================
201 static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer n, const char** a)
202 {
203   Standard_Real aDeflection, aAngle;
204   TopoDS_Shape aS;
205   //
206   if (n<3) {
207     printf(" use mpincmesh s deflection [angle]\n");
208     return 0;
209   }
210   //
211   aS=DBRep::Get(a[1]);
212   if (aS.IsNull()) {
213     printf(" null shapes is not allowed here\n");
214     return 0;
215   }
216   //
217   aDeflection=atof(a[2]);
218   aAngle=0.5;
219   if (n>3) {
220     aAngle=atof(a[3]);
221   }
222   //
223   Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aS,
224                                                                                    aDeflection,
225                                                                                    aAngle);
226   //
227   BRepMesh_FactoryError aErr = BRepMesh_DiscretFactory::Get().ErrorStatus();
228   if (aErr != BRepMesh_FE_NOERROR)
229   {
230     printf(" *Factory::Get().ErrorStatus()=%d\n", (int)aErr);
231   }
232   //
233   if (aMeshAlgo.IsNull())
234   {
235     printf(" *Can not create the algo\n");
236     return 0;
237   }
238   //
239   aMeshAlgo->Perform();
240   if (!aMeshAlgo->IsDone())
241   {
242     printf(" *Not done\n");
243   }
244   //
245   return 0;
246 }
247
248 //#######################################################################
249 static Standard_Integer triarea (Draw_Interpretor& di, int n, const char ** a)
250 {
251
252   if (n < 2) return 1;
253
254   TopoDS_Shape shape = DBRep::Get(a[1]);
255   if (shape.IsNull()) return 1;
256   Standard_Real anEps = -1.;
257   if (n > 2)
258     anEps = atof(a[2]);
259
260   TopTools_IndexedMapOfShape aMapF;
261   TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
262
263   // detect if a shape has triangulation
264   Standard_Boolean hasPoly = Standard_False;
265   int i;
266   for (i=1; i <= aMapF.Extent(); i++) {
267     const TopoDS_Face& aFace = TopoDS::Face(aMapF(i));
268     TopLoc_Location aLoc;
269     Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
270     if (!aPoly.IsNull()) {
271       hasPoly = Standard_True;
272       break;
273     }
274   }
275
276   // compute area by triangles
277   double aTriArea=0;
278   if (hasPoly) {
279     for (i=1; i <= aMapF.Extent(); i++) {
280       const TopoDS_Face& aFace = TopoDS::Face(aMapF(i));
281       TopLoc_Location aLoc;
282       Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
283       if (aPoly.IsNull()) {
284         cout << "face "<<i<<" has no triangulation"<<endl;
285         continue;
286       }
287       const Poly_Array1OfTriangle& triangles = aPoly->Triangles();
288       const TColgp_Array1OfPnt& nodes = aPoly->Nodes();
289       for (int j=triangles.Lower(); j <= triangles.Upper(); j++) {
290         const Poly_Triangle& tri = triangles(j);
291         int n1, n2, n3;
292         tri.Get (n1, n2, n3);
293         const gp_Pnt& p1 = nodes(n1);
294         const gp_Pnt& p2 = nodes(n2);
295         const gp_Pnt& p3 = nodes(n3);
296         gp_Vec v1(p1, p2);
297         gp_Vec v2(p1, p3);
298         double ar = v1.CrossMagnitude(v2);
299         aTriArea += ar;
300       }
301     }
302     aTriArea /= 2;
303   }
304
305   // compute area by geometry
306   GProp_GProps props;
307   if (anEps <= 0.)
308     BRepGProp::SurfaceProperties(shape, props);
309   else
310     BRepGProp::SurfaceProperties(shape, props, anEps);
311   double aGeomArea = props.Mass();
312
313   di << aTriArea << " " << aGeomArea << "\n";
314   return 0;
315 }
316
317 //#######################################################################
318 static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
319 {
320   if (n < 2) return 1;
321
322   TopoDS_Shape shape = DBRep::Get(a[1]);
323   if (shape.IsNull()) return 1;
324
325   TopTools_IndexedMapOfShape aMapF;
326   TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
327   Standard_CString name = ".";
328
329   // execute check
330   MeshTest_CheckTopology aCheck(shape);
331   aCheck.Perform(di);
332
333   // dump info on free links inside the triangulation
334   Standard_Integer nbFree = 0;
335   Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k;
336   if (nbFac > 0) {
337     for (k=1; k <= nbFac; k++) {
338       Standard_Integer nbEdge = aCheck.NbFreeLinks(k);
339       Standard_Integer iF = aCheck.GetFaceNumWithFL(k);
340       nbFree += nbEdge;
341       di << "free links of face " << iF << "\n";
342       const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(iF));
343       TopLoc_Location aLoc;
344       Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
345       const TColgp_Array1OfPnt& aPoints = aT->Nodes();
346       const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
347       const gp_Trsf& trsf = aLoc.Transformation();
348       TColgp_Array1OfPnt pnts(1,2);
349       TColgp_Array1OfPnt2d pnts2d(1,2);
350       for (i=1; i <= nbEdge; i++) {
351         Standard_Integer n1, n2;
352         aCheck.GetFreeLink(k, i, n1, n2);
353         di << "{" << n1 << " " << n2 << "} ";
354         pnts(1) = aPoints(n1).Transformed(trsf);
355         pnts(2) = aPoints(n2).Transformed(trsf);
356         Handle(Poly_Polygon3D) poly = new Poly_Polygon3D (pnts);
357         DrawTrSurf::Set (name, poly);
358         DrawTrSurf::Set (name, pnts(1));
359         DrawTrSurf::Set (name, pnts(2));
360         pnts2d(1) = aPoints2d(n1);
361         pnts2d(2) = aPoints2d(n2);
362         Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
363         DrawTrSurf::Set (name, poly2d);
364         DrawTrSurf::Set (name, pnts2d(1));
365         DrawTrSurf::Set (name, pnts2d(2));
366       }
367       di << "\n";
368     }
369   }
370
371   // dump info on cross face errors
372   Standard_Integer nbErr = aCheck.NbCrossFaceErrors();
373   if (nbErr > 0) {
374     di << "cross face errors: {face1, node1, face2, node2, distance}" << "\n";
375     for (i=1; i <= nbErr; i++) {
376       Standard_Integer iF1, n1, iF2, n2;
377       Standard_Real aVal;
378       aCheck.GetCrossFaceError(i, iF1, n1, iF2, n2, aVal);
379       di << "{" << iF1 << " " << n1 << " " << iF2 << " " << n2 << " " << aVal << "} ";
380     }
381     di << "\n";
382   }
383
384   // dump info on edges
385   Standard_Integer nbAsync = aCheck.NbAsyncEdges();
386   if (nbAsync > 0) {
387     di << "async edges:" << "\n";
388     for (i=1; i <= nbAsync; i++) {
389       Standard_Integer ie = aCheck.GetAsyncEdgeNum(i);
390       di << ie << " ";
391     }
392     di << "\n";
393   }
394
395   // dump info on free nodes
396   Standard_Integer nbFreeNodes = aCheck.NbFreeNodes();
397   if (nbFreeNodes > 0) {
398     di << "free nodes (in pairs: face / node): " << "\n";
399     for (i=1; i <= nbFreeNodes; i++) {
400       Standard_Integer iface, inode;
401       aCheck.GetFreeNodeNum(i, iface, inode);
402       di << "{" << iface << " " << inode << "} ";
403     }
404     di << "\n";
405   }
406
407   // output errors summary to DRAW
408   if ( nbFree > 0 || nbErr > 0 || nbAsync > 0 || nbFreeNodes > 0 )
409     di << "Free_links " << nbFree
410        << " Cross_face_errors " << nbErr
411        << " Async_edges " << nbAsync 
412        << " Free_nodes " << nbFreeNodes << "\n";
413   return 0;
414 }
415
416 //=======================================================================
417 //function : mpparallel
418 //purpose  :
419 //=======================================================================
420 static int mpparallel (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
421 {
422   if (argc == 2)
423   {
424     Standard_Boolean isParallelOn = atoi (argv[1]) == 1;
425     BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn);
426     if (isParallelOn)
427       Standard::SetReentrant(Standard_True);
428   }
429   std::cout << "Incremental Mesh, multi-threading "
430             << (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n");
431   return 0;
432 }