0022887: Request to make Intf_InterferencePolygon2d class thread-safe.
[occt.git] / src / IntPatch / IntPatch_PolyArc.cxx
1 // File:      IntPatch_PolyArc.cxx
2 // Created:   Wed Jan 27 09:44:03 1993
3 // Author:    Isabelle GRIGNON
4 // Copyright: Matra Datavision 1993
5
6 #include <IntPatch_PolyArc.ixx>
7
8 #include <Standard_ConstructionError.hxx>
9
10 inline void MinMax (const Standard_Real a1, const Standard_Real a2,
11                     Standard_Real& amin, Standard_Real& amax)
12 {
13   if (a1 < a2) {
14     amin = a1; amax = a2;
15   }
16   else {
17     amin = a2; amax = a1;
18   }
19 }
20
21 IntPatch_PolyArc::IntPatch_PolyArc(const Handle(Adaptor2d_HCurve2d)& Line ,
22                                    const Standard_Integer NbSample,
23                                    const Standard_Real aPdeb,
24                                    const Standard_Real aPfin,
25                                    const Bnd_Box2d& BoxOtherPolygon):
26                                    brise(1,Max(1,NbSample)),
27                                    param(1,Max(1,NbSample)),
28                                    offsetx(0.0),
29                                    offsety(0.0)
30 {
31   Standard_Real Pdeb = aPdeb;
32   Standard_Real Pfin = aPfin;
33   gp_Pnt2d p2d;
34   
35   if (Pdeb == RealFirst() || Pfin == RealLast() || NbSample <= 1) {
36     Standard_ConstructionError::Raise();
37   }
38   //----------------------------------------------------------------------
39   //-- On veut eviter les cas ou  le present polygone est beaucoup plus 
40   //-- grand que l objet en second.
41   //-- 
42   //-- Par exemple lorsque l objet en second est une ligne de cheminement
43   //-- qui contient de nombreux segments (>>100), une fleche nulle 
44   //-- et ce polygone quelques segments et une fleche qui contient
45   //-- toute la ligne de cheminement. 
46   //--
47   //-- Dans ce cas (tout un polygone compris dans la zone d influence)
48   //-- les calculs deviennent tres longs (N2)
49   //----------------------------------------------------------------------
50   Standard_Integer IndexInf = NbSample+1;
51   Standard_Integer IndexSup = 0;
52   
53   Standard_Real bx0,by0,bxmin,bxmax,bymin,bymax,r,r2;
54   
55   BoxOtherPolygon.Get(bxmin,bymin,bxmax,bymax);
56   r=(bxmax-bxmin)+(bymax-bymin);
57   bx0=(bxmax+bxmin)*0.5;
58   by0=(bymax+bymin)*0.5;
59   
60   Standard_Real Pas;
61   Standard_Real X,Y,Xs,Ys,Xm,Ym,XXs,YYs;
62   
63   r*=0.8;
64   r2 = r*r*49.;
65   Standard_Integer nbloop=0;
66   
67   do { 
68     nbloop++;
69     Pas = (Pfin-Pdeb)/(NbSample-1);
70     param(1) = Pdeb;
71     Line->D0(Pdeb,p2d);
72     Xs = p2d.X(); Ys = p2d.Y();
73     brise(1).SetCoord(Xs,Ys);
74     
75     myBox.SetVoid();
76     
77     myBox.Add(brise(1));
78     myError =0.;
79     
80     for (Standard_Integer i =2; i<=NbSample;i++) {
81       param(i) = Pdeb + (i-1)*Pas;
82       Line->D0(param(i),p2d);
83       X = p2d.X(); Y = p2d.Y();
84       brise(i).SetCoord(X,Y);
85       XXs = 0.5*(Xs+X);
86       YYs = 0.5*(Ys+Y);
87       //------------------------------------------------------------
88       //-- On recherche le debut et la fin de la zone significative
89       //------------------------------------------------------------
90       // MSV: (see cda 002 H2) if segment is too large (>>r) we have
91       //      a risk to jump through BoxOtherPolygon, therefore we should
92       //      check this condition if the first one is failure.
93       Standard_Boolean isMidPtInBox = (Abs(bx0-XXs) + Abs(by0-YYs)) < r;
94       Standard_Boolean isSegOut = Standard_True;
95       if(!isMidPtInBox) {
96         Standard_Real d = (X-Xs)*(X-Xs)+(Y-Ys)*(Y-Ys);
97         if (d > r2) {
98           Standard_Real xmin,xmax,ymin,ymax;
99           MinMax (Xs,X, xmin,xmax);
100           MinMax (Ys,Y, ymin,ymax);
101           isSegOut = (xmax < bxmin || xmin > bxmax ||
102                       ymax < bymin || ymin > bymax);
103         }
104       }
105       if(isMidPtInBox || !isSegOut) { 
106         // MSV: take the previous and the next segments too, because of
107         //      we check only the middle point (see BUC60946)
108         //if(IndexInf>i) IndexInf=i-1;
109         //if(IndexSup<i) IndexSup=i;
110         if(IndexInf>i) IndexInf=Max(i-2,1);
111         if(IndexSup<i) IndexSup=Min(i+1,NbSample);
112       }
113       
114       myBox.Add(brise(i));
115       Line->D0(param(i)-Pas*0.5,p2d);
116       Xm = p2d.X() - XXs;
117       Ym = p2d.Y() - YYs;
118       Xm = Sqrt(Xm*Xm+Ym*Ym);
119       myError =Max (myError , Xm);
120       Xs = X;
121       Ys = Y;
122     }
123     if(IndexInf > IndexSup) { 
124       r+=r; 
125       r2 = r*r*49.;
126       //-- cout<<" Le rayon : "<<r<<" est insuffisant "<<endl;
127     }
128     else {
129       //----------------------------------------------
130       //-- Si le nombre de points significatifs est
131       //-- insuffisant, on reechantillonne une fois
132       //-- encore
133       //----------------------------------------------
134       if((IndexSup-IndexInf)<(NbSample/2)) { 
135         //-- cout<<" --- On remet ca entre les index "<<IndexInf<<" et "<<IndexSup<<endl;
136         nbloop = 10;
137         //if(IndexInf>1) IndexInf--;
138         //if(IndexSup<NbSample) IndexSup++;
139         Pdeb = param(IndexInf); 
140         Pfin = param(IndexSup);
141         //IndexInf = IndexSup+1;
142         IndexInf = NbSample+1;
143         IndexSup = 0;
144       }
145     }
146   }
147   while((IndexInf > IndexSup) && nbloop<=10); 
148   myError*=1.2;
149   if(myError<0.00000001) 
150     myError = 0.00000001;
151   myBox.Enlarge(myError);
152
153   ferme = (Line->Value(aPdeb).Distance(Line->Value(aPfin)) <= 1e-7);
154 }
155
156 Standard_Boolean IntPatch_PolyArc::Closed() const { return ferme;}
157
158 Standard_Integer IntPatch_PolyArc::NbPoints() const {return brise.Length();}
159
160 gp_Pnt2d IntPatch_PolyArc::Point(const Standard_Integer Index ) const 
161
162   if(offsetx == 0.0 && offsety==0.0) 
163     return(brise(Index));
164   
165   const gp_Pnt2d& P = brise(Index);
166   return (gp_Pnt2d(P.X()+offsetx,P.Y()+offsety));
167 }
168
169 Standard_Real IntPatch_PolyArc::Parameter(const Standard_Integer Index ) const
170 { return param(Index);}
171
172
173 void IntPatch_PolyArc::SetOffset(const Standard_Real ox,const Standard_Real oy) { 
174   Standard_Real xmin,ymin,xmax,ymax,g;
175   myBox.Get(xmin,ymin,xmax,ymax);
176   g = myBox.GetGap();
177   
178   myBox.SetVoid();
179   
180   myBox.Update(xmin-offsetx,ymin-offsety,
181                xmax-offsetx,ymax-offsety);
182   offsetx = ox;
183   offsety = oy;
184   myBox.Update(xmin+offsetx,ymin+offsety,
185                xmax+offsetx,ymax+offsety);
186   myBox.SetGap(g);
187 }