1 // Created on: 1996-09-03
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1996-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 - Wed Dec 24 18:08:39 2003 OCC4455
18 
19 #include <BRepOffset_Inter2d.hxx>
20 
21 #include <Adaptor2d_Curve2d.hxx>
22 #include <Adaptor3d_CurveOnSurface.hxx>
23 #include <Adaptor3d_Surface.hxx>
24 #include <Bnd_Box.hxx>
25 #include <BndLib_Add3dCurve.hxx>
26 #include <BOPTools_AlgoTools.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRep_CurveRepresentation.hxx>
29 #include <BRep_GCurve.hxx>
30 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
31 #include <BRep_TEdge.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRepAdaptor_Curve.hxx>
34 #include <BRepAdaptor_Curve2d.hxx>
35 #include <BRepAdaptor_Surface.hxx>
36 #include <BRepAlgo_AsDes.hxx>
37 #include <BRepAlgo_Image.hxx>
38 #include <BRepLib.hxx>
39 #include <BRepLib_MakeVertex.hxx>
40 #include <BRepOffset_Analyse.hxx>
41 #include <BRepOffset_Offset.hxx>
42 #include <BRepOffset_Tool.hxx>
43 #include <BRepTools.hxx>
44 #include <BRepTools_WireExplorer.hxx>
45 #include <Geom2d_BezierCurve.hxx>
46 #include <Geom2d_BSplineCurve.hxx>
47 #include <Geom2d_Line.hxx>
48 #include <Geom2d_TrimmedCurve.hxx>
49 #include <Geom2dAdaptor_Curve.hxx>
50 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
51 #include <Geom2dInt_GInter.hxx>
52 #include <Geom_BSplineCurve.hxx>
53 #include <Geom_BSplineSurface.hxx>
54 #include <Geom_ConicalSurface.hxx>
55 #include <Geom_CylindricalSurface.hxx>
56 #include <Geom_Line.hxx>
57 #include <Geom_Plane.hxx>
58 #include <Geom_TrimmedCurve.hxx>
59 #include <GeomAdaptor_Surface.hxx>
60 #include <GeomAPI_ProjectPointOnCurve.hxx>
61 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
62 #include <GeomLib.hxx>
63 #include <GeomProjLib.hxx>
64 #include <gp_Pnt.hxx>
65 #include <IntRes2d_IntersectionPoint.hxx>
66 #include <IntRes2d_IntersectionSegment.hxx>
67 #include <IntTools_Tools.hxx>
68 #include <Precision.hxx>
69 #include <TColGeom2d_SequenceOfCurve.hxx>
70 #include <TColgp_Array1OfPnt2d.hxx>
71 #include <TColgp_SequenceOfPnt.hxx>
72 #include <TopExp.hxx>
73 #include <TopExp_Explorer.hxx>
74 #include <TopoDS.hxx>
75 #include <TopoDS_Edge.hxx>
76 #include <TopoDS_Face.hxx>
77 #include <TopoDS_Iterator.hxx>
78 #include <TopoDS_Vertex.hxx>
79 #include <TopoDS_Wire.hxx>
80 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
81 #include <TopTools_ListIteratorOfListOfShape.hxx>
82 #include <TopTools_ListOfShape.hxx>
83 #include <TopTools_SequenceOfShape.hxx>
84 
85 #include <stdio.h>
86 #ifdef DRAW
87 #include <DBRep.hxx>
88 #include <Geom2d_BoundedCurve.hxx>
89 #include <Geom_BoundedSurface.hxx>
90 #include <Geom_BoundedCurve.hxx>
91 #include <BRep_CurveOnSurface.hxx>
92 #include <Geom_Surface.hxx>
93 Standard_Boolean Inter2dAffichInt2d;
94 static Standard_Integer NbF2d = 0;
95 static Standard_Integer NbE2d = 0;
96 static Standard_Integer NbNewVertices  = 0;
97 #endif
98 
99 //=======================================================================
100 //function : CommonVertex
101 //purpose  :
102 //=======================================================================
103 
CommonVertex(TopoDS_Edge & E1,TopoDS_Edge & E2)104 static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1,
105 				  TopoDS_Edge& E2)
106 {
107   TopoDS_Vertex V1[2],V2[2],V;
108   //
109   TopExp::Vertices(E1,V1[0],V1[1], Standard_True);
110   TopExp::Vertices(E2,V2[0],V2[1], Standard_True);
111   // The first edge is the current one, the second edge is the next one.
112   // We check last vertex of the first edge first.
113   if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1];
114   if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0];
115   //
116   return V;
117 }
118 
DefineClosedness(const TopoDS_Face & theFace)119 static Standard_Integer DefineClosedness(const TopoDS_Face& theFace)
120 {
121   TopExp_Explorer anExplo (theFace, TopAbs_EDGE);
122   for (; anExplo.More(); anExplo.Next())
123   {
124     const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current());
125     if (BRepTools::IsReallyClosed(anEdge, theFace))
126     {
127       Standard_Real fpar, lpar;
128       Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar);
129       gp_Vec2d aTangent = aPCurve->DN(fpar, 1);
130       Standard_Real aCrossProd1 = aTangent ^ gp::DX2d();
131       Standard_Real aCrossProd2 = aTangent ^ gp::DY2d();
132       if (Abs(aCrossProd2) < Abs(aCrossProd1)) //pcurve is parallel to OY
133         return 1;
134       else
135         return 2;
136     }
137   }
138 
139   return 0;
140 }
141 
GetEdgesOrientedInFace(const TopoDS_Shape & theShape,const TopoDS_Face & theFace,const Handle (BRepAlgo_AsDes)& theAsDes,TopTools_SequenceOfShape & theSeqEdges)142 static void GetEdgesOrientedInFace(const TopoDS_Shape& theShape,
143                                    const TopoDS_Face&  theFace,
144                                    const Handle(BRepAlgo_AsDes)& theAsDes,
145                                    TopTools_SequenceOfShape&     theSeqEdges)
146 {
147   const TopTools_ListOfShape& aEdges = theAsDes->Descendant (theFace);
148 
149   TopExp_Explorer anExplo (theShape, TopAbs_EDGE);
150   for (; anExplo.More(); anExplo.Next())
151   {
152     const TopoDS_Shape& anEdge = anExplo.Current();
153     TopTools_ListIteratorOfListOfShape itl (aEdges);
154     for (; itl.More(); itl.Next())
155     {
156       const TopoDS_Shape& anEdgeInFace = itl.Value();
157       if (anEdgeInFace.IsSame(anEdge))
158       {
159         theSeqEdges.Append (anEdgeInFace);
160         break;
161       }
162     }
163   }
164 
165   if (theSeqEdges.Length() == 1)
166     return;
167 
168   TopTools_IndexedDataMapOfShapeListOfShape aVEmap;
169   for (Standard_Integer ii = 1; ii <= theSeqEdges.Length(); ii++)
170     TopExp::MapShapesAndAncestors (theSeqEdges(ii), TopAbs_VERTEX, TopAbs_EDGE, aVEmap);
171 
172   TopoDS_Vertex aFirstVertex;
173   TopoDS_Edge aFirstEdge;
174   for (Standard_Integer ii = 1; ii <= aVEmap.Extent(); ii++)
175   {
176     const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVEmap.FindKey(ii));
177     const TopTools_ListOfShape& aElist = aVEmap(ii);
178     if (aElist.Extent() == 1)
179     {
180       const TopoDS_Edge& anEdge = TopoDS::Edge(aElist.First());
181       TopoDS_Vertex aV1, aV2;
182       TopExp::Vertices(anEdge, aV1, aV2, Standard_True); //with orientation
183       if (aV1.IsSame(aVertex))
184       {
185         aFirstVertex = aVertex;
186         aFirstEdge = anEdge;
187         break;
188       }
189     }
190   }
191 
192   if (aFirstEdge.IsNull()) //closed set of edges
193   {
194     //Standard_Real aPeriod = 0.;
195     Standard_Integer IndCoord = DefineClosedness (theFace);
196     /*
197     BRepAdaptor_Surface aBAsurf (theFace, Standard_False);
198     if (IndCoord == 1)
199       aPeriod = aBAsurf.LastUParameter() - aBAsurf.FirstUParameter();
200     else if (IndCoord == 2)
201       aPeriod = aBAsurf.LastVParameter() - aBAsurf.FirstVParameter();
202     */
203 
204     if (IndCoord != 0)
205     {
206       Standard_Real aMaxDelta = 0.;
207       for (Standard_Integer ii = 1; ii <= aVEmap.Extent(); ii++)
208       {
209         const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVEmap.FindKey(ii));
210         const TopTools_ListOfShape& aElist = aVEmap(ii);
211         const TopoDS_Edge& anEdge1 = TopoDS::Edge(aElist.First());
212         const TopoDS_Edge& anEdge2 = TopoDS::Edge(aElist.Last());
213         Standard_Real aParam1 = BRep_Tool::Parameter(aVertex, anEdge1);
214         Standard_Real aParam2 = BRep_Tool::Parameter(aVertex, anEdge2);
215         BRepAdaptor_Curve2d aBAcurve1 (anEdge1, theFace);
216         BRepAdaptor_Curve2d aBAcurve2 (anEdge2, theFace);
217         gp_Pnt2d aPnt1 = aBAcurve1.Value(aParam1);
218         gp_Pnt2d aPnt2 = aBAcurve2.Value(aParam2);
219         Standard_Real aDelta = Abs(aPnt1.Coord(IndCoord) - aPnt2.Coord(IndCoord));
220         if (aDelta > aMaxDelta)
221         {
222           aMaxDelta = aDelta;
223           aFirstVertex = aVertex;
224         }
225       }
226       const TopTools_ListOfShape& aElist = aVEmap.FindFromKey(aFirstVertex);
227       TopTools_ListIteratorOfListOfShape itl (aElist);
228       for (; itl.More(); itl.Next())
229       {
230         const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
231         TopoDS_Vertex aV1, aV2;
232         TopExp::Vertices(anEdge, aV1, aV2, Standard_True); //with orientation
233         if (aV1.IsSame(aFirstVertex))
234         {
235           aFirstEdge = anEdge;
236           break;
237         }
238       }
239     }
240   }
241 
242   Standard_Integer aNbEdges = theSeqEdges.Length();
243   theSeqEdges.Clear();
244   theSeqEdges.Append (aFirstEdge);
245   TopoDS_Edge anEdge = aFirstEdge;
246   for (;;)
247   {
248     TopoDS_Vertex aLastVertex = TopExp::LastVertex (anEdge, Standard_True); //with orientation
249     if (aLastVertex.IsSame(aFirstVertex))
250       break;
251 
252     const TopTools_ListOfShape& aElist = aVEmap.FindFromKey(aLastVertex);
253     if (aElist.Extent() == 1)
254       break;
255 
256     if (aElist.First().IsSame(anEdge))
257       anEdge = TopoDS::Edge(aElist.Last());
258     else
259       anEdge = TopoDS::Edge(aElist.First());
260 
261     theSeqEdges.Append (anEdge);
262     if (theSeqEdges.Length() == aNbEdges)
263       break;
264   }
265 }
266 
267 //=======================================================================
268 //function : Store
269 //purpose  : Store the vertices <theLV> into AsDes for the edge <theEdge>.
270 //           The vertices are added despite of the coincidence with
271 //           already added vertices. When all vertices for all edges
272 //           are added the coinciding chains of vertices should be fused
273 //           using FuseVertices() method.
274 //=======================================================================
Store(const TopoDS_Edge & theEdge,const TopTools_ListOfShape & theLV,const Standard_Real theTol,const Standard_Boolean IsToUpdate,Handle (BRepAlgo_AsDes)theAsDes2d,TopTools_IndexedDataMapOfShapeListOfShape & theDMVV)275 static void Store(const TopoDS_Edge& theEdge,
276                   const TopTools_ListOfShape& theLV,
277                   const Standard_Real theTol,
278                   const Standard_Boolean IsToUpdate,
279                   Handle(BRepAlgo_AsDes) theAsDes2d,
280                   TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
281 {
282   // Update vertices
283   TopTools_ListIteratorOfListOfShape aIt(theLV);
284   for (; aIt.More(); aIt.Next()) {
285     const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value());
286     BRep_Builder().UpdateVertex(aV, theTol);
287   }
288 
289   // Get vertices already added to the edge and check the distances to the new ones
290   const TopTools_ListOfShape& aLVEx = theAsDes2d->Descendant(theEdge);
291   if (!IsToUpdate && aLVEx.IsEmpty()) {
292     if (theLV.Extent()) theAsDes2d->Add(theEdge, theLV);
293     return;
294   }
295   //
296   GeomAPI_ProjectPointOnCurve aProjPC;
297   Standard_Real aTolE = 0.0;
298   if (IsToUpdate) {
299     Standard_Real aT1, aT2;
300     const Handle(Geom_Curve)& aC = BRep_Tool::Curve(theEdge, aT1, aT2);
301     aProjPC.Init(aC, aT1, aT2);
302     aTolE = BRep_Tool::Tolerance(theEdge);
303   }
304   //
305   TopTools_MapOfShape aMV;
306   for (aIt.Init(theLV); aIt.More(); aIt.Next()) {
307     const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value());
308     if (!aMV.Add(aV)) {
309       continue;
310     }
311     //
312     const gp_Pnt& aP = BRep_Tool::Pnt(aV);
313     const Standard_Real aTol = BRep_Tool::Tolerance(aV);
314     //
315     TopTools_ListOfShape aLVC;
316     TopTools_ListIteratorOfListOfShape aItEx(aLVEx);
317     for (; aItEx.More(); aItEx.Next()) {
318       const TopoDS_Vertex& aVEx = TopoDS::Vertex(aItEx.Value());
319       if (aV.IsSame(aVEx)) {
320         break;
321       }
322       const gp_Pnt& aPEx = BRep_Tool::Pnt(aVEx);
323       const Standard_Real aTolVEx = BRep_Tool::Tolerance(aVEx);
324       if (aP.IsEqual(aPEx, aTol + aTolVEx)) {
325         aLVC.Append(aVEx);
326       }
327     }
328     //
329     if (aItEx.More()) {
330       continue;
331     }
332     //
333     if (IsToUpdate) {
334       // get parameter of the vertex on the edge
335       aProjPC.Perform(aP);
336       if (!aProjPC.NbPoints()) {
337         continue;
338       }
339       //
340       if (aProjPC.LowerDistance() > aTol + aTolE) {
341         continue;
342       }
343       //
344       Standard_Real aT = aProjPC.LowerDistanceParameter();
345       TopoDS_Shape aLocalShape = aV.Oriented(TopAbs_INTERNAL);
346       BRep_Builder().UpdateVertex(TopoDS::Vertex(aLocalShape), aT, theEdge, aTol);
347     }
348     //
349     if (aLVC.Extent()) {
350       TopTools_ListIteratorOfListOfShape aItLV(aLVC);
351       for (; aItLV.More(); aItLV.Next()) {
352         const TopoDS_Shape& aVC = aItLV.Value();
353         TopTools_ListOfShape* pLV = theDMVV.ChangeSeek(aVC);
354         if (!pLV) {
355           pLV = &theDMVV(theDMVV.Add(aVC, TopTools_ListOfShape()));
356         }
357         pLV->Append(aV);
358       }
359       //
360       TopTools_ListOfShape* pLV = theDMVV.ChangeSeek(aV);
361       if (!pLV) {
362         pLV = &theDMVV(theDMVV.Add(aV, TopTools_ListOfShape()));
363       }
364       pLV->Append(aLVC);
365     }
366     theAsDes2d->Add(theEdge, aV);
367   }
368 }
369 
370 //=======================================================================
371 //function : Store
372 //purpose  : Store the intersection vertices between two edges into AsDes
373 //=======================================================================
Store(const TopoDS_Edge & theE1,const TopoDS_Edge & theE2,const TopTools_ListOfShape & theLV1,const TopTools_ListOfShape & theLV2,const Standard_Real theTol,Handle (BRepAlgo_AsDes)theAsDes2d,TopTools_IndexedDataMapOfShapeListOfShape & theDMVV)374 static void  Store (const TopoDS_Edge& theE1,
375                     const TopoDS_Edge& theE2,
376                     const TopTools_ListOfShape& theLV1,
377                     const TopTools_ListOfShape& theLV2,
378                     const Standard_Real theTol,
379                     Handle(BRepAlgo_AsDes) theAsDes2d,
380                     TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
381 {
382   for (Standard_Integer i = 0; i < 2; ++i) {
383     const TopoDS_Edge& aE = !i ? theE1 : theE2;
384     const TopTools_ListOfShape& aLV = !i ? theLV1 : theLV2;
385     Store(aE, aLV, theTol, Standard_False, theAsDes2d, theDMVV);
386   }
387 }
388 
389 //=======================================================================
390 //function : EdgeInter
391 //purpose  :
392 //=======================================================================
393 
EdgeInter(const TopoDS_Face & F,const BRepAdaptor_Surface & BAsurf,const TopoDS_Edge & E1,const TopoDS_Edge & E2,const Handle (BRepAlgo_AsDes)& AsDes,Standard_Real Tol,Standard_Boolean WithOri,TopTools_IndexedDataMapOfShapeListOfShape & aDMVV)394 static void EdgeInter(const TopoDS_Face&              F,
395                       const BRepAdaptor_Surface&      BAsurf,
396                       const TopoDS_Edge&              E1,
397                       const TopoDS_Edge&              E2,
398                       const Handle(BRepAlgo_AsDes)&   AsDes,
399                       Standard_Real                   Tol,
400                       Standard_Boolean                WithOri,
401                       TopTools_IndexedDataMapOfShapeListOfShape& aDMVV)
402 {
403 #ifdef DRAW
404   if (Inter2dAffichInt2d) {
405     char name[256];
406     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
407     DBRep::Set(name,E1);
408     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
409     DBRep::Set(name,E2);
410   }
411 #endif
412 
413   if (E1.IsSame(E2))
414     return;
415 
416   Standard_Real f[3],l[3];
417   Standard_Real TolDub = 1.e-7;
418   Standard_Integer i;
419 
420   BRep_Tool::Range(E1, f[1], l[1]);
421   BRep_Tool::Range(E2, f[2], l[2]);
422 
423   BRepAdaptor_Curve CE1(E1,F);
424   BRepAdaptor_Curve CE2(E2,F);
425 
426   TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;
427   TopTools_ListOfShape        LV1;
428   TopTools_ListOfShape        LV2;
429   BRep_Builder                B;
430 
431   TopoDS_Vertex CV;
432   if (!TopExp::CommonVertex( E1, E2, CV ))
433     {
434       BRepLib::BuildCurve3d(E1);
435       BRepLib::BuildCurve3d(E2);
436 
437       Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
438       TolSum = Max( TolSum, 1.e-5 );
439 
440       TColgp_SequenceOfPnt   ResPoints;
441       TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2;
442       gp_Pnt DegPoint;
443       Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2);
444 
445       if (WithDegen)
446         {
447           Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2;
448           TopoDS_Iterator iter( EI[ideg] );
449           if (iter.More())
450             {
451               const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value());
452               DegPoint = BRep_Tool::Pnt(vdeg);
453             }
454           else
455             {
456               BRepAdaptor_Curve CEdeg( EI[ideg], F );
457               DegPoint = CEdeg.Value( CEdeg.FirstParameter() );
458             }
459         }
460         //
461       Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]);
462       Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]);
463       Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
464       Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
465       Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
466       for (i = 1; i <= Inter2d.NbPoints(); i++)
467         {
468           gp_Pnt P3d;
469           if (WithDegen)
470             P3d = DegPoint;
471           else
472             {
473               gp_Pnt2d P2d = Inter2d.Point(i).Value();
474               P3d = BAsurf.Value( P2d.X(), P2d.Y() );
475             }
476           ResPoints.Append( P3d );
477           ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() );
478           ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() );
479         }
480 
481       for (i = 1; i <= ResPoints.Length(); i++)
482         {
483           Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter();
484           Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter();
485           if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2))
486             {
487 #ifdef OCCT_DEBUG
488               std::cout << "Inter2d : Solution rejected due to infinite parameter"<<std::endl;
489 #endif
490               continue;
491             }
492 
493           gp_Pnt P = ResPoints(i); //ponc1.Value();
494           TopoDS_Vertex aNewVertex = BRepLib_MakeVertex(P);
495           aNewVertex.Orientation(TopAbs_INTERNAL);
496           B.UpdateVertex( aNewVertex, aT1, E1, Tol );
497           B.UpdateVertex( aNewVertex, aT2, E2, Tol );
498           gp_Pnt P1 = CE1.Value(aT1);
499           gp_Pnt P2 = CE2.Value(aT2);
500           Standard_Real dist1, dist2, dist3;
501           dist1 = P1.Distance(P);
502           dist2 = P2.Distance(P);
503           dist3 = P1.Distance(P2);
504           dist1 = Max( dist1, dist2 );
505           dist1 = Max( dist1, dist3 );
506           B.UpdateVertex( aNewVertex, dist1 );
507 
508 #ifdef OCCT_DEBUG
509           if (aT1 < f[1]-Tol  || aT1 > l[1]+Tol)
510             {
511               std::cout << "out of limit"<<std::endl;
512               std::cout<<"aT1 = "<<aT1<<", f[1] = "<<f[1]<<", l[1] = "<<l[1]<<std::endl;
513             }
514           if (aT2 < f[2]-Tol  || aT2 > l[2]+Tol)
515             {
516               std::cout << "out of limit"<<std::endl;
517               std::cout<<"aT2 = "<<aT2<<", f[2] = "<<f[2]<<", l[2] = "<<l[2]<<std::endl;
518             }
519           Standard_Real MilTol2 = 1000*Tol*Tol;
520           if (P1.SquareDistance(P) >  MilTol2 || P2.SquareDistance(P) > MilTol2 || P1.Distance(P2) > 2.*Tol)
521             {
522               std::cout << "Inter2d : Solution rejected "<<std::endl;
523               std::cout<<"P  = "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<std::endl;
524               std::cout<<"P1 = "<<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<std::endl;
525               std::cout<<"P2 = "<<P2.X()<<" "<<P2.Y()<<" "<<P2.Z()<<std::endl;
526               std::cout<<"MaxDist = "<<dist1<<std::endl;
527             }
528 #endif
529           //define the orientation of a new vertex
530           TopAbs_Orientation OO1 = TopAbs_REVERSED;
531           TopAbs_Orientation OO2 = TopAbs_REVERSED;
532           if (WithOri)
533             {
534               BRepAdaptor_Curve2d PCE1( E1, F );
535               BRepAdaptor_Curve2d PCE2( E2, F );
536               gp_Pnt2d P2d1, P2d2;
537               gp_Vec2d V1, V2, V1or, V2or;
538               PCE1.D1( aT1, P2d1, V1 );
539               PCE2.D1( aT2, P2d2, V2 );
540               V1or = V1; V2or = V2;
541               if (E1.Orientation() == TopAbs_REVERSED) V1or.Reverse();
542               if (E2.Orientation() == TopAbs_REVERSED) V2or.Reverse();
543               Standard_Real CrossProd = V2or ^ V1;
544 #ifdef OCCT_DEBUG
545               if (Abs(CrossProd) <= gp::Resolution())
546                 std::cout<<std::endl<<"CrossProd = "<<CrossProd<<std::endl;
547 #endif
548               if (CrossProd > 0.)
549                 OO1 = TopAbs_FORWARD;
550               CrossProd = V1or ^ V2;
551               if (CrossProd > 0.)
552                 OO2 = TopAbs_FORWARD;
553             }
554           LV1.Append( aNewVertex.Oriented(OO1) );
555           LV2.Append( aNewVertex.Oriented(OO2) );
556         }
557     }
558 
559   //----------------------------------
560   // Test at end.
561   //---------------------------------
562   Standard_Real U1,U2;
563   Standard_Real TolConf = Tol;
564   TopoDS_Vertex V1[2],V2[2];
565   TopExp::Vertices(E1,V1[0],V1[1]);
566   TopExp::Vertices(E2,V2[0],V2[1]);
567 
568   Standard_Integer j;
569   for (j = 0; j < 2; j++) {
570     if (V1[j].IsNull()) continue;
571     for (Standard_Integer k = 0; k < 2; k++) {
572       if (V2[k].IsNull()) continue;
573       if (V1[j].IsSame(V2[k])) {
574         if (AsDes->HasAscendant(V1[j])) {
575           continue;
576         }
577       }
578       //
579       gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);
580       gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);
581       Standard_Real Dist = P1.Distance(P2);
582       if (Dist < TolConf) {
583         Standard_Real aTol =
584           Max(BRep_Tool::Tolerance(V1[j]), BRep_Tool::Tolerance(V2[k]));
585         TopoDS_Vertex V = BRepLib_MakeVertex(P1);
586         U1 = (j == 0) ? f[1] : l[1];
587         U2 = (k == 0) ? f[2] : l[2];
588         //
589         TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
590         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,aTol);
591         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,aTol);
592         //
593         LV1.Prepend(V.Oriented(V1[j].Orientation()));
594         LV2.Prepend(V.Oriented(V2[k].Orientation()));
595       }
596     }
597   }
598 
599   Standard_Boolean AffichPurge = Standard_False;
600 
601   if ( !LV1.IsEmpty()) {
602     //----------------------------------
603     // Remove all vertices.
604     // There can be doubles
605     //----------------------------------
606     TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;
607     gp_Pnt P1,P2;
608     Standard_Boolean Purge = Standard_True;
609 
610     while (Purge) {
611       i = 1;
612       Purge = Standard_False;
613       for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2);
614            it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
615         j = 1;
616         it2LV1.Initialize(LV1);
617         while (j < i) {
618           P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
619           P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2LV1.Value()));
620 //  Modified by skv - Thu Jan 22 18:19:04 2004 OCC4455 Begin
621 //           if (P1.IsEqual(P2,10*Tol)) {
622           Standard_Real aTol;
623 
624           aTol = Max(BRep_Tool::Tolerance(TopoDS::Vertex(it1LV1.Value())),
625                      BRep_Tool::Tolerance(TopoDS::Vertex(it2LV1.Value())));
626           if (P1.IsEqual(P2,aTol)) {
627 //  Modified by skv - Thu Jan 22 18:19:05 2004 OCC4455 End
628             LV1.Remove(it1LV1);
629             LV2.Remove(it1LV2);
630             if (AffichPurge) std::cout <<"Doubles removed in EdgeInter."<<std::endl;
631             Purge = Standard_True;
632             break;
633           }
634           j++;
635           it2LV1.Next();
636         }
637         if (Purge) break;
638         i++;
639       }
640     }
641     //---------------------------------
642     // Vertex storage in DS.
643     //---------------------------------
644     Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
645     TolStore = Max (TolStore, Tol);
646     Store (E1,E2,LV1,LV2,TolStore,AsDes, aDMVV);
647   }
648 }
649 //=======================================================================
650 //function : EdgeInter
651 //purpose  :
652 //=======================================================================
653 
RefEdgeInter(const TopoDS_Face & F,const BRepAdaptor_Surface & BAsurf,const TopoDS_Edge & E1,const TopoDS_Edge & E2,const TopAbs_Orientation theOr1,const TopAbs_Orientation theOr2,const Handle (BRepAlgo_AsDes)& AsDes,Standard_Real Tol,Standard_Boolean WithOri,const TopoDS_Vertex & theVref,BRepAlgo_Image & theImageVV,TopTools_IndexedDataMapOfShapeListOfShape & aDMVV,Standard_Boolean & theCoincide)654 static void RefEdgeInter(const TopoDS_Face&              F,
655                          const BRepAdaptor_Surface&      BAsurf,
656                          const TopoDS_Edge&              E1,
657                          const TopoDS_Edge&              E2,
658                          const TopAbs_Orientation        theOr1,
659                          const TopAbs_Orientation        theOr2,
660                          const Handle(BRepAlgo_AsDes)&   AsDes,
661                          Standard_Real                   Tol,
662                          Standard_Boolean                WithOri,
663                          const TopoDS_Vertex&            theVref,
664                          BRepAlgo_Image&                 theImageVV,
665                          TopTools_IndexedDataMapOfShapeListOfShape& aDMVV,
666                          Standard_Boolean&               theCoincide)
667 {
668 #ifdef DRAW
669   if (Inter2dAffichInt2d) {
670     char name[256];
671     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
672     DBRep::Set(name,E1);
673     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
674     DBRep::Set(name,E2);
675   }
676 #endif
677   //
678   theCoincide = Standard_False;
679   //
680   if (E1.IsSame(E2))
681     return;
682 
683   Standard_Real f[3],l[3];
684   Standard_Real TolDub = 1.e-7, TolLL = 0.0;
685   Standard_Integer i;
686 
687   //BRep_Tool::Range(E1, f[1], l[1]);
688   //BRep_Tool::Range(E2, f[2], l[2]);
689 
690   BRepAdaptor_Curve CE1(E1,F);
691   BRepAdaptor_Curve CE2(E2,F);
692 
693   TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;
694   TopTools_ListOfShape        LV1;
695   TopTools_ListOfShape        LV2;
696   BRep_Builder                B;
697 
698   BRepLib::BuildCurve3d(E1);
699   BRepLib::BuildCurve3d(E2);
700 
701   TColgp_SequenceOfPnt   ResPoints;
702   TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2;
703   gp_Pnt DegPoint;
704   Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2);
705 
706   if (WithDegen)
707   {
708     Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2;
709     TopoDS_Iterator iter( EI[ideg] );
710     if (iter.More())
711     {
712       const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value());
713       DegPoint = BRep_Tool::Pnt(vdeg);
714     }
715     else
716     {
717       BRepAdaptor_Curve CEdeg( EI[ideg], F );
718       DegPoint = CEdeg.Value( CEdeg.FirstParameter() );
719     }
720   }
721   //
722   Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]);
723   Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]);
724   Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
725   Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
726   if ((GAC1.GetType() == GeomAbs_Line) &&
727       (GAC2.GetType() == GeomAbs_Line))
728   {
729     // Just quickly check if lines coincide
730     Standard_Real anAngle = Abs(GAC1.Line().Direction().Angle(GAC2.Line().Direction()));
731     if (anAngle <= 1.e-8 || M_PI - anAngle <= 1.e-8)
732     {
733       theCoincide = Standard_True;
734       return;
735     }
736     else
737     {
738       // Take into account the intersection range of line-line intersection
739       // (the smaller angle between curves, the bigger range)
740       TolLL = IntTools_Tools::ComputeIntRange(TolDub, TolDub, anAngle);
741       TolLL = Min (TolLL, 1.e-5);
742     }
743   }
744 
745   Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
746   //
747   if (!Inter2d.IsDone() || !Inter2d.NbPoints()) {
748     theCoincide = (Inter2d.NbSegments() &&
749                    (GAC1.GetType() == GeomAbs_Line) &&
750                    (GAC2.GetType() == GeomAbs_Line));
751     return;
752   }
753   //
754   for (i = 1; i <= Inter2d.NbPoints(); i++)
755   {
756     gp_Pnt P3d;
757     if (WithDegen)
758       P3d = DegPoint;
759     else
760     {
761       gp_Pnt2d P2d = Inter2d.Point(i).Value();
762       P3d = BAsurf.Value( P2d.X(), P2d.Y() );
763     }
764     ResPoints.Append( P3d );
765     ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() );
766     ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() );
767   }
768 
769   for (i = 1; i <= ResPoints.Length(); i++)
770   {
771     Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter();
772     Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter();
773     if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2))
774     {
775 #ifdef OCCT_DEBUG
776       std::cout << "Inter2d : Solution rejected due to infinite parameter"<<std::endl;
777 #endif
778       continue;
779     }
780 
781     gp_Pnt P = ResPoints(i); //ponc1.Value();
782     TopoDS_Vertex aNewVertex = BRepLib_MakeVertex(P);
783     aNewVertex.Orientation(TopAbs_INTERNAL);
784     B.UpdateVertex( aNewVertex, aT1, E1, Tol );
785     B.UpdateVertex( aNewVertex, aT2, E2, Tol );
786     gp_Pnt P1 = CE1.Value(aT1);
787     gp_Pnt P2 = CE2.Value(aT2);
788     Standard_Real dist1, dist2, dist3;
789     dist1 = P1.Distance(P);
790     dist2 = P2.Distance(P);
791     dist3 = P1.Distance(P2);
792     dist1 = Max( dist1, dist2 );
793     dist1 = Max( dist1, dist3 );
794     B.UpdateVertex( aNewVertex, dist1 );
795 
796 #ifdef OCCT_DEBUG
797     if (aT1 < f[1]-Tol  || aT1 > l[1]+Tol)
798     {
799       std::cout << "out of limit"<<std::endl;
800       std::cout<<"aT1 = "<<aT1<<", f[1] = "<<f[1]<<", l[1] = "<<l[1]<<std::endl;
801     }
802     if (aT2 < f[2]-Tol  || aT2 > l[2]+Tol)
803     {
804       std::cout << "out of limit"<<std::endl;
805       std::cout<<"aT2 = "<<aT2<<", f[2] = "<<f[2]<<", l[2] = "<<l[2]<<std::endl;
806     }
807     Standard_Real MilTol2 = 1000*Tol*Tol;
808     if (P1.SquareDistance(P) >  MilTol2 || P2.SquareDistance(P) > MilTol2 || P1.Distance(P2) > 2.*Tol)
809     {
810       std::cout << "Inter2d : Solution rejected"<<std::endl;
811       std::cout<<"P  = "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<std::endl;
812       std::cout<<"P1 = "<<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<std::endl;
813       std::cout<<"P2 = "<<P2.X()<<" "<<P2.Y()<<" "<<P2.Z()<<std::endl;
814       std::cout<<"MaxDist = "<<dist1<<std::endl;
815     }
816 #endif
817     //define the orientation of a new vertex
818     TopAbs_Orientation OO1 = TopAbs_REVERSED;
819     TopAbs_Orientation OO2 = TopAbs_REVERSED;
820     if (WithOri)
821     {
822       BRepAdaptor_Curve2d PCE1( E1, F );
823       BRepAdaptor_Curve2d PCE2( E2, F );
824       gp_Pnt2d P2d1, P2d2;
825       gp_Vec2d V1, V2, V1or, V2or;
826       PCE1.D1( aT1, P2d1, V1 );
827       PCE2.D1( aT2, P2d2, V2 );
828       V1or = V1; V2or = V2;
829       if (E1.Orientation() == TopAbs_REVERSED) V1or.Reverse();
830       if (E2.Orientation() == TopAbs_REVERSED) V2or.Reverse();
831       Standard_Real CrossProd = V2or ^ V1;
832 #ifdef OCCT_DEBUG
833       if (Abs(CrossProd) <= gp::Resolution())
834         std::cout<<std::endl<<"CrossProd = "<<CrossProd<<std::endl;
835 #endif
836       if (CrossProd > 0.)
837         OO1 = TopAbs_FORWARD;
838       CrossProd = V1or ^ V2;
839       if (CrossProd > 0.)
840         OO2 = TopAbs_FORWARD;
841     }
842 
843     if (theOr1 != TopAbs_EXTERNAL)
844       OO1 = theOr1;
845     if (theOr2 != TopAbs_EXTERNAL)
846       OO2 = theOr2;
847 
848     LV1.Append( aNewVertex.Oriented(OO1) );
849     LV2.Append( aNewVertex.Oriented(OO2) );
850   }
851 
852   //----------------------------------
853   // Test at end.
854   //---------------------------------
855   Standard_Real U1,U2;
856   Standard_Real TolConf = Tol;
857   TopoDS_Vertex V1[2],V2[2];
858   TopExp::Vertices(E1,V1[0],V1[1]);
859   TopExp::Vertices(E2,V2[0],V2[1]);
860 
861   Standard_Integer j;
862   for (j = 0; j < 2; j++) {
863     if (V1[j].IsNull()) continue;
864     for (Standard_Integer k = 0; k < 2; k++) {
865       if (V2[k].IsNull()) continue;
866       if (V1[j].IsSame(V2[k])) {
867         if (AsDes->HasAscendant(V1[j])) {
868           continue;
869         }
870       }
871       //
872       gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);
873       gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);
874       Standard_Real Dist = P1.Distance(P2);
875       if (Dist < TolConf) {
876         TopoDS_Vertex V = BRepLib_MakeVertex(P1);
877         U1 = (j == 0) ? f[1] : l[1];
878         U2 = (k == 0) ? f[2] : l[2];
879         TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
880         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
881         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
882         LV1.Prepend(V.Oriented(V1[j].Orientation()));
883         LV2.Prepend(V.Oriented(V2[k].Orientation()));
884       }
885     }
886   }
887 
888   Standard_Boolean AffichPurge = Standard_False;
889 
890   if ( !LV1.IsEmpty()) {
891     //----------------------------------
892     // Remove all vertices.
893     // there can be doubles
894     //----------------------------------
895     TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;
896     gp_Pnt P1,P2;
897     Standard_Boolean Purge = Standard_True;
898 
899     while (Purge) {
900       i = 1;
901       Purge = Standard_False;
902       for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2);
903            it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
904         j = 1;
905         it2LV1.Initialize(LV1);
906         while (j < i) {
907           P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
908           P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2LV1.Value()));
909           if (P1.IsEqual(P2, Tol)) {
910             LV1.Remove(it1LV1);
911             LV2.Remove(it1LV2);
912             if (AffichPurge) std::cout <<"Doubles removed in EdgeInter."<<std::endl;
913             Purge = Standard_True;
914             break;
915           }
916           j++;
917           it2LV1.Next();
918         }
919         if (Purge) break;
920         i++;
921       }
922     }
923     //---------------------------------
924     // Vertex storage in SD.
925     //---------------------------------
926 ////-----------------------------------------------------
927     if(LV1.Extent() > 1) {
928       //std::cout << "IFV - RefEdgeInter: remove vertex" << std::endl;
929       gp_Pnt Pref = BRep_Tool::Pnt(theVref);
930       Standard_Real dmin = RealLast();
931       TopoDS_Vertex Vmin;
932       for (it1LV1.Initialize(LV1); it1LV1.More(); it1LV1.Next()) {
933         gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
934         Standard_Real d = P.SquareDistance(Pref);
935         if(d < dmin) {
936           dmin = d;
937           Vmin = TopoDS::Vertex(it1LV1.Value());
938         }
939       }
940       for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2);
941            it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
942         if(!Vmin.IsSame(it1LV1.Value())) {
943           LV1.Remove(it1LV1);
944           LV2.Remove(it1LV2);
945           if(!it1LV1.More()) break;
946         }
947       }
948     }
949 
950     TopTools_ListIteratorOfListOfShape itl (LV1);
951     for (; itl.More(); itl.Next())
952     {
953       TopoDS_Shape aNewVertex = itl.Value();
954       aNewVertex.Orientation(TopAbs_FORWARD);
955       if (theImageVV.HasImage (theVref))
956         theImageVV.Add (theVref.Oriented(TopAbs_FORWARD), aNewVertex);
957       else
958         theImageVV.Bind (theVref.Oriented(TopAbs_FORWARD), aNewVertex);
959     }
960 
961 ////-----------------------------------------------------
962     Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
963     TolStore = Max (TolStore, Tol);
964     // Compare to Line-Line tolerance
965     TolStore = Max (TolStore, TolLL);
966     Store (E1,E2,LV1,LV2,TolStore,AsDes, aDMVV);
967   }
968 }
969 
970 
971 //======================================================================
972 //function : EvaluateMaxSegment
973 //purpose  : return MaxSegment to pass in approximation
974 //======================================================================
975 
evaluateMaxSegment(const Adaptor3d_CurveOnSurface & aCurveOnSurface)976 static Standard_Integer evaluateMaxSegment(const Adaptor3d_CurveOnSurface& aCurveOnSurface)
977 {
978   Handle(Adaptor3d_Surface) aSurf   = aCurveOnSurface.GetSurface();
979   Handle(Adaptor2d_Curve2d) aCurv2d = aCurveOnSurface.GetCurve();
980 
981   Standard_Real aNbSKnots = 0, aNbC2dKnots = 0;
982 
983   if (aSurf->GetType() == GeomAbs_BSplineSurface) {
984     Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline();
985     aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots());
986   }
987   if (aCurv2d->GetType() == GeomAbs_BSplineCurve) {
988     aNbC2dKnots = aCurv2d->NbKnots();
989   }
990   Standard_Integer aReturn = (Standard_Integer) (  30 + Max(aNbSKnots, aNbC2dKnots) ) ;
991   return aReturn;
992 }
993 
994 
995 //=======================================================================
996 //function : ExtendPCurve
997 //purpose  :
998 //=======================================================================
999 
ExtendPCurve(const Handle (Geom2d_Curve)& aPCurve,const Standard_Real anEf,const Standard_Real anEl,const Standard_Real a2Offset,Handle (Geom2d_Curve)& NewPCurve)1000 static Standard_Boolean ExtendPCurve(const Handle(Geom2d_Curve)& aPCurve,
1001                                      const Standard_Real anEf,
1002                                      const Standard_Real anEl,
1003                                      const Standard_Real a2Offset,
1004                                      Handle(Geom2d_Curve)& NewPCurve)
1005 {
1006   NewPCurve = aPCurve;
1007   if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1008     NewPCurve = Handle(Geom2d_TrimmedCurve)::DownCast (NewPCurve)->BasisCurve();
1009 
1010   Standard_Real FirstPar = NewPCurve->FirstParameter();
1011   Standard_Real LastPar  = NewPCurve->LastParameter();
1012 
1013   if (NewPCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) &&
1014       (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
1015     {
1016       if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BezierCurve)))
1017         {
1018           Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast (NewPCurve);
1019           if (aBezier->NbPoles() == 2)
1020             {
1021               TColgp_Array1OfPnt2d thePoles(1,2);
1022               aBezier->Poles(thePoles);
1023               gp_Vec2d aVec(thePoles(1), thePoles(2));
1024               NewPCurve = new Geom2d_Line(thePoles(1), aVec);
1025               return Standard_True;
1026             }
1027         }
1028       else if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BSplineCurve)))
1029         {
1030           Handle(Geom2d_BSplineCurve) aBSpline = Handle(Geom2d_BSplineCurve)::DownCast (NewPCurve);
1031           if (aBSpline->NbKnots() == 2 && aBSpline->NbPoles() == 2)
1032             {
1033               TColgp_Array1OfPnt2d thePoles(1,2);
1034               aBSpline->Poles(thePoles);
1035               gp_Vec2d aVec(thePoles(1), thePoles(2));
1036               NewPCurve = new Geom2d_Line(thePoles(1), aVec);
1037               return Standard_True;
1038             }
1039         }
1040     }
1041 
1042   FirstPar = aPCurve->FirstParameter();
1043   LastPar  = aPCurve->LastParameter();
1044   Handle(Geom2d_TrimmedCurve) aTrCurve =
1045     new Geom2d_TrimmedCurve(aPCurve, FirstPar, LastPar);
1046 
1047   // The curve is not prolonged on begin or end.
1048   // Trying to prolong it adding a segment to its bound.
1049   gp_Pnt2d                              aPBnd;
1050   gp_Vec2d                              aVBnd;
1051   gp_Pnt2d                              aPBeg;
1052   gp_Dir2d                              aDBnd;
1053   Handle(Geom2d_Line)                   aLin;
1054   Handle(Geom2d_TrimmedCurve)           aSegment;
1055   Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1);
1056   Standard_Real                         aTol = Precision::Confusion();
1057   Standard_Real                         aDelta = Max(a2Offset, 1.);
1058 
1059   if (FirstPar > anEf - a2Offset) {
1060     aPCurve->D1(FirstPar, aPBnd, aVBnd);
1061     aDBnd.SetXY(aVBnd.XY());
1062     aPBeg    = aPBnd.Translated(gp_Vec2d(-aDelta*aDBnd.XY()));
1063     aLin     = new Geom2d_Line(aPBeg, aDBnd);
1064     aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta);
1065 
1066     if (!aCompCurve.Add(aSegment, aTol))
1067       return Standard_False;
1068   }
1069 
1070   if (LastPar < anEl + a2Offset) {
1071     aPCurve->D1(LastPar, aPBeg, aVBnd);
1072     aDBnd.SetXY(aVBnd.XY());
1073     aLin     = new Geom2d_Line(aPBeg, aDBnd);
1074     aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta);
1075 
1076     if (!aCompCurve.Add(aSegment, aTol))
1077       return Standard_False;
1078   }
1079 
1080   NewPCurve  = aCompCurve.BSplineCurve();
1081   return Standard_True;
1082 }
1083 
1084 //=======================================================================
1085 //function : ExtentEdge
1086 //purpose  :
1087 //=======================================================================
1088 
1089 //  Modified by skv - Fri Dec 26 17:00:55 2003 OCC4455 Begin
1090 //static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE)
ExtentEdge(const TopoDS_Edge & E,TopoDS_Edge & NE,const Standard_Real theOffset)1091 Standard_Boolean BRepOffset_Inter2d::ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset)
1092 {
1093   //BRepLib::BuildCurve3d(E);
1094 
1095   TopoDS_Shape  aLocalShape = E.EmptyCopied();
1096   Standard_Real anEf;
1097   Standard_Real anEl;
1098   Standard_Real a2Offset = 2.*Abs(theOffset);
1099   BRep_Builder BB;
1100   Standard_Integer i, j;
1101 
1102   BRep_Tool::Range(E, anEf, anEl);
1103   NE = TopoDS::Edge(aLocalShape);
1104 //  NE = TopoDS::Edge(E.EmptyCopied());
1105   // Enough for analytic edges, for general case reconstruct the
1106   // geometry of the edge recalculating the intersection of surfaces.
1107 
1108   //BRepLib::BuildCurve3d(E);
1109 
1110   Standard_Integer NbPCurves = 0;
1111   Standard_Real FirstParOnPC = RealFirst(), LastParOnPC = RealLast();
1112   Handle(Geom2d_Curve) MinPC;
1113   Handle(Geom_Surface) MinSurf;
1114   TopLoc_Location      MinLoc;
1115 
1116   BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves() );
1117   for (; itr.More(); itr.Next())
1118     {
1119       Handle( BRep_CurveRepresentation ) CurveRep = itr.Value();
1120       Standard_Real FirstPar, LastPar;
1121       if (CurveRep->IsCurveOnSurface())
1122         {
1123           NbPCurves++;
1124           Handle(Geom2d_Curve) theCurve = CurveRep->PCurve();
1125           FirstPar = theCurve->FirstParameter();
1126           LastPar  = theCurve->LastParameter();
1127 
1128           if (theCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) &&
1129               (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
1130             {
1131               Handle(Geom2d_Curve) NewPCurve;
1132               if (ExtendPCurve(theCurve, anEf, anEl, a2Offset, NewPCurve))
1133                 {
1134                   CurveRep->PCurve(NewPCurve);
1135                   FirstPar = NewPCurve->FirstParameter();
1136                   LastPar  = NewPCurve->LastParameter();
1137                   if (CurveRep->IsCurveOnClosedSurface())
1138                     {
1139                       Handle(Geom2d_Curve) PCurve2 = CurveRep->PCurve2();
1140                       if (ExtendPCurve(PCurve2, anEf, anEl, a2Offset, NewPCurve))
1141                         CurveRep->PCurve2(NewPCurve);
1142                     }
1143                 }
1144             }
1145           else if (theCurve->IsPeriodic())
1146             {
1147               Standard_Real delta = (theCurve->Period() - (anEl - anEf))*0.5;
1148               delta *= 0.95;
1149               FirstPar = anEf - delta;
1150               LastPar  = anEl + delta;
1151             }
1152           else if (theCurve->IsClosed())
1153             LastPar -= 0.05*(LastPar - FirstPar);
1154 
1155           //check FirstPar and LastPar: the pcurve should be in its surface
1156           theCurve = CurveRep->PCurve();
1157           Handle(Geom_Surface) theSurf = CurveRep->Surface();
1158           Standard_Real Umin, Umax, Vmin, Vmax;
1159           theSurf->Bounds(Umin, Umax, Vmin, Vmax);
1160           TColGeom2d_SequenceOfCurve BoundLines;
1161           if (!Precision::IsInfinite(Vmin))
1162             {
1163               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmin ),
1164                                                           gp_Dir2d( 1., 0. ));
1165               BoundLines.Append(aLine);
1166             }
1167           if (!Precision::IsInfinite(Umin))
1168             {
1169               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umin, 0. ),
1170                                                           gp_Dir2d( 0., 1. ));
1171               BoundLines.Append(aLine);
1172             }
1173           if (!Precision::IsInfinite(Vmax))
1174             {
1175               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmax ),
1176                                                           gp_Dir2d( 1., 0. ));
1177               BoundLines.Append(aLine);
1178             }
1179           if (!Precision::IsInfinite(Umax))
1180             {
1181               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umax, 0. ),
1182                                                           gp_Dir2d( 0., 1. ));
1183               BoundLines.Append(aLine);
1184             }
1185 
1186           TColStd_SequenceOfReal params;
1187           Geom2dInt_GInter IntCC;
1188           Geom2dAdaptor_Curve GAcurve(theCurve);
1189           for (i = 1; i <= BoundLines.Length(); i++)
1190             {
1191               Geom2dAdaptor_Curve GAline( BoundLines(i) );
1192               IntCC.Perform( GAcurve, GAline, Precision::PConfusion(), Precision::PConfusion());
1193               if (IntCC.IsDone())
1194                 {
1195                   for (j = 1; j <= IntCC.NbPoints(); j++)
1196                     {
1197                       const IntRes2d_IntersectionPoint& ip = IntCC.Point(j);
1198                       gp_Pnt2d aPoint = ip.Value();
1199                       if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
1200                           aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
1201                         params.Append( ip.ParamOnFirst() );
1202                     }
1203                   for (j = 1; j <= IntCC.NbSegments(); j++)
1204                     {
1205                       const IntRes2d_IntersectionSegment& is = IntCC.Segment(j);
1206                       if (is.HasFirstPoint())
1207                         {
1208                           const IntRes2d_IntersectionPoint& ip = is.FirstPoint();
1209                           gp_Pnt2d aPoint = ip.Value();
1210                           if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
1211                               aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
1212                             params.Append( ip.ParamOnFirst() );
1213                         }
1214                       if (is.HasLastPoint())
1215                         {
1216                           const IntRes2d_IntersectionPoint& ip = is.LastPoint();
1217                           gp_Pnt2d aPoint = ip.Value();
1218                           if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
1219                               aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
1220                             params.Append( ip.ParamOnFirst() );
1221                         }
1222                     }
1223                 }
1224             }
1225           if (!params.IsEmpty())
1226             {
1227               if (params.Length() == 1)
1228                 {
1229                   gp_Pnt2d PntFirst = theCurve->Value(FirstPar);
1230                   if (PntFirst.X() >= Umin && PntFirst.X() <= Umax &&
1231                       PntFirst.Y() >= Vmin && PntFirst.Y() <= Vmax)
1232                     {
1233                       if (LastPar > params(1))
1234                         LastPar = params(1);
1235                     }
1236                   else if (FirstPar < params(1))
1237                     FirstPar = params(1);
1238                 }
1239               else
1240                 {
1241                   Standard_Real fpar = RealLast(), lpar = RealFirst();
1242                   for (i = 1; i <= params.Length(); i++)
1243                     {
1244                       if (params(i) < fpar)
1245                         fpar = params(i);
1246                       if (params(i) > lpar)
1247                         lpar = params(i);
1248                     }
1249                   if (FirstPar < fpar)
1250                     FirstPar = fpar;
1251                   if (LastPar > lpar)
1252                     LastPar = lpar;
1253                 }
1254             }
1255           //// end of check ////
1256           (Handle(BRep_GCurve)::DownCast(CurveRep))->SetRange( FirstPar, LastPar );
1257           //gp_Pnt2d Pfirst = theCurve->Value(FirstPar);
1258           //gp_Pnt2d Plast  = theCurve->Value(LastPar);
1259           //(Handle(BRep_CurveOnSurface)::DownCast(CurveRep))->SetUVPoints( Pfirst, Plast );
1260 
1261           //update FirstParOnPC and LastParOnPC
1262           if (FirstPar > FirstParOnPC)
1263             {
1264               FirstParOnPC = FirstPar;
1265               MinPC   = theCurve;
1266               MinSurf = theSurf;
1267               MinLoc  = CurveRep->Location();
1268             }
1269           if (LastPar  < LastParOnPC)
1270             {
1271               LastParOnPC  = LastPar;
1272               MinPC   = theCurve;
1273               MinSurf = theSurf;
1274               MinLoc  = CurveRep->Location();
1275             }
1276         }
1277     }
1278 
1279   Standard_Real f, l;
1280   Handle(Geom_Curve) C3d = BRep_Tool::Curve( NE, f, l );
1281   if (NbPCurves)
1282     {
1283       MinLoc = E.Location() * MinLoc;
1284       if (!C3d.IsNull())
1285         {
1286           if (MinPC->IsClosed())
1287             {
1288               f = FirstParOnPC;
1289               l = LastParOnPC;
1290             }
1291           else if (C3d->IsPeriodic())
1292             {
1293               Standard_Real delta = (C3d->Period() - (l - f))*0.5;
1294               delta *= 0.95;
1295               f -= delta;
1296               l += delta;
1297             }
1298           else if (C3d->IsClosed())
1299             l -= 0.05*(l - f);
1300           else
1301             {
1302               f = FirstParOnPC;
1303               l = LastParOnPC;
1304               GeomAPI_ProjectPointOnCurve Projector;
1305               if (!Precision::IsInfinite(FirstParOnPC))
1306                 {
1307                   gp_Pnt2d P2d1 = MinPC->Value(FirstParOnPC);
1308                   gp_Pnt P1 = MinSurf->Value( P2d1.X(), P2d1.Y() );
1309                   P1.Transform(MinLoc.Transformation());
1310                   Projector.Init( P1, C3d );
1311                   if (Projector.NbPoints() > 0)
1312                     f = Projector.LowerDistanceParameter();
1313 #ifdef OCCT_DEBUG
1314                   else
1315                     std::cout<<"ProjectPointOnCurve not done"<<std::endl;
1316 #endif
1317                 }
1318               if (!Precision::IsInfinite(LastParOnPC))
1319                 {
1320                   gp_Pnt2d P2d2 = MinPC->Value(LastParOnPC);
1321                   gp_Pnt P2 = MinSurf->Value( P2d2.X(), P2d2.Y() );
1322                   P2.Transform(MinLoc.Transformation());
1323                   Projector.Init( P2, C3d );
1324                   if (Projector.NbPoints() > 0)
1325                     l = Projector.LowerDistanceParameter();
1326 #ifdef OCCT_DEBUG
1327                   else
1328                     std::cout<<"ProjectPointOnCurve not done"<<std::endl;
1329 #endif
1330                 }
1331             }
1332           BB.Range( NE, f, l );
1333           if (!Precision::IsInfinite(f) && !Precision::IsInfinite(l))
1334             BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1335         }
1336       else if (!BRep_Tool::Degenerated(E)) //no 3d curve
1337         {
1338           MinSurf = Handle(Geom_Surface)::DownCast
1339             (MinSurf->Transformed(MinLoc.Transformation()));
1340           Standard_Real max_deviation = 0.;
1341           if (Precision::IsInfinite(FirstParOnPC) || Precision::IsInfinite(LastParOnPC))
1342             {
1343               if (MinPC->IsInstance(STANDARD_TYPE(Geom2d_Line)))
1344                 {
1345                   Standard_Boolean IsLine = Standard_False;
1346                   if (MinSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1347                     IsLine = Standard_True;
1348                   else if (MinSurf->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)) ||
1349                            MinSurf->IsInstance(STANDARD_TYPE(Geom_ConicalSurface)))
1350                     {
1351                       Handle(Geom2d_Line) theLine = Handle(Geom2d_Line)::DownCast (MinPC);
1352                       gp_Dir2d LineDir = theLine->Direction();
1353                       if (LineDir.IsParallel( gp::DY2d(), Precision::Angular() ))
1354                         IsLine = Standard_True;
1355                     }
1356                   if (IsLine)
1357                     {
1358                       gp_Pnt2d P2d1 = MinPC->Value(0.), P2d2 = MinPC->Value(1.);
1359                       gp_Pnt P1 = MinSurf->Value(P2d1.X(), P2d1.Y());
1360                       gp_Pnt P2 = MinSurf->Value(P2d2.X(), P2d2.Y());
1361                       gp_Vec aVec(P1, P2);
1362                       C3d = new Geom_Line( P1, aVec );
1363                     }
1364                 }
1365             }
1366           else
1367             {
1368               Geom2dAdaptor_Curve AC2d( MinPC, FirstParOnPC, LastParOnPC );
1369               GeomAdaptor_Surface GAsurf( MinSurf );
1370               Handle(Geom2dAdaptor_Curve) HC2d  = new Geom2dAdaptor_Curve( AC2d );
1371               Handle(GeomAdaptor_Surface) HSurf = new GeomAdaptor_Surface( GAsurf );
1372               Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
1373               Standard_Real /*max_deviation,*/ average_deviation;
1374               GeomAbs_Shape Continuity = GeomAbs_C1;
1375               Standard_Integer MaxDegree = 14;
1376               Standard_Integer MaxSegment = evaluateMaxSegment(ConS);
1377               GeomLib::BuildCurve3d(Precision::Confusion(),
1378                                     ConS, FirstParOnPC, LastParOnPC,
1379                                     C3d, max_deviation, average_deviation,
1380                                     Continuity, MaxDegree, MaxSegment);
1381             }
1382           BB.UpdateEdge( NE, C3d, max_deviation );
1383           //BB.Range( NE, FirstParOnPC, LastParOnPC );
1384           Standard_Boolean ProjectionSuccess = Standard_True;
1385           if (NbPCurves > 1)
1386             //BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1387             for (itr.Initialize((Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves());
1388                  itr.More();
1389                  itr.Next())
1390               {
1391                 Handle( BRep_CurveRepresentation ) CurveRep = itr.Value();
1392                 Standard_Real FirstPar, LastPar;
1393                 if (CurveRep->IsCurveOnSurface())
1394                   {
1395                     Handle(Geom2d_Curve) theCurve = CurveRep->PCurve();
1396                     Handle(Geom_Surface) theSurf  = CurveRep->Surface();
1397                     TopLoc_Location      theLoc   = CurveRep->Location();
1398                     if (theCurve == MinPC && theSurf == MinSurf && theLoc == MinLoc)
1399                       continue;
1400                     FirstPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First();
1401                     LastPar  = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last();
1402                     if (Abs(FirstPar - FirstParOnPC) > Precision::PConfusion() ||
1403                         Abs(LastPar  - LastParOnPC)  > Precision::PConfusion())
1404                       {
1405                         theLoc = E.Location() * theLoc;
1406                         theSurf = Handle(Geom_Surface)::DownCast
1407                           (theSurf->Transformed(theLoc.Transformation()));
1408 
1409                         if (theCurve->IsInstance(STANDARD_TYPE(Geom2d_Line)) &&
1410                             theSurf->IsKind(STANDARD_TYPE(Geom_BoundedSurface)))
1411                           {
1412                             gp_Dir2d theDir = Handle(Geom2d_Line)::DownCast (theCurve)->Direction();
1413                             if (theDir.IsParallel(gp::DX2d(), Precision::Angular()) ||
1414                                 theDir.IsParallel(gp::DY2d(), Precision::Angular()))
1415                               {
1416                                 Standard_Real U1, U2, V1, V2;
1417                                 theSurf->Bounds(U1, U2, V1, V2);
1418                                 gp_Pnt2d Origin = Handle(Geom2d_Line)::DownCast (theCurve)->Location();
1419                                 if (Abs(Origin.X()-U1) <= Precision::Confusion() ||
1420                                     Abs(Origin.X()-U2) <= Precision::Confusion() ||
1421                                     Abs(Origin.Y()-V1) <= Precision::Confusion() ||
1422                                     Abs(Origin.Y()-V2) <= Precision::Confusion())
1423                                   {
1424                                     BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1425                                     break;
1426                                   }
1427                               }
1428                           }
1429                         if (!C3d.IsNull() && FirstParOnPC < LastParOnPC)
1430                         {
1431                           Handle(Geom2d_Curve) ProjPCurve =
1432                             GeomProjLib::Curve2d(C3d, FirstParOnPC, LastParOnPC, theSurf);
1433                           if (ProjPCurve.IsNull())
1434                             ProjectionSuccess = Standard_False;
1435                           else
1436                             CurveRep->PCurve(ProjPCurve);
1437                         }
1438                         else
1439                         {
1440                           return Standard_False;
1441                         }
1442                       }
1443                   }
1444               }
1445           if (ProjectionSuccess)
1446             BB.Range( NE, FirstParOnPC, LastParOnPC );
1447           else
1448             {
1449               BB.Range( NE, FirstParOnPC, LastParOnPC, Standard_True );
1450               BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1451             }
1452         }
1453     }
1454   else //no pcurves
1455     {
1456       Standard_Real FirstPar = C3d->FirstParameter();
1457       Standard_Real LastPar  = C3d->LastParameter();
1458 
1459       if (C3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) &&
1460           (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
1461         {
1462           Handle(Geom_TrimmedCurve) aTrCurve =
1463             new Geom_TrimmedCurve(C3d, FirstPar, LastPar);
1464 
1465           // The curve is not prolonged on begin or end.
1466           // Trying to prolong it adding a segment to its bound.
1467           gp_Pnt                              aPBnd;
1468           gp_Vec                              aVBnd;
1469           gp_Pnt                              aPBeg;
1470           gp_Dir                              aDBnd;
1471           Handle(Geom_Line)                   aLin;
1472           Handle(Geom_TrimmedCurve)           aSegment;
1473           GeomConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1);
1474           Standard_Real                       aTol = Precision::Confusion();
1475           Standard_Real                       aDelta = Max(a2Offset, 1.);
1476 
1477           if (FirstPar > anEf - a2Offset) {
1478             C3d->D1(FirstPar, aPBnd, aVBnd);
1479             aDBnd.SetXYZ(aVBnd.XYZ());
1480             aPBeg    = aPBnd.Translated(gp_Vec(-aDelta*aDBnd.XYZ()));
1481             aLin     = new Geom_Line(aPBeg, aDBnd);
1482             aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta);
1483 
1484             if (!aCompCurve.Add(aSegment, aTol))
1485               return Standard_True;
1486           }
1487 
1488           if (LastPar < anEl + a2Offset) {
1489             C3d->D1(LastPar, aPBeg, aVBnd);
1490             aDBnd.SetXYZ(aVBnd.XYZ());
1491             aLin     = new Geom_Line(aPBeg, aDBnd);
1492             aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta);
1493 
1494             if (!aCompCurve.Add(aSegment, aTol))
1495               return Standard_True;
1496           }
1497 
1498           C3d = aCompCurve.BSplineCurve();
1499           FirstPar = C3d->FirstParameter();
1500           LastPar  = C3d->LastParameter();
1501           BB.UpdateEdge(NE, C3d, Precision::Confusion());
1502         }
1503       else if (C3d->IsPeriodic())
1504         {
1505           Standard_Real delta = (C3d->Period() - (anEl - anEf))*0.5;
1506           delta *= 0.95;
1507           FirstPar = anEf - delta;
1508           LastPar  = anEl + delta;
1509         }
1510       else if (C3d->IsClosed())
1511         LastPar -= 0.05*(LastPar - FirstPar);
1512 
1513       BB.Range( NE, FirstPar, LastPar );
1514     }
1515   return Standard_True;
1516 }
1517 //  Modified by skv - Fri Dec 26 17:00:57 2003 OCC4455 End
1518 
1519 
1520 //=======================================================================
1521 //function : UpdateVertex
1522 //purpose  :
1523 //=======================================================================
1524 
UpdateVertex(TopoDS_Vertex V,TopoDS_Edge & OE,TopoDS_Edge & NE,Standard_Real TolConf)1525 static Standard_Boolean  UpdateVertex(TopoDS_Vertex V,
1526                                       TopoDS_Edge&  OE,
1527                                       TopoDS_Edge&  NE,
1528                                       Standard_Real TolConf)
1529 {
1530   BRepAdaptor_Curve OC(OE);
1531   BRepAdaptor_Curve NC(NE);
1532   Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter();
1533   Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter();
1534   Standard_Real U = 0.;
1535   Standard_Real ParTol = Precision::PConfusion();
1536   gp_Pnt           P  = BRep_Tool::Pnt(V);
1537   Standard_Boolean OK = Standard_False;
1538 
1539   if (P.Distance(OC.Value(Of)) < TolConf) {
1540     if (Of >= Nf + ParTol && Of <= Nl + ParTol  && P.Distance(NC.Value(Of)) < TolConf) {
1541       OK = Standard_True;
1542       U    = Of;
1543     }
1544   }
1545   if (P.Distance(OC.Value(Ol)) < TolConf) {
1546     if (Ol >= Nf + ParTol && Ol <= Nl + ParTol  && P.Distance(NC.Value(Ol)) < TolConf) {
1547       OK = Standard_True;
1548       U    = Ol;
1549     }
1550   }
1551   if (OK) {
1552     BRep_Builder B;
1553     TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD);
1554     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
1555 //    TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD));
1556     aLocalShape = V.Oriented(TopAbs_INTERNAL);
1557     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
1558                    U,NE,BRep_Tool::Tolerance(NE));
1559 //    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
1560 //                   U,NE,BRep_Tool::Tolerance(NE));
1561   }
1562   return OK;
1563 }
1564 
1565 //=======================================================================
1566 //function : Compute
1567 //purpose  :
1568 //=======================================================================
1569 
Compute(const Handle (BRepAlgo_AsDes)& AsDes,const TopoDS_Face & F,const TopTools_IndexedMapOfShape & NewEdges,const Standard_Real Tol,const TopTools_DataMapOfShapeListOfShape & theEdgeIntEdges,TopTools_IndexedDataMapOfShapeListOfShape & theDMVV,const Message_ProgressRange & theRange)1570 void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)&     AsDes,
1571                                   const TopoDS_Face&                F,
1572                                   const TopTools_IndexedMapOfShape& NewEdges,
1573                                   const Standard_Real               Tol,
1574                                   const TopTools_DataMapOfShapeListOfShape& theEdgeIntEdges,
1575                                   TopTools_IndexedDataMapOfShapeListOfShape& theDMVV,
1576                                   const Message_ProgressRange& theRange)
1577 {
1578 #ifdef DRAW
1579   NbF2d++;
1580   NbE2d = 0;
1581 #endif
1582 
1583   //Do not intersect the edges of face
1584   TopTools_MapOfShape EdgesOfFace;
1585   TopExp_Explorer Explo( F, TopAbs_EDGE );
1586   for (; Explo.More(); Explo.Next())
1587     EdgesOfFace.Add( Explo.Current() );
1588 
1589   //-----------------------------------------------------------
1590   // calculate intersections2d on faces touched by
1591   // intersection3d
1592   //---------------------------------------------------------
1593   TopTools_ListIteratorOfListOfShape it1LE ;
1594   TopTools_ListIteratorOfListOfShape it2LE ;
1595 
1596   //-----------------------------------------------
1597   // Intersection of edges 2*2.
1598   //-----------------------------------------------
1599   const TopTools_ListOfShape&        LE = AsDes->Descendant(F);
1600   TopoDS_Vertex                      V1,V2;
1601   Standard_Integer                   j, i = 1;
1602   BRepAdaptor_Surface BAsurf(F);
1603   //
1604   Message_ProgressScope aPS(theRange, "Intersecting edges on faces", LE.Size());
1605   for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next(), aPS.Next()) {
1606     if (!aPS.More())
1607     {
1608       return;
1609     }
1610     const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value());
1611     j = 1;
1612     it2LE.Initialize(LE);
1613 
1614     while (j < i && it2LE.More()) {
1615       const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value());
1616 
1617       Standard_Boolean ToIntersect = Standard_True;
1618       if (theEdgeIntEdges.IsBound(E1))
1619       {
1620         const TopTools_ListOfShape& aElist = theEdgeIntEdges(E1);
1621         TopTools_ListIteratorOfListOfShape itedges (aElist);
1622         for (; itedges.More(); itedges.Next())
1623           if (E2.IsSame (itedges.Value()))
1624             ToIntersect = Standard_False;
1625 
1626         if (ToIntersect)
1627         {
1628           for (itedges.Initialize(aElist); itedges.More(); itedges.Next())
1629           {
1630             const TopoDS_Shape& anEdge = itedges.Value();
1631             if (theEdgeIntEdges.IsBound(anEdge))
1632             {
1633               const TopTools_ListOfShape& aElist2 = theEdgeIntEdges(anEdge);
1634               TopTools_ListIteratorOfListOfShape itedges2 (aElist2);
1635               for (; itedges2.More(); itedges2.Next())
1636                 if (E2.IsSame (itedges2.Value()))
1637                   ToIntersect = Standard_False;
1638             }
1639           }
1640         }
1641       }
1642 
1643       //--------------------------------------------------------------
1644       // Intersections of New edges obtained by intersection
1645       // between them and with edges of restrictions
1646       //------------------------------------------------------
1647       if (ToIntersect &&
1648           (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) &&
1649           (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) {
1650 
1651         TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
1652         EdgeInter(TopoDS::Face(aLocalShape),BAsurf,E1,E2,AsDes,Tol,Standard_True, theDMVV);
1653 //          EdgeInter(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),E1,E2,AsDes,Tol,Standard_True);
1654       }
1655       it2LE.Next();
1656       j++;
1657     }
1658     i++;
1659   }
1660 }
1661 
1662 //=======================================================================
1663 //function : ConnexIntByInt
1664 //purpose  :
1665 //=======================================================================
ConnexIntByInt(const TopoDS_Face & FI,BRepOffset_Offset & OFI,TopTools_DataMapOfShapeShape & MES,const TopTools_DataMapOfShapeShape & Build,const Handle (BRepAlgo_AsDes)& theAsDes,const Handle (BRepAlgo_AsDes)& AsDes2d,const Standard_Real Offset,const Standard_Real Tol,const BRepOffset_Analyse & Analyse,TopTools_IndexedMapOfShape & FacesWithVerts,BRepAlgo_Image & theImageVV,TopTools_DataMapOfShapeListOfShape & theEdgeIntEdges,TopTools_IndexedDataMapOfShapeListOfShape & theDMVV,const Message_ProgressRange & theRange)1666 Standard_Boolean BRepOffset_Inter2d::ConnexIntByInt
1667  (const TopoDS_Face&            FI,
1668   BRepOffset_Offset&            OFI,
1669   TopTools_DataMapOfShapeShape& MES,
1670   const TopTools_DataMapOfShapeShape& Build,
1671   const Handle(BRepAlgo_AsDes)& theAsDes,
1672   const Handle(BRepAlgo_AsDes)& AsDes2d,
1673   const Standard_Real           Offset,
1674   const Standard_Real           Tol,
1675   const BRepOffset_Analyse&     Analyse,
1676   TopTools_IndexedMapOfShape&   FacesWithVerts,
1677   BRepAlgo_Image&               theImageVV,
1678   TopTools_DataMapOfShapeListOfShape& theEdgeIntEdges,
1679   TopTools_IndexedDataMapOfShapeListOfShape& theDMVV,
1680   const Message_ProgressRange& theRange)
1681 {
1682 
1683   TopTools_DataMapOfShapeListOfShape MVE;
1684   BRepOffset_Tool::MapVertexEdges(FI,MVE);
1685   Message_ProgressScope aPS(theRange, "Intersecting edges obtained as intersection of faces", 1, Standard_True);
1686   //---------------------
1687   // Extension of edges.
1688   //---------------------
1689   TopoDS_Edge  NE;
1690   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(MVE);
1691   for  ( ; it.More(); it.Next()) {
1692     if (!aPS.More())
1693     {
1694       return Standard_False;
1695     }
1696     const TopTools_ListOfShape&  L = it.Value();
1697     Standard_Boolean   YaBuild = 0;
1698     TopTools_ListIteratorOfListOfShape itL(L);
1699     for (; itL.More(); itL.Next()) {
1700       YaBuild = Build.IsBound(itL.Value());
1701       if (YaBuild) break;
1702     }
1703     if (YaBuild) {
1704       for (itL.Initialize(L); itL.More(); itL.Next()) {
1705         const TopoDS_Edge& EI = TopoDS::Edge(itL.Value());
1706         if (EI.Orientation() != TopAbs_FORWARD &&
1707             EI.Orientation() != TopAbs_REVERSED)
1708           continue;
1709         TopoDS_Shape aLocalShape = OFI.Generated(EI);
1710         const TopoDS_Edge& OE = TopoDS::Edge(aLocalShape);
1711         if (!MES.IsBound(OE) && !Build.IsBound(EI)) {
1712           if (!ExtentEdge(OE, NE, Offset))
1713           {
1714             return Standard_False;
1715           }
1716           MES.Bind  (OE,NE);
1717         }
1718       }
1719     }
1720   }
1721 
1722   TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
1723   if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));
1724   //
1725   BRepAdaptor_Surface BAsurf(FIO);
1726 
1727   TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
1728   for (; exp.More(); exp.Next(), aPS.Next()) {
1729     if (!aPS.More())
1730     {
1731       return Standard_False;
1732     }
1733     const TopoDS_Wire&     W = TopoDS::Wire(exp.Current());
1734     BRepTools_WireExplorer wexp;
1735     Standard_Boolean       end = Standard_False ;
1736     TopoDS_Edge            FirstE,CurE,NextE;
1737 
1738     TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD);
1739     TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
1740     wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
1741     if (!wexp.More())
1742       continue; // Protection from case when explorer does not contain edges.
1743     CurE = FirstE  = wexp.Current();
1744     TopTools_IndexedMapOfShape Edges;
1745 
1746     while (!end) {
1747       wexp.Next();
1748       if (wexp.More()) {
1749         NextE = wexp.Current();
1750       }
1751       else {
1752         NextE = FirstE; end = Standard_True;
1753       }
1754       if (CurE.IsSame(NextE)) continue;
1755 
1756       TopoDS_Vertex Vref = CommonVertex(CurE, NextE);
1757 
1758       CurE = Analyse.EdgeReplacement (FI, CurE);
1759       NextE = Analyse.EdgeReplacement (FI, NextE);
1760 
1761       TopoDS_Shape aLocalShape = OFI.Generated(CurE);
1762       TopoDS_Edge CEO = TopoDS::Edge(aLocalShape);
1763       aLocalShape = OFI.Generated(NextE);
1764       TopoDS_Edge NEO = TopoDS::Edge(aLocalShape);
1765       //------------------------------------------
1766       // Inter processing of images of CurE NextE.
1767       //------------------------------------------
1768       TopTools_ListOfShape LV1,LV2;
1769       Standard_Boolean     DoInter = 1;
1770       TopoDS_Shape         NE1,NE2;
1771       TopTools_SequenceOfShape NE1seq, NE2seq;
1772       TopAbs_Orientation   anOr1 = TopAbs_EXTERNAL, anOr2 = TopAbs_EXTERNAL;
1773 
1774       Standard_Integer aChoice = 0;
1775       if (Build.IsBound(CurE) && Build.IsBound(NextE)) {
1776         aChoice = 1;
1777         NE1 = Build(CurE );
1778         NE2 = Build(NextE);
1779         GetEdgesOrientedInFace (NE1, FIO, theAsDes, NE1seq);
1780         GetEdgesOrientedInFace (NE2, FIO, theAsDes, NE2seq);
1781         anOr1 = TopAbs_REVERSED;
1782         anOr2 = TopAbs_FORWARD;
1783       }
1784       else if (Build.IsBound(CurE) && MES.IsBound(NEO)) {
1785         aChoice = 2;
1786         NE1 = Build(CurE);
1787         NE2 = MES  (NEO);
1788         NE2.Orientation (NextE.Orientation());
1789         GetEdgesOrientedInFace (NE1, FIO, theAsDes, NE1seq);
1790         NE2seq.Append (NE2);
1791         anOr1 = TopAbs_REVERSED;
1792         anOr2 = TopAbs_FORWARD;
1793       }
1794       else if (Build.IsBound(NextE) && MES.IsBound(CEO)) {
1795         aChoice = 3;
1796         NE1 = Build(NextE);
1797         NE2 = MES(CEO);
1798         NE2.Orientation (CurE.Orientation());
1799         GetEdgesOrientedInFace (NE1, FIO, theAsDes, NE1seq);
1800         NE2seq.Append (NE2);
1801         anOr1 = TopAbs_FORWARD;
1802         anOr2 = TopAbs_REVERSED;
1803       }
1804       else {
1805         DoInter = 0;
1806       }
1807       if (DoInter) {
1808         //------------------------------------
1809         // NE1,NE2 can be a compound of Edges.
1810         //------------------------------------
1811         Standard_Boolean bCoincide;
1812         TopoDS_Edge aE1, aE2;
1813         if (aChoice == 1 || aChoice == 2)
1814         {
1815           aE1 = TopoDS::Edge (NE1seq.Last());
1816           aE2 = TopoDS::Edge (NE2seq.First());
1817         }
1818         else // aChoice == 3
1819         {
1820           aE1 = TopoDS::Edge (NE1seq.First());
1821           aE2 = TopoDS::Edge (NE2seq.Last());
1822         }
1823 
1824         if (aE1.Orientation() == TopAbs_REVERSED)
1825           anOr1 = TopAbs::Reverse(anOr1);
1826         if (aE2.Orientation() == TopAbs_REVERSED)
1827           anOr2 = TopAbs::Reverse(anOr2);
1828 
1829         RefEdgeInter(FIO, BAsurf, aE1, aE2, anOr1, anOr2, AsDes2d,
1830                      Tol, Standard_True, Vref, theImageVV, theDMVV, bCoincide);
1831 
1832         if (theEdgeIntEdges.IsBound(aE1))
1833           theEdgeIntEdges(aE1).Append(aE2);
1834         else
1835         {
1836           TopTools_ListOfShape aElist;
1837           aElist.Append(aE2);
1838           theEdgeIntEdges.Bind (aE1, aElist);
1839         }
1840         if (theEdgeIntEdges.IsBound(aE2))
1841           theEdgeIntEdges(aE2).Append(aE1);
1842         else
1843         {
1844           TopTools_ListOfShape aElist;
1845           aElist.Append(aE1);
1846           theEdgeIntEdges.Bind (aE2, aElist);
1847         }
1848 
1849         //
1850         // check if some of the offset edges have been
1851         // generated out of the common vertex
1852         if (Build.IsBound(Vref)) {
1853           FacesWithVerts.Add(FI);
1854         }
1855       }
1856       else {
1857         TopoDS_Vertex  V = CommonVertex(CEO,NEO);
1858         if (!V.IsNull())
1859         {
1860           if (MES.IsBound(CEO)) {
1861             UpdateVertex  (V,CEO,TopoDS::Edge(MES(CEO)),Tol);
1862             AsDes2d->Add     (MES(CEO),V);
1863           }
1864           if (MES.IsBound(NEO)) {
1865             UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol);
1866             AsDes2d->Add    (MES(NEO),V);
1867           }
1868         }
1869       }
1870       CurE = wexp.Current();
1871     }
1872   }
1873   return Standard_True;
1874 }
1875 
1876 //=======================================================================
1877 //function : ConnexIntByIntInVert
1878 //purpose  : Intersection of the edges generated out of vertices
1879 //=======================================================================
ConnexIntByIntInVert(const TopoDS_Face & FI,BRepOffset_Offset & OFI,TopTools_DataMapOfShapeShape & MES,const TopTools_DataMapOfShapeShape & Build,const Handle (BRepAlgo_AsDes)& AsDes,const Handle (BRepAlgo_AsDes)& AsDes2d,const Standard_Real Tol,const BRepOffset_Analyse & Analyse,TopTools_IndexedDataMapOfShapeListOfShape & theDMVV,const Message_ProgressRange & theRange)1880 void BRepOffset_Inter2d::ConnexIntByIntInVert
1881  (const TopoDS_Face&            FI,
1882   BRepOffset_Offset&            OFI,
1883   TopTools_DataMapOfShapeShape& MES,
1884   const TopTools_DataMapOfShapeShape& Build,
1885   const Handle(BRepAlgo_AsDes)& AsDes,
1886   const Handle(BRepAlgo_AsDes)& AsDes2d,
1887   const Standard_Real           Tol,
1888   const BRepOffset_Analyse&     Analyse,
1889   TopTools_IndexedDataMapOfShapeListOfShape& theDMVV,
1890   const Message_ProgressRange& theRange)
1891 {
1892   TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
1893   if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));
1894   //
1895   TopTools_MapOfShape aME;
1896   const TopTools_ListOfShape& aLE = AsDes->Descendant(FIO);
1897   TopTools_ListIteratorOfListOfShape aItLE(aLE);
1898   for (; aItLE.More(); aItLE.Next()) {
1899     const TopoDS_Shape& aE = aItLE.Value();
1900     aME.Add(aE);
1901   }
1902   //
1903   BRepAdaptor_Surface BAsurf(FIO);
1904   //
1905   Message_ProgressScope aPS(theRange, "Intersecting edges created from vertices", 1, Standard_True);
1906   TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
1907   for (; exp.More(); exp.Next(), aPS.Next()) {
1908     if (!aPS.More())
1909     {
1910       return;
1911     }
1912     const TopoDS_Wire&     W = TopoDS::Wire(exp.Current());
1913     //
1914     BRepTools_WireExplorer wexp;
1915     Standard_Boolean       end = Standard_False ;
1916     TopoDS_Edge            FirstE,CurE,NextE;
1917     //
1918     TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD);
1919     TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
1920     wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
1921     if (!wexp.More())
1922       continue; // Protection from case when explorer does not contain edges.
1923     //
1924     CurE = FirstE  = wexp.Current();
1925     while (!end) {
1926       wexp.Next();
1927       if (wexp.More()) {
1928         NextE = wexp.Current();
1929       }
1930       else {
1931         NextE = FirstE; end = Standard_True;
1932       }
1933       if (CurE.IsSame(NextE)) continue;
1934       //
1935       TopoDS_Vertex Vref = CommonVertex(CurE, NextE);
1936       if (!Build.IsBound(Vref)) {
1937         CurE = NextE;
1938         continue;
1939       }
1940 
1941       CurE = Analyse.EdgeReplacement (FI, CurE);
1942       NextE = Analyse.EdgeReplacement (FI, NextE);
1943 
1944       TopoDS_Shape aLocalShape = OFI.Generated(CurE);
1945       TopoDS_Edge CEO = TopoDS::Edge(aLocalShape);
1946       aLocalShape = OFI.Generated(NextE);
1947       TopoDS_Edge NEO = TopoDS::Edge(aLocalShape);
1948       //
1949       TopoDS_Shape         NE1,NE2;
1950       TopAbs_Orientation   anOr1 = TopAbs_EXTERNAL, anOr2 = TopAbs_EXTERNAL;
1951 
1952       if (Build.IsBound(CurE) && Build.IsBound(NextE)) {
1953         NE1 = Build(CurE );
1954         NE2 = Build(NextE);
1955       }
1956       else if (Build.IsBound(CurE) && MES.IsBound(NEO)) {
1957         NE1 = Build(CurE);
1958         NE2 = MES  (NEO);
1959       }
1960       else if (Build.IsBound(NextE) && MES.IsBound(CEO)) {
1961         NE1 = Build(NextE);
1962         NE2 = MES(CEO);
1963       }
1964       else {
1965         CurE = wexp.Current();
1966         continue;
1967       }
1968       //
1969       TopExp_Explorer Exp1, Exp2;
1970       Standard_Boolean bCoincide;
1971       // intersect edges generated from vertex with the edges of the face
1972       TopoDS_Shape NE3 = Build(Vref);
1973       //
1974       for (Exp2.Init(NE3, TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
1975         const TopoDS_Edge& aE3 = *(TopoDS_Edge*)&Exp2.Current();
1976         if (!aME.Contains(aE3)) {
1977           continue;
1978         }
1979         //
1980         // intersection with first edge
1981         for (Exp1.Init(NE1, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
1982           const TopoDS_Edge& aE1 = TopoDS::Edge(Exp1.Current());
1983           BRepAlgo_Image anEmptyImage;
1984           RefEdgeInter(FIO, BAsurf, aE1, aE3, anOr1, anOr2, AsDes2d,
1985                        Tol, Standard_True, Vref, anEmptyImage, theDMVV, bCoincide);
1986           if (bCoincide) {
1987             // in case of coincidence trim the edge E3 the same way as E1
1988             Store(aE3, AsDes2d->Descendant(aE1), Tol, Standard_True, AsDes2d, theDMVV);
1989           }
1990         }
1991         //
1992         // intersection with second edge
1993         for (Exp1.Init(NE2, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
1994           const TopoDS_Edge& aE2 = TopoDS::Edge(Exp1.Current());
1995           BRepAlgo_Image anEmptyImage;
1996           RefEdgeInter(FIO, BAsurf, aE2, aE3, anOr1, anOr2, AsDes2d,
1997                        Tol, Standard_True, Vref, anEmptyImage, theDMVV, bCoincide);
1998           if (bCoincide) {
1999             // in case of coincidence trim the edge E3 the same way as E2
2000             Store(aE3, AsDes2d->Descendant(aE2), Tol, Standard_True, AsDes2d, theDMVV);
2001           }
2002         }
2003         //
2004         // intersection of the edges generated from vertex
2005         // among themselves
2006         for (Exp1.Init(NE3, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
2007           if (aE3.IsSame(Exp1.Current())) {
2008             break;
2009           }
2010         }
2011         //
2012         for (Exp1.Next(); Exp1.More(); Exp1.Next()) {
2013           const TopoDS_Edge& aE3Next = TopoDS::Edge(Exp1.Current());
2014           if (aME.Contains(aE3Next)) {
2015             BRepAlgo_Image anEmptyImage;
2016             RefEdgeInter(FIO, BAsurf, aE3Next, aE3, anOr1, anOr2, AsDes2d,
2017                          Tol, Standard_True, Vref, anEmptyImage, theDMVV, bCoincide);
2018           }
2019         }
2020       }
2021       CurE = wexp.Current();
2022     }
2023   }
2024 }
2025 
2026 //=======================================================================
2027 //function : MakeChain
2028 //purpose  :
2029 //=======================================================================
MakeChain(const TopoDS_Shape & theV,const TopTools_IndexedDataMapOfShapeListOfShape & theDMVV,TopTools_MapOfShape & theMDone,TopTools_ListOfShape & theChain)2030 static void MakeChain(const TopoDS_Shape& theV,
2031                       const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV,
2032                       TopTools_MapOfShape& theMDone,
2033                       TopTools_ListOfShape& theChain)
2034 {
2035   if (theMDone.Add(theV)) {
2036     theChain.Append(theV);
2037     const TopTools_ListOfShape* pLV = theDMVV.Seek(theV);
2038     if (pLV) {
2039       TopTools_ListIteratorOfListOfShape aIt(*pLV);
2040       for (; aIt.More(); aIt.Next()) {
2041         MakeChain(aIt.Value(), theDMVV, theMDone, theChain);
2042       }
2043     }
2044   }
2045 }
2046 
2047 //=======================================================================
2048 //function : FuseVertices
2049 //purpose  :
2050 //=======================================================================
FuseVertices(const TopTools_IndexedDataMapOfShapeListOfShape & theDMVV,const Handle (BRepAlgo_AsDes)& theAsDes,BRepAlgo_Image & theImageVV)2051 Standard_Boolean BRepOffset_Inter2d::FuseVertices (const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV,
2052                                                    const Handle(BRepAlgo_AsDes)& theAsDes,
2053                                                    BRepAlgo_Image&               theImageVV)
2054 {
2055   BRep_Builder aBB;
2056   TopTools_MapOfShape aMVDone;
2057   Standard_Integer i, aNb = theDMVV.Extent();
2058   for (i = 1; i <= aNb; ++i) {
2059     const TopoDS_Vertex& aV = TopoDS::Vertex(theDMVV.FindKey(i));
2060     //
2061     // find chain of vertices
2062     TopTools_ListOfShape aLVChain;
2063     MakeChain(aV, theDMVV, aMVDone, aLVChain);
2064     //
2065     if (aLVChain.Extent() < 2) {
2066       continue;
2067     }
2068     //
2069     // make new vertex
2070     TopoDS_Vertex aVNew;
2071     BOPTools_AlgoTools::MakeVertex(aLVChain, aVNew);
2072     //
2073     TopoDS_Vertex aVNewInt = TopoDS::Vertex(aVNew.Oriented(TopAbs_INTERNAL));
2074     //
2075     TopTools_ListIteratorOfListOfShape aIt(aLVChain);
2076     for (; aIt.More(); aIt.Next()) {
2077       const TopoDS_Shape& aVOld = aIt.Value();
2078       // update the parameters on edges
2079       TopoDS_Vertex aVOldInt = TopoDS::Vertex(aVOld.Oriented(TopAbs_INTERNAL));
2080       const TopTools_ListOfShape& aLE = theAsDes->Ascendant(aVOld);
2081       //
2082       TopTools_ListIteratorOfListOfShape aItLE(aLE);
2083       for (; aItLE.More(); aItLE.Next()) {
2084         const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
2085         Standard_Real aTolE = BRep_Tool::Tolerance(aE);
2086         Standard_Real aT;
2087         if (!BRep_Tool::Parameter(aVOldInt, aE, aT))
2088         {
2089           return Standard_False;
2090         }
2091         aBB.UpdateVertex(aVNewInt, aT, aE, aTolE);
2092       }
2093       // and replace the vertex
2094       theAsDes->Replace(aVOld, aVNew);
2095       if (theImageVV.IsImage(aVOld))
2096       {
2097         const TopoDS_Vertex& aProVertex = TopoDS::Vertex (theImageVV.ImageFrom(aVOld));
2098         theImageVV.Add (aProVertex, aVNew.Oriented(TopAbs_FORWARD));
2099       }
2100     }
2101   }
2102   return Standard_True;
2103 }
2104