1 /***************************************************************************
2  qgsarrowsymbollayer.h
3  ---------------------
4  begin                : January 2016
5  copyright            : (C) 2016 by Hugo Mercier
6  email                : hugo dot mercier at oslandia dot com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 #ifndef QGSARROWSYMBOLLAYER_H
17 #define QGSARROWSYMBOLLAYER_H
18 
19 #include "qgis_core.h"
20 #include "qgis.h"
21 #include "qgssymbollayer.h"
22 
23 class QgsFillSymbol;
24 
25 
26 /**
27  * \ingroup core
28  * \class QgsArrowSymbolLayer
29  * \brief Line symbol layer used for representing lines as arrows.
30  * \since QGIS 2.16
31  */
32 
33 class CORE_EXPORT QgsArrowSymbolLayer : public QgsLineSymbolLayer
34 {
35   public:
36     //! Simple constructor
37     QgsArrowSymbolLayer();
38     ~QgsArrowSymbolLayer() override;
39 
40     /**
41      * Create a new QgsArrowSymbolLayer
42      *
43      * \param properties A property map to deserialize saved information from properties()
44      *
45      * \returns A new QgsArrowSymbolLayer
46      */
47     static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY;
48 
49     QgsArrowSymbolLayer *clone() const override SIP_FACTORY;
50     QgsSymbol *subSymbol() override;
51     bool setSubSymbol( QgsSymbol *symbol SIP_TRANSFER ) override;
52     QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
53     bool hasDataDefinedProperties() const override;
54     bool usesMapUnits() const override;
55 
56     //! Gets current arrow width
arrowWidth()57     double arrowWidth() const { return mArrowWidth; }
58     //! Sets the arrow width
setArrowWidth(double width)59     void setArrowWidth( double width ) { mArrowWidth = width; }
60     //! Gets the unit for the arrow width
arrowWidthUnit()61     QgsUnitTypes::RenderUnit arrowWidthUnit() const { return mArrowWidthUnit; }
62     //! Sets the unit for the arrow width
setArrowWidthUnit(QgsUnitTypes::RenderUnit unit)63     void setArrowWidthUnit( QgsUnitTypes::RenderUnit unit ) { mArrowWidthUnit = unit; }
64     //! Gets the scale for the arrow width
arrowWidthUnitScale()65     QgsMapUnitScale arrowWidthUnitScale() const { return mArrowWidthUnitScale; }
66     //! Sets the scale for the arrow width
setArrowWidthUnitScale(const QgsMapUnitScale & scale)67     void setArrowWidthUnitScale( const QgsMapUnitScale &scale ) { mArrowWidthUnitScale = scale; }
68 
69     //! Gets current arrow start width. Only meaningful for single headed arrows
arrowStartWidth()70     double arrowStartWidth() const { return mArrowStartWidth; }
71     //! Sets the arrow start width
setArrowStartWidth(double width)72     void setArrowStartWidth( double width ) { mArrowStartWidth = width; }
73     //! Gets the unit for the arrow start width
arrowStartWidthUnit()74     QgsUnitTypes::RenderUnit arrowStartWidthUnit() const { return mArrowStartWidthUnit; }
75     //! Sets the unit for the arrow start width
setArrowStartWidthUnit(QgsUnitTypes::RenderUnit unit)76     void setArrowStartWidthUnit( QgsUnitTypes::RenderUnit unit ) { mArrowStartWidthUnit = unit; }
77     //! Gets the scale for the arrow start width
arrowStartWidthUnitScale()78     QgsMapUnitScale arrowStartWidthUnitScale() const { return mArrowStartWidthUnitScale; }
79     //! Sets the scale for the arrow start width
setArrowStartWidthUnitScale(const QgsMapUnitScale & scale)80     void setArrowStartWidthUnitScale( const QgsMapUnitScale &scale ) { mArrowStartWidthUnitScale = scale; }
81 
82     //! Gets the current arrow head length
headLength()83     double headLength() const { return mHeadLength; }
84     //! Sets the arrow head length
setHeadLength(double length)85     void setHeadLength( double length ) { mHeadLength = length; }
86     //! Gets the unit for the head length
headLengthUnit()87     QgsUnitTypes::RenderUnit headLengthUnit() const { return mHeadLengthUnit; }
88     //! Sets the unit for the head length
setHeadLengthUnit(QgsUnitTypes::RenderUnit unit)89     void setHeadLengthUnit( QgsUnitTypes::RenderUnit unit ) { mHeadLengthUnit = unit; }
90     //! Gets the scale for the head length
headLengthUnitScale()91     QgsMapUnitScale headLengthUnitScale() const { return mHeadLengthUnitScale; }
92     //! Sets the scale for the head length
setHeadLengthUnitScale(const QgsMapUnitScale & scale)93     void setHeadLengthUnitScale( const QgsMapUnitScale &scale ) { mHeadLengthUnitScale = scale; }
94 
95     //! Gets the current arrow head height
headThickness()96     double headThickness() const { return mHeadThickness; }
97     //! Sets the arrow head height
setHeadThickness(double thickness)98     void setHeadThickness( double thickness ) { mHeadThickness = thickness; }
99     //! Gets the unit for the head height
headThicknessUnit()100     QgsUnitTypes::RenderUnit headThicknessUnit() const { return mHeadThicknessUnit; }
101     //! Sets the unit for the head height
setHeadThicknessUnit(QgsUnitTypes::RenderUnit unit)102     void setHeadThicknessUnit( QgsUnitTypes::RenderUnit unit ) { mHeadThicknessUnit = unit; }
103     //! Gets the scale for the head height
headThicknessUnitScale()104     QgsMapUnitScale headThicknessUnitScale() const { return mHeadThicknessUnitScale; }
105     //! Sets the scale for the head height
setHeadThicknessUnitScale(const QgsMapUnitScale & scale)106     void setHeadThicknessUnitScale( const QgsMapUnitScale &scale ) { mHeadThicknessUnitScale = scale; }
107 
108     //! Returns whether it is a curved arrow or a straight one
isCurved()109     bool isCurved() const { return mIsCurved; }
110     //! Sets whether it is a curved arrow or a straight one
setIsCurved(bool isCurved)111     void setIsCurved( bool isCurved ) { mIsCurved = isCurved; }
112 
113     //! Returns whether the arrow is repeated along the line or not
isRepeated()114     bool isRepeated() const { return mIsRepeated; }
115     //! Sets whether the arrow is repeated along the line
setIsRepeated(bool isRepeated)116     void setIsRepeated( bool isRepeated ) { mIsRepeated = isRepeated; }
117 
118     //! Possible head types
119     enum HeadType
120     {
121       HeadSingle,   //< One single head at the end
122       HeadReversed, //< One single head at the beginning
123       HeadDouble    //< Two heads
124     };
125 
126     //! Gets the current head type
headType()127     HeadType headType() const { return mHeadType; }
128     //! Sets the head type
setHeadType(HeadType type)129     void setHeadType( HeadType type ) { mHeadType = type; }
130 
131     //! Possible arrow types
132     enum ArrowType
133     {
134       ArrowPlain,     //< Regular arrow
135       ArrowLeftHalf,  //< Halved arrow, only the left side of the arrow is rendered (for straight arrows) or the side toward the exterior (for curved arrows)
136       ArrowRightHalf  //< Halved arrow, only the right side of the arrow is rendered (for straight arrows) or the side toward the interior (for curved arrows)
137     };
138 
139     //! Gets the current arrow type
arrowType()140     ArrowType arrowType() const { return mArrowType; }
141     //! Sets the arrow type
setArrowType(ArrowType type)142     void setArrowType( ArrowType type ) { mArrowType = type; }
143 
144     QVariantMap properties() const override;
145     QString layerType() const override;
146     void startRender( QgsSymbolRenderContext &context ) override;
147     void stopRender( QgsSymbolRenderContext &context ) override;
148     void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override;
149     void setColor( const QColor &c ) override;
150     QColor color() const override;
151     bool canCauseArtifactsBetweenAdjacentTiles() const override;
152 
153   private:
154 #ifdef SIP_RUN
155     QgsArrowSymbolLayer( const QgsArrowSymbolLayer & );
156 #endif
157 
158     //! Filling sub symbol
159     std::unique_ptr<QgsFillSymbol> mSymbol;
160 
161     double mArrowWidth = 1.0;
162     QgsUnitTypes::RenderUnit mArrowWidthUnit = QgsUnitTypes::RenderMillimeters;
163     QgsMapUnitScale mArrowWidthUnitScale;
164 
165     double mArrowStartWidth = 1.0;
166     QgsUnitTypes::RenderUnit mArrowStartWidthUnit = QgsUnitTypes::RenderMillimeters;
167     QgsMapUnitScale mArrowStartWidthUnitScale;
168 
169     double mHeadLength = 1.5;
170     QgsUnitTypes::RenderUnit mHeadLengthUnit = QgsUnitTypes::RenderMillimeters;
171     QgsMapUnitScale mHeadLengthUnitScale;
172     double mHeadThickness = 1.5;
173     QgsUnitTypes::RenderUnit mHeadThicknessUnit = QgsUnitTypes::RenderMillimeters;
174     QgsMapUnitScale mHeadThicknessUnitScale;
175 
176     HeadType mHeadType = HeadSingle;
177     ArrowType mArrowType = ArrowPlain;
178     bool mIsCurved = true;
179     bool mIsRepeated = true;
180 
181     double mScaledArrowWidth = 1.0;
182     double mScaledArrowStartWidth = 1.0;
183     double mScaledHeadLength = 1.5;
184     double mScaledHeadThickness = 1.5;
185     double mScaledOffset = 0.0;
186     HeadType mComputedHeadType = HeadSingle;
187     ArrowType mComputedArrowType = ArrowPlain;
188 
189     std::unique_ptr<QgsExpressionContextScope> mExpressionScope;
190 
191     void _resolveDataDefined( QgsSymbolRenderContext & );
192 };
193 
194 #endif
195 
196 
197