/[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 331 by bh, Fri Sep 20 14:34:23 2002 UTC revision 1555 by bh, Thu Aug 7 15:41:05 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 20  import support Line 20  import support
20  support.initthuban()  support.initthuban()
21    
22  import shapelib  import shapelib
23    import dbflib
24    
25  from Thuban.Model.layer import Layer, SHAPETYPE_POLYGON, SHAPETYPE_ARC, \  from Thuban.Model.session import Session
26       SHAPETYPE_POINT  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, \  from Thuban.Model.messages import LAYER_LEGEND_CHANGED, \
29       LAYER_VISIBILITY_CHANGED       LAYER_VISIBILITY_CHANGED, LAYER_SHAPESTORE_REPLACED, LAYER_CHANGED
30  from Thuban.Model.color import Color  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,  class TestLayer(unittest.TestCase, support.FileTestMixin,
39                  support.FloatComparisonMixin):                  support.FloatComparisonMixin):
40    
41      """Test cases for different layer (shape) types"""      """Test cases for different layer (shape) types"""
42    
43      def assertFloatTuplesEqual(self, test, value):      def assertPointListEquals(self, test, value):
44          """Assert equality of two lists of tuples of float"""          """Assert equality of two lists of lists of tuples of float"""
45          for i in range(len(test)):          for i in range(len(test)):
46              self.assertFloatSeqEqual(test[i], value[i])              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):      def test_arc_layer(self):
98          """Test Layer with arc shapes"""          """Test Layer with arc shapes"""
99          layer = Layer("Test Layer",          layer = self.layer = Layer("Test Layer",
100                        os.path.join("..", "Data", "iceland", "roads-line.shp"))                                     self.open_shapefile("roads-line.shp"))
101          self.assertEquals(layer.Title(), "Test Layer")          self.failUnless(layer.HasClassification())
102            self.failUnless(layer.HasShapes())
103          self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)          self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
104          self.assertEquals(layer.NumShapes(), 839)          self.assertEquals(layer.NumShapes(), 839)
105          shape = layer.Shape(32)          shape = layer.Shape(32)
106          self.assertFloatTuplesEqual(shape.Points(),          self.assertPointListEquals(shape.Points(),
107                                      [(-15.082174301147461, 66.27738189697265),                                     [[(-15.082174301147461, 66.27738189697265),
108                                       (-15.026350021362305, 66.27339172363281)])                                       (-15.026350021362305, 66.27339172363281)]])
109          self.assertFloatSeqEqual(layer.BoundingBox(),          self.assertFloatSeqEqual(layer.BoundingBox(),
110                                   [-24.450359344482422, 63.426830291748047,                                   [-24.450359344482422, 63.426830291748047,
111                                    -13.55668830871582, 66.520111083984375])                                    -13.55668830871582, 66.520111083984375])
112          self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25)),          self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25)),
113                            [613, 726, 838])                            [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):      def test_polygon_layer(self):
134          """Test Layer with polygon shapes"""          """Test Layer with polygon shapes"""
135          layer = Layer("Test Layer",          layer = self.layer = Layer("Test Layer",
136                        os.path.join("..", "Data", "iceland", "political.shp"))                                     self.open_shapefile("political.shp"))
137          self.assertEquals(layer.Title(), "Test Layer")          self.failUnless(layer.HasClassification())
138            self.failUnless(layer.HasShapes())
139          self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)          self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
140          self.assertEquals(layer.NumShapes(), 156)          self.assertEquals(layer.NumShapes(), 156)
141          shape = layer.Shape(4)          shape = layer.Shape(4)
142          self.assertFloatTuplesEqual(shape.Points(),          self.assertPointListEquals(shape.Points(),
143                                      [(-22.406391143798828, 64.714111328125),                                     [[(-22.40639114379882, 64.714111328125),
144                                       (-22.41621208190918, 64.71600341796875),                                       (-22.41621208190918, 64.7160034179687),
145                                       (-22.406051635742188, 64.719200134277344),                                       (-22.40605163574218, 64.719200134277),
146                                       (-22.406391143798828, 64.714111328125)])                                       (-22.40639114379882, 64.714111328125)]])
147          self.assertFloatSeqEqual(layer.BoundingBox(),          self.assertFloatSeqEqual(layer.BoundingBox(),
148                                   [-24.546524047851562, 63.286754608154297,                                   [-24.546524047851562, 63.286754608154297,
149                                    -13.495815277099609, 66.563774108886719])                                    -13.495815277099609, 66.563774108886719])
# Line 75  class TestLayer(unittest.TestCase, suppo Line 152  class TestLayer(unittest.TestCase, suppo
152    
153      def test_point_layer(self):      def test_point_layer(self):
154          """Test Layer with point shapes"""          """Test Layer with point shapes"""
155          layer = Layer("Test Layer",          layer = self.layer = Layer("Test Layer",
156                        os.path.join("..", "Data", "iceland",                             self.open_shapefile("cultural_landmark-point.shp"))
157                                     "cultural_landmark-point.shp"))          self.failUnless(layer.HasClassification())
158          self.assertEquals(layer.Title(), "Test Layer")          self.failUnless(layer.HasShapes())
159          self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)          self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
160          self.assertEquals(layer.NumShapes(), 34)          self.assertEquals(layer.NumShapes(), 34)
161          shape = layer.Shape(0)          shape = layer.Shape(0)
162          self.assertFloatTuplesEqual(shape.Points(),          self.assertPointListEquals(shape.Points(),
163                                      [(-22.711074829101562, 66.36572265625)])                                     [[(-22.711074829101562, 66.36572265625)]])
164          self.assertFloatSeqEqual(layer.BoundingBox(),          self.assertFloatSeqEqual(layer.BoundingBox(),
165                                   [-23.806047439575195, 63.405960083007812,                                   [-23.806047439575195, 63.405960083007812,
166                                    -15.12291431427002, 66.36572265625])                                    -15.12291431427002, 66.36572265625])
# Line 96  class TestLayer(unittest.TestCase, suppo Line 173  class TestLayer(unittest.TestCase, suppo
173          shapefilename = self.temp_file_name("layer_empty.shp")          shapefilename = self.temp_file_name("layer_empty.shp")
174          shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)          shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
175          shp.close()          shp.close()
176            # create an empty DBF file too because Thuban can't cope yet
177          layer = Layer("Empty Layer", shapefilename)          # 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)          self.assertEquals(layer.BoundingBox(), None)
186          self.assertEquals(layer.LatLongBoundingBox(), None)          self.assertEquals(layer.LatLongBoundingBox(), None)
187          self.assertEquals(layer.NumShapes(), 0)          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                raise support.SkipTest("No gdal support")
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  class TestLayerLegend(unittest.TestCase, support.SubscriberMixin):      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.      """Test cases for Layer method that modify the layer.
325      """      """
326    
327      def setUp(self):      def setUp(self):
328          """Clear the list of received messages and create a layer          """Clear the list of received messages and create a layer and a session
329    
330          The layer is bound to self.layer.          The layer is bound to self.layer and the session to self.session.
331          """          """
332          self.clear_messages()          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",          self.layer = Layer("Test Layer",
336                             os.path.join("..", "Data", "iceland",                             self.session.OpenShapefile(filename))
                                         "political.shp"))  
337          self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,          self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
338                               LAYER_LEGEND_CHANGED)                               LAYER_LEGEND_CHANGED)
339          self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,          self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
340                               self.subscribe_with_params,                               self.subscribe_with_params,
341                               LAYER_VISIBILITY_CHANGED)                               LAYER_VISIBILITY_CHANGED)
342            self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
343                                 LAYER_CHANGED)
344    
345      def tearDown(self):      def tearDown(self):
346          """Clear the list of received messages and explictly destroy self.layer          """Clear the list of received messages and explictly destroy self.layer
347          """          """
348          self.layer.Destroy()          self.layer.Destroy()
349            self.layer = None
350            self.session.Destroy()
351            self.session = None
352          self.clear_messages()          self.clear_messages()
353    
354      def test_initial_settings(self):      def test_sanity(self):
355          """Test Layer's initial legend attributes"""          """TestLayerModification Sanity Checks"""
356          # test default settings          # test default settings
357          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)  
358          self.assertEquals(self.layer.Visible(), 1)          self.assertEquals(self.layer.Visible(), 1)
359          # no messages should have been produced          # no messages should have been produced
360          self.check_messages([])          self.check_messages([])
361    
     def test_fill(self):  
         """Test Layer's fill attribute"""  
         # modify the fill  
         self.layer.SetFill(Color(0.5, 1.0, 0.75))  
         self.check_messages([(self.layer, LAYER_LEGEND_CHANGED)])  
         self.assertEquals(self.layer.fill.hex().lower(), "#7fffbf")  
         self.assert_(self.layer.WasModified())  
   
     def test_stroke(self):  
         """Test Layer's stroke attribute"""  
         self.layer.SetStroke(Color(0.5, 1.0, 0.75))  
         self.assertEquals(self.layer.stroke.hex().lower(), "#7fffbf")  
         self.check_messages([(self.layer, LAYER_LEGEND_CHANGED)])  
         self.assert_(self.layer.WasModified())  
   
     def test_stroke_width(self):  
         """Test Layer's stroke_width attribute"""  
         self.layer.SetStrokeWidth(3.0)  
         self.assertEquals(self.layer.stroke_width, 3.0)  
         self.check_messages([(self.layer, LAYER_LEGEND_CHANGED)])  
         self.assert_(self.layer.WasModified())  
   
362      def test_visibility(self):      def test_visibility(self):
363          """Test Layer visibility"""          """Test Layer visibility"""
364          self.layer.SetVisible(0)          self.layer.SetVisible(0)
# Line 172  class TestLayerLegend(unittest.TestCase, Line 369  class TestLayerLegend(unittest.TestCase,
369          # the layer.          # the layer.
370          self.failIf(self.layer.WasModified())          self.failIf(self.layer.WasModified())
371    
372      def test_tree_info(self):      def test_set_classification(self):
373          """Test Layer.TreeInfo"""          """Test Layer.SetClassification"""
374          self.assertEquals(self.layer.TreeInfo(),          classification = Classification()
375                            ("Layer 'Test Layer'",          classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
376                             ['Shown',  
377                              'Shapes: 156',          self.layer.SetClassification(classification)
378                              ('Extent (lat-lon):'          self.layer.SetClassificationColumn("AREA")
379                               ' (-24.5465, 63.2868, -13.4958, 66.5638)'),  
380                              'Shapetype: Polygon',          self.check_messages([(self.layer, LAYER_CHANGED),
381                              'Fill: None',                               (self.layer, LAYER_CHANGED)])
382                              'Outline: (0.000, 0.000, 0.000)']))          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__":  if __name__ == "__main__":
412      unittest.main()      support.run_tests()

Legend:
Removed from v.331  
changed lines
  Added in v.1555

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26