georuby-ext 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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