81
RUBY Javier de la Torre GEOSPATIAL envisioning life CAPABILITIES IN Fernando Blat

Geospatial capabilities on Ruby

Embed Size (px)

Citation preview

RUBYJavier de la Torre

GEOSPATIAL

envisioning life

CAPABILITIES IN

Fernando Blat

A revolution going on...

http://www.flickr.com/photos/toasty/1540997910/

“The future belongs to those who understand how to use location data, tools, and services successfully”

http://www.flickr.com/photos/crschmidt/4972140289/

Google Maps as a disruptive technology

5

The birth of mashups

6

The birth of mashups

7

8

The birth of mashups

9

The birth of mashups

Twitter geolocates

Social media sites

12

http://vimeo.com/10453518

Mobile geo web

Otrobache.com

Otrobache.com

16

Otrobache.com v2

Helping to save the world

We like to work on stories and maps that matter

Crowdsourcing

Wikipedia

19

Wikipedia

Text

20

OpenStreetMapOpenStreetMap

21

22

23

Haiti Earthquake

http://www.flickr.com/photos/37913760@N03/4274633152/

24

Haiti - January 12, 2010

January 12, 2010

Peter Batty

25

Imagery made availableJanuary 13 2010

26

Haiti - January 14, 2010

January 14, 2010

Peter Batty

27

Haiti - January 26, 2010

January 26, 2010

Peter Batty

28

Damage Assessment

Damage Assesment

Peter Batty

29

30

The movie

Data is improving!

Oldweather

35

36

How all this work?

http://www.satimagingcorp.com/gallery/gis-layers.html

A very short GIS class

POINTLINEPOLYGON

http://en.wikipedia.org/wiki/Geographic_information_system

Welcome to PostGIS!

Based on PostgreSQL

Open Source

Very mature

Supported almost by every GIS software

“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');

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)

More than 600 functions

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.idFROM docks a, lakes bWHERE a.geom && b.geomAND ST_Relate(a.geom, b.geom, ‘ ’);

SELECT a.idFROM docks a, lakes bWHERE a.geom && b.geomAND ST_Relate(a.geom, b.geom, ‘TFF ’);

SELECT a.idFROM docks a, lakes bWHERE a.geom && b.geomAND ST_Relate(a.geom, b.geom, ‘TFFTFF ’);

SELECT a.idFROM docks a, lakes bWHERE a.geom && b.geomAND ST_Relate(a.geom, b.geom, ‘TFFTFF212’);

SELECT a.idFROM docks a, lakes bWHERE a.geom && b.geomAND ST_Relate(a.geom, b.geom, ‘TFFTFF212’);

What about the frontend

Google Maps Openlayers

Fusion Tables

Full GIS RIA on JS, HTML5...

Geoserver

And for rendering maps?

Fusion Tables

And what about Ruby?

In pure Ruby you can only model data

Classes to represent the data

Export and import it from formats such as KML, WKT, ...

But calculations are performed in the storage / search engine

Basic geometry classes:

Point, MultiPoint, LineString, Polygon, MultiPolygon....

Parsers for importing data:

GeorssParser, HexEWKBParser, EWKTParser

require 'rubygems'require 'geo_ruby'

point = GeoRuby::SimpleFeatures::Point.from_lon_lat( -3.726489543914795, 40.453423411115494)

puts point.y# => 40.4534234111155puts point.x# => -3.72648954391479puts point.as_kml# => => "<Point>\n<coordinates>-3.72648954391479,40.4534234111155</coordinates>\n</Point>\n"puts point.as_wkt# => "POINT(-71 33.2)"

PostGIS adapter

Original:

http://rubyforge.org/projects/postgis-adapter

Improvements for ProtectedPlanet.net

http://github.com/tokumine/postgis_adapter

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 endend

class WadusPoint < ActiveRecord::Base has_geom :the_geom => :pointend

class WadusPolygon < ActiveRecord::Base has_geom :the_geom => :polygonend

wpl = WadusPolygon.newp1 = 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.newwc.the_geom = Point.from_lon_lat(-3.726392984390259, 40.45302541822783)wc.save

wpl.contains?(wc)

Where is the magic?

How the ruby library implements those PostGIS functions?

# 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

# Order by distancedef 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

ActiveRecord adapter that supports MySQL spatial extensions and PostGIS

Supports migrations, data types, and geospatial indexes

Uses GeoRuby for data modeling

Calculate distance between two points

Geocoding using Google, Yahoo... geocoders

Rectangular bounds calculations

Rails Plugin

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. 

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

def close_items(limit = 10) Item.find :all, :origin => [lat,long], :order => 'distance ASC', :limit => limit, :conditions => "id != #{self.id}"end

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)

It's great, but take care with Active Record