@@ -2998,6 +2998,8 @@ QgsPointPatternFillSymbolLayer::QgsPointPatternFillSymbolLayer()
mDistanceY = 15 ;
mDisplacementX = 0 ;
mDisplacementY = 0 ;
mOffsetX = 0 ;
mOffsetY = 0 ;
setSubSymbol ( new QgsMarkerSymbol () );
QgsImageFillSymbolLayer::setSubSymbol ( nullptr ); // no stroke
}
@@ -3014,6 +3016,8 @@ void QgsPointPatternFillSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit uni
mDistanceYUnit = unit;
mDisplacementXUnit = unit;
mDisplacementYUnit = unit;
mOffsetXUnit = unit;
mOffsetYUnit = unit;
if ( mMarkerSymbol )
{
mMarkerSymbol ->setOutputUnit ( unit );
@@ -3024,7 +3028,7 @@ void QgsPointPatternFillSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit uni
QgsUnitTypes::RenderUnit QgsPointPatternFillSymbolLayer::outputUnit () const
{
QgsUnitTypes::RenderUnit unit = QgsImageFillSymbolLayer::outputUnit ();
if ( mDistanceXUnit != unit || mDistanceYUnit != unit || mDisplacementXUnit != unit || mDisplacementYUnit != unit )
if ( mDistanceXUnit != unit || mDistanceYUnit != unit || mDisplacementXUnit != unit || mDisplacementYUnit != unit || mOffsetXUnit != unit || mOffsetYUnit != unit )
{
return QgsUnitTypes::RenderUnknownUnit;
}
@@ -3038,14 +3042,18 @@ void QgsPointPatternFillSymbolLayer::setMapUnitScale( const QgsMapUnitScale &sca
mDistanceYMapUnitScale = scale;
mDisplacementXMapUnitScale = scale;
mDisplacementYMapUnitScale = scale;
mOffsetXMapUnitScale = scale;
mOffsetYMapUnitScale = scale;
}
QgsMapUnitScale QgsPointPatternFillSymbolLayer::mapUnitScale () const
{
if ( QgsImageFillSymbolLayer::mapUnitScale () == mDistanceXMapUnitScale &&
mDistanceXMapUnitScale == mDistanceYMapUnitScale &&
mDistanceYMapUnitScale == mDisplacementXMapUnitScale &&
mDisplacementXMapUnitScale == mDisplacementYMapUnitScale )
mDisplacementXMapUnitScale == mDisplacementYMapUnitScale &&
mDisplacementYMapUnitScale == mOffsetXMapUnitScale &&
mOffsetXMapUnitScale == mOffsetYMapUnitScale )
{
return mDistanceXMapUnitScale ;
}
@@ -3071,6 +3079,14 @@ QgsSymbolLayer *QgsPointPatternFillSymbolLayer::create( const QgsStringMap &prop
{
layer->setDisplacementY ( properties[QStringLiteral ( " displacement_y" )].toDouble () );
}
if ( properties.contains ( QStringLiteral ( " offset_x" ) ) )
{
layer->setOffsetX ( properties[QStringLiteral ( " offset_x" )].toDouble () );
}
if ( properties.contains ( QStringLiteral ( " offset_y" ) ) )
{
layer->setOffsetY ( properties[QStringLiteral ( " offset_y" )].toDouble () );
}
if ( properties.contains ( QStringLiteral ( " distance_x_unit" ) ) )
{
@@ -3104,6 +3120,23 @@ QgsSymbolLayer *QgsPointPatternFillSymbolLayer::create( const QgsStringMap &prop
{
layer->setDisplacementYMapUnitScale ( QgsSymbolLayerUtils::decodeMapUnitScale ( properties[QStringLiteral ( " displacement_y_map_unit_scale" )] ) );
}
if ( properties.contains ( QStringLiteral ( " offset_x_unit" ) ) )
{
layer->setOffsetXUnit ( QgsUnitTypes::decodeRenderUnit ( properties[QStringLiteral ( " offset_x_unit" )] ) );
}
if ( properties.contains ( QStringLiteral ( " offset_x_map_unit_scale" ) ) )
{
layer->setOffsetXMapUnitScale ( QgsSymbolLayerUtils::decodeMapUnitScale ( properties[QStringLiteral ( " offset_x_map_unit_scale" )] ) );
}
if ( properties.contains ( QStringLiteral ( " offset_y_unit" ) ) )
{
layer->setOffsetYUnit ( QgsUnitTypes::decodeRenderUnit ( properties[QStringLiteral ( " offset_y_unit" )] ) );
}
if ( properties.contains ( QStringLiteral ( " offset_y_map_unit_scale" ) ) )
{
layer->setOffsetYMapUnitScale ( QgsSymbolLayerUtils::decodeMapUnitScale ( properties[QStringLiteral ( " offset_y_map_unit_scale" )] ) );
}
if ( properties.contains ( QStringLiteral ( " outline_width_unit" ) ) )
{
layer->setStrokeWidthUnit ( QgsUnitTypes::decodeRenderUnit ( properties[QStringLiteral ( " outline_width_unit" )] ) );
@@ -3124,13 +3157,16 @@ QString QgsPointPatternFillSymbolLayer::layerType() const
}
void QgsPointPatternFillSymbolLayer::applyPattern ( const QgsSymbolRenderContext &context, QBrush &brush, double distanceX, double distanceY,
double displacementX, double displacementY )
double displacementX, double displacementY, double offsetX, double offsetY )
{
// render 3 rows and columns in one go to easily incorporate displacement
const QgsRenderContext &ctx = context.renderContext ();
double width = ctx.convertToPainterUnits ( distanceX, mDistanceXUnit , mDistanceXMapUnitScale ) * 2.0 ;
double height = ctx.convertToPainterUnits ( distanceY, mDistanceYUnit , mDisplacementYMapUnitScale ) * 2.0 ;
double widthOffset = std::fmod ( ctx.convertToPainterUnits ( offsetX, mOffsetXUnit , mOffsetXMapUnitScale ), width );
double heightOffset = std::fmod ( ctx.convertToPainterUnits ( offsetY, mOffsetYUnit , mOffsetYMapUnitScale ), height );
if ( width > 10000 || height > 10000 ) // protect symbol layer from eating too much memory
{
QImage img;
@@ -3162,20 +3198,33 @@ void QgsPointPatternFillSymbolLayer::applyPattern( const QgsSymbolRenderContext
mMarkerSymbol ->startRender ( pointRenderContext, context.fields () );
// 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 points on distance grid
for ( double currentX = -width; currentX <= width * 2.0 ; currentX += width )
{
for ( double currentY = -height; currentY <= height * 2.0 ; currentY += height )
{
mMarkerSymbol ->renderPoint ( QPointF ( currentX + widthOffset, currentY + heightOffset ), context.feature (), pointRenderContext );
}
}
// render displaced points
double displacementPixelX = ctx.convertToPainterUnits ( displacementX, mDisplacementXUnit , mDisplacementXMapUnitScale );
double displacementPixelY = ctx.convertToPainterUnits ( displacementY, mDisplacementYUnit , mDisplacementYMapUnitScale );
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 );
for ( double currentX = -width; currentX <= width * 2.0 ; currentX += width )
{
for ( double currentY = -height / 2.0 ; currentY <= height * 2.0 ; currentY += height )
{
mMarkerSymbol ->renderPoint ( QPointF ( currentX + widthOffset + displacementPixelX, currentY + heightOffset ), context.feature (), pointRenderContext );
}
}
for ( double currentX = -width / 2.0 ; currentX <= width * 2.0 ; currentX += width )
{
for ( double currentY = -height; currentY <= height * 2.0 ; currentY += height / 2.0 )
{
mMarkerSymbol ->renderPoint ( QPointF ( currentX + widthOffset, currentY + heightOffset - displacementPixelY ), context.feature (), pointRenderContext );
}
}
mMarkerSymbol ->stopRender ( pointRenderContext );
}
@@ -3196,7 +3245,7 @@ void QgsPointPatternFillSymbolLayer::applyPattern( const QgsSymbolRenderContext
void QgsPointPatternFillSymbolLayer::startRender ( QgsSymbolRenderContext &context )
{
applyPattern ( context, mBrush , mDistanceX , mDistanceY , mDisplacementX , mDisplacementY );
applyPattern ( context, mBrush , mDistanceX , mDistanceY , mDisplacementX , mDisplacementY , mOffsetX , mOffsetY );
if ( mStroke )
{
@@ -3219,14 +3268,20 @@ QgsStringMap QgsPointPatternFillSymbolLayer::properties() const
map.insert ( QStringLiteral ( " distance_y" ), QString::number ( mDistanceY ) );
map.insert ( QStringLiteral ( " displacement_x" ), QString::number ( mDisplacementX ) );
map.insert ( QStringLiteral ( " displacement_y" ), QString::number ( mDisplacementY ) );
map.insert ( QStringLiteral ( " offset_x" ), QString::number ( mOffsetX ) );
map.insert ( QStringLiteral ( " offset_y" ), QString::number ( mOffsetY ) );
map.insert ( QStringLiteral ( " distance_x_unit" ), QgsUnitTypes::encodeUnit ( mDistanceXUnit ) );
map.insert ( QStringLiteral ( " distance_y_unit" ), QgsUnitTypes::encodeUnit ( mDistanceYUnit ) );
map.insert ( QStringLiteral ( " displacement_x_unit" ), QgsUnitTypes::encodeUnit ( mDisplacementXUnit ) );
map.insert ( QStringLiteral ( " displacement_y_unit" ), QgsUnitTypes::encodeUnit ( mDisplacementYUnit ) );
map.insert ( QStringLiteral ( " offset_x_unit" ), QgsUnitTypes::encodeUnit ( mOffsetXUnit ) );
map.insert ( QStringLiteral ( " offset_y_unit" ), QgsUnitTypes::encodeUnit ( mOffsetYUnit ) );
map.insert ( QStringLiteral ( " distance_x_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mDistanceXMapUnitScale ) );
map.insert ( QStringLiteral ( " distance_y_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mDistanceYMapUnitScale ) );
map.insert ( QStringLiteral ( " displacement_x_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mDisplacementXMapUnitScale ) );
map.insert ( QStringLiteral ( " displacement_y_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mDisplacementYMapUnitScale ) );
map.insert ( QStringLiteral ( " offset_x_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mOffsetXMapUnitScale ) );
map.insert ( QStringLiteral ( " offset_y_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mOffsetYMapUnitScale ) );
map.insert ( QStringLiteral ( " outline_width_unit" ), QgsUnitTypes::encodeUnit ( mStrokeWidthUnit ) );
map.insert ( QStringLiteral ( " outline_width_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale ( mStrokeWidthMapUnitScale ) );
return map;
@@ -3338,7 +3393,19 @@ void QgsPointPatternFillSymbolLayer::applyDataDefinedSettings( QgsSymbolRenderCo
context.setOriginalValueVariable ( mDisplacementY );
displacementY = mDataDefinedProperties .valueAsDouble ( QgsSymbolLayer::PropertyDisplacementY, context.renderContext ().expressionContext (), mDisplacementY );
}
applyPattern ( context, mBrush , distanceX, distanceY, displacementX, displacementY );
double offsetX = mOffsetX ;
if ( mDataDefinedProperties .isActive ( QgsSymbolLayer::PropertyOffsetX ) )
{
context.setOriginalValueVariable ( mDisplacementX );
offsetX = mDataDefinedProperties .valueAsDouble ( QgsSymbolLayer::PropertyOffsetX, context.renderContext ().expressionContext (), mOffsetX );
}
double offsetY = mOffsetY ;
if ( mDataDefinedProperties .isActive ( QgsSymbolLayer::PropertyOffsetY ) )
{
context.setOriginalValueVariable ( mDisplacementY );
offsetY = mDataDefinedProperties .valueAsDouble ( QgsSymbolLayer::PropertyOffsetY, context.renderContext ().expressionContext (), mOffsetY );
}
applyPattern ( context, mBrush , distanceX, distanceY, displacementX, displacementY, offsetX, offsetY );
}
double QgsPointPatternFillSymbolLayer::estimateMaxBleed ( const QgsRenderContext & ) const