Module: Kamelopard

Defined in:
lib/kamelopard/classes.rb,
lib/kamelopard/pointlist.rb

Overview

XXX Right now I’m changing this to handle one-dimensional lists of numbers, that can be added together. We’ll probably want a way to add points, or other numeric sets, to a set of pointlists easily. So for instance we can have lists for altitude, longitude, and latitude, and add a single point to them in one easy command.

Defined Under Namespace

Modules: CoordinateList, Icon, ImagePyramid, 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, NumberList, 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 =
{
    :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



139
140
141
142
143
144
145
146
147
148
# File 'lib/kamelopard/classes.rb', line 139

def Kamelopard.add_altitudeMode(mode, e)
    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 +



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
135
136
# File 'lib/kamelopard/classes.rb', line 97

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

    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+)?$/ then
        # coord needs no transformation
        1
    elsif 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
end

.get_documentObject



48
49
50
# File 'lib/kamelopard/classes.rb', line 48

def Kamelopard.get_document
    DocumentHolder.instance.current_document
end

.get_next_idObject

:nodoc



52
53
54
55
# File 'lib/kamelopard/classes.rb', line 52

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

.id_prefixObject



61
62
63
# File 'lib/kamelopard/classes.rb', line 61

def Kamelopard.id_prefix
    @@id_prefix
end

.id_prefix=(a) ⇒ Object



57
58
59
# File 'lib/kamelopard/classes.rb', line 57

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

.interpolate(lists = [], resolution = [10]) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
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
# File 'lib/kamelopard/pointlist.rb', line 46

def Kamelopard.interpolate(lists = [], resolution = [10])
    # Ruby implementation of Catmull-Rom splines (http://www.cubic.org/docs/hermite.htm)
    # Return NDPointList interpolating a path along all points in this list

    size = lists.collect { |l| l.size }.max
    STDERR.puts size

    h = Matrix[
        [ 2,  -2,   1,   1 ],
        [-3,   3,  -2,  -1 ],
        [ 0,   0,   1,   0 ],
        [ 1,   0,   0,   0 ],
    ]

    # XXX This needs to be fixed
    result = []

    idx = 0
    resolution = [resolution] if ! resolution.respond_to? :[]

    # Calculate spline between every two points
    (0..(size-2)).each do |i|
        p1 = lists_at(lists, i)
        p2 = lists_at(lists, i+1)
        
        # Get surrounding points for calculating tangents
        if i <= 0 then pt1 = p1 else pt1 = lists_at(lists, i-1) end
        if i >= size - 2 then pt2 = p2 else pt2 = lists_at(lists, i+2) end

        # Build tangent points into matrices to calculate tangents.
        t1 = 0.5 * ( Matrix[p2]  - Matrix[pt1] )
        t2 = 0.5 * ( Matrix[pt2] - Matrix[p1] )

        # Build matrix of Hermite parameters
        c = Matrix[p1, p2, t1.row(0), t2.row(0)]

        # Make a set of points
        point_count = (resolution[idx] * 1.0 / size).to_i
        STDERR.puts point_count
        (0..point_count).each do |t|
            r = t/10.0
            s = Matrix[[r**3, r**2, r, 1]]
            tmp = s * h
            p = tmp * c
            result << p.row(0).to_a
        end
        idx += 1
        idx = 0 if idx >= resolution.size
    end
    result
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

++



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/kamelopard/classes.rb', line 76

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

.lists_at(lists, i) ⇒ Object



41
42
43
44
# File 'lib/kamelopard/pointlist.rb', line 41

def Kamelopard.lists_at(lists, i)
    # The modulus ensures lists will repeat if they're not the same size
    lists.collect { |l| l[i % l.size] }
end

.log(level, mod, msg) ⇒ Object



43
44
45
46
# File 'lib/kamelopard/classes.rb', line 43

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



38
39
40
41
# File 'lib/kamelopard/classes.rb', line 38

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 module, categorizing the log entries generally; and the third will be the message



34
35
36
# File 'lib/kamelopard/classes.rb', line 34

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

Instance Method Details

#get_stack_traceObject

:nodoc



954
955
956
957
958
# File 'lib/kamelopard/classes.rb', line 954

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