]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
Salome HOME
ebb5d83d3b0ff0d85eb2a95d40643d3d96841829
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 // Copyright (C) 2007-2016  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   // Interprete 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 {
855   SetErrorCode(KO);
856
857   if (theShape.IsNull()) return NULL;
858
859   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
860   if (aRefShape.IsNull()) return NULL;
861
862   //Add a new Vertex object
863   Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT);
864
865   //Add a function
866   Handle(GEOM_Function) aFunction =
867     aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
868   if (aFunction.IsNull()) return NULL;
869
870   //Check if the function is set correctly
871   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
872
873   GEOMImpl_IMeasure aCI (aFunction);
874   aCI.SetBase(aRefShape);
875   aCI.SetIndex(theIndex);
876
877   //Compute
878   try {
879     OCC_CATCH_SIGNALS;
880     if (!GetSolver()->ComputeFunction(aFunction)) {
881       SetErrorCode("Vertex by index driver failed.");
882       return NULL;
883     }
884   }
885   catch (Standard_Failure& aFail) {
886     SetErrorCode(aFail.GetMessageString());
887     return NULL;
888   }
889
890   //Make a Python command
891   GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" << theShape << ", " << theIndex << ")";
892
893   SetErrorCode(OK);
894   return aVertex;
895 }
896
897 //=============================================================================
898 /*!
899  *  GetNormal
900  */
901 //=============================================================================
902 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
903                                          (Handle(GEOM_Object) theFace,
904                                           Handle(GEOM_Object) theOptionalPoint)
905 {
906   SetErrorCode(KO);
907
908   if (theFace.IsNull()) return NULL;
909
910   //Add a new Normale object
911   Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR);
912
913   //Add a new Normale function
914   Handle(GEOM_Function) aFunction =
915     aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
916   if (aFunction.IsNull()) return NULL;
917
918   //Check if the function is set correctly
919   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
920
921   GEOMImpl_IMeasure aCI (aFunction);
922
923   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
924   if (aFace.IsNull()) return NULL;
925
926   aCI.SetBase(aFace);
927
928   if (!theOptionalPoint.IsNull()) {
929     Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
930     aCI.SetPoint(anOptPnt);
931   }
932
933   //Compute the Normale value
934   try {
935     OCC_CATCH_SIGNALS;
936     if (!GetSolver()->ComputeFunction(aFunction)) {
937       SetErrorCode("Measure driver failed to compute normake of face");
938       return NULL;
939     }
940   }
941   catch (Standard_Failure& aFail) {
942     SetErrorCode(aFail.GetMessageString());
943     return NULL;
944   }
945
946   //Make a Python command
947   GEOM::TPythonDump pd (aFunction);
948   pd << aNorm << " = geompy.GetNormal(" << theFace;
949   if (!theOptionalPoint.IsNull()) {
950     pd << ", " << theOptionalPoint;
951   }
952   pd << ")";
953
954   SetErrorCode(OK);
955   return aNorm;
956 }
957
958 //=============================================================================
959 /*!
960  *  GetBasicProperties
961  */
962 //=============================================================================
963 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
964                                                       const Standard_Real theTolerance,
965                                                       Standard_Real& theLength,
966                                                       Standard_Real& theSurfArea,
967                                                       Standard_Real& theVolume)
968 {
969   SetErrorCode(KO);
970
971   if (theShape.IsNull()) return;
972
973   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
974   if (aRefShape.IsNull()) return;
975
976   TopoDS_Shape aShape = aRefShape->GetValue();
977   if (aShape.IsNull()) {
978     SetErrorCode("The Objects has NULL Shape");
979     return;
980   }
981
982   //Compute the parameters
983   GProp_GProps LProps, SProps;
984   Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
985   try {
986     OCC_CATCH_SIGNALS;
987     BRepGProp::LinearProperties(aShape, LProps, Standard_True);
988     theLength = LProps.Mass();
989
990     BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
991     theSurfArea = SProps.Mass();
992
993     theVolume = 0.0;
994     if (aShape.ShapeType() < TopAbs_SHELL) {
995       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
996         GProp_GProps VProps;
997         BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
998         theVolume += VProps.Mass();
999       }
1000     }
1001   }
1002   catch (Standard_Failure& aFail) {
1003     SetErrorCode(aFail.GetMessageString());
1004     return;
1005   }
1006
1007   SetErrorCode(OK);
1008 }
1009
1010 //=============================================================================
1011 /*!
1012  *  GetInertia
1013  */
1014 //=============================================================================
1015 void GEOMImpl_IMeasureOperations::GetInertia
1016                    (Handle(GEOM_Object) theShape,
1017                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1018                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1019                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1020                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1021 {
1022   SetErrorCode(KO);
1023
1024   if (theShape.IsNull()) return;
1025
1026   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1027   if (aRefShape.IsNull()) return;
1028
1029   TopoDS_Shape aShape = aRefShape->GetValue();
1030   if (aShape.IsNull()) {
1031     SetErrorCode("The Objects has NULL Shape");
1032     return;
1033   }
1034
1035   //Compute the parameters
1036   GProp_GProps System;
1037
1038   try {
1039     OCC_CATCH_SIGNALS;
1040     if (aShape.ShapeType() == TopAbs_VERTEX ||
1041         aShape.ShapeType() == TopAbs_EDGE ||
1042         aShape.ShapeType() == TopAbs_WIRE) {
1043       BRepGProp::LinearProperties(aShape, System, Standard_True);
1044     } else if (aShape.ShapeType() == TopAbs_FACE ||
1045                aShape.ShapeType() == TopAbs_SHELL) {
1046       BRepGProp::SurfaceProperties(aShape, System, Standard_True);
1047     } else {
1048       BRepGProp::VolumeProperties(aShape, System, Standard_True);
1049     }
1050     gp_Mat I = System.MatrixOfInertia();
1051
1052     I11 = I(1,1);
1053     I12 = I(1,2);
1054     I13 = I(1,3);
1055
1056     I21 = I(2,1);
1057     I22 = I(2,2);
1058     I23 = I(2,3);
1059
1060     I31 = I(3,1);
1061     I32 = I(3,2);
1062     I33 = I(3,3);
1063
1064     GProp_PrincipalProps Pr = System.PrincipalProperties();
1065     Pr.Moments(Ix,Iy,Iz);
1066   }
1067   catch (Standard_Failure& aFail) {
1068     SetErrorCode(aFail.GetMessageString());
1069     return;
1070   }
1071
1072   SetErrorCode(OK);
1073 }
1074
1075 //=============================================================================
1076 /*!
1077  *  GetBoundingBox
1078  */
1079 //=============================================================================
1080 void GEOMImpl_IMeasureOperations::GetBoundingBox
1081                                      (Handle(GEOM_Object) theShape,
1082                                       const Standard_Boolean precise,
1083                                       Standard_Real& Xmin, Standard_Real& Xmax,
1084                                       Standard_Real& Ymin, Standard_Real& Ymax,
1085                                       Standard_Real& Zmin, Standard_Real& Zmax)
1086 {
1087   SetErrorCode(KO);
1088
1089   if (theShape.IsNull()) return;
1090
1091   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1092   if (aRefShape.IsNull()) return;
1093
1094   TopoDS_Shape aShape = aRefShape->GetValue();
1095   if (aShape.IsNull()) {
1096     SetErrorCode("The Objects has NULL Shape");
1097     return;
1098   }
1099
1100   //Compute the parameters
1101   Bnd_Box B;
1102
1103   try {
1104     OCC_CATCH_SIGNALS;
1105     BRepBuilderAPI_Copy aCopyTool (aShape);
1106     if (!aCopyTool.IsDone()) {
1107       SetErrorCode("GetBoundingBox Error: Bad shape detected");
1108       return;
1109     }
1110
1111     aShape = aCopyTool.Shape();
1112
1113     // remove triangulation to obtain more exact boundaries
1114     BRepTools::Clean(aShape);
1115
1116     BRepBndLib::Add(aShape, B);
1117
1118     if (precise) {
1119       if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
1120         SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
1121         return;
1122       }
1123     }
1124
1125     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1126   }
1127   catch (Standard_Failure& aFail) {
1128     SetErrorCode(aFail.GetMessageString());
1129     return;
1130   }
1131
1132   SetErrorCode(OK);
1133 }
1134
1135 //=============================================================================
1136 /*!
1137  *  GetBoundingBox
1138  */
1139 //=============================================================================
1140 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
1141                                                 (Handle(GEOM_Object) theShape,
1142                                                  const Standard_Boolean precise)
1143 {
1144   SetErrorCode(KO);
1145
1146   if (theShape.IsNull()) return NULL;
1147
1148   //Add a new BoundingBox object
1149   Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX);
1150
1151   //Add a new BoundingBox function
1152   const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
1153   Handle(GEOM_Function) aFunction =
1154     aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
1155   if (aFunction.IsNull()) return NULL;
1156
1157   //Check if the function is set correctly
1158   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1159
1160   GEOMImpl_IMeasure aCI (aFunction);
1161
1162   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1163   if (aRefShape.IsNull()) return NULL;
1164
1165   aCI.SetBase(aRefShape);
1166
1167   //Compute the BoundingBox value
1168   try {
1169     OCC_CATCH_SIGNALS;
1170     if (!GetSolver()->ComputeFunction(aFunction)) {
1171       SetErrorCode("Measure driver failed to compute a bounding box");
1172       return NULL;
1173     }
1174   }
1175   catch (Standard_Failure& aFail) {
1176     SetErrorCode(aFail.GetMessageString());
1177     return NULL;
1178   }
1179
1180   //Make a Python command
1181   GEOM::TPythonDump aPd(aFunction);
1182   
1183   aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
1184
1185   if (precise) {
1186     aPd << ", True";
1187   }
1188
1189   aPd << ")";
1190
1191   SetErrorCode(OK);
1192   return aBnd;
1193 }
1194
1195 //=============================================================================
1196 /*!
1197  *  GetTolerance
1198  */
1199 //=============================================================================
1200 void GEOMImpl_IMeasureOperations::GetTolerance
1201                                (Handle(GEOM_Object) theShape,
1202                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1203                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1204                                 Standard_Real& VertMin, Standard_Real& VertMax)
1205 {
1206   SetErrorCode(KO);
1207
1208   if (theShape.IsNull()) return;
1209
1210   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1211   if (aRefShape.IsNull()) return;
1212
1213   TopoDS_Shape aShape = aRefShape->GetValue();
1214   if (aShape.IsNull()) {
1215     SetErrorCode("The Objects has NULL Shape");
1216     return;
1217   }
1218
1219   //Compute the parameters
1220   Standard_Real T;
1221   FaceMin = EdgeMin = VertMin = RealLast();
1222   FaceMax = EdgeMax = VertMax = -RealLast();
1223
1224   try {
1225     OCC_CATCH_SIGNALS;
1226     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1227       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1228       T = BRep_Tool::Tolerance(Face);
1229       if (T > FaceMax)
1230         FaceMax = T;
1231       if (T < FaceMin)
1232         FaceMin = T;
1233     }
1234     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1235       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1236       T = BRep_Tool::Tolerance(Edge);
1237       if (T > EdgeMax)
1238         EdgeMax = T;
1239       if (T < EdgeMin)
1240         EdgeMin = T;
1241     }
1242     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1243       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1244       T = BRep_Tool::Tolerance(Vertex);
1245       if (T > VertMax)
1246         VertMax = T;
1247       if (T < VertMin)
1248         VertMin = T;
1249     }
1250   }
1251   catch (Standard_Failure& aFail) {
1252     SetErrorCode(aFail.GetMessageString());
1253     return;
1254   }
1255
1256   SetErrorCode(OK);
1257 }
1258
1259 //=============================================================================
1260 /*!
1261  *  CheckShape
1262  */
1263 //=============================================================================
1264 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)     theShape,
1265                                               const Standard_Boolean  theIsCheckGeom,
1266                                               std::list<ShapeError>  &theErrors)
1267 {
1268   SetErrorCode(KO);
1269   theErrors.clear();
1270
1271   if (theShape.IsNull()) return false;
1272
1273   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1274   if (aRefShape.IsNull()) return false;
1275
1276   TopoDS_Shape aShape = aRefShape->GetValue();
1277   if (aShape.IsNull()) {
1278     SetErrorCode("The Objects has NULL Shape");
1279     return false;
1280   }
1281
1282   //Compute the parameters
1283   bool isValid = false;
1284   try {
1285     OCC_CATCH_SIGNALS;
1286     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1287     if (ana.IsValid()) {
1288       isValid = true;
1289     } else {
1290       FillErrors(ana, aShape, theErrors);
1291     }
1292   }
1293   catch (Standard_Failure& aFail) {
1294     SetErrorCode(aFail.GetMessageString());
1295     return false;
1296   }
1297
1298   SetErrorCode(OK);
1299   return isValid;
1300 }
1301
1302 //=============================================================================
1303 /*!
1304  *  PrintShapeErrors
1305  */
1306 //=============================================================================
1307 TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
1308                                  (Handle(GEOM_Object)          theShape,
1309                                   const std::list<ShapeError> &theErrors)
1310 {
1311   TCollection_AsciiString aDump;
1312
1313   if (theShape.IsNull()) {
1314     return aDump;
1315   }
1316
1317   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1318
1319   if (aRefShape.IsNull()) {
1320     return aDump;
1321   }
1322
1323   TopoDS_Shape aShape = aRefShape->GetValue();
1324
1325   if (aShape.IsNull()) {
1326     SetErrorCode("The Objects has NULL Shape");
1327     return aDump;
1328   }
1329
1330   if (!theErrors.empty()) {
1331     // The shape is not valid. Prepare errors for dump.
1332     TopTools_IndexedMapOfShape anIndices;
1333     std::list<ShapeError>::const_iterator anIter = theErrors.begin();
1334     Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1335     nbv = nbe = nbw = nbf = nbs = nbo = 0;
1336
1337     // Map sub-shapes and their indices
1338     TopExp::MapShapes(aShape, anIndices);
1339
1340     const Standard_Integer aNbSubShapes = anIndices.Extent();
1341     TColStd_MapOfInteger   aMapPbInd;
1342
1343     aDump += " -- The Shape has problems :\n";
1344     aDump += "  Check                                    Count\n";
1345     aDump += " ------------------------------------------------\n";
1346
1347     for (; anIter != theErrors.end(); anIter++) {
1348       Standard_Integer aNbShapes = anIter->incriminated.size();
1349
1350       switch(anIter->error) {
1351       case BRepCheck_InvalidPointOnCurve:
1352         aDump += "  Invalid Point on Curve ................... ";
1353         break;
1354       case BRepCheck_InvalidPointOnCurveOnSurface:
1355         aDump += "  Invalid Point on CurveOnSurface .......... ";
1356         break;
1357       case BRepCheck_InvalidPointOnSurface:
1358         aDump += "  Invalid Point on Surface ................. ";
1359         break;
1360       case BRepCheck_No3DCurve:
1361         aDump += "  No 3D Curve .............................. ";
1362         break;
1363       case BRepCheck_Multiple3DCurve:
1364         aDump += "  Multiple 3D Curve ........................ ";
1365         break;
1366       case BRepCheck_Invalid3DCurve:
1367         aDump += "  Invalid 3D Curve ......................... ";
1368         break;
1369       case BRepCheck_NoCurveOnSurface:
1370         aDump += "  No Curve on Surface ...................... ";
1371         break;
1372       case BRepCheck_InvalidCurveOnSurface:
1373         aDump += "  Invalid Curve on Surface ................. ";
1374         break;
1375       case BRepCheck_InvalidCurveOnClosedSurface:
1376         aDump += "  Invalid Curve on closed Surface .......... ";
1377         break;
1378       case BRepCheck_InvalidSameRangeFlag:
1379         aDump += "  Invalid SameRange Flag ................... ";
1380         break;
1381       case BRepCheck_InvalidSameParameterFlag:
1382         aDump += "  Invalid SameParameter Flag ............... ";
1383         break;
1384       case BRepCheck_InvalidDegeneratedFlag:
1385         aDump += "  Invalid Degenerated Flag ................. ";
1386         break;
1387       case BRepCheck_FreeEdge:
1388         aDump += "  Free Edge ................................ ";
1389         break;
1390       case BRepCheck_InvalidMultiConnexity:
1391         aDump += "  Invalid MultiConnexity ................... ";
1392         break;
1393       case BRepCheck_InvalidRange:
1394         aDump += "  Invalid Range ............................ ";
1395         break;
1396       case BRepCheck_EmptyWire:
1397         aDump += "  Empty Wire ............................... ";
1398         break;
1399       case BRepCheck_RedundantEdge:
1400         aDump += "  Redundant Edge ........................... ";
1401         break;
1402       case BRepCheck_SelfIntersectingWire:
1403         aDump += "  Self Intersecting Wire ................... ";
1404         break;
1405       case BRepCheck_NoSurface:
1406         aDump += "  No Surface ............................... ";
1407         break;
1408       case BRepCheck_InvalidWire:
1409         aDump += "  Invalid Wire ............................. ";
1410         break;
1411       case BRepCheck_RedundantWire:
1412         aDump += "  Redundant Wire ........................... ";
1413         break;
1414       case BRepCheck_IntersectingWires:
1415         aDump += "  Intersecting Wires ....................... ";
1416         break;
1417       case BRepCheck_InvalidImbricationOfWires:
1418         aDump += "  Invalid Imbrication of Wires ............. ";
1419         break;
1420       case BRepCheck_EmptyShell:
1421         aDump += "  Empty Shell .............................. ";
1422         break;
1423       case BRepCheck_RedundantFace:
1424         aDump += "  Redundant Face ........................... ";
1425         break;
1426       case BRepCheck_UnorientableShape:
1427         aDump += "  Unorientable Shape ....................... ";
1428         break;
1429       case BRepCheck_NotClosed:
1430         aDump += "  Not Closed ............................... ";
1431         break;
1432       case BRepCheck_NotConnected:
1433         aDump += "  Not Connected ............................ ";
1434         break;
1435       case BRepCheck_SubshapeNotInShape:
1436         aDump += "  Sub-shape not in Shape ................... ";
1437         break;
1438       case BRepCheck_BadOrientation:
1439         aDump += "  Bad Orientation .......................... ";
1440         break;
1441       case BRepCheck_BadOrientationOfSubshape:
1442         aDump += "  Bad Orientation of Sub-shape ............. ";
1443         break;
1444       case BRepCheck_InvalidToleranceValue:
1445         aDump += "  Invalid Tolerance Value .................. ";
1446         break;
1447       case BRepCheck_CheckFail:
1448         aDump += "  Check Shape Failure ...................... ";
1449         break;
1450       default:
1451         break;
1452       }
1453
1454       aDump += TCollection_AsciiString(aNbShapes) + "\n";
1455
1456       // Count types of shape.
1457       std::list<int>::const_iterator aShIter = anIter->incriminated.begin();
1458
1459       for (; aShIter != anIter->incriminated.end(); aShIter++) {
1460         const Standard_Integer anIndex = *aShIter;
1461
1462         if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) {
1463           const TopoDS_Shape     &aSubShape = anIndices.FindKey(anIndex);
1464           const TopAbs_ShapeEnum  aType     = aSubShape.ShapeType();
1465
1466           switch (aType) {
1467             case TopAbs_VERTEX : nbv++; break;
1468             case TopAbs_EDGE   : nbe++; break;
1469             case TopAbs_WIRE   : nbw++; break;
1470             case TopAbs_FACE   : nbf++; break;
1471             case TopAbs_SHELL  : nbs++; break;
1472             case TopAbs_SOLID  : nbo++; break;
1473             default            : break;
1474           }
1475         }
1476       }
1477     }
1478
1479     const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo;
1480     aDump += " ------------------------------------------------\n";
1481     aDump += "*** Shapes with problems : ";
1482     aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n";
1483
1484     if (nbv > 0) {
1485       aDump += "VERTEX : ";
1486       if (nbv < 10) aDump += " ";
1487       aDump += TCollection_AsciiString(nbv) + "\n";
1488     }
1489     if (nbe > 0) {
1490       aDump += "EDGE   : ";
1491       if (nbe < 10) aDump += " ";
1492       aDump += TCollection_AsciiString(nbe) + "\n";
1493     }
1494     if (nbw > 0) {
1495       aDump += "WIRE   : ";
1496       if (nbw < 10) aDump += " ";
1497       aDump += TCollection_AsciiString(nbw) + "\n";
1498     }
1499     if (nbf > 0) {
1500       aDump += "FACE   : ";
1501       if (nbf < 10) aDump += " ";
1502       aDump += TCollection_AsciiString(nbf) + "\n";
1503     }
1504     if (nbs > 0) {
1505       aDump += "SHELL  : ";
1506       if (nbs < 10) aDump += " ";
1507       aDump += TCollection_AsciiString(nbs) + "\n";
1508     }
1509     if (nbo > 0) {
1510       aDump += "SOLID  : ";
1511       if (nbo < 10) aDump += " ";
1512       aDump += TCollection_AsciiString(nbo) + "\n";
1513     }
1514   }
1515
1516   return aDump;
1517 }
1518
1519 //=============================================================================
1520 /*!
1521  *  CheckSelfIntersections
1522  */
1523 //=============================================================================
1524 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
1525                          (Handle(GEOM_Object)                 theShape,
1526                           const SICheckLevel                  theCheckLevel,
1527                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1528 {
1529   SetErrorCode(KO);
1530
1531   if (theIntersections.IsNull())
1532     theIntersections = new TColStd_HSequenceOfInteger;
1533   else
1534     theIntersections->Clear();
1535
1536   if (theShape.IsNull())
1537     return false;
1538
1539   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1540   if (aRefShape.IsNull()) return false;
1541
1542   TopoDS_Shape aShape = aRefShape->GetValue();
1543   if (aShape.IsNull()) return false;
1544
1545   // 0. Prepare data
1546   TopoDS_Shape aScopy;
1547   //
1548   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1549   //
1550   // Map sub-shapes and their indices
1551   TopTools_IndexedMapOfShape anIndices;
1552   TopExp::MapShapes(aScopy, anIndices);
1553
1554   TopTools_ListOfShape aLCS;
1555   aLCS.Append(aScopy);
1556   //
1557   BOPAlgo_CheckerSI aCSI; // checker of self-interferences
1558   aCSI.SetArguments(aLCS);
1559   aCSI.SetLevelOfCheck(theCheckLevel);
1560
1561   // 1. Launch the checker
1562   aCSI.Perform();
1563   Standard_Boolean iErr = aCSI.HasErrors();
1564
1565   //
1566   Standard_Integer aNbS, n1, n2;
1567   BOPDS_MapIteratorOfMapOfPair aItMPK;
1568   //
1569   // 2. Take the shapes from DS
1570   const BOPDS_DS& aDS = aCSI.DS();
1571   aNbS=aDS.NbShapes();
1572   //
1573   // 3. Get the pairs of interfered shapes
1574   const BOPDS_MapOfPair& aMPK=aDS.Interferences();
1575   aItMPK.Initialize(aMPK);
1576   for (; aItMPK.More(); aItMPK.Next()) {
1577     const BOPDS_Pair& aPK=aItMPK.Value();
1578     aPK.Indices(n1, n2);
1579     //
1580     if (n1 > aNbS || n2 > aNbS){
1581       return false; // Error
1582     }
1583     const TopoDS_Shape& aS1 = aDS.Shape(n1);
1584     const TopoDS_Shape& aS2 = aDS.Shape(n2);
1585
1586     theIntersections->Append(anIndices.FindIndex(aS1));
1587     theIntersections->Append(anIndices.FindIndex(aS2));
1588   }
1589
1590   if (!iErr) {
1591     SetErrorCode(OK);
1592   }
1593
1594   return theIntersections->IsEmpty();
1595 }
1596
1597 //=============================================================================
1598 /*!
1599  *  CheckSelfIntersectionsFast
1600  */
1601 //=============================================================================
1602 bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
1603                          (Handle(GEOM_Object) theShape,
1604                           float theDeflection, double theTolerance,
1605                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1606 {
1607   SetErrorCode(KO);
1608
1609   if (theIntersections.IsNull())
1610     theIntersections = new TColStd_HSequenceOfInteger;
1611   else
1612     theIntersections->Clear();
1613
1614   if (theShape.IsNull())
1615     return false;
1616
1617   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1618   if (aRefShape.IsNull()) return false;
1619
1620   TopoDS_Shape aShape = aRefShape->GetValue();
1621   if (aShape.IsNull()) return false;
1622
1623   // Prepare data
1624   TopoDS_Shape aScopy;
1625
1626   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1627   GEOMUtils::MeshShape(aScopy, theDeflection);
1628
1629   // Map sub-shapes and their indices
1630   TopTools_IndexedMapOfShape anIndices;
1631   TopExp::MapShapes(aScopy, anIndices);
1632
1633   // Checker of fast interferences
1634   BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
1635
1636   // Launch the checker
1637   aTool.Perform();
1638   
1639   const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
1640   
1641   std::set<Standard_Integer> processed;
1642   
1643   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
1644     Standard_Integer idxLeft = it.Key();
1645     if (processed.count(idxLeft) > 0) continue; // already added
1646     processed.insert(idxLeft);
1647     const TColStd_PackedMapOfInteger& overlaps = it.Value();
1648     for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
1649       Standard_Integer idxRight = subit.Key();
1650       if (processed.count(idxRight) > 0) continue; // already added
1651       const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
1652       const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
1653       theIntersections->Append(anIndices.FindIndex(aS1));
1654       theIntersections->Append(anIndices.FindIndex(aS2));
1655     }
1656   }
1657
1658   if (aTool.IsDone())
1659     SetErrorCode(OK);
1660
1661   return theIntersections->IsEmpty();
1662 }
1663
1664 //=============================================================================
1665 /*!
1666  *  CheckBOPArguments
1667  */
1668 //=============================================================================
1669 bool GEOMImpl_IMeasureOperations::CheckBOPArguments
1670                                       (const Handle(GEOM_Object) &theShape)
1671 {
1672   SetErrorCode(KO);
1673
1674   if (theShape.IsNull()) {
1675     return false;
1676   }
1677
1678   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1679
1680   if (aRefShape.IsNull()) {
1681     return false;
1682   }
1683
1684   TopoDS_Shape aShape = aRefShape->GetValue();
1685
1686   if (aShape.IsNull()) {
1687     return false;
1688   }
1689
1690   //Compute the parameters
1691   bool isValid = GEOMUtils::CheckBOPArguments(aShape);
1692
1693   SetErrorCode(OK);
1694
1695   return isValid;
1696 }
1697
1698 //=============================================================================
1699 /*!
1700  *  FastIntersect
1701  */
1702 //=============================================================================
1703 bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1704                                                  double theTolerance, float theDeflection,
1705                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections1,
1706                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections2)
1707 {
1708   SetErrorCode(KO);
1709   bool isGood = false;
1710
1711   if (theIntersections1.IsNull())
1712     theIntersections1 = new TColStd_HSequenceOfInteger;
1713   else
1714     theIntersections1->Clear();
1715
1716   if (theIntersections2.IsNull())
1717     theIntersections2 = new TColStd_HSequenceOfInteger;
1718   else
1719     theIntersections2->Clear();
1720
1721   if (theShape1.IsNull() || theShape2.IsNull()) {
1722     SetErrorCode("Objects have NULL Shape");
1723     return isGood;
1724   }
1725
1726   if (theShape1 == theShape2) {
1727     SetErrorCode("Objects are equal");
1728     return isGood;
1729   }
1730   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1731   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1732   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
1733
1734   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1735   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1736   if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
1737
1738   // 0. Prepare data
1739   TopoDS_Shape aScopy1, aScopy2;
1740   GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
1741   GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
1742
1743   GEOMUtils::MeshShape(aScopy1, theDeflection);
1744   GEOMUtils::MeshShape(aScopy2, theDeflection);
1745   //
1746   // Map sub-shapes and their indices
1747   TopTools_IndexedMapOfShape anIndices1, anIndices2;
1748   TopExp::MapShapes(aScopy1, anIndices1);
1749   TopExp::MapShapes(aScopy2, anIndices2);
1750
1751   TopTools_ListOfShape aLCS1, aLCS2;
1752   aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
1753   //
1754   BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
1755   aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
1756   aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
1757
1758   // 1. Launch the checker
1759   aBSP.Perform();
1760  
1761   // 2. Get sets of IDs of overlapped faces
1762   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
1763   {
1764     const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
1765     theIntersections1->Append(anIndices1.FindIndex(aS1));
1766   }
1767   
1768   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
1769   {
1770     const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
1771     theIntersections2->Append(anIndices2.FindIndex(aS2));
1772   }
1773
1774   isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
1775
1776   if (aBSP.IsDone())
1777     SetErrorCode(OK);
1778
1779   return isGood;
1780 }
1781
1782 //=============================================================================
1783 /*!
1784  *  IsGoodForSolid
1785  */
1786 //=============================================================================
1787 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1788 {
1789   SetErrorCode(KO);
1790
1791   TCollection_AsciiString aRes = "";
1792
1793   if (theShape.IsNull()) {
1794     aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1795   }
1796   else {
1797     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1798     if (aRefShape.IsNull()) {
1799       aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1800     }
1801     else {
1802       TopoDS_Shape aShape = aRefShape->GetValue();
1803       if (aShape.IsNull()) {
1804         aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1805       }
1806       else {
1807         if (aShape.ShapeType() == TopAbs_COMPOUND) {
1808           TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1809           if (It.More()) aShape = It.Value();
1810         }
1811         if (aShape.ShapeType() == TopAbs_SHELL) {
1812           BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
1813           if (chkShell.Closed() == BRepCheck_NotClosed) {
1814             aRes = "WRN_SHAPE_UNCLOSED";
1815           }
1816         }
1817         else {
1818           aRes = "WRN_SHAPE_NOT_SHELL";
1819         }
1820       }
1821     }
1822   }
1823
1824   if (aRes.IsEmpty())
1825     SetErrorCode(OK);
1826
1827   return aRes;
1828 }
1829
1830 //=============================================================================
1831 /*!
1832  *  WhatIs
1833  */
1834 //=============================================================================
1835 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1836 {
1837   SetErrorCode(KO);
1838
1839   TCollection_AsciiString Astr;
1840
1841   if (theShape.IsNull()) return Astr;
1842
1843   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1844   if (aRefShape.IsNull()) return Astr;
1845
1846   TopoDS_Shape aShape = aRefShape->GetValue();
1847   if (aShape.IsNull()) {
1848     SetErrorCode("The Objects has NULL Shape");
1849     return Astr;
1850   }
1851
1852   //Compute the parameters
1853   if (aShape.ShapeType() == TopAbs_EDGE) {
1854     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1855       Astr = Astr + " It is a degenerated edge \n";
1856     }
1857   }
1858
1859   Astr = Astr + " Number of sub-shapes : \n";
1860
1861   try {
1862     OCC_CATCH_SIGNALS;
1863     int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
1864     for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
1865       nbTypes[iType] = 0;
1866       nbFlatType[iType] = 0;
1867     }
1868     nbTypes[aShape.ShapeType()]++;
1869
1870     TopTools_MapOfShape aMapOfShape;
1871     aMapOfShape.Add(aShape);
1872     TopTools_ListOfShape aListOfShape;
1873     aListOfShape.Append(aShape);
1874
1875     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1876     for (; itL.More(); itL.Next()) {
1877       TopoDS_Shape sp = itL.Value();
1878       TopoDS_Iterator it (sp);
1879       for (; it.More(); it.Next()) {
1880         TopoDS_Shape s = it.Value();
1881         if (aMapOfShape.Add(s)) {
1882           aListOfShape.Append(s);
1883           nbTypes[s.ShapeType()]++;
1884           if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
1885             nbFlatType[s.ShapeType()]++;
1886           }
1887         }
1888       }
1889     }
1890
1891     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1892     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1893     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1894     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1895     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1896     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1897     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1898     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1899     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
1900
1901     if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
1902       Astr = Astr + " --------------------- \n Flat content : \n";
1903       if (nbFlatType[TopAbs_VERTEX] > 0)
1904         Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
1905       if (nbFlatType[TopAbs_EDGE] > 0)
1906         Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
1907       if (nbFlatType[TopAbs_WIRE] > 0)
1908         Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
1909       if (nbFlatType[TopAbs_FACE] > 0)
1910         Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
1911       if (nbFlatType[TopAbs_SHELL] > 0)
1912         Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
1913       if (nbFlatType[TopAbs_SOLID] > 0)
1914         Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
1915     }
1916   }
1917   catch (Standard_Failure& aFail) {
1918     SetErrorCode(aFail.GetMessageString());
1919     return Astr;
1920   }
1921
1922   SetErrorCode(OK);
1923   return Astr;
1924 }
1925
1926 //=============================================================================
1927 /*!
1928  *  AreCoordsInside
1929  */
1930 //=============================================================================
1931 std::vector<bool>
1932 GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object)        theShape,
1933                                              const std::vector<double>& coords,
1934                                              double                     tolerance)
1935 {
1936   std::vector<bool> isInsideRes;
1937   if (!theShape.IsNull()) {
1938     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1939     if (!aRefShape.IsNull()) {
1940       TopoDS_Shape aShape = aRefShape->GetValue();
1941       if (!aShape.IsNull())
1942       {
1943         TopTools_IndexedMapOfShape mapShape;
1944         {
1945           TopExp_Explorer anExp;
1946           for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1947             mapShape.Add( anExp.Current() );
1948           for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1949             mapShape.Add( anExp.Current() );
1950           for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() )
1951             mapShape.Add( anExp.Current() );
1952           for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() )
1953             mapShape.Add( anExp.Current() ); //// ?????????
1954         }
1955         size_t nb_points = coords.size()/3, nb_points_inside = 0;
1956         isInsideRes.resize( nb_points, false );
1957
1958         for ( int iS = 1; iS <= mapShape.Extent(); ++iS )
1959         {
1960           if ( nb_points_inside == nb_points )
1961             break;
1962           aShape = mapShape( iS );
1963           switch ( aShape.ShapeType() ) {
1964           case TopAbs_SOLID:
1965           {
1966             BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape ));
1967             for ( size_t i = 0; i < nb_points; i++)
1968             {
1969               if ( isInsideRes[ i ]) continue;
1970               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
1971               SC.Perform( aPnt, tolerance );
1972               isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ));
1973               nb_points_inside += isInsideRes[ i ];
1974             }
1975             break;
1976           }
1977           case TopAbs_FACE:
1978           {
1979             Standard_Real u1,u2,v1,v2;
1980             const TopoDS_Face&   face = TopoDS::Face( aShape );
1981             Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
1982             surf->Bounds( u1,u2,v1,v2 );
1983             GeomAPI_ProjectPointOnSurf project;
1984             project.Init(surf, u1,u2, v1,v2, tolerance );
1985             for ( size_t i = 0; i < nb_points; i++)
1986             {
1987               if ( isInsideRes[ i ]) continue;
1988               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
1989               project.Perform( aPnt );
1990               if ( project.IsDone() &&
1991                    project.NbPoints() > 0 &&
1992                    project.LowerDistance() <= tolerance )
1993               {
1994                 Standard_Real u, v;
1995                 project.LowerDistanceParameters(u, v);
1996                 gp_Pnt2d uv( u, v );
1997                 BRepClass_FaceClassifier FC ( face, uv, tolerance );
1998                 isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON ));
1999                 nb_points_inside += isInsideRes[ i ];
2000               }
2001             }
2002             break;
2003           }
2004           case TopAbs_EDGE:
2005           {
2006             Standard_Real f,l;
2007             const TopoDS_Edge&  edge = TopoDS::Edge( aShape );
2008             Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
2009             GeomAPI_ProjectPointOnCurve project;
2010             project.Init( curve, f, l );
2011             for ( size_t i = 0; i < nb_points; i++)
2012             {
2013               if ( isInsideRes[ i ]) continue;
2014               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2015               project.Perform( aPnt );
2016               isInsideRes[ i ] = ( project.NbPoints() > 0 &&
2017                                    project.LowerDistance() <= tolerance );
2018               nb_points_inside += isInsideRes[ i ];
2019             }
2020             break;
2021           }
2022           case TopAbs_VERTEX:
2023           {
2024             gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ));
2025             for ( size_t i = 0; i < nb_points; i++)
2026             {
2027               if ( isInsideRes[ i ]) continue;
2028               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2029               isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance );
2030               nb_points_inside += isInsideRes[ i ];
2031             }
2032             break;
2033           }
2034           default:;
2035           } // switch ( aShape.ShapeType() )
2036         }
2037       }
2038     }
2039   }
2040   return isInsideRes;
2041 }
2042
2043 //=============================================================================
2044 /*!
2045  *  GetMinDistance
2046  */
2047 //=============================================================================
2048 Standard_Real
2049 GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
2050                                              Handle(GEOM_Object) theShape2,
2051                                              Standard_Real& X1,
2052                                              Standard_Real& Y1,
2053                                              Standard_Real& Z1,
2054                                              Standard_Real& X2,
2055                                              Standard_Real& Y2,
2056                                              Standard_Real& Z2)
2057 {
2058   SetErrorCode(KO);
2059   Standard_Real MinDist = 1.e9;
2060
2061   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
2062
2063   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2064   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2065   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
2066
2067   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2068   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2069   if (aShape1.IsNull() || aShape2.IsNull()) {
2070     SetErrorCode("One of Objects has NULL Shape");
2071     return MinDist;
2072   }
2073
2074   //Compute the parameters
2075   try {
2076     OCC_CATCH_SIGNALS;
2077
2078     gp_Pnt aPnt1, aPnt2;
2079
2080     MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
2081
2082     if (MinDist >= 0.0) {
2083       aPnt1.Coord(X1, Y1, Z1);
2084       aPnt2.Coord(X2, Y2, Z2);
2085     } else {
2086       return MinDist;
2087     }
2088   }
2089   catch (Standard_Failure& aFail) {
2090     SetErrorCode(aFail.GetMessageString());
2091     return MinDist;
2092   }
2093
2094   SetErrorCode(OK);
2095   return MinDist;
2096 }
2097
2098 //=======================================================================
2099 /*!
2100  *  Get coordinates of closest points of two shapes
2101  */
2102 //=======================================================================
2103 Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1,
2104                                                              Handle(GEOM_Object) theShape2,
2105                                                              Handle(TColStd_HSequenceOfReal)& theDoubles)
2106 {
2107   SetErrorCode(KO);
2108   Standard_Integer nbSolutions = 0;
2109
2110   if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions;
2111
2112   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2113   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2114   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions;
2115
2116   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2117   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2118   if (aShape1.IsNull() || aShape2.IsNull()) {
2119     SetErrorCode("One of Objects has NULL Shape");
2120     return nbSolutions;
2121   }
2122
2123   // Compute the extremities
2124   try {
2125     OCC_CATCH_SIGNALS;
2126
2127     // skl 30.06.2008
2128     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
2129     gp_Pnt P1, P2;
2130     double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1, P2);
2131     if (dist > -1.0) {
2132       nbSolutions = 1;
2133
2134       theDoubles->Append(P1.X());
2135       theDoubles->Append(P1.Y());
2136       theDoubles->Append(P1.Z());
2137       theDoubles->Append(P2.X());
2138       theDoubles->Append(P2.Y());
2139       theDoubles->Append(P2.Z());
2140
2141       SetErrorCode(OK);
2142       return nbSolutions;
2143     }
2144
2145     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
2146     if (dst.IsDone()) {
2147       nbSolutions = dst.NbSolution();
2148       if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2149
2150       gp_Pnt P1, P2;
2151       for (int i = 1; i <= nbSolutions; i++) {
2152         P1 = dst.PointOnShape1(i);
2153         P2 = dst.PointOnShape2(i);
2154
2155         theDoubles->Append(P1.X());
2156         theDoubles->Append(P1.Y());
2157         theDoubles->Append(P1.Z());
2158         theDoubles->Append(P2.X());
2159         theDoubles->Append(P2.Y());
2160         theDoubles->Append(P2.Z());
2161       }
2162     }
2163   }
2164   catch (Standard_Failure& aFail) {
2165     SetErrorCode(aFail.GetMessageString());
2166     return nbSolutions;
2167   }
2168
2169   SetErrorCode(OK);
2170   return nbSolutions;
2171 }
2172
2173 //=======================================================================
2174 /*!
2175  *  Get coordinates of point
2176  */
2177 //=======================================================================
2178 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
2179                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
2180 {
2181   SetErrorCode(KO);
2182
2183   if (theShape.IsNull())
2184     return;
2185
2186   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2187   if (aRefShape.IsNull())
2188     return;
2189
2190   TopoDS_Shape aShape = aRefShape->GetValue();
2191   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
2192   {
2193     SetErrorCode( "Shape must be a vertex" );
2194     return;
2195   }
2196
2197   try {
2198     OCC_CATCH_SIGNALS;
2199     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
2200     theX = aPnt.X();
2201     theY = aPnt.Y();
2202     theZ = aPnt.Z();
2203
2204     SetErrorCode(OK);
2205   }
2206   catch (Standard_Failure& aFail)
2207   {
2208     SetErrorCode( aFail.GetMessageString() );
2209   }
2210 }
2211
2212 //=======================================================================
2213 /*!
2214  *  Compute angle (in degrees) between two lines
2215  */
2216 //=======================================================================
2217 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
2218                                                      Handle(GEOM_Object) theLine2)
2219 {
2220   if (theLine1->GetType() == GEOM_VECTOR &&
2221       theLine2->GetType() == GEOM_VECTOR)
2222     return GetAngleBtwVectors(theLine1, theLine2);
2223
2224   SetErrorCode(KO);
2225
2226   Standard_Real anAngle = -1.0;
2227
2228   if (theLine1.IsNull() || theLine2.IsNull())
2229     return anAngle;
2230
2231   Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
2232   Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
2233   if (aRefLine1.IsNull() || aRefLine2.IsNull())
2234     return anAngle;
2235
2236   TopoDS_Shape aLine1 = aRefLine1->GetValue();
2237   TopoDS_Shape aLine2 = aRefLine2->GetValue();
2238   if (aLine1.IsNull() || aLine2.IsNull() ||
2239       aLine1.ShapeType() != TopAbs_EDGE ||
2240       aLine2.ShapeType() != TopAbs_EDGE)
2241   {
2242     SetErrorCode("Two edges must be given");
2243     return anAngle;
2244   }
2245
2246   try {
2247     OCC_CATCH_SIGNALS;
2248     TopoDS_Edge E1 = TopoDS::Edge(aLine1);
2249     TopoDS_Edge E2 = TopoDS::Edge(aLine2);
2250
2251     double fp,lp;
2252     Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2253     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
2254
2255     if ( C1.IsNull() || C2.IsNull() ||
2256         !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
2257         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
2258     {
2259       SetErrorCode("The edges must be linear");
2260       return anAngle;
2261     }
2262
2263     Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
2264     Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
2265
2266     gp_Lin aLin1 = L1->Lin();
2267     gp_Lin aLin2 = L2->Lin();
2268
2269     anAngle = aLin1.Angle(aLin2);
2270     anAngle *= 180. / M_PI; // convert radians into degrees
2271
2272     if (anAngle > 90.0) {
2273       anAngle = 180.0 - anAngle;
2274     }
2275
2276     SetErrorCode(OK);
2277   }
2278   catch (Standard_Failure& aFail)
2279   {
2280     SetErrorCode(aFail.GetMessageString());
2281   }
2282
2283   return anAngle;
2284 }
2285
2286 //=======================================================================
2287 /*!
2288  *  Compute angle (in degrees) between two vectors
2289  */
2290 //=======================================================================
2291 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
2292                                                                Handle(GEOM_Object) theVec2)
2293 {
2294   SetErrorCode(KO);
2295
2296   Standard_Real anAngle = -1.0;
2297
2298   if (theVec1.IsNull() || theVec2.IsNull())
2299     return anAngle;
2300
2301   if (theVec1->GetType() != GEOM_VECTOR || theVec2->GetType() != GEOM_VECTOR) {
2302     SetErrorCode("Two vectors must be given");
2303     return anAngle;
2304   }
2305
2306   Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2307   Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2308   if (aRefVec1.IsNull() || aRefVec2.IsNull())
2309     return anAngle;
2310
2311   TopoDS_Shape aVec1 = aRefVec1->GetValue();
2312   TopoDS_Shape aVec2 = aRefVec2->GetValue();
2313   if (aVec1.IsNull() || aVec2.IsNull() ||
2314       aVec1.ShapeType() != TopAbs_EDGE ||
2315       aVec2.ShapeType() != TopAbs_EDGE)
2316   {
2317     SetErrorCode("Two edges must be given");
2318     return anAngle;
2319   }
2320
2321   try {
2322     OCC_CATCH_SIGNALS;
2323     TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2324     TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2325
2326     TopoDS_Vertex aP11, aP12, aP21, aP22;
2327     TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2328     TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2329     if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2330       SetErrorCode("Bad edge given");
2331       return anAngle;
2332     }
2333
2334     gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2335     gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2336
2337     anAngle = aV1.Angle(aV2);
2338     anAngle *= 180. / M_PI; // convert radians into degrees
2339
2340     SetErrorCode(OK);
2341   }
2342   catch (Standard_Failure& aFail)
2343   {
2344     SetErrorCode(aFail.GetMessageString());
2345   }
2346
2347   return anAngle;
2348 }
2349
2350
2351 //=============================================================================
2352 /*!
2353  *  CurveCurvatureByParam
2354  */
2355 //=============================================================================
2356 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2357                         (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2358 {
2359   SetErrorCode(KO);
2360   Standard_Real aRes = -1.0;
2361
2362   if(theCurve.IsNull()) return aRes;
2363
2364   Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2365   if(aRefShape.IsNull()) return aRes;
2366
2367   TopoDS_Shape aShape = aRefShape->GetValue();
2368   if(aShape.IsNull()) {
2369     SetErrorCode("One of Objects has NULL Shape");
2370     return aRes;
2371   }
2372
2373   Standard_Real aFP, aLP, aP;
2374   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2375   aP = aFP + (aLP - aFP) * theParam;
2376
2377   if(aCurve.IsNull()) return aRes;
2378
2379   //Compute curvature
2380   try {
2381     OCC_CATCH_SIGNALS;
2382     GeomLProp_CLProps Prop = GeomLProp_CLProps
2383       (aCurve, aP, 2, Precision::Confusion());
2384     aRes = fabs(Prop.Curvature());
2385     SetErrorCode(OK);
2386   }
2387   catch (Standard_Failure& aFail) {
2388     SetErrorCode(aFail.GetMessageString());
2389     return aRes;
2390   }
2391
2392   if( aRes > Precision::Confusion() )
2393     aRes = 1/aRes;
2394   else
2395     aRes = RealLast();
2396
2397   return aRes;
2398 }
2399
2400
2401 //=============================================================================
2402 /*!
2403  *  CurveCurvatureByPoint
2404  */
2405 //=============================================================================
2406 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2407                    (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2408 {
2409   SetErrorCode(KO);
2410   Standard_Real aRes = -1.0;
2411
2412   if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2413
2414   Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2415   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2416   if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2417
2418   TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2419   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2420   if( anEdge.IsNull() || aPnt.IsNull() ) {
2421     SetErrorCode("One of Objects has NULL Shape");
2422     return aRes;
2423   }
2424
2425   Standard_Real aFP, aLP;
2426   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2427   if(aCurve.IsNull()) return aRes;
2428   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2429
2430   //Compute curvature
2431   try {
2432     OCC_CATCH_SIGNALS;
2433     GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2434     if(PPCurve.NbPoints()>0) {
2435       GeomLProp_CLProps Prop = GeomLProp_CLProps
2436         (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2437       aRes = fabs(Prop.Curvature());
2438       SetErrorCode(OK);
2439     }
2440   }
2441   catch (Standard_Failure& aFail) {
2442     SetErrorCode(aFail.GetMessageString());
2443     return aRes;
2444   }
2445
2446   if( aRes > Precision::Confusion() )
2447     aRes = 1/aRes;
2448   else
2449     aRes = RealLast();
2450
2451   return aRes;
2452 }
2453
2454
2455 //=============================================================================
2456 /*!
2457  *  getSurfaceCurvatures
2458  */
2459 //=============================================================================
2460 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2461                                           (const Handle(Geom_Surface)& aSurf,
2462                                            Standard_Real theUParam,
2463                                            Standard_Real theVParam,
2464                                            Standard_Boolean theNeedMaxCurv)
2465 {
2466   SetErrorCode(KO);
2467   Standard_Real aRes = 1.0;
2468
2469   if (aSurf.IsNull()) return aRes;
2470
2471   try {
2472     OCC_CATCH_SIGNALS;
2473     GeomLProp_SLProps Prop = GeomLProp_SLProps
2474       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2475     if(Prop.IsCurvatureDefined()) {
2476       if(Prop.IsUmbilic()) {
2477         //cout<<"is umbilic"<<endl;
2478         aRes = fabs(Prop.MeanCurvature());
2479       }
2480       else {
2481         //cout<<"is not umbilic"<<endl;
2482         double c1 = fabs(Prop.MaxCurvature());
2483         double c2 = fabs(Prop.MinCurvature());
2484         if(theNeedMaxCurv)
2485           aRes = Max(c1,c2);
2486         else
2487           aRes = Min(c1,c2);
2488       }
2489       SetErrorCode(OK);
2490     }
2491   }
2492   catch (Standard_Failure& aFail) {
2493     SetErrorCode(aFail.GetMessageString());
2494     return aRes;
2495   }
2496
2497   if( fabs(aRes) > Precision::Confusion() )
2498     aRes = 1/aRes;
2499   else
2500     aRes = RealLast();
2501
2502   return aRes;
2503 }
2504
2505
2506 //=============================================================================
2507 /*!
2508  *  MaxSurfaceCurvatureByParam
2509  */
2510 //=============================================================================
2511 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2512                                                   (Handle(GEOM_Object) theSurf,
2513                                                    Standard_Real& theUParam,
2514                                                    Standard_Real& theVParam)
2515 {
2516   SetErrorCode(KO);
2517   Standard_Real aRes = -1.0;
2518
2519   if (theSurf.IsNull()) return aRes;
2520
2521   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2522   if(aRefShape.IsNull()) return aRes;
2523
2524   TopoDS_Shape aShape = aRefShape->GetValue();
2525   if(aShape.IsNull()) {
2526     SetErrorCode("One of Objects has NULL Shape");
2527     return aRes;
2528   }
2529
2530   TopoDS_Face F = TopoDS::Face(aShape);
2531   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2532
2533   //Compute the parameters
2534   Standard_Real U1,U2,V1,V2;
2535   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2536   Standard_Real U = U1 + (U2-U1)*theUParam;
2537   Standard_Real V = V1 + (V2-V1)*theVParam;
2538
2539   return getSurfaceCurvatures(aSurf, U, V, true);
2540 }
2541
2542
2543 //=============================================================================
2544 /*!
2545  *  MaxSurfaceCurvatureByPoint
2546  */
2547 //=============================================================================
2548 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2549                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2550 {
2551   SetErrorCode(KO);
2552   Standard_Real aRes = -1.0;
2553
2554   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2555
2556   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2557   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2558   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2559
2560   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2561   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2562   if( aFace.IsNull() || aPnt.IsNull() ) {
2563     SetErrorCode("One of Objects has NULL Shape");
2564     return 0;
2565   }
2566
2567   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2568   if(aSurf.IsNull()) return aRes;
2569   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2570
2571   //Compute the parameters
2572   ShapeAnalysis_Surface sas(aSurf);
2573   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2574
2575   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2576 }
2577
2578
2579 //=============================================================================
2580 /*!
2581  *  MinSurfaceCurvatureByParam
2582  */
2583 //=============================================================================
2584 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2585                                                   (Handle(GEOM_Object) theSurf,
2586                                                    Standard_Real& theUParam,
2587                                                    Standard_Real& theVParam)
2588 {
2589   SetErrorCode(KO);
2590   Standard_Real aRes = -1.0;
2591
2592   if (theSurf.IsNull()) return aRes;
2593
2594   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2595   if(aRefShape.IsNull()) return aRes;
2596
2597   TopoDS_Shape aShape = aRefShape->GetValue();
2598   if(aShape.IsNull()) {
2599     SetErrorCode("One of Objects has NULL Shape");
2600     return aRes;
2601   }
2602
2603   TopoDS_Face F = TopoDS::Face(aShape);
2604   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2605
2606   //Compute the parameters
2607   Standard_Real U1,U2,V1,V2;
2608   ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2609   Standard_Real U = U1 + (U2-U1)*theUParam;
2610   Standard_Real V = V1 + (V2-V1)*theVParam;
2611
2612   return getSurfaceCurvatures(aSurf, U, V, false);
2613 }
2614
2615
2616 //=============================================================================
2617 /*!
2618  *  MinSurfaceCurvatureByPoint
2619  */
2620 //=============================================================================
2621 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2622                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2623 {
2624   SetErrorCode(KO);
2625   Standard_Real aRes = -1.0;
2626
2627   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2628
2629   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2630   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2631   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2632
2633   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2634   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2635   if( aFace.IsNull() || aPnt.IsNull() ) {
2636     SetErrorCode("One of Objects has NULL Shape");
2637     return 0;
2638   }
2639
2640   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2641   if(aSurf.IsNull()) return aRes;
2642   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2643
2644   //Compute the parameters
2645   ShapeAnalysis_Surface sas(aSurf);
2646   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2647
2648   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2649 }
2650
2651 //=======================================================================
2652 //function : FillErrorsSub
2653 //purpose  : Fill the errors list of subshapes on shape.
2654 //=======================================================================
2655 void GEOMImpl_IMeasureOperations::FillErrorsSub
2656            (const BRepCheck_Analyzer                   &theAna,
2657             const TopoDS_Shape                         &theShape,
2658             const TopAbs_ShapeEnum                     theSubType,
2659                   TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
2660 {
2661   TopExp_Explorer anExp(theShape, theSubType);
2662   TopTools_MapOfShape aMapSubShapes;
2663
2664   for (; anExp.More(); anExp.Next()) {
2665     const TopoDS_Shape &aSubShape = anExp.Current();
2666
2667     if (aMapSubShapes.Add(aSubShape)) {
2668       const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
2669
2670       for (aRes->InitContextIterator();
2671            aRes->MoreShapeInContext(); 
2672            aRes->NextShapeInContext()) {
2673         if (aRes->ContextualShape().IsSame(theShape)) {
2674           BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
2675
2676           if (itl.Value() != BRepCheck_NoError) {
2677             // Add all errors for theShape and its sub-shape.
2678             for (;itl.More(); itl.Next()) {
2679               const Standard_Integer aStat = (Standard_Integer)itl.Value();
2680
2681               if (!theMapErrors.IsBound(aStat)) {
2682                 TopTools_ListOfShape anEmpty;
2683
2684                 theMapErrors.Bind(aStat, anEmpty);
2685               }
2686
2687               TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
2688
2689               theShapes.Append(aSubShape);
2690               theShapes.Append(theShape);
2691             }
2692           }
2693         }
2694
2695         break;
2696       }
2697     }
2698   }
2699 }
2700
2701 //=======================================================================
2702 //function : FillErrors
2703 //purpose  : Fill the errors list.
2704 //=======================================================================
2705 void GEOMImpl_IMeasureOperations::FillErrors
2706              (const BRepCheck_Analyzer                   &theAna,
2707               const TopoDS_Shape                         &theShape,
2708                     TopTools_DataMapOfIntegerListOfShape &theMapErrors,
2709                     TopTools_MapOfShape                  &theMapShapes) const
2710 {
2711   if (theMapShapes.Add(theShape)) {
2712     // Fill errors of child shapes.
2713     for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
2714       FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
2715     }
2716
2717     // Fill errors of theShape.
2718     const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
2719
2720     if (!aRes.IsNull()) {
2721       BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
2722
2723       if (itl.Value() != BRepCheck_NoError) {
2724         // Add all errors for theShape.
2725         for (;itl.More(); itl.Next()) {
2726           const Standard_Integer aStat = (Standard_Integer)itl.Value();
2727
2728           if (!theMapErrors.IsBound(aStat)) {
2729             TopTools_ListOfShape anEmpty;
2730
2731             theMapErrors.Bind(aStat, anEmpty);
2732           }
2733
2734           theMapErrors.ChangeFind(aStat).Append(theShape);
2735         }
2736       }
2737     }
2738
2739     // Add errors of subshapes on theShape.
2740     const TopAbs_ShapeEnum aType = theShape.ShapeType();
2741
2742     switch (aType) {
2743     case TopAbs_EDGE:
2744       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
2745       break;
2746     case TopAbs_FACE:
2747       FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
2748       FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
2749       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
2750       break;
2751     case TopAbs_SOLID:
2752       FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
2753       break;
2754     default:
2755       break;
2756     }
2757   }
2758 }
2759
2760 //=======================================================================
2761 //function : FillErrors
2762 //purpose  : Fill the errors list.
2763 //=======================================================================
2764 void GEOMImpl_IMeasureOperations::FillErrors
2765                   (const BRepCheck_Analyzer    &theAna,
2766                    const TopoDS_Shape          &theShape,
2767                          std::list<ShapeError> &theErrors) const
2768 {
2769   // Fill the errors map.
2770   TopTools_DataMapOfIntegerListOfShape aMapErrors;
2771   TopTools_MapOfShape                  aMapShapes;
2772
2773   FillErrors(theAna, theShape, aMapErrors, aMapShapes);
2774
2775   // Map sub-shapes and their indices
2776   TopTools_IndexedMapOfShape anIndices;
2777
2778   TopExp::MapShapes(theShape, anIndices);
2779
2780   TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
2781
2782   for (; aMapIter.More(); aMapIter.Next()) {
2783     ShapeError anError;
2784
2785     anError.error = (BRepCheck_Status)aMapIter.Key();
2786
2787     TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
2788     TopTools_MapOfShape                aMapUnique;
2789
2790     for (; aListIter.More(); aListIter.Next()) {
2791       const TopoDS_Shape &aShape = aListIter.Value();
2792
2793       if (aMapUnique.Add(aShape)) {
2794         const Standard_Integer anIndex = anIndices.FindIndex(aShape);
2795
2796         anError.incriminated.push_back(anIndex);
2797       }
2798     }
2799
2800     if (!anError.incriminated.empty()) {
2801       theErrors.push_back(anError);
2802     }
2803   }
2804 }