class Geos::STRtree

Attributes

ptr[R]

Public Class Methods

new(capacity) click to toggle source
new(geoms_and_objects)
# File lib/ffi-geos/strtree.rb, line 22
def initialize(*args)
  geoms_and_objects = nil # forward declaration
  capacity = 10

  case args.first
    when Integer
      capacity = args.first
    when Array
      geoms_and_objects = if args.first.first.is_a?(Array)
        args.first
      else
        args
      end

      geoms_and_objects.each do |geom, _obj|
        check_geometry(geom)
      end
  end

  raise ArgumentError, 'STRtree capacity must be greater than 0' if capacity <= 0

  ptr = FFIGeos.GEOSSTRtree_create_r(Geos.current_handle_pointer, capacity)

  @ptr = FFI::AutoPointer.new(
    ptr,
    self.class.method(:release)
  )

  @storage = {}
  @ptrs = {}

  @storage_key = 0
  @built = false

  return unless geoms_and_objects

  geoms_and_objects.each do |geom, obj|
    insert(geom, obj)
  end
end

Public Instance Methods

built!() click to toggle source
# File lib/ffi-geos/strtree.rb, line 71
def built!
  @built = true
end
built?() click to toggle source
# File lib/ffi-geos/strtree.rb, line 67
def built?
  @built
end
insert(geom, item = nil) click to toggle source
# File lib/ffi-geos/strtree.rb, line 80
def insert(geom, item = nil)
  raise AlreadyBuiltError if built?

  check_geometry(geom)

  key = next_key
  key_ptr = FFI::MemoryPointer.new(:pointer)
  key_ptr.write_int(key)

  @storage[key] = {
    item: item,
    geometry: geom
  }
  @ptrs[key] = key_ptr

  FFIGeos.GEOSSTRtree_insert_r(Geos.current_handle_pointer, ptr, geom.ptr, key_ptr)
end
iterate(&block) click to toggle source
# File lib/ffi-geos/strtree.rb, line 169
def iterate(&block)
  @storage.each_value(&block)
end
nearest(geom) click to toggle source
# File lib/ffi-geos/strtree.rb, line 205
def nearest(geom)
  item = nearest_generic(geom)
  item[:geometry] if item
end
Also aliased as: nearest_geometry
nearest_generic(geom) click to toggle source
# File lib/ffi-geos/strtree.rb, line 174
def nearest_generic(geom)
  check_geometry(geom)

  built!

  return nil if @storage.empty?

  callback = proc { |item, _item_2, distance_ptr|
    key = item.read_int
    geom_from_storage = @storage[key][:geometry]

    next 0 if geom_from_storage.empty?

    distance = geom.distance(geom_from_storage)
    distance_ptr.write_double(distance)

    next 1
  }

  key_ptr = FFIGeos.GEOSSTRtree_nearest_generic_r(
    Geos.current_handle_pointer,
    ptr,
    geom.ptr,
    geom.envelope.ptr,
    callback,
    nil
  )

  @storage[key_ptr.read_int] unless key_ptr.null?
end
nearest_geometry(geom)
Alias for: nearest
nearest_item(geom) click to toggle source
# File lib/ffi-geos/strtree.rb, line 211
def nearest_item(geom)
  item = nearest_generic(geom)
  item[:item] if item
end
query(geom, ret = :item) { |item| ... } click to toggle source
# File lib/ffi-geos/strtree.rb, line 139
def query(geom, ret = :item)
  query_all(geom).collect { |storage|
    item = case ret
      when Array
        storage.inject({}) do |memo, k|
          memo.tap do
            memo[k] = storage[k]
          end
        end
      when :all
        storage
      else
        storage[ret]
    end

    item.tap do
      yield(item) if block_given?
    end
  }.compact
end
query_all(geom) { |storage| ... } click to toggle source
# File lib/ffi-geos/strtree.rb, line 114
def query_all(geom)
  check_geometry(geom)

  built!
  retval = []

  callback = proc { |*args|
    key = args.first.read_int
    storage = @storage[key]
    retval << storage

    yield(storage) if block_given?
  }

  FFIGeos.GEOSSTRtree_query_r(
    Geos.current_handle_pointer,
    ptr,
    geom.ptr,
    callback,
    nil
  )

  retval
end
query_geometries(geom) { |val| ... } click to toggle source
# File lib/ffi-geos/strtree.rb, line 160
def query_geometries(geom)
  query_all(geom).collect { |storage|
    storage[:geometry].tap do |val|
      yield(val) if block_given?
    end
  }.compact
end
Also aliased as: query_geoms
query_geoms(geom)
Alias for: query_geometries
remove(geom, item) click to toggle source
# File lib/ffi-geos/strtree.rb, line 98
def remove(geom, item)
  check_geometry(geom)

  key = if (storage = @storage.detect { |_k, v| v[:item] == item })
    storage[0]
  end

  return unless key

  key_ptr = @ptrs[key]
  result = FFIGeos.GEOSSTRtree_remove_r(Geos.current_handle_pointer, ptr, geom.ptr, key_ptr)
  built!

  @storage.delete(key) if result == 1
end

Private Instance Methods

next_key() click to toggle source
# File lib/ffi-geos/strtree.rb, line 75
def next_key
  @storage_key += 1
end