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