36#include <Qt3DCore/QEntity> 
   38#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) 
   39#include <Qt3DRender/QAttribute> 
   40#include <Qt3DRender/QBuffer> 
   41#include <Qt3DRender/QGeometry> 
   43#include <Qt3DCore/QAttribute> 
   44#include <Qt3DCore/QBuffer> 
   45#include <Qt3DCore/QGeometry> 
   48#include <Qt3DRender/QGeometryRenderer> 
   56  : mMapSettings( &map )
 
   58  , mGeometryType( geometryType )
 
   60  switch ( mGeometryType )
 
   63      setupMarker( parentEntity );
 
   66      setupLine( parentEntity, engine );
 
   67      setupMarker( parentEntity );
 
   70      setupMarker( parentEntity );
 
   71      setupLine( parentEntity, engine );
 
   72      setupPolygon( parentEntity );
 
   76      QgsDebugError( 
"Unknown GeometryType used in QgsRubberband3D" );
 
   81void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
 
   83  mMarkerEntity = 
new Qt3DCore::QEntity( parentEntity );
 
   85  mMarkerGeometryRenderer = 
new Qt3DRender::QGeometryRenderer;
 
   86  mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
 
   87  mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
 
   88  mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
 
   90  setMarkerType( mMarkerType );
 
   91  mMarkerEntity->addComponent( mMarkerGeometryRenderer );
 
   93  mMarkerTransform = 
new QgsGeoTransform;
 
   94  mMarkerTransform->setOrigin( mMapSettings->origin() );
 
   95  mMarkerEntity->addComponent( mMarkerTransform );
 
   98void QgsRubberBand3D::setupLine( Qt3DCore::QEntity *parentEntity, 
QgsAbstract3DEngine *engine )
 
  100  mLineEntity = 
new Qt3DCore::QEntity( parentEntity );
 
  102  QgsLineVertexData dummyLineData;
 
  103  mLineGeometry = dummyLineData.createGeometry( mLineEntity );
 
  105  Q_ASSERT( mLineGeometry->attributes().count() == 2 );
 
  106  mPositionAttribute = mLineGeometry->attributes().at( 0 );
 
  107  mIndexAttribute = mLineGeometry->attributes().at( 1 );
 
  109  mLineGeometryRenderer = 
new Qt3DRender::QGeometryRenderer;
 
  110  mLineGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
 
  111  mLineGeometryRenderer->setGeometry( mLineGeometry );
 
  112  mLineGeometryRenderer->setPrimitiveRestartEnabled( 
true );
 
  113  mLineGeometryRenderer->setRestartIndexValue( 0 );
 
  115  mLineEntity->addComponent( mLineGeometryRenderer );
 
  117  mLineMaterial = 
new QgsLineMaterial;
 
  118  mLineMaterial->setLineWidth( mWidth );
 
  119  mLineMaterial->setLineColor( mColor );
 
  122    mLineMaterial->setViewportSize( engine->
size() );
 
  124  mLineMaterial->setViewportSize( engine->
size() );
 
  126  mLineEntity->addComponent( mLineMaterial );
 
  128  mLineTransform = 
new QgsGeoTransform( mLineEntity );
 
  129  mLineTransform->setOrigin( mMapSettings->origin() );
 
  130  mLineEntity->addComponent( mLineTransform );
 
  133void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity )
 
  135  mPolygonEntity = 
new Qt3DCore::QEntity( parentEntity );
 
  139  Qt3DRender::QGeometryRenderer *polygonGeometryRenderer = 
new Qt3DRender::QGeometryRenderer;
 
  140  polygonGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
 
  141  polygonGeometryRenderer->setGeometry( mPolygonGeometry );
 
  142  mPolygonEntity->addComponent( polygonGeometryRenderer );
 
  147  polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
 
  149  mPolygonEntity->addComponent( mPolygonMaterial );
 
  151  mPolygonTransform = 
