![]() |
![]() |
#include <Iguana/GLBrowsers/interface/Ig3DRotationControl.h>
Public Member Functions | |
SoSFRotation * | field (void) const |
Get the field this control is attached to, or null if the control is currently not attached to a rotation field. | |
SbRotation | fieldValue (void) const |
Return the current value of the field this control is attached to. | |
Ig3DRotationControl (IgControlCategory *pane, QString label) | |
Create a new rotation controller. | |
void | setField (SoSFRotation *field) |
Attach this control to field. | |
void | yOver90 (bool value) |
Indicate whether current rotation around Y is over 90 degrees. | |
void | zForY90 (float degrees) |
Set Z rotation angle to degrees for the situation when it cannot be determined from the rotation matrix (rotation around Y axis is 90 degrees). | |
Static Public Member Functions | |
static float | deg2rad (float value) |
Convert value from degrees to radians. | |
static SbVec3f | eulerXYZAngles (const SbRotation &from, bool yOver90=false, float zForY90=0, float epsilon=.0001) |
Calculate Euler rotation angles in degrees from rotation matrix rot into a sequence of rotations around X, Y, and Z axes, in that order. | |
static float | rad2deg (float value) |
Convert value from radians to degrees. | |
static SbRotation | rotate (const SbRotation &rot, const SbVec3f &angles) |
Rotate rot by angles (where angles is in degrees). | |
Protected Member Functions | |
virtual void | applyValue (void) |
Apply the control's current value to the field. | |
virtual void | updateValue (void) |
Update the control's current value from the field. | |
Private Member Functions | |
void | setup (IgQtRangeControlFloat *c, QPixmap rev, QPixmap fwd) |
Private Attributes | |
bool | m_yOver90 |
float | m_zForY90 |
Definition at line 18 of file Ig3DRotationControl.h.
Ig3DRotationControl::Ig3DRotationControl | ( | IgControlCategory * | pane, | |
QString | label | |||
) |
Create a new rotation controller.
Definition at line 129 of file Ig3DRotationControl.cc.
References IgQtRangeControlCommon::resetChangedValue(), Ig3DVectorControl::xControl(), Ig3DVectorControl::yControl(), and Ig3DVectorControl::zControl().
00131 : Ig3DVectorControl (pane, label, RotationStyle), 00132 m_yOver90 (false), 00133 m_zForY90 (0) 00134 { 00135 xControl ()->resetChangedValue (true); 00136 yControl ()->resetChangedValue (true); 00137 zControl ()->resetChangedValue (true); 00138 00139 disconnect(pane, SIGNAL (tracking (bool)), 00140 xControl (), SLOT (resetChangedValue (bool))); 00141 disconnect(pane, SIGNAL (tracking (bool)), 00142 yControl (), SLOT (resetChangedValue (bool))); 00143 disconnect(pane, SIGNAL (tracking (bool)), 00144 zControl (), SLOT (resetChangedValue (bool))); 00145 }
Apply the control's current value to the field.
The control must currently be attached to a field; this is normally assured by base class apply() before invoking this method. Currently the control tracks only the changes made to the rotation matrix, not the actual angle values it has.
Reimplemented from Ig3DVectorBaseControl.
Reimplemented in Ig3DCameraRotControl.
Definition at line 217 of file Ig3DRotationControl.cc.
References Ig3DVectorControl::change(), field(), fieldValue(), Ig3DVectorBaseControl::isChanged(), and rotate().
Referenced by Ig3DCameraRotControl::applyValue().
00218 { 00219 if (isChanged ()) 00220 // We currently work only on changed (= delta) values, not the 00221 // absolute angles. To switch to using actual angle values use: 00222 // field ()->setValue (rotate (SbRotation (), value ())); 00223 field ()->setValue (rotate (fieldValue (), change ())); 00224 }
float Ig3DRotationControl::deg2rad | ( | float | value | ) | [static] |
Convert value from degrees to radians.
Definition at line 21 of file Ig3DRotationControl.cc.
Referenced by Ig3DRotationFControl::angle(), Ig3DAngleControl::applyValue(), and rotate().
00022 { return value * M_PI / 180; }
SbVec3f Ig3DRotationControl::eulerXYZAngles | ( | const SbRotation & | rot, | |
bool | yOver90 = false , |
|||
float | zForY90 = 0 , |
|||
float | epsilon = .0001 | |||
) | [static] |
Calculate Euler rotation angles in degrees from rotation matrix rot into a sequence of rotations around X, Y, and Z axes, in that order.
The resulting angles are in the range [-180, 180].
If yOver90 is set, rotation around Y is known to be within [-180,90) or (90,180] and the resulting angles will reflect that. Otherwise (= by default) it is assumed that Y is within [-90,90]. The range of Y cannot be determined automatically so passing this flag is useful when smooth results are needed and for example incremental rotations are applied.
If the rotation around the Y axis is exactly 90 degrees such that X maps to Z or vice versa, only the sum or difference of rotations around X and Z can be determined, but not each individually. If the client knows a good initial guess for Z rotation, for example when small incremental rotations are applied, it can pass it in the zForY90 argument to disambiguate the sum and to guarantee smooth results; by default Z is set to zero and X is given the complete rotation.
Pass epsilon to indicate how close values to 90-degree rotation around Y should be considered as 90 degrees. If you pass zero, only rotations of exactly 90 degrees will match. The default is a small but noticable error -- zero error makes it difficult to lock on a unit vector due to numerical errors. (FIXME: Test this with the new code.)
Definition at line 66 of file Ig3DRotationControl.cc.
References funct::cos(), m, rad2deg(), x, y, and z.
00070 { 00071 float x; 00072 float y; 00073 float z; 00074 SbMatrix m; 00075 00076 rot.getValue (m); 00077 00078 // In the notation below ca == cos(a), sa == sin(a) 00079 // 00080 // 0 1 2 00081 // m = cy*cz cz*sx*sy + cx*sz -cx*cz*sy + sx*sz 0 00082 // -cy*sz cx*cz - sx*sy*sz cz*sz + cx*sy*sz 1 00083 // sy -cy*sx cx*cy 2 00084 // 00085 // If sin(y) is +-1 (y is +- 90 deg) the solution is ambiguous and 00086 // we can only determine z+x (+90) or z-x (-90). Allow client to 00087 // lock on to +- 90 when we get close to avoid numerical errors. 00088 if (m [2][0] < 1-epsilon) 00089 { 00090 if (m [2][0] > -1+epsilon) 00091 { 00092 float yrad = asin (m [2][0]); 00093 if (yOver90) yrad = yrad > 0 ? M_PI - yrad : -M_PI - yrad; 00094 float cy = cos (yrad); 00095 y = rad2deg (yrad); 00096 z = rad2deg (atan2 (-m[1][0]/cy, m[0][0]/cy)); 00097 x = rad2deg (atan2 (-m[2][1]/cy, m[2][2]/cy)); 00098 } 00099 else 00100 { 00101 // sin(y) =~ -1, i.e. -90 degrees 00102 // m[0][1] == -cz*sx + cx*sz == sin(z-x) 00103 // m[1][1] == cx*cz + sx*sz == cos(z-x) 00104 // ==> z-x = atan2(sin(z-x),cos(z-x)) 00105 y = -90; 00106 z = zForY90; 00107 x = z - rad2deg (atan2 (m[0][1], m[1][1])); 00108 } 00109 } 00110 else 00111 { 00112 // sin(y) =~ 1, i.e. 90 degrees 00113 // m[0][1] == cz*sx + cx*sz == sin(z+x) 00114 // m[1][1] == cx*cz - sx*sz == cos(z+x) 00115 // ==> z+x = atan2(sin(z+x),cos(z+x)) 00116 y = 90; 00117 z = zForY90; 00118 x = rad2deg (atan2(m[0][1], m[1][1])) - z; 00119 } 00120 00121 // FIXME? return SbVec3f (x ? -x : 0, y ? -y : 0, z ? -z : 0); 00122 return SbVec3f (x, y, z); 00123 }
SoSFRotation * Ig3DRotationControl::field | ( | void | ) | const |
Get the field this control is attached to, or null if the control is currently not attached to a rotation field.
Reimplemented from Ig3DFieldControl.
Definition at line 167 of file Ig3DRotationControl.cc.
References Ig3DFieldControl::field().
Referenced by applyValue(), and fieldValue().
00168 { return static_cast<SoSFRotation *> (Ig3DFieldControl::field ()); }
SbRotation Ig3DRotationControl::fieldValue | ( | void | ) | const |
Return the current value of the field this control is attached to.
The control must currently by attached to a non-null field. Note that this is not necessarily the same as the current value that the control holds.
Definition at line 186 of file Ig3DRotationControl.cc.
References ASSERT, and field().
Referenced by applyValue().
float Ig3DRotationControl::rad2deg | ( | float | value | ) | [static] |
Convert value from radians to degrees.
Definition at line 26 of file Ig3DRotationControl.cc.
Referenced by eulerXYZAngles(), Ig3DRotationFControl::setValue(), and Ig3DAngleControl::updateValue().
00027 { return value * 180 / M_PI; }
SbRotation Ig3DRotationControl::rotate | ( | const SbRotation & | rot, | |
const SbVec3f & | angles | |||
) | [static] |
Rotate rot by angles (where angles is in degrees).
Definition at line 31 of file Ig3DRotationControl.cc.
References deg2rad().
Referenced by applyValue().
00032 { 00033 return SbRotation (SbVec3f (-1.F,0.F,0.F), deg2rad (angles [0])) 00034 * SbRotation (SbVec3f (0.F,-1.F,0.F), deg2rad (angles [1])) 00035 * SbRotation (SbVec3f (0.F,0.F,-1.F), deg2rad (angles [2])) 00036 * rot; 00037 }
void Ig3DRotationControl::setField | ( | SoSFRotation * | field | ) |
Attach this control to field.
Detaches the control from the field it was previously attached to if there is one, and attaches it to field if field is non-null.
Definition at line 176 of file Ig3DRotationControl.cc.
References Ig3DFieldControl::setField().
Referenced by Ig3DViewpointsCategory::attach(), and Ig3DViewpointsCategory::detach().
00177 { Ig3DFieldControl::setField (field); }
void Ig3DRotationControl::setup | ( | IgQtRangeControlFloat * | c, | |
QPixmap | rev, | |||
QPixmap | fwd | |||
) | [private] |
Update the control's current value from the field.
The control must currently be attached to a field; this is normally assured by base class update() before invoking this method. Currently the control tracks only the changes made to the rotation matrix, not the actual angle values it has, so this does nothing.
Reimplemented from Ig3DVectorBaseControl.
Definition at line 198 of file Ig3DRotationControl.cc.
00199 { 00200 // Since we never show the actual angle, there is nothing to do 00201 // here; when we get marked clean, the controls will also be made 00202 // clean, and will lose their change. (FIXME: Get the current 00203 // angle values and display them.) 00204 00205 // // Use old values as best guess? 00206 // setValue (eulerXYZAngles (fieldValue (), 00207 // fabs (yValue ()) > 90), 00208 // -zValue ())); 00209 }
Indicate whether current rotation around Y is over 90 degrees.
Use this to avoid jumps when the differences are known to be minor and current Y rotation is known.
Definition at line 158 of file Ig3DRotationControl.cc.
References m_yOver90.
void Ig3DRotationControl::zForY90 | ( | float | degrees | ) |
Set Z rotation angle to degrees for the situation when it cannot be determined from the rotation matrix (rotation around Y axis is 90 degrees).
The default value is zero.
Definition at line 151 of file Ig3DRotationControl.cc.
References ASSERT, and m_zForY90.
bool Ig3DRotationControl::m_yOver90 [private] |
float Ig3DRotationControl::m_zForY90 [private] |