You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
5.2 KiB
144 lines
5.2 KiB
3 months ago
|
// David Eberly, Geometric Tools, Redmond WA 98052
|
||
|
// Copyright (c) 1998-2021
|
||
|
// Distributed under the Boost Software License, Version 1.0.
|
||
|
// https://www.boost.org/LICENSE_1_0.txt
|
||
|
// https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
||
|
// Version: 4.0.2019.08.13
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <Mathematics/NURBSCurve.h>
|
||
|
|
||
|
// The algorithm for representing a circle as a NURBS curve or a sphere as a
|
||
|
// NURBS surface is described in
|
||
|
// https://www.geometrictools.com/Documentation/NURBSCircleSphere.pdf
|
||
|
// The implementations are related to the documents as shown next.
|
||
|
// NURBSQuarterCircleDegree2 implements equation (9)
|
||
|
// NURBSQuarterCircleDegree4 implements equation (10)
|
||
|
// NURBSHalfCircleDegree3 implements equation (12)
|
||
|
// NURBSFullCircleDegree3 implements Section 2.3
|
||
|
|
||
|
namespace gte
|
||
|
{
|
||
|
template <typename Real>
|
||
|
class NURBSQuarterCircleDegree2 : public NURBSCurve<2, Real>
|
||
|
{
|
||
|
public:
|
||
|
// Construction. The quarter circle is x^2 + y^2 = 1 for x >= 0
|
||
|
// and y >= 0. The direction of traversal is counterclockwise as
|
||
|
// u increase from 0 to 1.
|
||
|
NURBSQuarterCircleDegree2()
|
||
|
:
|
||
|
NURBSCurve<2, Real>(BasisFunctionInput<Real>(3, 2), nullptr, nullptr)
|
||
|
{
|
||
|
Real const sqrt2 = std::sqrt((Real)2);
|
||
|
this->mWeights[0] = sqrt2;
|
||
|
this->mWeights[1] = (Real)1;
|
||
|
this->mWeights[2] = sqrt2;
|
||
|
|
||
|
this->mControls[0] = { (Real)1, (Real)0 };
|
||
|
this->mControls[1] = { (Real)1, (Real)1 };
|
||
|
this->mControls[2] = { (Real)0, (Real)1 };
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename Real>
|
||
|
class NURBSQuarterCircleDegree4 : public NURBSCurve<2, Real>
|
||
|
{
|
||
|
public:
|
||
|
// Construction. The quarter circle is x^2 + y^2 = 1 for x >= 0
|
||
|
// and y >= 0. The direction of traversal is counterclockwise as
|
||
|
// u increases from 0 to 1.
|
||
|
NURBSQuarterCircleDegree4()
|
||
|
:
|
||
|
NURBSCurve<2, Real>(BasisFunctionInput<Real>(5, 4), nullptr, nullptr)
|
||
|
{
|
||
|
Real const sqrt2 = std::sqrt((Real)2);
|
||
|
this->mWeights[0] = (Real)1;
|
||
|
this->mWeights[1] = (Real)1;
|
||
|
this->mWeights[2] = (Real)2 * sqrt2 / (Real)3;
|
||
|
this->mWeights[3] = (Real)1;
|
||
|
this->mWeights[4] = (Real)1;
|
||
|
|
||
|
Real const x1 = (Real)1;
|
||
|
Real const y1 = (Real)0.5 / sqrt2;
|
||
|
Real const x2 = (Real)1 - sqrt2 / (Real)8;
|
||
|
this->mControls[0] = { (Real)1, (Real)0 };
|
||
|
this->mControls[1] = { x1, y1 };
|
||
|
this->mControls[2] = { x2, x2 };
|
||
|
this->mControls[3] = { y1, x1 };
|
||
|
this->mControls[4] = { (Real)0, (Real)1 };
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename Real>
|
||
|
class NURBSHalfCircleDegree3 : public NURBSCurve<2, Real>
|
||
|
{
|
||
|
public:
|
||
|
// Construction. The half circle is x^2 + y^2 = 1 for x >= 0. The
|
||
|
// direction of traversal is counterclockwise as u increases from
|
||
|
// 0 to 1.
|
||
|
NURBSHalfCircleDegree3()
|
||
|
:
|
||
|
NURBSCurve<2, Real>(BasisFunctionInput<Real>(4, 3), nullptr, nullptr)
|
||
|
{
|
||
|
Real const oneThird = (Real)1 / (Real)3;
|
||
|
this->mWeights[0] = (Real)1;
|
||
|
this->mWeights[1] = oneThird;
|
||
|
this->mWeights[2] = oneThird;
|
||
|
this->mWeights[3] = (Real)1;
|
||
|
|
||
|
this->mControls[0] = { (Real)1, (Real)0 };
|
||
|
this->mControls[1] = { (Real)1, (Real)2 };
|
||
|
this->mControls[2] = { (Real)-1, (Real)2 };
|
||
|
this->mControls[3] = { (Real)-1, (Real)0 };
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename Real>
|
||
|
class NURBSFullCircleDegree3 : public NURBSCurve<2, Real>
|
||
|
{
|
||
|
public:
|
||
|
// Construction. The full circle is x^2 + y^2 = 1. The direction of
|
||
|
// traversal is counterclockwise as u increases from 0 to 1.
|
||
|
NURBSFullCircleDegree3()
|
||
|
:
|
||
|
NURBSCurve<2, Real>(CreateBasisFunctionInput(), nullptr, nullptr)
|
||
|
{
|
||
|
Real const oneThird = (Real)1 / (Real)3;
|
||
|
this->mWeights[0] = (Real)1;
|
||
|
this->mWeights[1] = oneThird;
|
||
|
this->mWeights[2] = oneThird;
|
||
|
this->mWeights[3] = (Real)1;
|
||
|
this->mWeights[4] = oneThird;
|
||
|
this->mWeights[5] = oneThird;
|
||
|
this->mWeights[6] = (Real)1;
|
||
|
|
||
|
this->mControls[0] = { (Real)1, (Real)0 };
|
||
|
this->mControls[1] = { (Real)1, (Real)2 };
|
||
|
this->mControls[2] = { (Real)-1, (Real)2 };
|
||
|
this->mControls[3] = { (Real)-1, (Real)0 };
|
||
|
this->mControls[4] = { (Real)-1, (Real)-2 };
|
||
|
this->mControls[5] = { (Real)1, (Real)-2 };
|
||
|
this->mControls[6] = { (Real)1, (Real)0 };
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
static BasisFunctionInput<Real> CreateBasisFunctionInput()
|
||
|
{
|
||
|
// We need knots (0,0,0,0,1/2,1/2,1/2,1,1,1,1).
|
||
|
BasisFunctionInput<Real> input;
|
||
|
input.numControls = 7;
|
||
|
input.degree = 3;
|
||
|
input.uniform = true;
|
||
|
input.periodic = false;
|
||
|
input.numUniqueKnots = 3;
|
||
|
input.uniqueKnots.resize(input.numUniqueKnots);
|
||
|
input.uniqueKnots[0] = { (Real)0, 4 };
|
||
|
input.uniqueKnots[1] = { (Real)0.5, 3 };
|
||
|
input.uniqueKnots[2] = { (Real)1, 4 };
|
||
|
return input;
|
||
|
}
|
||
|
};
|
||
|
}
|