0022550: Fixing data races
[occt.git] / src / Intf / Intf_Tool.cxx
1 // File:        Intf_Tool.cxx
2 // Created:     Wed Jun 23 18:38:51 1993
3 // Author:      Didier PIFFAULT
4 //              <dpf@zerox>
5
6 #include <Intf_Tool.ixx>
7 #include <gp_XY.hxx>
8 #include <gp_Pln.hxx>
9 #include <IntAna2d_Conic.hxx>
10 #include <IntAna2d_IntPoint.hxx>
11 #include <IntAna2d_AnaIntersection.hxx>
12 #include <IntAna_IntConicQuad.hxx>
13 #include <ElCLib.hxx>
14 #include <Precision.hxx>
15
16 //=======================================================================
17 //function : Intf_Tool
18 //purpose  : 
19 //=======================================================================
20
21 Intf_Tool::Intf_Tool()
22      : nbSeg(0)
23 {}
24
25 //=======================================================================
26 //function : Lin2dBox
27 //purpose  : 
28 //=======================================================================
29
30 void  Intf_Tool::Lin2dBox(const gp_Lin2d& L2d, 
31                          const Bnd_Box2d& domain, 
32                          Bnd_Box2d& boxLin)
33 {
34   nbSeg=0;
35   boxLin.SetVoid();
36   if        (domain.IsWhole()) {
37     boxLin.Set(L2d.Location(), L2d.Direction());
38     boxLin.Add(L2d.Direction().Reversed());
39     nbSeg=1;
40     beginOnCurve[0]=-Precision::Infinite();
41     endOnCurve[0]=Precision::Infinite();
42     return;
43   }
44   else if   (domain.IsVoid())  return;
45
46   Standard_Real xmin, xmax, ymin, ymax;
47   Standard_Real Xmin=0, Xmax=0, Ymin=0, Ymax=0;
48   Standard_Real parmin=-Precision::Infinite();
49   Standard_Real parmax=Precision::Infinite();
50   Standard_Real parcur, par1,par2;
51   Standard_Boolean xToSet, yToSet;
52
53   domain.Get(xmin,ymin,xmax,ymax);
54
55
56   if      (L2d.Direction().XY().X()>0.) {
57     if (domain.IsOpenXmin()) parmin=-Precision::Infinite();
58     else parmin=(xmin-L2d.Location().XY().X())/L2d.Direction().XY().X();
59     if (domain.IsOpenXmax()) parmax=Precision::Infinite();
60     else parmax=(xmax-L2d.Location().XY().X())/L2d.Direction().XY().X();
61     xToSet=Standard_True;
62   }
63   else if (L2d.Direction().XY().X()<0.) {
64     if (domain.IsOpenXmax()) parmin=-Precision::Infinite();
65     else parmin=(xmax-L2d.Location().XY().X())/L2d.Direction().XY().X();
66     if (domain.IsOpenXmin()) parmax=Precision::Infinite();
67     else parmax=(xmin-L2d.Location().XY().X())/L2d.Direction().XY().X();
68     xToSet=Standard_True;
69   }
70   else { // Parallel to axis  X
71     if (L2d.Location().XY().X()<xmin || xmax<L2d.Location().XY().X())
72       return;
73     Xmin=L2d.Location().XY().X();
74     Xmax=L2d.Location().XY().X();
75     xToSet=Standard_False;
76   }
77
78   if      (L2d.Direction().XY().Y()>0.) {
79     if (domain.IsOpenYmin()) parcur=-Precision::Infinite();
80     else parcur=(ymin-L2d.Location().XY().Y())/L2d.Direction().XY().Y();
81     parmin=Max(parmin, parcur);
82     if (domain.IsOpenYmax()) parcur=Precision::Infinite();
83     else parcur=(ymax-L2d.Location().XY().Y())/L2d.Direction().XY().Y();
84     parmax=Min(parmax, parcur);
85     yToSet=Standard_True;
86   }
87   else if (L2d.Direction().XY().Y()<0.) {
88     if (domain.IsOpenYmax()) parcur=-Precision::Infinite();
89     else parcur=(ymax-L2d.Location().XY().Y())/L2d.Direction().XY().Y();
90     parmin=Max(parmin, parcur);
91     if (domain.IsOpenYmin()) parcur=Precision::Infinite();
92     else parcur=(ymin-L2d.Location().XY().Y())/L2d.Direction().XY().Y();
93     parmax=Min(parmax, parcur);
94     yToSet=Standard_True;
95   }
96   else { // Parallel to axis  Y
97     if (L2d.Location().XY().Y()<ymin || ymax<L2d.Location().XY().Y())
98       return;
99     Ymin=L2d.Location().XY().Y();
100     Ymax=L2d.Location().XY().Y();
101     yToSet=Standard_False;
102   }
103
104   nbSeg++;
105   beginOnCurve[0]=parmin;
106   endOnCurve[0]=parmax;
107
108   if (xToSet) {
109     par1=L2d.Location().XY().X()+parmin*L2d.Direction().XY().X();
110     par2=L2d.Location().XY().X()+parmax*L2d.Direction().XY().X();
111     Xmin=Min(par1, par2);
112     Xmax=Max(par1, par2);
113   }
114
115   if (yToSet) {
116     par1=L2d.Location().XY().Y()+parmin*L2d.Direction().XY().Y();
117     par2=L2d.Location().XY().Y()+parmax*L2d.Direction().XY().Y();
118     Ymin=Min(par1, par2);
119     Ymax=Max(par1, par2);
120   }
121
122   boxLin.Update(Xmin, Ymin, Xmax, Ymax);
123 }
124
125 //=======================================================================
126 //function : Hypr2dBox
127 //purpose  : 
128 //=======================================================================
129
130 void  Intf_Tool::Hypr2dBox(const gp_Hypr2d& theHypr2d, 
131                           const Bnd_Box2d& domain, 
132                           Bnd_Box2d& boxHypr2d)
133 {
134   nbSeg=0;
135   boxHypr2d.SetVoid();
136   if        (domain.IsWhole()) {
137     boxHypr2d.SetWhole();
138     nbSeg=1;
139     beginOnCurve[0]=-Precision::Infinite();
140     endOnCurve[0]=Precision::Infinite();
141     return;
142   }
143   else if   (domain.IsVoid())  return;
144
145   Standard_Integer nbPi=Inters2d(theHypr2d, domain);
146
147   if (nbPi>0) {
148     Standard_Real Xmin, Xmax, Ymin, Ymax;
149
150     domain.Get(Xmax, Ymax, Xmin, Ymin);
151
152     Standard_Integer npi;
153     for (npi=0; npi<nbPi; npi++) {
154       Xmin=Min(Xmin, xint[npi]);
155       Xmax=Max(Xmax, xint[npi]);
156       Ymin=Min(Ymin, yint[npi]);
157       Ymax=Max(Ymax, yint[npi]);
158     }
159     boxHypr2d.Update(Xmin, Ymin, Xmax, Ymax);
160
161     Standard_Integer npj, npk;
162     Standard_Real parmin;
163     for (npi=0; npi<nbPi; npi++) {
164       npk=npi;
165       for (npj=npi+1; npj<nbPi; npj++) 
166         if (parint[npj]<parint[npk]) npk=npj;
167       if (npk!=npi) {
168         parmin=parint[npk];
169         parint[npk]=parint[npi];
170         parint[npi]=parmin;
171         npj=bord[npk];
172         bord[npk]=bord[npi];
173         bord[npi]=npj;
174       }
175     }
176     
177     gp_Pnt2d Pn;
178     gp_Vec2d Tan;
179     Standard_Real sinan=0;
180     Standard_Boolean out=Standard_True;
181
182     for (npi=0; npi<nbPi; npi++) {
183       ElCLib::D1(parint[npi], theHypr2d, Pn, Tan);
184       switch (bord[npi]) {
185       case 1 :
186         sinan=gp_XY(-1.,0.)^Tan.XY();
187         break;
188       case 2 :
189         sinan=gp_XY(0.,-1.)^Tan.XY();
190         break;
191       case 3 :
192         sinan=gp_XY(1.,0.)^Tan.XY();
193         break;
194       case 4 :
195         sinan=gp_XY(0.,1.)^Tan.XY();
196         break;
197       }
198       if (Abs(sinan)>Precision::Angular()) {
199         if (sinan>0.) {
200           out=Standard_False;
201           beginOnCurve[nbSeg]=parint[npi];
202           nbSeg++;
203         }
204         else {
205           if (out) {
206             beginOnCurve[nbSeg]=-Precision::Infinite();
207             nbSeg++;
208           }
209           endOnCurve[nbSeg-1]=parint[npi];
210           out=Standard_True;
211
212           Standard_Integer ipmin;
213           if(beginOnCurve[nbSeg-1] < -10.) ipmin = -10;
214           else ipmin =  (Standard_Integer)(beginOnCurve[nbSeg-1]);
215
216           Standard_Integer ipmax;
217           if(endOnCurve[nbSeg-1] > 10.) ipmax = 10;
218           else ipmax =  (Standard_Integer)(endOnCurve[nbSeg-1]);
219
220           //Standard_Integer ipmin=Max((Standard_Integer)(beginOnCurve[nbSeg-1]),
221                 //                   -10);
222           //Standard_Integer ipmax=Min((Standard_Integer)(endOnCurve[nbSeg-1]), 
223                 //                   10);
224           ipmin=ipmin*10+1;
225           ipmax=ipmax*10-1;
226           Standard_Integer ip, pas=1;
227           for (ip=ipmin; ip<=ipmax; ip+=pas) {
228             boxHypr2d.Add(ElCLib::Value(Standard_Real(ip)/10., theHypr2d));
229             if (Abs(ip)<=10) pas=1;
230             else             pas=10;
231           }
232         }
233       }
234     }
235   }
236   else if (!domain.IsOut(ElCLib::Value(0., theHypr2d))) {
237     boxHypr2d=domain;
238     beginOnCurve[0]=-Precision::Infinite();
239     endOnCurve[0]=Precision::Infinite();
240     nbSeg=1;
241   }
242 }
243
244 //=======================================================================
245 //function : Inters2d
246 //purpose  : 
247 //=======================================================================
248
249 Standard_Integer Intf_Tool::Inters2d(const gp_Hypr2d& theCurv,
250                                     const Bnd_Box2d& Domain)
251 {
252   Standard_Integer nbpi=0;
253   Standard_Integer npi;
254   Standard_Real xmin, xmax, ymin, ymax;
255
256   Domain.Get(xmin,ymin,xmax,ymax);
257
258   if (!Domain.IsOpenYmax()) {
259     gp_Lin2d L1(gp_Pnt2d(0., ymax), gp_Dir2d(-1., 0.));
260     IntAna2d_AnaIntersection Inters1(theCurv, IntAna2d_Conic(L1));
261     if (Inters1.IsDone()) {
262       if (!Inters1.IsEmpty()) {
263         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
264           xint[nbpi]=Inters1.Point(npi).Value().X();
265           if (xmin < xint[nbpi] && xint[nbpi] <=xmax) {
266             yint[nbpi]=ymax;
267             parint[nbpi]=Inters1.Point(npi).ParamOnFirst();
268             bord[nbpi]=1;
269             nbpi++;
270           }
271         }
272       }
273     }
274   }
275
276   if (!Domain.IsOpenXmin()) {
277     gp_Lin2d L2(gp_Pnt2d(xmin, 0.), gp_Dir2d(0., -1.));
278     IntAna2d_AnaIntersection Inters2(theCurv, IntAna2d_Conic(L2));
279     if (Inters2.IsDone()) {
280       if (!Inters2.IsEmpty()) {
281         for (npi=1; npi<=Inters2.NbPoints(); npi++) {
282           yint[nbpi]=Inters2.Point(npi).Value().Y();
283           if (ymin < yint[nbpi] && yint[nbpi] <=ymax) {
284             xint[nbpi]=xmin;
285             parint[nbpi]=Inters2.Point(npi).ParamOnFirst();
286             bord[nbpi]=2;
287             nbpi++;
288           }
289         }
290       }
291     }
292   }
293
294   if (!Domain.IsOpenYmin()) {
295     gp_Lin2d L3(gp_Pnt2d(0., ymin), gp_Dir2d(1., 0.));
296     IntAna2d_AnaIntersection Inters3(theCurv, IntAna2d_Conic(L3));
297     if (Inters3.IsDone()) {
298       if (!Inters3.IsEmpty()) {
299         for (npi=1; npi<=Inters3.NbPoints(); npi++) {
300           xint[nbpi]=Inters3.Point(npi).Value().X();
301           if (xmin <=xint[nbpi] && xint[nbpi] <xmax) {
302             yint[nbpi]=ymin;
303             parint[nbpi]=Inters3.Point(npi).ParamOnFirst();
304             bord[nbpi]=3;
305             nbpi++;
306           }
307         }
308       }
309     }
310   }
311
312   if (!Domain.IsOpenXmax()) {
313     gp_Lin2d L4(gp_Pnt2d(xmax, 0.), gp_Dir2d(0., 1.));
314     IntAna2d_AnaIntersection Inters4(theCurv, IntAna2d_Conic(L4));
315     if (Inters4.IsDone()) {
316       if (!Inters4.IsEmpty()) {
317         for (npi=1; npi<=Inters4.NbPoints(); npi++) {
318           yint[nbpi]=Inters4.Point(npi).Value().Y();
319           if (ymin <= yint[nbpi] && yint[nbpi] < ymax) {
320             xint[nbpi]=xmax;
321             parint[nbpi]=Inters4.Point(npi).ParamOnFirst();
322             bord[nbpi]=4;
323             nbpi++;
324           }
325         }
326       }
327     }
328   }
329   return nbpi;
330 }
331
332 //=======================================================================
333 //function : Parab2dBox
334 //purpose  : 
335 //=======================================================================
336
337 void  Intf_Tool::Parab2dBox(const gp_Parab2d& theParab2d, 
338                            const Bnd_Box2d& domain, 
339                            Bnd_Box2d& boxParab2d)
340 {
341   nbSeg=0;
342   boxParab2d.SetVoid();
343   if        (domain.IsWhole()) {
344     boxParab2d.SetWhole();
345     nbSeg=1;
346     beginOnCurve[0]=-Precision::Infinite();
347     endOnCurve[0]=Precision::Infinite();
348     return;
349   }
350   else if   (domain.IsVoid())  return;
351
352   Standard_Integer nbPi=Inters2d(theParab2d, domain);
353
354   if (nbPi>0) {
355     Standard_Real Xmin, Xmax, Ymin, Ymax;
356
357     domain.Get(Xmax, Ymax, Xmin, Ymin);
358
359     Standard_Integer npi;
360     for (npi=0; npi<nbPi; npi++) {
361       Xmin=Min(Xmin, xint[npi]);
362       Xmax=Max(Xmax, xint[npi]);
363       Ymin=Min(Ymin, yint[npi]);
364       Ymax=Max(Ymax, yint[npi]);
365     }
366     boxParab2d.Update(Xmin, Ymin, Xmax, Ymax);
367
368     Standard_Integer npj, npk;
369     Standard_Real parmin;
370     for (npi=0; npi<nbPi; npi++) {
371       npk=npi;
372       for (npj=npi+1; npj<nbPi; npj++) 
373         if (parint[npj]<parint[npk]) npk=npj;
374       if (npk!=npi) {
375         parmin=parint[npk];
376         parint[npk]=parint[npi];
377         parint[npi]=parmin;
378         npj=bord[npk];
379         bord[npk]=bord[npi];
380         bord[npi]=npj;
381       }
382     }
383     
384     gp_Pnt2d Pn;
385     gp_Vec2d Tan;
386     Standard_Real sinan=0;
387     Standard_Boolean out=Standard_True;
388
389     for (npi=0; npi<nbPi; npi++) {
390       ElCLib::D1(parint[npi], theParab2d, Pn, Tan);
391       switch (bord[npi]) {
392       case 1 :
393         sinan=gp_XY(-1.,0.)^Tan.XY();
394         break;
395       case 2 :
396         sinan=gp_XY(0.,-1.)^Tan.XY();
397         break;
398       case 3 :
399         sinan=gp_XY(1.,0.)^Tan.XY();
400         break;
401       case 4 :
402         sinan=gp_XY(0.,1.)^Tan.XY();
403         break;
404       }
405       if (Abs(sinan)>Precision::Angular()) {
406         if (sinan>0.) {
407           out=Standard_False;
408           beginOnCurve[nbSeg]=parint[npi];
409           nbSeg++;
410         }
411         else {
412           if (out) {
413             beginOnCurve[nbSeg]=-Precision::Infinite();
414             nbSeg++;
415           }
416           endOnCurve[nbSeg-1]=parint[npi];
417           out=Standard_True;
418
419           Standard_Integer ipmin;
420           if(beginOnCurve[nbSeg-1] < -10.) ipmin = -10;
421           else ipmin =  (Standard_Integer)(beginOnCurve[nbSeg-1]);
422
423           Standard_Integer ipmax;
424           if(endOnCurve[nbSeg-1] > 10.) ipmax = 10;
425           else ipmax =  (Standard_Integer)(endOnCurve[nbSeg-1]);
426
427           //Standard_Integer ipmin=Max((Standard_Integer)(beginOnCurve[nbSeg-1]),
428                 //                   -10);
429           //Standard_Integer ipmax=Min((Standard_Integer)(endOnCurve[nbSeg-1]), 
430                 //                   10);
431           ipmin=ipmin*10+1;
432           ipmax=ipmax*10-1;
433           Standard_Integer ip, pas=1;
434           for (ip=ipmin; ip<=ipmax; ip+=pas) {
435             boxParab2d.Add(ElCLib::Value(Standard_Real(ip)/10., theParab2d));
436             if (Abs(ip)<=10) pas=1;
437             else             pas=10;
438           }
439         }
440       }
441     }
442   }
443   else if (!domain.IsOut(ElCLib::Value(0., theParab2d))) {
444     boxParab2d=domain;
445     beginOnCurve[0]=-Precision::Infinite();
446     endOnCurve[0]=Precision::Infinite();
447     nbSeg=1;
448   }
449 }
450
451 //=======================================================================
452 //function : Inters2d
453 //purpose  : 
454 //=======================================================================
455
456 Standard_Integer Intf_Tool::Inters2d(const gp_Parab2d& theCurv,
457                                     const Bnd_Box2d& Domain)
458 {
459   Standard_Integer nbpi=0;
460   Standard_Integer npi;
461   Standard_Real xmin, xmax, ymin, ymax;
462
463   Domain.Get(xmin,ymin,xmax,ymax);
464
465   if (!Domain.IsOpenYmax()) {
466     gp_Lin2d L1(gp_Pnt2d(0., ymax), gp_Dir2d(-1., 0.));
467     IntAna2d_AnaIntersection Inters1(theCurv, IntAna2d_Conic(L1));
468     if (Inters1.IsDone()) {
469       if (!Inters1.IsEmpty()) {
470         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
471           xint[nbpi]=Inters1.Point(npi).Value().X();
472           if (xmin < xint[nbpi] && xint[nbpi] <=xmax) {
473             yint[nbpi]=ymax;
474             parint[nbpi]=Inters1.Point(npi).ParamOnFirst();
475             bord[nbpi]=1;
476             nbpi++;
477           }
478         }
479       }
480     }
481   }
482
483   if (!Domain.IsOpenXmin()) {
484     gp_Lin2d L2(gp_Pnt2d(xmin, 0.), gp_Dir2d(0., -1.));
485     IntAna2d_AnaIntersection Inters2(theCurv, IntAna2d_Conic(L2));
486     if (Inters2.IsDone()) {
487       if (!Inters2.IsEmpty()) {
488         for (npi=1; npi<=Inters2.NbPoints(); npi++) {
489           yint[nbpi]=Inters2.Point(npi).Value().Y();
490           if (ymin < yint[nbpi] && yint[nbpi] <=ymax) {
491             xint[nbpi]=xmin;
492             parint[nbpi]=Inters2.Point(npi).ParamOnFirst();
493             bord[nbpi]=2;
494             nbpi++;
495           }
496         }
497       }
498     }
499   }
500
501   if (!Domain.IsOpenYmin()) {
502     gp_Lin2d L3(gp_Pnt2d(0., ymin), gp_Dir2d(1., 0.));
503     IntAna2d_AnaIntersection Inters3(theCurv, IntAna2d_Conic(L3));
504     if (Inters3.IsDone()) {
505       if (!Inters3.IsEmpty()) {
506         for (npi=1; npi<=Inters3.NbPoints(); npi++) {
507           xint[nbpi]=Inters3.Point(npi).Value().X();
508           if (xmin <=xint[nbpi] && xint[nbpi] <xmax) {
509             yint[nbpi]=ymin;
510             parint[nbpi]=Inters3.Point(npi).ParamOnFirst();
511             bord[nbpi]=3;
512             nbpi++;
513           }
514         }
515       }
516     }
517   }
518
519   if (!Domain.IsOpenXmax()) {
520     gp_Lin2d L4(gp_Pnt2d(xmax, 0.), gp_Dir2d(0., 1.));
521     IntAna2d_AnaIntersection Inters4(theCurv, IntAna2d_Conic(L4));
522     if (Inters4.IsDone()) {
523       if (!Inters4.IsEmpty()) {
524         for (npi=1; npi<=Inters4.NbPoints(); npi++) {
525           yint[nbpi]=Inters4.Point(npi).Value().Y();
526           if (ymin <= yint[nbpi] && yint[nbpi] < ymax) {
527             xint[nbpi]=xmax;
528             parint[nbpi]=Inters4.Point(npi).ParamOnFirst();
529             bord[nbpi]=4;
530             nbpi++;
531           }
532         }
533       }
534     }
535   }
536   return nbpi;
537 }
538
539
540
541
542 //=======================================================================
543 //function : LinBox
544 //purpose  : 
545 //=======================================================================
546
547 void  Intf_Tool::LinBox(const gp_Lin& L, 
548                        const Bnd_Box& domain, 
549                        Bnd_Box& boxLin)
550 {
551   nbSeg=0;
552   boxLin.SetVoid();
553   if        (domain.IsWhole()) {
554     boxLin.Set(L.Location(), L.Direction());
555     boxLin.Add(L.Direction().Reversed());
556     nbSeg=1;
557     beginOnCurve[0]=-Precision::Infinite();
558     endOnCurve[0]=Precision::Infinite();
559     return;
560   }
561   else if   (domain.IsVoid())  return;
562
563   Standard_Real xmin, xmax, ymin, ymax, zmin, zmax;
564   Standard_Real Xmin=0, Xmax=0, Ymin=0, Ymax=0, Zmin=0, Zmax=0;
565   Standard_Real parmin=-Precision::Infinite();
566   Standard_Real parmax=Precision::Infinite();
567   Standard_Real parcur, par1,par2;
568   Standard_Boolean xToSet, yToSet, zToSet;
569
570   domain.Get(xmin,ymin,zmin,xmax,ymax,zmax);
571
572
573   if      (L.Direction().XYZ().X()>0.) {
574     if (domain.IsOpenXmin()) parmin=-Precision::Infinite();
575     else parmin=(xmin-L.Location().XYZ().X())/L.Direction().XYZ().X();
576     if (domain.IsOpenXmax()) parmax=Precision::Infinite();
577     else parmax=(xmax-L.Location().XYZ().X())/L.Direction().XYZ().X();
578     xToSet=Standard_True;
579   }
580   else if (L.Direction().XYZ().X()<0.) {
581     if (domain.IsOpenXmax()) parmin=-Precision::Infinite();
582     else parmin=(xmax-L.Location().XYZ().X())/L.Direction().XYZ().X();
583     if (domain.IsOpenXmin()) parmax=Precision::Infinite();
584     else parmax=(xmin-L.Location().XYZ().X())/L.Direction().XYZ().X();
585     xToSet=Standard_True;
586   }
587   else { // Perpendiculaire a l axe  X
588     if (L.Location().XYZ().X()<xmin || xmax<L.Location().XYZ().X())
589       return;
590     Xmin=L.Location().XYZ().X();
591     Xmax=L.Location().XYZ().X();
592     xToSet=Standard_False;
593   }
594
595   if      (L.Direction().XYZ().Y()>0.) {
596     if (domain.IsOpenYmin()) parcur=-Precision::Infinite();
597     else parcur=(ymin-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
598     parmin=Max(parmin, parcur);
599     if (domain.IsOpenYmax()) parcur=Precision::Infinite();
600     else parcur=(ymax-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
601     parmax=Min(parmax, parcur);
602     yToSet=Standard_True;
603   }
604   else if (L.Direction().XYZ().Y()<0.) {
605     if (domain.IsOpenYmax()) parcur=-Precision::Infinite();
606     else parcur=(ymax-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
607     parmin=Max(parmin, parcur);
608     if (domain.IsOpenYmin()) parcur=Precision::Infinite();
609     else parcur=(ymin-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
610     parmax=Min(parmax, parcur);
611     yToSet=Standard_True;
612   }
613   else { // Perpendiculaire a l axe  Y
614     if (L.Location().XYZ().Y()<ymin || ymax<L.Location().XYZ().Y())
615       return;
616     Ymin=L.Location().XYZ().Y();
617     Ymax=L.Location().XYZ().Y();
618     yToSet=Standard_False;
619   }
620
621   if      (L.Direction().XYZ().Z()>0.) {
622     if (domain.IsOpenZmin()) parcur=-Precision::Infinite();
623     else parcur=(zmin-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
624     parmin=Max(parmin, parcur);
625     if (domain.IsOpenZmax()) parcur=Precision::Infinite();
626     else parcur=(zmax-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
627     parmax=Min(parmax, parcur);
628     zToSet=Standard_True;
629   }
630   else if (L.Direction().XYZ().Z()<0.) {
631     if (domain.IsOpenZmax()) parcur=-Precision::Infinite();
632     else parcur=(zmax-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
633     parmin=Max(parmin, parcur);
634     if (domain.IsOpenZmin()) parcur=Precision::Infinite();
635     else parcur=(zmin-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
636     parmax=Min(parmax, parcur);
637     zToSet=Standard_True;
638   }
639   else { // Perpendicular to axis Z
640     if (L.Location().XYZ().Z()<zmin || zmax<L.Location().XYZ().Z())
641       return;
642     Zmin=L.Location().XYZ().Z();
643     Zmax=L.Location().XYZ().Z();
644     zToSet=Standard_False;
645   }
646
647   nbSeg++;
648   beginOnCurve[0]=parmin;
649   endOnCurve[0]=parmax;
650
651   if (xToSet) {
652     par1=L.Location().XYZ().X()+parmin*L.Direction().XYZ().X();
653     par2=L.Location().XYZ().X()+parmax*L.Direction().XYZ().X();
654     Xmin=Min(par1, par2);
655     Xmax=Max(par1, par2);
656   }
657
658   if (yToSet) {
659     par1=L.Location().XYZ().Y()+parmin*L.Direction().XYZ().Y();
660     par2=L.Location().XYZ().Y()+parmax*L.Direction().XYZ().Y();
661     Ymin=Min(par1, par2);
662     Ymax=Max(par1, par2);
663   }
664
665   if (zToSet) {
666     par1=L.Location().XYZ().Z()+parmin*L.Direction().XYZ().Z();
667     par2=L.Location().XYZ().Z()+parmax*L.Direction().XYZ().Z();
668     Zmin=Min(par1, par2);
669     Zmax=Max(par1, par2);
670   }
671
672   boxLin.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
673 }
674
675 //=======================================================================
676 //function : HyprBox
677 //purpose  : 
678 //=======================================================================
679 void Intf_Tool::HyprBox(const gp_Hypr& theHypr, 
680                         const Bnd_Box& domain, 
681                         Bnd_Box& boxHypr)
682 {
683   nbSeg=0;
684   boxHypr.SetVoid();
685   
686   if (domain.IsWhole()) {
687     boxHypr.SetWhole();
688     nbSeg=1;
689     //beginOnCurve[0]=-Precision::Infinite();
690     //endOnCurve[0]=Precision::Infinite();
691     beginOnCurve[0]=-100.;
692     endOnCurve[0]=100.;
693     return;
694   }
695   else if (domain.IsVoid())  {
696     return;
697   }
698   //
699   Standard_Integer nbPi;
700   //
701   nbPi=Inters3d(theHypr, domain);
702   if (nbPi>0) {
703     Standard_Integer npi;
704     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
705     //
706     domain.Get(Xmax, Ymax, Zmax, Xmin, Ymin, Zmin);
707     //
708     for (npi=0; npi<nbPi; npi++) {
709       Xmin=Min(Xmin, xint[npi]);
710       Xmax=Max(Xmax, xint[npi]);
711       Ymin=Min(Ymin, yint[npi]);
712       Ymax=Max(Ymax, yint[npi]);
713       Zmin=Min(Zmin, zint[npi]);
714       Zmax=Max(Zmax, yint[npi]);
715     }
716     boxHypr.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
717     //
718     Standard_Integer npj, npk;
719     Standard_Real parmin;
720     for (npi=0; npi<nbPi; npi++) {
721       npk=npi;
722       for (npj=npi+1; npj<nbPi; npj++) {
723         if (parint[npj]<parint[npk]) {
724           npk=npj;
725         }
726       }
727       if (npk!=npi) {
728         parmin=parint[npk];
729         parint[npk]=parint[npi];
730         parint[npi]=parmin;
731         npj=bord[npk];
732         bord[npk]=bord[npi];
733         bord[npi]=npj;
734       }
735     }
736     //
737     gp_Pnt Pn;
738     gp_Vec Tan;
739     Standard_Real sinan=0;
740     Standard_Boolean out=Standard_True;
741
742     for (npi=0; npi<nbPi; npi++) {
743       ElCLib::D1(parint[npi], theHypr, Pn, Tan);
744       switch (bord[npi]) {
745       case 1 : sinan=gp_XYZ( 1., 0., 0.)*Tan.XYZ(); break;
746       case 2 : sinan=gp_XYZ( 0., 1., 0.)*Tan.XYZ(); break;
747       case 3 : sinan=gp_XYZ( 0., 0., 1.)*Tan.XYZ(); break;
748       case 4 : sinan=gp_XYZ(-1., 0., 0.)*Tan.XYZ(); break;
749       case 5 : sinan=gp_XYZ( 0.,-1., 0.)*Tan.XYZ(); break;
750       case 6 : sinan=gp_XYZ( 0., 0.,-1.)*Tan.XYZ(); break;
751       }
752       if (Abs(sinan)>Precision::Angular()) {
753         if (sinan>0.) {
754           out=Standard_False;
755           beginOnCurve[nbSeg]=parint[npi];
756           //// modified by jgv, 10.11.2009 /////
757           endOnCurve[nbSeg] = 10.;
758           //////////////////////////////////////
759           nbSeg++;
760         }
761         else {
762           if (out) {
763             //modified by NIZNHY-PKV Fri Jul 11 13:59:10 2008f
764             beginOnCurve[nbSeg]=-10.;
765             //beginOnCurve[nbSeg]=-Precision::Infinite();
766             //modified by NIZNHY-PKV Fri Jul 11 13:59:13 2008t
767             nbSeg++;
768           }
769           endOnCurve[nbSeg-1]=parint[npi];
770           out=Standard_True;
771           //
772           //modified by NIZNHY-PKV Fri Jul 11 13:54:54 2008f
773           Standard_Real ipmin, ipmax, ip, pas;
774           //
775           ipmin=-10.;
776           if (beginOnCurve[nbSeg-1]>ipmin) {
777             ipmin=beginOnCurve[nbSeg-1];
778           }
779           ipmax=10.;
780           if (endOnCurve[nbSeg-1]<ipmax) {
781             ipmax=endOnCurve[nbSeg-1];
782           }
783           ipmin=ipmin*10.+1.;
784           ipmax=ipmax*10.-1.;
785           //
786           pas=1.;
787           for (ip=ipmin; ip<=ipmax; ip+=pas) {
788             boxHypr.Add(ElCLib::Value(ip/10., theHypr));
789             pas=10.;
790             if (fabs(ip)<=10.) {
791               pas=1.;
792             }
793           }
794           /*
795           Standard_Integer ipmin=Max((Standard_Integer)(beginOnCurve[nbSeg-1]), -10);
796           Standard_Integer ipmax=Min((Standard_Integer)(endOnCurve[nbSeg-1]),    10);
797           
798           ipmin=ipmin*10+1;
799           ipmax=ipmax*10-1;
800           Standard_Integer ip, pas=1;
801           for (ip=ipmin; ip<=ipmax; ip+=pas) {
802             boxHypr.Add(ElCLib::Value(Standard_Real(ip)/10., theHypr));
803             
804             if (Abs(ip)<=10) {
805               pas=1;
806             }
807             else {
808               pas=10;
809             }
810           }
811           */
812           //modified by NIZNHY-PKV Fri Jul 11 13:55:04 2008t
813         }
814       }
815     }
816   }//if (nbPi>0) {
817   else if (!domain.IsOut(ElCLib::Value(0., theHypr))) {
818     boxHypr=domain;
819     //beginOnCurve[0]=-Precision::Infinite();
820     //endOnCurve[0]=Precision::Infinite();
821     beginOnCurve[0]=-100.;
822     endOnCurve[0]=100.;
823     nbSeg=1;
824   }
825 }
826
827 //=======================================================================
828 //function : Inters3d
829 //purpose  : 
830 //=======================================================================
831
832 Standard_Integer Intf_Tool::Inters3d(const gp_Hypr& theCurv,
833                                     const Bnd_Box& Domain)
834 {
835   Standard_Integer nbpi=0;
836   Standard_Integer npi;
837   Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
838
839   Domain.Get(xmin, ymin, zmin, xmax, ymax, zmax);
840
841   if (!Domain.IsOpenXmin()) {
842     IntAna_IntConicQuad Inters1(theCurv, 
843                                 gp_Pln(1., 0., 0., xmin),
844                                 Precision::Angular());
845     if (Inters1.IsDone()) {
846       if (!Inters1.IsInQuadric()) {
847         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
848           yint[nbpi]=Inters1.Point(npi).Y();
849           zint[nbpi]=Inters1.Point(npi).Z();
850           if (ymin <=yint[nbpi] && yint[nbpi] < ymax &&
851               zmin <=zint[nbpi] && zint[nbpi] < zmax) {
852             xint[nbpi]=xmin;
853             parint[nbpi]=Inters1.ParamOnConic(npi);
854             bord[nbpi]=1;
855             nbpi++;
856           }
857         }
858       }
859     }
860   }
861
862   if (!Domain.IsOpenYmin()) {
863     IntAna_IntConicQuad Inters1(theCurv, 
864                                 gp_Pln( 0., 1., 0., ymin),
865                                 Precision::Angular());
866     if (Inters1.IsDone()) {
867       if (!Inters1.IsInQuadric()) {
868         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
869           xint[nbpi]=Inters1.Point(npi).X();
870           zint[nbpi]=Inters1.Point(npi).Z();
871           if (xmin < xint[nbpi] && xint[nbpi] <=xmax &&
872               zmin <=zint[nbpi] && zint[nbpi] < zmax) {
873             yint[nbpi]=ymin;
874             parint[nbpi]=Inters1.ParamOnConic(npi);
875             bord[nbpi]=2;
876             nbpi++;
877           }
878         }
879       }
880     }
881   }
882
883   if (!Domain.IsOpenZmin()) {
884     IntAna_IntConicQuad Inters1(theCurv, 
885                                 gp_Pln( 0., 0., 1., zmin),
886                                 Precision::Angular());
887     if (Inters1.IsDone()) {
888       if (!Inters1.IsInQuadric()) {
889         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
890           xint[nbpi]=Inters1.Point(npi).X();
891           yint[nbpi]=Inters1.Point(npi).Y();
892           if (xmin < xint[nbpi] && xint[nbpi] <=xmax &&
893               ymin < yint[nbpi] && yint[nbpi] <=ymax) {
894             zint[nbpi]=zmin;
895             parint[nbpi]=Inters1.ParamOnConic(npi);
896             bord[nbpi]=3;
897             nbpi++;
898           }
899         }
900       }
901     }
902   }
903
904   if (!Domain.IsOpenXmax()) {
905     IntAna_IntConicQuad Inters1(theCurv, 
906                                 gp_Pln(-1., 0., 0., xmax),
907                                 Precision::Angular());
908     if (Inters1.IsDone()) {
909       if (!Inters1.IsInQuadric()) {
910         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
911           yint[nbpi]=Inters1.Point(npi).Y();
912           zint[nbpi]=Inters1.Point(npi).Z();
913           if (ymin < yint[nbpi] && yint[nbpi] <=ymax &&
914               zmin < zint[nbpi] && zint[nbpi] <=zmax) {
915             xint[nbpi]=xmax;
916             parint[nbpi]=Inters1.ParamOnConic(npi);
917             bord[nbpi]=4;
918             nbpi++;
919           }
920         }
921       }
922     }
923   }
924
925   if (!Domain.IsOpenYmax()) {
926     IntAna_IntConicQuad Inters1(theCurv, 
927                                 gp_Pln( 0.,-1., 0., ymax),
928                                 Precision::Angular());
929     if (Inters1.IsDone()) {
930       if (!Inters1.IsInQuadric()) {
931         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
932           xint[nbpi]=Inters1.Point(npi).X();
933           zint[nbpi]=Inters1.Point(npi).Z();
934           if (xmin <=xint[nbpi] && xint[nbpi] < xmax &&
935               zmin < zint[nbpi] && zint[nbpi] <=zmax) {
936             yint[nbpi]=ymax;
937             parint[nbpi]=Inters1.ParamOnConic(npi);
938             bord[nbpi]=5;
939             nbpi++;
940           }
941         }
942       }
943     }
944   }
945
946   if (!Domain.IsOpenZmax()) {
947     IntAna_IntConicQuad Inters1(theCurv, 
948                                 gp_Pln( 0., 0.,-1., zmax),
949                                 Precision::Angular());
950     if (Inters1.IsDone()) {
951       if (!Inters1.IsInQuadric()) {
952         for (npi=1; npi<=Inters1.NbPoints(); npi++) {
953           xint[nbpi]=Inters1.Point(npi).X();
954           yint[nbpi]=Inters1.Point(npi).Y();
955           if (xmin <=xint[nbpi] && xint[nbpi] < xmax &&
956               ymin <=yint[nbpi] && yint[nbpi] < ymax) {
957             zint[nbpi]=zmax;
958             parint[nbpi]=Inters1.ParamOnConic(npi);
959             bord[nbpi]=6;
960             nbpi++;
961           }
962         }
963       }
964     }
965   }
966   return nbpi;
967 }
968
969
970 //=======================================================================
971 //function : ParabBox
972 //purpose  : 
973 //=======================================================================
974
975 void  Intf_Tool::ParabBox(const gp_Parab&, 
976                          const Bnd_Box& domain, 
977                          Bnd_Box& boxParab)
978 {
979   nbSeg=0;
980   boxParab.SetVoid();
981   if        (domain.IsWhole()) {
982     boxParab.SetWhole();
983     nbSeg=1;
984     beginOnCurve[0]=-Precision::Infinite();
985     endOnCurve[0]=Precision::Infinite();
986     return;
987   }
988   else if   (domain.IsVoid())  return;
989
990   
991 }
992
993
994 //=======================================================================
995 //function : NbSegments
996 //purpose  : 
997 //=======================================================================
998
999 Standard_Integer Intf_Tool::NbSegments() const
1000 {
1001   return nbSeg;
1002 }
1003
1004 //=======================================================================
1005 //function : BeginParam
1006 //purpose  : 
1007 //=======================================================================
1008
1009 Standard_Real Intf_Tool::BeginParam(const Standard_Integer SegmentNum) const
1010 {
1011   Standard_OutOfRange_Raise_if(SegmentNum<1 || SegmentNum>nbSeg ,
1012                                "Intf_Tool::BeginParam");
1013   return beginOnCurve[SegmentNum-1];
1014 }
1015
1016 //=======================================================================
1017 //function : EndParam
1018 //purpose  : 
1019 //=======================================================================
1020
1021 Standard_Real Intf_Tool::EndParam(const Standard_Integer SegmentNum) const
1022 {
1023   Standard_OutOfRange_Raise_if(SegmentNum<1 || SegmentNum>nbSeg ,
1024                                "Intf_Tool::EndParam");
1025   return endOnCurve[SegmentNum-1];
1026 }
1027