]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
Salome HOME
0020628: EDF 1144 GEOM : In TUI, need a function to know the orientation of an edge...
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include <Standard_Stream.hxx>
23
24 #include <GEOMImpl_IMeasureOperations.hxx>
25
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOMImpl_MeasureDriver.hxx>
28 #include <GEOMImpl_IMeasure.hxx>
29
30 #include <GEOMAlgo_ShapeInfo.hxx>
31 #include <GEOMAlgo_ShapeInfoFiller.hxx>
32
33 #include <GEOM_Function.hxx>
34 #include <GEOM_PythonDump.hxx>
35
36 #include <utilities.h>
37 #include <OpUtil.hxx>
38 #include <Utils_ExceptHandlers.hxx>
39
40 // OCCT Includes
41 #include <TFunction_DriverTable.hxx>
42 #include <TFunction_Driver.hxx>
43 #include <TFunction_Logbook.hxx>
44 #include <TDF_Tool.hxx>
45
46 #include <BRep_Tool.hxx>
47 #include <BRepAdaptor_Surface.hxx>
48 #include <BRepBndLib.hxx>
49 #include <BRepCheck.hxx>
50 #include <BRepCheck_Result.hxx>
51 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
52 #include <BRepExtrema_DistShapeShape.hxx>
53 #include <BRepGProp.hxx>
54 #include <BRepTools.hxx>
55
56 #include <Bnd_Box.hxx>
57
58 #include <GProp_GProps.hxx>
59 #include <GProp_PrincipalProps.hxx>
60
61 #include <TopAbs.hxx>
62 #include <TopoDS.hxx>
63 #include <TopoDS_Edge.hxx>
64 #include <TopoDS_Face.hxx>
65 #include <TopoDS_Shape.hxx>
66 #include <TopoDS_Vertex.hxx>
67 #include <TopoDS_Iterator.hxx>
68 #include <TopExp_Explorer.hxx>
69 #include <TopTools_MapOfShape.hxx>
70 #include <TopTools_ListOfShape.hxx>
71 #include <TopTools_ListIteratorOfListOfShape.hxx>
72
73 #include <GeomAbs_SurfaceType.hxx>
74 #include <Geom_Surface.hxx>
75 #include <Geom_Plane.hxx>
76 #include <Geom_SphericalSurface.hxx>
77 #include <Geom_CylindricalSurface.hxx>
78 #include <Geom_ToroidalSurface.hxx>
79 #include <Geom_ConicalSurface.hxx>
80 #include <Geom_SurfaceOfLinearExtrusion.hxx>
81 #include <Geom_SurfaceOfRevolution.hxx>
82 #include <Geom_BezierSurface.hxx>
83 #include <Geom_BSplineSurface.hxx>
84 #include <Geom_RectangularTrimmedSurface.hxx>
85 #include <Geom_OffsetSurface.hxx>
86 #include <Geom_Line.hxx>
87
88 #include <gp_Pln.hxx>
89 #include <gp_Lin.hxx>
90
91 #include <GeomAPI_ProjectPointOnCurve.hxx>
92 #include <GeomLProp_CLProps.hxx>
93 #include <GeomLProp_SLProps.hxx>
94 #include <ShapeAnalysis.hxx>
95 #include <ShapeAnalysis_Surface.hxx>
96
97 #include <Standard_Failure.hxx>
98 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
99
100 #include <BRepClass3d_SolidClassifier.hxx>
101 #include <BRep_Builder.hxx>
102 #include <GeomAPI_IntSS.hxx>
103 #include <Geom_Circle.hxx>
104 #include <Geom_SphericalSurface.hxx>
105 #include <Geom_ToroidalSurface.hxx>
106 #include <ShapeFix_Shape.hxx>
107 #include <TopoDS_Compound.hxx>
108
109
110 //=============================================================================
111 /*!
112  *  Constructor
113  */
114 //=============================================================================
115 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID)
116 : GEOM_IOperations(theEngine, theDocID)
117 {
118   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
119 }
120
121 //=============================================================================
122 /*!
123  *  Destructor
124  */
125 //=============================================================================
126 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
127 {
128   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
129 }
130
131 //=============================================================================
132 /*! Get kind and parameters of the given shape.
133  */
134 //=============================================================================
135 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
136                              (Handle(GEOM_Object) theShape,
137                               Handle(TColStd_HSequenceOfInteger)& theIntegers,
138                               Handle(TColStd_HSequenceOfReal)&    theDoubles)
139 {
140   SetErrorCode(KO);
141   ShapeKind aKind = SK_NO_SHAPE;
142
143   if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
144   else                      theIntegers->Clear();
145
146   if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
147   else                     theDoubles->Clear();
148
149   if (theShape.IsNull())
150     return aKind;
151
152   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
153   if (aRefShape.IsNull()) return aKind;
154
155   TopoDS_Shape aShape = aRefShape->GetValue();
156   if (aShape.IsNull()) return aKind;
157
158   // Call algorithm
159   GEOMAlgo_ShapeInfoFiller aSF;
160   aSF.SetShape(aShape);
161   aSF.Perform();
162   Standard_Integer iErr = aSF.ErrorStatus();
163   if (iErr) {
164     SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
165     return SK_NO_SHAPE;
166   }
167   const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
168
169   // Interprete results
170   TopAbs_ShapeEnum aType = anInfo.Type();
171   switch (aType)
172   {
173   case TopAbs_COMPOUND:
174   case TopAbs_COMPSOLID:
175     {
176       // (+) geompy.kind.COMPOUND     nb_solids nb_faces nb_edges nb_vertices
177       // (+) geompy.kind.COMPSOLID    nb_solids nb_faces nb_edges nb_vertices
178       // ??? "nb_faces" - all faces or only 'standalone' faces?
179       if (aType == TopAbs_COMPOUND)
180         aKind = SK_COMPOUND;
181       else
182         aKind = SK_COMPSOLID;
183
184       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPOUND));
185       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPSOLID));
186       theIntegers->Append(anInfo.NbSubShapes(TopAbs_SOLID));
187       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
188       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
189       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
190     }
191     break;
192
193   case TopAbs_SHELL:
194     {
195       // (+) geompy.kind.SHELL  geompy.info.closed   nb_faces nb_edges nb_vertices
196       // (+) geompy.kind.SHELL  geompy.info.unclosed nb_faces nb_edges nb_vertices
197       aKind = SK_SHELL;
198
199       theIntegers->Append((int)anInfo.KindOfClosed());
200
201       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
202       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
203       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
204     }
205     break;
206
207   case TopAbs_WIRE:
208     {
209       // (+) geompy.kind.WIRE  geompy.info.closed   nb_edges nb_vertices
210       // (+) geompy.kind.WIRE  geompy.info.unclosed nb_edges nb_vertices
211       aKind = SK_WIRE;
212
213       theIntegers->Append((int)anInfo.KindOfClosed());
214
215       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
216       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
217     }
218     break;
219
220   case TopAbs_SOLID:
221     {
222       aKind = SK_SOLID;
223
224       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
225       switch (aKN)
226       {
227       case GEOMAlgo_KN_SPHERE:
228         // (+) geompy.kind.SPHERE  xc yc zc  R
229         {
230           aKind = SK_SPHERE;
231
232           gp_Pnt aC = anInfo.Location();
233           theDoubles->Append(aC.X());
234           theDoubles->Append(aC.Y());
235           theDoubles->Append(aC.Z());
236
237           theDoubles->Append(anInfo.Radius1());
238         }
239         break;
240       case GEOMAlgo_KN_CYLINDER:
241         // (+) geompy.kind.CYLINDER  xb yb zb  dx dy dz  R  H
242         {
243           aKind = SK_CYLINDER;
244
245           gp_Pnt aC = anInfo.Location();
246           theDoubles->Append(aC.X());
247           theDoubles->Append(aC.Y());
248           theDoubles->Append(aC.Z());
249
250           gp_Ax3 anAx3 = anInfo.Position();
251           gp_Dir aD = anAx3.Direction();
252           theDoubles->Append(aD.X());
253           theDoubles->Append(aD.Y());
254           theDoubles->Append(aD.Z());
255
256           theDoubles->Append(anInfo.Radius1());
257           theDoubles->Append(anInfo.Height());
258         }
259         break;
260       case GEOMAlgo_KN_BOX:
261         // (+) geompy.kind.BOX  xc yc zc  ax ay az
262         {
263           aKind = SK_BOX;
264
265           gp_Pnt aC = anInfo.Location();
266           theDoubles->Append(aC.X());
267           theDoubles->Append(aC.Y());
268           theDoubles->Append(aC.Z());
269
270           gp_Ax3 anAx3 = anInfo.Position();
271           gp_Dir aD = anAx3.Direction();
272           gp_Dir aX = anAx3.XDirection();
273
274           // ax ay az
275           if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
276               aX.IsParallel(gp::DX(), Precision::Angular())) {
277             theDoubles->Append(anInfo.Length()); // ax'
278             theDoubles->Append(anInfo.Width());  // ay'
279             theDoubles->Append(anInfo.Height()); // az'
280           }
281           else if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
282                    aX.IsParallel(gp::DY(), Precision::Angular())) {
283             theDoubles->Append(anInfo.Width());  // ay'
284             theDoubles->Append(anInfo.Length()); // ax'
285             theDoubles->Append(anInfo.Height()); // az'
286           }
287           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
288                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
289             theDoubles->Append(anInfo.Height()); // az'
290             theDoubles->Append(anInfo.Width());  // ay'
291             theDoubles->Append(anInfo.Length()); // ax'
292           }
293           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
294                    aX.IsParallel(gp::DY(), Precision::Angular())) {
295             theDoubles->Append(anInfo.Height()); // az'
296             theDoubles->Append(anInfo.Length()); // ax'
297             theDoubles->Append(anInfo.Width());  // ay'
298           }
299           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
300                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
301             theDoubles->Append(anInfo.Width());  // ay'
302             theDoubles->Append(anInfo.Height()); // az'
303             theDoubles->Append(anInfo.Length()); // ax'
304           }
305           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
306                    aX.IsParallel(gp::DX(), Precision::Angular())) {
307             theDoubles->Append(anInfo.Length()); // ax'
308             theDoubles->Append(anInfo.Height()); // az'
309             theDoubles->Append(anInfo.Width());  // ay'
310           }
311           else {
312             // (+) geompy.kind.ROTATED_BOX  xo yo zo  zx zy zz  xx xy xz  ax ay az
313             aKind = SK_ROTATED_BOX;
314
315             // Direction and XDirection
316             theDoubles->Append(aD.X());
317             theDoubles->Append(aD.Y());
318             theDoubles->Append(aD.Z());
319
320             theDoubles->Append(aX.X());
321             theDoubles->Append(aX.Y());
322             theDoubles->Append(aX.Z());
323
324             // ax ay az
325             theDoubles->Append(anInfo.Length());
326             theDoubles->Append(anInfo.Width());
327             theDoubles->Append(anInfo.Height());
328           }
329         }
330         break;
331       case GEOMAlgo_KN_TORUS:
332         // (+) geompy.kind.TORUS  xc yc zc  dx dy dz  R_1 R_2
333         {
334           aKind = SK_TORUS;
335
336           gp_Pnt aO = anInfo.Location();
337           theDoubles->Append(aO.X());
338           theDoubles->Append(aO.Y());
339           theDoubles->Append(aO.Z());
340
341           gp_Ax3 anAx3 = anInfo.Position();
342           gp_Dir aD = anAx3.Direction();
343           theDoubles->Append(aD.X());
344           theDoubles->Append(aD.Y());
345           theDoubles->Append(aD.Z());
346
347           theDoubles->Append(anInfo.Radius1());
348           theDoubles->Append(anInfo.Radius2());
349         }
350         break;
351       case GEOMAlgo_KN_CONE:
352         // (+) geompy.kind.CONE  xb yb zb  dx dy dz  R_1 R_2  H
353         {
354           aKind = SK_CONE;
355
356           gp_Pnt aO = anInfo.Location();
357           theDoubles->Append(aO.X());
358           theDoubles->Append(aO.Y());
359           theDoubles->Append(aO.Z());
360
361           gp_Ax3 anAx3 = anInfo.Position();
362           gp_Dir aD = anAx3.Direction();
363           theDoubles->Append(aD.X());
364           theDoubles->Append(aD.Y());
365           theDoubles->Append(aD.Z());
366
367           theDoubles->Append(anInfo.Radius1());
368           theDoubles->Append(anInfo.Radius2());
369           theDoubles->Append(anInfo.Height());
370         }
371         break;
372       case GEOMAlgo_KN_POLYHEDRON:
373         // (+) geompy.kind.POLYHEDRON  nb_faces nb_edges nb_vertices
374         {
375           aKind = SK_POLYHEDRON;
376
377           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
378           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
379           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
380         }
381         break;
382       default:
383         // (+) geompy.kind.SOLID  nb_faces nb_edges nb_vertices
384         {
385           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
386           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
387           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
388         }
389       }
390     }
391     break;
392
393   case TopAbs_FACE:
394     {
395       aKind = SK_FACE;
396
397       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
398       switch (aKN) {
399       case GEOMAlgo_KN_SPHERE:
400         // (+) geompy.kind.SPHERE2D  xc yc zc  R
401         {
402           aKind = SK_SPHERE2D;
403
404           gp_Pnt aC = anInfo.Location();
405           theDoubles->Append(aC.X());
406           theDoubles->Append(aC.Y());
407           theDoubles->Append(aC.Z());
408
409           theDoubles->Append(anInfo.Radius1());
410         }
411         break;
412       case GEOMAlgo_KN_CYLINDER:
413         // (+) geompy.kind.CYLINDER2D  xb yb zb  dx dy dz  R  H
414         {
415           aKind = SK_CYLINDER2D;
416
417           gp_Pnt aO = anInfo.Location();
418           theDoubles->Append(aO.X());
419           theDoubles->Append(aO.Y());
420           theDoubles->Append(aO.Z());
421
422           gp_Ax3 anAx3 = anInfo.Position();
423           gp_Dir aD = anAx3.Direction();
424           theDoubles->Append(aD.X());
425           theDoubles->Append(aD.Y());
426           theDoubles->Append(aD.Z());
427
428           theDoubles->Append(anInfo.Radius1());
429           theDoubles->Append(anInfo.Height());
430         }
431         break;
432       case GEOMAlgo_KN_TORUS:
433         // (+) geompy.kind.TORUS2D  xc yc zc  dx dy dz  R_1 R_2
434         {
435           aKind = SK_TORUS2D;
436
437           gp_Pnt aO = anInfo.Location();
438           theDoubles->Append(aO.X());
439           theDoubles->Append(aO.Y());
440           theDoubles->Append(aO.Z());
441
442           gp_Ax3 anAx3 = anInfo.Position();
443           gp_Dir aD = anAx3.Direction();
444           theDoubles->Append(aD.X());
445           theDoubles->Append(aD.Y());
446           theDoubles->Append(aD.Z());
447
448           theDoubles->Append(anInfo.Radius1());
449           theDoubles->Append(anInfo.Radius2());
450         }
451         break;
452       case GEOMAlgo_KN_CONE:
453         // (+) geompy.kind.CONE2D  xc yc zc  dx dy dz  R_1 R_2  H
454         {
455           aKind = SK_CONE2D;
456
457           gp_Pnt aO = anInfo.Location();
458           theDoubles->Append(aO.X());
459           theDoubles->Append(aO.Y());
460           theDoubles->Append(aO.Z());
461
462           gp_Ax3 anAx3 = anInfo.Position();
463           gp_Dir aD = anAx3.Direction();
464           theDoubles->Append(aD.X());
465           theDoubles->Append(aD.Y());
466           theDoubles->Append(aD.Z());
467
468           theDoubles->Append(anInfo.Radius1());
469           theDoubles->Append(anInfo.Radius2());
470           theDoubles->Append(anInfo.Height());
471         }
472         break;
473       case GEOMAlgo_KN_DISKCIRCLE:
474         // (+) geompy.kind.DISK_CIRCLE  xc yc zc  dx dy dz  R
475         {
476           aKind = SK_DISK_CIRCLE;
477
478           gp_Pnt aC = anInfo.Location();
479           theDoubles->Append(aC.X());
480           theDoubles->Append(aC.Y());
481           theDoubles->Append(aC.Z());
482
483           gp_Ax3 anAx3 = anInfo.Position();
484           gp_Dir aD = anAx3.Direction();
485           theDoubles->Append(aD.X());
486           theDoubles->Append(aD.Y());
487           theDoubles->Append(aD.Z());
488
489           theDoubles->Append(anInfo.Radius1());
490         }
491         break;
492       case GEOMAlgo_KN_DISKELLIPSE:
493         // (+) geompy.kind.DISK_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
494         {
495           aKind = SK_DISK_ELLIPSE;
496
497           gp_Pnt aC = anInfo.Location();
498           theDoubles->Append(aC.X());
499           theDoubles->Append(aC.Y());
500           theDoubles->Append(aC.Z());
501
502           gp_Ax3 anAx3 = anInfo.Position();
503           gp_Dir aD = anAx3.Direction();
504           theDoubles->Append(aD.X());
505           theDoubles->Append(aD.Y());
506           theDoubles->Append(aD.Z());
507
508           theDoubles->Append(anInfo.Radius1());
509           theDoubles->Append(anInfo.Radius2());
510         }
511         break;
512       case GEOMAlgo_KN_RECTANGLE:
513       case GEOMAlgo_KN_TRIANGLE:
514       case GEOMAlgo_KN_QUADRANGLE:
515       case GEOMAlgo_KN_POLYGON:
516         // (+) geompy.kind.POLYGON  xo yo zo  dx dy dz  nb_edges nb_vertices
517         {
518           aKind = SK_POLYGON;
519
520           gp_Pnt aO = anInfo.Location();
521           theDoubles->Append(aO.X());
522           theDoubles->Append(aO.Y());
523           theDoubles->Append(aO.Z());
524
525           gp_Ax3 anAx3 = anInfo.Position();
526           gp_Dir aD = anAx3.Direction();
527           theDoubles->Append(aD.X());
528           theDoubles->Append(aD.Y());
529           theDoubles->Append(aD.Z());
530
531           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
532           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
533         }
534         break;
535       case GEOMAlgo_KN_PLANE: // infinite
536         // (+) geompy.kind.PLANE  xo yo zo  dx dy dz
537         {
538           aKind = SK_PLANE;
539
540           gp_Pnt aC = anInfo.Location();
541           theDoubles->Append(aC.X());
542           theDoubles->Append(aC.Y());
543           theDoubles->Append(aC.Z());
544
545           gp_Ax3 anAx3 = anInfo.Position();
546           gp_Dir aD = anAx3.Direction();
547           theDoubles->Append(aD.X());
548           theDoubles->Append(aD.Y());
549           theDoubles->Append(aD.Z());
550         }
551         break;
552       default:
553         if (anInfo.KindOfShape() == GEOMAlgo_KS_PLANE) {
554           // (+) geompy.kind.PLANAR  xo yo zo  dx dy dz  nb_edges nb_vertices
555
556           aKind = SK_PLANAR;
557
558           gp_Pnt aC = anInfo.Location();
559           theDoubles->Append(aC.X());
560           theDoubles->Append(aC.Y());
561           theDoubles->Append(aC.Z());
562
563           gp_Ax3 anAx3 = anInfo.Position();
564           gp_Dir aD = anAx3.Direction();
565           theDoubles->Append(aD.X());
566           theDoubles->Append(aD.Y());
567           theDoubles->Append(aD.Z());
568
569           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
570           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
571         }
572         else {
573           // ??? geompy.kind.FACE  nb_edges nb_vertices _surface_type_id_
574           // (+) geompy.kind.FACE  nb_edges nb_vertices
575
576           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
577           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
578         }
579       }
580     }
581     break;
582
583   case TopAbs_EDGE:
584     {
585       aKind = SK_EDGE;
586
587       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
588       switch (aKN) {
589       case GEOMAlgo_KN_CIRCLE:
590         {
591           // (+) geompy.kind.CIRCLE  xc yc zc  dx dy dz  R
592           aKind = SK_CIRCLE;
593
594           gp_Pnt aC = anInfo.Location();
595           theDoubles->Append(aC.X());
596           theDoubles->Append(aC.Y());
597           theDoubles->Append(aC.Z());
598
599           gp_Ax3 anAx3 = anInfo.Position();
600           gp_Dir aD = anAx3.Direction();
601           theDoubles->Append(aD.X());
602           theDoubles->Append(aD.Y());
603           theDoubles->Append(aD.Z());
604
605           theDoubles->Append(anInfo.Radius1());
606         }
607         break;
608       case GEOMAlgo_KN_ARCCIRCLE:
609         {
610           // (+) geompy.kind.ARC_CIRCLE  xc yc zc  dx dy dz  R  x1 y1 z1  x2 y2 z2
611           aKind = SK_ARC_CIRCLE;
612
613           gp_Pnt aC = anInfo.Location();
614           theDoubles->Append(aC.X());
615           theDoubles->Append(aC.Y());
616           theDoubles->Append(aC.Z());
617
618           gp_Ax3 anAx3 = anInfo.Position();
619           gp_Dir aD = anAx3.Direction();
620           theDoubles->Append(aD.X());
621           theDoubles->Append(aD.Y());
622           theDoubles->Append(aD.Z());
623
624           theDoubles->Append(anInfo.Radius1());
625
626           gp_Pnt aP1 = anInfo.Pnt1();
627           theDoubles->Append(aP1.X());
628           theDoubles->Append(aP1.Y());
629           theDoubles->Append(aP1.Z());
630
631           gp_Pnt aP2 = anInfo.Pnt2();
632           theDoubles->Append(aP2.X());
633           theDoubles->Append(aP2.Y());
634           theDoubles->Append(aP2.Z());
635         }
636         break;
637       case GEOMAlgo_KN_ELLIPSE:
638         {
639           // (+) geompy.kind.ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
640           aKind = SK_ELLIPSE;
641
642           gp_Pnt aC = anInfo.Location();
643           theDoubles->Append(aC.X());
644           theDoubles->Append(aC.Y());
645           theDoubles->Append(aC.Z());
646
647           gp_Ax3 anAx3 = anInfo.Position();
648           gp_Dir aD = anAx3.Direction();
649           theDoubles->Append(aD.X());
650           theDoubles->Append(aD.Y());
651           theDoubles->Append(aD.Z());
652
653           theDoubles->Append(anInfo.Radius1());
654           theDoubles->Append(anInfo.Radius2());
655         }
656         break;
657       case GEOMAlgo_KN_ARCELLIPSE:
658         {
659           // (+) geompy.kind.ARC_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2  x1 y1 z1  x2 y2 z2
660           aKind = SK_ARC_ELLIPSE;
661
662           gp_Pnt aC = anInfo.Location();
663           theDoubles->Append(aC.X());
664           theDoubles->Append(aC.Y());
665           theDoubles->Append(aC.Z());
666
667           gp_Ax3 anAx3 = anInfo.Position();
668           gp_Dir aD = anAx3.Direction();
669           theDoubles->Append(aD.X());
670           theDoubles->Append(aD.Y());
671           theDoubles->Append(aD.Z());
672
673           theDoubles->Append(anInfo.Radius1());
674           theDoubles->Append(anInfo.Radius2());
675
676           gp_Pnt aP1 = anInfo.Pnt1();
677           theDoubles->Append(aP1.X());
678           theDoubles->Append(aP1.Y());
679           theDoubles->Append(aP1.Z());
680
681           gp_Pnt aP2 = anInfo.Pnt2();
682           theDoubles->Append(aP2.X());
683           theDoubles->Append(aP2.Y());
684           theDoubles->Append(aP2.Z());
685         }
686         break;
687       case GEOMAlgo_KN_LINE:
688         {
689           // ??? geompy.kind.LINE  x1 y1 z1  x2 y2 z2
690           // (+) geompy.kind.LINE  x1 y1 z1  dx dy dz
691           aKind = SK_LINE;
692
693           gp_Pnt aO = anInfo.Location();
694           theDoubles->Append(aO.X());
695           theDoubles->Append(aO.Y());
696           theDoubles->Append(aO.Z());
697
698           gp_Dir aD = anInfo.Direction();
699           theDoubles->Append(aD.X());
700           theDoubles->Append(aD.Y());
701           theDoubles->Append(aD.Z());
702         }
703         break;
704       case GEOMAlgo_KN_SEGMENT:
705         {
706           // (+) geompy.kind.SEGMENT  x1 y1 z1  x2 y2 z2
707           aKind = SK_SEGMENT;
708
709           gp_Pnt aP1 = anInfo.Pnt1();
710           theDoubles->Append(aP1.X());
711           theDoubles->Append(aP1.Y());
712           theDoubles->Append(aP1.Z());
713
714           gp_Pnt aP2 = anInfo.Pnt2();
715           theDoubles->Append(aP2.X());
716           theDoubles->Append(aP2.Y());
717           theDoubles->Append(aP2.Z());
718         }
719         break;
720       default:
721         // ??? geompy.kind.EDGE  nb_vertices _curve_type_id_
722         // (+) geompy.kind.EDGE  nb_vertices
723         theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
724       }
725     }
726     break;
727
728   case TopAbs_VERTEX:
729     {
730       // (+) geompy.kind.VERTEX  x y z
731       aKind = SK_VERTEX;
732
733       gp_Pnt aP = anInfo.Location();
734       theDoubles->Append(aP.X());
735       theDoubles->Append(aP.Y());
736       theDoubles->Append(aP.Z());
737     }
738     break;
739   }
740
741   SetErrorCode(OK);
742   return aKind;
743 }
744
745 //=============================================================================
746 /*! Get LCS, corresponding to the given shape.
747  *  Origin of the LCS is situated at the shape's center of mass.
748  *  Axes of the LCS are obtained from shape's location or,
749  *  if the shape is a planar face, from position of its plane.
750  */
751 //=============================================================================
752 gp_Ax3 GEOMImpl_IMeasureOperations::GetPosition (const TopoDS_Shape& theShape)
753 {
754   gp_Ax3 aResult;
755
756   if (theShape.IsNull())
757     return aResult;
758
759   // Axes
760   aResult.Transform(theShape.Location().Transformation());
761   if (theShape.ShapeType() == TopAbs_FACE) {
762     Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape));
763     if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
764       Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
765       gp_Pln aPln = aGPlane->Pln();
766       aResult = aPln.Position();
767     }
768   }
769
770   // Origin
771   gp_Pnt aPnt;
772   if (theShape.ShapeType() == TopAbs_VERTEX) {
773     aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
774   }
775   else {
776     GProp_GProps aSystem;
777     if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_WIRE)
778       BRepGProp::LinearProperties(theShape, aSystem);
779     else if (theShape.ShapeType() == TopAbs_FACE || theShape.ShapeType() == TopAbs_SHELL)
780       BRepGProp::SurfaceProperties(theShape, aSystem);
781     else
782       BRepGProp::VolumeProperties(theShape, aSystem);
783
784     aPnt = aSystem.CentreOfMass();
785   }
786
787   aResult.SetLocation(aPnt);
788
789   return aResult;
790 }
791
792 //=============================================================================
793 /*!
794  *  GetPosition
795  */
796 //=============================================================================
797 void GEOMImpl_IMeasureOperations::GetPosition
798                    (Handle(GEOM_Object) theShape,
799                     Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
800                     Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
801                     Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
802 {
803   SetErrorCode(KO);
804
805   //Set default values: global CS
806   Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
807   Zz = Xx = 1.;
808
809   if (theShape.IsNull()) return;
810
811   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
812   if (aRefShape.IsNull()) return;
813
814   TopoDS_Shape aShape = aRefShape->GetValue();
815   if (aShape.IsNull()) {
816     SetErrorCode("The Objects has NULL Shape");
817     return;
818   }
819
820   try {
821 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
822     OCC_CATCH_SIGNALS;
823 #endif
824
825     gp_Ax3 anAx3 = GetPosition(aShape);
826
827     gp_Pnt anOri = anAx3.Location();
828     gp_Dir aDirZ = anAx3.Direction();
829     gp_Dir aDirX = anAx3.XDirection();
830
831     // Output values
832     anOri.Coord(Ox, Oy, Oz);
833     aDirZ.Coord(Zx, Zy, Zz);
834     aDirX.Coord(Xx, Xy, Xz);
835   }
836   catch (Standard_Failure) {
837     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
838     SetErrorCode(aFail->GetMessageString());
839     return;
840   }
841
842   SetErrorCode(OK);
843 }
844
845 //=============================================================================
846 /*!
847  *  GetCentreOfMass
848  */
849 //=============================================================================
850 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
851                                                 (Handle(GEOM_Object) theShape)
852 {
853   SetErrorCode(KO);
854
855   if (theShape.IsNull()) return NULL;
856
857   //Add a new CentreOfMass object
858   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG);
859
860   //Add a new CentreOfMass function
861   Handle(GEOM_Function) aFunction =
862     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
863   if (aFunction.IsNull()) return NULL;
864
865   //Check if the function is set correctly
866   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
867
868   GEOMImpl_IMeasure aCI (aFunction);
869
870   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
871   if (aRefShape.IsNull()) return NULL;
872
873   aCI.SetBase(aRefShape);
874
875   //Compute the CentreOfMass value
876   try {
877 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
878     OCC_CATCH_SIGNALS;
879 #endif
880     if (!GetSolver()->ComputeFunction(aFunction)) {
881       SetErrorCode("Measure driver failed to compute centre of mass");
882       return NULL;
883     }
884   }
885   catch (Standard_Failure) {
886     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
887     SetErrorCode(aFail->GetMessageString());
888     return NULL;
889   }
890
891   //Make a Python command
892   GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
893
894   SetErrorCode(OK);
895   return aCDG;
896 }
897
898 //=============================================================================
899 /*!
900  *  GetVertexByIndex
901  */
902 //=============================================================================
903 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
904                                                 (Handle(GEOM_Object) theShape,
905                                                  Standard_Integer theIndex)
906 {
907   SetErrorCode(KO);
908
909   if (theShape.IsNull()) return NULL;
910
911   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
912   if (aRefShape.IsNull()) return NULL;
913
914   //Add a new Vertex object
915   Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GetDocID(), GEOM_POINT);
916
917   //Add a function
918   Handle(GEOM_Function) aFunction =
919     aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
920   if (aFunction.IsNull()) return NULL;
921
922   //Check if the function is set correctly
923   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
924
925   GEOMImpl_IMeasure aCI (aFunction);
926   aCI.SetBase(aRefShape);
927   aCI.SetIndex(theIndex);
928
929   //Compute
930   try {
931 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
932     OCC_CATCH_SIGNALS;
933 #endif
934     if (!GetSolver()->ComputeFunction(aFunction)) {
935       SetErrorCode("Vertex by index driver failed.");
936       return NULL;
937     }
938   }
939   catch (Standard_Failure) {
940     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
941     SetErrorCode(aFail->GetMessageString());
942     return NULL;
943   }
944
945   //Make a Python command
946   GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" << theShape << ", " << theIndex << ")";
947
948   SetErrorCode(OK);
949   return aVertex;
950 }
951
952 //=============================================================================
953 /*!
954  *  GetNormal
955  */
956 //=============================================================================
957 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
958                                          (Handle(GEOM_Object) theFace,
959                                           Handle(GEOM_Object) theOptionalPoint)
960 {
961   SetErrorCode(KO);
962
963   if (theFace.IsNull()) return NULL;
964
965   //Add a new Normale object
966   Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GetDocID(), GEOM_VECTOR);
967
968   //Add a new Normale function
969   Handle(GEOM_Function) aFunction =
970     aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
971   if (aFunction.IsNull()) return NULL;
972
973   //Check if the function is set correctly
974   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
975
976   GEOMImpl_IMeasure aCI (aFunction);
977
978   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
979   if (aFace.IsNull()) return NULL;
980
981   aCI.SetBase(aFace);
982
983   if (!theOptionalPoint.IsNull()) {
984     Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
985     aCI.SetPoint(anOptPnt);
986   }
987
988   //Compute the Normale value
989   try {
990 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
991     OCC_CATCH_SIGNALS;
992 #endif
993     if (!GetSolver()->ComputeFunction(aFunction)) {
994       SetErrorCode("Measure driver failed to compute normake of face");
995       return NULL;
996     }
997   }
998   catch (Standard_Failure) {
999     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1000     SetErrorCode(aFail->GetMessageString());
1001     return NULL;
1002   }
1003
1004   //Make a Python command
1005   GEOM::TPythonDump pd (aFunction);
1006   pd << aNorm << " = geompy.GetNormal(" << theFace;
1007   if (!theOptionalPoint.IsNull()) {
1008     pd << ", " << theOptionalPoint;
1009   }
1010   pd << ")";
1011
1012   SetErrorCode(OK);
1013   return aNorm;
1014 }
1015
1016 //=============================================================================
1017 /*!
1018  *  GetBasicProperties
1019  */
1020 //=============================================================================
1021 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
1022                                                       Standard_Real& theLength,
1023                                                       Standard_Real& theSurfArea,
1024                                                       Standard_Real& theVolume)
1025 {
1026   SetErrorCode(KO);
1027
1028   if (theShape.IsNull()) return;
1029
1030   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1031   if (aRefShape.IsNull()) return;
1032
1033   TopoDS_Shape aShape = aRefShape->GetValue();
1034   if (aShape.IsNull()) {
1035     SetErrorCode("The Objects has NULL Shape");
1036     return;
1037   }
1038
1039   //Compute the parameters
1040   GProp_GProps LProps, SProps;
1041   try {
1042 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1043     OCC_CATCH_SIGNALS;
1044 #endif
1045     BRepGProp::LinearProperties(aShape, LProps);
1046     theLength = LProps.Mass();
1047
1048     BRepGProp::SurfaceProperties(aShape, SProps);
1049     theSurfArea = SProps.Mass();
1050
1051     theVolume = 0.0;
1052     if (aShape.ShapeType() < TopAbs_SHELL) {
1053       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1054         GProp_GProps VProps;
1055         BRepGProp::VolumeProperties(Exp.Current(), VProps);
1056         theVolume += VProps.Mass();
1057       }
1058     }
1059   }
1060   catch (Standard_Failure) {
1061     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1062     SetErrorCode(aFail->GetMessageString());
1063     return;
1064   }
1065
1066   SetErrorCode(OK);
1067 }
1068
1069 //=============================================================================
1070 /*!
1071  *  GetInertia
1072  */
1073 //=============================================================================
1074 void GEOMImpl_IMeasureOperations::GetInertia
1075                    (Handle(GEOM_Object) theShape,
1076                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1077                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1078                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1079                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1080 {
1081   SetErrorCode(KO);
1082
1083   if (theShape.IsNull()) return;
1084
1085   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1086   if (aRefShape.IsNull()) return;
1087
1088   TopoDS_Shape aShape = aRefShape->GetValue();
1089   if (aShape.IsNull()) {
1090     SetErrorCode("The Objects has NULL Shape");
1091     return;
1092   }
1093
1094   //Compute the parameters
1095   GProp_GProps System;
1096
1097   try {
1098 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1099     OCC_CATCH_SIGNALS;
1100 #endif
1101     if (aShape.ShapeType() == TopAbs_VERTEX ||
1102         aShape.ShapeType() == TopAbs_EDGE ||
1103         aShape.ShapeType() == TopAbs_WIRE) {
1104       BRepGProp::LinearProperties(aShape, System);
1105     } else if (aShape.ShapeType() == TopAbs_FACE ||
1106                aShape.ShapeType() == TopAbs_SHELL) {
1107       BRepGProp::SurfaceProperties(aShape, System);
1108     } else {
1109       BRepGProp::VolumeProperties(aShape, System);
1110     }
1111     gp_Mat I = System.MatrixOfInertia();
1112
1113     I11 = I(1,1);
1114     I12 = I(1,2);
1115     I13 = I(1,3);
1116
1117     I21 = I(2,1);
1118     I22 = I(2,2);
1119     I23 = I(2,3);
1120
1121     I31 = I(3,1);
1122     I32 = I(3,2);
1123     I33 = I(3,3);
1124
1125     GProp_PrincipalProps Pr = System.PrincipalProperties();
1126     Pr.Moments(Ix,Iy,Iz);
1127   }
1128   catch (Standard_Failure) {
1129     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1130     SetErrorCode(aFail->GetMessageString());
1131     return;
1132   }
1133
1134   SetErrorCode(OK);
1135 }
1136
1137 //=============================================================================
1138 /*!
1139  *  GetBoundingBox
1140  */
1141 //=============================================================================
1142 void GEOMImpl_IMeasureOperations::GetBoundingBox
1143                                      (Handle(GEOM_Object) theShape,
1144                                       Standard_Real& Xmin, Standard_Real& Xmax,
1145                                       Standard_Real& Ymin, Standard_Real& Ymax,
1146                                       Standard_Real& Zmin, Standard_Real& Zmax)
1147 {
1148   SetErrorCode(KO);
1149
1150   if (theShape.IsNull()) return;
1151
1152   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1153   if (aRefShape.IsNull()) return;
1154
1155   TopoDS_Shape aShape = aRefShape->GetValue();
1156   if (aShape.IsNull()) {
1157     SetErrorCode("The Objects has NULL Shape");
1158     return;
1159   }
1160
1161   //Compute the parameters
1162   Bnd_Box B;
1163
1164   try {
1165 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1166     OCC_CATCH_SIGNALS;
1167 #endif
1168     BRepBndLib::Add(aShape, B);
1169     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1170   }
1171   catch (Standard_Failure) {
1172     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1173     SetErrorCode(aFail->GetMessageString());
1174     return;
1175   }
1176
1177   SetErrorCode(OK);
1178 }
1179
1180 //=============================================================================
1181 /*!
1182  *  GetTolerance
1183  */
1184 //=============================================================================
1185 void GEOMImpl_IMeasureOperations::GetTolerance
1186                                (Handle(GEOM_Object) theShape,
1187                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1188                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1189                                 Standard_Real& VertMin, Standard_Real& VertMax)
1190 {
1191   SetErrorCode(KO);
1192
1193   if (theShape.IsNull()) return;
1194
1195   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1196   if (aRefShape.IsNull()) return;
1197
1198   TopoDS_Shape aShape = aRefShape->GetValue();
1199   if (aShape.IsNull()) {
1200     SetErrorCode("The Objects has NULL Shape");
1201     return;
1202   }
1203
1204   //Compute the parameters
1205   Standard_Real T;
1206   FaceMin = EdgeMin = VertMin = RealLast();
1207   FaceMax = EdgeMax = VertMax = -RealLast();
1208
1209   try {
1210 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1211     OCC_CATCH_SIGNALS;
1212 #endif
1213     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1214       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1215       T = BRep_Tool::Tolerance(Face);
1216       if (T > FaceMax)
1217         FaceMax = T;
1218       if (T < FaceMin)
1219         FaceMin = T;
1220     }
1221     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1222       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1223       T = BRep_Tool::Tolerance(Edge);
1224       if (T > EdgeMax)
1225         EdgeMax = T;
1226       if (T < EdgeMin)
1227         EdgeMin = T;
1228     }
1229     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1230       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1231       T = BRep_Tool::Tolerance(Vertex);
1232       if (T > VertMax)
1233         VertMax = T;
1234       if (T < VertMin)
1235         VertMin = T;
1236     }
1237   }
1238   catch (Standard_Failure) {
1239     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1240     SetErrorCode(aFail->GetMessageString());
1241     return;
1242   }
1243
1244   SetErrorCode(OK);
1245 }
1246
1247 //=============================================================================
1248 /*!
1249  *  CheckShape
1250  */
1251 //=============================================================================
1252 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)      theShape,
1253                                               const Standard_Boolean   theIsCheckGeom,
1254                                               TCollection_AsciiString& theDump)
1255 {
1256   SetErrorCode(KO);
1257
1258   if (theShape.IsNull()) return false;
1259
1260   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1261   if (aRefShape.IsNull()) return false;
1262
1263   TopoDS_Shape aShape = aRefShape->GetValue();
1264   if (aShape.IsNull()) {
1265     SetErrorCode("The Objects has NULL Shape");
1266     return false;
1267   }
1268
1269   //Compute the parameters
1270   bool isValid = false;
1271   try {
1272 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1273     OCC_CATCH_SIGNALS;
1274 #endif
1275     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1276     if (ana.IsValid()) {
1277       theDump.Clear();
1278       isValid = true;
1279     } else {
1280       StructuralDump(ana, aShape, theDump);
1281     }
1282   }
1283   catch (Standard_Failure) {
1284     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1285     SetErrorCode(aFail->GetMessageString());
1286     return false;
1287   }
1288
1289   SetErrorCode(OK);
1290   return isValid;
1291 }
1292
1293 //=============================================================================
1294 /*!
1295  *  WhatIs
1296  */
1297 //=============================================================================
1298 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1299 {
1300   SetErrorCode(KO);
1301
1302   TCollection_AsciiString Astr;
1303
1304   if (theShape.IsNull()) return Astr;
1305
1306   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1307   if (aRefShape.IsNull()) return Astr;
1308
1309   TopoDS_Shape aShape = aRefShape->GetValue();
1310   if (aShape.IsNull()) {
1311     SetErrorCode("The Objects has NULL Shape");
1312     return Astr;
1313   }
1314
1315   //Compute the parameters
1316   if (aShape.ShapeType() == TopAbs_EDGE) {
1317     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1318       Astr = Astr + " It is a degenerated edge \n";
1319     }
1320   }
1321
1322   Astr = Astr + " Number of sub-shapes : \n";
1323
1324   try {
1325 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1326     OCC_CATCH_SIGNALS;
1327 #endif
1328     int iType, nbTypes [TopAbs_SHAPE];
1329     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1330       nbTypes[iType] = 0;
1331     nbTypes[aShape.ShapeType()]++;
1332
1333     TopTools_MapOfShape aMapOfShape;
1334     aMapOfShape.Add(aShape);
1335     TopTools_ListOfShape aListOfShape;
1336     aListOfShape.Append(aShape);
1337
1338     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1339     for (; itL.More(); itL.Next()) {
1340       TopoDS_Iterator it (itL.Value());
1341       for (; it.More(); it.Next()) {
1342         TopoDS_Shape s = it.Value();
1343         if (aMapOfShape.Add(s)) {
1344           aListOfShape.Append(s);
1345           nbTypes[s.ShapeType()]++;
1346         }
1347       }
1348     }
1349
1350     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1351     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1352     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1353     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1354     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1355     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1356     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1357     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1358     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
1359   }
1360   catch (Standard_Failure) {
1361     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1362     SetErrorCode(aFail->GetMessageString());
1363     return Astr;
1364   }
1365
1366   SetErrorCode(OK);
1367   return Astr;
1368 }
1369
1370
1371 //=======================================================================
1372 //function : CheckSingularCase
1373 //purpose  : auxilary for GetMinDistance()
1374 //           workaround for bugs 19899, 19908 and 19910 from Mantis
1375 //=======================================================================
1376 static double CheckSingularCase(const TopoDS_Shape& aSh1,
1377                                 const TopoDS_Shape& aSh2,
1378                                 gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
1379 {
1380   bool IsChange1 = false;
1381   double AddDist1 = 0.0;
1382   TopExp_Explorer anExp;
1383   TopoDS_Shape tmpSh1, tmpSh2;
1384   int nbf = 0;
1385   for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1386     nbf++;
1387     tmpSh1 = anExp.Current();
1388   }
1389   if(nbf==1) {
1390     TopoDS_Shape sh = aSh1;
1391     while(sh.ShapeType()==TopAbs_COMPOUND) {
1392       TopoDS_Iterator it(sh);
1393       sh = it.Value();
1394     }
1395     Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
1396     if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1397         S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1398       if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
1399         // non solid case
1400         double U1,U2,V1,V2;
1401         // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
1402         //S->Bounds(U1,U2,V1,V2); changed by
1403         ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh1),U1,U2,V1,V2);
1404         // end of changes for 020677 (dmv)
1405         Handle(Geom_RectangularTrimmedSurface) TrS1 = 
1406           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
1407         Handle(Geom_RectangularTrimmedSurface) TrS2 = 
1408           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
1409         BRep_Builder B;
1410         TopoDS_Face F1,F2;
1411         TopoDS_Compound Comp;
1412         B.MakeCompound(Comp);
1413         B.MakeFace(F1,TrS1,1.e-7);
1414         B.Add(Comp,F1);
1415         B.MakeFace(F2,TrS2,1.e-7);
1416         B.Add(Comp,F2);
1417         Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
1418         sfs->Init(Comp);
1419         sfs->SetPrecision(1.e-6);
1420         sfs->SetMaxTolerance(1.0);
1421         sfs->Perform();
1422         tmpSh1 = sfs->Shape();
1423         IsChange1 = true;
1424       }
1425       else {
1426         if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
1427           Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
1428           gp_Pnt PC = SS->Location();
1429           BRep_Builder B;
1430           TopoDS_Vertex V;
1431           B.MakeVertex(V,PC,1.e-7);
1432           tmpSh1 = V;
1433           AddDist1 = SS->Radius();
1434           IsChange1 = true;
1435         }
1436         else {
1437           Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
1438           gp_Ax3 ax3 = TS->Position();
1439           Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
1440           BRep_Builder B;
1441           TopoDS_Edge E;
1442           B.MakeEdge(E,C,1.e-7);
1443           tmpSh1 = E;
1444           AddDist1 = TS->MinorRadius();
1445           IsChange1 = true;
1446         }
1447       }
1448     }
1449     else
1450       tmpSh1 = aSh1;
1451   }
1452   else
1453     tmpSh1 = aSh1;
1454   bool IsChange2 = false;
1455   double AddDist2 = 0.0;
1456   nbf = 0;
1457   for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1458     nbf++;
1459     tmpSh2 = anExp.Current();
1460   }
1461   if(nbf==1) {
1462     TopoDS_Shape sh = aSh2;
1463     while(sh.ShapeType()==TopAbs_COMPOUND) {
1464       TopoDS_Iterator it(sh);
1465       sh = it.Value();
1466     }
1467     Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
1468     if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1469         S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1470       if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
1471         // non solid case
1472         double U1,U2,V1,V2;
1473         S->Bounds(U1,U2,V1,V2);
1474         Handle(Geom_RectangularTrimmedSurface) TrS1 = 
1475           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
1476         Handle(Geom_RectangularTrimmedSurface) TrS2 = 
1477           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
1478         BRep_Builder B;
1479         TopoDS_Face F1,F2;
1480         TopoDS_Compound Comp;
1481         B.MakeCompound(Comp);
1482         B.MakeFace(F1,TrS1,1.e-7);
1483         B.Add(Comp,F1);
1484         B.MakeFace(F2,TrS2,1.e-7);
1485         B.Add(Comp,F2);
1486         Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
1487         sfs->Init(Comp);
1488         sfs->SetPrecision(1.e-6);
1489         sfs->SetMaxTolerance(1.0);
1490         sfs->Perform();
1491         tmpSh2 = sfs->Shape();
1492         IsChange2 = true;
1493       }
1494       else {
1495         if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
1496           Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
1497           gp_Pnt PC = SS->Location();
1498           BRep_Builder B;
1499           TopoDS_Vertex V;
1500           B.MakeVertex(V,PC,1.e-7);
1501           tmpSh2 = V;
1502           AddDist2 = SS->Radius();
1503           IsChange2 = true;
1504         }
1505         else if( S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1506           Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
1507           gp_Ax3 ax3 = TS->Position();
1508           Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
1509           BRep_Builder B;
1510           TopoDS_Edge E;
1511           B.MakeEdge(E,C,1.e-7);
1512           tmpSh2 = E;
1513           AddDist2 = TS->MinorRadius();
1514           IsChange2 = true;
1515         }
1516       }
1517     }
1518     else
1519       tmpSh2 = aSh2;
1520   }
1521   else
1522     tmpSh2 = aSh2;
1523
1524   if( !IsChange1 && !IsChange2 )
1525     return -2.0;
1526
1527   BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
1528   if (dst.IsDone()) {
1529     double MinDist = 1.e9;
1530     gp_Pnt PMin1, PMin2, P1, P2;
1531     for (int i = 1; i <= dst.NbSolution(); i++) {
1532       P1 = dst.PointOnShape1(i);
1533       P2 = dst.PointOnShape2(i);
1534       Standard_Real Dist = P1.Distance(P2);
1535       if (MinDist > Dist) {
1536         MinDist = Dist;
1537         PMin1 = P1;
1538         PMin2 = P2;
1539       }
1540     }
1541     if(MinDist<1.e-7) {
1542       Ptmp1 = PMin1;
1543       Ptmp2 = PMin2;
1544     }
1545     else {
1546       gp_Dir aDir(gp_Vec(PMin1,PMin2));
1547       if( MinDist > (AddDist1+AddDist2) ) {
1548         Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
1549                         PMin1.Y() + aDir.Y()*AddDist1,
1550                         PMin1.Z() + aDir.Z()*AddDist1 );
1551         Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
1552                         PMin2.Y() - aDir.Y()*AddDist2,
1553                         PMin2.Z() - aDir.Z()*AddDist2 );
1554         return (MinDist - AddDist1 - AddDist2);
1555       }
1556       else {
1557         if( AddDist1 > 0 ) {
1558           Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
1559                           PMin1.Y() + aDir.Y()*AddDist1,
1560                           PMin1.Z() + aDir.Z()*AddDist1 );
1561           Ptmp2 = Ptmp1;
1562         }
1563         else {
1564           Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
1565                           PMin2.Y() - aDir.Y()*AddDist2,
1566                           PMin2.Z() - aDir.Z()*AddDist2 );
1567           Ptmp1 = Ptmp2;
1568         }
1569       }
1570     }
1571     double res = MinDist - AddDist1 - AddDist2;
1572     if(res<0.) res = 0.0;
1573     return res;
1574   }
1575   return -2.0;
1576 }
1577 /* old variant
1578 static bool CheckSingularCase(const TopoDS_Shape& aSh1,
1579                               const TopoDS_Shape& aSh2,
1580                               gp_Pnt& Ptmp)
1581 {
1582   TopExp_Explorer anExp;
1583   TopoDS_Shape tmpSh1, tmpSh2;
1584   int nbf = 0;
1585   for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1586     nbf++;
1587     tmpSh1 = anExp.Current();
1588   }
1589   if(nbf==1) {
1590     Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
1591     if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1592         S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1593       nbf = 0;
1594       for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1595         nbf++;
1596         tmpSh2 = anExp.Current();
1597         Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
1598         GeomAPI_IntSS ISS(S1,S2,1.e-7);
1599         if(ISS.IsDone()) {
1600           for(int i=1; i<=ISS.NbLines(); i++) {
1601             Handle(Geom_Curve) C3d = ISS.Line(i);
1602             BRep_Builder B;
1603             TopoDS_Edge E;
1604             B.MakeEdge(E,C3d,1.e-7);
1605             BRepExtrema_DistShapeShape dst(tmpSh2,E);
1606             if (dst.IsDone()) {
1607               gp_Pnt PMin1, PMin2, P1, P2;
1608               double MinDist = 1.e9;
1609               for (int i = 1; i <= dst.NbSolution(); i++) {
1610                 P1 = dst.PointOnShape1(i);
1611                 P2 = dst.PointOnShape2(i);
1612                 Standard_Real Dist = P1.Distance(P2);
1613                 if (MinDist > Dist) {
1614                   MinDist = Dist;
1615                   Ptmp = P1;
1616                 }
1617               }
1618               if(MinDist<1.e-7)
1619                 return true;
1620             }
1621           }
1622         }
1623       }
1624     }
1625   }
1626   nbf = 0;
1627   for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1628     nbf++;
1629     tmpSh1 = anExp.Current();
1630   }
1631   if(nbf==1) {
1632     Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
1633     if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1634         S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1635       nbf = 0;
1636       for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1637         nbf++;
1638         tmpSh2 = anExp.Current();
1639         Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
1640         GeomAPI_IntSS ISS(S1,S2,1.e-7);
1641         if(ISS.IsDone()) {
1642           for(int i=1; i<=ISS.NbLines(); i++) {
1643             Handle(Geom_Curve) C3d = ISS.Line(i);
1644             BRep_Builder B;
1645             TopoDS_Edge E;
1646             B.MakeEdge(E,C3d,1.e-7);
1647             BRepExtrema_DistShapeShape dst(tmpSh2,E);
1648             if (dst.IsDone()) {
1649               gp_Pnt P1,P2;
1650               double MinDist = 1.e9;
1651               for (int i = 1; i <= dst.NbSolution(); i++) {
1652                 P1 = dst.PointOnShape1(i);
1653                 P2 = dst.PointOnShape2(i);
1654                 Standard_Real Dist = P1.Distance(P2);
1655                 if (MinDist > Dist) {
1656                   MinDist = Dist;
1657                   Ptmp = P1;
1658                 }
1659               }
1660               if(MinDist<1.e-7)
1661                 return true;
1662             }
1663           }
1664         }
1665       }
1666     }
1667   }
1668   return false;
1669 }
1670 */
1671
1672
1673 //=============================================================================
1674 /*!
1675  *  GetMinDistance
1676  */
1677 //=============================================================================
1678 Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
1679   (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1680    Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1,
1681    Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2)
1682 {
1683   SetErrorCode(KO);
1684   Standard_Real MinDist = 1.e9;
1685
1686   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
1687
1688   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1689   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1690   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
1691
1692   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1693   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1694   if (aShape1.IsNull() || aShape2.IsNull()) {
1695     SetErrorCode("One of Objects has NULL Shape");
1696     return MinDist;
1697   }
1698
1699   //Compute the parameters
1700   try {
1701 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1702     OCC_CATCH_SIGNALS;
1703 #endif
1704
1705     // Issue 0020231: A min distance bug with torus and vertex.
1706     // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
1707
1708     // which of shapes consists of only one vertex?
1709     TopExp_Explorer exp1(aShape1,TopAbs_VERTEX), exp2(aShape2,TopAbs_VERTEX);
1710     TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
1711     TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
1712     exp1.Next(); exp2.Next();
1713     if ( exp1.More() ) V1.Nullify();
1714     if ( exp2.More() ) V2.Nullify();
1715     // vertex and container of solids
1716     TopoDS_Shape V = V1.IsNull() ? V2 : V1;
1717     TopoDS_Shape S = V1.IsNull() ? aShape1 : aShape2;
1718     if ( !V.IsNull() ) {
1719       // classify vertex against solids
1720       gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
1721       for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
1722         BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
1723         if ( classifier.State() == TopAbs_IN ) {
1724           p.Coord(X1, Y1, Z1);
1725           p.Coord(X2, Y2, Z2);
1726           SetErrorCode(OK);
1727           return 0.0;
1728         }
1729       }
1730     }
1731     // End Issue 0020231
1732
1733     // skl 30.06.2008
1734     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
1735     gp_Pnt Ptmp1, Ptmp2;
1736     double dist = CheckSingularCase(aShape1, aShape2, Ptmp1, Ptmp2);
1737     if(dist>-1.0) {
1738       Ptmp1.Coord(X1, Y1, Z1);
1739       Ptmp2.Coord(X2, Y2, Z2);
1740       SetErrorCode(OK);
1741       return dist;
1742     }
1743
1744     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
1745     if (dst.IsDone()) {
1746       gp_Pnt PMin1, PMin2, P1, P2;
1747
1748       for (int i = 1; i <= dst.NbSolution(); i++) {
1749         P1 = dst.PointOnShape1(i);
1750         P2 = dst.PointOnShape2(i);
1751
1752         Standard_Real Dist = P1.Distance(P2);
1753         if (MinDist > Dist) {
1754           MinDist = Dist;
1755           PMin1 = P1;
1756           PMin2 = P2;
1757         }
1758       }
1759
1760       PMin1.Coord(X1, Y1, Z1);
1761       PMin2.Coord(X2, Y2, Z2);
1762     }
1763   }
1764   catch (Standard_Failure) {
1765     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1766     SetErrorCode(aFail->GetMessageString());
1767     return MinDist;
1768   }
1769
1770   SetErrorCode(OK);
1771   return MinDist;
1772 }
1773
1774 //=======================================================================
1775 /*!
1776  *  Get coordinates of point
1777  */
1778 //=======================================================================
1779 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
1780                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
1781 {
1782   SetErrorCode(KO);
1783
1784   if (theShape.IsNull())
1785     return;
1786
1787   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1788   if (aRefShape.IsNull())
1789     return;
1790
1791   TopoDS_Shape aShape = aRefShape->GetValue();
1792   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
1793   {
1794     SetErrorCode( "Shape must be a vertex" );
1795     return;
1796   }
1797
1798   try {
1799 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1800     OCC_CATCH_SIGNALS;
1801 #endif
1802     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
1803     theX = aPnt.X();
1804     theY = aPnt.Y();
1805     theZ = aPnt.Z();
1806
1807     SetErrorCode(OK);
1808   }
1809   catch (Standard_Failure)
1810   {
1811     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1812     SetErrorCode( aFail->GetMessageString() );
1813   }
1814 }
1815
1816 //=======================================================================
1817 /*!
1818  *  Compute angle (in degrees) between two lines
1819  */
1820 //=======================================================================
1821 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
1822                                                      Handle(GEOM_Object) theLine2)
1823 {
1824   SetErrorCode(KO);
1825
1826   Standard_Real anAngle = -1.0;
1827
1828   if (theLine1.IsNull() || theLine2.IsNull())
1829     return anAngle;
1830
1831   Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
1832   Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
1833   if (aRefLine1.IsNull() || aRefLine2.IsNull())
1834     return anAngle;
1835
1836   TopoDS_Shape aLine1 = aRefLine1->GetValue();
1837   TopoDS_Shape aLine2 = aRefLine2->GetValue();
1838   if (aLine1.IsNull() || aLine2.IsNull() ||
1839       aLine1.ShapeType() != TopAbs_EDGE ||
1840       aLine2.ShapeType() != TopAbs_EDGE)
1841   {
1842     SetErrorCode("Two edges must be given");
1843     return anAngle;
1844   }
1845
1846   try {
1847 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1848     OCC_CATCH_SIGNALS;
1849 #endif
1850     TopoDS_Edge E1 = TopoDS::Edge(aLine1);
1851     TopoDS_Edge E2 = TopoDS::Edge(aLine2);
1852
1853     double fp,lp;
1854     Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
1855     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
1856
1857     if ( C1.IsNull() || C2.IsNull() ||
1858         !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
1859         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
1860     {
1861       SetErrorCode("The edges must be linear");
1862       return anAngle;
1863     }
1864
1865     Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
1866     Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
1867
1868     gp_Lin aLin1 = L1->Lin();
1869     gp_Lin aLin2 = L2->Lin();
1870
1871     anAngle = aLin1.Angle(aLin2);
1872     anAngle /= PI180; // convert radians into degrees
1873
1874     SetErrorCode(OK);
1875   }
1876   catch (Standard_Failure)
1877   {
1878     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1879     SetErrorCode(aFail->GetMessageString());
1880   }
1881
1882   return anAngle;
1883 }
1884
1885
1886 //=============================================================================
1887 /*!
1888  *  CurveCurvatureByParam
1889  */
1890 //=============================================================================
1891 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
1892                         (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
1893 {
1894   SetErrorCode(KO);
1895   Standard_Real aRes = -1.0;
1896
1897   if(theCurve.IsNull()) return aRes;
1898
1899   Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
1900   if(aRefShape.IsNull()) return aRes;
1901
1902   TopoDS_Shape aShape = aRefShape->GetValue();
1903   if(aShape.IsNull()) {
1904     SetErrorCode("One of Objects has NULL Shape");
1905     return aRes;
1906   }
1907
1908   Standard_Real aFP, aLP, aP;
1909   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
1910   aP = aFP + (aLP - aFP) * theParam;
1911
1912   if(aCurve.IsNull()) return aRes;
1913
1914   //Compute curvature
1915   try {
1916 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1917     OCC_CATCH_SIGNALS;
1918 #endif
1919     GeomLProp_CLProps Prop = GeomLProp_CLProps 
1920       (aCurve, aP, 2, Precision::Confusion());
1921     aRes = fabs(Prop.Curvature());
1922     SetErrorCode(OK);
1923   }
1924   catch (Standard_Failure) {
1925     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1926     SetErrorCode(aFail->GetMessageString());
1927     return aRes;
1928   }
1929
1930   if( aRes > Precision::Confusion() )
1931     aRes = 1/aRes;
1932   else
1933     aRes = RealLast();
1934   
1935   return aRes;
1936 }
1937
1938
1939 //=============================================================================
1940 /*!
1941  *  CurveCurvatureByPoint
1942  */
1943 //=============================================================================
1944 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
1945                    (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
1946 {
1947   SetErrorCode(KO);
1948   Standard_Real aRes = -1.0;
1949
1950   if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
1951
1952   Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
1953   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
1954   if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
1955
1956   TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
1957   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
1958   if( anEdge.IsNull() || aPnt.IsNull() ) {
1959     SetErrorCode("One of Objects has NULL Shape");
1960     return aRes;
1961   }
1962
1963   Standard_Real aFP, aLP;
1964   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
1965   if(aCurve.IsNull()) return aRes;
1966   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
1967
1968   //Compute curvature
1969   try {
1970 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1971     OCC_CATCH_SIGNALS;
1972 #endif
1973     GeomAPI_ProjectPointOnCurve PPC(aPoint, aCurve, aFP, aLP);
1974     if(PPC.NbPoints()>0) {
1975       GeomLProp_CLProps Prop = GeomLProp_CLProps 
1976         (aCurve, PPC.LowerDistanceParameter(), 2, Precision::Confusion());
1977       aRes = fabs(Prop.Curvature());
1978       SetErrorCode(OK);
1979     }
1980   }
1981   catch (Standard_Failure) {
1982     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1983     SetErrorCode(aFail->GetMessageString());
1984     return aRes;
1985   }
1986
1987   if( aRes > Precision::Confusion() )
1988     aRes = 1/aRes;
1989   else
1990     aRes = RealLast();
1991   
1992   return aRes;
1993 }
1994
1995
1996 //=============================================================================
1997 /*!
1998  *  getSurfaceCurvatures
1999  */
2000 //=============================================================================
2001 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2002                                           (const Handle(Geom_Surface)& aSurf,
2003                                            Standard_Real theUParam,
2004                                            Standard_Real theVParam,
2005                                            Standard_Boolean theNeedMaxCurv)
2006 {
2007   SetErrorCode(KO);
2008   Standard_Real aRes = 1.0;
2009
2010   if (aSurf.IsNull()) return aRes;
2011
2012   try {
2013 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2014     OCC_CATCH_SIGNALS;
2015 #endif
2016     GeomLProp_SLProps Prop = GeomLProp_SLProps 
2017       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2018     if(Prop.IsCurvatureDefined()) {
2019       if(Prop.IsUmbilic()) {
2020         //cout<<"is umbilic"<<endl;
2021         aRes = fabs(Prop.MeanCurvature());
2022       }
2023       else {
2024         //cout<<"is not umbilic"<<endl;
2025         double c1 = fabs(Prop.MaxCurvature());
2026         double c2 = fabs(Prop.MinCurvature());
2027         if(theNeedMaxCurv)
2028           aRes = Max(c1,c2);
2029         else
2030           aRes = Min(c1,c2);
2031       }
2032       SetErrorCode(OK);
2033     }
2034   }
2035   catch (Standard_Failure) {
2036     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2037     SetErrorCode(aFail->GetMessageString());
2038     return aRes;
2039   }
2040
2041   if( fabs(aRes) > Precision::Confusion() )
2042     aRes = 1/aRes;
2043   else
2044     aRes = RealLast();
2045   
2046   return aRes;
2047 }
2048
2049
2050 //=============================================================================
2051 /*!
2052  *  MaxSurfaceCurvatureByParam
2053  */
2054 //=============================================================================
2055 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2056                                                   (Handle(GEOM_Object) theSurf,
2057                                                    Standard_Real& theUParam,
2058                                                    Standard_Real& theVParam)
2059 {
2060   SetErrorCode(KO);
2061   Standard_Real aRes = -1.0;
2062
2063   if (theSurf.IsNull()) return aRes;
2064
2065   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2066   if(aRefShape.IsNull()) return aRes;
2067
2068   TopoDS_Shape aShape = aRefShape->GetValue();
2069   if(aShape.IsNull()) {
2070     SetErrorCode("One of Objects has NULL Shape");
2071     return aRes;
2072   }
2073
2074   TopoDS_Face F = TopoDS::Face(aShape);
2075   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2076
2077   //Compute the parameters
2078   Standard_Real U1,U2,V1,V2;
2079   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2080   Standard_Real U = U1 + (U2-U1)*theUParam;
2081   Standard_Real V = V1 + (V2-V1)*theVParam;
2082   
2083   return getSurfaceCurvatures(aSurf, U, V, true);
2084 }
2085
2086
2087 //=============================================================================
2088 /*!
2089  *  MaxSurfaceCurvatureByPoint
2090  */
2091 //=============================================================================
2092 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2093                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2094 {
2095   SetErrorCode(KO);
2096   Standard_Real aRes = -1.0;
2097
2098   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2099
2100   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2101   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2102   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2103
2104   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2105   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2106   if( aFace.IsNull() || aPnt.IsNull() ) {
2107     SetErrorCode("One of Objects has NULL Shape");
2108     return 0;
2109   }
2110
2111   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2112   if(aSurf.IsNull()) return aRes;
2113   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2114
2115   //Compute the parameters
2116   ShapeAnalysis_Surface sas(aSurf);
2117   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2118
2119   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2120 }
2121
2122
2123 //=============================================================================
2124 /*!
2125  *  MinSurfaceCurvatureByParam
2126  */
2127 //=============================================================================
2128 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2129                                                   (Handle(GEOM_Object) theSurf,
2130                                                    Standard_Real& theUParam,
2131                                                    Standard_Real& theVParam)
2132 {
2133   SetErrorCode(KO);
2134   Standard_Real aRes = -1.0;
2135
2136   if (theSurf.IsNull()) return aRes;
2137
2138   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2139   if(aRefShape.IsNull()) return aRes;
2140
2141   TopoDS_Shape aShape = aRefShape->GetValue();
2142   if(aShape.IsNull()) {
2143     SetErrorCode("One of Objects has NULL Shape");
2144     return aRes;
2145   }
2146
2147   TopoDS_Face F = TopoDS::Face(aShape);
2148   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2149
2150   //Compute the parameters
2151   Standard_Real U1,U2,V1,V2;
2152   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2153   Standard_Real U = U1 + (U2-U1)*theUParam;
2154   Standard_Real V = V1 + (V2-V1)*theVParam;
2155   
2156   return getSurfaceCurvatures(aSurf, U, V, false);
2157 }
2158
2159
2160 //=============================================================================
2161 /*!
2162  *  MinSurfaceCurvatureByPoint
2163  */
2164 //=============================================================================
2165 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2166                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2167 {
2168   SetErrorCode(KO);
2169   Standard_Real aRes = -1.0;
2170
2171   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2172
2173   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2174   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2175   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2176
2177   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2178   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2179   if( aFace.IsNull() || aPnt.IsNull() ) {
2180     SetErrorCode("One of Objects has NULL Shape");
2181     return 0;
2182   }
2183
2184   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2185   if(aSurf.IsNull()) return aRes;
2186   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2187
2188   //Compute the parameters
2189   ShapeAnalysis_Surface sas(aSurf);
2190   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2191
2192   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2193 }
2194
2195
2196 //=======================================================================
2197 //function : StructuralDump
2198 //purpose  : Structural (data exchange) style of output.
2199 //=======================================================================
2200 void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna,
2201                                                   const TopoDS_Shape&       theShape,
2202                                                   TCollection_AsciiString&  theDump)
2203 {
2204   Standard_Integer i;
2205   theDump.Clear();
2206   theDump += " -- The Shape has problems :\n";
2207   theDump += "  Check                                    Count\n";
2208   theDump += " ------------------------------------------------\n";
2209
2210   Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail;
2211   Handle(TColStd_HArray1OfInteger) NbProblems =
2212     new TColStd_HArray1OfInteger(1, last_stat);
2213   for (i = 1; i <= last_stat; i++)
2214     NbProblems->SetValue(i,0);
2215
2216   Handle(TopTools_HSequenceOfShape) sl;
2217   sl = new TopTools_HSequenceOfShape();
2218   TopTools_DataMapOfShapeListOfShape theMap;
2219   theMap.Clear();
2220   GetProblemShapes(theAna, theShape, sl, NbProblems, theMap);
2221   theMap.Clear();
2222
2223   Standard_Integer count = 0;
2224   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve);
2225   if (count > 0) {
2226     theDump += "  Invalid Point on Curve ................... ";
2227     theDump += TCollection_AsciiString(count) + "\n";
2228   }
2229   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface);
2230   if (count > 0) {
2231     theDump += "  Invalid Point on CurveOnSurface .......... ";
2232     theDump += TCollection_AsciiString(count) + "\n";
2233   }
2234   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface);
2235   if (count > 0) {
2236     theDump += "  Invalid Point on Surface ................. ";
2237     theDump += TCollection_AsciiString(count) + "\n";
2238   }
2239   count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve);
2240   if (count > 0) {
2241     theDump += "  No 3D Curve .............................. ";
2242     theDump += TCollection_AsciiString(count) + "\n";
2243   }
2244   count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve);
2245   if (count > 0) {
2246     theDump += "  Multiple 3D Curve ........................ ";
2247     theDump += TCollection_AsciiString(count) + "\n";
2248   }
2249   count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve);
2250   if (count > 0) {
2251     theDump += "  Invalid 3D Curve ......................... ";
2252     theDump += TCollection_AsciiString(count) + "\n";
2253   }
2254   count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface);
2255   if (count > 0) {
2256     theDump += "  No Curve on Surface ...................... ";
2257     theDump += TCollection_AsciiString(count) + "\n";
2258   }
2259   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface);
2260   if (count > 0) {
2261     theDump += "  Invalid Curve on Surface ................. ";
2262     theDump += TCollection_AsciiString(count) + "\n";
2263   }
2264   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface);
2265   if (count > 0) {
2266     theDump += "  Invalid Curve on closed Surface .......... ";
2267     theDump += TCollection_AsciiString(count) + "\n";
2268   }
2269   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag);
2270   if (count > 0) {
2271     theDump += "  Invalid SameRange Flag ................... ";
2272     theDump += TCollection_AsciiString(count) + "\n";
2273   }
2274   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag);
2275   if (count > 0) {
2276     theDump += "  Invalid SameParameter Flag ............... ";
2277     theDump += TCollection_AsciiString(count) + "\n";
2278   }
2279   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag);
2280   if (count > 0) {
2281     theDump += "  Invalid Degenerated Flag ................. ";
2282     theDump += TCollection_AsciiString(count) + "\n";
2283   }
2284   count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge);
2285   if (count > 0) {
2286     theDump += "  Free Edge ................................ ";
2287     theDump += TCollection_AsciiString(count) + "\n";
2288   }
2289   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity);
2290   if (count > 0) {
2291     theDump += "  Invalid MultiConnexity ................... ";
2292     theDump += TCollection_AsciiString(count) + "\n";
2293   }
2294   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange);
2295   if (count > 0) {
2296     theDump += "  Invalid Range ............................ ";
2297     theDump += TCollection_AsciiString(count) + "\n";
2298   }
2299   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire);
2300   if (count > 0) {
2301     theDump += "  Empty Wire ............................... ";
2302     theDump += TCollection_AsciiString(count) + "\n";
2303   }
2304   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge);
2305   if (count > 0) {
2306     theDump += "  Redundant Edge ........................... ";
2307     theDump += TCollection_AsciiString(count) + "\n";
2308   }
2309   count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire);
2310   if (count > 0) {
2311     theDump += "  Self Intersecting Wire ................... ";
2312     theDump += TCollection_AsciiString(count) + "\n";
2313   }
2314   count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface);
2315   if (count > 0) {
2316     theDump += "  No Surface ............................... ";
2317     theDump += TCollection_AsciiString(count) + "\n";
2318   }
2319   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire);
2320   if (count > 0) {
2321     theDump += "  Invalid Wire ............................. ";
2322     theDump += TCollection_AsciiString(count) + "\n";
2323   }
2324   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire);
2325   if (count > 0) {
2326     theDump += "  Redundant Wire ........................... ";
2327     theDump += TCollection_AsciiString(count) + "\n";
2328   }
2329   count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires);
2330   if (count > 0) {
2331     theDump += "  Intersecting Wires ....................... ";
2332     theDump += TCollection_AsciiString(count) + "\n";
2333   }
2334   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires);
2335   if (count > 0) {
2336     theDump += "  Invalid Imbrication of Wires ............. ";
2337     theDump += TCollection_AsciiString(count) + "\n";
2338   }
2339   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell);
2340   if (count > 0) {
2341     theDump += "  Empty Shell .............................. ";
2342     theDump += TCollection_AsciiString(count) + "\n";
2343   }
2344   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace);
2345   if (count > 0) {
2346     theDump += "  Redundant Face ........................... ";
2347     theDump += TCollection_AsciiString(count) + "\n";
2348   }
2349   count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape);
2350   if (count > 0) {
2351     theDump += "  Unorientable Shape ....................... ";
2352     theDump += TCollection_AsciiString(count) + "\n";
2353   }
2354   count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed);
2355   if (count > 0) {
2356     theDump += "  Not Closed ............................... ";
2357     theDump += TCollection_AsciiString(count) + "\n";
2358   }
2359   count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected);
2360   if (count > 0) {
2361     theDump += "  Not Connected ............................ ";
2362     theDump += TCollection_AsciiString(count) + "\n";
2363   }
2364   count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape);
2365   if (count > 0) {
2366     theDump += "  Subshape not in Shape .................... ";
2367     theDump += TCollection_AsciiString(count) + "\n";
2368   }
2369   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation);
2370   if (count > 0) {
2371     theDump += "  Bad Orientation .......................... ";
2372     theDump += TCollection_AsciiString(count) + "\n";
2373   }
2374   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape);
2375   if (count > 0) {
2376     theDump += "  Bad Orientation of Subshape .............. ";
2377     theDump += TCollection_AsciiString(count) + "\n";
2378   }
2379   count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail);
2380   if (count > 0) {
2381     theDump += "  checkshape failure ....................... ";
2382     theDump += TCollection_AsciiString(count) + "\n";
2383   }
2384
2385   theDump += " ------------------------------------------------\n";
2386   theDump += "*** Shapes with problems : ";
2387   theDump += TCollection_AsciiString(sl->Length()) + "\n";
2388
2389   Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
2390   nbv = nbe = nbw = nbf = nbs = nbo = 0;
2391
2392   for (i = 1; i <= sl->Length(); i++) {
2393     TopoDS_Shape shi = sl->Value(i);
2394     TopAbs_ShapeEnum sti = shi.ShapeType();
2395     switch (sti) {
2396       case TopAbs_VERTEX : nbv++; break;
2397       case TopAbs_EDGE   : nbe++; break;
2398       case TopAbs_WIRE   : nbw++; break;
2399       case TopAbs_FACE   : nbf++; break;
2400       case TopAbs_SHELL  : nbs++; break;
2401       case TopAbs_SOLID  : nbo++; break;
2402       default            : break;
2403     }
2404   }
2405
2406   if (nbv > 0) {
2407     theDump += "VERTEX : ";
2408     if (nbv < 10) theDump += " ";
2409     theDump += TCollection_AsciiString(nbv) + "\n";
2410   }
2411   if (nbe > 0) {
2412     theDump += "EDGE   : ";
2413     if (nbe < 10) theDump += " ";
2414     theDump += TCollection_AsciiString(nbe) + "\n";
2415   }
2416   if (nbw > 0) {
2417     theDump += "WIRE   : ";
2418     if (nbw < 10) theDump += " ";
2419     theDump += TCollection_AsciiString(nbw) + "\n";
2420   }
2421   if (nbf > 0) {
2422     theDump += "FACE   : ";
2423     if (nbf < 10) theDump += " ";
2424     theDump += TCollection_AsciiString(nbf) + "\n";
2425   }
2426   if (nbs > 0) {
2427     theDump += "SHELL  : ";
2428     if (nbs < 10) theDump += " ";
2429     theDump += TCollection_AsciiString(nbs) + "\n";
2430   }
2431   if (nbo > 0) {
2432     theDump += "SOLID  : ";
2433     if (nbo < 10) theDump += " ";
2434     theDump += TCollection_AsciiString(nbo) + "\n";
2435   }
2436 }
2437
2438
2439 //=======================================================================
2440 //function : GetProblemShapes
2441 // purpose : for StructuralDump
2442 //=======================================================================
2443 void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer&           theAna,
2444                                                     const TopoDS_Shape&                 theShape,
2445                                                     Handle(TopTools_HSequenceOfShape)&  sl,
2446                                                     Handle(TColStd_HArray1OfInteger)&   NbProblems,
2447                                                     TopTools_DataMapOfShapeListOfShape& theMap)
2448 {
2449   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
2450     GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap);
2451   }
2452   TopAbs_ShapeEnum styp = theShape.ShapeType();
2453   BRepCheck_ListIteratorOfListOfStatus itl;
2454   TopTools_ListOfShape empty;
2455   if (!theMap.IsBound(theShape)) {
2456     theMap.Bind(theShape,empty);
2457
2458     if (!theAna.Result(theShape).IsNull()) {
2459       itl.Initialize(theAna.Result(theShape)->Status());
2460       // !!! May be, we have to print all the problems, not only the first one ?
2461       if (itl.Value() != BRepCheck_NoError) {
2462         sl->Append(theShape);
2463         BRepCheck_Status stat = itl.Value();
2464         NbProblems->SetValue((Standard_Integer)stat,
2465                              NbProblems->Value((Standard_Integer)stat) + 1);
2466       }
2467     }
2468   }
2469
2470   switch (styp) {
2471   case TopAbs_EDGE:
2472     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
2473     break;
2474   case TopAbs_FACE:
2475     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap);
2476     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap);
2477     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
2478     break;
2479   case TopAbs_SHELL:
2480     break;
2481   case TopAbs_SOLID:
2482     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap);
2483     break;
2484   default:
2485     break;
2486   }
2487 }
2488
2489 //=======================================================================
2490 //function : Contains
2491 //=======================================================================
2492 static Standard_Boolean Contains (const TopTools_ListOfShape& L,
2493                                   const TopoDS_Shape& S)
2494 {
2495   TopTools_ListIteratorOfListOfShape it;
2496   for (it.Initialize(L); it.More(); it.Next()) {
2497     if (it.Value().IsSame(S)) {
2498       return Standard_True;
2499     }
2500   }
2501   return Standard_False;
2502 }
2503
2504 //=======================================================================
2505 //function : GetProblemSub
2506 // purpose : for StructuralDump
2507 //=======================================================================
2508 void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&           theAna,
2509                                                  const TopoDS_Shape&                 theShape,
2510                                                  Handle(TopTools_HSequenceOfShape)&  sl,
2511                                                  Handle(TColStd_HArray1OfInteger)&   NbProblems,
2512                                                  const TopAbs_ShapeEnum              Subtype,
2513                                                  TopTools_DataMapOfShapeListOfShape& theMap)
2514 {
2515   BRepCheck_ListIteratorOfListOfStatus itl;
2516   TopExp_Explorer exp;
2517   for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) {
2518     const TopoDS_Shape& sub = exp.Current();
2519
2520     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
2521     for (res->InitContextIterator();
2522          res->MoreShapeInContext();
2523          res->NextShapeInContext()) {
2524       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
2525         theMap(sub).Append(theShape);
2526         itl.Initialize(res->StatusOnShape());
2527
2528         if (itl.Value() != BRepCheck_NoError) {
2529           Standard_Integer ii = 0;
2530
2531           for (ii = 1; ii <= sl->Length(); ii++)
2532             if (sl->Value(ii).IsSame(sub)) break;
2533
2534           if (ii > sl->Length()) {
2535             sl->Append(sub);
2536             BRepCheck_Status stat = itl.Value();
2537             NbProblems->SetValue((Standard_Integer)stat,
2538                                  NbProblems->Value((Standard_Integer)stat) + 1);
2539           }
2540           for (ii = 1; ii <= sl->Length(); ii++)
2541             if (sl->Value(ii).IsSame(theShape)) break;
2542           if (ii > sl->Length()) {
2543             sl->Append(theShape);
2544             BRepCheck_Status stat = itl.Value();
2545             NbProblems->SetValue((Standard_Integer)stat,
2546                                  NbProblems->Value((Standard_Integer)stat) + 1);
2547           }
2548         }
2549         break;
2550       }
2551     }
2552   }
2553 }