ruby_kml 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/LICENSE +7 -0
  2. data/README.md +34 -0
  3. data/Rakefile +52 -0
  4. data/examples/melbourne-stations.kml +18 -0
  5. data/lib/kml/color_style.rb +34 -0
  6. data/lib/kml/container.rb +42 -0
  7. data/lib/kml/document.rb +46 -0
  8. data/lib/kml/feature.rb +185 -0
  9. data/lib/kml/folder.rb +29 -0
  10. data/lib/kml/geometry.rb +102 -0
  11. data/lib/kml/ground_overlay.rb +18 -0
  12. data/lib/kml/hot_spot.rb +31 -0
  13. data/lib/kml/icon.rb +15 -0
  14. data/lib/kml/icon_style.rb +52 -0
  15. data/lib/kml/lat_lon_box.rb +36 -0
  16. data/lib/kml/line_string.rb +40 -0
  17. data/lib/kml/line_style.rb +15 -0
  18. data/lib/kml/linear_ring.rb +67 -0
  19. data/lib/kml/link.rb +51 -0
  20. data/lib/kml/look_at.rb +28 -0
  21. data/lib/kml/model.rb +40 -0
  22. data/lib/kml/multi_geometry.rb +26 -0
  23. data/lib/kml/object.rb +37 -0
  24. data/lib/kml/overlay.rb +21 -0
  25. data/lib/kml/placemark.rb +60 -0
  26. data/lib/kml/point.rb +65 -0
  27. data/lib/kml/poly_style.rb +16 -0
  28. data/lib/kml/polygon.rb +91 -0
  29. data/lib/kml/screen_overlay.rb +61 -0
  30. data/lib/kml/snippet.rb +25 -0
  31. data/lib/kml/style.rb +23 -0
  32. data/lib/kml/style_map.rb +39 -0
  33. data/lib/kml/style_selector.rb +7 -0
  34. data/lib/kml/version.rb +9 -0
  35. data/lib/kml_file.rb +55 -0
  36. data/lib/ruby_kml.rb +8 -0
  37. data/ruby_kml.gemspec +14 -0
  38. data/test/cdata_and_snippet.kml +21 -0
  39. data/test/ground_overlays.kml +25 -0
  40. data/test/kml/point_test.rb +10 -0
  41. data/test/kml_file_test.rb +255 -0
  42. data/test/paths.kml +33 -0
  43. data/test/polygon.kml +20 -0
  44. data/test/polygon_inner.kml +25 -0
  45. data/test/polygon_style.kml +24 -0
  46. data/test/simple_placemark.kml +12 -0
  47. data/test/style_map.kml +40 -0
  48. data/test/test_helper.rb +11 -0
  49. metadata +124 -0
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.
@@ -0,0 +1,34 @@
1
+ ruby_kml
2
+ ========
3
+
4
+ Overview
5
+ --------
6
+
7
+ Library for generating KML(Keyhole Markup Language) files in Ruby.
8
+ Sweet if you want to place markers, overlays, and other awesome things over a google map or google earth.
9
+
10
+
11
+ Install
12
+ -------
13
+
14
+ gem install ruby_kml
15
+
16
+
17
+ Examples
18
+ --------
19
+
20
+ See `test/kml_file_test.rb` for more examples
21
+
22
+ kml = KMLFile.new
23
+ folder = KML::Folder.new(:name => 'Melbourne Stations')
24
+ [
25
+ ["Flinders St", -37.818078, 144.966811],
26
+ ["Southern Cross", -37.818358, 144.952417],
27
+ ].each do |name, lat, lng|
28
+ folder.features << KML::Placemark.new(
29
+ :name => name,
30
+ :geometry => KML::Point.new(:coordinates => {:lat => lat, :lng => lng})
31
+ )
32
+ end
33
+ kml.objects << folder
34
+ puts kml.render
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require 'rubygems/package_task'
7
+
8
+ require File.join(File.dirname(__FILE__), 'lib/kml', 'version')
9
+
10
+ spec = Gem::Specification.load('ruby_kml.gemspec')
11
+ Gem::PackageTask.new(spec) {}
12
+
13
+ Rake::TestTask.new(:test) do |t|
14
+ t.libs << 'lib'
15
+ t.pattern = 'test/**/*_test.rb'
16
+ t.verbose = true
17
+ end
18
+
19
+ desc 'Generate documentation for the library.'
20
+ Rake::RDocTask.new(:rdoc) do |rdoc|
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = 'KMLr'
23
+ rdoc.options << '--line-numbers' << '--inline-source'
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ desc "Generate code statistics"
28
+ task :lines do
29
+ lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
30
+
31
+ for file_name in FileList["lib/**/*.rb"]
32
+ next if file_name =~ /vendor/
33
+ f = File.open(file_name)
34
+
35
+ while line = f.gets
36
+ lines += 1
37
+ next if line =~ /^\s*$/
38
+ next if line =~ /^\s*#/
39
+ codelines += 1
40
+ end
41
+ puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
42
+
43
+ total_lines += lines
44
+ total_codelines += codelines
45
+
46
+ lines, codelines = 0, 0
47
+ end
48
+
49
+ puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
50
+ end
51
+
52
+ task :default => :test
@@ -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,42 @@
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
+ attr_accessor :plain_children
8
+
9
+ # Get the features in the container
10
+ def features
11
+ @features ||= []
12
+ end
13
+
14
+ def plain_children
15
+ @plain_children ||= []
16
+ end
17
+
18
+ def parse(node)
19
+ super(node) do |cld|
20
+ case cld.name
21
+ when 'Document'
22
+ self.features << KML::Document.parse(cld)
23
+ when 'Folder'
24
+ self.features << KML::Folder.parse(cld)
25
+ when 'NetworkLink'
26
+ when 'Placemark'
27
+ self.features << KML::Placemark.parse(cld)
28
+ when 'GroundOverlay'
29
+ when 'PhotoOverlay'
30
+ when 'ScreenOverlay'
31
+ else
32
+ yield cld
33
+ end
34
+ end
35
+ self
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ require 'kml/folder'
42
+ require 'kml/document'
@@ -0,0 +1,46 @@
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
+
26
+ def self.parse(node)
27
+ self.new.parse(node)
28
+ end
29
+
30
+ def parse(node)
31
+ super(node) do |cld|
32
+ case cld.name
33
+ when 'Style'
34
+ # TODO
35
+ when 'Schema'
36
+ # TODO
37
+ else
38
+ puts "Document"
39
+ p cld
40
+ puts
41
+ end
42
+ end
43
+ self
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,185 @@
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
+ # &lt;br&gt; 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 &lt;a href="http://.."&gt;&lt;/a&gt; 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 time_primitive.nil?
152
+ xm.StyleSelector { style_selector.render(xm) } unless style_selector.nil?
153
+ end
154
+
155
+ def parse(node)
156
+ super(node) do |cld|
157
+ case cld.name
158
+ when 'name'
159
+ self.name = cld.content
160
+ when 'visibility'
161
+ self.visibility = cld.content
162
+ when 'description'
163
+ self.description = cld.content
164
+ when 'styleUrl'
165
+ self.style_url = cld.content
166
+ when 'Region'
167
+ # TODO
168
+ when 'ExtendedData'
169
+ # TODO
170
+ when 'Snippet'
171
+ # TODO
172
+ else
173
+ yield cld
174
+ end
175
+ end
176
+ self
177
+ end
178
+ end
179
+ end
180
+
181
+ require 'kml/container'
182
+ require 'kml/placemark'
183
+ require 'kml/overlay'
184
+
185
+ require 'kml/snippet'
@@ -0,0 +1,29 @@
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
+
12
+ def self.parse(node)
13
+ self.new.parse(node)
14
+ end
15
+
16
+ def parse(node)
17
+ super(node) do |cld|
18
+ case cld.name
19
+ when 'Stylex'
20
+ when 'Schemax'
21
+ else
22
+ puts "Folder"
23
+ p cld
24
+ puts
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end