/[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 2339 - (show annotations)
Fri Aug 20 16:59:21 2004 UTC (20 years, 6 months ago) by silke
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 19246 byte(s)
Fix bug in projection handling of layers

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
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 [[[(9884828.7209840547, 5607720.9774499247),
175 (11298336.04640449, 9287823.2044059951)]]],
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 "ellps=clrk66"])
181 layer.SetProjection(proj)
182
183 self.assertFloatSeqEqual(layer.BoundingBox(),
184 (9884828.7209840547, 5607720.9774499247,
185 11298336.04640449, 9287823.2044059951))
186 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
187 (90.0, -8.90043373, 120, 11.1616263))
188 shapes = layer.ShapesInRegion((100, -10, 150, +10))
189 self.assertEquals([s.ShapeID() for s in shapes], [0])
190 self.assertFloatSeqEqual(layer.ShapesBoundingBox([0]),
191 (90.0, -8.90043373, 120, 11.1616263))
192
193 self.assertFloatSeqEqual(layer.ClipBoundingBox((-180, -6, 100, +120)),
194 (90.0, -6, 100, 11.1616263))
195 shapes = layer.ShapesInRegion((-180, -170, 200, +120))
196 print "Shapes", shapes
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.GetImageFilename(), os.path.abspath(filename))
235 self.assertFloatSeqEqual(layer.BoundingBox(),
236 [-24.5500000, 63.2833330,
237 -13.4916670, 66.5666670])
238 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
239 [-24.5500000, 63.2833330,
240 -13.4916670, 66.5666670])
241
242 def test_derived_store(self):
243 """Test layer with derived store"""
244 layer = self.layer = Layer("Test Layer",
245 self.open_shapefile("roads-line.shp"))
246 try:
247 store = layer.ShapeStore()
248 derived = DerivedShapeStore(store, store.Table())
249 layer.SetShapeStore(derived)
250 self.assert_(layer.ShapeStore() is derived)
251
252 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
253 self.assertEquals(layer.NumShapes(), 839)
254 shape = layer.Shape(32)
255 self.assertPointListEquals(shape.Points(),
256 [[(-15.082174301147, 66.277381896972),
257 (-15.026350021362, 66.273391723632)]])
258 self.assertFloatSeqEqual(layer.BoundingBox(),
259 [-24.450359344482422, 63.426830291748047,
260 -13.55668830871582, 66.520111083984375])
261 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
262 self.assertEquals([s.ShapeID() for s in shapes],
263 [613, 726, 838])
264
265 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
266 [-15.082174301147461, 66.27339172363281,
267 -15.026350021362305, 66.27738189697265])
268
269 finally:
270 store = derived = None
271
272
273 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
274
275 def setUp(self):
276 """Create a layer with a classification as self.layer"""
277 self.clear_messages()
278 self.session = Session("Test session for %s" % self.__class__)
279 self.shapefilename = os.path.join("..", "Data", "iceland",
280 "cultural_landmark-point.dbf")
281 self.store = self.session.OpenShapefile(self.shapefilename)
282 self.layer = Layer("test layer", self.store)
283 self.classification = Classification()
284 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
285 self.layer.SetClassificationColumn("CLPTLABEL")
286 self.layer.SetClassification(self.classification)
287 self.layer.UnsetModified()
288 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
289 self.subscribe_with_params,
290 LAYER_SHAPESTORE_REPLACED)
291 self.layer.Subscribe(LAYER_CHANGED,
292 self.subscribe_with_params, LAYER_CHANGED)
293
294 def tearDown(self):
295 self.clear_messages()
296 self.layer.Destroy()
297 self.session.Destroy()
298 self.session = self.layer = self.store = self.classification = None
299
300 def test_sanity(self):
301 """SetShapeStoreTests sanity check
302
303 Test the initial state of the test case instances after setUp.
304 """
305 cls = self.layer.GetClassification()
306 self.assert_(cls is self.classification)
307 field = self.layer.GetClassificationColumn()
308 self.assertEquals(field, "CLPTLABEL")
309 self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
310 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
311 self.failIf(self.layer.WasModified())
312
313 def test_set_shape_store_modified_flag(self):
314 """Test whether Layer.SetShapeStore() sets the modified flag"""
315 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
316 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
317 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
318
319 self.assert_(self.layer.WasModified())
320
321 def test_set_shape_store_different_field_name(self):
322 """Test Layer.SetShapeStore() with different column name"""
323 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
324 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
325 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
326 # The classification should contain only the default group now.
327 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
328 self.check_messages([(self.layer, LAYER_CHANGED),
329 (self.layer, LAYER_SHAPESTORE_REPLACED)])
330
331 def test_set_shape_store_same_field(self):
332 """Test Layer.SetShapeStore() with same column name and type"""
333 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
334 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
335 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
336 # The classification should be the same as before
337 self.assert_(self.layer.GetClassification() is self.classification)
338 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
339
340 def test_set_shape_store_same_field_different_type(self):
341 """Test Layer.SetShapeStore() with same column name but different type
342 """
343 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
344 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
345 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
346 # The classification should contain only the default group now.
347 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
348 self.check_messages([(self.layer, LAYER_CHANGED),
349 (self.layer, LAYER_SHAPESTORE_REPLACED)])
350
351
352 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
353
354 """Test cases for Layer method that modify the layer.
355 """
356
357 def setUp(self):
358 """Clear the list of received messages and create a layer and a session
359
360 The layer is bound to self.layer and the session to self.session.
361 """
362 self.clear_messages()
363 self.session = Session("Test session for %s" % self.__class__)
364 self.filename = os.path.join("..", "Data", "iceland", "political.shp")
365 self.layer = Layer("Test Layer",
366 self.session.OpenShapefile(self.filename))
367 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
368 LAYER_LEGEND_CHANGED)
369 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
370 self.subscribe_with_params,
371 LAYER_VISIBILITY_CHANGED)
372 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
373 LAYER_CHANGED)
374
375 def tearDown(self):
376 """Clear the list of received messages and explictly destroy self.layer
377 """
378 self.layer.Destroy()
379 self.layer = None
380 self.session.Destroy()
381 self.session = None
382 self.clear_messages()
383
384 def test_sanity(self):
385 """TestLayerModification Sanity Checks"""
386 # test default settings
387 self.failIf(self.layer.WasModified())
388 self.assertEquals(self.layer.Visible(), 1)
389 # no messages should have been produced
390 self.check_messages([])
391
392 def test_visibility(self):
393 """Test Layer visibility"""
394 self.layer.SetVisible(0)
395 self.assertEquals(self.layer.Visible(), 0)
396 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
397
398 # currently, modifying the visibility doesn't count as changing
399 # the layer.
400 self.failIf(self.layer.WasModified())
401
402 def test_set_classification(self):
403 """Test Layer.SetClassification"""
404 classification = Classification()
405 classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
406
407 self.layer.SetClassification(classification)
408 self.layer.SetClassificationColumn("AREA")
409
410 self.check_messages([(self.layer, LAYER_CHANGED),
411 (self.layer, LAYER_CHANGED)])
412 self.failUnless(self.layer.WasModified())
413
414 self.clear_messages()
415 self.layer.UnsetModified()
416
417 # change only the classification column. This should issue a
418 # LAYER_CHANGED message as well.
419 self.layer.SetClassificationColumn("PERIMETER")
420
421 self.check_messages([(self.layer, LAYER_CHANGED)])
422 self.failUnless(self.layer.WasModified())
423
424
425 def test_tree_info(self):
426 """Test Layer.TreeInfo"""
427 self.assertEquals(self.layer.TreeInfo(),
428 ("Layer 'Test Layer'",
429 ['Filename: %s' % os.path.abspath(self.filename),
430 'Shown',
431 'Shapes: 156',
432 'Extent (lat-lon): (-24.5465, 63.2868, -13.4958, 66.5638)',
433 'Shapetype: Polygon',
434 self.layer.GetClassification()]))
435
436
437 if __name__ == "__main__":
438 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