Top Level Namespace

Defined Under Namespace

Modules: Kamelopard, TelemetryProcessor Classes: Geocoder, GoogleGeocoder, MapquestGeocoder, YahooGeocoder

Instance Method Summary collapse

Instance Method Details

#balloonstyle(text, options = {}) ⇒ Object

Creates a BalloonStyle object.



585
586
587
# File 'lib/kamelopard/helpers.rb', line 585

def balloonstyle(text, options = {})
    Kamelopard::BalloonStyle.new text, options
end

#band(l, p) ⇒ Object

Returns an array of two values, equal to l +/- p%, defining a “band” around the central value l NB! p is interpreted as a percentage, not a fraction. IOW the result is divided by 100.0.



695
696
697
698
# File 'lib/kamelopard/helpers.rb', line 695

def band(l, p)
    f = l * p / 100.0
    [ l - f, l + f ]
end

#bounce(a, b, duration, points, options = {}) ⇒ Object

Generates a series of points in a path that will simulate Earth’s FlyTo in bounce mode, from one view to another. Note that the view objects must be the same type: either LookAt, or Camera. Options include :no_flyto and :show_placemarks, and match make_function_path’s meanings for those options – XXX Fix the limitation that the views must be the same type XXX Make it slow down a bit toward the end of the run ++



759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
# File 'lib/kamelopard/helpers.rb', line 759

def bounce(a, b, duration, points, options = {})
    raise "Arguments to bounce() must either be Camera or LookAt objects, and must be the same type" unless
        ((a.kind_of? Kamelopard::Camera and b.kind_of? Kamelopard::Camera) or
            (a.kind_of? Kamelopard::LookAt and b.kind_of? Kamelopard::LookAt))
    # The idea here is just to generate a function; the hard bit is finding
    # control points.
    include Kamelopard
    include Kamelopard::Functions

    max_alt = a.altitude
    max_alt = b.altitude if b.altitude > max_alt

    bounce_alt = 1.3 * (b.altitude - a.altitude).abs
        # 150 is the result of trial-and-error
    gc = 0.8 * great_circle_distance(a, b) * 150
    bounce_alt = gc if gc > bounce_alt
    #raise "wtf: #{a.inspect}, #{b.inspect}"

    latlonfunc = LatLonInterp.new(a, b) do |x, y, z|
        Line.interpolate(x, y)
    end

    opts = {
        :latitude => Line.interpolate(a.latitude, b.latitude),
        :longitude => Line.interpolate(a.longitude, b.longitude),
        :multidim => [[ latlonfunc, [ :latitude, :longitude ]]],
        :heading => Line.interpolate(a.heading, b.heading),
        :tilt => Line.interpolate(a.tilt, b.tilt),
            # XXX This doesn't really work. An actual altitude requires a
            # value, and a mode, and we ignore the modes because there's no
            # way for us to figure out absolute altitudes given, say,
            # :relativeToGround
                                            # ymin,    ymax        x1         y1
        :altitude => Quadratic.interpolate(a.altitude, b.altitude, 0.5, bounce_alt),
        :altitudeMode => a.altitudeMode,
        :duration => duration * 1.0 / points,
    }
    opts[:no_flyto] = 1 if options.has_key?(:no_flyto)
    opts[:show_placemarks] = 1 if options.has_key?(:show_placemarks)

    if a.kind_of? Camera then
        opts[:roll] = Line.interpolate(a.roll, b.roll)
    else
        opts[:range] = Line.interpolate(a.range, b.range)
    end
    return make_function_path(points, opts)
end

#camera(point = nil, options = {}) ⇒ Object

Creates a Camera object focused on the given point



600
601
602
# File 'lib/kamelopard/helpers.rb', line 600

def camera(point = nil, options = {})
    Kamelopard::Camera.new point, options
end

#cdata(text) ⇒ Object

Creates a CDATA XML::Node. This is useful for, among other things, ExtendedData values



689
690
691
# File 'lib/kamelopard/helpers.rb', line 689

