schleyfox-ruby_kml 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/LICENSE +7 -0
- data/README.textile +31 -0
- data/Rakefile +134 -0
- data/examples/melbourne-stations.kml +18 -0
- data/lib/kml/color_style.rb +34 -0
- data/lib/kml/container.rb +16 -0
- data/lib/kml/document.rb +26 -0
- data/lib/kml/feature.rb +161 -0
- data/lib/kml/folder.rb +12 -0
- data/lib/kml/geometry.rb +86 -0
- data/lib/kml/ground_overlay.rb +18 -0
- data/lib/kml/hot_spot.rb +31 -0
- data/lib/kml/icon.rb +15 -0
- data/lib/kml/icon_style.rb +52 -0
- data/lib/kml/lat_lon_box.rb +36 -0
- data/lib/kml/line_string.rb +40 -0
- data/lib/kml/line_style.rb +15 -0
- data/lib/kml/linear_ring.rb +49 -0
- data/lib/kml/link.rb +51 -0
- data/lib/kml/look_at.rb +21 -0
- data/lib/kml/model.rb +4 -0
- data/lib/kml/multi_geometry.rb +5 -0
- data/lib/kml/object.rb +29 -0
- data/lib/kml/overlay.rb +20 -0
- data/lib/kml/placemark.rb +36 -0
- data/lib/kml/point.rb +47 -0
- data/lib/kml/poly_style.rb +16 -0
- data/lib/kml/polygon.rb +44 -0
- data/lib/kml/snippet.rb +25 -0
- data/lib/kml/style.rb +23 -0
- data/lib/kml/style_map.rb +39 -0
- data/lib/kml/style_selector.rb +7 -0
- data/lib/kml/version.rb +9 -0
- data/lib/kml.rb +7 -0
- data/lib/kml_file.rb +28 -0
- data/test/kml/point_test.rb +10 -0
- data/test/kml_file_test.rb +220 -0
- data/test/test_helper.rb +23 -0
- metadata +93 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2006-2007 Anthony Eden
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Library for generating KML(Keyhole Markup Language) files in Ruby.
|
2
|
+
Sweet if you want to place markers, overlays, and other awesome things over a google map or google earth.
|
3
|
+
|
4
|
+
h2. Install
|
5
|
+
|
6
|
+
<pre><code>gem install xaviershay-ruby_kml --source http://gems.github.com</code></pre>
|
7
|
+
|
8
|
+
h2. Examples
|
9
|
+
|
10
|
+
See @test/kml_file_test.rb@ for more examples
|
11
|
+
|
12
|
+
h3. Placing markers on a map
|
13
|
+
|
14
|
+
"View on Google Maps":http://maps.google.com/maps?q=http://github.com/xaviershay/ruby_kml/tree/master%2Fexamples%2Fmelbourne-stations.kml?raw=true&t=k
|
15
|
+
|
16
|
+
<pre><code>require 'kml'
|
17
|
+
|
18
|
+
kml = KMLFile.new
|
19
|
+
folder = KML::Folder.new(:name => 'Melbourne Stations')
|
20
|
+
[
|
21
|
+
["Flinders St", -37.818078, 144.966811],
|
22
|
+
["Southern Cross", -37.818358, 144.952417],
|
23
|
+
].each do |name, lat, lng|
|
24
|
+
folder.features << KML::Placemark.new(
|
25
|
+
:name => name,
|
26
|
+
:geometry => KML::Point.new(:coordinates => {:lat => lat, :lng => lng})
|
27
|
+
)
|
28
|
+
end
|
29
|
+
kml.objects << folder
|
30
|
+
puts kml.render
|
31
|
+
</code></pre>
|
data/Rakefile
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/packagetask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require 'rake/contrib/rubyforgepublisher'
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'lib/kml', 'version')
|
9
|
+
|
10
|
+
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
11
|
+
PKG_NAME = 'kmlr'
|
12
|
+
PKG_VERSION = KML::VERSION::STRING + PKG_BUILD
|
13
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
14
|
+
PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
|
15
|
+
|
16
|
+
RELEASE_NAME = "REL #{PKG_VERSION}"
|
17
|
+
|
18
|
+
RUBY_FORGE_PROJECT = "kmlr"
|
19
|
+
RUBY_FORGE_USER = "aeden"
|
20
|
+
|
21
|
+
desc 'Default: run unit tests.'
|
22
|
+
task :default => :test
|
23
|
+
|
24
|
+
desc 'Test the library.'
|
25
|
+
Rake::TestTask.new(:test) do |t|
|
26
|
+
t.libs << 'lib'
|
27
|
+
t.pattern = 'test/**/*_test.rb'
|
28
|
+
t.verbose = true
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Clean up after tests.'
|
32
|
+
task :clean_tests do
|
33
|
+
FileList['test/*.kml'].each do |f|
|
34
|
+
File.unlink(f)
|
35
|
+
puts "Deleting #{f}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'Generate documentation for the library.'
|
40
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = 'KMLr'
|
43
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
44
|
+
rdoc.rdoc_files.include('README')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
47
|
+
|
48
|
+
PKG_FILES = FileList[
|
49
|
+
'CHANGELOG',
|
50
|
+
'README',
|
51
|
+
'TODO',
|
52
|
+
'Rakefile',
|
53
|
+
'bin/**/*',
|
54
|
+
'doc/**/*',
|
55
|
+
'lib/**/*',
|
56
|
+
] - [ 'test' ]
|
57
|
+
|
58
|
+
spec = Gem::Specification.new do |s|
|
59
|
+
s.name = 'kmlr'
|
60
|
+
s.version = PKG_VERSION
|
61
|
+
s.summary = "Library to product KML files."
|
62
|
+
s.description = <<-EOF
|
63
|
+
KMLr is a Ruby library which can be used to construct Keyhole Markup Language files.
|
64
|
+
EOF
|
65
|
+
|
66
|
+
s.add_dependency('rake', '>= 0.7.1')
|
67
|
+
|
68
|
+
s.rdoc_options << '--exclude' << '.'
|
69
|
+
s.has_rdoc = false
|
70
|
+
|
71
|
+
s.files = PKG_FILES.to_a.delete_if {|f| f.include?('.svn')}
|
72
|
+
s.require_path = 'lib'
|
73
|
+
|
74
|
+
s.author = "Anthony Eden"
|
75
|
+
s.email = "anthonyeden@gmail.com"
|
76
|
+
s.homepage = "http://kmlr.rubyforge.org/"
|
77
|
+
s.rubyforge_project = "kmlr"
|
78
|
+
end
|
79
|
+
|
80
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
81
|
+
pkg.gem_spec = spec
|
82
|
+
pkg.need_tar = true
|
83
|
+
pkg.need_zip = true
|
84
|
+
end
|
85
|
+
|
86
|
+
desc "Generate code statistics"
|
87
|
+
task :lines do
|
88
|
+
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
|
89
|
+
|
90
|
+
for file_name in FileList["lib/**/*.rb"]
|
91
|
+
next if file_name =~ /vendor/
|
92
|
+
f = File.open(file_name)
|
93
|
+
|
94
|
+
while line = f.gets
|
95
|
+
lines += 1
|
96
|
+
next if line =~ /^\s*$/
|
97
|
+
next if line =~ /^\s*#/
|
98
|
+
codelines += 1
|
99
|
+
end
|
100
|
+
puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
|
101
|
+
|
102
|
+
total_lines += lines
|
103
|
+
total_codelines += codelines
|
104
|
+
|
105
|
+
lines, codelines = 0, 0
|
106
|
+
end
|
107
|
+
|
108
|
+
puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
|
109
|
+
end
|
110
|
+
|
111
|
+
desc "Publish the release files to RubyForge."
|
112
|
+
task :release => [ :package ] do
|
113
|
+
`rubyforge login`
|
114
|
+
|
115
|
+
for ext in %w( gem tgz zip )
|
116
|
+
release_command = "rubyforge add_release kmlr #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}"
|
117
|
+
puts release_command
|
118
|
+
system(release_command)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
desc "Publish the API documentation"
|
123
|
+
task :pdoc => [:rdoc] do
|
124
|
+
Rake::SshDirPublisher.new("aeden@rubyforge.org", "/var/www/gforge-projects/kmlr/rdoc", "rdoc").upload
|
125
|
+
end
|
126
|
+
|
127
|
+
desc "Reinstall the gem from a local package copy"
|
128
|
+
task :reinstall => [:package] do
|
129
|
+
windows = RUBY_PLATFORM =~ /mswin/
|
130
|
+
sudo = windows ? '' : 'sudo'
|
131
|
+
gem = windows ? 'gem.bat' : 'gem'
|
132
|
+
`#{sudo} #{gem} uninstall -x -i #{PKG_NAME}`
|
133
|
+
`#{sudo} #{gem} install pkg/#{PKG_NAME}-#{PKG_VERSION}`
|
134
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<kml xmlns="http://earth.google.com/kml/2.1">
|
3
|
+
<Folder>
|
4
|
+
<name>Melbourne Stations</name>
|
5
|
+
<Placemark>
|
6
|
+
<name>Flinders St</name>
|
7
|
+
<Point>
|
8
|
+
<coordinates>144.966811,-37.818078</coordinates>
|
9
|
+
</Point>
|
10
|
+
</Placemark>
|
11
|
+
<Placemark>
|
12
|
+
<name>Southern Cross</name>
|
13
|
+
<Point>
|
14
|
+
<coordinates>144.952417,-37.818358</coordinates>
|
15
|
+
</Point>
|
16
|
+
</Placemark>
|
17
|
+
</Folder>
|
18
|
+
</kml>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module KML #:nodoc:
|
2
|
+
# Base class for specifying the color and color mode of extended style types.
|
3
|
+
class ColorStyle < KML::Object
|
4
|
+
# Color and opacity (alpha) values are expressed in hexadecimal notation. The range of values for any one color
|
5
|
+
# is 0 to 255 (00 to ff). For alpha, 00 is fully transparent and ff is fully opaque. The order of expression is
|
6
|
+
# aabbggrr, where aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff); rr=red (00 to ff). For example,
|
7
|
+
# if you want to apply a blue color with 50 percent opacity to an overlay, you would specify the following:
|
8
|
+
#
|
9
|
+
# style.color = '7fff0000'
|
10
|
+
#
|
11
|
+
# where alpha=0x7f, blue=0xff, green=0x00, and red=0x00.
|
12
|
+
attr_accessor :color
|
13
|
+
|
14
|
+
# Values for +color_mode+ are normal (no effect) and random. A value of random applies a random linear scale to
|
15
|
+
# the base +color+ as follows.
|
16
|
+
#
|
17
|
+
# * To achieve a truly random selection of colors, specify a base +color+ of white (ffffffff).
|
18
|
+
# * If you specify a single color component (for example, a value of ff0000ff for red), random color values for
|
19
|
+
# that one component (red) will be selected. In this case, the values would range from 00 (black) to ff (full red).
|
20
|
+
# * If you specify values for two or for all three color components, a random linear scale is applied to each color
|
21
|
+
# component, with results ranging from black to the maximum values specified for each component.
|
22
|
+
# * The opacity of a color comes from the alpha component of <color> and is never randomized.
|
23
|
+
attr_accessor :color_mode
|
24
|
+
|
25
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
26
|
+
xm.color(color) unless color.nil?
|
27
|
+
xm.colorMode(color_mode) unless color_mode.nil?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'kml/line_style'
|
33
|
+
require 'kml/poly_style'
|
34
|
+
require 'kml/icon_style'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module KML
|
2
|
+
# A Container is an abstract base class that holds one or more Features and allows the creation of nested hierarchies.
|
3
|
+
class Container < Feature
|
4
|
+
|
5
|
+
# Access the features in the container
|
6
|
+
attr_accessor :features
|
7
|
+
|
8
|
+
# Get the features in the container
|
9
|
+
def features
|
10
|
+
@features ||= []
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'kml/folder'
|
16
|
+
require 'kml/document'
|
data/lib/kml/document.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module KML #:nodoc:
|
2
|
+
# A document contains 0 or more features and 0 or more schemas.
|
3
|
+
class Document < Container
|
4
|
+
attr_accessor :schemas
|
5
|
+
|
6
|
+
# Shared styles
|
7
|
+
attr_accessor :styles
|
8
|
+
|
9
|
+
def schemas
|
10
|
+
@schemas ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def styles
|
14
|
+
@styles ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
18
|
+
xm.Document {
|
19
|
+
super
|
20
|
+
styles.each { |style| style.render(xm) }
|
21
|
+
features.each { |feature| feature.render(xm) }
|
22
|
+
schemas.each { |schema| schema.render(xm) }
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/kml/feature.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# This source file implements the Feature class of KML.
|
2
|
+
#
|
3
|
+
# Basic XML chunk structure:
|
4
|
+
#
|
5
|
+
# <name>...</name> <!-- string -->
|
6
|
+
# <visibility>1</visibility> <!-- boolean -->
|
7
|
+
# <open>1</open> <!-- boolean -->
|
8
|
+
# <address>...</address> <!-- string -->
|
9
|
+
# <AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">...
|
10
|
+
# </AddressDetails> <!-- string -->
|
11
|
+
# <phoneNumber>...</phoneNumber> <!-- string -->
|
12
|
+
# <Snippet maxLines="2">...</Snippet> <!-- string -->
|
13
|
+
# <description>...</description> <!-- string -->
|
14
|
+
# <LookAt>...</LookAt>
|
15
|
+
# <TimePrimitive>...</TimePrimitive>
|
16
|
+
# <styleUrl>...</styleUrl> <!-- anyURI -->
|
17
|
+
# <StyleSelector>...</StyleSelector>
|
18
|
+
# <Region>...</Region>
|
19
|
+
# <Metadata>...</Metadata> <!-- user-defined data -->
|
20
|
+
|
21
|
+
module KML #:nodoc:
|
22
|
+
# A feature is an abstract base class.
|
23
|
+
class Feature < KML::Object
|
24
|
+
# Accessor for the feature name
|
25
|
+
attr_accessor :name
|
26
|
+
|
27
|
+
# Return true if the feature is visible
|
28
|
+
def visibility?
|
29
|
+
@visibility || true
|
30
|
+
end
|
31
|
+
|
32
|
+
# If the visibility has been set then return '0' for false and '1' for true. If the visibility
|
33
|
+
# has never been explicitly set then return nil (which means that the associated KML tag will
|
34
|
+
# not be rendered)
|
35
|
+
def visibility
|
36
|
+
return nil if @visibility.nil?
|
37
|
+
@visibility ? '1' : '0'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set to true to indicate that the feature is visible.
|
41
|
+
def visibility=(v)
|
42
|
+
@visibility = v
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return true if the feature is expanded when initially displayed.
|
46
|
+
def open?
|
47
|
+
@open || true
|
48
|
+
end
|
49
|
+
|
50
|
+
# If the open has been set then return '0' for false and '1' for true. If the open has never been
|
51
|
+
# explicitly set then return nil (which means that the associated KML tag will not be rendered)
|
52
|
+
def open
|
53
|
+
return nil if @open.nil?
|
54
|
+
@open ? '1' : '0'
|
55
|
+
end
|
56
|
+
|
57
|
+
# Set to true to indicate that the feature is expanded when displayed. Set to false to indicate that the
|
58
|
+
# feature is collapsed.
|
59
|
+
def open=(v)
|
60
|
+
@open = v
|
61
|
+
end
|
62
|
+
|
63
|
+
# A string value representing an unstructured address written as a standard street, city, state address, and/or as
|
64
|
+
# a postal code. You can use the +address+ attribute to specify the location of a point instead of using latitude and
|
65
|
+
# longitude coordinates. (However, if a Point is provided, it takes precedence over the +address+.) To find out
|
66
|
+
# which locales are supported for this tag in Google Earth, go to the
|
67
|
+
# <a href="http://maps.google.com/support/bin/answer.py?answer=16634">Google Maps Help</a>.
|
68
|
+
attr_accessor :address
|
69
|
+
|
70
|
+
# A structured address, formatted as xAL, or eXtensible Address Language, an international standard for address
|
71
|
+
# formatting. AddressDetails is used by KML for geocoding in Google Maps only. For details, see the Google Maps
|
72
|
+
# API documentation. Currently, Google Earth does not use this attribute; use +address+ instead.
|
73
|
+
attr_accessor :address_details
|
74
|
+
|
75
|
+
# A string value representing a telephone number. This element is used by Google Maps Mobile only. The industry
|
76
|
+
# standard for Java-enabled cellular phones is RFC2806. For more information, see
|
77
|
+
# <a href="http://www.ietf.org/rfc/rfc2806.txt">http://www.ietf.org/rfc/rfc2806.txt</a>.
|
78
|
+
attr_accessor :phone_number
|
79
|
+
|
80
|
+
# Accessor for the snippet. See +KML::Snippet+
|
81
|
+
attr_accessor :snippet
|
82
|
+
# Set the snippet. See +KML::Snippet+
|
83
|
+
def snippet=(v)
|
84
|
+
case v
|
85
|
+
when String
|
86
|
+
@snippet = Snippet.new(v)
|
87
|
+
when Snippet
|
88
|
+
@snippet = v
|
89
|
+
else
|
90
|
+
raise ArgumentError, "Snippet must be a String or a Snippet"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# User-supplied text that appears in the description balloon when the user clicks on either the feature name
|
95
|
+
# in the Places panel or the Placemark icon in the 3D viewer. This text also appears beneath the feature name
|
96
|
+
# in the Places panel if no Snippet is specified for the feature.
|
97
|
+
#
|
98
|
+
# Description supports plain text as well as a subset of HTML formatting elements, including tables. It does
|
99
|
+
# not support other web-based technology, such as dynamic page markup (PHP, JSP, ASP), scripting languages
|
100
|
+
# (VBScript, Javascript), nor application languages (Java, Python).
|
101
|
+
#
|
102
|
+
# If your description contains no HTML markup, Google Earth attempts to format it, replacing newlines with
|
103
|
+
# <br> and wrapping URLs with anchor tags. A valid URL string for the World Wide Web is automatically
|
104
|
+
# converted to a hyperlink to that URL (e.g., http://www.google.com). Consequently, you do not need to surround
|
105
|
+
# a URL with the <a href="http://.."></a> tags in order to achieve a simple link.
|
106
|
+
attr_accessor :description
|
107
|
+
|
108
|
+
# Defines a camera viewpoint associated with any element derived from Feature. See LookAt.
|
109
|
+
attr_accessor :look_at
|
110
|
+
|
111
|
+
attr_accessor :time_primitive
|
112
|
+
|
113
|
+
# URI (a URI equals [URL]#ID) of a Style or StyleMap defined in a Document. If the style is in the same file,
|
114
|
+
# use a # reference. If the style is defined in an external file, use a full URL along with # referencing. Examples:
|
115
|
+
#
|
116
|
+
# +style_url='#myIconStyleID'
|
117
|
+
# +style_url='http://someserver.com/somestylefile.xml#restaurant'
|
118
|
+
attr_accessor :style_url
|
119
|
+
|
120
|
+
# One or more Styles and StyleMaps can be defined to customize the appearance of any element derived from Feature
|
121
|
+
# or of the Geometry in a Placemark. (See BalloonStyle, ListStyle, StyleSelector, and the styles derived from
|
122
|
+
# ColorStyle.) A style defined within a Feature is called an "inline style" and applies only to the Feature that
|
123
|
+
# contains it. A style defined as the child of a Document is called a "shared style." A shared style must have an id
|
124
|
+
# defined for it. This id is referenced by one or more Features within the <Document>. In cases where a style element
|
125
|
+
# is defined both in a shared style and in an inline style for a Feature—that is, a Folder, GroundOverlay,
|
126
|
+
# NetworkLink, Placemark, or ScreenOverlay—the value for the Feature's inline style takes precedence over the value
|
127
|
+
# for the shared style.
|
128
|
+
attr_accessor :style_selector
|
129
|
+
attr_accessor :region
|
130
|
+
attr_accessor :metadata
|
131
|
+
|
132
|
+
# Render the object and all of its sub-elements.
|
133
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
134
|
+
[:name, :visibility, :address].each do |a|
|
135
|
+
xm.__send__(a, self.__send__(a)) unless self.__send__(a).nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
xm.description { xm.cdata!(description) } unless description.nil?
|
139
|
+
xm.open(self.open) unless open.nil?
|
140
|
+
|
141
|
+
xm.phoneNumber(phone_number) unless phone_number.nil?
|
142
|
+
xm.styleUrl(style_url) unless style_url.nil?
|
143
|
+
|
144
|
+
unless address_details.nil?
|
145
|
+
xm.AddressDetails(:xmlns => "urn:oasis:names:tc:ciq:xsdschema:xAL:2.0") { address_details.render(xm) }
|
146
|
+
end
|
147
|
+
|
148
|
+
xm.Snippet(snippet.text, snippet.max_lines) unless snippet.nil?
|
149
|
+
|
150
|
+
xm.LookAt { look_at.render(xm) } unless look_at.nil?
|
151
|
+
xm.TimePrimitive { time_primitive.render(xm) } unless look_at.nil?
|
152
|
+
xm.StyleSelector { style_selector.render(xm) } unless style_selector.nil?
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
require 'kml/placemark'
|
158
|
+
require 'kml/container'
|
159
|
+
require 'kml/overlay'
|
160
|
+
|
161
|
+
require 'kml/snippet'
|
data/lib/kml/folder.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module KML #:nodoc:
|
2
|
+
# A Folder is used to arrange other Features hierarchically (Folders, Placemarks, NetworkLinks,
|
3
|
+
# or Overlays). A Feature is visible only if it and all its ancestors are visible.
|
4
|
+
class Folder < Container
|
5
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
6
|
+
xm.Folder {
|
7
|
+
super
|
8
|
+
features.each { |f| f.render(xm) }
|
9
|
+
}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/kml/geometry.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
module KML
|
2
|
+
class Geometry < KML::Object
|
3
|
+
# Specifies whether to connect the point to the ground. Extrusion requires that the point's +altitude_mode+ be
|
4
|
+
# either "relativeToGround" or "absolute" and that within the +coordinates+, the altitude component be greater
|
5
|
+
# than 0 (that is, in the air). Default is false.
|
6
|
+
def extrude?
|
7
|
+
@extrude
|
8
|
+
end
|
9
|
+
|
10
|
+
# Set to true to extrude.
|
11
|
+
def extrude=(v)
|
12
|
+
@extrude = v
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return nil if extrude has not been defined, otherwise return '1' for true or '0' for false.
|
16
|
+
def extrude
|
17
|
+
return nil unless @extrude
|
18
|
+
@extrude ? '1' : '0'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Specifies whether to allow lines and paths to follow the terrain. This specification applies only to LineStrings
|
22
|
+
# (paths) and LinearRings (polygons) that have an +altitude_mode+ of "clampToGround". Very long lines should enable
|
23
|
+
# tessellation so that they follow the curvature of the earth (otherwise, they may go underground and be hidden).
|
24
|
+
# Default is false.
|
25
|
+
def tessellate?
|
26
|
+
@tessellate
|
27
|
+
end
|
28
|
+
|
29
|
+
# Set to true to tessellate.
|
30
|
+
def tessellate=(v)
|
31
|
+
@tessellate = v
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return nil if tessellate has not been defined, otherwise return '1' for true or '0' for false.
|
35
|
+
def tessellate
|
36
|
+
return nil unless @tessellate
|
37
|
+
@tessellate ? '1' : '0'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Specifies how altitude components in the <coordinates> element are interpreted. Possible values are:
|
41
|
+
#
|
42
|
+
# * clampToGround - (default) Indicates to ignore an altitude specification (for example, in the +coordinates+).
|
43
|
+
# * relativeToGround - Sets the altitude of the element relative to the actual ground elevation of a particular
|
44
|
+
# location. For example, if the ground elevation of a location is exactly at sea level and the altitude for a
|
45
|
+
# point is set to 9 meters, then the elevation for the icon of a point placemark elevation is 9 meters with
|
46
|
+
# this mode. However, if the same coordinate is set over a location where the ground elevation is 10 meters
|
47
|
+
# above sea level, then the elevation of the coordinate is 19 meters. A typical use of this mode is for placing
|
48
|
+
# telephone poles or a ski lift.
|
49
|
+
# * absolute - Sets the altitude of the coordinate relative to sea level, regardless of the actual elevation
|
50
|
+
# of the terrain beneath the element. For example, if you set the altitude of a coordinate to 10 meters with
|
51
|
+
# an absolute altitude mode, the icon of a point placemark will appear to be at ground level if the terrain
|
52
|
+
# beneath is also 10 meters above sea level. If the terrain is 3 meters above sea level, the placemark will
|
53
|
+
# appear elevated above the terrain by 7 meters. A typical use of this mode is for aircraft placement.
|
54
|
+
def altitude_mode
|
55
|
+
@altitude_mode || 'clampToGround'
|
56
|
+
end
|
57
|
+
|
58
|
+
def altitude_mode_set?
|
59
|
+
!(@altitude_mode.nil?)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set the altitude mode
|
63
|
+
def altitude_mode=(mode)
|
64
|
+
allowed_modes = %w(clampToGround relativeToGround absolute)
|
65
|
+
if allowed_modes.include?(mode)
|
66
|
+
@altitude_mode = mode
|
67
|
+
else
|
68
|
+
raise ArgumentError, "Must be one of the allowed altitude modes: #{allowed_modes.join(',')}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
73
|
+
xm.extrude(extrude) unless extrude.nil?
|
74
|
+
xm.tessellate(tessellate) unless tessellate.nil?
|
75
|
+
xm.altitudeMode(altitude_mode) if altitude_mode_set?
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
require 'kml/point'
|
82
|
+
require 'kml/line_string'
|
83
|
+
require 'kml/linear_ring'
|
84
|
+
require 'kml/polygon'
|
85
|
+
require 'kml/model'
|
86
|
+
require 'kml/multi_geometry'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module KML #:nodoc:
|
2
|
+
# This element draws an image overlay draped onto the terrain.
|
3
|
+
class GroundOverlay < Overlay
|
4
|
+
attr_accessor :altitude
|
5
|
+
attr_accessor :altitude_mode
|
6
|
+
attr_accessor :lat_lon_box
|
7
|
+
|
8
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
9
|
+
raise InvalidKMLError, "GroundOverlay.lat_lon_box is required" if lat_lon_box.nil?
|
10
|
+
xm.GroundOverlay {
|
11
|
+
super
|
12
|
+
xm.altitude(altitude) unless altitude.nil?
|
13
|
+
xm.altitudeMode(altitude_mode) unless altitude_mode.nil?
|
14
|
+
lat_lon_box.render(xm)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/kml/hot_spot.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module KML #:nodoc:
|
2
|
+
# Specifies the position within the Icon that is "anchored" to the <Point> specified in the Placemark.
|
3
|
+
# The x and y values can be specified in three different ways: as pixels ("pixels"), as fractions of
|
4
|
+
# the icon ("fraction"), or as inset pixels ("insetPixels"), which is an offset in pixels from the upper
|
5
|
+
# right corner of the icon. The x and y positions can be specified in different ways—for example, x can
|
6
|
+
# be in pixels and y can be a fraction. The origin of the coordinate system is in the lower left corner
|
7
|
+
# of the icon.
|
8
|
+
#
|
9
|
+
# * x - Either the number of pixels, a fractional component of the icon, or a pixel inset indicating the
|
10
|
+
# x component of a point on the icon.
|
11
|
+
# * y - Either the number of pixels, a fractional component of the icon, or a pixel inset indicating the
|
12
|
+
# y component of a point on the icon.
|
13
|
+
# * xunits - Units in which the x value is specified. Default="fraction". A value of "fraction" indicates
|
14
|
+
# the x value is a fraction of the icon. A value of "pixels" indicates the x value in pixels. A value of
|
15
|
+
# "insetPixels" indicates the indent from the right edge of the icon.
|
16
|
+
# * yunits - Units in which the y value is specified. Default="fraction". A value of "fraction" indicates
|
17
|
+
# the y value is a fraction of the icon. A value of "pixels" indicates the y value in pixels. A value of
|
18
|
+
# "insetPixels" indicates the indent from the top edge of the icon.
|
19
|
+
class HotSpot
|
20
|
+
attr_reader :x
|
21
|
+
attr_reader :y
|
22
|
+
attr_reader :xunits
|
23
|
+
attr_reader :yunits
|
24
|
+
def initialize(x, y, xunits, yunits)
|
25
|
+
@x = x
|
26
|
+
@y = y
|
27
|
+
@xunits = xunits
|
28
|
+
@yunits = yunits
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/kml/icon.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module KML #:nodoc:
|
2
|
+
# Defines an image associated with an Icon style or overlay. Icon has the same child elements as +Link+.
|
3
|
+
# The required href defines the location of the image to be used as the overlay or as the icon for the
|
4
|
+
# placemark. This location can either be on a local file system or a remote web server.
|
5
|
+
class Icon < Link
|
6
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
7
|
+
raise InvalidKMLError, "Icon.href must be specified" if href.nil?
|
8
|
+
xm.Icon {
|
9
|
+
self.elements.each do |a|
|
10
|
+
xm.__send__(a, self.__send__(a)) unless self.__send__(a).nil?
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Source file contains the code for creating the IconStyle element:
|
2
|
+
#
|
3
|
+
# <IconStyle id="ID">
|
4
|
+
# <!-- inherited from ColorStyle -->
|
5
|
+
# <color>ffffffff</color> <!-- kml:color -->
|
6
|
+
# <colorMode>normal</colorMode> <!-- kml:colorModeEnum:normal or random -->
|
7
|
+
#
|
8
|
+
# <!-- specific to IconStyle -->
|
9
|
+
# <scale>1</scale> <!-- float -->
|
10
|
+
# <heading>0</heading> <!-- float -->
|
11
|
+
# <Icon>
|
12
|
+
# <href>...</href>
|
13
|
+
# </Icon>
|
14
|
+
# <hotSpot x="0.5" y="0.5"
|
15
|
+
# xunits="fraction" yunits="fraction"/> <!-- kml:vec2Type -->
|
16
|
+
# </IconStyle>
|
17
|
+
|
18
|
+
module KML #:nodoc:
|
19
|
+
# Specifies how icons for point Placemarks are drawn, both in the Places panel and in the 3D viewer of
|
20
|
+
# Google Earth. The Icon object specifies the icon image. The +scale+ specifies the x, y scaling of the
|
21
|
+
# icon.
|
22
|
+
class IconStyle < ColorStyle
|
23
|
+
# Compass direction, in degrees. Default=0 (North). (
|
24
|
+
# <a href="http://earth.google.com/kml/kml_tags_21.html#heading">See diagram.) Values range from 0 to
|
25
|
+
# ±180 degrees.
|
26
|
+
attr_accessor :heading
|
27
|
+
|
28
|
+
# Resizes the icon (default=1).
|
29
|
+
attr_accessor :scale
|
30
|
+
|
31
|
+
# A custom Icon.
|
32
|
+
attr_accessor :icon
|
33
|
+
|
34
|
+
# Specifies the position within the Icon that is "anchored" to the Point specified in the Placemark.
|
35
|
+
# See KML::HotSpot
|
36
|
+
attr_accessor :hot_spot
|
37
|
+
|
38
|
+
def render(xm=Builder::XmlMarkup.new(:indent => 2))
|
39
|
+
xm.IconStyle {
|
40
|
+
super
|
41
|
+
xm.scale(scale) unless scale.nil?
|
42
|
+
xm.heading(heading) unless heading.nil?
|
43
|
+
icon.render(xm) unless icon.nil?
|
44
|
+
unless hot_spot.nil?
|
45
|
+
xm.hotSpot(:x => hot_spot.x, :y => hot_spot.y, :xunits => hot_spot.xunits, :yunits => hot_spot.yunits)
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
require 'kml/hot_spot'
|