File indexing completed on 2024-05-26 04:27:30
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_nu_bspline_2d.h" 0008 0009 #include <kis_debug.h> 0010 #include <limits> 0011 0012 #include "einspline/nubspline_create.h" 0013 #include "einspline/nubspline_eval_std_s.h" 0014 0015 #include "kis_bspline_p.h" 0016 0017 namespace KisBSplines { 0018 0019 struct Q_DECL_HIDDEN KisNUBSpline2D::Private 0020 { 0021 BorderCondition bcX; 0022 BorderCondition bcY; 0023 0024 NUBspline_2d_s* spline; 0025 0026 NUgrid *xGrid; 0027 NUgrid *yGrid; 0028 0029 float minX; 0030 float maxX; 0031 float minY; 0032 float maxY; 0033 }; 0034 0035 KisNUBSpline2D::KisNUBSpline2D(const QVector<double> &xSamples, BorderCondition bcX, 0036 const QVector<double> &ySamples, BorderCondition bcY) 0037 : m_d(new Private), 0038 m_xSamples(xSamples), 0039 m_ySamples(ySamples) 0040 { 0041 m_d->xGrid = create_general_grid(const_cast<double*>(m_xSamples.constData()), m_xSamples.size()); 0042 m_d->yGrid = create_general_grid(const_cast<double*>(m_ySamples.constData()), m_ySamples.size()); 0043 0044 m_d->bcX = bcX; 0045 m_d->bcY = bcY; 0046 0047 m_d->minX = xSamples.first(); 0048 m_d->maxX = xSamples.last(); 0049 0050 m_d->minY = ySamples.first(); 0051 m_d->maxY = ySamples.last(); 0052 0053 m_d->spline = 0; 0054 } 0055 0056 KisNUBSpline2D::~KisNUBSpline2D() 0057 { 0058 if (m_d->spline) { 0059 destroy_Bspline(m_d->spline); 0060 } 0061 0062 destroy_grid(m_d->xGrid); 0063 destroy_grid(m_d->yGrid); 0064 } 0065 0066 void KisNUBSpline2D::initializeSplineImpl(const QVector<float> &values) 0067 { 0068 BCtype_s bctypeX; 0069 bctypeX.lCode = bctypeX.rCode = convertBorderType(m_d->bcX); 0070 bctypeX.lVal = bctypeX.rVal = 0.0; 0071 0072 BCtype_s bctypeY; 0073 bctypeY.lCode = bctypeY.rCode = convertBorderType(m_d->bcY); 0074 bctypeY.lVal = bctypeY.rVal = 0.0; 0075 0076 m_d->spline = 0077 create_NUBspline_2d_s(m_d->xGrid, m_d->yGrid, 0078 bctypeX, bctypeY, 0079 const_cast<float*>(values.constData())); 0080 } 0081 0082 float KisNUBSpline2D::value(float x, float y) const 0083 { 0084 /** 0085 * The spline works for an open interval only, so include the last point 0086 * explicitly 0087 */ 0088 0089 if (x == m_d->maxX) { 0090 x -= x * std::numeric_limits<float>::epsilon(); 0091 } 0092 0093 if (y == m_d->maxY) { 0094 y -= y * std::numeric_limits<float>::epsilon(); 0095 } 0096 0097 KIS_ASSERT_RECOVER_NOOP(x >= m_d->minX && x < m_d->maxX); 0098 KIS_ASSERT_RECOVER_NOOP(y >= m_d->minY && y < m_d->maxY); 0099 0100 float value; 0101 eval_NUBspline_2d_s(m_d->spline, x, y, &value); 0102 0103 return value; 0104 } 0105 0106 QPointF KisNUBSpline2D::topLeft() const 0107 { 0108 return QPointF(m_d->minX, m_d->minY); 0109 } 0110 0111 QPointF KisNUBSpline2D::bottomRight() const 0112 { 0113 return QPointF(m_d->maxX, m_d->maxY); 0114 } 0115 0116 BorderCondition KisNUBSpline2D::borderConditionX() const 0117 { 0118 return m_d->bcX; 0119 } 0120 0121 BorderCondition KisNUBSpline2D::borderConditionY() const 0122 { 0123 return m_d->bcY; 0124 } 0125 0126 }