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