Day 6 - PostGIS

26
Introducing PostGIS

Transcript of Day 6 - PostGIS

Page 1: Day 6 - PostGIS

Introducing PostGIS

Page 2: Day 6 - PostGIS

What is Geospatial

• Most common use

– Narrow a search within a distance from a point of origin

– Sort by that distance

Page 3: Day 6 - PostGIS

Distance Formulas

• Flat-surface formulae– Spherical Earth projected to a plane– Ellipsoidal Earth projected to a plane– Polar coordinate flat-Earth formula

• Spherical-surface formulae– Haversine– Tunnel distance

• Ellipsoidal-surface formulae– Lambert’s formula for long lines– Bowring’s method for short lines

Page 4: Day 6 - PostGIS

Here’s one example

Page 5: Day 6 - PostGIS

What you usually care about

• Given 2 latitude and longitude points

– Calculate the distance so we can find what’s close

• This is the common capability of databases with “geospatial” support

Page 6: Day 6 - PostGIS

A few options…

• Do the math in a query

• Here’s what it looks like in SQL– (ACOS(least(1,COS(0.607198022186895)*COS(-

1.4410239410591847)*COS(RADIANS(latitude))*COS(RAD

IANS(longitude)) + COS(0.607198022186895)*SIN(-

1.4410239410591847)*COS(RADIANS(latitude))*SIN(RAD

IANS(longitude)) +

SIN(0.607198022186895)*SIN(RADIANS(latitude))))*39

63.19)) <= 25)

– Calculating within 25 miles of a point of origin based on an origin point

– You can do that in any database (it’s just math)

– Very intense query that slows as your dataset grows

– This…is not using an index

Page 7: Day 6 - PostGIS

Speed that up

• Distance query a subset instead

• Use the lat/lng to create query a box around the boundary

• Queried with a numerical index

• Then check the distance from center for the subset

• NOTE: Doing this as part of another query is a lot easier with multi-index queries

Page 8: Day 6 - PostGIS

And here’s what THAT looks like

WHERE (

latitude > 34.42845936786603

AND latitude < 35.15130863213399

AND longitude > -83.00467808012291

AND longitude < -82.12450191987708

)

AND

( (ACOS(least(1,COS(0.607198022186895)*COS(-1.4410239410591847)*COS(RADIANS(latitude))*COS(RADIANS(longitude))+

COS(0.607198022186895)*SIN(-1.4410239410591847)*COS(RADIANS(latitude))*SIN(RADIANS(longitude))+

SIN(0.607198022186895)*SIN(RADIANS(latitude))))*3963.19)

) <= 25)

Simple, am I right?

Also, you need to drop that distance formula into the ORDER BY clause too.

Page 9: Day 6 - PostGIS

There’s a Gem for that!

Geokithttps://github.com/geokit/geokit• Distance calculations between 2 points

– Multiple formulas and units of measure

• Multiple providers for Geocoding different data– Addresses

• Yahoo• Geocoder.us/.ca• Geonames• Bing • Yandex• MapQuest• Geocode.io• Mapbox• Google• FCC• Open Street Map

– IP Address• hostip.info• Geoplugin.net• RIPE• MaxMind (HIGHLY RECOMMEND)• freegeoip.net

Geokit Rails (any database)https://github.com/geokit/geokit-rails• Premium Rails Integration• ActiveRecord distance finders• IP based location lookup• Cookie based user location tracking• Scopes: within, beyond, in_range, in_bounds,

closest, farthest, by_distance• Generate the SQL• Auto-Geocoding• Mixin

class Location < ActiveRecord::Base

acts_as_mappable :default_units => :miles,

:default_formula => :sphere,

:distance_field_name => :distance,

:lat_column_name => :lat,

:lng_column_name => :lng

end

Page 10: Day 6 - PostGIS

Actually, there’s several…

RGeo

• Adapters for– MySQL

– SQLite

– PostGIS

• Process GeoJSON

• Read shapefiles

• Uses C++ extensions for processing

Geocoder• Object Geocoding

– IP– Address

• Reverse Geocoding– Address from lat/lng or IP

• Center of Multiple Locations• Geographic Queries

– Near / nearby– Distance– Direction

• Easier to use• Seems to be some dispute about

accuracy of data

Page 11: Day 6 - PostGIS

What about PostgreSQL?

• Provide database functions to handle this calculations

– Distance in straight line or great circle

– Convert lat/lng to point

– Get lat/lng from a point

