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,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