void QgsMarkerSymbolLayerV2::markerOffset( const QgsSymbolV2RenderContext& context, double width, double height, QgsSymbolV2::OutputUnit widthUnit, QgsSymbolV2::OutputUnit heightUnit, double& offsetX, double& offsetY ) const { 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 ); HorizontalAnchorPoint horizontalAnchorPoint = mHorizontalAnchorPoint; VerticalAnchorPoint verticalAnchorPoint = mVerticalAnchorPoint; QgsExpression* horizontalAnchorExpression = expression( "horizontal_anchor_point" ); if ( horizontalAnchorExpression ) { horizontalAnchorPoint = decodeHorizontalAnchorPoint( horizontalAnchorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); } QgsExpression* verticalAnchorExpression = expression( "vertical_anchor_point" ); if ( verticalAnchorExpression ) { verticalAnchorPoint = decodeVerticalAnchorPoint( verticalAnchorExpression->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 ) / 2.0; double anchorPointCorrectionY = height * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), heightUnit ) / 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 QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { double offset = mOffset; QgsExpression* offsetExpression = expression( "offset" ); if ( offsetExpression ) { offset = offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } Placement placement = mPlacement; QgsExpression* placementExpression = expression( "placement" ); if ( placementExpression ) { QString placementString = placementExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); if ( placementString.compare( "vertex", Qt::CaseInsensitive ) == 0 ) { placement = Vertex; } else if ( placementString.compare( "lastvertex", Qt::CaseInsensitive ) == 0 ) { placement = LastVertex; } else if ( placementString.compare( "firstvertex", Qt::CaseInsensitive ) == 0 ) { placement = FirstVertex; } else if ( placementString.compare( "centerpoint", Qt::CaseInsensitive ) == 0 ) { placement = CentralPoint; } else { placement = Interval; } } if ( offset == 0 ) { if ( placement == Interval ) renderPolylineInterval( points, context ); else if ( placement == CentralPoint ) renderPolylineCentral( points, context ); else renderPolylineVertex( points, context, placement ); } else { QPolygonF points2 = ::offsetLine( points, offset * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit ) ); if ( placement == Interval ) renderPolylineInterval( points2, context ); else if ( placement == CentralPoint ) renderPolylineCentral( points2, context ); else renderPolylineVertex( points2, context, placement ); } }
void QgsExpressionSelectionDialog::on_mActionSelectInstersect_triggered() { const QgsFeatureIds &oldSelection = mLayer->selectedFeaturesIds(); QgsFeatureIds newSelection; QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() ); const QgsFields fields = mLayer->fields(); expression->prepare( fields ); QgsFeature feat; foreach ( const QgsFeatureId fid, oldSelection ) { QgsFeatureIterator features = mLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ); if ( features.nextFeature( feat ) ) { if ( expression->evaluate( &feat, fields ).toBool() ) { newSelection << feat.id(); } } else { Q_ASSERT( false ); } features.close(); }
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) { QgsExpressionContext expressionContext = c.expressionContext(); expressionContext.setFeature( feature ); if ( feature.fields() ) expressionContext.setFields( *feature.fields() ); QVariant attrVal; if ( is.classificationAttributeIsExpression ) { QgsExpression* expression = getExpression( is.classificationAttributeExpression, expressionContext ); attrVal = expression->evaluate( &expressionContext ); } else { attrVal = feature.attributes().at( is.classificationAttribute ); } bool ok = false; double val = attrVal.toDouble( &ok ); if ( !ok ) { return QSizeF(); //zero size if attribute is missing } return sizeForValue( val, s, is ); }
void QgsExpressionSelectionDialog::on_mActionAddToSelection_triggered() { QgsFeatureIds newSelection = mLayer->selectedFeaturesIds(); QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() ); const QgsFields fields = mLayer->fields(); QgsFeatureIterator features = mLayer->getFeatures(); expression->prepare( fields ); QgsFeature feat; while ( features.nextFeature( feat ) ) { if ( expression->evaluate( &feat, fields ).toBool() ) { newSelection << feat.id(); } } features.close(); mLayer->setSelectedFeatures( newSelection ); delete expression; saveRecent(); }
void QgsExpressionSelectionDialog::on_mActionSelectIntersect_triggered() { const QgsFeatureIds &oldSelection = mLayer->selectedFeaturesIds(); QgsFeatureIds newSelection; QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() ); QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( mLayer ); expression->prepare( &context ); QgsFeature feat; Q_FOREACH ( const QgsFeatureId fid, oldSelection ) { QgsFeatureIterator features = mLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ); if ( features.nextFeature( feat ) ) { context.setFeature( feat ); if ( expression->evaluate( &context ).toBool() ) { newSelection << feat.id(); } } else { Q_ASSERT( false ); } features.close(); }
QColor QgsSimpleLineSymbolLayerV2::dxfColor( const QgsSymbolV2RenderContext& context ) const { QgsExpression* strokeColorExpression = expression( "color" ); if ( strokeColorExpression ) { return ( QgsSymbolLayerV2Utils::decodeColor( strokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); } return mColor; }
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) { Q_UNUSED( c ); QVariant attrVal; if ( is.classificationAttributeIsExpression ) { QgsExpression* expression = getExpression( is.classificationAttributeExpression, feature.fields() ); attrVal = expression->evaluate( feature ); } else { attrVal = feature.attributes()[is.classificationAttribute]; } if ( !attrVal.isValid() ) { return QSizeF(); //zero size if attribute is missing } double scaledValue = attrVal.toDouble(); double scaledLowerValue = is.lowerValue; double scaledUpperValue = is.upperValue; double scaledLowerSizeWidth = is.lowerSize.width(); double scaledLowerSizeHeight = is.lowerSize.height(); double scaledUpperSizeWidth = is.upperSize.width(); double scaledUpperSizeHeight = is.upperSize.height(); // interpolate the squared value if scale by area if ( s.scaleByArea ) { scaledValue = sqrt( scaledValue ); scaledLowerValue = sqrt( scaledLowerValue ); scaledUpperValue = sqrt( scaledUpperValue ); scaledLowerSizeWidth = sqrt( scaledLowerSizeWidth ); scaledLowerSizeHeight = sqrt( scaledLowerSizeHeight ); scaledUpperSizeWidth = sqrt( scaledUpperSizeWidth ); scaledUpperSizeHeight = sqrt( scaledUpperSizeHeight ); } //interpolate size double scaledRatio = ( scaledValue - scaledLowerValue ) / ( scaledUpperValue - scaledLowerValue ); QSizeF size = QSizeF( is.upperSize.width() * scaledRatio + is.lowerSize.width() * ( 1 - scaledRatio ), is.upperSize.height() * scaledRatio + is.lowerSize.height() * ( 1 - scaledRatio ) ); // Scale, if extension is smaller than the specified minimum if ( size.width() <= s.minimumSize && size.height() <= s.minimumSize ) { size.scale( s.minimumSize, s.minimumSize, Qt::KeepAspectRatio ); } return size; }
double QgsSimpleLineSymbolLayerV2::dxfOffset( const QgsDxfExport& e, const QgsSymbolV2RenderContext& context ) const { Q_UNUSED( e ); double offset = mOffset; QgsExpression* offsetExpression = expression( "offset" ); if ( offsetExpression ) { offset = offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } return offset; }
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 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 ); }
QSizeF QgsHistogramDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) { QSizeF size; if ( feature.attributes().isEmpty() ) { return size; //zero size if no attributes } if ( qgsDoubleNear( is.upperValue, is.lowerValue ) ) return size; // invalid value range => zero size 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 ); maxValue = qMax( expression->evaluate( &expressionContext ).toDouble(), maxValue ); } // Scale, if extension is smaller than the specified minimum if ( maxValue < s.minimumSize ) { maxValue = s.minimumSize; } switch ( s.diagramOrientation ) { case QgsDiagramSettings::Up: case QgsDiagramSettings::Down: mScaleFactor = (( is.upperSize.width() - is.lowerSize.height() ) / ( is.upperValue - is.lowerValue ) ); size.scale( s.barWidth * s.categoryAttributes.size(), maxValue * mScaleFactor, Qt::IgnoreAspectRatio ); break; case QgsDiagramSettings::Right: case QgsDiagramSettings::Left: mScaleFactor = (( is.upperSize.width() - is.lowerSize.width() ) / ( is.upperValue - is.lowerValue ) ); size.scale( maxValue * mScaleFactor, s.barWidth * s.categoryAttributes.size(), Qt::IgnoreAspectRatio ); break; } return size; }
void QgsAttributeTypeDialog::defaultExpressionChanged() { QString expression = mExpressionWidget->expression(); if ( expression.isEmpty() ) { mDefaultPreviewLabel->setText( QString() ); return; } QgsExpressionContext context = mLayer->createExpressionContext(); if ( !mPreviewFeature.isValid() ) { // get first feature QgsFeatureIterator it = mLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ); it.nextFeature( mPreviewFeature ); } context.setFeature( mPreviewFeature ); QgsExpression exp = QgsExpression( expression ); exp.prepare( &context ); if ( exp.hasParserError() ) { mDefaultPreviewLabel->setText( "<i>" + exp.parserErrorString() + "</i>" ); return; } QVariant val = exp.evaluate( &context ); if ( exp.hasEvalError() ) { mDefaultPreviewLabel->setText( "<i>" + exp.evalErrorString() + "</i>" ); return; } QString previewText = val.toString(); QgsEditorWidgetFactory *factory = QgsEditorWidgetRegistry::instance()->factory( editorWidgetType() ); if ( factory ) { previewText = factory->representValue( mLayer, mFieldIdx, editorWidgetConfig(), QVariant(), val ); } mDefaultPreviewLabel->setText( "<i>" + previewText + "</i>" ); }
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 ); } }
void QgsSimpleLineSymbolLayerV2::applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QPen& pen, QPen& selPen, double& offset ) { if ( mDataDefinedProperties.isEmpty() ) return; // shortcut //data defined properties double scaledWidth = 0; QgsExpression* strokeWidthExpression = expression( "width" ); if ( strokeWidthExpression ) { scaledWidth = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale ); pen.setWidthF( scaledWidth ); selPen.setWidthF( scaledWidth ); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale ); pen.setWidthF( scaledWidth ); selPen.setWidthF( scaledWidth ); } //color QgsExpression* strokeColorExpression = expression( "color" ); if ( strokeColorExpression ) { pen.setColor( QgsSymbolLayerV2Utils::decodeColor( strokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); } //offset QgsExpression* lineOffsetExpression = expression( "offset" ); if ( lineOffsetExpression ) { offset = lineOffsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } //dash dot vector QgsExpression* dashPatternExpression = expression( "customdash" ); if ( dashPatternExpression ) { double scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale ); double dashWidthDiv = mPen.widthF(); if ( strokeWidthExpression ) { dashWidthDiv = pen.widthF(); scaledWidth = pen.widthF(); } //fix dash pattern width in Qt 4.8 QStringList versionSplit = QString( qVersion() ).split( "." ); if ( versionSplit.size() > 1 && versionSplit.at( 1 ).toInt() >= 8 && ( scaledWidth * context.renderContext().rasterScaleFactor() ) < 1.0 ) { dashWidthDiv = 1.0; } QVector<qreal> dashVector; QStringList dashList = dashPatternExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString().split( ";" ); QStringList::const_iterator dashIt = dashList.constBegin(); for ( ; dashIt != dashList.constEnd(); ++dashIt ) { dashVector.push_back( dashIt->toDouble() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mCustomDashPatternUnit, mCustomDashPatternMapUnitScale ) / dashWidthDiv ); } pen.setDashPattern( dashVector ); } //join style QgsExpression* joinStyleExpression = expression( "joinstyle" ); if ( joinStyleExpression ) { QString joinStyleString = joinStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); pen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( joinStyleString ) ); } //cap style QgsExpression* capStyleExpression = expression( "capstyle" ); if ( capStyleExpression ) { QString capStyleString = capStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); pen.setCapStyle( QgsSymbolLayerV2Utils::decodePenCapStyle( capStyleString ) ); } }
void QgsSimpleMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context ) { QPainter *p = context.renderContext().painter(); if ( !p ) { return; } //offset double offsetX = 0; double offsetY = 0; markerOffset( context, offsetX, offsetY ); QPointF off( offsetX, offsetY ); //angle double angle = mAngle; if ( mAngleExpression ) { angle = mAngleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } if ( angle ) off = _rotatedOffset( off, angle ); //data defined shape? if ( mNameExpression ) { QString name = mNameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); if ( !prepareShape( name ) ) // drawing as a polygon { preparePath( name ); // drawing as a painter path } } if ( mUsingCache ) { // we will use cached image QImage &img = context.selected() ? mSelCache : mCache; double s = img.width() / context.renderContext().rasterScaleFactor(); p->drawImage( QRectF( point.x() - s / 2.0 + off.x(), point.y() - s / 2.0 + off.y(), s, s ), img ); } else { QMatrix transform; // move to the desired position transform.translate( point.x() + off.x(), point.y() + off.y() ); QgsExpression *sizeExpression = expression( "size" ); bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression; // resize if necessary if ( hasDataDefinedSize ) { double scaledSize = mSize; if ( sizeExpression ) { scaledSize = sizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } scaledSize *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit ); switch ( mScaleMethod ) { case QgsSymbolV2::ScaleArea: scaledSize = sqrt( scaledSize ); break; case QgsSymbolV2::ScaleDiameter: break; } double half = scaledSize / 2.0; transform.scale( half, half ); } bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || mAngleExpression; if ( angle != 0 && hasDataDefinedRotation ) transform.rotate( angle ); QgsExpression* colorExpression = expression( "color" ); QgsExpression* colorBorderExpression = expression( "color_border" ); QgsExpression* outlineWidthExpression = expression( "outline_width" ); if ( colorExpression ) { mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); } if ( colorBorderExpression ) { mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorBorderExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); mSelPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorBorderExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); } if ( outlineWidthExpression ) { double outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); mPen.setWidthF( outlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ) ); mSelPen.setWidthF( outlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ) ); } p->setBrush( context.selected() ? mSelBrush : mBrush ); p->setPen( context.selected() ? mSelPen : mPen ); if ( !mPolygon.isEmpty() ) p->drawPolygon( transform.map( mPolygon ) ); else p->drawPath( transform.map( mPath ) ); } }
bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const { //data defined size? double size = mSize; QgsExpression *sizeExpression = expression( "size" ); bool hasDataDefinedSize = false; if ( context ) { hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression; } //data defined size if ( hasDataDefinedSize ) { if ( sizeExpression ) { size = sizeExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble(); } size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context->renderContext(), mSizeUnit ); switch ( mScaleMethod ) { case QgsSymbolV2::ScaleArea: size = sqrt( size ); break; case QgsSymbolV2::ScaleDiameter: break; } } if ( mSizeUnit == QgsSymbolV2::MM ) { size *= mmMapUnitScaleFactor; } double halfSize = size / 2.0; QColor c = mPen.color(); if ( mPen.style() == Qt::NoPen ) { c = mBrush.color(); } QgsExpression* colorExpression = expression( "color" ); if ( colorExpression ) { c = QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( *f ).toString() ); } int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() ); //offset double offsetX = 0; double offsetY = 0; markerOffset( *context, offsetX, offsetY ); QPointF off( offsetX, offsetY ); //angle double angle = mAngle; QgsExpression* angleExpression = expression( "angle" ); if ( angleExpression ) { angle = angleExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble(); } angle = -angle; //rotation in Qt is counterclockwise if ( angle ) off = _rotatedOffset( off, angle ); if ( mSizeUnit == QgsSymbolV2::MM ) { off *= mmMapUnitScaleFactor; } QTransform t; t.translate( shift.x() + offsetX, shift.y() + offsetY ); if ( angle != 0 ) t.rotate( angle ); //data defined symbol name if ( mName == "circle" ) { e.writeGroup( 0, "CIRCLE" ); e.writeGroup( 8, layerName ); e.writeGroup( 62, colorIndex ); e.writeGroup( 10, halfSize + shift.x() ); e.writeGroup( 20, halfSize + shift.y() ); e.writeGroup( 30, 0.0 ); e.writeGroup( 40, halfSize ); } else if ( mName == "square" || mName == "rectangle" ) { QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) ); QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) ); QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) ); QPointF pt4 = t.map( QPointF( halfSize, halfSize ) ); e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) ); } else if ( mName == "diamond" ) { QPointF pt1 = t.map( QPointF( -halfSize, 0 ) ); QPointF pt2 = t.map( QPointF( 0, -halfSize ) ); QPointF pt3 = t.map( QPointF( 0, halfSize ) ); QPointF pt4 = t.map( QPointF( halfSize, 0 ) ); e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) ); } else { return false; } return true; }
void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV2RenderContext& context, const QgsFeature* f ) { mPainterPath = QPainterPath(); const QgsRenderContext& ct = context.renderContext(); double width = 0; QgsExpression* widthExpression = expression( "width" ); if ( widthExpression ) //1. priority: data defined setting on symbol layer level { width = widthExpression->evaluate( const_cast<QgsFeature*>( f ) ).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; } width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( ct, mSymbolWidthUnit ); double height = 0; QgsExpression* heightExpression = expression( "height" ); if ( heightExpression ) //1. priority: data defined setting on symbol layer level { height = heightExpression->evaluate( const_cast<QgsFeature*>( f ) ).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; } height *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( ct, mSymbolHeightUnit ); if ( symbolName == "circle" ) { mPainterPath.addEllipse( QRectF( -width / 2.0, -height / 2.0, width, height ) ); } else if ( symbolName == "rectangle" ) { mPainterPath.addRect( QRectF( -width / 2.0, -height / 2.0, width, height ) ); } else if ( symbolName == "cross" ) { mPainterPath.moveTo( 0, -height / 2.0 ); mPainterPath.lineTo( 0, height / 2.0 ); mPainterPath.moveTo( -width / 2.0, 0 ); mPainterPath.lineTo( width / 2.0, 0 ); } else if ( symbolName == "triangle" ) { mPainterPath.moveTo( 0, -height / 2.0 ); mPainterPath.lineTo( -width / 2.0, height / 2.0 ); mPainterPath.lineTo( width / 2.0, height / 2.0 ); mPainterPath.lineTo( 0, -height / 2.0 ); } }
void QgsEllipseSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context ) { QgsExpression* outlineWidthExpression = expression( "outline_width" ); QgsExpression* fillColorExpression = expression( "fill_color" ); QgsExpression* outlineColorExpression = expression( "outline_color" ); QgsExpression* widthExpression = expression( "width" ); QgsExpression* heightExpression = expression( "height" ); QgsExpression* symbolNameExpression = expression( "symbol_name" ); QgsExpression* rotationExpression = expression( "rotation" ); if ( outlineWidthExpression ) { double width = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ); mPen.setWidthF( width ); } if ( fillColorExpression ) { QString colorString = fillColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); mBrush.setColor( QColor( colorString ) ); } if ( outlineColorExpression ) { QString colorString = outlineColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); mPen.setColor( QColor( colorString ) ); } if ( widthExpression || heightExpression || symbolNameExpression ) { QString symbolName = mSymbolName; if ( symbolNameExpression ) { symbolName = symbolNameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); } preparePath( symbolName, context, context.feature() ); } //offset double offsetX = 0; double offsetY = 0; markerOffset( context, mSymbolWidth, mSymbolHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY ); QPointF off( offsetX, offsetY ); QPainter* p = context.renderContext().painter(); if ( !p ) { return; } //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) double rotation = 0.0; if ( rotationExpression ) { rotation = rotationExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } else if ( !qgsDoubleNear( mAngle, 0.0 ) ) { rotation = mAngle; } if ( rotation ) off = _rotatedOffset( off, rotation ); QMatrix transform; transform.translate( point.x() + off.x(), point.y() + off.y() ); if ( !qgsDoubleNear( rotation, 0.0 ) ) { transform.rotate( rotation ); } p->setPen( mPen ); p->setBrush( mBrush ); p->drawPath( transform.map( mPainterPath ) ); }
void QgsAttributeTableModel::loadAttributes() { if ( !layer() ) { return; } bool ins = false, rm = false; QgsAttributeList attributes; const QgsFields& fields = layer()->pendingFields(); for ( int idx = 0; idx < fields.count(); ++idx ) { switch ( layer()->editType( idx ) ) { case QgsVectorLayer::Hidden: continue; case QgsVectorLayer::ValueMap: mValueMaps.insert( idx, new QMap< QString, QVariant >( layer()->valueMap( idx ) ) ); break; case QgsVectorLayer::ValueRelation: { const QgsVectorLayer::ValueRelationData &data = layer()->valueRelation( idx ); QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) ); if ( !layer ) continue; int ki = layer->fieldNameIndex( data.mKey ); int vi = layer->fieldNameIndex( data.mValue ); QgsExpression *e = 0; if ( !data.mFilterExpression.isEmpty() ) { e = new QgsExpression( data.mFilterExpression ); if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) ) continue; } if ( ki >= 0 && vi >= 0 ) { QSet<int> attributes; attributes << ki << vi; QgsFeatureRequest::Flag flags = QgsFeatureRequest::NoGeometry; if ( e ) { if ( e->needsGeometry() ) flags = QgsFeatureRequest::NoFlags; foreach ( const QString &field, e->referencedColumns() ) { int idx = layer->fieldNameIndex( field ); if ( idx < 0 ) continue; attributes << idx; } } QMap< QString, QVariant > *map = new QMap< QString, QVariant >(); QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFlags( flags ).setSubsetOfAttributes( attributes.toList() ) ); QgsFeature f; while ( fit.nextFeature( f ) ) { if ( e && !e->evaluate( &f ).toBool() ) continue; map->insert( f.attribute( vi ).toString(), f.attribute( ki ) ); } mValueMaps.insert( idx, map ); } } break; default: break; } attributes << idx; }
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 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; double offsetAlongLine = mOffsetAlongLine; QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" ); if ( offsetAlongLineExpression ) { offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } if ( offsetAlongLine != 0 ) { //scale offset along line offsetAlongLine *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale ); } 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; } if ( offsetAlongLine > 0 && ( placement == FirstVertex || placement == LastVertex ) ) { double distance; distance = placement == FirstVertex ? offsetAlongLine : -offsetAlongLine; renderOffsetVertexAlongLine( points, i, distance, context ); // restore original rotation mMarker->setAngle( origAngle ); return; } 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 QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context ) { QPainter *p = context.renderContext().painter(); if ( !p ) return; double size = mSize; QgsExpression* sizeExpression = expression( "size" ); bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression; if ( sizeExpression ) { size = sizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit ); if ( hasDataDefinedSize ) { switch ( mScaleMethod ) { case QgsSymbolV2::ScaleArea: size = sqrt( size ); break; case QgsSymbolV2::ScaleDiameter: break; } } //don't render symbols with size below one or above 10,000 pixels if (( int )size < 1 || 10000.0 < size ) { return; } p->save(); //offset double offsetX = 0; double offsetY = 0; markerOffset( context, offsetX, offsetY ); QPointF outputOffset( offsetX, offsetY ); double angle = mAngle; QgsExpression* angleExpression = expression( "angle" ); if ( angleExpression ) { angle = angleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } if ( angle ) outputOffset = _rotatedOffset( outputOffset, angle ); p->translate( point + outputOffset ); bool rotated = !qgsDoubleNear( angle, 0 ); bool drawOnScreen = qgsDoubleNear( context.renderContext().rasterScaleFactor(), 1.0, 0.1 ); if ( rotated ) p->rotate( angle ); QString path = mPath; QgsExpression* nameExpression = expression( "name" ); if ( nameExpression ) { path = nameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); } double outlineWidth = mOutlineWidth; QgsExpression* outlineWidthExpression = expression( "outline_width" ); if ( outlineWidthExpression ) { outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } QColor fillColor = mFillColor; QgsExpression* fillExpression = expression( "fill" ); if ( fillExpression ) { fillColor = QgsSymbolLayerV2Utils::decodeColor( fillExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); } QColor outlineColor = mOutlineColor; QgsExpression* outlineExpression = expression( "outline" ); if ( outlineExpression ) { outlineColor = QgsSymbolLayerV2Utils::decodeColor( outlineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ); } bool fitsInCache = true; bool usePict = true; double hwRatio = 1.0; if ( drawOnScreen && !rotated ) { usePict = false; const QImage& img = QgsSvgCache::instance()->svgAsImage( path, size, fillColor, outlineColor, outlineWidth, context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache ); if ( fitsInCache && img.width() > 1 ) { //consider transparency if ( !qgsDoubleNear( context.alpha(), 1.0 ) ) { QImage transparentImage = img.copy(); QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage ); hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width(); } else { p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img ); hwRatio = ( double )img.height() / ( double )img.width(); } } } if ( usePict || !fitsInCache ) { p->setOpacity( context.alpha() ); const QPicture& pct = QgsSvgCache::instance()->svgAsPicture( path, size, fillColor, outlineColor, outlineWidth, context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), context.renderContext().forceVectorOutput() ); if ( pct.width() > 1 ) { p->drawPicture( 0, 0, pct ); hwRatio = ( double )pct.height() / ( double )pct.width(); } } if ( context.selected() ) { QPen pen( context.renderContext().selectionColor() ); double penWidth = QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), QgsSymbolV2::MM ); if ( penWidth > size / 20 ) { // keep the pen width from covering symbol penWidth = size / 20; } double penOffset = penWidth / 2; pen.setWidth( penWidth ); p->setPen( pen ); p->setBrush( Qt::NoBrush ); double wSize = size + penOffset; double hSize = size * hwRatio + penOffset; p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) ); } p->restore(); }
void QgsSimpleLineSymbolLayerV2::applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QPen& pen, QPen& selPen, double& offset ) { //data defined properties double scaledWidth = 0; QgsExpression* strokeWidthExpression = expression( "width" ); if ( strokeWidthExpression ) { scaledWidth = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit ); pen.setWidthF( scaledWidth ); selPen.setWidthF( scaledWidth ); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit ); pen.setWidthF( scaledWidth ); selPen.setWidthF( scaledWidth ); } //color QgsExpression* strokeColorExpression = expression( "color" ); if ( strokeColorExpression ) { pen.setColor( QgsSymbolLayerV2Utils::decodeColor( strokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); } //offset offset = mOffset; QgsExpression* lineOffsetExpression = expression( "offset" ); if ( lineOffsetExpression ) { offset = lineOffsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } //dash dot vector QgsExpression* dashPatternExpression = expression( "customdash" ); if ( dashPatternExpression ) { QVector<qreal> dashVector; QStringList dashList = dashPatternExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString().split( ";" ); QStringList::const_iterator dashIt = dashList.constBegin(); for ( ; dashIt != dashList.constEnd(); ++dashIt ) { dashVector.push_back( dashIt->toDouble() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mCustomDashPatternUnit ) / mPen.widthF() ); } pen.setDashPattern( dashVector ); } //join style QgsExpression* joinStyleExpression = expression( "joinstyle" ); if ( joinStyleExpression ) { QString joinStyleString = joinStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); pen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( joinStyleString ) ); } //cap style QgsExpression* capStyleExpression = expression( "capstyle" ); if ( capStyleExpression ) { QString capStyleString = capStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); pen.setCapStyle( QgsSymbolLayerV2Utils::decodePenCapStyle( capStyleString ) ); } }
void QgsPieDiagram::renderDiagram( const QgsFeature& feature, 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<QString>::const_iterator catIt = s.categoryAttributes.constBegin(); for ( ; catIt != s.categoryAttributes.constEnd(); ++catIt ) { QgsExpression* expression = getExpression( *catIt, feature.fields() ); currentVal = expression->evaluate( feature ).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 ) { if ( *valIt ) { 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 + s.angleOffset, 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 ); } }
bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const { //width double symbolWidth = mSymbolWidth; QgsExpression* widthExpression = expression( "width" ); if ( widthExpression ) //1. priority: data defined setting on symbol layer level { symbolWidth = widthExpression->evaluate( const_cast<QgsFeature*>( f ) ).toDouble(); } else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { symbolWidth = mSize; } if ( mSymbolWidthUnit == QgsSymbolV2::MM ) { symbolWidth *= mmMapUnitScaleFactor; } //height double symbolHeight = mSymbolHeight; QgsExpression* heightExpression = expression( "height" ); if ( heightExpression ) //1. priority: data defined setting on symbol layer level { symbolHeight = heightExpression->evaluate( const_cast<QgsFeature*>( f ) ).toDouble(); } else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { symbolHeight = mSize; } if ( mSymbolHeightUnit == QgsSymbolV2::MM ) { symbolHeight *= mmMapUnitScaleFactor; } //outline width double outlineWidth = mOutlineWidth; QgsExpression* outlineWidthExpression = expression( "outline_width" ); if ( outlineWidthExpression ) { outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble(); } if ( mOutlineWidthUnit == QgsSymbolV2::MM ) { outlineWidth *= outlineWidth; } //color QColor c = mFillColor; QgsExpression* fillColorExpression = expression( "fill_color" ); if ( fillColorExpression ) { c = QColor( fillColorExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toString() ); } int colorIndex = e.closestColorMatch( c.rgb() ); //symbol name QString symbolName = mSymbolName; QgsExpression* symbolNameExpression = expression( "symbol_name" ); if ( symbolNameExpression ) { QgsExpression* symbolNameExpression = expression( "symbol_name" ); symbolName = symbolNameExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toString(); } //offset double offsetX = 0; double offsetY = 0; markerOffset( *context, offsetX, offsetY ); QPointF off( offsetX, offsetY ); //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) double rotation = 0.0; QgsExpression* rotationExpression = expression( "rotation" ); if ( rotationExpression ) { rotation = rotationExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble(); } else if ( !qgsDoubleNear( mAngle, 0.0 ) ) { rotation = mAngle; } rotation = -rotation; //rotation in Qt is counterclockwise if ( rotation ) off = _rotatedOffset( off, rotation ); QTransform t; t.translate( shift.x() + offsetX, shift.y() + offsetY ); if ( rotation != 0 ) t.rotate( rotation ); double halfWidth = symbolWidth / 2.0; double halfHeight = symbolHeight / 2.0; if ( symbolName == "circle" ) { //soon... } else if ( symbolName == "rectangle" ) { QPointF pt1( t.map( QPointF( -halfWidth, -halfHeight ) ) ); QPointF pt2( t.map( QPointF( halfWidth, -halfHeight ) ) ); QPointF pt3( t.map( QPointF( -halfWidth, halfHeight ) ) ); QPointF pt4( t.map( QPointF( halfWidth, halfHeight ) ) ); e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) ); return true; } else if ( symbolName == "cross" ) { QgsPolyline line1( 2 ); QPointF pt1( t.map( QPointF( -halfWidth, 0 ) ) ); QPointF pt2( t.map( QPointF( halfWidth, 0 ) ) ); line1[0] = QgsPoint( pt1.x(), pt1.y() ); line1[1] = QgsPoint( pt2.x(), pt2.y() ); e.writePolyline( line1, layerName, "CONTINUOUS", colorIndex, outlineWidth, false ); QgsPolyline line2( 2 ); QPointF pt3( t.map( QPointF( 0, halfHeight ) ) ); QPointF pt4( t.map( QPointF( 0, -halfHeight ) ) ); line2[0] = QgsPoint( pt3.x(), pt3.y() ); line2[1] = QgsPoint( pt3.x(), pt3.y() ); e.writePolyline( line2, layerName, "CONTINUOUS", colorIndex, outlineWidth, false ); return true; } else if ( symbolName == "triangle" ) { QPointF pt1( t.map( QPointF( -halfWidth, -halfHeight ) ) ); QPointF pt2( t.map( QPointF( halfWidth, -halfHeight ) ) ); QPointF pt3( t.map( QPointF( 0, halfHeight ) ) ); QPointF pt4( t.map( QPointF( 0, halfHeight ) ) ); e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) ); return true; } return false; //soon... }
void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.isEmpty() ) return; QPointF lastPt = points[0]; double lengthLeft = 0; // how much is left until next marker bool first = mOffsetAlongLine ? false : true; //only draw marker at first vertex when no offset along line is set double origAngle = mMarker->angle(); QgsRenderContext& rc = context.renderContext(); double interval = mInterval; QgsExpression* intervalExpression = expression( "interval" ); if ( intervalExpression ) { interval = intervalExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } if ( interval <= 0 ) { interval = 0.1; } double offsetAlongLine = mOffsetAlongLine; QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" ); if ( offsetAlongLineExpression ) { offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } double painterUnitInterval = interval * QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mIntervalUnit, mIntervalMapUnitScale ); lengthLeft = painterUnitInterval - offsetAlongLine * QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mIntervalUnit, mIntervalMapUnitScale ); for ( int i = 1; i < points.count(); ++i ) { const QPointF& pt = points[i]; if ( lastPt == pt ) // must not be equal! continue; // for each line, find out dx and dy, and length MyLine l( lastPt, pt ); QPointF diff = l.diffForInterval( painterUnitInterval ); // if there's some length left from previous line // use only the rest for the first point in new line segment double c = 1 - lengthLeft / painterUnitInterval; lengthLeft += l.length(); // rotate marker (if desired) if ( mRotateMarker ) { mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) ); } // draw first marker if ( first ) { mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() ); first = false; } // while we're not at the end of line segment, draw! while ( lengthLeft > painterUnitInterval ) { // "c" is 1 for regular point or in interval (0,1] for begin of line segment lastPt += c * diff; lengthLeft -= painterUnitInterval; mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() ); c = 1; // reset c (if wasn't 1 already) } lastPt = pt; } // restore original rotation mMarker->setAngle( origAngle ); }
bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &contents ) { contents.clear(); if (( mSource == QgsComposerAttributeTableV2::AtlasFeature || mSource == QgsComposerAttributeTableV2::RelationChildren ) && !mComposition->atlasComposition().enabled() ) { //source mode requires atlas, but atlas disabled return false; } QgsVectorLayer* layer = sourceLayer(); if ( !layer ) { //no source layer return false; } //prepare filter expression std::auto_ptr<QgsExpression> filterExpression; bool activeFilter = false; if ( mFilterFeatures && !mFeatureFilter.isEmpty() ) { filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) ); if ( !filterExpression->hasParserError() ) { activeFilter = true; } } QgsRectangle selectionRect; if ( mComposerMap && mShowOnlyVisibleFeatures ) { selectionRect = *mComposerMap->currentMapExtent(); if ( layer && mComposition->mapSettings().hasCrsTransformEnabled() ) { //transform back to layer CRS QgsCoordinateTransform coordTransform( layer->crs(), mComposition->mapSettings().destinationCrs() ); try { selectionRect = coordTransform.transformBoundingBox( selectionRect, QgsCoordinateTransform::ReverseTransform ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); return false; } } } QgsFeatureRequest req; if ( mSource == QgsComposerAttributeTableV2::RelationChildren ) { QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId ); QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature(); if ( atlasFeature ) { req = relation.getRelatedFeaturesRequest( *atlasFeature ); } else { //no atlas feature, so empty table return true; } } if ( !selectionRect.isEmpty() ) req.setFilterRect( selectionRect ); req.setFlags( mShowOnlyVisibleFeatures ? QgsFeatureRequest::ExactIntersect : QgsFeatureRequest::NoFlags ); if ( mSource == QgsComposerAttributeTableV2::AtlasFeature && mComposition->atlasComposition().enabled() ) { //source mode is current atlas feature QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature(); if ( atlasFeature ) { req.setFilterFid( atlasFeature->id() ); } else { //no atlas feature, so empty table return true; } } QgsFeature f; int counter = 0; QgsFeatureIterator fit = layer->getFeatures( req ); while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures ) { //check feature against filter if ( activeFilter ) { QVariant result = filterExpression->evaluate( &f, layer->pendingFields() ); // skip this feature if the filter evaluation is false if ( !result.toBool() ) { continue; } } //check against atlas feature intersection if ( mFilterToAtlasIntersection ) { if ( !f.geometry() || ! mComposition->atlasComposition().enabled() ) { continue; } QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature(); if ( !atlasFeature || !atlasFeature->geometry() || !f.geometry()->intersects( atlasFeature->geometry() ) ) { //feature falls outside current atlas feature continue; } } QgsComposerTableRow currentRow; QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); for ( ; columnIt != mColumns.constEnd(); ++columnIt ) { int idx = layer->fieldNameIndex(( *columnIt )->attribute() ); if ( idx != -1 ) { currentRow << f.attributes()[idx]; } else { // Lets assume it's an expression QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() ); expression->setCurrentRowNumber( counter + 1 ); expression->prepare( layer->pendingFields() ); QVariant value = expression->evaluate( f ) ; currentRow << value; } } if ( !mShowUniqueRowsOnly || !contentsContainsRow( contents, currentRow ) ) { contents << currentRow; ++counter; } } //sort the list, starting with the last attribute QgsComposerAttributeTableCompareV2 c; QList< QPair<int, bool> > sortColumns = sortAttributes(); for ( int i = sortColumns.size() - 1; i >= 0; --i ) { c.setSortColumn( sortColumns.at( i ).first ); c.setAscending( sortColumns.at( i ).second ); qStableSort( contents.begin(), contents.end(), c ); } recalculateTableSize(); return true; }
QVariant QmlExpression::evaluate( const QString &expression ) const { QgsExpression exp = QgsExpression( expression ); exp.prepare( &mExpressionContext ); return exp.evaluate( &mExpressionContext ); }
bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &attributeMaps ) { if ( !mVectorLayer ) { return false; } QScopedPointer< QgsExpressionContext > context( createExpressionContext() ); context->setFields( mVectorLayer->fields() ); attributeMaps.clear(); //prepare filter expression QScopedPointer<QgsExpression> filterExpression; bool activeFilter = false; if ( mFilterFeatures && !mFeatureFilter.isEmpty() ) { filterExpression.reset( new QgsExpression( mFeatureFilter ) ); if ( !filterExpression->hasParserError() ) { activeFilter = true; } } QgsRectangle selectionRect; if ( mComposerMap && mShowOnlyVisibleFeatures ) { selectionRect = *mComposerMap->currentMapExtent(); if ( mComposition->mapSettings().hasCrsTransformEnabled() ) { //transform back to layer CRS QgsCoordinateTransform coordTransform( mVectorLayer->crs(), mComposition->mapSettings().destinationCrs() ); try { selectionRect = coordTransform.transformBoundingBox( selectionRect, QgsCoordinateTransform::ReverseTransform ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); return false; } } } QgsFeatureRequest req; if ( !selectionRect.isEmpty() ) req.setFilterRect( selectionRect ); req.setFlags( mShowOnlyVisibleFeatures ? QgsFeatureRequest::ExactIntersect : QgsFeatureRequest::NoFlags ); QgsFeature f; int counter = 0; QgsFeatureIterator fit = mVectorLayer->getFeatures( req ); while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures ) { context->setFeature( f ); //check feature against filter if ( activeFilter && !filterExpression.isNull() ) { QVariant result = filterExpression->evaluate( context.data() ); // skip this feature if the filter evaluation is false if ( !result.toBool() ) { continue; } } attributeMaps.push_back( QgsAttributeMap() ); QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); int i = 0; for ( ; columnIt != mColumns.constEnd(); ++columnIt ) { int idx = mVectorLayer->fieldNameIndex(( *columnIt )->attribute() ); if ( idx != -1 ) { attributeMaps.last().insert( i, f.attributes().at( idx ) ); } else { // Lets assume it's an expression QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() ); context->lastScope()->setVariable( QString( "row_number" ), counter + 1 ); expression->prepare( context.data() ); QVariant value = expression->evaluate( context.data() ); attributeMaps.last().insert( i, value.toString() ); } i++; } ++counter; } //sort the list, starting with the last attribute QgsComposerAttributeTableCompare c; QList< QPair<int, bool> > sortColumns = sortAttributes(); for ( int i = sortColumns.size() - 1; i >= 0; --i ) { c.setSortColumn( sortColumns.at( i ).first ); c.setAscending( sortColumns.at( i ).second ); qStableSort( attributeMaps.begin(), attributeMaps.end(), c ); } adjustFrameToSize(); return true; }