wiki:DeveloperGuidelines/GIS

Version 47 (modified by graeme, 13 years ago) ( diff )

--

GIS Module

Guidelines for Developers wishing to make use of Mapping within their Module

The easiest approach is to call the Mapping API.

Controller

map = gis.show_map()
return dict(map=map)

View

{{=XML(map)}}

Examples

Check the following functions in controllers/gis.py:

  • map_viewing_client()
  • display_feature()
  • display_features()

Full API description

def show_map( self,
              height = None,
              width = None,
              bbox = {},
              lat = None,
              lon = None,
              zoom = None,
              projection = None,
              add_feature = False,
              add_feature_active = False,
              add_polygon = False,
              add_polygon_active = False,
              features = [],
              feature_queries = [],
              wms_browser = {},
              catalogue_layers = False,
              catalogue_toolbar = False,
              legend = False,
              toolbar = False,
              search = False,
              googleEarth = False,
              googleStreetview = False,
              mouse_position = "normal",
              print_tool = {},
              mgrs = {},
              window = False,
              window_hide = False,
              closable = True,
              collapsed = False,
              plugins = None
            ):
    """
        Returns the HTML to display a map

        Normally called in the controller as: map = gis.show_map()
        In the view, put: {{=XML(map)}}

        @param height: Height of viewport (if not provided then the default setting from the Map Service Catalogue is used)
        @param width: Width of viewport (if not provided then the default setting from the Map Service Catalogue is used)
        @param bbox: default Bounding Box of viewport (if not provided then the Lat/Lon/Zoom are used) (Dict):
            {
            "max_lat" : float,
            "max_lon" : float,
            "min_lat" : float,
            "min_lon" : float
            }
        @param lat: default Latitude of viewport (if not provided then the default setting from the Map Service Catalogue is used)
        @param lon: default Longitude of viewport (if not provided then the default setting from the Map Service Catalogue is used)
        @param zoom: default Zoom level of viewport (if not provided then the default setting from the Map Service Catalogue is used)
        @param projection: EPSG code for the Projection to use (if not provided then the default setting from the Map Service Catalogue is used)
        @param add_feature: Whether to include a DrawFeature control to allow adding a marker to the map
        @param add_feature_active: Whether the DrawFeature control should be active by default
        @param add_polygon: Whether to include a DrawFeature control to allow drawing a polygon over the map
        @param add_polygon_active: Whether the DrawFeature control should be active by default
        @param features: Simple Features to overlay on Map (no control over appearance & not interactive)
            [{
                lat: lat,
                lon: lon
            }]
        @param feature_queries: Feature Queries to overlay onto the map & their options (List of Dicts):
            [{
             name   : "MyLabel",    # A string: the label for the layer
             query  : query,        # A gluon.sql.Rows of gis_locations, which can be from a simple query or a Join.
                                    # Extra fields can be added for 'popup_url', 'popup_label' & either
                                    # 'marker' (url/height/width) or 'shape' (with optional 'colour' & 'size')
             active : True,         # Is the feed displayed upon load or needs ticking to load afterwards?
             marker : None          # Optional: A per-Layer marker query or marker_id for the icon used to display the feature
             opacity : 1            # Optional
             cluster_distance       # Optional
             cluster_threshold      # Optional
            }]
        @param wms_browser: WMS Server's GetCapabilities & options (dict)
            {
            name: string,           # Name for the Folder in LayerTree
            url: string             # URL of GetCapabilities
            }
        @param catalogue_overlays: Show the Overlays from the GIS Catalogue (@ToDo: make this a dict of which external overlays to allow)
        @param catalogue_toolbar: Show the Catalogue Toolbar
        @param legend: Show the Legend panel
        @param toolbar: Show the Icon Toolbar of Controls
        @param search: Show the Geonames search box
        @param mouse_position: Show the current coordinates in the bottom-right of the map. 3 Options: 'normal' (default), 'mgrs' (MGRS), False (off)
        @param print_tool: Show a print utility (NB This requires server-side support: http://eden.sahanafoundation.org/wiki/BluePrintGISPrinting)
            {
            url: string,            # URL of print service (e.g. http://localhost:8080/geoserver/pdf/)
            mapTitle: string        # Title for the Printed Map (optional)
            subTitle: string        # subTitle for the Printed Map (optional)
            }
        @param mgrs: Use the MGRS Control to select PDFs
            {
            name: string,           # Name for the Control
            url: string             # URL of PDF server
            }
        @param window: Have viewport pop out of page into a resizable window
        @param window_hide: Have the window hidden by default, ready to appear (e.g. on clicking a button)
        @param closable: In Window mode, whether the window is closable or not
        @param collapsed: Start the Tools panel (West region) collapsed
        @param public_url: pass from model (not yet defined when Module instantiated
    """

Variable Markers

Example:

