/[thuban]/branches/WIP-pyshapelib-bramz/test/test_layer.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/test/test_layer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1768 - (hide annotations)
Thu Oct 2 15:15:04 2003 UTC (21 years, 5 months ago) by bh
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 18797 byte(s)
(TestLayer.test_empty_layer): Explicitly
close the dbf file we create so that it's contents have been
written properly.

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