ruby_kml 0.1.7

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.
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,40 @@
1
+ module KML
2
+ class Model < Geometry
3
+
4
+ def initialize(params={})
5
+ @lng, @lat, @alt = *params[:location]
6
+ @heading, @tilt, @roll = *params[:orientation] || [0, 0, 0]
7
+ @x, @y, @z = *params[:scale] || [1, 1, 1]
8
+ @link = params[:link]
9
+ @id = params[:id] if params[:id]
10
+ end
11
+
12
+ def id
13
+ @id || "model_#{@link.href}_#{@x}_#{@y}"
14
+ end
15
+
16
+ def render(xm = Builder::XmlMarkup.new(:indent => 2))
17
+ xm.Model :id => id do
18
+ xm.altitudeMode(altitude_mode) if altitude_mode_set?
19
+ xm.Location do
20
+ xm.longitude @lng
21
+ xm.latitude @lat
22
+ xm.altitude @alt
23
+ end
24
+ xm.Orientation do
25
+ xm.heading @heading
26
+ xm.tilt @tilt
27
+ xm.roll @roll
28
+ end
29
+ xm.Scale do
30
+ xm.x @x
31
+ xm.y @y
32
+ xm.z @z
33
+ end
34
+ @link.render(xm)
35
+ # ResourceMap needs to be implemented still
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ module KML
2
+ class MultiGeometry < Geometry
3
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
4
+ xm.MultiGeometry { features.each { |f| f.render(xm) } }
5
+ end
6
+
7
+ def self.parse(node)
8
+ self.new.parse(node)
9
+ end
10
+
11
+ def parse(node)
12
+ super(node) do |cld|
13
+ case cld.name
14
+ when 'Polygon'
15
+ self.features << KML::Polygon.parse(cld)
16
+ else
17
+ puts "MultiGeometry"
18
+ p cld
19
+ puts
20
+ end
21
+ end
22
+ self
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,37 @@
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
+
21
+ def parse(node)
22
+ self.id = node['id']
23
+ node.element_children.each do |cld|
24
+ yield cld
25
+ end
26
+ self
27
+ end
28
+ end
29
+ end
30
+
31
+ require 'kml/feature'
32
+ require 'kml/geometry'
33
+ require 'kml/color_style'
34
+ require 'kml/style_selector'
35
+ require 'kml/link'
36
+ require 'kml/icon'
37
+ require 'kml/lat_lon_box'
@@ -0,0 +1,21 @@
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'
21
+ require 'kml/screen_overlay'
@@ -0,0 +1,60 @@
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 < KML::Container
27
+ attr_accessor :geometry
28
+
29
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
30
+ xm.Placemark {
31
+ super
32
+ features.each { |f| f.render(xm) }
33
+ plain_children.each { |c| xm << c }
34
+ geometry.render(xm) unless geometry.nil?
35
+ }
36
+ end
37
+
38
+ def self.parse(node)
39
+ self.new.parse(node)
40
+ end
41
+
42
+ def parse(node)
43
+ super(node) do |cld|
44
+ case cld.name
45
+ when 'MultiGeometry'
46
+ self.geometry = KML::MultiGeometry.parse(cld)
47
+ when 'Polygon'
48
+ self.geometry = KML::Polygon.parse(cld)
49
+ when 'Point'
50
+ self.geometry = KML::Point.parse(cld)
51
+ else
52
+ puts "Placemark"
53
+ p cld
54
+ puts
55
+ end
56
+ end
57
+ self
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,65 @@
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.strip.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
+ def self.parse(node)
47
+ self.new.parse(node)
48
+ end
49
+
50
+ def parse(node)
51
+ super(node) do |cld|
52
+ case cld.name
53
+ when 'coordinates'
54
+ self.coordinates = cld.content
55
+ else
56
+ puts "Point"
57
+ p cld
58
+ puts
59
+ end
60
+ end
61
+ self
62
+ end
63
+
64
+ end
65
+ 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,91 @@
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
+ # <innerBoundaryIs>
20
+ # ...
21
+ # </innerBoundaryIs>
22
+ # </Polygon>
23
+
24
+ module KML #:nodoc:
25
+ # A Polygon is defined by an outer boundary and 0 or more inner boundaries. The boundaries, in turn, are defined
26
+ # by LinearRings. When a Polygon is extruded, its boundaries are connected to the ground to form additional polygons,
27
+ # which gives the appearance of a building. When a Polygon is extruded, each point is extruded individually.
28
+ # Extruded Polygons use PolyStyle for their color, color mode, and fill.
29
+ class Polygon < Geometry
30
+ attr_accessor :outer_boundary_is
31
+
32
+ def inner_boundary_is
33
+ @inner_boundary_is ||= []
34
+ end
35
+
36
+ # allow old semantics for adding inner boundaries
37
+ def inner_boundary_is=(ib)
38
+ if ib.kind_of?(Array)
39
+ @inner_boundary_is = ib
40
+ else
41
+ self.inner_boundary_is << ib
42
+ end
43
+ end
44
+
45
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
46
+ xm.Polygon {
47
+ super
48
+ xm.outerBoundaryIs {
49
+ outer_boundary_is.render(xm)
50
+ }
51
+ inner_boundary_is.each do |ib|
52
+ xm.innerBoundaryIs {
53
+ ib.render(xm)
54
+ }
55
+ end
56
+ }
57
+ end
58
+
59
+ def self.parse(node)
60
+ self.new.parse(node)
61
+ end
62
+
63
+ def parse(node)
64
+ super(node) do |cld|
65
+ case cld.name
66
+ when 'outerBoundaryIs'
67
+ self.outer_boundary_is = self.parse_boundary(cld)
68
+ when 'innerBoundaryIs'
69
+ self.inner_boundary_is << self.parse_boundary(cld)
70
+ else
71
+ puts "Polygon"
72
+ p cld
73
+ puts
74
+ end
75
+ end
76
+ self
77
+ end
78
+
79
+ # should only contain a LinearRing
80
+ def parse_boundary(node)
81
+ ring = nil
82
+ node.element_children.each do |cld|
83
+ case cld.name
84
+ when 'LinearRing'
85
+ ring = KML::LinearRing.parse(cld)
86
+ end
87
+ end
88
+ ring
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,61 @@
1
+ # This file implements the ScreenOverlay type
2
+ # <ScreenOverlay id="ID">
3
+ # <!-- inherited from Feature element -->
4
+ # <!-- inherited from Overlay element -->
5
+ #
6
+ # <!-- specific to ScreenOverlay -->
7
+ # <overlayXY x="double" y="double" xunits="fraction" yunits="fraction"/>
8
+ # <!-- vec2 -->
9
+ # <!-- xunits and yunits can be one of: fraction, pixels, or insetPixels -->
10
+ # <screenXY x="double" y="double" xunits="fraction" yunits="fraction"/>
11
+ # <!-- vec2 -->
12
+ # <rotationXY x="double" y="double" xunits="fraction" yunits"fraction"/>
13
+ # <!-- vec2 -->
14
+ # <size x="double" y="double" xunits="fraction" yunits="fraction"/>
15
+ # <!-- vec2 -->
16
+ # <rotation>0</rotation> <!-- float -->
17
+ # </ScreenOverlay>
18
+
19
+ module KML
20
+
21
+ class ScreenOverlay < Overlay
22
+
23
+ # A hash of options in the form of {:x, :y, :xunits, :yunits} that
24
+ # specify the point on the overlay image that is mapped to the screen
25
+ def overlay_xy
26
+ @overlay_xy
27
+ end
28
+
29
+ # Set the overlay_xy coordinates
30
+ #
31
+ # xunits and yunits are :pixels or :fraction
32
+ def overlay_xy= coords
33
+ @overlay_xy = {:xunits => :fraction, :yunits => :fraction}.merge(coords)
34
+ end
35
+
36
+ # A hash of options in the form of {:x, :y, :xunits, :yunits} that
37
+ # specify the position on the screen where the image is mapped
38
+ def screen_xy
39
+ @screen_xy
40
+ end
41
+
42
+ #Set the screen_xy coordinates
43
+ #
44
+ # xunits and yunits are :pixels or :fraction
45
+ def screen_xy= coords
46
+ @screen_xy = {:xunits => :fraction, :yunits => :fraction}.merge(coords)
47
+ end
48
+
49
+ attr_accessor :size, :rotation
50
+
51
+ def render(xm=Builder::XmlMarkup.new(:indent => 2))
52
+ xm.ScreenOverlay {
53
+ super
54
+ xm.overlayXY(@overlay_xy) if @overlay_xy
55
+ xm.screenXY(@screen_xy) if @screen_xy
56
+ xm.size{ @size } if @size
57
+ xm.rotation{ @rotation } if @rotation
58
+ }
59
+ end
60
+ end
61
+ 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