def cdata(text)
    XML::Node.new_cdata text.to_s
end

#circ_bounds(v, max, min) ⇒ Object

Ensures v is within the range [min, max]. Modifies v to be within that range, assuming the number line is circular (as with latitude or longitude)



702
703
704
705
706
707
708
709
710
711
712
713
714
# File 'lib/kamelopard/helpers.rb', line 702

def circ_bounds(v, max, min)
    w = max - min
    if v > max then
        while (v > max) do
            v = v - w
        end
    elsif v < min then
        while (v < min) do
            v = v + w
        end
    end
    v
end

#clear_documentsObject

Clears out all KML documents in memory



26
27
28
29
# File 'lib/kamelopard/helpers.rb', line 26

def clear_documents
    dh = get_doc_holder
    dh.delete_current_doc while dh.documents.size > 0
end

#convert_heading(heading) ⇒ Object

Translates a heading into something between 0 and 360



174
175
176
177
178
179
180
181
182
183
184
# File 'lib/kamelopard/helpers.rb', line 174

def convert_heading(heading)
    if heading > 360 then
        step = -360
    else
        step = 360
    end
    while heading < 0 or heading > 360 do
        heading = heading + step
    end
    heading
end

#deg2rad(a) ⇒ Object



811
812
813
# File 'lib/kamelopard/helpers.rb', line 811

def deg2rad(a)
    a * Math::PI / 180
end

#each_flyto(d) ⇒ Object

Identical to each_placemark, only it deals in gx:FlyTo elements. Although it would be valid KML to use some prefix other than “gx” for Google’s KML extension namespace, this function recognizes only “gx”.



612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# File 'lib/kamelopard/helpers.rb', line 612

def each_flyto(d)
    d.find('//gx:FlyTo').each do |p|
        all_values = {}

        # These fields are part of the abstractview
        view_fields = %w{ latitude longitude heading range tilt roll altitude altitudeMode gx:altitudeMode coordinates}
        # These are other field I'm interested in
        other_fields = %w{ description name }
        all_fields = view_fields.clone
        all_fields.concat(other_fields.clone)
        all_fields.each do |k|
            if k == 'gx:altitudeMode' then
                ix = k
                next unless p.find_first('kml:altitudeMode').nil?
            else
                ix = "kml:#{k}"
            end
            r = k == "gx:altitudeMode" ? :altitudeMode : k.to_sym
            tmp = p.find_first("descendant::#{ix}")
            next if tmp.nil?
            all_values[k == "gx:altitudeMode" ? :altitudeMode : k.to_sym ] = tmp.content
        end
        view_values = {}
        view_fields.each do |v| view_values[v.to_sym] = all_values[v.to_sym].clone if all_values.has_key? v.to_sym end
        yield make_view_from(view_values), all_values
    end
end

#each_placemark(d) ⇒ Object

Pulls all Placemark elements from the XML::Document d and yields each in turn to the caller. Assumes “kml” is the namespace prefix for standard KML objects. – XXX This currently expects Placemarks to contain LookAt or Camera objects. It should do something useful with placemarks based on Points, or other objects ++



646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
# File 'lib/kamelopard/helpers.rb', line 646

def each_placemark(d)
    d.find('//kml:Placemark').each do |p|
        all_values = {}

        # These fields are part of the abstractview
        view_fields = %w{ latitude longitude heading range tilt roll altitude altitudeMode gx:altitudeMode }
        # These are other field I'm interested in
        other_fields = %w{ description name }
        all_fields = view_fields.clone
        all_fields.concat(other_fields.clone)
        all_fields.each do |k|
            if k == 'gx:altitudeMode' then
                ix = k
                next unless p.find_first('kml:altitudeMode').nil?
            else
                ix = "kml:#{k}"
            end
            r = k == "gx:altitudeMode" ? :altitudeMode : k.to_sym
            tmp = p.find_first("descendant::#{ix}")
            next if tmp.nil?
            all_values[k == "gx:altitudeMode" ? :altitudeMode : k.to_sym ] = tmp.content
        end
        view_values = {}
        view_fields.each do |v| view_values[v.to_sym] = all_values[v.to_sym].clone if all_values.has_key? v.to_sym end
        yield make_view_from(view_values), all_values
    end
