QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgstessellatedpolygongeometry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstessellatedpolygongeometry.cpp
3 --------------------------------------
4 Date : July 2017
5 Copyright : (C) 2017 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
19#include <Qt3DRender/QAttribute>
20#include <Qt3DRender/QBuffer>
21typedef Qt3DRender::QAttribute Qt3DQAttribute;
22typedef Qt3DRender::QBuffer Qt3DQBuffer;
23#else
24#include <Qt3DCore/QAttribute>
25#include <Qt3DCore/QBuffer>
26typedef Qt3DCore::QAttribute Qt3DQAttribute;
27typedef Qt3DCore::QBuffer Qt3DQBuffer;
28#endif
29
30#include "qgstessellator.h"
31#include "qgspolygon.h"
32
33QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( bool _withNormals, bool _invertNormals, bool _addBackFaces, bool _addTextureCoords, QNode *parent )
34 : QGeometry( parent )
35 , mWithNormals( _withNormals )
36 , mInvertNormals( _invertNormals )
37 , mAddBackFaces( _addBackFaces )
38 , mAddTextureCoords( _addTextureCoords )
39{
40 mVertexBuffer = new Qt3DQBuffer( this );
41
42 const QgsTessellator tmpTess( 0, 0, mWithNormals, false, false, false, mAddTextureCoords );
43 const int stride = tmpTess.stride();
44
45 mPositionAttribute = new Qt3DQAttribute( this );
46 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
47 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
48 mPositionAttribute->setVertexSize( 3 );
49 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
50 mPositionAttribute->setBuffer( mVertexBuffer );
51 mPositionAttribute->setByteStride( stride );
52 mPositionAttribute->setByteOffset( 0 );
53 addAttribute( mPositionAttribute );
54
55 if ( mWithNormals )
56 {
57 mNormalAttribute = new Qt3DQAttribute( this );
58 mNormalAttribute->setName( Qt3DQAttribute::defaultNormalAttributeName() );
59 mNormalAttribute->setVertexBaseType( Qt3DQAttribute::Float );
60 mNormalAttribute->setVertexSize( 3 );
61 mNormalAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
62 mNormalAttribute->setBuffer( mVertexBuffer );
63 mNormalAttribute->setByteStride( stride );
64 mNormalAttribute->setByteOffset( 3 * sizeof( float ) );
65 addAttribute( mNormalAttribute );
66 }
67 if ( mAddTextureCoords )
68 {
69 mTextureCoordsAttribute = new Qt3DQAttribute( this );
70 mTextureCoordsAttribute->setName( Qt3DQAttribute::defaultTextureCoordinateAttributeName() );
71 mTextureCoordsAttribute->setVertexBaseType( Qt3DQAttribute::Float );
72 mTextureCoordsAttribute->setVertexSize( 2 );
73 mTextureCoordsAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
74 mTextureCoordsAttribute->setBuffer( mVertexBuffer );
75 mTextureCoordsAttribute->setByteStride( stride );
76 mTextureCoordsAttribute->setByteOffset( mWithNormals ? 6 * sizeof( float ) : 3 * sizeof( float ) );
77 addAttribute( mTextureCoordsAttribute );
78 }
79}
80
81void QgsTessellatedPolygonGeometry::setPolygons( const QList<QgsPolygon *> &polygons, const QList<QgsFeatureId> &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList<float> &extrusionHeightPerPolygon )
82{
83 Q_ASSERT( polygons.count() == featureIds.count() );
84 mTriangleIndexStartingIndices.reserve( polygons.count() );
85 mTriangleIndexFids.reserve( polygons.count() );
86
87 QgsTessellator tessellator( origin.x(), origin.y(), mWithNormals, mInvertNormals, mAddBackFaces, false, mAddTextureCoords );
88 for ( int i = 0; i < polygons.count(); ++i )
89 {
90 Q_ASSERT( tessellator.dataVerticesCount() % 3 == 0 );
91 const uint startingTriangleIndex = static_cast<uint>( tessellator.dataVerticesCount() / 3 );
92 mTriangleIndexStartingIndices.append( startingTriangleIndex );
93 mTriangleIndexFids.append( featureIds[i] );
94
95 QgsPolygon *polygon = polygons.at( i );
96 const float extr = extrusionHeightPerPolygon.isEmpty() ? extrusionHeight : extrusionHeightPerPolygon.at( i );
97 tessellator.addPolygon( *polygon, extr );
98 }
99
100 qDeleteAll( polygons );
101
102 const QByteArray data( ( const char * )tessellator.data().constData(), tessellator.data().count() * sizeof( float ) );
103 const int nVerts = data.count() / tessellator.stride();
104
105 mVertexBuffer->setData( data );
106 mPositionAttribute->setCount( nVerts );
107 if ( mNormalAttribute )
108 mNormalAttribute->setCount( nVerts );
109 if ( mAddTextureCoords )
110 mTextureCoordsAttribute->setCount( nVerts );
111}
112
113void QgsTessellatedPolygonGeometry::setData( const QByteArray &vertexBufferData, int vertexCount, const QVector<QgsFeatureId> &triangleIndexFids, const QVector<uint> &triangleIndexStartingIndices )
114{
115 mTriangleIndexStartingIndices = triangleIndexStartingIndices;
116 mTriangleIndexFids = triangleIndexFids;
117
118 mVertexBuffer->setData( vertexBufferData );
119 mPositionAttribute->setCount( vertexCount );
120 if ( mNormalAttribute )
121 mNormalAttribute->setCount( vertexCount );
122 if ( mTextureCoordsAttribute )
123 mTextureCoordsAttribute->setCount( vertexCount );
124}
125
126
127// run binary search on a sorted array, return index i where data[i] <= x < data[i+1]
128static int binary_search( uint v, const uint *data, int count )
129{
130 int idx0 = 0;
131 int idx1 = count - 1;
132
133 if ( v < data[0] || v >= data[count - 1] )
134 return -1; // not in the array
135
136 while ( idx0 != idx1 )
137 {
138 const int idxPivot = ( idx0 + idx1 ) / 2;
139 const uint pivot = data[idxPivot];
140 if ( pivot <= v )
141 {
142 if ( data[idxPivot + 1] > v )
143 return idxPivot; // we're done!
144 else // continue searching values greater than the pivot
145 idx0 = idxPivot;
146 }
147 else // continue searching values lower than the pivot
148 idx1 = idxPivot;
149 }
150 return idx0;
151}
152
153
155{
156 const int i = binary_search( triangleIndex, mTriangleIndexStartingIndices.constData(), mTriangleIndexStartingIndices.count() );
157 return i != -1 ? mTriangleIndexFids[i] : FID_NULL;
158}
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
Polygon geometry type.
Definition: qgspolygon.h:34
void setPolygons(const QList< QgsPolygon * > &polygons, const QList< QgsFeatureId > &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList< float > &extrusionHeightPerPolygon=QList< float >())
Initializes vertex buffer from given polygons. Takes ownership of passed polygon geometries.
QgsFeatureId triangleIndexToFeatureId(uint triangleIndex) const
Returns ID of the feature to which given triangle index belongs (used for picking).
QgsTessellatedPolygonGeometry(bool _withNormals=true, bool invertNormals=false, bool addBackFaces=false, bool addTextureCoords=false, QNode *parent=nullptr)
Constructor.
void setData(const QByteArray &vertexBufferData, int vertexCount, const QVector< QgsFeatureId > &triangleIndexFids, const QVector< uint > &triangleIndexStartingIndices)
Initializes vertex buffer (and other members) from data that were already tessellated.
Class that takes care of tessellation of polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
int stride() const
Returns size of one vertex entry in bytes.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
#define FID_NULL
Definition: qgsfeatureid.h:29
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer