Skip to content

Commit e21de03

Browse files
committedApr 11, 2016
Add methods for retrieving and setting size units for QgsMarkerSymbolV2
1 parent 25ad0af commit e21de03

File tree

4 files changed

+301
-2
lines changed

4 files changed

+301
-2
lines changed
 

‎python/core/symbology-ng/qgssymbolv2.sip

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,19 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
363363

364364
QgsMarkerSymbolV2( const QgsSymbolLayerV2List& layers /Transfer/ = QgsSymbolLayerV2List() );
365365

366+
/** Sets the angle for the whole symbol. Individual symbol layer sizes
367+
* will be rotated to maintain their current relative angle to the whole symbol angle.
368+
* @param angle new symbol angle
369+
* @see angle()
370+
*/
366371
void setAngle( double angle );
372+
373+
/** Returns the marker angle for the whole symbol. Note that for symbols with
374+
* multiple symbol layers, this will correspond just to the angle of
375+
* the first symbol layer.
376+
* @note added in QGIS 2.16
377+
* @see setAngle()
378+
*/
367379
double angle() const;
368380

369381
/** Set data defined angle for whole symbol (including all symbol layers).
@@ -389,9 +401,60 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
389401
*/
390402
void setLineAngle( double lineAngle );
391403

404+
/** Sets the size for the whole symbol. Individual symbol layer sizes
405+
* will be scaled to maintain their current relative size to the whole symbol size.
406+
* @param size new symbol size
407+
* @see size()
408+
* @see setSizeUnit()
409+
* @see setSizeMapUnitScale()
410+
*/
392411
void setSize( double size );
412+
413+
/** Returns the size for the whole symbol, which is the maximum size of
414+
* all marker symbol layers in the symbol.
415+
* @see setSize()
416+
* @see sizeUnit()
417+
* @see sizeMapUnitScale()
418+
*/
393419
double size() const;
394420

421+
/** Sets the size units for the whole symbol (including all symbol layers).
422+
* @param unit size units
423+
* @note added in QGIS 2.16
424+
* @see sizeUnit()
425+
* @see setSizeMapUnitScale()
426+
* @see setSize()
427+
*/
428+
void setSizeUnit( OutputUnit unit );
429+
430+
/** Returns the size units for the whole symbol (including all symbol layers).
431+
* @returns size units, or mixed units if symbol layers have different units
432+
* @note added in QGIS 2.16
433+
* @see setSizeUnit()
434+
* @see sizeMapUnitScale()
435+
* @see size()
436+
*/
437+
OutputUnit sizeUnit() const;
438+
439+
/** Sets the size map unit scale for the whole symbol (including all symbol layers).
440+
* @param scale map unit scale
441+
* @note added in QGIS 2.16
442+
* @see sizeMapUnitScale()
443+
* @see setSizeUnit()
444+
* @see setSize()
445+
*/
446+
void setSizeMapUnitScale( const QgsMapUnitScale& scale );
447+
448+
/** Returns the size map unit scale for the whole symbol. Note that for symbols with
449+
* multiple symbol layers, this will correspond just to the map unit scale
450+
* for the first symbol layer.
451+
* @note added in QGIS 2.16
452+
* @see setSizeMapUnitScale()
453+
* @see sizeUnit()
454+
* @see size()
455+
*/
456+
QgsMapUnitScale sizeMapUnitScale() const;
457+
395458
/** Set data defined size for whole symbol (including all symbol layers).
396459
* @param dd data defined size
397460
* @note added in QGIS 2.9
@@ -415,7 +478,8 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
415478
/** Returns the approximate bounding box of the marker symbol, which includes the bounding box
416479
* of all symbol layers for the symbol.
417480
* @returns approximate symbol bounds, in painter units
418-
* @note added in QGIS 2.14 */
481+
* @note added in QGIS 2.14
482+
*/
419483
QRectF bounds( QPointF point, QgsRenderContext& context ) const;
420484

