Latest 1.0.1
License MIT
Platforms ios 8.0
Frameworks GLKit



PlanetaryMaps is an iOS library written in Objective-C that uses OpenGL to render tiled maps on a planet surface. In addition to the maps you can add bitmap markers and polygons on top of the maps.

The library uses a simple and clean API that enables easy customization of the map view.

The following screenshots are from the two sample apps. The leftmost is the Swift sample that shows the Moon between latitudes 75S and 75N. The six markers represent the positions of Apollo landers. The lines are just arbitrary connecting lines. The three other screenshots are from the Objective-C sample that displays Federal Aviation Admininistration’s Sectional and Terminal Area Charts. This sample uses two map layers and also displays a great circle line between the current position and San Francisco International Airport. The two markers represent SFO airport and the current position along with the current true heading.


The library itself has no dependencies but to use the scripts to make your own tilesets you will need to install GDAL and possibly ImageMagick (with WebP).


PlanetaryMaps is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod "PlanetaryMaps"

If you have use_frameworks in the Podfile then you must add import PlanetaryMaps statements in your Swift files.


There are two examples. One in Swift and one in Objective-C. To run the example project, clone the repo, and run pod install in either of the directories under Example.



This is the main class of the library. Add a GLKView to the project and set it’s class to PMPlanetaryView. Use the following methods to set the coordinate under camera and the viewing distance. The distance is scaled such that at distance of 1 the height of the planet is exactly the height of the view.


In order to control the visual aspect of the planet, halo and the background use the properties in PMPlanetaryView:

@property (nonatomic, strong) UIColor *backgroundColor;
@property (nonatomic, strong) UIColor *planetColor;

@property (nonatomic, assign) CGFloat minimumDistance;
@property (nonatomic, assign) CGFloat maximumDistance;

@property (nonatomic, assign) CGFloat haloWidth;
@property (nonatomic, strong) UIColor *haloColor;

@property (nonatomic, strong) UIColor *lineColor;
@property (nonatomic, assign) CGFloat lineSpacingInDegrees;
@property (nonatomic, assign) BOOL linesOnTop;

@property (nonatomic, assign) CGFloat edgeDimIntensity;

The lines refer to the lines of latitude and longitude that are drawn on the planet. Halo is drawn around the planet if the alpha component of haloColor is non-zero. The property haloWidth is defined as a percentage of the radius of the planet, for example a haloWidth on 100 means that the halo reaches to the distance of one radius from the planet surface.

The default values for PMPlanetaryView properties are like in this screenshot:

The background is black, the planet is gray, the lines are drawn underneath the tiles and the halo is a dim blue. Planet edges are dimmed slightly.

There are also properties for specifying the number of tiles that are kept in memory, cache and download queue:

@property (nonatomic, assign) NSInteger cacheSize;
@property (nonatomic, assign) NSInteger maxTiles;
@property (nonatomic, assign) NSInteger maxTilesInDownloadQueue;


To get callbacks regarding what user is doing with the view you can implement the following delegate methods:

-(void)planetaryView:(PMPlanetaryView*)view movedToDistance:(CGFloat)distance;
-(void)planetaryView:(PMPlanetaryView*)view movedToCoordinate:(CLLocationCoordinate2D)coordinate;

-(void)planetaryView:(PMPlanetaryView*)view isAboveTileAtZoom:(NSUInteger)zoom x:(NSUInteger)x y:(NSUInteger)y;
-(void)planetaryView:(PMPlanetaryView*)view tappedAt:(CLLocationCoordinate2D)location screenPoint:(CGPoint)screenPoint;


The difference between movedToCoordinate and isAboveTileAtZoom is that the former is called whenever the viewpoint changes and the latter only when the tile changes under the camera.


To show map tiles on the planet you will have to give PMPlanetaryView a tileDataSource and implement at least the following method:

-(NSURL*)urlForTileLayer:(NSUInteger)layer withZoom:(NSUInteger)zoom atX:(NSUInteger)x andY:(NSUInteger)y;

You can either return an NSURL that points to a web resource or a local file.

If you want to use a file type other than what can be decoded by [UIImage imageWithData:] you can also implement:


WebP is a great image format and can be used through the above delegate method.

If you want to use multiple layers you should implement:



If you want to change the resolution of the 3D geometry that makes one tile you can set the number of segments that each tile is made of:



