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