Skip to content
Permalink
Browse files

Add methods for retrieving and setting size units for QgsMarkerSymbolV2

  • Loading branch information
nyalldawson committed Apr 11, 2016
1 parent 25ad0af commit e21de0394d051de1eea7ce36d587cc933c474bae
@@ -363,7 +363,19 @@ class QgsMarkerSymbolV2 : QgsSymbolV2

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

/** Sets the angle for the whole symbol. Individual symbol layer sizes
* will be rotated to maintain their current relative angle to the whole symbol angle.
* @param angle new symbol angle
* @see angle()
*/
void setAngle( double angle );

/** Returns the marker angle for the whole symbol. Note that for symbols with
* multiple symbol layers, this will correspond just to the angle of
* the first symbol layer.
* @note added in QGIS 2.16
* @see setAngle()
*/
double angle() const;

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

/** Sets the size for the whole symbol. Individual symbol layer sizes
* will be scaled to maintain their current relative size to the whole symbol size.
* @param size new symbol size
* @see size()
* @see setSizeUnit()
* @see setSizeMapUnitScale()
*/
void setSize( double size );

/** Returns the size for the whole symbol, which is the maximum size of
* all marker symbol layers in the symbol.
* @see setSize()
* @see sizeUnit()
* @see sizeMapUnitScale()
*/
double size() const;

/** Sets the size units for the whole symbol (including all symbol layers).
* @param unit size units
* @note added in QGIS 2.16
* @see sizeUnit()
* @see setSizeMapUnitScale()
* @see setSize()
*/
void setSizeUnit( OutputUnit unit );

/** Returns the size units for the whole symbol (including all symbol layers).
* @returns size units, or mixed units if symbol layers have different units
* @note added in QGIS 2.16
* @see setSizeUnit()
* @see sizeMapUnitScale()
* @see size()
*/
OutputUnit sizeUnit() const;

/** Sets the size map unit scale for the whole symbol (including all symbol layers).
* @param scale map unit scale
* @note added in QGIS 2.16
* @see sizeMapUnitScale()
* @see setSizeUnit()
* @see setSize()
*/
void setSizeMapUnitScale( const QgsMapUnitScale& scale );

/** Returns the size map unit scale for the whole symbol. Note that for symbols with
* multiple symbol layers, this will correspond just to the map unit scale
* for the first symbol layer.
* @note added in QGIS 2.16
* @see setSizeMapUnitScale()
* @see sizeUnit()
* @see size()
*/
QgsMapUnitScale sizeMapUnitScale() const;

/** Set data defined size for whole symbol (including all symbol layers).
* @param dd data defined size
* @note added in QGIS 2.9
@@ -415,7 +478,8 @@ class QgsMarkerSymbolV2 : QgsSymbolV2
/** Returns the approximate bounding box of the marker symbol, which includes the bounding box
* of all symbol layers for the symbol.
* @returns approximate symbol bounds, in painter units
* @note added in QGIS 2.14 */
* @note added in QGIS 2.14
*/
QRectF bounds( QPointF point, QgsRenderContext& context ) const;

virtual QgsMarkerSymbolV2* clone() const /Factory/;
@@ -1233,6 +1233,67 @@ double QgsMarkerSymbolV2::size() const
return maxSize;
}

void QgsMarkerSymbolV2::setSizeUnit( QgsSymbolV2::OutputUnit unit )
{
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
{
if ( layer->type() != QgsSymbolV2::Marker )
continue;

QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
markerLayer->setSizeUnit( unit );
}
}

QgsSymbolV2::OutputUnit QgsMarkerSymbolV2::sizeUnit() const
{
bool first = true;
OutputUnit unit = Mixed;

Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
{
if ( layer->type() != QgsSymbolV2::Marker )
continue;
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );

if ( first )
unit = markerLayer->sizeUnit();
else
{
if ( unit != markerLayer->sizeUnit() )
return Mixed;
}

first = false;
}
return unit;
}

void QgsMarkerSymbolV2::setSizeMapUnitScale( const QgsMapUnitScale &scale )
{
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
{
if ( layer->type() != QgsSymbolV2::Marker )
continue;

QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
markerLayer->setSizeMapUnitScale( scale );
}
}

