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
7 // This file is part of Open CASCADE Technology software library.
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.
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
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>
31 // Angular precision (sinus) below that value two right segments
32 // are considered as having a potential zone of tangency.
35 static const Standard_Real PRCANG = Precision::Angular();
38 //=======================================================================
39 //function : Intf_InterferencePolygon2d
40 //purpose : constructor empty
41 //=======================================================================
43 Intf_InterferencePolygon2d::Intf_InterferencePolygon2d()
44 : Intf_Interference (Standard_False),
45 oClos (Standard_False),
46 tClos (Standard_False),
50 //=======================================================================
51 //function : Intf_InterferencePolygon2d
52 //purpose : Constructor of the interference between two Polygon.
53 //=======================================================================
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),
62 if (!Obje1.Bounding().IsOut(Obje2.Bounding())) {
63 Tolerance=Obje1.DeflectionOverEstimation()+
64 Obje2.DeflectionOverEstimation();
66 Tolerance=Epsilon(1000.);
67 nbso=Obje1.NbSegments();
70 Interference(Obje1, Obje2);
76 //=======================================================================
77 //function : Intf_InterferencePolygon2d
78 //purpose : Constructor of the auto interference of a Polygon.
79 //=======================================================================
81 Intf_InterferencePolygon2d::Intf_InterferencePolygon2d
82 (const Intf_Polygon2d& Obje)
83 : Intf_Interference (Standard_True),
84 oClos (Standard_False),
85 tClos (Standard_False),
88 Tolerance=Obje.DeflectionOverEstimation()*2;
90 Tolerance=Epsilon(1000.);
97 //=======================================================================
100 //=======================================================================
102 void Intf_InterferencePolygon2d::Perform
103 (const Intf_Polygon2d& Obje1, const Intf_Polygon2d& Obje2)
105 SelfInterference(Standard_False);
106 if (!Obje1.Bounding().IsOut(Obje2.Bounding())) {
107 Tolerance=Obje1.DeflectionOverEstimation()+
108 Obje2.DeflectionOverEstimation();
110 Tolerance=Epsilon(1000.);
111 nbso=Obje1.NbSegments();
112 oClos=Obje1.Closed();
113 tClos=Obje2.Closed();
114 Interference(Obje1, Obje2);
119 //=======================================================================
122 //=======================================================================
124 void Intf_InterferencePolygon2d::Perform
125 (const Intf_Polygon2d& Obje)
127 SelfInterference(Standard_True);
128 Tolerance=Obje.DeflectionOverEstimation()*2;
130 Tolerance=Epsilon(1000.);
137 //=======================================================================
138 //function : Pnt2dValue
139 //purpose : Give the section point of range Index in the interference.
140 //=======================================================================
142 gp_Pnt2d Intf_InterferencePolygon2d::Pnt2dValue
143 (const Standard_Integer Index) const
145 return gp_Pnt2d((mySPoins(Index)).Pnt().X(),
146 (mySPoins(Index)).Pnt().Y());
150 //=======================================================================
151 //function : Interference
153 //=======================================================================
155 void Intf_InterferencePolygon2d::Interference
156 (const Intf_Polygon2d& Obje1,
157 const Intf_Polygon2d& Obje2)
162 Standard_Integer iObje1, iObje2, n1 = nbso, n2 = Obje2.NbSegments();
163 Standard_Real d1 = Obje1.DeflectionOverEstimation(),
164 d2 = Obje2.DeflectionOverEstimation();
166 gp_Pnt2d p1b, p1e, p2b, p2e;
167 for (iObje1=1; iObje1<=n1; iObje1++)
170 Obje1.Segment(iObje1,p1b,p1e);
174 if (!Obje2.Bounding().IsOut(bSO)) {
175 for (iObje2=1; iObje2<=n2; iObje2++) {
177 Obje2.Segment(iObje2,p2b,p2e);
182 Intersect(iObje1, iObje2, p1b, p1e, p2b, p2e);
188 //=======================================================================
189 //function : Interference
191 //=======================================================================
193 void Intf_InterferencePolygon2d::Interference
194 (const Intf_Polygon2d& Obje)
199 Standard_Integer iObje1, iObje2, n = Obje.NbSegments();
200 Standard_Real d = Obje.DeflectionOverEstimation();
202 gp_Pnt2d p1b, p1e, p2b, p2e;
203 for (iObje1=1; iObje1<=n; iObje1++) {
205 Obje.Segment(iObje1,p1b,p1e);
209 if (!Obje.Bounding().IsOut(bSO)) {
210 for (iObje2=iObje1+1;iObje2<=n;iObje2++){
212 Obje.Segment(iObje2,p2b,p2e);
217 Intersect(iObje1, iObje2, p1b, p1e, p2b, p2e);
224 //=======================================================================
227 //=======================================================================
229 void Intf_InterferencePolygon2d::Clean()
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;
240 Standard_Integer tsp, tsps;
241 Standard_Integer lpi, ltz;
242 Standard_Boolean Only1Seg=Standard_False;
244 #define PI1 (myTZones(ltz-decal).GetPoint(lpi))
245 #define PI2 (myTZones(ltz-decal).GetPoint(tsp))
247 for (ltz=1; ltz<=nbIt; ltz++) {
249 Standard_Real pr1mi,pr1ma,pr2mi,pr2ma,delta1,delta2;
250 myTZones(ltz-decal).ParamOnFirst(pr1mi,pr1ma);
252 myTZones(ltz-decal).ParamOnSecond(pr2mi,pr2ma);
254 if (delta1<1. && delta2<1.) Only1Seg=Standard_True;
255 if (delta1==0. || delta2==0.) Only1Seg=Standard_True;
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) {
265 Only1Seg=Standard_False;
270 else if (dim1!=Intf_EXTERNAL && dim2!=Intf_EXTERNAL) {
275 mySPoins.Append(myTZones(ltz-decal).GetPoint(tsp));
276 myTZones.Remove(ltz-decal);
279 else if (Only1Seg && tsps!=0) {
280 mySPoins.Append(myTZones(ltz-decal).GetPoint(tsps));
281 myTZones.Remove(ltz-decal);
287 // The points of intersection located in the tangency zone are
288 // removed from the list :
289 nbIt=mySPoins.Length();
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);
304 //=======================================================================
305 //function : Intersect
307 //=======================================================================
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)
315 if(Abs(iObje1-iObje2)<=1) return; //-- Ajout du 15 jan 98
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();
325 // If the length of segment is zero, nothing is done
326 Standard_Real lgT =Sqrt(segT*segT);
328 Standard_Real lgO =Sqrt(segO*segO);
331 // Direction of parsing of segments
332 Standard_Real sigPS=(segO*segT)>0.0 ? 1.0 : -1.0;
334 // Precision of calculation
335 Standard_Real floatgap=Epsilon(lgO+lgT);
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;
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) {
349 parO[nbpi]=0.;parT[nbpi]=0.;
350 thePi.Append(Intf_SectionPoint(BegO,Intf_VERTEX,iObje1,0.,
351 Intf_VERTEX,iObje2,0.,sinTeta));
353 if (dbOeT<=Tolerance) {
355 parO[nbpi]=0.;parT[nbpi]=1.;
356 thePi.Append(Intf_SectionPoint(BegO,Intf_VERTEX,iObje1,0.,
357 Intf_VERTEX,iObje2+1,0.,sinTeta));
359 if (dbObT>Tolerance && dbOeT>Tolerance &&
360 dbObT+dbOeT<=(lgT+Tolerance)) {
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));
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) {
375 parO[nbpi]=1.;parT[nbpi]=0.;
376 thePi.Append(Intf_SectionPoint(EndO,Intf_VERTEX,iObje1+1,0.,
377 Intf_VERTEX,iObje2,0.,sinTeta));
379 if (deOeT<=Tolerance) {
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));
385 if (deObT>Tolerance && deOeT>Tolerance &&
386 deObT+deOeT<=(lgT+Tolerance)) {
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));
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)) {
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));
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)) {
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));
418 Standard_Boolean edgeSP=Standard_False;
419 Standard_Real parOSP=0, parTSP=0;
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;
427 else if (nbpi==0) return;
429 // If there is no interference it is necessary to take the points segment by segment
430 if (nbpi==0 && sinTeta>PRCANG) {
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));
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;
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;
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],
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;
471 else if (0.<parOfin && parOfin<1. && 0.<parTfin && parTfin<1. ) {
472 parO[nbpi+1]= parOfin;
473 parT[nbpi+1]= parTfin;
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.)) {
484 thePi.Append(Intf_SectionPoint(gp_Pnt2d(x, y),
485 Intf_EXTERNAL, iObje1, parO[nbpi],
486 Intf_EXTERNAL, iObje2, parT[nbpi],
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]);
507 parTdeb=parTdeb+sigPS*(delta*(deltaT/deltaO));
512 parTfin=parTfin-sigPS*(delta*(deltaT/deltaO));
518 parOdeb=parOdeb+delta*(deltaO/deltaT);
523 parOfin=parOfin-delta*(deltaO/deltaT);
530 parOdeb=parOdeb+delta*(deltaO/deltaT);
535 parOfin=parOfin-delta*(deltaO/deltaT);
539 if ((parOdeb<parOmin && parOmin>0.) ||
540 (sigPS>0. && parTdeb<parTmin && parTmin>0.) ||
541 (sigPS<0. && parTdeb>parTmax && parTmax<1.)) {
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],
553 if ((parOfin>parOmax && parOmax<1.) ||
554 (sigPS<0. && parTfin<parTmin && parTmin>0.) ||
555 (sigPS>0. && parTfin>parTmax && parTmax<1.)) {
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],
571 //-- lbr : The points too close to each other are suspended
572 Standard_Boolean suppr;
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);
581 for(Standard_Integer j=i; j<nbpi; j++) {
589 while(suppr==Standard_True);
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);
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;
613 mySPoins.Append(thePi(1));
615 else if (iObje2-iObje1!=1 &&
616 (!oClos || (iObje1!=1 && iObje2!=nbso))) {
617 mySPoins.Append(thePi(1));
622 Intf_TangentZone TheTZ;
624 TheTZ.PolygonInsert(thePi(1));
625 TheTZ.PolygonInsert(thePi(2));
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;
635 TheTZ.PolygonInsert(thePi(lmin));
636 TheTZ.PolygonInsert(thePi(lmax));
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;
644 if (ltmin!=lmin && ltmin!=lmax) TheTZ.PolygonInsert(thePi(ltmin));
645 if (ltmax!=lmin && ltmax!=lmax) TheTZ.PolygonInsert(thePi(ltmax));
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));
654 Standard_Integer nbtz=myTZones.Length();
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);
664 myTZones.Append(TheTZ);
666 TColStd_ListOfInteger LIndex;
667 for (Standard_Integer ltz=1; ltz<=nbtz; ltz++) {
668 if (TheTZ.HasCommonRange(myTZones(ltz))) {
672 //------------------------------------------------------------------------
673 //-- The list is parsed in ascending order by index, zone and tg
675 if(LIndex.IsEmpty()) {
676 myTZones.Append(TheTZ);
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);