31 #include <Qt3DRender/QGeometryRenderer> 
   32 #include <Qt3DRender/QAttribute> 
   33 #include <Qt3DRender/QTechnique> 
   34 #include <Qt3DRender/QShaderProgram> 
   35 #include <Qt3DRender/QGraphicsApiFilter> 
   36 #include <Qt3DRender/QEffect> 
   40 QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, 
unsigned int byteStride )
 
   42   , mPositionAttribute( new 
Qt3DRender::QAttribute( this ) )
 
   43   , mParameterAttribute( new 
Qt3DRender::QAttribute( this ) )
 
   44   , mColorAttribute( new 
Qt3DRender::QAttribute( this ) )
 
   45   , mVertexBuffer( new 
Qt3DRender::QBuffer( this ) )
 
   46   , mByteStride( byteStride )
 
   51 QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
   52   : QgsPointCloud3DGeometry( parent, byteStride )
 
   54   mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
   55   mPositionAttribute->setBuffer( mVertexBuffer );
 
   56   mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
   57   mPositionAttribute->setVertexSize( 3 );
 
   58   mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
 
   59   mPositionAttribute->setByteOffset( 0 );
 
   60   mPositionAttribute->setByteStride( mByteStride );
 
   61   addAttribute( mPositionAttribute );
 
   62   makeVertexBuffer( data );
 
   65 void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer( 
const QgsPointCloud3DSymbolHandler::PointData &data )
 
   67   QByteArray vertexBufferData;
 
   68   vertexBufferData.resize( data.positions.size() * mByteStride );
 
   69   float *rawVertexArray = 
reinterpret_cast<float *
>( vertexBufferData.data() );
 
   71   for ( 
int i = 0; i < data.positions.size(); ++i )
 
   73     rawVertexArray[idx++] = data.positions.at( i ).x();
 
   74     rawVertexArray[idx++] = data.positions.at( i ).y();
 
   75     rawVertexArray[idx++] = data.positions.at( i ).z();
 
   78   mVertexCount = data.positions.size();
 
   79   mVertexBuffer->setData( vertexBufferData );
 
   82 QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
   83   : QgsPointCloud3DGeometry( parent, byteStride )
 
   85   mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
   86   mPositionAttribute->setBuffer( mVertexBuffer );
 
   87   mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
   88   mPositionAttribute->setVertexSize( 3 );
 
   89   mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
 
   90   mPositionAttribute->setByteOffset( 0 );
 
   91   mPositionAttribute->setByteStride( mByteStride );
 
   92   addAttribute( mPositionAttribute );
 
   93   mParameterAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
   94   mParameterAttribute->setBuffer( mVertexBuffer );
 
   95   mParameterAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
   96   mParameterAttribute->setVertexSize( 1 );
 
   97   mParameterAttribute->setName( 
"vertexParameter" );
 
   98   mParameterAttribute->setByteOffset( 12 );
 
   99   mParameterAttribute->setByteStride( mByteStride );
 
  100   addAttribute( mParameterAttribute );
 
  101   makeVertexBuffer( data );
 
  104 void QgsColorRampPointCloud3DGeometry::makeVertexBuffer( 
const QgsPointCloud3DSymbolHandler::PointData &data )
 
  106   QByteArray vertexBufferData;
 
  107   vertexBufferData.resize( data.positions.size() * mByteStride );
 
  108   float *rawVertexArray = 