end

#fade_balloon_for(obj, value, options = {}) ⇒ Object

Fades a placemark’s popup balloon in or out. Takes as arguments the placemark object, 0 or 1 to hide or show the balloon, respectively, and a has of options to be passed to the AnimatedUpdate object created by this function. In order to have the balloon fade over some noticeable time, at minimum the :duration attribute in this hash should be set to some meaningful number of seconds.



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

def fade_balloon_for(obj, value, options = {})
    au = Kamelopard::AnimatedUpdate.new [], options
    if ! obj.is_a? Kamelopard::Placemark then
        raise "Can't show balloons for things that aren't placemarks"
    end
    a = XML::Node.new 'Change'
    b = XML::Node.new 'Placemark'
    b.attributes['targetId'] = obj.kml_id
    c = XML::Node.new 'color'
    c << XML::Node.new_text(value.to_s)
    b << c
    a << b
    au << a
end

#fade_in_balloon_for(p, options = {}) ⇒ Object

Refer to fade_balloon_for. This function only fades the balloon in.



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

def fade_in_balloon_for(p, options = {})
    fade_balloon_for(p, 'ffffffff', options)
end

#fade_out_balloon_for(obj, options = {}) ⇒ Object

Refer to fade_balloon_for. This function only fades the balloon out.



94
95
96
# File 'lib/kamelopard/helpers.rb', line 94

def fade_out_balloon_for(obj, options = {})
    fade_balloon_for(obj, '00ffffff', options)
end

#fade_overlay(ov, show, options = {}) ⇒ Object

Fades a screen overlay in or out. The show argument is boolean; true to show the overlay, or false to hide it. The fade will happen smoothly (as opposed to immediately) if the options hash includes a :duration element set to some positive number of seconds.



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/kamelopard/helpers.rb', line 345

def fade_overlay(ov, show, options = {})
    color = '00ffffff'
    color = 'ffffffff' if show
    if ov.is_a? String then
        id = ov
    else
        id = ov.kml_id
    end

    a = XML::Node.new 'Change'
    b = XML::Node.new 'ScreenOverlay'
    b.attributes['targetId'] = id
    c = XML::Node.new 'color'
    c << XML::Node.new_text(color)
    b << c
    a << b
    k = Kamelopard::AnimatedUpdate.new [a], options
end

#fly_placemarks(d, num_points = 30, ctrl_point_dur = 1, ctrl_point_cb = nil) ⇒ Object

Accepts an XML::Document object containing some placemarks. Creates a spline between those placemarks and flies along it.

d: The XML::Document object num_points: The number of points to include on the final flight path ctrl_point_dur: Default duration for each control point. Overridden by

the return value of ctrl_point_cb

ctrl_point_cb: Callback function accepting a control point view and a

sequence number, which returns the duration for this control point

Yields each fly_to object and a sequence number, in case the user wants to manipulate them further.



840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
# File 'lib/kamelopard/helpers.rb', line 840

def fly_placemarks(d, num_points = 30, ctrl_point_dur = 1, ctrl_point_cb = nil)
    i = 0
    sp = Kamelopard::Functions::ViewSplineFunction.new

    each_placemark(d) do |p, v|
        dur = ctrl_point_dur
        if ! ctrl_point_cb.nil?
            dur = ctrl_point_cb.call(p, i)
        end
        raise "The control point duration cannot be nil" if dur.nil?
        sp.add_control_point(p, dur)
        i += 1
    end

    (1..num_points).each do |i|
        f = fly_to sp.run_function(i.to_f/30.0), :duration => 0.8, :mode => :smooth
        yield f, i if block_given?
    end
end

#fly_to(view = nil, options = {}) ⇒ Object

Creates a FlyTo object flying to the given AbstractView



605
606
607
# File 'lib/kamelopard/helpers.rb', line 605

