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