Module: Kamelopard

Defined in:
lib/kamelopard/classes.rb,
lib/kamelopard/spline.rb,
lib/kamelopard/function.rb,
lib/kamelopard/multicam.rb,
lib/kamelopard/regionate.rb,
lib/kamelopard/function_paths.rb

Overview

– ++

Defined Under Namespace

Modules: CoordinateList, Functions, Icon, ImagePyramid, Multicam, Regionate, Snippet, ViewVolume Classes: AbstractView, Alias, AnimatedUpdate, BalloonStyle, Camera, ColorStyle, Container, Data, Document, DocumentHolder, Feature, FlyTo, Folder, Geometry, GroundOverlay, IconStyle, LabelStyle, LatLonBox, LatLonQuad, LineString, LineStyle, LinearRing, Link, ListStyle, Lod, LookAt, Model, MultiGeometry, NetworkLink, Object, Orientation, Overlay, PhotoOverlay, Placemark, Point, PolyStyle, Polygon, Region, ResourceMap, Scale, SchemaData, ScreenOverlay, SoundCue, Style, StyleMap, StyleSelector, TimePrimitive, TimeSpan, TimeStamp, Tour, TourControl, TourPrimitive, Track, VSRAction, Wait, XY

Constant Summary collapse

LogLevels =

Valid log levels:

  • :debug

  • :info

  • :notice

  • :warn

  • :error

  • :fatal

{
    :debug => 0,
    :info => 1,
    :notice => 2,
    :warn => 3,
    :error => 4,
    :fatal => 5
}
@@sequence =
0
@@id_prefix =
''
@@logger =
nil
@@log_level =
LogLevels[:notice]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_altitudeMode(mode, e) ⇒ Object

Helper function for altitudeMode / gx:altitudeMode elements



218
219
220
221
222
223
224
225
226
227
# File 'lib/kamelopard/classes.rb', line 218

def Kamelopard.add_altitudeMode(mode, e) # :nodoc:
    return if mode.nil?
    if mode == :clampToGround or mode == :relativeToGround or mode == :absolute then
        t = XML::Node.new 'altitudeMode'
    else
        t = XML::Node.new 'gx:altitudeMode'
    end
    t << mode.to_s
    e << t
end

.convert_coord(a) ⇒ Object

– Accepts XdX’X.X“, XDXmX.XXs, XdXmX.XXs, or X.XXXX with either /- or N/E/S/W +



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/kamelopard/classes.rb', line 171

