patterncppModerate
Bezier curves of grade n
Viewed 0 times
gradebeziercurves
Problem
I made a function which creates Bezier curves of grade n. What do you think?
float interpolate(float n1, float n2, float prec)
{
return n1 + ((n2-n1) * prec);
}
std::vector make_bezier(const std::vector& anchors, double accuracy=10000.0)
{
if(anchors.size() end;
end.push_back(anchors[0]);
for(float i=0.f; i temp;
for(unsigned int j=1; j1)
{
std::vector temp2;
for(unsigned int j=1; j<temp.size(); ++j)
temp2.push_back(Vector2f(interpolate(temp[j-1].x, temp[j].x, i),
interpolate(temp[j-1].y, temp[j].y, i)));
temp = temp2;
}
end.push_back(temp[0]);
}
return end;
}Solution
Just a few comments:
You're using
I'd write this a bit differently. As it stands,
This way, each value of
Literally all your calls to
With that in place, the loop above can be reduced to a fairly simple application of
Of course, pretty much the same would happen here:
...as well.
std::vector make_bezier(const std::vector& anchors, double accuracy=10000.0)You're using
float for all your other floating point variables. Unless there's some really good reason to use double here (for accuracy) I'd consider changing it to a float as well.std::vector end;
end.push_back(anchors[0]);
for(float i=0.f; i<1.f; i+=1.f/accuracy)I'd write this a bit differently. As it stands,
i can accumulate rounding errors from one iteration of the loop to the next. I'd prefer to do something like:for (int j=0; j<accuracy; j++) {
float i = 1.0f/j;
// ...This way, each value of
i is computed independently, and rounding from one iteration doesn't affect its value in the next.std::vector temp;
for(unsigned int j=1; j<anchors.size(); ++j)
temp.push_back(Vector2f(interpolate(anchors[j-1].x, anchors[j].x, i),
interpolate(anchors[j-1].y, anchors[j].y, i)));Literally all your calls to
interolate (at least in this code) happen in pairs. That being the case, I think I'd rewrite it a bit to take a couple of vector2fs as parameters, and return a vector2f containing the interpolation on both the x and y components of the inputs. It also uses i as a third input. My immediate reaction would be to define interpolate as a lambda that captured i, and took the other two parameters as inputs.vector2f interpolate(vector2f in1, vector2f const &in2) {
in1.x = /* ... */;
in1.y = /* ... */;
return in1;
}With that in place, the loop above can be reduced to a fairly simple application of
std::transform, something like this:std::transform(anchors.begin(), anchors.end(),
anchors.begin()+1,
std::back_inserter(temp));Of course, pretty much the same would happen here:
for(unsigned int j=1; j<temp.size(); ++j)
temp2.push_back(Vector2f(interpolate(temp[j-1].x, temp[j].x, i),
interpolate(temp[j-1].y, temp[j].y, i)));...as well.
Code Snippets
std::vector<Vector2f> make_bezier(const std::vector<Vector2f>& anchors, double accuracy=10000.0)std::vector<Vector2f> end;
end.push_back(anchors[0]);
for(float i=0.f; i<1.f; i+=1.f/accuracy)for (int j=0; j<accuracy; j++) {
float i = 1.0f/j;
// ...std::vector<Vector2f> temp;
for(unsigned int j=1; j<anchors.size(); ++j)
temp.push_back(Vector2f(interpolate(anchors[j-1].x, anchors[j].x, i),
interpolate(anchors[j-1].y, anchors[j].y, i)));vector2f interpolate(vector2f in1, vector2f const &in2) {
in1.x = /* ... */;
in1.y = /* ... */;
return in1;
}Context
StackExchange Code Review Q#43215, answer score: 11
Revisions (0)
No revisions yet.