int QgsPalLayerSettings::sizeToPixel( double size, const QgsRenderContext& c ) const { double pixelSize; if ( fontSizeInMapUnits ) { pixelSize = size / c.mapToPixel().mapUnitsPerPixel() * c.rasterScaleFactor(); } else //font size in points { // set font size from points to output size pixelSize = 0.3527 * size * c.scaleFactor() * c.rasterScaleFactor(); } return ( int )( pixelSize + 0.5 ); }
int QgsPieDiagramFactory::getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const { double squareSide = size * diagramSizeScaleFactor( context ) * context.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap; width = squareSide; height = squareSide; return 0; }
void QgsUniqueValueRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature& f, QImage* img, bool selected, double opacity ) { QPainter *p = renderContext.painter(); QgsSymbol* symbol = symbolForFeature( &f ); if ( !symbol ) //no matching symbol { if ( img && mGeometryType == QGis::Point ) { img->fill( 0 ); } else if ( mGeometryType != QGis::Point ) { p->setPen( Qt::NoPen ); p->setBrush( Qt::NoBrush ); } return; } // Point if ( img && mGeometryType == QGis::Point ) { double fieldScale = 1.0; double rotation = 0.0; if ( symbol->scaleClassificationField() >= 0 ) { //first find out the value for the scale classification attribute fieldScale = sqrt( qAbs( f.attribute( symbol->scaleClassificationField() ).toDouble() ) ); } if ( symbol->rotationClassificationField() >= 0 ) { rotation = f.attribute( symbol->rotationClassificationField() ).toDouble(); } QString oldName; if ( symbol->symbolField() >= 0 ) { QString name = f.attribute( symbol->symbolField() ).toString(); oldName = symbol->pointSymbolName(); symbol->setNamedPointSymbol( name ); } double scale = renderContext.scaleFactor(); if ( symbol->pointSizeUnits() ) { scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel(); } *img = symbol->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale, rotation, renderContext.rasterScaleFactor(), opacity ); if ( !oldName.isNull() ) { symbol->setNamedPointSymbol( oldName ); } } // Line, polygon else if ( mGeometryType != QGis::Point ) { if ( !selected ) { QPen pen = symbol->pen(); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); p->setPen( pen ); if ( mGeometryType == QGis::Polygon ) { QBrush brush = symbol->brush(); scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout p->setBrush( brush ); } } else { QPen pen = symbol->pen(); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); if ( mGeometryType == QGis::Polygon ) { QBrush brush = symbol->brush(); scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout brush.setColor( mSelectionColor ); p->setBrush( brush ); } else //don't draw outlines of polygons in selection color otherwise they appear merged { pen.setColor( mSelectionColor ); } p->setPen( pen ); } } }
QgsRasterLayerRenderer::QgsRasterLayerRenderer( QgsRasterLayer* layer, QgsRenderContext& rendererContext ) : QgsMapLayerRenderer( layer->id() ) , mRasterViewPort( nullptr ) , mPipe( nullptr ) { mPainter = rendererContext.painter(); const QgsMapToPixel& theQgsMapToPixel = rendererContext.mapToPixel(); mMapToPixel = &theQgsMapToPixel; QgsMapToPixel mapToPixel = theQgsMapToPixel; if ( mapToPixel.mapRotation() ) { // unset rotation for the sake of local computations. // Rotation will be handled by QPainter later // TODO: provide a method of QgsMapToPixel to fetch map center // in geographical units QgsPoint center = mapToPixel.toMapCoordinates( mapToPixel.mapWidth() / 2.0, mapToPixel.mapHeight() / 2.0 ); mapToPixel.setMapRotation( 0, center.x(), center.y() ); } QgsRectangle myProjectedViewExtent; QgsRectangle myProjectedLayerExtent; if ( rendererContext.coordinateTransform() ) { QgsDebugMsg( "coordinateTransform set -> project extents." ); try { myProjectedViewExtent = rendererContext.coordinateTransform()->transformBoundingBox( rendererContext.extent() ); } catch ( QgsCsException &cs ) { QgsMessageLog::logMessage( QObject::tr( "Could not reproject view extent: %1" ).arg( cs.what() ), QObject::tr( "Raster" ) ); myProjectedViewExtent.setMinimal(); } try { myProjectedLayerExtent = rendererContext.coordinateTransform()->transformBoundingBox( layer->extent() ); } catch ( QgsCsException &cs ) { QgsMessageLog::logMessage( QObject::tr( "Could not reproject layer extent: %1" ).arg( cs.what() ), QObject::tr( "Raster" ) ); myProjectedLayerExtent.setMinimal(); } } else { QgsDebugMsg( "coordinateTransform not set" ); myProjectedViewExtent = rendererContext.extent(); myProjectedLayerExtent = layer->extent(); } // clip raster extent to view extent QgsRectangle myRasterExtent = myProjectedViewExtent.intersect( &myProjectedLayerExtent ); if ( myRasterExtent.isEmpty() ) { QgsDebugMsg( "draw request outside view extent." ); // nothing to do return; } QgsDebugMsg( "theViewExtent is " + rendererContext.extent().toString() ); QgsDebugMsg( "myProjectedViewExtent is " + myProjectedViewExtent.toString() ); QgsDebugMsg( "myProjectedLayerExtent is " + myProjectedLayerExtent.toString() ); QgsDebugMsg( "myRasterExtent is " + myRasterExtent.toString() ); // // The first thing we do is set up the QgsRasterViewPort. This struct stores all the settings // relating to the size (in pixels and coordinate system units) of the raster part that is // in view in the map window. It also stores the origin. // //this is not a class level member because every time the user pans or zooms //the contents of the rasterViewPort will change mRasterViewPort = new QgsRasterViewPort(); mRasterViewPort->mDrawnExtent = myRasterExtent; if ( rendererContext.coordinateTransform() ) { mRasterViewPort->mSrcCRS = layer->crs(); mRasterViewPort->mDestCRS = rendererContext.coordinateTransform()->destCRS(); mRasterViewPort->mSrcDatumTransform = rendererContext.coordinateTransform()->sourceDatumTransform(); mRasterViewPort->mDestDatumTransform = rendererContext.coordinateTransform()->destinationDatumTransform(); } else { mRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid mRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid mRasterViewPort->mSrcDatumTransform = -1; mRasterViewPort->mDestDatumTransform = -1; } // get dimensions of clipped raster image in device coordinate space (this is the size of the viewport) mRasterViewPort->mTopLeftPoint = mapToPixel.transform( myRasterExtent.xMinimum(), myRasterExtent.yMaximum() ); mRasterViewPort->mBottomRightPoint = mapToPixel.transform( myRasterExtent.xMaximum(), myRasterExtent.yMinimum() ); // align to output device grid, i.e. floor/ceil to integers // TODO: this should only be done if paint device is raster - screen, image // for other devices (pdf) it can have floating point origin // we could use floating point for raster devices as well, but respecting the // output device grid should make it more effective as the resampling is done in // the provider anyway mRasterViewPort->mTopLeftPoint.setX( floor( mRasterViewPort->mTopLeftPoint.x() ) ); mRasterViewPort->mTopLeftPoint.setY( floor( mRasterViewPort->mTopLeftPoint.y() ) ); mRasterViewPort->mBottomRightPoint.setX( ceil( mRasterViewPort->mBottomRightPoint.x() ) ); mRasterViewPort->mBottomRightPoint.setY( ceil( mRasterViewPort->mBottomRightPoint.y() ) ); // recalc myRasterExtent to aligned values myRasterExtent.set( mapToPixel.toMapCoordinatesF( mRasterViewPort->mTopLeftPoint.x(), mRasterViewPort->mBottomRightPoint.y() ), mapToPixel.toMapCoordinatesF( mRasterViewPort->mBottomRightPoint.x(), mRasterViewPort->mTopLeftPoint.y() ) ); //raster viewport top left / bottom right are already rounded to int mRasterViewPort->mWidth = static_cast<int>( mRasterViewPort->mBottomRightPoint.x() - mRasterViewPort->mTopLeftPoint.x() ); mRasterViewPort->mHeight = static_cast<int>( mRasterViewPort->mBottomRightPoint.y() - mRasterViewPort->mTopLeftPoint.y() ); //the drawable area can start to get very very large when you get down displaying 2x2 or smaller, this is becasue //mapToPixel.mapUnitsPerPixel() is less then 1, //so we will just get the pixel data and then render these special cases differently in paintImageToCanvas() QgsDebugMsgLevel( QString( "mapUnitsPerPixel = %1" ).arg( mapToPixel.mapUnitsPerPixel() ), 3 ); QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( layer->width() ), 3 ); QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( layer->height() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.xMinimum() = %1" ).arg( myRasterExtent.xMinimum() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.xMaximum() = %1" ).arg( myRasterExtent.xMaximum() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.yMinimum() = %1" ).arg( myRasterExtent.yMinimum() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.yMaximum() = %1" ).arg( myRasterExtent.yMaximum() ), 3 ); QgsDebugMsgLevel( QString( "mTopLeftPoint.x() = %1" ).arg( mRasterViewPort->mTopLeftPoint.x() ), 3 ); QgsDebugMsgLevel( QString( "mBottomRightPoint.x() = %1" ).arg( mRasterViewPort->mBottomRightPoint.x() ), 3 ); QgsDebugMsgLevel( QString( "mTopLeftPoint.y() = %1" ).arg( mRasterViewPort->mTopLeftPoint.y() ), 3 ); QgsDebugMsgLevel( QString( "mBottomRightPoint.y() = %1" ).arg( mRasterViewPort->mBottomRightPoint.y() ), 3 ); QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( mRasterViewPort->mWidth ), 3 ); QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( mRasterViewPort->mHeight ), 3 ); // /\/\/\ - added to handle zoomed-in rasters // TODO R->mLastViewPort = *mRasterViewPort; // TODO: is it necessary? Probably WMS only? layer->dataProvider()->setDpi( rendererContext.rasterScaleFactor() * 25.4 * rendererContext.scaleFactor() ); // copy the whole raster pipe! mPipe = new QgsRasterPipe( *layer->pipe() ); }
void QgsLabel::renderLabel( QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes ) { Q_UNUSED( classAttributes ); if ( mLabelAttributes->selectedOnly() && !selected ) return; QPen pen; QFont font; QString value; QString text; /* Calc scale (not nice) */ QgsPoint point; point = renderContext.mapToPixel().transform( 0, 0 ); double x1 = point.x(); point = renderContext.mapToPixel().transform( 1000, 0 ); double x2 = point.x(); double scale = ( x2 - x1 ) * 0.001; /* Text */ value = fieldValue( Text, feature ); if ( value.isEmpty() ) { text = mLabelAttributes->text(); } else { text = value; } /* Font */ value = fieldValue( Family, feature ); if ( value.isEmpty() ) { font.setFamily( mLabelAttributes->family() ); } else { font.setFamily( value ); } double size; value = fieldValue( Size, feature ); if ( value.isEmpty() ) { size = mLabelAttributes->size(); } else { size = value.toDouble(); } int sizeType; value = fieldValue( SizeType, feature ); if ( value.isEmpty() ) sizeType = mLabelAttributes->sizeType(); else { value = value.toLower(); if ( value.compare( "mapunits" ) == 0 ) sizeType = QgsLabelAttributes::MapUnits; else sizeType = QgsLabelAttributes::PointUnits; } if ( sizeType == QgsLabelAttributes::MapUnits ) { size *= scale; } else //point units { double sizeMM = size * 0.3527; size = sizeMM * renderContext.scaleFactor(); } //Request font larger (multiplied by rasterScaleFactor) as a workaround for the Qt font bug //and scale the painter down by rasterScaleFactor when drawing the label size *= renderContext.rasterScaleFactor(); if (( int )size <= 0 ) // skip too small labels return; font.setPixelSize( size ); value = fieldValue( Color, feature ); if ( value.isEmpty() ) { pen.setColor( mLabelAttributes->color() ); } else { pen.setColor( QColor( value ) ); } value = fieldValue( Bold, feature ); if ( value.isEmpty() ) { font.setBold( mLabelAttributes->bold() ); } else { font.setBold(( bool ) value.toInt() ); } value = fieldValue( Italic, feature ); if ( value.isEmpty() ) { font.setItalic( mLabelAttributes->italic() ); } else { font.setItalic(( bool ) value.toInt() ); } value = fieldValue( Underline, feature ); if ( value.isEmpty() ) { font.setUnderline( mLabelAttributes->underline() ); } else { font.setUnderline(( bool ) value.toInt() ); } value = fieldValue( StrikeOut, feature ); if ( value.isEmpty() ) { font.setStrikeOut( mLabelAttributes->strikeOut() ); } else { font.setStrikeOut(( bool ) value.toInt() ); } // QgsPoint overridePoint; bool useOverridePoint = false; value = fieldValue( XCoordinate, feature ); if ( !value.isEmpty() ) { overridePoint.setX( value.toDouble() ); useOverridePoint = true; } value = fieldValue( YCoordinate, feature ); if ( !value.isEmpty() ) { overridePoint.setY( value.toDouble() ); useOverridePoint = true; } /* Alignment */ int alignment; QFontMetrics fm( font ); int width, height; if ( mLabelAttributes->multilineEnabled() ) { QStringList texts = text.split( "\n" ); width = 0; for ( int i = 0; i < texts.size(); i++ ) { int w = fm.width( texts[i] ); if ( w > width ) width = w; } height = fm.height() * texts.size(); } else { width = fm.width( text ); height = fm.height(); } int dx = 0; int dy = 0; value = fieldValue( Alignment, feature ); if ( value.isEmpty() ) { alignment = mLabelAttributes->alignment(); } else { value = value.toLower(); alignment = 0; if ( value.contains( "left" ) ) alignment |= Qt::AlignLeft; else if ( value.contains( "right" ) ) alignment |= Qt::AlignRight; else alignment |= Qt::AlignHCenter; if ( value.contains( "bottom" ) ) alignment |= Qt::AlignBottom; else if ( value.contains( "top" ) ) alignment |= Qt::AlignTop; else alignment |= Qt::AlignVCenter; } if ( alignment & Qt::AlignLeft ) { dx = 0; } else if ( alignment & Qt::AlignHCenter ) { dx = -width / 2; } else if ( alignment & Qt::AlignRight ) { dx = -width; } if ( alignment & Qt::AlignBottom ) { dy = 0; } else if ( alignment & Qt::AlignVCenter ) { dy = height / 2; } else if ( alignment & Qt::AlignTop ) { dy = height; } // Offset double xoffset, yoffset; value = fieldValue( XOffset, feature ); if ( value.isEmpty() ) { xoffset = mLabelAttributes->xOffset(); } else { xoffset = value.toDouble(); } value = fieldValue( YOffset, feature ); if ( value.isEmpty() ) { yoffset = mLabelAttributes->yOffset(); } else { yoffset = value.toDouble(); } // recalc offset to pixels if ( mLabelAttributes->offsetType() == QgsLabelAttributes::MapUnits ) { xoffset *= scale; yoffset *= scale; } else { xoffset = xoffset * 0.3527 * renderContext.scaleFactor(); yoffset = yoffset * 0.3527 * renderContext.scaleFactor(); } // Angle double ang; value = fieldValue( Angle, feature ); if ( value.isEmpty() ) { ang = mLabelAttributes->angle(); } else { ang = value.toDouble(); } // Work out a suitable position to put the label for the // feature. For multi-geometries, put the same label on each // part. if ( useOverridePoint ) { renderLabel( renderContext, overridePoint, text, font, pen, dx, dy, xoffset, yoffset, ang, width, height, alignment ); } else { std::vector<labelpoint> points; labelPoint( points, feature ); for ( uint i = 0; i < points.size(); ++i ) { renderLabel( renderContext, points[i].p, text, font, pen, dx, dy, xoffset, yoffset, mLabelAttributes->angleIsAuto() ? points[i].angle : ang, width, height, alignment ); } } }
void QgsLabel::renderLabel( QgsRenderContext &renderContext, QgsPoint point, QString text, QFont font, QPen pen, int dx, int dy, double xoffset, double yoffset, double ang, int width, int height, int alignment ) { QPainter *painter = renderContext.painter(); // Convert point to projected units if ( renderContext.coordinateTransform() ) { try { point = renderContext.coordinateTransform()->transform( point ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); // unused otherwise QgsDebugMsg( "Caught transform error. Skipping rendering this label" ); return; } } // and then to canvas units renderContext.mapToPixel().transform( &point ); double x = point.x(); double y = point.y(); double rad = ang * M_PI / 180; x = x + xoffset * cos( rad ) - yoffset * sin( rad ); y = y - xoffset * sin( rad ) - yoffset * cos( rad ); painter->save(); painter->setFont( font ); painter->translate( x, y ); //correct oversampled font size back by scaling painter down painter->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() ); painter->rotate( -ang ); // // Draw a buffer behind the text if one is desired // if ( mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled() ) { double myBufferSize = mLabelAttributes->bufferSize() * 0.3527 * renderContext.scaleFactor() * renderContext.rasterScaleFactor(); QPen bufferPen; if ( mLabelAttributes->bufferColorIsSet() ) { bufferPen.setColor( mLabelAttributes->bufferColor() ); } else //default to a white buffer { bufferPen.setColor( Qt::white ); } painter->setPen( bufferPen ); double bufferStepSize; //hack to distinguish pixel devices from logical devices if (( renderContext.scaleFactor() - 1 ) > 1.5 ) { bufferStepSize = 1; } else //draw more dense in case of logical devices { bufferStepSize = 1 / renderContext.rasterScaleFactor(); } for ( double i = dx - myBufferSize; i <= dx + myBufferSize; i += bufferStepSize ) { for ( double j = dy - myBufferSize; j <= dy + myBufferSize; j += bufferStepSize ) { if ( mLabelAttributes->multilineEnabled() ) painter->drawText( QRectF( i, j - height, width, height ), alignment, text ); else painter->drawText( QPointF( i, j ), text ); } } } painter->setPen( pen ); if ( mLabelAttributes->multilineEnabled() ) painter->drawText( dx, dy - height, width, height, alignment, text ); else painter->drawText( dx, dy, text ); painter->restore(); }
int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices, QgsRenderContext& ctx ) { Q_ASSERT( mMapRenderer != NULL ); // start with a temporary settings class, find out labeling info QgsPalLayerSettings lyrTmp; lyrTmp.readFromLayer( layer ); if ( !lyrTmp.enabled ) return 0; // find out which field will be needed int fldIndex = layer->fieldNameIndex( lyrTmp.fieldName ); if ( fldIndex == -1 ) return 0; attrIndices.insert( fldIndex ); //add indices of data defined fields QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator dIt = lyrTmp.dataDefinedProperties.constBegin(); for ( ; dIt != lyrTmp.dataDefinedProperties.constEnd(); ++dIt ) { attrIndices.insert( dIt.value() ); } // add layer settings to the pallabeling hashtable: <QgsVectorLayer*, QgsPalLayerSettings> mActiveLayers.insert( layer, lyrTmp ); // start using the reference to the layer in hashtable instead of local instance QgsPalLayerSettings& lyr = mActiveLayers[layer]; // how to place the labels Arrangement arrangement; switch ( lyr.placement ) { case QgsPalLayerSettings::AroundPoint: arrangement = P_POINT; break; case QgsPalLayerSettings::OverPoint: arrangement = P_POINT_OVER; break; case QgsPalLayerSettings::Line: arrangement = P_LINE; break; case QgsPalLayerSettings::Curved: arrangement = P_CURVED; break; case QgsPalLayerSettings::Horizontal: arrangement = P_HORIZ; break; case QgsPalLayerSettings::Free: arrangement = P_FREE; break; default: Q_ASSERT( "unsupported placement" && 0 ); return 0; } // create the pal layer double priority = 1 - lyr.priority / 10.0; // convert 0..10 --> 1..0 double min_scale = -1, max_scale = -1; if ( lyr.scaleMin != 0 && lyr.scaleMax != 0 ) { min_scale = lyr.scaleMin; max_scale = lyr.scaleMax; } Layer* l = mPal->addLayer( layer->id().toUtf8().data(), min_scale, max_scale, arrangement, METER, priority, lyr.obstacle, true, true ); if ( lyr.placementFlags ) l->setArrangementFlags( lyr.placementFlags ); // set label mode (label per feature is the default) l->setLabelMode( lyr.labelPerPart ? Layer::LabelPerFeaturePart : Layer::LabelPerFeature ); // set whether adjacent lines should be merged l->setMergeConnectedLines( lyr.mergeLines ); lyr.textFont.setPixelSize( lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx ) ); //raster and vector scale factors lyr.vectorScaleFactor = ctx.scaleFactor(); lyr.rasterCompressFactor = ctx.rasterScaleFactor(); // save the pal layer to our layer context (with some additional info) lyr.palLayer = l; lyr.fieldIndex = fldIndex; lyr.fontMetrics = new QFontMetricsF( lyr.textFont ); lyr.xform = mMapRenderer->coordinateTransform(); if ( mMapRenderer->hasCrsTransformEnabled() ) lyr.ct = new QgsCoordinateTransform( layer->crs(), mMapRenderer->destinationCrs() ); else lyr.ct = NULL; lyr.ptZero = lyr.xform->toMapCoordinates( 0, 0 ); lyr.ptOne = lyr.xform->toMapCoordinates( 1, 0 ); // rect for clipping lyr.extentGeom = QgsGeometry::fromRect( mMapRenderer->extent() ); return 1; // init successful }
void QgsGraduatedSymbolRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity ) { QPainter *p = renderContext.painter(); QgsSymbol* theSymbol = symbolForFeature( &f ); if ( !theSymbol ) { if ( img && mGeometryType == QGis::Point ) { img->fill( 0 ); } else if ( mGeometryType != QGis::Point ) { p->setPen( Qt::NoPen ); p->setBrush( Qt::NoBrush ); } return; } //set the qpen and qpainter to the right values // Point if ( img && mGeometryType == QGis::Point ) { double fieldScale = 1.0; double rotation = 0.0; if ( theSymbol->scaleClassificationField() >= 0 ) { //first find out the value for the scale classification attribute const QgsAttributeMap& attrs = f.attributeMap(); fieldScale = sqrt( qAbs( attrs[theSymbol->scaleClassificationField()].toDouble() ) ); QgsDebugMsgLevel( QString( "Feature has field scale factor %1" ).arg( fieldScale ), 3 ); } if ( theSymbol->rotationClassificationField() >= 0 ) { const QgsAttributeMap& attrs = f.attributeMap(); rotation = attrs[theSymbol->rotationClassificationField()].toDouble(); QgsDebugMsgLevel( QString( "Feature has rotation factor %1" ).arg( rotation ), 3 ); } QString oldName; if ( theSymbol->symbolField() >= 0 ) { const QgsAttributeMap& attrs = f.attributeMap(); QString name = attrs[theSymbol->symbolField()].toString(); QgsDebugMsgLevel( QString( "Feature has name %1" ).arg( name ), 3 ); oldName = theSymbol->pointSymbolName(); theSymbol->setNamedPointSymbol( name ); } double scale = renderContext.scaleFactor(); if ( theSymbol->pointSizeUnits() ) { scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel(); } *img = theSymbol->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale, rotation, renderContext.rasterScaleFactor(), opacity ); if ( !oldName.isNull() ) { theSymbol->setNamedPointSymbol( oldName ); } } // Line, polygon if ( mGeometryType != QGis::Point ) { if ( !selected ) { QPen pen = theSymbol->pen(); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); p->setPen( pen ); if ( mGeometryType == QGis::Polygon ) { QBrush brush = theSymbol->brush(); scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout p->setBrush( brush ); } } else { QPen pen = theSymbol->pen(); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); if ( mGeometryType == QGis::Polygon ) { QBrush brush = theSymbol->brush(); scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout brush.setColor( mSelectionColor ); p->setBrush( brush ); } else //don't draw outlines in selection color for polys otherwise they appear merged { pen.setColor( mSelectionColor ); } p->setPen( pen ); } } }
void QgsContinuousColorRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity ) { QPainter *p = renderContext.painter(); if (( mMinimumSymbol && mMaximumSymbol ) ) { //first find out the value for the classification attribute const QgsAttributes& attrs = f.attributes(); if ( attrs[mClassificationField].isNull() ) { if ( img ) *img = QImage(); } double fvalue = attrs[mClassificationField].toDouble(); //double fvalue = vec[mClassificationField].fieldValue().toDouble(); double minvalue = mMinimumSymbol->lowerValue().toDouble(); double maxvalue = mMaximumSymbol->lowerValue().toDouble(); QColor mincolor, maxcolor; if ( mGeometryType == QGis::Line || mGeometryType == QGis::Point ) { mincolor = mMinimumSymbol->pen().color(); maxcolor = mMaximumSymbol->pen().color(); } else //if polygon { p->setPen( mMinimumSymbol->pen() ); mincolor = mMinimumSymbol->fillColor(); maxcolor = mMaximumSymbol->fillColor(); } int red, green, blue; if (( maxvalue - minvalue ) != 0 ) { red = int ( maxcolor.red() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.red() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) ); green = int ( maxcolor.green() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.green() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) ); blue = int ( maxcolor.blue() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.blue() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) ); } else { red = int ( mincolor.red() ); green = int ( mincolor.green() ); blue = int ( mincolor.blue() ); } if ( mGeometryType == QGis::Point && img ) { // TODO we must get always new marker -> slow, but continuous color for points // probably is not used frequently // Use color for both pen and brush (user can add another layer with outpine) // later add support for both pen and brush to dialog QPen pen = mMinimumSymbol->pen(); pen.setColor( QColor( red, green, blue ) ); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); QBrush brush = mMinimumSymbol->brush(); if ( selected ) { pen.setColor( mSelectionColor ); brush.setColor( mSelectionColor ); } else { brush.setColor( QColor( red, green, blue ) ); } brush.setStyle( Qt::SolidPattern ); *img = QgsMarkerCatalogue::instance()->imageMarker( mMinimumSymbol->pointSymbolName(), mMinimumSymbol->pointSize() * renderContext.scaleFactor() * renderContext.rasterScaleFactor(), pen, brush, opacity ); } else if ( mGeometryType == QGis::Line ) { QPen linePen; linePen.setColor( QColor( red, green, blue ) ); linePen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() ); p->setPen( linePen ); } else //polygon { p->setBrush( QColor( red, green, blue ) ); if ( mDrawPolygonOutline ) { QPen pen; pen.setColor( QColor( 0, 0, 0 ) ); pen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() ); p->setPen( pen ); } else { p->setPen( Qt::NoPen ); } } if ( selected ) { //for polygons we don't use selection color for outline //otherwise adjacent features appear merged when selected if ( mGeometryType != QGis::Polygon ) { QPen pen = mMinimumSymbol->pen(); pen.setColor( mSelectionColor ); p->setPen( pen ); } QBrush brush = mMinimumSymbol->brush(); brush.setColor( mSelectionColor ); p->setBrush( brush ); } } }