/[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 1551 - (show annotations)
Wed Aug 6 17:21:07 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 17773 byte(s)
* Thuban/Model/data.py (ShapefileStore.Shape): For consistency, a
Shape object will always have the coordinates as a list of list of
coordinate pairs (tuples).
(Shape.compute_bbox): Adapt to new representation.

* Thuban/UI/viewport.py (ViewPort.find_shape_at)
(ViewPort.LabelShapeAt): Adapt to new coordinate representation in
Shape objects.

* test/test_shapefilestore.py
(ShapefileStoreTests.assertFloatTuplesEqual)
(ShapefileStoreTests.assertPointListEquals): Rename to
assertPointListEquals and change purpose to checking equality of
the lists returned by Shape.Points().
(TestShapefileStoreArc.test_shape)
(TestShapefileStorePolygon.test_shape)
(TestShapefileStorePoint.test_shape): Use the new
assertPointListEquals instead of assertFloatTuplesEqual

* test/test_layer.py (TestLayer.assertFloatTuplesEqual)
(TestLayer.assertPointListEquals): Rename to assertPointListEquals
and change purpose to checking equality of the lists returned by
Shape.Points().
(TestLayer.test_arc_layer, TestLayer.test_arc_layer)
(TestLayer.test_polygon_layer, TestLayer.test_point_layer)
(TestLayer.test_derived_store): Use the new assertPointListEquals
instead of assertFloatTuplesEqual

* test/test_derivedshapestore.py
(TestDerivedShapeStore.assertFloatTuplesEqual)
(TestDerivedShapeStore.assertPointListEquals): Rename to
assertPointListEquals and change purpose to checking equality of
the lists returned by Shape.Points().
(TestDerivedShapeStore.test_shape): Use the new
assertPointListEquals instead of assertFloatTuplesEqual

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