Search code examples
iosswiftgeocodingmbtilescarto-mobile

Offline geocoding using MBTiles with vector tiles


I load an MBTiles Vector Tile data source of my country, using carto-mobile SDK

    // Initialize base layer with a bundled styles
    let baseLayer = NTCartoOnlineVectorTileLayer(style: NTCartoBaseMapStyle.CARTO_BASEMAP_STYLE_GRAY)

    // Use the style for your own vector tile datasource (online, offline etc),
    let tileDataSource = NTMBTilesTileDataSource(path: Bundle.main.path(forResource: "estonia_ntvt", ofType: "mbtiles"))

    // Initialize offline layer & Grab vector tile layer from our base layer
    let offlineLayer = NTVectorTileLayer(tileDataSource, baseLayer?.getTileDecoder())

    mapView?.layers?.add(baseLayer)
    mapView?.layers?.add(offlineLayer)

and is showing everything ok, so i have my map and all the features.

So now i want to search, for a POI or a street name.

I know that an MBTiles have all the information inside him, but how can i access to that info??

Is this posible?? if it is possible, how i do that??


Solution

  • The latest version (4.1.0) of CARTO mobile SDK has NTVectorTileSearchService using mbtiles. There is no user doc for it yet, but sample code can be found from AdvancedMap.Swift.

    // init search service with your mbtiles 
    searchService = NTVectorTileSearchService(dataSource: baseSource, tileDecoder: baseLayer.getTileDecoder())
    
    // prepare search request, set some conditions. 
    // This search is to find attractions within 500m from a route geometry
    
    let request = NTSearchRequest()
    request?.setProjection(contentView.baseSource.getProjection())
    request?.setGeometry(geometry)
    request?.setSearchRadius(500.0)
    request?.setFilterExpression("class='attraction'")
    
    // actual search
    let results = contentView.searchService.findFeatures(request)
    let count = Int((results?.getFeatureCount())!)
    
    // go through found items
    for i in 0..<count {
            let item = results?.getFeature(Int32(i))!
    
            if (item?.getGeometry() is NTPointGeometry) {
                contentView.addPOI(feature: item!)
            }
    }
    

    Note that this Search service is more usable for POI or street geometry search. Also be aware that same street is often duplicated in different tiles, and big polygons are often partial in tiling.

    By geocoding we mean a bit different things - search for human-readable addresses or search for address given a location (reverse-geocode). MBTiles/Vector tiles does not have full data for this, it optimized for visual look. For example building or address points may have house number tag, but almost never have streets or city and country data in them, as it would be redundant and not needed for visual maps. Now for literal geocoding CARTO SDK has solution also: NTGeocodingService. You can use this online or offline, just for the offline case SDK has to download special different data packages per country (or city if you want). These data packages have full hierarchical address data, so real geocoding would work with them. So for complete offline data you would need to get two offline packages separately: mbtiles for maps and geocoding database. If you want offline routing also, then third dataset, as this also cannot be done properly from mbtiles/vector tiles alone.

    This is very new feature, so you need to use pre-release version of SDK, but your feedback is very welcome.