Skip to content

Commit fb3d07f

Browse files
lbartolettinyalldawson
authored andcommitted
[FEATURE] New class for triangle
Adds a new geometry class for Triangle geometries Methods include orthocenter, bisectors, medians, medial, circumscribed (center, radius), inscribed (center, radius) Also adds make_triangle expression function for creating triangles
1 parent 0710fb5 commit fb3d07f

15 files changed

+1624
-0
lines changed

python/core/core.sip

+1
Original file line numberDiff line numberDiff line change
@@ -370,5 +370,6 @@
370370
%Include geometry/qgspointv2.sip
371371
%Include geometry/qgspolygon.sip
372372
%Include geometry/qgssurface.sip
373+
%Include geometry/qgstriangle.sip
373374
%Include geometry/qgswkbtypes.sip
374375
%Include geometry/qgswkbptr.sip

python/core/geometry/qgsgeometryutils.sip

+6
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,10 @@ class QgsGeometryUtils
6767

6868
static QgsPointV2 midpoint (const QgsPointV2& pt1, const QgsPointV2& pt2);
6969

70+
static double gradient( const QgsPointV2& pt1, const QgsPointV2& pt2 );
71+
72+
static void coefficients(const QgsPointV2 &pt1, const QgsPointV2 &pt2, double& a /Out/, double& b /Out/, double& c /Out/);
73+
74+
static QgsLineString perpendicularSegment( const QgsPointV2& p, const QgsPointV2& s1, const QgsPointV2& s2 );
75+
7076
};

python/core/geometry/qgstriangle.sip

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
class QgsTriangle : public QgsPolygonV2
2+
{
3+
%TypeHeaderCode
4+
#include <qgstriangle.h>
5+
%End
6+
7+
public:
8+
QgsTriangle();
9+
QgsTriangle( const QgsPointV2 &p1, const QgsPointV2 &p2, const QgsPointV2 &p3 );
10+
explicit QgsTriangle( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3 );
11+
explicit QgsTriangle( const QPointF p1, const QPointF p2, const QPointF p3 );
12+
13+
// inherited: bool operator==( const QgsTriangle& other ) const;
14+
// inherited: bool operator!=( const QgsTriangle& other ) const;
15+
16+
virtual QString geometryType() const;
17+
virtual QgsTriangle* clone() const /Factory/;
18+
void clear();
19+
20+
virtual bool fromWkb( QgsConstWkbPtr& wkbPtr );
21+
bool fromWkt( const QString &wkt );
22+
// inherited: QString asWkt( int precision = 17 ) const;
23+
// inherited: QDomElement asGML2( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
24+
// inherited: QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
25+
// inherited: QString asJSON( int precision = 17 ) const;
26+
27+
QgsPolygonV2* surfaceToPolygon() const /Factory/;
28+
QgsAbstractGeometry* toCurveType() const /Factory/;
29+
30+
//overridden to handle LineString25D rings
31+
virtual void setExteriorRing( QgsCurve* ring /Transfer/ );
32+
virtual QgsAbstractGeometry* boundary() const /Factory/;
33+
// inherited: double pointDistanceToBoundary( double x, double y ) const;
34+
QgsPointV2 vertexAt( int atVertex ) const;
35+
36+
void addInteriorRing( QgsCurve* ring /Transfer/ ); // NOTE: no interior ring for triangle.
37+
bool deleteVertex( QgsVertexId position );
38+
bool insertVertex( QgsVertexId position, const QgsPointV2 &vertex );
39+
bool moveVertex( QgsVertexId vId, const QgsPointV2& newPos );
40+
41+
QVector<double> lengths() const;
42+
QVector<double> angles() const;
43+
44+
bool isIsocele( double lengthTolerance = 0.0001 ) const;
45+
bool isEquilateral( double lengthTolerance = 0.0001 ) const;
46+
bool isRight( double angleTolerance = 0.0001 ) const;
47+
bool isScalene( double lengthTolerance = 0.0001 ) const;
48+
49+
QVector<QgsLineString> altitudes( ) const;
50+
QVector<QgsLineString> medians( ) const;
51+
QVector<QgsLineString> bisectors( double lengthTolerance = 0.0001 ) const;
52+
53+
QgsTriangle medial( ) const;
54+
QgsPointV2 orthocenter( double lengthTolerance = 0.0001 ) const;
55+
QgsPointV2 circumscribedCenter( ) const;
56+
double circumscribedRadius( ) const;
57+
// TODO:
58+
// QgsCircle circumscribedCircle ( ) const; // need QgsCircle (from CADDigitize.CADCircle)
59+
QgsPointV2 inscribedCenter( ) const;
60+
double inscribedRadius( ) const;
61+
// TODO:
62+
// QgsCircle inscribedCircle ( ) const; // need QgsCircle (from CADDigitize.CADCircle)
63+
};

