Salome HOME
0023450: Fields are not displayed in GEOM
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <GEOMImpl_IMeasureOperations.hxx>
24 #include <GEOMImpl_IMeasure.hxx>
25 #include <GEOMImpl_MeasureDriver.hxx>
26 #include <GEOMImpl_Types.hxx>
27
28 #include <GEOMUtils.hxx>
29
30 #include <GEOMAlgo_AlgoTools.hxx>
31 #include <GEOMAlgo_KindOfName.hxx>
32 #include <GEOMAlgo_ShapeInfoFiller.hxx>
33
34 #include <GEOM_PythonDump.hxx>
35
36 #include <utilities.h>
37
38 // OCCT Includes
39 #include <Bnd_Box.hxx>
40 #include <BOPAlgo_CheckerSI.hxx>
41 #include <BOPCol_ListOfShape.hxx>
42 #include <BOPDS_DS.hxx>
43 #include <BOPDS_MapOfPassKey.hxx>
44 #include <BOPDS_MapOfPair.hxx>
45 #include <BOPDS_Pair.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 #include <BRepExtrema_SelfIntersection.hxx>
55 #include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
56 #include <BRepGProp.hxx>
57 #include <BRepTools.hxx>
58 #include <BRep_Tool.hxx>
59 #include <Geom_Line.hxx>
60 #include <GeomAPI_ProjectPointOnCurve.hxx>
61 #include <GeomAPI_ProjectPointOnSurf.hxx>
62 #include <GeomLProp_CLProps.hxx>
63 #include <GeomLProp_SLProps.hxx>
64 #include <Geom_Plane.hxx>
65 #include <GProp_GProps.hxx>
66 #include <GProp_PrincipalProps.hxx>
67 #include <ShapeAnalysis.hxx>
68 #include <ShapeAnalysis_Surface.hxx>
69 #include <TopExp.hxx>
70 #include <TopExp_Explorer.hxx>
71 #include <TopoDS.hxx>
72 #include <TopoDS_Edge.hxx>
73 #include <TopTools_IndexedMapOfShape.hxx>
74 #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
75 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
76 #include <TopTools_ListIteratorOfListOfShape.hxx>
77 #include <TopTools_ListOfShape.hxx>
78 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
79
80 #include <set>
81
82 //=============================================================================
83 /*!
84  *  Constructor
85  */
86 //=============================================================================
87 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID)
88 : GEOM_IOperations(theEngine, theDocID)
89 {
90   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
91 }
92
93 //=============================================================================
94 /*!
95  *  Destructor
96  */
97 //=============================================================================
98 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
99 {
100   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
101 }
102
103 //=============================================================================
104 /*! Get kind and parameters of the given shape.
105  */
106 //=============================================================================
107 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
108                              (Handle(GEOM_Object) theShape,
109                               Handle(TColStd_HSequenceOfInteger)& theIntegers,
110                               Handle(TColStd_HSequenceOfReal)&    theDoubles)
111 {
112   SetErrorCode(KO);
113   ShapeKind aKind = SK_NO_SHAPE;
114
115   if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
116   else                      theIntegers->Clear();
117
118   if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
119   else                     theDoubles->Clear();
120
121   if (theShape.IsNull())
122     return aKind;
123
124   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
125   if (aRefShape.IsNull()) return aKind;
126
127   TopoDS_Shape aShape = aRefShape->GetValue();
128   if (aShape.IsNull()) return aKind;
129
130   int geom_type = theShape->GetType();
131
132   // check if it's advanced shape
133   if ( geom_type > USER_TYPE ) {
134     SetErrorCode(OK);
135     return SK_ADVANCED;
136   }
137
138   // Call algorithm
139   GEOMAlgo_ShapeInfoFiller aSF;
140   aSF.SetShape(aShape);
141   aSF.Perform();
142
143   Standard_Integer iErr = aSF.ErrorStatus();
144
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                                                       const Standard_Real theTolerance,
969                                                       Standard_Real& theLength,
970                                                       Standard_Real& theSurfArea,
971                                                       Standard_Real& theVolume)
972 {
973   SetErrorCode(KO);
974
975   if (theShape.IsNull()) return;
976
977   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
978   if (aRefShape.IsNull()) return;
979
980   TopoDS_Shape aShape = aRefShape->GetValue();
981   if (aShape.IsNull()) {
982     SetErrorCode("The Objects has NULL Shape");
983     return;
984   }
985
986   //Compute the parameters
987   GProp_GProps LProps, SProps;
988   Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
989   try {
990     OCC_CATCH_SIGNALS;
991     BRepGProp::LinearProperties(aShape, LProps, Standard_True);
992     theLength = LProps.Mass();
993
994     BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
995     theSurfArea = SProps.Mass();
996
997     theVolume = 0.0;
998     if (aShape.ShapeType() < TopAbs_SHELL) {
999       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1000         GProp_GProps VProps;
1001         BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
1002         theVolume += VProps.Mass();
1003       }
1004     }
1005   }
1006   catch (Standard_Failure) {
1007     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1008     SetErrorCode(aFail->GetMessageString());
1009     return;
1010   }
1011
1012   SetErrorCode(OK);
1013 }
1014
1015 //=============================================================================
1016 /*!
1017  *  GetInertia
1018  */
1019 //=============================================================================
1020 void GEOMImpl_IMeasureOperations::GetInertia
1021                    (Handle(GEOM_Object) theShape,
1022                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1023                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1024                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1025                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1026 {
1027   SetErrorCode(KO);
1028
1029   if (theShape.IsNull()) return;
1030
1031   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1032   if (aRefShape.IsNull()) return;
1033
1034   TopoDS_Shape aShape = aRefShape->GetValue();
1035   if (aShape.IsNull()) {
1036     SetErrorCode("The Objects has NULL Shape");
1037     return;
1038   }
1039
1040   //Compute the parameters
1041   GProp_GProps System;
1042
1043   try {
1044     OCC_CATCH_SIGNALS;
1045     if (aShape.ShapeType() == TopAbs_VERTEX ||
1046         aShape.ShapeType() == TopAbs_EDGE ||
1047         aShape.ShapeType() == TopAbs_WIRE) {
1048       BRepGProp::LinearProperties(aShape, System, Standard_True);
1049     } else if (aShape.ShapeType() == TopAbs_FACE ||
1050                aShape.ShapeType() == TopAbs_SHELL) {
1051       BRepGProp::SurfaceProperties(aShape, System, Standard_True);
1052     } else {
1053       BRepGProp::VolumeProperties(aShape, System, Standard_True);
1054     }
1055     gp_Mat I = System.MatrixOfInertia();
1056
1057     I11 = I(1,1);
1058     I12 = I(1,2);
1059     I13 = I(1,3);
1060
1061     I21 = I(2,1);
1062     I22 = I(2,2);
1063     I23 = I(2,3);
1064
1065     I31 = I(3,1);
1066     I32 = I(3,2);
1067     I33 = I(3,3);
1068
1069     GProp_PrincipalProps Pr = System.PrincipalProperties();
1070     Pr.Moments(Ix,Iy,Iz);
1071   }
1072   catch (Standard_Failure) {
1073     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1074     SetErrorCode(aFail->GetMessageString());
1075     return;
1076   }
1077
1078   SetErrorCode(OK);
1079 }
1080
1081 //=============================================================================
1082 /*!
1083  *  GetBoundingBox
1084  */
1085 //=============================================================================
1086 void GEOMImpl_IMeasureOperations::GetBoundingBox
1087                                      (Handle(GEOM_Object) theShape,
1088                                       const Standard_Boolean precise,
1089                                       Standard_Real& Xmin, Standard_Real& Xmax,
1090                                       Standard_Real& Ymin, Standard_Real& Ymax,
1091                                       Standard_Real& Zmin, Standard_Real& Zmax)
1092 {
1093   SetErrorCode(KO);
1094
1095   if (theShape.IsNull()) return;
1096
1097   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1098   if (aRefShape.IsNull()) return;
1099
1100   TopoDS_Shape aShape = aRefShape->GetValue();
1101   if (aShape.IsNull()) {
1102     SetErrorCode("The Objects has NULL Shape");
1103     return;
1104   }
1105
1106   //Compute the parameters
1107   Bnd_Box B;
1108
1109   try {
1110     OCC_CATCH_SIGNALS;
1111     BRepBuilderAPI_Copy aCopyTool (aShape);
1112     if (!aCopyTool.IsDone()) {
1113       SetErrorCode("GetBoundingBox Error: Bad shape detected");
1114       return;
1115     }
1116
1117     aShape = aCopyTool.Shape();
1118
1119     // remove triangulation to obtain more exact boundaries
1120     BRepTools::Clean(aShape);
1121
1122     BRepBndLib::Add(aShape, B);
1123
1124     if (precise) {
1125       if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
1126         SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
1127         return;
1128       }
1129     }
1130
1131     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1132   }
1133   catch (Standard_Failure) {
1134     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1135     SetErrorCode(aFail->GetMessageString());
1136     return;
1137   }
1138
1139   SetErrorCode(OK);
1140 }
1141
1142 //=============================================================================
1143 /*!
1144  *  GetBoundingBox
1145  */
1146 //=============================================================================
1147 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
1148                                                 (Handle(GEOM_Object) theShape,
1149                                                  const Standard_Boolean precise)
1150 {
1151   SetErrorCode(KO);
1152
1153   if (theShape.IsNull()) return NULL;
1154
1155   //Add a new BoundingBox object
1156   Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GetDocID(), GEOM_BOX);
1157
1158   //Add a new BoundingBox function
1159   const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
1160   Handle(GEOM_Function) aFunction =
1161     aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
1162   if (aFunction.IsNull()) return NULL;
1163
1164   //Check if the function is set correctly
1165   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1166
1167   GEOMImpl_IMeasure aCI (aFunction);
1168
1169   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1170   if (aRefShape.IsNull()) return NULL;
1171
1172   aCI.SetBase(aRefShape);
1173
1174   //Compute the BoundingBox value
1175   try {
1176     OCC_CATCH_SIGNALS;
1177     if (!GetSolver()->ComputeFunction(aFunction)) {
1178       SetErrorCode("Measure driver failed to compute a bounding box");
1179       return NULL;
1180     }
1181   }
1182   catch (Standard_Failure) {
1183     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1184     SetErrorCode(aFail->GetMessageString());
1185     return NULL;
1186   }
1187
1188   //Make a Python command
1189   GEOM::TPythonDump aPd(aFunction);
1190   
1191   aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
1192
1193   if (precise) {
1194     aPd << ", True";
1195   }
1196
1197   aPd << ")";
1198
1199   SetErrorCode(OK);
1200   return aBnd;
1201 }
1202
1203 //=============================================================================
1204 /*!
1205  *  GetTolerance
1206  */
1207 //=============================================================================
1208 void GEOMImpl_IMeasureOperations::GetTolerance
1209                                (Handle(GEOM_Object) theShape,
1210                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1211                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1212                                 Standard_Real& VertMin, Standard_Real& VertMax)
1213 {
1214   SetErrorCode(KO);
1215
1216   if (theShape.IsNull()) return;
1217
1218   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1219   if (aRefShape.IsNull()) return;
1220
1221   TopoDS_Shape aShape = aRefShape->GetValue();
1222   if (aShape.IsNull()) {
1223     SetErrorCode("The Objects has NULL Shape");
1224     return;
1225   }
1226
1227   //Compute the parameters
1228   Standard_Real T;
1229   FaceMin = EdgeMin = VertMin = RealLast();
1230   FaceMax = EdgeMax = VertMax = -RealLast();
1231
1232   try {
1233     OCC_CATCH_SIGNALS;
1234     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1235       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1236       T = BRep_Tool::Tolerance(Face);
1237       if (T > FaceMax)
1238         FaceMax = T;
1239       if (T < FaceMin)
1240         FaceMin = T;
1241     }
1242     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1243       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1244       T = BRep_Tool::Tolerance(Edge);
1245       if (T > EdgeMax)
1246         EdgeMax = T;
1247       if (T < EdgeMin)
1248         EdgeMin = T;
1249     }
1250     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1251       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1252       T = BRep_Tool::Tolerance(Vertex);
1253       if (T > VertMax)
1254         VertMax = T;
1255       if (T < VertMin)
1256         VertMin = T;
1257     }
1258   }
1259   catch (Standard_Failure) {
1260     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1261     SetErrorCode(aFail->GetMessageString());
1262     return;
1263   }
1264
1265   SetErrorCode(OK);
1266 }
1267
1268 //=============================================================================
1269 /*!
1270  *  CheckShape
1271  */
1272 //=============================================================================
1273 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)     theShape,
1274                                               const Standard_Boolean  theIsCheckGeom,
1275                                               std::list<ShapeError>  &theErrors)
1276 {
1277   SetErrorCode(KO);
1278   theErrors.clear();
1279
1280   if (theShape.IsNull()) return false;
1281
1282   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1283   if (aRefShape.IsNull()) return false;
1284
1285   TopoDS_Shape aShape = aRefShape->GetValue();
1286   if (aShape.IsNull()) {
1287     SetErrorCode("The Objects has NULL Shape");
1288     return false;
1289   }
1290
1291   //Compute the parameters
1292   bool isValid = false;
1293   try {
1294     OCC_CATCH_SIGNALS;
1295     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1296     if (ana.IsValid()) {
1297       isValid = true;
1298     } else {
1299       FillErrors(ana, aShape, theErrors);
1300     }
1301   }
1302   catch (Standard_Failure) {
1303     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1304     SetErrorCode(aFail->GetMessageString());
1305     return false;
1306   }
1307
1308   SetErrorCode(OK);
1309   return isValid;
1310 }
1311
1312 //=============================================================================
1313 /*!
1314  *  PrintShapeErrors
1315  */
1316 //=============================================================================
1317 TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
1318                                  (Handle(GEOM_Object)          theShape,
1319                                   const std::list<ShapeError> &theErrors)
1320 {
1321   TCollection_AsciiString aDump;
1322
1323   if (theShape.IsNull()) {
1324     return aDump;
1325   }
1326
1327   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1328
1329   if (aRefShape.IsNull()) {
1330     return aDump;
1331   }
1332
1333   TopoDS_Shape aShape = aRefShape->GetValue();
1334
1335   if (aShape.IsNull()) {
1336     SetErrorCode("The Objects has NULL Shape");
1337     return aDump;
1338   }
1339
1340   if (!theErrors.empty()) {
1341     // The shape is not valid. Prepare errors for dump.
1342     TopTools_IndexedMapOfShape anIndices;
1343     std::list<ShapeError>::const_iterator anIter = theErrors.begin();
1344     Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1345     nbv = nbe = nbw = nbf = nbs = nbo = 0;
1346
1347     // Map sub-shapes and their indices
1348     TopExp::MapShapes(aShape, anIndices);
1349
1350     const Standard_Integer aNbSubShapes = anIndices.Extent();
1351     TColStd_MapOfInteger   aMapPbInd;
1352
1353     aDump += " -- The Shape has problems :\n";
1354     aDump += "  Check                                    Count\n";
1355     aDump += " ------------------------------------------------\n";
1356
1357     for (; anIter != theErrors.end(); anIter++) {
1358       Standard_Integer aNbShapes = anIter->incriminated.size();
1359
1360       switch(anIter->error) {
1361       case BRepCheck_InvalidPointOnCurve:
1362         aDump += "  Invalid Point on Curve ................... ";
1363         break;
1364       case BRepCheck_InvalidPointOnCurveOnSurface:
1365         aDump += "  Invalid Point on CurveOnSurface .......... ";
1366         break;
1367       case BRepCheck_InvalidPointOnSurface:
1368         aDump += "  Invalid Point on Surface ................. ";
1369         break;
1370       case BRepCheck_No3DCurve:
1371         aDump += "  No 3D Curve .............................. ";
1372         break;
1373       case BRepCheck_Multiple3DCurve:
1374         aDump += "  Multiple 3D Curve ........................ ";
1375         break;
1376       case BRepCheck_Invalid3DCurve:
1377         aDump += "  Invalid 3D Curve ......................... ";
1378         break;
1379       case BRepCheck_NoCurveOnSurface:
1380         aDump += "  No Curve on Surface ...................... ";
1381         break;
1382       case BRepCheck_InvalidCurveOnSurface:
1383         aDump += "  Invalid Curve on Surface ................. ";
1384         break;
1385       case BRepCheck_InvalidCurveOnClosedSurface:
1386         aDump += "  Invalid Curve on closed Surface .......... ";
1387         break;
1388       case BRepCheck_InvalidSameRangeFlag:
1389         aDump += "  Invalid SameRange Flag ................... ";
1390         break;
1391       case BRepCheck_InvalidSameParameterFlag:
1392         aDump += "  Invalid SameParameter Flag ............... ";
1393         break;
1394       case BRepCheck_InvalidDegeneratedFlag:
1395         aDump += "  Invalid Degenerated Flag ................. ";
1396         break;
1397       case BRepCheck_FreeEdge:
1398         aDump += "  Free Edge ................................ ";
1399         break;
1400       case BRepCheck_InvalidMultiConnexity:
1401         aDump += "  Invalid MultiConnexity ................... ";
1402         break;
1403       case BRepCheck_InvalidRange:
1404         aDump += "  Invalid Range ............................ ";
1405         break;
1406       case BRepCheck_EmptyWire:
1407         aDump += "  Empty Wire ............................... ";
1408         break;
1409       case BRepCheck_RedundantEdge:
1410         aDump += "  Redundant Edge ........................... ";
1411         break;
1412       case BRepCheck_SelfIntersectingWire:
1413         aDump += "  Self Intersecting Wire ................... ";
1414         break;
1415       case BRepCheck_NoSurface:
1416         aDump += "  No Surface ............................... ";
1417         break;
1418       case BRepCheck_InvalidWire:
1419         aDump += "  Invalid Wire ............................. ";
1420         break;
1421       case BRepCheck_RedundantWire:
1422         aDump += "  Redundant Wire ........................... ";
1423         break;
1424       case BRepCheck_IntersectingWires:
1425         aDump += "  Intersecting Wires ....................... ";
1426         break;
1427       case BRepCheck_InvalidImbricationOfWires:
1428         aDump += "  Invalid Imbrication of Wires ............. ";
1429         break;
1430       case BRepCheck_EmptyShell:
1431         aDump += "  Empty Shell .............................. ";
1432         break;
1433       case BRepCheck_RedundantFace:
1434         aDump += "  Redundant Face ........................... ";
1435         break;
1436       case BRepCheck_UnorientableShape:
1437         aDump += "  Unorientable Shape ....................... ";
1438         break;
1439       case BRepCheck_NotClosed:
1440         aDump += "  Not Closed ............................... ";
1441         break;
1442       case BRepCheck_NotConnected:
1443         aDump += "  Not Connected ............................ ";
1444         break;
1445       case BRepCheck_SubshapeNotInShape:
1446         aDump += "  Sub-shape not in Shape ................... ";
1447         break;
1448       case BRepCheck_BadOrientation:
1449         aDump += "  Bad Orientation .......................... ";
1450         break;
1451       case BRepCheck_BadOrientationOfSubshape:
1452         aDump += "  Bad Orientation of Sub-shape ............. ";
1453         break;
1454       case BRepCheck_InvalidToleranceValue:
1455         aDump += "  Invalid Tolerance Value .................. ";
1456         break;
1457       case BRepCheck_CheckFail:
1458         aDump += "  Check Shape Failure ...................... ";
1459         break;
1460       default:
1461         break;
1462       }
1463
1464       aDump += TCollection_AsciiString(aNbShapes) + "\n";
1465
1466       // Count types of shape.
1467       std::list<int>::const_iterator aShIter = anIter->incriminated.begin();
1468
1469       for (; aShIter != anIter->incriminated.end(); aShIter++) {
1470         const Standard_Integer anIndex = *aShIter;
1471
1472         if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) {
1473           const TopoDS_Shape     &aSubShape = anIndices.FindKey(anIndex);
1474           const TopAbs_ShapeEnum  aType     = aSubShape.ShapeType();
1475
1476           switch (aType) {
1477             case TopAbs_VERTEX : nbv++; break;
1478             case TopAbs_EDGE   : nbe++; break;
1479             case TopAbs_WIRE   : nbw++; break;
1480             case TopAbs_FACE   : nbf++; break;
1481             case TopAbs_SHELL  : nbs++; break;
1482             case TopAbs_SOLID  : nbo++; break;
1483             default            : break;
1484           }
1485         }
1486       }
1487     }
1488
1489     const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo;
1490     aDump += " ------------------------------------------------\n";
1491     aDump += "*** Shapes with problems : ";
1492     aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n";
1493
1494     if (nbv > 0) {
1495       aDump += "VERTEX : ";
1496       if (nbv < 10) aDump += " ";
1497       aDump += TCollection_AsciiString(nbv) + "\n";
1498     }
1499     if (nbe > 0) {
1500       aDump += "EDGE   : ";
1501       if (nbe < 10) aDump += " ";
1502       aDump += TCollection_AsciiString(nbe) + "\n";
1503     }
1504     if (nbw > 0) {
1505       aDump += "WIRE   : ";
1506       if (nbw < 10) aDump += " ";
1507       aDump += TCollection_AsciiString(nbw) + "\n";
1508     }
1509     if (nbf > 0) {
1510       aDump += "FACE   : ";
1511       if (nbf < 10) aDump += " ";
1512       aDump += TCollection_AsciiString(nbf) + "\n";
1513     }
1514     if (nbs > 0) {
1515       aDump += "SHELL  : ";
1516       if (nbs < 10) aDump += " ";
1517       aDump += TCollection_AsciiString(nbs) + "\n";
1518     }
1519     if (nbo > 0) {
1520       aDump += "SOLID  : ";
1521       if (nbo < 10) aDump += " ";
1522       aDump += TCollection_AsciiString(nbo) + "\n";
1523     }
1524   }
1525
1526   return aDump;
1527 }
1528
1529 //=============================================================================
1530 /*!
1531  *  CheckSelfIntersections
1532  */
1533 //=============================================================================
1534 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
1535                          (Handle(GEOM_Object)                 theShape,
1536                           const SICheckLevel                  theCheckLevel,
1537                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1538 {
1539   SetErrorCode(KO);
1540
1541   if (theIntersections.IsNull())
1542     theIntersections = new TColStd_HSequenceOfInteger;
1543   else
1544     theIntersections->Clear();
1545
1546   if (theShape.IsNull())
1547     return false;
1548
1549   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1550   if (aRefShape.IsNull()) return false;
1551
1552   TopoDS_Shape aShape = aRefShape->GetValue();
1553   if (aShape.IsNull()) return false;
1554
1555   // 0. Prepare data
1556   TopoDS_Shape aScopy;
1557   //
1558   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1559   //
1560   // Map sub-shapes and their indices
1561   TopTools_IndexedMapOfShape anIndices;
1562   TopExp::MapShapes(aScopy, anIndices);
1563
1564   BOPCol_ListOfShape aLCS;
1565   aLCS.Append(aScopy);
1566   //
1567   BOPAlgo_CheckerSI aCSI; // checker of self-interferences
1568   aCSI.SetArguments(aLCS);
1569   aCSI.SetLevelOfCheck(theCheckLevel);
1570
1571   // 1. Launch the checker
1572   aCSI.Perform();
1573   Standard_Boolean iErr = aCSI.HasErrors();
1574
1575   //
1576   Standard_Integer aNbS, n1, n2;
1577   BOPDS_MapIteratorOfMapOfPair aItMPK;
1578   //
1579   // 2. Take the shapes from DS
1580   const BOPDS_DS& aDS = aCSI.DS();
1581   aNbS=aDS.NbShapes();
1582   //
1583   // 3. Get the pairs of interfered shapes
1584   const BOPDS_MapOfPair& aMPK=aDS.Interferences();
1585   aItMPK.Initialize(aMPK);
1586   for (; aItMPK.More(); aItMPK.Next()) {
1587     const BOPDS_Pair& aPK=aItMPK.Value();
1588     aPK.Indices(n1, n2);
1589     //
1590     if (n1 > aNbS || n2 > aNbS){
1591       return false; // Error
1592     }
1593     const TopoDS_Shape& aS1 = aDS.Shape(n1);
1594     const TopoDS_Shape& aS2 = aDS.Shape(n2);
1595
1596     theIntersections->Append(anIndices.FindIndex(aS1));
1597     theIntersections->Append(anIndices.FindIndex(aS2));
1598   }
1599
1600   if (!iErr) {
1601     SetErrorCode(OK);
1602   }
1603
1604   return theIntersections->IsEmpty();
1605 }
1606
1607 //=============================================================================
1608 /*!
1609  *  CheckSelfIntersectionsFast
1610  */
1611 //=============================================================================
1612 bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
1613                          (Handle(GEOM_Object) theShape,
1614                           float theDeflection, double theTolerance,
1615                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1616 {
1617   SetErrorCode(KO);
1618
1619   if (theIntersections.IsNull())
1620     theIntersections = new TColStd_HSequenceOfInteger;
1621   else
1622     theIntersections->Clear();
1623
1624   if (theShape.IsNull())
1625     return false;
1626
1627   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1628   if (aRefShape.IsNull()) return false;
1629
1630   TopoDS_Shape aShape = aRefShape->GetValue();
1631   if (aShape.IsNull()) return false;
1632
1633   // Prepare data
1634   TopoDS_Shape aScopy;
1635
1636   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1637   GEOMUtils::MeshShape(aScopy, theDeflection);
1638
1639   // Map sub-shapes and their indices
1640   TopTools_IndexedMapOfShape anIndices;
1641   TopExp::MapShapes(aScopy, anIndices);
1642
1643   // Checker of fast interferences
1644   BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
1645
1646   // Launch the checker
1647   aTool.Perform();
1648   
1649   const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
1650   
1651   std::set<Standard_Integer> processed;
1652   
1653   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
1654     Standard_Integer idxLeft = it.Key();
1655     if (processed.count(idxLeft) > 0) continue; // already added
1656     processed.insert(idxLeft);
1657     const TColStd_PackedMapOfInteger& overlaps = it.Value();
1658     for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
1659       Standard_Integer idxRight = subit.Key();
1660       if (processed.count(idxRight) > 0) continue; // already added
1661       const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
1662       const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
1663       theIntersections->Append(anIndices.FindIndex(aS1));
1664       theIntersections->Append(anIndices.FindIndex(aS2));
1665     }
1666   }
1667
1668   if (aTool.IsDone())
1669     SetErrorCode(OK);
1670
1671   return theIntersections->IsEmpty();
1672 }
1673
1674 //=============================================================================
1675 /*!
1676  *  CheckBOPArguments
1677  */
1678 //=============================================================================
1679 bool GEOMImpl_IMeasureOperations::CheckBOPArguments
1680                                       (const Handle(GEOM_Object) &theShape)
1681 {
1682   SetErrorCode(KO);
1683
1684   if (theShape.IsNull()) {
1685     return false;
1686   }
1687
1688   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1689
1690   if (aRefShape.IsNull()) {
1691     return false;
1692   }
1693
1694   TopoDS_Shape aShape = aRefShape->GetValue();
1695
1696   if (aShape.IsNull()) {
1697     return false;
1698   }
1699
1700   //Compute the parameters
1701   bool isValid = GEOMUtils::CheckBOPArguments(aShape);
1702
1703   SetErrorCode(OK);
1704
1705   return isValid;
1706 }
1707
1708 //=============================================================================
1709 /*!
1710  *  FastIntersect
1711  */
1712 //=============================================================================
1713 bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1714                                                  double theTolerance, float theDeflection,
1715                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections1,
1716                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections2)
1717 {
1718   SetErrorCode(KO);
1719   bool isGood = false;
1720
1721   if (theIntersections1.IsNull())
1722     theIntersections1 = new TColStd_HSequenceOfInteger;
1723   else
1724     theIntersections1->Clear();
1725
1726   if (theIntersections2.IsNull())
1727     theIntersections2 = new TColStd_HSequenceOfInteger;
1728   else
1729     theIntersections2->Clear();
1730
1731   if (theShape1.IsNull() || theShape2.IsNull()) {
1732     SetErrorCode("Objects have NULL Shape");
1733     return isGood;
1734   }
1735
1736   if (theShape1 == theShape2) {
1737     SetErrorCode("Objects are equal");
1738     return isGood;
1739   }
1740   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1741   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1742   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
1743
1744   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1745   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1746   if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
1747
1748   // 0. Prepare data
1749   TopoDS_Shape aScopy1, aScopy2;
1750   GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
1751   GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
1752
1753   GEOMUtils::MeshShape(aScopy1, theDeflection);
1754   GEOMUtils::MeshShape(aScopy2, theDeflection);
1755   //
1756   // Map sub-shapes and their indices
1757   TopTools_IndexedMapOfShape anIndices1, anIndices2;
1758   TopExp::MapShapes(aScopy1, anIndices1);
1759   TopExp::MapShapes(aScopy2, anIndices2);
1760
1761   BOPCol_ListOfShape aLCS1, aLCS2;
1762   aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
1763   //
1764   BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
1765   aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
1766   aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
1767
1768   // 1. Launch the checker
1769   aBSP.Perform();
1770  
1771   // 2. Get sets of IDs of overlapped faces
1772   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
1773   {
1774     const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
1775     theIntersections1->Append(anIndices1.FindIndex(aS1));
1776   }
1777   
1778   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
1779   {
1780     const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
1781     theIntersections2->Append(anIndices2.FindIndex(aS2));
1782   }
1783
1784   isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
1785
1786   if (aBSP.IsDone())
1787     SetErrorCode(OK);
1788
1789   return isGood;
1790 }
1791
1792 //=============================================================================
1793 /*!
1794  *  IsGoodForSolid
1795  */
1796 //=============================================================================
1797 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1798 {
1799   SetErrorCode(KO);
1800
1801   TCollection_AsciiString aRes = "";
1802
1803   if (theShape.IsNull()) {
1804     aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1805   }
1806   else {
1807     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1808     if (aRefShape.IsNull()) {
1809       aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1810     }
1811     else {
1812       TopoDS_Shape aShape = aRefShape->GetValue();
1813       if (aShape.IsNull()) {
1814         aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1815       }
1816       else {
1817         if (aShape.ShapeType() == TopAbs_COMPOUND) {
1818           TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1819           if (It.More()) aShape = It.Value();
1820         }
1821         if (aShape.ShapeType() == TopAbs_SHELL) {
1822           BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
1823           if (chkShell.Closed() == BRepCheck_NotClosed) {
1824             aRes = "WRN_SHAPE_UNCLOSED";
1825           }
1826         }
1827         else {
1828           aRes = "WRN_SHAPE_NOT_SHELL";
1829         }
1830       }
1831     }
1832   }
1833
1834   if (aRes.IsEmpty())
1835     SetErrorCode(OK);
1836
1837   return aRes;
1838 }
1839
1840 //=============================================================================
1841 /*!
1842  *  WhatIs
1843  */
1844 //=============================================================================
1845 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1846 {
1847   SetErrorCode(KO);
1848
1849   TCollection_AsciiString Astr;
1850
1851   if (theShape.IsNull()) return Astr;
1852
1853   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1854   if (aRefShape.IsNull()) return Astr;
1855
1856   TopoDS_Shape aShape = aRefShape->GetValue();
1857   if (aShape.IsNull()) {
1858     SetErrorCode("The Objects has NULL Shape");
1859     return Astr;
1860   }
1861
1862   //Compute the parameters
1863   if (aShape.ShapeType() == TopAbs_EDGE) {
1864     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1865       Astr = Astr + " It is a degenerated edge \n";
1866     }
1867   }
1868
1869   Astr = Astr + " Number of sub-shapes : \n";
1870
1871   try {
1872     OCC_CATCH_SIGNALS;
1873     int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
1874     for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
1875       nbTypes[iType] = 0;
1876       nbFlatType[iType] = 0;
1877     }
1878     nbTypes[aShape.ShapeType()]++;
1879
1880     TopTools_MapOfShape aMapOfShape;
1881     aMapOfShape.Add(aShape);
1882     TopTools_ListOfShape aListOfShape;
1883     aListOfShape.Append(aShape);
1884
1885     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1886     for (; itL.More(); itL.Next()) {
1887       TopoDS_Shape sp = itL.Value();
1888       TopoDS_Iterator it (sp);
1889       for (; it.More(); it.Next()) {
1890         TopoDS_Shape s = it.Value();
1891         if (aMapOfShape.Add(s)) {
1892           aListOfShape.Append(s);
1893           nbTypes[s.ShapeType()]++;
1894           if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
1895             nbFlatType[s.ShapeType()]++;
1896           }
1897         }
1898       }
1899     }
1900
1901     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1902     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1903     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1904     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1905     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1906     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1907     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1908     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1909     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
1910
1911     if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
1912       Astr = Astr + " --------------------- \n Flat content : \n";
1913       if (nbFlatType[TopAbs_VERTEX] > 0)
1914         Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
1915       if (nbFlatType[TopAbs_EDGE] > 0)
1916         Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
1917       if (nbFlatType[TopAbs_WIRE] > 0)
1918         Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
1919       if (nbFlatType[TopAbs_FACE] > 0)
1920         Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
1921       if (nbFlatType[TopAbs_SHELL] > 0)
1922         Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
1923       if (nbFlatType[TopAbs_SOLID] > 0)
1924         Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
1925     }
1926   }
1927   catch (Standard_Failure) {
1928     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1929     SetErrorCode(aFail->GetMessageString());
1930     return Astr;
1931   }
1932
1933   SetErrorCode(OK);
1934   return Astr;
1935 }
1936
1937 //=============================================================================
1938 /*!
1939  *  AreCoordsInside
1940  */
1941 //=============================================================================
1942 std::vector<bool>
1943 GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object)        theShape,
1944                                              const std::vector<double>& coords,
1945                                              double                     tolerance)
1946 {
1947   std::vector<bool> isInsideRes;
1948   if (!theShape.IsNull()) {
1949     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1950     if (!aRefShape.IsNull()) {
1951       TopoDS_Shape aShape = aRefShape->GetValue();
1952       if (!aShape.IsNull())
1953       {
1954         TopTools_IndexedMapOfShape mapShape;
1955         {
1956           TopExp_Explorer anExp;
1957           for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1958             mapShape.Add( anExp.Current() );
1959           for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1960             mapShape.Add( anExp.Current() );
1961           for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() )
1962             mapShape.Add( anExp.Current() );
1963           for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() )
1964             mapShape.Add( anExp.Current() ); //// ?????????
1965         }
1966         size_t nb_points = coords.size()/3, nb_points_inside = 0;
1967         isInsideRes.resize( nb_points, false );
1968
1969         for ( int iS = 1; iS <= mapShape.Extent(); ++iS )
1970         {
1971           if ( nb_points_inside == nb_points )
1972             break;
1973           aShape = mapShape( iS );
1974           switch ( aShape.ShapeType() ) {
1975           case TopAbs_SOLID:
1976           {
1977             BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape ));
1978             for ( size_t i = 0; i < nb_points; i++)
1979             {
1980               if ( isInsideRes[ i ]) continue;
1981               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
1982               SC.Perform( aPnt, tolerance );
1983               isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ));
1984               nb_points_inside += isInsideRes[ i ];
1985             }
1986             break;
1987           }
1988           case TopAbs_FACE:
1989           {
1990             Standard_Real u1,u2,v1,v2;
1991             const TopoDS_Face&   face = TopoDS::Face( aShape );
1992             Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
1993             surf->Bounds( u1,u2,v1,v2 );
1994             GeomAPI_ProjectPointOnSurf project;
1995             project.Init(surf, u1,u2, v1,v2, tolerance );
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               if ( project.IsDone() &&
2002                    project.NbPoints() > 0 &&
2003                    project.LowerDistance() <= tolerance )
2004               {
2005                 Standard_Real u, v;
2006                 project.LowerDistanceParameters(u, v);
2007                 gp_Pnt2d uv( u, v );
2008                 BRepClass_FaceClassifier FC ( face, uv, tolerance );
2009                 isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON ));
2010                 nb_points_inside += isInsideRes[ i ];
2011               }
2012             }
2013             break;
2014           }
2015           case TopAbs_EDGE:
2016           {
2017             Standard_Real f,l;
2018             const TopoDS_Edge&  edge = TopoDS::Edge( aShape );
2019             Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
2020             GeomAPI_ProjectPointOnCurve project;
2021             project.Init( curve, f, l );
2022             for ( size_t i = 0; i < nb_points; i++)
2023             {
2024               if ( isInsideRes[ i ]) continue;
2025               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2026               project.Perform( aPnt );
2027               isInsideRes[ i ] = ( project.NbPoints() > 0 &&
2028                                    project.LowerDistance() <= tolerance );
2029               nb_points_inside += isInsideRes[ i ];
2030             }
2031             break;
2032           }
2033           case TopAbs_VERTEX:
2034           {
2035             gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ));
2036             for ( size_t i = 0; i < nb_points; i++)
2037             {
2038               if ( isInsideRes[ i ]) continue;
2039               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2040               isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance );
2041               nb_points_inside += isInsideRes[ i ];
2042             }
2043             break;
2044           }
2045           default:;
2046           } // switch ( aShape.ShapeType() )
2047         }
2048       }
2049     }
2050   }
2051   return isInsideRes;
2052 }
2053
2054 //=============================================================================
2055 /*!
2056  *  GetMinDistance
2057  */
2058 //=============================================================================
2059 Standard_Real
2060 GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
2061                                              Handle(GEOM_Object) theShape2,
2062                                              Standard_Real& X1,
2063                                              Standard_Real& Y1,
2064                                              Standard_Real& Z1,
2065                                              Standard_Real& X2,
2066                                              Standard_Real& Y2,
2067                                              Standard_Real& Z2)
2068 {
2069   SetErrorCode(KO);
2070   Standard_Real MinDist = 1.e9;
2071
2072   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
2073
2074   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2075   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2076   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
2077
2078   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2079   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2080   if (aShape1.IsNull() || aShape2.IsNull()) {
2081     SetErrorCode("One of Objects has NULL Shape");
2082     return MinDist;
2083   }
2084
2085   //Compute the parameters
2086   try {
2087     OCC_CATCH_SIGNALS;
2088
2089     gp_Pnt aPnt1, aPnt2;
2090
2091     MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
2092
2093     if (MinDist >= 0.0) {
2094       aPnt1.Coord(X1, Y1, Z1);
2095       aPnt2.Coord(X2, Y2, Z2);
2096     } else {
2097       return MinDist;
2098     }
2099   }
2100   catch (Standard_Failure) {
2101     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2102     SetErrorCode(aFail->GetMessageString());
2103     return MinDist;
2104   }
2105
2106   SetErrorCode(OK);
2107   return MinDist;
2108 }
2109
2110 //=======================================================================
2111 /*!
2112  *  Get coordinates of closest points of two shapes
2113  */
2114 //=======================================================================
2115 Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1,
2116                                                              Handle(GEOM_Object) theShape2,
2117                                                              Handle(TColStd_HSequenceOfReal)& theDoubles)
2118 {
2119   SetErrorCode(KO);
2120   Standard_Integer nbSolutions = 0;
2121
2122   if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions;
2123
2124   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2125   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2126   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions;
2127
2128   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2129   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2130   if (aShape1.IsNull() || aShape2.IsNull()) {
2131     SetErrorCode("One of Objects has NULL Shape");
2132     return nbSolutions;
2133   }
2134
2135   // Compute the extremities
2136   try {
2137     OCC_CATCH_SIGNALS;
2138
2139     // skl 30.06.2008
2140     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
2141     gp_Pnt P1, P2;
2142     double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1, P2);
2143     if (dist > -1.0) {
2144       nbSolutions = 1;
2145
2146       theDoubles->Append(P1.X());
2147       theDoubles->Append(P1.Y());
2148       theDoubles->Append(P1.Z());
2149       theDoubles->Append(P2.X());
2150       theDoubles->Append(P2.Y());
2151       theDoubles->Append(P2.Z());
2152
2153       SetErrorCode(OK);
2154       return nbSolutions;
2155     }
2156
2157     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
2158     if (dst.IsDone()) {
2159       nbSolutions = dst.NbSolution();
2160       if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2161
2162       gp_Pnt P1, P2;
2163       for (int i = 1; i <= nbSolutions; i++) {
2164         P1 = dst.PointOnShape1(i);
2165         P2 = dst.PointOnShape2(i);
2166
2167         theDoubles->Append(P1.X());
2168         theDoubles->Append(P1.Y());
2169         theDoubles->Append(P1.Z());
2170         theDoubles->Append(P2.X());
2171         theDoubles->Append(P2.Y());
2172         theDoubles->Append(P2.Z());
2173       }
2174     }
2175   }
2176   catch (Standard_Failure) {
2177     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2178     SetErrorCode(aFail->GetMessageString());
2179     return nbSolutions;
2180   }
2181
2182   SetErrorCode(OK);
2183   return nbSolutions;
2184 }
2185
2186 //=======================================================================
2187 /*!
2188  *  Get coordinates of point
2189  */
2190 //=======================================================================
2191 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
2192                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
2193 {
2194   SetErrorCode(KO);
2195
2196   if (theShape.IsNull())
2197     return;
2198
2199   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2200   if (aRefShape.IsNull())
2201     return;
2202
2203   TopoDS_Shape aShape = aRefShape->GetValue();
2204   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
2205   {
2206     SetErrorCode( "Shape must be a vertex" );
2207     return;
2208   }
2209
2210   try {
2211     OCC_CATCH_SIGNALS;
2212     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
2213     theX = aPnt.X();
2214     theY = aPnt.Y();
2215     theZ = aPnt.Z();
2216
2217     SetErrorCode(OK);
2218   }
2219   catch (Standard_Failure)
2220   {
2221     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2222     SetErrorCode( aFail->GetMessageString() );
2223   }
2224 }
2225
2226 //=======================================================================
2227 /*!
2228  *  Compute angle (in degrees) between two lines
2229  */
2230 //=======================================================================
2231 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
2232                                                      Handle(GEOM_Object) theLine2)
2233 {
2234   if (theLine1->GetType() == GEOM_VECTOR &&
2235       theLine2->GetType() == GEOM_VECTOR)
2236     return GetAngleBtwVectors(theLine1, theLine2);
2237
2238   SetErrorCode(KO);
2239
2240   Standard_Real anAngle = -1.0;
2241
2242   if (theLine1.IsNull() || theLine2.IsNull())
2243     return anAngle;
2244
2245   Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
2246   Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
2247   if (aRefLine1.IsNull() || aRefLine2.IsNull())
2248     return anAngle;
2249
2250   TopoDS_Shape aLine1 = aRefLine1->GetValue();
2251   TopoDS_Shape aLine2 = aRefLine2->GetValue();
2252   if (aLine1.IsNull() || aLine2.IsNull() ||
2253       aLine1.ShapeType() != TopAbs_EDGE ||
2254       aLine2.ShapeType() != TopAbs_EDGE)
2255   {
2256     SetErrorCode("Two edges must be given");
2257     return anAngle;
2258   }
2259
2260   try {
2261     OCC_CATCH_SIGNALS;
2262     TopoDS_Edge E1 = TopoDS::Edge(aLine1);
2263     TopoDS_Edge E2 = TopoDS::Edge(aLine2);
2264
2265     double fp,lp;
2266     Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2267     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
2268
2269     if ( C1.IsNull() || C2.IsNull() ||
2270         !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
2271         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
2272     {
2273       SetErrorCode("The edges must be linear");
2274       return anAngle;
2275     }
2276
2277     Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
2278     Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
2279
2280     gp_Lin aLin1 = L1->Lin();
2281     gp_Lin aLin2 = L2->Lin();
2282
2283     anAngle = aLin1.Angle(aLin2);
2284     anAngle *= 180. / M_PI; // convert radians into degrees
2285
2286     if (anAngle > 90.0) {
2287       anAngle = 180.0 - anAngle;
2288     }
2289
2290     SetErrorCode(OK);
2291   }
2292   catch (Standard_Failure)
2293   {
2294     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2295     SetErrorCode(aFail->GetMessageString());
2296   }
2297
2298   return anAngle;
2299 }
2300
2301 //=======================================================================
2302 /*!
2303  *  Compute angle (in degrees) between two vectors
2304  */
2305 //=======================================================================
2306 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
2307                                                                Handle(GEOM_Object) theVec2)
2308 {
2309   SetErrorCode(KO);
2310
2311   Standard_Real anAngle = -1.0;
2312
2313   if (theVec1.IsNull() || theVec2.IsNull())
2314     return anAngle;
2315
2316   if (theVec1->GetType() != GEOM_VECTOR || theVec2->GetType() != GEOM_VECTOR) {
2317     SetErrorCode("Two vectors must be given");
2318     return anAngle;
2319   }
2320
2321   Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2322   Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2323   if (aRefVec1.IsNull() || aRefVec2.IsNull())
2324     return anAngle;
2325
2326   TopoDS_Shape aVec1 = aRefVec1->GetValue();
2327   TopoDS_Shape aVec2 = aRefVec2->GetValue();
2328   if (aVec1.IsNull() || aVec2.IsNull() ||
2329       aVec1.ShapeType() != TopAbs_EDGE ||
2330       aVec2.ShapeType() != TopAbs_EDGE)
2331   {
2332     SetErrorCode("Two edges must be given");
2333     return anAngle;
2334   }
2335
2336   try {
2337     OCC_CATCH_SIGNALS;
2338     TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2339     TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2340
2341     TopoDS_Vertex aP11, aP12, aP21, aP22;
2342     TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2343     TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2344     if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2345       SetErrorCode("Bad edge given");
2346       return anAngle;
2347     }
2348
2349     gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2350     gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2351
2352     anAngle = aV1.Angle(aV2);
2353     anAngle *= 180. / M_PI; // convert radians into degrees
2354
2355     SetErrorCode(OK);
2356   }
2357   catch (Standard_Failure)
2358   {
2359     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2360     SetErrorCode(aFail->GetMessageString());
2361   }
2362
2363   return anAngle;
2364 }
2365
2366
2367 //=============================================================================
2368 /*!
2369  *  CurveCurvatureByParam
2370  */
2371 //=============================================================================
2372 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2373                         (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2374 {
2375   SetErrorCode(KO);
2376   Standard_Real aRes = -1.0;
2377
2378   if(theCurve.IsNull()) return aRes;
2379
2380   Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2381   if(aRefShape.IsNull()) return aRes;
2382
2383   TopoDS_Shape aShape = aRefShape->GetValue();
2384   if(aShape.IsNull()) {
2385     SetErrorCode("One of Objects has NULL Shape");
2386     return aRes;
2387   }
2388
2389   Standard_Real aFP, aLP, aP;
2390   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2391   aP = aFP + (aLP - aFP) * theParam;
2392
2393   if(aCurve.IsNull()) return aRes;
2394
2395   //Compute curvature
2396   try {
2397     OCC_CATCH_SIGNALS;
2398     GeomLProp_CLProps Prop = GeomLProp_CLProps
2399       (aCurve, aP, 2, Precision::Confusion());
2400     aRes = fabs(Prop.Curvature());
2401     SetErrorCode(OK);
2402   }
2403   catch (Standard_Failure) {
2404     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2405     SetErrorCode(aFail->GetMessageString());
2406     return aRes;
2407   }
2408
2409   if( aRes > Precision::Confusion() )
2410     aRes = 1/aRes;
2411   else
2412     aRes = RealLast();
2413
2414   return aRes;
2415 }
2416
2417
2418 //=============================================================================
2419 /*!
2420  *  CurveCurvatureByPoint
2421  */
2422 //=============================================================================
2423 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2424                    (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2425 {
2426   SetErrorCode(KO);
2427   Standard_Real aRes = -1.0;
2428
2429   if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2430
2431   Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2432   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2433   if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2434
2435   TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2436   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2437   if( anEdge.IsNull() || aPnt.IsNull() ) {
2438     SetErrorCode("One of Objects has NULL Shape");
2439     return aRes;
2440   }
2441
2442   Standard_Real aFP, aLP;
2443   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2444   if(aCurve.IsNull()) return aRes;
2445   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2446
2447   //Compute curvature
2448   try {
2449     OCC_CATCH_SIGNALS;
2450     GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2451     if(PPCurve.NbPoints()>0) {
2452       GeomLProp_CLProps Prop = GeomLProp_CLProps
2453         (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2454       aRes = fabs(Prop.Curvature());
2455       SetErrorCode(OK);
2456     }
2457   }
2458   catch (Standard_Failure) {
2459     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2460     SetErrorCode(aFail->GetMessageString());
2461     return aRes;
2462   }
2463
2464   if( aRes > Precision::Confusion() )
2465     aRes = 1/aRes;
2466   else
2467     aRes = RealLast();
2468
2469   return aRes;
2470 }
2471
2472
2473 //=============================================================================
2474 /*!
2475  *  getSurfaceCurvatures
2476  */
2477 //=============================================================================
2478 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2479                                           (const Handle(Geom_Surface)& aSurf,
2480                                            Standard_Real theUParam,
2481                                            Standard_Real theVParam,
2482                                            Standard_Boolean theNeedMaxCurv)
2483 {
2484   SetErrorCode(KO);
2485   Standard_Real aRes = 1.0;
2486
2487   if (aSurf.IsNull()) return aRes;
2488
2489   try {
2490     OCC_CATCH_SIGNALS;
2491     GeomLProp_SLProps Prop = GeomLProp_SLProps
2492       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2493     if(Prop.IsCurvatureDefined()) {
2494       if(Prop.IsUmbilic()) {
2495         //cout<<"is umbilic"<<endl;
2496         aRes = fabs(Prop.MeanCurvature());
2497       }
2498       else {
2499         //cout<<"is not umbilic"<<endl;
2500         double c1 = fabs(Prop.MaxCurvature());
2501         double c2 = fabs(Prop.MinCurvature());
2502         if(theNeedMaxCurv)
2503           aRes = Max(c1,c2);
2504         else
2505           aRes = Min(c1,c2);
2506       }
2507       SetErrorCode(OK);
2508     }
2509   }
2510   catch (Standard_Failure) {
2511     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2512     SetErrorCode(aFail->GetMessageString());
2513     return aRes;
2514   }
2515
2516   if( fabs(aRes) > Precision::Confusion() )
2517     aRes = 1/aRes;
2518   else
2519     aRes = RealLast();
2520
2521   return aRes;
2522 }
2523
2524
2525 //=============================================================================
2526 /*!
2527  *  MaxSurfaceCurvatureByParam
2528  */
2529 //=============================================================================
2530 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2531                                                   (Handle(GEOM_Object) theSurf,
2532                                                    Standard_Real& theUParam,
2533                                                    Standard_Real& theVParam)
2534 {
2535   SetErrorCode(KO);
2536   Standard_Real aRes = -1.0;
2537
2538   if (theSurf.IsNull()) return aRes;
2539
2540   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2541   if(aRefShape.IsNull()) return aRes;
2542
2543   TopoDS_Shape aShape = aRefShape->GetValue();
2544   if(aShape.IsNull()) {
2545     SetErrorCode("One of Objects has NULL Shape");
2546     return aRes;
2547   }
2548
2549   TopoDS_Face F = TopoDS::Face(aShape);
2550   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2551
2552   //Compute the parameters
2553   Standard_Real U1,U2,V1,V2;
2554   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2555   Standard_Real U = U1 + (U2-U1)*theUParam;
2556   Standard_Real V = V1 + (V2-V1)*theVParam;
2557
2558   return getSurfaceCurvatures(aSurf, U, V, true);
2559 }
2560
2561
2562 //=============================================================================
2563 /*!
2564  *  MaxSurfaceCurvatureByPoint
2565  */
2566 //=============================================================================
2567 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2568                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2569 {
2570   SetErrorCode(KO);
2571   Standard_Real aRes = -1.0;
2572
2573   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2574
2575   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2576   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2577   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2578
2579   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2580   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2581   if( aFace.IsNull() || aPnt.IsNull() ) {
2582     SetErrorCode("One of Objects has NULL Shape");
2583     return 0;
2584   }
2585
2586   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2587   if(aSurf.IsNull()) return aRes;
2588   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2589
2590   //Compute the parameters
2591   ShapeAnalysis_Surface sas(aSurf);
2592   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2593
2594   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2595 }
2596
2597
2598 //=============================================================================
2599 /*!
2600  *  MinSurfaceCurvatureByParam
2601  */
2602 //=============================================================================
2603 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2604                                                   (Handle(GEOM_Object) theSurf,
2605                                                    Standard_Real& theUParam,
2606                                                    Standard_Real& theVParam)
2607 {
2608   SetErrorCode(KO);
2609   Standard_Real aRes = -1.0;
2610
2611   if (theSurf.IsNull()) return aRes;
2612
2613   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2614   if(aRefShape.IsNull()) return aRes;
2615
2616   TopoDS_Shape aShape = aRefShape->GetValue();
2617   if(aShape.IsNull()) {
2618     SetErrorCode("One of Objects has NULL Shape");
2619     return aRes;
2620   }
2621
2622   TopoDS_Face F = TopoDS::Face(aShape);
2623   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2624
2625   //Compute the parameters
2626   Standard_Real U1,U2,V1,V2;
2627   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2628   Standard_Real U = U1 + (U2-U1)*theUParam;
2629   Standard_Real V = V1 + (V2-V1)*theVParam;
2630
2631   return getSurfaceCurvatures(aSurf, U, V, false);
2632 }
2633
2634
2635 //=============================================================================
2636 /*!
2637  *  MinSurfaceCurvatureByPoint
2638  */
2639 //=============================================================================
2640 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2641                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2642 {
2643   SetErrorCode(KO);
2644   Standard_Real aRes = -1.0;
2645
2646   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2647
2648   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2649   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2650   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2651
2652   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2653   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2654   if( aFace.IsNull() || aPnt.IsNull() ) {
2655     SetErrorCode("One of Objects has NULL Shape");
2656     return 0;
2657   }
2658
2659   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2660   if(aSurf.IsNull()) return aRes;
2661   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2662
2663   //Compute the parameters
2664   ShapeAnalysis_Surface sas(aSurf);
2665   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2666
2667   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2668 }
2669
2670 //=======================================================================
2671 //function : FillErrorsSub
2672 //purpose  : Fill the errors list of subshapes on shape.
2673 //=======================================================================
2674 void GEOMImpl_IMeasureOperations::FillErrorsSub
2675            (const BRepCheck_Analyzer                   &theAna,
2676             const TopoDS_Shape                         &theShape,
2677             const TopAbs_ShapeEnum                     theSubType,
2678                   TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
2679 {
2680   TopExp_Explorer anExp(theShape, theSubType);
2681   TopTools_MapOfShape aMapSubShapes;
2682
2683   for (; anExp.More(); anExp.Next()) {
2684     const TopoDS_Shape &aSubShape = anExp.Current();
2685
2686     if (aMapSubShapes.Add(aSubShape)) {
2687       const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
2688
2689       for (aRes->InitContextIterator();
2690            aRes->MoreShapeInContext(); 
2691            aRes->NextShapeInContext()) {
2692         if (aRes->ContextualShape().IsSame(theShape)) {
2693           BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
2694
2695           if (itl.Value() != BRepCheck_NoError) {
2696             // Add all errors for theShape and its sub-shape.
2697             for (;itl.More(); itl.Next()) {
2698               const Standard_Integer aStat = (Standard_Integer)itl.Value();
2699
2700               if (!theMapErrors.IsBound(aStat)) {
2701                 TopTools_ListOfShape anEmpty;
2702
2703                 theMapErrors.Bind(aStat, anEmpty);
2704               }
2705
2706               TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
2707
2708               theShapes.Append(aSubShape);
2709               theShapes.Append(theShape);
2710             }
2711           }
2712         }
2713
2714         break;
2715       }
2716     }
2717   }
2718 }
2719
2720 //=======================================================================
2721 //function : FillErrors
2722 //purpose  : Fill the errors list.
2723 //=======================================================================
2724 void GEOMImpl_IMeasureOperations::FillErrors
2725              (const BRepCheck_Analyzer                   &theAna,
2726               const TopoDS_Shape                         &theShape,
2727                     TopTools_DataMapOfIntegerListOfShape &theMapErrors,
2728                     TopTools_MapOfShape                  &theMapShapes) const
2729 {
2730   if (theMapShapes.Add(theShape)) {
2731     // Fill errors of child shapes.
2732     for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
2733       FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
2734     }
2735
2736     // Fill errors of theShape.
2737     const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
2738
2739     if (!aRes.IsNull()) {
2740       BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
2741
2742       if (itl.Value() != BRepCheck_NoError) {
2743         // Add all errors for theShape.
2744         for (;itl.More(); itl.Next()) {
2745           const Standard_Integer aStat = (Standard_Integer)itl.Value();
2746
2747           if (!theMapErrors.IsBound(aStat)) {
2748             TopTools_ListOfShape anEmpty;
2749
2750             theMapErrors.Bind(aStat, anEmpty);
2751           }
2752
2753           theMapErrors.ChangeFind(aStat).Append(theShape);
2754         }
2755       }
2756     }
2757
2758     // Add errors of subshapes on theShape.
2759     const TopAbs_ShapeEnum aType = theShape.ShapeType();
2760
2761     switch (aType) {
2762     case TopAbs_EDGE:
2763       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
2764       break;
2765     case TopAbs_FACE:
2766       FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
2767       FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
2768       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
2769       break;
2770     case TopAbs_SOLID:
2771       FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
2772       break;
2773     default:
2774       break;
2775     }
2776   }
2777 }
2778
2779 //=======================================================================
2780 //function : FillErrors
2781 //purpose  : Fill the errors list.
2782 //=======================================================================
2783 void GEOMImpl_IMeasureOperations::FillErrors
2784                   (const BRepCheck_Analyzer    &theAna,
2785                    const TopoDS_Shape          &theShape,
2786                          std::list<ShapeError> &theErrors) const
2787 {
2788   // Fill the errors map.
2789   TopTools_DataMapOfIntegerListOfShape aMapErrors;
2790   TopTools_MapOfShape                  aMapShapes;
2791
2792   FillErrors(theAna, theShape, aMapErrors, aMapShapes);
2793
2794   // Map sub-shapes and their indices
2795   TopTools_IndexedMapOfShape anIndices;
2796
2797   TopExp::MapShapes(theShape, anIndices);
2798
2799   TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
2800
2801   for (; aMapIter.More(); aMapIter.Next()) {
2802     ShapeError anError;
2803
2804     anError.error = (BRepCheck_Status)aMapIter.Key();
2805
2806     TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
2807     TopTools_MapOfShape                aMapUnique;
2808
2809     for (; aListIter.More(); aListIter.Next()) {
2810       const TopoDS_Shape &aShape = aListIter.Value();
2811
2812       if (aMapUnique.Add(aShape)) {
2813         const Standard_Integer anIndex = anIndices.FindIndex(aShape);
2814
2815         anError.incriminated.push_back(anIndex);
2816       }
2817     }
2818
2819     if (!anError.incriminated.empty()) {
2820       theErrors.push_back(anError);
2821     }
2822   }
2823 }