Skip to content

Commit

Permalink
Merge pull request #46395 from lbartoletti/backport-46372-to-queued_l…
Browse files Browse the repository at this point in the history
…tr_backports

Manual Backport "Fix triangle angles" to 3.16
  • Loading branch information
lbartoletti committed Dec 8, 2021
2 parents 1249c70 + 48d4cf6 commit e296eaa
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 26 deletions.
48 changes: 25 additions & 23 deletions src/core/geometry/qgstriangle.cpp
Expand Up @@ -377,9 +377,9 @@ QVector<double> QgsTriangle::lengths() const
if ( isEmpty() )
return lengths;

lengths.append( vertexAt( 0 ).distance( vertexAt( 1 ) ) );
lengths.append( vertexAt( 1 ).distance( vertexAt( 2 ) ) );
lengths.append( vertexAt( 2 ).distance( vertexAt( 0 ) ) );
lengths.append( vertexAt( 0 ).distance( vertexAt( 1 ) ) ); // c = |AB|
lengths.append( vertexAt( 1 ).distance( vertexAt( 2 ) ) ); // a = |BC|
lengths.append( vertexAt( 0 ).distance( vertexAt( 2 ) ) ); // b = |AC|

return lengths;
}
Expand All @@ -389,22 +389,24 @@ QVector<double> QgsTriangle::angles() const
QVector<double> angles;
if ( isEmpty() )
return angles;
double ax, ay, bx, by, cx, cy;

ax = vertexAt( 0 ).x();
ay = vertexAt( 0 ).y();
bx = vertexAt( 1 ).x();
by = vertexAt( 1 ).y();
cx = vertexAt( 2 ).x();
cy = vertexAt( 2 ).y();
QVector<double> l = lengths();

const double a = l[1];
const double b = l[2];
const double c = l[0];

double a1 = std::fmod( QgsGeometryUtils::angleBetweenThreePoints( cx, cy, ax, ay, bx, by ), M_PI );
double a2 = std::fmod( QgsGeometryUtils::angleBetweenThreePoints( ax, ay, bx, by, cx, cy ), M_PI );
double a3 = std::fmod( QgsGeometryUtils::angleBetweenThreePoints( bx, by, cx, cy, ax, ay ), M_PI );
const double a2 = a * a;
const double b2 = b * b;
const double c2 = c * c;

angles.append( ( a1 > M_PI_2 ? a1 - M_PI_2 : a1 ) );
angles.append( ( a2 > M_PI_2 ? a2 - M_PI_2 : a2 ) );
angles.append( ( a3 > M_PI_2 ? a3 - M_PI_2 : a3 ) );
const double alpha = acos( ( b2 + c2 - a2 ) / ( 2 * b * c ) );
const double beta = acos( ( a2 + c2 - b2 ) / ( 2 * a * c ) );
const double gamma = M_PI - alpha - beta; // acos((a2 + b2 - c2)/(2*a*b)); but ensure that alpha+beta+gamma = 180.0

angles.append( alpha );
angles.append( beta );
angles.append( gamma );

return angles;
}
Expand Down Expand Up @@ -580,13 +582,13 @@ QgsPoint QgsTriangle::inscribedCenter() const
if ( isEmpty() )
return QgsPoint();

