Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7163659
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 28, 20262026-05-28T13:56:23+00:00 2026-05-28T13:56:23+00:00

I have recently finished writing a script for Maya that exports a file containing

  • 0

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

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-28T13:56:24+00:00Added an answer on May 28, 2026 at 1:56 pm

    Alright so this’ll be a long answer. Here’s what Ive done:

    1. 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:

    #import <Foundation/Foundation.h>
    #import "AEBezierVertex.h"
    #import "AEBezierLine.h"
    
    @interface AEBezierPath : NSObject
    {
        NSMutableArray *vertices;
        NSMutableArray *lines;
        UIBezierPath *path;
    }
    
    @property (strong) NSMutableArray *vertices;
    @property (strong) NSMutableArray *lines;
    @property (strong) UIBezierPath *path;
    
    -(id) initFromFile: (NSString*) file;
    -(CGPoint) positionFromDistance: (float) fromDistance;
    
    @end
    

    .m file:

    #import "AEBezierPath.h"
    
    CGFloat bezierInterpolation(CGFloat t, CGFloat a, CGFloat b, CGFloat c, CGFloat d) {
        // see also below for another way to do this, that follows the 'coefficients'
        // idea, and is a little clearer
        CGFloat t2 = t * t;
        CGFloat t3 = t2 * t;
        return a + (-a * 3 + t * (3 * a - a * t)) * t
        + (3 * b + t * (-6 * b + b * 3 * t)) * t
        + (c * 3 - c * 3 * t) * t2
        + d * t3;
    }
    
    @implementation AEBezierPath
    @synthesize vertices;
    @synthesize lines;
    @synthesize path;
    
    -(id) initFromFile: (NSString*) file
    {
        self = [super init];
        if (self) {
    
            //Init file objects for reading
            NSError *fileError;
            NSStringEncoding *encoding;
    
            vertices = [[NSMutableArray alloc] init];
            lines = [[NSMutableArray alloc] init];
            path = [[UIBezierPath alloc] init]; 
    
            //Load the specified file's contents into an NSString
            NSString *fileData = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"testcurve" ofType:@"bezier"] usedEncoding:&encoding error:&fileError];
            NSScanner *scanner = [[NSScanner alloc] initWithString:fileData];
    
            if(fileData == nil)
            {
                NSLog(@"Error reading bezier path file");
            }
            else
            {
                float x;
                float y;
                float cx;
                float cy;
                float cx2;
                float cy2;
                float temp;
    
                CGPoint readPoint;
                CGPoint readControlIn;
                CGPoint readControlOut;
    
                int curRead = 0;
                int totalSegments = 0;
                float length;
    
                [scanner scanInt:&totalSegments];
    
                for (int s = 0; s < totalSegments; s++) {
                    [scanner scanFloat:&length];
                    AEBezierLine *newLine = [[AEBezierLine alloc] initWithLength:length];
    
                    [lines addObject:newLine];
                }
    
                AEBezierVertex *vertex;
    
                while ([scanner isAtEnd] == 0) {
    
                    if (curRead == 0) {
                        [scanner scanFloat:&x];
                        [scanner scanFloat:&temp];
                        [scanner scanFloat:&y];
    
    
                        [scanner scanFloat:&cx2];
                        [scanner scanFloat:&temp];
                        [scanner scanFloat:&cy2];  
    
                        cx = x;
                        cy = y;
                    }
    
                    else{
    
                        [scanner scanFloat:&cx];
                        [scanner scanFloat:&temp];
                        [scanner scanFloat:&cy];
    
                        [scanner scanFloat:&x];
                        [scanner scanFloat:&temp];
                        [scanner scanFloat:&y];
    
                        if ([scanner isAtEnd] == 0) {
                            [scanner scanFloat:&cx2];
                            [scanner scanFloat:&temp];
                            [scanner scanFloat:&cy2];
                        }else
                        {
                            cx = x;
                            cy = y;
                        }
                    }
    
                    readPoint = CGPointMake(x, y);
                    readControlIn = CGPointMake(cx, cy);
                    readControlOut = CGPointMake(cx2, cy2);
    
                    vertex = [[AEBezierVertex alloc] initWithControl:readPoint In:readControlIn Out:readControlOut];
    
                    [vertices addObject:vertex];
    
                    curRead ++;
    
                }
    
                for (int c = 0; c < [vertices count]-1; c++) {
    
                    //Init CGPoints for single bezier curve segment
                    CGPoint p1, p2, p3, p4;
    
                    //Store starting bezier point and control point
                    AEBezierVertex *b1 = [vertices objectAtIndex:c];
                    p1 = b1.control;
                    p2 = b1.controlOut;    
    
                    //Store ending bezier point and control point
                    AEBezierVertex *b2 = [vertices objectAtIndex:c+1];
                    p3 = b2.controlIn;
                    p4 = b2.control;
    
                    if (c == 0) {
                        [path moveToPoint:p1];
                    }
                    else
                    {
                        [path addCurveToPoint:p4 controlPoint1:p2 controlPoint2:p3];
                    }
                }
            }
        }
        return self;
    }
    
    -(CGPoint) positionFromDistance: (float) fromDistance
    {
        CGPoint position;
    
    
        AEBezierLine *line;
        float runningLength;
        int seg = 0;
    
        for (int c = 0; c < [lines count]; c++) {
            seg = c;
            line = [lines objectAtIndex:c];
            runningLength += line.length;
            if (runningLength > fromDistance) {
                break;
            }
        }
    
        CGPoint p1, p2, p3, p4;
    
        AEBezierVertex *vert1 = [vertices objectAtIndex:seg];
        p1 = vert1.control;
        p2 = vert1.controlOut;    
    
        //Store ending bezier point and control point
        AEBezierVertex *vert2 = [vertices objectAtIndex:seg+1];
        p3 = vert2.controlIn;
        p4 = vert2.control;
    
        float travelDist;
        travelDist = fromDistance;
    
        travelDist = runningLength - travelDist;
        travelDist = line.length - travelDist;
    
        float t = travelDist / line.length;
    
        //Create a new point to represent this position
        position = CGPointMake(bezierInterpolation(t, p1.x, p2.x, p3.x, p4.x),
                                     bezierInterpolation(t, p1.y, p2.y, p3.y, p4.y));    
    
        return position;
    }
    
    @end
    

    AEBezierVertex:

    .h file:

    #import <Foundation/Foundation.h>
    
    @interface AEBezierVertex : NSObject
    {
        CGPoint controlIn;
        CGPoint controlOut;
        CGPoint control;
    }
    @property CGPoint controlIn;
    @property CGPoint controlOut;
    @property CGPoint control;
    
    -(id) initWithControl: (CGPoint) setControl In: (CGPoint) setIn Out: (CGPoint) setOut;
    
    @end
    

    .m file:

    #import "AEBezierVertex.h"
    
    @implementation AEBezierVertex
    @synthesize controlIn;
    @synthesize controlOut;
    @synthesize control;
    
    -(id) initWithControl: (CGPoint) setControl In: (CGPoint) setIn Out: (CGPoint) setOut
    {
        self = [super init];
        if (self) {
            //Init
            control = setControl;
            controlIn = setIn;
            controlOut = setOut;
        }
        return self;
    }
    
    @end
    

    AEBezierLine:

    .h file:

    #import <Foundation/Foundation.h>
    
    @interface AEBezierLine : NSObject
    {
        float length;
    }
    @property float length;
    
    -(id) initWithLength: (float) setLength;
    
    @end
    

    .m file:

    #import "AEBezierLine.h"
    
    @implementation AEBezierLine
    @synthesize length;
    
    -(id) initWithLength: (float) setLength
    {
        self = [super init];
        if (self) {
            //Init
            length = setLength;
        }
        return self;
    }
    
    @end
    

    How It Works:

    1. Ensure you have created a .bezier file suiting the structure I’ve shown above and have it in your app’s bundle.

    2. 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.

    1. 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.

    • Adam Eisfeld
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm very new to Ruby. I've recently finished writing a simple script, which uses
I have recently finished phase 1 of my Facebook game: Rails Across Europe It
I have recently written an application(vb.net) that stores and allows searching for old council
I recently finished a class that we're using to tie Access to some WCF
Recently I have finished my first Iphone app and it works grate.... except for
I have recently bought a template that came with a flash header. I want
I have recently been doing some work that has been quite in depth, i
I have a script I'm writing to batch download images from an imageboard via
I have recently finished creating a STS setup and need to expose some WCF
I have recently finished my app and after I save, publish activate etc. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.