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