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