GeoRuby 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +17 -5
- data/lib/geo_ruby.rb +1 -0
- data/lib/geo_ruby/simple_features/envelope.rb +110 -0
- data/lib/geo_ruby/simple_features/geometry.rb +47 -0
- data/lib/geo_ruby/simple_features/geometry_collection.rb +56 -15
- data/lib/geo_ruby/simple_features/line_string.rb +69 -11
- data/lib/geo_ruby/simple_features/multi_line_string.rb +4 -3
- data/lib/geo_ruby/simple_features/multi_point.rb +3 -3
- data/lib/geo_ruby/simple_features/multi_polygon.rb +4 -3
- data/lib/geo_ruby/simple_features/point.rb +124 -15
- data/lib/geo_ruby/simple_features/polygon.rb +55 -3
- data/rakefile.rb +2 -2
- data/test/test_georss_kml.rb +68 -0
- data/test/test_simple_features.rb +34 -10
- metadata +6 -3
data/README
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=GeoRuby
|
2
|
-
This is GeoRuby
|
2
|
+
This is GeoRuby 1.1.0. It is intended as a holder for data returned from PostGIS and the Spatial Extensions of MySql. The data model roughly follows the OGC "Simple Features for SQL" specification (see http://www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections).
|
3
3
|
|
4
4
|
===Available data types
|
5
5
|
The following geometric data types are provided :
|
@@ -14,18 +14,30 @@ The following geometric data types are provided :
|
|
14
14
|
|
15
15
|
They can be in 2D, 3DZ, 3DM, and 4D.
|
16
16
|
|
17
|
+
On top of this an Envelope class is available, to contain the bounding box of a geometry.
|
18
|
+
|
17
19
|
===Input and output
|
18
20
|
These geometries can be input and output in WKB/EWKB/WKT/EWKT format (as well as the related HexWKB and HexEWKB formats). HexEWKB and WKB are the default form under which geometric data is returned respectively from PostGIS and MySql.
|
19
21
|
|
22
|
+
GeoRSS Simple, GeoRSS W3CGeo, GeoRSS GML can also be output. Note that they will not output valid RSS, but just the part strictly concerning the geometry as outlined in http://www.georss.org/1/ . Since the model does not allow multiple geometries, for geometry collections, only the first geometry will be output. Similarly, for polygons, the GeoRSS output will only contain the outer ring. As for W3CGeo output, only points can be output, so the first point of the geometry is chosen. By default the Simple format is output. Envelope can also be output in these formats: The box geometric type is chosen (except for W3CGeo, where the center of the envelope is chose).
|
23
|
+
|
24
|
+
On top of that, there is now support for KML output. As for GeoRSS, a valid KML file will not be output, but only the geometric data. Options <tt>:id</tt>, <tt>:extrude</tt>, <tt>:tesselate</tt> and <tt>:altitude_mode</tt> can be given. Note that if the <tt>:altitude_mode</tt> option is not passed or set to <tt>clampedToGround</tt>, the altitude data will not be output even if present. Envelopes output a LatLonAltBox instead of a geometry.
|
25
|
+
|
20
26
|
===Installation
|
21
27
|
To install the latest version, just type :
|
22
28
|
gem install GeoRuby
|
23
29
|
|
24
30
|
===Changes since the last version
|
25
|
-
-
|
26
|
-
-
|
27
|
-
- Addition of
|
28
|
-
-
|
31
|
+
- Addition of the Vincenty ellipsoidal distance calculation method
|
32
|
+
- The spherical distance now assumes the x and y are in degrees not radians
|
33
|
+
- Addition of aliases to the +x+ and +y+ accessors, as well as the <tt>from_x_y_...</tt> constructors so the +x+ can be replaced by +lon+ and +y+ by +lat+.
|
34
|
+
- Output of GeoRSS Simple, W3CGeo and GML formats
|
35
|
+
- Output of KML format
|
36
|
+
|
37
|
+
===For version 1.2.0
|
38
|
+
- Reading (and writing?) of SHP files
|
39
|
+
- Parsing of GeoRSS data
|
40
|
+
- Update of the tutorials to show the GeoRSS and KML output, as well as the reading of SHP files
|
29
41
|
|
30
42
|
===License
|
31
43
|
GeoRuby is released under the MIT license.
|
data/lib/geo_ruby.rb
CHANGED
@@ -7,6 +7,7 @@ require 'geo_ruby/simple_features/multi_point'
|
|
7
7
|
require 'geo_ruby/simple_features/multi_line_string'
|
8
8
|
require 'geo_ruby/simple_features/multi_polygon'
|
9
9
|
require 'geo_ruby/simple_features/geometry_collection'
|
10
|
+
require 'geo_ruby/simple_features/envelope'
|
10
11
|
require 'geo_ruby/simple_features/ewkb_parser'
|
11
12
|
require 'geo_ruby/simple_features/ewkt_parser'
|
12
13
|
require 'geo_ruby/simple_features/geometry_factory'
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module GeoRuby
|
2
|
+
module SimpleFeatures
|
3
|
+
|
4
|
+
class Envelope
|
5
|
+
attr_accessor :lower_corner, :upper_corner
|
6
|
+
attr_accessor :srid, :with_z
|
7
|
+
|
8
|
+
#Creates a enw Envelope with +lower_corner+ as the first element of the corners array and +upper_corner+ as the second element
|
9
|
+
def initialize(corners, srid = DEFAULT_SRID, with_z = false)
|
10
|
+
@lower_corner,@upper_corner = corners
|
11
|
+
@srid = srid
|
12
|
+
@with_z = with_z
|
13
|
+
end
|
14
|
+
|
15
|
+
#Merges the argument with the current evelope
|
16
|
+
def extend!(envelope)
|
17
|
+
lower_corner.x = [lower_corner.x,envelope.lower_corner.x].min
|
18
|
+
lower_corner.y = [lower_corner.y,envelope.lower_corner.y].min
|
19
|
+
upper_corner.x = [upper_corner.x,envelope.upper_corner.x].max
|
20
|
+
upper_corner.y = [upper_corner.y,envelope.upper_corner.y].max
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
#Merges the argument with the current evelope and sends back a new
|
25
|
+
#envelope without changing the current one
|
26
|
+
def extend(envelope)
|
27
|
+
e = Envelope.new([Point.from_x_y(lower_corner.x,lower_corner.y),
|
28
|
+
Point.from_x_y(upper_corner.x,upper_corner.y)])
|
29
|
+
e.extend!(envelope)
|
30
|
+
e
|
31
|
+
end
|
32
|
+
|
33
|
+
#Sends back the center of the envelope
|
34
|
+
def center
|
35
|
+
Point.from_x_y((lower_corner.x + upper_corner.x)/2,(lower_corner.y + upper_corner.y)/2)
|
36
|
+
end
|
37
|
+
|
38
|
+
#georss serialization: Dialect can be passed as option <tt>:dialect</tt> and set to <tt>:simple</tt> (default)
|
39
|
+
#<tt>:w3cgeo</tt> or <tt>:gml</tt>. Options <tt>:featuretypetag
|
40
|
+
def as_georss(options)
|
41
|
+
dialect= options[:dialect] || :simple
|
42
|
+
case(dialect)
|
43
|
+
when :simple
|
44
|
+
geom_attr = ""
|
45
|
+
geom_attr += " featuretypetag=\"#{options[:featuretypetag]}\"" if options[:featuretypetag]
|
46
|
+
geom_attr += " relationshiptag=\"#{options[:relationshiptag]}\"" if options[:relationshiptag]
|
47
|
+
geom_attr += " floor=\"#{options[:floor]}\"" if options[:floor]
|
48
|
+
geom_attr += " radius=\"#{options[:radius]}\"" if options[:radius]
|
49
|
+
geom_attr += " elev=\"#{options[:elev]}\"" if options[:elev]
|
50
|
+
|
51
|
+
georss_simple_representation(options.merge(:geom_attr => geom_attr))
|
52
|
+
when :w3cgeo
|
53
|
+
georss_w3cgeo_representation(options)
|
54
|
+
when :gml
|
55
|
+
georss_gml_representation(options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#georss simple representation
|
60
|
+
def georss_simple_representation(options) #:nodoc:
|
61
|
+
georss_ns = options[:georss_ns] || "georss"
|
62
|
+
geom_attr = options[:geom_attr]
|
63
|
+
"<#{georss_ns}:box#{geom_attr}>#{lower_corner.y} #{lower_corner.x} #{upper_corner.y} #{upper_corner.x}</#{georss_ns}:box>\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
#georss w3c representation : outputs the first point of the line
|
67
|
+
def georss_w3cgeo_representation(options) #:nodoc:
|
68
|
+
w3cgeo_ns = options[:w3cgeo_ns] || "geo"
|
69
|
+
point = self.center
|
70
|
+
"<#{w3cgeo_ns}:lat>#{point.y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{point.x}</#{w3cgeo_ns}:long>\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
#georss gml representation
|
74
|
+
def georss_gml_representation(options) #:nodoc:
|
75
|
+
georss_ns = options[:georss_ns] || "georss"
|
76
|
+
gml_ns = options[:gml_ns] || "gml"
|
77
|
+
result = "<#{georss_ns}:where>\n<#{gml_ns}:Envelope>\n"
|
78
|
+
result += "<#{gml_ns}:LowerCorner>" + "#{lower_corner.y} #{lower_corner.x}" + "</#{gml_ns}:LowerCorner>"
|
79
|
+
result += "<#{gml_ns}:UpperCorner>" + "#{upper_corner.y} #{upper_corner.x}" + "</#{gml_ns}:UpperCorner>"
|
80
|
+
result += "</#{gml_ns}:Envelope>\n</#{georss_ns}:where>\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
#Sends back a latlonaltbox
|
84
|
+
def as_kml(options = {})
|
85
|
+
geom_data = ""
|
86
|
+
geom_data = "<altitudeMode>#{options[:altitude_mode]}</altitudeMode>\n" if options[:altitude_mode]
|
87
|
+
|
88
|
+
allow_z = with_z && (!options[:altitude_mode].nil?) && options[:atitude_mode] != "clampToGround"
|
89
|
+
|
90
|
+
kml_representation(options.merge(:geom_data => geom_data,:allow_z => allow_z))
|
91
|
+
end
|
92
|
+
|
93
|
+
def kml_representation(options = {})#:nodoc:
|
94
|
+
result = "<LatLonAltBox>\n"
|
95
|
+
result += options[:geom_data]
|
96
|
+
result += "<north>#{upper_corner.y}</north>\n"
|
97
|
+
result += "<south>#{lower_corner.y}</south>\n"
|
98
|
+
result += "<east>#{upper_corner.x}</east>\n"
|
99
|
+
result += "<west>#{lower_corner.x}</west>\n"
|
100
|
+
|
101
|
+
if with_z
|
102
|
+
result += "<minAltitude>#{lower_corner.z}</minAltitude>"
|
103
|
+
result += "<maxAltitude>#{upper_corner.z}</maxAltitude>"
|
104
|
+
end
|
105
|
+
|
106
|
+
result += "</LatLonAltBox>\n"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -25,6 +25,16 @@ module GeoRuby#:nodoc:
|
|
25
25
|
@with_z=with_z
|
26
26
|
@with_m=with_m
|
27
27
|
end
|
28
|
+
|
29
|
+
|
30
|
+
#to be implemented in subclasses
|
31
|
+
def bounding_box
|
32
|
+
end
|
33
|
+
|
34
|
+
#Returns an Envelope object for the geometry
|
35
|
+
def envelope
|
36
|
+
Envelope.new(bounding_box,srid,with_z)
|
37
|
+
end
|
28
38
|
|
29
39
|
#Outputs the geometry as an EWKB string.
|
30
40
|
#The +allow_srid+, +allow_z+ and +allow_m+ arguments allow the output to include srid, z and m respectively if they are present in the geometry. If these arguments are set to false, srid, z and m are not included, even if they are present in the geometry. By default, the output string contains all the information in the object.
|
@@ -82,6 +92,43 @@ module GeoRuby#:nodoc:
|
|
82
92
|
def as_wkt
|
83
93
|
as_ewkt(false,false,false)
|
84
94
|
end
|
95
|
+
|
96
|
+
#Outputs the geometry in georss format.
|
97
|
+
#Assumes the geometries are in latlon format, with x as lon and y as lat.
|
98
|
+
def as_georss(options = {})
|
99
|
+
dialect= options[:dialect] || :simple
|
100
|
+
case(dialect)
|
101
|
+
when :simple
|
102
|
+
geom_attr = ""
|
103
|
+
geom_attr += " featuretypetag=\"#{options[:featuretypetag]}\"" if options[:featuretypetag]
|
104
|
+
geom_attr += " relationshiptag=\"#{options[:relationshiptag]}\"" if options[:relationshiptag]
|
105
|
+
geom_attr += " floor=\"#{options[:floor]}\"" if options[:floor]
|
106
|
+
geom_attr += " radius=\"#{options[:radius]}\"" if options[:radius]
|
107
|
+
geom_attr += " elev=\"#{options[:elev]}\"" if options[:elev]
|
108
|
+
georss_simple_representation(options.merge(:geom_attr => geom_attr))
|
109
|
+
when :w3cgeo
|
110
|
+
georss_w3cgeo_representation(options)
|
111
|
+
when :gml
|
112
|
+
georss_gml_representation(options)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
#Iutputs the geometry in kml format : options are <tt>:id</tt>, <tt>:tesselate</tt>, <tt>:extrude</tt>,
|
117
|
+
#<tt>:altitude_mode</tt>. If the altitude_mode option is not present, the Z (if present) will not be output (since
|
118
|
+
#it won't be used by GE anyway: clampToGround is the default)
|
119
|
+
def as_kml(options = {})
|
120
|
+
id_attr = ""
|
121
|
+
id_attr = " id=\"#{options[:id]}\"" if options[:id]
|
122
|
+
|
123
|
+
geom_data = ""
|
124
|
+
geom_data += "<extrude>#{options[:extrude]}</extrude>\n" if options[:extrude]
|
125
|
+
geom_data += "<tesselate>#{options[:tesselate]}</tesselate>\n" if options[:tesselate]
|
126
|
+
geom_data += "<altitudeMode>#{options[:altitude_mode]}</altitudeMode>\n" if options[:altitude_mode]
|
127
|
+
|
128
|
+
allow_z = with_z && (!options[:altitude_mode].nil?) && options[:atitude_mode] != "clampToGround"
|
129
|
+
|
130
|
+
kml_representation(options.merge(:id_attr => id_attr, :geom_data => geom_data, :allow_z => allow_z))
|
131
|
+
end
|
85
132
|
|
86
133
|
#Creates a geometry based on a EWKB string. The actual class returned depends of the content of the string passed as argument. Since WKB strings are a subset of EWKB, they are also valid.
|
87
134
|
def self.from_ewkb(ewkb)
|
@@ -16,19 +16,37 @@ module GeoRuby
|
|
16
16
|
@geometries.send(method_name,*args,&b)
|
17
17
|
end
|
18
18
|
|
19
|
-
#Bounding box in 2D. Returns an array of 2 points
|
19
|
+
#Bounding box in 2D/3D. Returns an array of 2 points
|
20
20
|
def bounding_box
|
21
|
-
max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
|
22
|
+
if with_z
|
23
|
+
max_z, min_z = -Float::MAX, Float::MAX
|
24
|
+
each do |geometry|
|
25
|
+
bbox = geometry.bounding_box
|
26
|
+
sw = bbox[0]
|
27
|
+
ne = bbox[1]
|
28
|
+
|
29
|
+
max_y = ne.y if ne.y > max_y
|
30
|
+
min_y = sw.y if sw.y < min_y
|
31
|
+
max_x = ne.x if ne.x > max_x
|
32
|
+
min_x = sw.x if sw.x < min_x
|
33
|
+
max_z = ne.z if ne.z > max_z
|
34
|
+
min_z = sw.z if sw.z < min_z
|
35
|
+
end
|
36
|
+
[Point.from_x_y_z(min_x,min_y,min_z),Point.from_x_y_z(max_x,max_y,max_z)]
|
37
|
+
else
|
38
|
+
each do |geometry|
|
39
|
+
bbox = geometry.bounding_box
|
40
|
+
sw = bbox[0]
|
41
|
+
ne = bbox[1]
|
42
|
+
|
43
|
+
max_y = ne.y if ne.y > max_y
|
44
|
+
min_y = sw.y if sw.y < min_y
|
45
|
+
max_x = ne.x if ne.x > max_x
|
46
|
+
min_x = sw.x if sw.x < min_x
|
47
|
+
end
|
48
|
+
[Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
|
30
49
|
end
|
31
|
-
[Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
|
32
50
|
end
|
33
51
|
|
34
52
|
#tests the equality of geometry collections
|
@@ -48,7 +66,7 @@ module GeoRuby
|
|
48
66
|
end
|
49
67
|
|
50
68
|
#Binary representation of the collection
|
51
|
-
def binary_representation(allow_z=true,allow_m=true)
|
69
|
+
def binary_representation(allow_z=true,allow_m=true) #:nodoc:
|
52
70
|
rep = [length].pack("V")
|
53
71
|
#output the list of geometries without outputting the SRID first and with the same setting regarding Z and M
|
54
72
|
each {|geometry| rep << geometry.as_ewkb(false,allow_z,allow_m) }
|
@@ -56,19 +74,42 @@ module GeoRuby
|
|
56
74
|
end
|
57
75
|
|
58
76
|
#WKB geometry type of the collection
|
59
|
-
def binary_geometry_type
|
77
|
+
def binary_geometry_type #:nodoc:
|
60
78
|
7
|
61
79
|
end
|
62
80
|
|
63
81
|
#Text representation of a geometry collection
|
64
|
-
def text_representation(allow_z=true,allow_m=true)
|
82
|
+
def text_representation(allow_z=true,allow_m=true) #:nodoc:
|
65
83
|
@geometries.collect{|geometry| geometry.as_ewkt(false,allow_z,allow_m)}.join(",")
|
66
84
|
end
|
67
85
|
|
68
86
|
#WKT geometry type
|
69
|
-
def text_geometry_type
|
87
|
+
def text_geometry_type #:nodoc:
|
70
88
|
"GEOMETRYCOLLECTION"
|
71
89
|
end
|
90
|
+
|
91
|
+
#georss simple representation : outputs only the first geometry of the collection
|
92
|
+
def georss_simple_representation(options)#:nodoc:
|
93
|
+
self[0].georss_simple_representation(options)
|
94
|
+
end
|
95
|
+
#georss w3c representation : outputs the first point of the outer ring
|
96
|
+
def georss_w3cgeo_representation(options)#:nodoc:
|
97
|
+
self[0].georss_w3cgeo_representation(options)
|
98
|
+
end
|
99
|
+
#georss gml representation : outputs only the first geometry of the collection
|
100
|
+
def georss_gml_representation(options)#:nodoc:
|
101
|
+
self[0].georss_gml_representation(options)
|
102
|
+
end
|
103
|
+
|
104
|
+
#outputs the geometry in kml format
|
105
|
+
def kml_representation(options = {}) #:nodoc:
|
106
|
+
result = "<MultiGeometry#{options[:id_attr]}>\n"
|
107
|
+
options[:id_attr] = "" #the subgeometries do not have an ID
|
108
|
+
each do |geometry|
|
109
|
+
result += geometry.kml_representation(options)
|
110
|
+
end
|
111
|
+
result += "</MultiGeometry>\n"
|
112
|
+
end
|
72
113
|
|
73
114
|
#creates a new GeometryCollection from an array of geometries
|
74
115
|
def self.from_geometries(geometries,srid=DEFAULT_SRID,with_z=false,with_m=false)
|
@@ -23,16 +23,29 @@ module GeoRuby
|
|
23
23
|
@points.first == @points.last
|
24
24
|
end
|
25
25
|
|
26
|
-
#Bounding box in 2D. Returns an array of 2 points
|
26
|
+
#Bounding box in 2D/3D. Returns an array of 2 points
|
27
27
|
def bounding_box
|
28
28
|
max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
if(with_z)
|
30
|
+
max_z, min_z = -Float::MAX,Float::MAX
|
31
|
+
each do |point|
|
32
|
+
max_y = point.y if point.y > max_y
|
33
|
+
min_y = point.y if point.y < min_y
|
34
|
+
max_x = point.x if point.x > max_x
|
35
|
+
min_x = point.x if point.x < min_x
|
36
|
+
max_z = point.z if point.z > max_z
|
37
|
+
min_z = point.z if point.z < min_z
|
38
|
+
end
|
39
|
+
[Point.from_x_y_z(min_x,min_y,min_z),Point.from_x_y_z(max_x,max_y,max_z)]
|
40
|
+
else
|
41
|
+
each do |point|
|
42
|
+
max_y = point.y if point.y > max_y
|
43
|
+
min_y = point.y if point.y < min_y
|
44
|
+
max_x = point.x if point.x > max_x
|
45
|
+
min_x = point.x if point.x < min_x
|
46
|
+
end
|
47
|
+
[Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
|
34
48
|
end
|
35
|
-
[Point.from_x_y(min_x,min_y),Point.from_x_y(max_x,max_y)]
|
36
49
|
end
|
37
50
|
|
38
51
|
#Tests the equality of line strings
|
@@ -51,25 +64,70 @@ module GeoRuby
|
|
51
64
|
end
|
52
65
|
|
53
66
|
#Binary representation of a line string
|
54
|
-
def binary_representation(allow_z=true,allow_m=true)
|
67
|
+
def binary_representation(allow_z=true,allow_m=true) #:nodoc:
|
55
68
|
rep = [length].pack("V")
|
56
69
|
each {|point| rep << point.binary_representation(allow_z,allow_m) }
|
57
70
|
rep
|
58
71
|
end
|
59
72
|
|
60
73
|
#WKB geometry type
|
61
|
-
def binary_geometry_type
|
74
|
+
def binary_geometry_type #:nodoc:
|
62
75
|
2
|
63
76
|
end
|
64
77
|
|
65
78
|
#Text representation of a line string
|
66
|
-
def text_representation(allow_z=true,allow_m=true)
|
79
|
+
def text_representation(allow_z=true,allow_m=true) #:nodoc:
|
67
80
|
@points.collect{|point| point.text_representation(allow_z,allow_m) }.join(",")
|
68
81
|
end
|
69
82
|
#WKT geometry type
|
70
|
-
def text_geometry_type
|
83
|
+
def text_geometry_type #:nodoc:
|
71
84
|
"LINESTRING"
|
72
85
|
end
|
86
|
+
|
87
|
+
#georss simple representation
|
88
|
+
def georss_simple_representation(options) #:nodoc:
|
89
|
+
georss_ns = options[:georss_ns] || "georss"
|
90
|
+
geom_attr = options[:geom_attr]
|
91
|
+
"<#{georss_ns}:line#{geom_attr}>" + georss_poslist + "</#{georss_ns}:line>\n"
|
92
|
+
end
|
93
|
+
#georss w3c representation : outputs the first point of the line
|
94
|
+
def georss_w3cgeo_representation(options) #:nodoc:
|
95
|
+
w3cgeo_ns = options[:w3cgeo_ns] || "geo"
|
96
|
+
"<#{w3cgeo_ns}:lat>#{self[0].y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{self[0].x}</#{w3cgeo_ns}:long>\n"
|
97
|
+
end
|
98
|
+
#georss gml representation
|
99
|
+
def georss_gml_representation(options) #:nodoc:
|
100
|
+
georss_ns = options[:georss_ns] || "georss"
|
101
|
+
gml_ns = options[:gml_ns] || "gml"
|
102
|
+
|
103
|
+
result = "<#{georss_ns}:where>\n<#{gml_ns}:LineString>\n<#{gml_ns}:posList>\n"
|
104
|
+
result += georss_poslist
|
105
|
+
result += "\n</#{gml_ns}:posList>\n</#{gml_ns}:LineString>\n</#{georss_ns}:where>\n"
|
106
|
+
end
|
107
|
+
|
108
|
+
def georss_poslist #:nodoc:
|
109
|
+
map {|point| "#{point.y} #{point.x}"}.join(" ")
|
110
|
+
end
|
111
|
+
|
112
|
+
#outputs the geometry in kml format : options are <tt>:id</tt>, <tt>:tesselate</tt>, <tt>:extrude</tt>,
|
113
|
+
#<tt>:altitude_mode</tt>. If the altitude_mode option is not present, the Z (if present) will not be output (since
|
114
|
+
#it won't be used by GE anyway: clampToGround is the default)
|
115
|
+
def kml_representation(options = {}) #:nodoc:
|
116
|
+
result = "<LineString#{options[:id_attr]}>\n"
|
117
|
+
result += options[:geom_data]
|
118
|
+
result += "<coordinates>"
|
119
|
+
result += kml_poslist(options[:allow_z])
|
120
|
+
result += "</coordinates>\n"
|
121
|
+
result += "</LineString>\n"
|
122
|
+
end
|
123
|
+
|
124
|
+
def kml_poslist(allow_z) #:nodoc:
|
125
|
+
if allow_z
|
126
|
+
map {|point| "#{point.x},#{point.y},#{point.z || 0}" }.join(" ")
|
127
|
+
else
|
128
|
+
map {|point| "#{point.x},#{point.y}" }.join(" ")
|
129
|
+
end
|
130
|
+
end
|
73
131
|
|
74
132
|
#Creates a new line string. Accept an array of points as argument
|
75
133
|
def self.from_points(points,srid=DEFAULT_SRID,with_z=false,with_m=false)
|
@@ -7,16 +7,17 @@ module GeoRuby
|
|
7
7
|
def initialize(srid = DEFAULT_SRID,with_z=false,with_m=false)
|
8
8
|
super(srid)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
|
+
def binary_geometry_type #:nodoc:
|
11
12
|
5
|
12
13
|
end
|
13
14
|
|
14
15
|
#Text representation of a multi line string
|
15
|
-
def text_representation(allow_z=true,allow_m=true)
|
16
|
+
def text_representation(allow_z=true,allow_m=true) #:nodoc:
|
16
17
|
@geometries.collect{|line_string| "(" + line_string.text_representation(allow_z,allow_m) + ")" }.join(",")
|
17
18
|
end
|
18
19
|
#WKT geometry type
|
19
|
-
def text_geometry_type
|
20
|
+
def text_geometry_type #:nodoc:
|
20
21
|
"MULTILINESTRING"
|
21
22
|
end
|
22
23
|
|
@@ -9,16 +9,16 @@ module GeoRuby
|
|
9
9
|
super(srid,with_z,with_m)
|
10
10
|
end
|
11
11
|
|
12
|
-
def binary_geometry_type
|
12
|
+
def binary_geometry_type #:nodoc:
|
13
13
|
4
|
14
14
|
end
|
15
15
|
|
16
16
|
#Text representation of a MultiPoint
|
17
|
-
def text_representation(allow_z=true,allow_m=true)
|
17
|
+
def text_representation(allow_z=true,allow_m=true) #:nodoc:
|
18
18
|
"(" + @geometries.collect{|point| point.text_representation(allow_z,allow_m)}.join("),(") + ")"
|
19
19
|
end
|
20
20
|
#WKT geoemtry type
|
21
|
-
def text_geometry_type
|
21
|
+
def text_geometry_type #:nodoc:
|
22
22
|
"MULTIPOINT"
|
23
23
|
end
|
24
24
|
|
@@ -8,15 +8,16 @@ module GeoRuby
|
|
8
8
|
def initialize(srid = DEFAULT_SRID,with_z=false,with_m=false)
|
9
9
|
super(srid)
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
|
+
def binary_geometry_type #:nodoc:
|
12
13
|
6
|
13
14
|
end
|
14
15
|
#Text representation of a MultiPolygon
|
15
|
-
def text_representation(allow_z=true,allow_m=true)
|
16
|
+
def text_representation(allow_z=true,allow_m=true) #:nodoc:
|
16
17
|
@geometries.collect{|polygon| "(" + polygon.text_representation(allow_z,allow_m) + ")"}.join(",")
|
17
18
|
end
|
18
19
|
#WKT geometry type
|
19
|
-
def text_geometry_type
|
20
|
+
def text_geometry_type #:nodoc:
|
20
21
|
"MULTIPOLYGON"
|
21
22
|
end
|
22
23
|
|
@@ -5,7 +5,11 @@ module GeoRuby
|
|
5
5
|
#Represents a point. It is in 3D if the Z coordinate is not +nil+.
|
6
6
|
class Point < Geometry
|
7
7
|
|
8
|
+
|
8
9
|
attr_accessor :x,:y,:z,:m
|
10
|
+
#if you prefer calling the coordinates lat and lon
|
11
|
+
alias :lon :x
|
12
|
+
alias :lat :y
|
9
13
|
|
10
14
|
def initialize(srid=DEFAULT_SRID,with_z=false,with_m=false)
|
11
15
|
super(srid,with_z,with_m)
|
@@ -20,34 +24,93 @@ module GeoRuby
|
|
20
24
|
@y=y
|
21
25
|
@z=z
|
22
26
|
end
|
27
|
+
alias :set_lon_lat_z :set_x_y_z
|
28
|
+
|
23
29
|
#sets all coordinates of a 2D point in one call
|
24
30
|
def set_x_y(x,y)
|
25
31
|
@x=x
|
26
32
|
@y=y
|
27
33
|
end
|
34
|
+
alias :set_lon_lat :set_x_y
|
28
35
|
|
29
36
|
#Return the distance between the 2D points (ie taking care only of the x and y coordinates), assuming the points are in projected coordinates. Euclidian distance in whatever unit the x and y ordinates are.
|
30
37
|
def euclidian_distance(point)
|
31
38
|
Math.sqrt((point.x - x)**2 + (point.y - y)**2)
|
32
39
|
end
|
33
40
|
|
34
|
-
#Returns the sperical distance, with a radius of 6471000m, with the haversine law. Assumes x is the lon and y the lat, in
|
35
|
-
def spherical_distance(point,radius=
|
36
|
-
|
37
|
-
|
38
|
-
|
41
|
+
#Returns the sperical distance in m, with a radius of 6471000m, with the haversine law. Assumes x is the lon and y the lat, in degrees (Changed in version 1.1). The user has to make sure using this distance makes sense (ie she should be in latlon coordinates)
|
42
|
+
def spherical_distance(point,radius=6370997.0)
|
43
|
+
deg_to_rad = 0.0174532925199433
|
44
|
+
|
45
|
+
radlat_from = lat * deg_to_rad
|
46
|
+
radlat_to = point.lat * deg_to_rad
|
47
|
+
|
48
|
+
dlat = (point.lat - lat) * deg_to_rad
|
49
|
+
dlon = (point.lon - lon) * deg_to_rad
|
50
|
+
|
51
|
+
a = Math.sin(dlat/2)**2 + Math.cos(radlat_from) * Math.cos(radlat_to) * Math.sin(dlon/2)**2
|
39
52
|
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
|
40
53
|
radius * c
|
41
54
|
end
|
42
55
|
|
43
|
-
#Ellipsoidal distance
|
44
|
-
|
45
|
-
|
46
|
-
|
56
|
+
#Ellipsoidal distance in m using Vincenty's formula. Lifted entirely from Chris Veness's code at http://www.movable-type.co.uk/scripts/LatLongVincenty.html and adapted for Ruby. Assumes the x and y are the lon and lat in degrees.
|
57
|
+
#a is the semi-major axis (equatorial radius) of the ellipsoid
|
58
|
+
#b is the semi-minor axis (polar radius) of the ellipsoid
|
59
|
+
#Their values by default are set to the ones of the WGS84 ellipsoid
|
60
|
+
def ellipsoidal_distance(point, a = 6378137.0, b = 6356752.3142)
|
61
|
+
deg_to_rad = 0.0174532925199433
|
62
|
+
|
63
|
+
f = (a-b) / a
|
64
|
+
l = (point.lon - lon) * deg_to_rad
|
65
|
+
|
66
|
+
u1 = Math.atan((1-f) * Math.tan(lat * deg_to_rad ))
|
67
|
+
u2 = Math.atan((1-f) * Math.tan(point.lat * deg_to_rad))
|
68
|
+
sinU1 = Math.sin(u1)
|
69
|
+
cosU1 = Math.cos(u1)
|
70
|
+
sinU2 = Math.sin(u2)
|
71
|
+
cosU2 = Math.cos(u2)
|
72
|
+
|
73
|
+
lambda = l
|
74
|
+
lambdaP = 2 * Math::PI
|
75
|
+
iterLimit = 20
|
76
|
+
|
77
|
+
while (lambda-lambdaP).abs > 1e-12 && --iterLimit>0
|
78
|
+
sinLambda = Math.sin(lambda)
|
79
|
+
cosLambda = Math.cos(lambda)
|
80
|
+
sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda))
|
81
|
+
|
82
|
+
return 0 if sinSigma == 0 #coincident points
|
83
|
+
|
84
|
+
cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda
|
85
|
+
sigma = Math.atan2(sinSigma, cosSigma)
|
86
|
+
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma
|
87
|
+
cosSqAlpha = 1 - sinAlpha*sinAlpha
|
88
|
+
cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha
|
89
|
+
|
90
|
+
cos2SigmaM = 0 if (cos2SigmaM.nan?) #equatorial line: cosSqAlpha=0
|
91
|
+
|
92
|
+
c = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha))
|
93
|
+
lambdaP = lambda
|
94
|
+
lambda = l + (1-c) * f * sinAlpha * (sigma + c * sinSigma * (cos2SigmaM + c * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))
|
95
|
+
end
|
96
|
+
return NaN if iterLimit==0 #formula failed to converge
|
97
|
+
|
98
|
+
uSq = cosSqAlpha * (a*a - b*b) / (b*b)
|
99
|
+
a_bis = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)))
|
100
|
+
b_bis = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)))
|
101
|
+
deltaSigma = b_bis * sinSigma*(cos2SigmaM + b_bis/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- b_bis/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)))
|
47
102
|
|
48
|
-
|
103
|
+
b*a_bis*(sigma-deltaSigma)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
#Bounding box in 2D/3D. Returns an array of 2 points
|
49
108
|
def bounding_box
|
50
|
-
|
109
|
+
unless with_z
|
110
|
+
[Point.from_x_y(@x,@y),Point.from_x_y(@x,@y)]
|
111
|
+
else
|
112
|
+
[Point.from_x_y_z(@x,@y,@z),Point.from_x_y_z(@x,@y,@z)]
|
113
|
+
end
|
51
114
|
end
|
52
115
|
|
53
116
|
#tests the equality of the position of points + m
|
@@ -58,29 +121,62 @@ module GeoRuby
|
|
58
121
|
@x == other_point.x and @y == other_point.y and @z == other_point.z and @m == other_point.m
|
59
122
|
end
|
60
123
|
end
|
124
|
+
|
61
125
|
#binary representation of a point. It lacks some headers to be a valid EWKB representation.
|
62
|
-
def binary_representation(allow_z=true,allow_m=true)
|
126
|
+
def binary_representation(allow_z=true,allow_m=true) #:nodoc:
|
63
127
|
bin_rep = [@x,@y].pack("EE")
|
64
128
|
bin_rep += [@z].pack("E") if @with_z and allow_z #Default value so no crash
|
65
129
|
bin_rep += [@m].pack("E") if @with_m and allow_m #idem
|
66
130
|
bin_rep
|
67
131
|
end
|
68
132
|
#WKB geometry type of a point
|
69
|
-
def binary_geometry_type
|
133
|
+
def binary_geometry_type#:nodoc:
|
70
134
|
1
|
71
135
|
end
|
72
136
|
|
73
137
|
#text representation of a point
|
74
|
-
def text_representation(allow_z=true,allow_m=true)
|
138
|
+
def text_representation(allow_z=true,allow_m=true) #:nodoc:
|
75
139
|
tex_rep = "#{@x} #{@y}"
|
76
140
|
tex_rep += " #{@z}" if @with_z and allow_z
|
77
141
|
tex_rep += " #{@m}" if @with_m and allow_m
|
78
142
|
tex_rep
|
79
143
|
end
|
80
144
|
#WKT geometry type of a point
|
81
|
-
def text_geometry_type
|
145
|
+
def text_geometry_type #:nodoc:
|
82
146
|
"POINT"
|
83
147
|
end
|
148
|
+
|
149
|
+
#georss simple representation
|
150
|
+
def georss_simple_representation(options) #:nodoc:
|
151
|
+
georss_ns = options[:georss_ns] || "georss"
|
152
|
+
geom_attr = options[:geom_attr]
|
153
|
+
"<#{georss_ns}:point#{geom_attr}>#{y} #{x}</#{georss_ns}:point>\n"
|
154
|
+
end
|
155
|
+
#georss w3c representation
|
156
|
+
def georss_w3cgeo_representation(options) #:nodoc:
|
157
|
+
w3cgeo_ns = options[:w3cgeo_ns] || "geo"
|
158
|
+
"<#{w3cgeo_ns}:lat>#{y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{x}</#{w3cgeo_ns}:long>\n"
|
159
|
+
end
|
160
|
+
#georss gml representation
|
161
|
+
def georss_gml_representation(options) #:nodoc:
|
162
|
+
georss_ns = options[:georss_ns] || "georss"
|
163
|
+
gml_ns = options[:gml_ns] || "gml"
|
164
|
+
result = "<#{georss_ns}:where>\n<#{gml_ns}:Point>\n<#{gml_ns}:pos>"
|
165
|
+
result += "#{y} #{x}"
|
166
|
+
result += "</#{gml_ns}:pos>\n</#{gml_ns}:Point>\n</#{georss_ns}:where>\n"
|
167
|
+
end
|
168
|
+
|
169
|
+
#outputs the geometry in kml format : options are <tt>:id</tt>, <tt>:tesselate</tt>, <tt>:extrude</tt>,
|
170
|
+
#<tt>:altitude_mode</tt>. If the altitude_mode option is not present, the Z (if present) will not be output (since
|
171
|
+
#it won't be used by GE anyway: clampToGround is the default)
|
172
|
+
def kml_representation(options = {}) #:nodoc:
|
173
|
+
result = "<Point#{options[:id_attr]}>\n"
|
174
|
+
result += options[:geom_data]
|
175
|
+
result += "<coordinates>#{x},#{y}"
|
176
|
+
result += ",#{z || 0}" if options[:allow_z]
|
177
|
+
result += "</coordinates>\n"
|
178
|
+
result += "</Point>\n"
|
179
|
+
end
|
84
180
|
|
85
181
|
#creates a point from an array of coordinates
|
86
182
|
def self.from_coordinates(coords,srid=DEFAULT_SRID,with_z=false,with_m=false)
|
@@ -94,18 +190,22 @@ module GeoRuby
|
|
94
190
|
from_x_y_m(coords[0],coords[1],coords[2],srid)
|
95
191
|
end
|
96
192
|
end
|
193
|
+
|
97
194
|
#creates a point from the X and Y coordinates
|
98
195
|
def self.from_x_y(x,y,srid=DEFAULT_SRID)
|
99
196
|
point= Point::new(srid)
|
100
197
|
point.set_x_y(x,y)
|
101
198
|
point
|
102
199
|
end
|
200
|
+
|
103
201
|
#creates a point from the X, Y and Z coordinates
|
104
202
|
def self.from_x_y_z(x,y,z,srid=DEFAULT_SRID)
|
105
203
|
point= Point::new(srid,true)
|
106
204
|
point.set_x_y_z(x,y,z)
|
107
205
|
point
|
108
206
|
end
|
207
|
+
|
208
|
+
|
109
209
|
#creates a point from the X, Y and M coordinates
|
110
210
|
def self.from_x_y_m(x,y,m,srid=DEFAULT_SRID)
|
111
211
|
point= Point::new(srid,false,true)
|
@@ -113,6 +213,7 @@ module GeoRuby
|
|
113
213
|
point.m=m
|
114
214
|
point
|
115
215
|
end
|
216
|
+
|
116
217
|
#creates a point from the X, Y, Z and M coordinates
|
117
218
|
def self.from_x_y_z_m(x,y,z,m,srid=DEFAULT_SRID)
|
118
219
|
point= Point::new(srid,true,true)
|
@@ -120,6 +221,14 @@ module GeoRuby
|
|
120
221
|
point.m=m
|
121
222
|
point
|
122
223
|
end
|
224
|
+
|
225
|
+
#aliasing the constructors in case you want to use lat/lon instead of y/x
|
226
|
+
class << self
|
227
|
+
alias :from_lon_lat :from_x_y
|
228
|
+
alias :from_lon_lat_z :from_x_y_z
|
229
|
+
alias :from_lon_lat_m :from_x_y_m
|
230
|
+
alias :from_lon_lat_z_m :from_x_y_z_m
|
231
|
+
end
|
123
232
|
end
|
124
233
|
end
|
125
234
|
end
|
@@ -17,9 +17,23 @@ module GeoRuby
|
|
17
17
|
@rings.send(method_name,*args,&b)
|
18
18
|
end
|
19
19
|
|
20
|
-
#Bounding box in 2D. Returns an array of 2 points
|
20
|
+
#Bounding box in 2D/3D. Returns an array of 2 points
|
21
21
|
def bounding_box
|
22
|
-
|
22
|
+
unless with_z
|
23
|
+
@rings[0].bounding_box
|
24
|
+
else
|
25
|
+
result = @rings[0].bounding_box #valid for x and y
|
26
|
+
max_z, min_z = result[1].z, result[0].z
|
27
|
+
1.upto(size - 1) do |index|
|
28
|
+
bbox = @rings[index].bounding_box
|
29
|
+
sw = bbox[0]
|
30
|
+
ne = bbox[1]
|
31
|
+
max_z = ne.z if ne.z > max_z
|
32
|
+
min_z = sw.z if sw.z < min_z
|
33
|
+
end
|
34
|
+
result[1].z, result[0].z = max_z, min_z
|
35
|
+
result
|
36
|
+
end
|
23
37
|
end
|
24
38
|
|
25
39
|
#tests for other equality. The SRID is not taken into account.
|
@@ -56,6 +70,45 @@ module GeoRuby
|
|
56
70
|
"POLYGON"
|
57
71
|
end
|
58
72
|
|
73
|
+
#georss simple representation : outputs only the outer ring
|
74
|
+
def georss_simple_representation(options)
|
75
|
+
georss_ns = options[:georss_ns] || "georss"
|
76
|
+
geom_attr = options[:geom_attr]
|
77
|
+
"<#{georss_ns}:polygon#{geom_attr}>" + self[0].georss_poslist + "</#{georss_ns}:polygon>\n"
|
78
|
+
end
|
79
|
+
#georss w3c representation : outputs the first point of the outer ring
|
80
|
+
def georss_w3cgeo_representation(options)
|
81
|
+
w3cgeo_ns = options[:w3cgeo_ns] || "geo"
|
82
|
+
|
83
|
+
"<#{w3cgeo_ns}:lat>#{self[0][0].y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{self[0][0].x}</#{w3cgeo_ns}:long>\n"
|
84
|
+
end
|
85
|
+
#georss gml representation
|
86
|
+
def georss_gml_representation(options)
|
87
|
+
georss_ns = options[:georss_ns] || "georss"
|
88
|
+
gml_ns = options[:gml_ns] || "gml"
|
89
|
+
|
90
|
+
result = "<#{georss_ns}:where>\n<#{gml_ns}:Polygon>\n<#{gml_ns}:exterior>\n<#{gml_ns}:LinearRing>\n<#{gml_ns}:posList>\n" + self[0].georss_poslist + "\n</#{gml_ns}:posList>\n</#{gml_ns}:LinearRing>\n</#{gml_ns}:exterior>\n</#{gml_ns}:Polygon>\n</#{georss_ns}:where>\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
#outputs the geometry in kml format : options are <tt>:id</tt>, <tt>:tesselate</tt>, <tt>:extrude</tt>,
|
94
|
+
#<tt>:altitude_mode</tt>. If the altitude_mode option is not present, the Z (if present) will not be output (since
|
95
|
+
#it won't be used by GE anyway: clampToGround is the default)
|
96
|
+
def kml_representation(options = {})
|
97
|
+
result = "<Polygon#{options[:id_attr]}>\n"
|
98
|
+
result += options[:geom_data]
|
99
|
+
rings.each_with_index do |ring, i|
|
100
|
+
if i == 0
|
101
|
+
boundary = "outerBoundaryIs"
|
102
|
+
else
|
103
|
+
boundary = "innerBoundaryIs"
|
104
|
+
end
|
105
|
+
result += "<#{boundary}><LinearRing><coordinates>\n"
|
106
|
+
result += ring.kml_poslist(options[:allow_z])
|
107
|
+
result += "\n</coordinates></LinearRing></#{boundary}>\n"
|
108
|
+
end
|
109
|
+
result += "</Polygon>\n"
|
110
|
+
end
|
111
|
+
|
59
112
|
#creates a new polygon. Accepts an array of linear strings as argument
|
60
113
|
def self.from_linear_rings(linear_rings,srid = DEFAULT_SRID,with_z=false,with_m=false)
|
61
114
|
polygon = Polygon::new(srid,with_z,with_m)
|
@@ -70,7 +123,6 @@ module GeoRuby
|
|
70
123
|
polygon
|
71
124
|
end
|
72
125
|
|
73
|
-
|
74
126
|
end
|
75
127
|
end
|
76
128
|
end
|
data/rakefile.rb
CHANGED
@@ -24,14 +24,14 @@ spec = Gem::Specification::new do |s|
|
|
24
24
|
s.platform = Gem::Platform::RUBY
|
25
25
|
|
26
26
|
s.name = 'GeoRuby'
|
27
|
-
s.version = "1.
|
27
|
+
s.version = "1.1.0"
|
28
28
|
s.summary = "Ruby data holder for OGC Simple Features"
|
29
29
|
s.description = <<EOF
|
30
30
|
GeoRuby is intended as a holder for data returned from PostGIS and MySQL Spatial queries. The data model roughly follows the OGC "Simple Features for SQL" specification (see www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections)
|
31
31
|
EOF
|
32
32
|
s.author = 'Guilhem Vellut'
|
33
33
|
s.email = 'guilhem.vellut+georuby@gmail.com'
|
34
|
-
s.homepage = "http://thepochisuperstarmegashow.com"
|
34
|
+
s.homepage = "http://thepochisuperstarmegashow.com/projects"
|
35
35
|
|
36
36
|
s.requirements << 'none'
|
37
37
|
s.require_path = 'lib'
|
@@ -0,0 +1,68 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'geo_ruby'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
include GeoRuby::SimpleFeatures
|
7
|
+
|
8
|
+
class TestGeorssKml < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_geometry_creation
|
11
|
+
point = Point.from_x_y(3,4)
|
12
|
+
|
13
|
+
assert_equal("<georss:point featuretypetag=\"hoyoyo\" elev=\"45.7\">4 3</georss:point>", point.as_georss(:dialect => :simple, :elev => 45.7, :featuretypetag => "hoyoyo").gsub("\n",""))
|
14
|
+
assert_equal("<geo:lat>4</geo:lat><geo:long>3</geo:long>",point.as_georss(:dialect => :w3cgeo).gsub("\n",""))
|
15
|
+
assert_equal("<georss:where><gml:Point><gml:pos>4 3</gml:pos></gml:Point></georss:where>",point.as_georss(:dialect => :gml).gsub("\n",""))
|
16
|
+
|
17
|
+
assert_equal("<Point id=\"HOYOYO-42\"><coordinates>3,4</coordinates></Point>",point.as_kml(:id => "HOYOYO-42").gsub("\n",""))
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_line_string
|
21
|
+
ls = LineString.from_points([Point.from_lon_lat_z(12.4,-45.3,56),Point.from_lon_lat_z(45.4,41.6,45)],123,true)
|
22
|
+
|
23
|
+
assert_equal("<georss:line>-45.3 12.4 41.6 45.4</georss:line>",ls.as_georss.gsub("\n",""))
|
24
|
+
assert_equal("<geo:lat>-45.3</geo:lat><geo:long>12.4</geo:long>",ls.as_georss(:dialect => :w3cgeo).gsub("\n",""))
|
25
|
+
assert_equal("<georss:where><gml:LineString><gml:posList>-45.3 12.4 41.6 45.4</gml:posList></gml:LineString></georss:where>",ls.as_georss(:dialect => :gml).gsub("\n",""))
|
26
|
+
|
27
|
+
assert_equal("<LineString><extrude>1</extrude><altitudeMode>absolute</altitudeMode><coordinates>12.4,-45.3,56 45.4,41.6,45</coordinates></LineString>",ls.as_kml(:extrude => 1, :altitude_mode => "absolute").gsub("\n",""))
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_polygon
|
31
|
+
linear_ring1 = LinearRing.from_coordinates([[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],256)
|
32
|
+
linear_ring2 = LinearRing.from_coordinates([[2.4,5.3],[5.4,1.4263],[14.46,1.06],[2.4,5.3]],256)
|
33
|
+
polygon = Polygon.from_linear_rings([linear_ring1,linear_ring2],256)
|
34
|
+
|
35
|
+
assert_equal("<hoyoyo:polygon>-45.3 12.4 41.6 45.4 1.0698 4.456 -45.3 12.4</hoyoyo:polygon>",polygon.as_georss(:georss_ns => "hoyoyo").gsub("\n",""))
|
36
|
+
assert_equal("<bouyoul:lat>-45.3</bouyoul:lat><bouyoul:long>12.4</bouyoul:long>",polygon.as_georss(:dialect => :w3cgeo, :w3cgeo_ns => "bouyoul").gsub("\n",""))
|
37
|
+
assert_equal("<georss:where><gml:Polygon><gml:exterior><gml:LinearRing><gml:posList>-45.3 12.4 41.6 45.4 1.0698 4.456 -45.3 12.4</gml:posList></gml:LinearRing></gml:exterior></gml:Polygon></georss:where>",polygon.as_georss(:dialect => :gml).gsub("\n",""))
|
38
|
+
|
39
|
+
assert_equal("<Polygon><outerBoundaryIs><LinearRing><coordinates>12.4,-45.3 45.4,41.6 4.456,1.0698 12.4,-45.3</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><coordinates>2.4,5.3 5.4,1.4263 14.46,1.06 2.4,5.3</coordinates></LinearRing></innerBoundaryIs></Polygon>",polygon.as_kml.gsub("\n",""))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_geometry_collection
|
43
|
+
gc = GeometryCollection.from_geometries([Point.from_x_y(4.67,45.4,256),LineString.from_coordinates([[5.7,12.45],[67.55,54]],256)],256)
|
44
|
+
|
45
|
+
#only the first geometry is output
|
46
|
+
assert_equal("<georss:point floor=\"4\">45.4 4.67</georss:point>",gc.as_georss(:dialect => :simple,:floor => 4).gsub("\n",""))
|
47
|
+
assert_equal("<geo:lat>45.4</geo:lat><geo:long>4.67</geo:long>",gc.as_georss(:dialect => :w3cgeo).gsub("\n",""))
|
48
|
+
assert_equal("<georss:where><gml:Point><gml:pos>45.4 4.67</gml:pos></gml:Point></georss:where>",gc.as_georss(:dialect => :gml).gsub("\n",""))
|
49
|
+
|
50
|
+
assert_equal("<MultiGeometry id=\"HOYOYO-42\"><Point><coordinates>4.67,45.4</coordinates></Point><LineString><coordinates>5.7,12.45 67.55,54</coordinates></LineString></MultiGeometry>",gc.as_kml(:id => "HOYOYO-42").gsub("\n",""))
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_envelope
|
54
|
+
linear_ring1 = LinearRing.from_coordinates([[12.4,-45.3,5],[45.4,41.6,6],[4.456,1.0698,8],[12.4,-45.3,3.5]],256,true)
|
55
|
+
linear_ring2 = LinearRing.from_coordinates([[2.4,5.3,9.0],[5.4,1.4263,-5.4],[14.46,1.06,34],[2.4,5.3,3.14]],256,true)
|
56
|
+
polygon = Polygon.from_linear_rings([linear_ring1,linear_ring2],256,true)
|
57
|
+
|
58
|
+
e = polygon.envelope
|
59
|
+
|
60
|
+
assert_equal("<georss:box>-45.3 4.456 41.6 45.4</georss:box>",e.as_georss(:dialect => :simple).gsub("\n",""))
|
61
|
+
#center
|
62
|
+
assert_equal("<geo:lat>-1.85</geo:lat><geo:long>24.928</geo:long>",e.as_georss(:dialect => :w3cgeo).gsub("\n",""))
|
63
|
+
assert_equal("<georss:where><gml:Envelope><gml:LowerCorner>-45.3 4.456</gml:LowerCorner><gml:UpperCorner>41.6 45.4</gml:UpperCorner></gml:Envelope></georss:where>",e.as_georss(:dialect => :gml).gsub("\n",""))
|
64
|
+
|
65
|
+
assert_equal("<LatLonAltBox><north>41.6</north><south>-45.3</south><east>45.4</east><west>4.456</west><minAltitude>-5.4</minAltitude><maxAltitude>34</maxAltitude></LatLonAltBox>",e.as_kml.gsub("\n",""))
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -85,8 +85,8 @@ class TestSimpleFeatures < Test::Unit::TestCase
|
|
85
85
|
|
86
86
|
bbox = Point.from_x_y_z_m(-1.6,2.8,-3.4,15,123).bounding_box
|
87
87
|
assert_equal(2,bbox.length)
|
88
|
-
assert_equal(Point.
|
89
|
-
assert_equal(Point.
|
88
|
+
assert_equal(Point.from_x_y_z(-1.6,2.8,-3.4),bbox[0])
|
89
|
+
assert_equal(Point.from_x_y_z(-1.6,2.8,-3.4),bbox[1])
|
90
90
|
end
|
91
91
|
|
92
92
|
def test_point_equal
|
@@ -140,10 +140,11 @@ class TestSimpleFeatures < Test::Unit::TestCase
|
|
140
140
|
def test_point_distance
|
141
141
|
point1 = Point.from_x_y(0,0)
|
142
142
|
point2 = Point.from_x_y(3,4)
|
143
|
-
assert_equal(point1.euclidian_distance(point2)
|
144
|
-
|
145
|
-
|
146
|
-
|
143
|
+
assert_equal(5,point1.euclidian_distance(point2))
|
144
|
+
|
145
|
+
assert_in_delta(554058.924,point1.ellipsoidal_distance(point2),0.001)
|
146
|
+
|
147
|
+
assert_in_delta(555811.68,point1.spherical_distance(point2),0.01)
|
147
148
|
|
148
149
|
|
149
150
|
end
|
@@ -192,8 +193,8 @@ class TestSimpleFeatures < Test::Unit::TestCase
|
|
192
193
|
|
193
194
|
bbox = LineString.from_coordinates([[12.4,-45.3,123],[45.4,41.6,333],[4.456,1.0698,987]],123,true).bounding_box
|
194
195
|
assert_equal(2,bbox.length)
|
195
|
-
assert_equal(Point.
|
196
|
-
assert_equal(Point.
|
196
|
+
assert_equal(Point.from_x_y_z(4.456,-45.3,123),bbox[0])
|
197
|
+
assert_equal(Point.from_x_y_z(45.4,41.6,987),bbox[1])
|
197
198
|
|
198
199
|
end
|
199
200
|
|
@@ -283,8 +284,8 @@ class TestSimpleFeatures < Test::Unit::TestCase
|
|
283
284
|
|
284
285
|
bbox = Polygon.from_coordinates([[[12.4,-45.3,15.2],[45.4,41.6,2.4],[4.456,1.0698,5.6],[12.4,-45.3,6.1]],[[2.4,5.3,4.5],[5.4,1.4263,4.2],[14.46,1.06,123.1],[2.4,5.3,4.4]]],256,true).bounding_box
|
285
286
|
assert_equal(2,bbox.length)
|
286
|
-
assert_equal(Point.
|
287
|
-
assert_equal(Point.
|
287
|
+
assert_equal(Point.from_x_y_z(4.456,-45.3,2.4),bbox[0])
|
288
|
+
assert_equal(Point.from_x_y_z(45.4,41.6,123.1),bbox[1])
|
288
289
|
|
289
290
|
end
|
290
291
|
def test_polygon_equal
|
@@ -461,4 +462,27 @@ class TestSimpleFeatures < Test::Unit::TestCase
|
|
461
462
|
|
462
463
|
end
|
463
464
|
|
465
|
+
def test_envelope
|
466
|
+
linear_ring = LinearRing.from_coordinates([[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],256)
|
467
|
+
polygon = Polygon.from_linear_rings([linear_ring],256)
|
468
|
+
e = polygon.envelope
|
469
|
+
|
470
|
+
assert_equal(e.lower_corner.class, Point)
|
471
|
+
assert_equal(e.upper_corner.class, Point)
|
472
|
+
|
473
|
+
assert_equal(e.lower_corner.x,4.456)
|
474
|
+
assert_equal(e.lower_corner.y,-45.3)
|
475
|
+
assert_equal(e.upper_corner.x,45.4)
|
476
|
+
assert_equal(e.upper_corner.y,41.6)
|
477
|
+
|
478
|
+
line_string = LineString.from_coordinates([[13.6,-49.3],[45.4,44.6],[14.2,1.09],[13.6,-49.3]],256)
|
479
|
+
e2 = line_string.envelope
|
480
|
+
|
481
|
+
e3 = e.extend(e2)
|
482
|
+
|
483
|
+
assert_equal(e3.lower_corner.x,4.456)
|
484
|
+
assert_equal(e3.lower_corner.y,-49.3)
|
485
|
+
assert_equal(e3.upper_corner.x,45.4)
|
486
|
+
assert_equal(e3.upper_corner.y,44.6)
|
487
|
+
end
|
464
488
|
end
|
metadata
CHANGED
@@ -3,13 +3,13 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: GeoRuby
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2006-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2006-12-31 00:00:00 +01:00
|
8
8
|
summary: Ruby data holder for OGC Simple Features
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email: guilhem.vellut+georuby@gmail.com
|
12
|
-
homepage: http://thepochisuperstarmegashow.com
|
12
|
+
homepage: http://thepochisuperstarmegashow.com/projects
|
13
13
|
rubyforge_project:
|
14
14
|
description: GeoRuby is intended as a holder for data returned from PostGIS and MySQL Spatial queries. The data model roughly follows the OGC "Simple Features for SQL" specification (see www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections)
|
15
15
|
autorequire:
|
@@ -30,6 +30,7 @@ authors:
|
|
30
30
|
- Guilhem Vellut
|
31
31
|
files:
|
32
32
|
- lib/geo_ruby.rb
|
33
|
+
- lib/geo_ruby/simple_features/envelope.rb
|
33
34
|
- lib/geo_ruby/simple_features/ewkb_parser.rb
|
34
35
|
- lib/geo_ruby/simple_features/ewkt_parser.rb
|
35
36
|
- lib/geo_ruby/simple_features/geometry.rb
|
@@ -44,6 +45,7 @@ files:
|
|
44
45
|
- lib/geo_ruby/simple_features/polygon.rb
|
45
46
|
- test/test_ewkb_parser.rb
|
46
47
|
- test/test_ewkt_parser.rb
|
48
|
+
- test/test_georss_kml.rb
|
47
49
|
- test/test_simple_features.rb
|
48
50
|
- README
|
49
51
|
- MIT-LICENSE
|
@@ -51,6 +53,7 @@ files:
|
|
51
53
|
test_files:
|
52
54
|
- test/test_ewkb_parser.rb
|
53
55
|
- test/test_ewkt_parser.rb
|
56
|
+
- test/test_georss_kml.rb
|
54
57
|
- test/test_simple_features.rb
|
55
58
|
rdoc_options:
|
56
59
|
- --main
|