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