6b65e87e36913f55597f5183adbb2dd86eaa1263
[occt.git] / src / Select3D / Select3D_Projector.cxx
1 // File:        Select3D_Projector.cxx
2 // Created:     Fri Mar 13 11:08:32 1992
3 // Author:      Christophe MARION
4 //              <cma@sdsun2>
5
6 #define IMP240100       //GG 
7 //                      Change RefToPix()/Convert() to Project() method.
8
9 #include <Select3D_Projector.ixx>
10 #include <Precision.hxx>
11 #include <gp_Ax3.hxx>
12 #include <gp_Vec.hxx>
13 #include <gp_Vec2d.hxx>
14
15 // formula for derivating a perspective, from Mathematica
16
17 //        X'[t]      X[t] Z'[t]                                     
18 // D1 =  -------- + -------------                                   
19 //           Z[t]          Z[t] 2                                   
20 //       1 - ----   f (1 - ----)                                    
21 //            f             f                                       
22
23 //=======================================================================
24 //function : Select3D_Projector
25 //purpose  : 
26 //=======================================================================
27
28
29 Select3D_Projector::Select3D_Projector(const Handle(V3d_View)& aViou):
30 myPersp(aViou->Type()==V3d_PERSPECTIVE),
31 myFocus(aViou->Focale()),
32 myD1(1,0),
33 myD2(0,1),
34 myD3(1,1),
35 myView(aViou)
36 {
37   Standard_Real Xat,Yat,Zat,XUp,YUp,ZUp,DX,DY,DZ;
38   //Standard_Boolean Pers=Standard_False;
39   
40   aViou->At(Xat,Yat,Zat);
41   aViou->Up(XUp,YUp,ZUp);
42   aViou->Proj(DX,DY,DZ);
43   gp_Pnt At (Xat,Yat,Zat); 
44   gp_Dir Zpers (DX,DY,DZ);
45   gp_Dir Ypers (XUp,YUp,ZUp);
46   gp_Dir Xpers = Ypers.Crossed(Zpers);
47   gp_Ax3 Axe (At, Zpers, Xpers);
48   myScaledTrsf.SetTransformation(Axe);
49   myGTrsf.SetTrsf(myScaledTrsf);
50   Scaled();
51   
52 }
53
54 Select3D_Projector::Select3D_Projector () :
55 myPersp(Standard_False),myFocus(0),myD1(1,0),myD2(0,1),myD3(1,1)
56 {
57   Scaled();
58   SetDirection();
59
60
61 //=======================================================================
62 //function : Select3D_Projector
63 //purpose  : 
64 //=======================================================================
65
66 Select3D_Projector::Select3D_Projector 
67   (const gp_Ax2& CS) :
68   myPersp(Standard_False), myFocus(0)
69 {
70   myScaledTrsf.SetTransformation(CS);
71   myGTrsf.SetTrsf(myScaledTrsf);
72   Scaled();
73   SetDirection();
74 }
75
76 //=======================================================================
77 //function : Select3D_Projector
78 //purpose  : 
79 //=======================================================================
80
81 Select3D_Projector::Select3D_Projector 
82   (const gp_Ax2& CS, 
83    const Standard_Real Focus) :
84   myPersp(Standard_True), myFocus(Focus)
85 {
86   myScaledTrsf.SetTransformation(CS);
87   myGTrsf.SetTrsf(myScaledTrsf);
88   Scaled();
89   SetDirection();
90 }
91
92 //=======================================================================
93 //function : Select3D_Projector
94 //purpose  : 
95 //=======================================================================
96
97 Select3D_Projector::Select3D_Projector 
98   (const gp_Trsf& T, 
99    const Standard_Boolean Persp,
100    const Standard_Real Focus) :
101   myPersp(Persp),
102   myFocus(Focus),
103   myScaledTrsf(T)
104 {
105   myGTrsf.SetTrsf(myScaledTrsf);
106   Scaled();
107   SetDirection();
108 }
109
110 //=======================================================================
111 //function : Select3D_Projector
112 //purpose  : 
113 //=======================================================================
114
115 Select3D_Projector::Select3D_Projector 
116   (const gp_Trsf& T, 
117    const Standard_Boolean Persp,
118    const Standard_Real Focus,
119    const gp_Vec2d& v1,
120    const gp_Vec2d& v2,
121    const gp_Vec2d& v3) :
122   myPersp(Persp),
123   myFocus(Focus),
124   myScaledTrsf(T),
125   myD1(v1),
126   myD2(v2),
127   myD3(v3)
128 {
129   myGTrsf.SetTrsf(myScaledTrsf);
130   Scaled();
131 }
132
133 //=======================================================================
134 //function : Select3D_Projector
135 //purpose  : 
136 //=======================================================================
137
138 Select3D_Projector::Select3D_Projector 
139   (const gp_GTrsf& GT, 
140    const Standard_Boolean Persp,
141    const Standard_Real Focus) :
142   myPersp(Persp),
143   myFocus(Focus),
144   myGTrsf(GT)
145 {
146   Scaled();
147   SetDirection();
148 }
149
150 void Select3D_Projector::Delete()
151 {}
152
153 //=======================================================================
154 //function : Set
155 //purpose  : 
156 //=======================================================================
157
158 void Select3D_Projector::Set
159   (const gp_Trsf& T, 
160    const Standard_Boolean Persp,
161    const Standard_Real Focus) 
162 {
163   myPersp      = Persp;
164   myFocus      = Focus;
165   myScaledTrsf = T;
166   Scaled();
167   SetDirection();
168 }
169
170 //=======================================================================
171 //function : Scaled
172 //purpose  : 
173 //=======================================================================
174
175 #include <gp_Mat.hxx>
176
177 static Standard_Integer TrsfType(const gp_GTrsf& Trsf) { 
178   const gp_Mat& Mat = Trsf.VectorialPart();
179   if(   (Abs(Mat.Value(1,1)-1.0) < 1e-15) 
180      && (Abs(Mat.Value(2,2)-1.0) < 1e-15)
181      && (Abs(Mat.Value(3,3)-1.0) < 1e-15)) { 
182     return(1); //-- top
183   }
184   else if(   (Abs(Mat.Value(1,1)-0.7071067811865476) < 1e-15)
185           && (Abs(Mat.Value(1,2)+0.5) < 1e-15)
186           && (Abs(Mat.Value(1,3)-0.5) < 1e-15)
187           
188           && (Abs(Mat.Value(2,1)-0.7071067811865476) < 1e-15)
189           && (Abs(Mat.Value(2,2)-0.5) < 1e-15)
190           && (Abs(Mat.Value(2,3)+0.5) < 1e-15)
191           
192           && (Abs(Mat.Value(3,1)) < 1e-15)  
193           && (Abs(Mat.Value(3,2)-0.7071067811865476) < 1e-15)
194           && (Abs(Mat.Value(3,3)-0.7071067811865476) < 1e-15)) { 
195     return(0); //-- 
196   }
197   else if(   (Abs(Mat.Value(1,1)-1.0) < 1e-15) 
198           && (Abs(Mat.Value(2,3)-1.0) < 1e-15)
199           && (Abs(Mat.Value(3,2)+1.0) < 1e-15)) { 
200     return(2); //-- front
201   }
202   else if(   (Abs(Mat.Value(1,1)-0.7071067811865476) < 1e-15)
203           && (Abs(Mat.Value(1,2)-0.7071067811865476) < 1e-15)
204           && (Abs(Mat.Value(1,3)) < 1e-15)
205           
206           && (Abs(Mat.Value(2,1)+0.5) < 1e-15)
207           && (Abs(Mat.Value(2,2)-0.5) < 1e-15)
208           && (Abs(Mat.Value(2,3)-0.7071067811865476) < 1e-15)
209           
210           && (Abs(Mat.Value(3,1)-0.5) < 1e-15)  
211           && (Abs(Mat.Value(3,2)+0.5) < 1e-15)
212           && (Abs(Mat.Value(3,3)-0.7071067811865476) < 1e-15)) { 
213     return(3); //-- axo
214   }
215   return(-1);
216 }
217
218 void Select3D_Projector::Scaled (const Standard_Boolean On)
219
220   myType=-1;
221   if (!On) {
222     if (!myPersp) { 
223       //myGTrsf.SetTranslationPart(gp_XYZ(0.,0.,0.));
224       myType=TrsfType(myGTrsf); 
225     }
226   }
227   myInvTrsf = myGTrsf;
228   myInvTrsf.Invert();
229 }
230
231 //=======================================================================
232 //function : Project
233 //purpose  : 
234 //=======================================================================
235
236 void Select3D_Projector::Project (const gp_Pnt& P, gp_Pnt2d& Pout) const
237 {
238
239   if(!myView.IsNull()){
240     Standard_Real Xout,Yout;
241 //    V3d_View
242 #ifdef IMP240100
243     myView->Project(P.X(),P.Y(),P.Z(),Xout,Yout);
244 #else
245     Standard_Integer Xp,Yp;
246     myView->RefToPix(P.X(),P.Y(),P.Z(),Xp,Yp);
247     myView->Convert(Xp,Yp,Xout,Yout);
248 #endif
249     Pout.SetCoord(Xout,Yout);
250   }
251   else{
252     if(myType!=-1) { 
253       Standard_Real X,Y;
254       switch (myType) { 
255       case 0: {  //-- axono standard
256         Standard_Real x07 = P.X()*0.7071067811865475;
257         Standard_Real y05 = P.Y()*0.5;
258         Standard_Real z05 = P.Z()*0.5;
259         X=x07-y05+z05;
260         Y=x07+y05-z05;
261         //-- Z=0.7071067811865475*(P.Y()+P.Z());
262         break;
263       }
264       case 1: { //-- top
265         X=P.X(); Y=P.Y(); //-- Z=P.Z();
266         Pout.SetCoord(X,Y);
267         break;
268       }
269       case 2: { 
270         X=P.X(); Y=P.Z(); //-- Z=-P.Y();
271         Pout.SetCoord(X,Y);
272         break;
273       }
274       case 3: { 
275         Standard_Real xmy05 = (P.X()-P.Y())*0.5;
276         Standard_Real z07 = P.Z()*0.7071067811865476;
277         X=0.7071067811865476*(P.X()+P.Y());
278         Y=-xmy05+z07;
279         Pout.SetCoord(X,Y);
280         //-- Z= xmy05+z07;
281         break;
282       }
283       default: { 
284         gp_Pnt P2 = P;
285         Transform(P2);
286         if (myPersp) {
287           Standard_Real R = 1.-P2.Z()/myFocus;
288           Pout.SetCoord(P2.X()/R,P2.Y()/R);
289         }
290         else 
291           Pout.SetCoord(P2.X(),P2.Y());    
292         break;
293       }
294       }
295     }
296     else { 
297       gp_Pnt P2 = P;
298       Transform(P2);
299       if (myPersp) {
300         Standard_Real R = 1.-P2.Z()/myFocus;
301         Pout.SetCoord(P2.X()/R,P2.Y()/R);
302       }
303       else 
304         Pout.SetCoord(P2.X(),P2.Y()); 
305     }
306   }
307   
308
309 }
310
311 //=======================================================================
312 //function : Project
313 //purpose  : 
314 //=======================================================================
315 /*  ====== TYPE 0  (??)
316    (0.7071067811865476, -0.5               ,  0.4999999999999999)
317    (0.7071067811865475,  0.5000000000000001, -0.5              )
318    (0.0,                 0.7071067811865475,  0.7071067811865476)
319
320   ====== TYPE 1 (top)
321 (1.0, 0.0, 0.0)
322 (0.0, 1.0, 0.0)
323 (0.0, 0.0, 1.0)
324
325  ======= TYPE 2 (front)
326 (1.0,  0.0                   , 0.0)
327 (0.0,  1.110223024625157e-16 , 1.0)
328 (0.0, -1.0                   , 1.110223024625157e-16)
329
330  ======= TYPE 3 
331 ( 0.7071067811865476, 0.7071067811865475, 0.0)
332 (-0.5               , 0.5000000000000001, 0.7071067811865475)
333 ( 0.4999999999999999, -0.5              , 0.7071067811865476)
334 */
335 void Select3D_Projector::Project (const gp_Pnt& P,
336                                  Standard_Real& X,
337                                  Standard_Real& Y,
338                                  Standard_Real& Z) const
339 {
340   if(!myView.IsNull()){
341 //    Standard_Real Xout,Yout;
342 //    V3d_View
343 #ifdef IMP240100
344     myView->Project(P.X(),P.Y(),P.Z(),X,Y);
345 #else
346     Standard_Integer Xp,Yp;
347     myView->RefToPix(P.X(),P.Y(),P.Z(),Xp,Yp);
348     myView->Convert(Xp,Yp,X,Y);
349 #endif
350   }
351   else{
352     if(myType!=-1) { 
353       switch (myType) { 
354       case 0: {  //-- axono standard
355         Standard_Real x07 = P.X()*0.7071067811865475;
356         Standard_Real y05 = P.Y()*0.5;
357         Standard_Real z05 = P.Z()*0.5;
358         X=x07-y05+z05;
359         Y=x07+y05-z05;
360         Z=0.7071067811865475*(P.Y()+P.Z());
361         break;
362       }
363       case 1: { //-- top
364         X=P.X(); Y=P.Y(); Z=P.Z();
365         break;
366       }
367       case 2: { 
368         X=P.X(); Y=P.Z(); Z=-P.Y();
369         break;
370       }
371       case 3: { 
372         Standard_Real xmy05 = (P.X()-P.Y())*0.5;
373         Standard_Real z07 = P.Z()*0.7071067811865476;
374         X=0.7071067811865476*(P.X()+P.Y());
375         Y=-xmy05+z07;
376         Z= xmy05+z07;
377         break;
378       }
379       default: { 
380         gp_Pnt P2 = P;
381         Transform(P2);
382         P2.Coord(X,Y,Z);
383         break;
384       }
385       }
386     }
387     else { 
388       gp_Pnt P2 = P;
389       Transform(P2);
390       P2.Coord(X,Y,Z);
391       if (myPersp) {
392         Standard_Real R = 1 - Z / myFocus;
393         X = X / R;
394         Y = Y / R;
395       }
396     }
397   }
398 }
399 //=======================================================================
400 //function : Project
401 //purpose  : 
402 //=======================================================================
403
404 void Select3D_Projector::Project (const gp_Pnt& P,
405                                  const gp_Vec& D1,
406                                  gp_Pnt2d& Pout,
407                                  gp_Vec2d& D1out) const
408 {
409   gp_Pnt PP = P;
410   Transform(PP);
411   gp_Vec DD1 = D1;
412   Transform(DD1);
413   if (myPersp) {
414     Standard_Real R = 1. - PP.Z() / myFocus;
415     Pout .SetCoord(PP .X()/R , PP.Y()/R);
416     D1out.SetCoord(DD1.X()/R + PP.X()*DD1.Z()/(myFocus * R*R),
417                    DD1.Y()/R + PP.Y()*DD1.Z()/(myFocus * R*R));
418   }
419   else {
420     Pout .SetCoord(PP .X(),PP .Y());
421     D1out.SetCoord(DD1.X(),DD1.Y());
422   }
423 }
424
425 //=======================================================================
426 //function : BoxAdd
427 //purpose  : 
428 //=======================================================================
429
430 void Select3D_Projector::BoxAdd
431   (const gp_Pnt2d& P,
432    Bnd_Box& B) const
433 {
434   gp_Vec2d V(P.X(),P.Y());
435   gp_Pnt PP(myD1 * V, myD2 * V, myD3 * V);
436   B.Add(PP);
437 }
438
439 //=======================================================================
440 //function : Shoot
441 //purpose  : 
442 //=======================================================================
443
444 gp_Lin Select3D_Projector::Shoot
445   (const Standard_Real X,
446    const Standard_Real Y) const
447 {
448   gp_Lin L;
449   
450   if (myPersp) {
451     L = gp_Lin(gp_Pnt(0,0, myFocus),
452                gp_Dir(X,Y,-myFocus));
453   }
454   else {
455     L = gp_Lin(gp_Pnt(X,Y,0),
456                gp_Dir(0,0,-1));
457   }
458   Transform(L, myInvTrsf);
459   return L;
460 }
461
462
463 //=======================================================================
464 //function : SetDirection
465 //purpose  : 
466 //=======================================================================
467
468 void Select3D_Projector::SetDirection () 
469 {
470   gp_Vec V1(1,0,0);
471   Transform(V1);
472   if ((Abs(V1.X()) + Abs(V1.Y())) < Precision::Angular()) V1.SetCoord(1,1,0);
473   gp_Vec2d D1(V1.X(),V1.Y());
474   myD1.SetCoord(-D1.Y(),D1.X());
475   gp_Vec V2(0,1,0);
476   Transform(V2);
477   if ((Abs(V2.X()) + Abs(V2.Y())) < Precision::Angular()) V2.SetCoord(1,1,0);
478   gp_Vec2d D2(V2.X(),V2.Y());
479   myD2.SetCoord(-D2.Y(),D2.X());
480   gp_Vec V3(0,0,1);
481   Transform(V3);
482   if ((Abs(V3.X()) + Abs(V3.Y())) < Precision::Angular()) V3.SetCoord(1,1,0);
483   gp_Vec2d D3(V3.X(),V3.Y());
484   myD3.SetCoord(-D3.Y(),D3.X());
485 }
486
487 void Select3D_Projector::SetView(const Handle(V3d_View)& aViou)
488 {
489   myView = aViou;
490   myPersp = aViou->Type()==V3d_PERSPECTIVE;
491   myFocus= aViou->Focale();
492   Standard_Real Xat,Yat,Zat,XUp,YUp,ZUp,DX,DY,DZ;
493   //Standard_Boolean Pers=Standard_False;
494   
495   aViou->At(Xat,Yat,Zat);
496   aViou->Up(XUp,YUp,ZUp);
497   aViou->Proj(DX,DY,DZ);
498   gp_Pnt At (Xat,Yat,Zat); 
499   gp_Dir Zpers (DX,DY,DZ);
500   gp_Dir Ypers (XUp,YUp,ZUp);
501   gp_Dir Xpers = Ypers.Crossed(Zpers);
502   gp_Ax3 Axe (At, Zpers, Xpers);
503   myScaledTrsf.SetTransformation(Axe);
504   Scaled();
505   
506 }