If you want to display bitmap markers on the planet use this delegate. The first two methods must be implemented. In addition to these two methods you should implement either imageForMarkerAtIndex or textureForMarkerAtIndex.

-(CLLocationCoordinate2D)coordinateForMarkerAtIndex:(NSInteger)index inSet:(NSInteger)set;
-(GLint)textureForMarkerAtIndex:(NSInteger)index inSet:(NSInteger)set;
-(UIImage*)imageForMarkerAtIndex:(NSInteger)index inSet:(NSInteger)set;
-(CLLocationDegrees)headingForMarkerAtIndex:(NSInteger)index inSet:(NSInteger)set;


These are the optional methods for Marker Delegate. The minimumDistanceForMarkersInSet method gives you the option to choose at which distance the marker becomes visible. The useScreenSpaceForMarkersInSet method can be used switch between screen space and world space markers. If the marker is rendered in screen space then sizeForMarkersInSet is given in screen points. If it’s in world space then the size is given in meters. The default size is 50×50 points for screen space and 10000 meters for world space.

-(void)didTapMarkerAtIndices:(NSArray*)indices inSets:(NSArray*)sets;


The lines on top of the map are referred to as polygons as groups of lines can be closed to form a polygon (see ToDo). You give the coordinates that make up a polygon through coordinatesForPolygonAtIndex delegate method. You can have an unlimited number of polygon sets and an unlimited number of polygons in one set. The occlusion algorithm is quite efficient so performance is good even with a high number of polygons.

-(NSArray<CLLocation*>*)coordinatesForPolygonAtIndex:(NSInteger)index inSet:(NSInteger)set;
-(BOOL)closePolygonAtIndex:(NSInteger)index inSet:(NSInteger)set;


These delegate methods control the visual aspect of the polygons. The method fillColorForPolygonStrokesInSet refers to the outline of polygon itself, so there are three colors that make up a polygon, the polygon outline has fill and stroke colors and the polygon itself can be filled with a color (only if closed, see ToDo). If the polygon is rendered in screen space then widthForPolygonOutlinesInSet is given in screen points. If it’s in world space then the size is given in meters. The default width is 15 points for screen space and 1852 meters (one nautical mile) for world space.



These two polygon delegate methods have not been implemented yet:


There are of course many features on the road map including text rendering, tapping inside polygons, Metal / Swift implementations and many more.


This library started as a feasibility study on rendering tiled maps on a spherical surface only using OpenGL shaders. It soon turned out that is not optimal performance-wise so the current implementation uses geometry to render map tiles, markers and polygons.


In the Scripts folder there are several Python and Bash scripts that can be used to convert GeoTIFF and GeoPDF files to tiles that are compatible with PlanetaryMaps. There are two examples that outline the usage of these scripts. Run and scripts inside Scripts/Examples.

The following scripts are available:

Reprojects the supplied GeoTIFF images into WGS84 and adds them to one VRT file. Requires a working GDAL installation.

The VRT file generated by can be run through this script to generate the tiles needed for PlanetaryMaps. This is a fork of from GDAL, it has been modified to output larger tiles (1024×1024 pixels).

This scripts takes a directory as a parameter and scans the folder for empty png files and removes them.

Scans a supplied directory and converts all png images to WebP format. Requires an installation of ImageMagick with WebP support.

This script simply converts a GeoPDF file to GeoTIFF that can be supplied to


Seppo Pietarinen, [email protected]


PlanetaryMaps is available under the MIT license. See the LICENSE file for more info.


Latest podspec

    "name": "PlanetaryMaps",
    "version": "1.0.1",
    "summary": "iOS OpenGL Tiled Maps Viewer",
    "description": "An iOS library that allows the developer to easily add a Google Earth style zoomable mapping view. It supports arbitrary zooming and panning and a clean API to draw lines and markers on the planet surface. You will need to provide URLs for map tiles that are in geodetic projection. Several Python and Bash scripts are provided that can be used to convert GeoTIFF and GeoPDF files to geodetic tiles that can be used with PlanetaryMaps.",
    "homepage": "",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    "authors": {
        "Seppo Pietarinen": "[email protected]"
    "source": {
        "git": "",
        "tag": "1.0.1"
    "social_media_url": "",
    "platforms": {
        "ios": "8.0"
    "source_files": "PlanetaryMaps/Classes/**/*",
    "resource_bundles": {
        "PlanetaryMaps": [
    "frameworks": "GLKit"

Pin It on Pinterest

Share This