void QgsTransformEffect::draw( QgsRenderContext &context ) { if ( !source() || !enabled() || !context.painter() ) return; QPainter* painter = context.painter(); //apply transformations painter->save(); QTransform t = createTransform( context ); painter->setTransform( t, true ); drawSource( *painter ); painter->restore(); }
void QgsAnnotation::drawFrame( QgsRenderContext &context ) const { if ( !mFillSymbol ) return; context.painter()->setRenderHint( QPainter::Antialiasing, context.flags() & QgsRenderContext::Antialiasing ); QPolygonF poly; QList<QPolygonF> rings; //empty list for ( int i = 0; i < 4; ++i ) { QLineF currentSegment = segment( i ); poly << currentSegment.p1(); if ( i == mBalloonSegment && mHasFixedMapPosition ) { poly << mBalloonSegmentPoint1; poly << QPointF( 0, 0 ); poly << mBalloonSegmentPoint2; } poly << currentSegment.p2(); } if ( poly.at( 0 ) != poly.at( poly.count() - 1 ) ) poly << poly.at( 0 ); mFillSymbol->startRender( context ); mFillSymbol->renderPolygon( poly, &rings, nullptr, context ); mFillSymbol->stopRender( context ); }
void QgsEffectStackPropertiesWidget::updatePreview() { QPainter painter; QImage previewImage( 150, 150, QImage::Format_ARGB32 ); previewImage.fill( Qt::transparent ); painter.begin( &previewImage ); painter.setRenderHint( QPainter::Antialiasing ); QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter ); if ( !mPreviewPicture ) { QPicture previewPic; QPainter previewPicPainter; previewPicPainter.begin( &previewPic ); previewPicPainter.setPen( Qt::red ); previewPicPainter.setBrush( QColor( 255, 100, 100, 255 ) ); previewPicPainter.drawEllipse( QPoint( 75, 75 ), 30, 30 ); previewPicPainter.end(); mStack->render( previewPic, context ); } else { context.painter()->translate( 35, 35 ); mStack->render( *mPreviewPicture, context ); } painter.end(); lblPreview->setPixmap( QPixmap::fromImage( previewImage ) ); emit widgetChanged(); }
void QgsAnnotation::render( QgsRenderContext &context ) const { QPainter *painter = context.painter(); if ( !painter ) { return; } painter->save(); drawFrame( context ); if ( mHasFixedMapPosition ) { drawMarkerSymbol( context ); } if ( mHasFixedMapPosition ) { painter->translate( mOffsetFromReferencePoint.x() + context.convertToPainterUnits( mContentsMargins.left(), QgsUnitTypes::RenderMillimeters ), mOffsetFromReferencePoint.y() + context.convertToPainterUnits( mContentsMargins.top(), QgsUnitTypes::RenderMillimeters ) ); } else { painter->translate( context.convertToPainterUnits( mContentsMargins.left(), QgsUnitTypes::RenderMillimeters ), context.convertToPainterUnits( mContentsMargins.top(), QgsUnitTypes::RenderMillimeters ) ); } QSizeF size( mFrameSize.width() - context.convertToPainterUnits( mContentsMargins.left() + mContentsMargins.right(), QgsUnitTypes::RenderMillimeters ), mFrameSize.height() - context.convertToPainterUnits( mContentsMargins.top() + mContentsMargins.bottom(), QgsUnitTypes::RenderMillimeters ) ); renderAnnotation( context, size ); painter->restore(); }
void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext &context, const ClusteredGroup &group ) { //calculate max diagonal size from all symbols in group double diagonal = 0; for ( const GroupedFeature &feature : group ) { if ( QgsMarkerSymbol *symbol = feature.symbol() ) { diagonal = std::max( diagonal, M_SQRT2 * symbol->size( context ) ); } } QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; double circleRadius = -1.0; double gridRadius = -1.0; int gridSize = -1; calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius, gridRadius, gridSize ); //only draw circle/grid if there's a pen present - otherwise skip drawing transparent grids if ( mCircleColor.isValid() && mCircleColor.alpha() > 0 ) { //draw circle if ( circleRadius > 0 ) drawCircle( circleRadius, symbolContext, centerPoint, group.size() ); //draw grid else drawGrid( gridSize, symbolContext, symbolPositions, group.size() ); } if ( group.size() > 1 ) { //draw mid point QgsFeature firstFeature = group.at( 0 ).feature; if ( mCenterSymbol ) { mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false ); } else { context.painter()->drawRect( QRectF( centerPoint.x() - symbolContext.outputLineWidth( 1 ), centerPoint.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( group, context, symbolPositions ); //and also the labels if ( mLabelIndex >= 0 ) { drawLabels( centerPoint, symbolContext, labelPositions, group ); } }
void QgsBlurEffect::drawBlurredImage( QgsRenderContext &context, QImage &image ) { //transparency QgsImageOperation::multiplyOpacity( image, 1.0 - mTransparency ); QPainter *painter = context.painter(); painter->save(); painter->setCompositionMode( mBlendMode ); painter->drawImage( imageOffset( context ), image ); painter->restore(); }
void QgsAnnotation::drawMarkerSymbol( QgsRenderContext &context ) const { if ( !context.painter() ) { return; } if ( mMarkerSymbol ) { mMarkerSymbol->startRender( context ); mMarkerSymbol->renderPoint( QPointF( 0, 0 ), nullptr, context ); mMarkerSymbol->stopRender( context ); } }
void QgsDrawSourceEffect::draw( QgsRenderContext &context ) { if ( !enabled() || !context.painter() ) return; QPainter *painter = context.painter(); if ( mBlendMode == QPainter::CompositionMode_SourceOver && qgsDoubleNear( mTransparency, 0.0 ) ) { //just draw unmodified source drawSource( *painter ); } else { //rasterize source and apply modifications QImage image = sourceAsImage( context )->copy(); QgsImageOperation::multiplyOpacity( image, 1.0 - mTransparency ); painter->save(); painter->setCompositionMode( mBlendMode ); painter->drawImage( imageOffset( context ), image ); painter->restore(); } }
void QgsColorEffect::draw( QgsRenderContext &context ) { if ( !source() || !enabled() || !context.painter() ) return; QPainter* painter = context.painter(); //rasterise source and apply modifications QImage image = sourceAsImage( context )->copy(); QgsImageOperation::adjustBrightnessContrast( image, mBrightness, mContrast / 100.0 + 1 ); if ( mGrayscaleMode != QgsImageOperation::GrayscaleOff ) { QgsImageOperation::convertToGrayscale( image, static_cast< QgsImageOperation::GrayscaleMode >( mGrayscaleMode ) ); } QgsImageOperation::adjustHueSaturation( image, mSaturation, mColorizeOn ? mColorizeColor : QColor(), mColorizeStrength / 100.0 ); QgsImageOperation::multiplyOpacity( image, 1.0 - mTransparency ); painter->save(); painter->setCompositionMode( mBlendMode ); painter->drawImage( imageOffset( context ), image ); painter->restore(); }
void QgsPaintEffect::begin( QgsRenderContext &context ) { //temporarily replace painter and direct paint operations for context to a QPicture mPrevPainter = context.painter(); delete mTempPicture; mTempPicture = new QPicture(); delete mEffectPainter; mEffectPainter = new QPainter(); mEffectPainter->begin( mTempPicture ); context.setPainter( mEffectPainter ); }
void QgsLayoutItemHtml::render( QgsRenderContext &context, const QRectF &renderExtent, const int, const QStyleOptionGraphicsItem * ) { if ( !mWebPage ) return; QPainter *painter = context.painter(); painter->save(); // painter is scaled to dots, so scale back to layout units painter->scale( context.scaleFactor() / mHtmlUnitsToLayoutUnits, context.scaleFactor() / mHtmlUnitsToLayoutUnits ); painter->translate( 0.0, -renderExtent.top() * mHtmlUnitsToLayoutUnits ); mWebPage->mainFrame()->render( painter, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToLayoutUnits, renderExtent.width() * mHtmlUnitsToLayoutUnits, renderExtent.height() * mHtmlUnitsToLayoutUnits ) ); painter->restore(); }
void QgsBlurEffect::draw( QgsRenderContext &context ) { if ( !source() || !enabled() || !context.painter() ) return; switch ( mBlurMethod ) { case StackBlur: drawStackBlur( context ); break; case GaussianBlur: drawGaussianBlur( context ); break; } }
void QgsNumericScaleBarRenderer::draw( QgsRenderContext &context, const QgsScaleBarSettings &settings, const ScaleBarContext &scaleContext ) const { if ( !context.painter() ) { return; } QPainter *painter = context.painter(); painter->save(); if ( context.flags() & QgsRenderContext::Antialiasing ) painter->setRenderHint( QPainter::Antialiasing, true ); double margin = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters ); //map scalebar alignment to Qt::AlignmentFlag type QgsTextRenderer::HAlignment hAlign = QgsTextRenderer::AlignLeft; switch ( settings.alignment() ) { case QgsScaleBarSettings::AlignLeft: hAlign = QgsTextRenderer::AlignLeft; break; case QgsScaleBarSettings::AlignMiddle: hAlign = QgsTextRenderer::AlignCenter; break; case QgsScaleBarSettings::AlignRight: hAlign = QgsTextRenderer::AlignRight; break; } //text destination is item's rect, excluding the margin QRectF painterRect( margin, margin, context.convertToPainterUnits( scaleContext.size.width(), QgsUnitTypes::RenderMillimeters ) - 2 * margin, context.convertToPainterUnits( scaleContext.size.height(), QgsUnitTypes::RenderMillimeters ) - 2 * margin ); QgsTextRenderer::drawText( painterRect, 0, hAlign, QStringList() << scaleText( scaleContext.scale ), context, settings.textFormat() ); painter->restore(); }
void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderContext& context, const ClusteredGroup& group ) { //calculate max diagonal size from all symbols in group double diagonal = 0; Q_FOREACH ( const GroupedFeature& feature, group ) { if ( QgsMarkerSymbol* symbol = feature.symbol ) { diagonal = qMax( diagonal, context.convertToPainterUnits( M_SQRT2 * symbol->size(), symbol->sizeUnit(), symbol->sizeMapUnitScale() ) ); } } QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderMillimeters, 1.0, false ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; double circleRadius = -1.0; calculateSymbolAndLabelPositions( symbolContext, centerPoint, group.size(), diagonal, symbolPositions, labelPositions, circleRadius ); //draw circle if ( circleRadius > 0 ) drawCircle( circleRadius, symbolContext, centerPoint, group.size() ); if ( group.size() > 1 ) { //draw mid point QgsFeature firstFeature = group.at( 0 ).feature; if ( mCenterSymbol ) { mCenterSymbol->renderPoint( centerPoint, &firstFeature, context, -1, false ); } else { context.painter()->drawRect( QRectF( centerPoint.x() - symbolContext.outputLineWidth( 1 ), centerPoint.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( group, context, symbolPositions ); //and also the labels if ( mLabelIndex >= 0 ) { drawLabels( centerPoint, symbolContext, labelPositions, group ); } }
void QgsHeatmapRenderer::startRender( QgsRenderContext& context, const QgsFields& fields ) { Q_UNUSED( fields ); if ( !context.painter() ) { return; } // find out classification attribute index from name mWeightAttrNum = fields.fieldNameIndex( mWeightExpressionString ); if ( mWeightAttrNum == -1 ) { mWeightExpression.reset( new QgsExpression( mWeightExpressionString ) ); mWeightExpression->prepare( fields ); } initializeValues( context ); }
void QgsLayoutItemTriangleShape::draw( QgsRenderContext &context, const QStyleOptionGraphicsItem * ) { QPainter *painter = context.painter(); painter->setPen( Qt::NoPen ); painter->setBrush( Qt::NoBrush ); double scale = context.convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); QPolygonF shapePolygon = QPolygonF() << QPointF( 0, rect().height() * scale ) << QPointF( rect().width() * scale, rect().height() * scale ) << QPointF( rect().width() / 2.0 * scale, 0 ) << QPointF( 0, rect().height() * scale ); QList<QPolygonF> rings; //empty list symbol()->startRender( context ); symbol()->renderPolygon( shapePolygon, &rings, nullptr, context ); symbol()->stopRender( context ); }
void QgsInvertedPolygonRenderer::startRender( QgsRenderContext& context, const QgsFields& fields ) { if ( !mSubRenderer ) { return; } mSubRenderer->startRender( context, fields ); mFeaturesCategoryMap.clear(); mFeatureDecorations.clear(); mFields = fields; // We compute coordinates of the extent which will serve as exterior ring // for the final polygon // It must be computed in the destination CRS if reprojection is enabled. const QgsMapToPixel& mtp( context.mapToPixel() ); // convert viewport to dest CRS QRect e( context.painter()->viewport() ); // add some space to hide borders and tend to infinity e.adjust( -e.width()*10, -e.height()*10, e.width()*10, e.height()*10 ); QgsPolyline exteriorRing; exteriorRing << mtp.toMapCoordinates( e.topLeft() ); exteriorRing << mtp.toMapCoordinates( e.topRight() ); exteriorRing << mtp.toMapCoordinates( e.bottomRight() ); exteriorRing << mtp.toMapCoordinates( e.bottomLeft() ); exteriorRing << mtp.toMapCoordinates( e.topLeft() ); mTransform = context.coordinateTransform(); // If reprojection is enabled, we must reproject during renderFeature // and act as if there is no reprojection // If we don't do that, there is no need to have a simple rectangular extent // that covers the whole screen // (a rectangle in the destCRS cannot be expressed as valid coordinates in the sourceCRS in general) if ( mTransform ) { // disable projection context.setCoordinateTransform( 0 ); } mExtentPolygon.clear(); mExtentPolygon.append( exteriorRing ); }
void QgsFormAnnotation::renderAnnotation( QgsRenderContext &context, QSizeF size ) const { if ( !mDesignerWidget ) return; // scale painter back to 96 dpi, so that forms look good even in layout prints context.painter()->save(); const double scaleFactor = context.painter()->device()->logicalDpiX() / 96.0; context.painter()->scale( scaleFactor, scaleFactor ); size /= scaleFactor; mDesignerWidget->setFixedSize( size.toSize() ); context.painter()->setBrush( Qt::NoBrush ); context.painter()->setPen( Qt::NoPen ); mDesignerWidget->render( context.painter(), QPoint( 0, 0 ) ); context.painter()->restore(); }
void QgsHeatmapRenderer::renderImage( QgsRenderContext& context ) { if ( !context.painter() || !mGradientRamp ) { return; } QImage image( context.painter()->device()->width() / mRenderQuality, context.painter()->device()->height() / mRenderQuality, QImage::Format_ARGB32 ); image.fill( Qt::transparent ); double scaleMax = mExplicitMax > 0 ? mExplicitMax : mCalculatedMaxValue; int idx = 0; double pixVal = 0; QColor pixColor; for ( int heightIndex = 0; heightIndex < image.height(); ++heightIndex ) { QRgb* scanLine = ( QRgb* )image.scanLine( heightIndex ); for ( int widthIndex = 0; widthIndex < image.width(); ++widthIndex ) { //scale result to fit in the range [0, 1] pixVal = mValues.at( idx ) > 0 ? qMin(( mValues.at( idx ) / scaleMax ), 1.0 ) : 0; //convert value to color from ramp pixColor = mGradientRamp->color( mInvertRamp ? 1 - pixVal : pixVal ); scanLine[widthIndex] = pixColor.rgba(); idx++; } } if ( mRenderQuality > 1 ) { QImage resized = image.scaled( context.painter()->device()->width(), context.painter()->device()->height() ); context.painter()->drawImage( 0, 0, resized ); } else { context.painter()->drawImage( 0, 0, image ); } }
void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected ) { //save old painter QPainter* renderPainter = context.painter(); QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() ); if ( layer != -1 ) { if ( layer >= 0 && layer < mLayers.count() ) { renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) mLayers[layer], points, symbolContext ); } return; } for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) { renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) * it, points, symbolContext ); } context.setPainter( renderPainter ); }
bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) { if ( !context.painter() ) { return false; } // store this feature as a feature to render with decoration if needed if ( selected || drawVertexMarker ) { mFeatureDecorations.append( FeatureDecoration( feature, selected, drawVertexMarker, layer ) ); } // Features are grouped by category of symbols (returned by symbol(s)ForFeature) // This way, users can have multiple inverted polygon fills for a layer, // for instance, with rule based renderer and different symbols // that have transparency. // // In order to assign a unique category to a set of symbols // during each rendering session (between startRender() and stopRender()), // we build an unique id as a QByteArray that is the concatenation // of each symbol's memory address. // The only assumption made here is that symbol(s)ForFeature will // always return the same address for the same symbol(s) shared amongst // different features. // This QByteArray can then be used as a key for a QMap where the list of // features for this category is stored QByteArray catId; if ( capabilities() & MoreSymbolsPerFeature ) { QgsSymbolV2List syms( mSubRenderer->symbolsForFeature( feature, context ) ); Q_FOREACH ( QgsSymbolV2* sym, syms ) { // append the memory address catId.append( reinterpret_cast<const char*>( &sym ), sizeof( sym ) ); }
bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) { Q_UNUSED( drawVertexMarker ); //point position in screen coords QgsGeometry* geom = feature.geometry(); QGis::WkbType geomType = geom->wkbType(); if ( geomType != QGis::WKBPoint && geomType != QGis::WKBPoint25D ) { //can only render point type return false; } QPointF pt; _getPoint( pt, context, geom->asWkb() ); //get list of labels and symbols QStringList labelAttributeList; QList<QgsMarkerSymbolV2*> symbolList; if ( mDisplacementIds.contains( feature.id() ) ) { //create the symbol for the whole display group if the id is the first entry in a display group QList<QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin(); for ( ; it != mDisplacementGroups.end(); ++it ) { //create the symbol for the whole display group if the id is the first entry in a display group if ( feature.id() == it->begin().key() ) { QMap<QgsFeatureId, QgsFeature>::iterator attIt = it->begin(); for ( ; attIt != it->end(); ++attIt ) { if ( mDrawLabels ) { labelAttributeList << getLabel( attIt.value() ); } else { labelAttributeList << QString(); } symbolList << dynamic_cast<QgsMarkerSymbolV2*>( firstSymbolForFeature( mRenderer, attIt.value() ) ); } } } } else //only one feature { symbolList << dynamic_cast<QgsMarkerSymbolV2*>( firstSymbolForFeature( mRenderer, feature ) ); if ( mDrawLabels ) { labelAttributeList << getLabel( feature ); } else { labelAttributeList << QString(); } } if ( symbolList.isEmpty() && labelAttributeList.isEmpty() ) { return true; //display all point symbols for one posi } //draw symbol double diagonal = 0; double currentWidthFactor; //scale symbol size to map unit and output resolution QList<QgsMarkerSymbolV2*>::const_iterator it = symbolList.constBegin(); for ( ; it != symbolList.constEnd(); ++it ) { if ( *it ) { currentWidthFactor = QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, ( *it )->outputUnit() ); double currentDiagonal = sqrt( 2 * (( *it )->size() * ( *it )->size() ) ) * currentWidthFactor; if ( currentDiagonal > diagonal ) { diagonal = currentDiagonal; } } } QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected ); double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition ); double radius = qMax(( diagonal / 2 ), labelAttributeList.size() * diagonal / 2 / M_PI ) + circleAdditionPainterUnits; //draw Circle drawCircle( radius, symbolContext, pt, symbolList.size() ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; calculateSymbolAndLabelPositions( pt, labelAttributeList.size(), radius, diagonal, symbolPositions, labelPositions ); //draw mid point if ( labelAttributeList.size() > 1 ) { if ( mCenterSymbol ) { mCenterSymbol->renderPoint( pt, &feature, context, layer, selected ); } else { context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( feature, context, symbolList, symbolPositions, selected ); //and also the labels drawLabels( pt, symbolContext, labelPositions, labelAttributeList ); return true; }
void QgsPieDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) { QPainter* p = c.painter(); if ( !p ) { return; } //get sum of values QList<double> values; double currentVal = 0; double valSum = 0; int valCount = 0; QList<int>::const_iterator catIt = s.categoryIndices.constBegin(); for ( ; catIt != s.categoryIndices.constEnd(); ++catIt ) { currentVal = att[*catIt].toDouble(); values.push_back( currentVal ); valSum += currentVal; if ( currentVal ) valCount++; } //draw the slices double totalAngle = 0; double currentAngle; //convert from mm / map units to painter units QSizeF spu = sizePainterUnits( s.size, s, c ); double w = spu.width(); double h = spu.height(); double baseX = position.x(); double baseY = position.y() - h; mPen.setColor( s.penColor ); setPenWidth( mPen, s, c ); p->setPen( mPen ); // there are some values > 0 available if ( valSum > 0 ) { QList<double>::const_iterator valIt = values.constBegin(); QList< QColor >::const_iterator colIt = s.categoryColors.constBegin(); for ( ; valIt != values.constEnd(); ++valIt, ++colIt ) { currentAngle = *valIt / valSum * 360 * 16; mCategoryBrush.setColor( *colIt ); p->setBrush( mCategoryBrush ); // if only 1 value is > 0, draw a circle if ( valCount == 1 ) { p->drawEllipse( baseX, baseY, w, h ); } else { p->drawPie( baseX, baseY, w, h, totalAngle, currentAngle ); } totalAngle += currentAngle; } } else // valSum > 0 { // draw empty circle if no values are defined at all mCategoryBrush.setColor( Qt::transparent ); p->setBrush( mCategoryBrush ); p->drawEllipse( baseX, baseY, w, h ); } }
void QgsDecorationNorthArrow::render( const QgsMapSettings &mapSettings, QgsRenderContext &context ) { //Large IF statement controlled by enable checkbox if ( enabled() ) { QSize size( 64, 64 ); QSvgRenderer svg; const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( QStringLiteral( ":/images/north_arrows/default.svg" ), size.width(), mColor, mOutlineColor, 1.0, 1.0 ); svg.load( svgContent ); if ( svg.isValid() ) { double centerXDouble = size.width() / 2.0; double centerYDouble = size.width() / 2.0; //save the current canvas rotation context.painter()->save(); // //work out how to shift the image so that it rotates // properly about its center //(x cos a + y sin a - x, -x sin a + y cos a - y) // // could move this call to somewhere else so that it is only // called when the projection or map extent changes if ( mAutomatic ) { mRotationInt = QgsBearingUtils:: bearingTrueNorth( mapSettings.destinationCrs(), context.extent().center() ); mRotationInt += mapSettings.rotation(); } double myRadiansDouble = mRotationInt * M_PI / 180.0; int xShift = static_cast<int>( ( ( centerXDouble * cos( myRadiansDouble ) ) + ( centerYDouble * sin( myRadiansDouble ) ) ) - centerXDouble ); int yShift = static_cast<int>( ( ( -centerXDouble * sin( myRadiansDouble ) ) + ( centerYDouble * cos( myRadiansDouble ) ) ) - centerYDouble ); // need width/height of paint device int myHeight = context.painter()->device()->height(); int myWidth = context.painter()->device()->width(); //QgsDebugMsg("Rendering north arrow at " + mPlacementLabels.at(mPlacementIndex)); // Set margin according to selected units int myXOffset = 0; int myYOffset = 0; switch ( mMarginUnit ) { case QgsUnitTypes::RenderMillimeters: { int myPixelsInchX = context.painter()->device()->logicalDpiX(); int myPixelsInchY = context.painter()->device()->logicalDpiY(); myXOffset = myPixelsInchX * INCHES_TO_MM * mMarginHorizontal; myYOffset = myPixelsInchY * INCHES_TO_MM * mMarginVertical; break; } case QgsUnitTypes::RenderPixels: myXOffset = mMarginHorizontal - 5; // Minus 5 to shift tight into corner myYOffset = mMarginVertical - 5; break; case QgsUnitTypes::RenderPercentage: myXOffset = ( ( myWidth - size.width() ) / 100. ) * mMarginHorizontal; myYOffset = ( ( myHeight - size.width() ) / 100. ) * mMarginVertical; break; default: // Use default of top left break; } //Determine placement of label from form combo box switch ( mPlacement ) { case BottomLeft: context.painter()->translate( myXOffset, myHeight - myYOffset - size.width() ); break; case TopLeft: context.painter()->translate( myXOffset, myYOffset ); break; case TopRight: context.painter()->translate( myWidth - myXOffset - size.width(), myYOffset ); break; case BottomRight: context.painter()->translate( myWidth - myXOffset - size.width(), myHeight - myYOffset - size.width() ); break; default: { //QgsDebugMsg("Unable to determine where to put north arrow so defaulting to top left"); } } //rotate the canvas by the north arrow rotation amount context.painter()->rotate( mRotationInt ); //Now we can actually do the drawing, and draw a smooth north arrow even when rotated context.painter()->translate( xShift, yShift ); svg.render( context.painter(), QRectF( 0, 0, size.width(), size.height() ) ); //unrotate the canvas again context.painter()->restore(); } else { QFont myQFont( QStringLiteral( "time" ), 12, QFont::Bold ); context.painter()->setFont( myQFont ); context.painter()->setPen( Qt::black ); context.painter()->drawText( 10, 20, tr( "North arrow pixmap not found" ) ); } } }
void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, QgsRenderContext& context ) { const QgsFeature& feature = group.begin().value().first; bool selected = mSelectedFeatures.contains( feature.id() ); // maybe we should highlight individual features instead of the whole group? //get list of labels and symbols QStringList labelAttributeList; QList<QgsMarkerSymbolV2*> symbolList; QgsMultiPointV2* groupMultiPoint = new QgsMultiPointV2(); for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt ) { labelAttributeList << ( mDrawLabels ? getLabel( attIt.value().first ) : QString() ); symbolList << dynamic_cast<QgsMarkerSymbolV2*>( attIt.value().second ); groupMultiPoint->addGeometry( attIt.value().first.constGeometry()->geometry()->clone() ); } //calculate centroid of all points, this will be center of group QgsGeometry groupGeom( groupMultiPoint ); QgsGeometry* centroid = groupGeom.centroid(); QPointF pt; _getPoint( pt, context, centroid->asWkb() ); delete centroid; //calculate max diagonal size from all symbols in group double diagonal = 0; Q_FOREACH ( QgsMarkerSymbolV2* symbol, symbolList ) { if ( symbol ) { diagonal = qMax( diagonal, QgsSymbolLayerV2Utils::convertToPainterUnits( context, M_SQRT2 * symbol->size(), symbol->outputUnit(), symbol->mapUnitScale() ) ); } } QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; double circleRadius = -1.0; calculateSymbolAndLabelPositions( symbolContext, pt, symbolList.size(), diagonal, symbolPositions, labelPositions, circleRadius ); //draw Circle if ( circleRadius > 0 ) drawCircle( circleRadius, symbolContext, pt, symbolList.size() ); //draw mid point if ( labelAttributeList.size() > 1 ) { if ( mCenterSymbol ) { mCenterSymbol->renderPoint( pt, &feature, context, -1, selected ); } else { context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( feature, context, symbolList, symbolPositions, selected ); //and also the labels drawLabels( pt, symbolContext, labelPositions, labelAttributeList ); }
bool QgsHeatmapRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) { Q_UNUSED( layer ); Q_UNUSED( selected ); Q_UNUSED( drawVertexMarker ); if ( !context.painter() ) { return false; } if ( !feature.constGeometry() || feature.constGeometry()->type() != QGis::Point ) { //can only render point type return false; } double weight = 1.0; if ( !mWeightExpressionString.isEmpty() ) { QVariant value; if ( mWeightAttrNum == -1 ) { Q_ASSERT( mWeightExpression.data() ); value = mWeightExpression->evaluate( &feature ); } else { QgsAttributes attrs = feature.attributes(); value = attrs.value( mWeightAttrNum ); } bool ok = false; double evalWeight = value.toDouble( &ok ); if ( ok ) { weight = evalWeight; } } int width = context.painter()->device()->width() / mRenderQuality; int height = context.painter()->device()->height() / mRenderQuality; //transform geometry if required QgsGeometry* transformedGeom = 0; const QgsCoordinateTransform* xform = context.coordinateTransform(); if ( xform ) { transformedGeom = new QgsGeometry( *feature.constGeometry() ); transformedGeom->transform( *xform ); } //convert point to multipoint QgsMultiPoint multiPoint = convertToMultipoint( transformedGeom ? transformedGeom : feature.constGeometry() ); delete transformedGeom; transformedGeom = 0; //loop through all points in multipoint for ( QgsMultiPoint::const_iterator pointIt = multiPoint.constBegin(); pointIt != multiPoint.constEnd(); ++pointIt ) { QgsPoint pixel = context.mapToPixel().transform( *pointIt ); int pointX = pixel.x() / mRenderQuality; int pointY = pixel.y() / mRenderQuality; for ( int x = qMax( pointX - mRadiusPixels, 0 ); x < qMin( pointX + mRadiusPixels, width ); ++x ) { for ( int y = qMax( pointY - mRadiusPixels, 0 ); y < qMin( pointY + mRadiusPixels, height ); ++y ) { int index = y * width + x; if ( index >= mValues.count( ) ) { continue; } double distanceSquared = pow( pointX - x, 2.0 ) + pow( pointY - y, 2.0 ); if ( distanceSquared > mRadiusSquared ) { continue; } double score = weight * quarticKernel( sqrt( distanceSquared ), mRadiusPixels ); double value = mValues[ index ] + score; if ( value > mCalculatedMaxValue ) { mCalculatedMaxValue = value; } mValues[ index ] = value; } } } mFeaturesRendered++; #if 0 //TODO - enable progressive rendering if ( mFeaturesRendered % 200 == 0 ) { renderImage( context ); } #endif return true; }
void QgsHistogramDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, QPointF position ) { QPainter* p = c.painter(); if ( !p ) { return; } QList<double> values; double maxValue = 0; QgsExpressionContext expressionContext = c.expressionContext(); expressionContext.setFeature( feature ); if ( !feature.fields().isEmpty() ) expressionContext.setFields( feature.fields() ); Q_FOREACH ( const QString& cat, s.categoryAttributes ) { QgsExpression* expression = getExpression( cat, expressionContext ); double currentVal = expression->evaluate( &expressionContext ).toDouble(); values.push_back( currentVal ); maxValue = qMax( currentVal, maxValue ); } double scaledMaxVal = sizePainterUnits( maxValue * mScaleFactor, s, c ); double currentOffset = 0; double scaledWidth = sizePainterUnits( s.barWidth, s, c ); double baseX = position.x(); double baseY = position.y(); mPen.setColor( s.penColor ); setPenWidth( mPen, s, c ); p->setPen( mPen ); QList<double>::const_iterator valIt = values.constBegin(); QList< QColor >::const_iterator colIt = s.categoryColors.constBegin(); for ( ; valIt != values.constEnd(); ++valIt, ++colIt ) { double length = sizePainterUnits( *valIt * mScaleFactor, s, c ); mCategoryBrush.setColor( *colIt ); p->setBrush( mCategoryBrush ); switch ( s.diagramOrientation ) { case QgsDiagramSettings::Up: p->drawRect( baseX + currentOffset, baseY, scaledWidth, length * -1 ); break; case QgsDiagramSettings::Down: p->drawRect( baseX + currentOffset, baseY - scaledMaxVal, scaledWidth, length ); break; case QgsDiagramSettings::Right: p->drawRect( baseX, baseY - currentOffset, length, scaledWidth * -1 ); break; case QgsDiagramSettings::Left: p->drawRect( baseX + scaledMaxVal, baseY - currentOffset, 0 - length, scaledWidth * -1 ); break; } currentOffset += scaledWidth; } }
void QgsDecorationNorthArrow::render( const QgsMapSettings &mapSettings, QgsRenderContext &context ) { if ( !enabled() ) return; double maxLength = mSize * mapSettings.outputDpi() / 25.4; QSvgRenderer svg; const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( svgPath(), maxLength, mColor, mOutlineColor, 1.0, 1.0 ); svg.load( svgContent ); if ( svg.isValid() ) { QSize size( maxLength, maxLength ); QRectF viewBox = svg.viewBoxF(); if ( viewBox.height() > viewBox.width() ) { size.setWidth( maxLength * viewBox.width() / viewBox.height() ); } else { size.setHeight( maxLength * viewBox.height() / viewBox.width() ); } double centerXDouble = size.width() / 2.0; double centerYDouble = size.height() / 2.0; //save the current canvas rotation context.painter()->save(); // //work out how to shift the image so that it rotates // properly about its center //(x cos a + y sin a - x, -x sin a + y cos a - y) // // could move this call to somewhere else so that it is only // called when the projection or map extent changes if ( mAutomatic ) { try { mRotationInt = QgsBearingUtils:: bearingTrueNorth( mapSettings.destinationCrs(), mapSettings.transformContext(), context.extent().center() ); } catch ( QgsException & ) { mRotationInt = 0.0; } mRotationInt += mapSettings.rotation(); } double radiansDouble = mRotationInt * M_PI / 180.0; int xShift = static_cast<int>( ( ( centerXDouble * std::cos( radiansDouble ) ) + ( centerYDouble * std::sin( radiansDouble ) ) ) - centerXDouble ); int yShift = static_cast<int>( ( ( -centerXDouble * std::sin( radiansDouble ) ) + ( centerYDouble * std::cos( radiansDouble ) ) ) - centerYDouble ); // need width/height of paint device int deviceHeight = context.painter()->device()->height(); int deviceWidth = context.painter()->device()->width(); // Set margin according to selected units int xOffset = 0; int yOffset = 0; switch ( mMarginUnit ) { case QgsUnitTypes::RenderMillimeters: { int pixelsInchX = context.painter()->device()->logicalDpiX(); int pixelsInchY = context.painter()->device()->logicalDpiY(); xOffset = pixelsInchX * INCHES_TO_MM * mMarginHorizontal; yOffset = pixelsInchY * INCHES_TO_MM * mMarginVertical; break; } case QgsUnitTypes::RenderPixels: xOffset = mMarginHorizontal - 5; // Minus 5 to shift tight into corner yOffset = mMarginVertical - 5; break; case QgsUnitTypes::RenderPercentage: xOffset = ( ( deviceWidth - size.width() ) / 100. ) * mMarginHorizontal; yOffset = ( ( deviceHeight - size.width() ) / 100. ) * mMarginVertical; break; case QgsUnitTypes::RenderMapUnits: case QgsUnitTypes::RenderPoints: case QgsUnitTypes::RenderInches: case QgsUnitTypes::RenderUnknownUnit: case QgsUnitTypes::RenderMetersInMapUnits: break; } //Determine placement of label from form combo box switch ( mPlacement ) { case BottomLeft: context.painter()->translate( xOffset, deviceHeight - yOffset - maxLength + ( maxLength - size.height() ) / 2 ); break; case TopLeft: context.painter()->translate( xOffset, yOffset ); break; case TopRight: context.painter()->translate( deviceWidth - xOffset - maxLength + ( maxLength - size.width() ) / 2, yOffset ); break; case BottomRight: context.painter()->translate( deviceWidth - xOffset - maxLength + ( maxLength - size.width() ) / 2, deviceHeight - yOffset - maxLength + ( maxLength - size.height() ) / 2 ); break; } //rotate the canvas by the north arrow rotation amount context.painter()->rotate( mRotationInt ); //Now we can actually do the drawing, and draw a smooth north arrow even when rotated context.painter()->translate( xShift, yShift ); svg.render( context.painter(), QRectF( 0, 0, size.width(), size.height() ) ); //unrotate the canvas again context.painter()->restore(); } }
void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, QgsRenderContext& context ) { const QgsFeature& feature = group.begin().value().first; bool selected = mSelectedFeatures.contains( feature.id() ); // maybe we should highlight individual features instead of the whole group? QPointF pt; _getPoint( pt, context, feature.constGeometry()->asWkb() ); //get list of labels and symbols QStringList labelAttributeList; QList<QgsMarkerSymbolV2*> symbolList; for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt ) { labelAttributeList << ( mDrawLabels ? getLabel( attIt.value().first ) : QString() ); symbolList << dynamic_cast<QgsMarkerSymbolV2*>( attIt.value().second ); } //draw symbol double diagonal = 0; double currentWidthFactor; //scale symbol size to map unit and output resolution QList<QgsMarkerSymbolV2*>::const_iterator it = symbolList.constBegin(); for ( ; it != symbolList.constEnd(); ++it ) { if ( *it ) { currentWidthFactor = QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, ( *it )->outputUnit(), ( *it )->mapUnitScale() ); double currentDiagonal = sqrt( 2 * (( *it )->size() * ( *it )->size() ) ) * currentWidthFactor; if ( currentDiagonal > diagonal ) { diagonal = currentDiagonal; } } } QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected ); double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition ); double radius = qMax(( diagonal / 2 ), labelAttributeList.size() * diagonal / 2 / M_PI ) + circleAdditionPainterUnits; //draw Circle drawCircle( radius, symbolContext, pt, symbolList.size() ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; calculateSymbolAndLabelPositions( pt, labelAttributeList.size(), radius, diagonal, symbolPositions, labelPositions ); //draw mid point if ( labelAttributeList.size() > 1 ) { if ( mCenterSymbol ) { mCenterSymbol->renderPoint( pt, &feature, context, -1, selected ); } else { context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( feature, context, symbolList, symbolPositions, selected ); //and also the labels drawLabels( pt, symbolContext, labelPositions, labelAttributeList ); }
void QgsTextDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, QPointF position ) { QPainter* p = c.painter(); if ( !p ) { return; } //convert from mm / map units to painter units QSizeF spu = sizePainterUnits( s.size, s, c ); double w = spu.width(); double h = spu.height(); double baseX = position.x(); double baseY = position.y() - h; QVector<QPointF> textPositions; //midpoints for text placement int nCategories = s.categoryAttributes.size(); for ( int i = 0; i < nCategories; ++i ) { if ( mOrientation == Horizontal ) { textPositions.push_back( QPointF( baseX + ( w / nCategories ) * i + w / nCategories / 2.0, baseY + h / 2.0 ) ); } else //vertical { textPositions.push_back( QPointF( baseX + w / 2.0, baseY + h / nCategories * i + w / nCategories / 2.0 ) ); } } mPen.setColor( s.penColor ); setPenWidth( mPen, s, c ); p->setPen( mPen ); mBrush.setColor( s.backgroundColor ); p->setBrush( mBrush ); //draw shapes and separator lines first if ( mShape == Circle ) { p->drawEllipse( baseX, baseY, w, h ); //draw separator lines QList<QPointF> intersect; //intersections between shape and separation lines QPointF center( baseX + w / 2.0, baseY + h / 2.0 ); double r1 = w / 2.0; double r2 = h / 2.0; for ( int i = 1; i < nCategories; ++i ) { if ( mOrientation == Horizontal ) { lineEllipseIntersection( QPointF( baseX + w / nCategories * i, baseY ), QPointF( baseX + w / nCategories * i, baseY + h ), center, r1, r2, intersect ); } else //vertical { lineEllipseIntersection( QPointF( baseX, baseY + h / nCategories * i ), QPointF( baseX + w, baseY + h / nCategories * i ), center, r1, r2, intersect ); } if ( intersect.size() > 1 ) { p->drawLine( intersect.at( 0 ), intersect.at( 1 ) ); } } } else if ( mShape == Rectangle ) { p->drawRect( QRectF( baseX, baseY, w, h ) ); for ( int i = 1; i < nCategories; ++i ) { if ( mOrientation == Horizontal ) { p->drawLine( QPointF( baseX + w / nCategories * i, baseY ), QPointF( baseX + w / nCategories * i, baseY + h ) ); } else { p->drawLine( QPointF( baseX, baseY + h / nCategories * i ), QPointF( baseX + w, baseY + h / nCategories * i ) ); } } } else //triangle { QPolygonF triangle; triangle << QPointF( baseX, baseY + h ) << QPointF( baseX + w, baseY + h ) << QPointF( baseX + w / 2.0, baseY ); p->drawPolygon( triangle ); QLineF triangleEdgeLeft( baseX + w / 2.0, baseY, baseX, baseY + h ); QLineF triangleEdgeRight( baseX + w, baseY + h, baseX + w / 2.0, baseY ); QPointF intersectionPoint1, intersectionPoint2; for ( int i = 1; i < nCategories; ++i ) { if ( mOrientation == Horizontal ) { QLineF verticalLine( baseX + w / nCategories * i, baseY + h, baseX + w / nCategories * i, baseY ); if ( baseX + w / nCategories * i < baseX + w / 2.0 ) { verticalLine.intersect( triangleEdgeLeft, &intersectionPoint1 ); } else { verticalLine.intersect( triangleEdgeRight, &intersectionPoint1 ); } p->drawLine( QPointF( baseX + w / nCategories * i, baseY + h ), intersectionPoint1 ); } else //vertical { QLineF horizontalLine( baseX, baseY + h / nCategories * i, baseX + w, baseY + h / nCategories * i ); horizontalLine.intersect( triangleEdgeLeft, &intersectionPoint1 ); horizontalLine.intersect( triangleEdgeRight, &intersectionPoint2 ); p->drawLine( intersectionPoint1, intersectionPoint2 ); } } } //draw text QFont sFont = scaledFont( s, c ); QFontMetricsF fontMetrics( sFont ); p->setFont( sFont ); QgsExpressionContext expressionContext = c.expressionContext(); expressionContext.setFeature( feature ); if ( feature.fields() ) expressionContext.setFields( *feature.fields() ); for ( int i = 0; i < textPositions.size(); ++i ) { QgsExpression* expression = getExpression( s.categoryAttributes.at( i ), expressionContext ); QString val = expression->evaluate( &expressionContext ).toString(); //find out dimesions double textWidth = fontMetrics.width( val ); double textHeight = fontMetrics.height(); mPen.setColor( s.categoryColors.at( i ) ); p->setPen( mPen ); QPointF position = textPositions.at( i ); // Calculate vertical placement double xOffset = 0; switch ( s.labelPlacementMethod ) { case QgsDiagramSettings::Height: xOffset = textHeight / 2.0; break; case QgsDiagramSettings::XHeight: xOffset = fontMetrics.xHeight(); break; } p->drawText( QPointF( position.x() - textWidth / 2.0, position.y() + xOffset ), val ); } }