georuby-ext 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.jrubyrc +1 -0
  2. data/.travis.yml +23 -0
  3. data/Gemfile +6 -0
  4. data/Guardfile +12 -2
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +2 -28
  7. data/georuby-ext.gemspec +14 -11
  8. data/lib/georuby-ext.rb +17 -2
  9. data/lib/georuby-ext/core_ext.rb +11 -0
  10. data/lib/georuby-ext/geokit.rb +10 -3
  11. data/lib/georuby-ext/georuby/envelope.rb +36 -1
  12. data/lib/georuby-ext/georuby/ewkb_parser.rb +11 -0
  13. data/lib/georuby-ext/georuby/ewkt_parser.rb +11 -0
  14. data/lib/georuby-ext/georuby/geometry.rb +46 -2
  15. data/lib/georuby-ext/georuby/line_string.rb +19 -7
  16. data/lib/georuby-ext/georuby/linear_ring.rb +15 -0
  17. data/lib/georuby-ext/georuby/locators.rb +30 -17
  18. data/lib/georuby-ext/georuby/multi_polygon.rb +15 -1
  19. data/lib/georuby-ext/georuby/point.rb +148 -24
  20. data/lib/georuby-ext/georuby/polygon.rb +38 -27
  21. data/lib/georuby-ext/georuby/rtree.rb +133 -0
  22. data/lib/georuby-ext/georuby/srid.rb +17 -0
  23. data/lib/georuby-ext/proj4.rb +15 -2
  24. data/lib/georuby-ext/rgeo/cartesian/feature_methods.rb +58 -0
  25. data/lib/georuby-ext/rgeo/feature/geometry.rb +11 -0
  26. data/lib/georuby-ext/rgeo/feature/geometry_collection.rb +11 -0
  27. data/lib/georuby-ext/rgeo/feature/rgeo.rb +157 -0
  28. data/lib/georuby-ext/rgeo/geos/ffi_feature_methods.rb +265 -0
  29. data/lib/georuby-ext/rspec_helper.rb +47 -8
  30. data/spec/lib/geokit_spec.rb +44 -0
  31. data/spec/lib/georuby/envelope_spec.rb +46 -0
  32. data/spec/lib/georuby/geometry_spec.rb +81 -0
  33. data/spec/{georuby → lib/georuby}/line_string_spec.rb +29 -14
  34. data/spec/lib/georuby/linear_ring_spec.rb +52 -0
  35. data/spec/lib/georuby/locators_spec.rb +123 -0
  36. data/spec/lib/georuby/multi_polygon_spec.rb +69 -0
  37. data/spec/lib/georuby/point_spec.rb +248 -0
  38. data/spec/lib/georuby/polygon_spec.rb +175 -0
  39. data/spec/lib/georuby/rtree_spec.rb +132 -0
  40. data/spec/lib/proj4_spec.rb +24 -0
  41. data/spec/lib/rgeo/cartesian/feature_methods_spec.rb +110 -0
  42. data/spec/lib/rgeo/geos/ffi_feature_methods_spec.rb +234 -0
  43. data/spec/spec_helper.rb +12 -8
  44. metadata +224 -189
  45. data/lib/georuby-ext/rgeo.rb +0 -23
  46. data/spec/georuby/linear_ring_spec.rb +0 -33
  47. data/spec/georuby/locators_spec.rb +0 -120
  48. data/spec/georuby/multi_polygon_spec.rb +0 -29
  49. data/spec/georuby/point_spec.rb +0 -44
  50. data/spec/georuby/polygon_spec.rb +0 -134
  51. data/spec/rgeo_spec.rb +0 -81
@@ -21,39 +21,78 @@ def geometry(text, srid = 4326)
21
21
  end
22
22
 
23
23
  def point(x=0.0, y=0.0, srid = 4326)
24
- GeoRuby::SimpleFeatures::Point.from_x_y(x,y,srid)
24
+ if String === x
25
+ geometry("POINT(#{x})")
26
+ else
27
+ GeoRuby::SimpleFeatures::Point.from_x_y x, y, srid
28
+ end
25
29
  end
26
30
 
27
31
  def points(text)
28
- text.split(",").collect { |definition| geometry "POINT(#{definition})" }
32
+ text.split(",").collect { |definition| point definition }
29
33
  end
30
34
 
31
35
  def line_string(*points)
32
36
  if points.one? and String === points.first
33
37
  geometry("LINESTRING(#{points})")
34
38
  else
35
- GeoRuby::SimpleFeatures::LineString.from_points(points)
39
+ GeoRuby::SimpleFeatures::LineString.from_points(points, points.first.srid)
40
+ end
41
+ end
42
+
43
+ def multi_line_string(*lines)
44
+ if lines.one? and String === lines.first
45
+ geometry("MULTILINESTRING(#{lines})")
46
+ else
47
+ GeoRuby::SimpleFeatures::MultiLineString.from_line_strings lines, lines.first.srid
36
48
  end
37
49
  end
38
50
 
39
51
  def linear_ring(*points)
40
- GeoRuby::SimpleFeatures::LinearRing.from_points(points)
52
+ GeoRuby::SimpleFeatures::LinearRing.from_points(points, points.first.srid)
53
+ end
54
+
55
+ def envelope(lower_corner, upper_corner)
56
+ lower_corner = point(lower_corner) if String === lower_corner
57
+ upper_corner = point(upper_corner) if String === upper_corner
58
+
59
+ GeoRuby::SimpleFeatures::Envelope.from_points([lower_corner, upper_corner], lower_corner.srid)
41
60
  end
42
61
 
43
62
  def polygon(*points)
44
- GeoRuby::SimpleFeatures::Polygon.from_points([points])
63
+ if points.one? and String === points.first
64
+ geometry("POLYGON(#{points})")
65
+ else
66
+ GeoRuby::SimpleFeatures::Polygon.from_points([points], points.first.srid)
67
+ end
45
68
  end
46
69
 
47
70
  def multi_polygon(*polygons)
48
- GeoRuby::SimpleFeatures::MultiPolygon.from_polygons([polygons])
71
+ GeoRuby::SimpleFeatures::MultiPolygon.from_polygons([polygons], polygons.first.srid)
72
+ end
73
+
74
+ def rgeo_factory
75
+ @rgeo_factory ||= RGeo::Geos.factory(:srid => 4326, :wkt_parser => {:support_ewkt => true})
49
76
  end
50
77
 
51
78
  def rgeo_point(x = 0, y = 0, srid = 4326)
52
- RGeo::Geos.factory(:srid => srid).point(x, y)
79
+ rgeo_factory.point(x, y)
80
+ end
81
+
82
+ def rgeo_multi_polygon(polygons, srid = 4326)
83
+ rgeo_factory.multi_polygon(polygons)
84
+ end
85
+
86
+ def rgeo_multi_line_string(multi_line_string, srid = 4326)
87
+ if lines.one? and String === lines.first
88
+ geometry("MULTILINESTRING(#{lines})")
89
+ else
90
+ Rgeo::Geos::MultiLineString.from_line_strings lines, lines.first.srid
91
+ end
53
92
  end
54
93
 
55
94
  def rgeometry(text, srid = 4326)
56
- RGeo::Geos.factory(:srid => srid).parse_wkt text
95
+ rgeo_factory.parse_wkt text
57
96
  end
58
97
 
