kamelopard 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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