SlideShare a Scribd company logo
GIS Tool in Drupal
PNW Drupal Summit - Seattle
    October 20th, 2012

  Mack Hardy & Tom Nightingale
        @AffinityBridge
History of Maps with Drupal Tools
Location Module,
proximity and filter
Server side geo_tools_in_drupal_pnw_2012
Server side geo_tools_in_drupal_pnw_2012
Storage and Import
Storage - GeoField
Where do we store data in drupal?


A common field format
for geodata
 • WKT
 • Lat Lon
 • Bounding
Server side geo_tools_in_drupal_pnw_2012
Spatial Import

How do we import data from external sources?

Shapefiles

KML files

Uses GeoPHP and ogr2ogr

Spatial module -> Saves as WKT -> Geofield

http://drupal.org/project/spatial
ogr2ogr

Wrapper module for the GDAL ogr2ogr library

- Spatial module calls ogr2ogr

- Converts data from source formats to WKT

http://drupal.org/project/ogr2ogr
Query
Sync_PostGIS Module

• Allows drupal to query PostGIS as a spatial query
  service, much in the way SOLR is used for search
• Syncs data from Drupal entities with geofields to
  PostGIS
• Provides query methods for testing intersection,
  within, buffer conditions

  http://drupal.org/project/sync_postgis
Sync_PostGIS Module
What does sync_postgis tell us?




  Intersections with other data points
  Within a buffer of 5km
