File indexing completed on 2024-12-22 04:10:01

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_bspline_2d.h"
0008 
0009 #include <kis_debug.h>
0010 #include <limits>
0011 
0012 #include "einspline/bspline_create.h"
0013 #include "einspline/bspline_eval_std_s.h"
0014 
0015 #include "kis_bspline_p.h"
0016 
0017 namespace KisBSplines {
0018 
0019 struct Q_DECL_HIDDEN KisBSpline2D::Private
0020 {
0021     BorderCondition bcX;
0022     BorderCondition bcY;
0023 
0024     UBspline_2d_s* spline;
0025 };
0026 
0027 KisBSpline2D::KisBSpline2D(float xStart, float xEnd, int numSamplesX, BorderCondition bcX,
0028                            float yStart, float yEnd, int numSamplesY, BorderCondition bcY)
0029   : m_d(new Private)
0030 {
0031     m_xStart = xStart;
0032     m_xEnd = xEnd;
0033     m_numSamplesX = numSamplesX;
0034 
0035     m_yStart = yStart;
0036     m_yEnd = yEnd;
0037     m_numSamplesY = numSamplesY;
0038 
0039     m_d->bcX = bcX;
0040     m_d->bcY = bcY;
0041 
0042     m_d->spline = 0;
0043 }
0044 
0045 KisBSpline2D::~KisBSpline2D()
0046 {
0047     if (m_d->spline) {
0048         destroy_Bspline(m_d->spline);
0049     }
0050 }
0051 
0052 void KisBSpline2D::initializeSplineImpl(const QVector<float> &values)
0053 {
0054     Ugrid xGrid;
0055     xGrid.start = m_xStart;
0056     xGrid.end = m_xEnd;
0057     xGrid.num = m_numSamplesX;
0058     xGrid.delta = 0.0;
0059     xGrid.delta_inv = 0.0;
0060 
0061     Ugrid yGrid;
0062     yGrid.start = m_yStart;
0063     yGrid.end = m_yEnd;
0064     yGrid.num = m_numSamplesY;
0065     yGrid.delta = 0.0;
0066     yGrid.delta_inv = 0.0;
0067 
0068     BCtype_s bctypeX;
0069     bctypeX.lCode = bctypeX.rCode = convertBorderType(m_d->bcX);
0070     bctypeX.lVal = 0.0;
0071     bctypeX.rVal = 0.0;
0072 
0073     BCtype_s bctypeY;
0074     bctypeY.lCode = bctypeY.rCode = convertBorderType(m_d->bcY);
0075     bctypeY.lVal = 0.0;
0076     bctypeY.rVal = 0.0;
0077 
0078     m_d->spline =
0079         create_UBspline_2d_s(xGrid, yGrid,
0080                              bctypeX, bctypeY,
0081                              const_cast<float*>(values.constData()));
0082 }
0083 
0084 float KisBSpline2D::value(float x, float y) const
0085 {
0086     /**
0087      * The spline works for an open interval only, so include the last point
0088      * explicitly
0089      */
0090 
0091     if (x == m_xEnd) {
0092         x -= x * std::numeric_limits<float>::epsilon();
0093     }
0094 
0095     if (y == m_yEnd) {
0096         y -= y * std::numeric_limits<float>::epsilon();
0097     }
0098 
0099     KIS_ASSERT_RECOVER_NOOP(x >= m_xStart && x < m_xEnd);
0100     KIS_ASSERT_RECOVER_NOOP(y >= m_yStart && y < m_yEnd);
0101 
0102     float value;
0103     eval_UBspline_2d_s (m_d->spline, x, y, &value);
0104 
0105     return value;
0106 }
0107 
0108 BorderCondition KisBSpline2D::borderConditionX() const
0109 {
0110     return m_d->bcX;
0111 }
0112 
0113 BorderCondition KisBSpline2D::borderConditionY() const
0114 {
0115     return m_d->bcY;
0116 }
0117 
0118 }