1 /***************************************************************************
2          qgsvectorfieldsymbollayer.h
3          -------------------------
4   begin                : Octorer 25, 2011
5   copyright            : (C) 2011 by Marco Hugentobler
6   email                : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef QGSVECTORFIELDSYMBOLLAYER_H
19 #define QGSVECTORFIELDSYMBOLLAYER_H
20 
21 #include "qgis_core.h"
22 #include "qgis.h"
23 #include "qgssymbollayer.h"
24 
25 /**
26  * \ingroup core
27  * \brief A symbol layer class for displaying displacement arrows based on point layer attributes.
28 */
29 class CORE_EXPORT QgsVectorFieldSymbolLayer: public QgsMarkerSymbolLayer
30 {
31   public:
32     enum VectorFieldType
33     {
34       Cartesian = 0,
35       Polar,
36       Height
37     };
38 
39     enum AngleOrientation
40     {
41       ClockwiseFromNorth = 0,
42       CounterclockwiseFromEast
43     };
44 
45     enum AngleUnits
46     {
47       Degrees = 0,
48       Radians
49     };
50 
51     QgsVectorFieldSymbolLayer();
52 
53     static QgsSymbolLayer *create( const QgsStringMap &properties = QgsStringMap() );
54     static QgsSymbolLayer *createFromSld( QDomElement &element );
55 
layerType()56     QString layerType() const override { return QStringLiteral( "VectorField" ); }
57 
58     bool setSubSymbol( QgsSymbol *symbol SIP_TRANSFER ) override;
subSymbol()59     QgsSymbol *subSymbol() override { return mLineSymbol.get(); }
60 
61     void setColor( const QColor &color ) override;
62     QColor color() const override;
63 
64     void renderPoint( QPointF point, QgsSymbolRenderContext &context ) override;
65     void startRender( QgsSymbolRenderContext &context ) override;
66     void stopRender( QgsSymbolRenderContext &context ) override;
67 
68     QgsVectorFieldSymbolLayer *clone() const override SIP_FACTORY;
69     QgsStringMap properties() const override;
70     bool usesMapUnits() const override;
71 
72     void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const override;
73 
74     void drawPreviewIcon( QgsSymbolRenderContext &context, QSize size ) override;
75 
76     QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
77     bool hasDataDefinedProperties() const override;
78 
79     //setters and getters
setXAttribute(const QString & attribute)80     void setXAttribute( const QString &attribute ) { mXAttribute = attribute; }
xAttribute()81     QString xAttribute() const { return mXAttribute; }
setYAttribute(const QString & attribute)82     void setYAttribute( const QString &attribute ) { mYAttribute = attribute; }
yAttribute()83     QString yAttribute() const { return mYAttribute; }
setScale(double s)84     void setScale( double s ) { mScale = s; }
scale()85     double scale() const { return mScale; }
setVectorFieldType(VectorFieldType type)86     void setVectorFieldType( VectorFieldType type ) { mVectorFieldType = type; }
vectorFieldType()87     VectorFieldType vectorFieldType() const { return mVectorFieldType; }
setAngleOrientation(AngleOrientation orientation)88     void setAngleOrientation( AngleOrientation orientation ) { mAngleOrientation = orientation; }
angleOrientation()89     AngleOrientation angleOrientation() const { return mAngleOrientation; }
setAngleUnits(AngleUnits units)90     void setAngleUnits( AngleUnits units ) { mAngleUnits = units; }
angleUnits()91     AngleUnits angleUnits() const { return mAngleUnits; }
92 
93     void setOutputUnit( QgsUnitTypes::RenderUnit unit ) override;
94     QgsUnitTypes::RenderUnit outputUnit() const override;
95 
96     void setMapUnitScale( const QgsMapUnitScale &scale ) override;
97     QgsMapUnitScale mapUnitScale() const override;
98 
99     /**
100      * Sets the units for the distance.
101      * \param unit distance units
102      * \see distanceUnit()
103     */
setDistanceUnit(QgsUnitTypes::RenderUnit unit)104     void setDistanceUnit( QgsUnitTypes::RenderUnit unit ) { mDistanceUnit = unit; }
105 
106     /**
107      * Returns the units for the distance.
108      * \see setDistanceUnit()
109     */
distanceUnit()110     QgsUnitTypes::RenderUnit distanceUnit() const { return mDistanceUnit; }
111 
setDistanceMapUnitScale(const QgsMapUnitScale & scale)112     void setDistanceMapUnitScale( const QgsMapUnitScale &scale ) { mDistanceMapUnitScale = scale; }
distanceMapUnitScale()113     const QgsMapUnitScale &distanceMapUnitScale() const { return mDistanceMapUnitScale; }
114 
115     // TODO - implement properly
bounds(QPointF,QgsSymbolRenderContext &)116     QRectF bounds( QPointF, QgsSymbolRenderContext & ) override { return QRectF(); }
117 
118   private:
119 #ifdef SIP_RUN
120     QgsVectorFieldSymbolLayer( const QgsVectorFieldSymbolLayer &other );
121 #endif
122 
123     QString mXAttribute;
124     QString mYAttribute;
125     QgsUnitTypes::RenderUnit mDistanceUnit = QgsUnitTypes::RenderMillimeters;
126     QgsMapUnitScale mDistanceMapUnitScale;
127     double mScale = 1.0;
128     VectorFieldType mVectorFieldType = Cartesian;
129     AngleOrientation mAngleOrientation = ClockwiseFromNorth;
130     AngleUnits mAngleUnits = Degrees;
131 
132     std::unique_ptr< QgsLineSymbol > mLineSymbol;
133 
134     //Attribute indices are resolved in startRender method
135     int mXIndex = -1;
136     int mYIndex = -1;
137 
138     //Converts length/angle to Cartesian x/y
139     void convertPolarToCartesian( double length, double angle, double &x, double &y ) const;
140 };
141 
142 #endif // QGSVECTORFIELDSYMBOLLAYER_H
143 
144 
145