Go to the documentation of this file.00001 #include <art_map/SmoothCurve.h>
00002
00003
00004 SmoothCurve::SmoothCurve(const std::vector<Point2f>& ctrl,
00005 float starttheta, float startspeed,
00006 float endtheta, float endspeed, bool use_pats)
00007 {
00008
00009
00010
00011
00012
00013 startspeed = fmax(1,startspeed);
00014 endspeed = fmax(1,endspeed);
00015
00016 degree=3;
00017
00018 dataPoints=ctrl;
00019
00020 int n =(dataPoints.size()-1)*2;
00021 controlPoints.resize(n);
00022
00023 for (int i = 0; i < (int)controlPoints.size(); i++)
00024 {
00025 controlPoints[i] = dataPoints[(i + 1 )/ 2];
00026 }
00027
00028
00029 n = dataPoints.size();
00030 float speed = (startspeed+endspeed) / 2.0;
00031 std::vector<Point2f> M;
00032 M.resize(n);
00033 M[0] = Vec2f(cosf(starttheta),sinf(starttheta))*startspeed;
00034 M[n-1] = Vec2f(cosf(endtheta),sinf(endtheta))*endspeed;
00035 for (int i = 1; i < n-1;i++)
00036 {
00037 Vec2f a = dataPoints[i] - dataPoints[i-1];
00038 Vec2f b = dataPoints[i+1] - dataPoints[i];
00039 a.normalize();
00040 b.normalize();
00041 Vec2f top=a+b;
00042 if (use_pats && i >1 && i <n-2) {
00043 Vec2f a2 = dataPoints[i] - dataPoints[i-2];
00044 Vec2f b2 = dataPoints[i+2] - dataPoints[i];
00045 a2.normalize();
00046 b2.normalize();
00047 float adot=a.dot(a2);
00048 float bdot=b.dot(b2);
00049 float ratio=adot/bdot;
00050 if (Epsilon::lte(ratio,.9775))
00051 top=b;
00052 else if (Epsilon::gte(ratio,1/.9775))
00053 top=a;
00054
00055
00056
00057
00058
00059
00060
00061 }
00062 top.normalize();
00063 M[i] = top*speed;
00064 }
00065
00066
00067 knots.resize(ctrl.size());
00068 knots[0]=0;
00069 for(unsigned int i=1;i<knots.size();i++){
00070 Vec2f a = dataPoints[i] - dataPoints[i-1];
00071 float alen=a.length();
00072
00073 Vec2f v1 = M[i-1];
00074 Vec2f v2 = M[i];
00075
00076 a.normalize();
00077 v1.normalize();
00078 v2.normalize();
00079
00080 float theta1 = acosf(fmax(-1.0,fmin(1.0,a.dot(v1))));
00081 float theta2 = acosf(fmax(-1.0,fmin(1.0,a.dot(v2))));
00082
00083 float l1 = 0, l2 = 0;
00084 float sinth1=sinf(theta1);
00085 if (Epsilon::equal(sinth1,0.0))
00086 l1 = alen;
00087 else
00088 l1 = fabs(alen*theta1/sinth1);
00089
00090
00091 float sinth2=sinf(theta2);
00092 if (Epsilon::equal(sinth2,0.0))
00093 l2 = alen;
00094 else
00095 l2 = fabs(alen*theta2/sinth2);
00096
00097
00098 float r= l1 + l2;
00099
00100 if(i==1){
00101 r/=(startspeed+speed);
00102 }
00103 else if(i==(knots.size()-1)){
00104 r/=(endspeed+speed);
00105 }
00106 else{
00107 r/=(2.0*speed);
00108 }
00109
00110
00111 knots[i]=knots[i-1]+r;
00112 }
00113
00114
00115
00116
00117
00118
00119 for(int i=0;i< (int)controlPoints.size();i++){
00120 Vec2f tempVec1 = M[(i+1)/2];
00121 float del;
00122
00123 if(i%2==0){
00124 del = (DeltaU(i/2)/((float)degree));
00125 controlPoints[i]+= tempVec1 * del;
00126 }
00127 else{
00128 del = (DeltaU((i-1)/2)/((float)degree));
00129 controlPoints[i]-= tempVec1 * del;
00130 }
00131 }
00132
00133 }
00134
00135 SmoothCurve::~SmoothCurve() {}
00136
00137 float SmoothCurve::DeltaU (int i)
00138 {
00139 if (i >= (int)knots.size()-1)
00140 {
00141 std::cerr << "Delta() - array out of bounds" << std::endl;
00142 exit(1);
00143 }
00144 else
00145 return knots[i+1] - knots[i];
00146 }
00147
00148 Point2f SmoothCurve::bezierPoint(int i)
00149 {
00150 Point2f temp;
00151 switch(i%3){
00152 case 0:
00153 temp=dataPoints[i/3];
00154 break;
00155 case 1:
00156 temp=controlPoints[2*(i/3)];
00157 break;
00158 default:
00159 temp=controlPoints[2*(i/3)+1];
00160 }
00161 return temp;
00162 }
00163
00164 Vec2f SmoothCurve::Delta(int i)
00165 {
00166 return bezierPoint(i+1)-bezierPoint(i);
00167 }
00168
00169
00170 int SmoothCurve::knotCount() const
00171 {
00172 return knots.size();
00173 }
00174
00175 int SmoothCurve::controlPointsCount() const
00176 {
00177 return controlPoints.size();
00178 }
00179
00180 int SmoothCurve::dataPointsCount() const
00181 {
00182 return dataPoints.size();
00183 }
00184
00185 Point2f SmoothCurve::getDataPoint(int index) const
00186 {
00187 return dataPoints[index];
00188 }
00189
00190 Point2f SmoothCurve::getControlPoint(int index) const
00191 {
00192 return controlPoints[index];
00193 }
00194
00195 float SmoothCurve::getKnot(int index) const
00196 {
00197 return knots[index];
00198 }
00199
00200 void SmoothCurve::clear()
00201 {
00202 dataPoints.clear();
00203 knots.clear();
00204 controlPoints.clear();
00205 }
00206
00207
00208 float SmoothCurve::curveLength()
00209 {
00210 return knots.empty() ? 0 : knots.back();
00211 }
00212
00213 Point2f SmoothCurve::evaluatePoint(float time)
00214 {
00215
00216 if (dataPoints.empty())
00217 return Point2f();
00218
00219 unsigned int i=0;
00220
00221 while (i < knots.size() &&
00222 knots[i] <= time)
00223 i++;
00224
00225 if (i == 0)
00226 return dataPoints[0];
00227 if (i >= knots.size())
00228 return dataPoints.back();
00229
00230
00231
00232
00233 Point2f sum(0,0);
00234 std::vector<float> b(degree+1,0);
00235 float u = (time-knots[i-1])/(knots[i]-knots[i-1]);
00236
00237 b[0]=powf(1-u,3);
00238 b[1]=3*(u*powf(1-u,2));
00239 b[2]=3*(powf(u,2)*powf(1-u,1));
00240 b[3]=powf(u,3);
00241
00242 i=(i-1)*3;
00243 for(int j=0;j<degree+1;j++)
00244 sum+=bezierPoint(i+j)*b[j];
00245 return sum;
00246 }
art_map
Author(s): David Li, Patrick Beeson, Bartley Gillen, Tarun Nimmagadda,
Mickey Ristroph, Michael Quinlan, Jack O'Quin
autogenerated on Tue Sep 24 2013 10:41:51