kamelopard 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,8 +7,8 @@
7
7
  module Kamelopard
8
8
  require 'singleton'
9
9
  require 'kamelopard/pointlist'
10
- require 'rexml/document'
11
- require 'rexml/element'
10
+ require 'xml'
11
+ require 'yaml'
12
12
 
13
13
  @@sequence = 0
14
14
 
@@ -37,10 +37,14 @@ module Kamelopard
37
37
  if ! a[0].nil? then
38
38
  if a[1].kind_of? Proc then
39
39
  a[1].call(e)
40
+ elsif a[0].kind_of? XML::Node then
41
+ d = XML::Node.new(a[1])
42
+ d << a[0]
43
+ e << d
40
44
  else
41
- t = REXML::Element.new a[1]
42
- t.text = a[0].to_s
43
- e.elements.add t
45
+ t = XML::Node.new a[1]
46
+ t << a[0].to_s
47
+ e << t
44
48
  end
45
49
  end
46
50
  end
@@ -90,32 +94,63 @@ module Kamelopard
90
94
  def Kamelopard.add_altitudeMode(mode, e)
91
95
  return if mode.nil?
92
96
  if mode == :clampToGround or mode == :relativeToGround or mode == :absolute then
93
- t = REXML::Element.new 'altitudeMode'
97
+ t = XML::Node.new 'altitudeMode'
94
98
  else
95
- t = REXML::Element.new 'gx:altitudeMode'
99
+ t = XML::Node.new 'gx:altitudeMode'
96
100
  end
97
- t.text = mode
98
- e.elements.add t
101
+ t << mode.to_s
102
+ e << t
99
103
  end
100
104
 
101
105
  # Base class for all Kamelopard objects. Manages object ID and a single
102
106
  # comment string associated with the object
103
107
  class Object
104
- attr_accessor :id, :comment
108
+ attr_accessor :kml_id
109
+ attr_reader :comment
105
110
 
106
- def initialize(comment = nil)
107
- @id = "#{self.class.name.gsub('Kamelopard::', '')}_#{ Kamelopard.get_next_id }"
108
- @comment = comment.gsub(/</, '&lt;') unless comment.nil?
111
+ def initialize(options = {})
112
+ @kml_id = "#{self.class.name.gsub('Kamelopard::', '')}_#{ Kamelopard.get_next_id }"
113
+
114
+ options.each do |k, v|
115
+ method = "#{k}=".to_sym
116
+ if self.respond_to? method then
117
+ self.method(method).call(v)
118
+ else
119
+ raise "Warning: couldn't find attribute for options hash key #{k}"
120
+ end
121
+ end
122
+ end
123
+
124
+ def comment=(a)
125
+ if a.respond_to? :gsub then
126
+ @comment = a.gsub(/</, '&lt;')
127
+ else
128
+ @comment = a
129
+ end
109
130
  end
110
131
 
111
132
  # Returns KML string for this object. Objects should override this method
112
133
  def to_kml(elem)
113
- elem.attributes['id'] = @id
134
+ elem.attributes['id'] = @kml_id.to_s
114
135
  if not @comment.nil? and @comment != '' then
115
- c = REXML::Comment.new " #{@comment} ", elem
136
+ c = XML::Node.new_comment " #{@comment} "
137
+ elem << c
116
138
  return c
117
139
  end
118
140
  end
141
+
142
+ # Generates a <Change> element suitable for changing the given field of
143
+ # an object to the given value
144
+ def change(field, value)
145
+ c = XML::Node.new 'Change'
146
+ o = XML::Node.new self.class.name.sub!(/Kamelopard::/, '')
147
+ o.attributes['targetId'] = self.kml_id
148
+ e = XML::Node.new field
149
+ e.content = value.to_s
150
+ o << e
151
+ c << o
152
+ c
153
+ end
119
154
  end
120
155
 
121
156
  # Abstract base class for Point and several other classes
@@ -124,69 +159,71 @@ module Kamelopard
124
159
 
125
160
  # Represents a Point in KML.
126
161
  class Point < Geometry
127
- attr_accessor :longitude, :latitude, :altitude, :altitudeMode, :extrude
128
- def initialize(long, lat, alt=0, altmode=:clampToGround, extrude=false)
129
- super()
162
+ attr_reader :longitude, :latitude
163
+ attr_accessor :altitude, :altitudeMode, :extrude
164
+
165
+ def initialize(longitude = nil, latitude = nil, altitude = nil, options = {})
166
+ super options
167
+ @longitude = longitude unless longitude.nil?
168
+ @latitude = latitude unless latitude.nil?
169
+ @altitude = altitude unless altitude.nil?
170
+ end
171
+
172
+ def longitude=(long)
130
173
  @longitude = Kamelopard.convert_coord(long)
174
+ end
175
+
176
+ def latitude=(lat)
131
177
  @latitude = Kamelopard.convert_coord(lat)
132
- @altitude = alt
133
- @altitudeMode = altmode
134
- @extrude = extrude
135
178
  end
136
-
179
+
137
180
  def to_s
138
181
  "Point (#{@longitude}, #{@latitude}, #{@altitude}, mode = #{@altitudeMode}, #{ @extrude ? 'extruded' : 'not extruded' })"
139
182
  end
140
183
 
141
- def to_kml(short = false)
142
- e = REXML::Element.new 'Point'
184
+ def to_kml(elem = nil, short = false)
185
+ e = XML::Node.new 'Point'
143
186
  super(e)
144
- e.attributes['id'] = @id
145
- c = REXML::Element.new 'coordinates'
146
- c.text = "#{ @longitude }, #{ @latitude }, #{ @altitude }"
147
- e.elements.add c
187
+ e.attributes['id'] = @kml_id
188
+ c = XML::Node.new 'coordinates'
189
+ c << "#{ @longitude }, #{ @latitude }, #{ @altitude }"
190
+ e << c
148
191
 
149
192
  if not short then
150
- c = REXML::Element.new 'extrude'
151
- c.text = @extrude ? 1 : 0
152
- e.elements.add c
193
+ c = XML::Node.new 'extrude'
194
+ c << ( @extrude ? 1 : 0 ).to_s
195
+ e << c
153
196
 
154
197
  Kamelopard.add_altitudeMode(@altitudeMode, e)
155
198
  end
156
199
 
157
- d = REXML::Document.new
158
- d.add_element e
159
- d
200
+ elem << e unless elem.nil?
201
+ e
160
202
  end
161
203
  end
162
204
 
163
205
  # Helper class for KML objects which need to know about several points at once
164
- class CoordinateList
206
+ module CoordinateList
165
207
  attr_reader :coordinates
166
208
 
167
- # Accepts an optional array of coordinates in any format add_element
168
- # accepts
169
- def initialize(coords = nil)
170
- # Internally we store coordinates as an array of three-element
171
- # arrays
172
- @coordinates = []
173
- if not coords.nil? then
174
- add_element coords
209
+ def coordinates=(a)
210
+ if a.nil? then
211
+ coordinates = []
175
212
  else
176
- @coordinates = []
213
+ add_element a
177
214
  end
178
215
  end
179
216
 
180
- def to_kml(elem = nil)
181
- e = REXML::Element.new 'coordinates'
217
+ def coordinates_to_kml(elem = nil)
218
+ e = XML::Node.new 'coordinates'
182
219
  t = ''
183
220
  @coordinates.each do |a|
184
221
  t << "#{ a[0] },#{ a[1] }"
185
222
  t << ",#{ a[2] }" if a.size > 2
186
223
  t << ' '
187
224
  end
188
- e.text = t.chomp(' ')
189
- elem.elements.add e unless elem.nil?
225
+ e << t.chomp(' ')
226
+ elem << e unless elem.nil?
190
227
  e
191
228
  end
192
229
 
@@ -204,6 +241,9 @@ module Kamelopard
204
241
  # Note that this will not accept a one-dimensional array of numbers to add
205
242
  # a single point. Instead, create a Point with those numbers, and pass
206
243
  # it to add_element
244
+ #-
245
+ # XXX The above stipulation is a weakness that needs fixing
246
+ #+
207
247
  def add_element(a)
208
248
  if a.kind_of? Enumerable then
209
249
  # We've got some sort of array or list. It could be a list of
@@ -252,31 +292,17 @@ module Kamelopard
252
292
 
253
293
  # Corresponds to the KML LineString object
254
294
  class LineString < Geometry
295
+ include CoordinateList
255
296
  attr_accessor :altitudeOffset, :extrude, :tessellate, :altitudeMode, :drawOrder, :longitude, :latitude, :altitude
256
- attr_reader :coordinates
257
297
 
258
- def initialize(coords, altMode = :clampToGround)
259
- super()
260
- @altitudeMode = altMode
261
- set_coords coords
262
- end
263
-
264
- # Sets @coordinates element
265
- def set_coords(a)
266
- if a.kind_of? CoordinateList then
267
- @coordinates = a
268
- else
269
- @coordinates = CoordinateList.new(a)
270
- end
271
- end
272
-
273
- # Appends an element to this LineString's CoordinateList. See CoordinateList#add_element
274
- def <<(a)
275
- @coordinates << a
298
+ def initialize(coordinates = [], options = {})
299
+ @coordinates = []
300
+ super options
301
+ self.coordinates=(coordinates) unless coordinates.nil?
276
302
  end
277
303
 
278
304
  def to_kml(elem = nil)
279
- k = REXML::Element.new 'LineString'
305
+ k = XML::Node.new 'LineString'
280
306
  super(k)
281
307
  Kamelopard.kml_array(k, [
282
308
  [@altitudeOffset, 'gx:altitudeOffset'],
@@ -284,48 +310,30 @@ module Kamelopard
284
310
  [@tessellate, 'tessellate'],
285
311
  [@drawOrder, 'gx:drawOrder']
286
312
  ])
287
- @coordinates.to_kml(k) unless @coordinates.nil?
313
+ coordinates_to_kml(k) unless @coordinates.nil?
288
314
  Kamelopard.add_altitudeMode @altitudeMode, k
289
- elem.elements << k unless elem.nil?
315
+ elem << k unless elem.nil?
290
316
  k
