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