4

I have been trying to get a calculation of MKPolygon and I have followed a few links on here and have adjusted accordingly. I cannot seem to get the right calculations of squared meters. I can provide more information if needed

Here is my code

func polygonArea() -> Double{
    var area: Double = 0
    var kEarthRadius:Double = 6378137
    var coord: NSArray = self.coordinates()
    if (coord.count > 2){
        var p1, p2, p3 : CLLocationCoordinate2D

        var lowerIndex, middleIndex, upperIndex: Int
        for var i = 0; i < points.count - 1; i++ {
            if (i == (points.count - 2)){
                lowerIndex = points.count - 2
                middleIndex = points.count - 1
                upperIndex = 0
            }else if (i == points.count - 1){
                lowerIndex = points.count - 1
                middleIndex = 0
                upperIndex = 1;

            }else{
                lowerIndex = i
                middleIndex = i + 1
                upperIndex = i + 2
            }
            p1 = points[lowerIndex]
            p2 = points[middleIndex]
            p3 = points[upperIndex]
            area +=  degreesToRadians(p2.longitude - p1.longitude) * (2 + sin(degreesToRadians(p1.latitude)) + sin(degreesToRadians(p2.latitude)))

        }
        area = area * kEarthRadius * kEarthRadius / 2

    }
    return area
    measureLabel.text = "\(area)"
}

I have followed this link specifically MKPolygon area calculation

Community
  • 1
  • 1
  • What is `polygonArea()` currently returning? – ndmeiri Dec 11 '15 at 00:52
  • Also, the line after `return area` will never be executed. You should move it above the return statement. – ndmeiri Dec 11 '15 at 00:52
  • What do you mean what is it returning? Like the value? and I will take away that last line. I know the number is off. right now it returns 382838.399394838 for example. Thanks for the reply as well! – Bosco Mitchell Dec 12 '15 at 01:03
  • Yes, the value. And what value are you expecting? You're welcome! – ndmeiri Dec 12 '15 at 16:44
  • 1439064387.63392 is what I get on an actual area of 13816 meters and also I see that var p3 is not being used but I didnt see it in the calculation in the link i mentioned either. – Bosco Mitchell Dec 12 '15 at 20:09
  • Hi pal... Have you figured out a solution for this? I'm stuck at this as well... Thanks – Cleversou Jul 31 '16 at 01:26
  • Yes I believe I marked the answer. Thank to everyone for their time and help. It is much appreciated! – Bosco Mitchell Aug 02 '16 at 15:35

3 Answers3

1

Here's the Objective-C version. You can use it in your code with no problems.

polygon on a sphere area 1 polygon on a sphere area 2

#define kEarthRadius 6378137
@implementation MKPolygon (AreaCalculation)

- (double) area {
  double area = 0;
  NSMutableArray *coords = [[self coordinates] mutableCopy];
  [coords addObject:[coords firstObject]];

  if (coords.count > 2) {
    CLLocationCoordinate2D p1, p2;
    for (int i = 0; i < coords.count - 1; i++) {
      p1 = [coords[i] MKCoordinateValue];
      p2 = [coords[i + 1] MKCoordinateValue];
      area += degreesToRadians(p2.longitude - p1.longitude) * (2 + sinf(degreesToRadians(p1.latitude)) + sinf(degreesToRadians(p2.latitude)));
    }

    area = - (area * kEarthRadius * kEarthRadius / 2);
  }
  return area;
}
- (NSArray *)coordinates {
  NSMutableArray *points = [NSMutableArray arrayWithCapacity:self.pointCount];
  for (int i = 0; i < self.pointCount; i++) {
    MKMapPoint *point = &self.points[i];
    [points addObject:[NSValue valueWithMKCoordinate:MKCoordinateForMapPoint(* point)]];
  }
  return points.copy;
}

double degreesToRadians(double radius) {
  return radius * M_PI / 180;
}

EDIT: updated so that the calculation also considers a point on the line as inside the poly.

StefanS
  • 1,089
  • 1
  • 11
  • 38
  • Im going to continue to work on this. It is really close Im going to set some coordinates and match them. I want to make sure before I mark this as the answer. Thanks alot! – Bosco Mitchell Apr 01 '16 at 15:11
  • Im off by 124-125 meters. Any Ideas as to why. Im trying to compare and put a few formulas together that I had previously – Bosco Mitchell Apr 02 '16 at 19:56
  • Because the constant - radius of the Earth is not constant. The Earth is not a perfect sphere. I think that area 125 meters roughly 15x15 meters is negligible. – StefanS Apr 03 '16 at 17:24
0

I was trying to solve the same issue, except using UTM as opposed to long/lat. After much searching I kept finding the same code that you have above, which just didn't work for me.

However, what I did find was a simple C function which when converted to Swift seemed to work pretty well. My calculations were only off by about 4 meters for a calculation of ~1600 meters which is probably down to the earths curve.

class func polygonArea(points: Array<GAPaddockPoint>) -> Double {

    var area:Double = 0.0
    var j = points.count - 1
    for var i=0; i<points.count; i++ {
        area = area + ( (points[j].easting + points[i].easting) * (points[j].northing - points[i].northing) )
        j=i
    }

    return area * 0.5
}
AndyDunn
  • 1,074
  • 1
  • 12
  • 19
  • Im going to check it out and see how it works. I appreciate your time and response. Ill let you know soon!! – Bosco Mitchell Feb 16 '16 at 18:41
  • This did not work but Im trying to understand what the difference would be in points. I had one caculation down to where it was fairly close but nothing in stone. – Bosco Mitchell Feb 19 '16 at 14:14
0

Swift version was posted by @AVT in MKPolygon area calculation:

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.
}
Community
  • 1
  • 1
Shmidt
  • 16,436
  • 18
  • 88
  • 136