Class: RGeo::WKRep::WKBGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/rgeo/wkrep/wkb_generator.rb

Overview

This class provides the functionality of serializing a geometry as WKB (well-known binary) format. You may also customize the serializer to generate PostGIS EWKB extensions to the output, or to follow the Simple Features Specification 1.2 extensions for Z and M coordinates.

To use this class, create an instance with the desired settings and customizations, and call the generate method.

Configuration options

The following options are recognized. These can be passed to the constructor, or set on the object afterwards.

:type_format

The format for type codes. Possible values are :wkb11, indicating SFS 1.1 WKB (i.e. no Z or M values); :ewkb, indicating the PostGIS EWKB extensions (i.e. Z and M presence flagged by the two high bits of the type code, and support for embedded SRID); or :wkb12 (indicating SFS 1.2 WKB (i.e. Z and M presence flagged by adding 1000 and/or 2000 to the type code.) Default is :wkb11.

:emit_ewkb_srid

If true, embed the SRID in the toplevel geometry. Available only if :type_format is :ewkb. Default is false.

:hex_format

If true, output a hex string instead of a byte string. Default is false.

:little_endian

If true, output little endian (NDR) byte order. If false, output big endian (XDR), or network byte order. Default is false.

Constant Summary collapse

TYPE_CODES =

:stopdoc:

{
  Feature::Point => 1,
  Feature::LineString => 2,
  Feature::LinearRing => 2,
  Feature::Line => 2,
  Feature::Polygon => 3,
  Feature::MultiPoint => 4,
  Feature::MultiLineString => 5,
  Feature::MultiPolygon => 6,
  Feature::GeometryCollection => 7,
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(opts_ = {}) ⇒ WKBGenerator

Create and configure a WKB generator. See the WKBGenerator documentation for the options that can be passed.


95
96
97
98
99
100
101
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 95

def initialize(opts_={})
  @type_format = opts_[:type_format] || :wkb11
  @emit_ewkb_srid = @type_format == :ewkb ?
    (opts_[:emit_ewkb_srid] ? true : false) : nil
  @hex_format = opts_[:hex_format] ? true : false
  @little_endian = opts_[:little_endian] ? true : false
end

Instance Method Details

#_emit_byte(value_) ⇒ Object

:nodoc:


228
229
230
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 228

def _emit_byte(value_)  # :nodoc:
  @cur_array << [value_].pack("C")
end

#_emit_doubles(array_) ⇒ Object

:nodoc:


238
239
240
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 238

def _emit_doubles(array_)  # :nodoc:
  @cur_array << array_.pack(@little_endian ? 'E*' : 'G*')
end

#_emit_integer(value_) ⇒ Object

:nodoc:


233
234
235
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 233

def _emit_integer(value_)  # :nodoc:
  @cur_array << [value_].pack(@little_endian ? 'V' : 'N')
end

#_emit_line_string_coords(obj_) ⇒ Object

:nodoc:


215
216
217
218
219
220
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 215

def _emit_line_string_coords(obj_)  # :nodoc:
  array_ = []
  obj_.points.each{ |p_| _point_coords(p_, array_) }
  _emit_integer(obj_.num_points)
  _emit_doubles(array_)
end

#_finish_emitterObject

:nodoc:


243
244
245
246
247
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 243

def _finish_emitter  # :nodoc:
  str_ = @cur_array.join
  @cur_array = nil
  @hex_format ? str_.unpack("H*")[0] : str_
end

#_generate_feature(obj_, toplevel_ = false) ⇒ Object

:nodoc:


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 156

def _generate_feature(obj_, toplevel_=false)  # :nodoc:
  _emit_byte(@little_endian ? 1 : 0)
  type_ = obj_.geometry_type
  type_code_ = TYPE_CODES[type_]
  unless type_code_
    raise Error::ParseError, "Unrecognized Geometry Type: #{type_}"
  end
  emit_srid_ = false
  if @type_format == :ewkb
    type_code_ |= 0x80000000 if @cur_has_z
    type_code_ |= 0x40000000 if @cur_has_m
    if @emit_ewkb_srid && toplevel_
      type_code_ |= 0x20000000
      emit_srid_ = true
    end
  elsif @type_format == :wkb12
    type_code_ += 1000 if @cur_has_z
    type_code_ += 2000 if @cur_has_m
  end
  _emit_integer(type_code_)
  _emit_integer(obj_.srid) if emit_srid_
  if type_ == Feature::Point
    _emit_doubles(_point_coords(obj_))
  elsif type_.subtype_of?(Feature::LineString)
    _emit_line_string_coords(obj_)
  elsif type_ == Feature::Polygon
    exterior_ring_ = obj_.exterior_ring
    if exterior_ring_.is_empty?
      _emit_integer(0)
    else
      _emit_integer(1 + obj_.num_interior_rings)
      _emit_line_string_coords(exterior_ring_)
      obj_.interior_rings.each{ |r_| _emit_line_string_coords(r_) }
    end
  elsif type_ == Feature::GeometryCollection
    _emit_integer(obj_.num_geometries)
    obj_.each{ |g_| _generate_feature(g_) }
  elsif type_ == Feature::MultiPoint
    _emit_integer(obj_.num_geometries)
    obj_.each{ |g_| _generate_feature(g_) }
  elsif type_ == Feature::MultiLineString
    _emit_integer(obj_.num_geometries)
    obj_.each{ |g_| _generate_feature(g_) }
  elsif type_ == Feature::MultiPolygon
    _emit_integer(obj_.num_geometries)
    obj_.each{ |g_| _generate_feature(g_) }
  end
end

#_point_coords(obj_, array_ = []) ⇒ Object

:nodoc:


206
207
208
209
210
211
212
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 206

def _point_coords(obj_, array_=[])  # :nodoc:
  array_ << obj_.x
  array_ << obj_.y
  array_ << obj_.z if @cur_has_z
  array_ << obj_.m if @cur_has_m
  array_
end

#_propertiesObject

:nodoc:


127
128
129
130
131
132
133
134
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 127

def _properties  # :nodoc:
  {
    'type_format' => @type_format.to_s,
    'emit_ewkb_srid' => @emit_ewkb_srid,
    'hex_format' => @hex_format,
    'little_endian' => @little_endian,
  }
end

#_start_emitterObject

:nodoc:


223
224
225
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 223

def _start_emitter  # :nodoc:
  @cur_array = []
end

#emit_ewkb_srid?Boolean

Returns whether SRID is embedded. See WKBGenerator for details.


110
111
112
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 110

def emit_ewkb_srid?
  @emit_ewkb_srid
end

#generate(obj_) ⇒ Object

Generate and return the WKB format for the given geometry object, according to the current settings.


140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 140

def generate(obj_)
  factory_ = obj_.factory
  if @type_format == :ewkb || @type_format == :wkb12
    @cur_has_z = factory_.property(:has_z_coordinate)
    @cur_has_m = factory_.property(:has_m_coordinate)
  else
    @cur_has_z = nil
    @cur_has_m = nil
  end
  @cur_dims = 2 + (@cur_has_z ? 1 : 0) + (@cur_has_m ? 1 : 0)
  _start_emitter
  _generate_feature(obj_, true)
  _finish_emitter
end

#hex_format?Boolean

Returns whether output is converted to hex. See WKBGenerator for details.


116
117
118
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 116

def hex_format?
  @hex_format
end

#little_endian?Boolean

Returns whether output is little-endian (NDR). See WKBGenerator for details.


122
123
124
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 122

def little_endian?
  @little_endian
end

#type_formatObject

Returns the format for type codes. See WKBGenerator for details.


105
106
107
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 105

def type_format
  @type_format
end