Cesium Map View

class tethys_sdk.gizmos.CesiumMapView(options=None, globe=None, view=None, layers=None, entities=None, primitives=None, terrain=None, models=None, clock=None, height='100%', width='100%', draw=False, attributes=None, classes='', cesium_ion_token='')

The Cesium Map View gizmo can be used to produce interactive maps of spatial data. It is powered by CesiumJS

Shapes that are drawn on the map by users can be retrieved from the map via a hidden text field named 'geometry' and it is updated every time the map is changed. If the Cesium Map View is embedded in a form, the geometry that is drawn on the map will automatically be submitted with the rest of the form via the hidden text field.

cesium_ion_token

Cesium Ion Access Token. See: Cesium Rest API - Authentication.

Type:

str

options

Viewer basic options. One item in dictionary per option.

Type:

dict

globe

Options to set on the Globe of the view.

Type:

dict

view

Set the initial view of the map using various methods(e.g.: flyTo, setView).

Type:

dict

layers

Add one or more imagery layers to the map.

Type:

list

entities
Type:

list

primitives

Add one or more primitives to the map.

Type:

list

terrain

Add terrain provider to the map.

Type:

dict

models

Add one or more 3D models to the map.

Type:

list

clock

Define custom clock options for viewer.

Type:

dict

height

Height of the map element. Any valid css unit of length (e.g.: '500px'). Defaults to '100%'.

Type:

str

width

Width of the map element. Any valid css unit of length (e.g.: '100%'). Defaults to '100%'.

Type:

str

draw

Turn drawing tools on/off.

Type:

boolean

attributes

A dictionary representing additional HTML attributes to add to the primary element (e.g. {"onclick": "run_me();"}).

Type:

dict

classes

Additional classes to add to the primary HTML element (e.g. "example-class another-class").

Type:

str

Cesium Version

You can specify the version of Cesium that you'd like to use by setting the cesium_version class property prior to creating your Cesium map view:

python
CesiumMapView.cesium_version = "1.63.1"
my_cesium_view = CesiumMapView(...)

Or you can choose to use the latest release by setting the version to the empty string:

python
CesiumMapView.cesium_version = ""
my_cesium_view = CesiumMapView(...)

Cesium Ion Token

This is your Cesium Ion Access token that grants you access to the Cesium REST APIs. In newer version of Cesium this token is required for proper functioning of the map viewer. To learn how to obtain a token, see Cesium REST API - Authentication.

python
cesium_access_token='mYf8k3t0KEn--asdfsdf98as7uj34n5a8-yvzhnj23q098-zdvnkj'

Options

Basic options for cesium example:

python
options={'shouldAnimate': False, 'timeline': False, 'homeButton': False}

Globe You can specify options that are often set on the Globe object associated with the Cesium viewer. For example, to achieve the equivalent of these calls in the Cesiumm JavaScript API:

python
// Cesium JS Example
viewer.scene.globe.enableLighting = true;
viewer.scene.globe.depthTestAgainstTerrain = true;

Pass the following Globe options to CesiumMapView:

python
# Tethys CesiumMapView example
cesium_map_view = CesiumMapView(
    globe={
        'enableLighting': True,
        'depthTestAgainstTerrain': True
    }
)

View

Here is how the view option is defined using the Cesium JavaScript API (Sandcastle - Camera):

python
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(-122.22, 46.12, 5000.0),
    orientation : {
         heading : Cesium.Math.toRadians(20.0),
         pitch : Cesium.Math.toRadians(-35.0),
         roll : 0.0
    }
});

In Tethys CesiumMapView, you can define this setting using python as follows

python
view={'flyTo': {
    'destination': {'Cesium.Cartesian3.fromDegrees': [-122.19, 46.25, 5000.0]},
    'orientation': {
         'heading': {'Cesium.Math.toRadians': [20]},
         'pitch': {'Cesium.Math.toRadians': [-35]},
         'roll': 0.0,
    }
}}

Layers

CesiumMapView supports all the imagery layers in the CesiumJS API (see Imagery Providers). It also support ImageWMS and TileWMS MVLayers (see: MVLayer). You can load one or more imagery layers using the following pattern:

