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