georuby-ext 0.0.1

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.
@@ -0,0 +1,73 @@
1
+ class GeoRuby::SimpleFeatures::Point
2
+
3
+ def self.from_lat_lng(object, srid = GeoRuby::SimpleFeatures::DEFAULT_SRID)
4
+ if object.respond_to?(:to_lat_lng)
5
+ lat_lng = object.to_lat_lng
6
+ else
7
+ lat_lng = Geokit::LatLng.normalize object
8
+ end
9
+ from_x_y lat_lng.lng, lat_lng.lat, srid
10
+ end
11
+
12
+ def eql?(other)
13
+ [x,y,srid] == [other.x, other.y, other.srid]
14
+ end
15
+
16
+ def hash
17
+ [x,y,srid].hash
18
+ end
19
+
20
+ def to_s
21
+ "#{y},#{x}"
22
+ end
23
+
24
+ def self.centroid(points)
25
+ case points.size
26
+ when 0
27
+ nil
28
+ when 1
29
+ points.first
30
+ when 2
31
+ return GeoRuby::SimpleFeatures::Point.from_x_y points.map(&:x).sum / 2, points.map(&:y).sum / 2, points.first.srid
32
+ else
33
+ points = [points.last, *points]
34
+ GeoRuby::SimpleFeatures::Polygon.from_points([points]).centroid.tap do |centroid|
35
+ centroid.srid = points.first.srid if centroid
36
+ end
37
+ end
38
+ end
39
+
40
+ def to_lat_lng
41
+ Geokit::LatLng.new y, x
42
+ end
43
+
44
+ def to_s
45
+ to_lat_lng.to_s
46
+ end
47
+
48
+ def to_wgs84
49
+ self.class.from_lat_lng to_lat_lng.google_to_wgs84, 4326
50
+ end
51
+
52
+ def to_google
53
+ self.class.from_lat_lng to_lat_lng.wgs84_to_google, 900913
54
+ end
55
+
56
+ def to_rgeo
57
+ factory = RGeo::Geos::Factory.create
58
+ factory.point(self.x, self.y)
59
+ end
60
+
61
+ def to_openlayers
62
+ OpenLayers::LonLat.new x, y
63
+ end
64
+
65
+ def self.bounds(points)
66
+ return nil if points.blank?
67
+
68
+ points.inject(points.first.envelope) do |envelope, point|
69
+ envelope.extend!(point.envelope)
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,68 @@
1
+ class GeoRuby::SimpleFeatures::Polygon
2
+
3
+ def self.circle(center, radius, sides_number = 24)
4
+ coordinates = (0...sides_number).collect do |side|
5
+ 2 * 180 / sides_number * side
6
+ end.collect do |angle|
7
+ point = GeoRuby::SimpleFeatures::Point.from_lat_lng(center.to_lat_lng.endpoint(angle, radius, {:units => :kms}))
8
+ [point.x, point.y]
9
+ end
10
+ # Close the circle
11
+ coordinates << coordinates.first
12
+ from_coordinates [coordinates]
13
+ end
14
+
15
+ def side_count
16
+ # Reduce by one because polygon is closed
17
+ (rings.collect(&:size).sum) - 1
18
+ end
19
+
20
+ def points
21
+ rings.collect(&:points).flatten
22
+ end
23
+
24
+ def centroid
25
+ if rgeo_polygon = to_rgeo
26
+ rgeo_polygon.centroid.to_georuby
27
+ end
28
+ end
29
+
30
+ def self.union(georuby_polygons)
31
+ factory = RGeo::Geos::Factory.create
32
+ if !georuby_polygons.empty?
33
+ polygon_union = georuby_polygons.first.to_rgeo
34
+ georuby_polygons.shift
35
+ end
36
+
37
+ georuby_polygons.each do |polygon|
38
+ polygon_union = polygon_union.union(polygon.to_rgeo)
39
+ end
40
+
41
+ polygon_union.to_georuby
42
+ end
43
+
44
+ def self.intersection(georuby_polygons)
45
+ factory = RGeo::Geos::Factory.create
46
+ if !georuby_polygons.empty?
47
+ polygon_intersection = georuby_polygons.first.to_rgeo
48
+ georuby_polygons.shift
49
+ end
50
+
51
+ georuby_polygons.each do |polygon|
52
+ polygon_intersection = polygon_intersection.intersection(polygon.to_rgeo)
53
+ end
54
+
55
+ polygon_intersection.to_georuby
56
+ end
57
+
58
+ def to_wgs84
59
+ self.class.from_points([self.points.collect(&:to_wgs84)], 4326)
60
+ end
61
+
62
+ def to_rgeo
63
+ # take only the first ring for the outer ring of RGeo::Feature::Polygon
64
+ factory = RGeo::Geos::Factory.create #(:srid => srid)
65
+ polygon = factory.polygon(self.rings.collect(&:to_rgeo).first)
66
+ end
67
+
68
+ end
@@ -0,0 +1,11 @@
1
+ class Proj4::Projection
2
+
3
+ def self.wgs84
4
+ Proj4::Projection.new '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
5
+ end
6
+
7
+ def self.google
8
+ Proj4::Projection.new '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs'
9
+ end
10
+
11
+ end
@@ -0,0 +1,23 @@
1
+ class RGeo::Geos::PointImpl
2
+ def to_georuby
3
+ GeoRuby::SimpleFeatures::Point.from_x_y x, y, srid
4
+ end
5
+ end
6
+
7
+ class RGeo::Geos::LineStringImpl
8
+ def to_georuby
9
+ GeoRuby::SimpleFeatures::LineString.from_points points.collect(&:to_georuby), srid
10
+ end
11
+ end
12
+
13
+ class RGeo::Geos::PolygonImpl
14
+ def to_georuby
15
+ GeoRuby::SimpleFeatures::Polygon.from_linear_rings [exterior_ring.to_georuby], srid
16
+ end
17
+ end
18
+
19
+ class RGeo::Geos::MultiPolygonImpl
20
+ def to_georuby
21
+ GeoRuby::SimpleFeatures::MultiPolygon.from_polygons collect(&:to_georuby), srid
22
+ end
23
+ end
@@ -0,0 +1,61 @@
1
+ RSpec::Matchers.define :be_same_polygon do |reference|
2
+ match do |actual|
3
+ reference =
4
+ case reference
5
+ when Array
6
+ GeoRuby::SimpleFeatures::Polygon.from_coordinates [reference]
7
+ when String
8
+ geometry reference
9
+ else
10
+ reference
11
+ end
12
+
13
+ [actual.points, reference.points].transpose.all? do |actual_point, reference_point|
14
+ actual_point.euclidian_distance(reference_point) < 0.01
15
+ end
16
+ end
17
+ end
18
+
19
+ def geometry(text, srid = 4326)
20
+ GeoRuby::SimpleFeatures::Geometry.from_ewkt "SRID=#{srid};#{text}"
21
+ end
22
+
23
+ def point(x=0.0, y=0.0, srid = 4326)
24
+ GeoRuby::SimpleFeatures::Point.from_x_y(x,y,srid)
25
+ end
26
+
27
+ def points(text)
28
+ text.split(",").collect { |definition| geometry "POINT(#{definition})" }
29
+ end
30
+
31
+ def line_string(*points)
32
+ if points.one? and String === points.first
33
+ geometry("LINESTRING(#{points})")
34
+ else
35
+ GeoRuby::SimpleFeatures::LineString.from_points(points)
36
+ end
37
+ end
38
+
39
+ def linear_ring(*points)
40
+ GeoRuby::SimpleFeatures::LinearRing.from_points(points)
41
+ end
42
+
43
+ def polygon(*points)
44
+ GeoRuby::SimpleFeatures::Polygon.from_points([points])
45
+ end
46
+
47
+ def multi_polygon(*polygons)
48
+ GeoRuby::SimpleFeatures::MultiPolygon.from_polygons([polygons])
49
+ end
50
+
51
+ def rgeo_point(x = 0, y = 0, srid = 4326)
52
+ RGeo::Geos.factory(:srid => srid).point(x, y)
53
+ end
54
+
55
+ def rgeometry(text, srid = 4326)
56
+ RGeo::Geos.factory(:srid => srid).parse_wkt text
57
+ end
58
+
59
+ def rgeo_line_string(text, srid = 4326)
60
+ rgeometry "LINESTRING(#{text})"
61
+ end
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeoRuby::SimpleFeatures::LineString do
4
+
5
+ subject { line_string "0 0,1 1,0 0" }
6
+
7
+ describe "#to_rgeo" do
8
+ it "should create a RGeo Geos geometry" do
9
+ subject.to_rgeo.should be_kind_of(RGeo::Geos::GeometryImpl)
10
+ end
11
+
12
+ context "returned RGeo LineString" do
13
+ it "should have the same srid" do
14
+ subject.to_rgeo.srid.should == subject.srid
15
+ end
16
+ it "should have the points" do
17
+ line_string("0 0,1 1,0 0").to_rgeo.should == rgeo_line_string("0 0,1 1,0 0")
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "#==" do
23
+
24
+ it "should be true when points are same" do
25
+ line_string("0 0,1 1").should == line_string("0 0,1 1")
26
+ end
27
+
28
+ it "should be true when the other is LineRing with the same points" do
29
+ line_string("0 0,1 1,0 0").should == line_string("0 0,1 1,0 0").to_ring
30
+ end
31
+
32
+ end
33
+
34
+ describe "#to_ring" do
35
+
36
+ it "should be a GeoRuby::SimpleFeatures::LinearRing" do
37
+ subject.to_ring.should be_instance_of(GeoRuby::SimpleFeatures::LinearRing)
38
+ end
39
+
40
+ context "returned LinearRing" do
41
+
42
+ it "should have the same srid" do
43
+ subject.to_ring.should have_same(:srid).than(subject)
44
+ # subject.to_ring.srid.should == subject.srid
45
+ end
46
+
47
+ context "when line is closed" do
48
+ subject { line_string("0 0,1 1,0 0") }
49
+
50
+ it "should have the same points" do
51
+ subject.to_ring.points.should == subject.points
52
+ end
53
+ end
54
+
55
+ context "when line isn't closed" do
56
+ subject { line_string("0 0,1 1") }
57
+
58
+ it "should have the line points and the first one" do
59
+ subject.to_ring.points.should == (subject.points << subject.first)
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ describe "#change" do
68
+
69
+ let(:other_points) { subject.points + points("3 3") }
70
+
71
+ it "should change the points if specified" do
72
+ subject.change(:points => other_points).points.should == other_points
73
+ end
74
+
75
+ it "should change the points if specified" do
76
+ subject.change(:srid => 1).srid.should == 1
77
+ end
78
+
79
+ it "should not change unspecified attributes" do
80
+ subject.change(:points => other_points).should have_same(:srid, :with_z, :with_m).than(subject)
81
+ end
82
+
83
+ end
84
+
85
+ describe "#reverse" do
86
+
87
+ it "should return a LineString with reversed points" do
88
+ subject.reverse.points.should == subject.points.reverse
89
+ end
90
+
91
+ it "should not change other attributes" do
92
+ subject.reverse.should have_same(:srid, :with_z, :with_m).than(subject)
93
+ end
94
+
95
+ end
96
+
97
+ describe "#to_wgs84" do
98
+
99
+ it "should project all points into wgs84" do
100
+ subject.to_wgs84.points.each_with_index do |wgs84_point, index|
101
+ wgs84_point.should == subject[index].to_wgs84
102
+ end
103
+ end
104
+
105
+ it "should have the srid 4326" do
106
+ subject.to_wgs84.srid.should == 4326
107
+ end
108
+
109
+ it "should not change other attributes" do
110
+ subject.reverse.should have_same(:with_z, :with_m).than(subject)
111
+ end
112
+
113
+ end
114
+
115
+ it "should be closed when is_closed is true" do
116
+ subject.stub :is_closed => true
117
+ subject.should be_closed
118
+ end
119
+
120
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe GeoRuby::SimpleFeatures::LinearRing do
4
+ let(:result) {factory = RGeo::Geos::Factory.create
5
+ factory.linear_ring([factory.point(0, 0), factory.point(2, 1), factory.point(3, 2), factory.point(0, 0)])}
6
+
7
+ describe "to_rgeo" do
8
+ it "should create a RGeo::Feature::LinearRing" do
9
+ line = linear_ring(point(0,0), point(2,1), point(3,2), point(0,0))
10
+ line.to_rgeo.should == result
11
+ end
12
+
13
+ # it "should create a RGeo::Feature::LinearRing if the georuby linear ring is not closed" do
14
+ # line = linear_ring(point(0,0), point(2,1), point(3,2))
15
+ # line.to_rgeo.should == result
16
+ # end
17
+
18
+ end
19
+
20
+ describe "#to_wgs84" do
21
+ let(:line) {linear_ring(point(0,0), point(1,1), point(0,0))}
22
+ let(:line_wgs84) { GeoRuby::SimpleFeatures::LinearRing.from_points([point(0,0,4326), point(0.000008983152841195214, 0.000008983152840993819,4326), point(0,0,4326)], 4326)}
23
+
24
+ it "should return true when we compare line coordinates" do
25
+ line.to_wgs84.should == line_wgs84
26
+ end
27
+
28
+ it "should return same srid" do
29
+ line.to_wgs84.srid.should == line_wgs84.srid
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeoRuby::SimpleFeatures::MultiLineString do
4
+
5
+ def point(x, y)
6
+ GeoRuby::SimpleFeatures::Point.from_x_y x,y
7
+ end
8
+ def line(*xy)
9
+ GeoRuby::SimpleFeatures::LineString.from_coordinates [*xy]
10
+ end
11
+ def lines(*lines)
12
+ GeoRuby::SimpleFeatures::MultiLineString.from_line_strings lines
13
+ end
14
+
15
+ it "should create a valid ewkb" do
16
+ GeoRuby::SimpleFeatures::Geometry.from_ewkb(lines(line([0,0],[4,0]),line([0,2],[4,2])).as_ewkb)
17
+ end
18
+
19
+ describe "locate_point" do
20
+
21
+ context "examples" do
22
+
23
+ it "should find 2,1 at 0.5 between 0,0 and 4,0" do
24
+ lines(line([0,0],[4,0])).locate_point(point(2,1)).should == 0.5
25
+ end
26
+
27
+ it "should find 2,1 at 1.5 for (0,4)...(0,1) and (0,0)...(4,0)" do
28
+ lines(line([0,4],[0,1]), line([0,0],[4,0])).locate_point(point(2,1)).should == 1.5
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ describe "interpolate_point" do
36
+
37
+ context "examples" do
38
+
39
+ it "should find 0.5 at (2,0) between 0,0 and 4,0" do
40
+ lines(line([0,0],[4,0])).interpolate_point(0.5).should == point(2,0)
41
+ end
42
+
43
+ it "should find 1.5 at (2,0) for (0,4)...(0,1) and (0,0)...(4,0)" do
44
+ lines(line([0,4],[0,1]), line([0,0],[4,0])).interpolate_point(1.5).should == point(2,0)
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ describe GeoRuby::SimpleFeatures::LineString do
54
+
55
+ def point(x, y)
56
+ GeoRuby::SimpleFeatures::Point.from_x_y x,y
57
+ end
58
+ def line(*xy)
59
+ GeoRuby::SimpleFeatures::LineString.from_coordinates [*xy]
60
+ end
61
+
62
+ describe "locate_point" do
63
+
64
+ context "examples" do
65
+
66
+ it "should find 2,1 at 0.5 between 0,0 and 4,0" do
67
+ line([0,0],[4,0]).locate_point(point(2,1)).should == 0.5
68
+ end
69
+
70
+ it "should find 2,1 at 0.5 between 0,0 and 4,0 (with several segments)" do
71
+ line([0,0],[2,0],[4,0]).locate_point(point(2,1)).should == 0.5
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+
79
+ end
80
+
81
+ describe GeoRuby::SimpleFeatures::LineString::PointLocator do
82
+
83
+ def point(x, y)
84
+ GeoRuby::SimpleFeatures::Point.from_x_y x,y
85
+ end
86
+ alias_method :p, :point
87
+
88
+ def locator(target, departure, arrival)
89
+ GeoRuby::SimpleFeatures::LineString::PointLocator.new target, departure, arrival
90
+ end
91
+
92
+ context "examples" do
93
+
94
+ it "should locate 0,y at 0 between 0,0 and 4,0" do
95
+ -10.upto(10) do |y|
96
+ locator(p(0,y), p(0,0), p(4,0)).locate_point.should be_zero
97
+ end
98
+ end
99
+
100
+ it "should locate 2,y at 0.5 between 0,0 and 4,0" do
101
+ -10.upto(10) do |y|
102
+ locator(p(2,y), p(0,0), p(4,0)).locate_point.should == 0.5
103
+ end
104
+ end
105
+
106
+ it "should locate 4,y at 1 between 0,0 and 4,0" do
107
+ -10.upto(10) do |y|
108
+ locator(p(4,y), p(0,0), p(4,0)).locate_point.should == 1
109
+ end
110
+ end
111
+
112
+ it "should find 2,y at a distance of y from 0,0 and 4,0" do
113
+ -10.upto(10) do |y|
114
+ locator(p(2,y), p(0,0), p(4,0)).distance_from_segment.should be_within(0.001).of(y.abs)
115
+ end
116
+ end
117
+
118
+ end
119
+
120
+ end