class RGeo::Geos::FFIFactory

This the FFI-GEOS implementation of ::RGeo::Feature::Factory.

Public Class Methods

new(opts_={}) click to toggle source

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

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

# File lib/rgeo/geos/ffi_factory.rb, line 55
def initialize(opts_={})
  # Main flags
  @uses_lenient_multi_polygon_assertions = opts_[:uses_lenient_assertions] ||
    opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
  @has_z = opts_[:has_z_coordinate] ? true : false
  @has_m = opts_[:has_m_coordinate] ? true : false
  if @has_z && @has_m
    raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
  end
  @_has_3d = @has_z || @has_m
  @buffer_resolution = opts_[:buffer_resolution].to_i
  @buffer_resolution = 1 if @buffer_resolution < 1
  @_auto_prepare = opts_[:auto_prepare] == :disabled ? false : true

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

  # Coordinate system (srid, proj4, and coord_sys)
  @srid = opts_[:srid]
  @proj4 = opts_[:proj4]
  if CoordSys::Proj4.supported?
    if @proj4.kind_of?(::String) || @proj4.kind_of?(::Hash)
      @proj4 = CoordSys::Proj4.create(@proj4)
    end
  else
    @proj4 = nil
  end
  @coord_sys = opts_[:coord_sys]
  if @coord_sys.kind_of?(::String)
    @coord_sys = CoordSys::CS.create_from_wkt(@coord_sys) rescue nil
  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
  @srid = @srid.to_i

  # Interpret parser options
  wkt_parser_ = opts_[:wkt_parser]
  case wkt_parser_
  when :geos
    @wkt_reader = ::Geos::WktReader.new
    @wkt_parser = nil
  when ::Hash
    @wkt_parser = WKRep::WKTParser.new(self, wkt_parser_)
    @wkt_reader = nil
  else
    @wkt_parser = WKRep::WKTParser.new(self)
    @wkt_reader = nil
  end
  wkb_parser_ = opts_[:wkb_parser]
  case wkb_parser_
  when :geos
    @wkb_reader = ::Geos::WkbReader.new
    @wkb_parser = nil
  when ::Hash
    @wkb_parser = WKRep::WKBParser.new(self, wkb_parser_)
    @wkb_reader = nil
  else
    @wkb_parser = WKRep::WKBParser.new(self)
    @wkb_reader = nil
  end
end

Public Instance Methods

==(rhs_) click to toggle source
Alias for: eql?
buffer_resolution() click to toggle source

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

# File lib/rgeo/geos/ffi_factory.rb, line 284
def buffer_resolution
  @buffer_resolution
end
collection(elems_) click to toggle source

See RGeo::Feature::Factory#collection

# File lib/rgeo/geos/ffi_factory.rb, line 427
def collection(elems_)
  elems_ = elems_.to_a unless elems_.kind_of?(::Array)
  klasses_ = []
  fg_geoms_ = []
  elems_.each do |elem_|
    k_ = elem_._klasses if elem_.factory.is_a?(FFIFactory)
    elem_ = ::RGeo::Feature.cast(elem_, self, :force_new, :keep_subtype)
    if elem_
      klasses_ << (k_ || elem_.class)
      fg_geoms_ << elem_._detach_fg_geom
    end
  end
  fg_geom_ = ::Geos::Utils.create_collection(
    ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION, fg_geoms_)
  fg_geom_ ? FFIGeometryCollectionImpl.new(self, fg_geom_, klasses_) : nil
end
coord_sys() click to toggle source

See RGeo::Feature::Factory#coord_sys

# File lib/rgeo/geos/ffi_factory.rb, line 516
def coord_sys
  @coord_sys
end
eql?(rhs_) click to toggle source

Factory equivalence test.

# File lib/rgeo/geos/ffi_factory.rb, line 156
def eql?(rhs_)
  rhs_.is_a?(self.class) && @srid == rhs_.srid &&
    @has_z == rhs_.property(:has_z_coordinate) &&
    @has_m == rhs_.property(:has_m_coordinate) &&
    @buffer_resolution == rhs_.property(:buffer_resolution) &&
    @proj4.eql?(rhs_.proj4)
end
Also aliased as: ==
hash() click to toggle source

Standard hash code

# File lib/rgeo/geos/ffi_factory.rb, line 168
def hash
  @hash ||= [@srid, @has_z, @has_m, @buffer_resolution, @proj4].hash
end
inspect() click to toggle source

Standard object inspection output

