Compute the area of a closed curve by counting pixels. http://stackoverflow.com/questions/14220719/ios-how-to-calculate-number-of-pixels-area-enclosed-by-a-curve
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; | |
} |
This comment has been minimized.
This comment has been minimized.
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
This comment has been minimized.
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.