/[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 1987 by bh, Fri Nov 28 11:37:35 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.Destroy()
52            self.session = None
53            if self.layer is not None:
54                self.layer.Destroy()
55                self.layer = None
56    
57        def build_path(self, filename):
58            return os.path.join("..", "Data", "iceland", filename)
59    
60        def open_shapefile(self, filename):
61            """Open and return a shapestore for filename in the iceland data set"""
62            return self.session.OpenShapefile(self.build_path(filename))
63    
64        def test_base_layer(self):
65            layer = self.layer = BaseLayer("Test BaseLayer")
66            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            self.failIf(layer.HasShapes())
78    
79            self.assertEquals(layer.GetProjection(), None)
80    
81            # set/get projection
82            proj = Projection(["proj=utm", "zone=26", "ellps=clrk66"])
83    
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      def test_arc_layer(self):      def test_arc_layer(self):
93          """Test Layer with arc shapes"""          """Test Layer with arc shapes"""
94          layer = Layer("Test Layer",          layer = self.layer = Layer("Test Layer",
95                        os.path.join("..", "Data", "iceland", "roads-line.shp"))                                     self.open_shapefile("roads-line.shp"))
96          self.assertEquals(layer.Title(), "Test Layer")          self.failUnless(layer.HasClassification())
97            self.failUnless(layer.HasShapes())
98          self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)          self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
99          self.assertEquals(layer.NumShapes(), 839)          self.assertEquals(layer.NumShapes(), 839)
100          shape = layer.Shape(32)          shape = layer.Shape(32)
101          self.assertFloatTuplesEqual(shape.Points(),          self.assertPointListEquals(shape.Points(),
102                                      [(-15.082174301147461, 66.27738189697265),                                     [[(-15.082174301147461, 66.27738189697265),
103                                       (-15.026350021362305, 66.27339172363281)])                                       (-15.026350021362305, 66.27339172363281)]])
104          self.assertFloatSeqEqual(layer.BoundingBox(),          self.assertFloatSeqEqual(layer.BoundingBox(),
105                                   [-24.450359344482422, 63.426830291748047,                                   [-24.450359344482422, 63.426830291748047,
106                                    -13.55668830871582, 66.520111083984375])                                    -13.55668830871582, 66.520111083984375])
107          self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25)),          shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
108            self.assertEquals([s.ShapeID() for s in shapes],
109                            [613, 726, 838])                            [613, 726, 838])
110    
111            self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
112                              [-15.082174301147461, 66.27339172363281,
113                               -15.026350021362305, 66.27738189697265])
114    
115            shape = layer.Shape(33)
116            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    
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      def test_polygon_layer(self):      def test_polygon_layer(self):
130          """Test Layer with polygon shapes"""          """Test Layer with polygon shapes"""
131          layer = Layer("Test Layer",          layer = self.layer = Layer("Test Layer",
132                        os.path.join("..", "Data", "iceland", "political.shp"))                                     self.open_shapefile("political.shp"))
133          self.assertEquals(layer.Title(), "Test Layer")          self.failUnless(layer.HasClassification())
134            self.failUnless(layer.HasShapes())
135          self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)          self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
136          self.assertEquals(layer.NumShapes(), 156)          self.assertEquals(layer.NumShapes(), 156)
137          shape = layer.Shape(4)          shape = layer.Shape(4)
138          self.assertFloatTuplesEqual(shape.Points(),          self.assertPointListEquals(shape.Points(),
139                                      [(-22.406391143798828, 64.714111328125),                                     [[(-22.40639114379882, 64.714111328125),
140                                       (-22.41621208190918, 64.71600341796875),                                       (-22.41621208190918, 64.7160034179687),
141                                       (-22.406051635742188, 64.719200134277344),                                       (-22.40605163574218, 64.719200134277),
142                                       (-22.406391143798828, 64.714111328125)])                                       (-22.40639114379882, 64.714111328125)]])
143          self.assertFloatSeqEqual(layer.BoundingBox(),          self.assertFloatSeqEqual(layer.BoundingBox(),
144                                   [-24.546524047851562, 63.286754608154297,                                   [-24.546524047851562, 63.286754608154297,
145                                    -13.495815277099609, 66.563774108886719])                                    -13.495815277099609, 66.563774108886719])
146          self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1)),          shapes = layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1))
147            self.assertEquals([s.ShapeID() for s in shapes],
148                            [91, 92, 144, 146, 148, 150, 152, 153])                            [91, 92, 144, 146, 148, 150, 152, 153])
149    
150      def test_point_layer(self):      def test_point_layer(self):
151          """Test Layer with point shapes"""          """Test Layer with point shapes"""
152          layer = Layer("Test Layer",          layer = self.layer = Layer("Test Layer",
153                        os.path.join("..", "Data", "iceland",                             self.open_shapefile("cultural_landmark-point.shp"))
154                                     "cultural_landmark-point.shp"))          self.failUnless(layer.HasClassification())
155          self.assertEquals(layer.Title(), "Test Layer")          self.failUnless(layer.HasShapes())
156          self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)          self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
157          self.assertEquals(layer.NumShapes(), 34)          self.assertEquals(layer.NumShapes(), 34)
158          shape = layer.Shape(0)          shape = layer.Shape(0)
159          self.assertFloatTuplesEqual(shape.Points(),          self.assertPointListEquals(shape.Points(),
160                                      [(-22.711074829101562, 66.36572265625)])                                     [[(-22.711074829101562, 66.36572265625)]])
161          self.assertFloatSeqEqual(layer.BoundingBox(),          self.assertFloatSeqEqual(layer.BoundingBox(),
162                                   [-23.806047439575195, 63.405960083007812,                                   [-23.806047439575195, 63.405960083007812,
163                                    -15.12291431427002, 66.36572265625])                                    -15.12291431427002, 66.36572265625])
164          self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1)),          shapes = layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1))
165            self.assertEquals([s.ShapeID() for s in shapes],
166                            [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])                            [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
167    
168        def test_arc_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_ARC,
174                                  [[[(9884828.7209840547, 5607720.9774499247),
175                                     (11298336.04640449, 9287823.2044059951)]]],
176                                             table)
177            layer = self.layer = Layer("Test Layer", store)
178    
179            proj = Projection(["proj=lcc", "lon_0=0", "lat_1=20n", "lat_2=60n",
180                               "ellps=clrk66"])
181            layer.SetProjection(proj)
182    
183            self.assertFloatSeqEqual(layer.BoundingBox(),
184                                     (9884828.7209840547, 5607720.9774499247,
185                                      11298336.04640449, 9287823.2044059951))
186            self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
187                                     (90.0, -8.90043373, 120, 11.1616263))
188            shapes = layer.ShapesInRegion((100, -10, 150, +10))
189            self.assertEquals([s.ShapeID() for s in shapes], [0])
190            self.assertFloatSeqEqual(layer.ShapesBoundingBox([0]),
191                                     (90.0, -8.90043373, 120, 11.1616263))
192    
193      def test_empty_layer(self):      def test_empty_layer(self):
194          """Test Layer with empty shape file"""          """Test Layer with empty shape file"""
195          # create an empty shape file          # create an empty shape file
# Line 102  class TestLayer(unittest.TestCase, suppo Line 201  class TestLayer(unittest.TestCase, suppo
201          dbffilename = self.temp_file_name("layer_empty.dbf")          dbffilename = self.temp_file_name("layer_empty.dbf")
202          dbf = dbflib.create(dbffilename)          dbf = dbflib.create(dbffilename)
203          dbf.add_field("NAME", dbflib.FTString, 20, 0)          dbf.add_field("NAME", dbflib.FTString, 20, 0)
204            dbf.close()
205    
206          # Now try to open it.          # Now try to open it.
207          layer = Layer("Empty Layer", shapefilename)          layer = self.layer = Layer("Empty Layer",
208                                       self.session.OpenShapefile(shapefilename))
209          self.assertEquals(layer.BoundingBox(), None)          self.assertEquals(layer.BoundingBox(), None)
210          self.assertEquals(layer.LatLongBoundingBox(), None)          self.assertEquals(layer.LatLongBoundingBox(), None)
211          self.assertEquals(layer.NumShapes(), 0)          self.assertEquals(layer.NumShapes(), 0)
212    
213        def test_get_field_type(self):
214            """Test Layer.GetFieldType()"""
215            layer = self.layer = Layer("Test Layer",
216                                       self.open_shapefile("roads-line.shp"))
217            self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
218            self.assertEquals(layer.GetFieldType("non existing"), None)
219    
220        def test_raster_layer(self):
221            if not Thuban.Model.resource.has_gdal_support():
222                raise support.SkipTest("No gdal support")
223    
224            filename = self.build_path("island.tif")
225            layer = RasterLayer("Test RasterLayer", filename)
226            self.failIf(layer.HasClassification())
227            self.failIf(layer.HasShapes())
228            self.assertEquals(layer.GetImageFilename(), os.path.abspath(filename))
229            self.assertFloatSeqEqual(layer.BoundingBox(),
230                                     [-24.5500000, 63.2833330,
231                                      -13.4916670, 66.5666670])
232            self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
233                                     [-24.5500000, 63.2833330,
234                                      -13.4916670, 66.5666670])
235    
236        def test_derived_store(self):
237            """Test layer with derived store"""
238            layer = self.layer = Layer("Test Layer",
239                                       self.open_shapefile("roads-line.shp"))
240            try:
241                store = layer.ShapeStore()
242                derived = DerivedShapeStore(store, store.Table())
243                layer.SetShapeStore(derived)
244                self.assert_(layer.ShapeStore() is derived)
245    
246                self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
247                self.assertEquals(layer.NumShapes(), 839)
248                shape = layer.Shape(32)
249                self.assertPointListEquals(shape.Points(),
250                                           [[(-15.082174301147, 66.277381896972),
251                                             (-15.026350021362, 66.273391723632)]])
252                self.assertFloatSeqEqual(layer.BoundingBox(),
253                                         [-24.450359344482422, 63.426830291748047,
254                                          -13.55668830871582, 66.520111083984375])
255                shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
256                self.assertEquals([s.ShapeID() for s in shapes],
257                                  [613, 726, 838])
258    
259                self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
260                                         [-15.082174301147461, 66.27339172363281,
261                                          -15.026350021362305, 66.27738189697265])
262    
263            finally:
264                store = derived = None
265    
266    
267  class TestLayerLegend(unittest.TestCase, support.SubscriberMixin):  class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
268    
269        def setUp(self):
270            """Create a layer with a classification as self.layer"""
271            self.clear_messages()
272            self.session = Session("Test session for %s" % self.__class__)
273            self.shapefilename = os.path.join("..", "Data", "iceland",
274                                              "cultural_landmark-point.dbf")
275            self.store = self.session.OpenShapefile(self.shapefilename)
276            self.layer = Layer("test layer", self.store)
277            self.classification = Classification()
278            self.classification.AppendGroup(ClassGroupSingleton("FARM"))
279            self.layer.SetClassificationColumn("CLPTLABEL")
280            self.layer.SetClassification(self.classification)
281            self.layer.UnsetModified()
282            self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
283                                 self.subscribe_with_params,
284                                 LAYER_SHAPESTORE_REPLACED)
285            self.layer.Subscribe(LAYER_CHANGED,
286                                 self.subscribe_with_params, LAYER_CHANGED)
287    
288        def tearDown(self):
289            self.clear_messages()
290            self.layer.Destroy()
291            self.session.Destroy()
292            self.session = self.layer = self.store = self.classification = None
293    
294        def test_sanity(self):
295            """SetShapeStoreTests sanity check
296    
297            Test the initial state of the test case instances after setUp.
298            """
299            cls = self.layer.GetClassification()
300            self.assert_(cls is self.classification)
301            field = self.layer.GetClassificationColumn()
302            self.assertEquals(field, "CLPTLABEL")
303            self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
304            self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
305            self.failIf(self.layer.WasModified())
306    
307        def test_set_shape_store_modified_flag(self):
308            """Test whether Layer.SetShapeStore() sets the modified flag"""
309            memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
310                          [("bla",)] * self.layer.ShapeStore().Table().NumRows())
311            self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
312    
313            self.assert_(self.layer.WasModified())
314    
315        def test_set_shape_store_different_field_name(self):
316            """Test Layer.SetShapeStore() with different column name"""
317            memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
318                          [("bla",)] * self.layer.ShapeStore().Table().NumRows())
319            self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
320            # The classification should contain only the default group now.
321            self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
322            self.check_messages([(self.layer, LAYER_CHANGED),
323                                 (self.layer, LAYER_SHAPESTORE_REPLACED)])
324    
325        def test_set_shape_store_same_field(self):
326            """Test Layer.SetShapeStore() with same column name and type"""
327            memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
328                          [("bla",)] * self.layer.ShapeStore().Table().NumRows())
329            self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
330            # The classification should be the same as before
331            self.assert_(self.layer.GetClassification() is self.classification)
332            self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
333    
334        def test_set_shape_store_same_field_different_type(self):
335            """Test Layer.SetShapeStore() with same column name but different type
336            """
337            memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
338                          [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
339            self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
340            # The classification should contain only the default group now.
341            self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
342            self.check_messages([(self.layer, LAYER_CHANGED),
343                                 (self.layer, LAYER_SHAPESTORE_REPLACED)])
344    
345    
346    class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
347    
348      """Test cases for Layer method that modify the layer.      """Test cases for Layer method that modify the layer.
349      """      """
350    
351      def setUp(self):      def setUp(self):
352          """Clear the list of received messages and create a layer          """Clear the list of received messages and create a layer and a session
353    
354          The layer is bound to self.layer.          The layer is bound to self.layer and the session to self.session.
355          """          """
356          self.clear_messages()          self.clear_messages()
357            self.session = Session("Test session for %s" % self.__class__)
358            filename = os.path.join("..", "Data", "iceland", "political.shp")
359          self.layer = Layer("Test Layer",          self.layer = Layer("Test Layer",
360                             os.path.join("..", "Data", "iceland",                             self.session.OpenShapefile(filename))
                                         "political.shp"))  
361          self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,          self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
362                               LAYER_LEGEND_CHANGED)                               LAYER_LEGEND_CHANGED)
363          self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,          self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
364                               self.subscribe_with_params,                               self.subscribe_with_params,
365                               LAYER_VISIBILITY_CHANGED)                               LAYER_VISIBILITY_CHANGED)
366            self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
367                                 LAYER_CHANGED)
368    
369      def tearDown(self):      def tearDown(self):
370          """Clear the list of received messages and explictly destroy self.layer          """Clear the list of received messages and explictly destroy self.layer
371          """          """
372          self.layer.Destroy()          self.layer.Destroy()
373            self.layer = None
374            self.session.Destroy()
375            self.session = None
376          self.clear_messages()          self.clear_messages()
377    
378      def test_initial_settings(self):      def test_sanity(self):
379          """Test Layer's initial legend attributes"""          """TestLayerModification Sanity Checks"""
380          # test default settings          # test default settings
381          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)  
382          self.assertEquals(self.layer.Visible(), 1)          self.assertEquals(self.layer.Visible(), 1)
383          # no messages should have been produced          # no messages should have been produced
384          self.check_messages([])          self.check_messages([])
# Line 157  class TestLayerLegend(unittest.TestCase, Line 393  class TestLayerLegend(unittest.TestCase,
393          # the layer.          # the layer.
394          self.failIf(self.layer.WasModified())          self.failIf(self.layer.WasModified())
395    
396            def test_set_classification(self):
397            """Test Layer.SetClassification"""
398            classification = Classification()
399            classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
400    
401            self.layer.SetClassification(classification)
402            self.layer.SetClassificationColumn("AREA")
403    
404            self.check_messages([(self.layer, LAYER_CHANGED),
405                                 (self.layer, LAYER_CHANGED)])
406            self.failUnless(self.layer.WasModified())
407    
408            self.clear_messages()
409            self.layer.UnsetModified()
410    
411            # change only the classification column. This should issue a
412            # LAYER_CHANGED message as well.
413            self.layer.SetClassificationColumn("PERIMETER")
414    
415            self.check_messages([(self.layer, LAYER_CHANGED)])
416            self.failUnless(self.layer.WasModified())
417    
418    
419  #  #
420  # the tree info now contains Color objects which are difficult to test  # the tree info now contains Color objects which are difficult to test
421  #  #
# Line 175  class TestLayerLegend(unittest.TestCase, Line 433  class TestLayerLegend(unittest.TestCase,
433    
434    
435  if __name__ == "__main__":  if __name__ == "__main__":
436      unittest.main()      support.run_tests()

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26