59
98
  def rgeo_line_string(text, srid = 4326)
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe GeoKit::LatLng do
4
+
5
+ subject { GeoKit::LatLng.new }
6
+
7
+ describe "#valid?" do
8
+
9
+ it "should be invalid when lat is nil" do
10
+ subject.lat, subject.lng = nil, 45
11
+ subject.should_not be_valid
12
+ end
13
+
14
+ it "should be invalid when lng is nil" do
15
+ subject.lat, subject.lng = 45, nil
16
+ subject.should_not be_valid
17
+ end
18
+
19
+ it "should be valid when lat is between -90 and 90, lng between -180 and 180" do
20
+ subject.lat, subject.lng = 45, 90
21
+ subject.should be_valid
22
+ end
23
+
24
+ end
25
+
26
+ describe "#wgs84_to_google" do
27
+
28
+ it "should return google coordinates" do
29
+ subject.lat, subject.lng = 45, 90
30
+ #subject.wgs84_to_google.eql?(Geokit::LatLng.new(5621521.48619207, 10018754.1713946)).should be_true
31
+ end
32
+
33
+ end
34
+
35
+ describe "#google_to_wgs84" do
36
+
37
+ it "should wgs84 coordinates" do
38
+ subject.lat, subject.lng = 45, 90
39
+ #subject.google_to_wgs84.eql?(Geokit::LatLng.new(0.000404241877844722, 0.000808483755707569)).should be_true
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeoRuby::SimpleFeatures::Envelope do
4
+
5
+ subject { envelope point(0,0), point(1,1) }
6
+
7
+ describe "#to_google" do
8
+
9
+ it "should return an Envelope with Google srid" do
10
+ subject.to_google.srid.should == 900913
11
+ end
12
+
13
+ end
14
+
15
+ describe "to_polygon" do
16
+ let(:geo_polygon){ polygon(point(0,0), point(0,1), point(1,1), point(1,0), point(0,0))}
17
+ let(:geo_envelope) { envelope( point(0,0), point(1,1) ) }
18
+
19
+ it "should return a polygon GeoRuby::SimpleFeatures::Polygon" do
20
+ (geo_envelope.to_polygon == geo_polygon).should be_true
21
+ end
22
+ end
23
+
24
+ describe ".bounds" do
25
+
26
+ it "should return a global bounds of children" do
27
+ geometries = [polygon("(0 0,1 1,1 0, 0 0)"), polygon("(1 1,2 2,2 0, 1 1)")]
28
+ GeoRuby::SimpleFeatures::Envelope.bounds(geometries).should == envelope("0 0","2 2")
29
+ end
30
+ end
31
+
32
+ describe ".overlaps?" do
33
+
34
+ it "should return true if bound is included in envelope" do
35
+ bound = envelope("0 0","1 1")
36
+ envelope("0 0","2 2").overlaps?(bound).should == true
37
+ end
38
+
39
+ it "should return true if bound intersects envelope" do
40
+ bound = envelope("0 0","1 1")
41
+ envelope("0.5 0.5","2 2").overlaps?(bound).should == true
42
+ end
43
+ end
44
+
45
+
46
+ end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ describe GeoRuby::SimpleFeatures::Geometry do
4
+
5
+ subject { point }
6
+
7
+ describe "#to_ewkt" do
8
+
9
+ it "should return as_ewkt result" do
10
+ subject.to_ewkt.should == subject.as_ewkt
11
+ end
12
+
13
+ end
14
+
15
+ it "should be wgs84 when srid == 4326" do
16
+ subject.srid = 4326
17
+ subject.should be_wgs84
18
+ end
19
+
20
+ it "should not be wgs84 when srid isn't 4326" do
21
+ subject.srid = 900913
22
+ subject.should_not be_wgs84
23
+ end
24
+
25
+ describe "#inspect" do
26
+
27
+ it "should include geometry class name" do
28
+ subject.inspect.should include(subject.class.name)
29
+ end
30
+
31
+ it "should include geometry ekwt" do
32
+ subject.inspect.should include(subject.to_ewkt)
33
+ end
34
+
35
+ end
36
+
37
+ describe ".srid!" do
38
+
39
+ it "should return the uniq srid of given geometries" do
40
+ GeoRuby::SimpleFeatures::Geometry.srid!([point.to_google]).should == 900913
41
+ end
42
+
43
+ it "should raise an error when srid is not uniq" do
44
+ lambda do
45
+ GeoRuby::SimpleFeatures::Geometry.srid!([point, point.to_google])
46
+ end.should raise_error
47
+ end
48
+
49
+ end
50
+
51
+ describe "#to_wgs84" do
52
+
53
+ let(:projected_geometry) { mock }
54
+
55
+ it "should return a geometry with 4326 srid" do
56
+ subject.to_wgs84.srid.should == 4326
57
+ end
58
+
59
+ it "should project the geometry in wgs84" do
60
+ subject.should_receive(:project_to).with(4326).and_return(projected_geometry)
61
+ subject.to_wgs84.should == projected_geometry
62
+ end
63
+
64
+ end
65
+
66
+ describe "#to_google" do
67
+
68
+ let(:projected_geometry) { mock }
69
+
70
+ it "should return a geometry with 900913 srid" do
71
+ subject.to_google.srid.should == 900913
72
+ end
73
+
74
+ it "should project the geometry in google" do
75
+ subject.should_receive(:project_to).with(900913).and_return(projected_geometry)
76
+ subject.to_google.should == projected_geometry
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -5,9 +5,6 @@ describe GeoRuby::SimpleFeatures::LineString do
5
5
  subject { line_string "0 0,1 1,0 0" }
6
6
 
7
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
8
 
12
9
  context "returned RGeo LineString" do
13
10
  it "should have the same srid" do
@@ -41,7 +38,6 @@ describe GeoRuby::SimpleFeatures::LineString do
41
38
 
42
39
  it "should have the same srid" do
43
40
  subject.to_ring.should have_same(:srid).than(subject)
44
- # subject.to_ring.srid.should == subject.srid
45
41
  end
46
42
 
47
43
  context "when line is closed" do
