3

I figured I would ask this before doing it the hard way. I've Googled and StackOverflowed around and can't find anything. MapKit is good at drawing region shapes on an MKMapView, and CoreLocation is good at telling you straight distance from CLLocation to CLLocation, but neither is exactly what I need.

I basically want to be able to drop a point on a map with a 10 meter radius, and know if there's anything already there (which would also have a 10m radius) and would intersect the area of the second dropped thing. I want to be able to get a total area of all of these points in square meters, which is easy, but with correction for overlapping circles.

Thanks for your help SO.

Eric G
  • 1,429
  • 18
  • 26

2 Answers2

2

I wrote this function that takes center x, y and radius for two circles and return the intersection area.

public func circlesIntesectionArea(x1 x1: Double, y1: Double, r1: Double, x2: Double, y2: Double, r2: Double) -> Double {

    let d: Double = sqrt( pow(x1 - x2, 2) + pow(y1 - y2, 2) ) // distance between circles center

    let dd: Double = pow(d, 2)
    let rr1: Double = pow(r1, 2)
    let rr2: Double = pow(r2, 2)

    if d > r2 + r1 { return 0.0 } // no overlap
    if d <= abs(r1 - r2) {
        if r1 >= r2 { return M_PI * rr2 } //Circle2 inside circle1
        else { return M_PI * rr1 } //Circle1 inside circle2
    } else {
        let phi: Double = acos((dd + rr1 - rr2) / (2 * r1 * d)) * 2; // circle1 sector angle
        let area1: Double = (phi * rr1)/2 - (rr1 * sin(phi))/2; // sector1 area - triangle1 area

        let theta: Double = acos((dd + rr2 - rr1) / (2 * r2 * d)) * 2; // circle2 sector center angle
        let area2: Double = (theta * rr2)/2 - (rr2 * sin(theta))/2; // sector2 area - triangle2 area

        let intersectionArea: Double = area1 + area2;
        return isnan(intersectionArea) ? 0.0 : intersectionArea; //isnan == no overlap
    }
}

Radius can't be in meters or miles here, so, if you have a circularRegion you have to convert it to MKCoordinateRegion:

let region1 = MKCoordinateRegionMakeWithDistance(circularRegion.center, circularRegion.radius, circularRegion.radius)

Then:

if circlesIntesectionArea(x1: region1.center.longitude, y1: region1.center.latitude, r1: region1.span.latitudeDelta,
                          x2: region2.center.longitude, y2: region2.center.latitude, r2: region2.span.latitudeDelta) == 0.0 {
    print("No overlapping")
} else {
    print("Overlapping")
}

I know this is an old question but may be someone will find this useful anyway...

Marco M
  • 1,215
  • 12
  • 12
2

There are a couple resources you will want to look at.

First, Mapkit has some helper functions for working with MKMapRect structures. They will help you convert between regions and MKMapRects and so forth. See them here: http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MapKitFunctionsReference/Reference/reference.html%23//apple_ref/doc/uid/TP40008209

Second, to do the geometry calculations you want to do (radius, area, etc...) you probably want this: http://trac.osgeo.org/geos/

It's hard to get compiled for iOS, but it can be done. A good place to look at getting it compiled would be with the spatialite project. Spatialite depends on geos and people have compiled spatialite for iOS. See here: how to compile spatialite for iOS

[Edit] Actually, after reading your question once more, you might just want to use Spatialite and not worry about geos alone. You will have to store your data in a database on the device. Doing so will allow you to construct SQL like queries that will answer the questions you are asking.

Community
  • 1
  • 1
Aaron
  • 2,403
  • 1
  • 24
  • 25
  • I actually ended up sidestepping the issue, but thanks for your reply. I'll keep those resources in mind for future projects. – Eric G May 19 '11 at 08:49