I'm overlaying the contents of a third-party shapefile. Some of the polygons consist of 138,000 points, most of them of about 3,000-8,000. In total there are 125 polygons.
Is that normal? Can I in some way, reduce the granularity of the polygons? CPU consumption peaks at over 190% on iPhone 5, and it takes a few minutes before the first overlays pop up.
One thing you might consider is using TileMill to render the Shapefile down into raster tiles with alpha transparency. You can then use that in either MapKit or the Mapbox iOS SDK. It will be highly performant, plus you can still use interactivity going the Mapbox route. Take this map, which was made from Shapefile data in TileMill: https://a.tiles.mapbox.com/v3/newamerica.motw_poverty/page.html#6/40.086/-95.471 The same way that the mouseovers work on the web, you could use Mapbox's RMInteractiveSource API to query and show on tap or other gestures.
Related
I'm using MKMapView to display a map on my iOS app. I've simulated my location to London for the sake of example as I know it has high quality aerial imagery.
Here is a picture from Apple's own Maps app. No problems, super quality:
Here is the same place from my app at the approximately same zoom level:
It looks like it's zoomed out, cropped and zoomed into that region as satellite image is from a more "zoomed out" zoom level. At that level, all the labels disappear too (in Maps), but I've got the labels. I've got multiple instances of MKMapView and the problem is present on all of them. I don't have any special filters, scaling, or anything that would affect the rendering of the maps. In other words, the view instances themselves aren't "zoomed in" in any way. What is exactly going on and how can I make MKMapView render the map at the quality where Maps renders it?
If you are using MKMapTypeSatellite type map, consider that this type has been abandoned by Apple.
Try using MKMapTypeSatelliteFlyover or MKMapTypeHybridFlyover for a better quality.
My project runs at 55-60FPS on an iPhone 6 but anything older is completely unplayable because something is eating CPU.
I think the issue is related to the number of tiles and layers on my map (64x256 with 4 layers) and Instruments shows "SKCRenderer:preprocessSpriteImp(..." taking 5198ms (23.2%) running time.
Does JSTileMap load every single tile's image (visible or not) at once? This post from RW indicates that is the case and that it could be worked around for large performance boosts:
http://www.raywenderlich.com/forums/viewtopic.php?f=29&t=9479
In another performance note - Sprite Kit checks all it's nodes and
decides which ones it needs to display each frame. If you have a big
tile map, this can be a big performance hit. JSTileMap loads all the
nodes (SKSpriteNode for each tile) when it loads the tile map. So, I
was also seeing performance issues in the Sprite Kit version with my
maps (which are 500 x 40 tiles). I added a check to my version of
JSTileMap that's included in the kit that marks the hidden property of
each tile, then intelligently unhides and hides only the tiles that
enter/exit the screen space. That increased performance on these
larger maps significantly.
Unfortunately that post does not go into detail regarding the steps taken to remedy this.
My first thought was to (I'm a beginner, please be gentle) create an array of nodes by looping through each point and checking for a tile on the specific layer. From there I'd work on adding/removing them based on distance from the player.
This didn't work, because the process of adding nodes to an array simply caused the app to hang forever on larger maps.
Could someone lend a hand? I'd love to work with larger/more complicated tilemaps but this performance issue is destroying my brain.
Thanks for reading!
UPDATE: Big thanks to SKAToolKit: https://github.com/SpriteKitAlliance/SKAToolKit
Their culling feature solved my problem and I'm now running even larger maps at less than 35% CPU.
JSTileMap has some issues handling larger maps but you do have a couple of options to consider:
Break your large map into several smaller pieces and load each new piece as required.
Only load those objects which are in the player's vicinity.
Only load those tiles which are in the player's vicinity.
I personally found it impossible to accomplish #3 with JSTileMap as I could not locate an array holding the map tiles. I solved this issue by using the SKAToolKit which provides easy access to map tile arrays. It is an excellent resource for parsing maps created in Tiled.
I would love to reproduce GoogleHeart-like 3D map flyover even when offline.
As of iOS 7 MapKit allows us to draw custom offline tiles. It also allows us to set a Camera in order to see the map in 3D or 2.5D as you may wish to call it.
I was wondering: can I draw a 3D shape like Apple does for its flyover feature, on my custom tiles?
I need to apply a "bump-map" to the map in order to get a GoogleHeart-like 3D view and I was wondering if Apple would allow me to do just that with iOS 7 and custom tiles rendering + camera settings.
Thanks
I have experimented pretty extensively with this, but there is no supported way to do this. Right now, Apple only offers raster tile-based overlay, albeit with automatic 2.5/3D transformation when overlaid on a map. Hopefully in the future they will support 3D API and/or custom, say, OpenGL-based augmentation to the map.
After updating to iOS 6 I have noticed sever performance decreases when panning or zooming a MKMapView with multiple overlays. An app I created has approximately 600 polygon overlays of various colours, and ran lag-free (even on older iOS devices) on iOS 5, now runs extremely laggily (when zooming & panning) on iOS 6, even on the latest devices.
My hunch is that this is due to the fact the device has to actually dynamically create the map (since its vector based) rather than just display tiles onscreen.
Has anyone got any ideas to reduce the lag experienced when panning or zooming the map?
Some extra info, this low frame rate also occurs whilst zooming or panning areas where the overlays are not displayed on screen at all, so it is not to do with the creation of the overlays as they come onscreen.
You can try combining all of your overlays into a single one. This can dramatically boost performance.
The idea is to create an overlay with a bounding box that encompasses all of your polygons. This way your mapView: viewForOverlay will always be called. Create a property for your overlay that holds all of your polygons. Then in the drawMapRect: method of your overlay view, test all of your polygons for intersection with mapRect and draw them if necessary. This is important since you don't want to be drawing polygons that are off screen.
This strategy is based on Apple's own MapKit example projects. Check out HazardMap for an example of drawing several objects in a single MKOverlayView and check out BreadCrumb for an example of how to efficiently test polygons for intersection with your current mapRect in the drawMapRect method
I have a minimalistic MapKit tech demo and it's lagging noticeably as I run it on an iPad 3 with iOS6. Profiling reveals that it's CPU bound, but only 0.2% is from my own code. The big culprits in my case are rendering roads, followed by rendering labels - both done by MapKit. I am showing downtown San Francisco at a 5KM scale, so there are a lot of roads and labels to render.
So the moral of the story is: iOS6 maps are SLOW. Can't tell you how this compares to iOS5 or to an iPad 2, though. But it's lagging, and I am barely doing any work of my own at all.
P.S:
Open Instruments and use the Time Profiler. Make a recording + drill down to find your culprits. Then check 'hide system libraries' to find out how much of the lag is your responsibility vs MapKit's. Then optimize only as needed.
I'd like to overlay a custom map using MapKit. I've currently implemented the TileMap sample from WWDC10. However, my overlay map is in vector form (pdf) and it seems like a terrible waste to rasterise it and convert it to tiles (also takes up about 10megs as opposed to 300KB).
Is there a way to either:
a) overlay a pdf using MKOverlay, or
b) easily convert a vector graphic into MKPolygons, lines etc., so I can recreate my overlay map in MapKit?
Notes: The map I'm trying to overlay is pretty simple but geographically huge. It does need to work offline.
You can overlay a PDF using MKOverlay. In the drawMapRect:zoomScale:inContext: method of your MKOverlayView just use standard PDF drawing functions. You can find those functions here.
The problem with this approach is that for each maprect that is sent to that drawing method you will have to draw the entire PDF each time. This will be really slow. I think you will see the best performance by rasterizing the PDF and converting it to tiles. 10 MB is not too large of a dataset to ship with an iOS app.