Commit 6a1d9283 authored by Lars Krecklau's avatar Lars Krecklau

* Added min/max functions to math

* Added a sampling function to the nurbs that also allows for the calculation of the derivatives
parent 8d2ab73d
......@@ -92,6 +92,12 @@ inline float abs(float a) {return(a < 0.0f ? -a : a);}
inline double abs(double a) {return(a < 0.0 ? -a : a);}
inline int_t abs(int_t a) {return(a < 0 ? -a : a);}
template<typename T>
inline T max(T a, T b) {return(a > b ? a : b);}
template<typename T>
inline T min(T a, T b) {return(a < b ? a : b);}
inline uint_t ring(int_t a, uint_t mod) {bool b = a < 0; a = abs(a) % mod; return(b ? mod - a : a);}
inline glm::mat3 rotationMatrixX(float degree)
......
......@@ -30,13 +30,6 @@ public:
{}
virtual ~NURBSControlPoint(void) {}
NURBSControlPoint operator+(const NURBSControlPoint<DATA_DIMENSION>& _c) const
{
NURBSControlPoint c;
c.data = data + _c.data;
c.weight = weight + _c.weight;
return c;
}
const NURBSControlPoint& operator+=(const NURBSControlPoint<DATA_DIMENSION>& _c)
{
......@@ -45,14 +38,6 @@ public:
return *this;
}
NURBSControlPoint operator-(const NURBSControlPoint<DATA_DIMENSION>& _c) const
{
NURBSControlPoint c;
c.data = data - _c.data;
c.weight = weight - _c.weight;
return c;
}
const NURBSControlPoint& operator-=(const NURBSControlPoint<DATA_DIMENSION>& _c)
{
data -= _c.data;
......@@ -60,27 +45,25 @@ public:
return *this;
}
NURBSControlPoint operator/(float _value) const
const NURBSControlPoint& operator*=(const NURBSControlPoint<DATA_DIMENSION>& _c)
{
NURBSControlPoint c;
c.data = data / _value;
c.weight = weight / _value;
return c;
data *= _c.data;
weight *= _c.weight;
return *this;
}
const NURBSControlPoint& operator/=(float _value)
const NURBSControlPoint& operator/=(const NURBSControlPoint<DATA_DIMENSION>& _c)
{
data /= _value;
weight /= _value;
data /= _c.data;
weight /= _c.weight;
return *this;
}
NURBSControlPoint operator*(float _value) const
const NURBSControlPoint& operator/=(float _value)
{
NURBSControlPoint c;
c.data = data * _value;
c.weight = weight * _value;
return c;
data /= _value;
weight /= _value;
return *this;
}
const NURBSControlPoint& operator*=(float _value)
......@@ -94,6 +77,69 @@ public:
float weight;
};
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator+(const NURBSControlPoint<DATA_DIMENSION>& _lhs, const NURBSControlPoint<DATA_DIMENSION>& _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs.data + _rhs.data;
c.weight = _lhs.weight + _rhs.weight;
return c;
}
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator-(const NURBSControlPoint<DATA_DIMENSION>& _lhs, const NURBSControlPoint<DATA_DIMENSION>& _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs.data - _rhs.data;
c.weight = _lhs.weight - _rhs.weight;
return c;
}
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator*(const NURBSControlPoint<DATA_DIMENSION>& _lhs, const NURBSControlPoint<DATA_DIMENSION>& _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs.data * _rhs.data;
c.weight = _lhs.weight * _rhs.weight;
return c;
}
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator/(const NURBSControlPoint<DATA_DIMENSION>& _lhs, const NURBSControlPoint<DATA_DIMENSION>& _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs.data / _rhs.data;
c.weight = _lhs.weight / _rhs.weight;
return c;
}
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator*(const NURBSControlPoint<DATA_DIMENSION>& _lhs, float _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs.data * _rhs;
c.weight = _lhs.weight * _rhs;
return c;
}
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator*(float _lhs, const NURBSControlPoint<DATA_DIMENSION>& _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs * _rhs.data;
c.weight = _lhs * _rhs.weight;
return c;
}
template<uint_t DATA_DIMENSION>
NURBSControlPoint<DATA_DIMENSION> operator/(const NURBSControlPoint<DATA_DIMENSION>& _lhs, float _rhs)
{
NURBSControlPoint<DATA_DIMENSION> c;
c.data = _lhs.data / _rhs;
c.weight = _lhs.weight / _rhs;
return c;
}
template<uint_t DATA_DIMENSION>
std::ostream& operator<<(std::ostream& _os, const NURBSControlPoint<DATA_DIMENSION>& _controlPoint)
{
......
......@@ -8,6 +8,8 @@
#include <ACGL/ACGL.hh>
#include <ACGL/Scene/NURBSControlPoint.hh>
#include <ACGL/Utils/Log.hh>
#include <ACGL/Math/Math.hh>
#include <vector>
......@@ -62,18 +64,7 @@ public:
// http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS/NURBS-knot-insert.html
void insertKnot(float _t)
{
//Find the interval that _t lies in
uint_t interval = mDegree;
uint_t start = mOrder;
uint_t end = mKnots.size() - mOrder;
for(uint_t i = start; i < end; ++i)
{
if(mKnots[i] <= _t)
interval++;
else
break;
}
uint_t interval = getIntervalOf(_t);
//Apply the weight of all NURBS control points and
//reverse the order in the span for easier indices
......@@ -99,6 +90,118 @@ public:
mControlPoints[interval - i] = newControlPoints[i];
}
NURBSControlPointType sampleAt(float _t) const
{
uint_t interval = getIntervalOf(_t);
//Apply the weight of all NURBS control points and
//reverse the order in the span to easier indices
//in the next step.
std::vector< std::vector<NURBSControlPointType> > controlPointsInSpan;
for(int i = 0; i < mOrder; ++i)
controlPointsInSpan.push_back(std::vector<NURBSControlPointType>());
for(int i = 0; i < mOrder; ++i)
{
NURBSControlPointType controlPoint = mControlPoints[interval - i];
controlPoint.data *= controlPoint.weight;
controlPointsInSpan[mDegree].push_back(controlPoint);
}
for(int l = 0; l < mDegree; ++l)
{
for(int i = 0; i < mDegree - l; ++i)
{
float fRatio = (_t - mKnots[interval - i]) / (mKnots[interval + mDegree - l - i] - mKnots[interval - i]);
//Please note: Due to the reversed order we have:
//cControlPointsInSpan[i + 1] = m_cControlPoints[interval - i - 1]
//cControlPointsInSpan[i] = m_cControlPoints[interval - i]
controlPointsInSpan[mDegree - l - 1].push_back((1.0f - fRatio) * controlPointsInSpan[mDegree - l][i + 1] + fRatio * controlPointsInSpan[mDegree - l][i]);
}
}
controlPointsInSpan[0][0].data /= controlPointsInSpan[0][0].weight;
return controlPointsInSpan[0][0];
}
std::vector<NURBSControlPointType> sampleAt(float _t, uint_t _derivatives) const
{
// The first entry of sampleAndDerivatives will be the sample itself. The
// others are the derivatives. Therefore, we have _derivatives + 1 result
// values.
_derivatives = Math::Functions::min(mDegree, _derivatives);
uint_t results = _derivatives + 1;
std::vector<NURBSControlPointType> sampleAndDerivatives(results);
uint_t interval = getIntervalOf(_t);
// Apply the weight of all NURBS control points and
// reverse the order in the span to easier indices
// in the next step.
std::vector< std::vector<NURBSControlPointType> > controlPointsInSpan;
for(uint_t i = 0; i < mOrder; ++i)
controlPointsInSpan.push_back(std::vector<NURBSControlPointType>());
for(uint_t i = 0; i < mOrder; ++i)
{
NURBSControlPointType controlPoint = mControlPoints[interval - i];
controlPoint.data *= controlPoint.weight;
controlPointsInSpan[mDegree].push_back(controlPoint);
}
for(uint_t l = 0; l < mDegree; ++l)
{
for(uint_t i = 0; i < mDegree - l; ++i)
{
float fRatio = (_t - mKnots[interval - i]) / (mKnots[interval + mDegree - l - i] - mKnots[interval - i]);
//Please note: Due to the reversed order we have:
//cControlPointsInSpan[i + 1] = m_cControlPoints[interval - i - 1]
//cControlPointsInSpan[i] = m_cControlPoints[interval - i]
controlPointsInSpan[mDegree - l - 1].push_back((1.0f - fRatio) * controlPointsInSpan[mDegree - l][i + 1] + fRatio * controlPointsInSpan[mDegree - l][i]);
}
}
// Add the sample as first return value
controlPointsInSpan[0][0].data /= controlPointsInSpan[0][0].weight;
controlPointsInSpan[0][0].weight = 1.0f;
sampleAndDerivatives[0] = controlPointsInSpan[0][0];
// Calculate the derivatives
std::vector<int_t> factors(_derivatives + 1, 1);
for(uint_t i = 0; i < _derivatives; ++i)
{
for(uint_t j = i; j > 0; --j)
{
factors[j] = factors[j] + factors[j - 1];
}
controlPointsInSpan[i+1][0].data /= controlPointsInSpan[i+1][0].weight;
controlPointsInSpan[i+1][0].weight = 1.0f;
sampleAndDerivatives[i+1] = controlPointsInSpan[i+1][0];
for(uint_t k = 1; k < i+2; ++k)
{
controlPointsInSpan[i+1][k].data /= controlPointsInSpan[i+1][k].weight;
controlPointsInSpan[i+1][k].weight = 1.0f;
sampleAndDerivatives[i+1] += (k%2==1?-factors[k]:factors[k]) * controlPointsInSpan[i+1][k];
}
}
return sampleAndDerivatives;
}
NURBSCurve getSubCurveAt(float _t) const
{
uint_t interval = getIntervalOf(_t);
// Get the subcurve, where _t lies in
std::vector<NURBSControlPointType> controlPointsInSpan(mOrder);
for(uint_t i = 0; i < mOrder; ++i)
controlPointsInSpan[mDegree - i] = mControlPoints[interval - i];
// Knots = #ControlPoints (here mOrder) + mDegree + 1 = 2 * mOrder
std::vector<float> knotsInSpan(mOrder * 2);
for(uint_t i = 0; i < mOrder * 2; ++i)
knotsInSpan[mDegree + mOrder - i] = mKnots[interval + mOrder - i];
return NURBSCurve(controlPointsInSpan, knotsInSpan, mDegree);
}
//This function takes a knot vector and normalizes
//it to [0,1] within the region that can be evaluated,
//namely between the knots (degree) and (#knots - degree - 1)
......@@ -113,6 +216,24 @@ public:
}
private:
uint_t getIntervalOf(float _t) const
{
//Find the interval that _t lies in
uint_t interval = mDegree;
uint_t start = mOrder;
uint_t end = mKnots.size() - mOrder;
for(uint_t i = start; i < end; ++i)
{
if(mKnots[i] <= _t)
interval++;
else
break;
}
return interval;
}
uint_t mDegree;
uint_t mOrder;
std::vector<NURBSControlPointType> mControlPoints;
......
......@@ -28,14 +28,6 @@ public:
static const uint_t sDataDimension;
uint_t getDataDimension (void) const { return sDataDimension;}
NURBSDataVector operator+(const NURBSDataVector<DATA_DIMENSION>& _v) const
{
NURBSDataVector v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = data[i] + _v.data[i];
return v;
}
const NURBSDataVector& operator+=(const NURBSDataVector<DATA_DIMENSION>& _v)
{
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
......@@ -43,14 +35,6 @@ public:
return *this;
}
NURBSDataVector operator-(const NURBSDataVector<DATA_DIMENSION>& _v) const
{
NURBSDataVector v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = data[i] - _v.data[i];
return v;
}
const NURBSDataVector& operator-=(const NURBSDataVector<DATA_DIMENSION>& _v)
{
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
......@@ -58,33 +42,31 @@ public:
return *this;
}
NURBSDataVector operator/(float _value) const
const NURBSDataVector& operator*=(const NURBSDataVector<DATA_DIMENSION>& _v)
{
NURBSDataVector v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = data[i] / _value;
return v;
data[i] *= _v.data[i];
return *this;
}
const NURBSDataVector& operator/=(float _value)
const NURBSDataVector& operator/=(const NURBSDataVector<DATA_DIMENSION>& _v)
{
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
data[i] /= _value;
data[i] /= _v.data[i];
return *this;
}
NURBSDataVector operator*(float _value) const
const NURBSDataVector& operator*=(float _value)
{
NURBSDataVector v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = data[i] * _value;
return v;
data[i] *= _value;
return *this;
}
const NURBSDataVector& operator*=(float _value)
const NURBSDataVector& operator/=(float _value)
{
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
data[i] *= _value;
data[i] /= _value;
return *this;
}
......@@ -104,6 +86,69 @@ public:
float data[DATA_DIMENSION];
};
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator+(const NURBSDataVector<DATA_DIMENSION>& _lhs, const NURBSDataVector<DATA_DIMENSION>& _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs.data[i] + _rhs.data[i];
return v;
}
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator-(const NURBSDataVector<DATA_DIMENSION>& _lhs, const NURBSDataVector<DATA_DIMENSION>& _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs.data[i] - _rhs.data[i];
return v;
}
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator*(const NURBSDataVector<DATA_DIMENSION>& _lhs, const NURBSDataVector<DATA_DIMENSION>& _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs.data[i] * _rhs.data[i];
return v;
}
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator/(const NURBSDataVector<DATA_DIMENSION>& _lhs, const NURBSDataVector<DATA_DIMENSION>& _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs.data[i] / _rhs.data[i];
return v;
}
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator*(const NURBSDataVector<DATA_DIMENSION>& _lhs, float _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs.data[i] * _rhs;
return v;
}
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator*(float _lhs, const NURBSDataVector<DATA_DIMENSION>& _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs * _rhs.data[i];
return v;
}
template<uint_t DATA_DIMENSION>
NURBSDataVector<DATA_DIMENSION> operator/(const NURBSDataVector<DATA_DIMENSION>& _lhs, float _rhs)
{
NURBSDataVector<DATA_DIMENSION> v;
for(uint_t i = 0; i < DATA_DIMENSION; ++i)
v.data[i] = _lhs.data[i] / _rhs;
return v;
}
template<uint_t DATA_DIMENSION>
const uint_t NURBSDataVector<DATA_DIMENSION>::sDataDimension = DATA_DIMENSION;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment