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