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