Salome HOME
Merging from V3_2_6pre4
[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 #include <Standard_Stream.hxx>
21
22 #include <GEOMImpl_IMeasureOperations.hxx>
23
24 #include <GEOMImpl_Types.hxx>
25 #include <GEOMImpl_MeasureDriver.hxx>
26 #include <GEOMImpl_IMeasure.hxx>
27
28 #include <GEOMAlgo_ShapeInfo.hxx>
29 #include <GEOMAlgo_ShapeInfoFiller.hxx>
30
31 #include <GEOM_Function.hxx>
32 #include <GEOM_PythonDump.hxx>
33
34 #include <utilities.h>
35 #include <OpUtil.hxx>
36 #include <Utils_ExceptHandlers.hxx>
37
38 // OCCT Includes
39 #include <TFunction_DriverTable.hxx>
40 #include <TFunction_Driver.hxx>
41 #include <TFunction_Logbook.hxx>
42 #include <TDF_Tool.hxx>
43
44 #include <BRep_Tool.hxx>
45 #include <BRepAdaptor_Surface.hxx>
46 #include <BRepBndLib.hxx>
47 #include <BRepCheck.hxx>
48 #include <BRepCheck_Result.hxx>
49 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
50 #include <BRepExtrema_DistShapeShape.hxx>
51 #include <BRepGProp.hxx>
52 #include <BRepTools.hxx>
53
54 #include <Bnd_Box.hxx>
55
56 #include <GProp_GProps.hxx>
57 #include <GProp_PrincipalProps.hxx>
58
59 #include <TopAbs.hxx>
60 #include <TopoDS.hxx>
61 #include <TopoDS_Edge.hxx>
62 #include <TopoDS_Face.hxx>
63 #include <TopoDS_Shape.hxx>
64 #include <TopoDS_Vertex.hxx>
65 #include <TopoDS_Iterator.hxx>
66 #include <TopExp_Explorer.hxx>
67 #include <TopTools_MapOfShape.hxx>
68 #include <TopTools_ListOfShape.hxx>
69 #include <TopTools_ListIteratorOfListOfShape.hxx>
70
71 #include <GeomAbs_SurfaceType.hxx>
72 #include <Geom_Surface.hxx>
73 #include <Geom_Plane.hxx>
74 #include <Geom_SphericalSurface.hxx>
75 #include <Geom_CylindricalSurface.hxx>
76 #include <Geom_ToroidalSurface.hxx>
77 #include <Geom_ConicalSurface.hxx>
78 #include <Geom_SurfaceOfLinearExtrusion.hxx>
79 #include <Geom_SurfaceOfRevolution.hxx>
80 #include <Geom_BezierSurface.hxx>
81 #include <Geom_BSplineSurface.hxx>
82 #include <Geom_RectangularTrimmedSurface.hxx>
83 #include <Geom_OffsetSurface.hxx>
84
85 #include <gp_Pln.hxx>
86
87 #include <Standard_Failure.hxx>
88 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
89
90 //=============================================================================
91 /*!
92  *   constructor:
93  */
94 //=============================================================================
95 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID)
96 : GEOM_IOperations(theEngine, theDocID)
97 {
98   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
99 }
100
101 //=============================================================================
102 /*!
103  *  destructor
104  */
105 //=============================================================================
106 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
107 {
108   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
109 }
110
111 //=============================================================================
112 /*! Get kind and parameters of the given shape.
113  */
114 //=============================================================================
115 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
116                              (Handle(GEOM_Object) theShape,
117                               Handle(TColStd_HSequenceOfInteger)& theIntegers,
118                               Handle(TColStd_HSequenceOfReal)&    theDoubles)
119 {
120   SetErrorCode(KO);
121   ShapeKind aKind = SK_NO_SHAPE;
122
123   if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
124   else                      theIntegers->Clear();
125
126   if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
127   else                     theDoubles->Clear();
128
129   if (theShape.IsNull())
130     return aKind;
131
132   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
133   if (aRefShape.IsNull()) return aKind;
134
135   TopoDS_Shape aShape = aRefShape->GetValue();
136   if (aShape.IsNull()) return aKind;
137
138   // Call algorithm
139   GEOMAlgo_ShapeInfoFiller aSF;
140   aSF.SetShape(aShape);
141   aSF.Perform();
142   Standard_Integer iErr = aSF.ErrorStatus();
143   if (iErr) {
144     SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
145     return SK_NO_SHAPE;
146   }
147   const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
148
149   // Interprete results
150   TopAbs_ShapeEnum aType = anInfo.Type();
151   switch (aType)
152   {
153   case TopAbs_COMPOUND:
154   case TopAbs_COMPSOLID:
155     {
156       // (+) geompy.kind.COMPOUND     nb_solids nb_faces nb_edges nb_vertices
157       // (+) geompy.kind.COMPSOLID    nb_solids nb_faces nb_edges nb_vertices
158       // ??? "nb_faces" - all faces or only 'standalone' faces?
159       if (aType == TopAbs_COMPOUND)
160         aKind = SK_COMPOUND;
161       else
162         aKind = SK_COMPSOLID;
163
164       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPOUND));
165       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPSOLID));
166       theIntegers->Append(anInfo.NbSubShapes(TopAbs_SOLID));
167       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
168       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
169       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
170     }
171     break;
172
173   case TopAbs_SHELL:
174     {
175       // (+) geompy.kind.SHELL  geompy.info.closed   nb_faces nb_edges nb_vertices
176       // (+) geompy.kind.SHELL  geompy.info.unclosed nb_faces nb_edges nb_vertices
177       aKind = SK_SHELL;
178
179       theIntegers->Append((int)anInfo.KindOfClosed());
180
181       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
182       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
183       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
184     }
185     break;
186
187   case TopAbs_WIRE:
188     {
189       // (+) geompy.kind.WIRE  geompy.info.closed   nb_edges nb_vertices
190       // (+) geompy.kind.WIRE  geompy.info.unclosed nb_edges nb_vertices
191       aKind = SK_WIRE;
192
193       theIntegers->Append((int)anInfo.KindOfClosed());
194
195       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
196       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
197     }
198     break;
199
200   case TopAbs_SOLID:
201     {
202       aKind = SK_SOLID;
203
204       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
205       switch (aKN)
206       {
207       case GEOMAlgo_KN_SPHERE:
208         // (+) geompy.kind.SPHERE  xc yc zc  R
209         {
210           aKind = SK_SPHERE;
211
212           gp_Pnt aC = anInfo.Location();
213           theDoubles->Append(aC.X());
214           theDoubles->Append(aC.Y());
215           theDoubles->Append(aC.Z());
216
217           theDoubles->Append(anInfo.Radius1());
218         }
219         break;
220       case GEOMAlgo_KN_CYLINDER:
221         // (+) geompy.kind.CYLINDER  xb yb zb  dx dy dz  R  H
222         {
223           aKind = SK_CYLINDER;
224
225           gp_Pnt aC = anInfo.Location();
226           theDoubles->Append(aC.X());
227           theDoubles->Append(aC.Y());
228           theDoubles->Append(aC.Z());
229
230           gp_Ax3 anAx3 = anInfo.Position();
231           gp_Dir aD = anAx3.Direction();
232           theDoubles->Append(aD.X());
233           theDoubles->Append(aD.Y());
234           theDoubles->Append(aD.Z());
235
236           theDoubles->Append(anInfo.Radius1());
237           theDoubles->Append(anInfo.Height());
238         }
239         break;
240       case GEOMAlgo_KN_BOX:
241         // (+) geompy.kind.BOX  xc yc zc  ax ay az
242         {
243           aKind = SK_BOX;
244
245           gp_Pnt aC = anInfo.Location();
246           theDoubles->Append(aC.X());
247           theDoubles->Append(aC.Y());
248           theDoubles->Append(aC.Z());
249
250           gp_Ax3 anAx3 = anInfo.Position();
251           gp_Dir aD = anAx3.Direction();
252           gp_Dir aX = anAx3.XDirection();
253
254           // ax ay az
255           if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
256               aX.IsParallel(gp::DX(), Precision::Angular())) {
257             theDoubles->Append(anInfo.Length()); // ax'
258             theDoubles->Append(anInfo.Width());  // ay'
259             theDoubles->Append(anInfo.Height()); // az'
260           }
261           else if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
262                    aX.IsParallel(gp::DY(), Precision::Angular())) {
263             theDoubles->Append(anInfo.Width());  // ay'
264             theDoubles->Append(anInfo.Length()); // ax'
265             theDoubles->Append(anInfo.Height()); // az'
266           }
267           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
268                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
269             theDoubles->Append(anInfo.Height()); // az'
270             theDoubles->Append(anInfo.Width());  // ay'
271             theDoubles->Append(anInfo.Length()); // ax'
272           }
273           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
274                    aX.IsParallel(gp::DY(), Precision::Angular())) {
275             theDoubles->Append(anInfo.Height()); // az'
276             theDoubles->Append(anInfo.Length()); // ax'
277             theDoubles->Append(anInfo.Width());  // ay'
278           }
279           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
280                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
281             theDoubles->Append(anInfo.Width());  // ay'
282             theDoubles->Append(anInfo.Height()); // az'
283             theDoubles->Append(anInfo.Length()); // ax'
284           }
285           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
286                    aX.IsParallel(gp::DX(), Precision::Angular())) {
287             theDoubles->Append(anInfo.Length()); // ax'
288             theDoubles->Append(anInfo.Height()); // az'
289             theDoubles->Append(anInfo.Width());  // ay'
290           }
291           else {
292             // (+) geompy.kind.ROTATED_BOX  xo yo zo  zx zy zz  xx xy xz  ax ay az
293             aKind = SK_ROTATED_BOX;
294
295             // Direction and XDirection
296             theDoubles->Append(aD.X());
297             theDoubles->Append(aD.Y());
298             theDoubles->Append(aD.Z());
299
300             theDoubles->Append(aX.X());
301             theDoubles->Append(aX.Y());
302             theDoubles->Append(aX.Z());
303
304             // ax ay az
305             theDoubles->Append(anInfo.Length());
306             theDoubles->Append(anInfo.Width());
307             theDoubles->Append(anInfo.Height());
308           }
309         }
310         break;
311       case GEOMAlgo_KN_TORUS:
312         // (+) geompy.kind.TORUS  xc yc zc  dx dy dz  R_1 R_2
313         {
314           aKind = SK_TORUS;
315
316           gp_Pnt aO = anInfo.Location();
317           theDoubles->Append(aO.X());
318           theDoubles->Append(aO.Y());
319           theDoubles->Append(aO.Z());
320
321           gp_Ax3 anAx3 = anInfo.Position();
322           gp_Dir aD = anAx3.Direction();
323           theDoubles->Append(aD.X());
324           theDoubles->Append(aD.Y());
325           theDoubles->Append(aD.Z());
326
327           theDoubles->Append(anInfo.Radius1());
328           theDoubles->Append(anInfo.Radius2());
329         }
330         break;
331       case GEOMAlgo_KN_CONE:
332         // (+) geompy.kind.CONE  xb yb zb  dx dy dz  R_1 R_2  H
333         {
334           aKind = SK_CONE;
335
336           gp_Pnt aO = anInfo.Location();
337           theDoubles->Append(aO.X());
338           theDoubles->Append(aO.Y());
339           theDoubles->Append(aO.Z());
340
341           gp_Ax3 anAx3 = anInfo.Position();
342           gp_Dir aD = anAx3.Direction();
343           theDoubles->Append(aD.X());
344           theDoubles->Append(aD.Y());
345           theDoubles->Append(aD.Z());
346
347           theDoubles->Append(anInfo.Radius1());
348           theDoubles->Append(anInfo.Radius2());
349           theDoubles->Append(anInfo.Height());
350         }
351         break;
352       case GEOMAlgo_KN_POLYHEDRON:
353         // (+) geompy.kind.POLYHEDRON  nb_faces nb_edges nb_vertices
354         {
355           aKind = SK_POLYHEDRON;
356
357           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
358           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
359           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
360         }
361         break;
362       default:
363         // (+) geompy.kind.SOLID  nb_faces nb_edges nb_vertices
364         {
365           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
366           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
367           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
368         }
369       }
370     }
371     break;
372
373   case TopAbs_FACE:
374     {
375       aKind = SK_FACE;
376
377       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
378       switch (aKN) {
379       case GEOMAlgo_KN_SPHERE:
380         // (+) geompy.kind.SPHERE2D  xc yc zc  R
381         {
382           aKind = SK_SPHERE2D;
383
384           gp_Pnt aC = anInfo.Location();
385           theDoubles->Append(aC.X());
386           theDoubles->Append(aC.Y());
387           theDoubles->Append(aC.Z());
388
389           theDoubles->Append(anInfo.Radius1());
390         }
391         break;
392       case GEOMAlgo_KN_CYLINDER:
393         // (+) geompy.kind.CYLINDER2D  xb yb zb  dx dy dz  R  H
394         {
395           aKind = SK_CYLINDER2D;
396
397           gp_Pnt aO = anInfo.Location();
398           theDoubles->Append(aO.X());
399           theDoubles->Append(aO.Y());
400           theDoubles->Append(aO.Z());
401
402           gp_Ax3 anAx3 = anInfo.Position();
403           gp_Dir aD = anAx3.Direction();
404           theDoubles->Append(aD.X());
405           theDoubles->Append(aD.Y());
406           theDoubles->Append(aD.Z());
407
408           theDoubles->Append(anInfo.Radius1());
409           theDoubles->Append(anInfo.Height());
410         }
411         break;
412       case GEOMAlgo_KN_TORUS:
413         // (+) geompy.kind.TORUS2D  xc yc zc  dx dy dz  R_1 R_2
414         {
415           aKind = SK_TORUS2D;
416
417           gp_Pnt aO = anInfo.Location();
418           theDoubles->Append(aO.X());
419           theDoubles->Append(aO.Y());
420           theDoubles->Append(aO.Z());
421
422           gp_Ax3 anAx3 = anInfo.Position();
423           gp_Dir aD = anAx3.Direction();
424           theDoubles->Append(aD.X());
425           theDoubles->Append(aD.Y());
426           theDoubles->Append(aD.Z());
427
428           theDoubles->Append(anInfo.Radius1());
429           theDoubles->Append(anInfo.Radius2());
430         }
431         break;
432       case GEOMAlgo_KN_CONE:
433         // (+) geompy.kind.CONE2D  xc yc zc  dx dy dz  R_1 R_2  H
434         {
435           aKind = SK_CONE2D;
436
437           gp_Pnt aO = anInfo.Location();
438           theDoubles->Append(aO.X());
439           theDoubles->Append(aO.Y());
440           theDoubles->Append(aO.Z());
441
442           gp_Ax3 anAx3 = anInfo.Position();
443           gp_Dir aD = anAx3.Direction();
444           theDoubles->Append(aD.X());
445           theDoubles->Append(aD.Y());
446           theDoubles->Append(aD.Z());
447
448           theDoubles->Append(anInfo.Radius1());
449           theDoubles->Append(anInfo.Radius2());
450           theDoubles->Append(anInfo.Height());
451         }
452         break;
453       case GEOMAlgo_KN_DISKCIRCLE:
454         // (+) geompy.kind.DISK_CIRCLE  xc yc zc  dx dy dz  R
455         {
456           aKind = SK_DISK_CIRCLE;
457
458           gp_Pnt aC = anInfo.Location();
459           theDoubles->Append(aC.X());
460           theDoubles->Append(aC.Y());
461           theDoubles->Append(aC.Z());
462
463           gp_Ax3 anAx3 = anInfo.Position();
464           gp_Dir aD = anAx3.Direction();
465           theDoubles->Append(aD.X());
466           theDoubles->Append(aD.Y());
467           theDoubles->Append(aD.Z());
468
469           theDoubles->Append(anInfo.Radius1());
470         }
471         break;
472       case GEOMAlgo_KN_DISKELLIPSE:
473         // (+) geompy.kind.DISK_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
474         {
475           aKind = SK_DISK_ELLIPSE;
476
477           gp_Pnt aC = anInfo.Location();
478           theDoubles->Append(aC.X());
479           theDoubles->Append(aC.Y());
480           theDoubles->Append(aC.Z());
481
482           gp_Ax3 anAx3 = anInfo.Position();
483           gp_Dir aD = anAx3.Direction();
484           theDoubles->Append(aD.X());
485           theDoubles->Append(aD.Y());
486           theDoubles->Append(aD.Z());
487
488           theDoubles->Append(anInfo.Radius1());
489           theDoubles->Append(anInfo.Radius2());
490         }
491         break;
492       case GEOMAlgo_KN_RECTANGLE:
493       case GEOMAlgo_KN_TRIANGLE:
494       case GEOMAlgo_KN_QUADRANGLE:
495       case GEOMAlgo_KN_POLYGON:
496         // (+) geompy.kind.POLYGON  xo yo zo  dx dy dz  nb_edges nb_vertices
497         {
498           aKind = SK_POLYGON;
499
500           gp_Pnt aO = anInfo.Location();
501           theDoubles->Append(aO.X());
502           theDoubles->Append(aO.Y());
503           theDoubles->Append(aO.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           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
512           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
513         }
514         break;
515       case GEOMAlgo_KN_PLANE: // infinite
516         // (+) geompy.kind.PLANE  xo yo zo  dx dy dz
517         {
518           aKind = SK_PLANE;
519
520           gp_Pnt aC = anInfo.Location();
521           theDoubles->Append(aC.X());
522           theDoubles->Append(aC.Y());
523           theDoubles->Append(aC.Z());
524
525           gp_Ax3 anAx3 = anInfo.Position();
526           gp_Dir aD = anAx3.Direction();
527           theDoubles->Append(aD.X());
528           theDoubles->Append(aD.Y());
529           theDoubles->Append(aD.Z());
530         }
531         break;
532       default:
533         if (anInfo.KindOfShape() == GEOMAlgo_KS_PLANE) {
534           // (+) geompy.kind.PLANAR  xo yo zo  dx dy dz  nb_edges nb_vertices
535
536           aKind = SK_PLANAR;
537
538           gp_Pnt aC = anInfo.Location();
539           theDoubles->Append(aC.X());
540           theDoubles->Append(aC.Y());
541           theDoubles->Append(aC.Z());
542
543           gp_Ax3 anAx3 = anInfo.Position();
544           gp_Dir aD = anAx3.Direction();
545           theDoubles->Append(aD.X());
546           theDoubles->Append(aD.Y());
547           theDoubles->Append(aD.Z());
548
549           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
550           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
551         }
552         else {
553           // ??? geompy.kind.FACE  nb_edges nb_vertices _surface_type_id_
554           // (+) geompy.kind.FACE  nb_edges nb_vertices
555
556           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
557           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
558         }
559       }
560     }
561     break;
562
563   case TopAbs_EDGE:
564     {
565       aKind = SK_EDGE;
566
567       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
568       switch (aKN) {
569       case GEOMAlgo_KN_CIRCLE:
570         {
571           // (+) geompy.kind.CIRCLE  xc yc zc  dx dy dz  R
572           aKind = SK_CIRCLE;
573
574           gp_Pnt aC = anInfo.Location();
575           theDoubles->Append(aC.X());
576           theDoubles->Append(aC.Y());
577           theDoubles->Append(aC.Z());
578
579           gp_Ax3 anAx3 = anInfo.Position();
580           gp_Dir aD = anAx3.Direction();
581           theDoubles->Append(aD.X());
582           theDoubles->Append(aD.Y());
583           theDoubles->Append(aD.Z());
584
585           theDoubles->Append(anInfo.Radius1());
586         }
587         break;
588       case GEOMAlgo_KN_ARCCIRCLE:
589         {
590           // (+) geompy.kind.ARC_CIRCLE  xc yc zc  dx dy dz  R  x1 y1 z1  x2 y2 z2
591           aKind = SK_ARC_CIRCLE;
592
593           gp_Pnt aC = anInfo.Location();
594           theDoubles->Append(aC.X());
595           theDoubles->Append(aC.Y());
596           theDoubles->Append(aC.Z());
597
598           gp_Ax3 anAx3 = anInfo.Position();
599           gp_Dir aD = anAx3.Direction();
600           theDoubles->Append(aD.X());
601           theDoubles->Append(aD.Y());
602           theDoubles->Append(aD.Z());
603
604           theDoubles->Append(anInfo.Radius1());
605
606           gp_Pnt aP1 = anInfo.Pnt1();
607           theDoubles->Append(aP1.X());
608           theDoubles->Append(aP1.Y());
609           theDoubles->Append(aP1.Z());
610
611           gp_Pnt aP2 = anInfo.Pnt2();
612           theDoubles->Append(aP2.X());
613           theDoubles->Append(aP2.Y());
614           theDoubles->Append(aP2.Z());
615         }
616         break;
617       case GEOMAlgo_KN_ELLIPSE:
618         {
619           // (+) geompy.kind.ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
620           aKind = SK_ELLIPSE;
621
622           gp_Pnt aC = anInfo.Location();
623           theDoubles->Append(aC.X());
624           theDoubles->Append(aC.Y());
625           theDoubles->Append(aC.Z());
626
627           gp_Ax3 anAx3 = anInfo.Position();
628           gp_Dir aD = anAx3.Direction();
629           theDoubles->Append(aD.X());
630           theDoubles->Append(aD.Y());
631           theDoubles->Append(aD.Z());
632
633           theDoubles->Append(anInfo.Radius1());
634           theDoubles->Append(anInfo.Radius2());
635         }
636         break;
637       case GEOMAlgo_KN_ARCELLIPSE:
638         {
639           // (+) geompy.kind.ARC_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2  x1 y1 z1  x2 y2 z2
640           aKind = SK_ARC_ELLIPSE;
641
642           gp_Pnt aC = anInfo.Location();
643           theDoubles->Append(aC.X());
644           theDoubles->Append(aC.Y());
645           theDoubles->Append(aC.Z());
646
647           gp_Ax3 anAx3 = anInfo.Position();
648           gp_Dir aD = anAx3.Direction();
649           theDoubles->Append(aD.X());
650           theDoubles->Append(aD.Y());
651           theDoubles->Append(aD.Z());
652
653           theDoubles->Append(anInfo.Radius1());
654           theDoubles->Append(anInfo.Radius2());
655
656           gp_Pnt aP1 = anInfo.Pnt1();
657           theDoubles->Append(aP1.X());
658           theDoubles->Append(aP1.Y());
659           theDoubles->Append(aP1.Z());
660
661           gp_Pnt aP2 = anInfo.Pnt2();
662           theDoubles->Append(aP2.X());
663           theDoubles->Append(aP2.Y());
664           theDoubles->Append(aP2.Z());
665         }
666         break;
667       case GEOMAlgo_KN_LINE:
668         {
669           // ??? geompy.kind.LINE  x1 y1 z1  x2 y2 z2
670           // (+) geompy.kind.LINE  x1 y1 z1  dx dy dz
671           aKind = SK_LINE;
672
673           gp_Pnt aO = anInfo.Location();
674           theDoubles->Append(aO.X());
675           theDoubles->Append(aO.Y());
676           theDoubles->Append(aO.Z());
677
678           gp_Dir aD = anInfo.Direction();
679           theDoubles->Append(aD.X());
680           theDoubles->Append(aD.Y());
681           theDoubles->Append(aD.Z());
682         }
683         break;
684       case GEOMAlgo_KN_SEGMENT:
685         {
686           // (+) geompy.kind.SEGMENT  x1 y1 z1  x2 y2 z2
687           aKind = SK_SEGMENT;
688
689           gp_Pnt aP1 = anInfo.Pnt1();
690           theDoubles->Append(aP1.X());
691           theDoubles->Append(aP1.Y());
692           theDoubles->Append(aP1.Z());
693
694           gp_Pnt aP2 = anInfo.Pnt2();
695           theDoubles->Append(aP2.X());
696           theDoubles->Append(aP2.Y());
697           theDoubles->Append(aP2.Z());
698         }
699         break;
700       default:
701         // ??? geompy.kind.EDGE  nb_vertices _curve_type_id_
702         // (+) geompy.kind.EDGE  nb_vertices
703         theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
704       }
705     }
706     break;
707
708   case TopAbs_VERTEX:
709     {
710       // (+) geompy.kind.VERTEX  x y z
711       aKind = SK_VERTEX;
712
713       gp_Pnt aP = anInfo.Location();
714       theDoubles->Append(aP.X());
715       theDoubles->Append(aP.Y());
716       theDoubles->Append(aP.Z());
717     }
718     break;
719   }
720
721   SetErrorCode(OK);
722   return aKind;
723 }
724
725 //=============================================================================
726 /*! Get LCS, corresponding to the given shape.
727  *  Origin of the LCS is situated at the shape's center of mass.
728  *  Axes of the LCS are obtained from shape's location or,
729  *  if the shape is a planar face, from position of its plane.
730  */
731 //=============================================================================
732 gp_Ax3 GEOMImpl_IMeasureOperations::GetPosition (const TopoDS_Shape& theShape)
733 {
734   gp_Ax3 aResult;
735
736   if (theShape.IsNull())
737     return aResult;
738
739   // Axes
740   aResult.Transform(theShape.Location().Transformation());
741   if (theShape.ShapeType() == TopAbs_FACE) {
742     Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape));
743     if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
744       Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
745       gp_Pln aPln = aGPlane->Pln();
746       aResult = aPln.Position();
747     }
748   }
749
750   // Origin
751   gp_Pnt aPnt;
752   if (theShape.ShapeType() == TopAbs_VERTEX) {
753     aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
754   }
755   else {
756     GProp_GProps aSystem;
757     if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_WIRE)
758       BRepGProp::LinearProperties(theShape, aSystem);
759     else if (theShape.ShapeType() == TopAbs_FACE || theShape.ShapeType() == TopAbs_SHELL)
760       BRepGProp::SurfaceProperties(theShape, aSystem);
761     else
762       BRepGProp::VolumeProperties(theShape, aSystem);
763
764     aPnt = aSystem.CentreOfMass();
765   }
766
767   aResult.SetLocation(aPnt);
768
769   return aResult;
770 }
771
772 //=============================================================================
773 /*!
774  *  GetPosition
775  */
776 //=============================================================================
777 void GEOMImpl_IMeasureOperations::GetPosition
778                    (Handle(GEOM_Object) theShape,
779                     Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
780                     Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
781                     Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
782 {
783   SetErrorCode(KO);
784
785   //Set default values: global CS
786   Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
787   Zz = Xx = 1.;
788
789   if (theShape.IsNull()) return;
790
791   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
792   if (aRefShape.IsNull()) return;
793
794   TopoDS_Shape aShape = aRefShape->GetValue();
795   if (aShape.IsNull()) {
796     SetErrorCode("The Objects has NULL Shape");
797     return;
798   }
799
800   try {
801 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
802     OCC_CATCH_SIGNALS;
803 #endif
804
805     gp_Ax3 anAx3 = GetPosition(aShape);
806
807     gp_Pnt anOri = anAx3.Location();
808     gp_Dir aDirZ = anAx3.Direction();
809     gp_Dir aDirX = anAx3.XDirection();
810
811     // Output values
812     anOri.Coord(Ox, Oy, Oz);
813     aDirZ.Coord(Zx, Zy, Zz);
814     aDirX.Coord(Xx, Xy, Xz);
815   }
816   catch (Standard_Failure) {
817     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
818     SetErrorCode(aFail->GetMessageString());
819     return;
820   }
821
822   SetErrorCode(OK);
823 }
824
825 //=============================================================================
826 /*!
827  *  GetCentreOfMass
828  */
829 //=============================================================================
830 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
831                                                 (Handle(GEOM_Object) theShape)
832 {
833   SetErrorCode(KO);
834
835   if (theShape.IsNull()) return NULL;
836
837   //Add a new CentreOfMass object
838   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG);
839
840   //Add a new CentreOfMass function
841   Handle(GEOM_Function) aFunction =
842     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
843   if (aFunction.IsNull()) return NULL;
844
845   //Check if the function is set correctly
846   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
847
848   GEOMImpl_IMeasure aCI (aFunction);
849
850   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
851   if (aRefShape.IsNull()) return NULL;
852
853   aCI.SetBase(aRefShape);
854
855   //Compute the CentreOfMass value
856   try {
857 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
858     OCC_CATCH_SIGNALS;
859 #endif
860     if (!GetSolver()->ComputeFunction(aFunction)) {
861       SetErrorCode("Measure driver failed to compute centre of mass");
862       return NULL;
863     }
864   }
865   catch (Standard_Failure) {
866     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
867     SetErrorCode(aFail->GetMessageString());
868     return NULL;
869   }
870
871   //Make a Python command
872   GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
873
874   SetErrorCode(OK);
875   return aCDG;
876 }
877
878 //=============================================================================
879 /*!
880  *  GetBasicProperties
881  */
882 //=============================================================================
883 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
884                                                       Standard_Real& theLength,
885                                                       Standard_Real& theSurfArea,
886                                                       Standard_Real& theVolume)
887 {
888   SetErrorCode(KO);
889
890   if (theShape.IsNull()) return;
891
892   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
893   if (aRefShape.IsNull()) return;
894
895   TopoDS_Shape aShape = aRefShape->GetValue();
896   if (aShape.IsNull()) {
897     SetErrorCode("The Objects has NULL Shape");
898     return;
899   }
900
901   //Compute the parameters
902   GProp_GProps LProps, SProps;
903   try {
904 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
905     OCC_CATCH_SIGNALS;
906 #endif
907     BRepGProp::LinearProperties(aShape, LProps);
908     theLength = LProps.Mass();
909
910     BRepGProp::SurfaceProperties(aShape, SProps);
911     theSurfArea = SProps.Mass();
912
913     theVolume = 0.0;
914     if (aShape.ShapeType() < TopAbs_SHELL) {
915       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
916         GProp_GProps VProps;
917         BRepGProp::VolumeProperties(Exp.Current(), VProps);
918         theVolume += VProps.Mass();
919       }
920     }
921   }
922   catch (Standard_Failure) {
923     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
924     SetErrorCode(aFail->GetMessageString());
925     return;
926   }
927
928   SetErrorCode(OK);
929 }
930
931 //=============================================================================
932 /*!
933  *  GetInertia
934  */
935 //=============================================================================
936 void GEOMImpl_IMeasureOperations::GetInertia
937                    (Handle(GEOM_Object) theShape,
938                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
939                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
940                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
941                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
942 {
943   SetErrorCode(KO);
944
945   if (theShape.IsNull()) return;
946
947   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
948   if (aRefShape.IsNull()) return;
949
950   TopoDS_Shape aShape = aRefShape->GetValue();
951   if (aShape.IsNull()) {
952     SetErrorCode("The Objects has NULL Shape");
953     return;
954   }
955
956   //Compute the parameters
957   GProp_GProps System;
958
959   try {
960 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
961     OCC_CATCH_SIGNALS;
962 #endif
963     if (aShape.ShapeType() == TopAbs_VERTEX ||
964         aShape.ShapeType() == TopAbs_EDGE ||
965         aShape.ShapeType() == TopAbs_WIRE) {
966       BRepGProp::LinearProperties(aShape, System);
967     } else if (aShape.ShapeType() == TopAbs_FACE ||
968                aShape.ShapeType() == TopAbs_SHELL) {
969       BRepGProp::SurfaceProperties(aShape, System);
970     } else {
971       BRepGProp::VolumeProperties(aShape, System);
972     }
973     gp_Mat I = System.MatrixOfInertia();
974
975     I11 = I(1,1);
976     I12 = I(1,2);
977     I13 = I(1,3);
978
979     I21 = I(2,1);
980     I22 = I(2,2);
981     I23 = I(2,3);
982
983     I31 = I(3,1);
984     I32 = I(3,2);
985     I33 = I(3,3);
986
987     GProp_PrincipalProps Pr = System.PrincipalProperties();
988     Pr.Moments(Ix,Iy,Iz);
989   }
990   catch (Standard_Failure) {
991     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
992     SetErrorCode(aFail->GetMessageString());
993     return;
994   }
995
996   SetErrorCode(OK);
997 }
998
999 //=============================================================================
1000 /*!
1001  *  GetBoundingBox
1002  */
1003 //=============================================================================
1004 void GEOMImpl_IMeasureOperations::GetBoundingBox
1005                                      (Handle(GEOM_Object) theShape,
1006                                       Standard_Real& Xmin, Standard_Real& Xmax,
1007                                       Standard_Real& Ymin, Standard_Real& Ymax,
1008                                       Standard_Real& Zmin, Standard_Real& Zmax)
1009 {
1010   SetErrorCode(KO);
1011
1012   if (theShape.IsNull()) return;
1013
1014   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1015   if (aRefShape.IsNull()) return;
1016
1017   TopoDS_Shape aShape = aRefShape->GetValue();
1018   if (aShape.IsNull()) {
1019     SetErrorCode("The Objects has NULL Shape");
1020     return;
1021   }
1022
1023   //Compute the parameters
1024   Bnd_Box B;
1025
1026   try {
1027 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1028     OCC_CATCH_SIGNALS;
1029 #endif
1030     BRepBndLib::Add(aShape, B);
1031     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1032   }
1033   catch (Standard_Failure) {
1034     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1035     SetErrorCode(aFail->GetMessageString());
1036     return;
1037   }
1038
1039   SetErrorCode(OK);
1040 }
1041
1042 //=============================================================================
1043 /*!
1044  *  GetTolerance
1045  */
1046 //=============================================================================
1047 void GEOMImpl_IMeasureOperations::GetTolerance
1048                                (Handle(GEOM_Object) theShape,
1049                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1050                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1051                                 Standard_Real& VertMin, Standard_Real& VertMax)
1052 {
1053   SetErrorCode(KO);
1054
1055   if (theShape.IsNull()) return;
1056
1057   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1058   if (aRefShape.IsNull()) return;
1059
1060   TopoDS_Shape aShape = aRefShape->GetValue();
1061   if (aShape.IsNull()) {
1062     SetErrorCode("The Objects has NULL Shape");
1063     return;
1064   }
1065
1066   //Compute the parameters
1067   Standard_Real T;
1068   FaceMin = EdgeMin = VertMin = RealLast();
1069   FaceMax = EdgeMax = VertMax = -RealLast();
1070
1071   try {
1072 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1073     OCC_CATCH_SIGNALS;
1074 #endif
1075     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1076       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1077       T = BRep_Tool::Tolerance(Face);
1078       if (T > FaceMax)
1079         FaceMax = T;
1080       if (T < FaceMin)
1081         FaceMin = T;
1082     }
1083     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1084       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1085       T = BRep_Tool::Tolerance(Edge);
1086       if (T > EdgeMax)
1087         EdgeMax = T;
1088       if (T < EdgeMin)
1089         EdgeMin = T;
1090     }
1091     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1092       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1093       T = BRep_Tool::Tolerance(Vertex);
1094       if (T > VertMax)
1095         VertMax = T;
1096       if (T < VertMin)
1097         VertMin = T;
1098     }
1099   }
1100   catch (Standard_Failure) {
1101     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1102     SetErrorCode(aFail->GetMessageString());
1103     return;
1104   }
1105
1106   SetErrorCode(OK);
1107 }
1108
1109 //=============================================================================
1110 /*!
1111  *  CheckShape
1112  */
1113 //=============================================================================
1114 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)      theShape,
1115                                               const Standard_Boolean   theIsCheckGeom,
1116                                               TCollection_AsciiString& theDump)
1117 {
1118   SetErrorCode(KO);
1119
1120   if (theShape.IsNull()) return false;
1121
1122   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1123   if (aRefShape.IsNull()) return false;
1124
1125   TopoDS_Shape aShape = aRefShape->GetValue();
1126   if (aShape.IsNull()) {
1127     SetErrorCode("The Objects has NULL Shape");
1128     return false;
1129   }
1130
1131   //Compute the parameters
1132   bool isValid = false;
1133   try {
1134 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1135     OCC_CATCH_SIGNALS;
1136 #endif
1137     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1138     if (ana.IsValid()) {
1139       theDump.Clear();
1140       isValid = true;
1141     } else {
1142       StructuralDump(ana, aShape, theDump);
1143     }
1144   }
1145   catch (Standard_Failure) {
1146     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1147     SetErrorCode(aFail->GetMessageString());
1148     return false;
1149   }
1150
1151   SetErrorCode(OK);
1152   return isValid;
1153 }
1154
1155 //=============================================================================
1156 /*!
1157  *  WhatIs
1158  */
1159 //=============================================================================
1160 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1161 {
1162   SetErrorCode(KO);
1163
1164   TCollection_AsciiString Astr;
1165
1166   if (theShape.IsNull()) return Astr;
1167
1168   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1169   if (aRefShape.IsNull()) return Astr;
1170
1171   TopoDS_Shape aShape = aRefShape->GetValue();
1172   if (aShape.IsNull()) {
1173     SetErrorCode("The Objects has NULL Shape");
1174     return Astr;
1175   }
1176
1177   //Compute the parameters
1178   if (aShape.ShapeType() == TopAbs_EDGE) {
1179     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1180       Astr = Astr + " It is a degenerated edge \n";
1181     }
1182   }
1183
1184   Astr = Astr + " Number of sub-shapes : \n";
1185
1186   try {
1187 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1188     OCC_CATCH_SIGNALS;
1189 #endif
1190     int iType, nbTypes [TopAbs_SHAPE];
1191     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1192       nbTypes[iType] = 0;
1193     nbTypes[aShape.ShapeType()]++;
1194
1195     TopTools_MapOfShape aMapOfShape;
1196     aMapOfShape.Add(aShape);
1197     TopTools_ListOfShape aListOfShape;
1198     aListOfShape.Append(aShape);
1199
1200     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1201     for (; itL.More(); itL.Next()) {
1202       TopoDS_Iterator it (itL.Value());
1203       for (; it.More(); it.Next()) {
1204         TopoDS_Shape s = it.Value();
1205         if (aMapOfShape.Add(s)) {
1206           aListOfShape.Append(s);
1207           nbTypes[s.ShapeType()]++;
1208         }
1209       }
1210     }
1211
1212     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1213     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1214     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1215     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1216     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1217     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1218     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1219     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1220     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
1221   }
1222   catch (Standard_Failure) {
1223     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1224     SetErrorCode(aFail->GetMessageString());
1225     return Astr;
1226   }
1227
1228   SetErrorCode(OK);
1229   return Astr;
1230 }
1231
1232 //=============================================================================
1233 /*!
1234  *  GetMinDistance
1235  */
1236 //=============================================================================
1237 Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
1238   (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1239    Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1,
1240    Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2)
1241 {
1242   SetErrorCode(KO);
1243   Standard_Real MinDist = 1.e9;
1244
1245   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
1246
1247   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1248   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1249   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
1250
1251   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1252   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1253   if (aShape1.IsNull() || aShape2.IsNull()) {
1254     SetErrorCode("One of Objects has NULL Shape");
1255     return MinDist;
1256   }
1257
1258   //Compute the parameters
1259   try {
1260 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1261     OCC_CATCH_SIGNALS;
1262 #endif
1263     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
1264     if (dst.IsDone()) {
1265       gp_Pnt PMin1, PMin2, P1, P2;
1266
1267       for (int i = 1; i <= dst.NbSolution(); i++) {
1268         P1 = dst.PointOnShape1(i);
1269         P2 = dst.PointOnShape2(i);
1270
1271         Standard_Real Dist = P1.Distance(P2);
1272         if (MinDist > Dist) {
1273           MinDist = Dist;
1274           PMin1 = P1;
1275           PMin2 = P2;
1276         }
1277       }
1278
1279       PMin1.Coord(X1, Y1, Z1);
1280       PMin2.Coord(X2, Y2, Z2);
1281     }
1282   }
1283   catch (Standard_Failure) {
1284     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1285     SetErrorCode(aFail->GetMessageString());
1286     return MinDist;
1287   }
1288
1289   SetErrorCode(OK);
1290   return MinDist;
1291 }
1292
1293 //=======================================================================
1294 //function : PointCoordinates
1295 //purpose  : Get coordinates of point
1296 //=======================================================================
1297 void GEOMImpl_IMeasureOperations::PointCoordinates( Handle(GEOM_Object) theShape,
1298                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ )
1299 {
1300   SetErrorCode( KO );
1301
1302   if ( theShape.IsNull() )
1303     return;
1304
1305   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1306   if ( aRefShape.IsNull() )
1307     return;
1308
1309   TopoDS_Shape aShape = aRefShape->GetValue();
1310   if ( aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX )
1311   {
1312     SetErrorCode( "Shape must be a vertex" );
1313     return;
1314   }
1315
1316   try {
1317 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1318     OCC_CATCH_SIGNALS;
1319 #endif
1320     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
1321     theX = aPnt.X();
1322     theY = aPnt.Y();
1323     theZ = aPnt.Z();
1324     SetErrorCode( OK );
1325   }
1326   catch ( Standard_Failure )
1327   {
1328     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1329     SetErrorCode( aFail->GetMessageString() );
1330   }
1331 }
1332
1333 //=======================================================================
1334 //function : StructuralDump
1335 //purpose  : Structural (data exchange) style of output.
1336 //=======================================================================
1337 void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna,
1338                                                   const TopoDS_Shape&       theShape,
1339                                                   TCollection_AsciiString&  theDump)
1340 {
1341   Standard_Integer i;
1342   theDump.Clear();
1343   theDump += " -- The Shape has problems :\n";
1344   theDump += "  Check                                    Count\n";
1345   theDump += " ------------------------------------------------\n";
1346
1347   Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail;
1348   Handle(TColStd_HArray1OfInteger) NbProblems =
1349     new TColStd_HArray1OfInteger(1, last_stat);
1350   for (i = 1; i <= last_stat; i++)
1351     NbProblems->SetValue(i,0);
1352
1353   Handle(TopTools_HSequenceOfShape) sl;
1354   sl = new TopTools_HSequenceOfShape();
1355   TopTools_DataMapOfShapeListOfShape theMap;
1356   theMap.Clear();
1357   GetProblemShapes(theAna, theShape, sl, NbProblems, theMap);
1358   theMap.Clear();
1359
1360   Standard_Integer count = 0;
1361   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve);
1362   if (count > 0) {
1363     theDump += "  Invalid Point on Curve ................... ";
1364     theDump += TCollection_AsciiString(count) + "\n";
1365   }
1366   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface);
1367   if (count > 0) {
1368     theDump += "  Invalid Point on CurveOnSurface .......... ";
1369     theDump += TCollection_AsciiString(count) + "\n";
1370   }
1371   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface);
1372   if (count > 0) {
1373     theDump += "  Invalid Point on Surface ................. ";
1374     theDump += TCollection_AsciiString(count) + "\n";
1375   }
1376   count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve);
1377   if (count > 0) {
1378     theDump += "  No 3D Curve .............................. ";
1379     theDump += TCollection_AsciiString(count) + "\n";
1380   }
1381   count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve);
1382   if (count > 0) {
1383     theDump += "  Multiple 3D Curve ........................ ";
1384     theDump += TCollection_AsciiString(count) + "\n";
1385   }
1386   count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve);
1387   if (count > 0) {
1388     theDump += "  Invalid 3D Curve ......................... ";
1389     theDump += TCollection_AsciiString(count) + "\n";
1390   }
1391   count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface);
1392   if (count > 0) {
1393     theDump += "  No Curve on Surface ...................... ";
1394     theDump += TCollection_AsciiString(count) + "\n";
1395   }
1396   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface);
1397   if (count > 0) {
1398     theDump += "  Invalid Curve on Surface ................. ";
1399     theDump += TCollection_AsciiString(count) + "\n";
1400   }
1401   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface);
1402   if (count > 0) {
1403     theDump += "  Invalid Curve on closed Surface .......... ";
1404     theDump += TCollection_AsciiString(count) + "\n";
1405   }
1406   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag);
1407   if (count > 0) {
1408     theDump += "  Invalid SameRange Flag ................... ";
1409     theDump += TCollection_AsciiString(count) + "\n";
1410   }
1411   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag);
1412   if (count > 0) {
1413     theDump += "  Invalid SameParameter Flag ............... ";
1414     theDump += TCollection_AsciiString(count) + "\n";
1415   }
1416   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag);
1417   if (count > 0) {
1418     theDump += "  Invalid Degenerated Flag ................. ";
1419     theDump += TCollection_AsciiString(count) + "\n";
1420   }
1421   count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge);
1422   if (count > 0) {
1423     theDump += "  Free Edge ................................ ";
1424     theDump += TCollection_AsciiString(count) + "\n";
1425   }
1426   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity);
1427   if (count > 0) {
1428     theDump += "  Invalid MultiConnexity ................... ";
1429     theDump += TCollection_AsciiString(count) + "\n";
1430   }
1431   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange);
1432   if (count > 0) {
1433     theDump += "  Invalid Range ............................ ";
1434     theDump += TCollection_AsciiString(count) + "\n";
1435   }
1436   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire);
1437   if (count > 0) {
1438     theDump += "  Empty Wire ............................... ";
1439     theDump += TCollection_AsciiString(count) + "\n";
1440   }
1441   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge);
1442   if (count > 0) {
1443     theDump += "  Redundant Edge ........................... ";
1444     theDump += TCollection_AsciiString(count) + "\n";
1445   }
1446   count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire);
1447   if (count > 0) {
1448     theDump += "  Self Intersecting Wire ................... ";
1449     theDump += TCollection_AsciiString(count) + "\n";
1450   }
1451   count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface);
1452   if (count > 0) {
1453     theDump += "  No Surface ............................... ";
1454     theDump += TCollection_AsciiString(count) + "\n";
1455   }
1456   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire);
1457   if (count > 0) {
1458     theDump += "  Invalid Wire ............................. ";
1459     theDump += TCollection_AsciiString(count) + "\n";
1460   }
1461   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire);
1462   if (count > 0) {
1463     theDump += "  Redundant Wire ........................... ";
1464     theDump += TCollection_AsciiString(count) + "\n";
1465   }
1466   count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires);
1467   if (count > 0) {
1468     theDump += "  Intersecting Wires ....................... ";
1469     theDump += TCollection_AsciiString(count) + "\n";
1470   }
1471   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires);
1472   if (count > 0) {
1473     theDump += "  Invalid Imbrication of Wires ............. ";
1474     theDump += TCollection_AsciiString(count) + "\n";
1475   }
1476   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell);
1477   if (count > 0) {
1478     theDump += "  Empty Shell .............................. ";
1479     theDump += TCollection_AsciiString(count) + "\n";
1480   }
1481   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace);
1482   if (count > 0) {
1483     theDump += "  Redundant Face ........................... ";
1484     theDump += TCollection_AsciiString(count) + "\n";
1485   }
1486   count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape);
1487   if (count > 0) {
1488     theDump += "  Unorientable Shape ....................... ";
1489     theDump += TCollection_AsciiString(count) + "\n";
1490   }
1491   count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed);
1492   if (count > 0) {
1493     theDump += "  Not Closed ............................... ";
1494     theDump += TCollection_AsciiString(count) + "\n";
1495   }
1496   count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected);
1497   if (count > 0) {
1498     theDump += "  Not Connected ............................ ";
1499     theDump += TCollection_AsciiString(count) + "\n";
1500   }
1501   count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape);
1502   if (count > 0) {
1503     theDump += "  Subshape not in Shape .................... ";
1504     theDump += TCollection_AsciiString(count) + "\n";
1505   }
1506   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation);
1507   if (count > 0) {
1508     theDump += "  Bad Orientation .......................... ";
1509     theDump += TCollection_AsciiString(count) + "\n";
1510   }
1511   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape);
1512   if (count > 0) {
1513     theDump += "  Bad Orientation of Subshape .............. ";
1514     theDump += TCollection_AsciiString(count) + "\n";
1515   }
1516   count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail);
1517   if (count > 0) {
1518     theDump += "  checkshape failure ....................... ";
1519     theDump += TCollection_AsciiString(count) + "\n";
1520   }
1521
1522   theDump += " ------------------------------------------------\n";
1523   theDump += "*** Shapes with problems : ";
1524   theDump += TCollection_AsciiString(sl->Length()) + "\n";
1525
1526   Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1527   nbv = nbe = nbw = nbf = nbs = nbo = 0;
1528
1529   for (i = 1; i <= sl->Length(); i++) {
1530     TopoDS_Shape shi = sl->Value(i);
1531     TopAbs_ShapeEnum sti = shi.ShapeType();
1532     switch (sti) {
1533       case TopAbs_VERTEX : nbv++; break;
1534       case TopAbs_EDGE   : nbe++; break;
1535       case TopAbs_WIRE   : nbw++; break;
1536       case TopAbs_FACE   : nbf++; break;
1537       case TopAbs_SHELL  : nbs++; break;
1538       case TopAbs_SOLID  : nbo++; break;
1539       default            : break;
1540     }
1541   }
1542
1543   if (nbv > 0) {
1544     theDump += "VERTEX : ";
1545     if (nbv < 10) theDump += " ";
1546     theDump += TCollection_AsciiString(nbv) + "\n";
1547   }
1548   if (nbe > 0) {
1549     theDump += "EDGE   : ";
1550     if (nbe < 10) theDump += " ";
1551     theDump += TCollection_AsciiString(nbe) + "\n";
1552   }
1553   if (nbw > 0) {
1554     theDump += "WIRE   : ";
1555     if (nbw < 10) theDump += " ";
1556     theDump += TCollection_AsciiString(nbw) + "\n";
1557   }
1558   if (nbf > 0) {
1559     theDump += "FACE   : ";
1560     if (nbf < 10) theDump += " ";
1561     theDump += TCollection_AsciiString(nbf) + "\n";
1562   }
1563   if (nbs > 0) {
1564     theDump += "SHELL  : ";
1565     if (nbs < 10) theDump += " ";
1566     theDump += TCollection_AsciiString(nbs) + "\n";
1567   }
1568   if (nbo > 0) {
1569     theDump += "SOLID  : ";
1570     if (nbo < 10) theDump += " ";
1571     theDump += TCollection_AsciiString(nbo) + "\n";
1572   }
1573 }
1574
1575 //=======================================================================
1576 //function : GetProblemShapes
1577 // purpose : for StructuralDump
1578 //=======================================================================
1579 void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer&           theAna,
1580                                                     const TopoDS_Shape&                 theShape,
1581                                                     Handle(TopTools_HSequenceOfShape)&  sl,
1582                                                     Handle(TColStd_HArray1OfInteger)&   NbProblems,
1583                                                     TopTools_DataMapOfShapeListOfShape& theMap)
1584 {
1585   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
1586     GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap);
1587   }
1588   TopAbs_ShapeEnum styp = theShape.ShapeType();
1589   BRepCheck_ListIteratorOfListOfStatus itl;
1590   TopTools_ListOfShape empty;
1591   if (!theMap.IsBound(theShape)) {
1592     theMap.Bind(theShape,empty);
1593
1594     if (!theAna.Result(theShape).IsNull()) {
1595       itl.Initialize(theAna.Result(theShape)->Status());
1596       // !!! May be, we have to print all the problems, not only the first one ?
1597       if (itl.Value() != BRepCheck_NoError) {
1598         sl->Append(theShape);
1599         BRepCheck_Status stat = itl.Value();
1600         NbProblems->SetValue((Standard_Integer)stat,
1601                              NbProblems->Value((Standard_Integer)stat) + 1);
1602       }
1603     }
1604   }
1605
1606   switch (styp) {
1607   case TopAbs_EDGE:
1608     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
1609     break;
1610   case TopAbs_FACE:
1611     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap);
1612     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap);
1613     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
1614     break;
1615   case TopAbs_SHELL:
1616     break;
1617   case TopAbs_SOLID:
1618     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap);
1619     break;
1620   default:
1621     break;
1622   }
1623 }
1624
1625 //=======================================================================
1626 //function : Contains
1627 //=======================================================================
1628 static Standard_Boolean Contains (const TopTools_ListOfShape& L,
1629                                   const TopoDS_Shape& S)
1630 {
1631   TopTools_ListIteratorOfListOfShape it;
1632   for (it.Initialize(L); it.More(); it.Next()) {
1633     if (it.Value().IsSame(S)) {
1634       return Standard_True;
1635     }
1636   }
1637   return Standard_False;
1638 }
1639
1640 //=======================================================================
1641 //function : GetProblemSub
1642 // purpose : for StructuralDump
1643 //=======================================================================
1644 void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&           theAna,
1645                                                  const TopoDS_Shape&                 theShape,
1646                                                  Handle(TopTools_HSequenceOfShape)&  sl,
1647                                                  Handle(TColStd_HArray1OfInteger)&   NbProblems,
1648                                                  const TopAbs_ShapeEnum              Subtype,
1649                                                  TopTools_DataMapOfShapeListOfShape& theMap)
1650 {
1651   BRepCheck_ListIteratorOfListOfStatus itl;
1652   TopExp_Explorer exp;
1653   for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) {
1654     const TopoDS_Shape& sub = exp.Current();
1655
1656     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
1657     for (res->InitContextIterator();
1658          res->MoreShapeInContext();
1659          res->NextShapeInContext()) {
1660       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
1661         theMap(sub).Append(theShape);
1662         itl.Initialize(res->StatusOnShape());
1663
1664         if (itl.Value() != BRepCheck_NoError) {
1665           Standard_Integer ii = 0;
1666
1667           for (ii = 1; ii <= sl->Length(); ii++)
1668             if (sl->Value(ii).IsSame(sub)) break;
1669
1670           if (ii > sl->Length()) {
1671             sl->Append(sub);
1672             BRepCheck_Status stat = itl.Value();
1673             NbProblems->SetValue((Standard_Integer)stat,
1674                                  NbProblems->Value((Standard_Integer)stat) + 1);
1675           }
1676           for (ii = 1; ii <= sl->Length(); ii++)
1677             if (sl->Value(ii).IsSame(theShape)) break;
1678           if (ii > sl->Length()) {
1679             sl->Append(theShape);
1680             BRepCheck_Status stat = itl.Value();
1681             NbProblems->SetValue((Standard_Integer)stat,
1682                                  NbProblems->Value((Standard_Integer)stat) + 1);
1683           }
1684         }
1685         break;
1686       }
1687     }
1688   }
1689 }