00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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;
00055
00056
00057
00058 rutz::dynamic_block<double> m_c0;
00059
00060
00061
00062 rutz::dynamic_block<double> m_c1;
00063
00064 double m_arg_min;
00065 double m_arg_max;
00066 double m_val_min;
00067 double m_val_max;
00068
00069 static int choose(int n, int k)
00070 {
00071
00072 int result = 1;
00073
00074
00075
00076 if ( (n-k) < k ) { k = n-k; }
00077
00078
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 }
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;
00147
00148
00149
00150
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