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 Attribute Summary collapse

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.



59
60
61
62
63
64
65
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 59

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 Attribute Details

#type_formatObject (readonly)

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



68
69
70
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 68

def type_format
  @type_format
end

Instance Method Details

#_emit_byte(value_) ⇒ Object

:nodoc:



182
183
184
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 182

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

#_emit_doubles(array_) ⇒ Object

:nodoc:



190
191
192
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 190

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

#_emit_integer(value_) ⇒ Object

:nodoc:



186
187
188
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 186

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

#_emit_line_string_coords(obj_) ⇒ Object

:nodoc:



171
172
173
174
175
176
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 171

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:



194
195
196
197
198
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 194

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:



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 114

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:



163
164
165
166
167
168
169
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 163

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:



87
88
89
90
91
92
93
94
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 87

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:



178
179
180
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 178

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

#emit_ewkb_srid?Boolean

Returns whether SRID is embedded. See WKBGenerator for details.

Returns:

  • (Boolean)


71
72
73
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 71

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.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 99

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.

Returns:

  • (Boolean)


77
78
79
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 77

def hex_format?
  @hex_format
end

#little_endian?Boolean

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

Returns:

  • (Boolean)


83
84
85
# File 'lib/rgeo/wkrep/wkb_generator.rb', line 83

def little_endian?
  @little_endian
end