schleyfox-ruby_kml 0.1.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.
@@ -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.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,49 @@
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.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
+ end
49
+ end
data/lib/kml/link.rb ADDED
@@ -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,21 @@
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
+ end
21
+ end
data/lib/kml/model.rb ADDED
@@ -0,0 +1,4 @@
1
+ module KML
2
+ class Model < Geometry
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module KML
2
+ class MultiGeometry < Geometry
3
+
4
+ end
5
+ end
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.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'builder'
3
+
4
+ require 'kml_file'
5
+
6
+ class InvalidKMLError < StandardError
7
+ 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