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

Methods included from ImplHelper::Utils

setup_coord_sys

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.



22
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
# File 'lib/rgeo/geos/capi_factory.rb', line 22

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]
  wkt_generator =
    case wkt_generator
    when Hash
      WKRep::WKTGenerator.new(wkt_generator)
    end
  wkb_generator = opts[:wkb_generator]
  wkb_generator =
    case wkb_generator
    when Hash
      WKRep::WKBGenerator.new(wkb_generator)
    end

  # Coordinate system (srid and coord_sys)
  coord_sys_info = ImplHelper::Utils.setup_coord_sys(opts[:srid], opts[:coord_sys], opts[:coord_sys_class])
  srid = coord_sys_info[:srid]
  coord_sys = coord_sys_info[:coord_sys]

  # Create the factory and set instance variables
  result = _create(
    flags,
    srid.to_i,
    buffer_resolution,
    wkt_generator,
    wkb_generator,
    coord_sys
  )

  # Interpret parser options
  wkt_parser = opts[:wkt_parser]
  wkt_parser =
    case wkt_parser
    when Hash
      WKRep::WKTParser.new(result, wkt_parser)
    end
  wkb_parser = opts[:wkb_parser]
  wkb_parser =
    case wkb_parser
    when Hash
      WKRep::WKBParser.new(result, wkb_parser)
    end
  result._set_wkrep_parsers(wkt_parser, wkb_parser)

  # Return the result
  result
end

Instance Method Details

#auto_prepareObject

:nodoc:



351
352
353
# File 'lib/rgeo/geos/capi_factory.rb', line 351

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

#buffer_resolutionObject

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



199
200
201
# File 'lib/rgeo/geos/capi_factory.rb', line 199

def buffer_resolution
  _buffer_resolution
end

#collection(elems_) ⇒ Object

See RGeo::Feature::Factory#collection



277
278
279
280
# File 'lib/rgeo/geos/capi_factory.rb', line 277

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



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

def coord_sys
  _coord_sys
end

#encode_with(coder_) ⇒ Object

Psych support



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rgeo/geos/capi_factory.rb', line 154

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

  return unless (coord_sys_ = _coord_sys)

  coder_["coord_sys"] = coord_sys_.to_wkt
end

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

Factory equivalence test.

Returns:

  • (Boolean)


99
100
101
102
103
# File 'lib/rgeo/geos/capi_factory.rb', line 99

def eql?(other)
  other.is_a?(CAPIFactory) && other.srid == _srid &&
    other._buffer_resolution == _buffer_resolution && other._flags == _flags &&
    other.coord_sys == coord_sys
end

#hashObject

Standard hash code



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

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

#init_with(coder_) ⇒ Object

:nodoc:



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/rgeo/geos/capi_factory.rb', line 170

def init_with(coder_) # :nodoc:
  cs_class = CoordSys::CONFIG.default_coord_sys_class
  coord_sys_ = coder_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }

  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,
      coord_sys: coord_sys_
    )
  )
end

#inspectObject

Standard object inspection output



93
94
95
# File 'lib/rgeo/geos/capi_factory.rb', line 93

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



257
258
259
# File 'lib/rgeo/geos/capi_factory.rb', line 257

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

#line_string(points_) ⇒ Object

See RGeo::Feature::Factory#line_string



249
250
251
252
253
# File 'lib/rgeo/geos/capi_factory.rb', line 249

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



263
264
265
266
# File 'lib/rgeo/geos/capi_factory.rb', line 263

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

#marshal_dumpObject

Marshal support



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rgeo/geos/capi_factory.rb', line 114

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 (coord_sys_ = _coord_sys)
    hash_["cs"] = coord_sys_.to_wkt
  end
  hash_
end

#marshal_load(data_) ⇒ Object

:nodoc:



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

def marshal_load(data_) # :nodoc:
  cs_class = CoordSys::CONFIG.default_coord_sys_class
  coord_sys_ = data_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }

  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"],
      coord_sys: coord_sys_
    )
  )
end

#multi_line_string(elems_) ⇒ Object

See RGeo::Feature::Factory#multi_line_string



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

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



284
285
286
287
# File 'lib/rgeo/geos/capi_factory.rb', line 284

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



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

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



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/rgeo/geos/capi_factory.rb', line 312

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 coord_sys-compatible.
    if original.factory != self && ntype == type &&
        original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
        (!project || original.factory.coord_sys == coord_sys)
      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.coord_sys == coord_sys) &&
        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)
    end

    if 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



231
232
233
234
235
236
237
# File 'lib/rgeo/geos/capi_factory.rb', line 231

def parse_wkb(str_)
  if (wkb_parser_ = _wkb_parser)
    wkb_parser_.parse(str_)
  else
    _parse_wkb_impl(str_)
  end
end

#parse_wkt(str_) ⇒ Object

See RGeo::Feature::Factory#parse_wkt



221
222
223
224
225
226
227
# File 'lib/rgeo/geos/capi_factory.rb', line 221

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



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

def point(x, y, *extra)
  raise(RGeo::Error::InvalidGeometry, "Parse error") if extra.length > (supports_z_or_m? ? 1 : 0)

  CAPIPointImpl.create(self, x, y, extra[0].to_f)
end

#polygon(outer_ring_, inner_rings_ = nil) ⇒ Object

See RGeo::Feature::Factory#polygon



270
271
272
273
# File 'lib/rgeo/geos/capi_factory.rb', line 270

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

#property(name_) ⇒ Object

See RGeo::Feature::Factory#property



204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/rgeo/geos/capi_factory.rb', line 204

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.



192
193
194
# File 'lib/rgeo/geos/capi_factory.rb', line 192

def srid
  _srid
end