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