291
317
  end
292
318
  end
293
319
 
294
320
  # Corresponds to KML's LinearRing object
295
321
  class LinearRing < Geometry
296
- attr_accessor :altitudeOffset, :extrude, :tessellate, :altitudeMode, :coordinates
297
-
298
- def initialize(coordinates = nil, tessellate = 0, extrude = 0, altitudeMode = :clampToGround, altitudeOffset = nil)
299
- super()
300
- if coordinates.nil? then
301
- @coordinates = nil
302
- elsif coordinates.kind_of? CoordinateList then
303
- @coordinates = coordinates
304
- else
305
- @coordinates = CoordinateList.new(coordinates)
306
- end
307
- @tessellate = tessellate
308
- @extrude = extrude
309
- @altitudeMode = altitudeMode
310
- @altitudeOffset = altitudeOffset
311
- end
322
+ attr_accessor :altitudeOffset, :extrude, :tessellate, :altitudeMode
323
+ include CoordinateList
312
324
 
313
- # Sets @coordinates element
314
- def set_coords(a)
315
- if a.kind_of? CoordinateList then
316
- @coordinates = a
317
- else
318
- @coordinates = CoordinateList.new(a)
319
- end
320
- end
325
+ def initialize(coordinates = [], options = {})
326
+ @tessellate = 0
327
+ @extrude = 0
328
+ @altitudeMode = :clampToGround
329
+ @coordinates = []
321
330
 
322
- # Appends an element to this LinearRing's CoordinateList. See CoordinateList#add_element
323
- def <<(a)
324
- @coordinates << a
331
+ super options
332
+ self.coordinates=(coordinates) unless coordinates.nil?
325
333
  end
326
334
 
327
335
  def to_kml(elem = nil)
328
- k = REXML::Element.new 'LinearRing'
336
+ k = XML::Node.new 'LinearRing'
329
337
  super(k)
330
338
  Kamelopard.kml_array(k, [
331
339
  [ @altitudeOffset, 'gx:altitudeOffset' ],
@@ -333,39 +341,44 @@ module Kamelopard
333
341
  [ @extrude, 'extrude' ]
334
342
  ])
335
343
  Kamelopard.add_altitudeMode(@altitudeMode, k)
336
- @coordinates.to_kml(k)
337
- elem.elements << k unless elem.nil?
344
+ coordinates_to_kml(k) unless @coordinates.nil?
345
+ elem << k unless elem.nil?
338
346
  k
339
347
  end
340
348
  end
341
349
 
342
350
  # Abstract class corresponding to KML's AbstractView object
343
351
  class AbstractView < Object
344
- attr_accessor :timestamp, :timespan, :options, :point, :heading, :tilt, :roll, :range, :altitudeMode
345
- def initialize(className, point = nil, heading = 0, tilt = 0, roll = 0, range = 0, altitudeMode = :clampToGround)
352
+ attr_accessor :timestamp, :timespan, :viewerOptions, :heading, :tilt, :roll, :range, :altitudeMode
353
+ attr_reader :className, :point
354
+
355
+ def initialize(className, point, options = {})
346
356
  raise "className argument must not be nil" if className.nil?
347
- super()
348
- @point = point
349
- @options = {}
357
+
358
+ @heading = 0
359
+ @tilt = 0
360
+ @roll = 0
361
+ @range = 0
362
+ @altitudeMode = :clampToGround
363
+ @viewerOptions = {}
364
+
365
+ super options
366
+
350
367
  @className = className
368
+ self.point= point unless point.nil?
369
+ end
370
+
371
+ def point=(point)
351
372
  if point.nil? then
352
373
  @point = nil
353
- elsif point.kind_of? Placemark then
354
- @point = point.point
355
374
  else
356
- @point = point
375
+ if point.respond_to? :point then
376
+ a = point.point
377
+ else
378
+ a = point
379
+ end
380
+ @point = Point.new a.longitude, a.latitude, a.altitude
357
381
  end
358
- @heading = heading
359
- @tilt = tilt
360
- @roll = roll
361
- @range = range
362
- @altitudeMode = altitudeMode
363
- end
364
-
365
- def point=(point)
366
- @point.longitude = point.longitude
367
- @point.latitude = point.latitude
368
- @point.altitude = point.altitude
369
382
  end
370
383
 
371
384
  def longitude
@@ -405,7 +418,7 @@ module Kamelopard
405
418
  end
406
419
 
407
420
  def to_kml(elem = nil)
408
- t = REXML::Element.new @className
421
+ t = XML::Node.new @className
409
422
  super(t)
410
423
  Kamelopard.kml_array(t, [
411
424
  [ @point.nil? ? nil : @point.longitude, 'longitude' ],
@@ -417,27 +430,27 @@ module Kamelopard
417
430
  [ @roll, 'roll' ]
418
431
  ])
419
432
  Kamelopard.add_altitudeMode(@altitudeMode, t)
420
- if @options.keys.length > 0 then
421
- vo = REXML::Element.new 'gx:ViewerOptions'
422
- @options.each do |k, v|
423
- o = REXML::Element.new 'gx:option'
424
- o.attributes['name'] = k
433
+ if @viewerOptions.keys.length > 0 then
434
+ vo = XML::Node.new 'gx:ViewerOptions'
435
+ @viewerOptions.each do |k, v|
436
+ o = XML::Node.new 'gx:option'
437
+ o.attributes['name'] = k.to_s
425
438
  o.attributes['enabled'] = v ? 'true' : 'false'
426
- vo.elements << o
439
+ vo << o
427
440
  end
428
- t.elements << vo
441
+ t << vo
429
442
  end
430
443
  if not @timestamp.nil? then
431
444
  @timestamp.to_kml(t, 'gx')
432
445
  elsif not @timespan.nil? then
433
446
  @timespan.to_kml(t, 'gx')
434
447
  end
435
- elem.elements << t unless elem.nil?
448
+ elem << t unless elem.nil?
436
449
  t
437
450
  end
438
451
 
439
452
  def [](a)
440
- return @options[a]
453
+ return @viewerOptions[a]
441
454
  end
442
455
 
443
456
  def []=(a, b)
@@ -447,14 +460,14 @@ module Kamelopard
447
460
  if a != :streetview and a != :historicalimagery and a != :sunlight then
448
461
  raise 'Option index must be :streetview, :historicalimagery, or :sunlight'
449
462
  end
450
- @options[a] = b
463
+ @viewerOptions[a] = b
451
464
  end
452
465
  end
453
466
 
454
467
  # Corresponds to KML's Camera object
455
468
  class Camera < AbstractView
456
- def initialize(point = nil, heading = 0, tilt = 0, roll = 0, altitudeMode = :clampToGround)
457
- super('Camera', point, heading, tilt, roll, nil, altitudeMode)
469
+ def initialize(point = nil, options = {})
470
+ super('Camera', point, options)
458
471
  end
459
472
 
460
473
  def range
@@ -468,8 +481,8 @@ module Kamelopard
468
481
 
469
482
  # Corresponds to KML's LookAt object
470
483
  class LookAt < AbstractView
471
- def initialize(point = nil, heading = 0, tilt = 0, range = 0, altitudeMode = :clampToGround)
472
- super('LookAt', point, heading, tilt, nil, range, altitudeMode)
484
+ def initialize(point = nil, options = {})
485
+ super('LookAt', point, options)
473
486
  end
474
487
 
475
488
  def roll
@@ -488,21 +501,21 @@ module Kamelopard
488
501
  # Corresponds to KML's TimeStamp object. The @when attribute must be in a format KML understands.
489
502
  class TimeStamp < TimePrimitive
490
503
  attr_accessor :when
491
- def initialize(t_when)
492
- super()
493
- @when = t_when
504
+ def initialize(ts_when = nil, options = {})
505
+ super options
506
+ @when = ts_when unless ts_when.nil?
494
507
  end
495
508
 
496
509
  def to_kml(elem = nil, ns = nil)
497
510
  prefix = ''
498
511
  prefix = ns + ':' unless ns.nil?
499
-
500
- k = REXML::Element.new "#{prefix}TimeStamp"
512
+
513
+ k = XML::Node.new "#{prefix}TimeStamp"
501
514
  super(k)
502
- w = REXML::Element.new 'when'
503
- w.text = @when
504
- k.elements << w
505
- elem.elements << k unless elem.nil?
515
+ w = XML::Node.new 'when'
516
+ w << @when
517
+ k << w
518
+ elem << k unless elem.nil?
506
519
  k
507
520
  end
508
521
  end
@@ -511,65 +524,85 @@ module Kamelopard
511
524
  # understands.
512
525
  class TimeSpan < TimePrimitive
513
526
  attr_accessor :begin, :end
514
- def initialize(t_begin, t_end)
515
- super()
516
- @begin = t_begin
517
- @end = t_end
527
+ def initialize(ts_begin = nil, ts_end = nil, options = {})
528
+ super options
529
+ @begin = ts_begin unless ts_begin.nil?
530
+ @end = ts_end unless ts_end.nil?
518
531
  end
519
532
 
520
533
  def to_kml(elem = nil, ns = nil)
521
534
  prefix = ''
522
535
  prefix = ns + ':' unless ns.nil?
523
-
524
- k = REXML::Element.new "#{prefix}TimeSpan"
536
+
537
+ k = XML::Node.new "#{prefix}TimeSpan"
525
538
  super(k)
526
539
  if not @begin.nil? then
527
- w = REXML::Element.new 'begin'
528
- w.text = @begin
529
- k.elements << w
540
+ w = XML::Node.new 'begin'
541
+ w << @begin
542
+ k << w
530
543
  end
531
544
  if not @end.nil? then
532
- w = REXML::Element.new 'end'
533
- w.text = @end
534
- k.elements << w
535
- elem.elements << k unless elem.nil?
545
+ w = XML::Node.new 'end'
546
+ w << @end
547
+ k << w
548
+ elem << k unless elem.nil?
536
549
  end
537
550
  k
538
551
  end
539
552
  end
540
553
 
541
554
  # Support class for Feature object
