Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Misc/ILCamera.cs @ 9372

Last change on this file since 9372 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 16.0 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40
41
42using System;
43using System.Collections.Generic;
44using System.Text;
45using System.Diagnostics;
46
47namespace ILNumerics.Drawing {
48    /// <summary>
49    /// This class represents the camera's positioning and aiming direction.
50    /// </summary>
51    [DebuggerDisplay("r:{m_distance} φ:{m_phiDebugDisp}° ρ:{m_rhoDebugDisp}° - P:{Position} - L:{LookAt}")]
52    public class ILCamera {
53
54        #region event handling
55        /// <summary>
56        /// fires, if the position of the camera has changed
57        /// </summary>
58        public event EventHandler Changed;
59        /// <summary>
60        /// Fires a Changed event
61        /// </summary>
62        public virtual void OnChange() {
63            if (Changed != null && !m_suspended)
64                Changed(this,new EventArgs());
65        }
66        #endregion
67
68        #region attributes
69        // input attributes (writable)
70        private bool m_suspended = false;
71        protected float m_posX;
72        protected float m_posY;
73        protected float m_posZ;
74        protected float m_topX;
75        protected float m_topY;
76        protected float m_topZ;
77        protected float m_lookAtX;
78        protected float m_lookAtY;
79        protected float m_lookAtZ;
80        // output/cached attributes (readonly)
81        // polar coordinates
82        private float m_distance = 1.0f;
83        private float m_phi = 0;
84        private float m_rho = 0.0f;
85        /// <summary>
86        /// Offset angle for 2nd cached triangular phi value (needed for surface plots)
87        /// </summary>
88        internal float Offset = (float)(Math.PI / 4);
89        /// <summary>
90        /// cachced triangular phi value with offset (needed for surface plots)
91        /// </summary>
92        internal float CosPhiShift;               
93        /// <summary>
94        /// cachced triangular phi value with offset (needed for surface plots)
95        /// </summary>
96        internal float SinPhiShift;
97        /// <summary>
98        /// cached value for cosine of phi - this is readonly and for performance only.
99        /// </summary>
100        internal float CosPhi;
101        /// <summary>
102        /// cached value for sine of phi - this is readonly and for performance only.
103        /// </summary>
104        internal float SinPhi;
105        /// <summary>
106        /// cached value for cosine of rho - this is readonly and for performance only.
107        /// </summary>
108        internal float CosRho;
109        /// <summary>
110        /// cached value for sine of rho - this is readonly and for performance only.
111        /// </summary>
112        internal float SinRho;
113        private CameraQuadrant m_quadrant;
114        #endregion
115
116        #region properties
117
118        /// <summary>
119        /// point, the camera is aiming at (world coords)
120        /// </summary>
121        public ILPoint3Df LookAt {
122            get { return new ILPoint3Df(m_lookAtX,m_lookAtY,m_lookAtZ); }
123            set {
124                //m_posX += (value.X - m_lookAtX);
125                //m_posY += (value.Y - m_lookAtY);
126                //m_posZ += (value.Z - m_lookAtZ);
127                m_lookAtX = value.X;
128                m_lookAtY = value.Y;
129                m_lookAtZ = value.Z;
130                 
131                updatePosition();
132                OnChange();
133            }
134        }
135
136        /// <summary>
137        /// distance from the scene (readonly)
138        /// </summary>
139        public float Distance {
140            get {
141                return m_distance;
142            }
143            set {
144                m_distance = Math.Abs(value);
145                updateCachedVars();
146                updatePosition();
147                OnChange();
148            }
149        }
150        /// <summary>
151        /// debugger helper: display phi in degrees (readonly)
152        /// </summary>
153        private int m_phiDebugDisp {
154            get {
155                return (int)Math.Round(m_phi * 180 / Math.PI);
156            }
157        }
158        /// <summary>
159        /// debugger helper: display rho in degrees
160        /// </summary>
161        private int m_rhoDebugDisp {
162            get {
163                return (int)Math.Round(m_rho * 180 / Math.PI);
164            }
165        }
166        /// <summary>
167        /// rotation of the scene (seen from above) [radians, readlony, rel. to lookat]
168        /// </summary>
169        public float Phi {
170            get {
171                return m_phi;
172            }
173            set {
174                m_phi = (float)((value + (Math.PI * 2)) % (Math.PI * 2));
175                updateCachedVars();
176                updatePosition();
177                OnChange();
178            }
179        }
180        /// <summary>
181        /// pitch of the scene [radians], setting moves camera around lookat point
182        /// </summary>
183        public float Rho {
184            get {
185                return m_rho;
186            }
187            set {
188                if (value < 0.0f)
189                    m_rho = 0.0f;
190                else if (value > Math.PI)
191                    m_rho = (float)Math.PI;
192                else
193                    m_rho = value;
194                updateCachedVars();
195                updatePosition();
196                OnChange();
197            }
198        }
199
200        /// <summary>
201        /// Quadrant the camera is currently watching the scene from
202        /// </summary>
203        public CameraQuadrant Quadrant {
204            get{
205                return m_quadrant;
206            }
207        }
208        /// <summary>
209        /// Determine, if camera is placed in an upper quadrant of the scene
210        /// </summary>
211        public bool LooksFromTop {
212            get {
213                return m_rho < Math.PI/2;
214            }
215        }
216        /// <summary>
217        /// Determine, if camera is located in an left quadrant of the scene
218        /// </summary>
219        public bool LooksFromLeft {
220            get {
221                return Math.Sin(m_phi) < 0;
222            }
223        }
224        /// <summary>
225        /// Determine, if camera is located in an front quadrant of the scene
226        /// </summary>
227        public bool LooksFromFront {
228            get {
229                return Math.Cos(m_phi) >= 0;
230            }
231        }
232        /// <summary>
233        /// true, when looking from top on the un-rotated scene (common for 2D plots)
234        /// </summary>
235        public bool Is2DView {
236            get {
237                return Math.Abs(SinPhi) < 1e-5 && Math.Abs(SinRho) < 1e-5;
238            }
239        }
240        /// <summary>
241        /// get/set camera position, absolute cartesian coordinates
242        /// </summary>
243        /// <remarks>Keep in mind, the angle for phi points towards negative Y axis! The cartesian property
244        /// <paramref name="Position"/> handles the camera position in absolute world coordinates, while the
245        /// polar coordinates (Rho, Phi, Distance) supress the camera position by means of coordinates
246        /// relative to the LookAt point (i.e. usually the center of the viewing cube)!</remarks>
247        public ILPoint3Df Position {
248            get {
249                ILPoint3Df ret = new ILPoint3Df(m_posX, m_posY, m_posZ);
250                return ret;
251            }
252            set {
253                m_posX = value.X;
254                m_posY = value.Y;
255                m_posZ = value.Z;
256                cart2Pol(value - new ILPoint3Df(m_lookAtX, m_lookAtY, m_lookAtZ));
257                updateCachedVars();
258                OnChange();
259            }
260        }
261        /// <summary>
262        /// orientation of the camera, normalized, readonly
263        /// </summary>
264        /// <remarks>This vector is readonly always points 'upwards'.</remarks>
265        public ILPoint3Df Top
266        {
267            get
268            {
269                ILPoint3Df ret = new ILPoint3Df(m_topX, m_topY, m_topZ);
270                return ret;
271            }
272        }
273        #endregion
274
275        #region constructors
276        public ILCamera (ILCamera vport) {
277            m_rho = vport.m_rho;
278            m_phi = vport.m_phi;
279            m_distance = vport.m_distance;
280            m_lookAtX = vport.m_lookAtX;
281            m_lookAtY = vport.m_lookAtY;
282            m_lookAtZ = vport.m_lookAtZ;
283            m_posX = vport.m_posX;
284            m_posY = vport.m_posY;
285            m_posZ = vport.m_posZ;
286            updateCachedVars();
287            computeQuadrant();
288        }
289        /// <summary>
290        /// Create a viewport: view at scene from top, no rotation
291        /// </summary>
292        public ILCamera () {
293            m_posX = 0;
294            m_posY = 0;
295            m_posZ = 10;
296            m_quadrant = CameraQuadrant.TopLeftFront;
297            updateCachedVars();
298        }
299        public ILCamera (float Phi, float Rho, float Distance) {
300            m_rho = Rho;
301            m_phi = Phi;
302            m_distance = Distance;
303            updateCachedVars();
304            updatePosition();
305            computeQuadrant();
306        }
307        #endregion
308
309        #region public interface
310        /// <summary>
311        /// suspend the firing of events until EventingResume() was called
312        /// </summary>
313        public void EventingSuspend() {
314            m_suspended = true;
315        }
316        /// <summary>
317        /// Resume firing 'Change' events after it has been suspended
318        /// </summary>
319        public void EventingResume() {
320            EventingResume(true);
321        }
322        /// <summary>
323        /// Resume firing 'Change' events, optionally skip pending events
324        /// </summary>
325        internal void EventingResume(bool fireEvents) {
326            m_suspended = false;
327            if (fireEvents)
328                OnChange();
329        }
330        /// <summary>
331        /// Set both angles and distance at once 
332        /// </summary>
333        /// <param name="phi">Rotation, radians</param>
334        /// <param name="rho">Pitch, radians</param>
335        /// <param name="distance">Distance from scene</param>
336        public void Set(float phi, float rho, float distance) {
337            if (distance < 0)
338                throw new Exceptions.ILArgumentException("Camera distance must be positive!");
339            m_phi = (float)(phi % (Math.PI * 2));
340            m_rho = (float)(rho % (Math.PI));
341            m_distance = distance;
342            updateCachedVars();
343            OnChange();
344        }
345        /// <summary>
346        /// Set complete camera position (angles and distance) at once
347        /// </summary>
348        /// <param name="phi">Rotation (degrees)</param>
349        /// <param name="rho">Pitch (degrees)</param>
350        /// <param name="distance">Distance from scene</param>
351        public void SetDeg(float phi,float rho, float distance) {
352            Set ((float)(phi/180.0 * Math.PI),(float)(rho / 180.0f * Math.PI),distance);
353        }
354        /// <summary>
355        /// Convert camera position to string
356        /// </summary>
357        /// <returns>string display with distance,roatation and pitch</returns>
358        public override string ToString() {
359            return String.Format("r:{0} φ:{1}° ρ:{2}° - P:{3} - L:{4}",
360                m_distance,m_phiDebugDisp,m_rhoDebugDisp,Position,LookAt);
361        }
362        #endregion
363
364        #region private helper
365        /// <summary>
366        /// update internal cartesian (absolut) coordinates of position relative
367        /// to lookAt point. To be called after any polar coordinates were changed.
368        /// </summary>
369        private void updatePosition() {
370            m_posX = m_lookAtX + (m_distance * SinRho * SinPhi);
371            m_posY = m_lookAtY + (m_distance * SinRho * -CosPhi);
372            m_posZ = m_lookAtZ + (m_distance * CosRho);
373        }
374        private void cart2Pol(ILPoint3Df cartVec) {
375            cartVec.ToPolar(out m_distance, out m_phi, out m_rho);
376        }
377        ///// <summary>
378        /////  update position, cons. polar coord and lookat as new
379        ///// </summary>
380        //private void pol2Cart() {
381               
382        //}
383
384        private void computeQuadrant() {
385            //if (m_phi == 0.0 && m_rho == 0.0) {
386            //    m_quadrant = CameraQuadrant.TopLeftFront;
387            //    return;
388            //}
389            if (m_rho < System.Math.PI / 2) {
390                // top
391                if (m_phi < Math.PI) {
392                    // right
393                    if (m_phi < Math.PI / 2) {
394                        // front
395                        m_quadrant = CameraQuadrant.TopRightFront;
396                    } else {
397                        // back
398                        m_quadrant = CameraQuadrant.TopRightBack;
399                    }
400                } else {
401                    // left
402                    if (m_phi > Math.PI / 2 * 3) {
403                        // front
404                        m_quadrant = CameraQuadrant.TopLeftFront;
405                    } else {
406                        // back
407                        m_quadrant = CameraQuadrant.TopLeftBack;
408                    }
409                }
410            } else {
411                // bottom
412                if (m_phi < Math.PI) {
413                    // right
414                    if (m_phi < Math.PI / 2) {
415                        // front
416                        m_quadrant = CameraQuadrant.BottomRightFront;
417                    } else {
418                        // back
419                        m_quadrant = CameraQuadrant.BottomRightBack;
420                    }
421                } else {
422                    // left
423                    if (m_phi > Math.PI / 2 * 3) {
424                        // front
425                        m_quadrant = CameraQuadrant.BottomLeftFront;
426                    } else {
427                        // back
428                        m_quadrant = CameraQuadrant.BottomLeftBack;
429                    }
430                }
431            }
432        }
433        private void updateCachedVars () {
434            CosPhi = (float)Math.Cos(m_phi);
435            SinPhi = (float)Math.Sin(m_phi);
436            SinPhiShift = (float)Math.Sin(m_phi + Offset);
437            CosPhiShift = (float)Math.Cos(m_phi + Offset);
438            CosRho = (float)Math.Cos(m_rho);
439            SinRho = (float)Math.Sin(m_rho);
440            // update top
441            ILPoint3Df top = ILPoint3Df.normalize(-SinPhi * CosRho, CosPhi * CosRho, SinRho);
442            m_topX = top.X;
443            m_topY = top.Y;
444            m_topZ = top.Z;
445
446            computeQuadrant();
447        }
448        #endregion
449
450    }
451}
Note: See TracBrowser for help on using the repository browser.