Skip to content
Permalink
Browse files

[FEATURE] New "Filled marker" symbol layer type

A "filled marker" is similar to the simple marker symbol layer, except
that it uses a fill sub symbol to render the marker. This allows use
of all the existing QGIS fill (and outline) styles for rendering
markers, eg gradient or shapeburst fills.

A new abstract class QgsSimpleMarkerSymbolLayerBase has been created
from which both QgsSimpleMarkerSymbolLayerV2 and
QgsFilledMarkerSymbolLayer derive. All common code has been moved to
this base class, allowing for easy addition of new shapes or features
to both simple markers and filled markers without duplication.

Also, adds a lot of missing docs to marker symbol layers.
  • Loading branch information
nyalldawson committed May 5, 2016
1 parent cda387c commit ea2014923914d21e5414b33461c8b40fe39f92dd
Showing with 2,945 additions and 654 deletions.
  1. +340 −54 python/core/symbology-ng/qgsmarkersymbollayerv2.sip
  2. +182 −23 python/core/symbology-ng/qgssymbollayerv2.sip
  3. +35 −0 python/gui/symbology-ng/qgssymbollayerv2widget.sip
  4. +1 −2 src/app/qgsdecorationgrid.cpp
  5. +965 −468 src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
  6. +357 −59 src/core/symbology-ng/qgsmarkersymbollayerv2.h
  7. +190 −25 src/core/symbology-ng/qgssymbollayerv2.h
  8. +2 −0 src/core/symbology-ng/qgssymbollayerv2registry.cpp
  9. +4 −2 src/core/symbology-ng/qgssymbologyv2conversion.cpp
  10. +1 −0 src/gui/symbology-ng/qgslayerpropertieswidget.cpp
  11. +190 −11 src/gui/symbology-ng/qgssymbollayerv2widget.cpp
  12. +55 −0 src/gui/symbology-ng/qgssymbollayerv2widget.h
  13. +3 −1 src/plugins/grass/qgsgrasseditrenderer.cpp
  14. +338 −0 src/ui/symbollayer/widget_filledmarker.ui
  15. +1 −0 tests/src/core/CMakeLists.txt
  16. +198 −0 tests/src/core/testqgsfilledmarker.cpp
  17. +8 −8 tests/src/core/testqgssimplemarker.cpp
  18. +75 −1 tests/src/python/test_qgssymbollayerv2.py
  19. BIN tests/testdata/control_images/symbol_filledmarker/expected_filledmarker/expected_filledmarker.png
  20. BIN .../testdata/control_images/symbol_filledmarker/expected_filledmarker/expected_filledmarker_mask.png
  21. BIN .../control_images/symbol_filledmarker/expected_filledmarker_bounds/expected_filledmarker_bounds.png
  22. BIN ...rol_images/symbol_filledmarker/expected_filledmarker_bounds/expected_filledmarker_bounds_mask.png
  23. BIN ...ol_filledmarker/expected_filledmarker_datadefinedshape/expected_filledmarker_datadefinedshape.png
  24. BIN ...lledmarker/expected_filledmarker_datadefinedshape/expected_filledmarker_datadefinedshape_mask.png

Large diffs are not rendered by default.

@@ -15,6 +15,8 @@ class QgsSymbolLayerV2
sipType = sipType_QgsFontMarkerSymbolLayerV2;
else if (dynamic_cast<QgsSimpleMarkerSymbolLayerV2*>(sipCpp) != NULL)
sipType = sipType_QgsSimpleMarkerSymbolLayerV2;
else if (dynamic_cast<QgsFilledMarkerSymbolLayer*>(sipCpp) != NULL)
sipType = sipType_QgsFilledMarkerSymbolLayer;
else if (dynamic_cast<QgsSvgMarkerSymbolLayerV2*>(sipCpp) != NULL)
sipType = sipType_QgsSvgMarkerSymbolLayerV2;
else if (dynamic_cast<QgsVectorFieldSymbolLayer*>(sipCpp) != NULL)
@@ -28,6 +30,8 @@ class QgsSymbolLayerV2
sipType = sipType_QgsMarkerLineSymbolLayerV2;
else if (dynamic_cast<QgsSimpleLineSymbolLayerV2*>(sipCpp) != NULL)
sipType = sipType_QgsSimpleLineSymbolLayerV2;
else if (dynamic_cast<QgsArrowSymbolLayer*>(sipCpp) != NULL)
sipType = sipType_QgsArrowSymbolLayer;
else
sipType = sipType_QgsLineSymbolLayerV2;
break;
@@ -330,81 +334,214 @@ class QgsSymbolLayerV2

