Salome HOME
Copyrights update
[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/
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                                               TCollection_AsciiString& theDump)
365 {
366   SetErrorCode(KO);
367
368   if (theShape.IsNull()) return false;
369
370   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
371   if (aRefShape.IsNull()) return false;
372
373   TopoDS_Shape aShape = aRefShape->GetValue();
374   if (aShape.IsNull()) {
375     SetErrorCode("The Objects has NULL Shape");
376     return false;
377   }
378
379   //Compute the parameters
380   bool isValid = false;
381   try {
382     BRepCheck_Analyzer ana (aShape, false);
383     if (ana.IsValid()) {
384       theDump.Clear();
385       isValid = true;
386     } else {
387       StructuralDump(ana, aShape, theDump);
388     }
389   }
390   catch (Standard_Failure) {
391     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
392     SetErrorCode(aFail->GetMessageString());
393     return false;
394   }
395
396   SetErrorCode(OK);
397   return isValid;
398 }
399
400 //=============================================================================
401 /*!
402  *  WhatIs
403  */
404 //=============================================================================
405 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
406 {
407   SetErrorCode(KO);
408
409   TCollection_AsciiString Astr;
410
411   if (theShape.IsNull()) return Astr;
412
413   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
414   if (aRefShape.IsNull()) return Astr;
415
416   TopoDS_Shape aShape = aRefShape->GetValue();
417   if (aShape.IsNull()) {
418     SetErrorCode("The Objects has NULL Shape");
419     return Astr;
420   }
421
422   //Compute the parameters
423   if (aShape.ShapeType() == TopAbs_EDGE) {
424     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
425       Astr = Astr + " It is a degenerated edge \n";
426     }
427   }
428
429   Astr = Astr + " Number of sub-shapes : \n";
430
431   try {
432     int iType, nbTypes [TopAbs_SHAPE];
433     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
434       nbTypes[iType] = 0;
435     nbTypes[aShape.ShapeType()]++;
436
437     TopTools_MapOfShape aMapOfShape;
438     aMapOfShape.Add(aShape);
439     TopTools_ListOfShape aListOfShape;
440     aListOfShape.Append(aShape);
441
442     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
443     for (; itL.More(); itL.Next()) {
444       TopoDS_Iterator it (itL.Value());
445       for (; it.More(); it.Next()) {
446         TopoDS_Shape s = it.Value();
447         if (aMapOfShape.Add(s)) {
448           aListOfShape.Append(s);
449           nbTypes[s.ShapeType()]++;
450         }
451       }
452     }
453
454     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
455     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
456     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
457     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
458     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
459     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
460     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
461     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
462     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
463   }
464   catch (Standard_Failure) {
465     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
466     SetErrorCode(aFail->GetMessageString());
467     return Astr;
468   }
469
470   SetErrorCode(OK);
471   return Astr;
472 }
473
474 //=============================================================================
475 /*!
476  *  GetMinDistance
477  */
478 //=============================================================================
479 Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
480   (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
481    Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1,
482    Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2)
483 {
484   SetErrorCode(KO);
485   Standard_Real MinDist = 1.e9;
486
487   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
488
489   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
490   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
491   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
492
493   TopoDS_Shape aShape1 = aRefShape1->GetValue();
494   TopoDS_Shape aShape2 = aRefShape2->GetValue();
495   if (aShape1.IsNull() || aShape2.IsNull()) {
496     SetErrorCode("One of Objects has NULL Shape");
497     return MinDist;
498   }
499
500   //Compute the parameters
501   try {
502     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
503     if (dst.IsDone()) {
504       gp_Pnt PMin1, PMin2, P1, P2;
505
506       for (int i = 1; i <= dst.NbSolution(); i++) {
507         P1 = dst.PointOnShape1(i);
508         P2 = dst.PointOnShape2(i);
509
510         Standard_Real Dist = P1.Distance(P2);
511         if (MinDist > Dist) {
512           MinDist = Dist;
513           PMin1 = P1;
514           PMin2 = P2;
515         }
516       }
517
518       PMin1.Coord(X1, Y1, Z1);
519       PMin2.Coord(X2, Y2, Z2);
520     }
521   }
522   catch (Standard_Failure) {
523     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
524     SetErrorCode(aFail->GetMessageString());
525     return MinDist;
526   }
527
528   SetErrorCode(OK);
529   return MinDist;
530 }
531
532 //=======================================================================
533 //function : PointCoordinates
534 //purpose  : Get coordinates of point
535 //=======================================================================
536 void GEOMImpl_IMeasureOperations::PointCoordinates( Handle(GEOM_Object) theShape,
537                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ )
538 {
539   SetErrorCode( KO );
540
541   if ( theShape.IsNull() )
542     return;
543
544   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
545   if ( aRefShape.IsNull() )
546     return;
547
548   TopoDS_Shape aShape = aRefShape->GetValue();
549   if ( aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX )
550   {
551     SetErrorCode( "Shape must be a vertex" );
552     return;
553   }
554
555   try
556   {
557     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
558     theX = aPnt.X();
559     theY = aPnt.Y();
560     theZ = aPnt.Z();
561     SetErrorCode( OK );
562   }
563   catch ( Standard_Failure )
564   {
565     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
566     SetErrorCode( aFail->GetMessageString() );
567   }
568 }
569
570 //=======================================================================
571 //function : StructuralDump
572 //purpose  : Structural (data exchange) style of output.
573 //=======================================================================
574 void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna,
575                                                   const TopoDS_Shape&       theShape,
576                                                   TCollection_AsciiString&  theDump)
577 {
578   Standard_Integer i;
579   theDump.Clear();
580   theDump += " -- The Shape has problems :\n";
581   theDump += "  Check                                    Count\n";
582   theDump += " ------------------------------------------------\n";
583
584   Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail;
585   Handle(TColStd_HArray1OfInteger) NbProblems =
586     new TColStd_HArray1OfInteger(1, last_stat);
587   for (i = 1; i <= last_stat; i++)
588     NbProblems->SetValue(i,0);
589
590   Handle(TopTools_HSequenceOfShape) sl;
591   sl = new TopTools_HSequenceOfShape();
592   TopTools_DataMapOfShapeListOfShape theMap;
593   theMap.Clear();
594   GetProblemShapes(theAna, theShape, sl, NbProblems, theMap);
595   theMap.Clear();
596
597   Standard_Integer count = 0;
598   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve);
599   if (count > 0) {
600     theDump += "  Invalid Point on Curve ................... ";
601     theDump += TCollection_AsciiString(count) + "\n";
602   }
603   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface);
604   if (count > 0) {
605     theDump += "  Invalid Point on CurveOnSurface .......... ";
606     theDump += TCollection_AsciiString(count) + "\n";
607   }
608   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface);
609   if (count > 0) {
610     theDump += "  Invalid Point on Surface ................. ";
611     theDump += TCollection_AsciiString(count) + "\n";
612   }
613   count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve);
614   if (count > 0) {
615     theDump += "  No 3D Curve .............................. ";
616     theDump += TCollection_AsciiString(count) + "\n";
617   }
618   count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve);
619   if (count > 0) {
620     theDump += "  Multiple 3D Curve ........................ ";
621     theDump += TCollection_AsciiString(count) + "\n";
622   }
623   count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve);
624   if (count > 0) {
625     theDump += "  Invalid 3D Curve ......................... ";
626     theDump += TCollection_AsciiString(count) + "\n";
627   }
628   count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface);
629   if (count > 0) {
630     theDump += "  No Curve on Surface ...................... ";
631     theDump += TCollection_AsciiString(count) + "\n";
632   }
633   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface);
634   if (count > 0) {
635     theDump += "  Invalid Curve on Surface ................. ";
636     theDump += TCollection_AsciiString(count) + "\n";
637   }
638   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface);
639   if (count > 0) {
640     theDump += "  Invalid Curve on closed Surface .......... ";
641     theDump += TCollection_AsciiString(count) + "\n";
642   }
643   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag);
644   if (count > 0) {
645     theDump += "  Invalid SameRange Flag ................... ";
646     theDump += TCollection_AsciiString(count) + "\n";
647   }
648   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag);
649   if (count > 0) {
650     theDump += "  Invalid SameParameter Flag ............... ";
651     theDump += TCollection_AsciiString(count) + "\n";
652   }
653   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag);
654   if (count > 0) {
655     theDump += "  Invalid Degenerated Flag ................. ";
656     theDump += TCollection_AsciiString(count) + "\n";
657   }
658   count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge);
659   if (count > 0) {
660     theDump += "  Free Edge ................................ ";
661     theDump += TCollection_AsciiString(count) + "\n";
662   }
663   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity);
664   if (count > 0) {
665     theDump += "  Invalid MultiConnexity ................... ";
666     theDump += TCollection_AsciiString(count) + "\n";
667   }
668   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange);
669   if (count > 0) {
670     theDump += "  Invalid Range ............................ ";
671     theDump += TCollection_AsciiString(count) + "\n";
672   }
673   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire);
674   if (count > 0) {
675     theDump += "  Empty Wire ............................... ";
676     theDump += TCollection_AsciiString(count) + "\n";
677   }
678   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge);
679   if (count > 0) {
680     theDump += "  Redundant Edge ........................... ";
681     theDump += TCollection_AsciiString(count) + "\n";
682   }
683   count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire);
684   if (count > 0) {
685     theDump += "  Self Intersecting Wire ................... ";
686     theDump += TCollection_AsciiString(count) + "\n";
687   }
688   count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface);
689   if (count > 0) {
690     theDump += "  No Surface ............................... ";
691     theDump += TCollection_AsciiString(count) + "\n";
692   }
693   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire);
694   if (count > 0) {
695     theDump += "  Invalid Wire ............................. ";
696     theDump += TCollection_AsciiString(count) + "\n";
697   }
698   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire);
699   if (count > 0) {
700     theDump += "  Redundant Wire ........................... ";
701     theDump += TCollection_AsciiString(count) + "\n";
702   }
703   count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires);
704   if (count > 0) {
705     theDump += "  Intersecting Wires ....................... ";
706     theDump += TCollection_AsciiString(count) + "\n";
707   }
708   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires);
709   if (count > 0) {
710     theDump += "  Invalid Imbrication of Wires ............. ";
711     theDump += TCollection_AsciiString(count) + "\n";
712   }
713   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell);
714   if (count > 0) {
715     theDump += "  Empty Shell .............................. ";
716     theDump += TCollection_AsciiString(count) + "\n";
717   }
718   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace);
719   if (count > 0) {
720     theDump += "  Redundant Face ........................... ";
721     theDump += TCollection_AsciiString(count) + "\n";
722   }
723   count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape);
724   if (count > 0) {
725     theDump += "  Unorientable Shape ....................... ";
726     theDump += TCollection_AsciiString(count) + "\n";
727   }
728   count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed);
729   if (count > 0) {
730     theDump += "  Not Closed ............................... ";
731     theDump += TCollection_AsciiString(count) + "\n";
732   }
733   count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected);
734   if (count > 0) {
735     theDump += "  Not Connected ............................ ";
736     theDump += TCollection_AsciiString(count) + "\n";
737   }
738   count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape);
739   if (count > 0) {
740     theDump += "  Subshape not in Shape .................... ";
741     theDump += TCollection_AsciiString(count) + "\n";
742   }
743   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation);
744   if (count > 0) {
745     theDump += "  Bad Orientation .......................... ";
746     theDump += TCollection_AsciiString(count) + "\n";
747   }
748   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape);
749   if (count > 0) {
750     theDump += "  Bad Orientation of Subshape .............. ";
751     theDump += TCollection_AsciiString(count) + "\n";
752   }
753   count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail);
754   if (count > 0) {
755     theDump += "  checkshape failure ....................... ";
756     theDump += TCollection_AsciiString(count) + "\n";
757   }
758
759   theDump += " ------------------------------------------------\n";
760   theDump += "*** Shapes with problems : ";
761   theDump += TCollection_AsciiString(sl->Length()) + "\n";
762
763   Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
764   nbv = nbe = nbw = nbf = nbs = nbo = 0;
765
766   for (i = 1; i <= sl->Length(); i++) {
767     TopoDS_Shape shi = sl->Value(i);
768     TopAbs_ShapeEnum sti = shi.ShapeType();
769     switch (sti) {
770       case TopAbs_VERTEX : nbv++; break;
771       case TopAbs_EDGE   : nbe++; break;
772       case TopAbs_WIRE   : nbw++; break;
773       case TopAbs_FACE   : nbf++; break;
774       case TopAbs_SHELL  : nbs++; break;
775       case TopAbs_SOLID  : nbo++; break;
776       default            : break;
777     }
778   }
779
780   if (nbv > 0) {
781     theDump += "VERTEX : ";
782     if (nbv < 10) theDump += " ";
783     theDump += TCollection_AsciiString(nbv) + "\n";
784   }
785   if (nbe > 0) {
786     theDump += "EDGE   : ";
787     if (nbe < 10) theDump += " ";
788     theDump += TCollection_AsciiString(nbe) + "\n";
789   }
790   if (nbw > 0) {
791     theDump += "WIRE   : ";
792     if (nbw < 10) theDump += " ";
793     theDump += TCollection_AsciiString(nbw) + "\n";
794   }
795   if (nbf > 0) {
796     theDump += "FACE   : ";
797     if (nbf < 10) theDump += " ";
798     theDump += TCollection_AsciiString(nbf) + "\n";
799   }
800   if (nbs > 0) {
801     theDump += "SHELL  : ";
802     if (nbs < 10) theDump += " ";
803     theDump += TCollection_AsciiString(nbs) + "\n";
804   }
805   if (nbo > 0) {
806     theDump += "SOLID  : ";
807     if (nbo < 10) theDump += " ";
808     theDump += TCollection_AsciiString(nbo) + "\n";
809   }
810 }
811
812 //=======================================================================
813 //function : GetProblemShapes
814 // purpose : for StructuralDump
815 //=======================================================================
816 void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer&           theAna,
817                                                     const TopoDS_Shape&                 theShape,
818                                                     Handle(TopTools_HSequenceOfShape)&  sl,
819                                                     Handle(TColStd_HArray1OfInteger)&   NbProblems,
820                                                     TopTools_DataMapOfShapeListOfShape& theMap)
821 {
822   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
823     GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap);
824   }
825   TopAbs_ShapeEnum styp = theShape.ShapeType();
826   BRepCheck_ListIteratorOfListOfStatus itl;
827   TopTools_ListOfShape empty;
828   if (!theMap.IsBound(theShape)) {
829     theMap.Bind(theShape,empty);
830
831     if (!theAna.Result(theShape).IsNull()) {
832       itl.Initialize(theAna.Result(theShape)->Status());
833       // !!! May be, we have to print all the problems, not only the first one ?
834       if (itl.Value() != BRepCheck_NoError) {
835         sl->Append(theShape);
836         BRepCheck_Status stat = itl.Value();
837         NbProblems->SetValue((Standard_Integer)stat,
838                              NbProblems->Value((Standard_Integer)stat) + 1);
839       }
840     }
841   }
842
843   switch (styp) {
844   case TopAbs_EDGE:
845     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
846     break;
847   case TopAbs_FACE:
848     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap);
849     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap);
850     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
851     break;
852   case TopAbs_SHELL:
853     break;
854   case TopAbs_SOLID:
855     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap);
856     break;
857   default:
858     break;
859   }
860 }
861
862 //=======================================================================
863 //function : Contains
864 //=======================================================================
865 static Standard_Boolean Contains (const TopTools_ListOfShape& L,
866                                   const TopoDS_Shape& S)
867 {
868   TopTools_ListIteratorOfListOfShape it;
869   for (it.Initialize(L); it.More(); it.Next()) {
870     if (it.Value().IsSame(S)) {
871       return Standard_True;
872     }
873   }
874   return Standard_False;
875 }
876
877 //=======================================================================
878 //function : GetProblemSub
879 // purpose : for StructuralDump
880 //=======================================================================
881 void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&           theAna,
882                                                  const TopoDS_Shape&                 theShape,
883                                                  Handle(TopTools_HSequenceOfShape)&  sl,
884                                                  Handle(TColStd_HArray1OfInteger)&   NbProblems,
885                                                  const TopAbs_ShapeEnum              Subtype,
886                                                  TopTools_DataMapOfShapeListOfShape& theMap)
887 {
888   BRepCheck_ListIteratorOfListOfStatus itl;
889   TopExp_Explorer exp;
890   for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) {
891     const TopoDS_Shape& sub = exp.Current();
892
893     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
894     for (res->InitContextIterator();
895          res->MoreShapeInContext();
896          res->NextShapeInContext()) {
897       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
898         theMap(sub).Append(theShape);
899         itl.Initialize(res->StatusOnShape());
900
901         if (itl.Value() != BRepCheck_NoError) {
902           Standard_Integer ii = 0;
903
904           for (ii = 1; ii <= sl->Length(); ii++)
905             if (sl->Value(ii).IsSame(sub)) break;
906
907           if (ii > sl->Length()) {
908             sl->Append(sub);
909             BRepCheck_Status stat = itl.Value();
910             NbProblems->SetValue((Standard_Integer)stat,
911                                  NbProblems->Value((Standard_Integer)stat) + 1);
912           }
913           for (ii = 1; ii <= sl->Length(); ii++)
914             if (sl->Value(ii).IsSame(theShape)) break;
915           if (ii > sl->Length()) {
916             sl->Append(theShape);
917             BRepCheck_Status stat = itl.Value();
918             NbProblems->SetValue((Standard_Integer)stat,
919                                  NbProblems->Value((Standard_Integer)stat) + 1);
920           }
921         }
922         break;
923       }
924     }
925   }
926 }