GeoRuby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +7 -0
- data/README +22 -0
- data/lib/geo_ruby/simple_features/ewkb_parser.rb +185 -0
- data/lib/geo_ruby/simple_features/geometry.rb +87 -0
- data/lib/geo_ruby/simple_features/geometry_collection.rb +94 -0
- data/lib/geo_ruby/simple_features/geometry_factory.rb +51 -0
- data/lib/geo_ruby/simple_features/line_string.rb +109 -0
- data/lib/geo_ruby/simple_features/linear_ring.rb +27 -0
- data/lib/geo_ruby/simple_features/multi_line_string.rb +35 -0
- data/lib/geo_ruby/simple_features/multi_point.rb +40 -0
- data/lib/geo_ruby/simple_features/multi_polygon.rb +38 -0
- data/lib/geo_ruby/simple_features/point.rb +85 -0
- data/lib/geo_ruby/simple_features/polygon.rb +103 -0
- data/lib/geo_ruby.rb +12 -0
- data/rakefile.rb +50 -0
- data/test/test_ewkb_parser.rb +91 -0
- data/test/test_simple_features.rb +303 -0
- metadata +62 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+georuby@gmail.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
=GeoRuby
|
2
|
+
This is GeoRuby 0.0.1. It is intended as a holder for data returned from PostGIS queries. Therefore, 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
|
+
|
4
|
+
===Available data types
|
5
|
+
The following geometric data types are provided :
|
6
|
+
- Point
|
7
|
+
- Line string
|
8
|
+
- Linear ring
|
9
|
+
- Polygon
|
10
|
+
- Multi point
|
11
|
+
- Multi line string
|
12
|
+
- Multi polygon
|
13
|
+
- Geometry collection
|
14
|
+
|
15
|
+
===Input and output
|
16
|
+
These geometries can be input and output in WKB/EWKB format (as well as the related HexWKB and HexEWKB formats). Since EWKB and HexEWKB are respectively the canonical binary and ASCII representations of geometries in PostGIS, this functionality can prove useful. Geometries can also be output as WKT/EWKT.
|
17
|
+
|
18
|
+
===License
|
19
|
+
GeoRuby is released under the MIT license.
|
20
|
+
|
21
|
+
===Support
|
22
|
+
Any questions, enhancement proposals, bug notifications or corrections can be sent to mailto:guilhem.vellut+georuby@gmail.com.
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'geo_ruby/simple_features/point'
|
2
|
+
require 'geo_ruby/simple_features/line_string'
|
3
|
+
require 'geo_ruby/simple_features/linear_ring'
|
4
|
+
require 'geo_ruby/simple_features/polygon'
|
5
|
+
require 'geo_ruby/simple_features/multi_point'
|
6
|
+
require 'geo_ruby/simple_features/multi_line_string'
|
7
|
+
require 'geo_ruby/simple_features/multi_polygon'
|
8
|
+
require 'geo_ruby/simple_features/geometry_collection'
|
9
|
+
|
10
|
+
module GeoRuby
|
11
|
+
module SimpleFeatures
|
12
|
+
#Parses EWKB strings and notifies of events (such as the beginning of the definition of geometry, the value of the SRID...) the factory passed as argument to the constructor.
|
13
|
+
#
|
14
|
+
#=Example
|
15
|
+
# factory = GeometryFactory::new
|
16
|
+
# ewkb_parser = EWKBParser::new(factory)
|
17
|
+
# ewkb_parser.parse(<EWKB String>)
|
18
|
+
# geometry = @factory.geometry
|
19
|
+
class EWKBParser
|
20
|
+
|
21
|
+
def initialize(factory)
|
22
|
+
@factory = factory
|
23
|
+
@parse_options ={
|
24
|
+
1 => method(:parse_point),
|
25
|
+
2 => method(:parse_line_string),
|
26
|
+
3 => method(:parse_polygon),
|
27
|
+
4 => method(:parse_multi_point),
|
28
|
+
5 => method(:parse_multi_line_string),
|
29
|
+
6 => method(:parse_multi_polygon),
|
30
|
+
7 => method(:parse_geometry_collection)
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
#Parses the ewkb string passed as argument and notifies the factory of events
|
35
|
+
def parse(ewkb)
|
36
|
+
@factory.reset
|
37
|
+
@unpack_structure=UnpackStructure::new(ewkb)
|
38
|
+
parse_geometry
|
39
|
+
@unpack_structure.done
|
40
|
+
end
|
41
|
+
private
|
42
|
+
def parse_geometry
|
43
|
+
@unpack_structure.endianness=@unpack_structure.read_byte
|
44
|
+
@geometry_type = @unpack_structure.read_uint
|
45
|
+
@dimension=2
|
46
|
+
|
47
|
+
if (@geometry_type & Z_MASK) != 0
|
48
|
+
@dimension=3
|
49
|
+
@geometry_type = @geometry_type & ~Z_MASK
|
50
|
+
end
|
51
|
+
if (@geometry_type & M_MASK) != 0
|
52
|
+
raise StandardError::new("For next version")
|
53
|
+
end
|
54
|
+
if (@geometry_type & SRID_MASK) != 0
|
55
|
+
@srid = @unpack_structure.read_uint
|
56
|
+
@geometry_type = @geometry_type & ~SRID_MASK
|
57
|
+
else
|
58
|
+
#to manage multi geometries : the srid is not present in sub_geometries, therefore we take the srid of the parent ; if it is the parent, we take the default srid
|
59
|
+
@srid= @srid || DEFAULT_SRID
|
60
|
+
end
|
61
|
+
if @parse_options.has_key? @geometry_type
|
62
|
+
@parse_options[@geometry_type].call
|
63
|
+
else
|
64
|
+
raise StandardError::new("Unknown geometry type")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
def parse_geometry_collection
|
68
|
+
parse_multi_geometries(GeometryCollection)
|
69
|
+
end
|
70
|
+
##must be corrected : endianness + geometry_type present
|
71
|
+
def parse_multi_polygon
|
72
|
+
parse_multi_geometries(MultiPolygon)
|
73
|
+
end
|
74
|
+
#must be corrected
|
75
|
+
def parse_multi_line_string
|
76
|
+
parse_multi_geometries(MultiLineString)
|
77
|
+
end
|
78
|
+
#must be corrected
|
79
|
+
def parse_multi_point
|
80
|
+
parse_multi_geometries(MultiPoint)
|
81
|
+
end
|
82
|
+
def parse_multi_geometries(geometry_type)
|
83
|
+
@factory.begin_geometry(geometry_type,@srid)
|
84
|
+
num_geometries = @unpack_structure.read_uint
|
85
|
+
1.upto(num_geometries) { parse_geometry }
|
86
|
+
@factory.end_geometry
|
87
|
+
end
|
88
|
+
def parse_polygon
|
89
|
+
@factory.begin_geometry(Polygon,@srid)
|
90
|
+
num_linear_rings = @unpack_structure.read_uint
|
91
|
+
1.upto(num_linear_rings) {parse_linear_ring}
|
92
|
+
@factory.end_geometry
|
93
|
+
end
|
94
|
+
def parse_linear_ring
|
95
|
+
parse_point_list(LinearRing)
|
96
|
+
end
|
97
|
+
def parse_line_string
|
98
|
+
parse_point_list(LineString)
|
99
|
+
end
|
100
|
+
#used to parse line_strings and linear_rings
|
101
|
+
def parse_point_list(geometry_type)
|
102
|
+
@factory.begin_geometry(geometry_type,@srid)
|
103
|
+
num_points = @unpack_structure.read_uint
|
104
|
+
1.upto(num_points) {parse_point}
|
105
|
+
@factory.end_geometry
|
106
|
+
end
|
107
|
+
def parse_point
|
108
|
+
@factory.begin_geometry(Point,@srid)
|
109
|
+
x = @unpack_structure.read_double
|
110
|
+
y = @unpack_structure.read_double
|
111
|
+
if @dimension == 3
|
112
|
+
z = @unpack_structure.read_double
|
113
|
+
@factory.add_point_x_y_z(x,y,z)
|
114
|
+
else
|
115
|
+
@factory.add_point_x_y(x,y)
|
116
|
+
end
|
117
|
+
@factory.end_geometry
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
#Parses HexEWKB strings. In reality, it just transforms the HexEWKB string into the equivalent EWKB string and lets the EWKBParser do the actual parsing.
|
122
|
+
class HexEWKBParser < EWKBParser
|
123
|
+
def initialize(factory)
|
124
|
+
super(factory)
|
125
|
+
end
|
126
|
+
#parses an HexEWKB string
|
127
|
+
def parse(hexewkb)
|
128
|
+
super(decode_hex(hexewkb))
|
129
|
+
end
|
130
|
+
#transforms a HexEWKB string into an EWKB string
|
131
|
+
def decode_hex(hexewkb)
|
132
|
+
temp_hexewkb= hexewkb.clone
|
133
|
+
result=""
|
134
|
+
while c = temp_hexewkb.slice!(0,2) do
|
135
|
+
break if c.length==0
|
136
|
+
result << c.hex
|
137
|
+
end
|
138
|
+
result
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
class UnpackStructure #:nodoc:
|
144
|
+
NDR=1
|
145
|
+
XDR=2
|
146
|
+
def initialize(ewkb)
|
147
|
+
@position=0
|
148
|
+
@ewkb=ewkb
|
149
|
+
end
|
150
|
+
def done
|
151
|
+
raise StandardError::new("Trailing data") if @position != @ewkb.length
|
152
|
+
end
|
153
|
+
def read_double
|
154
|
+
i=@position
|
155
|
+
@position += 8
|
156
|
+
packed_double = @ewkb[i...@position]
|
157
|
+
raise StandardError::new("Truncated data") if packed_double.nil? or packed_double.length < 8
|
158
|
+
packed_double.unpack(@double_mark)[0]
|
159
|
+
end
|
160
|
+
def read_uint
|
161
|
+
i=@position
|
162
|
+
@position += 4
|
163
|
+
packed_uint = @ewkb[i...@position]
|
164
|
+
raise StandardError::new("Truncated data") if packed_uint.nil? or packed_uint.length < 4
|
165
|
+
packed_uint.unpack(@uint_mark)[0]
|
166
|
+
end
|
167
|
+
def read_byte
|
168
|
+
i = @position
|
169
|
+
@position += 1
|
170
|
+
packed_byte = @ewkb[i...@position]
|
171
|
+
raise StandardError::new("Truncated data") if packed_byte.nil? or packed_byte.length < 1
|
172
|
+
packed_byte.unpack("C")[0]
|
173
|
+
end
|
174
|
+
def endianness=(byte_order)
|
175
|
+
if(byte_order == NDR)
|
176
|
+
@uint_mark="V"
|
177
|
+
@double_mark="E"
|
178
|
+
elsif(byte_order == XDR)
|
179
|
+
@uint_mark="N"
|
180
|
+
@double_mark="G"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module GeoRuby#:nodoc:
|
2
|
+
module SimpleFeatures
|
3
|
+
#arbitrary default SRID
|
4
|
+
DEFAULT_SRID=128
|
5
|
+
#indicates the presence of Z coordinates in EWKB strings
|
6
|
+
Z_MASK=0x80000000
|
7
|
+
#indicates the presence of M coordinates in EWKB strings. It is not supported at present.
|
8
|
+
M_MASK=0x40000000
|
9
|
+
#indicate the presence of a SRID in EWKB strings.
|
10
|
+
SRID_MASK=0x20000000
|
11
|
+
|
12
|
+
|
13
|
+
#Root of all geometric data classes.
|
14
|
+
#Objects of class Geometry should not be instantiated.
|
15
|
+
class Geometry
|
16
|
+
#SRID of the geometry
|
17
|
+
attr_accessor :srid
|
18
|
+
|
19
|
+
def initialize(srid=DEFAULT_SRID)
|
20
|
+
@srid=srid
|
21
|
+
end
|
22
|
+
|
23
|
+
#Outputs the geometry as an EWKB string.
|
24
|
+
#
|
25
|
+
#The argument +dimension+ forces the dimension of the output. The argument +with_srid+ indicates if the output must contain the SRID.
|
26
|
+
#
|
27
|
+
#WKB output can be obtained for any geometry by passing a +dimension+ of 2 and +with_srid+ set to false.
|
28
|
+
def as_binary(dimension=2,with_srid=true)
|
29
|
+
ewkb="";
|
30
|
+
|
31
|
+
ewkb << 1.chr #little_endian by default
|
32
|
+
|
33
|
+
type= binary_geometry_type
|
34
|
+
if dimension == 3
|
35
|
+
type = type | Z_MASK
|
36
|
+
end
|
37
|
+
if(with_srid)
|
38
|
+
type = type | SRID_MASK
|
39
|
+
ewkb << [type,@srid].pack("VV")
|
40
|
+
else
|
41
|
+
ewkb << [type].pack("V")
|
42
|
+
end
|
43
|
+
ewkb << binary_representation(dimension)
|
44
|
+
end
|
45
|
+
#Outputs the geometry as a HexEWKB string. It is almost the same as a WKB string, except that each byte of a WKB string is replaced by its hexadecimal 2-character representation in a HexEWKB string.
|
46
|
+
#
|
47
|
+
#The argument +dimension+ forces the dimension of the output. The argument +with_srid+ indicates if the output must contain the SRID.
|
48
|
+
#
|
49
|
+
#HexWKB output can be obtained for any geometry by passing a +dimension+ of 2 and +with_srid+ set to false.
|
50
|
+
def as_hex_binary(dimension=2,with_srid=true)
|
51
|
+
str = ""
|
52
|
+
as_binary(dimension,with_srid).each_byte {|char| str << sprintf("%02x",char).upcase}
|
53
|
+
str
|
54
|
+
end
|
55
|
+
|
56
|
+
#Outputs the geometry as a EWKT string.
|
57
|
+
#
|
58
|
+
#
|
59
|
+
#The argument +dimension+ forces the dimension of the output. The argument +with_srid+ indicates if the output must contain the SRID.
|
60
|
+
#
|
61
|
+
#WKT output can be obtained for any geometry by passing a +dimension+ of 2 and +with_srid+ set to false.
|
62
|
+
def as_text(dimension=2,with_srid=true)
|
63
|
+
if with_srid
|
64
|
+
ewkt="SRID=#{@srid};"
|
65
|
+
else
|
66
|
+
ewkt=""
|
67
|
+
end
|
68
|
+
ewkt << text_geometry_type << "("
|
69
|
+
ewkt << text_representation(dimension) << ")"
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.from_ewkb(ewkb)
|
73
|
+
factory = GeometryFactory::new
|
74
|
+
ewkb_parser= EWKBParser::new(factory)
|
75
|
+
ewkb_parser.parse(ewkb)
|
76
|
+
factory.geometry
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.from_hexewkb(hexewkb)
|
80
|
+
factory = GeometryFactory::new
|
81
|
+
hexewkb_parser= HexEWKBParser::new(factory)
|
82
|
+
hexewkb_parser.parse(hexewkb)
|
83
|
+
factory.geometry
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'geo_ruby/simple_features/geometry'
|
2
|
+
|
3
|
+
module GeoRuby
|
4
|
+
module SimpleFeatures
|
5
|
+
#Represents a collection of arbitrary geometries
|
6
|
+
class GeometryCollection < Geometry
|
7
|
+
attr_reader :geometries
|
8
|
+
|
9
|
+
def initialize(srid = DEFAULT_SRID)
|
10
|
+
super(srid)
|
11
|
+
@geometries = []
|
12
|
+
end
|
13
|
+
#add a geometry to the collection
|
14
|
+
def <<(geometry)
|
15
|
+
@geometries << geometry
|
16
|
+
end
|
17
|
+
#add geometries to the collection
|
18
|
+
def concat(geometries)
|
19
|
+
@geometries.concat geometries
|
20
|
+
end
|
21
|
+
#number of geometries in the collection
|
22
|
+
def length
|
23
|
+
@geometries.length
|
24
|
+
end
|
25
|
+
#gets the nth geometry
|
26
|
+
def [](n)
|
27
|
+
@geometries[n]
|
28
|
+
end
|
29
|
+
#replaces the nth geometry
|
30
|
+
def []=(n,geometry)
|
31
|
+
@geometries[n]=geometry
|
32
|
+
end
|
33
|
+
#iterates over all the geometries
|
34
|
+
def each(&proc)
|
35
|
+
@geometries.each(&proc)
|
36
|
+
end
|
37
|
+
#iterates over all the geometries, passing the index to the bloc
|
38
|
+
def each_index(&proc)
|
39
|
+
@geometries.each_index(&proc)
|
40
|
+
end
|
41
|
+
#inserts geometries at the nth position
|
42
|
+
def insert(n,*geometry)
|
43
|
+
@geometries.insert(n,*geometry)
|
44
|
+
end
|
45
|
+
#index of the geometry
|
46
|
+
def index(geometry)
|
47
|
+
@geometries.index(geometry)
|
48
|
+
end
|
49
|
+
#remove a slice of the collection
|
50
|
+
def remove(*slice)
|
51
|
+
@geometries.slice(*slice)
|
52
|
+
end
|
53
|
+
#tests the equality of geometry collections
|
54
|
+
def ==(other_collection)
|
55
|
+
if(other_collection.class != self.class)
|
56
|
+
false
|
57
|
+
elsif length != other_collection.length
|
58
|
+
false
|
59
|
+
else
|
60
|
+
index=0
|
61
|
+
while index<length
|
62
|
+
return false if self[index] != other_collection[index]
|
63
|
+
index+=1
|
64
|
+
end
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
#Binary representation of the collection
|
69
|
+
def binary_representation(dimension=2)
|
70
|
+
rep = [length].pack("V")
|
71
|
+
each {|geometry| rep << geometry.as_binary(dimension,false) }
|
72
|
+
rep
|
73
|
+
end
|
74
|
+
#WKB geometry type of the collection
|
75
|
+
def binary_geometry_type
|
76
|
+
7
|
77
|
+
end
|
78
|
+
#Text representation of a geometry collection
|
79
|
+
def text_representation(dimension=2)
|
80
|
+
@geometries.collect{|geometry| geometry.as_text(dimension,false)}.join(",")
|
81
|
+
end
|
82
|
+
#WKT geometry type
|
83
|
+
def text_geometry_type
|
84
|
+
"GEOMETRYCOLLECTION"
|
85
|
+
end
|
86
|
+
#creates a new GeometryCollection from an array of geometries
|
87
|
+
def self.from_geometries(geometries,srid=DEFAULT_SRID)
|
88
|
+
geometry_collection = GeometryCollection::new(srid)
|
89
|
+
geometry_collection.concat(geometries)
|
90
|
+
geometry_collection
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'geo_ruby/simple_features/point'
|
2
|
+
require 'geo_ruby/simple_features/line_string'
|
3
|
+
require 'geo_ruby/simple_features/linear_ring'
|
4
|
+
require 'geo_ruby/simple_features/polygon'
|
5
|
+
require 'geo_ruby/simple_features/multi_point'
|
6
|
+
require 'geo_ruby/simple_features/multi_line_string'
|
7
|
+
require 'geo_ruby/simple_features/multi_polygon'
|
8
|
+
require 'geo_ruby/simple_features/geometry_collection'
|
9
|
+
|
10
|
+
|
11
|
+
module GeoRuby
|
12
|
+
module SimpleFeatures
|
13
|
+
#Creates a new geometry according to constructions received from a parser, for example EWKBParser.
|
14
|
+
class GeometryFactory
|
15
|
+
#the built geometry
|
16
|
+
attr_reader :geometry
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@geometry_stack = []
|
20
|
+
end
|
21
|
+
#resets the factory
|
22
|
+
def reset
|
23
|
+
@geometry_stack = []
|
24
|
+
end
|
25
|
+
#add a 2D point to the current geometry
|
26
|
+
def add_point_x_y(x,y)
|
27
|
+
@geometry_stack.last.set_x_y(x,y)
|
28
|
+
end
|
29
|
+
#add a 3D point to the current geometry
|
30
|
+
def add_point_x_y_z(x,y,z)
|
31
|
+
@geometry_stack.last.set_x_y_z(x,y,z)
|
32
|
+
end
|
33
|
+
#begin a geometry of type +geometry_type+
|
34
|
+
def begin_geometry(geometry_type,srid=DEFAULT_SRID)
|
35
|
+
geometry= geometry_type::new(srid)
|
36
|
+
@geometry= geometry if @geometry.nil?
|
37
|
+
@geometry_stack << geometry
|
38
|
+
end
|
39
|
+
#terminates the current geometry
|
40
|
+
def end_geometry
|
41
|
+
geometry=@geometry_stack.pop
|
42
|
+
#add the newly defined geometry to its parent if there is one
|
43
|
+
@geometry_stack.last << geometry if !@geometry_stack.empty?
|
44
|
+
end
|
45
|
+
#abort a geometry
|
46
|
+
def abort_geometry
|
47
|
+
reset
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,109 @@
|
|
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 )
|
11
|
+
super(srid)
|
12
|
+
@points=[]
|
13
|
+
end
|
14
|
+
#tests if the line string is closed
|
15
|
+
def is_closed
|
16
|
+
#a bit naive...
|
17
|
+
@points.first == @points.last
|
18
|
+
end
|
19
|
+
#add a point to the end of the line string
|
20
|
+
def <<(point)
|
21
|
+
@points << point
|
22
|
+
end
|
23
|
+
#add points to the end of the line string
|
24
|
+
def concat(points)
|
25
|
+
@points.concat points
|
26
|
+
end
|
27
|
+
#number of points of the line string
|
28
|
+
def length
|
29
|
+
@points.length
|
30
|
+
end
|
31
|
+
#accesses the nth point in the line string
|
32
|
+
def [](n)
|
33
|
+
@points[n]
|
34
|
+
end
|
35
|
+
#replaces the nth point in the line string
|
36
|
+
def []=(n,point)
|
37
|
+
@points[n]=point
|
38
|
+
end
|
39
|
+
#iterates over the points in the line string
|
40
|
+
def each(&proc)
|
41
|
+
@points.each(&proc)
|
42
|
+
end
|
43
|
+
#iterates over the points, passing their indices to the bloc
|
44
|
+
def each_index(&proc)
|
45
|
+
@points.each_index(&proc)
|
46
|
+
end
|
47
|
+
#inserts points at the nth position
|
48
|
+
def insert(n,*point)
|
49
|
+
@points.insert(n,*point)
|
50
|
+
end
|
51
|
+
#gets the indices of point
|
52
|
+
def index(point)
|
53
|
+
@points.index(point)
|
54
|
+
end
|
55
|
+
#Removes a slice of points
|
56
|
+
def remove(*slice)
|
57
|
+
@points.slice(*slice)
|
58
|
+
end
|
59
|
+
#Tests the equality of line strings
|
60
|
+
def ==(other_line_string)
|
61
|
+
if(other_line_string.class != self.class or
|
62
|
+
other_line_string.length != self.length)
|
63
|
+
false
|
64
|
+
else
|
65
|
+
index=0
|
66
|
+
while index<length
|
67
|
+
return false if self[index] != other_line_string[index]
|
68
|
+
index+=1
|
69
|
+
end
|
70
|
+
true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#Binary representation of a line string
|
75
|
+
def binary_representation(dimension=2)
|
76
|
+
rep = [length].pack("V")
|
77
|
+
each {|point| rep << point.binary_representation(dimension) }
|
78
|
+
rep
|
79
|
+
end
|
80
|
+
#WKB geometry type
|
81
|
+
def binary_geometry_type
|
82
|
+
2
|
83
|
+
end
|
84
|
+
#Text representation of a line string
|
85
|
+
def text_representation(dimension=2)
|
86
|
+
@points.collect{|point| point.text_representation(dimension) }.join(",")
|
87
|
+
end
|
88
|
+
#WKT geometry type
|
89
|
+
def text_geometry_type
|
90
|
+
"LINESTRING"
|
91
|
+
end
|
92
|
+
|
93
|
+
#Creates a new line string. Accept an array of points as argument
|
94
|
+
def self.from_points(points,srid=DEFAULT_SRID)
|
95
|
+
line_string = LineString::new(srid)
|
96
|
+
line_string.concat(points)
|
97
|
+
line_string
|
98
|
+
end
|
99
|
+
|
100
|
+
#Creates a new line string. Accept a sequence of points as argument : ((x,y)...(x,y))
|
101
|
+
def self.from_raw_point_sequence(points,srid=DEFAULT_SRID)
|
102
|
+
line_string = LineString::new(srid)
|
103
|
+
line_string.concat( points.collect{|point_coords| Point.from_coordinates(point_coords,srid) } )
|
104
|
+
line_string
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'geo_ruby/simple_features/line_string'
|
2
|
+
|
3
|
+
module GeoRuby
|
4
|
+
module SimpleFeatures
|
5
|
+
#Represents a linear ring, which is a closed line string (see LineString). No check is performed to verify if the linear ring is really closed.
|
6
|
+
class LinearRing < LineString
|
7
|
+
def initialize(srid= DEFAULT_SRID)
|
8
|
+
super(srid)
|
9
|
+
end
|
10
|
+
|
11
|
+
#creates a new linear ring from an array of points. The first and last points should be equal, although no check is performed here.
|
12
|
+
def self.from_points(points,srid=DEFAULT_SRID)
|
13
|
+
linear_ring = LinearRing::new(srid)
|
14
|
+
linear_ring.concat(points)
|
15
|
+
linear_ring
|
16
|
+
end
|
17
|
+
|
18
|
+
#creates a new linear ring from a sequence of points : ((x,y)...(x,y)).
|
19
|
+
def self.from_raw_point_sequence(points,srid=DEFAULT_SRID)
|
20
|
+
linear_ring = LinearRing::new(srid)
|
21
|
+
linear_ring.concat( points.collect{|point_coords| Point.from_coordinates(point_coords,srid) } )
|
22
|
+
linear_ring
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'geo_ruby/simple_features/geometry_collection'
|
2
|
+
|
3
|
+
module GeoRuby
|
4
|
+
module SimpleFeatures
|
5
|
+
#Represents a group of line strings (see LineString).
|
6
|
+
class MultiLineString < GeometryCollection
|
7
|
+
def initialize(srid = DEFAULT_SRID)
|
8
|
+
super(srid)
|
9
|
+
end
|
10
|
+
def binary_geometry_type
|
11
|
+
5
|
12
|
+
end
|
13
|
+
#Text representation of a multi line string
|
14
|
+
def text_representation(dimension = 2)
|
15
|
+
@geometries.collect{|line_string| "(" + line_string.text_representation + ")" }.join(",")
|
16
|
+
end
|
17
|
+
#WKT geometry type
|
18
|
+
def text_geometry_type
|
19
|
+
"MULTILINESTRING"
|
20
|
+
end
|
21
|
+
#Creates a new multi line string from an array of line strings
|
22
|
+
def self.from_line_strings(line_strings,srid=DEFAULT_SRID)
|
23
|
+
multi_line_string = MultiLineString::new(srid)
|
24
|
+
multi_line_string.concat(line_strings)
|
25
|
+
multi_line_string
|
26
|
+
end
|
27
|
+
#Creates a new multi line string from sequences of points : (((x,y)...(x,y)),((x,y)...(x,y)))
|
28
|
+
def self.from_raw_point_sequences(point_sequences,srid=DEFAULT_SRID)
|
29
|
+
multi_line_string = MultiLineString::new(srid)
|
30
|
+
multi_line_string.concat(point_sequences.collect {|point_sequence| LineString.from_raw_point_sequence(point_sequence,srid) })
|
31
|
+
multi_line_string
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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)
|
9
|
+
super(srid)
|
10
|
+
end
|
11
|
+
|
12
|
+
def binary_geometry_type
|
13
|
+
4
|
14
|
+
end
|
15
|
+
#Text representation of a MultiPoint
|
16
|
+
def text_representation(dimension=2)
|
17
|
+
@geometries.collect{|point| point.text_representation(dimension)}.join(",")
|
18
|
+
end
|
19
|
+
#WKT geoemtry type
|
20
|
+
def text_geometry_type
|
21
|
+
"MULTIPOINT"
|
22
|
+
end
|
23
|
+
|
24
|
+
#Creates a new multi point from an array of points
|
25
|
+
def self.from_points(points,srid= DEFAULT_SRID)
|
26
|
+
multi_point= MultiPoint::new(srid)
|
27
|
+
multi_point.concat(points)
|
28
|
+
multi_point
|
29
|
+
end
|
30
|
+
|
31
|
+
#Creates a new multi point from a list of point coordinates : ((x,y)...(x,y))
|
32
|
+
def self.from_raw_point_sequence(point_sequence,srid= DEFAULT_SRID)
|
33
|
+
multi_point= MultiPoint::new(srid)
|
34
|
+
multi_point.concat(point_sequence.collect {|point| Point.from_coordinates(point,srid)})
|
35
|
+
multi_point
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|