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