georuby 1.9.3

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.
Files changed (75) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +29 -0
  3. data/History.txt +4 -0
  4. data/LICENSE +21 -0
  5. data/README.rdoc +184 -0
  6. data/Rakefile +48 -0
  7. data/VERSION +1 -0
  8. data/georuby.gemspec +128 -0
  9. data/lib/geo_ruby.rb +23 -0
  10. data/lib/geo_ruby/geojson.rb +129 -0
  11. data/lib/geo_ruby/georss.rb +133 -0
  12. data/lib/geo_ruby/gpx.rb +1 -0
  13. data/lib/geo_ruby/gpx4r/gpx.rb +118 -0
  14. data/lib/geo_ruby/shp.rb +1 -0
  15. data/lib/geo_ruby/shp4r/dbf.rb +42 -0
  16. data/lib/geo_ruby/shp4r/shp.rb +718 -0
  17. data/lib/geo_ruby/simple_features/envelope.rb +167 -0
  18. data/lib/geo_ruby/simple_features/ewkb_parser.rb +218 -0
  19. data/lib/geo_ruby/simple_features/ewkt_parser.rb +336 -0
  20. data/lib/geo_ruby/simple_features/geometry.rb +236 -0
  21. data/lib/geo_ruby/simple_features/geometry_collection.rb +144 -0
  22. data/lib/geo_ruby/simple_features/geometry_factory.rb +81 -0
  23. data/lib/geo_ruby/simple_features/helper.rb +18 -0
  24. data/lib/geo_ruby/simple_features/line_string.rb +228 -0
  25. data/lib/geo_ruby/simple_features/linear_ring.rb +34 -0
  26. data/lib/geo_ruby/simple_features/multi_line_string.rb +63 -0
  27. data/lib/geo_ruby/simple_features/multi_point.rb +58 -0
  28. data/lib/geo_ruby/simple_features/multi_polygon.rb +64 -0
  29. data/lib/geo_ruby/simple_features/point.rb +381 -0
  30. data/lib/geo_ruby/simple_features/polygon.rb +175 -0
  31. data/nofxx-georuby.gemspec +149 -0
  32. data/spec/data/geojson/feature_collection.json +34 -0
  33. data/spec/data/georss/atom.xml +21 -0
  34. data/spec/data/georss/gml.xml +40 -0
  35. data/spec/data/georss/w3c.xml +22 -0
  36. data/spec/data/gpx/fells_loop.gpx +1077 -0
  37. data/spec/data/gpx/long.gpx +1642 -0
  38. data/spec/data/gpx/long.kml +31590 -0
  39. data/spec/data/gpx/long.nmea +2220 -0
  40. data/spec/data/gpx/short.gpx +13634 -0
  41. data/spec/data/gpx/short.kml +130 -0
  42. data/spec/data/gpx/tracktreks.gpx +706 -0
  43. data/spec/data/multipoint.dbf +0 -0
  44. data/spec/data/multipoint.shp +0 -0
  45. data/spec/data/multipoint.shx +0 -0
  46. data/spec/data/point.dbf +0 -0
  47. data/spec/data/point.shp +0 -0
  48. data/spec/data/point.shx +0 -0
  49. data/spec/data/polygon.dbf +0 -0
  50. data/spec/data/polygon.shp +0 -0
  51. data/spec/data/polygon.shx +0 -0
  52. data/spec/data/polyline.dbf +0 -0
  53. data/spec/data/polyline.shp +0 -0
  54. data/spec/data/polyline.shx +0 -0
  55. data/spec/geo_ruby/geojson_spec.rb +147 -0
  56. data/spec/geo_ruby/georss.rb +218 -0
  57. data/spec/geo_ruby/georss_spec.rb +14 -0
  58. data/spec/geo_ruby/gpx4r/gpx_spec.rb +106 -0
  59. data/spec/geo_ruby/shp4r/shp_spec.rb +239 -0
  60. data/spec/geo_ruby/simple_features/envelope_spec.rb +47 -0
  61. data/spec/geo_ruby/simple_features/ewkb_parser_spec.rb +158 -0
  62. data/spec/geo_ruby/simple_features/ewkt_parser_spec.rb +179 -0
  63. data/spec/geo_ruby/simple_features/geometry_collection_spec.rb +55 -0
  64. data/spec/geo_ruby/simple_features/geometry_factory_spec.rb +11 -0
  65. data/spec/geo_ruby/simple_features/geometry_spec.rb +32 -0
  66. data/spec/geo_ruby/simple_features/line_string_spec.rb +259 -0
  67. data/spec/geo_ruby/simple_features/linear_ring_spec.rb +24 -0
  68. data/spec/geo_ruby/simple_features/multi_line_string_spec.rb +54 -0
  69. data/spec/geo_ruby/simple_features/multi_point_spec.rb +35 -0
  70. data/spec/geo_ruby/simple_features/multi_polygon_spec.rb +50 -0
  71. data/spec/geo_ruby/simple_features/point_spec.rb +356 -0
  72. data/spec/geo_ruby/simple_features/polygon_spec.rb +122 -0
  73. data/spec/geo_ruby_spec.rb +27 -0
  74. data/spec/spec_helper.rb +73 -0
  75. metadata +228 -0
