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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1555 - (show annotations)
Thu Aug 7 15:41:05 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: 16591 byte(s)
* test/support.py (SkipTest, ThubanTestResult, ThubanTestRunner)
(ThubanTestProgram): New classes that extend the respective
classes from unittest. These new version support skipping tests
under certain expected conditions. In the Thuban test suite we
uses this for tests that require the optional gdal support.
(run_tests): Use ThubanTestProgram instead of the unittest.main()

* test/runtests.py (main): Use the new ThubanTestRunner instead of
the normal one from unittest

* test/test_layer.py (TestLayer.test_raster_layer): If this test
is not run because gdal support isn't available report this to the
runner.

* test/test_baserenderer.py
(TestBaseRenderer.test_raster_no_projection): Do not run this test
if gdal support isn't available and report this to the runner.

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