kamelopard 0.0.4 → 0.0.5

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.
@@ -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