/[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 1174 - (show annotations)
Thu Jun 12 13:37:29 2003 UTC (21 years, 8 months ago) by jonathan
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 15427 byte(s)
Check for existence of gdal.

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