0022887: Request to make Intf_InterferencePolygon2d class thread-safe.
[occt.git] / src / IntCurve / IntCurve_Polygon2dGen.gxx
1 // File:        IntCurve_Polygon2dGen.gxx
2 // Created:     Mon Oct 12 17:17:30 1992
3 // Author:      Laurent BUCHARD
4
5 #define TEST 0
6
7 #include <Standard_ConstructionError.hxx>
8 #include <Bnd_Box2d.hxx>
9 #include <TColgp_Array1OfPnt2d.hxx>
10 #include <gp_Lin2d.hxx>
11 #include <gp_Vec2d.hxx>
12 #include <gp_Dir2d.hxx>
13
14
15 #define MAJORATION_DEFLECTION 1.5
16 //======================================================================
17 //== On echantillonne sur le Domain de la Curve  NbPts Points 
18 //== a parametres constants.
19 //== 
20 //== On estime la fleche maximum en prenant la distance maxi entre la 
21 //== droite Curve.Value(X(i))-->Curve.Value(X(i+1)) 
22 //== et le point Curve.Value(X(i+1/2))
23 //======================================================================
24 //  Modified by Sergey KHROMOV - Mon Mar 24 12:02:43 2003 Begin
25 IntCurve_Polygon2dGen::IntCurve_Polygon2dGen(const TheCurve&        C,
26                                              const Standard_Integer tNbPts,
27                                              const IntRes2d_Domain& D,
28                                              const Standard_Real    Tol):
29 //                                           const Standard_Real    ):
30 //  Modified by Sergey KHROMOV - Mon Mar 24 12:02:45 2003 End
31        ThePnts(1,(tNbPts<3)? 6 : (tNbPts+tNbPts)),
32        TheParams(1,(tNbPts<3)? 6 : (tNbPts+tNbPts)),
33        TheIndex(1,(tNbPts<3)? 6 : (tNbPts+tNbPts))
34
35          
36   Standard_Integer NbPts = (tNbPts<3)? 3 : tNbPts;
37   TheMaxNbPoints = NbPts+NbPts;
38   NbPntIn = NbPts;
39   //----------------------------------------------------- 
40   //--- Initialisation du Brise a d_Parametre constant
41   //---
42   Binf = D.FirstParameter();
43   Bsup = D.LastParameter();
44   //-----------------------------------------------------
45   //-- IntRes2d Raise si HasFirst retourne False
46   //-- et Acces a First Parameter
47   //-- 
48   Standard_Real u=Binf; 
49   Standard_Real u1=Bsup;
50   Standard_Real du=(u1-u)/(Standard_Real)(NbPts-1);
51 //  Standard_Integer ip1,i=1;
52   Standard_Integer i=1;
53   
54   do {
55     gp_Pnt2d P=TheCurveTool::Value(C,u);
56     myBox.Add(P);
57     TheIndex.SetValue(i,i);
58     ThePnts.SetValue(i,P); 
59     TheParams.SetValue(i,u);
60     u+=du;
61     i++;
62   }
63   while(i<=NbPts);
64
65
66   //-----------------------------------------------------
67   //--- Calcul d un majorant de fleche approche
68   //---
69 //  Modified by Sergey KHROMOV - Mon Mar 24 12:03:05 2003 Begin
70 //   TheDeflection = 0.000000001;
71   TheDeflection = Min(0.000000001, Tol/100.);
72 //  Modified by Sergey KHROMOV - Mon Mar 24 12:03:05 2003 End
73   i=1;
74   u=D.FirstParameter();
75   u+=du * 0.5;
76   
77   do {
78     gp_Pnt2d Pm = TheCurveTool::Value(C,u);
79     const gp_Pnt2d& P1 = ThePnts.Value(i);
80     const gp_Pnt2d& P2 = ThePnts.Value(i+1);
81
82     u+=du;
83     i++;
84
85
86     Standard_Real dx,dy,t=0;    
87     dx=P1.X()-P2.X(); if(dx<0) dx=-dx;
88     dy=P1.Y()-P2.Y(); if(dy<0) dy=-dy;
89     if(dx+dy>1e-12) { 
90       gp_Lin2d L(P1,gp_Dir2d(gp_Vec2d(P1,P2)));
91       t = L.Distance(Pm);
92       if(t>TheDeflection) {
93         TheDeflection = t;
94       }
95     }
96   }
97   while(i<NbPts);
98
99   myBox.Enlarge(TheDeflection*MAJORATION_DEFLECTION);
100   ClosedPolygon = Standard_False;
101 }
102 //======================================================================
103 //  Modified by Sergey KHROMOV - Mon Mar 24 12:03:26 2003 Begin
104 IntCurve_Polygon2dGen::IntCurve_Polygon2dGen(const TheCurve&        C,
105                                              const Standard_Integer tNbPts,
106                                              const IntRes2d_Domain& D,
107                                              const Standard_Real Tol,
108                                              const Bnd_Box2d& BoxOtherPolygon):
109 //  Modified by Sergey KHROMOV - Mon Mar 24 12:03:28 2003 End
110        ThePnts(1,(tNbPts<3)? 6 : (tNbPts+tNbPts)), 
111        TheParams(1,(tNbPts<3)? 6 : (tNbPts+tNbPts)), 
112        TheIndex(1,(tNbPts<3)? 6 : (tNbPts+tNbPts))
113 {
114   Standard_Integer NbPts = (tNbPts<3)? 3 : tNbPts;
115   TheMaxNbPoints = NbPts+NbPts;
116   NbPntIn = NbPts; 
117   //----------------------------------------------------- 
118   //--- Initialisation du Brise a d_Parametre constant
119   //---
120   Binf = D.FirstParameter();
121   Bsup = D.LastParameter();
122   //-----------------------------------------------------
123   Standard_Real u=Binf; 
124   Standard_Real u1=Bsup;
125   Standard_Real du=(u1-u)/(Standard_Real)(NbPts-1);
126   Standard_Integer i=1;
127   do {
128     gp_Pnt2d P=TheCurveTool::Value(C,u);
129     myBox.Add(P);
130     ThePnts.SetValue(i,P); 
131     TheParams.SetValue(i,u);
132     TheIndex.SetValue(i,i);
133     u+=du;
134     i++;
135   }
136   while(i<=NbPts);
137
138
139   //-----------------------------------------------------
140   //--- Calcul d un majorant de fleche approche
141   //---
142 //  Modified by Sergey KHROMOV - Mon Mar 24 12:03:55 2003 Begin
143 //   TheDeflection = 0.0000001;
144   TheDeflection = Min(0.0000001, Tol/100.);
145 //  Modified by Sergey KHROMOV - Mon Mar 24 12:03:56 2003 End
146   i=1;
147   u=D.FirstParameter();
148   u+=du * 0.5;
149   
150   do {
151     gp_Pnt2d Pm = TheCurveTool::Value(C,u);
152     const gp_Pnt2d& P1 = ThePnts.Value(i);
153     const gp_Pnt2d& P2 = ThePnts.Value(i+1);
154
155     Standard_Real dx,dy;    
156     dx=P1.X()-P2.X(); if(dx<0) dx=-dx;
157     dy=P1.Y()-P2.Y(); if(dy<0) dy=-dy;
158     if(dx+dy>1e-12) {      
159       gp_Lin2d L(P1,gp_Dir2d(gp_Vec2d(P1,P2)));
160       Standard_Real t = L.Distance(Pm);      
161       if(t>TheDeflection) {
162         TheDeflection = t;
163       }
164     }
165     u+=du;
166     i++;
167   }
168   while(i<NbPts);
169   
170   myBox.Enlarge(TheDeflection*MAJORATION_DEFLECTION);
171   ClosedPolygon = Standard_False;
172   //-------------------------------------------------------
173   //-- On supprime les points alignes 
174   //-- (Permet de diminuer le nombre total de points) 
175   //-- (Dans le cas ou la courbe est "droite"       )
176   Standard_Real DeflectionMaj = TheDeflection;
177   for(i=2;i<NbPntIn && NbPntIn>3;i++) { 
178     Standard_Integer indexim1 = TheIndex.Value(i-1);
179     Standard_Integer indexi   = TheIndex.Value(i);
180     Standard_Integer indexip1 = TheIndex.Value(i+1);
181     const gp_Pnt2d& Pim1 = ThePnts.Value(indexim1);
182     const gp_Pnt2d& Pi   = ThePnts.Value(indexi);
183     const gp_Pnt2d& Pip1 = ThePnts.Value(indexip1);
184
185     Standard_Real dx,dy;    
186     dx=Pim1.X()-Pip1.X(); if(dx<0) dx=-dx;
187     dy=Pim1.Y()-Pip1.Y(); if(dy<0) dy=-dy;
188     Standard_Real t=0;
189     if(dx+dy>1e-12) {    
190       gp_Lin2d L(Pim1,gp_Dir2d(gp_Vec2d(Pim1,Pip1)));
191       t = L.Distance(Pi);
192     }
193     if(t<=DeflectionMaj) { 
194       //-- On supprime le point i
195       for(Standard_Integer j = i; j<NbPntIn; j++) { 
196         TheIndex.SetValue(j,TheIndex.Value(j+1));
197       }
198       NbPntIn--;
199       i--;
200     }
201   }
202
203   ComputeWithBox(C,BoxOtherPolygon);
204 }
205 //======================================================================
206 void IntCurve_Polygon2dGen::ComputeWithBox(const TheCurve&        C,
207                                            const Bnd_Box2d& BoxOtherPolygon) {
208   if(myBox.IsOut(BoxOtherPolygon)) { 
209     NbPntIn=2;
210     myBox.SetVoid();
211   }
212   else { 
213      Standard_Real bx0,bx1,by0,by1;
214      BoxOtherPolygon.Get(bx0,by0,bx1,by1);
215
216     bx0-=TheDeflection; 
217     by0-=TheDeflection; 
218     bx1+=TheDeflection; 
219     by1+=TheDeflection;
220     Standard_Integer MaxIndexUsed = 1;
221     Standard_Integer i,nbp;
222     Standard_Integer Rprec,Ri;
223     Standard_Real x,y;
224     
225     nbp = 0;
226     x = ThePnts.Value(TheIndex.Value(1)).X();
227     y = ThePnts.Value(TheIndex.Value(1)).Y();
228     
229     Rprec = CalculRegion(x,y,bx0,bx1,by0,by1);
230     for(i = 2; i<=NbPntIn; i++) { 
231       const gp_Pnt2d& P2d = ThePnts.Value(TheIndex.Value(i));
232       Ri = CalculRegion(P2d.X(),P2d.Y(),bx0,bx1,by0,by1);
233       if((Ri & Rprec)==0) { 
234         if(nbp) { 
235           if(TheIndex.Value(nbp) != TheIndex.Value(i-1)) { 
236             nbp++;
237             TheIndex.SetValue(nbp,TheIndex.Value(i-1));
238           }
239         }
240         else {
241           nbp++;
242           TheIndex.SetValue(nbp,TheIndex.Value(i-1)); 
243         }
244         nbp++;
245         TheIndex.SetValue(nbp,TheIndex.Value(i));
246         if(TheIndex.Value(i) > MaxIndexUsed) MaxIndexUsed = TheIndex.Value(i);
247
248         Rprec = Ri;
249       }
250       else { 
251         if((Ri & Rprec)==0) { 
252           nbp++;
253           TheIndex.SetValue(nbp,TheIndex.Value(i));
254           if(TheIndex.Value(i) > MaxIndexUsed) MaxIndexUsed = TheIndex.Value(i);
255
256           Rprec = Ri; 
257         }
258       }
259       Rprec = Ri;
260     }
261     if(nbp==1) { 
262       NbPntIn=2;
263       myBox.SetVoid();
264     }
265     else {
266       myBox.SetVoid();
267       if(nbp) { 
268         myBox.Add(ThePnts.Value(TheIndex.Value(1)));
269       }
270       Standard_Real    RatioDeflection;
271       Standard_Integer nbpassagedeflection = 0;
272 //      Standard_Integer PointHasBeenAdded = 0;
273       do { 
274         nbpassagedeflection++;
275 //  Modified by Sergey KHROMOV - Mon Mar 24 12:05:28 2003 Begin
276 //      Standard_Real NewDeflection = 0.0000001;
277         Standard_Real NewDeflection = TheDeflection;
278 //  Modified by Sergey KHROMOV - Mon Mar 24 12:05:29 2003 End
279         for(i=2; i<=nbp; i++) { 
280           Standard_Integer Ii  = TheIndex.Value(i);
281           Standard_Integer Iim1= TheIndex.Value(i-1);
282           const gp_Pnt2d& Pi   = ThePnts.Value(Ii);
283           const gp_Pnt2d& Pim1 = ThePnts.Value(Iim1);
284           myBox.Add(Pi);
285           Standard_Integer Regi   = CalculRegion(Pi.X(),Pi.Y(),bx0,bx1,by0,by1);
286           Standard_Integer Regim1 = CalculRegion(Pim1.X(),Pim1.Y(),bx0,bx1,by0,by1); 
287           if((Regi & Regim1) == 0) {  
288             Standard_Real u = 0.5*( TheParams.Value(Ii)
289                                    +TheParams.Value(Iim1));
290             gp_Pnt2d Pm = TheCurveTool::Value(C,u);
291             Standard_Real dx,dy,t=0;    
292             dx=Pim1.X()-Pi.X(); if(dx<0) dx=-dx;
293             dy=Pim1.Y()-Pi.Y(); if(dy<0) dy=-dy;
294             if(dx+dy>1e-12)  {
295               gp_Lin2d L(Pim1,gp_Dir2d(gp_Vec2d(Pim1,Pi)));
296               t = L.Distance(Pm);
297               if((MaxIndexUsed<(TheMaxNbPoints-1)) && (t>(TheDeflection * 0.5))) {
298                 const gp_Pnt2d& P1=Pim1;
299                 nbp++;
300                 for(Standard_Integer j=nbp; j>=i+1; j--) { 
301                   TheIndex.SetValue(j,TheIndex.Value(j-1));
302                 }
303                 MaxIndexUsed++;
304                 TheIndex.SetValue(i,MaxIndexUsed);
305                 ThePnts.SetValue(MaxIndexUsed,Pm);
306                 TheParams.SetValue(MaxIndexUsed,u);
307                 
308                 Standard_Real u1m = 0.5*(u+TheParams.Value(TheIndex.Value(i-1)));
309                 Standard_Real um2 = 0.5*(u+TheParams.Value(TheIndex.Value(i+1)));
310                 gp_Pnt2d P1m = TheCurveTool::Value(C,u1m);
311 #ifdef DEB
312                 gp_Pnt2d Pm2 = TheCurveTool::Value(C,um2);
313 #else
314                 TheCurveTool::Value(C,um2);
315 #endif
316                 gp_Lin2d L1m(P1,gp_Dir2d(gp_Vec2d(P1,Pm)));
317 #ifdef DEB
318                 gp_Lin2d Lm2(Pm,gp_Dir2d(gp_Vec2d(Pm,ThePnts.Value(TheIndex.Value(i+1)))));
319 #else
320                 ThePnts.Value(TheIndex.Value(i+1));
321 #endif
322                 t = L1m.Distance(P1m);
323                 i--; 
324               }
325             }
326             else { 
327               if(t>NewDeflection) { 
328                 NewDeflection = t; 
329               }
330             }
331           }
332         }
333         if(NewDeflection) 
334           RatioDeflection = TheDeflection / NewDeflection; 
335         else RatioDeflection = 10.0;
336         TheDeflection = NewDeflection;
337         NbPntIn = nbp;
338       }
339       while((RatioDeflection<3.0)
340             && (nbpassagedeflection < 3) 
341             && (MaxIndexUsed<(TheMaxNbPoints-2)));
342     }
343
344     TheDeflection*=MAJORATION_DEFLECTION;
345     myBox.Enlarge(TheDeflection);
346   }
347   ClosedPolygon = Standard_False;
348   Dump();
349 }
350
351
352 Standard_Boolean IntCurve_Polygon2dGen::AutoIntersectionIsPossible() const { 
353
354   gp_Vec2d VRef(ThePnts.Value(TheIndex.Value(1)),
355                 ThePnts.Value(TheIndex.Value(2)));
356   for(Standard_Integer i=3; i<=NbPntIn; i++) { 
357     gp_Vec2d V(ThePnts.Value(TheIndex.Value(i-1)),
358                 ThePnts.Value(TheIndex.Value(i)));
359     if(V.Dot(VRef)<0.0) {
360       return(Standard_True);
361     }
362   }
363   return(Standard_False); 
364 }
365
366 //======================================================================
367 Standard_Real IntCurve_Polygon2dGen::ApproxParamOnCurve( const Standard_Integer Aindex
368                                                         ,const Standard_Real TheParamOnLine) 
369      const 
370 {
371   Standard_Integer Indexp1,Index = Aindex;
372   Standard_Real    ParamOnLine = TheParamOnLine;
373   if (Index > NbPntIn) {
374     cout << "OutOfRange Polygon2d::ApproxParamOnCurve " <<endl;
375   }
376   if((Index == NbPntIn) && (ParamOnLine == 0.0)) { 
377     Index--; ParamOnLine=1.0;
378   }
379   if(Index==0) { 
380     Index=1; 
381     ParamOnLine = 0.0;
382   }
383   Indexp1 = TheIndex.Value(Index+1);
384   Index   = TheIndex.Value(Index);
385
386   Standard_Real du = TheParams.Value(Indexp1)-TheParams.Value(Index);
387   Standard_Real u  = TheParams.Value(Index) + ParamOnLine * du;
388   return(u);
389 }
390
391
392 //======================================================================
393 #if TEST
394
395 extern Standard_Boolean DebugPolygon2d;
396 extern void DrawSegmentBlanc(const gp_Pnt2d& _P1,const gp_Pnt2d& _P2);
397 extern void DrawSegment(const gp_Pnt2d& _P1,const gp_Pnt2d& _P2);
398
399 void IntCurve_Polygon2dGen::Dump(void) const {
400   if(!DebugPolygon2d) return;
401   Standard_Real bx0,bx1,by0,by1;
402   if(myBox.IsVoid()) return;
403   myBox.Get(bx0,by0,bx1,by1);
404   DrawSegment(gp_Pnt2d(bx0,by0),gp_Pnt2d(bx1,by0));
405   DrawSegment(gp_Pnt2d(bx1,by0),gp_Pnt2d(bx1,by1));
406   DrawSegment(gp_Pnt2d(bx1,by1),gp_Pnt2d(bx0,by1));
407   DrawSegment(gp_Pnt2d(bx0,by1),gp_Pnt2d(bx0,by0));    
408   Standard_Integer i;
409   if(NbPntIn<=1) return;
410   for(i=2;i<=NbPntIn; i++) { 
411     DrawSegmentBlanc(ThePnts.Value(TheIndex.Value(i-1)),ThePnts.Value(TheIndex.Value(i)));
412   }
413 }
414 #else
415 void IntCurve_Polygon2dGen::Dump(void) const { 
416   static int debug = 0;
417   if(debug) { 
418     Standard_Real bx0,bx1,by0,by1;
419     
420     cout<<"\n ----- Dump de IntCurve_Polygon2dGen -----"<<endl;
421     if(myBox.IsVoid()) { 
422       cout<<"  Polygone Vide "<<endl;
423       return;
424     }
425     myBox.Get(bx0,by0,bx1,by1);
426     cout<<"  bx0:"<<bx0  <<endl;
427     cout<<"  by0:"<<by0<<endl;
428     cout<<"  bx1:"<<bx1<<endl;
429     cout<<"  by1:"<<by1<<endl;
430     
431     Standard_Integer i;
432     for(i=1;i<=NbPntIn; i++) { 
433       const gp_Pnt2d& P = ThePnts(TheIndex(i));
434       cout<<"  ("<<i<<") u:"<<TheParams.Value(TheIndex(i))<<" X:"<<P.X()<<"  Y:"<<P.Y()<<endl;
435     }
436   }
437
438 #endif
439 //======================================================================
440 void IntCurve_Polygon2dGen::Segment(const Standard_Integer theIndex,
441                                     gp_Pnt2d &theBegin, gp_Pnt2d &theEnd) const
442 {
443   Standard_Integer ind = theIndex;
444   theBegin = ThePnts(TheIndex(theIndex));
445   if (theIndex >= NbPntIn) {
446     if (!ClosedPolygon)
447       Standard_OutOfRange::Raise("IntCurve_Polygon2dGen::Segment!");
448     ind = 0;
449   }
450   theEnd = ThePnts(TheIndex(ind+1));
451 }
452 //======================================================================