Search code examples
iosmapscartodbnutiteqcarto-mobile

Fit map to objects in Carto mobile SDK


I have an array of NTVectorElements, how do I set the map bounds so that it fits every element to the screen? I see the moveToFitBounds function but I’m not sure how to implement it. Do you have an example?


Solution

  • I've dealt with this issue before. Figuring it out was not a trivial task, but I can provide an example snippet that solves this issue.

    You need to provide screen bounds as well as map bounds, meaning the the minimum and maximum position required to draw a bounding box.

    NTVectorElements there is no method to get object bounds immediately, you'd need to go through all of the elements in the array to find global max and min of their geometries

    Here's a snippet to fit the map to currently loaded sites, you should only require few modifications to it to fit your use case:

    -(void)fitMapToCurrentlyLoadedSites {
        int siteCount = (int)[_sitesOrderArray count];
        if (siteCount > 0) {
            if (siteCount == 1) {
                //zoom in on single site
                GenericMapMarker *siteMarker = [_sitesOrderArray objectAtIndex:0];
                NTMapPos *sitePosition = [CommonFunctions getMapPosFromCoordinate:_ntMapView coordinate:siteMarker.coordinate];
                [_ntMapView setFocusPos:sitePosition durationSeconds:0];
                [_ntMapView setZoom:15.0 durationSeconds:0];
            } else {
                //create vector of multiple sites
                NTMapPosVector* posVector = [[NTMapPosVector alloc] init];
                for (int i = 0; i < siteCount; i++) {
                    GenericMapMarker *siteMarker = [_sitesOrderArray objectAtIndex:i];
                    //get mapPos from coordinate
                    NTMapPos *mapPos = [CommonFunctions getMapPosFromCoordinate:_ntMapView coordinate:siteMarker.coordinate];
                    [posVector add:mapPos];
                }
                //create envelope of vectors
                NTMapEnvelope *envelope = [[NTMapEnvelope alloc] initWithConvexHull:posVector];
                //get mapBounds of envelope
                NTMapBounds *bounds = [envelope getBounds];
    
                [_ntMapView moveToFitBounds:bounds screenBounds:[self findScreenBounds] integerZoom:TRUE durationSeconds:1.0f];
            }
        }
    }
    

    And to find screen bounds:

    -(NTScreenBounds *)findScreenBounds {
        float screenWidth = self.view.frame.size.width;
        float screenHeight = self.view.frame.size.height;
        NTScreenPos *minScreenPos = [[NTScreenPos alloc] initWithX:0.0 y:0.0];
        NTScreenPos *maxScreenPos = [[NTScreenPos alloc] initWithX:screenWidth y:screenHeight];
        return [[NTScreenBounds alloc] initWithMin:minScreenPos max:maxScreenPos];
    }