Salome HOME
updated copyright message
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 // Copyright (C) 2007-2023  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 <GEOMImpl_IMeasureOperations.hxx>
24 #include <GEOMImpl_IMeasure.hxx>
25 #include <GEOMImpl_MeasureDriver.hxx>
26
27 #include <GEOMImpl_IPatchFace.hxx>
28 #include <GEOMImpl_IProximity.hxx>
29 #include <GEOMImpl_PatchFaceDriver.hxx>
30 #include <GEOMImpl_ShapeProximityDriver.hxx>
31
32 #include <GEOMImpl_Types.hxx>
33
34 #include <GEOMImpl_IConformity.hxx>
35 #include <GEOMImpl_ConformityDriver.hxx>
36
37 #include <GEOMUtils.hxx>
38
39 #include <GEOMAlgo_AlgoTools.hxx>
40 #include <GEOMAlgo_KindOfName.hxx>
41 #include <GEOMAlgo_ShapeInfoFiller.hxx>
42
43 #include <GEOM_PythonDump.hxx>
44
45 #include <utilities.h>
46
47 // OCCT Includes
48 #include <Bnd_Box.hxx>
49 #include <BOPAlgo_CheckerSI.hxx>
50 #include <TopTools_ListOfShape.hxx>
51 #include <BOPDS_DS.hxx>
52 #include <BOPDS_MapOfPair.hxx>
53 #include <BOPDS_Pair.hxx>
54 #include <BOPTools_AlgoTools.hxx>
55 #include <BRepBndLib.hxx>
56 #include <BRepBuilderAPI_Copy.hxx>
57 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
58 #include <BRepCheck_Shell.hxx>
59 #include <BRepClass3d_SolidClassifier.hxx>
60 #include <BRepClass_FaceClassifier.hxx>
61 #include <BRepExtrema_DistShapeShape.hxx>
62 #include <BRepExtrema_ShapeProximity.hxx>
63 #include <BRepExtrema_SelfIntersection.hxx>
64 #include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
65 #include <BRepGProp.hxx>
66 #include <BRepTools.hxx>
67 #include <BRep_Tool.hxx>
68 #include <Geom_Line.hxx>
69 #include <GeomAPI_ProjectPointOnCurve.hxx>
70 #include <GeomAPI_ProjectPointOnSurf.hxx>
71 #include <GeomLProp_CLProps.hxx>
72 #include <GeomLProp_SLProps.hxx>
73 #include <Geom_Plane.hxx>
74 #include <GProp_GProps.hxx>
75 #include <GProp_PrincipalProps.hxx>
76 #include <ShapeAnalysis.hxx>
77 #include <ShapeAnalysis_Surface.hxx>
78 #include <TopExp.hxx>
79 #include <TopExp_Explorer.hxx>
80 #include <TopoDS.hxx>
81 #include <TopoDS_Edge.hxx>
82 #include <TopTools_IndexedMapOfShape.hxx>
83 #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
84 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
85 #include <TopTools_ListIteratorOfListOfShape.hxx>
86 #include <TopTools_ListOfShape.hxx>
87 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
88
89 #include <set>
90
91 //=============================================================================
92 /*!
93  *  Constructor
94  */
95 //=============================================================================
96 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine)
97 : GEOM_IOperations(theEngine)
98 {
99   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
100 }
101
102 //=============================================================================
103 /*!
104  *  Destructor
105  */
106 //=============================================================================
107 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
108 {
109   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
110 }
111
112 //=============================================================================
113 /*! Get kind and parameters of the given shape.
114  */
115 //=============================================================================
116 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
117                              (Handle(GEOM_Object) theShape,
118                               Handle(TColStd_HSequenceOfInteger)& theIntegers,
119                               Handle(TColStd_HSequenceOfReal)&    theDoubles)
120 {
121   SetErrorCode(KO);
122   ShapeKind aKind = SK_NO_SHAPE;
123
124   if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
125   else                      theIntegers->Clear();
126
127   if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
128   else                     theDoubles->Clear();
129
130   if (theShape.IsNull())
131     return aKind;
132
133   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
134   if (aRefShape.IsNull()) return aKind;
135
136   TopoDS_Shape aShape = aRefShape->GetValue();
137   if (aShape.IsNull()) return aKind;
138
139   int geom_type = theShape->GetType();
140
141   // check if it's advanced shape
142   if ( geom_type > USER_TYPE ) {
143     SetErrorCode(OK);
144     return SK_ADVANCED;
145   }
146
147   // Call algorithm
148   GEOMAlgo_ShapeInfoFiller aSF;
149   aSF.SetShape(aShape);
150   aSF.Perform();
151
152   Standard_Integer iErr = aSF.ErrorStatus();
153
154   if (iErr) {
155     SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
156     return SK_NO_SHAPE;
157   }
158   const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
159
160   // specific processing for some "advanced" objects
161   switch ( geom_type ) {
162   case GEOM_MARKER:
163     // local coordinate system
164     // (+) geompy.kind.LCS  xc yc zc xx xy xz yx yy yz zx zy zz
165
166     TopoDS_Face aFace = TopoDS::Face( aShape );
167     Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) );
168     gp_Pnt aC = aPlane->Pln().Location();
169     gp_Ax3 anAx3 = aPlane->Pln().Position();
170
171     theDoubles->Append(aC.X());
172     theDoubles->Append(aC.Y());
173     theDoubles->Append(aC.Z());
174     
175     gp_Dir aD = anAx3.XDirection();
176     theDoubles->Append(aD.X());
177     theDoubles->Append(aD.Y());
178     theDoubles->Append(aD.Z());
179     aD = anAx3.YDirection();
180     theDoubles->Append(aD.X());
181     theDoubles->Append(aD.Y());
182     theDoubles->Append(aD.Z());
183     aD = anAx3.Direction();
184     theDoubles->Append(aD.X());
185     theDoubles->Append(aD.Y());
186     theDoubles->Append(aD.Z());
187
188     SetErrorCode(OK);
189     return SK_LCS;
190   }
191
192   // Interpret results
193   TopAbs_ShapeEnum aType = anInfo.Type();
194   switch (aType)
195   {
196   case TopAbs_COMPOUND:
197   case TopAbs_COMPSOLID:
198     {
199       // (+) geompy.kind.COMPOUND     nb_solids nb_faces nb_edges nb_vertices
200       // (+) geompy.kind.COMPSOLID    nb_solids nb_faces nb_edges nb_vertices
201       // ??? "nb_faces" - all faces or only 'standalone' faces?
202       if (aType == TopAbs_COMPOUND)
203         aKind = SK_COMPOUND;
204       else
205         aKind = SK_COMPSOLID;
206
207       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPOUND));
208       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPSOLID));
209       theIntegers->Append(anInfo.NbSubShapes(TopAbs_SOLID));
210       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
211       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
212       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
213     }
214     break;
215
216   case TopAbs_SHELL:
217     {
218       // (+) geompy.kind.SHELL  geompy.info.closed   nb_faces nb_edges nb_vertices
219       // (+) geompy.kind.SHELL  geompy.info.unclosed nb_faces nb_edges nb_vertices
220       aKind = SK_SHELL;
221
222       theIntegers->Append((int)anInfo.KindOfClosed());
223
224       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
225       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
226       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
227     }
228     break;
229
230   case TopAbs_WIRE:
231     {
232       // (+) geompy.kind.WIRE  geompy.info.closed   nb_edges nb_vertices
233       // (+) geompy.kind.WIRE  geompy.info.unclosed nb_edges nb_vertices
234       aKind = SK_WIRE;
235
236       theIntegers->Append((int)anInfo.KindOfClosed());
237
238       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
239       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
240     }
241     break;
242
243   case TopAbs_SOLID:
244     {
245       aKind = SK_SOLID;
246
247       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
248       switch (aKN)
249       {
250       case GEOMAlgo_KN_SPHERE:
251         // (+) geompy.kind.SPHERE  xc yc zc  R
252         {
253           aKind = SK_SPHERE;
254
255           gp_Pnt aC = anInfo.Location();
256           theDoubles->Append(aC.X());
257           theDoubles->Append(aC.Y());
258           theDoubles->Append(aC.Z());
259
260           theDoubles->Append(anInfo.Radius1());
261         }
262         break;
263       case GEOMAlgo_KN_CYLINDER:
264         // (+) geompy.kind.CYLINDER  xb yb zb  dx dy dz  R  H
265         {
266           aKind = SK_CYLINDER;
267
268           gp_Pnt aC = anInfo.Location();
269           theDoubles->Append(aC.X());
270           theDoubles->Append(aC.Y());
271           theDoubles->Append(aC.Z());
272
273           gp_Ax3 anAx3 = anInfo.Position();
274           gp_Dir aD = anAx3.Direction();
275           theDoubles->Append(aD.X());
276           theDoubles->Append(aD.Y());
277           theDoubles->Append(aD.Z());
278
279           theDoubles->Append(anInfo.Radius1());
280           theDoubles->Append(anInfo.Height());
281         }
282         break;
283       case GEOMAlgo_KN_BOX:
284         // (+) geompy.kind.BOX  xc yc zc  ax ay az
285         {
286           aKind = SK_BOX;
287
288           gp_Pnt aC = anInfo.Location();
289           theDoubles->Append(aC.X());
290           theDoubles->Append(aC.Y());
291           theDoubles->Append(aC.Z());
292
293           gp_Ax3 anAx3 = anInfo.Position();
294           gp_Dir aD = anAx3.Direction();
295           gp_Dir aX = anAx3.XDirection();
296
297           // ax ay az
298           if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
299               aX.IsParallel(gp::DX(), Precision::Angular())) {
300             theDoubles->Append(anInfo.Length()); // ax'
301             theDoubles->Append(anInfo.Width());  // ay'
302             theDoubles->Append(anInfo.Height()); // az'
303           }
304           else if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
305                    aX.IsParallel(gp::DY(), Precision::Angular())) {
306             theDoubles->Append(anInfo.Width());  // ay'
307             theDoubles->Append(anInfo.Length()); // ax'
308             theDoubles->Append(anInfo.Height()); // az'
309           }
310           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
311                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
312             theDoubles->Append(anInfo.Height()); // az'
313             theDoubles->Append(anInfo.Width());  // ay'
314             theDoubles->Append(anInfo.Length()); // ax'
315           }
316           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
317                    aX.IsParallel(gp::DY(), Precision::Angular())) {
318             theDoubles->Append(anInfo.Height()); // az'
319             theDoubles->Append(anInfo.Length()); // ax'
320             theDoubles->Append(anInfo.Width());  // ay'
321           }
322           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
323                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
324             theDoubles->Append(anInfo.Width());  // ay'
325             theDoubles->Append(anInfo.Height()); // az'
326             theDoubles->Append(anInfo.Length()); // ax'
327           }
328           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
329                    aX.IsParallel(gp::DX(), Precision::Angular())) {
330             theDoubles->Append(anInfo.Length()); // ax'
331             theDoubles->Append(anInfo.Height()); // az'
332             theDoubles->Append(anInfo.Width());  // ay'
333           }
334           else {
335             // (+) geompy.kind.ROTATED_BOX  xo yo zo  zx zy zz  xx xy xz  ax ay az
336             aKind = SK_ROTATED_BOX;
337
338             // Direction and XDirection
339             theDoubles->Append(aD.X());
340             theDoubles->Append(aD.Y());
341             theDoubles->Append(aD.Z());
342
343             theDoubles->Append(aX.X());
344             theDoubles->Append(aX.Y());
345             theDoubles->Append(aX.Z());
346
347             // ax ay az
348             theDoubles->Append(anInfo.Length());
349             theDoubles->Append(anInfo.Width());
350             theDoubles->Append(anInfo.Height());
351           }
352         }
353         break;
354       case GEOMAlgo_KN_TORUS:
355         // (+) geompy.kind.TORUS  xc yc zc  dx dy dz  R_1 R_2
356         {
357           aKind = SK_TORUS;
358
359           gp_Pnt aO = anInfo.Location();
360           theDoubles->Append(aO.X());
361           theDoubles->Append(aO.Y());
362           theDoubles->Append(aO.Z());
363
364           gp_Ax3 anAx3 = anInfo.Position();
365           gp_Dir aD = anAx3.Direction();
366           theDoubles->Append(aD.X());
367           theDoubles->Append(aD.Y());
368           theDoubles->Append(aD.Z());
369
370           theDoubles->Append(anInfo.Radius1());
371           theDoubles->Append(anInfo.Radius2());
372         }
373         break;
374       case GEOMAlgo_KN_CONE:
375         // (+) geompy.kind.CONE  xb yb zb  dx dy dz  R_1 R_2  H
376         {
377           aKind = SK_CONE;
378
379           gp_Pnt aO = anInfo.Location();
380           theDoubles->Append(aO.X());
381           theDoubles->Append(aO.Y());
382           theDoubles->Append(aO.Z());
383
384           gp_Ax3 anAx3 = anInfo.Position();
385           gp_Dir aD = anAx3.Direction();
386           theDoubles->Append(aD.X());
387           theDoubles->Append(aD.Y());
388           theDoubles->Append(aD.Z());
389
390           theDoubles->Append(anInfo.Radius1());
391           theDoubles->Append(anInfo.Radius2());
392           theDoubles->Append(anInfo.Height());
393         }
394         break;
395       case GEOMAlgo_KN_POLYHEDRON:
396         // (+) geompy.kind.POLYHEDRON  nb_faces nb_edges nb_vertices
397         {
398           aKind = SK_POLYHEDRON;
399
400           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
401           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
402           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
403         }
404         break;
405       default:
406         // (+) geompy.kind.SOLID  nb_faces nb_edges nb_vertices
407         {
408           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
409           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
410           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
411         }
412       }
413     }
414     break;
415
416   case TopAbs_FACE:
417     {
418       aKind = SK_FACE;
419
420       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
421       switch (aKN) {
422       case GEOMAlgo_KN_SPHERE:
423         // (+) geompy.kind.SPHERE2D  xc yc zc  R
424         {
425           aKind = SK_SPHERE2D;
426
427           gp_Pnt aC = anInfo.Location();
428           theDoubles->Append(aC.X());
429           theDoubles->Append(aC.Y());
430           theDoubles->Append(aC.Z());
431
432           theDoubles->Append(anInfo.Radius1());
433         }
434         break;
435       case GEOMAlgo_KN_CYLINDER:
436         // (+) geompy.kind.CYLINDER2D  xb yb zb  dx dy dz  R  H
437         {
438           aKind = SK_CYLINDER2D;
439
440           gp_Pnt aO = anInfo.Location();
441           theDoubles->Append(aO.X());
442           theDoubles->Append(aO.Y());
443           theDoubles->Append(aO.Z());
444
445           gp_Ax3 anAx3 = anInfo.Position();
446           gp_Dir aD = anAx3.Direction();
447           theDoubles->Append(aD.X());
448           theDoubles->Append(aD.Y());
449           theDoubles->Append(aD.Z());
450
451           theDoubles->Append(anInfo.Radius1());
452           theDoubles->Append(anInfo.Height());
453         }
454         break;
455       case GEOMAlgo_KN_TORUS:
456         // (+) geompy.kind.TORUS2D  xc yc zc  dx dy dz  R_1 R_2
457         {
458           aKind = SK_TORUS2D;
459
460           gp_Pnt aO = anInfo.Location();
461           theDoubles->Append(aO.X());
462           theDoubles->Append(aO.Y());
463           theDoubles->Append(aO.Z());
464
465           gp_Ax3 anAx3 = anInfo.Position();
466           gp_Dir aD = anAx3.Direction();
467           theDoubles->Append(aD.X());
468           theDoubles->Append(aD.Y());
469           theDoubles->Append(aD.Z());
470
471           theDoubles->Append(anInfo.Radius1());
472           theDoubles->Append(anInfo.Radius2());
473         }
474         break;
475       case GEOMAlgo_KN_CONE:
476         // (+) geompy.kind.CONE2D  xc yc zc  dx dy dz  R_1 R_2  H
477         {
478           aKind = SK_CONE2D;
479
480           gp_Pnt aO = anInfo.Location();
481           theDoubles->Append(aO.X());
482           theDoubles->Append(aO.Y());
483           theDoubles->Append(aO.Z());
484
485           gp_Ax3 anAx3 = anInfo.Position();
486           gp_Dir aD = anAx3.Direction();
487           theDoubles->Append(aD.X());
488           theDoubles->Append(aD.Y());
489           theDoubles->Append(aD.Z());
490
491           theDoubles->Append(anInfo.Radius1());
492           theDoubles->Append(anInfo.Radius2());
493           theDoubles->Append(anInfo.Height());
494         }
495         break;
496       case GEOMAlgo_KN_DISKCIRCLE:
497         // (+) geompy.kind.DISK_CIRCLE  xc yc zc  dx dy dz  R
498         {
499           aKind = SK_DISK_CIRCLE;
500
501           gp_Pnt aC = anInfo.Location();
502           theDoubles->Append(aC.X());
503           theDoubles->Append(aC.Y());
504           theDoubles->Append(aC.Z());
505
506           gp_Ax3 anAx3 = anInfo.Position();
507           gp_Dir aD = anAx3.Direction();
508           theDoubles->Append(aD.X());
509           theDoubles->Append(aD.Y());
510           theDoubles->Append(aD.Z());
511
512           theDoubles->Append(anInfo.Radius1());
513         }
514         break;
515       case GEOMAlgo_KN_DISKELLIPSE:
516         // (+) geompy.kind.DISK_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
517         {
518           aKind = SK_DISK_ELLIPSE;
519
520           gp_Pnt aC = anInfo.Location();
521           theDoubles->Append(aC.X());
522           theDoubles->Append(aC.Y());
523           theDoubles->Append(aC.Z());
524
525           gp_Ax3 anAx3 = anInfo.Position();
526           gp_Dir aD = anAx3.Direction();
527           theDoubles->Append(aD.X());
528           theDoubles->Append(aD.Y());
529           theDoubles->Append(aD.Z());
530
531           theDoubles->Append(anInfo.Radius1());
532           theDoubles->Append(anInfo.Radius2());
533         }
534         break;
535       case GEOMAlgo_KN_RECTANGLE:
536       case GEOMAlgo_KN_TRIANGLE:
537       case GEOMAlgo_KN_QUADRANGLE:
538       case GEOMAlgo_KN_POLYGON:
539         // (+) geompy.kind.POLYGON  xo yo zo  dx dy dz  nb_edges nb_vertices
540         {
541           aKind = SK_POLYGON;
542
543           gp_Pnt aO = anInfo.Location();
544           theDoubles->Append(aO.X());
545           theDoubles->Append(aO.Y());
546           theDoubles->Append(aO.Z());
547
548           gp_Ax3 anAx3 = anInfo.Position();
549           gp_Dir aD = anAx3.Direction();
550           theDoubles->Append(aD.X());
551           theDoubles->Append(aD.Y());
552           theDoubles->Append(aD.Z());
553
554           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
555           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
556         }
557         break;
558       case GEOMAlgo_KN_PLANE: // infinite
559         // (+) geompy.kind.PLANE  xo yo zo  dx dy dz
560         {
561           aKind = SK_PLANE;
562
563           gp_Pnt aC = anInfo.Location();
564           theDoubles->Append(aC.X());
565           theDoubles->Append(aC.Y());
566           theDoubles->Append(aC.Z());
567
568           gp_Ax3 anAx3 = anInfo.Position();
569           gp_Dir aD = anAx3.Direction();
570           theDoubles->Append(aD.X());
571           theDoubles->Append(aD.Y());
572           theDoubles->Append(aD.Z());
573
574           if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE)
575           {
576             // (+) geompy.kind.PLANAR  xo yo zo  dx dy dz  nb_edges nb_vertices
577             aKind = SK_PLANAR;
578             
579             theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
580             theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
581           }
582         }
583         break;
584       default:
585         // ??? geompy.kind.FACE  nb_edges nb_vertices _surface_type_id_
586         // (+) geompy.kind.FACE  nb_edges nb_vertices
587         theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
588         theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
589       }
590     }
591     break;
592
593   case TopAbs_EDGE:
594     {
595       aKind = SK_EDGE;
596
597       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
598       switch (aKN) {
599       case GEOMAlgo_KN_CIRCLE:
600         {
601           // (+) geompy.kind.CIRCLE  xc yc zc  dx dy dz  R
602           aKind = SK_CIRCLE;
603
604           gp_Pnt aC = anInfo.Location();
605           theDoubles->Append(aC.X());
606           theDoubles->Append(aC.Y());
607           theDoubles->Append(aC.Z());
608
609           gp_Ax3 anAx3 = anInfo.Position();
610           gp_Dir aD = anAx3.Direction();
611           theDoubles->Append(aD.X());
612           theDoubles->Append(aD.Y());
613           theDoubles->Append(aD.Z());
614
615           theDoubles->Append(anInfo.Radius1());
616         }
617         break;
618       case GEOMAlgo_KN_ARCCIRCLE:
619         {
620           // (+) geompy.kind.ARC_CIRCLE  xc yc zc  dx dy dz  R  x1 y1 z1  x2 y2 z2
621           aKind = SK_ARC_CIRCLE;
622
623           gp_Pnt aC = anInfo.Location();
624           theDoubles->Append(aC.X());
625           theDoubles->Append(aC.Y());
626           theDoubles->Append(aC.Z());
627
628           gp_Ax3 anAx3 = anInfo.Position();
629           gp_Dir aD = anAx3.Direction();
630           theDoubles->Append(aD.X());
631           theDoubles->Append(aD.Y());
632           theDoubles->Append(aD.Z());
633
634           theDoubles->Append(anInfo.Radius1());
635
636           gp_Pnt aP1 = anInfo.Pnt1();
637           theDoubles->Append(aP1.X());
638           theDoubles->Append(aP1.Y());
639           theDoubles->Append(aP1.Z());
640
641           gp_Pnt aP2 = anInfo.Pnt2();
642           theDoubles->Append(aP2.X());
643           theDoubles->Append(aP2.Y());
644           theDoubles->Append(aP2.Z());
645         }
646         break;
647       case GEOMAlgo_KN_ELLIPSE:
648         {
649           // (+) geompy.kind.ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
650           aKind = SK_ELLIPSE;
651
652           gp_Pnt aC = anInfo.Location();
653           theDoubles->Append(aC.X());
654           theDoubles->Append(aC.Y());
655           theDoubles->Append(aC.Z());
656
657           gp_Ax3 anAx3 = anInfo.Position();
658           gp_Dir aD = anAx3.Direction();
659           theDoubles->Append(aD.X());
660           theDoubles->Append(aD.Y());
661           theDoubles->Append(aD.Z());
662
663           theDoubles->Append(anInfo.Radius1());
664           theDoubles->Append(anInfo.Radius2());
665         }
666         break;
667       case GEOMAlgo_KN_ARCELLIPSE:
668         {
669           // (+) geompy.kind.ARC_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2  x1 y1 z1  x2 y2 z2
670           aKind = SK_ARC_ELLIPSE;
671
672           gp_Pnt aC = anInfo.Location();
673           theDoubles->Append(aC.X());
674           theDoubles->Append(aC.Y());
675           theDoubles->Append(aC.Z());
676
677           gp_Ax3 anAx3 = anInfo.Position();
678           gp_Dir aD = anAx3.Direction();
679           theDoubles->Append(aD.X());
680           theDoubles->Append(aD.Y());
681           theDoubles->Append(aD.Z());
682
683           theDoubles->Append(anInfo.Radius1());
684           theDoubles->Append(anInfo.Radius2());
685
686           gp_Pnt aP1 = anInfo.Pnt1();
687           theDoubles->Append(aP1.X());
688           theDoubles->Append(aP1.Y());
689           theDoubles->Append(aP1.Z());
690
691           gp_Pnt aP2 = anInfo.Pnt2();
692           theDoubles->Append(aP2.X());
693           theDoubles->Append(aP2.Y());
694           theDoubles->Append(aP2.Z());
695         }
696         break;
697       case GEOMAlgo_KN_LINE:
698         {
699           // ??? geompy.kind.LINE  x1 y1 z1  x2 y2 z2
700           // (+) geompy.kind.LINE  x1 y1 z1  dx dy dz
701           aKind = SK_LINE;
702
703           gp_Pnt aO = anInfo.Location();
704           theDoubles->Append(aO.X());
705           theDoubles->Append(aO.Y());
706           theDoubles->Append(aO.Z());
707
708           gp_Dir aD = anInfo.Direction();
709           theDoubles->Append(aD.X());
710           theDoubles->Append(aD.Y());
711           theDoubles->Append(aD.Z());
712         }
713         break;
714       case GEOMAlgo_KN_SEGMENT:
715         {
716           // (+) geompy.kind.SEGMENT  x1 y1 z1  x2 y2 z2
717           aKind = SK_SEGMENT;
718
719           gp_Pnt aP1 = anInfo.Pnt1();
720           theDoubles->Append(aP1.X());
721           theDoubles->Append(aP1.Y());
722           theDoubles->Append(aP1.Z());
723
724           gp_Pnt aP2 = anInfo.Pnt2();
725           theDoubles->Append(aP2.X());
726           theDoubles->Append(aP2.Y());
727           theDoubles->Append(aP2.Z());
728         }
729         break;
730       default:
731         // ??? geompy.kind.EDGE  nb_vertices _curve_type_id_
732         // (+) geompy.kind.EDGE  nb_vertices
733         theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
734       }
735     }
736     break;
737
738   case TopAbs_VERTEX:
739     {
740       // (+) geompy.kind.VERTEX  x y z
741       aKind = SK_VERTEX;
742
743       gp_Pnt aP = anInfo.Location();
744       theDoubles->Append(aP.X());
745       theDoubles->Append(aP.Y());
746       theDoubles->Append(aP.Z());
747     }
748     break;
749   default:;
750   }
751
752   SetErrorCode(OK);
753   return aKind;
754 }
755
756 //=============================================================================
757 /*!
758  *  GetPosition
759  */
760 //=============================================================================
761 void GEOMImpl_IMeasureOperations::GetPosition
762                    (Handle(GEOM_Object) theShape,
763                     Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
764                     Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
765                     Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
766 {
767   SetErrorCode(KO);
768
769   //Set default values: global CS
770   Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
771   Zz = Xx = 1.;
772
773   if (theShape.IsNull()) return;
774
775   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
776   if (aRefShape.IsNull()) return;
777
778   TopoDS_Shape aShape = aRefShape->GetValue();
779   if (aShape.IsNull()) {
780     SetErrorCode("The Objects has NULL Shape");
781     return;
782   }
783
784   try {
785     OCC_CATCH_SIGNALS;
786
787     gp_Ax3 anAx3 = GEOMUtils::GetPosition(aShape);
788
789     gp_Pnt anOri = anAx3.Location();
790     gp_Dir aDirZ = anAx3.Direction();
791     gp_Dir aDirX = anAx3.XDirection();
792
793     // Output values
794     anOri.Coord(Ox, Oy, Oz);
795     aDirZ.Coord(Zx, Zy, Zz);
796     aDirX.Coord(Xx, Xy, Xz);
797   }
798   catch (Standard_Failure& aFail) {
799     SetErrorCode(aFail.GetMessageString());
800     return;
801   }
802
803   SetErrorCode(OK);
804 }
805
806 //=============================================================================
807 /*!
808  *  GetCentreOfMass
809  */
810 //=============================================================================
811 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
812                                                 (Handle(GEOM_Object) theShape)
813 {
814   SetErrorCode(KO);
815
816   if (theShape.IsNull()) return NULL;
817
818   //Add a new CentreOfMass object
819   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG);
820
821   //Add a new CentreOfMass function
822   Handle(GEOM_Function) aFunction =
823     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
824   if (aFunction.IsNull()) return NULL;
825
826   //Check if the function is set correctly
827   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
828
829   GEOMImpl_IMeasure aCI (aFunction);
830
831   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
832   if (aRefShape.IsNull()) return NULL;
833
834   aCI.SetBase(aRefShape);
835
836   //Compute the CentreOfMass value
837   try {
838     OCC_CATCH_SIGNALS;
839     if (!GetSolver()->ComputeFunction(aFunction)) {
840       SetErrorCode("Measure driver failed to compute centre of mass");
841       return NULL;
842     }
843   }
844   catch (Standard_Failure& aFail) {
845     SetErrorCode(aFail.GetMessageString());
846     return NULL;
847   }
848
849   //Make a Python command
850   GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
851
852   SetErrorCode(OK);
853   return aCDG;
854 }
855
856 //=============================================================================
857 /*!
858  *  GetVertexByIndex
859  */
860 //=============================================================================
861 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
862                                                 (Handle(GEOM_Object) theShape,
863                                                  Standard_Integer theIndex,
864                                                  Standard_Boolean theUseOri)
865 {
866   SetErrorCode(KO);
867
868   if (theShape.IsNull()) return NULL;
869
870   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
871   if (aRefShape.IsNull()) return NULL;
872
873   //Add a new Vertex object
874   Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT);
875
876   //Add a function
877   Handle(GEOM_Function) aFunction =
878     aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
879   if (aFunction.IsNull()) return NULL;
880
881   //Check if the function is set correctly
882   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
883
884   GEOMImpl_IMeasure aCI (aFunction);
885   aCI.SetBase(aRefShape);
886   aCI.SetIndex(theIndex);
887   aCI.SetUseOri(theUseOri);
888
889   //Compute
890   try {
891     OCC_CATCH_SIGNALS;
892     if (!GetSolver()->ComputeFunction(aFunction)) {
893       SetErrorCode("Vertex by index driver failed.");
894       return NULL;
895     }
896   }
897   catch (Standard_Failure& aFail) {
898     SetErrorCode(aFail.GetMessageString());
899     return NULL;
900   }
901
902   //Make a Python command
903   GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex("
904                                << theShape << ", "
905                                << theIndex << ", "
906                                << theUseOri << ")";
907
908   SetErrorCode(OK);
909   return aVertex;
910 }
911
912 //=============================================================================
913 /*!
914  *  GetNormal
915  */
916 //=============================================================================
917 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
918                                          (Handle(GEOM_Object) theFace,
919                                           Handle(GEOM_Object) theOptionalPoint)
920 {
921   SetErrorCode(KO);
922
923   if (theFace.IsNull()) return NULL;
924
925   //Add a new Normale object
926   Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR);
927
928   //Add a new Normale function
929   Handle(GEOM_Function) aFunction =
930     aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
931   if (aFunction.IsNull()) return NULL;
932
933   //Check if the function is set correctly
934   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
935
936   GEOMImpl_IMeasure aCI (aFunction);
937
938   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
939   if (aFace.IsNull()) return NULL;
940
941   aCI.SetBase(aFace);
942
943   if (!theOptionalPoint.IsNull()) {
944     Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
945     aCI.SetPoint(anOptPnt);
946   }
947
948   //Compute the Normale value
949   try {
950     OCC_CATCH_SIGNALS;
951     if (!GetSolver()->ComputeFunction(aFunction)) {
952       SetErrorCode("Measure driver failed to compute normake of face");
953       return NULL;
954     }
955   }
956   catch (Standard_Failure& aFail) {
957     SetErrorCode(aFail.GetMessageString());
958     return NULL;
959   }
960
961   //Make a Python command
962   GEOM::TPythonDump pd (aFunction);
963   pd << aNorm << " = geompy.GetNormal(" << theFace;
964   if (!theOptionalPoint.IsNull()) {
965     pd << ", " << theOptionalPoint;
966   }
967   pd << ")";
968
969   SetErrorCode(OK);
970   return aNorm;
971 }
972
973 //=============================================================================
974 /*!
975  *  GetBasicProperties
976  */
977 //=============================================================================
978 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
979                                                       const Standard_Real theTolerance,
980                                                       Standard_Real& theLength,
981                                                       Standard_Real& theSurfArea,
982                                                       Standard_Real& theVolume)
983 {
984   SetErrorCode(KO);
985
986   if (theShape.IsNull()) return;
987
988   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
989   if (aRefShape.IsNull()) return;
990
991   TopoDS_Shape aShape = aRefShape->GetValue();
992   if (aShape.IsNull()) {
993     SetErrorCode("The Objects has NULL Shape");
994     return;
995   }
996
997   //Compute the parameters
998   GProp_GProps LProps, SProps;
999   Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
1000   try {
1001     OCC_CATCH_SIGNALS;
1002     BRepGProp::LinearProperties(aShape, LProps, Standard_True);
1003     theLength = LProps.Mass();
1004
1005     BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
1006     theSurfArea = SProps.Mass();
1007
1008     theVolume = 0.0;
1009     if (aShape.ShapeType() < TopAbs_SHELL) {
1010       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1011         GProp_GProps VProps;
1012         BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
1013         theVolume += VProps.Mass();
1014       }
1015     }
1016   }
1017   catch (Standard_Failure& aFail) {
1018     SetErrorCode(aFail.GetMessageString());
1019     return;
1020   }
1021
1022   SetErrorCode(OK);
1023 }
1024
1025 //=============================================================================
1026 /*!
1027  *  GetInertia
1028  */
1029 //=============================================================================
1030 void GEOMImpl_IMeasureOperations::GetInertia
1031                    (Handle(GEOM_Object) theShape,
1032                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1033                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1034                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1035                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1036 {
1037   SetErrorCode(KO);
1038
1039   if (theShape.IsNull()) return;
1040
1041   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1042   if (aRefShape.IsNull()) return;
1043
1044   TopoDS_Shape aShape = aRefShape->GetValue();
1045   if (aShape.IsNull()) {
1046     SetErrorCode("The Objects has NULL Shape");
1047     return;
1048   }
1049
1050   //Compute the parameters
1051   GProp_GProps System;
1052
1053   try {
1054     OCC_CATCH_SIGNALS;
1055     if (aShape.ShapeType() == TopAbs_VERTEX ||
1056         aShape.ShapeType() == TopAbs_EDGE ||
1057         aShape.ShapeType() == TopAbs_WIRE) {
1058       BRepGProp::LinearProperties(aShape, System, Standard_True);
1059     } else if (aShape.ShapeType() == TopAbs_FACE ||
1060                aShape.ShapeType() == TopAbs_SHELL) {
1061       BRepGProp::SurfaceProperties(aShape, System, Standard_True);
1062     } else {
1063       BRepGProp::VolumeProperties(aShape, System, Standard_True);
1064     }
1065     gp_Mat I = System.MatrixOfInertia();
1066
1067     I11 = I(1,1);
1068     I12 = I(1,2);
1069     I13 = I(1,3);
1070
1071     I21 = I(2,1);
1072     I22 = I(2,2);
1073     I23 = I(2,3);
1074
1075     I31 = I(3,1);
1076     I32 = I(3,2);
1077     I33 = I(3,3);
1078
1079     GProp_PrincipalProps Pr = System.PrincipalProperties();
1080     Pr.Moments(Ix,Iy,Iz);
1081   }
1082   catch (Standard_Failure& aFail) {
1083     SetErrorCode(aFail.GetMessageString());
1084     return;
1085   }
1086
1087   SetErrorCode(OK);
1088 }
1089
1090 //=============================================================================
1091 /*!
1092  *  GetBoundingBox
1093  */
1094 //=============================================================================
1095 void GEOMImpl_IMeasureOperations::GetBoundingBox
1096                                      (Handle(GEOM_Object) theShape,
1097                                       const Standard_Boolean precise,
1098                                       Standard_Real& Xmin, Standard_Real& Xmax,
1099                                       Standard_Real& Ymin, Standard_Real& Ymax,
1100                                       Standard_Real& Zmin, Standard_Real& Zmax)
1101 {
1102   SetErrorCode(KO);
1103
1104   if (theShape.IsNull()) return;
1105
1106   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1107   if (aRefShape.IsNull()) return;
1108
1109   TopoDS_Shape aShape = aRefShape->GetValue();
1110   if (aShape.IsNull()) {
1111     SetErrorCode("The Objects has NULL Shape");
1112     return;
1113   }
1114
1115   //Compute the parameters
1116   Bnd_Box B;
1117
1118   try {
1119     OCC_CATCH_SIGNALS;
1120     BRepBuilderAPI_Copy aCopyTool (aShape);
1121     if (!aCopyTool.IsDone()) {
1122       SetErrorCode("GetBoundingBox Error: Bad shape detected");
1123       return;
1124     }
1125
1126     aShape = aCopyTool.Shape();
1127
1128     // remove triangulation to obtain more exact boundaries
1129     BRepTools::Clean(aShape);
1130
1131     BRepBndLib::Add(aShape, B);
1132
1133     if (precise) {
1134       if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
1135         SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
1136         return;
1137       }
1138     }
1139
1140     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1141   }
1142   catch (Standard_Failure& aFail) {
1143     SetErrorCode(aFail.GetMessageString());
1144     return;
1145   }
1146
1147   SetErrorCode(OK);
1148 }
1149
1150 //=============================================================================
1151 /*!
1152  *  GetBoundingBox
1153  */
1154 //=============================================================================
1155 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
1156                                                 (Handle(GEOM_Object) theShape,
1157                                                  const Standard_Boolean precise)
1158 {
1159   SetErrorCode(KO);
1160
1161   if (theShape.IsNull()) return NULL;
1162
1163   //Add a new BoundingBox object
1164   Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX);
1165
1166   //Add a new BoundingBox function
1167   const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
1168   Handle(GEOM_Function) aFunction =
1169     aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
1170   if (aFunction.IsNull()) return NULL;
1171
1172   //Check if the function is set correctly
1173   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1174
1175   GEOMImpl_IMeasure aCI (aFunction);
1176
1177   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1178   if (aRefShape.IsNull()) return NULL;
1179
1180   aCI.SetBase(aRefShape);
1181
1182   //Compute the BoundingBox value
1183   try {
1184     OCC_CATCH_SIGNALS;
1185     if (!GetSolver()->ComputeFunction(aFunction)) {
1186       SetErrorCode("Measure driver failed to compute a bounding box");
1187       return NULL;
1188     }
1189   }
1190   catch (Standard_Failure& aFail) {
1191     SetErrorCode(aFail.GetMessageString());
1192     return NULL;
1193   }
1194
1195   //Make a Python command
1196   GEOM::TPythonDump aPd(aFunction);
1197   
1198   aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
1199
1200   if (precise) {
1201     aPd << ", True";
1202   }
1203
1204   aPd << ")";
1205
1206   SetErrorCode(OK);
1207   return aBnd;
1208 }
1209
1210 //=============================================================================
1211 /*!
1212  *  GetTolerance
1213  */
1214 //=============================================================================
1215 void GEOMImpl_IMeasureOperations::GetTolerance
1216                                (Handle(GEOM_Object) theShape,
1217                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1218                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1219                                 Standard_Real& VertMin, Standard_Real& VertMax)
1220 {
1221   SetErrorCode(KO);
1222
1223   if (theShape.IsNull()) return;
1224
1225   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1226   if (aRefShape.IsNull()) return;
1227
1228   TopoDS_Shape aShape = aRefShape->GetValue();
1229   if (aShape.IsNull()) {
1230     SetErrorCode("The Objects has NULL Shape");
1231     return;
1232   }
1233
1234   //Compute the parameters
1235   Standard_Real T;
1236   FaceMin = EdgeMin = VertMin = RealLast();
1237   FaceMax = EdgeMax = VertMax = -RealLast();
1238
1239   try {
1240     OCC_CATCH_SIGNALS;
1241     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1242       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1243       T = BRep_Tool::Tolerance(Face);
1244       if (T > FaceMax)
1245         FaceMax = T;
1246       if (T < FaceMin)
1247         FaceMin = T;
1248     }
1249     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1250       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1251       T = BRep_Tool::Tolerance(Edge);
1252       if (T > EdgeMax)
1253         EdgeMax = T;
1254       if (T < EdgeMin)
1255         EdgeMin = T;
1256     }
1257     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1258       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1259       T = BRep_Tool::Tolerance(Vertex);
1260       if (T > VertMax)
1261         VertMax = T;
1262       if (T < VertMin)
1263         VertMin = T;
1264     }
1265   }
1266   catch (Standard_Failure& aFail) {
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& aFail) {
1309     SetErrorCode(aFail.GetMessageString());
1310     return false;
1311   }
1312
1313   SetErrorCode(OK);
1314   return isValid;
1315 }
1316
1317 //=============================================================================
1318 /*!
1319  *  PrintShapeErrors
1320  */
1321 //=============================================================================
1322 TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
1323                                  (Handle(GEOM_Object)          theShape,
1324                                   const std::list<ShapeError> &theErrors)
1325 {
1326   TCollection_AsciiString aDump;
1327
1328   if (theShape.IsNull()) {
1329     return aDump;
1330   }
1331
1332   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1333
1334   if (aRefShape.IsNull()) {
1335     return aDump;
1336   }
1337
1338   TopoDS_Shape aShape = aRefShape->GetValue();
1339
1340   if (aShape.IsNull()) {
1341     SetErrorCode("The Objects has NULL Shape");
1342     return aDump;
1343   }
1344
1345   if (!theErrors.empty()) {
1346     // The shape is not valid. Prepare errors for dump.
1347     TopTools_IndexedMapOfShape anIndices;
1348     std::list<ShapeError>::const_iterator anIter = theErrors.begin();
1349     Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1350     nbv = nbe = nbw = nbf = nbs = nbo = 0;
1351
1352     // Map sub-shapes and their indices
1353     TopExp::MapShapes(aShape, anIndices);
1354
1355     const Standard_Integer aNbSubShapes = anIndices.Extent();
1356     TColStd_MapOfInteger   aMapPbInd;
1357
1358     aDump += " -- The Shape has problems :\n";
1359     aDump += "  Check                                    Count\n";
1360     aDump += " ------------------------------------------------\n";
1361
1362     for (; anIter != theErrors.end(); anIter++) {
1363       Standard_Integer aNbShapes = anIter->incriminated.size();
1364
1365       switch(anIter->error) {
1366       case BRepCheck_InvalidPointOnCurve:
1367         aDump += "  Invalid Point on Curve ................... ";
1368         break;
1369       case BRepCheck_InvalidPointOnCurveOnSurface:
1370         aDump += "  Invalid Point on CurveOnSurface .......... ";
1371         break;
1372       case BRepCheck_InvalidPointOnSurface:
1373         aDump += "  Invalid Point on Surface ................. ";
1374         break;
1375       case BRepCheck_No3DCurve:
1376         aDump += "  No 3D Curve .............................. ";
1377         break;
1378       case BRepCheck_Multiple3DCurve:
1379         aDump += "  Multiple 3D Curve ........................ ";
1380         break;
1381       case BRepCheck_Invalid3DCurve:
1382         aDump += "  Invalid 3D Curve ......................... ";
1383         break;
1384       case BRepCheck_NoCurveOnSurface:
1385         aDump += "  No Curve on Surface ...................... ";
1386         break;
1387       case BRepCheck_InvalidCurveOnSurface:
1388         aDump += "  Invalid Curve on Surface ................. ";
1389         break;
1390       case BRepCheck_InvalidCurveOnClosedSurface:
1391         aDump += "  Invalid Curve on closed Surface .......... ";
1392         break;
1393       case BRepCheck_InvalidSameRangeFlag:
1394         aDump += "  Invalid SameRange Flag ................... ";
1395         break;
1396       case BRepCheck_InvalidSameParameterFlag:
1397         aDump += "  Invalid SameParameter Flag ............... ";
1398         break;
1399       case BRepCheck_InvalidDegeneratedFlag:
1400         aDump += "  Invalid Degenerated Flag ................. ";
1401         break;
1402       case BRepCheck_FreeEdge:
1403         aDump += "  Free Edge ................................ ";
1404         break;
1405       case BRepCheck_InvalidMultiConnexity:
1406         aDump += "  Invalid MultiConnexity ................... ";
1407         break;
1408       case BRepCheck_InvalidRange:
1409         aDump += "  Invalid Range ............................ ";
1410         break;
1411       case BRepCheck_EmptyWire:
1412         aDump += "  Empty Wire ............................... ";
1413         break;
1414       case BRepCheck_RedundantEdge:
1415         aDump += "  Redundant Edge ........................... ";
1416         break;
1417       case BRepCheck_SelfIntersectingWire:
1418         aDump += "  Self Intersecting Wire ................... ";
1419         break;
1420       case BRepCheck_NoSurface:
1421         aDump += "  No Surface ............................... ";
1422         break;
1423       case BRepCheck_InvalidWire:
1424         aDump += "  Invalid Wire ............................. ";
1425         break;
1426       case BRepCheck_RedundantWire:
1427         aDump += "  Redundant Wire ........................... ";
1428         break;
1429       case BRepCheck_IntersectingWires:
1430         aDump += "  Intersecting Wires ....................... ";
1431         break;
1432       case BRepCheck_InvalidImbricationOfWires:
1433         aDump += "  Invalid Imbrication of Wires ............. ";
1434         break;
1435       case BRepCheck_EmptyShell:
1436         aDump += "  Empty Shell .............................. ";
1437         break;
1438       case BRepCheck_RedundantFace:
1439         aDump += "  Redundant Face ........................... ";
1440         break;
1441       case BRepCheck_UnorientableShape:
1442         aDump += "  Unorientable Shape ....................... ";
1443         break;
1444       case BRepCheck_NotClosed:
1445         aDump += "  Not Closed ............................... ";
1446         break;
1447       case BRepCheck_NotConnected:
1448         aDump += "  Not Connected ............................ ";
1449         break;
1450       case BRepCheck_SubshapeNotInShape:
1451         aDump += "  Sub-shape not in Shape ................... ";
1452         break;
1453       case BRepCheck_BadOrientation:
1454         aDump += "  Bad Orientation .......................... ";
1455         break;
1456       case BRepCheck_BadOrientationOfSubshape:
1457         aDump += "  Bad Orientation of Sub-shape ............. ";
1458         break;
1459       case BRepCheck_InvalidToleranceValue:
1460         aDump += "  Invalid Tolerance Value .................. ";
1461         break;
1462       case BRepCheck_CheckFail:
1463         aDump += "  Check Shape Failure ...................... ";
1464         break;
1465       default:
1466         break;
1467       }
1468
1469       aDump += TCollection_AsciiString(aNbShapes) + "\n";
1470
1471       // Count types of shape.
1472       std::list<int>::const_iterator aShIter = anIter->incriminated.begin();
1473
1474       for (; aShIter != anIter->incriminated.end(); aShIter++) {
1475         const Standard_Integer anIndex = *aShIter;
1476
1477         if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) {
1478           const TopoDS_Shape     &aSubShape = anIndices.FindKey(anIndex);
1479           const TopAbs_ShapeEnum  aType     = aSubShape.ShapeType();
1480
1481           switch (aType) {
1482             case TopAbs_VERTEX : nbv++; break;
1483             case TopAbs_EDGE   : nbe++; break;
1484             case TopAbs_WIRE   : nbw++; break;
1485             case TopAbs_FACE   : nbf++; break;
1486             case TopAbs_SHELL  : nbs++; break;
1487             case TopAbs_SOLID  : nbo++; break;
1488             default            : break;
1489           }
1490         }
1491       }
1492     }
1493
1494     const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo;
1495     aDump += " ------------------------------------------------\n";
1496     aDump += "*** Shapes with problems : ";
1497     aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n";
1498
1499     if (nbv > 0) {
1500       aDump += "VERTEX : ";
1501       if (nbv < 10) aDump += " ";
1502       aDump += TCollection_AsciiString(nbv) + "\n";
1503     }
1504     if (nbe > 0) {
1505       aDump += "EDGE   : ";
1506       if (nbe < 10) aDump += " ";
1507       aDump += TCollection_AsciiString(nbe) + "\n";
1508     }
1509     if (nbw > 0) {
1510       aDump += "WIRE   : ";
1511       if (nbw < 10) aDump += " ";
1512       aDump += TCollection_AsciiString(nbw) + "\n";
1513     }
1514     if (nbf > 0) {
1515       aDump += "FACE   : ";
1516       if (nbf < 10) aDump += " ";
1517       aDump += TCollection_AsciiString(nbf) + "\n";
1518     }
1519     if (nbs > 0) {
1520       aDump += "SHELL  : ";
1521       if (nbs < 10) aDump += " ";
1522       aDump += TCollection_AsciiString(nbs) + "\n";
1523     }
1524     if (nbo > 0) {
1525       aDump += "SOLID  : ";
1526       if (nbo < 10) aDump += " ";
1527       aDump += TCollection_AsciiString(nbo) + "\n";
1528     }
1529   }
1530
1531   return aDump;
1532 }
1533
1534 //=============================================================================
1535 /*!
1536  *  CheckSelfIntersections
1537  */
1538 //=============================================================================
1539 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
1540                          (Handle(GEOM_Object)                 theShape,
1541                           const SICheckLevel                  theCheckLevel,
1542                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1543 {
1544   SetErrorCode(KO);
1545
1546   if (theIntersections.IsNull())
1547     theIntersections = new TColStd_HSequenceOfInteger;
1548   else
1549     theIntersections->Clear();
1550
1551   if (theShape.IsNull())
1552     return false;
1553
1554   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1555   if (aRefShape.IsNull()) return false;
1556
1557   TopoDS_Shape aShape = aRefShape->GetValue();
1558   if (aShape.IsNull()) return false;
1559
1560   // 0. Prepare data
1561   TopoDS_Shape aScopy;
1562   //
1563   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1564   //
1565   // Map sub-shapes and their indices
1566   TopTools_IndexedMapOfShape anIndices;
1567   TopExp::MapShapes(aScopy, anIndices);
1568
1569   TopTools_ListOfShape aLCS;
1570   aLCS.Append(aScopy);
1571   //
1572   BOPAlgo_CheckerSI aCSI; // checker of self-interferences
1573   aCSI.SetArguments(aLCS);
1574   aCSI.SetLevelOfCheck(theCheckLevel);
1575
1576   // 1. Launch the checker
1577   aCSI.Perform();
1578   Standard_Boolean iErr = aCSI.HasErrors();
1579
1580   //
1581   Standard_Integer aNbS, n1, n2;
1582   BOPDS_MapIteratorOfMapOfPair aItMPK;
1583   //
1584   // 2. Take the shapes from DS
1585   const BOPDS_DS& aDS = aCSI.DS();
1586   aNbS=aDS.NbShapes();
1587   //
1588   // 3. Get the pairs of interfered shapes
1589   const BOPDS_MapOfPair& aMPK=aDS.Interferences();
1590   aItMPK.Initialize(aMPK);
1591   for (; aItMPK.More(); aItMPK.Next()) {
1592     const BOPDS_Pair& aPK=aItMPK.Value();
1593     aPK.Indices(n1, n2);
1594     //
1595     if (n1 > aNbS || n2 > aNbS){
1596       return false; // Error
1597     }
1598     const TopoDS_Shape& aS1 = aDS.Shape(n1);
1599     const TopoDS_Shape& aS2 = aDS.Shape(n2);
1600
1601     theIntersections->Append(anIndices.FindIndex(aS1));
1602     theIntersections->Append(anIndices.FindIndex(aS2));
1603   }
1604
1605   if (!iErr) {
1606     SetErrorCode(OK);
1607   }
1608
1609   return theIntersections->IsEmpty();
1610 }
1611
1612 //=============================================================================
1613 /*!
1614  *  CheckSelfIntersectionsFast
1615  */
1616 //=============================================================================
1617 bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
1618                          (Handle(GEOM_Object) theShape,
1619                           float theDeflection, double theTolerance,
1620                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1621 {
1622   SetErrorCode(KO);
1623
1624   if (theIntersections.IsNull())
1625     theIntersections = new TColStd_HSequenceOfInteger;
1626   else
1627     theIntersections->Clear();
1628
1629   if (theShape.IsNull())
1630     return false;
1631
1632   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1633   if (aRefShape.IsNull()) return false;
1634
1635   TopoDS_Shape aShape = aRefShape->GetValue();
1636   if (aShape.IsNull()) return false;
1637
1638   // Prepare data
1639   TopoDS_Shape aScopy;
1640
1641   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1642   GEOMUtils::MeshShape(aScopy, theDeflection);
1643
1644   // Map sub-shapes and their indices
1645   TopTools_IndexedMapOfShape anIndices;
1646   TopExp::MapShapes(aScopy, anIndices);
1647
1648   // Checker of fast interferences
1649   BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
1650
1651   // Launch the checker
1652   aTool.Perform();
1653   
1654   const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
1655   
1656   std::set<Standard_Integer> processed;
1657   
1658   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
1659     Standard_Integer idxLeft = it.Key();
1660     if (processed.count(idxLeft) > 0) continue; // already added
1661     processed.insert(idxLeft);
1662     const TColStd_PackedMapOfInteger& overlaps = it.Value();
1663     for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
1664       Standard_Integer idxRight = subit.Key();
1665       if (processed.count(idxRight) > 0) continue; // already added
1666       const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
1667       const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
1668       theIntersections->Append(anIndices.FindIndex(aS1));
1669       theIntersections->Append(anIndices.FindIndex(aS2));
1670     }
1671   }
1672
1673   if (aTool.IsDone())
1674     SetErrorCode(OK);
1675
1676   return theIntersections->IsEmpty();
1677 }
1678
1679 //=============================================================================
1680 /*!
1681  *  CheckBOPArguments
1682  */
1683 //=============================================================================
1684 bool GEOMImpl_IMeasureOperations::CheckBOPArguments
1685                                       (const Handle(GEOM_Object) &theShape)
1686 {
1687   SetErrorCode(KO);
1688
1689   if (theShape.IsNull()) {
1690     return false;
1691   }
1692
1693   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1694
1695   if (aRefShape.IsNull()) {
1696     return false;
1697   }
1698
1699   TopoDS_Shape aShape = aRefShape->GetValue();
1700
1701   if (aShape.IsNull()) {
1702     return false;
1703   }
1704
1705   //Compute the parameters
1706   bool isValid = GEOMUtils::CheckBOPArguments(aShape);
1707
1708   SetErrorCode(OK);
1709
1710   return isValid;
1711 }
1712
1713 //=============================================================================
1714 /*!
1715  *  FastIntersect
1716  */
1717 //=============================================================================
1718 bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1719                                                  double theTolerance, float theDeflection,
1720                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections1,
1721                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections2)
1722 {
1723   SetErrorCode(KO);
1724   bool isGood = false;
1725
1726   if (theIntersections1.IsNull())
1727     theIntersections1 = new TColStd_HSequenceOfInteger;
1728   else
1729     theIntersections1->Clear();
1730
1731   if (theIntersections2.IsNull())
1732     theIntersections2 = new TColStd_HSequenceOfInteger;
1733   else
1734     theIntersections2->Clear();
1735
1736   if (theShape1.IsNull() || theShape2.IsNull()) {
1737     SetErrorCode("Objects have NULL Shape");
1738     return isGood;
1739   }
1740
1741   if (theShape1 == theShape2) {
1742     SetErrorCode("Objects are equal");
1743     return isGood;
1744   }
1745   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1746   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1747   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
1748
1749   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1750   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1751   if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
1752
1753   // 0. Prepare data
1754   TopoDS_Shape aScopy1, aScopy2;
1755   GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
1756   GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
1757
1758   GEOMUtils::MeshShape(aScopy1, theDeflection);
1759   GEOMUtils::MeshShape(aScopy2, theDeflection);
1760   //
1761   // Map sub-shapes and their indices
1762   TopTools_IndexedMapOfShape anIndices1, anIndices2;
1763   TopExp::MapShapes(aScopy1, anIndices1);
1764   TopExp::MapShapes(aScopy2, anIndices2);
1765
1766   TopTools_ListOfShape aLCS1, aLCS2;
1767   aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
1768   //
1769   BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
1770   aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
1771   aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
1772
1773   // 1. Launch the checker
1774   aBSP.Perform();
1775  
1776   // 2. Get sets of IDs of overlapped faces
1777   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
1778   {
1779     const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
1780     theIntersections1->Append(anIndices1.FindIndex(aS1));
1781   }
1782   
1783   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
1784   {
1785     const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
1786     theIntersections2->Append(anIndices2.FindIndex(aS2));
1787   }
1788
1789   isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
1790
1791   if (aBSP.IsDone())
1792     SetErrorCode(OK);
1793
1794   return isGood;
1795 }
1796
1797 //=============================================================================
1798 /*!
1799  *  IsGoodForSolid
1800  */
1801 //=============================================================================
1802 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1803 {
1804   SetErrorCode(KO);
1805
1806   TCollection_AsciiString aRes = "";
1807
1808   if (theShape.IsNull()) {
1809     aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1810   }
1811   else {
1812     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1813     if (aRefShape.IsNull()) {
1814       aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1815     }
1816     else {
1817       TopoDS_Shape aShape = aRefShape->GetValue();
1818       if (aShape.IsNull()) {
1819         aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1820       }
1821       else {
1822         if (aShape.ShapeType() == TopAbs_COMPOUND) {
1823           TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1824           if (It.More()) aShape = It.Value();
1825         }
1826         if (aShape.ShapeType() == TopAbs_SHELL) {
1827           BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
1828           if (chkShell.Closed() == BRepCheck_NotClosed) {
1829             aRes = "WRN_SHAPE_UNCLOSED";
1830           }
1831         }
1832         else {
1833           aRes = "WRN_SHAPE_NOT_SHELL";
1834         }
1835       }
1836     }
1837   }
1838
1839   if (aRes.IsEmpty())
1840     SetErrorCode(OK);
1841
1842   return aRes;
1843 }
1844
1845 //=============================================================================
1846 /*!
1847  *  WhatIs
1848  */
1849 //=============================================================================
1850 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1851 {
1852   SetErrorCode(KO);
1853
1854   TCollection_AsciiString Astr;
1855
1856   if (theShape.IsNull()) return Astr;
1857
1858   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1859   if (aRefShape.IsNull()) return Astr;
1860
1861   TopoDS_Shape aShape = aRefShape->GetValue();
1862   if (aShape.IsNull()) {
1863     SetErrorCode("The Objects has NULL Shape");
1864     return Astr;
1865   }
1866
1867   //Compute the parameters
1868   if (aShape.ShapeType() == TopAbs_EDGE) {
1869     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1870       Astr = Astr + " It is a degenerated edge \n";
1871     }
1872   }
1873
1874   Astr = Astr + " Number of sub-shapes : \n";
1875
1876   try {
1877     OCC_CATCH_SIGNALS;
1878     int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
1879     for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
1880       nbTypes[iType] = 0;
1881       nbFlatType[iType] = 0;
1882     }
1883     nbTypes[aShape.ShapeType()]++;
1884
1885     TopTools_MapOfShape aMapOfShape;
1886     aMapOfShape.Add(aShape);
1887     TopTools_ListOfShape aListOfShape;
1888     aListOfShape.Append(aShape);
1889
1890     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1891     for (; itL.More(); itL.Next()) {
1892       TopoDS_Shape sp = itL.Value();
1893       TopoDS_Iterator it (sp);
1894       for (; it.More(); it.Next()) {
1895         TopoDS_Shape s = it.Value();
1896         if (aMapOfShape.Add(s)) {
1897           aListOfShape.Append(s);
1898           nbTypes[s.ShapeType()]++;
1899           if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
1900             nbFlatType[s.ShapeType()]++;
1901           }
1902         }
1903       }
1904     }
1905
1906     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1907     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1908     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1909     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1910     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1911     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1912     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1913     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1914     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
1915
1916     if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
1917       Astr = Astr + " --------------------- \n Flat content : \n";
1918       if (nbFlatType[TopAbs_VERTEX] > 0)
1919         Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
1920       if (nbFlatType[TopAbs_EDGE] > 0)
1921         Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
1922       if (nbFlatType[TopAbs_WIRE] > 0)
1923         Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
1924       if (nbFlatType[TopAbs_FACE] > 0)
1925         Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
1926       if (nbFlatType[TopAbs_SHELL] > 0)
1927         Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
1928       if (nbFlatType[TopAbs_SOLID] > 0)
1929         Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
1930     }
1931   }
1932   catch (Standard_Failure& aFail) {
1933     SetErrorCode(aFail.GetMessageString());
1934     return Astr;
1935   }
1936
1937   SetErrorCode(OK);
1938   return Astr;
1939 }
1940
1941 //=============================================================================
1942 /*!
1943  *  AreCoordsInside
1944  */
1945 //=============================================================================
1946 std::vector<bool>
1947 GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object)        theShape,
1948                                              const std::vector<double>& coords,
1949                                              double                     tolerance)
1950 {
1951   std::vector<bool> isInsideRes;
1952   if (!theShape.IsNull()) {
1953     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1954     if (!aRefShape.IsNull()) {
1955       TopoDS_Shape aShape = aRefShape->GetValue();
1956       if (!aShape.IsNull())
1957       {
1958         TopTools_IndexedMapOfShape mapShape;
1959         {
1960           TopExp_Explorer anExp;
1961           for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1962             mapShape.Add( anExp.Current() );
1963           for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1964             mapShape.Add( anExp.Current() );
1965           for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() )
1966             mapShape.Add( anExp.Current() );
1967           for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() )
1968             mapShape.Add( anExp.Current() ); //// ?????????
1969         }
1970         size_t nb_points = coords.size()/3, nb_points_inside = 0;
1971         isInsideRes.resize( nb_points, false );
1972
1973         for ( int iS = 1; iS <= mapShape.Extent(); ++iS )
1974         {
1975           if ( nb_points_inside == nb_points )
1976             break;
1977           aShape = mapShape( iS );
1978           switch ( aShape.ShapeType() ) {
1979           case TopAbs_SOLID:
1980           {
1981             BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape ));
1982             for ( size_t i = 0; i < nb_points; i++)
1983             {
1984               if ( isInsideRes[ i ]) continue;
1985               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
1986               SC.Perform( aPnt, tolerance );
1987               isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ));
1988               nb_points_inside += isInsideRes[ i ];
1989             }
1990             break;
1991           }
1992           case TopAbs_FACE:
1993           {
1994             Standard_Real u1,u2,v1,v2;
1995             const TopoDS_Face&   face = TopoDS::Face( aShape );
1996             Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
1997             surf->Bounds( u1,u2,v1,v2 );
1998             GeomAPI_ProjectPointOnSurf project;
1999             project.Init(surf, u1,u2, v1,v2, tolerance );
2000             for ( size_t i = 0; i < nb_points; i++)
2001             {
2002               if ( isInsideRes[ i ]) continue;
2003               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2004               project.Perform( aPnt );
2005               if ( project.IsDone() &&
2006                    project.NbPoints() > 0 &&
2007                    project.LowerDistance() <= tolerance )
2008               {
2009                 Standard_Real u, v;
2010                 project.LowerDistanceParameters(u, v);
2011                 gp_Pnt2d uv( u, v );
2012                 BRepClass_FaceClassifier FC ( face, uv, tolerance );
2013                 isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON ));
2014                 nb_points_inside += isInsideRes[ i ];
2015               }
2016             }
2017             break;
2018           }
2019           case TopAbs_EDGE:
2020           {
2021             Standard_Real f,l;
2022             const TopoDS_Edge&  edge = TopoDS::Edge( aShape );
2023             Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
2024             GeomAPI_ProjectPointOnCurve project;
2025             project.Init( curve, f, l );
2026             for ( size_t i = 0; i < nb_points; i++)
2027             {
2028               if ( isInsideRes[ i ]) continue;
2029               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2030               project.Perform( aPnt );
2031               isInsideRes[ i ] = ( project.NbPoints() > 0 &&
2032                                    project.LowerDistance() <= tolerance );
2033               nb_points_inside += isInsideRes[ i ];
2034             }
2035             break;
2036           }
2037           case TopAbs_VERTEX:
2038           {
2039             gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ));
2040             for ( size_t i = 0; i < nb_points; i++)
2041             {
2042               if ( isInsideRes[ i ]) continue;
2043               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2044               isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance );
2045               nb_points_inside += isInsideRes[ i ];
2046             }
2047             break;
2048           }
2049           default:;
2050           } // switch ( aShape.ShapeType() )
2051         }
2052       }
2053     }
2054   }
2055   return isInsideRes;
2056 }
2057
2058 //=============================================================================
2059 /*!
2060  *  GetMinDistance
2061  */
2062 //=============================================================================
2063 Standard_Real
2064 GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
2065                                              Handle(GEOM_Object) theShape2,
2066                                              Standard_Real& X1,
2067                                              Standard_Real& Y1,
2068                                              Standard_Real& Z1,
2069                                              Standard_Real& X2,
2070                                              Standard_Real& Y2,
2071                                              Standard_Real& Z2)
2072 {
2073   SetErrorCode(KO);
2074   Standard_Real MinDist = 1.e9;
2075
2076   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
2077
2078   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2079   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2080   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
2081
2082   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2083   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2084   if (aShape1.IsNull() || aShape2.IsNull()) {
2085     SetErrorCode("One of Objects has NULL Shape");
2086     return MinDist;
2087   }
2088
2089   //Compute the parameters
2090   try {
2091     OCC_CATCH_SIGNALS;
2092
2093     gp_Pnt aPnt1, aPnt2;
2094
2095     MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
2096
2097     if (MinDist >= 0.0) {
2098       aPnt1.Coord(X1, Y1, Z1);
2099       aPnt2.Coord(X2, Y2, Z2);
2100     } else {
2101       return MinDist;
2102     }
2103   }
2104   catch (Standard_Failure& aFail) {
2105     SetErrorCode(aFail.GetMessageString());
2106     return MinDist;
2107   }
2108
2109   SetErrorCode(OK);
2110   return MinDist;
2111 }
2112
2113 //=======================================================================
2114 /*!
2115  *  Get coordinates of closest points of two shapes
2116  */
2117 //=======================================================================
2118 Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1,
2119                                                              Handle(GEOM_Object) theShape2,
2120                                                              Handle(TColStd_HSequenceOfReal)& theDoubles)
2121 {
2122   SetErrorCode(KO);
2123   Standard_Integer nbSolutions = 0;
2124
2125   if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions;
2126
2127   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2128   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2129   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions;
2130
2131   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2132   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2133   if (aShape1.IsNull() || aShape2.IsNull()) {
2134     SetErrorCode("One of Objects has NULL Shape");
2135     return nbSolutions;
2136   }
2137
2138   // Compute the extremities
2139   try {
2140     OCC_CATCH_SIGNALS;
2141
2142     // skl 30.06.2008
2143     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
2144     gp_Pnt P1s, P2s;
2145     double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s);
2146     bool singularBetter = dist >= 0;
2147
2148     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
2149     if (dst.IsDone()) {
2150       nbSolutions = dst.NbSolution();
2151       if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2152
2153       gp_Pnt P1, P2;
2154       for (int i = 1; i <= nbSolutions; i++) {
2155         P1 = dst.PointOnShape1(i);
2156         P2 = dst.PointOnShape2(i);
2157         
2158         theDoubles->Append(P1.X());
2159         theDoubles->Append(P1.Y());
2160         theDoubles->Append(P1.Z());
2161         theDoubles->Append(P2.X());
2162         theDoubles->Append(P2.Y());
2163         theDoubles->Append(P2.Z());
2164         
2165         Standard_Real Dist = P1.Distance(P2);
2166         singularBetter = singularBetter && dist < Dist;
2167       }
2168     }
2169
2170     if (singularBetter) {
2171       if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2172       else theDoubles->Clear();
2173
2174       nbSolutions = 1;
2175     
2176       theDoubles->Append(P1s.X());
2177       theDoubles->Append(P1s.Y());
2178       theDoubles->Append(P1s.Z());
2179       theDoubles->Append(P2s.X());
2180       theDoubles->Append(P2s.Y());
2181       theDoubles->Append(P2s.Z());
2182     }
2183   }
2184   catch (Standard_Failure& aFail) {
2185     SetErrorCode(aFail.GetMessageString());
2186     return nbSolutions;
2187   }
2188
2189   SetErrorCode(OK);
2190   return nbSolutions;
2191 }
2192
2193 //=======================================================================
2194 /*!
2195  *  Get coordinates of point
2196  */
2197 //=======================================================================
2198 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
2199                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
2200 {
2201   SetErrorCode(KO);
2202
2203   if (theShape.IsNull())
2204     return;
2205
2206   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2207   if (aRefShape.IsNull())
2208     return;
2209
2210   TopoDS_Shape aShape = aRefShape->GetValue();
2211   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
2212   {
2213     SetErrorCode( "Shape must be a vertex" );
2214     return;
2215   }
2216
2217   try {
2218     OCC_CATCH_SIGNALS;
2219     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
2220     theX = aPnt.X();
2221     theY = aPnt.Y();
2222     theZ = aPnt.Z();
2223
2224     SetErrorCode(OK);
2225   }
2226   catch (Standard_Failure& aFail)
2227   {
2228     SetErrorCode( aFail.GetMessageString() );
2229   }
2230 }
2231
2232 //=======================================================================
2233 /*!
2234  *  Compute angle (in degrees) between two lines
2235  */
2236 //=======================================================================
2237 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
2238                                                      Handle(GEOM_Object) theLine2)
2239 {
2240   if (theLine1->GetType() == GEOM_VECTOR &&
2241       theLine2->GetType() == GEOM_VECTOR)
2242     return GetAngleBtwVectors(theLine1, theLine2);
2243
2244   SetErrorCode(KO);
2245
2246   Standard_Real anAngle = -1.0;
2247
2248   if (theLine1.IsNull() || theLine2.IsNull())
2249     return anAngle;
2250
2251   Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
2252   Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
2253   if (aRefLine1.IsNull() || aRefLine2.IsNull())
2254     return anAngle;
2255
2256   TopoDS_Shape aLine1 = aRefLine1->GetValue();
2257   TopoDS_Shape aLine2 = aRefLine2->GetValue();
2258   if (aLine1.IsNull() || aLine2.IsNull() ||
2259       aLine1.ShapeType() != TopAbs_EDGE ||
2260       aLine2.ShapeType() != TopAbs_EDGE)
2261   {
2262     SetErrorCode("Two edges must be given");
2263     return anAngle;
2264   }
2265
2266   try {
2267     OCC_CATCH_SIGNALS;
2268     TopoDS_Edge E1 = TopoDS::Edge(aLine1);
2269     TopoDS_Edge E2 = TopoDS::Edge(aLine2);
2270
2271     double fp,lp;
2272     Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2273     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
2274
2275     if ( C1.IsNull() || C2.IsNull() ||
2276         !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
2277         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
2278     {
2279       SetErrorCode("The edges must be linear");
2280       return anAngle;
2281     }
2282
2283     Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
2284     Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
2285
2286     gp_Lin aLin1 = L1->Lin();
2287     gp_Lin aLin2 = L2->Lin();
2288
2289     anAngle = aLin1.Angle(aLin2);
2290     anAngle *= 180. / M_PI; // convert radians into degrees
2291
2292     if (anAngle > 90.0) {
2293       anAngle = 180.0 - anAngle;
2294     }
2295
2296     SetErrorCode(OK);
2297   }
2298   catch (Standard_Failure& aFail)
2299   {
2300     SetErrorCode(aFail.GetMessageString());
2301   }
2302
2303   return anAngle;
2304 }
2305
2306 //=======================================================================
2307 /*!
2308  *  Compute angle (in degrees) between two vectors
2309  */
2310 //=======================================================================
2311 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
2312                                                                Handle(GEOM_Object) theVec2)
2313 {
2314   SetErrorCode(KO);
2315
2316   Standard_Real anAngle = -1.0;
2317
2318   if (theVec1.IsNull() || theVec2.IsNull())
2319     return anAngle;
2320
2321   if (theVec1->GetType() != GEOM_VECTOR || theVec2->GetType() != GEOM_VECTOR) {
2322     SetErrorCode("Two vectors must be given");
2323     return anAngle;
2324   }
2325
2326   Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2327   Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2328   if (aRefVec1.IsNull() || aRefVec2.IsNull())
2329     return anAngle;
2330
2331   TopoDS_Shape aVec1 = aRefVec1->GetValue();
2332   TopoDS_Shape aVec2 = aRefVec2->GetValue();
2333   if (aVec1.IsNull() || aVec2.IsNull() ||
2334       aVec1.ShapeType() != TopAbs_EDGE ||
2335       aVec2.ShapeType() != TopAbs_EDGE)
2336   {
2337     SetErrorCode("Two edges must be given");
2338     return anAngle;
2339   }
2340
2341   try {
2342     OCC_CATCH_SIGNALS;
2343     TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2344     TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2345
2346     TopoDS_Vertex aP11, aP12, aP21, aP22;
2347     TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2348     TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2349     if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2350       SetErrorCode("Bad edge given");
2351       return anAngle;
2352     }
2353
2354     gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2355     gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2356
2357     anAngle = aV1.Angle(aV2);
2358     anAngle *= 180. / M_PI; // convert radians into degrees
2359
2360     SetErrorCode(OK);
2361   }
2362   catch (Standard_Failure& aFail)
2363   {
2364     SetErrorCode(aFail.GetMessageString());
2365   }
2366
2367   return anAngle;
2368 }
2369
2370
2371 //=============================================================================
2372 /*!
2373  *  PatchFace
2374  */
2375  //=============================================================================
2376 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape)
2377 {
2378   SetErrorCode(KO);
2379
2380   if (theShape.IsNull()) return NULL;
2381
2382   Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE);
2383   Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1);
2384   if (aFunction.IsNull()) return NULL;
2385
2386   //Check if the function is set correctly
2387   if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL;
2388
2389   GEOMImpl_IPatchFace aPI(aFunction);
2390   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2391   if (aRefShape.IsNull()) return NULL;
2392
2393   aPI.SetShape(aRefShape);
2394   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2395
2396   // Perform
2397   try
2398   {
2399     OCC_CATCH_SIGNALS;
2400     if (!GetSolver()->ComputeFunction(aFunction))
2401     {
2402       SetErrorCode("patch face driver failed");
2403       return NULL;
2404     }
2405
2406     // Get result compound and collect all faces into result sequence
2407     TopoDS_Shape aResCompound = aFunction->GetValue();
2408     TopTools_IndexedMapOfShape anIndices;
2409     TopExp::MapShapes(aResCompound, anIndices);
2410
2411     Handle(TColStd_HArray1OfInteger) anArray;
2412     for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next())
2413     {
2414       TopoDS_Shape aValue = anExpW.Value();
2415       anArray = new TColStd_HArray1OfInteger(1, 1);
2416       anArray->SetValue(1, anIndices.FindIndex(aValue));
2417
2418       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray);
2419       if (!anObj.IsNull())
2420       {
2421         aSeq->Append(anObj);
2422       }
2423     }
2424   }
2425   catch (Standard_Failure& aFail)
2426   {
2427     SetErrorCode(aFail.GetMessageString());
2428     return aSeq;
2429   }
2430
2431   //Make a Python command
2432   GEOM::TPythonDump(aFunction, true)
2433     << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")";
2434
2435   SetErrorCode(OK);
2436   return aSeq;
2437 }
2438
2439 //=============================================================================
2440 /*!
2441  *  CurveCurvatureByParam
2442  */
2443 //=============================================================================
2444 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2445                         (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2446 {
2447   SetErrorCode(KO);
2448   Standard_Real aRes = -1.0;
2449
2450   if(theCurve.IsNull()) return aRes;
2451
2452   Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2453   if(aRefShape.IsNull()) return aRes;
2454
2455   TopoDS_Shape aShape = aRefShape->GetValue();
2456   if(aShape.IsNull()) {
2457     SetErrorCode("One of Objects has NULL Shape");
2458     return aRes;
2459   }
2460
2461   Standard_Real aFP, aLP, aP;
2462   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2463   aP = aFP + (aLP - aFP) * theParam;
2464
2465   if(aCurve.IsNull()) return aRes;
2466
2467   //Compute curvature
2468   try {
2469     OCC_CATCH_SIGNALS;
2470     GeomLProp_CLProps Prop = GeomLProp_CLProps
2471       (aCurve, aP, 2, Precision::Confusion());
2472     aRes = fabs(Prop.Curvature());
2473     SetErrorCode(OK);
2474   }
2475   catch (Standard_Failure& aFail) {
2476     SetErrorCode(aFail.GetMessageString());
2477     return aRes;
2478   }
2479
2480   if( aRes > Precision::Confusion() )
2481     aRes = 1/aRes;
2482   else
2483     aRes = RealLast();
2484
2485   return aRes;
2486 }
2487
2488
2489 //=============================================================================
2490 /*!
2491  *  CurveCurvatureByPoint
2492  */
2493 //=============================================================================
2494 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2495                    (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2496 {
2497   SetErrorCode(KO);
2498   Standard_Real aRes = -1.0;
2499
2500   if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2501
2502   Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2503   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2504   if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2505
2506   TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2507   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2508   if( anEdge.IsNull() || aPnt.IsNull() ) {
2509     SetErrorCode("One of Objects has NULL Shape");
2510     return aRes;
2511   }
2512
2513   Standard_Real aFP, aLP;
2514   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2515   if(aCurve.IsNull()) return aRes;
2516   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2517
2518   //Compute curvature
2519   try {
2520     OCC_CATCH_SIGNALS;
2521     GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2522     if(PPCurve.NbPoints()>0) {
2523       GeomLProp_CLProps Prop = GeomLProp_CLProps
2524         (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2525       aRes = fabs(Prop.Curvature());
2526       SetErrorCode(OK);
2527     }
2528   }
2529   catch (Standard_Failure& aFail) {
2530     SetErrorCode(aFail.GetMessageString());
2531     return aRes;
2532   }
2533
2534   if( aRes > Precision::Confusion() )
2535     aRes = 1/aRes;
2536   else
2537     aRes = RealLast();
2538
2539   return aRes;
2540 }
2541
2542
2543 //=============================================================================
2544 /*!
2545  *  getSurfaceCurvatures
2546  */
2547 //=============================================================================
2548 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2549                                           (const Handle(Geom_Surface)& aSurf,
2550                                            Standard_Real theUParam,
2551                                            Standard_Real theVParam,
2552                                            Standard_Boolean theNeedMaxCurv)
2553 {
2554   SetErrorCode(KO);
2555   Standard_Real aRes = 1.0;
2556
2557   if (aSurf.IsNull()) return aRes;
2558
2559   try {
2560     OCC_CATCH_SIGNALS;
2561     GeomLProp_SLProps Prop = GeomLProp_SLProps
2562       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2563     if(Prop.IsCurvatureDefined()) {
2564       if(Prop.IsUmbilic()) {
2565         //cout<<"is umbilic"<<endl;
2566         aRes = fabs(Prop.MeanCurvature());
2567       }
2568       else {
2569         //cout<<"is not umbilic"<<endl;
2570         double c1 = fabs(Prop.MaxCurvature());
2571         double c2 = fabs(Prop.MinCurvature());
2572         if(theNeedMaxCurv)
2573           aRes = Max(c1,c2);
2574         else
2575           aRes = Min(c1,c2);
2576       }
2577       SetErrorCode(OK);
2578     }
2579   }
2580   catch (Standard_Failure& aFail) {
2581     SetErrorCode(aFail.GetMessageString());
2582     return aRes;
2583   }
2584
2585   if( fabs(aRes) > Precision::Confusion() )
2586     aRes = 1/aRes;
2587   else
2588     aRes = RealLast();
2589
2590   return aRes;
2591 }
2592
2593
2594 //=============================================================================
2595 /*!
2596  *  MaxSurfaceCurvatureByParam
2597  */
2598 //=============================================================================
2599 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2600                                                   (Handle(GEOM_Object) theSurf,
2601                                                    Standard_Real& theUParam,
2602                                                    Standard_Real& theVParam)
2603 {
2604   SetErrorCode(KO);
2605   Standard_Real aRes = -1.0;
2606
2607   if (theSurf.IsNull()) return aRes;
2608
2609   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2610   if(aRefShape.IsNull()) return aRes;
2611
2612   TopoDS_Shape aShape = aRefShape->GetValue();
2613   if(aShape.IsNull()) {
2614     SetErrorCode("One of Objects has NULL Shape");
2615     return aRes;
2616   }
2617
2618   TopoDS_Face F = TopoDS::Face(aShape);
2619   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2620
2621   //Compute the parameters
2622   Standard_Real U1,U2,V1,V2;
2623   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2624   Standard_Real U = U1 + (U2-U1)*theUParam;
2625   Standard_Real V = V1 + (V2-V1)*theVParam;
2626
2627   return getSurfaceCurvatures(aSurf, U, V, true);
2628 }
2629
2630
2631 //=============================================================================
2632 /*!
2633  *  MaxSurfaceCurvatureByPoint
2634  */
2635 //=============================================================================
2636 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2637                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2638 {
2639   SetErrorCode(KO);
2640   Standard_Real aRes = -1.0;
2641
2642   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2643
2644   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2645   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2646   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2647
2648   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2649   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2650   if( aFace.IsNull() || aPnt.IsNull() ) {
2651     SetErrorCode("One of Objects has NULL Shape");
2652     return 0;
2653   }
2654
2655   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2656   if(aSurf.IsNull()) return aRes;
2657   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2658
2659   //Compute the parameters
2660   ShapeAnalysis_Surface sas(aSurf);
2661   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2662
2663   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2664 }
2665
2666
2667 //=============================================================================
2668 /*!
2669  *  MinSurfaceCurvatureByParam
2670  */
2671 //=============================================================================
2672 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2673                                                   (Handle(GEOM_Object) theSurf,
2674                                                    Standard_Real& theUParam,
2675                                                    Standard_Real& theVParam)
2676 {
2677   SetErrorCode(KO);
2678   Standard_Real aRes = -1.0;
2679
2680   if (theSurf.IsNull()) return aRes;
2681
2682   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2683   if(aRefShape.IsNull()) return aRes;
2684
2685   TopoDS_Shape aShape = aRefShape->GetValue();
2686   if(aShape.IsNull()) {
2687     SetErrorCode("One of Objects has NULL Shape");
2688     return aRes;
2689   }
2690
2691   TopoDS_Face F = TopoDS::Face(aShape);
2692   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2693
2694   //Compute the parameters
2695   Standard_Real U1,U2,V1,V2;
2696   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2697   Standard_Real U = U1 + (U2-U1)*theUParam;
2698   Standard_Real V = V1 + (V2-V1)*theVParam;
2699
2700   return getSurfaceCurvatures(aSurf, U, V, false);
2701 }
2702
2703
2704 //=============================================================================
2705 /*!
2706  *  MinSurfaceCurvatureByPoint
2707  */
2708 //=============================================================================
2709 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2710                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2711 {
2712   SetErrorCode(KO);
2713   Standard_Real aRes = -1.0;
2714
2715   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2716
2717   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2718   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2719   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2720
2721   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2722   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2723   if( aFace.IsNull() || aPnt.IsNull() ) {
2724     SetErrorCode("One of Objects has NULL Shape");
2725     return 0;
2726   }
2727
2728   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2729   if(aSurf.IsNull()) return aRes;
2730   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2731
2732   //Compute the parameters
2733   ShapeAnalysis_Surface sas(aSurf);
2734   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2735
2736   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2737 }
2738
2739 //=============================================================================
2740 /*!
2741  *  SurfaceCurvatureByPointAndDirection
2742  */
2743 //=============================================================================
2744 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirection
2745                                                  (Handle(GEOM_Object) theSurf,
2746                                                   Handle(GEOM_Object) thePoint,
2747                                                   Handle(GEOM_Object) theDirection)
2748 {
2749   SetErrorCode(KO);
2750
2751   if (theSurf.IsNull() || thePoint.IsNull() || theDirection.IsNull()) return NULL;
2752
2753   Handle(GEOM_Function) aSurf = theSurf->GetLastFunction();
2754   Handle(GEOM_Function) aPoint = thePoint->GetLastFunction();
2755   Handle(GEOM_Function) aDirection = theDirection->GetLastFunction();
2756   if (aSurf.IsNull() || aPoint.IsNull() || aDirection.IsNull()) return NULL;
2757
2758   //Add a new CurvatureVector object
2759   //Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_CURVATURE_VEC);
2760   Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_VECTOR);
2761
2762   //Add a new CurvatureVector function
2763   Handle(GEOM_Function) aFunction =
2764     aCV->AddFunction(GEOMImpl_MeasureDriver::GetID(), CURVATURE_VEC_MEASURE);
2765   if (aFunction.IsNull()) return NULL;
2766
2767   //Check if the function is set correctly
2768   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
2769
2770   GEOMImpl_IMeasure aCI (aFunction);
2771   aCI.SetBase(aSurf);
2772   aCI.SetPoint(aPoint);
2773   aCI.SetDirection(aDirection);
2774
2775   //Compute the CurvatureVector
2776   try {
2777     OCC_CATCH_SIGNALS;
2778     if (!GetSolver()->ComputeFunction(aFunction)) {
2779       SetErrorCode("Measure driver failed to compute a surface curvature");
2780       return NULL;
2781     }
2782   }
2783   catch (Standard_Failure& aFail) {
2784     SetErrorCode(aFail.GetMessageString());
2785     return NULL;
2786   }
2787
2788   //Make a Python command
2789   GEOM::TPythonDump(aFunction) << aCV << " = geompy.CurvatureOnFace(" << theSurf
2790                                << ", " << thePoint << ", " << theDirection << ")";
2791
2792   SetErrorCode(OK);
2793   return aCV;
2794 }
2795
2796 //=============================================================================
2797 /*!
2798  *  XYZtoUV
2799  */
2800  //=============================================================================
2801 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::XYZtoUV
2802                                                   (Handle(GEOM_Object) theSurf,
2803                                                    const Handle(TColStd_HArray1OfReal)& theXYZlist,
2804                                                    bool isNormalized)
2805 {
2806   SetErrorCode(KO);
2807
2808   Handle(TColStd_HArray1OfReal) aRet;
2809
2810   // Check list of coordinates
2811   int nbC = theXYZlist->Length();
2812   int nbP = nbC / 3;
2813   if (nbP * 3 != nbC) {
2814     SetErrorCode("Coordinates list length is not divisible by 3");
2815     return aRet;
2816   }
2817
2818   // Check face
2819   if (theSurf.IsNull()) {
2820     SetErrorCode("The shape is NULL");
2821     return aRet;
2822   }
2823
2824   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2825   if (aRefShape.IsNull()) {
2826     SetErrorCode("The shape is NULL");
2827     return aRet;
2828   }
2829
2830   TopoDS_Shape aShape = aRefShape->GetValue();
2831   if (aShape.IsNull()) {
2832     SetErrorCode("The shape is NULL");
2833     return aRet;
2834   }
2835
2836   // The shape can be a face, a shell of one face or a compound with one face
2837   TopoDS_Face F;
2838   if (aShape.ShapeType() == TopAbs_FACE) {
2839     F = TopoDS::Face(aShape);
2840   }
2841   else if (aShape.ShapeType() < TopAbs_FACE) {
2842     TopExp_Explorer Exp (aShape, TopAbs_FACE);
2843     if (Exp.More()) {
2844       F = TopoDS::Face(Exp.Current());
2845       Exp.Next();
2846       if (Exp.More()) {
2847         SetErrorCode("There should be only one face");
2848         return aRet;
2849       }
2850     }
2851   }
2852   if (F.IsNull()) {
2853     SetErrorCode("There are no faces");
2854     return aRet;
2855   }
2856
2857   // Face tolerance
2858   Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
2859   squareTolerance = squareTolerance * squareTolerance;
2860
2861   // Compute parameters
2862   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2863   aRet = new TColStd_HArray1OfReal (0, nbP * 2 - 1);
2864
2865   Standard_Real U1,U2, V1,V2;
2866   BRepTools::UVBounds(F, U1, U2, V1, V2);
2867   Standard_Real dU = U2 - U1;
2868   Standard_Real dV = V2 - V1;
2869
2870   int iCLower = theXYZlist->Lower();
2871   for (int iP = 0; iP < nbP; iP++) {
2872     gp_Pnt aP (theXYZlist->Value(iCLower + iP * 3),
2873                theXYZlist->Value(iCLower + iP * 3 + 1),
2874                theXYZlist->Value(iCLower + iP * 3 + 2));
2875     Standard_Real U, V;
2876     gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V);
2877     if (aP.SquareDistance(aPonF) < squareTolerance) {
2878       if (isNormalized) {
2879         // Normalize parameters to be in [0, 1]
2880         U = (U - U1) / dU;
2881         V = (V - V1) / dV;
2882       }
2883       aRet->SetValue(iP * 2    , U);
2884       aRet->SetValue(iP * 2 + 1, V);
2885     }
2886     else {
2887       SetErrorCode("Point too far from face");
2888       return aRet;
2889     }
2890   }
2891
2892   SetErrorCode(OK);
2893   return aRet;
2894 }
2895
2896 //=============================================================================
2897 /*!
2898  *  UVtoXYZ
2899  */
2900  //=============================================================================
2901 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::UVtoXYZ
2902                                                   (Handle(GEOM_Object) theSurf,
2903                                                    const Handle(TColStd_HArray1OfReal)& theUVlist,
2904                                                    bool isNormalized)
2905 {
2906   SetErrorCode(KO);
2907
2908   Handle(TColStd_HArray1OfReal) aRet;
2909
2910   // Check list of parameters
2911   int nbC = theUVlist->Length();
2912   int nbP = nbC / 2;
2913   if (nbP * 2 != nbC) {
2914     SetErrorCode("Parameters list length is not divisible by 2");
2915     return aRet;
2916   }
2917
2918   // Check face
2919   if (theSurf.IsNull()) {
2920     SetErrorCode("The shape is NULL");
2921     return aRet;
2922   }
2923
2924   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2925   if (aRefShape.IsNull()) {
2926     SetErrorCode("The shape is NULL");
2927     return aRet;
2928   }
2929
2930   TopoDS_Shape aShape = aRefShape->GetValue();
2931   if (aShape.IsNull()) {
2932     SetErrorCode("The shape is NULL");
2933     return aRet;
2934   }
2935
2936   // The shape can be a face, a shell of one face or a compound with one face
2937   TopoDS_Face F;
2938   if (aShape.ShapeType() == TopAbs_FACE) {
2939     F = TopoDS::Face(aShape);
2940   }
2941   else if (aShape.ShapeType() < TopAbs_FACE) {
2942     TopExp_Explorer Exp (aShape, TopAbs_FACE);
2943     if (Exp.More()) {
2944       F = TopoDS::Face(Exp.Current());
2945       Exp.Next();
2946       if (Exp.More()) {
2947         SetErrorCode("There should be only one face");
2948         return aRet;
2949       }
2950     }
2951   }
2952   if (F.IsNull()) {
2953     SetErrorCode("There are no faces");
2954     return aRet;
2955   }
2956
2957   // Face tolerance
2958   Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
2959   squareTolerance = squareTolerance * squareTolerance;
2960
2961   // Compute coordinates
2962   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2963   aRet = new TColStd_HArray1OfReal (0, nbP * 3 - 1);
2964
2965   Standard_Real U1,U2, V1,V2;
2966   BRepTools::UVBounds(F, U1, U2, V1, V2);
2967   Standard_Real dU = U2 - U1;
2968   Standard_Real dV = V2 - V1;
2969
2970   Standard_Real tol = 1.e-4;
2971   Standard_Real pc = Precision::Confusion();
2972
2973   int iCLower = theUVlist->Lower();
2974   for (int iP = 0; iP < nbP; iP++) {
2975     Standard_Real U = theUVlist->Value(iCLower + iP * 2);
2976     Standard_Real V = theUVlist->Value(iCLower + iP * 2 + 1);
2977
2978     if (isNormalized) {
2979       // Get real parameters from given normalized ones in [0, 1]
2980       if (!(-pc < U && U < 1 + pc) || !(-pc < V && V < 1 + pc)) {
2981         SetErrorCode("Normalized parameter is out of range [0,1]");
2982         return aRet;
2983       }
2984       U = U1 + dU * U;
2985       V = V1 + dV * V;
2986     }
2987
2988     gp_Pnt2d aP2d (U, V);
2989
2990     BRepClass_FaceClassifier aClsf (F, aP2d, tol);
2991     if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
2992       SetErrorCode("Given parameters are out of face");
2993       return aRet;
2994     }
2995     gp_Pnt surfPnt = aSurf->Value(U, V);
2996
2997     aRet->SetValue(iP * 3    , surfPnt.X());
2998     aRet->SetValue(iP * 3 + 1, surfPnt.Y());
2999     aRet->SetValue(iP * 3 + 2, surfPnt.Z());
3000   }
3001
3002   SetErrorCode(OK);
3003   return aRet;
3004 }
3005
3006 //=============================================================================
3007 /*!
3008  *  SelfIntersected2D
3009  *  Find all self-intersected 2D curves.
3010  *  \param theChecks list of failed checks, contains type of check and failed shapes
3011  */
3012  //=============================================================================
3013 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3014   GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list<FailedChecks>& theChecks)
3015 {
3016   SetErrorCode(KO);
3017   MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D");
3018
3019   std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters2D;
3020   try
3021   {
3022     OCC_CATCH_SIGNALS;
3023     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3024          anIter != theChecks.end(); ++anIter)
3025     {
3026       if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3027         aSelfInters2D.push_back(anIter->FailedShapes);
3028     }
3029   }
3030   catch (Standard_Failure& aFail)
3031   {
3032     SetErrorCode(aFail.GetMessageString());
3033     return aSelfInters2D;
3034   }
3035
3036   SetErrorCode(OK);
3037   return aSelfInters2D;
3038 }
3039
3040 namespace
3041 {
3042   static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes,
3043                          const int theShapeType1,
3044                          const int theShapeType2)
3045   {
3046     if (theShapeType1 == -1 && theShapeType2 == -1)
3047       return true;
3048
3049     TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull()
3050       ? TopAbs_SHAPE
3051       : theShapes.first->GetValue().ShapeType();
3052     TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull()
3053       ? TopAbs_SHAPE
3054       : theShapes.second->GetValue().ShapeType();
3055
3056     if (theShapeType1 == -1)
3057       return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2;
3058     else if (theShapeType2 == -1)
3059       return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1;
3060     return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) ||
3061       (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1);
3062   }
3063 } // namespace
3064
3065 //=============================================================================
3066 /*!
3067  *  InterferingSubshapes
3068  *  Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
3069  *  \param theChecks list of failed checks, contains type of check and failed shapes
3070  *  \param theShapeType1 Type of shape.
3071  *  \param theShapeType2 Type of shape.
3072  */
3073  //=============================================================================
3074 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3075   GEOMImpl_IMeasureOperations::InterferingSubshapes
3076     (const std::list<FailedChecks>& theChecks,
3077      const int                      theShapeType1,
3078      const int                      theShapeType2)
3079 {
3080   SetErrorCode(KO);
3081   MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes");
3082
3083   std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> anInterfer;
3084   try
3085   {
3086     OCC_CATCH_SIGNALS;
3087     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3088          anIter != theChecks.end(); ++anIter)
3089     {
3090       if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect &&
3091           checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2))
3092         anInterfer.push_back(anIter->FailedShapes);
3093     }
3094   }
3095   catch (Standard_Failure& aFail)
3096   {
3097     SetErrorCode(aFail.GetMessageString());
3098     return anInterfer;
3099   }
3100
3101   SetErrorCode(OK);
3102   return anInterfer;
3103 }
3104
3105 //=============================================================================
3106 /*!
3107  *  SmallEdges
3108  *  Find edges, which are fully covered by tolerances of vertices.
3109  *  \param theChecks list of failed checks, contains type of check and failed shapes
3110  */
3111  //=============================================================================
3112 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges(
3113     const std::list<FailedChecks>& theChecks)
3114 {
3115   SetErrorCode(KO);
3116   MESSAGE("GEOMImpl_IMeasureOperations::smallEdges");
3117
3118   Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient;
3119   try
3120   {
3121     OCC_CATCH_SIGNALS;
3122     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3123          anIter != theChecks.end(); ++anIter)
3124     {
3125       if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge)
3126         aSmallEdges->Append(anIter->FailedShapes.first);
3127     }
3128   }
3129   catch (Standard_Failure& aFail)
3130   {
3131     SetErrorCode(aFail.GetMessageString());
3132     return NULL;
3133   }
3134
3135   SetErrorCode(OK);
3136   return aSmallEdges;
3137 }
3138
3139 //=============================================================================
3140 /*!
3141  *  DistantShapes
3142  *  find remote objects (sub-shape on a shape).
3143  *  \param theShape Shape for check.
3144  *  \param theShapeType Type of shape.
3145  *  \param theSubShapeType Type of sub-shape.
3146  *  \param theTolerance tolerance.
3147  */
3148  //=============================================================================
3149 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3150   GEOMImpl_IMeasureOperations::DistantShapes
3151     (const std::list<FailedChecks>& theChecks,
3152      const int                      theShapeType,
3153      const int                      theSubShapeType,
3154      double                         theTolerance)
3155 {
3156   SetErrorCode(KO);
3157   MESSAGE("GEOMImpl_IMeasureOperations::distantShapes");
3158
3159   std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistShapes;
3160   try
3161   {
3162     OCC_CATCH_SIGNALS;
3163     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3164          anIter != theChecks.end(); ++anIter)
3165     {
3166       Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first;
3167       Handle(GEOM_Object) aShape = anIter->FailedShapes.second;
3168       if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface ||
3169            anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex ||
3170            anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge ||
3171            anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) &&
3172           aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) &&
3173           aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType))
3174       {
3175         gp_XYZ aP1, aP2;
3176         Standard_Real aDist = Precision::Infinite();
3177         if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3178           aDist = ComputeTolerance(aSubShape, aShape);
3179         if (aDist > theTolerance)
3180           aDistShapes.push_back(anIter->FailedShapes);
3181       }
3182     }
3183   }
3184   catch (Standard_Failure& aFail)
3185   {
3186     SetErrorCode(aFail.GetMessageString());
3187     return aDistShapes;
3188   }
3189
3190   SetErrorCode(OK);
3191   return aDistShapes;
3192 }
3193
3194 //=============================================================================
3195 /*!
3196  *  CheckConformityShape
3197  *  Perform analyse of shape and find imperfections in the shape.
3198  *  \param theShape Shape for analyse.
3199  */
3200  //=============================================================================
3201 void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list<FailedChecks>& theChecks)
3202 {
3203   SetErrorCode(KO);
3204   MESSAGE("GEOMImpl_IMeasureOperations::checkShape");
3205
3206   Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3207   Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE);
3208   if (aFunction.IsNull()) return;
3209
3210   //Check if the function is set correctly
3211   if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return;
3212
3213   GEOMImpl_IConformity aCI(aFunction);
3214
3215   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3216   if (aRefShape.IsNull()) return;
3217
3218   aCI.SetShape(aRefShape);
3219
3220   try
3221   {
3222     OCC_CATCH_SIGNALS;
3223     if (!GetSolver()->ComputeFunction(aFunction))
3224     {
3225       SetErrorCode("Failed: checkShape");
3226       return;
3227     }
3228     Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS);
3229     Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices();
3230     if (aRes.IsNull())
3231       return;
3232
3233     for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex)
3234     {
3235       std::pair<Handle(GEOM_Object), Handle(GEOM_Object)> aPair;
3236       Handle(TColStd_HArray1OfInteger) anArray;
3237       anArray = new TColStd_HArray1OfInteger(1, 1);
3238       anArray->SetValue(1, aRes->Value(anIndex, 1));
3239
3240       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3241       if (!anObj.IsNull())
3242         aPair.first = anObj;
3243
3244       anArray = new TColStd_HArray1OfInteger(1, 1);
3245       anArray->SetValue(1, aRes->Value(anIndex, 2));
3246
3247       anObj = GetEngine()->AddSubShape(theShape, anArray);
3248       if (!anObj.IsNull())
3249         aPair.second = anObj;
3250       theChecks.push_back({ aTypesChecks->Value(anIndex), aPair });
3251     }
3252   }
3253   catch (Standard_Failure& aFail)
3254   {
3255     SetErrorCode(aFail.GetMessageString());
3256     return;
3257   }
3258
3259   SetErrorCode(OK);
3260   return;
3261 }
3262
3263 //=============================================================================
3264 /*!
3265  *  UpdateTolerance
3266  *  Compute possible tolerance for the shape, minimize tolerance of shape as well
3267  *  as tolerance of sub-shapes as much as possible
3268  *  \param theShape Shape for compute tolerance.
3269  */
3270  //=============================================================================
3271 double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape)
3272 {
3273   SetErrorCode(KO);
3274   MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance");
3275
3276   double aResTol = -1;
3277   Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3278   Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL);
3279   if (aFunction.IsNull()) return aResTol;
3280
3281   //Check if the function is set correctly
3282   if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol;
3283
3284   GEOMImpl_IConformity aCI(aFunction);
3285
3286   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3287   if (aRefShape.IsNull()) return aResTol;
3288
3289   aCI.SetShape(aRefShape);
3290
3291   try
3292   {
3293     OCC_CATCH_SIGNALS;
3294     if (!GetSolver()->ComputeFunction(aFunction))
3295     {
3296       SetErrorCode("Failed: updateTolerance");
3297       return aResTol;
3298     }
3299     aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE);
3300   }
3301   catch (Standard_Failure& aFail)
3302   {
3303     SetErrorCode(aFail.GetMessageString());
3304     return aResTol;
3305   }
3306
3307   SetErrorCode(OK);
3308   return aResTol;
3309 }
3310
3311 //=============================================================================
3312 /*!
3313  *  ComputeTolerance
3314  *  Compute distance from the edge to the face.
3315  */
3316  //=============================================================================
3317 double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge,
3318                                                      Handle(GEOM_Object) theFace)
3319 {
3320   double aMaxDist = Precision::Infinite();
3321   if (theEdge.IsNull() || theFace.IsNull())
3322     return aMaxDist;
3323
3324   Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction();
3325   Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
3326   if (aRefEdge.IsNull() || aRefFace.IsNull())
3327     return aMaxDist;
3328
3329   TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue());
3330   TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue());
3331   if (aEdge.IsNull() || aFace.IsNull())
3332     return aMaxDist;
3333
3334   double aParam = 0.0;
3335   BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam);
3336   return aMaxDist;
3337 }
3338
3339 //=======================================================================
3340 //function : FillErrorsSub
3341 //purpose  : Fill the errors list of subshapes on shape.
3342 //=======================================================================
3343 void GEOMImpl_IMeasureOperations::FillErrorsSub
3344            (const BRepCheck_Analyzer                   &theAna,
3345             const TopoDS_Shape                         &theShape,
3346             const TopAbs_ShapeEnum                     theSubType,
3347                   TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
3348 {
3349   TopExp_Explorer anExp(theShape, theSubType);
3350   TopTools_MapOfShape aMapSubShapes;
3351
3352   for (; anExp.More(); anExp.Next()) {
3353     const TopoDS_Shape &aSubShape = anExp.Current();
3354
3355     if (aMapSubShapes.Add(aSubShape)) {
3356       const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
3357
3358       for (aRes->InitContextIterator();
3359            aRes->MoreShapeInContext(); 
3360            aRes->NextShapeInContext()) {
3361         if (aRes->ContextualShape().IsSame(theShape)) {
3362           BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
3363
3364           if (itl.Value() != BRepCheck_NoError) {
3365             // Add all errors for theShape and its sub-shape.
3366             for (;itl.More(); itl.Next()) {
3367               const Standard_Integer aStat = (Standard_Integer)itl.Value();
3368
3369               if (!theMapErrors.IsBound(aStat)) {
3370                 TopTools_ListOfShape anEmpty;
3371
3372                 theMapErrors.Bind(aStat, anEmpty);
3373               }
3374
3375               TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
3376
3377               theShapes.Append(aSubShape);
3378               theShapes.Append(theShape);
3379             }
3380           }
3381         }
3382
3383         break;
3384       }
3385     }
3386   }
3387 }
3388
3389 //=======================================================================
3390 //function : FillErrors
3391 //purpose  : Fill the errors list.
3392 //=======================================================================
3393 void GEOMImpl_IMeasureOperations::FillErrors
3394              (const BRepCheck_Analyzer                   &theAna,
3395               const TopoDS_Shape                         &theShape,
3396                     TopTools_DataMapOfIntegerListOfShape &theMapErrors,
3397                     TopTools_MapOfShape                  &theMapShapes) const
3398 {
3399   if (theMapShapes.Add(theShape)) {
3400     // Fill errors of child shapes.
3401     for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
3402       FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
3403     }
3404
3405     // Fill errors of theShape.
3406     const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
3407
3408     if (!aRes.IsNull()) {
3409       BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
3410
3411       if (itl.Value() != BRepCheck_NoError) {
3412         // Add all errors for theShape.
3413         for (;itl.More(); itl.Next()) {
3414           const Standard_Integer aStat = (Standard_Integer)itl.Value();
3415
3416           if (!theMapErrors.IsBound(aStat)) {
3417             TopTools_ListOfShape anEmpty;
3418
3419             theMapErrors.Bind(aStat, anEmpty);
3420           }
3421
3422           theMapErrors.ChangeFind(aStat).Append(theShape);
3423         }
3424       }
3425     }
3426
3427     // Add errors of subshapes on theShape.
3428     const TopAbs_ShapeEnum aType = theShape.ShapeType();
3429
3430     switch (aType) {
3431     case TopAbs_EDGE:
3432       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3433       break;
3434     case TopAbs_FACE:
3435       FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
3436       FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
3437       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3438       break;
3439     case TopAbs_SOLID:
3440       FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
3441       break;
3442     default:
3443       break;
3444     }
3445   }
3446 }
3447
3448 //=======================================================================
3449 //function : FillErrors
3450 //purpose  : Fill the errors list.
3451 //=======================================================================
3452 void GEOMImpl_IMeasureOperations::FillErrors
3453                   (const BRepCheck_Analyzer    &theAna,
3454                    const TopoDS_Shape          &theShape,
3455                          std::list<ShapeError> &theErrors) const
3456 {
3457   // Fill the errors map.
3458   TopTools_DataMapOfIntegerListOfShape aMapErrors;
3459   TopTools_MapOfShape                  aMapShapes;
3460
3461   FillErrors(theAna, theShape, aMapErrors, aMapShapes);
3462
3463   // Map sub-shapes and their indices
3464   TopTools_IndexedMapOfShape anIndices;
3465
3466   TopExp::MapShapes(theShape, anIndices);
3467
3468   TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
3469
3470   for (; aMapIter.More(); aMapIter.Next()) {
3471     ShapeError anError;
3472
3473     anError.error = (BRepCheck_Status)aMapIter.Key();
3474
3475     TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
3476     TopTools_MapOfShape                aMapUnique;
3477
3478     for (; aListIter.More(); aListIter.Next()) {
3479       const TopoDS_Shape &aShape = aListIter.Value();
3480
3481       if (aMapUnique.Add(aShape)) {
3482         const Standard_Integer anIndex = anIndices.FindIndex(aShape);
3483
3484         anError.incriminated.push_back(anIndex);
3485       }
3486     }
3487
3488     if (!anError.incriminated.empty()) {
3489       theErrors.push_back(anError);
3490     }
3491   }
3492 }
3493
3494 //=======================================================================
3495 //function : ShapeProximityCalculator
3496 //purpose  : returns an object to compute the proximity value
3497 //=======================================================================
3498 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator
3499                                           (Handle(GEOM_Object) theShape1,
3500                                            Handle(GEOM_Object) theShape2)
3501 {
3502   SetErrorCode(KO);
3503
3504   if (theShape1.IsNull() || theShape2.IsNull())
3505     return NULL;
3506
3507   Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction();
3508   Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction();
3509   if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
3510     return NULL;
3511
3512   Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY);
3513   if (aProximityCalc.IsNull())
3514     return NULL;
3515
3516   Handle(GEOM_Function) aProximityFuncCoarse =
3517       aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE);
3518   //Check if the function is set correctly
3519   if (aProximityFuncCoarse.IsNull() ||
3520       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3521     return NULL;
3522
3523   GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3524   aProximity.SetShapes(aShapeFunc1, aShapeFunc2);
3525
3526   //Make a Python command
3527   GEOM::TPythonDump pd (aProximityFuncCoarse);
3528   pd << "p = geompy.ShapeProximity()\n";
3529   pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")";
3530
3531   SetErrorCode(OK);
3532   return aProximityCalc;
3533 }
3534
3535 //=======================================================================
3536 //function : SetShapeSampling
3537 //purpose  : set number sample points to compute the coarse proximity
3538 //=======================================================================
3539 void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator,
3540                                                    Handle(GEOM_Object) theShape,
3541                                                    const Standard_Integer theNbSamples)
3542 {
3543   SetErrorCode(KO);
3544   if (theShape.IsNull() ||
3545       theCalculator.IsNull() ||
3546       theCalculator->GetNbFunctions() <= 0 ||
3547       theNbSamples <= 0)
3548     return ;
3549
3550   Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3551   if (aProximityFuncCoarse.IsNull() ||
3552       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3553     return ;
3554
3555   Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction();
3556   if (aShapeFunc.IsNull())
3557     return ;
3558
3559   GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
3560   Handle(GEOM_Function) aShape1, aShape2;
3561   aProximity.GetShapes(aShape1, aShape2);
3562   if (aShape1->GetValue() == aShapeFunc->GetValue())
3563     aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples);
3564   else if (aShape2->GetValue() == aShapeFunc->GetValue())
3565     aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples);
3566
3567   //Make a Python command
3568   GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) <<
3569     "p.setSampling(" << theShape << ", " << theNbSamples << ")";
3570
3571   SetErrorCode(OK);
3572 }
3573
3574 //=======================================================================
3575 //function : GetCoarseProximity
3576 //purpose  : compute coarse proximity
3577 //=======================================================================
3578 Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator,
3579                                                               bool doPythonDump)
3580 {
3581   SetErrorCode(KO);
3582   if (theCalculator.IsNull())
3583     return -1;
3584
3585   Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3586   if (aProximityFuncCoarse.IsNull() ||
3587       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3588       aProximityFuncCoarse->GetType() != PROXIMITY_COARSE)
3589     return -1;
3590
3591   // Perform
3592   // We have to recompute the function each time,
3593   // because the number of samples can be changed
3594   try {
3595     OCC_CATCH_SIGNALS;
3596     if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) {
3597       SetErrorCode("shape proximity driver failed");
3598       return -1;
3599     }
3600   }
3601   catch (Standard_Failure& aFail) {
3602     SetErrorCode(aFail.GetMessageString());
3603     return -1;
3604   }
3605
3606   //Make a Python command
3607   if (doPythonDump)
3608     GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()";
3609
3610   SetErrorCode(OK);
3611   GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3612   return aProximity.GetValue();
3613 }
3614
3615 //=======================================================================
3616 //function : GetPreciseProximity
3617 //purpose  : compute precise proximity
3618 //=======================================================================
3619 Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
3620 {
3621   SetErrorCode(KO);
3622   if (theCalculator.IsNull())
3623     return -1;
3624
3625   Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3626   Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2);
3627   if (aProximityFuncFine.IsNull())
3628     aProximityFuncFine = theCalculator->AddFunction
3629       (GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE);
3630
3631   //Check if the functions are set correctly
3632   if (aProximityFuncCoarse.IsNull() ||
3633       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3634       aProximityFuncFine.IsNull() ||
3635       aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3636     return -1;
3637
3638   // perform coarse computation beforehand
3639   GetCoarseProximity(theCalculator, /*doPythonDump=*/false);
3640
3641   // transfer parameters from the coarse to precise calculator
3642   GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse);
3643   Handle(GEOM_Function) aShape1, aShape2;
3644   aCoarseProximity.GetShapes(aShape1, aShape2);
3645   if (aShape1.IsNull() || aShape2.IsNull())
3646     return -1;
3647   gp_Pnt aProxPnt1, aProxPnt2;
3648   Standard_Integer intStatus1, intStatus2;
3649   aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3650   aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2);
3651   Standard_Real aResultValue = aCoarseProximity.GetValue();
3652
3653   GEOMImpl_IProximity aFineProximity (aProximityFuncFine);
3654   aFineProximity.SetShapes(aShape1, aShape2);
3655   aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2);
3656   aFineProximity.SetStatusOfPoints(intStatus1, intStatus2);
3657   aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised
3658
3659   // Perform
3660   try {
3661     OCC_CATCH_SIGNALS;
3662     if (!GetSolver()->ComputeFunction(aProximityFuncFine)) {
3663       SetErrorCode("shape proximity driver failed");
3664       return -1;
3665     }
3666   }
3667   catch (Standard_Failure& aFail) {
3668     SetErrorCode(aFail.GetMessageString());
3669     return -1;
3670   }
3671
3672   aResultValue = aFineProximity.GetValue();
3673   aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3674
3675   //Make a Python command
3676   GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()";
3677
3678   SetErrorCode(OK);
3679   return aResultValue;
3680 }