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