Class: RGeo::Geos::CAPIFactory

Inherits:
Object
  • Object
show all
Includes:
Feature::Factory::Instance, ImplHelper::Utils
Defined in:
lib/rgeo/geos/capi_factory.rb

Overview

This the GEOS CAPI implementation of RGeo::Feature::Factory.

Constant Summary collapse

IMPL_CLASSES =

:stopdoc:

{
  Feature::Point => CAPIPointImpl,
  Feature::LineString => CAPILineStringImpl,
  Feature::LinearRing => CAPILinearRingImpl,
  Feature::Line => CAPILineImpl,
  Feature::GeometryCollection => CAPIGeometryCollectionImpl,
  Feature::MultiPoint => CAPIMultiPointImpl,
  Feature::MultiLineString => CAPIMultiLineStringImpl,
  Feature::MultiPolygon => CAPIMultiPolygonImpl
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create(opts_ = {}) ⇒ Object Also known as: new

Create a new factory. Returns nil if the GEOS CAPI implementation is not supported.

See RGeo::Geos.factory for a list of supported options.


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rgeo/geos/capi_factory.rb', line 23

def create(opts_ = {})
  # Make sure GEOS is available
  return unless respond_to?(:_create)

  # Get flags to pass to the C extension
  flags = 0
  flags |= 2 if opts_[:has_z_coordinate]
  flags |= 4 if opts_[:has_m_coordinate]
  if flags & 6 == 6
    raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
  end
  flags |= 8 unless opts_[:auto_prepare] == :disabled

  # Buffer resolution
  buffer_resolution_ = opts_[:buffer_resolution].to_i
  buffer_resolution_ = 1 if buffer_resolution_ < 1

  # Interpret the generator options
  wkt_generator_ = opts_[:wkt_generator]
  case wkt_generator_
  when :geos
    wkt_generator_ = nil
  when Hash
    wkt_generator_ = WKRep::WKTGenerator.new(wkt_generator_)
  else
    wkt_generator_ = WKRep::WKTGenerator.new(convert_case: :upper)
  end
  wkb_generator_ = opts_[:wkb_generator]
  case wkb_generator_
  when :geos
    wkb_generator_ = nil
  when Hash
    wkb_generator_ = WKRep::WKBGenerator.new(wkb_generator_)
  else
    wkb_generator_ = WKRep::WKBGenerator.new
  end

  # Coordinate system (srid, proj4, and coord_sys)
  srid_ = opts_[:srid]
  proj4_ = opts_[:proj4]
  if proj4_ && CoordSys.check!(:proj4)
    if proj4_.is_a?(String) || proj4_.is_a?(Hash)
      proj4_ = CoordSys::Proj4.create(proj4_)
    end
  else
    proj4_ = nil
  end
  coord_sys_ = opts_[:coord_sys]
  if coord_sys_.is_a?(String)
    coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_)
  end
  srid_ ||= coord_sys_.authority_code if coord_sys_

  # Create the factory and set instance variables
  result = _create(flags, srid_.to_i, buffer_resolution_,
    wkt_generator_, wkb_generator_, proj4_, coord_sys_)

  # Interpret parser options
  wkt_parser_ = opts_[:wkt_parser]
  case wkt_parser_
  when :geos
    wkt_parser_ = nil
  when Hash
    wkt_parser_ = WKRep::WKTParser.new(result, wkt_parser_)
  else
    wkt_parser_ = WKRep::WKTParser.new(result)
  end
  wkb_parser_ = opts_[:wkb_parser]
  case wkb_parser_
  when :geos
    wkb_parser_ = nil
  when Hash
    wkb_parser_ = WKRep::WKBParser.new(result, wkb_parser_)
  else
    wkb_parser_ = WKRep::WKBParser.new(result)
  end
  result._set_wkrep_parsers(wkt_parser_, wkb_parser_)

  # Return the result
  result
end

Instance Method Details

#auto_prepareObject

:nodoc:


405
406
407
# File 'lib/rgeo/geos/capi_factory.rb', line 405

def auto_prepare # :nodoc:
  prepare_heuristic? ? :simple : :disabled
end

#buffer_resolutionObject

