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