Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Select3D / Select3D_SensitiveCircle.cxx
1 // File:    Select3D_SensitiveCircle.cxx
2 // Created: Tue Feb  6 14:15:06 1996
3 // Author:  Robert COUBLANC
4 //      <rob@fidox>
5 // Modified    Tue Apr 14 1998 by rob : fix Bug : Case of Null Radius Circle...
6
7 #include <Select3D_SensitiveCircle.ixx>
8 #include <Precision.hxx>
9 #include <gp_Lin2d.hxx>
10
11 #include <CSLib_Class2d.hxx>
12 #include <Select3D_SensitiveTriangle.hxx>
13 #include <ElCLib.hxx>
14 #include <Select3D_Pnt.hxx>
15 #include <Select3D_Pnt2d.hxx>
16
17 //=======================================================================
18 //function : Select3D_SensitiveCircle (constructeur)
19 //purpose  : Definition d'un cercle sensible
20 //=======================================================================
21 static Standard_Integer S3D_GetCircleNBPoints(const Handle(Geom_Circle)& C,
22                                               const Standard_Integer anInputNumber)
23
24   if(C->Radius()>Precision::Confusion())
25     return 2*anInputNumber+1;
26   return 1;
27 }
28 static Standard_Integer S3D_GetArcNBPoints(const Handle(Geom_Circle)& C,
29                     const Standard_Integer anInputNumber)
30
31   if(C->Radius()>Precision::Confusion())
32     return 2*anInputNumber-1;
33   return 1;
34 }
35      
36 Select3D_SensitiveCircle::
37 Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId, 
38              const Handle(Geom_Circle)& TheCircle, 
39              const Standard_Boolean FilledCircle,
40              const Standard_Integer NbPoints):
41 Select3D_SensitivePoly(OwnerId, S3D_GetCircleNBPoints(TheCircle,NbPoints)),
42 myFillStatus(FilledCircle),
43 myDetectedIndex(-1)
44 {
45   if(mynbpoints!=1){
46     gp_Pnt p1,p2;//,pmid;
47     gp_Vec v1;//,v2;
48     Standard_Real ustart = TheCircle->FirstParameter(),uend = TheCircle->LastParameter();
49     Standard_Real du = (uend-ustart)/NbPoints;
50     Standard_Real R = TheCircle->Radius();
51     Standard_Integer rank = 1;
52     Standard_Real curu =ustart;
53     for(Standard_Integer i=1;i<=NbPoints;i++) 
54     {
55       TheCircle->D1(curu,p1,v1);
56     
57       v1.Normalize();
58       ((Select3D_Pnt*)mypolyg3d)[rank-1] = p1;
59       rank++;
60       p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
61             p1.Y()+v1.Y()*tan(du/2.)*R,
62             p1.Z()+v1.Z()*tan(du/2.)*R);
63       ((Select3D_Pnt*)mypolyg3d)[rank-1] = p2;
64       rank++;
65       curu+=du;
66     }
67     ((Select3D_Pnt*)mypolyg3d)[NbPoints*2] = ((Select3D_Pnt*)mypolyg3d)[0];
68   }
69   // Radius = 0.0
70   else
71     ((Select3D_Pnt*)mypolyg3d)[0] = TheCircle->Location();
72 }
73
74 //=======================================================================
75 //function : Select3D_SensitiveCircle (constructeur)
76 //purpose  : Definition d'un arc sensible
77 //=======================================================================
78 Select3D_SensitiveCircle::
79 Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId, 
80              const Handle(Geom_Circle)& TheCircle,
81              const Standard_Real u1,
82              const Standard_Real u2,
83              const Standard_Boolean FilledCircle,
84              const Standard_Integer NbPoints):
85 Select3D_SensitivePoly(OwnerId, S3D_GetArcNBPoints(TheCircle,NbPoints)),
86 myFillStatus(FilledCircle),
87 myDetectedIndex(-1)
88 {
89
90   if(mynbpoints > 1){
91     gp_Pnt p1,p2;//,pmid;
92     gp_Vec v1;//,v2;
93     
94     Standard_Real ustart = u1;
95     Standard_Real uend = u2;
96     
97     if (u1 > u2) {ustart=u1;uend=u2;}
98     
99     Standard_Real du = (uend-ustart)/(NbPoints-1);
100     Standard_Real R = TheCircle->Radius();
101     Standard_Integer rank = 1;
102     Standard_Real curu =ustart;
103     
104     
105     
106     for(Standard_Integer i=1;i<=NbPoints-1;i++)
107     {
108       TheCircle->D1(curu,p1,v1);
109       v1.Normalize();
110       ((Select3D_Pnt*)mypolyg3d)[rank-1] = p1;
111       rank++;
112       p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
113             p1.Y()+v1.Y()*tan(du/2.)*R,
114             p1.Z()+v1.Z()*tan(du/2.)*R);
115       ((Select3D_Pnt*)mypolyg3d)[rank-1] = p2;            
116       rank++;
117       curu+=du;
118     }
119     TheCircle->D0(uend,p1);
120     ((Select3D_Pnt*)mypolyg3d)[NbPoints*2-2] = p1;            
121   }
122   else
123     ((Select3D_Pnt*)mypolyg3d)[0] = TheCircle->Location();                
124 }
125
126 //=======================================================================
127 //function : Select3D_SensitiveCircle
128 //purpose  : 
129 //=======================================================================
130 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
131                            const Handle(TColgp_HArray1OfPnt)& Thepolyg3d,
132                            const Standard_Boolean FilledCircle):
133 Select3D_SensitivePoly(OwnerId, Thepolyg3d),
134 myFillStatus(FilledCircle),
135 myDetectedIndex(-1)
136 {
137   
138 }
139 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
140                            const TColgp_Array1OfPnt& Thepolyg3d,
141                            const Standard_Boolean FilledCircle):
142 Select3D_SensitivePoly(OwnerId, Thepolyg3d),
143 myFillStatus(FilledCircle),
144 myDetectedIndex(-1)
145 {
146 }
147
148 Standard_Boolean Select3D_SensitiveCircle::
149 Matches(const Standard_Real X, 
150     const Standard_Real Y, 
151     const Standard_Real aTol, 
152     Standard_Real& DMin)
153 {
154   
155
156   // dans le cas Edge (pourtour de la face seulement 
157   //on regarde si le point souris X,Y se trouve a l'interieur du triangle
158   // pi,pi+1,pi+2 a la tolerance pres... si oui on a fini...
159   if(mynbpoints>1){
160     Standard_Boolean Found =Standard_False;
161     Standard_Integer i = 0;
162     //gp_Pnt2d p1,p2,p3,pg;
163     
164     if(!myFillStatus){
165       while(i < mynbpoints-2 && !Found) {
166     Standard_Integer TheStat = 
167       Select3D_SensitiveTriangle::Status(((Select3D_Pnt2d*)mypolyg2d)[i],
168                          ((Select3D_Pnt2d*)mypolyg2d)[i+1],
169                          ((Select3D_Pnt2d*)mypolyg2d)[i+2],
170                          gp_XY(X,Y),aTol,DMin);
171     Found = (TheStat!=2);
172     if(Found) myDetectedIndex=i;
173     i+=2;
174     
175       }
176     }
177     else {
178       myDetectedIndex =-1;
179 #ifndef DEB
180       Standard_Real DMin2 = 0.;
181 #else
182       Standard_Real DMin2;
183 #endif
184       Standard_Real Xmin,Ymin,Xmax,Ymax;
185       Bnd_Box2d(mybox2d).Get(Xmin,Ymin,Xmax,Ymax);
186       if(!Bnd_Box2d(mybox2d).IsVoid())
187         DMin2 = gp_XY(Xmax-Xmin,Ymax-Ymin).SquareModulus();
188       TColgp_Array1OfPnt2d aArrayOf2dPnt(1, mynbpoints);
189       Points2D(aArrayOf2dPnt);
190       CSLib_Class2d TheInOutTool(aArrayOf2dPnt,aTol,aTol,Xmin,Ymin,Xmax,Ymax);
191       Standard_Integer TheStat = TheInOutTool.SiDans(gp_Pnt2d(X,Y));
192       Standard_Real aTol2 = aTol*aTol;
193       if(TheStat!=1) {
194         for(Standard_Integer I=0;i<mynbpoints-1;i+=2){
195           gp_XY V1(((Select3D_Pnt2d*)mypolyg2d)[I+1]),V(X,Y);
196           V1-=((Select3D_Pnt2d*)mypolyg2d)[I];
197           V-=((Select3D_Pnt2d*)mypolyg2d)[I];
198           Standard_Real Vector = V1^V;
199           Standard_Real V1V1 = V1.SquareModulus();
200           DMin2 = 
201             (V1V1 <=aTol2) ? 
202               Min(DMin2,V.SquareModulus()): // si le segment est trop petit...
203                 Min(DMin2,Vector*Vector/V1V1);
204           
205         }
206         Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
207         return Standard_True;
208       }
209       return Standard_False;
210       
211     }
212     if(!Found) 
213       myDetectedIndex=-1;
214     else
215       Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
216     
217     return Found;
218   }
219   return Standard_True;
220
221 }
222 Standard_Boolean Select3D_SensitiveCircle::
223 Matches(const Standard_Real XMin,
224     const Standard_Real YMin,
225     const Standard_Real XMax,
226     const Standard_Real YMax,
227     const Standard_Real aTol)
228 {
229   myDetectedIndex =-1;
230   Bnd_Box2d abox;
231   abox.Update(Min(XMin,XMax),Min(YMin,YMax),Max(XMin,XMax),Max(YMin,YMax));
232   abox.Enlarge(aTol);
233   for(Standard_Integer i=0;i<mynbpoints;i++)
234     if(abox.IsOut(((Select3D_Pnt2d*)mypolyg2d)[i])) return Standard_False;
235
236   return Standard_True;
237 }
238
239
240 //=======================================================================
241 //function : Matches
242 //purpose  : 
243 //=======================================================================
244
245 Standard_Boolean Select3D_SensitiveCircle::
246 Matches (const TColgp_Array1OfPnt2d& aPoly,
247      const Bnd_Box2d& aBox,
248      const Standard_Real aTol)
249
250   Standard_Real Umin,Vmin,Umax,Vmax;
251   aBox.Get(Umin,Vmin,Umax,Vmax);
252   Standard_Real Tolu,Tolv;
253   Tolu = 1e-7;
254   Tolv = 1e-7;
255   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
256
257   for(Standard_Integer j=1;j<=mynbpoints;j++){
258     Standard_Integer RES = aClassifier2d.SiDans(((Select3D_Pnt2d*)mypolyg2d)[j-1]);
259     if(RES!=1) return Standard_False;
260   }
261   return Standard_True;
262 }
263
264
265
266
267 void Select3D_SensitiveCircle::
268 ArrayBounds(Standard_Integer & Low,
269           Standard_Integer & Up) const
270 {
271   Low = 0;
272   Up  = mynbpoints-1;
273 }
274
275
276 gp_Pnt Select3D_SensitiveCircle::
277 GetPoint3d(const Standard_Integer Rank) const
278 {
279   if(Rank>=0&& Rank<mynbpoints)
280     return ((Select3D_Pnt*)mypolyg3d)[Rank];
281   return ((Select3D_Pnt*)mypolyg3d)[0];
282 }
283
284
285 //=======================================================================
286 //function : Dump
287 //purpose  : 
288 //=======================================================================
289
290 void Select3D_SensitiveCircle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
291 {
292   //  Standard_Integer rank(1);
293   gp_XYZ CDG(0.,0.,0.);
294   
295   S<<"\tSensitiveCircle 3D :";
296   
297   Standard_Boolean isclosed = 1== mynbpoints;
298   if(isclosed)
299     S<<"(Closed Circle)"<<endl;
300   else
301     S<<"(Arc Of Circle)"<<endl;
302   
303   if(HasLocation())
304     S<<"\t\tExisting Location"<<endl;
305   
306
307   if(FullDump){
308     Standard_Integer EndIndex = isclosed? mynbpoints-2 : mynbpoints-1, nbpt(0);
309     for(Standard_Integer i=0;i<EndIndex;i+=2){
310       CDG +=((Select3D_Pnt*)mypolyg3d)[i];
311       nbpt++;
312     }
313     
314     CDG/=nbpt;
315     
316     Standard_Real R = (CDG-((Select3D_Pnt*)mypolyg3d)[0]).Modulus();
317     
318     S<<"\t\t Center : ("<<CDG.X()<<" , "<<CDG.Y()<<" , "<<CDG.Z()<<" )"<<endl;
319     S<<"\t\t Radius :"<<R<<endl;
320     
321   }
322 }
323 Standard_Real Select3D_SensitiveCircle::ComputeDepth(const gp_Lin& EyeLine) const
324 {
325   gp_Pnt CDG;
326   if(myDetectedIndex==-1){
327     gp_XYZ CurCoord(((Select3D_Pnt*)mypolyg3d)[0]);
328     Standard_Boolean isclosed = 1==mynbpoints;
329     Standard_Integer EndIndex = isclosed ? mynbpoints-2 : mynbpoints-1, nbpt(0);
330     for(Standard_Integer i=1;i<EndIndex;i+=2){
331       CurCoord +=((Select3D_Pnt*)mypolyg3d)[i];
332       nbpt++;
333     }
334     CDG.SetXYZ(CurCoord);
335   }
336   else{
337     gp_XYZ CurCoord(((Select3D_Pnt*)mypolyg3d)[myDetectedIndex]);
338     CurCoord+=((Select3D_Pnt*)mypolyg3d)[myDetectedIndex+1];
339     CurCoord+=((Select3D_Pnt*)mypolyg3d)[myDetectedIndex+2];
340     CDG.SetXYZ(CurCoord);
341   }
342
343   return  ElCLib::Parameter(EyeLine,CDG);
344   
345 }