Created
January 11, 2013 22:30
-
-
Save mayoff/4514516 to your computer and use it in GitHub Desktop.
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
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
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.