postgis_adapter 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,172 @@
1
+ module PostgisFunctions
2
+ ####
3
+ ###
4
+ ##
5
+ #
6
+ # LINESTRING
7
+ #
8
+
9
+ module LineStringFunctions
10
+
11
+ #
12
+ # Returns the 2D length of the geometry if it is a linestring, multilinestring,
13
+ # ST_Curve, ST_MultiCurve. 0 is returned for areal geometries. For areal geometries
14
+ # use 'perimeter'. Measurements are in the units of the spatial reference system
15
+ # of the geometry.
16
+ #
17
+ # Returns Float
18
+ #
19
+ def length
20
+ dis = postgis_calculate(:length, self).to_f
21
+ end
22
+
23
+ #
24
+ # Returns the 3-dimensional or 2-dimensional length of the geometry if it is
25
+ # a linestring or multi-linestring. For 2-d lines it will just return the 2-d
26
+ # length (same as 'length')
27
+ #
28
+ # Returns Float
29
+ #
30
+ def length_3d
31
+ dis = postgis_calculate(:length3d, self).to_f
32
+ end
33
+
34
+ #
35
+ # Calculates the length of a geometry on an ellipsoid. This is useful if the
36
+ # coordinates of the geometry are in longitude/latitude and a length is
37
+ # desired without reprojection. The ellipsoid is a separate database type and
38
+ # can be constructed as follows:
39
+ #
40
+ # SPHEROID[<NAME>,<SEMI-MAJOR AXIS>,<INVERSE FLATTENING>]
41
+ #
42
+ # Example:
43
+ # SPHEROID["GRS_1980",6378137,298.257222101]
44
+ #
45
+ # Defaults to:
46
+ #
47
+ # SPHEROID["IERS_2003",6378136.6,298.25642]
48
+ #
49
+ # Returns Float length_spheroid(geometry linestring, spheroid);
50
+ #
51
+ def length_spheroid(spheroid = EARTH_SPHEROID)
52
+ dis = postgis_calculate(:length_spheroid, self, spheroid).to_f
53
+ end
54
+
55
+ #
56
+ # Return the number of points of the geometry.
57
+ # PostGis ST_NumPoints does not work as nov/08
58
+ #
59
+ # Returns Integer ST_NPoints(geometry g1);
60
+ #
61
+ def num_points
62
+ postgis_calculate(:npoints, self).to_i
63
+ end
64
+
65
+ #
66
+ # Returns geometry start point.
67
+ #
68
+ def start_point
69
+ postgis_calculate(:startpoint, self)
70
+ end
71
+
72
+ #
73
+ # Returns geometry end point.
74
+ #
75
+ def end_point
76
+ postgis_calculate(:endpoint, self)
77
+ end
78
+
79
+ #
80
+ # Takes two geometry objects and returns TRUE if their intersection
81
+ # "spatially cross", that is, the geometries have some, but not all interior
82
+ # points in common. The intersection of the interiors of the geometries must
83
+ # not be the empty set and must have a dimensionality less than the the
84
+ # maximum dimension of the two input geometries. Additionally, the
85
+ # intersection of the two geometries must not equal either of the source
86
+ # geometries. Otherwise, it returns FALSE.
87
+ #
88
+ #
89
+ # Returns Boolean ST_Crosses(geometry g1, geometry g2);
90
+ #
91
+ def crosses? other
92
+ postgis_calculate(:crosses, [self, other])
93
+ end
94
+
95
+ #
96
+ # Returns a float between 0 and 1 representing the location of the closest point
97
+ # on LineString to the given Point, as a fraction of total 2d line length.
98
+ #
99
+ # You can use the returned location to extract a Point (ST_Line_Interpolate_Point)
100
+ # or a substring (ST_Line_Substring).
101
+ #
102
+ # This is useful for approximating numbers of addresses.
103
+ #
104
+ # Returns float (0 to 1) ST_Line_Locate_Point(geometry a_linestring, geometry a_point);
105
+ #
106
+ def locate_point point
107
+ postgis_calculate(:line_locate_point, [self, point]).to_f
108
+ end
109
+
110
+ #
111
+ # Return a derived geometry collection value with elements that match the
112
+ # specified measure. Polygonal elements are not supported.
113
+ #
114
+ # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for
115
+ # Continuation CD Editing Meeting
116
+ #
117
+ # Returns geometry ST_Locate_Along_Measure(geometry ageom_with_measure, float a_measure);
118
+ #
119
+ def locate_along_measure(measure)
120
+ postgis_calculate(:locate_along_measure, self, measure)
121
+ end
122
+
123
+ #
124
+ # Return a derived geometry collection value with elements that match the
125
+ # specified range of measures inclusively. Polygonal elements are not supported.
126
+ #
127
+ # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for Continuation CD Editing Meeting
128
+ #
129
+ # Returns geometry ST_Locate_Between_Measures(geometry geomA, float measure_start, float measure_end);
130
+ #
131
+ def locate_between_measures(a, b)
132
+ postgis_calculate(:locate_between_measures, self, [a,b])
133
+ end
134
+
135
+ #
136
+ # Returns a point interpolated along a line. First argument must be a LINESTRING.
137
+ # Second argument is a float8 between 0 and 1 representing fraction of total
138
+ # linestring length the point has to be located.
139
+ #
140
+ # See ST_Line_Locate_Point for computing the line location nearest to a Point.
141
+ #
142
+ # Returns geometry ST_Line_Interpolate_Point(geometry a_linestring, float a_fraction);
143
+ #
144
+ def interpolate_point(fraction)
145
+ postgis_calculate(:line_interpolate_point, self, fraction)
146
+ end
147
+
148
+ #
149
+ # Return a linestring being a substring of the input one starting and ending
150
+ # at the given fractions of total 2d length. Second and third arguments are
151
+ # float8 values between 0 and 1. This only works with LINESTRINGs. To use
152
+ # with contiguous MULTILINESTRINGs use in conjunction with ST_LineMerge.
153
+ #
154
+ # If 'start' and 'end' have the same value this is equivalent to 'interpolate_point'.
155
+ #
156
+ # See 'locate_point' for computing the line location nearest to a Point.
157
+ #
158
+ # Returns geometry ST_Line_Substring(geometry a_linestring, float startfraction, float endfraction);
159
+ #
160
+ def line_substring(s,e)
161
+ postgis_calculate(:line_substring, self, [s, e])
162
+ end
163
+
164
+ ###
165
+ #Not implemented in postgis yet
166
+ # ST_max_distance Returns the largest distance between two line strings.
167
+ #def max_distance other
168
+ # #float ST_Max_Distance(geometry g1, geometry g2);
169
+ # postgis_calculate(:max_distance, [self, other])
170
+ #end
171
+ end
172
+ end
@@ -0,0 +1,89 @@
1
+ module PostgisFunctions
2
+ ####
3
+ ###
4
+ ##
5
+ #
6
+ # POINT
7
+ #
8
+ #
9
+ module PointFunctions
10
+
11
+ #
12
+ # Returns a float between 0 and 1 representing the location of the closest point
13
+ # on LineString to the given Point, as a fraction of total 2d line length.
14
+ #
15
+ # You can use the returned location to extract a Point (ST_Line_Interpolate_Point)
16
+ # or a substring (ST_Line_Substring).
17
+ #
18
+ # This is useful for approximating numbers of addresses.
19
+ #
20
+ # Returns float (0 to 1) ST_Line_Locate_Point(geometry a_linestring, geometry a_point);
21
+ #
22
+ def where_on_line line
23
+ postgis_calculate(:line_locate_point, [line, self]).to_f
24
+ end
25
+
26
+ #
27
+ # Linear distance in meters between two lon/lat points.
28
+ # Uses a spherical earth and radius of 6370986 meters.
29
+ # Faster than 'distance_spheroid', but less accurate.
30
+ #
31
+ # Only implemented for points.
32
+ #
33
+ # Returns Float ST_Distance_Sphere(geometry pointlonlatA, geometry pointlonlatB);
34
+ #
35
+ def distance_sphere_to(other)
36
+ dis = postgis_calculate(:distance_sphere, [self, other]).to_f
37
+ end
38
+
39
+ #
40
+ # Calculates the distance on an ellipsoid. This is useful if the
41
+ # coordinates of the geometry are in longitude/latitude and a length is
42
+ # desired without reprojection. The ellipsoid is a separate database type and
43
+ # can be constructed as follows:
44
+ #
45
+ # This is slower then 'distance_sphere_to', but more precise.
46
+ #
47
+ # SPHEROID[<NAME>,<SEMI-MAJOR AXIS>,<INVERSE FLATTENING>]
48
+ #
49
+ # Example:
50
+ # SPHEROID["GRS_1980",6378137,298.257222101]
51
+ #
52
+ # Defaults to:
53
+ #
54
+ # SPHEROID["IERS_2003",6378136.6,298.25642]
55
+ #
56
+ # Returns ST_Distance_Spheroid(geometry geomA, geometry geomB, spheroid);
57
+ #
58
+ def distance_spheroid_to(other, spheroid = EARTH_SPHEROID)
59
+ postgis_calculate(:distance_spheroid, [self, other], spheroid).to_f
60
+ end
61
+
62
+ #
63
+ # The azimuth of the segment defined by the given Point geometries,
64
+ # or NULL if the two points are coincident. Return value is in radians.
65
+ #
66
+ # The Azimuth is mathematical concept defined as the angle, in this case
67
+ # measured in radian, between a reference plane and a point.
68
+ #
69
+ # Returns Float ST_Azimuth(geometry pointA, geometry pointB);
70
+ #
71
+ def azimuth other
72
+ #TODO: return if not point/point
73
+ postgis_calculate(:azimuth, [self, other]).to_f
74
+ rescue
75
+ ActiveRecord::StatementInvalid
76
+ end
77
+
78
+ #
79
+ # True if the geometry is a point and is inside the circle.
80
+ #
81
+ # Returns Boolean ST_point_inside_circle(geometry, float, float, float)
82
+ #
83
+ def inside_circle?(x,y,r)
84
+ postgis_calculate(:point_inside_circle, self, [x,y,r])
85
+ end
86
+
87
+ end
88
+
89
+ end
@@ -0,0 +1,78 @@
1
+ module PostgisFunctions
2
+ ###
3
+ ##
4
+ #
5
+ # Polygon
6
+ #
7
+ #
8
+ module PolygonFunctions
9
+
10
+ #
11
+ # The area of the geometry if it is a polygon or multi-polygon.
12
+ # Return the area measurement of an ST_Surface or ST_MultiSurface value.
13
+ # Area is in the units of the spatial reference system.
14
+ #
15
+ # Returns Float ST_Area(geometry g1);
16
+ #
17
+ def area
18
+ postgis_calculate(:area, self).to_f
19
+ end
20
+
21
+ #
22
+ # Returns the 2D perimeter of the geometry if it is a ST_Surface, ST_MultiSurface
23
+ # (Polygon, Multipolygon). 0 is returned for non-areal geometries. For linestrings
24
+ # use 'length'. Measurements are in the units of the spatial reference system of
25
+ # the geometry.
26
+ #
27
+ # Returns Float ST_Perimeter(geometry g1);
28
+ #
29
+ def perimeter
30
+ postgis_calculate(:perimeter, self).to_f
31
+ end
32
+
33
+ #
34
+ # Returns the 3-dimensional perimeter of the geometry, if it is a polygon or multi-polygon.
35
+ # If the geometry is 2-dimensional, then the 2-dimensional perimeter is returned.
36
+ #
37
+ # Returns Float ST_Perimeter3D(geometry geomA);
38
+ #
39
+ def perimeter3d
40
+ postgis_calculate(:perimeter3d, self).to_f
41
+ end
42
+
43
+ #
44
+ # True if the LineString's start and end points are coincident.
45
+ #
46
+ # This method implements the OpenGIS Simple Features Implementation
47
+ # Specification for SQL.
48
+ #
49
+ # SQL-MM defines the result of ST_IsClosed(NULL) to be 0, while PostGIS returns NULL.
50
+ #
51
+ # Returns boolean ST_IsClosed(geometry g);
52
+ #
53
+ def closed?
54
+ postgis_calculate(:isclosed, self)
55
+ end
56
+ alias_method "is_closed?", "closed?"
57
+
58
+ #
59
+ # True if no point in Geometry B is outside Geometry A
60
+ #
61
+ # This function call will automatically include a bounding box comparison
62
+ # that will make use of any indexes that are available on the geometries.
63
+ # To avoid index use, use the function _ST_Covers.
64
+ #
65
+ # Do not call with a GEOMETRYCOLLECTION as an argument
66
+ # Do not use this function with invalid geometries. You will get unexpected results.
67
+ #
68
+ # Performed by the GEOS module.
69
+ #
70
+ # Returns Boolean ST_Covers(geometry geomA, geometry geomB);
71
+ #
72
+ def covers? other
73
+ postgis_calculate(:covers, [self, other])
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "postgis_adapter"
3
+ s.version = "0.1.8"
4
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
5
+ s.authors = ["Marcos Piccinini"]
6
+ s.date = "2008-12-16"
7
+ s.description = "Postgis Adapter for Activer Record"
8
+ s.email = ["x@nofxx.com"]
9
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
10
+ s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "init.rb", "install.rb", "lib/postgis_adapter.rb", "lib/postgis_adapter/acts_as_geom.rb", "lib/postgis_adapter/common_spatial_adapter.rb", "lib/postgis_functions.rb", "lib/postgis_functions/bbox.rb", "lib/postgis_functions/class.rb", "lib/postgis_functions/common.rb", "lib/postgis_functions/linestring.rb", "lib/postgis_functions/point.rb", "lib/postgis_functions/polygon.rb", "postgis_adapter.gemspec", "rails/init.rb", "script/console", "script/destroy", "script/generate", "uninstall.rb"]
11
+ s.test_files = ["spec/acts_as_geom_spec.rb", "spec/common_spatial_adapter_spec.rb", "spec/db/database_postgis.yml", "spec/db/models_postgis.rb", "spec/db/schema_postgis.rb", "spec/postgis_adapter_spec.rb", "spec/postgis_functions/bbox_spec.rb", "spec/postgis_functions/linestring_spec.rb", "spec/postgis_functions/point_spec.rb", "spec/postgis_functions/polygon_spec.rb", "spec/postgis_functions_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"]
12
+ s.has_rdoc = true
13
+ s.homepage = "http://github.com/nofxx/postgis_adapter"
14
+ s.rdoc_options = ["--main", "README.rdoc"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{postgis_adapter}
17
+ s.rubygems_version = %q{1.3.1}
18
+ s.summary = "Postgis Adapter for Activer Record"
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 2
23
+
24
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
25
+ s.add_runtime_dependency(%q<activerecord>, [">= 2.0.2"])
26
+ s.add_development_dependency(%q<newgem>, [">= 1.1.0"])
27
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
28
+ else
29
+ s.add_dependency(%q<activerecord>, [">= 2.0.2"])
30
+ s.add_dependency(%q<newgem>, [">= 1.1.0"])
31
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<activerecord>, [">= 2.0.2"])
35
+ s.add_dependency(%q<newgem>, [">= 1.1.0"])
36
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
37
+ end
38
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,8 @@
1
+ class SpatialAdapterNotCompatibleError < StandardError
2
+ end
3
+
4
+ unless ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
5
+ raise SpatialAdapterNotCompatibleError.
6
+ new("Only PostgreSQL with PostGIS is supported by the postgis adapter plugin.")
7
+ end
8
+ require 'postgis_adapter'
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/postgis_adapter.rb'}"
9
+ puts "Loading postgis_adapter gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "ActsAsGeom" do
4
+
5
+ before(:each) do
6
+ class City < ActiveRecord::Base
7
+ acts_as_geom :geom
8
+ end
9
+ end
10
+
11
+ it "should get the geom type" do
12
+ City.get_geom_type(:geom).should eql(:polygon)
13
+ end
14
+
15
+ end