Testing for Intersection
function geoquery_intersects($item1, $item2) {
  $params = array($item1, $item2);
  foreach ($params as &$param) {
    if (is_scalar($param)) {
      $param = array('entity_type' => 'node', 'eid' => $param);
    }
  }
  if ($connection = sync_postgis_get_postgis_connection()) {
    $geo_query = new syncPgQuery($connection);
    return $geo_query->booleanRelQuery('intersects',
$params[0], $params[1])->execute();
  }
Testing for Buffer Distance
function geoquery_dwithin($item1, $item2, $distance = 0, $srid = 4326)
{
  $params = array($item1, $item2);
  foreach ($params as &$param) {
    if (is_scalar($param)) {
      $param = array('entity_type' => 'node', 'eid' => $param);
    }
  }
  if ($connection = sync_postgis_get_postgis_connection()) {
    $geo_query = new syncPgQuery($connection, $srid);
    return $geo_query->booleanRelQuery('dwithin', $params[0],
$params[1], $distance)->execute();
  }
}
Displaying the results
With the results from the PostGIS
backend, we can show the user
useful information

In this case they know that

- target is in the protected area

- target intersects 2 traplines

- target is within a 5 km buffer of 4
other nodes of interest
Scaling
Beyond Vector Based Maps
We want to show huge datasets, the vector model requires
"painting" the data onto the map, which is computationally
expensive

Pre-rendering the dataset onto a tile, means the client can
load the data quickly, and tiles are easy to cache

Obvious downside of caching, is that it doesn't work well
with frequently changing data

Tilemill has been great for creating base tiles, but
regenerating the entire tileset when the data changes is
hard and time consuming
Comparing Vector vs MB Tiles
Vector - 2.30 MB of transfer - Client side render




Tiles - 529 kB of transfer - Server side render
Tilestache

Python application for serving tiles


tilestache takes inputs of :
--- mbtiles which are pre-generated
--- mapnik configuration (to generate tiles on the fly)
--- vector (geojson, arcjson)
--- combinations of these inputs as composite

We are generating using mapnik with PostGIS as a datasource

- provides a caching layer for serving tiles
Composite maps from PostGIS Data

• base map satellite images
• tilestache provides the data
  layers from PostGIS via mapnik
• leaflet map definition points to
  layers in the layer switcher




                    Image credit http://mike.teczno.com/notes/tilestache.html
WAX interactivity
• parcel data with tiles in JSON
• on mouseover and on click behaviours
• need to pre-cache WAX styling
WAX interactivity
WAX interactivity




  Demo
WAX interactivity




How UTF8 grid works
http://mapbox.com/demo/visiblemap/
Random Tools
Leaflet Draw
Leaflet Paste
Search API

Next we want to be able to return data items from SOLR
to a map

Search on non-geographic facets - just like a view

Search on geographic facets - facet controls pull data
from PostGIS, or use SOLRs spatial extensions

http://drupal.org/project/search_api_location
Discussion




mack@affinitybridge.com
 http://affinitybridge.com

More Related Content

Server side geo_tools_in_drupal_pnw_2012

  • 1. GIS Tool in Drupal PNW Drupal Summit - Seattle October 20th, 2012 Mack Hardy & Tom Nightingale @AffinityBridge
  • 2. History of Maps with Drupal Tools
  • 7. Storage - GeoField Where do we store data in drupal? A common field format for geodata • WKT • Lat Lon • Bounding
  • 9. Spatial Import How do we import data from external sources? Shapefiles KML files Uses GeoPHP and ogr2ogr Spatial module -> Saves as WKT -> Geofield http://drupal.org/project/spatial
  • 10. ogr2ogr Wrapper module for the GDAL ogr2ogr library - Spatial module calls ogr2ogr - Converts data from source formats to WKT http://drupal.org/project/ogr2ogr
  • 11. Query
  • 12. Sync_PostGIS Module • Allows drupal to query PostGIS as a spatial query service, much in the way SOLR is used for search • Syncs data from Drupal entities with geofields to PostGIS • Provides query methods for testing intersection, within, buffer conditions http://drupal.org/project/sync_postgis
  • 14. What does sync_postgis tell us? Intersections with other data points Within a buffer of 5km
  • 15. Testing for Intersection function geoquery_intersects($item1, $item2) { $params = array($item1, $item2); foreach ($params as &$param) { if (is_scalar($param)) { $param = array('entity_type' => 'node', 'eid' => $param); } } if ($connection = sync_postgis_get_postgis_connection()) { $geo_query = new syncPgQuery($connection); return $geo_query->booleanRelQuery('intersects', $params[0], $params[1])->execute(); }
  • 16. Testing for Buffer Distance function geoquery_dwithin($item1, $item2, $distance = 0, $srid = 4326) { $params = array($item1, $item2); foreach ($params as &$param) { if (is_scalar($param)) { $param = array('entity_type' => 'node', 'eid' => $param); } } if ($connection = sync_postgis_get_postgis_connection()) { $geo_query = new syncPgQuery($connection, $srid); return $geo_query->booleanRelQuery('dwithin', $params[0], $params[1], $distance)->execute(); } }
  • 17. Displaying the results With the results from the PostGIS backend, we can show the user useful information In this case they know that - target is in the protected area - target intersects 2 traplines - target is within a 5 km buffer of 4 other nodes of interest
  • 19. Beyond Vector Based Maps We want to show huge datasets, the vector model requires "painting" the data onto the map, which is computationally expensive Pre-rendering the dataset onto a tile, means the client can load the data quickly, and tiles are easy to cache Obvious downside of caching, is that it doesn't work well with frequently changing data Tilemill has been great for creating base tiles, but regenerating the entire tileset when the data changes is hard and time consuming
  • 20. Comparing Vector vs MB Tiles Vector - 2.30 MB of transfer - Client side render Tiles - 529 kB of transfer - Server side render
  • 21. Tilestache Python application for serving tiles tilestache takes inputs of : --- mbtiles which are pre-generated --- mapnik configuration (to generate tiles on the fly) --- vector (geojson, arcjson) --- combinations of these inputs as composite We are generating using mapnik with PostGIS as a datasource - provides a caching layer for serving tiles
  • 22. Composite maps from PostGIS Data • base map satellite images • tilestache provides the data layers from PostGIS via mapnik • leaflet map definition points to layers in the layer switcher Image credit http://mike.teczno.com/notes/tilestache.html
  • 23. WAX interactivity • parcel data with tiles in JSON • on mouseover and on click behaviours • need to pre-cache WAX styling
  • 26. WAX interactivity How UTF8 grid works http://mapbox.com/demo/visiblemap/
  • 30. Search API Next we want to be able to return data items from SOLR to a map Search on non-geographic facets - just like a view Search on geographic facets - facet controls pull data from PostGIS, or use SOLRs spatial extensions http://drupal.org/project/search_api_location

Editor's Notes

  1. Location module - geocoding and showing on a map Location module - proximity searches for points, small sets * some example of some old timey proximity tools *  Performance issues  as > 500 markers
  2. Make a simpler verison? Remove this slide?
  3. Make a simpler verison? Remove this slide?
  4. Now that the geodata is in postgis, we can pull the data from postgis into other applications some examples of this would be  tilestache, and tilemill
  5. Now that the geodata is in postgis, we can pull the data from postgis into other applications some examples of this would be  tilestache, and tilemill
  6. http://ctweb06.cantrusthosting.com:8888/fnfn-stories--water/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--roads/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--survey/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--sites/preview.html#10/58.6809/-121.8900
  7. http://ctweb06.cantrusthosting.com:8888/fnfn-stories--water/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--roads/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--survey/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--sites/preview.html#10/58.6809/-121.8900
  8. http://ctweb06.cantrusthosting.com:8888/fnfn-stories--water/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--roads/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--survey/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--sites/preview.html#10/58.6809/-121.8900
  9. http://ctweb06.cantrusthosting.com:8888/fnfn-stories--water/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--roads/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--survey/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--sites/preview.html#10/58.6809/-121.8900
  10. http://ctweb06.cantrusthosting.com:8888/fnfn-stories--water/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--roads/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--survey/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--sites/preview.html#10/58.6809/-121.8900
  11. http://ctweb06.cantrusthosting.com:8888/fnfn-stories--water/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--roads/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--survey/preview.html#10/58.6809/-121.8900 http://ctweb06.cantrusthosting.com:8888/fnfn-stories--sites/preview.html#10/58.6809/-121.8900