]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
Salome HOME
PAL12608: Add possibility to check geometry of a shape.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 #include <Standard_Stream.hxx>
21
22 #include <GEOMImpl_IMeasureOperations.hxx>
23
24 #include <GEOMImpl_Types.hxx>
25 #include <GEOMImpl_MeasureDriver.hxx>
26 #include <GEOMImpl_IMeasure.hxx>
27
28 #include <GEOM_Function.hxx>
29 #include <GEOM_PythonDump.hxx>
30
31 #include "utilities.h"
32 #include <OpUtil.hxx>
33 #include <Utils_ExceptHandlers.hxx>
34
35 #include <TFunction_DriverTable.hxx>
36 #include <TFunction_Driver.hxx>
37 #include <TFunction_Logbook.hxx>
38 #include <TDF_Tool.hxx>
39
40 #include <BRep_Tool.hxx>
41 #include <BRepCheck.hxx>
42 #include <BRepCheck_Result.hxx>
43 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
44 #include <BRepGProp.hxx>
45 #include <BRepBndLib.hxx>
46 #include <BRepExtrema_DistShapeShape.hxx>
47
48 #include <Bnd_Box.hxx>
49
50 #include <GProp_GProps.hxx>
51 #include <GProp_PrincipalProps.hxx>
52
53 #include <TopAbs.hxx>
54 #include <TopoDS.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopoDS_Face.hxx>
57 #include <TopoDS_Shape.hxx>
58 #include <TopoDS_Vertex.hxx>
59 #include <TopoDS_Iterator.hxx>
60 #include <TopExp_Explorer.hxx>
61 #include <TopTools_MapOfShape.hxx>
62 #include <TopTools_ListOfShape.hxx>
63 #include <TopTools_ListIteratorOfListOfShape.hxx>
64
65 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
66
67 //=============================================================================
68 /*!
69  *   constructor:
70  */
71 //=============================================================================
72 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID)
73 : GEOM_IOperations(theEngine, theDocID)
74 {
75   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
76 }
77
78 //=============================================================================
79 /*!
80  *  destructor
81  */
82 //=============================================================================
83 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
84 {
85   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
86 }
87
88
89 //=============================================================================
90 /*!
91  *  GetCentreOfMass
92  */
93 //=============================================================================
94 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
95                                                 (Handle(GEOM_Object) theShape)
96 {
97   SetErrorCode(KO);
98
99   if (theShape.IsNull()) return NULL;
100
101   //Add a new CentreOfMass object
102   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG);
103
104   //Add a new CentreOfMass function
105   Handle(GEOM_Function) aFunction =
106     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
107   if (aFunction.IsNull()) return NULL;
108
109   //Check if the function is set correctly
110   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
111
112   GEOMImpl_IMeasure aCI (aFunction);
113
114   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
115   if (aRefShape.IsNull()) return NULL;
116
117   aCI.SetBase(aRefShape);
118
119   //Compute the CentreOfMass value
120   try {
121     if (!GetSolver()->ComputeFunction(aFunction)) {
122       SetErrorCode("Measure driver failed to compute centre of mass");
123       return NULL;
124     }
125   }
126   catch (Standard_Failure) {
127     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
128     SetErrorCode(aFail->GetMessageString());
129     return NULL;
130   }
131
132   //Make a Python command
133   GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
134
135   SetErrorCode(OK);
136   return aCDG;
137 }
138
139 //=============================================================================
140 /*!
141  *  GetBasicProperties
142  */
143 //=============================================================================
144 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
145                                                       Standard_Real& theLength,
146                                                       Standard_Real& theSurfArea,
147                                                       Standard_Real& theVolume)
148 {
149   SetErrorCode(KO);
150
151   if (theShape.IsNull()) return;
152
153   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
154   if (aRefShape.IsNull()) return;
155
156   TopoDS_Shape aShape = aRefShape->GetValue();
157   if (aShape.IsNull()) {
158     SetErrorCode("The Objects has NULL Shape");
159     return;
160   }
161
162   //Compute the parameters
163   GProp_GProps LProps, SProps;
164   try {
165     BRepGProp::LinearProperties(aShape, LProps);
166     theLength = LProps.Mass();
167
168     BRepGProp::SurfaceProperties(aShape, SProps);
169     theSurfArea = SProps.Mass();
170
171     theVolume = 0.0;
172     if (aShape.ShapeType() < TopAbs_SHELL) {
173       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
174         GProp_GProps VProps;
175         BRepGProp::VolumeProperties(Exp.Current(), VProps);
176         theVolume += VProps.Mass();
177       }
178     }
179   }
180   catch (Standard_Failure) {
181     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
182     SetErrorCode(aFail->GetMessageString());
183     return;
184   }
185
186   SetErrorCode(OK);
187 }
188
189 //=============================================================================
190 /*!
191  *  GetInertia
192  */
193 //=============================================================================
194 void GEOMImpl_IMeasureOperations::GetInertia
195                    (Handle(GEOM_Object) theShape,
196                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
197                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
198                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
199                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
200 {
201   SetErrorCode(KO);
202
203   if (theShape.IsNull()) return;
204
205   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
206   if (aRefShape.IsNull()) return;
207
208   TopoDS_Shape aShape = aRefShape->GetValue();
209   if (aShape.IsNull()) {
210     SetErrorCode("The Objects has NULL Shape");
211     return;
212   }
213
214   //Compute the parameters
215   GProp_GProps System;
216
217   try {
218     if (aShape.ShapeType() == TopAbs_VERTEX ||
219         aShape.ShapeType() == TopAbs_EDGE ||
220         aShape.ShapeType() == TopAbs_WIRE) {
221       BRepGProp::LinearProperties(aShape, System);
222     } else if (aShape.ShapeType() == TopAbs_FACE ||
223                aShape.ShapeType() == TopAbs_SHELL) {
224       BRepGProp::SurfaceProperties(aShape, System);
225     } else {
226       BRepGProp::VolumeProperties(aShape, System);
227     }
228     gp_Mat I = System.MatrixOfInertia();
229
230     I11 = I(1,1);
231     I12 = I(1,2);
232     I13 = I(1,3);
233
234     I21 = I(2,1);
235     I22 = I(2,2);
236     I23 = I(2,3);
237
238     I31 = I(3,1);
239     I32 = I(3,2);
240     I33 = I(3,3);
241
242     GProp_PrincipalProps Pr = System.PrincipalProperties();
243     Pr.Moments(Ix,Iy,Iz);
244   }
245   catch (Standard_Failure) {
246     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
247     SetErrorCode(aFail->GetMessageString());
248     return;
249   }
250
251   SetErrorCode(OK);
252 }
253
254 //=============================================================================
255 /*!
256  *  GetBoundingBox
257  */
258 //=============================================================================
259 void GEOMImpl_IMeasureOperations::GetBoundingBox
260                                      (Handle(GEOM_Object) theShape,
261                                       Standard_Real& Xmin, Standard_Real& Xmax,
262                                       Standard_Real& Ymin, Standard_Real& Ymax,
263                                       Standard_Real& Zmin, Standard_Real& Zmax)
264 {
265   SetErrorCode(KO);
266
267   if (theShape.IsNull()) return;
268
269   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
270   if (aRefShape.IsNull()) return;
271
272   TopoDS_Shape aShape = aRefShape->GetValue();
273   if (aShape.IsNull()) {
274     SetErrorCode("The Objects has NULL Shape");
275     return;
276   }
277
278   //Compute the parameters
279   Bnd_Box B;
280
281   try {
282     BRepBndLib::Add(aShape, B);
283     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
284   }
285   catch (Standard_Failure) {
286     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
287     SetErrorCode(aFail->GetMessageString());
288     return;
289   }
290
291   SetErrorCode(OK);
292 }
293
294 //=============================================================================
295 /*!
296  *  GetTolerance
297  */
298 //=============================================================================
299 void GEOMImpl_IMeasureOperations::GetTolerance
300                                (Handle(GEOM_Object) theShape,
301                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
302                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
303                                 Standard_Real& VertMin, Standard_Real& VertMax)
304 {
305   SetErrorCode(KO);
306
307   if (theShape.IsNull()) return;
308
309   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
310   if (aRefShape.IsNull()) return;
311
312   TopoDS_Shape aShape = aRefShape->GetValue();
313   if (aShape.IsNull()) {
314     SetErrorCode("The Objects has NULL Shape");
315     return;
316   }
317
318   //Compute the parameters
319   Standard_Real T;
320   FaceMin = EdgeMin = VertMin = RealLast();
321   FaceMax = EdgeMax = VertMax = -RealLast();
322
323   try {
324     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
325       TopoDS_Face Face = TopoDS::Face(ExF.Current());
326       T = BRep_Tool::Tolerance(Face);
327       if (T > FaceMax)
328         FaceMax = T;
329       if (T < FaceMin)
330         FaceMin = T;
331     }
332     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
333       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
334       T = BRep_Tool::Tolerance(Edge);
335       if (T > EdgeMax)
336         EdgeMax = T;
337       if (T < EdgeMin)
338         EdgeMin = T;
339     }
340     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
341       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
342       T = BRep_Tool::Tolerance(Vertex);
343       if (T > VertMax)
344         VertMax = T;
345       if (T < VertMin)
346         VertMin = T;
347     }
348   }
349   catch (Standard_Failure) {
350     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
351     SetErrorCode(aFail->GetMessageString());
352     return;
353   }
354
355   SetErrorCode(OK);
356 }
357
358 //=============================================================================
359 /*!
360  *  CheckShape
361  */
362 //=============================================================================
363 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)      theShape,
364                                               const Standard_Boolean   theIsCheckGeom,
365                                               TCollection_AsciiString& theDump)
366 {
367   SetErrorCode(KO);
368
369   if (theShape.IsNull()) return false;
370
371   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
372   if (aRefShape.IsNull()) return false;
373
374   TopoDS_Shape aShape = aRefShape->GetValue();
375   if (aShape.IsNull()) {
376     SetErrorCode("The Objects has NULL Shape");
377     return false;
378   }
379
380   //Compute the parameters
381   bool isValid = false;
382   try {
383     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
384     if (ana.IsValid()) {
385       theDump.Clear();
386       isValid = true;
387     } else {
388       StructuralDump(ana, aShape, theDump);
389     }
390   }
391   catch (Standard_Failure) {
392     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
393     SetErrorCode(aFail->GetMessageString());
394     return false;
395   }
396
397   SetErrorCode(OK);
398   return isValid;
399 }
400
401 //=============================================================================
402 /*!
403  *  WhatIs
404  */
405 //=============================================================================
406 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
407 {
408   SetErrorCode(KO);
409
410   TCollection_AsciiString Astr;
411
412   if (theShape.IsNull()) return Astr;
413
414   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
415   if (aRefShape.IsNull()) return Astr;
416
417   TopoDS_Shape aShape = aRefShape->GetValue();
418   if (aShape.IsNull()) {
419     SetErrorCode("The Objects has NULL Shape");
420     return Astr;
421   }
422
423   //Compute the parameters
424   if (aShape.ShapeType() == TopAbs_EDGE) {
425     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
426       Astr = Astr + " It is a degenerated edge \n";
427     }
428   }
429
430   Astr = Astr + " Number of sub-shapes : \n";
431
432   try {
433     int iType, nbTypes [TopAbs_SHAPE];
434     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
435       nbTypes[iType] = 0;
436     nbTypes[aShape.ShapeType()]++;
437
438     TopTools_MapOfShape aMapOfShape;
439     aMapOfShape.Add(aShape);
440     TopTools_ListOfShape aListOfShape;
441     aListOfShape.Append(aShape);
442
443     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
444     for (; itL.More(); itL.Next()) {
445       TopoDS_Iterator it (itL.Value());
446       for (; it.More(); it.Next()) {
447         TopoDS_Shape s = it.Value();
448         if (aMapOfShape.Add(s)) {
449           aListOfShape.Append(s);
450           nbTypes[s.ShapeType()]++;
451         }
452       }
453     }
454
455     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
456     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
457     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
458     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
459     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
460     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
461     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
462     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
463     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
464   }
465   catch (Standard_Failure) {
466     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
467     SetErrorCode(aFail->GetMessageString());
468     return Astr;
469   }
470
471   SetErrorCode(OK);
472   return Astr;
473 }
474
475 //=============================================================================
476 /*!
477  *  GetMinDistance
478  */
479 //=============================================================================
480 Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
481   (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
482    Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1,
483    Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2)
484 {
485   SetErrorCode(KO);
486   Standard_Real MinDist = 1.e9;
487
488   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
489
490   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
491   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
492   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
493
494   TopoDS_Shape aShape1 = aRefShape1->GetValue();
495   TopoDS_Shape aShape2 = aRefShape2->GetValue();
496   if (aShape1.IsNull() || aShape2.IsNull()) {
497     SetErrorCode("One of Objects has NULL Shape");
498     return MinDist;
499   }
500
501   //Compute the parameters
502   try {
503     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
504     if (dst.IsDone()) {
505       gp_Pnt PMin1, PMin2, P1, P2;
506
507       for (int i = 1; i <= dst.NbSolution(); i++) {
508         P1 = dst.PointOnShape1(i);
509         P2 = dst.PointOnShape2(i);
510
511         Standard_Real Dist = P1.Distance(P2);
512         if (MinDist > Dist) {
513           MinDist = Dist;
514           PMin1 = P1;
515           PMin2 = P2;
516         }
517       }
518
519       PMin1.Coord(X1, Y1, Z1);
520       PMin2.Coord(X2, Y2, Z2);
521     }
522   }
523   catch (Standard_Failure) {
524     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
525     SetErrorCode(aFail->GetMessageString());
526     return MinDist;
527   }
528
529   SetErrorCode(OK);
530   return MinDist;
531 }
532
533 //=======================================================================
534 //function : PointCoordinates
535 //purpose  : Get coordinates of point
536 //=======================================================================
537 void GEOMImpl_IMeasureOperations::PointCoordinates( Handle(GEOM_Object) theShape,
538                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ )
539 {
540   SetErrorCode( KO );
541
542   if ( theShape.IsNull() )
543     return;
544
545   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
546   if ( aRefShape.IsNull() )
547     return;
548
549   TopoDS_Shape aShape = aRefShape->GetValue();
550   if ( aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX )
551   {
552     SetErrorCode( "Shape must be a vertex" );
553     return;
554   }
555
556   try
557   {
558     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
559     theX = aPnt.X();
560     theY = aPnt.Y();
561     theZ = aPnt.Z();
562     SetErrorCode( OK );
563   }
564   catch ( Standard_Failure )
565   {
566     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
567     SetErrorCode( aFail->GetMessageString() );
568   }
569 }
570
571 //=======================================================================
572 //function : StructuralDump
573 //purpose  : Structural (data exchange) style of output.
574 //=======================================================================
575 void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna,
576                                                   const TopoDS_Shape&       theShape,
577                                                   TCollection_AsciiString&  theDump)
578 {
579   Standard_Integer i;
580   theDump.Clear();
581   theDump += " -- The Shape has problems :\n";
582   theDump += "  Check                                    Count\n";
583   theDump += " ------------------------------------------------\n";
584
585   Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail;
586   Handle(TColStd_HArray1OfInteger) NbProblems =
587     new TColStd_HArray1OfInteger(1, last_stat);
588   for (i = 1; i <= last_stat; i++)
589     NbProblems->SetValue(i,0);
590
591   Handle(TopTools_HSequenceOfShape) sl;
592   sl = new TopTools_HSequenceOfShape();
593   TopTools_DataMapOfShapeListOfShape theMap;
594   theMap.Clear();
595   GetProblemShapes(theAna, theShape, sl, NbProblems, theMap);
596   theMap.Clear();
597
598   Standard_Integer count = 0;
599   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve);
600   if (count > 0) {
601     theDump += "  Invalid Point on Curve ................... ";
602     theDump += TCollection_AsciiString(count) + "\n";
603   }
604   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface);
605   if (count > 0) {
606     theDump += "  Invalid Point on CurveOnSurface .......... ";
607     theDump += TCollection_AsciiString(count) + "\n";
608   }
609   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface);
610   if (count > 0) {
611     theDump += "  Invalid Point on Surface ................. ";
612     theDump += TCollection_AsciiString(count) + "\n";
613   }
614   count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve);
615   if (count > 0) {
616     theDump += "  No 3D Curve .............................. ";
617     theDump += TCollection_AsciiString(count) + "\n";
618   }
619   count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve);
620   if (count > 0) {
621     theDump += "  Multiple 3D Curve ........................ ";
622     theDump += TCollection_AsciiString(count) + "\n";
623   }
624   count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve);
625   if (count > 0) {
626     theDump += "  Invalid 3D Curve ......................... ";
627     theDump += TCollection_AsciiString(count) + "\n";
628   }
629   count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface);
630   if (count > 0) {
631     theDump += "  No Curve on Surface ...................... ";
632     theDump += TCollection_AsciiString(count) + "\n";
633   }
634   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface);
635   if (count > 0) {
636     theDump += "  Invalid Curve on Surface ................. ";
637     theDump += TCollection_AsciiString(count) + "\n";
638   }
639   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface);
640   if (count > 0) {
641     theDump += "  Invalid Curve on closed Surface .......... ";
642     theDump += TCollection_AsciiString(count) + "\n";
643   }
644   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag);
645   if (count > 0) {
646     theDump += "  Invalid SameRange Flag ................... ";
647     theDump += TCollection_AsciiString(count) + "\n";
648   }
649   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag);
650   if (count > 0) {
651     theDump += "  Invalid SameParameter Flag ............... ";
652     theDump += TCollection_AsciiString(count) + "\n";
653   }
654   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag);
655   if (count > 0) {
656     theDump += "  Invalid Degenerated Flag ................. ";
657     theDump += TCollection_AsciiString(count) + "\n";
658   }
659   count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge);
660   if (count > 0) {
661     theDump += "  Free Edge ................................ ";
662     theDump += TCollection_AsciiString(count) + "\n";
663   }
664   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity);
665   if (count > 0) {
666     theDump += "  Invalid MultiConnexity ................... ";
667     theDump += TCollection_AsciiString(count) + "\n";
668   }
669   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange);
670   if (count > 0) {
671     theDump += "  Invalid Range ............................ ";
672     theDump += TCollection_AsciiString(count) + "\n";
673   }
674   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire);
675   if (count > 0) {
676     theDump += "  Empty Wire ............................... ";
677     theDump += TCollection_AsciiString(count) + "\n";
678   }
679   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge);
680   if (count > 0) {
681     theDump += "  Redundant Edge ........................... ";
682     theDump += TCollection_AsciiString(count) + "\n";
683   }
684   count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire);
685   if (count > 0) {
686     theDump += "  Self Intersecting Wire ................... ";
687     theDump += TCollection_AsciiString(count) + "\n";
688   }
689   count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface);
690   if (count > 0) {
691     theDump += "  No Surface ............................... ";
692     theDump += TCollection_AsciiString(count) + "\n";
693   }
694   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire);
695   if (count > 0) {
696     theDump += "  Invalid Wire ............................. ";
697     theDump += TCollection_AsciiString(count) + "\n";
698   }
699   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire);
700   if (count > 0) {
701     theDump += "  Redundant Wire ........................... ";
702     theDump += TCollection_AsciiString(count) + "\n";
703   }
704   count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires);
705   if (count > 0) {
706     theDump += "  Intersecting Wires ....................... ";
707     theDump += TCollection_AsciiString(count) + "\n";
708   }
709   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires);
710   if (count > 0) {
711     theDump += "  Invalid Imbrication of Wires ............. ";
712     theDump += TCollection_AsciiString(count) + "\n";
713   }
714   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell);
715   if (count > 0) {
716     theDump += "  Empty Shell .............................. ";
717     theDump += TCollection_AsciiString(count) + "\n";
718   }
719   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace);
720   if (count > 0) {
721     theDump += "  Redundant Face ........................... ";
722     theDump += TCollection_AsciiString(count) + "\n";
723   }
724   count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape);
725   if (count > 0) {
726     theDump += "  Unorientable Shape ....................... ";
727     theDump += TCollection_AsciiString(count) + "\n";
728   }
729   count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed);
730   if (count > 0) {
731     theDump += "  Not Closed ............................... ";
732     theDump += TCollection_AsciiString(count) + "\n";
733   }
734   count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected);
735   if (count > 0) {
736     theDump += "  Not Connected ............................ ";
737     theDump += TCollection_AsciiString(count) + "\n";
738   }
739   count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape);
740   if (count > 0) {
741     theDump += "  Subshape not in Shape .................... ";
742     theDump += TCollection_AsciiString(count) + "\n";
743   }
744   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation);
745   if (count > 0) {
746     theDump += "  Bad Orientation .......................... ";
747     theDump += TCollection_AsciiString(count) + "\n";
748   }
749   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape);
750   if (count > 0) {
751     theDump += "  Bad Orientation of Subshape .............. ";
752     theDump += TCollection_AsciiString(count) + "\n";
753   }
754   count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail);
755   if (count > 0) {
756     theDump += "  checkshape failure ....................... ";
757     theDump += TCollection_AsciiString(count) + "\n";
758   }
759
760   theDump += " ------------------------------------------------\n";
761   theDump += "*** Shapes with problems : ";
762   theDump += TCollection_AsciiString(sl->Length()) + "\n";
763
764   Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
765   nbv = nbe = nbw = nbf = nbs = nbo = 0;
766
767   for (i = 1; i <= sl->Length(); i++) {
768     TopoDS_Shape shi = sl->Value(i);
769     TopAbs_ShapeEnum sti = shi.ShapeType();
770     switch (sti) {
771       case TopAbs_VERTEX : nbv++; break;
772       case TopAbs_EDGE   : nbe++; break;
773       case TopAbs_WIRE   : nbw++; break;
774       case TopAbs_FACE   : nbf++; break;
775       case TopAbs_SHELL  : nbs++; break;
776       case TopAbs_SOLID  : nbo++; break;
777       default            : break;
778     }
779   }
780
781   if (nbv > 0) {
782     theDump += "VERTEX : ";
783     if (nbv < 10) theDump += " ";
784     theDump += TCollection_AsciiString(nbv) + "\n";
785   }
786   if (nbe > 0) {
787     theDump += "EDGE   : ";
788     if (nbe < 10) theDump += " ";
789     theDump += TCollection_AsciiString(nbe) + "\n";
790   }
791   if (nbw > 0) {
792     theDump += "WIRE   : ";
793     if (nbw < 10) theDump += " ";
794     theDump += TCollection_AsciiString(nbw) + "\n";
795   }
796   if (nbf > 0) {
797     theDump += "FACE   : ";
798     if (nbf < 10) theDump += " ";
799     theDump += TCollection_AsciiString(nbf) + "\n";
800   }
801   if (nbs > 0) {
802     theDump += "SHELL  : ";
803     if (nbs < 10) theDump += " ";
804     theDump += TCollection_AsciiString(nbs) + "\n";
805   }
806   if (nbo > 0) {
807     theDump += "SOLID  : ";
808     if (nbo < 10) theDump += " ";
809     theDump += TCollection_AsciiString(nbo) + "\n";
810   }
811 }
812
813 //=======================================================================
814 //function : GetProblemShapes
815 // purpose : for StructuralDump
816 //=======================================================================
817 void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer&           theAna,
818                                                     const TopoDS_Shape&                 theShape,
819                                                     Handle(TopTools_HSequenceOfShape)&  sl,
820                                                     Handle(TColStd_HArray1OfInteger)&   NbProblems,
821                                                     TopTools_DataMapOfShapeListOfShape& theMap)
822 {
823   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
824     GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap);
825   }
826   TopAbs_ShapeEnum styp = theShape.ShapeType();
827   BRepCheck_ListIteratorOfListOfStatus itl;
828   TopTools_ListOfShape empty;
829   if (!theMap.IsBound(theShape)) {
830     theMap.Bind(theShape,empty);
831
832     if (!theAna.Result(theShape).IsNull()) {
833       itl.Initialize(theAna.Result(theShape)->Status());
834       // !!! May be, we have to print all the problems, not only the first one ?
835       if (itl.Value() != BRepCheck_NoError) {
836         sl->Append(theShape);
837         BRepCheck_Status stat = itl.Value();
838         NbProblems->SetValue((Standard_Integer)stat,
839                              NbProblems->Value((Standard_Integer)stat) + 1);
840       }
841     }
842   }
843
844   switch (styp) {
845   case TopAbs_EDGE:
846     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
847     break;
848   case TopAbs_FACE:
849     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap);
850     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap);
851     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
852     break;
853   case TopAbs_SHELL:
854     break;
855   case TopAbs_SOLID:
856     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap);
857     break;
858   default:
859     break;
860   }
861 }
862
863 //=======================================================================
864 //function : Contains
865 //=======================================================================
866 static Standard_Boolean Contains (const TopTools_ListOfShape& L,
867                                   const TopoDS_Shape& S)
868 {
869   TopTools_ListIteratorOfListOfShape it;
870   for (it.Initialize(L); it.More(); it.Next()) {
871     if (it.Value().IsSame(S)) {
872       return Standard_True;
873     }
874   }
875   return Standard_False;
876 }
877
878 //=======================================================================
879 //function : GetProblemSub
880 // purpose : for StructuralDump
881 //=======================================================================
882 void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&           theAna,
883                                                  const TopoDS_Shape&                 theShape,
884                                                  Handle(TopTools_HSequenceOfShape)&  sl,
885                                                  Handle(TColStd_HArray1OfInteger)&   NbProblems,
886                                                  const TopAbs_ShapeEnum              Subtype,
887                                                  TopTools_DataMapOfShapeListOfShape& theMap)
888 {
889   BRepCheck_ListIteratorOfListOfStatus itl;
890   TopExp_Explorer exp;
891   for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) {
892     const TopoDS_Shape& sub = exp.Current();
893
894     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
895     for (res->InitContextIterator();
896          res->MoreShapeInContext();
897          res->NextShapeInContext()) {
898       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
899         theMap(sub).Append(theShape);
900         itl.Initialize(res->StatusOnShape());
901
902         if (itl.Value() != BRepCheck_NoError) {
903           Standard_Integer ii = 0;
904
905           for (ii = 1; ii <= sl->Length(); ii++)
906             if (sl->Value(ii).IsSame(sub)) break;
907
908           if (ii > sl->Length()) {
909             sl->Append(sub);
910             BRepCheck_Status stat = itl.Value();
911             NbProblems->SetValue((Standard_Integer)stat,
912                                  NbProblems->Value((Standard_Integer)stat) + 1);
913           }
914           for (ii = 1; ii <= sl->Length(); ii++)
915             if (sl->Value(ii).IsSame(theShape)) break;
916           if (ii > sl->Length()) {
917             sl->Append(theShape);
918             BRepCheck_Status stat = itl.Value();
919             NbProblems->SetValue((Standard_Integer)stat,
920                                  NbProblems->Value((Standard_Integer)stat) + 1);
921           }
922         }
923         break;
924       }
925     }
926   }
927 }