Class: RGeo::Geos::CAPIFactory

Inherits:
Object
  • Object
show all
Includes:
Feature::Factory::Instance
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.



20
21
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rgeo/geos/capi_factory.rb', line 20

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

  # Get flags to pass to the C extension
  flags_ = 0
  flags_ |= 1 if opts_[:uses_lenient_assertions] || opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
  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 CoordSys::Proj4.supported?
    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_ = begin
                   CoordSys::CS.create_from_wkt(coord_sys_)
                 rescue
                   nil
                 end
  end
  if (!proj4_ || !coord_sys_) && srid_ && (db_ = opts_[:srs_database])
    entry_ = db_.get(srid_.to_i)
    if entry_
      proj4_ ||= entry_.proj4
      coord_sys_ ||= entry_.coord_sys
    end
  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

#buffer_resolutionObject

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



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

def buffer_resolution
  _buffer_resolution
end

#collection(elems_) ⇒ Object

See ::RGeo::Feature::Factory#collection



357
358
359
360
361
362
363
364
# File 'lib/rgeo/geos/capi_factory.rb', line 357

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

#coord_sysObject

See ::RGeo::Feature::Factory#coord_sys



407
408
409
# File 'lib/rgeo/geos/capi_factory.rb', line 407

def coord_sys
  _coord_sys
end

#encode_with(coder_) ⇒ Object

Psych support



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/rgeo/geos/capi_factory.rb', line 191

def encode_with(coder_) # :nodoc:
  coder_["has_z_coordinate"] = (_flags & 0x2 != 0)
  coder_["has_m_coordinate"] = (_flags & 0x4 != 0)
  coder_["srid"] = _srid
  coder_["buffer_resolution"] = _buffer_resolution
  coder_["lenient_multi_polygon_assertions"] = (_flags & 0x1 != 0)
  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"] = ((_flags & 0x8) == 0 ? "disabled" : "simple")
  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)


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

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



133
134
135
# File 'lib/rgeo/geos/capi_factory.rb', line 133

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

#init_with(coder_) ⇒ Object

:nodoc:



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/rgeo/geos/capi_factory.rb', line 211

def init_with(coder_) # :nodoc:
  if (proj4_data_ = coder_["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: ImplHelper::Utils.symbolize_hash(coder_["wkt_generator"]),
                    wkb_generator: ImplHelper::Utils.symbolize_hash(coder_["wkb_generator"]),
                    wkt_parser: ImplHelper::Utils.symbolize_hash(coder_["wkt_parser"]),
                    wkb_parser: ImplHelper::Utils.symbolize_hash(coder_["wkb_parser"]),
                    auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
                    uses_lenient_multi_polygon_assertions: coder_["lenient_multi_polygon_assertions"],
                    proj4: proj4_,
                    coord_sys: coord_sys_
  ))
end

#inspectObject

Standard object inspection output



118
119
120
# File 'lib/rgeo/geos/capi_factory.rb', line 118

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

#lenient_multi_polygon_assertions?Boolean

Returns true if this factory is lenient with MultiPolygon assertions

Returns:

  • (Boolean)


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

def lenient_multi_polygon_assertions?
  _flags & 0x1 != 0
end

#line(start_, end_) ⇒ Object

See ::RGeo::Feature::Factory#line



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

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

#line_string(points_) ⇒ Object

See ::RGeo::Feature::Factory#line_string



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

def line_string(points_)
  points_ = points_.to_a unless points_.is_a?(::Array)
  begin
    CAPILineStringImpl.create(self, points_)
  rescue
    nil
  end
end

#linear_ring(points_) ⇒ Object

See ::RGeo::Feature::Factory#linear_ring



335
336
337
338
339
340
341
342
# File 'lib/rgeo/geos/capi_factory.rb', line 335

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

#marshal_dumpObject

Marshal support



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/rgeo/geos/capi_factory.rb', line 139

def marshal_dump # :nodoc:
  hash_ = {
    "hasz" => (_flags & 0x2 != 0),
    "hasm" => (_flags & 0x4 != 0),
    "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 : {},
    "lmpa" => (_flags & 0x1 != 0),
    "apre" => ((_flags & 0x8) >> 3)
  }
  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:



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

