SlideShare a Scribd company logo
1 of 39
What is
geolocation?
identication of a real-world geographic
                location
identication of a real-world geographic
                location
                    =

        context
Brief history: early days


   many 1000s BC: smoke signals
   as early as 3200 BC: celestial navigation
   from 1000 BC: homing pigeons
   between 1100-1200 AD: the magnetic compass
Brief history: modern era


   early 1900s: radio triangulation
   1960s: satellite GPS
   1990s: automotive GPS navigation
Brief history: web era
   late 1990s: IP lookup
   mid 2000s: WiFi, GSM relevation
   2004: A-GPS on smartphones
Brief history: web era
   late 1990s: IP lookup
   mid 2000s: WiFi, GSM relevation
   2004: A-GPS on smartphones
Location-aware apps




 Later also Google, Facebook, and Twitter
Cool!
Let's join the party
Cool!
Let's join the party

      introducing:
 Stalk my Friends
1st step: display a map
    We'll use Google Maps

    # app/views/layouts/application.html.slim
    = javascript_include_tag https://maps.googleapis.com/maps/api/js


    // app/assets/javascripts/maps.js
    $(document).ready(function() {
        var mapOptions = {
            zoom: 8,
            center: new google.maps.LatLng(43.7710332, 11.2480006),
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map($(’#map’)[0], mapOptions);
    });

git: google maps
2nd step: geolocate
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
            function(p) {
                var latlng = new google.maps.LatLng(p.coords.latitude,
                                                    p.coords.longitude);
                $(’span#position’).text(latlng);
                if (myMarker) myMarker.setMap(null);
                myMarker = new google.maps.Marker(
                    {position: latlng, map: map, title: This is me}
                );
            },
            function(error) {
                alert(error.message);
            },
            {maximumAge: 600000}
        );
    }
    else { console.error(No HTML5? What are you using, IE6?); }
git: HTML5 geolocation
Geolocation API
supported by all current browers
location sources:
  1. GPS
  2. WiFi/Bluetooth MAC address
  3. GSM/CDMA cell IDs
  4. IP address
one-shot vs continuous
Geocode
 New feature: set the position manually.
Geocode
 New feature: set the position manually.
 We need to geocode the address.
Geocode
 New feature: set the position manually.
 We need to geocode the address.
 Several services:
     Google: 2.500 requests/day [1]
     Yahoo!: 50.000 requests/day [2]
     Bing: 50.000 requests/day [3]
     Nominatim: 1 request/second [4]
     FreeGeoIP: 1000 requests/hour [5]
     Geocoder.ca and Geocoder.us: ?
     many others...
Gems for geocode


   Geokit (deprecated, still lacks support for Rails 3) [7]
   Graticule [6]
   Geocoder [8]
Geocoder gem in action
 # Gemfile
 gem geocoder


 # map_controller.rb
 def geocode
   position = Geocoder.coordinates(params[:query])
   respond_to do |wants|
     wants.json { render :json = position }
   end
 end


 // applications.js
 $(’[data-action=cheat]’).click(function() {
     $.getJSON(’/geocode/’, {query: $(’#address’).val()}, map.cheat);
 });    git: geocoding
Awesome! We have a user position.
    Now to interact with other users we need:
store lat/long (and address, eventually) in a DB
query the DB for nearby points
1st approach: D.I.Y. I
 # migration
 class CreateUsers  ActiveRecord::Migration
   def change
     create_table :users do |t|
       t.string :name
       t.float :latitude
       t.float :longitude
       t.string :address

       t.timestamps
     end
   end
 end
1st approach: D.I.Y. II

 # app/controllers/users_controller.rb
 class UsersController  ApplicationController
   respond_to :json

   def index
     @users = @user.nearbys(params[:radius])
     respond_with @users
   end
 end
1st approach: D.I.Y. III

 # app/models/user.rb
 class User  ActiveRecord::Base
   attr_accessible :address, :latitude, :longitude, :name

   def nearbys(radius)
   # ... oh s@#!t
   end
 end
Let’s do some math

 Earth is a sphere: coordinates are in degree, distance is in
 meters.
 Solve the second (inverse) geodetic problem
 Given two points, determine the azimuth and length of the
 line (straight line, arc or geodesic) that connects them. [9]

     spherical model: Haversine formula (approximation)
     oblate spheroid model: Vincenty's formulae
Haversine formula

  d = 2r arcsin   h(φ2 − φ1 ) + cos(φ1 ) cos(φ2 ) h(ψ2 − ψ1 )                   (1)


    =2 r arcsin   sin2
                         φ2 − φ1
                            2
                                    + cos(φ1 ) cos(φ2 ) sin2
                                                                ψ2 − ψ1
                                                                   2
                                                                                (2)



 where:
     h() is the haversine function: h(θ) = sin(θ/2)              2
                                                                     =   1−cos(θ)
                                                                            2

     d distance
     r radius of the sphere (6371.0 km)
     φ1 , φ2 latitude of point 1 and latitude of point 2
     ψ1 , ψ2 longitude of point 1 and longitude of point 2
Geocoder to the rescue!
    # app/models/user.rb
    geocoded_by :address
    reverse_geocoded_by :latitude, :longitude
    after_validation :reverse_geocode


    # app/controllers/users_controller.rb
    def index
      @users = @user.nearbys(params[:radius])
      respond_with @users
    end

    Geocoder implements the Haversine formula
    directly in the SQL query.
git: Geocoder backend
Geocoder goodies
 # Nearest point
 user = User.near(Firenze, 50, :order = distance).first

 # distance from arbitrary point to user
 user.distance_from([40.714, 11.234])

 # Find the bearing (direction) between places
 bearing = user.bearing_to(Paris, France)
 Geocoder::Calculations.compass_point(bearing)
   = NW

 # find the geographic center (aka center of gravity)
 polygon = [user1, user2, [40.22,-73.99], user4]
 Geocoder::Calculations.geographic_center(polygon)
   = [35.14968, -90.048929]
Geocoder considerations

 Pros
   simple and easy to use

 Cons
   only circle areas
   SLOW (depends on the DBMS)
2nd approach: PostGIS




 PostGIS [10] is an extention for PostgreSQL that adds
 support for geographic objects.
 Alternatives are:
     MySQL: implements the datatype geometry
     Sqlite: with SpatiaLite extension
PostGIS setup
 # install on a ubuntu box
 sudo apt-get install postgresql-9.1-postgis


 # prepare the db
 createdb template_postgis
 createlang plpgsql template_postigs
 psql -Upostgres -d template_postgis -f   [...]/postgis.sql
 psql -Upostgres -d template_postgis -f   [...]/spatial_ref_sys.sql
 psql -Upostgres -d template_postgis -f   [...]/postgis_comments.sql
 # inside postgres console
 UPDATE pg_database SET datistemplate =   TRUE
 WHERE datname = ’template_postgis’;
PostGIS features

 PostGIS follows the OpenGIS Simple Features
 Specication for SQL [11]
     data types for points, linestrings, polygons, multipoints,
     multilinestrings, multipolygons and geometrycollections
     functions for measurement like area, distance, length
     and perimeter
     spatial indexes for high speed spatial querying
PostGIS with Ruby


 We'll use gem activerecord-postgis-adapter
 to integrate postgis data types in ActiveRecord.
ActiveRecord PostGIS
 # config/database.yml
 development:
   adapter: postgis
   encoding: unicode
   database: stalk_my_friends
   pool: 5
   username: nebirhos
   template: template_postgis


 # migration
 add_column :users, :position, :point, :geographic = true
 add_index :users, :position, :spatial = true


 # app/models/user.rb
 self.rgeo_factory_generator = RGeo::Geographic.simple_mercator_factory
 # SRID 4326, used by Google Maps
PostGIS query


     # app/models/user.rb
     def nearbys(radius)
       radius = radius.to_i*1000
       User.where( ST_Distance(position, ?, false) = ? ,
                   position, radius ).where(id  ?, id)
     end




git: master
Questions?
Thanks for watching!

 Francesco Disperati | @nebirhos
                http://nebirhos.com

 Source code of the demo app available at
 https://github.com/nebirhos/stalk-my-friends


    Special thanks to Cantiere Creativo and Silvia Shell
Random stuff cited
   Google Geocode API        https://developers.google.com/maps/documentation/geocoding/

   Yahoo! PlaceFinder      http://developer.yahoo.com/geo/placefinder/guide/responses.html

   Bing API    http://msdn.microsoft.com/en-us/library/ff701715.aspx

   Nominatim     http://wiki.openstreetmap.org/wiki/Nominatim

   FreeGeoIP    http://github.com/fiorix/freegeoip/blob/master/README.rst

   Graticule   http://graticule.rubyforge.org/

   Geokit   http://geokit.rubyforge.org/

   Geocoder    http://www.rubygeocoder.com/

   Geodesy on Wikipedia       http://en.wikipedia.org/wiki/Geodesy

   PostGIS   http://postgis.refractions.net/

   OpenGIS     http://www.opengeospatial.org/standards/sfs

   PostGIS ActiveRecord Adapter            https://github.com/dazuma/activerecord-postgis-adapter

More Related Content

Similar to Geolocation on Rails

OSCON july 2011
OSCON july 2011OSCON july 2011
OSCON july 2011
chelm
 
Geo distance search with my sql presentation
Geo distance search with my sql presentationGeo distance search with my sql presentation
Geo distance search with my sql presentation
GSMboy
 
Geospatial Enhancements in MongoDB 2.4
Geospatial Enhancements in MongoDB 2.4Geospatial Enhancements in MongoDB 2.4
Geospatial Enhancements in MongoDB 2.4
MongoDB
 
Python en la Plataforma ArcGIS
Python en la Plataforma ArcGISPython en la Plataforma ArcGIS
Python en la Plataforma ArcGIS
Xander Bakker
 
Mashup caravan android-talks
Mashup caravan android-talksMashup caravan android-talks
Mashup caravan android-talks
honjo2
 

Similar to Geolocation on Rails (20)

Geopy module in python
Geopy module in pythonGeopy module in python
Geopy module in python
 
Geo search introduction
Geo search introductionGeo search introduction
Geo search introduction
 
OSCON july 2011
OSCON july 2011OSCON july 2011
OSCON july 2011
 
Sample document
Sample documentSample document
Sample document
 
Geo distance search with my sql presentation
Geo distance search with my sql presentationGeo distance search with my sql presentation
Geo distance search with my sql presentation
 
Geospatial Enhancements in MongoDB 2.4
Geospatial Enhancements in MongoDB 2.4Geospatial Enhancements in MongoDB 2.4
Geospatial Enhancements in MongoDB 2.4
 
2017 RM-URISA Track: Spatial SQL - The Best Kept Secret in the Geospatial World
2017 RM-URISA Track:  Spatial SQL - The Best Kept Secret in the Geospatial World2017 RM-URISA Track:  Spatial SQL - The Best Kept Secret in the Geospatial World
2017 RM-URISA Track: Spatial SQL - The Best Kept Secret in the Geospatial World
 
Gmaps Railscamp2008
Gmaps Railscamp2008Gmaps Railscamp2008
Gmaps Railscamp2008
 
Geolocation
GeolocationGeolocation
Geolocation
 
Python en la Plataforma ArcGIS
Python en la Plataforma ArcGISPython en la Plataforma ArcGIS
Python en la Plataforma ArcGIS
 
Geopy Module in Python
Geopy Module in PythonGeopy Module in Python
Geopy Module in Python
 
Mashup caravan android-talks
Mashup caravan android-talksMashup caravan android-talks
Mashup caravan android-talks
 
GeoDjango & HTML5 Geolocation
GeoDjango & HTML5 GeolocationGeoDjango & HTML5 Geolocation
GeoDjango & HTML5 Geolocation
 
Geolocation and Mapping
Geolocation and MappingGeolocation and Mapping
Geolocation and Mapping
 
Pycon2011
Pycon2011Pycon2011
Pycon2011
 
GeoAdmin API & Mobile API, 2012
GeoAdmin API & Mobile API, 2012GeoAdmin API & Mobile API, 2012
GeoAdmin API & Mobile API, 2012
 
Saving Gaia with GeoDjango
Saving Gaia with GeoDjangoSaving Gaia with GeoDjango
Saving Gaia with GeoDjango
 
Building Location-Aware Apps using Open Source (AnDevCon SF 2014)
Building Location-Aware Apps using Open Source (AnDevCon SF 2014)Building Location-Aware Apps using Open Source (AnDevCon SF 2014)
Building Location-Aware Apps using Open Source (AnDevCon SF 2014)
 
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
 
Opensource gis development - part 2
Opensource gis development - part 2Opensource gis development - part 2
Opensource gis development - part 2
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governance
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 

Geolocation on Rails

  • 1.
  • 3. identication of a real-world geographic location
  • 4. identication of a real-world geographic location = context
  • 5. Brief history: early days many 1000s BC: smoke signals as early as 3200 BC: celestial navigation from 1000 BC: homing pigeons between 1100-1200 AD: the magnetic compass
  • 6. Brief history: modern era early 1900s: radio triangulation 1960s: satellite GPS 1990s: automotive GPS navigation
  • 7. Brief history: web era late 1990s: IP lookup mid 2000s: WiFi, GSM relevation 2004: A-GPS on smartphones
  • 8. Brief history: web era late 1990s: IP lookup mid 2000s: WiFi, GSM relevation 2004: A-GPS on smartphones
  • 9. Location-aware apps Later also Google, Facebook, and Twitter
  • 11. Cool! Let's join the party introducing: Stalk my Friends
  • 12.
  • 13. 1st step: display a map We'll use Google Maps # app/views/layouts/application.html.slim = javascript_include_tag https://maps.googleapis.com/maps/api/js // app/assets/javascripts/maps.js $(document).ready(function() { var mapOptions = { zoom: 8, center: new google.maps.LatLng(43.7710332, 11.2480006), mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map($(’#map’)[0], mapOptions); }); git: google maps
  • 14. 2nd step: geolocate if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( function(p) { var latlng = new google.maps.LatLng(p.coords.latitude, p.coords.longitude); $(’span#position’).text(latlng); if (myMarker) myMarker.setMap(null); myMarker = new google.maps.Marker( {position: latlng, map: map, title: This is me} ); }, function(error) { alert(error.message); }, {maximumAge: 600000} ); } else { console.error(No HTML5? What are you using, IE6?); } git: HTML5 geolocation
  • 15. Geolocation API supported by all current browers location sources: 1. GPS 2. WiFi/Bluetooth MAC address 3. GSM/CDMA cell IDs 4. IP address one-shot vs continuous
  • 16.
  • 17. Geocode New feature: set the position manually.
  • 18. Geocode New feature: set the position manually. We need to geocode the address.
  • 19. Geocode New feature: set the position manually. We need to geocode the address. Several services: Google: 2.500 requests/day [1] Yahoo!: 50.000 requests/day [2] Bing: 50.000 requests/day [3] Nominatim: 1 request/second [4] FreeGeoIP: 1000 requests/hour [5] Geocoder.ca and Geocoder.us: ? many others...
  • 20. Gems for geocode Geokit (deprecated, still lacks support for Rails 3) [7] Graticule [6] Geocoder [8]
  • 21. Geocoder gem in action # Gemfile gem geocoder # map_controller.rb def geocode position = Geocoder.coordinates(params[:query]) respond_to do |wants| wants.json { render :json = position } end end // applications.js $(’[data-action=cheat]’).click(function() { $.getJSON(’/geocode/’, {query: $(’#address’).val()}, map.cheat); }); git: geocoding
  • 22. Awesome! We have a user position. Now to interact with other users we need: store lat/long (and address, eventually) in a DB query the DB for nearby points
  • 23. 1st approach: D.I.Y. I # migration class CreateUsers ActiveRecord::Migration def change create_table :users do |t| t.string :name t.float :latitude t.float :longitude t.string :address t.timestamps end end end
  • 24. 1st approach: D.I.Y. II # app/controllers/users_controller.rb class UsersController ApplicationController respond_to :json def index @users = @user.nearbys(params[:radius]) respond_with @users end end
  • 25. 1st approach: D.I.Y. III # app/models/user.rb class User ActiveRecord::Base attr_accessible :address, :latitude, :longitude, :name def nearbys(radius) # ... oh s@#!t end end
  • 26. Let’s do some math Earth is a sphere: coordinates are in degree, distance is in meters. Solve the second (inverse) geodetic problem Given two points, determine the azimuth and length of the line (straight line, arc or geodesic) that connects them. [9] spherical model: Haversine formula (approximation) oblate spheroid model: Vincenty's formulae
  • 27. Haversine formula d = 2r arcsin h(φ2 − φ1 ) + cos(φ1 ) cos(φ2 ) h(ψ2 − ψ1 ) (1) =2 r arcsin sin2 φ2 − φ1 2 + cos(φ1 ) cos(φ2 ) sin2 ψ2 − ψ1 2 (2) where: h() is the haversine function: h(θ) = sin(θ/2) 2 = 1−cos(θ) 2 d distance r radius of the sphere (6371.0 km) φ1 , φ2 latitude of point 1 and latitude of point 2 ψ1 , ψ2 longitude of point 1 and longitude of point 2
  • 28. Geocoder to the rescue! # app/models/user.rb geocoded_by :address reverse_geocoded_by :latitude, :longitude after_validation :reverse_geocode # app/controllers/users_controller.rb def index @users = @user.nearbys(params[:radius]) respond_with @users end Geocoder implements the Haversine formula directly in the SQL query. git: Geocoder backend
  • 29. Geocoder goodies # Nearest point user = User.near(Firenze, 50, :order = distance).first # distance from arbitrary point to user user.distance_from([40.714, 11.234]) # Find the bearing (direction) between places bearing = user.bearing_to(Paris, France) Geocoder::Calculations.compass_point(bearing) = NW # find the geographic center (aka center of gravity) polygon = [user1, user2, [40.22,-73.99], user4] Geocoder::Calculations.geographic_center(polygon) = [35.14968, -90.048929]
  • 30. Geocoder considerations Pros simple and easy to use Cons only circle areas SLOW (depends on the DBMS)
  • 31. 2nd approach: PostGIS PostGIS [10] is an extention for PostgreSQL that adds support for geographic objects. Alternatives are: MySQL: implements the datatype geometry Sqlite: with SpatiaLite extension
  • 32. PostGIS setup # install on a ubuntu box sudo apt-get install postgresql-9.1-postgis # prepare the db createdb template_postgis createlang plpgsql template_postigs psql -Upostgres -d template_postgis -f [...]/postgis.sql psql -Upostgres -d template_postgis -f [...]/spatial_ref_sys.sql psql -Upostgres -d template_postgis -f [...]/postgis_comments.sql # inside postgres console UPDATE pg_database SET datistemplate = TRUE WHERE datname = ’template_postgis’;
  • 33. PostGIS features PostGIS follows the OpenGIS Simple Features Specication for SQL [11] data types for points, linestrings, polygons, multipoints, multilinestrings, multipolygons and geometrycollections functions for measurement like area, distance, length and perimeter spatial indexes for high speed spatial querying
  • 34. PostGIS with Ruby We'll use gem activerecord-postgis-adapter to integrate postgis data types in ActiveRecord.
  • 35. ActiveRecord PostGIS # config/database.yml development: adapter: postgis encoding: unicode database: stalk_my_friends pool: 5 username: nebirhos template: template_postgis # migration add_column :users, :position, :point, :geographic = true add_index :users, :position, :spatial = true # app/models/user.rb self.rgeo_factory_generator = RGeo::Geographic.simple_mercator_factory # SRID 4326, used by Google Maps
  • 36. PostGIS query # app/models/user.rb def nearbys(radius) radius = radius.to_i*1000 User.where( ST_Distance(position, ?, false) = ? , position, radius ).where(id ?, id) end git: master
  • 38. Thanks for watching! Francesco Disperati | @nebirhos http://nebirhos.com Source code of the demo app available at https://github.com/nebirhos/stalk-my-friends Special thanks to Cantiere Creativo and Silvia Shell
  • 39. Random stuff cited Google Geocode API https://developers.google.com/maps/documentation/geocoding/ Yahoo! PlaceFinder http://developer.yahoo.com/geo/placefinder/guide/responses.html Bing API http://msdn.microsoft.com/en-us/library/ff701715.aspx Nominatim http://wiki.openstreetmap.org/wiki/Nominatim FreeGeoIP http://github.com/fiorix/freegeoip/blob/master/README.rst Graticule http://graticule.rubyforge.org/ Geokit http://geokit.rubyforge.org/ Geocoder http://www.rubygeocoder.com/ Geodesy on Wikipedia http://en.wikipedia.org/wiki/Geodesy PostGIS http://postgis.refractions.net/ OpenGIS http://www.opengeospatial.org/standards/sfs PostGIS ActiveRecord Adapter https://github.com/dazuma/activerecord-postgis-adapter