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