void
nsSMILKeySpline::CalcSampleValues()
{
    for (int i = 0; i < kSplineTableSize; ++i) {
        mSampleValues[i] = CalcBezier(double(i) * kSampleStepSize, mX1, mX2);
    }
}
double
nsSMILKeySpline::GetSplineValue(double aX) const
{
    if (mX1 == mY1 && mX2 == mY2)
        return aX;

    return CalcBezier(GetTForX(aX), mY1, mY2);
}
double
nsSMILKeySpline::NewtonRaphsonIterate(double aX, double aGuessT) const
{
    // Refine guess with Newton-Raphson iteration
    for (int i = 0; i < NEWTON_ITERATIONS; ++i) {
        // We're trying to find where f(t) = aX,
        // so we're actually looking for a root for: CalcBezier(t) - aX
        double currentX = CalcBezier(aGuessT, mX1, mX2) - aX;
        double currentSlope = GetSlope(aGuessT, mX1, mX2);

        if (currentSlope == 0.0)
            return aGuessT;

        aGuessT -= currentX / currentSlope;
    }

    return aGuessT;
}
double
nsSMILKeySpline::BinarySubdivide(double aX, double aA, double aB) const
{
    double currentX;
    double currentT;
    int i = 0;

    do
    {
        currentT = aA + (aB - aA) / 2.0;
        currentX = CalcBezier(currentT, mX1, mX2) - aX;

        if (currentX > 0.0) {
            aB = currentT;
        } else {
            aA = currentT;
        }
    } while (fabs(currentX) > SUBDIVISION_PRECISION
             && ++i < SUBDIVISION_MAX_ITERATIONS);

    return currentT;
}
Example #5
0
void CDSegment::Draw(CDC *pDC, CDoubleRect DrawPlace, int iWidth) const
{
	int i, nBez,b;
	CPoint * paPoints;
	double daContr[4];
	double *pBezPts;
	double dRelWidth, dRelHeight;

	paPoints = new CPoint[m_nCount];
	if (paPoints == NULL) return;

	dRelWidth = DrawPlace.Width() / iWidth;
	dRelHeight = DrawPlace.Height() / NORM_DIGIHEIGHT;
	for (i = 0; i < m_nCount; i++)
	{
		if (m_paTypes[i] != PT_BEZIERTO)
		{
			paPoints[i] = CPoint(DrawPlace.left + dRelWidth	 * m_paPoints[i].x + 0.5,
								 DrawPlace.top  + dRelHeight * m_paPoints[i].y + 0.5);
		}
	}

	for (i = 0; i < m_nCount; i++)
	{
		if (m_paTypes[i] == PT_MOVETO)
		{
			pDC->MoveTo(paPoints[i]);
		}
		else if (m_paTypes[i] == PT_LINETO)
		{
			VERIFY(pDC->LineTo(paPoints[i]));
		}
		else if (m_paTypes[i] == PT_BEZIERTO)
		{
			// Look for the first non-bezier point(This is the EndPoint)...
			nBez = 0;
			do
			{
				nBez++;
			} while (m_paTypes[i+nBez] == PT_BEZIERTO);

			pBezPts = new double[2*(nBez+2)];
			for (b = 0; b < (nBez+2)*2; b += 2)
			{
				pBezPts[b  ] = DrawPlace.left + dRelWidth	* m_paPoints[i-1+b/2].x; 
				pBezPts[b+1] = DrawPlace.top  + dRelHeight	* m_paPoints[i-1+b/2].y;
			}
			CalcBezier(pBezPts, 2*(nBez+2), daContr);
			delete[] pBezPts;

			paPoints[i  ].x	= daContr[0] + 0.5;
			paPoints[i  ].y	= daContr[1] + 0.5;
			paPoints[i+1].x	= daContr[2] + 0.5;
			paPoints[i+1].y	= daContr[3] + 0.5;
			paPoints[i+2]	= paPoints[i+nBez];

			VERIFY(pDC->PolyBezierTo(&paPoints[i], 3));
			i += nBez;
		}
	} // for
	delete[] paPoints;
}