kamelopard 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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