Offline geocoding using MBTiles with vector tiles - ios

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??

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.

Related

Get the city and country name with latitude and longitude (iOS)

I use this function:
func getDataCity(tmpLat:Double,tmpLong:Double) {
let tmpCLGeocoder = CLGeocoder.init()
let tmpDataLoc = CLLocation.init(latitude: tmpLat, longitude: tmpLong)
tmpCLGeocoder.reverseGeocodeLocation(tmpDataLoc, completionHandler: {(placemarks,error) in
guard let tmpPlacemarks = placemarks else{
return
}
let placeMark = tmpPlacemarks[0] as CLPlacemark
// Country
guard let countryLocality = placeMark.country else{
return
}
// City
guard let cityLocality = placeMark.locality else{
return
}
print(countryLocality)
print(cityLocality)
})
}
When I use coordinates, for example, from Berlin/Germany
getDataCity(tmpLat: 52.52000659999999, tmpLong: 13.404953999999975)
the function works fine, it shows me the city and country. However I use coordinates from small cities or island, for example Djerba (island in Tunisia)
getDataCity(tmpLat: 33.8075978, tmpLong: 10.845146699999987)
the function doesn't print anything. Is there an explanation from Apple? What can I do about it?
To use the function in your own project, add CLLocationManagerDelegate to ViewController and don't forget to add the Privacy - Location When In Use Usage Description in your Info.plist
Apple's maps do not include a city for that location. Your code does recognize the country, but doesn't recognize a city there (in which case you abort).
If you open Apple Maps, you'll note that no cities are marked on that island, and searching for Houmt Arbah, Tunisia (the closest town) doesn't return a result in Apple Maps (it strangely returns Dahmani, which is a mainland town; I don't know why). It does know about Houmt Souq, but that's quite a ways from the given location.
The short and long of it is that Apple's map database doesn't know a lot about Tunisian geography. If you spend a little time looking around in Google Maps vs Apple Maps, you'll see that there are several parts of Tunisia that Apple Maps knows very little about. For example, if you look at Douz in satellite mode and then switch to map mode, you'll see that Apple's satellite imagery includes an entire village (Al-Qalah) that isn't mapped. And the street map of Douz itself (a town of 38k people), is, to put it bluntly, pathetic.
While Apple's maps have dramatically improved over the years, and in some areas they're now better than Google's maps, in most places Google tends to have far better information. If you need the best maps in arbitrary places, Google's maps are today the gold standard.

Load pdf maps on iOS using ArcGis Api

I exported a layer and features attribute to PDF using ArcGis software. And now, I would like to build an iOS app that I can load this map offline. as I just have started to use ArcGis for iOS, I tried tried this code and I could'n see this map:
override func viewDidLoad() {
super.viewDidLoad()
self.map = AGSMap(basemap: AGSBasemap.topographic())
self.mapView.map = map
let path = Bundle.main.url(forResource: "Map1", withExtension: "pdf")
let localTiledLayer = AGSArcGISTiledLayer(tileCache: AGSTileCache(fileURL: path!))
self.mapView.map = map
map.operationalLayers.add(localTiledLayer)
}
How do I load this pdf file? Thanks.
PDF maps are not supported by the Runtime.
If you want to export feature data, you should use Mobile Map Packages, which can be generated by ArcGIS Pro. They package up a map (or many maps) with data, symbology, popup configuration etc. and can be opened using the AGSMobileMapPackage class.
If you are using ArcMap, then you could export a Runtime Geodatabase and open that using the AGSGeodatabase class, but Mobile Map Packages provide more capabilities in a single file rather than having to create maps and load layers from various sources.
This video gives a good overview of what's possible, and you can read more here.

Cannot apply style to GMSMapView

My code is as below:
/* Map */
mapView = GMSMapView()
mapView.delegate = self
mapView.mapType = .normal
do {
// Set the map style by passing the URL of the local file.
if let styleURL = Bundle.main.url(forResource: "styles", withExtension: "json") {
mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)
} else {
NSLog("Unable to find styles.json")
}
} catch {
NSLog("One or more of the map styles failed to load. \(error)")
}
I am following this tutorial on how to customize my Google map.
Above is my code for implementing the styles.json file. I added the file in my build bundle, and the code never throws an exception regarding not being able to parse my json file. It simply does not apply the style effects onto my map.
Any help would be appreciated. I am slowly dying inside!!!
Leaving an answer for anyone in the future that goes down my path:
Google map styling does not work for maps of South Korea. It even works in North Korea, but not South. South Korea's law prohibits map data from being exported to foreign datacenters.
source:
Yes , Korea does not support some features offered by Google Map due to national law. Google Map Korea can not be export map data for data centers abroad or including the ability to dynamically change the map image. Many South Korea Maps and services are limited to the domestic uses and Google is striving to make this a better service. For more details here's the original answer in Korean: original reply from Google Maps Korea

How to show places like "national parks" using google maps sdk in iOS?

I'm using xcode 6.4, Swift and iOS8. My goal is to show a map using the google maps (and places?) sdk. This map should contain all results google delivers when i search for "national park" on google maps.
What I already did is the following:
Create an API Key for iOS at google (places and maps sdk)
Show the map and the users current position
Now I'm struggling in showing the parks when the user opens the map. I already dived around in googles sdk documentation, and came to the conclusion that I'll need the Places SDK for that. But now I'm a bit lost, all I find are scenarios in which the user either has to choose between different "place types" or the app is calling information for one particular place, knowing its id.
After you have the key and every thing you can get places by calling the map api like this. the parameters (format strings are self explanatory) you have to tell the center location by giving latitude longitude (you can get it from users location if you want to show surrounding places). distance is the area for which you want to query for places. types this mention types of places so it canbe parks, restaurants etc.
When you have run the query you will get a list of places with details and the you have to draw using map annotations
var googleURLString NSString(format:#"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=%#&types=%#&sensor=true&key=%#",latitude, longitute, distance, type, apiKey ) as String
let googleURL = NSURL(string: googleURLString)
let locationData = NSData(contentsOfURL: googleURL!, options: nil, error: nil)
let dataToUse = NSJSONSerialization.JSONObjectWithData(locationData, options: NSJSONReadingOptions.AllowFragments, error:&error) as NSDictionary
let locations = dataToUse["results"]

Instagram user location with api

How can i find user location on intagram api ?
instagram endpoints have this uri : https://api.instagram.com/v1/locations/{location-id}?access_token=ACCESS-TOKEN
You can approximate the location of a user by exploiting the location services on the media feed. That is, you can pull the location tag from one or more of the desired user's posted images. You could then use all the user's images to come up with an approximate location or something like that.
Note that not every image has a location tag, and some user's have location services turned completely off, in which case no images will be tagged. But you can do it like this:
using the image id for one of #instagram's images that has a location. then connecting to the instagram api using the python library to get info on that image. then accessing the images location.
image_id = '976907440786573124_25025320'
image_info = api.media(image_id)
lat = image_info.location.point.latitude
lon = image_info.location.point.longitude
print (lat,lon)
gives the result (51.565501504,-0.089821461)
To add on to jstnstwrt's answer, the most direct way is:
If you install the python-instagram libary for python, you can do the following:
import instagram
api = InstagramAPI(access_token=access_token, client_secret=client_secret)
id = <id of the user you're trying to get location from>
location = api.location(id) # returns error if no location set
coordinates = location.point #returns point object with lat and long coordinates
EDIT 25/07/2019:
This has long stopped working, instagram has locked down their APIs significantly. I would recommend something like instaloader (https://pypi.org/project/instaloader/) that works decently.

Resources