mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[FEATURE] Rendering of vector data on mesh layers
Rudimentary support of rendering of vector data (e.g. velocity) on mesh map layers. Rendering can be adjusted by QgsMeshRenderer*Settings. Only in Python API, no GUI widgets for styling present.
This commit is contained in:
parent
9296528822
commit
aea3dccea7
@ -36,19 +36,64 @@ support of nodata values
|
|||||||
public:
|
public:
|
||||||
QgsMeshDatasetValue( double x,
|
QgsMeshDatasetValue( double x,
|
||||||
double y );
|
double y );
|
||||||
|
%Docstring
|
||||||
|
Ctor
|
||||||
|
%End
|
||||||
|
|
||||||
QgsMeshDatasetValue( double scalar );
|
QgsMeshDatasetValue( double scalar );
|
||||||
|
%Docstring
|
||||||
|
Ctor
|
||||||
|
%End
|
||||||
|
|
||||||
QgsMeshDatasetValue( );
|
QgsMeshDatasetValue( );
|
||||||
|
%Docstring
|
||||||
|
Ctor
|
||||||
|
%End
|
||||||
|
|
||||||
~QgsMeshDatasetValue();
|
~QgsMeshDatasetValue();
|
||||||
|
|
||||||
void setNodata( bool nodata = true );
|
void setNodata( bool nodata = true );
|
||||||
|
%Docstring
|
||||||
|
Sets nodata value for this dataset value
|
||||||
|
%End
|
||||||
bool isNodata() const;
|
bool isNodata() const;
|
||||||
|
%Docstring
|
||||||
|
Returns whether it is nodata value
|
||||||
|
%End
|
||||||
bool isScalar() const;
|
bool isScalar() const;
|
||||||
double scalar() const; //length for vectors, value for scalars
|
%Docstring
|
||||||
|
Returns whether it is scalar value
|
||||||
|
%End
|
||||||
|
double scalar() const;
|
||||||
|
%Docstring
|
||||||
|
Returns scalar value. Length for vectors, value for scalars
|
||||||
|
%End
|
||||||
|
|
||||||
void set( double scalar );
|
void set( double scalar );
|
||||||
|
%Docstring
|
||||||
|
Sets scalar value
|
||||||
|
%End
|
||||||
|
|
||||||
void setX( double x );
|
void setX( double x );
|
||||||
|
%Docstring
|
||||||
|
Sets X value
|
||||||
|
%End
|
||||||
|
|
||||||
void setY( double y );
|
void setY( double y );
|
||||||
|
%Docstring
|
||||||
|
Sets Y value
|
||||||
|
%End
|
||||||
|
|
||||||
double x() const;
|
double x() const;
|
||||||
|
%Docstring
|
||||||
|
Returns x value
|
||||||
|
%End
|
||||||
|
|
||||||
double y() const;
|
double y() const;
|
||||||
|
%Docstring
|
||||||
|
Returns y value
|
||||||
|
%End
|
||||||
|
|
||||||
bool operator==( const QgsMeshDatasetValue &other ) const;
|
bool operator==( const QgsMeshDatasetValue &other ) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -78,14 +123,14 @@ read on demand
|
|||||||
|
|
||||||
virtual int vertexCount() const = 0;
|
virtual int vertexCount() const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return number of vertices in the native mesh
|
Returns number of vertices in the native mesh
|
||||||
|
|
||||||
:return: Number of vertices in the mesh
|
:return: Number of vertices in the mesh
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual int faceCount() const = 0;
|
virtual int faceCount() const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return number of faces in the native mesh
|
Returns number of faces in the native mesh
|
||||||
|
|
||||||
:return: Number of faces in the mesh
|
:return: Number of faces in the mesh
|
||||||
%End
|
%End
|
||||||
@ -94,7 +139,7 @@ read on demand
|
|||||||
%Docstring
|
%Docstring
|
||||||
Factory for mesh vertex with index
|
Factory for mesh vertex with index
|
||||||
|
|
||||||
:return: new mesh vertex on index
|
:return: New mesh vertex on index
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual QgsMeshFace face( int index ) const = 0;
|
virtual QgsMeshFace face( int index ) const = 0;
|
||||||
@ -133,32 +178,32 @@ read on demand
|
|||||||
|
|
||||||
virtual int datasetCount() const = 0;
|
virtual int datasetCount() const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return number of datasets loaded
|
Returns number of datasets loaded
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual bool datasetHasScalarData( int index ) const = 0;
|
virtual bool datasetHasScalarData( int index ) const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Whether dataset has scalar data associated
|
Returns whether dataset has scalar data associated
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual bool datasetIsOnVertices( int index ) const = 0;
|
virtual bool datasetIsOnVertices( int index ) const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Whether dataset is on vertices
|
Returns whether dataset is on vertices
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
|
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return dataset metadata
|
Returns dataset metadata
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
|
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return value associated with the index from the dataset
|
Returns value associated with the index from the dataset
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual bool datasetIsValid( int index ) const = 0;
|
virtual bool datasetIsValid( int index ) const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return whether dataset is valid
|
Returns whether dataset is valid
|
||||||
%End
|
%End
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,8 +52,6 @@ E.g. to create mesh with one quad and one triangle
|
|||||||
);
|
);
|
||||||
QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
|
QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
|
||||||
|
|
||||||
Add datasets by adding them through data provider, :py:func:`QgsMeshDatasetSource.addDataset`
|
|
||||||
|
|
||||||
\subsection mdal MDAL data provider (mdal)
|
\subsection mdal MDAL data provider (mdal)
|
||||||
|
|
||||||
Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
|
Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
|
||||||
@ -118,32 +116,68 @@ QgsMeshLayer cannot be copied.
|
|||||||
|
|
||||||
QString providerType() const;
|
QString providerType() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return the provider type for this layer
|
Returns the provider type for this layer
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QgsSymbol *nativeMeshSymbol();
|
QgsMeshRendererMeshSettings rendererNativeMeshSettings() const /Factory/;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns a line symbol used for rendering native mesh.
|
Returns rendrer settings
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QgsSymbol *triangularMeshSymbol();
|
void setRendererNativeMeshSettings( const QgsMeshRendererMeshSettings &settings );
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns a line symbol used for rendering of triangular (derived) mesh.
|
Sets new rendering settings, triggers repaint
|
||||||
|
|
||||||
.. seealso:: :py:func:`toggleTriangularMeshRendering`
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void toggleTriangularMeshRendering( bool toggle );
|
QgsMeshRendererMeshSettings rendererTriangularMeshSettings() const /Factory/;
|
||||||
%Docstring
|
%Docstring
|
||||||
Toggle rendering of triangular (derived) mesh. Off by default
|
Returns rendrer settings
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setRendererTriangularMeshSettings( const QgsMeshRendererMeshSettings &settings );
|
||||||
|
%Docstring
|
||||||
|
Sets new rendering settings, triggers repaint
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsMeshRendererScalarSettings rendererScalarSettings() const /Factory/;
|
||||||
|
%Docstring
|
||||||
|
Returns rendrer settings
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setRendererScalarSettings( const QgsMeshRendererScalarSettings &settings );
|
||||||
|
%Docstring
|
||||||
|
Sets new rendering settings, triggers repaint
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsMeshRendererVectorSettings rendererVectorSettings() const /Factory/;
|
||||||
|
%Docstring
|
||||||
|
Returns rendrer settings
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setRendererVectorSettings( const QgsMeshRendererVectorSettings &settings );
|
||||||
|
%Docstring
|
||||||
|
Sets new rendering settings, triggers repaint
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void setActiveScalarDataset( int index = -1 );
|
void setActiveScalarDataset( int index = -1 );
|
||||||
void setActiveVectorDataset( int index = -1 );
|
%Docstring
|
||||||
|
Sets active scalar dataset for rendering
|
||||||
|
%End
|
||||||
int activeScalarDataset() const;
|
int activeScalarDataset() const;
|
||||||
|
%Docstring
|
||||||
|
Returns active scalar dataset
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setActiveVectorDataset( int index = -1 );
|
||||||
|
%Docstring
|
||||||
|
Sets active vector dataset for rendering. If dataset is not vector based, do nothing
|
||||||
|
%End
|
||||||
|
int activeVectorDataset() const;
|
||||||
|
%Docstring
|
||||||
|
Returns active vector dataset
|
||||||
|
%End
|
||||||
|
|
||||||
private: // Private methods
|
private: // Private methods
|
||||||
QgsMeshLayer( const QgsMeshLayer &rhs );
|
QgsMeshLayer( const QgsMeshLayer &rhs );
|
||||||
|
282
python/core/auto_generated/mesh/qgsmeshrenderersettings.sip.in
Normal file
282
python/core/auto_generated/mesh/qgsmeshrenderersettings.sip.in
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsmeshrenderersettings.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsMeshRendererMeshSettings
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
|
||||||
|
Represents a mesh renderer settings for mesh object
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The API is considered EXPERIMENTAL and can be changed without a notice
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsmeshrenderersettings.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
bool isEnabled() const;
|
||||||
|
%Docstring
|
||||||
|
Returns whether mesh structure rendering is enabled
|
||||||
|
%End
|
||||||
|
void setEnabled( bool enabled );
|
||||||
|
%Docstring
|
||||||
|
Sets whether mesh structure rendering is enabled
|
||||||
|
%End
|
||||||
|
|
||||||
|
double lineWidth() const;
|
||||||
|
%Docstring
|
||||||
|
Returns line width used for rendering (in millimeters)
|
||||||
|
%End
|
||||||
|
void setLineWidth( double lineWidth );
|
||||||
|
%Docstring
|
||||||
|
Sets line width used for rendering (in millimeters)
|
||||||
|
%End
|
||||||
|
|
||||||
|
QColor color() const;
|
||||||
|
%Docstring
|
||||||
|
Returns color used for rendering
|
||||||
|
%End
|
||||||
|
void setColor( const QColor &color );
|
||||||
|
%Docstring
|
||||||
|
Sets color used for rendering of the mesh
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class QgsMeshRendererScalarSettings
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
|
||||||
|
Represents a mesh renderer settings for scalar datasets
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The API is considered EXPERIMENTAL and can be changed without a notice
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsmeshrenderersettings.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
QColor maxColor() const;
|
||||||
|
%Docstring
|
||||||
|
Returns color representing maximum scalar value in the dataset
|
||||||
|
%End
|
||||||
|
void setMaxColor( const QColor &maxColor );
|
||||||
|
%Docstring
|
||||||
|
Sets color representing maximum scalar value in the dataset
|
||||||
|
%End
|
||||||
|
|
||||||
|
QColor minColor() const;
|
||||||
|
%Docstring
|
||||||
|
Returns color representing minimum scalar value in the dataset
|
||||||
|
%End
|
||||||
|
void setMinColor( const QColor &minColor );
|
||||||
|
%Docstring
|
||||||
|
Sets color representing maximum scalar value in the dataset
|
||||||
|
%End
|
||||||
|
|
||||||
|
double minValue() const;
|
||||||
|
%Docstring
|
||||||
|
Returns min scalar value that represents minColor()
|
||||||
|
|
||||||
|
if set to numerical_limits<double>.quiet_NaN(), value for minColor() is
|
||||||
|
taken from minimum value of active scalar dataset
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setMinValue( double minValue );
|
||||||
|
%Docstring
|
||||||
|
Sets min scalar value that represents minColor()
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`QgsMeshRendererScalarSettings.minValue`
|
||||||
|
%End
|
||||||
|
|
||||||
|
double maxValue() const;
|
||||||
|
%Docstring
|
||||||
|
Returns max scalar value that represents maxColor()
|
||||||
|
|
||||||
|
if set to numerical_limits<double>.quiet_NaN(), value for maxColor() is
|
||||||
|
taken from maximum value of active scalar dataset
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setMaxValue( double maxValue );
|
||||||
|
%Docstring
|
||||||
|
Sets min scalar value that represents minColor()
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`QgsMeshRendererScalarSettings.maxValue`
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class QgsMeshRendererVectorSettings
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
|
||||||
|
Represents a mesh renderer settings for vector datasets
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The API is considered EXPERIMENTAL and can be changed without a notice
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsmeshrenderersettings.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
enum VectorRenderingType
|
||||||
|
{
|
||||||
|
|
||||||
|
MinMax,
|
||||||
|
|
||||||
|
Scaled,
|
||||||
|
|
||||||
|
Fixed
|
||||||
|
};
|
||||||
|
|
||||||
|
double lineWidth() const;
|
||||||
|
%Docstring
|
||||||
|
Returns line width of the arrow (in millimeters)
|
||||||
|
%End
|
||||||
|
void setLineWidth( double lineWidth );
|
||||||
|
%Docstring
|
||||||
|
Sets line width of the arrow in pixels (in millimeters)
|
||||||
|
%End
|
||||||
|
|
||||||
|
QColor color() const;
|
||||||
|
%Docstring
|
||||||
|
Returns color used for drawing arrows
|
||||||
|
%End
|
||||||
|
void setColor( const QColor &color );
|
||||||
|
%Docstring
|
||||||
|
Sets color used for drawing arrows
|
||||||
|
%End
|
||||||
|
|
||||||
|
double filterMin() const;
|
||||||
|
%Docstring
|
||||||
|
Returns filter value for vector magnitudes.
|
||||||
|
|
||||||
|
If magnitude of the vector is lower than this value, the vector is not
|
||||||
|
drawn. -1 represents that filtering is not active.
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setFilterMin( double filterMin );
|
||||||
|
%Docstring
|
||||||
|
Sets filter value for vector magnitudes.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`QgsMeshRendererVectorSettings.vectorFilterMin`
|
||||||
|
%End
|
||||||
|
|
||||||
|
double filterMax() const;
|
||||||
|
%Docstring
|
||||||
|
Returns filter value for vector magnitudes.
|
||||||
|
|
||||||
|
If magnitude of the vector is higher than this value, the vector is not
|
||||||
|
drawn. -1 represents that filtering is not active.
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setFilterMax( double filterMax );
|
||||||
|
%Docstring
|
||||||
|
Sets filter value for vector magnitudes.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`QgsMeshRendererVectorSettings.vectorFilterMax`
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsMeshRendererVectorSettings::VectorRenderingType shaftLengthMethod() const;
|
||||||
|
%Docstring
|
||||||
|
Returns method used for drawing arrows
|
||||||
|
%End
|
||||||
|
void setShaftLengthMethod( const QgsMeshRendererVectorSettings::VectorRenderingType &shaftLengthMethod );
|
||||||
|
%Docstring
|
||||||
|
Sets method used for drawing arrows
|
||||||
|
%End
|
||||||
|
|
||||||
|
double minShaftLength() const;
|
||||||
|
%Docstring
|
||||||
|
Returns mininimum shaft length (in millimeters)
|
||||||
|
|
||||||
|
Only for QgsMeshRendererVectorSettings.ArrowType.MinMax
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setMinShaftLength( double minShaftLength );
|
||||||
|
%Docstring
|
||||||
|
Sets mininimum shaft length (in millimeters)
|
||||||
|
|
||||||
|
Only for QgsMeshRendererVectorSettings.ArrowType.MinMax
|
||||||
|
%End
|
||||||
|
|
||||||
|
double maxShaftLength() const;
|
||||||
|
%Docstring
|
||||||
|
Returns maximum shaft length (in millimeters)
|
||||||
|
|
||||||
|
Only for QgsMeshRendererVectorSettings.ArrowType.MinMax
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setMaxShaftLength( double maxShaftLength );
|
||||||
|
%Docstring
|
||||||
|
Sets maximum shaft length (in millimeters)
|
||||||
|
|
||||||
|
Only for QgsMeshRendererVectorSettings.ArrowType.MinMax
|
||||||
|
%End
|
||||||
|
|
||||||
|
double scaleFactor() const;
|
||||||
|
%Docstring
|
||||||
|
Returns scale factor. Only for QgsMeshRendererVectorSettings.ArrowType.Scaled
|
||||||
|
%End
|
||||||
|
void setScaleFactor( double scaleFactor );
|
||||||
|
%Docstring
|
||||||
|
Sets scale factor. Only for QgsMeshRendererVectorSettings.ArrowType.Scaled
|
||||||
|
%End
|
||||||
|
|
||||||
|
double fixedShaftLength() const;
|
||||||
|
%Docstring
|
||||||
|
Returns fixed arrow length (in millimeters). Only for QgsMeshRendererVectorSettings.ArrowType.Fixed
|
||||||
|
%End
|
||||||
|
void setFixedShaftLength( double fixedShaftLength );
|
||||||
|
%Docstring
|
||||||
|
Sets fixed length (in millimeters). Only for QgsMeshRendererVectorSettings.ArrowType.Fixed
|
||||||
|
%End
|
||||||
|
|
||||||
|
double arrowHeadWidthRatio() const;
|
||||||
|
%Docstring
|
||||||
|
Returns ratio of the head width of the arrow (range 0-1)
|
||||||
|
%End
|
||||||
|
void setArrowHeadWidthRatio( double arrowHeadWidthRatio );
|
||||||
|
%Docstring
|
||||||
|
Sets ratio of the head width of the arrow (range 0-1)
|
||||||
|
%End
|
||||||
|
|
||||||
|
double arrowHeadLengthRatio() const;
|
||||||
|
%Docstring
|
||||||
|
Returns ratio of the head length of the arrow (range 0-1)
|
||||||
|
%End
|
||||||
|
void setArrowHeadLengthRatio( double arrowHeadLengthRatio );
|
||||||
|
%Docstring
|
||||||
|
Sets ratio of the head length of the arrow (range 0-1)
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsmeshrenderersettings.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
@ -1,4 +1,3 @@
|
|||||||
// Include auto-generated SIP files
|
|
||||||
%Include auto_generated/expression/qgsexpression.sip
|
%Include auto_generated/expression/qgsexpression.sip
|
||||||
%Include auto_generated/expression/qgsexpressionnode.sip
|
%Include auto_generated/expression/qgsexpressionnode.sip
|
||||||
%Include auto_generated/expression/qgsexpressionnodeimpl.sip
|
%Include auto_generated/expression/qgsexpressionnodeimpl.sip
|
||||||
@ -381,6 +380,7 @@
|
|||||||
%Include auto_generated/raster/qgsrasterprojector.sip
|
%Include auto_generated/raster/qgsrasterprojector.sip
|
||||||
%Include auto_generated/mesh/qgsmeshdataprovider.sip
|
%Include auto_generated/mesh/qgsmeshdataprovider.sip
|
||||||
%Include auto_generated/mesh/qgsmeshlayer.sip
|
%Include auto_generated/mesh/qgsmeshlayer.sip
|
||||||
|
%Include auto_generated/mesh/qgsmeshrenderersettings.sip
|
||||||
%Include auto_generated/geometry/qgsabstractgeometry.sip
|
%Include auto_generated/geometry/qgsabstractgeometry.sip
|
||||||
%Include auto_generated/geometry/qgsgeometry.sip
|
%Include auto_generated/geometry/qgsgeometry.sip
|
||||||
%Include auto_generated/geometry/qgspoint.sip
|
%Include auto_generated/geometry/qgspoint.sip
|
||||||
|
@ -454,6 +454,8 @@ SET(QGIS_CORE_SRCS
|
|||||||
mesh/qgsmeshmemorydataprovider.cpp
|
mesh/qgsmeshmemorydataprovider.cpp
|
||||||
mesh/qgstriangularmesh.cpp
|
mesh/qgstriangularmesh.cpp
|
||||||
mesh/qgsmeshlayerinterpolator.cpp
|
mesh/qgsmeshlayerinterpolator.cpp
|
||||||
|
mesh/qgsmeshvectorrenderer.cpp
|
||||||
|
mesh/qgsmeshrenderersettings.cpp
|
||||||
|
|
||||||
geometry/qgsabstractgeometry.cpp
|
geometry/qgsabstractgeometry.cpp
|
||||||
geometry/qgsbox3d.cpp
|
geometry/qgsbox3d.cpp
|
||||||
@ -1077,6 +1079,8 @@ SET(QGIS_CORE_HDRS
|
|||||||
mesh/qgstriangularmesh.h
|
mesh/qgstriangularmesh.h
|
||||||
mesh/qgsmeshlayerrenderer.h
|
mesh/qgsmeshlayerrenderer.h
|
||||||
mesh/qgsmeshlayerinterpolator.h
|
mesh/qgsmeshlayerinterpolator.h
|
||||||
|
mesh/qgsmeshvectorrenderer.h
|
||||||
|
mesh/qgsmeshrenderersettings.h
|
||||||
|
|
||||||
scalebar/qgsdoubleboxscalebarrenderer.h
|
scalebar/qgsdoubleboxscalebarrenderer.h
|
||||||
scalebar/qgsnumericscalebarrenderer.h
|
scalebar/qgsnumericscalebarrenderer.h
|
||||||
|
@ -52,21 +52,44 @@ class CORE_EXPORT QgsMeshDatasetValue
|
|||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//! Ctor
|
||||||
QgsMeshDatasetValue( double x,
|
QgsMeshDatasetValue( double x,
|
||||||
double y );
|
double y );
|
||||||
|
|
||||||
|
//! Ctor
|
||||||
QgsMeshDatasetValue( double scalar );
|
QgsMeshDatasetValue( double scalar );
|
||||||
|
|
||||||
|
//! Ctor
|
||||||
QgsMeshDatasetValue( ) = default;
|
QgsMeshDatasetValue( ) = default;
|
||||||
|
|
||||||
|
//! Dtor
|
||||||
~QgsMeshDatasetValue() = default;
|
~QgsMeshDatasetValue() = default;
|
||||||
|
|
||||||
|
//! Sets nodata value for this dataset value
|
||||||
void setNodata( bool nodata = true );
|
void setNodata( bool nodata = true );
|
||||||
|
//! Returns whether it is nodata value
|
||||||
bool isNodata() const;
|
bool isNodata() const;
|
||||||
|
//! Returns whether it is scalar value
|
||||||
bool isScalar() const;
|
bool isScalar() const;
|
||||||
double scalar() const; //length for vectors, value for scalars
|
//! Returns scalar value. Length for vectors, value for scalars
|
||||||
|
double scalar() const;
|
||||||
|
|
||||||
|
//! Sets scalar value
|
||||||
void set( double scalar );
|
void set( double scalar );
|
||||||
|
|
||||||
|
//! Sets X value
|
||||||
void setX( double x );
|
void setX( double x );
|
||||||
|
|
||||||
|
//! Sets Y value
|
||||||
void setY( double y ) ;
|
void setY( double y ) ;
|
||||||
|
|
||||||
|
//! Returns x value
|
||||||
double x() const;
|
double x() const;
|
||||||
|
|
||||||
|
//! Returns y value
|
||||||
double y() const;
|
double y() const;
|
||||||
|
|
||||||
|
//! Equals
|
||||||
bool operator==( const QgsMeshDatasetValue &other ) const;
|
bool operator==( const QgsMeshDatasetValue &other ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -96,20 +119,20 @@ class CORE_EXPORT QgsMeshSource SIP_ABSTRACT
|
|||||||
virtual ~QgsMeshSource() = default;
|
virtual ~QgsMeshSource() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return number of vertices in the native mesh
|
* \brief Returns number of vertices in the native mesh
|
||||||
* \returns Number of vertices in the mesh
|
* \returns Number of vertices in the mesh
|
||||||
*/
|
*/
|
||||||
virtual int vertexCount() const = 0;
|
virtual int vertexCount() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return number of faces in the native mesh
|
* \brief Returns number of faces in the native mesh
|
||||||
* \returns Number of faces in the mesh
|
* \returns Number of faces in the mesh
|
||||||
*/
|
*/
|
||||||
virtual int faceCount() const = 0;
|
virtual int faceCount() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Factory for mesh vertex with index
|
* \brief Factory for mesh vertex with index
|
||||||
* \returns new mesh vertex on index
|
* \returns New mesh vertex on index
|
||||||
*/
|
*/
|
||||||
virtual QgsMeshVertex vertex( int index ) const = 0;
|
virtual QgsMeshVertex vertex( int index ) const = 0;
|
||||||
|
|
||||||
@ -143,32 +166,32 @@ class CORE_EXPORT QgsMeshDatasetSource SIP_ABSTRACT
|
|||||||
virtual bool addDataset( const QString &uri ) = 0;
|
virtual bool addDataset( const QString &uri ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return number of datasets loaded
|
* \brief Returns number of datasets loaded
|
||||||
*/
|
*/
|
||||||
virtual int datasetCount() const = 0;
|
virtual int datasetCount() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Whether dataset has scalar data associated
|
* \brief Returns whether dataset has scalar data associated
|
||||||
*/
|
*/
|
||||||
virtual bool datasetHasScalarData( int index ) const = 0;
|
virtual bool datasetHasScalarData( int index ) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Whether dataset is on vertices
|
* \brief Returns whether dataset is on vertices
|
||||||
*/
|
*/
|
||||||
virtual bool datasetIsOnVertices( int index ) const = 0;
|
virtual bool datasetIsOnVertices( int index ) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return dataset metadata
|
* \brief Returns dataset metadata
|
||||||
*/
|
*/
|
||||||
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
|
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return value associated with the index from the dataset
|
* \brief Returns value associated with the index from the dataset
|
||||||
*/
|
*/
|
||||||
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
|
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return whether dataset is valid
|
* \brief Returns whether dataset is valid
|
||||||
*/
|
*/
|
||||||
virtual bool datasetIsValid( int index ) const = 0;
|
virtual bool datasetIsValid( int index ) const = 0;
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "qgsfillsymbollayer.h"
|
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgsmeshdataprovider.h"
|
#include "qgsmeshdataprovider.h"
|
||||||
#include "qgsmeshlayer.h"
|
#include "qgsmeshlayer.h"
|
||||||
@ -37,12 +37,8 @@ QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
|
|||||||
// load data
|
// load data
|
||||||
setDataProvider( providerKey );
|
setDataProvider( providerKey );
|
||||||
|
|
||||||
QgsSymbolLayerList l1;
|
// show at least the mesh by default so we render something
|
||||||
l1 << new QgsSimpleFillSymbolLayer( Qt::white, Qt::NoBrush, Qt::black, Qt::SolidLine, 1.0 );
|
mRendererNativeMeshSettings.setEnabled( true );
|
||||||
mNativeMeshSymbol.reset( new QgsFillSymbol( l1 ) );
|
|
||||||
|
|
||||||
|
|
||||||
toggleTriangularMeshRendering( false );
|
|
||||||
|
|
||||||
} // QgsMeshLayer ctor
|
} // QgsMeshLayer ctor
|
||||||
|
|
||||||
@ -99,34 +95,53 @@ QgsTriangularMesh *QgsMeshLayer::triangularMesh() SIP_SKIP
|
|||||||
return mTriangularMesh.get();
|
return mTriangularMesh.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbol *QgsMeshLayer::nativeMeshSymbol()
|
|
||||||
|
QgsMeshRendererMeshSettings QgsMeshLayer::rendererNativeMeshSettings() const
|
||||||
{
|
{
|
||||||
return mNativeMeshSymbol.get();
|
return mRendererNativeMeshSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbol *QgsMeshLayer::triangularMeshSymbol()
|
void QgsMeshLayer::setRendererNativeMeshSettings( const QgsMeshRendererMeshSettings &settings )
|
||||||
{
|
{
|
||||||
return mTriangularMeshSymbol.get();
|
mRendererNativeMeshSettings = settings;
|
||||||
}
|
|
||||||
|
|
||||||
void QgsMeshLayer::toggleTriangularMeshRendering( bool toggle )
|
|
||||||
{
|
|
||||||
if ( toggle && mTriangularMeshSymbol )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( toggle )
|
|
||||||
{
|
|
||||||
QgsSymbolLayerList l2;
|
|
||||||
l2 << new QgsSimpleFillSymbolLayer( Qt::white, Qt::NoBrush, Qt::red, Qt::SolidLine, 0.26 );
|
|
||||||
mTriangularMeshSymbol.reset( new QgsFillSymbol( l2 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mTriangularMeshSymbol.reset();
|
|
||||||
}
|
|
||||||
triggerRepaint();
|
triggerRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMeshRendererMeshSettings QgsMeshLayer::rendererTriangularMeshSettings() const
|
||||||
|
{
|
||||||
|
return mRendererTriangularMeshSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayer::setRendererTriangularMeshSettings( const QgsMeshRendererMeshSettings &settings )
|
||||||
|
{
|
||||||
|
mRendererTriangularMeshSettings = settings;
|
||||||
|
triggerRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshRendererScalarSettings QgsMeshLayer::rendererScalarSettings() const
|
||||||
|
{
|
||||||
|
return mRendererScalarSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayer::setRendererScalarSettings( const QgsMeshRendererScalarSettings &settings )
|
||||||
|
{
|
||||||
|
mRendererScalarSettings = settings;
|
||||||
|
triggerRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QgsMeshRendererVectorSettings QgsMeshLayer::rendererVectorSettings() const
|
||||||
|
{
|
||||||
|
return mRendererVectorSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayer::setRendererVectorSettings( const QgsMeshRendererVectorSettings &settings )
|
||||||
|
{
|
||||||
|
mRendererVectorSettings = settings;
|
||||||
|
triggerRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsMeshLayer::setActiveScalarDataset( int index )
|
void QgsMeshLayer::setActiveScalarDataset( int index )
|
||||||
{
|
{
|
||||||
if ( index < 0 )
|
if ( index < 0 )
|
||||||
@ -136,8 +151,8 @@ void QgsMeshLayer::setActiveScalarDataset( int index )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT( dataProvider()->datasetCount() > index );
|
Q_ASSERT( dataProvider()->datasetCount() > index );
|
||||||
if ( dataProvider()->datasetHasScalarData( index ) )
|
// for vector datasets, we render magnitude
|
||||||
mActiveScalarDataset = index;
|
mActiveScalarDataset = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsMeshLayer::setActiveVectorDataset( int index )
|
void QgsMeshLayer::setActiveVectorDataset( int index )
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "qgsmaplayer.h"
|
#include "qgsmaplayer.h"
|
||||||
#include "qgsrendercontext.h"
|
#include "qgsrendercontext.h"
|
||||||
#include "qgsmeshdataprovider.h"
|
#include "qgsmeshdataprovider.h"
|
||||||
|
#include "qgsmeshrenderersettings.h"
|
||||||
|
|
||||||
class QgsMapLayerRenderer;
|
class QgsMapLayerRenderer;
|
||||||
class QgsSymbol;
|
class QgsSymbol;
|
||||||
@ -70,8 +71,6 @@ struct QgsMesh;
|
|||||||
* QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
|
* QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* Add datasets by adding them through data provider, \see QgsMeshDatasetSource::addDataset()
|
|
||||||
*
|
|
||||||
* \subsection mdal MDAL data provider (mdal)
|
* \subsection mdal MDAL data provider (mdal)
|
||||||
*
|
*
|
||||||
* Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
|
* Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
|
||||||
@ -123,32 +122,49 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
|
|||||||
bool readXml( const QDomNode &layer_node, QgsReadWriteContext &context ) override;
|
bool readXml( const QDomNode &layer_node, QgsReadWriteContext &context ) override;
|
||||||
bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
|
bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
|
||||||
|
|
||||||
//! Return the provider type for this layer
|
//! Returns the provider type for this layer
|
||||||
QString providerType() const;
|
QString providerType() const;
|
||||||
|
|
||||||
//! return native mesh (nullprt before rendering)
|
//! Returns native mesh (nullprt before rendering)
|
||||||
QgsMesh *nativeMesh() SIP_SKIP;
|
QgsMesh *nativeMesh() SIP_SKIP;
|
||||||
|
|
||||||
//! return triangular mesh (nullprt before rendering)
|
//! Returns triangular mesh (nullprt before rendering)
|
||||||
QgsTriangularMesh *triangularMesh() SIP_SKIP;
|
QgsTriangularMesh *triangularMesh() SIP_SKIP;
|
||||||
|
|
||||||
//! Returns a line symbol used for rendering native mesh.
|
//! Returns rendrer settings
|
||||||
QgsSymbol *nativeMeshSymbol();
|
QgsMeshRendererMeshSettings rendererNativeMeshSettings() const SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
//! Sets new rendering settings, triggers repaint
|
||||||
* Returns a line symbol used for rendering of triangular (derived) mesh.
|
void setRendererNativeMeshSettings( const QgsMeshRendererMeshSettings &settings );
|
||||||
* \see toggleTriangularMeshRendering
|
|
||||||
*/
|
|
||||||
QgsSymbol *triangularMeshSymbol();
|
|
||||||
|
|
||||||
//! Toggle rendering of triangular (derived) mesh. Off by default
|
//! Returns rendrer settings
|
||||||
void toggleTriangularMeshRendering( bool toggle );
|
QgsMeshRendererMeshSettings rendererTriangularMeshSettings() const SIP_FACTORY;
|
||||||
|
|
||||||
|
//! Sets new rendering settings, triggers repaint
|
||||||
|
void setRendererTriangularMeshSettings( const QgsMeshRendererMeshSettings &settings );
|
||||||
|
|
||||||
|
//! Returns rendrer settings
|
||||||
|
QgsMeshRendererScalarSettings rendererScalarSettings() const SIP_FACTORY;
|
||||||
|
|
||||||
|
//! Sets new rendering settings, triggers repaint
|
||||||
|
void setRendererScalarSettings( const QgsMeshRendererScalarSettings &settings );
|
||||||
|
|
||||||
|
//! Returns rendrer settings
|
||||||
|
QgsMeshRendererVectorSettings rendererVectorSettings() const SIP_FACTORY;
|
||||||
|
|
||||||
|
//! Sets new rendering settings, triggers repaint
|
||||||
|
void setRendererVectorSettings( const QgsMeshRendererVectorSettings &settings );
|
||||||
|
|
||||||
|
//! Sets active scalar dataset for rendering
|
||||||
void setActiveScalarDataset( int index = -1 );
|
void setActiveScalarDataset( int index = -1 );
|
||||||
void setActiveVectorDataset( int index = -1 );
|
//! Returns active scalar dataset
|
||||||
|
|
||||||
int activeScalarDataset() const { return mActiveScalarDataset; }
|
int activeScalarDataset() const { return mActiveScalarDataset; }
|
||||||
|
|
||||||
|
//! Sets active vector dataset for rendering. If dataset is not vector based, do nothing
|
||||||
|
void setActiveVectorDataset( int index = -1 );
|
||||||
|
//! Returns active vector dataset
|
||||||
|
int activeVectorDataset() const { return mActiveVectorDataset; }
|
||||||
|
|
||||||
private: // Private methods
|
private: // Private methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,7 +173,7 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
|
|||||||
bool isReadOnly() const override {return true;}
|
bool isReadOnly() const override {return true;}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind layer to a specific data provider
|
* Binds layer to a specific data provider
|
||||||
* \param provider provider key string, must match a valid QgsMeshDataProvider key. E.g. "mesh_memory", etc.
|
* \param provider provider key string, must match a valid QgsMeshDataProvider key. E.g. "mesh_memory", etc.
|
||||||
*/
|
*/
|
||||||
bool setDataProvider( QString const &provider );
|
bool setDataProvider( QString const &provider );
|
||||||
@ -182,16 +198,15 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
|
|||||||
//! Pointer to derived mesh structure
|
//! Pointer to derived mesh structure
|
||||||
std::unique_ptr<QgsTriangularMesh> mTriangularMesh;
|
std::unique_ptr<QgsTriangularMesh> mTriangularMesh;
|
||||||
|
|
||||||
//! rendering native mesh
|
QgsMeshRendererMeshSettings mRendererNativeMeshSettings;
|
||||||
std::unique_ptr<QgsSymbol> mNativeMeshSymbol;
|
QgsMeshRendererMeshSettings mRendererTriangularMeshSettings;
|
||||||
|
QgsMeshRendererScalarSettings mRendererScalarSettings;
|
||||||
|
QgsMeshRendererVectorSettings mRendererVectorSettings;
|
||||||
|
|
||||||
//! rendering triangular mesh
|
//! index of active scalar dataset; -1 if none
|
||||||
std::unique_ptr<QgsSymbol> mTriangularMeshSymbol;
|
|
||||||
|
|
||||||
//! TODO
|
|
||||||
int mActiveScalarDataset = -1;
|
int mActiveScalarDataset = -1;
|
||||||
|
|
||||||
//! TODO
|
//! index of active vector dataset; -1 if none
|
||||||
int mActiveVectorDataset = -1;
|
int mActiveVectorDataset = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,66 +21,22 @@
|
|||||||
|
|
||||||
#include "qgsrasterinterface.h"
|
#include "qgsrasterinterface.h"
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
|
#include "qgsmaptopixel.h"
|
||||||
|
|
||||||
// TODO: use QgsMapToPixel
|
static void bbox2rect(
|
||||||
class MapToPixel
|
const QgsMapToPixel &mtp,
|
||||||
|
const QSize &outputSize,
|
||||||
|
const QgsRectangle &bbox,
|
||||||
|
int &leftLim, int &rightLim, int &topLim, int &bottomLim )
|
||||||
{
|
{
|
||||||
public:
|
QgsPointXY ll = mtp.transform( bbox.xMinimum(), bbox.yMinimum() );
|
||||||
MapToPixel( double llX, double llY, double mupp, int rows )
|
QgsPointXY ur = mtp.transform( bbox.xMaximum(), bbox.yMaximum() );
|
||||||
: mLlX( llX ), mLlY( llY ), mMupp( mupp ), mRows( rows ) {}
|
topLim = std::max( int( ur.y() ), 0 );
|
||||||
|
bottomLim = std::min( int( ll.y() ), outputSize.height() - 1 );
|
||||||
MapToPixel( const MapToPixel &obj )
|
leftLim = std::max( int( ll.x() ), 0 );
|
||||||
: mLlX( obj.mLlX ), mLlY( obj.mLlY ), mMupp( obj.mMupp ), mRows( obj.mRows ) {}
|
rightLim = std::min( int( ur.x() ), outputSize.width() - 1 );
|
||||||
|
|
||||||
QPointF realToPixel( double rx, double ry ) const
|
|
||||||
{
|
|
||||||
double px = ( rx - mLlX ) / mMupp;
|
|
||||||
double py = mRows - ( ry - mLlY ) / mMupp;
|
|
||||||
return QPointF( px, py );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QPointF realToPixel( const QPointF &pt ) const
|
|
||||||
{
|
|
||||||
return realToPixel( pt.x(), pt.y() );
|
|
||||||
}
|
|
||||||
|
|
||||||
QPointF pixelToReal( double px, double py ) const
|
|
||||||
{
|
|
||||||
double rx = mLlX + ( px * mMupp );
|
|
||||||
double ry = mLlY + mMupp * ( mRows - py );
|
|
||||||
return QPointF( rx, ry );
|
|
||||||
}
|
|
||||||
|
|
||||||
QPointF pixelToReal( const QPointF &pt ) const
|
|
||||||
{
|
|
||||||
return pixelToReal( pt.x(), pt.y() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
double mLlX, mLlY;
|
|
||||||
double mMupp; // map units per pixel
|
|
||||||
double mRows; // (actually integer value)
|
|
||||||
};
|
|
||||||
|
|
||||||
void bbox2rect( const MapToPixel &mtp, const QSize &outputSize, const QgsRectangle &bbox, int &leftLim, int &rightLim, int &topLim, int &bottomLim )
|
|
||||||
{
|
|
||||||
QPoint ll = mtp.realToPixel( bbox.xMinimum(), bbox.yMinimum() ).toPoint();
|
|
||||||
QPoint ur = mtp.realToPixel( bbox.xMaximum(), bbox.yMaximum() ).toPoint();
|
|
||||||
topLim = std::max( ur.y(), 0 );
|
|
||||||
bottomLim = std::min( ll.y(), outputSize.height() - 1 );
|
|
||||||
leftLim = std::max( ll.x(), 0 );
|
|
||||||
rightLim = std::min( ur.x(), outputSize.width() - 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MapView
|
|
||||||
{
|
|
||||||
MapView(): mtp( 0, 0, 0, 0 ) {}
|
|
||||||
MapToPixel mtp;
|
|
||||||
QSize outputSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void lam_tol( double &lam )
|
static void lam_tol( double &lam )
|
||||||
{
|
{
|
||||||
const static double eps = 1e-6;
|
const static double eps = 1e-6;
|
||||||
@ -90,7 +46,7 @@ static void lam_tol( double &lam )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool E3T_physicalToBarycentric( QPointF pA, QPointF pB, QPointF pC, QPointF pP, double &lam1, double &lam2, double &lam3 )
|
static bool E3T_physicalToBarycentric( QPointF pA, QPointF pB, QPointF pC, QPointF pP, double &lam1, double &lam2, double &lam3 )
|
||||||
{
|
{
|
||||||
if ( pA == pB || pA == pC || pB == pC )
|
if ( pA == pB || pA == pC || pB == pC )
|
||||||
return false; // this is not a valid triangle!
|
return false; // this is not a valid triangle!
|
||||||
@ -148,24 +104,14 @@ double interpolateFromFacesData( const QPointF &p1, const QPointF &p2, const QPo
|
|||||||
|
|
||||||
QgsMeshLayerInterpolator::QgsMeshLayerInterpolator( const QgsTriangularMesh &m,
|
QgsMeshLayerInterpolator::QgsMeshLayerInterpolator( const QgsTriangularMesh &m,
|
||||||
const QVector<double> &datasetValues, bool dataIsOnVertices,
|
const QVector<double> &datasetValues, bool dataIsOnVertices,
|
||||||
const QgsRenderContext &context )
|
const QgsRenderContext &context,
|
||||||
|
const QSize &size )
|
||||||
: mTriangularMesh( m ),
|
: mTriangularMesh( m ),
|
||||||
mDatasetValues( datasetValues ),
|
mDatasetValues( datasetValues ),
|
||||||
mContext( context ),
|
mContext( context ),
|
||||||
mDataOnVertices( dataIsOnVertices )
|
mDataOnVertices( dataIsOnVertices ),
|
||||||
|
mOutputSize( size )
|
||||||
{
|
{
|
||||||
// figure out image size
|
|
||||||
QgsRectangle extent = mContext.extent(); // this is extent in layer's coordinate system - but we need it in map coordinate system
|
|
||||||
QgsMapToPixel mapToPixel = mContext.mapToPixel();
|
|
||||||
// TODO: what if OTF reprojection is used - see crayfish layer_renderer.py (_calculate_extent)
|
|
||||||
QgsPointXY topleft = mapToPixel.transform( extent.xMinimum(), extent.yMaximum() );
|
|
||||||
QgsPointXY bottomright = mapToPixel.transform( extent.xMaximum(), extent.yMinimum() );
|
|
||||||
int width = bottomright.x() - topleft.x();
|
|
||||||
int height = bottomright.y() - topleft.y();
|
|
||||||
|
|
||||||
mMapView.reset( new MapView() );
|
|
||||||
mMapView->mtp = MapToPixel( extent.xMinimum(), extent.yMinimum(), mapToPixel.mapUnitsPerPixel(), height );
|
|
||||||
mMapView->outputSize = QSize( width, height );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsMeshLayerInterpolator::~QgsMeshLayerInterpolator() = default;
|
QgsMeshLayerInterpolator::~QgsMeshLayerInterpolator() = default;
|
||||||
@ -177,7 +123,7 @@ QgsRasterInterface *QgsMeshLayerInterpolator::clone() const
|
|||||||
|
|
||||||
Qgis::DataType QgsMeshLayerInterpolator::dataType( int ) const
|
Qgis::DataType QgsMeshLayerInterpolator::dataType( int ) const
|
||||||
{
|
{
|
||||||
return Qgis::Float32;
|
return Qgis::Float64;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsMeshLayerInterpolator::bandCount() const
|
int QgsMeshLayerInterpolator::bandCount() const
|
||||||
@ -187,9 +133,9 @@ int QgsMeshLayerInterpolator::bandCount() const
|
|||||||
|
|
||||||
QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback )
|
QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback )
|
||||||
{
|
{
|
||||||
QgsRasterBlock *b = new QgsRasterBlock( Qgis::Float32, width, height );
|
QgsRasterBlock *b = new QgsRasterBlock( Qgis::Float64, width, height );
|
||||||
b->setIsNoData(); // assume initially that all values are unset
|
b->setIsNoData(); // assume initially that all values are unset
|
||||||
float *data = reinterpret_cast<float *>( b->bits() );
|
double *data = reinterpret_cast<double *>( b->bits() );
|
||||||
|
|
||||||
const QVector<QgsMeshFace> &triangels = mTriangularMesh.triangles();
|
const QVector<QgsMeshFace> &triangels = mTriangularMesh.triangles();
|
||||||
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
|
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
|
||||||
@ -217,16 +163,16 @@ QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent
|
|||||||
|
|
||||||
// Get the BBox of the element in pixels
|
// Get the BBox of the element in pixels
|
||||||
int topLim, bottomLim, leftLim, rightLim;
|
int topLim, bottomLim, leftLim, rightLim;
|
||||||
bbox2rect( mMapView->mtp, mMapView->outputSize, bbox, leftLim, rightLim, topLim, bottomLim );
|
bbox2rect( mContext.mapToPixel(), mOutputSize, bbox, leftLim, rightLim, topLim, bottomLim );
|
||||||
|
|
||||||
// interpolate in the bounding box of the face
|
// interpolate in the bounding box of the face
|
||||||
for ( int j = topLim; j <= bottomLim; j++ )
|
for ( int j = topLim; j <= bottomLim; j++ )
|
||||||
{
|
{
|
||||||
float *line = data + ( j * width );
|
double *line = data + ( j * width );
|
||||||
for ( int k = leftLim; k <= rightLim; k++ )
|
for ( int k = leftLim; k <= rightLim; k++ )
|
||||||
{
|
{
|
||||||
double val;
|
double val;
|
||||||
QPointF p = mMapView->mtp.pixelToReal( k, j );
|
QPointF p = mContext.mapToPixel().toMapCoordinates( k, j ).toQPointF();
|
||||||
if ( mDataOnVertices )
|
if ( mDataOnVertices )
|
||||||
val = interpolateFromVerticesData(
|
val = interpolateFromVerticesData(
|
||||||
QPointF( p1.x(), p1.y() ),
|
QPointF( p1.x(), p1.y() ),
|
||||||
|
@ -24,6 +24,7 @@ class QgsSymbol;
|
|||||||
#define SIP_NO_FILE
|
#define SIP_NO_FILE
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
#include "qgis.h"
|
#include "qgis.h"
|
||||||
|
|
||||||
@ -37,8 +38,6 @@ class QgsSymbol;
|
|||||||
|
|
||||||
///@cond PRIVATE
|
///@cond PRIVATE
|
||||||
|
|
||||||
struct MapView;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup core
|
* \ingroup core
|
||||||
* Interpolate mesh scalar dataset to raster block
|
* Interpolate mesh scalar dataset to raster block
|
||||||
@ -49,10 +48,12 @@ struct MapView;
|
|||||||
class QgsMeshLayerInterpolator : public QgsRasterInterface
|
class QgsMeshLayerInterpolator : public QgsRasterInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
//! Ctor
|
||||||
QgsMeshLayerInterpolator( const QgsTriangularMesh &m,
|
QgsMeshLayerInterpolator( const QgsTriangularMesh &m,
|
||||||
const QVector<double> &datasetValues,
|
const QVector<double> &datasetValues,
|
||||||
bool dataIsOnVertices,
|
bool dataIsOnVertices,
|
||||||
const QgsRenderContext &context );
|
const QgsRenderContext &context,
|
||||||
|
const QSize &size );
|
||||||
~QgsMeshLayerInterpolator() override;
|
~QgsMeshLayerInterpolator() override;
|
||||||
|
|
||||||
virtual QgsRasterInterface *clone() const override;
|
virtual QgsRasterInterface *clone() const override;
|
||||||
@ -64,8 +65,8 @@ class QgsMeshLayerInterpolator : public QgsRasterInterface
|
|||||||
const QgsTriangularMesh &mTriangularMesh;
|
const QgsTriangularMesh &mTriangularMesh;
|
||||||
const QVector<double> &mDatasetValues;
|
const QVector<double> &mDatasetValues;
|
||||||
const QgsRenderContext &mContext;
|
const QgsRenderContext &mContext;
|
||||||
std::unique_ptr<MapView> mMapView;
|
|
||||||
bool mDataOnVertices;
|
bool mDataOnVertices;
|
||||||
|
QSize mOutputSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
///@endcond
|
///@endcond
|
||||||
|
@ -27,10 +27,19 @@
|
|||||||
#include "qgssinglebandpseudocolorrenderer.h"
|
#include "qgssinglebandpseudocolorrenderer.h"
|
||||||
#include "qgsrastershader.h"
|
#include "qgsrastershader.h"
|
||||||
#include "qgsmeshlayerinterpolator.h"
|
#include "qgsmeshlayerinterpolator.h"
|
||||||
|
#include "qgsmeshvectorrenderer.h"
|
||||||
|
#include "qgsfillsymbollayer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context )
|
QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context )
|
||||||
: QgsMapLayerRenderer( layer->id() )
|
: QgsMapLayerRenderer( layer->id() )
|
||||||
|
, mFeedback( new QgsMeshLayerRendererFeedback )
|
||||||
, mContext( context )
|
, mContext( context )
|
||||||
|
, mRendererNativeMeshSettings( layer->rendererNativeMeshSettings() )
|
||||||
|
, mRendererTriangularMeshSettings( layer->rendererTriangularMeshSettings() )
|
||||||
|
, mRendererScalarSettings( layer-> rendererScalarSettings() )
|
||||||
|
, mRendererVectorSettings( layer-> rendererVectorSettings() )
|
||||||
{
|
{
|
||||||
// make copies for mesh data
|
// make copies for mesh data
|
||||||
Q_ASSERT( layer->nativeMesh() );
|
Q_ASSERT( layer->nativeMesh() );
|
||||||
@ -38,18 +47,45 @@ QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContex
|
|||||||
mNativeMesh = *( layer->nativeMesh() );
|
mNativeMesh = *( layer->nativeMesh() );
|
||||||
mTriangularMesh = *( layer->triangularMesh() );
|
mTriangularMesh = *( layer->triangularMesh() );
|
||||||
|
|
||||||
// make copies for symbols
|
createMeshSymbol( mNativeMeshSymbol, mRendererNativeMeshSettings );
|
||||||
if ( layer->nativeMeshSymbol() )
|
createMeshSymbol( mTriangularMeshSymbol, mRendererTriangularMeshSettings );
|
||||||
{
|
|
||||||
mNativeMeshSymbol.reset( layer->nativeMeshSymbol()->clone() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( layer->triangularMeshSymbol() )
|
|
||||||
{
|
|
||||||
mTriangularMeshSymbol.reset( layer->triangularMeshSymbol()->clone() );
|
|
||||||
}
|
|
||||||
|
|
||||||
copyScalarDatasetValues( layer );
|
copyScalarDatasetValues( layer );
|
||||||
|
copyVectorDatasetValues( layer );
|
||||||
|
|
||||||
|
calculateOutputSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsFeedback *QgsMeshLayerRenderer::feedback() const
|
||||||
|
{
|
||||||
|
return mFeedback.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayerRenderer::calculateOutputSize()
|
||||||
|
{
|
||||||
|
// figure out image size
|
||||||
|
QgsRectangle extent = mContext.extent(); // this is extent in layer's coordinate system - but we need it in map coordinate system
|
||||||
|
QgsMapToPixel mapToPixel = mContext.mapToPixel();
|
||||||
|
QgsPointXY topleft = mapToPixel.transform( extent.xMinimum(), extent.yMaximum() );
|
||||||
|
QgsPointXY bottomright = mapToPixel.transform( extent.xMaximum(), extent.yMinimum() );
|
||||||
|
int width = int( bottomright.x() - topleft.x() );
|
||||||
|
int height = int( bottomright.y() - topleft.y() );
|
||||||
|
mOutputSize = QSize( width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayerRenderer::createMeshSymbol( std::unique_ptr<QgsSymbol> &symbol,
|
||||||
|
const QgsMeshRendererMeshSettings &settings )
|
||||||
|
{
|
||||||
|
if ( settings.isEnabled() )
|
||||||
|
{
|
||||||
|
QgsSymbolLayerList l1;
|
||||||
|
l1 << new QgsSimpleFillSymbolLayer( Qt::white,
|
||||||
|
Qt::NoBrush,
|
||||||
|
settings.color(),
|
||||||
|
Qt::SolidLine,
|
||||||
|
settings.lineWidth() );
|
||||||
|
symbol.reset( new QgsFillSymbol( l1 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -58,39 +94,69 @@ void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
|
|||||||
int datasetIndex = layer->activeScalarDataset();
|
int datasetIndex = layer->activeScalarDataset();
|
||||||
if ( datasetIndex != -1 )
|
if ( datasetIndex != -1 )
|
||||||
{
|
{
|
||||||
mDataOnVertices = layer->dataProvider()->datasetIsOnVertices( datasetIndex );
|
mScalarDataOnVertices = layer->dataProvider()->datasetIsOnVertices( datasetIndex );
|
||||||
if ( mDataOnVertices )
|
int count;
|
||||||
|
if ( mScalarDataOnVertices )
|
||||||
|
count = mNativeMesh.vertices.count();
|
||||||
|
else
|
||||||
|
count = mNativeMesh.faces.count();
|
||||||
|
|
||||||
|
mScalarDatasetValues.resize( count );
|
||||||
|
for ( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
int count = mNativeMesh.vertices.count();
|
double v = layer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
|
||||||
mDatasetValues.resize( count );
|
mScalarDatasetValues[i] = v;
|
||||||
for ( int i = 0; i < count; ++i )
|
}
|
||||||
{
|
}
|
||||||
double v = layer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
|
}
|
||||||
mDatasetValues[i] = v;
|
|
||||||
}
|
void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
|
||||||
|
{
|
||||||
|
int datasetIndex = layer->activeVectorDataset();
|
||||||
|
if ( datasetIndex != -1 )
|
||||||
|
{
|
||||||
|
bool isScalar = layer->dataProvider()->datasetHasScalarData( datasetIndex );
|
||||||
|
if ( isScalar )
|
||||||
|
{
|
||||||
|
QgsDebugMsg( "Dataset has no vector values" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//on faces
|
mVectorDataOnVertices = layer->dataProvider()->datasetIsOnVertices( datasetIndex );
|
||||||
int count = mNativeMesh.faces.count();
|
int count;
|
||||||
mDatasetValues.resize( count );
|
if ( mVectorDataOnVertices )
|
||||||
|
count = mNativeMesh.vertices.count();
|
||||||
|
else
|
||||||
|
count = mNativeMesh.faces.count();
|
||||||
|
|
||||||
|
mVectorDatasetValuesX.resize( count );
|
||||||
|
mVectorDatasetValuesY.resize( count );
|
||||||
|
mVectorDatasetValuesMag.resize( count );
|
||||||
for ( int i = 0; i < count; ++i )
|
for ( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
double v = layer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
|
double x = layer->dataProvider()->datasetValue( datasetIndex, i ).x();
|
||||||
mDatasetValues[i] = v;
|
mVectorDatasetValuesX[i] = x;
|
||||||
|
|
||||||
|
double y = layer->dataProvider()->datasetValue( datasetIndex, i ).y();
|
||||||
|
mVectorDatasetValuesY[i] = y;
|
||||||
|
|
||||||
|
double mag = layer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
|
||||||
|
mVectorDatasetValuesMag[i] = mag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QgsMeshLayerRenderer::render()
|
bool QgsMeshLayerRenderer::render()
|
||||||
{
|
{
|
||||||
|
|
||||||
renderScalarDataset();
|
renderScalarDataset();
|
||||||
|
|
||||||
renderMesh( mNativeMeshSymbol, mNativeMesh.faces ); // native mesh
|
renderMesh( mNativeMeshSymbol, mNativeMesh.faces ); // native mesh
|
||||||
renderMesh( mTriangularMeshSymbol, mTriangularMesh.triangles() ); // triangular mesh
|
renderMesh( mTriangularMeshSymbol, mTriangularMesh.triangles() ); // triangular mesh
|
||||||
|
|
||||||
|
renderVectorDataset();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,37 +197,30 @@ void QgsMeshLayerRenderer::renderMesh( const std::unique_ptr<QgsSymbol> &symbol,
|
|||||||
|
|
||||||
void QgsMeshLayerRenderer::renderScalarDataset()
|
void QgsMeshLayerRenderer::renderScalarDataset()
|
||||||
{
|
{
|
||||||
if ( mDatasetValues.isEmpty() )
|
if ( mScalarDatasetValues.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// figure out image size
|
// do not render if magnitude is outside of the filtered range (if filtering is enabled)
|
||||||
QgsRectangle extent = mContext.extent(); // this is extent in layer's coordinate system - but we need it in map coordinate system
|
double vMin = mRendererScalarSettings.minValue();
|
||||||
QgsMapToPixel mapToPixel = mContext.mapToPixel();
|
if ( std::isnan( vMin ) )
|
||||||
// TODO: what if OTF reprojection is used - see crayfish layer_renderer.py (_calculate_extent)
|
vMin = *std::min_element( mScalarDatasetValues.constBegin(), mScalarDatasetValues.constEnd() );
|
||||||
QgsPointXY topleft = mapToPixel.transform( extent.xMinimum(), extent.yMaximum() );
|
|
||||||
QgsPointXY bottomright = mapToPixel.transform( extent.xMaximum(), extent.yMinimum() );
|
|
||||||
int width = bottomright.x() - topleft.x();
|
|
||||||
int height = bottomright.y() - topleft.y();
|
|
||||||
|
|
||||||
double vMin = mDatasetValues[0], vMax = mDatasetValues[0];
|
|
||||||
for ( int i = 1; i < mDatasetValues.count(); ++i )
|
double vMax = mRendererScalarSettings.maxValue();
|
||||||
{
|
if ( std::isnan( vMax ) )
|
||||||
double v = mDatasetValues[i];
|
vMax = *std::max_element( mScalarDatasetValues.constBegin(), mScalarDatasetValues.constEnd() );
|
||||||
if ( v < vMin ) vMin = v;
|
|
||||||
if ( v > vMax ) vMax = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QgsColorRampShader::ColorRampItem> lst;
|
QList<QgsColorRampShader::ColorRampItem> lst;
|
||||||
lst << QgsColorRampShader::ColorRampItem( vMin, Qt::red, QString::number( vMin ) );
|
lst << QgsColorRampShader::ColorRampItem( vMin, mRendererScalarSettings.minColor(), QString::number( vMin ) );
|
||||||
lst << QgsColorRampShader::ColorRampItem( vMax, Qt::blue, QString::number( vMax ) );
|
lst << QgsColorRampShader::ColorRampItem( vMax, mRendererScalarSettings.maxColor(), QString::number( vMax ) );
|
||||||
|
|
||||||
QgsColorRampShader *fcn = new QgsColorRampShader( vMin, vMax );
|
QgsColorRampShader *fcn = new QgsColorRampShader( vMin, vMax );
|
||||||
fcn->setColorRampItemList( lst );
|
fcn->setColorRampItemList( lst );
|
||||||
QgsRasterShader *sh = new QgsRasterShader( 0, 1000 );
|
QgsRasterShader *sh = new QgsRasterShader( vMin, vMax );
|
||||||
sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
|
sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
|
||||||
QgsMeshLayerInterpolator interpolator( mTriangularMesh, mDatasetValues, mDataOnVertices, mContext );
|
QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarDataOnVertices, mContext, mOutputSize );
|
||||||
QgsSingleBandPseudoColorRenderer r( &interpolator, 0, sh ); // takes ownership of sh
|
QgsSingleBandPseudoColorRenderer r( &interpolator, 0, sh ); // takes ownership of sh
|
||||||
QgsRasterBlock *bl = r.block( 0, extent, width, height ); // TODO: feedback
|
QgsRasterBlock *bl = r.block( 0, mContext.extent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() );
|
||||||
Q_ASSERT( bl );
|
Q_ASSERT( bl );
|
||||||
|
|
||||||
QImage img = bl->image();
|
QImage img = bl->image();
|
||||||
@ -169,3 +228,18 @@ void QgsMeshLayerRenderer::renderScalarDataset()
|
|||||||
mContext.painter()->drawImage( 0, 0, img );
|
mContext.painter()->drawImage( 0, 0, img );
|
||||||
delete bl;
|
delete bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayerRenderer::renderVectorDataset()
|
||||||
|
{
|
||||||
|
if ( mVectorDatasetValuesX.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( mVectorDatasetValuesX.size() != mVectorDatasetValuesY.size() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QgsMeshVectorRenderer renderer( mTriangularMesh,
|
||||||
|
mVectorDatasetValuesX, mVectorDatasetValuesY, mVectorDatasetValuesMag,
|
||||||
|
mVectorDataOnVertices, mRendererVectorSettings, mContext, mOutputSize );
|
||||||
|
|
||||||
|
renderer.draw();
|
||||||
|
}
|
||||||
|
@ -28,8 +28,24 @@ class QgsSymbol;
|
|||||||
#include "qgis.h"
|
#include "qgis.h"
|
||||||
|
|
||||||
#include "qgsmaplayerrenderer.h"
|
#include "qgsmaplayerrenderer.h"
|
||||||
|
#include "qgsrasterinterface.h"
|
||||||
#include "qgsrendercontext.h"
|
#include "qgsrendercontext.h"
|
||||||
#include "qgstriangularmesh.h"
|
#include "qgstriangularmesh.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgssymbol.h"
|
||||||
|
|
||||||
|
///@cond PRIVATE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feedback for mesh layer rendering - right now derived from raster block feedback so that we
|
||||||
|
* can pass it to block reading in the raster interface.
|
||||||
|
*/
|
||||||
|
class QgsMeshLayerRendererFeedback : public QgsRasterBlockFeedback
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
///@endcond
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup core
|
* \ingroup core
|
||||||
@ -43,16 +59,23 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
|
|||||||
public:
|
public:
|
||||||
//! Ctor
|
//! Ctor
|
||||||
QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context );
|
QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context );
|
||||||
|
|
||||||
~QgsMeshLayerRenderer() override = default;
|
~QgsMeshLayerRenderer() override = default;
|
||||||
|
QgsFeedback *feedback() const override;
|
||||||
bool render() override;
|
bool render() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderMesh( const std::unique_ptr<QgsSymbol> &symbol, const QVector<QgsMeshFace> &faces );
|
void renderMesh( const std::unique_ptr<QgsSymbol> &symbol, const QVector<QgsMeshFace> &faces );
|
||||||
void renderScalarDataset();
|
void renderScalarDataset();
|
||||||
|
void renderVectorDataset();
|
||||||
void copyScalarDatasetValues( QgsMeshLayer *layer );
|
void copyScalarDatasetValues( QgsMeshLayer *layer );
|
||||||
|
void copyVectorDatasetValues( QgsMeshLayer *layer );
|
||||||
|
void createMeshSymbol( std::unique_ptr<QgsSymbol> &symbol, const QgsMeshRendererMeshSettings &settings );
|
||||||
|
void calculateOutputSize();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
//! feedback class for cancelation
|
||||||
|
std::unique_ptr<QgsMeshLayerRendererFeedback> mFeedback;
|
||||||
|
|
||||||
// copy from mesh layer
|
// copy from mesh layer
|
||||||
QgsMesh mNativeMesh;
|
QgsMesh mNativeMesh;
|
||||||
|
|
||||||
@ -60,8 +83,14 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
|
|||||||
QgsTriangularMesh mTriangularMesh;
|
QgsTriangularMesh mTriangularMesh;
|
||||||
|
|
||||||
// copy of the scalar dataset
|
// copy of the scalar dataset
|
||||||
QVector<double> mDatasetValues;
|
QVector<double> mScalarDatasetValues;
|
||||||
bool mDataOnVertices;
|
bool mScalarDataOnVertices;
|
||||||
|
|
||||||
|
// copy of the vector dataset
|
||||||
|
QVector<double> mVectorDatasetValuesX;
|
||||||
|
QVector<double> mVectorDatasetValuesY;
|
||||||
|
QVector<double> mVectorDatasetValuesMag;
|
||||||
|
bool mVectorDataOnVertices;
|
||||||
|
|
||||||
// copy from mesh layer
|
// copy from mesh layer
|
||||||
std::unique_ptr<QgsSymbol> mNativeMeshSymbol = nullptr;
|
std::unique_ptr<QgsSymbol> mNativeMeshSymbol = nullptr;
|
||||||
@ -71,6 +100,15 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
|
|||||||
|
|
||||||
// rendering context
|
// rendering context
|
||||||
QgsRenderContext &mContext;
|
QgsRenderContext &mContext;
|
||||||
|
|
||||||
|
// copy of rendering settings
|
||||||
|
QgsMeshRendererMeshSettings mRendererNativeMeshSettings;
|
||||||
|
QgsMeshRendererMeshSettings mRendererTriangularMeshSettings;
|
||||||
|
QgsMeshRendererScalarSettings mRendererScalarSettings;
|
||||||
|
QgsMeshRendererVectorSettings mRendererVectorSettings;
|
||||||
|
|
||||||
|
// output screen size
|
||||||
|
QSize mOutputSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class QgsMeshMemoryDataProvider: public QgsMeshDataProvider
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add dataset to a mesh in-memory data provider from data string
|
* Adds dataset to a mesh in-memory data provider from data string
|
||||||
*
|
*
|
||||||
* Data string constains simple definition of datasets
|
* Data string constains simple definition of datasets
|
||||||
* Each entry is separated by "\n" sign and section deliminer "---"
|
* Each entry is separated by "\n" sign and section deliminer "---"
|
||||||
|
198
src/core/mesh/qgsmeshrenderersettings.cpp
Normal file
198
src/core/mesh/qgsmeshrenderersettings.cpp
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshrenderersettings.cpp
|
||||||
|
---------------------------
|
||||||
|
begin : May 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 "qgsmeshrenderersettings.h"
|
||||||
|
|
||||||
|
bool QgsMeshRendererMeshSettings::isEnabled() const
|
||||||
|
{
|
||||||
|
return mEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererMeshSettings::setEnabled( bool on )
|
||||||
|
{
|
||||||
|
mEnabled = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererMeshSettings::lineWidth() const
|
||||||
|
{
|
||||||
|
return mLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererMeshSettings::setLineWidth( double lineWidth )
|
||||||
|
{
|
||||||
|
mLineWidth = lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor QgsMeshRendererMeshSettings::color() const
|
||||||
|
{
|
||||||
|
return mColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererMeshSettings::setColor( const QColor &color )
|
||||||
|
{
|
||||||
|
mColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor QgsMeshRendererScalarSettings::maxColor() const
|
||||||
|
{
|
||||||
|
return mMaxColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererScalarSettings::setMaxColor( const QColor &maxColor )
|
||||||
|
{
|
||||||
|
mMaxColor = maxColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor QgsMeshRendererScalarSettings::minColor() const
|
||||||
|
{
|
||||||
|
return mMinColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererScalarSettings::setMinColor( const QColor &minColor )
|
||||||
|
{
|
||||||
|
mMinColor = minColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererScalarSettings::minValue() const
|
||||||
|
{
|
||||||
|
return mMinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererScalarSettings::setMinValue( double minValue )
|
||||||
|
{
|
||||||
|
mMinValue = minValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererScalarSettings::maxValue() const
|
||||||
|
{
|
||||||
|
return mMaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererScalarSettings::setMaxValue( double maxValue )
|
||||||
|
{
|
||||||
|
mMaxValue = maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::lineWidth() const
|
||||||
|
{
|
||||||
|
return mLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setLineWidth( double lineWidth )
|
||||||
|
{
|
||||||
|
mLineWidth = lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor QgsMeshRendererVectorSettings::color() const
|
||||||
|
{
|
||||||
|
return mColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setColor( const QColor &vectorColor )
|
||||||
|
{
|
||||||
|
mColor = vectorColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::filterMin() const
|
||||||
|
{
|
||||||
|
return mFilterMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setFilterMin( double vectorFilterMin )
|
||||||
|
{
|
||||||
|
mFilterMin = vectorFilterMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::filterMax() const
|
||||||
|
{
|
||||||
|
return mFilterMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setFilterMax( double vectorFilterMax )
|
||||||
|
{
|
||||||
|
mFilterMax = vectorFilterMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshRendererVectorSettings::VectorRenderingType QgsMeshRendererVectorSettings::shaftLengthMethod() const
|
||||||
|
{
|
||||||
|
return mShaftLengthMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setShaftLengthMethod( const QgsMeshRendererVectorSettings::VectorRenderingType &shaftLengthMethod )
|
||||||
|
{
|
||||||
|
mShaftLengthMethod = shaftLengthMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::minShaftLength() const
|
||||||
|
{
|
||||||
|
return mMinShaftLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setMinShaftLength( double minShaftLength )
|
||||||
|
{
|
||||||
|
mMinShaftLength = minShaftLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::maxShaftLength() const
|
||||||
|
{
|
||||||
|
return mMaxShaftLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setMaxShaftLength( double maxShaftLength )
|
||||||
|
{
|
||||||
|
mMaxShaftLength = maxShaftLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::scaleFactor() const
|
||||||
|
{
|
||||||
|
return mScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setScaleFactor( double scaleFactor )
|
||||||
|
{
|
||||||
|
mScaleFactor = scaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::fixedShaftLength() const
|
||||||
|
{
|
||||||
|
return mFixedShaftLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setFixedShaftLength( double fixedShaftLength )
|
||||||
|
{
|
||||||
|
mFixedShaftLength = fixedShaftLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::arrowHeadWidthRatio() const
|
||||||
|
{
|
||||||
|
return mArrowHeadWidthRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setArrowHeadWidthRatio( double vectorHeadWidthRatio )
|
||||||
|
{
|
||||||
|
mArrowHeadWidthRatio = vectorHeadWidthRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsMeshRendererVectorSettings::arrowHeadLengthRatio() const
|
||||||
|
{
|
||||||
|
return mArrowHeadLengthRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshRendererVectorSettings::setArrowHeadLengthRatio( double vectorHeadLengthRatio )
|
||||||
|
{
|
||||||
|
mArrowHeadLengthRatio = vectorHeadLengthRatio;
|
||||||
|
}
|
254
src/core/mesh/qgsmeshrenderersettings.h
Normal file
254
src/core/mesh/qgsmeshrenderersettings.h
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshrenderersettings.h
|
||||||
|
-------------------------
|
||||||
|
begin : May 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 QGSMESHRENDERERSETTINGS_H
|
||||||
|
#define QGSMESHRENDERERSETTINGS_H
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgis.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
*
|
||||||
|
* Represents a mesh renderer settings for mesh object
|
||||||
|
*
|
||||||
|
* \note The API is considered EXPERIMENTAL and can be changed without a notice
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsMeshRendererMeshSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Returns whether mesh structure rendering is enabled
|
||||||
|
bool isEnabled() const;
|
||||||
|
//! Sets whether mesh structure rendering is enabled
|
||||||
|
void setEnabled( bool enabled );
|
||||||
|
|
||||||
|
//! Returns line width used for rendering (in millimeters)
|
||||||
|
double lineWidth() const;
|
||||||
|
//! Sets line width used for rendering (in millimeters)
|
||||||
|
void setLineWidth( double lineWidth );
|
||||||
|
|
||||||
|
//! Returns color used for rendering
|
||||||
|
QColor color() const;
|
||||||
|
//! Sets color used for rendering of the mesh
|
||||||
|
void setColor( const QColor &color );
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mEnabled = false;
|
||||||
|
double mLineWidth = DEFAULT_LINE_WIDTH;
|
||||||
|
QColor mColor = Qt::black;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
*
|
||||||
|
* Represents a mesh renderer settings for scalar datasets
|
||||||
|
*
|
||||||
|
* \note The API is considered EXPERIMENTAL and can be changed without a notice
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsMeshRendererScalarSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Returns color representing maximum scalar value in the dataset
|
||||||
|
QColor maxColor() const;
|
||||||
|
//! Sets color representing maximum scalar value in the dataset
|
||||||
|
void setMaxColor( const QColor &maxColor );
|
||||||
|
|
||||||
|
//! Returns color representing minimum scalar value in the dataset
|
||||||
|
QColor minColor() const;
|
||||||
|
//! Sets color representing maximum scalar value in the dataset
|
||||||
|
void setMinColor( const QColor &minColor );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns min scalar value that represents minColor()
|
||||||
|
*
|
||||||
|
* if set to numerical_limits<double>::quiet_NaN(), value for minColor() is
|
||||||
|
* taken from minimum value of active scalar dataset
|
||||||
|
*/
|
||||||
|
double minValue() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets min scalar value that represents minColor()
|
||||||
|
* \see QgsMeshRendererScalarSettings::minValue()
|
||||||
|
*/
|
||||||
|
void setMinValue( double minValue );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max scalar value that represents maxColor()
|
||||||
|
*
|
||||||
|
* if set to numerical_limits<double>::quiet_NaN(), value for maxColor() is
|
||||||
|
* taken from maximum value of active scalar dataset
|
||||||
|
*/
|
||||||
|
double maxValue() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets min scalar value that represents minColor()
|
||||||
|
* \see QgsMeshRendererScalarSettings::maxValue()
|
||||||
|
*/
|
||||||
|
void setMaxValue( double maxValue );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QColor mMaxColor = QColor::fromRgb( 255, 0, 0 );
|
||||||
|
QColor mMinColor = QColor::fromRgb( 0, 0, 255 );
|
||||||
|
double mMaxValue = std::numeric_limits<double>::quiet_NaN(); //disabled
|
||||||
|
double mMinValue = std::numeric_limits<double>::quiet_NaN(); //disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
*
|
||||||
|
* Represents a mesh renderer settings for vector datasets
|
||||||
|
*
|
||||||
|
* \note The API is considered EXPERIMENTAL and can be changed without a notice
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsMeshRendererVectorSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Algorithm how to transform vector magnitude to length of arrow on the device in pixels
|
||||||
|
enum VectorRenderingType
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale vector magnitude linearly to fit in range of vectorFilterMin() and vectorFilterMax()
|
||||||
|
*/
|
||||||
|
MinMax = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale vector magnitude by factor scaleFactor()
|
||||||
|
*/
|
||||||
|
Scaled,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use fixed length fixedShaftLength() regardless of vector's magnitude
|
||||||
|
*/
|
||||||
|
Fixed
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Returns line width of the arrow (in millimeters)
|
||||||
|
double lineWidth() const;
|
||||||
|
//! Sets line width of the arrow in pixels (in millimeters)
|
||||||
|
void setLineWidth( double lineWidth );
|
||||||
|
|
||||||
|
//! Returns color used for drawing arrows
|
||||||
|
QColor color() const;
|
||||||
|
//! Sets color used for drawing arrows
|
||||||
|
void setColor( const QColor &color );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns filter value for vector magnitudes.
|
||||||
|
*
|
||||||
|
* If magnitude of the vector is lower than this value, the vector is not
|
||||||
|
* drawn. -1 represents that filtering is not active.
|
||||||
|
*/
|
||||||
|
double filterMin() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets filter value for vector magnitudes.
|
||||||
|
* \see QgsMeshRendererVectorSettings::vectorFilterMin()
|
||||||
|
*/
|
||||||
|
void setFilterMin( double filterMin );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns filter value for vector magnitudes.
|
||||||
|
*
|
||||||
|
* If magnitude of the vector is higher than this value, the vector is not
|
||||||
|
* drawn. -1 represents that filtering is not active.
|
||||||
|
*/
|
||||||
|
double filterMax() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets filter value for vector magnitudes.
|
||||||
|
* \see QgsMeshRendererVectorSettings::vectorFilterMax()
|
||||||
|
*/
|
||||||
|
void setFilterMax( double filterMax );
|
||||||
|
|
||||||
|
//! Returns method used for drawing arrows
|
||||||
|
QgsMeshRendererVectorSettings::VectorRenderingType shaftLengthMethod() const;
|
||||||
|
//! Sets method used for drawing arrows
|
||||||
|
void setShaftLengthMethod( const QgsMeshRendererVectorSettings::VectorRenderingType &shaftLengthMethod );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns mininimum shaft length (in millimeters)
|
||||||
|
*
|
||||||
|
* Only for QgsMeshRendererVectorSettings::ArrowType::MinMax
|
||||||
|
*/
|
||||||
|
double minShaftLength() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets mininimum shaft length (in millimeters)
|
||||||
|
*
|
||||||
|
* Only for QgsMeshRendererVectorSettings::ArrowType::MinMax
|
||||||
|
*/
|
||||||
|
void setMinShaftLength( double minShaftLength );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns maximum shaft length (in millimeters)
|
||||||
|
*
|
||||||
|
* Only for QgsMeshRendererVectorSettings::ArrowType::MinMax
|
||||||
|
*/
|
||||||
|
double maxShaftLength() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets maximum shaft length (in millimeters)
|
||||||
|
*
|
||||||
|
* Only for QgsMeshRendererVectorSettings::ArrowType::MinMax
|
||||||
|
*/
|
||||||
|
void setMaxShaftLength( double maxShaftLength );
|
||||||
|
|
||||||
|
//! Returns scale factor. Only for QgsMeshRendererVectorSettings::ArrowType::Scaled
|
||||||
|
double scaleFactor() const;
|
||||||
|
//! Sets scale factor. Only for QgsMeshRendererVectorSettings::ArrowType::Scaled
|
||||||
|
void setScaleFactor( double scaleFactor );
|
||||||
|
|
||||||
|
//! Returns fixed arrow length (in millimeters). Only for QgsMeshRendererVectorSettings::ArrowType::Fixed
|
||||||
|
double fixedShaftLength() const;
|
||||||
|
//! Sets fixed length (in millimeters). Only for QgsMeshRendererVectorSettings::ArrowType::Fixed
|
||||||
|
void setFixedShaftLength( double fixedShaftLength );
|
||||||
|
|
||||||
|
//! Returns ratio of the head width of the arrow (range 0-1)
|
||||||
|
double arrowHeadWidthRatio() const;
|
||||||
|
//! Sets ratio of the head width of the arrow (range 0-1)
|
||||||
|
void setArrowHeadWidthRatio( double arrowHeadWidthRatio );
|
||||||
|
|
||||||
|
//! Returns ratio of the head length of the arrow (range 0-1)
|
||||||
|
double arrowHeadLengthRatio() const;
|
||||||
|
//! Sets ratio of the head length of the arrow (range 0-1)
|
||||||
|
void setArrowHeadLengthRatio( double arrowHeadLengthRatio );
|
||||||
|
|
||||||
|
private:
|
||||||
|
double mLineWidth = DEFAULT_LINE_WIDTH; //in milimeters
|
||||||
|
QColor mColor = Qt::black;
|
||||||
|
double mFilterMin = -1; //disabled
|
||||||
|
double mFilterMax = -1; //disabled
|
||||||
|
QgsMeshRendererVectorSettings::VectorRenderingType mShaftLengthMethod = QgsMeshRendererVectorSettings::VectorRenderingType::MinMax;
|
||||||
|
double mMinShaftLength = 0.8; //in milimeters
|
||||||
|
double mMaxShaftLength = 10; //in milimeters
|
||||||
|
double mScaleFactor = 10;
|
||||||
|
double mFixedShaftLength = 20; //in milimeters
|
||||||
|
double mArrowHeadWidthRatio = 0.15;
|
||||||
|
double mArrowHeadLengthRatio = 0.40;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QGSMESHRENDERERSETTINGS_H
|
264
src/core/mesh/qgsmeshvectorrenderer.cpp
Normal file
264
src/core/mesh/qgsmeshvectorrenderer.cpp
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshvectorrenderer.cpp
|
||||||
|
-------------------------
|
||||||
|
begin : May 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 "qgsmeshvectorrenderer.h"
|
||||||
|
#include "qgsrendercontext.h"
|
||||||
|
#include "qgscoordinatetransform.h"
|
||||||
|
#include "qgsmaptopixel.h"
|
||||||
|
#include "qgsunittypes.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <QPen>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
inline double mag( double input )
|
||||||
|
{
|
||||||
|
if ( input < 0.0 )
|
||||||
|
{
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshVectorRenderer::QgsMeshVectorRenderer( const QgsTriangularMesh &m,
|
||||||
|
const QVector<double> &datasetValuesX,
|
||||||
|
const QVector<double> &datasetValuesY,
|
||||||
|
const QVector<double> &datasetValuesMag,
|
||||||
|
bool dataIsOnVertices,
|
||||||
|
const QgsMeshRendererVectorSettings &settings,
|
||||||
|
QgsRenderContext &context, const QSize &size )
|
||||||
|
: mTriangularMesh( m )
|
||||||
|
, mDatasetValuesX( datasetValuesX )
|
||||||
|
, mDatasetValuesY( datasetValuesY )
|
||||||
|
, mDatasetValuesMag( datasetValuesMag )
|
||||||
|
, mContext( context )
|
||||||
|
, mCfg( settings )
|
||||||
|
, mDataOnVertices( dataIsOnVertices )
|
||||||
|
, mOutputSize( size )
|
||||||
|
{
|
||||||
|
mMinX = *std::min_element( datasetValuesX.constBegin(), datasetValuesX.constEnd() );
|
||||||
|
mMaxX = *std::max_element( datasetValuesX.constBegin(), datasetValuesX.constEnd() );
|
||||||
|
mMinY = *std::min_element( datasetValuesY.constBegin(), datasetValuesY.constEnd() );
|
||||||
|
mMaxY = *std::max_element( datasetValuesY.constBegin(), datasetValuesY.constEnd() );
|
||||||
|
mMinMag = *std::min_element( mDatasetValuesMag.constBegin(), mDatasetValuesMag.constEnd() );
|
||||||
|
mMaxMag = *std::max_element( mDatasetValuesMag.constBegin(), mDatasetValuesMag.constEnd() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshVectorRenderer::~QgsMeshVectorRenderer() = default;
|
||||||
|
|
||||||
|
void QgsMeshVectorRenderer::draw()
|
||||||
|
{
|
||||||
|
// Set up the render configuration options
|
||||||
|
QPainter *p = mContext.painter();
|
||||||
|
p->setRenderHint( QPainter::Antialiasing );
|
||||||
|
QPen pen = p->pen();
|
||||||
|
pen.setCapStyle( Qt::FlatCap );
|
||||||
|
pen.setJoinStyle( Qt::MiterJoin );
|
||||||
|
|
||||||
|
double penWidth = mContext.convertToPainterUnits( mCfg.lineWidth(),
|
||||||
|
QgsUnitTypes::RenderUnit::RenderMillimeters );
|
||||||
|
pen.setWidthF( penWidth );
|
||||||
|
pen.setColor( mCfg.color() );
|
||||||
|
p->setPen( pen );
|
||||||
|
|
||||||
|
if ( mDataOnVertices )
|
||||||
|
drawVectorDataOnVertices();
|
||||||
|
else
|
||||||
|
drawVectorDataOnFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshVectorRenderer::calcVectorLineEnd(
|
||||||
|
QgsPointXY &lineEnd,
|
||||||
|
double &vectorLength,
|
||||||
|
double &cosAlpha,
|
||||||
|
double &sinAlpha, //out
|
||||||
|
const QgsPointXY &lineStart,
|
||||||
|
double xVal,
|
||||||
|
double yVal,
|
||||||
|
double magnitude //in
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// return true on error
|
||||||
|
|
||||||
|
if ( xVal == 0.0 && yVal == 0.0 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// do not render if magnitude is outside of the filtered range (if filtering is enabled)
|
||||||
|
if ( mCfg.filterMin() >= 0 && magnitude < mCfg.filterMin() )
|
||||||
|
return true;
|
||||||
|
if ( mCfg.filterMax() >= 0 && magnitude > mCfg.filterMax() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Determine the angle of the vector, counter-clockwise, from east
|
||||||
|
// (and associated trigs)
|
||||||
|
double vectorAngle = -1.0 * atan( ( -1.0 * yVal ) / xVal );
|
||||||
|
cosAlpha = cos( vectorAngle ) * mag( xVal );
|
||||||
|
sinAlpha = sin( vectorAngle ) * mag( xVal );
|
||||||
|
|
||||||
|
// Now determine the X and Y distances of the end of the line from the start
|
||||||
|
double xDist = 0.0;
|
||||||
|
double yDist = 0.0;
|
||||||
|
switch ( mCfg.shaftLengthMethod() )
|
||||||
|
{
|
||||||
|
case QgsMeshRendererVectorSettings::VectorRenderingType::MinMax:
|
||||||
|
{
|
||||||
|
double minShaftLength = mContext.convertToPainterUnits( mCfg.minShaftLength(),
|
||||||
|
QgsUnitTypes::RenderUnit::RenderMillimeters );
|
||||||
|
double maxShaftLength = mContext.convertToPainterUnits( mCfg.maxShaftLength(),
|
||||||
|
QgsUnitTypes::RenderUnit::RenderMillimeters );
|
||||||
|
double minVal = mMinMag;
|
||||||
|
double maxVal = mMaxMag;
|
||||||
|
double k = ( magnitude - minVal ) / ( maxVal - minVal );
|
||||||
|
double L = minShaftLength + k * ( maxShaftLength - minShaftLength );
|
||||||
|
xDist = cosAlpha * L;
|
||||||
|
yDist = sinAlpha * L;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QgsMeshRendererVectorSettings::VectorRenderingType::Scaled:
|
||||||
|
{
|
||||||
|
double scaleFactor = mCfg.scaleFactor();
|
||||||
|
xDist = scaleFactor * xVal;
|
||||||
|
yDist = scaleFactor * yVal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QgsMeshRendererVectorSettings::VectorRenderingType::Fixed:
|
||||||
|
{
|
||||||
|
// We must be using a fixed length
|
||||||
|
double fixedShaftLength = mContext.convertToPainterUnits( mCfg.fixedShaftLength(),
|
||||||
|
QgsUnitTypes::RenderUnit::RenderMillimeters );
|
||||||
|
xDist = cosAlpha * fixedShaftLength;
|
||||||
|
yDist = sinAlpha * fixedShaftLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip the Y axis (pixel vs real-world axis)
|
||||||
|
yDist *= -1.0;
|
||||||
|
|
||||||
|
if ( qAbs( xDist ) < 1 && qAbs( yDist ) < 1 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Determine the line coords
|
||||||
|
lineEnd = QgsPointXY( lineStart.x() + xDist,
|
||||||
|
lineStart.y() + yDist );
|
||||||
|
|
||||||
|
vectorLength = sqrt( xDist * xDist + yDist * yDist );
|
||||||
|
|
||||||
|
// Check to see if any of the coords are outside the QImage area, if so, skip the whole vector
|
||||||
|
if ( lineStart.x() < 0 || lineStart.x() > mOutputSize.width() ||
|
||||||
|
lineStart.y() < 0 || lineStart.y() > mOutputSize.height() ||
|
||||||
|
lineEnd.x() < 0 || lineEnd.x() > mOutputSize.width() ||
|
||||||
|
lineEnd.y() < 0 || lineEnd.y() > mOutputSize.height() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false; //success
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QgsMeshVectorRenderer::drawVectorDataOnVertices()
|
||||||
|
{
|
||||||
|
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
|
||||||
|
|
||||||
|
// currently expecting that triangulation does not add any new extra vertices on the way
|
||||||
|
Q_ASSERT( mDatasetValuesMag.count() == vertices.count() );
|
||||||
|
|
||||||
|
for ( int i = 0; i < vertices.size(); ++i )
|
||||||
|
{
|
||||||
|
const QgsMeshVertex &vertex = vertices.at( i );
|
||||||
|
//if (!nodeInsideView(nodeIndex))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
double xVal = mDatasetValuesX[i];
|
||||||
|
double yVal = mDatasetValuesY[i];
|
||||||
|
double V = mDatasetValuesMag[i]; // pre-calculated magnitude
|
||||||
|
QgsPointXY lineStart = mContext.mapToPixel().transform( vertex.x(), vertex.y() );
|
||||||
|
|
||||||
|
drawVectorArrow( lineStart, xVal, yVal, V );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshVectorRenderer::drawVectorDataOnFaces()
|
||||||
|
{
|
||||||
|
const QVector<QgsMeshVertex> ¢roids = mTriangularMesh.centroids();
|
||||||
|
|
||||||
|
for ( int i = 0; i < centroids.count(); i++ )
|
||||||
|
{
|
||||||
|
//if (elemOutsideView(elemIndex))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
QgsPointXY center = centroids.at( i );
|
||||||
|
double xVal = mDatasetValuesX[i];
|
||||||
|
double yVal = mDatasetValuesY[i];
|
||||||
|
double V = mDatasetValuesMag[i]; // pre-calculated magnitude
|
||||||
|
QgsPointXY lineStart = mContext.mapToPixel().transform( center.x(), center.y() );
|
||||||
|
|
||||||
|
drawVectorArrow( lineStart, xVal, yVal, V );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QgsMeshVectorRenderer::drawVectorArrow( const QgsPointXY &lineStart, double xVal, double yVal, double magnitude )
|
||||||
|
{
|
||||||
|
QgsPointXY lineEnd;
|
||||||
|
double vectorLength;
|
||||||
|
double cosAlpha, sinAlpha;
|
||||||
|
if ( calcVectorLineEnd( lineEnd, vectorLength, cosAlpha, sinAlpha,
|
||||||
|
lineStart, xVal, yVal, magnitude ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make a set of vector head coordinates that we will place at the end of each vector,
|
||||||
|
// scale, translate and rotate.
|
||||||
|
QgsPointXY vectorHeadPoints[3];
|
||||||
|
QVector<QPointF> finalVectorHeadPoints( 3 );
|
||||||
|
|
||||||
|
double vectorHeadWidthRatio = mCfg.arrowHeadWidthRatio();
|
||||||
|
double vectorHeadLengthRatio = mCfg.arrowHeadLengthRatio();
|
||||||
|
|
||||||
|
// First head point: top of ->
|
||||||
|
vectorHeadPoints[0].setX( -1.0 * vectorHeadLengthRatio );
|
||||||
|
vectorHeadPoints[0].setY( vectorHeadWidthRatio * 0.5 );
|
||||||
|
|
||||||
|
// Second head point: right of ->
|
||||||
|
vectorHeadPoints[1].setX( 0.0 );
|
||||||
|
vectorHeadPoints[1].setY( 0.0 );
|
||||||
|
|
||||||
|
// Third head point: bottom of ->
|
||||||
|
vectorHeadPoints[2].setX( -1.0 * vectorHeadLengthRatio );
|
||||||
|
vectorHeadPoints[2].setY( -1.0 * vectorHeadWidthRatio * 0.5 );
|
||||||
|
|
||||||
|
// Determine the arrow head coords
|
||||||
|
for ( int j = 0; j < 3; j++ )
|
||||||
|
{
|
||||||
|
finalVectorHeadPoints[j].setX( lineEnd.x()
|
||||||
|
+ ( vectorHeadPoints[j].x() * cosAlpha * vectorLength )
|
||||||
|
- ( vectorHeadPoints[j].y() * sinAlpha * vectorLength )
|
||||||
|
);
|
||||||
|
|
||||||
|
finalVectorHeadPoints[j].setY( lineEnd.y()
|
||||||
|
- ( vectorHeadPoints[j].x() * sinAlpha * vectorLength )
|
||||||
|
- ( vectorHeadPoints[j].y() * cosAlpha * vectorLength )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now actually draw the vector
|
||||||
|
mContext.painter()->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
|
||||||
|
mContext.painter()->drawPolygon( finalVectorHeadPoints );
|
||||||
|
}
|
103
src/core/mesh/qgsmeshvectorrenderer.h
Normal file
103
src/core/mesh/qgsmeshvectorrenderer.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgstriangularmesh.h
|
||||||
|
-------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 QGSMESHVECTORRENDERER_H
|
||||||
|
#define QGSMESHVECTORRENDERER_H
|
||||||
|
|
||||||
|
|
||||||
|
#define SIP_NO_FILE
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
#include "qgsrendercontext.h"
|
||||||
|
#include "qgstriangularmesh.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgspointxy.h"
|
||||||
|
|
||||||
|
///@cond PRIVATE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
*
|
||||||
|
* Helper private class for rendering vector datasets (e.g. velocity)
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
* \note not available in Python bindings
|
||||||
|
*/
|
||||||
|
class QgsMeshVectorRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Ctor
|
||||||
|
QgsMeshVectorRenderer( const QgsTriangularMesh &m,
|
||||||
|
const QVector<double> &datasetValuesX,
|
||||||
|
const QVector<double> &datasetValuesY,
|
||||||
|
const QVector<double> &datasetValuesMag,
|
||||||
|
bool dataIsOnVertices,
|
||||||
|
const QgsMeshRendererVectorSettings &settings,
|
||||||
|
QgsRenderContext &context,
|
||||||
|
const QSize &size );
|
||||||
|
//! Dtor
|
||||||
|
~QgsMeshVectorRenderer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws vector arrows in the context's painter base on settings
|
||||||
|
*/
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Draws for data defined on vertices
|
||||||
|
void drawVectorDataOnVertices();
|
||||||
|
//! Draws for data defined on face centers
|
||||||
|
void drawVectorDataOnFaces();
|
||||||
|
//! Draws arrow from start point and vector data
|
||||||
|
void drawVectorArrow( const QgsPointXY &lineStart, double xVal, double yVal, double magnitude );
|
||||||
|
//! Calculates the end point of the arrow based on start point and vector data
|
||||||
|
bool calcVectorLineEnd( QgsPointXY &lineEnd,
|
||||||
|
double &vectorLength,
|
||||||
|
double &cosAlpha,
|
||||||
|
double &sinAlpha, //out
|
||||||
|
const QgsPointXY &lineStart,
|
||||||
|
double xVal,
|
||||||
|
double yVal,
|
||||||
|
double magnitude //in
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const QgsTriangularMesh &mTriangularMesh;
|
||||||
|
const QVector<double> &mDatasetValuesX;
|
||||||
|
const QVector<double> &mDatasetValuesY;
|
||||||
|
const QVector<double> &mDatasetValuesMag; //magnitudes
|
||||||
|
double mMinX;
|
||||||
|
double mMaxX;
|
||||||
|
double mMinY;
|
||||||
|
double mMaxY;
|
||||||
|
double mMinMag;
|
||||||
|
double mMaxMag;
|
||||||
|
QgsRenderContext &mContext;
|
||||||
|
const QgsMeshRendererVectorSettings &mCfg;
|
||||||
|
bool mDataOnVertices;
|
||||||
|
QSize mOutputSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
///@endcond
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // QGSMESHVECTORRENDERER_H
|
@ -19,6 +19,51 @@
|
|||||||
#include "qgsrendercontext.h"
|
#include "qgsrendercontext.h"
|
||||||
#include "qgscoordinatetransform.h"
|
#include "qgscoordinatetransform.h"
|
||||||
|
|
||||||
|
static void ENP_centroid_step( const QPolygonF &pX, double &cx, double &cy, double &signedArea, int i, int i1 )
|
||||||
|
{
|
||||||
|
double x0 = 0.0; // Current vertex X
|
||||||
|
double y0 = 0.0; // Current vertex Y
|
||||||
|
double x1 = 0.0; // Next vertex X
|
||||||
|
double y1 = 0.0; // Next vertex Y
|
||||||
|
double a = 0.0; // Partial signed area
|
||||||
|
|
||||||
|
x0 = pX[i].x();
|
||||||
|
y0 = pX[i].y();
|
||||||
|
x1 = pX[i1].x();
|
||||||
|
y1 = pX[i1].y();
|
||||||
|
a = x0 * y1 - x1 * y0;
|
||||||
|
signedArea += a;
|
||||||
|
cx += ( x0 + x1 ) * a;
|
||||||
|
cy += ( y0 + y1 ) * a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ENP_centroid( const QPolygonF &pX, double &cx, double &cy )
|
||||||
|
{
|
||||||
|
// http://stackoverflow.com/questions/2792443/finding-the-centroid-of-a-polygon/2792459#2792459
|
||||||
|
cx = 0;
|
||||||
|
cy = 0;
|
||||||
|
|
||||||
|
if ( pX.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
double signedArea = 0.0;
|
||||||
|
|
||||||
|
// For all vertices except last
|
||||||
|
int i = 0;
|
||||||
|
for ( ; i < pX.size() - 1; ++i )
|
||||||
|
{
|
||||||
|
ENP_centroid_step( pX, cx, cy, signedArea, i, i + 1 );
|
||||||
|
}
|
||||||
|
// Do last vertex separately to avoid performing an expensive
|
||||||
|
// modulus operation in each iteration.
|
||||||
|
ENP_centroid_step( pX, cx, cy, signedArea, i, 0 );
|
||||||
|
|
||||||
|
signedArea *= 0.5;
|
||||||
|
cx /= ( 6.0 * signedArea );
|
||||||
|
cy /= ( 6.0 * signedArea );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsTriangularMesh::update( QgsMesh *nativeMesh, QgsRenderContext *context )
|
void QgsTriangularMesh::update( QgsMesh *nativeMesh, QgsRenderContext *context )
|
||||||
{
|
{
|
||||||
Q_ASSERT( nativeMesh );
|
Q_ASSERT( nativeMesh );
|
||||||
@ -27,6 +72,7 @@ void QgsTriangularMesh::update( QgsMesh *nativeMesh, QgsRenderContext *context )
|
|||||||
mTriangularMesh.vertices.clear();
|
mTriangularMesh.vertices.clear();
|
||||||
mTriangularMesh.faces.clear();
|
mTriangularMesh.faces.clear();
|
||||||
mTrianglesToNativeFaces.clear();
|
mTrianglesToNativeFaces.clear();
|
||||||
|
mNativeMeshFaceCentroids.clear();
|
||||||
|
|
||||||
// TRANSFORM VERTICES
|
// TRANSFORM VERTICES
|
||||||
QgsCoordinateTransform transform = context->coordinateTransform();
|
QgsCoordinateTransform transform = context->coordinateTransform();
|
||||||
@ -79,6 +125,23 @@ void QgsTriangularMesh::update( QgsMesh *nativeMesh, QgsRenderContext *context )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CALCULATE CENTROIDS
|
||||||
|
mNativeMeshFaceCentroids.resize( nativeMesh->faces.size() );
|
||||||
|
for ( int i = 0; i < nativeMesh->faces.size(); ++i )
|
||||||
|
{
|
||||||
|
const QgsMeshFace &face = nativeMesh->faces.at( i ) ;
|
||||||
|
QVector<QPointF> points;
|
||||||
|
for ( int j = 0; j < face.size(); ++j )
|
||||||
|
{
|
||||||
|
int index = face.at( j );
|
||||||
|
const QgsMeshVertex &vertex = mTriangularMesh.vertices[index]; // we need projected vertices
|
||||||
|
points.push_back( vertex.toQPointF() );
|
||||||
|
}
|
||||||
|
QPolygonF poly( points );
|
||||||
|
double cx, cy;
|
||||||
|
ENP_centroid( poly, cx, cy );
|
||||||
|
mNativeMeshFaceCentroids[i] = QgsMeshVertex( cx, cy );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<QgsMeshVertex> &QgsTriangularMesh::vertices() const
|
const QVector<QgsMeshVertex> &QgsTriangularMesh::vertices() const
|
||||||
@ -91,6 +154,11 @@ const QVector<QgsMeshFace> &QgsTriangularMesh::triangles() const
|
|||||||
return mTriangularMesh.faces;
|
return mTriangularMesh.faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVector<QgsMeshVertex> &QgsTriangularMesh::centroids() const
|
||||||
|
{
|
||||||
|
return mNativeMeshFaceCentroids;
|
||||||
|
}
|
||||||
|
|
||||||
const QVector<int> &QgsTriangularMesh::trianglesToNativeFaces() const
|
const QVector<int> &QgsTriangularMesh::trianglesToNativeFaces() const
|
||||||
{
|
{
|
||||||
return mTrianglesToNativeFaces;
|
return mTrianglesToNativeFaces;
|
||||||
|
@ -55,22 +55,26 @@ class CORE_EXPORT QgsTriangularMesh
|
|||||||
~QgsTriangularMesh() = default;
|
~QgsTriangularMesh() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct triangular mesh from layer's native mesh and context
|
* Constructs triangular mesh from layer's native mesh and context
|
||||||
* \param nativeMesh QgsMesh to access native vertices and faces
|
* \param nativeMesh QgsMesh to access native vertices and faces
|
||||||
* \param context Rendering context to estimate number of triagles to create for an face
|
* \param context Rendering context to estimate number of triagles to create for an face
|
||||||
*/
|
*/
|
||||||
void update( QgsMesh *nativeMesh, QgsRenderContext *context );
|
void update( QgsMesh *nativeMesh, QgsRenderContext *context );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return vertices in map CRS
|
* Returns vertices in map CRS
|
||||||
*
|
*
|
||||||
* The list of consist of vertices from native mesh (0-N) and
|
* The list of consist of vertices from native mesh (0-N) and
|
||||||
* extra vertices needed to create triangles (N+1 - len)
|
* extra vertices needed to create triangles (N+1 - len)
|
||||||
*/
|
*/
|
||||||
const QVector<QgsMeshVertex> &vertices() const ;
|
const QVector<QgsMeshVertex> &vertices() const ;
|
||||||
//! Return triangles
|
//! Returns triangles
|
||||||
const QVector<QgsMeshFace> &triangles() const ;
|
const QVector<QgsMeshFace> &triangles() const ;
|
||||||
//! Return mapping between triangles and original faces
|
|
||||||
|
//! Returns centroids of the native faces in map CRS
|
||||||
|
const QVector<QgsMeshVertex> ¢roids() const ;
|
||||||
|
|
||||||
|
//! Returns mapping between triangles and original faces
|
||||||
const QVector<int> &trianglesToNativeFaces() const ;
|
const QVector<int> &trianglesToNativeFaces() const ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -78,6 +82,9 @@ class CORE_EXPORT QgsTriangularMesh
|
|||||||
// faces are derived triangles
|
// faces are derived triangles
|
||||||
QgsMesh mTriangularMesh;
|
QgsMesh mTriangularMesh;
|
||||||
QVector<int> mTrianglesToNativeFaces; //len(mTrianglesToNativeFaces) == len(mTriangles). Mapping derived -> native
|
QVector<int> mTrianglesToNativeFaces; //len(mTrianglesToNativeFaces) == len(mTriangles). Mapping derived -> native
|
||||||
|
|
||||||
|
// centroids of the native faces in map CRS
|
||||||
|
QVector<QgsMeshVertex> mNativeMeshFaceCentroids;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ class QgsMdalLayerItem : public QgsLayerItem
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
//! Ctor
|
||||||
QgsMdalLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri );
|
QgsMdalLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri );
|
||||||
|
|
||||||
QString layerName() const override;
|
QString layerName() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,14 +64,22 @@ class TestQgsMeshRenderer : public QObject
|
|||||||
|
|
||||||
void test_native_mesh_rendering();
|
void test_native_mesh_rendering();
|
||||||
void test_triangular_mesh_rendering();
|
void test_triangular_mesh_rendering();
|
||||||
|
|
||||||
void test_vertex_scalar_dataset_rendering();
|
void test_vertex_scalar_dataset_rendering();
|
||||||
|
void test_vertex_vector_dataset_rendering();
|
||||||
|
void test_face_scalar_dataset_rendering();
|
||||||
|
void test_face_vector_dataset_rendering();
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestQgsMeshRenderer::init()
|
void TestQgsMeshRenderer::init()
|
||||||
{
|
{
|
||||||
mMemoryLayer->toggleTriangularMeshRendering( false );
|
|
||||||
mMemoryLayer->setActiveScalarDataset();
|
mMemoryLayer->setActiveScalarDataset();
|
||||||
mMemoryLayer->setActiveVectorDataset();
|
mMemoryLayer->setActiveVectorDataset();
|
||||||
|
|
||||||
|
mMemoryLayer->setRendererNativeMeshSettings( QgsMeshRendererMeshSettings() );
|
||||||
|
mMemoryLayer->setRendererTriangularMeshSettings( QgsMeshRendererMeshSettings() );
|
||||||
|
mMemoryLayer->setRendererScalarSettings( QgsMeshRendererScalarSettings() );
|
||||||
|
mMemoryLayer->setRendererVectorSettings( QgsMeshRendererVectorSettings() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestQgsMeshRenderer::initTestCase()
|
void TestQgsMeshRenderer::initTestCase()
|
||||||
@ -128,15 +136,20 @@ bool TestQgsMeshRenderer::imageCheck( const QString &testType )
|
|||||||
|
|
||||||
void TestQgsMeshRenderer::test_native_mesh_rendering()
|
void TestQgsMeshRenderer::test_native_mesh_rendering()
|
||||||
{
|
{
|
||||||
mMemoryLayer->toggleTriangularMeshRendering( false );
|
QgsMeshRendererMeshSettings settings = mMemoryLayer->rendererNativeMeshSettings();
|
||||||
QVERIFY( mMemoryLayer->triangularMeshSymbol() == nullptr );
|
settings.setEnabled( true );
|
||||||
|
settings.setLineWidth( 1. );
|
||||||
|
mMemoryLayer->setRendererNativeMeshSettings( settings );
|
||||||
QVERIFY( imageCheck( "quad_and_triangle_native_mesh" ) );
|
QVERIFY( imageCheck( "quad_and_triangle_native_mesh" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestQgsMeshRenderer::test_triangular_mesh_rendering()
|
void TestQgsMeshRenderer::test_triangular_mesh_rendering()
|
||||||
{
|
{
|
||||||
mMemoryLayer->toggleTriangularMeshRendering( true );
|
QgsMeshRendererMeshSettings settings = mMemoryLayer->rendererTriangularMeshSettings();
|
||||||
QVERIFY( mMemoryLayer->triangularMeshSymbol() != nullptr );
|
settings.setEnabled( true );
|
||||||
|
settings.setColor( Qt::red );
|
||||||
|
settings.setLineWidth( 0.26 );
|
||||||
|
mMemoryLayer->setRendererTriangularMeshSettings( settings );
|
||||||
QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh" ) );
|
QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,9 +159,39 @@ void TestQgsMeshRenderer::test_vertex_scalar_dataset_rendering()
|
|||||||
mMemoryLayer->setActiveScalarDataset( ds );
|
mMemoryLayer->setActiveScalarDataset( ds );
|
||||||
QgsMeshDatasetMetadata metadata = mMemoryLayer->dataProvider()->datasetMetadata( ds );
|
QgsMeshDatasetMetadata metadata = mMemoryLayer->dataProvider()->datasetMetadata( ds );
|
||||||
QVERIFY( metadata["name"] == "VertexScalarDataset" );
|
QVERIFY( metadata["name"] == "VertexScalarDataset" );
|
||||||
|
QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset" ) );
|
||||||
|
}
|
||||||
|
|
||||||
// TODO!
|
void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering()
|
||||||
// QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset" ) );
|
{
|
||||||
|
int ds = 1;
|
||||||
|
mMemoryLayer->setActiveVectorDataset( ds );
|
||||||
|
QgsMeshDatasetMetadata metadata = mMemoryLayer->dataProvider()->datasetMetadata( ds );
|
||||||
|
QVERIFY( metadata["name"] == "VertexVectorDataset" );
|
||||||
|
|
||||||
|
QgsMeshRendererVectorSettings settings = mMemoryLayer->rendererVectorSettings();
|
||||||
|
settings.setMinShaftLength( 15 );
|
||||||
|
mMemoryLayer->setRendererVectorSettings( settings );
|
||||||
|
|
||||||
|
QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshRenderer::test_face_scalar_dataset_rendering()
|
||||||
|
{
|
||||||
|
int ds = 2;
|
||||||
|
mMemoryLayer->setActiveScalarDataset( ds );
|
||||||
|
QgsMeshDatasetMetadata metadata = mMemoryLayer->dataProvider()->datasetMetadata( ds );
|
||||||
|
QVERIFY( metadata["name"] == "FaceScalarDataset" );
|
||||||
|
QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshRenderer::test_face_vector_dataset_rendering()
|
||||||
|
{
|
||||||
|
int ds = 3;
|
||||||
|
mMemoryLayer->setActiveVectorDataset( ds );
|
||||||
|
QgsMeshDatasetMetadata metadata = mMemoryLayer->dataProvider()->datasetMetadata( ds );
|
||||||
|
QVERIFY( metadata["name"] == "FaceVectorDataset" );
|
||||||
|
QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsMeshRenderer )
|
QGSTEST_MAIN( TestQgsMeshRenderer )
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Loading…
x
Reference in New Issue
Block a user