Efficent way of determining country polygon touches on a MKMapView? - ios

When a user taps a point on an MKMapView in my application, I want to determine what country they tapped on. Speed is my priority, since a user will definitely notice the lag between a map touch and an annotation callout begin presented with the name of the country.
I have the polygon information for all the countries and I can parse/store them in any kind of data structure necessary. Currently, they are in GeoJSON format and have thousands of verticies. I also have bounding boxes computed and stored for each country.
One suggestion was to store an array of CGRects for each polygon's bounding box and first doing a CGRectContainsPoint search on all the bounding boxes to quickly narrow down the search. If that search returns multiple bounding boxes (common on country borders where the bounding boxes can overlap) then I can check the filtered country's full polygon for the point in question. Even on very congested overlapping areas, this full search would be 5 or less full country polygons to check.
To accomplish this, I'll need to store both a CGRect bounding box and a full, complex CGPath for each country. (and a country can have multiple polygons if it has territories) I don't know if storing these in-memory is a good idea, since there are potentially many thousands of polygons.
Compiling SpatiaLite is not an option because of the licensing requirements for GEOS. Compiling SQLite with the R-Tree extension is a possibility. The polygons do not change, so I'm able to precompute and store them on disk in any way that is suggested.
If I follow this suggestion, what is the best way to store and access all these CGRect and CGPaths for quick searching and access?
I'm open to any other suggestions people have.

I would recommend either using the Mapbox iOS SDK or at least using the RMInteractiveSource and RMMBTilesSource parts of it. You can use TileMill to turn your source data into raster tiles with encoded interactivity info on a per-pixel basis. Here's an example: https://github.com/mapbox/mapbox-ios-example The interactivity data is basically a highly efficient key-value store on a per-pixel basis. You can then convert a CGPoint at a given map zoom level and panning offset into the value.
Technology background: https://www.mapbox.com/developers/utfgrid/

Related

GTFS Shape Extraneous Data Points

I am working on an iOS application which uses GTFS data. The data is provided by the local transit authority. When plotting the route overlays onto a map, I have found a number of outlying data points as seen in the image below:
Screen Shot (Imgur)
*Sorry I didn't have enough reputation to post an image
In order to make the data more managable I have filtered the shape data through the Ramer-Douglas-Peucker Algorithm to remove redundant data points.
I am unsure of how to process the data further to remove these obviously incorrect points. Could someone offer some advice on to filter out these data points?
It looks like the agency has maybe added extraneous segments from the road to each stop's location on the side of the road? You might try filtering small segments that pop out to a stop location and back.

iOS MapKit - defining irregular touchable regions

I'm working on an app that lets a user select locations on a map. The entire map is subdivided into irregular regions (administrative boundaries), and when a user touches a point on a map, I need to be able to figure out which region the point belongs to. Just to clarify, there is no finite set of points for a user to choose from, they just tap anywhere on the map.
What is the best way to achieve this? I have been looking at MKPolygon class but cannot really figure out if this is the way to go. If it is, would I be using intersectsMapRect: method of the MKOverlay protocol to check for a match? Are there any good tutorials on this kind of map operations?
A good approach here might be the MapBox iOS SDK and it's RMInteractiveSource, which is designed for this. Check out this sample app which shows interactive regions.
This is done by a space-optimized, offline-capable key-value store of sorts that keys pixels at varying zoom levels to arbitrary content values (region name, data, imagery, etc.)
In MapKit proper, you'll need some sort of spatial analysis (maybe Spatialite?) to determine intersections between points touched and irregularly-shaped regions.

Best way to create custom building's map for iOS

I see some ways to do it:
1) Draw using OpenGL programmatically.
2) Draw using QuartzCore and CoreAnimation programmatically.
3) Draw map in AutoCad and then somehow connect it to iOS.
4) Draw map using SVG.
Requirments are supporting pathfinding and gps navigation.
For first 2 ways I think that it's expensive in terms of performance way, redraw all elements on scaling; and I don't think that this way may have GPS-navigation support.
Using AutoCad pictured maps is hard to understand for me how to connect it with graphs\paths for pathfinding.
My colleagues will develop this app on web using SVG. I found it - https://github.com/SVGKit/SVGKit , but still have no idea how it will support pathfinding and navigation.
I would appreciate any help.
Generally there are two types of map application:
A) They display a map, (with or without a user position) without needing to calculate a path like a navigation system does (see point B)
B) Application that use the vectors of a map and calculate something: e.g to find a best path. The shortest connection, e.g A navighation system , etc.
Application for A) are usually less complex then that of B), because the vectors can be somewhat inacurate, have no conections, have small gaps, have no logic between the edges, etc.
1) To only display a building map, you would only need a list of edges. (An edge is pair of coordinates (x1,y1) - (x2,y2). How ever you get that. E.g MapInfo Professional format mif/mid.
Or even you could dispaly a pdf that contains the map of the builing. Right with the built in PDF View, (also with SVG but more difficult).
Things get much more complicated if it is not a relative map, but also a map that is positioned with an reference coordinate system, like latitude/longitude (WGS84).
In that case you would use a Tool (mapInfoProfessional, to import AutoCad DXF Files, and apply 3 GPS measured reference points at the corner of the house, and convert that to LatLong WGS84 coordinates system.
With ios you cannot measure that 3 Points because you cannot average a position, ios stops sending when you are standing still at one corner of the house.
You could try to extract the positions from a google earth satellite foto if you are living in a region where google Sattelite fotos have high resolution. (But this might violate the license conditions of that Satellite Foto provider (Topic: derived data))
Finally you now have a list of edges in Lat Lon coordinate System.
For Displaying I personally would either do with 1) OpenGL) or 2) Quartz2D.
Now the Path finding part.
Probaly you need a second "map" that defines the possible paths inside the building.
This structure must be a connect graph (points with connected neighbours).
Computer games do it that way. (Some even allow you to display that path in developper mode)
The path can be drawn, in a different layer of the floor plan. But this path
has higher requirements: No gaps are allowed, all must be perfect connected.
Call that layer "Path" and export it as own plan.
Now use only this path layer, and import, and create a graph of nodes with connect neighbours.
Use Dijkstra Algo to search for shortest path.

