// Geometric Tools, LLC // Copyright (c) 1998-2012 // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt // // File Version: 5.0.1 (2010/10/01) #include "BSplineCurve.h" namespace NURBS { //---------------------------------------------------------------------------- template BSplineCurve::BSplineCurve (int numCtrlPoints, const Array1D_Vector3& ctrlPoint, int degree, bool loop, bool open) : SingleCurve((Real)0, (Real)1), mLoop(loop) { assertion(numCtrlPoints >= 2, "Invalid input\n"); assertion(1 <= degree && degree <= numCtrlPoints-1, "Invalid input\n"); mNumCtrlPoints = numCtrlPoints; mReplicate = (loop ? (open ? 1 : degree) : 0); CreateControl(ctrlPoint); mBasis.Create(mNumCtrlPoints + mReplicate, degree, open); } //---------------------------------------------------------------------------- template BSplineCurve::BSplineCurve (int numCtrlPoints, const Array1D_Vector3& ctrlPoint, int degree, bool loop, const Real* knot) : SingleCurve((Real)0, (Real)1), mLoop(loop) { assertion(numCtrlPoints >= 2, "Invalid input\n"); assertion(1 <= degree && degree <= numCtrlPoints-1, "Invalid input\n"); mNumCtrlPoints = numCtrlPoints; mReplicate = (loop ? 1 : 0); CreateControl(ctrlPoint); mBasis.Create(mNumCtrlPoints + mReplicate, degree, knot); } //---------------------------------------------------------------------------- template void BSplineCurve::CreateControl (const Array1D_Vector3& ctrlPoint) { int newNumCtrlPoints = mNumCtrlPoints + mReplicate; newNumCtrlPoints = newNumCtrlPoints; mCtrlPoint = ctrlPoint; for (int i = 0; i < mReplicate; ++i) { mCtrlPoint[mNumCtrlPoints + i] = ctrlPoint[i]; } } //---------------------------------------------------------------------------- template int BSplineCurve::GetNumCtrlPoints () const { return mNumCtrlPoints; } //---------------------------------------------------------------------------- template int BSplineCurve::GetDegree () const { return mBasis.GetDegree(); } //---------------------------------------------------------------------------- template bool BSplineCurve::IsOpen () const { return mBasis.IsOpen(); } //---------------------------------------------------------------------------- template bool BSplineCurve::IsUniform () const { return mBasis.IsUniform(); } //---------------------------------------------------------------------------- template bool BSplineCurve::IsLoop () const { return mLoop; } //---------------------------------------------------------------------------- template void BSplineCurve::SetControlPoint (int i, const Vector3& ctrl) { if (0 <= i && i < mNumCtrlPoints) { // Set the control point. mCtrlPoint[i] = ctrl; // Set the replicated control point. if (i < mReplicate) { mCtrlPoint[mNumCtrlPoints + i] = ctrl; } } } //---------------------------------------------------------------------------- template Vector3 BSplineCurve::GetControlPoint (int i) const { if (0 <= i && i < mNumCtrlPoints) { return mCtrlPoint[i]; } return Vector3(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); } //---------------------------------------------------------------------------- template void BSplineCurve::SetKnot (int i, Real knot) { mBasis.SetKnot(i, knot); } //---------------------------------------------------------------------------- template Real BSplineCurve::GetKnot (int i) const { return mBasis.GetKnot(i); } //---------------------------------------------------------------------------- template void BSplineCurve::Get (Real t, Vector3* pos, Vector3* der1, Vector3* der2, Vector3* der3) { int i, imin, imax; if (der3) { mBasis.Compute(t, 0, imin, imax); mBasis.Compute(t, 1, imin, imax); mBasis.Compute(t, 2, imin, imax); mBasis.Compute(t, 3, imin, imax); } else if (der2) { mBasis.Compute(t, 0, imin, imax); mBasis.Compute(t, 1, imin, imax); mBasis.Compute(t, 2, imin, imax); } else if (der1) { mBasis.Compute(t, 0, imin, imax); mBasis.Compute(t, 1, imin, imax); } else { mBasis.Compute(t, 0, imin, imax); } if (pos) { *pos = Vector3_ZERO; for (i = imin; i <= imax; ++i) { *pos += mBasis.GetD0(i)*mCtrlPoint[i]; } } if (der1) { *der1 = Vector3_ZERO; for (i = imin; i <= imax; ++i) { *der1 += mBasis.GetD1(i)*mCtrlPoint[i]; } } if (der2) { *der2 = Vector3_ZERO; for (i = imin; i <= imax; ++i) { *der2 += mBasis.GetD2(i)*mCtrlPoint[i]; } } if (der3) { *der3 = Vector3_ZERO; for (i = imin; i <= imax; ++i) { *der3 += mBasis.GetD3(i)*mCtrlPoint[i]; } } } //---------------------------------------------------------------------------- template BSplineBasis& BSplineCurve::GetBasis () { return mBasis; } //---------------------------------------------------------------------------- template Vector3 BSplineCurve::GetPosition (Real t) { Vector3 pos; Get(t, &pos, 0, 0, 0); return pos; } //---------------------------------------------------------------------------- template Vector3 BSplineCurve::GetFirstDerivative (Real t) { Vector3 der1; Get(t, 0, &der1, 0, 0); return der1; } //---------------------------------------------------------------------------- template Vector3 BSplineCurve::GetSecondDerivative (Real t) { Vector3 der2; Get(t, 0, 0, &der2, 0); return der2; } //---------------------------------------------------------------------------- template Vector3 BSplineCurve::GetThirdDerivative (Real t) { Vector3 der3; Get(t, 0, 0, 0, &der3); return der3; } //---------------------------------------------------------------------------- template Array1D_Real NURBS::BSplineCurve::GetKnotVector(bool isInnerOnly) { if(isInnerOnly) { int d = this->GetDegree() + 1; Array1D_Real result(mBasis.mKnot.begin() + d, mBasis.mKnot.end() - d); return result; } else return this->mBasis.mKnot; } //---------------------------------------------------------------------------- // Explicit instantiation. //---------------------------------------------------------------------------- //template //class BSplineCurve; template class BSplineCurve; //---------------------------------------------------------------------------- }