def fly_to(view = nil, options = {})
    Kamelopard::FlyTo.new view, options
end

#folder(name) ⇒ Object

Creates a new Folder with the current name



150
151
152
# File 'lib/kamelopard/helpers.rb', line 150

def folder(name)
    Kamelopard::Folder.new(name)
end

#get_actionsObject

Returns the Document’s VSRActions as a YAML string, suitable for writing to a viewsyncrelay configuration file



741
742
743
# File 'lib/kamelopard/helpers.rb', line 741

def get_actions
    get_document.get_actions_yaml
end

#get_doc_holderObject

Returns the singleton Kamelopard::DocumentHolder object



16
17
18
# File 'lib/kamelopard/helpers.rb', line 16

def get_doc_holder
    return Kamelopard::DocumentHolder.instance
end

#get_documentObject

Returns the current Document object



11
12
13
# File 'lib/kamelopard/helpers.rb', line 11

def get_document()
    Kamelopard::DocumentHolder.instance.current_document
end

#get_folderObject

Returns the current Folder object



143
144
145
146
147
# File 'lib/kamelopard/helpers.rb', line 143

def get_folder()
    f = Kamelopard::DocumentHolder.instance.current_document.folders.last
    Kamelopard::Folder.new() if f.nil?
    Kamelopard::DocumentHolder.instance.current_document.folders.last
end

#get_kmlObject

Returns the KML that makes up the current Kamelopard::Document



118
119
120
# File 'lib/kamelopard/helpers.rb', line 118

def get_kml
    Kamelopard::DocumentHolder.instance.current_document.get_kml_document
end

#get_kml_stringObject

Returns the KML that makes up the current Document, as a string



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

def get_kml_string
    get_kml.to_s
end

#get_tourObject

Returns the current Tour object



133
134
135
# File 'lib/kamelopard/helpers.rb', line 133

def get_tour()
    Kamelopard::DocumentHolder.instance.current_document.tour
end

#great_circle_distance(a, b) ⇒ Object

Returns the great circle distance between two points



808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
# File 'lib/kamelopard/helpers.rb', line 808

def great_circle_distance(a, b)
    # Stolen from http://rosettacode.org/wiki/Haversine_formula#Ruby

    def deg2rad(a)
        a * Math::PI / 180
    end

    radius = 6371  # rough radius of the Earth, in kilometers
    lat1, long1 = [Math::PI * a.latitude / 180.0, Math::PI * a.longitude / 180.0]
    lat2, long2 = [Math::PI * b.latitude / 180.0, Math::PI * b.longitude / 180.0]
    d = 2 * radius *
        Math.asin( Math.sqrt(
            Math.sin((lat2-lat1)/2)**2 +
            Math.cos(lat1) * Math.cos(lat2) *
            Math.sin((long2 - long1)/2)**2
        ))

    return d
end

#hide_balloon_for(obj, options = {}) ⇒ Object

Hides the popup balloon for a Placemark or ScreenOverlay object. Require the object as the first argument, and takes a hash of options passed to the AnimatedUpdate object this functino creates. See also show_balloon_for and toggle_balloon_for



60
61
62
# File 'lib/kamelopard/helpers.rb', line 60

def hide_balloon_for(obj, options = {})
    toggle_balloon_for(obj, 0, options)
end

#iconstyle(href = nil, options = {}) ⇒ Object

Creates an IconStyle object.



575
576
577
# File 'lib/kamelopard/helpers.rb', line 575

def iconstyle(href = nil, options = {})
    Kamelopard::IconStyle.new href, options
end

#labelstyle(scale = 1, options = {}) ⇒ Object

Creates a LabelStyle object.



580
581
582
# File 'lib/kamelopard/helpers.rb', line 580

def labelstyle(scale = 1, options = {})
    Kamelopard::LabelStyle.new scale, options
end

#lat_check(l) ⇒ Object

These functions ensure the given value is within appropriate bounds for a latitude or longitude. Modifies it as necessary if it’s not.



718
719
720
# File 'lib/kamelopard/helpers.rb', line 718

