Scott
Scott

Reputation: 1204

Efficent way of determining country polygon touches on a MKMapView?

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.

Upvotes: 0

Views: 555

Answers (1)

incanus
incanus

Reputation: 5128

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/

Upvotes: 1

Related Questions