kamelopard 0.0.6 → 0.0.7
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 +84 -22
- data/lib/kamelopard/functions.rb +161 -24
- data/lib/kamelopard/pointlist.rb +51 -76
- metadata +4 -4
data/lib/kamelopard/classes.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
# vim:ts=4:sw=4:et:smartindent:nowrap
|
2
3
|
|
3
4
|
# Classes to manage various KML objects. See
|
4
5
|
# http://code.google.com/apis/kml/documentation/kmlreference.html for a
|
5
6
|
# description of KML
|
6
7
|
|
7
|
-
# XXX gx:balloonVisibility isn't represented here. Fix that.
|
8
|
-
|
9
8
|
module Kamelopard
|
10
9
|
require 'singleton'
|
11
10
|
require 'kamelopard/pointlist'
|
12
11
|
require 'xml'
|
13
12
|
require 'yaml'
|
13
|
+
require 'erb'
|
14
14
|
|
15
15
|
@@sequence = 0
|
16
16
|
@@id_prefix = ''
|
@@ -396,7 +396,7 @@ module Kamelopard
|
|
396
396
|
else
|
397
397
|
a = point
|
398
398
|
end
|
399
|
-
@point = Point.new a.longitude, a.latitude, a.altitude
|
399
|
+
@point = Point.new a.longitude, a.latitude, a.altitude, :altitudeMode => a.altitudeMode
|
400
400
|
end
|
401
401
|
end
|
402
402
|
|
@@ -707,7 +707,7 @@ module Kamelopard
|
|
707
707
|
def styleUrl=(a)
|
708
708
|
if a.is_a? String then
|
709
709
|
@styleUrl = a
|
710
|
-
elsif a.respond_to?
|
710
|
+
elsif a.respond_to? :kml_id then
|
711
711
|
@styleUrl = "##{ a.kml_id }"
|
712
712
|
else
|
713
713
|
@styleUrl = a.to_s
|
@@ -870,6 +870,53 @@ module Kamelopard
|
|
870
870
|
@folders.last
|
871
871
|
end
|
872
872
|
|
873
|
+
# Makes a screenoverlay with a balloon containing links to the tours in this document
|
874
|
+
# The erb argument contains ERB to populate the description. It can be left nil
|
875
|
+
# The options hash is passed to the ScreenOverlay constructor
|
876
|
+
def make_tour_index(erb = nil, options = {})
|
877
|
+
options[:name] ||= 'Tour index'
|
878
|
+
|
879
|
+
options[:screenXY] ||= Kamelopard::XY.new(0.0, 1.0, :fraction, :fraction)
|
880
|
+
options[:overlayXY] ||= Kamelopard::XY.new(0.0, 1.0, :fraction, :fraction)
|
881
|
+
s = Kamelopard::ScreenOverlay.new options
|
882
|
+
t = ERB.new( erb || %{
|
883
|
+
<html>
|
884
|
+
<body>
|
885
|
+
<ul><% @tours.each do |t| %>
|
886
|
+
<li><a href="#<%= t.kml_id %>;flyto"><% if t.icon.nil? %><%= t.name %><% else %><img src="<%= t.icon %>" /><% end %></a></li>
|
887
|
+
<% end %></ul>
|
888
|
+
</body>
|
889
|
+
</html>
|
890
|
+
})
|
891
|
+
|
892
|
+
s.description = XML::Node.new_cdata t.result(binding)
|
893
|
+
s.balloonVisibility = 1
|
894
|
+
|
895
|
+
balloon_au = [0, 1].collect do |v|
|
896
|
+
au = Kamelopard::AnimatedUpdate.new [], :standalone => true
|
897
|
+
a = XML::Node.new 'Change'
|
898
|
+
b = XML::Node.new 'ScreenOverlay'
|
899
|
+
b.attributes['targetId'] = s.kml_id
|
900
|
+
c = XML::Node.new 'gx:balloonVisibility'
|
901
|
+
c << XML::Node.new_text(v.to_s)
|
902
|
+
b << c
|
903
|
+
a << b
|
904
|
+
au << a
|
905
|
+
au
|
906
|
+
end
|
907
|
+
|
908
|
+
# Handle hiding and displaying the index
|
909
|
+
@tours.each do |t|
|
910
|
+
q = Wait.new(0.1, :standalone => true)
|
911
|
+
t.playlist.unshift balloon_au[0]
|
912
|
+
t.playlist.unshift q
|
913
|
+
t.playlist << balloon_au[1]
|
914
|
+
t.playlist << q
|
915
|
+
end
|
916
|
+
|
917
|
+
s
|
918
|
+
end
|
919
|
+
|
873
920
|
def get_kml_document
|
874
921
|
k = XML::Document.new
|
875
922
|
# XXX fix this
|
@@ -1304,7 +1351,7 @@ module Kamelopard
|
|
1304
1351
|
# Corresponds to KML's Placemark objects. The geometry attribute requires a
|
1305
1352
|
# descendant of Geometry
|
1306
1353
|
class Placemark < Feature
|
1307
|
-
attr_accessor :name, :geometry
|
1354
|
+
attr_accessor :name, :geometry, :balloonVisibility
|
1308
1355
|
|
1309
1356
|
def initialize(name = nil, options = {})
|
1310
1357
|
super
|
@@ -1315,6 +1362,11 @@ module Kamelopard
|
|
1315
1362
|
k = XML::Node.new 'Placemark'
|
1316
1363
|
super k
|
1317
1364
|
@geometry.to_kml(k) unless @geometry.nil?
|
1365
|
+
if ! @balloonVisibility.nil? then
|
1366
|
+
x = XML::Node.new 'gx:balloonVisibility'
|
1367
|
+
x << ( @balloonVisibility ? 1 : 0 )
|
1368
|
+
k << x
|
1369
|
+
end
|
1318
1370
|
elem << k unless elem.nil?
|
1319
1371
|
k
|
1320
1372
|
end
|
@@ -1352,9 +1404,14 @@ module Kamelopard
|
|
1352
1404
|
|
1353
1405
|
# Abstract class corresponding to KML's gx:TourPrimitive object. Tours are made up
|
1354
1406
|
# of descendants of these.
|
1407
|
+
# The :standalone option affects only initialization; there's no point in
|
1408
|
+
# doing anything with it after initialization. It determines whether the
|
1409
|
+
# TourPrimitive object is added to the current tour or not
|
1355
1410
|
class TourPrimitive < Object
|
1411
|
+
attr_accessor :standalone
|
1412
|
+
|
1356
1413
|
def initialize(options = {})
|
1357
|
-
Document.instance.tour << self
|
1414
|
+
Document.instance.tour << self unless options[:standalone]
|
1358
1415
|
super
|
1359
1416
|
end
|
1360
1417
|
end
|
@@ -1526,18 +1583,19 @@ module Kamelopard
|
|
1526
1583
|
|
1527
1584
|
# Corresponds to a KML gx:Tour object
|
1528
1585
|
class Tour < Object
|
1529
|
-
attr_accessor :name, :description, :last_abs_view
|
1586
|
+
attr_accessor :name, :description, :last_abs_view, :playlist, :icon
|
1587
|
+
|
1530
1588
|
def initialize(name = nil, description = nil)
|
1531
1589
|
super()
|
1532
1590
|
@name = name
|
1533
1591
|
@description = description
|
1534
|
-
@
|
1592
|
+
@playlist = []
|
1535
1593
|
Document.instance.tours << self
|
1536
1594
|
end
|
1537
1595
|
|
1538
1596
|
# Add another element to this Tour
|
1539
1597
|
def <<(a)
|
1540
|
-
@
|
1598
|
+
@playlist << a
|
1541
1599
|
@last_abs_view = a.view if a.kind_of? FlyTo
|
1542
1600
|
end
|
1543
1601
|
|
@@ -1549,7 +1607,7 @@ module Kamelopard
|
|
1549
1607
|
[ @description, 'description' ],
|
1550
1608
|
])
|
1551
1609
|
p = XML::Node.new 'gx:Playlist'
|
1552
|
-
@
|
1610
|
+
@playlist.map do |a| a.to_kml p end
|
1553
1611
|
k << p
|
1554
1612
|
elem << k unless elem.nil?
|
1555
1613
|
k
|
@@ -1580,7 +1638,7 @@ module Kamelopard
|
|
1580
1638
|
|
1581
1639
|
# Corresponds to KML's ScreenOverlay object
|
1582
1640
|
class ScreenOverlay < Overlay
|
1583
|
-
attr_accessor :overlayXY, :screenXY, :rotationXY, :size, :rotation
|
1641
|
+
attr_accessor :overlayXY, :screenXY, :rotationXY, :size, :rotation, :balloonVisibility
|
1584
1642
|
|
1585
1643
|
def to_kml(elem = nil)
|
1586
1644
|
k = XML::Node.new 'ScreenOverlay'
|
@@ -1594,6 +1652,11 @@ module Kamelopard
|
|
1594
1652
|
d << @rotation.to_s
|
1595
1653
|
k << d
|
1596
1654
|
end
|
1655
|
+
if ! @balloonVisibility.nil? then
|
1656
|
+
x = XML::Node.new 'gx:balloonVisibility'
|
1657
|
+
x << ( @balloonVisibility ? 1 : 0 )
|
1658
|
+
k << x
|
1659
|
+
end
|
1597
1660
|
elem << k unless elem.nil?
|
1598
1661
|
k
|
1599
1662
|
end
|
@@ -1995,10 +2058,10 @@ module Kamelopard
|
|
1995
2058
|
end
|
1996
2059
|
x << loc
|
1997
2060
|
Kamelopard.add_altitudeMode(@location.altitudeMode, x)
|
1998
|
-
@link.to_kml x
|
1999
|
-
@orientation.to_kml x
|
2000
|
-
@scale.to_kml x
|
2001
|
-
@resourceMap.to_kml x
|
2061
|
+
@link.to_kml x unless @link.nil?
|
2062
|
+
@orientation.to_kml x unless @orientation.nil?
|
2063
|
+
@scale.to_kml x unless @scale.nil?
|
2064
|
+
@resourceMap.to_kml x unless @resourceMap.nil?
|
2002
2065
|
elem << x unless elem.nil?
|
2003
2066
|
x
|
2004
2067
|
end
|
@@ -2077,12 +2140,12 @@ module Kamelopard
|
|
2077
2140
|
attr_accessor :refreshVisibility, :flyToView, :link
|
2078
2141
|
|
2079
2142
|
def initialize(href = '', options = {})
|
2080
|
-
|
2081
|
-
@
|
2082
|
-
|
2083
|
-
@link = Link.new(href, refreshMode, viewRefreshMode)
|
2084
|
-
@refreshVisibility
|
2085
|
-
@flyToView
|
2143
|
+
super(( options[:name] || ''), options)
|
2144
|
+
@refreshMode ||= :onChange
|
2145
|
+
@viewRefreshMode ||= :never
|
2146
|
+
@link = Link.new(href, :refreshMode => @refreshMode, :viewRefreshMode => @viewRefreshMode)
|
2147
|
+
@refreshVisibility ||= 0
|
2148
|
+
@flyToView ||= 0
|
2086
2149
|
end
|
2087
2150
|
|
2088
2151
|
def refreshMode
|
@@ -2147,6 +2210,5 @@ module Kamelopard
|
|
2147
2210
|
e
|
2148
2211
|
end
|
2149
2212
|
end
|
2150
|
-
|
2151
2213
|
end
|
2152
2214
|
# End of Kamelopard module
|
data/lib/kamelopard/functions.rb
CHANGED
@@ -4,31 +4,63 @@ def fly_to(p, d = 0, r = 100, m = nil)
|
|
4
4
|
Kamelopard::FlyTo.new p, :range => r, :duration => d, :mode => m
|
5
5
|
end
|
6
6
|
|
7
|
+
def get_document()
|
8
|
+
Kamelopard::Document.instance
|
9
|
+
end
|
10
|
+
|
7
11
|
def set_flyto_mode_to(a)
|
8
12
|
Kamelopard::Document.instance.flyto_mode = a
|
9
13
|
end
|
10
14
|
|
11
|
-
def
|
12
|
-
au = Kamelopard::AnimatedUpdate.new
|
15
|
+
def toggle_balloon_for(p, v, options = {})
|
16
|
+
au = Kamelopard::AnimatedUpdate.new [], options
|
17
|
+
if ! p.kind_of? Kamelopard::Placemark and ! p.kind_of? Kamelopard::ScreenOverlay then
|
18
|
+
raise "Can't show balloons for things that aren't Placemarks or ScreenOverlays"
|
19
|
+
end
|
20
|
+
a = XML::Node.new 'Change'
|
21
|
+
# XXX This can probably be more robust, based on just the class's name
|
22
|
+
if p.kind_of? Kamelopard::Placemark then
|
23
|
+
b = XML::Node.new 'Placemark'
|
24
|
+
else
|
25
|
+
b = XML::Node.new 'ScreenOverlay'
|
26
|
+
end
|
27
|
+
b.attributes['targetId'] = p.kml_id
|
28
|
+
c = XML::Node.new 'gx:balloonVisibility'
|
29
|
+
c << XML::Node.new_text(v.to_s)
|
30
|
+
b << c
|
31
|
+
a << b
|
32
|
+
au << a
|
33
|
+
end
|
34
|
+
|
35
|
+
def hide_balloon_for(p, options = {})
|
36
|
+
toggle_balloon_for(p, 0, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_balloon_for(p, options = {})
|
40
|
+
toggle_balloon_for(p, 1, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def fade_balloon_for(p, v, options = {})
|
44
|
+
au = Kamelopard::AnimatedUpdate.new [], options
|
13
45
|
if ! p.is_a? Kamelopard::Placemark then
|
14
|
-
raise "Can't show
|
46
|
+
raise "Can't show balloons for things that aren't placemarks"
|
15
47
|
end
|
16
48
|
a = XML::Node.new 'Change'
|
17
49
|
b = XML::Node.new 'Placemark'
|
18
50
|
b.attributes['targetId'] = p.kml_id
|
19
|
-
c = XML::Node.new '
|
51
|
+
c = XML::Node.new 'color'
|
20
52
|
c << XML::Node.new_text(v.to_s)
|
21
53
|
b << c
|
22
54
|
a << b
|
23
55
|
au << a
|
24
56
|
end
|
25
57
|
|
26
|
-
def
|
27
|
-
|
58
|
+
def fade_out_balloon_for(p, options = {})
|
59
|
+
fade_balloon_for(p, '00ffffff', options)
|
28
60
|
end
|
29
61
|
|
30
|
-
def
|
31
|
-
|
62
|
+
def fade_in_balloon_for(p, options = {})
|
63
|
+
fade_balloon_for(p, 'ffffffff', options)
|
32
64
|
end
|
33
65
|
|
34
66
|
def point(lo, la, alt=0, mode=nil, extrude = false)
|
@@ -36,6 +68,10 @@ def point(lo, la, alt=0, mode=nil, extrude = false)
|
|
36
68
|
Kamelopard::Point.new(lo, la, alt, :altitudeMode => m, :extrude => extrude)
|
37
69
|
end
|
38
70
|
|
71
|
+
def placemark(name = nil, options = {})
|
72
|
+
Kamelopard::Placemark.new name, options
|
73
|
+
end
|
74
|
+
|
39
75
|
# Returns the KML that makes up the current Kamelopard::Document, as a string.
|
40
76
|
def get_kml
|
41
77
|
Kamelopard::Document.instance.get_kml_document
|
@@ -49,11 +85,19 @@ def pause(p)
|
|
49
85
|
Kamelopard::Wait.new p
|
50
86
|
end
|
51
87
|
|
88
|
+
def get_tour()
|
89
|
+
Kamelopard::Document.instance.tour
|
90
|
+
end
|
91
|
+
|
52
92
|
def name_tour(a)
|
53
93
|
Kamelopard::Document.instance.tour.name = a
|
54
94
|
end
|
55
95
|
|
56
|
-
def
|
96
|
+
def get_folder()
|
97
|
+
Kamelopard::Document.instance.folders.last
|
98
|
+
end
|
99
|
+
|
100
|
+
def folder(name)
|
57
101
|
Kamelopard::Folder.new(name)
|
58
102
|
end
|
59
103
|
|
@@ -62,6 +106,11 @@ def name_folder(a)
|
|
62
106
|
return Kamelopard::Document.instance.folder
|
63
107
|
end
|
64
108
|
|
109
|
+
def name_document(a)
|
110
|
+
Kamelopard::Document.instance.name = a
|
111
|
+
return Kamelopard::Document.instance
|
112
|
+
end
|
113
|
+
|
65
114
|
def zoom_out(dist = 1000, dur = 0, mode = nil)
|
66
115
|
l = Kamelopard::Document.instance.tour.last_abs_view
|
67
116
|
raise "No current position to zoom out from\n" if l.nil?
|
@@ -135,7 +184,8 @@ def set_prefix_to(a)
|
|
135
184
|
end
|
136
185
|
|
137
186
|
def write_kml_to(file = 'doc.kml')
|
138
|
-
File.open(file, 'w') do |f| f.write get_kml.to_s
|
187
|
+
File.open(file, 'w') do |f| f.write get_kml.to_s end
|
188
|
+
#File.open(file, 'w') do |f| f.write get_kml.to_s.gsub(/balloonVis/, 'gx:balloonVis') end
|
139
189
|
end
|
140
190
|
|
141
191
|
def fade_overlay(ov, show, options = {})
|
@@ -150,20 +200,6 @@ def fade_overlay(ov, show, options = {})
|
|
150
200
|
k
|
151
201
|
end
|
152
202
|
|
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
203
|
module TelemetryProcessor
|
168
204
|
Pi = 3.1415926535
|
169
205
|
|
@@ -281,3 +317,104 @@ def tour_from_points(points, options = {})
|
|
281
317
|
TelemetryProcessor::add_flyto points[i,3]
|
282
318
|
end
|
283
319
|
end
|
320
|
+
|
321
|
+
def make_view_from(options = {})
|
322
|
+
o = {}
|
323
|
+
o.merge! options
|
324
|
+
options.each do |k, v|
|
325
|
+
o[k.to_sym] = v unless k.kind_of? Symbol
|
326
|
+
end
|
327
|
+
|
328
|
+
# Set defaults
|
329
|
+
[
|
330
|
+
[ :altitude, 0 ],
|
331
|
+
[ :altitudeMode, :relativeToGround ],
|
332
|
+
[ :latitude, 0 ],
|
333
|
+
[ :longitude, 0 ],
|
334
|
+
[ :tilt, 0 ],
|
335
|
+
[ :heading, 0 ],
|
336
|
+
].each do |a|
|
337
|
+
o[a[0]] = a[1] unless o.has_key? a[0]
|
338
|
+
end
|
339
|
+
|
340
|
+
p = point o[:longitude], o[:latitude], o[:altitude], o[:altitudeMode]
|
341
|
+
|
342
|
+
if o.has_key? :roll then
|
343
|
+
view = Kamelopard::Camera.new p
|
344
|
+
else
|
345
|
+
view = Kamelopard::LookAt.new p
|
346
|
+
end
|
347
|
+
|
348
|
+
[ :altitudeMode, :tilt, :heading, :timestamp, :timespan, :timestamp, :range, :roll, :viewerOptions ].each do |a|
|
349
|
+
view.method("#{a.to_s}=").call(o[a]) if o.has_key? a
|
350
|
+
end
|
351
|
+
|
352
|
+
view
|
353
|
+
end
|
354
|
+
|
355
|
+
def screenoverlay(options = {})
|
356
|
+
Kamelopard::ScreenOverlay.new options
|
357
|
+
end
|
358
|
+
|
359
|
+
def xy(x = 0.5, y = 0.5, xt = :fraction, yt = :fraction)
|
360
|
+
Kamelopard::XY.new x, y, xt, yt
|
361
|
+
end
|
362
|
+
|
363
|
+
def iconstyle(href = nil, options = {})
|
364
|
+
Kamelopard::IconStyle.new href, options
|
365
|
+
end
|
366
|
+
|
367
|
+
def labelstyle(scale = 1, options = {})
|
368
|
+
Kamelopard::LabelStyle.new scale, options
|
369
|
+
end
|
370
|
+
|
371
|
+
def style(options = {})
|
372
|
+
Kamelopard::Style.new options
|
373
|
+
end
|
374
|
+
|
375
|
+
def look_at(point = nil, options = {})
|
376
|
+
Kamelopard::LookAt.new point, options
|
377
|
+
end
|
378
|
+
|
379
|
+
def camera(point = nil, options = {})
|
380
|
+
Kamelopard::Camera.new point, options
|
381
|
+
end
|
382
|
+
|
383
|
+
def fly_to(view = nil, options = {})
|
384
|
+
Kamelopard::FlyTo.new view, options
|
385
|
+
end
|
386
|
+
|
387
|
+
# k = an XML::Document containing KML
|
388
|
+
# Pulls the Placemarks from the KML document and flys to each one in turn
|
389
|
+
def each_placemark(d)
|
390
|
+
i = 0
|
391
|
+
d.find('//kml:Placemark').each do |p|
|
392
|
+
all_values = {}
|
393
|
+
|
394
|
+
# These fields are part of the abstractview
|
395
|
+
view_fields = %w{ latitude longitude heading range tilt roll altitude altitudeMode gx:altitudeMode }
|
396
|
+
# These are other field I'm interested in
|
397
|
+
other_fields = %w{ description name }
|
398
|
+
all_fields = view_fields.clone
|
399
|
+
all_fields.concat(other_fields.clone)
|
400
|
+
all_fields.each do |k|
|
401
|
+
if k == 'gx:altitudeMode' then
|
402
|
+
ix = k
|
403
|
+
next unless p.find_first('kml:altitudeMode').nil?
|
404
|
+
else
|
405
|
+
ix = "kml:#{k}"
|
406
|
+
end
|
407
|
+
r = k == "gx:altitudeMode" ? :altitudeMode : k.to_sym
|
408
|
+
tmp = p.find_first("descendant::#{ix}")
|
409
|
+
next if tmp.nil?
|
410
|
+
all_values[k == "gx:altitudeMode" ? :altitudeMode : k.to_sym ] = tmp.content
|
411
|
+
end
|
412
|
+
view_values = {}
|
413
|
+
view_fields.each do |v| view_values[v] = all_values[v].clone if all_values.has_key? v end
|
414
|
+
yield make_view_from(view_values), all_values
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
def make_tour_index(erb = nil, options = {})
|
419
|
+
get_document.make_tour_index(erb, options)
|
420
|
+
end
|
data/lib/kamelopard/pointlist.rb
CHANGED
@@ -2,72 +2,54 @@
|
|
2
2
|
require 'matrix'
|
3
3
|
#require 'kamelopard_classes'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
# XXX Right now I'm changing this to handle one-dimensional lists of numbers,
|
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.
|
10
|
+
|
11
|
+
module Kamelopard
|
12
|
+
class NumberList
|
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
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
def size
|
21
|
+
return @points.size
|
22
|
+
end
|
19
23
|
|
20
|
-
|
21
|
-
# Append points to our list
|
22
|
-
if a.kind_of? Kamelopard::Point then
|
23
|
-
if self.dim == 3 then
|
24
|
-
@points << [a.longitude, a.latitude, a.altitude]
|
25
|
-
else
|
26
|
-
@points << [a.longitude, a.latitude]
|
27
|
-
end
|
28
|
-
elsif a.respond_to? 'dim' and @dim != a.dim then
|
29
|
-
raise "Argument's dimension #{a.dim} must agree with our dimension #{@dim} to append to an NDPointList"
|
30
|
-
else
|
24
|
+
def <<(a)
|
31
25
|
@points << a
|
32
26
|
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def last
|
36
|
-
@points.last
|
37
|
-
end
|
38
27
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def x
|
44
|
-
@points.collect do |a| a[0] end
|
45
|
-
end
|
28
|
+
def last
|
29
|
+
@points.last
|
30
|
+
end
|
46
31
|
|
47
|
-
|
48
|
-
|
49
|
-
@points.collect do |a| a[1] end
|
50
|
-
else
|
51
|
-
raise "NDPointList of size #{@dim} has no Y element"
|
32
|
+
def [](i)
|
33
|
+
@points[i]
|
52
34
|
end
|
53
|
-
end
|
54
35
|
|
55
|
-
|
56
|
-
|
57
|
-
@points.collect do |a| a[2] end
|
58
|
-
else
|
59
|
-
raise "NDPointList of size #{@dim} has no Z element"
|
36
|
+
def each(&blk)
|
37
|
+
@points.each(&blk)
|
60
38
|
end
|
61
39
|
end
|
62
|
-
|
63
|
-
def
|
64
|
-
|
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] }
|
65
44
|
end
|
66
45
|
|
67
|
-
def interpolate(resolution = [10])
|
46
|
+
def Kamelopard.interpolate(lists = [], resolution = [10])
|
68
47
|
# Ruby implementation of Catmull-Rom splines (http://www.cubic.org/docs/hermite.htm)
|
69
48
|
# Return NDPointList interpolating a path along all points in this list
|
70
49
|
|
50
|
+
size = lists.collect { |l| l.size }.max
|
51
|
+
STDERR.puts size
|
52
|
+
|
71
53
|
h = Matrix[
|
72
54
|
[ 2, -2, 1, 1 ],
|
73
55
|
[-3, 3, -2, -1 ],
|
@@ -75,19 +57,20 @@ class NDPointList
|
|
75
57
|
[ 1, 0, 0, 0 ],
|
76
58
|
]
|
77
59
|
|
78
|
-
|
60
|
+
# XXX This needs to be fixed
|
61
|
+
result = []
|
79
62
|
|
80
63
|
idx = 0
|
81
|
-
resolution = [resolution] if ! resolution.respond_to? []
|
64
|
+
resolution = [resolution] if ! resolution.respond_to? :[]
|
82
65
|
|
83
66
|
# Calculate spline between every two points
|
84
|
-
(0..(
|
85
|
-
p1 =
|
86
|
-
p2 =
|
67
|
+
(0..(size-2)).each do |i|
|
68
|
+
p1 = lists_at(lists, i)
|
69
|
+
p2 = lists_at(lists, i+1)
|
87
70
|
|
88
71
|
# Get surrounding points for calculating tangents
|
89
|
-
if i <= 0 then pt1 = p1 else pt1 =
|
90
|
-
if i
|
72
|
+
if i <= 0 then pt1 = p1 else pt1 = lists_at(lists, i-1) end
|
73
|
+
if i >= size - 2 then pt2 = p2 else pt2 = lists_at(lists, i+2) end
|
91
74
|
|
92
75
|
# Build tangent points into matrices to calculate tangents.
|
93
76
|
t1 = 0.5 * ( Matrix[p2] - Matrix[pt1] )
|
@@ -97,7 +80,8 @@ class NDPointList
|
|
97
80
|
c = Matrix[p1, p2, t1.row(0), t2.row(0)]
|
98
81
|
|
99
82
|
# Make a set of points
|
100
|
-
point_count = (resolution[idx] * 1.0 /
|
83
|
+
point_count = (resolution[idx] * 1.0 / size).to_i
|
84
|
+
STDERR.puts point_count
|
101
85
|
(0..point_count).each do |t|
|
102
86
|
r = t/10.0
|
103
87
|
s = Matrix[[r**3, r**2, r, 1]]
|
@@ -112,20 +96,11 @@ class NDPointList
|
|
112
96
|
end
|
113
97
|
end
|
114
98
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
super 2
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class ThreeDPointList < NDPointList
|
128
|
-
def initialize
|
129
|
-
super 3
|
130
|
-
end
|
131
|
-
end
|
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,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kamelopard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshua Tolley
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-07-12 00:00:00 Z
|
20
20
|
dependencies: []
|
21
21
|
|
22
22
|
description: Various classes and functions used to ease development of KML files, in particular for development of Google Earth tours
|