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_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(); }
void QgsVectorLayerFeatureIterator::prepareExpressions() { const QList<QgsExpressionFieldBuffer::ExpressionField> exps = mSource->mExpressionFieldBuffer->expressions(); for ( int i = 0; i < mSource->mFields.count(); i++ ) { if ( mSource->mFields.fieldOrigin( i ) == QgsFields::OriginExpression ) { // Only prepare if there is no subset defined or the subset contains this field if ( !( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) || mRequest.subsetOfAttributes().contains( i ) ) { int oi = mSource->mFields.fieldOriginIndex( i ); QgsExpression* exp = new QgsExpression( exps[oi].expression ); exp->prepare( mSource->mFields ); mExpressionFieldInfo.insert( i, exp ); if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs; Q_FOREACH( const QString& col, exp->referencedColumns() ) { attrs.append( mSource->mFields.fieldNameIndex( col ) ); } mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() + attrs ); } if ( exp->needsGeometry() ) { mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry ); } } }
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(); }
bool QgsVectorLayerLabelProvider::prepare( const QgsRenderContext &context, QSet<QString> &attributeNames ) { QgsPalLayerSettings &lyr = mSettings; const QgsMapSettings &mapSettings = mEngine->mapSettings(); QgsDebugMsgLevel( "PREPARE LAYER " + mLayerId, 4 ); if ( lyr.drawLabels ) { if ( lyr.fieldName.isEmpty() ) { return false; } if ( lyr.isExpression ) { QgsExpression exp( lyr.fieldName ); if ( exp.hasEvalError() ) { QgsDebugMsgLevel( "Prepare error:" + exp.evalErrorString(), 4 ); return false; } } else { // If we aren't an expression, we check to see if we can find the column. if ( mFields.lookupField( lyr.fieldName ) == -1 ) { return false; } } } lyr.mCurFields = mFields; if ( lyr.drawLabels || lyr.obstacle ) { if ( lyr.drawLabels ) { // add field indices for label's text, from expression or field if ( lyr.isExpression ) { // prepare expression for use in QgsPalLayerSettings::registerFeature() QgsExpression *exp = lyr.getLabelExpression(); exp->prepare( &context.expressionContext() ); if ( exp->hasEvalError() ) { QgsDebugMsgLevel( "Prepare error:" + exp->evalErrorString(), 4 ); } Q_FOREACH ( const QString &name, exp->referencedColumns() ) { QgsDebugMsgLevel( "REFERENCED COLUMN = " + name, 4 ); attributeNames.insert( name ); } } else { attributeNames.insert( lyr.fieldName ); } }
void QgsVectorLayerRenderer::prepareDiagrams( QgsVectorLayer* layer, QStringList& attributeNames ) { if ( !mContext.labelingEngine() ) return; if ( !layer->diagramRenderer() || !layer->diagramLayerSettings() ) return; mDiagrams = true; const QgsDiagramRendererV2* diagRenderer = layer->diagramRenderer(); const QgsDiagramLayerSettings* diagSettings = layer->diagramLayerSettings(); mContext.labelingEngine()->addDiagramLayer( layer, diagSettings ); // will make internal copy of diagSettings + initialize it //add attributes needed by the diagram renderer QList<QString> att = diagRenderer->diagramAttributes(); QList<QString>::const_iterator attIt = att.constBegin(); for ( ; attIt != att.constEnd(); ++attIt ) { QgsExpression* expression = diagRenderer->diagram()->getExpression( *attIt, &mFields ); QStringList columns = expression->referencedColumns(); QStringList::const_iterator columnsIterator = columns.constBegin(); for ( ; columnsIterator != columns.constEnd(); ++columnsIterator ) { if ( !attributeNames.contains( *columnsIterator ) ) attributeNames << *columnsIterator; } } const QgsLinearlyInterpolatedDiagramRenderer* linearlyInterpolatedDiagramRenderer = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( layer->diagramRenderer() ); if ( linearlyInterpolatedDiagramRenderer != NULL ) { if ( linearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() ) { QgsExpression* expression = diagRenderer->diagram()->getExpression( linearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), &mFields ); QStringList columns = expression->referencedColumns(); QStringList::const_iterator columnsIterator = columns.constBegin(); for ( ; columnsIterator != columns.constEnd(); ++columnsIterator ) { if ( !attributeNames.contains( *columnsIterator ) ) attributeNames << *columnsIterator; } } else { QString name = mFields.at( linearlyInterpolatedDiagramRenderer->classificationAttribute() ).name(); if ( !attributeNames.contains( name ) ) attributeNames << name; } } //and the ones needed for data defined diagram positions if ( diagSettings->xPosColumn != -1 ) attributeNames << mFields.at( diagSettings->xPosColumn ).name(); if ( diagSettings->yPosColumn != -1 ) attributeNames << mFields.at( diagSettings->yPosColumn ).name(); }
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; }
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 ); } }
QgsExpression *QgsDiagram::getExpression( const QString &expression, const QgsExpressionContext &context ) { if ( !mExpressions.contains( expression ) ) { QgsExpression *expr = new QgsExpression( expression ); expr->prepare( &context ); mExpressions[expression] = expr; } return mExpressions[expression]; }
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 ); }
QgsFeatureRequest::QgsFeatureRequest( const QgsExpression& expr ) : mFilter( FilterExpression ) , mFilterFid( -1 ) , mFilterExpression( new QgsExpression( expr.expression() ) ) , mFlags( 0 ) { }
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; }
bool QgsWFSUtils::expressionToOGCFilter( QgsExpression& exp, QDomDocument& doc ) { doc.clear(); QDomElement filterElem = doc.createElement( "Filter" ); doc.appendChild( filterElem ); QgsExpressionOGCVisitor v( doc, filterElem ); exp.acceptVisitor( v ); return v.result(); }
bool QgsWFSUtils::expressionToOGCFilter( QgsExpression& exp, QDomDocument& doc ) { doc.clear(); QDomElement filterElem = doc.createElement( "Filter" ); filterElem.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" ); doc.appendChild( filterElem ); QgsExpressionOGCVisitor v( doc, filterElem ); exp.acceptVisitor( v ); return v.result(); }
bool QgsFeatureListModel::setDisplayExpression( const QString expression ) { const QgsFields fields = mFilterModel->layer()->dataProvider()->fields(); QgsExpression* exp = new QgsExpression( expression ); exp->prepare( fields ); if ( exp->hasParserError() ) { mParserErrorString = exp->parserErrorString(); delete exp; return false; } delete mExpression; mExpression = exp; emit( dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) ) ); return true; }
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 QgsRuleBasedRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer ) { double currentScale = context.rendererScale(); // filter out rules which are not compatible with this scale mCurrentRules.clear(); for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it ) { Rule& rule = *it; if ( rule.isScaleOK( currentScale ) ) mCurrentRules.append( &rule ); } QgsFieldMap pendingFields = vlayer->pendingFields(); for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it ) { Rule* rule = *it; QgsExpression* exp = rule->filter(); if ( exp ) exp->prepare( pendingFields ); rule->symbol()->startRender( context ); } }
bool QgsFeatureListModel::setDisplayExpression( const QString& expression ) { QgsExpression* exp = new QgsExpression( expression ); QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( mFilterModel->layer() ); exp->prepare( &context ); if ( exp->hasParserError() ) { mParserErrorString = exp->parserErrorString(); delete exp; return false; } delete mExpression; mExpression = exp; emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) ); return true; }
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 test_from_ogc_filter() { QFETCH( QString, xmlText ); QFETCH( QString, dumpText ); QDomDocument doc; QVERIFY(doc.setContent(xmlText, true)); QDomElement rootElem = doc.documentElement(); QgsExpression* expr = QgsExpression::createFromOgcFilter( rootElem ); QVERIFY( expr ); qDebug("OGC XML : %s", xmlText.toAscii().data() ); qDebug("EXPR-DUMP: %s", expr->dump().toAscii().data() ); if ( expr->hasParserError() ) qDebug( "ERROR: %s ", expr->parserErrorString().toAscii().data() ); QVERIFY( !expr->hasParserError() ); QCOMPARE( dumpText, expr->dump() ); delete expr; }
QVariant QmlExpression::evaluate( const QString &expression ) const { QgsExpression exp = QgsExpression( expression ); exp.prepare( &mExpressionContext ); return exp.evaluate( &mExpressionContext ); }
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 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 ); }
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 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 ) ); }