"parallel" bezier curves

Started by
5 comments, last by Erkki 20 years, 8 months ago
In my game prototype, I am defining roads in the game world with bezier curves & lines. But when I want to draw these roads, I need to draw a few "parallel" (probably the wrong term) curves, depending on how many lanes there are on the road etc. The minimum would be 2 for one road (the sides of the road). But I don''t know how to calculate a "parallel" curve. The other curves would be a bit different and so the control points must change too. Is it even possible to calculate it? It would probably be easier if I used catmull-roms? Here''s a little picture to illustrate: http://lap.ttu.ee/erkki/bezier.jpg It isn''t exactly what I need, that just has the copy of the same curve placed next to the other. And in reality, the end points should not be apart like that, but one should be on the others normal.
Advertisement
You can find the normal component to the curve at each point. By adding or substracting the normal vector to the position vector of that point, you''ll get another point. Now, do this for each point, and you should get a parallel curve... Even better, from the inital curve, create two parallel curves (so the inital shape serves as an axis).

How to do this? Well a Bézier curve is a R² Bernstein polynomial, of the form

{ X(t) = an t^n + .... a1 t + a0
{ Y(t) = bn t^n + .... b1 t + b0

So the tangent vector is obtained by derivating

{ Xtan(t) = n an t^(n-1) + ..... 2 a2 t + a1
{ Ytan(t) = n bn t^(n-1) + ..... 2 b2 t + b1

So Xnor = -Ytan, Ynor = Xran is a normal vector. Normalize it to have a magnitude vector, and multiply it by half the width of the path you want to create.

Basically, one side of your path will be

{ X(t) + (Width / 2) * (normalized)Xnor(t)
{ Y(t) + (Width / 2) * (normalized)Ynor(t)

And the other will be

{ X(t) - (Width / 2) * (normalized)Xnor(t)
{ Y(t) - (Width / 2) * (normalized)Ynor(t)

So for each (t) you can compute a point on each side of your road.


ToohrVyk

yeah, you need to derive the curve to get the direction at the point of interest on the curve, and the second derivative will give you the ''acceleration'', which would be a direction pointing towards the ''inside'' of the curve. You cross product the two, and it will give you the vector towards the side of the curvature, basically, where to draw the parallel curve. The catmul-romms are not continuous in the second derivative, so they won;t be very useful for what you need. However, since you are doing roads, you can expect the road to be generally pointing up towards the sky. In that case, you can use just the first derivative, and deduce the direction of the width of the road.

// normal spline calculation, to get the point on a spline and the direction at that point.void CalculatePointOnPath(float u, Vector& P, Vector& Dir){...............}Vector CalculateSideVector(Vector Dir, Vector Up=Vector(0, 1, 0)){     Vector Side = Up.Cross(Dir);         Side.Normalise();     Up = Dir.Cross(Side);     return Side;}


so for a given point on the spline, the point on the other lane would be

float u;        // Position on the spline of the control pointVector P;       // point on the reference spline (control point)Vector Dir;     // the direction of the spline at point PVector Up;      // the reference direction of the roadVector Side;    // where the parallel spline should be relative to the reference spline// calculate the point on path and the direction of the path at that pointCalculatePointOnPath(u, P, Dir);Dir.Normalise();Up = Vector(0, 1, 0);// calculate the side direction at the point on path to generate a point on a parallel splineSide = CalculateSideVector(Dir, Up);// calculate the point on the parallel splinePother = P + Side * widthOfLane;



if the spline is C2 continous, you can do

float u;        // Position on the spline of the control pointVector P;       // point on the reference spline (control point)Vector Dir;     // the direction of the spline at point PVector Up;      // the reference direction of the roadVector Side;    // where the parallel spline should be relative to the reference spline// calculate the point on path and the direction of the path at that pointCalculatePointOnPath(u, P, Dir, Up);Dir.Normalise();Up.Normalise();// calculate the side direction at the point on path to generate a point on a parallel splineSide = Up.Cross(Up, Dir);Side.Normalise();// calculate the point on the parallel splinePother = P + Side * widthOfLane;

Everything is better with Metal.

Uuh... thanx for your help. I haven''t done much math for several years so It''ll take me some time to figure this out
Thanx a lot, ToohrVyk! I got it now.
I feel stupid for not figuring this out myself
I don''t know if this is more of a math or programming question, but:

If I want to have a bit more bends following each other, should I use a bezier curve with more control points (I haven''t looked into how that works exactly, but the code I''ve been using to draw a bezier - from SDL_gfx - let''s you use any number of points >= 3)? Or should I just put several 4-point beziers together?

I think the first option would make everything a bit more difficult so I''m leaning towards using several 4-point beziers in a row.
Id'' advise you to use several 4-point curves (even 3-point ones) because that solution is less computationnally expensive/

ToohrVyk

This topic is closed to new replies.

Advertisement