QVector<double> l = lengths();
double x = ( l.at( 0 ) * vertexAt( 2 ).x() +
l.at( 1 ) * vertexAt( 0 ).x() +
l.at( 2 ) * vertexAt( 1 ).x() ) / perimeter();
double y = ( l.at( 0 ) * vertexAt( 2 ).y() +
l.at( 1 ) * vertexAt( 0 ).y() +
l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter();
const QVector<double> l = lengths();
const double x = ( l.at( 0 ) * vertexAt( 2 ).x() +
l.at( 1 ) * vertexAt( 0 ).x() +
l.at( 2 ) * vertexAt( 1 ).x() ) / perimeter();
const double y = ( l.at( 0 ) * vertexAt( 2 ).y() +
l.at( 1 ) * vertexAt( 0 ).y() +
l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter();

QgsPoint center( x, y );

Expand Down
53 changes: 50 additions & 3 deletions tests/src/core/testqgsgeometry.cpp
Expand Up @@ -7306,17 +7306,64 @@ void TestQgsGeometry::triangle()


// lengths and angles
QgsTriangle tr( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ) );

QVector<double> a_tested;
QVector<double> angles = tr.angles();
a_tested.append( M_PI / 4.0 );
a_tested.append( M_PI / 2.0 );
a_tested.append( M_PI / 4.0 );

QGSCOMPARENEAR( a_tested.at( 0 ), angles.at( 0 ), 0.0001 );
QGSCOMPARENEAR( a_tested.at( 1 ), angles.at( 1 ), 0.0001 );
QGSCOMPARENEAR( a_tested.at( 2 ), angles.at( 2 ), 0.0001 );

QVector<double> a_empty = QgsTriangle().angles();
QVERIFY( a_empty.isEmpty() );

// From issue #46370
tr = QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 1, sqrt( 3 ) ), QgsPoint( 2, 0 ) );
angles = tr.angles();
QGSCOMPARENEAR( angles.at( 0 ), M_PI / 3.0, 0.0001 );
QGSCOMPARENEAR( angles.at( 1 ), M_PI / 3.0, 0.0001 );
QGSCOMPARENEAR( angles.at( 2 ), M_PI / 3.0, 0.0001 );

tr = QgsTriangle( QgsPoint( 2, 0 ), QgsPoint( 1, sqrt( 3 ) ), QgsPoint( 0, 0 ) );
angles = tr.angles();
QGSCOMPARENEAR( angles.at( 0 ), M_PI / 3.0, 0.0001 );
QGSCOMPARENEAR( angles.at( 1 ), M_PI / 3.0, 0.0001 );
QGSCOMPARENEAR( angles.at( 2 ), M_PI / 3.0, 0.0001 );

tr = QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 0, 3 ), QgsPoint( 4, 0 ) );
angles = tr.angles();
QGSCOMPARENEAR( angles.at( 0 ), M_PI / 2.0, 0.0001 );
QGSCOMPARENEAR( angles.at( 1 ), 0.9272952, 0.0001 );
QGSCOMPARENEAR( angles.at( 2 ), 0.6435011, 0.0001 );
tr = QgsTriangle( QgsPoint( 4, 0 ), QgsPoint( 0, 3 ), QgsPoint( 0, 0 ) );
angles = tr.angles();
QGSCOMPARENEAR( angles.at( 0 ), 0.6435011, 0.0001 );
QGSCOMPARENEAR( angles.at( 1 ), 0.9272952, 0.0001 );
QGSCOMPARENEAR( angles.at( 2 ), M_PI / 2.0, 0.0001 );

tr = QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 1, 3 ), QgsPoint( 3, 0 ) );
angles = tr.angles();
QGSCOMPARENEAR( angles.at( 0 ), 1.2490457, 0.0001 );
QGSCOMPARENEAR( angles.at( 1 ), 0.9097531, 0.0001 );
QGSCOMPARENEAR( angles.at( 2 ), 0.9827937, 0.0001 );
tr = QgsTriangle( QgsPoint( 3, 0 ), QgsPoint( 1, 3 ), QgsPoint( 0, 0 ) );
angles = tr.angles();
QGSCOMPARENEAR( angles.at( 0 ), 0.9827937, 0.0001 );
QGSCOMPARENEAR( angles.at( 1 ), 0.9097531, 0.0001 );
QGSCOMPARENEAR( angles.at( 2 ), 1.2490457, 0.0001 );
QgsTriangle t7( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ) );

QVector<double> a_tested, a_t7 = t7.angles();
QVector<double> a_t7 = t7.angles();
a_tested.append( M_PI / 4.0 );
a_tested.append( M_PI / 2.0 );
a_tested.append( M_PI / 4.0 );
QGSCOMPARENEAR( a_tested.at( 0 ), a_t7.at( 0 ), 0.0001 );
QGSCOMPARENEAR( a_tested.at( 1 ), a_t7.at( 1 ), 0.0001 );
QGSCOMPARENEAR( a_tested.at( 2 ), a_t7.at( 2 ), 0.0001 );
QVector<double> a_empty = QgsTriangle().angles();
QVERIFY( a_empty.isEmpty() );

QVector<double> l_tested, l_t7 = t7.lengths();
l_tested.append( 5 );
Expand Down

0 comments on commit e296eaa

Please sign in to comment.