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