rgeo 1.1.2 → 2.0.0
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.
- checksums.yaml +4 -4
- data/ext/geos_c_impl/extconf.rb +5 -3
- data/ext/geos_c_impl/factory.c +4 -4
- data/ext/geos_c_impl/geometry.c +1 -1
- data/lib/rgeo.rb +2 -4
- data/lib/rgeo/cartesian.rb +6 -16
- data/lib/rgeo/cartesian/analysis.rb +22 -20
- data/lib/rgeo/cartesian/bounding_box.rb +83 -79
- data/lib/rgeo/cartesian/calculations.rb +40 -38
- data/lib/rgeo/cartesian/factory.rb +134 -169
- data/lib/rgeo/cartesian/feature_classes.rb +2 -18
- data/lib/rgeo/cartesian/feature_methods.rb +37 -39
- data/lib/rgeo/cartesian/interface.rb +11 -9
- data/lib/rgeo/coord_sys.rb +9 -8
- data/lib/rgeo/coord_sys/cs/entities.rb +345 -303
- data/lib/rgeo/coord_sys/cs/factories.rb +30 -28
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +128 -126
- data/lib/rgeo/coord_sys/srs_database/{interface.rb → entry.rb} +26 -32
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +19 -17
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +21 -19
- data/lib/rgeo/error.rb +3 -1
- data/lib/rgeo/feature.rb +23 -34
- data/lib/rgeo/feature/curve.rb +2 -0
- data/lib/rgeo/feature/factory.rb +15 -13
- data/lib/rgeo/feature/factory_generator.rb +7 -5
- data/lib/rgeo/feature/geometry.rb +31 -29
- data/lib/rgeo/feature/geometry_collection.rb +6 -4
- data/lib/rgeo/feature/line.rb +2 -0
- data/lib/rgeo/feature/line_string.rb +3 -1
- data/lib/rgeo/feature/linear_ring.rb +2 -0
- data/lib/rgeo/feature/multi_curve.rb +2 -0
- data/lib/rgeo/feature/multi_line_string.rb +2 -0
- data/lib/rgeo/feature/multi_point.rb +2 -0
- data/lib/rgeo/feature/multi_polygon.rb +2 -0
- data/lib/rgeo/feature/multi_surface.rb +2 -0
- data/lib/rgeo/feature/point.rb +2 -0
- data/lib/rgeo/feature/polygon.rb +3 -1
- data/lib/rgeo/feature/surface.rb +2 -0
- data/lib/rgeo/feature/types.rb +107 -103
- data/lib/rgeo/geographic.rb +17 -27
- data/lib/rgeo/geographic/factory.rb +154 -199
- data/lib/rgeo/geographic/interface.rb +141 -137
- data/lib/rgeo/geographic/proj4_projector.rb +28 -23
- data/lib/rgeo/geographic/projected_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/projected_feature_methods.rb +59 -49
- data/lib/rgeo/geographic/projected_window.rb +4 -2
- data/lib/rgeo/geographic/simple_mercator_projector.rb +41 -39
- data/lib/rgeo/geographic/spherical_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/spherical_feature_methods.rb +67 -67
- data/lib/rgeo/geographic/spherical_math.rb +81 -87
- data/lib/rgeo/geos.rb +23 -34
- data/lib/rgeo/geos/capi_factory.rb +106 -135
- data/lib/rgeo/geos/capi_feature_classes.rb +19 -37
- data/lib/rgeo/geos/ffi_factory.rb +276 -297
- data/lib/rgeo/geos/ffi_feature_classes.rb +2 -20
- data/lib/rgeo/geos/ffi_feature_methods.rb +170 -166
- data/lib/rgeo/geos/interface.rb +25 -23
- data/lib/rgeo/geos/utils.rb +47 -39
- data/lib/rgeo/geos/zm_factory.rb +171 -185
- data/lib/rgeo/geos/zm_feature_classes.rb +2 -20
- data/lib/rgeo/geos/zm_feature_methods.rb +76 -72
- data/lib/rgeo/impl_helper.rb +1 -11
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +72 -75
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +21 -23
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +57 -49
- data/lib/rgeo/impl_helper/basic_point_methods.rb +29 -25
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +31 -27
- data/lib/rgeo/impl_helper/math.rb +2 -0
- data/lib/rgeo/impl_helper/utils.rb +9 -15
- data/lib/rgeo/version.rb +3 -1
- data/lib/rgeo/wkrep.rb +20 -30
- data/lib/rgeo/wkrep/wkb_generator.rb +87 -84
- data/lib/rgeo/wkrep/wkb_parser.rb +93 -93
- data/lib/rgeo/wkrep/wkt_generator.rb +67 -63
- data/lib/rgeo/wkrep/wkt_parser.rb +172 -168
- metadata +17 -32
- data/lib/rgeo/feature/mixins.rb +0 -143
data/lib/rgeo/version.rb
CHANGED
data/lib/rgeo/wkrep.rb
CHANGED
@@ -1,36 +1,26 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The WKRep module contains implementations of the OpenGIS well-known
|
4
|
+
# representations: the WKT (well-known text representation) and the
|
5
|
+
# WKB (well-known binary representation), as defined in the Simple
|
6
|
+
# Features Specification, version 1.1. Facilities are provided to
|
7
|
+
# serialize any geometry into one of these formats, and to parse a
|
8
|
+
# serialized string back into a geometry. Support is also provided for
|
9
|
+
# the common extensions to these formats-- notably, the EWKT and EWKB
|
10
|
+
# formats used by PostGIS.
|
2
11
|
#
|
3
|
-
#
|
12
|
+
# To serialize a geometry into WKT (well-known text) format, use
|
13
|
+
# the WKRep::WKTGenerator class.
|
4
14
|
#
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# serialized string back into a geometry. Support is also provided for
|
14
|
-
# the common extensions to these formats-- notably, the EWKT and EWKB
|
15
|
-
# formats used by PostGIS.
|
16
|
-
#
|
17
|
-
# To serialize a geometry into WKT (well-known text) format, use
|
18
|
-
# the WKRep::WKTGenerator class.
|
19
|
-
#
|
20
|
-
# To serialize a geometry into WKB (well-known binary) format, use
|
21
|
-
# the WKRep::WKBGenerator class.
|
22
|
-
#
|
23
|
-
# To parse a string in WKT (well-known text) format back into a
|
24
|
-
# geometry object, use the WKRep::WKTParser class.
|
25
|
-
#
|
26
|
-
# To parse a byte string in WKB (well-known binary) format back into a
|
27
|
-
# geometry object, use the WKRep::WKBParser class.
|
28
|
-
|
29
|
-
module WKRep
|
30
|
-
end
|
31
|
-
end
|
15
|
+
# To serialize a geometry into WKB (well-known binary) format, use
|
16
|
+
# the WKRep::WKBGenerator class.
|
17
|
+
#
|
18
|
+
# To parse a string in WKT (well-known text) format back into a
|
19
|
+
# geometry object, use the WKRep::WKTParser class.
|
20
|
+
#
|
21
|
+
# To parse a byte string in WKB (well-known binary) format back into a
|
22
|
+
# geometry object, use the WKRep::WKBParser class.
|
32
23
|
|
33
|
-
# Implementation files
|
34
24
|
require "rgeo/wkrep/wkt_parser"
|
35
25
|
require "rgeo/wkrep/wkt_generator"
|
36
26
|
require "rgeo/wkrep/wkb_parser"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# Well-known binary generator for RGeo
|
@@ -56,12 +58,11 @@ module RGeo
|
|
56
58
|
# Create and configure a WKB generator. See the WKBGenerator
|
57
59
|
# documentation for the options that can be passed.
|
58
60
|
|
59
|
-
def initialize(
|
60
|
-
@type_format =
|
61
|
-
@emit_ewkb_srid = @type_format == :ewkb
|
62
|
-
|
63
|
-
@
|
64
|
-
@little_endian = opts_[:little_endian] ? true : false
|
61
|
+
def initialize(opts = {})
|
62
|
+
@type_format = opts[:type_format] || :wkb11
|
63
|
+
@emit_ewkb_srid = @type_format == :ewkb && opts[:emit_ewkb_srid]
|
64
|
+
@hex_format = opts[:hex_format] ? true : false
|
65
|
+
@little_endian = opts[:little_endian] ? true : false
|
65
66
|
end
|
66
67
|
|
67
68
|
# Returns the format for type codes. See WKBGenerator for details.
|
@@ -84,7 +85,7 @@ module RGeo
|
|
84
85
|
@little_endian
|
85
86
|
end
|
86
87
|
|
87
|
-
def
|
88
|
+
def properties
|
88
89
|
{
|
89
90
|
"type_format" => @type_format.to_s,
|
90
91
|
"emit_ewkb_srid" => @emit_ewkb_srid,
|
@@ -96,105 +97,107 @@ module RGeo
|
|
96
97
|
# Generate and return the WKB format for the given geometry object,
|
97
98
|
# according to the current settings.
|
98
99
|
|
99
|
-
def generate(
|
100
|
-
|
100
|
+
def generate(obj)
|
101
|
+
factory = obj.factory
|
101
102
|
if @type_format == :ewkb || @type_format == :wkb12
|
102
|
-
@cur_has_z =
|
103
|
-
@cur_has_m =
|
103
|
+
@cur_has_z = factory.property(:has_z_coordinate)
|
104
|
+
@cur_has_m = factory.property(:has_m_coordinate)
|
104
105
|
else
|
105
106
|
@cur_has_z = nil
|
106
107
|
@cur_has_m = nil
|
107
108
|
end
|
108
109
|
@cur_dims = 2 + (@cur_has_z ? 1 : 0) + (@cur_has_m ? 1 : 0)
|
109
|
-
|
110
|
-
|
111
|
-
|
110
|
+
start_emitter
|
111
|
+
generate_feature(obj, true)
|
112
|
+
finish_emitter
|
112
113
|
end
|
113
114
|
|
114
|
-
|
115
|
-
_emit_byte(@little_endian ? 1 : 0)
|
116
|
-
type_ = obj_.geometry_type
|
117
|
-
type_code_ = TYPE_CODES[type_]
|
118
|
-
unless type_code_
|
119
|
-
raise Error::ParseError, "Unrecognized Geometry Type: #{type_}"
|
120
|
-
end
|
121
|
-
emit_srid_ = false
|
122
|
-
if @type_format == :ewkb
|
123
|
-
type_code_ |= 0x80000000 if @cur_has_z
|
124
|
-
type_code_ |= 0x40000000 if @cur_has_m
|
125
|
-
if @emit_ewkb_srid && toplevel_
|
126
|
-
type_code_ |= 0x20000000
|
127
|
-
emit_srid_ = true
|
128
|
-
end
|
129
|
-
elsif @type_format == :wkb12
|
130
|
-
type_code_ += 1000 if @cur_has_z
|
131
|
-
type_code_ += 2000 if @cur_has_m
|
132
|
-
end
|
133
|
-
_emit_integer(type_code_)
|
134
|
-
_emit_integer(obj_.srid) if emit_srid_
|
135
|
-
if type_ == Feature::Point
|
136
|
-
_emit_doubles(_point_coords(obj_))
|
137
|
-
elsif type_.subtype_of?(Feature::LineString)
|
138
|
-
_emit_line_string_coords(obj_)
|
139
|
-
elsif type_ == Feature::Polygon
|
140
|
-
exterior_ring_ = obj_.exterior_ring
|
141
|
-
if exterior_ring_.is_empty?
|
142
|
-
_emit_integer(0)
|
143
|
-
else
|
144
|
-
_emit_integer(1 + obj_.num_interior_rings)
|
145
|
-
_emit_line_string_coords(exterior_ring_)
|
146
|
-
obj_.interior_rings.each { |r_| _emit_line_string_coords(r_) }
|
147
|
-
end
|
148
|
-
elsif type_ == Feature::GeometryCollection
|
149
|
-
_emit_integer(obj_.num_geometries)
|
150
|
-
obj_.each { |g_| _generate_feature(g_) }
|
151
|
-
elsif type_ == Feature::MultiPoint
|
152
|
-
_emit_integer(obj_.num_geometries)
|
153
|
-
obj_.each { |g_| _generate_feature(g_) }
|
154
|
-
elsif type_ == Feature::MultiLineString
|
155
|
-
_emit_integer(obj_.num_geometries)
|
156
|
-
obj_.each { |g_| _generate_feature(g_) }
|
157
|
-
elsif type_ == Feature::MultiPolygon
|
158
|
-
_emit_integer(obj_.num_geometries)
|
159
|
-
obj_.each { |g_| _generate_feature(g_) }
|
160
|
-
end
|
161
|
-
end
|
115
|
+
private
|
162
116
|
|
163
|
-
def
|
164
|
-
|
165
|
-
array_ << obj_.y
|
166
|
-
array_ << obj_.z if @cur_has_z
|
167
|
-
array_ << obj_.m if @cur_has_m
|
168
|
-
array_
|
117
|
+
def emit_byte(value)
|
118
|
+
@cur_array << [value].pack("C")
|
169
119
|
end
|
170
120
|
|
171
|
-
def
|
172
|
-
|
173
|
-
obj_.points.each { |p_| _point_coords(p_, array_) }
|
174
|
-
_emit_integer(obj_.num_points)
|
175
|
-
_emit_doubles(array_)
|
121
|
+
def emit_integer(value)
|
122
|
+
@cur_array << [value].pack(@little_endian ? "V" : "N")
|
176
123
|
end
|
177
124
|
|
178
|
-
def
|
179
|
-
@cur_array
|
125
|
+
def emit_doubles(array)
|
126
|
+
@cur_array << array.pack(@little_endian ? "E*" : "G*")
|
180
127
|
end
|
181
128
|
|
182
|
-
def
|
183
|
-
|
129
|
+
def emit_line_string_coords(obj)
|
130
|
+
array = []
|
131
|
+
obj.points.each { |p| point_coords(p, array) }
|
132
|
+
emit_integer(obj.num_points)
|
133
|
+
emit_doubles(array)
|
184
134
|
end
|
185
135
|
|
186
|
-
def
|
187
|
-
|
136
|
+
def point_coords(obj, array = [])
|
137
|
+
array << obj.x
|
138
|
+
array << obj.y
|
139
|
+
array << obj.z if @cur_has_z
|
140
|
+
array << obj.m if @cur_has_m
|
141
|
+
array
|
188
142
|
end
|
189
143
|
|
190
|
-
def
|
191
|
-
@cur_array
|
144
|
+
def start_emitter
|
145
|
+
@cur_array = []
|
192
146
|
end
|
193
147
|
|
194
|
-
def
|
195
|
-
|
148
|
+
def finish_emitter
|
149
|
+
str = @cur_array.join
|
196
150
|
@cur_array = nil
|
197
|
-
@hex_format ?
|
151
|
+
@hex_format ? str.unpack("H*")[0] : str
|
152
|
+
end
|
153
|
+
|
154
|
+
def generate_feature(obj, toplevel = false)
|
155
|
+
emit_byte(@little_endian ? 1 : 0)
|
156
|
+
type = obj.geometry_type
|
157
|
+
type_code = TYPE_CODES[type]
|
158
|
+
unless type_code
|
159
|
+
raise Error::ParseError, "Unrecognized Geometry Type: #{type}"
|
160
|
+
end
|
161
|
+
emit_srid = false
|
162
|
+
if @type_format == :ewkb
|
163
|
+
type_code |= 0x80000000 if @cur_has_z
|
164
|
+
type_code |= 0x40000000 if @cur_has_m
|
165
|
+
if @emit_ewkb_srid && toplevel
|
166
|
+
type_code |= 0x20000000
|
167
|
+
emit_srid = true
|
168
|
+
end
|
169
|
+
elsif @type_format == :wkb12
|
170
|
+
type_code += 1000 if @cur_has_z
|
171
|
+
type_code += 2000 if @cur_has_m
|
172
|
+
end
|
173
|
+
emit_integer(type_code)
|
174
|
+
emit_integer(obj.srid) if emit_srid
|
175
|
+
if type == Feature::Point
|
176
|
+
emit_doubles(point_coords(obj))
|
177
|
+
elsif type.subtype_of?(Feature::LineString)
|
178
|
+
emit_line_string_coords(obj)
|
179
|
+
elsif type == Feature::Polygon
|
180
|
+
exterior_ring = obj.exterior_ring
|
181
|
+
if exterior_ring.is_empty?
|
182
|
+
emit_integer(0)
|
183
|
+
else
|
184
|
+
emit_integer(1 + obj.num_interior_rings)
|
185
|
+
emit_line_string_coords(exterior_ring)
|
186
|
+
obj.interior_rings.each { |r| emit_line_string_coords(r) }
|
187
|
+
end
|
188
|
+
elsif type == Feature::GeometryCollection
|
189
|
+
emit_integer(obj.num_geometries)
|
190
|
+
obj.each { |g| generate_feature(g) }
|
191
|
+
elsif type == Feature::MultiPoint
|
192
|
+
emit_integer(obj.num_geometries)
|
193
|
+
obj.each { |g| generate_feature(g) }
|
194
|
+
elsif type == Feature::MultiLineString
|
195
|
+
emit_integer(obj.num_geometries)
|
196
|
+
obj.each { |g| generate_feature(g) }
|
197
|
+
elsif type == Feature::MultiPolygon
|
198
|
+
emit_integer(obj.num_geometries)
|
199
|
+
obj.each { |g| generate_feature(g) }
|
200
|
+
end
|
198
201
|
end
|
199
202
|
end
|
200
203
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# Well-known binary parser for RGeo
|
@@ -45,21 +47,21 @@ module RGeo
|
|
45
47
|
# Create and configure a WKB parser. See the WKBParser
|
46
48
|
# documentation for the options that can be passed.
|
47
49
|
|
48
|
-
def initialize(
|
49
|
-
if
|
50
|
-
@factory_generator = Feature::FactoryGenerator.single(
|
51
|
-
@exact_factory =
|
52
|
-
elsif
|
53
|
-
@factory_generator =
|
50
|
+
def initialize(factory_generator = nil, opts = {})
|
51
|
+
if factory_generator.is_a?(Feature::Factory::Instance)
|
52
|
+
@factory_generator = Feature::FactoryGenerator.single(factory_generator)
|
53
|
+
@exact_factory = factory_generator
|
54
|
+
elsif factory_generator.respond_to?(:call)
|
55
|
+
@factory_generator = factory_generator
|
54
56
|
@exact_factory = nil
|
55
57
|
else
|
56
58
|
@factory_generator = Cartesian.method(:preferred_factory)
|
57
59
|
@exact_factory = nil
|
58
60
|
end
|
59
|
-
@support_ewkb =
|
60
|
-
@support_wkb12 =
|
61
|
-
@ignore_extra_bytes =
|
62
|
-
@default_srid =
|
61
|
+
@support_ewkb = opts[:support_ewkb] ? true : false
|
62
|
+
@support_wkb12 = opts[:support_wkb12] ? true : false
|
63
|
+
@ignore_extra_bytes = opts[:ignore_extra_bytes] ? true : false
|
64
|
+
@default_srid = opts[:default_srid]
|
63
65
|
end
|
64
66
|
|
65
67
|
# Returns the factory generator. See WKBParser for details.
|
@@ -87,7 +89,7 @@ module RGeo
|
|
87
89
|
@ignore_extra_bytes
|
88
90
|
end
|
89
91
|
|
90
|
-
def
|
92
|
+
def properties
|
91
93
|
{
|
92
94
|
"support_ewkb" => @support_ewkb,
|
93
95
|
"support_wkb12" => @support_wkb12,
|
@@ -102,73 +104,75 @@ module RGeo
|
|
102
104
|
# The #parse_hex method is a synonym, present for historical
|
103
105
|
# reasons but deprecated. Use #parse instead.
|
104
106
|
|
105
|
-
def parse(
|
106
|
-
|
107
|
+
def parse(data)
|
108
|
+
data = [data].pack("H*") if data[0, 1] =~ /[0-9a-fA-F]/
|
107
109
|
@cur_has_z = nil
|
108
110
|
@cur_has_m = nil
|
109
111
|
@cur_srid = nil
|
110
112
|
@cur_dims = 2
|
111
113
|
@cur_factory = nil
|
112
114
|
begin
|
113
|
-
|
114
|
-
|
115
|
+
start_scanner(data)
|
116
|
+
obj = parse_object(false)
|
115
117
|
unless @ignore_extra_bytes
|
116
|
-
|
117
|
-
if
|
118
|
-
raise Error::ParseError, "Found #{
|
118
|
+
bytes = bytes_remaining
|
119
|
+
if bytes > 0
|
120
|
+
raise Error::ParseError, "Found #{bytes} extra bytes at the end of the stream."
|
119
121
|
end
|
120
122
|
end
|
121
123
|
ensure
|
122
|
-
|
124
|
+
@data = nil
|
123
125
|
end
|
124
|
-
|
126
|
+
obj
|
125
127
|
end
|
126
128
|
alias parse_hex parse
|
127
129
|
|
128
|
-
|
129
|
-
|
130
|
-
|
130
|
+
private
|
131
|
+
|
132
|
+
def parse_object(contained)
|
133
|
+
endian_value = get_byte
|
134
|
+
case endian_value
|
131
135
|
when 0
|
132
|
-
|
136
|
+
little_endian = false
|
133
137
|
when 1
|
134
|
-
|
138
|
+
little_endian = true
|
135
139
|
else
|
136
|
-
raise Error::ParseError, "Bad endian byte value: #{
|
140
|
+
raise Error::ParseError, "Bad endian byte value: #{endian_value}"
|
137
141
|
end
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
+
type_code = get_integer(little_endian)
|
143
|
+
has_z = false
|
144
|
+
has_m = false
|
145
|
+
srid = contained ? nil : @default_srid
|
142
146
|
if @support_ewkb
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
+
has_z ||= type_code & 0x80000000 != 0
|
148
|
+
has_m ||= type_code & 0x40000000 != 0
|
149
|
+
srid = get_integer(little_endian) if type_code & 0x20000000 != 0
|
150
|
+
type_code &= 0x0fffffff
|
147
151
|
end
|
148
152
|
if @support_wkb12
|
149
|
-
|
150
|
-
|
151
|
-
|
153
|
+
has_z ||= (type_code / 1000) & 1 != 0
|
154
|
+
has_m ||= (type_code / 1000) & 2 != 0
|
155
|
+
type_code %= 1000
|
152
156
|
end
|
153
|
-
if
|
154
|
-
if
|
155
|
-
raise Error::ParseError, "Enclosed type=#{
|
157
|
+
if contained
|
158
|
+
if contained != true && contained != type_code
|
159
|
+
raise Error::ParseError, "Enclosed type=#{type_code} is different from container constraint #{contained}"
|
156
160
|
end
|
157
|
-
if
|
158
|
-
raise Error::ParseError, "Enclosed hasZ=#{
|
161
|
+
if has_z != @cur_has_z
|
162
|
+
raise Error::ParseError, "Enclosed hasZ=#{has_z} is different from toplevel hasZ=#{@cur_has_z}"
|
159
163
|
end
|
160
|
-
if
|
161
|
-
raise Error::ParseError, "Enclosed hasM=#{
|
164
|
+
if has_m != @cur_has_m
|
165
|
+
raise Error::ParseError, "Enclosed hasM=#{has_m} is different from toplevel hasM=#{@cur_has_m}"
|
162
166
|
end
|
163
|
-
if
|
164
|
-
raise Error::ParseError, "Enclosed SRID #{
|
167
|
+
if srid && srid != @cur_srid
|
168
|
+
raise Error::ParseError, "Enclosed SRID #{srid} is different from toplevel srid #{@cur_srid || '(unspecified)'}"
|
165
169
|
end
|
166
170
|
else
|
167
|
-
@cur_has_z =
|
168
|
-
@cur_has_m =
|
171
|
+
@cur_has_z = has_z
|
172
|
+
@cur_has_m = has_m
|
169
173
|
@cur_dims = 2 + (@cur_has_z ? 1 : 0) + (@cur_has_m ? 1 : 0)
|
170
|
-
@cur_srid =
|
171
|
-
@cur_factory = @factory_generator.call(srid: @cur_srid, has_z_coordinate:
|
174
|
+
@cur_srid = srid
|
175
|
+
@cur_factory = @factory_generator.call(srid: @cur_srid, has_z_coordinate: has_z, has_m_coordinate: has_m)
|
172
176
|
if @cur_has_z && !@cur_factory.property(:has_z_coordinate)
|
173
177
|
raise Error::ParseError, "Data has Z coordinates but the factory doesn't have Z coordinates"
|
174
178
|
end
|
@@ -176,75 +180,71 @@ module RGeo
|
|
176
180
|
raise Error::ParseError, "Data has M coordinates but the factory doesn't have M coordinates"
|
177
181
|
end
|
178
182
|
end
|
179
|
-
case
|
183
|
+
case type_code
|
180
184
|
when 1
|
181
|
-
|
182
|
-
@cur_factory.point(*
|
185
|
+
coords = get_doubles(little_endian, @cur_dims)
|
186
|
+
@cur_factory.point(*coords)
|
183
187
|
when 2
|
184
|
-
|
188
|
+
parse_line_string(little_endian)
|
185
189
|
when 3
|
186
|
-
|
187
|
-
|
188
|
-
@cur_factory.polygon(
|
190
|
+
interior_rings = (1..get_integer(little_endian)).map { parse_line_string(little_endian) }
|
191
|
+
exterior_ring = interior_rings.shift || @cur_factory.linear_ring([])
|
192
|
+
@cur_factory.polygon(exterior_ring, interior_rings)
|
189
193
|
when 4
|
190
|
-
@cur_factory.multi_point((1..
|
194
|
+
@cur_factory.multi_point((1..get_integer(little_endian)).map { parse_object(1) })
|
191
195
|
when 5
|
192
|
-
@cur_factory.multi_line_string((1..
|
196
|
+
@cur_factory.multi_line_string((1..get_integer(little_endian)).map { parse_object(2) })
|
193
197
|
when 6
|
194
|
-
@cur_factory.multi_polygon((1..
|
198
|
+
@cur_factory.multi_polygon((1..get_integer(little_endian)).map { parse_object(3) })
|
195
199
|
when 7
|
196
|
-
@cur_factory.collection((1..
|
200
|
+
@cur_factory.collection((1..get_integer(little_endian)).map { parse_object(true) })
|
197
201
|
else
|
198
|
-
raise Error::ParseError, "Unknown type value: #{
|
202
|
+
raise Error::ParseError, "Unknown type value: #{type_code}."
|
199
203
|
end
|
200
204
|
end
|
201
205
|
|
202
|
-
def
|
203
|
-
|
204
|
-
|
205
|
-
@cur_factory.line_string((0...
|
206
|
-
end
|
207
|
-
|
208
|
-
def _start_scanner(data_) # :nodoc:
|
209
|
-
@_data = data_
|
210
|
-
@_len = data_.length
|
211
|
-
@_pos = 0
|
206
|
+
def parse_line_string(little_endian)
|
207
|
+
count = get_integer(little_endian)
|
208
|
+
coords = get_doubles(little_endian, @cur_dims * count)
|
209
|
+
@cur_factory.line_string((0...count).map { |i| @cur_factory.point(*coords[@cur_dims * i, @cur_dims]) })
|
212
210
|
end
|
213
211
|
|
214
|
-
def
|
215
|
-
@
|
212
|
+
def start_scanner(data)
|
213
|
+
@data = data
|
214
|
+
@len = data.length
|
215
|
+
@pos = 0
|
216
216
|
end
|
217
217
|
|
218
|
-
def
|
219
|
-
@
|
218
|
+
def bytes_remaining
|
219
|
+
@len - @pos
|
220
220
|
end
|
221
221
|
|
222
|
-
def
|
223
|
-
if @
|
222
|
+
def get_byte
|
223
|
+
if @pos + 1 > @len
|
224
224
|
raise Error::ParseError, "Not enough bytes left to fulfill 1 byte"
|
225
225
|
end
|
226
|
-
|
227
|
-
@
|
228
|
-
|
226
|
+
str = @data[@pos, 1]
|
227
|
+
@pos += 1
|
228
|
+
str.unpack("C").first
|
229
229
|
end
|
230
230
|
|
231
|
-
def
|
232
|
-
if @
|
231
|
+
def get_integer(little_endian)
|
232
|
+
if @pos + 4 > @len
|
233
233
|
raise Error::ParseError, "Not enough bytes left to fulfill 1 integer"
|
234
234
|
end
|
235
|
-
|
236
|
-
@
|
237
|
-
|
235
|
+
str = @data[@pos, 4]
|
236
|
+
@pos += 4
|
237
|
+
str.unpack(little_endian ? "V" : "N").first
|
238
238
|
end
|
239
239
|
|
240
|
-
def
|
241
|
-
|
242
|
-
if @
|
243
|
-
raise Error::ParseError, "Not enough bytes left to fulfill #{
|
240
|
+
def get_doubles(little_endian, count)
|
241
|
+
len = 8 * count
|
242
|
+
if @pos + len > @len
|
243
|
+
raise Error::ParseError, "Not enough bytes left to fulfill #{count} doubles"
|
244
244
|
end
|
245
|
-
|
246
|
-
@
|
247
|
-
|
245
|
+
str = @data[@pos, len]
|
246
|
+
@pos += len
|
247
|
+
str.unpack("#{little_endian ? 'E' : 'G'}*")
|
248
248
|
end
|
249
249
|
end
|
250
250
|
end
|