rgeo-kml 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Version +1 -0
- data/lib/rgeo-kml.rb +7 -0
- data/lib/rgeo/kml.rb +39 -0
- data/lib/rgeo/kml/coder.rb +222 -0
- data/lib/rgeo/kml/coordinates_builder.rb +37 -0
- data/lib/rgeo/kml/entities.rb +275 -0
- data/lib/rgeo/kml/interface.rb +99 -0
- data/lib/rgeo/kml/kml_stream_listener.rb +82 -0
- data/lib/rgeo/kml/line_string_builder.rb +20 -0
- data/lib/rgeo/kml/linear_ring_builder.rb +20 -0
- data/lib/rgeo/kml/multi_geometry_builder.rb +73 -0
- data/lib/rgeo/kml/point_builder.rb +20 -0
- data/lib/rgeo/kml/polygon_builder.rb +26 -0
- data/lib/rgeo/kml/version.rb +26 -0
- data/test/tc_basic_test.rb +328 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 06227b992bdd5a2c5169650431585db1648c8b04
|
4
|
+
data.tar.gz: df4e6c62b71585076ddafef8721e85f770b4f871
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4fb3bb15dd469492f7dda89d9a6141441531e9afa19f3166ba40d253a690ad1b56df2fb212d11276cf3a7979bd1fce0831653bd9f16d42ae1225e0e3a4804c3d
|
7
|
+
data.tar.gz: 786a6e34ea432784590336be029e4e466ea47ad8d3644701ce2693155953edfcd2a1afb4daf6581525ec9f4577d70fe097230377db22f71fb2f26b6e0533bfba
|
data/Version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/rgeo-kml.rb
ADDED
data/lib/rgeo/kml.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Kml implementation for RGeo
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
|
7
|
+
# Dependencies
|
8
|
+
require 'rgeo'
|
9
|
+
|
10
|
+
# RGeo is a spatial data library for Ruby, provided by the "rgeo" gem.
|
11
|
+
#
|
12
|
+
# The optional RGeo::GeoJSON module provides a set of tools for GeoJSON
|
13
|
+
# encoding and decoding.
|
14
|
+
|
15
|
+
module RGeo
|
16
|
+
|
17
|
+
|
18
|
+
# This is a namespace for a set of tools that provide KML encoding.
|
19
|
+
# See https://developers.google.com/kml/documentation/ for more information about this specification.
|
20
|
+
|
21
|
+
module Kml
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Implementation files
|
29
|
+
require 'rgeo/kml/version'
|
30
|
+
require 'rgeo/kml/entities'
|
31
|
+
require 'rgeo/kml/coder'
|
32
|
+
require 'rgeo/kml/interface'
|
33
|
+
require 'rgeo/kml/kml_stream_listener'
|
34
|
+
require 'rgeo/kml/coordinates_builder'
|
35
|
+
require 'rgeo/kml/point_builder'
|
36
|
+
require 'rgeo/kml/line_string_builder'
|
37
|
+
require 'rgeo/kml/linear_ring_builder'
|
38
|
+
require 'rgeo/kml/polygon_builder'
|
39
|
+
require 'rgeo/kml/multi_geometry_builder'
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Kml encoder object
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
|
7
|
+
require "rexml/document"
|
8
|
+
require 'rexml/parsers/pullparser'
|
9
|
+
|
10
|
+
module RGeo
|
11
|
+
|
12
|
+
module Kml
|
13
|
+
|
14
|
+
|
15
|
+
# This object encapsulates encoding and decoding settings (principally
|
16
|
+
# the RGeo::Feature::Factory and the RGeo::Kml::EntityFactory to
|
17
|
+
# be used) so that you can encode and decode without specifying those
|
18
|
+
# settings every time.
|
19
|
+
|
20
|
+
class Coder
|
21
|
+
|
22
|
+
ELEMENT_MAP = {
|
23
|
+
'Point' => "point",
|
24
|
+
'LineString' => "line_string",
|
25
|
+
'LinearRing' => "linear_ring",
|
26
|
+
'Polygon' => "polygon",
|
27
|
+
'MultiGeometry' => "geometry_collection"
|
28
|
+
}
|
29
|
+
|
30
|
+
@@kml_available = nil
|
31
|
+
@@activesupport_available = nil
|
32
|
+
|
33
|
+
|
34
|
+
# Create a new coder settings object. The geo factory is passed as
|
35
|
+
# a required argument.
|
36
|
+
#
|
37
|
+
# Options include:
|
38
|
+
#
|
39
|
+
# [<tt>:geo_factory</tt>]
|
40
|
+
# Specifies the geo factory to use to create geometry objects.
|
41
|
+
# Defaults to the preferred cartesian factory.
|
42
|
+
# [<tt>:entity_factory</tt>]
|
43
|
+
# Specifies an entity factory, which lets you override the types
|
44
|
+
# of Kml entities that are created. It defaults to the default
|
45
|
+
# RGeo::Kml::EntityFactory, which generates objects of type
|
46
|
+
# RGeo::Kml::Feature or RGeo::Kml::FeatureCollection.
|
47
|
+
# See RGeo::Kml::EntityFactory for more information.
|
48
|
+
|
49
|
+
def initialize(opts_={})
|
50
|
+
@geo_factory = opts_[:geo_factory] || ::RGeo::Cartesian.preferred_factory
|
51
|
+
@entity_factory = opts_[:entity_factory] || EntityFactory.instance
|
52
|
+
@buffer = ''
|
53
|
+
|
54
|
+
@num_coordinates = 2
|
55
|
+
@num_coordinates += 1 if @geo_factory.property(:has_z_coordinate)
|
56
|
+
@num_coordinates += 1 if @geo_factory.property(:has_m_coordinate)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Encode the given object as Kml. The object may be one of the
|
61
|
+
# geometry objects specified in RGeo::Feature, or an appropriate
|
62
|
+
# Kml wrapper entity supported by this coder's entity factory.
|
63
|
+
#
|
64
|
+
# This method returns a KML object (xml with Placemark).
|
65
|
+
#
|
66
|
+
# Returns nil if nil is passed in as the object.
|
67
|
+
|
68
|
+
def encode(object_)
|
69
|
+
if @entity_factory.is_feature_collection?(object_)
|
70
|
+
{
|
71
|
+
'type' => 'FeatureCollection',
|
72
|
+
'features' => @entity_factory.map_feature_collection(object_){ |f_| _encode_feature(f_) },
|
73
|
+
}
|
74
|
+
elsif @entity_factory.is_feature?(object_)
|
75
|
+
_encode_feature(object_)
|
76
|
+
elsif object_.nil?
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
_encode_geometry(object_)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Returns the RGeo::Feature::Factory used to generate geometry objects.
|
85
|
+
|
86
|
+
def geo_factory
|
87
|
+
@geo_factory
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# Returns the RGeo::Kml::EntityFactory used to generate Kml
|
92
|
+
# wrapper entities.
|
93
|
+
|
94
|
+
def entity_factory
|
95
|
+
@entity_factory
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def _encode_feature(object_) # :nodoc:
|
100
|
+
id_ = @entity_factory.get_feature_id(object_)
|
101
|
+
kml_ = '<?xml version="1.0" encoding="UTF-8"?>\n'
|
102
|
+
kml_ += '<kml xmlns="http://www.opengis.net/kml/2.2">\n'
|
103
|
+
kml_ += "<Document>"
|
104
|
+
kml_ += "<name>Kml File</name>"
|
105
|
+
kml_ += "<Placemark id="#{id_}">\n"
|
106
|
+
kml_ += _encode_geometry(@entity_factory.get_feature_geometry(object_))
|
107
|
+
kml_ += "</Placemark>\n"
|
108
|
+
kml_ += "</Document>"
|
109
|
+
kml_ += "</kml>"
|
110
|
+
|
111
|
+
# 'properties' => @entity_factory.get_feature_properties(object_).dup,
|
112
|
+
# id_ = @entity_factory.get_feature_id(object_)
|
113
|
+
# json_['id'] = id_ if id_
|
114
|
+
kml_
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
def _encode_geometry(object_, point_encoder_=nil) # :nodoc:
|
119
|
+
unless point_encoder_
|
120
|
+
if object_.factory.property(:has_z_coordinate)
|
121
|
+
if object_.factory.property(:has_m_coordinate)
|
122
|
+
point_encoder_ = ::Proc.new{ |p_| [p_.x, p_.y, p_.z, p_.m].join(",") }
|
123
|
+
else
|
124
|
+
point_encoder_ = ::Proc.new{ |p_| [p_.x, p_.y, p_.z].join(",") }
|
125
|
+
end
|
126
|
+
else
|
127
|
+
if object_.factory.property(:has_m_coordinate)
|
128
|
+
point_encoder_ = ::Proc.new{ |p_| [p_.x, p_.y, p_.m].join(",") }
|
129
|
+
else
|
130
|
+
point_encoder_ = ::Proc.new{ |p_| [p_.x, p_.y].join(",") }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
case object_
|
135
|
+
when ::RGeo::Feature::Point
|
136
|
+
result = "<Point>\n"
|
137
|
+
#result += options[:geom_data] if options[:geom_data]
|
138
|
+
result += "<coordinates>" + point_encoder_.call(object_)
|
139
|
+
result += "</coordinates>\n"
|
140
|
+
result += "</Point>\n"
|
141
|
+
when ::RGeo::Feature::LineString
|
142
|
+
result = "<LineString>\n"
|
143
|
+
#result += options[:geom_data] if options[:geom_data]
|
144
|
+
result += "<coordinates>\n"
|
145
|
+
result += object_.points.map(&point_encoder_).join("\n")
|
146
|
+
result += "\n</coordinates>\n"
|
147
|
+
result += "</LineString>\n"
|
148
|
+
when ::RGeo::Feature::Polygon
|
149
|
+
result = "<Polygon>\n"
|
150
|
+
#result += options[:geom_data] if options[:geom_data]
|
151
|
+
result += "<outerBoundaryIs><LinearRing><coordinates>\n"
|
152
|
+
result += object_.exterior_ring.points.map(&point_encoder_).join("\n")
|
153
|
+
result += "\n</coordinates></LinearRing></outerBoundaryIs>\n"
|
154
|
+
object_.interior_rings.each do |interior_ring|
|
155
|
+
result += "<innerBoundaryIs><LinearRing><coordinates>\n"
|
156
|
+
result += interior_ring.points.map(&point_encoder_).join("\n")
|
157
|
+
result += "\n</coordinates></LinearRing></innerBoundaryIs>\n"
|
158
|
+
end
|
159
|
+
result += "</Polygon>\n"
|
160
|
+
when ::RGeo::Feature::MultiPoint
|
161
|
+
result = "<MultiGeometry>\n"
|
162
|
+
object_.each do |geometry|
|
163
|
+
result += "<Point>\n<coordinates>"
|
164
|
+
#options[:id_attr] = "" #the subgeometries do not have an ID
|
165
|
+
result += point_encoder_.call(geometry)
|
166
|
+
result += "</coordinates>\n</Point>\n"
|
167
|
+
end
|
168
|
+
result += "</MultiGeometry>\n"
|
169
|
+
when ::RGeo::Feature::MultiLineString
|
170
|
+
result = "<MultiGeometry>\n"
|
171
|
+
object_.each do |geometry|
|
172
|
+
#options[:id_attr] = "" #the subgeometries do not have an ID
|
173
|
+
result += "<LineString>\n"
|
174
|
+
#result += options[:geom_data] if options[:geom_data]
|
175
|
+
result += "<coordinates>\n"
|
176
|
+
result += geometry.points.map(&point_encoder_).join("\n")
|
177
|
+
result += "\n</coordinates>\n"
|
178
|
+
result += "</LineString>\n"
|
179
|
+
end
|
180
|
+
result += "</MultiGeometry>\n"
|
181
|
+
when ::RGeo::Feature::MultiPolygon
|
182
|
+
result = "<MultiGeometry>\n"
|
183
|
+
object_.each do |geometry|
|
184
|
+
#options[:id_attr] = "" #the subgeometries do not have an ID
|
185
|
+
result += "<Polygon>\n"
|
186
|
+
#result += options[:geom_data] if options[:geom_data]
|
187
|
+
result += "<outerBoundaryIs><LinearRing><coordinates>\n"
|
188
|
+
result += geometry.exterior_ring.points.map(&point_encoder_).join("\n")
|
189
|
+
result += "\n</coordinates></LinearRing></outerBoundaryIs>\n"
|
190
|
+
geometry.interior_rings.each do |interior_ring|
|
191
|
+
result += "<innerBoundaryIs><LinearRing><coordinates>\n"
|
192
|
+
result += interior_ring.points.map(&point_encoder_).join("\n")
|
193
|
+
result += "\n</coordinates></LinearRing></innerBoundaryIs>\n"
|
194
|
+
end
|
195
|
+
result += "</Polygon>\n"
|
196
|
+
end
|
197
|
+
result += "</MultiGeometry>\n"
|
198
|
+
when ::RGeo::Feature::GeometryCollection
|
199
|
+
result = "<MultiGeometry>\n"
|
200
|
+
#options[:id_attr] = "" #the subgeometries do not have an ID
|
201
|
+
result += object_.map{ |geom_| _encode_geometry(geom_, point_encoder_) }.join("")
|
202
|
+
result += "</MultiGeometry>\n"
|
203
|
+
else
|
204
|
+
nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
# Decode an object from Kml. The input may a
|
210
|
+
# String, or an IO object from which to read the KML string.
|
211
|
+
# If an error occurs, nil is returned.
|
212
|
+
def decode(input_)
|
213
|
+
@kml_stream_listener = KmlStreamListener.new(geo_factory)
|
214
|
+
@kml_stream_listener.parse(input_)
|
215
|
+
@kml_stream_listener.result
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RGeo
|
2
|
+
module Kml
|
3
|
+
|
4
|
+
class CoordinatesBuilder
|
5
|
+
attr_reader :geo_factory, :parent, :points
|
6
|
+
attr_accessor :text
|
7
|
+
|
8
|
+
def initialize( geo_factory, parent)
|
9
|
+
@geo_factory = geo_factory
|
10
|
+
@parent = parent
|
11
|
+
@points = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def build
|
15
|
+
@text.gsub(/\n/, ' ').strip.split(/\s+/).each do |coord|
|
16
|
+
x, y, z = coord.split(',')
|
17
|
+
if x.nil? || y.nil?
|
18
|
+
fail StandardError, 'Coordinates must have at least x and y elements'
|
19
|
+
end
|
20
|
+
if z.nil?
|
21
|
+
@points << @geo_factory.point(x, y)
|
22
|
+
else
|
23
|
+
@points << @geo_factory.point(x, y, z)
|
24
|
+
end
|
25
|
+
|
26
|
+
@points
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue Exception => e
|
30
|
+
puts "Exception #{e.message} \n #{e.backtrace}"
|
31
|
+
raise StandardError, 'Error parsing coordinates: check your kml for errors'
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,275 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Kml standard entities
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
|
7
|
+
|
8
|
+
module RGeo
|
9
|
+
|
10
|
+
module Kml
|
11
|
+
|
12
|
+
|
13
|
+
# This is a Kml wrapper entity that corresponds to the Kml
|
14
|
+
# "Feature" type. It is an immutable type.
|
15
|
+
#
|
16
|
+
# This is the default implementation that is generated by
|
17
|
+
# RGeo::Kml::EntityFactory. You may replace this implementation
|
18
|
+
# by writing your own entity factory. Note that an alternate Feature
|
19
|
+
# implementation need not subclass or even duck-type this class.
|
20
|
+
# the entity factory mediates all interaction between the Kml
|
21
|
+
# engine and features.
|
22
|
+
|
23
|
+
class Feature
|
24
|
+
|
25
|
+
|
26
|
+
# Create a feature wrapping the given geometry, with the given ID
|
27
|
+
# and properties.
|
28
|
+
|
29
|
+
def initialize(geometry_, id_=nil, properties_={})
|
30
|
+
@geometry = geometry_
|
31
|
+
@id = id_
|
32
|
+
@properties = {}
|
33
|
+
properties_.each do |k_, v_|
|
34
|
+
@properties[k_.to_s] = v_
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def inspect # :nodoc:
|
40
|
+
"#<#{self.class}:0x#{object_id.to_s(16)} id=#{@id.inspect} geom=#{@geometry ? @geometry.as_text.inspect : 'nil'}>"
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s # :nodoc:
|
44
|
+
inspect
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash # :nodoc:
|
48
|
+
@geometry.hash + @id.hash + @properties.hash
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Two features are equal if their geometries, IDs, and properties
|
53
|
+
# are all equal.
|
54
|
+
# This method uses the eql? method to test geometry equality, which
|
55
|
+
# may behave differently than the == operator.
|
56
|
+
|
57
|
+
def eql?(rhs_)
|
58
|
+
rhs_.kind_of?(Feature) && @geometry.eql?(rhs_.geometry) && @id.eql?(rhs_.feature_id) && @properties.eql?(rhs_.instance_variable_get(:@properties))
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# Two features are equal if their geometries, IDs, and properties
|
63
|
+
# are all equal.
|
64
|
+
# This method uses the == operator to test geometry equality, which
|
65
|
+
# may behave differently than the eql? method.
|
66
|
+
|
67
|
+
def ==(rhs_)
|
68
|
+
rhs_.kind_of?(Feature) && @geometry == rhs_.geometry && @id == rhs_.feature_id && @properties == rhs_.instance_variable_get(:@properties)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Returns the geometry contained in this feature, which may be nil.
|
73
|
+
|
74
|
+
def geometry
|
75
|
+
@geometry
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Returns the ID for this feature, which may be nil.
|
80
|
+
|
81
|
+
def feature_id
|
82
|
+
@id
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# Returns a copy of the properties for this feature.
|
87
|
+
|
88
|
+
def properties
|
89
|
+
@properties.dup
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Gets the value of the given named property.
|
94
|
+
# Returns nil if the given property is not found.
|
95
|
+
|
96
|
+
def property(key_)
|
97
|
+
@properties[key_.to_s]
|
98
|
+
end
|
99
|
+
alias_method :[], :property
|
100
|
+
|
101
|
+
|
102
|
+
# Gets an array of the known property keys in this feature.
|
103
|
+
|
104
|
+
def keys
|
105
|
+
@properties.keys
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
# This is a Kml wrapper entity that corresponds to the Kml
|
113
|
+
# "FeatureCollection" type. It is an immutable type.
|
114
|
+
#
|
115
|
+
# This is the default implementation that is generated by
|
116
|
+
# RGeo::Kml::EntityFactory. You may replace this implementation
|
117
|
+
# by writing your own entity factory. Note that an alternate
|
118
|
+
# FeatureCollection implementation need not subclass or even
|
119
|
+
# duck-type this class. The entity factory mediates all interaction
|
120
|
+
# between the Kml engine and feature collections.
|
121
|
+
|
122
|
+
class FeatureCollection
|
123
|
+
|
124
|
+
include ::Enumerable
|
125
|
+
|
126
|
+
|
127
|
+
# Create a new FeatureCollection with the given features, which must
|
128
|
+
# be provided as an Enumerable.
|
129
|
+
|
130
|
+
def initialize(features_=[])
|
131
|
+
@features = []
|
132
|
+
features_.each{ |f_| @features << f_ if f_.kind_of?(Feature) }
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
def inspect # :nodoc:
|
137
|
+
"#<#{self.class}:0x#{object_id.to_s(16)}>"
|
138
|
+
end
|
139
|
+
|
140
|
+
def to_s # :nodoc:
|
141
|
+
inspect
|
142
|
+
end
|
143
|
+
|
144
|
+
def hash # :nodoc:
|
145
|
+
@features.hash
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
# Two feature collections are equal if they contain the same
|
150
|
+
# features in the same order.
|
151
|
+
# This methods uses the eql? method to test geometry equality, which
|
152
|
+
# may behave differently than the == operator.
|
153
|
+
|
154
|
+
def eql?(rhs_)
|
155
|
+
rhs_.kind_of?(FeatureCollection) && @features.eql?(rhs_.instance_variable_get(:@features))
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
# Two feature collections are equal if they contain the same
|
160
|
+
# features in the same order.
|
161
|
+
# This methods uses the == operator to test geometry equality, which
|
162
|
+
# may behave differently than the eql? method.
|
163
|
+
|
164
|
+
def ==(rhs_)
|
165
|
+
rhs_.kind_of?(FeatureCollection) && @features == rhs_.instance_variable_get(:@features)
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
# Iterates or returns an iterator for the features.
|
170
|
+
|
171
|
+
def each(&block_)
|
172
|
+
@features.each(&block_)
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# Returns the number of features contained in this collection.
|
177
|
+
|
178
|
+
def size
|
179
|
+
@features.size
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
# Access a feature by index.
|
184
|
+
|
185
|
+
def [](index_)
|
186
|
+
@features[index_]
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
# This is the default entity factory. It creates objects of type
|
194
|
+
# RGeo::Kml::Feature and RGeo::Kml::FeatureCollection.
|
195
|
+
# You may create your own entity factory by duck-typing this class.
|
196
|
+
|
197
|
+
class EntityFactory
|
198
|
+
|
199
|
+
|
200
|
+
# Create and return a new feature, given geometry, ID, and
|
201
|
+
# properties hash. Note that, per the Kml spec, geometry and/or
|
202
|
+
# properties may be nil.
|
203
|
+
|
204
|
+
def feature(geometry_, id_=nil, properties_=nil)
|
205
|
+
Feature.new(geometry_, id_, properties_ || {})
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
# Create and return a new feature collection, given an enumerable
|
210
|
+
# of feature objects.
|
211
|
+
|
212
|
+
def feature_collection(features_=[])
|
213
|
+
FeatureCollection.new(features_)
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
# Returns true if the given object is a feature created by this
|
218
|
+
# entity factory.
|
219
|
+
|
220
|
+
def is_feature?(object_)
|
221
|
+
object_.kind_of?(Feature)
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
# Returns true if the given object is a feature collection created
|
226
|
+
# by this entity factory.
|
227
|
+
|
228
|
+
def is_feature_collection?(object_)
|
229
|
+
object_.kind_of?(FeatureCollection)
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
# Run Enumerable#map on the features contained in the given feature
|
234
|
+
# collection.
|
235
|
+
|
236
|
+
def map_feature_collection(object_, &block_)
|
237
|
+
object_.map(&block_)
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
# Returns the geometry associated with the given feature.
|
242
|
+
|
243
|
+
def get_feature_geometry(object_)
|
244
|
+
object_.geometry
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
# Returns the ID of the given feature, or nil for no ID.
|
249
|
+
|
250
|
+
def get_feature_id(object_)
|
251
|
+
object_.feature_id
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
# Returns the properties of the given feature as a hash. Editing
|
256
|
+
# this hash does not change the state of the feature.
|
257
|
+
|
258
|
+
def get_feature_properties(object_)
|
259
|
+
object_.properties
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
# Return the singleton instance of EntityFactory.
|
264
|
+
|
265
|
+
def self.instance
|
266
|
+
@instance ||= self.new
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|