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