Returns the resolution used by buffer calculations on geometries created by this factory


243
244
245
# File 'lib/rgeo/geos/capi_factory.rb', line 243

def buffer_resolution
  _buffer_resolution
end

#collection(elems_) ⇒ Object

See RGeo::Feature::Factory#collection


327
328
329
330
# File 'lib/rgeo/geos/capi_factory.rb', line 327

def collection(elems_)
  elems_ = elems_.to_a unless elems_.is_a?(Array)
  CAPIGeometryCollectionImpl.create(self, elems_)
end

#coord_sysObject

See RGeo::Feature::Factory#coord_sys


362
363
364
# File 'lib/rgeo/geos/capi_factory.rb', line 362

def coord_sys
  _coord_sys
end

#encode_with(coder_) ⇒ Object

Psych support


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rgeo/geos/capi_factory.rb', line 182

def encode_with(coder_) # :nodoc:
  coder_["has_z_coordinate"] = supports_z?
  coder_["has_m_coordinate"] = supports_m?
  coder_["srid"] = _srid
  coder_["buffer_resolution"] = _buffer_resolution
  coder_["wkt_generator"] = _wkt_generator ? _wkt_generator.properties : {}
  coder_["wkb_generator"] = _wkb_generator ? _wkb_generator.properties : {}
  coder_["wkt_parser"] = _wkt_parser ? _wkt_parser.properties : {}
  coder_["wkb_parser"] = _wkb_parser ? _wkb_parser.properties : {}
  coder_["auto_prepare"] = auto_prepare
  if (proj4_ = _proj4)
    str_ = proj4_.original_str || proj4_.canonical_str
    coder_["proj4"] = proj4_.radians? ? { "proj4" => str_, "radians" => true } : str_
  end
  if (coord_sys_ = _coord_sys)
    coder_["coord_sys"] = coord_sys_.to_wkt
  end
end

#eql?(rhs_) ⇒ Boolean Also known as: ==

Factory equivalence test.

Returns:

  • (Boolean)

115
116
117
118
119
# File 'lib/rgeo/geos/capi_factory.rb', line 115

def eql?(rhs_)
  rhs_.is_a?(CAPIFactory) && rhs_.srid == _srid &&
    rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags &&
    rhs_.proj4 == _proj4
end

#hashObject

Standard hash code


124
125
126
# File 'lib/rgeo/geos/capi_factory.rb', line 124

def hash
  @hash ||= [_srid, _buffer_resolution, _flags, _proj4].hash
end

#init_with(coder_) ⇒ Object

:nodoc:


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/rgeo/geos/capi_factory.rb', line 201

def init_with(coder_) # :nodoc:
  if (proj4_data_ = coder_["proj4"])
    CoordSys.check!(:proj4)
    if proj4_data_.is_a?(Hash)
      proj4_ = CoordSys::Proj4.create(proj4_data_["proj4"], radians: proj4_data_["radians"])
    else
      proj4_ = CoordSys::Proj4.create(proj4_data_.to_s)
    end
  else
    proj4_ = nil
  end
  if (coord_sys_data_ = coder_["cs"])
    coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_.to_s)
  else
    coord_sys_ = nil
  end
  initialize_copy(
    CAPIFactory.create(
      has_z_coordinate: coder_["has_z_coordinate"],
      has_m_coordinate: coder_["has_m_coordinate"],
      srid: coder_["srid"],
      buffer_resolution: coder_["buffer_resolution"],
      wkt_generator: symbolize_hash(coder_["wkt_generator"]),
      wkb_generator: symbolize_hash(coder_["wkb_generator"]),
      wkt_parser: symbolize_hash(coder_["wkt_parser"]),
      wkb_parser: symbolize_hash(coder_["wkb_parser"]),
      auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
      proj4: proj4_,
      coord_sys: coord_sys_
    )
  )
end

#inspectObject

Standard object inspection output


109
110
111
# File 'lib/rgeo/geos/capi_factory.rb', line 109

def inspect
  "#<#{self.class}:0x#{object_id.to_s(16)} srid=#{_srid} bufres=#{_buffer_resolution} flags=#{_flags}>"
