kamelopard 0.0.5 → 0.0.6
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.
- data/lib/kamelopard/classes.rb +141 -32
- data/lib/kamelopard/functions.rb +157 -3
- data/lib/kamelopard/pointlist.rb +9 -5
- metadata +5 -7
    
        data/lib/kamelopard/classes.rb
    CHANGED
    
    | @@ -4,6 +4,8 @@ | |
| 4 4 | 
             
            # http://code.google.com/apis/kml/documentation/kmlreference.html for a
         | 
| 5 5 | 
             
            # description of KML
         | 
| 6 6 |  | 
| 7 | 
            +
            # XXX gx:balloonVisibility isn't represented here. Fix that.
         | 
| 8 | 
            +
             | 
| 7 9 | 
             
            module Kamelopard
         | 
| 8 10 | 
             
                require 'singleton'
         | 
| 9 11 | 
             
                require 'kamelopard/pointlist'
         | 
| @@ -11,6 +13,7 @@ module Kamelopard | |
| 11 13 | 
             
                require 'yaml'
         | 
| 12 14 |  | 
| 13 15 | 
             
                @@sequence = 0
         | 
| 16 | 
            +
                @@id_prefix = ''
         | 
| 14 17 |  | 
| 15 18 | 
             
                def Kamelopard.get_document
         | 
| 16 19 | 
             
                    Document.instance
         | 
| @@ -21,6 +24,14 @@ module Kamelopard | |
| 21 24 | 
             
                    @@sequence
         | 
| 22 25 | 
             
                end
         | 
| 23 26 |  | 
| 27 | 
            +
                def Kamelopard.id_prefix=(a)
         | 
| 28 | 
            +
                    @@id_prefix = a
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def Kamelopard.id_prefix
         | 
| 32 | 
            +
                    @@id_prefix
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 24 35 | 
             
                #--
         | 
| 25 36 | 
             
                # Intelligently adds elements to a KML object. Expects the KML object as the
         | 
| 26 37 | 
             
                # first argument, an array as the second.  Each entry in the array is itself an
         | 
| @@ -54,7 +65,7 @@ module Kamelopard | |
| 54 65 | 
             
                # Accepts XdX'X.X", XDXmX.XXs, XdXmX.XXs, or X.XXXX with either +/- or N/E/S/W
         | 
| 55 66 | 
             
                #++
         | 
| 56 67 | 
             
                def Kamelopard.convert_coord(a)    # :nodoc
         | 
| 57 | 
            -
                    a = a.to_s.upcase.strip
         | 
| 68 | 
            +
                    a = a.to_s.upcase.strip.gsub(/\s+/, '')
         | 
| 58 69 |  | 
| 59 70 | 
             
                    mult = 1
         | 
| 60 71 | 
             
                    if a =~ /^-/ then
         | 
| @@ -80,6 +91,10 @@ module Kamelopard | |
| 80 91 | 
             
                        # coord is in d'"
         | 
| 81 92 | 
             
                        p = a.split /[D"']/
         | 
| 82 93 | 
             
                        a = p[0].to_f + (p[2].to_f / 60.0 + p[1].to_f) / 60.0
         | 
| 94 | 
            +
                    elsif m = (a =~ /^(\d+)°(\d+)'(\d+\.\d+)?"$/) then
         | 
| 95 | 
            +
                        # coord is in °'"
         | 
| 96 | 
            +
                        b = a
         | 
| 97 | 
            +
                        a = $1.to_f + ($3.to_f / 60.0 + $2.to_f) / 60.0
         | 
| 83 98 | 
             
                    else
         | 
| 84 99 | 
             
                        raise "Couldn't determine coordinate format for #{a}"
         | 
| 85 100 | 
             
                    end
         | 
| @@ -103,13 +118,17 @@ module Kamelopard | |
| 103 118 | 
             
                end
         | 
| 104 119 |  | 
| 105 120 | 
             
                # Base class for all Kamelopard objects. Manages object ID and a single
         | 
| 106 | 
            -
                # comment string associated with the object
         | 
| 121 | 
            +
                # comment string associated with the object. Object IDs are stored in the
         | 
| 122 | 
            +
                # kml_id attribute, and are prefixed with the value last passed to
         | 
| 123 | 
            +
                # Kamelopard.id_prefix=, if anything. Note that assigning this prefix will
         | 
| 124 | 
            +
                # *not* change the IDs of Kamelopard objects that are already
         | 
| 125 | 
            +
                # initialized... just ones initialized thereafter.
         | 
| 107 126 | 
             
                class Object
         | 
| 108 127 | 
             
                    attr_accessor :kml_id
         | 
| 109 128 | 
             
                    attr_reader :comment
         | 
| 110 129 |  | 
| 111 130 | 
             
                    def initialize(options = {})
         | 
| 112 | 
            -
                        @kml_id = "#{self.class.name.gsub('Kamelopard::', '')}_#{ Kamelopard.get_next_id }"
         | 
| 131 | 
            +
                        @kml_id = "#{Kamelopard.id_prefix}#{self.class.name.gsub('Kamelopard::', '')}_#{ Kamelopard.get_next_id }"
         | 
| 113 132 |  | 
| 114 133 | 
             
                        options.each do |k, v|
         | 
| 115 134 | 
             
                            method = "#{k}=".to_sym
         | 
| @@ -164,8 +183,8 @@ module Kamelopard | |
| 164 183 |  | 
| 165 184 | 
             
                    def initialize(longitude = nil, latitude = nil, altitude = nil, options = {})
         | 
| 166 185 | 
             
                        super options
         | 
| 167 | 
            -
                        @longitude = longitude unless longitude.nil?
         | 
| 168 | 
            -
                        @latitude = latitude unless latitude.nil?
         | 
| 186 | 
            +
                        @longitude = Kamelopard.convert_coord(longitude) unless longitude.nil?
         | 
| 187 | 
            +
                        @latitude = Kamelopard.convert_coord(latitude) unless latitude.nil?
         | 
| 169 188 | 
             
                        @altitude = altitude unless altitude.nil?
         | 
| 170 189 | 
             
                    end
         | 
| 171 190 |  | 
| @@ -357,8 +376,8 @@ module Kamelopard | |
| 357 376 |  | 
| 358 377 | 
             
                        @heading = 0
         | 
| 359 378 | 
             
                        @tilt = 0
         | 
| 360 | 
            -
                        @roll =  | 
| 361 | 
            -
                        @range =  | 
| 379 | 
            +
                        @roll = nil
         | 
| 380 | 
            +
                        @range = nil
         | 
| 362 381 | 
             
                        @altitudeMode = :clampToGround
         | 
| 363 382 | 
             
                        @viewerOptions = {}
         | 
| 364 383 |  | 
| @@ -523,6 +542,7 @@ module Kamelopard | |
| 523 542 | 
             
                # Corresponds to KML's TimeSpan object. @begin and @end must be in a format KML
         | 
| 524 543 | 
             
                # understands.
         | 
| 525 544 | 
             
                class TimeSpan < TimePrimitive
         | 
| 545 | 
            +
                # XXX Evidence suggests this doesn't support unbounded intervals. Fix that, if it's true.
         | 
| 526 546 | 
             
                    attr_accessor :begin, :end
         | 
| 527 547 | 
             
                    def initialize(ts_begin = nil, ts_end = nil, options = {})
         | 
| 528 548 | 
             
                        super options
         | 
| @@ -564,14 +584,61 @@ module Kamelopard | |
| 564 584 | 
             
                    end
         | 
| 565 585 | 
             
                end
         | 
| 566 586 |  | 
| 587 | 
            +
                # Corresponds to Data elements within ExtendedData
         | 
| 588 | 
            +
                class Data
         | 
| 589 | 
            +
                    attr_accessor :name, :displayName, :value
         | 
| 590 | 
            +
                    def initialize(name, value, displayName = nil)
         | 
| 591 | 
            +
                        @name = name
         | 
| 592 | 
            +
                        @displayName = displayName
         | 
| 593 | 
            +
                        @value = value
         | 
| 594 | 
            +
                    end
         | 
| 595 | 
            +
             | 
| 596 | 
            +
                    def to_kml(elem = nil)
         | 
| 597 | 
            +
                        v = XML::Node.new 'Data'
         | 
| 598 | 
            +
                        v.attributes['name'] = @name
         | 
| 599 | 
            +
                        Kamelopard.kml_array(v, [
         | 
| 600 | 
            +
                                [@value, 'value'],
         | 
| 601 | 
            +
                                [@displayName, 'displayName']
         | 
| 602 | 
            +
                            ])
         | 
| 603 | 
            +
                        elem << v unless elem.nil?
         | 
| 604 | 
            +
                        v
         | 
| 605 | 
            +
                    end
         | 
| 606 | 
            +
                end
         | 
| 607 | 
            +
             | 
| 608 | 
            +
                # ExtendedData SchemaData objects
         | 
| 609 | 
            +
                class SchemaData
         | 
| 610 | 
            +
                    attr_accessor :schemaUrl, :simpleData
         | 
| 611 | 
            +
                    def initialize(schemaUrl, simpleData = {})
         | 
| 612 | 
            +
                        @schemaUrl = schemaUrl
         | 
| 613 | 
            +
                        raise "SchemaData's simpleData attribute should behave like a hash" unless simpleData.respond_to? :keys
         | 
| 614 | 
            +
                        @simpleData = simpleData
         | 
| 615 | 
            +
                    end
         | 
| 616 | 
            +
             | 
| 617 | 
            +
                    def <<(a)
         | 
| 618 | 
            +
                        @simpleData.merge a
         | 
| 619 | 
            +
                    end
         | 
| 620 | 
            +
             | 
| 621 | 
            +
                    def to_kml(elem = nil)
         | 
| 622 | 
            +
                        s = XML::Node.new 'SchemaData'
         | 
| 623 | 
            +
                        s.attributes['schemaUrl'] = @schemaUrl
         | 
| 624 | 
            +
                        @simpleData.each do |k, v|
         | 
| 625 | 
            +
                            sd = XML::Node.new 'SimpleData', v
         | 
| 626 | 
            +
                            sd.attributes['name'] = k
         | 
| 627 | 
            +
                            s << sd
         | 
| 628 | 
            +
                        end
         | 
| 629 | 
            +
                        elem << v unless elem.nil?
         | 
| 630 | 
            +
                        v
         | 
| 631 | 
            +
                    end
         | 
| 632 | 
            +
                end
         | 
| 633 | 
            +
             | 
| 567 634 | 
             
                # Abstract class corresponding to KML's Feature object.
         | 
| 635 | 
            +
                # XXX Make this support alternate namespaces
         | 
| 568 636 | 
             
                class Feature < Object
         | 
| 569 637 | 
             
                    # Abstract class
         | 
| 570 638 | 
             
                    attr_accessor :visibility, :open, :atom_author, :atom_link, :name,
         | 
| 571 | 
            -
                        :phoneNumber, :description, :abstractView,
         | 
| 572 | 
            -
                        :timeprimitive, :styleUrl, :styleSelector, :region, :metadata | 
| 573 | 
            -
             | 
| 574 | 
            -
                    attr_reader :addressDetails, :snippet
         | 
| 639 | 
            +
                        :phoneNumber, :description, :abstractView, :styles,
         | 
| 640 | 
            +
                        :timeprimitive, :styleUrl, :styleSelector, :region, :metadata
         | 
| 641 | 
            +
                    attr_reader :addressDetails, :snippet, :extendedData
         | 
| 575 642 |  | 
| 576 643 | 
             
                    include Snippet
         | 
| 577 644 |  | 
| @@ -583,6 +650,11 @@ module Kamelopard | |
| 583 650 | 
             
                        @name = name unless name.nil?
         | 
| 584 651 | 
             
                    end
         | 
| 585 652 |  | 
| 653 | 
            +
                    def extendedData=(a)
         | 
| 654 | 
            +
                        raise "extendedData attribute must respond to the 'each' method" unless a.respond_to? :each
         | 
| 655 | 
            +
                        @extendedData = a
         | 
| 656 | 
            +
                    end
         | 
| 657 | 
            +
             | 
| 586 658 | 
             
                    def styles=(a)
         | 
| 587 659 | 
             
                        if a.is_a? Array then
         | 
| 588 660 | 
             
                            @styles = a
         | 
| @@ -665,11 +737,11 @@ module Kamelopard | |
| 665 737 | 
             
                                [@description, 'description'],
         | 
| 666 738 | 
             
                                [@styleUrl, 'styleUrl'],
         | 
| 667 739 | 
             
                                [@styleSelector, lambda { |o| @styleSelector.to_kml(o) }],
         | 
| 668 | 
            -
                                [@metadata, 'Metadata' ] | 
| 669 | 
            -
                                [@extendedData, 'ExtendedData' ]
         | 
| 740 | 
            +
                                [@metadata, 'Metadata' ]
         | 
| 670 741 | 
             
                            ])
         | 
| 671 742 | 
             
                        styles_to_kml(elem)
         | 
| 672 743 | 
             
                        snippet_to_kml(elem) unless @snippet_text.nil?
         | 
| 744 | 
            +
                        extended_data_to_kml(elem) unless @extendedData.nil?
         | 
| 673 745 | 
             
                        @abstractView.to_kml(elem) unless @abstractView.nil?
         | 
| 674 746 | 
             
                        @timeprimitive.to_kml(elem) unless @timeprimitive.nil?
         | 
| 675 747 | 
             
                        @region.to_kml(elem) unless @region.nil?
         | 
| @@ -677,9 +749,18 @@ module Kamelopard | |
| 677 749 | 
             
                        elem
         | 
| 678 750 | 
             
                    end
         | 
| 679 751 |  | 
| 752 | 
            +
                    def extended_data_to_kml(elem)
         | 
| 753 | 
            +
                        v = XML::Node.new 'ExtendedData'
         | 
| 754 | 
            +
                        @extendedData.each do |f|
         | 
| 755 | 
            +
                            v << f.to_kml
         | 
| 756 | 
            +
                        end
         | 
| 757 | 
            +
                        elem << v unless elem.nil?
         | 
| 758 | 
            +
                        v
         | 
| 759 | 
            +
                    end
         | 
| 760 | 
            +
             | 
| 680 761 | 
             
                    def styles_to_kml(elem)
         | 
| 681 762 | 
             
                        @styles.each do |a|
         | 
| 682 | 
            -
                            a.to_kml(elem)
         | 
| 763 | 
            +
                            a.to_kml(elem) unless a.attached?
         | 
| 683 764 | 
             
                        end
         | 
| 684 765 | 
             
                    end
         | 
| 685 766 | 
             
                end
         | 
| @@ -767,27 +848,26 @@ module Kamelopard | |
| 767 848 | 
             
                # scripts can (for now) manage only one Document at a time.
         | 
| 768 849 | 
             
                class Document < Container
         | 
| 769 850 | 
             
                    include Singleton
         | 
| 770 | 
            -
                    attr_accessor :flyto_mode, : | 
| 851 | 
            +
                    attr_accessor :flyto_mode, :folders, :tours, :uses_xal
         | 
| 771 852 |  | 
| 772 853 | 
             
                    def initialize(options = {})
         | 
| 773 | 
            -
                        @ | 
| 774 | 
            -
                        @ | 
| 775 | 
            -
                        @doc_styles = []
         | 
| 854 | 
            +
                        @tours = []
         | 
| 855 | 
            +
                        @folders = []
         | 
| 776 856 | 
             
                        super
         | 
| 777 857 | 
             
                    end
         | 
| 778 858 |  | 
| 779 859 | 
             
                    # Returns the current Tour object
         | 
| 780 860 | 
             
                    def tour
         | 
| 781 | 
            -
                        Tour.new if @ | 
| 782 | 
            -
                        @ | 
| 861 | 
            +
                        Tour.new if @tours.length == 0
         | 
| 862 | 
            +
                        @tours.last
         | 
| 783 863 | 
             
                    end
         | 
| 784 864 |  | 
| 785 865 | 
             
                    # Returns the current Folder object
         | 
| 786 866 | 
             
                    def folder
         | 
| 787 | 
            -
                        if @ | 
| 867 | 
            +
                        if @folders.size == 0 then
         | 
| 788 868 | 
             
                            Folder.new
         | 
| 789 869 | 
             
                        end
         | 
| 790 | 
            -
                        @ | 
| 870 | 
            +
                        @folders.last
         | 
| 791 871 | 
             
                    end
         | 
| 792 872 |  | 
| 793 873 | 
             
                    def get_kml_document
         | 
| @@ -813,15 +893,16 @@ module Kamelopard | |
| 813 893 | 
             
                        super d
         | 
| 814 894 |  | 
| 815 895 | 
             
                        # Print styles first
         | 
| 816 | 
            -
                         | 
| 896 | 
            +
                        #! These get printed out in the call to super, in Feature.to_kml()
         | 
| 897 | 
            +
                        #@styles.map do |a| d << a.to_kml unless a.attached? end
         | 
| 817 898 |  | 
| 818 899 | 
             
                        # then folders
         | 
| 819 | 
            -
                        @ | 
| 900 | 
            +
                        @folders.map do |a|
         | 
| 820 901 | 
             
                            a.to_kml(d) unless a.has_parent?
         | 
| 821 902 | 
             
                        end
         | 
| 822 903 |  | 
| 823 904 | 
             
                        # then tours
         | 
| 824 | 
            -
                        @ | 
| 905 | 
            +
                        @tours.map do |a| a.to_kml(d) end
         | 
| 825 906 |  | 
| 826 907 | 
             
                        d
         | 
| 827 908 | 
             
                    end
         | 
| @@ -949,12 +1030,12 @@ module Kamelopard | |
| 949 1030 | 
             
                   attr_accessor :href, :x, :y, :w, :h, :refreshMode, :refreshInterval, :viewRefreshMode, :viewRefreshTime, :viewBoundScale, :viewFormat, :httpQuery
         | 
| 950 1031 |  | 
| 951 1032 | 
             
                    def href=(h)
         | 
| 952 | 
            -
                        @icon_id = "Icon_#{Kamelopard.get_next_id}" if @icon_id.nil?
         | 
| 1033 | 
            +
                        @icon_id = "#{Kamelopard.id_prefix}Icon_#{Kamelopard.get_next_id}" if @icon_id.nil?
         | 
| 953 1034 | 
             
                        @href = h
         | 
| 954 1035 | 
             
                    end
         | 
| 955 1036 |  | 
| 956 1037 | 
             
                    def icon_to_kml(elem = nil)
         | 
| 957 | 
            -
                        @icon_id = "Icon_#{Kamelopard.get_next_id}" if @icon_id.nil?
         | 
| 1038 | 
            +
                        @icon_id = "#{Kamelopard.id_prefix}Icon_#{Kamelopard.get_next_id}" if @icon_id.nil?
         | 
| 958 1039 | 
             
                        k = XML::Node.new 'Icon'
         | 
| 959 1040 | 
             
                        k.attributes['id'] = @icon_id
         | 
| 960 1041 | 
             
                        Kamelopard.kml_array(k, [
         | 
| @@ -1145,7 +1226,7 @@ module Kamelopard | |
| 1145 1226 | 
             
                    def initialize(options = {})
         | 
| 1146 1227 | 
             
                        super
         | 
| 1147 1228 | 
             
                        @attached = false
         | 
| 1148 | 
            -
                        Document.instance. | 
| 1229 | 
            +
                        Document.instance.styles << self
         | 
| 1149 1230 | 
             
                    end
         | 
| 1150 1231 |  | 
| 1151 1232 | 
             
                    def attached?
         | 
| @@ -1261,6 +1342,8 @@ module Kamelopard | |
| 1261 1342 | 
             
                    def point
         | 
| 1262 1343 | 
             
                        if @geometry.kind_of? Point then
         | 
| 1263 1344 | 
             
                            @geometry
         | 
| 1345 | 
            +
                        elsif @geometry.respond_to? :point then
         | 
| 1346 | 
            +
                            @geometry.point
         | 
| 1264 1347 | 
             
                        else
         | 
| 1265 1348 | 
             
                            raise "This placemark uses a non-point geometry, but the operation you're trying requires a point object"
         | 
| 1266 1349 | 
             
                        end
         | 
| @@ -1291,6 +1374,8 @@ module Kamelopard | |
| 1291 1374 | 
             
                    def view=(view)
         | 
| 1292 1375 | 
             
                        if view.kind_of? AbstractView then
         | 
| 1293 1376 | 
             
                            @view = view
         | 
| 1377 | 
            +
                        elsif view.respond_to? :abstractView then
         | 
| 1378 | 
            +
                            @view = view.abstractView
         | 
| 1294 1379 | 
             
                        else
         | 
| 1295 1380 | 
             
                            @view = LookAt.new view
         | 
| 1296 1381 | 
             
                        end
         | 
| @@ -1684,11 +1769,8 @@ module Kamelopard | |
| 1684 1769 | 
             
                    def initialize(icon, options = {})
         | 
| 1685 1770 | 
             
                        @altitude = 0
         | 
| 1686 1771 | 
             
                        @altitudeMode = :clampToGround
         | 
| 1772 | 
            +
                        @href = icon
         | 
| 1687 1773 | 
             
                        super options
         | 
| 1688 | 
            -
                        @latlonbox = latlonbox
         | 
| 1689 | 
            -
                        @latlonquad = latlonquad
         | 
| 1690 | 
            -
                        @altitude = altitude
         | 
| 1691 | 
            -
                        @altitudeMode = altitudeMode
         | 
| 1692 1774 | 
             
                    end
         | 
| 1693 1775 |  | 
| 1694 1776 | 
             
                    def to_kml(elem = nil)
         | 
| @@ -1932,6 +2014,7 @@ module Kamelopard | |
| 1932 2014 | 
             
                        @extrude = 0
         | 
| 1933 2015 | 
             
                        @altitudeMode = :clampToGround
         | 
| 1934 2016 | 
             
                        @inner = []
         | 
| 2017 | 
            +
                        @outer = outer
         | 
| 1935 2018 | 
             
                        super options
         | 
| 1936 2019 | 
             
                    end
         | 
| 1937 2020 |  | 
| @@ -2039,5 +2122,31 @@ module Kamelopard | |
| 2039 2122 | 
             
                    end
         | 
| 2040 2123 | 
             
                end
         | 
| 2041 2124 |  | 
| 2125 | 
            +
                class Track < Geometry
         | 
| 2126 | 
            +
                    attr_accessor :altitudeMode, :when, :coord, :angles, :model
         | 
| 2127 | 
            +
                    def initialize(options = {})
         | 
| 2128 | 
            +
                        @when = []
         | 
| 2129 | 
            +
                        @coord = []
         | 
| 2130 | 
            +
                        @angles = []
         | 
| 2131 | 
            +
                        super
         | 
| 2132 | 
            +
                    end
         | 
| 2133 | 
            +
             | 
| 2134 | 
            +
                    def to_kml(elem = nil)
         | 
| 2135 | 
            +
                        e = XML::Node.new 'gx:Track'
         | 
| 2136 | 
            +
                        [
         | 
| 2137 | 
            +
                            [ @coord, 'gx:coord' ],
         | 
| 2138 | 
            +
                            [ @when, 'when' ],
         | 
| 2139 | 
            +
                            [ @angles, 'gx:angles' ],
         | 
| 2140 | 
            +
                        ].each do |a|
         | 
| 2141 | 
            +
                            a[0].each do |g|
         | 
| 2142 | 
            +
                                w = XML::Node.new a[1], g.to_s
         | 
| 2143 | 
            +
                                e << w
         | 
| 2144 | 
            +
                            end
         | 
| 2145 | 
            +
                        end
         | 
| 2146 | 
            +
                        elem << e unless elem.nil?
         | 
| 2147 | 
            +
                        e
         | 
| 2148 | 
            +
                    end
         | 
| 2149 | 
            +
                end
         | 
| 2150 | 
            +
             | 
| 2042 2151 | 
             
            end
         | 
| 2043 2152 | 
             
            # End of Kamelopard module
         | 
    
        data/lib/kamelopard/functions.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # vim:ts=4:sw=4:et:smartindent:nowrap
         | 
| 2 2 | 
             
            def fly_to(p, d = 0, r = 100, m = nil)
         | 
| 3 3 | 
             
                m = Kamelopard::Document.instance.flyto_mode if m.nil?
         | 
| 4 | 
            -
                Kamelopard::FlyTo.new | 
| 4 | 
            +
                Kamelopard::FlyTo.new p, :range => r, :duration => d, :mode => m
         | 
| 5 5 | 
             
            end
         | 
| 6 6 |  | 
| 7 7 | 
             
            def set_flyto_mode_to(a)
         | 
| @@ -15,7 +15,7 @@ def mod_popup_for(p, v) | |
| 15 15 | 
             
                end
         | 
| 16 16 | 
             
                a = XML::Node.new 'Change'
         | 
| 17 17 | 
             
                b = XML::Node.new 'Placemark'
         | 
| 18 | 
            -
                b.attributes['targetId'] = p. | 
| 18 | 
            +
                b.attributes['targetId'] = p.kml_id
         | 
| 19 19 | 
             
                c = XML::Node.new 'visibility'
         | 
| 20 20 | 
             
                c << XML::Node.new_text(v.to_s)
         | 
| 21 21 | 
             
                b << c
         | 
| @@ -32,7 +32,8 @@ def show_popup_for(p) | |
| 32 32 | 
             
            end
         | 
| 33 33 |  | 
| 34 34 | 
             
            def point(lo, la, alt=0, mode=nil, extrude = false)
         | 
| 35 | 
            -
                 | 
| 35 | 
            +
                m = ( mode.nil? ? :clampToGround : mode )
         | 
| 36 | 
            +
                Kamelopard::Point.new(lo, la, alt, :altitudeMode => m, :extrude => extrude)
         | 
| 36 37 | 
             
            end
         | 
| 37 38 |  | 
| 38 39 | 
             
            # Returns the KML that makes up the current Kamelopard::Document, as a string.
         | 
| @@ -58,6 +59,7 @@ end | |
| 58 59 |  | 
| 59 60 | 
             
            def name_folder(a)
         | 
| 60 61 | 
             
                Kamelopard::Document.instance.folder.name = a
         | 
| 62 | 
            +
                return Kamelopard::Document.instance.folder
         | 
| 61 63 | 
             
            end
         | 
| 62 64 |  | 
| 63 65 | 
             
            def zoom_out(dist = 1000, dur = 0, mode = nil)
         | 
| @@ -127,3 +129,155 @@ end | |
| 127 129 | 
             
            #         fly_to 
         | 
| 128 130 | 
             
            #     end
         | 
| 129 131 | 
             
            # end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            def set_prefix_to(a)
         | 
| 134 | 
            +
                Kamelopard.id_prefix = a
         | 
| 135 | 
            +
            end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
            def write_kml_to(file = 'doc.kml')
         | 
| 138 | 
            +
                File.open(file, 'w') do |f| f.write get_kml.to_s.gsub(/balloonVis/, 'gx:balloonVis') end
         | 
| 139 | 
            +
            end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
            def fade_overlay(ov, show, options = {})
         | 
| 142 | 
            +
                color = '00ffffff'
         | 
| 143 | 
            +
                color = 'ffffffff' if show
         | 
| 144 | 
            +
                if ov.is_a? String then
         | 
| 145 | 
            +
                    id = ov  
         | 
| 146 | 
            +
                else
         | 
| 147 | 
            +
                    id = ov.kml_id
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
                k = Kamelopard::AnimatedUpdate.new "<Change><ScreenOverlay targetId=\"#{id}\"><color>#{color}</color></ScreenOverlay></Change>", options 
         | 
| 150 | 
            +
                k
         | 
| 151 | 
            +
            end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            def mod_balloon_for(a, val)
         | 
| 154 | 
            +
                c = a.change('gx:balloonVisibility', val).to_s
         | 
| 155 | 
            +
                STDERR.puts c
         | 
| 156 | 
            +
                Kamelopard::AnimatedUpdate.new c
         | 
| 157 | 
            +
            end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
            def show_balloon_for(a)
         | 
| 160 | 
            +
                Kamelopard::AnimatedUpdate.new %{<Change><Placemark targetId="#{a.kml_id}"><balloonVisibility>1</balloonVisibility></Placemark></Change>}
         | 
| 161 | 
            +
            end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            def hide_balloon_for(a)
         | 
| 164 | 
            +
                Kamelopard::AnimatedUpdate.new %{<Change><Placemark targetId="#{a.kml_id}"><balloonVisibility>0</balloonVisibility></Placemark></Change>}
         | 
| 165 | 
            +
            end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
            module TelemetryProcessor
         | 
| 168 | 
            +
                Pi = 3.1415926535
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                def TelemetryProcessor.get_heading(p)
         | 
| 171 | 
            +
                    x1, y1, x2, y2 = [ p[1][0], p[1][1], p[2][0], p[2][1] ]
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    h = Math.atan((x2-x1) / (y2-y1)) * 180 / Pi
         | 
| 174 | 
            +
                    h = h + 180.0 if y2 < y1
         | 
| 175 | 
            +
                    h
         | 
| 176 | 
            +
                end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                def TelemetryProcessor.get_dist2(x1, y1, x2, y2)
         | 
| 179 | 
            +
                    Math.sqrt( (x2 - x1)**2 + (y2 - y1)**2).abs
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                def TelemetryProcessor.get_dist3(x1, y1, z1, x2, y2, z2)
         | 
| 183 | 
            +
                    Math.sqrt( (x2 - x1)**2 + (y2 - y1)**2 + (z2 - z1)**2 ).abs
         | 
| 184 | 
            +
                end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                def TelemetryProcessor.get_tilt(p)
         | 
| 187 | 
            +
                    x1, y1, z1, x2, y2, z2 = [ p[1][0], p[1][1], p[1][2], p[2][0], p[2][1], p[2][2] ]
         | 
| 188 | 
            +
                    smoothing_factor = 10.0
         | 
| 189 | 
            +
                    dist = get_dist3(x1, y1, z1, x2, y2, z2)
         | 
| 190 | 
            +
                    dist = dist + 1
         | 
| 191 | 
            +
                            # + 1 to avoid setting dist to 0, and having div-by-0 errors later
         | 
| 192 | 
            +
                    t = Math.atan((z2 - z1) / dist) * 180 / Pi / @@options[:exaggerate]
         | 
| 193 | 
            +
                            # the / 2.0 is just because it looked nicer that way
         | 
| 194 | 
            +
                    90.0 + t
         | 
| 195 | 
            +
                end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                    # roll = get_roll(last_last_lon, last_last_lat, last_lon, last_lat, lon, lat)
         | 
| 198 | 
            +
                def TelemetryProcessor.get_roll(p)
         | 
| 199 | 
            +
                    x1, y1, x2, y2, x3, y3 = [ p[0][0], p[0][1], p[1][0], p[1][1], p[2][0], p[2][1] ]
         | 
| 200 | 
            +
                    return 0 if x1.nil? or x2.nil?
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                    # Measure roll based on angle between P1 -> P2 and P2 -> P3. To be really
         | 
| 203 | 
            +
                    # exact I ought to take into account altitude as well, but ... I don't want
         | 
| 204 | 
            +
                    # to
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                    # Set x2, y2 as the origin
         | 
| 207 | 
            +
                    xn1 = x1 - x2
         | 
| 208 | 
            +
                    xn3 = x3 - x2
         | 
| 209 | 
            +
                    yn1 = y1 - y2
         | 
| 210 | 
            +
                    yn3 = y3 - y2
         | 
| 211 | 
            +
                    
         | 
| 212 | 
            +
                    # Use dot product to get the angle between the two segments
         | 
| 213 | 
            +
                    angle = Math.acos( ((xn1 * xn3) + (yn1 * yn3)) / (get_dist2(0, 0, xn1, yn1).abs * get_dist2(0, 0, xn3, yn3).abs) ) * 180 / Pi
         | 
| 214 | 
            +
             | 
| 215 | 
            +
            #    angle = angle > 90 ? 90 : angle
         | 
| 216 | 
            +
                    @@options[:exaggerate] * (angle - 180)
         | 
| 217 | 
            +
                end
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                def TelemetryProcessor.fix_coord(a)
         | 
| 220 | 
            +
                    a = a - 360 if a > 180
         | 
| 221 | 
            +
                    a = a + 360 if a < -180
         | 
| 222 | 
            +
                    a
         | 
| 223 | 
            +
                end
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                def TelemetryProcessor.add_flyto(p)
         | 
| 226 | 
            +
                    # p is an array of three points, where p[0] is the earliest. Each point is itself an array of [longitude, latitude, altitude].
         | 
| 227 | 
            +
                    p2 = TelemetryProcessor::normalize_points p
         | 
| 228 | 
            +
                    p = p2
         | 
| 229 | 
            +
                    heading = get_heading p
         | 
| 230 | 
            +
                    tilt = get_tilt p
         | 
| 231 | 
            +
                    # roll = get_roll(last_last_lon, last_last_lat, last_lon, last_lat, lon, lat)
         | 
| 232 | 
            +
                    roll = get_roll p
         | 
| 233 | 
            +
                    #p = Kamelopard::Point.new last_lon, last_lat, last_alt, { :altitudeMode => :absolute }
         | 
| 234 | 
            +
                    point = Kamelopard::Point.new p[1][0], p[1][1], p[1][2], { :altitudeMode => :absolute }
         | 
| 235 | 
            +
                    c = Kamelopard::Camera.new point, { :heading => heading, :tilt => tilt, :roll => roll, :altitudeMode => :absolute }
         | 
| 236 | 
            +
                    f = Kamelopard::FlyTo.new c, { :duration => @@options[:pause], :mode => :smooth }
         | 
| 237 | 
            +
                    f.comment = "#{p[1][0]} #{p[1][1]} #{p[1][2]} to #{p[2][0]} #{p[2][1]} #{p[2][2]}"
         | 
| 238 | 
            +
                end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                def TelemetryProcessor.options=(a)
         | 
| 241 | 
            +
                    @@options = a
         | 
| 242 | 
            +
                end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                def TelemetryProcessor.normalize_points(p)
         | 
| 245 | 
            +
                    # The whole point here is to prevent problems when you cross the poles or the dateline
         | 
| 246 | 
            +
                    # This could have serious problems if points are really far apart, like
         | 
| 247 | 
            +
                    # hundreds of degrees. This seems unlikely.
         | 
| 248 | 
            +
                    lons = ((0..2).collect { |i| p[i][0] })
         | 
| 249 | 
            +
                    lats = ((0..2).collect { |i| p[i][1] })
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                    lon_min, lon_max = lons.minmax
         | 
| 252 | 
            +
                    lat_min, lat_max = lats.minmax
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                    if (lon_max - lon_min).abs > 200 then
         | 
| 255 | 
            +
                        (0..2).each do |i|
         | 
| 256 | 
            +
                            lons[i] += 360.0 if p[i][0] < 0
         | 
| 257 | 
            +
                        end
         | 
| 258 | 
            +
                    end
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                    if (lat_max - lat_min).abs > 200 then
         | 
| 261 | 
            +
                        (0..2).each do |i|
         | 
| 262 | 
            +
                            lats[i] += 360.0 if p[i][1] < 0
         | 
| 263 | 
            +
                        end
         | 
| 264 | 
            +
                    end
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                    return [
         | 
| 267 | 
            +
                        [ lons[0], lats[0], p[0][2] ],
         | 
| 268 | 
            +
                        [ lons[1], lats[1], p[1][2] ],
         | 
| 269 | 
            +
                        [ lons[2], lats[2], p[2][2] ],
         | 
| 270 | 
            +
                    ]
         | 
| 271 | 
            +
                end
         | 
| 272 | 
            +
            end
         | 
| 273 | 
            +
             | 
| 274 | 
            +
            def tour_from_points(points, options = {})
         | 
| 275 | 
            +
                options.merge!({
         | 
| 276 | 
            +
                    :pause => 1,
         | 
| 277 | 
            +
                    :exaggerate => 1
         | 
| 278 | 
            +
                }) { |key, old, new| old }
         | 
| 279 | 
            +
                TelemetryProcessor.options = options
         | 
| 280 | 
            +
                (0..(points.size-3)).each do |i|
         | 
| 281 | 
            +
                    TelemetryProcessor::add_flyto points[i,3]
         | 
| 282 | 
            +
                end
         | 
| 283 | 
            +
            end
         | 
    
        data/lib/kamelopard/pointlist.rb
    CHANGED
    
    | @@ -59,14 +59,12 @@ class NDPointList | |
| 59 59 | 
             
                        raise "NDPointList of size #{@dim} has no Z element"
         | 
| 60 60 | 
             
                    end
         | 
| 61 61 | 
             
                end
         | 
| 62 | 
            -
             | 
| 62 | 
            +
                
         | 
| 63 63 | 
             
                def each(&blk)
         | 
| 64 64 | 
             
                    @points.each(&blk)
         | 
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 | 
            -
                def interpolate(resolution =  | 
| 68 | 
            -
                    # XXX Figure out how to implement the "resolution" argument
         | 
| 69 | 
            -
                    STDERR.puts "resolution argument to NDPointList.interpolate is ignored" if resolution.nil?
         | 
| 67 | 
            +
                def interpolate(resolution = [10])
         | 
| 70 68 | 
             
                    # Ruby implementation of Catmull-Rom splines (http://www.cubic.org/docs/hermite.htm)
         | 
| 71 69 | 
             
                    # Return NDPointList interpolating a path along all points in this list
         | 
| 72 70 |  | 
| @@ -79,6 +77,9 @@ class NDPointList | |
| 79 77 |  | 
| 80 78 | 
             
                    result = NDPointList.new(@dim)
         | 
| 81 79 |  | 
| 80 | 
            +
                    idx = 0
         | 
| 81 | 
            +
                    resolution = [resolution] if ! resolution.respond_to? []
         | 
| 82 | 
            +
             | 
| 82 83 | 
             
                    # Calculate spline between every two points
         | 
| 83 84 | 
             
                    (0..(self.size-2)).each do |i|
         | 
| 84 85 | 
             
                        p1 = self[i]
         | 
| @@ -96,13 +97,16 @@ class NDPointList | |
| 96 97 | 
             
                        c = Matrix[p1, p2, t1.row(0), t2.row(0)]
         | 
| 97 98 |  | 
| 98 99 | 
             
                        # Make a set of points
         | 
| 99 | 
            -
                        (0 | 
| 100 | 
            +
                        point_count = (resolution[idx] * 1.0 / self.size).to_i
         | 
| 101 | 
            +
                        (0..point_count).each do |t|
         | 
| 100 102 | 
             
                            r = t/10.0
         | 
| 101 103 | 
             
                            s = Matrix[[r**3, r**2, r, 1]]
         | 
| 102 104 | 
             
                            tmp = s * h
         | 
| 103 105 | 
             
                            p = tmp * c
         | 
| 104 106 | 
             
                            result << p.row(0).to_a
         | 
| 105 107 | 
             
                        end
         | 
| 108 | 
            +
                        idx += 1
         | 
| 109 | 
            +
                        idx = 0 if idx >= resolution.size
         | 
| 106 110 | 
             
                    end
         | 
| 107 111 | 
             
                    result
         | 
| 108 112 | 
             
                end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: kamelopard
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash:  | 
| 4 | 
            +
              hash: 19
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
              segments: 
         | 
| 7 7 | 
             
              - 0
         | 
| 8 8 | 
             
              - 0
         | 
| 9 | 
            -
              -  | 
| 10 | 
            -
              version: 0.0. | 
| 9 | 
            +
              - 6
         | 
| 10 | 
            +
              version: 0.0.6
         | 
| 11 11 | 
             
            platform: ruby
         | 
| 12 12 | 
             
            authors: 
         | 
| 13 13 | 
             
            - Joshua Tolley
         | 
| @@ -16,8 +16,7 @@ autorequire: | |
| 16 16 | 
             
            bindir: bin
         | 
| 17 17 | 
             
            cert_chain: []
         | 
| 18 18 |  | 
| 19 | 
            -
            date: 2012- | 
| 20 | 
            -
            default_executable: 
         | 
| 19 | 
            +
            date: 2012-05-04 00:00:00 Z
         | 
| 21 20 | 
             
            dependencies: []
         | 
| 22 21 |  | 
| 23 22 | 
             
            description: Various classes and functions used to ease development of KML files, in particular for development of Google Earth tours
         | 
| @@ -36,7 +35,6 @@ files: | |
| 36 35 | 
             
            - lib/kamelopard/functions.rb
         | 
| 37 36 | 
             
            - lib/kamelopard/pointlist.rb
         | 
| 38 37 | 
             
            - lib/kamelopard.rb
         | 
| 39 | 
            -
            has_rdoc: true
         | 
| 40 38 | 
             
            homepage: http://www.endpoint.com/services/liquid_galaxy
         | 
| 41 39 | 
             
            licenses: []
         | 
| 42 40 |  | 
| @@ -66,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 66 64 | 
             
            requirements: []
         | 
| 67 65 |  | 
| 68 66 | 
             
            rubyforge_project: 
         | 
| 69 | 
            -
            rubygems_version: 1. | 
| 67 | 
            +
            rubygems_version: 1.8.21
         | 
| 70 68 | 
             
            signing_key: 
         | 
| 71 69 | 
             
            specification_version: 3
         | 
| 72 70 | 
             
            summary: Tools for building KML
         |