Salome HOME
Porting to OCCT6.5.1
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 #include <Standard_Stream.hxx>
23
24 #include <GEOMImpl_IMeasureOperations.hxx>
25
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOMImpl_MeasureDriver.hxx>
28 #include <GEOMImpl_IMeasure.hxx>
29 #include <GEOMImpl_IShapesOperations.hxx>
30
31 #include <GEOMAlgo_ShapeInfo.hxx>
32 #include <GEOMAlgo_ShapeInfoFiller.hxx>
33
34 #include <GEOM_Function.hxx>
35 #include <GEOM_PythonDump.hxx>
36
37 #include <Basics_OCCTVersion.hxx>
38
39 #include <utilities.h>
40 #include <OpUtil.hxx>
41 #include <Utils_ExceptHandlers.hxx>
42
43 // OCCT Includes
44 #include <TFunction_DriverTable.hxx>
45 #include <TFunction_Driver.hxx>
46 #include <TFunction_Logbook.hxx>
47 #include <TDF_Tool.hxx>
48
49 #include <BRep_Tool.hxx>
50 #include <BRepAdaptor_Surface.hxx>
51 #include <BRepBndLib.hxx>
52 #include <BRepCheck.hxx>
53 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
54 #include <BRepCheck_Result.hxx>
55 #include <BRepCheck_Shell.hxx>
56 #include <BRepExtrema_DistShapeShape.hxx>
57 #include <BRepGProp.hxx>
58 #include <BRepTools.hxx>
59
60 #include <Bnd_Box.hxx>
61
62 #include <GProp_GProps.hxx>
63 #include <GProp_PrincipalProps.hxx>
64
65 #include <TopAbs.hxx>
66 #include <TopExp.hxx>
67 #include <TopoDS.hxx>
68 #include <TopoDS_Edge.hxx>
69 #include <TopoDS_Face.hxx>
70 #include <TopoDS_Shape.hxx>
71 #include <TopoDS_Vertex.hxx>
72 #include <TopoDS_Iterator.hxx>
73 #include <TopExp_Explorer.hxx>
74 #include <TopTools_MapOfShape.hxx>
75 #include <TopTools_ListOfShape.hxx>
76 #include <TopTools_ListIteratorOfListOfShape.hxx>
77
78 #include <GeomAbs_SurfaceType.hxx>
79 #include <Geom_Surface.hxx>
80 #include <Geom_Plane.hxx>
81 #include <Geom_SphericalSurface.hxx>
82 #include <Geom_CylindricalSurface.hxx>
83 #include <Geom_ToroidalSurface.hxx>
84 #include <Geom_ConicalSurface.hxx>
85 #include <Geom_SurfaceOfLinearExtrusion.hxx>
86 #include <Geom_SurfaceOfRevolution.hxx>
87 #include <Geom_BezierSurface.hxx>
88 #include <Geom_BSplineSurface.hxx>
89 #include <Geom_RectangularTrimmedSurface.hxx>
90 #include <Geom_OffsetSurface.hxx>
91 #include <Geom_Line.hxx>
92
93 #include <gp_Pln.hxx>
94 #include <gp_Lin.hxx>
95
96 #include <GeomAPI_ProjectPointOnCurve.hxx>
97 #include <GeomLProp_CLProps.hxx>
98 #include <GeomLProp_SLProps.hxx>
99 #include <ShapeAnalysis.hxx>
100 #include <ShapeAnalysis_Surface.hxx>
101
102 #include <Standard_Failure.hxx>
103 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
104
105 #include <BRepClass3d_SolidClassifier.hxx>
106 #include <BRep_Builder.hxx>
107 #include <GeomAPI_IntSS.hxx>
108 #include <Geom_Circle.hxx>
109 #include <Geom_SphericalSurface.hxx>
110 #include <Geom_ToroidalSurface.hxx>
111 #include <ShapeFix_Shape.hxx>
112 #include <TopoDS_Compound.hxx>
113
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 /*! Get LCS, corresponding to the given shape.
760  *  Origin of the LCS is situated at the shape's center of mass.
761  *  Axes of the LCS are obtained from shape's location or,
762  *  if the shape is a planar face, from position of its plane.
763  */
764 //=============================================================================
765 gp_Ax3 GEOMImpl_IMeasureOperations::GetPosition (const TopoDS_Shape& theShape)
766 {
767   gp_Ax3 aResult;
768
769   if (theShape.IsNull())
770     return aResult;
771
772   // Axes
773   aResult.Transform(theShape.Location().Transformation());
774   if (theShape.ShapeType() == TopAbs_FACE) {
775     Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape));
776     if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
777       Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
778       gp_Pln aPln = aGPlane->Pln();
779       aResult = aPln.Position();
780     }
781   }
782
783   // Origin
784   gp_Pnt aPnt;
785
786   TopAbs_ShapeEnum aShType = theShape.ShapeType();
787
788   if (aShType == TopAbs_VERTEX) {
789     aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
790   }
791   else {
792     if (aShType == TopAbs_COMPOUND) {
793       aShType = GEOMImpl_IShapesOperations::GetTypeOfSimplePart(theShape);
794     }
795
796     GProp_GProps aSystem;
797     if (aShType == TopAbs_EDGE || aShType == TopAbs_WIRE)
798       BRepGProp::LinearProperties(theShape, aSystem);
799     else if (aShType == TopAbs_FACE || aShType == TopAbs_SHELL)
800       BRepGProp::SurfaceProperties(theShape, aSystem);
801     else
802       BRepGProp::VolumeProperties(theShape, aSystem);
803
804     aPnt = aSystem.CentreOfMass();
805   }
806
807   aResult.SetLocation(aPnt);
808
809   return aResult;
810 }
811
812 //=============================================================================
813 /*!
814  *  GetPosition
815  */
816 //=============================================================================
817 void GEOMImpl_IMeasureOperations::GetPosition
818                    (Handle(GEOM_Object) theShape,
819                     Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
820                     Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
821                     Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
822 {
823   SetErrorCode(KO);
824
825   //Set default values: global CS
826   Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
827   Zz = Xx = 1.;
828
829   if (theShape.IsNull()) return;
830
831   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
832   if (aRefShape.IsNull()) return;
833
834   TopoDS_Shape aShape = aRefShape->GetValue();
835   if (aShape.IsNull()) {
836     SetErrorCode("The Objects has NULL Shape");
837     return;
838   }
839
840   try {
841 #if OCC_VERSION_LARGE > 0x06010000
842     OCC_CATCH_SIGNALS;
843 #endif
844
845     gp_Ax3 anAx3 = GetPosition(aShape);
846
847     gp_Pnt anOri = anAx3.Location();
848     gp_Dir aDirZ = anAx3.Direction();
849     gp_Dir aDirX = anAx3.XDirection();
850
851     // Output values
852     anOri.Coord(Ox, Oy, Oz);
853     aDirZ.Coord(Zx, Zy, Zz);
854     aDirX.Coord(Xx, Xy, Xz);
855   }
856   catch (Standard_Failure) {
857     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
858     SetErrorCode(aFail->GetMessageString());
859     return;
860   }
861
862   SetErrorCode(OK);
863 }
864
865 //=============================================================================
866 /*!
867  *  GetCentreOfMass
868  */
869 //=============================================================================
870 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
871                                                 (Handle(GEOM_Object) theShape)
872 {
873   SetErrorCode(KO);
874
875   if (theShape.IsNull()) return NULL;
876
877   //Add a new CentreOfMass object
878   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG);
879
880   //Add a new CentreOfMass function
881   Handle(GEOM_Function) aFunction =
882     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
883   if (aFunction.IsNull()) return NULL;
884
885   //Check if the function is set correctly
886   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
887
888   GEOMImpl_IMeasure aCI (aFunction);
889
890   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
891   if (aRefShape.IsNull()) return NULL;
892
893   aCI.SetBase(aRefShape);
894
895   //Compute the CentreOfMass value
896   try {
897 #if OCC_VERSION_LARGE > 0x06010000
898     OCC_CATCH_SIGNALS;
899 #endif
900     if (!GetSolver()->ComputeFunction(aFunction)) {
901       SetErrorCode("Measure driver failed to compute centre of mass");
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) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
913
914   SetErrorCode(OK);
915   return aCDG;
916 }
917
918 //=============================================================================
919 /*!
920  *  GetVertexByIndex
921  */
922 //=============================================================================
923 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
924                                                 (Handle(GEOM_Object) theShape,
925                                                  Standard_Integer theIndex)
926 {
927   SetErrorCode(KO);
928
929   if (theShape.IsNull()) return NULL;
930
931   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
932   if (aRefShape.IsNull()) return NULL;
933
934   //Add a new Vertex object
935   Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GetDocID(), GEOM_POINT);
936
937   //Add a function
938   Handle(GEOM_Function) aFunction =
939     aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
940   if (aFunction.IsNull()) return NULL;
941
942   //Check if the function is set correctly
943   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
944
945   GEOMImpl_IMeasure aCI (aFunction);
946   aCI.SetBase(aRefShape);
947   aCI.SetIndex(theIndex);
948
949   //Compute
950   try {
951 #if OCC_VERSION_LARGE > 0x06010000
952     OCC_CATCH_SIGNALS;
953 #endif
954     if (!GetSolver()->ComputeFunction(aFunction)) {
955       SetErrorCode("Vertex by index driver failed.");
956       return NULL;
957     }
958   }
959   catch (Standard_Failure) {
960     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
961     SetErrorCode(aFail->GetMessageString());
962     return NULL;
963   }
964
965   //Make a Python command
966   GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" << theShape << ", " << theIndex << ")";
967
968   SetErrorCode(OK);
969   return aVertex;
970 }
971
972 //=============================================================================
973 /*!
974  *  GetNormal
975  */
976 //=============================================================================
977 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
978                                          (Handle(GEOM_Object) theFace,
979                                           Handle(GEOM_Object) theOptionalPoint)
980 {
981   SetErrorCode(KO);
982
983   if (theFace.IsNull()) return NULL;
984
985   //Add a new Normale object
986   Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GetDocID(), GEOM_VECTOR);
987
988   //Add a new Normale function
989   Handle(GEOM_Function) aFunction =
990     aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
991   if (aFunction.IsNull()) return NULL;
992
993   //Check if the function is set correctly
994   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
995
996   GEOMImpl_IMeasure aCI (aFunction);
997
998   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
999   if (aFace.IsNull()) return NULL;
1000
1001   aCI.SetBase(aFace);
1002
1003   if (!theOptionalPoint.IsNull()) {
1004     Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
1005     aCI.SetPoint(anOptPnt);
1006   }
1007
1008   //Compute the Normale value
1009   try {
1010 #if OCC_VERSION_LARGE > 0x06010000
1011     OCC_CATCH_SIGNALS;
1012 #endif
1013     if (!GetSolver()->ComputeFunction(aFunction)) {
1014       SetErrorCode("Measure driver failed to compute normake of face");
1015       return NULL;
1016     }
1017   }
1018   catch (Standard_Failure) {
1019     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1020     SetErrorCode(aFail->GetMessageString());
1021     return NULL;
1022   }
1023
1024   //Make a Python command
1025   GEOM::TPythonDump pd (aFunction);
1026   pd << aNorm << " = geompy.GetNormal(" << theFace;
1027   if (!theOptionalPoint.IsNull()) {
1028     pd << ", " << theOptionalPoint;
1029   }
1030   pd << ")";
1031
1032   SetErrorCode(OK);
1033   return aNorm;
1034 }
1035
1036 //=============================================================================
1037 /*!
1038  *  GetBasicProperties
1039  */
1040 //=============================================================================
1041 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
1042                                                       Standard_Real& theLength,
1043                                                       Standard_Real& theSurfArea,
1044                                                       Standard_Real& theVolume)
1045 {
1046   SetErrorCode(KO);
1047
1048   if (theShape.IsNull()) return;
1049
1050   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1051   if (aRefShape.IsNull()) return;
1052
1053   TopoDS_Shape aShape = aRefShape->GetValue();
1054   if (aShape.IsNull()) {
1055     SetErrorCode("The Objects has NULL Shape");
1056     return;
1057   }
1058
1059   //Compute the parameters
1060   GProp_GProps LProps, SProps;
1061   try {
1062 #if OCC_VERSION_LARGE > 0x06010000
1063     OCC_CATCH_SIGNALS;
1064 #endif
1065     BRepGProp::LinearProperties(aShape, LProps);
1066     theLength = LProps.Mass();
1067
1068     BRepGProp::SurfaceProperties(aShape, SProps);
1069     theSurfArea = SProps.Mass();
1070
1071     theVolume = 0.0;
1072     if (aShape.ShapeType() < TopAbs_SHELL) {
1073       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1074         GProp_GProps VProps;
1075         BRepGProp::VolumeProperties(Exp.Current(), VProps);
1076         theVolume += VProps.Mass();
1077       }
1078     }
1079   }
1080   catch (Standard_Failure) {
1081     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1082     SetErrorCode(aFail->GetMessageString());
1083     return;
1084   }
1085
1086   SetErrorCode(OK);
1087 }
1088
1089 //=============================================================================
1090 /*!
1091  *  GetInertia
1092  */
1093 //=============================================================================
1094 void GEOMImpl_IMeasureOperations::GetInertia
1095                    (Handle(GEOM_Object) theShape,
1096                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1097                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1098                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1099                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1100 {
1101   SetErrorCode(KO);
1102
1103   if (theShape.IsNull()) return;
1104
1105   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1106   if (aRefShape.IsNull()) return;
1107
1108   TopoDS_Shape aShape = aRefShape->GetValue();
1109   if (aShape.IsNull()) {
1110     SetErrorCode("The Objects has NULL Shape");
1111     return;
1112   }
1113
1114   //Compute the parameters
1115   GProp_GProps System;
1116
1117   try {
1118 #if OCC_VERSION_LARGE > 0x06010000
1119     OCC_CATCH_SIGNALS;
1120 #endif
1121     if (aShape.ShapeType() == TopAbs_VERTEX ||
1122         aShape.ShapeType() == TopAbs_EDGE ||
1123         aShape.ShapeType() == TopAbs_WIRE) {
1124       BRepGProp::LinearProperties(aShape, System);
1125     } else if (aShape.ShapeType() == TopAbs_FACE ||
1126                aShape.ShapeType() == TopAbs_SHELL) {
1127       BRepGProp::SurfaceProperties(aShape, System);
1128     } else {
1129       BRepGProp::VolumeProperties(aShape, System);
1130     }
1131     gp_Mat I = System.MatrixOfInertia();
1132
1133     I11 = I(1,1);
1134     I12 = I(1,2);
1135     I13 = I(1,3);
1136
1137     I21 = I(2,1);
1138     I22 = I(2,2);
1139     I23 = I(2,3);
1140
1141     I31 = I(3,1);
1142     I32 = I(3,2);
1143     I33 = I(3,3);
1144
1145     GProp_PrincipalProps Pr = System.PrincipalProperties();
1146     Pr.Moments(Ix,Iy,Iz);
1147   }
1148   catch (Standard_Failure) {
1149     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1150     SetErrorCode(aFail->GetMessageString());
1151     return;
1152   }
1153
1154   SetErrorCode(OK);
1155 }
1156
1157 //=============================================================================
1158 /*!
1159  *  GetBoundingBox
1160  */
1161 //=============================================================================
1162 void GEOMImpl_IMeasureOperations::GetBoundingBox
1163                                      (Handle(GEOM_Object) theShape,
1164                                       Standard_Real& Xmin, Standard_Real& Xmax,
1165                                       Standard_Real& Ymin, Standard_Real& Ymax,
1166                                       Standard_Real& Zmin, Standard_Real& Zmax)
1167 {
1168   SetErrorCode(KO);
1169
1170   if (theShape.IsNull()) return;
1171
1172   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1173   if (aRefShape.IsNull()) return;
1174
1175   TopoDS_Shape aShape = aRefShape->GetValue();
1176   if (aShape.IsNull()) {
1177     SetErrorCode("The Objects has NULL Shape");
1178     return;
1179   }
1180
1181   //Compute the parameters
1182   Bnd_Box B;
1183
1184   try {
1185 #if OCC_VERSION_LARGE > 0x06010000
1186     OCC_CATCH_SIGNALS;
1187 #endif
1188     BRepBndLib::Add(aShape, B);
1189     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1190   }
1191   catch (Standard_Failure) {
1192     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1193     SetErrorCode(aFail->GetMessageString());
1194     return;
1195   }
1196
1197   SetErrorCode(OK);
1198 }
1199
1200 //=============================================================================
1201 /*!
1202  *  GetTolerance
1203  */
1204 //=============================================================================
1205 void GEOMImpl_IMeasureOperations::GetTolerance
1206                                (Handle(GEOM_Object) theShape,
1207                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1208                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1209                                 Standard_Real& VertMin, Standard_Real& VertMax)
1210 {
1211   SetErrorCode(KO);
1212
1213   if (theShape.IsNull()) return;
1214
1215   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1216   if (aRefShape.IsNull()) return;
1217
1218   TopoDS_Shape aShape = aRefShape->GetValue();
1219   if (aShape.IsNull()) {
1220     SetErrorCode("The Objects has NULL Shape");
1221     return;
1222   }
1223
1224   //Compute the parameters
1225   Standard_Real T;
1226   FaceMin = EdgeMin = VertMin = RealLast();
1227   FaceMax = EdgeMax = VertMax = -RealLast();
1228
1229   try {
1230 #if OCC_VERSION_LARGE > 0x06010000
1231     OCC_CATCH_SIGNALS;
1232 #endif
1233     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1234       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1235       T = BRep_Tool::Tolerance(Face);
1236       if (T > FaceMax)
1237         FaceMax = T;
1238       if (T < FaceMin)
1239         FaceMin = T;
1240     }
1241     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1242       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1243       T = BRep_Tool::Tolerance(Edge);
1244       if (T > EdgeMax)
1245         EdgeMax = T;
1246       if (T < EdgeMin)
1247         EdgeMin = T;
1248     }
1249     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1250       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1251       T = BRep_Tool::Tolerance(Vertex);
1252       if (T > VertMax)
1253         VertMax = T;
1254       if (T < VertMin)
1255         VertMin = T;
1256     }
1257   }
1258   catch (Standard_Failure) {
1259     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1260     SetErrorCode(aFail->GetMessageString());
1261     return;
1262   }
1263
1264   SetErrorCode(OK);
1265 }
1266
1267 //=============================================================================
1268 /*!
1269  *  CheckShape
1270  */
1271 //=============================================================================
1272 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)      theShape,
1273                                               const Standard_Boolean   theIsCheckGeom,
1274                                               TCollection_AsciiString& theDump)
1275 {
1276   SetErrorCode(KO);
1277
1278   if (theShape.IsNull()) return false;
1279
1280   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1281   if (aRefShape.IsNull()) return false;
1282
1283   TopoDS_Shape aShape = aRefShape->GetValue();
1284   if (aShape.IsNull()) {
1285     SetErrorCode("The Objects has NULL Shape");
1286     return false;
1287   }
1288
1289   //Compute the parameters
1290   bool isValid = false;
1291   try {
1292 #if OCC_VERSION_LARGE > 0x06010000
1293     OCC_CATCH_SIGNALS;
1294 #endif
1295     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1296     if (ana.IsValid()) {
1297       theDump.Clear();
1298       isValid = true;
1299     } else {
1300       StructuralDump(ana, aShape, theDump);
1301     }
1302   }
1303   catch (Standard_Failure) {
1304     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1305     SetErrorCode(aFail->GetMessageString());
1306     return false;
1307   }
1308
1309   SetErrorCode(OK);
1310   return isValid;
1311 }
1312
1313 //=============================================================================
1314 /*!
1315  *  IsGoodForSolid
1316  */
1317 //=============================================================================
1318 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1319 {
1320   SetErrorCode(KO);
1321
1322   TCollection_AsciiString aRes = "";
1323
1324   if (theShape.IsNull()) {
1325     aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1326   }
1327   else {
1328     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1329     if (aRefShape.IsNull()) {
1330       aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1331     }
1332     else {
1333       TopoDS_Shape aShape = aRefShape->GetValue();
1334       if (aShape.IsNull()) {
1335         aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1336       }
1337       else {
1338         if (aShape.ShapeType() == TopAbs_COMPOUND) {
1339           TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1340           if (It.More()) aShape = It.Value();
1341         }
1342         if (aShape.ShapeType() == TopAbs_SHELL) {
1343           BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
1344           if (chkShell.Closed() == BRepCheck_NotClosed) {
1345             aRes = "WRN_SHAPE_UNCLOSED";
1346           }
1347         }
1348         else {
1349           aRes = "WRN_SHAPE_NOT_SHELL";
1350         }
1351       }
1352     }
1353   }
1354
1355   if (aRes.IsEmpty())
1356     SetErrorCode(OK);
1357
1358   return aRes;
1359 }
1360
1361 //=============================================================================
1362 /*!
1363  *  WhatIs
1364  */
1365 //=============================================================================
1366 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1367 {
1368   SetErrorCode(KO);
1369
1370   TCollection_AsciiString Astr;
1371
1372   if (theShape.IsNull()) return Astr;
1373
1374   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1375   if (aRefShape.IsNull()) return Astr;
1376
1377   TopoDS_Shape aShape = aRefShape->GetValue();
1378   if (aShape.IsNull()) {
1379     SetErrorCode("The Objects has NULL Shape");
1380     return Astr;
1381   }
1382
1383   //Compute the parameters
1384   if (aShape.ShapeType() == TopAbs_EDGE) {
1385     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1386       Astr = Astr + " It is a degenerated edge \n";
1387     }
1388   }
1389
1390   Astr = Astr + " Number of sub-shapes : \n";
1391
1392   try {
1393 #if OCC_VERSION_LARGE > 0x06010000
1394     OCC_CATCH_SIGNALS;
1395 #endif
1396     int iType, nbTypes [TopAbs_SHAPE];
1397     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1398       nbTypes[iType] = 0;
1399     nbTypes[aShape.ShapeType()]++;
1400
1401     TopTools_MapOfShape aMapOfShape;
1402     aMapOfShape.Add(aShape);
1403     TopTools_ListOfShape aListOfShape;
1404     aListOfShape.Append(aShape);
1405
1406     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1407     for (; itL.More(); itL.Next()) {
1408       TopoDS_Iterator it (itL.Value());
1409       for (; it.More(); it.Next()) {
1410         TopoDS_Shape s = it.Value();
1411         if (aMapOfShape.Add(s)) {
1412           aListOfShape.Append(s);
1413           nbTypes[s.ShapeType()]++;
1414         }
1415       }
1416     }
1417
1418     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1419     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1420     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1421     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1422     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1423     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1424     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1425     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1426     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent());
1427   }
1428   catch (Standard_Failure) {
1429     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1430     SetErrorCode(aFail->GetMessageString());
1431     return Astr;
1432   }
1433
1434   SetErrorCode(OK);
1435   return Astr;
1436 }
1437
1438
1439 //=======================================================================
1440 //function : CheckSingularCase
1441 //purpose  : auxilary for GetMinDistance()
1442 //           workaround for bugs 19899, 19908 and 19910 from Mantis
1443 //=======================================================================
1444 static double CheckSingularCase(const TopoDS_Shape& aSh1,
1445                                 const TopoDS_Shape& aSh2,
1446                                 gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
1447 {
1448   bool IsChange1 = false;
1449   double AddDist1 = 0.0;
1450   TopExp_Explorer anExp;
1451   TopoDS_Shape tmpSh1, tmpSh2;
1452   int nbf = 0;
1453   for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1454     nbf++;
1455     tmpSh1 = anExp.Current();
1456   }
1457   if(nbf==1) {
1458     TopoDS_Shape sh = aSh1;
1459     while(sh.ShapeType()==TopAbs_COMPOUND) {
1460       TopoDS_Iterator it(sh);
1461       sh = it.Value();
1462     }
1463     Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
1464     if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1465         S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1466       if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
1467         // non solid case
1468         double U1,U2,V1,V2;
1469         // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
1470         //S->Bounds(U1,U2,V1,V2); changed by
1471         ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh1),U1,U2,V1,V2);
1472         // end of changes for 020677 (dmv)
1473         Handle(Geom_RectangularTrimmedSurface) TrS1 =
1474           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
1475         Handle(Geom_RectangularTrimmedSurface) TrS2 =
1476           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
1477         BRep_Builder B;
1478         TopoDS_Face F1,F2;
1479         TopoDS_Compound Comp;
1480         B.MakeCompound(Comp);
1481         B.MakeFace(F1,TrS1,1.e-7);
1482         B.Add(Comp,F1);
1483         B.MakeFace(F2,TrS2,1.e-7);
1484         B.Add(Comp,F2);
1485         Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
1486         sfs->Init(Comp);
1487         sfs->SetPrecision(1.e-6);
1488         sfs->SetMaxTolerance(1.0);
1489         sfs->Perform();
1490         tmpSh1 = sfs->Shape();
1491         IsChange1 = true;
1492       }
1493       else {
1494         if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
1495           Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
1496           gp_Pnt PC = SS->Location();
1497           BRep_Builder B;
1498           TopoDS_Vertex V;
1499           B.MakeVertex(V,PC,1.e-7);
1500           tmpSh1 = V;
1501           AddDist1 = SS->Radius();
1502           IsChange1 = true;
1503         }
1504         else {
1505           Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
1506           gp_Ax3 ax3 = TS->Position();
1507           Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
1508           BRep_Builder B;
1509           TopoDS_Edge E;
1510           B.MakeEdge(E,C,1.e-7);
1511           tmpSh1 = E;
1512           AddDist1 = TS->MinorRadius();
1513           IsChange1 = true;
1514         }
1515       }
1516     }
1517     else
1518       tmpSh1 = aSh1;
1519   }
1520   else
1521     tmpSh1 = aSh1;
1522   bool IsChange2 = false;
1523   double AddDist2 = 0.0;
1524   nbf = 0;
1525   for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1526     nbf++;
1527     tmpSh2 = anExp.Current();
1528   }
1529   if(nbf==1) {
1530     TopoDS_Shape sh = aSh2;
1531     while(sh.ShapeType()==TopAbs_COMPOUND) {
1532       TopoDS_Iterator it(sh);
1533       sh = it.Value();
1534     }
1535     Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
1536     if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1537         S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1538       if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
1539         // non solid case
1540         double U1,U2,V1,V2;
1541         //S->Bounds(U1,U2,V1,V2);
1542         ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh2),U1,U2,V1,V2);
1543         Handle(Geom_RectangularTrimmedSurface) TrS1 =
1544           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
1545         Handle(Geom_RectangularTrimmedSurface) TrS2 =
1546           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
1547         BRep_Builder B;
1548         TopoDS_Face F1,F2;
1549         TopoDS_Compound Comp;
1550         B.MakeCompound(Comp);
1551         B.MakeFace(F1,TrS1,1.e-7);
1552         B.Add(Comp,F1);
1553         B.MakeFace(F2,TrS2,1.e-7);
1554         B.Add(Comp,F2);
1555         Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
1556         sfs->Init(Comp);
1557         sfs->SetPrecision(1.e-6);
1558         sfs->SetMaxTolerance(1.0);
1559         sfs->Perform();
1560         tmpSh2 = sfs->Shape();
1561         IsChange2 = true;
1562       }
1563       else {
1564         if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
1565           Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
1566           gp_Pnt PC = SS->Location();
1567           BRep_Builder B;
1568           TopoDS_Vertex V;
1569           B.MakeVertex(V,PC,1.e-7);
1570           tmpSh2 = V;
1571           AddDist2 = SS->Radius();
1572           IsChange2 = true;
1573         }
1574         else if( S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1575           Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
1576           gp_Ax3 ax3 = TS->Position();
1577           Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
1578           BRep_Builder B;
1579           TopoDS_Edge E;
1580           B.MakeEdge(E,C,1.e-7);
1581           tmpSh2 = E;
1582           AddDist2 = TS->MinorRadius();
1583           IsChange2 = true;
1584         }
1585       }
1586     }
1587     else
1588       tmpSh2 = aSh2;
1589   }
1590   else
1591     tmpSh2 = aSh2;
1592
1593   if( !IsChange1 && !IsChange2 )
1594     return -2.0;
1595
1596   BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
1597   if (dst.IsDone()) {
1598     double MinDist = 1.e9;
1599     gp_Pnt PMin1, PMin2, P1, P2;
1600     for (int i = 1; i <= dst.NbSolution(); i++) {
1601       P1 = dst.PointOnShape1(i);
1602       P2 = dst.PointOnShape2(i);
1603       Standard_Real Dist = P1.Distance(P2);
1604       if (MinDist > Dist) {
1605         MinDist = Dist;
1606         PMin1 = P1;
1607         PMin2 = P2;
1608       }
1609     }
1610     if(MinDist<1.e-7) {
1611       Ptmp1 = PMin1;
1612       Ptmp2 = PMin2;
1613     }
1614     else {
1615       gp_Dir aDir(gp_Vec(PMin1,PMin2));
1616       if( MinDist > (AddDist1+AddDist2) ) {
1617         Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
1618                         PMin1.Y() + aDir.Y()*AddDist1,
1619                         PMin1.Z() + aDir.Z()*AddDist1 );
1620         Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
1621                         PMin2.Y() - aDir.Y()*AddDist2,
1622                         PMin2.Z() - aDir.Z()*AddDist2 );
1623         return (MinDist - AddDist1 - AddDist2);
1624       }
1625       else {
1626         if( AddDist1 > 0 ) {
1627           Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
1628                           PMin1.Y() + aDir.Y()*AddDist1,
1629                           PMin1.Z() + aDir.Z()*AddDist1 );
1630           Ptmp2 = Ptmp1;
1631         }
1632         else {
1633           Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
1634                           PMin2.Y() - aDir.Y()*AddDist2,
1635                           PMin2.Z() - aDir.Z()*AddDist2 );
1636           Ptmp1 = Ptmp2;
1637         }
1638       }
1639     }
1640     double res = MinDist - AddDist1 - AddDist2;
1641     if(res<0.) res = 0.0;
1642     return res;
1643   }
1644   return -2.0;
1645 }
1646 /* old variant
1647 static bool CheckSingularCase(const TopoDS_Shape& aSh1,
1648                               const TopoDS_Shape& aSh2,
1649                               gp_Pnt& Ptmp)
1650 {
1651   TopExp_Explorer anExp;
1652   TopoDS_Shape tmpSh1, tmpSh2;
1653   int nbf = 0;
1654   for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1655     nbf++;
1656     tmpSh1 = anExp.Current();
1657   }
1658   if(nbf==1) {
1659     Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
1660     if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1661         S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1662       nbf = 0;
1663       for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1664         nbf++;
1665         tmpSh2 = anExp.Current();
1666         Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
1667         GeomAPI_IntSS ISS(S1,S2,1.e-7);
1668         if(ISS.IsDone()) {
1669           for(int i=1; i<=ISS.NbLines(); i++) {
1670             Handle(Geom_Curve) C3d = ISS.Line(i);
1671             BRep_Builder B;
1672             TopoDS_Edge E;
1673             B.MakeEdge(E,C3d,1.e-7);
1674             BRepExtrema_DistShapeShape dst(tmpSh2,E);
1675             if (dst.IsDone()) {
1676               gp_Pnt PMin1, PMin2, P1, P2;
1677               double MinDist = 1.e9;
1678               for (int i = 1; i <= dst.NbSolution(); i++) {
1679                 P1 = dst.PointOnShape1(i);
1680                 P2 = dst.PointOnShape2(i);
1681                 Standard_Real Dist = P1.Distance(P2);
1682                 if (MinDist > Dist) {
1683                   MinDist = Dist;
1684                   Ptmp = P1;
1685                 }
1686               }
1687               if(MinDist<1.e-7)
1688                 return true;
1689             }
1690           }
1691         }
1692       }
1693     }
1694   }
1695   nbf = 0;
1696   for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1697     nbf++;
1698     tmpSh1 = anExp.Current();
1699   }
1700   if(nbf==1) {
1701     Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
1702     if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1703         S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
1704       nbf = 0;
1705       for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1706         nbf++;
1707         tmpSh2 = anExp.Current();
1708         Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
1709         GeomAPI_IntSS ISS(S1,S2,1.e-7);
1710         if(ISS.IsDone()) {
1711           for(int i=1; i<=ISS.NbLines(); i++) {
1712             Handle(Geom_Curve) C3d = ISS.Line(i);
1713             BRep_Builder B;
1714             TopoDS_Edge E;
1715             B.MakeEdge(E,C3d,1.e-7);
1716             BRepExtrema_DistShapeShape dst(tmpSh2,E);
1717             if (dst.IsDone()) {
1718               gp_Pnt P1,P2;
1719               double MinDist = 1.e9;
1720               for (int i = 1; i <= dst.NbSolution(); i++) {
1721                 P1 = dst.PointOnShape1(i);
1722                 P2 = dst.PointOnShape2(i);
1723                 Standard_Real Dist = P1.Distance(P2);
1724                 if (MinDist > Dist) {
1725                   MinDist = Dist;
1726                   Ptmp = P1;
1727                 }
1728               }
1729               if(MinDist<1.e-7)
1730                 return true;
1731             }
1732           }
1733         }
1734       }
1735     }
1736   }
1737   return false;
1738 }
1739 */
1740
1741
1742 //=============================================================================
1743 /*!
1744  *  AreCoordsInside
1745  */
1746 //=============================================================================
1747 std::vector<bool> GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape,
1748                                                                const std::vector<double>& coords,
1749                                                                double tolerance)
1750 {
1751   std::vector<bool> res;
1752   if (!theShape.IsNull()) {
1753     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1754     if (!aRefShape.IsNull()) {
1755       TopoDS_Shape aShape = aRefShape->GetValue();
1756       if (!aShape.IsNull()) {
1757         BRepClass3d_SolidClassifier SC(aShape);
1758         unsigned int nb_points = coords.size()/3;
1759         for (int i = 0; i < nb_points; i++) {
1760           double x = coords[3*i];
1761           double y = coords[3*i+1];
1762           double z = coords[3*i+2];
1763           gp_Pnt aPnt(x, y, z);
1764           SC.Perform(aPnt, tolerance);
1765           res.push_back( ( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ) );
1766         }
1767       }
1768     }
1769   }
1770   return res;
1771 }
1772
1773 //=============================================================================
1774 /*!
1775  *  GetMinDistance
1776  */
1777 //=============================================================================
1778 Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance
1779   (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1780    Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1,
1781    Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2)
1782 {
1783   SetErrorCode(KO);
1784   Standard_Real MinDist = 1.e9;
1785
1786   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
1787
1788   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1789   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1790   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
1791
1792   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1793   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1794   if (aShape1.IsNull() || aShape2.IsNull()) {
1795     SetErrorCode("One of Objects has NULL Shape");
1796     return MinDist;
1797   }
1798
1799   //Compute the parameters
1800   try {
1801 #if OCC_VERSION_LARGE > 0x06010000
1802     OCC_CATCH_SIGNALS;
1803 #endif
1804
1805     // Issue 0020231: A min distance bug with torus and vertex.
1806     // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
1807
1808     // which of shapes consists of only one vertex?
1809     TopExp_Explorer exp1(aShape1,TopAbs_VERTEX), exp2(aShape2,TopAbs_VERTEX);
1810     TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
1811     TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
1812     exp1.Next(); exp2.Next();
1813     if ( exp1.More() ) V1.Nullify();
1814     if ( exp2.More() ) V2.Nullify();
1815     // vertex and container of solids
1816     TopoDS_Shape V = V1.IsNull() ? V2 : V1;
1817     TopoDS_Shape S = V1.IsNull() ? aShape1 : aShape2;
1818     if ( !V.IsNull() ) {
1819       // classify vertex against solids
1820       gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
1821       for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
1822         BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
1823         if ( classifier.State() == TopAbs_IN ) {
1824           p.Coord(X1, Y1, Z1);
1825           p.Coord(X2, Y2, Z2);
1826           SetErrorCode(OK);
1827           return 0.0;
1828         }
1829       }
1830     }
1831     // End Issue 0020231
1832
1833     // skl 30.06.2008
1834     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
1835     gp_Pnt Ptmp1, Ptmp2;
1836     double dist = CheckSingularCase(aShape1, aShape2, Ptmp1, Ptmp2);
1837     if(dist>-1.0) {
1838       Ptmp1.Coord(X1, Y1, Z1);
1839       Ptmp2.Coord(X2, Y2, Z2);
1840       SetErrorCode(OK);
1841       return dist;
1842     }
1843
1844     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
1845     if (dst.IsDone()) {
1846       gp_Pnt PMin1, PMin2, P1, P2;
1847
1848       for (int i = 1; i <= dst.NbSolution(); i++) {
1849         P1 = dst.PointOnShape1(i);
1850         P2 = dst.PointOnShape2(i);
1851
1852         Standard_Real Dist = P1.Distance(P2);
1853         if (MinDist > Dist) {
1854           MinDist = Dist;
1855           PMin1 = P1;
1856           PMin2 = P2;
1857         }
1858       }
1859
1860       PMin1.Coord(X1, Y1, Z1);
1861       PMin2.Coord(X2, Y2, Z2);
1862     }
1863   }
1864   catch (Standard_Failure) {
1865     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1866     SetErrorCode(aFail->GetMessageString());
1867     return MinDist;
1868   }
1869
1870   SetErrorCode(OK);
1871   return MinDist;
1872 }
1873
1874 //=======================================================================
1875 /*!
1876  *  Get coordinates of point
1877  */
1878 //=======================================================================
1879 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
1880                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
1881 {
1882   SetErrorCode(KO);
1883
1884   if (theShape.IsNull())
1885     return;
1886
1887   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1888   if (aRefShape.IsNull())
1889     return;
1890
1891   TopoDS_Shape aShape = aRefShape->GetValue();
1892   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
1893   {
1894     SetErrorCode( "Shape must be a vertex" );
1895     return;
1896   }
1897
1898   try {
1899 #if OCC_VERSION_LARGE > 0x06010000
1900     OCC_CATCH_SIGNALS;
1901 #endif
1902     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
1903     theX = aPnt.X();
1904     theY = aPnt.Y();
1905     theZ = aPnt.Z();
1906
1907     SetErrorCode(OK);
1908   }
1909   catch (Standard_Failure)
1910   {
1911     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1912     SetErrorCode( aFail->GetMessageString() );
1913   }
1914 }
1915
1916 //=======================================================================
1917 /*!
1918  *  Compute angle (in degrees) between two lines
1919  */
1920 //=======================================================================
1921 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
1922                                                      Handle(GEOM_Object) theLine2)
1923 {
1924   SetErrorCode(KO);
1925
1926   Standard_Real anAngle = -1.0;
1927
1928   if (theLine1.IsNull() || theLine2.IsNull())
1929     return anAngle;
1930
1931   Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
1932   Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
1933   if (aRefLine1.IsNull() || aRefLine2.IsNull())
1934     return anAngle;
1935
1936   TopoDS_Shape aLine1 = aRefLine1->GetValue();
1937   TopoDS_Shape aLine2 = aRefLine2->GetValue();
1938   if (aLine1.IsNull() || aLine2.IsNull() ||
1939       aLine1.ShapeType() != TopAbs_EDGE ||
1940       aLine2.ShapeType() != TopAbs_EDGE)
1941   {
1942     SetErrorCode("Two edges must be given");
1943     return anAngle;
1944   }
1945
1946   try {
1947 #if OCC_VERSION_LARGE > 0x06010000
1948     OCC_CATCH_SIGNALS;
1949 #endif
1950     TopoDS_Edge E1 = TopoDS::Edge(aLine1);
1951     TopoDS_Edge E2 = TopoDS::Edge(aLine2);
1952
1953     double fp,lp;
1954     Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
1955     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
1956
1957     if ( C1.IsNull() || C2.IsNull() ||
1958         !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
1959         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
1960     {
1961       SetErrorCode("The edges must be linear");
1962       return anAngle;
1963     }
1964
1965     Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
1966     Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
1967
1968     gp_Lin aLin1 = L1->Lin();
1969     gp_Lin aLin2 = L2->Lin();
1970
1971     anAngle = aLin1.Angle(aLin2);
1972     anAngle /= PI180; // convert radians into degrees
1973
1974     if (anAngle > 90.0) {
1975       anAngle = 180.0 - anAngle;
1976     }
1977
1978     SetErrorCode(OK);
1979   }
1980   catch (Standard_Failure)
1981   {
1982     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1983     SetErrorCode(aFail->GetMessageString());
1984   }
1985
1986   return anAngle;
1987 }
1988
1989 //=======================================================================
1990 /*!
1991  *  Compute angle (in degrees) between two vectors
1992  */
1993 //=======================================================================
1994 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
1995                                                                Handle(GEOM_Object) theVec2)
1996 {
1997   SetErrorCode(KO);
1998
1999   Standard_Real anAngle = -1.0;
2000
2001   if (theVec1.IsNull() || theVec2.IsNull())
2002     return anAngle;
2003
2004   Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2005   Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2006   if (aRefVec1.IsNull() || aRefVec2.IsNull())
2007     return anAngle;
2008
2009   TopoDS_Shape aVec1 = aRefVec1->GetValue();
2010   TopoDS_Shape aVec2 = aRefVec2->GetValue();
2011   if (aVec1.IsNull() || aVec2.IsNull() ||
2012       aVec1.ShapeType() != TopAbs_EDGE ||
2013       aVec2.ShapeType() != TopAbs_EDGE)
2014   {
2015     SetErrorCode("Two edges must be given");
2016     return anAngle;
2017   }
2018
2019   try {
2020 #if OCC_VERSION_LARGE > 0x06010000
2021     OCC_CATCH_SIGNALS;
2022 #endif
2023     TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2024     TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2025
2026     TopoDS_Vertex aP11, aP12, aP21, aP22;
2027     TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2028     TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2029     if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2030       SetErrorCode("Bad edge given");
2031       return anAngle;
2032     }
2033
2034     gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2035     gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2036
2037     anAngle = aV1.Angle(aV2);
2038     anAngle /= PI180; // convert radians into degrees
2039
2040     SetErrorCode(OK);
2041   }
2042   catch (Standard_Failure)
2043   {
2044     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2045     SetErrorCode(aFail->GetMessageString());
2046   }
2047
2048   return anAngle;
2049 }
2050
2051
2052 //=============================================================================
2053 /*!
2054  *  CurveCurvatureByParam
2055  */
2056 //=============================================================================
2057 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2058                         (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2059 {
2060   SetErrorCode(KO);
2061   Standard_Real aRes = -1.0;
2062
2063   if(theCurve.IsNull()) return aRes;
2064
2065   Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2066   if(aRefShape.IsNull()) return aRes;
2067
2068   TopoDS_Shape aShape = aRefShape->GetValue();
2069   if(aShape.IsNull()) {
2070     SetErrorCode("One of Objects has NULL Shape");
2071     return aRes;
2072   }
2073
2074   Standard_Real aFP, aLP, aP;
2075   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2076   aP = aFP + (aLP - aFP) * theParam;
2077
2078   if(aCurve.IsNull()) return aRes;
2079
2080   //Compute curvature
2081   try {
2082 #if OCC_VERSION_LARGE > 0x06010000
2083     OCC_CATCH_SIGNALS;
2084 #endif
2085     GeomLProp_CLProps Prop = GeomLProp_CLProps
2086       (aCurve, aP, 2, Precision::Confusion());
2087     aRes = fabs(Prop.Curvature());
2088     SetErrorCode(OK);
2089   }
2090   catch (Standard_Failure) {
2091     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2092     SetErrorCode(aFail->GetMessageString());
2093     return aRes;
2094   }
2095
2096   if( aRes > Precision::Confusion() )
2097     aRes = 1/aRes;
2098   else
2099     aRes = RealLast();
2100
2101   return aRes;
2102 }
2103
2104
2105 //=============================================================================
2106 /*!
2107  *  CurveCurvatureByPoint
2108  */
2109 //=============================================================================
2110 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2111                    (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2112 {
2113   SetErrorCode(KO);
2114   Standard_Real aRes = -1.0;
2115
2116   if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2117
2118   Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2119   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2120   if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2121
2122   TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2123   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2124   if( anEdge.IsNull() || aPnt.IsNull() ) {
2125     SetErrorCode("One of Objects has NULL Shape");
2126     return aRes;
2127   }
2128
2129   Standard_Real aFP, aLP;
2130   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2131   if(aCurve.IsNull()) return aRes;
2132   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2133
2134   //Compute curvature
2135   try {
2136 #if OCC_VERSION_LARGE > 0x06010000
2137     OCC_CATCH_SIGNALS;
2138 #endif
2139     GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2140     if(PPCurve.NbPoints()>0) {
2141       GeomLProp_CLProps Prop = GeomLProp_CLProps
2142         (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2143       aRes = fabs(Prop.Curvature());
2144       SetErrorCode(OK);
2145     }
2146   }
2147   catch (Standard_Failure) {
2148     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2149     SetErrorCode(aFail->GetMessageString());
2150     return aRes;
2151   }
2152
2153   if( aRes > Precision::Confusion() )
2154     aRes = 1/aRes;
2155   else
2156     aRes = RealLast();
2157
2158   return aRes;
2159 }
2160
2161
2162 //=============================================================================
2163 /*!
2164  *  getSurfaceCurvatures
2165  */
2166 //=============================================================================
2167 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2168                                           (const Handle(Geom_Surface)& aSurf,
2169                                            Standard_Real theUParam,
2170                                            Standard_Real theVParam,
2171                                            Standard_Boolean theNeedMaxCurv)
2172 {
2173   SetErrorCode(KO);
2174   Standard_Real aRes = 1.0;
2175
2176   if (aSurf.IsNull()) return aRes;
2177
2178   try {
2179 #if OCC_VERSION_LARGE > 0x06010000
2180     OCC_CATCH_SIGNALS;
2181 #endif
2182     GeomLProp_SLProps Prop = GeomLProp_SLProps
2183       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2184     if(Prop.IsCurvatureDefined()) {
2185       if(Prop.IsUmbilic()) {
2186         //cout<<"is umbilic"<<endl;
2187         aRes = fabs(Prop.MeanCurvature());
2188       }
2189       else {
2190         //cout<<"is not umbilic"<<endl;
2191         double c1 = fabs(Prop.MaxCurvature());
2192         double c2 = fabs(Prop.MinCurvature());
2193         if(theNeedMaxCurv)
2194           aRes = Max(c1,c2);
2195         else
2196           aRes = Min(c1,c2);
2197       }
2198       SetErrorCode(OK);
2199     }
2200   }
2201   catch (Standard_Failure) {
2202     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2203     SetErrorCode(aFail->GetMessageString());
2204     return aRes;
2205   }
2206
2207   if( fabs(aRes) > Precision::Confusion() )
2208     aRes = 1/aRes;
2209   else
2210     aRes = RealLast();
2211
2212   return aRes;
2213 }
2214
2215
2216 //=============================================================================
2217 /*!
2218  *  MaxSurfaceCurvatureByParam
2219  */
2220 //=============================================================================
2221 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2222                                                   (Handle(GEOM_Object) theSurf,
2223                                                    Standard_Real& theUParam,
2224                                                    Standard_Real& theVParam)
2225 {
2226   SetErrorCode(KO);
2227   Standard_Real aRes = -1.0;
2228
2229   if (theSurf.IsNull()) return aRes;
2230
2231   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2232   if(aRefShape.IsNull()) return aRes;
2233
2234   TopoDS_Shape aShape = aRefShape->GetValue();
2235   if(aShape.IsNull()) {
2236     SetErrorCode("One of Objects has NULL Shape");
2237     return aRes;
2238   }
2239
2240   TopoDS_Face F = TopoDS::Face(aShape);
2241   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2242
2243   //Compute the parameters
2244   Standard_Real U1,U2,V1,V2;
2245   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2246   Standard_Real U = U1 + (U2-U1)*theUParam;
2247   Standard_Real V = V1 + (V2-V1)*theVParam;
2248
2249   return getSurfaceCurvatures(aSurf, U, V, true);
2250 }
2251
2252
2253 //=============================================================================
2254 /*!
2255  *  MaxSurfaceCurvatureByPoint
2256  */
2257 //=============================================================================
2258 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2259                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2260 {
2261   SetErrorCode(KO);
2262   Standard_Real aRes = -1.0;
2263
2264   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2265
2266   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2267   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2268   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2269
2270   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2271   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2272   if( aFace.IsNull() || aPnt.IsNull() ) {
2273     SetErrorCode("One of Objects has NULL Shape");
2274     return 0;
2275   }
2276
2277   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2278   if(aSurf.IsNull()) return aRes;
2279   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2280
2281   //Compute the parameters
2282   ShapeAnalysis_Surface sas(aSurf);
2283   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2284
2285   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2286 }
2287
2288
2289 //=============================================================================
2290 /*!
2291  *  MinSurfaceCurvatureByParam
2292  */
2293 //=============================================================================
2294 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2295                                                   (Handle(GEOM_Object) theSurf,
2296                                                    Standard_Real& theUParam,
2297                                                    Standard_Real& theVParam)
2298 {
2299   SetErrorCode(KO);
2300   Standard_Real aRes = -1.0;
2301
2302   if (theSurf.IsNull()) return aRes;
2303
2304   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2305   if(aRefShape.IsNull()) return aRes;
2306
2307   TopoDS_Shape aShape = aRefShape->GetValue();
2308   if(aShape.IsNull()) {
2309     SetErrorCode("One of Objects has NULL Shape");
2310     return aRes;
2311   }
2312
2313   TopoDS_Face F = TopoDS::Face(aShape);
2314   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2315
2316   //Compute the parameters
2317   Standard_Real U1,U2,V1,V2;
2318   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2319   Standard_Real U = U1 + (U2-U1)*theUParam;
2320   Standard_Real V = V1 + (V2-V1)*theVParam;
2321
2322   return getSurfaceCurvatures(aSurf, U, V, false);
2323 }
2324
2325
2326 //=============================================================================
2327 /*!
2328  *  MinSurfaceCurvatureByPoint
2329  */
2330 //=============================================================================
2331 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2332                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2333 {
2334   SetErrorCode(KO);
2335   Standard_Real aRes = -1.0;
2336
2337   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2338
2339   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2340   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2341   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2342
2343   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2344   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2345   if( aFace.IsNull() || aPnt.IsNull() ) {
2346     SetErrorCode("One of Objects has NULL Shape");
2347     return 0;
2348   }
2349
2350   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2351   if(aSurf.IsNull()) return aRes;
2352   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2353
2354   //Compute the parameters
2355   ShapeAnalysis_Surface sas(aSurf);
2356   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2357
2358   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2359 }
2360
2361
2362 //=======================================================================
2363 //function : StructuralDump
2364 //purpose  : Structural (data exchange) style of output.
2365 //=======================================================================
2366 void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna,
2367                                                   const TopoDS_Shape&       theShape,
2368                                                   TCollection_AsciiString&  theDump)
2369 {
2370   Standard_Integer i;
2371   theDump.Clear();
2372   theDump += " -- The Shape has problems :\n";
2373   theDump += "  Check                                    Count\n";
2374   theDump += " ------------------------------------------------\n";
2375
2376   Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail;
2377   Handle(TColStd_HArray1OfInteger) NbProblems =
2378     new TColStd_HArray1OfInteger(1, last_stat);
2379   for (i = 1; i <= last_stat; i++)
2380     NbProblems->SetValue(i,0);
2381
2382   Handle(TopTools_HSequenceOfShape) sl;
2383   sl = new TopTools_HSequenceOfShape();
2384   TopTools_DataMapOfShapeListOfShape theMap;
2385   theMap.Clear();
2386   GetProblemShapes(theAna, theShape, sl, NbProblems, theMap);
2387   theMap.Clear();
2388
2389   Standard_Integer count = 0;
2390   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve);
2391   if (count > 0) {
2392     theDump += "  Invalid Point on Curve ................... ";
2393     theDump += TCollection_AsciiString(count) + "\n";
2394   }
2395   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface);
2396   if (count > 0) {
2397     theDump += "  Invalid Point on CurveOnSurface .......... ";
2398     theDump += TCollection_AsciiString(count) + "\n";
2399   }
2400   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface);
2401   if (count > 0) {
2402     theDump += "  Invalid Point on Surface ................. ";
2403     theDump += TCollection_AsciiString(count) + "\n";
2404   }
2405   count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve);
2406   if (count > 0) {
2407     theDump += "  No 3D Curve .............................. ";
2408     theDump += TCollection_AsciiString(count) + "\n";
2409   }
2410   count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve);
2411   if (count > 0) {
2412     theDump += "  Multiple 3D Curve ........................ ";
2413     theDump += TCollection_AsciiString(count) + "\n";
2414   }
2415   count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve);
2416   if (count > 0) {
2417     theDump += "  Invalid 3D Curve ......................... ";
2418     theDump += TCollection_AsciiString(count) + "\n";
2419   }
2420   count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface);
2421   if (count > 0) {
2422     theDump += "  No Curve on Surface ...................... ";
2423     theDump += TCollection_AsciiString(count) + "\n";
2424   }
2425   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface);
2426   if (count > 0) {
2427     theDump += "  Invalid Curve on Surface ................. ";
2428     theDump += TCollection_AsciiString(count) + "\n";
2429   }
2430   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface);
2431   if (count > 0) {
2432     theDump += "  Invalid Curve on closed Surface .......... ";
2433     theDump += TCollection_AsciiString(count) + "\n";
2434   }
2435   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag);
2436   if (count > 0) {
2437     theDump += "  Invalid SameRange Flag ................... ";
2438     theDump += TCollection_AsciiString(count) + "\n";
2439   }
2440   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag);
2441   if (count > 0) {
2442     theDump += "  Invalid SameParameter Flag ............... ";
2443     theDump += TCollection_AsciiString(count) + "\n";
2444   }
2445   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag);
2446   if (count > 0) {
2447     theDump += "  Invalid Degenerated Flag ................. ";
2448     theDump += TCollection_AsciiString(count) + "\n";
2449   }
2450   count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge);
2451   if (count > 0) {
2452     theDump += "  Free Edge ................................ ";
2453     theDump += TCollection_AsciiString(count) + "\n";
2454   }
2455   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity);
2456   if (count > 0) {
2457     theDump += "  Invalid MultiConnexity ................... ";
2458     theDump += TCollection_AsciiString(count) + "\n";
2459   }
2460   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange);
2461   if (count > 0) {
2462     theDump += "  Invalid Range ............................ ";
2463     theDump += TCollection_AsciiString(count) + "\n";
2464   }
2465   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire);
2466   if (count > 0) {
2467     theDump += "  Empty Wire ............................... ";
2468     theDump += TCollection_AsciiString(count) + "\n";
2469   }
2470   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge);
2471   if (count > 0) {
2472     theDump += "  Redundant Edge ........................... ";
2473     theDump += TCollection_AsciiString(count) + "\n";
2474   }
2475   count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire);
2476   if (count > 0) {
2477     theDump += "  Self Intersecting Wire ................... ";
2478     theDump += TCollection_AsciiString(count) + "\n";
2479   }
2480   count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface);
2481   if (count > 0) {
2482     theDump += "  No Surface ............................... ";
2483     theDump += TCollection_AsciiString(count) + "\n";
2484   }
2485   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire);
2486   if (count > 0) {
2487     theDump += "  Invalid Wire ............................. ";
2488     theDump += TCollection_AsciiString(count) + "\n";
2489   }
2490   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire);
2491   if (count > 0) {
2492     theDump += "  Redundant Wire ........................... ";
2493     theDump += TCollection_AsciiString(count) + "\n";
2494   }
2495   count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires);
2496   if (count > 0) {
2497     theDump += "  Intersecting Wires ....................... ";
2498     theDump += TCollection_AsciiString(count) + "\n";
2499   }
2500   count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires);
2501   if (count > 0) {
2502     theDump += "  Invalid Imbrication of Wires ............. ";
2503     theDump += TCollection_AsciiString(count) + "\n";
2504   }
2505   count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell);
2506   if (count > 0) {
2507     theDump += "  Empty Shell .............................. ";
2508     theDump += TCollection_AsciiString(count) + "\n";
2509   }
2510   count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace);
2511   if (count > 0) {
2512     theDump += "  Redundant Face ........................... ";
2513     theDump += TCollection_AsciiString(count) + "\n";
2514   }
2515   count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape);
2516   if (count > 0) {
2517     theDump += "  Unorientable Shape ....................... ";
2518     theDump += TCollection_AsciiString(count) + "\n";
2519   }
2520   count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed);
2521   if (count > 0) {
2522     theDump += "  Not Closed ............................... ";
2523     theDump += TCollection_AsciiString(count) + "\n";
2524   }
2525   count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected);
2526   if (count > 0) {
2527     theDump += "  Not Connected ............................ ";
2528     theDump += TCollection_AsciiString(count) + "\n";
2529   }
2530   count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape);
2531   if (count > 0) {
2532     theDump += "  Subshape not in Shape .................... ";
2533     theDump += TCollection_AsciiString(count) + "\n";
2534   }
2535   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation);
2536   if (count > 0) {
2537     theDump += "  Bad Orientation .......................... ";
2538     theDump += TCollection_AsciiString(count) + "\n";
2539   }
2540   count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape);
2541   if (count > 0) {
2542     theDump += "  Bad Orientation of Subshape .............. ";
2543     theDump += TCollection_AsciiString(count) + "\n";
2544   }
2545   count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail);
2546   if (count > 0) {
2547     theDump += "  checkshape failure ....................... ";
2548     theDump += TCollection_AsciiString(count) + "\n";
2549   }
2550
2551   theDump += " ------------------------------------------------\n";
2552   theDump += "*** Shapes with problems : ";
2553   theDump += TCollection_AsciiString(sl->Length()) + "\n";
2554
2555   Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
2556   nbv = nbe = nbw = nbf = nbs = nbo = 0;
2557
2558   for (i = 1; i <= sl->Length(); i++) {
2559     TopoDS_Shape shi = sl->Value(i);
2560     TopAbs_ShapeEnum sti = shi.ShapeType();
2561     switch (sti) {
2562       case TopAbs_VERTEX : nbv++; break;
2563       case TopAbs_EDGE   : nbe++; break;
2564       case TopAbs_WIRE   : nbw++; break;
2565       case TopAbs_FACE   : nbf++; break;
2566       case TopAbs_SHELL  : nbs++; break;
2567       case TopAbs_SOLID  : nbo++; break;
2568       default            : break;
2569     }
2570   }
2571
2572   if (nbv > 0) {
2573     theDump += "VERTEX : ";
2574     if (nbv < 10) theDump += " ";
2575     theDump += TCollection_AsciiString(nbv) + "\n";
2576   }
2577   if (nbe > 0) {
2578     theDump += "EDGE   : ";
2579     if (nbe < 10) theDump += " ";
2580     theDump += TCollection_AsciiString(nbe) + "\n";
2581   }
2582   if (nbw > 0) {
2583     theDump += "WIRE   : ";
2584     if (nbw < 10) theDump += " ";
2585     theDump += TCollection_AsciiString(nbw) + "\n";
2586   }
2587   if (nbf > 0) {
2588     theDump += "FACE   : ";
2589     if (nbf < 10) theDump += " ";
2590     theDump += TCollection_AsciiString(nbf) + "\n";
2591   }
2592   if (nbs > 0) {
2593     theDump += "SHELL  : ";
2594     if (nbs < 10) theDump += " ";
2595     theDump += TCollection_AsciiString(nbs) + "\n";
2596   }
2597   if (nbo > 0) {
2598     theDump += "SOLID  : ";
2599     if (nbo < 10) theDump += " ";
2600     theDump += TCollection_AsciiString(nbo) + "\n";
2601   }
2602 }
2603
2604
2605 //=======================================================================
2606 //function : GetProblemShapes
2607 // purpose : for StructuralDump
2608 //=======================================================================
2609 void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer&           theAna,
2610                                                     const TopoDS_Shape&                 theShape,
2611                                                     Handle(TopTools_HSequenceOfShape)&  sl,
2612                                                     Handle(TColStd_HArray1OfInteger)&   NbProblems,
2613                                                     TopTools_DataMapOfShapeListOfShape& theMap)
2614 {
2615   for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
2616     GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap);
2617   }
2618   TopAbs_ShapeEnum styp = theShape.ShapeType();
2619   BRepCheck_ListIteratorOfListOfStatus itl;
2620   TopTools_ListOfShape empty;
2621   if (!theMap.IsBound(theShape)) {
2622     theMap.Bind(theShape,empty);
2623
2624     if (!theAna.Result(theShape).IsNull()) {
2625       itl.Initialize(theAna.Result(theShape)->Status());
2626       // !!! May be, we have to print all the problems, not only the first one ?
2627       if (itl.Value() != BRepCheck_NoError) {
2628         sl->Append(theShape);
2629         BRepCheck_Status stat = itl.Value();
2630         NbProblems->SetValue((Standard_Integer)stat,
2631                              NbProblems->Value((Standard_Integer)stat) + 1);
2632       }
2633     }
2634   }
2635
2636   switch (styp) {
2637   case TopAbs_EDGE:
2638     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
2639     break;
2640   case TopAbs_FACE:
2641     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap);
2642     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap);
2643     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap);
2644     break;
2645   case TopAbs_SHELL:
2646     break;
2647   case TopAbs_SOLID:
2648     GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap);
2649     break;
2650   default:
2651     break;
2652   }
2653 }
2654
2655 //=======================================================================
2656 //function : Contains
2657 //=======================================================================
2658 static Standard_Boolean Contains (const TopTools_ListOfShape& L,
2659                                   const TopoDS_Shape& S)
2660 {
2661   TopTools_ListIteratorOfListOfShape it;
2662   for (it.Initialize(L); it.More(); it.Next()) {
2663     if (it.Value().IsSame(S)) {
2664       return Standard_True;
2665     }
2666   }
2667   return Standard_False;
2668 }
2669
2670 //=======================================================================
2671 //function : GetProblemSub
2672 // purpose : for StructuralDump
2673 //=======================================================================
2674 void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer&           theAna,
2675                                                  const TopoDS_Shape&                 theShape,
2676                                                  Handle(TopTools_HSequenceOfShape)&  sl,
2677                                                  Handle(TColStd_HArray1OfInteger)&   NbProblems,
2678                                                  const TopAbs_ShapeEnum              Subtype,
2679                                                  TopTools_DataMapOfShapeListOfShape& theMap)
2680 {
2681   BRepCheck_ListIteratorOfListOfStatus itl;
2682   TopExp_Explorer exp;
2683   for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) {
2684     const TopoDS_Shape& sub = exp.Current();
2685
2686     const Handle(BRepCheck_Result)& res = theAna.Result(sub);
2687     for (res->InitContextIterator();
2688          res->MoreShapeInContext();
2689          res->NextShapeInContext()) {
2690       if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) {
2691         theMap(sub).Append(theShape);
2692         itl.Initialize(res->StatusOnShape());
2693
2694         if (itl.Value() != BRepCheck_NoError) {
2695           Standard_Integer ii = 0;
2696
2697           for (ii = 1; ii <= sl->Length(); ii++)
2698             if (sl->Value(ii).IsSame(sub)) break;
2699
2700           if (ii > sl->Length()) {
2701             sl->Append(sub);
2702             BRepCheck_Status stat = itl.Value();
2703             NbProblems->SetValue((Standard_Integer)stat,
2704                                  NbProblems->Value((Standard_Integer)stat) + 1);
2705           }
2706           for (ii = 1; ii <= sl->Length(); ii++)
2707             if (sl->Value(ii).IsSame(theShape)) break;
2708           if (ii > sl->Length()) {
2709             sl->Append(theShape);
2710             BRepCheck_Status stat = itl.Value();
2711             NbProblems->SetValue((Standard_Integer)stat,
2712                                  NbProblems->Value((Standard_Integer)stat) + 1);
2713           }
2714         }
2715         break;
2716       }
2717     }
2718   }
2719 }