src/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ SET(QGIS_CORE_SRCS
383383
geometry/qgsmultisurface.cpp
384384
geometry/qgspointv2.cpp
385385
geometry/qgspolygon.cpp
386+
geometry/qgstriangle.cpp
386387
geometry/qgswkbptr.cpp
387388
geometry/qgswkbtypes.cpp
388389

@@ -922,6 +923,7 @@ SET(QGIS_CORE_HDRS
922923
geometry/qgsmultisurface.h
923924
geometry/qgspointv2.h
924925
geometry/qgspolygon.h
926+
geometry/qgstriangle.h
925927
geometry/qgssurface.h
926928
geometry/qgswkbptr.h
927929
geometry/qgswkbtypes.h

src/core/geometry/qgsgeometryutils.cpp

+74
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ email : marco.hugentobler at sourcepole dot com
2121
#include "qgslinestring.h"
2222
#include "qgswkbptr.h"
2323

24+
#include <memory>
2425
#include <QStringList>
2526
#include <QVector>
2627
#include <QRegularExpression>
@@ -834,6 +835,79 @@ QgsPointV2 QgsGeometryUtils::midpoint( const QgsPointV2 &pt1, const QgsPointV2 &
834835
return QgsPointV2( pType, x, y, z, m );
835836
}
836837

838+
double QgsGeometryUtils::gradient( const QgsPointV2 &pt1, const QgsPointV2 &pt2 )
839+
{
840+
double delta_x = pt2.x() - pt1.x();
841+
double delta_y = pt2.y() - pt1.y();
842+
if ( qgsDoubleNear( delta_x, 0.0 ) )
843+
{
844+
return INFINITY;
845+
}
846+
847+
return delta_y / delta_x;
848+
}
849+
850+
void QgsGeometryUtils::coefficients( const QgsPointV2 &pt1, const QgsPointV2 &pt2, double &a, double &b, double &c )
851+
{
852+
if ( qgsDoubleNear( pt1.x(), pt2.x() ) )
853+
{
854+
a = 1;
855+
b = 0;
856+
c = -pt1.x();
857+
}
858+
else if ( qgsDoubleNear( pt1.y(), pt2.y() ) )
859+
{
860+
a = 0;
861+
b = 1;
862+
c = -pt1.y();
863+
}
864+
else
865+
{
866+
a = pt1.y() - pt2.y();
867+
b = pt2.x() - pt1.x();
868+
c = pt1.x() * pt2.y() - pt1.y() * pt2.x();
869+
}
870+
871+
}
872+
873+
QgsLineString QgsGeometryUtils::perpendicularSegment( const QgsPointV2 &p, const QgsPointV2 &s1, const QgsPointV2 &s2 )
874+
{
875+
QgsLineString line;
876+
QgsPointV2 p2;
877+
878+
if ( ( p == s1 ) || ( p == s2 ) )
879+
{
880+
return line;
881+
}
882+
883+
double a, b, c;
884+
coefficients( s1, s2, a, b, c );
885+
886+
if ( qgsDoubleNear( a, 0 ) )
887+
{
888+
p2 = QgsPointV2( p.x(), s1.y() );
889+
}
890+
else if ( qgsDoubleNear( b, 0 ) )
891+
{
892+
p2 = QgsPointV2( s1.x(), p.y() );
893+
}
894+
else
895+
{
896+
double y = ( -c - a * p.x() ) / b;
897+
double m = gradient( s1, s2 );
898+
double d2 = 1 + m * m;
899+
double H = p.y() - y;
900+
double dx = m * H / d2;
901+
double dy = m * dx;
902+
p2 = QgsPointV2( p.x() + dx, y + dy );
903+
}
904+
905+
line.addVertex( p );
906+
line.addVertex( p2 );
907+
908+
return line;
909+
}
910+
837911
double QgsGeometryUtils::lineAngle( double x1, double y1, double x2, double y2 )
838912
{
839913
double at = atan2( y2 - y1, x2 - x1 );

src/core/geometry/qgsgeometryutils.h

+27
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,33 @@ class CORE_EXPORT QgsGeometryUtils
291291
*/
292292
static QgsPointV2 midpoint( const QgsPointV2 &pt1, const QgsPointV2 &pt2 );
293293

294+
/** Return the gradient of a line defined by points \a pt1 and \a pt2.
295+
* @param pt1 first point.
296+
* @param pt2 second point.
297+
* @return The gradient of this linear entity, or infinity if vertical
298+
* @note added in QGIS 3.0
299+
*/
300+
static double gradient( const QgsPointV2 &pt1, const QgsPointV2 &pt2 );
301+
302+
/** Return the coefficients (a, b, c for equation "ax + by + c = 0") of a line defined by points \a pt1 and \a pt2.
303+
* @param pt1 first point.
304+
* @param pt2 second point.
305+
* @param a Output parameter, a coefficient of the equation.
306+
* @param b Output parameter, b coefficient of the equation.
307+
* @param c Output parameter, c coefficient of the equation.
308+
* @note added in QGIS 3.0
309+
*/
310+
static void coefficients( const QgsPointV2 &pt1, const QgsPointV2 &pt2, double &a, double &b, double &c );
311+
312+
/**
313+
* @brief Create a perpendicular line segment from p to segment [s1, s2]
314+
* @param p The point
315+
* @param s1 The segment start point
316+
* @param s2 The segment end point
317+
* @return A line (segment) from p to perpendicular point on segment [s1, s2]
318+
*/
319+
static QgsLineString perpendicularSegment( const QgsPointV2 &p, const QgsPointV2 &s1, const QgsPointV2 &s2 );
320+
294321
//! @note not available in Python bindings
295322
enum ComponentType
296323
{

src/core/geometry/qgslinestring.h

+1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ class CORE_EXPORT QgsLineString: public QgsCurve
210210
void fromWkbPoints( QgsWkbTypes::Type type, const QgsConstWkbPtr &wkb );
211211

212212
friend class QgsPolygonV2;
213+
friend class QgsTriangle;
213214

214215
};
215216

0 commit comments

Comments
 (0)