0026151: Wrong result obtained by intersection algorithm.
[occt.git] / src / IntPolyh / IntPolyh_Intersection.cxx
1 // Created on: 1999-03-03
2 // Created by: Fabrice SERVANT
3 // Copyright (c) 1999-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 Edward AGAPOV (eap) Tue Jan 22 12:29:55 2002 (occ53)
18 //  Modified by skv - Thu Sep 25 18:24:29 2003 OCC567
19
20 #include <IntPolyh_Intersection.ixx>
21 #include <IntPolyh_SectionLine.hxx>
22 #include <IntPolyh_StartPoint.hxx>
23 #include <IntPolyh_MaillageAffinage.hxx>
24 #include <IntPolyh_Couple.hxx>
25 #include <IntPolyh_Triangle.hxx>
26
27 Standard_Integer MYDISPLAY = 0;
28 Standard_Integer MYPRINT   = 0;
29
30 IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1,
31                                              const Handle(Adaptor3d_HSurface)& S2)
32 {
33   myNbSU1 = -1;
34   myNbSV1 = -1;
35   myNbSU2 = -1; 
36   myNbSV2 = -1; 
37   mySurf1 = S1;
38   mySurf2 = S2;
39   done = Standard_False;
40   TSectionLines.Init(1000);
41   TTangentZones.Init(10000);
42   Perform();
43 }
44
45 IntPolyh_Intersection::IntPolyh_Intersection(const Handle(Adaptor3d_HSurface)& S1,
46                                              const Standard_Integer NbSU1,
47                                              const Standard_Integer NbSV1,
48                                              const Handle(Adaptor3d_HSurface)& S2,
49                                              const Standard_Integer NbSU2,
50                                              const Standard_Integer NbSV2)
51 {
52   myNbSU1 = NbSU1;
53   myNbSV1 = NbSV1;
54   myNbSU2 = NbSU2; 
55   myNbSV2 = NbSV2; 
56   mySurf1 = S1;
57   mySurf2 = S2;
58   done = Standard_False;
59   TSectionLines.Init(1000);
60   TTangentZones.Init(10000);
61   Perform();
62 }
63
64 void IntPolyh_Intersection::Perform() { 
65
66   done = Standard_True;
67
68   Standard_Boolean isStdDone = Standard_False;
69   Standard_Boolean isAdvDone = Standard_False;
70   Standard_Integer nbCouplesStd = 0;
71   Standard_Integer nbCouplesAdv = 0;
72   
73   IntPolyh_PMaillageAffinage aPMaillageStd = 0;
74   IntPolyh_PMaillageAffinage aPMaillageFF = 0;
75   IntPolyh_PMaillageAffinage aPMaillageFR = 0;
76   IntPolyh_PMaillageAffinage aPMaillageRF = 0;
77   IntPolyh_PMaillageAffinage aPMaillageRR = 0;
78
79   isStdDone = PerformStd(aPMaillageStd,nbCouplesStd);
80
81   // default interference done well, use it
82   if(isStdDone && nbCouplesStd > 10) {
83     aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
84   }
85   // default interference done, but too few interferences foud;
86   // use advanced interference
87   else if(isStdDone && nbCouplesStd <= 10) {
88     isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
89
90     // advanced interference found
91     if(isAdvDone && nbCouplesAdv > 10) {
92       aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
93       aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
94       aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
95       aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
96     }
97     else {
98       // use result of default
99       if(nbCouplesStd > 0)
100         aPMaillageStd->StartPointsChain(TSectionLines, TTangentZones);
101     }
102   }
103   // default interference faild, use advanced
104   else {
105     //       isAdvDone = PerformAdv(aPMaillageFF,aPMaillageFR,aPMaillageRF,aPMaillageRR,nbCouplesAdv);
106
107     //       if(isAdvDone && nbCouplesAdv > 0) {cout << "4adv done, nbc: " << nbCouplesAdv << endl;
108     //  aPMaillageFF->StartPointsChain(TSectionLines,TTangentZones);
109     //  aPMaillageFR->StartPointsChain(TSectionLines,TTangentZones);
110     //  aPMaillageRF->StartPointsChain(TSectionLines,TTangentZones);
111     //  aPMaillageRR->StartPointsChain(TSectionLines,TTangentZones);
112     //       }
113   }
114
115   // accept result
116   nbsectionlines = TSectionLines.NbItems();
117   nbtangentzones = TTangentZones.NbItems();
118
119   // clean up
120   if(aPMaillageStd) delete aPMaillageStd;
121   if(aPMaillageFF) delete aPMaillageFF;
122   if(aPMaillageFR) delete aPMaillageFR;
123   if(aPMaillageRF) delete aPMaillageRF;
124   if(aPMaillageRR) delete aPMaillageRR;
125
126   // verify
127   if(!isStdDone && !isAdvDone)
128     done = Standard_False;
129 }
130
131
132 Standard_Boolean IntPolyh_Intersection::IsDone() const {
133   return(done);
134 }
135
136
137 Standard_Integer IntPolyh_Intersection::NbSectionLines() const { 
138   return(nbsectionlines);
139 }
140
141
142 Standard_Integer IntPolyh_Intersection::NbPointsInLine(const Standard_Integer IndexLine) const { 
143   
144   return(TSectionLines[IndexLine-1].NbStartPoints());
145 }
146
147
148 Standard_Integer IntPolyh_Intersection::NbPointsInTangentZone(const Standard_Integer) const {   
149   //-- IndexLine--;     (pas implemente) Attention : Tableaux de 0 a n-1 
150   // eap
151   // return(TTangentZones.NbTangentZones());
152   return 1;
153 }
154
155
156 Standard_Integer IntPolyh_Intersection::NbTangentZones() const { 
157   return(nbtangentzones);
158 }
159
160
161 void IntPolyh_Intersection::GetLinePoint(const Standard_Integer Indexl,
162                                  const Standard_Integer Indexp,
163                                  Standard_Real &x,
164                                  Standard_Real &y,
165                                  Standard_Real &z,
166                                  Standard_Real &u1,
167                                  Standard_Real &v1,
168                                  Standard_Real &u2,
169                                  Standard_Real &v2,
170                                  Standard_Real &incidence) const { 
171   const IntPolyh_SectionLine  &msl=TSectionLines[Indexl-1];
172   const IntPolyh_StartPoint   &sp=msl[Indexp-1];
173   x=sp.X();
174   y=sp.Y();
175   z=sp.Z();
176   u1=sp.U1();
177   v1=sp.V1();
178   u2=sp.U2();
179   v2=sp.V2();
180   incidence=sp.GetAngle();
181 }
182
183
184 void IntPolyh_Intersection::GetTangentZonePoint(const Standard_Integer Indexz,
185                                         const Standard_Integer /*Indexp*/,
186                                         Standard_Real &x,
187                                         Standard_Real &y,
188                                         Standard_Real &z,
189                                         Standard_Real &u1,
190                                         Standard_Real &v1,
191                                         Standard_Real &u2,
192                                         Standard_Real &v2) const { 
193   //--   Indexz--;    tableaux C
194   // eap
195   //const IntPolyh_StartPoint   &sp=TTangentZones[Indexp-1];
196   const IntPolyh_StartPoint   &sp=TTangentZones[Indexz-1];
197   x=sp.X();
198   y=sp.Y();
199   z=sp.Z();
200   u1=sp.U1();
201   v1=sp.V1();
202   u2=sp.U2();
203   v2=sp.V2();
204 }
205
206 //  Modified by skv - Thu Sep 25 18:07:41 2003 OCC567 Begin
207 //=======================================================================
208 //function : PerformMaillage
209 //purpose  : Computes MaillageAffinage
210 //=======================================================================
211 Standard_Boolean IntPolyh_Intersection::PerformMaillage
212                  (const Standard_Boolean            isFirstFwd,
213                   const Standard_Boolean            isSecondFwd,
214                         IntPolyh_PMaillageAffinage &theMaillageS)
215 {
216   if (myNbSU1 == -1)
217     theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, mySurf2, MYPRINT);
218   else
219     theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, myNbSU1, myNbSV1,
220                                                  mySurf2, myNbSU2, myNbSV2,
221                                                  MYPRINT);
222
223   theMaillageS->FillArrayOfPnt(1, isFirstFwd);
224   theMaillageS->FillArrayOfPnt(2, isSecondFwd);
225   
226   
227   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
228   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
229                           xx0, yy0, zz0, xx1, yy1, zz1);
230   
231   theMaillageS->FillArrayOfEdges(1);
232   theMaillageS->FillArrayOfEdges(2);
233
234   theMaillageS->FillArrayOfTriangles(1);
235   theMaillageS->FillArrayOfTriangles(2);
236   
237   theMaillageS->LinkEdges2Triangles();
238   
239   theMaillageS->TrianglesDeflectionsRefinementBSB();
240
241   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
242
243   // if too many intersections, consider surfaces parallel (eap)
244   if(FinTTC > 200 &&
245      (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbItems() ||
246       FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbItems()) ) {
247     return Standard_False;
248   }
249
250   return Standard_True;
251 }
252
253 //=======================================================================
254 //function : PerformMaillage
255 //purpose  : Computes MaillageAffinage
256 //=======================================================================
257 Standard_Boolean IntPolyh_Intersection::PerformMaillage(IntPolyh_PMaillageAffinage &theMaillageS)
258 {
259   if (myNbSU1 == -1)
260     theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, mySurf2, MYPRINT);
261   else
262     theMaillageS = new IntPolyh_MaillageAffinage(mySurf1, myNbSU1, myNbSV1,
263                                                  mySurf2, myNbSU2, myNbSV2,
264                                                  MYPRINT);
265
266   theMaillageS->FillArrayOfPnt(1);
267   theMaillageS->FillArrayOfPnt(2);
268   
269   
270   Standard_Real xx0,yy0,zz0,xx1,yy1,zz1;
271   theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
272                           xx0, yy0, zz0, xx1, yy1, zz1);
273   
274   theMaillageS->FillArrayOfEdges(1);
275   theMaillageS->FillArrayOfEdges(2);
276
277   theMaillageS->FillArrayOfTriangles(1);
278   theMaillageS->FillArrayOfTriangles(2);
279   
280   theMaillageS->LinkEdges2Triangles();
281   
282   theMaillageS->TrianglesDeflectionsRefinementBSB();
283
284   Standard_Integer FinTTC = theMaillageS->TriangleCompare();
285
286   if( FinTTC == 0 ) {
287     Standard_Boolean myZone = Standard_True;
288     theMaillageS->SetEnlargeZone( myZone );
289     theMaillageS->FillArrayOfPnt(1);
290     theMaillageS->FillArrayOfPnt(2);
291     theMaillageS->CommonBox(theMaillageS->GetBox(1), theMaillageS->GetBox(2),
292                             xx0, yy0, zz0, xx1, yy1, zz1);
293     theMaillageS->FillArrayOfEdges(1);
294     theMaillageS->FillArrayOfEdges(2);
295     theMaillageS->FillArrayOfTriangles(1);
296     theMaillageS->FillArrayOfTriangles(2);
297     theMaillageS->LinkEdges2Triangles();
298     theMaillageS->TrianglesDeflectionsRefinementBSB();
299     FinTTC = theMaillageS->TriangleCompare();
300     myZone = Standard_False;
301     theMaillageS->SetEnlargeZone( myZone );
302   }
303
304   /*
305   // if too many intersections, consider surfaces parallel (eap)
306   if(FinTTC > 200 &&
307      (FinTTC >= theMaillageS->GetArrayOfTriangles(1).NbTriangles() ||
308       FinTTC >= theMaillageS->GetArrayOfTriangles(2).NbTriangles()) ) {
309     return Standard_False;
310   }
311   */
312   
313   return Standard_True;
314 }
315
316 //=======================================================================
317 //function : MergeCouples
318 //purpose  : This method analyzes arrays to find same couples. If some 
319 //           are detected it leaves the couple in only one array 
320 //           deleting from others.
321 //=======================================================================
322
323 void IntPolyh_Intersection::MergeCouples
324                             (IntPolyh_ArrayOfCouples &anArrayFF,
325                              IntPolyh_ArrayOfCouples &anArrayFR,
326                              IntPolyh_ArrayOfCouples &anArrayRF,
327                              IntPolyh_ArrayOfCouples &anArrayRR) const
328 {
329   // Step 1: Sorting arrays.
330   IntPolyh_ArrayOfCouples *anArrays[4];
331   Standard_Integer         aNbCouples[4];
332   Standard_Integer         i;
333   IntPolyh_ArrayOfCouples *aTmpPtr;
334   Standard_Integer         aTmpNbr;
335
336   anArrays[0] = &anArrayFF;
337   anArrays[1] = &anArrayFR;
338   anArrays[2] = &anArrayRF;
339   anArrays[3] = &anArrayRR;
340
341   for (i = 0; i < 4; i++)
342     aNbCouples[i] = anArrays[i]->NbItems();
343
344   Standard_Boolean isChanged = Standard_True;
345
346   while (isChanged) {
347     isChanged = Standard_False;
348
349     for (i = 0; i < 3; i++) {
350       if (aNbCouples[i] < aNbCouples[i + 1]) {
351         aTmpPtr           = anArrays[i];
352         anArrays[i]       = anArrays[i + 1];
353         anArrays[i + 1]   = aTmpPtr;
354         aTmpNbr           = aNbCouples[i];
355         aNbCouples[i]     = aNbCouples[i + 1];
356         aNbCouples[i + 1] = aTmpNbr;
357         isChanged         = Standard_True;
358       }
359     }
360   }
361
362   // Step 2: Searching for same couples.
363   Standard_Integer j;
364   Standard_Integer indC1;
365   Standard_Integer indC2;
366
367   for (i = 0; i < 3; i++) {
368     for (j = i + 1; j < 4; j++) {
369       for (indC1 = 1; indC1 <= aNbCouples[i]; indC1++) {
370         IntPolyh_Couple &aCouple1 = anArrays[i]->ChangeValue(indC1);
371
372         if (aCouple1.AnalyseFlagValue() == 1)
373           continue;
374
375         for (indC2 = 1; indC2 <= aNbCouples[j]; indC2++) {
376           IntPolyh_Couple &aCouple2 = anArrays[j]->ChangeValue(indC2);
377
378           if (aCouple2.AnalyseFlagValue() == 1)
379             continue;
380
381           if (aCouple1.FirstValue()  == aCouple2.FirstValue() &&
382               aCouple1.SecondValue() == aCouple2.SecondValue()) {
383             aCouple2.SetAnalyseFlag(1);
384           }
385         }
386       }
387     }
388   }
389 }
390 //  Modified by skv - Thu Sep 25 18:07:42 2003 OCC567 End
391
392 Standard_Boolean IntPolyh_Intersection::PerformStd(IntPolyh_PMaillageAffinage& MaillageS,
393                                                    Standard_Integer&           NbCouples)
394 {
395   Standard_Boolean isdone = PerformMaillage(MaillageS);
396   NbCouples = (isdone) ? (MaillageS->GetArrayOfCouples().NbItems()) : 0;
397   return isdone;
398 }
399
400 Standard_Boolean IntPolyh_Intersection::PerformAdv(IntPolyh_PMaillageAffinage& MaillageFF,
401                                                    IntPolyh_PMaillageAffinage& MaillageFR,
402                                                    IntPolyh_PMaillageAffinage& MaillageRF,
403                                                    IntPolyh_PMaillageAffinage& MaillageRR,
404                                                    Standard_Integer&           NbCouples)
405 {
406   Standard_Boolean isdone = Standard_True;
407   NbCouples = 0;
408
409   if(!PerformMaillage(Standard_True,Standard_False,MaillageFR) ||
410      !PerformMaillage(Standard_False,Standard_True,MaillageRF) ||
411      !PerformMaillage(Standard_True,Standard_True,MaillageFF)  ||
412      !PerformMaillage(Standard_False,Standard_False,MaillageRR) )
413     isdone = Standard_False; 
414
415   if(isdone) {
416     NbCouples = MaillageFF->GetArrayOfCouples().NbItems() +
417       MaillageFR->GetArrayOfCouples().NbItems() +
418         MaillageRF->GetArrayOfCouples().NbItems() +
419           MaillageRR->GetArrayOfCouples().NbItems();
420
421     if(NbCouples > 0)
422       MergeCouples(MaillageFF->GetArrayOfCouples(),MaillageFR->GetArrayOfCouples(),
423                    MaillageRF->GetArrayOfCouples(),MaillageRR->GetArrayOfCouples());
424   }
425   return isdone;
426 }