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