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_BEZIER4_H_UTC20050626084023_DEFINED
00035 #define GROOVX_GEOM_BEZIER4_H_UTC20050626084023_DEFINED
00036
00037 #include "rutz/algo.h"
00038
00039 #include <cmath>
00040
00041 namespace geom
00042 {
00043
00044
00045
00047
00048 class bezier4
00049 {
00050 private:
00051 double m_ctrl[4];
00052
00053
00054
00055 double m_c0[4];
00056
00057
00058
00059 double m_c1[4];
00060
00061 double m_val_min;
00062 double m_val_max;
00063
00064 bool m_have_min_max;
00065
00066 void compute_min_max();
00067
00068 public:
00070 inline bezier4(double R0, double R1, double R2, double R3);
00071
00073 inline void set_control_points(double R0, double R1,
00074 double R2, double R3);
00075
00077 inline double eval(double u);
00079 inline double eval_deriv(double u);
00080
00082 inline double eval_min();
00084 inline double eval_max();
00085 };
00086
00087 }
00088
00089
00090
00091
00092
00093 inline geom::bezier4::bezier4(double R0, double R1,
00094 double R2, double R3) :
00095 m_ctrl(),
00096 m_c0(),
00097 m_c1(),
00098 m_val_min(0.0),
00099 m_val_max(0.0),
00100 m_have_min_max(false)
00101 {
00102 set_control_points(R0, R1, R2, R3);
00103 }
00104
00105 inline void geom::bezier4::compute_min_max()
00106 {
00107 double b2_4ac = m_c1[1]*m_c1[1] - 4*m_c1[0]*m_c1[2];
00108
00109 using rutz::max;
00110 using rutz::min;
00111
00112 m_val_min = min(eval(0.0), eval(1.0));
00113 m_val_max = max(eval(0.0), eval(1.0));
00114
00115 if (b2_4ac >= 0.0)
00116 {
00117 double part1 = -m_c1[1] / (2*m_c1[2]);
00118 double part2 = sqrt(b2_4ac) / (2*m_c1[2]);
00119
00120 double extremum1 = rutz::clamp(part1 + part2, 0.0, 1.0);
00121 double extremum2 = rutz::clamp(part1 - part2, 0.0, 1.0);
00122
00123 double v1 = eval(extremum1);
00124 double v2 = eval(extremum2);
00125
00126 if (v1 < m_val_min) m_val_min = v1;
00127 else if (v1 > m_val_max) m_val_max = v1;
00128
00129 if (v2 < m_val_min) m_val_min = v2;
00130 else if (v2 > m_val_max) m_val_max = v2;
00131 }
00132
00133 m_have_min_max = true;
00134 }
00135
00136 inline void geom::bezier4::set_control_points(double R0, double R1,
00137 double R2, double R3)
00138 {
00139 m_have_min_max = false;
00140
00141 m_ctrl[0] = R0;
00142 m_ctrl[1] = R1;
00143 m_ctrl[2] = R2;
00144 m_ctrl[3] = R3;
00145
00146
00147 m_c0[0] = m_ctrl[0];
00148 m_c0[1] = -3*m_ctrl[0] + 3*m_ctrl[1];
00149 m_c0[2] = 3*m_ctrl[0] - 6*m_ctrl[1] + 3*m_ctrl[2];
00150 m_c0[3] = -m_ctrl[0] + 3*m_ctrl[1] - 3*m_ctrl[2] + m_ctrl[3];
00151
00152
00153 m_c1[0] = 1 * m_c0[1];
00154 m_c1[1] = 2 * m_c0[2];
00155 m_c1[2] = 3 * m_c0[3];
00156 }
00157
00158 inline double geom::bezier4::eval(double u)
00159 {
00160 return (m_c0[0] + m_c0[1]*u + m_c0[2]*u*u + m_c0[3]*u*u*u);
00161 }
00162
00163 inline double geom::bezier4::eval_deriv(double u)
00164 {
00165 return (m_c1[0] + m_c1[1]*u + m_c1[2]*u*u);
00166 }
00167
00168 inline double geom::bezier4::eval_max()
00169 {
00170 if (!m_have_min_max) compute_min_max();
00171 return m_val_max;
00172 }
00173
00174 inline double geom::bezier4::eval_min()
00175 {
00176 if (!m_have_min_max) compute_min_max();
00177 return m_val_min;
00178 }
00179
00180 static const char __attribute__((used)) vcid_groovx_geom_bezier4_h_utc20050626084023[] = "$Id: bezier4.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00181 #endif // !GROOVX_GEOM_BEZIER4_H_UTC20050626084023_DEFINED