BRDFSlices.DisplayForm.SolveNewton C# (CSharp) Метод

SolveNewton() защищенный Метод

Numerically computes the intersection of a straight line with a strange curve we know the equation of... We're using the http://en.wikipedia.org/wiki/Newton's_method The computation is occurring in [ThetaH,ThetaD] space: ^ ThetaD | PI/2 +----------/-----+ ThetaH PI/2 We're looking for intersection point o given 2 values: the slope of the straight line and PhiD that guides the curvature of the strange curve C(y) The position of a point P on the line is given by P(x)=[x,slope.x] (we know the slope) we find o so that o = P(x) = C(y) So we can write: x = atan( tan(PI/2 - y) / cos(PhiD)) y = slope.x Replacing: x = atan( tan(PI/2 - slope.x) / cos(PhiD) ) Tanning: tan(x) = tan(PI/2 - slope.x) / cos(PhiD) Or: tan(x).tan(slope.x) = 1 / cos(PhiD) We know "slope" and "PhiD", we need solve to find x which is the ThetaH at which the intersection occurs...
protected SolveNewton ( double a, double b, int &_IterationsCount ) : double
a double
b double
_IterationsCount int
Результат double
        protected double SolveNewton( double a, double b, out int _IterationsCount )
        {
            if ( a > 1.0 )
                a = 1.0 / a;	// Mirror to avoid badly formed equations... (the scale factor is symmetric anyway)

            // Compute the original intersection of the straight line of slope tan( ThetaH0 / ThetaD0 ) with the line ThetaD = PI/2
            double	OriginalThetaH = 0.5 * Math.PI;
            double	OriginalThetaD = 0.5 * Math.PI * a;	// ThetaD_without_intersection = PI/2 * slope
            double	OriginalSqLength = OriginalThetaD*OriginalThetaD + OriginalThetaH*OriginalThetaH;

            // Start from 0 and iterate
            double	x = 0.499999 * Math.PI;		// Start from nearby PI/2 where the function is ill defined but will converge quickly
            double	Value = Math.Tan(a*x) * Math.Tan(x) - b;
            _IterationsCount = 0;
            bool	bError = false;
            while ( Value > 1e-4 )
            {
                _IterationsCount++;

                // Compute the step we need to perform...
                double	Derivative = a * Math.Tan(x) / (Math.Cos(a * x) * Math.Cos(a * x)) + Math.Tan(a * x) / (Math.Cos(x)*Math.Cos(x));
                if ( Math.Abs( Derivative ) < 1e-10 )
                {	// Can't go on!
                    bError = true;
                    break;
                }

                double	Step = Value / Derivative;
                x -= Step;

                // Estimate new error...
                double	OldValue = Value;
                Value = Math.Tan(a*x) * Math.Tan(x) - b;

                double	ErrorDiff = OldValue - Value;
                if ( ErrorDiff < 1e-4 )
                {	// Seems to be either static or divergent... There is no obvious solution but we'll accept the current value anyway...
                    bError = true;
                    break;
                }
            }

            double	IntersectionThetaH = Math.Min( 0.5 * Math.PI, x );
            double	IntersectionThetaD = a * IntersectionThetaH;
            double	IntersectionSqLength = IntersectionThetaH*IntersectionThetaH + IntersectionThetaD*IntersectionThetaD;

            double	ScaleFactor = Math.Sqrt( IntersectionSqLength / OriginalSqLength );
            if ( ScaleFactor > 1.0 || bError )
                throw new Exception( "Crap!" );

            //			ScaleFactor = Math.Min( 1.0, ScaleFactor * 1.1 );
            ScaleFactor = ScaleFactor * floatTrackbarControlScaleFactor.Value;

            return ScaleFactor;
        }