542
- class Snippet
543
- attr_accessor :text, :maxLines
544
- def initialize(text = nil, maxLines = 2)
545
- @text = text
546
- @maxLines = maxLines
547
- end
548
-
549
- def to_kml(elem = nil)
550
- e = REXML::Element.new 'Snippet'
551
- e.attributes['maxLines'] = @maxLines
552
- e.text = @text
553
- elem.elements << e unless elem.nil?
555
+ module Snippet
556
+ attr_accessor :snippet_text, :maxLines
557
+
558
+ def snippet_to_kml(elem = nil)
559
+ e = XML::Node.new 'Snippet'
560
+ e.attributes['maxLines'] = @maxLines.to_s
561
+ e << @snippet_text
562
+ elem << e unless elem.nil?
554
563
  e
555
564
  end
556
565
  end
557
566
 
558
567
  # Abstract class corresponding to KML's Feature object.
559
568
  class Feature < Object
560
- # Abatract class
569
+ # Abstract class
561
570
  attr_accessor :visibility, :open, :atom_author, :atom_link, :name,
562
- :phoneNumber, :snippet, :description, :abstractView,
571
+ :phoneNumber, :description, :abstractView,
563
572
  :timeprimitive, :styleUrl, :styleSelector, :region, :metadata,
564
573
  :extendedData, :styles
565
- attr_reader :addressDetails
574
+ attr_reader :addressDetails, :snippet
566
575
 
567
- def initialize (name = nil)
568
- super()
569
- @name = name
576
+ include Snippet
577
+
578
+ def initialize (name = nil, options = {})
570
579
  @visibility = true
571
580
  @open = false
572
581
  @styles = []
582
+ super options
583
+ @name = name unless name.nil?
584
+ end
585
+
586
+ def styles=(a)
587
+ if a.is_a? Array then
588
+ @styles = a
589
+ elsif @styles.nil? then
590
+ @styles = []
591
+ else
592
+ @styles = [a]
593
+ end
594
+ end
595
+
596
+ # Hides the object. Note that this governs only whether the object is
597
+ # initially visible or invisible; to show or hide the feature
598
+ # dynamically during a tour, use an AnimatedUpdate object
599
+ def hide
600
+ @visibility = false
601
+ end
602
+
603
+ # Shows the object. See note for hide() method
604
+ def show
605
+ @visibility = true
573
606
  end
574
607
 
575
608
  def timestamp
@@ -598,28 +631,28 @@ module Kamelopard
598
631
  end
599
632
 
600
633
  # This function accepts either a StyleSelector object, or a string
601
- # containing the desired StyleSelector's @id
634
+ # containing the desired StyleSelector's @kml_id
602
635
  def styleUrl=(a)
603
636
  if a.is_a? String then
604
637
  @styleUrl = a
605
638
  elsif a.respond_to? 'id' then
606
- @styleUrl = "##{ a.id }"
639
+ @styleUrl = "##{ a.kml_id }"
607
640
  else
608
641
  @styleUrl = a.to_s
609
642
  end
610
643
  end
611
644
 
612
645
  def self.add_author(o, a)
613
- e = REXML::Element.new 'atom:name'
614
- e.text = a
615
- f = REXML::Element.new 'atom:author'
646
+ e = XML::Node.new 'atom:name'
647
+ e << a.to_s
648
+ f = XML::Node.new 'atom:author'
616
649
  f << e
617
650
  o << f
618
651
  end
619
652
 
620
653
  def to_kml(elem = nil)
621
- elem = REXML::Element.new 'Feature' if elem.nil?
622
- super(elem)
654
+ elem = XML::Node.new 'Feature' if elem.nil?
655
+ super elem
623
656
  Kamelopard.kml_array(elem, [
624
657
  [@name, 'name'],
625
658
  [(@visibility.nil? || @visibility) ? 1 : 0, 'visibility'],
@@ -636,14 +669,14 @@ module Kamelopard
636
669
  [@extendedData, 'ExtendedData' ]
637
670
  ])
638
671
  styles_to_kml(elem)
639
- @snippet.to_kml(elem) unless @snippet.nil?
672
+ snippet_to_kml(elem) unless @snippet_text.nil?
640
673
  @abstractView.to_kml(elem) unless @abstractView.nil?
641
674
  @timeprimitive.to_kml(elem) unless @timeprimitive.nil?
642
675
  @region.to_kml(elem) unless @region.nil?
643
676
  yield(elem) if block_given?
644
- elem
677
+ elem
645
678
  end
646
-
679
+
647
680
  def styles_to_kml(elem)
648
681
  @styles.each do |a|
649
682
  a.to_kml(elem)
@@ -653,9 +686,17 @@ module Kamelopard
653
686
 
654
687
  # Abstract class corresponding to KML's Container object.
655
688
  class Container < Feature
656
- def initialize
657
- super
689
+ def initialize(name = nil, options = {})
658
690
  @features = []
691
+ super
692
+ end
693
+
694
+ def features=(a)
695
+ if a.respond_to? :[] then
696
+ @features = a
697
+ else
698
+ @features = [a]
699
+ end
659
700
  end
660
701
 
661
702
  # Adds a new object to this container.
@@ -668,16 +709,31 @@ module Kamelopard
668
709
  class Folder < Container
669
710
  attr_accessor :styles, :folders, :parent_folder
670
711
 
671
- def initialize(name = nil)
672
- super()
673
- @name = name
712
+ def initialize(name = nil, options = {})
674
713
  @styles = []
675
714
  @folders = []
715
+ super
676
716
  Document.instance.folders << self
677
717
  end
678
718
 
719
+ def styles=(a)
720
+ if a.respond_to? :[] then
721
+ @styles = a
722
+ else
723
+ @styles = [a]
724
+ end
725
+ end
726
+
727
+ def folders=(a)
728
+ if a.respond_to? :[] then
729
+ @folders = a
730
+ else
731
+ @folders = [a]
732
+ end
733
+ end
734
+
679
735
  def to_kml(elem = nil)
680
- h = REXML::Element.new 'Folder'
736
+ h = XML::Node.new 'Folder'
681
737
  super h
682
738
  @features.each do |a|
683
739
  a.to_kml(h)
@@ -685,7 +741,7 @@ module Kamelopard
685
741
  @folders.each do |a|
686
742
  a.to_kml(h)
687
743
  end
688
- elem.elements << h unless elem.nil?
744
+ elem << h unless elem.nil?
689
745
  h
690
746
  end
691
747
 
@@ -711,36 +767,35 @@ module Kamelopard
711
767
  # scripts can (for now) manage only one Document at a time.
712
768
  class Document < Container
713
769
  include Singleton
714
- attr_accessor :flyto_mode, :folders, :tours, :uses_xal
770
+ attr_accessor :flyto_mode, :doc_folders, :doc_tours, :uses_xal, :doc_styles
715
771
 
716
- def initialize
772
+ def initialize(options = {})
773
+ @doc_tours = []
774
+ @doc_folders = []
775
+ @doc_styles = []
717
776
  super
718
- @tours = []
719
- @folders = []
720
- @styles = []
721
777
  end
722
778
 
723
779
  # Returns the current Tour object
724
780
  def tour
725
- @tours << Tour.new if @tours.length == 0
726
- @tours.last
781
+ Tour.new if @doc_tours.length == 0
782
+ @doc_tours.last
727
783
  end
728
784
 
729
785
  # Returns the current Folder object
730
786
  def folder
731
- if @folders.size == 0 then
787
+ if @doc_folders.size == 0 then
732
788
  Folder.new
733
789
  end
734
- @folders.last
790
+ @doc_folders.last
735
791
  end
736
792
 
737
- # def styles_to_kml(elem = nil)
738
- # end
739
-
740
793
  def get_kml_document
741
- k = REXML::Document.new
742
- k << REXML::XMLDecl.default
743
- r = REXML::Element.new('kml')
794
+ k = XML::Document.new
795
+ # XXX fix this
796
+ #k << XML::XMLDecl.default
797
+ k.root = XML::Node.new('kml')
798
+ r = k.root
744
799
  if @uses_xal then
745
800
  r.attributes['xmlns:xal'] = "urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"
746
801
  end
@@ -749,25 +804,24 @@ module Kamelopard
749
804
  r.attributes['xmlns:gx'] = 'http://www.google.com/kml/ext/2.2'
750
805
  r.attributes['xmlns:kml'] = 'http://www.opengis.net/kml/2.2'
751
806
  r.attributes['xmlns:atom'] = 'http://www.w3.org/2005/Atom'
752
- r.elements << self.to_kml
753
- k << r
807
+ r << self.to_kml
754
808
  k
755
809
  end
756
810
 
757
811
  def to_kml
758
- d = REXML::Element.new 'Document'
759
- super(d)
812
+ d = XML::Node.new 'Document'
813
+ super d
760
814
 
761
815
  # Print styles first
762
- @styles.map do |a| a.to_kml(d) unless a.attached? end
816
+ @doc_styles.map do |a| d << a.to_kml unless a.attached? end
763
817
 
764
818
  # then folders
765
- @folders.map do |a|
819
+ @doc_folders.map do |a|
766
820
  a.to_kml(d) unless a.has_parent?
767
821
  end
768
822
 
769
823
  # then tours
770
- @tours.map do |a| a.to_kml(d) end
824
+ @doc_tours.map do |a| a.to_kml(d) end
771
825
 
772
826
  d
773
827
  end
@@ -779,13 +833,10 @@ module Kamelopard
779
833
  class ColorStyle < Object
780
834
  attr_accessor :color
781
835
  attr_reader :colorMode
782
-
783
- def initialize(color, colorMode = :normal)
784
- super()
785
- # Note: color element order is aabbggrr
786
- @color = color
787
- validate_colorMode colorMode
788
- @colorMode = colorMode # Can be :normal or :random
836
+
837
+ def initialize(color = nil, options = {})
838
+ super options
839
+ @color = color unless color.nil?
789
840
  end
790
841
 
791
842
  def validate_colorMode(a)
@@ -830,14 +881,14 @@ module Kamelopard
830
881
  end
831
882
 
832
883
  def to_kml(elem = nil)
