/[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 1983 - (show annotations)
Thu Nov 27 15:57:23 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 18998 byte(s)
* Thuban/Model/layer.py (Layer.LatLongBoundingBox)
(Layer.ShapesBoundingBox, RasterLayer.LatLongBoundingBox): Use the
new InverseBBox method to determine the unprojected bounding box
(Layer.ShapesInRegion): Use the ForwardBBox method to project the
bbox.

* test/test_layer.py (TestLayer.test_point_layer_with_projection):
Removed.
(TestLayer.test_arc_layer_with_projection): New. This test is
better able to test whether bounding boxes are projected correctly
than test_point_layer_with_projection

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_arc_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_ARC,
174 [[[(9884848.1401601825, 5607709.9111020016),
175 (11298371.027199602, 9287809.2948032897)]]],
176 table)
177 layer = self.layer = Layer("Test Layer", store)
178
179 proj = Projection(["proj=lcc", "lon_0=0", "lat_1=20n", "lat_2=60n"])
180 layer.SetProjection(proj)
181
182 self.assertFloatSeqEqual(layer.BoundingBox(),
183 (9884848.1401601825, 5607709.9111020016,
184 11298371.027199602, 9287809.2948032897))
185 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
186 (90.0, -8.899852, 120, 11.16092))
187 shapes = layer.ShapesInRegion((100, -10, 150, +10))
188 self.assertEquals([s.ShapeID() for s in shapes], [0])
189 self.assertFloatSeqEqual(layer.ShapesBoundingBox([0]),
190 (90.0, -8.899852, 120, 11.16092))
191
192 def test_empty_layer(self):
193 """Test Layer with empty shape file"""
194 # create an empty shape file
195 shapefilename = self.temp_file_name("layer_empty.shp")
196 shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
197 shp.close()
198 # create an empty DBF file too because Thuban can't cope yet
199 # with missing DBF file.
200 dbffilename = self.temp_file_name("layer_empty.dbf")
201 dbf = dbflib.create(dbffilename)
202 dbf.add_field("NAME", dbflib.FTString, 20, 0)
203 dbf.close()
204
205 # Now try to open it.
206 layer = self.layer = Layer("Empty Layer",
207 self.session.OpenShapefile(shapefilename))
208 self.assertEquals(layer.BoundingBox(), None)
209 self.assertEquals(layer.LatLongBoundingBox(), None)
210 self.assertEquals(layer.NumShapes(), 0)
211
212 def test_get_field_type(self):
213 """Test Layer.GetFieldType()"""
214 layer = self.layer = Layer("Test Layer",
215 self.open_shapefile("roads-line.shp"))
216 self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
217 self.assertEquals(layer.GetFieldType("non existing"), None)
218
219 def test_raster_layer(self):
220 if not Thuban.Model.resource.has_gdal_support():
221 raise support.SkipTest("No gdal support")
222
223 filename = self.build_path("island.tif")
224 layer = RasterLayer("Test RasterLayer", filename)
225 self.failIf(layer.HasClassification())
226 self.failIf(layer.HasShapes())
227 self.assertEquals(layer.GetImageFilename(), os.path.abspath(filename))
228 self.assertFloatSeqEqual(layer.BoundingBox(),
229 [-24.5500000, 63.2833330,
230 -13.4916670, 66.5666670])
231 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
232 [-24.5500000, 63.2833330,
233 -13.4916670, 66.5666670])
234
235 def test_derived_store(self):
236 """Test layer with derived store"""
237 layer = self.layer = Layer("Test Layer",
238 self.open_shapefile("roads-line.shp"))
239 try:
240 store = layer.ShapeStore()
241 derived = DerivedShapeStore(store, store.Table())
242 layer.SetShapeStore(derived)
243 self.assert_(layer.ShapeStore() is derived)
244
245 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
246 self.assertEquals(layer.NumShapes(), 839)
247 shape = layer.Shape(32)
248 self.assertPointListEquals(shape.Points(),
249 [[(-15.082174301147, 66.277381896972),
250 (-15.026350021362, 66.273391723632)]])
251 self.assertFloatSeqEqual(layer.BoundingBox(),
252 [-24.450359344482422, 63.426830291748047,
253 -13.55668830871582, 66.520111083984375])
254 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
255 self.assertEquals([s.ShapeID() for s in shapes],
256 [613, 726, 838])
257
258 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
259 [-15.082174301147461, 66.27339172363281,
260 -15.026350021362305, 66.27738189697265])
261
262 finally:
263 store = derived = None
264
265
266 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
267
268 def setUp(self):
269 """Create a layer with a classification as self.layer"""
270 self.clear_messages()
271 self.session = Session("Test session for %s" % self.__class__)
272 self.shapefilename = os.path.join("..", "Data", "iceland",
273 "cultural_landmark-point.dbf")
274 self.store = self.session.OpenShapefile(self.shapefilename)
275 self.layer = Layer("test layer", self.store)
276 self.classification = Classification()
277 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
278 self.layer.SetClassificationColumn("CLPTLABEL")
279 self.layer.SetClassification(self.classification)
280 self.layer.UnsetModified()
281 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
282 self.subscribe_with_params,
283 LAYER_SHAPESTORE_REPLACED)
284 self.layer.Subscribe(LAYER_CHANGED,
285 self.subscribe_with_params, LAYER_CHANGED)
286
287 def tearDown(self):
288 self.clear_messages()
289 self.layer.Destroy()
290 self.session.Destroy()
291 self.session = self.layer = self.store = self.classification = None
292
293 def test_sanity(self):
294 """SetShapeStoreTests sanity check
295
296 Test the initial state of the test case instances after setUp.
297 """
298 cls = self.layer.GetClassification()
299 self.assert_(cls is self.classification)
300 field = self.layer.GetClassificationColumn()
301 self.assertEquals(field, "CLPTLABEL")
302 self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
303 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
304 self.failIf(self.layer.WasModified())
305
306 def test_set_shape_store_modified_flag(self):
307 """Test whether Layer.SetShapeStore() sets the modified flag"""
308 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
309 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
310 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
311
312 self.assert_(self.layer.WasModified())
313
314 def test_set_shape_store_different_field_name(self):
315 """Test Layer.SetShapeStore() with different column name"""
316 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
317 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
318 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
319 # The classification should contain only the default group now.
320 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
321 self.check_messages([(self.layer, LAYER_CHANGED),
322 (self.layer, LAYER_SHAPESTORE_REPLACED)])
323
324 def test_set_shape_store_same_field(self):
325 """Test Layer.SetShapeStore() with same column name and type"""
326 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
327 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
328 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
329 # The classification should be the same as before
330 self.assert_(self.layer.GetClassification() is self.classification)
331 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
332
333 def test_set_shape_store_same_field_different_type(self):
334 """Test Layer.SetShapeStore() with same column name but different type
335 """
336 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
337 [(0.0,)] * 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
345 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
346
347 """Test cases for Layer method that modify the layer.
348 """
349
350 def setUp(self):
351 """Clear the list of received messages and create a layer and a session
352
353 The layer is bound to self.layer and the session to self.session.
354 """
355 self.clear_messages()
356 self.session = Session("Test session for %s" % self.__class__)
357 filename = os.path.join("..", "Data", "iceland", "political.shp")
358 self.layer = Layer("Test Layer",
359 self.session.OpenShapefile(filename))
360 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
361 LAYER_LEGEND_CHANGED)
362 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
363 self.subscribe_with_params,
364 LAYER_VISIBILITY_CHANGED)
365 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
366 LAYER_CHANGED)
367
368 def tearDown(self):
369 """Clear the list of received messages and explictly destroy self.layer
370 """
371 self.layer.Destroy()
372 self.layer = None
373 self.session.Destroy()
374 self.session = None
375 self.clear_messages()
376
377 def test_sanity(self):
378 """TestLayerModification Sanity Checks"""
379 # test default settings
380 self.failIf(self.layer.WasModified())
381 self.assertEquals(self.layer.Visible(), 1)
382 # no messages should have been produced
383 self.check_messages([])
384
385 def test_visibility(self):
386 """Test Layer visibility"""
387 self.layer.SetVisible(0)
388 self.assertEquals(self.layer.Visible(), 0)
389 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
390
391 # currently, modifying the visibility doesn't count as changing
392 # the layer.
393 self.failIf(self.layer.WasModified())
394
395 def test_set_classification(self):
396 """Test Layer.SetClassification"""
397 classification = Classification()
398 classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
399
400 self.layer.SetClassification(classification)
401 self.layer.SetClassificationColumn("AREA")
402
403 self.check_messages([(self.layer, LAYER_CHANGED),
404 (self.layer, LAYER_CHANGED)])
405 self.failUnless(self.layer.WasModified())
406
407 self.clear_messages()
408 self.layer.UnsetModified()
409
410 # change only the classification column. This should issue a
411 # LAYER_CHANGED message as well.
412 self.layer.SetClassificationColumn("PERIMETER")
413
414 self.check_messages([(self.layer, LAYER_CHANGED)])
415 self.failUnless(self.layer.WasModified())
416
417
418 #
419 # the tree info now contains Color objects which are difficult to test
420 #
421 # def test_tree_info(self):
422 # """Test Layer.TreeInfo"""
423 # self.assertEquals(self.layer.TreeInfo(),
424 # ("Layer 'Test Layer'",
425 # ['Shown',
426 # 'Shapes: 156',
427 # ('Extent (lat-lon):'
428 # ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
429 # 'Shapetype: Polygon',
430 # 'Fill: None',
431 # 'Outline: (0.000, 0.000, 0.000)']))
432
433
434 if __name__ == "__main__":
435 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