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