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