/[thuban]/branches/WIP-pyshapelib-bramz/test/test_layer.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/test/test_layer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2587 - (show annotations)
Wed Mar 23 15:30:27 2005 UTC (19 years, 11 months ago) by jonathan
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 21901 byte(s)
Add support for adjusting the opacity of a raster layer.

1 # Copyright (c) 2002, 2003, 2004 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with Thuban for details.
7
8 """
9 Test the Layer class
10 """
11
12 __version__ = "$Revision$"
13 # $Source$
14 # $Id$
15
16 import os
17 import unittest
18
19 import mockgeo
20 import support
21 support.initthuban()
22
23 import shapelib
24 import dbflib
25
26 from Thuban.Model.session import Session
27 from Thuban.Model.layer import BaseLayer, Layer, RasterLayer
28 from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
29 from Thuban.Model.messages import LAYER_LEGEND_CHANGED, \
30 LAYER_VISIBILITY_CHANGED, LAYER_SHAPESTORE_REPLACED, LAYER_CHANGED
31 from Thuban.Model.table import FIELDTYPE_DOUBLE, FIELDTYPE_STRING, MemoryTable
32 from Thuban.Model.proj import Projection
33 from Thuban.Model.data import DerivedShapeStore
34 from Thuban.Model.classification import Classification, ClassGroupSingleton, \
35 ClassGroupRange
36 from Thuban.Model.color import Color
37
38 import Thuban.Model.resource
39
40 class TestLayer(unittest.TestCase, support.FileTestMixin,
41 support.FloatComparisonMixin):
42
43 """Test cases for different layer (shape) types"""
44
45 def setUp(self):
46 """Create a session self.session and initialize self.layer to None"""
47 self.session = Session("Test session for %s" % self.__class__)
48 self.layer = None
49
50 def tearDown(self):
51 """Call the layer's Destroy method and set session and layer to None"""
52 self.session.Destroy()
53 self.session = None
54 if self.layer is not None:
55 self.layer.Destroy()
56 self.layer = None
57
58 def build_path(self, filename):
59 return os.path.join("..", "Data", "iceland", filename)
60
61 def open_shapefile(self, filename):
62 """Open and return a shapestore for filename in the iceland data set"""
63 return self.session.OpenShapefile(self.build_path(filename))
64
65 def test_base_layer(self):
66 layer = self.layer = BaseLayer("Test BaseLayer")
67 self.assertEquals(layer.Title(), "Test BaseLayer")
68 self.failUnless(layer.Visible())
69
70 # toggle visibility
71 layer.SetVisible(False)
72 self.failIf(layer.Visible())
73
74 layer.SetVisible(True)
75 self.failUnless(layer.Visible())
76
77 self.failIf(layer.HasClassification())
78 self.failIf(layer.HasShapes())
79
80 self.assertEquals(layer.GetProjection(), None)
81
82 # set/get projection
83 proj = Projection(["proj=utm", "zone=26", "ellps=clrk66"])
84
85 layer.SetProjection(proj)
86 self.failUnless(layer.GetProjection() is proj)
87
88 # __init__ with other arguments
89 layer = BaseLayer("Test BaseLayer", False, proj)
90 self.failIf(layer.Visible())
91 self.failUnless(layer.GetProjection() is proj)
92
93 def test_arc_layer(self):
94 """Test Layer with arc shapes"""
95 layer = self.layer = Layer("Test Layer",
96 self.open_shapefile("roads-line.shp"))
97 self.failUnless(layer.HasClassification())
98 self.failUnless(layer.HasShapes())
99 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
100 self.assertEquals(layer.NumShapes(), 839)
101 shape = layer.Shape(32)
102 self.assertPointListEquals(shape.Points(),
103 [[(-15.082174301147461, 66.27738189697265),
104 (-15.026350021362305, 66.27339172363281)]])
105 self.assertFloatSeqEqual(layer.BoundingBox(),
106 [-24.450359344482422, 63.426830291748047,
107 -13.55668830871582, 66.520111083984375])
108 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
109 self.assertEquals([s.ShapeID() for s in shapes],
110 [613, 726, 838])
111
112 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
113 [-15.082174301147461, 66.27339172363281,
114 -15.026350021362305, 66.27738189697265])
115
116 shape = layer.Shape(33)
117 self.assertPointListEquals(shape.Points(),
118 [[(-22.24850654602050, 66.30645751953125),
119 (-22.23273086547851, 66.29407501220703),
120 (-22.23158073425293, 66.2876892089843),
121 (-22.24631881713867, 66.27006530761718)]])
122
123 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32, 33]),
124 [-22.248506546020508, 66.270065307617188,
125 -15.026350021362305, 66.30645751953125])
126
127 self.assertEquals(layer.ShapesBoundingBox([]), None)
128 self.assertEquals(layer.ShapesBoundingBox(None), None)
129
130 def test_polygon_layer(self):
131 """Test Layer with polygon shapes"""
132 layer = self.layer = Layer("Test Layer",
133 self.open_shapefile("political.shp"))
134 self.failUnless(layer.HasClassification())
135 self.failUnless(layer.HasShapes())
136 self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
137 self.assertEquals(layer.NumShapes(), 156)
138 shape = layer.Shape(4)
139 self.assertPointListEquals(shape.Points(),
140 [[(-22.40639114379882, 64.714111328125),
141 (-22.41621208190918, 64.7160034179687),
142 (-22.40605163574218, 64.719200134277),
143 (-22.40639114379882, 64.714111328125)]])
144 self.assertFloatSeqEqual(layer.BoundingBox(),
145 [-24.546524047851562, 63.286754608154297,
146 -13.495815277099609, 66.563774108886719])
147 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1))
148 self.assertEquals([s.ShapeID() for s in shapes],
149 [91, 92, 144, 146, 148, 150, 152, 153])
150
151 def test_point_layer(self):
152 """Test Layer with point shapes"""
153 layer = self.layer = Layer("Test Layer",
154 self.open_shapefile("cultural_landmark-point.shp"))
155 self.failUnless(layer.HasClassification())
156 self.failUnless(layer.HasShapes())
157 self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
158 self.assertEquals(layer.NumShapes(), 34)
159 shape = layer.Shape(0)
160 self.assertPointListEquals(shape.Points(),
161 [[(-22.711074829101562, 66.36572265625)]])
162 self.assertFloatSeqEqual(layer.BoundingBox(),
163 [-23.806047439575195, 63.405960083007812,
164 -15.12291431427002, 66.36572265625])
165 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1))
166 self.assertEquals([s.ShapeID() for s in shapes],
167 [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
168
169 def test_arc_layer_with_projection(self):
170 """Test Layer with point shapes and a projection"""
171 # We use mock data here so that we have precise control over the
172 # values
173 table = MemoryTable([("FOO", FIELDTYPE_STRING)], [("bla",)])
174 store = mockgeo.SimpleShapeStore(SHAPETYPE_ARC,
175 [[[(9884828.7209840547, 5607720.9774499247),
176 (11298336.04640449, 9287823.2044059951)]]],
177 table)
178 layer = self.layer = Layer("Test Layer", store)
179
180 proj = Projection(["proj=lcc", "lon_0=0", "lat_1=20n", "lat_2=60n",
181 "ellps=clrk66"])
182 layer.SetProjection(proj)
183
184 self.assertFloatSeqEqual(layer.BoundingBox(),
185 (9884828.7209840547, 5607720.9774499247,
186 11298336.04640449, 9287823.2044059951))
187 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
188 (90.0, -8.90043373, 120, 11.1616263))
189 shapes = layer.ShapesInRegion((100, -10, 150, +10))
190 self.assertEquals([s.ShapeID() for s in shapes], [0])
191 self.assertFloatSeqEqual(layer.ShapesBoundingBox([0]),
192 (90.0, -8.90043373, 120, 11.1616263))
193
194 self.assertFloatSeqEqual(layer.ClipBoundingBox((-180, -6, 100, +120)),
195 (90.0, -6, 100, 11.1616263))
196 shapes = layer.ShapesInRegion((-180, -170, 200, +120))
197 self.assertEquals([s.ShapeID() for s in shapes],[0])
198
199 def test_empty_layer(self):
200 """Test Layer with empty shape file"""
201 # create an empty shape file
202 shapefilename = self.temp_file_name("layer_empty.shp")
203 shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
204 shp.close()
205 # create an empty DBF file too because Thuban can't cope yet
206 # with missing DBF file.
207 dbffilename = self.temp_file_name("layer_empty.dbf")
208 dbf = dbflib.create(dbffilename)
209 dbf.add_field("NAME", dbflib.FTString, 20, 0)
210 dbf.close()
211
212 # Now try to open it.
213 layer = self.layer = Layer("Empty Layer",
214 self.session.OpenShapefile(shapefilename))
215 self.assertEquals(layer.BoundingBox(), None)
216 self.assertEquals(layer.LatLongBoundingBox(), None)
217 self.assertEquals(layer.NumShapes(), 0)
218
219 def test_get_field_type(self):
220 """Test Layer.GetFieldType()"""
221 layer = self.layer = Layer("Test Layer",
222 self.open_shapefile("roads-line.shp"))
223 self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
224 self.assertEquals(layer.GetFieldType("non existing"), None)
225
226 def test_raster_layer(self):
227 if not Thuban.Model.resource.has_gdal_support():
228 raise support.SkipTest("No gdal support")
229
230 filename = self.build_path("island.tif")
231 layer = RasterLayer("Test RasterLayer", filename)
232 self.failIf(layer.HasClassification())
233 self.failIf(layer.HasShapes())
234 self.assertEquals(layer.MaskType(), layer.MASK_BIT)
235 self.assertEquals(layer.GetImageFilename(), os.path.abspath(filename))
236 self.assertFloatSeqEqual(layer.BoundingBox(),
237 [-24.5500000, 63.2833330,
238 -13.4916670, 66.5666670])
239 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
240 [-24.5500000, 63.2833330,
241 -13.4916670, 66.5666670])
242
243 info = layer.ImageInfo()
244 self.failIf(info is None)
245 self.failUnless(info.has_key("nBands"))
246 self.failUnless(info.has_key("Size"))
247 self.failUnless(info.has_key("Driver"))
248 self.failUnless(info.has_key("BandData"))
249
250 self.assertEquals(info["nBands"], 1)
251 self.assertEquals(info["Size"], (5002, 394))
252 self.assertEquals(info["Driver"], "GTiff")
253 self.assertEquals(info["BandData"], [(0.0, 140.0)])
254
255 def test_derived_store(self):
256 """Test layer with derived store"""
257 layer = self.layer = Layer("Test Layer",
258 self.open_shapefile("roads-line.shp"))
259 try:
260 store = layer.ShapeStore()
261 derived = DerivedShapeStore(store, store.Table())
262 layer.SetShapeStore(derived)
263 self.assert_(layer.ShapeStore() is derived)
264
265 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
266 self.assertEquals(layer.NumShapes(), 839)
267 shape = layer.Shape(32)
268 self.assertPointListEquals(shape.Points(),
269 [[(-15.082174301147, 66.277381896972),
270 (-15.026350021362, 66.273391723632)]])
271 self.assertFloatSeqEqual(layer.BoundingBox(),
272 [-24.450359344482422, 63.426830291748047,
273 -13.55668830871582, 66.520111083984375])
274 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
275 self.assertEquals([s.ShapeID() for s in shapes],
276 [613, 726, 838])
277
278 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
279 [-15.082174301147461, 66.27339172363281,
280 -15.026350021362305, 66.27738189697265])
281
282 finally:
283 store = derived = None
284
285
286 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
287
288 def setUp(self):
289 """Create a layer with a classification as self.layer"""
290 self.clear_messages()
291 self.session = Session("Test session for %s" % self.__class__)
292 self.shapefilename = os.path.join("..", "Data", "iceland",
293 "cultural_landmark-point.dbf")
294 self.store = self.session.OpenShapefile(self.shapefilename)
295 self.layer = Layer("test layer", self.store)
296 self.classification = Classification()
297 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
298 self.layer.SetClassificationColumn("CLPTLABEL")
299 self.layer.SetClassification(self.classification)
300 self.layer.UnsetModified()
301 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
302 self.subscribe_with_params,
303 LAYER_SHAPESTORE_REPLACED)
304 self.layer.Subscribe(LAYER_CHANGED,
305 self.subscribe_with_params, LAYER_CHANGED)
306
307 def tearDown(self):
308 self.clear_messages()
309 self.layer.Destroy()
310 self.session.Destroy()
311 self.session = self.layer = self.store = self.classification = None
312
313 def test_sanity(self):
314 """SetShapeStoreTests sanity check
315
316 Test the initial state of the test case instances after setUp.
317 """
318 cls = self.layer.GetClassification()
319 self.assert_(cls is self.classification)
320 field = self.layer.GetClassificationColumn()
321 self.assertEquals(field, "CLPTLABEL")
322 self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
323 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
324 self.failIf(self.layer.WasModified())
325
326 def test_set_shape_store_modified_flag(self):
327 """Test whether Layer.SetShapeStore() sets the modified flag"""
328 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
329 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
330 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
331
332 self.assert_(self.layer.WasModified())
333
334 def test_set_shape_store_different_field_name(self):
335 """Test Layer.SetShapeStore() with different column name"""
336 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
337 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
338 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
339 # The classification should contain only the default group now.
340 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
341 self.check_messages([(self.layer, LAYER_CHANGED),
342 (self.layer, LAYER_SHAPESTORE_REPLACED)])
343
344 def test_set_shape_store_same_field(self):
345 """Test Layer.SetShapeStore() with same column name and type"""
346 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
347 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
348 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
349 # The classification should be the same as before
350 self.assert_(self.layer.GetClassification() is self.classification)
351 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
352
353 def test_set_shape_store_same_field_different_type(self):
354 """Test Layer.SetShapeStore() with same column name but different type
355 """
356 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
357 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
358 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
359 # The classification should contain only the default group now.
360 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
361 self.check_messages([(self.layer, LAYER_CHANGED),
362 (self.layer, LAYER_SHAPESTORE_REPLACED)])
363
364
365 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
366
367 """Test cases for Layer method that modify the layer.
368 """
369
370 def setUp(self):
371 """Clear the list of received messages and create a layer and a session
372
373 The layer is bound to self.layer and the session to self.session.
374 """
375 self.clear_messages()
376 self.session = Session("Test session for %s" % self.__class__)
377 self.filename = os.path.join("..", "Data", "iceland", "political.shp")
378 self.layer = Layer("Test Layer",
379 self.session.OpenShapefile(self.filename))
380 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
381 LAYER_LEGEND_CHANGED)
382 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
383 self.subscribe_with_params,
384 LAYER_VISIBILITY_CHANGED)
385 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
386 LAYER_CHANGED)
387
388 def tearDown(self):
389 """Clear the list of received messages and explictly destroy self.layer
390 """
391 self.layer.Destroy()
392 self.layer = None
393 self.session.Destroy()
394 self.session = None
395 self.clear_messages()
396
397 def build_path(self, filename):
398 return os.path.join("..", "Data", "iceland", filename)
399
400 def test_sanity(self):
401 """TestLayerModification Sanity Checks"""
402 # test default settings
403 self.failIf(self.layer.WasModified())
404 self.assertEquals(self.layer.Visible(), 1)
405 # no messages should have been produced
406 self.check_messages([])
407
408 def test_visibility(self):
409 """Test Layer visibility"""
410 self.layer.SetVisible(0)
411 self.assertEquals(self.layer.Visible(), 0)
412 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
413
414 # currently, modifying the visibility doesn't count as changing
415 # the layer.
416 self.failIf(self.layer.WasModified())
417
418 def test_set_classification(self):
419 """Test Layer.SetClassification"""
420 classification = Classification()
421 classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
422
423 self.layer.SetClassification(classification)
424 self.layer.SetClassificationColumn("AREA")
425
426 self.check_messages([(self.layer, LAYER_CHANGED),
427 (self.layer, LAYER_CHANGED)])
428 self.failUnless(self.layer.WasModified())
429
430 self.clear_messages()
431 self.layer.UnsetModified()
432
433 # change only the classification column. This should issue a
434 # LAYER_CHANGED message as well.
435 self.layer.SetClassificationColumn("PERIMETER")
436
437 self.check_messages([(self.layer, LAYER_CHANGED)])
438 self.failUnless(self.layer.WasModified())
439
440
441 def test_tree_info(self):
442 """Test Layer.TreeInfo"""
443 self.assertEquals(self.layer.TreeInfo(),
444 ("Layer 'Test Layer'",
445 ['Filename: %s' % os.path.abspath(self.filename),
446 'Shown',
447 'Shapes: 156',
448 'Extent (lat-lon): (-24.5465, 63.2868, -13.4958, 66.5638)',
449 'Shapetype: Polygon',
450 self.layer.GetClassification()]))
451
452 def test_raster_layer(self):
453 if not Thuban.Model.resource.has_gdal_support():
454 raise support.SkipTest("No gdal support")
455
456
457 filename = self.build_path("island.tif")
458 layer = RasterLayer("Test RasterLayer", filename)
459
460 layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
461 LAYER_CHANGED)
462
463 self.assertEquals(layer.MaskType(), layer.MASK_BIT)
464
465 layer.SetMaskType(layer.MASK_NONE)
466 self.failIf(layer.MaskType() != layer.MASK_NONE)
467 self.check_messages([(layer, LAYER_CHANGED)])
468 self.clear_messages()
469
470 layer.SetMaskType(layer.MASK_NONE)
471 self.failIf(layer.MaskType() != layer.MASK_NONE)
472 self.check_messages([])
473 self.clear_messages()
474
475 layer.SetMaskType(layer.MASK_BIT)
476 self.failIf(layer.MaskType() != layer.MASK_BIT)
477 self.check_messages([(layer, LAYER_CHANGED)])
478 self.clear_messages()
479
480 layer.SetMaskType(layer.MASK_BIT)
481 self.failIf(layer.MaskType() != layer.MASK_BIT)
482 self.check_messages([])
483 self.clear_messages()
484
485 layer.SetMaskType(layer.MASK_ALPHA)
486 self.failIf(layer.MaskType() != layer.MASK_ALPHA)
487
488 layer.SetOpacity(0)
489 self.assertEquals(layer.Opacity(), 0)
490 layer.SetOpacity(0.5)
491 self.assertEquals(layer.Opacity(), 0.5)
492
493 self.clear_messages()
494 layer.SetOpacity(1)
495 self.assertEquals(layer.Opacity(), 1)
496 self.check_messages([(layer, LAYER_CHANGED)])
497 self.clear_messages()
498
499 self.assertRaises(ValueError, layer.SetOpacity, -0.1)
500 self.assertRaises(ValueError, layer.SetOpacity, 1.1)
501
502 layer.SetMaskType(layer.MASK_NONE)
503 self.clear_messages()
504 self.assertEquals(layer.Opacity(), 1)
505 self.check_messages([])
506 self.clear_messages()
507
508 self.assertRaises(ValueError, layer.SetMaskType, -1)
509 self.assertRaises(ValueError, layer.SetMaskType, 4)
510
511
512 if __name__ == "__main__":
513 support.run_tests()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26