GeoRuby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ require 'geo_ruby/simple_features/geometry_collection'
2
+
3
+
4
+ module GeoRuby
5
+ module SimpleFeatures
6
+ #Represents a group of polygons (see Polygon).
7
+ class MultiPolygon < GeometryCollection
8
+ def initialize(srid = DEFAULT_SRID)
9
+ super(srid)
10
+ end
11
+ def binary_geometry_type
12
+ 6
13
+ end
14
+ #Text representation of a MultiPolygon
15
+ def text_representation(dimension=2)
16
+ @geometries.collect{|polygon| "(" + polygon.text_representation(dimension) + ")"}.join(",")
17
+ end
18
+ #WKT geometry type
19
+ def text_geometry_type
20
+ "MULTIPOLYGON"
21
+ end
22
+
23
+ #Creates a multi polygon from an array of polygons
24
+ def self.from_polygons(polygons,srid=DEFAULT_SRID)
25
+ multi_polygon = MultiPolygon::new(srid)
26
+ multi_polygon.concat(polygons)
27
+ multi_polygon
28
+ end
29
+ #Creates a multi polygon from sequences of points : ((((x,y)...(x,y)),((x,y)...(x,y)),((x,y)...(x,y)))
30
+ def self.from_raw_point_sequences(point_sequences, srid= DEFAULT_SRID)
31
+ multi_polygon = MultiPolygon::new(srid)
32
+ multi_polygon.concat( point_sequences.collect {|point_sequence| Polygon.from_raw_point_sequences(point_sequence,srid) } )
33
+ multi_polygon
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,85 @@
1
+ require "geo_ruby/simple_features/geometry"
2
+
3
+ module GeoRuby
4
+ module SimpleFeatures
5
+ #Represents a point. It is in 3D if the Z coordinate is not +nil+.
6
+ class Point < Geometry
7
+ #Coordinates of the point
8
+ attr_accessor :x,:y,:z
9
+
10
+ def initialize(srid=DEFAULT_SRID)
11
+ super(srid)
12
+ @x=0.0
13
+ @y=0.0
14
+ @z=nil
15
+ end
16
+ #sets all coordinates in one call
17
+ def set_x_y_z(x,y,z)
18
+ @x=x
19
+ @y=y
20
+ @z=z
21
+ end
22
+ #sets all coordinates of a 2D point in one call
23
+ def set_x_y(x,y)
24
+ @x=x
25
+ @y=y
26
+ end
27
+ #tests the equality of points
28
+ def ==(other_point)
29
+ if other_point.class != self.class
30
+ false
31
+ else
32
+ @x == other_point.x and @y == other_point.y and @z == other_point.z
33
+ end
34
+ end
35
+ #binary representation of a point. It lacks some headers to be a valid EWKB representation.
36
+ def binary_representation(dimension=2)
37
+ if dimension == 2
38
+ [@x,@y].pack("EE")
39
+ else
40
+ [@x,@y,@z || 0].pack("EEE")
41
+ end
42
+ end
43
+ #WKB geometry type of a point
44
+ def binary_geometry_type
45
+ 1
46
+ end
47
+
48
+ #text representation of a point
49
+ def text_representation(dimension=2)
50
+ if dimension == 2
51
+ "#{@x} #{@y}"
52
+ else
53
+ "#{@x} #{@y} #{@z || 0}"
54
+ end
55
+ end
56
+ #WKT geometry type of a point
57
+ def text_geometry_type
58
+ "POINT"
59
+ end
60
+
61
+ #creates a point from an array of coordinates
62
+ def self.from_coordinates(coords,srid=DEFAULT_SRID)
63
+ point= Point::new(srid)
64
+ if coords.length == 2
65
+ point.set_x_y(*coords)
66
+ else
67
+ point.set_x_y_z(*coords)
68
+ end
69
+ point
70
+ end
71
+ #creates a point from the X and Y coordinates
72
+ def self.from_x_y(x,y,srid=DEFAULT_SRID)
73
+ point= Point::new(srid)
74
+ point.set_x_y(x,y)
75
+ point
76
+ end
77
+ #creates a point from the X, Y and Z coordinates
78
+ def self.from_x_y_z(x,y,z,srid=DEFAULT_SRID)
79
+ point= Point::new(srid)
80
+ point.set_x_y_z(x,y,z)
81
+ point
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,103 @@
1
+ require 'geo_ruby/simple_features/geometry'
2
+
3
+ module GeoRuby
4
+ module SimpleFeatures
5
+ #Represents a polygon as an array of linear rings (see LinearRing). No check is performed regarding the validity of the geometries forming the polygon.
6
+ class Polygon < Geometry
7
+ #the list of rings forming the polygon
8
+ attr_reader :rings
9
+
10
+ def initialize(srid = DEFAULT_SRID)
11
+ super(srid)
12
+ @rings = []
13
+ end
14
+ #add one to the polygon
15
+ def <<(ring)
16
+ @rings << ring
17
+ end
18
+ #add one or more rings to the polygon
19
+ def concat(rings)
20
+ @rings.concat rings
21
+ end
22
+ #number of linear rings in the polygon
23
+ def length
24
+ @rings.length
25
+ end
26
+ #access the nth linear ring
27
+ def [](n)
28
+ @rings[n]
29
+ end
30
+ #modifies the value of the nth linear ring
31
+ def []=(n,ring)
32
+ @rings[n]=ring
33
+ end
34
+ #iterates over the linear rings
35
+ def each(&proc)
36
+ @rings.each(&proc)
37
+ end
38
+ #iterates over the linear rings, passing their indices to the bloc
39
+ def each_index(&proc)
40
+ @rings.each_index(&proc)
41
+ end
42
+ #insert linear rings at the nth position
43
+ def insert(n,*ring)
44
+ @rings.insert(n,*ring)
45
+ end
46
+ #index of the linear_ring
47
+ def index(ring)
48
+ @rings.index(ring)
49
+ end
50
+ #remove linear rings. Arguments can be of the same type as Array#slice
51
+ def remove(*slice)
52
+ @rings.slice(*slice)
53
+ end
54
+ #tests for other equality. The SRID is not taken into account.
55
+ def ==(other_polygon)
56
+ if other_polygon.class != self.class or
57
+ length != other_polygon.length
58
+ false
59
+ else
60
+ index=0
61
+ while index<length
62
+ return false if self[index] != other_polygon[index]
63
+ index+=1
64
+ end
65
+ true
66
+ end
67
+ end
68
+ #binary representation of a polygon, without the headers neccessary for a valid WKB string
69
+ def binary_representation(dimension=2)
70
+ rep = [length].pack("V")
71
+ each {|linear_ring| rep << linear_ring.binary_representation(dimension) }
72
+ rep
73
+ end
74
+ #WKB geometry type
75
+ def binary_geometry_type
76
+ 3
77
+ end
78
+ #Text representation of a polygon
79
+ def text_representation(dimension=2)
80
+ @rings.collect{|line_string| "(" + line_string.text_representation(dimension) + ")" }.join(",")
81
+ end
82
+ #WKT geometry type
83
+ def text_geometry_type
84
+ "POLYGON"
85
+ end
86
+ #creates a new polygon. Accepts an array of linear strings as argument
87
+ def self.from_linear_rings(linear_rings,srid = DEFAULT_SRID)
88
+ polygon = Polygon::new(srid)
89
+ polygon.concat(linear_rings)
90
+ polygon
91
+ end
92
+
93
+ #creates a new polygon. Accepts a sequence of points as argument : ((x,y)....(x,y)),((x,y).....(x,y))
94
+ def self.from_raw_point_sequences(point_sequences,srid=DEFAULT_SRID)
95
+ polygon = Polygon::new(srid)
96
+ polygon.concat( point_sequences.collect {|point_sequence| LinearRing.from_raw_point_sequence(point_sequence,srid) } )
97
+ polygon
98
+ end
99
+
100
+
101
+ end
102
+ end
103
+ end
data/lib/geo_ruby.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'geo_ruby/simple_features/geometry'
2
+ require 'geo_ruby/simple_features/point'
3
+ require 'geo_ruby/simple_features/line_string'
4
+ require 'geo_ruby/simple_features/linear_ring'
5
+ require 'geo_ruby/simple_features/polygon'
6
+ require 'geo_ruby/simple_features/multi_point'
7
+ require 'geo_ruby/simple_features/multi_line_string'
8
+ require 'geo_ruby/simple_features/multi_polygon'
9
+ require 'geo_ruby/simple_features/geometry_collection'
10
+ require 'geo_ruby/simple_features/ewkb_parser'
11
+ require 'geo_ruby/simple_features/geometry_factory'
12
+
data/rakefile.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+
6
+ task :default => :test
7
+
8
+ desc "Run the tests"
9
+ Rake::TestTask::new do |t|
10
+ t.test_files = FileList['test/test*.rb']
11
+ t.verbose = true
12
+ end
13
+
14
+ desc "Generate the documentation"
15
+ Rake::RDocTask::new do |rdoc|
16
+ rdoc.rdoc_dir = 'doc/'
17
+ rdoc.title = "GeoRuby Documentation"
18
+ rdoc.options << '--line-numbers' << '--inline-source'
19
+ rdoc.rdoc_files.include('README')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ spec = Gem::Specification::new do |s|
24
+ s.platform = Gem::Platform::RUBY
25
+
26
+ s.name = 'GeoRuby'
27
+ s.version = "0.0.1"
28
+ s.summary = "Ruby data holder for OGC Simple Features"
29
+ s.description = <<EOF
30
+ GeoRuby 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 www.opengis.org/docs/99-049.pdf), although without any kind of advanced functionalities (such as geometric operators or reprojections)
31
+ EOF
32
+ s.author = 'Guilhem Vellut'
33
+ s.email = 'guilhem.vellut+georuby@gmail.com'
34
+ s.homepage = "http://thepochisuperstarmegashow.com"
35
+
36
+ s.requirements << 'none'
37
+ s.require_path = 'lib'
38
+ s.files = FileList["lib/**/*.rb", "test/**/*.rb", "README","MIT-LICENSE","rakefile.rb"]
39
+ s.test_files = FileList['test/test*.rb']
40
+
41
+ s.has_rdoc = true
42
+ s.extra_rdoc_files = ["README"]
43
+ s.rdoc_options.concat ['--main', 'README']
44
+ end
45
+
46
+ desc "Package the library as a gem"
47
+ Rake::GemPackageTask.new(spec) do |pkg|
48
+ pkg.need_zip = true
49
+ pkg.need_tar = true
50
+ end
@@ -0,0 +1,91 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'geo_ruby'
4
+ require 'test/unit'
5
+
6
+ include GeoRuby::SimpleFeatures
7
+
8
+ class TestEWKBParser < Test::Unit::TestCase
9
+
10
+ def setup
11
+ @factory = GeometryFactory::new
12
+ @hex_ewkb_parser = HexEWKBParser::new(@factory)
13
+ end
14
+
15
+ def test_point2d
16
+ @hex_ewkb_parser.parse("01010000207B000000CDCCCCCCCCCC28406666666666A64640")
17
+ point = @factory.geometry
18
+ assert(point.instance_of?(Point))
19
+ assert_equal(Point.from_x_y(12.4,45.3,123),point)
20
+ end
21
+
22
+ def test_point3d
23
+ @hex_ewkb_parser.parse("01010000A07B000000CDCCCCCCCCCC28406666666666A646400000000000000CC0")
24
+ point = @factory.geometry
25
+ assert(point.instance_of?(Point))
26
+ assert_equal(Point.from_x_y_z(12.4,45.3,-3.5,123),point)
27
+ end
28
+
29
+ def test_line_string
30
+ @hex_ewkb_parser.parse("01020000200001000002000000CDCCCCCCCCCC28406666666666A646C03333333333B34640CDCCCCCCCCCC4440")
31
+ line_string = @factory.geometry
32
+ assert(line_string.instance_of?(LineString))
33
+ assert_equal(LineString.from_raw_point_sequence([[12.4,-45.3],[45.4,41.6]],256),line_string)
34
+ end
35
+
36
+ def test_polygon
37
+ @hex_ewkb_parser.parse("0103000020000100000200000005000000000000000000000000000000000000000000000000001040000000000000000000000000000010400000000000001040000000000000000000000000000010400000000000000000000000000000000005000000000000000000F03F000000000000F03F0000000000000840000000000000F03F00000000000008400000000000000840000000000000F03F0000000000000840000000000000F03F000000000000F03F")
38
+ polygon = @factory.geometry
39
+ assert(polygon.instance_of?(Polygon))
40
+ assert_equal(Polygon.from_raw_point_sequences([[[0,0],[4,0],[4,4],[0,4],[0,0]],[[1,1],[3,1],[3,3],[1,3],[1,1]]],256),polygon)
41
+ end
42
+
43
+ def test_geometry_collection
44
+ @hex_ewkb_parser.parse("010700002000010000020000000101000000AE47E17A14AE12403333333333B34640010200000002000000CDCCCCCCCCCC16406666666666E628403333333333E350400000000000004B40")
45
+ geometry_collection = @factory.geometry
46
+ assert(geometry_collection.instance_of?(GeometryCollection))
47
+ assert_equal(GeometryCollection.from_geometries([Point.from_x_y(4.67,45.4,256),LineString.from_raw_point_sequence([[5.7,12.45],[67.55,54]],256)],256),geometry_collection)
48
+ assert_equal(256,geometry_collection[0].srid)
49
+ end
50
+
51
+ def test_multi_point
52
+ @hex_ewkb_parser.parse("0104000020BC010000030000000101000000CDCCCCCCCCCC28403333333333D35EC0010100000066666666664650C09A99999999D95E4001010000001F97DD388EE35E400000000000C05E40")
53
+ multi_point = @factory.geometry
54
+ assert(multi_point.instance_of?(MultiPoint))
55
+ assert_equal(MultiPoint.from_raw_point_sequence([[12.4,-123.3],[-65.1,123.4],[123.55555555,123]],444),multi_point)
56
+ assert_equal(444,multi_point.srid)
57
+ assert_equal(444,multi_point[0].srid)
58
+ end
59
+
60
+ def test_multi_line_string
61
+ @hex_ewkb_parser.parse("01050000200001000002000000010200000002000000000000000000F83F9A99999999994640E4BD6A65C20F4BC0FA7E6ABC749388BF010200000003000000000000000000F83F9A99999999994640E4BD6A65C20F4BC0FA7E6ABC749388BF39B4C876BE8F46403333333333D35E40")
62
+ multi_line_string = @factory.geometry
63
+ assert(multi_line_string.instance_of?(MultiLineString))
64
+ assert_equal(MultiLineString.from_line_strings([LineString.from_raw_point_sequence([[1.5,45.2],[-54.12312,-0.012]],256),LineString.from_raw_point_sequence([[1.5,45.2],[-54.12312,-0.012],[45.123,123.3]],256)],256),multi_line_string)
65
+ assert_equal(256,multi_line_string.srid)
66
+ assert_equal(256,multi_line_string[0].srid)
67
+ end
68
+
69
+ def test_multi_polygon
70
+ @hex_ewkb_parser.parse("0106000020000100000200000001030000000200000004000000CDCCCCCCCCCC28406666666666A646C03333333333B34640CDCCCCCCCCCC44406DE7FBA9F1D211403D2CD49AE61DF13FCDCCCCCCCCCC28406666666666A646C004000000333333333333034033333333333315409A999999999915408A8EE4F21FD2F63FEC51B81E85EB2C40F6285C8FC2F5F03F3333333333330340333333333333154001030000000200000005000000000000000000000000000000000000000000000000001040000000000000000000000000000010400000000000001040000000000000000000000000000010400000000000000000000000000000000005000000000000000000F03F000000000000F03F0000000000000840000000000000F03F00000000000008400000000000000840000000000000F03F0000000000000840000000000000F03F000000000000F03F")
71
+ multi_polygon = @factory.geometry
72
+ assert(multi_polygon.instance_of?(MultiPolygon))
73
+ assert_equal(MultiPolygon.from_polygons([Polygon.from_raw_point_sequences([[[12.4,-45.3],[45.4,41.6],[4.456,1.0698],[12.4,-45.3]],[[2.4,5.3],[5.4,1.4263],[14.46,1.06],[2.4,5.3]]],256),Polygon.from_raw_point_sequences([[[0,0],[4,0],[4,4],[0,4],[0,0]],[[1,1],[3,1],[3,3],[1,3],[1,1]]],256)],256),multi_polygon)
74
+ assert_equal(256,multi_polygon.srid)
75
+ assert_equal(256,multi_polygon[0].srid)
76
+ end
77
+ def test_failure_trailing_data
78
+ #added A345 at the end
79
+ assert_raise(StandardError){@hex_ewkb_parser.parse("01010000207B000000CDCCCCCCCCCC28406666666666A64640A345")}
80
+ end
81
+ def test_failure_unknown_geometry_type
82
+ assert_raise(StandardError){@hex_ewkb_parser.parse("01090000207B000000CDCCCCCCCCCC28406666666666A64640")}
83
+ end
84
+ def test_failure_m
85
+ assert_raise(StandardError){@hex_ewkb_parser.parse("01010000607B000000CDCCCCCCCCCC28406666666666A64640")}
86
+ end
87
+ def test_failure_truncated_data
88
+ assert_raise(StandardError){@hex_ewkb_parser.parse("01010000207B000000CDCCCCCCCCCC2840666666")}
89
+ end
90
+
91
+ end