0026151: Wrong result obtained by intersection algorithm.
[occt.git] / src / IntPolyh / IntPolyh_Intersection_1.cxx
1 // Created on: 2005-09-26
2 // Created by: Igor FEOKTISTOV
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <IntPolyh_Intersection.ixx>
17 #include <IntPolyh_PMaillageAffinage.hxx>
18 #include <IntPolyh_MaillageAffinage.hxx>
19 #include <IntPolyh_ArrayOfCouples.hxx>
20 #include <IntPolyh_Couple.hxx>
21 #include <IntPolyh_Triangle.hxx>
22
23 Standard_Integer MYPRINT1   = 0;
24
25
26 //=======================================================================
27 //function : IntPolyh_Intersection
28 //purpose  : 
29 //=======================================================================
30 IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1,
31                                              const TColStd_Array1OfReal& Upars1,
32                                              const TColStd_Array1OfReal& Vpars1,
33                                              const Handle(Adaptor3d_HSurface)& S2,
34                                              const TColStd_Array1OfReal& Upars2,
35                                              const TColStd_Array1OfReal& Vpars2)
36 {
37   myNbSU1 = Upars1.Length();
38   myNbSV1 = Vpars1.Length();
39   myNbSU2 = Upars2.Length(); 
40   myNbSV2 = Vpars2.Length(); 
41   mySurf1 = S1;
42   mySurf2 = S2;
43   done = Standard_False;
44   TSectionLines.Init(1000);
45   TTangentZones.Init(10000);
46   Perform(Upars1, Vpars1, Upars2, Vpars2);
47 }
48
49 //=======================================================================
50 //function : Perform
51 //purpose  : 
52 //=======================================================================
53
54 void IntPolyh_Intersection::Perform(const TColStd_Array1OfReal& Upars1,
55                                     const TColStd_Array1OfReal& Vpars1,
56                                     const TColStd_Array1OfReal& Upars2,
57                                     const TColStd_Array1OfReal& Vpars2) { 
58
59   done = Standard_True;
60
61   Standard_Boolean isStdDone = Standard_False;
62   Standard_Boolean isAdvDone = Standard_False;
63   Standard_Integer nbCouplesStd = 0;
64   Standard_Integer nbCouplesAdv = 0;
65   
66   
67   IntPolyh_PMaillageAffinage aPMaillageStd = 0;
68   IntPolyh_PMaillageAffinage aPMaillageFF = 0;
69   IntPolyh_PMaillageAffinage aPMaillageFR = 0;
70   IntPolyh_PMaillageAffinage aPMaillageRF = 0;
71   IntPolyh_PMaillageAffinage aPMaillageRR = 0;
72
73   isStdDone = PerformStd( Upars1, Vpars1, Upars2, Vpars2, 
74                           aPMaillageStd,nbCouplesStd);
75
76   // default interference done well, use it
77   if(isStdDone && nbCouplesStd > 10) {
78     aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
79   }
80   // default interference done, but too few interferences foud;
81   // use advanced interference
82   else if(isStdDone && nbCouplesStd <= 10) {
83     isAdvDone = PerformAdv( Upars1, Vpars1, Upars2, Vpars2,
84                             aPMaillageFF,aPMaillageFR,aPMaillageRF,
85                             aPMaillageRR,nbCouplesAdv);
86       
87     // advanced interference found
88     if(isAdvDone && nbCouplesAdv > 10) {
89       aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
90       aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
91       aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
92       aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
93     }
94     else {
95       // use result of default
96       if(nbCouplesStd > 0)
97         aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
98     }
99   }
100   // default interference faild, use advanced
101   else {
102 //       isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
103       
104 //       if(isAdvDone && nbCouplesAdv > 0) {cout << "4adv done, nbc: " << nbCouplesAdv << endl;
105 //      aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
106 //      aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
107 //      aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
108 //      aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
109 //       }
110   }
111
112   // accept result
113   nbsectionlines = TSectionLines.NbItems();
114   nbtangentzones = TTangentZones.NbItems();
115
116   // clean up
117   if(aPMaillageStd) delete aPMaillageStd;
118   if(aPMaillageFF) delete aPMaillageFF;
119   if(aPMaillageFR) delete aPMaillageFR;
120   if(aPMaillageRF) delete aPMaillageRF;
121   if(aPMaillageRR) delete aPMaillageRR;
122
123   // verify
124   if(!isStdDone && !isAdvDone)
125     done = Standard_False;
126 }
127
128 //=======================================================================
129 //function : PerformMaillage
130 //purpose  : Computes MaillageAffinage
131 //=======================================================================
132 Standard_Boolean IntPolyh_Intersection::PerformMaillage(const Standard_Boolean isFirstFwd,
133                                                         const Standard_Boolean isSecondFwd,
134                                                         const TColStd_Array1OfReal& Upars1,
135                                                         const TColStd_Array1OfReal& Vpars1,
136                                                         const TColStd_Array1OfReal& Upars2,
137                                                         const TColStd_Array1OfReal& Vpars2,
138                                                         IntPolyh_PMaillageAffinage &theMaillageS)
139 {
140   theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(),
141                                                mySurf2, Upars2.Length(), Vpars2.Length(),
142                                                MYPRINT1);
143   
144   
145   theMaillageS->FillArrayOfPnt(1, isFirstFwd, Upars1, Vpars1);
146   theMaillageS->FillArrayOfPnt(2, isSecondFwd, Upars2, Vpars2);
147   
148   
149   
150   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
151   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
152                           xx0, yy0, zz0, xx1, yy1, zz1);
153   
154   theMaillageS->FillArrayOfEdges(1);
155   theMaillageS->FillArrayOfEdges(2);
156
157   theMaillageS->FillArrayOfTriangles(1);
158   theMaillageS->FillArrayOfTriangles(2);
159   
160   theMaillageS->LinkEdges2Triangles();
161   
162   theMaillageS->TrianglesDeflectionsRefinementBSB();
163
164   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
165
166   // if too many intersections, consider surfaces parallel (eap)
167 /*
168   if(FinTTC > 200 &&
169      (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbTriangles() ||
170       FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbTriangles()) ) {
171     return Standard_False;
172 }
173 */
174 //IFV test for parallel surf
175   if(FinTTC > 200) {
176     const Standard_Real eps = .996; //~ cos of 5deg.
177     IntPolyh_ArrayOfCouples& Couples = theMaillageS->GetArrayOfCouples();
178
179     Standard_Integer i, npara = 0;
180     for(i = 0; i < FinTTC; ++i) {
181       Standard_Real cosa = Abs(Couples[i].AngleValue());
182       if(cosa > eps) ++npara;
183     }
184     if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
185        npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) {
186       return Standard_False;
187     }
188   }
189
190   return Standard_True;
191 }
192
193 //=======================================================================
194 //function : PerformMaillage
195 //purpose  : Computes MaillageAffinage
196 //=======================================================================
197 Standard_Boolean IntPolyh_Intersection::PerformMaillage(const TColStd_Array1OfReal& Upars1,
198                                                         const TColStd_Array1OfReal& Vpars1,
199                                                         const TColStd_Array1OfReal& Upars2,
200                                                         const TColStd_Array1OfReal& Vpars2,
201                                                         IntPolyh_PMaillageAffinage &theMaillageS)
202 {
203     
204   theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(),
205                                                mySurf2, Upars2.Length(), Vpars2.Length(),
206                                                MYPRINT1);
207   
208   theMaillageS->FillArrayOfPnt(1, Upars1, Vpars1);
209   theMaillageS->FillArrayOfPnt(2, Upars2, Vpars2);
210   
211   
212   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
213   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
214                           xx0, yy0, zz0, xx1, yy1, zz1);
215   theMaillageS->FillArrayOfEdges(1);
216   theMaillageS->FillArrayOfEdges(2);
217
218   theMaillageS->FillArrayOfTriangles(1);
219   theMaillageS->FillArrayOfTriangles(2);
220   
221   theMaillageS->LinkEdges2Triangles();
222   
223   theMaillageS->TrianglesDeflectionsRefinementBSB();
224
225   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
226
227   if( FinTTC == 0 ) {
228     Standard_Boolean myZone = Standard_True;
229     theMaillageS->SetEnlargeZone( myZone );
230     theMaillageS->FillArrayOfPnt(1);
231     theMaillageS->FillArrayOfPnt(2);
232     theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
233                             xx0, yy0, zz0, xx1, yy1, zz1);
234     theMaillageS->FillArrayOfEdges(1);
235     theMaillageS->FillArrayOfEdges(2);
236     theMaillageS->FillArrayOfTriangles(1);
237     theMaillageS->FillArrayOfTriangles(2);
238     theMaillageS->LinkEdges2Triangles();
239     theMaillageS->TrianglesDeflectionsRefinementBSB();
240     FinTTC = theMaillageS->TriangleCompare();
241     myZone = Standard_False;
242     theMaillageS->SetEnlargeZone( myZone );
243   }
244
245   // if too many intersections, consider surfaces parallel (eap)
246 /*
247   if(FinTTC > 200 &&
248      (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbTriangles() ||
249       FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbTriangles()) ) {
250     return Standard_False;
251 }
252 */
253 //IFV test for parallel surf
254   if(FinTTC > 200) {
255     const Standard_Real eps = .996; //~ cos of 5deg.
256     IntPolyh_ArrayOfCouples& Couples = theMaillageS->GetArrayOfCouples();
257
258     Standard_Integer i, npara = 0;
259     for(i = 0; i < FinTTC; ++i) {
260       Standard_Real cosa = Abs(Couples[i].AngleValue());
261       if(cosa > eps) ++npara;
262     }
263     if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
264        npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) {
265       return Standard_False;
266     }
267   }
268   
269   return Standard_True;
270 }
271
272 //=======================================================================
273 //function : PerformAdv
274 //purpose  : 
275 //=======================================================================
276 Standard_Boolean IntPolyh_Intersection::PerformAdv(const TColStd_Array1OfReal& Upars1,
277                                                    const TColStd_Array1OfReal& Vpars1,
278                                                    const TColStd_Array1OfReal& Upars2,
279                                                    const TColStd_Array1OfReal& Vpars2,
280                                                    IntPolyh_PMaillageAffinage& MaillageFF,
281                                                    IntPolyh_PMaillageAffinage& MaillageFR,
282                                                    IntPolyh_PMaillageAffinage& MaillageRF,
283                                                    IntPolyh_PMaillageAffinage& MaillageRR,
284                                                    Standard_Integer&           NbCouples)
285 {
286   Standard_Boolean isdone = Standard_True;
287   NbCouples = 0;
288
289   if(!PerformMaillage(Standard_True,Standard_False,
290                       Upars1, Vpars1, Upars2, Vpars2, 
291                       MaillageFR) ||
292      !PerformMaillage(Standard_False,Standard_True,
293                       Upars1, Vpars1, Upars2, Vpars2, 
294                       MaillageRF) ||
295      !PerformMaillage(Standard_True,Standard_True,
296                       Upars1, Vpars1, Upars2, Vpars2, 
297                       MaillageFF)  ||
298      !PerformMaillage(Standard_False,Standard_False,
299                       Upars1, Vpars1, Upars2, Vpars2, 
300                       MaillageRR) )
301     isdone = Standard_False; 
302
303   if(isdone) {
304     NbCouples = MaillageFF->GetArrayOfCouples().NbItems() +
305       MaillageFR->GetArrayOfCouples().NbItems() +
306         MaillageRF->GetArrayOfCouples().NbItems() +
307           MaillageRR->GetArrayOfCouples().NbItems();
308
309     if(NbCouples > 0)
310       MergeCouples(MaillageFF->GetArrayOfCouples(),MaillageFR->GetArrayOfCouples(),
311                    MaillageRF->GetArrayOfCouples(),MaillageRR->GetArrayOfCouples());
312   }
313   return isdone;
314 }
315 //=======================================================================
316 //function : PerformStd
317 //purpose  : 
318 //=======================================================================
319
320 Standard_Boolean IntPolyh_Intersection::PerformStd(const TColStd_Array1OfReal& Upars1,
321                                                    const TColStd_Array1OfReal& Vpars1,
322                                                    const TColStd_Array1OfReal& Upars2,
323                                                    const TColStd_Array1OfReal& Vpars2,
324                                                    IntPolyh_PMaillageAffinage& MaillageS,
325                                                    Standard_Integer&           NbCouples)
326 {
327   Standard_Boolean isdone = PerformMaillage(Upars1, Vpars1, Upars2, Vpars2, 
328                                             MaillageS);
329   NbCouples = (isdone) ? (MaillageS->GetArrayOfCouples().NbItems()) : 0;
330   return isdone;
331 }