0025880: fuzzy booleans with multiple tools
[occt.git] / src / BOPTools / BOPTools_AlgoTools2D_1.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2015 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BOPTools_AlgoTools2D.hxx>
16 #include <Precision.hxx>
17
18 #include <gp_Vec2d.hxx>
19 #include <gp_Dir2d.hxx>
20
21 #include <TopLoc_Location.hxx>
22
23 #include <Geom2d_Curve.hxx>
24 #include <Geom2d_TrimmedCurve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <GeomLib.hxx>
27
28 #include <GeomAPI_ProjectPointOnCurve.hxx>
29
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Face.hxx>
32
33 #include <BRep_Builder.hxx>
34 #include <BRep_Tool.hxx>
35 #include <BRepLib.hxx>
36
37 #include <TopExp_Explorer.hxx>
38
39 #include <IntTools_Context.hxx>
40
41 #include <BOPTools_AlgoTools2D.hxx>
42
43
44
45 static
46   Standard_Integer UpdateClosedPCurve(const TopoDS_Edge& ,
47                                       const TopoDS_Edge& ,
48                                       const TopoDS_Face& , 
49                                       const Handle(IntTools_Context)& );
50 static
51   Standard_Boolean IsToReverse(const TopoDS_Edge& ,
52                                const TopoDS_Edge& ,
53                                const Handle(IntTools_Context)& );
54 static
55   Standard_Boolean IsClosed(const TopoDS_Edge& ,
56                             const TopoDS_Face& );
57
58
59 //=======================================================================
60 //function : AttachExistingPCurve
61 //purpose  : 
62 //=======================================================================
63 Standard_Integer BOPTools_AlgoTools2D::AttachExistingPCurve
64   (const TopoDS_Edge& aE2, // old
65    const TopoDS_Edge& aE1, // new
66    const TopoDS_Face& aF, 
67    const Handle(IntTools_Context)& aCtx)
68 {
69   Standard_Boolean bIsToReverse, bIsClosed;
70   Standard_Integer iRet;
71   Standard_Real aTol, aT11, aT12, aT21, aT22, aTolPPC;
72   Handle(Geom2d_Curve) aC2Dold, aC2DoldC;
73   Handle(Geom2d_TrimmedCurve) aC2DT;
74   BRep_Builder aBB;
75   //
76   iRet=0;
77   //
78   aC2Dold=BRep_Tool::CurveOnSurface(aE2, aF, aT21, aT22);
79   if (aC2Dold.IsNull()){
80     iRet=1;
81     return iRet;
82   }
83   //
84   aC2DoldC=Handle(Geom2d_Curve)::DownCast(aC2Dold->Copy());
85   //
86   bIsToReverse=IsToReverse(aE2, aE1, aCtx);
87   if (bIsToReverse) {
88     aC2DoldC->Reverse();
89     //
90     gp_Pnt2d aP1, aP2;
91     //
92     aC2Dold->D0(aT22, aP2);
93     aC2DoldC->D0(aT21, aP1);
94     aC2DoldC->Translate(aP1, aP2);
95   }
96   //
97   aC2DT=new Geom2d_TrimmedCurve(aC2DoldC, aT21, aT22);
98   //
99   aTol=BRep_Tool::Tolerance(aE1);
100   BRep_Tool::Range (aE1, aT11, aT12);
101   aBB.SameRange(aE1, Standard_False);
102   aBB.SameParameter(aE1, Standard_False);
103   
104   aTolPPC=Precision::PConfusion();
105   //
106   GeomLib::SameRange(aTolPPC, aC2DT, aT21, aT22, aT11, aT12, aC2DT);
107   //
108   if (aC2DT.IsNull()){
109     iRet=2;
110     return iRet;
111   }
112   //
113   aBB.UpdateEdge(aE1, aC2DT, aF, aTol);
114   BRepLib::SameParameter(aE1);
115   BRepLib::SameRange(aE1);
116   //
117   bIsClosed=IsClosed(aE2, aF);
118   if (bIsClosed) {
119     iRet=UpdateClosedPCurve(aE2, aE1, aF, aCtx);
120     if(iRet) {
121       iRet=3;
122     }
123   }
124   //
125   return iRet;
126 }
127 //=======================================================================
128 //function : UpdateClosedPCurve
129 //purpose  : 
130 //=======================================================================
131 Standard_Integer UpdateClosedPCurve(const TopoDS_Edge& aEold,
132                                     const TopoDS_Edge& aEnew,
133                                     const TopoDS_Face& aF, 
134                                     const Handle(IntTools_Context)& aCtx)
135 {
136   Standard_Boolean bUClosed, bRevOrder;
137   Standard_Integer aNbPoints, iRet;
138   Standard_Real aTS1, aTS2, aTS, aScPr, aUS1, aVS1, aUS2, aVS2, aT, aU, aV;
139   Standard_Real aT1, aT2, aTol;
140   gp_Pnt2d aP2DS1, aP2DS2, aP2D; 
141   gp_Vec2d aV2DT, aV2D, aV2DS1, aV2DS2;
142   gp_Pnt aP;
143   Handle(Geom2d_Curve) aC2D, aC2DS1, aC2DS2, aC2Dnew, aC2DoldCT;         
144   Handle(Geom2d_Curve) aC2Dold;         
145   Handle(Geom2d_TrimmedCurve) aC2DTnew;
146   Handle(Geom_Surface) aS;
147   TopoDS_Edge aES;
148   BRep_Builder aBB;
149   //
150   iRet=0;
151   aTol=BRep_Tool::Tolerance(aEnew);
152   //
153   // aC2DoldCT is alone p-curve of aEnew that we've built
154   // The task is to build closed p-curves for aEnew
155   aC2DoldCT=BRep_Tool::CurveOnSurface(aEnew, aF, aT1, aT2);
156   //
157   // aC2Dold is p-curve of aEold
158   aC2Dold=BRep_Tool::CurveOnSurface(aEold, aF, aT1, aT2);
159   //
160   // As aEold is closed on aF, it is possible to retrieve
161   // the two p-curves:  
162   //  aC2DS1 -first p-curve 
163   //  aC2DS2 -second p-curve
164   aES=aEold;
165   aES.Orientation(TopAbs_FORWARD);
166   aC2DS1=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
167   //
168   aES.Orientation(TopAbs_REVERSED);
169   aC2DS2=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
170   //
171   aTS=BOPTools_AlgoTools2D::IntermediatePoint(aTS1, aTS2);
172   //
173   aC2DS1->D1(aTS, aP2DS1, aV2DS1);
174   aC2DS2->D1(aTS, aP2DS2, aV2DS2);
175   //
176   // aV2DS12 - translation vector 
177   gp_Vec2d aV2DS12(aP2DS1, aP2DS2);
178   gp_Dir2d aD2DS12(aV2DS12);
179   const gp_Dir2d& aD2DX=gp::DX2d();
180   //
181   // Directoion of closeness: U-Closed or V-Closed 
182   aScPr=aD2DS12*aD2DX;
183   bUClosed=Standard_True;
184   if (fabs(aScPr) < aTol) {
185     bUClosed=!bUClosed;
186   }
187   //
188   aP2DS1.Coord(aUS1, aVS1);
189   aP2DS2.Coord(aUS2, aVS2);
190   //
191   // aP - some 3D-point on seam edge of the surface aS
192   aS=BRep_Tool::Surface(aF);
193   aS->D0(aUS1, aVS1, aP);
194   //
195   GeomAPI_ProjectPointOnCurve& aProjPC=aCtx->ProjPC(aEnew);
196   //
197   aProjPC.Perform(aP);
198   aNbPoints=aProjPC.NbPoints();
199   if (!aNbPoints) {
200     iRet=1;
201     return iRet;
202   }
203   //
204   // aT - parameter for aP on the curves of aEnew
205   aT=aProjPC.LowerDistanceParameter();
206   //
207   aC2D=aC2DoldCT;
208   aC2D->D1(aT, aP2D, aV2D);
209   aP2D.Coord(aU, aV);
210   //
211   aC2Dnew=Handle(Geom2d_Curve)::DownCast(aC2D->Copy());
212   aC2DTnew=new Geom2d_TrimmedCurve(aC2Dnew, aT1, aT2);
213   //
214   aV2DT=aV2DS12;
215   if (!bUClosed) {    // V Closed
216     if (fabs(aV-aVS2)<aTol) {
217       aV2DT.Reverse();
218     }
219   }
220   else {   // U Closed
221     if (fabs(aU-aUS2)<aTol) {
222       aV2DT.Reverse();
223     }
224   }
225   //
226   // Translate aC2DTnew
227   aC2DTnew->Translate(aV2DT);
228   //
229   // 4 Order the 2D curves
230   bRevOrder=Standard_False;
231   aScPr=aV2D*aV2DS1;
232   if(aScPr<0.) {
233     bRevOrder=!bRevOrder;
234   }
235   //
236   if (!bRevOrder) {
237     aBB.UpdateEdge(aEnew, aC2D, aC2DTnew, aF, aTol);
238   }
239   else {
240     aBB.UpdateEdge(aEnew, aC2DTnew, aC2D , aF, aTol);
241   }
242   return iRet;
243 }
244 //=======================================================================
245 //function : IsToReverse
246 //purpose  : 
247 //=======================================================================
248 Standard_Boolean IsToReverse(const TopoDS_Edge& aEold,
249                              const TopoDS_Edge& aEnew,
250                              const Handle(IntTools_Context)& aCtx)
251 {
252   Standard_Boolean bRet, bFlag, bIsDegenerated;
253   Standard_Real aTnew, aTold, aScPr, aTa, aTb, aT1, aT2;
254   gp_Vec aVold, aVnew, aVE, aVS;
255   gp_Pnt aP;
256   Handle(Geom_Curve) aCold, aCnew;
257   //
258   bRet=Standard_False;
259   //
260   bIsDegenerated=(BRep_Tool::Degenerated(aEold) ||
261                   BRep_Tool::Degenerated(aEnew));
262   if (bIsDegenerated) {
263     return bRet;
264   }
265   //
266   aCold=BRep_Tool::Curve(aEold, aT1, aT2);
267   aCnew=BRep_Tool::Curve(aEnew, aTa, aTb);
268   //
269   if (aCold==aCnew) {
270     return bRet;
271   }
272   //
273   aTnew=BOPTools_AlgoTools2D::IntermediatePoint(aTa, aTb);
274   aCnew->D1(aTnew, aP, aVnew);
275   aVnew.Normalize(); 
276   //
277   bFlag=aCtx->ProjectPointOnEdge(aP, aEold, aTold);
278   aCold->D1(aTold, aP, aVold);
279   aVold.Normalize(); 
280   //
281   aScPr=aVnew*aVold;
282   bRet=(aScPr<0.);
283   //
284   return bRet;
285 }
286 //=======================================================================
287 //function : IsClosed
288 //purpose  :
289 //=======================================================================
290 Standard_Boolean IsClosed(const TopoDS_Edge& aE,
291                           const TopoDS_Face& aF)
292 {
293   Standard_Boolean bRet;
294   //
295   bRet=BRep_Tool::IsClosed(aE, aF);
296   if (bRet) {
297     Standard_Integer iCnt;
298     //
299     iCnt=0;
300     TopExp_Explorer aExp(aF, TopAbs_EDGE);
301     for (; (aExp.More() || iCnt==2); aExp.Next()) {
302       const TopoDS_Shape& aEx=aExp.Current();
303       if(aEx.IsSame(aE)) {
304         ++iCnt;
305       }
306     }
307     bRet=(iCnt==2);
308   }
309   return bRet;
310 }
311