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