Search code examples
iosshapescllocation

Check if CLLocation is in Shape?


Im looking for a way to detect if the user is in The Netherlands or in Belgium. I don't want to call an API or use the users telephone services, so everything needs to be done locally and should be something easy and quick, small check. I have the users location each second and want to check each minute.

Goal: The user is travelling with our app and I want to show a different view when he/she arrived Belgium/Netherlands.

I've found two shape files from http://www.diva-gis.org/datadown with Netherlands and Belgium. These files are quite small and now Im looking for a way to create this method:

- (BOOL)isUserInNetherlands:(CLLocation)location;

which should check the location is it is in the content of the shapefile.

The shapefile for the Netherlands looks something like this:

netherlands shapefile

I can convert the shapefile to a sqlLite database but not idea what to do next.

Any idea's?


Solution

  • One way to do this is:

    1) convert the shapefile to geoJson

    2) load the geoJson file data in your code.

    3) create polygons from these gps points (note: CountryDetectorController is my controller class)

    + (MKPolygon *)overlaysFromPolygons:(NSArray *)polygons title:(NSString *)title;
    {
        NSMutableArray *interiorPolygons = [NSMutableArray arrayWithCapacity:[polygons count] - 1];
        for (int i = 1; i < [polygons count]; i++) {
            [interiorPolygons addObject:[CountryDetectorController polygonFromPoints:polygons[i] interiorPolygons:nil]];
        }
    
        MKPolygon *overlayPolygon = [CountryDetectorController polygonFromPoints:polygons[0] interiorPolygons:interiorPolygons];
        overlayPolygon.title = title;
    
    
        return overlayPolygon;
    }
    
    + (MKPolygon *)polygonFromPoints:(NSArray *)points interiorPolygons:(NSArray *)polygons;
    {
        NSInteger numberOfCoordinates = [points count];
        CLLocationCoordinate2D *polygonPoints = malloc(numberOfCoordinates * sizeof(CLLocationCoordinate2D));
    
        NSInteger index = 0;
        for (NSArray *pointArray in points) {
            polygonPoints[index] = CLLocationCoordinate2DMake([pointArray[1] floatValue], [pointArray[0] floatValue]);
            index++;
        }
    
        MKPolygon *polygon;
    
        if (polygons) {
            polygon = [MKPolygon polygonWithCoordinates:polygonPoints count:numberOfCoordinates interiorPolygons:polygons];
        } else {
            polygon = [MKPolygon polygonWithCoordinates:polygonPoints count:numberOfCoordinates];
        }
        free(polygonPoints);
    
        return polygon;
    }
    

    4) create a CGPath from the polygon

    + (CGPathRef)pathForPolygon:(MKPolygon*)aPolygon;
    {
        CGMutablePathRef mpr = CGPathCreateMutable();
    
        MKMapPoint *polygonPoints = aPolygon.points;
        size_t nCount = aPolygon.pointCount;
    
        for (int p = 0; p < nCount; p++)
        {
            MKMapPoint mp = polygonPoints[p];
    
            if (p == 0)
                CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
            else
                CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
        }
    
        return mpr; //Keep in memory;
    }
    

    5) check if coordinate is in CGPath (pathsBelgium is an array with NSValue of CGPaths)

    - (void)checkCoordinate:(CLLocationCoordinate2D)coordinate;
    {
        MKMapPoint mapPoint = MKMapPointForCoordinate(coordinate);
        CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
    
        BOOL userIsInBelgium = FALSE;
        for(NSValue *valuePathBE in pathsBelgium)
        {
            CGPathRef pathBe;
            [valuePathBE getValue:&pathBe];
    
            BOOL pointInBelgium = CGPathContainsPoint(pathBe, NULL, mapPointAsCGP, FALSE);
            if(pointInBelgium)
            {
                userIsInBelgium = TRUE;
                break;
            }
        }
    
        NSLog(@"User is in Belgium: %i", userIsInBelgium);
    }