Skip to main content
gamedev.net
🔒 Locked

Path class

Started by patrrr 2 replies 600+ views
Original Post
patrrr
patrrr
Hello guys! I'm working on a project where I'm going to need paths, like splines, circles, lines, etc. So I figured I would have a Path-class which can contain multiple sub-paths (one spline leading to one straight line and ends with a half circle", and from that class I can get coordinates for a position (0.0 - 1.0). Example: (2D)

CPath MyPath;
MyPath.Append(new CLine(0.0, 0.0, 10.0, 10.0));    // p1x, p1y, p2x, p2y
MyPath.Append(new CBezier(10.0, 10.0, 15.0, 15.0, 20.0, 10.0));   // p1x, p1y, p2x, p2y, p3x, p3y
MyPath.Append(new CArc(20.0, 15.0, 5.0, PI / 2.0, -PI / 2.0));   // centerx, centery, radius, startangle, endangle

Pos = MyPath.GetPosition(0.5); // would probably be on the Bezier curve
It would look something like this:

           _  |
  _/ \_/
 /
/
So, my question #1 is: how would you implement this? If I know the length of each "sub-path" (ie, the line, bezier graph and the arc) it would be pretty easy to calculate which sub-path the position refers to, but how would I get the position on that sub-path? (My head is blocked I'm afraid). EDIT: Impossible to get the ASCII-art correct...
iMalc
iMalc
Getting the poisition on the sub-path is easy if you know how long each sub-path preceeding it is, and how long the segment it is within is. You just remap the t parameter to between zero and one just for that piece, and then interpolate t along the curve.

I think its number 2 that needs to be solved first though, as number 1 depends on it. The best way I know of for measuring the length or the bezier is by adaptive subdivision.
Zakwayda
Zakwayda
The first thing you need to do is associate a range [min_t, max_t] with each curve based on its length and the total length of the composite curve. Pseudocode:
float total_length = sum( curve lengths );float length = 0;for (each curve) {    curve.min_t = length / total_length;    length += curve.length;    curve.max_t = length / total_length;}
Then, given a value of t you can determine the correct curve based on which of these ranges t happens to fall in. From there you can map t to the range [0,1] so that it can function as the 'local' parametric value for that particular curve. Here's the function I use for such mappings:
template < typename T >T map_range(T value, T min1, T max1, T min2, T max2) {    return min2 + ((value - min1) / (max1 - min1)) * (max2 - min2);}
(Note that this function assumes the input interval has non-zero magnitude.)

You would then compute the 'local' t as follows:
t = map_range(t, curve.min_t, curve.max_t, 0, 1);
Of course this all assumes that you have the tools in place for arc-length reparameterization. You can find a good article on the subject here called 'Moving at Constant Speed'.

I think I've seen articles on computing the length of a Bezier curve analytically, but I'm not sure I'd bother; one of the numerical methods mentioned in the article should suffice.
patrrr
patrrr
Thanks! That cleared my mind a bit.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.