# Get CGPath total length

I have many UIBezierPath that I am animating with CALyerAnimation @”StrokeStart” and @”strokeEnd”.

I wish that the animation will have the same speed for all the paths so I thougt I might use the length of the path in :

• Get points from a UIBezierPath
• Undestanding UIBezierPath curving mechanism, controlPoint and the curve point
• How to animate a human written stroke using Swift/iOS?
• Reposition CGPath/UIBezierPath in View
• Draw Line Using UIPinchGeustureRecognizer
• How to draw Signature on UIView
• DISTANCE / TIME = SPEED

Is there a way to calculate the path “length” ?

Thanks

Shani

### 2 Solutions Collect From Internet About “Get CGPath total length”

While you can calculate Bezier path’s length by integrating it numerically, it can be done much easier by dividing path into linear segments. If the segments are small enough the approximation error should be neglectable, especially that you are just trying to animate it.

I’ll show you function for quad curves, but you can easily incorporate the solution for cubic curves as well:

``````- (float) bezierCurveLengthFromStartPoint: (CGPoint) start toEndPoint: (CGPoint) end withControlPoint: (CGPoint) control
{
const int kSubdivisions = 50;
const float step = 1.0f/(float)kSubdivisions;

float totalLength = 0.0f;
CGPoint prevPoint = start;

// starting from i = 1, since for i = 0 calulated point is equal to start point
for (int i = 1; i <= kSubdivisions; i++)
{
float t = i*step;

float x = (1.0 - t)*(1.0 - t)*start.x + 2.0*(1.0 - t)*t*control.x + t*t*end.x;
float y = (1.0 - t)*(1.0 - t)*start.y + 2.0*(1.0 - t)*t*control.y + t*t*end.y;

CGPoint diff = CGPointMake(x - prevPoint.x, y - prevPoint.y);

totalLength += sqrtf(diff.x*diff.x + diff.y*diff.y); // Pythagorean

prevPoint = CGPointMake(x, y);
}

}
``````

EDIT

If you don’t have access to path control points (say you created path using arcs) you can always access underlying Bezier curves using `CGPathApply` function:

``````- (void) testPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointZero];

CGPathRef p = path.CGPath;

CGPathApply(p, nil, pathFunction);
}

void pathFunction(void *info, const CGPathElement *element)
{
{
CGPoint p;
p = element->points[0]; // control point
NSLog(@"%lg %lg", p.x, p.y);

p = element->points[1]; // end point
NSLog(@"%lg %lg", p.x, p.y);
}
// check other cases as well!
}
``````

Note that it doesn’t provide the path’s start point, but it’s easy to keep track of it on your own.

Recently I had the same issue, but in this case I needed the complete path length regardless the elements involved. e.g lines, curves, arcs, and the solution above doesn’t worked for me, I came up with a general solution.

Here the complete code written in swift UIBezierPath.length

This is the extension that contain the `length` property.

``````extension UIBezierPath{
var length: CGFloat{
var pathLength:CGFloat = 0.0
var current = CGPointZero
var first   = CGPointZero

self.CGPath.forEach{ element in
pathLength += element.distance(to: current, startPoint: first)

if element.type == .MoveToPoint{
first = element.point
}
if element.type != .CloseSubpath{
current = element.point
}
}
return pathLength
}
}

// e.g
let path = UIBezierPath()
path.lineWidth = 10
path.moveToPoint(CGPoint(x: 10, y: 10))