end

#line(start_, end_) ⇒ Object

See RGeo::Feature::Factory#line


307
308
309
# File 'lib/rgeo/geos/capi_factory.rb', line 307

def line(start_, end_)
  CAPILineImpl.create(self, start_, end_)
end

#line_string(points_) ⇒ Object

See RGeo::Feature::Factory#line_string


299
300
301
302
303
# File 'lib/rgeo/geos/capi_factory.rb', line 299

def line_string(points_)
  points_ = points_.to_a unless points_.is_a?(Array)
  CAPILineStringImpl.create(self, points_) ||
    raise(RGeo::Error::InvalidGeometry, "Parse error")
end

#linear_ring(points_) ⇒ Object

See RGeo::Feature::Factory#linear_ring


313
314
315
316
# File 'lib/rgeo/geos/capi_factory.rb', line 313

def linear_ring(points_)
  points_ = points_.to_a unless points_.is_a?(Array)
  CAPILinearRingImpl.create(self, points_)
end

#marshal_dumpObject

Marshal support


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/rgeo/geos/capi_factory.rb', line 130

def marshal_dump # :nodoc:
  hash_ = {
    "hasz" => supports_z?,
    "hasm" => supports_m?,
    "srid" => _srid,
    "bufr" => _buffer_resolution,
    "wktg" => _wkt_generator ? _wkt_generator.properties : {},
    "wkbg" => _wkb_generator ? _wkb_generator.properties : {},
    "wktp" => _wkt_parser ? _wkt_parser.properties : {},
    "wkbp" => _wkb_parser ? _wkb_parser.properties : {},
    "apre" => auto_prepare
  }
  if (proj4_ = _proj4)
    hash_["proj4"] = proj4_.marshal_dump
  end
  if (coord_sys_ = _coord_sys)
    hash_["cs"] = coord_sys_.to_wkt
  end
  hash_
end

#marshal_load(data_) ⇒ Object

:nodoc:


151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rgeo/geos/capi_factory.rb', line 151

def marshal_load(data_) # :nodoc:
  if (proj4_data_ = data_["proj4"]) && CoordSys.check!(:proj4)
    proj4_ = CoordSys::Proj4.allocate
    proj4_.marshal_load(proj4_data_)
  else
    proj4_ = nil
  end
  if (coord_sys_data_ = data_["cs"])
    coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_)
  else
    coord_sys_ = nil
  end
  initialize_copy(
    CAPIFactory.create(
      has_z_coordinate: data_["hasz"],
      has_m_coordinate: data_["hasm"],
      srid: data_["srid"],
      buffer_resolution: data_["bufr"],
      wkt_generator: symbolize_hash(data_["wktg"]),
      wkb_generator: symbolize_hash(data_["wkbg"]),
      wkt_parser: symbolize_hash(data_["wktp"]),
      wkb_parser: symbolize_hash(data_["wkbp"]),
      auto_prepare: data_["apre"],
      proj4: proj4_,
      coord_sys: coord_sys_
    )
  )
end

#multi_line_string(elems_) ⇒ Object

See RGeo::Feature::Factory#multi_line_string


341
342
343
344
# File 'lib/rgeo/geos/capi_factory.rb', line 341

def multi_line_string(elems_)
  elems_ = elems_.to_a unless elems_.is_a?(Array)
  CAPIMultiLineStringImpl.create(self, elems_)
end

#multi_point(elems_) ⇒ Object

See RGeo::Feature::Factory#multi_point


334
335
336
337
# File 'lib/rgeo/geos/capi_factory.rb', line 334

def multi_point(elems_)
  elems_ = elems_.to_a unless elems_.is_a?(Array)
  CAPIMultiPointImpl.create(self, elems_)
end

#multi_polygon(elems_) ⇒ Object

See RGeo::Feature::Factory#multi_polygon


348
349
350
351
352
# File 'lib/rgeo/geos/capi_factory.rb', line 348

def multi_polygon(elems_)
  elems_ = elems_.to_a unless elems_.is_a?(Array)
  CAPIMultiPolygonImpl.create(self, elems_) ||
    raise(RGeo::Error::InvalidGeometry, "Parse error")