def lat_check(l)
    circ_bounds(l * 1.0, 90.0, -90.0)
end

#long_check(l) ⇒ Object

See lat_check()



723
724
725
# File 'lib/kamelopard/helpers.rb', line 723

def long_check(l)
    circ_bounds(l * 1.0, 180.0, -180.0)
end

#look_at(point = nil, options = {}) ⇒ Object

Creates a LookAt object focused on the given point



595
596
597
# File 'lib/kamelopard/helpers.rb', line 595

def look_at(point = nil, options = {})
    Kamelopard::LookAt.new point, options
end

#make_tour_index(erb = nil, options = {}) ⇒ Object

Makes an HTML tour index, linked to a one-pixel screen overlay. The HTML contains links to start each tour.



676
677
678
# File 'lib/kamelopard/helpers.rb', line 676

def make_tour_index(erb = nil, options = {})
    get_document.make_tour_index(erb, options)
end

#make_view_from(options = {}) ⇒ Object

Given a hash of values, this creates an AbstractView object. Possible values in the hash are :latitude, :longitude, :altitude, :altitudeMode, :tilt, :heading, :roll, :range, :begin, :end, and :when. If the hash specifies :roll, a Camera object will result; otherwise, a LookAt object will result. Specifying both :roll and :range will still result in a Camera object, and the :range option will be ignored.

:begin, :end, and :when are used to create the view’s timestamp or timespan

:roll, :range, and the timestamp / timespan options have no default; all other values default to 0 except :altitudeMode, which defaults to :relativeToGround.



514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/kamelopard/helpers.rb', line 514

def make_view_from(options = {})
    o = {}
    o.merge! options
    options.each do |k, v|
        o[k.to_sym] = v unless k.kind_of? Symbol
    end

    # Set defaults
    [
        [ :altitude, 0 ],
        [ :altitudeMode, :relativeToGround ],
        [ :latitude, 0 ],
        [ :longitude, 0 ],
        [ :tilt, 0 ],
        [ :heading, 0 ],
        [ :extrude, 0 ],
    ].each do |a|
        o[a[0]] = a[1] unless o.has_key? a[0]
    end

    p = point o[:longitude].to_f, o[:latitude].to_f, o[:altitude].to_f, o[:altitudeMode], o[:extrude].to_i

    if o.has_key? :roll then
        view = Kamelopard::Camera.new p
    else
        view = Kamelopard::LookAt.new p
    end

    if o.has_key? :when then
        o[:timestamp] = Kamelopard::TimeStamp.new(o[:when])
    elsif o.has_key? :begin or o.has_key? :end then
        (b, e) = [nil, nil]
        b = o[:begin] if o.has_key? :begin
        e = o[:end] if o.has_key? :end
        o[:timespan] = Kamelopard::TimeSpan.new(b, e)
    end

    [ :altitudeMode, :timespan, :timestamp, :viewerOptions ].each do |a|
        #p o[a] if o.has_key? a and a == :timestamp
        view.method("#{a.to_s}=").call(o[a]) if o.has_key? a
    end

    [ :tilt, :heading, :range, :roll].each do |a|
        #p o[a] if o.has_key? a and a == :timestamp
        view.method("#{a.to_s}=").call(o[a].to_f) if o.has_key? a
    end

    view
end

#name_document(name) ⇒ Object

Names (or renames) the current Document object, and returns it



161
162
163
164
# File 'lib/kamelopard/helpers.rb', line 161

def name_document(name)
    Kamelopard::DocumentHolder.instance.current_document.name = name
    return Kamelopard::DocumentHolder.instance.current_document
end

#name_folder(name) ⇒ Object

Names (or renames) the current Folder, and returns it



155
156
157
158
# File 'lib/kamelopard/helpers.rb', line 155

def name_folder(name)
    Kamelopard::DocumentHolder.instance.current_document.folder.name = name
    return Kamelopard::DocumentHolder.instance.current_document.folder
end

#name_tour(name) ⇒ Object