# File lib/rgeo/geos/ffi_factory.rb, line 149
def inspect
  "#<#{self.class}:0x#{object_id.to_s(16)} srid=#{srid}>"
end
lenient_multi_polygon_assertions?() click to toggle source

Returns true if this factory is lenient with MultiPolygon assertions

# File lib/rgeo/geos/ffi_factory.rb, line 291
def lenient_multi_polygon_assertions?
  @uses_lenient_multi_polygon_assertions
end
line(start_, end_) click to toggle source

See RGeo::Feature::Factory#line

# File lib/rgeo/geos/ffi_factory.rb, line 381
def line(start_, end_)
  return nil unless ::RGeo::Feature::Point.check_type(start_) &&
    ::RGeo::Feature::Point.check_type(end_)
  cs_ = ::Geos::CoordinateSequence.new(2, 3)
  cs_.set_x(0, start_.x)
  cs_.set_x(1, end_.x)
  cs_.set_y(0, start_.y)
  cs_.set_y(1, end_.y)
  if @has_z
    cs_.set_z(0, start_.z)
    cs_.set_z(1, end_.z)
  elsif @has_m
    cs_.set_z(0, start_.m)
    cs_.set_z(1, end_.m)
  end
  FFILineImpl.new(self, ::Geos::Utils.create_line_string(cs_), nil)
end
line_string(points_) click to toggle source

See RGeo::Feature::Factory#line_string

# File lib/rgeo/geos/ffi_factory.rb, line 360
def line_string(points_)
  points_ = points_.to_a unless points_.kind_of?(::Array)
  size_ = points_.size
  return nil if size_ == 1
  cs_ = ::Geos::CoordinateSequence.new(size_, 3)
  points_.each_with_index do |p_, i_|
    return nil unless ::RGeo::Feature::Point.check_type(p_)
    cs_.set_x(i_, p_.x)
    cs_.set_y(i_, p_.y)
    if @has_z
      cs_.set_z(i_, p_.z)
    elsif @has_m
      cs_.set_z(i_, p_.m)
    end
  end
  FFILineStringImpl.new(self, ::Geos::Utils.create_line_string(cs_), nil)
end
linear_ring(points_) click to toggle source

See RGeo::Feature::Factory#linear_ring

# File lib/rgeo/geos/ffi_factory.rb, line 402
def linear_ring(points_)
  points_ = points_.to_a unless points_.kind_of?(::Array)
  fg_geom_ = _create_fg_linear_ring(points_)
  fg_geom_ ? FFILinearRingImpl.new(self, fg_geom_, nil) : nil
end
multi_line_string(elems_) click to toggle source

See RGeo::Feature::Factory#multi_line_string

# File lib/rgeo/geos/ffi_factory.rb, line 464
def multi_line_string(elems_)
  elems_ = elems_.to_a unless elems_.kind_of?(::Array)
  klasses_ = []
  elems_ = elems_.map do |elem_|
    elem_ = ::RGeo::Feature.cast(elem_, self, ::RGeo::Feature::LineString,
      :force_new, :keep_subtype)
    return nil unless elem_
    klasses_ << elem_.class
    elem_._detach_fg_geom
  end
  fg_geom_ = ::Geos::Utils.create_collection(
    ::Geos::GeomTypes::GEOS_MULTILINESTRING, elems_)
  fg_geom_ ? FFIMultiLineStringImpl.new(self, fg_geom_, klasses_) : nil
end
multi_point(elems_) click to toggle source

See RGeo::Feature::Factory#multi_point

# File lib/rgeo/geos/ffi_factory.rb, line 447
def multi_point(elems_)
  elems_ = elems_.to_a unless elems_.kind_of?(::Array)
  elems_ = elems_.map do |elem_|
    elem_ = ::RGeo::Feature.cast(elem_, self, ::RGeo::Feature::Point,
      :force_new, :keep_subtype)
    return nil unless elem_
    elem_._detach_fg_geom
  end
  klasses_ = ::Array.new(elems_.size, FFIPointImpl)
  fg_geom_ = ::Geos::Utils.create_collection(
    ::Geos::GeomTypes::GEOS_MULTIPOINT, elems_)
  fg_geom_ ? FFIMultiPointImpl.new(self, fg_geom_, klasses_) : nil
end
multi_polygon(elems_) click to toggle source

See RGeo::Feature::Factory#multi_polygon

