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];
174 setExtrusionFacesLegacy( facade );
184 setExtrusionFacesLegacy( facade );
201 mScale = bounds.
isNull() ? 1.0 : std::max( 10000.0 / bounds.
width(), 10000.0 / bounds.
height() );
206 mInputZValueIgnored = ignore;
211 mExtrusionFaces = faces;
214void QgsTessellator::setExtrusionFacesLegacy(
int facade )
240 mTextureRotation = rotation;
245 mAddBackFaces = addBackFaces;
250 mInvertNormals = invertNormals;
255 mAddNormals = addNormals;
261 mAddTextureCoords = addTextureUVs;
270void QgsTessellator::updateStride()
272 mStride = 3 *
sizeof( float );
274 mStride += 3 *
sizeof( float );
275 if ( mAddTextureCoords )
276 mStride += 2 *
sizeof( float );
279void QgsTessellator::makeWalls(
const QgsLineString &ring,
bool ccw,
float extrusionHeight )
287 QgsPoint ptPrev = ring.
pointN( is_counter_clockwise == ccw ? 0 : ring.
numPoints() - 1 );
288 for (
int i = 1; i < ring.
numPoints(); ++i )
290 pt = ring.
pointN( is_counter_clockwise == ccw ? i : ring.
numPoints() - i - 1 );
292 const QVector3D pt1(
static_cast<float>( ptPrev.
x() - mOrigin.x() ),
static_cast<float>( ptPrev.
y() - mOrigin.y() ),
static_cast<float>( std::isnan( ptPrev.
z() ) ? 0 : ptPrev.
z() - mOrigin.z() ) );
294 const QVector3D pt2(
static_cast<float>( pt.
x() - mOrigin.x() ),
static_cast<float>( pt.
y() - mOrigin.y() ),
static_cast<float>( std::isnan( pt.
z() ) ? 0 : pt.
z() - mOrigin.z() ) );
297 addExtrusionWallQuad( pt1, pt2, extrusionHeight );
302static QVector3D calculateNormal(
const QgsLineString *curve,
double originX,
double originY,
double originZ,
bool invertNormal,
float extrusionHeight )
307 if ( extrusionHeight != 0 )
308 return QVector3D( 0, 0, 1 );
311 float orientation = 1.f;
313 orientation = -orientation;
315 orientation = -orientation;
316 return QVector3D( 0, 0, orientation );
324 for (
int i = 1; i < curve->
numPoints(); i++ )
327 if ( pt1.
z() != pt2.
z() )
333 if ( sameZ && extrusionHeight != 0 )
334 return QVector3D( 0, 0, 1 );
341 double nx = 0, ny = 0, nz = 0;
344 pt1.
setX( pt1.
x() - originX );
345 pt1.
setY( pt1.
y() - originY );
346 pt1.
setZ( std::isnan( pt1.
z() ) ? 0.0 : pt1.
z() - originZ );
347 for (
int i = 1; i < curve->
numPoints(); i++ )
350 pt2.
setX( pt2.
x() - originX );
351 pt2.
setY( pt2.
y() - originY );
352 pt2.
setZ( std::isnan( pt2.
z() ) ? 0.0 : pt2.
z() - originZ );
354 nx += ( pt1.
y() - pt2.
y() ) * ( pt1.
z() + pt2.
z() );
355 ny += ( pt1.
z() - pt2.
z() ) * ( pt1.
x() + pt2.
x() );
356 nz += ( pt1.
x() - pt2.
x() ) * ( pt1.
y() + pt2.
y() );
361 QVector3D normal( nx, ny, nz );
369static void normalVectorToXYVectors(
const QVector3D &pNormal, QVector3D &pXVector, QVector3D &pYVector )
374 if ( pNormal.z() > 0.001 || pNormal.z() < -0.001 )
376 pXVector = QVector3D( 1, 0, -pNormal.x() / pNormal.z() );
378 else if ( pNormal.y() > 0.001 || pNormal.y() < -0.001 )
380 pXVector = QVector3D( 1, -pNormal.x() / pNormal.y(), 0 );
384 pXVector = QVector3D( -pNormal.y() / pNormal.x(), 1, 0 );
386 pXVector.normalize();
387 pYVector = QVector3D::normal( pNormal, pXVector );
392 std::size_t
operator()(
const std::pair<float, float> pair )
const
394 const std::size_t h1 = std::hash<float>()( pair.first );
395 const std::size_t h2 = std::hash<float>()( pair.second );
405 polyline.reserve( pCount );
407 const double *srcXData = ring->
xData();
408 const double *srcYData = ring->
yData();
409 const double *srcZData = ring->
zData();
410 std::unordered_set<std::pair<float, float>,
float_pair_hash> foundPoints;
412 for (
int i = 0; i < pCount - 1; ++i )
414 const float x = *srcXData++;
415 const float y = *srcYData++;
417 const auto res = foundPoints.insert( std::make_pair( x, y ) );
424 p2t::Point *pt2 =
new p2t::Point( x, y );
425 polyline.push_back( pt2 );
428 ( *zHash )[pt2] = *srcZData++;
436 const double exp = 1e10;
437 return round( x * exp ) / exp;
450 double *xData = x.data();
451 double *yData = y.data();
452 double *zData = z.data();
454 const double *srcXData = curve.
xData();
455 const double *srcYData = curve.
yData();
456 const double *srcZData = curve.
is3D() ? curve.
zData() :
nullptr;
458 for (
int i = 0; i < count; ++i )
460 QVector4D v( *srcXData++ - pt0.
x(), *srcYData++ - pt0.
y(), srcZData ? *srcZData++ - pt0.
z() : 0, 0 );
462 v = toNewBase->map( v );
465 v.setX( v.x() * scale );
466 v.setY( v.y() * scale );
500 std::vector< const QgsLineString * > rings;
509 if ( numPoints <= 1 )
512 const double *srcXData = ring->
xData();
513 const double *srcYData = ring->
yData();
514 double x0 = *srcXData++;
515 double y0 = *srcYData++;
516 for (
int i = 1; i < numPoints; ++i )
518 const double x1 = *srcXData++;
519 const double y1 = *srcYData++;
528 return min_d != 1e20 ? std::sqrt( min_d ) : 1e20;
533 return QByteArray(
reinterpret_cast<const char *
>( mData.constData() ),
sizeof(
float ) * mData.size() );
538 return QByteArray(
reinterpret_cast<const char *
>( mIndexBuffer.constData() ),
sizeof( uint32_t ) * mIndexBuffer.size() );
541void QgsTessellator::calculateBaseTransform(
const QVector3D &pNormal, QMatrix4x4 *base )
const
543 if ( !mInputZValueIgnored && pNormal != QVector3D( 0, 0, 1 ) )
547 QVector3D pXVector, pYVector;
548 normalVectorToXYVectors( pNormal, pXVector, pYVector );
553 *base = QMatrix4x4( pXVector.x(), pXVector.y(), pXVector.z(), 0, pYVector.x(), pYVector.y(), pYVector.z(), 0, pNormal.x(), pNormal.y(), pNormal.z(), 0, 0, 0, 0, 0 );
557 base->setToIdentity();
561QVector3D QgsTessellator::applyTransformWithExtrusion(
const QVector3D point,
float extrusionHeight, QMatrix4x4 *transformMatrix,
const QgsPoint *originOffset )
563 const float z = mInputZValueIgnored ? 0.0f : point.z();
564 QVector4D pt( point.x(), point.y(), z, 0 );
566 pt = *transformMatrix * pt;
568 const double fx = pt.
x() - mOrigin.x() + originOffset->
x();
569 const double fy = pt.y() - mOrigin.y() + originOffset->
y();
570 const double baseHeight = mInputZValueIgnored ? 0 : pt.z() - mOrigin.z() + originOffset->
z();
571 const double fz = mInputZValueIgnored ? 0.0 : ( baseHeight + extrusionHeight );
573 if ( baseHeight < mZMin )
574 mZMin =
static_cast<float>( baseHeight );
575 if ( baseHeight > mZMax )
576 mZMax =
static_cast<float>( baseHeight );
578 mZMax =
static_cast<float>( fz );
582 return QVector3D(
static_cast<float>( fx ),
static_cast<float>( fy ),
static_cast<float>( fz ) );
584 return QVector3D(
static_cast<float>( fx ),
static_cast<float>( fz ),
static_cast<float>( -fy ) );
589void QgsTessellator::ringToEarcutPoints(
const QgsLineString *ring, std::vector<std::array<double, 2>> &polyline, QHash<std::array<double, 2> *,
float> *zHash )
593 polyline.reserve( pCount );
595 const double *srcXData = ring->
xData();
596 const double *srcYData = ring->
yData();
597 const double *srcZData = ring->
zData();
600 for (
int i = 0; i < pCount - 1; ++i )
602 const float x =
static_cast<float>( *srcXData++ );
603 const float y =
static_cast<float>( *srcYData++ );
605 std::array<double, 2> pt = { x, y };
606 polyline.push_back( pt );
608 if ( zHash && srcZData )
610 ( *zHash )[&pt] = *srcZData++;
615std::vector<QVector3D> QgsTessellator::generateConstrainedDelaunayTriangles(
const QgsPolygon *polygonNew )
617 QList<std::vector<p2t::Point *>> polylinesToDelete;
618 QHash<p2t::Point *, float> z;
621 std::vector<p2t::Point *> polyline;
623 polylinesToDelete << polyline;
625 p2t::CDT cdt = p2t::CDT( polyline );
630 std::vector<p2t::Point *> holePolyline;
633 ringToPoly2tri( hole, holePolyline, mInputZValueIgnored ?
nullptr : &z );
635 cdt.AddHole( holePolyline );
636 polylinesToDelete << holePolyline;
640 std::vector<p2t::Triangle *> triangles = cdt.GetTriangles();
642 std::vector<QVector3D> trianglePoints;
643 trianglePoints.reserve( triangles.size() * 3 );
645 for ( p2t::Triangle *t : triangles )
647 trianglePoints.emplace_back( t->GetPoint( 0 )->x / mScale, t->GetPoint( 0 )->y / mScale, z.value( t->GetPoint( 0 ) ) );
648 trianglePoints.emplace_back( t->GetPoint( 1 )->x / mScale, t->GetPoint( 1 )->y / mScale, z.value( t->GetPoint( 1 ) ) );
649 trianglePoints.emplace_back( t->GetPoint( 2 )->x / mScale, t->GetPoint( 2 )->y / mScale, z.value( t->GetPoint( 2 ) ) );
652 for (
int i = 0; i < polylinesToDelete.count(); ++i )
653 qDeleteAll( polylinesToDelete[i] );
655 return trianglePoints;
658std::vector<QVector3D> QgsTessellator::generateEarcutTriangles(
const QgsPolygon *polygonNew )
660 QHash<std::array<double, 2> *,
float> z;
661 std::vector<std::vector<std::array<double, 2>>> rings;
662 std::vector<std::array<double, 2>> polyline;
665 rings.push_back( polyline );
669 std::vector<std::array<double, 2>> holePolyline;
671 rings.push_back( holePolyline );
674 std::vector<std::array<double, 2>> points;
675 for (
const auto &ring : rings )
677 points.insert( points.end(), ring.begin(), ring.end() );
680 std::vector<uint32_t> indices = mapbox::earcut<uint32_t>( rings );
681 std::vector<QVector3D> trianglePoints;
682 trianglePoints.reserve( points.size() );
684 for (
size_t i = 0; i < indices.size(); i++ )
686 uint32_t vertexIndex = indices[i];
687 std::array<double, 2> vertex = points[vertexIndex];
689 double x = vertex[0];
690 double y = vertex[1];
692 float zValue = z.value( &vertex, 0.0f );
694 trianglePoints.emplace_back( x / mScale, y / mScale, zValue );
697 return trianglePoints;
700void QgsTessellator::addVertex(
701 const QVector3D &point,
const QVector3D &normal,
float extrusionHeight, QMatrix4x4 *transformMatrix,
const QgsPoint *originOffset, QHash<VertexPoint, unsigned int> *vertexBuffer,
const size_t &vertexBufferOffset
704 const QVector3D pt = applyTransformWithExtrusion( point, extrusionHeight, transformMatrix, originOffset );
705 const VertexPoint vertex( pt, normal );
709 mIndexBuffer << vertexBufferOffset + index;
715 mIndexBuffer << vertexBufferOffset + index;
717 mData << pt.x() << pt.y() << pt.z();
720 mData << normal.x() << normal.y() << normal.z();
722 if ( mAddTextureCoords )
724 const std::pair<float, float> pr = rotateCoords(
static_cast<float>( point.x() ),
static_cast<float>( point.y() ), 0.0f, 0.0f, mTextureRotation );
725 mData << pr.first << pr.second;
730void QgsTessellator::addVertex(
const QVector3D &point,
const QVector3D &normal,
float extrusionHeight, QMatrix4x4 *transformMatrix,
const QgsPoint *originOffset )
732 const QVector3D pt = applyTransformWithExtrusion( point, extrusionHeight, transformMatrix, originOffset );
734 mData << pt.x() << pt.y() << pt.z();
737 mData << normal.x() << normal.y() << normal.z();
739 if ( mAddTextureCoords )
741 const std::pair<float, float> pr = rotateCoords(
static_cast<float>( point.x() ),
static_cast<float>( point.y() ), 0.0f, 0.0f, mTextureRotation );
742 mData << pr.first << pr.second;
752 const QVector3D pNormal = !mInputZValueIgnored ? calculateNormal( exterior, mOrigin.x(), mOrigin.y(), mOrigin.z(), mInvertNormals, extrusionHeight ) : QVector3D();
753 const int pCount = exterior->
numPoints();
760 std::unique_ptr<QgsPolygon> polygonNew;
762 if ( !mInputZValueIgnored && !
qgsDoubleNear( pNormal.length(), 1, 0.001 ) )
769 if ( buildFloor || buildRoof )
771 calculateBaseTransform( pNormal, &base );
777 normal = QVector3D( pNormal.x(), pNormal.z(), -pNormal.y() );
784 base = base.transposed();
788 Q_ASSERT( polygonNew->exteriorRing()->numPoints() >= 3 );
791 const QVector3D p1(
static_cast<float>( triangle->
xAt( 0 ) ),
static_cast<float>( triangle->
yAt( 0 ) ),
static_cast<float>( triangle->
zAt( 0 ) ) );
792 const QVector3D p2(
static_cast<float>( triangle->
xAt( 1 ) ),
static_cast<float>( triangle->
yAt( 1 ) ),
static_cast<float>( triangle->
zAt( 1 ) ) );
793 const QVector3D p3(
static_cast<float>( triangle->
xAt( 2 ) ),
static_cast<float>( triangle->
yAt( 2 ) ),
static_cast<float>( triangle->
zAt( 2 ) ) );
794 std::array<QVector3D, 3> points = { p1, p2, p3 };
796 for (
const QVector3D &point : points )
798 addVertex( point, normal, extrusionHeight, &base, &extrusionOrigin );
803 for (
size_t i = points.size(); i-- > 0; )
805 const QVector3D &point = points[i];
806 addVertex( point, -normal, extrusionHeight, &base, &extrusionOrigin );
810 if ( extrusionHeight != 0 && buildFloor )
812 for (
const QVector3D &point : points )
814 addVertex( point, normal, 0.0, &base, &extrusionOrigin );
819 for (
size_t i = points.size(); i-- > 0; )
821 const QVector3D &point = points[i];
822 addVertex( point, -normal, 0.0, &base, &extrusionOrigin );
836 if ( polygonSimplified.
isNull() )
838 mError = QObject::tr(
"geometry simplification failed - skipping" );
846 mError = QObject::tr(
"geometry's coordinates are too close to each other and simplification failed - skipping" );
851 polygonNew.reset( polygonSimplifiedData->
clone() );
858 std::vector<QVector3D> trianglePoints;
859 switch ( mTriangulationAlgorithm )
862 trianglePoints = generateConstrainedDelaunayTriangles( polygonNew.get() );
865 trianglePoints = generateEarcutTriangles( polygonNew.get() );
869 if ( trianglePoints.empty() )
871 mError = QObject::tr(
"Failed to triangulate polygon." );
875 Q_ASSERT( trianglePoints.size() % 3 == 0 );
877 mData.reserve( mData.size() + trianglePoints.size() * 3 * (
stride() /
sizeof(
float ) ) );
881 for (
size_t i = 0; i < trianglePoints.size(); i += 3 )
883 const std::array<QVector3D, 3> points = { trianglePoints[i + 0], trianglePoints[i + 1], trianglePoints[i + 2] };
886 for (
const QVector3D &point : points )
888 addVertex( point, normal, extrusionHeight, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
893 for (
size_t i = points.size(); i-- > 0; )
895 const QVector3D &point = points[i];
896 addVertex( point, -normal, extrusionHeight, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
900 if ( extrusionHeight != 0 && buildFloor )
902 for (
const QVector3D &point : points )
904 addVertex( point, normal, 0.0, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
909 for (
size_t i = points.size(); i-- > 0; )
911 const QVector3D &point = points[i];
912 addVertex( point, -normal, 0.0, &base, &extrusionOrigin, &
vertexBuffer, vertexBufferSize );
918 catch ( std::runtime_error &err )
924 mError = QObject::tr(
"An unknown error occurred" );
930 if ( extrusionHeight != 0 && buildWalls )
932 makeWalls( *exterior,
false, extrusionHeight );
940 return mIndexBuffer.size();
945 auto mp = std::make_unique< QgsMultiPolygon >();
946 const size_t nVals = mIndexBuffer.size();
948 Q_ASSERT( nVals % 3 == 0 );
950 mp->reserve( nVals / 3 );
951 const size_t noOfElements =
stride() /
sizeof( float );
953 for (
size_t i = 0; i + 2 < nVals; i += 3 )
955 const uint32_t index1 = mIndexBuffer[i] * noOfElements;
956 const uint32_t index2 = mIndexBuffer[i + 1] * noOfElements;
957 const uint32_t index3 = mIndexBuffer[i + 2] * noOfElements;
961 const QgsPoint p1( mData[index1], mData[index1 + 1], mData[index1 + 2] );
962 const QgsPoint p2( mData[index2], mData[index2 + 1], mData[index2 + 2] );
963 const QgsPoint p3( mData[index3], mData[index3 + 1], mData[index3 + 2] );
969 const QgsPoint p1( mData[index1], -mData[index1 + 2], mData[index1 + 1] );
970 const QgsPoint p2( mData[index2], -mData[index2 + 2], mData[index2 + 1] );
971 const QgsPoint p3( mData[index3], -mData[index3 + 2], mData[index3 + 1] );
981 const size_t n = mIndexBuffer.size();
983 return QVector<float>();
985 QVector<float> tData;
986 size_t noOfElements =
stride() /
sizeof( float );
987 tData.reserve( n * noOfElements );
989 for (
auto &index : mIndexBuffer )
991 for (
size_t i = 0; i < noOfElements; i++ )
993 tData << mData[index * noOfElements + i];
1002 if ( mData.size() == 0 )
1005 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