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