new QgsGeoTransform;
 
  152  mPolygonTransform->setOrigin( mMapSettings->origin() );
 
  153  mPolygonEntity->addComponent( mPolygonTransform );
 
  156void QgsRubberBand3D::removePoint( 
int index )
 
  158  if ( 
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
 
  160    QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
 
  161    const int vertexIndex = index < 0 ? lineString->
numPoints() - 1 + index : index;
 
  169  else if ( 
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
 
  171    const int vertexIndex = index < 0 ? lineString->
numPoints() + index : index;
 
  182QgsRubberBand3D::~QgsRubberBand3D()
 
  184  if ( mPolygonEntity )
 
  185    delete mPolygonEntity;
 
  189    delete mMarkerEntity;
 
  193float QgsRubberBand3D::width()
 const 
  198void QgsRubberBand3D::setWidth( 
float width )
 
  203  if ( isLineOrPolygon && mEdgesEnabled )
 
  206    mLineMaterial->setLineWidth( width );
 
  210  mMarkerSymbol->setSize( width );
 
  211  updateMarkerMaterial();
 
  214QColor QgsRubberBand3D::color()
 const 
  219void QgsRubberBand3D::setColor( 
const QColor color )
 
  224  if ( mEdgesEnabled && isLineOrPolygon )
 
  226    mLineMaterial->setLineColor( color );
 
  229  if ( isLineOrPolygon )
 
  231    mMarkerSymbol->setColor( color.lighter( 130 ) );
 
  235    mMarkerSymbol->setColor( color );
 
  238  if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String( 
"SimpleMarker" ) && !mOutlineColor.value() )
 
  240    mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
 
  242  updateMarkerMaterial();
 
  246    if ( mPolygonMaterial )
 
  247      mPolygonEntity->removeComponent( mPolygonMaterial );
 
  249    if ( mPolygonFillEnabled )
 
  254      polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
 
  256      mPolygonEntity->addComponent( mPolygonMaterial );
 
  261QColor QgsRubberBand3D::outlineColor()
 const 
  263  return mOutlineColor;
 
  266void QgsRubberBand3D::setOutlineColor( 
const QColor color )
 
  268  mOutlineColor = color;
 
  270  if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String( 
"SimpleMarker" ) )
 
  272    mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
 
  274  updateMarkerMaterial();
 
  277void QgsRubberBand3D::setMarkerType( 
const MarkerType marker )
 
  279  mMarkerType = marker;
 
  283  const QVariantMap props {
 
  284    { QStringLiteral( 
"color" ), lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
 
  285    { QStringLiteral( 
"size_unit" ), QStringLiteral( 
"pixel" ) },
 
  286    { QStringLiteral( 
"size" ), QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
 
  287    { QStringLiteral( 
"outline_color" ), mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
 
  289    { QStringLiteral( 
"outline_width" ), QString::number( lineOrPolygon ? 0.5 : 1 ) },
 
  290    { QStringLiteral( 
"name" ), mMarkerType == Square ? QStringLiteral( 
"square" ) : QStringLiteral( 
"circle" ) }
 
  294  updateMarkerMaterial();
 
  297QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType()
 const 
  302void QgsRubberBand3D::setMarkerOutlineStyle( 
const Qt::PenStyle style )
 
  304  mMarkerOutlineStyle = style;
 
  305  setMarkerType( markerType() );
 
  308Qt::PenStyle QgsRubberBand3D::markerOutlineStyle()
 const 
  310  return mMarkerOutlineStyle;
 
  313void QgsRubberBand3D::setMarkersEnabled( 
const bool enable )
 
  315  mMarkerEnabled = enable;
 
  316  updateMarkerMaterial();
 
  319bool QgsRubberBand3D::hasMarkersEnabled()
 const 
  321  return mMarkerEnabled;
 
  324void QgsRubberBand3D::setEdgesEnabled( 
const bool enable )
 
  326  mEdgesEnabled = enable;
 
  330bool QgsRubberBand3D::hasEdgesEnabled()
 const 
  332  return mEdgesEnabled;
 
  335void QgsRubberBand3D::setFillEnabled( 
const bool enable )
 
  337  mPolygonFillEnabled = enable;
 
  341bool QgsRubberBand3D::hasFillEnabled()
 const 
  343  return mPolygonFillEnabled;
 
  346void QgsRubberBand3D::reset()
 
  348  mGeometry.set( 
nullptr );
 
  352void QgsRubberBand3D::addPoint( 
const QgsPoint &pt )
 
  354  if ( 
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
 
  356    QgsLineString *exteriorRing = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
 
  357    const int lastVertexIndex = exteriorRing->
numPoints() - 1;
 
  360  else if ( 
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
 
  369  else if ( !mGeometry.constGet() )
 
  371    mGeometry.set( 
new QgsLineString( QVector<QgsPoint> { pt } ) );
 
  377void QgsRubberBand3D::setGeometry( 
const QgsGeometry &geometry )
 
  379  mGeometry = geometry;
 
  380  mGeometryType = geometry.
type();
 
  385void QgsRubberBand3D::removeLastPoint()
 
  390void QgsRubberBand3D::removePenultimatePoint()
 
  395void QgsRubberBand3D::moveLastPoint( 
const QgsPoint &pt )
 
  397  if ( 
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
 
  399    QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
 
  400    const int lastVertexIndex = lineString->
numPoints() - 2;
 
  403  else if ( 
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
 
  405    const int lastVertexIndex = lineString->
numPoints() - 1;
 
  416void QgsRubberBand3D::updateGeometry()
 
  419  const QgsBox3D box = mGeometry.constGet() ? mGeometry.constGet()->boundingBox3D() : 
QgsBox3D();
 
  422  QgsLineVertexData lineData;
 
  423  lineData.withAdjacency = 
true;
 
  426  if ( 
const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( mGeometry.constGet() ) )
 
  428    std::unique_ptr< QgsLineString > lineString( qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing()->clone() ) );
 
  429    const int lastVertexIndex = lineString->
numPoints() - 1;
 
  431    lineData.addLineString( *lineString, 0, 
true );
 
  433  else if ( 
const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( mGeometry.constGet() ) )
 
  435    lineData.addLineString( *lineString, 0, 
false );
 
  441    mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
 
  442    mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
 
  443    mLineGeometryRenderer->setVertexCount( lineData.indexes.count() );
 
  444    mLineTransform->setGeoTranslation( dataOrigin );
 
  448  lineData.vertices.pop_front();
 
  451  if ( mHideLastMarker && !lineData.vertices.isEmpty() )
 
  452    lineData.vertices.pop_back();
 
  454  mMarkerGeometry->setPoints( lineData.vertices );
 
  455  mMarkerGeometryRenderer->setVertexCount( lineData.vertices.count() );
 
  456  mMarkerTransform->setGeoTranslation( dataOrigin );
 
  460    if ( 
const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( mGeometry.constGet() ) )
 
  464      const QgsVector3D polygonOrigin( mMapSettings->origin().x(), mMapSettings->origin().y(), 0 );
 
  465      QgsTessellator tessellator( polygonOrigin.x(), polygonOrigin.y(), 
true );
 
  466      tessellator.setOutputZUp( 
true );
 
  467      tessellator.addPolygon( *polygon, 0 );
 
  468      if ( !tessellator.error().isEmpty() )
 
  473      const QByteArray data( 
reinterpret_cast<const char *
>( tessellator.data().constData() ), 
static_cast<int>( tessellator.data().count() * 
sizeof( 
float ) ) );
 
  474      const int vertexCount = data.count() / tessellator.stride();
 
  475      mPolygonGeometry->setData( data, vertexCount, QVector<QgsFeatureId>(), QVector<uint>() );
 
  476      mPolygonTransform->setGeoTranslation( polygonOrigin );
 
  480      mPolygonGeometry->setData( QByteArray(), 0, QVector<QgsFeatureId>(), QVector<uint>() );
 
  485void QgsRubberBand3D::updateMarkerMaterial()
 
  487  if ( mMarkerEnabled )
 
  491    mMarkerEntity->addComponent( mMarkerMaterial );
 
  495      mMarkerMaterial->setViewportSize( mEngine->size() );
 
  497    mMarkerMaterial->setViewportSize( mEngine->size() );
 
  501    mMarkerEntity->removeComponent( mMarkerMaterial );
 
  502    QObject::disconnect( mEngine, 
nullptr, mMarkerMaterial, 
nullptr );
 
@ Absolute
Elevation is taken directly from feature and is independent of terrain height (final elevation = feat...
 
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
 
@ Vertex
Clamp every vertex of feature.
 
@ Globe
Scene is represented as a globe using a geocentric CRS.
 
static Qgs3DRenderContext fromMapSettings(const Qgs3DMapSettings *mapSettings)
Creates an initialized Qgs3DRenderContext instance from given Qgs3DMapSettings.
 
Base class for 3D engine implementation.
 
void sizeChanged()
Emitted after a call to setSize()
 
virtual QSize size() const =0
Returns size of the engine's rendering area in pixels.
 
Geometry of the billboard rendering for points in 3D map view.
 
A 3-dimensional box composed of x, y, z coordinates.
 
QgsVector3D center() const
Returns the center of the box as a vector.
 
bool isNull() const
Test if the box is null (holding no spatial information).
 
A geometry is the spatial representation of a feature.
 
Line string geometry type, with support for z-dimension and m-values.
 
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
 
int numPoints() const override
Returns the number of points in the curve.
 
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
 
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
 
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
 
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
 
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
 
Context settings for a material.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
Basic shading material used for rendering based on the Phong shading model with three color component...
 
void setOpacity(double opacity)
Sets opacity of the surface.
 
QgsMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QgsMaterial object representing the material settings.
 
void setDiffuse(const QColor &diffuse)
Sets diffuse color component.
 
void setAmbient(const QColor &ambient)
Sets ambient color component.
 
Material of the billboard rendering for points in 3D map view.
 
Point geometry type, with support for z-dimension and m-values.
 
static QString encodePenStyle(Qt::PenStyle style)
 
Qt3DRender::QGeometry subclass that represents polygons tessellated into 3D geometry.
 
Tessellates polygons into triangles.
 
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
 
@ Triangles
Triangle based rendering (default)
 
#define QgsDebugError(str)
 
Utility class for identifying a unique vertex within a geometry.