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