Skip to content

Instantly share code, notes, and snippets.

@mayoff mayoff/curveArea.m
Created Jan 11, 2013

Embed
What would you like to do?
static CGPathRef createClosedPathWithPoints(const CGPoint *points, size_t count) {
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddLines(path, NULL, points, count);
CGPathCloseSubpath(path);
return path;
}
static CGRect integralFrameForPath(CGPathRef path) {
CGRect frame = CGPathGetBoundingBox(path);
return CGRectIntegral(frame);
}
static size_t bytesPerRowForWidth(CGFloat width) {
static const size_t kFactor = 64;
// Round up to a multiple of kFactor, which must be a power of 2.
return ((size_t)width + (kFactor - 1)) & ~(kFactor - 1);
}
static CGContextRef createBitmapContextWithFrame(CGRect frame, size_t bytesPerRow) {
CGColorSpaceRef grayscale = CGColorSpaceCreateDeviceGray();
CGContextRef gc = CGBitmapContextCreate(NULL, frame.size.width, frame.size.height, 8, bytesPerRow, grayscale, kCGImageAlphaNone);
CGColorSpaceRelease(grayscale);
CGContextTranslateCTM(gc, -frame.origin.x, -frame.origin.x);
return gc;
}
static double areaFilledInBitmapContext(gc) {
size_t width = CGBitmapContextGetWidth(gc);
size_t height = CGBitmapContextGetHeight(gc);
size_t stride = CGBitmapContextGetBytesPerRow(gc);
uint8_t *pixels = CGBitmapContextGetData(gc);
uint64_t coverage = 0;
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
coverage += pixels[y * stride + x];
}
}
return (double)coverage / UINT8_MAX;
}
static double areaOfCurveWithPoints(const CGPoint *points, size_t count) {
CGPathRef path = createClosedPathWithPoints(points, count);
CGRect frame = integralFrameForPath(path);
size_t bytesPerRow = bytesPerRowForWidth(frame.size.width);
CGContextRef gc = createBitmapContextWithFrame(frame, bytesPerRow);
CGContextSetFillColorWithColor(gc, [UIColor whiteColor].CGColor);
CGContextAddPath(gc, path);
CGContextFillPath(gc);
CGPathRelease(path);
double area = areaFilledInBitmapContext(gc);
CGContextRelease(gc);
return area;
}
@chika-kasymov

This comment has been minimized.

Copy link

chika-kasymov commented Oct 17, 2017

Thanks!

I changed this line CGContextTranslateCTM(gc, -frame.origin.x, -frame.origin.x); to this: CGContextTranslateCTM(gc, -frame.origin.x, -frame.origin.y); to apply your solution to custom UIBezierPath shape. Then it works fine.

@johanblomgren

This comment has been minimized.

Copy link

johanblomgren commented Nov 19, 2018

Thanks!

I changed this line CGContextTranslateCTM(gc, -frame.origin.x, -frame.origin.x); to this: CGContextTranslateCTM(gc, -frame.origin.x, -frame.origin.y); to apply your solution to custom UIBezierPath shape. Then it works fine.
@chika-kasymov

I'm facing a similar challenge, trying to calculate the "area" of an enclosed, custom UIBezierPath. Would you mind sharing your solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.