reinterpret_cast<float *
>( vertexBufferData.data() );
 
  110   Q_ASSERT( data.positions.size() == data.parameter.size() );
 
  111   for ( 
int i = 0; i < data.positions.size(); ++i )
 
  113     rawVertexArray[idx++] = data.positions.at( i ).x();
 
  114     rawVertexArray[idx++] = data.positions.at( i ).y();
 
  115     rawVertexArray[idx++] = data.positions.at( i ).z();
 
  116     rawVertexArray[idx++] = data.parameter.at( i );
 
  119   mVertexCount = data.positions.size();
 
  120   mVertexBuffer->setData( vertexBufferData );
 
  123 QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
  124   : QgsPointCloud3DGeometry( parent, byteStride )
 
  126   mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
  127   mPositionAttribute->setBuffer( mVertexBuffer );
 
  128   mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
  129   mPositionAttribute->setVertexSize( 3 );
 
  130   mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
 
  131   mPositionAttribute->setByteOffset( 0 );
 
  132   mPositionAttribute->setByteStride( mByteStride );
 
  133   addAttribute( mPositionAttribute );
 
  134   mColorAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
  135   mColorAttribute->setBuffer( mVertexBuffer );
 
  136   mColorAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
  137   mColorAttribute->setVertexSize( 3 );
 
  138   mColorAttribute->setName( QStringLiteral( 
"vertexColor" ) );
 
  139   mColorAttribute->setByteOffset( 12 );
 
  140   mColorAttribute->setByteStride( mByteStride );
 
  141   addAttribute( mColorAttribute );
 
  142   makeVertexBuffer( data );
 
  145 void QgsRGBPointCloud3DGeometry::makeVertexBuffer( 
const QgsPointCloud3DSymbolHandler::PointData &data )
 
  147   QByteArray vertexBufferData;
 
  148   vertexBufferData.resize( data.positions.size() * mByteStride );
 
  149   float *rawVertexArray = 
reinterpret_cast<float *
>( vertexBufferData.data() );
 
  151   Q_ASSERT( data.positions.size() == data.colors.size() );
 
  152   for ( 
int i = 0; i < data.positions.size(); ++i )
 
  154     rawVertexArray[idx++] = data.positions.at( i ).x();
 
  155     rawVertexArray[idx++] = data.positions.at( i ).y();
 
  156     rawVertexArray[idx++] = data.positions.at( i ).z();
 
  157     rawVertexArray[idx++] = data.colors.at( i ).x();
 
  158     rawVertexArray[idx++] = data.colors.at( i ).y();
 
  159     rawVertexArray[idx++] = data.colors.at( i ).z();
 
  161   mVertexCount = data.positions.size();
 
  162   mVertexBuffer->setData( vertexBufferData );
 
  165 QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
 
  169 void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const QgsPointCloud3DRenderContext &context, QgsPointCloud3DSymbolHandler::PointData &out, 
bool selected )
 
  173   if ( out.positions.empty() )
 
  177   Qt3DRender::QGeometry *geom = makeGeometry( parent, out, context.
symbol()->
byteStride() );
 
  178   Qt3DRender::QGeometryRenderer *gr = 
new Qt3DRender::QGeometryRenderer;
 
  179   gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
 
  180   gr->setVertexCount( out.positions.count() );
 
  181   gr->setGeometry( geom );
 
  184   Qt3DCore::QTransform *tr = 
new Qt3DCore::QTransform;
 
  187   Qt3DRender::QMaterial *mat = 
new Qt3DRender::QMaterial;
 
  191   Qt3DRender::QShaderProgram *shaderProgram = 
new Qt3DRender::QShaderProgram( mat );
 
  192   shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/pointcloud.vert" ) ) ) );
 
  193   shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/pointcloud.frag" ) ) ) );
 
  195   Qt3DRender::QRenderPass *renderPass = 
new Qt3DRender::QRenderPass( mat );
 
  196   renderPass->setShaderProgram( shaderProgram );
 
  198   Qt3DRender::QPointSize *pointSize = 
new Qt3DRender::QPointSize( renderPass );
 
  199   pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );  
 
  201   renderPass->addRenderState( pointSize );
 
  204   Qt3DRender::QFilterKey *filterKey = 
new Qt3DRender::QFilterKey;
 
  205   filterKey->setName( QStringLiteral( 
"renderingStyle" ) );
 
  206   filterKey->setValue( 
"forward" );
 
  208   Qt3DRender::QTechnique *technique = 
new Qt3DRender::QTechnique;
 
  209   technique->addRenderPass( renderPass );
 
  210   technique->addFilterKey( filterKey );
 
  211   technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
 
  212   technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
 
  213   technique->graphicsApiFilter()->setMajorVersion( 3 );
 
  214   technique->graphicsApiFilter()->setMinorVersion( 1 );
 
  216   Qt3DRender::QEffect *eff = 
new Qt3DRender::QEffect;
 
  217   eff->addTechnique( technique );
 
  218   mat->setEffect( eff );
 
  221   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  222   entity->addComponent( gr );
 
  223   entity->addComponent( tr );
 
  224   entity->addComponent( mat );
 
  225   entity->setParent( parent );
 
  233   if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Local )
 
  237   else if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Remote )
 
  239     bool loopAborted = 
