1 // Created on: 1995-10-27
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 //  Modified by skv - Tue Mar 15 16:20:43 2005
18 // Add methods for supporting history.
19 //  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455
20 
21 #include <Adaptor3d_CurveOnSurface.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
24 #include <BRep_PointRepresentation.hxx>
25 #include <BRep_TEdge.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_TVertex.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <BRepAdaptor_Curve2d.hxx>
30 #include <BRepAdaptor_Surface.hxx>
31 #include <BRepAlgo_AsDes.hxx>
32 #include <BRepAlgo_Image.hxx>
33 #include <BRepCheck_Analyzer.hxx>
34 #include <BRepCheck_Edge.hxx>
35 #include <BRepCheck_Vertex.hxx>
36 #include <BRepClass3d_SolidClassifier.hxx>
37 #include <BRepGProp.hxx>
38 #include <BRepLib.hxx>
39 #include <BRepLib_FindSurface.hxx>
40 #include <BRepLib_MakeEdge.hxx>
41 #include <BRepLib_MakeFace.hxx>
42 #include <BRepLib_MakeVertex.hxx>
43 #include <BRepOffset_Analyse.hxx>
44 #include <BRepOffset_DataMapIteratorOfDataMapOfShapeOffset.hxx>
45 #include <BRepOffset_DataMapOfShapeMapOfShape.hxx>
46 #include <BRepOffset_DataMapOfShapeOffset.hxx>
47 #include <BRepOffset_Inter2d.hxx>
48 #include <BRepOffset_Inter3d.hxx>
49 #include <BRepOffset_Interval.hxx>
50 #include <BRepOffset_ListOfInterval.hxx>
51 #include <BRepOffset_MakeLoops.hxx>
52 #include <BRepOffset_MakeOffset.hxx>
53 #include <BRepOffset_Offset.hxx>
54 #include <BRepOffset_Tool.hxx>
55 #include <BRepTools.hxx>
56 #include <BRepTools_Quilt.hxx>
57 #include <BRepTools_Substitution.hxx>
58 #include <BRepTools_WireExplorer.hxx>
59 #include <ElCLib.hxx>
60 #include <ElSLib.hxx>
61 #include <GC_MakeCylindricalSurface.hxx>
62 #include <GCE2d_MakeLine.hxx>
63 #include <gce_MakeCone.hxx>
64 #include <gce_MakeDir.hxx>
65 #include <Geom2d_Line.hxx>
66 #include <Geom2d_TrimmedCurve.hxx>
67 #include <Geom2dAdaptor_Curve.hxx>
68 #include <Geom_Circle.hxx>
69 #include <Geom_ConicalSurface.hxx>
70 #include <Geom_CylindricalSurface.hxx>
71 #include <Geom_OffsetSurface.hxx>
72 #include <Geom_Plane.hxx>
73 #include <Geom_SphericalSurface.hxx>
74 #include <Geom_SurfaceOfLinearExtrusion.hxx>
75 #include <Geom_TrimmedCurve.hxx>
76 #include <GeomAdaptor_Surface.hxx>
77 #include <GeomAPI_ProjectPointOnCurve.hxx>
78 #include <GeomFill_Generator.hxx>
79 #include <GeomLib.hxx>
80 #include <GeomLib_IsPlanarSurface.hxx>
81 #include <gp_Cone.hxx>
82 #include <gp_Lin2d.hxx>
83 #include <gp_Pnt.hxx>
84 #include <GProp_GProps.hxx>
85 #include <IntTools_FClass2d.hxx>
86 #include <NCollection_List.hxx>
87 #include <Precision.hxx>
88 #include <Standard_ConstructionError.hxx>
89 #include <Standard_NotImplemented.hxx>
90 #include <TColStd_ListIteratorOfListOfInteger.hxx>
91 #include <TopExp.hxx>
92 #include <TopExp_Explorer.hxx>
93 #include <TopoDS.hxx>
94 #include <TopoDS_Compound.hxx>
95 #include <TopoDS_Edge.hxx>
96 #include <TopoDS_Face.hxx>
97 #include <TopoDS_Iterator.hxx>
98 #include <TopoDS_Shape.hxx>
99 #include <TopoDS_Shell.hxx>
100 #include <TopoDS_Solid.hxx>
101 #include <TopoDS_Vertex.hxx>
102 #include <TopoDS_Wire.hxx>
103 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
104 #include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
105 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
106 #include <TopTools_DataMapOfShapeShape.hxx>
107 #include <TopTools_IndexedMapOfShape.hxx>
108 #include <TopTools_ListIteratorOfListOfShape.hxx>
109 #include <TopTools_ListOfShape.hxx>
110 #include <TopTools_MapIteratorOfMapOfShape.hxx>
111 #include <TopTools_MapOfShape.hxx>
112 #include <TopTools_SequenceOfShape.hxx>
113 #include <BRepBuilderAPI_Sewing.hxx>
114 #include <Geom_Line.hxx>
115 #include <NCollection_Vector.hxx>
116 #include <NCollection_IncAllocator.hxx>
117 //
118 #include <BOPAlgo_MakerVolume.hxx>
119 #include <BOPTools_AlgoTools.hxx>
120 
121 #include <stdio.h>
122 // POP for NT
123 #ifdef DRAW
124 
125 #include <DBRep.hxx>
126 #endif
127 #ifdef OCCT_DEBUG
128 #include <OSD_Chronometer.hxx>
129 //#define DEB_VERB
130   Standard_Boolean AffichInt2d = Standard_False;
131   Standard_Boolean AffichOffC  = Standard_False;
132   Standard_Boolean ChronBuild  = Standard_False;
133   Standard_Integer NbAE        = 0;
134   Standard_Integer NbAF        = 0;
135   Standard_Integer NVP        = 0;
136   Standard_Integer NVM        = 0;
137   Standard_Integer NVN        = 0;
138   static OSD_Chronometer  Clock;
139   char name[100];
140 
141 
142 
143 
144 //=======================================================================
145 //function :  DEBVerticesControl
146 //purpose  :
147 //=======================================================================
148 
DEBVerticesControl(const TopTools_IndexedMapOfShape & NewEdges,Handle (BRepAlgo_AsDes)AsDes)149 static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
150                                       Handle(BRepAlgo_AsDes)      AsDes)
151 {
152   TopTools_ListOfShape               LVP;
153   TopTools_ListIteratorOfListOfShape it1LE ;
154   TopTools_ListIteratorOfListOfShape it2LE ;
155 
156   Standard_Integer i;
157   for (i = 1; i <= NewEdges.Extent(); i++) {
158     const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i));
159     if (AsDes->HasDescendant(NE)) {
160       for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
161         if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
162           LVP.Append(it1LE.Value());
163           std::cout <<"Vertex on at least 3 edges."<<std::endl;
164 #ifdef DRAW
165           if (AffichInt2d) {
166             sprintf (name,"VP_%d",NVP++);
167             DBRep::Set(name,it1LE.Value());
168           }
169 #endif
170         }
171         else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
172           std::cout <<"Vertex on more than 3 edges."<<std::endl;
173 #ifdef DRAW
174           if (AffichInt2d) {
175             sprintf (name,"VM_%d",NVM++);
176             DBRep::Set(name,it1LE.Value());
177           }
178 #endif
179 
180         }
181         else {
182 #ifdef DRAW
183           if (AffichInt2d) {
184             sprintf (name,"VN_%d",NVN++);
185             DBRep::Set(name,it1LE.Value());
186           }
187 #endif
188         }
189       }
190     }
191   }
192   //------------------------------------------------
193   // Try to mix spoiled vertices.
194   //------------------------------------------------
195   BRep_Builder B;
196   TopTools_ListIteratorOfListOfShape it1(LVP);
197   Standard_Real                      TolConf = 1.e-5;
198   Standard_Real                      Tol     = Precision::Confusion();
199   //Standard_Integer                   i = 1;
200 
201   i = 1;
202   for ( ; it1.More(); it1.Next()) {
203     TopoDS_Shape   V1 = it1.Value();
204     gp_Pnt         P1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
205     Standard_Real  distmin = Precision::Infinite();
206     TopTools_ListIteratorOfListOfShape it2(LVP);
207     Standard_Integer j = 1;
208 
209     for ( ; it2.More(); it2.Next()) {
210       if (j > i) {
211         TopoDS_Shape V2 = it2.Value();
212         gp_Pnt       P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
213         if (!V1.IsSame(V2)) {
214           Standard_Real       dist    = P1.Distance(P2);
215           if (dist < distmin) distmin = dist;
216           if (dist < TolConf) {
217             Standard_Real UV2;
218             TopoDS_Edge   EWE2;
219             const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
220             TopTools_ListIteratorOfListOfShape itAsDes;
221             for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
222               EWE2  = TopoDS::Edge(itAsDes.Value());
223               TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
224               UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
225               aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
226               B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
227 //              UV2   =
228 //                BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
229 //              B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
230 //                             UV2,EWE2,Tol);
231             }
232             AsDes->Replace(V2,V1);
233           }
234         }
235       }
236       j++;
237     }
238     i++;
239     std::cout <<" distmin between VP : "<<distmin<<std::endl;
240   }
241 }
242 #endif
243 
244 namespace
245 {
246   //=======================================================================
247   //function : BRepOffset_PIOperation
248   //purpose  : List of operations to be supported by the Progress Indicator
249   //=======================================================================
250   enum BRepOffset_PIOperation
251   {
252     PIOperation_CheckInputData = 0,
253     PIOperation_Analyse,
254     PIOperation_BuildOffsetBy,
255     PIOperation_Intersection,
256     PIOperation_MakeMissingWalls,
257     PIOperation_MakeShells,
258     PIOperation_MakeSolid,
259     PIOperation_Sewing,
260     PIOperation_Last
261   };
262 
263   //=======================================================================
264   //function : normalizeSteps
265   //purpose  : Normalization of progress steps
266   //=======================================================================
normalizeSteps(const Standard_Real theWhole,TColStd_Array1OfReal & theSteps)267   static void normalizeSteps(const Standard_Real theWhole,
268                              TColStd_Array1OfReal& theSteps)
269   {
270     Standard_Real aSum = 0.;
271     for (Standard_Integer i = theSteps.Lower(); i <= theSteps.Upper(); ++i)
272     {
273       aSum += theSteps(i);
274     }
275 
276     // Normalize steps
277     for (Standard_Integer i = theSteps.Lower(); i <= theSteps.Upper(); ++i)
278     {
279       theSteps(i) = theWhole * theSteps(i) / aSum;
280     }
281   }
282 
283 }
284 
285 //=======================================================================
286 // static methods
287 //=======================================================================
288 static
289   void GetEnlargedFaces(const TopTools_ListOfShape& theFaces,
290                         const BRepOffset_DataMapOfShapeOffset& theMapSF,
291                         const TopTools_DataMapOfShapeShape& theMES,
292                         TopTools_DataMapOfShapeShape& theFacesOrigins,
293                         BRepAlgo_Image& theImage,
294                         TopTools_ListOfShape& theLSF);
295 
296 static
297   Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
298                                             BRepAlgo_Image& theImage,
299                                             TopoDS_Shape& theShells,
300                                             const Message_ProgressRange& theRange);
301 
302 static
303   Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
304                                 const TopAbs_ShapeEnum theSSType,
305                                 TopoDS_Shape& theResult);
306 
307 static
308   void UpdateInitOffset(BRepAlgo_Image&         myInitOffset,
309                         BRepAlgo_Image&         myImageOffset,
310                         const TopoDS_Shape&     myOffsetShape,
311                         const TopAbs_ShapeEnum &theShapeType);
312 
313 static
314   void RemoveShapes(TopoDS_Shape& theS,
315                     const TopTools_ListOfShape& theLS);
316 
317 static
318   Standard_Boolean IsSolid(const TopoDS_Shape& theS);
319 
320 static
321   void UpdateHistory(const TopTools_ListOfShape& theLF,
322                      BOPAlgo_Builder& theGF,
323                      BRepAlgo_Image& theImage);
324 
325 static
326 void RemoveSeamAndDegeneratedEdges(const TopoDS_Face& theFace,
327                                    const TopoDS_Face& theOldFace);
328 
329 static
330   Standard_Boolean TrimEdge(TopoDS_Edge& NE,
331                             const Handle(BRepAlgo_AsDes)& AsDes2d,
332                             Handle(BRepAlgo_AsDes)& AsDes,
333                             TopTools_DataMapOfShapeShape& theETrimEInf);
334 
335 static
336   Standard_Boolean TrimEdges(const TopoDS_Shape& theShape,
337                              const Standard_Real theOffset,
338                              const BRepOffset_Analyse& Analyse,
339                              BRepOffset_DataMapOfShapeOffset& theMapSF,
340                              TopTools_DataMapOfShapeShape& theMES,
341                              TopTools_DataMapOfShapeShape& theBuild,
342                              Handle(BRepAlgo_AsDes)& theAsDes,
343                              Handle(BRepAlgo_AsDes)& theAsDes2d,
344                              TopTools_IndexedMapOfShape& theNewEdges,
345                              TopTools_DataMapOfShapeShape& theETrimEInf,
346                              TopTools_DataMapOfShapeListOfShape& theEdgesOrigins);
347 
348 static
349   void AppendToList(TopTools_ListOfShape& theL,
350                     const TopoDS_Shape& theS);
351 
352 static BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
353                                          const Standard_Real theVParam,
354                                          const Handle(Geom_Surface)& theSurf,
355                                          const NCollection_Vector<gp_Pnt>& theBadPoints);
356 
357 //---------------------------------------------------------------------
358 static void UpdateTolerance (      TopoDS_Shape&               myShape,
359                              const TopTools_IndexedMapOfShape& myFaces);
360 static Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
361                                     const Handle(Geom_Curve)& theCrv,
362                                     const Standard_Real theFirst,
363                                     const Standard_Real theLast);
364 
365 static void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList);
366 //---------------------------------------------------------------------
367 
OrientationOfEdgeInFace(const TopoDS_Edge & theEdge,const TopoDS_Face & theFace)368 static TopAbs_Orientation OrientationOfEdgeInFace(const TopoDS_Edge& theEdge,
369                                                   const TopoDS_Face& theFace)
370 {
371   TopAbs_Orientation anOr = TopAbs_EXTERNAL;
372 
373   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
374   for (; Explo.More(); Explo.Next())
375   {
376     const TopoDS_Shape& anEdge = Explo.Current();
377     if (anEdge.IsSame(theEdge))
378     {
379       anOr = anEdge.Orientation();
380       break;
381     }
382   }
383 
384   return anOr;
385 }
386 
387 //
FindParameter(const TopoDS_Vertex & V,const TopoDS_Edge & E,Standard_Real & U)388 static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
389                                       const TopoDS_Edge& E,
390                                       Standard_Real& U)
391 {
392   // Search the vertex in the edge
393 
394   Standard_Boolean rev = Standard_False;
395   TopoDS_Shape VF;
396   TopAbs_Orientation orient = TopAbs_INTERNAL;
397 
398   TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
399 
400   // if the edge has no vertices
401   // and is degenerated use the vertex orientation
402   // RLE, june 94
403 
404   if (!itv.More() && BRep_Tool::Degenerated(E)) {
405     orient = V.Orientation();
406   }
407 
408   while (itv.More()) {
409     const TopoDS_Shape& Vcur = itv.Value();
410     if (V.IsSame(Vcur)) {
411       if (VF.IsNull()) {
412         VF = Vcur;
413       }
414       else {
415         rev = E.Orientation() == TopAbs_REVERSED;
416         if (Vcur.Orientation() == V.Orientation()) {
417           VF = Vcur;
418         }
419       }
420     }
421     itv.Next();
422   }
423 
424   if (!VF.IsNull()) orient = VF.Orientation();
425 
426   Standard_Real f,l;
427 
428   if (orient ==  TopAbs_FORWARD) {
429     BRep_Tool::Range(E,f,l);
430     //return (rev) ? l : f;
431     U = (rev) ? l : f;
432     return Standard_True;
433   }
434 
435   else if (orient ==  TopAbs_REVERSED) {
436     BRep_Tool::Range(E,f,l);
437     //return (rev) ? f : l;
438     U = (rev) ? f : l;
439     return Standard_True;
440    }
441 
442   else {
443     TopLoc_Location L;
444     const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
445     L = L.Predivided(V.Location());
446     if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
447       BRep_ListIteratorOfListOfPointRepresentation itpr
448         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
449 
450       while (itpr.More()) {
451         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
452         if (pr->IsPointOnCurve(C,L)) {
453           Standard_Real p = pr->Parameter();
454           Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
455           if (!C.IsNull()) {
456             // Closed curves RLE 16 june 94
457             if (Precision::IsNegativeInfinite(f))
458               {
459                 //return pr->Parameter();//p;
460                 U = pr->Parameter();
461                 return Standard_True;
462               }
463             if (Precision::IsPositiveInfinite(l))
464               {
465                 //return pr->Parameter();//p;
466                 U = pr->Parameter();
467                 return Standard_True;
468               }
469             gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
470             gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
471             Standard_Real tol = BRep_Tool::Tolerance(V);
472             if (Pf.Distance(Pl) < tol) {
473               if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
474                 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
475                 else                                   res = l;//p = l;
476               }
477             }
478           }
479           //return res;//p;
480           U = res;
481           return Standard_True;
482         }
483         itpr.Next();
484       }
485     }
486     else {
487       // no 3d curve !!
488       // let us try with the first pcurve
489       Handle(Geom2d_Curve) PC;
490       Handle(Geom_Surface) S;
491       BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
492       L = L.Predivided(V.Location());
493       BRep_ListIteratorOfListOfPointRepresentation itpr
494         ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
495 
496       while (itpr.More()) {
497         const Handle(BRep_PointRepresentation)& pr = itpr.Value();
498         if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
499           Standard_Real p = pr->Parameter();
500           // Closed curves RLE 16 june 94
501           if (PC->IsClosed()) {
502             if ((p == PC->FirstParameter()) ||
503                 (p == PC->LastParameter())) {
504               if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
505               else                                   p = PC->LastParameter();
506             }
507           }
508           //return p;
509           U = p;
510           return Standard_True;
511         }
512         itpr.Next();
513       }
514     }
515   }
516 
517   //throw Standard_NoSuchObject("BRep_Tool:: no parameter on edge");
518   return Standard_False;
519 }
520 
521 //=======================================================================
522 //function : GetEdgePoints
523 //purpose  : gets the first, last and middle points of the edge
524 //=======================================================================
GetEdgePoints(const TopoDS_Edge & anEdge,const TopoDS_Face & aFace,gp_Pnt & fPnt,gp_Pnt & mPnt,gp_Pnt & lPnt)525 static void GetEdgePoints(const TopoDS_Edge& anEdge,
526                                       const TopoDS_Face& aFace,
527                                       gp_Pnt& fPnt, gp_Pnt& mPnt,
528                                       gp_Pnt& lPnt)
529 {
530   Standard_Real f, l;
531   Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
532   gp_Pnt2d fPnt2d = theCurve->Value(f);
533   gp_Pnt2d lPnt2d = theCurve->Value(l);
534   gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
535   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
536   fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
537   lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
538   mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
539 }
540 
541 //=======================================================================
542 //function : FillContours
543 //purpose  : fills free boundary contours and faces connected (MapEF)
544 //=======================================================================
FillContours(const TopoDS_Shape & aShape,const BRepOffset_Analyse & Analyser,TopTools_IndexedDataMapOfShapeListOfShape & Contours,TopTools_DataMapOfShapeShape & MapEF)545 static void FillContours(const TopoDS_Shape& aShape,
546                          const BRepOffset_Analyse& Analyser,
547                          TopTools_IndexedDataMapOfShapeListOfShape& Contours,
548                          TopTools_DataMapOfShapeShape& MapEF)
549 {
550   TopTools_ListOfShape Edges;
551 
552   TopExp_Explorer Explo(aShape, TopAbs_FACE);
553   BRepTools_WireExplorer Wexp;
554 
555   for (; Explo.More(); Explo.Next())
556   {
557     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
558     TopoDS_Iterator itf(aFace);
559     for (; itf.More(); itf.Next())
560     {
561       TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
562       for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
563       {
564         TopoDS_Edge anEdge = Wexp.Current();
565         if (BRep_Tool::Degenerated(anEdge))
566           continue;
567         const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
568         if (!Lint.IsEmpty() && Lint.First().Type() == ChFiDS_FreeBound)
569         {
570           MapEF.Bind(anEdge, aFace);
571           Edges.Append(anEdge);
572         }
573       }
574     }
575   }
576 
577   TopTools_ListIteratorOfListOfShape itl;
578   while (!Edges.IsEmpty())
579     {
580       TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
581       Edges.RemoveFirst();
582       TopoDS_Vertex StartVertex, CurVertex;
583       TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
584       TopTools_ListOfShape aContour;
585       aContour.Append(StartEdge);
586       while (!CurVertex.IsSame(StartVertex))
587         for (itl.Initialize(Edges); itl.More(); itl.Next())
588           {
589             TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
590             TopoDS_Vertex V1, V2;
591             TopExp::Vertices(anEdge, V1, V2);
592             if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
593               {
594                 aContour.Append(anEdge);
595                 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
596                 Edges.Remove(itl);
597                 break;
598               }
599           }
600       Contours.Add(StartVertex, aContour);
601     }
602 }
603 
604 //
605 //-----------------------------------------------------------------------
606 //
607 //=======================================================================
608 //function : BRepOffset_MakeOffset
609 //purpose  :
610 //=======================================================================
611 
BRepOffset_MakeOffset()612 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
613 {
614   myAsDes = new BRepAlgo_AsDes();
615 }
616 
617 
618 //=======================================================================
619 //function : BRepOffset_MakeOffset
620 //purpose  :
621 //=======================================================================
622 
BRepOffset_MakeOffset(const TopoDS_Shape & S,const Standard_Real Offset,const Standard_Real Tol,const BRepOffset_Mode Mode,const Standard_Boolean Inter,const Standard_Boolean SelfInter,const GeomAbs_JoinType Join,const Standard_Boolean Thickening,const Standard_Boolean RemoveIntEdges,const Message_ProgressRange & theRange)623 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S,
624                                              const Standard_Real    Offset,
625                                              const Standard_Real    Tol,
626                                              const BRepOffset_Mode  Mode,
627                                              const Standard_Boolean Inter,
628                                              const Standard_Boolean SelfInter,
629                                              const GeomAbs_JoinType Join,
630                                              const Standard_Boolean Thickening,
631                                              const Standard_Boolean RemoveIntEdges,
632                                              const Message_ProgressRange& theRange)
633 :
634 myOffset     (Offset),
635 myTol        (Tol),
636 myInitialShape (S),
637 myShape      (S),
638 myMode       (Mode),
639 myInter      (Inter),
640 mySelfInter  (SelfInter),
641 myJoin       (Join),
642 myThickening    (Thickening),
643 myRemoveIntEdges(RemoveIntEdges),
644 myDone     (Standard_False)
645 {
646   myAsDes = new BRepAlgo_AsDes();
647   myIsLinearizationAllowed = Standard_True;
648 
649   MakeOffsetShape(theRange);
650 }
651 
652 
653 //=======================================================================
654 //function : Initialize
655 //purpose  :
656 //=======================================================================
657 
Initialize(const TopoDS_Shape & S,const Standard_Real Offset,const Standard_Real Tol,const BRepOffset_Mode Mode,const Standard_Boolean Inter,const Standard_Boolean SelfInter,const GeomAbs_JoinType Join,const Standard_Boolean Thickening,const Standard_Boolean RemoveIntEdges)658 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S,
659                                        const Standard_Real    Offset,
660                                        const Standard_Real    Tol,
661                                        const BRepOffset_Mode  Mode,
662                                        const Standard_Boolean Inter,
663                                        const Standard_Boolean SelfInter,
664                                        const GeomAbs_JoinType Join,
665                                        const Standard_Boolean Thickening,
666                                        const Standard_Boolean RemoveIntEdges)
667 {
668   myOffset     = Offset;
669   myInitialShape = S;
670   myShape      = S;
671   myTol        = Tol;
672   myMode       = Mode;
673   myInter      = Inter;
674   mySelfInter  = SelfInter;
675   myJoin       = Join;
676   myThickening     = Thickening;
677   myRemoveIntEdges = RemoveIntEdges;
678   myIsLinearizationAllowed = Standard_True;
679   myDone     = Standard_False;
680   myIsPerformSewing = Standard_False;
681   myIsPlanar = Standard_False;
682   Clear();
683 }
684 
685 
686 //=======================================================================
687 //function : Clear
688 //purpose  :
689 //=======================================================================
690 
Clear()691 void BRepOffset_MakeOffset::Clear()
692 {
693   myOffsetShape.Nullify();
694   myInitOffsetFace .Clear();
695   myInitOffsetEdge .Clear();
696   myImageOffset    .Clear();
697   myImageVV        .Clear();
698   myFaces          .Clear();
699   myOriginalFaces  .Clear();
700   myFaceOffset     .Clear();
701   myEdgeIntEdges   .Clear();
702   myAsDes          ->Clear();
703   myDone     = Standard_False;
704   myGenerated.Clear();
705   myResMap.Clear();
706 }
707 
708 //=======================================================================
709 //function : AllowLinearization
710 //purpose  :
711 //=======================================================================
712 
AllowLinearization(const Standard_Boolean theIsAllowed)713 void BRepOffset_MakeOffset::AllowLinearization(const Standard_Boolean theIsAllowed)
714 {
715   myIsLinearizationAllowed = theIsAllowed;
716 }
717 
718 //=======================================================================
719 //function : AddFace
720 //purpose  :
721 //=======================================================================
722 
AddFace(const TopoDS_Face & F)723 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
724 
725   myOriginalFaces.Add(F);
726 }
727 
728 //=======================================================================
729 //function : SetOffsetOnFace
730 //purpose  :
731 //=======================================================================
732 
SetOffsetOnFace(const TopoDS_Face & F,const Standard_Real Off)733 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face&  F,
734                                             const Standard_Real Off)
735 {
736   myFaceOffset.Bind(F, Off);
737 }
738 
739 //=======================================================================
740 //function : RemoveCorks
741 //purpose  :
742 //=======================================================================
743 
RemoveCorks(TopoDS_Shape & S,TopTools_IndexedMapOfShape & Faces)744 static void RemoveCorks (TopoDS_Shape&               S,
745                          TopTools_IndexedMapOfShape& Faces)
746 {
747   TopoDS_Compound SS;
748   BRep_Builder    B;
749   B.MakeCompound (SS);
750   //-----------------------------------------------------
751   // Construction of a shape without caps.
752   // and Orientation of caps as in shape S.
753   //-----------------------------------------------------
754   TopExp_Explorer exp(S,TopAbs_FACE);
755   for (; exp.More(); exp.Next()) {
756     const TopoDS_Shape& Cork = exp.Current();
757     if (!Faces.Contains(Cork)) {
758       B.Add(SS,Cork);
759     }
760     else {
761       Faces.RemoveKey(Cork);
762       Faces.Add(Cork); // to reset it with proper orientation.
763     }
764   }
765   S = SS;
766 #ifdef DRAW
767   if ( AffichOffC)
768     DBRep::Set("myInit", SS);
769 #endif
770 
771 }
772 
773 //=======================================================================
774 //function : IsConnectedShell
775 //purpose  :
776 //=======================================================================
IsConnectedShell(const TopoDS_Shape & S)777 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
778 {
779   BRepTools_Quilt Glue;
780   Glue.Add( S );
781 
782   TopoDS_Shape SS = Glue.Shells();
783   TopExp_Explorer Explo( SS, TopAbs_SHELL );
784   Explo.Next();
785   if (Explo.More())
786     return Standard_False;
787 
788   return Standard_True;
789 }
790 
791 
792 //=======================================================================
793 //function : MakeList
794 //purpose  :
795 //=======================================================================
796 
MakeList(TopTools_ListOfShape & OffsetFaces,const BRepAlgo_Image & myInitOffsetFace,const TopTools_IndexedMapOfShape & myFaces)797 static void MakeList (TopTools_ListOfShape&             OffsetFaces,
798                       const BRepAlgo_Image&             myInitOffsetFace,
799                       const TopTools_IndexedMapOfShape& myFaces)
800 {
801   TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
802   for ( ; itLOF.More(); itLOF.Next()) {
803     const TopoDS_Shape& Root = itLOF.Value();
804     if (!myFaces.Contains(Root)) {
805       if (myInitOffsetFace.HasImage(Root)) {
806         TopTools_ListIteratorOfListOfShape aItLS(myInitOffsetFace.Image(Root));
807         for (; aItLS.More(); aItLS.Next()) {
808           OffsetFaces.Append(aItLS.Value());
809         }
810       }
811     }
812   }
813 }
814 
815 //=======================================================================
816 //function : EvalMax
817 //purpose  :
818 //=======================================================================
819 
EvalMax(const TopoDS_Shape & S,Standard_Real & Tol)820 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
821 {
822   TopExp_Explorer exp;
823   for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
824     const TopoDS_Vertex& V    = TopoDS::Vertex(exp.Current());
825     Standard_Real        TolV = BRep_Tool::Tolerance(V);
826     if (TolV > Tol) Tol = TolV;
827   }
828 }
829 
830 //=======================================================================
831 //function : SetFaces
832 //purpose  :
833 //=======================================================================
834 
SetFaces()835 void BRepOffset_MakeOffset::SetFaces()
836 {
837   for (Standard_Integer ii = 1; ii <= myOriginalFaces.Extent(); ii++)
838   {
839     TopoDS_Face aFace = TopoDS::Face(myOriginalFaces(ii));
840     const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aFace);
841     if (aPlanface)
842       aFace = TopoDS::Face(*aPlanface);
843 
844     myFaces.Add(aFace);
845     //-------------
846     // MAJ SD.
847     //-------------
848     myInitOffsetFace.SetRoot (aFace)  ;
849     myInitOffsetFace.Bind    (aFace, aFace);
850     myImageOffset.SetRoot    (aFace)  ;
851   }
852 }
853 
854 //=======================================================================
855 //function : SetFacesWithOffset
856 //purpose  :
857 //=======================================================================
858 
SetFacesWithOffset()859 void BRepOffset_MakeOffset::SetFacesWithOffset()
860 {
861   TopTools_DataMapIteratorOfDataMapOfShapeShape anItmap(myFacePlanfaceMap);
862   for (; anItmap.More(); anItmap.Next())
863   {
864     TopoDS_Face aFace = TopoDS::Face(anItmap.Key());
865     TopoDS_Face aPlanface = TopoDS::Face(anItmap.Value());
866     if (myFaceOffset.IsBound(aFace))
867     {
868       Standard_Real anOffset = myFaceOffset(aFace);
869       myFaceOffset.UnBind(aFace);
870       myFaceOffset.Bind(aPlanface, anOffset);
871     }
872   }
873 }
874 
875 //=======================================================================
876 //function : MakeOffsetShape
877 //purpose  :
878 //=======================================================================
879 
MakeOffsetShape(const Message_ProgressRange & theRange)880 void BRepOffset_MakeOffset::MakeOffsetShape(const Message_ProgressRange& theRange)
881 {
882   myDone = Standard_False;
883   //
884 
885   // check if shape consists of only planar faces
886   myIsPlanar = IsPlanar();
887 
888   SetFaces();
889   SetFacesWithOffset();
890 
891   BuildFaceComp();
892 
893   //------------------------------------------
894   // Construction of myShape without caps.
895   //------------------------------------------
896   if(!myFaces.IsEmpty())
897   {
898     RemoveCorks (myShape, myOriginalFaces);
899     RemoveCorks (myFaceComp, myFaces);
900   }
901 
902   Message_ProgressScope aPS(theRange, "Making offset shape", 100);
903 
904   TColStd_Array1OfReal aSteps(0, PIOperation_Last - 1);
905   analyzeProgress(100., aSteps);
906 
907   if (!CheckInputData(aPS.Next(aSteps(PIOperation_CheckInputData))) || myError != BRepOffset_NoError)
908   {
909     // There is error in input data.
910     // Check Error() method.
911     return;
912   }
913   myError = BRepOffset_NoError;
914   TopAbs_State       Side = TopAbs_IN;
915   if (myOffset < 0.) Side = TopAbs_OUT;
916 
917   // ------------
918   // Preanalyse.
919   // ------------
920   EvalMax(myShape,myTol);
921   // There are possible second variant: analytical continuation of arcsin.
922   Standard_Real TolAngleCoeff = Min(myTol / (Abs(myOffset * 0.5) + Precision::Confusion()), 1.0);
923   Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
924   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar)
925   {
926     myAnalyse.SetOffsetValue (myOffset);
927     myAnalyse.SetFaceOffsetMap (myFaceOffset);
928   }
929   myAnalyse.Perform(myFaceComp,TolAngle, aPS.Next(aSteps(PIOperation_Analyse)));
930   if (!aPS.More())
931   {
932     myError = BRepOffset_UserBreak;
933     return;
934   }
935   //---------------------------------------------------
936   // Construction of Offset from preanalysis.
937   //---------------------------------------------------
938   //----------------------------
939   // MaJ of SD Face - Offset
940   //----------------------------
941   UpdateFaceOffset();
942 
943   if (myJoin == GeomAbs_Arc)
944     BuildOffsetByArc(aPS.Next(aSteps(PIOperation_BuildOffsetBy)));
945   else if (myJoin == GeomAbs_Intersection)
946     BuildOffsetByInter(aPS.Next(aSteps(PIOperation_BuildOffsetBy)));
947   if (myError != BRepOffset_NoError)
948   {
949     return;
950   }
951   //-----------------
952   // Auto unwinding.
953   //-----------------
954   // if (mySelfInter)  SelfInter(Modif);
955   //-----------------
956   // Intersection 3d .
957   //-----------------
958   Message_ProgressScope aPSInter(aPS.Next(aSteps(PIOperation_Intersection)), NULL, 100);
959   aPSInter.SetName((myJoin == GeomAbs_Arc) ? "Connect offset faces by arc" :
960                                              "Connect offset faces by intersection");
961 
962   BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
963   Intersection3D (Inter, aPSInter.Next(90));
964   if (myError != BRepOffset_NoError)
965   {
966     return;
967   }
968   //-----------------
969   // Intersection2D
970   //-----------------
971   TopTools_IndexedMapOfShape& Modif    = Inter.TouchedFaces();
972   TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
973 
974   if (!Modif.IsEmpty())
975   {
976     Intersection2D(Modif, NewEdges, aPSInter.Next(4));
977     if (myError != BRepOffset_NoError)
978     {
979       return;
980     }
981   }
982 
983   //-------------------------------------------------------
984   // Unwinding 2D and reconstruction of modified faces
985   //----------------------------------------------------
986   MakeLoops (Modif, aPSInter.Next(4));
987   if (myError != BRepOffset_NoError)
988   {
989     return;
990   }
991   //-----------------------------------------------------
992   // Reconstruction of non modified faces sharing
993   // reconstructed edges
994   //------------------------------------------------------
995   if (!Modif.IsEmpty())
996   {
997     MakeFaces(Modif, aPSInter.Next(2));
998     if (myError != BRepOffset_NoError)
999     {
1000       return;
1001     }
1002   }
1003 
1004   aPSInter.Close();
1005 
1006   if (myThickening)
1007   {
1008     MakeMissingWalls(aPS.Next(aSteps(PIOperation_MakeMissingWalls)));
1009     if (myError != BRepOffset_NoError)
1010     {
1011       return;
1012     }
1013   }
1014 
1015   //-------------------------
1016   // Construction of shells.
1017   //-------------------------
1018   MakeShells (aPS.Next(aSteps(PIOperation_MakeShells)));
1019   if (myError != BRepOffset_NoError)
1020   {
1021     return;
1022   }
1023   if (myOffsetShape.IsNull()) {
1024     // not done
1025     myDone = Standard_False;
1026     return;
1027   }
1028   //--------------
1029   // Unwinding 3D.
1030   //--------------
1031   SelectShells ();
1032   //----------------------------------
1033   // Remove INTERNAL edges if necessary
1034   //----------------------------------
1035   if (myRemoveIntEdges) {
1036     RemoveInternalEdges();
1037   }
1038   //----------------------------------
1039   // Coding of regularities.
1040   //----------------------------------
1041   EncodeRegularity();
1042   //----------------------------------
1043   // Replace roots in history maps
1044   //----------------------------------
1045   ReplaceRoots();
1046   //----------------------
1047   // Creation of solids.
1048   //----------------------
1049   MakeSolid (aPS.Next(aSteps(PIOperation_MakeSolid)));
1050   if (myError != BRepOffset_NoError)
1051   {
1052     return;
1053   }
1054   //-----------------------------
1055   // MAJ Tolerance edge and Vertex
1056   // ----------------------------
1057   if (!myOffsetShape.IsNull()) {
1058     UpdateTolerance (myOffsetShape,myFaces);
1059     BRepLib::UpdateTolerances( myOffsetShape );
1060   }
1061 
1062   CorrectConicalFaces();
1063 
1064   // Result solid should be computed in MakeOffset scope.
1065   if (myThickening &&
1066       myIsPerformSewing)
1067   {
1068     BRepBuilderAPI_Sewing aSew(myTol);
1069     aSew.Add(myOffsetShape);
1070     aSew.Perform(aPS.Next(aSteps(PIOperation_Sewing) / 2.));
1071     if (!aPS.More())
1072     {
1073       myError = BRepOffset_UserBreak;
1074       return;
1075     }
1076     myOffsetShape = aSew.SewedShape();
1077 
1078     // Rebuild solid.
1079     // Offset shape expected to be really closed after sewing.
1080     myOffsetShape.Closed(Standard_True);
1081     MakeSolid(aPS.Next(aSteps(PIOperation_Sewing) / 2.));
1082     if (myError != BRepOffset_NoError)
1083     {
1084       return;
1085     }
1086   }
1087 
1088   myDone = Standard_True;
1089 }
1090 
1091 
1092 
1093 //=======================================================================
1094 //function : MakeThickSolid
1095 //purpose  :
1096 //=======================================================================
1097 
MakeThickSolid(const Message_ProgressRange & theRange)1098 void BRepOffset_MakeOffset::MakeThickSolid(const Message_ProgressRange& theRange)
1099 {
1100   //--------------------------------------------------------------
1101   // Construction of shell parallel to shell (initial without cap).
1102   //--------------------------------------------------------------
1103   MakeOffsetShape (theRange);
1104 
1105   if (!myDone)
1106   {
1107     // Save return code and myDone state.
1108     return;
1109   }
1110 
1111   //--------------------------------------------------------------------
1112   // Construction of a solid with the initial shell, parallel shell
1113   // limited by caps.
1114   //--------------------------------------------------------------------
1115   if (!myFaces.IsEmpty())
1116   {
1117     TopoDS_Solid    Res;
1118     TopExp_Explorer exp;
1119     BRep_Builder    B;
1120     Standard_Integer NbF = myFaces.Extent();
1121 
1122     B.MakeSolid(Res);
1123 
1124     BRepTools_Quilt Glue;
1125     for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next())
1126     {
1127       NbF++;
1128       Glue.Add (exp.Current());
1129     }
1130     Standard_Boolean YaResult = 0;
1131     if (!myOffsetShape.IsNull())
1132       {
1133       for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
1134         {
1135         YaResult = 1;
1136         Glue.Add (exp.Current().Reversed());
1137         }
1138 #ifdef OCCT_DEBUG
1139       if(YaResult == 0)
1140         {
1141         std::cout << "OffsetShape does not contain a FACES." << std::endl;
1142         }
1143 #endif
1144       }
1145 #ifdef OCCT_DEBUG
1146     else
1147       {
1148       std::cout << "OffsetShape is null!" << std::endl;
1149       }
1150 #endif
1151 
1152     if (YaResult == 0)
1153       {
1154       myDone = Standard_False;
1155       myError = BRepOffset_UnknownError;
1156       return;
1157       }
1158 
1159     myOffsetShape = Glue.Shells();
1160     for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next())
1161     {
1162       B.Add(Res,exp.Current());
1163     }
1164     Res.Closed(Standard_True);
1165     myOffsetShape = Res;
1166 
1167     // Test of Validity of the result of thick Solid
1168     // more face than the initial solid.
1169     Standard_Integer NbOF = 0;
1170     for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
1171     {
1172       NbOF++;
1173     }
1174     if (NbOF <= NbF)
1175     {
1176       myDone = Standard_False;
1177       myError = BRepOffset_UnknownError;
1178       return;
1179     }
1180   }
1181 
1182   if (myOffset > 0 ) myOffsetShape.Reverse();
1183 
1184   myDone = Standard_True;
1185 }
1186 
1187 //=======================================================================
1188 //function : IsDone
1189 //purpose  :
1190 //=======================================================================
1191 
IsDone() const1192 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
1193 {
1194   return myDone;
1195 }
1196 
1197 //=======================================================================
1198 //function : Error
1199 //purpose  :
1200 //=======================================================================
1201 
Error() const1202 BRepOffset_Error BRepOffset_MakeOffset::Error() const
1203 {
1204   return myError;
1205 }
1206 
1207 //=======================================================================
1208 //function : Shape
1209 //purpose  :
1210 //=======================================================================
1211 
Shape() const1212 const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const
1213 {
1214   return myOffsetShape;
1215 }
1216 
1217 //=======================================================================
1218 //function : MakeOffsetFaces
1219 //purpose  :
1220 //=======================================================================
MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset & theMapSF,const Message_ProgressRange & theRange)1221 void BRepOffset_MakeOffset::MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF, const Message_ProgressRange& theRange)
1222 {
1223   Standard_Real aCurOffset;
1224   TopTools_ListOfShape aLF;
1225   TopTools_DataMapOfShapeShape ShapeTgt;
1226   TopTools_ListIteratorOfListOfShape aItLF;
1227   //
1228   Standard_Boolean OffsetOutside = (myOffset > 0.);
1229   //
1230   BRepLib::SortFaces(myFaceComp, aLF);
1231   //
1232   Message_ProgressScope aPS(theRange, "Making offset faces", aLF.Size());
1233   aItLF.Initialize(aLF);
1234   for (; aItLF.More(); aItLF.Next(), aPS.Next()) {
1235     if (!aPS.More())
1236     {
1237       myError = BRepOffset_UserBreak;
1238       return;
1239     }
1240     const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
1241     aCurOffset = myFaceOffset.IsBound(aF) ? myFaceOffset(aF) : myOffset;
1242     BRepOffset_Offset OF(aF, aCurOffset, ShapeTgt, OffsetOutside, myJoin);
1243     TopTools_ListOfShape Let;
1244     myAnalyse.Edges(aF,ChFiDS_Tangential,Let);
1245     TopTools_ListIteratorOfListOfShape itl(Let);
1246     for (; itl.More(); itl.Next()) {
1247       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1248       if ( !ShapeTgt.IsBound(Cur) && !myAnalyse.HasGenerated (Cur)) {
1249         TopoDS_Shape aLocalShape = OF.Generated(Cur);
1250         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1251         ShapeTgt.Bind(Cur,OF.Generated(Cur));
1252         TopoDS_Vertex V1,V2,OV1,OV2;
1253         TopExp::Vertices (Cur,V1,V2);
1254         TopExp::Vertices (OTE,OV1,OV2);
1255         TopTools_ListOfShape LE;
1256         if (!ShapeTgt.IsBound(V1)) {
1257           myAnalyse.Edges(V1,ChFiDS_Tangential,LE);
1258           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1259           if (LE.Extent() == LA.Extent())
1260             ShapeTgt.Bind(V1,OV1);
1261         }
1262         if (!ShapeTgt.IsBound(V2)) {
1263           LE.Clear();
1264           myAnalyse.Edges(V2,ChFiDS_Tangential,LE);
1265           const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1266           if (LE.Extent() == LA.Extent())
1267             ShapeTgt.Bind(V2,OV2);
1268         }
1269       }
1270     }
1271     theMapSF.Bind(aF,OF);
1272   }
1273   //
1274   const TopTools_ListOfShape& aNewFaces = myAnalyse.NewFaces();
1275   for (TopTools_ListOfShape::Iterator it (aNewFaces); it.More(); it.Next())
1276   {
1277     const TopoDS_Face& aF = TopoDS::Face (it.Value());
1278     BRepOffset_Offset OF(aF, 0.0, ShapeTgt, OffsetOutside, myJoin);
1279     theMapSF.Bind (aF, OF);
1280   }
1281 }
1282 
1283 //=======================================================================
1284 //function : BuildOffsetByInter
1285 //purpose  :
1286 //=======================================================================
BuildOffsetByInter(const Message_ProgressRange & theRange)1287 void BRepOffset_MakeOffset::BuildOffsetByInter(const Message_ProgressRange& theRange)
1288 {
1289 #ifdef OCCT_DEBUG
1290   if ( ChronBuild) {
1291     std::cout << " CONSTRUCTION OF OFFSETS :" << std::endl;
1292     Clock.Reset();
1293     Clock.Start();
1294   }
1295 #endif
1296 
1297   Message_ProgressScope aPSOuter(theRange, "Connect offset faces by intersection", 100);
1298   // just for better management and visualization of the progress steps
1299   // define a nested enum listing all the steps of the current method.
1300   enum BuildOffsetByInter_PISteps
1301   {
1302     BuildOffsetByInter_MakeOffsetFaces = 0,
1303     BuildOffsetByInter_ConnexIntByInt,
1304     BuildOffsetByInter_ContextIntByInt,
1305     BuildOffsetByInter_IntersectEdges,
1306     BuildOffsetByInter_CompleteEdgesIntersection,
1307     BuildOffsetByInter_BuildFaces,
1308     BuildOffsetByInter_FillHistoryForOffsets,
1309     BuildOffsetByInter_FillHistoryForDeepenings,
1310     BuildOffsetByInter_Last
1311   };
1312 
1313   Standard_Real aNbFaces = myFaceComp.NbChildren() + myAnalyse.NewFaces().Extent() + myFaces.Extent();
1314   Standard_Real anOffsetsPart = (myFaceComp.NbChildren() + myAnalyse.NewFaces().Extent()) / aNbFaces;
1315   Standard_Real aDeepeningsPart = myFaces.Extent() / aNbFaces;
1316 
1317   TColStd_Array1OfReal aSteps(0, BuildOffsetByInter_Last - 1);
1318   {
1319     aSteps.Init(0);
1320 
1321     Standard_Boolean isInter = myJoin == GeomAbs_Intersection;
1322     Standard_Real aFaceInter = isInter ? 25. : 50.;
1323     Standard_Real aBuildFaces = isInter ? 50. : 25.;
1324     aSteps(BuildOffsetByInter_MakeOffsetFaces) = 5.;
1325     aSteps(BuildOffsetByInter_ConnexIntByInt)  = aFaceInter * anOffsetsPart;
1326     aSteps(BuildOffsetByInter_ContextIntByInt) = aFaceInter * aDeepeningsPart;
1327     aSteps(BuildOffsetByInter_IntersectEdges) = 10.;
1328     aSteps(BuildOffsetByInter_CompleteEdgesIntersection) = 5.;
1329     aSteps(BuildOffsetByInter_BuildFaces) = aBuildFaces;
1330     aSteps(BuildOffsetByInter_FillHistoryForOffsets) = 5. * anOffsetsPart;
1331     aSteps(BuildOffsetByInter_FillHistoryForDeepenings) = 5. * aDeepeningsPart;
1332     normalizeSteps(100., aSteps);
1333   }
1334 
1335   TopExp_Explorer Exp, Exp2, ExpC;
1336   TopTools_ListIteratorOfListOfShape itLF;
1337 
1338   //--------------------------------------------------------
1339   // Construction of faces parallel to initial faces
1340   //--------------------------------------------------------
1341   BRepOffset_DataMapOfShapeOffset MapSF;
1342   MakeOffsetFaces(MapSF, aPSOuter.Next(aSteps(BuildOffsetByInter_MakeOffsetFaces)));
1343   if (!aPSOuter.More())
1344   {
1345     myError = BRepOffset_UserBreak;
1346     return;
1347   }
1348   //--------------------------------------------------------------------
1349   // MES   : Map of OffsetShape -> Extended Shapes.
1350   // Build : Map of Initial SS  -> OffsetShape build by Inter.
1351   //                               can be an edge or a compound of edges
1352   //---------------------------------------------------------------------
1353   TopTools_DataMapOfShapeShape MES;
1354   TopTools_DataMapOfShapeShape Build;
1355   TopTools_ListOfShape         Failed;
1356   TopAbs_State                 Side = TopAbs_IN;
1357   Handle(BRepAlgo_AsDes)       AsDes = new BRepAlgo_AsDes();
1358 
1359   //-------------------------------------------------------------------
1360   // Extension of faces and calculation of new edges of intersection.
1361   //-------------------------------------------------------------------
1362   Standard_Boolean  ExtentContext = 0;
1363   if (myOffset > 0) ExtentContext = 1;
1364 
1365   BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
1366   // Intersection between parallel faces
1367   Inter3.ConnexIntByInt(myFaceComp, MapSF, myAnalyse, MES, Build, Failed,
1368                         aPSOuter.Next(aSteps(BuildOffsetByInter_ConnexIntByInt)), myIsPlanar);
1369   if (!aPSOuter.More())
1370   {
1371     myError = BRepOffset_UserBreak;
1372     return;
1373   }
1374   // Intersection with caps.
1375   Inter3.ContextIntByInt(myFaces, ExtentContext, MapSF, myAnalyse, MES, Build, Failed,
1376                          aPSOuter.Next(aSteps(BuildOffsetByInter_ContextIntByInt)), myIsPlanar);
1377   if (!aPSOuter.More())
1378   {
1379     myError = BRepOffset_UserBreak;
1380     return;
1381   }
1382 
1383   TopTools_ListOfShape aLFaces;
1384   for (Exp.Init(myFaceComp,TopAbs_FACE) ; Exp.More(); Exp.Next())
1385     aLFaces.Append (Exp.Current());
1386   for (TopTools_ListOfShape::Iterator it (myAnalyse.NewFaces()); it.More(); it.Next())
1387     aLFaces.Append (it.Value());
1388   //---------------------------------------------------------------------------------
1389   // Extension of neighbor edges of new edges and intersection between neighbors.
1390   //--------------------------------------------------------------------------------
1391   Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
1392   IntersectEdges(aLFaces, MapSF, MES, Build, AsDes, AsDes2d,
1393                  aPSOuter.Next(aSteps(BuildOffsetByInter_IntersectEdges)));
1394   if (myError != BRepOffset_NoError)
1395   {
1396     return;
1397   }
1398   //-----------------------------------------------------------
1399   // Great restriction of new edges and update of AsDes.
1400   //------------------------------------------ ----------------
1401   TopTools_DataMapOfShapeListOfShape anEdgesOrigins; // offset edge - initial edges
1402   TopTools_IndexedMapOfShape NewEdges;
1403   TopTools_DataMapOfShapeShape aETrimEInf; // trimmed - not trimmed edges
1404   //
1405   //Map of edges obtained after FACE-FACE (offsetted) intersection.
1406   //Key1 is edge trimmed by intersection points with other edges;
1407   //Item is not-trimmed edge.
1408   if (!TrimEdges(myFaceComp, myOffset, myAnalyse, MapSF, MES, Build,
1409                  AsDes, AsDes2d, NewEdges, aETrimEInf, anEdgesOrigins))
1410   {
1411     myError = BRepOffset_CannotTrimEdges;
1412     return;
1413   }
1414   //
1415   //---------------------------------
1416   // Intersection 2D on //
1417   //---------------------------------
1418   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
1419   TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face
1420   TopTools_ListOfShape LFE;
1421   BRepAlgo_Image     IMOE;
1422   GetEnlargedFaces(aLFaces, MapSF, MES, aFacesOrigins, IMOE, LFE);
1423   //
1424   TopTools_ListIteratorOfListOfShape itLFE(LFE);
1425   Message_ProgressScope aPS2d(aPSOuter.Next(aSteps(BuildOffsetByInter_CompleteEdgesIntersection)), NULL, 2);
1426   Message_ProgressScope aPS2dOffsets(aPS2d.Next(2. * anOffsetsPart), NULL, LFE.Size());
1427   for (; itLFE.More(); itLFE.Next())
1428   {
1429     if (!aPS2dOffsets.More())
1430     {
1431       myError = BRepOffset_UserBreak;
1432       return;
1433     }
1434     const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1435     Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF);
1436     BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, myEdgeIntEdges, aDMVV, aPS2dOffsets.Next());
1437   }
1438   //----------------------------------------------
1439   // Intersections 2d on caps.
1440   //----------------------------------------------
1441   Standard_Integer i;
1442   Message_ProgressScope aPS2dCaps(aPS2d.Next(2. * aDeepeningsPart), NULL, myFaces.Extent());
1443   for (i = 1; i <= myFaces.Extent(); i++)
1444   {
1445     if (!aPS2dCaps.More())
1446     {
1447       myError = BRepOffset_UserBreak;
1448       return;
1449     }
1450     const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
1451     Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork);
1452     BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, myEdgeIntEdges, aDMVV, aPS2dCaps.Next());
1453   }
1454   //
1455   BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes, myImageVV);
1456   //-------------------------------
1457   // Unwinding of extended Faces.
1458   //-------------------------------
1459   //
1460   TopTools_MapOfShape aMFDone;
1461   //
1462   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
1463     BuildSplitsOfExtendedFaces(LFE, myAnalyse, AsDes, anEdgesOrigins, aFacesOrigins, aETrimEInf,
1464                                IMOE, aPSOuter.Next(aSteps(BuildOffsetByInter_BuildFaces)));
1465     if (myError != BRepOffset_NoError)
1466     {
1467       return;
1468     }
1469     //
1470     TopTools_ListIteratorOfListOfShape aItLF(LFE);
1471     for (; aItLF.More(); aItLF.Next()) {
1472       const TopoDS_Shape& aS = aItLF.Value();
1473       aMFDone.Add(aS);
1474     }
1475   }
1476   else {
1477     myMakeLoops.Build(LFE, AsDes, IMOE, myImageVV, aPSOuter.Next(aSteps(BuildOffsetByInter_BuildFaces)));
1478     if (!aPSOuter.More())
1479     {
1480       myError = BRepOffset_UserBreak;
1481       return;
1482     }
1483   }
1484   //
1485 #ifdef OCCT_DEBUG
1486   TopTools_IndexedMapOfShape COES;
1487 #endif
1488   //---------------------------
1489   // MAJ SD. for faces //
1490   //---------------------------
1491   Message_ProgressScope aPSHist(aPSOuter.Next(aSteps(BuildOffsetByInter_FillHistoryForOffsets)),
1492                                 "Fill history for offset faces", aLFaces.Size());
1493   for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next(), aPSHist.Next())
1494   {
1495     if (!aPSHist.More())
1496     {
1497       myError = BRepOffset_UserBreak;
1498       return;
1499     }
1500     const TopoDS_Shape& FI   = it.Value();
1501     myInitOffsetFace.SetRoot(FI);
1502     TopoDS_Face  OF  = MapSF(FI).Face();
1503     if (MES.IsBound(OF)) {
1504       OF = TopoDS::Face(MES(OF));
1505       if (IMOE.HasImage(OF)) {
1506         const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1507         myInitOffsetFace.Bind(FI,LOFE);
1508         for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1509           const TopoDS_Shape& OFE =  itLF.Value();
1510           myImageOffset.SetRoot(OFE);
1511 #ifdef DRAW
1512           if (AffichInt2d) {
1513             sprintf(name,"AF_%d",NbAF++);
1514             DBRep::Set(name,OFE);
1515           }
1516 #endif
1517           TopTools_MapOfShape View;
1518           for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1519                Exp2.More(); Exp2.Next()) {
1520             const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1521 
1522             myAsDes->Add (OFE,COE);
1523 #ifdef DRAW
1524             if (AffichInt2d) {
1525               sprintf(name,"AE_%d",NbAE++);
1526               DBRep::Set(name,COE);
1527               COES.Add(COE);
1528             }
1529 #endif
1530             if (View.Add(COE)){
1531               if (!myAsDes->HasDescendant(COE)) {
1532                 TopoDS_Vertex CV1,CV2;
1533                 TopExp::Vertices(COE,CV1,CV2);
1534                 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1535                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1536               }
1537             }
1538           }
1539         }
1540       }
1541       else {
1542         if (aMFDone.Contains(OF)) {
1543           continue;
1544         }
1545         //
1546         myInitOffsetFace.Bind(FI,OF);
1547         myImageOffset.SetRoot(OF);
1548 #ifdef DRAW
1549         if (AffichInt2d) {
1550           sprintf(name,"AF_%d",NbAF++);
1551           DBRep::Set(name,OF);
1552         }
1553 #endif
1554         const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1555         for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1556           const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1557           if (IMOE.HasImage(OE)) {
1558             const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1559             TopTools_ListIteratorOfListOfShape itLOE(LOE);
1560             for (; itLOE.More(); itLOE.Next()) {
1561               TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1562               const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1563 //              const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1564               myAsDes->Add(OF,COE);
1565 #ifdef DRAW
1566               if (AffichInt2d) {
1567                 sprintf(name,"AE_%d",NbAE++);
1568                 DBRep::Set(name,COE);
1569                 COES.Add(COE);
1570               }
1571 #endif
1572 
1573               if (!myAsDes->HasDescendant(COE)) {
1574                 TopoDS_Vertex CV1,CV2;
1575                 TopExp::Vertices(COE,CV1,CV2);
1576                  if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1577                 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1578               }
1579             }
1580           }
1581           else {
1582             myAsDes->Add(OF,OE);
1583 #ifdef DRAW
1584             if (AffichInt2d) {
1585               sprintf(name,"AE_%d",NbAE++);
1586               DBRep::Set(name,OE);
1587               COES.Add(OE);
1588             }
1589 #endif
1590 
1591             const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1592             myAsDes->Add(OE,LV);
1593           }
1594         }
1595       }
1596     }
1597     else {
1598       myInitOffsetFace.Bind(FI,OF);
1599       myImageOffset.SetRoot(OF);
1600       TopTools_MapOfShape View;
1601       for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1602            Exp2.More(); Exp2.Next()) {
1603 
1604         const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1605         myAsDes->Add (OF,COE);
1606 #ifdef DRAW
1607         if (AffichInt2d) {
1608           sprintf(name,"AE_%d",NbAE++);
1609           DBRep::Set(name,COE);
1610           COES.Add(COE);
1611         }
1612 #endif
1613 
1614         if (View.Add(Exp2.Current())) {
1615           if (!myAsDes->HasDescendant(COE)) {
1616             TopoDS_Vertex CV1,CV2;
1617             TopExp::Vertices(COE,CV1,CV2);
1618             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1619             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1620           }
1621         }
1622       }
1623     }
1624   }
1625   //  Modified by skv - Tue Mar 15 16:20:43 2005
1626   // Add methods for supporting history.
1627   TopTools_MapOfShape aMapEdges;
1628 
1629   for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
1630   {
1631     const TopoDS_Shape& aFaceRef = it.Value();
1632     Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1633 
1634     for (; Exp2.More(); Exp2.Next()) {
1635       const TopoDS_Shape& anEdgeRef = Exp2.Current();
1636 
1637       if (aMapEdges.Add(anEdgeRef)) {
1638         myInitOffsetEdge.SetRoot(anEdgeRef);
1639         if (Build.IsBound(anEdgeRef)) {
1640           TopoDS_Shape aNewShape = Build(anEdgeRef);
1641 
1642           if (aNewShape.ShapeType() == TopAbs_EDGE) {
1643             if (IMOE.HasImage(aNewShape)) {
1644               const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1645 
1646               myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1647             } else
1648               myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1649           } else { // aNewShape != TopAbs_EDGE
1650             TopTools_ListOfShape aListNewEdge;
1651 
1652             for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1653               const TopoDS_Shape &aResEdge = ExpC.Current();
1654 
1655               if (IMOE.HasImage(aResEdge)) {
1656                 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1657                 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1658 
1659                 for (; aNewEIter.More(); aNewEIter.Next())
1660                   aListNewEdge.Append(aNewEIter.Value());
1661               } else
1662                 aListNewEdge.Append(aResEdge);
1663             }
1664 
1665             myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1666           }
1667         }
1668         else { // Free boundary.
1669           TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1670 
1671           if (MES.IsBound(aNewEdge))
1672             aNewEdge = MES(aNewEdge);
1673 
1674           if (IMOE.HasImage(aNewEdge)) {
1675             const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1676 
1677             myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1678           } else
1679             myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1680         }
1681       }
1682     }
1683   }
1684 //  Modified by skv - Tue Mar 15 16:20:43 2005
1685 
1686   //---------------------------
1687   // MAJ SD. for caps
1688   //---------------------------
1689   //TopTools_MapOfShape View;
1690   Message_ProgressScope aPSHist2(aPSOuter.Next(aSteps(BuildOffsetByInter_FillHistoryForDeepenings)),
1691                                  "Fill history for deepening faces", myFaces.Extent());
1692   for (i = 1; i <= myFaces.Extent(); i++, aPSHist2.Next()) {
1693     if (!aPSHist2.More())
1694     {
1695       myError = BRepOffset_UserBreak;
1696       return;
1697     }
1698     const TopoDS_Shape& Cork = myFaces(i);
1699     const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1700     for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1701       const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1702       if (IMOE.HasImage(OE)) {
1703         const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1704           TopTools_ListIteratorOfListOfShape itLOE(LOE);
1705         for (; itLOE.More(); itLOE.Next()) {
1706           const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1707           myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1708 #ifdef DRAW
1709           if (AffichInt2d) {
1710             sprintf(name,"AE_%d",NbAE++);
1711             DBRep::Set(name,COE);
1712             COES.Add(COE);
1713           }
1714 #endif
1715 
1716           if (!myAsDes->HasDescendant(COE)) {
1717             TopoDS_Vertex CV1,CV2;
1718             TopExp::Vertices(COE,CV1,CV2);
1719             if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1720             if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1721           }
1722         }
1723       }
1724       else {
1725         myAsDes->Add(Cork,OE);
1726         if (AsDes->HasDescendant(OE)) {
1727           myAsDes->Add(OE,AsDes->Descendant(OE));
1728         }
1729 #ifdef DRAW
1730         if (AffichInt2d) {
1731           sprintf(name,"AE_%d",NbAE++);
1732           DBRep::Set(name,OE);
1733           COES.Add(OE);
1734         }
1735 #endif
1736       }
1737     }
1738   }
1739 
1740 #ifdef OCCT_DEBUG
1741   DEBVerticesControl (COES,myAsDes);
1742   if ( ChronBuild) Clock.Show();
1743 #endif
1744 
1745 }
1746 
1747 //=======================================================================
1748 //function : ReplaceRoots
1749 //purpose  :
1750 //=======================================================================
ReplaceRoots()1751 void BRepOffset_MakeOffset::ReplaceRoots()
1752 {
1753   // Replace the artificial faces and edges in InitOffset maps with the original ones.
1754   TopTools_MapOfShape View;
1755   for (TopExp_Explorer anExpF (myFaceComp, TopAbs_EDGE); anExpF.More(); anExpF.Next())
1756   {
1757     const TopoDS_Shape& aF = anExpF.Current();
1758     for (TopExp_Explorer anExpE (aF, TopAbs_EDGE); anExpE.More(); anExpE.Next())
1759     {
1760       const TopoDS_Shape& aE = anExpE.Current();
1761       if (!View.Add (aE))
1762         continue;
1763 
1764       TopoDS_Shape aFGen = myAnalyse.Generated (aE);
1765       if (aFGen.IsNull())
1766         continue;
1767 
1768       myInitOffsetFace.ReplaceRoot (aFGen, aE);
1769 
1770       for (TopoDS_Iterator itV (aE); itV.More(); itV.Next())
1771       {
1772         const TopoDS_Shape& aV = itV.Value();
1773         if (!View.Add (aV))
1774           continue;
1775 
1776         TopoDS_Shape aEGen = myAnalyse.Generated (aV);
1777         if (aEGen.IsNull())
1778           continue;
1779 
1780         myInitOffsetEdge.ReplaceRoot (aEGen, aV);
1781       }
1782     }
1783   }
1784 }
1785 
1786 //=======================================================================
1787 //function : BuildFaceComp
1788 //purpose  : Make a compound containing actual faces (including planar faces instead of their originals)
1789 //=======================================================================
BuildFaceComp()1790 void BRepOffset_MakeOffset::BuildFaceComp()
1791 {
1792   BRep_Builder aBB;
1793   aBB.MakeCompound(myFaceComp);
1794   TopExp_Explorer anExplo(myShape, TopAbs_FACE);
1795   for (; anExplo.More(); anExplo.Next())
1796   {
1797     TopoDS_Shape aFace = anExplo.Current();
1798     TopAbs_Orientation anOr = aFace.Orientation();
1799     const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aFace);
1800     if (aPlanface)
1801       aFace = *aPlanface;
1802     aBB.Add(myFaceComp, aFace.Oriented(anOr));
1803   }
1804 }
1805 
1806 //=======================================================================
1807 //function : BuildOffsetByArc
1808 //purpose  :
1809 //=======================================================================
BuildOffsetByArc(const Message_ProgressRange & theRange)1810 void BRepOffset_MakeOffset::BuildOffsetByArc(const Message_ProgressRange& theRange)
1811 {
1812 #ifdef OCCT_DEBUG
1813   if ( ChronBuild) {
1814     std::cout << " CONSTRUCTION OF OFFSETS :" << std::endl;
1815     Clock.Reset();
1816     Clock.Start();
1817   }
1818 #endif
1819 
1820   TopExp_Explorer Exp;
1821   TopTools_ListIteratorOfListOfShape itLF;
1822   TopTools_MapOfShape Done;
1823   Message_ProgressScope aPSOuter(theRange, NULL, 10);
1824   //--------------------------------------------------------
1825   // Construction of faces parallel to initial faces
1826   //--------------------------------------------------------
1827   BRepOffset_DataMapOfShapeOffset MapSF;
1828   MakeOffsetFaces(MapSF, aPSOuter.Next());
1829   if (myError != BRepOffset_NoError)
1830   {
1831     return;
1832   }
1833   //--------------------------------------------------------
1834   // Construction of tubes on edge.
1835   //--------------------------------------------------------
1836   ChFiDS_TypeOfConcavity OT = ChFiDS_Convex;
1837   if (myOffset < 0.) OT = ChFiDS_Concave;
1838 
1839   Message_ProgressScope aPS1(aPSOuter.Next(4), "Constructing tubes on edges", 1, Standard_True);
1840   for (Exp.Init(myFaceComp,TopAbs_EDGE); Exp.More(); Exp.Next(), aPS1.Next()) {
1841     if (!aPS1.More())
1842     {
1843       myError = BRepOffset_UserBreak;
1844       return;
1845     }
1846     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1847     if (Done.Add(E)) {
1848       const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
1849       if (Anc.Extent() == 2) {
1850         const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1851         if (!L.IsEmpty() && L.First().Type() == OT) {
1852           Standard_Real CurOffset = myOffset;
1853           if ( myFaceOffset.IsBound(Anc.First()))
1854             CurOffset = myFaceOffset(Anc.First());
1855           TopoDS_Shape aLocalShapeGen = MapSF(Anc.First()).Generated(E);
1856           TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
1857           aLocalShapeGen = MapSF(Anc.Last()).Generated(E);
1858           TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
1859 //          TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1860 //          TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
1861           // find if exits tangent edges in the original shape
1862           TopoDS_Edge E1f, E1l;
1863           TopoDS_Vertex V1f, V1l;
1864           TopExp::Vertices(E,V1f,V1l);
1865           TopTools_ListOfShape TangE;
1866           myAnalyse.TangentEdges(E,V1f,TangE);
1867           // find if the pipe on the tangent edges are soon created.
1868           TopTools_ListIteratorOfListOfShape itl(TangE);
1869           Standard_Boolean Find = Standard_False;
1870           for ( ; itl.More() && !Find; itl.Next()) {
1871             if ( MapSF.IsBound(itl.Value())) {
1872               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
1873               E1f  = TopoDS::Edge(aLocalShape);
1874 //              E1f  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
1875               Find = Standard_True;
1876             }
1877           }
1878           TangE.Clear();
1879           myAnalyse.TangentEdges(E,V1l,TangE);
1880           // find if the pipe on the tangent edges are soon created.
1881           itl.Initialize(TangE);
1882           Find = Standard_False;
1883           for ( ; itl.More() && !Find; itl.Next()) {
1884             if ( MapSF.IsBound(itl.Value())) {
1885               TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
1886               E1l  = TopoDS::Edge(aLocalShape);
1887 //              E1l  = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
1888               Find = Standard_True;
1889             }
1890           }
1891           BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
1892           MapSF.Bind(E,OF);
1893         }
1894       }
1895       else {
1896         // ----------------------
1897         // free border.
1898         // ----------------------
1899         TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1900         TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1901 ///        TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1902         myInitOffsetEdge.SetRoot(E); // skv: supporting history.
1903         myInitOffsetEdge.Bind (E,EOn1);
1904       }
1905     }
1906   }
1907 
1908   //--------------------------------------------------------
1909   // Construction of spheres on vertex.
1910   //--------------------------------------------------------
1911   Done.Clear();
1912   TopTools_ListIteratorOfListOfShape it;
1913   Message_ProgressScope aPS2(aPSOuter.Next(4), "Constructing spheres on vertices", 1, Standard_True);
1914   for (Exp.Init(myFaceComp,TopAbs_VERTEX); Exp.More(); Exp.Next(), aPS2.Next()) {
1915     if (!aPS2.More())
1916     {
1917       myError = BRepOffset_UserBreak;
1918       return;
1919     }
1920     const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
1921     if (Done.Add(V)) {
1922       const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
1923       TopTools_ListOfShape LE;
1924       myAnalyse.Edges(V,OT,LE);
1925 
1926       if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
1927         TopTools_ListOfShape LOE;
1928         //--------------------------------------------------------
1929         // Return connected edges on tubes.
1930         //--------------------------------------------------------
1931         for (it.Initialize(LE) ; it.More(); it.Next()) {
1932           LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
1933         }
1934         //----------------------
1935         // construction sphere.
1936         //-----------------------
1937         const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
1938         const TopoDS_Shape& FF = LLA.First();
1939         Standard_Real CurOffset = myOffset;
1940         if ( myFaceOffset.IsBound(FF))
1941           CurOffset = myFaceOffset(FF);
1942 
1943         BRepOffset_Offset OF(V,LOE,CurOffset);
1944         MapSF.Bind(V,OF);
1945       }
1946       //--------------------------------------------------------------
1947       // Particular processing if V is at least a free border.
1948       //-------------------------------------------------------------
1949       TopTools_ListOfShape LBF;
1950       myAnalyse.Edges(V,ChFiDS_FreeBound,LBF);
1951       if (!LBF.IsEmpty()) {
1952         Standard_Boolean First = Standard_True;
1953         for (it.Initialize(LE) ; it.More(); it.Next()) {
1954           if (First) {
1955             myInitOffsetEdge.SetRoot(V); // skv: supporting history.
1956             myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
1957             First = Standard_False;
1958           }
1959           else {
1960             myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
1961           }
1962         }
1963       }
1964     }
1965   }
1966 
1967   //------------------------------------------------------------
1968   // Extension of parallel faces to the context.
1969   // Extended faces are ordered in DS and removed from MapSF.
1970   //------------------------------------------------------------
1971   if (!myFaces.IsEmpty()) ToContext (MapSF);
1972 
1973   //------------------------------------------------------
1974   // MAJ SD.
1975   //------------------------------------------------------
1976   ChFiDS_TypeOfConcavity RT = ChFiDS_Concave;
1977   if (myOffset < 0.) RT = ChFiDS_Convex;
1978   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
1979   Message_ProgressScope aPS3(aPSOuter.Next(), NULL, MapSF.Size());
1980   for ( ; It.More(); It.Next(), aPS3.Next()) {
1981     if (!aPS3.More())
1982     {
1983       myError = BRepOffset_UserBreak;
1984       return;
1985     }
1986     const TopoDS_Shape& SI = It.Key();
1987     const BRepOffset_Offset& SF = It.Value();
1988     if (SF.Status() == BRepOffset_Reversed ||
1989         SF.Status() == BRepOffset_Degenerated ) {
1990       //------------------------------------------------
1991       // Degenerated or returned faces are not stored.
1992       //------------------------------------------------
1993       continue;
1994     }
1995 
1996     const TopoDS_Face&  OF = It.Value().Face();
1997     myInitOffsetFace.Bind    (SI,OF);
1998     myInitOffsetFace.SetRoot (SI);      // Initial<-> Offset
1999     myImageOffset.SetRoot    (OF);      // FaceOffset root of images
2000 
2001     if (SI.ShapeType() == TopAbs_FACE) {
2002       for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2003            Exp.More(); Exp.Next()) {
2004         //--------------------------------------------------------------------
2005         // To each face are associatedthe edges that restrict that
2006         // The edges that do not generate tubes or are not tangent
2007         // to two faces are removed.
2008         //--------------------------------------------------------------------
2009         const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
2010         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
2011         if (!L.IsEmpty() && L.First().Type() != RT) {
2012           TopAbs_Orientation OO  = E.Orientation();
2013           TopoDS_Shape aLocalShape = It.Value().Generated(E);
2014           TopoDS_Edge        OE  = TopoDS::Edge(aLocalShape);
2015 //          TopoDS_Edge        OE  = TopoDS::Edge(It.Value().Generated(E));
2016           myAsDes->Add (OF,OE.Oriented(OO));
2017         }
2018       }
2019     }
2020     else {
2021       for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2022            Exp.More(); Exp.Next()) {
2023         myAsDes->Add (OF,Exp.Current());
2024       }
2025     }
2026   }
2027 
2028 #ifdef OCCT_DEBUG
2029   if ( ChronBuild) Clock.Show();
2030 #endif
2031 }
2032 
2033 
2034 
2035 //=======================================================================
2036 //function : SelfInter
2037 //purpose  :
2038 //=======================================================================
2039 
SelfInter(TopTools_MapOfShape &)2040 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
2041 {
2042 #ifdef OCCT_DEBUG
2043   if ( ChronBuild) {
2044     std::cout << " AUTODEBOUCLAGE:" << std::endl;
2045     Clock.Reset();
2046     Clock.Start();
2047   }
2048 #endif
2049 
2050   throw Standard_NotImplemented();
2051 }
2052 
2053 
2054 //=======================================================================
2055 //function : ToContext
2056 //purpose  :
2057 //=======================================================================
2058 
ToContext(BRepOffset_DataMapOfShapeOffset & MapSF)2059 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
2060 {
2061   TopTools_DataMapOfShapeShape        Created;
2062   TopTools_DataMapOfShapeShape        MEF;
2063   TopTools_IndexedMapOfShape          FacesToBuild;
2064   TopTools_ListIteratorOfListOfShape  itl;
2065   TopExp_Explorer                     exp;
2066 
2067 //  TopAbs_State       Side = TopAbs_IN;
2068 //  if (myOffset < 0.) Side = TopAbs_OUT;
2069 
2070   TopAbs_State       Side = TopAbs_OUT;
2071 
2072   /*
2073   Standard_Integer i;
2074   for (i = 1; i <= myFaces.Extent(); i++) {
2075     const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
2076     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2077          exp.More(); exp.Next()) {
2078       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2079       if (!myAnalyse.HasAncestor(E)) {
2080         //----------------------------------------------------------------
2081         // The edges of context faces that are not in the initial shape
2082         // can appear in the result.
2083         //----------------------------------------------------------------
2084         //myAsDes->Add(CF,E);
2085       }
2086     }
2087   }
2088   */
2089 
2090   //--------------------------------------------------------
2091   // Determine the edges and faces reconstructed by
2092   // intersection.
2093   //---------------------------------------------------------
2094   Standard_Integer j;
2095   for (j = 1; j <= myFaces.Extent(); j++) {
2096     const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
2097     for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2098          exp.More(); exp.Next()) {
2099       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2100       if (myAnalyse.HasAncestor(E)) {
2101         const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
2102         for (itl.Initialize(LEA); itl.More(); itl.Next()) {
2103           const BRepOffset_Offset& OF = MapSF(itl.Value());
2104           FacesToBuild.Add(itl.Value());
2105           MEF.Bind(OF.Generated(E),CF);
2106         }
2107          TopoDS_Vertex V[2];
2108         TopExp::Vertices(E,V[0],V[1]);
2109         for (Standard_Integer i = 0; i < 2; i++) {
2110           const TopTools_ListOfShape& LVA =  myAnalyse.Ancestors(V[i]);
2111           for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
2112             const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
2113             if (MapSF.IsBound(EV)) {
2114               const BRepOffset_Offset& OF = MapSF(EV);
2115               FacesToBuild.Add(EV);
2116               MEF.Bind(OF.Generated(V[i]),CF);
2117             }
2118           }
2119         }
2120       }
2121     }
2122   }
2123   //---------------------------
2124   // Reconstruction of faces.
2125   //---------------------------
2126   TopoDS_Face        F,NF;
2127   ChFiDS_TypeOfConcavity RT = ChFiDS_Concave;
2128   if (myOffset < 0.) RT = ChFiDS_Convex;
2129   TopoDS_Shape       OE,NE;
2130   TopAbs_Orientation Or;
2131 
2132   for (j = 1; j <= FacesToBuild.Extent(); j++) {
2133     const TopoDS_Shape& S   = FacesToBuild(j);
2134     BRepOffset_Offset   BOF;
2135     BOF = MapSF(S);
2136     F = TopoDS::Face(BOF.Face());
2137     BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
2138     MapSF.UnBind(S);
2139     //--------------
2140     // MAJ SD.
2141     //--------------
2142     myInitOffsetFace.Bind    (S,NF);
2143     myInitOffsetFace.SetRoot (S);      // Initial<-> Offset
2144     myImageOffset.SetRoot    (NF);
2145 
2146     if (S.ShapeType() == TopAbs_FACE) {
2147       for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2148            exp.More(); exp.Next()) {
2149 
2150         const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2151         const BRepOffset_ListOfInterval& L  = myAnalyse.Type(E);
2152         OE = BOF.Generated(E);
2153         Or = E.Orientation();
2154         OE.Orientation(Or);
2155         if (!L.IsEmpty() && L.First().Type() != RT) {
2156           if (Created.IsBound(OE)) {
2157             NE = Created(OE);
2158             if (NE.Orientation() == TopAbs_REVERSED)
2159               NE.Orientation(TopAbs::Reverse(Or));
2160             else
2161               NE.Orientation(Or);
2162             myAsDes->Add(NF,NE);
2163           }
2164           else {
2165             myAsDes->Add(NF,OE);
2166           }
2167         }
2168       }
2169     }
2170     else {
2171       //------------------
2172       // Tube
2173       //---------------------
2174       for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2175            exp.More(); exp.Next()) {
2176         myAsDes->Add (NF,exp.Current());
2177       }
2178     }
2179     MapSF.UnBind(S);
2180   }
2181 
2182   //------------------
2183   // MAJ free borders
2184   //------------------
2185   TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
2186   for (itc.Initialize(Created); itc.More(); itc.Next()) {
2187     OE = itc.Key();
2188     NE = itc.Value();
2189     if (myInitOffsetEdge.IsImage(OE)) {
2190       TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
2191       Or = myInitOffsetEdge.Image(E).First().Orientation();
2192       if (NE.Orientation() == TopAbs_REVERSED)
2193         NE.Orientation(TopAbs::Reverse(Or));
2194       else
2195         NE.Orientation(Or);
2196       myInitOffsetEdge.Remove(OE);
2197       myInitOffsetEdge.Bind(E,NE);
2198     }
2199   }
2200 }
2201 
2202 
2203 //=======================================================================
2204 //function : UpdateFaceOffset
2205 //purpose  :
2206 //=======================================================================
2207 
UpdateFaceOffset()2208 void BRepOffset_MakeOffset::UpdateFaceOffset()
2209 {
2210   TopTools_MapOfShape M;
2211   TopTools_DataMapOfShapeReal CopiedMap;
2212   CopiedMap.Assign(myFaceOffset);
2213   TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
2214 
2215   ChFiDS_TypeOfConcavity RT = ChFiDS_Convex;
2216   if (myOffset < 0.) RT = ChFiDS_Concave;
2217 
2218   for ( ; it.More(); it.Next()) {
2219     const TopoDS_Face& F = TopoDS::Face(it.Key());
2220     Standard_Real CurOffset = CopiedMap(F);
2221     if ( !M.Add(F)) continue;
2222     TopoDS_Compound Co;
2223     BRep_Builder Build;
2224     Build.MakeCompound(Co);
2225     TopTools_MapOfShape Dummy;
2226     Build.Add(Co,F);
2227     if (myJoin == GeomAbs_Arc)
2228       myAnalyse.AddFaces(F,Co,Dummy,ChFiDS_Tangential,RT);
2229     else
2230       myAnalyse.AddFaces(F,Co,Dummy,ChFiDS_Tangential);
2231 
2232     TopExp_Explorer exp(Co,TopAbs_FACE);
2233     for (; exp.More(); exp.Next()) {
2234       const TopoDS_Face& FF = TopoDS::Face(exp.Current());
2235       if ( !M.Add(FF)) continue;
2236       if ( myFaceOffset.IsBound(FF))
2237         myFaceOffset.UnBind(FF);
2238       myFaceOffset.Bind(FF,CurOffset);
2239     }
2240   }
2241 }
2242 
2243 //=======================================================================
2244 //function : CorrectConicalFaces
2245 //purpose  :
2246 //=======================================================================
2247 
CorrectConicalFaces()2248 void BRepOffset_MakeOffset::CorrectConicalFaces()
2249 {
2250   if(myOffsetShape.IsNull())
2251   {
2252     return;
2253   }
2254   //
2255   TopTools_SequenceOfShape Cones;
2256   TopTools_SequenceOfShape Circs;
2257   TopTools_SequenceOfShape Seams;
2258   Standard_Real TolApex = 1.e-5;
2259 
2260   Standard_Integer i;
2261 
2262   TopTools_DataMapOfShapeListOfShape FacesOfCone;
2263   //TopTools_DataMapOfShapeShape DegEdges;
2264   TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
2265   if (myJoin == GeomAbs_Arc)
2266   {
2267     for (; Explo.More(); Explo.Next())
2268     {
2269       TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
2270       Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
2271       //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2272       //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
2273 
2274       TopTools_IndexedMapOfShape Emap;
2275       TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
2276       for (i = 1; i <= Emap.Extent(); i++)
2277       {
2278         TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
2279         //Standard_Real f, l;
2280         //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
2281         //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
2282         if (BRep_Tool::Degenerated(anEdge))
2283         {
2284           //Check if anEdge is a really degenerated edge or not
2285           BRepAdaptor_Curve BACurve(anEdge, aFace);
2286           gp_Pnt Pfirst, Plast, Pmid;
2287           Pfirst = BACurve.Value(BACurve.FirstParameter());
2288           Plast  = BACurve.Value(BACurve.LastParameter());
2289           Pmid   = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
2290           if (Pfirst.Distance(Plast) <= TolApex &&
2291               Pfirst.Distance(Pmid)  <= TolApex)
2292             continue;
2293           //Cones.Append( aFace );
2294           //Circs.Append( anEdge );
2295           //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
2296           TopoDS_Edge OrEdge =
2297             TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
2298           TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
2299           if ( FacesOfCone.IsBound(VF) )
2300           {
2301             //add a face to the existing list
2302             TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
2303             aFaces.Append (aFace);
2304             //DegEdges.Bind(aFace, anEdge);
2305           }
2306           else
2307           {
2308             //the vertex is not in the map => create a new key and items
2309             TopTools_ListOfShape aFaces;
2310             aFaces.Append (aFace);
2311             FacesOfCone.Bind(VF, aFaces);
2312             //DegEdges.Bind(aFace, anEdge);
2313           }
2314         }
2315       } //for (i = 1; i <= Emap.Extent(); i++)
2316     } //for (; fexp.More(); fexp.Next())
2317   } //if (myJoin == GeomAbs_Arc)
2318 
2319   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
2320   BRep_Builder BB;
2321   TopLoc_Location L;
2322   Standard_Boolean IsModified = Standard_False;
2323   for (; Cone.More(); Cone.Next() ) {
2324     gp_Sphere theSphere;
2325     Handle(Geom_SphericalSurface) aSphSurf;
2326     TopoDS_Wire SphereWire;
2327     BB.MakeWire(SphereWire);
2328     TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
2329     const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
2330     TopTools_ListIteratorOfListOfShape itFaces(Faces);
2331     Standard_Boolean isFirstFace = Standard_True;
2332     gp_Pnt FirstPoint;
2333     TopoDS_Vertex theFirstVertex, CurFirstVertex;
2334     for (; itFaces.More(); itFaces.Next())
2335     {
2336       TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
2337       TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
2338       for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2339       {
2340         DegEdge = TopoDS::Edge(Explo.Current());
2341         if (BRep_Tool::Degenerated(DegEdge))
2342         {
2343           TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
2344           TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
2345           if (VF.IsSame(anApex))
2346             break;
2347         }
2348       }
2349       TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
2350       TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
2351       BB.Degenerated(CurEdge, Standard_False);
2352       BB.SameRange(CurEdge, Standard_False);
2353       BB.SameParameter(CurEdge, Standard_False);
2354       gp_Pnt fPnt, lPnt, mPnt;
2355       GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
2356       Standard_Real f, l;
2357       BRep_Tool::Range(CurEdge, f, l);
2358       if (isFirstFace)
2359       {
2360         gp_Vec aVec1(fPnt, mPnt);
2361         gp_Vec aVec2(fPnt, lPnt);
2362         gp_Vec aNorm = aVec1.Crossed(aVec2);
2363         gp_Pnt theApex = BRep_Tool::Pnt(anApex);
2364         gp_Vec ApexToFpnt(theApex, fPnt);
2365         gp_Vec Ydir = aNorm ^ ApexToFpnt;
2366         gp_Vec Xdir = Ydir ^ aNorm;
2367         //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
2368         gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
2369         theSphere.SetRadius(myOffset);
2370         theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
2371         aSphSurf = new Geom_SphericalSurface(theSphere);
2372         FirstPoint = fPnt;
2373         theFirstVertex = BRepLib_MakeVertex(fPnt);
2374         CurFirstVertex = theFirstVertex;
2375       }
2376 
2377       TopoDS_Vertex v1, v2, FirstVert, EndVert;
2378       TopExp::Vertices(CurEdge, v1, v2);
2379       FirstVert = CurFirstVertex;
2380       if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
2381         EndVert = theFirstVertex;
2382       else
2383         EndVert = BRepLib_MakeVertex(lPnt);
2384       CurEdge.Free( Standard_True );
2385       BB.Remove(CurEdge, v1);
2386       BB.Remove(CurEdge, v2);
2387       BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
2388       BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
2389       //take the curve from sphere an put it to the edge
2390       Standard_Real Uf, Vf, Ul, Vl;
2391       ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
2392       ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
2393       if (Abs(Ul) <= Precision::Confusion())
2394         Ul = 2.*M_PI;
2395       Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
2396       /*
2397         if (!isFirstFace)
2398         {
2399         gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
2400         if (Abs(Uf - f) > Precision::Confusion())
2401         {
2402         aCircle.Rotate(aCircle.Axis(), f - Uf);
2403         aCurv = new Geom_Circle(aCircle);
2404         }
2405         }
2406       */
2407       Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
2408       BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
2409       BB.Range(CurEdge, Uf, Ul, Standard_True);
2410       Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
2411       Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
2412       BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
2413       BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
2414       BRepLib::SameParameter(CurEdge);
2415       BB.Add(SphereWire, CurEdge);
2416       //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
2417       BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
2418       gp_Pnt2d fPnt2d, lPnt2d;
2419       fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
2420       lPnt2d = BAc2d.Value(BAc2d.LastParameter());
2421       TopTools_IndexedMapOfShape Emap;
2422       TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
2423       TopoDS_Edge EE [2];
2424       Standard_Integer j = 0, k;
2425       for (k = 1; k <= Emap.Extent(); k++)
2426       {
2427         const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
2428         if (!BRep_Tool::Degenerated(anEdge))
2429         {
2430           TopoDS_Vertex V1, V2;
2431           TopExp::Vertices(anEdge, V1, V2);
2432           if (V1.IsSame(v1) || V2.IsSame(v1))
2433             EE[j++] = anEdge;
2434         }
2435       }
2436       for (k = 0; k < j; k++)
2437       {
2438         TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
2439         TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
2440         Eforward.Free(Standard_True);
2441         TopoDS_Vertex V1, V2;
2442         TopExp::Vertices( Eforward, V1, V2 );
2443         BRepAdaptor_Curve2d EEc( Eforward, aFace );
2444         gp_Pnt2d p2d1, p2d2;
2445         p2d1 = EEc.Value(EEc.FirstParameter());
2446         p2d2 = EEc.Value(EEc.LastParameter());
2447         if (V1.IsSame(v1))
2448         {
2449           TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2450             FirstVert : EndVert;
2451           BB.Remove( Eforward, V1 );
2452           BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2453         }
2454         else
2455         {
2456           TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2457             FirstVert : EndVert;
2458           BB.Remove( Eforward, V2 );
2459           BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2460         }
2461       }
2462 
2463       isFirstFace = Standard_False;
2464       CurFirstVertex = EndVert;
2465     }
2466     //Building new spherical face
2467     Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2468     gp_Pnt2d p2d1, p2d2;
2469     TopTools_ListOfShape EdgesOfWire;
2470     TopoDS_Iterator itw(SphereWire);
2471     for (; itw.More(); itw.Next())
2472     {
2473       const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2474       EdgesOfWire.Append(anEdge);
2475       Standard_Real f, l;
2476       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2477       p2d1 = aC2d->Value(f);
2478       p2d2 = aC2d->Value(l);
2479       if (p2d1.X() < Ufirst)
2480         Ufirst = p2d1.X();
2481       if (p2d1.X() > Ulast)
2482         Ulast = p2d1.X();
2483       if (p2d2.X() < Ufirst)
2484         Ufirst = p2d2.X();
2485       if (p2d2.X() > Ulast)
2486         Ulast = p2d2.X();
2487     }
2488     TopTools_ListOfShape NewEdges;
2489     TopoDS_Edge FirstEdge;
2490     TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2491     for (; itl.More(); itl.Next())
2492     {
2493       FirstEdge = TopoDS::Edge(itl.Value());
2494       Standard_Real f, l;
2495       Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2496       p2d1 = aC2d->Value(f);
2497       p2d2 = aC2d->Value(l);
2498       if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2499       {
2500         EdgesOfWire.Remove(itl);
2501         break;
2502       }
2503     }
2504     NewEdges.Append(FirstEdge.Oriented(TopAbs_FORWARD));
2505     TopoDS_Vertex Vf1, CurVertex;
2506     TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2507     itl.Initialize(EdgesOfWire);
2508     while (itl.More())
2509     {
2510       const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2511       TopoDS_Vertex V1, V2;
2512       TopExp::Vertices(anEdge, V1, V2);
2513       if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2514       {
2515         NewEdges.Append(anEdge.Oriented(TopAbs_FORWARD));
2516         CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2517         EdgesOfWire.Remove(itl);
2518       }
2519       else
2520         itl.Next();
2521     }
2522 
2523     Standard_Real Vfirst, Vlast;
2524     if (p2d1.Y() > 0.)
2525     {
2526       Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2527     }
2528     else
2529     {
2530       Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2531     }
2532     TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2533     TopoDS_Edge OldEdge, DegEdge;
2534     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2535     {
2536       DegEdge = TopoDS::Edge(Explo.Current());
2537       if (BRep_Tool::Degenerated(DegEdge))
2538         break;
2539     }
2540     TopoDS_Vertex DegVertex = TopExp::FirstVertex(DegEdge);
2541     for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2542     {
2543       OldEdge = TopoDS::Edge(Explo.Current());
2544       TopoDS_Vertex V1, V2;
2545       TopExp::Vertices(OldEdge, V1, V2);
2546       if (!V1.IsSame(DegVertex) && !V2.IsSame(DegVertex))
2547         break;
2548     }
2549     TopoDS_Vertex V1, V2;
2550     TopExp::Vertices(OldEdge, V1, V2);
2551     TopTools_ListOfShape LV1, LV2;
2552     LV1.Append(Vf1.Oriented(TopAbs_FORWARD));
2553     LV2.Append(CurVertex.Oriented(TopAbs_FORWARD));
2554     BRepTools_Substitution theSubstitutor;
2555     theSubstitutor.Substitute(V1.Oriented(TopAbs_FORWARD), LV1);
2556     if (!V1.IsSame(V2))
2557       theSubstitutor.Substitute(V2.Oriented(TopAbs_FORWARD), LV2);
2558     theSubstitutor.Substitute(OldEdge.Oriented(TopAbs_FORWARD), NewEdges);
2559     theSubstitutor.Build(NewSphericalFace);
2560     if (theSubstitutor.IsCopied(NewSphericalFace))
2561     {
2562       const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2563       NewSphericalFace = TopoDS::Face(listSh.First());
2564     }
2565 
2566     //Adding NewSphericalFace to the shell
2567     Explo.Init( myOffsetShape, TopAbs_SHELL );
2568     TopoDS_Shape theShell = Explo.Current();
2569     theShell.Free( Standard_True );
2570     BB.Add( theShell, NewSphericalFace );
2571     IsModified = Standard_True;
2572     if(!theShell.Closed())
2573     {
2574       if(BRep_Tool::IsClosed(theShell))
2575       {
2576         theShell.Closed(Standard_True);
2577       }
2578     }
2579   }
2580   //
2581   if(!IsModified)
2582   {
2583     return;
2584   }
2585   //
2586   if (myShape.ShapeType() == TopAbs_SOLID || myThickening)
2587   {
2588     //Explo.Init( myOffsetShape, TopAbs_SHELL );
2589 
2590     //if (Explo.More()) {
2591     //  TopoDS_Shape theShell = Explo.Current();
2592     //  theShell.Closed( Standard_True );
2593     //}
2594 
2595     Standard_Integer            NbShell = 0;
2596     TopoDS_Compound             NC;
2597     TopoDS_Shape                S1;
2598     BB.MakeCompound (NC);
2599 
2600     TopoDS_Solid Sol;
2601     BB.MakeSolid(Sol);
2602     Sol.Closed(Standard_True);
2603     for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2604       TopoDS_Shell Sh = TopoDS::Shell(Explo.Current());
2605       //if (myThickening && myOffset > 0.)
2606       //  Sh.Reverse();
2607       NbShell++;
2608       if (Sh.Closed()) {
2609         BB.Add(Sol,Sh);
2610       }
2611       else {
2612         BB.Add (NC,Sh);
2613         if(NbShell == 1)
2614         {
2615           S1 = Sh;
2616         }
2617       }
2618     }
2619     Standard_Integer nbs = Sol.NbChildren();
2620     Standard_Boolean SolIsNull = (nbs == 0);
2621     //Checking solid
2622     if (nbs > 1)
2623     {
2624       BRepCheck_Analyzer aCheck (Sol, Standard_False);
2625       if (!aCheck.IsValid ())
2626       {
2627         TopTools_ListOfShape aSolList;
2628         CorrectSolid (Sol, aSolList);
2629         if (!aSolList.IsEmpty ())
2630         {
2631           BB.Add (NC, Sol);
2632           TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
2633           for (; aSLIt.More (); aSLIt.Next ())
2634           {
2635             BB.Add (NC, aSLIt.Value ());
2636           }
2637           SolIsNull = Standard_True;
2638         }
2639       }
2640     }
2641     //
2642     Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
2643     if((!SolIsNull) && (!NCIsNull))
2644     {
2645       BB.Add(NC, Sol);
2646       myOffsetShape = NC;
2647     }
2648     else if(SolIsNull && (!NCIsNull))
2649     {
2650       if (NbShell == 1)
2651       {
2652         myOffsetShape = S1;
2653       }
2654       else
2655       {
2656         myOffsetShape = NC;
2657       }
2658     }
2659     else if((!SolIsNull) && NCIsNull)
2660     {
2661       myOffsetShape = Sol;
2662     }
2663     else
2664     {
2665       myOffsetShape = NC;
2666     }
2667   }
2668 }
2669 
2670 
2671 //=======================================================================
2672 //function : Intersection3D
2673 //purpose  :
2674 //=======================================================================
2675 
Intersection3D(BRepOffset_Inter3d & Inter,const Message_ProgressRange & theRange)2676 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter, const Message_ProgressRange& theRange)
2677 {
2678 #ifdef OCCT_DEBUG
2679   if (ChronBuild) {
2680     std::cout << " INTERSECTION 3D:" << std::endl;
2681     Clock.Reset();
2682     Clock.Start();
2683   }
2684 #endif
2685   Message_ProgressScope aPS(theRange, NULL, (myFaces.Extent() && myJoin == GeomAbs_Arc) ? 2 : 1);
2686 
2687   // In the Complete Intersection mode, implemented currently for planar
2688   // solids only, there is no need to intersect the faces here.
2689   // This intersection will be performed in the method BuildShellsCompleteInter
2690   // where the special treatment is applied to produced faces.
2691   //
2692   // Make sure to match the parameters in which the method
2693   // BuildShellsCompleteInter is called.
2694   if (myInter && (myJoin == GeomAbs_Intersection) && myIsPlanar &&
2695       !myThickening && myFaces.IsEmpty() && IsSolid(myShape))
2696     return;
2697 
2698 
2699   TopTools_ListOfShape OffsetFaces;  // list of faces // created.
2700   MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2701 
2702   if (!myFaces.IsEmpty()) {
2703     Standard_Boolean InSide = (myOffset < 0.); // Temporary
2704     // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2705     // between the cap and the part.
2706 
2707     if (myJoin == GeomAbs_Arc)
2708       Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge, aPS.Next());
2709   }
2710   if (myInter) {
2711     //-------------
2712     //Complete.
2713     //-------------
2714     Inter.CompletInt (OffsetFaces,myInitOffsetFace, aPS.Next());
2715     if (!aPS.More())
2716     {
2717       myError = BRepOffset_UserBreak;
2718       return;
2719     }
2720     TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2721     if (myJoin == GeomAbs_Intersection) {
2722       BRepOffset_Tool::CorrectOrientation (myFaceComp,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2723     }
2724   }
2725   else {
2726     //--------------------------------
2727     // Only between neighbor faces.
2728     //--------------------------------
2729     Inter.ConnexIntByArc(OffsetFaces,myFaceComp,myAnalyse,myInitOffsetFace, aPS.Next());
2730     if (!aPS.More())
2731     {
2732       myError = BRepOffset_UserBreak;
2733       return;
2734     }
2735   }
2736 #ifdef OCCT_DEBUG
2737   if ( ChronBuild) Clock.Show();
2738 #endif
2739 }
2740 
2741 //=======================================================================
2742 //function : Intersection2D
2743 //purpose  :
2744 //=======================================================================
2745 
Intersection2D(const TopTools_IndexedMapOfShape & Modif,const TopTools_IndexedMapOfShape & NewEdges,const Message_ProgressRange & theRange)2746 void BRepOffset_MakeOffset::Intersection2D (const TopTools_IndexedMapOfShape& Modif,
2747                                             const TopTools_IndexedMapOfShape& NewEdges,
2748                                             const Message_ProgressRange&      theRange)
2749 {
2750 #ifdef OCCT_DEBUG
2751   if (ChronBuild) {
2752     std::cout << " INTERSECTION 2D:" << std::endl;
2753     Clock.Reset();
2754     Clock.Start();
2755   }
2756 #endif
2757   //--------------------------------------------------------
2758   // calculate intersections2d on faces concerned by
2759   // intersection3d
2760   //---------------------------------------------------------
2761   //TopTools_MapIteratorOfMapOfShape it(Modif);
2762   //-----------------------------------------------
2763   // Intersection of edges 2 by 2.
2764   //-----------------------------------------------
2765   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
2766   Standard_Integer i;
2767   Message_ProgressScope aPS(theRange, "Intersection 2D", Modif.Extent());
2768   for (i = 1; i <= Modif.Extent(); i++) {
2769     if (!aPS.More())
2770     {
2771       myError = BRepOffset_UserBreak;
2772       return;
2773     }
2774     const TopoDS_Face& F  = TopoDS::Face(Modif(i));
2775     BRepOffset_Inter2d::Compute(myAsDes, F, NewEdges, myTol, myEdgeIntEdges, aDMVV, aPS.Next());
2776   }
2777   //
2778   BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes, myImageVV);
2779   //
2780 #ifdef OCCT_DEBUG
2781   if (AffichInt2d) {
2782     DEBVerticesControl (NewEdges,myAsDes);
2783   }
2784   if ( ChronBuild) Clock.Show();
2785 #endif
2786 }
2787 
2788 
2789 //=======================================================================
2790 //function : MakeLoops
2791 //purpose  :
2792 //=======================================================================
2793 
MakeLoops(TopTools_IndexedMapOfShape & Modif,const Message_ProgressRange & theRange)2794 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif, const Message_ProgressRange& theRange)
2795 {
2796 #ifdef OCCT_DEBUG
2797   if (ChronBuild) {
2798      std::cout << " DEBOUCLAGE 2D:" << std::endl;
2799      Clock.Reset();
2800      Clock.Start();
2801   }
2802 #endif
2803   //TopTools_MapIteratorOfMapOfShape    it(Modif);
2804   TopTools_ListOfShape                LF,LC;
2805   //-----------------------------------------
2806   // unwinding of faces // modified.
2807   //-----------------------------------------
2808   Standard_Integer i;
2809   for (i = 1; i <= Modif.Extent(); i++) {
2810     if (!myFaces.Contains(Modif(i)))
2811       LF.Append(Modif(i));
2812   }
2813   //
2814   Message_ProgressScope aPS(theRange, NULL, LF.Extent() + myFaces.Extent());
2815   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2816     BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset, aPS.Next(LF.Extent()));
2817   }
2818   else {
2819     myMakeLoops.Build(LF,myAsDes,myImageOffset,myImageVV, aPS.Next(LF.Extent()));
2820   }
2821   if (!aPS.More())
2822   {
2823     myError = BRepOffset_UserBreak;
2824     return;
2825   }
2826 
2827   //-----------------------------------------
2828   // unwinding of caps.
2829   //-----------------------------------------
2830   for (i = 1; i <= myFaces.Extent(); i++)
2831     LC.Append(myFaces(i));
2832 
2833   Standard_Boolean   InSide = 1;
2834   if (myOffset > 0 ) InSide = 0;
2835   myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide, aPS.Next(LC.Extent()));
2836 
2837 #ifdef OCCT_DEBUG
2838   if ( ChronBuild) Clock.Show();
2839 #endif
2840 }
2841 
2842 //=======================================================================
2843 //function : MakeFaces
2844 //purpose  : Reconstruction of topologically unchanged faces that
2845 //           share edges that were reconstructed.
2846 //=======================================================================
2847 
MakeFaces(TopTools_IndexedMapOfShape &,const Message_ProgressRange & theRange)2848 void BRepOffset_MakeOffset::MakeFaces (TopTools_IndexedMapOfShape& /*Modif*/,
2849                                        const Message_ProgressRange& theRange)
2850 {
2851 #ifdef OCCT_DEBUG
2852   if (ChronBuild) {
2853     std::cout << " RECONSTRUCTION OF FACES:" << std::endl;
2854     Clock.Reset();
2855     Clock.Start();
2856   }
2857 #endif
2858   TopTools_ListIteratorOfListOfShape itr;
2859   const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2860   TopTools_ListOfShape        LOF;
2861   //----------------------------------
2862   // Loop on all faces //.
2863   //----------------------------------
2864   for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2865     TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2866     if (!myImageOffset.HasImage(F)) {
2867       LOF.Append(F);
2868     }
2869   }
2870   //
2871   Message_ProgressScope aPS(theRange, NULL, 1);
2872   if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2873     BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset, aPS.Next());
2874   }
2875   else {
2876     myMakeLoops.BuildFaces(LOF, myAsDes, myImageOffset, aPS.Next());
2877   }
2878   if (!aPS.More())
2879   {
2880     myError = BRepOffset_UserBreak;
2881     return;
2882   }
2883 #ifdef OCCT_DEBUG
2884   if ( ChronBuild) Clock.Show();
2885 #endif
2886 }
2887 
2888 //=======================================================================
2889 //function : UpdateInitOffset
2890 //purpose  : Update and cleaning of myInitOffset
2891 //=======================================================================
UpdateInitOffset(BRepAlgo_Image & myInitOffset,BRepAlgo_Image & myImageOffset,const TopoDS_Shape & myOffsetShape,const TopAbs_ShapeEnum & theShapeType)2892 static void UpdateInitOffset (BRepAlgo_Image&         myInitOffset,
2893                               BRepAlgo_Image&         myImageOffset,
2894                               const TopoDS_Shape&     myOffsetShape,
2895                               const TopAbs_ShapeEnum &theShapeType) // skv
2896 {
2897   BRepAlgo_Image NIOF;
2898   const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2899   TopTools_ListIteratorOfListOfShape it(Roots);
2900   for (; it.More(); it.Next()) {
2901     NIOF.SetRoot (it.Value());
2902   }
2903   for (it.Initialize(Roots); it.More(); it.Next()) {
2904     const TopoDS_Shape& SI = it.Value();
2905     TopTools_ListOfShape LI;
2906     TopTools_ListOfShape L1;
2907     myInitOffset.LastImage(SI,L1);
2908     TopTools_ListIteratorOfListOfShape itL1(L1);
2909     for (; itL1.More(); itL1.Next()) {
2910       const TopoDS_Shape& O1 = itL1.Value();
2911       TopTools_ListOfShape L2;
2912       myImageOffset.LastImage(O1,L2);
2913       LI.Append(L2);
2914     }
2915     NIOF.Bind(SI,LI);
2916   }
2917 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
2918 //  Supporting history.
2919 //   NIOF.Filter(myOffsetShape,TopAbs_FACE);
2920   NIOF.Filter(myOffsetShape, theShapeType);
2921 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
2922   myInitOffset = NIOF;
2923 }
2924 
2925 //=======================================================================
2926 //function : MakeMissingWalls
2927 //purpose  :
2928 //=======================================================================
MakeMissingWalls(const Message_ProgressRange & theRange)2929 void BRepOffset_MakeOffset::MakeMissingWalls (const Message_ProgressRange& theRange)
2930 {
2931   TopTools_IndexedDataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2932   TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2933   Standard_Real OffsetVal = Abs(myOffset);
2934 
2935   FillContours(myFaceComp, myAnalyse, Contours, MapEF);
2936 
2937   Message_ProgressScope aPS(theRange, "Making missing walls", Contours.Extent());
2938   for (Standard_Integer ic = 1; ic <= Contours.Extent(); ic++, aPS.Next())
2939   {
2940     if (!aPS.More())
2941     {
2942       myError = BRepOffset_UserBreak;
2943       return;
2944     }
2945     TopoDS_Vertex StartVertex = TopoDS::Vertex(Contours.FindKey(ic));
2946     TopoDS_Edge StartEdge;
2947     const TopTools_ListOfShape& aContour = Contours(ic);
2948     TopTools_ListIteratorOfListOfShape itl(aContour);
2949     Standard_Boolean FirstStep = Standard_True;
2950     TopoDS_Edge PrevEdge;
2951     TopoDS_Vertex PrevVertex = StartVertex;
2952     Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
2953     for (; itl.More(); itl.Next())
2954     {
2955       TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2956       TopoDS_Face aFaceOfEdge = TopoDS::Face(MapEF(anEdge));
2957 
2958       // Check for offset existence.
2959       if (!myInitOffsetEdge.HasImage(anEdge))
2960         continue;
2961 
2962       // Check for existence of two different vertices.
2963       TopTools_ListOfShape LOE, LOE2;
2964       myInitOffsetEdge.LastImage( anEdge, LOE );
2965       myImageOffset.LastImage( LOE.Last(), LOE2 );
2966       TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2967       TopoDS_Vertex V1, V2, V3, V4;
2968       TopExp::Vertices(OE,     V4, V3);
2969       TopExp::Vertices(anEdge, V1, V2);
2970       Standard_Real aF, aL;
2971       const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
2972       if (!aC.IsNull() &&
2973          (!aC->IsClosed() && !aC->IsPeriodic()))
2974       {
2975         gp_Pnt aPntF = BRep_Tool::Pnt(V1);
2976         gp_Pnt aPntL = BRep_Tool::Pnt(V2);
2977         Standard_Real aDistE = aPntF.SquareDistance(aPntL);
2978         if ( aDistE < Precision::SquareConfusion())
2979         {
2980           // Bad case: non closed, but vertexes mapped to same 3d point.
2981           continue;
2982         }
2983 
2984         Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
2985         if (aDistE < anEdgeTol)
2986         {
2987           // Potential problems not detected via checkshape.
2988           gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
2989           gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
2990           if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
2991           {
2992             // To avoid computation of complex analytical continuation of Sin / ArcSin.
2993             Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
2994             Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
2995             Standard_Real aCurrentAngle =  gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
2996             if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
2997                 Abs (aCurrentAngle) > aMaxAngle)
2998             {
2999               // anEdge not collinear to offset edge.
3000               isBuildFromScratch = Standard_True;
3001               myIsPerformSewing = Standard_True;
3002               continue;
3003             }
3004           }
3005         }
3006       }
3007 
3008       Standard_Boolean ToReverse = Standard_False;
3009       if (!V1.IsSame(PrevVertex))
3010       {
3011         TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
3012         aVtx = V3; V3 = V4; V4 = aVtx;
3013         ToReverse = Standard_True;
3014       }
3015 
3016       OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
3017       TopoDS_Edge E3, E4;
3018       Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
3019       if (FirstStep || isBuildFromScratch)
3020       {
3021         E4 = BRepLib_MakeEdge( V1, V4 );
3022         if (FirstStep)
3023           StartEdge = E4;
3024       }
3025       else
3026         E4 = PrevEdge;
3027       if (V2.IsSame(StartVertex) && !ArcOnV2)
3028         E3 = StartEdge;
3029       else
3030         E3 = BRepLib_MakeEdge( V2, V3 );
3031       E4.Reverse();
3032 
3033       if (isBuildFromScratch)
3034       {
3035         E3.Reverse();
3036         E4.Reverse();
3037       }
3038 
3039       TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
3040       const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
3041       Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
3042       Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
3043       BRep_Builder BB;
3044       TopoDS_Wire theWire;
3045       BB.MakeWire(theWire);
3046       if (ToReverse)
3047       {
3048         BB.Add(theWire, anEdge.Reversed());
3049         BB.Add(theWire, E3.Reversed());
3050         BB.Add(theWire, OE.Reversed());
3051         BB.Add(theWire, E4.Reversed());
3052       }
3053       else
3054       {
3055         BB.Add(theWire, anEdge);
3056         BB.Add(theWire, E3);
3057         BB.Add(theWire, OE);
3058         BB.Add(theWire, E4);
3059       }
3060 
3061       BRepLib::BuildCurves3d( theWire, myTol );
3062       theWire.Closed(Standard_True);
3063       TopoDS_Face NewFace;
3064       Handle(Geom_Surface) theSurf;
3065       BRepAdaptor_Curve BAcurve(anEdge);
3066       BRepAdaptor_Curve BAcurveOE(OE);
3067       Standard_Real fpar = BAcurve.FirstParameter();
3068       Standard_Real lpar = BAcurve.LastParameter();
3069       gp_Pnt PonE  = BAcurve.Value(fpar);
3070       gp_Pnt PonOE = BAcurveOE.Value(fpar);
3071       gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
3072       Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
3073       Standard_Boolean IsPlanar = Standard_False;
3074       if (BAcurve.GetType() == GeomAbs_Circle &&
3075         BAcurveOE.GetType() == GeomAbs_Circle)
3076       {
3077         gp_Circ aCirc = BAcurve.Circle();
3078         gp_Circ aCircOE = BAcurveOE.Circle();
3079         gp_Lin anAxisLine(aCirc.Axis());
3080         gp_Dir CircAxisDir = aCirc.Axis().Direction();
3081         if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
3082           anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
3083         { //cylinder, plane or cone
3084           if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
3085             theSurf = GC_MakeCylindricalSurface(aCirc).Value();
3086           else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
3087             IsPlanar = Standard_True;
3088             //
3089             gp_Pnt PonEL = BAcurve.Value(lpar);
3090             if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
3091               Standard_Boolean bIsHole;
3092               TopoDS_Edge aE1, aE2;
3093               TopoDS_Wire aW1, aW2;
3094               Handle(Geom_Plane) aPL;
3095               IntTools_FClass2d aClsf;
3096               //
3097               if (aCirc.Radius()>aCircOE.Radius()) {
3098                 aE1 = anEdge;
3099                 aE2 = OE;
3100               } else {
3101                 aE1 = OE;
3102                 aE2 = anEdge;
3103               }
3104               //
3105               BB.MakeWire(aW1);
3106               BB.Add(aW1, aE1);
3107               BB.MakeWire(aW2);
3108               BB.Add(aW2, aE2);
3109               //
3110               aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
3111               for (Standard_Integer i = 0; i < 2; ++i) {
3112                 TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
3113                 TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
3114                 //
3115                 TopoDS_Face aFace;
3116                 BB.MakeFace(aFace, aPL, Precision::Confusion());
3117                 BB.Add (aFace, aW);
3118                 aClsf.Init(aFace, Precision::Confusion());
3119                 bIsHole=aClsf.IsHole();
3120                 if ((bIsHole && !i) || (!bIsHole && i)) {
3121                   aW.Nullify();
3122                   BB.MakeWire(aW);
3123                   BB.Add(aW, aE.Reversed());
3124                 }
3125               }
3126               //
3127               BB.MakeFace(NewFace, aPL, Precision::Confusion());
3128               BB.Add(NewFace, aW1);
3129               BB.Add(NewFace, aW2);
3130             }
3131           }
3132           else //case of cone
3133           {
3134             gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
3135               aCirc.Radius(), aCircOE.Radius());
3136             gp_Ax3 theAx3(aCirc.Position());
3137             if (CircAxisDir * theCone.Axis().Direction() < 0.)
3138             {
3139               theAx3.ZReverse();
3140               CircAxisDir.Reverse();
3141             }
3142             theCone.SetPosition(theAx3);
3143             theSurf = new Geom_ConicalSurface(theCone);
3144           }
3145           if (!IsPlanar) {
3146             TopLoc_Location Loc;
3147             EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
3148             BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
3149             Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
3150             OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
3151             BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
3152             aLine2d  = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
3153             aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
3154             if (E3.IsSame(E4))
3155             {
3156               if (Coeff > 0.)
3157                 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
3158               else
3159               {
3160                 BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
3161                 theWire.Nullify();
3162                 BB.MakeWire(theWire);
3163                 BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
3164                 BB.Add(theWire, E4);
3165                 BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
3166                 BB.Add(theWire, E3);
3167                 theWire.Closed(Standard_True);
3168               }
3169             }
3170             else
3171             {
3172               BB.SameParameter(E3, Standard_False);
3173               BB.SameRange(E3, Standard_False);
3174               BB.SameParameter(E4, Standard_False);
3175               BB.SameRange(E4, Standard_False);
3176               BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
3177               BB.Range(E3, theSurf, Loc, 0., OffsetVal);
3178               BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
3179               BB.Range(E4, theSurf, Loc, 0., OffsetVal);
3180             }
3181             NewFace = BRepLib_MakeFace(theSurf, theWire);
3182           }
3183         } //cylinder or cone
3184       } //if both edges are arcs of circles
3185       if (NewFace.IsNull())
3186       {
3187         BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
3188         if (MF.Error() == BRepLib_FaceDone)
3189         {
3190           NewFace = MF.Face();
3191           IsPlanar = Standard_True;
3192         }
3193         else //Extrusion (by thrusections)
3194         {
3195           Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
3196           Handle(Geom_TrimmedCurve) TrEdgeCurve =
3197             new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
3198           Standard_Real fparOE, lparOE;
3199           Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
3200           Handle(Geom_TrimmedCurve) TrOffsetCurve =
3201             new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
3202           GeomFill_Generator ThrusecGenerator;
3203           ThrusecGenerator.AddCurve( TrEdgeCurve );
3204           ThrusecGenerator.AddCurve( TrOffsetCurve );
3205           ThrusecGenerator.Perform( Precision::PConfusion() );
3206           theSurf = ThrusecGenerator.Surface();
3207           //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
3208           Standard_Real Uf, Ul, Vf, Vl;
3209           theSurf->Bounds(Uf, Ul, Vf, Vl);
3210           TopLoc_Location Loc;
3211           EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
3212           BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
3213           OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
3214           BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
3215           Standard_Real UonV1 = (ToReverse)? Ul : Uf;
3216           Standard_Real UonV2 = (ToReverse)? Uf : Ul;
3217           aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
3218           aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
3219           if (E3.IsSame(E4))
3220           {
3221             BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
3222             Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
3223             BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
3224             BB.Range(E3, Vf, Vl);
3225           }
3226           else
3227           {
3228             BB.SameParameter(E3, Standard_False);
3229             BB.SameRange(E3, Standard_False);
3230             BB.SameParameter(E4, Standard_False);
3231             BB.SameRange(E4, Standard_False);
3232             BB.UpdateEdge(E3, aLine2d,  theSurf, Loc, Precision::Confusion());
3233             BB.Range(E3, theSurf, Loc, Vf, Vl);
3234             BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
3235             BB.Range(E4, theSurf, Loc, Vf, Vl);
3236             Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
3237             BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
3238             BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
3239             Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
3240             BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
3241             BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
3242           }
3243           NewFace = BRepLib_MakeFace(theSurf, theWire);
3244         }
3245       }
3246       if (!IsPlanar)
3247       {
3248         Standard_Real fparOE = BAcurveOE.FirstParameter();
3249         Standard_Real lparOE = BAcurveOE.LastParameter();
3250         TopLoc_Location Loc;
3251         if (Abs(fpar - fparOE) > Precision::Confusion())
3252         {
3253           const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
3254           gp_Pnt2d fp2d   = EdgeLine2d->Value(fpar);
3255           gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
3256           aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
3257           Handle(Geom_Curve) aCurve;
3258           Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
3259           Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
3260           GeomAdaptor_Surface GAsurf( theSurf );
3261           Handle(Geom2dAdaptor_Curve) HC2d  = new Geom2dAdaptor_Curve( AC2d );
3262           Handle(GeomAdaptor_Surface) HSurf = new GeomAdaptor_Surface( GAsurf );
3263           Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
3264           Standard_Real max_deviation = 0., average_deviation;
3265           GeomLib::BuildCurve3d(Precision::Confusion(),
3266             ConS, FirstPar, LastPar,
3267             aCurve, max_deviation, average_deviation);
3268           BB.UpdateEdge( anE4, aCurve, max_deviation );
3269           BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
3270           BB.Range( anE4, FirstPar, LastPar );
3271         }
3272         if (Abs(lpar - lparOE) > Precision::Confusion())
3273         {
3274           const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
3275           gp_Pnt2d lp2d   = EdgeLine2d->Value(lpar);
3276           gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
3277           aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
3278           Handle(Geom_Curve) aCurve;
3279           Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
3280           Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
3281           GeomAdaptor_Surface GAsurf( theSurf );
3282           Handle(Geom2dAdaptor_Curve) HC2d  = new Geom2dAdaptor_Curve( AC2d );
3283           Handle(GeomAdaptor_Surface) HSurf = new GeomAdaptor_Surface( GAsurf );
3284           Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
3285           Standard_Real max_deviation = 0., average_deviation;
3286           GeomLib::BuildCurve3d(Precision::Confusion(),
3287             ConS, FirstPar, LastPar,
3288             aCurve, max_deviation, average_deviation);
3289           BB.UpdateEdge( anE3, aCurve, max_deviation );
3290           BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
3291           BB.Range( anE3, FirstPar, LastPar );
3292         }
3293       }
3294       BRepLib::SameParameter(NewFace);
3295       BRepTools::Update(NewFace);
3296       //Check orientation
3297       TopAbs_Orientation anOr = OrientationOfEdgeInFace(anEdge, aFaceOfEdge);
3298       TopAbs_Orientation OrInNewFace = OrientationOfEdgeInFace(anEdge, NewFace);
3299       if (OrInNewFace != TopAbs::Reverse(anOr))
3300         NewFace.Reverse();
3301       ///////////////////
3302       myWalls.Append(NewFace);
3303       if (ArcOnV2)
3304       {
3305         TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
3306         TopoDS_Vertex arcV1, arcV2;
3307         TopExp::Vertices(anArc, arcV1, arcV2);
3308         Standard_Boolean ArcReverse = Standard_False;
3309         if (!arcV1.IsSame(V3))
3310         {
3311           TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
3312           ArcReverse = Standard_True;
3313         }
3314         TopoDS_Edge EA1, EA2;
3315         //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
3316         EA1 = E3;
3317         EA1.Reverse();
3318         if (ToReverse)
3319           EA1.Reverse();
3320         //////////////////////////////////////////////////////
3321         if (V2.IsSame(StartVertex))
3322           EA2 = StartEdge;
3323         else
3324           EA2 = BRepLib_MakeEdge( V2, arcV2 );
3325         anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
3326         if (EA1.Orientation() == TopAbs_REVERSED)
3327           anArc.Reverse();
3328         EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
3329         TopoDS_Wire arcWire;
3330         BB.MakeWire(arcWire);
3331         BB.Add(arcWire, EA1);
3332         BB.Add(arcWire, anArc);
3333         BB.Add(arcWire, EA2);
3334         BRepLib::BuildCurves3d( arcWire, myTol );
3335         arcWire.Closed(Standard_True);
3336         TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
3337         BRepTools::Update(arcFace);
3338         myWalls.Append(arcFace);
3339         TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
3340         const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
3341         PrevEdge = CEA2;
3342         PrevVertex = V2;
3343       }
3344       else
3345       {
3346         if (isBuildFromScratch)
3347         {
3348           PrevEdge = TopoDS::Edge(E4);
3349           PrevVertex = V1;
3350           isBuildFromScratch = Standard_False;
3351         }
3352         else
3353         {
3354           PrevEdge = E3;
3355           PrevVertex = V2;
3356         }
3357       }
3358       FirstStep = Standard_False;
3359     }
3360   }
3361 }
3362 
3363 //=======================================================================
3364 //function : MakeShells
3365 //purpose  :
3366 //=======================================================================
3367 
MakeShells(const Message_ProgressRange & theRange)3368 void BRepOffset_MakeOffset::MakeShells (const Message_ProgressRange& theRange)
3369 {
3370 #ifdef OCCT_DEBUG
3371   if (ChronBuild) {
3372     std::cout << " RECONSTRUCTION OF SHELLS:" << std::endl;
3373     Clock.Reset();
3374     Clock.Start();
3375   }
3376 #endif
3377   //
3378   Message_ProgressScope aPS(theRange, "Making shells", 1);
3379   // Prepare list of splits of the offset faces to make the shells
3380   TopTools_ListOfShape aLSF;
3381   const TopTools_ListOfShape& R = myImageOffset.Roots();
3382   TopTools_ListIteratorOfListOfShape it(R);
3383   //
3384   for (; it.More(); it.Next()) {
3385     if (!aPS.More())
3386     {
3387       myError = BRepOffset_UserBreak;
3388       return;
3389     }
3390     TopoDS_Shape aF = it.Value();
3391     if (myThickening) //offsetted faces must change their orientations
3392       aF.Reverse();
3393     //
3394     TopTools_ListOfShape Image;
3395     myImageOffset.LastImage(aF,Image);
3396     TopTools_ListIteratorOfListOfShape it2(Image);
3397     for (; it2.More(); it2.Next()) {
3398       const TopoDS_Shape& aFIm = it2.Value();
3399       aLSF.Append(aFIm);
3400     }
3401   }
3402   //
3403   if (myThickening) {
3404     TopExp_Explorer Explo(myShape, TopAbs_FACE);
3405     for (; Explo.More(); Explo.Next()) {
3406       const TopoDS_Shape& aF = Explo.Current();
3407       aLSF.Append(aF);
3408     }
3409     //
3410     it.Initialize(myWalls);
3411     for (; it.More(); it.Next()) {
3412       const TopoDS_Shape& aF = it.Value();
3413       aLSF.Append(aF);
3414     }
3415   }
3416   //
3417   if (aLSF.IsEmpty()) {
3418     return;
3419   }
3420   //
3421   Standard_Boolean bDone = Standard_False;
3422   if ((myJoin == GeomAbs_Intersection) && myInter &&
3423       !myThickening && myFaces.IsEmpty() &&
3424       IsSolid(myShape) && myIsPlanar) {
3425     //
3426     TopoDS_Shape aShells;
3427     bDone = BuildShellsCompleteInter(aLSF, myImageOffset, aShells, aPS.Next());
3428     if (bDone) {
3429       myOffsetShape = aShells;
3430     }
3431   }
3432   //
3433   if (!bDone) {
3434     BRepTools_Quilt Glue;
3435     TopTools_ListIteratorOfListOfShape aItLS(aLSF);
3436     for (; aItLS.More(); aItLS.Next()) {
3437       Glue.Add(aItLS.Value());
3438     }
3439     myOffsetShape = Glue.Shells();
3440   }
3441   //
3442   //Set correct value for closed flag
3443   TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
3444   for(; Explo.More(); Explo.Next())
3445   {
3446     TopoDS_Shape aS = Explo.Current();
3447     if(!aS.Closed())
3448     {
3449       if(BRep_Tool::IsClosed(aS))
3450       {
3451         aS.Closed(Standard_True);
3452       }
3453     }
3454   }
3455 }
3456 
3457 //=======================================================================
3458 //function : MakeSolid
3459 //purpose  :
3460 //=======================================================================
3461 
MakeSolid(const Message_ProgressRange & theRange)3462 void BRepOffset_MakeOffset::MakeSolid (const Message_ProgressRange& theRange)
3463 {
3464  if (myOffsetShape.IsNull()) return;
3465 
3466 //  Modified by skv - Mon Apr  4 18:17:27 2005 Begin
3467 //  Supporting history.
3468   UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3469   UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3470 //  Modified by skv - Mon Apr  4 18:17:27 2005 End
3471   TopExp_Explorer             exp;
3472   BRep_Builder                B;
3473   Standard_Integer            NbShell = 0;
3474   TopoDS_Compound             NC;
3475   TopoDS_Shape                S1;
3476   B.MakeCompound (NC);
3477 
3478   Message_ProgressScope aPS(theRange, "Making solid", 1);
3479 
3480   TopoDS_Solid Sol;
3481   B.MakeSolid(Sol);
3482   Sol.Closed(Standard_True);
3483   Standard_Boolean aMakeSolid = (myShape.ShapeType() == TopAbs_SOLID) || myThickening;
3484   for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3485     if (!aPS.More())
3486     {
3487       myError = BRepOffset_UserBreak;
3488       return;
3489     }
3490     TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3491     if (myThickening && myOffset > 0.)
3492       Sh.Reverse();
3493     NbShell++;
3494     if (Sh.Closed() && aMakeSolid) {
3495       B.Add(Sol,Sh);
3496     }
3497     else {
3498       B.Add (NC,Sh);
3499       if(NbShell == 1)
3500       {
3501         S1 = Sh;
3502       }
3503     }
3504   }
3505   Standard_Integer nbs = Sol.NbChildren();
3506   Standard_Boolean SolIsNull = (nbs == 0);
3507   //Checking solid
3508   if (nbs > 1)
3509   {
3510     BRepCheck_Analyzer aCheck (Sol, Standard_False);
3511     if (!aCheck.IsValid ())
3512     {
3513       TopTools_ListOfShape aSolList;
3514       CorrectSolid (Sol, aSolList);
3515       if (!aSolList.IsEmpty ())
3516       {
3517         B.Add (NC, Sol);
3518         TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
3519         for (; aSLIt.More (); aSLIt.Next ())
3520         {
3521           B.Add (NC, aSLIt.Value ());
3522         }
3523         SolIsNull = Standard_True;
3524       }
3525     }
3526   }
3527   Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
3528   if((!SolIsNull) && (!NCIsNull))
3529   {
3530     B.Add(NC, Sol);
3531     myOffsetShape = NC;
3532   }
3533   else if(SolIsNull && (!NCIsNull))
3534   {
3535     if (NbShell == 1)
3536     {
3537       myOffsetShape = S1;
3538     }
3539     else
3540     {
3541       myOffsetShape = NC;
3542     }
3543   }
3544   else if((!SolIsNull) && NCIsNull)
3545   {
3546     myOffsetShape = Sol;
3547   }
3548   else
3549   {
3550     myOffsetShape = NC;
3551   }
3552 }
3553 
3554 //=======================================================================
3555 //function : SelectShells
3556 //purpose  :
3557 //=======================================================================
3558 
SelectShells()3559 void BRepOffset_MakeOffset::SelectShells ()
3560 {
3561   TopTools_MapOfShape FreeEdges;
3562   TopExp_Explorer exp(myFaceComp,TopAbs_EDGE);
3563   //-------------------------------------------------------------
3564   // FreeEdges all edges that can have free border in the
3565   // parallel shell
3566   // 1 - free borders of myShape .
3567   //-------------------------------------------------------------
3568   for ( ; exp.More(); exp.Next()) {
3569     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3570     const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3571     if (LA.Extent() < 2) {
3572       if (myAnalyse.Type(E).First().Type() == ChFiDS_FreeBound) {
3573               FreeEdges.Add(E);
3574       }
3575     }
3576   }
3577   // myShape has free borders and there are no caps
3578   // no unwinding 3d.
3579   if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3580 
3581   myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3582 }
3583 
3584 //=======================================================================
3585 //function : OffsetFacesFromShapes
3586 //purpose  :
3587 //=======================================================================
3588 
OffsetFacesFromShapes() const3589 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3590 {
3591   return myInitOffsetFace;
3592 }
3593 
3594 //  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3595 
3596 //=======================================================================
3597 //function : GetJoinType
3598 //purpose  : Query offset join type.
3599 //=======================================================================
3600 
GetJoinType() const3601 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3602 {
3603   return myJoin;
3604 }
3605 
3606 //=======================================================================
3607 //function : OffsetEdgesFromShapes
3608 //purpose  :
3609 //=======================================================================
3610 
OffsetEdgesFromShapes() const3611 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3612 {
3613   return myInitOffsetEdge;
3614 }
3615 
3616 //  Modified by skv - Tue Mar 15 16:20:43 2005 End
3617 
3618 //=======================================================================
3619 //function : ClosingFaces
3620 //purpose  :
3621 //=======================================================================
3622 
ClosingFaces() const3623 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3624 {
3625   return myOriginalFaces;
3626 }
3627 
3628 
3629 
3630 //=======================================================================
3631 //function : EncodeRegularity
3632 //purpose  :
3633 //=======================================================================
3634 
EncodeRegularity()3635 void BRepOffset_MakeOffset::EncodeRegularity ()
3636 {
3637 #ifdef OCCT_DEBUG
3638   if (ChronBuild) {
3639     std::cout << " CODING OF REGULARITIES:" << std::endl;
3640     Clock.Reset();
3641     Clock.Start();
3642   }
3643 #endif
3644 
3645   if (myOffsetShape.IsNull()) return;
3646   // find edges G1 in the result
3647   TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3648 
3649   BRep_Builder B;
3650   TopTools_MapOfShape MS;
3651 
3652   for ( ; exp.More(); exp.Next()) {
3653     TopoDS_Edge OE  = TopoDS::Edge(exp.Current());
3654     BRepLib::BuildCurve3d(OE,myTol);
3655     TopoDS_Edge ROE = OE;
3656 
3657     if ( !MS.Add(OE)) continue;
3658 
3659     if ( myImageOffset.IsImage(OE))
3660       ROE = TopoDS::Edge(myImageOffset.Root(OE));
3661 
3662     const TopTools_ListOfShape& LofOF    = myAsDes->Ascendant(ROE);
3663 
3664     if (LofOF.Extent() != 2) {
3665 #ifdef OCCT_DEBUG_VERB
3666     std::cout << " Edge shared by " << LofOF.Extent() << " Faces" << std::endl;
3667 #endif
3668       continue;
3669     }
3670 
3671     const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3672     const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3673 
3674     if ( F1.IsNull() || F2.IsNull())
3675       continue;
3676 
3677     const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3678     const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3679 
3680     TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3681     TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3682 
3683     if (F1.IsSame(F2)) {
3684       if (BRep_Tool::IsClosed(OE,F1)) {
3685         // Temporary Debug for the Bench.
3686         // Check with YFR.
3687         // In mode intersection, the edges are not coded in myInitOffsetEdge
3688         // so, manage case by case
3689         // Note DUB; for Hidden parts, it is NECESSARY to code CN
3690         // Analytic Surfaces.
3691         if (myJoin == GeomAbs_Intersection) {
3692           BRepAdaptor_Surface BS(F1,Standard_False);
3693           GeomAbs_SurfaceType SType = BS.GetType();
3694           if (SType == GeomAbs_Cylinder ||
3695               SType == GeomAbs_Cone     ||
3696               SType == GeomAbs_Sphere   ||
3697               SType == GeomAbs_Torus      ) {
3698             B.Continuity(OE,F1,F1,GeomAbs_CN);
3699           }
3700           else {
3701             // See YFR : MaJ of myInitOffsetFace
3702           }
3703         }
3704         else if (myInitOffsetEdge.IsImage(ROE)) {
3705           if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3706             const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3707             const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3708             GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3709             if (Conti == GeomAbs_CN) {
3710               B.Continuity(OE,F1,F1,GeomAbs_CN);
3711             }
3712             else if ( Conti > GeomAbs_C0) {
3713               B.Continuity(OE,F1,F1,GeomAbs_G1);
3714             }
3715           }
3716         }
3717       }
3718       continue;
3719     }
3720 
3721 
3722     //  code regularities G1 between :
3723     //    - sphere and tube : one root is a vertex, the other is an edge
3724     //                        and the vertex is included in the edge
3725     //    - face and tube   : one root is a face, the other an edge
3726     //                        and the edge is included in the face
3727     //    - face and face    : if two root faces are tangent in
3728     //                        the initial shape, they will be tangent in the offset shape
3729     //    - tube and tube  : if 2 edges generating tubes are
3730     //                        tangents, the 2 will be tangent either.
3731     if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3732       TopoDS_Vertex V1,V2;
3733       TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3734       if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3735         B.Continuity(OE,F1,F2,GeomAbs_G1);
3736       }
3737     }
3738     else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3739       TopoDS_Vertex V1,V2;
3740       TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3741       if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3742         B.Continuity(OE,F1,F2,GeomAbs_G1);
3743       }
3744     }
3745     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3746       TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3747       for ( ; exp2.More(); exp2.Next()) {
3748         if ( exp2.Current().IsSame(Root2)) {
3749           B.Continuity(OE,F1,F2,GeomAbs_G1);
3750           break;
3751         }
3752       }
3753     }
3754     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3755       TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3756       for ( ; exp2.More(); exp2.Next()) {
3757         if ( exp2.Current().IsSame(Root1)) {
3758           B.Continuity(OE,F1,F2,GeomAbs_G1);
3759           break;
3760         }
3761       }
3762     }
3763     else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3764     //  if two root faces are tangent in
3765     //  the initial shape, they will be tangent in the offset shape
3766       TopTools_ListOfShape LE;
3767       BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_EDGE, LE);
3768       if ( LE.Extent() == 1) {
3769         const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3770         if ( myAnalyse.HasAncestor(Ed)) {
3771           const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3772           if (LI.Extent()       == 1   &&
3773               LI.First().Type() == ChFiDS_Tangential) {
3774             B.Continuity(OE,F1,F2,GeomAbs_G1);
3775           }
3776         }
3777       }
3778     }
3779     else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3780       TopTools_ListOfShape LV;
3781       BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_VERTEX, LV);
3782       if ( LV.Extent() == 1) {
3783         TopTools_ListOfShape LEdTg;
3784         myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3785                                TopoDS::Vertex(LV.First()),
3786                                LEdTg);
3787         TopTools_ListIteratorOfListOfShape it(LEdTg);
3788         for (; it.More(); it.Next()) {
3789           if ( it.Value().IsSame(Root2)) {
3790             B.Continuity(OE,F1,F2,GeomAbs_G1);
3791             break;
3792           }
3793         }
3794       }
3795     }
3796   }
3797 
3798 #ifdef OCCT_DEBUG
3799   if ( ChronBuild) Clock.Show();
3800 #endif
3801 }
3802 
3803 //=======================================================================
3804 //function : ComputeMaxDist
3805 //purpose  :
3806 //=======================================================================
ComputeMaxDist(const gp_Pln & thePlane,const Handle (Geom_Curve)& theCrv,const Standard_Real theFirst,const Standard_Real theLast)3807 Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
3808                              const Handle(Geom_Curve)& theCrv,
3809                              const Standard_Real theFirst,
3810                              const Standard_Real theLast)
3811 {
3812   Standard_Real aMaxDist = 0.;
3813   Standard_Integer i, NCONTROL = 23;
3814   Standard_Real aPrm, aDist2;
3815   gp_Pnt aP;
3816   for (i = 0; i< NCONTROL; i++) {
3817     aPrm = ((NCONTROL - 1 - i)*theFirst + i*theLast) / (NCONTROL - 1);
3818     aP = theCrv->Value(aPrm);
3819     if (Precision::IsInfinite(aP.X()) || Precision::IsInfinite(aP.Y())
3820       || Precision::IsInfinite(aP.Z()))
3821     {
3822       return Precision::Infinite();
3823     }
3824     aDist2 = thePlane.SquareDistance(aP);
3825     if (aDist2 > aMaxDist) aMaxDist = aDist2;
3826   }
3827   return sqrt(aMaxDist)*1.05;
3828 }
3829 //=======================================================================
3830 //function : UpDateTolerance
3831 //purpose  :
3832 //=======================================================================
3833 
UpdateTolerance(TopoDS_Shape & S,const TopTools_IndexedMapOfShape & Faces)3834 void UpdateTolerance (TopoDS_Shape& S,
3835                       const TopTools_IndexedMapOfShape& Faces)
3836 {
3837   BRep_Builder B;
3838   TopTools_MapOfShape View;
3839   TopoDS_Vertex V[2];
3840 
3841   // The edges of caps are not modified.
3842   Standard_Integer j;
3843   for (j = 1; j <= Faces.Extent(); j++) {
3844     const TopoDS_Shape& F = Faces(j);
3845     TopExp_Explorer Exp;
3846     for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3847       View.Add(Exp.Current());
3848     }
3849   }
3850 
3851   Standard_Real Tol;
3852   TopExp_Explorer ExpF;
3853   for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
3854   {
3855     const TopoDS_Shape& F = ExpF.Current();
3856     if (Faces.Contains(F))
3857     {
3858       continue;
3859     }
3860     BRepAdaptor_Surface aBAS(TopoDS::Face(F), Standard_False);
3861     TopExp_Explorer Exp;
3862     for (Exp.Init(F, TopAbs_EDGE); Exp.More(); Exp.Next()) {
3863       TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3864       Standard_Boolean isUpdated = Standard_False;
3865       if (aBAS.GetType() == GeomAbs_Plane)
3866       {
3867         //Edge does not seem to have pcurve on plane,
3868         //so EdgeCorrector does not include it in tolerance calculation
3869         Standard_Real aFirst, aLast;
3870         Handle(Geom_Curve) aCrv = BRep_Tool::Curve(E, aFirst, aLast);
3871         Standard_Real aMaxDist = ComputeMaxDist(aBAS.Plane(), aCrv, aFirst, aLast);
3872         E.Locked (Standard_False);
3873         B.UpdateEdge(E, aMaxDist);
3874         isUpdated = Standard_True;
3875       }
3876       if (View.Add(E))
3877       {
3878 
3879         BRepCheck_Edge EdgeCorrector(E);
3880         Tol = EdgeCorrector.Tolerance();
3881         B.UpdateEdge(E, Tol);
3882         isUpdated = Standard_True;
3883       }
3884       if (isUpdated)
3885       {
3886         Tol = BRep_Tool::Tolerance(E);
3887         // Update the vertices.
3888         TopExp::Vertices(E, V[0], V[1]);
3889 
3890         for (Standard_Integer i = 0; i <= 1; i++) {
3891           if (View.Add(V[i])) {
3892             Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3893             TV->Tolerance(0.);
3894             BRepCheck_Vertex VertexCorrector(V[i]);
3895             V[i].Locked (Standard_False);
3896             B.UpdateVertex(V[i], VertexCorrector.Tolerance());
3897             // use the occasion to clean the vertices.
3898             (TV->ChangePoints()).Clear();
3899           }
3900           B.UpdateVertex(V[i], Tol);
3901         }
3902       }
3903     }
3904   }
3905 }
3906 
3907 //=======================================================================
3908 //function : CorrectSolid
3909 //purpose  :
3910 //=======================================================================
CorrectSolid(TopoDS_Solid & theSol,TopTools_ListOfShape & theSolList)3911 void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
3912 {
3913   BRep_Builder aBB;
3914   TopoDS_Shape anOuterShell;
3915   NCollection_List<Standard_Real> aVols;
3916   Standard_Real aVolMax = 0., anOuterVol = 0.;
3917 
3918   TopoDS_Iterator anIt(theSol);
3919   for(; anIt.More(); anIt.Next())
3920   {
3921     const TopoDS_Shape& aSh = anIt.Value();
3922     GProp_GProps aVProps;
3923     BRepGProp::VolumeProperties(aSh, aVProps, Standard_True);
3924     if(Abs(aVProps.Mass()) > aVolMax)
3925     {
3926       anOuterVol = aVProps.Mass();
3927       aVolMax = Abs(anOuterVol);
3928       anOuterShell = aSh;
3929     }
3930     aVols.Append(aVProps.Mass());
3931   }
3932   //
3933   if (Abs(anOuterVol) < Precision::Confusion()) {
3934     return;
3935   }
3936   if(anOuterVol < 0.)
3937   {
3938     anOuterShell.Reverse();
3939   }
3940   TopoDS_Solid aNewSol;
3941   aBB.MakeSolid(aNewSol);
3942   aNewSol.Closed(Standard_True);
3943   aBB.Add(aNewSol, anOuterShell);
3944   BRepClass3d_SolidClassifier aSolClass(aNewSol);
3945   //
3946   anIt.Initialize(theSol);
3947   NCollection_List<Standard_Real>::Iterator aVIt(aVols);
3948   for(; anIt.More(); anIt.Next(), aVIt.Next())
3949   {
3950     TopoDS_Shell aSh = TopoDS::Shell(anIt.Value());
3951     if(aSh.IsSame(anOuterShell))
3952     {
3953       continue;
3954     }
3955     else
3956     {
3957       TopExp_Explorer aVExp(aSh, TopAbs_VERTEX);
3958       const TopoDS_Vertex& aV = TopoDS::Vertex(aVExp.Current());
3959       gp_Pnt aP = BRep_Tool::Pnt(aV);
3960       aSolClass.Perform(aP, BRep_Tool::Tolerance(aV));
3961       if(aSolClass.State() == TopAbs_IN)
3962       {
3963         if(aVIt.Value() > 0.)
3964         {
3965           aSh.Reverse();
3966         }
3967         aBB.Add(aNewSol, aSh);
3968       }
3969       else
3970       {
3971         if(aVIt.Value() < 0.)
3972         {
3973           aSh.Reverse();
3974         }
3975         TopoDS_Solid aSol;
3976         aBB.MakeSolid(aSol);
3977         aSol.Closed(Standard_True);
3978         aBB.Add(aSol, aSh);
3979         theSolList.Append(aSol);
3980       }
3981     }
3982   }
3983   theSol = aNewSol;
3984 }
3985 
3986 //=======================================================================
3987 //function : CheckInputData
3988 //purpose  : Check input data for possibility of offset perform.
3989 //=======================================================================
CheckInputData(const Message_ProgressRange & theRange)3990 Standard_Boolean BRepOffset_MakeOffset::CheckInputData(const Message_ProgressRange& theRange)
3991 {
3992   // Set initial error state.
3993   myError = BRepOffset_NoError;
3994   TopoDS_Shape aTmpShape;
3995   myBadShape = aTmpShape;
3996   Message_ProgressScope aPS(theRange, NULL, 1);
3997   // Non-null offset.
3998   if (Abs(myOffset) <= myTol)
3999   {
4000     Standard_Boolean isFound = Standard_False;
4001     TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
4002     for( ; anIter.More(); anIter.Next())
4003     {
4004       if (Abs(anIter.Value()) > myTol)
4005       {
4006         isFound = Standard_True;
4007         break;
4008       }
4009     }
4010 
4011     if (!isFound)
4012     {
4013       // No face with non-null offset found.
4014       myError = BRepOffset_NullOffset;
4015       return Standard_False;
4016     }
4017   }
4018 
4019   // Connectivity of input shape.
4020   if (!IsConnectedShell(myFaceComp))
4021   {
4022     myError = BRepOffset_NotConnectedShell;
4023     return Standard_False;
4024   }
4025 
4026   // Normals check and continuity check.
4027   const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
4028   Standard_Real aUmin, aUmax, aVmin, aVmax;
4029   TopExp_Explorer anExpSF(myFaceComp, TopAbs_FACE);
4030   NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
4031   TopLoc_Location L;
4032   gp_Pnt2d aPnt2d;
4033   for( ; anExpSF.More(); anExpSF.Next())
4034   {
4035     if (!aPS.More())
4036     {
4037       myError = BRepOffset_UserBreak;
4038       return Standard_False;
4039     }
4040     const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
4041 
4042     if (aPresenceMap.Contains(aF.TShape()))
4043     {
4044       // Not perform computations with partner shapes,
4045       // since they are contain same geometry.
4046       continue;
4047     }
4048     aPresenceMap.Add(aF.TShape());
4049 
4050     const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
4051     BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
4052 
4053     // Continuity check.
4054     if (aSurf->Continuity() == GeomAbs_C0)
4055     {
4056       myError = BRepOffset_C0Geometry;
4057       return Standard_False;
4058     }
4059 
4060     // Get degenerated points, to avoid check them.
4061     NCollection_Vector<gp_Pnt> aBad3dPnts;
4062     TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
4063     for( ; anExpFE.More(); anExpFE.Next())
4064     {
4065       const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
4066       if (BRep_Tool::Degenerated(aE))
4067       {
4068         aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
4069       }
4070     }
4071 
4072     // Geometry grid check.
4073     for(Standard_Integer i = 0; i <= aPntPerDim; i++)
4074     {
4075       Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
4076       for(Standard_Integer j = 0; j <= aPntPerDim; j++)
4077       {
4078         Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
4079 
4080         myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
4081         if (myError != BRepOffset_NoError)
4082           return Standard_False;
4083       }
4084     }
4085 
4086     // Vertex list check.
4087     TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
4088     for( ; anExpFV.More(); anExpFV.Next())
4089     {
4090       const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
4091       aPnt2d = BRep_Tool::Parameters(aV, aF);
4092 
4093       myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
4094       if (myError != BRepOffset_NoError)
4095         return Standard_False;
4096     }
4097   }
4098 
4099   return Standard_True;
4100 }
4101 
4102 
4103 //=======================================================================
4104 //function : GetBadShape
4105 //purpose  : Get shape where problems detected.
4106 //=======================================================================
GetBadShape() const4107 const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
4108 {
4109   return myBadShape;
4110 }
4111 
4112 //=======================================================================
4113 //function : RemoveInternalEdges
4114 //purpose  :
4115 //=======================================================================
RemoveInternalEdges()4116 void BRepOffset_MakeOffset::RemoveInternalEdges()
4117 {
4118   Standard_Boolean bRemoveWire, bRemoveEdge;
4119   TopExp_Explorer aExpF, aExpW, aExpE;
4120   TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
4121   //
4122   TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
4123   //
4124   aExpF.Init(myOffsetShape, TopAbs_FACE);
4125   for (; aExpF.More(); aExpF.Next()) {
4126     TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
4127     //
4128     TopTools_ListOfShape aLIW;
4129     //
4130     aExpW.Init(aF, TopAbs_WIRE);
4131     for (; aExpW.More(); aExpW.Next()) {
4132       TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
4133       //
4134       bRemoveWire = Standard_True;
4135       TopTools_ListOfShape aLIE;
4136       //
4137       aExpE.Init(aW, TopAbs_EDGE);
4138       for (; aExpE.More(); aExpE.Next()) {
4139         const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
4140         if (aE.Orientation() != TopAbs_INTERNAL) {
4141           bRemoveWire = Standard_False;
4142           continue;
4143         }
4144         //
4145         const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
4146         bRemoveEdge = (aLF.Extent() == 1);
4147         if (bRemoveEdge) {
4148           aLIE.Append(aE);
4149         }
4150         else {
4151           bRemoveWire = Standard_False;
4152         }
4153       }
4154       //
4155       if (bRemoveWire) {
4156         aLIW.Append(aW);
4157       }
4158       else if (aLIE.Extent()) {
4159         RemoveShapes(aW, aLIE);
4160       }
4161     }
4162     //
4163     if (aLIW.Extent()) {
4164       RemoveShapes(aF, aLIW);
4165     }
4166   }
4167 }
4168 
4169 //=======================================================================
4170 // static methods implementation
4171 //=======================================================================
4172 
4173 //=======================================================================
4174 //function : checkSinglePoint
4175 //purpose  : Check single point on surface for bad normals
4176 //=======================================================================
checkSinglePoint(const Standard_Real theUParam,const Standard_Real theVParam,const Handle (Geom_Surface)& theSurf,const NCollection_Vector<gp_Pnt> & theBadPoints)4177 BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
4178                                   const Standard_Real theVParam,
4179                                   const Handle(Geom_Surface)& theSurf,
4180                                   const NCollection_Vector<gp_Pnt>& theBadPoints)
4181 {
4182   gp_Pnt aPnt;
4183   gp_Vec aD1U, aD1V;
4184   theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
4185 
4186   if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
4187       aD1V.SquareMagnitude() < Precision::SquareConfusion() )
4188   {
4189     Standard_Boolean isKnownBadPnt = Standard_False;
4190     for(Standard_Integer anIdx  = theBadPoints.Lower();
4191                          anIdx <= theBadPoints.Upper();
4192                        ++anIdx)
4193     {
4194       if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
4195       {
4196         isKnownBadPnt = Standard_True;
4197         break;
4198       }
4199     } // for(Standard_Integer anIdx  = theBadPoints.Lower();
4200 
4201     if (!isKnownBadPnt)
4202     {
4203       return BRepOffset_BadNormalsOnGeometry;
4204     }
4205     else
4206     {
4207       return BRepOffset_NoError;
4208     }
4209   } //  if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
4210 
4211   if (aD1U.IsParallel(aD1V, Precision::Confusion()))
4212   {
4213     // Isolines are collinear.
4214     return BRepOffset_BadNormalsOnGeometry;
4215   }
4216 
4217   return BRepOffset_NoError;
4218 }
4219 
4220 //=======================================================================
4221 //function : RemoveShapes
4222 //purpose  : Removes the shapes <theLS> from the shape <theS>
4223 //=======================================================================
RemoveShapes(TopoDS_Shape & theS,const TopTools_ListOfShape & theLS)4224 void RemoveShapes(TopoDS_Shape& theS,
4225                   const TopTools_ListOfShape& theLS)
4226 {
4227   BRep_Builder aBB;
4228   //
4229   Standard_Boolean bFree = theS.Free();
4230   theS.Free(Standard_True);
4231   //
4232   TopTools_ListIteratorOfListOfShape aIt(theLS);
4233   for (; aIt.More(); aIt.Next()) {
4234     const TopoDS_Shape& aSI = aIt.Value();
4235     aBB.Remove(theS, aSI);
4236   }
4237   //
4238   theS.Free(bFree);
4239 }
4240 
4241 //=======================================================================
4242 //function : UpdateHistory
4243 //purpose  : Updates the history information
4244 //=======================================================================
UpdateHistory(const TopTools_ListOfShape & theLF,BOPAlgo_Builder & theGF,BRepAlgo_Image & theImage)4245 void UpdateHistory(const TopTools_ListOfShape& theLF,
4246                    BOPAlgo_Builder& theGF,
4247                    BRepAlgo_Image& theImage)
4248 {
4249   TopTools_ListIteratorOfListOfShape aIt(theLF);
4250   for (; aIt.More(); aIt.Next()) {
4251     const TopoDS_Shape& aF = aIt.Value();
4252     const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
4253     if (aLFIm.Extent()) {
4254       if (theImage.HasImage(aF)) {
4255         theImage.Add(aF, aLFIm);
4256       }
4257       else {
4258         theImage.Bind(aF, aLFIm);
4259       }
4260     }
4261   }
4262 }
4263 
4264 //=======================================================================
4265 //function : IntersectEdges
4266 //purpose  :
4267 //=======================================================================
IntersectEdges(const TopTools_ListOfShape & theFaces,BRepOffset_DataMapOfShapeOffset & theMapSF,TopTools_DataMapOfShapeShape & theMES,TopTools_DataMapOfShapeShape & theBuild,Handle (BRepAlgo_AsDes)& theAsDes,Handle (BRepAlgo_AsDes)& theAsDes2d,const Message_ProgressRange & theRange)4268 void BRepOffset_MakeOffset::IntersectEdges(const TopTools_ListOfShape& theFaces,
4269                                            BRepOffset_DataMapOfShapeOffset& theMapSF,
4270                                            TopTools_DataMapOfShapeShape& theMES,
4271                                            TopTools_DataMapOfShapeShape& theBuild,
4272                                            Handle(BRepAlgo_AsDes)& theAsDes,
4273                                            Handle(BRepAlgo_AsDes)& theAsDes2d,
4274                                            const Message_ProgressRange& theRange)
4275 {
4276   Standard_Real aTolF;
4277   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
4278   // intersect edges created from edges
4279   TopTools_IndexedMapOfShape aMFV;
4280   Message_ProgressScope aPSOuter(theRange, NULL , 2);
4281   Message_ProgressScope aPS1(aPSOuter.Next(), NULL, theFaces.Size());
4282   for (TopTools_ListOfShape::Iterator it (theFaces); it.More(); it.Next())
4283   {
4284     const TopoDS_Face& aF  = TopoDS::Face (it.Value());
4285     aTolF = BRep_Tool::Tolerance (aF);
4286     if (!BRepOffset_Inter2d::ConnexIntByInt(aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d,
4287                                             myOffset, aTolF, myAnalyse, aMFV, myImageVV, myEdgeIntEdges, aDMVV, aPS1.Next()))
4288     {
4289       myError = BRepOffset_CannotExtentEdge;
4290       return;
4291     }
4292     if (!aPS1.More())
4293     {
4294       myError = BRepOffset_UserBreak;
4295       return;
4296     }
4297   }
4298   // intersect edges created from vertices
4299   Standard_Integer i, aNbF = aMFV.Extent();
4300   Message_ProgressScope aPS2(aPSOuter.Next(), "Intersecting edges created from vertices", aNbF);
4301   for (i = 1; i <= aNbF; ++i) {
4302     const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
4303     aTolF = BRep_Tool::Tolerance(aF);
4304     BRepOffset_Inter2d::ConnexIntByIntInVert
4305       (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, myAnalyse, aDMVV, aPS2.Next());
4306     if (!aPS2.More())
4307     {
4308       myError = BRepOffset_UserBreak;
4309       return;
4310     }
4311   }
4312   //
4313   // fuse vertices on edges
4314   if (!BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d, myImageVV))
4315   {
4316     myError = BRepOffset_CannotFuseVertices;
4317     return;
4318   }
4319 }
4320 
4321 //=======================================================================
4322 //function : TrimEdges
4323 //purpose  :
4324 //=======================================================================
TrimEdges(const TopoDS_Shape & theShape,const Standard_Real theOffset,const BRepOffset_Analyse & Analyse,BRepOffset_DataMapOfShapeOffset & theMapSF,TopTools_DataMapOfShapeShape & theMES,TopTools_DataMapOfShapeShape & theBuild,Handle (BRepAlgo_AsDes)& theAsDes,Handle (BRepAlgo_AsDes)& theAsDes2d,TopTools_IndexedMapOfShape & theNewEdges,TopTools_DataMapOfShapeShape & theETrimEInf,TopTools_DataMapOfShapeListOfShape & theEdgesOrigins)4325 Standard_Boolean TrimEdges(const TopoDS_Shape& theShape,
4326                  const Standard_Real theOffset,
4327                  const BRepOffset_Analyse& Analyse,
4328                  BRepOffset_DataMapOfShapeOffset& theMapSF,
4329                  TopTools_DataMapOfShapeShape& theMES,
4330                  TopTools_DataMapOfShapeShape& theBuild,
4331                  Handle(BRepAlgo_AsDes)& theAsDes,
4332                  Handle(BRepAlgo_AsDes)& theAsDes2d,
4333                  TopTools_IndexedMapOfShape& theNewEdges,
4334                  TopTools_DataMapOfShapeShape& theETrimEInf,
4335                  TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
4336 {
4337   TopExp_Explorer Exp,Exp2,ExpC;
4338   TopoDS_Shape    NE;
4339   TopoDS_Edge     TNE;
4340   TopoDS_Face     NF;
4341 
4342   TopTools_ListOfShape aLFaces;
4343   for (Exp.Init (theShape, TopAbs_FACE); Exp.More(); Exp.Next())
4344     aLFaces.Append (Exp.Current());
4345 
4346   TopTools_MapOfShape aMFGenerated;
4347   TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
4348   for (TopTools_ListOfShape::Iterator it (Analyse.NewFaces()); it.More(); it.Next())
4349   {
4350     const TopoDS_Shape& aFG = it.Value();
4351     aLFaces.Append (aFG);
4352     aMFGenerated.Add (aFG);
4353     TopExp::MapShapesAndUniqueAncestors (aFG, TopAbs_EDGE, TopAbs_FACE, aDMEF);
4354   }
4355 
4356   for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
4357   {
4358     const TopoDS_Face& FI  = TopoDS::Face (it.Value());
4359     NF = theMapSF(FI).Face();
4360     if (theMES.IsBound(NF)) {
4361       NF = TopoDS::Face(theMES(NF));
4362     }
4363     //
4364     TopTools_MapOfShape View;
4365     TopTools_IndexedMapOfShape VEmap;
4366     Standard_Integer i, aNb;
4367     //
4368     TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
4369     TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
4370     //
4371     aNb = VEmap.Extent();
4372     for (i = 1; i <= aNb; ++i) {
4373       const TopoDS_Shape& aS = VEmap(i);
4374       if (!View.Add(aS)) {
4375         continue;
4376       }
4377       //
4378       if (theBuild.IsBound(aS)) {
4379         NE = theBuild(aS);
4380         // keep connection to original edges
4381         ExpC.Init(NE, TopAbs_EDGE);
4382         for (; ExpC.More(); ExpC.Next()) {
4383           const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
4384           TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
4385           if (!pLEOr) {
4386             pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
4387           }
4388           AppendToList(*pLEOr, aS);
4389         }
4390         // trim edges
4391         if (NE.ShapeType() == TopAbs_EDGE) {
4392           if (theNewEdges.Add(NE)) {
4393             if (!TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf))
4394               return Standard_False;
4395           }
4396         }
4397         else {
4398           //------------------------------------------------------------
4399           // The Intersections are on several edges.
4400           // The pieces without intersections with neighbors
4401           // are removed from AsDes.
4402           //------------------------------------------------------------
4403           for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
4404             TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
4405             if (theNewEdges.Add(NEC)) {
4406               if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
4407                 if(!TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf))
4408                   return Standard_False;
4409               }
4410               else {
4411                 if (theAsDes->HasAscendant(NEC)) {
4412                   theAsDes->Remove(NEC);
4413                 }
4414               }
4415             }
4416           }
4417         }
4418       }
4419       else {
4420         if (aS.ShapeType() != TopAbs_EDGE) {
4421           continue;
4422         }
4423         if (aMFGenerated.Contains (FI) && aDMEF.FindFromKey (aS).Extent() == 1)
4424           continue;
4425 
4426         NE = theMapSF(FI).Generated(aS);
4427         //// modified by jgv, 19.12.03 for OCC4455 ////
4428         NE.Orientation(aS.Orientation());
4429         //
4430         TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
4431         if (!pLEOr) {
4432           pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
4433         }
4434         AppendToList(*pLEOr, aS);
4435         //
4436         if (theMES.IsBound(NE)) {
4437           NE = theMES(NE);
4438           NE.Orientation(aS.Orientation());
4439           if (theNewEdges.Add(NE)) {
4440             if (!TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf))
4441               return Standard_False;
4442           }
4443         }
4444         else {
4445           TopoDS_Edge& anEdge = TopoDS::Edge(NE);
4446           BRepAdaptor_Curve aBAC(anEdge);
4447           if (aBAC.GetType() == GeomAbs_Line) {
4448             TopoDS_Edge aNewEdge;
4449             BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
4450             theETrimEInf.Bind(anEdge, aNewEdge);
4451           }
4452         }
4453         theAsDes->Add(NF,NE);
4454       }
4455     }
4456   }
4457   return Standard_True;
4458 }
4459 
4460 //=======================================================================
4461 //function : TrimEdge
4462 //purpose  : Trim the edge of the largest of descendants in AsDes2d.
4463 //           Order in AsDes two vertices that have trimmed the edge.
4464 //=======================================================================
TrimEdge(TopoDS_Edge & NE,const Handle (BRepAlgo_AsDes)& AsDes2d,Handle (BRepAlgo_AsDes)& AsDes,TopTools_DataMapOfShapeShape & theETrimEInf)4465 Standard_Boolean TrimEdge(TopoDS_Edge&                  NE,
4466               const Handle(BRepAlgo_AsDes)& AsDes2d,
4467               Handle(BRepAlgo_AsDes)& AsDes,
4468               TopTools_DataMapOfShapeShape& theETrimEInf)
4469 {
4470   TopoDS_Edge aSourceEdge;
4471   TopoDS_Vertex V1,V2;
4472   Standard_Real aT1, aT2;
4473   //
4474   TopExp::Vertices(NE, V1, V2);
4475   BRep_Tool::Range(NE, aT1, aT2);
4476   //
4477   BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
4478   //
4479   //
4480   Standard_Real aSameParTol = Precision::Confusion();
4481 
4482   Standard_Real U = 0.;
4483   Standard_Real UMin =  Precision::Infinite();
4484   Standard_Real UMax = -UMin;
4485 
4486   const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
4487   //
4488   Standard_Boolean bTrim = Standard_False;
4489   //
4490   if (LE.Extent() > 1) {
4491     TopTools_ListIteratorOfListOfShape it (LE);
4492     for (; it.More(); it.Next()) {
4493       TopoDS_Vertex V = TopoDS::Vertex(it.Value());
4494       if (NE.Orientation() == TopAbs_REVERSED)
4495         V.Reverse();
4496       //V.Orientation(TopAbs_INTERNAL);
4497       if (!FindParameter(V, NE, U)) {
4498         Standard_Real f, l;
4499         Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
4500         gp_Pnt thePoint = BRep_Tool::Pnt(V);
4501         GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
4502         if (Projector.NbPoints() == 0)
4503         {
4504           return Standard_False;
4505         }
4506         U = Projector.LowerDistanceParameter();
4507       }
4508       if (U < UMin) {
4509         UMin = U; V1   = V;
4510       }
4511       if (U > UMax) {
4512         UMax = U; V2   = V;
4513       }
4514     }
4515     //
4516     if (V1.IsNull() || V2.IsNull()) {
4517       return Standard_False;
4518     }
4519     if (!V1.IsSame(V2)) {
4520       NE.Free( Standard_True );
4521       BRep_Builder B;
4522       TopAbs_Orientation Or = NE.Orientation();
4523       NE.Orientation(TopAbs_FORWARD);
4524       TopoDS_Vertex VF,VL;
4525       TopExp::Vertices (NE,VF,VL);
4526       B.Remove(NE,VF);
4527       B.Remove(NE,VL);
4528       B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
4529       B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
4530       B.Range(NE,UMin,UMax);
4531       NE.Orientation(Or);
4532       AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
4533       AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
4534       BRepLib::SameParameter(NE, aSameParTol, Standard_True);
4535       //
4536       bTrim = Standard_True;
4537     }
4538   }
4539   //
4540   if (!bTrim) {
4541     BRepAdaptor_Curve aBAC(NE);
4542     if (aBAC.GetType() == GeomAbs_Line) {
4543       if (AsDes->HasAscendant(NE)) {
4544         AsDes->Remove(NE);
4545       }
4546     }
4547   }
4548   else
4549   {
4550     if (!theETrimEInf.IsBound(NE)) {
4551       theETrimEInf.Bind(NE, aSourceEdge);
4552     }
4553   }
4554   return Standard_True;
4555 }
4556 
4557 //=======================================================================
4558 //function : GetEnlargedFaces
4559 //purpose  :
4560 //=======================================================================
GetEnlargedFaces(const TopTools_ListOfShape & theFaces,const BRepOffset_DataMapOfShapeOffset & theMapSF,const TopTools_DataMapOfShapeShape & theMES,TopTools_DataMapOfShapeShape & theFacesOrigins,BRepAlgo_Image & theImage,TopTools_ListOfShape & theLSF)4561 void GetEnlargedFaces(const TopTools_ListOfShape& theFaces,
4562                       const BRepOffset_DataMapOfShapeOffset& theMapSF,
4563                       const TopTools_DataMapOfShapeShape& theMES,
4564                       TopTools_DataMapOfShapeShape& theFacesOrigins,
4565                       BRepAlgo_Image& theImage,
4566                       TopTools_ListOfShape& theLSF)
4567 {
4568   for (TopTools_ListOfShape::Iterator it (theFaces); it.More(); it.Next())
4569   {
4570     const TopoDS_Shape& FI  = it.Value();
4571     const TopoDS_Shape& OFI = theMapSF(FI).Face();
4572     if (theMES.IsBound(OFI)) {
4573       const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
4574       theLSF.Append(aLocalFace);
4575       theImage.SetRoot(aLocalFace);
4576       theFacesOrigins.Bind(aLocalFace, FI);
4577     }
4578   }
4579 }
4580 
4581 //=======================================================================
4582 //function : BuildShellsCompleteInter
4583 //purpose  : Make the shells from list of faces using MakerVolume algorithm.
4584 //           In case there will be more than just one solid, it will be
4585 //           rebuilt using only outer faces.
4586 //=======================================================================
BuildShellsCompleteInter(const TopTools_ListOfShape & theLF,BRepAlgo_Image & theImage,TopoDS_Shape & theShells,const Message_ProgressRange & theRange)4587 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
4588                                           BRepAlgo_Image& theImage,
4589                                           TopoDS_Shape& theShells,
4590                                           const Message_ProgressRange& theRange)
4591 {
4592   Message_ProgressScope aPS(theRange, NULL, 5);
4593   // make solids
4594   BOPAlgo_MakerVolume aMV1;
4595   aMV1.SetArguments(theLF);
4596   // we need to intersect the faces to process the tangential faces
4597   aMV1.SetIntersect(Standard_True);
4598   aMV1.SetAvoidInternalShapes(Standard_True);
4599   aMV1.Perform(aPS.Next(3));
4600   //
4601   Standard_Boolean bDone = ! aMV1.HasErrors();
4602   if (!bDone) {
4603     return bDone;
4604   }
4605   //
4606   UpdateHistory(theLF, aMV1, theImage);
4607   //
4608   const TopoDS_Shape& aResult1 = aMV1.Shape();
4609   if (aResult1.ShapeType() == TopAbs_SOLID) {
4610     // result is the alone solid, nothing to do
4611     return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
4612   }
4613 
4614   // Allocators for effective memory allocations
4615   // Global allocator for the long-living containers
4616   Handle(NCollection_IncAllocator) anAllocGlob = new NCollection_IncAllocator;
4617   // Local allocator for the local containers
4618   Handle(NCollection_IncAllocator) anAllocLoc = new NCollection_IncAllocator;
4619 
4620   // Since the <theImage> object does not support multiple ancestors,
4621   // prepare local copy of the origins, which will be used to resolve
4622   // non-manifold solids produced by Maker Volume algorithm by comparison
4623   // of the normal directions of the split faces with their origins.
4624   TopTools_DataMapOfShapeListOfShape anOrigins(1, anAllocGlob);
4625   TopTools_ListIteratorOfListOfShape aItLR(theImage.Roots());
4626   for (; aItLR.More(); aItLR.Next())
4627   {
4628     const TopoDS_Shape& aFR = aItLR.Value();
4629 
4630     // Reset the local allocator
4631     anAllocLoc->Reset();
4632     // Find the last splits of the root face, including the ones
4633     // created during MakeVolume operation
4634     TopTools_ListOfShape aLFIm(anAllocLoc);
4635     theImage.LastImage(aFR, aLFIm);
4636 
4637     TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4638     for (; aItLFIm.More(); aItLFIm.Next())
4639     {
4640       const TopoDS_Shape& aFIm = aItLFIm.Value();
4641       TopTools_ListOfShape *pLFOr = anOrigins.ChangeSeek(aFIm);
4642       if (!pLFOr) {
4643         pLFOr = anOrigins.Bound(aFIm, TopTools_ListOfShape(anAllocGlob));
4644       }
4645       pLFOr->Append(aFR);
4646     }
4647   }
4648 
4649   // Reset the local allocator
4650   anAllocLoc->Reset();
4651   // It is necessary to rebuild the solids, avoiding internal faces
4652   // Map faces to solids
4653   TopTools_IndexedDataMapOfShapeListOfShape aDMFS(1, anAllocLoc);
4654   TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
4655   //
4656   Standard_Integer i, aNb = aDMFS.Extent();
4657   bDone = (aNb > 0);
4658   if (!bDone) {
4659     // unable to build any solid
4660     return bDone;
4661   }
4662   //
4663   // get faces attached to only one solid
4664   TopTools_ListOfShape aLF(anAllocLoc);
4665   for (i = 1; i <= aNb; ++i) {
4666     const TopTools_ListOfShape& aLS = aDMFS(i);
4667     if (aLS.Extent() == 1) {
4668       const TopoDS_Shape& aF = aDMFS.FindKey(i);
4669       aLF.Append(aF);
4670     }
4671   }
4672   //
4673   // make solids from the new list
4674   BOPAlgo_MakerVolume aMV2;
4675   aMV2.SetArguments(aLF);
4676   // no need to intersect this time
4677   aMV2.SetIntersect(Standard_False);
4678   aMV2.SetAvoidInternalShapes(Standard_True);
4679   aMV2.Perform(aPS.Next());
4680   bDone = ! aMV2.HasErrors();
4681   if (!bDone) {
4682     return bDone;
4683   }
4684   //
4685   const TopoDS_Shape& aResult2 = aMV2.Shape();
4686   if (aResult2.ShapeType() == TopAbs_SOLID) {
4687     return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
4688   }
4689   //
4690   TopExp_Explorer aExp(aResult2, TopAbs_FACE);
4691   bDone = aExp.More();
4692   if (!bDone) {
4693     return bDone;
4694   }
4695   //
4696   aLF.Clear();
4697   aDMFS.Clear();
4698   anAllocLoc->Reset();
4699 
4700   // the result is non-manifold - resolve it comparing normal
4701   // directions of the offset faces and original faces
4702   for (; aExp.More(); aExp.Next())
4703   {
4704     const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
4705     const TopTools_ListOfShape* pLFOr = anOrigins.Seek(aF);
4706     if (!pLFOr)
4707     {
4708       Standard_ASSERT_INVOKE("BRepOffset_MakeOffset::BuildShellsCompleteInterSplit(): "
4709                              "Origins map does not contain the split face");
4710       continue;
4711     }
4712     // Check orientation
4713     TopTools_ListIteratorOfListOfShape aItLOr(*pLFOr);
4714     for (; aItLOr.More(); aItLOr.Next())
4715     {
4716       const TopoDS_Face& aFOr = TopoDS::Face(aItLOr.Value());
4717       if (BRepOffset_Tool::CheckPlanesNormals(aF, aFOr))
4718       {
4719         aLF.Append(aF);
4720         break;
4721       }
4722     }
4723   }
4724   //
4725   // make solid from most outer faces with correct normal direction
4726   BOPAlgo_MakerVolume aMV3;
4727   aMV3.SetArguments(aLF);
4728   aMV3.SetIntersect(Standard_False);
4729   aMV3.SetAvoidInternalShapes(Standard_True);
4730   aMV3.Perform(aPS.Next());
4731   bDone = ! aMV3.HasErrors();
4732   if (!bDone) {
4733     return bDone;
4734   }
4735   //
4736   const TopoDS_Shape& aResult3 = aMV3.Shape();
4737   return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
4738 }
4739 
4740 //=======================================================================
4741 //function : Generated
4742 //purpose  :
4743 //=======================================================================
Generated(const TopoDS_Shape & theS)4744 const TopTools_ListOfShape& BRepOffset_MakeOffset::Generated (const TopoDS_Shape& theS)
4745 {
4746   myGenerated.Clear();
4747   const TopAbs_ShapeEnum aType = theS.ShapeType();
4748   switch (aType)
4749   {
4750     case TopAbs_VERTEX:
4751     {
4752       if (myAnalyse.HasAncestor (theS))
4753       {
4754         TopTools_MapOfShape aMFence;
4755         const TopTools_ListOfShape& aLA = myAnalyse.Ancestors (theS);
4756         TopTools_ListOfShape::Iterator itLA (aLA);
4757         for (; myGenerated.IsEmpty() && itLA.More(); itLA.Next())
4758         {
4759           const TopoDS_Shape& aE = itLA.Value();
4760           if (!myInitOffsetEdge.HasImage (aE))
4761             continue;
4762           TopTools_ListOfShape aLEIm;
4763           myInitOffsetEdge.LastImage (aE, aLEIm);
4764           TopTools_ListOfShape::Iterator itLEIm (aLEIm);
4765           for (; myGenerated.IsEmpty() && itLEIm.More(); itLEIm.Next())
4766           {
4767             TopoDS_Iterator itV (itLEIm.Value());
4768             for (; itV.More(); itV.Next())
4769             {
4770               if (!aMFence.Add (itV.Value()))
4771               {
4772                 myGenerated.Append (itV.Value());
4773                 break;
4774               }
4775             }
4776           }
4777         }
4778       }
4779     }
4780     Standard_FALLTHROUGH
4781     case TopAbs_EDGE:
4782     {
4783       if (myInitOffsetEdge.HasImage (theS))
4784       {
4785         myInitOffsetEdge.LastImage (theS, myGenerated);
4786       }
4787     }
4788     Standard_FALLTHROUGH
4789     case TopAbs_FACE:
4790     {
4791       TopoDS_Shape aS = theS;
4792       const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aS);
4793       if (aPlanface)
4794         aS = TopoDS::Face(*aPlanface);
4795 
4796       if (!myFaces.Contains (aS) &&
4797           myInitOffsetFace.HasImage (aS))
4798       {
4799         myInitOffsetFace.LastImage (aS, myGenerated);
4800 
4801         if (!myFaces.IsEmpty())
4802         {
4803           // Reverse generated shapes in case of small solids.
4804           // Useful only for faces without influence on others.
4805           TopTools_ListIteratorOfListOfShape it(myGenerated);
4806           for (; it.More(); it.Next())
4807             it.Value().Reverse();
4808         }
4809       }
4810       break;
4811     }
4812     case TopAbs_SOLID:
4813     {
4814       if (theS.IsSame (myShape))
4815         myGenerated.Append (myOffsetShape);
4816       break;
4817     }
4818     default:
4819       break;
4820   }
4821 
4822   if (myResMap.IsEmpty())
4823     TopExp::MapShapes (myOffsetShape, myResMap);
4824 
4825   for (TopTools_ListOfShape::Iterator it (myGenerated); it.More();)
4826   {
4827     if (myResMap.Contains (it.Value()))
4828       it.Next();
4829     else
4830       myGenerated.Remove (it);
4831   }
4832 
4833   return myGenerated;
4834 }
4835 
4836 //=======================================================================
4837 //function : Modified
4838 //purpose  :
4839 //=======================================================================
Modified(const TopoDS_Shape & theShape)4840 const TopTools_ListOfShape& BRepOffset_MakeOffset::Modified (const TopoDS_Shape& theShape)
4841 {
4842   myGenerated.Clear();
4843 
4844   if (theShape.ShapeType() == TopAbs_FACE)
4845   {
4846     TopoDS_Shape aS = theShape;
4847     const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aS);
4848     if (aPlanface)
4849       aS = TopoDS::Face(*aPlanface);
4850 
4851     if (myFaces.Contains (aS) &&
4852         myInitOffsetFace.HasImage (aS))
4853     {
4854       myInitOffsetFace.LastImage (aS, myGenerated);
4855 
4856       if (!myFaces.IsEmpty())
4857       {
4858         // Reverse generated shapes in case of small solids.
4859         // Useful only for faces without influence on others.
4860         TopTools_ListIteratorOfListOfShape it(myGenerated);
4861         for (; it.More(); it.Next())
4862           it.Value().Reverse();
4863       }
4864     }
4865   }
4866 
4867   return myGenerated;
4868 }
4869 
4870 //=======================================================================
4871 //function : IsDeleted
4872 //purpose  :
4873 //=======================================================================
IsDeleted(const TopoDS_Shape & theS)4874 Standard_Boolean BRepOffset_MakeOffset::IsDeleted (const TopoDS_Shape& theS)
4875 {
4876   if (myResMap.IsEmpty())
4877     TopExp::MapShapes (myOffsetShape, myResMap);
4878 
4879   if (myResMap.Contains (theS))
4880     return Standard_False;
4881 
4882   return Generated (theS).IsEmpty()
4883       && Modified  (theS).IsEmpty();
4884 }
4885 
4886 //=======================================================================
4887 //function : GetSubShapes
4888 //purpose  :
4889 //=======================================================================
GetSubShapes(const TopoDS_Shape & theShape,const TopAbs_ShapeEnum theSSType,TopoDS_Shape & theResult)4890 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
4891                               const TopAbs_ShapeEnum theSSType,
4892                               TopoDS_Shape& theResult)
4893 {
4894   TopExp_Explorer aExp(theShape, theSSType);
4895   if (!aExp.More()) {
4896     return Standard_False;
4897   }
4898   //
4899   TopoDS_Compound aResult;
4900   BRep_Builder().MakeCompound(aResult);
4901   //
4902   for (; aExp.More(); aExp.Next()) {
4903     const TopoDS_Shape& aSS = aExp.Current();
4904     BRep_Builder().Add(aResult, aSS);
4905   }
4906   theResult = aResult;
4907   return Standard_True;
4908 }
4909 
4910 //=======================================================================
4911 //function : analyzeProgress
4912 //purpose  :
4913 //=======================================================================
analyzeProgress(const Standard_Real theWhole,TColStd_Array1OfReal & theSteps) const4914 void BRepOffset_MakeOffset::analyzeProgress (const Standard_Real theWhole,
4915                                              TColStd_Array1OfReal& theSteps) const
4916 {
4917   theSteps.Init(0.0);
4918 
4919   // Set, approximately, the proportions for each operation.
4920   // It is not a problem that the sum of the set values will not
4921   // be equal to 100%, as the values will be normalized.
4922   // The main point is to make the proportions valid relatively each other.
4923 
4924   // Proportions will be different for different connection types
4925   Standard_Boolean isArc = (myJoin == GeomAbs_Arc);
4926   Standard_Boolean isPlanarIntCase = myInter && !isArc && myIsPlanar && !myThickening &&
4927                                      myFaces.IsEmpty() && IsSolid(myShape);
4928 
4929   theSteps(PIOperation_CheckInputData) = 1.;
4930   theSteps(PIOperation_Analyse) = 2.;
4931   theSteps(PIOperation_BuildOffsetBy) = isPlanarIntCase ? 70. : (isArc ? 20. : 50.);
4932   theSteps(PIOperation_Intersection) = isPlanarIntCase ? 0. : (isArc ? 50. : 20.);
4933   if (myThickening)
4934   {
4935     theSteps(PIOperation_MakeMissingWalls) = 5.;
4936   }
4937   theSteps(PIOperation_MakeShells) = isPlanarIntCase ? 25. : 5.;
4938   theSteps(PIOperation_MakeSolid) = 5.;
4939   if (myIsPerformSewing && myThickening)
4940   {
4941     theSteps(PIOperation_Sewing) = 10.;
4942   }
4943 
4944   normalizeSteps(theWhole, theSteps);
4945 }
4946 
4947 //=======================================================================
4948 //function : IsPlanar
4949 //purpose  : Checks if all the faces of the shape are planes
4950 //=======================================================================
IsPlanar()4951 Standard_Boolean BRepOffset_MakeOffset::IsPlanar()
4952 {
4953   Standard_Boolean aIsNonPlanarFound = Standard_False;
4954   BRep_Builder aBB;
4955 
4956   TopExp_Explorer aExp(myShape, TopAbs_FACE);
4957   for (; aExp.More(); aExp.Next())
4958   {
4959     const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
4960     BRepAdaptor_Surface aBAS(aF, Standard_False);
4961     if (aBAS.GetType() == GeomAbs_Plane)
4962       continue;
4963 
4964     if (myIsLinearizationAllowed)
4965     {
4966       //define the toleance
4967       Standard_Real aTolForFace = BRep_Tool::Tolerance(aF);
4968 
4969       //try to linearize
4970       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
4971       GeomLib_IsPlanarSurface aPlanarityChecker(aSurf, Precision::Confusion());
4972       if (aPlanarityChecker.IsPlanar())
4973       {
4974         gp_Pln aPln = aPlanarityChecker.Plan();
4975         Handle(Geom_Plane) aPlane = new Geom_Plane(aPln);
4976         TopoDS_Face aPlanarFace;
4977         aBB.MakeFace(aPlanarFace, aPlane, aTolForFace);
4978         TopoDS_Face aFaceForward = aF;
4979         aFaceForward.Orientation(TopAbs_FORWARD);
4980         TopoDS_Iterator anItFace(aFaceForward);
4981         for (; anItFace.More(); anItFace.Next())
4982         {
4983           const TopoDS_Shape& aWire = anItFace.Value();
4984           aBB.Add(aPlanarFace, aWire);
4985         }
4986         RemoveSeamAndDegeneratedEdges(aPlanarFace, aFaceForward);
4987         myFacePlanfaceMap.Bind(aF, aPlanarFace);
4988         if (myFaces.Contains(aF))
4989         {
4990           myFaces.RemoveKey(aF);
4991           myFaces.Add(aPlanarFace);
4992         }
4993       }
4994       else
4995         aIsNonPlanarFound = Standard_True;
4996     }
4997     else
4998       aIsNonPlanarFound = Standard_True;
4999   }
5000 
5001   return (!aIsNonPlanarFound);
5002 }
5003 
5004 //=======================================================================
5005 //function : RemoveSeamAndDegeneratedEdges
5006 //purpose  : Removes useless seam and degenerated edges from a face that becomes planar
5007 //=======================================================================
RemoveSeamAndDegeneratedEdges(const TopoDS_Face & theFace,const TopoDS_Face & theOldFace)5008 void RemoveSeamAndDegeneratedEdges(const TopoDS_Face& theFace,
5009                                    const TopoDS_Face& theOldFace)
5010 {
5011   TopoDS_Face aFace = theFace;
5012   aFace.Orientation(TopAbs_FORWARD);
5013 
5014   Standard_Boolean aIsDegOrSeamFound = Standard_False;
5015   TopTools_SequenceOfShape aEseq;
5016   TopExp_Explorer anExplo(aFace, TopAbs_EDGE);
5017   for (; anExplo.More(); anExplo.Next())
5018   {
5019     const TopoDS_Edge& anEdge = TopoDS::Edge(anExplo.Current());
5020     if (BRep_Tool::Degenerated(anEdge) ||
5021         BRepTools::IsReallyClosed(anEdge, theOldFace))
5022       aIsDegOrSeamFound = Standard_True;
5023     else
5024       aEseq.Append(anEdge);
5025   }
5026 
5027   if (!aIsDegOrSeamFound)
5028     return;
5029 
5030   //Reconstruct wires
5031   BRep_Builder aBB;
5032   TopTools_ListOfShape aWlist;
5033   TopoDS_Iterator anItFace(aFace);
5034   for (; anItFace.More(); anItFace.Next())
5035     aWlist.Append(anItFace.Value());
5036 
5037   aFace.Free(Standard_True);
5038   TopTools_ListIteratorOfListOfShape anItl(aWlist);
5039   for (; anItl.More(); anItl.Next())
5040     aBB.Remove(aFace, anItl.Value());
5041 
5042   while (!aEseq.IsEmpty())
5043   {
5044     TopoDS_Wire aNewWire;
5045     aBB.MakeWire(aNewWire);
5046     TopoDS_Edge aCurEdge = TopoDS::Edge(aEseq(1));
5047     aBB.Add(aNewWire, aCurEdge);
5048     aEseq.Remove(1);
5049     TopoDS_Vertex aFirstVertex, aCurVertex;
5050     TopExp::Vertices(aCurEdge, aFirstVertex, aCurVertex, Standard_True); //with orientation
5051     while (!aCurVertex.IsSame(aFirstVertex))
5052     {
5053       TopoDS_Vertex aV1, aV2;
5054       Standard_Integer ind;
5055       for (ind = 1; ind <= aEseq.Length(); ind++)
5056       {
5057         aCurEdge = TopoDS::Edge(aEseq(ind));
5058         TopExp::Vertices(aCurEdge, aV1, aV2, Standard_True); //with orientation
5059         if (aV1.IsSame(aCurVertex))
5060           break;
5061       }
5062       if (ind > aEseq.Length()) //error occurred: wire is not closed
5063         break;
5064 
5065       aBB.Add(aNewWire, aCurEdge);
5066       aEseq.Remove(ind);
5067       aCurVertex = aV2;
5068     }
5069 
5070     aBB.Add(aFace, aNewWire);
5071   }
5072 }
5073 
5074 //=======================================================================
5075 //function : IsSolid
5076 //purpose  : Checks if the shape is solid
5077 //=======================================================================
IsSolid(const TopoDS_Shape & theS)5078 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
5079 {
5080   TopExp_Explorer aExp(theS, TopAbs_SOLID);
5081   return aExp.More();
5082 }
5083 
5084 //=======================================================================
5085 //function : AppendToList
5086 //purpose  : Add to a list only unique elements
5087 //=======================================================================
AppendToList(TopTools_ListOfShape & theList,const TopoDS_Shape & theShape)5088 void AppendToList(TopTools_ListOfShape& theList,
5089                   const TopoDS_Shape& theShape)
5090 {
5091   TopTools_ListIteratorOfListOfShape aIt(theList);
5092   for (; aIt.More(); aIt.Next()) {
5093     const TopoDS_Shape& aS = aIt.Value();
5094     if (aS.IsSame(theShape)) {
5095       return;
5096     }
5097   }
5098   theList.Append(theShape);
5099 }
5100