nofxx-georuby 1.3.7

Sign up to get free protection for your applications and to get access to all the features.
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