false;
 
  251       block = req->
block();
 
  258 QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
 
  259   : QgsPointCloud3DSymbolHandler()
 
  279   std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
 
  283   const char *ptr = block->
data();
 
  291   bool alreadyPrintedDebug = 
false;
 
  293   for ( 
int i = 0; i < count; ++i )
 
  298     qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
 
  299     qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
 
  300     qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
 
  302     double x = blockOffset.
x() + blockScale.
x() * ix;
 
  303     double y = blockOffset.
y() + blockScale.
y() * iy;
 
  304     double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
 
  311       if ( !alreadyPrintedDebug )
 
  313         QgsDebugMsg( QStringLiteral( 
"Error transforming point coordinate" ) );
 
  314         alreadyPrintedDebug = 
true;
 
  319     outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
 
  325   makeEntity( parent, context, outNormal, 
false );
 
  328 Qt3DRender::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
  330   return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
 
  333 QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
 
  334   : QgsPointCloud3DSymbolHandler()
 
  348   const int xOffset = 0;
 
  355   QString attributeName;
 
  356   bool attrIsX = 
false;
 
  357   bool attrIsY = 
false;
 
  358   bool attrIsZ = 
false;
 
  360   int attributeOffset = 0;
 
  364   bool alreadyPrintedDebug = 
false;
 
  372     if ( symbol->
attribute() == QLatin1String( 
"X" ) )
 
  376     else if ( symbol->
attribute() == QLatin1String( 
"Y" ) )
 
  380     else if ( symbol->
attribute() == QLatin1String( 
"Z" ) )
 
  389         attributeType = attr->
type();
 
  390         attributeName = attr->
name();
 
  397   if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
 
  402   std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
 
  406   const char *ptr = block->
data();
 
  413   for ( 
int i = 0; i < count; ++i )
 
  418     qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
 
  419     qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
 
  420     qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
 
  422     double x = blockOffset.
x() + blockScale.
x() * ix;
 
  423     double y = blockOffset.
y() + blockScale.
y() * iy;
 
  424     double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
 
  431       if ( !alreadyPrintedDebug )
 
  433         QgsDebugMsg( QStringLiteral( 
"Error transforming point coordinate" ) );
 
  434         alreadyPrintedDebug = 
true;
 
  438     point = context.map().mapToWorldCoordinates( point );
 
  439     outNormal.positions.push_back( QVector3D( point.x(), point.y(), point.z() ) );
 
  442       outNormal.parameter.push_back( x );
 
  444       outNormal.parameter.push_back( y );
 
  446       outNormal.parameter.push_back( z );
 
  450       context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
 
  451       outNormal.parameter.push_back( iParam );
 
  458   makeEntity( parent, context, outNormal, 
false );
 
  461 Qt3DRender::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
  463   return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
 
  466 QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
 
  467   : QgsPointCloud3DSymbolHandler()
 
  507   std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
 
  511   const char *ptr = block->
data();
 
  520   bool alreadyPrintedDebug = 
false;
 
  533   for ( 
int i = 0; i < count; ++i )
 
  538     qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
 
  539     qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
 
  540     qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
 
  541     double x = blockOffset.
x() + blockScale.
x() * ix;
 
  542     double y = blockOffset.
y() + blockScale.
y() * iy;
 
  543     double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
 
  550       if ( !alreadyPrintedDebug )
 
  552         QgsDebugMsg( QStringLiteral( 
"Error transforming point coordinate" ) );
 
  553         alreadyPrintedDebug = 
true;
 
  557     QgsVector3D p = context.map().mapToWorldCoordinates( point );
 
  559     QVector3D color( 0.0f, 0.0f, 0.0f );
 
  561     context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
 
  562     context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
 
  563     context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
 
  574     if ( useRedContrastEnhancement )
 
  578     if ( useGreenContrastEnhancement )
 
  582     if ( useBlueContrastEnhancement )
 
  587     color.setX( ir / 255.0f );
 
  588     color.setY( ig / 255.0f );
 
  589     color.setZ( ib / 255.0f );
 
  591     outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
 
  592     outNormal.colors.push_back( color );
 
  598   makeEntity( parent, context, outNormal, 
false );
 
  601 Qt3DRender::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
  603   return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
 
  606 QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
 
  607   : QgsPointCloud3DSymbolHandler()
 
  621   const int xOffset = 0;
 
  628   QString attributeName;
 
  629   bool attrIsX = 