//////////////////////

/** \ingroup core
* \class QgsMarkerSymbolLayerV2
* \brief Abstract base class for marker symbol layers.
*/
class QgsMarkerSymbolLayerV2 : QgsSymbolLayerV2
{
%TypeHeaderCode
#include <qgssymbollayerv2.h>
%End
public:

//! Symbol horizontal anchor points
enum HorizontalAnchorPoint
{
Left,
HCenter,
Right
Left, /*!< Align to left side of symbol */
HCenter, /*!< Align to horizontal center of symbol */
Right, /*!< Align to right side of symbol */
};

//! Symbol vertical anchor points
enum VerticalAnchorPoint
{
Top,
VCenter,
Bottom
Top, /*!< Align to top of symbol */
VCenter, /*!< Align to vertical center of symbol */
Bottom, /*!< Align to bottom of symbol */
};

void startRender( QgsSymbolV2RenderContext& context );

/** Renders a marker at the specified point. Derived classes must implement this to
* handle drawing the point.
* @param point position at which to render point, in painter units
* @param context symbol render context
*/
virtual void renderPoint( QPointF point, QgsSymbolV2RenderContext& context ) = 0;

void drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size );

/** Sets the rotation angle for the marker.
* @param angle angle in degrees clockwise from north.
* @see angle()
* @see setLineAngle()
*/
void setAngle( double angle );

/** Returns the rotation angle for the marker, in degrees clockwise from north.
* @see setAngle()
*/
double angle() const;

/** Sets the line angle modification for the symbol's angle. This angle is added to
* the marker's rotation and data defined rotation before rendering the symbol, and
* is usually used for orienting symbols to match a line's angle.
* @param lineAngle Angle in degrees, valid values are between 0 and 360
* @param lineAngle Angle in degrees clockwise from north, valid values are between 0 and 360
* @note added in QGIS 2.9
* @see setAngle()
* @see angle()
*/
void setLineAngle( double lineAngle );

/** Sets the symbol size.
* @param size symbol size. Units are specified by sizeUnit().
* @see size()
* @see setSizeUnit()
* @see setSizeMapUnitScale()
*/
void setSize( double size );

/** Returns the symbol size. Units are specified by sizeUnit().
* @see setSize()
* @see sizeUnit()
* @see sizeUnitMapScale()
*/
double size() const;

/** Sets the units for the symbol's size.
* @param unit size units
* @see sizeUnit()
* @see setSize()
* @see setSizeMapUnitScale()
*/
void setSizeUnit( QgsSymbolV2::OutputUnit unit );

/** Returns the units for the symbol's size.
* @see setSizeUnit()
* @see size()
* @see sizeMapUnitScale()
*/
QgsSymbolV2::OutputUnit sizeUnit() const;

/** Sets the map unit scale for the symbol's size.
* @param scale size map unit scale
* @see sizeMapUnitScale()
* @see setSize()
* @see setSizeUnit()
*/
void setSizeMapUnitScale( const QgsMapUnitScale& scale);

/** Returns the map unit scale for the symbol's size.
* @see setSizeMapUnitScale()
* @see size()
* @see sizeUnit()
*/
const QgsMapUnitScale& sizeMapUnitScale() const;

/** Sets the method to use for scaling the marker's size.
* @param scaleMethod scale method
* @see scaleMethod()
*/
void setScaleMethod( QgsSymbolV2::ScaleMethod scaleMethod );

