ConfusedByCode
ConfusedByCode

Reputation: 1730

How to check if CLCircularRegions intersect

I'm developing an iOS app (with Swift) that keeps a log of a user's location history. As part of a search algorithm, I'd like to check if two CLCircularRegions intersect, but I can't seem to find a Core Location method or function to do it. CLCircularRegion has the containsCoordinate method, but that's not exactly what I need. I also know that Map Kit includes functions to check for intersecting MKMapRects, but since I'm not actually working with maps, those solutions don't seem ideal.

I hope I'm missing something obvious, but I can't seem to figure it out. How can I check if two CLCircularRegions intersect?

Upvotes: 2

Views: 533

Answers (2)

heyfrank
heyfrank

Reputation: 5647

Swift 4.2 version of The Paramagnetic Croissant's answer

extension CLCircularRegion {
    func intersects(_ r2: CLCircularRegion) -> Bool {
        let r1 = self
        let meanEarthRad: Double = 6371009
        let metersPerDegree = 2 * Double.pi * meanEarthRad / 360

        let dLat = r2.center.latitude - r1.center.latitude
        let dLon = r2.center.longitude - r1.center.longitude

        let actCenterDist = hypot(dLat, dLon) * metersPerDegree
        let minCenterDist = r1.radius + r2.radius

        return actCenterDist < minCenterDist
    }
}

Upvotes: 1

If you don't mind small inaccuracies, you can assume that the regions are small enough that the curvature of the Earth is negligible therefore the regions can be treated as planes.

In this case, just check whether the distance of the two center points is smaller than the sum of the radii. Two circles intersect if and only if their centers are closer than the sum of their radii.

CLCircularRegion r1, r2;

const double meanEarthRad = 6371009;
const double metersPerDegree = 2 * M_PI * meanEarthRad / 360;

double dLat = r2.center.latitude - r1.center.latitude;
double dLon = r2.center.longitude - r1.center.longitude;

double actCenterDist = hypot(dLat, dLon) * metersPerDegree;
double minCenterDist = r1.radius + r2.radius;

if (actCenterDist < minCenterDist) {
    // the regions intersect
}

Upvotes: 4

Related Questions