@@ -72,7 +68,7 @@ describe GeoRuby::SimpleFeatures::LineString do
72
68
  subject.change(:points => other_points).points.should == other_points
73
69
  end
74
70
 
75
- it "should change the points if specified" do
71
+ it "should change the srid if specified" do
76
72
  subject.change(:srid => 1).srid.should == 1
77
73
  end
78
74
 
@@ -94,27 +90,46 @@ describe GeoRuby::SimpleFeatures::LineString do
94
90
 
95
91
  end
96
92
 
97
- describe "#to_wgs84" do
93
+ describe "#project_to" do
94
+
95
+ let(:target_srid) { 900913 }
96
+ subject { line_string("0 0,1 1,0 0") }
98
97
 
99
98
  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
99
+ subject.project_to(target_srid).points.each_with_index do |point, index|
100
+ point.should == subject[index].project_to(target_srid)
102
101
  end
103
102
  end
104
103
 
105
- it "should have the srid 4326" do
106
- subject.to_wgs84.srid.should == 4326
104
+ it "should have the target srid" do
105
+ subject.project_to(target_srid).srid.should == target_srid
107
106
  end
108
107
 
109
108
  it "should not change other attributes" do
110
- subject.reverse.should have_same(:with_z, :with_m).than(subject)
109
+ subject.project_to(target_srid).should have_same(:with_z, :with_m).than(subject)
110
+ end
111
+
112
+ end
113
+
114
+ describe "#close!" do
115
+
116
+ it "should add first point if needed" do
117
+ line_string("0 0,1 1").close!.should == line_string("0 0,1 1,0 0")
118
+ end
119
+
120
+ it "should not change a closed line" do
121
+ line_string("0 0,1 1,0 0").close!.should == line_string("0 0,1 1,0 0")
111
122
  end
112
123
 
113
124
  end
114
125
 
115
- it "should be closed when is_closed is true" do
116
- subject.stub :is_closed => true
117
- subject.should be_closed
126
+ describe "#side_count" do
127
+
128
+ it "should return point count minus one" do
129
+ line_string("0 0,1 1,2 2").side_count.should == 2
130
+ end
131
+
118
132
  end
119
133
 
120
134
  end
