/[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 1576 - (show annotations)
Mon Aug 11 12:08:26 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: 17484 byte(s)
(TestLayer.assertPointListEquals): Removed.
It's now in FloatComparisonMixin

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