CMS 3D CMS Logo

Ig3DUnitVec3fControl.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
00002 
00003 #include "Iguana/GLBrowsers/interface/Ig3DUnitVec3fControl.h"
00004 #include "Iguana/GLBrowsers/interface/IgControlCategory.h"
00005 #include "Iguana/GLBrowsers/interface/IgQtRangeControlFloat.h"
00006 #include <classlib/utils/DebugAids.h>
00007 
00008 #ifdef WIN32
00009 #include <float.h>
00010 #define copysign _copysign
00011 #endif // WIN32
00012 
00013 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00014 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00015 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00016 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00017 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00018 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00019 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00020 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00021 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00022 
00023 Ig3DUnitVec3fControl::Ig3DUnitVec3fControl (IgControlCategory *pane,
00024                                             QString           label,
00025                                             Style style /*= DirectionStyle*/ )
00026     : Ig3DVec3fControl (pane, label, style),
00027       m_internalUpdate (false)
00028 {
00029     control ()->setSmallStep (.01); 
00030     control ()->setLongStep (.1); 
00031     control ()->setRange (-1.,1.);
00032     
00033     xControl ()->rangeEditable (false);
00034     yControl ()->rangeEditable (false);
00035     zControl ()->rangeEditable (false);
00036     
00037     m_internalUpdate = true;
00038     setValue(1., 0., 0.);
00039     m_internalUpdate = false;
00040 }
00041 
00042 void
00043 Ig3DUnitVec3fControl::setValues (const float *values, unsigned int size)
00044 {
00045     ASSERT (size == 3);
00046     SbVec3f vec (values[0], values[1], values[2]);
00047     // If this is coming from inside, don't touch it
00048     if (! m_internalUpdate)
00049         vec.normalize ();
00050 
00051     // Save current precision setting across the update.  Increase the
00052     // precision while setting the value to avoid jittered values.
00053     float savedPrecision = control (0)->precision ();
00054     bool oldSetting = control (0)->isEmitSettingsChanged ();
00055     control (0)->setEmitSettingsChanged (false);
00056     for(unsigned int i = 0; i < 3; i++)
00057       control (i)->setPrecision (.00001);
00058 
00059     // Set the value.  Prevent further internal normalisation.  Then
00060     // mark all the controls clean.
00061     bool savedInternal = m_internalUpdate;
00062     m_internalUpdate = true;
00063     Ig3DVectorBaseControl::setValues (vec.getValue (), (unsigned int)(3));
00064 
00065     for(unsigned int i = 0; i < 3; i++)
00066       control (i)->setClean ();
00067 
00068     m_internalUpdate = savedInternal;
00069 
00070     // Restore the precision back to whatever it was.
00071     
00072     for(unsigned int i = 0; i < 3; i++)
00073       control (i)->setPrecision (savedPrecision);
00074     
00075     control (0)->setEmitSettingsChanged (oldSetting);
00076 }
00077 
00078 void
00079 Ig3DUnitVec3fControl::setDirty (bool dirty)
00080 {
00081     // Normalise the vector if the value is not being forced on us
00082     // from outside and we are not recursing (from setValue() below).
00083     //
00084     // If the change occurs due to GUI changes and there is just one
00085     // changed component, fix the changed one and normalise the other
00086     // two components relative to it.  This makes the user interface
00087     // more intuitive and avoids numerical errors when one of the
00088     // values is stepped to boundaries.
00089     if (m_internalUpdate || ! dirty)
00090                 Ig3DVectorControl::setDirty (dirty);
00091 
00092     else
00093     {    
00094                 SbVec3f vec (value ());
00095                 bool xdirty = xControl ()->isDirty ();
00096                 bool ydirty = yControl ()->isDirty ();
00097                 bool zdirty = zControl ()->isDirty ();
00098         
00099                 if (xdirty && !ydirty && !zdirty)
00100                 // Fix X and normalise the others.
00101                 normalize (xChange (), vec[0], vec[1], vec[2],
00102                        0.00001);
00103                 else if (!xdirty && ydirty && !zdirty)
00104                 // Fix Y and normalise the others.
00105                 normalize (yChange (), vec[1], vec[0], vec[2],
00106                        0.00001);
00107                 else if (!xdirty && !ydirty && zdirty)
00108                 // Fix Z and normalise the others.
00109                 normalize (zChange (), vec[2], vec[0], vec[1],
00110                        0.00001);
00111                 else
00112                 // Normalise all.
00113                 vec.normalize ();
00114 
00115                 // Prevent recursive normalisation and set it.
00116                 m_internalUpdate = true;
00117                 setValue (vec);
00118                 m_internalUpdate = false;
00119     }
00120 }
00121 
00122 void
00123 Ig3DUnitVec3fControl::normalize (float delta, float &v, float &a1, float &a2,
00124                                  float precision /* = 0.001 */)
00125 {
00126     // If the other two components are zero, give v everything;
00127     // determine the sign from v's previous value, or if zero, from
00128     // the direction we are going to (increase -> 1, decrease -> -1).
00129     
00130     if (fabs(a1) <= precision && fabs(a2) <= precision)
00131     {
00132         a1 = a2 = 0.;
00133         v = copysign (1, v ? v : delta);
00134     }
00135     // Otherwise, if v is nearly one, make it one.
00136     else if ((fabs (v) + precision) >= 1.0)
00137     {
00138         v = copysign (1, v);
00139         a1 = a2 = 0.;
00140     }
00141 
00142     // Otherwise, normalise by fixing v and giving the rest of the
00143     // magnitude to one or two other components.
00144     else
00145     {
00146         float newMag = v * v;
00147         float oldMag = (v-delta) * (v-delta);
00148         float diff   = newMag - oldMag;
00149 
00150         ASSERT (newMag <= 1);
00151         // If no difference, nothing to do
00152         if (diff == 0.)
00153             ;
00154 
00155         // If one component is zero, give the rest of magnitude to the other
00156         else if (fabs(a1) <= precision)
00157         {
00158             a1 = 0.;
00159             a2 = copysign (sqrt (1-newMag), a2);
00160         }
00161         else if (fabs(a2) <= precision)
00162         {
00163             a2 = 0.;
00164             a1 = copysign (sqrt (1-newMag), a1);
00165         }
00166 
00167         // Otherwise, distribute the magnitude growth to the other two
00168         // proportional to their current magnitudes.
00169         else
00170         {
00171             float a11 = a1*a1;
00172             float a22 = a2*a2;
00173             a11 = fabs (a11 * (1. - diff / (a11 + a22)));
00174             a22 = fabs (a22 * (1. - diff / (a11 + a22)));
00175             a1 = copysign (sqrt (a11), a1);
00176             a2 = copysign (sqrt (a22), a2);
00177         }
00178     }
00179 }

Generated on Tue Jun 9 17:38:37 2009 for CMSSW by  doxygen 1.5.4