Salome HOME
Merge branch occ/shape_reparation_2
[modules/geom.git] / src / GEOMUtils / GEOMUtils.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <Standard_Stream.hxx>
24
25 #include <GEOMUtils.hxx>
26
27 #include <Basics_OCCTVersion.hxx>
28
29 #include <OpUtil.hxx>
30 #include <Utils_ExceptHandlers.hxx>
31
32 // OCCT Includes
33 #include <BRepMesh_IncrementalMesh.hxx>
34
35 #include <BRepExtrema_DistShapeShape.hxx>
36
37 #include <BRep_Builder.hxx>
38 #include <BRep_Tool.hxx>
39 #include <BRepBndLib.hxx>
40 #include <BRepGProp.hxx>
41 #include <BRepTools.hxx>
42
43 #include <BRepClass3d_SolidClassifier.hxx>
44
45 #include <BRepBuilderAPI_MakeFace.hxx>
46 #include <BRepBuilderAPI_Sewing.hxx>
47
48 #include <BRepCheck_Analyzer.hxx>
49
50 #include <Bnd_Box.hxx>
51
52 #include <BOPTools_AlgoTools.hxx>
53
54 #include <TopAbs.hxx>
55 #include <TopExp.hxx>
56 #include <TopoDS.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Face.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Vertex.hxx>
61 #include <TopoDS_Compound.hxx>
62 #include <TopoDS_Iterator.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopTools_MapOfShape.hxx>
65 #include <TopTools_ListOfShape.hxx>
66 #include <TopTools_ListIteratorOfListOfShape.hxx>
67 #include <TopTools_Array1OfShape.hxx>
68
69 #include <Geom_Circle.hxx>
70 #include <Geom_Surface.hxx>
71 #include <Geom_Plane.hxx>
72 #include <Geom_SphericalSurface.hxx>
73 #include <Geom_ToroidalSurface.hxx>
74 #include <Geom_RectangularTrimmedSurface.hxx>
75
76 #include <GeomLProp_CLProps.hxx>
77 #include <GeomLProp_SLProps.hxx>
78
79 #include <GProp_GProps.hxx>
80 #include <GProp_PrincipalProps.hxx>
81
82 #include <TColStd_Array1OfReal.hxx>
83
84 #include <gp_Pln.hxx>
85 #include <gp_Lin.hxx>
86
87 #include <ShapeAnalysis.hxx>
88 #include <ShapeFix_Shape.hxx>
89 #include <ShapeFix_ShapeTolerance.hxx>
90
91 #include <ProjLib.hxx>
92 #include <ElSLib.hxx>
93
94 #include <vector>
95 #include <sstream>
96 #include <algorithm>
97
98 #include <Standard_Failure.hxx>
99 #include <Standard_NullObject.hxx>
100 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
101
102 #define STD_SORT_ALGO 1
103
104 // When the following macro is defined, ShapeFix_ShapeTolerance function is used to set max tolerance of curve
105 // in GEOMUtils::FixShapeCurves function; otherwise less restrictive BRep_Builder::UpdateEdge/UpdateVertex
106 // approach is used
107 // VSR (29/12/2014): macro disabled
108 //#define USE_LIMIT_TOLERANCE
109
110 namespace
111 {
112   /**
113    * This function constructs and returns modified shape from the original one
114    * for singular cases. It is used for the method GetMinDistanceSingular.
115    *
116    * \param theShape the original shape
117    * \param theModifiedShape output parameter. The modified shape.
118    * \param theAddDist output parameter. The added distance for modified shape.
119    * \retval true if the shape is modified; false otherwise.
120    *
121    * \internal
122    */
123   Standard_Boolean ModifyShape(const TopoDS_Shape  &theShape,
124                                TopoDS_Shape  &theModifiedShape,
125                                Standard_Real &theAddDist)
126   {
127     TopExp_Explorer anExp;
128     int nbf = 0;
129
130     theAddDist = 0.;
131     theModifiedShape.Nullify();
132
133     for ( anExp.Init( theShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
134       nbf++;
135       theModifiedShape = anExp.Current();
136     }
137     if(nbf==1) {
138       TopoDS_Shape sh = theShape;
139       while(sh.ShapeType()==TopAbs_COMPOUND) {
140         TopoDS_Iterator it(sh);
141         sh = it.Value();
142       }
143       Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(theModifiedShape));
144       if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
145           S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ||
146           S->IsUPeriodic()) {
147         const Standard_Boolean isShell =
148           (sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE);
149
150         if ( !isShell && S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
151           Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
152           gp_Pnt PC = SS->Location();
153           BRep_Builder B;
154           TopoDS_Vertex V;
155           B.MakeVertex(V,PC,1.e-7);
156           theModifiedShape = V;
157           theAddDist = SS->Radius();
158           return Standard_True;
159         }
160         if ( !isShell && S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
161           Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
162           gp_Ax3 ax3 = TS->Position();
163           Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
164           BRep_Builder B;
165           TopoDS_Edge E;
166           B.MakeEdge(E,C,1.e-7);
167           theModifiedShape = E;
168           theAddDist = TS->MinorRadius();
169           return Standard_True;
170         }
171
172         // non solid case or any periodic surface (Mantis 22454).
173         double U1,U2,V1,V2;
174         // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
175         //S->Bounds(U1,U2,V1,V2); changed by
176         ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(theModifiedShape),U1,U2,V1,V2);
177         // end of changes for 020677 (dmv)
178         Handle(Geom_RectangularTrimmedSurface) TrS1 =
179           new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
180         Handle(Geom_RectangularTrimmedSurface) TrS2 =
181           new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
182         TopoDS_Shape aMShape;
183         
184         TopoDS_Face F1 = BRepBuilderAPI_MakeFace(TrS1, Precision::Confusion());
185         TopoDS_Face F2 = BRepBuilderAPI_MakeFace(TrS2, Precision::Confusion());
186         
187         if (isShell) {
188           BRep_Builder B;
189           B.MakeCompound(TopoDS::Compound(aMShape));
190           B.Add(aMShape, F1);
191           B.Add(aMShape, F2);
192         } else {
193           // The original shape is a solid.
194           BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
195           aSewing.Add(F1);
196           aSewing.Add(F2);
197           aSewing.Perform();
198           aMShape = aSewing.SewedShape();
199           BRep_Builder B;
200           TopoDS_Solid aSolid;
201           B.MakeSolid(aSolid);
202           B.Add(aSolid, aMShape);
203           aMShape = aSolid;
204         }
205         
206         Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
207         sfs->Init(aMShape);
208         sfs->SetPrecision(1.e-6);
209         sfs->SetMaxTolerance(1.0);
210         sfs->Perform();
211         theModifiedShape = sfs->Shape();
212         return Standard_True;
213       }
214     }
215     
216     theModifiedShape = theShape;
217     return Standard_False;
218   }
219
220   void parseWard( const GEOMUtils::LevelsList &theLevelList, std::string &treeStr )
221   {
222     treeStr.append( "{" );
223     for( GEOMUtils::LevelsList::const_iterator j = theLevelList.begin(); 
224          j != theLevelList.end(); ++j ) {
225       if ( j != theLevelList.begin() ) {
226         treeStr.append( ";" );
227       }
228       GEOMUtils::LevelInfo level = (*j);
229       GEOMUtils::LevelInfo::iterator upIter;
230       for ( upIter = level.begin(); upIter != level.end(); ++upIter ) {
231         if ( upIter != level.begin() ) {
232           treeStr.append( "," );
233         }
234         treeStr.append( upIter->first );
235         for ( std::vector<std::string>::iterator k = upIter->second.begin(); k != upIter->second.end(); ++k ) {
236           treeStr.append( "_" );
237           treeStr.append( *k );
238         }
239       }
240     }
241     treeStr.append( "}" );
242   }
243
244   GEOMUtils::LevelsList parseWard( const std::string& theData, std::size_t& theCursor )
245   {
246     std::size_t indexStart = theData.find( "{", theCursor ) + 1;
247     std::size_t indexEnd = theData.find( "}", indexStart );
248
249     std::string ward = theData.substr( indexStart, indexEnd - indexStart );
250     std::stringstream ss(ward);
251     std::string substr;
252     std::vector<std::string> levelsListStr;
253     while ( std::getline( ss, substr, ';' ) ) {
254       if ( !substr.empty() )
255         levelsListStr.push_back( substr );
256     }
257     GEOMUtils::LevelsList levelsListData;
258     for( int level = 0; level < levelsListStr.size(); level++ ) {
259       std::vector<std::string> namesListStr;
260       std::stringstream ss1( levelsListStr[level] );
261       while ( std::getline( ss1, substr, ',' ) ) {
262         if ( !substr.empty() )
263           namesListStr.push_back( substr );
264       }
265       GEOMUtils::LevelInfo levelInfoData;
266       for( int node = 0; node < namesListStr.size(); node++ ) {
267         std::vector<std::string> linksListStr;
268         std::stringstream ss2( namesListStr[node] );
269         while ( std::getline( ss2, substr, '_' ) ) {
270           if ( !substr.empty() )
271             linksListStr.push_back( substr );
272         }
273         std::string nodeItem = linksListStr[0];
274         if( !nodeItem.empty() ) {
275           GEOMUtils::NodeLinks linksListData;
276           for( int link = 1; link < linksListStr.size(); link++ ) {
277             std::string linkItem = linksListStr[link];
278             linksListData.push_back( linkItem );
279           }// Links
280           levelInfoData[nodeItem] = linksListData;
281         }
282       }// Level's objects
283       levelsListData.push_back(levelInfoData);
284     }// Levels
285
286     theCursor = indexEnd + 1;
287     return levelsListData;
288   }
289
290 }
291
292 //=======================================================================
293 //function : ShapeToDouble
294 //purpose  : used by CompareShapes::operator()
295 //=======================================================================
296 std::pair<double, double> GEOMUtils::ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting)
297 {
298   // Computing of CentreOfMass
299   gp_Pnt GPoint;
300   double Len;
301
302   if (S.ShapeType() == TopAbs_VERTEX) {
303     GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
304     Len = (double)S.Orientation();
305   }
306   else {
307     GProp_GProps GPr;
308     // BEGIN: fix for Mantis issue 0020842
309     if (isOldSorting) {
310       BRepGProp::LinearProperties(S, GPr);
311     }
312     else {
313       if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
314         BRepGProp::LinearProperties(S, GPr);
315       }
316       else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
317         BRepGProp::SurfaceProperties(S, GPr);
318       }
319       else {
320         BRepGProp::VolumeProperties(S, GPr);
321       }
322     }
323     // END: fix for Mantis issue 0020842
324     GPoint = GPr.CentreOfMass();
325     Len = GPr.Mass();
326   }
327
328   double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
329   return std::make_pair(dMidXYZ, Len);
330 }
331
332 //=======================================================================
333 //function : GetPosition
334 //purpose  :
335 //=======================================================================
336 gp_Ax3 GEOMUtils::GetPosition (const TopoDS_Shape& theShape)
337 {
338   gp_Ax3 aResult;
339
340   if (theShape.IsNull())
341     return aResult;
342
343   // Axes
344   aResult.Transform(theShape.Location().Transformation());
345   if (theShape.ShapeType() == TopAbs_FACE) {
346     Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape));
347     if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
348       Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
349       gp_Pln aPln = aGPlane->Pln();
350       aResult = aPln.Position();
351       // In case of reverse orinetation of the face invert the plane normal
352       // (the face's normal does not mathc the plane's normal in this case)
353       if(theShape.Orientation() == TopAbs_REVERSED)
354       {
355         gp_Dir Vx =  aResult.XDirection();
356         gp_Dir N  =  aResult.Direction().Mirrored(Vx);
357         gp_Pnt P  =  aResult.Location();
358         aResult = gp_Ax3(P, N, Vx);
359       }
360     }
361   }
362
363   // Origin
364   gp_Pnt aPnt;
365
366   TopAbs_ShapeEnum aShType = theShape.ShapeType();
367
368   if (aShType == TopAbs_VERTEX) {
369     aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
370   }
371   else {
372     if (aShType == TopAbs_COMPOUND) {
373       aShType = GetTypeOfSimplePart(theShape);
374     }
375
376     GProp_GProps aSystem;
377     if (aShType == TopAbs_EDGE || aShType == TopAbs_WIRE)
378       BRepGProp::LinearProperties(theShape, aSystem);
379     else if (aShType == TopAbs_FACE || aShType == TopAbs_SHELL)
380       BRepGProp::SurfaceProperties(theShape, aSystem);
381     else
382       BRepGProp::VolumeProperties(theShape, aSystem);
383
384     aPnt = aSystem.CentreOfMass();
385   }
386
387   aResult.SetLocation(aPnt);
388
389   return aResult;
390 }
391
392 //=======================================================================
393 //function : GetVector
394 //purpose  :
395 //=======================================================================
396 gp_Vec GEOMUtils::GetVector (const TopoDS_Shape& theShape,
397                              Standard_Boolean doConsiderOrientation)
398 {
399   if (theShape.IsNull())
400     Standard_NullObject::Raise("Null shape is given for a vector");
401
402   if (theShape.ShapeType() != TopAbs_EDGE)
403     Standard_TypeMismatch::Raise("Invalid shape is given, must be a vector or an edge");
404
405   TopoDS_Edge anE = TopoDS::Edge(theShape);
406
407   TopoDS_Vertex V1, V2;
408   TopExp::Vertices(anE, V1, V2, doConsiderOrientation);
409
410   if (V1.IsNull() || V2.IsNull())
411     Standard_NullObject::Raise("Invalid edge is given, it must have two points");
412
413   gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
414   if (aV.Magnitude() < gp::Resolution()) {
415     Standard_ConstructionError::Raise("Vector of zero length is given");
416   }
417
418   return aV;
419 }
420
421 //=======================================================================
422 //function : CompareShapes::operator()
423 //purpose  : used by std::sort(), called from SortShapes()
424 //=======================================================================
425 bool GEOMUtils::CompareShapes::operator() (const TopoDS_Shape& theShape1,
426                                            const TopoDS_Shape& theShape2)
427 {
428   if (!myMap.IsBound(theShape1)) {
429     myMap.Bind(theShape1, ShapeToDouble(theShape1, myIsOldSorting));
430   }
431
432   if (!myMap.IsBound(theShape2)) {
433     myMap.Bind(theShape2, ShapeToDouble(theShape2, myIsOldSorting));
434   }
435
436   std::pair<double, double> val1 = myMap.Find(theShape1);
437   std::pair<double, double> val2 = myMap.Find(theShape2);
438
439   double tol = Precision::Confusion();
440   bool exchange = Standard_False;
441
442   double dMidXYZ = val1.first - val2.first;
443   if (dMidXYZ >= tol) {
444     exchange = Standard_True;
445   }
446   else if (Abs(dMidXYZ) < tol) {
447     double dLength = val1.second - val2.second;
448     if (dLength >= tol) {
449       exchange = Standard_True;
450     }
451     else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
452       // PAL17233
453       // equal values possible on shapes such as two halves of a sphere and
454       // a membrane inside the sphere
455       Bnd_Box box1,box2;
456       BRepBndLib::Add(theShape1, box1);
457       if (!box1.IsVoid()) {
458         BRepBndLib::Add(theShape2, box2);
459         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
460         if (dSquareExtent >= tol) {
461           exchange = Standard_True;
462         }
463         else if (Abs(dSquareExtent) < tol) {
464           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
465           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
466           val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
467           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
468           val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
469           if ((val1 - val2) >= tol) {
470             exchange = Standard_True;
471           }
472         }
473       }
474     }
475   }
476
477   //return val1 < val2;
478   return !exchange;
479 }
480
481 //=======================================================================
482 //function : SortShapes
483 //purpose  :
484 //=======================================================================
485 void GEOMUtils::SortShapes (TopTools_ListOfShape& SL,
486                             const Standard_Boolean isOldSorting)
487 {
488 #ifdef STD_SORT_ALGO
489   std::vector<TopoDS_Shape> aShapesVec;
490   aShapesVec.reserve(SL.Extent());
491
492   TopTools_ListIteratorOfListOfShape it (SL);
493   for (; it.More(); it.Next()) {
494     aShapesVec.push_back(it.Value());
495   }
496   SL.Clear();
497
498   CompareShapes shComp (isOldSorting);
499   std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
500   //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp);
501
502   std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
503   for (; anIter != aShapesVec.end(); ++anIter) {
504     SL.Append(*anIter);
505   }
506 #else
507   // old implementation
508   Standard_Integer MaxShapes = SL.Extent();
509   TopTools_Array1OfShape  aShapes (1,MaxShapes);
510   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
511   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
512   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
513
514   // Computing of CentreOfMass
515   Standard_Integer Index;
516   GProp_GProps GPr;
517   gp_Pnt GPoint;
518   TopTools_ListIteratorOfListOfShape it(SL);
519   for (Index=1;  it.More();  Index++)
520   {
521     TopoDS_Shape S = it.Value();
522     SL.Remove( it ); // == it.Next()
523     aShapes(Index) = S;
524     OrderInd.SetValue (Index, Index);
525     if (S.ShapeType() == TopAbs_VERTEX) {
526       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
527       Length.SetValue( Index, (Standard_Real) S.Orientation());
528     }
529     else {
530       // BEGIN: fix for Mantis issue 0020842
531       if (isOldSorting) {
532         BRepGProp::LinearProperties (S, GPr);
533       }
534       else {
535         if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
536           BRepGProp::LinearProperties (S, GPr);
537         }
538         else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
539           BRepGProp::SurfaceProperties(S, GPr);
540         }
541         else {
542           BRepGProp::VolumeProperties(S, GPr);
543         }
544       }
545       // END: fix for Mantis issue 0020842
546       GPoint = GPr.CentreOfMass();
547       Length.SetValue(Index, GPr.Mass());
548     }
549     MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9);
550     //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
551   }
552
553   // Sorting
554   Standard_Integer aTemp;
555   Standard_Boolean exchange, Sort = Standard_True;
556   Standard_Real    tol = Precision::Confusion();
557   while (Sort)
558   {
559     Sort = Standard_False;
560     for (Index=1; Index < MaxShapes; Index++)
561     {
562       exchange = Standard_False;
563       Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
564       Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
565       if ( dMidXYZ >= tol ) {
566 //         cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
567 //              << " d: " << dMidXYZ << endl;
568         exchange = Standard_True;
569       }
570       else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
571 //         cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
572 //              << " d: " << dLength << endl;
573         exchange = Standard_True;
574       }
575       else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
576                 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
577         // PAL17233
578         // equal values possible on shapes such as two halves of a sphere and
579         // a membrane inside the sphere
580         Bnd_Box box1,box2;
581         BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
582         if ( box1.IsVoid() ) continue;
583         BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
584         Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
585         if ( dSquareExtent >= tol ) {
586 //           cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
587           exchange = Standard_True;
588         }
589         else if ( Abs(dSquareExtent) < tol ) {
590           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
591           box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
592           val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
593           box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
594           val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
595           //exchange = val1 > val2;
596           if ((val1 - val2) >= tol) {
597             exchange = Standard_True;
598           }
599           //cout << "box: " << val1<<" > "<<val2 << endl;
600         }
601       }
602
603       if (exchange)
604       {
605 //         cout << "exchange " << Index << " & " << Index+1 << endl;
606         aTemp = OrderInd(Index);
607         OrderInd(Index) = OrderInd(Index+1);
608         OrderInd(Index+1) = aTemp;
609         Sort = Standard_True;
610       }
611     }
612   }
613
614   for (Index=1; Index <= MaxShapes; Index++)
615     SL.Append( aShapes( OrderInd(Index) ));
616 #endif
617 }
618
619 //=======================================================================
620 //function : CompsolidToCompound
621 //purpose  :
622 //=======================================================================
623 TopoDS_Shape GEOMUtils::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
624 {
625   if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
626     return theCompsolid;
627   }
628
629   TopoDS_Compound aCompound;
630   BRep_Builder B;
631   B.MakeCompound(aCompound);
632
633   TopTools_MapOfShape mapShape;
634   TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
635
636   for (; It.More(); It.Next()) {
637     TopoDS_Shape aShape_i = It.Value();
638     if (mapShape.Add(aShape_i)) {
639       B.Add(aCompound, aShape_i);
640     }
641   }
642
643   return aCompound;
644 }
645
646 //=======================================================================
647 //function : AddSimpleShapes
648 //purpose  :
649 //=======================================================================
650 void GEOMUtils::AddSimpleShapes (const TopoDS_Shape& theShape, TopTools_ListOfShape& theList)
651 {
652   if (theShape.ShapeType() != TopAbs_COMPOUND &&
653       theShape.ShapeType() != TopAbs_COMPSOLID) {
654     theList.Append(theShape);
655     return;
656   }
657
658   TopTools_MapOfShape mapShape;
659   TopoDS_Iterator It (theShape, Standard_True, Standard_True);
660
661   for (; It.More(); It.Next()) {
662     TopoDS_Shape aShape_i = It.Value();
663     if (mapShape.Add(aShape_i)) {
664       if (aShape_i.ShapeType() == TopAbs_COMPOUND ||
665           aShape_i.ShapeType() == TopAbs_COMPSOLID) {
666         AddSimpleShapes(aShape_i, theList);
667       } else {
668         theList.Append(aShape_i);
669       }
670     }
671   }
672 }
673
674 //=======================================================================
675 //function : CheckTriangulation
676 //purpose  :
677 //=======================================================================
678 bool GEOMUtils::CheckTriangulation (const TopoDS_Shape& aShape)
679 {
680   bool isTriangulation = true;
681
682   TopExp_Explorer exp (aShape, TopAbs_FACE);
683   if (exp.More())
684   {
685     TopLoc_Location aTopLoc;
686     Handle(Poly_Triangulation) aTRF;
687     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
688     if (aTRF.IsNull()) {
689       isTriangulation = false;
690     }
691   }
692   else // no faces, try edges
693   {
694     TopExp_Explorer expe (aShape, TopAbs_EDGE);
695     if (!expe.More()) {
696       return false;
697     }
698     TopLoc_Location aLoc;
699     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
700     if (aPE.IsNull()) {
701       isTriangulation = false;
702     }
703   }
704
705   if (!isTriangulation) {
706     // calculate deflection
707     Standard_Real aDeviationCoefficient = 0.001;
708
709     Bnd_Box B;
710     BRepBndLib::Add(aShape, B);
711     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
712     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
713
714     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
715     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
716     Standard_Real aHLRAngle = 0.349066;
717
718     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
719   }
720
721   return true;
722 }
723
724 //=======================================================================
725 //function : GetTypeOfSimplePart
726 //purpose  :
727 //=======================================================================
728 TopAbs_ShapeEnum GEOMUtils::GetTypeOfSimplePart (const TopoDS_Shape& theShape)
729 {
730   TopAbs_ShapeEnum aType = theShape.ShapeType();
731   if      (aType == TopAbs_VERTEX)                             return TopAbs_VERTEX;
732   else if (aType == TopAbs_EDGE  || aType == TopAbs_WIRE)      return TopAbs_EDGE;
733   else if (aType == TopAbs_FACE  || aType == TopAbs_SHELL)     return TopAbs_FACE;
734   else if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) return TopAbs_SOLID;
735   else if (aType == TopAbs_COMPOUND) {
736     // Only the iType of the first shape in the compound is taken into account
737     TopoDS_Iterator It (theShape, Standard_False, Standard_False);
738     if (It.More()) {
739       return GetTypeOfSimplePart(It.Value());
740     }
741   }
742   return TopAbs_SHAPE;
743 }
744
745 //=======================================================================
746 //function : GetEdgeNearPoint
747 //purpose  :
748 //=======================================================================
749 TopoDS_Shape GEOMUtils::GetEdgeNearPoint (const TopoDS_Shape& theShape,
750                                           const TopoDS_Vertex& thePoint)
751 {
752   TopoDS_Shape aResult;
753
754   // 1. Explode the shape on edges
755   TopTools_MapOfShape mapShape;
756   Standard_Integer nbEdges = 0;
757   TopExp_Explorer exp (theShape, TopAbs_EDGE);
758   for (; exp.More(); exp.Next()) {
759     if (mapShape.Add(exp.Current())) {
760       nbEdges++;
761     }
762   }
763
764   if (nbEdges == 0)
765     Standard_NullObject::Raise("Given shape contains no edges");
766
767   mapShape.Clear();
768   Standard_Integer ind = 1;
769   TopTools_Array1OfShape anEdges (1, nbEdges);
770   TColStd_Array1OfReal aDistances (1, nbEdges);
771   for (exp.Init(theShape, TopAbs_EDGE); exp.More(); exp.Next()) {
772     if (mapShape.Add(exp.Current())) {
773       TopoDS_Shape anEdge = exp.Current();
774       anEdges(ind) = anEdge;
775
776       // 2. Classify the point relatively each edge
777       BRepExtrema_DistShapeShape aDistTool (thePoint, anEdges(ind));
778       if (!aDistTool.IsDone())
779         Standard_ConstructionError::Raise("Cannot find a distance from the given point to one of edges");
780
781       aDistances(ind) = aDistTool.Value();
782       ind++;
783     }
784   }
785
786   // 3. Define edge, having minimum distance to the point
787   Standard_Real nearest = RealLast(), nbFound = 0;
788   Standard_Real prec = Precision::Confusion();
789   for (ind = 1; ind <= nbEdges; ind++) {
790     if (Abs(aDistances(ind) - nearest) < prec) {
791       nbFound++;
792     }
793     else if (aDistances(ind) < nearest) {
794       nearest = aDistances(ind);
795       aResult = anEdges(ind);
796       nbFound = 1;
797     }
798     else {
799     }
800   }
801   if (nbFound > 1) {
802     Standard_ConstructionError::Raise("Multiple edges near the given point are found");
803   }
804   else if (nbFound == 0) {
805     Standard_ConstructionError::Raise("There are no edges near the given point");
806   }
807   else {
808   }
809
810   return aResult;
811 }
812
813 //=======================================================================
814 //function : PreciseBoundingBox
815 //purpose  : 
816 //=======================================================================
817 Standard_Boolean GEOMUtils::PreciseBoundingBox
818                           (const TopoDS_Shape &theShape, Bnd_Box &theBox)
819 {
820   if ( theBox.IsVoid() ) BRepBndLib::Add( theShape, theBox );
821   if ( theBox.IsVoid() ) return Standard_False;
822
823   Standard_Real aBound[6];
824   theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
825
826   Standard_Integer i;
827   const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]),  // XMid
828                     0.5*(aBound[3] + aBound[2]),  // YMid
829                     0.5*(aBound[5] + aBound[4])); // ZMid
830   const gp_XYZ aSize(aBound[1] - aBound[0],       // DX
831                      aBound[3] - aBound[2],       // DY
832                      aBound[5] - aBound[4]);      // DZ
833   const gp_Pnt aPnt[6] =
834     {
835       gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin
836       gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax
837       gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin
838       gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax
839       gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin
840       gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4]))  // ZMax
841     };
842   const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() };
843   const Standard_Real aPlnSize[3] =
844     {
845       0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes
846       0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes
847       0.5*Max(aSize.X(), aSize.Y())  // ZMin, ZMax planes
848     };
849   gp_Pnt aPMin[2];
850
851   for (i = 0; i < 6; i++) {
852     const Standard_Integer iHalf = i/2;
853     const gp_Pln aPln(aPnt[i], aDir[iHalf]);
854     BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf],
855                                     -aPlnSize[iHalf], aPlnSize[iHalf]);
856
857     if (!aMkFace.IsDone()) {
858       return Standard_False;
859     }
860
861     TopoDS_Shape aFace = aMkFace.Shape();
862
863     // Get minimal distance between planar face and shape.
864     Standard_Real aMinDist =
865       GEOMUtils::GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]);
866
867     if (aMinDist < 0.) {
868       return Standard_False;
869     }
870
871     aBound[i] = aPMin[1].Coord(iHalf + 1);
872   }
873
874   // Update Bounding box with the new values.
875   theBox.SetVoid();
876   theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
877
878   return Standard_True;
879 }
880
881 //=======================================================================
882 //function : GetMinDistanceSingular
883 //purpose  : 
884 //=======================================================================
885 double GEOMUtils::GetMinDistanceSingular(const TopoDS_Shape& aSh1,
886                                          const TopoDS_Shape& aSh2,
887                                          gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
888 {
889   TopoDS_Shape     tmpSh1;
890   TopoDS_Shape     tmpSh2;
891   Standard_Real    AddDist1 = 0.;
892   Standard_Real    AddDist2 = 0.;
893   Standard_Boolean IsChange1 = ModifyShape(aSh1, tmpSh1, AddDist1);
894   Standard_Boolean IsChange2 = ModifyShape(aSh2, tmpSh2, AddDist2);
895
896   if( !IsChange1 && !IsChange2 )
897     return -2.0;
898
899   BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
900   if (dst.IsDone()) {
901     double MinDist = 1.e9;
902     gp_Pnt PMin1, PMin2, P1, P2;
903     for (int i = 1; i <= dst.NbSolution(); i++) {
904       P1 = dst.PointOnShape1(i);
905       P2 = dst.PointOnShape2(i);
906       Standard_Real Dist = P1.Distance(P2);
907       if (MinDist > Dist) {
908         MinDist = Dist;
909         PMin1 = P1;
910         PMin2 = P2;
911       }
912     }
913     if(MinDist<1.e-7) {
914       Ptmp1 = PMin1;
915       Ptmp2 = PMin2;
916     }
917     else {
918       gp_Dir aDir(gp_Vec(PMin1,PMin2));
919       if( MinDist > (AddDist1+AddDist2) ) {
920         Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
921                         PMin1.Y() + aDir.Y()*AddDist1,
922                         PMin1.Z() + aDir.Z()*AddDist1 );
923         Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
924                         PMin2.Y() - aDir.Y()*AddDist2,
925                         PMin2.Z() - aDir.Z()*AddDist2 );
926         return (MinDist - AddDist1 - AddDist2);
927       }
928       else {
929         if( AddDist1 > 0 ) {
930           Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
931                           PMin1.Y() + aDir.Y()*AddDist1,
932                           PMin1.Z() + aDir.Z()*AddDist1 );
933           Ptmp2 = Ptmp1;
934         }
935         else {
936           Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
937                           PMin2.Y() - aDir.Y()*AddDist2,
938                           PMin2.Z() - aDir.Z()*AddDist2 );
939           Ptmp1 = Ptmp2;
940         }
941       }
942     }
943     double res = MinDist - AddDist1 - AddDist2;
944     if(res<0.) res = 0.0;
945     return res;
946   }
947   return -2.0;
948 }
949
950 //=======================================================================
951 //function : GetMinDistance
952 //purpose  : 
953 //=======================================================================
954 Standard_Real GEOMUtils::GetMinDistance
955                                (const TopoDS_Shape& theShape1,
956                                 const TopoDS_Shape& theShape2,
957                                 gp_Pnt& thePnt1, gp_Pnt& thePnt2)
958 {
959   Standard_Real aResult = 1.e9;
960
961   // Issue 0020231: A min distance bug with torus and vertex.
962   // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
963
964   // which of shapes consists of only one vertex?
965   TopExp_Explorer exp1(theShape1,TopAbs_VERTEX), exp2(theShape2,TopAbs_VERTEX);
966   TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
967   TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
968   exp1.Next(); exp2.Next();
969   if ( exp1.More() ) V1.Nullify();
970   if ( exp2.More() ) V2.Nullify();
971   // vertex and container of solids
972   TopoDS_Shape V = V1.IsNull() ? V2 : V1;
973   TopoDS_Shape S = V1.IsNull() ? theShape1 : theShape2;
974   if ( !V.IsNull() ) {
975     // classify vertex against solids
976     gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
977     for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
978       BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
979       if ( classifier.State() == TopAbs_IN ) {
980         thePnt1 = p;
981         thePnt2 = p;
982         return 0.0;
983       }
984     }
985   }
986   // End Issue 0020231
987
988   // skl 30.06.2008
989   // additional workaround for bugs 19899, 19908 and 19910 from Mantis
990   double dist = GEOMUtils::GetMinDistanceSingular
991       (theShape1, theShape2, thePnt1, thePnt2);
992
993   if (dist > -1.0) {
994     return dist;
995   }
996
997   BRepExtrema_DistShapeShape dst (theShape1, theShape2);
998   if (dst.IsDone()) {
999     gp_Pnt P1, P2;
1000
1001     for (int i = 1; i <= dst.NbSolution(); i++) {
1002       P1 = dst.PointOnShape1(i);
1003       P2 = dst.PointOnShape2(i);
1004
1005       Standard_Real Dist = P1.Distance(P2);
1006       if (aResult > Dist) {
1007         aResult = Dist;
1008         thePnt1 = P1;
1009         thePnt2 = P2;
1010       }
1011     }
1012   }
1013
1014   return aResult;
1015 }
1016
1017 //=======================================================================
1018 // function : ConvertClickToPoint()
1019 // purpose  : Returns the point clicked in 3D view
1020 //=======================================================================
1021 gp_Pnt GEOMUtils::ConvertClickToPoint( int x, int y, Handle(V3d_View) aView )
1022 {
1023   V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
1024   aView->Eye( XEye, YEye, ZEye );
1025
1026   aView->At( XAt, YAt, ZAt );
1027   gp_Pnt EyePoint( XEye, YEye, ZEye );
1028   gp_Pnt AtPoint( XAt, YAt, ZAt );
1029
1030   gp_Vec EyeVector( EyePoint, AtPoint );
1031   gp_Dir EyeDir( EyeVector );
1032
1033   gp_Pln PlaneOfTheView = gp_Pln( AtPoint, EyeDir );
1034   Standard_Real X, Y, Z;
1035   aView->Convert( x, y, X, Y, Z );
1036   gp_Pnt ConvertedPoint( X, Y, Z );
1037
1038   gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project( PlaneOfTheView, ConvertedPoint );
1039   gp_Pnt ResultPoint = ElSLib::Value( ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(), PlaneOfTheView );
1040   return ResultPoint;
1041 }
1042
1043 //=======================================================================
1044 // function : ConvertTreeToString()
1045 // purpose  : Returns the string representation of dependency tree
1046 //=======================================================================
1047 void GEOMUtils::ConvertTreeToString( const TreeModel& tree,
1048                                      std::string& dependencyStr )
1049 {
1050   TreeModel::const_iterator i;
1051   for ( i = tree.begin(); i != tree.end(); ++i ) {
1052     dependencyStr.append( i->first );
1053     dependencyStr.append( "-" );
1054     std::vector<LevelInfo> upLevelList = i->second.first;
1055     dependencyStr.append( "upward" );
1056     parseWard( upLevelList, dependencyStr );
1057     std::vector<LevelInfo> downLevelList = i->second.second;
1058     dependencyStr.append( "downward" );
1059     parseWard( downLevelList, dependencyStr );
1060   }
1061 }
1062
1063 //=======================================================================
1064 // function : ConvertStringToTree()
1065 // purpose  : Returns the dependency tree
1066 //=======================================================================
1067 void GEOMUtils::ConvertStringToTree( const std::string& dependencyStr,
1068                                      TreeModel& tree )
1069 {
1070   std::size_t cursor = 0;
1071
1072   while( dependencyStr.find('-',cursor) != std::string::npos ) //find next selected object
1073   {
1074     std::size_t objectIndex = dependencyStr.find( '-', cursor );
1075     std::string objectEntry = dependencyStr.substr( cursor, objectIndex - cursor );
1076     cursor = objectIndex;
1077
1078     std::size_t upwardIndexBegin = dependencyStr.find("{",cursor) + 1;
1079     std::size_t upwardIndexFinish = dependencyStr.find("}",upwardIndexBegin);
1080     LevelsList upwardList = parseWard( dependencyStr, cursor );
1081
1082     LevelsList downwardList = parseWard( dependencyStr, cursor );
1083
1084     tree[objectEntry] = std::pair<LevelsList,LevelsList>( upwardList, downwardList );
1085   }
1086 }
1087
1088 bool GEOMUtils::CheckShape( TopoDS_Shape& shape,
1089                             bool checkGeometry )
1090 {
1091   BRepCheck_Analyzer analyzer( shape, checkGeometry );
1092   return analyzer.IsValid();
1093 }
1094
1095 bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
1096                                    TopAbs_ShapeEnum type,
1097                                    Standard_Real tolerance,
1098                                    bool checkGeometry )
1099 {
1100   ShapeFix_ShapeTolerance aSft;
1101   aSft.LimitTolerance( shape, tolerance, tolerance, type );
1102   Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape( shape );
1103   aSfs->Perform();
1104   shape = aSfs->Shape();
1105   return CheckShape( shape, checkGeometry );
1106 }
1107
1108 bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
1109                                    Standard_Real tolerance,
1110                                    bool checkGeometry )
1111 {
1112   return FixShapeTolerance( shape, TopAbs_SHAPE, tolerance, checkGeometry );
1113 }
1114
1115 bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
1116                                    bool checkGeometry )
1117 {
1118   return FixShapeTolerance( shape, Precision::Confusion(), checkGeometry );
1119 }
1120
1121 bool GEOMUtils::FixShapeCurves( TopoDS_Shape& shape )
1122 {
1123   Standard_Real aT, aTolE, aD, aDMax;
1124   TopExp_Explorer aExpF, aExpE;
1125   NCollection_DataMap<TopoDS_Edge, Standard_Real, TopTools_ShapeMapHasher> aDMETol;
1126   aExpF.Init(shape, TopAbs_FACE);
1127   for (; aExpF.More(); aExpF.Next()) {
1128     const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
1129     aExpE.Init(aF, TopAbs_EDGE);
1130     for (; aExpE.More(); aExpE.Next()) {
1131       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
1132       try {
1133         if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) {
1134           continue;
1135         }
1136       }
1137       catch(...) {
1138         continue;
1139       }
1140       aTolE = BRep_Tool::Tolerance(aE);
1141       if (aDMax < aTolE) continue;
1142       if (aDMETol.IsBound(aE)) {
1143         aD = aDMETol.Find(aE);
1144         if (aDMax > aD) {
1145           aDMETol.UnBind(aE);
1146           aDMETol.Bind(aE, aDMax);
1147         }
1148       }
1149       else {
1150         aDMETol.Bind(aE, aDMax);
1151       }
1152     }
1153   }
1154   NCollection_DataMap<TopoDS_Edge, Standard_Real, TopTools_ShapeMapHasher>::Iterator aDMETolIt(aDMETol);
1155 #ifdef USE_LIMIT_TOLERANCE
1156   ShapeFix_ShapeTolerance sat;
1157 #else
1158   BRep_Builder b;
1159 #endif
1160   for (; aDMETolIt.More(); aDMETolIt.Next()) {
1161 #ifdef USE_LIMIT_TOLERANCE
1162     sat.LimitTolerance(aDMETolIt.Key(), aDMETolIt.Value()*1.001);
1163 #else
1164     TopoDS_Iterator itv(aDMETolIt.Key());
1165     for (; itv.More(); itv.Next())
1166       b.UpdateVertex(TopoDS::Vertex(itv.Value()), aDMETolIt.Value()*1.001);
1167     b.UpdateEdge(aDMETolIt.Key(), aDMETolIt.Value()*1.001);
1168 #endif
1169   }
1170   return CheckShape( shape );
1171 }
1172
1173 bool GEOMUtils::Write( const TopoDS_Shape& shape, const char* fileName )
1174 {
1175   return BRepTools::Write( shape, fileName );
1176 }