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
@@ -0,0 +1,102 @@
1
+ module KML
2
+ class Geometry < KML::Container
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
+ def self.parse(node)
79
+ self.new.parse(node)
80
+ end
81
+
82
+ def parse(node)
83
+ super(node) do |cld|
84
+ case cld.name
85
+ when 'tessellate'
86
+ self.tessellate = cld.content
87
+ else
88
+ yield cld
89
+ end
90
+ end
91
+ self
92
+ end
93
+
94
+ end
95
+ end
96
+
97
+ require 'kml/point'
98
+ require 'kml/line_string'
99
+ require 'kml/linear_ring'
100
+ require 'kml/polygon'
101
+ require 'kml/model'
102
+ 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
@@ -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
@@ -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'
@@ -0,0 +1,36 @@
1
+ module KML #:nodoc:
2
+ # Specifies where the top, bottom, right, and left sides of a bounding box for the ground overlay are aligned. Values for
3
+ # +north+, +south+, +east+, and +west+ are required.
4
+ #
5
+ # * +north+ (required) Specifies the latitude of the north edge of the bounding box, in decimal degrees from 0 to ±90.
6
+ # * +south+ (required) Specifies the latitude of the south edge of the bounding box, in decimal degrees from 0 to ±90.
7
+ # * +east+ (required) Specifies the longitude of the east edge of the bounding box, in decimal degrees from 0 to ±180.
8
+ # (For overlays that overlap the meridian of 180° longitude, values can extend beyond that range.)
9
+ # * +west+ (required) Specifies the longitude of the west edge of the bounding box, in decimal degrees from 0 to ±180.
10
+ # (For overlays that overlap the meridian of 180° longitude, values can extend beyond that range.)
11
+ # * +rotation+ (optional) specifies a rotation of the overlay about its center, in degrees. Values can be ±180. The
12
+ # default is 0 (north). Rotations are specified in a clockwise direction.
13
+
14
+ class LatLonBox < KML::Object
15
+ attr_accessor :north
16
+ attr_accessor :south
17
+ attr_accessor :east
18
+ attr_accessor :west
19
+ attr_accessor :rotation
20
+
21
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
22
+ raise InvalidKMLError, "LatLonBox.north is required" if north.nil?
23
+ raise InvalidKMLError, "LatLonBox.south is required" if south.nil?
24
+ raise InvalidKMLError, "LatLonBox.east is required" if east.nil?
25
+ raise InvalidKMLError, "LatLonBox.west is required" if west.nil?
26
+
27
+ xm.LatLonBox {
28
+ xm.north(north)
29
+ xm.south(south)
30
+ xm.east(east)
31
+ xm.west(west)
32
+ xm.rotation unless rotation.nil?
33
+ }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ module KML #:nodoc:
2
+ # Defines a connected set of line segments. Use LineStyle to specify the color, color mode, and width of the line.
3
+ # When a LineString is extruded, the line is extended to the ground, forming a polygon that looks somewhat like a wall.
4
+ # For extruded LineStrings, the line itself uses the current LineStyle, and the extrusion uses the current PolyStyle.
5
+ # See the <a href="http://earth.google.com/kml/kml_tut.html">KML Tutorial</a> for examples of LineStrings (or paths).
6
+ class LineString < Geometry
7
+
8
+ # Two or more coordinate tuples, each consisting of floating point values for longitude, latitude, and altitude.
9
+ # The altitude component is optional.
10
+ def coordinates
11
+ @coordinates
12
+ end
13
+
14
+ # Set the coordinates. When specifying as a String, insert a space or linebreak between tuples. Do not include spaces
15
+ # within a tuple.
16
+ def coordinates=(c)
17
+ case c
18
+ when String
19
+ @coordinates = c.strip.split(/\s+/).collect { |coord| coord.split(',') }
20
+ when Array
21
+ c.each do |coord_array|
22
+ unless coord_array.is_a?(Array)
23
+ raise ArgumentError, "If set with an array, coordinates must be specified as an array of arrays"
24
+ end
25
+ end
26
+ @coordinates = c
27
+ else
28
+ raise ArgumentError, "Coordinates must either be a String or an Array of Arrays"
29
+ end
30
+ end
31
+
32
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
33
+ raise ArgumentError, "Coordinates required" if coordinates.nil?
34
+ xm.LineString {
35
+ super
36
+ xm.coordinates(coordinates.collect { |c| c.join(',') }.join(" "))
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module KML
2
+ # Specifies the drawing style (color, color mode, and line width) for all line geometry. Line geometry includes the
3
+ # outlines of outlined polygons and the extruded "tether" of Placemark icons (if extrusion is enabled).
4
+ class LineStyle < ColorStyle
5
+ # Width of the line, in pixels.
6
+ attr_accessor :width
7
+
8
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
9
+ xm.LineStyle {
10
+ super
11
+ xm.width(width) unless width.nil?
12
+ }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,67 @@
1
+ # Source code for producing a LinearRing element:
2
+ #
3
+ # <LinearRing id="ID">
4
+ # <!-- specific to LinearRing -->
5
+ # <extrude>0</extrude> <!-- boolean -->
6
+ # <tessellate>0</tessellate> <!-- boolean -->
7
+ # <altitudeMode>clampToGround</altitudeMode>
8
+ # <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
9
+ # <coordinates>...</coordinates> <!-- lon,lat[,alt] tuples -->
10
+ # </LinearRing>
11
+
12
+ module KML #:nodoc:
13
+ # Defines a closed line string, typically the outer boundary of a Polygon. Optionally, a LinearRing can also
14
+ # be used as the inner boundary of a Polygon to create holes in the Polygon. A Polygon can contain multiple
15
+ # LinearRing instances used as inner boundaries.
16
+ class LinearRing < Geometry
17
+ # Four or more tuples, each consisting of floating point values for longitude, latitude, and altitude.
18
+ # The altitude component is optional. Do not include spaces within a tuple. The last coordinate must be
19
+ # the same as the first coordinate. Coordinates are expressed in decimal degrees only.
20
+ def coordinates
21
+ @coordinates
22
+ end
23
+
24
+ # Set the coordinates
25
+ def coordinates=(c)
26
+ case c
27
+ when String
28
+ @coordinates = c.strip.split(/\s+/).collect { |coord| coord.split(',') }
29
+ when Array
30
+ c.each do |coord_array|
31
+ unless coord_array.is_a?(Array)
32
+ raise ArgumentError, "If set with an array, coordinates must be specified as an array of arrays"
33
+ end
34
+ end
35
+ @coordinates = c
36
+ else
37
+ raise ArgumentError, "Coordinates must either be a String or an Array of Arrays"
38
+ end
39
+ end
40
+
41
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
42
+ raise ArgumentError, "Coordinates required" if coordinates.nil?
43
+ xm.LinearRing {
44
+ super
45
+ xm.coordinates(coordinates.collect { |c| c.join(',') }.join(" "))
46
+ }
47
+ end
48
+
49
+ def self.parse(node)
50
+ self.new.parse(node)
51
+ end
52
+
53
+ def parse(node)
54
+ super(node) do |cld|
55
+ case cld.name
56
+ when 'coordinates'
57
+ self.coordinates = cld.content
58
+ else
59
+ puts "LinearRing"
60
+ p cld
61
+ puts
62
+ end
63
+ end
64
+ self
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,51 @@
1
+ module KML #:nodoc:
2
+ # Link specifies the location of any of the following:
3
+ #
4
+ # * KML files fetched by network links
5
+ # * Image files used by icons in icon styles, ground overlays, and screen overlays
6
+ # * Model files used in the Model element
7
+ #
8
+ # The file is conditionally loaded and refreshed, depending on the refresh parameters supplied here.
9
+ # Two different sets of refresh parameters can be specified: one set is based on time (+refresh_mode+ and
10
+ # +refresh_interval+) and one is based on the current "camera" view (+view_refresh_mode+ and
11
+ # +view_refresh_time+). In addition, Link specifies whether to scale the bounding box parameters that
12
+ # are sent to the server (+view_bound_scale+ and provides a set of optional viewing parameters that can
13
+ # be sent to the server (+view_format+) as well as a set of optional parameters containing version and
14
+ # language information.
15
+ #
16
+ # When a file is fetched, the URL that is sent to the server is composed of three pieces of information:
17
+ #
18
+ # * the +href+ (Hypertext Reference) that specifies the file to load.
19
+ # * an arbitrary format string that is created from (a) parameters that you specify in +view_format+ or
20
+ # (b) bounding box parameters (this is the default and is used if no +view_format+ is specified).
21
+ # * a second format string that is specified in +http_query+.
22
+ #
23
+ # If the file specified in +href+ is a local file, +view_format+ and +http_query+ are not used.
24
+ class Link < KML::Object
25
+ attr_accessor :href
26
+ attr_accessor :refresh_mode
27
+ attr_accessor :refresh_interval
28
+ attr_accessor :view_refresh_mode
29
+ attr_accessor :view_refresh_time
30
+ attr_accessor :view_bound_scale
31
+ attr_accessor :view_format
32
+ attr_accessor :http_query
33
+
34
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
35
+ raise InvalidKMLError, "Link.href must be specified" if href.nil?
36
+ xm.Link {
37
+ self.elements.each do |a|
38
+ xm.__send__(a, self.__send__(a)) unless self.__send__(a).nil?
39
+ end
40
+ }
41
+ end
42
+
43
+ protected
44
+ def elements
45
+ [
46
+ :href, :refresh_mode, :refresh_interval, :view_refresh_mode, :view_refresh_time,
47
+ :view_bound_scale, :view_format, :http_query
48
+ ]
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ # <LookAt id="ID">
2
+ # <longitude></longitude> <!-- kml:angle180 -->
3
+ # <latitude></latitude> <!-- kml:angle90 -->
4
+ # <altitude>0</altitude> <!-- double -->
5
+ # <range></range> <!-- double -->
6
+ # <tilt>0</tilt> <!-- float -->
7
+ # <heading>0</heading> <!-- float -->
8
+ # <altitudeMode>clampToGround</altitudeMode>
9
+ # <!--kml:altitudeModeEnum:clampToGround, relativeToGround, absolute -->
10
+ # </LookAt>
11
+ module KML
12
+ class LookAt < KML::Object
13
+ attr_accessor :longitude
14
+ attr_accessor :latitude
15
+ attr_accessor :altitude
16
+ attr_accessor :range
17
+ attr_accessor :tilt
18
+ attr_accessor :heading
19
+ attr_accessor :altitude_mode
20
+
21
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
22
+ [:longitude, :latitude, :altitude, :range, :tilt, :heading, :altitude_mode].each do |a|
23
+ xm.__send__(a, self.__send__(a)) unless self.__send__(a).nil?
24
+ end
25
+ end
26
+
27
+ end
28
+ end