0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / HLRAlgo / HLRAlgo_Projector.cxx
1 // Created on: 1992-03-13
2 // Created by: Christophe MARION
3 // Copyright (c) 1992-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 #ifndef No_Exception
18 // #define No_Exception
19 #endif
20
21
22 #include <gp_Ax2.hxx>
23 #include <gp_Ax3.hxx>
24 #include <gp_Lin.hxx>
25 #include <gp_Pnt.hxx>
26 #include <gp_Pnt2d.hxx>
27 #include <gp_Trsf.hxx>
28 #include <gp_Vec.hxx>
29 #include <gp_Vec2d.hxx>
30 #include <HLRAlgo_Projector.hxx>
31 #include <Precision.hxx>
32 #include <Standard_NoSuchObject.hxx>
33
34 // formula for derivating a perspective, from Mathematica
35 //        X'[t]      X[t] Z'[t]                                     
36 // D1 =  -------- + -------------                                   
37 //           Z[t]          Z[t] 2                                   
38 //       1 - ----   f (1 - ----)                                    
39 //            f             f                                       
40 //=======================================================================
41 //function : HLRAlgo_Projector
42 //purpose  : 
43 //=======================================================================
44 HLRAlgo_Projector::HLRAlgo_Projector () :
45        myPersp(Standard_False),myFocus(0)
46 {
47   Scaled();
48
49
50 //=======================================================================
51 //function : HLRAlgo_Projector
52 //purpose  : 
53 //=======================================================================
54
55 HLRAlgo_Projector::HLRAlgo_Projector (const gp_Ax2& CS) :
56 myPersp(Standard_False), myFocus(0)
57 {
58   myScaledTrsf.SetTransformation(CS);
59   Scaled();
60   SetDirection();
61 }
62
63 //=======================================================================
64 //function : HLRAlgo_Projector
65 //purpose  : 
66 //=======================================================================
67
68 HLRAlgo_Projector::HLRAlgo_Projector (const gp_Ax2& CS, 
69                                       const Standard_Real Focus) :
70                                       myPersp(Standard_True), myFocus(Focus)
71 {
72   myScaledTrsf.SetTransformation(CS);
73   Scaled();
74   SetDirection();
75 }
76
77 //=======================================================================
78 //function : HLRAlgo_Projector
79 //purpose  : 
80 //=======================================================================
81
82 HLRAlgo_Projector::HLRAlgo_Projector (const gp_Trsf& T, 
83                                       const Standard_Boolean Persp,
84                                       const Standard_Real Focus) :
85                                       myPersp(Persp),
86                                       myFocus(Focus),
87                                       myScaledTrsf(T)
88 {
89   Scaled();
90   SetDirection();
91 }
92
93 //=======================================================================
94 //function : HLRAlgo_Projector
95 //purpose  : 
96 //=======================================================================
97
98 HLRAlgo_Projector::HLRAlgo_Projector (const gp_Trsf& T, 
99                                       const Standard_Boolean Persp,
100                                       const Standard_Real Focus,
101                                       const gp_Vec2d& v1,
102                                       const gp_Vec2d& v2,
103                                       const gp_Vec2d& v3) :
104                                       myPersp(Persp),
105                                       myFocus(Focus),
106                                       myScaledTrsf(T),
107                                       myD1(v1),
108                                       myD2(v2),
109                                       myD3(v3)
110 {
111   Scaled();
112 }
113
114 //=======================================================================
115 //function : Set
116 //purpose  : 
117 //=======================================================================
118
119 void HLRAlgo_Projector::Set (const gp_Trsf& T, 
120                              const Standard_Boolean Persp,
121                              const Standard_Real Focus) 
122 {
123   myPersp      = Persp;
124   myFocus      = Focus;
125   myScaledTrsf = T;
126   Scaled();
127   SetDirection();
128 }
129
130 //=======================================================================
131 //function : Scaled
132 //purpose  : 
133 //=======================================================================
134
135 #include <gp_Mat.hxx>
136
137 static Standard_Integer TrsfType(const gp_Trsf& Trsf) { 
138   const gp_Mat& Mat = Trsf.VectorialPart();
139   if(   (Abs(Mat.Value(1,1)-1.0) < 1e-15) 
140      && (Abs(Mat.Value(2,2)-1.0) < 1e-15)
141      && (Abs(Mat.Value(3,3)-1.0) < 1e-15)) { 
142     return(1); //-- top
143   }
144   else if(   (Abs(Mat.Value(1,1)-0.7071067811865476) < 1e-15)
145           && (Abs(Mat.Value(1,2)+0.5) < 1e-15)
146           && (Abs(Mat.Value(1,3)-0.5) < 1e-15)
147           
148           && (Abs(Mat.Value(2,1)-0.7071067811865476) < 1e-15)
149           && (Abs(Mat.Value(2,2)-0.5) < 1e-15)
150           && (Abs(Mat.Value(2,3)+0.5) < 1e-15)
151           
152           && (Abs(Mat.Value(3,1)) < 1e-15)  
153           && (Abs(Mat.Value(3,2)-0.7071067811865476) < 1e-15)
154           && (Abs(Mat.Value(3,3)-0.7071067811865476) < 1e-15)) { 
155     return(0); //-- 
156   }
157   else if(   (Abs(Mat.Value(1,1)-1.0) < 1e-15) 
158           && (Abs(Mat.Value(2,3)-1.0) < 1e-15)
159           && (Abs(Mat.Value(3,2)+1.0) < 1e-15)) { 
160     return(2); //-- front
161   }
162   else if(   (Abs(Mat.Value(1,1)-0.7071067811865476) < 1e-15)
163           && (Abs(Mat.Value(1,2)-0.7071067811865476) < 1e-15)
164           && (Abs(Mat.Value(1,3)) < 1e-15)
165           
166           && (Abs(Mat.Value(2,1)+0.5) < 1e-15)
167           && (Abs(Mat.Value(2,2)-0.5) < 1e-15)
168           && (Abs(Mat.Value(2,3)-0.7071067811865476) < 1e-15)
169           
170           && (Abs(Mat.Value(3,1)-0.5) < 1e-15)  
171           && (Abs(Mat.Value(3,2)+0.5) < 1e-15)
172           && (Abs(Mat.Value(3,3)-0.7071067811865476) < 1e-15)) { 
173     return(3); //-- axo
174   }
175   return(-1);
176 }
177
178 void HLRAlgo_Projector::Scaled (const Standard_Boolean On)
179
180   myType=-1;
181   myTrsf = myScaledTrsf;
182   if (!On) {
183     myTrsf.SetScaleFactor(1.);
184     if (!myPersp) { 
185       myTrsf.SetTranslationPart(gp_Vec(0.,0.,0.));
186       myType=TrsfType(myTrsf); 
187     }
188   }
189   myInvTrsf = myTrsf;
190   myInvTrsf.Invert();
191 }
192
193 //=======================================================================
194 //function : Project
195 //purpose  : 
196 //=======================================================================
197
198 void HLRAlgo_Projector::Project (const gp_Pnt& P, gp_Pnt2d& Pout) const
199 {
200   if(myType!=-1) { 
201     Standard_Real X,Y;
202     switch (myType) { 
203     case 0: {  //-- axono standard
204       Standard_Real x07 = P.X()*0.7071067811865475;
205       Standard_Real y05 = P.Y()*0.5;
206       Standard_Real z05 = P.Z()*0.5;
207       X=x07-y05+z05;
208       Y=x07+y05-z05;
209       //-- Z=0.7071067811865475*(P.Y()+P.Z());
210       break;
211     }
212     case 1: { //-- top
213       X=P.X(); Y=P.Y(); //-- Z=P.Z();
214       Pout.SetCoord(X,Y);
215       break;
216     }
217     case 2: { 
218       X=P.X(); Y=P.Z(); //-- Z=-P.Y();
219       Pout.SetCoord(X,Y);
220       break;
221     }
222     case 3: { 
223       Standard_Real xmy05 = (P.X()-P.Y())*0.5;
224       Standard_Real z07 = P.Z()*0.7071067811865476;
225       X=0.7071067811865476*(P.X()+P.Y());
226       Y=-xmy05+z07;
227       Pout.SetCoord(X,Y);
228       //-- Z= xmy05+z07;
229       break;
230     }
231     default: { 
232       gp_Pnt P2 = P;
233       Transform(P2);
234       if (myPersp) {
235         Standard_Real R = 1.-P2.Z()/myFocus;
236         Pout.SetCoord(P2.X()/R,P2.Y()/R);
237       }
238       else 
239         Pout.SetCoord(P2.X(),P2.Y());    
240       break;
241     }
242     }
243   }
244   else { 
245     gp_Pnt P2 = P;
246     Transform(P2);
247     if (myPersp) {
248       Standard_Real R = 1.-P2.Z()/myFocus;
249       Pout.SetCoord(P2.X()/R,P2.Y()/R);
250     }
251     else 
252       Pout.SetCoord(P2.X(),P2.Y()); 
253   }
254 }
255
256 //=======================================================================
257 //function : Project
258 //purpose  : 
259 //=======================================================================
260 /*  ====== TYPE 0  (??)
261    (0.7071067811865476, -0.5               ,  0.4999999999999999)
262    (0.7071067811865475,  0.5000000000000001, -0.5              )
263    (0.0,                 0.7071067811865475,  0.7071067811865476)
264
265   ====== TYPE 1 (top)
266 (1.0, 0.0, 0.0)
267 (0.0, 1.0, 0.0)
268 (0.0, 0.0, 1.0)
269
270  ======= TYPE 2 (front)
271 (1.0,  0.0                   , 0.0)
272 (0.0,  1.110223024625157e-16 , 1.0)
273 (0.0, -1.0                   , 1.110223024625157e-16)
274
275  ======= TYPE 3 
276 ( 0.7071067811865476, 0.7071067811865475, 0.0)
277 (-0.5               , 0.5000000000000001, 0.7071067811865475)
278 ( 0.4999999999999999, -0.5              , 0.7071067811865476)
279 */
280 void HLRAlgo_Projector::Project (const gp_Pnt& P,
281                                  Standard_Real& X,
282                                  Standard_Real& Y,
283                                  Standard_Real& Z) const
284 {
285   if(myType!=-1) { 
286     switch (myType) { 
287     case 0: {  //-- axono standard
288       Standard_Real x07 = P.X()*0.7071067811865475;
289       Standard_Real y05 = P.Y()*0.5;
290       Standard_Real z05 = P.Z()*0.5;
291       X=x07-y05+z05;
292       Y=x07+y05-z05;
293       Z=0.7071067811865475*(P.Y()+P.Z());
294       break;
295     }
296     case 1: { //-- top
297       X=P.X(); Y=P.Y(); Z=P.Z();
298       break;
299     }
300     case 2: { 
301       X=P.X(); Y=P.Z(); Z=-P.Y();
302       break;
303     }
304     case 3: { 
305       Standard_Real xmy05 = (P.X()-P.Y())*0.5;
306       Standard_Real z07 = P.Z()*0.7071067811865476;
307       X=0.7071067811865476*(P.X()+P.Y());
308       Y=-xmy05+z07;
309       Z= xmy05+z07;
310       break;
311     }
312     default: { 
313       gp_Pnt P2 = P;
314       Transform(P2);
315       P2.Coord(X,Y,Z);
316       break;
317     }
318     }
319   }
320   else { 
321     gp_Pnt P2 = P;
322     Transform(P2);
323     P2.Coord(X,Y,Z);
324     if (myPersp) {
325       Standard_Real R = 1 - Z / myFocus;
326       X = X / R;
327       Y = Y / R;
328     }
329   }
330 }
331
332 //=======================================================================
333 //function : Project
334 //purpose  : 
335 //=======================================================================
336
337 void HLRAlgo_Projector::Project (const gp_Pnt& P,
338                                  const gp_Vec& D1,
339                                  gp_Pnt2d& Pout,
340                                  gp_Vec2d& D1out) const
341 {
342   gp_Pnt PP = P;
343   PP.Transform(myTrsf);
344   gp_Vec DD1 = D1;
345   DD1.Transform(myTrsf);
346   if (myPersp) {
347     Standard_Real R = 1. - PP.Z() / myFocus;
348     Pout .SetCoord(PP .X()/R , PP.Y()/R);
349     D1out.SetCoord(DD1.X()/R + PP.X()*DD1.Z()/(myFocus * R*R),
350                    DD1.Y()/R + PP.Y()*DD1.Z()/(myFocus * R*R));
351   }
352   else {
353     Pout .SetCoord(PP .X(),PP .Y());
354     D1out.SetCoord(DD1.X(),DD1.Y());
355   }
356 }
357
358 //=======================================================================
359 //function : Shoot
360 //purpose  : 
361 //=======================================================================
362
363 gp_Lin HLRAlgo_Projector::Shoot (const Standard_Real X,
364                                  const Standard_Real Y) const
365 {
366   gp_Lin L;
367   if (myPersp) {
368     L = gp_Lin(gp_Pnt(0,0, myFocus),
369                gp_Dir(X,Y,-myFocus));
370   }
371   else {
372     L = gp_Lin(gp_Pnt(X,Y,0),
373                gp_Dir(0,0,-1));
374   }
375   L.Transform(myInvTrsf);
376   return L;
377 }
378
379 //=======================================================================
380 //function : SetDirection
381 //purpose  : 
382 //=======================================================================
383
384 void HLRAlgo_Projector::SetDirection () 
385 {
386   gp_Vec V1(1,0,0);
387   V1.Transform(myTrsf);
388   if ((Abs(V1.X()) + Abs(V1.Y())) < Precision::Angular()) V1.SetCoord(1,1,0);
389   gp_Vec2d D1(V1.X(),V1.Y());
390   myD1.SetCoord(-D1.Y(),D1.X());
391   gp_Vec V2(0,1,0);
392   V2.Transform(myTrsf);
393   if ((Abs(V2.X()) + Abs(V2.Y())) < Precision::Angular()) V2.SetCoord(1,1,0);
394   gp_Vec2d D2(V2.X(),V2.Y());
395   myD2.SetCoord(-D2.Y(),D2.X());
396   gp_Vec V3(0,0,1);
397   V3.Transform(myTrsf);
398   if ((Abs(V3.X()) + Abs(V3.Y())) < Precision::Angular()) V3.SetCoord(1,1,0);
399   gp_Vec2d D3(V3.X(),V3.Y());
400   myD3.SetCoord(-D3.Y(),D3.X());
401 }
402
403 //=======================================================================
404 //function : Transformation
405 //purpose  : 
406 //=======================================================================
407
408 const gp_Trsf & HLRAlgo_Projector::Transformation() const
409 { return myTrsf; }