Sets a name for the current Tour



138
139
140
# File 'lib/kamelopard/helpers.rb', line 138

def name_tour(name)
    Kamelopard::DocumentHolder.instance.current_document.tour.name = name
end

#orbit(center, range = 100, tilt = 90, startHeading = 0, endHeading = 360, options = {}) ⇒ Object

Creates a list of FlyTo elements to orbit and look at a given point (center), at a given range (in meters), starting and ending at given angles (in degrees) from the center, where 0 and 360 (and -360, and 720, and -980, etc.) are north. To orbit multiple times, add or subtract 360 from the endHeading. The tilt argument matches the KML LookAt tilt argument already_there, if true, means we’ve already flown to the initial point The options hash can contain:

:duration   The total duration of the orbit. Defaults to 0, which means it will take 2 seconds per step
:step       How much to change the heading for each flyto. Defaults to some strange value >= 5
:already_there
            Default false. Indicates that we've already flown to the initial position


198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/kamelopard/helpers.rb', line 198

def orbit(center, range = 100, tilt = 90, startHeading = 0, endHeading = 360, options = {})
    duration = options.has_key?(:duration) ? options[:duration] : 0
    step = options.has_key?(:step) ? options[:step] : nil
    already_there = options.has_key?(:already_there) ? options[:already_there] : false

    am = center.altitudeMode

    if not step.nil? then
        if (endHeading - startHeading > 0 and step < 0) or (endHeading - startHeading < 0 and step > 0) then
            raise "Given start = #{startHeading}, end = #{endHeading}, and step = #{step}, this will be an infinite loop"
        end
    end

    # We want at least 5 points (arbitrarily chosen value), plus at least 5 for
    # each full revolution

    # When I tried this all in one step, ruby told me 360 / 10 = 1805. I'm sure
    # there's some reason why this is a feature and not a bug, but I'd rather
    # not look it up right now.
    dur = 2
    if step.nil? then
        num = (endHeading - startHeading).abs
        num_steps = ((endHeading - startHeading) / 360.0).to_i.abs * 5 + 5
        step = num / num_steps
        step = 1 if step < 1
        step = step * -1 if startHeading > endHeading
        if already_there
            num_steps = num_steps - 1
            startHeading = startHeading + step
        end
        if duration != 0
        dur = duration.to_f / num_steps
        end
    else
        dur = duration * 1.0 / ((endHeading - startHeading) * 1.0 / step) if duration != 0
        startHeading = startHeading + step if already_there
    end

    lastval = startHeading
    mode = :bounce
    mode = :smooth if already_there
    startHeading.step(endHeading, step) do |theta|
        lastval = theta
        heading = convert_heading theta
        fly_to Kamelopard::LookAt.new(center, :heading => heading, :tilt => tilt, :range => range, :altitudeMode => am), :duration => dur, :mode => mode
        mode = :smooth
    end
    if lastval != endHeading then
        fly_to Kamelopard::LookAt.new(center, :heading => convert_heading(endHeading), :tilt => tilt, :range => range, :altitudeMode => am), :duration => dur, :mode => :smooth
    end
end

#pause(p, options = {}) ⇒ Object

Inserts a KML gx:Wait element



128
129
130
# File 'lib/kamelopard/helpers.rb', line 128

def pause(p, options = {})
    Kamelopard::Wait.new p, options
end

#placemark(name = nil, options = {}) ⇒ Object

Creates a Placemark with the given name. Other Placemark attributes are set in the options hash. The note under the Kamelopard::Placemark class applies equally to the results of this function.



113
114
115
# File 'lib/kamelopard/helpers.rb', line 113

def placemark(name = nil, options = {})
    Kamelopard::Placemark.new name, options
end

#point(lo, la, alt = 0, mode = nil, extrude = false) ⇒ Object

Creates a Point object. Arguments are latitude, longitude, altitude, altitude mode, and extrude



105
106
107
108
# File 'lib/kamelopard/helpers.rb', line 105

