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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.395  
changed lines
  Added in v.1599

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26