1

I need some help combining zipcode or current location values with an responding action for an custom area. Thought it was called a Polygon Class. Correct me if I am wrong.

For example: I have these following locations. If the users input falls in the following locations. There must be an action.

(52.38434879837112, 4.882092475891113)(52.38036714957116, 4.888787269592285)(52.37964674712061, 4.890203475952148)(52.37891323436772, 4.893829822540283)(52.38018377551705, 4.895482063293457)(52.38163764888611, 4.891576766967773)(52.38241040893942, 4.889967441558838)(52.38284262476619, 4.890375137329102)(52.384977446937405, 4.890353679656982)(52.38694191601119, 4.890375137329102)(52.38828425293476, 4.890316128730774)(52.38823841771291, 4.889897704124451)(52.388035432586925, 4.886292815208435)(52.38811400758514, 4.885584712028503)(52.38819585639288, 4.884763956069946)(52.3877014872842, 4.884393811225891)(52.386264184057815, 4.88343358039856)(52.386120123751006, 4.883519411087036)(52.38551768464715, 4.883063435554504)(52.38496107599452, 4.882376790046692)(52.3845125097973, 4.882033467292786)

Wat are the possibilities for this in xcode? Or do I need the do this in other coding languages? Might be useful to do this in HTML and implement this in the UIWebView?

Update 1:

I've got the Polygon Map working. Only thing is, I don't know how to make a proper annotation and let it check the Polygon area. I get a samantic issue with MKMapPoint *mapPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(52.366243, 4.891097)); which says it's a incompatible type of 'MKMapPoint'.

What I do wrong?

This is btw, 1 of the polygons in the map. How does the CGPathContainsPoint code check multiple polygons?

    CLLocationCoordinate2D roodPoly2[8];

    roodPoly2[0] = CLLocationCoordinate2DMake(52.36715572007325, 4.889763593673706);
    roodPoly2[1] = CLLocationCoordinate2DMake(52.367037801571975, 4.889838695526123);
    roodPoly2[2] = CLLocationCoordinate2DMake(52.36681506576634, 4.891244173049927);
    roodPoly2[3] = CLLocationCoordinate2DMake(52.3667561061004, 4.893143177032471);
    roodPoly2[4] = CLLocationCoordinate2DMake(52.365314845350156, 4.892692565917969);
    roodPoly2[5] = CLLocationCoordinate2DMake(52.36555724249258, 4.890578985214233);
    roodPoly2[6] = CLLocationCoordinate2DMake(52.366729901779145, 4.888583421707153);
    roodPoly2[7] = CLLocationCoordinate2DMake(52.36707710777403, 4.889581203460693);

    MKPolygon *roodpoly2 = [MKPolygon polygonWithCoordinates:roodPoly2 count:8];
    roodpoly2.title = @"Dinsdag & Vrijdag";
    [myMapView addOverlay:roodpoly2];

    MKMapPoint *mapPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(52.366243, 4.891097));

    CGMutablePathRef mpr = CGPathCreateMutable();

    MKMapPoint *polygonPoints = roodpoly2.points;
    //myPolygon is the MKPolygon

    for (int p=0; p < roodpoly2.pointCount; p++)
    {
        MKMapPoint mp = polygonPoints[p];
        if (p == 0)
            CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
        else
            CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
    }

    CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
    //mapPoint above is the MKMapPoint of the coordinate we are testing.
    //Putting it in a CGPoint because that's what CGPathContainsPoint wants.

    BOOL pointIsInPolygon = CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE);

    CGPathRelease(mpr);

}

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
    if ([overlay isKindOfClass:[MKPolygon class]])
    {
        MKPolygonView* aView = [[MKPolygonView alloc] initWithPolygon:       (MKPolygon*)overlay];

        aView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.2];
        aView.strokeColor = [[UIColor greenColor] colorWithAlphaComponent:0.7];
        aView.lineWidth = 3;

        return aView;
    }
    return nil;
}
SwingerDinger
  • 276
  • 1
  • 7
  • 21
  • Do you want to know if the user comes near each of these _individual_ coordinates or enters the region defined by _all_ these coordinates? –  Mar 31 '14 at 14:54
  • Enters the region defined by all these coordinates. – SwingerDinger Mar 31 '14 at 15:21
  • You can create an MKPolygon from these coordinates and then (for example when user location changes) test whether a coordinate is inside that MKPolygon using CGPathContainsPoint. See http://stackoverflow.com/questions/19014926/detecting-a-point-in-a-mkpolygon-broke-with-ios7-cgpathcontainspoint for an example with using CGPathContainsPoint. Technically, to implement that approach, all you need is a list of coordinates or MKMapPoints (the MKPolygon is not required unless you want to display it on the map). –  Mar 31 '14 at 15:35
  • Thanks for the Info Anna, I'm just a beginner at this. What is a good way to set up the coordinates with the MKMapPoint? I now got it like this: `points[0] = MKMapPointForCoordinate(CLLocationCoordinate2DMake(52.38434879837112, 4.882092475891113));`? – SwingerDinger Apr 01 '14 at 11:48
  • That's fine but actually all you'll need in the end is the CGPath (see linked answer) so you can call CGPathContainsPoint. Where the list of points comes from to create the path is not important (could be MKPolygon, C array like your example, NSArray, etc). Try it out and if any problems, update your question with the code. –  Apr 02 '14 at 02:18
  • Anna, I changed my application approach. I do want a Polygon to be visible on a map. So I made a working Polygon Map, but now I'm testing your code of the `CGPathContainsPoint` and I'm doing something wrong. See the updated question. – SwingerDinger Apr 02 '14 at 13:03

