1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| /** Base class for curve representation.
*/
template< class PosType , unsigned short POS_TYPE_DIMENSION , class ValueType = float, class RelationType = float >
class Curve
{
public:
static const unsigned short DIMENSIONS = POS_TYPE_DIMENSION;
/** Constructor.
@param beginPoint Point where the curve begins in it's origin period. (Pos 1.0f)
@param endPoint Point where the curve ends in it's origin period. (Pos 0.0f)
*/
Curve( const PosType& beginPoint, const PosType& endPoint )
: m_beginPoint( beginPoint )
, m_endPoint( endPoint )
{;}
/** Destructor.
*/
virtual ~Curve(){;}
/** Calculate the position of a point on the curve.
This method will call calculateFromEquation to determine the position of the point in the origin period.
@param curveRelativePos Define where on the curve the point is, 0 being the begin point and 1 the end point.
If this value is over 1 or under 0, the curve will be managed as a infinitely repeating sequence, like if
between 0 and 1 it's a full period.
*/
PosType calculatePoint( const RelationType& curveRelativePos );
/** Get the begin point of the curve (in it's origin period).
*/
const PosType& getBeginPoint() const { return m_beginPoint; }
/** Get the end point of the curve (in it's origin period).
*/
const PosType& getEndPoint() const { return m_endPoint; }
protected:
/// Begin point of the curve (in it's origin period).
const PosType& m_beginPoint;
/// End point of the curve (in it's origin period).
const PosType& m_endPoint;
/** Equation from witch we get the position of a point on the origin period of the curve.
@param posParamIdx Index of the member of the position type to use in the equation.
@param absRelationA Value between 0 and 1 that determine where is the value between the begin point and the end point.
@param absRelationB Value equal to : 1 - absRelationA
*/
virtual ValueType calculateFromEquation( unsigned int posParamIdx, const RelationType& absRelationA , const RelationType& absRelationB ) = 0;
};
template< class PosType , unsigned short POS_TYPE_DIMENSION , class ValueType , class RelationType >
PosType Curve< PosType, POS_TYPE_DIMENSION, ValueType, RelationType >::calculatePoint( const RelationType& curveRelativePos )
{
const RelationType positiveCurveRelativePos = fabs( curveRelativePos );
const RelationType a = (positiveCurveRelativePos > 0 && positiveCurveRelativePos == ceil(positiveCurveRelativePos)) ? 1 : fmod( positiveCurveRelativePos , RelationType(1) );
const RelationType b = RelationType(1) - a;
const RelationType fullPeriodCount = (curveRelativePos == 0 ) ? 0 : (floor(curveRelativePos) - (floor(a) + floor(b))) ; // number of times we got OVER 1.0
const PosType lineVector = m_endPoint - m_beginPoint;
PosType resultPos;
if( fullPeriodCount >= 0 )
{
for( int i = 0; i < POS_TYPE_DIMENSION; ++i )
{
// note : the last part of the calculus is to allow having points farther than the begin point or the end point
resultPos[i] = this->calculateFromEquation( i, b, a) + ( fullPeriodCount * lineVector[i] ) ;
}
}
else
{
for( int i = 0; i < POS_TYPE_DIMENSION; ++i )
{
// note : the last part of the calculus is to allow having points farther than the begin point or the end point
resultPos[i] = this->calculateFromEquation( i, a, b) + ( fullPeriodCount * lineVector[i] ) ;
}
}
return resultPos;
}
// 1D specific version, assuming that PosType is not an array-like type
template< class PosType, class ValueType , class RelationType >
PosType Curve< PosType, 1, ValueType, RelationType >::calculatePoint< PosType, 1 , ValueType , RelationType >( const RelationType& curveRelativePos )
{
const RelationType positiveCurveRelativePos = fabs( curveRelativePos );
const RelationType a = (positiveCurveRelativePos > 0 && positiveCurveRelativePos == ceil(positiveCurveRelativePos)) ? 1 : fmod( positiveCurveRelativePos , RelationType(1) );
const RelationType b = RelationType(1) - a;
const RelationType fullPeriodCount = (curveRelativePos == 0 ) ? 0 : (floor(curveRelativePos) - (floor(a) + floor(b))) ; // number of times we got OVER 1.0
const PosType lineVector = m_endPoint - m_beginPoint;
PosType resultPos;
if( fullPeriodCount >= 0 )
{
// note : the last part of the calculus is to allow having points farther than the begin point or the end point
resultPos = this->calculateFromEquation( 0, b, a) + ( fullPeriodCount * lineVector ) ;
}
else
{
// note : the last part of the calculus is to allow having points farther than the begin point or the end point
resultPos = this->calculateFromEquation( 0, a, b) + ( fullPeriodCount * lineVector ) ;
}
return resultPos;
} |
Partager