Determine whether a CLLocationCoordinate2D is within a defined region (bounds)?

丶灬走出姿态 提交于 2019-12-08 06:11:32

问题


I am trying to find a simple method to determine whether a CLLocationCoordinate2D lies within the boundaries of an arbitrary shape defined by a series of other CLLocationCoordinate2D's. The shapes may be large enough that great-circle paths need to be considered.

CL used to have a circular region and the containsCoordinate: call to test against, but this has been deprecated in iOS7 and the dox do not contain a hint of what might replace it. I cannot find any other examples, notably one that works on polygons.

There are many similar questions here on SO, but they are not related to iOS specifically, and again, I can't seem to find one that works generally on great-circle polys.


回答1:


Here's an example (using Algonquin Provincial Park) of an approach that may work for you.

To use CGPathContainsPoint for this purpose, an MKMapView is not required.

Nor is it necessary to create an MKPolygon or even to use the CLLocationCoordinate2D or MKMapPoint structs. They just make the code easier to understand.

The screenshot below was created from the data only for illustration purposes.

int numberOfCoordinates = 10;

//This example draws a crude polygon with 10 coordinates
//around Algonquin Provincial Park.  Use as many coordinates
//as you like to achieve the accuracy you require.
CLLocationCoordinate2D algonquinParkCoordinates[numberOfCoordinates];
algonquinParkCoordinates[0] = CLLocationCoordinate2DMake(46.105,    -79.4);
algonquinParkCoordinates[1] = CLLocationCoordinate2DMake(46.15487,  -78.80759);
algonquinParkCoordinates[2] = CLLocationCoordinate2DMake(46.16629,  -78.12095);
algonquinParkCoordinates[3] = CLLocationCoordinate2DMake(46.11964,  -77.70896);
algonquinParkCoordinates[4] = CLLocationCoordinate2DMake(45.74140,  -77.45627);
algonquinParkCoordinates[5] = CLLocationCoordinate2DMake(45.52630,  -78.22532);
algonquinParkCoordinates[6] = CLLocationCoordinate2DMake(45.18662,  -78.06601);
algonquinParkCoordinates[7] = CLLocationCoordinate2DMake(45.11689,  -78.29123);
algonquinParkCoordinates[8] = CLLocationCoordinate2DMake(45.42230,  -78.69773);
algonquinParkCoordinates[9] = CLLocationCoordinate2DMake(45.35672,  -78.90647);

//Create CGPath from the above coordinates...
CGMutablePathRef mpr = CGPathCreateMutable();

for (int p=0; p < numberOfCoordinates; p++)
{
    CLLocationCoordinate2D c = algonquinParkCoordinates[p];

    if (p == 0)
        CGPathMoveToPoint(mpr, NULL, c.longitude, c.latitude);
    else
        CGPathAddLineToPoint(mpr, NULL, c.longitude, c.latitude);
}

//set up some test coordinates and test them...
int numberOfTests = 7;
CLLocationCoordinate2D testCoordinates[numberOfTests];
testCoordinates[0] = CLLocationCoordinate2DMake(45.5, -78.5);
testCoordinates[1] = CLLocationCoordinate2DMake(45.3, -79.1);
testCoordinates[2] = CLLocationCoordinate2DMake(45.1, -77.9);
testCoordinates[3] = CLLocationCoordinate2DMake(47.3, -79.6);
testCoordinates[4] = CLLocationCoordinate2DMake(45.5, -78.7);
testCoordinates[5] = CLLocationCoordinate2DMake(46.8, -78.4);
testCoordinates[6] = CLLocationCoordinate2DMake(46.1, -78.2);

for (int t=0; t < numberOfTests; t++)
{
    CGPoint testCGPoint = CGPointMake(testCoordinates[t].longitude, testCoordinates[t].latitude);

    BOOL tcInPolygon = CGPathContainsPoint(mpr, NULL, testCGPoint, FALSE);

    NSLog(@"tc[%d] (%f,%f) in polygon = %@",
          t,
          testCoordinates[t].latitude,
          testCoordinates[t].longitude,
          (tcInPolygon ? @"Yes" : @"No"));
}

CGPathRelease(mpr);

Here are the results of the above test:

tc[0] (45.500000,-78.500000) in polygon = Yes
tc[1] (45.300000,-79.100000) in polygon = No
tc[2] (45.100000,-77.900000) in polygon = No
tc[3] (47.300000,-79.600000) in polygon = No
tc[4] (45.500000,-78.700000) in polygon = Yes
tc[5] (46.800000,-78.400000) in polygon = No
tc[6] (46.100000,-78.200000) in polygon = Yes


This screenshot is to illustrate the data only (actual MKMapView is not required to run the code above):




回答2:


Anna's solution converted to Swift 3.0:

extension CLLocationCoordinate2D {

    func contained(by vertices: [CLLocationCoordinate2D]) -> Bool {
        let path = CGMutablePath()

        for vertex in vertices {
            if path.isEmpty {
                path.move(to: CGPoint(x: vertex.longitude, y: vertex.latitude))
            } else {
                path.addLine(to: CGPoint(x: vertex.longitude, y: vertex.latitude))
            }
        }

        let point = CGPoint(x: self.longitude, y: self.latitude)
        return path.contains(point)
    }
}


来源:https://stackoverflow.com/questions/25835985/determine-whether-a-cllocationcoordinate2d-is-within-a-defined-region-bounds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!