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.
@@ -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 = 0
361
- @range = 0
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
- :extendedData, :styles
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, :doc_folders, :doc_tours, :uses_xal, :doc_styles
851
+ attr_accessor :flyto_mode, :folders, :tours, :uses_xal
771
852
 
772
853
  def initialize(options = {})
773
- @doc_tours = []
774
- @doc_folders = []
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 @doc_tours.length == 0
782
- @doc_tours.last
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 @doc_folders.size == 0 then
867
+ if @folders.size == 0 then
788
868
  Folder.new
789
869
  end
790
- @doc_folders.last
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
- @doc_styles.map do |a| d << a.to_kml unless a.attached? end
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
- @doc_folders.map do |a|
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
- @doc_tours.map do |a| a.to_kml(d) end
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.doc_styles << self
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
@@ -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(p, r, d, m)
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.obj_id
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
- Kamelopard::Point.new(lo, la, alt, mode.nil? ? :clampToGround : mode, extrude)
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
@@ -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 = nil)
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..10).each do |t|
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: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
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-01-17 00:00:00 -07:00
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.5.3
67
+ rubygems_version: 1.8.21
70
68
  signing_key:
71
69
  specification_version: 3
72
70
  summary: Tools for building KML