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