# File lib/rgeo/geos/ffi_factory.rb, line 482
def multi_polygon(elems_)
  elems_ = elems_.to_a unless elems_.kind_of?(::Array)
  elems_ = elems_.map do |elem_|
    elem_ = ::RGeo::Feature.cast(elem_, self, ::RGeo::Feature::Polygon,
      :force_new, :keep_subtype)
    return nil unless elem_
    elem_._detach_fg_geom
  end
  unless @uses_lenient_multi_polygon_assertions
    (1...elems_.size).each do |i_|
      (0...i_).each do |j_|
        igeom_ = elems_[i_]
        jgeom_ = elems_[j_]
        return nil if igeom_.relate_pattern(jgeom_, "2********") ||
          igeom_.relate_pattern(jgeom_, "****1****")
      end
    end
  end
  klasses_ = ::Array.new(elems_.size, FFIPolygonImpl)
  fg_geom_ = ::Geos::Utils.create_collection(
    ::Geos::GeomTypes::GEOS_MULTIPOLYGON, elems_)
  fg_geom_ ? FFIMultiPolygonImpl.new(self, fg_geom_, klasses_) : nil
end
override_cast(original_, ntype_, flags_) click to toggle source

See RGeo::Feature::Factory#override_cast

# File lib/rgeo/geos/ffi_factory.rb, line 523
def override_cast(original_, ntype_, flags_)
  false
  # TODO
end
parse_wkb(str_) click to toggle source

See RGeo::Feature::Factory#parse_wkb

# File lib/rgeo/geos/ffi_factory.rb, line 338
def parse_wkb(str_)
  if @wkb_reader
    _wrap_fg_geom(@wkb_reader.read(str_), nil)
  else
    @wkb_parser.parse(str_)
  end
end
parse_wkt(str_) click to toggle source

See RGeo::Feature::Factory#parse_wkt

# File lib/rgeo/geos/ffi_factory.rb, line 327
def parse_wkt(str_)
  if @wkt_reader
    _wrap_fg_geom(@wkt_reader.read(str_), nil)
  else
    @wkt_parser.parse(str_)
  end
end
point(x_, y_, z_=0) click to toggle source

See RGeo::Feature::Factory#point

# File lib/rgeo/geos/ffi_factory.rb, line 349
def point(x_, y_, z_=0)
  cs_ = ::Geos::CoordinateSequence.new(1, 3)
  cs_.set_x(0, x_)
  cs_.set_y(0, y_)
  cs_.set_z(0, z_)
  FFIPointImpl.new(self, ::Geos::Utils.create_point(cs_), nil)
end
polygon(outer_ring_, inner_rings_=nil) click to toggle source

See RGeo::Feature::Factory#polygon

# File lib/rgeo/geos/ffi_factory.rb, line 411
def polygon(outer_ring_, inner_rings_=nil)
  inner_rings_ = inner_rings_.to_a unless inner_rings_.kind_of?(::Array)
  return nil unless ::RGeo::Feature::LineString.check_type(outer_ring_)
  outer_ring_ = _create_fg_linear_ring(outer_ring_.points)
  inner_rings_ = inner_rings_.map do |r_|
    return nil unless ::RGeo::Feature::LineString.check_type(r_)
    _create_fg_linear_ring(r_.points)
  end
  inner_rings_.compact!
  fg_geom_ = ::Geos::Utils.create_polygon(outer_ring_, *inner_rings_)
  fg_geom_ ? FFIPolygonImpl.new(self, fg_geom_, nil) : nil
end
proj4() click to toggle source

See RGeo::Feature::Factory#proj4

# File lib/rgeo/geos/ffi_factory.rb, line 509
def proj4
  @proj4
end
property(name_) click to toggle source

See RGeo::Feature::Factory#property

# File lib/rgeo/geos/ffi_factory.rb, line 298
def property(name_)
  case name_
  when :has_z_coordinate
    @has_z
  when :has_m_coordinate
    @has_m
  when :is_cartesian
    true
  when :buffer_resolution
    @buffer_resolution
  when :uses_lenient_multi_polygon_assertions
    @uses_lenient_multi_polygon_assertions
  when :auto_prepare
    @_auto_prepare ? :simple : :disabled
  else
    nil
  end
end
srid() click to toggle source

Returns the SRID of geometries created by this factory.

# File lib/rgeo/geos/ffi_factory.rb, line 276
def srid
  @srid
end
wrap_fg_geom(fg_geom_) click to toggle source

Create a feature that wraps the given ffi-geos geometry object

# File lib/rgeo/geos/ffi_factory.rb, line 320
def wrap_fg_geom(fg_geom_)
  _wrap_fg_geom(fg_geom_, nil)
end