kamelopard 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
data/spec/test.rb ADDED
@@ -0,0 +1,2999 @@
1
+ # vim:ts=4:sw=4:et:smartindent:nowrap
2
+
3
+ $LOAD_PATH << './lib'
4
+ require 'kamelopard'
5
+ require "xml"
6
+ require 'tempfile'
7
+
8
+ include Kamelopard
9
+ include Kamelopard::Functions
10
+
11
+ Kamelopard.set_logger lambda { |lev, mod, msg|
12
+ STDERR.puts "#{lev} #{mod}: #{msg}"
13
+ }
14
+
15
+ # Namespace array for find_first
16
+ NS = [
17
+ "xmlns:http://www.opengis.net/kml/2.2",
18
+ "gx:http://www.google.com/kml/ext/2.2",
19
+ "kml:http://www.opengis.net/kml/2.2",
20
+ "atom:http://www.w3.org/2005/Atom"
21
+ ]
22
+
23
+ # Printing debug information.
24
+ def put_info(str)
25
+ puts
26
+ puts "="*60
27
+ puts str
28
+ puts "*"*60
29
+ end
30
+
31
+ #
32
+ # Returns the first node found in given doc using given xpath.
33
+ #
34
+ #
35
+ def find_first_kml(doc, xpath)
36
+ doc.find_first xpath, "kml:http://www.opengis.net/kml/2.2"
37
+ end
38
+
39
+
40
+ #
41
+ # Returns the first node found among children with given name.
42
+ #
43
+ #
44
+ def get_child(node, name)
45
+ a = nil
46
+ node.children.each { |child|
47
+ if child.name == name
48
+ a = child
49
+ break
50
+ end
51
+ }
52
+ return a
53
+ end
54
+
55
+ #
56
+ # Returns the content of the first node found among children with given name.
57
+ #
58
+ #
59
+ def get_child_content(node, name)
60
+ n = node.children.detect{ |child| child.name == name}
61
+ n.content unless n.nil?
62
+ end
63
+
64
+ #
65
+ # Returns the first child with given name.
66
+ #
67
+ # On the object param there used to_kml method for getting the kml.
68
+ #
69
+ def get_obj_child(object, name)
70
+ k = object.to_kml
71
+ get_child(k, name)
72
+ end
73
+
74
+ #
75
+ # Returns the content of the first child with given name.
76
+ #
77
+ # On the object param there used to_kml method for getting the kml.
78
+ #
79
+ def get_obj_child_content(object, name)
80
+ k = object.to_kml
81
+ get_child_content(k, name)
82
+ end
83
+
84
+ #
85
+ # Builds proper kml from given node. It surrounds kml from given node with kml tag.
86
+ # This must be done for using xpath with libxml. If you want to use xpath, then the
87
+ # node need to belong to a proper libxml document, so we need a proper xml.
88
+ #
89
+ def build_doc_from_node(node)
90
+ kml =<<DOCFROMENODE
91
+ <kml xmlns="http://www.opengis.net/kml/2.2"
92
+ xmlns:gx="http://www.google.com/kml/ext/2.2"
93
+ xmlns:kml="http://www.opengis.net/kml/2.2"
94
+ xmlns:atom="http://www.w3.org/2005/Atom"
95
+ xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
96
+ #{node.to_kml.to_s}
97
+ </kml>
98
+ DOCFROMENODE
99
+ doc = XML::Document.string(kml)
100
+ end
101
+
102
+
103
+ def test_lat_lon_quad(d, n)
104
+ get_child_content(d, 'coordinates').should == "#{n},#{n} #{n},#{n} #{n},#{n} #{n},#{n}"
105
+ end
106
+
107
+ def test_lat_lon_box(l, latlon)
108
+ get_child_content(l, 'north').should == latlon.north.to_s
109
+ get_child_content(l, 'south').should == latlon.south.to_s
110
+ get_child_content(l, 'east').should == latlon.east.to_s
111
+ get_child_content(l, 'west').should == latlon.west.to_s
112
+ end
113
+
114
+ def test_lod(d, lodval)
115
+ %w[ minLodPixels maxLodPixels minFadeExtent maxFadeExtent ].each do |f|
116
+ get_child_content(d, "#{f}").to_i.should == lodval
117
+ end
118
+ end
119
+
120
+ def check_kml_values(o, values)
121
+ values.each do |k, v|
122
+ o.method("#{k}=").call(v)
123
+ doc = build_doc_from_node o
124
+ found = find_first_kml doc, "//kml:#{k}"
125
+ found.should_not be_nil
126
+ found.content.should == v.to_s
127
+ # get_obj_child_content(o, k).should == v.to_s
128
+ end
129
+ end
130
+
131
+ def fields_exist(o, fields)
132
+ fields.each do |f|
133
+ o.should respond_to(f.to_sym)
134
+ o.should respond_to("#{f}=".to_sym)
135
+ end
136
+ end
137
+
138
+ def match_view_vol(x, e)
139
+ %w[ near rightFov topFov ].each do |a|
140
+ get_child_content(x, a).to_i.should == e
141
+ end
142
+ %w[ leftFov bottomFov ].each do |a|
143
+ get_child_content(x, a).to_i.should == -e
144
+ end
145
+ end
146
+
147
+ def match_image_pyramid(x, e)
148
+ %w[ tileSize maxWidth maxHeight gridOrigin ].each do |a|
149
+ get_child_content(x, a).to_i.should == e
150
+ end
151
+ end
152
+
153
+ def validate_abstractview(k, type, point, heading, tilt, roll, range, mode)
154
+ [
155
+ [ k.name != type, "Wrong type #{ k.name }" ],
156
+ [ get_child_content(k, 'longitude').to_f != point.longitude, 'Wrong longitude' ],
157
+ [ get_child_content(k, 'longitude').to_f != point.longitude, 'Wrong longitude' ],
158
+ [ get_child_content(k, 'latitude').to_f != point.latitude, 'Wrong latitude' ],
159
+ [ get_child_content(k, 'altitude').to_f != point.altitude, 'Wrong altitude' ],
160
+ [ get_child_content(k, 'heading').to_f != heading, 'Wrong heading' ],
161
+ [ get_child_content(k, 'tilt').to_f != tilt, 'Wrong tilt' ],
162
+ [ type == 'Kamelopard::LookAt' && get_child_content(k, 'range').to_f != range, 'Wrong range' ],
163
+ [ type == 'Kamelopard::Camera' && get_child_content(k, 'roll').to_f != roll, 'Wrong roll' ],
164
+ [ mode !~ /SeaFloor/ && get_child_content(k, 'altitudeMode') != mode.to_s, 'Wrong altitude mode' ],
165
+ [ mode =~ /SeaFloor/ && get_child_content(k, 'gx:altitudeMode') != mode.to_s, 'Wrong gx:altitudeMode' ]
166
+ ].each do |a|
167
+ return [false, a[1]] if a[0]
168
+ end
169
+ end
170
+
171
+ def get_test_substyles()
172
+ i = Kamelopard::IconStyle.new({ :href => 'icon' })
173
+ la = Kamelopard::LabelStyle.new
174
+ lin = Kamelopard::LineStyle.new
175
+ p = Kamelopard::PolyStyle.new
176
+ b = Kamelopard::BalloonStyle.new({ :text => 'balloon' })
177
+ lis = Kamelopard::ListStyle.new
178
+ [ i, la, lin, p, b, lis ]
179
+ end
180
+
181
+ def get_test_styles()
182
+ i, la, lin, p, b, lis = get_test_substyles()
183
+
184
+ si = Kamelopard::Style.new({ :icon => i })
185
+ sl = Kamelopard::Style.new({
186
+ :icon => i,
187
+ :label => la,
188
+ :line => lin,
189
+ :poly => p,
190
+ :balloon => b,
191
+ :list => lis
192
+ })
193
+ sm = Kamelopard::StyleMap.new( { :icon => si, :list => sl } )
194
+
195
+ si.kml_id = 'icon'
196
+ sl.kml_id = 'list'
197
+ sm.kml_id = 'map'
198
+
199
+ [ si, sl, sm ]
200
+ end
201
+
202
+ def check_time_primitive(set_var_lambda, get_kml_lambda, xpath)
203
+ b = '2011-01-01'
204
+ e = '2011-02-01'
205
+ w = '2011-01-01'
206
+ tn = Kamelopard::TimeSpan.new b, e
207
+ tm = Kamelopard::TimeStamp.new w
208
+
209
+ set_var_lambda.call(tn)
210
+ d = get_kml_lambda.call
211
+
212
+ t = get_child d, 'TimeSpan'
213
+ get_child_content(t, 'begin').should == b
214
+ get_child_content(t, 'end').should == e
215
+
216
+ set_var_lambda.call(tm)
217
+ d = get_kml_lambda.call
218
+ t = get_child d, 'TimeStamp'
219
+ get_child_content(t, 'when').should == w
220
+ end
221
+
222
+ def get_kml_header
223
+ <<-header
224
+ <?xml version="1.0" encoding="UTF-8"?>
225
+ <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
226
+ <Document>
227
+ header
228
+ end
229
+
230
+ shared_examples_for 'field_producer' do
231
+ it 'has the right attributes' do
232
+ fields_exist @o, @fields
233
+ end
234
+ end
235
+
236
+ shared_examples_for 'Kamelopard::Object' do
237
+ it 'descends from Kamelopard::Object' do
238
+ @o.kind_of?(Kamelopard::Object).should == true
239
+ end
240
+
241
+ it 'has an id' do
242
+ @o.kml_id.should_not be_nil
243
+ end
244
+
245
+ it 'allows a comment' do
246
+ @o.should respond_to(:comment)
247
+ @o.should respond_to(:comment=)
248
+ end
249
+
250
+ it 'should put its comment in the KML' do
251
+ @o.comment = 'Look for this string'
252
+ k = @o.to_kml
253
+ k.to_s.should =~ /Look for this string/
254
+ end
255
+
256
+ it 'should HTML escape comments' do
257
+ @o.comment = 'Look for << this string'
258
+ k = @o.to_kml
259
+ k.to_s.should =~ /Look for &lt;&lt; this string/
260
+ end
261
+
262
+ it 'responds to master_only' do
263
+ @o.should respond_to(:master_only)
264
+ @o.should respond_to(:master_only=)
265
+ @o.master_only = true
266
+ @o.master_only = false
267
+ end
268
+
269
+ it 'returns KML in master mode only when master_only' do
270
+ @o.master_only = false
271
+ @o.to_kml.to_s.should_not == ''
272
+ @o.master_only = true
273
+ @o.master_only.should be_true
274
+ @o.to_kml.to_s.should == ''
275
+ get_document.master_mode = true
276
+ get_document.master_mode.should be_true
277
+ @o.to_kml.to_s.should_not == ''
278
+ get_document.master_mode = false
279
+ @o.to_kml.to_s.should == ''
280
+ @o.master_only = false
281
+ end
282
+
283
+ it 'appends itself to arbitrary XML nodes correctly' do
284
+ # These classes behave differently when XML::Nodes are passed to their to_kml methods
285
+ skip = %w{Document Feature StyleSelector ColorStyle}
286
+
287
+ if ! skip.include?(@o.class.name.gsub(/Kamelopard::/, ''))
288
+ x = XML::Node.new 'random'
289
+ count = x.children.size
290
+ @o.to_kml(x)
291
+ x.children.size.should == count + 1
292
+ end
293
+
294
+ end
295
+
296
+ it 'creates valid Change objects' do
297
+ # Objects can set @attr_name and @new_value
298
+ if (! @attr_name.nil? and ! @new_value.nil?) then
299
+ c = @o.change(@attr_name, @new_value)
300
+ c.should be_a_kind_of(XML::Node)
301
+ c.name.should == 'Change'
302
+ c.first.should_not be_nil
303
+ c.first.name.should == @o.class.name.gsub(/^Kamelopard::/, '')
304
+ c.first.attributes[:targetId].should == @o.kml_id
305
+ c.first.first.name.should == @attr_name.to_s
306
+ c.first.first.first.text?.should be_true
307
+ c.first.first.first.to_s.should == @new_value.to_s
308
+ # ... or they can set @skip_change to avoid this test
309
+ elsif (! @skip_change.nil? and @skip_change) then
310
+ # Nothing happens here
311
+ # ... or they'll get a FAIL
312
+ else
313
+ fail "#{@o.class.name} needs to set @skip_change, or @attr_name and @new_value"
314
+ end
315
+ end
316
+ end
317
+
318
+ shared_examples_for 'altitudeMode' do
319
+ it 'uses the right altitudeMode element' do
320
+ [:absolute, :clampToGround, :relativeToGround].each do |m|
321
+ @o.altitudeMode = m
322
+ k = @o.to_kml
323
+ get_child_content(k, "altitudeMode").should == m.to_s
324
+ end
325
+
326
+ [:clampToSeaFloor, :relativeToSeaFloor].each do |m|
327
+ @o.altitudeMode = m
328
+ k = @o.to_kml
329
+ get_child_content(k, "gx:altitudeMode").should == m.to_s
330
+ end
331
+ end
332
+ end
333
+
334
+ shared_examples_for 'KML_includes_id' do
335
+ it 'should include the object ID in the KML' do
336
+ d = @o.to_kml
337
+ d.attributes['id'].should_not be_nil
338
+ end
339
+ end
340
+
341
+ shared_examples_for 'KML_producer' do
342
+ it 'should have a to_kml function' do
343
+ @o.should respond_to(:to_kml)
344
+ end
345
+
346
+ it 'should create a XML document when to_xml is called' do
347
+ @o.to_kml.class.to_s.should == 'LibXML::XML::Node'
348
+ end
349
+ end
350
+
351
+ shared_examples_for 'Kamelopard::Geometry' do
352
+ it_should_behave_like 'Kamelopard::Object'
353
+
354
+ it 'descends from Kamelopard::Geometry' do
355
+ @o.kind_of?(Kamelopard::Geometry).should == true
356
+ end
357
+ end
358
+
359
+ shared_examples_for 'Kamelopard::AbstractView' do
360
+ it_should_behave_like 'Kamelopard::Object'
361
+ it_should_behave_like 'altitudeMode'
362
+ it_should_behave_like 'KML_includes_id'
363
+ it_should_behave_like 'KML_producer'
364
+
365
+ it 'descends from Kamelopard::AbstractView' do
366
+ @o.kind_of?(Kamelopard::AbstractView).should == true
367
+ end
368
+
369
+ it 'accepts viewer options and includes them in the KML' do
370
+ k = @o.to_kml
371
+ k.should_not =~ /ViewerOptions/
372
+
373
+ @o[:streetview] = true
374
+ @o[:sunlight] = true
375
+ @o[:historicalimagery] = true
376
+ doc = build_doc_from_node(@o)
377
+ v = doc.find("//ViewerOptions | //gx:ViewerOptions")
378
+ v.size.should_not == 0
379
+ v.find(".//gx:option[@name='sunlight',@enabled='true']").should_not == 0
380
+ v.find(".//gx:option[@name='streetview',@enabled='true']").should_not == 0
381
+ v.find(".//gx:option[@name='historicalimagery',@enabled='true']").should_not == 0
382
+
383
+ @o[:streetview] = false
384
+ @o[:sunlight] = false
385
+ @o[:historicalimagery] = false
386
+ doc = build_doc_from_node(@o)
387
+ v = doc.find("//ViewerOptions | //gx:ViewerOptions")
388
+ v.should_not == 0
389
+ v.find(".//gx:option[@name='sunlight',@enabled='true']").should_not == 0
390
+ v.find(".//gx:option[@name='streetview',@enabled='true']").should_not == 0
391
+ v.find(".//gx:option[@name='historicalimagery',@enabled='true']").should_not == 0
392
+ end
393
+
394
+ it 'whines when a strange option is provided' do
395
+ lambda { @o[:something_strange] = true }.should raise_exception
396
+ lambda { @o[:streetview] = true }.should_not raise_exception
397
+ lambda { @o[:sunlight] = true }.should_not raise_exception
398
+ lambda { @o[:historicalimagery] = true }.should_not raise_exception
399
+ end
400
+ end
401
+
402
+ shared_examples_for 'Kamelopard::CoordinateList' do
403
+ it 'returns coordinates in its KML' do
404
+ @o << [[1,2,3], [2,3,4], [3,4,5]]
405
+ k = @o.to_kml
406
+ e = get_child(k, 'coordinates')
407
+ #e = k.elements['//coordinates']
408
+ #e = k.root if e.nil?
409
+ e = k if e.nil?
410
+
411
+ e.should_not be_nil
412
+ e.name.should == 'coordinates'
413
+ e.content.should =~ /1.0,2.0,3.0/
414
+ e.content.should =~ /2.0,3.0,4.0/
415
+ e.content.should =~ /3.0,4.0,5.0/
416
+ end
417
+
418
+ describe 'when adding elements' do
419
+ it 'accepts arrays of arrays' do
420
+ @o << [[1,2,3], [2,3,4], [3,4,5]]
421
+ end
422
+
423
+ it 'accepts Kamelopard::Points' do
424
+ @o << Kamelopard::Point.new( 3, 2, 1 )
425
+ end
426
+
427
+ it 'accepts arrays of points' do
428
+ q = []
429
+ [[1,2,3], [2,3,4], [3,4,5]].each do |a|
430
+ q << Kamelopard::Point.new(a[0], a[1], a[2])
431
+ end
432
+ @o << q
433
+ end
434
+
435
+ it 'accepts another Kamelopard::CoordinateList' do
436
+ p = Kamelopard::LinearRing.new([[1,2,3], [2,3,4], [3,4,5]])
437
+ @o << p.coordinates
438
+ end
439
+
440
+ it 'complains when trying to add something weird' do
441
+ a = 42
442
+ lambda { @o << a }.should raise_error
443
+ end
444
+ end
445
+
446
+ end
447
+
448
+ shared_examples_for 'Kamelopard::Camera-like' do
449
+ it_should_behave_like 'Kamelopard::AbstractView'
450
+
451
+ it 'has the right attributes' do
452
+ fields = %w[ timestamp timespan viewerOptions longitude latitude altitude heading tilt roll altitudeMode ]
453
+ fields_exist @o, fields
454
+ end
455
+
456
+ it 'contains the right KML attributes' do
457
+ @o.heading = 12
458
+ @o.tilt = 12
459
+ get_obj_child(@o, 'longitude').should_not be_nil
460
+ get_obj_child(@o, 'latitude').should_not be_nil
461
+ get_obj_child(@o, 'altitude').should_not be_nil
462
+ get_obj_child(@o, 'heading').should_not be_nil
463
+ get_obj_child(@o, 'tilt').should_not be_nil
464
+ end
465
+
466
+ it 'creates a queries.txt entry' do
467
+ q = @o.to_queries_txt('name', 'planet')
468
+ q.should_not be_nil
469
+ q.should match /planet@name@flytoview=/
470
+ end
471
+ end
472
+
473
+ shared_examples_for "Kamelopard::TimePrimitive" do
474
+ it_should_behave_like 'Kamelopard::Object'
475
+ it_should_behave_like 'KML_producer'
476
+ it_should_behave_like 'KML_includes_id'
477
+
478
+ it 'descends from Kamelopard::TimePrimitive' do
479
+ @o.kind_of?(Kamelopard::TimePrimitive).should == true
480
+ end
481
+ end
482
+
483
+ shared_examples_for 'Kamelopard::Feature' do
484
+ def document_has_styles(d)
485
+ doc = build_doc_from_node d
486
+
487
+ si = find_first_kml doc, "//kml:Style[@id='icon']"
488
+ raise 'Could not find iconstyle' if si.nil?
489
+
490
+ sl = find_first_kml doc, "//kml:Style[@id='list']"
491
+ raise 'Could not find liststyle' if sl.nil?
492
+
493
+ sm = find_first_kml doc, "//kml:StyleMap[@id='map']"
494
+ raise 'Could not find stylemap' if sm.nil?
495
+
496
+ si = find_first_kml doc, "//kml:StyleMap/kml:Pair/kml:Style[@id='icon']"
497
+ raise 'Could not find iconstyle in stylemap' if si.nil?
498
+
499
+ sl = find_first_kml doc, '//kml:StyleMap/kml:Pair/kml:Style[@id="list"]'
500
+ raise 'Could not find liststyle in stylemap' if sl.nil?
501
+ true
502
+ end
503
+
504
+ it_should_behave_like 'Kamelopard::Object'
505
+ it_should_behave_like 'KML_includes_id'
506
+ it_should_behave_like 'KML_producer'
507
+
508
+ it 'descends from Kamelopard::Feature' do
509
+ @o.kind_of?(Kamelopard::Feature).should == true
510
+ end
511
+
512
+ it 'has the right attributes' do
513
+ fields = %w[
514
+ visibility open atom_author atom_link name
515
+ phoneNumber snippet_text maxLines description abstractView
516
+ timestamp timespan styleUrl styleSelector region metadata
517
+ extendedData styles
518
+ ]
519
+ fields_exist @o, fields
520
+
521
+ @o.should respond_to(:addressDetails)
522
+ end
523
+
524
+ it 'handles extended data correctly' do
525
+ ed = []
526
+ {
527
+ 'foo' => 'bar',
528
+ 'baz' => 'qux'
529
+ }.each do |k, v|
530
+ ed << Kamelopard::Data.new(k, v)
531
+ end
532
+ @o.extendedData = ed
533
+ end
534
+
535
+ it 'handles show and hide methods correctly' do
536
+ @o.hide
537
+ get_obj_child_content(@o, 'visibility').to_i.should == 0
538
+ @o.show
539
+ get_obj_child_content(@o, 'visibility').to_i.should == 1
540
+ end
541
+
542
+ it 'handles extended address stuff correctly' do
543
+ @o.addressDetails = 'These are some extended details'
544
+ (get_kml_string =~ /xmlns:xal/).should be_true
545
+ get_obj_child_content(@o, 'xal:AddressDetails').should == @o.addressDetails
546
+ end
547
+
548
+ it 'handles styles correctly' do
549
+ get_test_styles().each do |s|
550
+ @o.styleUrl = s
551
+ get_obj_child_content(@o, 'styleUrl').should == "##{s.kml_id}"
552
+ end
553
+ @o.styleUrl = '#random'
554
+ get_obj_child_content(@o, 'styleUrl').should == "#random"
555
+ end
556
+
557
+ it 'returns style KML correctly' do
558
+ get_test_styles().each do |s|
559
+ @o.styles << s
560
+ end
561
+
562
+ header = get_kml_header
563
+
564
+ document_has_styles(@o).should == true
565
+ end
566
+
567
+ it 'returns the right KML for simple fields' do
568
+ marker = 'Look for this string'
569
+ fields = %w( name address phoneNumber description styleUrl )
570
+ fields.each do |f|
571
+ p = Kamelopard::Feature.new
572
+ Kamelopard::DocumentHolder.instance.current_document.folder << p
573
+ p.instance_variable_set("@#{f}".to_sym, marker)
574
+ e = get_obj_child p, "#{f}"
575
+ e.should_not be_nil
576
+ e.content.should == marker
577
+ end
578
+ end
579
+
580
+ it 'returns the right KML for more complex fields' do
581
+ marker = 'Look for this string'
582
+ [
583
+ [ :@addressDetails, 'xal:AddressDetails' ],
584
+ [ :@metadata, 'Metadata' ],
585
+ [ :@atom_link, 'atom:link' ]
586
+ ].each do |a|
587
+ p = Kamelopard::Feature.new
588
+ p.instance_variable_set(a[0], marker)
589
+ e = get_child p.to_kml, a[1]
590
+ e.should_not be_nil
591
+ e.content.should == marker
592
+ end
593
+ end
594
+ #TODO: investigate why the field atom:author is missing
595
+
596
+ it 'correctly KML-ifies the atom:author field' do
597
+ o = Kamelopard::Feature.new
598
+ marker = 'Look for this text'
599
+ o.atom_author = marker
600
+ doc = build_doc_from_node o
601
+ doc.find_first('//atom:author/atom:name').content.should == marker
602
+ end
603
+
604
+ it 'returns the right KML for boolean fields' do
605
+ %w( visibility open ).each do |k|
606
+ [false, true].each do |v|
607
+ o = Kamelopard::Feature.new
608
+ o.instance_variable_set("@#{k}".to_sym, v)
609
+ get_obj_child_content(o, "#{k}").to_i.should == (v ? 1 : 0)
610
+ end
611
+ end
612
+ end
613
+
614
+ it 'correctly KML\'s the Kamelopard::Snippet' do
615
+ maxLines = 2
616
+ text = "This is my snippet\nIt's more than two lines long.\nNo, really."
617
+
618
+ @o.maxLines = maxLines
619
+ @o.snippet_text = text
620
+ doc = build_doc_from_node @o
621
+ s = doc.find_first("//kml:Snippet[@maxLines='#{maxLines}']", 'kml:http://www.opengis.net/kml/2.2')
622
+ s.should_not be_nil
623
+ s.content.should == text
624
+ end
625
+
626
+ describe 'correctly produces Kamelopard::Region KML' do
627
+ before(:all) do
628
+ @o = Kamelopard::Feature.new({ :name => 'my feature' })
629
+ @latlon = Kamelopard::LatLonBox.new( 1, -1, 1, -1, 10 )
630
+ @lod = Kamelopard::Lod.new(128, 1024, 128, 128)
631
+ @r = Kamelopard::Region.new({ :latlonaltbox => @latlon, :lod => @lod })
632
+ @o.region = @r
633
+
634
+ @reg = get_obj_child(@o, 'Region')
635
+ @l = get_child(@reg, 'LatLonAltBox')
636
+ @ld = get_child(@reg, 'Lod')
637
+ end
638
+
639
+ it 'creates a Kamelopard::Region element' do
640
+ @reg.should_not be_nil
641
+ @reg['id'].should =~ /^Region_\d+$/
642
+ end
643
+
644
+ it 'creates the right LatLonAltBox' do
645
+ @l.should_not be_nil
646
+ test_lat_lon_box(@l, @latlon)
647
+ end
648
+
649
+ it 'creates the right LOD' do
650
+ @ld.should_not be_nil
651
+ get_child_content(@ld, 'minLodPixels'). should == @lod.minpixels.to_s
652
+ get_child_content(@ld, 'maxLodPixels'). should == @lod.maxpixels.to_s
653
+ get_child_content(@ld, 'minFadeExtent'). should == @lod.minfade.to_s
654
+ get_child_content(@ld, 'maxFadeExtent'). should == @lod.maxfade.to_s
655
+ end
656
+
657
+ end
658
+
659
+ it 'correctly KML\'s the Kamelopard::StyleSelector' do
660
+ @o = Kamelopard::Feature.new({ :name => 'StyleSelector test' })
661
+ get_test_styles.each do |s| @o.styles << s end
662
+ document_has_styles(@o).should == true
663
+ end
664
+
665
+ it 'correctly KML\'s the Kamelopard::TimePrimitive' do
666
+ @o.timeprimitive = Kamelopard::TimeStamp.new('dflkj')
667
+ check_time_primitive(
668
+ lambda { |t| @o.timeprimitive = t },
669
+ lambda { @o.to_kml },
670
+ ''
671
+ )
672
+ end
673
+
674
+ it 'correctly KML\'s the Kamelopard::AbstractView' do
675
+ long, lat, alt = 13, 12, 11
676
+ heading, tilt, roll, range, mode = 1, 2, 3, 4, :clampToSeaFloor
677
+ p = Kamelopard::Point.new long, lat, alt
678
+ camera = Kamelopard::Camera.new(p, {
679
+ :heading => heading,
680
+ :tilt => tilt,
681
+ :roll => roll
682
+ })
683
+ lookat = Kamelopard::LookAt.new(p, {
684
+ :heading => heading,
685
+ :tilt => tilt,
686
+ :range => range
687
+ })
688
+ @o.abstractView = camera
689
+ a = get_obj_child(@o, "Camera")
690
+ a.should_not be_nil
691
+ validate_abstractview(a, 'Camera', p, heading, tilt, roll, range, mode).should be_true
692
+ @o.abstractView = lookat
693
+ a = get_obj_child(@o, "LookAt")
694
+ a.should_not be_nil
695
+ validate_abstractview(a, 'LookAt', p, heading, tilt, roll, range, mode).should be_true
696
+ end
697
+ end
698
+
699
+ shared_examples_for 'Kamelopard::Container' do
700
+ it 'should handle <<' do
701
+ @o.should respond_to('<<')
702
+ end
703
+ end
704
+
705
+ shared_examples_for 'Kamelopard::ColorStyle' do
706
+ it_should_behave_like 'Kamelopard::Object'
707
+ it_should_behave_like 'KML_includes_id'
708
+ it_should_behave_like 'KML_producer'
709
+
710
+ it 'should accept only valid color modes' do
711
+ @o.colorMode = :normal
712
+ @o.colorMode = :random
713
+ begin
714
+ @o.colorMode = :something_wrong
715
+ rescue RuntimeError => f
716
+ q = f.to_s
717
+ end
718
+ q.should =~ /colorMode must be either/
719
+ end
720
+
721
+ it 'should allow setting and retrieving alpha, blue, green, and red' do
722
+ a = 'ab'
723
+ @o.alpha = a
724
+ @o.alpha.should == a
725
+ @o.blue = a
726
+ @o.blue.should == a
727
+ @o.green = a
728
+ @o.green.should == a
729
+ @o.red = a
730
+ @o.red.should == a
731
+ end
732
+
733
+ it 'should get settings in the right order' do
734
+ @o.alpha = 'de'
735
+ @o.blue = 'ad'
736
+ @o.green = 'be'
737
+ @o.red = 'ef'
738
+ @o.color.should == 'deadbeef'
739
+ end
740
+
741
+ it 'should do its KML right' do
742
+ color = 'abcdefab'
743
+ colorMode = :random
744
+ @o.color = color
745
+ @o.colorMode = colorMode
746
+ get_obj_child_content(@o, 'color').should == color
747
+ get_obj_child_content(@o, 'colorMode').should == colorMode.to_s
748
+ end
749
+ end
750
+
751
+ shared_examples_for 'StyleSelector' do
752
+ it_should_behave_like 'Kamelopard::Object'
753
+ it_should_behave_like 'KML_producer'
754
+ it_should_behave_like 'KML_includes_id'
755
+
756
+ it 'should handle being attached to stuff' do
757
+ @o.should respond_to(:attach)
758
+ p = Kamelopard::Placemark.new({
759
+ :geometry => Kamelopard::Point.new(123, 23),
760
+ :name => 'test'
761
+ })
762
+ @o.attach(p)
763
+ @o.attached?.should be_true
764
+ end
765
+ end
766
+
767
+ shared_examples_for 'KML_root_name' do
768
+ it 'should have the right namespace and root' do
769
+ d = @o.to_kml
770
+ if ! @ns.nil? then
771
+ ns_url = 'http://www.google.com/kml/ext/2.2'
772
+ # TODO
773
+ # There is no add_namespace method
774
+ # d.add_namespace @ns, ns_url
775
+ # d.root.namespace.should == ns_url
776
+ end
777
+ # d.name.should == @o.class.name.gsub('Kamelopard::', '')
778
+ end
779
+ end
780
+
781
+ shared_examples_for 'Kamelopard::TourPrimitive' do
782
+ before(:each) do
783
+ @ns = 'gx'
784
+ end
785
+
786
+ it_should_behave_like 'Kamelopard::Object'
787
+ it_should_behave_like 'KML_includes_id'
788
+ it_should_behave_like 'KML_producer'
789
+ it_should_behave_like 'KML_root_name'
790
+ end
791
+
792
+ shared_examples_for 'Kamelopard::Overlay' do
793
+ it_should_behave_like 'Kamelopard::Feature'
794
+
795
+ it 'should have the right KML' do
796
+ href = 'look for this href'
797
+ drawOrder = 10
798
+ color = 'ffffff'
799
+
800
+ @o.href = href
801
+ @o.drawOrder = drawOrder
802
+ @o.color = color
803
+
804
+ x = get_obj_child(@o, "Icon")
805
+ get_child_content(x, "href").should == href
806
+
807
+ get_obj_child_content(@o, "color").should == color
808
+ get_obj_child_content(@o, "drawOrder").to_i.should == drawOrder
809
+
810
+ end
811
+ end
812
+
813
+ describe 'Kamelopard::Point' do
814
+ before(:each) do
815
+ @skip_change = true
816
+ @attrs = { :lat => 12.4, :long => 34.2, :alt => 500 }
817
+ @fields = %w[ latitude longitude altitude altitudeMode extrude ]
818
+ @o = Kamelopard::Point.new(@attrs[:long], @attrs[:lat], @attrs[:alt])
819
+ end
820
+
821
+ it_should_behave_like 'KML_includes_id'
822
+ it_should_behave_like 'Kamelopard::Geometry'
823
+ it_should_behave_like 'field_producer'
824
+
825
+ it 'parses itself correctly' do
826
+ p = point(1, 2, 3, :clampToGround, true)
827
+ new_p = Kamelopard::Point.parse(build_doc_from_node(p))
828
+ new_p.latitude.should == p.latitude
829
+ new_p.longitude.should == p.longitude
830
+ new_p.altitude.should == p.altitude
831
+ new_p.altitudeMode.should == p.altitudeMode
832
+ new_p.extrude.should == p.extrude
833
+ end
834
+
835
+ it 'accepts different coordinate formats' do
836
+ coords = [ [ '123D30m12.2s S', '34D56m24.4s E' ],
837
+ [ '32d10\'23.10" N', -145.3487 ],
838
+ [ 123.5985745, -45.32487 ] ]
839
+ coords.each do |a|
840
+ lambda { Kamelopard::Point.new(a[1], a[0]) }.should_not raise_error
841
+ end
842
+ end
843
+
844
+ # it 'does not accept coordinates that are out of range' do
845
+ # q = ''
846
+ # begin
847
+ # Kamelopard::Point.new(342.32487, 45908.123487)
848
+ # rescue RuntimeError => f
849
+ # q = f.to_s
850
+ # end
851
+ # q.should =~ /out of range/
852
+ # end
853
+
854
+ describe 'KML output' do
855
+ it_should_behave_like 'KML_producer'
856
+ it_should_behave_like 'altitudeMode'
857
+
858
+ it 'has the right coordinates' do
859
+ k = @o.to_kml
860
+ get_child_content(k, 'coordinates').should == "#{ @attrs[:long] }, #{ @attrs[:lat] }, #{ @attrs[:alt] }"
861
+ end
862
+
863
+ it 'handles extrude properly' do
864
+ @o.extrude = true
865
+ k = @o.to_kml
866
+ get_child_content(k, 'extrude').should == '1'
867
+ @o.extrude = false
868
+ k = @o.to_kml
869
+ get_child_content(k, 'extrude').should == '0'
870
+ end
871
+
872
+ it 'provides the correct short form' do
873
+ @o.altitudeMode = :clampToSeaFloor
874
+ @o.extrude = 1
875
+ k = @o.to_kml(nil, true)
876
+ get_child_content(k, 'extrude').should be_nil
877
+ get_child_content(k, 'altitudeMode').should be_nil
878
+ @o.master_only = true
879
+ get_child_content(k, 'extrude').should be_nil
880
+ get_child_content(k, 'altitudeMode').should be_nil
881
+ @o.master_only = false
882
+ end
883
+ end
884
+ end
885
+
886
+ describe 'Kamelopard::LineString' do
887
+ before(:each) do
888
+ @skip_change = true
889
+ @o = Kamelopard::LineString.new([ [1,2,3], [2,3,4], [3,4,5] ])
890
+ @fields = %w[
891
+ altitudeOffset extrude tessellate altitudeMode
892
+ drawOrder longitude latitude altitude
893
+ ]
894
+ end
895
+
896
+ it_should_behave_like 'altitudeMode'
897
+ it_should_behave_like 'KML_includes_id'
898
+ it_should_behave_like 'KML_producer'
899
+ it_should_behave_like 'Kamelopard::Geometry'
900
+ it_should_behave_like 'Kamelopard::CoordinateList'
901
+ it_should_behave_like 'field_producer'
902
+
903
+ it 'contains the right KML attributes' do
904
+ @o.altitudeOffset = nil
905
+ get_obj_child(@o, 'gx:altitudeOffset').should be_nil
906
+ @o.altitudeOffset = 1
907
+ get_obj_child(@o, 'gx:altitudeOffset').should_not be_nil
908
+ @o.extrude = nil
909
+ get_obj_child(@o, 'extrude').should be_nil
910
+ @o.extrude = true
911
+ get_obj_child(@o, 'extrude').should_not be_nil
912
+ @o.tessellate = nil
913
+ get_obj_child(@o, 'tessellate').should be_nil
914
+ @o.tessellate = true
915
+ get_obj_child(@o, 'tessellate').should_not be_nil
916
+ @o.drawOrder = nil
917
+ get_obj_child(@o, 'gx:drawOrder').should be_nil
918
+ @o.drawOrder = true
919
+ get_obj_child(@o, 'gx:drawOrder').should_not be_nil
920
+ end
921
+ end
922
+
923
+ describe 'Kamelopard::LinearRing' do
924
+ before(:each) do
925
+ @skip_change = true
926
+ @o = Kamelopard::LinearRing.new([ [1,2,3], [2,3,4], [3,4,5] ])
927
+ @fields = %w[ altitudeOffset extrude tessellate altitudeMode ]
928
+ end
929
+
930
+ it_should_behave_like 'altitudeMode'
931
+ it_should_behave_like 'KML_includes_id'
932
+ it_should_behave_like 'KML_producer'
933
+ it_should_behave_like 'Kamelopard::Geometry'
934
+ it_should_behave_like 'Kamelopard::CoordinateList'
935
+ it_should_behave_like 'field_producer'
936
+
937
+ it 'contains the right KML attributes' do
938
+ @o.altitudeOffset = nil
939
+ get_obj_child(@o, 'gx:altitudeOffset').should be_nil
940
+ @o.altitudeOffset = 1
941
+ get_obj_child(@o, 'gx:altitudeOffset').should_not be_nil
942
+ @o.extrude = nil
943
+ get_obj_child(@o, 'extrude').should be_nil
944
+ @o.extrude = true
945
+ get_obj_child(@o, 'extrude').should_not be_nil
946
+ @o.tessellate = nil
947
+ get_obj_child(@o, 'tessellate').should be_nil
948
+ @o.tessellate = true
949
+ get_obj_child(@o, 'tessellate').should_not be_nil
950
+ end
951
+ end
952
+
953
+ describe "Polygon" do
954
+ before(:each) do
955
+ @skip_change = true
956
+ @l = Kamelopard::LinearRing.new([[1,2,3],[2,3,4],[3,4,5]])
957
+ @o = Kamelopard::Polygon.new(@l, :inner => [@l])
958
+ end
959
+
960
+ it_should_behave_like 'Kamelopard::Geometry'
961
+ end
962
+
963
+ describe 'Kamelopard::Camera' do
964
+ before(:each) do
965
+ @skip_change = true
966
+ @o = Kamelopard::Camera.new(
967
+ Kamelopard::Point.new( 123, -123, 123 ),
968
+ {
969
+ :heading => 10,
970
+ :tilt => 10,
971
+ :roll => 10,
972
+ :altitudeMode => :clampToGround
973
+ }
974
+ )
975
+ @fields = [ 'roll' ]
976
+ end
977
+
978
+ it_should_behave_like 'Kamelopard::Camera-like'
979
+ it_should_behave_like 'field_producer'
980
+
981
+ it 'contains the right KML attributes' do
982
+ @o.roll = 12
983
+ get_obj_child_content(@o, 'roll').should == '12'
984
+ end
985
+ end
986
+
987
+ describe 'Kamelopard::LookAt' do
988
+ before(:each) do
989
+ @skip_change = true
990
+ @o = Kamelopard::LookAt.new(
991
+ Kamelopard::Point.new( 123, -123, 123 ),
992
+ {
993
+ :heading => 10,
994
+ :tilt => 10,
995
+ :range => 10,
996
+ :altitudeMode => :clampToGround
997
+ }
998
+ )
999
+ @fields = [ 'range' ]
1000
+ end
1001
+
1002
+ it_should_behave_like 'Kamelopard::Camera-like'
1003
+ it_should_behave_like 'field_producer'
1004
+ it_should_behave_like 'KML_root_name'
1005
+
1006
+ it 'contains the right KML attributes' do
1007
+ @o.range = 10
1008
+ get_folder << placemark('test', :geometry => @o)
1009
+ get_kml.find_first('//range').should_not be_nil
1010
+ get_obj_child_content(@o, 'range').should == '10'
1011
+ end
1012
+
1013
+ it 'parses itself correctly' do
1014
+ # XXX Include tests for gx:TimeSpan, gx:TimeStamp, and ViewerOptions elements
1015
+ l = Kamelopard::LookAt.new(point(12, 12, 12), :heading => 14, :tilt => 13, :range => 11)
1016
+ new_l = Kamelopard::LookAt.parse(build_doc_from_node(l))
1017
+ new_l.latitude.should == l.latitude
1018
+ new_l.longitude.should == l.longitude
1019
+ new_l.altitude.should == l.altitude
1020
+ new_l.altitudeMode.should == l.altitudeMode
1021
+ new_l.heading.should == l.heading
1022
+ new_l.tilt.should == l.tilt
1023
+ new_l.range.should == l.range
1024
+ end
1025
+ end
1026
+
1027
+ describe 'Kamelopard::TimeStamp' do
1028
+ before(:each) do
1029
+ @skip_change = true
1030
+ @when = '01 Dec 1934 12:12:12 PM'
1031
+ @o = Kamelopard::TimeStamp.new @when
1032
+ @fields = [ :when ]
1033
+ end
1034
+
1035
+ it_should_behave_like 'Kamelopard::TimePrimitive'
1036
+ it_should_behave_like 'field_producer'
1037
+ it_should_behave_like 'KML_root_name'
1038
+
1039
+ it 'has the right KML elements' do
1040
+ doc = build_doc_from_node @o
1041
+ doc.find("//*/*[when='#{@when}']").should_not == 0
1042
+ end
1043
+
1044
+ it 'behaves correctly when to_kml() gets an XML::Node' do
1045
+ a = XML::Node.new 'testnode'
1046
+ @o.to_kml(a)
1047
+ a.children.first.name.should == 'TimeStamp'
1048
+ end
1049
+
1050
+ it 'adds the correct namespace' do
1051
+ a = @o.to_kml(nil, 'test')
1052
+ a.name.should == 'test:TimeStamp'
1053
+ end
1054
+ end
1055
+
1056
+ describe 'Kamelopard::TimeSpan' do
1057
+ before(:each) do
1058
+ @skip_change = true
1059
+ @begin = '01 Dec 1934 12:12:12 PM'
1060
+ @end = '02 Dec 1934 12:12:12 PM'
1061
+ @o = Kamelopard::TimeSpan.new({ :begin => @begin, :end => @end })
1062
+ @fields = %w[ begin end ]
1063
+ end
1064
+
1065
+ it_should_behave_like 'Kamelopard::TimePrimitive'
1066
+ it_should_behave_like 'field_producer'
1067
+ it_should_behave_like 'KML_root_name'
1068
+
1069
+ it 'has the right KML elements' do
1070
+ doc = build_doc_from_node @o
1071
+ doc.find("//*/*[begin='#{ @begin }']").should_not be_nil
1072
+ doc.find("//*/*[end='#{ @end }']").should_not be_nil
1073
+ end
1074
+ end
1075
+
1076
+ describe 'Kamelopard::Feature' do
1077
+ before(:each) do
1078
+ @attr_name = :visibility
1079
+ @new_value = 1
1080
+ @o = Kamelopard::Feature.new('Some feature')
1081
+ @fields = []
1082
+ end
1083
+ it_should_behave_like 'Kamelopard::Feature'
1084
+
1085
+ it 'responds correctly when to_kml() is passed an XML::Node object' do
1086
+ a = XML::Node.new 'testnode'
1087
+ @o.to_kml(a)
1088
+ a.attributes[:id].should_not be_nil
1089
+ found = false
1090
+ a.children.each do |c|
1091
+ if c.name == 'name'
1092
+ found = true
1093
+ break
1094
+ end
1095
+ end
1096
+ found.should be_true
1097
+ end
1098
+ end
1099
+
1100
+ describe 'Kamelopard::Container' do
1101
+ before(:each) do
1102
+ @o = Kamelopard::Container.new
1103
+ end
1104
+
1105
+ it_should_behave_like 'Kamelopard::Container'
1106
+ end
1107
+
1108
+ describe 'Kamelopard::Folder' do
1109
+ before(:each) do
1110
+ @skip_change = true
1111
+ @o = Kamelopard::Folder.new('test folder')
1112
+ @fields = []
1113
+ end
1114
+ it_should_behave_like 'Kamelopard::Container'
1115
+ it_should_behave_like 'Kamelopard::Feature'
1116
+ end
1117
+
1118
+ describe 'Kamelopard::Document' do
1119
+ before(:each) do
1120
+ @skip_change = true
1121
+ @o = Kamelopard::DocumentHolder.instance.current_document
1122
+
1123
+ # Subsequent runs seem to keep the vsr_actions from previous runs, so clear 'em
1124
+ @o.vsr_actions = []
1125
+
1126
+ @lat = Kamelopard.convert_coord('10d10m10.1s N')
1127
+ @lon = Kamelopard.convert_coord('10d10m10.1s E')
1128
+ @alt = 1000
1129
+ @head = 150
1130
+
1131
+ @vsractions = %w{a b c d e f}
1132
+ @vsractions.each do |a|
1133
+ Kamelopard::VSRAction.new(a, :constraints => {
1134
+ :latitude => to_constraint(band(@lat, 0.1).collect{ |l| lat_check(l) }),
1135
+ :longitude => to_constraint(band(@lon, 0.1).collect{ |l| long_check(l) }),
1136
+ :heading => to_constraint(band(@head, 1)),
1137
+ :altitude => to_constraint(band(@alt, 2))
1138
+ })
1139
+ end
1140
+ end
1141
+
1142
+ it_should_behave_like 'Kamelopard::Container'
1143
+ it_should_behave_like 'Kamelopard::Feature'
1144
+
1145
+ it 'accepts new viewsyncrelay actions' do
1146
+ Kamelopard::DocumentHolder.instance.current_document.vsr_actions.size.should == @vsractions.size
1147
+ end
1148
+
1149
+ it 'can write its viewsyncrelay actions to a valid YAML string' do
1150
+ Kamelopard::DocumentHolder.instance.current_document.vsr_actions.size.should == @vsractions.size
1151
+ act = YAML.load(get_actions)
1152
+ act['actions'].size.should == @vsractions.size
1153
+ end
1154
+
1155
+ it 'can write its viewsyncrelay actions to a file' do
1156
+ file = Tempfile.new('kamelopard_test')
1157
+ file.close
1158
+ write_actions_to file.path
1159
+ YAML.parse_file(file.path)
1160
+ file.unlink
1161
+ end
1162
+
1163
+ it 'should return a tour' do
1164
+ @o.should respond_to(:tour)
1165
+ @o.tour.class.should == Kamelopard::Tour
1166
+ end
1167
+
1168
+ it 'should return a folder' do
1169
+ @o.should respond_to(:folder)
1170
+ @o.folder.class.should == Kamelopard::Folder
1171
+ end
1172
+
1173
+ it 'should have a get_kml_document method' do
1174
+ @o.should respond_to(:get_kml_document)
1175
+ @o.get_kml_document.class.should == LibXML::XML::Document
1176
+ end
1177
+ end
1178
+
1179
+ describe 'Kamelopard::ColorStyle' do
1180
+ before(:each) do
1181
+ @new_value = '11111111'
1182
+ @attr_name = :color
1183
+ @o = Kamelopard::ColorStyle.new 'deadbeef'
1184
+ @o.colorMode = :random
1185
+ end
1186
+
1187
+ it_should_behave_like 'Kamelopard::ColorStyle'
1188
+ it_should_behave_like 'KML_root_name'
1189
+
1190
+ it 'should return the right KML' do
1191
+ get_obj_child_content(@o, 'color').should == 'deadbeef'
1192
+ get_obj_child_content(@o, 'colorMode').should == 'random'
1193
+ end
1194
+
1195
+ it 'responds correctly when to_kml() is passed an XML::Node object' do
1196
+ a = XML::Node.new 'testnode'
1197
+ @o.to_kml(a)
1198
+ a.attributes[:id].should_not be_nil
1199
+ a.children.size.should == 2
1200
+
1201
+ sums = {
1202
+ :color => 0,
1203
+ :colorMode => 0,
1204
+ }
1205
+ a.children.each do |c|
1206
+ sums[c.name.to_sym] += 1
1207
+ end
1208
+ sums.keys.each do |k|
1209
+ sums[k].should == 1
1210
+ end
1211
+ end
1212
+ end
1213
+
1214
+ describe 'Kamelopard::BalloonStyle' do
1215
+ before(:each) do
1216
+ @new_value = '11111111'
1217
+ @attr_name = :color
1218
+ @o = Kamelopard::BalloonStyle.new 'balloon text'
1219
+ @o.textColor = 'deadbeef'
1220
+ @o.bgColor = 'deadbeef'
1221
+ @o.displayMode = :hide
1222
+ end
1223
+
1224
+ it_should_behave_like 'Kamelopard::Object'
1225
+ it_should_behave_like 'KML_includes_id'
1226
+ it_should_behave_like 'KML_producer'
1227
+ it_should_behave_like 'KML_root_name'
1228
+
1229
+ it 'should have the right attributes' do
1230
+ @o.bgColor.should == 'deadbeef'
1231
+ @o.textColor.should == 'deadbeef'
1232
+ @o.displayMode.should == :hide
1233
+ end
1234
+
1235
+ it 'should return the right KML' do
1236
+ get_obj_child_content(@o, 'text').should == 'balloon text'
1237
+ get_obj_child_content(@o, 'bgColor').should == 'deadbeef'
1238
+ get_obj_child_content(@o, 'textColor').should == 'deadbeef'
1239
+ get_obj_child_content(@o, 'displayMode').should == 'hide'
1240
+ end
1241
+ end
1242
+
1243
+ describe 'Kamelopard::XY' do
1244
+ before(:each) do
1245
+ @x, @y, @xunits, @yunits = 0.2, 13, :fraction, :pixels
1246
+ @o = Kamelopard::XY.new @x, @y, @xunits, @yunits
1247
+ end
1248
+
1249
+ it 'should return the right KML' do
1250
+ d = @o.to_kml 'test'
1251
+ d.name = 'test'
1252
+ d.attributes['x'].to_f.should == @x
1253
+ d.attributes['y'].to_f.should == @y
1254
+ d.attributes['xunits'].to_sym.should == @xunits
1255
+ d.attributes['yunits'].to_sym.should == @yunits
1256
+ end
1257
+ end
1258
+
1259
+ shared_examples_for 'Kamelopard::Icon' do
1260
+ before(:each) do
1261
+ @href = 'icon href'
1262
+ @values = {
1263
+ 'href' => @href,
1264
+ 'x' => 1.0,
1265
+ 'y' => 2.0,
1266
+ 'w' => 3.0,
1267
+ 'h' => 4.0,
1268
+ 'refreshMode' => :onInterval,
1269
+ 'refreshInterval' => 4,
1270
+ 'viewRefreshMode' => :onStop,
1271
+ 'viewRefreshTime' => 4,
1272
+ 'viewBoundScale' => 1,
1273
+ 'viewFormat' => 'format',
1274
+ 'httpQuery' => 'query'
1275
+ }
1276
+ @fields = @values.keys
1277
+ end
1278
+
1279
+ it_should_behave_like 'KML_includes_id'
1280
+ it_should_behave_like 'KML_producer'
1281
+ it_should_behave_like 'field_producer'
1282
+
1283
+ it 'puts the right fields in KML' do
1284
+ @values.each do |f, v|
1285
+ @o.method("#{f.to_s}=".to_sym).call(v)
1286
+ kml = @o.to_kml
1287
+ d = get_obj_child(kml, 'Icon')
1288
+ elem = f
1289
+ if f == 'x' || f == 'y' || f == 'w' || f == 'h' then
1290
+ elem = 'gx:' + f
1291
+ end
1292
+ #e = d.elements["//#{elem}"]
1293
+ e = get_child d, elem
1294
+ e.should_not be_nil
1295
+ e.content.should == v.to_s
1296
+ end
1297
+ end
1298
+ end
1299
+
1300
+ describe 'Kamelopard::IconStyle' do
1301
+ before(:each) do
1302
+ @new_value = '11111111'
1303
+ @attr_name = :color
1304
+ @href = 'Kamelopard::IconStyle href'
1305
+ @scale = 1.0
1306
+ @heading = 2.0
1307
+ @hs_x = 0.4
1308
+ @hs_y = 0.6
1309
+ @hs_xunits = :fraction
1310
+ @hs_yunits = :pixels
1311
+ @color = 'abcdefab'
1312
+ @colorMode = :random
1313
+ @o = Kamelopard::IconStyle.new( @href, {
1314
+ :scale => @scale,
1315
+ :heading => @heading,
1316
+ :hs_x => @hs_x,
1317
+ :hs_y => @hs_y,
1318
+ :hs_xunits => @hs_xunits,
1319
+ :hs_yunits => @hs_yunits,
1320
+ :color => @color,
1321
+ :colorMode => @colorMode
1322
+ })
1323
+ end
1324
+
1325
+ it_should_behave_like 'Kamelopard::ColorStyle'
1326
+
1327
+ it 'should support the right elements' do
1328
+ @o.should respond_to(:scale)
1329
+ @o.should respond_to(:scale=)
1330
+ @o.should respond_to(:heading)
1331
+ @o.should respond_to(:heading=)
1332
+ end
1333
+
1334
+ it 'should have the right KML' do
1335
+ d = @o.to_kml
1336
+ i = get_child d, "Icon"
1337
+ get_child_content(i, "href").should == @href
1338
+
1339
+ get_child_content(d, "scale").should == @scale.to_s
1340
+ get_child_content(d, "heading").should == @heading.to_s
1341
+
1342
+ h = get_child d, 'hotSpot'
1343
+ h.attributes['x'].should == @hs_x.to_s
1344
+ h.attributes['y'].should == @hs_y.to_s
1345
+ h.attributes['xunits'].should == @hs_xunits.to_s
1346
+ h.attributes['yunits'].should == @hs_yunits.to_s
1347
+ end
1348
+ end
1349
+
1350
+ describe 'Kamelopard::LabelStyle' do
1351
+ before(:each) do
1352
+ @new_value = '11111111'
1353
+ @attr_name = :color
1354
+ @fields = %w[ scale color colorMode ]
1355
+ @scale = 2
1356
+ @color = 'abcdefab'
1357
+ @colorMode = :random
1358
+ @o = Kamelopard::LabelStyle.new( @scale, {
1359
+ :color => @color,
1360
+ :colorMode => @colorMode
1361
+ })
1362
+ end
1363
+
1364
+ it_should_behave_like 'Kamelopard::ColorStyle'
1365
+
1366
+ it 'should have a scale field' do
1367
+ @o.should respond_to(:scale)
1368
+ @o.should respond_to(:scale=)
1369
+ get_obj_child_content(@o, 'scale').to_i.should == @scale
1370
+ end
1371
+ end
1372
+
1373
+ describe 'Kamelopard::LineStyle' do
1374
+ before(:each) do
1375
+ @new_value = '11111111'
1376
+ @attr_name = :color
1377
+ @width = 1
1378
+ @outerColor = 'aaaaaaaa'
1379
+ @outerWidth = 2
1380
+ @physicalWidth = 3
1381
+ @color = 'abcdefab'
1382
+ @colorMode = :normal
1383
+ @o = Kamelopard::LineStyle.new({
1384
+ :width => @width,
1385
+ :outerColor => @outerColor,
1386
+ :outerWidth => @outerWidth,
1387
+ :physicalWidth => @physicalWidth,
1388
+ :color => @color,
1389
+ :colorMode => @colorMode
1390
+ })
1391
+ @values = {
1392
+ 'width' => @width,
1393
+ 'outerColor' => @outerColor,
1394
+ 'outerWidth' => @outerWidth,
1395
+ 'physicalWidth' => @physicalWidth
1396
+ }
1397
+ @fields = @values.keys
1398
+ end
1399
+
1400
+ it_should_behave_like 'Kamelopard::ColorStyle'
1401
+ it_should_behave_like 'field_producer'
1402
+
1403
+ it 'should do its KML right' do
1404
+ @values.each do |k, v|
1405
+ @o.method("#{k}=").call(v)
1406
+ elem = (k == 'width' ? k : "gx:#{k}" )
1407
+ get_obj_child_content(@o, "#{elem}").should == v.to_s
1408
+ end
1409
+ end
1410
+ end
1411
+
1412
+ describe 'Kamelopard::ListStyle' do
1413
+ before(:each) do
1414
+ @new_value = '11111111'
1415
+ @attr_name = :color
1416
+ @bgColor = 'ffffffff'
1417
+ @state = :closed
1418
+ @listItemType = :check
1419
+ @href = 'list href'
1420
+ @o = Kamelopard::ListStyle.new({
1421
+ :bgColor => @bgColor,
1422
+ :state => @state,
1423
+ :href => @href,
1424
+ :listItemType => @listItemType
1425
+ })
1426
+ @fields = %w[ bgColor state listItemType href ]
1427
+ end
1428
+
1429
+ it_should_behave_like 'Kamelopard::Object'
1430
+ it_should_behave_like 'KML_includes_id'
1431
+ it_should_behave_like 'KML_producer'
1432
+ it_should_behave_like 'field_producer'
1433
+
1434
+ it 'makes the right KML' do
1435
+ values = {
1436
+ 'href' => @href,
1437
+ 'state' => @state,
1438
+ 'listItemType' => @listItemType,
1439
+ 'bgColor' => @bgColor
1440
+ }
1441
+
1442
+ check_kml_values @o, values
1443
+ end
1444
+ end
1445
+
1446
+ describe 'Kamelopard::PolyStyle' do
1447
+ before(:each) do
1448
+ @attr_name = :color
1449
+ @new_value = '11111111'
1450
+ @fill = 1
1451
+ @outline = 1
1452
+ @color = 'abcdefab'
1453
+ @colorMode = :random
1454
+ @o = Kamelopard::PolyStyle.new({
1455
+ :fill => @fill,
1456
+ :outline => @outline,
1457
+ :color => @color,
1458
+ :colorMode => @colorMode
1459
+ })
1460
+ end
1461
+
1462
+ it_should_behave_like 'Kamelopard::ColorStyle'
1463
+
1464
+ it 'should have the right fields' do
1465
+ fields = %w[ fill outline ]
1466
+ fields_exist @o, fields
1467
+ end
1468
+
1469
+ it 'should do the right KML' do
1470
+ values = {
1471
+ 'fill' => @fill,
1472
+ 'outline' => @outline
1473
+ }
1474
+ check_kml_values @o, values
1475
+ end
1476
+ end
1477
+
1478
+ describe 'StyleSelector' do
1479
+ before(:each) do
1480
+ @skip_change = true
1481
+ @o = Kamelopard::StyleSelector.new
1482
+ end
1483
+
1484
+ it_should_behave_like 'StyleSelector'
1485
+
1486
+ it 'responds correctly when to_kml() is passed an XML::Node object' do
1487
+ a = XML::Node.new 'testnode'
1488
+ @o.to_kml(a)
1489
+ a.attributes[:id].should_not be_nil
1490
+ end
1491
+ end
1492
+
1493
+ describe 'Style' do
1494
+ before(:each) do
1495
+ @skip_change = true
1496
+ i, la, lin, p, b, lis = get_test_substyles
1497
+ @o = Kamelopard::Style.new({
1498
+ :icon => i,
1499
+ :label => la,
1500
+ :line => lin,
1501
+ :poly => p,
1502
+ :balloon => b,
1503
+ :list => lis
1504
+ })
1505
+ end
1506
+
1507
+ it_should_behave_like 'StyleSelector'
1508
+
1509
+ it 'should have the right attributes' do
1510
+ [ :icon, :label, :line, :poly, :balloon, :list ].each do |a|
1511
+ @o.should respond_to(a)
1512
+ @o.should respond_to("#{ a.to_s }=".to_sym)
1513
+ end
1514
+ end
1515
+
1516
+ it 'should have the right KML bits' do
1517
+ d = @o.to_kml
1518
+ %w[ IconStyle LabelStyle LineStyle PolyStyle BalloonStyle ListStyle ].each do |e|
1519
+ get_child(d, e).should_not be_nil
1520
+ end
1521
+ end
1522
+ end
1523
+
1524
+ describe 'StyleMap' do
1525
+ def has_correct_stylemap_kml?(o)
1526
+ doc = build_doc_from_node o
1527
+ f = find_first_kml doc, '//kml:StyleMap/kml:Pair[kml:key="normal"]/kml:Style'
1528
+ s = find_first_kml doc, '//kml:StyleMap/kml:Pair[kml:key="highlight"]/kml:styleUrl'
1529
+ return f && s
1530
+ end
1531
+
1532
+ before(:each) do
1533
+ @skip_change = true
1534
+ i, la, lin, p, b, lis = get_test_substyles
1535
+ s = Kamelopard::Style.new({
1536
+ :icon => i,
1537
+ :balloon => b,
1538
+ :list => lis
1539
+ })
1540
+ @o = Kamelopard::StyleMap.new({ 'normal' => s, 'highlight' => 'someUrl' })
1541
+ end
1542
+
1543
+ it_should_behave_like 'StyleSelector'
1544
+
1545
+ it 'should handle styles vs. styleurls correctly' do
1546
+ has_correct_stylemap_kml?(@o).should be_true
1547
+ end
1548
+
1549
+ it 'should merge right' do
1550
+ o = Kamelopard::StyleMap.new({ 'normal' => Kamelopard::Style.new })
1551
+ o.merge( { 'highlight' => 'test2' } )
1552
+ has_correct_stylemap_kml?(o).should be_true
1553
+ end
1554
+ end
1555
+
1556
+ describe 'Kamelopard::Placemark' do
1557
+ before(:each) do
1558
+ @attr_name = 'gx:balloonVisibility'
1559
+ @new_value = 1
1560
+ @p = Kamelopard::Point.new( 123, 123 )
1561
+ @o = Kamelopard::Placemark.new({
1562
+ :name => 'placemark',
1563
+ :geometry => @p
1564
+ })
1565
+ end
1566
+
1567
+ it_should_behave_like 'Kamelopard::Feature'
1568
+
1569
+ it 'supports the right attributes' do
1570
+ [
1571
+ :latitude,
1572
+ :longitude,
1573
+ :altitude,
1574
+ :altitudeMode
1575
+ ].each do |f|
1576
+ @o.should respond_to(f)
1577
+ end
1578
+ end
1579
+
1580
+ it 'handles returning point correctly' do
1581
+ o1 = Kamelopard::Placemark.new( 'non-point', {
1582
+ :geometry => Kamelopard::Object.new
1583
+ })
1584
+ o2 = Kamelopard::Placemark.new( 'point', {
1585
+ :geometry => Kamelopard::Point.new(123, 123)
1586
+ })
1587
+
1588
+ lambda { o1.point }.should raise_exception
1589
+ lambda { o2.point }.should_not raise_exception
1590
+ end
1591
+ end
1592
+
1593
+ describe 'Kamelopard::FlyTo' do
1594
+ before(:each) do
1595
+ @attr_name = :duration
1596
+ @new_value = 10
1597
+ @o = Kamelopard::FlyTo.new
1598
+ end
1599
+
1600
+ it_should_behave_like 'Kamelopard::TourPrimitive'
1601
+
1602
+ it 'puts the right stuff in the KML' do
1603
+ duration = 10
1604
+ mode = :smooth
1605
+ @o.duration = duration
1606
+ @o.mode = mode
1607
+ get_child_content(@o.to_kml, "gx:duration").should == duration.to_s
1608
+ get_child_content(@o.to_kml, "gx:flyToMode").should == mode.to_s
1609
+ end
1610
+
1611
+ it 'handles Kamelopard::AbstractView correctly' do
1612
+ o = Kamelopard::FlyTo.new Kamelopard::LookAt.new( Kamelopard::Point.new(100, 100) )
1613
+ o.view.class.should == Kamelopard::LookAt
1614
+ o = Kamelopard::FlyTo.new Kamelopard::Point.new(90, 90)
1615
+ o.view.class.should == Kamelopard::LookAt
1616
+ o = Kamelopard::FlyTo.new Kamelopard::Camera.new(Kamelopard::Point.new(90, 90))
1617
+ o.view.class.should == Kamelopard::Camera
1618
+ end
1619
+ end
1620
+
1621
+ describe 'Kamelopard::AnimatedUpdate' do
1622
+ before(:each) do
1623
+ @skip_change = true
1624
+ @duration = 10
1625
+ @target = 'abcd'
1626
+ @delayedstart = 10
1627
+ @o = Kamelopard::AnimatedUpdate.new([], {
1628
+ :duration => @duration, :target => @target, :delayedStart => @delayedstart
1629
+ })
1630
+ end
1631
+
1632
+ it_should_behave_like 'Kamelopard::TourPrimitive'
1633
+
1634
+ it 'allows adding updates' do
1635
+ @o.updates.size.should == 0
1636
+ @o << '<Change><Placemark targetId="1"><visibility>1</visibility></Placemark></Change>'
1637
+ @o << '<Change><Placemark targetId="2"><visibility>0</visibility></Placemark></Change>'
1638
+ @o.updates.size.should == 2
1639
+ end
1640
+
1641
+ it 'returns the right KML' do
1642
+ @o.is_a?(Kamelopard::AnimatedUpdate).should == true
1643
+ @o << '<Change><Placemark targetId="1"><visibility>1</visibility></Placemark></Change>'
1644
+ d = @o.to_kml
1645
+ doc = build_doc_from_node @o
1646
+ find_first_kml(doc, "//kml:Update/kml:targetHref").content.should == @target
1647
+ find_first_kml(doc, "//kml:Update/kml:Change/kml:Placemark").should_not be_nil
1648
+ get_child_content(d, "gx:delayedStart").should == @delayedstart.to_s
1649
+ get_child_content(d, "gx:duration").should == @duration.to_s
1650
+
1651
+
1652
+ # d.elements['//Update/targetHref'].text.should == @target
1653
+ # d.elements['//Update/Change/Placemark'].should_not be_nil
1654
+ # d.elements['//gx:delayedStart'].text.to_i.should == @delayedstart
1655
+ # d.elements['//gx:duration'].text.to_i.should == @duration
1656
+ end
1657
+ end
1658
+
1659
+ describe 'Kamelopard::TourControl' do
1660
+ before(:each) do
1661
+ @skip_change = true
1662
+ @o = Kamelopard::TourControl.new
1663
+ end
1664
+
1665
+ it_should_behave_like 'Kamelopard::TourPrimitive'
1666
+
1667
+ it 'should have the right KML' do
1668
+ get_obj_child_content(@o, "gx:playMode").should == 'pause'
1669
+ end
1670
+ end
1671
+
1672
+ describe 'Kamelopard::Wait' do
1673
+ before(:each) do
1674
+ @skip_change = true
1675
+ @pause = 10
1676
+ @o = Kamelopard::Wait.new(@pause)
1677
+ end
1678
+
1679
+ it_should_behave_like 'Kamelopard::TourPrimitive'
1680
+
1681
+ it 'should have the right KML' do
1682
+ get_obj_child_content(@o, "gx:duration").to_i.should == @pause
1683
+ end
1684
+ end
1685
+
1686
+ describe 'Kamelopard::SoundCue' do
1687
+ before(:each) do
1688
+ @attr_name = :href
1689
+ @new_value = 'new href'
1690
+ @href = 'href'
1691
+ @delayedStart = 10.0
1692
+ @o = Kamelopard::SoundCue.new @href, @delayedStart
1693
+ end
1694
+
1695
+ it_should_behave_like 'Kamelopard::TourPrimitive'
1696
+
1697
+ it 'should have the right KML' do
1698
+ d = @o.to_kml
1699
+ get_obj_child_content(@o, "href").should == @href
1700
+ get_obj_child_content(@o, "gx:delayedStart").to_f.should == @delayedStart
1701
+ end
1702
+ end
1703
+
1704
+ describe 'Kamelopard::Tour' do
1705
+ before(:each) do
1706
+ @skip_change = true
1707
+ @name = 'TourName'
1708
+ @description = 'TourDescription'
1709
+ @o = Kamelopard::Tour.new @name, @description
1710
+ @ns = 'gx'
1711
+ end
1712
+
1713
+ it_should_behave_like 'Kamelopard::Object'
1714
+ it_should_behave_like 'KML_includes_id'
1715
+ it_should_behave_like 'KML_producer'
1716
+ it_should_behave_like 'KML_root_name'
1717
+
1718
+ it 'has the right KML' do
1719
+ Kamelopard::Wait.new
1720
+ Kamelopard::Wait.new
1721
+ Kamelopard::Wait.new
1722
+ Kamelopard::Wait.new
1723
+
1724
+ get_obj_child_content(@o, "name").should == @name
1725
+ get_obj_child_content(@o, "description").should == @description
1726
+
1727
+ playlist = get_obj_child(@o, "gx:Playlist")
1728
+ playlist.should_not be_nil
1729
+
1730
+ # There are five waits here, because Kamelopard includes one wait at
1731
+ # the beginning of each tour automatically
1732
+ playlist.children.length.should == 5
1733
+ end
1734
+ end
1735
+
1736
+ describe 'Kamelopard::ScreenOverlay' do
1737
+ before(:each) do
1738
+ @attr_name = :color
1739
+ @new_value = '11111111'
1740
+ @x = 10
1741
+ @un = :pixel
1742
+ @xy = Kamelopard::XY.new @x, @x, @un, @un
1743
+ @rotation = 10
1744
+ @name = 'some name'
1745
+ @o = Kamelopard::ScreenOverlay.new({
1746
+ :href => 'test',
1747
+ :name => @name,
1748
+ :size => @xy,
1749
+ :rotation => @rotation,
1750
+ :overlayXY => @xy,
1751
+ :screenXY => @xy,
1752
+ :rotationXY => @xy
1753
+ })
1754
+ @fields = %w[ overlayXY screenXY rotationXY size rotation ]
1755
+ end
1756
+
1757
+ it_should_behave_like 'Kamelopard::Overlay'
1758
+ it_should_behave_like 'field_producer'
1759
+
1760
+ it 'has the right KML' do
1761
+ d = @o.to_kml
1762
+ get_obj_child_content(@o, "name").should == @name
1763
+ get_obj_child_content(@o, "rotation").should == @rotation.to_s
1764
+ %w[ overlayXY screenXY rotationXY size ].each do |a|
1765
+ node = get_obj_child(@o, a)
1766
+ node.attributes['x'].should == @x.to_s
1767
+ node.attributes['y'].should == @x.to_s
1768
+ node.attributes['xunits'].should == @un.to_s
1769
+ node.attributes['yunits'].should == @un.to_s
1770
+
1771
+ end
1772
+ end
1773
+ end
1774
+
1775
+ shared_examples_for 'Kamelopard::ViewVolume' do
1776
+ before(:each) do
1777
+ @n = 53
1778
+ @fields = %w[ leftFov rightFov bottomFov topFov near ]
1779
+ end
1780
+
1781
+ it_should_behave_like 'field_producer'
1782
+
1783
+ it 'has the right KML' do
1784
+ @o.leftFov = -@n
1785
+ @o.rightFov = @n
1786
+ @o.bottomFov = -@n
1787
+ @o.topFov = @n
1788
+ @o.near = @n
1789
+
1790
+ d = @o.to_kml
1791
+ volume = get_obj_child(@o, "ViewVolume")
1792
+ match_view_vol(volume, @n)
1793
+ end
1794
+ end
1795
+
1796
+ shared_examples_for 'Kamelopard::ImagePyramid' do
1797
+ before(:each) do
1798
+ @fields = %w[ tileSize maxWidth maxHeight gridOrigin ]
1799
+ end
1800
+
1801
+ it_should_behave_like 'field_producer'
1802
+
1803
+ it 'has the right KML' do
1804
+ @o.tileSize = @n
1805
+ @o.maxWidth = @n
1806
+ @o.maxHeight = @n
1807
+ @o.gridOrigin = @n
1808
+ d = @o.to_kml
1809
+ pyramid = get_obj_child(@o, "ImagePyramid")
1810
+ match_image_pyramid(pyramid, @n)
1811
+ end
1812
+ end
1813
+
1814
+ describe 'Kamelopard::PhotoOverlay' do
1815
+ before(:each) do
1816
+ @n = 34
1817
+ @rotation = 10
1818
+ @point = Kamelopard::Point.new(@n, @n)
1819
+ @shape = 'cylinder'
1820
+ @o = Kamelopard::PhotoOverlay.new({
1821
+ :href => 'test',
1822
+ :point => @point,
1823
+ :rotation => @rotation,
1824
+ :point => @point,
1825
+ :shape => @shape,
1826
+ :leftFov => -@n,
1827
+ :rightFov => @n,
1828
+ :bottomFov => -@n,
1829
+ :topFov => @n,
1830
+ :near => @n,
1831
+ :tileSize => @n,
1832
+ :maxWidth => @n,
1833
+ :maxHeight => @n,
1834
+ :gridOrigin => @n
1835
+ })
1836
+ @fields = %w[ rotation point shape ]
1837
+ @attr_name = :color
1838
+ @new_value = '11111111'
1839
+ end
1840
+
1841
+ it_should_behave_like 'Kamelopard::Overlay'
1842
+ it_should_behave_like 'field_producer'
1843
+ it_should_behave_like 'Kamelopard::ViewVolume'
1844
+ it_should_behave_like 'Kamelopard::ImagePyramid'
1845
+ it_should_behave_like 'KML_root_name'
1846
+
1847
+ it 'has the right KML' do
1848
+
1849
+ get_obj_child_content(@o, "shape").should == @shape
1850
+ get_obj_child_content(@o, "rotation").should == @rotation.to_s
1851
+
1852
+
1853
+ volume = get_obj_child(@o, "ViewVolume")
1854
+ pyramid = get_obj_child(@o, "ImagePyramid")
1855
+
1856
+ match_view_vol(volume, @n).should be_true
1857
+ match_image_pyramid(pyramid, @n).should be_true
1858
+ end
1859
+ end
1860
+
1861
+ describe 'Kamelopard::LatLonBox' do
1862
+ before(:each) do
1863
+ @n = 130.2
1864
+ @o = Kamelopard::LatLonBox.new @n, @n, @n, @n, @n, @n, @n, :relativeToGround
1865
+ @fields = %w[ north south east west rotation minAltitude maxAltitude altitudeMode ]
1866
+ end
1867
+
1868
+ it_should_behave_like 'KML_producer'
1869
+ it_should_behave_like 'field_producer'
1870
+
1871
+ it 'has the right KML in altitude mode' do
1872
+ d = @o.to_kml(nil, true)
1873
+ get_child_content(d, "minAltitude").should == @n.to_s
1874
+ get_child_content(d, "maxAltitude").should == @n.to_s
1875
+ test_lat_lon_box(d, @o)
1876
+ end
1877
+
1878
+ it 'has the right KML in non-altitude mode' do
1879
+ d = @o.to_kml(nil, false)
1880
+ test_lat_lon_box(d, @o)
1881
+ end
1882
+ end
1883
+
1884
+ describe 'Kamelopard::LatLonQuad' do
1885
+ before(:each) do
1886
+ @n = 123.2
1887
+ @p = Kamelopard::Point.new(@n, @n)
1888
+ @o = Kamelopard::LatLonQuad.new @p, @p, @p, @p
1889
+ @fields = %w[ lowerLeft lowerRight upperRight upperLeft ]
1890
+ end
1891
+
1892
+ it_should_behave_like 'KML_producer'
1893
+ it_should_behave_like 'field_producer'
1894
+
1895
+ it 'has the right KML' do
1896
+ d = @o.to_kml
1897
+ test_lat_lon_quad(d, @n)
1898
+ end
1899
+ end
1900
+
1901
+ describe 'Kamelopard::GroundOverlay' do
1902
+ before(:each) do
1903
+ @icon_href = 'some href'
1904
+ @n = 123.2
1905
+ @lb = Kamelopard::LatLonBox.new @n, @n, @n, @n, @n, @n, @n, :relativeToGround
1906
+ @p = Kamelopard::Point.new(@n, @n)
1907
+ @lq = Kamelopard::LatLonQuad.new @p, @p, @p, @p
1908
+ @altmode = :relativeToSeaFloor
1909
+ @o = Kamelopard::GroundOverlay.new @icon_href, { :latlonbox => @lb, :latlonquad => @lq, :altitude => @n, :altitudeMode => @altmode }
1910
+ @fields = %w[ altitude altitudeMode latlonbox latlonquad ]
1911
+ @attr_name = :color
1912
+ @new_value = '11111111'
1913
+ end
1914
+
1915
+ it_should_behave_like 'Kamelopard::Overlay'
1916
+ it_should_behave_like 'field_producer'
1917
+ it_should_behave_like 'altitudeMode'
1918
+ it_should_behave_like 'KML_root_name'
1919
+
1920
+ it 'complains when latlonbox and latlonquad are nil' do
1921
+ o = Kamelopard::GroundOverlay.new @icon_href, { :altitude => @n, :altitudeMode => @altmode }
1922
+ lambda { o.to_kml }.should raise_exception
1923
+ o.latlonquad = @lq
1924
+ lambda { o.to_kml }.should_not raise_exception
1925
+ end
1926
+
1927
+ it 'has the right KML' do
1928
+ d = @o.to_kml
1929
+ get_child_content(d, 'altitude').should == @n.to_s
1930
+
1931
+ lat_lon_box = get_child d, "LatLonBox"
1932
+ test_lat_lon_box(lat_lon_box, @lb)
1933
+
1934
+
1935
+ lat_lon_quad = get_child d, "gx:LatLonQuad"
1936
+ test_lat_lon_quad(lat_lon_quad, @n)
1937
+ end
1938
+ end
1939
+
1940
+ describe 'Kamelopard::Lod' do
1941
+ before(:each) do
1942
+ @n = 324
1943
+ @o = Kamelopard::Lod.new @n, @n, @n, @n
1944
+ @fields = %w[ minpixels maxpixels minfade maxfade ]
1945
+ end
1946
+
1947
+ it_should_behave_like 'field_producer'
1948
+ it_should_behave_like 'KML_root_name'
1949
+
1950
+ it 'has the right KML' do
1951
+ d = @o.to_kml
1952
+ test_lod d, @n
1953
+ end
1954
+ end
1955
+
1956
+ describe 'Kamelopard::Region' do
1957
+ before(:each) do
1958
+ @skip_change = true
1959
+ @n = 12
1960
+ @lb = Kamelopard::LatLonBox.new @n, @n, @n, @n, @n, @n, @n, :relativeToGround
1961
+ @ld = Kamelopard::Lod.new @n, @n, @n, @n
1962
+ @o = Kamelopard::Region.new({ :latlonaltbox => @lb, :lod => @ld })
1963
+ @fields = %w[ latlonaltbox lod ]
1964
+ end
1965
+
1966
+ it_should_behave_like 'Kamelopard::Object'
1967
+ it_should_behave_like 'field_producer'
1968
+ it_should_behave_like 'KML_root_name'
1969
+
1970
+ it 'has the right KML' do
1971
+ d = @o.to_kml
1972
+ test_lat_lon_box(get_child(d, 'LatLonAltBox'), @lb)
1973
+ test_lod(get_child(d, 'Lod'), @n)
1974
+ end
1975
+ end
1976
+
1977
+ describe 'Kamelopard::Orientation' do
1978
+ before(:each) do
1979
+ @n = 37
1980
+ @o = Kamelopard::Orientation.new @n, @n, @n
1981
+ @fields = %w[ heading tilt roll ]
1982
+ end
1983
+
1984
+ it_should_behave_like 'KML_producer'
1985
+ it_should_behave_like 'field_producer'
1986
+ it_should_behave_like 'KML_root_name'
1987
+
1988
+ # it 'should complain with weird arguments' do
1989
+ # lambda { Kamelopard::Orientation.new -1, @n, @n }.should raise_exception
1990
+ # lambda { Kamelopard::Orientation.new @n, -1, @n }.should raise_exception
1991
+ # lambda { Kamelopard::Orientation.new @n, @n, -1 }.should raise_exception
1992
+ # lambda { Kamelopard::Orientation.new 483, @n, @n }.should raise_exception
1993
+ # lambda { Kamelopard::Orientation.new @n, 483, @n }.should raise_exception
1994
+ # lambda { Kamelopard::Orientation.new @n, @n, 483 }.should raise_exception
1995
+ # end
1996
+
1997
+ it 'has the right KML' do
1998
+ d = @o.to_kml
1999
+ @fields.each do |f|
2000
+ get_child_content(d, f).to_i.should == @n
2001
+ end
2002
+ end
2003
+ end
2004
+
2005
+ describe 'Kamelopard::Scale' do
2006
+ before(:each) do
2007
+ @n = 213
2008
+ @o = Kamelopard::Scale.new @n, @n, @n
2009
+ @fields = %w[ x y z ]
2010
+ end
2011
+
2012
+ it_should_behave_like 'KML_producer'
2013
+ it_should_behave_like 'field_producer'
2014
+ it_should_behave_like 'KML_root_name'
2015
+
2016
+ it 'has the right KML' do
2017
+ d = @o.to_kml
2018
+ @fields.each do |f|
2019
+ get_child_content(d, f).to_i.should == @n
2020
+ end
2021
+ end
2022
+ end
2023
+
2024
+ describe 'Kamelopard::Alias' do
2025
+ before(:each) do
2026
+ @n = 'some href'
2027
+ @o = Kamelopard::Alias.new @n, @n
2028
+ @fields = %w[ targetHref sourceHref ]
2029
+ end
2030
+
2031
+ it_should_behave_like 'KML_producer'
2032
+ it_should_behave_like 'field_producer'
2033
+ it_should_behave_like 'KML_root_name'
2034
+
2035
+ it 'has the right KML' do
2036
+ d = @o.to_kml
2037
+ @fields.each do |f|
2038
+ get_child_content(d, "#{f}").should == @n
2039
+ end
2040
+ end
2041
+ end
2042
+
2043
+ describe 'Kamelopard::ResourceMap' do
2044
+ before(:each) do
2045
+ targets = %w[ Neque porro quisquam est qui dolorem ipsum quia dolor sit amet consectetur adipisci velit ]
2046
+ sources = %w[ Lorem ipsum dolor sit amet consectetur adipiscing elit Nunc quis odio metus Fusce at ]
2047
+ @aliases = []
2048
+ targets.zip(sources).each do |a|
2049
+ @aliases << Kamelopard::Alias.new(a[0], a[1])
2050
+ end
2051
+ @o = Kamelopard::ResourceMap.new @aliases
2052
+ @fields = [ 'aliases' ]
2053
+ end
2054
+
2055
+ it_should_behave_like 'KML_producer'
2056
+ it_should_behave_like 'field_producer'
2057
+ it_should_behave_like 'KML_root_name'
2058
+
2059
+ it 'accepts various aliases correctly' do
2060
+ # ResourceMap should accept its initializer's alias argument either as
2061
+ # an array of Alias object, or as a single Alias object. The
2062
+ # before(:each) block tests the former, and this test the latter
2063
+ o = Kamelopard::ResourceMap.new Kamelopard::Alias.new('test', 'test')
2064
+ o.aliases.size.should == 1
2065
+ @o.aliases.size.should == @aliases.size
2066
+ end
2067
+
2068
+ it 'has the right KML' do
2069
+ # Make this a REXML::Document instead of just a collection of elements, for better XPath support
2070
+ doc = build_doc_from_node @o
2071
+
2072
+ @aliases.each do |a|
2073
+ find_first_kml(doc, "//kml:Alias[kml:targetHref=\"#{a.targetHref}\" and kml:sourceHref=\"#{a.sourceHref}\"]").should_not be_nil
2074
+ end
2075
+ end
2076
+ end
2077
+
2078
+ describe 'Kamelopard::Link' do
2079
+ before(:each) do
2080
+ @attr_name = :href
2081
+ @new_value = 'something else'
2082
+ @href = 'some href'
2083
+ @refreshMode = :onInterval
2084
+ @viewRefreshMode = :onRegion
2085
+ @o = Kamelopard::Link.new @href, { :refreshMode => @refreshMode, :viewRefreshMode => @viewRefreshMode }
2086
+ @fields = %w[ href refreshMode refreshInterval viewRefreshMode viewBoundScale viewFormat httpQuery ]
2087
+ end
2088
+
2089
+ it_should_behave_like 'Kamelopard::Object'
2090
+ it_should_behave_like 'KML_producer'
2091
+ it_should_behave_like 'field_producer'
2092
+ it_should_behave_like 'KML_root_name'
2093
+
2094
+ it 'has the right KML' do
2095
+ @n = 213
2096
+ @o.refreshInterval = @n
2097
+ @o.viewBoundScale = @n
2098
+ @o.viewFormat = @href
2099
+ @o.httpQuery = @href
2100
+ d = @o.to_kml
2101
+ {
2102
+ :href => @href,
2103
+ :refreshMode => @refreshMode,
2104
+ :refreshInterval => @n,
2105
+ :viewRefreshMode => @viewRefreshMode,
2106
+ :viewBoundScale => @n,
2107
+ :viewFormat => @href,
2108
+ :httpQuery => @href
2109
+ }.each do |k, v|
2110
+ get_child_content(d, k.to_s).should == v.to_s
2111
+ end
2112
+ end
2113
+ end
2114
+
2115
+ describe 'Kamelopard::Model' do
2116
+ before(:each) do
2117
+ @attr_name = :scale
2118
+ @new_value = 10
2119
+ @n = 123
2120
+ @href = 'some href'
2121
+ @refreshMode = :onInterval
2122
+ @viewRefreshMode = :onRegion
2123
+ @link = Kamelopard::Link.new @href, { :refreshMode => @refreshMode, :viewRefreshMode => @viewRefreshMode }
2124
+ @loc = Kamelopard::Point.new(@n, @n, @n)
2125
+ @orient = Kamelopard::Orientation.new @n, @n, @n
2126
+ @scale = Kamelopard::Scale.new @n, @n, @n
2127
+ targets = %w[ Neque porro quisquam est qui dolorem ipsum quia dolor sit amet consectetur adipisci velit ]
2128
+ sources = %w[ Lorem ipsum dolor sit amet consectetur adipiscing elit Nunc quis odio metus Fusce at ]
2129
+ @aliases = []
2130
+ targets.zip(sources).each do |a|
2131
+ @aliases << Kamelopard::Alias.new(a[0], a[1])
2132
+ end
2133
+ @resmap = Kamelopard::ResourceMap.new @aliases
2134
+ @o = Kamelopard::Model.new({ :link => @link, :location => @loc, :orientation => @orient, :scale => @scale, :resourceMap => @resmap })
2135
+ @fields = %w[ link location orientation scale resourceMap ]
2136
+ end
2137
+
2138
+ it_should_behave_like 'Kamelopard::Geometry'
2139
+ it_should_behave_like 'KML_producer'
2140
+ it_should_behave_like 'field_producer'
2141
+
2142
+ it 'makes the right KML' do
2143
+ d = @o.to_kml
2144
+ %w[ Link Location Orientation Scale ResourceMap ].each do |f|
2145
+ get_child(d, f).should_not be_nil
2146
+ end
2147
+ %w[ longitude latitude altitude ].each do |f|
2148
+ location = get_child(d, "Location")
2149
+ location.should_not be_nil
2150
+ get_child_content(location, f).to_i.should == @n
2151
+ end
2152
+ end
2153
+ end
2154
+
2155
+ describe 'Kamelopard::Container' do
2156
+ before(:each) do
2157
+ @o = Kamelopard::Container.new()
2158
+ end
2159
+
2160
+ it_should_behave_like 'Kamelopard::Container'
2161
+ end
2162
+
2163
+ describe 'placemark reading' do
2164
+ before(:each) do
2165
+ @s = %{<?xml version="1.0" encoding="UTF-8"?>
2166
+ <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
2167
+ <Document>
2168
+ <name>My Places.kml</name>
2169
+ <Style id="some_style">
2170
+ <IconStyle>
2171
+ <scale>1.1</scale>
2172
+ <Icon>
2173
+ <href>something.png</href>
2174
+ </Icon>
2175
+ <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
2176
+ </IconStyle>
2177
+ </Style>
2178
+ <Folder>
2179
+ <name>My Places</name>
2180
+ <open>1</open>
2181
+ <Placemark>
2182
+ <name>1</name>
2183
+ <LookAt>
2184
+ <longitude>-122.5701578349128</longitude>
2185
+ <latitude>37.83004301072002</latitude>
2186
+ <altitude>0</altitude>
2187
+ <heading>51.16129662831626</heading>
2188
+ <tilt>45.60413428326378</tilt>
2189
+ <range>292356.4207362059</range>
2190
+ <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
2191
+ </LookAt>
2192
+ <styleUrl>#some_style</styleUrl>
2193
+ <Point>
2194
+ <coordinates>-122.5701578349128,37.83004301072002,0</coordinates>
2195
+ </Point>
2196
+ </Placemark>
2197
+ <Placemark>
2198
+ <name>2</name>
2199
+ <LookAt>
2200
+ <longitude>-122.4831599898557</longitude>
2201
+ <latitude>37.81426712799578</latitude>
2202
+ <altitude>0</altitude>
2203
+ <heading>106.7198650112253</heading>
2204
+ <tilt>53.06224485674277</tilt>
2205
+ <range>11157.71457873637</range>
2206
+ <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
2207
+ </LookAt>
2208
+ <styleUrl>#some_style</styleUrl>
2209
+ <Point>
2210
+ <coordinates>-122.4831599898557,37.81426712799578,0</coordinates>
2211
+ </Point>
2212
+ </Placemark>
2213
+ <Placemark>
2214
+ <name>3</name>
2215
+ <LookAt>
2216
+ <longitude>-122.4791157460921</longitude>
2217
+ <latitude>37.82200644299443</latitude>
2218
+ <altitude>0</altitude>
2219
+ <heading>171.349340928465</heading>
2220
+ <tilt>52.66258054379743</tilt>
2221
+ <range>3481.461153245</range>
2222
+ <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
2223
+ </LookAt>
2224
+ <styleUrl>#some_style</styleUrl>
2225
+ <Point>
2226
+ <coordinates>-122.4791157460921,37.82200644299443,0</coordinates>
2227
+ </Point>
2228
+ </Placemark>
2229
+ </Folder>
2230
+ </Document>
2231
+ </kml>
2232
+ }
2233
+ end
2234
+
2235
+ it 'gets the right number of placemarks' do
2236
+ i = 0
2237
+ each_placemark(XML::Document.string(@s)) do |v, p|
2238
+ i += 1
2239
+ end
2240
+ i.should == 3
2241
+ end
2242
+ end
2243
+
2244
+ describe 'The band function' do
2245
+ it 'correctly calculates bands' do
2246
+ band(100, 20).should == [80, 120]
2247
+ band(100, 20).should_not == [70, 120]
2248
+ band(100, 20).should_not == [80, 140]
2249
+ end
2250
+ end
2251
+
2252
+ describe 'The latitude and longitude range checker function' do
2253
+ it 'handles longitude correctly' do
2254
+ # Within range
2255
+ long_check(35).should == 35
2256
+ # At edge of range
2257
+ long_check(180).should == 180
2258
+ # Below range
2259
+ long_check(-190).should == 170
2260
+ # Above range
2261
+ long_check(200).should == -160
2262
+ # Far below range
2263
+ long_check(-980).should == 100
2264
+ end
2265
+
2266
+ it 'handles latitude correctly' do
2267
+ # Within range
2268
+ lat_check(15).should == 15
2269
+ # At edge of range
2270
+ lat_check(90).should == 90
2271
+ # Below range
2272
+ lat_check(-95).should == 85
2273
+ # Above range
2274
+ lat_check(100).should == -80
2275
+ # Far below range
2276
+ lat_check(-980).should == -80
2277
+ end
2278
+ end
2279
+
2280
+ describe 'VSRActions' do
2281
+ before(:each) do
2282
+ @action_name = 'action name'
2283
+ @action_cmd = 'ls -1'
2284
+ @latitude = 45
2285
+ @longitude = 34
2286
+ @heading = 123
2287
+ @altitude = 453
2288
+
2289
+ @action = Kamelopard::VSRAction.new(@action_name, :constraints => {
2290
+ 'latitude' => to_constraint(band(@latitude, 0.1).collect{ |v| lat_check(v) }),
2291
+ 'longitude' => to_constraint(band(@longitude, 0.1).collect{ |v| long_check(v) }),
2292
+ 'heading' => to_constraint(band(@heading, 1)),
2293
+ 'altitude' => to_constraint(band(@altitude, 2))
2294
+ }, :action => @action_cmd)
2295
+ end
2296
+
2297
+ describe 'make themselves into hashes. A hash' do
2298
+ before(:each) do
2299
+ @hash = @action.to_hash
2300
+ end
2301
+
2302
+ it 'doesn\'t barf when created' do
2303
+ @hash.should_not be_nil
2304
+ end
2305
+
2306
+ it 'contains proper constraints' do
2307
+ @hash['constraints'].should_not be_nil
2308
+ @hash['constraints']['latitude'].should_not be_nil
2309
+ %w{latitude longitude heading altitude}.each do |i|
2310
+ @hash['constraints'][i].should =~ /\[.*, .*\]/
2311
+ end
2312
+ end
2313
+ end
2314
+ end
2315
+
2316
+ describe 'DocumentHolder' do
2317
+ it 'supports multiple documents' do
2318
+ Kamelopard::Document.new
2319
+ name_document 'First'
2320
+ i = Kamelopard::DocumentHolder.instance.document_index
2321
+ Kamelopard::Document.new
2322
+ name_document 'Second'
2323
+ j = Kamelopard::DocumentHolder.instance.document_index
2324
+
2325
+ get_doc_holder.document_index = i
2326
+ get_document.name.should == 'First'
2327
+ get_doc_holder.document_index = j
2328
+ get_document.name.should == 'Second'
2329
+ end
2330
+
2331
+ it 'can delete the current document' do
2332
+ get_folder << placemark('test')
2333
+ get_kml.find_first('//Placemark').should_not be_nil
2334
+
2335
+ dh = get_doc_holder
2336
+ dh.delete_current_doc while dh.documents.size > 0
2337
+
2338
+ get_kml.find_first('//Placemark').should be_nil
2339
+ end
2340
+ end
2341
+
2342
+ def val_within_range(o, val, expected, perc)
2343
+ res = o.run_function(val)
2344
+ res.should <= expected + perc
2345
+ res.should >= expected - perc
2346
+ end
2347
+
2348
+ shared_examples_for 'mathematical functions' do
2349
+ it 'includes the start and end points, within a margin of error' do
2350
+ val_within_range @o, @o.min, @start_value, @one_perc
2351
+ val_within_range @o, @o.max, @end_value, @one_perc
2352
+ end
2353
+ end
2354
+
2355
+ describe 'Line function' do
2356
+ before(:each) do
2357
+ @start_value = 100
2358
+ @end_value = 300
2359
+ @one_perc = (@end_value - @start_value).abs / 30.0
2360
+ @o = Kamelopard::Functions::Line.interpolate(@start_value, @end_value)
2361
+ end
2362
+
2363
+ it_should_behave_like 'mathematical functions'
2364
+ end
2365
+
2366
+ describe 'Quadratic function' do
2367
+ before(:each) do
2368
+ @start_value = 100
2369
+ @end_value = 300
2370
+ @mid_value = 20
2371
+ @one_perc = (@end_value - @mid_value).abs / 30.0
2372
+ @o = Kamelopard::Functions::Quadratic.interpolate(@start_value, @end_value, 0.5, @mid_value)
2373
+ end
2374
+
2375
+ it_should_behave_like 'mathematical functions'
2376
+
2377
+ it 'includes the midpoint' do
2378
+ val_within_range @o, 0.5, @mid_value, @one_perc
2379
+ end
2380
+ end
2381
+
2382
+ describe 'Cubic function' do
2383
+ before(:each) do
2384
+ @start_value = 70
2385
+ @end_value = 15
2386
+ @x1 = 0.3
2387
+ @y1 = 20
2388
+ @x2 = 0.6
2389
+ @y2 = 25
2390
+ @one_perc = (@end_value - @start_value).abs / 30.0
2391
+ @o = Kamelopard::Functions::Cubic.interpolate(@start_value, @end_value, @x1, @y1, @x2, @y2)
2392
+ end
2393
+
2394
+ it_should_behave_like 'mathematical functions'
2395
+
2396
+ it 'includes the defining points' do
2397
+ val_within_range @o, @x1, @y1, @one_perc
2398
+ val_within_range @o, @x2, @y2, @one_perc
2399
+ end
2400
+ end
2401
+
2402
+ describe 'make_function_path' do
2403
+ it 'handles callback_value properly' do
2404
+ i = 0
2405
+ make_function_path(10,
2406
+ :latitude => 1,
2407
+ :altitude => 1,
2408
+ :heading => 1,
2409
+ :tilt => 1,
2410
+ :roll => 0,
2411
+ :show_placemarks => 1,
2412
+ :duration => 1,
2413
+ ) do |a, v|
2414
+ v[:callback_value].should == i - 1 if i > 0
2415
+ v[:callback_value] = i
2416
+ i = i + 1
2417
+ v
2418
+ end
2419
+ end
2420
+
2421
+ it 'pauses when told to' do
2422
+ clear_documents
2423
+ make_function_path( 2, :latitude => 1, :pause => 10 )
2424
+ doc = XML::Document.string(get_kml.to_s)
2425
+ doc.find("//gx:Wait/gx:duration/text()='10'", NS).should be_true
2426
+ end
2427
+
2428
+ it "handles coordinates correctly" do
2429
+ make_function_path(10, :latitude => Line.interpolate(0, 1)) do |i, h|
2430
+ h[:latitude].should == i/10.0
2431
+ h
2432
+ end
2433
+ end
2434
+
2435
+ it "handles altitudeMode and extrude correctly" do
2436
+ (v, pl) = make_function_path(10, :latitude => 10, :altitudeMode => :relativeToSeaFloor, :extrude => 1)
2437
+ pl.each do |p|
2438
+ p.geometry.extrude.should == 1
2439
+ p.altitudeMode.should == :relativeToSeaFloor
2440
+ end
2441
+ end
2442
+
2443
+ it "handles multidim correctly, and multidim overrides individual settings" do
2444
+ class TestMultiDim < Kamelopard::Functions::FunctionMultiDim
2445
+ def run_function(x)
2446
+ return [1, 1, 1, 1, 1]
2447
+ end
2448
+ end
2449
+
2450
+ a = Kamelopard.make_function_path(100,
2451
+ :altitudeMode => :relativeToGround, :tilt => 45, :show_placemarks => 1, :heading => 10,
2452
+ :multidim => [ [ TestMultiDim.new, [ :heading, :latitude, :longitude, nil, :altitude ] ] ]
2453
+ ) do |i, h|
2454
+ # "multidim overrides individual settings" means that even though
2455
+ # :heading shows up as an individual constant (10), it gets its
2456
+ # final value from the multidim it's also in. Therefore, its final
2457
+ # value is 1, from the TestMultiDim class.
2458
+ [:heading, :latitude, :longitude, :altitude].each { |s| h[s].should == 1 }
2459
+ h
2460
+ end
2461
+ end
2462
+
2463
+ it "yields properly to a code block, only after other assignments are complete" do
2464
+ pt = 0
2465
+ make_function_path(5, :latitude => 10, :longitude => 10 ) do |i, h|
2466
+ i.should == pt
2467
+ pt = pt + 1
2468
+ h[:latitude].should == 10
2469
+ h[:longitude].should == 10
2470
+ h
2471
+ end
2472
+ end
2473
+
2474
+ it 'returns placemark and view arrays' do
2475
+ (v, p) = make_function_path(10, :longitude => 10)
2476
+ v.each do |view|
2477
+ view.is_a?(Kamelopard::AbstractView).should be_true
2478
+ end
2479
+ p.each do |placemark|
2480
+ placemark.is_a?(Kamelopard::Placemark).should be_true
2481
+ end
2482
+ v.size.should == 10
2483
+ p.size.should == 10
2484
+ end
2485
+
2486
+ # Sample function:
2487
+ #make_function_path(10,
2488
+ # :latitude => Line.interpolate(38.8, 40.3),
2489
+ # :altitude => Line.interpolate(10000, 2000),
2490
+ # :heading => Line.interpolate(0, 90),
2491
+ # :tilt => Line.interpolate(40.0, 90),
2492
+ # :roll => 0,
2493
+ # :show_placemarks => 1,
2494
+ # :duration => Quadratic.interpolate(2.0, 4.0, 0.0, 1.0),
2495
+ #) do |a, v|
2496
+ # puts "callback here"
2497
+ # if v.has_key? :callback_value then
2498
+ # v[:callback_value] += 1
2499
+ # else
2500
+ # v[:pause] = 0.01
2501
+ # v[:callback_value] = 1
2502
+ # end
2503
+ # puts v[:callback_value]
2504
+ # v
2505
+ #end
2506
+
2507
+ # Sample with timestamp /timespan
2508
+ # require 'time'
2509
+ # (views, placemarks) = make_function_path(10,
2510
+ # :latitude => Line.interpolate(38.8, 40.3),
2511
+ # :altitude => Line.interpolate(10000, 2000),
2512
+ # :heading => Line.interpolate(0, 90),
2513
+ # :tilt => Line.interpolate(40.0, 90),
2514
+ # :roll => 0,
2515
+ # :show_placemarks => 1,
2516
+ # :when => l,
2517
+ # :duration => Quadratic.interpolate(2.0, 4.0, 0.0, 1.0),
2518
+ # ) do |a, v|
2519
+ # tm = begintime + v[:when] * interval
2520
+ # b = tm
2521
+ # e = tm + 36000
2522
+ # b = b.xmlschema() if Kml_format
2523
+ # e = e.xmlschema() if Kml_format
2524
+ # v.delete :when
2525
+ # v[:begin] = b
2526
+ # v[:end] = e
2527
+ # if v.has_key? :callback_value then
2528
+ # v[:callback_value] += 1
2529
+ # else
2530
+ # v[:pause] = 0.01
2531
+ # v[:callback_value] = 1
2532
+ # end
2533
+ # v
2534
+ # end
2535
+ end
2536
+
2537
+ describe 'helper functions' do
2538
+ before :each do
2539
+ @view1 = make_view_from( :latitude => 1, :longitude => 1 )
2540
+ @view2 = make_view_from( :latitude => 2, :longitude => 2 )
2541
+ end
2542
+
2543
+ it 'can get_document' do
2544
+ nm = 'test document'
2545
+ name_document nm
2546
+ get_document.name.should == nm
2547
+ end
2548
+
2549
+ it 'can set flyto_mode' do
2550
+ set_flyto_mode_to :smooth
2551
+ a = fly_to @view1
2552
+ a.mode.should == :smooth
2553
+ end
2554
+
2555
+ it 'toggle_balloon_for' do
2556
+ f = get_folder
2557
+ a = placemark 'place', :description => 'place', :geometry => point(1, 1), :kml_id => 'test_placemark'
2558
+ toggle_balloon_for a, 0
2559
+ toggle_balloon_for a, 1
2560
+ d = build_doc_from_node(get_document)
2561
+ d.find("//kml:Placemark[@targetId='test_placemark']").size.should == 2
2562
+ a = point(1, 1)
2563
+ # XXX Why doesn't this catch the exception?
2564
+ #toggle_balloon_for(a, 0).should raise_exception(RuntimeError)
2565
+ end
2566
+
2567
+ # NB! Commented out on the grounds that balloons suck and we hate them.
2568
+ # it 'hide_balloon_for' do
2569
+ # pending 'Need to write this'
2570
+ # end
2571
+ #
2572
+ # it 'show_balloon_for' do
2573
+ # pending 'Need to write this'
2574
+ # end
2575
+ #
2576
+ # it 'fade_balloon_for' do
2577
+ # pending 'Need to write this'
2578
+ # end
2579
+ #
2580
+ # it 'fade_out_balloon_for' do
2581
+ # pending 'Need to write this'
2582
+ # end
2583
+ #
2584
+ # it 'fade_in_balloon_for' do
2585
+ # pending 'Need to write this'
2586
+ # end
2587
+
2588
+ it 'has working point function' do
2589
+ p = point(10, 20, 30, :relativeToGround)
2590
+ p.longitude.should == 10
2591
+ p.latitude.should == 20
2592
+ p.altitude.should == 30
2593
+ p.altitudeMode.should == :relativeToGround
2594
+ end
2595
+
2596
+ it 'has working placemark function' do
2597
+ placemark('name').class.should == Kamelopard::Placemark
2598
+ end
2599
+
2600
+ it 'get_kml' do
2601
+ get_kml.class.should == XML::Document
2602
+ end
2603
+
2604
+ it 'has working clear_documents' do
2605
+ Kamelopard::Document.new 'a'
2606
+ Kamelopard::Document.new 'b'
2607
+ Kamelopard::Document.new 'c'
2608
+ clear_documents
2609
+ get_document.name.should == ''
2610
+ end
2611
+
2612
+ it 'get_kml_string' do
2613
+ clear_documents
2614
+ name_document 'a'
2615
+ get_folder << placemark('a placemark')
2616
+ get_kml.find_first('//Document/name').should_not be_nil
2617
+ get_kml.find_first('//Placemark/name').should_not be_nil
2618
+ clear_documents
2619
+ get_kml.find_first('//Document/name').should_not be_nil
2620
+ get_kml.find_first('//Placemark/name').should be_nil
2621
+ end
2622
+
2623
+ it 'pause' do
2624
+ pause 10, :kml_id => 1
2625
+ # XXX Hack! I have no idea why I can't just get_kml.find_first, but it doesn't work
2626
+ doc = XML::Document.string(get_kml.to_s)
2627
+ doc.find_first('//gx:Wait[@id=1]', NS).should_not be_nil
2628
+ end
2629
+
2630
+ it 'get_tour' do
2631
+ get_tour.class.should == Kamelopard::Tour
2632
+ end
2633
+
2634
+ it 'name_tour' do
2635
+ name_tour 'this is a tour'
2636
+ get_tour.name.should == 'this is a tour'
2637
+ end
2638
+
2639
+ it 'get_folder' do
2640
+ get_folder.class.should == Kamelopard::Folder
2641
+ end
2642
+
2643
+ it 'folder' do
2644
+ name_folder 'test'
2645
+ folder 'test2'
2646
+ get_folder.name.should == 'test2'
2647
+ end
2648
+
2649
+ it 'name_folder' do
2650
+ name_folder 'test'
2651
+ get_folder.name.should == 'test'
2652
+ end
2653
+
2654
+ it 'name_document' do
2655
+ name_document 'a'
2656
+ get_document.name.should == 'a'
2657
+ name_document 'b'
2658
+ get_document.name.should == 'b'
2659
+ end
2660
+
2661
+ # NB! Commented out on the grounds that no one actually uses zoom_out
2662
+ # it 'zoom_out' do
2663
+ # pending 'Need to write this'
2664
+ # end
2665
+
2666
+ it 'orbit' do
2667
+ d = Document.new 'orbit test'
2668
+ p = point(10, 10)
2669
+ orbit p, 100, 90, 0, 360, { :duration => 10, :already_there => 1 }
2670
+ doc = build_doc_from_node(d)
2671
+ doc.find('//gx:FlyTo').size.should == 10
2672
+ doc.find("//gx:FlyTo/kml:LookAt/kml:heading/text()='36'").should be_true
2673
+ doc.find("//gx:FlyTo/kml:LookAt/kml:heading/text()='37'").should be_false
2674
+ doc.find("//gx:FlyTo/kml:LookAt/kml:heading/text()='72'").should be_true
2675
+ orbit p, 100, 90, 0, 360, { :duration => 10 }
2676
+ doc = build_doc_from_node(d)
2677
+ doc.find('//gx:FlyTo').size.should == 21
2678
+ end
2679
+
2680
+ # NB! Sound cues are Windoze/Mac only. So they're not too useful for our Galaxies.
2681
+ # it 'sound_cue' do
2682
+ # s = sound_cue('href')
2683
+ # s.class.should == Kamelopard::SoundCue
2684
+ # s.href.should == 'href'
2685
+ # end
2686
+
2687
+ it 'set_prefix_to' do
2688
+ old_prefix = Kamelopard.id_prefix
2689
+ set_prefix_to 'random_prefix'
2690
+ p = point(10, 10)
2691
+ p.kml_id.should =~ /random_prefix/
2692
+ set_prefix_to old_prefix
2693
+ p = point(10, 10)
2694
+ p.kml_id =~ /\d/
2695
+ end
2696
+
2697
+ it 'write_kml_to' do
2698
+ filename = 'kamelopard_test.kml.tmp'
2699
+ name_folder 'test_writing'
2700
+ write_kml_to filename
2701
+ d = XML::Document.file filename
2702
+ d.find("//kml:Folder/kml:name/text()='test_writing'").should be_true
2703
+ end
2704
+
2705
+ it 'fade_overlay' do
2706
+ o = Kamelopard::ScreenOverlay.new({
2707
+ :href => 'test',
2708
+ :name => 'something',
2709
+ :size => xy,
2710
+ :rotation => 10,
2711
+ :overlayXY => xy,
2712
+ :screenXY => xy,
2713
+ :rotationXY => xy
2714
+ })
2715
+ fade_overlay o, false, :duration => 123
2716
+ d = build_doc_from_node get_document
2717
+ d.find("//gx:AnimatedUpdate[gx:duration/text()='123' and kml:Update/kml:Change/kml:ScreenOverlay[@targetId='#{o.kml_id}']]").should be_true
2718
+ end
2719
+
2720
+ # NB! Not really worth testing this unless it gets used with any frequency at all
2721
+ # it 'TelemetryProcessor.get_heading' do
2722
+ # pending 'Need to write this'
2723
+ # end
2724
+ #
2725
+ # it 'TelemetryProcessor.get_dist2' do
2726
+ # pending 'Need to write this'
2727
+ # end
2728
+ #
2729
+ # it 'TelemetryProcessor.get_dist3' do
2730
+ # pending 'Need to write this'
2731
+ # end
2732
+ #
2733
+ # it 'TelemetryProcessor.get_tilt' do
2734
+ # pending 'Need to write this'
2735
+ # end
2736
+ #
2737
+ # it 'TelemetryProcessor.get_roll' do
2738
+ # pending 'Need to write this'
2739
+ # end
2740
+ #
2741
+ # it 'TelemetryProcessor.fix_coord' do
2742
+ # pending 'Need to write this'
2743
+ # end
2744
+ #
2745
+ # it 'TelemetryProcessor.add_flyto' do
2746
+ # pending 'Need to write this'
2747
+ # end
2748
+ #
2749
+ # it 'TelemetryProcessor.options=' do
2750
+ # pending 'Need to write this'
2751
+ # end
2752
+ #
2753
+ # it 'TelemetryProcessor.normalize_points' do
2754
+ # pending 'Need to write this'
2755
+ # end
2756
+
2757
+ it 'tour_from_points' do
2758
+ pending 'Need to write this'
2759
+ end
2760
+
2761
+ it 'make_view_from' do
2762
+ def compare(hash, view)
2763
+ fields = {
2764
+ :begin => 1, :end => 1, :when => 1
2765
+ }
2766
+ hash.each do |k, val|
2767
+ if fields.has_key? k then
2768
+ if k == :when then
2769
+ view.timestamp.when.should == val
2770
+ else
2771
+ view.timespan.method(k).call.should == val
2772
+ end
2773
+ else
2774
+ view.method(k).call.should == val
2775
+ end
2776
+ end
2777
+ end
2778
+
2779
+ hash = {
2780
+ :latitude => 10,
2781
+ :longitude => 20,
2782
+ :altitude => 30,
2783
+ :altitudeMode => :absolute,
2784
+ :heading => 40,
2785
+ :tilt => 50,
2786
+ :roll => 60,
2787
+ :begin => '2013-01-01',
2788
+ :end => '2013-02-02'
2789
+ }
2790
+ view = make_view_from hash
2791
+ view.class.should == Kamelopard::Camera
2792
+ compare(hash, view)
2793
+
2794
+ [:begin, :end, :roll].each do |k| hash.delete k end
2795
+ hash.merge!({
2796
+ :when => '2013-03-03',
2797
+ :range => 1000
2798
+ })
2799
+ view = make_view_from hash
2800
+ view.class.should == Kamelopard::LookAt
2801
+ compare(hash, view)
2802
+ end
2803
+
2804
+ it 'screenoverlay works' do
2805
+ s = screenoverlay :rotation => xy
2806
+ s.class.should == Kamelopard::ScreenOverlay
2807
+ end
2808
+
2809
+ it 'xy' do
2810
+ xy.class.should == Kamelopard::XY
2811
+ end
2812
+
2813
+ define 'handles styles' do
2814
+ before :each do
2815
+ @l = labelstyle
2816
+ @ihref = 'test'
2817
+ @i = iconstyle @ihref
2818
+ @btext = 'text'
2819
+ @b = balloonstyle @btext
2820
+ @s = style :icon => @i, :label => @l, :balloon => @b
2821
+ end
2822
+
2823
+ it 'with iconstyle' do
2824
+ @i.class.should == Kamelopard::IconStyle
2825
+ @i.href.should == @ihref
2826
+ end
2827
+
2828
+ it 'with labelstyle' do
2829
+ @l.class.should == Kamelopard::LabelStyle
2830
+ end
2831
+
2832
+ it 'with balloonstyle' do
2833
+ @b.class.should == Kamelopard::BalloonStyle
2834
+ @b.text.should == @btext
2835
+ end
2836
+
2837
+ it 'with style' do
2838
+ @s.class.should == Kamelopard::Style
2839
+ @s.icon.should == @i
2840
+ @s.balloon.should == @b
2841
+ @s.label.should == @l
2842
+ end
2843
+ end
2844
+
2845
+ it 'look_at' do
2846
+ l = look_at @view1
2847
+ l.longitude.should == @view1.longitude
2848
+ end
2849
+
2850
+ it 'camera' do
2851
+ c = camera @view1
2852
+ c.longitude.should == @view1.longitude
2853
+ end
2854
+
2855
+ it 'fly_to' do
2856
+ f = fly_to @view1, :duration => 10
2857
+ f.class.should == Kamelopard::FlyTo
2858
+ f.duration.should == 10
2859
+ end
2860
+
2861
+ it 'each_placemark works correctly' do
2862
+ kml = %[<?xml version="1.0" encoding="UTF-8"?>
2863
+ <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
2864
+ <Document id="Document_3">
2865
+ <name/>
2866
+ <visibility>1</visibility>
2867
+ <open>0</open>
2868
+ <Folder id="Folder_4">
2869
+ <visibility>1</visibility>
2870
+ <open>0</open>
2871
+ <Placemark id="Placemark_2">
2872
+ <name>1</name>
2873
+ <visibility>1</visibility>
2874
+ <open>0</open>
2875
+ <Point id="Point_1">
2876
+ <coordinates>1.0, -23.0, 0</coordinates>
2877
+ <extrude>0</extrude>
2878
+ <altitudeMode>clampToGround</altitudeMode>
2879
+ </Point>
2880
+ </Placemark>
2881
+ <Placemark id="Placemark_6">
2882
+ <name>2</name>
2883
+ <visibility>1</visibility>
2884
+ <open>0</open>
2885
+ <Point id="Point_5">
2886
+ <coordinates>-164.0, -76.0, 0</coordinates>
2887
+ <extrude>0</extrude>
2888
+ <altitudeMode>clampToGround</altitudeMode>
2889
+ </Point>
2890
+ </Placemark>
2891
+ <Placemark id="Placemark_8">
2892
+ <name>3</name>
2893
+ <visibility>1</visibility>
2894
+ <open>0</open>
2895
+ <Point id="Point_7">
2896
+ <coordinates>-168.0, -18.0, 0</coordinates>
2897
+ <extrude>0</extrude>
2898
+ <altitudeMode>clampToGround</altitudeMode>
2899
+ </Point>
2900
+ </Placemark>
2901
+ </Folder>
2902
+ </Document>
2903
+ </kml>]
2904
+ placemarks = []
2905
+ each_placemark(XML::Document.string(kml)) do |p|
2906
+ placemarks << p
2907
+ end
2908
+ placemarks.size.should == 3
2909
+ end
2910
+
2911
+ it 'make_tour_index' do
2912
+ # Make sure there's some tour already
2913
+ %w[A B C].each do |i|
2914
+ Kamelopard::Tour.new "Tour #{i}"
2915
+ pause 10
2916
+ end
2917
+ make_tour_index nil, :kml_id => 'my_index'
2918
+ index_text = %{<html>
2919
+ <body>
2920
+ Something custom here.
2921
+ <ul><% @tours.each do |t| %>
2922
+ <li><a href="#<%= t.kml_id %>;flyto"></a></li>
2923
+ <% end %></ul>
2924
+ </body>
2925
+ </html>}
2926
+ make_tour_index index_text, :kml_id => 'my_index2'
2927
+ d = XML::Document.string(get_kml_string)
2928
+ ['', '2'].each do |i|
2929
+ d.find("//kml:ScreenOverlay[@id='my_index#{i}']").should be_true
2930
+ end
2931
+ d.find("//kml:ScreenOverlay[@id='my_index2' and contains(description, 'Something custom here')]").should be_true
2932
+ end
2933
+
2934
+ it 'show_hide_balloon' do
2935
+ pending 'Need to write this'
2936
+ end
2937
+
2938
+ it 'cdata' do
2939
+ a = cdata 'a'
2940
+ a.cdata?.should be_true
2941
+ end
2942
+
2943
+ it 'do_action' do
2944
+ pending 'Need to write this'
2945
+ end
2946
+
2947
+ it 'great_circle_distance' do
2948
+ pending 'Need to write this'
2949
+ end
2950
+
2951
+ it 'can get the document holder' do
2952
+ get_doc_holder.class.should == Kamelopard::DocumentHolder
2953
+ end
2954
+
2955
+ it 'can bounce' do
2956
+ get_doc_holder.delete_current_doc
2957
+ get_obj_child(get_document, 'Placemark').should be_nil
2958
+ get_obj_child(get_document, 'LookAt').should be_nil
2959
+
2960
+ get_doc_holder.delete_current_doc
2961
+ bounce(@view1, @view2, 10, 10)
2962
+ get_obj_child(get_document, 'Placemark').should be_nil
2963
+ get_kml.find_first('//LookAt').should_not be_nil
2964
+
2965
+ get_doc_holder.delete_current_doc
2966
+ bounce(@view1, @view2, 10, 10, :no_flyto => 1)
2967
+ get_obj_child(get_document, 'Placemark').should be_nil
2968
+ get_kml.find_first('//LookAt').should be_nil
2969
+
2970
+ get_doc_holder.delete_current_doc
2971
+ bounce(@view1, @view2, 10, 10, :show_placemarks => 1)
2972
+ get_kml.find_first('//Placemark').should_not be_nil
2973
+ end
2974
+ end
2975
+
2976
+ describe "splines" do
2977
+ it "build and run correctly" do
2978
+ require 'kamelopard/spline'
2979
+
2980
+ sp = Kamelopard::Functions::SplineFunction.new(5)
2981
+ sp.add_control_point [4,30,30,10000,234], 10
2982
+ sp.add_control_point [8,40,30,9000,234], 30
2983
+ sp.add_control_point [8,50,50,8000,234], 100
2984
+ sp.add_control_point [4,35,50,7000,234], 10
2985
+
2986
+ spline_result = sp.run_function(0.5)
2987
+ spline_result.size.should == 5
2988
+ spline_result.should respond_to(:[])
2989
+
2990
+ # a = Kamelopard.make_function_path(100,
2991
+ # :altitudeMode => :relativeToGround, :tilt => 45, :show_placemarks => 1,
2992
+ # :multidim => [ [ sp, [ nil, :latitude, :longitude, :altitude ] ] ]
2993
+ # )
2994
+ end
2995
+ end
2996
+
2997
+ describe "viewsplines" do
2998
+ pending "Write tests for ViewSplines"
2999
+ end