421485
virtual QgsMarkerSymbolV2* clone() const /Factory/;

‎src/core/symbology-ng/qgssymbolv2.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,67 @@ double QgsMarkerSymbolV2::size() const
12331233
return maxSize;
12341234
}
12351235

1236+
void QgsMarkerSymbolV2::setSizeUnit( QgsSymbolV2::OutputUnit unit )
1237+
{
1238+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1239+
{
1240+
if ( layer->type() != QgsSymbolV2::Marker )
1241+
continue;
1242+
1243+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1244+
markerLayer->setSizeUnit( unit );
1245+
}
1246+
}
1247+
1248+
QgsSymbolV2::OutputUnit QgsMarkerSymbolV2::sizeUnit() const
1249+
{
1250+
bool first = true;
1251+
OutputUnit unit = Mixed;
1252+
1253+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1254+
{
1255+
if ( layer->type() != QgsSymbolV2::Marker )
1256+
continue;
1257+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1258+
1259+
if ( first )
1260+
unit = markerLayer->sizeUnit();
1261+
else
1262+
{
1263+
if ( unit != markerLayer->sizeUnit() )
1264+
return Mixed;
1265+
}
1266+
1267+
first = false;
1268+
}
1269+
return unit;
1270+
}
1271+
1272+
void QgsMarkerSymbolV2::setSizeMapUnitScale( const QgsMapUnitScale &scale )
1273+
{
1274+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1275+
{
1276+
if ( layer->type() != QgsSymbolV2::Marker )
1277+
continue;
1278+
1279+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1280+
markerLayer->setSizeMapUnitScale( scale );
1281+
}
1282+
}
1283+
1284+
QgsMapUnitScale QgsMarkerSymbolV2::sizeMapUnitScale() const
1285+
{
1286+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1287+
{
1288+
if ( layer->type() != QgsSymbolV2::Marker )
1289+
continue;
1290+
1291+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1292+
return markerLayer->sizeMapUnitScale();
1293+
}
1294+
return QgsMapUnitScale();
1295+
}
1296+
12361297
void QgsMarkerSymbolV2::setDataDefinedSize( const QgsDataDefined &dd )
12371298
{
12381299
const double symbolSize = size();

‎src/core/symbology-ng/qgssymbolv2.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,14 +424,27 @@ class CORE_EXPORT QgsSymbolV2RenderContext
424424
class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
425425
{
426426
public:
427+
427428
/** Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
428429
* This is a convenience method for easier creation of marker symbols.
429430
*/
430431
static QgsMarkerSymbolV2* createSimple( const QgsStringMap& properties );
431432

432433
QgsMarkerSymbolV2( const QgsSymbolLayerV2List& layers = QgsSymbolLayerV2List() );
433434

435+
/** Sets the angle for the whole symbol. Individual symbol layer sizes
436+
* will be rotated to maintain their current relative angle to the whole symbol angle.
437+
* @param angle new symbol angle
438+
* @see angle()
439+
*/
434440
void setAngle( double angle );
441+
442+
/** Returns the marker angle for the whole symbol. Note that for symbols with
443+
* multiple symbol layers, this will correspond just to the angle of
444+
* the first symbol layer.
445+
* @note added in QGIS 2.16
446+
* @see setAngle()
447+
*/
435448
double angle() const;
436449

437450
/** Set data defined angle for whole symbol (including all symbol layers).
@@ -457,9 +470,60 @@ class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
457470
*/
458471
void setLineAngle( double lineAngle );
459472

473+
/** Sets the size for the whole symbol. Individual symbol layer sizes
474+
* will be scaled to maintain their current relative size to the whole symbol size.
475+
* @param size new symbol size
476+
* @see size()
477+
* @see setSizeUnit()
478+
* @see setSizeMapUnitScale()
479+
*/
460480
void setSize( double size );
481+
482+
/** Returns the size for the whole symbol, which is the maximum size of
483+
* all marker symbol layers in the symbol.
484+
* @see setSize()
485+
* @see sizeUnit()
486+
* @see sizeMapUnitScale()
487+
*/
461488
double size() const;
462489

490+
/** Sets the size units for the whole symbol (including all symbol layers).
491+
* @param unit size units
492+
* @note added in QGIS 2.16
493+
* @see sizeUnit()
494+
* @see setSizeMapUnitScale()
495+
* @see setSize()
496+
*/
497+
void setSizeUnit( OutputUnit unit );
498+
499+
/** Returns the size units for the whole symbol (including all symbol layers).
500+
* @returns size units, or mixed units if symbol layers have different units
501+
* @note added in QGIS 2.16
502+
* @see setSizeUnit()
503+
* @see sizeMapUnitScale()
504+
* @see size()
505+
*/
506+
OutputUnit sizeUnit() const;
507+
508+
/** Sets the size map unit scale for the whole symbol (including all symbol layers).
509+
* @param scale map unit scale
510+
* @note added in QGIS 2.16
511+
* @see sizeMapUnitScale()
512+
* @see setSizeUnit()
513+
* @see setSize()
514+
*/
515+
void setSizeMapUnitScale( const QgsMapUnitScale& scale );
516+
517+
/** Returns the size map unit scale for the whole symbol. Note that for symbols with
518+
* multiple symbol layers, this will correspond just to the map unit scale
519+
* for the first symbol layer.
520+
* @note added in QGIS 2.16
521+
* @see setSizeMapUnitScale()
522+
* @see sizeUnit()
523+
* @see size()
524+
*/
525+
QgsMapUnitScale sizeMapUnitScale() const;
526+
463527
/** Set data defined size for whole symbol (including all symbol layers).
464528
* @param dd data defined size
465529
* @note added in QGIS 2.9

‎tests/src/python/test_qgssymbolv2.py

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@
3131
from PyQt.QtGui import QImage, QColor, QPainter
3232

3333
from qgis.core import (QgsGeometry,
34+
QgsSymbolV2,
35+
QgsMapUnitScale,
3436
QgsMarkerSymbolV2,
3537
QgsFillSymbolV2,
3638
QgsLineSymbolV2,
3739
QgsRenderContext,
3840
QgsFeature,
3941
QGis,
4042
QgsMapSettings,
41-
QgsRenderChecker
43+
QgsRenderChecker,
44+
QgsSimpleMarkerSymbolLayerV2
4245
)
4346

4447
from qgis.testing import unittest, start_app
@@ -183,5 +186,112 @@ def imageCheck(self, name, reference_image, image):
183186
return result
184187

185188

189+
class TestQgsMarkerSymbolV2(unittest.TestCase):
190+
191+
def setUp(self):
192+
self.report = "<h1>Python QgsMarkerSymbolV2 Tests</h1>\n"
193+
194+
def tearDown(self):
195+
report_file_path = "%s/qgistest.html" % QDir.tempPath()
196+
with open(report_file_path, 'a') as report_file:
197+
report_file.write(self.report)
198+
199+
def testSize(self):
200+
# test size and setSize
201+
202+
# create a marker symbol with a single layer
203+
markerSymbol = QgsMarkerSymbolV2()
204+
markerSymbol.deleteSymbolLayer(0)
205+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
206+
self.assertEqual(markerSymbol.size(), 10)
207+
markerSymbol.setSize(20)
208+
self.assertEqual(markerSymbol.size(), 20)
209+
self.assertEqual(markerSymbol.symbolLayer(0).size(), 20)
210+
211+
# add additional layers
212+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
213+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 30))
214+
self.assertEqual(markerSymbol.size(), 30)
215+
markerSymbol.setSize(3)
216+
self.assertEqual(markerSymbol.size(), 3)
217+
# layer sizes should maintain relative size
218+
self.assertEqual(markerSymbol.symbolLayer(0).size(), 2)
219+
self.assertEqual(markerSymbol.symbolLayer(1).size(), 1)
220+
self.assertEqual(markerSymbol.symbolLayer(2).size(), 3)
221+
222+
def testAngle(self):
223+
# test angle and setAngle
224+
225+
# create a marker symbol with a single layer
226+
markerSymbol = QgsMarkerSymbolV2()
227+
markerSymbol.deleteSymbolLayer(0)
228+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10, 90))
229+
self.assertEqual(markerSymbol.angle(), 90)
230+
markerSymbol.setAngle(100)
231+
self.assertEqual(markerSymbol.angle(), 100)
232+
self.assertEqual(markerSymbol.symbolLayer(0).angle(), 100)
233+
234+
# add additional layers
235+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10, 130))
236+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10, 150))
237+
# should take first layer's angle
238+
self.assertEqual(markerSymbol.angle(), 100)
239+
markerSymbol.setAngle(10)
240+
self.assertEqual(markerSymbol.angle(), 10)
241+
# layer angles should maintain relative angle
242+
self.assertEqual(markerSymbol.symbolLayer(0).angle(), 10)
243+
self.assertEqual(markerSymbol.symbolLayer(1).angle(), 40)
244+
self.assertEqual(markerSymbol.symbolLayer(2).angle(), 60)
245+
246+
def testSizeUnit(self):
247+
# test sizeUnit and setSizeUnit
248+
249+
# create a marker symbol with a single layer
250+
markerSymbol = QgsMarkerSymbolV2()
251+
markerSymbol.deleteSymbolLayer(0)
252+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
253+
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.MM)
254+
markerSymbol.setSizeUnit(QgsSymbolV2.MapUnit)
255+
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.MapUnit)
256+
self.assertEqual(markerSymbol.symbolLayer(0).sizeUnit(), QgsSymbolV2.MapUnit)
257+
258+
# add additional layers
259+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
260+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 30))
261+
# should now be mixed size units
262+
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.Mixed)
263+
markerSymbol.setSizeUnit(QgsSymbolV2.Pixel)
264+
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.Pixel)
265+
# all layers should have size unit set
266+
self.assertEqual(markerSymbol.symbolLayer(0).sizeUnit(), QgsSymbolV2.Pixel)
267+
self.assertEqual(markerSymbol.symbolLayer(1).sizeUnit(), QgsSymbolV2.Pixel)
268+
self.assertEqual(markerSymbol.symbolLayer(2).sizeUnit(), QgsSymbolV2.Pixel)
269+
270+
def testSizeMapUnitScale(self):
271+
# test sizeMapUnitScale and setSizeMapUnitScale
272+
273+
# create a marker symbol with a single layer
274+
markerSymbol = QgsMarkerSymbolV2()
275+
markerSymbol.deleteSymbolLayer(0)
276+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
277+
markerSymbol.symbolLayer(0).setSizeMapUnitScale(QgsMapUnitScale(10000, 20000))
278+
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(10000, 20000))
279+
markerSymbol.setSizeMapUnitScale(QgsMapUnitScale(1000, 2000))
280+
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(1000, 2000))
281+
self.assertEqual(markerSymbol.symbolLayer(0).sizeMapUnitScale(), QgsMapUnitScale(1000, 2000))
282+
283+
# add additional layers
284+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
285+
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 30))
286+
# should take first layer's map unit scale
287+
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(1000, 2000))
288+
markerSymbol.setSizeMapUnitScale(QgsMapUnitScale(3000, 4000))
289+
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
290+
# all layers should have size unit set
291+
self.assertEqual(markerSymbol.symbolLayer(0).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
292+
self.assertEqual(markerSymbol.symbolLayer(1).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
293+
self.assertEqual(markerSymbol.symbolLayer(2).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
294+
295+
186296
if __name__ == '__main__':
187297
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.