0

I have a triangle polygon on a MKMapView that I would like to redraw very quickly or to anchor in a specific position on the phone.

This polygon will always point to the top of the phone but the map itself will spin to supplied headings. Currently the only way I have come up with is to remove the overlay and then re-add it. The problem with this is that it is very choppy.

The next idea I had was to just add a triangle image over the map and resize the map as needed this triangle image be an accurate visualization of what the polygon would be when added as a map overlay. This almost works but it isn't very accurate. For some reason it almost never responds to changes in the latitude zoom level and some other issues.

My method for this is:

- (void)setMapVisibleRect {
    //we have to mock the heading to 0 so that the distances show up in lat/long correctly
    //create a new instance of the cone model with a fake heading of 0 for calculations
    ConePolygonModel *conePolygonModel = [[ConePolygonModel alloc] init:[self.userLocationModel getLocation].coordinate
                                                            withHeading:0
                                                  withLatLongMultiplier:[self.conePolygonModel getLatLongMultiplier]
                                                 withDistanceMultiplier:[self.conePolygonModel getDistanceMultiplier]];
    //reset the map heading to 0
    [self.mapView.camera setHeading:0];

    //top left setup
    CLLocationCoordinate2D topLeftCoordinate;
    topLeftCoordinate.latitude = [[[conePolygonModel getXCoordinates] objectAtIndex:1] doubleValue];
    topLeftCoordinate.longitude = [[[conePolygonModel getYCoordinates] objectAtIndex:1] doubleValue];

    CLLocation *topLeftLocation = [[CLLocation alloc] initWithLatitude:topLeftCoordinate.latitude longitude:topLeftCoordinate.longitude];

    //top right setup
    CLLocationCoordinate2D topRightCoordinate;
    topRightCoordinate.latitude = [[[conePolygonModel getXCoordinates] objectAtIndex:2] doubleValue];
    topRightCoordinate.longitude = [[[conePolygonModel getYCoordinates] objectAtIndex:2] doubleValue];

    CLLocation *topRightLocation = [[CLLocation alloc] initWithLatitude:topRightCoordinate.latitude longitude:topRightCoordinate.longitude];

    //center setup
    CLLocationCoordinate2D topCenterCoordinate = [conePolygonModel midpointBetweenCoordinate:topLeftCoordinate andCoordinate:topRightCoordinate];

    CLLocation *topCenterLocation = [[CLLocation alloc] initWithLatitude:topCenterCoordinate.latitude longitude:topCenterCoordinate.longitude];

    //set distances
    CLLocationDistance latitudeDistance = [topLeftLocation distanceFromLocation:topRightLocation];
    CLLocationDistance longitudeDistance = [topCenterLocation distanceFromLocation:[self.userLocationModel getLocation]];

    //set the map zoom
    NSLog(@"zoom levels: %f %f", latitudeDistance, longitudeDistance);
    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance([self.userLocationModel getLocation].coordinate, latitudeDistance, longitudeDistance);
    [self.mapView setRegion:viewRegion];

    //move the map to the actual heading
    [self.mapView.camera setHeading:self.currentHeading];
}

Is there a way to keep an overlay always pointing to the top of the screen regardless of the map rotation? The zooming of the map so that the overlay would always take up the same size on the screen would also be nice but it is not as important as the other point.

shiznatix
  • 1,087
  • 1
  • 20
  • 37
  • So, to double check, you want your triangle to always have the same physical size on the user's screen, and the same rotation, regardless of how the user manipulates the map? – Mike Mertsock Feb 02 '14 at 14:18

1 Answers1

0

Try implementing this as an MKAnnotationView instead of an overlay, since you want the triangle to always have the same size and orientation, but still be attached to a specific point in the map's coordinate system.

The simplest way to do this would be to create a PNG file and assign a UIImage of it to the image property of an MKAnnotationView in your mapView:viewForAnnotation: delegate method. Alternatively, you could use Core Graphics to programmatically draw the triangle and turn it into a UIImage, at runtime. You can render the image using Core Graphics once and keep a reference to the UIImage object so you aren't redrawing it every time viewForAnnotation is called.

Mike Mertsock
  • 11,825
  • 7
  • 42
  • 75