2 Answers2

2

First, the compiler error "incompatible type MKMapPoint" on this line:

MKMapPoint *mapPoint = MKMapPointForCoordinate(...);

is because MKMapPointForCoordinate returns a plain MKMapPoint struct but you've declared mapPoint as a pointer to an MKMapPoint struct so it's "incompatible".

Don't declare mapPoint as a pointer (remove the asterisk). So change that line to:

MKMapPoint mapPoint = MKMapPointForCoordinate(...);



Next, your other question was "How does the CGPathContainsPoint code check multiple polygons?"

One way is to store all the CGMutablePathRef paths for all the polygons in a C array just like you're storing the individual polygon coordinates in a C array.

Then, you can loop through the paths array and call CGPathContainsPoint with each one.


Following is an example to test multiple polygon overlays that have been added to the map. This example assumes you've already added MKPolygon overlays to the map using addOverlay or addOverlays.

Wherever you want to test whether some coordinate is in any of the polygons added to the map, put this:

CLLocationCoordinate2D coordinateToTest = 
    CLLocationCoordinate2DMake(52.366243, 4.891097);

MKMapPoint mapPointToTest = MKMapPointForCoordinate(coordinateToTest);

//Loop through MKPolygon overlays...
for (id<MKOverlay> overlay in myMapView.overlays)
{
    if ([overlay isKindOfClass:[MKPolygon class]])
    {
        MKPolygon *polygon = (MKPolygon *)overlay;


        CGMutablePathRef mpr = CGPathCreateMutable();

        MKMapPoint *polygonPoints = polygon.points;

        for (int p=0; p < polygon.pointCount; p++)
        {
            MKMapPoint mp = polygonPoints[p];
            if (p == 0)
                CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
            else
                CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
        }

        CGPoint mapPointAsCGP = CGPointMake(mapPointToTest.x, mapPointToTest.y);

        BOOL pointIsInPolygon = CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE);
        NSLog(@"Coordinate %f,%f is in polygon %@: %@",
              coordinateToTest.latitude, coordinateToTest.longitude,
              polygon.title,
              (pointIsInPolygon ? @"Yes" : @"No"));

        CGPathRelease(mpr);
    }
}
  • Thanks Anna, I see when the location hits the polygon I get an output of 1, true right? Last question if I may. What is the best way to get multiple colors for the different Polygon. I now got the `if ([overlay isKindOfClass:[MKPolygon class]])` statement. Many thanks Anna! – SwingerDinger Apr 03 '14 at 08:36
  • Yes, 1 means true but it's better to work with BOOL variables using YES and NO instead of assuming a specific internal representation (`if (someBooleanVariable == YES) {...}` or just `if (someBooleanVariable) {...}`). I suggest reading an intro to the C language and then an intro to Objective-C. –  Apr 03 '14 at 10:50
  • 1
    For different colored polygon overlays, see this answer: http://stackoverflow.com/questions/7464098/different-coloured-polygon-overlays –  Apr 03 '14 at 10:53
  • Still do have a question Anna. Not sure how I do multiple Polygons to the `CGPathContainsPoint`. Do I have to store the different Polygons in an `MutableArray`? And what do I have to change in the CGPathContainsPoint code? Cuz in this code: `MKMapPoint *polygonPoints = roodpoly2.points;` I want not only roodpoly2 but al the 10 other Polygons to be checked. – SwingerDinger Apr 09 '14 at 20:30
  • I've added an example based on the assumption that you're adding the MKPolygon overlays to the map. –  Apr 10 '14 at 02:52
  • Anna, since your an expert an the Mapkit, I still have 1.5 question. Fist: I don't want the `CGPathContainsPoint ` code to start in the `ViewDidLoad`, but when I hit the return button on the keyboard, or when I click my user location button (see next question). Is there a specific method for the `CGPathContainsPoint `. Second: I need to check if the user location is in one of the Polygons. Is there an way for this, can't find it on the web. – SwingerDinger Apr 15 '14 at 11:50
  • @DaxRahusen, please start a new question. –  Apr 15 '14 at 11:54
0

What system framework are you talking about? MKMapView maybe? Dig into the CLLocationCoordinate and how to compare them:

memcmp(&first_cllc2d, &second_cllc2d, sizeof(CLLocationCoordinate2D)) 

(fabs(first_cllc2d.latitude - second_cllc2d.latitude) <= epsilon && 
 fabs(first_cllc2d.longitude - second_cllc2d.longitude) <= epsilon)
Sergey Grischyov
  • 11,995
  • 20
  • 81
  • 120
  • Yes, the MKMapView. I don't want to see the actual polygon, only the the message if the location is detected within the points. – SwingerDinger Apr 01 '14 at 11:39