mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Allow for exact calculation of symbol sizes with mixed layer units
Fixes #21143
This commit is contained in:
parent
427cb0b27a
commit
867e39947b
@ -223,6 +223,8 @@ Create a new MarkerLineSymbolLayerV2 from SLD
|
||||
|
||||
virtual double width() const;
|
||||
|
||||
virtual double width( const QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
virtual double estimateMaxBleed( const QgsRenderContext &context ) const;
|
||||
|
||||
|
@ -687,6 +687,10 @@ Will take ownership.
|
||||
|
||||
class QgsMarkerSymbol : QgsSymbol
|
||||
{
|
||||
%Docstring
|
||||
|
||||
A marker symbol type, for rendering Point and MultiPoint geometries.
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgssymbol.h"
|
||||
@ -700,6 +704,11 @@ This is a convenience method for easier creation of marker symbols.
|
||||
%End
|
||||
|
||||
QgsMarkerSymbol( const QgsSymbolLayerList &layers /Transfer/ = QgsSymbolLayerList() );
|
||||
%Docstring
|
||||
Constructor for QgsMarkerSymbol, with the specified list of initial symbol ``layers``.
|
||||
|
||||
Ownership of the ``layers`` are transferred to the symbol.
|
||||
%End
|
||||
|
||||
void setAngle( double symbolAngle );
|
||||
%Docstring
|
||||
@ -770,14 +779,37 @@ will be scaled to maintain their current relative size to the whole symbol size.
|
||||
|
||||
double size() const;
|
||||
%Docstring
|
||||
Returns the size for the whole symbol, which is the maximum size of
|
||||
Returns the estimated size for the whole symbol, which is the maximum size of
|
||||
all marker symbol layers in the symbol.
|
||||
|
||||
.. warning::
|
||||
|
||||
This returned value is inaccurate if the symbol consists of multiple
|
||||
symbol layers with different size units. Use the overload accepting a :py:class:`QgsRenderContext`
|
||||
argument instead for accurate sizes in this case.
|
||||
|
||||
.. seealso:: :py:func:`setSize`
|
||||
|
||||
.. seealso:: :py:func:`sizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`sizeMapUnitScale`
|
||||
%End
|
||||
|
||||
double size( const QgsRenderContext &context ) const;
|
||||
%Docstring
|
||||
Returns the symbol size, in painter units. This is the maximum size of
|
||||
all marker symbol layers in the symbol.
|
||||
|
||||
This method returns an accurate size by calculating the actual rendered
|
||||
size of each symbol layer using the provided render ``context``.
|
||||
|
||||
.. seealso:: :py:func:`setSize`
|
||||
|
||||
.. seealso:: :py:func:`sizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`sizeMapUnitScale`
|
||||
|
||||
.. versionadded:: 3.4.5
|
||||
%End
|
||||
|
||||
void setSizeUnit( QgsUnitTypes::RenderUnit unit );
|
||||
@ -890,6 +922,10 @@ and stopRender() calls, or data defined rotation and offset will not be correctl
|
||||
|
||||
class QgsLineSymbol : QgsSymbol
|
||||
{
|
||||
%Docstring
|
||||
|
||||
A line symbol type, for rendering LineString and MultiLineString geometries.
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgssymbol.h"
|
||||
@ -903,9 +939,46 @@ This is a convenience method for easier creation of line symbols.
|
||||
%End
|
||||
|
||||
QgsLineSymbol( const QgsSymbolLayerList &layers /Transfer/ = QgsSymbolLayerList() );
|
||||
%Docstring
|
||||
Constructor for QgsLineSymbol, with the specified list of initial symbol ``layers``.
|
||||
|
||||
Ownership of the ``layers`` are transferred to the symbol.
|
||||
%End
|
||||
|
||||
void setWidth( double width );
|
||||
%Docstring
|
||||
Sets the ``width`` for the whole line symbol. Individual symbol layer sizes
|
||||
will be scaled to maintain their current relative size to the whole symbol size.
|
||||
|
||||
.. seealso:: :py:func:`width`
|
||||
%End
|
||||
|
||||
double width() const;
|
||||
%Docstring
|
||||
Returns the estimated width for the whole symbol, which is the maximum width of
|
||||
all marker symbol layers in the symbol.
|
||||
|
||||
.. warning::
|
||||
|
||||
This returned value is inaccurate if the symbol consists of multiple
|
||||
symbol layers with different width units. Use the overload accepting a :py:class:`QgsRenderContext`
|
||||
argument instead for accurate sizes in this case.
|
||||
|
||||
.. seealso:: :py:func:`setWidth`
|
||||
%End
|
||||
|
||||
double width( const QgsRenderContext &context ) const;
|
||||
%Docstring
|
||||
Returns the symbol width, in painter units. This is the maximum width of
|
||||
all marker symbol layers in the symbol.
|
||||
|
||||
This method returns an accurate width by calculating the actual rendered
|
||||
width of each symbol layer using the provided render ``context``.
|
||||
|
||||
.. seealso:: :py:func:`setWidth`
|
||||
|
||||
.. versionadded:: 3.4.5
|
||||
%End
|
||||
|
||||
void setDataDefinedWidth( const QgsProperty &property );
|
||||
%Docstring
|
||||
@ -938,6 +1011,10 @@ Returns data defined width for whole symbol (including all symbol layers).
|
||||
|
||||
class QgsFillSymbol : QgsSymbol
|
||||
{
|
||||
%Docstring
|
||||
|
||||
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgssymbol.h"
|
||||
@ -951,6 +1028,11 @@ This is a convenience method for easier creation of fill symbols.
|
||||
%End
|
||||
|
||||
QgsFillSymbol( const QgsSymbolLayerList &layers /Transfer/ = QgsSymbolLayerList() );
|
||||
%Docstring
|
||||
Constructor for QgsFillSymbol, with the specified list of initial symbol ``layers``.
|
||||
|
||||
Ownership of the ``layers`` are transferred to the symbol.
|
||||
%End
|
||||
void setAngle( double angle );
|
||||
void renderPolygon( const QPolygonF &points, QList<QPolygonF> *rings, const QgsFeature *f, QgsRenderContext &context, int layer = -1, bool selected = false );
|
||||
|
||||
|
@ -840,7 +840,31 @@ class QgsLineSymbolLayer : QgsSymbolLayer
|
||||
virtual void renderPolygonStroke( const QPolygonF &points, QList<QPolygonF> *rings, QgsSymbolRenderContext &context );
|
||||
|
||||
virtual void setWidth( double width );
|
||||
|
||||
virtual double width() const;
|
||||
%Docstring
|
||||
Returns the estimated width for the line symbol layer.
|
||||
|
||||
.. warning::
|
||||
|
||||
This returned value is inaccurate if the symbol layer has sub-symbols with
|
||||
different width units. Use the overload accepting a :py:class:`QgsRenderContext`
|
||||
argument instead for accurate sizes in this case.
|
||||
|
||||
.. seealso:: :py:func:`setWidth`
|
||||
%End
|
||||
|
||||
virtual double width( const QgsRenderContext &context ) const;
|
||||
%Docstring
|
||||
Returns the line symbol layer width, in painter units.
|
||||
|
||||
This method returns an accurate width by calculating the actual rendered
|
||||
width of the symbol layer using the provided render ``context``.
|
||||
|
||||
.. seealso:: :py:func:`setWidth`
|
||||
|
||||
.. versionadded:: 3.4.5
|
||||
%End
|
||||
|
||||
double offset() const;
|
||||
void setOffset( double offset );
|
||||
|
@ -421,7 +421,7 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
|
||||
if ( QgsMarkerSymbol *markerSymbol = dynamic_cast<QgsMarkerSymbol *>( s ) )
|
||||
{
|
||||
// allow marker symbol to occupy bigger area if necessary
|
||||
double size = context.convertToPainterUnits( markerSymbol->size(), markerSymbol->sizeUnit(), markerSymbol->sizeMapUnitScale() ) / context.scaleFactor();
|
||||
double size = markerSymbol->size( context ) / context.scaleFactor();
|
||||
height = size;
|
||||
width = size;
|
||||
if ( width < settings.symbolSize().width() )
|
||||
|
@ -1113,7 +1113,8 @@ void QgsMarkerLineSymbolLayer::renderPolylineVertex( const QPolygonF &points, Qg
|
||||
|| ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) )
|
||||
{
|
||||
//transform
|
||||
x = vPoint.x(), y = vPoint.y();
|
||||
x = vPoint.x();
|
||||
y = vPoint.y();
|
||||
z = 0.0;
|
||||
if ( ct.isValid() )
|
||||
{
|
||||
@ -1618,6 +1619,11 @@ double QgsMarkerLineSymbolLayer::width() const
|
||||
return mMarker->size();
|
||||
}
|
||||
|
||||
double QgsMarkerLineSymbolLayer::width( const QgsRenderContext &context ) const
|
||||
{
|
||||
return mMarker->size( context );
|
||||
}
|
||||
|
||||
void QgsMarkerLineSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit unit )
|
||||
{
|
||||
QgsLineSymbolLayer::setOutputUnit( unit );
|
||||
@ -1675,7 +1681,7 @@ bool QgsMarkerLineSymbolLayer::hasDataDefinedProperties() const
|
||||
|
||||
double QgsMarkerLineSymbolLayer::estimateMaxBleed( const QgsRenderContext &context ) const
|
||||
{
|
||||
return context.convertToPainterUnits( ( mMarker->size() / 2.0 ), mMarker->sizeUnit(), mMarker->sizeMapUnitScale() ) +
|
||||
return ( mMarker->size( context ) / 2.0 ) +
|
||||
context.convertToPainterUnits( std::fabs( mOffset ), mOffsetUnit, mOffsetMapUnitScale );
|
||||
}
|
||||
|
||||
|
@ -234,6 +234,7 @@ class CORE_EXPORT QgsMarkerLineSymbolLayer : public QgsLineSymbolLayer
|
||||
|
||||
void setWidth( double width ) override;
|
||||
double width() const override;
|
||||
double width( const QgsRenderContext &context ) const override;
|
||||
|
||||
double estimateMaxBleed( const QgsRenderContext &context ) const override;
|
||||
|
||||
|
@ -61,12 +61,11 @@ void QgsPointDisplacementRenderer::drawGroup( QPointF centerPoint, QgsRenderCont
|
||||
//calculate max diagonal size from all symbols in group
|
||||
double diagonal = 0;
|
||||
|
||||
Q_FOREACH ( const GroupedFeature &feature, group )
|
||||
for ( const GroupedFeature &feature : group )
|
||||
{
|
||||
if ( QgsMarkerSymbol *symbol = feature.symbol() )
|
||||
{
|
||||
diagonal = std::max( diagonal, context.convertToPainterUnits( M_SQRT2 * symbol->size(),
|
||||
symbol->sizeUnit(), symbol->sizeMapUnitScale() ) );
|
||||
diagonal = std::max( diagonal, M_SQRT2 * symbol->size( context ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,8 +273,7 @@ void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRe
|
||||
}
|
||||
case ConcentricRings:
|
||||
{
|
||||
double centerDiagonal = symbolContext.renderContext().convertToPainterUnits( M_SQRT2 * mCenterSymbol->size(),
|
||||
mCenterSymbol->sizeUnit(), mCenterSymbol->sizeMapUnitScale() );
|
||||
double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
|
||||
|
||||
int pointsRemaining = nPosition;
|
||||
int ringNumber = 1;
|
||||
@ -307,8 +305,7 @@ void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolRe
|
||||
}
|
||||
case Grid:
|
||||
{
|
||||
double centerDiagonal = symbolContext.renderContext().convertToPainterUnits( M_SQRT2 * mCenterSymbol->size(),
|
||||
mCenterSymbol->sizeUnit(), mCenterSymbol->sizeMapUnitScale() );
|
||||
double centerDiagonal = mCenterSymbol->size( symbolContext.renderContext() ) * M_SQRT2;
|
||||
int pointsRemaining = nPosition;
|
||||
gridSize = std::ceil( std::sqrt( pointsRemaining ) );
|
||||
if ( pointsRemaining - std::pow( gridSize - 1, 2 ) < gridSize )
|
||||
|
@ -1312,6 +1312,21 @@ double QgsMarkerSymbol::size() const
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
double QgsMarkerSymbol::size( const QgsRenderContext &context ) const
|
||||
{
|
||||
// return size of the largest symbol
|
||||
double maxSize = 0;
|
||||
for ( QgsSymbolLayer *layer : mLayers )
|
||||
{
|
||||
if ( layer->type() != QgsSymbol::Marker )
|
||||
continue;
|
||||
const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
|
||||
const double layerSize = context.convertToPainterUnits( markerLayer->size(), markerLayer->sizeUnit(), markerLayer->sizeMapUnitScale() );
|
||||
maxSize = std::max( maxSize, layerSize );
|
||||
}
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
void QgsMarkerSymbol::setSizeUnit( QgsUnitTypes::RenderUnit unit )
|
||||
{
|
||||
Q_FOREACH ( QgsSymbolLayer *layer, mLayers )
|
||||
@ -1634,6 +1649,21 @@ double QgsLineSymbol::width() const
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
double QgsLineSymbol::width( const QgsRenderContext &context ) const
|
||||
{
|
||||
// return width of the largest symbol
|
||||
double maxWidth = 0;
|
||||
for ( QgsSymbolLayer *layer : mLayers )
|
||||
{
|
||||
if ( layer->type() != QgsSymbol::Line )
|
||||
continue;
|
||||
const QgsLineSymbolLayer *lineLayer = static_cast<const QgsLineSymbolLayer *>( layer );
|
||||
const double layerWidth = lineLayer->width( context );
|
||||
maxWidth = std::max( maxWidth, layerWidth );
|
||||
}
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
void QgsLineSymbol::setDataDefinedWidth( const QgsProperty &property )
|
||||
{
|
||||
const double symbolWidth = width();
|
||||
|
@ -726,6 +726,8 @@ class CORE_EXPORT QgsSymbolRenderContext
|
||||
/**
|
||||
* \ingroup core
|
||||
* \class QgsMarkerSymbol
|
||||
*
|
||||
* A marker symbol type, for rendering Point and MultiPoint geometries.
|
||||
*/
|
||||
class CORE_EXPORT QgsMarkerSymbol : public QgsSymbol
|
||||
{
|
||||
@ -737,6 +739,11 @@ class CORE_EXPORT QgsMarkerSymbol : public QgsSymbol
|
||||
*/
|
||||
static QgsMarkerSymbol *createSimple( const QgsStringMap &properties ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Constructor for QgsMarkerSymbol, with the specified list of initial symbol \a layers.
|
||||
*
|
||||
* Ownership of the \a layers are transferred to the symbol.
|
||||
*/
|
||||
QgsMarkerSymbol( const QgsSymbolLayerList &layers SIP_TRANSFER = QgsSymbolLayerList() );
|
||||
|
||||
/**
|
||||
@ -792,14 +799,34 @@ class CORE_EXPORT QgsMarkerSymbol : public QgsSymbol
|
||||
void setSize( double size );
|
||||
|
||||
/**
|
||||
* Returns the size for the whole symbol, which is the maximum size of
|
||||
* Returns the estimated size for the whole symbol, which is the maximum size of
|
||||
* all marker symbol layers in the symbol.
|
||||
*
|
||||
* \warning This returned value is inaccurate if the symbol consists of multiple
|
||||
* symbol layers with different size units. Use the overload accepting a QgsRenderContext
|
||||
* argument instead for accurate sizes in this case.
|
||||
*
|
||||
* \see setSize()
|
||||
* \see sizeUnit()
|
||||
* \see sizeMapUnitScale()
|
||||
*/
|
||||
double size() const;
|
||||
|
||||
/**
|
||||
* Returns the symbol size, in painter units. This is the maximum size of
|
||||
* all marker symbol layers in the symbol.
|
||||
*
|
||||
* This method returns an accurate size by calculating the actual rendered
|
||||
* size of each symbol layer using the provided render \a context.
|
||||
*
|
||||
* \see setSize()
|
||||
* \see sizeUnit()
|
||||
* \see sizeMapUnitScale()
|
||||
*
|
||||
* \since QGIS 3.4.5
|
||||
*/
|
||||
double size( const QgsRenderContext &context ) const;
|
||||
|
||||
/**
|
||||
* Sets the size units for the whole symbol (including all symbol layers).
|
||||
* \param unit size units
|
||||
@ -887,6 +914,8 @@ class CORE_EXPORT QgsMarkerSymbol : public QgsSymbol
|
||||
/**
|
||||
* \ingroup core
|
||||
* \class QgsLineSymbol
|
||||
*
|
||||
* A line symbol type, for rendering LineString and MultiLineString geometries.
|
||||
*/
|
||||
class CORE_EXPORT QgsLineSymbol : public QgsSymbol
|
||||
{
|
||||
@ -898,11 +927,46 @@ class CORE_EXPORT QgsLineSymbol : public QgsSymbol
|
||||
*/
|
||||
static QgsLineSymbol *createSimple( const QgsStringMap &properties ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Constructor for QgsLineSymbol, with the specified list of initial symbol \a layers.
|
||||
*
|
||||
* Ownership of the \a layers are transferred to the symbol.
|
||||
*/
|
||||
QgsLineSymbol( const QgsSymbolLayerList &layers SIP_TRANSFER = QgsSymbolLayerList() );
|
||||
|
||||
/**
|
||||
* Sets the \a width for the whole line symbol. Individual symbol layer sizes
|
||||
* will be scaled to maintain their current relative size to the whole symbol size.
|
||||
*
|
||||
* \see width()
|
||||
*/
|
||||
void setWidth( double width );
|
||||
|
||||
/**
|
||||
* Returns the estimated width for the whole symbol, which is the maximum width of
|
||||
* all marker symbol layers in the symbol.
|
||||
*
|
||||
* \warning This returned value is inaccurate if the symbol consists of multiple
|
||||
* symbol layers with different width units. Use the overload accepting a QgsRenderContext
|
||||
* argument instead for accurate sizes in this case.
|
||||
*
|
||||
* \see setWidth()
|
||||
*/
|
||||
double width() const;
|
||||
|
||||
/**
|
||||
* Returns the symbol width, in painter units. This is the maximum width of
|
||||
* all marker symbol layers in the symbol.
|
||||
*
|
||||
* This method returns an accurate width by calculating the actual rendered
|
||||
* width of each symbol layer using the provided render \a context.
|
||||
*
|
||||
* \see setWidth()
|
||||
*
|
||||
* \since QGIS 3.4.5
|
||||
*/
|
||||
double width( const QgsRenderContext &context ) const;
|
||||
|
||||
/**
|
||||
* Set data defined width for whole symbol (including all symbol layers).
|
||||
* \see dataDefinedWidth()
|
||||
@ -933,6 +997,8 @@ class CORE_EXPORT QgsLineSymbol : public QgsSymbol
|
||||
/**
|
||||
* \ingroup core
|
||||
* \class QgsFillSymbol
|
||||
*
|
||||
* A fill symbol type, for rendering Polygon and MultiPolygon geometries.
|
||||
*/
|
||||
class CORE_EXPORT QgsFillSymbol : public QgsSymbol
|
||||
{
|
||||
@ -944,6 +1010,11 @@ class CORE_EXPORT QgsFillSymbol : public QgsSymbol
|
||||
*/
|
||||
static QgsFillSymbol *createSimple( const QgsStringMap &properties ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Constructor for QgsFillSymbol, with the specified list of initial symbol \a layers.
|
||||
*
|
||||
* Ownership of the \a layers are transferred to the symbol.
|
||||
*/
|
||||
QgsFillSymbol( const QgsSymbolLayerList &layers SIP_TRANSFER = QgsSymbolLayerList() );
|
||||
void setAngle( double angle );
|
||||
void renderPolygon( const QPolygonF &points, QList<QPolygonF> *rings, const QgsFeature *f, QgsRenderContext &context, int layer = -1, bool selected = false );
|
||||
|
@ -656,6 +656,11 @@ void QgsLineSymbolLayer::renderPolygonStroke( const QPolygonF &points, QList<QPo
|
||||
}
|
||||
}
|
||||
|
||||
double QgsLineSymbolLayer::width( const QgsRenderContext &context ) const
|
||||
{
|
||||
return context.convertToPainterUnits( mWidth, mWidthUnit, mWidthMapUnitScale );
|
||||
}
|
||||
|
||||
double QgsLineSymbolLayer::dxfWidth( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const
|
||||
{
|
||||
Q_UNUSED( context );
|
||||
|
@ -791,8 +791,30 @@ class CORE_EXPORT QgsLineSymbolLayer : public QgsSymbolLayer
|
||||
virtual void renderPolygonStroke( const QPolygonF &points, QList<QPolygonF> *rings, QgsSymbolRenderContext &context );
|
||||
|
||||
virtual void setWidth( double width ) { mWidth = width; }
|
||||
|
||||
/**
|
||||
* Returns the estimated width for the line symbol layer.
|
||||
*
|
||||
* \warning This returned value is inaccurate if the symbol layer has sub-symbols with
|
||||
* different width units. Use the overload accepting a QgsRenderContext
|
||||
* argument instead for accurate sizes in this case.
|
||||
*
|
||||
* \see setWidth()
|
||||
*/
|
||||
virtual double width() const { return mWidth; }
|
||||
|
||||
/**
|
||||
* Returns the line symbol layer width, in painter units.
|
||||
*
|
||||
* This method returns an accurate width by calculating the actual rendered
|
||||
* width of the symbol layer using the provided render \a context.
|
||||
*
|
||||
* \see setWidth()
|
||||
*
|
||||
* \since QGIS 3.4.5
|
||||
*/
|
||||
virtual double width( const QgsRenderContext &context ) const;
|
||||
|
||||
double offset() const { return mOffset; }
|
||||
void setOffset( double offset ) { mOffset = offset; }
|
||||
|
||||
|
@ -27,7 +27,7 @@ import qgis # NOQA
|
||||
|
||||
from utilities import unitTestDataPath
|
||||
|
||||
from qgis.PyQt.QtCore import QDir, Qt
|
||||
from qgis.PyQt.QtCore import QDir, Qt, QSize
|
||||
from qgis.PyQt.QtGui import QImage, QColor, QPainter
|
||||
from qgis.PyQt.QtXml import QDomDocument
|
||||
|
||||
@ -49,7 +49,9 @@ from qgis.core import (QgsGeometry,
|
||||
QgsFontUtils,
|
||||
QgsLineSymbol,
|
||||
QgsSymbolLayer,
|
||||
QgsProperty
|
||||
QgsProperty,
|
||||
QgsRectangle,
|
||||
QgsUnitTypes
|
||||
)
|
||||
|
||||
from qgis.testing import unittest, start_app
|
||||
@ -68,6 +70,38 @@ class TestQgsMarkerLineSymbolLayer(unittest.TestCase):
|
||||
with open(report_file_path, 'a') as report_file:
|
||||
report_file.write(self.report)
|
||||
|
||||
def testWidth(self):
|
||||
ms = QgsMapSettings()
|
||||
extent = QgsRectangle(100, 200, 100, 200)
|
||||
ms.setExtent(extent)
|
||||
ms.setOutputSize(QSize(400, 400))
|
||||
context = QgsRenderContext.fromMapSettings(ms)
|
||||
context.setScaleFactor(96 / 25.4) # 96 DPI
|
||||
ms.setExtent(QgsRectangle(100, 150, 100, 150))
|
||||
ms.setOutputDpi(ms.outputDpi() * 2)
|
||||
context2 = QgsRenderContext.fromMapSettings(ms)
|
||||
context2.setScaleFactor(300 / 25.4)
|
||||
|
||||
s = QgsFillSymbol()
|
||||
s.deleteSymbolLayer(0)
|
||||
|
||||
marker_line = QgsMarkerLineSymbolLayer(True)
|
||||
marker_line.setPlacement(QgsMarkerLineSymbolLayer.FirstVertex)
|
||||
marker = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 10)
|
||||
marker.setColor(QColor(255, 0, 0))
|
||||
marker.setStrokeStyle(Qt.NoPen)
|
||||
marker_symbol = QgsMarkerSymbol()
|
||||
marker_symbol.changeSymbolLayer(0, marker)
|
||||
marker_line.setSubSymbol(marker_symbol)
|
||||
|
||||
self.assertEqual(marker_line.width(), 10)
|
||||
self.assertAlmostEqual(marker_line.width(context), 37.795275590551185, 3)
|
||||
self.assertAlmostEqual(marker_line.width(context2), 118.11023622047244, 3)
|
||||
|
||||
marker_line.subSymbol().setSizeUnit(QgsUnitTypes.RenderPixels)
|
||||
self.assertAlmostEqual(marker_line.width(context), 10.0, 3)
|
||||
self.assertAlmostEqual(marker_line.width(context2), 10.0, 3)
|
||||
|
||||
def testRingFilter(self):
|
||||
# test filtering rings during rendering
|
||||
s = QgsFillSymbol()
|
||||
|
@ -27,7 +27,7 @@ import qgis # NOQA
|
||||
|
||||
from utilities import unitTestDataPath
|
||||
|
||||
from qgis.PyQt.QtCore import QDir, Qt
|
||||
from qgis.PyQt.QtCore import QDir, Qt, QSize
|
||||
from qgis.PyQt.QtGui import QImage, QColor, QPainter
|
||||
from qgis.PyQt.QtXml import QDomDocument
|
||||
|
||||
@ -48,6 +48,7 @@ from qgis.core import (QgsGeometry,
|
||||
QgsRenderChecker,
|
||||
QgsSimpleMarkerSymbolLayer,
|
||||
QgsSimpleMarkerSymbolLayerBase,
|
||||
QgsSimpleLineSymbolLayer,
|
||||
QgsSimpleFillSymbolLayer,
|
||||
QgsUnitTypes,
|
||||
QgsWkbTypes,
|
||||
@ -509,6 +510,16 @@ class TestQgsMarkerSymbol(unittest.TestCase):
|
||||
|
||||
def testSize(self):
|
||||
# test size and setSize
|
||||
ms = QgsMapSettings()
|
||||
extent = QgsRectangle(100, 200, 100, 200)
|
||||
ms.setExtent(extent)
|
||||
ms.setOutputSize(QSize(400, 400))
|
||||
context = QgsRenderContext.fromMapSettings(ms)
|
||||
context.setScaleFactor(96 / 25.4) # 96 DPI
|
||||
ms.setExtent(QgsRectangle(100, 150, 100, 150))
|
||||
ms.setOutputDpi(ms.outputDpi() * 2)
|
||||
context2 = QgsRenderContext.fromMapSettings(ms)
|
||||
context2.setScaleFactor(300 / 25.4)
|
||||
|
||||
# create a marker symbol with a single layer
|
||||
markerSymbol = QgsMarkerSymbol()
|
||||
@ -517,9 +528,13 @@ class TestQgsMarkerSymbol(unittest.TestCase):
|
||||
QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0),
|
||||
strokeColor=QColor(0, 255, 0), size=10))
|
||||
self.assertEqual(markerSymbol.size(), 10)
|
||||
self.assertAlmostEqual(markerSymbol.size(context), 37.795275590551185, 3)
|
||||
self.assertAlmostEqual(markerSymbol.size(context2), 118.11023622047244, 3)
|
||||
markerSymbol.setSize(20)
|
||||
self.assertEqual(markerSymbol.size(), 20)
|
||||
self.assertEqual(markerSymbol.symbolLayer(0).size(), 20)
|
||||
self.assertAlmostEqual(markerSymbol.size(context), 75.59055118, 3)
|
||||
self.assertAlmostEqual(markerSymbol.size(context2), 236.2204724409449, 3)
|
||||
|
||||
# add additional layers
|
||||
markerSymbol.appendSymbolLayer(
|
||||
@ -529,6 +544,9 @@ class TestQgsMarkerSymbol(unittest.TestCase):
|
||||
QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0),
|
||||
strokeColor=QColor(0, 255, 0), size=30))
|
||||
self.assertEqual(markerSymbol.size(), 30)
|
||||
self.assertAlmostEqual(markerSymbol.size(context), 113.38582677165356, 3)
|
||||
self.assertAlmostEqual(markerSymbol.size(context2), 354.33070866141736, 3)
|
||||
|
||||
markerSymbol.setSize(3)
|
||||
self.assertEqual(markerSymbol.size(), 3)
|
||||
# layer sizes should maintain relative size
|
||||
@ -536,6 +554,17 @@ class TestQgsMarkerSymbol(unittest.TestCase):
|
||||
self.assertEqual(markerSymbol.symbolLayer(1).size(), 1)
|
||||
self.assertEqual(markerSymbol.symbolLayer(2).size(), 3)
|
||||
|
||||
# symbol layer in different size
|
||||
markerSymbol.symbolLayer(1).setSize(15)
|
||||
self.assertAlmostEqual(markerSymbol.size(context), 56.69291338582678, 3)
|
||||
self.assertAlmostEqual(markerSymbol.size(context2), 177.16535433070868, 3)
|
||||
markerSymbol.symbolLayer(1).setSizeUnit(QgsUnitTypes.RenderPixels)
|
||||
self.assertAlmostEqual(markerSymbol.size(context), 15, 3)
|
||||
self.assertAlmostEqual(markerSymbol.size(context2), 35.43307086614173, 3)
|
||||
markerSymbol.symbolLayer(1).setSize(45)
|
||||
self.assertAlmostEqual(markerSymbol.size(context), 45, 3)
|
||||
self.assertAlmostEqual(markerSymbol.size(context2), 45, 3)
|
||||
|
||||
def testAngle(self):
|
||||
# test angle and setAngle
|
||||
|
||||
@ -628,6 +657,71 @@ class TestQgsMarkerSymbol(unittest.TestCase):
|
||||
self.assertEqual(markerSymbol.symbolLayer(2).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
|
||||
|
||||
|
||||
class TestQgsLineSymbol(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.report = "<h1>Python QgsLineSymbol Tests</h1>\n"
|
||||
|
||||
def tearDown(self):
|
||||
report_file_path = "%s/qgistest.html" % QDir.tempPath()
|
||||
with open(report_file_path, 'a') as report_file:
|
||||
report_file.write(self.report)
|
||||
|
||||
def testWidth(self):
|
||||
# test width and setWidth
|
||||
ms = QgsMapSettings()
|
||||
extent = QgsRectangle(100, 200, 100, 200)
|
||||
ms.setExtent(extent)
|
||||
ms.setOutputSize(QSize(400, 400))
|
||||
context = QgsRenderContext.fromMapSettings(ms)
|
||||
context.setScaleFactor(96 / 25.4) # 96 DPI
|
||||
ms.setExtent(QgsRectangle(100, 150, 100, 150))
|
||||
ms.setOutputDpi(ms.outputDpi() * 2)
|
||||
context2 = QgsRenderContext.fromMapSettings(ms)
|
||||
context2.setScaleFactor(300 / 25.4)
|
||||
|
||||
# create a line symbol with a single layer
|
||||
line_symbol = QgsLineSymbol()
|
||||
line_symbol.deleteSymbolLayer(0)
|
||||
line_symbol.appendSymbolLayer(
|
||||
QgsSimpleLineSymbolLayer(color=QColor(255, 0, 0), width=10))
|
||||
self.assertEqual(line_symbol.width(), 10)
|
||||
self.assertAlmostEqual(line_symbol.width(context), 37.795275590551185, 3)
|
||||
self.assertAlmostEqual(line_symbol.width(context2), 118.11023622047244, 3)
|
||||
line_symbol.setWidth(20)
|
||||
self.assertEqual(line_symbol.width(), 20)
|
||||
self.assertEqual(line_symbol.symbolLayer(0).width(), 20)
|
||||
self.assertAlmostEqual(line_symbol.width(context), 75.59055118, 3)
|
||||
self.assertAlmostEqual(line_symbol.width(context2), 236.2204724409449, 3)
|
||||
|
||||
# add additional layers
|
||||
line_symbol.appendSymbolLayer(
|
||||
QgsSimpleLineSymbolLayer(color=QColor(255, 0, 0), width=10))
|
||||
line_symbol.appendSymbolLayer(
|
||||
QgsSimpleLineSymbolLayer(color=QColor(255, 0, 0), width=30))
|
||||
self.assertEqual(line_symbol.width(), 30)
|
||||
self.assertAlmostEqual(line_symbol.width(context), 113.38582677165356, 3)
|
||||
self.assertAlmostEqual(line_symbol.width(context2), 354.33070866141736, 3)
|
||||
|
||||
line_symbol.setWidth(3)
|
||||
self.assertEqual(line_symbol.width(), 3)
|
||||
# layer widths should maintain relative size
|
||||
self.assertEqual(line_symbol.symbolLayer(0).width(), 2)
|
||||
self.assertEqual(line_symbol.symbolLayer(1).width(), 1)
|
||||
self.assertEqual(line_symbol.symbolLayer(2).width(), 3)
|
||||
|
||||
# symbol layer in different size
|
||||
line_symbol.symbolLayer(1).setWidth(15)
|
||||
self.assertAlmostEqual(line_symbol.width(context), 56.69291338582678, 3)
|
||||
self.assertAlmostEqual(line_symbol.width(context2), 177.16535433070868, 3)
|
||||
line_symbol.symbolLayer(1).setWidthUnit(QgsUnitTypes.RenderPixels)
|
||||
self.assertAlmostEqual(line_symbol.width(context), 15, 3)
|
||||
self.assertAlmostEqual(line_symbol.width(context2), 35.43307086614173, 3)
|
||||
line_symbol.symbolLayer(1).setWidth(45)
|
||||
self.assertAlmostEqual(line_symbol.width(context), 45, 3)
|
||||
self.assertAlmostEqual(line_symbol.width(context2), 45, 3)
|
||||
|
||||
|
||||
class TestQgsFillSymbol(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user