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