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