Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mayoff
Created January 11, 2013 22:30
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mayoff/4514516 to your computer and use it in GitHub Desktop.
Save mayoff/4514516 to your computer and use it in GitHub Desktop.
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
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
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