0024043: Performance improvements: Modeling Algorithms
[occt.git] / src / Intf / Intf_InterferencePolygon2d.cxx
1 // Created on: 1991-06-24
2 // Created by: Didier PIFFAULT
3 // Copyright (c) -1999 Matra Datavision
4 // Copyright (c) 1991-1999 Matra Datavision
5 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 //
7 // The content of this file is subject to the Open CASCADE Technology Public
8 // License Version 6.5 (the "License"). You may not use the content of this file
9 // except in compliance with the License. Please obtain a copy of the License
10 // at http://www.opencascade.org and read it completely before using this file.
11 //
12 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
13 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 //
15 // The Original Code and all software distributed under the License is
16 // distributed on an "AS IS" basis, without warranty of any kind, and the
17 // Initial Developer hereby disclaims all such warranties, including without
18 // limitation, any warranties of merchantability, fitness for a particular
19 // purpose or non-infringement. Please see the License for the specific terms
20 // and conditions governing the rights and limitations under the License.
21
22
23 #include <Intf_InterferencePolygon2d.ixx>
24
25 #include <gp_Pnt2d.hxx>
26 #include <Bnd_Box2d.hxx>
27 #include <Intf_SectionPoint.hxx>
28 #include <Intf_SeqOfSectionPoint.hxx>
29 #include <Intf_TangentZone.hxx>
30 #include <Intf_SeqOfTangentZone.hxx>
31 #include <Precision.hxx>
32 #include <TColStd_ListOfInteger.hxx>
33
34 // Angular precision (sinus) below that value two right segments
35 // are considered as having a potential zone of tangency.
36 namespace
37 {
38   static const Standard_Real PRCANG = Precision::Angular();
39 };
40
41 //=======================================================================
42 //function : Intf_InterferencePolygon2d
43 //purpose  : constructor empty
44 //=======================================================================
45
46 Intf_InterferencePolygon2d::Intf_InterferencePolygon2d()
47 : Intf_Interference (Standard_False),
48   oClos (Standard_False),
49   tClos (Standard_False),
50   nbso (0)
51 {}
52
53 //=======================================================================
54 //function : Intf_InterferencePolygon2d
55 //purpose  : Constructor of the interference beetween two Polygon.
56 //=======================================================================
57
58 Intf_InterferencePolygon2d::Intf_InterferencePolygon2d
59   (const Intf_Polygon2d& Obje1, const Intf_Polygon2d& Obje2)
60 : Intf_Interference (Standard_False),
61   oClos (Standard_False),
62   tClos (Standard_False),
63   nbso (0)
64 {
65   if (!Obje1.Bounding().IsOut(Obje2.Bounding())) {
66     Tolerance=Obje1.DeflectionOverEstimation()+
67               Obje2.DeflectionOverEstimation();
68     if (Tolerance==0.)
69       Tolerance=Epsilon(1000.);
70     nbso=Obje1.NbSegments();
71     oClos=Obje1.Closed();
72     tClos=Obje2.Closed();
73     Interference(Obje1, Obje2);
74     Clean();
75   }
76 }
77
78
79 //=======================================================================
80 //function : Intf_InterferencePolygon2d
81 //purpose  : Constructor of the auto interference of a Polygon.
82 //=======================================================================
83
84 Intf_InterferencePolygon2d::Intf_InterferencePolygon2d
85   (const Intf_Polygon2d& Obje)
86 : Intf_Interference (Standard_True),
87   oClos (Standard_False),
88   tClos (Standard_False),
89   nbso (0)
90 {
91   Tolerance=Obje.DeflectionOverEstimation()*2;
92   if (Tolerance==0.)
93     Tolerance=Epsilon(1000.);
94   oClos=Obje.Closed();
95   tClos=oClos;
96   Interference(Obje);
97   Clean();
98 }
99
100 //=======================================================================
101 //function : Perform
102 //purpose  : 
103 //=======================================================================
104
105 void Intf_InterferencePolygon2d::Perform
106   (const Intf_Polygon2d& Obje1, const Intf_Polygon2d& Obje2)
107 {
108   SelfInterference(Standard_False);
109   if (!Obje1.Bounding().IsOut(Obje2.Bounding())) {
110     Tolerance=Obje1.DeflectionOverEstimation()+
111               Obje2.DeflectionOverEstimation();
112     if (Tolerance==0.)
113       Tolerance=Epsilon(1000.);
114     nbso=Obje1.NbSegments();
115     oClos=Obje1.Closed();
116     tClos=Obje2.Closed();
117     Interference(Obje1, Obje2);
118     Clean();
119   }
120 }
121
122 //=======================================================================
123 //function : Perform
124 //purpose  : 
125 //=======================================================================
126
127 void Intf_InterferencePolygon2d::Perform 
128   (const Intf_Polygon2d& Obje)
129 {
130   SelfInterference(Standard_True);
131   Tolerance=Obje.DeflectionOverEstimation()*2;
132   if (Tolerance==0.)
133     Tolerance=Epsilon(1000.);
134   oClos=Obje.Closed();
135   tClos=oClos;
136   Interference(Obje);
137   Clean();
138 }
139
140 //=======================================================================
141 //function : Pnt2dValue
142 //purpose  : Give the section point of range Index in the interference.
143 //=======================================================================
144
145 gp_Pnt2d Intf_InterferencePolygon2d::Pnt2dValue
146   (const Standard_Integer Index) const
147 {
148   return gp_Pnt2d((mySPoins(Index)).Pnt().X(),
149                   (mySPoins(Index)).Pnt().Y());
150 }
151
152
153 //=======================================================================
154 //function : Interference
155 //purpose  : 
156 //=======================================================================
157
158 void Intf_InterferencePolygon2d::Interference
159   (const Intf_Polygon2d& Obje1,
160    const Intf_Polygon2d& Obje2)
161 {
162   Bnd_Box2d bSO;
163   Bnd_Box2d bST;
164
165   Standard_Integer iObje1, iObje2, n1 = nbso, n2 = Obje2.NbSegments();
166   Standard_Real d1 = Obje1.DeflectionOverEstimation(),
167     d2 = Obje2.DeflectionOverEstimation();
168
169   gp_Pnt2d p1b, p1e, p2b, p2e;
170   for (iObje1=1; iObje1<=n1; iObje1++)
171   {
172     bSO.SetVoid();
173     Obje1.Segment(iObje1,p1b,p1e);
174     bSO.Add(p1b);
175     bSO.Add(p1e);
176     bSO.Enlarge(d1);
177     if (!Obje2.Bounding().IsOut(bSO)) {
178       for (iObje2=1; iObje2<=n2; iObje2++) {
179         bST.SetVoid();
180         Obje2.Segment(iObje2,p2b,p2e);
181         bST.Add(p2b);
182         bST.Add(p2e);
183         bST.Enlarge(d2);
184         if (!bSO.IsOut(bST))
185           Intersect(iObje1, iObje2, p1b, p1e, p2b, p2e);
186       }
187     }
188   }
189 }
190
191 //=======================================================================
192 //function : Interference
193 //purpose  : 
194 //=======================================================================
195
196 void Intf_InterferencePolygon2d::Interference
197   (const Intf_Polygon2d& Obje)
198 {
199   Bnd_Box2d bSO;
200   Bnd_Box2d bST;
201
202   Standard_Integer iObje1, iObje2, n = Obje.NbSegments();
203   Standard_Real d = Obje.DeflectionOverEstimation();
204
205   gp_Pnt2d p1b, p1e, p2b, p2e;
206   for (iObje1=1; iObje1<=n; iObje1++) {
207     bSO.SetVoid();
208     Obje.Segment(iObje1,p1b,p1e);
209     bSO.Add(p1b);
210     bSO.Add(p1e);
211     bSO.Enlarge(d);
212     if (!Obje.Bounding().IsOut(bSO)) {
213       for (iObje2=iObje1+1;iObje2<=n;iObje2++){
214         bST.SetVoid();
215         Obje.Segment(iObje2,p2b,p2e);
216         bST.Add(p2b);
217         bST.Add(p2e);
218         bST.Enlarge(d);
219         if (!bSO.IsOut(bST))
220           Intersect(iObje1, iObje2, p1b, p1e, p2b, p2e);
221       }
222     }
223   }
224 }
225
226
227 //=======================================================================
228 //function : Clean
229 //purpose  : 
230 //=======================================================================
231
232 void Intf_InterferencePolygon2d::Clean()
233 {
234
235 // The zones of tangency that concerns only one couple of segments are
236 // conserved if the angle between the segments is less than <PRCANG> and
237 // if there is no real point of intersection EDGE/EDGE:
238   Standard_Integer nbIt=myTZones.Length();
239   Standard_Integer decal=0;
240   Standard_Integer addr1, addr2;
241   Intf_PIType      dim1, dim2;
242   Standard_Real    par;
243   Standard_Integer tsp, tsps;
244   Standard_Integer lpi, ltz;
245   Standard_Boolean Only1Seg=Standard_False;
246
247 #define PI1 (myTZones(ltz-decal).GetPoint(lpi))
248 #define PI2 (myTZones(ltz-decal).GetPoint(tsp))
249
250   for (ltz=1; ltz<=nbIt; ltz++) {
251     tsp=tsps=0;
252     Standard_Real pr1mi,pr1ma,pr2mi,pr2ma,delta1,delta2;
253     myTZones(ltz-decal).ParamOnFirst(pr1mi,pr1ma);
254     delta1=pr1ma-pr1mi;
255     myTZones(ltz-decal).ParamOnSecond(pr2mi,pr2ma);
256     delta2=pr2ma-pr2mi;
257     if (delta1<1. && delta2<1.) Only1Seg=Standard_True;
258     if (delta1==0. || delta2==0.) Only1Seg=Standard_True;
259
260     for (lpi=1; lpi<=myTZones(ltz-decal).NumberOfPoints(); lpi++) {
261       if (PI1.Incidence()<=PRCANG) {tsp=tsps=0;break;}
262       PI1.InfoFirst(dim1,addr1,par);
263       PI1.InfoSecond(dim2,addr2,par);
264       if (dim1==Intf_EDGE && dim2==Intf_EDGE) {
265         tsps=0;
266         if (tsp>0) {
267           tsp=0;
268           Only1Seg=Standard_False;
269           break;
270         }
271         tsp=lpi;
272       }
273       else if (dim1!=Intf_EXTERNAL && dim2!=Intf_EXTERNAL) {
274         tsps=lpi;
275       }
276     }
277     if (tsp>0) {
278       mySPoins.Append(myTZones(ltz-decal).GetPoint(tsp));
279       myTZones.Remove(ltz-decal);
280       decal++;
281     }
282     else if (Only1Seg && tsps!=0) {
283       mySPoins.Append(myTZones(ltz-decal).GetPoint(tsps));
284       myTZones.Remove(ltz-decal);
285       decal++;
286     }
287   }
288
289
290 // The points of intersection located in the tangency zone are
291 // removed from the list :
292   nbIt=mySPoins.Length();
293   decal=0;
294
295   for (lpi=1; lpi<=nbIt; lpi++) {
296     for (ltz=1; ltz<=myTZones.Length(); ltz++) {
297       if (myTZones(ltz).RangeContains(mySPoins(lpi-decal))) {
298         mySPoins.Remove(lpi-decal);
299         decal++;
300         break;
301       }
302     }
303   }
304 }
305
306
307 //=======================================================================
308 //function : Intersect
309 //purpose  : 
310 //=======================================================================
311
312 void Intf_InterferencePolygon2d::Intersect
313   (const Standard_Integer iObje1, const Standard_Integer iObje2,
314    const gp_Pnt2d& BegO, const gp_Pnt2d& EndO,
315    const gp_Pnt2d& BegT, const gp_Pnt2d& EndT)
316 {
317   if(SelfIntf) { 
318     if(Abs(iObje1-iObje2)<=1) return;  //-- Ajout du 15 jan 98 
319   }
320
321   Standard_Integer nbpi=0;
322   Standard_Real parO[8];
323   Standard_Real parT[8];
324   Intf_SeqOfSectionPoint thePi;
325   gp_XY segT =EndT.XY()-BegT.XY();
326   gp_XY segO =EndO.XY()-BegO.XY();
327
328 // If the length of segment is zero, nothing is done
329   Standard_Real lgT =Sqrt(segT*segT);
330   if (lgT<=0.) return;
331   Standard_Real lgO =Sqrt(segO*segO);
332   if (lgO<=0.) return;
333
334 // Direction of parsing of segments
335   Standard_Real sigPS=(segO*segT)>0.0 ? 1.0 : -1.0;
336
337 // Precision of calculation
338   Standard_Real floatgap=Epsilon(lgO+lgT);
339
340 // Angle between two straight lines and radius of interference
341   Standard_Real sinTeta=(segO.CrossMagnitude(segT)/lgO)/lgT;
342   Standard_Real rayIntf=0.;
343   if (sinTeta>0.) rayIntf=Tolerance/sinTeta;
344           
345 // Interference <begO> <segT>
346   Standard_Real dbOT=((BegO.XY()-BegT.XY())^segT)/lgT;
347   Standard_Real dbObT=BegO.Distance(BegT);
348   Standard_Real dbOeT=BegO.Distance(EndT);
349   if (Abs(dbOT)<=Tolerance) {
350     if (dbObT<=Tolerance) {
351       nbpi++;
352       parO[nbpi]=0.;parT[nbpi]=0.;
353       thePi.Append(Intf_SectionPoint(BegO,Intf_VERTEX,iObje1,0.,
354                                      Intf_VERTEX,iObje2,0.,sinTeta));
355     }
356     if (dbOeT<=Tolerance) {
357       nbpi++;
358       parO[nbpi]=0.;parT[nbpi]=1.;
359       thePi.Append(Intf_SectionPoint(BegO,Intf_VERTEX,iObje1,0.,
360                                      Intf_VERTEX,iObje2+1,0.,sinTeta));
361     }
362     if (dbObT>Tolerance && dbOeT>Tolerance &&
363         dbObT+dbOeT<=(lgT+Tolerance)) {
364       nbpi++;
365       parO[nbpi]=0.;parT[nbpi]=dbObT/lgT;
366       thePi.Append(Intf_SectionPoint(BegO,Intf_VERTEX,iObje1,0.,
367                                      Intf_EDGE,iObje2,parT[nbpi],sinTeta));
368     }
369   }
370   
371 // Interference <endO> <segT>
372   Standard_Real deOT=((EndO.XY()-BegT.XY())^segT)/lgT;
373   Standard_Real deObT=EndO.Distance(BegT);
374   Standard_Real deOeT=EndO.Distance(EndT);
375   if (Abs(deOT)<=Tolerance) {
376     if (deObT<=Tolerance) {
377       nbpi++;
378       parO[nbpi]=1.;parT[nbpi]=0.;
379       thePi.Append(Intf_SectionPoint(EndO,Intf_VERTEX,iObje1+1,0.,
380                                      Intf_VERTEX,iObje2,0.,sinTeta));
381     }
382     if (deOeT<=Tolerance) {
383       nbpi++;
384       parO[nbpi]=1.;parT[nbpi]=1.;
385       thePi.Append(Intf_SectionPoint(EndO,Intf_VERTEX,iObje1+1,0.,
386                                      Intf_VERTEX,iObje2+1,0.,sinTeta));
387     }
388     if (deObT>Tolerance && deOeT>Tolerance &&
389         deObT+deOeT<=(lgT+Tolerance)) {
390       nbpi++;
391       parO[nbpi]=1.;parT[nbpi]=deObT/lgT;
392       thePi.Append(Intf_SectionPoint(EndO,Intf_VERTEX,iObje1+1,0.,
393                                      Intf_EDGE,iObje2,parT[nbpi],sinTeta));
394     }
395   }
396   
397 // Interference <begT> <segO>
398   Standard_Real dbTO=((BegT.XY()-BegO.XY())^segO)/lgO;
399   if (Abs(dbTO)<=Tolerance) {
400     if (dbObT>Tolerance && deObT>Tolerance &&
401         dbObT+deObT<=(lgO+Tolerance)) {
402       nbpi++;
403       parO[nbpi]=dbObT/lgO;parT[nbpi]=0.;
404       thePi.Append(Intf_SectionPoint(BegT,Intf_EDGE,iObje1,parO[nbpi],
405                                      Intf_VERTEX,iObje2,0.,sinTeta));
406     }
407   }
408
409 // Interference <endT> <segO>
410   Standard_Real deTO=((EndT.XY()-BegO.XY())^segO)/lgO;
411   if (Abs(deTO)<=Tolerance) {
412     if (dbOeT>Tolerance && deOeT>Tolerance &&
413         dbOeT+deOeT<=(lgO+Tolerance)) {
414       nbpi++;
415       parO[nbpi]=dbOeT/lgO;parT[nbpi]=1.;
416       thePi.Append(Intf_SectionPoint(EndT,Intf_EDGE,iObje1,parO[nbpi],
417                                      Intf_VERTEX,iObje2+1,0.,sinTeta));
418     }
419   }
420
421   Standard_Boolean edgeSP=Standard_False;
422   Standard_Real parOSP=0, parTSP=0;
423
424   if (Abs(dbOT-deOT)>floatgap && Abs(dbTO-deTO)>floatgap) {
425     parOSP=dbOT/(dbOT-deOT);
426     parTSP=dbTO/(dbTO-deTO);
427     if (dbOT*deOT<=0. && dbTO*deTO<=0.) {
428       edgeSP=Standard_True;
429     }
430     else if (nbpi==0) return;
431
432 // If there is no interference it is necessary to take the points segment by segment
433     if (nbpi==0 && sinTeta>PRCANG) {
434       nbpi++;
435       parO[nbpi]=parOSP;
436       parT[nbpi]=parTSP;
437       thePi.Append(Intf_SectionPoint(gp_Pnt2d (BegO.X()+ (segO.X()*parOSP),
438                                                BegO.Y()+ (segO.Y()*parOSP)),
439                                      Intf_EDGE,iObje1,parOSP,
440                                      Intf_EDGE,iObje2,parTSP,sinTeta));
441     }
442
443 // Otherwise it is required to check if there is no other
444     else if (rayIntf>=Tolerance) {
445       Standard_Real deltaO=rayIntf/lgO;
446       Standard_Real deltaT=rayIntf/lgT;
447       Standard_Real x, y;
448       Standard_Real parOdeb=parOSP-deltaO;
449       Standard_Real parOfin=parOSP+deltaO;
450       Standard_Real parTdeb=parTSP-sigPS*deltaT;
451       Standard_Real parTfin=parTSP+sigPS*deltaT;
452       if (nbpi==0) {
453         parO[1]=parOdeb;
454         parO[2]=parOfin;
455         parT[1]=parTdeb;
456         parT[2]=parTfin;
457         while (nbpi<2) {
458           nbpi++;
459           x=BegO.X()+ (segO.X()*parO[nbpi]);
460           y=BegO.Y()+ (segO.Y()*parO[nbpi]);
461           thePi.Append(Intf_SectionPoint(gp_Pnt2d(x, y),
462                                          Intf_EXTERNAL, iObje1, parO[nbpi],
463                                          Intf_EXTERNAL, iObje2, parT[nbpi],
464                                          sinTeta));
465         }
466       }
467       else {  //nbpi>0
468         if (nbpi==1) {
469           Standard_Boolean ok=Standard_True;
470           if (0.<parOdeb && parOdeb<1. && 0.<parTdeb && parTdeb<1. ) {
471             parO[nbpi+1]=parOdeb;
472             parT[nbpi+1]=parTdeb;
473           }
474           else if (0.<parOfin && parOfin<1. && 0.<parTfin && parTfin<1. ) {
475             parO[nbpi+1]= parOfin;
476             parT[nbpi+1]= parTfin;
477           }
478           else {
479             ok=Standard_False;
480           }
481
482           if (ok) {
483             x=BegO.X()+ (segO.X()*parO[nbpi+1]);
484             y=BegO.Y()+ (segO.Y()*parO[nbpi+1]);
485             if (thePi(1).Pnt().Distance(gp_Pnt(x, y, 0)) >= (Tolerance/4.)) {
486               nbpi++;
487               thePi.Append(Intf_SectionPoint(gp_Pnt2d(x, y),
488                                              Intf_EXTERNAL, iObje1, parO[nbpi],
489                                              Intf_EXTERNAL, iObje2, parT[nbpi],
490                                              sinTeta));
491             }
492           }
493         }
494         else { // plus d une singularite
495           Standard_Real parOmin=parO[1];
496           Standard_Real parOmax=parO[1];
497           Standard_Real parTmin=parT[1];
498           Standard_Real parTmax=parT[1];
499           for (Standard_Integer i=2; i<=nbpi; i++) {
500             parOmin=Min(parOmin, parO[i]);
501             parOmax=Max(parOmax, parO[i]);
502             parTmin=Min(parTmin, parT[i]);
503             parTmax=Max(parTmax, parT[i]);
504           }
505
506           Standard_Real    delta;
507           if (parOdeb<0.) {
508             delta=-parOdeb;
509             parOdeb=0.;
510             parTdeb=parTdeb+sigPS*(delta*(deltaT/deltaO));
511           }
512           if (parOfin>1.) {
513             delta=parOfin-1.;
514             parOfin=1.;
515             parTfin=parTfin-sigPS*(delta*(deltaT/deltaO));
516           }
517           if (sigPS>0.) {
518             if (parTdeb<0.) {
519               delta=-parTdeb;
520               parTdeb=0.;
521               parOdeb=parOdeb+delta*(deltaO/deltaT);
522             }
523             if (parTfin>1.) {
524               delta=parTfin-1.;
525               parTfin=1.;
526               parOfin=parOfin-delta*(deltaO/deltaT);
527             }
528           }
529           else {
530             if (parTdeb>1.) {
531               delta=parTdeb-1.;
532               parTdeb=1.;
533               parOdeb=parOdeb+delta*(deltaO/deltaT);
534             }
535             if (parTfin<0.) {
536               delta=-parTfin;
537               parTfin=0.;
538               parOfin=parOfin-delta*(deltaO/deltaT);
539             }
540           }
541
542           if ((parOdeb<parOmin && parOmin>0.) || 
543               (sigPS>0. && parTdeb<parTmin && parTmin>0.) || 
544               (sigPS<0. && parTdeb>parTmax && parTmax<1.)) {
545             nbpi++;
546             parO[nbpi]=Max(0., Min(1., parOdeb));
547             parT[nbpi]=Max(0., Min(1., parTdeb));
548             x=BegO.X()+ (segO.X()*parO[nbpi]);
549             y=BegO.Y()+ (segO.Y()*parO[nbpi]);
550             thePi.Append(Intf_SectionPoint(gp_Pnt2d(x, y),
551                                            Intf_EXTERNAL, iObje1, parO[nbpi],
552                                            Intf_EXTERNAL, iObje2, parT[nbpi],
553                                            sinTeta));
554           }
555
556           if ((parOfin>parOmax && parOmax<1.) || 
557               (sigPS<0. && parTfin<parTmin && parTmin>0.) || 
558               (sigPS>0. && parTfin>parTmax && parTmax<1.)) {
559             nbpi++;
560             parO[nbpi]=Min(1., Max(0., parOfin));
561             parT[nbpi]=Min(1., Max(0., parTfin));
562             x=BegO.X()+ (segO.X()*parO[nbpi]);
563             y=BegO.Y()+ (segO.Y()*parO[nbpi]);
564             thePi.Append(Intf_SectionPoint(gp_Pnt2d(x, y),
565                                            Intf_EXTERNAL, iObje1, parO[nbpi],
566                                            Intf_EXTERNAL, iObje2, parT[nbpi],
567                                            sinTeta));
568           }
569         }
570       }
571     }
572   }
573   
574   //-- lbr : The points too close to each other are suspended
575   Standard_Boolean suppr;
576   do { 
577     suppr=Standard_False;
578     for(Standard_Integer i=2; suppr==Standard_False && i<=nbpi; i++) { 
579       const gp_Pnt& Pim1 = thePi(i-1).Pnt();
580       const gp_Pnt& Pi   = thePi(i).Pnt();
581       Standard_Real d=Pi.Distance(Pim1);
582       d*=50.0;
583       if(d<lgT && d<lgO) { 
584         for(Standard_Integer j=i; j<nbpi; j++) { 
585           thePi(j)=thePi(j+1);
586         }
587         nbpi--;
588         suppr=Standard_True;
589       }
590     }
591   }
592   while(suppr==Standard_True);
593   
594   
595
596
597
598   
599   if (nbpi==1) {
600     if (edgeSP) {
601       thePi(1)=Intf_SectionPoint(gp_Pnt2d (BegO.X()+ (segO.X()*parOSP),
602                                            BegO.Y()+ (segO.Y()*parOSP)),
603                                  Intf_EDGE,iObje1,parOSP,
604                                  Intf_EDGE,iObje2,parTSP,sinTeta);
605       parO[1]=parOSP;
606       parT[1]=parTSP;
607     }
608     if (!SelfIntf) {
609       Standard_Boolean contains = Standard_False;
610       for (Standard_Integer i = 1; i <= mySPoins.Length(); i++)
611         if (thePi(1).IsEqual(mySPoins(i))) {
612           contains = Standard_True;
613           break;
614         }
615       if (!contains)
616         mySPoins.Append(thePi(1));
617     }
618     else if (iObje2-iObje1!=1 && 
619              (!oClos || (iObje1!=1 && iObje2!=nbso))) {
620       mySPoins.Append(thePi(1));
621     }
622   }
623
624   else if (nbpi>=2) {
625     Intf_TangentZone TheTZ;
626     if (nbpi==2) {
627       TheTZ.PolygonInsert(thePi(1));
628       TheTZ.PolygonInsert(thePi(2));
629     }
630     else {
631       Standard_Integer lpj;
632       Standard_Integer lmin=1;
633       Standard_Integer lmax=1;
634       for (lpj=2; lpj<=nbpi; lpj++) {
635         if      (parO[lpj]<parO[lmin]) lmin=lpj;
636         else if (parO[lpj]>parO[lmax]) lmax=lpj;
637       }
638       TheTZ.PolygonInsert(thePi(lmin));
639       TheTZ.PolygonInsert(thePi(lmax));
640
641       Standard_Integer ltmin=1;
642       Standard_Integer ltmax=1;
643       for (lpj=2; lpj<=nbpi; lpj++) {
644         if      (parT[lpj]<parT[ltmin]) ltmin=lpj;
645         else if (parT[lpj]>parT[ltmax]) ltmax=lpj;
646       }
647       if (ltmin!=lmin && ltmin!=lmax) TheTZ.PolygonInsert(thePi(ltmin));
648       if (ltmax!=lmin && ltmax!=lmax) TheTZ.PolygonInsert(thePi(ltmax));
649     }
650     
651     if (edgeSP) TheTZ.PolygonInsert(Intf_SectionPoint
652                                     (gp_Pnt2d (BegO.X()+ (segO.X()*parOSP),
653                                                BegO.Y()+ (segO.Y()*parOSP)),
654                                      Intf_EDGE,iObje1,parOSP,
655                                      Intf_EDGE,iObje2,parTSP,sinTeta));
656
657     Standard_Integer nbtz=myTZones.Length();
658 #if 0 
659     Standard_Integer decaltz=0;
660     for (Standard_Integer ltz=1; ltz<=nbtz; ltz++) {
661       if (TheTZ.HasCommonRange(myTZones(ltz-decaltz))) {
662         TheTZ.Append(myTZones(ltz-decaltz));
663         myTZones.Remove(ltz-decaltz);
664         decaltz++;
665       }
666     }
667     myTZones.Append(TheTZ);
668 #else 
669     TColStd_ListOfInteger LIndex;
670     for (Standard_Integer ltz=1; ltz<=nbtz; ltz++) {
671       if (TheTZ.HasCommonRange(myTZones(ltz))) {
672         LIndex.Append(ltz);
673       }
674     }
675     //------------------------------------------------------------------------
676     //--   The list is parsed in ascending order by index, zone and tg
677     //--
678     if(LIndex.IsEmpty()) { 
679       myTZones.Append(TheTZ);
680     }
681     else {
682       Standard_Integer indexfirst = LIndex.First();
683       LIndex.RemoveFirst();
684       Standard_Integer decal = 0;
685       myTZones(indexfirst).Append(TheTZ);
686       while(!LIndex.IsEmpty()) {
687         Standard_Integer index = LIndex.First();
688         LIndex.RemoveFirst();
689         myTZones(indexfirst).Append(myTZones(index-decal));
690         myTZones.Remove(index-decal);
691         decal++;
692       }
693     }
694 #endif
695   }
696 }