Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GMSTileURLConstructor Returns Strange Data for Zoom

I am trying to draw a custom overlay on Google Maps for iOS using GMSTileURLConstructor.

I am using the following code to get my URL

GMSTileURLConstructor urls = ^(NSUInteger x, NSUInteger y, NSUInteger zoom) {
        NSString *url = @"";

        for (NSDictionary *limits in [selectedPropertyMap objectForKey:@"property_map_zoom_levels"]) {
            int zoomLevel = [[limits objectForKey:@"level"] intValue];
            int tileMinX = 0;
            int tileMaxX = 0;
            int tileMinY = 0;
            int tileMaxY = 0;

            if ([limits objectForKey:@"tile_min_x"] != (id)[NSNull null]) {
                tileMinX = [[limits objectForKey:@"tile_min_x"] intValue];
            }
            if ([limits objectForKey:@"tile_max_x"] != (id)[NSNull null]) {
                tileMaxX = [[limits objectForKey:@"tile_max_x"] intValue];
            }
            if ([limits objectForKey:@"tile_min_y"] != (id)[NSNull null]) {
                tileMinY = [[limits objectForKey:@"tile_min_y"] intValue];
            }
            if ([limits objectForKey:@"tile_max_y"] != (id)[NSNull null]) {
                tileMaxY = [[limits objectForKey:@"tile_max_y"] intValue];
            }

            if (zoomLevel == (unsigned long)zoom) {
                if ((tileMinX <= x) && (tileMaxX >= x) && (tileMinY <= y) && (tileMaxY >= y)) {
                    url = [NSString stringWithFormat:@"%@%@/%@/%@/%lu_%lu.png", MAP_URL, [property objectForKey:@"id"], [limits objectForKey:@"property_map_id"], [limits objectForKey:@"id"], (unsigned long)x, (unsigned long)y];
                    NSLog(@"url -> %@/zoom %lu/%i",url, (unsigned long)zoom, zoomLevel);
                    return [NSURL URLWithString:url];
                }
            }
        }
        return [NSURL URLWithString:url];
    };

When I log out the URL, zoom and zoomLevel I get the following information:

2014-05-16 17:25:15.621 Application[24491:61003] url -> <BASEURL>/16/9/19/159786_195303.png/zoom 19/19

At the same time, I am logging the camera zoom when the camera changes

- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
    zoomLevelLabel.text = [NSString stringWithFormat:@"ZL: %.2f",position.zoom];
    NSLog(@"camera changed - zoom %f",position.zoom);
    [self hideMarkersBasedOnZoom:position.zoom];
    if(position.zoom > 21) {
        GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:position.target.latitude longitude:position.target.longitude zoom:21];
        [mapView_ setCamera:camera];
    }
}

Which logs

2014-05-16 17:25:15.640 Application[24491:60b] camera changed - zoom 18.022364

Can anyone explain the discrepancy in zoom level value and how to have it match appropriately?

like image 770
WhoaItsAFactorial Avatar asked May 16 '14 21:05

WhoaItsAFactorial


Video Answer


1 Answers

After I did some research, I believe the way Google handles the zoom level for GMSTileLayer is not the same with zoom level for the camera of mapView.

GMSTileLayer Class Reference

https://developers.google.com/maps/documentation/ios/reference/interface_g_m_s_tile_layer

At zoom level 0 the whole world is a square covered by a single tile, and the coordinates x and y are both 0 for that tile. At zoom level 1, the world is covered by 4 tiles with x and y being 0 or 1, and so on.

For the mapView Camera

https://developers.google.com/maps/documentation/ios/views#zoom

The zoom level of the camera determines the scale of the map. At larger zoom levels more detail can be seen on the screen, while at smaller zoom levels more of the world can be seen on the screen. At zoom level 0, the scale of the map is such that the entire world has a width of approximately 256 points.

Increasing the zoom level by 1 doubles the width of the world on the screen. Hence at zoom level N, the width of the world is approximately 256 * 2N, i.e., at zoom level 2, the whole world is approximately 1024 points wide. Note that the zoom level need not be an integer. The range of zoom levels permitted by the map depends on a number of factors including location, map type and screen size.

The zoom for GMSTileLayer is NSUInteger while the zoom for camera is float. The zoom for GMSTileLayer is used to determine the number of tiles. While the zoom for camera is used to determine the number of points based on the formula 256 * 2N.

I could be wrong but I think both the zoom levels would not be matched up.

Not so related: Google just released iOS Maps SDK V1.8.1 that solved an issue related to GMSTileLayer and also fixed a crash.

like image 155
Ricky Avatar answered Sep 28 '22 06:09

Ricky