Coder Social home page Coder Social logo

bradediger / postgis_adapter Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nofxx/postgis_adapter

2.0 4.0 0.0 163 KB

Fork of spatial_adapter to give postgis more love

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

License: Other

Ruby 100.00%

postgis_adapter's Introduction

PostgisAdapter

A plugin for ActiveRecord which manages the PostGIS geometric columns in a transparent way (that is like the other base data type columns). It also provides a way to manage these columns in migrations.

This fork adds handy methods to make geometrical calculations on postgis.

Postgis Manual - postgis.refractions.net/documentation/manual-svn

*PostGIS and Rails 2+ only*.

Install

If you are using Spatial Adapter, *remove it first*.

Dependencies

  • georuby

  • postgres 8.3+

  • postgis 1.3+

As gem:

sudo gem sources --add http://gems.github.com
sudo gem install nofxx-postgis_adapter

config.gem "nofxx-postgis_adapter", :lib => "postgis_adapter", :source => "http://gems.github.com"

As plugin:

script/plugin install git://github.com/nofxx/postgis_adapter.git

How to Use

Geometric columns in your ActiveRecord models now appear just like any other column of other basic data types. They can also be dumped in ruby schema mode and loaded in migrations the same way as columns of basic types.

Model

class TablePoint < ActiveRecord::Base
end

That was easy! As you see, there is no need to declare a column as geometric. The plugin will get this information by itself.

Here is an example of PostGIS row creation and access, using the model and the table defined above :

	pt = TablePoint.new(:data => "Hello!",:geom => Point.from_x_y(1,2))
	pt.save
	pt = TablePoint.first
	puts pt.geom.x
	=> 1

PostGIS Functions

Here are this fork additions. To use it:

class Street < ActiveRecord::Base
  acts_as_geom :line
end

...

@place  =   Poi.new(    :data  =>   **Point**      )
@park   =   Park.new(   :area  =>  **Polygon**     )
@street =   Street.new( :line  => **LineString**   )

Play!

@place.inside?(@park)
=> true

@place.in_bounds?(@park, 0.5) # margin
=> false

@place.outside?(@park)

@street.crosses?(@park)

@area.contains?(@place)

Polygons:

@park.area
=> 1345

@park.contains?(@point)
=> true

@park.overlaps?(@other_park)
=> false

Line Strings:

@street_east.intersects?(@street_west)
=> false

@street_central.length
=> 4508.53636

@street_central.length(:miles)
=> 2.81798593

@street.length_spheroid
=> 4.40853636

And for classes:

City.close_to(@point)
=> [Array of cities in order by distance...

Street.close_to(@point)
=> [Array streets in order by distance...

Country.contain(@point)
=> The Conutry that contains the point

Areas.contains(@point)
=> [Array of areas contains the point...

BBox Support

@area.strictly_left_of? @point

@area.overlaps_or_above? @street

...

completely_contained_by?
completely_contains?
overlaps_or_above?
overlaps_or_below?
overlaps_or_left_of?
overlaps_or_right_of?
strictly_above?
strictly_below?
strictly_left_of?
strictly_right_of?
interacts_with?
binary_equal?
same_as?

Or use a (almost) postgis like notation:

@area.bbox "<<", @point

@area.bbox "|>>", @point

@area.bbox "@",  @park

Warning

*To be fixed:*

This only supports one geom column per model. Still looking for the best way to implement a multi geom.

nofxx.lighthouseapp.com/projects/20712/tickets/3-multiple-geoms-in-model

Wiki

Check out the wiki pages (github.com/nofxx/postgis_adapter/wikis). For all functions.

Find_by

find_by_column has been redefined when column is of a geometric type. Instead of using the Rails default ‘=’ operator, for which I can’t see a definition for MySql spatial datatypes and which performs a bounding box equality test in PostGIS, it uses a bounding box intersection: && in PostGIS and MBRIntersects in MySQL, which can both make use of a spatial index if one is present to speed up the queries. You could use this query, for example, if you need to display data from the database: You would want only the geometries which are in the screen rectangle and you could use a bounding box query for that. Since this is a common case, it is the default. You have 2 ways to use the find_by_geom_column: Either by passing a geometric object directly, or passing an array with the 2 opposite corners of a bounding box (with 2 or 3 coordinates depending of the dimension of the data).

	Park.find_by_geom(LineString.from_coordinates([[1.4,5.6],[2.7,8.9],[1.6,5.6]]))

or

	Park.find_by_geom([[3,5.6],[19.98,5.9]])

In PostGIS, since you can only use operations with geometries with the same SRID, you can add a third element representing the SRID of the bounding box to the array. It is by default set to -1:

	Park.find_by_geom([[3,5.6],[19.98,5.9],123])

Database Tools

Migrations

Here is an example of code for the creation of a table with a geometric column in PostGIS, along with the addition of a spatial index on the column :

  ActiveRecord::Schema.define do
	  create_table :places do |t|
      t.string :name
    	t.point  :geom, :srid => 123, :with_z => true, :null => false
  	 
      t.timestamps
    end
	  add_index :table_points, :geom, :spatial=>true
  end

Fixtures

If you use fixtures for your unit tests, at some point, you will want to input a geometry. You could transform your geometries to a form suitable for YAML yourself everytime but the spatial adapter provides a method to do it for you: to_yaml. It works for both MySQL and PostGIS (although the string returned is different for each database). You would use it like this, if the geometric column is a point:

  fixture:
	  id: 1
	  data: HELLO
	  geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>

Annotate

If you are using annotate_models, check out this fork which adds geometrical annotations for PostgisAdapter and SpatialAdapter:

github.com/nofxx/annotate_models

Geometric data types

Ruby geometric datatypes are currently made available only through the GeoRuby library (georuby.rubyforge.org): This is where the Point.from_x_y in the example above comes from. It is a goal of a future release of the Spatial Adapter to support additional geometric datatype libraries, such as Ruby/GEOS, as long as they can support reading and writing of EWKB.

Warning

  • Since ActiveRecord seems to keep only the string values directly

returned from the database, it translates from these to the correct types everytime an attribute is read, which is probably ok for simple types, but might be less than efficient for geometries, since the EWKB string has to be parsed everytime. Also it means you cannot modify the geometry object returned from an attribute directly :

place = Place.first
place.the_geom.y=123456.7
  • Since the translation to a geometry is performed everytime the_geom

is read, the change to y will not be saved! You would have to do something like this :

place = Place.first
the_geom = place.the_geom
the_geom.y=123456.7
place.the_geom = the_geom

License

Spatial Adapter for Rails is released under the MIT license. Postgis Adapter is released under the MIT license.

Support

Tested using rails 2.2.2 / postgresql 8.3.5 / postgis 1.3.3 / linux / osx

Any questions, enhancement proposals, bug notifications or corrections:

PostgisAdapter

Project Tracker nofxx.lighthouseapp.com/projects/20712-postgis_adapter

SpatialAdapter

[email protected].

postgis_adapter's People

Contributors

nofxx avatar bradediger avatar

Stargazers

Angus H. avatar  avatar

Watchers

 avatar James Cloos avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.