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