## Finding the center of a CGPath

uibezierpath
cgpath transform
cgpath circle
cgpath tutorial
swift draw shapes
spritekit bezier path

I have an arbitrary `CGPath` and I'd like to find it's geographic center. I can get the path bounding box with `CGPathGetPathBoundingBox` and then find the center of that box. But is there a better way to find the center of a path?

Update for those who like to see code: here is code for using the average-of-points method suggested by Adam in the answers (don't miss the even better technique in the answers below)...

```    BOOL moved = NO; // the first coord should be a move, the rest add lines
CGPoint total = CGPointZero;
for (NSDictionary *coord in [polygon objectForKey:@"coordinates"]) {
CGPoint point = CGPointMake([(NSNumber *)[coord objectForKey:@"x"] floatValue],
[(NSNumber *)[coord objectForKey:@"y"] floatValue]);
if (moved) {
// calculate totals of x and y to help find the center later
// skip the first "move" point since it is repeated at the end in this data
total.x = total.x + point.x;
total.y = total.y + point.y;
} else {
CGContextMoveToPoint(context, point.x, point.y);
moved = YES; // we only move once, then we add lines
}
}

// the center is the average of the total points
CGPoint center = CGPointMake(total.x / ([[polygon objectForKey:@"coordinates"] count]-1), total.y / ([[polygon objectForKey:@"coordinates"] count]-1));
```

If you have a better idea, please share!

The technique works, but the code you put in the question doesn't. AFAICS, that only works for the few situations where you are doing straight-line polygons ONLY, and you have a list of points, and you haven't made the CGPath object yet.

I needed to do it for arbitrary CGPath objects. Using Adam's (other Adam) suggestion, and Apple's CGPathApply, I came up with this, which works very well:

```{
float dataArray = { 0, 0, 0 };
CGPathApply( (CGPathRef) YOUR_PATH, dataArray, pathApplierSumCoordinatesOfAllPoints);

float averageX = dataArray / dataArray;
float averageY = dataArray  / dataArray;
CGPoint centerOfPath = CGPointMake(averageX, averageY);
}

static void pathApplierSumCoordinatesOfAllPoints(void* info, const CGPathElement* element)
{
float* dataArray = (float*) info;
float xTotal = dataArray;
float yTotal = dataArray;
float numPoints = dataArray;

switch (element->type)
{
case kCGPathElementMoveToPoint:
{
/** for a move to, add the single target point only */

CGPoint p = element->points;
xTotal += p.x;
yTotal += p.y;
numPoints += 1.0;

}
break;
{
/** for a line to, add the single target point only */

CGPoint p = element->points;
xTotal += p.x;
yTotal += p.y;
numPoints += 1.0;

}
break;
for( int i=0; i<2; i++ ) // note: quad has TWO not THREE
{
/** for a curve, we add all ppints, including the control poitns */
CGPoint p = element->points[i];
xTotal += p.x;
yTotal += p.y;
numPoints += 1.0;
}
break;
for( int i=0; i<3; i++ ) // note: cubic has THREE not TWO
{
/** for a curve, we add all ppints, including the control poitns */
CGPoint p = element->points[i];
xTotal += p.x;
yTotal += p.y;
numPoints += 1.0;
}
break;
case kCGPathElementCloseSubpath:
/** for a close path, do nothing */
break;
}

//NSLog(@"new x=%2.2f, new y=%2.2f, new num=%2.2f", xTotal, yTotal, numPoints);
dataArray = xTotal;
dataArray = yTotal;
dataArray = numPoints;
}
```

Core Graphics, Part 4: A Path! A Path!, Depending on how you're calculating points, accumulated floating point round off let squarePath = CGPath(rect: rect1, transform: nil) let ovalpath Arc – Give it the center of the circle, its radius, and the starting and ending  Centering a CGPath in Swift Recently I was trying to work out how to center a CGPath in Swift, and Google was failing me. I found a pretty quick and easy way to do it so I thought I’d drop it here for others to find.

For me, the simple average of all points in the path did not suffice for some of the polygons I was dealing with.

I implemented it using the area (see wikipedia, Centroid of polygon and Paul Bourke's page). It might not be the most efficient implementation but it works for me.

Note that it only works for closed, non-intersecting polygons. The vertices are assumed to be numbered in order of their occurrence along the polygon's perimeter, and the last point is assumed to be the same as the first point.

```CGPoint GetCenterPointOfCGPath (CGPathRef aPath)
{
// Convert path to an array
NSMutableArray* a = [NSMutableArray new];
CGPathApply(aPath, (__bridge void *)(a), convertToListOfPoints);
return centroid(a);
}

static void convertToListOfPoints(void* info, const CGPathElement* element)
{
NSMutableArray* a = (__bridge NSMutableArray*) info;

switch (element->type)
{
case kCGPathElementMoveToPoint:
{
}
break;
{
}
break;
{
for (int i=0; i<2; i++)
}
break;
{
for (int i=0; i<3; i++)
}
break;
case kCGPathElementCloseSubpath:
break;
}
}

double polygonArea(NSMutableArray* points) {
int i,j;
double area = 0;
int N = [points count];

for (i=0;i<N;i++) {
j = (i + 1) % N;
CGPoint pi =  [(NSValue*)[points objectAtIndex:i] CGPointValue];
CGPoint pj =  [(NSValue*)[points objectAtIndex:j] CGPointValue];
area += pi.x * pj.y;
area -= pi.y * pj.x;
}

area /= 2;
return area;
}

CGPoint centroid(NSMutableArray* points) {
double cx = 0, cy = 0;
double area = polygonArea(points);

int i, j, n = [points count];

double factor = 0;
for (i = 0; i < n; i++) {
j = (i + 1) % n;
CGPoint pi =  [(NSValue*)[points objectAtIndex:i] CGPointValue];
CGPoint pj =  [(NSValue*)[points objectAtIndex:j] CGPointValue];
factor = (pi.x * pj.y - pj.x * pi.y);
cx += (pi.x + pj.x) * factor;
cy += (pi.y + pj.y) * factor;
}

cx *= 1 / (6.0f * area);
cy *= 1 / (6.0f * area);

return CGPointMake(cx, cy);
}
```

CGMutablePath, class CGMutablePath : CGPath func addArc(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool, transform:  Arc – Give it the center of the circle, its radius, and the starting and ending angles (in radians) of the arc segment you want. The section of the circle between the start and ending angles (going clockwise or counter-clockwise) is what will be drawn.

Does the simple average of all x and all y for the points in the path give the point you want? Calculate one value for x and one for y. I made a quick sketch and this method gave a believable answer.

If not you may need to first find the area - see Paul Bourke's page.

calculate points on UIBezierPath – MachineThinks, cgPath. shapeLayer.fillColor = UIColor.clear.cgColor. shapeLayer.strokeColor It will be useful to calculate the intermidiate point on curve. easiest way to find the center of the circle. draw a square (square has four equal sides and four right angles) inside the circle with the corners exactly on the circular line then draw a straight line from one corner of the square to its opposite corner do it also on the other two corners left, the center of the circle will be the intersection point of the two straight lines drawn from the

```extension CGPath {
func findCenter() -> CGPoint {
class Context {
var sumX: CGFloat = 0
var sumY: CGFloat = 0
var points = 0
}

var context = Context()

apply(info: &context) { (context, element) in
guard let context = context?.assumingMemoryBound(to: Context.self).pointee else {
return
}
switch element.pointee.type {
let point = element.pointee.points
context.sumX += point.x
context.sumY += point.y
context.points += 1
let controlPoint = element.pointee.points
let point = element.pointee.points
context.sumX += point.x + controlPoint.x
context.sumY += point.y + controlPoint.y
context.points += 2
let controlPoint1 = element.pointee.points
let controlPoint2 = element.pointee.points
let point = element.pointee.points
context.sumX += point.x + controlPoint1.x + controlPoint2.x
context.sumY += point.y + controlPoint1.y + controlPoint2.y
context.points += 3
case .closeSubpath:
break
}
}

return CGPoint(x: context.sumX / CGFloat(context.points),
y: context.sumY / CGFloat(context.points))
}
}
```

But be careful, CGPath may have extra move commands that will break this logic because of point count

Thinking like a Bézier path, Orange dots are the center of the circles that define the rounded corners. or their counterparts for CGPath's: Unless you are calculating the exact point for a given t there is no need to do these calculations yourself but having seen them can  Finding Center, Marion, Ohio. 1.4K likes. Finding Center specializes in hot yoga. Classes ranging from Vinyasa Flow to Yin Yoga. Our retail space includes handmade jewelry, leisure apparel, and

Here is the centroid, come get it:

```-(CLLocationCoordinate2D)getCentroidFor:(GMSMutablePath *)rect
{
CLLocationCoordinate2D coord = [rect coordinateAtIndex:0];
double minX = coord.longitude;
double maxX = coord.longitude;
double minY = coord.latitude;
double maxY = coord.latitude;
for (int i = 1; i < rect.count; i++)
{
CLLocationCoordinate2D coord = [rect coordinateAtIndex:i];
if (minX > coord.longitude)
minX = coord.longitude;
if (maxX < coord.longitude)
maxX = coord.longitude;
if (minY > coord.latitude)
minY = coord.latitude;
if (maxY < coord.latitude)
maxY = coord.latitude;
}

CLLocationDegrees centerX = minX + ((maxX - minX) / 2);
CLLocationDegrees centerY = minY + ((maxY - minY) / 2);
return CLLocationCoordinate2DMake(centerY, centerX);
}
```

Core Graphics Tutorial: Arcs and Paths, And now that you know c and d, you can calculate the radius with the arcHeight​: CGFloat, startAngle: Angle, endAngle: Angle ) -> CGPath  This work provides the foundation for creating a CGPath based on ID2D1PathGeometry and GeometrySink. A simple implementation for adding a simple line, moving the current location to a new point and retrieving some basic information from the Geometry sink has been added. Isolated unit tests have also been added to ensure

UIBezierPath, addArcWithCenter(CGPoint(x: 2, y: 2), // center point of circle radius: 2, // this will make it CGPath // apply other properties related to the path shapeLayer. 15, 5, 17, 3, 10, 20] // 1. find center of draw rect let center: CGPoint = CGPoint(x: rect. * Switch all internal interfaces to HR returns. * Implement the CGContext non-drawing path functions in terms of CGPath. Curiously, CGContext path queries and CopyPath return untransformed units. Closes #1238. * Finish Simple line and status CGPath APIs. * Finish Simple line and status CGPath APIs. Add additional tests to cover these scenarios.

How to use UIBezierPath and CGPath in SwiftUI, If you have existing paths made using UIBezierPath or CGPath it's trivial to convert them for use in SwiftUI because the Path struct has an  4.0 out of 5 stars Finding the Center by V.S. Naipaul Reviewed in the United States on February 27, 2002 It is a rear book of two essays that dealt with the author's own personal experiences in two entirely different worlds.

Advanced UIView shadow effects using shadowPath – Hacking with , Making UIKit calculate the shadow path dynamically is significantly but normally I just create a UIBezierPath then use its cgPath property. Similarly, with the GraphView selected, Control-drag from the center slightly up (still within the view), and choose Height from the popup menu. Control-drag left from inside the view to outside the view and choose Center Horizontally in Container. Control-drag up from inside the view to outside the view, and choose Center Vertically in Container.

• There's a bug here, `kCGPathElementAddCurveToPoint` has 3 points, not 4.