/** Returns the method to use for scaling the marker's size.
* @see setScaleMethod()
*/
QgsSymbolV2::ScaleMethod scaleMethod() const;

/** Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker
* should have from the original feature's geometry.
* @param offset marker offset. Units are specified by offsetUnit()
* @see offset()
* @see setOffsetUnit()
* @see setOffsetMapUnitScale()
*/
void setOffset( QPointF offset );
QPointF offset();

virtual void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const;

virtual void writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const;
/** Returns the marker's offset, which is the horizontal and vertical displacement which the rendered marker
* will have from the original feature's geometry. Units are specified by offsetUnit().
* @see setOffset()
* @see offsetUnit()
* @see offsetMapUnitScale()
*/
QPointF offset();

/** Sets the units for the symbol's offset.
* @param unit offset units
* @see offsetUnit()
* @see setOffset()
* @see setOffsetMapUnitScale()
*/
void setOffsetUnit( QgsSymbolV2::OutputUnit unit );

/** Returns the units for the symbol's offset.
* @see setOffsetUnit()
* @see offset()
* @see offsetMapUnitScale()
*/
QgsSymbolV2::OutputUnit offsetUnit() const;

/** Sets the map unit scale for the symbol's offset.
* @param scale offset map unit scale
* @see offsetMapUnitScale()
* @see setOffset()
* @see setOffsetUnit()
*/
void setOffsetMapUnitScale( const QgsMapUnitScale& scale);

/** Returns the map unit scale for the symbol's offset.
* @see setOffsetMapUnitScale()
* @see offset()
* @see offsetUnit()
*/
const QgsMapUnitScale& offsetMapUnitScale() const;

void setSizeUnit( QgsSymbolV2::OutputUnit unit );
QgsSymbolV2::OutputUnit sizeUnit() const;
/** Sets the horizontal anchor point for positioning the symbol.
* @param h anchor point. Symbol will be drawn so that the horizontal anchor point is aligned with
* the marker's desired location.
* @see horizontalAnchorPoint()
* @see setVerticalAnchorPoint()
*/
void setHorizontalAnchorPoint( HorizontalAnchorPoint h );

void setSizeMapUnitScale( const QgsMapUnitScale& scale);
const QgsMapUnitScale& sizeMapUnitScale() const;
/** Returns the horizontal anchor point for positioning the symbol. The symbol will be drawn so that
* the horizontal anchor point is aligned with the marker's desired location.
* @see setHorizontalAnchorPoint()
* @see verticalAnchorPoint()
*/
HorizontalAnchorPoint horizontalAnchorPoint() const;

/** Sets the vertical anchor point for positioning the symbol.
* @param v anchor point. Symbol will be drawn so that the vertical anchor point is aligned with
* the marker's desired location.
* @see verticalAnchorPoint()
* @see setHorizontalAnchorPoint()
*/
void setVerticalAnchorPoint( VerticalAnchorPoint v );

/** Returns the vertical anchor point for positioning the symbol. The symbol will be drawn so that
* the vertical anchor point is aligned with the marker's desired location.
* @see setVerticalAnchorPoint()
* @see horizontalAnchorPoint()
*/
VerticalAnchorPoint verticalAnchorPoint() const;

virtual void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const;

/** Writes the symbol layer definition as a SLD XML element.
* @param doc XML document
* @param element parent XML element
* @param props symbol layer definition (see properties())
*/
virtual void writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const;

void setOutputUnit( QgsSymbolV2::OutputUnit unit );
QgsSymbolV2::OutputUnit outputUnit() const;

void setMapUnitScale( const QgsMapUnitScale& scale );
QgsMapUnitScale mapUnitScale() const;

void setHorizontalAnchorPoint( HorizontalAnchorPoint h );
HorizontalAnchorPoint horizontalAnchorPoint() const;

void setVerticalAnchorPoint( VerticalAnchorPoint v );
VerticalAnchorPoint verticalAnchorPoint() const;

