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