query = (db.gis_location.deleted == False)
query = query & (db.gis_location.id == db["%s_%s" % (module, resource)].location_id)
locations = db(query).select(db.gis_location.id, db.gis_location.uuid, db.gis_location.name, db.gis_location.wkt, db.gis_location.lat, db.gis_location.lon)
for i in range(0, len(locations)):
    locations[i].gis_location.shape = "circle"
    locations[i].gis_location.size = locations[i][db["%s_%s" % (module, resource)].MyIntegerField]

Guidelines for Developers wishing to extend the functionality of the core GIS

OpenLayers

The GIS module uses OpenLayers for Display purposes, so a thorough understanding of this is a great foundation for what we do:

Projections: http://trac.openlayers.org/wiki/Documentation/Dev/proj4js

Debugging advice: http://docs.openlayers.org/help/minimize.html

GUI

The map window is wrapped in an Ext GUI based on GeoExt (formerly MapFish client)

How to debug WMS

How to add a new Layer type

Assuming that OpenLayers supports the layertype:

Model

models/03_gis.py

_gis_layer_types = ["newlayertype", "..."]
table = db.define_table("gis_layer_newlayertype",
                            name_field(),
                            Field("description", label=T("Description")),
                            Field("enabled", "boolean", default=True, label=T("Available in Viewer?")),
                            Field("visible", "boolean", default=True,
                                  label=T("On by default? (only applicable to Overlays)")),
                            Field("url", label=T("Location"), requires = IS_NOT_EMPTY(),
                                  comment=DIV( _class="tooltip",
                                               _title="%s|%s" % (T("Location"),
                                                                 T("The URL to access the service.")))),
                            Field("version", length=32,
                                  label=T("Version"), default="1.1.1",
                                  requires=IS_IN_SET(["1.1.1", "1.3.0"], zero=None)),
                            Field("base", "boolean", default=False,
                                  label=T("Base Layer?")),
                            Field("transparent", "boolean", default=True,
                                  label=T("Transparent?")),
                            gis_opacity(),
                            role_required(),       # Single Role
                            #roles_permitted(),    # Multiple Roles (needs implementing in modules/s3gis.py)
                            *s3_timestamp())

Controller

controllers/gis.py

def layer_newlayertype():
    """ RESTful CRUD controller """
    if deployment_settings.get_security_map() and not shn_has_role("MapAdmin"):
        unauthorised()

    resourcename = request.function
    tablename = "%s_%s" % (module, resourcename)
    table = db[tablename]

    # Model options
    table.url.comment = SPAN("*", _class="req")

    # CRUD Strings
    type = "New Layer Type"
    LAYERS = T(TYPE_LAYERS_FMT % type)
    ADD_NEW_LAYER = T(ADD_NEW_TYPE_LAYER_FMT % type)
    EDIT_LAYER = T(EDIT_TYPE_LAYER_FMT % type)
    LIST_LAYERS = T(LIST_TYPE_LAYERS_FMT % type)
    NO_LAYERS = T(NO_TYPE_LAYERS_FMT % type)
    s3.crud_strings[tablename] = Storage(
        title_create=ADD_LAYER,
        title_display=LAYER_DETAILS,
        title_list=LAYERS,
        title_update=EDIT_LAYER,
        title_search=SEARCH_LAYERS,
        subtitle_create=ADD_NEW_LAYER,
        subtitle_list=LIST_LAYERS,
        label_list_button=LIST_LAYERS,
        label_create_button=ADD_LAYER,
        label_delete_button = DELETE_LAYER,
        msg_record_created=LAYER_ADDED,
        msg_record_modified=LAYER_UPDATED,
        msg_record_deleted=LAYER_DELETED,
        msg_list_empty=NO_LAYERS)

    # Post-processor
    def user_postp(jr, output):
        shn_action_buttons(jr)
        return output
    response.s3.postp = user_postp

    output = s3_rest_controller(module, resourcename)

    if not "gis" in response.view:
        response.view = "gis/" + response.view

    return output

View

views/gis/map_service_catalogue.html

<li><a href='{{=URL(f="layer_newlayertype")}}'>New Layer Type</a> - Description</li>

Module

Classes need adding: modules/s3gis.py

class NewTypeLayer(Layer):
...

def show_map():
for LayerType in [
                  ...
                  NewTypeLayer,

Static

OpenLayers code needs adding: static/scripts/S3/s3.gis.layers.js

function addNewTyppeLayer(layer) {
    ...
}
function addLayers() {
    ....
    if (S3.gis.layers_newlayertype) {
        for (i = 0; i < S3.gis.layers_newlayertype.length; i++) {
            addNewTypeLayer(S3.gis.layers_newlayertype[i]);
        }
    }
    ....
}
cd static/scripts/tools
build gis

See Also

BluePrintGeographicInformationSystems

UserGuidelinesGIS

DeveloperGuidelines

Note: See TracWiki for help on using the wiki.