def Kamelopard.convert_coord(a)    # :nodoc:
    a = a.to_s.upcase.strip.gsub(/\s+/, '')

    if a =~ /^[+-]?\d+(\.\d+)?$/ then
        # coord needs no transformation
        return a.to_f
    elsif a =~ /^[+-]?\d+\.\d+E?-?\d+/ then
        # Scientific notation
        return a.to_f
    end

    mult = 1
    if a =~ /^-/ then
        mult *= -1
    end
    a = a.sub /^\+|-/, ''
    a = a.strip

    if a =~ /[SW]$/ then
        mult *= -1
    end
    a = a.sub /[NESW]$/, ''
    a = a.strip

    if a =~ /^\d+D\d+M\d+(\.\d+)?S$/ then
        # coord is in dms
        p = a.split /[D"']/
        a = p[0].to_f + (p[2].to_f / 60.0 + p[1].to_f) / 60.0
    elsif a =~ /^\d+D\d+'\d+(\.\d+)?"$/ then
        # coord is in d'"
        p = a.split /[D"']/
        a = p[0].to_f + (p[2].to_f / 60.0 + p[1].to_f) / 60.0
    elsif m = (a =~ /^(\d+)°(\d+)'(\d+\.\d+)?"$/) then
        # coord is in °'"
        b = a
        a = $1.to_f + ($3.to_f / 60.0 + $2.to_f) / 60.0
    else
        raise "Couldn't determine coordinate format for #{a}"
    end

    # check that it's within range
    a = a.to_f * mult
    raise "Coordinate #{a} out of range" if a > 180 or a < -180
    return a.to_f
end

.get_next_idObject

:nodoc:



123
124
125
126
# File 'lib/kamelopard/classes.rb', line 123

def Kamelopard.get_next_id   # :nodoc:
    @@sequence += 1
    @@sequence
end

.id_prefixObject

Returns the current kml_id prefix value. See #Kamelopard.id_prefix=



135
136
137
# File 'lib/kamelopard/classes.rb', line 135

def Kamelopard.id_prefix
    @@id_prefix
end

.id_prefix=(a) ⇒ Object

Sets a prefix for all kml_id values generated from this time forth. Does not change previously generated kml_ids



130
131
132
# File 'lib/kamelopard/classes.rb', line 130

def Kamelopard.id_prefix=(a)
    @@id_prefix = a
end

.kml_array(e, m) ⇒ Object

– Intelligently adds elements to a KML object. Expects the KML object as the first argument, an array as the second. Each entry in the array is itself an array, containing first an Object, and second either a string or a Proc object. If the first Object is nil, nothing happens. If it’s not nil, then:

* if the second element is a string, add a new element to the KML. This
  string is the element name, and the stringified form of the first element
  is its text value
* if the second element is a proc, call the proc, passing it the KML
  object, and let the Proc (presumably) add itself to the KML

++



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/kamelopard/classes.rb', line 150

def Kamelopard.kml_array(e, m) # :nodoc:
    m.map do |a|
        if ! a[0].nil? then
            if a[1].kind_of? Proc then
                a[1].call(e)
            elsif a[0].kind_of? XML::Node then
                d = XML::Node.new(a[1])
                d << a[0]
                e << d
            else
                t = XML::Node.new a[1]
                t << a[0].to_s
                e << t
            end
        end
    end
end

.log(level, mod, msg) ⇒ Object

Logs a message, provided a log level, a text string, and the log message. See #Kamelopard.set_logger for details.



98
99
100
101
# File 'lib/kamelopard/classes.rb', line 98

def Kamelopard.log(level, mod, msg)
    raise "Unknown log level #{level} for error message #{msg}" unless LogLevels.has_key? level
    @@logger.call(level, mod, msg) unless @@logger.nil? or @@log_level > LogLevels[level]
end

.set_log_level(lev) ⇒ Object

Sets the current logging level. Valid levels are defined in the LogLevels hash



91
92
93
94
# File 'lib/kamelopard/classes.rb', line 91

def Kamelopard.set_log_level(lev)
    raise "Unknown log level #{lev}" unless LogLevels.has_key? lev
    @@log_level = LogLevels[lev]
end

.set_logger(l) ⇒ Object

Sets a logging callback function. This function should expect three arguments. The first will be a log level (:debug, :info, :notice, :warn, :error, or :fatal); the second will be a text string, categorizing the log entries generally; and the third will be the log message itself



86
87
88
# File 'lib/kamelopard/classes.rb', line 86

def Kamelopard.set_logger(l)
    @@logger = l
end

.xml_to_hash(node, fields) ⇒ Object

:nodoc:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/kamelopard/classes.rb', line 103

def Kamelopard.xml_to_hash(node, fields) # :nodoc:
    result = {}
    fields.each do |field|
        begin
            if field =~ /:/
                xmlfield = field
            else
                xmlfield = "kml:#{field}"
            end
            my_f = node.find("//#{xmlfield}").first
            if ! my_f.nil?
                result[field.to_sym] = my_f.first
            end
        rescue NoMethodError
            log(:debug, 'xml-to-hash', "Error getting field #{field} (#{xmlfileld}) from node")
        end
    end
    result
end

Instance Method Details

#get_stack_traceObject

:nodoc:



1098
1099
1100
1101
1102
# File 'lib/kamelopard/classes.rb', line 1098

def get_stack_trace   # :nodoc:
    k = ''
    caller.each do |a| k << "#{a}\n" end
    k
end

#make_function_path(points = 10, options = {}) ⇒ Object

This function creates a hash, then uses that hash to create a point in a tour, using make_view_from() among other things. It will yield to a code block, if one is provided, as described below. Arguments:

points: The number of points in the series
hash: Values used to create the hash, which creates the point in the
series. Keys in this hash include:
  Any option suitable for the make_view_from() function
    These can be constant numbers, Proc objects, or Function1D objects.
    The latter two will be called once for each point in the series.
    Proc objects will be passed the number of the point they're
    calculating, starting with 0, and the current value of the hash
    created for this point. "duration" represents the time in seconds
    spent flying from the last point to this one.
  callback_value
    A placeholder the callback function can use. It can set it when
    it's called one time, and see that value when called the next time.
  pause
    The amount of time to pause after flying to each point, or nil for no pause
  show_placemarks
    If set, a placemark object will be created at each point
  no_flyto
    If set, on flyto objects will be created
  multidim
    An array. Each array element is itself an array, containing two
    values. The first is associated with a FunctionMultiDim class
    representing a multidimensional function. The second is an array of
    symbols and nils. Valid symbols include any of the possible
    make_function_path options, except :multidim. At execution, the
    FunctionMultiDim will be evaluated, returning an array of values.
    The symbols in the :vals array will be assigned the returned value
    corresponding to their position in the :vals array. For instance,
    assume the following :multidim argument
       [ [ myFunc, [:latitude, :longitude, nil, :altitude] ],
         [ anotherFunc, [:pause] ] ]
    When myFunc is evaluated, assume it returns [1, 2, 3, 4, 5]. Thus,
    :latitude will be 1, :longitude 2, and so on. Because :vals[2] is
    nil, the corresponding element in the results of myFunc will be
    ignored. Also, given that :vals contains four values whereas myFunc
    returned 5, the unallocated final myFunc value will also be
    ignored.
 NOTE ON PROCESSING ORDER
    Individually specified hash options are processed first, followed by
    :multidim. So hash options included directly as
    well as in a :multidim :vals array will take the value from
    :multidim. make_function_path yields to code blocks last, after all
    other assignment.


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/kamelopard/function_paths.rb', line 57

def make_function_path(points = 10, options = {})

    def val(a, b, c) # :nodoc:
        if a.kind_of? Function then
            return a.get_value(c)
        elsif a.kind_of? Proc then
            return a.call(b, a)
        else
            return a
        end
    end

    views = []
    placemarks = []

    callback_value = nil
    i = 0
    while (i < points)
        p = i.to_f / points.to_f
        hash = {}
        [ :latitude, :longitude, :altitude, :heading,
          :tilt, :altitudeMode, :extrude, :when,
          :roll, :range, :pause, :begin, :end, :show_placemarks,
          :no_flyto
        ].each do |k|
            if options.has_key? k then
                hash[k] = val(options[k], i, p)
            end
        end

        hash[:show_placemarks] = options[:show_placemarks] if options.has_key? :show_placemarks
        #hash[:roll] = val(options[:roll], i, p) if options.has_key? :roll
        #hash[:range] = val(options[:range], i, p) if options.has_key? :range
        #hash[:pause] = val(options[:pause], i, p) if options.has_key? :pause

        if options.has_key? :duration
            duration = val(options[:duration], i, p)
        else
            duration = (i == 0 ? 0 : 2)
        end
        hash[:duration] = duration

        if options.has_key? :multidim then
            options[:multidim].each do |md|
                r = val(md[0], i, p)
                md[1].each_index do |ind|
                    hash[md[1][ind]] = r[ind] unless md[1][ind].nil?
                end
            end
        end

        hash[:callback_value] = callback_value unless callback_value.nil?

        begin
            tmp = yield(i, hash)
            hash = tmp unless tmp.nil?
        rescue LocalJumpError
            # Don't do anything; there's no block to yield to
        end
        #hash = options[:callback].call(i, hash) if options.has_key? :callback
        callback_value = hash[:callback_value] if hash.has_key? :callback_value

        v = make_view_from(hash)
        p = point(v.longitude, v.latitude, v.altitude, hash[:altitudeMode], hash[:extrude])
        # XXX Should I add the view's timestamp / timespan, if it exists, to the placemark?
        pl = placemark(i.to_s, :geometry => p)
        pl.abstractView = v
        get_folder << pl if hash.has_key? :show_placemarks
        fly_to v, :duration => duration , :mode => :smooth unless hash.has_key? :no_flyto
        views << v
        placemarks << pl

        pause hash[:pause] if hash.has_key? :pause

        i = i + 1
    end
    [views, placemarks]
end

#val(a, b, c) ⇒ Object

:nodoc:



59
60
61
62
63
64
65
66
67
# File 'lib/kamelopard/function_paths.rb', line 59

def val(a, b, c) # :nodoc:
    if a.kind_of? Function then
        return a.get_value(c)
    elsif a.kind_of? Proc then
        return a.call(b, a)
    else
        return a
    end
end