QGIS API Documentation 3.27.0-Master (f261cc1f8b)
qgstriangle.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstriangle.cpp
3 -------------------
4 begin : January 2017
5 copyright : (C) 2017 by Loïc Bartoletti
6 email : lbartoletti at tuxfamily dot org
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgstriangle.h"
19#include "qgsgeometryutils.h"
20#include "qgslinestring.h"
21#include "qgswkbptr.h"
22
23#include <memory>
24
26{
28}
29
30QgsTriangle::QgsTriangle( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3 )
31{
33
34 const QVector< double > x { p1.x(), p2.x(), p3.x(), p1.x() };
35 const QVector< double > y { p1.y(), p2.y(), p3.y(), p1.y() };
36 QVector< double > z;
37 if ( p1.is3D() )
38 {
39 z = { p1.z(), p2.z(), p3.z(), p1.z() };
40 }
41 QVector< double > m;
42 if ( p1.isMeasure() )
43 {
44 m = {p1.m(), p2.m(), p3.m(), p1.m() };
45 }
46 setExteriorRing( new QgsLineString( x, y, z, m ) );
47}
48
49QgsTriangle::QgsTriangle( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3 )
50{
52
53 const QVector< double > x { p1.x(), p2.x(), p3.x(), p1.x() };
54 const QVector< double > y {p1.y(), p2.y(), p3.y(), p1.y() };
55 QgsLineString *ext = new QgsLineString( x, y );
56 setExteriorRing( ext );
57}
58
59QgsTriangle::QgsTriangle( const QPointF p1, const QPointF p2, const QPointF p3 )
60{
62
63 const QVector< double > x{ p1.x(), p2.x(), p3.x(), p1.x() };
64 const QVector< double > y{ p1.y(), p2.y(), p3.y(), p1.y() };
65 QgsLineString *ext = new QgsLineString( x, y );
66 setExteriorRing( ext );
67}
68
69bool QgsTriangle::operator==( const QgsTriangle &other ) const
70{
71 if ( isEmpty() && other.isEmpty() )
72 {
73 return true;
74 }
75 else if ( isEmpty() || other.isEmpty() )
76 {
77 return false;
78 }
79
80 return ( ( vertexAt( 0 ) == other.vertexAt( 0 ) ) &&
81 ( vertexAt( 1 ) == other.vertexAt( 1 ) ) &&
82 ( vertexAt( 2 ) == other.vertexAt( 2 ) )
83 );
84}
85
86bool QgsTriangle::operator!=( const QgsTriangle &other ) const
87{
88 return !operator==( other );
89}
90
92{
93 return QStringLiteral( "Triangle" );
94}
95
97{
98 auto result = std::make_unique< QgsTriangle >();
99 result->mWkbType = mWkbType;
100 return result.release();
101}
102
104{
107}
108
110{
111 return new QgsTriangle( *this );
112}
113
115{
116 clear();
117 if ( !wkbPtr )
118 {
119 return false;
120 }
121
122 const QgsWkbTypes::Type type = wkbPtr.readHeader();
124 {
125 return false;
126 }
127 mWkbType = type;
128
129 QgsWkbTypes::Type ringType;
130 switch ( mWkbType )
131 {
133 ringType = QgsWkbTypes::LineStringZ;
134 break;
136 ringType = QgsWkbTypes::LineStringM;
137 break;
139 ringType = QgsWkbTypes::LineStringZM;
140 break;
141 default:
142 ringType = QgsWkbTypes::LineString;
143 break;
144 }
145
146 int nRings;
147 wkbPtr >> nRings;
148 if ( nRings > 1 )
149 {
150 return false;
151 }
152
153 QgsLineString *line = new QgsLineString();
154 line->fromWkbPoints( ringType, wkbPtr );
155 mExteriorRing.reset( line );
156
157 return true;
158}
159
160bool QgsTriangle::fromWkt( const QString &wkt )
161{
162 clear();
163
164 const QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
165
167 return false;
168
169 mWkbType = parts.first;
170
171 QString secondWithoutParentheses = parts.second;
172 secondWithoutParentheses = secondWithoutParentheses.simplified().remove( ' ' );
173 if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
174 secondWithoutParentheses.isEmpty() )
175 return true;
176
177 const QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
178
179 const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
180 for ( const QString &childWkt : blocks )
181 {
182 const QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
183
184 const QgsWkbTypes::Type flatCurveType = QgsWkbTypes::flatType( childParts.first );
185
186 if ( flatCurveType == QgsWkbTypes::LineString )
187 mInteriorRings.append( new QgsLineString() );
188 else
189 {
190 clear();
191 return false;
192 }
193 if ( !mInteriorRings.back()->fromWkt( childWkt ) )
194 {
195 clear();
196 return false;
197 }
198 }
199
200 mExteriorRing.reset( mInteriorRings.takeFirst() );
201 if ( ( mExteriorRing->numPoints() < 3 ) || ( mExteriorRing->numPoints() > 4 ) || ( mExteriorRing->numPoints() == 4 && mExteriorRing->startPoint() != mExteriorRing->endPoint() ) )
202 {
203 clear();
204 return false;
205 }
206
207 //scan through rings and check if dimensionality of rings is different to CurvePolygon.
208 //if so, update the type dimensionality of the CurvePolygon to match
209 bool hasZ = false;
210 bool hasM = false;
211 if ( mExteriorRing )
212 {
213 hasZ = hasZ || mExteriorRing->is3D();
214 hasM = hasM || mExteriorRing->isMeasure();
215 }
216 if ( hasZ )
217 addZValue( 0 );
218 if ( hasM )
219 addMValue( 0 );
220
221 return true;
222}
223
224QDomElement QgsTriangle::asGml3( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
225{
226
227 QDomElement elemTriangle = doc.createElementNS( ns, QStringLiteral( "Triangle" ) );
228
229 if ( isEmpty() )
230 return elemTriangle;
231
232 QDomElement elemExterior = doc.createElementNS( ns, QStringLiteral( "exterior" ) );
233 QDomElement curveElem = exteriorRing()->asGml3( doc, precision, ns, axisOrder );
234 if ( curveElem.tagName() == QLatin1String( "LineString" ) )
235 {
236 curveElem.setTagName( QStringLiteral( "LinearRing" ) );
237 }
238 elemExterior.appendChild( curveElem );
239 elemTriangle.appendChild( elemExterior );
240
241 return elemTriangle;
242}
243
245{
246 return toPolygon();
247}
248
250{
251 std::unique_ptr<QgsCurvePolygon> curvePolygon( new QgsCurvePolygon() );
252 curvePolygon->setExteriorRing( mExteriorRing->clone() );
253
254 return curvePolygon.release();
255}
256
258{
259 delete ring;
260}
261
263{
264 Q_UNUSED( position )
265 return false;
266}
267
268bool QgsTriangle::insertVertex( QgsVertexId position, const QgsPoint &vertex )
269{
270 Q_UNUSED( position )
271 Q_UNUSED( vertex )
272 return false;
273}
274
276{
277 if ( isEmpty() )
278 return false;
279
280 if ( !mExteriorRing || vId.part != 0 || vId.ring != 0 || vId.vertex < 0 || vId.vertex > 4 )
281 {
282 return false;
283 }
284
285 if ( vId.vertex == 4 )
286 {
287 vId.vertex = 0;
288 }
289
290 const int n = mExteriorRing->numPoints();
291 const bool success = mExteriorRing->moveVertex( vId, newPos );
292 if ( success )
293 {
294 // If first or last vertex is moved, also move the last/first vertex
295 if ( vId.vertex == 0 )
296 mExteriorRing->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
297 clearCache();
298 }
299 return success;
300}
301
303{
304 if ( !ring )
305 {
306 return;
307 }
308
309 if ( ring->hasCurvedSegments() )
310 {
311 //need to segmentize ring as polygon does not support curves
312 QgsCurve *line = ring->segmentize();
313 delete ring;
314 ring = line;
315 }
316
317 if ( ( ring->numPoints() > 4 ) || ( ring->numPoints() < 3 ) )
318 {
319 delete ring;
320 return;
321 }
322 else if ( ring->numPoints() == 4 )
323 {
324 if ( !ring->isClosed() )
325 {
326 delete ring;
327 return;
328 }
329 }
330 else if ( ring->numPoints() == 3 )
331 {
332 if ( ring->isClosed() )
333 {
334 delete ring;
335 return;
336 }
337 QgsLineString *lineString = static_cast< QgsLineString *>( ring );
338 if ( !lineString->isClosed() )
339 {
340 lineString->close();
341 }
342 ring = lineString;
343 }
344
345 mExteriorRing.reset( ring );
346
347 //set proper wkb type
349
350 clearCache();
351}
352
354{
355 if ( !mExteriorRing )
356 return nullptr;
357
358 return mExteriorRing->clone();
359}
360
361QgsPoint QgsTriangle::vertexAt( int atVertex ) const
362{
363 if ( isEmpty() )
364 return QgsPoint();
365
366 const QgsVertexId id( 0, 0, atVertex );
367 return mExteriorRing->vertexAt( id );
368}
369
370QVector<double> QgsTriangle::lengths() const
371{
372 QVector<double> lengths;
373 if ( isEmpty() )
374 return lengths;
375
376 lengths.append( vertexAt( 0 ).distance( vertexAt( 1 ) ) ); // c = |AB|
377 lengths.append( vertexAt( 1 ).distance( vertexAt( 2 ) ) ); // a = |BC|
378 lengths.append( vertexAt( 0 ).distance( vertexAt( 2 ) ) ); // b = |AC|
379
380 return lengths;
381}
382
383QVector<double> QgsTriangle::angles() const
384{
385 QVector<double> angles;
386 if ( isEmpty() )
387 return angles;
388
389 QVector<double> l = lengths();
390
391 const double a = l[1];
392 const double b = l[2];
393 const double c = l[0];
394
395 const double a2 = a * a;
396 const double b2 = b * b;
397 const double c2 = c * c;
398
399 const double alpha = acos( ( b2 + c2 - a2 ) / ( 2 * b * c ) );
400 const double beta = acos( ( a2 + c2 - b2 ) / ( 2 * a * c ) );
401 const double gamma = M_PI - alpha - beta; // acos((a2 + b2 - c2)/(2*a*b)); but ensure that alpha+beta+gamma = 180.0
402
403 angles.append( alpha );
404 angles.append( beta );
405 angles.append( gamma );
406
407 return angles;
408}
409
411{
412 if ( isEmpty() )
413 return true;
414
415 const QgsPoint p1( vertexAt( 0 ) );
416 const QgsPoint p2( vertexAt( 1 ) );
417 const QgsPoint p3( vertexAt( 2 ) );
418 return ( ( ( p1 == p2 ) || ( p1 == p3 ) || ( p2 == p3 ) ) || QgsGeometryUtils::leftOfLine( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() ) == 0 );
419}
420
421bool QgsTriangle::isIsocele( double lengthTolerance ) const
422{
423 if ( isEmpty() )
424 return false;
425 const QVector<double> sides = lengths();
426 const bool ab_bc = qgsDoubleNear( sides.at( 0 ), sides.at( 1 ), lengthTolerance );
427 const bool bc_ca = qgsDoubleNear( sides.at( 1 ), sides.at( 2 ), lengthTolerance );
428 const bool ca_ab = qgsDoubleNear( sides.at( 2 ), sides.at( 0 ), lengthTolerance );
429
430 return ( ab_bc || bc_ca || ca_ab );
431}
432
433bool QgsTriangle::isEquilateral( double lengthTolerance ) const
434{
435 if ( isEmpty() )
436 return false;
437 const QVector<double> sides = lengths();
438 const bool ab_bc = qgsDoubleNear( sides.at( 0 ), sides.at( 1 ), lengthTolerance );
439 const bool bc_ca = qgsDoubleNear( sides.at( 1 ), sides.at( 2 ), lengthTolerance );
440 const bool ca_ab = qgsDoubleNear( sides.at( 2 ), sides.at( 0 ), lengthTolerance );
441
442 return ( ab_bc && bc_ca && ca_ab );
443}
444
445bool QgsTriangle::isRight( double angleTolerance ) const
446{
447 if ( isEmpty() )
448 return false;
449 QVector<double> a = angles();
450 QVector<double>::iterator ita = a.begin();
451 while ( ita != a.end() )
452 {
453 if ( qgsDoubleNear( *ita, M_PI_2, angleTolerance ) )
454 return true;
455 ++ita;
456 }
457 return false;
458}
459
460bool QgsTriangle::isScalene( double lengthTolerance ) const
461{
462 if ( isEmpty() )
463 return false;
464 return !isIsocele( lengthTolerance );
465}
466
467QVector<QgsLineString> QgsTriangle::altitudes() const
468{
469 QVector<QgsLineString> alt;
470 if ( isEmpty() )
471 return alt;
472
473 alt.append( QgsGeometryUtils::perpendicularSegment( vertexAt( 0 ), vertexAt( 2 ), vertexAt( 1 ) ) );
474 alt.append( QgsGeometryUtils::perpendicularSegment( vertexAt( 1 ), vertexAt( 0 ), vertexAt( 2 ) ) );
475 alt.append( QgsGeometryUtils::perpendicularSegment( vertexAt( 2 ), vertexAt( 0 ), vertexAt( 1 ) ) );
476
477 return alt;
478}
479
480QVector<QgsLineString> QgsTriangle::medians() const
481{
482 QVector<QgsLineString> med;
483 if ( isEmpty() )
484 return med;
485
486 QgsLineString med1;
487 QgsLineString med2;
488 QgsLineString med3;
492 med.append( med1 );
493 med.append( med2 );
494 med.append( med3 );
495
496 return med;
497}
498
499QVector<QgsLineString> QgsTriangle::bisectors( double lengthTolerance ) const
500{
501 QVector<QgsLineString> bis;
502 if ( isEmpty() )
503 return bis;
504
505 QgsLineString bis1;
506 QgsLineString bis2;
507 QgsLineString bis3;
508 const QgsPoint incenter = inscribedCenter();
509 QgsPoint out;
510 bool intersection = false;
511
512 QgsGeometryUtils::segmentIntersection( vertexAt( 0 ), incenter, vertexAt( 1 ), vertexAt( 2 ), out, intersection, lengthTolerance );
513 bis1.setPoints( QgsPointSequence() << vertexAt( 0 ) << out );
514
515 QgsGeometryUtils::segmentIntersection( vertexAt( 1 ), incenter, vertexAt( 0 ), vertexAt( 2 ), out, intersection, lengthTolerance );
516 bis2.setPoints( QgsPointSequence() << vertexAt( 1 ) << out );
517
518 QgsGeometryUtils::segmentIntersection( vertexAt( 2 ), incenter, vertexAt( 0 ), vertexAt( 1 ), out, intersection, lengthTolerance );
519 bis3.setPoints( QgsPointSequence() << vertexAt( 2 ) << out );
520
521 bis.append( bis1 );
522 bis.append( bis2 );
523 bis.append( bis3 );
524
525 return bis;
526}
527
529{
530 if ( isEmpty() )
531 return QgsTriangle();
532 QgsPoint p1, p2, p3;
536 return QgsTriangle( p1, p2, p3 );
537}
538
539QgsPoint QgsTriangle::orthocenter( double lengthTolerance ) const
540{
541 if ( isEmpty() )
542 return QgsPoint();
543 const QVector<QgsLineString> alt = altitudes();
544 QgsPoint ortho;
545 bool intersection;
546 QgsGeometryUtils::segmentIntersection( alt.at( 0 ).pointN( 0 ), alt.at( 0 ).pointN( 1 ), alt.at( 1 ).pointN( 0 ), alt.at( 1 ).pointN( 1 ), ortho, intersection, lengthTolerance );
547
548 return ortho;
549}
550
552{
553 if ( isEmpty() )
554 return QgsPoint();
555 double r, x, y;
557 return QgsPoint( x, y );
558}
559
561{
562 if ( isEmpty() )
563 return 0.0;
564 double r, x, y;
566 return r;
567}
568
570{
571 if ( isEmpty() )
572 return QgsCircle();
574}
575
577{
578 if ( isEmpty() )
579 return QgsPoint();
580
581 const QVector<double> l = lengths();
582 const double x = ( l.at( 0 ) * vertexAt( 2 ).x() +
583 l.at( 1 ) * vertexAt( 0 ).x() +
584 l.at( 2 ) * vertexAt( 1 ).x() ) / perimeter();
585 const double y = ( l.at( 0 ) * vertexAt( 2 ).y() +
586 l.at( 1 ) * vertexAt( 0 ).y() +
587 l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter();
588
589 QgsPoint center( x, y );
590
591 QgsPointSequence points;
592 points << vertexAt( 0 ) << vertexAt( 1 ) << vertexAt( 2 );
594
595 return center;
596}
597
599{
600 if ( isEmpty() )
601 return 0.0;
602 return ( 2.0 * area() / perimeter() );
603}
604
606{
607 if ( isEmpty() )
608 return QgsCircle();
610}
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
virtual QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const =0
Returns a GML3 representation of the geometry.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
QgsWkbTypes::Type mWkbType
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
Circle geometry type.
Definition: qgscircle.h:44
A const WKB pointer.
Definition: qgswkbptr.h:138
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
Curve polygon geometry type.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsPolygon * toPolygon(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a new polygon geometry corresponding to a segmentized approximation of the curve.
QVector< QgsCurve * > mInteriorRings
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
double area() const override SIP_HOLDGIL
Returns the planar, 2-dimensional area of the geometry.
double perimeter() const override SIP_HOLDGIL
Returns the planar, 2-dimensional perimeter of the geometry.
std::unique_ptr< QgsCurve > mExteriorRing
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
Definition: qgscurve.cpp:175
virtual bool isClosed() const SIP_HOLDGIL
Returns true if the curve is closed.
Definition: qgscurve.cpp:53
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
static QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns a middle point between points pt1 and pt2.
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false) SIP_HOLDGIL
Compute the intersection between two segments.
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double &centerX, double &centerY) SIP_HOLDGIL
Returns radius and center of the circle through pt1, pt2, pt3.
static QgsLineString perpendicularSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2) SIP_HOLDGIL
Create a perpendicular line segment from p to segment [s1, s2].
static bool transferFirstZOrMValueToPoint(Iterator verticesBegin, Iterator verticesEnd, QgsPoint &point)
A Z or M dimension is added to point if one of the points in the list points contains Z or M value.
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2) SIP_HOLDGIL
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:45
bool isClosed() const override SIP_HOLDGIL
Returns true if the curve is closed.
void setPoints(size_t size, const double *x, const double *y, const double *z=nullptr, const double *m=nullptr)
Resets the line string to match the specified point data.
void close()
Closes the line string by appending the first point to the end of the line, if it is not already clos...
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
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double z
Definition: qgspoint.h:54
double m
Definition: qgspoint.h:55
double y
Definition: qgspoint.h:53
Polygon geometry type.
Definition: qgspolygon.h:34
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgspolygon.cpp:59
friend class QgsCurvePolygon
Definition: qgspolygon.h:118
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Definition: qgssurface.cpp:43
Triangle geometry type.
Definition: qgstriangle.h:34
QgsTriangle medial() const SIP_HOLDGIL
Medial (or midpoint) triangle of a triangle ABC is the triangle with vertices at the midpoints of the...
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
QgsPolygon * surfaceToPolygon() const override
Gets a polygon representation of this surface.
bool isEquilateral(double lengthTolerance=0.0001) const SIP_HOLDGIL
Is the triangle equilateral (three sides with the same length)?
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool operator==(const QgsTriangle &other) const SIP_HOLDGIL
Definition: qgstriangle.cpp:69
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
QgsCurve * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
QVector< double > angles() const SIP_HOLDGIL
Returns the three angles of the triangle.
QgsPoint circumscribedCenter() const SIP_HOLDGIL
Center of the circumscribed circle of the triangle.
QgsTriangle * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
Definition: qgstriangle.cpp:96
bool deleteVertex(QgsVertexId position) override
Inherited method not used. You cannot delete or insert a vertex directly. Returns always false.
QgsTriangle * clone() const override
Clones the geometry by performing a deep copy.
QgsCircle circumscribedCircle() const SIP_HOLDGIL
Circumscribed circle of the triangle.
bool isRight(double angleTolerance=0.0001) const SIP_HOLDGIL
Is the triangle right-angled?
bool moveVertex(QgsVertexId vId, const QgsPoint &newPos) override
Moves a vertex within the geometry.
bool operator!=(const QgsTriangle &other) const SIP_HOLDGIL
Definition: qgstriangle.cpp:86
QgsCircle inscribedCircle() const SIP_HOLDGIL
Inscribed circle of the triangle.
QgsCurvePolygon * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsCurvePolygon.
bool isScalene(double lengthTolerance=0.0001) const SIP_HOLDGIL
Is the triangle scalene (all sides have different lengths)?
void addInteriorRing(QgsCurve *ring) override
Inherited method not used. You cannot add an interior ring into a triangle.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
QgsPoint vertexAt(int atVertex) const SIP_HOLDGIL
Returns coordinates of a vertex.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inherited method not used. You cannot delete or insert a vertex directly. Returns always false.
QVector< QgsLineString > bisectors(double lengthTolerance=0.0001) const SIP_HOLDGIL
The segment (defined by a QgsLineString) returned bisect the angle of a vertex to the opposite side.
QgsPoint orthocenter(double lengthTolerance=0.0001) const SIP_HOLDGIL
An orthocenter is the point of intersection of the altitudes of a triangle.
bool isDegenerate() const SIP_HOLDGIL
Convenient method checking if the geometry is degenerate (have duplicate or colinear point(s)).
double inscribedRadius() const SIP_HOLDGIL
Radius of the inscribed circle of the triangle.
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
Definition: qgstriangle.cpp:91
QgsPoint inscribedCenter() const SIP_HOLDGIL
Center of the inscribed circle of the triangle.
QVector< QgsLineString > altitudes() const SIP_HOLDGIL
An altitude is a segment (defined by a QgsLineString) from a vertex to the opposite side (or,...
double circumscribedRadius() const SIP_HOLDGIL
Radius of the circumscribed circle of the triangle.
QgsTriangle() SIP_HOLDGIL
Constructor for an empty triangle geometry.
Definition: qgstriangle.cpp:25
QVector< double > lengths() const SIP_HOLDGIL
Returns the three lengths of the triangle.
QVector< QgsLineString > medians() const SIP_HOLDGIL
A median is a segment (defined by a QgsLineString) from a vertex to the midpoint of the opposite side...
bool isIsocele(double lengthTolerance=0.0001) const SIP_HOLDGIL
Is the triangle isocele (two sides with the same length)?
bool fromWkb(QgsConstWkbPtr &wkbPtr) override
Sets the geometry from a WKB string.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
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 c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2396
QVector< QgsPoint > QgsPointSequence
int precision
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31
int vertex
Vertex number.
Definition: qgsvertexid.h:95
int part
Part number.
Definition: qgsvertexid.h:89
int ring
Ring number.
Definition: qgsvertexid.h:92