50#include <Qt3DCore/QTransform>
51#include <Qt3DRender/QGeometryRenderer>
52#include <QtConcurrentRun>
54#include "moc_qgsannotationlayerchunkloader_p.cpp"
56using namespace Qt::StringLiterals;
61QgsAnnotationLayerChunkLoader::QgsAnnotationLayerChunkLoader(
const QgsAnnotationLayerChunkLoaderFactory *factory, QgsChunkNode *node )
62 : QgsChunkLoader( node )
64 , mRenderContext( factory->mRenderContext )
73 const QgsMarkerSymbol *markerSymbol =
nullptr;
85 struct PictureBillboardGroup
91 bool operator<(
const PictureBillboardGroup &other )
const
93 if ( path != other.path )
94 return path < other.path;
95 return scaleMode < other.scaleMode;
99 struct PictureBillboard
106void QgsAnnotationLayerChunkLoader::start()
108 QgsChunkNode *node = chunk();
109 if ( node->level() < mFactory->mLeafLevel )
111 QTimer::singleShot( 0,
this, &QgsAnnotationLayerChunkLoader::finished );
116 mLayerName = mFactory->mLayer->
name();
126 mRenderContext.setExpressionContext( exprContext );
137 QgsDebugError( u
"Error transforming annotation layer extent to 3d map extent: %1"_s.arg( e.
what() ) );
141 const double zOffset = mFactory->mZOffset;
143 bool showCallouts = mFactory->mShowCallouts;
147 const QStringList itemsList = layer->queryIndex( layerExtent );
148 QSet< QString > itemIds( itemsList.begin(), itemsList.end() );
155 itemIds.unite( layer->mNonIndexedItems );
157 mItemsToRender.reserve( itemIds.size() );
158 std::transform( itemIds.begin(), itemIds.end(), std::back_inserter( mItemsToRender ), [layer](
const QString &
id ) -> std::unique_ptr< QgsAnnotationItem > {
159 return std::unique_ptr< QgsAnnotationItem >( layer->item( id )->clone() );
165 mFutureWatcher =
new QFutureWatcher<void>(
this );
166 connect( mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsChunkQueueJob::finished );
168 const QFuture<void> future = QtConcurrent::run( [
this, rect, layerToMapTransform, zOffset, altitudeClamping, showCallouts, textFormat] {
169 const QgsScopedEvent e( u
"3D"_s, u
"Annotation layer chunk load"_s );
171 std::vector< Billboard > billboards;
172 billboards.reserve( mItemsToRender.size() );
173 QVector< QImage > textures;
174 textures.reserve(
static_cast< qsizetype
>( mItemsToRender.size() ) );
176 std::vector< TextBillboard > textBillboards;
177 textBillboards.reserve( mItemsToRender.size() );
178 QStringList textBillboardTexts;
179 textBillboardTexts.reserve(
static_cast< qsizetype
>( mItemsToRender.size() ) );
181 QMap< PictureBillboardGroup, QVector< PictureBillboard > > groupedPictures;
182 mPictureBillboards.reserve(
static_cast< qsizetype
>( mItemsToRender.size() ) );
184 auto addTextBillboard = [layerToMapTransform,
191 &textBillboardTexts](
const QgsPointXY &p,
const QString &annotationText,
const QgsTextFormat &annotationTextFormat ) {
192 QString text = annotationText;
193 if ( annotationTextFormat.allowHtmlFormatting() )
199 if ( !text.isEmpty() )
203 const QgsPointXY mapPoint = layerToMapTransform.transform( p );
204 if ( !rect.contains( mapPoint ) )
209 : mRenderContext.terrainRenderingEnabled() && mRenderContext.terrainGenerator()
210 ? static_cast<float>( mRenderContext.terrainGenerator()->heightAt( mapPoint.x(), mapPoint.y(), mRenderContext ) * mRenderContext.terrainSettings()->verticalScale() )
213 switch ( altitudeClamping )
222 z = terrainZ + zOffset;
226 TextBillboard billboard;
227 billboard.position = (
QgsVector3D( mapPoint.
x(), mapPoint.
y(), z ) - mChunkOrigin ).toVector3D();
228 billboard.text = text;
229 textBillboards.emplace_back( std::move( billboard ) );
230 textBillboardTexts.append( text );
234 mCalloutLines <<
QgsLineString( { mapPoint.
x(), mapPoint.
x() }, { mapPoint.
y(), mapPoint.
y() }, { terrainZ, z } );
237 mZMax = std::max( mZMax, showCallouts ? std::max( 0.0, z ) : z );
238 mZMin = std::min( mZMin, showCallouts ? std::min( 0.0, z ) : z );
247 for (
const std::unique_ptr< QgsAnnotationItem > &item : std::as_const( mItemsToRender ) )
259 if ( marker->symbol() )
264 const QgsPointXY mapPoint = layerToMapTransform.transform( p );
265 if ( !rect.contains( mapPoint ) )
270 : mRenderContext.terrainRenderingEnabled() && mRenderContext.terrainGenerator()
271 ? static_cast<float>( mRenderContext.terrainGenerator()->heightAt( mapPoint.x(), mapPoint.y(), mRenderContext ) * mRenderContext.terrainSettings()->verticalScale() )
274 switch ( altitudeClamping )
283 z = terrainZ + zOffset;
288 billboard.position = (
QgsVector3D( mapPoint.
x(), mapPoint.
y(), z ) - mChunkOrigin ).toVector3D();
289 billboard.textureId = -1;
291 for (
const Billboard &existingBillboard : billboards )
293 if ( existingBillboard.markerSymbol && marker->symbol()->rendersIdenticallyTo( existingBillboard.markerSymbol ) )
296 billboard.textureId = existingBillboard.textureId;
301 if ( billboard.textureId < 0 )
304 billboard.markerSymbol = marker->symbol();
305 billboard.textureId = textures.size();
306 textures.append( QgsPoint3DBillboardMaterial::renderSymbolToImage( marker->symbol(), mRenderContext ) );
308 billboards.emplace_back( std::move( billboard ) );
312 mCalloutLines <<
QgsLineString( { mapPoint.
x(), mapPoint.
x() }, { mapPoint.
y(), mapPoint.
y() }, { terrainZ, z } );
315 mZMax = std::max( mZMax, showCallouts ? std::max( 0.0, z ) : z );
316 mZMin = std::min( mZMin, showCallouts ? std::min( 0.0, z ) : z );
326 addTextBillboard( pointText->point(), pointText->text(), pointText->format() );
331 std::unique_ptr< QgsPoint > point(
geos.pointOnSurface() );
334 addTextBillboard( *point, lineText->text(), lineText->format() );
339 switch ( rectText->placementMode() )
344 addTextBillboard( rectText->bounds().center(), rectText->text(), rectText->format() );
354 if ( pictureItem->path().isEmpty() )
363 const QgsPointXY p = pictureItem->bounds().center();
367 mapPoint = layerToMapTransform.transform( p );
375 if ( !rect.contains( mapPoint ) )
380 : mRenderContext.terrainRenderingEnabled() && mRenderContext.terrainGenerator()
381 ? static_cast<float>( mRenderContext.terrainGenerator()->heightAt( mapPoint.x(), mapPoint.y(), mRenderContext ) * mRenderContext.terrainSettings()->verticalScale() )
384 switch ( altitudeClamping )
393 z = terrainZ + zOffset;
397 PictureBillboardGroup billboardGroup;
398 billboardGroup.path = pictureItem->path();
399 billboardGroup.pictureFormat = pictureItem->format();
400 billboardGroup.scaleMode = pictureItem->billboard3DScaleMode();
402 PictureBillboard billboardItem;
403 billboardItem.position = (
QgsVector3D( mapPoint.
x(), mapPoint.
y(), z ) - mChunkOrigin ).toVector3D();
404 billboardItem.size = pictureItem->billboard3DSize();
405 if ( billboardItem.size.isEmpty() )
407 constexpr QSizeF DEFAULT_FIXED_SIZE = QSizeF( 128, 128 );
408 constexpr QSizeF DEFAULT_WORLD_SIZE = QSizeF( 20, 20 );
409 billboardItem.size = billboardGroup.scaleMode == Qgis::BillboardScaleMode::ViewIndependent ? DEFAULT_FIXED_SIZE : DEFAULT_WORLD_SIZE;
412 groupedPictures[billboardGroup].append( billboardItem );
416 mCalloutLines <<
QgsLineString( { mapPoint.
x(), mapPoint.
x() }, { mapPoint.
y(), mapPoint.
y() }, { terrainZ, z } );
419 mZMax = std::max( mZMax, showCallouts ? std::max( 0.0, z ) : z );
420 mZMin = std::min( mZMin, showCallouts ? std::min( 0.0, z ) : z );
424 mItemsToRender.clear();
426 if ( !textures.isEmpty() )
432 mBillboardPositions.reserve(
static_cast< int >( billboards.size() ) );
433 for ( Billboard &billboard : billboards )
435 const QRect textureRect = atlas.
rect( billboard.textureId );
437 geometry.
position = billboard.position;
439 static_cast< float >( textureRect.left() ) /
static_cast< float>( mBillboardAtlas.width() ),
440 1 - (
static_cast< float >( textureRect.bottom() ) /
static_cast< float>( mBillboardAtlas.height() ) )
443 static_cast< float >( textureRect.width() ) /
static_cast< float>( mBillboardAtlas.width() ),
static_cast< float>( textureRect.height() ) /
static_cast< float>( mBillboardAtlas.height() )
445 geometry.
pixelOffset = QPoint( 0, textureRect.height() / 2 );
446 mBillboardPositions.append( geometry );
451 QgsDebugError( u
"Error encountered building texture atlas"_s );
452 mBillboardAtlas = QImage();
457 mBillboardAtlas = QImage();
458 mBillboardPositions.clear();
461 if ( !textBillboardTexts.isEmpty() )
467 mTextBillboardPositions.reserve(
static_cast< int >( textBillboards.size() ) );
468 for ( TextBillboard &billboard : textBillboards )
470 int graphemeIndex = 0;
471 const int graphemeCount = atlas.
graphemeCount( billboard.text );
473 const double xOffset = atlas.
totalWidth( billboard.text ) / 2.0;
474 for ( ; graphemeIndex < graphemeCount; ++graphemeIndex )
478 geometry.
position = billboard.position;
480 static_cast< float >( textureRect.left() ) /
static_cast< float>( mTextBillboardAtlas.width() ),
481 1 - (
static_cast< float >( textureRect.bottom() ) /
static_cast< float>( mTextBillboardAtlas.height() ) )
484 static_cast< float >( textureRect.width() ) /
static_cast< float>( mTextBillboardAtlas.width() ),
485 static_cast< float>( textureRect.height() ) /
static_cast< float>( mTextBillboardAtlas.height() )
489 = QPoint(
static_cast< int >( std::round( -xOffset + pixelOffset.x() + 0.5 * textureRect.width() ) ),
static_cast< int >( std::round( pixelOffset.y() + 0.5 * textureRect.height() ) ) );
490 mTextBillboardPositions.append( geometry );
496 QgsDebugError( u
"Error encountered building font texture atlas"_s );
497 mTextBillboardAtlas = QImage();
502 mTextBillboardAtlas = QImage();
503 mTextBillboardPositions.clear();
507 for (
auto it = groupedPictures.constBegin(); it != groupedPictures.constEnd(); ++it )
509 QSizeF maxGroupSize( 0, 0 );
510 for (
auto picIt = it.value().constBegin(); picIt != it.value().constEnd(); ++picIt )
512 if ( picIt->size.width() > maxGroupSize.width() )
514 maxGroupSize.setWidth( picIt->size.width() );
516 if ( picIt->size.height() > maxGroupSize.height() )
518 maxGroupSize.setHeight( picIt->size.height() );
523 bool fitsInCache =
false;
526 constexpr int MAXIMUM_PICTURE_TEXTURE_SIZE_FIXED_SIZE = 256;
528 constexpr int MAXIMUM_PICTURE_TEXTURE_SIZE_PERSPECTIVE = 1024;
530 switch ( it.key().pictureFormat )
535 QSize imageSize = originalSize;
536 if ( imageSize.isEmpty() )
538 imageSize = maxGroupSize.toSize();
540 if ( imageSize.width() >= imageSize.height() && imageSize.width() > textureSize )
542 imageSize = QSize( textureSize,
static_cast< int >( std::round( imageSize.height() * textureSize / imageSize.width() ) ) );
544 else if ( imageSize.height() > textureSize )
546 imageSize = QSize(
static_cast< int >( std::round( imageSize.width() * textureSize / imageSize.height() ) ), textureSize );
555 if ( !picture.isNull() && picture.boundingRect().width() > 0 && picture.boundingRect().height() > 0 )
557 const QRectF picRect = picture.boundingRect();
558 QSize imageSize = picRect.size().toSize();
559 if ( imageSize.width() >= imageSize.height() )
561 imageSize = QSize( textureSize,
static_cast< int >( std::round( picRect.height() *
static_cast< double >( textureSize ) / picRect.width() ) ) );
565 imageSize = QSize(
static_cast< int >( std::round( picRect.width() *
static_cast< double >( textureSize ) / picRect.height() ) ), textureSize );
568 image = QImage( imageSize, QImage::Format_ARGB32_Premultiplied );
569 image.fill( Qt::transparent );
571 const double scale =
static_cast< double >( imageSize.width() ) / picRect.width();
573 QPainter painter( &image );
574 painter.setRenderHint( QPainter::Antialiasing );
575 painter.scale( scale, scale );
587 PictureBillboards billboard;
588 billboard.scaleMode = it.key().scaleMode;
589 billboard.image = image;
590 billboard.positions.reserve( it.value().size() );
591 billboard.sizes.reserve( it.value().size() );
592 for (
const PictureBillboard &item : it.value() )
594 billboard.positions.append( item.position );
595 billboard.sizes.append( item.size );
598 mPictureBillboards.append( billboard );
603 mFutureWatcher->setFuture( future );
606QgsAnnotationLayerChunkLoader::~QgsAnnotationLayerChunkLoader()
608 if ( mFutureWatcher && !mFutureWatcher->isFinished() )
610 disconnect( mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsChunkQueueJob::finished );
611 mFutureWatcher->waitForFinished();
615void QgsAnnotationLayerChunkLoader::cancel()
620Qt3DCore::QEntity *QgsAnnotationLayerChunkLoader::createEntity( Qt3DCore::QEntity *parent )
622 if ( mNode->level() < mFactory->mLeafLevel )
624 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity( parent );
625 entity->setObjectName( mLayerName +
"_CONTAINER_" + mNode->tileId().text() );
629 if ( mBillboardPositions.empty() && mTextBillboardPositions.empty() && mPictureBillboards.empty() )
634 mNode->updateParentBoundingBoxesRecursively();
638 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity( parent );
639 entity->setObjectName( mLayerName +
"_" + mNode->tileId().text() );
641 QgsGeoTransform *billboardTransform =
new QgsGeoTransform;
642 billboardTransform->setGeoTranslation( mChunkOrigin );
643 entity->addComponent( billboardTransform );
645 if ( !mBillboardPositions.empty() )
650 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
651 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::TriangleStrip );
652 billboardGeometryRenderer->setGeometry( billboardGeometry );
653 billboardGeometryRenderer->setVertexCount( 4 );
654 billboardGeometryRenderer->setInstanceCount( mBillboardPositions.count() );
659 Qt3DCore::QEntity *billboardEntity =
new Qt3DCore::QEntity;
660 billboardEntity->addComponent( billboardMaterial );
661 billboardEntity->addComponent( billboardGeometryRenderer );
662 billboardEntity->setParent( entity );
665 if ( !mTextBillboardPositions.empty() )
670 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
671 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::TriangleStrip );
672 billboardGeometryRenderer->setGeometry( textBillboardGeometry );
673 billboardGeometryRenderer->setVertexCount( 4 );
674 billboardGeometryRenderer->setInstanceCount( mTextBillboardPositions.count() );
679 Qt3DCore::QEntity *billboardEntity =
new Qt3DCore::QEntity;
680 billboardEntity->addComponent( billboardMaterial );
681 billboardEntity->addComponent( billboardGeometryRenderer );
682 billboardEntity->setParent( entity );
685 for (
const PictureBillboards &pictureBillboard : mPictureBillboards )
690 Qt3DRender::QGeometryRenderer *pictureGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
691 pictureGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::TriangleStrip );
692 pictureGeometryRenderer->setGeometry( pictureGeometry );
693 pictureGeometryRenderer->setVertexCount( 4 );
694 pictureGeometryRenderer->setInstanceCount(
static_cast< int >( pictureBillboard.positions.size() ) );
702 Qt3DCore::QEntity *pictureEntity =
new Qt3DCore::QEntity;
703 pictureEntity->addComponent( pictureMaterial );
704 pictureEntity->addComponent( pictureGeometryRenderer );
705 pictureEntity->setParent( entity );
708 if ( mFactory->mShowCallouts )
710 QgsLineVertexData lineData;
711 lineData.withAdjacency =
true;
712 lineData.geocentricCoordinates =
false;
717 lineData.addLineString( line, 0,
false );
720 QgsLineMaterial *mat =
new QgsLineMaterial;
721 mat->setLineColor( mFactory->mCalloutLineColor );
722 mat->setLineWidth( mFactory->mCalloutLineWidth );
724 Qt3DCore::QEntity *calloutEntity =
new Qt3DCore::QEntity;
725 calloutEntity->setObjectName( parent->objectName() +
"_CALLOUTS" );
728 Qt3DRender::QGeometryRenderer *calloutRenderer =
new Qt3DRender::QGeometryRenderer;
729 calloutRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
730 calloutRenderer->setGeometry( lineData.createGeometry( calloutEntity ) );
731 calloutRenderer->setVertexCount( lineData.indexes.count() );
732 calloutRenderer->setPrimitiveRestartEnabled(
true );
733 calloutRenderer->setRestartIndexValue( 0 );
736 calloutEntity->addComponent( calloutRenderer );
737 calloutEntity->addComponent( mat );
739 calloutEntity->setParent( entity );
743 if ( mZMin != std::numeric_limits<float>::max() && mZMax != std::numeric_limits<float>::lowest() )
748 mNode->setExactBox3D( box );
749 mNode->updateParentBoundingBoxesRecursively();
758QgsAnnotationLayerChunkLoaderFactory::QgsAnnotationLayerChunkLoaderFactory(
765 const QColor &calloutLineColor,
766 double calloutLineWidth,
771 : mRenderContext( context )
773 , mLeafLevel( leafLevel )
774 , mClamping( clamping )
775 , mZOffset( zOffset )
776 , mShowCallouts( showCallouts )
777 , mCalloutLineColor( calloutLineColor )
778 , mCalloutLineWidth( calloutLineWidth )
779 , mTextFormat( textFormat )
785 QgsDebugError( u
"Annotation layers in globe scenes are not supported yet!"_s );
786 setupQuadtree( QgsBox3D( -1e7, -1e7, -1e7, 1e7, 1e7, 1e7 ), -1, leafLevel );
793 if ( layerExtentInMapCrs.isValid() )
795 extent = context.extent().intersect( layerExtentInMapCrs );
797 if ( extent.isValid() )
799 QgsBox3D rootBox3D( extent, zMin, zMax );
802 rootBox3D.grow( 1.0 );
803 setupQuadtree( rootBox3D, -1, leafLevel );
807QgsChunkLoader *QgsAnnotationLayerChunkLoaderFactory::createChunkLoader( QgsChunkNode *node )
const
809 return new QgsAnnotationLayerChunkLoader(
this, node );
816QgsAnnotationLayerChunkedEntity::QgsAnnotationLayerChunkedEntity(
822 const QColor &calloutLineColor,
823 double calloutLineWidth,
828 : QgsAbstractFeatureBasedChunkedEntity(
831 new QgsAnnotationLayerChunkLoaderFactory(
Qgs3DRenderContext::fromMapSettings( map ), layer, 3, clamping, zOffset, showCallouts, calloutLineColor, calloutLineWidth, textFormat, zMin, zMax ),
835 onTerrainElevationOffsetChanged();
838QgsAnnotationLayerChunkedEntity::~QgsAnnotationLayerChunkedEntity()
845bool QgsAnnotationLayerChunkedEntity::applyTerrainOffset()
const
847 if (
auto loaderFactory =
static_cast<QgsAnnotationLayerChunkLoaderFactory *
>( mChunkLoaderFactory ) )
854QList<QgsRayCastHit> QgsAnnotationLayerChunkedEntity::rayIntersection(
const QgsRay3D &ray,
const QgsRayCastContext &context )
const
AltitudeClamping
Altitude clamping.
@ Relative
Elevation is relative to terrain height (final elevation = terrain elevation + feature elevation).
@ Terrain
Elevation is clamped to terrain (final elevation = terrain elevation).
@ Absolute
Elevation is taken directly from feature and is independent of terrain height (final elevation = feat...
@ Geocentric
Geocentric CRS.
PictureFormat
Picture formats.
@ Unknown
Invalid or unknown image type.
@ Vertex
Clamp every vertex of feature.
BillboardScaleMode
3D billboard scaling modes.
@ Perspective
Billboard size is scaled with perspective distance from camera, using world units.
@ SpatialBounds
Item is rendered inside fixed spatial bounds, and size will depend on map scale.
@ FixedSize
Item is rendered at a fixed size, regardless of map scale. Item's location is georeferenced to a spat...
@ RelativeToMapFrame
Items size and placement is relative to the map's frame, and the item will always be rendered in the ...
@ Reverse
Reverse/inverse transform (from destination to source).
Rendering context for preparation of 3D entities.
QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system used in the 3D scene.
QgsRectangle extent() const
Returns the 3D scene's 2D extent in the 3D scene's CRS.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
static QgsRectangle tryReprojectExtent2D(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs1, const QgsCoordinateReferenceSystem &crs2, const QgsCoordinateTransformContext &context)
Reprojects extent from crs1 to crs2 coordinate reference system with context context.
Abstract base class for annotation items which are drawn with QgsAnnotationLayers.
bool enabled() const
Returns true if the item is enabled and will be rendered in the layer.
Represents a map layer containing a set of georeferenced annotations, e.g.
An annotation item which renders text along a line geometry.
An annotation item which renders a marker symbol at a point location.
An annotation item which renders a picture.
An annotation item which renders a text string at a point location.
An annotation item which renders paragraphs of text within a rectangle.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
Geometry of the billboard rendering for points in 3D map view.
void setBillboardData(const QVector< QgsBillboardGeometry::BillboardAtlasData > &billboards, bool includePixelOffsets=false)
Set the position and texture data for the billboard.
void setPositionsAndSizes(const QVector< QVector3D > &positions, const QVector< QSizeF > &sizes)
Sets per-instance positions and sizes for billboards sharing a single texture.
A 3-dimensional box composed of x, y, z coordinates.
void setZMinimum(double z)
Sets the minimum z value.
void setZMaximum(double z)
Sets the maximum z value.
Qgis::CrsType type() const
Returns the type of the CRS.
Custom exception class for Coordinate Reference System related exceptions.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
static QgsFontTextureAtlas create(const QgsTextFormat &format, const QStringList &strings)
Creates the texture atlas for a set of strings, using the specified text format.
Encapsulates a font texture atlas.
int graphemeCount(const QString &string) const
Returns the number of graphemes to render for a given string.
bool isValid() const
Returns true if the atlas is valid.
QImage renderAtlasTexture() const
Renders the combined texture atlas, containing all required characters.
int totalWidth(const QString &string) const
Returns the total width (in pixels) required for a given string.
QRect textureRectForGrapheme(const QString &string, int graphemeIndex) const
Returns the packed rectangle for the texture for the matching grapheme.
QPoint pixelOffsetForGrapheme(const QString &string, int graphemeIndex) const
Returns the pixel offset at which the texture for the matching grapheme should be placed.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
Line string geometry type, with support for z-dimension and m-values.
QgsCoordinateReferenceSystem crs
static void drawPicture(QPainter *painter, const QPointF &point, const QPicture &picture)
Draws a picture onto a painter, correctly applying workarounds to avoid issues with incorrect scaling...
Material of the billboard rendering for points in 3D map view.
void setVerticalOffset(float offset)
Set the vertical offset.
void setTexture2DFromImage(const QImage &image)
Set the texture2D of the billboard from an image.
A representation of a ray in 3D.
Responsible for defining parameters of the ray casting operations in 3D map canvases.
A rectangle specified with double values.
QPicture svgAsPicture(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool forceVectorOutput=false, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > ¶meters=QMap< QString, QString >())
Returns an SVG drawing as a QPicture.
Represents a document consisting of one or more QgsTextBlock objects.
QStringList toPlainText() const
Returns a list of plain text lines of text representing the document.
static QgsTextDocument fromTextAndFormat(const QStringList &lines, const QgsTextFormat &format)
Constructor for QgsTextDocument consisting of a set of lines, respecting settings from a text format.
Container for all settings relating to text rendering.
static QgsTextureAtlas createFromImages(const QVector< QImage > &images, int maxSide=1000)
Creates a texture atlas for a set of images.
Encapsulates a texture atlas.
bool isValid() const
Returns true if the atlas is valid.
QRect rect(int index) const
Returns the packed rectangle for the texture with the specified index.
QImage renderAtlasTexture() const
Renders the combined texture atlas, containing all source images.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
Contains geos related utilities and functions.
bool operator<(const QVariant &v1, const QVariant &v2)
Compares two QVariant values and returns whether the first is less than the second.
#define QgsDebugError(str)
Contains the billboard positions and texture information.
QPoint pixelOffset
Optional pixel offset for billboard.
QVector3D position
Vertex position for billboard placement.
QVector2D textureAtlasOffset
Texture atlas offset for associated billboard texture.
QVector2D textureAtlasSize
Texture atlas size for associated billboard texture.