false;
 
  630   bool attrIsY = 
false;
 
  631   bool attrIsZ = 
false;
 
  633   int attributeOffset = 0;
 
  640     if ( symbol->
attribute() == QLatin1String( 
"X" ) )
 
  644     else if ( symbol->
attribute() == QLatin1String( 
"Y" ) )
 
  648     else if ( symbol->
attribute() == QLatin1String( 
"Z" ) )
 
  657         attributeType = attr->
type();
 
  658         attributeName = attr->
name();
 
  665   if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
 
  670   std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
 
  674   const char *ptr = block->
data();
 
  683   bool alreadyPrintedDebug = 
false;
 
  686   for ( 
int i = 0; i < count; ++i )
 
  691     qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
 
  692     qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
 
  693     qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
 
  695     double x = blockOffset.
x() + blockScale.
x() * ix;
 
  696     double y = blockOffset.
y() + blockScale.
y() * iy;
 
  697     double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
 
  704       if ( !alreadyPrintedDebug )
 
  706         QgsDebugMsg( QStringLiteral( 
"Error transforming point coordinate" ) );
 
  707         alreadyPrintedDebug = 
true;
 
  711     QgsVector3D p = context.map().mapToWorldCoordinates( point );
 
  720       context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
 
  722     if ( filteredOutValues.contains( ( 
int ) iParam ) )
 
  724     outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
 
  725     outNormal.parameter.push_back( iParam );
 
  731   makeEntity( parent, context, outNormal, 
false );
 
  735 Qt3DRender::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, 
const QgsPointCloud3DSymbolHandler::PointData &data, 
unsigned int byteStride )
 
  737   return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
 
Represents a indexed point cloud node in octree.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Custom exception class for Coordinate Reference System related exceptions.
void canceled()
Internal routines can connect to this signal if they use event loop.
Encapsulates the render context for a 3D point cloud rendering operation.
void getAttribute(const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value) const
Retrieves the attribute value from data at the specified offset, where type indicates the original da...
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering and check if rendering was canceled.
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
bool isCanceled() const
Returns true if the rendering is canceled.
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
virtual unsigned int byteStride()=0
Returns the byte stride for the geometries used to for the vertex buffer.
virtual void fillMaterial(Qt3DRender::QMaterial *material)=0SIP_SKIP
Used to fill material object with necessary QParameters (and consequently opengl uniforms)
float pointSize() const
Returns the point size of the point cloud.
Collection of point cloud attributes.
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
int pointRecordSize() const
Returns total size of record.
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Attribute for point cloud data pair of name and size in bytes.
DataType
Systems of unit measurement.
QString name() const
Returns name of the attribute.
DataType type() const
Returns the data type.
Base class for handling loading QgsPointCloudBlock asynchronously.
QgsPointCloudBlock * block()
Returns the requested block.
void finished()
Emitted when the request processing has finished.
Base class for storing raw data from point cloud nodes.
QgsVector3D scale() const
Returns the custom scale of the block.
const char * data() const
Returns raw pointer to data.
int pointCount() const
Returns number of points that are stored in the block.
QgsVector3D offset() const
Returns the custom offset of the block.
Represents a indexed point clouds data in octree.
virtual QgsPointCloudBlock * nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns node data block.
virtual AccessType accessType() const =0
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
virtual QgsPointCloudBlockRequest * asyncNodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns a handle responsible for loading a node data block.
Point cloud data request.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
QString blueAttribute() const
Returns the attribute to use for the blue channel.
QString greenAttribute() const
Returns the attribute to use for the green channel.
QgsContrastEnhancement * blueContrastEnhancement()
Returns the contrast enhancement to use for the blue channel.
QString redAttribute() const
Returns the attribute to use for the red channel.
QgsContrastEnhancement * greenContrastEnhancement()
Returns the contrast enhancement to use for the green channel.
QgsContrastEnhancement * redContrastEnhancement()
Returns the contrast enhancement to use for the red channel.
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.