void QgsPointDisplacementRenderer::drawLabels( const QPointF& centerPoint, QgsSymbolV2RenderContext& context, const QList<QPointF>& labelShifts, const QStringList& labelList ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } QPen labelPen( mLabelColor ); p->setPen( labelPen ); //scale font (for printing) QFont pixelSizeFont = mLabelFont; pixelSizeFont.setPixelSize( context.outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) ); QFont scaledFont = pixelSizeFont; scaledFont.setPixelSize( pixelSizeFont.pixelSize() * context.renderContext().rasterScaleFactor() ); p->setFont( scaledFont ); QFontMetricsF fontMetrics( pixelSizeFont ); QPointF currentLabelShift; //considers the signs to determine the label position QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin(); QStringList::const_iterator text_it = labelList.constBegin(); for ( ; labelPosIt != labelShifts.constEnd() && text_it != labelList.constEnd(); ++labelPosIt, ++text_it ) { currentLabelShift = *labelPosIt; if ( currentLabelShift.x() < 0 ) { currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( *text_it ) ); } if ( currentLabelShift.y() > 0 ) { currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() ); } QPointF drawingPoint( centerPoint + currentLabelShift ); p->save(); p->translate( drawingPoint.x(), drawingPoint.y() ); p->scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); p->drawText( QPointF( 0, 0 ), *text_it ); p->restore(); } }
QSizeF QgsEllipseSymbolLayerV2::calculateSize( QgsSymbolV2RenderContext& context, double* scaledWidth, double* scaledHeight ) { double width = 0; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le { context.setOriginalValueVariable( mSymbolWidth ); width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mSymbolWidth ).toDouble(); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { width = mSize; } else //3. priority: global width setting { width = mSymbolWidth; } if ( scaledWidth ) { *scaledWidth = width; } width = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), width, mSymbolWidthUnit, mSymbolHeightMapUnitScale ); double height = 0; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level { context.setOriginalValueVariable( mSymbolHeight ); height = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, context, mSymbolHeight ).toDouble(); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { height = mSize; } else //3. priority: global height setting { height = mSymbolHeight; } if ( scaledHeight ) { *scaledHeight = height; } height = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), height, mSymbolHeightUnit, mSymbolHeightMapUnitScale ); return QSizeF( width, height ); }
void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } //size scaling by field if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { applySizeScale( context, mPen, mSelPen ); } double offset = mOffset; applyDataDefinedSymbology( context, mPen, mSelPen, offset ); p->setPen( context.selected() ? mSelPen : mPen ); // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #2 points). if ( points.size() <= 2 && ( context.renderContext().vectorSimplifyMethod().simplifyHints() & QgsVectorSimplifyMethod::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::isGeneralizableByDeviceBoundingBox( points, context.renderContext().vectorSimplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawPolyline( points ); p->setRenderHint( QPainter::Antialiasing, true ); return; } if ( qgsDoubleNear( offset, 0 ) ) { p->drawPolyline( points ); } else { double scaledOffset = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), offset, mOffsetUnit, mOffsetMapUnitScale ); QList<QPolygonF> mline = ::offsetLine( points, scaledOffset, context.feature() ? context.feature()->constGeometry()->type() : QGis::Line ); for ( int part = 0; part < mline.count(); ++part ) p->drawPolyline( mline[ part ] ); } }
void QgsMarkerSymbolLayerV2::markerOffset( const QgsSymbolV2RenderContext& context, double width, double height, QgsSymbolV2::OutputUnit widthUnit, QgsSymbolV2::OutputUnit heightUnit, double& offsetX, double& offsetY, const QgsMapUnitScale& widthMapUnitScale, const QgsMapUnitScale& heightMapUnitScale ) const { offsetX = mOffset.x(); offsetY = mOffset.y(); if ( mOffsetExpression ) { QPointF offset = QgsSymbolLayerV2Utils::decodePoint( mOffsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); offsetX = offset.x(); offsetY = offset.y(); } offsetX *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit, mOffsetMapUnitScale ); offsetY *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit, mOffsetMapUnitScale ); HorizontalAnchorPoint horizontalAnchorPoint = mHorizontalAnchorPoint; VerticalAnchorPoint verticalAnchorPoint = mVerticalAnchorPoint; if ( mHorizontalAnchorExpression ) { horizontalAnchorPoint = decodeHorizontalAnchorPoint( mHorizontalAnchorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); } if ( mVerticalAnchorExpression ) { verticalAnchorPoint = decodeVerticalAnchorPoint( mVerticalAnchorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); } //correct horizontal position according to anchor point if ( horizontalAnchorPoint == HCenter && verticalAnchorPoint == VCenter ) { return; } double anchorPointCorrectionX = width * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), widthUnit, widthMapUnitScale ) / 2.0; double anchorPointCorrectionY = height * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), 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; } }
void QgsEllipseSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { if ( !context.feature() || !hasDataDefinedProperty() ) { preparePath( mSymbolName, context ); } mPen.setColor( mOutlineColor ); mPen.setWidthF( mOutlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ) ); mBrush.setColor( mFillColor ); prepareExpressions( context.layer() ); }
void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context ) { QgsPaintEffect* effect = layer->paintEffect(); if ( effect && effect->enabled() ) { QPainter* p = context.renderContext().painter(); p->save(); p->translate( points.boundingRect().topLeft() ); effect->begin( context.renderContext() ); layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context ); effect->end( context.renderContext() ); p->restore(); } else { layer->renderPolyline( points, context ); } }
void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { if ( !p ) { return; } // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #5 points). if ( points.size() <= 5 && ( context.renderContext().vectorSimplifyMethod().simplifyHints() & QgsVectorSimplifyMethod::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::isGeneralizableByDeviceBoundingBox( points, context.renderContext().vectorSimplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawRect( points.boundingRect() ); p->setRenderHint( QPainter::Antialiasing, true ); return; } if ( rings == NULL ) { // simple polygon without holes p->drawPolygon( points ); } else { // polygon with holes must be drawn using painter path QPainterPath path; QPolygonF outerRing = points; path.addPolygon( outerRing ); QList<QPolygonF>::const_iterator it = rings->constBegin(); for ( ; it != rings->constEnd(); ++it ) { QPolygonF ring = *it; path.addPolygon( ring ); } p->drawPath( path ); } }
void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { QgsSymbolV2::SymbolType layertype = layer->type(); QgsPaintEffect* effect = layer->paintEffect(); if ( effect && effect->enabled() ) { QRectF bounds = polygonBounds( points, rings ); QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() ); QPainter* p = context.renderContext().painter(); p->save(); p->translate( bounds.topLeft() ); effect->begin( context.renderContext() ); if ( layertype == QgsSymbolV2::Fill ) { (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context ); } else if ( layertype == QgsSymbolV2::Line ) { (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context ); } delete translatedRings; effect->end( context.renderContext() ); p->restore(); } else { if ( layertype == QgsSymbolV2::Fill ) { (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points, rings, context ); } else if ( layertype == QgsSymbolV2::Line ) { (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points, rings, context ); } } }
void QgsEllipseSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions if ( !context.feature() || !hasDataDefinedProperties() ) { preparePath( mSymbolName, context ); } mPen.setColor( mOutlineColor ); mPen.setStyle( mOutlineStyle ); mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) ); mBrush.setColor( mFillColor ); prepareExpressions( context ); }
void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, const QPointF& point, QgsSymbolV2RenderContext& context ) { static QPointF nullPoint( 0, 0 ); QgsPaintEffect* effect = layer->paintEffect(); if ( effect && effect->enabled() ) { QPainter* p = context.renderContext().painter(); p->save(); p->translate( point ); effect->begin( context.renderContext() ); layer->renderPoint( nullPoint, context ); effect->end( context.renderContext() ); p->restore(); } else { layer->renderPoint( point, context ); } }
void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { if ( mSvgViewBox.isNull() ) { return; } delete mSvgPattern; mSvgPattern = 0; double size = context.outputPixelSize( mPatternWidth ); //don't render pattern if symbol size is below one or above 10,000 pixels if (( int )size < 1.0 || 10000.0 < size ) { mSvgPattern = new QImage(); mBrush.setTextureImage( *mSvgPattern ); } else { bool fitsInCache = true; const QImage& patternImage = QgsSvgCache::instance()->svgAsImage( mSvgFilePath, size, mSvgFillColor, mSvgOutlineColor, mSvgOutlineWidth, context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache ); if ( !fitsInCache ) { const QPicture& patternPict = QgsSvgCache::instance()->svgAsPicture( mSvgFilePath, size, mSvgFillColor, mSvgOutlineColor, mSvgOutlineWidth, context.renderContext().scaleFactor(), 1.0 ); double hwRatio = 1.0; if ( patternPict.width() > 0 ) { hwRatio = ( double )patternPict.height() / ( double )patternPict.width(); } mSvgPattern = new QImage(( int )size, ( int )( size * hwRatio ), QImage::Format_ARGB32_Premultiplied ); mSvgPattern->fill( 0 ); // transparent background QPainter p( mSvgPattern ); p.drawPicture( QPointF( size / 2, size * hwRatio / 2 ), patternPict ); } QTransform brushTransform; brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); if ( !doubleNear( context.alpha(), 1.0 ) ) { QImage transparentImage = fitsInCache ? patternImage.copy() : mSvgPattern->copy(); QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); mBrush.setTextureImage( transparentImage ); } else { mBrush.setTextureImage( fitsInCache ? patternImage : *mSvgPattern ); } mBrush.setTransform( brushTransform ); } if ( mOutline ) { mOutline->startRender( context.renderContext() ); } }
void QgsLineDecorationSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { // draw arrow at the end of line QPainter* p = context.renderContext().painter(); if ( !p ) { return; } int cnt = points.count(); if ( cnt < 2 ) { return; } QPointF p2 = points.at( --cnt ); QPointF p1 = points.at( --cnt ); while ( p2 == p1 && cnt ) p1 = points.at( --cnt ); if ( p1 == p2 ) { // this is a collapsed line... don't bother drawing an arrow // with arbitrary orientation return; } double angle = atan2( p2.y() - p1.y(), p2.x() - p1.x() ); double size = ( mWidth * 8 ) * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit ); double angle1 = angle + M_PI / 6; double angle2 = angle - M_PI / 6; QPointF p2_1 = p2 - QPointF( size * cos( angle1 ), size * sin( angle1 ) ); QPointF p2_2 = p2 - QPointF( size * cos( angle2 ), size * sin( angle2 ) ); p->setPen( context.selected() ? mSelPen : mPen ); p->drawLine( p2, p2_1 ); p->drawLine( p2, p2_2 ); }
void QgsSymbolLayerV2::prepareExpressions( const QgsSymbolV2RenderContext& context ) { QMap< QString, QgsDataDefined* >::const_iterator it = mDataDefinedProperties.constBegin(); for ( ; it != mDataDefinedProperties.constEnd(); ++it ) { if ( it.value() ) { QMap<QString, QVariant> params; if ( context.renderContext().rendererScale() > 0 ) { params.insert( "scale", context.renderContext().rendererScale() ); } it.value()->setExpressionParams( params ); it.value()->prepareExpression( context.renderContext().expressionContext() ); } } if ( context.fields() ) { //QgsFields is implicitly shared, so it's cheap to make a copy mFields = *context.fields(); } }
void QgsMarkerLineSymbolLayerV2::renderPolygonOutline( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { const QgsCurvePolygonV2* curvePolygon = dynamic_cast<const QgsCurvePolygonV2*>( context.renderContext().geometry() ); if ( curvePolygon ) { context.renderContext().setGeometry( curvePolygon->exteriorRing() ); } renderPolyline( points, context ); if ( rings ) { mOffset = -mOffset; // invert the offset for rings! for ( int i = 0; i < rings->size(); ++i ) { if ( curvePolygon ) { context.renderContext().setGeometry( curvePolygon->interiorRing( i ) ); } renderPolyline( rings->at( i ), context ); } mOffset = -mOffset; } }
void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolV2RenderContext& context, const QPointF& centerPoint, int nSymbols ) { QPainter* p = context.renderContext().painter(); if ( nSymbols < 2 || !p ) //draw circle only if multiple features { return; } //draw Circle QPen circlePen( mCircleColor ); circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) ); p->setPen( circlePen ); p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 ); }
void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } double offset = 0.0; applyDataDefinedSymbology( context, mPen, mSelPen, offset ); p->setPen( context.selected() ? mSelPen : mPen ); if ( offset == 0 ) { p->drawPolyline( points ); } else { double scaledOffset = offset * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit ); p->drawPolyline( ::offsetLine( points, scaledOffset ) ); } }
void QgsSimpleLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { QColor penColor = mColor; penColor.setAlphaF( mColor.alphaF() * context.alpha() ); mPen.setColor( penColor ); double scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit ); mPen.setWidthF( scaledWidth ); if ( mUseCustomDashPattern && scaledWidth != 0 ) { mPen.setStyle( Qt::CustomDashLine ); //scale pattern vector QVector<qreal> scaledVector; QVector<qreal>::const_iterator it = mCustomDashVector.constBegin(); for ( ; it != mCustomDashVector.constEnd(); ++it ) { //the dash is specified in terms of pen widths, therefore the division scaledVector << ( *it ) * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mCustomDashPatternUnit ) / scaledWidth; } mPen.setDashPattern( scaledVector ); } else { mPen.setStyle( mPenStyle ); } mPen.setJoinStyle( mPenJoinStyle ); mPen.setCapStyle( mPenCapStyle ); mSelPen = mPen; QColor selColor = context.renderContext().selectionColor(); if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); mSelPen.setColor( selColor ); //prepare expressions for data defined properties prepareExpressions( context.layer() ); }
double QgsSimpleLineSymbolLayerV2::dxfWidth( const QgsDxfExport& e, const QgsSymbolV2RenderContext& context ) const { double width = mWidth; QgsExpression* strokeWidthExpression = expression( "width" ); if ( strokeWidthExpression ) { width = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble() * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() ); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { width = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale ); } return width * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() ); }
void QgsMarkerLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { mMarker->setAlpha( context.alpha() ); mMarker->setOutputUnit( context.outputUnit() ); // if being rotated, it gets initialized with every line segment int hints = 0; if ( mRotateMarker ) hints |= QgsSymbolV2::DataDefinedRotation; if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) hints |= QgsSymbolV2::DataDefinedSizeScale; mMarker->setRenderHints( hints ); mMarker->startRender( context.renderContext() ); }
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); int i, maxCount; bool isRing = false; if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } for ( ; i < maxCount; ++i ) { if ( isRing && placement == Vertex && i == points.count() - 1 ) { continue; // don't draw the last marker - it has been drawn already } // rotate marker (if desired) if ( mRotateMarker ) { double angle = markerAngle( points, isRing, i ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() ); } // restore original rotation mMarker->setAngle( origAngle ); }
void QgsMarkerSymbolLayerV2::markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY ) { offsetX = mOffset.x(); offsetY = mOffset.y(); QgsExpression* offsetExpression = expression( "offset" ); if ( offsetExpression ) { QPointF offset = QgsSymbolLayerV2Utils::decodePoint( offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); offsetX = offset.x(); offsetY = offset.y(); } offsetX *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit ); offsetY *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit ); }
double QgsSimpleLineSymbolLayerV2::dxfWidth( const QgsDxfExport& e, QgsSymbolV2RenderContext& context ) const { double width = mWidth; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) { context.setOriginalValueVariable( mWidth ); width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mWidth ).toDouble() * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() ); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { width = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mWidth, mWidthUnit, mWidthMapUnitScale ); } return width * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() ); }
void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.size() > 0 ) { // calc length qreal length = 0; QPolygonF::const_iterator it = points.constBegin(); QPointF last = *it; for ( ++it; it != points.constEnd(); ++it ) { length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) ); last = *it; } // find the segment where the central point lies it = points.constBegin(); last = *it; qreal last_at = 0, next_at = 0; QPointF next; int segment = 0; for ( ++it; it != points.constEnd(); ++it ) { next = *it; next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) ); if ( next_at >= length / 2 ) break; // we have reached the center last = *it; last_at = next_at; segment++; } // find out the central point on segment MyLine l( last, next ); // for line angle qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at ); QPointF pt = last + ( next - last ) * k; // draw the marker double origAngle = mMarker->angle(); if ( mRotateMarker ) mMarker->setAngle( origAngle + l.angle() * 180 / M_PI ); mMarker->renderPoint( pt, context.feature(), context.renderContext(), -1, context.selected() ); if ( mRotateMarker ) mMarker->setAngle( origAngle ); } }
void QgsSimpleLineSymbolLayerV2::renderPolygonOutline( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } if ( mDrawInsidePolygon ) { //only drawing the line on the interior of the polygon, so set clip path for painter p->save(); QPainterPath clipPath; clipPath.addPolygon( points ); if ( rings != NULL ) { //add polygon rings QList<QPolygonF>::const_iterator it = rings->constBegin(); for ( ; it != rings->constEnd(); ++it ) { QPolygonF ring = *it; clipPath.addPolygon( ring ); } } //use intersect mode, as a clip path may already exist (eg, for composer maps) p->setClipPath( clipPath, Qt::IntersectClip ); } renderPolyline( points, context ); if ( rings ) { mOffset = -mOffset; // invert the offset for rings! foreach ( const QPolygonF& ring, *rings ) renderPolyline( ring, context ); mOffset = -mOffset; } if ( mDrawInsidePolygon ) { //restore painter to reset clip path p->restore(); } }
void QgsEllipseSymbolLayerV2::calculateOffsetAndRotation( QgsSymbolV2RenderContext& 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 ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION ) ) { context.setOriginalValueVariable( angle ); angle = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle, &ok ).toDouble() + mLineAngle; usingDataDefinedRotation = ok; } hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || 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->constGeometry(); if ( g && g->type() == QGis::Point ) { const QgsMapToPixel& m2p = context.renderContext().mapToPixel(); angle += m2p.mapRotation(); } } } if ( angle ) offset = _rotatedOffset( offset, angle ); }
void QgsMarkerLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { mMarker->setAlpha( context.alpha() ); // if being rotated, it gets initialized with every line segment int hints = 0; if ( mRotateMarker ) hints |= QgsSymbolV2::DataDefinedRotation; if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) hints |= QgsSymbolV2::DataDefinedSizeScale; mMarker->setRenderHints( hints ); mMarker->startRender( context.renderContext(), context.layer() ); //prepare expressions for data defined properties prepareExpressions( context.layer() ); }
void QgsArrowSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { mExpressionScope.reset( new QgsExpressionContextScope() ); mScaledArrowWidth = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), arrowWidth(), arrowWidthUnit(), arrowWidthUnitScale() ); mScaledArrowStartWidth = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), arrowStartWidth(), arrowStartWidthUnit(), arrowStartWidthUnitScale() ); mScaledHeadWidth = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), headWidth(), headWidthUnit(), headWidthUnitScale() ); mScaledHeadHeight = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), headHeight(), headHeightUnit(), headHeightUnitScale() ); mScaledOffset = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), offset(), offsetUnit(), offsetMapUnitScale() ); mComputedHeadType = headType(); mComputedArrowType = arrowType(); mSymbol->startRender( context.renderContext() ); }
void QgsVectorFieldSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { if ( mLineSymbol ) { mLineSymbol->startRender( context.renderContext() ); } const QgsVectorLayer* layer = context.layer(); if ( layer ) { mXIndex = layer->fieldNameIndex( mXAttribute ); mYIndex = layer->fieldNameIndex( mYAttribute ); } else { mXIndex = -1; mYIndex = -1; } }
void QgsSimpleFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } p->setBrush( context.selected() ? mSelBrush : mBrush ); p->setPen( mPen ); p->setPen( context.selected() ? mSelPen : mPen ); if ( !mOffset.isNull() ) p->translate( mOffset ); _renderPolygon( p, points, rings ); if ( !mOffset.isNull() ) p->translate( -mOffset ); }
QVariant QgsSymbolLayerV2::evaluateDataDefinedProperty( const QString& property, const QgsSymbolV2RenderContext& context, const QVariant& defaultVal, bool* ok ) const { if ( ok ) *ok = false; QgsDataDefined* dd = getDataDefinedProperty( property ); if ( !dd || !dd->isActive() ) return defaultVal; if ( dd->useExpression() ) { if ( dd->expression() ) { QVariant result = dd->expression()->evaluate( &context.renderContext().expressionContext() ); if ( result.isValid() ) { if ( ok ) *ok = true; return result; } else return defaultVal; } else { return defaultVal; } } else if ( context.feature() && !dd->field().isEmpty() && !mFields.isEmpty() ) { int attributeIndex = mFields.fieldNameIndex( dd->field() ); if ( attributeIndex >= 0 ) { if ( ok ) *ok = true; return context.feature()->attribute( attributeIndex ); } } return defaultVal; }