python
layers=[
    {<layer_name>: {
        'imageryProvider': {<imagery_provider_class>: {
            <option1>: <value1>,
            <option2>: <value2>
        }
    },
    <MVLayer Object>
]

Examples:

  • Bing: The following values can be used for mapStyle: Aerial, AerialWithLabels, CanvasDark, CanvasGray, CanvasLight, CollinsBart, OrdnanceSurvey, Road

python
layers=[
    {'Bing Map': {
        'imageryProvider': {'Cesium.BingMapsImageryProvider': {
            'url': 'https://dev.virtualearth.net',
            'key': 'YouR-api-KEy',
            'mapStyle': 'Aerial',
        }}
    }}
]
  • ESRI:

python
layers=[
    {'Esri Arc GIS Map Server': {
        'imageryProvider': {'Cesium.ArcGisMapServerImageryProvider': [{
            'url': 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
        }]}
    }}
]
  • OpenStreetMap:

python
layers=[
    {'Open Street Map': {
        'imageryProvider': {'Cesium.OpenStreetMapImageryProvider': {
            'url': 'https://a.tile.openstreetmap.org/'
        }}
    }}
]
  • WMS Imagery Service:

python
layers=[
    {'WMS Imagery Provider': {
        'imageryProvider': {'Cesium.WebMapServiceImageryProvider': [{
            'url': 'https://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer',
            'layers': '0',
            'proxy': {'Cesium.DefaultProxy': ['/proxy/']}
        }]}
    }}
]
  • Mix with MVLayer Objects

python
layers=[
    {'Open Street Map': {
        'imageryProvider': {'Cesium.OpenStreetMapImageryProvider': {
            'url': 'https://a.tile.openstreetmap.org/'
        }}
    }},
    MVLayer(
        source='ImageWMS',
        legend_title='MVLayer ImageWMS',
        options={
            'url': 'https://demo.geo-solutions.it/geoserver/wms',
            'params': {'LAYERS': 'topp:states'},
            'serverType': 'geoserver'
        },
    )
]

Entities

Supports CZML and GeoJSON entities. Also supports GeoJSON MVLayers (see: MVLayer).

  • CZML Example:

python
entities=[
    {
        'source': 'czml',
        'options': [
            {
                "id": "document",
                "name": "CZML Geometries: Polygon",
                "version": "1.0"
            },
            {
                "id": "whitePolygon",
                "name": "White polygon on surface",
                "polygon": {"positions": {
                    "cartographicDegrees": [
                        -115.0, 37.0, 0,
                        -115.0, 32.0, 0,
                        -107.0, 33.0, 0,
                        -102.0, 31.0, 0,
                        -102.0, 35.0, 0
                    ]
                }},
                "material": {
                    "solidColor": {
                        "color": {
                            "rgba": [255, 0, 0, 255]
                        }
                    }
                }
            }
        ]
    }
]
  • GeoJSON Example:

python
entities=[
    {
        'source': 'geojson',
        'options': {
            'type': 'FeatureCollection',
            'crs': {
                'type': 'name',
                'properties': {
                    'name': 'EPSG:4326'
                }
            },
            'features': [
                {
                    'type': 'Feature',
                    'geometry': {
                        'type': 'Point',
                        'coordinates': [0, 0]
                    }
                },
                {
                    'type': 'Feature',
                    'geometry': {
                        'type': 'LineString',
                        'coordinates': [[35.9326113, -17.6789142], [71.8652227, 17.6789142]]
                    }
                },
                {
                    'type': 'Feature',
                    'geometry': {
                        'type': 'Polygon',
                        'coordinates': [
                            [[-44.9157642, -8.9465739], [-35.9326114, 8.9465739], [-26.9494585, -8.9465739]]
                        ]
                    }
                }
            ]
        }
    }
]
  • GeoJSON MVLayer

python
entities=[
    MVLayer(
        source='GeoJSON',
        legend_title='MVLayer GeoJSON Example',
        options={
            'type': 'FeatureCollection',
            'crs': {
                'type': 'name',
                'properties': {
                    'name': 'EPSG:4326'
                }
            },
            'features': [
                {
                    'type': 'Feature',
                    'geometry': {
                        'type': 'Point',
                        'coordinates': [0, 0]
                    }
                },
                {
                    'type': 'Feature',
                    'geometry': {
                        'type': 'LineString',
                        'coordinates': [[35.9326113, -17.6789142], [71.8652227, 17.6789142]]
                    }
                },
                {
                    'type': 'Feature',
                    'geometry': {
                        'type': 'Polygon',
                        'coordinates': [
                            [[-44.9157642, -8.9465739], [-35.9326114, 8.9465739], [-26.9494585, -8.9465739]]
                        ]
                    }
                }
            ]
        }
    )
]

Primitives

Support Cesium Primitive such as Cesium Ion

You can load a Cessium Ion using the following pattern:

python
primitives=[
    {'Cesium_Ion_Data': {'Cesium.Cesium3DTileset': {'url': {'Cesium.IonResource.fromAssetId': 123}}}},
    MVLayer(
        source='CesiumPrimitive',
        legend_title='Cesium 3D Buildings',
        options={'Cesium.Cesium3DTileset': {'url': {'Cesium.IonResource.fromAssetId': 96188}}},
        data={'layer_name': 'Cesium_Buildings', 'layer_variable': 'variable', 'layer_id': 1}
    )
]

Terrain

Supports all the terrain providers available in Cesium (see Cesium Terrain Providers

You can load a terrain provider using the following pattern:

python
terrain={
    'terrainProvider': {<terrain_provider_class>: {
        <option1>: <value1>,
        <option2>: <value2>
    }
}

For example:

python
terrain={'terrainProvider': {
    'Cesium.createWorldTerrain': {
        'requestVertexNormals' : True,
        'requestWaterMask': True
    }
}}

Models

Support loading glTF 3d model. It could be traditional glTF with a .gltf extension or binary glTF with a .glb extension

For example:

python
object = 'link_to.glb'

models=[
    {'Cesium_Airplane': {
        'model': {
            'uri': object1,
            'show': True,
            'minimumPixelSize': 128,
            'maximumScale': 20000,
            'shadows': 'enabled',
        },
        'name': 'Cesium Airplane',
        'orientation': {
            'Cesium.Transforms.headingPitchRollQuaternion': [
                {'Cesium.Cartesian3.fromDegrees': [-123.0744619, 44.0503706, 5000]},
                {'Cesium.HeadingPitchRoll': [{'Cesium.Math.toRadians': 135}, 0, 0]}
        ]},
        'position': {'Cesium.Cartesian3.fromDegrees': [-123.0744619, 44.0503706, 5000]},
    }},
    MVLayer(
        source='CesiumModel',
        legend_title='Cesium Ballon',
        options={'model': {
            'uri': object2,
            'show': True,
            'minimumPixelSize': 128,
            'maximumScale': 20000,
            'shadows': 'enabled'},
            'name': 'Cesium_Ballon',
            'orientation': {
                'Cesium.Transforms.headingPitchRollQuaternion':
                    [{'Cesium.Cartesian3.fromDegrees': [-123.0744619, 44.0503706, 5000]},
                     {'Cesium.HeadingPitchRoll': [{'Cesium.Math.toRadians': 135}, 0, 0]}]},
            'position': {'Cesium.Cartesian3.fromDegrees': [-123.0744619, 44.0503706, 5000]}
         },
        data={
            'layer_id': "cesium_ballon_id",
            'layer_name': "Cesium_Ballon",
            'popup_title': "Cesium Ballon",
        }
    ),
]

Cesium Ion Resource using Assest ID

Support loading data from Cesium Ion assets and resources.

For example:

python
primitives = [{'Cesium_World_Terrain': {'Cesium.Cesium3DTileset': {'url': {'Cesium.IonResource.fromAssetId': 1}}}},
              MVLayer(source='CesiumPrimitive', legend_title='Cesium 3D Buildings',
                      options={'Cesium.Cesium3DTileset': {'url': {'Cesium.IonResource.fromAssetId': 96188}}},
                      data={'layer_name': 'Cesium_Buildings', 'layer_variable': 'variable', 'layer_id': 1})]

Clock

You can customize the clock on the viewer such as specifying the starting date and time and specifying the time step interval. For example, to achieve the equivalent of these calls in the Cesiumm JavaScript API:

python
// Cesium JS Example
var clock = new Cesium.Clock({
    startTime : Cesium.JulianDate.fromIso8601('2017-07-11T00:00:00Z'),
    stopTime : Cesium.JulianDate.fromIso8601('2017-07-11T24:00:00Z'),
    currentTime : Cesium.JulianDate.fromIso8601('2017-07-11T10:00:00Z'),
    clockRange : Cesium.ClockRange.LOOP_STOP,
    clockStep : Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER,
    multiplier : 1000,
    shouldAnimate : true
});
var viewer = new Cesium.Viewer('cesiumContainer', {
    clockViewModel : new Cesium.ClockViewModel(clock),
});

Pass the following Clock options to CesiumMapView:

python
# Tethys CesiumMapView example
cesium_map_view = CesiumMapView(
    clock = {'clock': {'Cesium.Clock': {
        'startTime': {'Cesium.JulianDate.fromIso8601': ['2017-07-11T00:00:00Z']},
        'stopTime': {'Cesium.JulianDate.fromIso8601': ['2017-07-11T24:00:00Z']},
        'currentTime': {'Cesium.JulianDate.fromIso8601': ['2017-07-11T10:00:00Z']},
        'clockRange': 'Cesium.ClockRange.LOOP_STOP',
        'clockStep': 'Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER',
        'multiplier': 1000,
        'shouldAnimate': True
    }}}
)

Drawing

The following drawing options are supported:

  • Add marker

  • 2D polyline

  • 2D polygon

  • Extent

  • Circle

All the drawing options can be view in the log and are available upon submit using a hidden text field named 'geometry'

The drawing feature also have the following tools:

  • Delete All: Use to delete all the drawing features on the map.

  • Turn logging on or off: Use to turn on or off logging.

Translate Cesium Attributes from Javascript to Python

You can find a lots of way to define cesium attributes in the sandcastle page: Sandcastle

Here are a few things to remember:

  1. Put Cesium method/class in a dictionary with the method/class as key and its argument in a list.

  2. If the argument of a given Cesium method/class has another Cesium method/class as its argument, simply follows the same procedure in 1.

For example:

python
'orientation': {'Cesium.Transforms.headingPitchRollQuaternion': [
    {'Cesium.Cartesian3.fromDegrees': [-123.0744619, 44.0503706, 5000]},
    {'Cesium.HeadingPitchRoll': [{'Cesium.Math.toRadians' : 135}, 0, 0]}
]}

JavaScript API

For advanced features, the JavaScript API can be used to interact with the Cesium viewer object that is generated by the Cesium Map View JavaScript library.

CESIUM_MAP_VIEW.getMap()

This method returns the Cesium Viewer instance. You can use the Cesium.Viewer API Docs to perform operations on this object such as changing the view, animating, and modifying the entities, layers, and models.

python
$(function() { //wait for page to load

    var c_map = CESIUM_MAP_VIEW.getMap();
    var entities = c_map.entities;
    c_map.flyTo(entities[0]);

});

CESIUM_MAP_VIEW.reInitializeMap()

This method is intended for initializing a map generated from an AJAX request.

Caution

This method assumes there is only one and that there will only ever be one map on the page.

Note

In order to use this you will need to import the JavaScript/CSS libraries in the main html template page using the import_gizmo_dependency tag in the import_gizmos block.

For example:

python
{% block import_gizmos %}
    {% import_gizmo_dependency cesium_map_view %}
{% endblock %}

Three elements are required:

  1. A controller for the AJAX call with a Cesium map view gizmo.

python
@controller(
    url="dam-break/map/dam_break_map_ajax",
)
def dam_break_map_ajax(request):
    """
    Controller for the dam_break_map ajax request.
    """
    if request.GET:
        ...

        #get layers
        map_layer_list = ...

        cesium_map_view = CesiumMapView(...)

        context = { "cesium_map_view": cesium_map_view }

        return render(request, "dam_break_map_ajax/map_ajax.html", context)
  1. A template for with the tethys gizmo (e.g. map_ajax.html)

html+django
{% load tethys_gizmos %}

{% gizmo cesium_map_view %}
  1. The AJAX call in the javascript

javascript
$(function() { //wait for page to load

    $.ajax({
        url: ajax_url,
        method: 'GET',
        data: ajax_data,
        success: function(data) {
            //add new map to map div
            $('#main_map_div').html(data);

            CESIUM_MAP_VIEW.reInitializeMap();
        }
    });

});

Caution

When referring to the Cesium documentation, ensure that you are browsing the correct version of documentation.