MKPolygon area calculation

前端 未结 3 935
萌比男神i
萌比男神i 2020-12-01 17:39

I\'m trying to make an area calculation category for MKPolygon. I found some JS code https://github.com/mapbox/geojson-area/blob/master/index.js#L1 with a link to the algori

相关标签:
3条回答
  • 2020-12-01 17:49

    The final step for i = N-1 and i+1 = 0 (wrap around) is missing in your loop.

    0 讨论(0)
  • 2020-12-01 18:02

    This may help to someone... You need to pass the shape edge points into below method and it returns the correct area of a polygon

    static double areaOfCurveWithPoints(const NSArray *shapeEdgePoints) {
    
        CGPoint initialPoint = [shapeEdgePoints.firstObject CGPointValue];
    
        CGMutablePathRef cgPath = CGPathCreateMutable();
        CGPathMoveToPoint(cgPath, &CGAffineTransformIdentity, initialPoint.x, initialPoint.y);
    
        for (int i = 1;i<shapeEdgePoints.count ;i++) {
    
            CGPoint point = [[shapeEdgePoints objectAtIndex:i] CGPointValue];
            CGPathAddLineToPoint(cgPath, &CGAffineTransformIdentity, point.x, point.y);
        }
        CGPathCloseSubpath(cgPath);
    
        CGRect frame = integralFrameForPath(cgPath);
        size_t bytesPerRow = bytesPerRowForWidth(frame.size.width);
        CGContextRef gc = createBitmapContextWithFrame(frame, bytesPerRow);
        CGContextSetFillColorWithColor(gc, [UIColor whiteColor].CGColor);
        CGContextAddPath(gc, cgPath);
        CGContextFillPath(gc);
    
        double area = areaFilledInBitmapContext(gc);
    
        CGPathRelease(cgPath);
        CGContextRelease(gc);
    
        return area;
    }
    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(CGContextRef gc) {
        size_t width = CGBitmapContextGetWidth(gc);
        size_t height = CGBitmapContextGetHeight(gc);
        size_t stride = CGBitmapContextGetBytesPerRow(gc);
    
        // Get a pointer to the data
        unsigned char *bitmapData = (unsigned char *)CGBitmapContextGetData(gc);
    
        uint64_t coverage = 0;
        for (size_t y = 0; y < height; ++y) {
            for (size_t x = 0; x < width; ++x) {
                coverage += bitmapData[y * stride + x];
            }
        }
       // NSLog(@"coverage =%llu  UINT8_MAX =%d",coverage,UINT8_MAX);
        return (double)coverage / UINT8_MAX;
    }
    
    0 讨论(0)
  • 2020-12-01 18:08

    The whole algorithm implemented in Swift 3.0 :

    import MapKit
    let kEarthRadius = 6378137.0
    
    // CLLocationCoordinate2D uses degrees but we need radians
    func radians(degrees: Double) -> Double {
        return degrees * M_PI / 180;
    }
    
    func regionArea(locations: [CLLocationCoordinate2D]) -> Double {
    
        guard locations.count > 2 else { return 0 }
        var area = 0.0
    
        for i in 0..<locations.count {
            let p1 = locations[i > 0 ? i - 1 : locations.count - 1]
            let p2 = locations[i]
    
            area += radians(degrees: p2.longitude - p1.longitude) * (2 + sin(radians(degrees: p1.latitude)) + sin(radians(degrees: p2.latitude)) )
        }
    
        area = -(area * kEarthRadius * kEarthRadius / 2);
    
        return max(area, -area) // In order not to worry about is polygon clockwise or counterclockwise defined.
    }
    
    0 讨论(0)
提交回复
热议问题