0023548: Boolean operation between two faces fails
[occt.git] / src / IntPolyh / IntPolyh_Intersection_1.cxx
1 // Created on: 2005-09-26
2 // Created by: Igor FEOKTISTOV
3 // Copyright (c) 2005-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21
22 #include <IntPolyh_Intersection.ixx>
23 #include <IntPolyh_PMaillageAffinage.hxx>
24 #include <IntPolyh_MaillageAffinage.hxx>
25 #include <IntPolyh_ArrayOfCouples.hxx>
26 #include <IntPolyh_Couple.hxx>
27 #include <IntPolyh_Triangle.hxx>
28
29 Standard_Integer MYPRINT1   = 0;
30
31
32 //=======================================================================
33 //function : IntPolyh_Intersection
34 //purpose  : 
35 //=======================================================================
36
37 IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1,
38                                              const TColStd_Array1OfReal& Upars1,
39                                              const TColStd_Array1OfReal& Vpars1,
40                                              const Handle(Adaptor3d_HSurface)& S2,
41                                              const TColStd_Array1OfReal& Upars2,
42                                              const TColStd_Array1OfReal& Vpars2)
43 {
44   myNbSU1 = Upars1.Length();
45   myNbSV1 = Vpars1.Length();
46   myNbSU2 = Upars2.Length(); 
47   myNbSV2 = Vpars2.Length(); 
48   mySurf1 = S1;
49   mySurf2 = S2;
50   done = Standard_False;
51   TSectionLines.Init(1000);
52   TTangentZones.Init(10000);
53   Perform(Upars1, Vpars1, Upars2, Vpars2);
54 }
55
56 //=======================================================================
57 //function : Perform
58 //purpose  : 
59 //=======================================================================
60
61 void IntPolyh_Intersection::Perform(const TColStd_Array1OfReal& Upars1,
62                                     const TColStd_Array1OfReal& Vpars1,
63                                     const TColStd_Array1OfReal& Upars2,
64                                     const TColStd_Array1OfReal& Vpars2) { 
65
66   done = Standard_True;
67
68   Standard_Boolean startFromAdvanced = Standard_False;
69   Standard_Boolean isStdDone = Standard_False;
70   Standard_Boolean isAdvDone = Standard_False;
71   Standard_Integer nbCouplesStd = 0;
72   Standard_Integer nbCouplesAdv = 0;
73   
74   
75   IntPolyh_PMaillageAffinage aPMaillageStd = 0;
76   IntPolyh_PMaillageAffinage aPMaillageFF = 0;
77   IntPolyh_PMaillageAffinage aPMaillageFR = 0;
78   IntPolyh_PMaillageAffinage aPMaillageRF = 0;
79   IntPolyh_PMaillageAffinage aPMaillageRR = 0;
80
81
82   if(!startFromAdvanced) {
83
84     isStdDone = PerformStd(Upars1, Vpars1, Upars2, Vpars2, 
85                            aPMaillageStd,nbCouplesStd);
86
87     // default interference done well, use it
88     if(isStdDone && nbCouplesStd > 10) {
89       aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
90     }
91     // default interference done, but too few interferences foud;
92     // use advanced interference
93     else if(isStdDone && nbCouplesStd <= 10) {
94       isAdvDone = PerformAdv(Upars1, Vpars1, Upars2, Vpars2,
95                              aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
96       
97       // advanced interference found
98       if(isAdvDone && nbCouplesAdv > 10) {
99         aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
100         aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
101         aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
102         aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
103       }
104       else {
105         // use result of default
106         if(nbCouplesStd > 0)
107           aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
108       }
109     }
110     // default interference faild, use advanced
111     else {
112 //       isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
113       
114 //       if(isAdvDone && nbCouplesAdv > 0) {cout << "4adv done, nbc: " << nbCouplesAdv << endl;
115 //      aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
116 //      aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
117 //      aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
118 //      aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
119 //       }
120     }
121   }// start from default
122   else {
123     
124     isAdvDone = PerformAdv(Upars1, Vpars1, Upars2, Vpars2,
125                            aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
126
127     // advanced done, interference found; use it
128     if(isAdvDone) {
129
130       if(nbCouplesAdv > 0) {
131         aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
132         aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
133         aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
134         aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
135       }
136       else {
137         isStdDone = PerformStd(aPMaillageStd,nbCouplesStd);
138         if(isStdDone && nbCouplesStd > 0)
139           aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
140       }
141     }
142     else {
143       isStdDone = PerformStd(Upars1, Vpars1, Upars2, Vpars2,
144                              aPMaillageStd,nbCouplesStd);
145       if(isStdDone && nbCouplesStd > 0)
146         aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
147     }
148   } // start from advanced
149
150   // accept result
151   nbsectionlines = TSectionLines.NbItems();
152   nbtangentzones = TTangentZones.NbItems();
153
154   // clean up
155   if(aPMaillageStd) delete aPMaillageStd;
156   if(aPMaillageFF) delete aPMaillageFF;
157   if(aPMaillageFR) delete aPMaillageFR;
158   if(aPMaillageRF) delete aPMaillageRF;
159   if(aPMaillageRR) delete aPMaillageRR;
160
161   // verify
162   if(!isStdDone && !isAdvDone)
163     done = Standard_False;
164 }
165
166 //=======================================================================
167 //function : PerformMaillage
168 //purpose  : Computes MaillageAffinage
169 //=======================================================================
170 Standard_Boolean IntPolyh_Intersection::PerformMaillage(const Standard_Boolean isFirstFwd,
171                                                         const Standard_Boolean isSecondFwd,
172                                                         const TColStd_Array1OfReal& Upars1,
173                                                         const TColStd_Array1OfReal& Vpars1,
174                                                         const TColStd_Array1OfReal& Upars2,
175                                                         const TColStd_Array1OfReal& Vpars2,
176                                                         IntPolyh_PMaillageAffinage &theMaillageS)
177 {
178   theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(),
179                                                mySurf2, Upars2.Length(), Vpars2.Length(),
180                                                MYPRINT1);
181   
182   
183   theMaillageS->FillArrayOfPnt(1, isFirstFwd, Upars1, Vpars1);
184   theMaillageS->FillArrayOfPnt(2, isSecondFwd, Upars2, Vpars2);
185   
186   
187   
188   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
189   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
190                           xx0, yy0, zz0, xx1, yy1, zz1);
191   
192   theMaillageS->FillArrayOfEdges(1);
193   theMaillageS->FillArrayOfEdges(2);
194
195   theMaillageS->FillArrayOfTriangles(1);
196   theMaillageS->FillArrayOfTriangles(2);
197   
198   theMaillageS->LinkEdges2Triangles();
199   
200   theMaillageS->TrianglesDeflectionsRefinementBSB();
201
202   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
203
204   // if too many intersections, consider surfaces parallel (eap)
205 /*
206   if(FinTTC > 200 &&
207      (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbTriangles() ||
208       FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbTriangles()) ) {
209     return Standard_False;
210   }
211 */
212 //IFV test for parallel surf
213   if(FinTTC > 200) {
214     const Standard_Real eps = .996; //~ cos of 5deg.
215     IntPolyh_ArrayOfCouples& Couples = theMaillageS->GetArrayOfCouples();
216     
217     Standard_Integer i, npara = 0;
218     for(i = 0; i < FinTTC; ++i) {
219       Standard_Real cosa = Abs(Couples[i].AngleValue());
220       if(cosa > eps) ++npara;
221     }
222     if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
223        npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) {
224       return Standard_False;
225     }
226   }
227
228   return Standard_True;
229 }
230
231 //=======================================================================
232 //function : PerformMaillage
233 //purpose  : Computes MaillageAffinage
234 //=======================================================================
235 Standard_Boolean IntPolyh_Intersection::PerformMaillage(const TColStd_Array1OfReal& Upars1,
236                                                         const TColStd_Array1OfReal& Vpars1,
237                                                         const TColStd_Array1OfReal& Upars2,
238                                                         const TColStd_Array1OfReal& Vpars2,
239                                                         IntPolyh_PMaillageAffinage &theMaillageS)
240 {
241     
242   theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(),
243                                                mySurf2, Upars2.Length(), Vpars2.Length(),
244                                                MYPRINT1);
245   
246   theMaillageS->FillArrayOfPnt(1, Upars1, Vpars1);
247   theMaillageS->FillArrayOfPnt(2, Upars2, Vpars2);
248   
249   
250   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
251   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
252                           xx0, yy0, zz0, xx1, yy1, zz1);
253   theMaillageS->FillArrayOfEdges(1);
254   theMaillageS->FillArrayOfEdges(2);
255
256   theMaillageS->FillArrayOfTriangles(1);
257   theMaillageS->FillArrayOfTriangles(2);
258   
259   theMaillageS->LinkEdges2Triangles();
260   
261   theMaillageS->TrianglesDeflectionsRefinementBSB();
262
263   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
264
265   if( FinTTC == 0 ) {
266     Standard_Boolean myZone = Standard_True;
267     theMaillageS->SetEnlargeZone( myZone );
268     theMaillageS->FillArrayOfPnt(1);
269     theMaillageS->FillArrayOfPnt(2);
270     theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
271                             xx0, yy0, zz0, xx1, yy1, zz1);
272     theMaillageS->FillArrayOfEdges(1);
273     theMaillageS->FillArrayOfEdges(2);
274     theMaillageS->FillArrayOfTriangles(1);
275     theMaillageS->FillArrayOfTriangles(2);
276     theMaillageS->LinkEdges2Triangles();
277     theMaillageS->TrianglesDeflectionsRefinementBSB();
278     FinTTC = theMaillageS->TriangleCompare();
279     myZone = Standard_False;
280     theMaillageS->SetEnlargeZone( myZone );
281   }
282
283   // if too many intersections, consider surfaces parallel (eap)
284 /*
285   if(FinTTC > 200 &&
286      (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbTriangles() ||
287       FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbTriangles()) ) {
288     return Standard_False;
289   }
290 */
291 //IFV test for parallel surf
292   if(FinTTC > 200) {
293     const Standard_Real eps = .996; //~ cos of 5deg.
294     IntPolyh_ArrayOfCouples& Couples = theMaillageS->GetArrayOfCouples();
295     
296     Standard_Integer i, npara = 0;
297     for(i = 0; i < FinTTC; ++i) {
298       Standard_Real cosa = Abs(Couples[i].AngleValue());
299       if(cosa > eps) ++npara;
300     }
301     if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
302        npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) {
303       return Standard_False;
304     }
305   }
306   
307   return Standard_True;
308 }
309
310 //=======================================================================
311 //function : PerformAdv
312 //purpose  : 
313 //=======================================================================
314
315 Standard_Boolean IntPolyh_Intersection::PerformAdv(const TColStd_Array1OfReal& Upars1,
316                                                    const TColStd_Array1OfReal& Vpars1,
317                                                    const TColStd_Array1OfReal& Upars2,
318                                                    const TColStd_Array1OfReal& Vpars2,
319                                                    IntPolyh_PMaillageAffinage& MaillageFF,
320                                                    IntPolyh_PMaillageAffinage& MaillageFR,
321                                                    IntPolyh_PMaillageAffinage& MaillageRF,
322                                                    IntPolyh_PMaillageAffinage& MaillageRR,
323                                                    Standard_Integer&           NbCouples)
324 {
325   Standard_Boolean isdone = Standard_True;
326   NbCouples = 0;
327
328   if(!PerformMaillage(Standard_True,Standard_False,
329                       Upars1, Vpars1, Upars2, Vpars2, 
330                       MaillageFR) ||
331      !PerformMaillage(Standard_False,Standard_True,
332                       Upars1, Vpars1, Upars2, Vpars2, 
333                       MaillageRF) ||
334      !PerformMaillage(Standard_True,Standard_True,
335                       Upars1, Vpars1, Upars2, Vpars2, 
336                       MaillageFF)  ||
337      !PerformMaillage(Standard_False,Standard_False,
338                       Upars1, Vpars1, Upars2, Vpars2, 
339                       MaillageRR) )
340     isdone = Standard_False; 
341
342   if(isdone) {
343     NbCouples = MaillageFF->GetArrayOfCouples().NbItems() +
344       MaillageFR->GetArrayOfCouples().NbItems() +
345         MaillageRF->GetArrayOfCouples().NbItems() +
346           MaillageRR->GetArrayOfCouples().NbItems();
347
348     if(NbCouples > 0)
349       MergeCouples(MaillageFF->GetArrayOfCouples(),MaillageFR->GetArrayOfCouples(),
350                    MaillageRF->GetArrayOfCouples(),MaillageRR->GetArrayOfCouples());
351   }
352   return isdone;
353 }
354 //=======================================================================
355 //function : PerformStd
356 //purpose  : 
357 //=======================================================================
358
359 Standard_Boolean IntPolyh_Intersection::PerformStd(const TColStd_Array1OfReal& Upars1,
360                                                    const TColStd_Array1OfReal& Vpars1,
361                                                    const TColStd_Array1OfReal& Upars2,
362                                                    const TColStd_Array1OfReal& Vpars2,
363                                                    IntPolyh_PMaillageAffinage& MaillageS,
364                                                    Standard_Integer&           NbCouples)
365 {
366   Standard_Boolean isdone = PerformMaillage(Upars1, Vpars1, Upars2, Vpars2, 
367                                             MaillageS);
368   NbCouples = (isdone) ? (MaillageS->GetArrayOfCouples().NbItems()) : 0;
369   return isdone;
370 }