Geospatial capabilities on Ruby

2,173 views
2,055 views

Published on

Presentation given at Conferencia Rails 2010 http://conferenciarails.org/ Given by Javier de la Torre and Fernando Blar

Published in: Technology

Geospatial capabilities on Ruby

  1. 1. RUBY Javier de la Torre GEOSPATIAL envisioning life CAPABILITIESIN Fernando Blat
  2. 2. A revolution going on... http://www.flickr.com/photos/toasty/1540997910/
  3. 3. “The future belongs to those who understand how to use location data, tools, and services successfully” http://www.flickr.com/photos/crschmidt/4972140289/
  4. 4. Google Maps as a disruptive technology
  5. 5. 5 The birth of mashups
  6. 6. 6 The birth of mashups
  7. 7. 7
  8. 8. 8 The birth of mashups
  9. 9. 9 The birth of mashups
  10. 10. Twitter geolocates
  11. 11. Social media sites
  12. 12. 12 http://vimeo.com/10453518
  13. 13. Mobile geo web
  14. 14. Otrobache.com
  15. 15. Otrobache.com
  16. 16. 16 Otrobache.com v2
  17. 17. Helping to save the world We like to work on stories and maps that matter
  18. 18. Crowdsourcing
  19. 19. Wikipedia 19 Wikipedia Text
  20. 20. 20 OpenStreetMapOpenStreetMap
  21. 21. 21
  22. 22. 22
  23. 23. 23 Haiti Earthquake http://www.flickr.com/photos/37913760@N03/4274633152/
  24. 24. 24 January 12, 2010 Peter Batty
  25. 25. 25 Imagery made available January 13 2010
  26. 26. 26 January 14, 2010 Peter Batty
  27. 27. 27 January 26, 2010 Peter Batty
  28. 28. 28 Damage Assesment Peter Batty
  29. 29. 29
  30. 30. 30
  31. 31. The movie
  32. 32. Data is improving!
  33. 33. Oldweather
  34. 34. 35
  35. 35. 36
  36. 36. How all this work? http://www.satimagingcorp.com/gallery/gis-layers.html
  37. 37. A very short GIS class POINT LINE POLYGON http://en.wikipedia.org/wiki/Geographic_information_system
  38. 38. Welcome to PostGIS!
  39. 39. Based on PostgreSQL Open Source Very mature Supported almost by every GIS software
  40. 40. “Manually” create geometries create table points (the_geom geometry, name varchar); insert into points values ('POINT(0 0)', 'Location1'); insert into points values ('POINT(5 0)', 'Location2'); insert into points values ('POINT(0 5)', 'Location3');
  41. 41. select name, ST_AsText(the_geom),  ST_Distance(the_geom, 'POINT(5 5)') from points; name  | astext  | distance ---------  + -------------- Location1 | POINT(0 0)  | 7.07106 Location2 | POINT(5 0)  | 5 Location3 | POINT(0 5)  | 5 (3 rows)
  42. 42. More than 600 functions
  43. 43. W W W . R E F R A C T I O N S . N E T Sample PostGIS Queries 3. Find all docks that are contained completely within a lake, not touching a lake bank. SELECT a.id FROM docks a, lakes b WHERE a.geom && b.geom AND ST_Relate(a.geom, b.geom, ‘ ’); SELECT a.id FROM docks a, lakes b WHERE a.geom && b.geom AND ST_Relate(a.geom, b.geom, ‘TFF ’); SELECT a.id FROM docks a, lakes b WHERE a.geom && b.geom AND ST_Relate(a.geom, b.geom, ‘TFFTFF ’); SELECT a.id FROM docks a, lakes b WHERE a.geom && b.geom AND ST_Relate(a.geom, b.geom, ‘TFFTFF212’); SELECT a.id FROM docks a, lakes b WHERE a.geom && b.geom AND ST_Relate(a.geom, b.geom, ‘TFFTFF212’);
  44. 44. What about the frontend Google Maps Openlayers Fusion Tables
  45. 45. Full GIS RIA on JS, HTML5...
  46. 46. Geoserver And for rendering maps? Fusion Tables
  47. 47. And what about Ruby?
  48. 48. In pure Ruby you can only model data
  49. 49. Classes to represent the data
  50. 50. Export and import it from formats such as KML, WKT, ...
  51. 51. But calculations are performed in the storage / search engine
  52. 52. http://georuby.rubyforge.org GeoRuby
  53. 53. Basic geometry classes: Point, MultiPoint, LineString, Polygon, MultiPolygon....
  54. 54. Parsers for importing data: GeorssParser, HexEWKBParser, EWKTParser
  55. 55. require 'rubygems' require 'geo_ruby' point = GeoRuby::SimpleFeatures::Point.from_lon_lat( -3.726489543914795, 40.453423411115494 ) puts point.y # => 40.4534234111155 puts point.x # => -3.72648954391479 puts point.as_kml # => => "<Point> n<coordinates>-3.72648954391479,40.4534234111155</ coordinates>n</Point>n" puts point.as_wkt # => "POINT(-71 33.2)"
  56. 56. PostGIS adapter
  57. 57. Original: http://rubyforge.org/projects/postgis-adapter Improvements for ProtectedPlanet.net http://github.com/tokumine/postgis_adapter
  58. 58. class CreateWadusPolygons1 < ActiveRecord::Migration def self.up create_table :wadus_polygons do |t| t.geometry :the_geom, :srid => 4326, :null => false t.timestamps end end def self.down drop_table :wadus_polygons end end
  59. 59. class WadusPoint < ActiveRecord::Base has_geom :the_geom => :point end class WadusPolygon < ActiveRecord::Base has_geom :the_geom => :polygon end
  60. 60. wpl = WadusPolygon.new p1 = Point.from_lon_lat(-3.7271440029144287, 40.45342545209858) p2 = Point.from_lon_lat(-3.725684881210327, 40.45358056663219) p3 = Point.from_lon_lat(-3.72560977935791, 40.45302541822783) p4 = Point.from_lon_lat(-3.7267684936523438, 40.45290295840354) wpl.the_geom = Polygon.from_points([[p1, p2, p3, p4]]) wc = WadusPoint.new wc.the_geom = Point.from_lon_lat(-3.726392984390259, 40.45302541822783) wc.save wpl.contains?(wc)
  61. 61. Where is the magic? How the ruby library implements those PostGIS functions?
  62. 62. # postgis_adapter/lib/postgis_functions/class.rb def contains(p, srid=4326) find(:all, :conditions => ["ST_Contains(geom, GeomFromText('POINT(#{p.x} #{p.y})', #{srid}))"]) end
  63. 63. # Order by distance def close_to(p, opts = {}) srid = opts.delete(:srid) || 4326 opts.merge!(:order => "ST_Distance(geom, GeomFromText ('POINT(#{p.x} #{p.y})', #{srid}))") find(:all, opts) end
  64. 64. http://github.com/fragility/ spatial_adapter Spatial Adapter
  65. 65. ActiveRecord adapter that supports MySQL spatial extensions and PostGIS
  66. 66. Supports migrations, data types, and geospatial indexes
  67. 67. Uses GeoRuby for data modeling
  68. 68. http://geokit.rubyforge.org/ Geokit Ruby & Rails
  69. 69. https://github.com/andre/geokit- gem Gem
  70. 70. Calculate distance between two points Geocoding using Google, Yahoo... geocoders Rectangular bounds calculations
  71. 71. Rails Plugin
  72. 72. ActiveRecord distance-based finders IP-based location lookup utilizing hostip.info A before_filter helper to geocoder the user's location based on IP address, and retain the location in a cookie. 
  73. 73. class Item < ActiveRecord::Base acts_as_mappable :default_units => :miles, :default_formula => :sphere, :distance_field_name => :distance, :lat_column_name => :lat, :lng_column_name => :long end
  74. 74. def close_items(limit = 10) Item.find :all, :origin => [lat,long], :order => 'distance ASC', :limit => limit, :conditions => "id != #{self.id}" end
  75. 75. SELECT *, (ACOS(least(1,COS(0.688863980396179)*COS(-0.00643627778823306) *COS(RADIANS(items.lat))*COS(RADIANS(items.long))+ COS(0.688863980396179)*SIN(-0.00643627778823306)*COS(RADIANS (items.lat))*SIN(RADIANS(items.long))+ SIN(0.688863980396179)*SIN(RADIANS(items.lat))))*6376.77271) AS distance FROM `items` WHERE (((items.lat>39.4600136605259 AND items.lat<39.4779838100416 AND items.long>-0.380410723713182 AND items.long<-0.357132382365919)) AND ( (ACOS(least(1,COS(0.688863980396179)*COS(-0.00643627778823306) *COS(RADIANS(items.lat))*COS(RADIANS(items.long))+ COS(0.688863980396179)*SIN(-0.00643627778823306)*COS(RADIANS (items.lat))*SIN(RADIANS(items.long))+ SIN(0.688863980396179)*SIN(RADIANS(items.lat))))*6376.77271)
  76. 76. It's great, but take care with Active Record
  77. 77. Fusion tables gem http://github.com/tokumine/ fusion-tables
  78. 78. ferblape@gmail.com fernando.blat.es THANKS ;) @ferblape jatorre@vizzuality.com blog.vizzuality.com @jatorre

×