Skip to content

Commit

Permalink
[FEATURE][symbology] Add offset settings for point pattern fill symbo…
Browse files Browse the repository at this point in the history
…l layer
  • Loading branch information
nirvn committed Apr 24, 2019
1 parent e0a73d3 commit 7569646
Show file tree
Hide file tree
Showing 11 changed files with 529 additions and 29 deletions.
120 changes: 120 additions & 0 deletions python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in
Expand Up @@ -1623,6 +1623,46 @@ class QgsPointPatternFillSymbolLayer: QgsImageFillSymbolLayer
double displacementY() const;
void setDisplacementY( double d );

void setOffsetX( double offset );
%Docstring
Sets the horizontal offset values for points in the pattern.

:param offset: offset value

.. seealso:: :py:func:`offsetX`

.. seealso:: :py:func:`setOffsetY`
%End

double offsetX() const;
%Docstring
Returns the horizontal offset values for points in the pattern.

.. seealso:: :py:func:`setOffsetX`

.. seealso:: :py:func:`offsetY`
%End

void setOffsetY( double offset );
%Docstring
Sets the vertical offset values for points in the pattern.

:param offset: offset value

.. seealso:: :py:func:`offsetY`

.. seealso:: :py:func:`setOffsetX`
%End

double offsetY() const;
%Docstring
Returns the vertical offset values for points in the pattern.

.. seealso:: :py:func:`setOffsetY`

.. seealso:: :py:func:`offsetX`
%End

virtual bool setSubSymbol( QgsSymbol *symbol /Transfer/ );

virtual QgsSymbol *subSymbol();
Expand Down Expand Up @@ -1719,6 +1759,86 @@ Returns the units for the vertical displacement between rows in the pattern.
void setDisplacementYMapUnitScale( const QgsMapUnitScale &scale );
const QgsMapUnitScale &displacementYMapUnitScale() const;

void setOffsetXUnit( QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the units for the horizontal offset between rows in the pattern.

:param unit: offset units

.. seealso:: :py:func:`offsetXUnit`

.. seealso:: :py:func:`setOffsetYUnit`
%End

QgsUnitTypes::RenderUnit offsetXUnit() const;
%Docstring
Returns the units for the horizontal offset for rows in the pattern.

.. seealso:: :py:func:`setOffsetXUnit`

.. seealso:: :py:func:`offsetYUnit`
%End

void setOffsetXMapUnitScale( const QgsMapUnitScale &scale );
%Docstring
Sets the unit scale for the horizontal offset for rows in the pattern.

:param scale: offset unit scale

.. seealso:: :py:func:`offsetXMapUnitScale`

.. seealso:: :py:func:`setOffsetYMapUnitScale`
%End

const QgsMapUnitScale &offsetXMapUnitScale() const;
%Docstring
Returns the unit scale for the horizontal offset for rows in the pattern.

.. seealso:: :py:func:`setOffsetXMapUnitScale`

.. seealso:: :py:func:`offsetYMapUnitScale`
%End

void setOffsetYUnit( QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the units for the vertical offset for rows in the pattern.

:param unit: offset units

.. seealso:: :py:func:`offsetYUnit`

.. seealso:: :py:func:`setOffsetXUnit`
%End

QgsUnitTypes::RenderUnit offsetYUnit() const;
%Docstring
Returns the units for the vertical offset for rows in the pattern.

.. seealso:: :py:func:`setOffsetYUnit`

.. seealso:: :py:func:`offsetXUnit`
%End

void setOffsetYMapUnitScale( const QgsMapUnitScale &scale );
%Docstring
Sets the unit scale for the vertical offset for rows in the pattern.

:param scale: offset unit scale

.. seealso:: :py:func:`offsetYMapUnitScale`

.. seealso:: :py:func:`setOffsetXMapUnitScale`
%End

const QgsMapUnitScale &offsetYMapUnitScale() const;
%Docstring
Returns the unit scale for the vertical offset between rows in the pattern.

.. seealso:: :py:func:`setOffsetYMapUnitScale`

.. seealso:: :py:func:`offsetXMapUnitScale`
%End

virtual void setOutputUnit( QgsUnitTypes::RenderUnit unit );

virtual QgsUnitTypes::RenderUnit outputUnit() const;
Expand Down
2 changes: 2 additions & 0 deletions python/core/auto_generated/symbology/qgssymbollayer.sip.in
Expand Up @@ -133,6 +133,8 @@ class QgsSymbolLayer
PropertyArrowHeadThickness,
PropertyArrowHeadType,
PropertyArrowType,
PropertyOffsetX,
PropertyOffsetY,
};

static const QgsPropertiesDefinition &propertyDefinitions();
Expand Down
97 changes: 82 additions & 15 deletions src/core/symbology/qgsfillsymbollayer.cpp
Expand Up @@ -2998,6 +2998,8 @@ QgsPointPatternFillSymbolLayer::QgsPointPatternFillSymbolLayer()
mDistanceY = 15;
mDisplacementX = 0;
mDisplacementY = 0;
mOffsetX = 0;
mOffsetY = 0;
setSubSymbol( new QgsMarkerSymbol() );
QgsImageFillSymbolLayer::setSubSymbol( nullptr ); //no stroke
}
Expand All @@ -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 );
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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" ) ) )
{
Expand Down Expand Up @@ -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" )] ) );
Expand All @@ -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;
Expand Down Expand Up @@ -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 );
}
Expand All @@ -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 )
{
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 7569646

Please sign in to comment.