00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <geometry/spline.h>
00025 #include <geometry/hom_vector.h>
00026 #include <cmath>
00027
00028 using namespace std;
00029
00030 namespace fawkes {
00031
00032
00033
00034
00035
00036
00037
00038 Spline::Spline()
00039 {
00040 m_num_subdivisions = 0;
00041 }
00042
00043
00044
00045
00046 Spline::Spline(const vector<HomPoint>& control_points)
00047 : m_control_points(control_points)
00048 {
00049 m_num_subdivisions = 0;
00050
00051 register_primitives();
00052 construct_bezier_curves();
00053 }
00054
00055
00056 Spline::~Spline()
00057 {
00058 }
00059
00060
00061
00062
00063 void
00064 Spline::set_control_points(const vector<HomPoint>& control_points)
00065 {
00066 m_control_points = control_points;
00067
00068 clear_primitives();
00069 register_primitives();
00070 construct_bezier_curves();
00071 }
00072
00073
00074
00075
00076
00077 void
00078 Spline::set_control_point(unsigned int i, const HomPoint& point)
00079 {
00080 m_control_points[i] = point;
00081
00082 clear_primitives();
00083 register_primitives();
00084 construct_bezier_curves();
00085 }
00086
00087
00088
00089
00090 const vector<HomPoint>&
00091 Spline::get_control_points() const
00092 {
00093 return m_control_points;
00094 }
00095
00096
00097
00098
00099 const vector<Bezier>&
00100 Spline::get_bezier_curves() const
00101 {
00102 return m_bezier_curves;
00103 }
00104
00105
00106
00107
00108
00109
00110 HomPoint
00111 Spline::eval(unsigned int bezier_index, float t)
00112 {
00113 return m_bezier_curves[bezier_index].eval(t);
00114 }
00115
00116
00117
00118
00119
00120
00121 HomVector
00122 Spline::tangent(unsigned int bezier_index, float t)
00123 {
00124 return m_bezier_curves[bezier_index].tangent_at_t(t);
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 HomVector
00134 Spline::tangent(unsigned int point_index)
00135 {
00136 unsigned int points_per_bezier = (unsigned int) rint( powf(2.0, m_num_subdivisions) ) * 3;
00137 unsigned int points_total = m_bezier_curves.size() * (points_per_bezier - 1) + 1;
00138
00139 if (point_index >= points_total)
00140 { return m_bezier_curves.back().tangent_at_t(1.0); }
00141 else
00142 {
00143 unsigned int bezier_index = point_index / points_per_bezier;
00144 unsigned int index = point_index - bezier_index * points_per_bezier;
00145
00146 return m_bezier_curves[bezier_index].tangent_at_t( index / (float) points_per_bezier );
00147 }
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 vector<HomPoint>
00161 Spline::approximate(unsigned int num_subdivisions)
00162 {
00163 vector<HomPoint> approximation;
00164
00165 for ( vector<Bezier>::iterator bit = m_bezier_curves.begin();
00166 bit != m_bezier_curves.end();
00167 ++bit )
00168 {
00169 vector<HomPoint> points = bit->approximate(num_subdivisions);
00170 vector<HomPoint>::iterator pit = points.begin();
00171
00172 if ( bit != m_bezier_curves.begin() )
00173
00174
00175 { ++pit; }
00176
00177 for ( vector<HomPoint>::iterator iter = pit;
00178 iter != points.end();
00179 ++iter )
00180 {
00181 approximation.push_back( *iter );
00182 }
00183 }
00184
00185 m_num_subdivisions = num_subdivisions;
00186
00187 return approximation;
00188 }
00189
00190 void
00191 Spline::register_primitives()
00192 {
00193 vector<HomPoint>::iterator iter;
00194 for ( iter = m_control_points.begin();
00195 iter != m_control_points.end();
00196 ++iter )
00197 {
00198 HomCoord& c = *iter;
00199 add_primitive( &c );
00200 }
00201 }
00202
00203 void
00204 Spline::post_transform()
00205 {
00206 construct_bezier_curves();
00207 }
00208
00209 void
00210 Spline::construct_bezier_curves()
00211 {
00212 m_bezier_curves.clear();
00213
00214 if ( 0 == m_control_points.size() )
00215 { return; }
00216
00217 vector<HomPoint>::iterator i = m_control_points.begin();
00218 vector<HomPoint>::iterator prev = i;
00219 vector<HomPoint>::iterator cur = ++i;
00220 vector<HomPoint>::iterator next = ++i;
00221
00222 HomPoint cp1 = (*prev);
00223
00224 while ( cur != m_control_points.end() )
00225 {
00226 HomPoint cp2;
00227 HomPoint cp3;
00228 HomPoint cp4;
00229
00230 HomVector v;
00231
00232 v = (*cur) - (*prev);
00233
00234 cp2 = (*prev) + v * (1.0 / 3.0);
00235 cp3 = (*prev) + v * (2.0 / 3.0);
00236
00237 if ( next == m_control_points.end() )
00238 { cp4 = *cur; }
00239 else
00240 {
00241 HomPoint t;
00242
00243 v = (*next) - (*cur);
00244 t = (*cur) + v * (1.0 / 3.0);
00245 cp4 = cp3 + (t - cp3) * 0.5;
00246 }
00247
00248 vector<HomPoint> control_points;
00249 control_points.push_back(cp1);
00250 control_points.push_back(cp2);
00251 control_points.push_back(cp3);
00252 control_points.push_back(cp4);
00253
00254 m_bezier_curves.push_back( Bezier(control_points) );
00255
00256 cp1 = cp4;
00257 ++prev;
00258 ++cur;
00259 ++next;
00260 }
00261 }
00262
00263 }