/** Returns the approximate bounding box of the marker symbol layer, taking into account
* any data defined overrides and offsets which are set for the marker layer.
* @returns approximate symbol bounds, in painter units
@@ -415,12 +552,29 @@ class QgsMarkerSymbolLayerV2 : QgsSymbolLayerV2
virtual QRectF bounds( QPointF point, QgsSymbolV2RenderContext& context );

protected:

/** Constructor for QgsMarkerSymbolLayerV2.
* @param locked set to true to lock symbol color
*/
QgsMarkerSymbolLayerV2( bool locked = false );

//handles marker offset and anchor point shift together
/** Calculates the required marker offset, including both the symbol offset
* and any displacement required to align with the marker's anchor point.
* @param context symbol render context
* @param offsetX will be set to required horizontal offset (in painter units)
* @param offsetY will be set to required vertical offset (in painter units)
*/
void markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY ) const;

//! @note available in python as markerOffsetWithWidthAndHeight
/** Calculates the required marker offset, including both the symbol offset
* and any displacement required to align with the marker's anchor point.
* @param context symbol render context
* @param width marker width
* @param height marker height
* @param offsetX will be set to required horizontal offset (in painter units)
* @param offsetY will be set to required vertical offset (in painter units)
* @note available in python as markerOffsetWithWidthAndHeight
*/
void markerOffset( QgsSymbolV2RenderContext& context, double width, double height, double& offsetX, double& offsetY ) const /PyName=markerOffsetWithWidthAndHeight/;

//! @note available in python bindings as markerOffset2
@@ -429,6 +583,11 @@ class QgsMarkerSymbolLayerV2 : QgsSymbolLayerV2
double& offsetX, double& offsetY,
const QgsMapUnitScale &widthMapUnitScale, const QgsMapUnitScale &heightMapUnitScale ) const /PyName=markerOffset2/;

/** Adjusts a marker offset to account for rotation.
* @param offset offset prior to rotation
* @param angle rotation angle in degrees clockwise from north
* @return adjusted offset
*/
static QPointF _rotatedOffset( QPointF offset, double angle );
};

@@ -178,6 +178,41 @@ class QgsSimpleFillSymbolLayerV2Widget : QgsSymbolLayerV2Widget

///////////

/** \ingroup gui
* \class QgsFilledMarkerSymbolLayerWidget
* \brief Widget for configuring QgsFilledMarkerSymbolLayer symbol layers.
* \note Added in version 2.16
*/
class QgsFilledMarkerSymbolLayerWidget : QgsSymbolLayerV2Widget
{
%TypeHeaderCode
#include <qgssymbollayerv2widget.h>
%End

public:

/** Constructor for QgsFilledMarkerSymbolLayerWidget.
* @param vl associated vector layer
* @param parent parent widget
*/
QgsFilledMarkerSymbolLayerWidget( const QgsVectorLayer* vl, QWidget* parent /TransferThis/ = nullptr );

~QgsFilledMarkerSymbolLayerWidget();

/** Creates a new QgsFilledMarkerSymbolLayerWidget.
* @param vl associated vector layer
*/
static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) /Factory/;

// from base class
virtual void setSymbolLayer( QgsSymbolLayerV2* layer );
virtual QgsSymbolLayerV2* symbolLayer();

};

///////////


class QgsGradientFillSymbolLayerV2Widget : QgsSymbolLayerV2Widget
{
%TypeHeaderCode
@@ -153,8 +153,7 @@ void QgsDecorationGrid::projectRead()
{
// set default symbol : cross with width=3
QgsSymbolLayerV2List symbolList;
symbolList << new QgsSimpleMarkerSymbolLayerV2( "cross", DEFAULT_SIMPLEMARKER_COLOR,
DEFAULT_SIMPLEMARKER_BORDERCOLOR, 3, 0 );
symbolList << new QgsSimpleMarkerSymbolLayerV2( QgsSimpleMarkerSymbolLayerBase::Cross, 3, 0 );
mMarkerSymbol = new QgsMarkerSymbolV2( symbolList );
// mMarkerSymbol = new QgsMarkerSymbolV2();
}

0 comments on commit ea20149

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