def point(lo, la, alt=0, mode=nil, extrude = false)
    m = ( mode.nil? ? :clampToGround : mode )
    Kamelopard::Point.new(lo, la, alt, :altitudeMode => m, :extrude => extrude)
end

#screenoverlay(options = {}) ⇒ Object

Creates a ScreenOverlay object



565
566
567
# File 'lib/kamelopard/helpers.rb', line 565

def screenoverlay(options = {})
    Kamelopard::ScreenOverlay.new options
end

#set_flyto_mode_to(mode) ⇒ Object

Changes the default FlyTo mode. Possible values are :smooth and :bounce



21
22
23
# File 'lib/kamelopard/helpers.rb', line 21

def set_flyto_mode_to(mode)
    Kamelopard::DocumentHolder.instance.current_document.flyto_mode = mode
end

#set_prefix_to(a) ⇒ Object

Sets a prefix for all kml_id objects. Note that this does not change previously created objects’ kml_ids… just new kml_ids going forward.



282
283
284
# File 'lib/kamelopard/helpers.rb', line 282

def set_prefix_to(a)
    Kamelopard.id_prefix = a
end

#show_balloon_for(obj, options = {}) ⇒ Object

Displays the popup balloon for a Placemark or ScreenOverlay object. Require the object as the first argument, and takes a hash of options passed to the AnimatedUpdate object this functino creates. See also show_balloon_for and toggle_balloon_for



68
69
70
# File 'lib/kamelopard/helpers.rb', line 68

def show_balloon_for(obj, options = {})
    toggle_balloon_for(obj, 1, options)
end

#show_hide_balloon(p, wait, options = {}) ⇒ Object

Superceded by toggle_balloon_for, but retained for backward compatibility



681
682
683
684
685
# File 'lib/kamelopard/helpers.rb', line 681

def show_hide_balloon(p, wait, options = {})
    show_balloon_for p, options
    pause wait
    hide_balloon_for p, options
end

#sound_cue(href, ds = nil) ⇒ Object

Adds a SoundCue object.



251
252
253
# File 'lib/kamelopard/helpers.rb', line 251

def sound_cue(href, ds = nil)
    Kamelopard::SoundCue.new href, ds
end

#style(options = {}) ⇒ Object

Creates a Style object.



590
591
592
# File 'lib/kamelopard/helpers.rb', line 590

def style(options = {})
    Kamelopard::Style.new options
end

#to_constraint(arr) ⇒ Object

Turns an array of two values (min, max) into a string suitable for use as a viewsyncrelay constraint



729
730
731
# File 'lib/kamelopard/helpers.rb', line 729

def to_constraint(arr)
    "[#{arr[0]}, #{arr[1]}]"
end

#toggle_balloon_for(obj, value, options = {}) ⇒ Object

Shows or hides the popup balloon for Placemark and ScreenOverlay objects. Arguments are the object; 0 or 1 to hide or show the balloon, respectively; and a hash of options to be added to the AnimatedUpdate object this function creates. Refer to the AnimatedUpdate documentation for details on possible options.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/kamelopard/helpers.rb', line 36

def toggle_balloon_for(obj, value, options = {})
    au = Kamelopard::AnimatedUpdate.new [], options
    if ! obj.kind_of? Kamelopard::Placemark and ! obj.kind_of? Kamelopard::ScreenOverlay then
        raise "Can't show balloons for things that aren't Placemarks or ScreenOverlays"
    end
    a = XML::Node.new 'Change'
    # XXX This can probably be more robust, based on just the class's name
    if obj.kind_of? Kamelopard::Placemark then
        b = XML::Node.new 'Placemark'
    else
        b = XML::Node.new 'ScreenOverlay'
    end
    b.attributes['targetId'] = obj.kml_id
    c = XML::Node.new 'gx:balloonVisibility'
    c << XML::Node.new_text(value.to_s)
    b << c
    a << b
    au << a
end

#tour_from_points(points, options = {}) ⇒ Object

Creates a tour from a series of points, using TelemetryProcessor::add_flyto.