135
+
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe GeoRuby::SimpleFeatures::LinearRing do
4
+ let(:result) { rgeo_factory.linear_ring([rgeo_point(0, 0), rgeo_point(2, 1), rgeo_point(3, 2), rgeo_point(0, 0)])}
5
+
6
+ describe "to_rgeo" do
7
+ it "should create a RGeo::Feature::LinearRing" do
8
+ line = linear_ring(point(0,0), point(2,1), point(3,2), point(0,0))
9
+ line.to_rgeo.should == result
10
+ end
11
+
12
+ it "should create a RGeo::Feature::LinearRing if the georuby linear ring is not closed" do
13
+ line = linear_ring(point(0,0), point(2,1), point(3,2))
14
+ line.to_rgeo.should == result
15
+ end
16
+
17
+ end
18
+
19
+ describe ".from_points" do
20
+
21
+ it "should be closed even if last point is missing" do
22
+ GeoRuby::SimpleFeatures::LinearRing.from_points(points("0 0,1 1,0 0")).should be_closed
23
+ end
24
+
25
+ it "should accept already closed line" do
26
+ GeoRuby::SimpleFeatures::LinearRing.from_points(points("0 0,1 1,0 0")).should == line_string("0 0,1 1,0 0")
27
+ end
28
+
29
+ end
30
+
31
+ describe ".from_coordinates" do
32
+
33
+ it "should be closed even if last point is missing" do
34
+ GeoRuby::SimpleFeatures::LinearRing.from_coordinates([[0,0],[1,1],[0,0]]).should be_closed
35
+ end
36
+
37
+ it "should accept already closed line" do
38
+ GeoRuby::SimpleFeatures::LinearRing.from_coordinates([[0,0],[1,1],[0,0]]).should == line_string("0 0,1 1,0 0")
39
+ end
40
+
41
+ end
42
+
43
+ it "should close linear rings parsed from ekt" do
44
+ polygon("(0 0,1 1)").rings.first.should be_closed
45
+ end
46
+
47
+ it "should close linear rings parsed from ekb" do
48
+ ewkb_polygon = GeoRuby::SimpleFeatures::Geometry.from_ewkb(polygon("(0 0,1 1,0 0)").as_ewkb)
49
+ ewkb_polygon.rings.first.should be_closed
50
+ end
51
+
52
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeoRuby::SimpleFeatures::MultiLineString do
4
+
5
+ describe "locate_point" do
6
+
7
+ context "examples" do
8
+
9
+ # it "should find 2,1 at 0.5 between 0,0 and 4,0" do
10
+ # multi_line_string("(0 0,4 0)").locate_point(point(2,1)).should == 0.5
11
+ # end
12
+
13
+ # it "should find 2,1 at 1.5 for (0,4)...(0,1) and (0,0)...(4,0)" do
14
+ # multi_line_string("(0 4,0 1),(0 0,4 0)").locate_point(point(2,1)).should == 1.5
15
+ # end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ describe "interpolate_point" do
22
+
23
+ context "examples" do
24
+
25
+ it "should find 0.5 at (2,0) between 0,0 and 4,0" do
26
+ multi_line_string("(0 0,4 0)").interpolate_point(0.5).should == point(2,0)
27
+ end
28
+
29
+ it "should find 1.5 at (2,0) for (0,4)...(0,1) and (0,0)...(4,0)" do
30
+ multi_line_string("(0 4,0 1),(0 0,4 0)").interpolate_point(1.5).should == point(2,0)
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ describe GeoRuby::SimpleFeatures::LineString do
40
+
41
+ describe "locate_point" do
42
+
43
+ # context "examples" do
44
+
45
+ # it "should find 2,1 at 0.5 between 0,0 and 4,0" do
46
+ # line_string("0 0,4 0").locate_point(point(2,1)).should == 0.5
47
+ # end
48
+
49
+ # it "should find 2,1 at 0.5 between 0,0 and 4,0 (with several segments)" do
50
+ # line_string("0 0,2 0,4 0").locate_point(point(2,1)).should == 0.5
51
+ # end
52
+
53
+ # end
54
+
55
+ it "should find Tour Eiffel at 0.434073695339917 on Avenue Gustave Eiffel" do
56
+ tour_eiffel = point 2.2946, 48.8580
57
+ avenue_gustave_eiffel = line_string "2.29406861440145 48.8570391455916,2.29498049424636 48.8576531708278,2.29540512788116 48.8579392878211,2.29634853859254 48.8585744605187"
58
+ expected_location = 0.434073695339917
59
+
60
+ avenue_gustave_eiffel.locate_point(tour_eiffel).should be_within(0.001).of(expected_location)
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ describe GeoRuby::SimpleFeatures::LineString::PointLocator do
68
+
69
+ alias_method :p, :point
70
+
71
+ def locator(target, departure, arrival)
72
+ GeoRuby::SimpleFeatures::LineString::PointLocator.new target, departure, arrival
73
+ end
74
+
75
+ describe "distance_from_segment" do
76
+
77
+ it "should be zero if target is the segment departure" do
78
+ departure = point(0, 0)
79
+ locator(departure, departure, p(1,1)).distance_from_segment.should be_zero
80
+ end
81
+
82
+ it "should be zero if target is the segment arrival" do
83
+ arrival = point(0, 0)
84
+ locator(arrival, p(1,1), arrival).distance_from_segment.should be_zero
85
+ end
86
+
87
+ end
88
+
89
+ context "examples" do
90
+
91
+ it "should find right angle between 3 points" do
92
+ origin = tour_eiffel = point(2.2946, 48.8580)
93
+ locator(origin.endpoint(45, 100), origin, origin.endpoint(90, 100)).angle.rad2deg.should be_within(0.001).of(45)
94
+ end
95
+
96
+ # it "should locate 0,y at 0 between 0,0 and 4,0" do
97
+ # -10.upto(10) do |y|
98
+ # locator(p(0,y), p(0,0), p(4,0)).locate_point.should be_zero
99
+ # end
100
+ # end
101
+
102
+ # it "should locate 2,y at 0.5 between 0,0 and 4,0" do
103
+ # -10.upto(10) do |y|
104
+ # locator(p(2,y), p(0,0), p(4,0)).locate_point.should == 0.5
105
+ # end
106
+ # end
107
+
108
+ # it "should locate 4,y at 1 between 0,0 and 4,0" do
109
+ # -10.upto(10) do |y|
110
+ # locator(p(4,y), p(0,0), p(4,0)).locate_point.should == 1
111
+ # end
112
+ # end
113
+
114
+ # it "should find 2,y at a distance of y from 0,0 and 4,0" do
115
+ # -10.upto(10) do |y|
116
+ # locator(p(2,y), p(0,0), p(4,0)).distance_from_segment.should be_within(0.001).of(y.abs)
117
+ # end
118
+ # end
119
+
120
+ end
121
+
122
+
123
+ end