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