Salome HOME
[bos #36169] EDF 25230 - Conversion xyz => uv => xyz. Replace all calls of ShapeAnaly...
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IMeasureOperations.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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_IProximity.hxx>
29 #include <GEOMImpl_PatchFaceDriver.hxx>
30 #include <GEOMImpl_ShapeProximityDriver.hxx>
31
32 #include <GEOMImpl_Types.hxx>
33
34 #include <GEOMImpl_IConformity.hxx>
35 #include <GEOMImpl_ConformityDriver.hxx>
36
37 #include <GEOMUtils.hxx>
38
39 #include <GEOMAlgo_AlgoTools.hxx>
40 #include <GEOMAlgo_KindOfName.hxx>
41 #include <GEOMAlgo_ShapeInfoFiller.hxx>
42
43 #include <GEOM_PythonDump.hxx>
44
45 #include <utilities.h>
46
47 // OCCT Includes
48 #include <Bnd_Box.hxx>
49 #include <BOPAlgo_CheckerSI.hxx>
50 #include <TopTools_ListOfShape.hxx>
51 #include <BOPDS_DS.hxx>
52 #include <BOPDS_MapOfPair.hxx>
53 #include <BOPDS_Pair.hxx>
54 #include <BOPTools_AlgoTools.hxx>
55 #include <BRepBndLib.hxx>
56 #include <BRepBuilderAPI_Copy.hxx>
57 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
58 #include <BRepCheck_Shell.hxx>
59 #include <BRepClass3d_SolidClassifier.hxx>
60 #include <BRepClass_FaceClassifier.hxx>
61 #include <BRepExtrema_DistShapeShape.hxx>
62 #include <BRepExtrema_ShapeProximity.hxx>
63 #include <BRepExtrema_SelfIntersection.hxx>
64 #include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
65 #include <BRepGProp.hxx>
66 #include <BRepTools.hxx>
67 #include <BRep_Tool.hxx>
68 #include <Geom_Line.hxx>
69 #include <GeomAPI_ProjectPointOnCurve.hxx>
70 #include <GeomAPI_ProjectPointOnSurf.hxx>
71 #include <GeomLProp_CLProps.hxx>
72 #include <GeomLProp_SLProps.hxx>
73 #include <Geom_Plane.hxx>
74 #include <GProp_GProps.hxx>
75 #include <GProp_PrincipalProps.hxx>
76 #include <ShapeAnalysis_Surface.hxx>
77 #include <TopExp.hxx>
78 #include <TopExp_Explorer.hxx>
79 #include <TopoDS.hxx>
80 #include <TopoDS_Edge.hxx>
81 #include <TopTools_IndexedMapOfShape.hxx>
82 #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
83 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
84 #include <TopTools_ListIteratorOfListOfShape.hxx>
85 #include <TopTools_ListOfShape.hxx>
86 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
87
88 #include <set>
89
90 //=============================================================================
91 /*!
92  *  Constructor
93  */
94 //=============================================================================
95 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine)
96 : GEOM_IOperations(theEngine)
97 {
98   MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
99 }
100
101 //=============================================================================
102 /*!
103  *  Destructor
104  */
105 //=============================================================================
106 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
107 {
108   MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
109 }
110
111 //=============================================================================
112 /*! Get kind and parameters of the given shape.
113  */
114 //=============================================================================
115 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
116                              (Handle(GEOM_Object) theShape,
117                               Handle(TColStd_HSequenceOfInteger)& theIntegers,
118                               Handle(TColStd_HSequenceOfReal)&    theDoubles)
119 {
120   SetErrorCode(KO);
121   ShapeKind aKind = SK_NO_SHAPE;
122
123   if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
124   else                      theIntegers->Clear();
125
126   if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
127   else                     theDoubles->Clear();
128
129   if (theShape.IsNull())
130     return aKind;
131
132   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
133   if (aRefShape.IsNull()) return aKind;
134
135   TopoDS_Shape aShape = aRefShape->GetValue();
136   if (aShape.IsNull()) return aKind;
137
138   int geom_type = theShape->GetType();
139
140   // check if it's advanced shape
141   if ( geom_type > USER_TYPE ) {
142     SetErrorCode(OK);
143     return SK_ADVANCED;
144   }
145
146   // Call algorithm
147   GEOMAlgo_ShapeInfoFiller aSF;
148   aSF.SetShape(aShape);
149   aSF.Perform();
150
151   Standard_Integer iErr = aSF.ErrorStatus();
152
153   if (iErr) {
154     SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
155     return SK_NO_SHAPE;
156   }
157   const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
158
159   // specific processing for some "advanced" objects
160   switch ( geom_type ) {
161   case GEOM_MARKER:
162     // local coordinate system
163     // (+) geompy.kind.LCS  xc yc zc xx xy xz yx yy yz zx zy zz
164
165     TopoDS_Face aFace = TopoDS::Face( aShape );
166     Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) );
167     gp_Pnt aC = aPlane->Pln().Location();
168     gp_Ax3 anAx3 = aPlane->Pln().Position();
169
170     theDoubles->Append(aC.X());
171     theDoubles->Append(aC.Y());
172     theDoubles->Append(aC.Z());
173     
174     gp_Dir aD = anAx3.XDirection();
175     theDoubles->Append(aD.X());
176     theDoubles->Append(aD.Y());
177     theDoubles->Append(aD.Z());
178     aD = anAx3.YDirection();
179     theDoubles->Append(aD.X());
180     theDoubles->Append(aD.Y());
181     theDoubles->Append(aD.Z());
182     aD = anAx3.Direction();
183     theDoubles->Append(aD.X());
184     theDoubles->Append(aD.Y());
185     theDoubles->Append(aD.Z());
186
187     SetErrorCode(OK);
188     return SK_LCS;
189   }
190
191   // Interpret results
192   TopAbs_ShapeEnum aType = anInfo.Type();
193   switch (aType)
194   {
195   case TopAbs_COMPOUND:
196   case TopAbs_COMPSOLID:
197     {
198       // (+) geompy.kind.COMPOUND     nb_solids nb_faces nb_edges nb_vertices
199       // (+) geompy.kind.COMPSOLID    nb_solids nb_faces nb_edges nb_vertices
200       // ??? "nb_faces" - all faces or only 'standalone' faces?
201       if (aType == TopAbs_COMPOUND)
202         aKind = SK_COMPOUND;
203       else
204         aKind = SK_COMPSOLID;
205
206       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPOUND));
207       //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPSOLID));
208       theIntegers->Append(anInfo.NbSubShapes(TopAbs_SOLID));
209       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
210       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
211       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
212     }
213     break;
214
215   case TopAbs_SHELL:
216     {
217       // (+) geompy.kind.SHELL  geompy.info.closed   nb_faces nb_edges nb_vertices
218       // (+) geompy.kind.SHELL  geompy.info.unclosed nb_faces nb_edges nb_vertices
219       aKind = SK_SHELL;
220
221       theIntegers->Append((int)anInfo.KindOfClosed());
222
223       theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
224       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
225       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
226     }
227     break;
228
229   case TopAbs_WIRE:
230     {
231       // (+) geompy.kind.WIRE  geompy.info.closed   nb_edges nb_vertices
232       // (+) geompy.kind.WIRE  geompy.info.unclosed nb_edges nb_vertices
233       aKind = SK_WIRE;
234
235       theIntegers->Append((int)anInfo.KindOfClosed());
236
237       theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
238       theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
239     }
240     break;
241
242   case TopAbs_SOLID:
243     {
244       aKind = SK_SOLID;
245
246       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
247       switch (aKN)
248       {
249       case GEOMAlgo_KN_SPHERE:
250         // (+) geompy.kind.SPHERE  xc yc zc  R
251         {
252           aKind = SK_SPHERE;
253
254           gp_Pnt aC = anInfo.Location();
255           theDoubles->Append(aC.X());
256           theDoubles->Append(aC.Y());
257           theDoubles->Append(aC.Z());
258
259           theDoubles->Append(anInfo.Radius1());
260         }
261         break;
262       case GEOMAlgo_KN_CYLINDER:
263         // (+) geompy.kind.CYLINDER  xb yb zb  dx dy dz  R  H
264         {
265           aKind = SK_CYLINDER;
266
267           gp_Pnt aC = anInfo.Location();
268           theDoubles->Append(aC.X());
269           theDoubles->Append(aC.Y());
270           theDoubles->Append(aC.Z());
271
272           gp_Ax3 anAx3 = anInfo.Position();
273           gp_Dir aD = anAx3.Direction();
274           theDoubles->Append(aD.X());
275           theDoubles->Append(aD.Y());
276           theDoubles->Append(aD.Z());
277
278           theDoubles->Append(anInfo.Radius1());
279           theDoubles->Append(anInfo.Height());
280         }
281         break;
282       case GEOMAlgo_KN_BOX:
283         // (+) geompy.kind.BOX  xc yc zc  ax ay az
284         {
285           aKind = SK_BOX;
286
287           gp_Pnt aC = anInfo.Location();
288           theDoubles->Append(aC.X());
289           theDoubles->Append(aC.Y());
290           theDoubles->Append(aC.Z());
291
292           gp_Ax3 anAx3 = anInfo.Position();
293           gp_Dir aD = anAx3.Direction();
294           gp_Dir aX = anAx3.XDirection();
295
296           // ax ay az
297           if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
298               aX.IsParallel(gp::DX(), Precision::Angular())) {
299             theDoubles->Append(anInfo.Length()); // ax'
300             theDoubles->Append(anInfo.Width());  // ay'
301             theDoubles->Append(anInfo.Height()); // az'
302           }
303           else if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
304                    aX.IsParallel(gp::DY(), Precision::Angular())) {
305             theDoubles->Append(anInfo.Width());  // ay'
306             theDoubles->Append(anInfo.Length()); // ax'
307             theDoubles->Append(anInfo.Height()); // az'
308           }
309           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
310                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
311             theDoubles->Append(anInfo.Height()); // az'
312             theDoubles->Append(anInfo.Width());  // ay'
313             theDoubles->Append(anInfo.Length()); // ax'
314           }
315           else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
316                    aX.IsParallel(gp::DY(), Precision::Angular())) {
317             theDoubles->Append(anInfo.Height()); // az'
318             theDoubles->Append(anInfo.Length()); // ax'
319             theDoubles->Append(anInfo.Width());  // ay'
320           }
321           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
322                    aX.IsParallel(gp::DZ(), Precision::Angular())) {
323             theDoubles->Append(anInfo.Width());  // ay'
324             theDoubles->Append(anInfo.Height()); // az'
325             theDoubles->Append(anInfo.Length()); // ax'
326           }
327           else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
328                    aX.IsParallel(gp::DX(), Precision::Angular())) {
329             theDoubles->Append(anInfo.Length()); // ax'
330             theDoubles->Append(anInfo.Height()); // az'
331             theDoubles->Append(anInfo.Width());  // ay'
332           }
333           else {
334             // (+) geompy.kind.ROTATED_BOX  xo yo zo  zx zy zz  xx xy xz  ax ay az
335             aKind = SK_ROTATED_BOX;
336
337             // Direction and XDirection
338             theDoubles->Append(aD.X());
339             theDoubles->Append(aD.Y());
340             theDoubles->Append(aD.Z());
341
342             theDoubles->Append(aX.X());
343             theDoubles->Append(aX.Y());
344             theDoubles->Append(aX.Z());
345
346             // ax ay az
347             theDoubles->Append(anInfo.Length());
348             theDoubles->Append(anInfo.Width());
349             theDoubles->Append(anInfo.Height());
350           }
351         }
352         break;
353       case GEOMAlgo_KN_TORUS:
354         // (+) geompy.kind.TORUS  xc yc zc  dx dy dz  R_1 R_2
355         {
356           aKind = SK_TORUS;
357
358           gp_Pnt aO = anInfo.Location();
359           theDoubles->Append(aO.X());
360           theDoubles->Append(aO.Y());
361           theDoubles->Append(aO.Z());
362
363           gp_Ax3 anAx3 = anInfo.Position();
364           gp_Dir aD = anAx3.Direction();
365           theDoubles->Append(aD.X());
366           theDoubles->Append(aD.Y());
367           theDoubles->Append(aD.Z());
368
369           theDoubles->Append(anInfo.Radius1());
370           theDoubles->Append(anInfo.Radius2());
371         }
372         break;
373       case GEOMAlgo_KN_CONE:
374         // (+) geompy.kind.CONE  xb yb zb  dx dy dz  R_1 R_2  H
375         {
376           aKind = SK_CONE;
377
378           gp_Pnt aO = anInfo.Location();
379           theDoubles->Append(aO.X());
380           theDoubles->Append(aO.Y());
381           theDoubles->Append(aO.Z());
382
383           gp_Ax3 anAx3 = anInfo.Position();
384           gp_Dir aD = anAx3.Direction();
385           theDoubles->Append(aD.X());
386           theDoubles->Append(aD.Y());
387           theDoubles->Append(aD.Z());
388
389           theDoubles->Append(anInfo.Radius1());
390           theDoubles->Append(anInfo.Radius2());
391           theDoubles->Append(anInfo.Height());
392         }
393         break;
394       case GEOMAlgo_KN_POLYHEDRON:
395         // (+) geompy.kind.POLYHEDRON  nb_faces nb_edges nb_vertices
396         {
397           aKind = SK_POLYHEDRON;
398
399           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
400           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
401           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
402         }
403         break;
404       default:
405         // (+) geompy.kind.SOLID  nb_faces nb_edges nb_vertices
406         {
407           theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
408           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
409           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
410         }
411       }
412     }
413     break;
414
415   case TopAbs_FACE:
416     {
417       aKind = SK_FACE;
418
419       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
420       switch (aKN) {
421       case GEOMAlgo_KN_SPHERE:
422         // (+) geompy.kind.SPHERE2D  xc yc zc  R
423         {
424           aKind = SK_SPHERE2D;
425
426           gp_Pnt aC = anInfo.Location();
427           theDoubles->Append(aC.X());
428           theDoubles->Append(aC.Y());
429           theDoubles->Append(aC.Z());
430
431           theDoubles->Append(anInfo.Radius1());
432         }
433         break;
434       case GEOMAlgo_KN_CYLINDER:
435         // (+) geompy.kind.CYLINDER2D  xb yb zb  dx dy dz  R  H
436         {
437           aKind = SK_CYLINDER2D;
438
439           gp_Pnt aO = anInfo.Location();
440           theDoubles->Append(aO.X());
441           theDoubles->Append(aO.Y());
442           theDoubles->Append(aO.Z());
443
444           gp_Ax3 anAx3 = anInfo.Position();
445           gp_Dir aD = anAx3.Direction();
446           theDoubles->Append(aD.X());
447           theDoubles->Append(aD.Y());
448           theDoubles->Append(aD.Z());
449
450           theDoubles->Append(anInfo.Radius1());
451           theDoubles->Append(anInfo.Height());
452         }
453         break;
454       case GEOMAlgo_KN_TORUS:
455         // (+) geompy.kind.TORUS2D  xc yc zc  dx dy dz  R_1 R_2
456         {
457           aKind = SK_TORUS2D;
458
459           gp_Pnt aO = anInfo.Location();
460           theDoubles->Append(aO.X());
461           theDoubles->Append(aO.Y());
462           theDoubles->Append(aO.Z());
463
464           gp_Ax3 anAx3 = anInfo.Position();
465           gp_Dir aD = anAx3.Direction();
466           theDoubles->Append(aD.X());
467           theDoubles->Append(aD.Y());
468           theDoubles->Append(aD.Z());
469
470           theDoubles->Append(anInfo.Radius1());
471           theDoubles->Append(anInfo.Radius2());
472         }
473         break;
474       case GEOMAlgo_KN_CONE:
475         // (+) geompy.kind.CONE2D  xc yc zc  dx dy dz  R_1 R_2  H
476         {
477           aKind = SK_CONE2D;
478
479           gp_Pnt aO = anInfo.Location();
480           theDoubles->Append(aO.X());
481           theDoubles->Append(aO.Y());
482           theDoubles->Append(aO.Z());
483
484           gp_Ax3 anAx3 = anInfo.Position();
485           gp_Dir aD = anAx3.Direction();
486           theDoubles->Append(aD.X());
487           theDoubles->Append(aD.Y());
488           theDoubles->Append(aD.Z());
489
490           theDoubles->Append(anInfo.Radius1());
491           theDoubles->Append(anInfo.Radius2());
492           theDoubles->Append(anInfo.Height());
493         }
494         break;
495       case GEOMAlgo_KN_DISKCIRCLE:
496         // (+) geompy.kind.DISK_CIRCLE  xc yc zc  dx dy dz  R
497         {
498           aKind = SK_DISK_CIRCLE;
499
500           gp_Pnt aC = anInfo.Location();
501           theDoubles->Append(aC.X());
502           theDoubles->Append(aC.Y());
503           theDoubles->Append(aC.Z());
504
505           gp_Ax3 anAx3 = anInfo.Position();
506           gp_Dir aD = anAx3.Direction();
507           theDoubles->Append(aD.X());
508           theDoubles->Append(aD.Y());
509           theDoubles->Append(aD.Z());
510
511           theDoubles->Append(anInfo.Radius1());
512         }
513         break;
514       case GEOMAlgo_KN_DISKELLIPSE:
515         // (+) geompy.kind.DISK_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2
516         {
517           aKind = SK_DISK_ELLIPSE;
518
519           gp_Pnt aC = anInfo.Location();
520           theDoubles->Append(aC.X());
521           theDoubles->Append(aC.Y());
522           theDoubles->Append(aC.Z());
523
524           gp_Ax3 anAx3 = anInfo.Position();
525           gp_Dir aD = anAx3.Direction();
526           theDoubles->Append(aD.X());
527           theDoubles->Append(aD.Y());
528           theDoubles->Append(aD.Z());
529
530           theDoubles->Append(anInfo.Radius1());
531           theDoubles->Append(anInfo.Radius2());
532         }
533         break;
534       case GEOMAlgo_KN_RECTANGLE:
535       case GEOMAlgo_KN_TRIANGLE:
536       case GEOMAlgo_KN_QUADRANGLE:
537       case GEOMAlgo_KN_POLYGON:
538         // (+) geompy.kind.POLYGON  xo yo zo  dx dy dz  nb_edges nb_vertices
539         {
540           aKind = SK_POLYGON;
541
542           gp_Pnt aO = anInfo.Location();
543           theDoubles->Append(aO.X());
544           theDoubles->Append(aO.Y());
545           theDoubles->Append(aO.Z());
546
547           gp_Ax3 anAx3 = anInfo.Position();
548           gp_Dir aD = anAx3.Direction();
549           theDoubles->Append(aD.X());
550           theDoubles->Append(aD.Y());
551           theDoubles->Append(aD.Z());
552
553           theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
554           theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
555         }
556         break;
557       case GEOMAlgo_KN_PLANE: // infinite
558         // (+) geompy.kind.PLANE  xo yo zo  dx dy dz
559         {
560           aKind = SK_PLANE;
561
562           gp_Pnt aC = anInfo.Location();
563           theDoubles->Append(aC.X());
564           theDoubles->Append(aC.Y());
565           theDoubles->Append(aC.Z());
566
567           gp_Ax3 anAx3 = anInfo.Position();
568           gp_Dir aD = anAx3.Direction();
569           theDoubles->Append(aD.X());
570           theDoubles->Append(aD.Y());
571           theDoubles->Append(aD.Z());
572
573           if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE)
574           {
575             // (+) geompy.kind.PLANAR  xo yo zo  dx dy dz  nb_edges nb_vertices
576             aKind = SK_PLANAR;
577             
578             theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
579             theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
580           }
581         }
582         break;
583       default:
584         // ??? geompy.kind.FACE  nb_edges nb_vertices _surface_type_id_
585         // (+) geompy.kind.FACE  nb_edges nb_vertices
586         theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
587         theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
588       }
589     }
590     break;
591
592   case TopAbs_EDGE:
593     {
594       aKind = SK_EDGE;
595
596       GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
597       switch (aKN) {
598       case GEOMAlgo_KN_CIRCLE:
599         {
600           // (+) geompy.kind.CIRCLE  xc yc zc  dx dy dz  R
601           aKind = SK_CIRCLE;
602
603           gp_Pnt aC = anInfo.Location();
604           theDoubles->Append(aC.X());
605           theDoubles->Append(aC.Y());
606           theDoubles->Append(aC.Z());
607
608           gp_Ax3 anAx3 = anInfo.Position();
609           gp_Dir aD = anAx3.Direction();
610           theDoubles->Append(aD.X());
611           theDoubles->Append(aD.Y());
612           theDoubles->Append(aD.Z());
613
614           theDoubles->Append(anInfo.Radius1());
615         }
616         break;
617       case GEOMAlgo_KN_ARCCIRCLE:
618         {
619           // (+) geompy.kind.ARC_CIRCLE  xc yc zc  dx dy dz  R  x1 y1 z1  x2 y2 z2
620           aKind = SK_ARC_CIRCLE;
621
622           gp_Pnt aC = anInfo.Location();
623           theDoubles->Append(aC.X());
624           theDoubles->Append(aC.Y());
625           theDoubles->Append(aC.Z());
626
627           gp_Ax3 anAx3 = anInfo.Position();
628           gp_Dir aD = anAx3.Direction();
629           theDoubles->Append(aD.X());
630           theDoubles->Append(aD.Y());
631           theDoubles->Append(aD.Z());
632
633           theDoubles->Append(anInfo.Radius1());
634
635           gp_Pnt aP1 = anInfo.Pnt1();
636           theDoubles->Append(aP1.X());
637           theDoubles->Append(aP1.Y());
638           theDoubles->Append(aP1.Z());
639
640           gp_Pnt aP2 = anInfo.Pnt2();
641           theDoubles->Append(aP2.X());
642           theDoubles->Append(aP2.Y());
643           theDoubles->Append(aP2.Z());
644         }
645         break;
646       case GEOMAlgo_KN_ELLIPSE:
647         {
648           // (+) geompy.kind.ELLIPSE  xc yc zc  dx dy dz  R_1 R_2  xVx yVx zVx  xVy yVy zVy
649           aKind = SK_ELLIPSE;
650
651           gp_Pnt aC = anInfo.Location();
652           theDoubles->Append(aC.X());
653           theDoubles->Append(aC.Y());
654           theDoubles->Append(aC.Z());
655
656           gp_Ax3 anAx3 = anInfo.Position();
657           gp_Dir aD = anAx3.Direction();
658           theDoubles->Append(aD.X());
659           theDoubles->Append(aD.Y());
660           theDoubles->Append(aD.Z());
661
662           theDoubles->Append(anInfo.Radius1());
663           theDoubles->Append(anInfo.Radius2());
664
665           gp_Dir aXD = anAx3.XDirection();
666           theDoubles->Append(aXD.X());
667           theDoubles->Append(aXD.Y());
668           theDoubles->Append(aXD.Z());
669
670           gp_Dir aYD = anAx3.YDirection();
671           theDoubles->Append(aYD.X());
672           theDoubles->Append(aYD.Y());
673           theDoubles->Append(aYD.Z());
674         }
675         break;
676       case GEOMAlgo_KN_ARCELLIPSE:
677         {
678           // (+) geompy.kind.ARC_ELLIPSE  xc yc zc  dx dy dz  R_1 R_2  x1 y1 z1  x2 y2 z2  xVx yVx zVx  xVy yVy zVy
679           aKind = SK_ARC_ELLIPSE;
680
681           gp_Pnt aC = anInfo.Location();
682           theDoubles->Append(aC.X());
683           theDoubles->Append(aC.Y());
684           theDoubles->Append(aC.Z());
685
686           gp_Ax3 anAx3 = anInfo.Position();
687           gp_Dir aD = anAx3.Direction();
688           theDoubles->Append(aD.X());
689           theDoubles->Append(aD.Y());
690           theDoubles->Append(aD.Z());
691
692           theDoubles->Append(anInfo.Radius1());
693           theDoubles->Append(anInfo.Radius2());
694
695           gp_Pnt aP1 = anInfo.Pnt1();
696           theDoubles->Append(aP1.X());
697           theDoubles->Append(aP1.Y());
698           theDoubles->Append(aP1.Z());
699
700           gp_Pnt aP2 = anInfo.Pnt2();
701           theDoubles->Append(aP2.X());
702           theDoubles->Append(aP2.Y());
703           theDoubles->Append(aP2.Z());
704
705           gp_Dir aXD = anAx3.XDirection();
706           theDoubles->Append(aXD.X());
707           theDoubles->Append(aXD.Y());
708           theDoubles->Append(aXD.Z());
709
710           gp_Dir aYD = anAx3.YDirection();
711           theDoubles->Append(aYD.X());
712           theDoubles->Append(aYD.Y());
713           theDoubles->Append(aYD.Z());
714         }
715         break;
716       case GEOMAlgo_KN_LINE:
717         {
718           // ??? geompy.kind.LINE  x1 y1 z1  x2 y2 z2
719           // (+) geompy.kind.LINE  x1 y1 z1  dx dy dz
720           aKind = SK_LINE;
721
722           gp_Pnt aO = anInfo.Location();
723           theDoubles->Append(aO.X());
724           theDoubles->Append(aO.Y());
725           theDoubles->Append(aO.Z());
726
727           gp_Dir aD = anInfo.Direction();
728           theDoubles->Append(aD.X());
729           theDoubles->Append(aD.Y());
730           theDoubles->Append(aD.Z());
731         }
732         break;
733       case GEOMAlgo_KN_SEGMENT:
734         {
735           // (+) geompy.kind.SEGMENT  x1 y1 z1  x2 y2 z2
736           aKind = SK_SEGMENT;
737
738           gp_Pnt aP1 = anInfo.Pnt1();
739           theDoubles->Append(aP1.X());
740           theDoubles->Append(aP1.Y());
741           theDoubles->Append(aP1.Z());
742
743           gp_Pnt aP2 = anInfo.Pnt2();
744           theDoubles->Append(aP2.X());
745           theDoubles->Append(aP2.Y());
746           theDoubles->Append(aP2.Z());
747         }
748         break;
749       case GEOMAlgo_KN_CURVEBSPLINE:
750         {
751           // (+) geompy.kind.CRV_BSPLINE  p d np nk nw nm  x1 y1 z1 ... xnp ynp znp  k1 ... knk  w1 ... wnw  m1 ... mnm
752           aKind = SK_CRV_BSPLINE;
753           Standard_Integer aNbPoles = anInfo.NbPoles();
754           Standard_Integer aNbKnots = anInfo.NbKnots();
755           Standard_Integer aNbWeights = anInfo.NbWeights();
756           Standard_Integer aNbMultiplicities = anInfo.NbMultiplicities();
757
758           theIntegers->Append(anInfo.KindOfPeriod() == GEOMAlgo_KP_PERIODIC ? 1 : 0);
759           theIntegers->Append(anInfo.Degree());
760           theIntegers->Append(aNbPoles);
761           theIntegers->Append(aNbKnots);
762           theIntegers->Append(aNbWeights);
763           theIntegers->Append(aNbMultiplicities);
764           //
765           Standard_Integer i;
766           if (aNbPoles > 0) {
767             Handle(TColgp_HArray1OfPnt) aPoles = anInfo.Poles();
768             if (aPoles.IsNull() || aPoles->Length() != aNbPoles) {
769               SetErrorCode("B-Spline Curve: no or wrong number of poles given");
770               return aKind;
771             }
772             for (i=1; i<=aNbPoles; i++) {
773               const gp_Pnt &aP = aPoles->Value(i);
774               theDoubles->Append(aP.X());
775               theDoubles->Append(aP.Y());
776               theDoubles->Append(aP.Z());
777             }
778           }
779           //
780           if (aNbKnots > 0) {
781             Handle(TColStd_HArray1OfReal) aKnots = anInfo.Knots();
782             if (aKnots.IsNull() || aKnots->Length() != aNbKnots) {
783               SetErrorCode("B-Spline Curve: no or wrong number of knots given");
784               return aKind;
785             }
786             for (i=1; i<=aNbKnots; i++)
787               theDoubles->Append(aKnots->Value(i));
788           }
789           //
790           if (aNbWeights > 0) {
791             Handle(TColStd_HArray1OfReal) aWeights = anInfo.Weights();
792             if (aNbWeights > 0 && (aWeights.IsNull() || aWeights->Length() != aNbWeights)) {
793               SetErrorCode("B-Spline Curve: no or wrong number of weights given");
794               return aKind;
795             }
796             for (i=1; i<=aNbWeights; i++)
797               theDoubles->Append(aWeights->Value(i));
798           }
799           //
800           if (aNbMultiplicities > 0) {
801             Handle(TColStd_HArray1OfInteger) aMults = anInfo.Multiplicities();
802             if (aMults.IsNull() || aMults->Length() != aNbMultiplicities) {
803               SetErrorCode("B-Spline Curve: no or wrong number of multiplicities given");
804               return aKind;
805             }
806             for (i=1; i<=aNbMultiplicities; i++)
807               theIntegers->Append(aMults->Value(i));
808           }
809         }
810         break;
811       case GEOMAlgo_KN_CURVEBEZIER:
812         {
813           // (+) geompy.kind.CRV_BEZIER  np nw  x1 y1 z1 ... xnp ynp znp  w1 ... wnw
814           aKind = SK_CRV_BEZIER;
815           Standard_Integer aNbPoles = anInfo.NbPoles();
816           Standard_Integer aNbWeights = anInfo.NbWeights();
817
818           theIntegers->Append(aNbPoles);
819           theIntegers->Append(aNbWeights);
820           //
821           Standard_Integer i;
822           if (aNbPoles > 0) {
823             Handle(TColgp_HArray1OfPnt) aPoles = anInfo.Poles();
824             if (aPoles.IsNull() || aPoles->Length() != aNbPoles) {
825               SetErrorCode("Bezier Curve: no or wrong number of poles given");
826               return aKind;
827             }
828             for (i=1; i<=aNbPoles; i++) {
829               const gp_Pnt &aP = aPoles->Value(i);
830               theDoubles->Append(aP.X());
831               theDoubles->Append(aP.Y());
832               theDoubles->Append(aP.Z());
833             }
834           }
835           //
836           if (aNbWeights > 0) {
837             Handle(TColStd_HArray1OfReal) aWeights = anInfo.Weights();
838             if (aNbWeights > 0 && (aWeights.IsNull() || aWeights->Length() != aNbWeights)) {
839               SetErrorCode("B-Spline Curve: no or wrong number of weights given");
840               return aKind;
841             }
842             for (i=1; i<=aNbWeights; i++)
843               theDoubles->Append(aWeights->Value(i));
844           }
845         }
846         break;
847       case GEOMAlgo_KN_HYPERBOLA:
848         {
849           // (+) geompy.kind.HYPERBOLA  xc yc zc  dx dy dz  R_1 R_2  xVx yVx zVx  xVy yVy zVy
850           aKind = SK_HYPERBOLA;
851
852           gp_Pnt aC = anInfo.Location();
853           theDoubles->Append(aC.X());
854           theDoubles->Append(aC.Y());
855           theDoubles->Append(aC.Z());
856
857           gp_Ax3 anAx3 = anInfo.Position();
858           gp_Dir aD = anAx3.Direction();
859           theDoubles->Append(aD.X());
860           theDoubles->Append(aD.Y());
861           theDoubles->Append(aD.Z());
862
863           theDoubles->Append(anInfo.Radius1());
864           theDoubles->Append(anInfo.Radius2());
865
866           gp_Dir aXD = anAx3.XDirection();
867           theDoubles->Append(aXD.X());
868           theDoubles->Append(aXD.Y());
869           theDoubles->Append(aXD.Z());
870
871           gp_Dir aYD = anAx3.YDirection();
872           theDoubles->Append(aYD.X());
873           theDoubles->Append(aYD.Y());
874           theDoubles->Append(aYD.Z());
875         }
876         break;
877       case GEOMAlgo_KN_PARABOLA:
878         {
879           // (+) geompy.kind.PARABOLA  xc yc zc  dx dy dz  F  xVx yVx zVx  xVy yVy zVy
880           aKind = SK_PARABOLA;
881
882           gp_Pnt aC = anInfo.Location();
883           theDoubles->Append(aC.X());
884           theDoubles->Append(aC.Y());
885           theDoubles->Append(aC.Z());
886
887           gp_Ax3 anAx3 = anInfo.Position();
888           gp_Dir aD = anAx3.Direction();
889           theDoubles->Append(aD.X());
890           theDoubles->Append(aD.Y());
891           theDoubles->Append(aD.Z());
892
893           theDoubles->Append(anInfo.Radius1());
894
895           gp_Dir aXD = anAx3.XDirection();
896           theDoubles->Append(aXD.X());
897           theDoubles->Append(aXD.Y());
898           theDoubles->Append(aXD.Z());
899
900           gp_Dir aYD = anAx3.YDirection();
901           theDoubles->Append(aYD.X());
902           theDoubles->Append(aYD.Y());
903           theDoubles->Append(aYD.Z());
904         }
905         break;
906       default:
907         // ??? geompy.kind.EDGE  nb_vertices _curve_type_id_
908         // (+) geompy.kind.EDGE  nb_vertices
909         theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
910       }
911     }
912     break;
913
914   case TopAbs_VERTEX:
915     {
916       // (+) geompy.kind.VERTEX  x y z
917       aKind = SK_VERTEX;
918
919       gp_Pnt aP = anInfo.Location();
920       theDoubles->Append(aP.X());
921       theDoubles->Append(aP.Y());
922       theDoubles->Append(aP.Z());
923     }
924     break;
925   default:;
926   }
927
928   SetErrorCode(OK);
929   return aKind;
930 }
931
932 //=============================================================================
933 /*!
934  *  GetPosition
935  */
936 //=============================================================================
937 void GEOMImpl_IMeasureOperations::GetPosition
938                    (Handle(GEOM_Object) theShape,
939                     Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
940                     Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
941                     Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
942 {
943   SetErrorCode(KO);
944
945   //Set default values: global CS
946   Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
947   Zz = Xx = 1.;
948
949   if (theShape.IsNull()) return;
950
951   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
952   if (aRefShape.IsNull()) return;
953
954   TopoDS_Shape aShape = aRefShape->GetValue();
955   if (aShape.IsNull()) {
956     SetErrorCode("The Objects has NULL Shape");
957     return;
958   }
959
960   try {
961     OCC_CATCH_SIGNALS;
962
963     gp_Ax3 anAx3 = GEOMUtils::GetPosition(aShape);
964
965     gp_Pnt anOri = anAx3.Location();
966     gp_Dir aDirZ = anAx3.Direction();
967     gp_Dir aDirX = anAx3.XDirection();
968
969     // Output values
970     anOri.Coord(Ox, Oy, Oz);
971     aDirZ.Coord(Zx, Zy, Zz);
972     aDirX.Coord(Xx, Xy, Xz);
973   }
974   catch (Standard_Failure& aFail) {
975     SetErrorCode(aFail.GetMessageString());
976     return;
977   }
978
979   SetErrorCode(OK);
980 }
981
982 //=============================================================================
983 /*!
984  *  GetCentreOfMass
985  */
986 //=============================================================================
987 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
988                                                 (Handle(GEOM_Object) theShape)
989 {
990   SetErrorCode(KO);
991
992   if (theShape.IsNull()) return NULL;
993
994   //Add a new CentreOfMass object
995   Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG);
996
997   //Add a new CentreOfMass function
998   Handle(GEOM_Function) aFunction =
999     aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
1000   if (aFunction.IsNull()) return NULL;
1001
1002   //Check if the function is set correctly
1003   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1004
1005   GEOMImpl_IMeasure aCI (aFunction);
1006
1007   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1008   if (aRefShape.IsNull()) return NULL;
1009
1010   aCI.SetBase(aRefShape);
1011
1012   //Compute the CentreOfMass value
1013   try {
1014     OCC_CATCH_SIGNALS;
1015     if (!GetSolver()->ComputeFunction(aFunction)) {
1016       SetErrorCode("Measure driver failed to compute centre of mass");
1017       return NULL;
1018     }
1019   }
1020   catch (Standard_Failure& aFail) {
1021     SetErrorCode(aFail.GetMessageString());
1022     return NULL;
1023   }
1024
1025   //Make a Python command
1026   GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
1027
1028   SetErrorCode(OK);
1029   return aCDG;
1030 }
1031
1032 //=============================================================================
1033 /*!
1034  *  GetVertexByIndex
1035  */
1036 //=============================================================================
1037 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
1038                                                 (Handle(GEOM_Object) theShape,
1039                                                  Standard_Integer theIndex,
1040                                                  Standard_Boolean theUseOri)
1041 {
1042   SetErrorCode(KO);
1043
1044   if (theShape.IsNull()) return NULL;
1045
1046   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1047   if (aRefShape.IsNull()) return NULL;
1048
1049   //Add a new Vertex object
1050   Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT);
1051
1052   //Add a function
1053   Handle(GEOM_Function) aFunction =
1054     aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
1055   if (aFunction.IsNull()) return NULL;
1056
1057   //Check if the function is set correctly
1058   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1059
1060   GEOMImpl_IMeasure aCI (aFunction);
1061   aCI.SetBase(aRefShape);
1062   aCI.SetIndex(theIndex);
1063   aCI.SetUseOri(theUseOri);
1064
1065   //Compute
1066   try {
1067     OCC_CATCH_SIGNALS;
1068     if (!GetSolver()->ComputeFunction(aFunction)) {
1069       SetErrorCode("Vertex by index driver failed.");
1070       return NULL;
1071     }
1072   }
1073   catch (Standard_Failure& aFail) {
1074     SetErrorCode(aFail.GetMessageString());
1075     return NULL;
1076   }
1077
1078   //Make a Python command
1079   GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex("
1080                                << theShape << ", "
1081                                << theIndex << ", "
1082                                << theUseOri << ")";
1083
1084   SetErrorCode(OK);
1085   return aVertex;
1086 }
1087
1088 //=============================================================================
1089 /*!
1090  *  GetNormal
1091  */
1092 //=============================================================================
1093 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
1094                                          (Handle(GEOM_Object) theFace,
1095                                           Handle(GEOM_Object) theOptionalPoint)
1096 {
1097   SetErrorCode(KO);
1098
1099   if (theFace.IsNull()) return NULL;
1100
1101   //Add a new Normale object
1102   Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR);
1103
1104   //Add a new Normale function
1105   Handle(GEOM_Function) aFunction =
1106     aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
1107   if (aFunction.IsNull()) return NULL;
1108
1109   //Check if the function is set correctly
1110   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1111
1112   GEOMImpl_IMeasure aCI (aFunction);
1113
1114   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
1115   if (aFace.IsNull()) return NULL;
1116
1117   aCI.SetBase(aFace);
1118
1119   if (!theOptionalPoint.IsNull()) {
1120     Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
1121     aCI.SetPoint(anOptPnt);
1122   }
1123
1124   //Compute the Normale value
1125   try {
1126     OCC_CATCH_SIGNALS;
1127     if (!GetSolver()->ComputeFunction(aFunction)) {
1128       SetErrorCode("Measure driver failed to compute normake of face");
1129       return NULL;
1130     }
1131   }
1132   catch (Standard_Failure& aFail) {
1133     SetErrorCode(aFail.GetMessageString());
1134     return NULL;
1135   }
1136
1137   //Make a Python command
1138   GEOM::TPythonDump pd (aFunction);
1139   pd << aNorm << " = geompy.GetNormal(" << theFace;
1140   if (!theOptionalPoint.IsNull()) {
1141     pd << ", " << theOptionalPoint;
1142   }
1143   pd << ")";
1144
1145   SetErrorCode(OK);
1146   return aNorm;
1147 }
1148
1149 //=============================================================================
1150 /*!
1151  *  GetBasicProperties
1152  */
1153 //=============================================================================
1154 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
1155                                                       const Standard_Real theTolerance,
1156                                                       Standard_Real& theLength,
1157                                                       Standard_Real& theSurfArea,
1158                                                       Standard_Real& theVolume)
1159 {
1160   SetErrorCode(KO);
1161
1162   if (theShape.IsNull()) return;
1163
1164   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1165   if (aRefShape.IsNull()) return;
1166
1167   TopoDS_Shape aShape = aRefShape->GetValue();
1168   if (aShape.IsNull()) {
1169     SetErrorCode("The Objects has NULL Shape");
1170     return;
1171   }
1172
1173   //Compute the parameters
1174   GProp_GProps LProps, SProps;
1175   Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
1176   try {
1177     OCC_CATCH_SIGNALS;
1178     BRepGProp::LinearProperties(aShape, LProps, Standard_True);
1179     theLength = LProps.Mass();
1180
1181     BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
1182     theSurfArea = SProps.Mass();
1183
1184     theVolume = 0.0;
1185     if (aShape.ShapeType() < TopAbs_SHELL) {
1186       for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1187         GProp_GProps VProps;
1188         BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
1189         theVolume += VProps.Mass();
1190       }
1191     }
1192   }
1193   catch (Standard_Failure& aFail) {
1194     SetErrorCode(aFail.GetMessageString());
1195     return;
1196   }
1197
1198   SetErrorCode(OK);
1199 }
1200
1201 //=============================================================================
1202 /*!
1203  *  GetInertia
1204  */
1205 //=============================================================================
1206 void GEOMImpl_IMeasureOperations::GetInertia
1207                    (Handle(GEOM_Object) theShape,
1208                     Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1209                     Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1210                     Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1211                     Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1212 {
1213   SetErrorCode(KO);
1214
1215   if (theShape.IsNull()) return;
1216
1217   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1218   if (aRefShape.IsNull()) return;
1219
1220   TopoDS_Shape aShape = aRefShape->GetValue();
1221   if (aShape.IsNull()) {
1222     SetErrorCode("The Objects has NULL Shape");
1223     return;
1224   }
1225
1226   //Compute the parameters
1227   GProp_GProps System;
1228
1229   try {
1230     OCC_CATCH_SIGNALS;
1231     if (aShape.ShapeType() == TopAbs_VERTEX ||
1232         aShape.ShapeType() == TopAbs_EDGE ||
1233         aShape.ShapeType() == TopAbs_WIRE) {
1234       BRepGProp::LinearProperties(aShape, System, Standard_True);
1235     } else if (aShape.ShapeType() == TopAbs_FACE ||
1236                aShape.ShapeType() == TopAbs_SHELL) {
1237       BRepGProp::SurfaceProperties(aShape, System, Standard_True);
1238     } else {
1239       BRepGProp::VolumeProperties(aShape, System, Standard_True);
1240     }
1241     gp_Mat I = System.MatrixOfInertia();
1242
1243     I11 = I(1,1);
1244     I12 = I(1,2);
1245     I13 = I(1,3);
1246
1247     I21 = I(2,1);
1248     I22 = I(2,2);
1249     I23 = I(2,3);
1250
1251     I31 = I(3,1);
1252     I32 = I(3,2);
1253     I33 = I(3,3);
1254
1255     GProp_PrincipalProps Pr = System.PrincipalProperties();
1256     Pr.Moments(Ix,Iy,Iz);
1257   }
1258   catch (Standard_Failure& aFail) {
1259     SetErrorCode(aFail.GetMessageString());
1260     return;
1261   }
1262
1263   SetErrorCode(OK);
1264 }
1265
1266 //=============================================================================
1267 /*!
1268  *  GetBoundingBox
1269  */
1270 //=============================================================================
1271 void GEOMImpl_IMeasureOperations::GetBoundingBox
1272                                      (Handle(GEOM_Object) theShape,
1273                                       const Standard_Boolean precise,
1274                                       Standard_Real& Xmin, Standard_Real& Xmax,
1275                                       Standard_Real& Ymin, Standard_Real& Ymax,
1276                                       Standard_Real& Zmin, Standard_Real& Zmax)
1277 {
1278   SetErrorCode(KO);
1279
1280   if (theShape.IsNull()) return;
1281
1282   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1283   if (aRefShape.IsNull()) return;
1284
1285   TopoDS_Shape aShape = aRefShape->GetValue();
1286   if (aShape.IsNull()) {
1287     SetErrorCode("The Objects has NULL Shape");
1288     return;
1289   }
1290
1291   //Compute the parameters
1292   Bnd_Box B;
1293
1294   try {
1295     OCC_CATCH_SIGNALS;
1296     BRepBuilderAPI_Copy aCopyTool (aShape);
1297     if (!aCopyTool.IsDone()) {
1298       SetErrorCode("GetBoundingBox Error: Bad shape detected");
1299       return;
1300     }
1301
1302     aShape = aCopyTool.Shape();
1303
1304     // remove triangulation to obtain more exact boundaries
1305     BRepTools::Clean(aShape);
1306
1307     BRepBndLib::Add(aShape, B);
1308
1309     if (precise) {
1310       if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
1311         SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
1312         return;
1313       }
1314     }
1315
1316     B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1317   }
1318   catch (Standard_Failure& aFail) {
1319     SetErrorCode(aFail.GetMessageString());
1320     return;
1321   }
1322
1323   SetErrorCode(OK);
1324 }
1325
1326 //=============================================================================
1327 /*!
1328  *  GetBoundingBox
1329  */
1330 //=============================================================================
1331 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
1332                                                 (Handle(GEOM_Object) theShape,
1333                                                  const Standard_Boolean precise)
1334 {
1335   SetErrorCode(KO);
1336
1337   if (theShape.IsNull()) return NULL;
1338
1339   //Add a new BoundingBox object
1340   Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX);
1341
1342   //Add a new BoundingBox function
1343   const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
1344   Handle(GEOM_Function) aFunction =
1345     aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
1346   if (aFunction.IsNull()) return NULL;
1347
1348   //Check if the function is set correctly
1349   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1350
1351   GEOMImpl_IMeasure aCI (aFunction);
1352
1353   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1354   if (aRefShape.IsNull()) return NULL;
1355
1356   aCI.SetBase(aRefShape);
1357
1358   //Compute the BoundingBox value
1359   try {
1360     OCC_CATCH_SIGNALS;
1361     if (!GetSolver()->ComputeFunction(aFunction)) {
1362       SetErrorCode("Measure driver failed to compute a bounding box");
1363       return NULL;
1364     }
1365   }
1366   catch (Standard_Failure& aFail) {
1367     SetErrorCode(aFail.GetMessageString());
1368     return NULL;
1369   }
1370
1371   //Make a Python command
1372   GEOM::TPythonDump aPd(aFunction);
1373   
1374   aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
1375
1376   if (precise) {
1377     aPd << ", True";
1378   }
1379
1380   aPd << ")";
1381
1382   SetErrorCode(OK);
1383   return aBnd;
1384 }
1385
1386 //=============================================================================
1387 /*!
1388  *  GetTolerance
1389  */
1390 //=============================================================================
1391 void GEOMImpl_IMeasureOperations::GetTolerance
1392                                (Handle(GEOM_Object) theShape,
1393                                 Standard_Real& FaceMin, Standard_Real& FaceMax,
1394                                 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1395                                 Standard_Real& VertMin, Standard_Real& VertMax)
1396 {
1397   SetErrorCode(KO);
1398
1399   if (theShape.IsNull()) return;
1400
1401   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1402   if (aRefShape.IsNull()) return;
1403
1404   TopoDS_Shape aShape = aRefShape->GetValue();
1405   if (aShape.IsNull()) {
1406     SetErrorCode("The Objects has NULL Shape");
1407     return;
1408   }
1409
1410   //Compute the parameters
1411   Standard_Real T;
1412   FaceMin = EdgeMin = VertMin = RealLast();
1413   FaceMax = EdgeMax = VertMax = -RealLast();
1414
1415   try {
1416     OCC_CATCH_SIGNALS;
1417     for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1418       TopoDS_Face Face = TopoDS::Face(ExF.Current());
1419       T = BRep_Tool::Tolerance(Face);
1420       if (T > FaceMax)
1421         FaceMax = T;
1422       if (T < FaceMin)
1423         FaceMin = T;
1424     }
1425     for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1426       TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1427       T = BRep_Tool::Tolerance(Edge);
1428       if (T > EdgeMax)
1429         EdgeMax = T;
1430       if (T < EdgeMin)
1431         EdgeMin = T;
1432     }
1433     for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1434       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1435       T = BRep_Tool::Tolerance(Vertex);
1436       if (T > VertMax)
1437         VertMax = T;
1438       if (T < VertMin)
1439         VertMin = T;
1440     }
1441   }
1442   catch (Standard_Failure& aFail) {
1443     SetErrorCode(aFail.GetMessageString());
1444     return;
1445   }
1446
1447   SetErrorCode(OK);
1448 }
1449
1450 //=============================================================================
1451 /*!
1452  *  CheckShape
1453  */
1454 //=============================================================================
1455 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object)     theShape,
1456                                               const Standard_Boolean  theIsCheckGeom,
1457                                               std::list<ShapeError>  &theErrors)
1458 {
1459   SetErrorCode(KO);
1460   theErrors.clear();
1461
1462   if (theShape.IsNull()) return false;
1463
1464   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1465   if (aRefShape.IsNull()) return false;
1466
1467   TopoDS_Shape aShape = aRefShape->GetValue();
1468   if (aShape.IsNull()) {
1469     SetErrorCode("The Objects has NULL Shape");
1470     return false;
1471   }
1472
1473   //Compute the parameters
1474   bool isValid = false;
1475   try {
1476     OCC_CATCH_SIGNALS;
1477     BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1478     if (ana.IsValid()) {
1479       isValid = true;
1480     } else {
1481       FillErrors(ana, aShape, theErrors);
1482     }
1483   }
1484   catch (Standard_Failure& aFail) {
1485     SetErrorCode(aFail.GetMessageString());
1486     return false;
1487   }
1488
1489   SetErrorCode(OK);
1490   return isValid;
1491 }
1492
1493 //=============================================================================
1494 /*!
1495  *  PrintShapeErrors
1496  */
1497 //=============================================================================
1498 TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
1499                                  (Handle(GEOM_Object)          theShape,
1500                                   const std::list<ShapeError> &theErrors)
1501 {
1502   TCollection_AsciiString aDump;
1503
1504   if (theShape.IsNull()) {
1505     return aDump;
1506   }
1507
1508   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1509
1510   if (aRefShape.IsNull()) {
1511     return aDump;
1512   }
1513
1514   TopoDS_Shape aShape = aRefShape->GetValue();
1515
1516   if (aShape.IsNull()) {
1517     SetErrorCode("The Objects has NULL Shape");
1518     return aDump;
1519   }
1520
1521   if (!theErrors.empty()) {
1522     // The shape is not valid. Prepare errors for dump.
1523     TopTools_IndexedMapOfShape anIndices;
1524     std::list<ShapeError>::const_iterator anIter = theErrors.begin();
1525     Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1526     nbv = nbe = nbw = nbf = nbs = nbo = 0;
1527
1528     // Map sub-shapes and their indices
1529     TopExp::MapShapes(aShape, anIndices);
1530
1531     const Standard_Integer aNbSubShapes = anIndices.Extent();
1532     TColStd_MapOfInteger   aMapPbInd;
1533
1534     aDump += " -- The Shape has problems :\n";
1535     aDump += "  Check                                    Count\n";
1536     aDump += " ------------------------------------------------\n";
1537
1538     for (; anIter != theErrors.end(); anIter++) {
1539       Standard_Integer aNbShapes = anIter->incriminated.size();
1540
1541       switch(anIter->error) {
1542       case BRepCheck_InvalidPointOnCurve:
1543         aDump += "  Invalid Point on Curve ................... ";
1544         break;
1545       case BRepCheck_InvalidPointOnCurveOnSurface:
1546         aDump += "  Invalid Point on CurveOnSurface .......... ";
1547         break;
1548       case BRepCheck_InvalidPointOnSurface:
1549         aDump += "  Invalid Point on Surface ................. ";
1550         break;
1551       case BRepCheck_No3DCurve:
1552         aDump += "  No 3D Curve .............................. ";
1553         break;
1554       case BRepCheck_Multiple3DCurve:
1555         aDump += "  Multiple 3D Curve ........................ ";
1556         break;
1557       case BRepCheck_Invalid3DCurve:
1558         aDump += "  Invalid 3D Curve ......................... ";
1559         break;
1560       case BRepCheck_NoCurveOnSurface:
1561         aDump += "  No Curve on Surface ...................... ";
1562         break;
1563       case BRepCheck_InvalidCurveOnSurface:
1564         aDump += "  Invalid Curve on Surface ................. ";
1565         break;
1566       case BRepCheck_InvalidCurveOnClosedSurface:
1567         aDump += "  Invalid Curve on closed Surface .......... ";
1568         break;
1569       case BRepCheck_InvalidSameRangeFlag:
1570         aDump += "  Invalid SameRange Flag ................... ";
1571         break;
1572       case BRepCheck_InvalidSameParameterFlag:
1573         aDump += "  Invalid SameParameter Flag ............... ";
1574         break;
1575       case BRepCheck_InvalidDegeneratedFlag:
1576         aDump += "  Invalid Degenerated Flag ................. ";
1577         break;
1578       case BRepCheck_FreeEdge:
1579         aDump += "  Free Edge ................................ ";
1580         break;
1581       case BRepCheck_InvalidMultiConnexity:
1582         aDump += "  Invalid MultiConnexity ................... ";
1583         break;
1584       case BRepCheck_InvalidRange:
1585         aDump += "  Invalid Range ............................ ";
1586         break;
1587       case BRepCheck_EmptyWire:
1588         aDump += "  Empty Wire ............................... ";
1589         break;
1590       case BRepCheck_RedundantEdge:
1591         aDump += "  Redundant Edge ........................... ";
1592         break;
1593       case BRepCheck_SelfIntersectingWire:
1594         aDump += "  Self Intersecting Wire ................... ";
1595         break;
1596       case BRepCheck_NoSurface:
1597         aDump += "  No Surface ............................... ";
1598         break;
1599       case BRepCheck_InvalidWire:
1600         aDump += "  Invalid Wire ............................. ";
1601         break;
1602       case BRepCheck_RedundantWire:
1603         aDump += "  Redundant Wire ........................... ";
1604         break;
1605       case BRepCheck_IntersectingWires:
1606         aDump += "  Intersecting Wires ....................... ";
1607         break;
1608       case BRepCheck_InvalidImbricationOfWires:
1609         aDump += "  Invalid Imbrication of Wires ............. ";
1610         break;
1611       case BRepCheck_EmptyShell:
1612         aDump += "  Empty Shell .............................. ";
1613         break;
1614       case BRepCheck_RedundantFace:
1615         aDump += "  Redundant Face ........................... ";
1616         break;
1617       case BRepCheck_UnorientableShape:
1618         aDump += "  Unorientable Shape ....................... ";
1619         break;
1620       case BRepCheck_NotClosed:
1621         aDump += "  Not Closed ............................... ";
1622         break;
1623       case BRepCheck_NotConnected:
1624         aDump += "  Not Connected ............................ ";
1625         break;
1626       case BRepCheck_SubshapeNotInShape:
1627         aDump += "  Sub-shape not in Shape ................... ";
1628         break;
1629       case BRepCheck_BadOrientation:
1630         aDump += "  Bad Orientation .......................... ";
1631         break;
1632       case BRepCheck_BadOrientationOfSubshape:
1633         aDump += "  Bad Orientation of Sub-shape ............. ";
1634         break;
1635       case BRepCheck_InvalidToleranceValue:
1636         aDump += "  Invalid Tolerance Value .................. ";
1637         break;
1638       case BRepCheck_CheckFail:
1639         aDump += "  Check Shape Failure ...................... ";
1640         break;
1641       default:
1642         break;
1643       }
1644
1645       aDump += TCollection_AsciiString(aNbShapes) + "\n";
1646
1647       // Count types of shape.
1648       std::list<int>::const_iterator aShIter = anIter->incriminated.begin();
1649
1650       for (; aShIter != anIter->incriminated.end(); aShIter++) {
1651         const Standard_Integer anIndex = *aShIter;
1652
1653         if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) {
1654           const TopoDS_Shape     &aSubShape = anIndices.FindKey(anIndex);
1655           const TopAbs_ShapeEnum  aType     = aSubShape.ShapeType();
1656
1657           switch (aType) {
1658             case TopAbs_VERTEX : nbv++; break;
1659             case TopAbs_EDGE   : nbe++; break;
1660             case TopAbs_WIRE   : nbw++; break;
1661             case TopAbs_FACE   : nbf++; break;
1662             case TopAbs_SHELL  : nbs++; break;
1663             case TopAbs_SOLID  : nbo++; break;
1664             default            : break;
1665           }
1666         }
1667       }
1668     }
1669
1670     const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo;
1671     aDump += " ------------------------------------------------\n";
1672     aDump += "*** Shapes with problems : ";
1673     aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n";
1674
1675     if (nbv > 0) {
1676       aDump += "VERTEX : ";
1677       if (nbv < 10) aDump += " ";
1678       aDump += TCollection_AsciiString(nbv) + "\n";
1679     }
1680     if (nbe > 0) {
1681       aDump += "EDGE   : ";
1682       if (nbe < 10) aDump += " ";
1683       aDump += TCollection_AsciiString(nbe) + "\n";
1684     }
1685     if (nbw > 0) {
1686       aDump += "WIRE   : ";
1687       if (nbw < 10) aDump += " ";
1688       aDump += TCollection_AsciiString(nbw) + "\n";
1689     }
1690     if (nbf > 0) {
1691       aDump += "FACE   : ";
1692       if (nbf < 10) aDump += " ";
1693       aDump += TCollection_AsciiString(nbf) + "\n";
1694     }
1695     if (nbs > 0) {
1696       aDump += "SHELL  : ";
1697       if (nbs < 10) aDump += " ";
1698       aDump += TCollection_AsciiString(nbs) + "\n";
1699     }
1700     if (nbo > 0) {
1701       aDump += "SOLID  : ";
1702       if (nbo < 10) aDump += " ";
1703       aDump += TCollection_AsciiString(nbo) + "\n";
1704     }
1705   }
1706
1707   return aDump;
1708 }
1709
1710 //=============================================================================
1711 /*!
1712  *  CheckSelfIntersections
1713  */
1714 //=============================================================================
1715 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
1716                          (Handle(GEOM_Object)                 theShape,
1717                           const SICheckLevel                  theCheckLevel,
1718                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1719 {
1720   SetErrorCode(KO);
1721
1722   if (theIntersections.IsNull())
1723     theIntersections = new TColStd_HSequenceOfInteger;
1724   else
1725     theIntersections->Clear();
1726
1727   if (theShape.IsNull())
1728     return false;
1729
1730   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1731   if (aRefShape.IsNull()) return false;
1732
1733   TopoDS_Shape aShape = aRefShape->GetValue();
1734   if (aShape.IsNull()) return false;
1735
1736   // 0. Prepare data
1737   TopoDS_Shape aScopy;
1738   //
1739   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1740   //
1741   // Map sub-shapes and their indices
1742   TopTools_IndexedMapOfShape anIndices;
1743   TopExp::MapShapes(aScopy, anIndices);
1744
1745   TopTools_ListOfShape aLCS;
1746   aLCS.Append(aScopy);
1747   //
1748   BOPAlgo_CheckerSI aCSI; // checker of self-interferences
1749   aCSI.SetArguments(aLCS);
1750   aCSI.SetLevelOfCheck(theCheckLevel);
1751
1752   // 1. Launch the checker
1753   aCSI.Perform();
1754   Standard_Boolean iErr = aCSI.HasErrors();
1755
1756   //
1757   Standard_Integer aNbS, n1, n2;
1758   BOPDS_MapIteratorOfMapOfPair aItMPK;
1759   //
1760   // 2. Take the shapes from DS
1761   const BOPDS_DS& aDS = aCSI.DS();
1762   aNbS=aDS.NbShapes();
1763   //
1764   // 3. Get the pairs of interfered shapes
1765   const BOPDS_MapOfPair& aMPK=aDS.Interferences();
1766   aItMPK.Initialize(aMPK);
1767   for (; aItMPK.More(); aItMPK.Next()) {
1768     const BOPDS_Pair& aPK=aItMPK.Value();
1769     aPK.Indices(n1, n2);
1770     //
1771     if (n1 > aNbS || n2 > aNbS){
1772       return false; // Error
1773     }
1774     const TopoDS_Shape& aS1 = aDS.Shape(n1);
1775     const TopoDS_Shape& aS2 = aDS.Shape(n2);
1776
1777     theIntersections->Append(anIndices.FindIndex(aS1));
1778     theIntersections->Append(anIndices.FindIndex(aS2));
1779   }
1780
1781   if (!iErr) {
1782     SetErrorCode(OK);
1783   }
1784
1785   return theIntersections->IsEmpty();
1786 }
1787
1788 //=============================================================================
1789 /*!
1790  *  CheckSelfIntersectionsFast
1791  */
1792 //=============================================================================
1793 bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
1794                          (Handle(GEOM_Object) theShape,
1795                           float theDeflection, double theTolerance,
1796                           Handle(TColStd_HSequenceOfInteger)& theIntersections)
1797 {
1798   SetErrorCode(KO);
1799
1800   if (theIntersections.IsNull())
1801     theIntersections = new TColStd_HSequenceOfInteger;
1802   else
1803     theIntersections->Clear();
1804
1805   if (theShape.IsNull())
1806     return false;
1807
1808   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1809   if (aRefShape.IsNull()) return false;
1810
1811   TopoDS_Shape aShape = aRefShape->GetValue();
1812   if (aShape.IsNull()) return false;
1813
1814   // Prepare data
1815   TopoDS_Shape aScopy;
1816
1817   GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1818   GEOMUtils::MeshShape(aScopy, theDeflection);
1819
1820   // Map sub-shapes and their indices
1821   TopTools_IndexedMapOfShape anIndices;
1822   TopExp::MapShapes(aScopy, anIndices);
1823
1824   // Checker of fast interferences
1825   BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
1826
1827   // Launch the checker
1828   aTool.Perform();
1829   
1830   const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
1831   
1832   std::set<Standard_Integer> processed;
1833   
1834   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
1835     Standard_Integer idxLeft = it.Key();
1836     if (processed.count(idxLeft) > 0) continue; // already added
1837     processed.insert(idxLeft);
1838     const TColStd_PackedMapOfInteger& overlaps = it.Value();
1839     for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
1840       Standard_Integer idxRight = subit.Key();
1841       if (processed.count(idxRight) > 0) continue; // already added
1842       const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
1843       const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
1844       theIntersections->Append(anIndices.FindIndex(aS1));
1845       theIntersections->Append(anIndices.FindIndex(aS2));
1846     }
1847   }
1848
1849   if (aTool.IsDone())
1850     SetErrorCode(OK);
1851
1852   return theIntersections->IsEmpty();
1853 }
1854
1855 //=============================================================================
1856 /*!
1857  *  CheckBOPArguments
1858  */
1859 //=============================================================================
1860 bool GEOMImpl_IMeasureOperations::CheckBOPArguments
1861                                       (const Handle(GEOM_Object) &theShape)
1862 {
1863   SetErrorCode(KO);
1864
1865   if (theShape.IsNull()) {
1866     return false;
1867   }
1868
1869   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1870
1871   if (aRefShape.IsNull()) {
1872     return false;
1873   }
1874
1875   TopoDS_Shape aShape = aRefShape->GetValue();
1876
1877   if (aShape.IsNull()) {
1878     return false;
1879   }
1880
1881   //Compute the parameters
1882   bool isValid = GEOMUtils::CheckBOPArguments(aShape);
1883
1884   SetErrorCode(OK);
1885
1886   return isValid;
1887 }
1888
1889 //=============================================================================
1890 /*!
1891  *  FastIntersect
1892  */
1893 //=============================================================================
1894 bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1895                                                  double theTolerance, float theDeflection,
1896                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections1,
1897                                                  Handle(TColStd_HSequenceOfInteger)& theIntersections2)
1898 {
1899   SetErrorCode(KO);
1900   bool isGood = false;
1901
1902   if (theIntersections1.IsNull())
1903     theIntersections1 = new TColStd_HSequenceOfInteger;
1904   else
1905     theIntersections1->Clear();
1906
1907   if (theIntersections2.IsNull())
1908     theIntersections2 = new TColStd_HSequenceOfInteger;
1909   else
1910     theIntersections2->Clear();
1911
1912   if (theShape1.IsNull() || theShape2.IsNull()) {
1913     SetErrorCode("Objects have NULL Shape");
1914     return isGood;
1915   }
1916
1917   if (theShape1 == theShape2) {
1918     SetErrorCode("Objects are equal");
1919     return isGood;
1920   }
1921   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1922   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1923   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
1924
1925   TopoDS_Shape aShape1 = aRefShape1->GetValue();
1926   TopoDS_Shape aShape2 = aRefShape2->GetValue();
1927   if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
1928
1929   // 0. Prepare data
1930   TopoDS_Shape aScopy1, aScopy2;
1931   GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
1932   GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
1933
1934   GEOMUtils::MeshShape(aScopy1, theDeflection);
1935   GEOMUtils::MeshShape(aScopy2, theDeflection);
1936   //
1937   // Map sub-shapes and their indices
1938   TopTools_IndexedMapOfShape anIndices1, anIndices2;
1939   TopExp::MapShapes(aScopy1, anIndices1);
1940   TopExp::MapShapes(aScopy2, anIndices2);
1941
1942   TopTools_ListOfShape aLCS1, aLCS2;
1943   aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
1944   //
1945   BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
1946   aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
1947   aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
1948
1949   // 1. Launch the checker
1950   aBSP.Perform();
1951  
1952   // 2. Get sets of IDs of overlapped faces
1953   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
1954   {
1955     const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
1956     theIntersections1->Append(anIndices1.FindIndex(aS1));
1957   }
1958   
1959   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
1960   {
1961     const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
1962     theIntersections2->Append(anIndices2.FindIndex(aS2));
1963   }
1964
1965   isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
1966
1967   if (aBSP.IsDone())
1968     SetErrorCode(OK);
1969
1970   return isGood;
1971 }
1972
1973 //=============================================================================
1974 /*!
1975  *  IsGoodForSolid
1976  */
1977 //=============================================================================
1978 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1979 {
1980   SetErrorCode(KO);
1981
1982   TCollection_AsciiString aRes = "";
1983
1984   if (theShape.IsNull()) {
1985     aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1986   }
1987   else {
1988     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1989     if (aRefShape.IsNull()) {
1990       aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1991     }
1992     else {
1993       TopoDS_Shape aShape = aRefShape->GetValue();
1994       if (aShape.IsNull()) {
1995         aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1996       }
1997       else {
1998         if (aShape.ShapeType() == TopAbs_COMPOUND) {
1999           TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2000           if (It.More()) aShape = It.Value();
2001         }
2002         if (aShape.ShapeType() == TopAbs_SHELL) {
2003           BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
2004           if (chkShell.Closed() == BRepCheck_NotClosed) {
2005             aRes = "WRN_SHAPE_UNCLOSED";
2006           }
2007         }
2008         else {
2009           aRes = "WRN_SHAPE_NOT_SHELL";
2010         }
2011       }
2012     }
2013   }
2014
2015   if (aRes.IsEmpty())
2016     SetErrorCode(OK);
2017
2018   return aRes;
2019 }
2020
2021 //=============================================================================
2022 /*!
2023  *  WhatIs
2024  */
2025 //=============================================================================
2026 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
2027 {
2028   SetErrorCode(KO);
2029
2030   TCollection_AsciiString Astr;
2031
2032   if (theShape.IsNull()) return Astr;
2033
2034   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2035   if (aRefShape.IsNull()) return Astr;
2036
2037   TopoDS_Shape aShape = aRefShape->GetValue();
2038   if (aShape.IsNull()) {
2039     SetErrorCode("The Objects has NULL Shape");
2040     return Astr;
2041   }
2042
2043   //Compute the parameters
2044   if (aShape.ShapeType() == TopAbs_EDGE) {
2045     if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
2046       Astr = Astr + " It is a degenerated edge \n";
2047     }
2048   }
2049
2050   Astr = Astr + " Number of sub-shapes : \n";
2051
2052   try {
2053     OCC_CATCH_SIGNALS;
2054     int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
2055     for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
2056       nbTypes[iType] = 0;
2057       nbFlatType[iType] = 0;
2058     }
2059     nbTypes[aShape.ShapeType()]++;
2060
2061     TopTools_MapOfShape aMapOfShape;
2062     aMapOfShape.Add(aShape);
2063     TopTools_ListOfShape aListOfShape;
2064     aListOfShape.Append(aShape);
2065
2066     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2067     for (; itL.More(); itL.Next()) {
2068       TopoDS_Shape sp = itL.Value();
2069       TopoDS_Iterator it (sp);
2070       for (; it.More(); it.Next()) {
2071         TopoDS_Shape s = it.Value();
2072         if (aMapOfShape.Add(s)) {
2073           aListOfShape.Append(s);
2074           nbTypes[s.ShapeType()]++;
2075           if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
2076             nbFlatType[s.ShapeType()]++;
2077           }
2078         }
2079       }
2080     }
2081
2082     Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
2083     Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
2084     Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
2085     Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
2086     Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
2087     Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
2088     Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
2089     Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
2090     Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
2091
2092     if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
2093       Astr = Astr + " --------------------- \n Flat content : \n";
2094       if (nbFlatType[TopAbs_VERTEX] > 0)
2095         Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
2096       if (nbFlatType[TopAbs_EDGE] > 0)
2097         Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
2098       if (nbFlatType[TopAbs_WIRE] > 0)
2099         Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
2100       if (nbFlatType[TopAbs_FACE] > 0)
2101         Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
2102       if (nbFlatType[TopAbs_SHELL] > 0)
2103         Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
2104       if (nbFlatType[TopAbs_SOLID] > 0)
2105         Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
2106     }
2107   }
2108   catch (Standard_Failure& aFail) {
2109     SetErrorCode(aFail.GetMessageString());
2110     return Astr;
2111   }
2112
2113   SetErrorCode(OK);
2114   return Astr;
2115 }
2116
2117 //=============================================================================
2118 /*!
2119  *  AreCoordsInside
2120  */
2121 //=============================================================================
2122 std::vector<bool>
2123 GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object)        theShape,
2124                                              const std::vector<double>& coords,
2125                                              double                     tolerance)
2126 {
2127   std::vector<bool> isInsideRes;
2128   if (!theShape.IsNull()) {
2129     Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2130     if (!aRefShape.IsNull()) {
2131       TopoDS_Shape aShape = aRefShape->GetValue();
2132       if (!aShape.IsNull())
2133       {
2134         TopTools_IndexedMapOfShape mapShape;
2135         {
2136           TopExp_Explorer anExp;
2137           for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() )
2138             mapShape.Add( anExp.Current() );
2139           for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() )
2140             mapShape.Add( anExp.Current() );
2141           for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() )
2142             mapShape.Add( anExp.Current() );
2143           for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() )
2144             mapShape.Add( anExp.Current() ); //// ?????????
2145         }
2146         size_t nb_points = coords.size()/3, nb_points_inside = 0;
2147         isInsideRes.resize( nb_points, false );
2148
2149         for ( int iS = 1; iS <= mapShape.Extent(); ++iS )
2150         {
2151           if ( nb_points_inside == nb_points )
2152             break;
2153           aShape = mapShape( iS );
2154           switch ( aShape.ShapeType() ) {
2155           case TopAbs_SOLID:
2156           {
2157             BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape ));
2158             for ( size_t i = 0; i < nb_points; i++)
2159             {
2160               if ( isInsideRes[ i ]) continue;
2161               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2162               SC.Perform( aPnt, tolerance );
2163               isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ));
2164               nb_points_inside += isInsideRes[ i ];
2165             }
2166             break;
2167           }
2168           case TopAbs_FACE:
2169           {
2170             Standard_Real u1,u2,v1,v2;
2171             const TopoDS_Face&   face = TopoDS::Face( aShape );
2172             Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
2173             surf->Bounds( u1,u2,v1,v2 );
2174             GeomAPI_ProjectPointOnSurf project;
2175             project.Init(surf, u1,u2, v1,v2, tolerance );
2176             for ( size_t i = 0; i < nb_points; i++)
2177             {
2178               if ( isInsideRes[ i ]) continue;
2179               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2180               project.Perform( aPnt );
2181               if ( project.IsDone() &&
2182                    project.NbPoints() > 0 &&
2183                    project.LowerDistance() <= tolerance )
2184               {
2185                 Standard_Real u, v;
2186                 project.LowerDistanceParameters(u, v);
2187                 gp_Pnt2d uv( u, v );
2188                 BRepClass_FaceClassifier FC ( face, uv, tolerance );
2189                 isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON ));
2190                 nb_points_inside += isInsideRes[ i ];
2191               }
2192             }
2193             break;
2194           }
2195           case TopAbs_EDGE:
2196           {
2197             Standard_Real f,l;
2198             const TopoDS_Edge&  edge = TopoDS::Edge( aShape );
2199             Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
2200             GeomAPI_ProjectPointOnCurve project;
2201             project.Init( curve, f, l );
2202             for ( size_t i = 0; i < nb_points; i++)
2203             {
2204               if ( isInsideRes[ i ]) continue;
2205               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2206               project.Perform( aPnt );
2207               isInsideRes[ i ] = ( project.NbPoints() > 0 &&
2208                                    project.LowerDistance() <= tolerance );
2209               nb_points_inside += isInsideRes[ i ];
2210             }
2211             break;
2212           }
2213           case TopAbs_VERTEX:
2214           {
2215             gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ));
2216             for ( size_t i = 0; i < nb_points; i++)
2217             {
2218               if ( isInsideRes[ i ]) continue;
2219               gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2220               isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance );
2221               nb_points_inside += isInsideRes[ i ];
2222             }
2223             break;
2224           }
2225           default:;
2226           } // switch ( aShape.ShapeType() )
2227         }
2228       }
2229     }
2230   }
2231   return isInsideRes;
2232 }
2233
2234 //=============================================================================
2235 /*!
2236  *  GetMinDistance
2237  */
2238 //=============================================================================
2239 Standard_Real
2240 GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
2241                                              Handle(GEOM_Object) theShape2,
2242                                              Standard_Real& X1,
2243                                              Standard_Real& Y1,
2244                                              Standard_Real& Z1,
2245                                              Standard_Real& X2,
2246                                              Standard_Real& Y2,
2247                                              Standard_Real& Z2)
2248 {
2249   SetErrorCode(KO);
2250   Standard_Real MinDist = 1.e9;
2251
2252   if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
2253
2254   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2255   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2256   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
2257
2258   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2259   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2260   if (aShape1.IsNull() || aShape2.IsNull()) {
2261     SetErrorCode("One of Objects has NULL Shape");
2262     return MinDist;
2263   }
2264
2265   //Compute the parameters
2266   try {
2267     OCC_CATCH_SIGNALS;
2268
2269     gp_Pnt aPnt1, aPnt2;
2270
2271     MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
2272
2273     if (MinDist >= 0.0) {
2274       aPnt1.Coord(X1, Y1, Z1);
2275       aPnt2.Coord(X2, Y2, Z2);
2276     } else {
2277       return MinDist;
2278     }
2279   }
2280   catch (Standard_Failure& aFail) {
2281     SetErrorCode(aFail.GetMessageString());
2282     return MinDist;
2283   }
2284
2285   SetErrorCode(OK);
2286   return MinDist;
2287 }
2288
2289 //=======================================================================
2290 /*!
2291  *  Get coordinates of closest points of two shapes
2292  */
2293 //=======================================================================
2294 Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1,
2295                                                              Handle(GEOM_Object) theShape2,
2296                                                              Handle(TColStd_HSequenceOfReal)& theDoubles)
2297 {
2298   SetErrorCode(KO);
2299   Standard_Integer nbSolutions = 0;
2300
2301   if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions;
2302
2303   Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2304   Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2305   if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions;
2306
2307   TopoDS_Shape aShape1 = aRefShape1->GetValue();
2308   TopoDS_Shape aShape2 = aRefShape2->GetValue();
2309   if (aShape1.IsNull() || aShape2.IsNull()) {
2310     SetErrorCode("One of Objects has NULL Shape");
2311     return nbSolutions;
2312   }
2313
2314   // Compute the extremities
2315   try {
2316     OCC_CATCH_SIGNALS;
2317
2318     // skl 30.06.2008
2319     // additional workaround for bugs 19899, 19908 and 19910 from Mantis
2320     gp_Pnt P1s, P2s;
2321     double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s);
2322     bool singularBetter = dist >= 0;
2323
2324     BRepExtrema_DistShapeShape dst (aShape1, aShape2);
2325     if (dst.IsDone()) {
2326       nbSolutions = dst.NbSolution();
2327       if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2328
2329       gp_Pnt P1, P2;
2330       for (int i = 1; i <= nbSolutions; i++) {
2331         P1 = dst.PointOnShape1(i);
2332         P2 = dst.PointOnShape2(i);
2333         
2334         theDoubles->Append(P1.X());
2335         theDoubles->Append(P1.Y());
2336         theDoubles->Append(P1.Z());
2337         theDoubles->Append(P2.X());
2338         theDoubles->Append(P2.Y());
2339         theDoubles->Append(P2.Z());
2340         
2341         Standard_Real Dist = P1.Distance(P2);
2342         singularBetter = singularBetter && dist < Dist;
2343       }
2344     }
2345
2346     if (singularBetter) {
2347       if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2348       else theDoubles->Clear();
2349
2350       nbSolutions = 1;
2351     
2352       theDoubles->Append(P1s.X());
2353       theDoubles->Append(P1s.Y());
2354       theDoubles->Append(P1s.Z());
2355       theDoubles->Append(P2s.X());
2356       theDoubles->Append(P2s.Y());
2357       theDoubles->Append(P2s.Z());
2358     }
2359   }
2360   catch (Standard_Failure& aFail) {
2361     SetErrorCode(aFail.GetMessageString());
2362     return nbSolutions;
2363   }
2364
2365   SetErrorCode(OK);
2366   return nbSolutions;
2367 }
2368
2369 //=======================================================================
2370 /*!
2371  *  Get coordinates of point
2372  */
2373 //=======================================================================
2374 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
2375                         Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
2376 {
2377   SetErrorCode(KO);
2378
2379   if (theShape.IsNull())
2380     return;
2381
2382   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2383   if (aRefShape.IsNull())
2384     return;
2385
2386   TopoDS_Shape aShape = aRefShape->GetValue();
2387   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
2388   {
2389     SetErrorCode( "Shape must be a vertex" );
2390     return;
2391   }
2392
2393   try {
2394     OCC_CATCH_SIGNALS;
2395     gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
2396     theX = aPnt.X();
2397     theY = aPnt.Y();
2398     theZ = aPnt.Z();
2399
2400     SetErrorCode(OK);
2401   }
2402   catch (Standard_Failure& aFail)
2403   {
2404     SetErrorCode( aFail.GetMessageString() );
2405   }
2406 }
2407
2408 //=======================================================================
2409 /*!
2410  *  Compute angle (in degrees) between two lines
2411  */
2412 //=======================================================================
2413 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
2414                                                      Handle(GEOM_Object) theLine2)
2415 {
2416   if (theLine1->GetType() == GEOM_VECTOR &&
2417       theLine2->GetType() == GEOM_VECTOR)
2418     return GetAngleBtwVectors(theLine1, theLine2);
2419
2420   SetErrorCode(KO);
2421
2422   Standard_Real anAngle = -1.0;
2423
2424   if (theLine1.IsNull() || theLine2.IsNull())
2425     return anAngle;
2426
2427   Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
2428   Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
2429   if (aRefLine1.IsNull() || aRefLine2.IsNull())
2430     return anAngle;
2431
2432   TopoDS_Shape aLine1 = aRefLine1->GetValue();
2433   TopoDS_Shape aLine2 = aRefLine2->GetValue();
2434   if (aLine1.IsNull() || aLine2.IsNull() ||
2435       aLine1.ShapeType() != TopAbs_EDGE ||
2436       aLine2.ShapeType() != TopAbs_EDGE)
2437   {
2438     SetErrorCode("Two edges must be given");
2439     return anAngle;
2440   }
2441
2442   try {
2443     OCC_CATCH_SIGNALS;
2444     TopoDS_Edge E1 = TopoDS::Edge(aLine1);
2445     TopoDS_Edge E2 = TopoDS::Edge(aLine2);
2446
2447     double fp,lp;
2448     Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2449     Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
2450
2451     if ( C1.IsNull() || C2.IsNull() ||
2452         !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
2453         !C2->IsKind(STANDARD_TYPE(Geom_Line)))
2454     {
2455       SetErrorCode("The edges must be linear");
2456       return anAngle;
2457     }
2458
2459     Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
2460     Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
2461
2462     gp_Lin aLin1 = L1->Lin();
2463     gp_Lin aLin2 = L2->Lin();
2464
2465     anAngle = aLin1.Angle(aLin2);
2466     anAngle *= 180. / M_PI; // convert radians into degrees
2467
2468     if (anAngle > 90.0) {
2469       anAngle = 180.0 - anAngle;
2470     }
2471
2472     SetErrorCode(OK);
2473   }
2474   catch (Standard_Failure& aFail)
2475   {
2476     SetErrorCode(aFail.GetMessageString());
2477   }
2478
2479   return anAngle;
2480 }
2481
2482 //=======================================================================
2483 /*!
2484  *  Compute angle (in degrees) between two vectors
2485  */
2486 //=======================================================================
2487 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
2488                                                                Handle(GEOM_Object) theVec2)
2489 {
2490   SetErrorCode(KO);
2491
2492   Standard_Real anAngle = -1.0;
2493
2494   if (theVec1.IsNull() || theVec2.IsNull())
2495     return anAngle;
2496
2497   if (theVec1->GetType() != GEOM_VECTOR || theVec2->GetType() != GEOM_VECTOR) {
2498     SetErrorCode("Two vectors must be given");
2499     return anAngle;
2500   }
2501
2502   Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2503   Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2504   if (aRefVec1.IsNull() || aRefVec2.IsNull())
2505     return anAngle;
2506
2507   TopoDS_Shape aVec1 = aRefVec1->GetValue();
2508   TopoDS_Shape aVec2 = aRefVec2->GetValue();
2509   if (aVec1.IsNull() || aVec2.IsNull() ||
2510       aVec1.ShapeType() != TopAbs_EDGE ||
2511       aVec2.ShapeType() != TopAbs_EDGE)
2512   {
2513     SetErrorCode("Two edges must be given");
2514     return anAngle;
2515   }
2516
2517   try {
2518     OCC_CATCH_SIGNALS;
2519     TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2520     TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2521
2522     TopoDS_Vertex aP11, aP12, aP21, aP22;
2523     TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2524     TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2525     if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2526       SetErrorCode("Bad edge given");
2527       return anAngle;
2528     }
2529
2530     gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2531     gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2532
2533     anAngle = aV1.Angle(aV2);
2534     anAngle *= 180. / M_PI; // convert radians into degrees
2535
2536     SetErrorCode(OK);
2537   }
2538   catch (Standard_Failure& aFail)
2539   {
2540     SetErrorCode(aFail.GetMessageString());
2541   }
2542
2543   return anAngle;
2544 }
2545
2546
2547 //=============================================================================
2548 /*!
2549  *  PatchFace
2550  */
2551  //=============================================================================
2552 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape)
2553 {
2554   SetErrorCode(KO);
2555
2556   if (theShape.IsNull()) return NULL;
2557
2558   Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE);
2559   Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1);
2560   if (aFunction.IsNull()) return NULL;
2561
2562   //Check if the function is set correctly
2563   if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL;
2564
2565   GEOMImpl_IPatchFace aPI(aFunction);
2566   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2567   if (aRefShape.IsNull()) return NULL;
2568
2569   aPI.SetShape(aRefShape);
2570   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2571
2572   // Perform
2573   try
2574   {
2575     OCC_CATCH_SIGNALS;
2576     if (!GetSolver()->ComputeFunction(aFunction))
2577     {
2578       SetErrorCode("patch face driver failed");
2579       return NULL;
2580     }
2581
2582     // Get result compound and collect all faces into result sequence
2583     TopoDS_Shape aResCompound = aFunction->GetValue();
2584     TopTools_IndexedMapOfShape anIndices;
2585     TopExp::MapShapes(aResCompound, anIndices);
2586
2587     Handle(TColStd_HArray1OfInteger) anArray;
2588     for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next())
2589     {
2590       TopoDS_Shape aValue = anExpW.Value();
2591       anArray = new TColStd_HArray1OfInteger(1, 1);
2592       anArray->SetValue(1, anIndices.FindIndex(aValue));
2593
2594       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray);
2595       if (!anObj.IsNull())
2596       {
2597         aSeq->Append(anObj);
2598       }
2599     }
2600   }
2601   catch (Standard_Failure& aFail)
2602   {
2603     SetErrorCode(aFail.GetMessageString());
2604     return aSeq;
2605   }
2606
2607   //Make a Python command
2608   GEOM::TPythonDump(aFunction, true)
2609     << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")";
2610
2611   SetErrorCode(OK);
2612   return aSeq;
2613 }
2614
2615 //=============================================================================
2616 /*!
2617  *  CurveCurvatureByParam
2618  */
2619 //=============================================================================
2620 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2621                         (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2622 {
2623   SetErrorCode(KO);
2624   Standard_Real aRes = -1.0;
2625
2626   if(theCurve.IsNull()) return aRes;
2627
2628   Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2629   if(aRefShape.IsNull()) return aRes;
2630
2631   TopoDS_Shape aShape = aRefShape->GetValue();
2632   if(aShape.IsNull()) {
2633     SetErrorCode("One of Objects has NULL Shape");
2634     return aRes;
2635   }
2636
2637   Standard_Real aFP, aLP, aP;
2638   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2639   aP = aFP + (aLP - aFP) * theParam;
2640
2641   if(aCurve.IsNull()) return aRes;
2642
2643   //Compute curvature
2644   try {
2645     OCC_CATCH_SIGNALS;
2646     GeomLProp_CLProps Prop = GeomLProp_CLProps
2647       (aCurve, aP, 2, Precision::Confusion());
2648     aRes = fabs(Prop.Curvature());
2649     SetErrorCode(OK);
2650   }
2651   catch (Standard_Failure& aFail) {
2652     SetErrorCode(aFail.GetMessageString());
2653     return aRes;
2654   }
2655
2656   if( aRes > Precision::Confusion() )
2657     aRes = 1/aRes;
2658   else
2659     aRes = RealLast();
2660
2661   return aRes;
2662 }
2663
2664
2665 //=============================================================================
2666 /*!
2667  *  CurveCurvatureByPoint
2668  */
2669 //=============================================================================
2670 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2671                    (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2672 {
2673   SetErrorCode(KO);
2674   Standard_Real aRes = -1.0;
2675
2676   if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2677
2678   Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2679   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2680   if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2681
2682   TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2683   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2684   if( anEdge.IsNull() || aPnt.IsNull() ) {
2685     SetErrorCode("One of Objects has NULL Shape");
2686     return aRes;
2687   }
2688
2689   Standard_Real aFP, aLP;
2690   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2691   if(aCurve.IsNull()) return aRes;
2692   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2693
2694   //Compute curvature
2695   try {
2696     OCC_CATCH_SIGNALS;
2697     GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2698     if(PPCurve.NbPoints()>0) {
2699       GeomLProp_CLProps Prop = GeomLProp_CLProps
2700         (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2701       aRes = fabs(Prop.Curvature());
2702       SetErrorCode(OK);
2703     }
2704   }
2705   catch (Standard_Failure& aFail) {
2706     SetErrorCode(aFail.GetMessageString());
2707     return aRes;
2708   }
2709
2710   if( aRes > Precision::Confusion() )
2711     aRes = 1/aRes;
2712   else
2713     aRes = RealLast();
2714
2715   return aRes;
2716 }
2717
2718
2719 //=============================================================================
2720 /*!
2721  *  getSurfaceCurvatures
2722  */
2723 //=============================================================================
2724 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2725                                           (const Handle(Geom_Surface)& aSurf,
2726                                            Standard_Real theUParam,
2727                                            Standard_Real theVParam,
2728                                            Standard_Boolean theNeedMaxCurv)
2729 {
2730   SetErrorCode(KO);
2731   Standard_Real aRes = 1.0;
2732
2733   if (aSurf.IsNull()) return aRes;
2734
2735   try {
2736     OCC_CATCH_SIGNALS;
2737     GeomLProp_SLProps Prop = GeomLProp_SLProps
2738       (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2739     if(Prop.IsCurvatureDefined()) {
2740       if(Prop.IsUmbilic()) {
2741         //cout<<"is umbilic"<<endl;
2742         aRes = fabs(Prop.MeanCurvature());
2743       }
2744       else {
2745         //cout<<"is not umbilic"<<endl;
2746         double c1 = fabs(Prop.MaxCurvature());
2747         double c2 = fabs(Prop.MinCurvature());
2748         if(theNeedMaxCurv)
2749           aRes = Max(c1,c2);
2750         else
2751           aRes = Min(c1,c2);
2752       }
2753       SetErrorCode(OK);
2754     }
2755   }
2756   catch (Standard_Failure& aFail) {
2757     SetErrorCode(aFail.GetMessageString());
2758     return aRes;
2759   }
2760
2761   if( fabs(aRes) > Precision::Confusion() )
2762     aRes = 1/aRes;
2763   else
2764     aRes = RealLast();
2765
2766   return aRes;
2767 }
2768
2769
2770 //=============================================================================
2771 /*!
2772  *  MaxSurfaceCurvatureByParam
2773  */
2774 //=============================================================================
2775 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2776                                                   (Handle(GEOM_Object) theSurf,
2777                                                    Standard_Real& theUParam,
2778                                                    Standard_Real& theVParam)
2779 {
2780   SetErrorCode(KO);
2781   Standard_Real aRes = -1.0;
2782
2783   if (theSurf.IsNull()) return aRes;
2784
2785   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2786   if(aRefShape.IsNull()) return aRes;
2787
2788   TopoDS_Shape aShape = aRefShape->GetValue();
2789   if(aShape.IsNull()) {
2790     SetErrorCode("One of Objects has NULL Shape");
2791     return aRes;
2792   }
2793
2794   TopoDS_Face F = TopoDS::Face(aShape);
2795   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2796
2797   //Compute the parameters
2798   Standard_Real U1,U2,V1,V2;
2799   BRepTools::UVBounds(F,U1,U2,V1,V2);
2800   Standard_Real U = U1 + (U2-U1)*theUParam;
2801   Standard_Real V = V1 + (V2-V1)*theVParam;
2802
2803   return getSurfaceCurvatures(aSurf, U, V, true);
2804 }
2805
2806
2807 //=============================================================================
2808 /*!
2809  *  MaxSurfaceCurvatureByPoint
2810  */
2811 //=============================================================================
2812 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2813                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2814 {
2815   SetErrorCode(KO);
2816   Standard_Real aRes = -1.0;
2817
2818   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2819
2820   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2821   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2822   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2823
2824   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2825   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2826   if( aFace.IsNull() || aPnt.IsNull() ) {
2827     SetErrorCode("One of Objects has NULL Shape");
2828     return 0;
2829   }
2830
2831   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2832   if(aSurf.IsNull()) return aRes;
2833   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2834
2835   //Compute the parameters
2836   ShapeAnalysis_Surface sas(aSurf);
2837   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2838
2839   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2840 }
2841
2842
2843 //=============================================================================
2844 /*!
2845  *  MinSurfaceCurvatureByParam
2846  */
2847 //=============================================================================
2848 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2849                                                   (Handle(GEOM_Object) theSurf,
2850                                                    Standard_Real& theUParam,
2851                                                    Standard_Real& theVParam)
2852 {
2853   SetErrorCode(KO);
2854   Standard_Real aRes = -1.0;
2855
2856   if (theSurf.IsNull()) return aRes;
2857
2858   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2859   if(aRefShape.IsNull()) return aRes;
2860
2861   TopoDS_Shape aShape = aRefShape->GetValue();
2862   if(aShape.IsNull()) {
2863     SetErrorCode("One of Objects has NULL Shape");
2864     return aRes;
2865   }
2866
2867   TopoDS_Face F = TopoDS::Face(aShape);
2868   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2869
2870   //Compute the parameters
2871   Standard_Real U1,U2,V1,V2;
2872   BRepTools::UVBounds(F,U1,U2,V1,V2);
2873   Standard_Real U = U1 + (U2-U1)*theUParam;
2874   Standard_Real V = V1 + (V2-V1)*theVParam;
2875
2876   return getSurfaceCurvatures(aSurf, U, V, false);
2877 }
2878
2879
2880 //=============================================================================
2881 /*!
2882  *  MinSurfaceCurvatureByPoint
2883  */
2884 //=============================================================================
2885 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2886                     (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2887 {
2888   SetErrorCode(KO);
2889   Standard_Real aRes = -1.0;
2890
2891   if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2892
2893   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2894   Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2895   if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2896
2897   TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2898   TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2899   if( aFace.IsNull() || aPnt.IsNull() ) {
2900     SetErrorCode("One of Objects has NULL Shape");
2901     return 0;
2902   }
2903
2904   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2905   if(aSurf.IsNull()) return aRes;
2906   gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2907
2908   //Compute the parameters
2909   ShapeAnalysis_Surface sas(aSurf);
2910   gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2911
2912   return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2913 }
2914
2915 //=============================================================================
2916 /*!
2917  *  SurfaceCurvatureByPointAndDirection
2918  */
2919 //=============================================================================
2920 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirection
2921                                                  (Handle(GEOM_Object) theSurf,
2922                                                   Handle(GEOM_Object) thePoint,
2923                                                   Handle(GEOM_Object) theDirection)
2924 {
2925   SetErrorCode(KO);
2926
2927   if (theSurf.IsNull() || thePoint.IsNull() || theDirection.IsNull()) return NULL;
2928
2929   Handle(GEOM_Function) aSurf = theSurf->GetLastFunction();
2930   Handle(GEOM_Function) aPoint = thePoint->GetLastFunction();
2931   Handle(GEOM_Function) aDirection = theDirection->GetLastFunction();
2932   if (aSurf.IsNull() || aPoint.IsNull() || aDirection.IsNull()) return NULL;
2933
2934   //Add a new CurvatureVector object
2935   //Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_CURVATURE_VEC);
2936   Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_VECTOR);
2937
2938   //Add a new CurvatureVector function
2939   Handle(GEOM_Function) aFunction =
2940     aCV->AddFunction(GEOMImpl_MeasureDriver::GetID(), CURVATURE_VEC_MEASURE);
2941   if (aFunction.IsNull()) return NULL;
2942
2943   //Check if the function is set correctly
2944   if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
2945
2946   GEOMImpl_IMeasure aCI (aFunction);
2947   aCI.SetBase(aSurf);
2948   aCI.SetPoint(aPoint);
2949   aCI.SetDirection(aDirection);
2950
2951   //Compute the CurvatureVector
2952   try {
2953     OCC_CATCH_SIGNALS;
2954     if (!GetSolver()->ComputeFunction(aFunction)) {
2955       SetErrorCode("Measure driver failed to compute a surface curvature");
2956       return NULL;
2957     }
2958   }
2959   catch (Standard_Failure& aFail) {
2960     SetErrorCode(aFail.GetMessageString());
2961     return NULL;
2962   }
2963
2964   //Make a Python command
2965   GEOM::TPythonDump(aFunction) << aCV << " = geompy.CurvatureOnFace(" << theSurf
2966                                << ", " << thePoint << ", " << theDirection << ")";
2967
2968   SetErrorCode(OK);
2969   return aCV;
2970 }
2971
2972 //=============================================================================
2973 /*!
2974  *  XYZtoUV
2975  */
2976  //=============================================================================
2977 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::XYZtoUV
2978                                                   (Handle(GEOM_Object) theSurf,
2979                                                    const Handle(TColStd_HArray1OfReal)& theXYZlist,
2980                                                    bool isNormalized)
2981 {
2982   SetErrorCode(KO);
2983
2984   Handle(TColStd_HArray1OfReal) aRet;
2985
2986   // Check list of coordinates
2987   int nbC = theXYZlist->Length();
2988   int nbP = nbC / 3;
2989   if (nbP * 3 != nbC) {
2990     SetErrorCode("Coordinates list length is not divisible by 3");
2991     return aRet;
2992   }
2993
2994   // Check face
2995   if (theSurf.IsNull()) {
2996     SetErrorCode("The shape is NULL");
2997     return aRet;
2998   }
2999
3000   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
3001   if (aRefShape.IsNull()) {
3002     SetErrorCode("The shape is NULL");
3003     return aRet;
3004   }
3005
3006   TopoDS_Shape aShape = aRefShape->GetValue();
3007   if (aShape.IsNull()) {
3008     SetErrorCode("The shape is NULL");
3009     return aRet;
3010   }
3011
3012   // The shape can be a face, a shell of one face or a compound with one face
3013   TopoDS_Face F;
3014   if (aShape.ShapeType() == TopAbs_FACE) {
3015     F = TopoDS::Face(aShape);
3016   }
3017   else if (aShape.ShapeType() < TopAbs_FACE) {
3018     TopExp_Explorer Exp (aShape, TopAbs_FACE);
3019     if (Exp.More()) {
3020       F = TopoDS::Face(Exp.Current());
3021       Exp.Next();
3022       if (Exp.More()) {
3023         SetErrorCode("There should be only one face");
3024         return aRet;
3025       }
3026     }
3027   }
3028   if (F.IsNull()) {
3029     SetErrorCode("There are no faces");
3030     return aRet;
3031   }
3032
3033   // Face tolerance
3034   Standard_Real aTol = BRep_Tool::Tolerance(F);
3035   Standard_Real squareTolerance = aTol * aTol;
3036
3037   // Compute parameters
3038   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
3039   aRet = new TColStd_HArray1OfReal (0, nbP * 2 - 1);
3040
3041   Standard_Real U1,U2, V1,V2;
3042   BRepTools::UVBounds(F, U1, U2, V1, V2);
3043   Standard_Real dU = U2 - U1;
3044   Standard_Real dV = V2 - V1;
3045
3046   int iCLower = theXYZlist->Lower();
3047   for (int iP = 0; iP < nbP; iP++) {
3048     gp_Pnt aP (theXYZlist->Value(iCLower + iP * 3),
3049                theXYZlist->Value(iCLower + iP * 3 + 1),
3050                theXYZlist->Value(iCLower + iP * 3 + 2));
3051     try { // as GEOMUtils::ProjectPointOnFace can throw exceptions
3052       Standard_Real U, V;
3053       gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V, aTol);
3054       if (aP.SquareDistance(aPonF) < squareTolerance) {
3055         if (isNormalized) {
3056           // Normalize parameters to be in [0, 1]
3057           U = (U - U1) / dU;
3058           V = (V - V1) / dV;
3059         }
3060         aRet->SetValue(iP * 2    , U);
3061         aRet->SetValue(iP * 2 + 1, V);
3062       }
3063       else {
3064         SetErrorCode("Point too far from face");
3065         return aRet;
3066       }
3067     }
3068     catch (Standard_Failure& aFail) {
3069       SetErrorCode(aFail.GetMessageString());
3070       return aRet;
3071     }
3072   }
3073
3074   SetErrorCode(OK);
3075   return aRet;
3076 }
3077
3078 //=============================================================================
3079 /*!
3080  *  UVtoXYZ
3081  */
3082  //=============================================================================
3083 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::UVtoXYZ
3084                                                   (Handle(GEOM_Object) theSurf,
3085                                                    const Handle(TColStd_HArray1OfReal)& theUVlist,
3086                                                    bool isNormalized)
3087 {
3088   SetErrorCode(KO);
3089
3090   Handle(TColStd_HArray1OfReal) aRet;
3091
3092   // Check list of parameters
3093   int nbC = theUVlist->Length();
3094   int nbP = nbC / 2;
3095   if (nbP * 2 != nbC) {
3096     SetErrorCode("Parameters list length is not divisible by 2");
3097     return aRet;
3098   }
3099
3100   // Check face
3101   if (theSurf.IsNull()) {
3102     SetErrorCode("The shape is NULL");
3103     return aRet;
3104   }
3105
3106   Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
3107   if (aRefShape.IsNull()) {
3108     SetErrorCode("The shape is NULL");
3109     return aRet;
3110   }
3111
3112   TopoDS_Shape aShape = aRefShape->GetValue();
3113   if (aShape.IsNull()) {
3114     SetErrorCode("The shape is NULL");
3115     return aRet;
3116   }
3117
3118   // The shape can be a face, a shell of one face or a compound with one face
3119   TopoDS_Face F;
3120   if (aShape.ShapeType() == TopAbs_FACE) {
3121     F = TopoDS::Face(aShape);
3122   }
3123   else if (aShape.ShapeType() < TopAbs_FACE) {
3124     TopExp_Explorer Exp (aShape, TopAbs_FACE);
3125     if (Exp.More()) {
3126       F = TopoDS::Face(Exp.Current());
3127       Exp.Next();
3128       if (Exp.More()) {
3129         SetErrorCode("There should be only one face");
3130         return aRet;
3131       }
3132     }
3133   }
3134   if (F.IsNull()) {
3135     SetErrorCode("There are no faces");
3136     return aRet;
3137   }
3138
3139   // Face tolerance
3140   Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
3141   squareTolerance = squareTolerance * squareTolerance;
3142
3143   // Compute coordinates
3144   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
3145   aRet = new TColStd_HArray1OfReal (0, nbP * 3 - 1);
3146
3147   Standard_Real U1,U2, V1,V2;
3148   BRepTools::UVBounds(F, U1, U2, V1, V2);
3149   Standard_Real dU = U2 - U1;
3150   Standard_Real dV = V2 - V1;
3151
3152   Standard_Real tol = 1.e-4;
3153   Standard_Real pc = Precision::Confusion();
3154
3155   int iCLower = theUVlist->Lower();
3156   for (int iP = 0; iP < nbP; iP++) {
3157     Standard_Real U = theUVlist->Value(iCLower + iP * 2);
3158     Standard_Real V = theUVlist->Value(iCLower + iP * 2 + 1);
3159
3160     if (isNormalized) {
3161       // Get real parameters from given normalized ones in [0, 1]
3162       if (!(-pc < U && U < 1 + pc) || !(-pc < V && V < 1 + pc)) {
3163         SetErrorCode("Normalized parameter is out of range [0,1]");
3164         return aRet;
3165       }
3166       U = U1 + dU * U;
3167       V = V1 + dV * V;
3168     }
3169
3170     gp_Pnt2d aP2d (U, V);
3171
3172     BRepClass_FaceClassifier aClsf (F, aP2d, tol);
3173     if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
3174       SetErrorCode("Given parameters are out of face");
3175       return aRet;
3176     }
3177     gp_Pnt surfPnt = aSurf->Value(U, V);
3178
3179     aRet->SetValue(iP * 3    , surfPnt.X());
3180     aRet->SetValue(iP * 3 + 1, surfPnt.Y());
3181     aRet->SetValue(iP * 3 + 2, surfPnt.Z());
3182   }
3183
3184   SetErrorCode(OK);
3185   return aRet;
3186 }
3187
3188 //=============================================================================
3189 /*!
3190  *  SelfIntersected2D
3191  *  Find all self-intersected 2D curves.
3192  *  \param theChecks list of failed checks, contains type of check and failed shapes
3193  */
3194  //=============================================================================
3195 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3196   GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list<FailedChecks>& theChecks)
3197 {
3198   SetErrorCode(KO);
3199   MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D");
3200
3201   std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters2D;
3202   try
3203   {
3204     OCC_CATCH_SIGNALS;
3205     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3206          anIter != theChecks.end(); ++anIter)
3207     {
3208       if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3209         aSelfInters2D.push_back(anIter->FailedShapes);
3210     }
3211   }
3212   catch (Standard_Failure& aFail)
3213   {
3214     SetErrorCode(aFail.GetMessageString());
3215     return aSelfInters2D;
3216   }
3217
3218   SetErrorCode(OK);
3219   return aSelfInters2D;
3220 }
3221
3222 namespace
3223 {
3224   static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes,
3225                          const int theShapeType1,
3226                          const int theShapeType2)
3227   {
3228     if (theShapeType1 == -1 && theShapeType2 == -1)
3229       return true;
3230
3231     TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull()
3232       ? TopAbs_SHAPE
3233       : theShapes.first->GetValue().ShapeType();
3234     TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull()
3235       ? TopAbs_SHAPE
3236       : theShapes.second->GetValue().ShapeType();
3237
3238     if (theShapeType1 == -1)
3239       return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2;
3240     else if (theShapeType2 == -1)
3241       return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1;
3242     return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) ||
3243       (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1);
3244   }
3245 } // namespace
3246
3247 //=============================================================================
3248 /*!
3249  *  InterferingSubshapes
3250  *  Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
3251  *  \param theChecks list of failed checks, contains type of check and failed shapes
3252  *  \param theShapeType1 Type of shape.
3253  *  \param theShapeType2 Type of shape.
3254  */
3255  //=============================================================================
3256 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3257   GEOMImpl_IMeasureOperations::InterferingSubshapes
3258     (const std::list<FailedChecks>& theChecks,
3259      const int                      theShapeType1,
3260      const int                      theShapeType2)
3261 {
3262   SetErrorCode(KO);
3263   MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes");
3264
3265   std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> anInterfer;
3266   try
3267   {
3268     OCC_CATCH_SIGNALS;
3269     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3270          anIter != theChecks.end(); ++anIter)
3271     {
3272       if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect &&
3273           checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2))
3274         anInterfer.push_back(anIter->FailedShapes);
3275     }
3276   }
3277   catch (Standard_Failure& aFail)
3278   {
3279     SetErrorCode(aFail.GetMessageString());
3280     return anInterfer;
3281   }
3282
3283   SetErrorCode(OK);
3284   return anInterfer;
3285 }
3286
3287 //=============================================================================
3288 /*!
3289  *  SmallEdges
3290  *  Find edges, which are fully covered by tolerances of vertices.
3291  *  \param theChecks list of failed checks, contains type of check and failed shapes
3292  */
3293  //=============================================================================
3294 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges(
3295     const std::list<FailedChecks>& theChecks)
3296 {
3297   SetErrorCode(KO);
3298   MESSAGE("GEOMImpl_IMeasureOperations::smallEdges");
3299
3300   Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient;
3301   try
3302   {
3303     OCC_CATCH_SIGNALS;
3304     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3305          anIter != theChecks.end(); ++anIter)
3306     {
3307       if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge)
3308         aSmallEdges->Append(anIter->FailedShapes.first);
3309     }
3310   }
3311   catch (Standard_Failure& aFail)
3312   {
3313     SetErrorCode(aFail.GetMessageString());
3314     return NULL;
3315   }
3316
3317   SetErrorCode(OK);
3318   return aSmallEdges;
3319 }
3320
3321 //=============================================================================
3322 /*!
3323  *  DistantShapes
3324  *  find remote objects (sub-shape on a shape).
3325  *  \param theShape Shape for check.
3326  *  \param theShapeType Type of shape.
3327  *  \param theSubShapeType Type of sub-shape.
3328  *  \param theTolerance tolerance.
3329  */
3330  //=============================================================================
3331 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3332   GEOMImpl_IMeasureOperations::DistantShapes
3333     (const std::list<FailedChecks>& theChecks,
3334      const int                      theShapeType,
3335      const int                      theSubShapeType,
3336      double                         theTolerance)
3337 {
3338   SetErrorCode(KO);
3339   MESSAGE("GEOMImpl_IMeasureOperations::distantShapes");
3340
3341   std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistShapes;
3342   try
3343   {
3344     OCC_CATCH_SIGNALS;
3345     for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3346          anIter != theChecks.end(); ++anIter)
3347     {
3348       Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first;
3349       Handle(GEOM_Object) aShape = anIter->FailedShapes.second;
3350       if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface ||
3351            anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex ||
3352            anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge ||
3353            anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) &&
3354           aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) &&
3355           aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType))
3356       {
3357         gp_XYZ aP1, aP2;
3358         Standard_Real aDist = Precision::Infinite();
3359         if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3360           aDist = ComputeTolerance(aSubShape, aShape);
3361         if (aDist > theTolerance)
3362           aDistShapes.push_back(anIter->FailedShapes);
3363       }
3364     }
3365   }
3366   catch (Standard_Failure& aFail)
3367   {
3368     SetErrorCode(aFail.GetMessageString());
3369     return aDistShapes;
3370   }
3371
3372   SetErrorCode(OK);
3373   return aDistShapes;
3374 }
3375
3376 //=============================================================================
3377 /*!
3378  *  CheckConformityShape
3379  *  Perform analyse of shape and find imperfections in the shape.
3380  *  \param theShape Shape for analyse.
3381  */
3382  //=============================================================================
3383 void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list<FailedChecks>& theChecks)
3384 {
3385   SetErrorCode(KO);
3386   MESSAGE("GEOMImpl_IMeasureOperations::checkShape");
3387
3388   Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3389   Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE);
3390   if (aFunction.IsNull()) return;
3391
3392   //Check if the function is set correctly
3393   if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return;
3394
3395   GEOMImpl_IConformity aCI(aFunction);
3396
3397   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3398   if (aRefShape.IsNull()) return;
3399
3400   aCI.SetShape(aRefShape);
3401
3402   try
3403   {
3404     OCC_CATCH_SIGNALS;
3405     if (!GetSolver()->ComputeFunction(aFunction))
3406     {
3407       SetErrorCode("Failed: checkShape");
3408       return;
3409     }
3410     Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS);
3411     Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices();
3412     if (aRes.IsNull())
3413       return;
3414
3415     for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex)
3416     {
3417       std::pair<Handle(GEOM_Object), Handle(GEOM_Object)> aPair;
3418       Handle(TColStd_HArray1OfInteger) anArray;
3419       anArray = new TColStd_HArray1OfInteger(1, 1);
3420       anArray->SetValue(1, aRes->Value(anIndex, 1));
3421
3422       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3423       if (!anObj.IsNull())
3424         aPair.first = anObj;
3425
3426       anArray = new TColStd_HArray1OfInteger(1, 1);
3427       anArray->SetValue(1, aRes->Value(anIndex, 2));
3428
3429       anObj = GetEngine()->AddSubShape(theShape, anArray);
3430       if (!anObj.IsNull())
3431         aPair.second = anObj;
3432       theChecks.push_back({ aTypesChecks->Value(anIndex), aPair });
3433     }
3434   }
3435   catch (Standard_Failure& aFail)
3436   {
3437     SetErrorCode(aFail.GetMessageString());
3438     return;
3439   }
3440
3441   SetErrorCode(OK);
3442   return;
3443 }
3444
3445 //=============================================================================
3446 /*!
3447  *  UpdateTolerance
3448  *  Compute possible tolerance for the shape, minimize tolerance of shape as well
3449  *  as tolerance of sub-shapes as much as possible
3450  *  \param theShape Shape for compute tolerance.
3451  */
3452  //=============================================================================
3453 double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape)
3454 {
3455   SetErrorCode(KO);
3456   MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance");
3457
3458   double aResTol = -1;
3459   Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3460   Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL);
3461   if (aFunction.IsNull()) return aResTol;
3462
3463   //Check if the function is set correctly
3464   if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol;
3465
3466   GEOMImpl_IConformity aCI(aFunction);
3467
3468   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3469   if (aRefShape.IsNull()) return aResTol;
3470
3471   aCI.SetShape(aRefShape);
3472
3473   try
3474   {
3475     OCC_CATCH_SIGNALS;
3476     if (!GetSolver()->ComputeFunction(aFunction))
3477     {
3478       SetErrorCode("Failed: updateTolerance");
3479       return aResTol;
3480     }
3481     aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE);
3482   }
3483   catch (Standard_Failure& aFail)
3484   {
3485     SetErrorCode(aFail.GetMessageString());
3486     return aResTol;
3487   }
3488
3489   SetErrorCode(OK);
3490   return aResTol;
3491 }
3492
3493 //=============================================================================
3494 /*!
3495  *  ComputeTolerance
3496  *  Compute distance from the edge to the face.
3497  */
3498  //=============================================================================
3499 double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge,
3500                                                      Handle(GEOM_Object) theFace)
3501 {
3502   double aMaxDist = Precision::Infinite();
3503   if (theEdge.IsNull() || theFace.IsNull())
3504     return aMaxDist;
3505
3506   Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction();
3507   Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
3508   if (aRefEdge.IsNull() || aRefFace.IsNull())
3509     return aMaxDist;
3510
3511   TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue());
3512   TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue());
3513   if (aEdge.IsNull() || aFace.IsNull())
3514     return aMaxDist;
3515
3516   double aParam = 0.0;
3517   BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam);
3518   return aMaxDist;
3519 }
3520
3521 //=======================================================================
3522 //function : FillErrorsSub
3523 //purpose  : Fill the errors list of subshapes on shape.
3524 //=======================================================================
3525 void GEOMImpl_IMeasureOperations::FillErrorsSub
3526            (const BRepCheck_Analyzer                   &theAna,
3527             const TopoDS_Shape                         &theShape,
3528             const TopAbs_ShapeEnum                     theSubType,
3529                   TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
3530 {
3531   TopExp_Explorer anExp(theShape, theSubType);
3532   TopTools_MapOfShape aMapSubShapes;
3533
3534   for (; anExp.More(); anExp.Next()) {
3535     const TopoDS_Shape &aSubShape = anExp.Current();
3536
3537     if (aMapSubShapes.Add(aSubShape)) {
3538       const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
3539
3540       for (aRes->InitContextIterator();
3541            aRes->MoreShapeInContext(); 
3542            aRes->NextShapeInContext()) {
3543         if (aRes->ContextualShape().IsSame(theShape)) {
3544           BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
3545
3546           if (itl.Value() != BRepCheck_NoError) {
3547             // Add all errors for theShape and its sub-shape.
3548             for (;itl.More(); itl.Next()) {
3549               const Standard_Integer aStat = (Standard_Integer)itl.Value();
3550
3551               if (!theMapErrors.IsBound(aStat)) {
3552                 TopTools_ListOfShape anEmpty;
3553
3554                 theMapErrors.Bind(aStat, anEmpty);
3555               }
3556
3557               TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
3558
3559               theShapes.Append(aSubShape);
3560               theShapes.Append(theShape);
3561             }
3562           }
3563         }
3564
3565         break;
3566       }
3567     }
3568   }
3569 }
3570
3571 //=======================================================================
3572 //function : FillErrors
3573 //purpose  : Fill the errors list.
3574 //=======================================================================
3575 void GEOMImpl_IMeasureOperations::FillErrors
3576              (const BRepCheck_Analyzer                   &theAna,
3577               const TopoDS_Shape                         &theShape,
3578                     TopTools_DataMapOfIntegerListOfShape &theMapErrors,
3579                     TopTools_MapOfShape                  &theMapShapes) const
3580 {
3581   if (theMapShapes.Add(theShape)) {
3582     // Fill errors of child shapes.
3583     for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
3584       FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
3585     }
3586
3587     // Fill errors of theShape.
3588     const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
3589
3590     if (!aRes.IsNull()) {
3591       BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
3592
3593       if (itl.Value() != BRepCheck_NoError) {
3594         // Add all errors for theShape.
3595         for (;itl.More(); itl.Next()) {
3596           const Standard_Integer aStat = (Standard_Integer)itl.Value();
3597
3598           if (!theMapErrors.IsBound(aStat)) {
3599             TopTools_ListOfShape anEmpty;
3600
3601             theMapErrors.Bind(aStat, anEmpty);
3602           }
3603
3604           theMapErrors.ChangeFind(aStat).Append(theShape);
3605         }
3606       }
3607     }
3608
3609     // Add errors of subshapes on theShape.
3610     const TopAbs_ShapeEnum aType = theShape.ShapeType();
3611
3612     switch (aType) {
3613     case TopAbs_EDGE:
3614       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3615       break;
3616     case TopAbs_FACE:
3617       FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
3618       FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
3619       FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3620       break;
3621     case TopAbs_SOLID:
3622       FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
3623       break;
3624     default:
3625       break;
3626     }
3627   }
3628 }
3629
3630 //=======================================================================
3631 //function : FillErrors
3632 //purpose  : Fill the errors list.
3633 //=======================================================================
3634 void GEOMImpl_IMeasureOperations::FillErrors
3635                   (const BRepCheck_Analyzer    &theAna,
3636                    const TopoDS_Shape          &theShape,
3637                          std::list<ShapeError> &theErrors) const
3638 {
3639   // Fill the errors map.
3640   TopTools_DataMapOfIntegerListOfShape aMapErrors;
3641   TopTools_MapOfShape                  aMapShapes;
3642
3643   FillErrors(theAna, theShape, aMapErrors, aMapShapes);
3644
3645   // Map sub-shapes and their indices
3646   TopTools_IndexedMapOfShape anIndices;
3647
3648   TopExp::MapShapes(theShape, anIndices);
3649
3650   TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
3651
3652   for (; aMapIter.More(); aMapIter.Next()) {
3653     ShapeError anError;
3654
3655     anError.error = (BRepCheck_Status)aMapIter.Key();
3656
3657     TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
3658     TopTools_MapOfShape                aMapUnique;
3659
3660     for (; aListIter.More(); aListIter.Next()) {
3661       const TopoDS_Shape &aShape = aListIter.Value();
3662
3663       if (aMapUnique.Add(aShape)) {
3664         const Standard_Integer anIndex = anIndices.FindIndex(aShape);
3665
3666         anError.incriminated.push_back(anIndex);
3667       }
3668     }
3669
3670     if (!anError.incriminated.empty()) {
3671       theErrors.push_back(anError);
3672     }
3673   }
3674 }
3675
3676 //=======================================================================
3677 //function : ShapeProximityCalculator
3678 //purpose  : returns an object to compute the proximity value
3679 //=======================================================================
3680 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator
3681                                           (Handle(GEOM_Object) theShape1,
3682                                            Handle(GEOM_Object) theShape2)
3683 {
3684   SetErrorCode(KO);
3685
3686   if (theShape1.IsNull() || theShape2.IsNull())
3687     return NULL;
3688
3689   Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction();
3690   Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction();
3691   if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
3692     return NULL;
3693
3694   Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY);
3695   if (aProximityCalc.IsNull())
3696     return NULL;
3697
3698   Handle(GEOM_Function) aProximityFuncCoarse =
3699       aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE);
3700   //Check if the function is set correctly
3701   if (aProximityFuncCoarse.IsNull() ||
3702       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3703     return NULL;
3704
3705   GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3706   aProximity.SetShapes(aShapeFunc1, aShapeFunc2);
3707
3708   //Make a Python command
3709   GEOM::TPythonDump pd (aProximityFuncCoarse);
3710   pd << "p = geompy.ShapeProximity()\n";
3711   pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")";
3712
3713   SetErrorCode(OK);
3714   return aProximityCalc;
3715 }
3716
3717 //=======================================================================
3718 //function : SetShapeSampling
3719 //purpose  : set number sample points to compute the coarse proximity
3720 //=======================================================================
3721 void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator,
3722                                                    Handle(GEOM_Object) theShape,
3723                                                    const Standard_Integer theNbSamples)
3724 {
3725   SetErrorCode(KO);
3726   if (theShape.IsNull() ||
3727       theCalculator.IsNull() ||
3728       theCalculator->GetNbFunctions() <= 0 ||
3729       theNbSamples <= 0)
3730     return ;
3731
3732   Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3733   if (aProximityFuncCoarse.IsNull() ||
3734       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3735     return ;
3736
3737   Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction();
3738   if (aShapeFunc.IsNull())
3739     return ;
3740
3741   GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
3742   Handle(GEOM_Function) aShape1, aShape2;
3743   aProximity.GetShapes(aShape1, aShape2);
3744   if (aShape1->GetValue() == aShapeFunc->GetValue())
3745     aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples);
3746   else if (aShape2->GetValue() == aShapeFunc->GetValue())
3747     aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples);
3748
3749   //Make a Python command
3750   GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) <<
3751     "p.setSampling(" << theShape << ", " << theNbSamples << ")";
3752
3753   SetErrorCode(OK);
3754 }
3755
3756 //=======================================================================
3757 //function : GetCoarseProximity
3758 //purpose  : compute coarse proximity
3759 //=======================================================================
3760 Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator,
3761                                                               bool doPythonDump)
3762 {
3763   SetErrorCode(KO);
3764   if (theCalculator.IsNull())
3765     return -1;
3766
3767   Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3768   if (aProximityFuncCoarse.IsNull() ||
3769       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3770       aProximityFuncCoarse->GetType() != PROXIMITY_COARSE)
3771     return -1;
3772
3773   // Perform
3774   // We have to recompute the function each time,
3775   // because the number of samples can be changed
3776   try {
3777     OCC_CATCH_SIGNALS;
3778     if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) {
3779       SetErrorCode("shape proximity driver failed");
3780       return -1;
3781     }
3782   }
3783   catch (Standard_Failure& aFail) {
3784     SetErrorCode(aFail.GetMessageString());
3785     return -1;
3786   }
3787
3788   //Make a Python command
3789   if (doPythonDump)
3790     GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()";
3791
3792   SetErrorCode(OK);
3793   GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3794   return aProximity.GetValue();
3795 }
3796
3797 //=======================================================================
3798 //function : GetPreciseProximity
3799 //purpose  : compute precise proximity
3800 //=======================================================================
3801 Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
3802 {
3803   SetErrorCode(KO);
3804   if (theCalculator.IsNull())
3805     return -1;
3806
3807   Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3808   Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2);
3809   if (aProximityFuncFine.IsNull())
3810     aProximityFuncFine = theCalculator->AddFunction
3811       (GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE);
3812
3813   //Check if the functions are set correctly
3814   if (aProximityFuncCoarse.IsNull() ||
3815       aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3816       aProximityFuncFine.IsNull() ||
3817       aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3818     return -1;
3819
3820   // perform coarse computation beforehand
3821   GetCoarseProximity(theCalculator, /*doPythonDump=*/false);
3822
3823   // transfer parameters from the coarse to precise calculator
3824   GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse);
3825   Handle(GEOM_Function) aShape1, aShape2;
3826   aCoarseProximity.GetShapes(aShape1, aShape2);
3827   if (aShape1.IsNull() || aShape2.IsNull())
3828     return -1;
3829   gp_Pnt aProxPnt1, aProxPnt2;
3830   Standard_Integer intStatus1, intStatus2;
3831   aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3832   aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2);
3833   Standard_Real aResultValue = aCoarseProximity.GetValue();
3834
3835   GEOMImpl_IProximity aFineProximity (aProximityFuncFine);
3836   aFineProximity.SetShapes(aShape1, aShape2);
3837   aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2);
3838   aFineProximity.SetStatusOfPoints(intStatus1, intStatus2);
3839   aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised
3840
3841   // Perform
3842   try {
3843     OCC_CATCH_SIGNALS;
3844     if (!GetSolver()->ComputeFunction(aProximityFuncFine)) {
3845       SetErrorCode("shape proximity driver failed");
3846       return -1;
3847     }
3848   }
3849   catch (Standard_Failure& aFail) {
3850     SetErrorCode(aFail.GetMessageString());
3851     return -1;
3852   }
3853
3854   aResultValue = aFineProximity.GetValue();
3855   aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3856
3857   //Make a Python command
3858   GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()";
3859
3860   SetErrorCode(OK);
3861   return aResultValue;
3862 }