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