Add method to return weighted point inside triangle

This commit is contained in:
Nyall Dawson 2019-09-29 11:19:07 +10:00
parent 975eedc146
commit 3a6cc5c2ca
4 changed files with 106 additions and 0 deletions

View File

@ -632,6 +632,25 @@ An algorithm to calculate an (approximate) intersection of two lines in 3D.
Returns the area of the triangle denoted by the points (``aX``, ``aY``), (``bX``, ``bY``) and
(``cX``, ``cY``).
.. versionadded:: 3.10
%End
static void weightedPointInTriangle( double aX, double aY, double bX, double bY, double cX, double cY,
double weightB, double weightC, double &pointX /Out/, double &pointY /Out/ );
%Docstring
Returns a weighted point inside the triangle denoted by the points (``aX``, ``aY``), (``bX``, ``bY``) and
(``cX``, ``cY``).
:param aX: x-coordinate of first vertex in triangle
:param aY: y-coordinate of first vertex in triangle
:param bX: x-coordinate of second vertex in triangle
:param bY: y-coordinate of second vertex in triangle
:param cX: x-coordinate of third vertex in triangle
:param cY: y-coordinate of third vertex in triangle
:param weightB: weighting factor along axis A-B (between 0 and 1)
:param weightC: weighting factor along axis A-C (between 0 and 1)
:param pointY: y-coordinate of generated point
.. versionadded:: 3.10
%End

View File

@ -1603,6 +1603,25 @@ double QgsGeometryUtils::triangleArea( double aX, double aY, double bX, double b
return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
}
void QgsGeometryUtils::weightedPointInTriangle( const double aX, const double aY, const double bX, const double bY, const double cX, const double cY,
double weightB, double weightC, double &pointX, double &pointY )
{
// if point will be outside of the triangle, invert weights
if ( weightB + weightC > 1 )
{
weightB = 1 - weightB;
weightC = 1 - weightC;
}
const double rBx = weightB * ( bX - aX );
const double rBy = weightB * ( bY - aY );
const double rCx = weightC * ( cX - aX );
const double rCy = weightC * ( cY - aY );
pointX = rBx + rCx + aX;
pointY = rBy + rCy + aY;
}
bool QgsGeometryUtils::setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point )
{
bool rc = false;

View File

@ -671,6 +671,26 @@ class CORE_EXPORT QgsGeometryUtils
*/
static double triangleArea( double aX, double aY, double bX, double bY, double cX, double cY );
/**
* Returns a weighted point inside the triangle denoted by the points (\a aX, \a aY), (\a bX, \a bY) and
* (\a cX, \a cY).
*
* \param aX x-coordinate of first vertex in triangle
* \param aY y-coordinate of first vertex in triangle
* \param bX x-coordinate of second vertex in triangle
* \param bY y-coordinate of second vertex in triangle
* \param cX x-coordinate of third vertex in triangle
* \param cY y-coordinate of third vertex in triangle
* \param weightB weighting factor along axis A-B (between 0 and 1)
* \param weightC weighting factor along axis A-C (between 0 and 1)
* \param pointX x-coordinate of generated point
* \param pointY y-coordinate of generated point
*
* \since QGIS 3.10
*/
static void weightedPointInTriangle( double aX, double aY, double bX, double bY, double cX, double cY,
double weightB, double weightC, double &pointX SIP_OUT, double &pointY SIP_OUT );
/**
* A Z dimension is added to \a point if one of the point in the list
* \a points is in 3D. Moreover, the Z value of \a point is updated with.

View File

@ -78,6 +78,8 @@ class TestQgsGeometryUtils: public QObject
void testSegmentizeArcFullCircle();
void testTriangleArea_data();
void testTriangleArea();
void testWeightedPointInTriangle_data();
void testWeightedPointInTriangle();
};
@ -1380,5 +1382,51 @@ void TestQgsGeometryUtils::testTriangleArea()
QGSCOMPARENEAR( QgsGeometryUtils::triangleArea( aX, aY, bX, bY, cX, cY ), expectedResult, 0.0000001 );
}
void TestQgsGeometryUtils::testWeightedPointInTriangle_data()
{
QTest::addColumn<double>( "aX" );
QTest::addColumn<double>( "aY" );
QTest::addColumn<double>( "bX" );
QTest::addColumn<double>( "bY" );
QTest::addColumn<double>( "cX" );
QTest::addColumn<double>( "cY" );
QTest::addColumn<double>( "weightB" );
QTest::addColumn<double>( "weightC" );
QTest::addColumn<double>( "expectedX" );
QTest::addColumn<double>( "expectedY" );
QTest::newRow( "weighted 1" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.0 << 0.0 << 15.0 << 15.0;
QTest::newRow( "weighted 2" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.5 << 0.0 << 19.0 << 22.5;
QTest::newRow( "weighted 3" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 1.0 << 0.0 << 23.0 << 30.0;
QTest::newRow( "weighted 4" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.0 << 0.5 << 32.5 << 20.0;
QTest::newRow( "weighted 5" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.0 << 1.0 << 50.0 << 25.0;
QTest::newRow( "weighted 6" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.5 << 0.5 << 36.5 << 27.5;
QTest::newRow( "weighted 7" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 1.0 << 1.0 << 15.0 << 15.0;
QTest::newRow( "weighted 8" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 25.0 << 0.0 << 0.0 << 15.0 << 16.0;
QTest::newRow( "weighted 9" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 25.0 << 1.0 << 0.0 << 15.0 << 16.0;
QTest::newRow( "weighted 10" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 16.0 << 0.0 << 1.0 << 15.0 << 16.0;
QTest::newRow( "weighted 11" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 16.0 << 1.0 << 1.0 << 15.0 << 16.0;
QTest::newRow( "weighted 12" ) << -15.0 << -15.0 << -23.0 << -30.0 << -50.0 << -25.0 << 0.5 << 0.5 << -36.5 << -27.5;
}
void TestQgsGeometryUtils::testWeightedPointInTriangle()
{
QFETCH( double, aX );
QFETCH( double, aY );
QFETCH( double, bX );
QFETCH( double, bY );
QFETCH( double, cX );
QFETCH( double, cY );
QFETCH( double, weightB );
QFETCH( double, weightC );
QFETCH( double, expectedX );
QFETCH( double, expectedY );
double x, y;
QgsGeometryUtils::weightedPointInTriangle( aX, aY, bX, bY, cX, cY, weightB, weightC, x, y );
QGSCOMPARENEAR( x, expectedX, 0.0000001 );
QGSCOMPARENEAR( y, expectedY, 0.0000001 );
}
QGSTEST_MAIN( TestQgsGeometryUtils )
#include "testqgsgeometryutils.moc"