QgsMapUnitScale QgsMarkerSymbolV2::sizeMapUnitScale() const
{
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
{
if ( layer->type() != QgsSymbolV2::Marker )
continue;

QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
return markerLayer->sizeMapUnitScale();
}
return QgsMapUnitScale();
}

void QgsMarkerSymbolV2::setDataDefinedSize( const QgsDataDefined &dd )
{
const double symbolSize = size();
@@ -424,14 +424,27 @@ class CORE_EXPORT QgsSymbolV2RenderContext
class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
{
public:

/** Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
* This is a convenience method for easier creation of marker symbols.
*/
static QgsMarkerSymbolV2* createSimple( const QgsStringMap& properties );

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

/** Sets the angle for the whole symbol. Individual symbol layer sizes
* will be rotated to maintain their current relative angle to the whole symbol angle.
* @param angle new symbol angle
* @see angle()
*/
void setAngle( double angle );

/** Returns the marker angle for the whole symbol. Note that for symbols with
* multiple symbol layers, this will correspond just to the angle of
* the first symbol layer.
* @note added in QGIS 2.16
* @see setAngle()
*/
double angle() const;

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

/** Sets the size for the whole symbol. Individual symbol layer sizes
* will be scaled to maintain their current relative size to the whole symbol size.
* @param size new symbol size
* @see size()
* @see setSizeUnit()
* @see setSizeMapUnitScale()
*/
void setSize( double size );

/** Returns the size for the whole symbol, which is the maximum size of
* all marker symbol layers in the symbol.
* @see setSize()
* @see sizeUnit()
* @see sizeMapUnitScale()
*/
double size() const;

/** Sets the size units for the whole symbol (including all symbol layers).
* @param unit size units
* @note added in QGIS 2.16
* @see sizeUnit()
* @see setSizeMapUnitScale()
* @see setSize()
*/
void setSizeUnit( OutputUnit unit );

/** Returns the size units for the whole symbol (including all symbol layers).
* @returns size units, or mixed units if symbol layers have different units
* @note added in QGIS 2.16
* @see setSizeUnit()
* @see sizeMapUnitScale()
* @see size()
*/
OutputUnit sizeUnit() const;

/** Sets the size map unit scale for the whole symbol (including all symbol layers).
* @param scale map unit scale
* @note added in QGIS 2.16
* @see sizeMapUnitScale()
* @see setSizeUnit()
* @see setSize()
*/
void setSizeMapUnitScale( const QgsMapUnitScale& scale );

/** Returns the size map unit scale for the whole symbol. Note that for symbols with
* multiple symbol layers, this will correspond just to the map unit scale
* for the first symbol layer.
* @note added in QGIS 2.16
* @see setSizeMapUnitScale()
* @see sizeUnit()
* @see size()
*/
QgsMapUnitScale sizeMapUnitScale() const;

/** Set data defined size for whole symbol (including all symbol layers).
* @param dd data defined size
* @note added in QGIS 2.9
@@ -31,14 +31,17 @@
from PyQt.QtGui import QImage, QColor, QPainter

from qgis.core import (QgsGeometry,
QgsSymbolV2,
QgsMapUnitScale,
QgsMarkerSymbolV2,
QgsFillSymbolV2,
QgsLineSymbolV2,
QgsRenderContext,
QgsFeature,
QGis,
QgsMapSettings,
QgsRenderChecker
QgsRenderChecker,
QgsSimpleMarkerSymbolLayerV2
)

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


class TestQgsMarkerSymbolV2(unittest.TestCase):

def setUp(self):
self.report = "<h1>Python QgsMarkerSymbolV2 Tests</h1>\n"

def tearDown(self):
report_file_path = "%s/qgistest.html" % QDir.tempPath()
with open(report_file_path, 'a') as report_file:
report_file.write(self.report)

def testSize(self):
# test size and setSize

# create a marker symbol with a single layer
markerSymbol = QgsMarkerSymbolV2()
markerSymbol.deleteSymbolLayer(0)
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
self.assertEqual(markerSymbol.size(), 10)
markerSymbol.setSize(20)
self.assertEqual(markerSymbol.size(), 20)
self.assertEqual(markerSymbol.symbolLayer(0).size(), 20)

# add additional layers
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 30))
self.assertEqual(markerSymbol.size(), 30)
markerSymbol.setSize(3)
self.assertEqual(markerSymbol.size(), 3)
# layer sizes should maintain relative size
self.assertEqual(markerSymbol.symbolLayer(0).size(), 2)
self.assertEqual(markerSymbol.symbolLayer(1).size(), 1)
self.assertEqual(markerSymbol.symbolLayer(2).size(), 3)

def testAngle(self):
# test angle and setAngle

# create a marker symbol with a single layer
markerSymbol = QgsMarkerSymbolV2()
markerSymbol.deleteSymbolLayer(0)
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10, 90))
self.assertEqual(markerSymbol.angle(), 90)
markerSymbol.setAngle(100)
self.assertEqual(markerSymbol.angle(), 100)
self.assertEqual(markerSymbol.symbolLayer(0).angle(), 100)

# add additional layers
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10, 130))
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10, 150))
# should take first layer's angle
self.assertEqual(markerSymbol.angle(), 100)
markerSymbol.setAngle(10)
self.assertEqual(markerSymbol.angle(), 10)
# layer angles should maintain relative angle
self.assertEqual(markerSymbol.symbolLayer(0).angle(), 10)
self.assertEqual(markerSymbol.symbolLayer(1).angle(), 40)
self.assertEqual(markerSymbol.symbolLayer(2).angle(), 60)

def testSizeUnit(self):
# test sizeUnit and setSizeUnit

# create a marker symbol with a single layer
markerSymbol = QgsMarkerSymbolV2()
markerSymbol.deleteSymbolLayer(0)
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.MM)
markerSymbol.setSizeUnit(QgsSymbolV2.MapUnit)
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.MapUnit)
self.assertEqual(markerSymbol.symbolLayer(0).sizeUnit(), QgsSymbolV2.MapUnit)

# add additional layers
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 30))
# should now be mixed size units
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.Mixed)
markerSymbol.setSizeUnit(QgsSymbolV2.Pixel)
self.assertEqual(markerSymbol.sizeUnit(), QgsSymbolV2.Pixel)
# all layers should have size unit set
self.assertEqual(markerSymbol.symbolLayer(0).sizeUnit(), QgsSymbolV2.Pixel)
self.assertEqual(markerSymbol.symbolLayer(1).sizeUnit(), QgsSymbolV2.Pixel)
self.assertEqual(markerSymbol.symbolLayer(2).sizeUnit(), QgsSymbolV2.Pixel)

def testSizeMapUnitScale(self):
# test sizeMapUnitScale and setSizeMapUnitScale

# create a marker symbol with a single layer
markerSymbol = QgsMarkerSymbolV2()
markerSymbol.deleteSymbolLayer(0)
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
markerSymbol.symbolLayer(0).setSizeMapUnitScale(QgsMapUnitScale(10000, 20000))
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(10000, 20000))
markerSymbol.setSizeMapUnitScale(QgsMapUnitScale(1000, 2000))
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(1000, 2000))
self.assertEqual(markerSymbol.symbolLayer(0).sizeMapUnitScale(), QgsMapUnitScale(1000, 2000))

# add additional layers
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 10))
markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayerV2('star', QColor(255, 0, 0), QColor(0, 255, 0), 30))
# should take first layer's map unit scale
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(1000, 2000))
markerSymbol.setSizeMapUnitScale(QgsMapUnitScale(3000, 4000))
self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
# all layers should have size unit set
self.assertEqual(markerSymbol.symbolLayer(0).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
self.assertEqual(markerSymbol.symbolLayer(1).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
self.assertEqual(markerSymbol.symbolLayer(2).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))


if __name__ == '__main__':
unittest.main()

0 comments on commit e21de03

Please sign in to comment.
You can’t perform that action at this time.