nofxx-georuby 1.3.7

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 (54) hide show
  1. data/History.txt +4 -0
  2. data/LICENSE +21 -0
  3. data/README.txt +59 -0
  4. data/Rakefile +49 -0
  5. data/VERSION.yml +4 -0
  6. data/lib/geo_ruby.rb +21 -0
  7. data/lib/geo_ruby/base/envelope.rb +167 -0
  8. data/lib/geo_ruby/base/ewkb_parser.rb +216 -0
  9. data/lib/geo_ruby/base/ewkt_parser.rb +336 -0
  10. data/lib/geo_ruby/base/geometry.rb +234 -0
  11. data/lib/geo_ruby/base/geometry_collection.rb +136 -0
  12. data/lib/geo_ruby/base/geometry_factory.rb +81 -0
  13. data/lib/geo_ruby/base/georss_parser.rb +135 -0
  14. data/lib/geo_ruby/base/helper.rb +18 -0
  15. data/lib/geo_ruby/base/line_string.rb +184 -0
  16. data/lib/geo_ruby/base/linear_ring.rb +12 -0
  17. data/lib/geo_ruby/base/multi_line_string.rb +39 -0
  18. data/lib/geo_ruby/base/multi_point.rb +41 -0
  19. data/lib/geo_ruby/base/multi_polygon.rb +37 -0
  20. data/lib/geo_ruby/base/point.rb +310 -0
  21. data/lib/geo_ruby/base/polygon.rb +150 -0
  22. data/lib/geo_ruby/shp4r/dbf.rb +180 -0
  23. data/lib/geo_ruby/shp4r/shp.rb +701 -0
  24. data/spec/data/multipoint.dbf +0 -0
  25. data/spec/data/multipoint.shp +0 -0
  26. data/spec/data/multipoint.shx +0 -0
  27. data/spec/data/point.dbf +0 -0
  28. data/spec/data/point.shp +0 -0
  29. data/spec/data/point.shx +0 -0
  30. data/spec/data/polygon.dbf +0 -0
  31. data/spec/data/polygon.shp +0 -0
  32. data/spec/data/polygon.shx +0 -0
  33. data/spec/data/polyline.dbf +0 -0
  34. data/spec/data/polyline.shp +0 -0
  35. data/spec/data/polyline.shx +0 -0
  36. data/spec/geo_ruby/base/envelope_spec.rb +45 -0
  37. data/spec/geo_ruby/base/ewkb_parser_spec.rb +158 -0
  38. data/spec/geo_ruby/base/ewkt_parser_spec.rb +179 -0
  39. data/spec/geo_ruby/base/geometry_collection_spec.rb +55 -0
  40. data/spec/geo_ruby/base/geometry_factory_spec.rb +11 -0
  41. data/spec/geo_ruby/base/geometry_spec.rb +32 -0
  42. data/spec/geo_ruby/base/georss_parser_spec.rb +218 -0
  43. data/spec/geo_ruby/base/line_string_spec.rb +208 -0
  44. data/spec/geo_ruby/base/linear_ring_spec.rb +14 -0
  45. data/spec/geo_ruby/base/multi_line_string_spec.rb +35 -0
  46. data/spec/geo_ruby/base/multi_point_spec.rb +29 -0
  47. data/spec/geo_ruby/base/multi_polygon_spec.rb +35 -0
  48. data/spec/geo_ruby/base/point_spec.rb +275 -0
  49. data/spec/geo_ruby/base/polygon_spec.rb +108 -0
  50. data/spec/geo_ruby/shp4r/shp_spec.rb +238 -0
  51. data/spec/geo_ruby_spec.rb +27 -0
  52. data/spec/spec.opts +6 -0
  53. data/spec/spec_helper.rb +12 -0
  54. metadata +123 -0
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-08-14
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ GeoRuby License
2
+
3
+ Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+georuby@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to
7
+ deal in the Software without restriction, including without limitation the
8
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9
+ permit persons to whom the Software is furnished to do so, subject to the
10
+ following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ = geo_ruby
2
+
3
+ Experiment with GeoRuby (http://georuby.rubyforge.org) with the fast Geo (http://geo.rubyforge.org).
4
+
5
+
6
+ == DESCRIPTION:
7
+
8
+ the objective is provide all the georuby functionalities, with time consuming calculus in C.
9
+ _this is not usable yet_
10
+
11
+ See:
12
+ GeoRuby (http://georuby.rubyforge.org)
13
+ Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+georuby@gmail.com>
14
+
15
+ Geo (http://geo.rubyforge.org)
16
+ Copyright (C) 2007 Martin Kihlgren
17
+
18
+
19
+ == REQUIREMENTS:
20
+
21
+ glib:: http://www.gtk.org/
22
+
23
+ == FEATURES:
24
+
25
+ =Available data types
26
+
27
+ - Point
28
+ - Line string
29
+ - Linear ring
30
+ - Polygon
31
+ - Multi point
32
+ - Multi line string
33
+ - Multi polygon
34
+ - Geometry collection
35
+
36
+ They can be in 2D, 3DZ, 3DM, and 4D.
37
+
38
+
39
+ Geo::Point:: A 2D point providing some common geometry operations.
40
+ Geo::Line:: A 2D line consisting of 2 Geo::Points providing some common geometry operations.
41
+ Geo::Triangle:: A 2D triangle consisting of 3 Geo::Points providing some common geometry operations.
42
+ Geo::PointSet:: A Set-like container of Points.
43
+ Geo::LineSet:: A Set-like container of Lines that provides optimized versions of some common geometry operations on lines.
44
+ Geo::TriangleSet:: A Set-like container of Triangles that provides optimized versions of some common geometry operations on lines.
45
+
46
+ == Usage:
47
+
48
+ Just install the gem.
49
+
50
+ == Examples:
51
+
52
+ To find if a given line intersects a set of 100 000 other lines:
53
+
54
+ :include:examples/intersects.rb
55
+
56
+ == License:
57
+
58
+ GeoRuby is released under the MIT license.
59
+ geo is provided under the GPL-2.
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "georuby"
8
+ gem.summary = "Ruby data holder for OGC Simple Features"
9
+ gem.description = "GeoRuby provides geometric data types from the OGC 'Simple Features' specification."
10
+ gem.email = "x@nofxx.com"
11
+ gem.homepage = "http://github.com/nofxx/georuby"
12
+ gem.authors = ["Guilhem Vellut", "Marcos Augusto"]
13
+
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ require 'spec/rake/spectask'
21
+ Spec::Rake::SpecTask.new(:spec) do |spec|
22
+ spec.libs << 'lib' << 'spec'
23
+ spec.spec_files = FileList['spec/**/*_spec.rb']
24
+ end
25
+
26
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.pattern = 'spec/**/*_spec.rb'
29
+ spec.rcov = true
30
+ end
31
+
32
+
33
+ task :default => :spec
34
+
35
+ require 'rake/rdoctask'
36
+ Rake::RDocTask.new do |rdoc|
37
+ if File.exist?('VERSION.yml')
38
+ config = YAML.load(File.read('VERSION.yml'))
39
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
40
+ else
41
+ version = ""
42
+ end
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "geo_ruby #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
49
+
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 1
3
+ :minor: 3
4
+ :patch: 7
@@ -0,0 +1,21 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'geo_ruby/base/helper'
5
+ require 'geo_ruby/base/ewkt_parser'
6
+ require 'geo_ruby/base/ewkb_parser'
7
+ require 'geo_ruby/base/geometry'
8
+ require 'geo_ruby/base/point'
9
+ require 'geo_ruby/base/line_string'
10
+ require 'geo_ruby/base/linear_ring'
11
+ require 'geo_ruby/base/polygon'
12
+ require 'geo_ruby/base/multi_point'
13
+ require 'geo_ruby/base/multi_line_string'
14
+ require 'geo_ruby/base/multi_polygon'
15
+ require 'geo_ruby/base/geometry_collection'
16
+ require 'geo_ruby/base/envelope'
17
+ require 'geo_ruby/base/geometry_factory'
18
+ require 'geo_ruby/base/georss_parser'
19
+ require 'geo_ruby/shp4r/shp'
20
+
21
+ GeoRuby::SimpleFeatures = GeoRuby::Base
@@ -0,0 +1,167 @@
1
+ module GeoRuby
2
+ module Base
3
+
4
+ #Contains the bounding box of a geometry
5
+ class Envelope
6
+ attr_accessor :lower_corner, :upper_corner
7
+ attr_accessor :srid, :with_z, :zoom
8
+
9
+ #Creates a enw Envelope with +lower_corner+ as the first element of the corners array and +upper_corner+ as the second element
10
+ def initialize(srid = @@default_srid, with_z = false)
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.from_points([Point.from_x_y(lower_corner.x,lower_corner.y),
28
+ Point.from_x_y(upper_corner.x,upper_corner.y)],srid,with_z)
29
+ e.extend!(envelope)
30
+ e
31
+ end
32
+ # def bounding_box(markers)
33
+ # max_lat, max_lon, min_lat, min_lon = -Float::MAX, -Float::MAX, Float::MAX, Float::MAX
34
+ # markers.each do |marker|
35
+ # coord = marker.point
36
+ # max_lat = coord.lat if coord.lat > max_lat
37
+ # min_lat = coord.lat if coord.lat < min_lat
38
+ # max_lon = coord.lng if coord.lng > max_lon
39
+ # min_lon = coord.lng if coord.lng < min_lon
40
+ # end
41
+ # min_point = Point.from_x_y(min_lat,min_lon)
42
+ # max_point = Point.from_x_y(max_lat,max_lon)
43
+
44
+ # end
45
+ # centrelat = (max_lat + min_lat)/2
46
+ # centrelng = (max_lon + min_lon)/2
47
+ # # logger.info("distance[#{distance}],zoom[#{zoom}]")
48
+ # #return GLatLngBounds.new(GLatLng.new(min_point),GLatLng.new(max_point)), [centrelat,centrelng], zoom
49
+ # return [centrelat,centrelng], zoom
50
+
51
+ #Sends back the center of the envelope
52
+ def center
53
+ Point.from_x_y((lower_corner.x + upper_corner.x)/2,(lower_corner.y + upper_corner.y)/2)
54
+ end
55
+
56
+ #Zoom level
57
+ def zoom
58
+ distance = lower_corner.spherical_distance(upper_corner)/10000
59
+ @zoom = case distance
60
+ when 150..9000 then 5
61
+ when 80..149 then 6
62
+ when 50..79 then 7
63
+ when 20..49 then 8
64
+ when 10..19 then 9
65
+ when 5..9 then 10
66
+ else 13
67
+ end
68
+ end
69
+
70
+ #Tests the equality of line strings
71
+ def ==(other_envelope)
72
+ if other_envelope.class != self.class
73
+ false
74
+ else
75
+ upper_corner == other_envelope.upper_corner and lower_corner == other_envelope.lower_corner
76
+ end
77
+ end
78
+
79
+ #georss serialization: Dialect can be passed as option <tt>:dialect</tt> and set to <tt>:simple</tt> (default)
80
+ #<tt>:w3cgeo</tt> or <tt>:gml</tt>. Options <tt>:featuretypetag
81
+ def as_georss(options = {})
82
+ dialect= options[:dialect] || :simple
83
+ case(dialect)
84
+ when :simple
85
+ geom_attr = ""
86
+ geom_attr += " featuretypetag=\"#{options[:featuretypetag]}\"" if options[:featuretypetag]
87
+ geom_attr += " relationshiptag=\"#{options[:relationshiptag]}\"" if options[:relationshiptag]
88
+ geom_attr += " floor=\"#{options[:floor]}\"" if options[:floor]
89
+ geom_attr += " radius=\"#{options[:radius]}\"" if options[:radius]
90
+ geom_attr += " elev=\"#{options[:elev]}\"" if options[:elev]
91
+
92
+ georss_simple_representation(options.merge(:geom_attr => geom_attr))
93
+ when :w3cgeo
94
+ georss_w3cgeo_representation(options)
95
+ when :gml
96
+ georss_gml_representation(options)
97
+ end
98
+ end
99
+
100
+ #georss simple representation
101
+ def georss_simple_representation(options = {}) #:nodoc:
102
+ georss_ns = options[:georss_ns] || "georss"
103
+ geom_attr = options[:geom_attr]
104
+ "<#{georss_ns}:box#{geom_attr}>#{lower_corner.y} #{lower_corner.x} #{upper_corner.y} #{upper_corner.x}</#{georss_ns}:box>\n"
105
+ end
106
+
107
+ #georss w3c representation : outputs the first point of the line
108
+ def georss_w3cgeo_representation(options = {}) #:nodoc:
109
+ w3cgeo_ns = options[:w3cgeo_ns] || "geo"
110
+ point = self.center
111
+ "<#{w3cgeo_ns}:lat>#{point.y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{point.x}</#{w3cgeo_ns}:long>\n"
112
+ end
113
+
114
+ #georss gml representation
115
+ def georss_gml_representation(options = {}) #:nodoc:
116
+ georss_ns = options[:georss_ns] || "georss"
117
+ gml_ns = options[:gml_ns] || "gml"
118
+ result = "<#{georss_ns}:where>\n<#{gml_ns}:Envelope>\n"
119
+ result += "<#{gml_ns}:LowerCorner>" + "#{lower_corner.y} #{lower_corner.x}" + "</#{gml_ns}:LowerCorner>"
120
+ result += "<#{gml_ns}:UpperCorner>" + "#{upper_corner.y} #{upper_corner.x}" + "</#{gml_ns}:UpperCorner>"
121
+ result += "</#{gml_ns}:Envelope>\n</#{georss_ns}:where>\n"
122
+ end
123
+
124
+ #Sends back a latlonaltbox
125
+ def as_kml(options = {})
126
+ geom_data = ""
127
+ geom_data = "<altitudeMode>#{options[:altitude_mode]}</altitudeMode>\n" if options[:altitude_mode]
128
+
129
+ allow_z = with_z && (!options[:altitude_mode].nil?) && options[:atitude_mode] != "clampToGround"
130
+
131
+ kml_representation(options.merge(:geom_data => geom_data,:allow_z => allow_z))
132
+ end
133
+
134
+ def kml_representation(options = {})#:nodoc:
135
+ result = "<LatLonAltBox>\n"
136
+ result += options[:geom_data]
137
+ result += "<north>#{upper_corner.y}</north>\n"
138
+ result += "<south>#{lower_corner.y}</south>\n"
139
+ result += "<east>#{upper_corner.x}</east>\n"
140
+ result += "<west>#{lower_corner.x}</west>\n"
141
+
142
+ if with_z
143
+ result += "<minAltitude>#{lower_corner.z}</minAltitude>"
144
+ result += "<maxAltitude>#{upper_corner.z}</maxAltitude>"
145
+ end
146
+
147
+ result += "</LatLonAltBox>\n"
148
+ end
149
+
150
+ #Creates a new envelope. Accept an array of 2 points as argument
151
+ def self.from_points(points,srid=@@default_srid,with_z=false)
152
+ raise "Not an array" unless points.class == Array
153
+ e = Envelope.new(srid,with_z)
154
+ e.lower_corner, e.upper_corner = points
155
+ e
156
+ end
157
+
158
+ #Creates a new envelope. Accept a sequence of point coordinates as argument : ((x,y),(x,y))
159
+ def self.from_coordinates(points,srid=@@default_srid,with_z=false)
160
+ e = Envelope.new(srid,with_z)
161
+ e.lower_corner, e.upper_corner = points.collect{|point_coords| Point.from_coordinates(point_coords,srid,with_z)}
162
+ e
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,216 @@
1
+ require 'geo_ruby/base/point'
2
+ require 'geo_ruby/base/line_string'
3
+ require 'geo_ruby/base/linear_ring'
4
+ require 'geo_ruby/base/polygon'
5
+ require 'geo_ruby/base/multi_point'
6
+ require 'geo_ruby/base/multi_line_string'
7
+ require 'geo_ruby/base/multi_polygon'
8
+ require 'geo_ruby/base/geometry_collection'
9
+
10
+ module GeoRuby
11
+ module Base
12
+
13
+ #Raised when an error in the EWKB string is detected
14
+ class EWKBFormatError < StandardError
15
+ end
16
+
17
+ #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.
18
+ #
19
+ #=Example
20
+ # factory = GeometryFactory::new
21
+ # ewkb_parser = EWKBParser::new(factory)
22
+ # ewkb_parser.parse(<EWKB String>)
23
+ # geometry = @factory.geometry
24
+ #
25
+ #You can also use directly the static method Geometry.from_ewkb
26
+ class EWKBParser
27
+
28
+ def initialize(factory)
29
+ @factory = factory
30
+ @parse_options ={
31
+ 1 => method(:parse_point),
32
+ 2 => method(:parse_line_string),
33
+ 3 => method(:parse_polygon),
34
+ 4 => method(:parse_multi_point),
35
+ 5 => method(:parse_multi_line_string),
36
+ 6 => method(:parse_multi_polygon),
37
+ 7 => method(:parse_geometry_collection)
38
+ }
39
+ end
40
+
41
+ #Parses the ewkb string passed as argument and notifies the factory of events
42
+ def parse(ewkb)
43
+ @factory.reset
44
+ @unpack_structure=UnpackStructure::new(ewkb)
45
+ @with_z = false
46
+ @with_m = false
47
+ parse_geometry
48
+ @unpack_structure.done
49
+ @srid=nil
50
+ end
51
+
52
+ private
53
+ def parse_geometry
54
+ @unpack_structure.endianness=@unpack_structure.read_byte
55
+ @geometry_type = @unpack_structure.read_uint
56
+
57
+ if (@geometry_type & Z_MASK) != 0
58
+ @with_z=true
59
+ @geometry_type = @geometry_type & ~Z_MASK
60
+ end
61
+ if (@geometry_type & M_MASK) != 0
62
+ @with_m=true
63
+ @geometry_type = @geometry_type & ~M_MASK
64
+ end
65
+ if (@geometry_type & SRID_MASK) != 0
66
+ @srid = @unpack_structure.read_uint
67
+ @geometry_type = @geometry_type & ~SRID_MASK
68
+ else
69
+ #to manage multi geometries : the srid is not present in sub_geometries, therefore we take the srid of the parent ; if it is the root, we take the default srid
70
+ @srid= @srid || @@default_srid
71
+ end
72
+
73
+ if @parse_options.has_key? @geometry_type
74
+ @parse_options[@geometry_type].call
75
+ else
76
+ raise EWKBFormatError::new("Unknown geometry type")
77
+ end
78
+ end
79
+
80
+ def parse_geometry_collection
81
+ parse_multi_geometries(GeometryCollection)
82
+ end
83
+
84
+ def parse_multi_polygon
85
+ parse_multi_geometries(MultiPolygon)
86
+ end
87
+
88
+ def parse_multi_line_string
89
+ parse_multi_geometries(MultiLineString)
90
+ end
91
+
92
+ def parse_multi_point
93
+ parse_multi_geometries(MultiPoint)
94
+ end
95
+
96
+ def parse_multi_geometries(geometry_type)
97
+ @factory.begin_geometry(geometry_type,@srid)
98
+ num_geometries = @unpack_structure.read_uint
99
+ 1.upto(num_geometries) { parse_geometry }
100
+ @factory.end_geometry(@with_z,@with_m)
101
+ end
102
+
103
+ def parse_polygon
104
+ @factory.begin_geometry(Polygon,@srid)
105
+ num_linear_rings = @unpack_structure.read_uint
106
+ 1.upto(num_linear_rings) {parse_linear_ring}
107
+ @factory.end_geometry(@with_z,@with_m)
108
+ end
109
+
110
+ def parse_linear_ring
111
+ parse_point_list(LinearRing)
112
+ end
113
+
114
+ def parse_line_string
115
+ parse_point_list(LineString)
116
+ end
117
+
118
+ #used to parse line_strings and linear_rings
119
+ def parse_point_list(geometry_type)
120
+ @factory.begin_geometry(geometry_type,@srid)
121
+ num_points = @unpack_structure.read_uint
122
+ 1.upto(num_points) {parse_point}
123
+ @factory.end_geometry(@with_z,@with_m)
124
+ end
125
+
126
+ def parse_point
127
+ @factory.begin_geometry(Point,@srid)
128
+ x = @unpack_structure.read_double
129
+ y = @unpack_structure.read_double
130
+ if ! (@with_z or @with_m) #most common case probably
131
+ @factory.add_point_x_y(x,y)
132
+ elsif @with_m and @with_z
133
+ z = @unpack_structure.read_double
134
+ m = @unpack_structure.read_double
135
+ @factory.add_point_x_y_z_m(x,y,z,m)
136
+ elsif @with_z
137
+ z = @unpack_structure.read_double
138
+ @factory.add_point_x_y_z(x,y,z)
139
+ else
140
+ m = @unpack_structure.read_double
141
+ @factory.add_point_x_y_m(x,y,m)
142
+ end
143
+
144
+ @factory.end_geometry(@with_z,@with_m)
145
+ end
146
+ end
147
+
148
+ #Parses HexEWKB strings. In reality, it just transforms the HexEWKB string into the equivalent EWKB string and lets the EWKBParser do the actual parsing.
149
+ class HexEWKBParser < EWKBParser
150
+ def initialize(factory)
151
+ super(factory)
152
+ end
153
+ #parses an HexEWKB string
154
+ def parse(hexewkb)
155
+ super(decode_hex(hexewkb))
156
+ end
157
+ #transforms a HexEWKB string into an EWKB string
158
+ def decode_hex(hexewkb)
159
+ result=""
160
+ num_bytes = (hexewkb.size + 1) / 2
161
+ 0.upto(num_bytes-1) do |i|
162
+ result << hexewkb[i*2,2].hex
163
+ end
164
+ result
165
+ end
166
+ end
167
+
168
+ class HexEWKBParser < EWKBParser
169
+ #transforms a HexEWKB string into an EWKB string
170
+ # Patched for speedup
171
+
172
+ end
173
+
174
+ class UnpackStructure #:nodoc:
175
+ NDR=1
176
+ XDR=0
177
+ def initialize(ewkb)
178
+ @position=0
179
+ @ewkb=ewkb
180
+ end
181
+ def done
182
+ raise EWKBFormatError::new("Trailing data") if @position != @ewkb.length
183
+ end
184
+ def read_double
185
+ i=@position
186
+ @position += 8
187
+ packed_double = @ewkb[i...@position]
188
+ raise EWKBFormatError::new("Truncated data") if packed_double.nil? or packed_double.length < 8
189
+ packed_double.unpack(@double_mark)[0]
190
+ end
191
+ def read_uint
192
+ i=@position
193
+ @position += 4
194
+ packed_uint = @ewkb[i...@position]
195
+ raise EWKBFormatError::new("Truncated data") if packed_uint.nil? or packed_uint.length < 4
196
+ packed_uint.unpack(@uint_mark)[0]
197
+ end
198
+ def read_byte
199
+ i = @position
200
+ @position += 1
201
+ packed_byte = @ewkb[i...@position]
202
+ raise EWKBFormatError::new("Truncated data") if packed_byte.nil? or packed_byte.length < 1
203
+ packed_byte.unpack("C")[0]
204
+ end
205
+ def endianness=(byte_order)
206
+ if(byte_order == NDR)
207
+ @uint_mark="V"
208
+ @double_mark="E"
209
+ elsif(byte_order == XDR)
210
+ @uint_mark="N"
211
+ @double_mark="G"
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end