File indexing completed on 2024-05-12 15:58:16
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_FOUR_POINT_INTERPOLATOR_BACKWARD_H 0008 #define __KIS_FOUR_POINT_INTERPOLATOR_BACKWARD_H 0009 0010 #include <QPolygon> 0011 #include <QPointF> 0012 0013 #include "kis_global.h" 0014 #include "kis_algebra_2d.h" 0015 0016 0017 /** 0018 * A-----B The polygons must be initialized in this order: 0019 * | | 0020 * | | polygon << A << B << D << C; 0021 * C-----D 0022 */ 0023 0024 class KisFourPointInterpolatorBackward 0025 { 0026 public: 0027 KisFourPointInterpolatorBackward(const QPolygonF &srcPolygon, const QPolygonF &dstPolygon) { 0028 m_a = dstPolygon[1] - dstPolygon[0]; // AB 0029 m_b = dstPolygon[2] - dstPolygon[1]; // BD 0030 m_c = dstPolygon[3] - dstPolygon[0]; // AC 0031 m_d = m_b - m_c; // BD - AC 0032 0033 m_qA = m_c.x() * m_d.y() - m_c.y() * m_d.x(); 0034 0035 m_srcBase = srcPolygon[0]; 0036 m_dstBase = dstPolygon[0]; 0037 m_xCoeff = srcPolygon[1].x() - srcPolygon[0].x(); // AB_src 0038 m_yCoeff = srcPolygon[3].y() - srcPolygon[0].y(); // AC_src 0039 0040 m_qB_const = m_c.x() * m_a.y() - m_c.y() * m_a.x(); 0041 0042 m_qD_div = 1.0 / (2 * m_qA); 0043 0044 //m_qB_varX = 0.0; 0045 //m_qB_varY = 0.0; 0046 } 0047 0048 /** 0049 * Checks if linear dimensions of the destination polygon are 0050 * bigger than \p tolerance. 0051 */ 0052 inline bool isValid(const qreal tolerance = 0.1) const { 0053 const qreal toleranceSq = pow2(tolerance); 0054 0055 const qreal sq1 = qAbs(m_qB_const); 0056 const qreal sq2 = qAbs(KisAlgebra2D::crossProduct(m_b, m_c - m_b + m_a)); 0057 0058 return sq1 + sq2 > 2 * toleranceSq; 0059 } 0060 0061 inline QPointF fallbackSourcePoint() const { 0062 return m_srcBase + QPointF(0.5 * m_xCoeff, 0.5 * m_yCoeff); 0063 } 0064 0065 inline QPointF map(const QPointF &pt) { 0066 setX(pt.x()); 0067 setY(pt.y()); 0068 return getValue(); 0069 } 0070 0071 inline void setX(qreal x) { 0072 x -= m_dstBase.x(); 0073 0074 m_qB_varX = - x * m_d.y(); 0075 m_qC_varX = - x * m_a.y(); 0076 m_px = x; 0077 } 0078 0079 inline void setY(qreal y) { 0080 y -= m_dstBase.y(); 0081 0082 m_qB_varY = y * m_d.x(); 0083 m_qC_varY = y * m_a.x(); 0084 m_py = y; 0085 } 0086 0087 inline QPointF getValue() const { 0088 static const qreal eps = 1e-10; 0089 0090 qreal qB = m_qB_const + m_qB_varX + m_qB_varY; 0091 qreal qC = m_qC_varX + m_qC_varY; 0092 0093 qreal nu = 0.0; 0094 0095 if (qAbs(m_qA) < eps) { 0096 nu = -qC / qB; 0097 } else { 0098 qreal D = pow2(qB) - 4 * m_qA * qC; 0099 if (D > 0.0) { 0100 qreal sqrtD = std::sqrt(D); 0101 nu = (-qB - sqrtD) * m_qD_div; 0102 if (nu < 0.0 || nu > 1.0) { 0103 qreal nu2 = (-qB + sqrtD) * m_qD_div; 0104 0105 if (nu2 < 0.0 || nu2 > 1.0) { 0106 nu = qBound(qreal(0.0), nu, qreal(1.0)); 0107 } else { 0108 nu = nu2; 0109 } 0110 } 0111 } else { 0112 nu = 0.0; 0113 } 0114 } 0115 0116 qreal xBasedDenominator = m_a.x() + nu * m_d.x(); 0117 0118 qreal mu; 0119 0120 if (qAbs(xBasedDenominator) > eps) { 0121 mu = (m_px - nu * m_c.x()) / xBasedDenominator; 0122 } else { 0123 mu = (m_py - nu * m_c.y()) / (m_a.y() + nu * m_d.y()); 0124 } 0125 0126 return m_srcBase + QPointF(mu * m_xCoeff, nu * m_yCoeff); 0127 } 0128 0129 private: 0130 QPointF m_a; // AB 0131 QPointF m_b; // BD 0132 QPointF m_c; // AC 0133 QPointF m_d; // m_b - m_c 0134 0135 qreal m_qA {0.0}; // quadratic equation A coeff 0136 qreal m_qB_const {0.0}; // quadratic equation B coeff, const part 0137 qreal m_qB_varX {0.0}; // quadratic equation B coeff, X-dep part 0138 qreal m_qB_varY {0.0}; // quadratic equation B coeff, Y-dep part 0139 qreal m_qC_varX {0.0}; // quadratic equation C coeff, X-dep part 0140 qreal m_qC_varY {0.0}; // quadratic equation C coeff, Y-dep part 0141 qreal m_qD_div {0.0}; // inverted divisor of the quadratic equation solution 0142 qreal m_px {0.0}; // saved relative X coordinate 0143 qreal m_py {0.0}; // saved relative Y coordinate 0144 0145 QPointF m_srcBase; 0146 QPointF m_dstBase; 0147 qreal m_xCoeff {0.0}; 0148 qreal m_yCoeff {0.0}; 0149 }; 0150 0151 #endif /* __KIS_FOUR_POINT_INTERPOLATOR_BACKWARD_H */