void QgsMarkerLineSymbolLayerV2::renderOffsetVertexAlongLine( const QPolygonF &points, int vertex, double distance, QgsSymbolV2RenderContext& context ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); if ( distance == 0 ) { // rotate marker (if desired) if ( mRotateMarker ) { bool isRing = false; if ( points.first() == points.last() ) isRing = true; double angle = markerAngle( points, isRing, vertex ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points[vertex], context.feature(), rc, -1, context.selected() ); return; } int pointIncrement = distance > 0 ? 1 : -1; QPointF previousPoint = points[vertex]; int startPoint = distance > 0 ? qMin( vertex + 1, points.count() - 1 ) : qMax( vertex - 1, 0 ); int endPoint = distance > 0 ? points.count() - 1 : 0; double distanceLeft = qAbs( distance ); for ( int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement ) { const QPointF& pt = points[i]; if ( previousPoint == pt ) // must not be equal! continue; // create line segment MyLine l( previousPoint, pt ); if ( distanceLeft < l.length() ) { //destination point is in current segment QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft ); // rotate marker (if desired) if ( mRotateMarker ) { mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) ); } mMarker->renderPoint( markerPoint, context.feature(), rc, -1, context.selected() ); return; } distanceLeft -= l.length(); previousPoint = pt; } //didn't find point return; }
void QgsSimpleLineSymbolLayerV2::applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QPen& pen, QPen& selPen, double& offset ) { //data defined properties double scaledWidth = 0; if ( mStrokeWidthExpression ) { scaledWidth = mStrokeWidthExpression->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 if ( mStrokeColorExpression ) { pen.setColor( QgsSymbolLayerV2Utils::decodeColor( mStrokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) ); } //offset offset = mOffset; if ( mLineOffsetExpression ) { offset = mLineOffsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } //dash dot vector if ( mDashPatternExpression ) { QVector<qreal> dashVector; QStringList dashList = mDashPatternExpression->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 if ( mJoinStyleExpression ) { QString joinStyleString = mJoinStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); pen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( joinStyleString ) ); } //cap style if ( mCapStyleExpression ) { QString capStyleString = mCapStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString(); pen.setCapStyle( QgsSymbolLayerV2Utils::decodePenCapStyle( capStyleString ) ); } }
void QgsVectorFieldSymbolLayer::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context ) { if ( !mLineSymbol ) { return; } const QgsFeature* f = context.feature(); if ( !f ) { //preview QPolygonF line; line << QPointF( 0, 50 ); line << QPointF( 100, 50 ); mLineSymbol->renderPolyline( line, 0, context.renderContext() ); } double xComponent = 0; double yComponent = 0; double xVal = 0; if ( mXIndex != -1 ) { xVal = f->attributeMap()[mXIndex].toDouble(); } double yVal = 0; if ( mYIndex != -1 ) { yVal = f->attributeMap()[mYIndex].toDouble(); } switch ( mVectorFieldType ) { case Cartesian: xComponent = context.outputLineWidth( xVal ); yComponent = context.outputLineWidth( yVal ); break; case Polar: convertPolarToCartesian( xVal, yVal, xComponent, yComponent ); xComponent = context.outputLineWidth( xComponent ); yComponent = context.outputLineWidth( yComponent ); break; case Height: xComponent = 0; yComponent = context.outputLineWidth( yVal ); break; default: break; } xComponent *= mScale; yComponent *= mScale; QPolygonF line; line << point; line << QPointF( point.x() + xComponent, point.y() - yComponent ); mLineSymbol->renderPolyline( line, f, context.renderContext() ); }
void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } p->setPen( QPen( Qt::NoPen ) ); if ( context.selected() ) { QColor selColor = context.selectionColor(); // Alister - this doesn't seem to work here //if ( ! selectionIsOpaque ) // selColor.setAlphaF( context.alpha() ); p->setBrush( QBrush( selColor ) ); _renderPolygon( p, points, rings ); } if ( doubleNear( mAngle, 0.0 ) ) { p->setBrush( mBrush ); } else { QTransform t = mBrush.transform(); t.rotate( mAngle ); QBrush rotatedBrush = mBrush; rotatedBrush.setTransform( t ); p->setBrush( rotatedBrush ); } _renderPolygon( p, points, rings ); if ( mOutline ) { mOutline->renderPolyline( points, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() ); if ( rings ) { QList<QPolygonF>::const_iterator ringIt = rings->constBegin(); for ( ; ringIt != rings->constEnd(); ++ringIt ) { mOutline->renderPolyline( *ringIt, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() ); } } } }
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 QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } //size scaling by field if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { applySizeScale( context, mPen, mSelPen ); } double offset = mOffset; applyDataDefinedSymbology( context, mPen, mSelPen, offset ); p->setPen( context.selected() ? mSelPen : mPen ); // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #2 points). if ( points.size() <= 2 && ( context.renderContext().vectorSimplifyMethod().simplifyHints() & QgsVectorSimplifyMethod::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::isGeneralizableByDeviceBoundingBox( points, context.renderContext().vectorSimplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawPolyline( points ); p->setRenderHint( QPainter::Antialiasing, true ); return; } if ( qgsDoubleNear( offset, 0 ) ) { p->drawPolyline( points ); } else { double scaledOffset = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), offset, mOffsetUnit, mOffsetMapUnitScale ); QList<QPolygonF> mline = ::offsetLine( points, scaledOffset, context.feature() ? context.feature()->constGeometry()->type() : QGis::Line ); for ( int part = 0; part < mline.count(); ++part ) p->drawPolyline( mline[ part ] ); } }
void QgsEllipseSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { if ( !context.feature() || !hasDataDefinedProperty() ) { preparePath( mSymbolName, context ); } mPen.setColor( mOutlineColor ); mPen.setWidthF( mOutlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ) ); mBrush.setColor( mFillColor ); prepareExpressions( context.layer(), context.renderContext().rendererScale() ); }
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; }
QVariant QgsSymbolLayerV2::evaluateDataDefinedProperty( const QString& property, const QgsSymbolV2RenderContext& context, const QVariant& defaultVal, bool* ok ) const { if ( ok ) *ok = false; QgsDataDefined* dd = getDataDefinedProperty( property ); if ( !dd || !dd->isActive() ) return defaultVal; if ( dd->useExpression() ) { if ( dd->expression() ) { QVariant result = dd->expression()->evaluate( &context.renderContext().expressionContext() ); if ( result.isValid() ) { if ( ok ) *ok = true; return result; } else return defaultVal; } else { return defaultVal; } } else if ( context.feature() && !dd->field().isEmpty() && !mFields.isEmpty() ) { int attributeIndex = mFields.fieldNameIndex( dd->field() ); if ( attributeIndex >= 0 ) { if ( ok ) *ok = true; return context.feature()->attribute( attributeIndex ); } } return defaultVal; }
void QgsEllipseSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) { QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions if ( !context.feature() || !hasDataDefinedProperties() ) { preparePath( mSymbolName, context ); } mPen.setColor( mOutlineColor ); mPen.setStyle( mOutlineStyle ); mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) ); mBrush.setColor( mFillColor ); prepareExpressions( context ); }
double QgsSimpleLineSymbolLayerV2::dxfWidth( const QgsDxfExport& e, const QgsSymbolV2RenderContext& context ) const { double width = mWidth; QgsExpression* strokeWidthExpression = expression( "width" ); if ( strokeWidthExpression ) { width = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble() * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() ); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { width = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale ); } return width * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() ); }
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); int i, maxCount; bool isRing = false; if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } for ( ; i < maxCount; ++i ) { if ( isRing && placement == Vertex && i == points.count() - 1 ) { continue; // don't draw the last marker - it has been drawn already } // rotate marker (if desired) if ( mRotateMarker ) { double angle = markerAngle( points, isRing, i ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() ); } // restore original rotation mMarker->setAngle( origAngle ); }
void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.size() > 0 ) { // calc length qreal length = 0; QPolygonF::const_iterator it = points.constBegin(); QPointF last = *it; for ( ++it; it != points.constEnd(); ++it ) { length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) ); last = *it; } // find the segment where the central point lies it = points.constBegin(); last = *it; qreal last_at = 0, next_at = 0; QPointF next; int segment = 0; for ( ++it; it != points.constEnd(); ++it ) { next = *it; next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) ); if ( next_at >= length / 2 ) break; // we have reached the center last = *it; last_at = next_at; segment++; } // find out the central point on segment MyLine l( last, next ); // for line angle qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at ); QPointF pt = last + ( next - last ) * k; // draw the marker double origAngle = mMarker->angle(); if ( mRotateMarker ) mMarker->setAngle( origAngle + l.angle() * 180 / M_PI ); mMarker->renderPoint( pt, context.feature(), context.renderContext(), -1, context.selected() ); if ( mRotateMarker ) mMarker->setAngle( origAngle ); } }
void QgsEllipseSymbolLayerV2::calculateOffsetAndRotation( QgsSymbolV2RenderContext& context, double scaledWidth, double scaledHeight, bool& hasDataDefinedRotation, QPointF& offset, double& angle ) const { double offsetX = 0; double offsetY = 0; markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale ); offset = QPointF( offsetX, offsetY ); //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) bool ok = true; angle = mAngle + mLineAngle; bool usingDataDefinedRotation = false; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION ) ) { context.setOriginalValueVariable( angle ); angle = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle, &ok ).toDouble() + mLineAngle; usingDataDefinedRotation = ok; } hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || usingDataDefinedRotation; if ( hasDataDefinedRotation ) { // For non-point markers, "dataDefinedRotation" means following the // shape (shape-data defined). For them, "field-data defined" does // not work at all. TODO: if "field-data defined" ever gets implemented // we'll need a way to distinguish here between the two, possibly // using another flag in renderHints() const QgsFeature* f = context.feature(); if ( f ) { const QgsGeometry *g = f->constGeometry(); if ( g && g->type() == QGis::Point ) { const QgsMapToPixel& m2p = context.renderContext().mapToPixel(); angle += m2p.mapRotation(); } } } if ( angle ) offset = _rotatedOffset( offset, angle ); }
void QgsCentroidFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { Q_UNUSED( rings ); // calculate centroid double cx = 0, cy = 0; double area, sum = 0; for ( int i = points.count() - 1, j = 0; j < points.count(); i = j++ ) { const QPointF& p1 = points[i]; const QPointF& p2 = points[j]; area = p1.x() * p2.y() - p1.y() * p2.x(); sum += area; cx += ( p1.x() + p2.x() ) * area; cy += ( p1.y() + p2.y() ) * area; } sum *= 3.0; cx /= sum; cy /= sum; mMarker->renderPoint( QPointF( cx, cy ), context.feature(), context.renderContext(), -1, context.selected() ); }
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 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(); }
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 QgsDxfExport::addFeature( const QgsSymbolV2RenderContext& ctx, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ) { const QgsFeature* fet = ctx.feature(); if ( !fet ) { return; } QgsGeometry* geom = fet->geometry(); if ( geom ) { int c = 0; if ( mSymbologyExport != NoSymbology ) { c = colorFromSymbolLayer( symbolLayer, ctx ); } double width = -1; if ( mSymbologyExport != NoSymbology && symbolLayer ) { width = symbolLayer->dxfWidth( *this, ctx ); } QString lineStyleName = "CONTINUOUS"; if ( mSymbologyExport != NoSymbology ) { lineStyleName = lineStyleFromSymbolLayer( symbolLayer ); } QGis::WkbType geometryType = geom->wkbType(); //single point if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D ) { writePoint( geom->asPoint(), layer, c, fet, symbolLayer, symbol ); } //multipoint if ( geometryType == QGis::WKBMultiPoint || geometryType == QGis::WKBMultiPoint25D ) { QgsMultiPoint multiPoint = geom->asMultiPoint(); QgsMultiPoint::const_iterator it = multiPoint.constBegin(); for ( ; it != multiPoint.constEnd(); ++it ) { writePoint( *it, layer, c, fet, symbolLayer, symbol ); } } //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { writePolyline( geom->asPolyline(), layer, lineStyleName, c, width, false ); } //multiline if ( geometryType == QGis::WKBMultiLineString || geometryType == QGis::WKBMultiLineString25D ) { QgsMultiPolyline multiLine = geom->asMultiPolyline(); QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); for ( ; lIt != multiLine.constEnd(); ++lIt ) { writePolyline( *lIt, layer, lineStyleName, c, width, false ); } } //polygon if ( geometryType == QGis::WKBPolygon || geometryType == QGis::WKBPolygon25D ) { QgsPolygon polygon = geom->asPolygon(); QgsPolygon::const_iterator polyIt = polygon.constBegin(); for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings { writePolyline( *polyIt, layer, lineStyleName, c, width, true ); } } //multipolygon or polygon if ( geometryType == QGis::WKBMultiPolygon || geometryType == QGis::WKBMultiPolygon25D ) { QgsMultiPolygon mp = geom->asMultiPolygon(); QgsMultiPolygon::const_iterator mpIt = mp.constBegin(); for ( ; mpIt != mp.constEnd(); ++mpIt ) { QgsPolygon::const_iterator polyIt = mpIt->constBegin(); for ( ; polyIt != mpIt->constEnd(); ++polyIt ) { writePolyline( *polyIt, layer, lineStyleName, c, width, true ); } } } } }
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 QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); double angle; int i, maxCount; bool isRing = false; if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } for ( ; i < maxCount; ++i ) { const QPointF& pt = points[i]; // rotate marker (if desired) if ( mRotateMarker ) { if ( i == 0 ) { if ( !isRing ) { // use first segment's angle const QPointF& nextPt = points[i+1]; if ( pt == nextPt ) continue; angle = MyLine( pt, nextPt ).angle(); } else { // closed ring: use average angle between first and last segment const QPointF& prevPt = points[points.count() - 2]; const QPointF& nextPt = points[1]; if ( prevPt == pt || nextPt == pt ) continue; angle = _averageAngle( prevPt, pt, nextPt ); } } else if ( i == points.count() - 1 ) { if ( !isRing ) { // use last segment's angle const QPointF& prevPt = points[i-1]; if ( pt == prevPt ) continue; angle = MyLine( prevPt, pt ).angle(); } else { // don't draw the last marker - it has been drawn already continue; } } else { // use average angle const QPointF& prevPt = points[i-1]; const QPointF& nextPt = points[i+1]; if ( prevPt == pt || nextPt == pt ) continue; angle = _averageAngle( prevPt, pt, nextPt ); } 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 QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { Q_UNUSED( points ); if ( !context.renderContext().painter() ) { return; } context.renderContext().expressionContext().appendScope( mExpressionScope.data() ); mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT, points.size() + 1 ); mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, 1 ); if ( isCurved() ) { for ( int pIdx = 0; pIdx < points.size() - 1; pIdx += 2 ) { mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 ); _resolveDataDefined( context ); if ( points.size() - pIdx >= 3 ) { // origin point QPointF po( points.at( pIdx ) ); // middle point QPointF pm( points.at( pIdx + 1 ) ); // destination point QPointF pd( points.at( pIdx + 2 ) ); QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadSize, mComputedHeadType, mScaledOffset ); mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() ); } // straight arrow else if ( points.size() - pIdx == 2 ) { // origin point QPointF po( points.at( pIdx ) ); // destination point QPointF pd( points.at( pIdx + 1 ) ); QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadSize, mComputedHeadType, mScaledOffset ); mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() ); } } } else { // only straight arrows for ( int pIdx = 0; pIdx < points.size() - 1; pIdx++ ) { mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 ); _resolveDataDefined( context ); // origin point QPointF po( points.at( pIdx ) ); // destination point QPointF pd( points.at( pIdx + 1 ) ); QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadSize, mComputedHeadType, mScaledOffset ); mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() ); } } context.renderContext().expressionContext().popScope(); }
void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { double offset = mOffset; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET ) ) { context.setOriginalValueVariable( mOffset ); offset = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET, context, mOffset ).toDouble(); } Placement placement = mPlacement; bool ok; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_PLACEMENT ) ) { QString placementString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_PLACEMENT, context, QVariant(), &ok ).toString(); if ( ok ) { 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 if ( placementString.compare( "curvepoint", Qt::CaseInsensitive ) == 0 ) { placement = CurvePoint; } 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 { context.renderContext().setGeometry( 0 ); //always use segmented geometry with offset QList<QPolygonF> mline = ::offsetLine( points, QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), offset, mOffsetUnit, mOffsetMapUnitScale ), context.feature() ? context.feature()->constGeometry()->type() : QGis::Line ); for ( int part = 0; part < mline.count(); ++part ) { const QPolygonF &points2 = mline[ part ]; if ( placement == Interval ) renderPolylineInterval( points2, context ); else if ( placement == CentralPoint ) renderPolylineCentral( points2, context ); else renderPolylineVertex( points2, context, placement ); } } }
void QgsEllipseSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context ) { bool ok; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) ) { context.setOriginalValueVariable( mOutlineWidth ); double width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, mOutlineWidth ).toDouble(); width = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), width, mOutlineWidthUnit, mOutlineWidthMapUnitScale ); mPen.setWidthF( width ); } if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE ) ) { context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodePenStyle( mPen.style() ) ); QString styleString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE, context, QVariant(), &ok ).toString(); if ( ok ) { Qt::PenStyle style = QgsSymbolLayerV2Utils::decodePenStyle( styleString ); mPen.setStyle( style ); } } if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR ) ) { context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mBrush.color() ) ); QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, context, QVariant(), &ok ).toString(); if ( ok ) mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) ); } if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR ) ) { context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mPen.color() ) ); QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, context, QVariant(), &ok ).toString(); if ( ok ) mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) ); } double scaledWidth = mSymbolWidth; double scaledHeight = mSymbolHeight; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) || hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) || hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME ) ) { QString symbolName = mSymbolName; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME ) ) { context.setOriginalValueVariable( mSymbolName ); symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context, mSymbolName ).toString(); } preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() ); } //offset double offsetX = 0; double offsetY = 0; markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale ); 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 ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION ) ) { context.setOriginalValueVariable( mAngle ); rotation = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle ).toDouble() + mLineAngle; } else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) ) { rotation = mAngle + mLineAngle; } 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 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 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::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 QgsRenderContext& rc = context.renderContext(); double interval = mInterval; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_INTERVAL ) ) { context.setOriginalValueVariable( mInterval ); interval = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_INTERVAL, context, mInterval ).toDouble(); } if ( interval <= 0 ) { interval = 0.1; } double offsetAlongLine = mOffsetAlongLine; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) ) { context.setOriginalValueVariable( mOffsetAlongLine ); offsetAlongLine = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE, context, mOffsetAlongLine ).toDouble(); } double painterUnitInterval = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, interval, mIntervalUnit, mIntervalMapUnitScale ); lengthLeft = painterUnitInterval - QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, 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->setLineAngle( 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; } }
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; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) ) { context.setOriginalValueVariable( mOffsetAlongLine ); offsetAlongLine = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE, context, mOffsetAlongLine ).toDouble(); } if ( offsetAlongLine != 0 ) { //scale offset along line offsetAlongLine = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale ); } if ( offsetAlongLine == 0 && context.renderContext().geometry() && context.renderContext().geometry()->hasCurvedSegments() && ( placement == Vertex || placement == CurvePoint ) ) { const QgsCoordinateTransform* ct = context.renderContext().coordinateTransform(); const QgsMapToPixel& mtp = context.renderContext().mapToPixel(); QgsVertexId vId; QgsPointV2 vPoint; double x, y, z; QPointF mapPoint; while ( context.renderContext().geometry()->nextVertex( vId, vPoint ) ) { if (( placement == Vertex && vId.type == QgsVertexId::SegmentVertex ) || ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) ) { //transform x = vPoint.x(), y = vPoint.y(); z = vPoint.z(); if ( ct ) { ct->transformInPlace( x, y, z ); } mapPoint.setX( x ); mapPoint.setY( y ); mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() ); if ( mRotateMarker ) { double angle = context.renderContext().geometry()->vertexAngle( vId ); mMarker->setAngle( angle * 180 / M_PI ); } mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() ); } } return; } if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else if ( placement == Vertex ) { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } else { return; } 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 QgsPointPatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { //render 3 rows and columns in one go to easily incorporate displacement double width = context.outputPixelSize( mDistanceX ) * 2.0; double height = context.outputPixelSize( mDistanceY ) * 2.0; QImage patternImage( width, height, QImage::Format_ARGB32 ); patternImage.fill( 0 ); if ( mMarkerSymbol ) { QPainter p( &patternImage ); //marker rendering needs context for drawing on patternImage QgsRenderContext pointRenderContext; pointRenderContext.setPainter( &p ); pointRenderContext.setRasterScaleFactor( 1.0 ); pointRenderContext.setScaleFactor( context.renderContext().scaleFactor() * context.renderContext().rasterScaleFactor() ); QgsMapToPixel mtp( context.renderContext().mapToPixel().mapUnitsPerPixel() / context.renderContext().rasterScaleFactor() ); pointRenderContext.setMapToPixel( mtp ); pointRenderContext.setForceVectorOutput( false ); mMarkerSymbol->setOutputUnit( context.outputUnit() ); mMarkerSymbol->startRender( pointRenderContext ); //render corner points mMarkerSymbol->renderPoint( QPointF( 0, 0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width, 0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( 0, height ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width, height ), context.feature(), pointRenderContext ); //render displaced points double displacementPixelX = context.outputPixelSize( mDisplacementX ); double displacementPixelY = context.outputPixelSize( mDisplacementY ); mMarkerSymbol->renderPoint( QPointF( width / 2.0, -displacementPixelY ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width / 2.0 + displacementPixelX, height / 2.0 - displacementPixelY ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width + displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width / 2.0, height - displacementPixelY ), context.feature(), pointRenderContext ); mMarkerSymbol->stopRender( pointRenderContext ); } if ( !doubleNear( context.alpha(), 1.0 ) ) { QImage transparentImage = patternImage.copy(); QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); mBrush.setTextureImage( transparentImage ); } else { mBrush.setTextureImage( patternImage ); } QTransform brushTransform; brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); mBrush.setTransform( brushTransform ); if ( mOutline ) { mOutline->startRender( context.renderContext() ); } }