QRectF QgsEllipseSymbolLayer::bounds( QPointF point, QgsSymbolRenderContext &context ) { QSizeF size = calculateSize( context ); bool hasDataDefinedRotation = false; QPointF offset; double angle = 0; calculateOffsetAndRotation( context, size.width(), size.height(), hasDataDefinedRotation, offset, angle ); QMatrix transform; // move to the desired position transform.translate( point.x() + offset.x(), point.y() + offset.y() ); if ( !qgsDoubleNear( angle, 0.0 ) ) transform.rotate( angle ); double penWidth = 0.0; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeWidth ) ) { context.setOriginalValueVariable( mStrokeWidth ); QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeWidth, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { bool ok; double strokeWidth = exprVal.toDouble( &ok ); if ( ok ) { penWidth = context.renderContext().convertToPainterUnits( strokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ); } } } if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeStyle ) ) { context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle ) ); QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeStyle, context.renderContext().expressionContext() ); if ( exprVal.isValid() && exprVal.toString() == QLatin1String( "no" ) ) { penWidth = 0.0; } } //antialiasing, add 1 pixel penWidth += 1; QRectF symbolBounds = transform.mapRect( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) ); //extend bounds by pen width / 2.0 symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0, penWidth / 2.0, penWidth / 2.0 ); return symbolBounds; }
void QgsMarkerSymbolLayer::markerOffset( QgsSymbolRenderContext& context, double width, double height, QgsUnitTypes::RenderUnit widthUnit, QgsUnitTypes::RenderUnit heightUnit, double& offsetX, double& offsetY, const QgsMapUnitScale& widthMapUnitScale, const QgsMapUnitScale& heightMapUnitScale ) const { offsetX = mOffset.x(); offsetY = mOffset.y(); if ( hasDataDefinedProperty( QgsSymbolLayer::EXPR_OFFSET ) ) { context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePoint( mOffset ) ); QPointF offset = QgsSymbolLayerUtils::decodePoint( evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_OFFSET, context ).toString() ); offsetX = offset.x(); offsetY = offset.y(); } offsetX = QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), offsetX, mOffsetUnit, mOffsetMapUnitScale ); offsetY = QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), offsetY, mOffsetUnit, mOffsetMapUnitScale ); HorizontalAnchorPoint horizontalAnchorPoint = mHorizontalAnchorPoint; VerticalAnchorPoint verticalAnchorPoint = mVerticalAnchorPoint; if ( hasDataDefinedProperty( QgsSymbolLayer::EXPR_HORIZONTAL_ANCHOR_POINT ) ) { horizontalAnchorPoint = decodeHorizontalAnchorPoint( evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_HORIZONTAL_ANCHOR_POINT , context ).toString() ); } if ( hasDataDefinedProperty( QgsSymbolLayer::EXPR_VERTICAL_ANCHOR_POINT ) ) { verticalAnchorPoint = decodeVerticalAnchorPoint( evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_VERTICAL_ANCHOR_POINT, context ).toString() ); } //correct horizontal position according to anchor point if ( horizontalAnchorPoint == HCenter && verticalAnchorPoint == VCenter ) { return; } double anchorPointCorrectionX = QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), width, widthUnit, widthMapUnitScale ) / 2.0; double anchorPointCorrectionY = QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), height, heightUnit, heightMapUnitScale ) / 2.0; if ( horizontalAnchorPoint == Left ) { offsetX += anchorPointCorrectionX; } else if ( horizontalAnchorPoint == Right ) { offsetX -= anchorPointCorrectionX; } //correct vertical position according to anchor point if ( verticalAnchorPoint == Top ) { offsetY += anchorPointCorrectionY; } else if ( verticalAnchorPoint == Bottom ) { offsetY -= anchorPointCorrectionY; } }
QSizeF QgsEllipseSymbolLayer::calculateSize( QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight ) { double width = 0; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) ) //1. priority: data defined setting on symbol layer le { context.setOriginalValueVariable( mSymbolWidth ); width = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyWidth, context.renderContext().expressionContext(), mSymbolWidth ); } else //2. priority: global width setting { width = mSymbolWidth; } if ( scaledWidth ) { *scaledWidth = width; } width = context.renderContext().convertToPainterUnits( width, mSymbolWidthUnit, mSymbolHeightMapUnitScale ); double height = 0; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) ) //1. priority: data defined setting on symbol layer level { context.setOriginalValueVariable( mSymbolHeight ); height = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), mSymbolHeight ); } else //2. priority: global height setting { height = mSymbolHeight; } if ( scaledHeight ) { *scaledHeight = height; } height = context.renderContext().convertToPainterUnits( height, mSymbolHeightUnit, mSymbolHeightMapUnitScale ); return QSizeF( width, height ); }
void QgsEllipseSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const { double offsetX = 0; double offsetY = 0; markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale ); offset = QPointF( offsetX, offsetY ); //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) bool ok = true; angle = mAngle + mLineAngle; bool usingDataDefinedRotation = false; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyAngle ) ) { context.setOriginalValueVariable( angle ); angle = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyAngle, context.renderContext().expressionContext(), 0 ) + mLineAngle; usingDataDefinedRotation = ok; } hasDataDefinedRotation = context.renderHints() & QgsSymbol::DynamicRotation || usingDataDefinedRotation; if ( hasDataDefinedRotation ) { // For non-point markers, "dataDefinedRotation" means following the // shape (shape-data defined). For them, "field-data defined" does // not work at all. TODO: if "field-data defined" ever gets implemented // we'll need a way to distinguish here between the two, possibly // using another flag in renderHints() const QgsFeature *f = context.feature(); if ( f ) { const QgsGeometry g = f->geometry(); if ( !g.isNull() && g.type() == QgsWkbTypes::PointGeometry ) { const QgsMapToPixel &m2p = context.renderContext().mapToPixel(); angle += m2p.mapRotation(); } } } if ( angle ) offset = _rotatedOffset( offset, angle ); }
void QgsMarkerSymbolLayer::markerOffset( QgsSymbolRenderContext &context, double width, double height, QgsUnitTypes::RenderUnit widthUnit, QgsUnitTypes::RenderUnit heightUnit, double &offsetX, double &offsetY, const QgsMapUnitScale &widthMapUnitScale, const QgsMapUnitScale &heightMapUnitScale ) const { offsetX = mOffset.x(); offsetY = mOffset.y(); if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyOffset ) ) { context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePoint( mOffset ) ); QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyOffset, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { QPointF offset = QgsSymbolLayerUtils::decodePoint( exprVal.toString() ); offsetX = offset.x(); offsetY = offset.y(); } } offsetX = context.renderContext().convertToPainterUnits( offsetX, mOffsetUnit, mOffsetMapUnitScale ); offsetY = context.renderContext().convertToPainterUnits( offsetY, mOffsetUnit, mOffsetMapUnitScale ); HorizontalAnchorPoint horizontalAnchorPoint = mHorizontalAnchorPoint; VerticalAnchorPoint verticalAnchorPoint = mVerticalAnchorPoint; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHorizontalAnchor ) ) { QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyHorizontalAnchor, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { horizontalAnchorPoint = decodeHorizontalAnchorPoint( exprVal.toString() ); } } if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyVerticalAnchor ) ) { QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyVerticalAnchor, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { verticalAnchorPoint = decodeVerticalAnchorPoint( exprVal.toString() ); } } //correct horizontal position according to anchor point if ( horizontalAnchorPoint == HCenter && verticalAnchorPoint == VCenter ) { return; } double anchorPointCorrectionX = context.renderContext().convertToPainterUnits( width, widthUnit, widthMapUnitScale ) / 2.0; double anchorPointCorrectionY = context.renderContext().convertToPainterUnits( height, heightUnit, heightMapUnitScale ) / 2.0; if ( horizontalAnchorPoint == Left ) { offsetX += anchorPointCorrectionX; } else if ( horizontalAnchorPoint == Right ) { offsetX -= anchorPointCorrectionX; } //correct vertical position according to anchor point if ( verticalAnchorPoint == Top ) { offsetY += anchorPointCorrectionY; } else if ( verticalAnchorPoint == Bottom ) { offsetY -= anchorPointCorrectionY; } }
bool QgsEllipseSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const { //width double symbolWidth = mSymbolWidth; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) ) //1. priority: data defined setting on symbol layer le { context.setOriginalValueVariable( mSymbolWidth ); symbolWidth = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyWidth, context.renderContext().expressionContext(), mSymbolWidth ); } if ( mSymbolWidthUnit == QgsUnitTypes::RenderMillimeters ) { symbolWidth *= mmMapUnitScaleFactor; } //height double symbolHeight = mSymbolHeight; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) ) //1. priority: data defined setting on symbol layer level { context.setOriginalValueVariable( mSymbolHeight ); symbolWidth = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), mSymbolHeight ); } if ( mSymbolHeightUnit == QgsUnitTypes::RenderMillimeters ) { symbolHeight *= mmMapUnitScaleFactor; } //stroke width double strokeWidth = mStrokeWidth; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeWidth ) ) { context.setOriginalValueVariable( mStrokeWidth ); strokeWidth = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyStrokeWidth, context.renderContext().expressionContext(), mStrokeWidth ); } if ( mStrokeWidthUnit == QgsUnitTypes::RenderMillimeters ) { strokeWidth *= strokeWidth; } //fill color QColor fc = mColor; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyFillColor ) ) { context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) ); fc = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor ); } //stroke color QColor oc = mStrokeColor; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeColor ) ) { context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mStrokeColor ) ); oc = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor ); } //symbol name QString symbolName = mSymbolName; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName ) ) { context.setOriginalValueVariable( mSymbolName ); symbolName = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext(), mSymbolName ); } //offset double offsetX = 0; double offsetY = 0; markerOffset( context, offsetX, offsetY ); QPointF off( offsetX, offsetY ); //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) double rotation = 0.0; if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyAngle ) ) { context.setOriginalValueVariable( mAngle ); rotation = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyAngle, context.renderContext().expressionContext(), mAngle ) + mLineAngle; } else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) ) { rotation = mAngle + mLineAngle; } rotation = -rotation; //rotation in Qt is counterclockwise if ( rotation ) off = _rotatedOffset( off, rotation ); QTransform t; t.translate( shift.x() + offsetX, shift.y() + offsetY ); if ( !qgsDoubleNear( rotation, 0.0 ) ) t.rotate( rotation ); double halfWidth = symbolWidth / 2.0; double halfHeight = symbolHeight / 2.0; if ( symbolName == QLatin1String( "circle" ) ) { if ( qgsDoubleNear( halfWidth, halfHeight ) ) { QgsPoint pt( t.map( QPointF( 0, 0 ) ) ); e.writeFilledCircle( layerName, oc, pt, halfWidth ); } else { QgsPointSequence line; double stepsize = 2 * M_PI / 40; for ( int i = 0; i < 39; ++i ) { double angle = stepsize * i; double x = halfWidth * std::cos( angle ); double y = halfHeight * std::sin( angle ); line << QgsPoint( t.map( QPointF( x, y ) ) ); } //close ellipse with first point line << line.at( 0 ); if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsRingSequence() << line, layerName, QStringLiteral( "SOLID" ), fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( line, layerName, QStringLiteral( "CONTINUOUS" ), oc, strokeWidth ); } } else if ( symbolName == QLatin1String( "rectangle" ) ) { QgsPointSequence p; p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) ) << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) ) << QgsPoint( t.map( QPointF( halfWidth, halfHeight ) ) ) << QgsPoint( t.map( QPointF( -halfWidth, halfHeight ) ) ); p << p[0]; if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsRingSequence() << p, layerName, QStringLiteral( "SOLID" ), fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( p, layerName, QStringLiteral( "CONTINUOUS" ), oc, strokeWidth ); return true; } else if ( symbolName == QLatin1String( "cross" ) && mPen.style() != Qt::NoPen ) { e.writePolyline( QgsPointSequence() << QgsPoint( t.map( QPointF( -halfWidth, 0 ) ) ) << QgsPoint( t.map( QPointF( halfWidth, 0 ) ) ), layerName, QStringLiteral( "CONTINUOUS" ), oc, strokeWidth ); e.writePolyline( QgsPointSequence() << QgsPoint( t.map( QPointF( 0, halfHeight ) ) ) << QgsPoint( t.map( QPointF( 0, -halfHeight ) ) ), layerName, QStringLiteral( "CONTINUOUS" ), oc, strokeWidth ); return true; } else if ( symbolName == QLatin1String( "triangle" ) ) { QgsPointSequence p; p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) ) << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) ) << QgsPoint( t.map( QPointF( 0, halfHeight ) ) ); p << p[0]; if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsRingSequence() << p, layerName, QStringLiteral( "SOLID" ), fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( p, layerName, QStringLiteral( "CONTINUOUS" ), oc, strokeWidth ); return true; } return false; //soon... }
void QgsEllipseSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext &context ) { double scaledWidth = mSymbolWidth; double scaledHeight = mSymbolHeight; if ( mDataDefinedProperties.hasActiveProperties() ) { bool ok; context.setOriginalValueVariable( mStrokeWidth ); QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeWidth, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { double width = exprVal.toDouble( &ok ); if ( ok ) { width = context.renderContext().convertToPainterUnits( width, mStrokeWidthUnit, mStrokeWidthMapUnitScale ); mPen.setWidthF( width ); } } context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle ) ); exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeStyle, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { mPen.setStyle( QgsSymbolLayerUtils::decodePenStyle( exprVal.toString() ) ); } context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle ) ); exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyJoinStyle, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( exprVal.toString() ) ); } context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) ); mBrush.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor ) ); context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mStrokeColor ) ); mPen.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor ) ); if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName ) ) { QString symbolName = mSymbolName; context.setOriginalValueVariable( mSymbolName ); exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext() ); if ( exprVal.isValid() ) { symbolName = exprVal.toString(); } preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() ); } } //offset and rotation bool hasDataDefinedRotation = false; QPointF offset; double angle = 0; calculateOffsetAndRotation( context, scaledWidth, scaledHeight, hasDataDefinedRotation, offset, angle ); QPainter *p = context.renderContext().painter(); if ( !p ) { return; } QMatrix transform; transform.translate( point.x() + offset.x(), point.y() + offset.y() ); if ( !qgsDoubleNear( angle, 0.0 ) ) { transform.rotate( angle ); } p->setPen( mPen ); p->setBrush( mBrush ); p->drawPath( transform.map( mPainterPath ) ); }