– Calculate containment within a cube

• Point datatype

– Operator to get distance between

Earth Distance extension

http://www.postgresql.org/docs/9.2/static/earthdistance.html

Cube based

Point based

Page 12: Day 6 - PostGIS

SO WHAT DOES POSTGIS DO THEN?

Funny you should ask…

Page 13: Day 6 - PostGIS

EVERYTHING

Seriously…it does pretty much everything

Page 14: Day 6 - PostGIS

Import and Export Data

• Import CSV• Import/export with GDAL (Geospatial Abstraction

Library) – Shapefiles– OGR– Geospatial vector data files– OpenStreetMap data (openstreetmap.org)– Raster datasets

• Import OGR files• ETL migration tools

– GeoKettle

Page 15: Day 6 - PostGIS

GIS Desktop Software

Open Source

• OpenJump

• QuantumGIS

• uDig

• GvSig

• OrbisGIS

• PostGIS Viewer

• pgAdmin plugin

Commercial

• CadCorp SIS

• Manifold.net

• MapInfo Professional

• AutoCAD

• ESRI ArcGIS

Page 16: Day 6 - PostGIS

Mapping Servers Integration

• Mapserver

• GeoServer

• Deegree

• QGIS Server

• MapGuide

Page 17: Day 6 - PostGIS

Data: OpenStreetMap

Page 18: Day 6 - PostGIS

Data: US Census

Page 19: Day 6 - PostGIS

Data: WorldClim

Page 20: Day 6 - PostGIS

US Geological Survey

Page 21: Day 6 - PostGIS

Natural Earth

Page 22: Day 6 - PostGIS

MaxMind GeoIP

Web Services / API

Constantly Updated Databases

Free and Paid Versions

Check your IP to try it out

https://www.maxmind.com/en/locate_my_ip

Page 23: Day 6 - PostGIS

Working with Data

• Datatypes– Geography

• Ellipsoidal spatial data

– Geometry• Planar spatial data

• Indexes• Topology• Spatial Joins• 3D

– Mapping (building, etc)– Image generation

• pgRoute– Generate driving route

• Generate raster images from SQL queries

• Spatial Relationship Functions– ST_Contains– ST_Covers– ST_Crosses– ST_DWithin– ST_Intersects– ST_Distance

• Clustered Queries for Huge Datasets

Page 24: Day 6 - PostGIS

Fun data tricks

• Use a TRIGGER to populate a geographic data column for transparent indexing

• Create a Geospatial View

• Use table inheritance to centralize commonality among different data types

– Geographic Data

– Search Data

Page 25: Day 6 - PostGIS

AR PostGIS Adapter

Migrations

create_table :locations do |t|

t.column :shape1, :geometry

t.geometry :shape2

t.line_string :path, :srid => 3785

t.point :lonlat, :geographic => true

t.point :lonlatheight, :geographic => true, :has_z => true

t.index :lonlat, :spatial => true

end

Datatypes

:geometry -- Any geometric type:point -- Point data:line_string -- LineString data:polygon -- Polygon data:geometry_collection -- Any collection type:multi_point -- A collection of Points:multi_line_string -- A collection of LineStrings:multi_polygon -- A collection of Polygons

ActiveRecord

Location.where(:lonlat => 'POINT(-122 47)').first

Location.where("ST_Distance(latlon,'POINT(-122.330779 47.604828)') < 10000")

scope :distance_from, ->(lat, lon, dist) do

where(“ST_Distance(latlon, ‘POINT(? ?)’) < ?, lat, lon, dist)

end

Location.where("ST_Intersects(latlon,'POLYGON((

-122.19 47.68,

-122.2 47.675,

-122.19 47.67,

-122.19 47.68))')")

https://github.com/rgeo/activerecord-postgis-adapter

Features

• Uses Rgeo gem

• Spatial Migrations

• Spatial Datatype

• Spatial Queries

• Create / Update PostGIS DB

• Support central schema

Page 26: Day 6 - PostGIS

Assignment 2

• Refine and improve your application• Add authentication• Add authors (or some type of user) to created data• Display author info on your data• Implement simple_form somewhere• Add a new validation rule to a model• Add a page to show related data for an author• Use slim (or haml) to create one of your views

• Add a BASIC geographic capability (optional)– Use your own discretion for how deep you go– Suggestions / Ideas

• Geocode user IP addresses to get city/state/zip info• Add address fields to your data type to make it geographically relevant• Use a distance filter in search