I have recently finished writing a script for Maya that exports a file containing data for a Bezier path (a series of xy points and xy control points).
This bezier path is meant to represent the 3D “rail” or path that my character will travel along at a constant speed inside of the app.
I understand how to construct a UIBezierCurve, but I cant seem to find any solid information on if its possible / how to get the x / y position of a point on the curve, given a distance to travel along the curve.
I found this list on apple:
http://lists.apple.com/archives/cocoa-dev/2002/Feb/msg01806.html
But I dont quite understand what that function is returning and how I would use it to accomplish what Im aiming for.
Any help / advice would be greatly appreciated,
Thanks,
– Adam Eisfeld
Alright so this’ll be a long answer. Here’s what Ive done:
Ive programmed a MEL script that allows you to draw a bezier curve within Maya and then – selecting that curve – run my script which will go through the curve analyzing each bezier section of the curve calculating the length of each section and the positions of the curve points / control points. Once it has all of this data calculated, it exports everything to a .bezier file that is structured like this:
Line 1: Number of individual bezier curves contained in the entire bezier path
Line 2: Length of first bezier curve
…
Line X: Length of last bezier curve
X Position of the first control point of the first curve point
Y Position of the first control point of the first curve point
Z Position of the first control point of the first curve point
X Position of the first curve point
Y Position of the first curve point
Z Position of the first curve point
X Position of the second control point of the first curve point
Y Position of the second control point of the first curve point
Z Position of the second control point of the first curve point
…
X Position of the first control point of the last curve point
Y Position of the first control point of the last curve point
Z Position of the first control point of the last curve point
X Position of the last curve point
Y Position of the last curve point
Z Position of the last curve point
X Position of the second control point of the last curve point
Y Position of the second control point of the last curve point
Z Position of the second control point of the last curve point
So for this set of classes to work you’ll need a file structured like that.
Here are the three classes Ive then programmed to handle .bezier files:
AEBezierPath:
.h file:
.m file:
AEBezierVertex:
.h file:
.m file:
AEBezierLine:
.h file:
.m file:
How It Works:
Ensure you have created a .bezier file suiting the structure I’ve shown above and have it in your app’s bundle.
Instantiate a new AEBezierPath instance via:
-(id) initFromFile: (NSString*) file;
This will read in all of the data from the .bezier file named *file and construct a UIBezierPath from it, as well as store the necessary length information into the AEBezierPath.
Query the AEBezierPath for an x/y position in the form of a CGPoint, by sending it a distance value to travel from the start of the path, using the method:
-(CGPoint) positionFromDistance: (float) fromDistance;
This method will first determine which bezier segment that distance lies on by using the lengths of each bezier segment previously retrieved from the .bezier file. After this the method will use the bezierInterpolation function mentioned in the previous posts on this SO Question to calculate the x/y position on the bezier path at this distance, and return it as a CGPoint.
Its not perfect, there still is some noticeable differences in the distance traveled over long bezier curves vs short tight corners, but it is certainly far less noticeable than not using this system at all and instead relying on a percentage value to travel along the bezier curve.
I know the code can certainly be optimized, this is just a first run through to get everything working, but I think its good enough to post as an answer for now.