geos-extensions 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +3 -0
- data/Gemfile +17 -0
- data/Guardfile +17 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +19 -91
- data/Rakefile +1 -12
- data/geos-extensions.gemspec +1 -9
- data/lib/geos-extensions.rb +1 -9
- data/lib/geos/coordinate_sequence.rb +92 -0
- data/lib/geos/extensions/version.rb +1 -1
- data/lib/geos/geometry.rb +252 -0
- data/lib/geos/geometry_collection.rb +60 -0
- data/lib/geos/geos_helper.rb +86 -72
- data/lib/geos/google_maps.rb +1 -0
- data/lib/geos/google_maps/api_2.rb +9 -23
- data/lib/geos/google_maps/api_3.rb +10 -24
- data/lib/geos/google_maps/api_common.rb +41 -0
- data/lib/geos/line_string.rb +15 -0
- data/lib/geos/multi_line_string.rb +15 -0
- data/lib/geos/multi_point.rb +15 -0
- data/lib/geos/multi_polygon.rb +27 -0
- data/lib/geos/point.rb +120 -0
- data/lib/geos/polygon.rb +158 -0
- data/lib/geos/yaml.rb +30 -0
- data/lib/geos/yaml/psych.rb +18 -0
- data/lib/geos/yaml/syck.rb +41 -0
- data/lib/geos_extensions.rb +110 -711
- data/test/google_maps_api_2_tests.rb +54 -32
- data/test/google_maps_api_3_tests.rb +58 -36
- data/test/google_maps_polyline_encoder_tests.rb +1 -1
- data/test/helper_tests.rb +28 -0
- data/test/misc_tests.rb +130 -10
- data/test/reader_tests.rb +38 -1
- data/test/test_helper.rb +54 -146
- data/test/writer_tests.rb +329 -10
- data/test/yaml_tests.rb +203 -0
- metadata +26 -102
- data/app/models/geos/geometry_column.rb +0 -39
- data/app/models/geos/spatial_ref_sys.rb +0 -12
- data/lib/geos/active_record_extensions.rb +0 -12
- data/lib/geos/active_record_extensions/connection_adapters/postgresql_adapter.rb +0 -151
- data/lib/geos/active_record_extensions/spatial_columns.rb +0 -367
- data/lib/geos/active_record_extensions/spatial_scopes.rb +0 -493
- data/lib/geos/rails/engine.rb +0 -6
- data/lib/tasks/test.rake +0 -42
- data/test/adapter_tests.rb +0 -38
- data/test/database.yml +0 -17
- data/test/fixtures/foo3ds.yml +0 -16
- data/test/fixtures/foo_geographies.yml +0 -16
- data/test/fixtures/foos.yml +0 -16
- data/test/geography_columns_tests.rb +0 -176
- data/test/geometry_columns_tests.rb +0 -178
- data/test/spatial_scopes_geographies_tests.rb +0 -107
- data/test/spatial_scopes_tests.rb +0 -337
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MDdiYzQwZjU5MjYzNDMzNDI4ZGZjOTI5NmI0Yzc2NDJjOTYxNzE1Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDc0MWJiM2RmOTJiMzE5NTA2NGM3ZmZhMmQ3MDk1YWZjZTEwNmRkNw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MGM2NDQ3ODUzYTBkM2Y3OGViZGZkNWE3OTc2OTA4NWE1NTc3OTc5ZTM2MTZj
|
10
|
+
MGMwNDA0OTY2Nzg4MTQ5OWRiMDlkODYwMjc4ZDhlZmJjMTQxMjFjMjVkZTAx
|
11
|
+
MzRmYTFmNmY2ZTk2NTdjZTI3Zjc4NTFlNWI0Y2UzMWYyZjFkZDA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YTkxYzA1NTMzYTdjNzU4NmFkZTY4YTEwNjM5MjhjYWE1MWMzNTJmOWM1MTNi
|
14
|
+
ZTE5YjJhZDU3MDY2M2JjMzUyZGIyYWQxM2E5OGM2MGNkZTRhMDQ1ZTVjYTc1
|
15
|
+
MDg4YjdhY2VjOWFkMzNjNzM4NWRjZjRiOTRlM2QxZTI5YmY2Yjc=
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,3 +1,20 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
gemspec
|
4
|
+
|
5
|
+
gem "rdoc", "~> 3.12"
|
6
|
+
gem "rake", "~> 10.0"
|
7
|
+
gem "minitest"
|
8
|
+
gem "minitest-reporters"
|
9
|
+
gem "guard-minitest"
|
10
|
+
gem "simplecov"
|
11
|
+
|
12
|
+
if RbConfig::CONFIG['host_os'] =~ /^darwin/
|
13
|
+
gem "rb-fsevent"
|
14
|
+
gem "growl"
|
15
|
+
end
|
16
|
+
|
17
|
+
if File.exists?('Gemfile.local')
|
18
|
+
instance_eval File.read('Gemfile.local')
|
19
|
+
end
|
20
|
+
|
data/Guardfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
guard 'minitest', :test_folders => 'test', :test_file_patterns => '*_tests.rb' do
|
3
|
+
watch(%r|^test/(.+)_tests\.rb|)
|
4
|
+
|
5
|
+
watch(%r|^lib/(.*)([^/]+)\.rb|) do |m|
|
6
|
+
"test/#{m[1]}#{m[2]}_tests.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
watch(%r|^test/test_helper\.rb|) do
|
10
|
+
"test"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if File.exists?('Guardfile.local')
|
15
|
+
instance_eval File.read('Guardfile.local')
|
16
|
+
end
|
17
|
+
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
= Zoocasa GEOS Extensions
|
3
3
|
|
4
4
|
The Zoocasa GEOS Extensions library (ZGEL) is a set of utilities and tools that
|
5
5
|
extend the GEOS Ruby bindings module. From http://geos.refractions.net/ ...
|
@@ -46,85 +46,7 @@ ZGEL contains a number of enhancements to the GEOS Ruby library:
|
|
46
46
|
|
47
47
|
* Geos::GeometryCollection has been made an Enumerable.
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
* automatic detection of geometry columns and just-in-time conversions
|
52
|
-
for input and output to and from WKB when using PostGIS. This allows
|
53
|
-
you to do stuff like this with your ActiveRecord models:
|
54
|
-
|
55
|
-
m = MyModel.find(12345)
|
56
|
-
m.the_geom # => spits out the untouched geometry value as a string in WKB
|
57
|
-
m.the_geom_geos # => spits out the geometry wrapped in a Geos::Geometry object
|
58
|
-
m.the_geom = 'POINT(0 0)' # => setters will automatically make
|
59
|
-
conversions from any of the formats that the Geos.read can recognize,
|
60
|
-
so Google Maps formats, WKT, WKB, etc. are all converted
|
61
|
-
automatically.
|
62
|
-
m.the_geom_wkt # => automatically converts to a WKT string
|
63
|
-
m.the_geom_wkb_bin # => automatically converts to WKB in binary
|
64
|
-
|
65
|
-
There's also some funky SRID handling code that will automatically
|
66
|
-
look in the geometry_columns table to make conversions for you when
|
67
|
-
necessary. Saving WKT as "SRID=default; POINT(0 0)" for instance will
|
68
|
-
automatically set the SRID when saving the ActiveRecord, or the SRID
|
69
|
-
can be specified manually.
|
70
|
-
|
71
|
-
* multiple geometry columns are supported and detected for
|
72
|
-
automatically. These column accessors are all generated dynamically at
|
73
|
-
run time.
|
74
|
-
|
75
|
-
* automatic generation of named scopes for ActiveRecord models. The
|
76
|
-
usual suspects are supported:
|
77
|
-
|
78
|
-
* st_contains
|
79
|
-
* st_containsproperly
|
80
|
-
* st_covers
|
81
|
-
* st_coveredby
|
82
|
-
* st_crosses
|
83
|
-
* st_disjoint
|
84
|
-
* st_equals
|
85
|
-
* st_intersects
|
86
|
-
* st_orderingequals
|
87
|
-
* st_overlaps
|
88
|
-
* st_touches
|
89
|
-
* st_within
|
90
|
-
* st_dwithin
|
91
|
-
|
92
|
-
Ordering scopes are also included:
|
93
|
-
|
94
|
-
* order_by_ndims
|
95
|
-
* order_by_npoints
|
96
|
-
* order_by_nrings
|
97
|
-
* order_by_numgeometries
|
98
|
-
* order_by_numinteriorring
|
99
|
-
* order_by_numinteriorrings
|
100
|
-
* order_by_numpoints
|
101
|
-
* order_by_length3d
|
102
|
-
* order_by_length
|
103
|
-
* order_by_length2d
|
104
|
-
* order_by_perimeter
|
105
|
-
* order_by_perimeter2d
|
106
|
-
* order_by_perimeter3d
|
107
|
-
* order_by_distance
|
108
|
-
* order_by_distance_sphere
|
109
|
-
* order_by_maxdistance
|
110
|
-
* order_by_hausdorffdistance
|
111
|
-
* order_by_distance_spheroid
|
112
|
-
* order_by_length2d_spheroid
|
113
|
-
* order_by_length3d_spheroid
|
114
|
-
* order_by_length_spheroid
|
115
|
-
|
116
|
-
These let you chain together scopes to build geospatial queries:
|
117
|
-
|
118
|
-
neighbourhood = Neighbourhood.find(12345)
|
119
|
-
my_model = MyModel.active.
|
120
|
-
recent.
|
121
|
-
st_within(neighbourhood.the_geom_geos.envelope).
|
122
|
-
st_dwithin(point, 0.1).
|
123
|
-
all(
|
124
|
-
:limit => 10
|
125
|
-
)
|
126
|
-
|
127
|
-
=== Google Maps API Output
|
49
|
+
== Google Maps API Output
|
128
50
|
|
129
51
|
Starting with version 0.1.0, ZGEL supports both Google Maps API
|
130
52
|
version 2 and version 3 style outputs. By default and for the sake of
|
@@ -148,14 +70,20 @@ At an unspecified point in the future, we'll likely make Google Maps
|
|
148
70
|
API version 3 the default, but for the time being, we'll stick with
|
149
71
|
version 2 since switching between the two is pretty painless.
|
150
72
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
73
|
+
== ActiveRecord Extensions
|
74
|
+
|
75
|
+
This extension used to contain a bunch of extensions to ActiveRecord, but as of
|
76
|
+
version 0.3.0 we have decided to strip those extensions out and move them into
|
77
|
+
their own gem called activerecord-spatial available at
|
78
|
+
https://github.com/zoocasa/activerecord-spatial .
|
79
|
+
|
80
|
+
== Thanks
|
81
|
+
|
82
|
+
* Thanks to Charlie Savage for donating for YAML dumping and loading
|
83
|
+
support.
|
84
|
+
|
85
|
+
== License
|
86
|
+
|
87
|
+
This gem is licensed under an MIT-style license. See the +MIT-LICENSE+ file for
|
88
|
+
details.
|
89
|
+
|
data/Rakefile
CHANGED
@@ -2,23 +2,12 @@
|
|
2
2
|
# -*- ruby -*-
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
|
-
|
6
|
-
gem 'rdoc', '~> 3.12'
|
7
|
-
|
8
5
|
require 'rubygems/package_task'
|
9
6
|
require 'rake/testtask'
|
10
7
|
require 'rdoc/task'
|
11
8
|
require 'bundler/gem_tasks'
|
12
9
|
|
13
|
-
|
14
|
-
begin
|
15
|
-
gem 'psych'
|
16
|
-
rescue Exception => e
|
17
|
-
# it's okay, fall back on the bundled psych
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
$:.push 'lib'
|
10
|
+
$:.push File.expand_path(File.dirname(__FILE__), 'lib')
|
22
11
|
|
23
12
|
version = Geos::Extensions::VERSION
|
24
13
|
|
data/geos-extensions.gemspec
CHANGED
@@ -20,14 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.homepage = "http://github.com/zoocasa/geos-extensions"
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
|
23
|
-
s.add_dependency("
|
24
|
-
s.add_dependency("ffi-geos", ["~> 0.0.4"])
|
25
|
-
if RUBY_PLATFORM == "java"
|
26
|
-
s.add_dependency("activerecord-jdbcpostgresql-adapter")
|
27
|
-
else
|
28
|
-
s.add_dependency("pg")
|
29
|
-
end
|
30
|
-
s.add_dependency("rdoc")
|
31
|
-
s.add_dependency("rake", ["~> 0.9"])
|
23
|
+
s.add_dependency("ffi-geos", ["~> 0.1"])
|
32
24
|
end
|
33
25
|
|
data/lib/geos-extensions.rb
CHANGED
@@ -1,13 +1,5 @@
|
|
1
1
|
|
2
2
|
require File.join(File.dirname(__FILE__), *%w{ geos_extensions })
|
3
3
|
|
4
|
-
|
5
|
-
require File.join(Geos::GEOS_EXTENSIONS_BASE, *%w{ geos active_record_extensions })
|
6
|
-
end
|
7
|
-
|
8
|
-
if defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
9
|
-
require File.join(Geos::GEOS_EXTENSIONS_BASE, %w{ geos rails engine })
|
10
|
-
end
|
11
|
-
|
12
|
-
Geos::GoogleMaps.use_api(2)
|
4
|
+
Geos::GoogleMaps.use_api(3)
|
13
5
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
module Geos
|
3
|
+
class CoordinateSequence
|
4
|
+
# Returns a Ruby Array of Arrays of coordinates within the
|
5
|
+
# CoordinateSequence in the form [ x, y, z ].
|
6
|
+
def to_a
|
7
|
+
(0...self.length).to_a.collect do |p|
|
8
|
+
[
|
9
|
+
self.get_x(p),
|
10
|
+
(self.dimensions >= 2 ? self.get_y(p) : nil),
|
11
|
+
(self.dimensions >= 3 && self.get_z(p) > 1.7e-306 ? self.get_z(p) : nil)
|
12
|
+
].compact
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Build some XmlMarkup for KML. You can set various KML options like
|
17
|
+
# tessellate, altitudeMode, etc. Use Rails/Ruby-style code and it
|
18
|
+
# will be converted automatically, i.e. :altitudeMode, not
|
19
|
+
# :altitude_mode.
|
20
|
+
def to_kml(*args)
|
21
|
+
xml, options = Geos::Helper.xml_options(*args)
|
22
|
+
|
23
|
+
xml.LineString(:id => options[:id]) do
|
24
|
+
xml.extrude(options[:extrude]) if options[:extrude]
|
25
|
+
xml.tessellate(options[:tessellate]) if options[:tessellate]
|
26
|
+
xml.altitudeMode(Geos::Helper.camelize(options[:altitude_mode])) if options[:altitudeMode]
|
27
|
+
xml.coordinates do
|
28
|
+
self.to_a.each do
|
29
|
+
xml << (self.to_a.join(','))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Build some XmlMarkup for GeoRSS GML. You should include the
|
36
|
+
# appropriate georss and gml XML namespaces in your document.
|
37
|
+
def to_georss(*args)
|
38
|
+
xml = Geos::Helper.xml_options(*args)[0]
|
39
|
+
|
40
|
+
xml.georss(:where) do
|
41
|
+
xml.gml(:LineString) do
|
42
|
+
xml.gml(:posList) do
|
43
|
+
xml << self.to_a.collect do |p|
|
44
|
+
"#{p[1]} #{p[0]}"
|
45
|
+
end.join(' ')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a Hash suitable for converting to JSON.
|
52
|
+
#
|
53
|
+
# Options:
|
54
|
+
#
|
55
|
+
# * :encoded - enable or disable Google Maps encoding. The default is
|
56
|
+
# true.
|
57
|
+
# * :level - set the level of the Google Maps encoding algorithm.
|
58
|
+
def as_json(options = {})
|
59
|
+
options = {
|
60
|
+
:encoded => true,
|
61
|
+
:level => 3
|
62
|
+
}.merge options
|
63
|
+
|
64
|
+
if options[:encoded]
|
65
|
+
{
|
66
|
+
:type => 'lineString',
|
67
|
+
:encoded => true
|
68
|
+
}.merge(Geos::GoogleMaps::PolylineEncoder.encode(self.to_a, options[:level]))
|
69
|
+
else
|
70
|
+
{
|
71
|
+
:type => 'lineString',
|
72
|
+
:encoded => false,
|
73
|
+
:points => self.to_a
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
alias :to_jsonable :as_json
|
78
|
+
|
79
|
+
def as_geojson(options = {})
|
80
|
+
{
|
81
|
+
:type => 'LineString',
|
82
|
+
:coordinates => self.to_a
|
83
|
+
}
|
84
|
+
end
|
85
|
+
alias :to_geojsonable :as_geojson
|
86
|
+
|
87
|
+
def to_geojson(options = {})
|
88
|
+
self.to_geojsonable(options).to_json
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,252 @@
|
|
1
|
+
|
2
|
+
module Geos
|
3
|
+
# This is our base module that we use for some generic methods used all
|
4
|
+
# over the place.
|
5
|
+
class Geometry
|
6
|
+
protected
|
7
|
+
|
8
|
+
WKB_WRITER_OPTIONS = [ :output_dimensions, :byte_order, :include_srid ].freeze
|
9
|
+
def wkb_writer(options = {}) #:nodoc:
|
10
|
+
writer = WkbWriter.new
|
11
|
+
options.reject { |k, v| !WKB_WRITER_OPTIONS.include?(k) }.each do |k, v|
|
12
|
+
writer.send("#{k}=", v)
|
13
|
+
end
|
14
|
+
writer
|
15
|
+
end
|
16
|
+
|
17
|
+
public
|
18
|
+
|
19
|
+
# Spits the geometry out into WKB in binary.
|
20
|
+
#
|
21
|
+
# You can set the :output_dimensions, :byte_order and :include_srid
|
22
|
+
# options via the options Hash.
|
23
|
+
def to_wkb_bin(options = {})
|
24
|
+
wkb_writer(options).write(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Quickly call to_wkb_bin with :include_srid set to true.
|
28
|
+
def to_ewkb_bin(options = {})
|
29
|
+
options = {
|
30
|
+
:include_srid => true
|
31
|
+
}.merge options
|
32
|
+
to_wkb_bin(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Spits the geometry out into WKB in hex.
|
36
|
+
#
|
37
|
+
# You can set the :output_dimensions, :byte_order and :include_srid
|
38
|
+
# options via the options Hash.
|
39
|
+
def to_wkb(options = {})
|
40
|
+
wkb_writer(options).write_hex(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Quickly call to_wkb with :include_srid set to true.
|
44
|
+
def to_ewkb(options = {})
|
45
|
+
options = {
|
46
|
+
:include_srid => true
|
47
|
+
}.merge options
|
48
|
+
to_wkb(options)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Spits the geometry out into WKT. You can specify the :include_srid
|
52
|
+
# option to create a PostGIS-style EWKT output.
|
53
|
+
def to_wkt(options = {})
|
54
|
+
writer = WktWriter.new
|
55
|
+
|
56
|
+
# Older versions of the Geos library don't allow for options here.
|
57
|
+
args = if WktWriter.instance_method(:write).arity < -1
|
58
|
+
[ options ]
|
59
|
+
else
|
60
|
+
[]
|
61
|
+
end
|
62
|
+
|
63
|
+
ret = ''
|
64
|
+
|
65
|
+
if options[:include_srid]
|
66
|
+
srid = if options[:srid]
|
67
|
+
options[:srid]
|
68
|
+
else
|
69
|
+
self.srid
|
70
|
+
end
|
71
|
+
|
72
|
+
ret << "SRID=#{srid};"
|
73
|
+
end
|
74
|
+
|
75
|
+
ret << writer.write(self, *args)
|
76
|
+
ret
|
77
|
+
end
|
78
|
+
|
79
|
+
# Quickly call to_wkt with :include_srid set to true.
|
80
|
+
def to_ewkt(options = {})
|
81
|
+
options = {
|
82
|
+
:include_srid => true
|
83
|
+
}.merge options
|
84
|
+
to_wkt(options)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns a Point for the envelope's upper left coordinate.
|
88
|
+
def upper_left
|
89
|
+
if defined?(@upper_left)
|
90
|
+
@upper_left
|
91
|
+
else
|
92
|
+
cs = self.envelope.exterior_ring.coord_seq
|
93
|
+
@upper_left = Geos::wkt_reader_singleton.read("POINT(#{cs.get_x(3)} #{cs.get_y(3)})")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
alias :nw :upper_left
|
97
|
+
alias :northwest :upper_left
|
98
|
+
|
99
|
+
# Returns a Point for the envelope's upper right coordinate.
|
100
|
+
def upper_right
|
101
|
+
if defined?(@upper_right)
|
102
|
+
@upper_right
|
103
|
+
else
|
104
|
+
cs = self.envelope.exterior_ring.coord_seq
|
105
|
+
@upper_right = Geos::wkt_reader_singleton.read("POINT(#{cs.get_x(2)} #{cs.get_y(2)})")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
alias :ne :upper_right
|
109
|
+
alias :northeast :upper_right
|
110
|
+
|
111
|
+
# Returns a Point for the envelope's lower right coordinate.
|
112
|
+
def lower_right
|
113
|
+
if defined?(@lower_right)
|
114
|
+
@lower_right
|
115
|
+
else
|
116
|
+
cs = self.envelope.exterior_ring.coord_seq
|
117
|
+
@lower_right = Geos::wkt_reader_singleton.read("POINT(#{cs.get_x(1)} #{cs.get_y(1)})")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
alias :se :lower_right
|
121
|
+
alias :southeast :lower_right
|
122
|
+
|
123
|
+
# Returns a Point for the envelope's lower left coordinate.
|
124
|
+
def lower_left
|
125
|
+
if defined?(@lower_left)
|
126
|
+
@lower_left
|
127
|
+
else
|
128
|
+
cs = self.envelope.exterior_ring.coord_seq
|
129
|
+
@lower_left = Geos::wkt_reader_singleton.read("POINT(#{cs.get_x(0)} #{cs.get_y(0)})")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
alias :sw :lower_left
|
133
|
+
alias :southwest :lower_left
|
134
|
+
|
135
|
+
# Northern-most Y coordinate.
|
136
|
+
def top
|
137
|
+
if defined?(@top)
|
138
|
+
@top
|
139
|
+
else
|
140
|
+
@top = self.upper_right.y
|
141
|
+
end
|
142
|
+
end
|
143
|
+
alias :n :top
|
144
|
+
alias :north :top
|
145
|
+
|
146
|
+
# Eastern-most X coordinate.
|
147
|
+
def right
|
148
|
+
if defined?(@right)
|
149
|
+
@right
|
150
|
+
else
|
151
|
+
@right = self.upper_right.x
|
152
|
+
end
|
153
|
+
end
|
154
|
+
alias :e :right
|
155
|
+
alias :east :right
|
156
|
+
|
157
|
+
# Southern-most Y coordinate.
|
158
|
+
def bottom
|
159
|
+
if defined?(@bottom)
|
160
|
+
@bottom
|
161
|
+
else
|
162
|
+
@bottom = self.lower_left.y
|
163
|
+
end
|
164
|
+
end
|
165
|
+
alias :s :bottom
|
166
|
+
alias :south :bottom
|
167
|
+
|
168
|
+
# Western-most X coordinate.
|
169
|
+
def left
|
170
|
+
if defined?(@left)
|
171
|
+
@left
|
172
|
+
else
|
173
|
+
@left = self.lower_left.x
|
174
|
+
end
|
175
|
+
end
|
176
|
+
alias :w :left
|
177
|
+
alias :west :left
|
178
|
+
|
179
|
+
# Spits out a bounding box the way Flickr likes it. You can set the
|
180
|
+
# precision of the rounding using the :precision option. In order to
|
181
|
+
# ensure that the box is indeed a box and not merely a point, the
|
182
|
+
# southwest coordinates are floored and the northeast point ceiled.
|
183
|
+
def to_flickr_bbox(options = {})
|
184
|
+
options = {
|
185
|
+
:precision => 1
|
186
|
+
}.merge(options)
|
187
|
+
precision = 10.0 ** options[:precision]
|
188
|
+
|
189
|
+
[
|
190
|
+
(self.west * precision).floor / precision,
|
191
|
+
(self.south * precision).floor / precision,
|
192
|
+
(self.east * precision).ceil / precision,
|
193
|
+
(self.north * precision).ceil / precision
|
194
|
+
].join(',')
|
195
|
+
end
|
196
|
+
|
197
|
+
# Spits out the actual stringified GeoJSON.
|
198
|
+
def to_geojson(options = {})
|
199
|
+
self.to_geojsonable(options).to_json
|
200
|
+
end
|
201
|
+
|
202
|
+
# Returns the Y and X coordinates of the Geometry's centroid in an Array.
|
203
|
+
def lat_lng
|
204
|
+
self.centroid.to_a[0, 2].reverse
|
205
|
+
end
|
206
|
+
alias :lat_long :lat_lng
|
207
|
+
alias :latlng :lat_lng
|
208
|
+
alias :latlong :lat_lng
|
209
|
+
alias :lat_lon :lat_lng
|
210
|
+
alias :latlon :lat_lng
|
211
|
+
|
212
|
+
# Returns the X and Y coordinates of the Geometry's centroid in an Array.
|
213
|
+
def lng_lat
|
214
|
+
self.centroid.to_a[0, 2]
|
215
|
+
end
|
216
|
+
alias :long_lat :lng_lat
|
217
|
+
alias :lnglat :lng_lat
|
218
|
+
alias :longlat :lng_lat
|
219
|
+
alias :lon_lat :lng_lat
|
220
|
+
alias :lonlat :lng_lat
|
221
|
+
|
222
|
+
# Spits out a Hash containing the cardinal points that describe the
|
223
|
+
# Geometry's bbox.
|
224
|
+
def to_bbox(long_or_short_names = :long)
|
225
|
+
case long_or_short_names
|
226
|
+
when :long
|
227
|
+
{
|
228
|
+
:north => self.north,
|
229
|
+
:east => self.east,
|
230
|
+
:south => self.south,
|
231
|
+
:west => self.west
|
232
|
+
}
|
233
|
+
when :short
|
234
|
+
{
|
235
|
+
:n => self.north,
|
236
|
+
:e => self.east,
|
237
|
+
:s => self.south,
|
238
|
+
:w => self.west
|
239
|
+
}
|
240
|
+
else
|
241
|
+
raise ArgumentError.new("Expected either :long or :short for long_or_short_names argument")
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Spits out a PostGIS BOX2D-style representing the Geometry's bounding
|
246
|
+
# box.
|
247
|
+
def to_box2d
|
248
|
+
"BOX(#{self.southwest.to_a.join(' ')}, #{self.northeast.to_a.join(' ')})"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|