]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
Salome HOME
NPAL15298: KindOfShape(). A tool by PKV.
[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 // OCCT Includes
36 #include <TFunction_DriverTable.hxx>
37 #include <TFunction_Driver.hxx>
38 #include <TFunction_Logbook.hxx>
39 #include <TDF_Tool.hxx>
40
41 #include <BRep_Tool.hxx>
42 #include <BRepAdaptor_Surface.hxx>
43 #include <BRepBndLib.hxx>
44 #include <BRepCheck.hxx>
45 #include <BRepCheck_Result.hxx>
46 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
47 #include <BRepExtrema_DistShapeShape.hxx>
48 #include <BRepGProp.hxx>
49 #include <BRepTools.hxx>
50
51 #include <Bnd_Box.hxx>
52
53 #include <GProp_GProps.hxx>
54 #include <GProp_PrincipalProps.hxx>
55
56 #include <TopAbs.hxx>
57 #include <TopoDS.hxx>
58 #include <TopoDS_Edge.hxx>
59 #include <TopoDS_Face.hxx>
60 #include <TopoDS_Shape.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopoDS_Iterator.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopTools_MapOfShape.hxx>
65 #include <TopTools_ListOfShape.hxx>
66 #include <TopTools_ListIteratorOfListOfShape.hxx>
67
68 #include <GeomAbs_SurfaceType.hxx>
69 #include <Geom_Surface.hxx>
70 #include <Geom_Plane.hxx>
71 #include <Geom_SphericalSurface.hxx>
72 #include <Geom_CylindricalSurface.hxx>
73 #include <Geom_ToroidalSurface.hxx>
74 #include <Geom_ConicalSurface.hxx>
75 #include <Geom_SurfaceOfLinearExtrusion.hxx>
76 #include <Geom_SurfaceOfRevolution.hxx>
77 #include <Geom_BezierSurface.hxx>
78 #include <Geom_BSplineSurface.hxx>
79 #include <Geom_RectangularTrimmedSurface.hxx>
80 #include <Geom_OffsetSurface.hxx>
81
82 #include <gp_Pln.hxx>
83
84 #include <Standard_Failure.hxx>
85 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
86
87 //=============================================================================
88 /*!
89  *   constructor:
90  */
91 //=============================================================================
92 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID)
93 : GEOM_IOperations(theEngine, theDocID)
94 {
95   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
96 }
97
98 //=============================================================================
99 /*!
100  *  destructor
101  */
102 //=============================================================================
103 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
104 {
105   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
106 }
107
108 //=============================================================================
109 /*! Get kind and parameters of the given shape.
110  */
111 //=============================================================================
112 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
113                              (Handle(GEOM_Object) theShape,
114                               Handle(TColStd_HSequenceOfInteger)& theIntegers,
115                               Handle(TColStd_HSequenceOfReal)&    theDoubles)
116 {
117   SetErrorCode(KO);
118   ShapeKind aKind = SK_NO_SHAPE;
119
120   if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
121   else                      theIntegers->Clear();
122
123   if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
124   else                     theDoubles->Clear();
125
126   if (theShape.IsNull())
127     return aKind;
128
129   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
130   if (aRefShape.IsNull()) return aKind;
131
132   TopoDS_Shape aShape = aRefShape->GetValue();
133   if (aShape.IsNull()) return aKind;
134
135   TopAbs_ShapeEnum aType = aShape.ShapeType();
136   switch (aType)
137   {
138     //??? geompy.kind.compound     nb_solids nb_faces nb_edges nb_vertices
139     //??? geompy.kind.compsolid    nb_solids nb_faces nb_edges nb_vertices
140     //? "nb_faces" - all faces or only 'standalone' faces?
141     case TopAbs_COMPOUND:
142       aKind = SK_COMPOUND;
143       //
144       break;
145     case TopAbs_COMPSOLID:
146       aKind = SK_COMPSOLID;
147       //
148       break;
149     case TopAbs_SHELL:
150       //geompy.kind.shell        geompy.info.closed   nb_faces nb_edges nb_vertices
151       //geompy.kind.shell        geompy.info.unclosed nb_faces nb_edges nb_vertices
152       aKind = SK_SHELL;
153       //
154       break;
155     case TopAbs_WIRE:
156       //geompy.kind.wire         geompy.info.closed   nb_edges nb_vertices
157       //geompy.kind.wire         geompy.info.unclosed nb_edges nb_vertices
158       aKind = SK_WIRE;
159       //
160       break;
161     case TopAbs_SOLID:
162       //geompy.kind.sphere       xc yc zc  R
163       //geompy.kind.cylinder     xb yb zb  dx dy dz  R  H
164       //geompy.kind.box          xc yc zc  dx dy dz
165       //geompy.kind.rotated_box  xo yo zo  zx zy zz  xx xy xz  dx dy dz
166       //geompy.kind.torus        xc yc zc  dx dy dz  R_1 R_2
167       //geompy.kind.cone         xb yb zb  dx dy dz  H  R_1  R_2
168       //geompy.kind.polyhedron   nb_faces nb_edges nb_vertices
169       //geompy.kind.solid        nb_faces nb_edges nb_vertices
170       aKind = SK_SOLID;
171       //if () {
172       //  aKind = SK_SPHERE;
173       //  aKind = SK_CYLINDER;
174       //  aKind = SK_BOX;
175       //  aKind = SK_ROTATED_BOX;
176       //  aKind = SK_TORUS;
177       //  aKind = SK_CONE;
178       //  aKind = SK_POLYHEDRON;
179       //}
180       break;
181     case TopAbs_FACE:
182       // geompy.kind.sphere2d     xc yc zc  R
183       // + geompy.kind.cylinder2d   xb yb zb  dx dy dz  R  H
184       // geompy.kind.torus2d      xc yc zc  dx dy dz  R_1 R_2
185       // geompy.kind.cone2d       xc yc zc  dx dy dz  R_1 R_2
186       // geompy.kind.disk         xc yc zc  dx dy dz  R
187       // geompy.kind.ellipse2d    xc yc zc  dx dy dz  R_1 R_2
188       // geompy.kind.polygon      xo yo zo  dx dy dz  nb_edges nb_vertices
189       // + geompy.kind.planar       xo yo zo  dx dy dz  nb_edges nb_vertices
190       // + geompy.kind.face         nb_edges nb_vertices _surface_type_id_
191       aKind = SK_FACE;
192       {
193         TopoDS_Face aF = TopoDS::Face(aShape);
194
195         int nbWires = 0, nbEdges = 0, nbVertices = 0;
196
197         TopTools_MapOfShape mapShape;
198         TopExp_Explorer expw (aF, TopAbs_WIRE);
199         for (; expw.More(); expw.Next()) {
200           if (mapShape.Add(expw.Current())) {
201             //listShape.Append(expw.Current());
202             nbWires++;
203           }
204         }
205
206         mapShape.Clear();
207         TopExp_Explorer expe (aF, TopAbs_EDGE);
208         for (; expe.More(); expe.Next()) {
209           if (mapShape.Add(expe.Current())) {
210             //listShape.Append(expe.Current());
211             nbEdges++;
212           }
213         }
214
215         mapShape.Clear();
216         TopExp_Explorer expf (aF, TopAbs_VERTEX);
217         for (; expf.More(); expf.Next()) {
218           if (mapShape.Add(expf.Current())) {
219             //listShape.Append(expf.Current());
220             nbVertices++;
221           }
222         }
223
224         // Geometry
225         Handle(Geom_Surface) aGS = BRep_Tool::Surface(aF);
226         if (!aGS.IsNull()) {
227           BRepAdaptor_Surface aBAS (aF);
228
229           if (aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
230             // planar
231             aKind = SK_PLANAR;
232
233             Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
234             gp_Pln aPln = aGPlane->Pln();
235             gp_Ax3 aPos = aPln.Position();
236             gp_Pnt anOri = aPos.Location();
237             gp_Dir aDirZ = aPos.Direction();
238             //gp_Dir aDirX = aPos.XDirection();
239
240             // xo yo zo
241             theDoubles->Append(anOri.X());
242             theDoubles->Append(anOri.Y());
243             theDoubles->Append(anOri.Z());
244
245             // dx dy dz
246             theDoubles->Append(aDirZ.X());
247             theDoubles->Append(aDirZ.Y());
248             theDoubles->Append(aDirZ.Z());
249
250             // nb_edges nb_vertices (for planar only)
251             theIntegers->Append(nbEdges);
252             theIntegers->Append(nbVertices);
253
254             //if () {
255             //  aKind = SK_DISK;
256             //  aKind = SK_ELLIPSE2D;
257             //  aKind = SK_POLYGON;
258             //}
259           }
260           else if (aGS->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
261             //if (/*isSphere*/false) {
262             if (aBAS.IsUClosed() && aBAS.IsVClosed()) { // does not work
263               Handle(Geom_SphericalSurface) aGSph = Handle(Geom_SphericalSurface)::DownCast(aGS);
264
265               // parameters
266               gp_Pnt aLoc = aGSph->Location();
267               Standard_Real rr = aGSph->Radius();
268
269               // xc yc zc
270               theDoubles->Append(aLoc.X());
271               theDoubles->Append(aLoc.Y());
272               theDoubles->Append(aLoc.Z());
273
274               // R
275               theDoubles->Append(rr);
276
277               aKind = SK_SPHERE2D;
278             }
279             else {
280               // nb_edges nb_vertices (for spherical only)
281               theIntegers->Append(nbEdges);
282               theIntegers->Append(nbVertices);
283
284               theIntegers->Append((Standard_Integer)GeomAbs_Sphere);
285             }
286           }
287           else if (aGS->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
288             // Pure cylinder or just a piece of cylindric surface
289             TopLoc_Location aL;
290             Handle(Geom_Surface) aGSLoc = BRep_Tool::Surface(aF, aL);
291
292             //aF.Orientation(TopAbs_FORWARD);
293             TopExp_Explorer ex (aF, TopAbs_EDGE);
294             Standard_Real uMin, uMax, vMin, vMax;
295             bool isCylinder = true;
296             for (; ex.More(); ex.Next()) {
297               // check all edges: pure cylinder has only one seam edge
298               //                  and two edges with const v parameter
299               TopoDS_Edge E = TopoDS::Edge(ex.Current());
300
301               if (BRep_Tool::IsClosed(E, aGSLoc, aL)) {
302                 // seam edge
303                 //TopoDS_Edge ERevr = E;
304                 //ERevr.Reverse();
305                 //Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface(E    , aF, f,l);
306                 //Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface(ERevr, aF, f,l);
307               }
308               else {
309                 BRepTools::UVBounds(aF, E, uMin, uMax, vMin, vMax);
310                 if (Abs(vMin - vMax) > Precision::Confusion())
311                   // neither seam, nor v-constant
312                   isCylinder = false;
313               }
314             }
315
316             if (isCylinder) {
317               aKind = SK_CYLINDER2D;
318
319               Handle(Geom_CylindricalSurface) aGCyl = Handle(Geom_CylindricalSurface)::DownCast(aGS);
320
321               // parameters
322               gp_Pnt aLoc = aGCyl->Location();
323               gp_Ax1 anAx = aGCyl->Axis();
324               gp_Dir aDir = anAx.Direction();
325               Standard_Real rr = aGCyl->Radius();
326
327               // xb yb zb
328               theDoubles->Append(aLoc.X());
329               theDoubles->Append(aLoc.Y());
330               theDoubles->Append(aLoc.Z());
331
332               // dx dy dz
333               theDoubles->Append(aDir.X());
334               theDoubles->Append(aDir.Y());
335               theDoubles->Append(aDir.Z());
336
337               // R
338               theDoubles->Append(rr);
339
340               // H
341               Standard_Real hh = Abs(aBAS.FirstVParameter() - aBAS.LastVParameter());
342               theDoubles->Append(hh);
343             }
344             else {
345               // nb_edges nb_vertices (for cylinrical only)
346               theIntegers->Append(nbEdges);
347               theIntegers->Append(nbVertices);
348
349               theIntegers->Append((Standard_Integer)GeomAbs_Cylinder);
350             }
351           }
352           else if (aGS->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
353             //  aKind = SK_TORUS2D;
354             theIntegers->Append(nbEdges);
355             theIntegers->Append(nbVertices);
356
357             theIntegers->Append((Standard_Integer)GeomAbs_Torus);
358           }
359           else if (aGS->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
360             //  aKind = SK_CONE2D;
361             theIntegers->Append(nbEdges);
362             theIntegers->Append(nbVertices);
363
364             theIntegers->Append((Standard_Integer)GeomAbs_Cone);
365           }
366           else if (aGS->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
367             //
368             theIntegers->Append(nbEdges);
369             theIntegers->Append(nbVertices);
370
371             theIntegers->Append((Standard_Integer)GeomAbs_SurfaceOfExtrusion);
372           }
373           else if (aGS->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
374             //
375             theIntegers->Append(nbEdges);
376             theIntegers->Append(nbVertices);
377
378             theIntegers->Append((Standard_Integer)GeomAbs_SurfaceOfRevolution);
379           }
380           else if (aGS->IsKind(STANDARD_TYPE(Geom_BezierSurface))) {
381             //
382             theIntegers->Append(nbEdges);
383             theIntegers->Append(nbVertices);
384
385             theIntegers->Append((Standard_Integer)GeomAbs_BezierSurface);
386           }
387           else if (aGS->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
388             //
389             theIntegers->Append(nbEdges);
390             theIntegers->Append(nbVertices);
391
392             theIntegers->Append((Standard_Integer)GeomAbs_BSplineSurface);
393           }
394           else if (aGS->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
395             //
396             theIntegers->Append(nbEdges);
397             theIntegers->Append(nbVertices);
398
399             theIntegers->Append((Standard_Integer)GeomAbs_OffsetSurface);
400           }
401           else if (aGS->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
402             //
403             theIntegers->Append(nbEdges);
404             theIntegers->Append(nbVertices);
405
406             theIntegers->Append((Standard_Integer)GeomAbs_OtherSurface);
407           }
408           else {
409             // ???
410             theIntegers->Append(nbEdges);
411             theIntegers->Append(nbVertices);
412
413             theIntegers->Append((Standard_Integer)GeomAbs_OtherSurface);
414           }
415         }
416       }
417       break;
418     case TopAbs_EDGE:
419       //geompy.kind.circle       xc yc zc  dx dy dz  R
420       //geompy.kind.arc          xc yc zc  dx dy dz  R  x1 y1 z1  x2 y2 z2
421       //geompy.kind.ellipse      xc yc zc  dx dy dz  R_1 R_2
422       //geompy.kind.arcEllipse   xc yc zc  dx dy dz  R_1 R_2  x1 y1 z1  x2 y2 z2
423       //geompy.kind.line         x1 y1 z1  x2 y2 z2
424       //geompy.kind.segment      x1 y1 z1  x2 y2 z2
425       //geompy.kind.edge         nb_vertices _curve_type_id_
426       aKind = SK_EDGE;
427       //if () {
428       //  aKind = SK_CIRCLE;
429       //  aKind = SK_ARC;
430       //  aKind = SK_ELLIPSE;
431       //  aKind = SK_ARC_ELLIPSE;
432       //  aKind = SK_LINE;
433       //  aKind = SK_SEGMENT;
434       //}
435       break;
436     case TopAbs_VERTEX:
437       //geompy.kind.VERTEX  x y z
438       aKind = SK_VERTEX;
439       {
440         TopoDS_Vertex aV = TopoDS::Vertex(aShape);
441         gp_Pnt aP = BRep_Tool::Pnt(aV);
442         theDoubles->Append(aP.X());
443         theDoubles->Append(aP.Y());
444         theDoubles->Append(aP.Z());
445       }
446       break;
447   }
448
449   SetErrorCode(OK);
450   return aKind;
451 }
452
453 //=============================================================================
454 /*! Get LCS, corresponding to the given shape.
455  *  Origin of the LCS is situated at the shape's center of mass.
456  *  Axes of the LCS are obtained from shape's location or,
457  *  if the shape is a planar face, from position of its plane.
458  */
459 //=============================================================================
460 gp_Ax3 GEOMImpl_IMeasureOperations::GetPosition (const TopoDS_Shape& theShape)
461 {
462   gp_Ax3 aResult;
463
464   if (theShape.IsNull())
465     return aResult;
466
467   // Axes
468   aResult.Transform(theShape.Location().Transformation());
469   if (theShape.ShapeType() == TopAbs_FACE) {
470     Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape));
471     if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
472       Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
473       gp_Pln aPln = aGPlane->Pln();
474       aResult = aPln.Position();
475     }
476   }
477
478   // Origin
479   gp_Pnt aPnt;
480   if (theShape.ShapeType() == TopAbs_VERTEX) {
481     aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
482   }
483   else {
484     GProp_GProps aSystem;
485     if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_WIRE)
486       BRepGProp::LinearProperties(theShape, aSystem);
487     else if (theShape.ShapeType() == TopAbs_FACE || theShape.ShapeType() == TopAbs_SHELL)
488       BRepGProp::SurfaceProperties(theShape, aSystem);
489     else
490       BRepGProp::VolumeProperties(theShape, aSystem);
491
492     aPnt = aSystem.CentreOfMass();
493   }
494
495   aResult.SetLocation(aPnt);
496
497   return aResult;
498 }
499
500 //=============================================================================
501 /*!
502  *  GetPosition
503  */
504 //=============================================================================
505 void GEOMImpl_IMeasureOperations::GetPosition
506                    (Handle(GEOM_Object) theShape,
507                     Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
508                     Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
509                     Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
510 {
511   SetErrorCode(KO);
512
513   //Set default values: global CS
514   Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
515   Zz = Xx = 1.;
516
517   if (theShape.IsNull()) return;
518
519   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
520   if (aRefShape.IsNull()) return;
521
522   TopoDS_Shape aShape = aRefShape->GetValue();
523   if (aShape.IsNull()) {
524     SetErrorCode("The Objects has NULL Shape");
525     return;
526   }
527
528   try {
529 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
530     OCC_CATCH_SIGNALS;
531 #endif
532
533     gp_Ax3 anAx3 = GetPosition(aShape);
534
535     gp_Pnt anOri = anAx3.Location();
536     gp_Dir aDirZ = anAx3.Direction();
537     gp_Dir aDirX = anAx3.XDirection();
538
539     // Output values
540     anOri.Coord(Ox, Oy, Oz);
541     aDirZ.Coord(Zx, Zy, Zz);
542     aDirX.Coord(Xx, Xy, Xz);
543   }
544   catch (Standard_Failure) {
545     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
546     SetErrorCode(aFail->GetMessageString());
547     return;
548   }
549
550   SetErrorCode(OK);
551 }
552
553 //=============================================================================
554 /*!
555  *  GetCentreOfMass
556  */
557 //=============================================================================
558 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
559                                                 (Handle(GEOM_Object) theShape)
560 {
561   SetErrorCode(KO);
562
563   if (theShape.IsNull()) return NULL;
564
565   //Add a new CentreOfMass object
566   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG);
567
568   //Add a new CentreOfMass function
569   Handle(GEOM_Function) aFunction =
570     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
571   if (aFunction.IsNull()) return NULL;
572
573   //Check if the function is set correctly
574   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
575
576   GEOMImpl_IMeasure aCI (aFunction);
577
578   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
579   if (aRefShape.IsNull()) return NULL;
580
581   aCI.SetBase(aRefShape);
582
583   //Compute the CentreOfMass value
584   try {
585 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
586     OCC_CATCH_SIGNALS;
587 #endif
588     if (!GetSolver()->ComputeFunction(aFunction)) {
589       SetErrorCode("Measure driver failed to compute centre of mass");
590       return NULL;
591     }
592   }
593   catch (Standard_Failure) {
594     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
595     SetErrorCode(aFail->GetMessageString());
596     return NULL;
597   }
598
599   //Make a Python command
600   GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
601
602   SetErrorCode(OK);
603   return aCDG;
604 }
605
606 //=============================================================================
607 /*!
608  *  GetBasicProperties
609  */
610 //=============================================================================
611 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
612                                                       Standard_Real& theLength,
613                                                       Standard_Real& theSurfArea,
614                                                       Standard_Real& theVolume)
615 {
616   SetErrorCode(KO);
617
618   if (theShape.IsNull()) return;
619
620   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
621   if (aRefShape.IsNull()) return;
622
623   TopoDS_Shape aShape = aRefShape->GetValue();
624   if (aShape.IsNull()) {
625     SetErrorCode("The Objects has NULL Shape");
626     return;
627   }
628
629   //Compute the parameters
630   GProp_GProps LProps, SProps;
631   try {
632 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
633     OCC_CATCH_SIGNALS;
634 #endif
635     BRepGProp::LinearProperties(aShape, LProps);
636     theLength = LProps.Mass();
637
638     BRepGProp::SurfaceProperties(aShape, SProps);
639     theSurfArea = SProps.Mass();
640
641     theVolume = 0.0;
642     if (aShape.ShapeType() < TopAbs_SHELL) {
643       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
644         GProp_GProps VProps;
645         BRepGProp::VolumeProperties(Exp.Current(), VProps);
646         theVolume += VProps.Mass();
647       }
648     }
649   }
650   catch (Standard_Failure) {
651     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
652     SetErrorCode(aFail->GetMessageString());
653     return;
654   }
655
656   SetErrorCode(OK);
657 }
658
659 //=============================================================================
660 /*!
661  *  GetInertia
662  */
663 //=============================================================================
664 void GEOMImpl_IMeasureOperations::GetInertia
665                    (Handle(GEOM_Object) theShape,
666                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
667                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
668                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
669                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
670 {
671   SetErrorCode(KO);
672
673   if (theShape.IsNull()) return;
674
675   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
676   if (aRefShape.IsNull()) return;
677
678   TopoDS_Shape aShape = aRefShape->GetValue();
679   if (aShape.IsNull()) {
680     SetErrorCode("The Objects has NULL Shape");
681     return;
682   }
683
684   //Compute the parameters
685   GProp_GProps System;
686
687   try {
688 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
689     OCC_CATCH_SIGNALS;
690 #endif
691     if (aShape.ShapeType() == TopAbs_VERTEX ||
692         aShape.ShapeType() == TopAbs_EDGE ||
693         aShape.ShapeType() == TopAbs_WIRE) {
694       BRepGProp::LinearProperties(aShape, System);
695     } else if (aShape.ShapeType() == TopAbs_FACE ||
696                aShape.ShapeType() == TopAbs_SHELL) {
697       BRepGProp::SurfaceProperties(aShape, System);
698     } else {
699       BRepGProp::VolumeProperties(aShape, System);
700     }
701     gp_Mat I = System.MatrixOfInertia();
702
703     I11 = I(1,1);
704     I12 = I(1,2);
705     I13 = I(1,3);
706
707     I21 = I(2,1);
708     I22 = I(2,2);
709     I23 = I(2,3);
710
711     I31 = I(3,1);
712     I32 = I(3,2);
713     I33 = I(3,3);
714
715     GProp_PrincipalProps Pr = System.PrincipalProperties();
716     Pr.Moments(Ix,Iy,Iz);
717   }
718   catch (Standard_Failure) {
719     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
720     SetErrorCode(aFail->GetMessageString());
721     return;
722   }
723
724   SetErrorCode(OK);
725 }
726
727 //=============================================================================
728 /*!
729  *  GetBoundingBox
730  */
731 //=============================================================================
732 void GEOMImpl_IMeasureOperations::GetBoundingBox
733                                      (Handle(GEOM_Object) theShape,
734                                       Standard_Real& Xmin, Standard_Real& Xmax,
735                                       Standard_Real& Ymin, Standard_Real& Ymax,
736                                       Standard_Real& Zmin, Standard_Real& Zmax)
737 {
738   SetErrorCode(KO);
739
740   if (theShape.IsNull()) return;
741
742   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
743   if (aRefShape.IsNull()) return;
744
745   TopoDS_Shape aShape = aRefShape->GetValue();
746   if (aShape.IsNull()) {
747     SetErrorCode("The Objects has NULL Shape");
748     return;
749   }
750
751   //Compute the parameters
752   Bnd_Box B;
753
754   try {
755 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
756     OCC_CATCH_SIGNALS;
757 #endif
758     BRepBndLib::Add(aShape, B);
759     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
760   }
761   catch (Standard_Failure) {
762     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
763     SetErrorCode(aFail->GetMessageString());
764     return;
765   }
766
767   SetErrorCode(OK);
768 }
769
770 //=============================================================================
771 /*!
772  *  GetTolerance
773  */
774 //=============================================================================
775 void GEOMImpl_IMeasureOperations::GetTolerance
776                                (Handle(GEOM_Object) theShape,
777                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
778                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
779                                 Standard_Real& VertMin, Standard_Real& VertMax)
780 {
781   SetErrorCode(KO);
782
783   if (theShape.IsNull()) return;
784
785   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
786   if (aRefShape.IsNull()) return;
787
788   TopoDS_Shape aShape = aRefShape->GetValue();
789   if (aShape.IsNull()) {
790     SetErrorCode("The Objects has NULL Shape");
791     return;
792   }
793
794   //Compute the parameters
795   Standard_Real T;
796   FaceMin = EdgeMin = VertMin = RealLast();
797   FaceMax = EdgeMax = VertMax = -RealLast();
798
799   try {
800 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
801     OCC_CATCH_SIGNALS;
802 #endif
803     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
804       TopoDS_Face Face = TopoDS::Face(ExF.Current());
805       T = BRep_Tool::Tolerance(Face);
806       if (T > FaceMax)
807         FaceMax = T;
808       if (T < FaceMin)
809         FaceMin = T;
810     }
811     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
812       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
813       T = BRep_Tool::Tolerance(Edge);
814       if (T > EdgeMax)
815         EdgeMax = T;
816       if (T < EdgeMin)
817         EdgeMin = T;
818     }
819     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
820       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
821       T = BRep_Tool::Tolerance(Vertex);
822       if (T > VertMax)
823         VertMax = T;
824       if (T < VertMin)
825         VertMin = T;
826     }
827   }
828   catch (Standard_Failure) {
829     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
830     SetErrorCode(aFail->GetMessageString());
831     return;
832   }
833
834   SetErrorCode(OK);
835 }
836
837 //=============================================================================
838 /*!
839  *  CheckShape
840  */
841 //=============================================================================
842 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)      theShape,
843                                               const Standard_Boolean   theIsCheckGeom,
844                                               TCollection_AsciiString& theDump)
845 {
846   SetErrorCode(KO);
847
848   if (theShape.IsNull()) return false;
849
850   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
851   if (aRefShape.IsNull()) return false;
852
853   TopoDS_Shape aShape = aRefShape->GetValue();
854   if (aShape.IsNull()) {
855     SetErrorCode("The Objects has NULL Shape");
856     return false;
857   }
858
859   //Compute the parameters
860   bool isValid = false;
861   try {
862 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
863     OCC_CATCH_SIGNALS;
864 #endif
865     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
866     if (ana.IsValid()) {
867       theDump.Clear();
868       isValid = true;
869     } else {
870       StructuralDump(ana, aShape, theDump);
871     }
872   }
873   catch (Standard_Failure) {
874     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
875     SetErrorCode(aFail->GetMessageString());
876     return false;
877   }
878
879   SetErrorCode(OK);
880   return isValid;
881 }
882
883 //=============================================================================
884 /*!
885  *  WhatIs
886  */
887 //=============================================================================
888 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
889 {
890   SetErrorCode(KO);
891
892   TCollection_AsciiString Astr;
893
894   if (theShape.IsNull()) return Astr;
895
896   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
897   if (aRefShape.IsNull()) return Astr;
898
899   TopoDS_Shape aShape = aRefShape->GetValue();
900   if (aShape.IsNull()) {
901     SetErrorCode("The Objects has NULL Shape");
902     return Astr;
903   }
904
905   //Compute the parameters
906   if (aShape.ShapeType() == TopAbs_EDGE) {
907     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
908       Astr = Astr + " It is a degenerated edge \n";
909     }
910   }
911
912   Astr = Astr + " Number of sub-shapes : \n";
913
914   try {
915 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
916     OCC_CATCH_SIGNALS;
917 #endif
918     int iType, nbTypes [TopAbs_SHAPE];
919     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
920       nbTypes[iType] = 0;
921     nbTypes[aShape.ShapeType()]++;
922
923     TopTools_MapOfShape aMapOfShape;
924     aMapOfShape.Add(aShape);
925     TopTools_ListOfShape aListOfShape;
926     aListOfShape.Append(aShape);
927
928     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
929     for (; itL.More(); itL.Next()) {
930       TopoDS_Iterator it (itL.Value());
931       for (; it.More(); it.Next()) {
932         TopoDS_Shape s = it.Value();
933         if (aMapOfShape.Add(s)) {
934           aListOfShape.Append(s);
935           nbTypes[s.ShapeType()]++;
936         }
937       }
938     }
939
940     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
941     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
942     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
943     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
944     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
945     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
946     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
947     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
948     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
949   }
950   catch (Standard_Failure) {
951     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
952     SetErrorCode(aFail->GetMessageString());
953     return Astr;
954   }
955
956   SetErrorCode(OK);
957   return Astr;
958 }
959
960 //=============================================================================
961 /*!
962  *  GetMinDistance
963  */
964 //=============================================================================
965 Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
966   (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
967    Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1,
968    Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2)
969 {
970   SetErrorCode(KO);
971   Standard_Real MinDist = 1.e9;
972
973   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
974
975   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
976   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
977   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
978
979   TopoDS_Shape aShape1 = aRefShape1->GetValue();
980   TopoDS_Shape aShape2 = aRefShape2->GetValue();
981   if (aShape1.IsNull() || aShape2.IsNull()) {
982     SetErrorCode("One of Objects has NULL Shape");
983     return MinDist;
984   }
985
986   //Compute the parameters
987   try {
988 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
989     OCC_CATCH_SIGNALS;
990 #endif
991     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
992     if (dst.IsDone()) {
993       gp_Pnt PMin1, PMin2, P1, P2;
994
995       for (int i = 1; i <= dst.NbSolution(); i++) {
996         P1 = dst.PointOnShape1(i);
997         P2 = dst.PointOnShape2(i);
998
999         Standard_Real Dist = P1.Distance(P2);
1000         if (MinDist > Dist) {
1001           MinDist = Dist;
1002           PMin1 = P1;
1003           PMin2 = P2;
1004         }
1005       }
1006
1007       PMin1.Coord(X1, Y1, Z1);
1008       PMin2.Coord(X2, Y2, Z2);
1009     }
1010   }
1011   catch (Standard_Failure) {
1012     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1013     SetErrorCode(aFail->GetMessageString());
1014     return MinDist;
1015   }
1016
1017   SetErrorCode(OK);
1018   return MinDist;
1019 }
1020
1021 //=======================================================================
1022 //function : PointCoordinates
1023 //purpose  : Get coordinates of point
1024 //=======================================================================
1025 void GEOMImpl_IMeasureOperations::PointCoordinates( Handle(GEOM_Object) theShape,
1026                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ )
1027 {
1028   SetErrorCode( KO );
1029
1030   if ( theShape.IsNull() )
1031     return;
1032
1033   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1034   if ( aRefShape.IsNull() )
1035     return;
1036
1037   TopoDS_Shape aShape = aRefShape->GetValue();
1038   if ( aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX )
1039   {
1040     SetErrorCode( "Shape must be a vertex" );
1041     return;
1042   }
1043
1044   try {
1045 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1046     OCC_CATCH_SIGNALS;
1047 #endif
1048     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
1049     theX = aPnt.X();
1050     theY = aPnt.Y();
1051     theZ = aPnt.Z();
1052     SetErrorCode( OK );
1053   }
1054   catch ( Standard_Failure )
1055   {
1056     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1057     SetErrorCode( aFail->GetMessageString() );
1058   }
1059 }
1060
1061 //=======================================================================
1062 //function : StructuralDump
1063 //purpose  : Structural (data exchange) style of output.
1064 //=======================================================================
1065 void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna,
1066                                                   const TopoDS_Shape&       theShape,
1067                                                   TCollection_AsciiString&  theDump)
1068 {
1069   Standard_Integer i;
1070   theDump.Clear();
1071   theDump += " -- The Shape has problems :\n";
1072   theDump += "  Check                                    Count\n";
1073   theDump += " ------------------------------------------------\n";
1074
1075   Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail;
1076   Handle(TColStd_HArray1OfInteger) NbProblems =
1077     new TColStd_HArray1OfInteger(1, last_stat);
1078   for (i = 1; i <= last_stat; i++)
1079     NbProblems->SetValue(i,0);
1080
1081   Handle(TopTools_HSequenceOfShape) sl;
1082   sl = new TopTools_HSequenceOfShape();
1083   TopTools_DataMapOfShapeListOfShape theMap;
1084   theMap.Clear();
1085   GetProblemShapes(theAna, theShape, sl, NbProblems, theMap);
1086   theMap.Clear();
1087
1088   Standard_Integer count = 0;
1089   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve);
1090   if (count > 0) {
1091     theDump += "  Invalid Point on Curve ................... ";
1092     theDump += TCollection_AsciiString(count) + "\n";
1093   }
1094   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface);
1095   if (count > 0) {
1096     theDump += "  Invalid Point on CurveOnSurface .......... ";
1097     theDump += TCollection_AsciiString(count) + "\n";
1098   }
1099   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface);
1100   if (count > 0) {
1101     theDump += "  Invalid Point on Surface ................. ";
1102     theDump += TCollection_AsciiString(count) + "\n";
1103   }
1104   count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve);
1105   if (count > 0) {
1106     theDump += "  No 3D Curve .............................. ";
1107     theDump += TCollection_AsciiString(count) + "\n";
1108   }
1109   count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve);
1110   if (count > 0) {
1111     theDump += "  Multiple 3D Curve ........................ ";
1112     theDump += TCollection_AsciiString(count) + "\n";
1113   }
1114   count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve);
1115   if (count > 0) {
1116     theDump += "  Invalid 3D Curve ......................... ";
1117     theDump += TCollection_AsciiString(count) + "\n";
1118   }
1119   count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface);
1120   if (count > 0) {
1121     theDump += "  No Curve on Surface ...................... ";
1122     theDump += TCollection_AsciiString(count) + "\n";
1123   }
1124   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface);
1125   if (count > 0) {
1126     theDump += "  Invalid Curve on Surface ................. ";
1127     theDump += TCollection_AsciiString(count) + "\n";
1128   }
1129   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface);
1130   if (count > 0) {
1131     theDump += "  Invalid Curve on closed Surface .......... ";
1132     theDump += TCollection_AsciiString(count) + "\n";
1133   }
1134   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag);
1135   if (count > 0) {
1136     theDump += "  Invalid SameRange Flag ................... ";
1137     theDump += TCollection_AsciiString(count) + "\n";
1138   }
1139   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag);
1140   if (count > 0) {
1141     theDump += "  Invalid SameParameter Flag ............... ";
1142     theDump += TCollection_AsciiString(count) + "\n";
1143   }
1144   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag);
1145   if (count > 0) {
1146     theDump += "  Invalid Degenerated Flag ................. ";
1147     theDump += TCollection_AsciiString(count) + "\n";
1148   }
1149   count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge);
1150   if (count > 0) {
1151     theDump += "  Free Edge ................................ ";
1152     theDump += TCollection_AsciiString(count) + "\n";
1153   }
1154   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity);
1155   if (count > 0) {
1156     theDump += "  Invalid MultiConnexity ................... ";
1157     theDump += TCollection_AsciiString(count) + "\n";
1158   }
1159   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange);
1160   if (count > 0) {
1161     theDump += "  Invalid Range ............................ ";
1162     theDump += TCollection_AsciiString(count) + "\n";
1163   }
1164   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire);
1165   if (count > 0) {
1166     theDump += "  Empty Wire ............................... ";
1167     theDump += TCollection_AsciiString(count) + "\n";
1168   }
1169   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge);
1170   if (count > 0) {
1171     theDump += "  Redundant Edge ........................... ";
1172     theDump += TCollection_AsciiString(count) + "\n";
1173   }
1174   count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire);
1175   if (count > 0) {
1176     theDump += "  Self Intersecting Wire ................... ";
1177     theDump += TCollection_AsciiString(count) + "\n";
1178   }
1179   count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface);
1180   if (count > 0) {
1181     theDump += "  No Surface ............................... ";
1182     theDump += TCollection_AsciiString(count) + "\n";
1183   }
1184   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire);
1185   if (count > 0) {
1186     theDump += "  Invalid Wire ............................. ";
1187     theDump += TCollection_AsciiString(count) + "\n";
1188   }
1189   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire);
1190   if (count > 0) {
1191     theDump += "  Redundant Wire ........................... ";
1192     theDump += TCollection_AsciiString(count) + "\n";
1193   }
1194   count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires);
1195   if (count > 0) {
1196     theDump += "  Intersecting Wires ....................... ";
1197     theDump += TCollection_AsciiString(count) + "\n";
1198   }
1199   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires);
1200   if (count > 0) {
1201     theDump += "  Invalid Imbrication of Wires ............. ";
1202     theDump += TCollection_AsciiString(count) + "\n";
1203   }
1204   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell);
1205   if (count > 0) {
1206     theDump += "  Empty Shell .............................. ";
1207     theDump += TCollection_AsciiString(count) + "\n";
1208   }
1209   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace);
1210   if (count > 0) {
1211     theDump += "  Redundant Face ........................... ";
1212     theDump += TCollection_AsciiString(count) + "\n";
1213   }
1214   count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape);
1215   if (count > 0) {
1216     theDump += "  Unorientable Shape ....................... ";
1217     theDump += TCollection_AsciiString(count) + "\n";
1218   }
1219   count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed);
1220   if (count > 0) {
1221     theDump += "  Not Closed ............................... ";
1222     theDump += TCollection_AsciiString(count) + "\n";
1223   }
1224   count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected);
1225   if (count > 0) {
1226     theDump += "  Not Connected ............................ ";
1227     theDump += TCollection_AsciiString(count) + "\n";
1228   }
1229   count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape);
1230   if (count > 0) {
1231     theDump += "  Subshape not in Shape .................... ";
1232     theDump += TCollection_AsciiString(count) + "\n";
1233   }
1234   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation);
1235   if (count > 0) {
1236     theDump += "  Bad Orientation .......................... ";
1237     theDump += TCollection_AsciiString(count) + "\n";
1238   }
1239   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape);
1240   if (count > 0) {
1241     theDump += "  Bad Orientation of Subshape .............. ";
1242     theDump += TCollection_AsciiString(count) + "\n";
1243   }
1244   count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail);
1245   if (count > 0) {
1246     theDump += "  checkshape failure ....................... ";
1247     theDump += TCollection_AsciiString(count) + "\n";
1248   }
1249
1250   theDump += " ------------------------------------------------\n";
1251   theDump += "*** Shapes with problems : ";
1252   theDump += TCollection_AsciiString(sl->Length()) + "\n";
1253
1254   Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1255   nbv = nbe = nbw = nbf = nbs = nbo = 0;
1256
1257   for (i = 1; i <= sl->Length(); i++) {
1258     TopoDS_Shape shi = sl->Value(i);
1259     TopAbs_ShapeEnum sti = shi.ShapeType();
1260     switch (sti) {
1261       case TopAbs_VERTEX : nbv++; break;
1262       case TopAbs_EDGE   : nbe++; break;
1263       case TopAbs_WIRE   : nbw++; break;
1264       case TopAbs_FACE   : nbf++; break;
1265       case TopAbs_SHELL  : nbs++; break;
1266       case TopAbs_SOLID  : nbo++; break;
1267       default            : break;
1268     }
1269   }
1270
1271   if (nbv > 0) {
1272     theDump += "VERTEX : ";
1273     if (nbv < 10) theDump += " ";
1274     theDump += TCollection_AsciiString(nbv) + "\n";
1275   }
1276   if (nbe > 0) {
1277     theDump += "EDGE   : ";
1278     if (nbe < 10) theDump += " ";
1279     theDump += TCollection_AsciiString(nbe) + "\n";
1280   }
1281   if (nbw > 0) {
1282     theDump += "WIRE   : ";
1283     if (nbw < 10) theDump += " ";
1284     theDump += TCollection_AsciiString(nbw) + "\n";
1285   }
1286   if (nbf > 0) {
1287     theDump += "FACE   : ";
1288     if (nbf < 10) theDump += " ";
1289     theDump += TCollection_AsciiString(nbf) + "\n";
1290   }
1291   if (nbs > 0) {
1292     theDump += "SHELL  : ";
1293     if (nbs < 10) theDump += " ";
1294     theDump += TCollection_AsciiString(nbs) + "\n";
1295   }
1296   if (nbo > 0) {
1297     theDump += "SOLID  : ";
1298     if (nbo < 10) theDump += " ";
1299     theDump += TCollection_AsciiString(nbo) + "\n";
1300   }
1301 }
1302
1303 //=======================================================================
1304 //function : GetProblemShapes
1305 // purpose : for StructuralDump
1306 //=======================================================================
1307 void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer&           theAna,
1308                                                     const TopoDS_Shape&                 theShape,
1309                                                     Handle(TopTools_HSequenceOfShape)&  sl,
1310                                                     Handle(TColStd_HArray1OfInteger)&   NbProblems,
1311                                                     TopTools_DataMapOfShapeListOfShape& theMap)
1312 {
1313   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
1314     GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap);
1315   }
1316   TopAbs_ShapeEnum styp = theShape.ShapeType();
1317   BRepCheck_ListIteratorOfListOfStatus itl;
1318   TopTools_ListOfShape empty;
1319   if (!theMap.IsBound(theShape)) {
1320     theMap.Bind(theShape,empty);
1321
1322     if (!theAna.Result(theShape).IsNull()) {
1323       itl.Initialize(theAna.Result(theShape)->Status());
1324       // !!! May be, we have to print all the problems, not only the first one ?
1325       if (itl.Value() != BRepCheck_NoError) {
1326         sl->Append(theShape);
1327         BRepCheck_Status stat = itl.Value();
1328         NbProblems->SetValue((Standard_Integer)stat,
1329                              NbProblems->Value((Standard_Integer)stat) + 1);
1330       }
1331     }
1332   }
1333
1334   switch (styp) {
1335   case TopAbs_EDGE:
1336     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
1337     break;
1338   case TopAbs_FACE:
1339     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap);
1340     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap);
1341     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
1342     break;
1343   case TopAbs_SHELL:
1344     break;
1345   case TopAbs_SOLID:
1346     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap);
1347     break;
1348   default:
1349     break;
1350   }
1351 }
1352
1353 //=======================================================================
1354 //function : Contains
1355 //=======================================================================
1356 static Standard_Boolean Contains (const TopTools_ListOfShape& L,
1357                                   const TopoDS_Shape& S)
1358 {
1359   TopTools_ListIteratorOfListOfShape it;
1360   for (it.Initialize(L); it.More(); it.Next()) {
1361     if (it.Value().IsSame(S)) {
1362       return Standard_True;
1363     }
1364   }
1365   return Standard_False;
1366 }
1367
1368 //=======================================================================
1369 //function : GetProblemSub
1370 // purpose : for StructuralDump
1371 //=======================================================================
1372 void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&           theAna,
1373                                                  const TopoDS_Shape&                 theShape,
1374                                                  Handle(TopTools_HSequenceOfShape)&  sl,
1375                                                  Handle(TColStd_HArray1OfInteger)&   NbProblems,
1376                                                  const TopAbs_ShapeEnum              Subtype,
1377                                                  TopTools_DataMapOfShapeListOfShape& theMap)
1378 {
1379   BRepCheck_ListIteratorOfListOfStatus itl;
1380   TopExp_Explorer exp;
1381   for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) {
1382     const TopoDS_Shape& sub = exp.Current();
1383
1384     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
1385     for (res->InitContextIterator();
1386          res->MoreShapeInContext();
1387          res->NextShapeInContext()) {
1388       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
1389         theMap(sub).Append(theShape);
1390         itl.Initialize(res->StatusOnShape());
1391
1392         if (itl.Value() != BRepCheck_NoError) {
1393           Standard_Integer ii = 0;
1394
1395           for (ii = 1; ii <= sl->Length(); ii++)
1396             if (sl->Value(ii).IsSame(sub)) break;
1397
1398           if (ii > sl->Length()) {
1399             sl->Append(sub);
1400             BRepCheck_Status stat = itl.Value();
1401             NbProblems->SetValue((Standard_Integer)stat,
1402                                  NbProblems->Value((Standard_Integer)stat) + 1);
1403           }
1404           for (ii = 1; ii <= sl->Length(); ii++)
1405             if (sl->Value(ii).IsSame(theShape)) break;
1406           if (ii > sl->Length()) {
1407             sl->Append(theShape);
1408             BRepCheck_Status stat = itl.Value();
1409             NbProblems->SetValue((Standard_Integer)stat,
1410                                  NbProblems->Value((Standard_Integer)stat) + 1);
1411           }
1412         }
1413         break;
1414       }
1415     }
1416   }
1417 }