nux-1.14.0
BezierCurveControl.cpp
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 #include "Nux.h"
00024 #include "NuxCore/Math/Constants.h"
00025 #include "NuxCore/Math/Spline.h"
00026 #include "NuxCore/Math/Bezier.h"
00027 #include "BezierCurveControl.h"
00028 
00029 namespace nux
00030 {
00031 
00032   const int KNOT_SIZE = 2;
00033   const int KNOT_HIT_TEST = 4;
00034 
00035   BezierCurveControl::BezierCurveControl (NUX_FILE_LINE_DECL)
00036     :   View (NUX_FILE_LINE_PARAM)
00037     ,   m_minX (0.0f),
00038     m_minY (0.0f),
00039     m_maxX (1.0f),
00040     m_maxY (1.0f),
00041     m_FunctionCallback (0)
00042   {
00043     SetMinimumSize (400, 300);
00044     SetBaseSize (400, 300);
00045 
00046     m_control_knot.push_back (Knot (0.0f, 0.0f) );
00047     m_control_knot.push_back (Knot (0.1f, 0.0f) );
00048     m_control_knot.push_back (Knot (0.7f, 0.9f) );
00049     m_control_knot.push_back (Knot (1.0f, 1.0f) );
00050 
00051     mouse_down.connect (sigc::mem_fun (this, &BezierCurveControl::RecvMouseDown) );
00052     mouse_up.connect (sigc::mem_fun (this, &BezierCurveControl::RecvMouseUp) );
00053     mouse_drag.connect (sigc::mem_fun (this, &BezierCurveControl::RecvMouseDrag) );
00054 
00055   }
00056 
00057   BezierCurveControl::~BezierCurveControl()
00058   {
00059 
00060 
00061   }
00062 
00063 
00064   long BezierCurveControl::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00065   {
00066     long ret = TraverseInfo;
00067 
00068     if (ievent.e_event == NUX_MOUSE_PRESSED)
00069     {
00070       if (!GetGeometry().IsPointInside (ievent.e_x, ievent.e_y) )
00071       {
00072         //ProcEvInfo = eDoNotProcess;
00073         //return TraverseInfo;
00074       }
00075     }
00076 
00077     ret = PostProcessEvent2 (ievent, ret, 0);
00078     return ret;
00079   }
00080 
00081 
00082   void BezierCurveControl::Draw (GraphicsEngine &GfxContext, bool force_draw)
00083   {
00084     Geometry base = GetGeometry();
00085 
00086     GetPainter().PaintBackground (GfxContext, base);
00087     GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (COLOR_BACKGROUND_SECONDARY) );
00088 
00089 #define N 3
00090     t_u32 i;
00091     t_u32 nsample = 30;
00092     double t;
00093     t_u32 nbKnot = (t_u32) m_control_knot.size();
00094 
00095     if (nbKnot > 0)
00096     {
00097       double *xcon = new double[nbKnot];
00098       double xval;
00099       double *ycon = new double[nbKnot];
00100       double yval;
00101 
00102 
00103       for (i = 0; i < nbKnot; i++)
00104       {
00105         xcon[i] = m_control_knot[i].m_X;
00106         ycon[i] = m_control_knot[i].m_Y;
00107       }
00108 
00109       int W = GetBaseWidth() - 2;
00110       int H = GetBaseHeight() - 2;
00111       int X = GetBaseX() + 1;
00112       int Y = GetBaseY() + 1;
00113 
00114       double xprev, yprev;
00115       Bezier_XY (N, 0.0, xcon, ycon, &xprev, &yprev);
00116 
00117       //GetPainter().Draw2DLine(X, Y, X+W, Y+H, Color(0xFFFF0000));
00118 
00119       base.OffsetPosition (1, 1);
00120       base.OffsetSize (-2, -2);
00121 
00122       GfxContext.PushClippingRectangle (base);
00123 
00124       GfxContext.GetRenderStates().EnableLineSmooth (TRUE, 1, GL_FASTEST);
00125       GfxContext.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00126 
00127       for (i = 1; i < nsample; i++)
00128       {
00129         t = ( double ) ( i ) / ( double ) ( nsample - 1 );
00130         Bezier_XY ( N, t, xcon, ycon, &xval, &yval );
00131 
00132         int X0, Y0, X1, Y1;
00133         X0 = X + W * (xprev - m_minX) / (m_maxX - m_minX);
00134         Y0 = Y + H * ( 1 - (yprev - m_minY) / (m_maxY - m_minY) );
00135         X1 = X + W * (xval - m_minX) / (m_maxX - m_minX);
00136         Y1 = Y + H * ( 1 - (yval - m_minY) / (m_maxY - m_minY) );
00137 
00138         GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFF0000) );
00139 
00140         xprev = xval;
00141         yprev = yval;
00142       }
00143 
00144       GfxContext.GetRenderStates().EnableLineSmooth (FALSE);
00145       GfxContext.GetRenderStates().SetBlend (GL_FALSE);
00146 
00147       for (i = 0; i < nbKnot - 1; i++)
00148       {
00149         int X0, Y0, X1, Y1;
00150         X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00151         Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00152         X1 = X + W * (m_control_knot[i+1].m_X - m_minX) / (m_maxX - m_minX);
00153         Y1 = Y + H * ( 1 - (m_control_knot[i+1].m_Y - m_minY) / (m_maxY - m_minY) );
00154 
00155         GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFF0000FF) );
00156 
00157       }
00158 
00159       for (i = 0; i < nbKnot; i++)
00160       {
00161         int X0, Y0;
00162         X0 = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00163         Y0 = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00164 
00165         if (m_control_knot[i].m_IsSelected)
00166           GetPainter().Paint2DQuadColor (GfxContext, X0 - KNOT_SIZE, Y0 - KNOT_SIZE, 2 * KNOT_SIZE, 2 * KNOT_SIZE, Color (0xFF00FF00) );
00167         else
00168           GetPainter().Paint2DQuadColor (GfxContext, X0 - KNOT_SIZE, Y0 - KNOT_SIZE, 2 * KNOT_SIZE, 2 * KNOT_SIZE, Color (0xFF777777) );
00169       }
00170 
00171       delete[] xcon;
00172       delete[] ycon;
00173     }
00174 
00175 //    for(int i = 1; i < GetWidth(); i++)
00176 //    {
00177 //        float x1, y1;
00178 //
00179 //        x1 = x0 + dX;
00180 //        y1 = EvalFunction(x1);
00181 //
00182 //        int X0, Y0, X1, Y1;
00183 //        X0 = X + W * (x0 - m_minX) / (m_maxX - m_minX);
00184 //        Y0 = Y - H * (y0 + m_minY) / (m_maxY - m_minY);
00185 //        X1 = X + W * (x1 - m_minX) / (m_maxX - m_minX);
00186 //        Y1 = Y - H * (y1 + m_minY) / (m_maxY - m_minY);
00187 //        GetPainter().Draw2DLine(X0, Y0, X1, Y1, Color(0xFFFF0000));
00188 //
00189 //        x0 = x1;
00190 //        y0 = y1;
00191 //
00192 //    }
00193     GfxContext.PopClippingRectangle();
00194   }
00195 
00196 
00197   void BezierCurveControl::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
00198   {
00199 
00200   }
00201 
00202   void BezierCurveControl::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
00203   {
00204 
00205   }
00206 
00207 
00208   void BezierCurveControl::SetXAxisBounds (float minX, float maxX)
00209   {
00210     m_minX = minX;
00211     m_maxX = maxX;
00212     QueueDraw();
00213   }
00214 
00215   void BezierCurveControl::SetYAxisBounds (float minY, float maxY)
00216   {
00217     m_minY = minY;
00218     m_maxY = maxY;
00219     QueueDraw();
00220   }
00221 
00222   void BezierCurveControl::SetFunctionCallback (FunctionCallback f)
00223   {
00224     m_FunctionCallback = f;
00225     QueueDraw();
00226   }
00227 
00228   float BezierCurveControl::EvalFunction (float x)
00229   {
00230     if (m_FunctionCallback != 0)
00231       return (*m_FunctionCallback) (x);
00232 
00233     return 0;
00234   }
00235 
00236   void BezierCurveControl::UpdateGraph()
00237   {
00238     QueueDraw();
00239   }
00240 
00241 
00242 // check if a value lies within a closed interval
00243 #ifndef INSIDE_BOUNDS
00244 #define INSIDE_BOUNDS( x, lo, hi ) ( (x) >= (lo) && (x) <= (hi) )
00245 #endif
00246 
00247 //check if a 2D point lies within a 2D box
00248 #ifndef PT_INSIDE_BOX
00249 #define PT_INSIDE_BOX( x, y, lo_x, hi_x, lo_y, hi_y ) ( INSIDE_BOUNDS(x,lo_x,hi_x) && INSIDE_BOUNDS(y,lo_y,hi_y) )
00250 #endif
00251 
00252   void BezierCurveControl::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
00253   {
00254     QueueDraw();
00255   }
00256 
00257   void BezierCurveControl::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
00258   {
00259     t_u32 nbKnot = (t_u32) m_control_knot.size();
00260 
00261     for (t_u32 i = 0; i < nbKnot; i++)
00262     {
00263       m_control_knot[i].m_IsSelected = false;
00264     }
00265 
00266     int W = GetBaseWidth() - 2;
00267     int H = GetBaseHeight() - 2;
00268     int X = GetBaseX() + 1;
00269     int Y = GetBaseY() + 1;
00270 
00271     bool b = PT_INSIDE_BOX (X + x, Y + y, X, X + W, Y, Y + H);
00272 
00273     if (b == false)
00274       return;
00275 
00276     X = GetBaseX();
00277     Y = GetBaseY();
00278 
00279     for (t_u32 i = 0; i < nbKnot; i++)
00280     {
00281       int Xp, Yp;
00282       Xp = X + W * (m_control_knot[i].m_X - m_minX) / (m_maxX - m_minX);
00283       Yp = Y + H * ( 1 - (m_control_knot[i].m_Y - m_minY) / (m_maxY - m_minY) );
00284 
00285       if (PT_INSIDE_BOX (X + x, Y + y, Xp - KNOT_HIT_TEST, Xp + KNOT_HIT_TEST, Yp - KNOT_HIT_TEST, Yp + KNOT_HIT_TEST) )
00286       {
00287         m_control_knot[i].m_IsSelected = true;
00288         break;
00289       }
00290     }
00291 
00292     QueueDraw();
00293   }
00294 
00295   void BezierCurveControl::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00296   {
00297     float xp, yp;
00298 
00299     int W = GetBaseWidth();
00300     int H = GetBaseHeight();
00301     t_u32 nbKnot = (t_u32) m_control_knot.size();
00302 
00303     xp = m_minX + (m_maxX - m_minX) * dx / W;
00304     yp = m_minY + (m_maxY - m_minY) * dy / H;
00305 
00306 
00307 
00308     for (t_u32 i = 0; i < nbKnot; i++)
00309     {
00310       if (m_control_knot[i].m_IsSelected)
00311       {
00312         m_control_knot[i].m_X += xp;
00313         m_control_knot[i].m_Y -= yp;
00314 
00315         if (m_control_knot[i].m_X < m_minX)
00316         {
00317           m_control_knot[i].m_X = m_minX;
00318         }
00319 
00320         if (m_control_knot[i].m_X > m_maxX)
00321         {
00322           m_control_knot[i].m_X = m_maxX;
00323         }
00324 
00325         if (m_control_knot[i].m_Y < m_minY)
00326         {
00327           m_control_knot[i].m_Y = m_minY;
00328         }
00329 
00330         if (m_control_knot[i].m_Y > m_maxY)
00331         {
00332           m_control_knot[i].m_Y = m_maxY;
00333         }
00334 
00335         break;
00336       }
00337     }
00338 
00339     QueueDraw();
00340   }
00341 
00342 
00343 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends