kamelopard 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
data/lib/kamelopard.rb
CHANGED
data/lib/kamelopard/classes.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
#--
|
2
3
|
# vim:ts=4:sw=4:et:smartindent:nowrap
|
3
|
-
|
4
|
+
#++
|
4
5
|
# Classes to manage various KML objects. See
|
5
6
|
# http://code.google.com/apis/kml/documentation/kmlreference.html for a
|
6
7
|
# description of KML
|
7
8
|
|
9
|
+
# Pretty much everything important is in this module
|
8
10
|
module Kamelopard
|
9
11
|
require 'singleton'
|
10
|
-
require 'kamelopard/pointlist'
|
11
12
|
require 'xml'
|
12
13
|
require 'yaml'
|
13
14
|
require 'erb'
|
@@ -16,6 +17,14 @@ module Kamelopard
|
|
16
17
|
@@sequence = 0
|
17
18
|
@@id_prefix = ''
|
18
19
|
@@logger = nil
|
20
|
+
|
21
|
+
# Valid log levels:
|
22
|
+
# * :debug
|
23
|
+
# * :info
|
24
|
+
# * :notice
|
25
|
+
# * :warn
|
26
|
+
# * :error
|
27
|
+
# * :fatal
|
19
28
|
LogLevels = {
|
20
29
|
:debug => 0,
|
21
30
|
:info => 1,
|
@@ -29,35 +38,37 @@ module Kamelopard
|
|
29
38
|
|
30
39
|
# Sets a logging callback function. This function should expect three
|
31
40
|
# arguments. The first will be a log level (:debug, :info, :notice, :warn,
|
32
|
-
# :error, or :fatal); the second will be a
|
33
|
-
# entries generally; and the third will be the message
|
41
|
+
# :error, or :fatal); the second will be a text string, categorizing the
|
42
|
+
# log entries generally; and the third will be the log message itself
|
34
43
|
def Kamelopard.set_logger(l)
|
35
44
|
@@logger = l
|
36
45
|
end
|
37
46
|
|
47
|
+
# Sets the current logging level. Valid levels are defined in the LogLevels hash
|
38
48
|
def Kamelopard.set_log_level(lev)
|
39
49
|
raise "Unknown log level #{lev}" unless LogLevels.has_key? lev
|
40
50
|
@@log_level = LogLevels[lev]
|
41
51
|
end
|
42
52
|
|
53
|
+
# Logs a message, provided a log level, a text string, and the log message.
|
54
|
+
# See #Kamelopard.set_logger for details.
|
43
55
|
def Kamelopard.log(level, mod, msg)
|
44
56
|
raise "Unknown log level #{level} for error message #{msg}" unless LogLevels.has_key? level
|
45
57
|
@@logger.call(level, mod, msg) unless @@logger.nil? or @@log_level > LogLevels[level]
|
46
58
|
end
|
47
59
|
|
48
|
-
def Kamelopard.
|
49
|
-
DocumentHolder.instance.current_document
|
50
|
-
end
|
51
|
-
|
52
|
-
def Kamelopard.get_next_id # :nodoc
|
60
|
+
def Kamelopard.get_next_id # :nodoc:
|
53
61
|
@@sequence += 1
|
54
62
|
@@sequence
|
55
63
|
end
|
56
64
|
|
65
|
+
# Sets a prefix for all kml_id values generated from this time forth. Does
|
66
|
+
# not change previously generated kml_ids
|
57
67
|
def Kamelopard.id_prefix=(a)
|
58
68
|
@@id_prefix = a
|
59
69
|
end
|
60
70
|
|
71
|
+
# Returns the current kml_id prefix value. See #Kamelopard.id_prefix=
|
61
72
|
def Kamelopard.id_prefix
|
62
73
|
@@id_prefix
|
63
74
|
end
|
@@ -73,7 +84,7 @@ module Kamelopard
|
|
73
84
|
# * if the second element is a proc, call the proc, passing it the KML
|
74
85
|
# object, and let the Proc (presumably) add itself to the KML
|
75
86
|
#++
|
76
|
-
def Kamelopard.kml_array(e, m) # :nodoc
|
87
|
+
def Kamelopard.kml_array(e, m) # :nodoc:
|
77
88
|
m.map do |a|
|
78
89
|
if ! a[0].nil? then
|
79
90
|
if a[1].kind_of? Proc then
|
@@ -94,7 +105,7 @@ module Kamelopard
|
|
94
105
|
#--
|
95
106
|
# Accepts XdX'X.X", XDXmX.XXs, XdXmX.XXs, or X.XXXX with either +/- or N/E/S/W
|
96
107
|
#++
|
97
|
-
def Kamelopard.convert_coord(a) # :nodoc
|
108
|
+
def Kamelopard.convert_coord(a) # :nodoc:
|
98
109
|
a = a.to_s.upcase.strip.gsub(/\s+/, '')
|
99
110
|
|
100
111
|
mult = 1
|
@@ -136,7 +147,7 @@ module Kamelopard
|
|
136
147
|
end
|
137
148
|
|
138
149
|
# Helper function for altitudeMode / gx:altitudeMode elements
|
139
|
-
def Kamelopard.add_altitudeMode(mode, e)
|
150
|
+
def Kamelopard.add_altitudeMode(mode, e) # :nodoc:
|
140
151
|
return if mode.nil?
|
141
152
|
if mode == :clampToGround or mode == :relativeToGround or mode == :absolute then
|
142
153
|
t = XML::Node.new 'altitudeMode'
|
@@ -182,6 +193,14 @@ module Kamelopard
|
|
182
193
|
end
|
183
194
|
end
|
184
195
|
|
196
|
+
def change(attributes, values)
|
197
|
+
change = XML::Node.new 'Change'
|
198
|
+
child = XML::Node.new self.class.name
|
199
|
+
child.attributes[:targetId] = @kml_id
|
200
|
+
change << child
|
201
|
+
return change
|
202
|
+
end
|
203
|
+
|
185
204
|
# If this is a master-only object, this function gets called internally
|
186
205
|
# in place of the object's original to_kml method
|
187
206
|
def _alternate_to_kml(*a)
|
@@ -297,7 +316,8 @@ module Kamelopard
|
|
297
316
|
end
|
298
317
|
|
299
318
|
def to_s
|
300
|
-
|
319
|
+
p @extrude
|
320
|
+
"Point (#{@longitude}, #{@latitude}, #{@altitude}, mode = #{@altitudeMode}, #{ @extrude == 1 ? 'extruded' : 'not extruded' })"
|
301
321
|
end
|
302
322
|
|
303
323
|
def to_kml(elem = nil, short = false)
|
@@ -496,7 +516,7 @@ module Kamelopard
|
|
496
516
|
else
|
497
517
|
a = point
|
498
518
|
end
|
499
|
-
@point = Point.new a.longitude, a.latitude, a.altitude, :altitudeMode => a.altitudeMode
|
519
|
+
@point = Point.new a.longitude, a.latitude, a.altitude, :altitudeMode => a.altitudeMode, :extrude => a.extrude
|
500
520
|
end
|
501
521
|
end
|
502
522
|
|
@@ -568,6 +588,10 @@ module Kamelopard
|
|
568
588
|
t
|
569
589
|
end
|
570
590
|
|
591
|
+
def to_queries_txt(name = '', planet = 'earth')
|
592
|
+
return "#{planet}@#{name}@flytoview=" + self.to_kml.to_s.gsub(/^\s+/, '').gsub("\n", '')
|
593
|
+
end
|
594
|
+
|
571
595
|
def [](a)
|
572
596
|
return @viewerOptions[a]
|
573
597
|
end
|
@@ -951,7 +975,7 @@ module Kamelopard
|
|
951
975
|
end
|
952
976
|
end
|
953
977
|
|
954
|
-
def get_stack_trace # :nodoc
|
978
|
+
def get_stack_trace # :nodoc:
|
955
979
|
k = ''
|
956
980
|
caller.each do |a| k << "#{a}\n" end
|
957
981
|
k
|
@@ -1131,6 +1155,11 @@ module Kamelopard
|
|
1131
1155
|
@document_index += 1
|
1132
1156
|
end
|
1133
1157
|
|
1158
|
+
def set_current(a)
|
1159
|
+
raise "Must set current document to an existing Document object" unless a.kind_of? Document
|
1160
|
+
@document_index = @documents.index(a)
|
1161
|
+
end
|
1162
|
+
|
1134
1163
|
def [](a)
|
1135
1164
|
return @documents[a]
|
1136
1165
|
end
|
@@ -1601,7 +1630,7 @@ module Kamelopard
|
|
1601
1630
|
attr_accessor :standalone
|
1602
1631
|
|
1603
1632
|
def initialize(options = {})
|
1604
|
-
DocumentHolder.instance.current_document.tour << self unless options
|
1633
|
+
DocumentHolder.instance.current_document.tour << self unless options.has_key?(:standalone)
|
1605
1634
|
super
|
1606
1635
|
end
|
1607
1636
|
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
#--
|
2
|
+
# vim:ts=4:sw=4:et:smartindent:nowrap
|
3
|
+
#++
|
4
|
+
# Describes functions that can be calculated to create flight paths
|
5
|
+
|
6
|
+
require 'matrix'
|
7
|
+
|
8
|
+
#--
|
9
|
+
#++
|
10
|
+
module Kamelopard
|
11
|
+
|
12
|
+
# Classes to manage functions, which can be interpolated into flight paths
|
13
|
+
# and other things
|
14
|
+
module Functions
|
15
|
+
|
16
|
+
# Abstract class representing a one-dimensional function
|
17
|
+
class Function1D
|
18
|
+
# min and max describe the function's domain. Values passed to
|
19
|
+
# get_value will only range from 0 to 1; the actual value
|
20
|
+
# calculated will be mapped to a percentage of that domain.
|
21
|
+
attr_reader :min, :max, :start, :end
|
22
|
+
|
23
|
+
# Another function this one is composed with, or appended to the end of this one
|
24
|
+
attr_reader :compose, :append
|
25
|
+
|
26
|
+
attr_accessor :verbose
|
27
|
+
|
28
|
+
def initialize(min = 0, max = 1)
|
29
|
+
@min = min
|
30
|
+
@max = max
|
31
|
+
@verbose = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def max=(m)
|
35
|
+
raise "Cannot have a nil domain maximum" if m.nil?
|
36
|
+
@max = m
|
37
|
+
end
|
38
|
+
|
39
|
+
def min=(m)
|
40
|
+
raise "Cannot have a nil domain minimum" if m.nil?
|
41
|
+
@min = m
|
42
|
+
end
|
43
|
+
|
44
|
+
def compose=(f)
|
45
|
+
raise "Can only compose another one-dimensional function" unless f.kind_of? Function1D or f.nil?
|
46
|
+
@compose = f
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_value(x)
|
50
|
+
raise "Value #{x} must be between 0 and 1" if (x.to_f > 1 or x.to_f < 0)
|
51
|
+
val = x * (max - min) + min
|
52
|
+
if @compose.nil? then
|
53
|
+
return run_function(val)
|
54
|
+
else
|
55
|
+
return run_function(@compose.get_value(val))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#def append(f)
|
60
|
+
# raise "Can only append another one-dimensional function" unless f.kind_of? Function1D or f.nil?
|
61
|
+
# print STDERR "WARNING: append() isn't actually implemented" unless f.nil?
|
62
|
+
# # XXX
|
63
|
+
# # Gotta implement this. The idea is to have one function for the first
|
64
|
+
# # part of a domain, and another for the next. The domain of the second
|
65
|
+
# # function will begin with the end of the last function.
|
66
|
+
# # Perhaps allow two methods. One just appends the two; the second
|
67
|
+
# # smooths things somewhat by adding to the result of the second the
|
68
|
+
# # value of the first at the end of its domain.
|
69
|
+
# @append = f
|
70
|
+
#end
|
71
|
+
|
72
|
+
def run_function(x)
|
73
|
+
raise "Override this method before calling it, please"
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.interpolate(a, b)
|
77
|
+
# Creates a new Function1D object between points A and B
|
78
|
+
raise "Override this method before calling it, please"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Represents a cubic equation of the form c3 * x^3 + c2 * x^2 + c1 * x + c0
|
83
|
+
class Cubic < Function1D
|
84
|
+
attr_accessor :c0, :c1, :c2, :c3
|
85
|
+
def initialize(c3 = 1.0, c2 = 0.0, c1 = 0.0, c0 = 0.0, min = -1.0, max = 1.0)
|
86
|
+
@c3 = c3.to_f
|
87
|
+
@c2 = c2.to_f
|
88
|
+
@c1 = c1.to_f
|
89
|
+
@c0 = c0.to_f
|
90
|
+
super min, max
|
91
|
+
end
|
92
|
+
|
93
|
+
def run_function(x)
|
94
|
+
puts "#{self.class.name}: [#{@min}, #{@max}] (#{@c3}, #{@c2}, #{@c1}, #{@c0}): #{x} -> #{ @c3 * x * x * x + @c2 * x * x + @c1 * x + @c0 }" if @verbose
|
95
|
+
return @c3 * x ** 3 + @c2 * x ** 2 + @c1 * x + @c0
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.interpolate(ymin, ymax, x1, y1, x2, y2, min = -1.0, max = 1.0)
|
99
|
+
xm = Matrix[[min ** 3, x1 ** 3, x2 ** 3, max ** 3], [min ** 2, x1 ** 2, x2 ** 2, max ** 2], [min, x1, x2, max], [1, 1, 1, 1]]
|
100
|
+
ym = Matrix[[ymin, y1, y2, ymax]]
|
101
|
+
m = ym * xm.inverse
|
102
|
+
c3 = m[0,0]
|
103
|
+
c2 = m[0,1]
|
104
|
+
c1 = m[0,2]
|
105
|
+
c0 = m[0,3]
|
106
|
+
return Cubic.new(c3, c2, c1, c0, min, max)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Describes a quadratic equation
|
111
|
+
class Quadratic < Cubic
|
112
|
+
def initialize(c2 = 1.0, c1 = 0.0, c0 = 0.0, min = -1.0, max = 1.0)
|
113
|
+
super(0.0, c2, c1, c0, min, max)
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.interpolate(ymin, ymax, x1, y1, min = -1.0, max = 1.0)
|
117
|
+
x1 = (max.to_f + min) / 2.0 if x1.nil?
|
118
|
+
y1 = (ymax.to_f + ymin) / 2.0 if y1.nil?
|
119
|
+
xm = Matrix[[min ** 2, x1 ** 2, max ** 2], [min, x1, max], [1, 1, 1]]
|
120
|
+
ym = Matrix[[ymin, y1, ymax]]
|
121
|
+
m = ym * xm.inverse
|
122
|
+
c2 = m[0,0]
|
123
|
+
c1 = m[0,1]
|
124
|
+
c0 = m[0,2]
|
125
|
+
return Quadratic.new(c2, c1, c0, min, max)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Describes a line
|
130
|
+
class Line < Cubic
|
131
|
+
def initialize(c1 = 1.0, c0 = 0.0, min = 0.0, max = 1.0)
|
132
|
+
super(0.0, 0.0, c1, c0, min, max)
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.interpolate(a, b)
|
136
|
+
return Line.new(b - a, a)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class Constant < Cubic
|
141
|
+
def initialize(c0 = 0.0, min = 0.0, max = 1.0)
|
142
|
+
super(0, 0, 0, c0, min, max)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Interpolation isn't terribly useful for constants; to avoid using
|
146
|
+
# some superclass's interpolation accidentally, we'll just
|
147
|
+
# interpolate to the average of the two values
|
148
|
+
def self.interpolate(a, b)
|
149
|
+
return Constant.new((b.to_f - a.to_f) / 0.0)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
# include Kamelopard::Functions
|
155
|
+
#
|
156
|
+
# l = Line.new 1.0, 0.0
|
157
|
+
# puts l.get_value(0.35)
|
158
|
+
#
|
159
|
+
# s = Quadratic.new
|
160
|
+
# puts s.get_value(0.4)
|
161
|
+
#
|
162
|
+
# l.compose = s
|
163
|
+
# puts l.get_value(0.35)
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#--
|
2
|
+
# vim:ts=4:sw=4:et:smartindent:nowrap
|
3
|
+
#++
|
4
|
+
# Logic to create flyto paths from mathematical functions.
|
5
|
+
|
6
|
+
#--
|
7
|
+
#++
|
8
|
+
module Kamelopard
|
9
|
+
|
10
|
+
# This function creates a hash, then uses that hash to create a point in a
|
11
|
+
# tour, using make_view_from() among other things.
|
12
|
+
# Arguments:
|
13
|
+
# points: The number of points in the series
|
14
|
+
# hash: Values used to create the hash, which creates the point in the
|
15
|
+
# series. Keys in this hash include:
|
16
|
+
# latitude, longitude, altitude, heading, tilt, roll, range, duration, altitudeMode, extrude
|
17
|
+
# These can be constant numbers, Proc objects, or Function1D objects.
|
18
|
+
# The latter two will be called once for each point in the series.
|
19
|
+
# Proc objects will be passed the number of the point they're
|
20
|
+
# calculating, starting with 0, and the current value of the hash
|
21
|
+
# created for this point. "duration" represents the time in seconds
|
22
|
+
# spent flying from the last point to this one.
|
23
|
+
# callback
|
24
|
+
# This Proc object, if defined, will be called after the above hash
|
25
|
+
# keys have been calculated. It gets passed the number of the point,
|
26
|
+
# and the current value of the hash for this point. It can modify and
|
27
|
+
# return that hash as needed.
|
28
|
+
# callback_value
|
29
|
+
# A placeholder the callback function can use. It can set it when
|
30
|
+
# it's called one time, and see that value when called the next time.
|
31
|
+
# pause
|
32
|
+
# The amount of time to pause after flying to this point, or nil for no pause
|
33
|
+
# show_placemarks
|
34
|
+
# If set, a placemark object will be created at this point
|
35
|
+
# no_flyto
|
36
|
+
# If set, on flyto objects will be created
|
37
|
+
|
38
|
+
def make_function_path(points = 10, options = {})
|
39
|
+
|
40
|
+
def val(a, b, c) # :nodoc:
|
41
|
+
if a.kind_of? Function1D then
|
42
|
+
return a.get_value(c)
|
43
|
+
elsif a.kind_of? Proc then
|
44
|
+
return a.call(b, a)
|
45
|
+
else
|
46
|
+
return a
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
result_points = []
|
51
|
+
|
52
|
+
callback_value = nil
|
53
|
+
i = 0
|
54
|
+
while (i <= points)
|
55
|
+
p = i.to_f / points.to_f
|
56
|
+
hash = {
|
57
|
+
:latitude => val(options[:latitude], i, p),
|
58
|
+
:longitude => val(options[:longitude], i, p),
|
59
|
+
:altitude => val(options[:altitude], i, p),
|
60
|
+
:heading => val(options[:heading], i, p),
|
61
|
+
:tilt => val(options[:tilt], i, p),
|
62
|
+
:altitudeMode => val(options[:altitudeMode], i, p),
|
63
|
+
:extrude => val(options[:extrude], i, p),
|
64
|
+
}
|
65
|
+
|
66
|
+
hash[:show_placemarks] = options[:show_placemarks] if options.has_key? :show_placemarks
|
67
|
+
hash[:roll] = val(options[:roll], i, p) if options.has_key? :roll
|
68
|
+
hash[:range] = val(options[:range], i, p) if options.has_key? :range
|
69
|
+
hash[:pause] = val(options[:pause], i, p) if options.has_key? :pause
|
70
|
+
|
71
|
+
if hash.has_key? :duration
|
72
|
+
duration = val(options[:duration], i, p)
|
73
|
+
else
|
74
|
+
duration = (i == 0 ? 0 : 2)
|
75
|
+
end
|
76
|
+
|
77
|
+
hash[:callback_value] = callback_value unless callback_value.nil?
|
78
|
+
tmp = yield(i, hash)
|
79
|
+
hash = tmp unless tmp.nil?
|
80
|
+
#hash = options[:callback].call(i, hash) if options.has_key? :callback
|
81
|
+
callback_value = hash[:callback_value] if hash.has_key? :callback_value
|
82
|
+
|
83
|
+
v = make_view_from(hash)
|
84
|
+
p = point(v.longitude, v.latitude, v.altitude, hash[:altitudeMode], hash[:extrude])
|
85
|
+
get_folder << placemark(i.to_s, :geometry => p) if hash.has_key? :show_placemarks
|
86
|
+
fly_to v, :duration => duration , :mode => :smooth unless hash.has_key? :no_flyto
|
87
|
+
result_points << v
|
88
|
+
|
89
|
+
pause hash[:pause] if hash.has_key? :pause
|
90
|
+
|
91
|
+
i = i + 1
|
92
|
+
end
|
93
|
+
result_points
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -1,4 +1,7 @@
|
|
1
|
+
#--
|
1
2
|
# vim:ts=4:sw=4:et:smartindent:nowrap
|
3
|
+
#++
|
4
|
+
# Various helper functions
|
2
5
|
|
3
6
|
# Returns the current Document object
|
4
7
|
def get_document()
|
@@ -122,6 +125,8 @@
|
|
122
125
|
|
123
126
|
# Returns the current Folder object
|
124
127
|
def get_folder()
|
128
|
+
f = Kamelopard::DocumentHolder.instance.current_document.folders.last
|
129
|
+
Kamelopard::Folder.new() if f.nil?
|
125
130
|
Kamelopard::DocumentHolder.instance.current_document.folders.last
|
126
131
|
end
|
127
132
|
|
@@ -415,11 +420,12 @@
|
|
415
420
|
[ :longitude, 0 ],
|
416
421
|
[ :tilt, 0 ],
|
417
422
|
[ :heading, 0 ],
|
423
|
+
[ :extrude, 0 ],
|
418
424
|
].each do |a|
|
419
425
|
o[a[0]] = a[1] unless o.has_key? a[0]
|
420
426
|
end
|
421
427
|
|
422
|
-
p = point o[:longitude], o[:latitude], o[:altitude], o[:altitudeMode]
|
428
|
+
p = point o[:longitude], o[:latitude], o[:altitude], o[:altitudeMode], o[:extrude]
|
423
429
|
|
424
430
|
if o.has_key? :roll then
|
425
431
|
view = Kamelopard::Camera.new p
|
@@ -1,51 +1,11 @@
|
|
1
1
|
# vim:ts=4:sw=4:et:smartindent:nowrap
|
2
2
|
require 'matrix'
|
3
|
-
#require 'kamelopard_classes'
|
4
3
|
|
5
|
-
#
|
6
|
-
# that can be added together. We'll probably want a way to add points, or other
|
7
|
-
# numeric sets, to a set of pointlists easily. So for instance we can have
|
8
|
-
# lists for altitude, longitude, and latitude, and add a single point to them
|
9
|
-
# in one easy command.
|
4
|
+
# Basic support for splines
|
10
5
|
|
11
6
|
module Kamelopard
|
12
|
-
|
13
|
-
# Contains a list of numbers
|
14
|
-
|
15
|
-
def initialize(init = [])
|
16
|
-
raise "Constructor argument needs to be an array" unless init.kind_of? Array
|
17
|
-
@points = init
|
18
|
-
end
|
19
|
-
|
20
|
-
def size
|
21
|
-
return @points.size
|
22
|
-
end
|
23
|
-
|
24
|
-
def <<(a)
|
25
|
-
@points << a
|
26
|
-
end
|
27
|
-
|
28
|
-
def last
|
29
|
-
@points.last
|
30
|
-
end
|
31
|
-
|
32
|
-
def [](i)
|
33
|
-
@points[i]
|
34
|
-
end
|
35
|
-
|
36
|
-
def each(&blk)
|
37
|
-
@points.each(&blk)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def Kamelopard.lists_at(lists, i)
|
42
|
-
# The modulus ensures lists will repeat if they're not the same size
|
43
|
-
lists.collect { |l| l[i % l.size] }
|
44
|
-
end
|
45
|
-
|
46
|
-
def Kamelopard.interpolate(lists = [], resolution = [10])
|
7
|
+
def spline(lists = [], resolution = [10])
|
47
8
|
# Ruby implementation of Catmull-Rom splines (http://www.cubic.org/docs/hermite.htm)
|
48
|
-
# Return NDPointList interpolating a path along all points in this list
|
49
9
|
|
50
10
|
size = lists.collect { |l| l.size }.max
|
51
11
|
STDERR.puts size
|
@@ -95,12 +55,3 @@ module Kamelopard
|
|
95
55
|
result
|
96
56
|
end
|
97
57
|
end
|
98
|
-
|
99
|
-
#a = Kamelopard::NumberList.new [1, 2, 3]
|
100
|
-
#b = Kamelopard::NumberList.new [5, 6, 10]
|
101
|
-
#
|
102
|
-
#i = 0
|
103
|
-
#Kamelopard.interpolate([a, b], [100]).each do |f|
|
104
|
-
# i += 1
|
105
|
-
# puts "#{i}\t#{f.inspect}"
|
106
|
-
#end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kamelopard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: Various classes and functions used to ease development of KML files,
|
16
16
|
in particular for development of Google Earth tours
|
@@ -23,8 +23,10 @@ extra_rdoc_files: []
|
|
23
23
|
files:
|
24
24
|
- lib/kamelopard/geocode.rb
|
25
25
|
- lib/kamelopard/classes.rb
|
26
|
-
- lib/kamelopard/
|
27
|
-
- lib/kamelopard/
|
26
|
+
- lib/kamelopard/helpers.rb
|
27
|
+
- lib/kamelopard/function_paths.rb
|
28
|
+
- lib/kamelopard/function.rb
|
29
|
+
- lib/kamelopard/spline.rb
|
28
30
|
- lib/kamelopard.rb
|
29
31
|
homepage: http://www.endpoint.com/services/liquid_galaxy
|
30
32
|
licenses: []
|