xaviershay-ruby_kml 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.
data/lib/kml/object.rb ADDED
@@ -0,0 +1,29 @@
1
+ module KML #:nodoc:
2
+ # Base class for all KML objects
3
+ class Object
4
+ # The KML object ID
5
+ attr_accessor :id
6
+
7
+ # Initialize the object, optionally passing a Hash of attributes to set.
8
+ def initialize(attributes=nil)
9
+ if attributes
10
+ case attributes
11
+ when Hash
12
+ attributes.each do |name, value|
13
+ self.__send__("#{name}=".to_sym, value)
14
+ end
15
+ else
16
+ raise ArgumentError, "Attributes must be specified as a Hash"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ require 'kml/feature'
24
+ require 'kml/geometry'
25
+ require 'kml/color_style'
26
+ require 'kml/style_selector'
27
+ require 'kml/link'
28
+ require 'kml/icon'
29
+ require 'kml/lat_lon_box'
@@ -0,0 +1,20 @@
1
+ module KML
2
+ # Overlay is the base type for image overlays drawn on the planet surface or on the screen. +icon+ specifies the
3
+ # image to use and can be configured to reload images based on a timer or by camera changes. This element also
4
+ # includes specifications for stacking order of multiple overlays and for adding color and transparency values to
5
+ # the base image.
6
+ class Overlay < Feature
7
+ attr_accessor :color
8
+ attr_accessor :draw_order
9
+ attr_accessor :icon
10
+
11
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
12
+ super
13
+ xm.color(color) unless color.nil?
14
+ xm.drawOrder(drawOrder) unless draw_order.nil?
15
+ icon.render(xm) unless icon.nil?
16
+ end
17
+ end
18
+ end
19
+
20
+ require 'kml/ground_overlay'
@@ -0,0 +1,36 @@
1
+ # Basic XML Structure:
2
+ #
3
+ # <Placemark id="ID">
4
+ # <!-- inherited from Feature element -->
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>
20
+ #
21
+ # <!-- specific to Placemark element -->
22
+ # <Geometry>...</Geometry>
23
+ # </Placemark>
24
+
25
+ module KML
26
+ class Placemark < Feature
27
+ attr_accessor :geometry
28
+
29
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
30
+ xm.Placemark {
31
+ super
32
+ geometry.render(xm) unless geometry.nil?
33
+ }
34
+ end
35
+ end
36
+ end
data/lib/kml/point.rb ADDED
@@ -0,0 +1,47 @@
1
+ # <Point id="ID">
2
+ # <!-- specific to Point -->
3
+ # <extrude>0</extrude> <!-- boolean -->
4
+ # <tessellate>0</tessellate> <!-- boolean -->
5
+ # <altitudeMode>clampToGround</altitudeMode>
6
+ # <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
7
+ # <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
8
+ # </Point>
9
+ module KML
10
+ class Point < Geometry
11
+
12
+ # A single tuple consisting of floating point values for longitude, latitude, and altitude (in that order).
13
+ # Longitude and latitude values are in degrees, where:
14
+ #
15
+ # * longitude ≥ -180 and <= 180
16
+ # * latitude ≥ -90 and ≤ 90
17
+ # * altitude values (optional) are in meters above sea level
18
+ def coordinates
19
+ @coordinates
20
+ end
21
+
22
+ # Set the coordinates
23
+ def coordinates=(c)
24
+ case c
25
+ when String
26
+ @coordinates = c.split(',')
27
+ unless @coordinates.length == 2 || @coordinates.length == 3
28
+ raise "Coordinates string may only have 2 parts (indicating lat and long) or 3 parts (lat, long and altitude)"
29
+ end
30
+ when Array
31
+ @coordinates = c
32
+ when Hash
33
+ @coordinates = [:lng, :lat, :alt].collect {|attr| c[attr]}.compact
34
+ else
35
+ raise ArgumentError, "Coordinates must be either a String, Hash or an Array"
36
+ end
37
+ end
38
+
39
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
40
+ xm.Point {
41
+ super
42
+ xm.coordinates(coordinates.join(","))
43
+ }
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ module KML
2
+ # Specifies the drawing style for all polygons, including polygon extrusions (which look like the walls of buildings)
3
+ # and line extrusions (which look like solid fences).
4
+ class PolyStyle < ColorStyle
5
+ attr_accessor :fill
6
+ attr_accessor :outline
7
+
8
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
9
+ xm.PolyStyle {
10
+ super
11
+ xm.fill(fill) unless fill.nil?
12
+ xm.outline(outline) unless outline.nil?
13
+ }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ # Source file which generates a Polygon element.
2
+ #
3
+ # <Polygon id="ID">
4
+ # <!-- specific to Polygon -->
5
+ # <extrude>0</extrude> <!-- boolean -->
6
+ # <tessellate>0</tessellate> <!-- boolean -->
7
+ # <altitudeMode>clampToGround</altitudeMode>
8
+ # <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
9
+ # <outerBoundaryIs>
10
+ # <LinearRing>
11
+ # <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
12
+ # </LinearRing>
13
+ # </outerBoundaryIs>
14
+ # <innerBoundaryIs>
15
+ # <LinearRing>
16
+ # <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
17
+ # </LinearRing>
18
+ # </innerBoundaryIs>
19
+ # </Polygon>
20
+
21
+ module KML #:nodoc:
22
+ # A Polygon is defined by an outer boundary and 0 or more inner boundaries. The boundaries, in turn, are defined
23
+ # by LinearRings. When a Polygon is extruded, its boundaries are connected to the ground to form additional polygons,
24
+ # which gives the appearance of a building. When a Polygon is extruded, each point is extruded individually.
25
+ # Extruded Polygons use PolyStyle for their color, color mode, and fill.
26
+ class Polygon < Geometry
27
+ attr_accessor :inner_boundary_is
28
+ attr_accessor :outer_boundary_is
29
+
30
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
31
+ xm.Polygon {
32
+ super
33
+ xm.outerBoundaryIs {
34
+ outer_boundary_is.render(xm)
35
+ }
36
+ unless inner_boundary_is.nil?
37
+ xm.innerBoundaryIs {
38
+ inner_boundary_is.render(xm)
39
+ }
40
+ end
41
+ }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ module KML #:nodoc:
2
+ # A short description of a feature. In Google Earth, this description is displayed in the Places panel
3
+ # under the name of the feature. If a Snippet is not supplied, the first two lines of the description are
4
+ # used. In Google Earth, if a Placemark contains both a description and a Snippet, the Snippet appears
5
+ # beneath the Placemark in the Places panel, and the description appears in the Placemark's description
6
+ # balloon. This object does not support HTML markup.
7
+ class Snippet
8
+ # The maximum number of lines to display.
9
+ attr_accessor :max_lines
10
+
11
+ # The text that is displayed (HTML not supported)
12
+ attr_accessor :text
13
+
14
+ # Initialize the snippet with the given text and optionally with the given max_lines value.
15
+ def initialize(text, max_lines=nil)
16
+ @text = text
17
+ @max_lines = max_lines
18
+ end
19
+
20
+ # The maximum number of lines to display. Default is 2
21
+ def max_lines
22
+ @max_lines ||= 2
23
+ end
24
+ end
25
+ end
data/lib/kml/style.rb ADDED
@@ -0,0 +1,23 @@
1
+ module KML
2
+ # A Style defines an addressable style group that can be referenced by StyleMaps and Features. Styles affect
3
+ # how Geometry is presented in the 3D viewer and how Features appear in the Places panel of the List view.
4
+ # Shared styles are collected in a Document and must have an id defined for them so that they can be referenced
5
+ # by the individual Features that use them.
6
+ class Style < StyleSelector
7
+ attr_accessor :icon_style
8
+ attr_accessor :label_style
9
+ attr_accessor :line_style
10
+ attr_accessor :poly_style
11
+ attr_accessor :balloon_style
12
+ attr_accessor :list_style
13
+
14
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
15
+ xm.Style(:id => id) {
16
+ %w(Icon Label Line Poly Balloon List).each do |name|
17
+ field = "#{name.downcase}_style".to_sym
18
+ self.__send__(field).render(xm) unless self.__send__(field).nil?
19
+ end
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ # Source file that defines a StyleMap element
2
+ #
3
+ # <StyleMap id="ID">
4
+ # <!-- extends StyleSelector -->
5
+ # <!-- elements specific to StyleMap -->
6
+ # <Pair id="ID">
7
+ # <key>normal</key> <!-- kml:styleStateEnum: normal or highlight
8
+ # <styleUrl>...</styleUrl> <!-- anyURI -->
9
+ # </Pair>
10
+ # </StyeMap>
11
+
12
+ module KML #:nodoc:
13
+ # A StyleMap maps between two different icon styles. Typically a StyleMap element is used to provide
14
+ # separate normal and highlighted styles for a placemark, so that the highlighted version appears when
15
+ # the user mouses over the icon in Google Earth.
16
+ class StyleMap < StyleSelector
17
+ # Key/styleUrl pairs
18
+ attr_accessor :pairs
19
+
20
+ # Get the pairs Hash. Each key/value pair maps a mode (normal or highlight) to the predefined style URL.
21
+ # Each pair contains a key and a value which references the style. For referenced style elements that
22
+ # are local to the KML document, a simple # referencing is used. For styles that are contained in
23
+ # external files, use a full URL along with # referencing.
24
+ def pairs
25
+ @pairs ||= {}
26
+ end
27
+
28
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
29
+ xm.StyleMap(:id => id) {
30
+ pairs.each do |key, value|
31
+ xm.Pair {
32
+ xm.key(key)
33
+ xm.styleUrl(value)
34
+ }
35
+ end
36
+ }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ module KML
2
+ class StyleSelector < KML::Object
3
+ end
4
+ end
5
+
6
+ require 'kml/style'
7
+ require 'kml/style_map'
@@ -0,0 +1,9 @@
1
+ module KML#:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/kml_file.rb ADDED
@@ -0,0 +1,28 @@
1
+ # The KMLFile class is the top level class for constructing KML files. To create a new KML file
2
+ # create a KMLFile instance and add KML objects to its objects. For example:
3
+ #
4
+ # f = KMLFile.new
5
+ # f.objects << Placemark.new(
6
+ # :name => 'Simple placemark',
7
+ # :description => 'Attached to the ground. Intelligently places itself at the height of the underlying terrain.',
8
+ # :geometry => Point.new(:coordinates=>'-122.0822035425683,37.42228990140251,0')
9
+ # )
10
+ # puts f.render
11
+ class KMLFile
12
+ attr_accessor :objects
13
+
14
+ # The objects in the KML file
15
+ def objects
16
+ @objects ||= []
17
+ end
18
+
19
+ # Render the KML file.
20
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
21
+ xm.instruct!
22
+ xm.kml(:xmlns => 'http://earth.google.com/kml/2.1'){
23
+ objects.each { |o| o.render(xm) }
24
+ }
25
+ end
26
+ end
27
+
28
+ require 'kml/object'
@@ -0,0 +1,10 @@
1
+ require "#{File.dirname(__FILE__)}/../test_helper"
2
+
3
+ class KML::PointTest < Test::Unit::TestCase
4
+ include KML
5
+
6
+ def test_allows_coordinates_to_be_specified_with_a_hash
7
+ point = Point.new(:coordinates => {:lat => 10, :lng => 20, :alt => 30})
8
+ assert_equal [20, 10, 30], point.coordinates
9
+ end
10
+ end
@@ -0,0 +1,220 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+
3
+ class KMLFileTest < Test::Unit::TestCase
4
+ include KML
5
+
6
+ def test_placemark
7
+ kml = KMLFile.new
8
+ kml.objects << Placemark.new(
9
+ :name => 'Simple placemark',
10
+ :description => 'Attached to the ground. Intelligently places itself at the height of the underlying terrain.',
11
+ :geometry => Point.new(:coordinates=>'-122.0822035425683,37.42228990140251,0')
12
+ )
13
+ write_and_show(kml, File.dirname(__FILE__) + '/simple_placemark.kml')
14
+ end
15
+
16
+ def test_cdata_description
17
+ description = <<-DESC
18
+ <h1>CDATA Tags are useful!</h1>
19
+ <p><font color="red">Text is <i>more readable</i> and
20
+ <b>easier to write</b> when you can avoid using entity
21
+ references.</font></p>
22
+ DESC
23
+
24
+ kml = KMLFile.new
25
+ document = Document.new(
26
+ :name => 'Document with CDATA example',
27
+ :snippet => Snippet.new("Document level snippet")
28
+ )
29
+ document.features << Placemark.new(
30
+ :name => 'CDATA example',
31
+ :description => description,
32
+ :snippet => Snippet.new("Example of a snippet"),
33
+ :geometry => Point.new(:coordinates=>'-122.0822035425683,37.4228,0')
34
+ )
35
+ kml.objects << document
36
+ write_and_show(kml, File.dirname(__FILE__) + '/cdata_and_snippet.kml')
37
+ end
38
+
39
+ def test_ground_overlays
40
+ kml = KMLFile.new
41
+ folder = Folder.new(
42
+ :name => 'Ground Overlays',
43
+ :description => 'Examples of ground overlays'
44
+ )
45
+ folder.features << GroundOverlay.new(
46
+ :name => 'Large-scale overlay on terrain',
47
+ :description => 'Overlay shows Mount Etna erupting on July 13th, 2001.',
48
+ :icon => Icon.new(:href => 'http://code.google.com/apis/kml/documentation/etna.jpg'),
49
+ :lat_lon_box => LatLonBox.new(
50
+ :north => 37.91904192681665,
51
+ :south => 37.46543388598137,
52
+ :east => 15.35832653742206,
53
+ :west => 14.60128369746704,
54
+ :rotation => -0.1556640799496235
55
+ )
56
+ )
57
+ kml.objects << folder
58
+ write_and_show(kml, File.dirname(__FILE__) + '/ground_overlays.kml')
59
+ end
60
+
61
+ def test_paths
62
+ kml = KMLFile.new
63
+ kml.objects << Document.new(
64
+ :name => 'Paths',
65
+ :description => 'Examples of paths. Note that the tessellate tag is by default
66
+ set to 0. If you want to create tessellated lines, they must be authored
67
+ (or edited) directly in KML.',
68
+ :styles => [
69
+ Style.new(
70
+ :id => 'yellowLineGreenPoly',
71
+ :line_style => LineStyle.new(:color => '7f00ffff', :width => 4),
72
+ :poly_style => PolyStyle.new(:color => '7f00ff00')
73
+ )
74
+ ],
75
+ :features => [
76
+ Placemark.new(
77
+ :name => 'Absolute Extruded',
78
+ :description => 'Transparent green wall with yellow outlines',
79
+ :style_url => '#yellowLineGreenPoly',
80
+ :geometry => LineString.new(
81
+ :extrude => true,
82
+ :tessellate => true,
83
+ :altitude_mode => 'absolute',
84
+ :coordinates => '-112.2550785337791,36.07954952145647,2357
85
+ -112.2549277039738,36.08117083492122,2357
86
+ -112.2552505069063,36.08260761307279,2357
87
+ -112.2564540158376,36.08395660588506,2357
88
+ -112.2580238976449,36.08511401044813,2357
89
+ -112.2595218489022,36.08584355239394,2357
90
+ -112.2608216347552,36.08612634548589,2357
91
+ -112.262073428656,36.08626019085147,2357
92
+ -112.2633204928495,36.08621519860091,2357
93
+ -112.2644963846444,36.08627897945274,2357
94
+ -112.2656969554589,36.08649599090644,2357'
95
+ )
96
+ )
97
+ ]
98
+ )
99
+ #puts kml.render
100
+ write_and_show(kml, File.dirname(__FILE__) + '/paths.kml')
101
+ end
102
+
103
+ def test_polygon
104
+ kml = KMLFile.new
105
+ kml.objects << Placemark.new(
106
+ :name => 'The Pentagon',
107
+ :geometry => Polygon.new(
108
+ :extrude => true,
109
+ :altitude_mode => 'relativeToGround',
110
+ :outer_boundary_is => LinearRing.new(
111
+ :coordinates => '-77.05788457660967,38.87253259892824,100
112
+ -77.05465973756702,38.87291016281703,100
113
+ -77.05315536854791,38.87053267794386,100
114
+ -77.05552622493516,38.868757801256,100
115
+ -77.05844056290393,38.86996206506943,100
116
+ -77.05788457660967,38.87253259892824,100'
117
+ ),
118
+ :inner_boundary_is => LinearRing.new(
119
+ :coordinates => '-77.05668055019126,38.87154239798456,100
120
+ -77.05542625960818,38.87167890344077,100
121
+ -77.05485125901024,38.87076535397792,100
122
+ -77.05577677433152,38.87008686581446,100
123
+ -77.05691162017543,38.87054446963351,100
124
+ -77.05668055019126,38.87154239798456,100'
125
+ )
126
+ )
127
+ )
128
+
129
+ #puts kml.render
130
+ write_and_show(kml, File.dirname(__FILE__) + '/polygon.kml')
131
+ end
132
+
133
+ def test_geometry_styles
134
+ kml = KMLFile.new
135
+ kml.objects << Style.new(
136
+ :id => "transBluePoly",
137
+ :line_style => LineStyle.new(
138
+ :width => 1.5
139
+ ),
140
+ :poly_style => PolyStyle.new(
141
+ :color => '7dff0000'
142
+ )
143
+ )
144
+ kml.objects << Placemark.new(
145
+ :name => 'Building 41',
146
+ :style_url => '#transBluePoly',
147
+ :geometry => Polygon.new(
148
+ :extrude => true,
149
+ :altitude_mode => 'relativeToGround',
150
+ :outer_boundary_is => LinearRing.new(
151
+ :coordinates => '-122.0857412771483,37.42227033155257,17
152
+ -122.0858169768481,37.42231408832346,17
153
+ -122.085852582875,37.42230337469744,17
154
+ -122.0858799945639,37.42225686138789,17
155
+ -122.0858860101409,37.4222311076138,17
156
+ -122.0858069157288,37.42220250173855,17
157
+ -122.0858379542653,37.42214027058678,17
158
+ -122.0856732640519,37.42208690214408,17
159
+ -122.0856022926407,37.42214885429042,17
160
+ -122.0855902778436,37.422128290487,17
161
+ -122.0855841672237,37.42208171967246,17
162
+ -122.0854852065741,37.42210455874995,17
163
+ -122.0855067264352,37.42214267949824,17
164
+ -122.0854430712915,37.42212783846172,17
165
+ -122.0850990714904,37.42251282407603,17
166
+ -122.0856769818632,37.42281815323651,17
167
+ -122.0860162273783,37.42244918858722,17
168
+ -122.0857260327004,37.42229239604253,17
169
+ -122.0857412771483,37.42227033155257,17'
170
+ )
171
+ )
172
+ )
173
+
174
+ write_and_show(kml, File.dirname(__FILE__) + '/polygon_style.kml')
175
+ end
176
+
177
+ def test_style_map
178
+ kml = KMLFile.new
179
+ kml.objects << Document.new(
180
+ :name => 'Highlighted Icon',
181
+ :description => 'Place your mouse over the icon to see it display the new icon',
182
+ :styles => [
183
+ Style.new(
184
+ :id => "highlightPlacemark",
185
+ :icon_style => IconStyle.new(
186
+ :icon => Icon.new(
187
+ :href => "http://maps.google.com/mapfiles/kml/paddle/red-stars.png"
188
+ )
189
+ )
190
+ ),
191
+ Style.new(
192
+ :id => "normalPlacemark",
193
+ :icon_style => IconStyle.new(
194
+ :icon => Icon.new(
195
+ :href => "http://maps.google.com/mapfiles/kml/paddle/wht-blank.png"
196
+ )
197
+ )
198
+ ),
199
+ StyleMap.new(
200
+ :id => 'exampleStyleMap',
201
+ :pairs => {
202
+ 'normal' => '#normalPlacemark',
203
+ 'highlight' => '#highlightPlacemark'
204
+ }
205
+ )
206
+ ],
207
+ :features => [
208
+ Placemark.new(
209
+ :name => 'Roll over this icon',
210
+ :style_url => '#exampleStyleMap',
211
+ :geometry => Point.new(
212
+ :coordinates => '-122.0856545755255,37.42243077405461,0'
213
+ )
214
+ )
215
+ ]
216
+ )
217
+ #puts kml.render
218
+ write_and_show(kml, File.dirname(__FILE__) + '/style_map.kml')
219
+ end
220
+ end