@@ -0,0 +1,18 @@
1
+ module GeoRuby
2
+ module SimpleFeatures
3
+ #indicates the presence of Z coordinates in EWKB strings
4
+ Z_MASK=0x80000000
5
+ #indicates the presence of M coordinates in EWKB strings.
6
+ M_MASK=0x40000000
7
+ #indicate the presence of a SRID in EWKB strings.
8
+ SRID_MASK=0x20000000
9
+ #GeoRSS namespace
10
+ GEORSS_NS = "http://www.georss.org/georss"
11
+ #GML Namespace
12
+ GML_NS = "http://www.opengis.net/gml"
13
+ #W3CGeo Namespace
14
+ W3CGEO_NS = "http://www.w3.org/2003/01/geo/wgs84_pos#"
15
+ #KML Namespace
16
+ KML_NS = "http://earth.google.com/kml/2.1"
17
+ end
18
+ end
@@ -0,0 +1,228 @@
1
+ require "geo_ruby/simple_features/geometry"
2
+
3
+ module GeoRuby
4
+ module SimpleFeatures
5
+ #Represents a line string as an array of points (see Point).
6
+ class LineString < Geometry
7
+ #the list of points forming the line string
8
+ attr_reader :points
9
+
10
+ def initialize(srid= DEFAULT_SRID,with_z=false,with_m=false)
11
+ super(srid,with_z,with_m)
12
+ @points=[]
13
+ end
14
+
15
+ #Delegate the unknown methods to the points array
16
+ def method_missing(method_name,*args,&b)
17
+ @points.send(method_name,*args,&b)
18
+ end
19
+
20
+ #tests if the line string is closed
21
+ def is_closed
22
+ #a bit naive...
23
+ @points.first == @points.last
24
+ end
25
+ alias :closed? :is_closed
26
+
27
+ def clockwise?
28
+ tuples = @points.zip(
29
+ @points[1..-1] + [@points[0]],
30
+ @points[2..-1] + [@points[0], @points[1]])
31
+ tuples.map!{ |a,b,c| b.x * (c.y - a.y) }
32
+ sum = tuples.inject(0.0){ |sum, elem| sum+elem }
33
+
34
+ sum < 0.0
35
+ end
36
+
37
+ #Bounding box in 2D/3D. Returns an array of 2 points
38
+ def bounding_box
39
+ max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
40
+ if(with_z)
41
+ max_z, min_z = -Float::MAX,Float::MAX
42
+ each do |point|
43
+ max_y = point.y if point.y > max_y
44
+ min_y = point.y if point.y < min_y
45
+ max_x = point.x if point.x > max_x
46
+ min_x = point.x if point.x < min_x
47
+ max_z = point.z if point.z > max_z
48
+ min_z = point.z if point.z < min_z
49
+ end
50
+ [Point.from_x_y_z(min_x,min_y,min_z),Point.from_x_y_z(max_x,max_y,max_z)]
51
+ else
52
+ each do |point|
53
+ max_y = point.y if point.y > max_y
54
+ min_y = point.y if point.y < min_y
55
+ max_x = point.x if point.x > max_x
56
+ min_x = point.x if point.x < min_x
57
+ end
58
+ [Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
59
+ end
60
+ end
61
+
62
+ def m_range
63
+ if with_m
64
+ max_m, min_m = -Float::MAX, Float::MAX
65
+ each do |point|
66
+ max_m = point.m if point.m > max_m
67
+ min_m = point.m if point.m < min_m
68
+ end
69
+ [min_m,max_m]
70
+ else
71
+ [0,0]
72
+ end
73
+ end
74
+
75
+ #call to native Geo intersect, return true or false
76
+ def intersects?(other_line_string)
77
+
78
+ end
79
+
80
+ def spherical_distance
81
+ total = 0
82
+ @points.each_with_index do |p,i|
83
+ total += p.spherical_distance(@points[i+1]) if @points[i+1]
84
+ end
85
+ total
86
+ end
87
+
88
+ def euclidian_distance
89
+ total = 0
90
+ @points.each_with_index do |p,i|
91
+ total += p.euclidian_distance(@points[i+1]) if @points[i+1]
92
+ end
93
+ total
94
+ end
95
+
96
+ #Tests the equality of line strings
97
+ def ==(other_line_string)
98
+ if(other_line_string.class != self.class or
99
+ other_line_string.length != self.length)
100
+ false
101
+ else
102
+ index=0
103
+ while index<length
104
+ return false if self[index] != other_line_string[index]
105
+ index+=1
106
+ end
107
+ true
108
+ end
109
+ end
110
+
111
+ #Binary representation of a line string
112
+ def binary_representation(allow_z=true,allow_m=true) #:nodoc:
113
+ rep = [length].pack("V")
114
+ each {|point| rep << point.binary_representation(allow_z,allow_m) }
115
+ rep
116
+ end
117
+
118
+ #WKB geometry type
119
+ def binary_geometry_type #:nodoc:
120
+ 2
121
+ end
122
+
123
+ #Text representation of a line string
124
+ def text_representation(allow_z=true,allow_m=true) #:nodoc:
125
+ @points.collect{|point| point.text_representation(allow_z,allow_m) }.join(",")
126
+ end
127
+ #WKT geometry type
128
+ def text_geometry_type #:nodoc:
129
+ "LINESTRING"
130
+ end
131
+
132
+ #georss simple representation
133
+ def georss_simple_representation(options) #:nodoc:
134
+ georss_ns = options[:georss_ns] || "georss"
135
+ geom_attr = options[:geom_attr]
136
+ "<#{georss_ns}:line#{geom_attr}>" + georss_poslist + "</#{georss_ns}:line>\n"
137
+ end
138
+ #georss w3c representation : outputs the first point of the line
139
+ def georss_w3cgeo_representation(options) #:nodoc:
140
+ w3cgeo_ns = options[:w3cgeo_ns] || "geo"
141
+ "<#{w3cgeo_ns}:lat>#{self[0].y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{self[0].x}</#{w3cgeo_ns}:long>\n"
142
+ end
143
+ #georss gml representation
144
+ def georss_gml_representation(options) #:nodoc:
145
+ georss_ns = options[:georss_ns] || "georss"
146
+ gml_ns = options[:gml_ns] || "gml"
147
+
148
+ result = "<#{georss_ns}:where>\n<#{gml_ns}:LineString>\n<#{gml_ns}:posList>\n"
149
+ result += georss_poslist
150
+ result += "\n</#{gml_ns}:posList>\n</#{gml_ns}:LineString>\n</#{georss_ns}:where>\n"
151
+ end
152
+
153
+ def georss_poslist #:nodoc:
154
+ map {|point| "#{point.y} #{point.x}"}.join(" ")
155
+ end
156
+
157
+ #outputs the geometry in kml format : options are <tt>:id</tt>, <tt>:tesselate</tt>, <tt>:extrude</tt>,
158
+ #<tt>:altitude_mode</tt>. If the altitude_mode option is not present, the Z (if present) will not be output (since
159
+ #it won't be used by GE anyway: clampToGround is the default)
160
+ def kml_representation(options = {}) #:nodoc:
161
+ result = "<LineString#{options[:id_attr]}>\n"
162
+ result += options[:geom_data] if options[:geom_data]
163
+ result += "<coordinates>"
164
+ result += kml_poslist(options)
165
+ result += "</coordinates>\n"
166
+ result += "</LineString>\n"
167
+ end
168
+
169
+ def kml_poslist(options) #:nodoc:
170
+ pos_list = if options[:allow_z]
171
+ map {|point| "#{point.x},#{point.y},#{options[:fixed_z] || point.z || 0}" }
172
+ else
173
+ map {|point| "#{point.x},#{point.y}" }
174
+ end
175
+ pos_list.reverse! if(options[:reverse])
176
+ pos_list.join(" ")
177
+ end
178
+
179
+ # Simplify linestring (Douglas Peucker Algorithm)
180
+ # http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
181
+ def simplify(epsilon=1)
182
+ LineString.from_points(do_simplify(@points, epsilon))
183
+ end
184
+
185
+ def do_simplify(list, epsilon)
186
+ index = dmax = 0
187
+ 2.upto(list.length - 1) do |i|
188
+ d = list[i].orthogonal_distance(list[0], list[-1])
189
+ index, dmax = i, d if d > dmax
190
+ end
191
+
192
+ if dmax >= epsilon
193
+ res1 = do_simplify(list[0..index], epsilon)
194
+ res2 = do_simplify(list[index..-1], epsilon)
195
+ res1[0..-2] + res2[0..-1]
196
+ else
197
+ [list[0], list[-1]]
198
+ end
199
+ end
200
+
201
+ def to_coordinates
202
+ points.map{|p| p.to_coordinates }
203
+ end
204
+
205
+ # simple geojson representation
206
+ # TODO add CRS / SRID support?
207
+ def to_json(options = {})
208
+ {:type => 'LineString',
209
+ :coordinates => self.to_coordinates}.to_json(options)
210
+ end
211
+ alias :as_geojson :to_json
212
+
213
+ #Creates a new line string. Accept an array of points as argument
214
+ def self.from_points(points,srid=DEFAULT_SRID,with_z=false,with_m=false)
215
+ line_string = new(srid,with_z,with_m)
216
+ line_string.concat(points)
217
+ line_string
218
+ end
219
+
220
+ #Creates a new line string. Accept a sequence of points as argument : ((x,y)...(x,y))
221
+ def self.from_coordinates(points,srid=DEFAULT_SRID,with_z=false,with_m=false)
222
+ line_string = new(srid,with_z,with_m)
223
+ line_string.concat( points.map {|p| Point.from_coordinates(p,srid,with_z,with_m) } )
224
+ line_string
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,34 @@
1
+ require 'geo_ruby/simple_features/line_string'
2
+
3
+ module GeoRuby
4
+
5
+ module SimpleFeatures
6
+
7
+ #Represents a linear ring, which is a closed line string (see LineString).
8
+ #Currently, no check is performed to verify if the linear ring is really closed.
9
+ class LinearRing < LineString
10
+
11
+ def initialize(srid= DEFAULT_SRID,with_z=false,with_m=false)
12
+ super(srid,with_z,with_m)
13
+ end
14
+
15
+
16
+ # Does this linear string contain the given point? We use the
17
+ # algorithm described here:
18
+ #
19
+ # http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
20
+ def contains_point?(point)
21
+ x, y = point.x, point.y
22
+ tuples = @points.zip(@points[1..-1] + [@points[0]])
23
+ crossings =
24
+ tuples.select do |a, b|
25
+ (b.y > y != a.y > y) && (x < (a.x - b.x) * (y - b.y) / (a.y - b.y) + b.x)
26
+ end
27
+
28
+ crossings.size % 2 == 1
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,63 @@
1
+ require 'geo_ruby/simple_features/geometry_collection'
2
+
3
+ module GeoRuby
4
+
5
+ module SimpleFeatures
6
+
7
+ #Represents a group of line strings (see LineString).
8
+ class MultiLineString < GeometryCollection
9
+
10
+ def initialize(srid = DEFAULT_SRID,with_z=false,with_m=false)
11
+ super(srid)
12
+ end
13
+
14
+ def binary_geometry_type #:nodoc:
15
+ 5
16
+ end
17
+
18
+ def points
19
+ geometries.map(&:points).flatten
20
+ end
21
+
22
+ #Text representation of a multi line string
23
+ def text_representation(allow_z=true,allow_m=true) #:nodoc:
24
+ @geometries.collect{|line_string| "(" + line_string.text_representation(allow_z,allow_m) + ")" }.join(",")
25
+ end
26
+
27
+ #WKT geometry type
28
+ def text_geometry_type #:nodoc:
29
+ "MULTILINESTRING"
30
+ end
31
+
32
+ def to_line_string(join = true)
33
+ LineString.from_points(points)
34
+ end
35
+
36
+ def to_coordinates
37
+ geometries.map{|ls| ls.to_coordinates}
38
+ end
39
+
40
+ # simple geojson representation
41
+ # TODO add CRS / SRID support?
42
+ def to_json(options = {})
43
+ {:type => 'MultiLineString',
44
+ :coordinates => self.to_coordinates}.to_json(options)
45
+ end
46
+ alias :as_geojson :to_json
47
+
48
+ #Creates a new multi line string from an array of line strings
49
+ def self.from_line_strings(line_strings,srid=DEFAULT_SRID,with_z=false,with_m=false)
50
+ multi_line_string = new(srid,with_z,with_m)
51
+ multi_line_string.concat(line_strings)
52
+ multi_line_string
53
+ end
54
+
55
+ #Creates a new multi line string from sequences of points : (((x,y)...(x,y)),((x,y)...(x,y)))
56
+ def self.from_coordinates(point_sequences,srid=DEFAULT_SRID,with_z=false,with_m=false)
57
+ multi_line_string = new(srid,with_z,with_m)
58
+ multi_line_string.concat(point_sequences.collect {|points| LineString.from_coordinates(points,srid,with_z,with_m) })
59
+ multi_line_string
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,58 @@
1
+ require 'geo_ruby/simple_features/geometry_collection'
2
+
3
+ module GeoRuby
4
+ module SimpleFeatures
5
+ #Represents a group of points (see Point).
6
+ class MultiPoint < GeometryCollection
7
+
8
+ def initialize(srid= DEFAULT_SRID,with_z=false,with_m=false)
9
+ super(srid,with_z,with_m)
10
+ end
11
+
12
+ def binary_geometry_type #:nodoc:
13
+ 4
14
+ end
15
+
16
+ def points
17
+ @geometries
18
+ end
19
+
20
+ #Text representation of a MultiPoint
21
+ def text_representation(allow_z=true,allow_m=true) #:nodoc:
22
+ "(" + @geometries.collect{|point| point.text_representation(allow_z,allow_m)}.join("),(") + ")"
23
+ end
24
+
25
+ #WKT geoemtry type
26
+ def text_geometry_type #:nodoc:
27
+ "MULTIPOINT"
28
+ end
29
+
30
+ def to_coordinates
31
+ points.map{|p| p.to_coordinates }
32
+ end
33
+
34
+ # simple geojson representation
35
+ # TODO add CRS / SRID support?
36
+ def to_json(options = {})
37
+ {:type => 'MultiPoint',
38
+ :coordinates => self.to_coordinates}.to_json(options)
39
+ end
40
+ alias :as_geojson :to_json
41
+
42
+ #Creates a new multi point from an array of points
43
+ def self.from_points(points,srid= DEFAULT_SRID,with_z=false,with_m=false)
44
+ multi_point= new(srid,with_z,with_m)
45
+ multi_point.concat(points)
46
+ multi_point
47
+ end
48
+
49
+ #Creates a new multi point from a list of point coordinates : ((x,y)...(x,y))
50
+ def self.from_coordinates(points,srid= DEFAULT_SRID,with_z=false,with_m=false)
51
+ multi_point= new(srid,with_z,with_m)
52
+ multi_point.concat(points.collect {|point| Point.from_coordinates(point,srid,with_z,with_m)})
53
+ multi_point
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,64 @@
1
+ require 'geo_ruby/simple_features/geometry_collection'
2
+
3
+ module GeoRuby
4
+
5
+ module SimpleFeatures
6
+
7
+ #Represents a group of polygons (see Polygon).
8
+ class MultiPolygon < GeometryCollection
9
+
10
+ def initialize(srid = DEFAULT_SRID,with_z=false,with_m=false)
11
+ super(srid)
12
+ end
13
+
14
+ def binary_geometry_type #:nodoc:
15
+ 6
16
+ end
17
+
18
+ def points
19
+ @points ||= geometries.inject([]) do |arr, r|
20
+ arr.concat(r.rings.map(&:points).flatten)
21
+ end
22
+ end
23
+
24
+ #Text representation of a MultiPolygon
25
+ def text_representation(allow_z=true,allow_m=true) #:nodoc:
26
+ @geometries.map {|polygon| "(" + polygon.text_representation(allow_z,allow_m) + ")"}.join(",")
27
+ end
28
+
29
+ #WKT geometry type
30
+ def text_geometry_type #:nodoc:
31
+ "MULTIPOLYGON"
32
+ end
33
+
34
+ def to_coordinates
35
+ geometries.map{|polygon| polygon.to_coordinates}
36
+ end
37
+
38
+ # simple geojson representation
39
+ # TODO add CRS / SRID support?
40
+ def to_json(options = {})
41
+ {:type => 'MultiPolygon',
42
+ :coordinates => self.to_coordinates}.to_json(options)
43
+ end
44
+ alias :as_geojson :to_json
45
+
46
+ #Creates a multi polygon from an array of polygons
47
+ def self.from_polygons(polygons,srid=DEFAULT_SRID,with_z=false,with_m=false)
48
+ multi_polygon = new(srid,with_z,with_m)
49
+ multi_polygon.concat(polygons)
50
+ multi_polygon
51
+ end
52
+
53
+ #Creates a multi polygon from sequences of points : ((((x,y)...(x,y)),((x,y)...(x,y)),((x,y)...(x,y)))
54
+ def self.from_coordinates(point_sequence_sequences,srid= DEFAULT_SRID,with_z=false,with_m=false)
55
+ multi_polygon = new(srid,with_z,with_m)
56
+ multi_polygon.concat( point_sequence_sequences.collect {|point_sequences| Polygon.from_coordinates(point_sequences,srid,with_z,with_m) } )
57
+ multi_polygon
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end