Changes between Initial Version and Version 1 of DeveloperGuidelines/GIS/InAction


Ignore:
Timestamp:
10/01/11 09:07:43 (14 years ago)
Author:
graeme
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DeveloperGuidelines/GIS/InAction

    v1 v1  
     1[[TOC]]
     2= How to use the GIS API within an application =
     3This mini guide will show you how to use the GIS code in an Eden Application to display a map. The features that will be developed include:
     4 * A map of the zoomed into the area of interest
     5 * Markers displayed on the map for each point of interest
     6 * A pop-up displaying additional information when a marker is clicked
     7 * Multiple map layers which can be selected and deselected by the user
     8The code for this guide is taken from the survey module and can be found (at the time or writing  in the controllers/survey.py/series_map() function
     9== Displaying the map ==
     10The display of the map is done with the show_map function
     11{{{
     12#!div style="font-size: 80%"
     13Code highlighting:
     14  {{{#!python
     15map = gis.show_map()
     16output["map"] = map
     17}}}
     18}}}
     19This will create a map and place it in a map container that has been added to the view. The relevant part of the view is as follows:
     20{{{
     21 <div class='survey_map-container'>
     22  {{try:}}
     23   {{=map}}
     24  {{except:}}
     25   {{pass}}
     26 </div>
     27}}}
     28This will display a plain map at the default zoom level. The next task will be to add some markers.
     29== Adding the markers ==
     30The API supports two mechanisms to add markers. The first is a simple list of latitude and longitude points. This is the features parameter and it adds non-interactive points. For the survey application interactive points were required and to the slightly more complex feature_queries parameter is required.
     31The first step is to create a query that will hold all of the points that are to be displayed. The code for this is as follows:
     32{{{
     33#!div style="font-size: 80%"
     34Code highlighting:
     35  {{{#!python
     36ctable = db.survey_complete
     37atable = db.survey_answer
     38gtable = db.gis_location
     39
     40series_name = response.s3.survey_getSeriesFromID(series_id)
     41question_id = response.s3.survey_getLocationQuestionsIDForSeries(series_id)
     42
     43query = (atable.question_id == question_id) & \
     44        (ctable.series_id == series_id) & \
     45        (atable.complete_id == ctable.id ) & \
     46        (atable.value == gtable.name)
     47
     48response_locations =  db(query).select(atable.complete_id,
     49                                       gtable.uuid,
     50                                       gtable.id,
     51                                       gtable.name,
     52                                       gtable.lat,
     53                                       gtable.lon,
     54                                      )
     55}}}
     56}}}
     57The above is a query which links several tables together, the series_id has been passed into the function. The name of the series and the question_id are obtained from calls to functions defined in the model. The linking of the tables requires the series_id and the question_id, it then retrieves data from the gis_location table.
     58Fully understanding this specific query is not essential to understanding how to add markers what is important is that you need construct a query that will return basic data from the gis_location table. The next step is to set up the features_query parameter, which can be done as follows:
     59{{{
     60#!div style="font-size: 80%"
     61Code highlighting:
     62  {{{#!python
     63feature_queries.append({ "name": "%s: Assessments" % series_name,
     64                         "query": response_locations,
     65                         "active": True })
     66}}}
     67}}}
     68This will create a layer with the name of the series_name and points that were set up by the query stored in response_locations. The active of true means that the layer will be turned on by default.
     69
     70Finally the feature layer needs to be added to the call to show_map()
     71{{{
     72#!div style="font-size: 80%"
     73Code highlighting:
     74  {{{#!python
     75map = gis.show_map(feature_queries = feature_queries)
     76}}}
     77}}}
     78== Adding colour to the marker ==
     79Some basic colour and shape can be added to the marker. These are added by extending the details returned by the query. A shape, size of the shape and colour of the shape can be added as follows:
     80{{{
     81#!div style="font-size: 80%"
     82Code highlighting:
     83  {{{#!python
     84response_colour_code = {-1:"#888888", # grey
     85                         0:"#000080", # blue
     86                         1:"#008000", # green
     87                         2:"#FFFF00", # yellow
     88                         3:"#FFA500", # orange
     89                         4:"#FF0000", # red
     90                         5:"#880088", # purple
     91                       }
     92if len(response_locations) > 0:
     93   for i in range( 0 , len( response_locations) ):
     94      complete_id = response_locations[i].survey_answer.complete_id
     95      response_locations[i].shape = "circle"
     96      response_locations[i].size = 5
     97      priority = analysisTool.priority(complete_id)
     98      response_locations[i].colour = response_colour_code[priority]
     99}}}
     100}}}
     101This will add small circular markers which are coloured depending upon a priority, which has been calculated by the call to analysisTool.priority(complete_id), again exactly how this works (and how the analysisTool object is created is not an important detail. The key is how the values are added to the response_location variable.
     102
     103The shapes that are currently supported are defined in the gis_feature_query() function in models/03_gis.py as follows:
     104{{{
     105"circle", "square", "star", "x", "cross", "triangle"
     106}}}
     107The markers have now been added but when they are displayed because it is still using the default zoom they have probably been merged into a single cluster marker.
     108== Zooming in to the required bounds ==
     109When multiple markers appear at the same location they are grouped together and replaced by a single cluster marker. If the zoom level is changed then more of the markers may take a unique location on the map and will be displayed using the feature marker.
     110The bounds of the map can be calculated by calling the get_bounds() function as follows:
     111{{{
     112#!div style="font-size: 80%"
     113Code highlighting:
     114{{{#!python
     115bounds = gis.get_bounds(response_locations.records)
     116}}}
     117}}}
     118This is then passed to the show_map function as follows:
     119{{{
     120#!div style="font-size: 80%"
     121Code highlighting:
     122{{{#!python
     123map = gis.show_map(feature_queries = feature_queries,
     124                   bbox = bounds,
     125                  )
     126}}}
     127}}}
     128== Adding a pop-up ==
     129The final feature to be added to the map is when clicking on the marker a pop-up appears displaying additional data. This is similar to the code that adds the marker and is placed in the same loop. The specific code is as follows:
     130{{{
     131#!div style="font-size: 80%"
     132Code highlighting:
     133{{{#!python
     134url = URL(c="survey",
     135          f="series",
     136          args=[series_id,
     137                "complete",
     138                complete_id,
     139                "read"
     140               ]
     141         )
     142response_locations[i].popup_url = url
     143response_locations[i].popup_label = response_locations[i].gis_location.name
     144}}}
     145}}}
     146Again the details of the url is not important although it is important to have a url that will return data suitable for an ajax call.