833
- k = elem.nil? ? REXML::Element.new('ColorStyle') : elem
884
+ k = elem.nil? ? XML::Node.new('ColorStyle') : elem
834
885
  super k
835
- e = REXML::Element.new 'color'
836
- e.text = @color
837
- k.elements << e
838
- e = REXML::Element.new 'colorMode'
839
- e.text = @colorMode
840
- k.elements << e
886
+ e = XML::Node.new 'color'
887
+ e << @color
888
+ k << e
889
+ e = XML::Node.new 'colorMode'
890
+ e << @colorMode
891
+ k << e
841
892
  k
842
893
  end
843
894
  end
@@ -849,16 +900,17 @@ module Kamelopard
849
900
  attr_accessor :bgColor, :text, :textColor, :displayMode
850
901
 
851
902
  # Note: color element order is aabbggrr
852
- def initialize(text = '', textColor = 'ff000000', bgColor = 'ffffffff', displayMode = :default)
853
- super()
854
- @bgColor = bgColor
855
- @text = text
856
- @textColor = textColor
857
- @displayMode = displayMode
903
+ def initialize(text = nil, options = {})
904
+ #text = '', textColor = 'ff000000', bgColor = 'ffffffff', displayMode = :default)
905
+ @bgColor = 'ffffffff'
906
+ @textColor = 'ff000000'
907
+ @displayMode = :default
908
+ super options
909
+ @text = text unless text.nil?
858
910
  end
859
911
 
860
912
  def to_kml(elem = nil)
861
- k = REXML::Element.new 'BalloonStyle'
913
+ k = XML::Node.new 'BalloonStyle'
862
914
  super k
