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