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