Upgrading from osgEarth 2.x to osgEarth 3.x

The goal for osgEarth 3.x was to make the SDK easier to work with for both developers (writing against the API) and end users (creating earth files). This document serves to help you update existing code and earth files for use with osgEarth 3.x.

The primary objectives of 3.x were:

  • Treat everything as a Layer, so that a Map can be a container for almost all data.

  • Make all the various Layer types explicit and reduce the dependency on using plug-ins.

  • Simplify the API for creating and adding Layers by eschewing the “Options” structure pattern.

  • Simplify the approach to making new or custom Layer types.

Earth File Changes

Following the idea of downplaying plugin layer types, Layers in an earth file are now explicit. For a GDAL layer in 2.x you would have had something like this:

<image name="My Layer" driver="gdal">
    <url>file.tif</url>
</image>

In 3.x the layer type is explicit, like so:

<GDALImage name="My Layer">
    <url>file.tif</url>
</GDALImage>

Image and Elevation layer types are still separate, and use explicit types are well. A 3.x GDAL elevation layer looks like:

<GDALElevation name="My DEM">
    <url>dem.tif</url>
</GDALElevation>

Here is a partial table mapping old setups to the new 3.x format:

2.x 3.x
<image driver="gdal"> <GDALImage>
<elevation driver="gdal"> <GDALElevation>
<image driver="tms"> <TMSImage>
<elevation driver="tms"> <TMSElevation>
<image driver="xyz"> <XYZImage>
<elevation driver="xyz"> <XYZElevation>
<image driver="wms"> <WMSImage>

Composite layers

Composite layers in 2.x used the “composite” driver in an image or elevation layer. In 3.x there is a new first-class CompositeImage and CompositeElevation types. Here is an example:

<Map>
    <CompositeImage name="combined">
        <layers>
            <TMSImage>
                <url>http://readymap.org/readymap/tiles/1.0.0/7/</url>
            </TMSImage>
            <GDALImage>
                <url>locallInset.tif</url>
            </GDALImage>
        </layers>
    </CompositeImage>
</Map>

Feature sources

Feature layers (layers containing feature data) are not new to 3.x, but they are also explicit just like the visible layer types above. For example, in osgEarth 2.x you might define a simple feature layer like so:

<feature_model name="states">
    <features name="states" driver="ogr">
        <url>../data/usa.shp</url>
    </features>        
    <styles>
        <style type="text/css">
            states {
               stroke: #ffff00;
            }                    
        </style>
    </styles>        
</feature_model>

In osgEarth 3.x, the definition (using an embedded feature source) looks like this:

<FeatureModel name="US States">
    <OGRFeatures name="US-Data">
        <url>../data/usa.shp</url>
    </OGRFeatures>
    <styles>
        <style type="text/css">
            states {
               stroke:#ffff00;
            }                    
        </style>
    </styles>        
</FeatureModel>

Or, you can define your feature data as a separate Layer and reference it. This way, multiple visible Layers can use the same feature source:

<OGRFeatures name="data:states">
    <url>../data/usa.shp</url>
</OGRFeatures>

<FeatureModel name="US States" features="data:states">
    <styles>
        <style type="text/css">
            states {
               stroke: #ffff00;
            }                    
        </style>
    </styles>        
</FeatureModel>

Even a stylesheet can be a separate layer now. You can rewrite the same thing above as:

<OGRFeatures name="data:states">
    <url>../data/usa.shp</url>
</OGRFeatures>

<Styles name="data:styles">
    <style type="text/css">
        states {
           stroke: #ffff00;
        }                    
    </style>
</Styles>  

<FeatureModel name="US States" features="data:states" styles="data:styles">         
</FeatureModel>

API Changes

In 2.x, you created map layers (and various other things) by creating an “Options” structure and then passing that to the constructor of the new Layer. In 3.x you no longer need to do that; you can just create a new Layer and call its setter functions.

Here is an example of creating a WMS image layer in osgEarth 2.x:

#include <osgEarthDrivers/wms/WMSOptions>
...
WMSOptions wms;
wms.url() = "http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi";
wms.format() = "png";
wms.layers() = "nexrad-n0r";
wms.srs() = "EPSG:4326";
wms.transparent() = true;

ImageLayerOptions wmsLayerOptions("WMS NEXRAD", wms);
wmsLayerOptions.cachePolicy() = CachePolicy::NO_CACHE;

ImageLayer* layer = new ImageLayer(wmsLayerOptions);
map->addLayer(layer);

In 3.x the API is more intuitive, without any intermediate structures:

#include <osgEarth/WMS>
...
WMSImageLayer* wms = new WMSImageLayer();
wms->setURL("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi");
wms->setFormat("png");
wms->setLayers("nexrad-n0r");
wms->setSRS("EPSG:4326");
wms->setTransparent(true);
wms->options().cachePolicy() = CachePolicy::NO_CACHE;
map->addLayer(wms);

Follow the same pattern for all layer types. See the osgearth_map.cpp example for several examples.