// Use de Casteljau subdivision to approximate the parameter required to find x // on a Bezier spline // note, atX is already determined to be >= P0_X, <P1_X const float Spline::ApproximateCubicBezierParameter ( float atX, float P0_X, float C0_X, float C1_X, float P1_X ) const { if (fabs(atX - P0_X) < GetRangedEpsilon(atX, P0_X) ) { return 0.0; } if (fabs(P1_X - atX) < GetRangedEpsilon(atX, P1_X) ) { return 1.0; } int iterationStep = 0; float u = 0.0f; float v = 1.0f; // iteratively apply subdivision to approach value atX while (iterationStep < MAXIMUM_ITERATIONS) { float a = (P0_X + C0_X)*0.5f; float b = (C0_X + C1_X)*0.5f; float c = (C1_X + P1_X)*0.5f; float d = (a + b)*0.5f; float e = (b + c)*0.5f; float f = (d + e)*0.5f; // must be on curve - a Bezier spline is 2nd order diff continuous // The curve point is close enough to required value. if (fabsf(f - atX) < GetRangedEpsilon(f, atX) ) { break; } if (f < atX) { P0_X = f; C0_X = e; C1_X = c; u = (u + v)*0.5f; } else { C0_X = a; C1_X = d; P1_X = f; v = (u + v)*0.5f; } iterationStep++; } return ClampToZeroOne((u + v)*0.5f); }
bool Vector2::operator==(const Vector2& rhs) const { if (fabsf(x - rhs.x) > GetRangedEpsilon(x, rhs.x)) { return false; } if (fabsf(y - rhs.y) > GetRangedEpsilon(y, rhs.y)) { return false; } return true; }
const float Spline::GetYFromMonotonicX(float x) const { int segmentIndex=0; float yValue = 0.0f; if(FindSegment(x, segmentIndex)) { float s = ApproximateCubicBezierParameter (x, mKnots[segmentIndex].x, mOutTangents[segmentIndex].x, mInTangents[segmentIndex+1].x, mKnots[segmentIndex+1].x); yValue = GetY(segmentIndex, s); } else { if(mKnots.size() > 0) { Vector3 lastPoint = mKnots[mKnots.size()-1]; if(fabsf(lastPoint.x - x) < GetRangedEpsilon(lastPoint.x, x)) { yValue = lastPoint.y; } } } return yValue; }
View::Orientation View::DegreeToViewOrientation( Degree degree ) { View::Orientation orientation = PORTRAIT; if( fabsf( mOrientationFunction[PORTRAIT] - degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT], degree ) ) { orientation = PORTRAIT; } else if( fabsf( mOrientationFunction[LANDSCAPE] - degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE], degree ) ) { orientation = LANDSCAPE; } else if( fabsf( mOrientationFunction[PORTRAIT_INVERSE] - degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT_INVERSE], degree ) ) { orientation = PORTRAIT_INVERSE; } else if( fabsf( mOrientationFunction[LANDSCAPE_INVERSE] - degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE_INVERSE], degree ) ) { orientation = LANDSCAPE_INVERSE; } return orientation; }
bool Degree::operator==( const Degree& rhs ) const { return fabsf( mValue - rhs.mValue ) < GetRangedEpsilon( mValue, rhs.mValue ); }
bool PointSize::operator==( PointSize pointSize ) { return fabs( value - pointSize.value ) < GetRangedEpsilon( value, pointSize.value ); }
bool Radian::operator==( const Radian& rhs ) const { return fabsf( mValue - rhs.mValue ) < GetRangedEpsilon( mValue, rhs.mValue ); }