end

#override_cast(original, ntype, flags) ⇒ Object

See RGeo::Feature::Factory#override_cast


368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/rgeo/geos/capi_factory.rb', line 368

def override_cast(original, ntype, flags)
  return unless Geos.supported?
  keep_subtype = flags[:keep_subtype]
  # force_new_ = flags[:force_new]
  project = flags[:project]
  type = original.geometry_type
  ntype = type if keep_subtype && type.include?(ntype)
  case original
  when CAPIGeometryMethods
    # Optimization if we're just changing factories, but the
    # factories are zm-compatible and proj4-compatible.
    if original.factory != self && ntype == type &&
        original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
        (!project || original.factory.proj4 == _proj4)
      result = original.dup
      result.factory = self
      return result
    end
    # LineString conversion optimization.
    if (original.factory != self || ntype != type) &&
        original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
        (!project || original.factory.proj4 == _proj4) &&
        type.subtype_of?(Feature::LineString) && ntype.subtype_of?(Feature::LineString)
      return IMPL_CLASSES[ntype]._copy_from(self, original)
    end
  when ZMGeometryMethods
    # Optimization for just removing a coordinate from an otherwise
    # compatible factory
    if supports_z? && !supports_m? && self == original.factory.z_factory
      return Feature.cast(original.z_geometry, ntype, flags)
    elsif supports_m? && !supports_z? && self == original.factory.m_factory
      return Feature.cast(original.m_geometry, ntype, flags)
    end
  end
  false
end

#parse_wkb(str_) ⇒ Object

See RGeo::Feature::Factory#parse_wkb


275
276
277
278
279
280
281
282
283
284
285
# File 'lib/rgeo/geos/capi_factory.rb', line 275

def parse_wkb(str_)
  if (wkb_parser_ = _wkb_parser)
    wkb_parser_.parse(str_)
  else
    if str_[0] == "\x00" || str_[0] == "\x01"
      _parse_wkb_impl(str_)
    else
      _parse_wkb_impl([str_].pack('H*'))
    end
  end
end

#parse_wkt(str_) ⇒ Object

See RGeo::Feature::Factory#parse_wkt


265
266
267
268
269
270
271
# File 'lib/rgeo/geos/capi_factory.rb', line 265

def parse_wkt(str_)
  if (wkt_parser_ = _wkt_parser)
    wkt_parser_.parse(str_)
  else
    _parse_wkt_impl(str_)
  end
end

#point(x, y, *extra) ⇒ Object

See RGeo::Feature::Factory#point


289
290
291
292
293
294
295
# File 'lib/rgeo/geos/capi_factory.rb', line 289

def point(x, y, *extra)
  if extra.length > (supports_z_or_m? ? 1 : 0)
    raise(RGeo::Error::InvalidGeometry, "Parse error")
  else
    CAPIPointImpl.create(self, x, y, extra[0].to_f)
  end
end

#polygon(outer_ring_, inner_rings_ = nil) ⇒ Object

See RGeo::Feature::Factory#polygon


320
321
322
323
# File 'lib/rgeo/geos/capi_factory.rb', line 320

def polygon(outer_ring_, inner_rings_ = nil)
  inner_rings_ = inner_rings_.to_a unless inner_rings_.is_a?(Array)
  CAPIPolygonImpl.create(self, outer_ring_, inner_rings_)
end

#proj4Object

See RGeo::Feature::Factory#proj4


356
357
358
# File 'lib/rgeo/geos/capi_factory.rb', line 356

def proj4
  _proj4
end

#property(name_) ⇒ Object

See RGeo::Feature::Factory#property


248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/rgeo/geos/capi_factory.rb', line 248

def property(name_)
  case name_
  when :has_z_coordinate
    supports_z?
  when :has_m_coordinate
    supports_m?
  when :is_cartesian
    true
  when :buffer_resolution
    _buffer_resolution
  when :auto_prepare
    prepare_heuristic? ? :simple : :disabled
  end
end

#sridObject

Returns the SRID of geometries created by this factory.


236
237
238
# File 'lib/rgeo/geos/capi_factory.rb', line 236

def srid
  _srid
end