File indexing completed on 2024-05-19 04:25:07
0001 /* 0002 * SPDX-FileCopyrightText: 2023 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #ifndef KISBEZIERPATCHPARAMTOSOURCESAMPLER_H 0007 #define KISBEZIERPATCHPARAMTOSOURCESAMPLER_H 0008 0009 #include "KisBezierPatch.h" 0010 #include "KisBezierUtils.h" 0011 #include "KisBezierPatchParamSpaceUtils.h" 0012 0013 /** 0014 * A simple class that maps param-space point of a bezier patch into the source-range 0015 */ 0016 struct KisBezierPatchParamToSourceSampler 0017 { 0018 using Range = KisBezierUtils::Range; 0019 0020 KisBezierPatchParamToSourceSampler(const KisBezierPatch &_patch) 0021 : patch(_patch) 0022 , topLength(KisBezierUtils::curveLength(patch.points[KisBezierPatch::TL], patch.points[KisBezierPatch::TL_HC], patch.points[KisBezierPatch::TR_HC], patch.points[KisBezierPatch::TR], 0.01)) 0023 , bottomLength(KisBezierUtils::curveLength(patch.points[KisBezierPatch::BL], patch.points[KisBezierPatch::BL_HC], patch.points[KisBezierPatch::BR_HC], patch.points[KisBezierPatch::BR], 0.01)) 0024 , leftLength(KisBezierUtils::curveLength(patch.points[KisBezierPatch::TL], patch.points[KisBezierPatch::TL_VC], patch.points[KisBezierPatch::BL_VC], patch.points[KisBezierPatch::BL], 0.01)) 0025 , rightLength(KisBezierUtils::curveLength(patch.points[KisBezierPatch::TR], patch.points[KisBezierPatch::TR_VC], patch.points[KisBezierPatch::BR_VC], patch.points[KisBezierPatch::BR], 0.01)) 0026 {} 0027 0028 KisBezierPatch patch; 0029 0030 qreal topLength; 0031 qreal bottomLength; 0032 0033 qreal leftLength; 0034 qreal rightLength ; 0035 0036 Range xRange(qreal xParam) const 0037 { 0038 qreal xCoord1 = KisBezierUtils::curveLengthAtPoint(patch.points[KisBezierPatch::TL], patch.points[KisBezierPatch::TL_HC], patch.points[KisBezierPatch::TR_HC], patch.points[KisBezierPatch::TR], xParam, 0.01) / topLength; 0039 qreal xCoord2 = KisBezierUtils::curveLengthAtPoint(patch.points[KisBezierPatch::BL], patch.points[KisBezierPatch::BL_HC], patch.points[KisBezierPatch::BR_HC], patch.points[KisBezierPatch::BR], xParam, 0.01) / bottomLength; 0040 0041 xCoord1 = patch.originalRect.left() + xCoord1 * patch.originalRect.width(); 0042 xCoord2 = patch.originalRect.left() + xCoord2 * patch.originalRect.width(); 0043 0044 if (xCoord1 > xCoord2) { 0045 std::swap(xCoord1, xCoord2); 0046 } 0047 0048 return {xCoord1, xCoord2}; 0049 }; 0050 0051 Range yRange(qreal yParam) const 0052 { 0053 qreal yCoord1 = KisBezierUtils::curveLengthAtPoint(patch.points[KisBezierPatch::TL], patch.points[KisBezierPatch::TL_VC], patch.points[KisBezierPatch::BL_VC], patch.points[KisBezierPatch::BL], yParam, 0.01) / leftLength; 0054 qreal yCoord2 = KisBezierUtils::curveLengthAtPoint(patch.points[KisBezierPatch::TR], patch.points[KisBezierPatch::TR_VC], patch.points[KisBezierPatch::BR_VC], patch.points[KisBezierPatch::BR], yParam, 0.01) / rightLength; 0055 0056 yCoord1 = patch.originalRect.top() + yCoord1 * patch.originalRect.height(); 0057 yCoord2 = patch.originalRect.top() + yCoord2 * patch.originalRect.height(); 0058 0059 if (yCoord1 > yCoord2) { 0060 std::swap(yCoord1, yCoord2); 0061 } 0062 0063 return {yCoord1, yCoord2}; 0064 }; 0065 0066 QPointF point(qreal xParam, qreal yParam) const 0067 { 0068 using KisAlgebra2D::lerp; 0069 0070 const Range xRange = this->xRange(xParam); 0071 const Range yRange = this->yRange(yParam); 0072 0073 return QPointF(lerp(xRange.start, xRange.end, yParam), 0074 lerp(yRange.start, yRange.end, xParam)); 0075 } 0076 0077 QPointF point(const QPointF &pt) const { 0078 return point(pt.x(), pt.y()); 0079 } 0080 }; 0081 0082 #endif // KISBEZIERPATCHPARAMTOSOURCESAMPLER_H