lib/rgeo/kml/entities.rb
# -----------------------------------------------------------------------------
#
# Kml standard entities
#
# -----------------------------------------------------------------------------
module RGeo
module Kml
# This is a Kml wrapper entity that corresponds to the Kml
# "Feature" type. It is an immutable type.
#
# This is the default implementation that is generated by
# RGeo::Kml::EntityFactory. You may replace this implementation
# by writing your own entity factory. Note that an alternate Feature
# implementation need not subclass or even duck-type this class.
# the entity factory mediates all interaction between the Kml
# engine and features.
class Feature
# Create a feature wrapping the given geometry, with the given ID
# and properties.
def initialize(geometry_, id_=nil, properties_={})
@geometry = geometry_
@id = id_
@properties = {}
properties_.each do |k_, v_|
@properties[k_.to_s] = v_
end
end
def inspect # :nodoc:
"#<#{self.class}:0x#{object_id.to_s(16)} id=#{@id.inspect} geom=#{@geometry ? @geometry.as_text.inspect : 'nil'}>"
end
def to_s # :nodoc:
inspect
end
def hash # :nodoc:
@geometry.hash + @id.hash + @properties.hash
end
# Two features are equal if their geometries, IDs, and properties
# are all equal.
# This method uses the eql? method to test geometry equality, which
# may behave differently than the == operator.
def eql?(rhs_)
rhs_.kind_of?(Feature) && @geometry.eql?(rhs_.geometry) && @id.eql?(rhs_.feature_id) && @properties.eql?(rhs_.instance_variable_get(:@properties))
end
# Two features are equal if their geometries, IDs, and properties
# are all equal.
# This method uses the == operator to test geometry equality, which
# may behave differently than the eql? method.
def ==(rhs_)
rhs_.kind_of?(Feature) && @geometry == rhs_.geometry && @id == rhs_.feature_id && @properties == rhs_.instance_variable_get(:@properties)
end
# Returns the geometry contained in this feature, which may be nil.
def geometry
@geometry
end
# Returns the ID for this feature, which may be nil.
def feature_id
@id
end
# Returns a copy of the properties for this feature.
def properties
@properties.dup
end
# Gets the value of the given named property.
# Returns nil if the given property is not found.
def property(key_)
@properties[key_.to_s]
end
alias_method :[], :property
# Gets an array of the known property keys in this feature.
def keys
@properties.keys
end
end
# This is a Kml wrapper entity that corresponds to the Kml
# "FeatureCollection" type. It is an immutable type.
#
# This is the default implementation that is generated by
# RGeo::Kml::EntityFactory. You may replace this implementation
# by writing your own entity factory. Note that an alternate
# FeatureCollection implementation need not subclass or even
# duck-type this class. The entity factory mediates all interaction
# between the Kml engine and feature collections.
class FeatureCollection
include ::Enumerable
# Create a new FeatureCollection with the given features, which must
# be provided as an Enumerable.
def initialize(features_=[])
@features = []
features_.each{ |f_| @features << f_ if f_.kind_of?(Feature) }
end
def inspect # :nodoc:
"#<#{self.class}:0x#{object_id.to_s(16)}>"
end
def to_s # :nodoc:
inspect
end
def hash # :nodoc:
@features.hash
end
# Two feature collections are equal if they contain the same
# features in the same order.
# This methods uses the eql? method to test geometry equality, which
# may behave differently than the == operator.
def eql?(rhs_)
rhs_.kind_of?(FeatureCollection) && @features.eql?(rhs_.instance_variable_get(:@features))
end
# Two feature collections are equal if they contain the same
# features in the same order.
# This methods uses the == operator to test geometry equality, which
# may behave differently than the eql? method.
def ==(rhs_)
rhs_.kind_of?(FeatureCollection) && @features == rhs_.instance_variable_get(:@features)
end
# Iterates or returns an iterator for the features.
def each(&block_)
@features.each(&block_)
end
# Returns the number of features contained in this collection.
def size
@features.size
end
# Access a feature by index.
def [](index_)
@features[index_]
end
end
# This is the default entity factory. It creates objects of type
# RGeo::Kml::Feature and RGeo::Kml::FeatureCollection.
# You may create your own entity factory by duck-typing this class.
class EntityFactory
# Create and return a new feature, given geometry, ID, and
# properties hash. Note that, per the Kml spec, geometry and/or
# properties may be nil.
def feature(geometry_, id_=nil, properties_=nil)
Feature.new(geometry_, id_, properties_ || {})
end
# Create and return a new feature collection, given an enumerable
# of feature objects.
def feature_collection(features_=[])
FeatureCollection.new(features_)
end
# Returns true if the given object is a feature created by this
# entity factory.
def is_feature?(object_)
object_.kind_of?(Feature)
end
# Returns true if the given object is a feature collection created
# by this entity factory.
def is_feature_collection?(object_)
object_.kind_of?(FeatureCollection)
end
# Run Enumerable#map on the features contained in the given feature
# collection.
def map_feature_collection(object_, &block_)
object_.map(&block_)
end
# Returns the geometry associated with the given feature.
def get_feature_geometry(object_)
object_.geometry
end
# Returns the ID of the given feature, or nil for no ID.
def get_feature_id(object_)
object_.feature_id
end
# Returns the properties of the given feature as a hash. Editing
# this hash does not change the state of the feature.
def get_feature_properties(object_)
object_.properties
end
# Return the singleton instance of EntityFactory.
def self.instance
@instance ||= self.new
end
end
end
end