Change QLineF::setLength() to work whenever length() is non-zero
Previously it only worked when isNull() was false, which is true for very short lines, even though length() may be non-zero. [ChangeLog][QtCore][QLineF] QLineF::setLength() will now set the length if the line's length() is non-zero. Previously, it was documented to only set the length if isNull() was false; this is a fuzzy check, so isNull() could be true for a line with non-zero length(). Fixes: QTBUG-89569 Change-Id: I803e622ad09c85815dde25df8dd3ba6dfcba0714 Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 6974737695eae5a41bc8a3f344a4f1f199006f21) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
636fcc4bb2
commit
28ba7ac178
@ -517,12 +517,13 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
|
|||||||
\fn void QLineF::setLength(qreal length)
|
\fn void QLineF::setLength(qreal length)
|
||||||
|
|
||||||
Sets the length of the line to the given \a length. QLineF will
|
Sets the length of the line to the given \a length. QLineF will
|
||||||
move the end point - p2() - of the line to give the line its new length.
|
move the end point - p2() - of the line to give the line its new
|
||||||
|
length, unless length() was previously zero, in which case no
|
||||||
|
scaling is attempted. For lines with very short lengths
|
||||||
|
(represented by denormal floating-point values), results may be
|
||||||
|
imprecise.
|
||||||
|
|
||||||
A null line will not be rescaled. For non-null lines with very short lengths
|
\sa length(), unitVector()
|
||||||
(represented by denormal floating-point values), results may be imprecise.
|
|
||||||
|
|
||||||
\sa length(), isNull(), unitVector()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -372,12 +372,11 @@ constexpr inline QPointF QLineF::center() const
|
|||||||
|
|
||||||
inline void QLineF::setLength(qreal len)
|
inline void QLineF::setLength(qreal len)
|
||||||
{
|
{
|
||||||
if (isNull())
|
const qreal oldLength = length();
|
||||||
return;
|
// Scale len by dx() / length() and dy() / length(), two O(1) quantities,
|
||||||
Q_ASSERT(length() > 0);
|
// rather than scaling dx() and dy() by len / length(), which might overflow.
|
||||||
const QLineF v = unitVector();
|
if (oldLength > 0)
|
||||||
len /= v.length(); // In case it's not quite exactly 1.
|
pt2 = QPointF(pt1.x() + len * (dx() / oldLength), pt1.y() + len * (dy() / oldLength));
|
||||||
pt2 = QPointF(pt1.x() + len * v.dx(), pt1.y() + len * v.dy());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline QPointF QLineF::pointAt(qreal t) const
|
constexpr inline QPointF QLineF::pointAt(qreal t) const
|
||||||
|
@ -247,8 +247,8 @@ void tst_QLine::testLength_data()
|
|||||||
<< -(tiny * .5) << -(tiny * .5) << (tiny * .5) << (tiny * .5)
|
<< -(tiny * .5) << -(tiny * .5) << (tiny * .5) << (tiny * .5)
|
||||||
<< (tiny * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0;
|
<< (tiny * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0;
|
||||||
QTest::newRow("[1+3e-13,1+4e-13]|1895| (1, 1)")
|
QTest::newRow("[1+3e-13,1+4e-13]|1895| (1, 1)")
|
||||||
<< 1.0 << 1.0 << (1 + 3e-13) << (1 + 4e-13) // isNull(), so ignores setLength()
|
<< 1.0 << 1.0 << (1 + 3e-13) << (1 + 4e-13)
|
||||||
<< 5e-13 << 1895.0 << 3e-13 << 4e-13;
|
<< 5e-13 << 1895.0 << 1137.0 << 1516.0;
|
||||||
QTest::newRow("[4e-323,5e-324]|1892|") // Unavoidable underflow: denormals
|
QTest::newRow("[4e-323,5e-324]|1892|") // Unavoidable underflow: denormals
|
||||||
<< 0.0 << 0.0 << 4e-323 << 5e-324
|
<< 0.0 << 0.0 << 4e-323 << 5e-324
|
||||||
<< 4e-323 << 1892.0 << 4e-323 << 5e-324; // vx, vy values ignored
|
<< 4e-323 << 1892.0 << 4e-323 << 5e-324; // vx, vy values ignored
|
||||||
@ -266,14 +266,14 @@ void tst_QLine::testLength()
|
|||||||
QFETCH(double, vy);
|
QFETCH(double, vy);
|
||||||
|
|
||||||
QLineF l(x1, y1, x2, y2);
|
QLineF l(x1, y1, x2, y2);
|
||||||
const bool wasNull = l.isNull();
|
QCOMPARE(l.length(), qreal(length));
|
||||||
if (!wasNull)
|
|
||||||
QCOMPARE(l.length(), qreal(length));
|
|
||||||
|
|
||||||
l.setLength(lengthToSet);
|
l.setLength(lengthToSet);
|
||||||
QCOMPARE(l.length(), wasNull ? qreal(length) : qreal(lengthToSet));
|
|
||||||
// Scaling tiny values up to big can be imprecise: don't try to test vx, vy
|
// Scaling tiny values up to big can be imprecise: don't try to test vx, vy
|
||||||
if (wasNull || !qFuzzyIsNull(length)) {
|
if (length > 0 && qFuzzyIsNull(length)) {
|
||||||
|
QVERIFY(l.length() > lengthToSet / 2 && l.length() < lengthToSet * 2);
|
||||||
|
} else {
|
||||||
|
QCOMPARE(l.length(), length > 0 ? qreal(lengthToSet) : qreal(length));
|
||||||
QCOMPARE(l.dx(), qreal(vx));
|
QCOMPARE(l.dx(), qreal(vx));
|
||||||
QCOMPARE(l.dy(), qreal(vy));
|
QCOMPARE(l.dy(), qreal(vy));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user