iOS Mapkit - How to offset a user's location be specified amount

I am developing an app that uses the user's location to be displayed on a map with other users.
I want to ensure that all users have a bit of privacy when it comes to their location being displayed openly to other users, so I am hoping to just set their location with a specified offset (lets say 1 mile) and display the "edited" location to all other users while still showing the "exact" location to the current user.
Example - If I am looking at the map, I want my "user location" (the blue dot) to be somewhat exact, while all other player's will see my location slightly offset from the real location.
What is the best way to achieve this?
I think the question you actually want the answer to is this:
How do I convert the user's location into an "approximate location" in a way that preserves the user's privacy?
It's not an easy problem:
Offsetting by a specific distance doesn't work:
There's a trivial attack if the direction is fixed.
If the direction does not change often enough, then the attacker only needs to wait to identify what looks like a road.
If the direction changes too often, then they'll tend to form a 1-mile circle around the target's house/work.
Offsetting by a random distance/direction doesn't work; the attacker just needs to collect enough samples; the clusters will likely be centered on the target's home/work.
Quantizing to a grid naively (e.g. "X is within this grid square") will tell you when the target crosses a grid boundary. This is especially bad if the target lives on a grid boundary.
Here's something that works a little better, but wil still (eventually) give away the user's location:
Pick an (approximately) 1-mile grid. For a "square" grid, you could use the Pierce quincunxal projection (there are four points of infinite distortion but you can make those all at sea — it looks like you can limit distortion on land to a factor of 2). There are also projections onto cube and, for a triangular grid, an icosahedron.
When you first need to report the user's location, give the nearest point on the grid. Also pick a threshold distance between 1 and 2 grid "squares", or so.
While the user is within the threshold distance of the center of the grid square, continue to report the same grid square. Otherwise, repeat.
It'll still eventually be obvious if the user happens to live on a grid boundary. There are various ways to attempt to fix this problem (e.g. a bias to reporting grid squares you've reported before), but these will eventually fail.
This seems a lot like trying to remove a digital watermark (the user's actual location) by using lossy compression (the approximation process) while producing an output image/audio (approximate location) that sounds/looks like the original. (The analogy works a little better if you treat the "watermark" as the user's daily habits, which will be visible in the output unless you know exactly what those habits are and can remove them.)
Or in signal processing terms: A low SNR simply means you have to listen for longer to extract the signal.
Are you showing everyone else as a pin? It might be strange if you show a pin at an exact location but the other user isn't there. For example if someone was a mile north and you showed their pin at the same location as the current user. Maybe you should display the other users with an MKOVerlay circle, and then use some calculation base on a userID to shift it slightly off centre so that people don't find out that it is always shifted 500m east and thus easily see here people are.
Whether or not you change the display, the code you seek is here: Get the GPS coordinate given the current location, bearing and distance

Building density maps with large geocoded datasets?

I have a data set with over 50,000 geocoded points (lat-long). Each point has a set of data associated with it -- things like quality, status, etc.
I'd like to make a set of density maps showing the distribution of data by those metrics. For example, one map would show the density of all items with a quality of "good".
With a smaller set of points, I'd use Google Maps and custom markers. Here, however, different segments have tens of thousands of points
Are there any APIs or libraries that could help me do this?
The solution I will be going with:
Break the area to be mapped into a
grid.
Count the number of entries
falling inside each square.
For each
square, generate a PNG with
transparency relative to the number
of entries.
Populate a Google Map with
this set of PNGs as markers.
Google Fusion Table does a nice job at it http://www.google.com/fusiontables/Home/
Good for you that your data are already geocoded, because -from my recent experience-, Google location resolver does not let you dealing with ambiguous location..
One solution could be to create bitmaps with your density maps and add them (only one at the same time) as overlay on your google map (with GGroundOverlay)
You may have a look at this post that gives an example of density map with google map. It uses the HeatMapAPI. Unfortunately, this API is not free if you use it with a large number of points...
Put build your own density bitmap may be not so complicated...
One other solution is to reduce the number of markers you can use. It could be done with the MarkerClustered library. It is not exactly a density map, but... can maybe be useful.
http://heatmap.codeplex.com/

Resources