863
915
  Kamelopard.kml_array(k, [
864
916
  [ @bgColor, 'bgColor' ],
@@ -882,28 +934,29 @@ module Kamelopard
882
934
  end
883
935
 
884
936
  def to_kml(name, elem = nil)
885
- k = REXML::Element.new name
886
- k.attributes['x'] = @x
887
- k.attributes['y'] = @y
888
- k.attributes['xunits'] = @xunits
889
- k.attributes['yunits'] = @yunits
890
- elem.elements << k unless elem.nil?
937
+ k = XML::Node.new name
938
+ k.attributes['x'] = @x.to_s
939
+ k.attributes['y'] = @y.to_s
940
+ k.attributes['xunits'] = @xunits.to_s
941
+ k.attributes['yunits'] = @yunits.to_s
942
+ elem << k unless elem.nil?
891
943
  k
892
944
  end
893
945
  end
894
946
 
895
947
  # Corresponds to the KML Icon object
896
- class Icon
897
- attr_accessor :id, :href, :x, :y, :w, :h, :refreshMode, :refreshInterval, :viewRefreshMode, :viewRefreshTime, :viewBoundScale, :viewFormat, :httpQuery
948
+ module Icon
949
+ attr_accessor :href, :x, :y, :w, :h, :refreshMode, :refreshInterval, :viewRefreshMode, :viewRefreshTime, :viewBoundScale, :viewFormat, :httpQuery
898
950
 
899
- def initialize(href = nil)
900
- @href = href
901
- @id = "Icon_#{ Kamelopard.get_next_id }"
951
+ def href=(h)
952
+ @icon_id = "Icon_#{Kamelopard.get_next_id}" if @icon_id.nil?
953
+ @href = h
902
954
  end
903
955
 
904
- def to_kml(elem = nil)
905
- k = REXML::Element.new 'Icon'
906
- k.attributes['id'] = @id
956
+ def icon_to_kml(elem = nil)
957
+ @icon_id = "Icon_#{Kamelopard.get_next_id}" if @icon_id.nil?
958
+ k = XML::Node.new 'Icon'
959
+ k.attributes['id'] = @icon_id
907
960
  Kamelopard.kml_array(k, [
908
961
  [@href, 'href'],
909
962
  [@x, 'gx:x'],
@@ -918,40 +971,56 @@ module Kamelopard
918
971
  [@viewFormat, 'viewFormat'],
919
972
  [@httpQuery, 'httpQuery'],
920
973
  ])
921
- elem.elements << k unless elem.nil?
974
+ elem << k unless elem.nil?
922
975
  k
923
976
  end
924
977
  end
925
978
 
926
979
  # Corresponds to KML's IconStyle object.
927
980
  class IconStyle < ColorStyle
928
- attr_accessor :scale, :heading, :hotspot, :icon
981
+ attr_accessor :scale, :heading, :hotspot
929
982
 
930
- def initialize(href, scale = 1, heading = 0, hs_x = 0.5, hs_y = 0.5, hs_xunits = :fraction, hs_yunits = :fraction, color = 'ffffffff', colormode = :normal)
931
- super(color, colormode)
932
- @scale = scale
933
- @heading = heading
934
- @icon = Icon.new(href) unless href.nil?
935
- @hotspot = XY.new(hs_x, hs_y, hs_xunits, hs_yunits) unless (hs_x.nil? and hs_y.nil? and hs_xunits.nil? and hs_yunits.nil?)
983
+ include Icon
984
+
985
+ def initialize(href = nil, options = {})
986
+ @hotspot = XY.new(0.5, 0.5, :fraction, :fraction)
987
+ super nil, options
988
+ @href = href unless href.nil?
989
+ end
990
+
991
+ def hs_x=(a)
992
+ @hotspot.x = a
993
+ end
994
+
995
+ def hs_y=(a)
996
+ @hotspot.y = a
997
+ end
998
+
999
+ def hs_xunits=(a)
1000
+ @hotspot.xunits = a
1001
+ end
1002
+
1003
+ def hs_yunits=(a)
1004
+ @hotspot.yunits = a
936
1005
  end
937
1006
 
938
1007
  def to_kml(elem = nil)
939
- k = REXML::Element.new 'IconStyle'
1008
+ k = XML::Node.new 'IconStyle'
940
1009
  super(k)
941
1010
  Kamelopard.kml_array( k, [
942
1011
  [ @scale, 'scale' ],
943
1012
  [ @heading, 'heading' ]
944
1013
  ])
945
1014
  if not @hotspot.nil? then
946
- h = REXML::Element.new 'hotSpot'
947
- h.attributes['x'] = @hotspot.x
948
- h.attributes['y'] = @hotspot.y
949
- h.attributes['xunits'] = @hotspot.xunits
950
- h.attributes['yunits'] = @hotspot.yunits
951
- k.elements << h
1015
+ h = XML::Node.new 'hotSpot'
1016
+ h.attributes['x'] = @hotspot.x.to_s
1017
+ h.attributes['y'] = @hotspot.y.to_s
1018
+ h.attributes['xunits'] = @hotspot.xunits.to_s
1019
+ h.attributes['yunits'] = @hotspot.yunits.to_s
1020
+ k << h
952
1021
  end
953
- @icon.to_kml(k) unless @icon.nil?
954
- elem.elements << k unless elem.nil?
1022
+ icon_to_kml(k)
1023
+ elem << k unless elem.nil?
955
1024
  k
956
1025
  end
957
1026
  end
@@ -960,18 +1029,18 @@ module Kamelopard
960
1029
  class LabelStyle < ColorStyle
961
1030
  attr_accessor :scale
962
1031
 
963
- def initialize(scale = 1, color = 'ffffffff', colormode = :normal)
964
- super(color, colormode)
965
- @scale = scale
1032
+ def initialize(scale = 1, options = {})
1033
+ @scale = scale
1034
+ super nil, options
966
1035
  end
967
1036
 
968
1037
  def to_kml(elem = nil)
969
- k = REXML::Element.new 'LabelStyle'
1038
+ k = XML::Node.new 'LabelStyle'
970
1039
  super k
971
- s = REXML::Element.new 'scale'
972
- s.text = @scale
973
- k.elements << s
974
- elem.elements << k unless elem.nil?
1040
+ s = XML::Node.new 'scale'
1041
+ s << @scale.to_s
1042
+ k << s
1043
+ elem << k unless elem.nil?
975
1044
  k
976
1045
  end
977
1046
  end
@@ -980,18 +1049,20 @@ module Kamelopard
980
1049
  # string, with two characters each of alpha, blue, green, and red values, in
981
1050
  # that order, matching the ordering the KML spec demands.
982
1051
  class LineStyle < ColorStyle
983
- attr_accessor :outerColor, :outerWidth, :physicalWidth, :width
1052
+ attr_accessor :outerColor, :outerWidth, :physicalWidth, :width, :labelVisibility
1053
+
1054
+ def initialize(options = {})
1055
+ @outerColor = 'ffffffff'
1056
+ @width = 1
1057
+ @outerWidth = 0
1058
+ @physicalWidth = 0
1059
+ @labelVisibility = 0
984
1060
 
985
- def initialize(width = 1, outercolor = 'ffffffff', outerwidth = 0, physicalwidth = 0, color = 'ffffffff', colormode = :normal)
986
- super(color, colormode)
987
- @width = width
988
- @outerColor = outercolor
989
- @outerWidth = outerwidth
990
- @physicalWidth = physicalwidth
1061
+ super nil, options
991
1062
  end
992
1063
 
993
1064
  def to_kml(elem = nil)
994
- k = REXML::Element.new 'LineStyle'
1065
+ k = XML::Node.new 'LineStyle'
995
1066
  super k
996
1067
  Kamelopard.kml_array(k, [
997
1068
  [ @width, 'width' ],
@@ -999,7 +1070,7 @@ module Kamelopard
999
1070
  [ @outerWidth, 'gx:outerWidth' ],
1000
1071
  [ @physicalWidth, 'gx:physicalWidth' ],
1001
1072
  ])
1002
- elem.elements << k unless elem.nil?
1073
+ elem << k unless elem.nil?
1003
1074
  k
1004
1075
  end
1005
1076
  end
@@ -1007,33 +1078,38 @@ module Kamelopard
1007
1078
  # Corresponds to KML's ListStyle object. Color is stored as an 8-character hex
1008
1079
  # string, with two characters each of alpha, blue, green, and red values, in
1009
1080
  # that order, matching the ordering the KML spec demands.
1010
- class ListStyle < ColorStyle
1081
+ #--
1082
+ # This doesn't descend from ColorStyle because I don't want the to_kml()
1083
+ # call to super() adding color and colorMode elements to the KML -- Google
1084
+ # Earth complains about 'em
1085
+ #++
1086
+ class ListStyle < Object
1011
1087
  attr_accessor :listItemType, :bgColor, :state, :href
1012
1088
 
1013
- def initialize(bgcolor = nil, state = nil, href = nil, listitemtype = nil)
1014
- super(nil, :normal)
1015
- @bgcolor = bgcolor
1016
- @state = state
1017
- @href = href
1018
- @listitemtype = listitemtype
1089
+ def initialize(options = {})
1090
+ #bgcolor = nil, state = nil, href = nil, listitemtype = nil)
1091
+ @state = :open
1092
+ @bgColor = 'ffffffff'
1093
+ super
1019
1094
  end
1020
1095
 
1021
1096
  def to_kml(elem = nil)
1022
- k = REXML::Element.new 'ListStyle'
1097
+ k = XML::Node.new 'ListStyle'
1098
+
1023
1099
  super k
1024
1100
  Kamelopard.kml_array(k, [
1025
- [@listitemtype, 'listItemType'],
1026
- [@bgcolor, 'bgColor']
1101
+ [@listItemType, 'listItemType'],
1102
+ [@bgColor, 'bgColor']
1027
1103
  ])
1028
1104
  if (! @state.nil? or ! @href.nil?) then
1029
- i = REXML::Element.new 'ItemIcon'
1105
+ i = XML::Node.new 'ItemIcon'
1030
1106
  Kamelopard.kml_array(i, [
1031
1107
  [ @state, 'state' ],
1032
1108
  [ @href, 'href' ]
1033
1109
  ])
1034
- k.elements << i
1110
+ k << i
1035
1111
  end
1036
- elem.elements << k unless elem.nil?
1112
+ elem << k unless elem.nil?
1037
1113
  k
1038
1114
  end
1039
1115
  end
@@ -1044,31 +1120,32 @@ module Kamelopard
1044
1120
  class PolyStyle < ColorStyle
1045
1121
  attr_accessor :fill, :outline
1046
1122
 
1047
- def initialize(fill = 1, outline = 1, color = 'ffffffff', colormode = :normal)
1048
- super(color, colormode)
1049
- @fill = fill
1050
- @outline = outline
1123
+ def initialize(options = {})
1124
+ #fill = 1, outline = 1, color = 'ffffffff', colormode = :normal)
1125
+ @fill = 1
1126
+ @outline = 1
1127
+ super nil, options
1051
1128
  end
1052
1129
 
1053
1130
  def to_kml(elem = nil)
1054
- k = REXML::Element.new 'PolyStyle'
1131
+ k = XML::Node.new 'PolyStyle'
1055
1132
  super k
1056
1133
  Kamelopard.kml_array( k, [
1057
1134
  [ @fill, 'fill' ],
1058
1135
  [ @outline, 'outline' ]
1059
1136
  ])
1060
- elem.elements << k unless elem.nil?
1137
+ elem << k unless elem.nil?
1061
1138
  k
1062
1139
  end
1063
1140
  end
1064
1141
 
1065
1142
  # Abstract class corresponding to KML's StyleSelector object.
1066
1143
  class StyleSelector < Object
1067
- attr_accessor :attached
1068
- def initialize
1144
+
1145
+ def initialize(options = {})
1069
1146
  super
1070
1147
  @attached = false
1071
- Document.instance.styles << self
1148
+ Document.instance.doc_styles << self
1072
1149
  end
1073
1150
 
1074
1151
  def attached?
@@ -1081,7 +1158,7 @@ module Kamelopard
1081
1158
  end
1082
1159
 
1083
1160
  def to_kml(elem = nil)
1084
- elem = REXML::Element.new 'StyleSelector' if elem.nil?
1161
+ elem = XML::Node.new 'StyleSelector' if elem.nil?
1085
1162
  super elem
1086
1163
  elem
1087
1164
  end
@@ -1091,26 +1168,17 @@ module Kamelopard
1091
1168
  # LabelStyle, LineStyle, PolyStyle, BalloonStyle, and ListStyle objects.
1092
1169
  class Style < StyleSelector
1093
1170
  attr_accessor :icon, :label, :line, :poly, :balloon, :list
1094
- def initialize(icon = nil, label = nil, line = nil, poly = nil, balloon = nil, list = nil)
1095
- super()
1096
- @icon = icon
1097
- @label = label
1098
- @line = line
1099
- @poly = poly
1100
- @balloon = balloon
1101
- @list = list
1102
- end
1103
1171
 
1104
1172
  def to_kml(elem = nil)
1105
- k = REXML::Element.new 'Style'
1106
- super(k)
1173
+ k = XML::Node.new 'Style'
1174
+ super k
1107
1175
  @icon.to_kml(k) unless @icon.nil?
1108
1176
  @label.to_kml(k) unless @label.nil?
1109
1177
  @line.to_kml(k) unless @line.nil?
1110
1178
  @poly.to_kml(k) unless @poly.nil?
1111
1179
  @balloon.to_kml(k) unless @balloon.nil?
1112
1180
  @list.to_kml(k) unless @list.nil?
1113
- elem.elements << k unless elem.nil?
1181
+ elem << k unless elem.nil?
1114
1182
  k
1115
1183
  end
1116
1184
  end
@@ -1120,8 +1188,8 @@ module Kamelopard
1120
1188
  # StyleMap manages pairs. The first entry in each pair is a string key, the
1121
1189
  # second is either a Style or a styleUrl. It will be assumed to be the
1122
1190
  # latter if its kind_of? method doesn't claim it's a Style object
1123
- def initialize(pairs = {})
1124
- super()
1191
+ def initialize(pairs = {}, options = {})
1192
+ super options
1125
1193
  @pairs = pairs
1126
1194
  end
1127
1195
 
@@ -1131,23 +1199,23 @@ module Kamelopard
1131
1199
  end
1132
1200
 
1133
1201
  def to_kml(elem = nil)
1134
- t = REXML::Element.new 'StyleMap'
1202
+ t = XML::Node.new 'StyleMap'
1135
1203
  super t
1136
1204
  @pairs.each do |k, v|
1137
- p = REXML::Element.new 'Pair'
1138
- key = REXML::Element.new 'key'
1139
- key.text = k
1140
- p.elements << key
1205
+ p = XML::Node.new 'Pair'
1206
+ key = XML::Node.new 'key'
1207
+ key << k.to_s
1208
+ p. << key
1141
1209
  if v.kind_of? Style then
1142
1210
  v.to_kml(p)
1143
1211
  else
1144
- s = REXML::Element.new 'styleUrl'
1145
- s.text = v
1146
- p.elements << s
1212
+ s = XML::Node.new 'styleUrl'
1213
+ s << v.to_s
1214
+ p << s
1147
1215
  end
1148
- t.elements << p
1216
+ t << p
1149
1217
  end
1150
- elem.elements << t unless elem.nil?
1218
+ elem << t unless elem.nil?
1151
1219
  t
1152
1220
  end
1153
1221
  end
@@ -1156,25 +1224,22 @@ module Kamelopard
1156
1224
  # descendant of Geometry
1157
1225
  class Placemark < Feature
1158
1226
  attr_accessor :name, :geometry
1159
- def initialize(name = nil, geo = nil)
1160
- super(name)
1161
- if geo.respond_to? '[]' then
1162
- @geometry = geo
1163
- else
1164
- @geometry = [ geo ]
1165
- end
1227
+
1228
+ def initialize(name = nil, options = {})
1229
+ super
1230
+ @name = name unless name.nil?
1166
1231
  end
1167
-
1232
+
1168
1233
  def to_kml(elem = nil)
1169
- k = REXML::Element.new 'Placemark'
1234
+ k = XML::Node.new 'Placemark'
1170
1235
  super k
1171
- @geometry.each do |i| i.to_kml(k) unless i.nil? end
1236
+ @geometry.to_kml(k) unless @geometry.nil?
1172
1237
  elem << k unless elem.nil?
1173
1238
  k
1174
1239
  end
1175
1240
 
1176
1241
  def to_s
1177
- "Placemark id #{ @id } named #{ @name }"
1242
+ "Placemark id #{ @kml_id } named #{ @name }"
1178
1243
  end
1179
1244
 
1180
1245
  def longitude
@@ -1194,8 +1259,8 @@ module Kamelopard
1194
1259
  end
1195
1260
 
1196
1261
  def point
1197
- if @geometry[0].kind_of? Point then
1198
- @geometry[0]
1262
+ if @geometry.kind_of? Point then
1263
+ @geometry
1199
1264
  else
1200
1265
  raise "This placemark uses a non-point geometry, but the operation you're trying requires a point object"
1201
1266
  end
@@ -1205,7 +1270,7 @@ module Kamelopard
1205
1270
  # Abstract class corresponding to KML's gx:TourPrimitive object. Tours are made up
1206
1271
  # of descendants of these.
1207
1272
  class TourPrimitive < Object
1208
- def initialize
1273
+ def initialize(options = {})
1209
1274
  Document.instance.tour << self
1210
1275
  super
1211
1276
  end
@@ -1216,22 +1281,29 @@ module Kamelopard
1216
1281
  class FlyTo < TourPrimitive
1217
1282
  attr_accessor :duration, :mode, :view
1218
1283
 
1219
- def initialize(view = nil, range = nil, duration = 0, mode = :bounce)
1220
- @duration = duration
1221
- @mode = mode
1284
+ def initialize(view = nil, options = {})
1285
+ @duration = 0
1286
+ @mode = :bounce
1287
+ super options
1288
+ self.view= view unless view.nil?
1289
+ end
1290
+
1291
+ def view=(view)
1222
1292
  if view.kind_of? AbstractView then
1223
1293
  @view = view
1224
1294
  else
1225
- @view = LookAt.new(view)
1295
+ @view = LookAt.new view
1226
1296
  end
1297
+ end
1298
+
1299
+ def range=(range)
1227
1300
  if view.respond_to? 'range' and not range.nil? then
1228
1301
  @view.range = range
1229
1302
  end
1230
- super()
1231
1303
  end
1232
1304
 
1233
1305
  def to_kml(elem = nil)
1234
- k = REXML::Element.new 'gx:FlyTo'
1306
+ k = XML::Node.new 'gx:FlyTo'
1235
1307
  super k
1236
1308
  Kamelopard.kml_array(k, [
1237
1309
  [ @duration, 'gx:duration' ],
@@ -1249,43 +1321,60 @@ module Kamelopard
1249
1321
  class AnimatedUpdate < TourPrimitive
1250
1322
  # XXX For now, the user has to specify the change / create / delete elements in
1251
1323
  # the <Update> manually, rather than creating objects.
1252
- attr_accessor :target, :delayedStart, :updates, :duration
1324
+ attr_accessor :target, :delayedStart, :duration
1325
+ attr_reader :updates
1253
1326
 
1254
1327
  # The updates argument is an array of strings containing <Change> elements
1255
- def initialize(updates = [], duration = 0, target = '', delayedstart = nil)
1256
- super()
1257
- begin
1258
- raise "incorrect object type" unless @target.kind_of? Object
1259
- @target = target.id
1260
- rescue RuntimeError
1328
+ def initialize(updates, options = {})
1329
+ #duration = 0, target = '', delayedstart = nil)
1330
+ @updates = []
1331
+ super options
1332
+ @updates = updates unless updates.nil? or updates.size == 0
1333
+ end
1334
+
1335
+ def target=(target)
1336
+ if target.kind_of? Object then
1337
+ @target = target.kml_id
1338
+ else
1261
1339
  @target = target
1262
1340
  end
1263
- @updates = updates
1264
- @duration = duration
1265
- @delayedStart = delayedstart
1341
+ end
1342
+
1343
+ def updates=(a)
1344
+ updates.each do |u| self.<<(u) end
1266
1345
  end
1267
1346
 
1268
1347
  # Adds another update string, presumably containing a <Change> element
1269
1348
  def <<(a)
1270
- @updates << REXML::Document.new(a).root
1349
+ @updates << a
1271
1350
  end
1272
1351
 
1273
1352
  def to_kml(elem = nil)
1274
- k = REXML::Element.new 'gx:AnimatedUpdate'
1353
+ k = XML::Node.new 'gx:AnimatedUpdate'
1275
1354
  super(k)
1276
- d = REXML::Element.new 'gx:duration'
1277
- d.text = @duration
1355
+ d = XML::Node.new 'gx:duration'
1356
+ d << @duration.to_s
1278
1357
  k << d
1279
1358
  if not @delayedStart.nil? then
1280
- d = REXML::Element.new 'gx:delayedStart'
1281
- d.text = @delayedStart
1359
+ d = XML::Node.new 'gx:delayedStart'
1360
+ d << @delayedStart.to_s
1282
1361
  k << d
1283
1362
  end
1284
- d = REXML::Element.new 'Update'
1285
- q = REXML::Element.new 'targetHref'
1286
- q.text = @target
1363
+ d = XML::Node.new 'Update'
1364
+ q = XML::Node.new 'targetHref'
1365
+ q << @target.to_s
1287
1366
  d << q
1288
- @updates.each do |i| d << i end
1367
+ @updates.each do |i|
1368
+ if i.is_a? XML::Node then
1369
+ d << i
1370
+ else
1371
+ parser = reader = XML::Parser.string(i)
1372
+ doc = parser.parse
1373
+ node = doc.child
1374
+ n = node.copy true
1375
+ d << n
1376
+ end
1377
+ end
1289
1378
  k << d
1290
1379
  elem << k unless elem.nil?
1291
1380
  k
@@ -1294,15 +1383,12 @@ module Kamelopard
1294
1383
 
1295
1384
  # Corresponds to a KML gx:TourControl object
1296
1385
  class TourControl < TourPrimitive
1297
- def initialize
1298
- super
1299
- end
1300
1386
 
1301
1387
  def to_kml(elem = nil)
1302
- k = REXML::Element.new 'gx:TourControl'
1388
+ k = XML::Node.new 'gx:TourControl'
1303
1389
  super(k)
1304
- q = REXML::Element.new 'gx:playMode'
1305
- q.text = 'pause'
1390
+ q = XML::Node.new 'gx:playMode'
1391
+ q << 'pause'
1306
1392
  k << q
1307
1393
  elem << k unless elem.nil?
1308
1394
  k
@@ -1312,16 +1398,16 @@ module Kamelopard
1312
1398
  # Corresponds to a KML gx:Wait object
1313
1399
  class Wait < TourPrimitive
1314
1400
  attr_accessor :duration
1315
- def initialize(duration = 0)
1316
- super()
1401
+ def initialize(duration = 0, options = {})
1402
+ super options
1317
1403
  @duration = duration
1318
1404
  end
1319
1405
 
1320
1406
  def to_kml(elem = nil)
1321
- k = REXML::Element.new 'gx:Wait'
1407
+ k = XML::Node.new 'gx:Wait'
1322
1408
  super k
1323
- d = REXML::Element.new 'gx:duration'
1324
- d.text = @duration
1409
+ d = XML::Node.new 'gx:duration'
1410
+ d << @duration.to_s
1325
1411
  k << d
1326
1412
  elem << k unless elem.nil?
1327
1413
  k
@@ -1338,14 +1424,14 @@ module Kamelopard
1338
1424
  end
1339
1425
 
1340
1426
  def to_kml(elem = nil)
1341
- k = REXML::Element.new 'gx:SoundCue'
1427
+ k = XML::Node.new 'gx:SoundCue'
1342
1428
  super k
1343
- d = REXML::Element.new 'href'
1344
- d.text = @href
1429
+ d = XML::Node.new 'href'
1430
+ d << @href.to_s
1345
1431
  k << d
1346
1432
  if not @delayedStart.nil? then
1347
- d = REXML::Element.new 'gx:delayedStart'
1348
- d.text = @delayedStart
1433
+ d = XML::Node.new 'gx:delayedStart'
1434
+ d << @delayedStart.to_s
1349
1435
  k << d
1350
1436
  end
1351
1437
  elem << k unless elem.nil?
@@ -1371,13 +1457,13 @@ module Kamelopard
1371
1457
  end
1372
1458
 
1373
1459
  def to_kml(elem = nil)
1374
- k = REXML::Element.new 'gx:Tour'
1460
+ k = XML::Node.new 'gx:Tour'
1375
1461
  super k
1376
1462
  Kamelopard.kml_array(k, [
1377
1463
  [ @name, 'name' ],
1378
1464
  [ @description, 'description' ],
1379
1465
  ])
1380
- p = REXML::Element.new 'gx:Playlist'
1466
+ p = XML::Node.new 'gx:Playlist'
1381
1467
  @items.map do |a| a.to_kml p end
1382
1468
  k << p
1383
1469
  elem << k unless elem.nil?
@@ -1387,16 +1473,13 @@ module Kamelopard
1387
1473
 
1388
1474
  # Abstract class corresponding to the KML Overlay object
1389
1475
  class Overlay < Feature
1390
- attr_accessor :color, :drawOrder, :icon
1476
+ attr_accessor :color, :drawOrder
1391
1477
 
1392
- def initialize(icon, name = nil)
1393
- super(name)
1478
+ include Icon
1479
+
1480
+ def initialize(options = {})
1481
+ super nil, options
1394
1482
  Document.instance.folder << self
1395
- if icon.respond_to?('to_kml') then
1396
- @icon = icon
1397
- elsif not icon.nil?
1398
- @icon = Icon.new(icon.to_s)
1399
- end
1400
1483
  end
1401
1484
 
1402
1485
  def to_kml(elem)
@@ -1405,7 +1488,7 @@ module Kamelopard
1405
1488
  [ @color, 'color' ],
1406
1489
  [ @drawOrder, 'drawOrder' ],
1407
1490
  ])
1408
- @icon.to_kml(elem) unless @icon.nil?
1491
+ icon_to_kml(elem)
1409
1492
  elem
1410
1493
  end
1411
1494
  end
@@ -1413,25 +1496,17 @@ module Kamelopard
1413
1496
  # Corresponds to KML's ScreenOverlay object
1414
1497
  class ScreenOverlay < Overlay
1415
1498
  attr_accessor :overlayXY, :screenXY, :rotationXY, :size, :rotation
1416
- def initialize(icon, name = nil, size = nil, rotation = nil, overlayXY = nil, screenXY = nil, rotationXY = nil)
1417
- super(icon, name)
1418
- @overlayXY = overlayXY
1419
- @screenXY = screenXY
1420
- @rotationXY = rotationXY
1421
- @size = size
1422
- @rotation = rotation
1423
- end
1424
1499
 
1425
1500
  def to_kml(elem = nil)
1426
- k = REXML::Element.new 'ScreenOverlay'
1501
+ k = XML::Node.new 'ScreenOverlay'
1427
1502
  super k
1428
1503
  @overlayXY.to_kml('overlayXY', k) unless @overlayXY.nil?
1429
1504
  @screenXY.to_kml('screenXY', k) unless @screenXY.nil?
1430
1505
  @rotationXY.to_kml('rotationXY', k) unless @rotationXY.nil?
1431
1506
  @size.to_kml('size', k) unless @size.nil?
1432
1507
  if ! @rotation.nil? then
1433
- d = REXML::Element.new 'rotation'
1434
- d.text = @rotation
1508
+ d = XML::Node.new 'rotation'
1509
+ d << @rotation.to_s
1435
1510
  k << d
1436
1511
  end
1437
1512
  elem << k unless elem.nil?
@@ -1439,19 +1514,12 @@ module Kamelopard
1439
1514
  end
1440
1515
  end
1441
1516
 
1442
- # Supporting object for the PhotoOverlay class
1443
- class ViewVolume
1517
+ # Supporting module for the PhotoOverlay class
1518
+ module ViewVolume
1444
1519
  attr_accessor :leftFov, :rightFov, :bottomFov, :topFov, :near
1445
- def initialize(near, leftFov = -45, rightFov = 45, bottomFov = -45, topFov = 45)
1446
- @leftFov = leftFov
1447
- @rightFov = rightFov
1448
- @bottomFov = bottomFov
1449
- @topFov = topFov
1450
- @near = near
1451
- end
1452
1520
 
1453
- def to_kml(elem = nil)
1454
- p = REXML::Element.new 'ViewVolume'
1521
+ def viewVolume_to_kml(elem = nil)
1522
+ p = XML::Node.new 'ViewVolume'
1455
1523
  {
1456
1524
  :near => @near,
1457
1525
  :leftFov => @leftFov,
@@ -1459,8 +1527,9 @@ module Kamelopard
1459
1527
  :topFov => @topFov,
1460
1528
  :bottomFov => @bottomFov
1461
1529
  }.each do |k, v|
1462
- d = REXML::Element.new k.to_s
1463
- d.text = v
1530
+ d = XML::Node.new k.to_s
1531
+ v = 0 if v.nil?
1532
+ d << v.to_s
1464
1533
  p << d
1465
1534
  end
1466
1535
  elem << p unless elem.nil?
@@ -1468,27 +1537,22 @@ module Kamelopard
1468
1537
  end
1469
1538
  end
1470
1539
 
1471
- # Supporting object for the PhotoOverlay class
1472
- class ImagePyramid
1540
+ # Supporting module for the PhotoOverlay class
1541
+ module ImagePyramid
1473
1542
  attr_accessor :tileSize, :maxWidth, :maxHeight, :gridOrigin
1474
1543
 
1475
- def initialize(maxWidth, maxHeight, gridOrigin, tileSize = 256)
1476
- @tileSize = tileSize
1477
- @maxWidth = maxWidth
1478
- @maxHeight = maxHeight
1479
- @gridOrigin = gridOrigin
1480
- end
1481
-
1482
- def to_kml(elem = nil)
1483
- p = REXML::Element.new 'ImagePyramid'
1544
+ def imagePyramid_to_kml(elem = nil)
1545
+ @tileSize = 256 if @tileSize.nil?
1546
+ p = XML::Node.new 'ImagePyramid'
1484
1547
  {
1485
1548
  :tileSize => @tileSize,
1486
1549
  :maxWidth => @maxWidth,
1487
1550
  :maxHeight => @maxHeight,
1488
1551
  :gridOrigin => @gridOrigin
1489
1552
  }.each do |k, v|
1490
- d = REXML::Element.new k.to_s
1491
- d.text = v
1553
+ d = XML::Node.new k.to_s
1554
+ v = 0 if v.nil?
1555
+ d << v.to_s
1492
1556
  p << d
1493
1557
  end
1494
1558
  elem << p unless elem.nil?
@@ -1498,33 +1562,35 @@ module Kamelopard
1498
1562
 
1499
1563
  # Corresponds to KML's PhotoOverlay class
1500
1564
  class PhotoOverlay < Overlay
1501
- attr_accessor :rotation, :viewvolume, :imagepyramid, :point, :shape
1565
+ attr_accessor :rotation, :point, :shape
1502
1566
 
1503
- def initialize(icon, point, rotation = 0, viewvolume = nil, imagepyramid = nil, shape = :rectangle)
1504
- super(icon)
1567
+ include ViewVolume
1568
+ include ImagePyramid
1569
+
1570
+ def initialize(options = {})
1571
+ super
1572
+ end
1573
+
1574
+ def point=(point)
1505
1575
  if point.respond_to?('point')
1506
1576
  @point = point.point
1507
1577
  else
1508
1578
  @point = point
1509
1579
  end
1510
- @rotation = rotation
1511
- @viewVolume = viewvolume
1512
- @imagePyramid = imagepyramid
1513
- @shape = shape
1514
1580
  end
1515
1581
 
1516
1582
  def to_kml(elem = nil)
1517
- p = REXML::Element.new 'PhotoOverlay'
1583
+ p = XML::Node.new 'PhotoOverlay'
1518
1584
  super p
1519
- @viewVolume.to_kml p unless @viewVolume.nil?
1520
- @imagePyramid.to_kml p unless @imagePyramid.nil?
1521
- p << @point.to_kml(true)
1585
+ viewVolume_to_kml p
1586
+ imagePyramid_to_kml p
1587
+ p << @point.to_kml(nil, true)
1522
1588
  {
1523
1589
  :rotation => @rotation,
1524
1590
  :shape => @shape
1525
1591
  }.each do |k, v|
1526
- d = REXML::Element.new k.to_s
1527
- d.text = v
1592
+ d = XML::Node.new k.to_s
1593
+ d << v.to_s
1528
1594
  p << d
1529
1595
  end
1530
1596
  elem << p unless elem.nil?
@@ -1566,28 +1632,28 @@ module Kamelopard
1566
1632
 
1567
1633
  def to_kml(elem = nil, alt = false)
1568
1634
  name = alt ? 'LatLonAltBox' : 'LatLonBox'
1569
- k = REXML::Element.new name
1635
+ k = XML::Node.new name
1570
1636
  [
1571
- ['north', @north],
1572
- ['south', @south],
1573
- ['east', @east],
1637
+ ['north', @north],
1638
+ ['south', @south],
1639
+ ['east', @east],
1574
1640
  ['west', @west],
1575
1641
  ['minAltitude', @minAltitude],
1576
1642
  ['maxAltitude', @maxAltitude]
1577
1643
  ].each do |a|
1578
1644
  if not a[1].nil? then
1579
- m = REXML::Element.new a[0]
1580
- m.text = a[1]
1581
- k.elements << m
1645
+ m = XML::Node.new a[0]
1646
+ m << a[1].to_s
1647
+ k << m
1582
1648
  end
1583
1649
  end
1584
1650
  if (not @minAltitude.nil? or not @maxAltitude.nil?) then
1585
1651
  Kamelopard.add_altitudeMode(@altitudeMode, k)
1586
1652
  end
1587
- m = REXML::Element.new 'rotation'
1588
- m.text = @rotation
1589
- k.elements << m
1590
- elem.elements << k unless elem.nil?
1653
+ m = XML::Node.new 'rotation'
1654
+ m = @rotation.to_s
1655
+ k << m
1656
+ elem << k unless elem.nil?
1591
1657
  k
1592
1658
  end
1593
1659
  end
@@ -1603,9 +1669,9 @@ module Kamelopard
1603
1669
  end
1604
1670
 
1605
1671
  def to_kml(elem = nil)
1606
- k = REXML::Element.new 'gx:LatLonQuad'
1607
- d = REXML::Element.new 'coordinates'
1608
- d.text = "#{ @lowerLeft.longitude },#{ @lowerLeft.latitude } #{ @lowerRight.longitude },#{ @lowerRight.latitude } #{ @upperRight.longitude },#{ @upperRight.latitude } #{ @upperLeft.longitude },#{ @upperLeft.latitude }"
1672
+ k = XML::Node.new 'gx:LatLonQuad'
1673
+ d = XML::Node.new 'coordinates'
1674
+ d << "#{ @lowerLeft.longitude },#{ @lowerLeft.latitude } #{ @lowerRight.longitude },#{ @lowerRight.latitude } #{ @upperRight.longitude },#{ @upperRight.latitude } #{ @upperLeft.longitude },#{ @upperLeft.latitude }"
1609
1675
  k << d
1610
1676
  elem << k unless elem.nil?
1611
1677
  k
@@ -1615,8 +1681,10 @@ module Kamelopard
1615
1681
  # Corresponds to KML's GroundOverlay object
1616
1682
  class GroundOverlay < Overlay
1617
1683
  attr_accessor :altitude, :altitudeMode, :latlonbox, :latlonquad
1618
- def initialize(icon, latlonbox = nil, latlonquad = nil, altitude = 0, altitudeMode = :clampToGround)
1619
- super(icon)
1684
+ def initialize(icon, options = {})
1685
+ @altitude = 0
1686
+ @altitudeMode = :clampToGround
1687
+ super options
1620
1688
  @latlonbox = latlonbox
1621
1689
  @latlonquad = latlonquad
1622
1690
  @altitude = altitude
@@ -1625,10 +1693,10 @@ module Kamelopard
1625
1693
 
1626
1694
  def to_kml(elem = nil)
1627
1695
  raise "Either latlonbox or latlonquad must be non-nil" if @latlonbox.nil? and @latlonquad.nil?
1628
- k = REXML::Element.new 'GroundOverlay'
1696
+ k = XML::Node.new 'GroundOverlay'
1629
1697
  super k
1630
- d = REXML::Element.new 'altitude'
1631
- d.text = @altitude
1698
+ d = XML::Node.new 'altitude'
1699
+ d << @altitude.to_s
1632
1700
  k << d
1633
1701
  Kamelopard.add_altitudeMode(@altitudeMode, k)
1634
1702
  @latlonbox.to_kml(k) unless @latlonbox.nil?
@@ -1649,20 +1717,20 @@ module Kamelopard
1649
1717
  end
1650
1718
 
1651
1719
  def to_kml(elem = nil)
1652
- k = REXML::Element.new 'Lod'
1653
- m = REXML::Element.new 'minLodPixels'
1654
- m.text = @minpixels
1655
- k.elements << m
1656
- m = REXML::Element.new 'maxLodPixels'
1657
- m.text = @maxpixels
1658
- k.elements << m
1659
- m = REXML::Element.new 'minFadeExtent'
1660
- m.text = @minfade
1661
- k.elements << m
1662
- m = REXML::Element.new 'maxFadeExtent'
1663
- m.text = @maxfade
1664
- k.elements << m
1665
- elem.elements << k unless elem.nil?
1720
+ k = XML::Node.new 'Lod'
1721
+ m = XML::Node.new 'minLodPixels'
1722
+ m << @minpixels.to_s
1723
+ k << m
1724
+ m = XML::Node.new 'maxLodPixels'
1725
+ m << @maxpixels.to_s
1726
+ k << m
1727
+ m = XML::Node.new 'minFadeExtent'
1728
+ m << @minfade.to_s
1729
+ k << m
1730
+ m = XML::Node.new 'maxFadeExtent'
1731
+ m << @maxfade.to_s
1732
+ k << m
1733
+ elem << k unless elem.nil?
1666
1734
  k
1667
1735
  end
1668
1736
  end
@@ -1671,18 +1739,16 @@ module Kamelopard
1671
1739
  class Region < Object
1672
1740
  attr_accessor :latlonaltbox, :lod
1673
1741
 
1674
- def initialize(latlonaltbox, lod)
1675
- super()
1676
- @latlonaltbox = latlonaltbox
1677
- @lod = lod
1742
+ def initialize(options = {})
1743
+ super
1678
1744
  end
1679
1745
 
1680
1746
  def to_kml(elem = nil)
1681
- k = REXML::Element.new 'Region'
1682
- super(k)
1747
+ k = XML::Node.new 'Region'
1748
+ super k
1683
1749
  @latlonaltbox.to_kml(k, true) unless @latlonaltbox.nil?
1684
1750
  @lod.to_kml(k) unless @lod.nil?
1685
- elem.elements << k unless elem.nil?
1751
+ elem << k unless elem.nil?
1686
1752
  k
1687
1753
  end
1688
1754
  end
@@ -1703,14 +1769,14 @@ module Kamelopard
1703
1769
  end
1704
1770
 
1705
1771
  def to_kml(elem = nil)
1706
- x = REXML::Element.new 'Orientation'
1772
+ x = XML::Node.new 'Orientation'
1707
1773
  {
1708
1774
  :heading => @heading,
1709
1775
  :tilt => @tilt,
1710
1776
  :roll => @roll
1711
1777
  }.each do |k, v|
1712
- d = REXML::Element.new k.to_s
1713
- d.text = v
1778
+ d = XML::Node.new k.to_s
1779
+ d << v.to_s
1714
1780
  x << d
1715
1781
  end
1716
1782
  elem << x unless elem.nil?
@@ -1728,14 +1794,14 @@ module Kamelopard
1728
1794
  end
1729
1795
 
1730
1796
  def to_kml(elem = nil)
1731
- x = REXML::Element.new 'Scale'
1797
+ x = XML::Node.new 'Scale'
1732
1798
  {
1733
1799
  :x => @x,
1734
1800
  :y => @y,
1735
1801
  :z => @z
1736
1802
  }.each do |k, v|
1737
- d = REXML::Element.new k.to_s
1738
- d.text = v
1803
+ d = XML::Node.new k.to_s
1804
+ d << v.to_s
1739
1805
  x << d
1740
1806
  end
1741
1807
  elem << x unless elem.nil?
@@ -1752,13 +1818,13 @@ module Kamelopard
1752
1818
  end
1753
1819
 
1754
1820
  def to_kml(elem = nil)
1755
- x = REXML::Element.new 'Alias'
1821
+ x = XML::Node.new 'Alias'
1756
1822
  {
1757
1823
  :targetHref => @targetHref,
1758
1824
  :sourceHref => @sourceHref,
1759
1825
  }.each do |k, v|
1760
- d = REXML::Element.new k.to_s
1761
- d.text = v
1826
+ d = XML::Node.new k.to_s
1827
+ d << v.to_s
1762
1828
  x << d
1763
1829
  end
1764
1830
  elem << x unless elem.nil?
@@ -1781,7 +1847,7 @@ module Kamelopard
1781
1847
  end
1782
1848
 
1783
1849
  def to_kml(elem = nil)
1784
- k = REXML::Element.new 'ResourceMap'
1850
+ k = XML::Node.new 'ResourceMap'
1785
1851
  @aliases.each do |a| k << a.to_kml(k) end
1786
1852
  elem << k unless elem.nil?
1787
1853
  k
@@ -1791,23 +1857,22 @@ module Kamelopard
1791
1857
  # Corresponds to KML's Link object
1792
1858
  class Link < Object
1793
1859
  attr_accessor :href, :refreshMode, :refreshInterval, :viewRefreshMode, :viewBoundScale, :viewFormat, :httpQuery
1794
- def initialize(href = '', refreshMode = :onChange, viewRefreshMode = :never)
1795
- super()
1796
- @href = href
1797
- @refreshMode = refreshMode
1798
- @viewRefreshMode = viewRefreshMode
1860
+
1861
+ def initialize(href = '', options = {})
1862
+ super options
1863
+ @href = href unless href == ''
1799
1864
  end
1800
1865
 
1801
1866
  def to_kml(elem = nil)
1802
- x = REXML::Element.new 'Link'
1867
+ x = XML::Node.new 'Link'
1803
1868
  super x
1804
1869
  {
1805
1870
  :href => @href,
1806
1871
  :refreshMode => @refreshMode,
1807
1872
  :viewRefreshMode => @viewRefreshMode,
1808
1873
  }.each do |k, v|
1809
- d = REXML::Element.new k.to_s
1810
- d.text = v
1874
+ d = XML::Node.new k.to_s
1875
+ d << v.to_s
1811
1876
  x << d
1812
1877
  end
1813
1878
  Kamelopard.kml_array(x, [
@@ -1828,26 +1893,22 @@ module Kamelopard
1828
1893
  # location should be a Point, or some object that can behave like one,
1829
1894
  # including a Placemark. Model will get its Location and altitudeMode data
1830
1895
  # from this attribute
1831
- def initialize(link, location, orientation, scale, resourceMap)
1832
- super()
1833
- @link = link
1834
- @location = location
1835
- @orientation = orientation
1836
- @scale = scale
1837
- @resourceMap = resourceMap
1896
+ def initialize(options = {})
1897
+ #link, location, orientation, scale, resourceMap)
1898
+ super
1838
1899
  end
1839
1900
 
1840
1901
  def to_kml(elem = nil)
1841
- x = REXML::Element.new 'Model'
1902
+ x = XML::Node.new 'Model'
1842
1903
  super x
1843
- loc = REXML::Element.new 'Location'
1904
+ loc = XML::Node.new 'Location'
1844
1905
  {
1845
1906
  :longitude => @location.longitude,
1846
1907
  :latitude => @location.latitude,
1847
1908
  :altitude => @location.altitude,
1848
1909
  }.each do |k, v|
1849
- d = REXML::Element.new k.to_s
1850
- d.text = v
1910
+ d = XML::Node.new k.to_s
1911
+ d << v.to_s
1851
1912
  loc << d
1852
1913
  end
1853
1914
  x << loc
@@ -1861,5 +1922,122 @@ module Kamelopard
1861
1922
  end
1862
1923
  end
1863
1924
 
1925
+ # Corresponds to the KML Polygon class
1926
+ class Polygon < Geometry
1927
+ # NB! No support for tessellate, because Google Earth doesn't support it, it seems
1928
+ attr_accessor :outer, :inner, :altitudeMode, :extrude
1929
+
1930
+ def initialize(outer, options = {})
1931
+ #extrude = 0, altitudeMode = :clampToGround)
1932
+ @extrude = 0
1933
+ @altitudeMode = :clampToGround
1934
+ @inner = []
1935
+ super options
1936
+ end
1937
+
1938
+ def inner=(a)
1939
+ if a.kind_of? Array then
1940
+ @inner = a
1941
+ else
1942
+ @inner = [ a ]
1943
+ end
1944
+ end
1945
+
1946
+ def <<(a)
1947
+ @inner << a
1948
+ end
1949
+
1950
+ def to_kml(elem = nil)
1951
+ k = XML::Node.new 'Polygon'
1952
+ super k
1953
+ e = XML::Node.new 'extrude'
1954
+ e << @extrude.to_s
1955
+ k << e
1956
+ Kamelopard.add_altitudeMode @altitudeMode, k
1957
+ e = XML::Node.new('outerBoundaryIs')
1958
+ e << @outer.to_kml
1959
+ k << e
1960
+ @inner.each do |i|
1961
+ e = XML::Node.new('innerBoundaryIs')
1962
+ e << i.to_kml
1963
+ k << e
1964
+ end
1965
+ elem << k unless elem.nil?
1966
+ k
1967
+ end
1968
+ end
1969
+
1970
+ class MultiGeometry < Geometry
1971
+ attr_accessor :geometries
1972
+
1973
+ def initialize(a = nil, options = {})
1974
+ @geometries = []
1975
+ @geometries << a unless a.nil?
1976
+ super options
1977
+ end
1978
+
1979
+ def <<(a)
1980
+ @geometries << a
1981
+ end
1982
+
1983
+ def to_kml(elem = nil)
1984
+ e = XML::Node.new 'MultiGeometry'
1985
+ @geometries.each do |g|
1986
+ g.to_kml e
1987
+ end
1988
+ elem << e unless elem.nil?
1989
+ e
1990
+ end
1991
+ end
1992
+
1993
+ class NetworkLink < Feature
1994
+ attr_accessor :refreshVisibility, :flyToView, :link
1995
+
1996
+ def initialize(href = '', options = {})
1997
+ @refreshMode = :onChange
1998
+ @viewRefreshMode = :never
1999
+ super options
2000
+ @link = Link.new(href, refreshMode, viewRefreshMode)
2001
+ @refreshVisibility = 0
2002
+ @flyToView = 0
2003
+ end
2004
+
2005
+ def refreshMode
2006
+ link.refreshMode
2007
+ end
2008
+
2009
+ def viewRefreshMode
2010
+ link.viewRefreshMode
2011
+ end
2012
+
2013
+ def href
2014
+ link.href
2015
+ end
2016
+
2017
+ def refreshMode=(a)
2018
+ link.refreshMode = a
2019
+ end
2020
+
2021
+ def viewRefreshMode=(a)
2022
+ link.viewRefreshMode = a
2023
+ end
2024
+
2025
+ def href=(a)
2026
+ link.href = a
2027
+ end
2028
+
2029
+ def to_kml(elem = nil)
2030
+ e = XML::Node.new 'NetworkLink'
2031
+ super e
2032
+ @link.to_kml e
2033
+ Kamelopard.kml_array(e, [
2034
+ [@flyToView, 'flyToView'],
2035
+ [@refreshVisibility, 'refreshVisibility']
2036
+ ])
2037
+ elem << e unless elem.nil?
2038
+ e
2039
+ end
2040
+ end
2041
+
1864
2042
  end
1865
2043
  # End of Kamelopard module