The first argument is an ordered array of points, where each point is represented as an array of longitude, latitude, and altitude (in meters), in that order. The only options currently recognized are :pause and :exaggerate. :pause controls the flight speed by specifying the duration of each FlyTo element. Its default is 1 second. There is currently no mechanism for having anything other than constant durations between points. :exaggerate is an numeric value that defaults to 1; when set to larger values, it will exaggerate tilt and roll values, because they’re sort of boring at normal scale.



491
492
493
494
495
496
497
498
499
500
# File 'lib/kamelopard/helpers.rb', line 491

def tour_from_points(points, options = {})
    options.merge!({
        :pause => 1,
        :exaggerate => 1
    }) { |key, old, new| old }
    TelemetryProcessor.options = options
    (0..(points.size-3)).each do |i|
        TelemetryProcessor::add_flyto points[i,3]
    end
end

#write_actions_to(filename = 'actions.yml') ⇒ Object

Writes actions to a viewsyncrelay config file



746
747
748
# File 'lib/kamelopard/helpers.rb', line 746

def write_actions_to(filename = 'actions.yml')
    File.open(filename, 'w') do |f| f.write get_actions end
end

#write_documentsObject

Writes all KML documents in memory to their filenames, as set in their :filename properties. It’s a good idea to set this property for each Document before calling this function.



334
335
336
337
338
339
# File 'lib/kamelopard/helpers.rb', line 334

def write_documents
    get_doc_holder.documents.each do |d|
        get_doc_holder.set_current d
        write_kml_to d.filename
    end
end

#write_kml_to(filename = 'doc.kml', actions_file = 'actions.yml') ⇒ Object

Writes KML output (and if applicable, viewsyncrelay configuration) to files. Include a file name for the actions_file argument to get viewsyncrelay configuration output as well. Note that this configuration includes only the actions section; users are responsible for creating appropriate linkages, inputs and outputs, and transformations, on their own, presumably in a separate file.

If the filename ends in .kmz, it will create a KMZ file archive instead, with this file as doc.kml in that archive. Note that the KMZ will not contain any other files, like images that Overlay objects might depend on – TODO: Get it to add any other files it depends on (images, etc.) automatically ++



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/kamelopard/helpers.rb', line 299

def write_kml_to(filename = 'doc.kml', actions_file = 'actions.yml')
    if filename =~ /\.kmz$/
        # Require rubyzip here so that we don't write to doc.kml and then
        # leave it there when we die later finding out we don't have
        # rubyzip
        require 'zip'
        require 'tempfile'

        kmlfile = Tempfile.new("kamelopard-#{filename}")
        make_kmz = true
    else
        make_kmz = false
        kmlfile = File.open(filename, 'w')
    end

    begin
        kmlfile.write get_kml.to_s
        if (get_document.vsr_actions.size > 0) then
            File.open(actions_file, 'w') do |f| f.write get_document.get_actions end
        end

        if make_kmz
            Zip::File.open(filename, Zip::File::CREATE) do |zipfile|
                zipfile.add('doc.kml', kmlfile.path)
            end
        end
    ensure
        kmlfile.close unless kmlfile.closed?
        kmlfile.unlink if make_kmz
    end
end

#xy(x = 0.5, y = 0.5, xt = :fraction, yt = :fraction) ⇒ Object

Creates an XY object, for use when building Overlay objects



570
571
572
# File 'lib/kamelopard/helpers.rb', line 570

def xy(x = 0.5, y = 0.5, xt = :fraction, yt = :fraction)
    Kamelopard::XY.new x, y, xt, yt
end

#zoom_out(dist = 1000, dur = 0, mode = nil) ⇒ Object



166
167
168
169
170
171
# File 'lib/kamelopard/helpers.rb', line 166

def zoom_out(dist = 1000, dur = 0, mode = nil)
    l = Kamelopard::DocumentHolder.instance.current_document.tour.last_abs_view
    raise "No current position to zoom out from\n" if l.nil?
    l.range += dist
    Kamelopard::FlyTo.new(l, nil, dur, mode)
end