20#include <unordered_set>
37static std::pair<float, float> rotateCoords(
float x,
float y,
float origin_x,
float origin_y,
float r )
39 r = qDegreesToRadians( r );
40 float x0 = x - origin_x, y0 = y - origin_y;
44 const float x1 = origin_x + x0 * qCos( r ) - y0 * qSin( r );
45 const float y1 = origin_y + x0 * qSin( r ) + y0 * qCos( r );
46 return std::make_pair( x1, y1 );
49void QgsTessellator::addExtrusionWallQuad(
const QVector3D &pt1,
const QVector3D &pt2,
float height )
51 const float dx = pt2.x() - pt1.x();
52 const float dy = pt2.y() - pt1.y();
55 QVector3D vn = mOutputZUp ? QVector3D( -dy, dx, 0 ) : QVector3D( -dy, 0, -dx );
63 QVector<double> textureCoordinates;
64 textureCoordinates.reserve( 12 );
66 if ( fabsf( dy ) <= fabsf( dx ) )
70 v0 = pt1.z() + height;
73 v1 = pt2.z() + height;
85 v0 = pt1.z() + height;
88 v1 = pt2.z() + height;
97 textureCoordinates.push_back( u0 );
98 textureCoordinates.push_back( v0 );
100 textureCoordinates.push_back( u1 );
101 textureCoordinates.push_back( v1 );
103 textureCoordinates.push_back( u2 );
104 textureCoordinates.push_back( v2 );
106 textureCoordinates.push_back( u3 );
107 textureCoordinates.push_back( v3 );
109 for (
int i = 0; i < textureCoordinates.size(); i += 2 )
111 const std::pair<float, float> rotated = rotateCoords( textureCoordinates[i], textureCoordinates[i + 1], 0, 0, mTextureRotation );
112 textureCoordinates[i] = rotated.first;
113 textureCoordinates[i + 1] = rotated.second;
119 mData << pt1.x() << pt1.y() << pt1.z() + height;
121 mData << pt1.x() << pt1.z() + height << -pt1.y();
123 mData << vn.x() << vn.y() << vn.z();
124 if ( mAddTextureCoords )
125 mData << textureCoordinates[0] << textureCoordinates[1];
130 mData << pt2.x() << pt2.y() << pt2.z() + height;
132 mData << pt2.x() << pt2.z() + height << -pt2.y();
134 mData << vn.x() << vn.y() << vn.z();
135 if ( mAddTextureCoords )
136 mData << textureCoordinates[2] << textureCoordinates[3];
141 mData << pt1.x() << pt1.y() << pt1.z();
143 mData << pt1.x() << pt1.z() << -pt1.y();
145 mData << vn.x() << vn.y() << vn.z();
146 if ( mAddTextureCoords )
147 mData << textureCoordinates[4] << textureCoordinates[5];
158 mData << pt2.x() << pt2.y() << pt2.z();
160 mData << pt2.x() << pt2.z() << -pt2.y();
162 mData << vn.x() << vn.y() << vn.z();
163 if ( mAddTextureCoords )
164 mData << textureCoordinates[6] << textureCoordinates[7];
175 setExtrusionFacesLegacy( facade );
186 setExtrusionFacesLegacy( facade );
203 mScale = bounds.
isNull() ? 1.0 : std::max( 10000.0 / bounds.
width(), 10000.0 / bounds.
height() );
208 mInputZValueIgnored = ignore;
213 mExtrusionFaces = faces;
216void QgsTessellator::setExtrusionFacesLegacy(
int facade )
242 mTextureRotation = rotation;
247 mAddBackFaces = addBackFaces;
252 mInvertNormals = invertNormals;
257 mAddNormals = addNormals;
263 mAddTextureCoords = addTextureUVs;
272void QgsTessellator::updateStride()
274 mStride = 3 *
sizeof( float );
276 mStride += 3 *
sizeof( float );
277 if ( mAddTextureCoords )
278 mStride += 2 *
sizeof( float );
281void QgsTessellator::makeWalls(
const QgsLineString &ring,
bool ccw,
float extrusionHeight )
289 QgsPoint ptPrev = ring.
pointN( is_counter_clockwise == ccw ? 0 : ring.
numPoints() - 1 );
290 for (
int i = 1; i < ring.
numPoints(); ++i )
292 pt = ring.
pointN( is_counter_clockwise == ccw ? i : ring.
numPoints() - i - 1 );
295 static_cast<float>( ptPrev.
x() - mOrigin.x() ),
296 static_cast<float>( ptPrev.
y() - mOrigin.y() ),
297 static_cast<float>( std::isnan( ptPrev.
z() ) ? 0 : ptPrev.
z() - mOrigin.z() ) );
300 static_cast<float>( pt.
x() - mOrigin.x() ),
301 static_cast<float>( pt.
y() - mOrigin.y() ),
302 static_cast<float>( std::isnan( pt.
z() ) ? 0 : pt.
z() - mOrigin.z() ) );
305 addExtrusionWallQuad( pt1, pt2, extrusionHeight );
310static QVector3D calculateNormal(
const QgsLineString *curve,
double originX,
double originY,
double originZ,
bool invertNormal,
float extrusionHeight )
315 if ( extrusionHeight != 0 )
316 return QVector3D( 0, 0, 1 );
319 float orientation = 1.f;
321 orientation = -orientation;
323 orientation = -orientation;
324 return QVector3D( 0, 0, orientation );
332 for (
int i = 1; i < curve->
numPoints(); i++ )
335 if ( pt1.
z() != pt2.
z() )
341 if ( sameZ && extrusionHeight != 0 )
342 return QVector3D( 0, 0, 1 );
349 double nx = 0, ny = 0, nz = 0;
352 pt1.
setX( pt1.
x() - originX );
353 pt1.
setY( pt1.
y() - originY );
354 pt1.
setZ( std::isnan( pt1.
z() ) ? 0.0 : pt1.
z() - originZ );
355 for (
int i = 1; i < curve->
numPoints(); i++ )
358 pt2.
setX( pt2.
x() - originX );
359 pt2.
setY( pt2.
y() - originY );
360 pt2.
setZ( std::isnan( pt2.
z() ) ? 0.0 : pt2.
z() - originZ );
362 nx += ( pt1.
y() - pt2.
y() ) * ( pt1.
z() + pt2.
z() );
363 ny += ( pt1.
z() - pt2.
z() ) * ( pt1.
x() + pt2.
x() );
364 nz += ( pt1.
x() - pt2.
x() ) * ( pt1.
y() + pt2.
y() );
369 QVector3D normal( nx, ny, nz );
377static void normalVectorToXYVectors(
const QVector3D &pNormal, QVector3D &pXVector, QVector3D &pYVector )
382 if ( pNormal.z() > 0.001 || pNormal.z() < -0.001 )
384 pXVector = QVector3D( 1, 0, -pNormal.x() / pNormal.z() );
386 else if ( pNormal.y() > 0.001 || pNormal.y() < -0.001 )
388 pXVector = QVector3D( 1, -pNormal.x() / pNormal.y(), 0 );
392 pXVector = QVector3D( -pNormal.y() / pNormal.x(), 1, 0 );
394 pXVector.normalize();
395 pYVector = QVector3D::normal( pNormal, pXVector );
400 std::size_t
operator()(
const std::pair<float, float> pair )
const
402 const std::size_t h1 = std::hash<float>()( pair.first );
403 const std::size_t h2 = std::hash<float>()( pair.second );
413 polyline.reserve( pCount );
415 const double *srcXData = ring->
xData();
416 const double *srcYData = ring->
yData();
417 const double *srcZData = ring->
zData();
418 std::unordered_set<std::pair<float, float>,
float_pair_hash> foundPoints;
420 for (
int i = 0; i < pCount - 1; ++i )
422 const float x = *srcXData++;
423 const float y = *srcYData++;
425 const auto res = foundPoints.insert( std::make_pair( x, y ) );
432 p2t::Point *pt2 =
new p2t::Point( x, y );
433 polyline.push_back( pt2 );
436 ( *zHash )[pt2] = *srcZData++;
444 const double exp = 1e10;
445 return round( x * exp ) / exp;
458 double *xData = x.data();
459 double *yData = y.data();
460 double *zData = z.data();
462 const double *srcXData = curve.
xData();
463 const double *srcYData = curve.
yData();
464 const double *srcZData = curve.
is3D() ? curve.
zData() :
nullptr;
466 for (
int i = 0; i < count; ++i )
468 QVector4D v( *srcXData++ - pt0.
x(),
469 *srcYData++ - pt0.
y(),
470 srcZData ? *srcZData++ - pt0.
z() : 0,
473 v = toNewBase->map( v );
476 v.setX( v.x() * scale );
477 v.setY( v.y() * scale );
511 std::vector< const QgsLineString * > rings;
520 if ( numPoints <= 1 )
523 const double *srcXData = ring->
xData();
524 const double *srcYData = ring->
yData();
525 double x0 = *srcXData++;
526 double y0 = *srcYData++;
527 for (
int i = 1; i < numPoints; ++i )
529 const double x1 = *srcXData++;
530 const double y1 = *srcYData++;
539 return min_d != 1e20 ? std::sqrt( min_d ) : 1e20;
544 return QByteArray(
reinterpret_cast<const char *
>( mData.constData() ),
sizeof(
float ) * mData.size() );
549 return QByteArray(
reinterpret_cast<const char *
>( mIndexBuffer.constData() ),
sizeof( uint32_t ) * mIndexBuffer.size() );
552void QgsTessellator::calculateBaseTransform(
const QVector3D &pNormal, QMatrix4x4 *base )
const
554 if ( !mInputZValueIgnored && pNormal != QVector3D( 0, 0, 1 ) )
558 QVector3D pXVector, pYVector;
559 normalVectorToXYVectors( pNormal, pXVector, pYVector );
565 pXVector.x(), pXVector.y(), pXVector.z(), 0,
566 pYVector.x(), pYVector.y(), pYVector.z(), 0,
567 pNormal.x(), pNormal.y(), pNormal.z(), 0,
572 base->setToIdentity();
576QVector3D QgsTessellator::applyTransformWithExtrusion(
577 const QVector3D point,
578 float extrusionHeight,
579 QMatrix4x4 *transformMatrix,
583 const float z = mInputZValueIgnored ? 0.0f : point.z();
584 QVector4D pt( point.x(), point.y(), z, 0 );
586 pt = *transformMatrix * pt;
588 const double fx = pt.
x() - mOrigin.x() + originOffset->
x();
589 const double fy = pt.y() - mOrigin.y() + originOffset->
y();
590 const double baseHeight = mInputZValueIgnored ? 0 : pt.z() - mOrigin.z() + originOffset->
z();
591 const double fz = mInputZValueIgnored ? 0.0 : ( baseHeight + extrusionHeight );
593 if ( baseHeight < mZMin )
594 mZMin =
static_cast<float>( baseHeight );
595 if ( baseHeight > mZMax )
596 mZMax =
static_cast<float>( baseHeight );
598 mZMax =
static_cast<float>( fz );
602 return QVector3D(
static_cast<float>( fx ),
static_cast<float>( fy ),
static_cast<float>( fz ) );
604 return QVector3D(
static_cast<float>( fx ),
static_cast<float>( fz ),
static_cast<float>( -fy ) );
609void QgsTessellator::ringToEarcutPoints(
const QgsLineString *ring, std::vector<std::array<double, 2>> &polyline, QHash<std::array<double, 2>*,
float> *zHash )
613 polyline.reserve( pCount );
615 const double *srcXData = ring->
xData();
616 const double *srcYData = ring->
yData();
617 const double *srcZData = ring->
zData();
620 for (
int i = 0; i < pCount - 1; ++i )
622 const float x =
static_cast<float>( *srcXData++ );
623 const float y =
static_cast<float>( *srcYData++ );
625 std::array<double, 2> pt = { x, y };
626 polyline.push_back( pt );
628 if ( zHash && srcZData )
630 ( *zHash )[ &pt ] = *srcZData++;
635std::vector<QVector3D> QgsTessellator::generateConstrainedDelaunayTriangles(
const QgsPolygon *polygonNew )
637 QList<std::vector<p2t::Point *>> polylinesToDelete;
638 QHash<p2t::Point *, float> z;
641 std::vector<p2t::Point *> polyline;
643 polylinesToDelete << polyline;
645 p2t::CDT cdt = p2t::CDT( polyline );
650 std::vector<p2t::Point *> holePolyline;
653 ringToPoly2tri( hole, holePolyline, mInputZValueIgnored ?
nullptr : &z );
655 cdt.AddHole( holePolyline );
656 polylinesToDelete << holePolyline;
660 std::vector<p2t::Triangle *> triangles = cdt.GetTriangles();
662 std::vector<QVector3D> trianglePoints;
663 trianglePoints.reserve( triangles.size() * 3 );
665 for ( p2t::Triangle *t : triangles )
667 trianglePoints.emplace_back( t->GetPoint( 0 )->x / mScale, t->GetPoint( 0 )->y / mScale, z.value( t->GetPoint( 0 ) ) );
668 trianglePoints.emplace_back( t->GetPoint( 1 )->x / mScale, t->GetPoint( 1 )->y / mScale, z.value( t->GetPoint( 1 ) ) );
669 trianglePoints.emplace_back( t->GetPoint( 2 )->x / mScale, t->GetPoint( 2 )->y / mScale, z.value( t->GetPoint( 2 ) ) );
672 for (
int i = 0; i < polylinesToDelete.count(); ++i )
673 qDeleteAll( polylinesToDelete[i] );
675 return trianglePoints;
678std::vector<QVector3D> QgsTessellator::generateEarcutTriangles(
const QgsPolygon *polygonNew )
680 QHash<std::array<double, 2>*,
float> z;
681 std::vector<std::vector<std::array<double, 2>>> rings;
682 std::vector<std::array<double, 2>> polyline;
685 rings.push_back( polyline );
689 std::vector<std::array<double, 2>> holePolyline;
691 rings.push_back( holePolyline );
694 std::vector<std::array<double, 2>> points;
695 for (
const auto &ring : rings )
697 points.insert( points.end(), ring.begin(), ring.end() );
700 std::vector<uint32_t> indices = mapbox::earcut<uint32_t>( rings );
701 std::vector<QVector3D> trianglePoints;
702 trianglePoints.reserve( points.size() );
704 for (
size_t i = 0; i < indices.size(); i++ )
706 uint32_t vertexIndex = indices[ i ];
707 std::array<double, 2> vertex = points[ vertexIndex ];
709 double x = vertex[ 0 ];
710 double y = vertex[ 1 ];
712 float zValue = z.value( &vertex, 0.0f );
714 trianglePoints.emplace_back( x / mScale, y / mScale, zValue );
717 return trianglePoints;
720void QgsTessellator::addVertex(
const QVector3D &point,
const QVector3D &normal,
float extrusionHeight, QMatrix4x4 *transformMatrix,
const QgsPoint *originOffset, QHash<VertexPoint, unsigned int> *vertexBuffer,
const size_t &vertexBufferOffset )
722 const QVector3D pt = applyTransformWithExtrusion( point, extrusionHeight, transformMatrix, originOffset );
723 const VertexPoint vertex( pt, normal );
727 mIndexBuffer << vertexBufferOffset + index;
733 mIndexBuffer << vertexBufferOffset + index;
735 mData << pt.x() << pt.y() << pt.z();
738 mData << normal.x() << normal.y() << normal.z();
740 if ( mAddTextureCoords )
742 const std::pair<float, float> pr = rotateCoords(
static_cast<float>( point.x() ),
static_cast<float>( point.y() ), 0.0f, 0.0f, mTextureRotation );
743 mData << pr.first << pr.second;
748void QgsTessellator::addVertex(
const QVector3D &point,
const QVector3D &normal,
float extrusionHeight, QMatrix4x4 *transformMatrix,
const QgsPoint *originOffset )
750 const QVector3D pt = applyTransformWithExtrusion( point, extrusionHeight, transformMatrix, originOffset );
752 mData << pt.x() << pt.y() << pt.z();
755 mData << normal.x() << normal.y() << normal.z();
757 if ( mAddTextureCoords )
759 const std::pair<float, float> pr = rotateCoords(
static_cast<float>( point.x() ),
static_cast<float>( point.y() ), 0.0f, 0.0f, mTextureRotation );
760 mData << pr.first << pr.second;
770 const QVector3D pNormal = !mInputZValueIgnored ? calculateNormal( exterior, mOrigin.x(), mOrigin.y(), mOrigin.z(), mInvertNormals, extrusionHeight ) : QVector3D();
771 const int pCount = exterior->
numPoints();
778 std::unique_ptr<QgsPolygon> polygonNew;
780 if ( !mInputZValueIgnored && !
qgsDoubleNear( pNormal.length(), 1, 0.001 ) )
787 if ( buildFloor || buildRoof )
789 calculateBaseTransform( pNormal, &base );
795 normal = QVector3D( pNormal.x(), pNormal.z(), - pNormal.y() );
802 base = base.transposed();
806 Q_ASSERT( polygonNew->exteriorRing()->numPoints() >= 3 );
809 const QVector3D p1(
static_cast<float>( triangle->
xAt( 0 ) ),
static_cast<float>( triangle->
yAt( 0 ) ),
static_cast<float>( triangle->
zAt( 0 ) ) );
810 const QVector3D p2(
static_cast<float>( triangle->
xAt( 1 ) ),
static_cast<float>( triangle->
yAt( 1 ) ),
static_cast<float>( triangle->
zAt( 1 ) ) );
811 const QVector3D p3(
static_cast<float>( triangle->
xAt( 2 ) ),
static_cast<float>( triangle->
yAt( 2 ) ),
static_cast<float>( triangle->
zAt( 2 ) ) );
812 std::array<QVector3D, 3> points = { p1, p2, p3 };
814 for (
const QVector3D &point : points )
816 addVertex( point, normal, extrusionHeight, &base, &extrusionOrigin );
821 for (
size_t i = points.size(); i-- > 0; )
823 const QVector3D &point = points[ i ];
824 addVertex( point, -normal, extrusionHeight, &base, &extrusionOrigin );
828 if ( extrusionHeight != 0 && buildFloor )
830 for (
const QVector3D &point : points )
832 addVertex( point, normal, 0.0, &base, &extrusionOrigin );
837 for (
size_t i = points.size(); i-- > 0; )
839 const QVector3D &point = points[ i ];
840 addVertex( point, -normal, 0.0, &base, &extrusionOrigin );
854 if ( polygonSimplified.
isNull() )
856 mError = QObject::tr(
"geometry simplification failed - skipping" );
864 mError = QObject::tr(
"geometry's coordinates are too close to each other and simplification failed - skipping" );
869 polygonNew.reset( polygonSimplifiedData->
clone() );
876 std::vector<QVector3D> trianglePoints;
877 switch ( mTriangulationAlgorithm )
880 trianglePoints = generateConstrainedDelaunayTriangles( polygonNew.get() );
883 trianglePoints = generateEarcutTriangles( polygonNew.get() );
887 if ( trianglePoints.empty() )
889 mError = QObject::tr(
"Failed to triangulate polygon." );
893 Q_ASSERT( trianglePoints.size() % 3 == 0 );
895 mData.reserve( mData.size() + trianglePoints.size() * 3 * (
stride() /
sizeof(
float ) ) );
899 for (
size_t i = 0; i < trianglePoints.size(); i += 3 )
901 const std::array<QVector3D, 3> points = { trianglePoints[ i + 0 ], trianglePoints[ i + 1 ], trianglePoints[ i + 2 ] };
904 for (
const QVector3D &point : points )
906 addVertex( point, normal, extrusionHeight, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
911 for (
size_t i = points.size(); i-- > 0; )
913 const QVector3D &point = points[ i ];
914 addVertex( point, -normal, extrusionHeight, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
918 if ( extrusionHeight != 0 && buildFloor )
920 for (
const QVector3D &point : points )
922 addVertex( point, normal, 0.0, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
927 for (
size_t i = points.size(); i-- > 0; )
929 const QVector3D &point = points[ i ];
930 addVertex( point, -normal, 0.0, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
936 catch ( std::runtime_error &err )
942 mError = QObject::tr(
"An unknown error occurred" );
948 if ( extrusionHeight != 0 && buildWalls )
950 makeWalls( *exterior,
false, extrusionHeight );
958 return mIndexBuffer.size();
963 auto mp = std::make_unique< QgsMultiPolygon >();
964 const size_t nVals = mIndexBuffer.size();
966 Q_ASSERT( nVals % 3 == 0 );
968 mp->reserve( nVals / 3 );
969 const size_t noOfElements =
stride() /
sizeof( float );
971 for (
size_t i = 0; i + 2 < nVals; i += 3 )
973 const uint32_t index1 = mIndexBuffer[ i ] * noOfElements;
974 const uint32_t index2 = mIndexBuffer[ i + 1 ] * noOfElements;
975 const uint32_t index3 = mIndexBuffer[ i + 2 ] * noOfElements;
979 const QgsPoint p1( mData[ index1 ], mData[ index1 + 1 ], mData[ index1 + 2 ] );
980 const QgsPoint p2( mData[ index2 ], mData[ index2 + 1 ], mData[ index2 + 2 ] );
981 const QgsPoint p3( mData[ index3 ], mData[ index3 + 1 ], mData[ index3 + 2 ] );
987 const QgsPoint p1( mData[ index1 ], -mData[ index1 + 2 ], mData[ index1 + 1 ] );
988 const QgsPoint p2( mData[ index2 ], -mData[ index2 + 2 ], mData[ index2 + 1 ] );
989 const QgsPoint p3( mData[ index3 ], -mData[ index3 + 2 ], mData[ index3 + 1 ] );
999 const size_t n = mIndexBuffer.size();
1001 return QVector<float>();
1003 QVector<float> tData;
1004 size_t noOfElements =
stride() /
sizeof( float );
1005 tData.reserve( n * noOfElements );
1007 for (
auto &index : mIndexBuffer )
1009 for (
size_t i = 0; i < noOfElements; i++ )
1011 tData << mData[ index * noOfElements + i ];
1020 if ( mData.size() == 0 )
1023 return mData.size() / (
stride() /
sizeof( float ) );
@ CounterClockwise
Counter-clockwise direction.
@ Clockwise
Clockwise direction.
TriangulationAlgorithm
Triangulation algorithms.
QFlags< ExtrusionFace > ExtrusionFaces
Tessellator extrusion face types.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
Qgis::AngularDirection orientation() const
Returns the curve's orientation, e.g.
static double sqrDistance2D(double x1, double y1, double x2, double y2)
Returns the squared 2D distance between (x1, y1) and (x2, y2).
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
QgsPoint startPoint() const override
Returns the starting point of the curve.
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
double zAt(int index) const override
Returns the z-coordinate of the specified node in the line string.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Point geometry type, with support for z-dimension and m-values.
void setY(double y)
Sets the point's y-coordinate.
void setX(double x)
Sets the point's x-coordinate.
void setZ(double z)
Sets the point's z-coordinate.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership).
QgsPolygon * clone() const override
Clones the geometry by performing a deep copy.
A rectangle specified with double values.
std::unique_ptr< QgsMultiPolygon > asMultiPolygon() const
Returns the triangulation as a multipolygon geometry.
float textureRotation() const
Returns the rotation of texture UV coordinates (in degrees).
void setTextureRotation(float rotation)
Sets the rotation of texture UV coordinates (in degrees).
void setOrigin(const QgsVector3D &origin)
Sets the origin point of the map.
void setTriangulationAlgorithm(Qgis::TriangulationAlgorithm algorithm)
Sets the triangulation algorithm.
Q_DECL_DEPRECATED QVector< float > data() const
Returns array of triangle vertex data.
QByteArray vertexBuffer() const
Returns vertex buffer for the generated points.
int stride() const
Returns size of one vertex entry in bytes.
void setBounds(const QgsRectangle &bounds)
Sets scaling and the bounds of the input geometry coordinates.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
QgsVector3D origin() const
Returns the origin point of the map.
int uniqueVertexCount() const
Returns unique vertex count.
QByteArray indexBuffer() const
Returns index buffer for the generated points.
void setInvertNormals(bool invertNormals)
Sets whether normals should be inverted (true) or not (false).
void setBackFacesEnabled(bool addBackFaces)
Sets whether back faces should be added to the output data (true) or not (false).
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
void setExtrusionFaces(Qgis::ExtrusionFaces faces)
Sets which faces should be generated during extrusion.
void setInputZValueIgnored(bool ignore)
Sets whether Z values from the input geometries are ignored (true) or not (false).
void setAddTextureUVs(bool addTextureUVs)
Sets whether texture UV coordinates should be added to the output data (true) or not (false).
void setAddNormals(bool addNormals)
Sets whether normals should be added to the output data (true) or not (false).
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
double minimumDistanceBetweenCoordinates(const QgsPolygon &polygon)
void ringToPoly2tri(const QgsLineString *ring, std::vector< p2t::Point * > &polyline, QHash< p2t::Point *, float > *zHash)
QgsPolygon * transformPolygonToNewBase(const QgsPolygon &polygon, const QgsPoint &pt0, const QMatrix4x4 *toNewBase, const float scale)
double roundCoord(double x)
std::size_t operator()(const std::pair< float, float > pair) const