kamelopard 0.0.10 → 0.0.11
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.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: []
|