Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsvectorfieldsymbollayer.cpp 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 : : #include "qgsvectorfieldsymbollayer.h" 19 : : #include "qgsvectorlayer.h" 20 : : #include "qgsunittypes.h" 21 : : #include "qgssymbollayerutils.h" 22 : : 23 : 0 : QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer() 24 : 0 : { 25 : 0 : setSubSymbol( new QgsLineSymbol() ); 26 : 0 : } 27 : : 28 : 0 : void QgsVectorFieldSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit unit ) 29 : : { 30 : 0 : QgsMarkerSymbolLayer::setOutputUnit( unit ); 31 : 0 : mDistanceUnit = unit; 32 : 0 : } 33 : : 34 : 0 : QgsUnitTypes::RenderUnit QgsVectorFieldSymbolLayer::outputUnit() const 35 : : { 36 : 0 : if ( QgsMarkerSymbolLayer::outputUnit() == mDistanceUnit ) 37 : : { 38 : 0 : return mDistanceUnit; 39 : : } 40 : 0 : return QgsUnitTypes::RenderUnknownUnit; 41 : 0 : } 42 : : 43 : 0 : void QgsVectorFieldSymbolLayer::setMapUnitScale( const QgsMapUnitScale &scale ) 44 : : { 45 : 0 : QgsMarkerSymbolLayer::setMapUnitScale( scale ); 46 : 0 : mDistanceMapUnitScale = scale; 47 : 0 : } 48 : : 49 : 0 : QgsMapUnitScale QgsVectorFieldSymbolLayer::mapUnitScale() const 50 : : { 51 : 0 : if ( QgsMarkerSymbolLayer::mapUnitScale() == mDistanceMapUnitScale ) 52 : : { 53 : 0 : return mDistanceMapUnitScale; 54 : : } 55 : 0 : return QgsMapUnitScale(); 56 : 0 : } 57 : : 58 : 0 : QgsSymbolLayer *QgsVectorFieldSymbolLayer::create( const QVariantMap &properties ) 59 : : { 60 : 0 : QgsVectorFieldSymbolLayer *symbolLayer = new QgsVectorFieldSymbolLayer(); 61 : 0 : if ( properties.contains( QStringLiteral( "x_attribute" ) ) ) 62 : : { 63 : 0 : symbolLayer->setXAttribute( properties[QStringLiteral( "x_attribute" )].toString() ); 64 : 0 : } 65 : 0 : if ( properties.contains( QStringLiteral( "y_attribute" ) ) ) 66 : : { 67 : 0 : symbolLayer->setYAttribute( properties[QStringLiteral( "y_attribute" )].toString() ); 68 : 0 : } 69 : 0 : if ( properties.contains( QStringLiteral( "distance_unit" ) ) ) 70 : : { 71 : 0 : symbolLayer->setDistanceUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "distance_unit" )].toString() ) ); 72 : 0 : } 73 : 0 : if ( properties.contains( QStringLiteral( "distance_map_unit_scale" ) ) ) 74 : : { 75 : 0 : symbolLayer->setDistanceMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "distance_map_unit_scale" )].toString() ) ); 76 : 0 : } 77 : 0 : if ( properties.contains( QStringLiteral( "scale" ) ) ) 78 : : { 79 : 0 : symbolLayer->setScale( properties[QStringLiteral( "scale" )].toDouble() ); 80 : 0 : } 81 : 0 : if ( properties.contains( QStringLiteral( "vector_field_type" ) ) ) 82 : : { 83 : 0 : symbolLayer->setVectorFieldType( static_cast< VectorFieldType >( properties[QStringLiteral( "vector_field_type" )].toInt() ) ); 84 : 0 : } 85 : 0 : if ( properties.contains( QStringLiteral( "angle_orientation" ) ) ) 86 : : { 87 : 0 : symbolLayer->setAngleOrientation( static_cast< AngleOrientation >( properties[QStringLiteral( "angle_orientation" )].toInt() ) ); 88 : 0 : } 89 : 0 : if ( properties.contains( QStringLiteral( "angle_units" ) ) ) 90 : : { 91 : 0 : symbolLayer->setAngleUnits( static_cast< AngleUnits >( properties[QStringLiteral( "angle_units" )].toInt() ) ); 92 : 0 : } 93 : 0 : if ( properties.contains( QStringLiteral( "size" ) ) ) 94 : : { 95 : 0 : symbolLayer->setSize( properties[QStringLiteral( "size" )].toDouble() ); 96 : 0 : } 97 : 0 : if ( properties.contains( QStringLiteral( "size_unit" ) ) ) 98 : : { 99 : 0 : symbolLayer->setSizeUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "size_unit" )].toString() ) ); 100 : 0 : } 101 : 0 : if ( properties.contains( QStringLiteral( "size_map_unit_scale" ) ) ) 102 : : { 103 : 0 : symbolLayer->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "size_map_unit_scale" )].toString() ) ); 104 : 0 : } 105 : 0 : if ( properties.contains( QStringLiteral( "offset" ) ) ) 106 : : { 107 : 0 : symbolLayer->setOffset( QgsSymbolLayerUtils::decodePoint( properties[QStringLiteral( "offset" )].toString() ) ); 108 : 0 : } 109 : 0 : if ( properties.contains( QStringLiteral( "offset_unit" ) ) ) 110 : : { 111 : 0 : symbolLayer->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "offset_unit" )].toString() ) ); 112 : 0 : } 113 : 0 : if ( properties.contains( QStringLiteral( "offset_map_unit_scale" ) ) ) 114 : : { 115 : 0 : symbolLayer->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "offset_map_unit_scale" )].toString() ) ); 116 : 0 : } 117 : 0 : return symbolLayer; 118 : 0 : } 119 : : 120 : 0 : bool QgsVectorFieldSymbolLayer::setSubSymbol( QgsSymbol *symbol ) 121 : : { 122 : 0 : if ( symbol->type() == QgsSymbol::Line ) 123 : : { 124 : 0 : mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) ); 125 : 0 : return true; 126 : 0 : } 127 : 0 : return false; 128 : 0 : } 129 : 0 : 130 : 0 : void QgsVectorFieldSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext &context ) 131 : 0 : { 132 : 0 : if ( !mLineSymbol ) 133 : : { 134 : 0 : return; 135 : : } 136 : 0 : 137 : 0 : const QgsRenderContext &ctx = context.renderContext(); 138 : : 139 : 0 : if ( !context.feature() ) 140 : : { 141 : : //preview 142 : 0 : QPolygonF line; 143 : 0 : line << QPointF( 0, 50 ); 144 : 0 : line << QPointF( 100, 50 ); 145 : 0 : mLineSymbol->renderPolyline( line, nullptr, context.renderContext() ); 146 : : return; 147 : 0 : } 148 : : 149 : 0 : const QgsFeature f( *context.feature() ); 150 : : 151 : 0 : double xComponent = 0; 152 : 0 : double yComponent = 0; 153 : : 154 : 0 : double xVal = 0; 155 : 0 : if ( mXIndex != -1 ) 156 : : { 157 : 0 : xVal = f.attribute( mXIndex ).toDouble(); 158 : 0 : } 159 : 0 : double yVal = 0; 160 : 0 : if ( mYIndex != -1 ) 161 : : { 162 : 0 : yVal = f.attribute( mYIndex ).toDouble(); 163 : 0 : } 164 : : 165 : 0 : const QgsMapToPixel &m2p = ctx.mapToPixel(); 166 : 0 : const double mapRotation = m2p.mapRotation(); 167 : : 168 : 0 : QPolygonF line; 169 : 0 : line << point; 170 : : 171 : 0 : QPointF destPoint; 172 : 0 : switch ( mVectorFieldType ) 173 : : { 174 : : case Cartesian: 175 : : { 176 : 0 : destPoint = QPointF( point.x() + mScale * ctx.convertToPainterUnits( xVal, mDistanceUnit, mDistanceMapUnitScale ), 177 : 0 : point.y() - mScale * ctx.convertToPainterUnits( yVal, mDistanceUnit, mDistanceMapUnitScale ) ); 178 : 0 : break; 179 : : } 180 : : 181 : : case Polar: 182 : : { 183 : 0 : convertPolarToCartesian( xVal, yVal, xComponent, yComponent ); 184 : 0 : destPoint = QPointF( point.x() + mScale * ctx.convertToPainterUnits( xComponent, mDistanceUnit, mDistanceMapUnitScale ), 185 : 0 : point.y() - mScale * ctx.convertToPainterUnits( yComponent, mDistanceUnit, mDistanceMapUnitScale ) ); 186 : 0 : break; 187 : : } 188 : : 189 : : case Height: 190 : : { 191 : 0 : destPoint = QPointF( point.x(), point.y() - ( mScale * ctx.convertToPainterUnits( yVal, mDistanceUnit, mDistanceMapUnitScale ) ) ); 192 : 0 : break; 193 : : } 194 : : } 195 : : 196 : 0 : if ( !qgsDoubleNear( mapRotation, 0.0 ) && mVectorFieldType != Height ) 197 : : { 198 : 0 : const double radians = mapRotation * M_PI / 180.0; 199 : 0 : destPoint = QPointF( cos( radians ) * ( destPoint.x() - point.x() ) - sin( radians ) * ( destPoint.y() - point.y() ) + point.x(), 200 : 0 : sin( radians ) * ( destPoint.x() - point.x() ) + cos( radians ) * ( destPoint.y() - point.y() ) + point.y() ); 201 : 0 : } 202 : : 203 : 0 : line << destPoint; 204 : 0 : mLineSymbol->renderPolyline( line, &f, context.renderContext() ); 205 : 0 : } 206 : : 207 : 0 : void QgsVectorFieldSymbolLayer::startRender( QgsSymbolRenderContext &context ) 208 : : { 209 : 0 : if ( mLineSymbol ) 210 : : { 211 : 0 : mLineSymbol->startRender( context.renderContext(), context.fields() ); 212 : 0 : } 213 : : 214 : 0 : QgsFields fields = context.fields(); 215 : 0 : if ( !fields.isEmpty() ) 216 : : { 217 : 0 : mXIndex = fields.lookupField( mXAttribute ); 218 : 0 : mYIndex = fields.lookupField( mYAttribute ); 219 : 0 : } 220 : : else 221 : : { 222 : 0 : mXIndex = -1; 223 : 0 : mYIndex = -1; 224 : : } 225 : 0 : } 226 : : 227 : 0 : void QgsVectorFieldSymbolLayer::stopRender( QgsSymbolRenderContext &context ) 228 : : { 229 : 0 : if ( mLineSymbol ) 230 : : { 231 : 0 : mLineSymbol->stopRender( context.renderContext() ); 232 : 0 : } 233 : 0 : } 234 : : 235 : 0 : QgsVectorFieldSymbolLayer *QgsVectorFieldSymbolLayer::clone() const 236 : : { 237 : 0 : QgsSymbolLayer *clonedLayer = QgsVectorFieldSymbolLayer::create( properties() ); 238 : 0 : if ( mLineSymbol ) 239 : : { 240 : 0 : clonedLayer->setSubSymbol( mLineSymbol->clone() ); 241 : 0 : } 242 : 0 : return static_cast< QgsVectorFieldSymbolLayer * >( clonedLayer ); 243 : 0 : } 244 : : 245 : 0 : QVariantMap QgsVectorFieldSymbolLayer::properties() const 246 : : { 247 : 0 : QVariantMap properties; 248 : 0 : properties[QStringLiteral( "x_attribute" )] = mXAttribute; 249 : 0 : properties[QStringLiteral( "y_attribute" )] = mYAttribute; 250 : 0 : properties[QStringLiteral( "distance_unit" )] = QgsUnitTypes::encodeUnit( mDistanceUnit ); 251 : 0 : properties[QStringLiteral( "distance_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mDistanceMapUnitScale ); 252 : 0 : properties[QStringLiteral( "scale" )] = QString::number( mScale ); 253 : 0 : properties[QStringLiteral( "vector_field_type" )] = QString::number( mVectorFieldType ); 254 : 0 : properties[QStringLiteral( "angle_orientation" )] = QString::number( mAngleOrientation ); 255 : 0 : properties[QStringLiteral( "angle_units" )] = QString::number( mAngleUnits ); 256 : 0 : properties[QStringLiteral( "size" )] = QString::number( mSize ); 257 : 0 : properties[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit ); 258 : 0 : properties[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale ); 259 : 0 : properties[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset ); 260 : 0 : properties[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit ); 261 : 0 : properties[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale ); 262 : 0 : return properties; 263 : 0 : } 264 : : 265 : 0 : bool QgsVectorFieldSymbolLayer::usesMapUnits() const 266 : : { 267 : 0 : return mDistanceUnit == QgsUnitTypes::RenderMapUnits || mDistanceUnit == QgsUnitTypes::RenderMetersInMapUnits 268 : 0 : || mOffsetUnit == QgsUnitTypes::RenderMapUnits || mOffsetUnit == QgsUnitTypes::RenderMetersInMapUnits 269 : 0 : || mSizeUnit == QgsUnitTypes::RenderMapUnits || mSizeUnit == QgsUnitTypes::RenderMetersInMapUnits; 270 : : } 271 : : 272 : 0 : void QgsVectorFieldSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const 273 : : { 274 : 0 : element.appendChild( doc.createComment( QStringLiteral( "VectorField not implemented yet..." ) ) ); 275 : 0 : mLineSymbol->toSld( doc, element, props ); 276 : 0 : } 277 : : 278 : 0 : QgsSymbolLayer *QgsVectorFieldSymbolLayer::createFromSld( QDomElement &element ) 279 : : { 280 : 0 : Q_UNUSED( element ) 281 : 0 : return nullptr; 282 : : } 283 : : 284 : 0 : void QgsVectorFieldSymbolLayer::drawPreviewIcon( QgsSymbolRenderContext &context, QSize size ) 285 : : { 286 : 0 : if ( mLineSymbol ) 287 : : { 288 : 0 : mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size ); 289 : 0 : } 290 : 0 : } 291 : : 292 : 0 : QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes( const QgsRenderContext &context ) const 293 : : { 294 : 0 : QSet<QString> attributes = QgsMarkerSymbolLayer::usedAttributes( context ); 295 : 0 : if ( !mXAttribute.isEmpty() ) 296 : : { 297 : 0 : attributes.insert( mXAttribute ); 298 : 0 : } 299 : 0 : if ( !mYAttribute.isEmpty() ) 300 : : { 301 : 0 : attributes.insert( mYAttribute ); 302 : 0 : } 303 : 0 : if ( mLineSymbol ) 304 : : { 305 : 0 : attributes.unite( mLineSymbol->usedAttributes( context ) ); 306 : 0 : } 307 : 0 : return attributes; 308 : 0 : } 309 : : 310 : 0 : bool QgsVectorFieldSymbolLayer::hasDataDefinedProperties() const 311 : : { 312 : 0 : if ( QgsSymbolLayer::hasDataDefinedProperties() ) 313 : 0 : return true; 314 : 0 : if ( mLineSymbol && mLineSymbol->hasDataDefinedProperties() ) 315 : 0 : return true; 316 : 0 : return false; 317 : 0 : } 318 : : 319 : 0 : void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double &x, double &y ) const 320 : : { 321 : : //convert angle to degree and to north orientation 322 : 0 : if ( mAngleOrientation == CounterclockwiseFromEast ) 323 : : { 324 : 0 : if ( angle <= 90 ) 325 : : { 326 : 0 : angle = 90 - angle; 327 : 0 : } 328 : : else 329 : : { 330 : 0 : angle = 360 - angle + 90; 331 : : } 332 : 0 : } 333 : : 334 : 0 : if ( mAngleUnits == Degrees ) 335 : : { 336 : 0 : angle = angle * M_PI / 180.0; 337 : 0 : } 338 : : 339 : 0 : x = length * std::sin( angle ); 340 : 0 : y = length * std::cos( angle ); 341 : 0 : } 342 : : 343 : 0 : void QgsVectorFieldSymbolLayer::setColor( const QColor &color ) 344 : : { 345 : 0 : if ( mLineSymbol ) 346 : 0 : mLineSymbol->setColor( color ); 347 : : 348 : 0 : mColor = color; 349 : 0 : } 350 : : 351 : 0 : QColor QgsVectorFieldSymbolLayer::color() const 352 : : { 353 : 0 : return mLineSymbol ? mLineSymbol->color() : mColor; 354 : : } 355 : : 356 : :