mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -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
|
.. versionadded:: 3.22
|
||||||
%End
|
%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:
|
public slots:
|
||||||
|
|
||||||
virtual void setTransformContext( const QgsCoordinateTransformContext &transformContext );
|
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/qgsmeshlayer.sip
|
||||||
%Include auto_generated/mesh/qgsmeshlayerelevationproperties.sip
|
%Include auto_generated/mesh/qgsmeshlayerelevationproperties.sip
|
||||||
%Include auto_generated/mesh/qgsmeshlayerinterpolator.sip
|
%Include auto_generated/mesh/qgsmeshlayerinterpolator.sip
|
||||||
|
%Include auto_generated/mesh/qgsmeshlayerlabeling.sip
|
||||||
%Include auto_generated/mesh/qgsmeshlayertemporalproperties.sip
|
%Include auto_generated/mesh/qgsmeshlayertemporalproperties.sip
|
||||||
%Include auto_generated/mesh/qgsmeshrenderersettings.sip
|
%Include auto_generated/mesh/qgsmeshrenderersettings.sip
|
||||||
%Include auto_generated/mesh/qgsmeshspatialindex.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/qgstopologicalmesh.cpp
|
||||||
mesh/qgsmeshadvancedediting.cpp
|
mesh/qgsmeshadvancedediting.cpp
|
||||||
mesh/qgsmeshforcebypolylines.cpp
|
mesh/qgsmeshforcebypolylines.cpp
|
||||||
|
mesh/qgsmeshlayerlabeling.cpp
|
||||||
|
mesh/qgsmeshlayerlabelprovider.cpp
|
||||||
|
|
||||||
pointcloud/qgspointcloudattribute.cpp
|
pointcloud/qgspointcloudattribute.cpp
|
||||||
pointcloud/qgspointcloudattributebyramprenderer.cpp
|
pointcloud/qgspointcloudattributebyramprenderer.cpp
|
||||||
@ -1618,6 +1620,8 @@ set(QGIS_CORE_HDRS
|
|||||||
mesh/qgstopologicalmesh.h
|
mesh/qgstopologicalmesh.h
|
||||||
mesh/qgsmeshadvancedediting.h
|
mesh/qgsmeshadvancedediting.h
|
||||||
mesh/qgsmeshforcebypolylines.h
|
mesh/qgsmeshforcebypolylines.h
|
||||||
|
mesh/qgsmeshlayerlabeling.h
|
||||||
|
mesh/qgsmeshlayerlabelprovider.h
|
||||||
|
|
||||||
pal/costcalculator.h
|
pal/costcalculator.h
|
||||||
pal/feature.h
|
pal/feature.h
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
#include "qgsunittypes.h"
|
#include "qgsunittypes.h"
|
||||||
#include "qgsspatialindex.h"
|
#include "qgsspatialindex.h"
|
||||||
#include "qgscolorrampimpl.h"
|
#include "qgscolorrampimpl.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgsmeshdataset.h"
|
||||||
|
|
||||||
#include <QMimeDatabase>
|
#include <QMimeDatabase>
|
||||||
#include <QProcessEnvironment>
|
#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 * )
|
static QVariant fcnFeature( const QVariantList &, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * )
|
||||||
{
|
{
|
||||||
if ( !context )
|
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_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" ) )
|
<< 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
|
// functions for arrays
|
||||||
<< new QgsArrayForeachExpressionFunction()
|
<< new QgsArrayForeachExpressionFunction()
|
||||||
<< new QgsArrayFilterExpressionFunction()
|
<< new QgsArrayFilterExpressionFunction()
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include "qgsthreadingutils.h"
|
#include "qgsthreadingutils.h"
|
||||||
#include "qgsapplication.h"
|
#include "qgsapplication.h"
|
||||||
#include "qgsruntimeprofiler.h"
|
#include "qgsruntimeprofiler.h"
|
||||||
|
#include "qgsmeshlayerlabeling.h"
|
||||||
|
|
||||||
QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
|
QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
|
||||||
const QString &baseName,
|
const QString &baseName,
|
||||||
@ -106,6 +107,7 @@ bool QgsMeshLayer::hasSimplifiedMeshes() const
|
|||||||
|
|
||||||
QgsMeshLayer::~QgsMeshLayer()
|
QgsMeshLayer::~QgsMeshLayer()
|
||||||
{
|
{
|
||||||
|
delete mLabeling;
|
||||||
delete mDataProvider;
|
delete mDataProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1773,6 +1775,16 @@ bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &e
|
|||||||
blendModeElement.appendChild( blendModeText );
|
blendModeElement.appendChild( blendModeText );
|
||||||
node.appendChild( blendModeElement );
|
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
|
// add the layer opacity
|
||||||
if ( categories.testFlag( Rendering ) )
|
if ( categories.testFlag( Rendering ) )
|
||||||
{
|
{
|
||||||
@ -2148,3 +2160,28 @@ QgsMapLayerElevationProperties *QgsMeshLayer::elevationProperties()
|
|||||||
|
|
||||||
return mElevationProperties;
|
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 QgsMeshEditor;
|
||||||
class QgsMeshEditingError;
|
class QgsMeshEditingError;
|
||||||
class QgsMeshLayerElevationProperties;
|
class QgsMeshLayerElevationProperties;
|
||||||
|
class QgsAbstractMeshLayerLabeling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup core
|
* \ingroup core
|
||||||
@ -881,6 +882,53 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer, public QgsAbstractProfileSo
|
|||||||
*/
|
*/
|
||||||
int meshEdgeCount() const;
|
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:
|
public slots:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -991,6 +1039,12 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer, public QgsAbstractProfileSo
|
|||||||
|
|
||||||
QgsMeshEditor *mMeshEditor = nullptr;
|
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;
|
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
|
//! 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 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();
|
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
|
//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 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 );
|
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