mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -04:00
initial support for mesh labeling
This commit is contained in:
parent
452c344b1e
commit
9ded559386
@ -877,6 +877,57 @@ Returns the edges count of the mesh frame
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
bool labelsEnabled() const;
|
||||
%Docstring
|
||||
Returns whether the layer contains labels which are enabled and should be drawn.
|
||||
|
||||
:return: ``True`` if layer contains enabled labels
|
||||
|
||||
.. seealso:: :py:func:`setLabelsEnabled`
|
||||
|
||||
.. seealso:: :py:func:`labeling`
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
void setLabelsEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether labels should be ``enabled`` for the layer.
|
||||
|
||||
.. note::
|
||||
|
||||
Labels will only be rendered if :py:func:`~QgsMeshLayer.labelsEnabled` is ``True`` and a labeling
|
||||
object is returned by :py:func:`~QgsMeshLayer.labeling`.
|
||||
|
||||
.. seealso:: :py:func:`labelsEnabled`
|
||||
|
||||
.. seealso:: :py:func:`labeling`
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
|
||||
QgsAbstractMeshLayerLabeling *labeling();
|
||||
%Docstring
|
||||
Access to labeling configuration. May be ``None`` if labeling is not used.
|
||||
|
||||
.. note::
|
||||
|
||||
Labels will only be rendered if :py:func:`~QgsMeshLayer.labelsEnabled` returns ``True``.
|
||||
|
||||
.. seealso:: :py:func:`labelsEnabled`
|
||||
|
||||
.. versionadded:: 3.26
|
||||
%End
|
||||
|
||||
void setLabeling( QgsAbstractMeshLayerLabeling *labeling /Transfer/ );
|
||||
%Docstring
|
||||
Sets labeling configuration. Takes ownership of the object.
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void setTransformContext( const QgsCoordinateTransformContext &transformContext );
|
||||
|
172
python/core/auto_generated/mesh/qgsmeshlayerlabeling.sip.in
Normal file
172
python/core/auto_generated/mesh/qgsmeshlayerlabeling.sip.in
Normal file
@ -0,0 +1,172 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/mesh/qgsmeshlayerlabeling.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAbstractMeshLayerLabeling
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
Abstract base class - its implementations define different approaches to the labeling of a mesh layer.
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsmeshlayerlabeling.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsAbstractMeshLayerLabeling();
|
||||
%Docstring
|
||||
Default constructor
|
||||
%End
|
||||
virtual ~QgsAbstractMeshLayerLabeling();
|
||||
|
||||
virtual QString type() const = 0;
|
||||
%Docstring
|
||||
Unique type string of the labeling configuration implementation
|
||||
%End
|
||||
|
||||
virtual QgsAbstractMeshLayerLabeling *clone() const = 0 /Factory/;
|
||||
%Docstring
|
||||
Returns a new copy of the object
|
||||
%End
|
||||
|
||||
|
||||
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const = 0;
|
||||
%Docstring
|
||||
Returns labeling configuration as XML element
|
||||
%End
|
||||
|
||||
virtual QStringList subProviders() const;
|
||||
%Docstring
|
||||
Gets list of sub-providers within the layer's labeling.
|
||||
%End
|
||||
|
||||
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const = 0;
|
||||
%Docstring
|
||||
Gets associated label settings. In case of multiple sub-providers with different settings,
|
||||
they are identified by their ID.
|
||||
%End
|
||||
|
||||
virtual void setSettings( QgsPalLayerSettings *settings /Transfer/, const QString &providerId = QString() ) = 0;
|
||||
%Docstring
|
||||
Set pal settings for a specific provider (takes ownership).
|
||||
|
||||
:param settings: Pal layer settings
|
||||
:param providerId: The id of the provider
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
virtual bool requiresAdvancedEffects() const = 0;
|
||||
%Docstring
|
||||
Returns ``True`` if drawing labels requires advanced effects like composition
|
||||
modes, which could prevent it being used as an isolated cached image
|
||||
or exported to a vector format.
|
||||
%End
|
||||
|
||||
virtual void multiplyOpacity( double opacityFactor );
|
||||
%Docstring
|
||||
Multiply opacity by ``opacityFactor``.
|
||||
|
||||
This method multiplies the opacity of the labeling elements (text, shadow, buffer etc.)
|
||||
by ``opacity`` effectively changing the opacity of the whole labeling elements.
|
||||
|
||||
.. versionadded:: 3.32
|
||||
%End
|
||||
|
||||
|
||||
static QgsAbstractMeshLayerLabeling *create( const QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
|
||||
%Docstring
|
||||
Try to create instance of an implementation based on the XML data
|
||||
%End
|
||||
|
||||
virtual void toSld( QDomNode &parent, const QVariantMap &props ) const;
|
||||
%Docstring
|
||||
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings
|
||||
%End
|
||||
|
||||
virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const;
|
||||
%Docstring
|
||||
Accepts the specified symbology ``visitor``, causing it to visit all symbols associated
|
||||
with the labeling.
|
||||
|
||||
Returns ``True`` if the visitor should continue visiting other objects, or ``False`` if visiting
|
||||
should be canceled.
|
||||
%End
|
||||
|
||||
static QgsPalLayerSettings defaultSettingsForLayer( const QgsMeshLayer *layer );
|
||||
%Docstring
|
||||
Returns the default layer settings to use for the specified mesh ``layer``.
|
||||
%End
|
||||
|
||||
private:
|
||||
QgsAbstractMeshLayerLabeling( const QgsAbstractMeshLayerLabeling &rhs );
|
||||
};
|
||||
|
||||
class QgsMeshLayerSimpleLabeling : QgsAbstractMeshLayerLabeling
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
Basic implementation of the labeling interface for mesh layer.
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsmeshlayerlabeling.h"
|
||||
%End
|
||||
public:
|
||||
explicit QgsMeshLayerSimpleLabeling( const QgsPalLayerSettings &settings );
|
||||
%Docstring
|
||||
Constructs simple labeling configuration with given initial settings
|
||||
%End
|
||||
|
||||
virtual QString type() const;
|
||||
|
||||
virtual QgsMeshLayerSimpleLabeling *clone() const /Factory/;
|
||||
|
||||
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const;
|
||||
|
||||
virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const;
|
||||
|
||||
|
||||
virtual void setSettings( QgsPalLayerSettings *settings /Transfer/, const QString &providerId = QString() );
|
||||
|
||||
%Docstring
|
||||
Set pal settings (takes ownership).
|
||||
|
||||
:param settings: Pal layer settings
|
||||
:param providerId: Unused parameter
|
||||
%End
|
||||
|
||||
virtual bool requiresAdvancedEffects() const;
|
||||
|
||||
virtual void multiplyOpacity( double opacityFactor );
|
||||
|
||||
static QgsMeshLayerSimpleLabeling *create( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
%Docstring
|
||||
Create the instance from a DOM element with saved configuration
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/mesh/qgsmeshlayerlabeling.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -477,6 +477,7 @@
|
||||
%Include auto_generated/mesh/qgsmeshlayer.sip
|
||||
%Include auto_generated/mesh/qgsmeshlayerelevationproperties.sip
|
||||
%Include auto_generated/mesh/qgsmeshlayerinterpolator.sip
|
||||
%Include auto_generated/mesh/qgsmeshlayerlabeling.sip
|
||||
%Include auto_generated/mesh/qgsmeshlayertemporalproperties.sip
|
||||
%Include auto_generated/mesh/qgsmeshrenderersettings.sip
|
||||
%Include auto_generated/mesh/qgsmeshspatialindex.sip
|
||||
|
24
resources/function_help/json/mesh_contour
Normal file
24
resources/function_help/json/mesh_contour
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "mesh_contour",
|
||||
"type": "function",
|
||||
"groups": ["Meshes"],
|
||||
"description": "Returns the mesh scalar value at a given point for a dataset group used for contour rendering.",
|
||||
"arguments": [{
|
||||
"arg": "point",
|
||||
"description": "point geometry (for multipart geometries having more than one part, a first part will be used)."
|
||||
}, {
|
||||
"arg": "timestamp",
|
||||
"description": "timestamp (defaults to current time)."
|
||||
}, {
|
||||
"arg": "layer",
|
||||
"description": "mesh layer (defaults to current layer)."
|
||||
}],
|
||||
"examples": [{
|
||||
"expression": "mesh_contour(make_point(1,1))",
|
||||
"returns": "2.5"
|
||||
}, {
|
||||
"expression": "mesh_contour(make_point(1,1), make_datetime(2020,5,4,13,45,30.5))",
|
||||
"returns": "2.5"
|
||||
}],
|
||||
"tags": ["mesh", "contour", "point"]
|
||||
}
|
27
resources/function_help/json/mesh_data
Normal file
27
resources/function_help/json/mesh_data
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "mesh_data",
|
||||
"type": "function",
|
||||
"groups": ["Meshes"],
|
||||
"description": "Returns the mesh value at a given point for a given dataset group",
|
||||
"arguments": [{
|
||||
"arg": "point",
|
||||
"description": "point geometry (for multipart geometries having more than one part, a first part will be used)."
|
||||
}, {
|
||||
"arg": "dataset_group",
|
||||
"description": "name of the mesh dataset group."
|
||||
}, {
|
||||
"arg": "timestamp",
|
||||
"description": "timestamp (defaults to current time)."
|
||||
}, {
|
||||
"arg": "layer",
|
||||
"description": "mesh layer (defaults to current layer)."
|
||||
}],
|
||||
"examples": [{
|
||||
"expression": "mesh_data(make_point(1,1), 'Bed Elevation')",
|
||||
"returns": "2.5"
|
||||
}, {
|
||||
"expression": "mesh_contour(make_point(1,1), 'Bed Elevation' make_datetime(2020,5,4,13,45,30.5))",
|
||||
"returns": "2.5"
|
||||
}],
|
||||
"tags": ["mesh", "dataset", "point"]
|
||||
}
|
@ -795,6 +795,8 @@ set(QGIS_CORE_SRCS
|
||||
mesh/qgstopologicalmesh.cpp
|
||||
mesh/qgsmeshadvancedediting.cpp
|
||||
mesh/qgsmeshforcebypolylines.cpp
|
||||
mesh/qgsmeshlayerlabeling.cpp
|
||||
mesh/qgsmeshlayerlabelprovider.cpp
|
||||
|
||||
pointcloud/qgspointcloudattribute.cpp
|
||||
pointcloud/qgspointcloudattributebyramprenderer.cpp
|
||||
@ -1618,6 +1620,8 @@ set(QGIS_CORE_HDRS
|
||||
mesh/qgstopologicalmesh.h
|
||||
mesh/qgsmeshadvancedediting.h
|
||||
mesh/qgsmeshforcebypolylines.h
|
||||
mesh/qgsmeshlayerlabeling.h
|
||||
mesh/qgsmeshlayerlabelprovider.h
|
||||
|
||||
pal/costcalculator.h
|
||||
pal/feature.h
|
||||
|
@ -64,6 +64,8 @@
|
||||
#include "qgsunittypes.h"
|
||||
#include "qgsspatialindex.h"
|
||||
#include "qgscolorrampimpl.h"
|
||||
#include "qgsmeshlayer.h"
|
||||
#include "qgsmeshdataset.h"
|
||||
|
||||
#include <QMimeDatabase>
|
||||
#include <QProcessEnvironment>
|
||||
@ -1865,6 +1867,173 @@ static QVariant fcnRasterAttributes( const QVariantList &values, const QgsExpres
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnMeshContour( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
|
||||
QDateTime datetime;
|
||||
if ( values.size() < 2 || QgsVariantUtils::isNull( values.at( 1 ) ) )
|
||||
{
|
||||
datetime = QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
else
|
||||
{
|
||||
datetime = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
|
||||
}
|
||||
|
||||
QVariant layer;
|
||||
if ( values.size() < 3 || QgsVariantUtils::isNull( values.at( 2 ) ) )
|
||||
{
|
||||
layer = context->variable( QStringLiteral( "layer" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
layer = values.at( 2 );
|
||||
}
|
||||
|
||||
bool foundLayer = false;
|
||||
const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [geom, parent]( QgsMapLayer * mapLayer ) -> QVariant
|
||||
{
|
||||
QgsMeshLayer *layer = qobject_cast< QgsMeshLayer * >( mapLayer );
|
||||
if ( !layer )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if ( geom.isNull() || geom.type() != Qgis::GeometryType::Point )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `mesh_contour` requires a valid point geometry." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsPointXY point = geom.asPoint();
|
||||
if ( geom.isMultipart() )
|
||||
{
|
||||
QgsMultiPointXY multiPoint = geom.asMultiPoint();
|
||||
if ( multiPoint.count() == 1 )
|
||||
{
|
||||
point = multiPoint[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QgsMeshDatasetIndex index = layer->staticScalarDatasetIndex();
|
||||
if ( !index.isValid() )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
const QgsMeshDatasetValue scalarValue = layer->datasetValue( index, point );
|
||||
return scalarValue.scalar();
|
||||
}, foundLayer );
|
||||
|
||||
|
||||
if ( !foundLayer )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnMeshData( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
|
||||
QString datasetGroupName = values.at( 1 ).toString();
|
||||
if ( datasetGroupName.isEmpty() )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Mesh dataset group name can not be empty." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QDateTime datetime;
|
||||
if ( values.size() < 3 || QgsVariantUtils::isNull( values.at( 2 ) ) )
|
||||
{
|
||||
datetime = QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
else
|
||||
{
|
||||
datetime = QgsExpressionUtils::getDateTimeValue( values.at( 2 ), parent );
|
||||
}
|
||||
|
||||
QVariant layer;
|
||||
if ( values.size() < 4 || QgsVariantUtils::isNull( values.at( 3 ) ) )
|
||||
{
|
||||
layer = context->variable( QStringLiteral( "layer" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
layer = values.at( 3 );
|
||||
}
|
||||
|
||||
bool foundLayer = false;
|
||||
const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [geom, datasetGroupName, parent]( QgsMapLayer * mapLayer ) -> QVariant
|
||||
{
|
||||
QgsMeshLayer *layer = qobject_cast< QgsMeshLayer * >( mapLayer );
|
||||
if ( !layer )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if ( geom.isNull() || geom.type() != Qgis::GeometryType::Point )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `mesh_data` requires a valid point geometry." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsPointXY point = geom.asPoint();
|
||||
if ( geom.isMultipart() )
|
||||
{
|
||||
QgsMultiPointXY multiPoint = geom.asMultiPoint();
|
||||
if ( multiPoint.count() == 1 )
|
||||
{
|
||||
point = multiPoint[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QgsMeshDatasetGroupTreeItem *root = layer->datasetGroupTreeRootItem();
|
||||
QList<QgsMeshDatasetIndex> datasetIndexList;
|
||||
const QList<int> allGroup = layer->enabledDatasetGroupsIndexes();
|
||||
for ( int groupIndex : allGroup )
|
||||
{
|
||||
QgsMeshDatasetGroupTreeItem *group = root->childFromDatasetGroupIndex( groupIndex );
|
||||
if ( group->name() == datasetGroupName )
|
||||
{
|
||||
datasetIndexList.append( QgsMeshDatasetIndex( groupIndex, 0 ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( datasetIndexList.size() == 0 )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Dataset group '%1' not found." ).arg( datasetGroupName ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const QgsMeshDatasetValue scalarValue = layer->datasetValue( datasetIndexList.at( 0 ), point );
|
||||
return scalarValue.scalar();
|
||||
}, foundLayer );
|
||||
|
||||
|
||||
if ( !foundLayer )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnFeature( const QVariantList &, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
if ( !context )
|
||||
@ -9195,6 +9364,10 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_value" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "band" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ), fcnRasterValue, QStringLiteral( "Rasters" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_attributes" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "band" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ), fcnRasterAttributes, QStringLiteral( "Rasters" ) )
|
||||
|
||||
// mesh
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "mesh_contour" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "point" ), false ) << QgsExpressionFunction::Parameter( QStringLiteral( "timestamp" ), true ) << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ), true ), fcnMeshContour, QStringLiteral( "Meshes" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "mesh_data" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "point" ), false ) << QgsExpressionFunction::Parameter( QStringLiteral( "dataset_group" ), false ) << QgsExpressionFunction::Parameter( QStringLiteral( "timestamp" ), true ) << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ), true ), fcnMeshData, QStringLiteral( "Meshes" ) )
|
||||
|
||||
// functions for arrays
|
||||
<< new QgsArrayForeachExpressionFunction()
|
||||
<< new QgsArrayFilterExpressionFunction()
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "qgsthreadingutils.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsruntimeprofiler.h"
|
||||
#include "qgsmeshlayerlabeling.h"
|
||||
|
||||
QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
|
||||
const QString &baseName,
|
||||
@ -106,6 +107,7 @@ bool QgsMeshLayer::hasSimplifiedMeshes() const
|
||||
|
||||
QgsMeshLayer::~QgsMeshLayer()
|
||||
{
|
||||
delete mLabeling;
|
||||
delete mDataProvider;
|
||||
}
|
||||
|
||||
@ -1773,6 +1775,16 @@ bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &e
|
||||
blendModeElement.appendChild( blendModeText );
|
||||
node.appendChild( blendModeElement );
|
||||
|
||||
if ( categories.testFlag( Labeling ) )
|
||||
{
|
||||
if ( mLabeling )
|
||||
{
|
||||
QDomElement labelingElement = mLabeling->save( doc, context );
|
||||
elem.appendChild( labelingElement );
|
||||
}
|
||||
elem.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
}
|
||||
|
||||
// add the layer opacity
|
||||
if ( categories.testFlag( Rendering ) )
|
||||
{
|
||||
@ -2148,3 +2160,28 @@ QgsMapLayerElevationProperties *QgsMeshLayer::elevationProperties()
|
||||
|
||||
return mElevationProperties;
|
||||
}
|
||||
|
||||
bool QgsMeshLayer::labelsEnabled() const
|
||||
{
|
||||
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
|
||||
|
||||
return mLabelsEnabled && static_cast< bool >( mLabeling );
|
||||
}
|
||||
|
||||
void QgsMeshLayer::setLabelsEnabled( bool enabled )
|
||||
{
|
||||
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
|
||||
|
||||
mLabelsEnabled = enabled;
|
||||
}
|
||||
|
||||
void QgsMeshLayer::setLabeling( QgsAbstractMeshLayerLabeling *labeling )
|
||||
{
|
||||
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
|
||||
|
||||
if ( mLabeling == labeling )
|
||||
return;
|
||||
|
||||
delete mLabeling;
|
||||
mLabeling = labeling;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ class QgsMeshDatasetGroupStore;
|
||||
class QgsMeshEditor;
|
||||
class QgsMeshEditingError;
|
||||
class QgsMeshLayerElevationProperties;
|
||||
class QgsAbstractMeshLayerLabeling;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
@ -881,6 +882,53 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer, public QgsAbstractProfileSo
|
||||
*/
|
||||
int meshEdgeCount() const;
|
||||
|
||||
/**
|
||||
* Returns whether the layer contains labels which are enabled and should be drawn.
|
||||
* \returns TRUE if layer contains enabled labels
|
||||
*
|
||||
* \see setLabelsEnabled()
|
||||
* \see labeling()
|
||||
* \since QGIS 3.36
|
||||
*/
|
||||
bool labelsEnabled() const;
|
||||
|
||||
/**
|
||||
* Sets whether labels should be \a enabled for the layer.
|
||||
*
|
||||
* \note Labels will only be rendered if labelsEnabled() is TRUE and a labeling
|
||||
* object is returned by labeling().
|
||||
*
|
||||
* \see labelsEnabled()
|
||||
* \see labeling()
|
||||
* \since QGIS 3.36
|
||||
*/
|
||||
void setLabelsEnabled( bool enabled );
|
||||
|
||||
/**
|
||||
* Access to const labeling configuration. May be NULLPTR if labeling is not used.
|
||||
* \note Labels will only be rendered if labelsEnabled() returns TRUE.
|
||||
*
|
||||
* \see labelsEnabled()
|
||||
* \see setLabelsEnabled()
|
||||
* \since QGIS 3.36
|
||||
*/
|
||||
const QgsAbstractMeshLayerLabeling *labeling() const SIP_SKIP { return mLabeling; }
|
||||
|
||||
/**
|
||||
* Access to labeling configuration. May be NULLPTR if labeling is not used.
|
||||
* \note Labels will only be rendered if labelsEnabled() returns TRUE.
|
||||
* \see labelsEnabled()
|
||||
* \since QGIS 3.26
|
||||
*/
|
||||
QgsAbstractMeshLayerLabeling *labeling() { return mLabeling; }
|
||||
|
||||
/**
|
||||
* Sets labeling configuration. Takes ownership of the object.
|
||||
* \since QGIS 3.36
|
||||
*/
|
||||
void setLabeling( QgsAbstractMeshLayerLabeling *labeling SIP_TRANSFER );
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@ -991,6 +1039,12 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer, public QgsAbstractProfileSo
|
||||
|
||||
QgsMeshEditor *mMeshEditor = nullptr;
|
||||
|
||||
//! True if labels are enabled
|
||||
bool mLabelsEnabled = false;
|
||||
|
||||
//! Labeling configuration
|
||||
QgsAbstractMeshLayerLabeling *mLabeling = nullptr;
|
||||
|
||||
int closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const;
|
||||
|
||||
//! Returns the exact position in map coordinates of the closest vertex in the search area
|
||||
|
132
src/core/mesh/qgsmeshlayerlabeling.cpp
Normal file
132
src/core/mesh/qgsmeshlayerlabeling.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/***************************************************************************
|
||||
qgsmeshlayerlabeling.cpp
|
||||
---------------------
|
||||
begin : November 2023
|
||||
copyright : (C) 2023 by LutraConsulting
|
||||
email : info at lutraconsulting dot co dot uk
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsmeshlayerlabeling.h"
|
||||
|
||||
#include "qgspallabeling.h"
|
||||
#include "qgsmeshlayer.h"
|
||||
#include "qgis.h"
|
||||
#include "qgsstyleentityvisitor.h"
|
||||
#include "qgsmeshlayerlabelprovider.h"
|
||||
|
||||
QgsAbstractMeshLayerLabeling *QgsAbstractMeshLayerLabeling::create( const QDomElement &element, const QgsReadWriteContext &context )
|
||||
{
|
||||
const QString type = element.attribute( QStringLiteral( "type" ) );
|
||||
if ( type == QLatin1String( "simple" ) )
|
||||
{
|
||||
return QgsMeshLayerSimpleLabeling::create( element, context );
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsAbstractMeshLayerLabeling::accept( QgsStyleEntityVisitorInterface * ) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsPalLayerSettings QgsAbstractMeshLayerLabeling::defaultSettingsForLayer( const QgsMeshLayer *layer )
|
||||
{
|
||||
QgsPalLayerSettings settings;
|
||||
settings.setFormat( QgsStyle::defaultTextFormatForProject( layer->project() ) );
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
|
||||
|
||||
QgsMeshLayerSimpleLabeling::QgsMeshLayerSimpleLabeling( const QgsPalLayerSettings &settings )
|
||||
: mSettings( new QgsPalLayerSettings( settings ) )
|
||||
{
|
||||
}
|
||||
|
||||
QString QgsMeshLayerSimpleLabeling::type() const
|
||||
{
|
||||
return QStringLiteral( "simple" );
|
||||
}
|
||||
|
||||
QgsMeshLayerSimpleLabeling *QgsMeshLayerSimpleLabeling::clone() const
|
||||
{
|
||||
return new QgsMeshLayerSimpleLabeling( *mSettings );
|
||||
}
|
||||
|
||||
QgsMeshLayerLabelProvider *QgsMeshLayerSimpleLabeling::provider( QgsMeshLayer *layer ) const
|
||||
{
|
||||
return new QgsMeshLayerLabelProvider( layer, QString(), mSettings.get() );
|
||||
}
|
||||
|
||||
QDomElement QgsMeshLayerSimpleLabeling::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
QDomElement elem = doc.createElement( QStringLiteral( "labeling" ) );
|
||||
elem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "simple" ) );
|
||||
elem.appendChild( mSettings->writeXml( doc, context ) );
|
||||
return elem;
|
||||
}
|
||||
|
||||
QgsPalLayerSettings QgsMeshLayerSimpleLabeling::settings( const QString &providerId ) const
|
||||
{
|
||||
Q_UNUSED( providerId )
|
||||
return *mSettings;
|
||||
}
|
||||
|
||||
bool QgsMeshLayerSimpleLabeling::accept( QgsStyleEntityVisitorInterface *visitor ) const
|
||||
{
|
||||
if ( mSettings )
|
||||
{
|
||||
QgsStyleLabelSettingsEntity entity( *mSettings );
|
||||
if ( !visitor->visit( &entity ) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsMeshLayerSimpleLabeling::requiresAdvancedEffects() const
|
||||
{
|
||||
return mSettings->containsAdvancedEffects();
|
||||
}
|
||||
|
||||
QgsMeshLayerSimpleLabeling *QgsMeshLayerSimpleLabeling::create( const QDomElement &element, const QgsReadWriteContext &context )
|
||||
{
|
||||
const QDomElement settingsElem = element.firstChildElement( QStringLiteral( "settings" ) );
|
||||
if ( !settingsElem.isNull() )
|
||||
{
|
||||
QgsPalLayerSettings settings;
|
||||
settings.readXml( settingsElem, context );
|
||||
return new QgsMeshLayerSimpleLabeling( settings );
|
||||
}
|
||||
|
||||
return new QgsMeshLayerSimpleLabeling( QgsPalLayerSettings() );
|
||||
}
|
||||
|
||||
void QgsMeshLayerSimpleLabeling::multiplyOpacity( double opacityFactor )
|
||||
{
|
||||
QgsTextFormat format { mSettings->format() };
|
||||
format.multiplyOpacity( opacityFactor );
|
||||
mSettings->setFormat( format );
|
||||
}
|
||||
|
||||
void QgsMeshLayerSimpleLabeling::setSettings( QgsPalLayerSettings *settings, const QString &providerId )
|
||||
{
|
||||
Q_UNUSED( providerId )
|
||||
|
||||
if ( mSettings.get() == settings )
|
||||
return;
|
||||
|
||||
mSettings.reset( settings );
|
||||
}
|
180
src/core/mesh/qgsmeshlayerlabeling.h
Normal file
180
src/core/mesh/qgsmeshlayerlabeling.h
Normal file
@ -0,0 +1,180 @@
|
||||
/***************************************************************************
|
||||
qgsmeshlayerlabeling.h
|
||||
---------------------
|
||||
begin : November 2023
|
||||
copyright : (C) 2023 by LutraConsulting
|
||||
email : info at lutraconsulting dot co dot uk
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSMESHLAYERLABELING_H
|
||||
#define QGSMESHLAYERLABELING_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDomNode>
|
||||
|
||||
#include "qgis.h"
|
||||
|
||||
class QDomDocument;
|
||||
class QDomElement;
|
||||
|
||||
class QgsPalLayerSettings;
|
||||
class QgsReadWriteContext;
|
||||
class QgsMeshLayer;
|
||||
class QgsMeshLayerLabelProvider;
|
||||
class QgsStyleEntityVisitorInterface;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \brief Abstract base class - its implementations define different approaches to the labeling of a mesh layer.
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
class CORE_EXPORT QgsAbstractMeshLayerLabeling
|
||||
{
|
||||
public:
|
||||
|
||||
//! Default constructor
|
||||
QgsAbstractMeshLayerLabeling() = default;
|
||||
virtual ~QgsAbstractMeshLayerLabeling() = default;
|
||||
|
||||
//! Unique type string of the labeling configuration implementation
|
||||
virtual QString type() const = 0;
|
||||
|
||||
//! Returns a new copy of the object
|
||||
virtual QgsAbstractMeshLayerLabeling *clone() const = 0 SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Factory for label provider implementation
|
||||
* \note not available in Python bindings
|
||||
*/
|
||||
virtual QgsMeshLayerLabelProvider *provider( QgsMeshLayer *layer ) const SIP_SKIP { Q_UNUSED( layer ) return nullptr; }
|
||||
|
||||
//! Returns labeling configuration as XML element
|
||||
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const = 0;
|
||||
|
||||
//! Gets list of sub-providers within the layer's labeling.
|
||||
virtual QStringList subProviders() const { return QStringList( QString() ); }
|
||||
|
||||
/**
|
||||
* Gets associated label settings. In case of multiple sub-providers with different settings,
|
||||
* they are identified by their ID.
|
||||
*/
|
||||
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const = 0;
|
||||
|
||||
/**
|
||||
* Set pal settings for a specific provider (takes ownership).
|
||||
*
|
||||
* \param settings Pal layer settings
|
||||
* \param providerId The id of the provider
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
virtual void setSettings( QgsPalLayerSettings *settings SIP_TRANSFER, const QString &providerId = QString() ) = 0;
|
||||
|
||||
/**
|
||||
* Returns TRUE if drawing labels requires advanced effects like composition
|
||||
* modes, which could prevent it being used as an isolated cached image
|
||||
* or exported to a vector format.
|
||||
*/
|
||||
virtual bool requiresAdvancedEffects() const = 0;
|
||||
|
||||
/**
|
||||
* Multiply opacity by \a opacityFactor.
|
||||
*
|
||||
* This method multiplies the opacity of the labeling elements (text, shadow, buffer etc.)
|
||||
* by \a opacity effectively changing the opacity of the whole labeling elements.
|
||||
*
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
virtual void multiplyOpacity( double opacityFactor ) { Q_UNUSED( opacityFactor ); };
|
||||
|
||||
|
||||
// static stuff
|
||||
|
||||
//! Try to create instance of an implementation based on the XML data
|
||||
static QgsAbstractMeshLayerLabeling *create( const QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings
|
||||
*/
|
||||
virtual void toSld( QDomNode &parent, const QVariantMap &props ) const
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
Q_UNUSED( props )
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
parent.appendChild( doc.createComment( QStringLiteral( "SE Export for %1 not implemented yet" ).arg( type() ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts the specified symbology \a visitor, causing it to visit all symbols associated
|
||||
* with the labeling.
|
||||
*
|
||||
* Returns TRUE if the visitor should continue visiting other objects, or FALSE if visiting
|
||||
* should be canceled.
|
||||
*/
|
||||
virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const;
|
||||
|
||||
/**
|
||||
* Returns the default layer settings to use for the specified mesh \a layer.
|
||||
*/
|
||||
static QgsPalLayerSettings defaultSettingsForLayer( const QgsMeshLayer *layer );
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY( QgsAbstractMeshLayerLabeling )
|
||||
|
||||
#ifdef SIP_RUN
|
||||
QgsAbstractMeshLayerLabeling( const QgsAbstractMeshLayerLabeling &rhs );
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \brief Basic implementation of the labeling interface for mesh layer.
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
class CORE_EXPORT QgsMeshLayerSimpleLabeling : public QgsAbstractMeshLayerLabeling
|
||||
{
|
||||
public:
|
||||
//! Constructs simple labeling configuration with given initial settings
|
||||
explicit QgsMeshLayerSimpleLabeling( const QgsPalLayerSettings &settings );
|
||||
|
||||
QString type() const override;
|
||||
QgsMeshLayerSimpleLabeling *clone() const override SIP_FACTORY;
|
||||
//! \note not available in Python bindings
|
||||
QgsMeshLayerLabelProvider *provider( QgsMeshLayer *layer ) const override SIP_SKIP;
|
||||
QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const override;
|
||||
QgsPalLayerSettings settings( const QString &providerId = QString() ) const override;
|
||||
bool accept( QgsStyleEntityVisitorInterface *visitor ) const override;
|
||||
|
||||
/**
|
||||
* Set pal settings (takes ownership).
|
||||
*
|
||||
* \param settings Pal layer settings
|
||||
* \param providerId Unused parameter
|
||||
*/
|
||||
void setSettings( QgsPalLayerSettings *settings SIP_TRANSFER, const QString &providerId = QString() ) override;
|
||||
|
||||
bool requiresAdvancedEffects() const override;
|
||||
void multiplyOpacity( double opacityFactor ) override;
|
||||
//! Create the instance from a DOM element with saved configuration
|
||||
static QgsMeshLayerSimpleLabeling *create( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
|
||||
private:
|
||||
std::unique_ptr<QgsPalLayerSettings> mSettings;
|
||||
};
|
||||
|
||||
#endif // QGSMESHLAYERLABELING_H
|
173
src/core/mesh/qgsmeshlayerlabelprovider.cpp
Normal file
173
src/core/mesh/qgsmeshlayerlabelprovider.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
/***************************************************************************
|
||||
qgsmeshlayerlabelprovider.cpp
|
||||
---------------------
|
||||
begin : November 2023
|
||||
copyright : (C) 2023 by LutraConsulting
|
||||
email : info at lutraconsulting dot co dot uk
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmeshlayerlabelprovider.h"
|
||||
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgslabelsearchtree.h"
|
||||
#include "qgspallabeling.h"
|
||||
#include "qgstextlabelfeature.h"
|
||||
#include "qgsmeshlayer.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsrenderer.h"
|
||||
#include "qgspolygon.h"
|
||||
#include "qgslinestring.h"
|
||||
#include "qgsmultipolygon.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
#include "qgsmaskidprovider.h"
|
||||
#include "qgstextcharacterformat.h"
|
||||
#include "qgstextfragment.h"
|
||||
#include "qgslabelingresults.h"
|
||||
#include "qgstextrenderer.h"
|
||||
#include "qgstriangularmesh.h"
|
||||
|
||||
#include "feature.h"
|
||||
#include "labelposition.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qgsmarkersymbol.h"
|
||||
|
||||
#include "pal/layer.h"
|
||||
|
||||
#include <QPicture>
|
||||
#include <QTextDocument>
|
||||
#include <QTextFragment>
|
||||
|
||||
using namespace pal;
|
||||
|
||||
QgsMeshLayerLabelProvider::QgsMeshLayerLabelProvider( QgsMeshLayer *layer, const QString &providerId, const QgsPalLayerSettings *settings, const QString &layerName )
|
||||
: QgsAbstractLabelProvider( layer, providerId )
|
||||
, mSettings( settings ? * settings : QgsPalLayerSettings() )
|
||||
, mCrs( layer->crs() )
|
||||
{
|
||||
mName = layerName.isEmpty() ? layer->id() : layerName;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
void QgsMeshLayerLabelProvider::init()
|
||||
{
|
||||
mPlacement = mSettings.placement;
|
||||
|
||||
mFlags = Flags();
|
||||
if ( mSettings.drawLabels )
|
||||
mFlags |= DrawLabels;
|
||||
if ( mSettings.lineSettings().mergeLines() && !mSettings.lineSettings().addDirectionSymbol() )
|
||||
mFlags |= MergeConnectedLines;
|
||||
if ( mSettings.centroidInside )
|
||||
mFlags |= CentroidMustBeInside;
|
||||
|
||||
mPriority = 1 - mSettings.priority / 10.0; // convert 0..10 --> 1..0
|
||||
|
||||
if ( mLabelFaces )
|
||||
{
|
||||
mVectorLayer = std::make_unique<QgsVectorLayer>( QStringLiteral( "Polygon?crs=%1" ).arg( mCrs.authid() ), QStringLiteral( "faces" ), QStringLiteral( "memory" ) );
|
||||
QgsMesh *mesh = qobject_cast<QgsMeshLayer *>( layer() )->nativeMesh();
|
||||
int faceCount = mesh->faceCount();
|
||||
QList<QgsFeature> features;
|
||||
for ( int i = 0; i < faceCount; i++ )
|
||||
{
|
||||
QgsFeature f;
|
||||
QgsGeometry geom = QgsMeshUtils::toGeometry( mesh->face( i ), mesh->vertices );
|
||||
f.setGeometry( geom );
|
||||
features << f;
|
||||
}
|
||||
mVectorLayer->dataProvider()->addFeatures( features );
|
||||
}
|
||||
else
|
||||
{
|
||||
mVectorLayer = std::make_unique<QgsVectorLayer>( QStringLiteral( "Polygon?crs=%1" ).arg( mCrs.authid() ), QStringLiteral( "faces" ), QStringLiteral( "memory" ) );
|
||||
QgsMesh *mesh = qobject_cast<QgsMeshLayer *>( layer() )->nativeMesh();
|
||||
int vertexCount = mesh->vertexCount();
|
||||
QList<QgsFeature> features;
|
||||
for ( int i = 0; i < vertexCount; i++ )
|
||||
{
|
||||
QgsFeature f;
|
||||
QgsGeometry geom = QgsGeometry( new QgsPoint( mesh->vertex( i ) ) );
|
||||
f.setGeometry( geom );
|
||||
features << f;
|
||||
}
|
||||
mVectorLayer->dataProvider()->addFeatures( features );
|
||||
}
|
||||
|
||||
mVectorLabelProvider = std::make_unique<QgsVectorLayerLabelProvider>( mVectorLayer.get(), QStringLiteral(), false, &mSettings );
|
||||
|
||||
if ( mLabelFaces )
|
||||
{
|
||||
//override obstacle type to treat any intersection of a label with the point symbol as a high cost conflict
|
||||
mObstacleType = QgsLabelObstacleSettings::PolygonWhole;
|
||||
}
|
||||
else
|
||||
{
|
||||
mObstacleType = mSettings.obstacleSettings().type();
|
||||
}
|
||||
|
||||
mUpsidedownLabels = mSettings.upsidedownLabels;
|
||||
}
|
||||
|
||||
|
||||
QgsMeshLayerLabelProvider::~QgsMeshLayerLabelProvider()
|
||||
{
|
||||
qDeleteAll( mLabels );
|
||||
}
|
||||
|
||||
bool QgsMeshLayerLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
|
||||
{
|
||||
const QgsMapSettings &mapSettings = mEngine->mapSettings();
|
||||
|
||||
return mSettings.prepare( context, attributeNames, QgsFields(), mapSettings, mCrs );
|
||||
}
|
||||
|
||||
void QgsMeshLayerLabelProvider::startRender( QgsRenderContext &context )
|
||||
{
|
||||
QgsAbstractLabelProvider::startRender( context );
|
||||
mSettings.startRender( context );
|
||||
}
|
||||
|
||||
void QgsMeshLayerLabelProvider::stopRender( QgsRenderContext &context )
|
||||
{
|
||||
QgsAbstractLabelProvider::stopRender( context );
|
||||
mSettings.stopRender( context );
|
||||
}
|
||||
|
||||
QList<QgsLabelFeature *> QgsMeshLayerLabelProvider::labelFeatures( QgsRenderContext &ctx )
|
||||
{
|
||||
Q_UNUSED( ctx );
|
||||
return mLabels;
|
||||
}
|
||||
|
||||
QList< QgsLabelFeature * > QgsMeshLayerLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
||||
{
|
||||
std::unique_ptr< QgsLabelFeature > label = mSettings.registerFeatureWithDetails( feature, context, obstacleGeometry, symbol );
|
||||
QList< QgsLabelFeature * > res;
|
||||
if ( label )
|
||||
{
|
||||
res << label.get();
|
||||
mLabels << label.release();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const QgsPalLayerSettings &QgsMeshLayerLabelProvider::settings() const
|
||||
{
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
void QgsMeshLayerLabelProvider::drawLabel( QgsRenderContext &context, pal::LabelPosition *label ) const
|
||||
{
|
||||
mVectorLabelProvider->drawLabel( context, label );
|
||||
}
|
114
src/core/mesh/qgsmeshlayerlabelprovider.h
Normal file
114
src/core/mesh/qgsmeshlayerlabelprovider.h
Normal file
@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
qgsmeshlayerlabelprovider.h
|
||||
---------------------
|
||||
begin : November 2023
|
||||
copyright : (C) 2023 by LutraConsulting
|
||||
email : info at lutraconsulting dot co dot uk
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSMESHLAYERLABELPROVIDER_H
|
||||
#define QGSMESHLAYERLABELPROVIDER_H
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgslabelingengine.h"
|
||||
#include "qgsrenderer.h"
|
||||
#include "qgspallabeling.h"
|
||||
|
||||
class QgsMeshLayer;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \brief The QgsMeshLayerLabelProvider class implements a label provider
|
||||
* for mesh layers. Parameters for the labeling are taken from the layer's
|
||||
* custom properties or from the given settings.
|
||||
*
|
||||
* \note this class is not a part of public API yet. See notes in QgsLabelingEngine
|
||||
* \note not available in Python bindings
|
||||
* \since QGIS 2.12
|
||||
*/
|
||||
class CORE_EXPORT QgsMeshLayerLabelProvider : public QgsAbstractLabelProvider
|
||||
{
|
||||
public:
|
||||
|
||||
//! Convenience constructor to initialize the provider from given mesh layer
|
||||
explicit QgsMeshLayerLabelProvider( QgsMeshLayer *layer,
|
||||
const QString &providerId,
|
||||
const QgsPalLayerSettings *settings,
|
||||
const QString &layerName = QString() );
|
||||
|
||||
~QgsMeshLayerLabelProvider() override;
|
||||
|
||||
QList<QgsLabelFeature *> labelFeatures( QgsRenderContext &context ) override;
|
||||
|
||||
//void drawLabelBackground( QgsRenderContext &context, pal::LabelPosition *label ) const override;
|
||||
void drawLabel( QgsRenderContext &context, pal::LabelPosition *label ) const override;
|
||||
//void drawUnplacedLabel( QgsRenderContext &context, pal::LabelPosition *label ) const override;
|
||||
void startRender( QgsRenderContext &context ) override;
|
||||
void stopRender( QgsRenderContext &context ) override;
|
||||
|
||||
/**
|
||||
* Prepare for registration of features. Must be called after provider has been added to engine (uses its map settings)
|
||||
* \param context render context.
|
||||
* \param attributeNames list of attribute names to which additional required attributes shall be added
|
||||
* \returns Whether the preparation was successful - if not, the provider shall not be used
|
||||
*/
|
||||
virtual bool prepare( QgsRenderContext &context, QSet<QString> &attributeNames );
|
||||
|
||||
/**
|
||||
* Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels
|
||||
*
|
||||
* \param feature feature to label
|
||||
* \param context render context. The QgsExpressionContext contained within the render context
|
||||
* must have already had the feature and fields sets prior to calling this method.
|
||||
* \param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry
|
||||
* should be used as an obstacle for labels (e.g., if the feature has been rendered with an offset point
|
||||
* symbol, the obstacle geometry should represent the bounds of the offset symbol). If not set,
|
||||
* the feature's original geometry will be used as an obstacle for labels.
|
||||
* \param symbol feature symbol to label (ownership is not transferred - the symbol must exist until after labeling is complete)
|
||||
* \returns a list of the newly generated label features. Ownership of these label features is not transferred
|
||||
* (it has already been assigned to the label provider).
|
||||
*/
|
||||
virtual QList< QgsLabelFeature * > registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr );
|
||||
|
||||
/**
|
||||
* Returns the layer's settings.
|
||||
*/
|
||||
const QgsPalLayerSettings &settings() const;
|
||||
|
||||
protected:
|
||||
//! initialization method - called from constructors
|
||||
void init();
|
||||
//! Internal label drawing method
|
||||
void drawLabelPrivate( pal::LabelPosition *label, QgsRenderContext &context, QgsPalLayerSettings &tmpLyr, Qgis::TextComponent drawType, double dpiRatio = 1.0 ) const;
|
||||
|
||||
protected:
|
||||
//! Layer's labeling configuration
|
||||
QgsPalLayerSettings mSettings;
|
||||
|
||||
bool mLabelFaces = false;
|
||||
|
||||
//! Layer's CRS
|
||||
QgsCoordinateReferenceSystem mCrs;
|
||||
|
||||
//! List of generated
|
||||
QList<QgsLabelFeature *> mLabels;
|
||||
|
||||
private:
|
||||
std::unique_ptr<QgsVectorLayerLabelProvider> mVectorLabelProvider;
|
||||
std::unique_ptr<QgsVectorLayer> mVectorLayer;
|
||||
|
||||
friend class TestQgsLabelingEngine;
|
||||
};
|
||||
|
||||
#endif // QGSMESHLAYERLABELPROVIDER_H
|
@ -2016,6 +2016,13 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "raster_attributes wrong band 2" ) << QStringLiteral( "raster_attributes('%1',2,243)" ).arg( mRasterLayerWithAttributeTable->name() ) << true << QVariant();
|
||||
QTest::newRow( "raster_attributes no attributes" ) << QStringLiteral( "raster_attributes('%1',1,1)" ).arg( mRasterLayerWithAttributeTable->name() ) << false << QVariant();
|
||||
|
||||
// mesh_contour tests
|
||||
QTest::newRow( "mesh_contour invalid geometry" ) << QStringLiteral( "mesh_contour('invalid geom', make_datetime(2023,11,29,10,34,52), '%1')" ).arg( mMeshLayer->name() ) << true << QVariant();
|
||||
QTest::newRow( "mesh_contour valid" ) << QStringLiteral( "mesh_contour(make_point(2000,3000), make_datetime(2023,11,29,10,34,52), '%1')" ).arg( mMeshLayer->name() ) << false << QVariant( 200.0 );
|
||||
QTest::newRow( "mesh_data invalid geometry" ) << QStringLiteral( "mesh_data('invalid geom', 'Bed Elevation', make_datetime(2023,11,29,10,34,52), '%1')" ).arg( mMeshLayer->name() ) << true << QVariant();
|
||||
QTest::newRow( "mesh_data invalid group" ) << QStringLiteral( "mesh_data(make_point(2000,3000), 'Bad elevation', make_datetime(2023,11,29,10,34,52), '%1')" ).arg( mMeshLayer->name() ) << true << QVariant();
|
||||
QTest::newRow( "mesh_data valid" ) << QStringLiteral( "mesh_data(make_point(2000,3000), 'Bed Elevation', make_datetime(2023,11,29,10,34,52), '%1')" ).arg( mMeshLayer->name() ) << false << QVariant( 200.0 );
|
||||
|
||||
//test conversions to bool
|
||||
QTest::newRow( "feature to bool false" ) << QStringLiteral( "case when get_feature('none','none',499) then true else false end" ) << false << QVariant( false );
|
||||
QTest::newRow( "feature to bool true" ) << QStringLiteral( "case when get_feature('test','col1',10) then true else false end" ) << false << QVariant( true );
|
||||
|
Loading…
x
Reference in New Issue
Block a user