nux-0.9.46

Nux/SplineCurveEditor.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #ifndef SPLINECURVEEDITOR_H
00024 #define SPLINECURVEEDITOR_H
00025 
00026 #include "PaintLayer.h"
00027 
00028 namespace nux
00029 {
00030 
00031   class CubicSpline;
00032   class SplineKnot;
00033   class GLSh_DrawFunction;
00034 
00035   class SplineKnot
00036   {
00037   public:
00038     class Knot
00039     {
00040     public:
00041       Knot (double kX, double kY, bool selected = false, bool excluded = false)
00042         :   m_IsSelected (selected)
00043         ,   m_IsExcluded (excluded)
00044       {
00045         x = kX;
00046         y = kY;
00047       }
00048 
00049       bool operator == (const Knot &knot)
00050       {
00051         return ( (x == knot.x) && (y == knot.y) );
00052       }
00053 
00054       bool operator != (const Knot &knot)
00055       {
00056         return ( (x != knot.x) || (y != knot.y) );
00057       }
00058 
00059       bool operator > (const Knot &knot) const
00060       {
00061         return (x > knot.x);
00062       }
00063 
00064       bool operator < (const Knot &knot) const
00065       {
00066         return (x < knot.x);
00067       }
00068 
00069       double GetX() const
00070       {
00071         return x;
00072       }
00073       double GetY() const
00074       {
00075         return y;
00076       }
00077       void SetX (double d)
00078       {
00079         x = d;
00080       }
00081       void SetY (double d)
00082       {
00083         y = d;
00084       }
00085     private:
00086       double x, y;
00087       bool m_IsSelected;
00088       bool m_IsExcluded;
00089 
00090       friend class SplineKnot;
00091     };
00092 
00093   public :
00094 
00095     SplineKnot()
00096     {
00097       // There must always be at least two points for the spline interpolation to work
00098 //        m_knot.push_back(Knot(0.0, 0.0));
00099 //        m_knot.push_back(Knot(1.0, 1.0));
00100     }
00101 
00102     SplineKnot (const SplineKnot &Other)
00103     {
00104       m_knot = Other.m_knot;
00105     }
00106 
00107     SplineKnot &operator = (const SplineKnot &Other)
00108     {
00109       Reset();
00110       m_knot = Other.m_knot;
00111       return *this;
00112     }
00113 
00114 //    void operator = (const SplineKnot* Other)
00115 //    {
00116 //        if(Other == 0)
00117 //            return
00118 //        Reset();
00119 //        m_knot = Other->m_knot;
00120 //        //return *this;
00121 //    }
00122 
00123     void AddKnot (double x, double y, bool selected = false)
00124     {
00125       std::vector<Knot>::iterator it;
00126 
00127       // Check if the exacte same knot is already in.
00128       it = std::find (m_knot.begin(), m_knot.end(), Knot (x, y) );
00129 
00130       if (it != m_knot.end() )
00131       {
00132         // already in
00133         return;
00134       }
00135 
00136       // Check if a knot is already in with the same x.
00137       for (it = m_knot.begin(); it != m_knot.end(); it++)
00138       {
00139         if ( (*it).x == x)
00140         {
00141           (*it).y = y;
00142           (*it).m_IsSelected = selected;
00143           return;
00144         }
00145       }
00146 
00147       m_knot.push_back (Knot (x, y, selected) );
00148       std::sort (m_knot.begin(), m_knot.end(), std::less<SplineKnot::Knot>() );
00149     }
00150 
00151     bool isKnotSelected (int i) const
00152     {
00153       if (i >= GetNumKnot() || i < 0)
00154       {
00155         return false;
00156       }
00157 
00158       return m_knot[i].m_IsSelected;
00159     }
00160 
00161     const Knot &operator [] (int i) const
00162     {
00163       return m_knot[i];
00164     }
00165 
00166     Knot &operator [] (int i)
00167     {
00168       return m_knot[i];
00169     }
00170 
00171     void EraseKnot (int i)
00172     {
00173       if (m_knot.size() <= 2)
00174       {
00175         // There must always be at least two points for the spline interpolation to work
00176         return;
00177       }
00178 
00179       if (i >= GetNumKnot() || i < 0)
00180       {
00181         return;
00182       }
00183 
00184       std::vector<Knot>::iterator it = m_knot.begin();
00185       it += i;
00186       m_knot.erase (it);
00187     }
00188 
00189     void EraseSelectedKnot()
00190     {
00191       if (m_knot.size() <= 2)
00192       {
00193         // There must always be at least two points for the spline interpolation to work
00194         return;
00195       }
00196 
00197       // Traverse the array and erase selected knots.
00198       bool finish = false;
00199 
00200       do
00201       {
00202         // loop many times to avoid erasing iterators while traversing the array. This is not efficient!
00203         bool found = false;
00204         std::vector<Knot>::iterator it;
00205 
00206         for (it = m_knot.begin(); it != m_knot.end(); it++)
00207         {
00208           if ( (*it).m_IsSelected)
00209           {
00210             m_knot.erase (it);
00211             found = TRUE;
00212             break;
00213           }
00214         }
00215 
00216         if (!found)
00217           finish = TRUE;
00218       }
00219       while ( (!finish) && (m_knot.size() > 2) );
00220     }
00221 
00222     void SelectKnot (int i, bool b)
00223     {
00224       m_knot[i].m_IsSelected = b;
00225     }
00226 
00227     t_u32 GetNumSelectedKnot()
00228     {
00229       t_u32 n = 0;
00230       std::vector<Knot>::iterator it;
00231 
00232       for (t_u32 i = 0; i < (t_u32) m_knot.size(); i++)
00233       {
00234         if (m_knot[i].m_IsSelected)
00235           n++;
00236       }
00237 
00238       return n;
00239     }
00240 
00241     void SelectAllKnot()
00242     {
00243       std::vector<Knot>::iterator it;
00244 
00245       for (it = m_knot.begin(); it != m_knot.end(); it++)
00246       {
00247         (*it).m_IsSelected = TRUE;
00248       }
00249     }
00250 
00251     void UnSelectAllKnot()
00252     {
00253       std::vector<Knot>::iterator it;
00254 
00255       for (it = m_knot.begin(); it != m_knot.end(); it++)
00256       {
00257         (*it).m_IsSelected = false;
00258       }
00259     }
00260 
00261     const std::vector<double> GetXArray()
00262     {
00263       std::vector<double> array;
00264       std::vector<Knot>::iterator it;
00265 
00266       for (it = m_knot.begin(); it != m_knot.end(); it++)
00267       {
00268         if (! (*it).m_IsExcluded)
00269           array.push_back ( (*it).x);
00270       }
00271 
00272       return array;
00273     }
00274 
00275 
00276     const std::vector<double> GetYArray()
00277     {
00278       std::vector<double> array;
00279       std::vector<Knot>::iterator it;
00280 
00281       for (it = m_knot.begin(); it != m_knot.end(); it++)
00282       {
00283         if (! (*it).m_IsExcluded)
00284           array.push_back ( (*it).y);
00285       }
00286 
00287       return array;
00288     }
00289 
00290     int GetNumKnot() const
00291     {
00292       return (int) m_knot.size();
00293     }
00294     Knot GetKnot (int i) const
00295     {
00296       return m_knot[i];
00297     }
00298 
00302     void Reset()
00303     {
00304       m_knot.clear();
00305       AddKnot (0, 0);
00306       AddKnot (1, 1);
00307     }
00308   private:
00309     std::vector<Knot> m_knot;
00310   };
00311 
00312   typedef float (*SplineFunctionCallback) (float);
00313 
00314   class SplineCurveEditor : public View
00315   {
00316   public:
00317     SplineCurveEditor (NUX_FILE_LINE_PROTO);
00318     ~SplineCurveEditor();
00319     void SetControlPoints (const SplineKnot &splineKnot);
00320     const SplineKnot &GetControlPoints() const;
00321     virtual long ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo);
00322     virtual void Draw (GraphicsEngine &GfxContext, bool force_draw);
00323     virtual void DrawContent (GraphicsEngine &GfxContext, bool force_draw);
00324     virtual void PostDraw (GraphicsEngine &GfxContext, bool force_draw);
00325 
00326     double Eval (double t);
00327 
00328     void RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags);
00329     void RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags);
00330     void RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
00331     void RecvKeyEvent (
00332       GraphicsEngine  &GfxContext, /*Graphics Context for text operation*/
00333       unsigned long   eventType  , /*event type*/
00334       unsigned long   keysym     , /*event keysym*/
00335       unsigned long   state      , /*event state*/
00336       const TCHAR*    character  , /*character*/
00337       unsigned short  keyCount     /*key repeat count*/
00338     );
00339 
00340     sigc::signal< void, SplineCurveEditor * > sigCurveChange;
00341 
00345     void Reset();
00346 
00347     int GetNumKnot() const
00348     {
00349       return (int) m_control_knot.GetNumKnot();
00350     }
00351     SplineKnot::Knot GetKnot (int i) const
00352     {
00353       return m_control_knot.GetKnot (i);
00354     }
00355     void AddKnot (double x, double y, bool selected = false);
00356 
00357   protected:
00358     void InitializeWidgets();
00359     void InitializeLayout();
00360     void DestroyLayout();
00361 
00362   private:
00363     ObjectPtr<IOpenGLBaseTexture> m_Texture;
00364     GLSh_DrawFunction *m_DrawFunctionShader;
00365     AbstractPaintLayer *m_Background;
00366 
00367     void SetXAxisBounds (float minX, float maxX);
00368     void SetYAxisBounds (float minY, float maxY);
00369     void SetFunctionCallback (SplineFunctionCallback f);
00370     float EvalFunction (float x);
00371     void UpdateGraph();
00372 
00373     SplineKnot m_control_knot;
00374 
00375     float m_minX, m_minY, m_maxX, m_maxY;
00376     SplineFunctionCallback m_FunctionCallback;
00377 
00378     float hit_point_dx;
00379     float hit_point_dy;
00380 
00381     CubicSpline m_CubicSpline;
00382   };
00383 
00384 }
00385 
00386 #endif // SPLINECURVEEDITOR_H