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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1552 - (hide annotations)
Wed Aug 6 17:21:32 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/test/test_baserenderer.py
File MIME type: text/x-python
File size: 16450 byte(s)
* Thuban/UI/renderer.py (MapRenderer): Most of the code/methods in
this class is now in BaseRenderer. This class is now practically
only a specialization of BaseRenderer for rendering to an actual
wx DC.
(ScreenRenderer.draw_shape_layer): Use self.low_level_renderer()
to get the shapetype specific rendering functions.

* test/test_baserenderer.py: New. Test cases for BaseRenderer

* Thuban/UI/view.py (MapCanvas.__init__): New instance variable
error_on_redraw to guard agains endless loops and stack overflows
when there's a bug in the rendering code that raises exceptions.
(MapCanvas.OnIdle, MapCanvas._do_redraw): Split the actual
rendering into a separate method _do_redraw so that error handling
is a bit easier. When an exception occurs, set error_on_redraw to
true. When it's true on entry to OnIdle do nothing and return
immediately.

1 bh 1552 # Copyright (C) 2003 by Intevation GmbH
2     # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with the software for details.
7    
8     """Test Thuban.Model.baserenderer"""
9    
10     __version__ = "$Revision$"
11     # $Source$
12     # $Id$
13    
14     import os
15     import binascii
16     import unittest
17    
18     import support
19     support.initthuban()
20    
21     from Thuban.Model.color import Transparent, Color
22     from Thuban.Model.data import Shape, SHAPETYPE_ARC, SHAPETYPE_POLYGON, \
23     SHAPETYPE_POINT
24     from Thuban.Model.map import Map
25     from Thuban.Model.layer import Layer, RasterLayer
26     from Thuban.Model.table import MemoryTable, \
27     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING
28    
29     from Thuban.UI.baserenderer import BaseRenderer
30    
31    
32     class MockDC:
33    
34     def __init__(self, size = None):
35     self.calls = []
36     self.size = size
37    
38     def GetSizeTuple(self):
39     return self.size
40    
41     def __getattr__(self, attr):
42     def method(*args):
43     self.calls.append((attr,) + args)
44     return method
45    
46     class P:
47    
48     """A simple point"""
49    
50     def __init__(self, x, y):
51     self.x = x
52     self.y = y
53    
54     def __eq__(self, other):
55     return self.x == other.x and self.y == other.y
56    
57     def __ne__(self, other):
58     return self.x != other.x and self.y != other.y
59    
60     def __repr__(self):
61     return "P(%r, %r)" % (self.x, self.y)
62    
63    
64     class SimpleRenderer(BaseRenderer):
65    
66     TRANSPARENT_PEN = ("pen", Transparent)
67     TRANSPARENT_BRUSH = ("brush", Transparent)
68    
69     def make_point(self, x, y):
70     return P(x, y)
71    
72     def tools_for_property(self, prop):
73     fill = prop.GetFill()
74     brush = ("brush", fill)
75    
76     stroke = prop.GetLineColor()
77     stroke_width = prop.GetLineWidth()
78     if stroke is Transparent:
79     pen = ("pen", Transparent)
80     else:
81     pen = ("pen", stroke, stroke_width)
82    
83     return pen, brush
84    
85     def label_font(self):
86     return "label font"
87    
88     def draw_raster_data(self, data):
89     self.raster_data = data
90    
91     class SimpleShapeStore:
92    
93     def __init__(self, shapetype, shapes, table):
94     self.shapetype = shapetype
95     self.shapes = shapes
96     self.table = table
97     assert table.NumRows() == len(shapes)
98    
99     def ShapeType(self):
100     return self.shapetype
101    
102     def Table(self):
103     return self.table
104    
105     def NumShapes(self):
106     return len(self.shapes)
107    
108     def Shape(self, index):
109     return Shape(self.shapes[index])
110    
111    
112     class MockProjection:
113    
114     """Objects that look like projections but simply apply non-uniform scalings
115     """
116    
117     def __init__(self, xscale, yscale):
118     self.xscale = float(xscale)
119     self.yscale = float(yscale)
120    
121     def Forward(self, x, y):
122     return (x * self.xscale, y * self.yscale)
123    
124     def Inverse(self, x, y):
125     return (x / self.xscale, y / self.yscale)
126    
127    
128     class TestBaseRenderer(unittest.TestCase):
129    
130     def setUp(self):
131     """Set self.to_destroy to an empty list
132    
133     Test should put all objects whose Destroy should be called atunittest.main
134     the end into this list so that they're destroyed in tearDown
135     """
136     self.to_destroy = []
137    
138     def tearDown(self):
139     for obj in self.to_destroy:
140     obj.Destroy()
141    
142     def test_arc_no_projection(self):
143     """Test BaseRenderer with arc layer and no projections"""
144     table = MemoryTable([("type", FIELDTYPE_STRING),
145     ("value", FIELDTYPE_DOUBLE),
146     ("code", FIELDTYPE_INT)],
147     [("UNKNOWN", 0.0, 0)])
148     shapes = [[[(0, 0), (10, 10)]]]
149     store = SimpleShapeStore(SHAPETYPE_ARC, shapes, table)
150    
151     map = Map("TestBaseRenderer")
152     self.to_destroy.append(map)
153     layer = Layer("arc layer", store)
154     map.AddLayer(layer)
155    
156     dc = MockDC()
157     renderer = SimpleRenderer(dc, 2, (10, 10))
158    
159     renderer.render_map(map)
160    
161     self.assertEquals(dc.calls,
162     [('BeginDrawing',),
163     ('SetBrush', ('brush', Transparent)),
164     ('SetPen', ('pen', Color(0, 0, 0), 1)),
165     ('DrawLines', [P(10, 10), P(30, -10)]),
166     ('SetFont', "label font"),
167     ('EndDrawing',)])
168    
169     def test_polygon_no_projection(self):
170     """Test BaseRenderer with polygon layer and no projections"""
171     table = MemoryTable([("type", FIELDTYPE_STRING),
172     ("value", FIELDTYPE_DOUBLE),
173     ("code", FIELDTYPE_INT)],
174     [("UNKNOWN", 0.0, 0)])
175     shapes = [[[(0, 0), (10, 10), (10, 0), (0, 0)]]]
176     store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
177    
178     map = Map("TestBaseRenderer")
179     layer = Layer("polygon layer", store)
180     prop = layer.GetClassification().GetDefaultGroup().GetProperties()
181     prop.SetFill(Color(1, 1, 1))
182    
183     map.AddLayer(layer)
184     self.to_destroy.append(map)
185    
186     dc = MockDC()
187     renderer = SimpleRenderer(dc, 2, (10, 10))
188    
189     renderer.render_map(map)
190    
191     self.assertEquals(dc.calls,
192     [('BeginDrawing',),
193     ('SetBrush', ('brush', Color(1, 1, 1))),
194     ('SetPen', ('pen', Transparent)),
195     ('DrawPolygon', [P(10, 10), P(30, -10), P(30, 10),
196     P(10, 10)]),
197     ('SetBrush', ('brush', Transparent)),
198     ('SetPen', ('pen', Color(0, 0, 0), 1)),
199     ('DrawLines', [P(10, 10), P(30, -10), P(30, 10),
200     P(10, 10)]),
201     ('SetFont', "label font"),
202     ('EndDrawing',)])
203    
204     def test_complex_polygon(self):
205     """Test BaseRenderer with complex polygon and no projections"""
206     # A square inside a sqare. This has to be drawn with at least a
207     # draw polygon call and two draw lines calls.
208     shapes = [[[(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
209     [(2, 2), (8, 2), (8, 8), (2, 8), (2, 2)]]]
210    
211     table = MemoryTable([("type", FIELDTYPE_STRING),
212     ("value", FIELDTYPE_DOUBLE),
213     ("code", FIELDTYPE_INT)],
214     [("UNKNOWN", 0.0, 0)])
215     store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
216    
217     map = Map("TestBaseRenderer")
218     layer = Layer("polygon layer", store)
219     prop = layer.GetClassification().GetDefaultGroup().GetProperties()
220     prop.SetFill(Color(1, 1, 1))
221    
222     map.AddLayer(layer)
223     self.to_destroy.append(map)
224    
225     dc = MockDC()
226     renderer = SimpleRenderer(dc, 2, (10, 10))
227    
228     renderer.render_map(map)
229    
230     self.assertEquals(dc.calls,
231     [('BeginDrawing',),
232     ('SetBrush', ('brush', Color(1, 1, 1))),
233     ('SetPen', ('pen', Transparent)),
234     ('DrawPolygon',
235     [P(10, 10), P(10, -10), P(30, -10), P(30, 10),
236     P(10, 10),
237     P(14, 6), P(26, 6), P(26, -6), P(14, -6),
238     P(14, 6),
239     P(10, 10)]),
240     ('SetBrush', ('brush', Transparent)),
241     ('SetPen', ('pen', Color(0, 0, 0), 1)),
242     ('DrawLines', [P(10, 10), P(10, -10), P(30, -10),
243     P(30, 10), P(10, 10)]),
244     ('DrawLines', [P(14, 6), P(26, 6), P(26, -6),
245     P(14, -6), P(14, 6)]),
246     ('SetFont', "label font"),
247     ('EndDrawing',)])
248    
249     def test_point_no_projection(self):
250     """Test BaseRenderer with point layer and no projections"""
251     table = MemoryTable([("type", FIELDTYPE_STRING),
252     ("value", FIELDTYPE_DOUBLE),
253     ("code", FIELDTYPE_INT)],
254     [("UNKNOWN", 0.0, 0),
255     ("UNKNOWN", 0.0, 1)])
256     shapes = [[[(0, 0)]], [[(10, 10)]]]
257     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
258    
259     map = Map("TestBaseRenderer")
260     layer = Layer("point layer", store)
261     map.AddLayer(layer)
262     self.to_destroy.append(map)
263    
264     dc = MockDC()
265     renderer = SimpleRenderer(dc, 2, (10, 10))
266    
267     renderer.render_map(map)
268    
269     self.assertEquals(dc.calls,
270     [('BeginDrawing',),
271     ('SetBrush', ('brush', Transparent)),
272     ('SetPen', ('pen', Color(0, 0, 0), 1)),
273     ('DrawEllipse', 5, 5, 10, 10),
274     ('SetBrush', ('brush', Transparent)),
275     ('SetPen', ('pen', Color(0, 0, 0), 1)),
276     ('DrawEllipse', 25, -15, 10, 10),
277     ('SetFont', "label font"),
278     ('EndDrawing',)])
279    
280     def test_raster_no_projection(self):
281     """Test BaseRenderer with raster layer and no projections
282    
283     This test is very simple minded and perhaps can easily fail due
284     to round-off errors. It simply compares the complete BMP file
285     returned by gdalwarp.ProjectRasterFile to a BMP file data.
286     """
287     map = Map("TestBaseRenderer")
288    
289     layer = RasterLayer("raster layer",
290     os.path.join("..", "Data", "iceland",
291     "island.tif"))
292     map.AddLayer(layer)
293     self.to_destroy.append(map)
294    
295     dc = MockDC(size = (20, 20))
296     renderer = SimpleRenderer(dc, 34, (800, 2250))
297    
298     renderer.render_map(map)
299    
300     # The following commented out code block can be used to generate
301     # the base64 coded reference image data
302     #hexed = binascii.b2a_base64(renderer.raster_data)
303     #while hexed:
304     # print repr(hexed[:65])
305     # hexed = hexed[65:]
306    
307     # The reference data as a base64 coded BMP image
308     raw_data = binascii.a2b_base64(
309     'Qk3GBQAAAAAAADYEAAAoAAAAFAAAABQAAAABAAgAAAAAAJABAAAAAAAAAAAAAAABA'
310     'AAAAAAAApYOAALGAgAGfjoAHmZyACZ2egAujo4AArICAE66GgACngIA5mZSAJqONg'
311     'ACzgIAAoIyABZqZgAO4uYAAtICAAKqAgAScloAAtYCADKepgAS2t4AAooiAALaAgA'
312     'CtgIAHsbOAAp2TgACogIAFtbaACqOigAidnoAAuICADKaogACfjoAAr4CAAKSFgAm'
313     'fnoAAo4eABrS1gAibnoAHsbKAAp6SgACmg4AGs7SACLCxgAqioIAAoYqAAZ6RgACm'
314     'goAKrK6AALmAgAC3gIAApIaABZqagACngYAAo4iAAKmAgAivsYAJoJ6AALCAgACyg'
315     'IAAq4CAAKWEgAOclYALpqeAAK6AgACgjYAEm5eAAKKKgAGekIAHmp6ABpmcgAChi4'
316     'ALpaaACJyegAClhYAEnJeAAZ+QgAqhoIADnZSAB5mdgACiiYAJnp6ACqGegAqrrYA'
317     'GmpuAB5megACkh4ALqqyAA52VgAulpYAAoI6AAZ+PgASbmIALpKWAA7m5gAWbmYAG'
318     'mpyAC6SjgAqioYADnZOAA7q6gAianoALqauABpqagAqgnoAEnJWAAp6RgAWbmIACu'
319     '7uACqGfgAqiooAMqauAAby8gAmusIAMp6qAC6WngAyoqoABvb2AC6SkgAS3uIAJra'
320     '+AB7KzgAynqIALq62ADKirgAC+voAGsrSABLi4gAG8vYADubqAC6qtgAuprIABvb6'
321     'ACLCygAW2t4AKra+AAru8gAS4uYACuruAAry8gAG+voAAEBAAFhkZABAQEAABp6fA'
322     'EBACAAAgPwAAPu/AJE9CgBACAAALj1BAEAICAAGPAAAQAgAAAY8+gBACL8AJTxXAA'
323     'gIQAAAPEAAAAgIAAY8QABACAgAAGQAAABAAAAALpoAAEBAAAAALgAAAEAABkAGAEA'
324     'IQAD2AEAAvwAIAJAu2ABAQEAALmQ5AEBAQAAAnp8AAEAIAAD4+gAAv78An5rDAEBA'
325     'QAAuhAcAQEBAAAb8AABAvwAAAGQKAABAAABpLksAQEAIAC4ACwBAAAAAAPkGAAC/Q'
326     'AD2APoAvwC/AJ0umgBAQEAAAGRkAABAQAAGnp8AQEAIAPcA/AC/AL8A7D0GAEAIQA'
327     'D4hAAAv0AAAAD8QAAAvwgA92T6AL9AvwDsLlcAQEBAAC4AQABAAAgA+EAAAL8IAAA'
328     '8AAAACAAAAJ8uVgBAQEAAAGQ5AABAQAAAnpcAAEBAAPYAQAC/AAgAnQsGAEAAQAAA'
329     'hG0AAEBAAB38PQAIv0AA9mT6AL9AvwAJLmwAZUBAAB0AQAAIAAgAHUAAAAgIAAAAA'
330     'AAAAAAAAACzbAAAQEAA//k5AH+/QAAGb5cAQEBAAACy5AAAQAgAAIpAAABACAAAAA'
331     'AAAAAAAAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQk'
332     'JCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJ'
333     'CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJC'
334     'QkJCQkJCQkJCQkJCQkJCQkJCQkyEi8aQCEJCQkJCQkJCQkJCQkJCTI7OwgILzsyCg'
335     'kJCQkJCQkJCQkJCzcJFggvADwGEDc3EhYAMgkJCQkJEjcVJDohGj0LGgYAPT0hCT0'
336     'LDyI3CQoBLwAaFgkyEC9AJAE8OgsIMjoABi8kCx4JCQkJCQkeGko8KTcLCxIyNwkJ'
337     'CQkWEjwWNUAQPCEAMwgJCQkJCQkSQBcvEkAPAQkyN0AMCQkJCQhBFyEvNy89JCIkM'
338     'yItGQwJCQo9RxozIgkyCQoPFxAtDBkgIgkJCQkJCQkJMRoQECJQNi9EIAAgCQkJCQ'
339     'kSUA88UAYeBjELICA8HiI=\n')
340     self.assertEquals(renderer.raster_data, raw_data)
341    
342     self.assertEquals(dc.calls,
343     [('BeginDrawing',),
344     ('SetFont', "label font"),
345     ('EndDrawing',)])
346    
347     def test_point_map_projection(self):
348     """Test BaseRenderer with point layer and map projection"""
349     table = MemoryTable([("type", FIELDTYPE_STRING),
350     ("value", FIELDTYPE_DOUBLE),
351     ("code", FIELDTYPE_INT)],
352     [("UNKNOWN", 0.0, 0)])
353     shapes = [[[(10, 10)]]]
354     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
355    
356     map = Map("TestBaseRenderer")
357     map.SetProjection(MockProjection(-3, 3))
358     layer = Layer("point layer", store)
359     map.AddLayer(layer)
360     self.to_destroy.append(map)
361    
362     dc = MockDC()
363     renderer = SimpleRenderer(dc, 2, (10, 10))
364    
365     renderer.render_map(map)
366    
367     self.assertEquals(dc.calls,
368     [('BeginDrawing',),
369     ('SetBrush', ('brush', Transparent)),
370     ('SetPen', ('pen', Color(0, 0, 0), 1)),
371     ('DrawEllipse', -55, -55, 10, 10),
372     ('SetFont', "label font"),
373     ('EndDrawing',)])
374    
375     def test_point_layer_projection(self):
376     """Test BaseRenderer with point layer and layer projection"""
377     table = MemoryTable([("type", FIELDTYPE_STRING),
378     ("value", FIELDTYPE_DOUBLE),
379     ("code", FIELDTYPE_INT)],
380     [("UNKNOWN", 0.0, 0)])
381     shapes = [[[(9, 9)]]]
382     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
383    
384     map = Map("TestBaseRenderer")
385     layer = Layer("point layer", store)
386     layer.SetProjection(MockProjection(3, -3))
387     map.AddLayer(layer)
388     self.to_destroy.append(map)
389    
390     dc = MockDC()
391     renderer = SimpleRenderer(dc, 2, (10, 10))
392    
393     renderer.render_map(map)
394    
395     self.assertEquals(dc.calls,
396     [('BeginDrawing',),
397     ('SetBrush', ('brush', Transparent)),
398     ('SetPen', ('pen', Color(0, 0, 0), 1)),
399     ('DrawEllipse', 11, 11, 10, 10),
400     ('SetFont', "label font"),
401     ('EndDrawing',)])
402    
403     def test_point_layer_and_map_projection(self):
404     """Test BaseRenderer with point layer and layer and map projection"""
405     table = MemoryTable([("type", FIELDTYPE_STRING),
406     ("value", FIELDTYPE_DOUBLE),
407     ("code", FIELDTYPE_INT)],
408     [("UNKNOWN", 0.0, 0)])
409     shapes = [[[(9, 9)]]]
410     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
411    
412     map = Map("TestBaseRenderer")
413     map.SetProjection(MockProjection(-3, 3))
414     layer = Layer("point layer", store)
415     layer.SetProjection(MockProjection(3, -3))
416     map.AddLayer(layer)
417     self.to_destroy.append(map)
418    
419     dc = MockDC()
420     renderer = SimpleRenderer(dc, 2, (10, 10))
421    
422     renderer.render_map(map)
423    
424     self.assertEquals(dc.calls,
425     [('BeginDrawing',),
426     ('SetBrush', ('brush', Transparent)),
427     ('SetPen', ('pen', Color(0, 0, 0), 1)),
428     ('DrawEllipse', -13, 23, 10, 10),
429     ('SetFont', "label font"),
430     ('EndDrawing',)])
431    
432    
433    
434     if __name__ == "__main__":
435     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