def marshal_load(data_) # :nodoc:
  if CoordSys::Proj4.supported? && (proj4_data_ = data_["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: ImplHelper::Utils.symbolize_hash(data_["wktg"]),
                    wkb_generator: ImplHelper::Utils.symbolize_hash(data_["wkbg"]),
                    wkt_parser: ImplHelper::Utils.symbolize_hash(data_["wktp"]),
                    wkb_parser: ImplHelper::Utils.symbolize_hash(data_["wkbp"]),
                    uses_lenient_multi_polygon_assertions: data_["lmpa"],
                    auto_prepare: (data_["apre"] == 0 ? :disabled : :simple),
                    proj4: proj4_,
                    coord_sys: coord_sys_
  ))
end

#multi_line_string(elems_) ⇒ Object

See ::RGeo::Feature::Factory#multi_line_string



379
380
381
382
383
384
385
386
# File 'lib/rgeo/geos/capi_factory.rb', line 379

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

#multi_point(elems_) ⇒ Object

See ::RGeo::Feature::Factory#multi_point



368
369
370
371
372
373
374
375
# File 'lib/rgeo/geos/capi_factory.rb', line 368

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

#multi_polygon(elems_) ⇒ Object

See ::RGeo::Feature::Factory#multi_polygon



390
391
392
393
394
395
396
397
# File 'lib/rgeo/geos/capi_factory.rb', line 390

def multi_polygon(elems_)
  elems_ = elems_.to_a unless elems_.is_a?(::Array)
  begin
    CAPIMultiPolygonImpl.create(self, elems_)
  rescue
    nil
  end
end

#override_cast(original_, ntype_, flags_) ⇒ Object

See ::RGeo::Feature::Factory#override_cast



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
# File 'lib/rgeo/geos/capi_factory.rb', line 413

def override_cast(original_, ntype_, flags_)
  return nil 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 & 0x6 == _flags & 0x6 &&
        (!project_ || original_.factory.proj4 == _proj4)
      result_ = original_.dup
      result_._set_factory(self)
      return result_
    end
    # LineString conversion optimization.
    if (original_.factory != self || ntype_ != type_) &&
        original_.factory._flags & 0x6 == _flags & 0x6 &&
        (!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 _flags & 0x6 == 0x2 && self == original_.factory.z_factory
      return Feature.cast(original_.z_geometry, ntype_, flags_)
    elsif _flags & 0x6 == 0x4 && 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



292
293
294
295
296
297
298
# File 'lib/rgeo/geos/capi_factory.rb', line 292

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



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

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



302
303
304
305
306
307
308
309
310
311
312
# File 'lib/rgeo/geos/capi_factory.rb', line 302

def point(x_, y_, *extra_)
  if extra_.length > (_flags & 6 == 0 ? 0 : 1)
    nil
  else
    begin
      CAPIPointImpl.create(self, x_, y_, extra_[0].to_f)
    rescue
      nil
    end
  end
end

#polygon(outer_ring_, inner_rings_ = nil) ⇒ Object

See ::RGeo::Feature::Factory#polygon



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

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

#proj4Object

See ::RGeo::Feature::Factory#proj4



401
402
403
# File 'lib/rgeo/geos/capi_factory.rb', line 401

def proj4
  _proj4
end

#property(name_) ⇒ Object

See ::RGeo::Feature::Factory#property



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/rgeo/geos/capi_factory.rb', line 263

def property(name_)
  case name_
  when :has_z_coordinate
    _flags & 0x2 != 0
  when :has_m_coordinate
    _flags & 0x4 != 0
  when :is_cartesian
    true
  when :uses_lenient_multi_polygon_assertions
    _flags & 0x1 != 0
  when :buffer_resolution
    _buffer_resolution
  when :auto_prepare
    _flags & 0x8 != 0 ? :simple : :disabled
  end
end

#sridObject

Returns the SRID of geometries created by this factory.



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

def srid
  _srid
end