Skip to content

Commit 1a7dede

Browse files
committedJan 21, 2016
Add TestQgsSymbolV2 with tests for rendering different geometry types
1 parent 0063381 commit 1a7dede

File tree

11 files changed

+186
-0
lines changed

11 files changed

+186
-0
lines changed
 

‎tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ ADD_PYTHON_TEST(PyQgsSpatialiteProvider test_provider_spatialite.py)
6060
ADD_PYTHON_TEST(PyQgsSymbolLayerV2 test_qgssymbollayerv2.py)
6161
ADD_PYTHON_TEST(PyQgsSymbolExpressionVariables test_qgssymbolexpressionvariables.py)
6262
ADD_PYTHON_TEST(PyQgsSyntacticSugar test_syntactic_sugar.py)
63+
ADD_PYTHON_TEST(PyQgsSymbolV2 test_qgssymbolv2.py)
6364
ADD_PYTHON_TEST(PyQgsVectorColorRamp test_qgsvectorcolorramp.py)
6465
ADD_PYTHON_TEST(PyQgsVectorFileWriter test_qgsvectorfilewriter.py)
6566
ADD_PYTHON_TEST(PyQgsVectorLayer test_qgsvectorlayer.py)

‎tests/src/python/test_qgssymbolv2.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
test_qgssymbolv2.py
6+
---------------------
7+
Date : January 2016
8+
Copyright : (C) 2016 by Nyall Dawson
9+
Email : nyall dot dawson at gmail dot com
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
__author__ = 'Nyall Dawson'
21+
__date__ = 'January 2016'
22+
__copyright__ = '(C) 2016, Nyall Dawson'
23+
# This will get replaced with a git SHA1 when you do a git archive
24+
__revision__ = '$Format:%H$'
25+
26+
import os
27+
import csv
28+
29+
from utilities import (unitTestDataPath,
30+
getQgisTestApp,
31+
TestCase,
32+
unittest,
33+
expectedFailure
34+
)
35+
36+
from PyQt4.QtCore import QSize, QDir
37+
from PyQt4.QtGui import QImage, QColor, QPainter
38+
39+
from qgis.core import (QgsGeometry,
40+
QgsMarkerSymbolV2,
41+
QgsFillSymbolV2,
42+
QgsLineSymbolV2,
43+
QgsRenderContext,
44+
QgsFeature,
45+
QGis,
46+
QgsMapSettings,
47+
QgsRectangle,
48+
QgsRenderChecker
49+
)
50+
51+
QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
52+
TEST_DATA_DIR = unitTestDataPath()
53+
54+
55+
class TestQgsSymbolV2(TestCase):
56+
57+
def setUp(self):
58+
#Create some simple symbols
59+
self.fill_symbol = QgsFillSymbolV2.createSimple({'color': '#ffffff'})
60+
self.line_symbol = QgsLineSymbolV2.createSimple({'color': '#ffffff', 'line_width': '3'})
61+
self.marker_symbol = QgsMarkerSymbolV2.createSimple({'color': '#ffffff', 'size': '3'})
62+
self.report = "<h1>Python QgsSymbolV2 Tests</h1>\n"
63+
64+
def tearDown(self):
65+
report_file_path = "%s/qgistest.html" % QDir.tempPath()
66+
with open(report_file_path, 'a') as report_file:
67+
report_file.write(self.report)
68+
69+
def testGeometryRendering(self):
70+
'''Tests rendering a bunch of different geometries, including bad/odd geometries.'''
71+
72+
tests = [{'name': 'Point',
73+
'wkt': 'Point (1 2)',
74+
'reference_image': 'point'},
75+
{'name': 'MultiPoint',
76+
'wkt': 'MultiPoint ((10 30),(40 20),(30 10),(20 10))',
77+
'reference_image': 'multipoint'},
78+
{'name': 'LineString',
79+
'wkt': 'LineString (0 0,3 4,4 3)',
80+
'reference_image': 'linestring'},
81+
{'name': 'MultiLineString',
82+
'wkt': 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 1, 5 1, 5 0, 6 0))',
83+
'reference_image': 'multilinestring'},
84+
{'name': 'Polygon',
85+
'wkt': 'Polygon ((0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5))',
86+
'reference_image': 'polygon'},
87+
{'name': 'MultiPolygon',
88+
'wkt': 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))',
89+
'reference_image': 'multipolygon'},
90+
{'name': 'CircularString',
91+
'wkt': 'CIRCULARSTRING(268 415,227 505,227 406)',
92+
'reference_image': 'circular_string'},
93+
{'name': 'CompoundCurve',
94+
'wkt': 'COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))',
95+
'reference_image': 'compound_curve'},
96+
{'name': 'CurvePolygon',
97+
'wkt': 'CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))',
98+
'reference_image': 'curve_polygon'}]
99+
100+
for test in tests:
101+
geom = QgsGeometry.fromWkt(test['wkt'])
102+
assert geom and not geom.isEmpty(), 'Could not create geometry'
103+
rendered_image = self.renderGeometry(geom)
104+
assert self.imageCheck(test['name'], test['reference_image'], rendered_image)
105+
106+
#Note - each test is repeated with the same geometry and reference image, but with added
107+
#z and m dimensions. This tests that presence of the dimensions does not affect rendering
108+
109+
#test with Z
110+
geom_z = QgsGeometry.fromWkt(test['wkt'])
111+
geom_z.geometry().addZValue(5)
112+
rendered_image = self.renderGeometry(geom_z)
113+
assert self.imageCheck(test['name'] + ' z', test['reference_image'], rendered_image)
114+
115+
#test with ZM
116+
geom_z.geometry().addMValue(15)
117+
rendered_image = self.renderGeometry(geom_z)
118+
assert self.imageCheck(test['name'] + ' zm', test['reference_image'], rendered_image)
119+
120+
#test with ZM
121+
geom_m = QgsGeometry.fromWkt(test['wkt'])
122+
geom_m.geometry().addMValue(15)
123+
rendered_image = self.renderGeometry(geom_m)
124+
assert self.imageCheck(test['name'] + ' m', test['reference_image'], rendered_image)
125+
126+
def renderGeometry(self, geom):
127+
f = QgsFeature()
128+
f.setGeometry(geom)
129+
130+
image = QImage(200, 200, QImage.Format_RGB32)
131+
132+
painter = QPainter()
133+
ms = QgsMapSettings()
134+
extent = geom.geometry().boundingBox()
135+
# buffer extent by 10%
136+
if extent.width() > 0:
137+
extent = extent.buffer((extent.height() + extent.width()) / 20.0)
138+
else:
139+
extent = extent.buffer(10)
140+
141+
ms.setExtent(extent)
142+
ms.setOutputSize(image.size())
143+
context = QgsRenderContext.fromMapSettings(ms)
144+
context.setPainter(painter)
145+
context.setScaleFactor(96 / 25.4) # 96 DPI
146+
147+
painter.begin(image)
148+
image.fill(QColor(0, 0, 0))
149+
150+
if geom.type() == QGis.Polygon:
151+
self.fill_symbol.startRender(context)
152+
self.fill_symbol.renderFeature(f, context)
153+
self.fill_symbol.stopRender(context)
154+
155+
elif geom.type() == QGis.Line:
156+
self.line_symbol.startRender(context)
157+
self.line_symbol.renderFeature(f, context)
158+
self.line_symbol.stopRender(context)
159+
160+
elif geom.type() == QGis.Point:
161+
self.marker_symbol.startRender(context)
162+
self.marker_symbol.renderFeature(f, context)
163+
self.marker_symbol.stopRender(context)
164+
165+
painter.end()
166+
return image
167+
168+
def imageCheck(self, name, reference_image, image):
169+
self.report += "<h2>Render {}</h2>\n".format(name)
170+
temp_dir = QDir.tempPath() + '/'
171+
file_name = temp_dir + 'symbol_' + name + ".png"
172+
image.save(file_name, "PNG")
173+
checker = QgsRenderChecker()
174+
checker.setControlPathPrefix("symbolv2")
175+
checker.setControlName("expected_" + reference_image)
176+
checker.setRenderedImage(file_name)
177+
checker.setColorTolerance(2)
178+
result = checker.compareImages(name, 20)
179+
self.report += checker.report()
180+
print self.report
181+
return result
182+
183+
184+
if __name__ == '__main__':
185+
unittest.main()# -*- coding: utf-8 -*-
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)
Please sign in to comment.