added: utility function to lower/raise order of a Bspline basis

and tests
This commit is contained in:
Arne Morten Kvarving 2023-09-07 20:29:53 +02:00
parent a9096e5333
commit 5bfae73494
3 changed files with 110 additions and 1 deletions

View File

@ -309,6 +309,30 @@ Go::SplineVolume* SplineUtils::project (const Go::SplineVolume* volume,
}
Go::BsplineBasis SplineUtils::adjustBasis (const Go::BsplineBasis& basis,
SplineUtils::AdjustOp adjust)
{
if (adjust == AdjustOp::Original)
return basis;
std::vector<double> knots;
basis.knotsSimple(knots);
std::vector<int> mult;
basis.knotMultiplicities(mult);
std::vector<int> cont(knots.size());
cont.front() = cont.back() = -1;
int order = basis.order();
int start_cont = adjust == AdjustOp::Lower ? order-2 : order;
int mult_adjust = adjust == AdjustOp::Lower ? 0 : 1;
int new_order = adjust == AdjustOp::Lower ? order - 1 : order + 1;
for (size_t i = 1; i < knots.size()-1; ++i)
cont[i] = start_cont - (mult[i] == 1 ? 1 : mult[i] + mult_adjust);
std::vector<double> newknot = SplineUtils::buildKnotVector(new_order-1, knots, cont);
return Go::BsplineBasis(new_order, newknot.begin(), newknot.end());
}
std::vector<double> SplineUtils::buildKnotVector(int p,
const std::vector<double>& knots,
const std::vector<int>& cont)

View File

@ -27,6 +27,7 @@ namespace Go {
struct BasisDerivsSf3;
struct BasisDerivs;
struct BasisDerivs2;
class BsplineBasis;
class SplineCurve;
class SplineSurface;
class SplineVolume;
@ -82,6 +83,17 @@ namespace SplineUtils //! Various utility functions on spline objects.
const FunctionBase& f,
int nComp = 1, Real time = Real(0));
//! \brief Enumeration of basis adjustment operations.
enum class AdjustOp {
Lower, //!< Lower order by one
Original, //!< Keep original
Raise, //!< Raise order by one
};
//! \brief Returns a basis adjusted according to the given operation.
Go::BsplineBasis adjustBasis(const Go::BsplineBasis& basis,
AdjustOp adjust);
//! \brief Builds a knot vector from a given polynomial order, knots and continuities.
std::vector<double> buildKnotVector(int p, const std::vector<double>& simple_knots,
const std::vector<int>& continuities);

View File

@ -12,10 +12,11 @@
#include "SplineUtils.h"
#include "GoTools/utils/Point.h"
#include "GoTools/geometry/SplineSurface.h"
#include <GoTools/geometry/BsplineBasis.h>
#include "GoTools/geometry/Line.h"
#include "GoTools/geometry/Disc.h"
#include "GoTools/geometry/Plane.h"
#include "GoTools/geometry/SplineSurface.h"
#include "GoTools/trivariate/SphereVolume.h"
#include "GoTools/trivariate/SplineVolume.h"
#include "ExprFunctions.h"
@ -450,3 +451,75 @@ TEST(TestSplineUtils, BuildKnotVector)
for (size_t i = 0; i < ref.size(); ++i)
EXPECT_FLOAT_EQ(ref[i], res[i]);
}
namespace {
struct AdjustBasisTest {
int order_in;
std::vector<double> knots_in;
SplineUtils::AdjustOp op;
std::vector<double> knots_out;
};
using Op = SplineUtils::AdjustOp;
const std::vector<AdjustBasisTest> tests = {
// p1 -> p1
{2, {0.0, 0.0, 1.0, 1.0}, Op::Original,
{0.0, 0.0, 1.0, 1.0}},
// p1 -> p2
{2, {0.0, 0.0, 1.0, 1.0}, Op::Raise,
{0.0, 0.0, 0.0, 1.0, 1.0, 1.0}},
// p1 -> p2, extra knot
{2, {0.0, 0.0, 0.5, 1.0, 1.0}, Op::Raise,
{0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0}},
// p2 -> p3, extra knot
{3, {0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0}, Op::Raise,
{0.0, 0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0, 1.0}},
// p2 -> p3, reduced cont
{3, {0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0}, Op::Raise,
{0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0}},
//p3 -> p4
{4, {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}, Op::Raise,
{0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0}},
//p3 -> p4, reduced cont
{4, {0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0}, Op::Raise,
{0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0}},
//p2 -> p1
{3, {0.0, 0.0, 0.0, 1.0, 1.0, 1.0}, Op::Lower,
{0.0, 0.0, 1.0, 1.0}},
//p2 -> p1, extra knot
{3, {0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0}, Op::Lower,
{0.0, 0.0, 0.5, 1.0, 1.0}},
//p3 -> p2, reduced cont
{4, {0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0}, Op::Lower,
{0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0}},
//p4 -> p3
{5, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0}, Op::Lower,
{0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}},
};
}
class TestSplineUtils : public testing::Test,
public testing::WithParamInterface<AdjustBasisTest>
{
};
TEST_P(TestSplineUtils, AdjustBasis)
{
Go::BsplineBasis basis_in(GetParam().order_in,
GetParam().knots_in.begin(),
GetParam().knots_in.end());
const Go::BsplineBasis res = SplineUtils::adjustBasis(basis_in,GetParam().op);
const std::vector<double> out{res.begin(), res.end()};
EXPECT_EQ(out, GetParam().knots_out);
}
INSTANTIATE_TEST_SUITE_P(TestSplineUtils, TestSplineUtils, testing::ValuesIn(tests));