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