bezier.h

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2002-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Wed Nov 20 12:17:07 2002
00010 // commit: $Id: bezier.h 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/geom/bezier.h $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_GEOM_BEZIER_H_UTC20050626084023_DEFINED
00035 #define GROOVX_GEOM_BEZIER_H_UTC20050626084023_DEFINED
00036 
00037 #include "rutz/algo.h"
00038 #include "rutz/arrays.h"
00039 
00040 #include <cmath>
00041 
00042 namespace geom
00043 {
00044   //  #######################################################
00045   //  =======================================================
00046 
00048 
00051   class bezier
00052   {
00053   private:
00054     rutz::dynamic_block<double> m_ctrl;      // control points
00055 
00056     // coefficients of the Bezier polynomial
00057     // p(u) = c0[0] + c0[1]*u + c0[2]*u^2 + c0[3]*u^3
00058     rutz::dynamic_block<double> m_c0;
00059 
00060     // coefficients of the derivative polynomial
00061     // p'(u) = c1[0] + c1[1]*u + c1[2]*u^2
00062     rutz::dynamic_block<double> m_c1;
00063 
00064     double m_arg_min;  // value of u in [0,1] which gives the minimum
00065     double m_arg_max;  // value of u in [0,1] which gives the maximum
00066     double m_val_min;
00067     double m_val_max;
00068 
00069     static int choose(int n, int k)
00070     {
00071       // result = n! / [k!(n-k)!]
00072       int result = 1;
00073 
00074       // we have symmetry of (n k) = (n n-k)
00075       // smaller k gives a faster computation, so:
00076       if ( (n-k) < k ) { k = n-k; }
00077 
00078       // compute n! / (n-k)!  =  n*(n-1)*(n-2)...(n-k+1)
00079       for (int f = n; f > (n-k); --f)
00080         {
00081           result *= f;
00082         }
00083       for (int d = 2; d <= k; ++d)
00084         {
00085           result /= d;
00086         }
00087 
00088       return result;
00089     }
00090 
00091   public:
00097     bezier(const rutz::dynamic_block<double>& RR, int extrema_res=-1);
00098 
00100     void set_control_points(const rutz::dynamic_block<double>& RR,
00101                             int extrema_res=-1);
00102 
00103 
00105     double eval(double u);
00107     double eval_deriv(double u);
00108 
00110     double arg_min() { return m_arg_min; }
00112     double arg_max() { return m_arg_max; }
00113 
00115     double eval_min() { return m_val_min; }
00117     double eval_max() { return m_val_max; }
00118   };
00119 
00120 } // end namespace geom
00121 
00122 //  #######################################################
00123 //  =======================================================
00124 
00125 geom::bezier::bezier(const rutz::dynamic_block<double>& RR,
00126                      int extrema_res) :
00127   m_ctrl(),
00128   m_c0(),
00129   m_c1(),
00130   m_arg_min(0.0),
00131   m_arg_max(0.0),
00132   m_val_min(0.0),
00133   m_val_max(0.0)
00134 {
00135   set_control_points(RR, extrema_res);
00136 }
00137 
00138 void geom::bezier::set_control_points
00139   (const rutz::dynamic_block<double>& RR,
00140    int extrema_res)
00141 {
00142   m_ctrl = RR;
00143   m_c0.resize(RR.size());
00144   m_c1.resize(RR.size()-1);
00145 
00146   int n = RR.size()-1;          // degree of polynomial = num_points - 1
00147 
00148   //         ( n )    i  {     (i+k)   ( i )      }
00149   // c0    = (   ) * sum {  (-1)     * (   ) * R  }
00150   //   i     ( i )   k=0 {             ( k )    k }
00151 
00152   {for (int i = 0; i <= n; ++i)
00153     {
00154       m_c0[i] = 0;
00155 
00156       for (int k = 0; k <= i; ++k)
00157         {
00158           int i_choose_k = bezier::choose(i,k);
00159 
00160           m_c0[i] += ( (i+k)%2 ? 1 : -1) * i_choose_k * m_ctrl[k];
00161         }
00162 
00163       m_c0[i] *= bezier::choose(n,i);
00164     }
00165   }
00166 
00167   {for (size_t i = 0; i < m_c1.size(); ++i)
00168     {
00169       m_c1[i] = (i+1) * m_c0[i+1];
00170     }
00171   }
00172 
00173 
00174   if (extrema_res <= 0) { extrema_res = 4*(RR.size()); }
00175 
00176   m_arg_min = m_arg_max = 0.0;
00177   m_val_min = m_val_max = eval(0.0);
00178 
00179   for (int e = 1; e <= extrema_res; ++e)
00180     {
00181       const double u = double(e)/extrema_res;
00182       const double current = eval(u);
00183       if (current < m_val_min)
00184         {
00185           m_val_min = current;
00186           m_arg_min = u;
00187         }
00188       else if (current > m_val_max)
00189         {
00190           m_val_max = current;
00191           m_arg_max = u;
00192         }
00193     }
00194 }
00195 
00196 double geom::bezier::eval(double u)
00197 {
00198   double result = 0.0;
00199   double powers = 1.0;
00200   for (size_t i = 0; i < m_c0.size(); ++i)
00201     {
00202       result += m_c0[i] * powers;
00203       powers *= u;
00204     }
00205   return result;
00206 }
00207 
00208 double geom::bezier::eval_deriv(double u)
00209 {
00210   double result = 0.0;
00211   double powers = 1.0;
00212   for (size_t i = 0; i < m_c1.size(); ++i)
00213     {
00214       result += m_c1[i] * powers;
00215       powers *= u;
00216     }
00217   return result;
00218 }
00219 
00220 static const char __attribute__((used)) vcid_groovx_geom_bezier_h_utc20050626084023[] = "$Id: bezier.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00221 #endif // !GROOVX_GEOM_BEZIER_H_UTC20050626084023_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:38 2008 by Doxygen version 1.5.5.