= GIS Module = [[TOC]] We use [http://openlayers.org OpenLayers] to display Maps with some [http://geoext.org GeoExt] widgets. == 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, id = "default_map", height = None, width = None, bbox = {}, lat = None, lon = None, zoom = None, projection = None, add_feature = False, add_feature_active = False, add_line = False, add_line_active = False, add_polygon = False, add_polygon_active = False, features = None, feature_queries = None, feature_resources = None, wms_browser = {}, catalogue_layers = False, legend = False, toolbar = False, area = False, nav = None, save = False, search = False, mouse_position = None, overview = None, permalink = None, scaleline = None, zoomcontrol = None, zoomWheelEnabled = True, mgrs = {}, window = False, window_hide = False, closable = True, maximizable = True, collapsed = False, callback = "DEFAULT", 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 id: ID to uniquely identify this map if there are several on a page @param height: Height of viewport (if not provided then the default deployment setting is used) @param width: Width of viewport (if not provided then the default deployment setting is used) @param bbox: default Bounding Box of viewport (if not provided then the Lat/Lon/Zoom are used) (Dict): {"lon_min" : float, "lat_min" : float, "lon_max" : float, "lat_max" : 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) [wkt] @param feature_queries: Feature Queries to overlay onto the map & their options (List of Dicts): [{"name" : T("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_attribute", # Optional "cluster_distance", # Optional "cluster_threshold" # Optional }] @param feature_resources: REST URLs for (filtered) resources to overlay onto the map & their options (List of Dicts): [{"name" : T("MyLabel"), # A string: the label for the layer "id" : "search", # A string: the id for the layer (for manipulation by JavaScript) "active" : True, # Is the feed displayed upon load or needs ticking to load afterwards? EITHER: "layer_id" : 1, # An integer: the layer_id to load (optional alternative to specifying URL/tablename/marker) "filter" : "filter", # A string: an optional URL filter which *replaces* any in the layer OR: "tablename" : "module_resource", # A string: the tablename (used to determine whether to locate via location_id or site_id) "url" : "/eden/module/resource.geojson?filter", # A URL to load the resource "marker" : None, # Optional: A per-Layer marker dict for the icon used to display the feature (overrides layer_id if-set) "opacity" : 1, # Optional (overrides layer_id if-set) "cluster_attribute", # Optional (overrides layer_id if-set) "cluster_distance", # Optional (overrides layer_id if-set) "cluster_threshold", # Optional (overrides layer_id if-set) "dir", # Optional (overrides layer_id if-set) "style", # Optional (overrides layer_id if-set) }] @param wms_browser: WMS Server's GetCapabilities & options (dict) {"name": T("MyLabel"), # Name for the Folder in LayerTree "url": string # URL of GetCapabilities } @param catalogue_layers: Show all the enabled Layers from the GIS Catalogue Defaults to False: Just show the default Base layer @param legend: True: Show the GeoExt Legend panel, False: No Panel, "float": New floating Legend Panel @param toolbar: Show the Icon Toolbar of Controls @param area: Show the Area tool on the Toolbar @param nav: Show the Navigation controls on the Toolbar @param save: Show the Save tool on the Toolbar @param search: Show the Geonames search box (requires a username to be configured) @param mouse_position: Show the current coordinates in the bottom-right of the map. 3 Options: 'normal', 'mgrs', False (defaults to checking deployment_settings, which defaults to 'normal') @param overview: Show the Overview Map (defaults to checking deployment_settings, which defaults to True) @param permalink: Show the Permalink control (defaults to checking deployment_settings, which defaults to True) @param scaleline: Show the ScaleLine control (defaults to checking deployment_settings, which defaults to True) @param zoomcontrol: Show the Zoom control (defaults to checking deployment_settings, which defaults to True) @param mgrs: Use the MGRS Control to select PDFs {"name": string, # Name for the Control "url": string # URL of PDF server } @ToDo: Also add MGRS Search support: http://gxp.opengeo.org/master/examples/mgrs.html @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 callback: Code to run once the Map JavaScript has loaded @param plugins: an iterable of objects which support the following methods: .extend_gis_map(map) Client-side portion suppoprts the following methods: .addToMapWindow(items) .setup(map) """ }}} === 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: * http://trac.openlayers.org/wiki/Documentation#BeforeGettingStarted--TheTechnologiesBehindOpenLayers * http://trac.openlayers.org/wiki/NewToOpenLayers 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 [http://geoext.org GeoExt] (formerly [https://trac.mapfish.org/trac/mapfish/wiki/HowToUseWidgets MapFish client]) === How to debug WMS === * [https://addons.mozilla.org/en-US/firefox/addon/91406 WMS Inspector] - Firefox add-on === How to add a new Layer type === Assuming that !OpenLayers supports the layertype: ==== Model ==== {{{modules/s3db/gis.py}}} {{{ _gis_layer_types = ["newlayertype", "..."] table = self.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 settings.get_security_map() and not s3_has_role("MapAdmin"): unauthorised() resourcename = request.function tablename = "%s_%s" % (module, resourcename) table = s3db[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 postp(r, output): s3_action_buttons(r) return output response.s3.postp = postp output = s3_rest_controller() if not "gis" in response.view: response.view = "gis/" + response.view return output }}} ==== View ==== {{{views/gis/map_service_catalogue.html}}} {{{