0028639: Improve performance of the IntPolyh_MaillageAffinage 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
17 #include <Adaptor3d_HSurface.hxx>
18 #include <IntPolyh_ListOfCouples.hxx>
19 #include <IntPolyh_Couple.hxx>
20 #include <IntPolyh_Intersection.hxx>
21 #include <IntPolyh_MaillageAffinage.hxx>
22 #include <IntPolyh_PMaillageAffinage.hxx>
23 #include <IntPolyh_Triangle.hxx>
24
25 Standard_Integer MYPRINT1   = 0;
26
27
28 //=======================================================================
29 //function : IntPolyh_Intersection
30 //purpose  : 
31 //=======================================================================
32 IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1,
33                                              const TColStd_Array1OfReal& Upars1,
34                                              const TColStd_Array1OfReal& Vpars1,
35                                              const Handle(Adaptor3d_HSurface)& S2,
36                                              const TColStd_Array1OfReal& Upars2,
37                                              const TColStd_Array1OfReal& Vpars2)
38 {
39   myNbSU1 = Upars1.Length();
40   myNbSV1 = Vpars1.Length();
41   myNbSU2 = Upars2.Length(); 
42   myNbSV2 = Vpars2.Length(); 
43   mySurf1 = S1;
44   mySurf2 = S2;
45   done = Standard_False;
46   TSectionLines.Init(1000);
47   TTangentZones.Init(10000);
48   Perform(Upars1, Vpars1, Upars2, Vpars2);
49 }
50
51 //=======================================================================
52 //function : Perform
53 //purpose  : 
54 //=======================================================================
55
56 void IntPolyh_Intersection::Perform(const TColStd_Array1OfReal& Upars1,
57                                     const TColStd_Array1OfReal& Vpars1,
58                                     const TColStd_Array1OfReal& Upars2,
59                                     const TColStd_Array1OfReal& Vpars2) { 
60
61   done = Standard_True;
62
63   Standard_Boolean isStdDone = Standard_False;
64   Standard_Boolean isAdvDone = Standard_False;
65   Standard_Integer nbCouplesStd = 0;
66   Standard_Integer nbCouplesAdv = 0;
67   
68   
69   IntPolyh_PMaillageAffinage aPMaillageStd = 0;
70   IntPolyh_PMaillageAffinage aPMaillageFF = 0;
71   IntPolyh_PMaillageAffinage aPMaillageFR = 0;
72   IntPolyh_PMaillageAffinage aPMaillageRF = 0;
73   IntPolyh_PMaillageAffinage aPMaillageRR = 0;
74
75   isStdDone = PerformStd( Upars1, Vpars1, Upars2, Vpars2, 
76                           aPMaillageStd,nbCouplesStd);
77
78   // default interference done well, use it
79   if(isStdDone && nbCouplesStd > 10) {
80     aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
81   }
82   // default interference done, but too few interferences foud;
83   // use advanced interference
84   else if(isStdDone && nbCouplesStd <= 10) {
85     isAdvDone = PerformAdv( Upars1, Vpars1, Upars2, Vpars2,
86                             aPMaillageFF,aPMaillageFR,aPMaillageRF,
87                             aPMaillageRR,nbCouplesAdv);
88       
89     // advanced interference found
90     if(isAdvDone && nbCouplesAdv > 0) {
91       aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
92       aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
93       aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
94       aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
95     }
96     else {
97       // use result of default
98       if(nbCouplesStd > 0)
99         aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
100     }
101   }
102   // default interference faild, use advanced
103   else {
104 //       isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
105       
106 //       if(isAdvDone && nbCouplesAdv > 0) {cout << "4adv done, nbc: " << nbCouplesAdv << endl;
107 //      aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
108 //      aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
109 //      aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
110 //      aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
111 //       }
112   }
113
114   // accept result
115   nbsectionlines = TSectionLines.NbItems();
116   nbtangentzones = TTangentZones.NbItems();
117
118   // clean up
119   if(aPMaillageStd) delete aPMaillageStd;
120   if(aPMaillageFF) delete aPMaillageFF;
121   if(aPMaillageFR) delete aPMaillageFR;
122   if(aPMaillageRF) delete aPMaillageRF;
123   if(aPMaillageRR) delete aPMaillageRR;
124
125   // verify
126   if(!isStdDone && !isAdvDone)
127     done = Standard_False;
128 }
129
130 //=======================================================================
131 //function : PerformMaillage
132 //purpose  : Computes MaillageAffinage
133 //=======================================================================
134 Standard_Boolean IntPolyh_Intersection::PerformMaillage(const Standard_Boolean isFirstFwd,
135                                                         const Standard_Boolean isSecondFwd,
136                                                         const TColStd_Array1OfReal& Upars1,
137                                                         const TColStd_Array1OfReal& Vpars1,
138                                                         const TColStd_Array1OfReal& Upars2,
139                                                         const TColStd_Array1OfReal& Vpars2,
140                                                         IntPolyh_PMaillageAffinage &theMaillageS)
141 {
142   theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(),
143                                                mySurf2, Upars2.Length(), Vpars2.Length(),
144                                                MYPRINT1);
145   
146   
147   theMaillageS->FillArrayOfPnt(1, isFirstFwd, Upars1, Vpars1);
148   theMaillageS->FillArrayOfPnt(2, isSecondFwd, Upars2, Vpars2);
149   
150   
151   
152   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
153   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
154                           xx0, yy0, zz0, xx1, yy1, zz1);
155   
156   theMaillageS->FillArrayOfTriangles(1);
157   theMaillageS->FillArrayOfTriangles(2);
158
159   theMaillageS->FillArrayOfEdges(1);
160   theMaillageS->FillArrayOfEdges(2);
161
162   theMaillageS->TrianglesDeflectionsRefinementBSB();
163
164   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
165
166   // if too many intersections, consider surfaces parallel (eap)
167   // test for parallel surf
168   if(FinTTC > 200) {
169     const Standard_Real eps = .996; //~ cos of 5deg.
170     IntPolyh_ListOfCouples& Couples = theMaillageS->GetCouples();
171
172     Standard_Integer npara = 0;
173     IntPolyh_ListIteratorOfListOfCouples aIt(Couples);
174     for(; aIt.More(); aIt.Next()) {
175       Standard_Real cosa = Abs(aIt.Value().Angle());
176       if(cosa > eps) ++npara;
177     }
178     if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
179        npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) {
180       return Standard_False;
181     }
182   }
183
184   return Standard_True;
185 }
186
187 //=======================================================================
188 //function : PerformMaillage
189 //purpose  : Computes MaillageAffinage
190 //=======================================================================
191 Standard_Boolean IntPolyh_Intersection::PerformMaillage(const TColStd_Array1OfReal& Upars1,
192                                                         const TColStd_Array1OfReal& Vpars1,
193                                                         const TColStd_Array1OfReal& Upars2,
194                                                         const TColStd_Array1OfReal& Vpars2,
195                                                         IntPolyh_PMaillageAffinage &theMaillageS)
196 {
197     
198   theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, Upars1.Length(), Vpars1.Length(),
199                                                mySurf2, Upars2.Length(), Vpars2.Length(),
200                                                MYPRINT1);
201   
202   theMaillageS->FillArrayOfPnt(1, Upars1, Vpars1);
203   theMaillageS->FillArrayOfPnt(2, Upars2, Vpars2);
204   
205   
206   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
207   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
208                           xx0, yy0, zz0, xx1, yy1, zz1);
209
210   theMaillageS->FillArrayOfTriangles(1);
211   theMaillageS->FillArrayOfTriangles(2);
212
213   theMaillageS->FillArrayOfEdges(1);
214   theMaillageS->FillArrayOfEdges(2);
215
216   theMaillageS->TrianglesDeflectionsRefinementBSB();
217
218   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
219
220   if( FinTTC == 0 ) {
221     Standard_Boolean myZone = Standard_True;
222     theMaillageS->SetEnlargeZone( myZone );
223     theMaillageS->FillArrayOfPnt(1);
224     theMaillageS->FillArrayOfPnt(2);
225     theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
226                             xx0, yy0, zz0, xx1, yy1, zz1);
227     theMaillageS->FillArrayOfTriangles(1);
228     theMaillageS->FillArrayOfTriangles(2);
229     theMaillageS->FillArrayOfEdges(1);
230     theMaillageS->FillArrayOfEdges(2);
231     theMaillageS->TrianglesDeflectionsRefinementBSB();
232     FinTTC = theMaillageS->TriangleCompare();
233     myZone = Standard_False;
234     theMaillageS->SetEnlargeZone( myZone );
235   }
236
237   // if too many intersections, consider surfaces parallel (eap)
238 //IFV test for parallel surf
239   if(FinTTC > 200) {
240     const Standard_Real eps = .996; //~ cos of 5deg.
241     IntPolyh_ListOfCouples& Couples = theMaillageS->GetCouples();
242
243     Standard_Integer npara = 0;
244     IntPolyh_ListIteratorOfListOfCouples aIt(Couples);
245     for(; aIt.More(); aIt.Next()) {
246       Standard_Real cosa = Abs(aIt.Value().Angle());
247       if(cosa > eps) ++npara;
248     }
249     if(npara >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
250        npara >= theMaillageS->GetArrayOfTriangles(2).NbItems() ) {
251       return Standard_False;
252     }
253   }
254   
255   return Standard_True;
256 }
257
258 //=======================================================================
259 //function : PerformAdv
260 //purpose  : 
261 //=======================================================================
262 Standard_Boolean IntPolyh_Intersection::PerformAdv(const TColStd_Array1OfReal& Upars1,
263                                                    const TColStd_Array1OfReal& Vpars1,
264                                                    const TColStd_Array1OfReal& Upars2,
265                                                    const TColStd_Array1OfReal& Vpars2,
266                                                    IntPolyh_PMaillageAffinage& MaillageFF,
267                                                    IntPolyh_PMaillageAffinage& MaillageFR,
268                                                    IntPolyh_PMaillageAffinage& MaillageRF,
269                                                    IntPolyh_PMaillageAffinage& MaillageRR,
270                                                    Standard_Integer&           NbCouples)
271 {
272   Standard_Boolean isdone = Standard_True;
273   NbCouples = 0;
274
275   if(!PerformMaillage(Standard_True,Standard_False,
276                       Upars1, Vpars1, Upars2, Vpars2, 
277                       MaillageFR) ||
278      !PerformMaillage(Standard_False,Standard_True,
279                       Upars1, Vpars1, Upars2, Vpars2, 
280                       MaillageRF) ||
281      !PerformMaillage(Standard_True,Standard_True,
282                       Upars1, Vpars1, Upars2, Vpars2, 
283                       MaillageFF)  ||
284      !PerformMaillage(Standard_False,Standard_False,
285                       Upars1, Vpars1, Upars2, Vpars2, 
286                       MaillageRR) )
287     isdone = Standard_False; 
288
289   if(isdone) {
290     NbCouples = MaillageFF->GetCouples().Extent() +
291       MaillageFR->GetCouples().Extent() +
292         MaillageRF->GetCouples().Extent() +
293           MaillageRR->GetCouples().Extent();
294
295     if(NbCouples > 0)
296       MergeCouples(MaillageFF->GetCouples(),MaillageFR->GetCouples(),
297                    MaillageRF->GetCouples(),MaillageRR->GetCouples());
298   }
299   return isdone;
300 }
301 //=======================================================================
302 //function : PerformStd
303 //purpose  : 
304 //=======================================================================
305
306 Standard_Boolean IntPolyh_Intersection::PerformStd(const TColStd_Array1OfReal& Upars1,
307                                                    const TColStd_Array1OfReal& Vpars1,
308                                                    const TColStd_Array1OfReal& Upars2,
309                                                    const TColStd_Array1OfReal& Vpars2,
310                                                    IntPolyh_PMaillageAffinage& MaillageS,
311                                                    Standard_Integer&           NbCouples)
312 {
313   Standard_Boolean isdone = PerformMaillage(Upars1, Vpars1, Upars2, Vpars2, 
314                                             MaillageS);
315   NbCouples = (isdone) ? (MaillageS->GetCouples().Extent()) : 0;
316   return isdone;
317 }