/[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 1687 - (show annotations)
Fri Aug 29 10:02:16 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 18777 byte(s)
Add some missing parameters to projections. Proj complains about
them on windows but for some reason not on Linux.

* test/test_save.py (SaveSessionTest.testLayerProjection): Add
missing required projection parameters

* test/test_proj.py (TestProjFile.test): Add missing required
projection parameters

* test/test_load_0_8.py (TestLayerProjection.file_contents)
(TestLayerProjection.test): Add missing required projection
parameters and tests for them

* test/test_load.py (TestLayerProjection.file_contents)
(TestLayerProjection.test): Add missing required projection
parameters and tests for them

* test/test_layer.py (TestLayer.test_base_layer): Add missing
required projection parameters

1 # Copyright (c) 2002, 2003 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
37 import Thuban.Model.resource
38
39 class TestLayer(unittest.TestCase, support.FileTestMixin,
40 support.FloatComparisonMixin):
41
42 """Test cases for different layer (shape) types"""
43
44 def setUp(self):
45 """Create a session self.session and initialize self.layer to None"""
46 self.session = Session("Test session for %s" % self.__class__)
47 self.layer = None
48
49 def tearDown(self):
50 """Call the layer's Destroy method and set session and layer to None"""
51 self.session.Destroy()
52 self.session = None
53 if self.layer is not None:
54 self.layer.Destroy()
55 self.layer = None
56
57 def build_path(self, filename):
58 return os.path.join("..", "Data", "iceland", filename)
59
60 def open_shapefile(self, filename):
61 """Open and return a shapestore for filename in the iceland data set"""
62 return self.session.OpenShapefile(self.build_path(filename))
63
64 def test_base_layer(self):
65 layer = self.layer = BaseLayer("Test BaseLayer")
66 self.assertEquals(layer.Title(), "Test BaseLayer")
67 self.failUnless(layer.Visible())
68
69 # toggle visibility
70 layer.SetVisible(False)
71 self.failIf(layer.Visible())
72
73 layer.SetVisible(True)
74 self.failUnless(layer.Visible())
75
76 self.failIf(layer.HasClassification())
77 self.failIf(layer.HasShapes())
78
79 self.assertEquals(layer.GetProjection(), None)
80
81 # set/get projection
82 proj = Projection(["proj=utm", "zone=26", "ellps=clrk66"])
83
84 layer.SetProjection(proj)
85 self.failUnless(layer.GetProjection() is proj)
86
87 # __init__ with other arguments
88 layer = BaseLayer("Test BaseLayer", False, proj)
89 self.failIf(layer.Visible())
90 self.failUnless(layer.GetProjection() is proj)
91
92 def test_arc_layer(self):
93 """Test Layer with arc shapes"""
94 layer = self.layer = Layer("Test Layer",
95 self.open_shapefile("roads-line.shp"))
96 self.failUnless(layer.HasClassification())
97 self.failUnless(layer.HasShapes())
98 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
99 self.assertEquals(layer.NumShapes(), 839)
100 shape = layer.Shape(32)
101 self.assertPointListEquals(shape.Points(),
102 [[(-15.082174301147461, 66.27738189697265),
103 (-15.026350021362305, 66.27339172363281)]])
104 self.assertFloatSeqEqual(layer.BoundingBox(),
105 [-24.450359344482422, 63.426830291748047,
106 -13.55668830871582, 66.520111083984375])
107 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
108 self.assertEquals([s.ShapeID() for s in shapes],
109 [613, 726, 838])
110
111 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
112 [-15.082174301147461, 66.27339172363281,
113 -15.026350021362305, 66.27738189697265])
114
115 shape = layer.Shape(33)
116 self.assertPointListEquals(shape.Points(),
117 [[(-22.24850654602050, 66.30645751953125),
118 (-22.23273086547851, 66.29407501220703),
119 (-22.23158073425293, 66.2876892089843),
120 (-22.24631881713867, 66.27006530761718)]])
121
122 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32, 33]),
123 [-22.248506546020508, 66.270065307617188,
124 -15.026350021362305, 66.30645751953125])
125
126 self.assertEquals(layer.ShapesBoundingBox([]), None)
127 self.assertEquals(layer.ShapesBoundingBox(None), None)
128
129 def test_polygon_layer(self):
130 """Test Layer with polygon shapes"""
131 layer = self.layer = Layer("Test Layer",
132 self.open_shapefile("political.shp"))
133 self.failUnless(layer.HasClassification())
134 self.failUnless(layer.HasShapes())
135 self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
136 self.assertEquals(layer.NumShapes(), 156)
137 shape = layer.Shape(4)
138 self.assertPointListEquals(shape.Points(),
139 [[(-22.40639114379882, 64.714111328125),
140 (-22.41621208190918, 64.7160034179687),
141 (-22.40605163574218, 64.719200134277),
142 (-22.40639114379882, 64.714111328125)]])
143 self.assertFloatSeqEqual(layer.BoundingBox(),
144 [-24.546524047851562, 63.286754608154297,
145 -13.495815277099609, 66.563774108886719])
146 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1))
147 self.assertEquals([s.ShapeID() for s in shapes],
148 [91, 92, 144, 146, 148, 150, 152, 153])
149
150 def test_point_layer(self):
151 """Test Layer with point shapes"""
152 layer = self.layer = Layer("Test Layer",
153 self.open_shapefile("cultural_landmark-point.shp"))
154 self.failUnless(layer.HasClassification())
155 self.failUnless(layer.HasShapes())
156 self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
157 self.assertEquals(layer.NumShapes(), 34)
158 shape = layer.Shape(0)
159 self.assertPointListEquals(shape.Points(),
160 [[(-22.711074829101562, 66.36572265625)]])
161 self.assertFloatSeqEqual(layer.BoundingBox(),
162 [-23.806047439575195, 63.405960083007812,
163 -15.12291431427002, 66.36572265625])
164 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1))
165 self.assertEquals([s.ShapeID() for s in shapes],
166 [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
167
168 def test_point_layer_with_projection(self):
169 """Test Layer with point shapes and a projection"""
170 # We use mock data here so that we have precise control over the
171 # values
172 table = MemoryTable([("FOO", FIELDTYPE_STRING)], [("bla",)])
173 store = mockgeo.SimpleShapeStore(SHAPETYPE_POINT, [[[(10,10)]]], table)
174 layer = self.layer = Layer("Test Layer", store)
175
176 # Rotation by 45 degrees counter clockwise. This detects a bug
177 # in the ShapesInRegion method which transforms the bounding box
178 # by only transforming two opposite corners because they have
179 # the same x or y coordinates after application of the
180 # projection or its inverse.
181 proj = mockgeo.AffineProjection((1, 1, -1, 1, 0, 0))
182 layer.SetProjection(proj)
183
184 self.assertEquals(layer.BoundingBox(), (10, 10, 10, 10))
185 self.assertEquals(layer.LatLongBoundingBox(), (10.0, 0.0, 10.0, 0.0))
186 shapes = layer.ShapesInRegion((0, 0, 20, 20))
187 self.assertEquals([s.ShapeID() for s in shapes], [0])
188
189 def test_empty_layer(self):
190 """Test Layer with empty shape file"""
191 # create an empty shape file
192 shapefilename = self.temp_file_name("layer_empty.shp")
193 shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
194 shp.close()
195 # create an empty DBF file too because Thuban can't cope yet
196 # with missing DBF file.
197 dbffilename = self.temp_file_name("layer_empty.dbf")
198 dbf = dbflib.create(dbffilename)
199 dbf.add_field("NAME", dbflib.FTString, 20, 0)
200
201 # Now try to open it.
202 layer = self.layer = Layer("Empty Layer",
203 self.session.OpenShapefile(shapefilename))
204 self.assertEquals(layer.BoundingBox(), None)
205 self.assertEquals(layer.LatLongBoundingBox(), None)
206 self.assertEquals(layer.NumShapes(), 0)
207
208 def test_get_field_type(self):
209 """Test Layer.GetFieldType()"""
210 layer = self.layer = Layer("Test Layer",
211 self.open_shapefile("roads-line.shp"))
212 self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
213 self.assertEquals(layer.GetFieldType("non existing"), None)
214
215 def test_raster_layer(self):
216 if not Thuban.Model.resource.has_gdal_support():
217 raise support.SkipTest("No gdal support")
218
219 filename = self.build_path("island.tif")
220 layer = RasterLayer("Test RasterLayer", filename)
221 self.failIf(layer.HasClassification())
222 self.failIf(layer.HasShapes())
223 self.assertEquals(layer.GetImageFilename(), os.path.abspath(filename))
224 self.assertFloatSeqEqual(layer.BoundingBox(),
225 [-24.5500000, 63.2833330,
226 -13.4916670, 66.5666670])
227 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
228 [-24.5500000, 63.2833330,
229 -13.4916670, 66.5666670])
230
231 def test_derived_store(self):
232 """Test layer with derived store"""
233 layer = self.layer = Layer("Test Layer",
234 self.open_shapefile("roads-line.shp"))
235 try:
236 store = layer.ShapeStore()
237 derived = DerivedShapeStore(store, store.Table())
238 layer.SetShapeStore(derived)
239 self.assert_(layer.ShapeStore() is derived)
240
241 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
242 self.assertEquals(layer.NumShapes(), 839)
243 shape = layer.Shape(32)
244 self.assertPointListEquals(shape.Points(),
245 [[(-15.082174301147, 66.277381896972),
246 (-15.026350021362, 66.273391723632)]])
247 self.assertFloatSeqEqual(layer.BoundingBox(),
248 [-24.450359344482422, 63.426830291748047,
249 -13.55668830871582, 66.520111083984375])
250 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
251 self.assertEquals([s.ShapeID() for s in shapes],
252 [613, 726, 838])
253
254 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
255 [-15.082174301147461, 66.27339172363281,
256 -15.026350021362305, 66.27738189697265])
257
258 finally:
259 store = derived = None
260
261
262 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
263
264 def setUp(self):
265 """Create a layer with a classification as self.layer"""
266 self.clear_messages()
267 self.session = Session("Test session for %s" % self.__class__)
268 self.shapefilename = os.path.join("..", "Data", "iceland",
269 "cultural_landmark-point.dbf")
270 self.store = self.session.OpenShapefile(self.shapefilename)
271 self.layer = Layer("test layer", self.store)
272 self.classification = Classification()
273 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
274 self.layer.SetClassificationColumn("CLPTLABEL")
275 self.layer.SetClassification(self.classification)
276 self.layer.UnsetModified()
277 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
278 self.subscribe_with_params,
279 LAYER_SHAPESTORE_REPLACED)
280 self.layer.Subscribe(LAYER_CHANGED,
281 self.subscribe_with_params, LAYER_CHANGED)
282
283 def tearDown(self):
284 self.clear_messages()
285 self.layer.Destroy()
286 self.session.Destroy()
287 self.session = self.layer = self.store = self.classification = None
288
289 def test_sanity(self):
290 """SetShapeStoreTests sanity check
291
292 Test the initial state of the test case instances after setUp.
293 """
294 cls = self.layer.GetClassification()
295 self.assert_(cls is self.classification)
296 field = self.layer.GetClassificationColumn()
297 self.assertEquals(field, "CLPTLABEL")
298 self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
299 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
300 self.failIf(self.layer.WasModified())
301
302 def test_set_shape_store_modified_flag(self):
303 """Test whether Layer.SetShapeStore() sets the modified flag"""
304 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
305 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
306 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
307
308 self.assert_(self.layer.WasModified())
309
310 def test_set_shape_store_different_field_name(self):
311 """Test Layer.SetShapeStore() with different column name"""
312 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
313 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
314 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
315 # The classification should contain only the default group now.
316 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
317 self.check_messages([(self.layer, LAYER_CHANGED),
318 (self.layer, LAYER_SHAPESTORE_REPLACED)])
319
320 def test_set_shape_store_same_field(self):
321 """Test Layer.SetShapeStore() with same column name and type"""
322 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
323 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
324 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
325 # The classification should be the same as before
326 self.assert_(self.layer.GetClassification() is self.classification)
327 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
328
329 def test_set_shape_store_same_field_different_type(self):
330 """Test Layer.SetShapeStore() with same column name but different type
331 """
332 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
333 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
334 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
335 # The classification should contain only the default group now.
336 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
337 self.check_messages([(self.layer, LAYER_CHANGED),
338 (self.layer, LAYER_SHAPESTORE_REPLACED)])
339
340
341 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
342
343 """Test cases for Layer method that modify the layer.
344 """
345
346 def setUp(self):
347 """Clear the list of received messages and create a layer and a session
348
349 The layer is bound to self.layer and the session to self.session.
350 """
351 self.clear_messages()
352 self.session = Session("Test session for %s" % self.__class__)
353 filename = os.path.join("..", "Data", "iceland", "political.shp")
354 self.layer = Layer("Test Layer",
355 self.session.OpenShapefile(filename))
356 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
357 LAYER_LEGEND_CHANGED)
358 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
359 self.subscribe_with_params,
360 LAYER_VISIBILITY_CHANGED)
361 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
362 LAYER_CHANGED)
363
364 def tearDown(self):
365 """Clear the list of received messages and explictly destroy self.layer
366 """
367 self.layer.Destroy()
368 self.layer = None
369 self.session.Destroy()
370 self.session = None
371 self.clear_messages()
372
373 def test_sanity(self):
374 """TestLayerModification Sanity Checks"""
375 # test default settings
376 self.failIf(self.layer.WasModified())
377 self.assertEquals(self.layer.Visible(), 1)
378 # no messages should have been produced
379 self.check_messages([])
380
381 def test_visibility(self):
382 """Test Layer visibility"""
383 self.layer.SetVisible(0)
384 self.assertEquals(self.layer.Visible(), 0)
385 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
386
387 # currently, modifying the visibility doesn't count as changing
388 # the layer.
389 self.failIf(self.layer.WasModified())
390
391 def test_set_classification(self):
392 """Test Layer.SetClassification"""
393 classification = Classification()
394 classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
395
396 self.layer.SetClassification(classification)
397 self.layer.SetClassificationColumn("AREA")
398
399 self.check_messages([(self.layer, LAYER_CHANGED),
400 (self.layer, LAYER_CHANGED)])
401 self.failUnless(self.layer.WasModified())
402
403 self.clear_messages()
404 self.layer.UnsetModified()
405
406 # change only the classification column. This should issue a
407 # LAYER_CHANGED message as well.
408 self.layer.SetClassificationColumn("PERIMETER")
409
410 self.check_messages([(self.layer, LAYER_CHANGED)])
411 self.failUnless(self.layer.WasModified())
412
413
414 #
415 # the tree info now contains Color objects which are difficult to test
416 #
417 # def test_tree_info(self):
418 # """Test Layer.TreeInfo"""
419 # self.assertEquals(self.layer.TreeInfo(),
420 # ("Layer 'Test Layer'",
421 # ['Shown',
422 # 'Shapes: 156',
423 # ('Extent (lat-lon):'
424 # ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
425 # 'Shapetype: Polygon',
426 # 'Fill: None',
427 # 'Outline: (0.000, 0.000, 0.000)']))
428
429
430 if __name__ == "__main__":
431 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