QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
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
18#include <QMatrix4x4>
19
20#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
21#include <Qt3DRender/QAttribute>
22#include <Qt3DRender/QBuffer>
23typedef Qt3DRender::QAttribute Qt3DQAttribute;
24typedef Qt3DRender::QBuffer Qt3DQBuffer;
25#else
26#include <Qt3DCore/QAttribute>
27#include <Qt3DCore/QBuffer>
28typedef Qt3DCore::QAttribute Qt3DQAttribute;
29typedef Qt3DCore::QBuffer Qt3DQBuffer;
30#endif
31
32#include "qgstessellator.h"
33#include "qgspolygon.h"
34
35QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( bool _withNormals, bool _invertNormals, bool _addBackFaces, bool _addTextureCoords, QNode *parent )
36 : QGeometry( parent )
37 , mWithNormals( _withNormals )
38 , mInvertNormals( _invertNormals )
39 , mAddBackFaces( _addBackFaces )
40 , mAddTextureCoords( _addTextureCoords )
41{
42 mVertexBuffer = new Qt3DQBuffer( this );
43
44 const QgsTessellator tmpTess( 0, 0, mWithNormals, false, false, false, mAddTextureCoords );
45 const int stride = tmpTess.stride();
46
47 mPositionAttribute = new Qt3DQAttribute( this );
48 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
49 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
50 mPositionAttribute->setVertexSize( 3 );
51 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
52 mPositionAttribute->setBuffer( mVertexBuffer );
53 mPositionAttribute->setByteStride( stride );
54 mPositionAttribute->setByteOffset( 0 );
55 addAttribute( mPositionAttribute );
56
57 if ( mWithNormals )
58 {
59 mNormalAttribute = new Qt3DQAttribute( this );
60 mNormalAttribute->setName( Qt3DQAttribute::defaultNormalAttributeName() );
61 mNormalAttribute->setVertexBaseType( Qt3DQAttribute::Float );
62 mNormalAttribute->setVertexSize( 3 );
63 mNormalAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
64 mNormalAttribute->setBuffer( mVertexBuffer );
65 mNormalAttribute->setByteStride( stride );
66 mNormalAttribute->setByteOffset( 3 * sizeof( float ) );
67 addAttribute( mNormalAttribute );
68 }
69 if ( mAddTextureCoords )
70 {
71 mTextureCoordsAttribute = new Qt3DQAttribute( this );
72 mTextureCoordsAttribute->setName( Qt3DQAttribute::defaultTextureCoordinateAttributeName() );
73 mTextureCoordsAttribute->setVertexBaseType( Qt3DQAttribute::Float );
74 mTextureCoordsAttribute->setVertexSize( 2 );
75 mTextureCoordsAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
76 mTextureCoordsAttribute->setBuffer( mVertexBuffer );
77 mTextureCoordsAttribute->setByteStride( stride );
78 mTextureCoordsAttribute->setByteOffset( mWithNormals ? 6 * sizeof( float ) : 3 * sizeof( float ) );
79 addAttribute( mTextureCoordsAttribute );
80 }
81}
82
83void QgsTessellatedPolygonGeometry::setPolygons( const QList<QgsPolygon *> &polygons, const QList<QgsFeatureId> &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList<float> &extrusionHeightPerPolygon )
84{
85 Q_ASSERT( polygons.count() == featureIds.count() );
86 mTriangleIndexStartingIndices.reserve( polygons.count() );
87 mTriangleIndexFids.reserve( polygons.count() );
88
89 QgsTessellator tessellator( origin.x(), origin.y(), mWithNormals, mInvertNormals, mAddBackFaces, false, mAddTextureCoords );
90 for ( int i = 0; i < polygons.count(); ++i )
91 {
92 Q_ASSERT( tessellator.dataVerticesCount() % 3 == 0 );
93 const uint startingTriangleIndex = static_cast<uint>( tessellator.dataVerticesCount() / 3 );
94 mTriangleIndexStartingIndices.append( startingTriangleIndex );
95 mTriangleIndexFids.append( featureIds[i] );
96
97 QgsPolygon *polygon = polygons.at( i );
98 const float extr = extrusionHeightPerPolygon.isEmpty() ? extrusionHeight : extrusionHeightPerPolygon.at( i );
99 tessellator.addPolygon( *polygon, extr );
100 }
101
102 qDeleteAll( polygons );
103
104 const QByteArray data( ( const char * )tessellator.data().constData(), tessellator.data().count() * sizeof( float ) );
105 const int nVerts = data.count() / tessellator.stride();
106
107 mVertexBuffer->setData( data );
108 mPositionAttribute->setCount( nVerts );
109 if ( mNormalAttribute )
110 mNormalAttribute->setCount( nVerts );
111 if ( mAddTextureCoords )
112 mTextureCoordsAttribute->setCount( nVerts );
113}
114
115void QgsTessellatedPolygonGeometry::setData( const QByteArray &vertexBufferData, int vertexCount, const QVector<QgsFeatureId> &triangleIndexFids, const QVector<uint> &triangleIndexStartingIndices )
116{
117 mTriangleIndexStartingIndices = triangleIndexStartingIndices;
118 mTriangleIndexFids = triangleIndexFids;
119
120 mVertexBuffer->setData( vertexBufferData );
121 mPositionAttribute->setCount( vertexCount );
122 if ( mNormalAttribute )
123 mNormalAttribute->setCount( vertexCount );
124 if ( mTextureCoordsAttribute )
125 mTextureCoordsAttribute->setCount( vertexCount );
126}
127
128// run binary search on a sorted array, return index i where data[i] <= v < data[i+1]
129static int binary_search( uint v, const uint *data, int count )
130{
131 int idx0 = 0;
132 int idx1 = count - 1;
133
134 if ( v < data[0] )
135 return -1; // not in the array
136
137 if ( v >= data[count - 1] )
138 return count - 1; // for larger values the last bin is returned
139
140 while ( idx0 != idx1 )
141 {
142 const int idxPivot = ( idx0 + idx1 ) / 2;
143 const uint pivot = data[idxPivot];
144 if ( pivot <= v )
145 {
146 if ( data[idxPivot + 1] > v )
147 return idxPivot; // we're done!
148 else // continue searching values greater than the pivot
149 idx0 = idxPivot;
150 }
151 else // continue searching values lower than the pivot
152 idx1 = idxPivot;
153 }
154 return idx0;
155}
156
157
159{
160 const int i = binary_search( triangleIndex, mTriangleIndexStartingIndices.constData(), mTriangleIndexStartingIndices.count() );
161 return i != -1 ? mTriangleIndexFids[i] : FID_NULL;
162}
bool isEmpty() const override
Returns true if the geometry is empty.
A class to represent a 2D point.
Definition qgspointxy.h:59
double y
Definition qgspointxy.h:63
double x
Definition qgspointxy.h:62
Polygon geometry type.
Definition qgspolygon.h:34
QVector< QgsFeatureId > featureIds() const
Returns included feature ids.
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.
QVector< uint > triangleIndexStartingIndices() const
Returns triangle index for features. For a feature featureIds()[i], matching triangles start at trian...
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.
Qt3DCore::QAttribute Qt3DQAttribute
Definition qgs3daxis.cpp:28
Qt3DCore::QBuffer Qt3DQBuffer
Definition qgs3daxis.cpp:30
#define FID_NULL
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer