System.Drawing.GeomUtilities.SigmaBellShape C# (CSharp) Method

SigmaBellShape() static private method

static private SigmaBellShape ( float focus, float scale ) : System.Drawing.Drawing2D.Blend
focus float
scale float
return System.Drawing.Drawing2D.Blend
        internal static Blend SigmaBellShape(float focus, float scale)
        {
            Blend blend = new Blend();

            float pos = 0.0f;
            int count = 511; /* total no of samples */
            int index;
            float sigma;
            float mean;
            float fall_off_len = 2.0f; /* curve fall off length in terms of SIGMA */
            float delta; /* distance between two samples */

            float phi; /* variable to hold the value of Phi - Normal Distribution - CFD etc... */

            /* we get a curve not starting from 0 and not ending at 1.
             * so we subtract the starting value and divide by the curve
             * height to make it fit in the 0 to scale range
             */
            float curve_bottom;
            float curve_top;
            float curve_height;

            if (focus == 0 || focus == 1) {
                count = 256;
            }

            if (blend.Positions.Length != count) {
                blend = new Blend(count);
            }

            /* Set the blend colors. We use integral of the Normal Distribution,
             * i.e. Cumulative Distribution Function (CDF).
             *
             * Normal distribution:
             *
             * y (x) = (1 / sqrt (2 * PI * sq (sigma))) * exp (-sq (x - mu)/ (2 * sq (sigma)))
             *
             * where, y = height of normal curve,
             *        sigma = standard deviation
             *        mu = mean
             * OR
             * y (x) = peak * exp ( - z * z / 2)
             * where, z = (x - mu) / sigma
             *
             * In this curve, peak would occur at mean i.e. for x = mu. This results in
             * a peak value of peak = (1 / sqrt (2 * PI * sq (sigma))).
             *
             * Cumulative distribution function:
             * Ref: http://mathworld.wolfram.com/NormalDistribution.html
             * see function Phi(x) below - Φ(x)
             *
             * D (x) = Phi(z)
             * where, z = (x - mu) / sigma
             *
             */
            if (focus == 0) {
                /* right part of the curve with a complete fall in fall_off_len * SIGMAs */
                sigma = 1.0f / fall_off_len;
                mean = 0.5f;
                delta = 1.0f / 255.0f;

                curve_bottom = (float)Phi((1.0f - mean) / sigma);
                curve_top = (float)Phi((focus - mean) / sigma);
                curve_height = curve_top - curve_bottom;

                /* set the start */
                blend.Positions[0] = focus;
                blend.Factors[0] = scale;

                for (index = 1, pos = delta; index < 255; index++, pos += delta)
                {
                    blend.Positions[index] = pos;
                    phi = (float)Phi((pos - mean) / sigma);
                    blend.Factors[index] = (scale / curve_height) *
                        (phi - curve_bottom);
                }

                /* set the end */
                blend.Positions [count - 1] = 1.0f;
                blend.Factors [count - 1] = 0.0f;
            }

            else if (focus == 1) {
                /* left part of the curve with a complete rise in fall_off_len * SIGMAs */
                sigma = 1.0f / fall_off_len;
                mean = 0.5f;
                delta = 1.0f / 255.0f;

                curve_bottom = (float)Phi((0.0f - mean) / sigma);
                curve_top = (float)Phi((focus - mean) / sigma);
                curve_height = curve_top - curve_bottom;

                /* set the start */
                blend.Positions[0] = 0.0f;
                blend.Factors[0] = 0.0f;

                for (index = 1, pos = delta; index < 255; index++, pos += delta)
                {
                    blend.Positions[index] = pos;
                    phi = (float)Phi((pos - mean) / sigma);
                    blend.Factors[index] = (scale / curve_height) *
                        (pos - curve_bottom);
                }

                /* set the end */
                blend.Positions [count - 1] = focus;
                blend.Factors [count - 1] = scale;
            }

            else {
                /* left part of the curve with a complete fall in fall_off_len * SIGMAs */
                sigma = focus / (2 * fall_off_len);
                mean = focus / 2.0f;
                delta = focus / 255.0f;

                /* set the start */
                blend.Positions [0] = 0.0f;
                blend.Factors [0] = 0.0f;

                curve_bottom = (float)Phi((0.0f - mean) / sigma);
                curve_top = (float)Phi((focus - mean) / sigma);
                curve_height = curve_top - curve_bottom;

                for (index = 1, pos = delta; index < 255; index++, pos += delta) {
                    blend.Positions [index] = pos;
                    phi = (float)Phi((pos - mean) / sigma);
                    blend.Factors [index] = (scale / curve_height) *
                        (phi - curve_bottom);
                }

                blend.Positions [index] = focus;
                blend.Factors [index] = scale;

                /* right part of the curve with a complete fall in fall_off_len * SIGMAs */
                sigma = (1.0f - focus) / (2 * fall_off_len);
                mean = (1.0f + focus) / 2.0f;
                delta = (1.0f - focus) / 255.0f;

                curve_bottom = (float)Phi((1.0f - mean) / sigma);
                curve_top = (float)Phi((focus - mean) / sigma);

                curve_height = curve_top - curve_bottom;

                index ++;
                pos = focus + delta;

                for (; index < 510; index++, pos += delta) {
                    blend.Positions [index] = pos;
                    phi = (float)Phi((pos - mean) / sigma);
                    blend.Factors [index] = (scale / curve_height) *
                        (phi - curve_bottom);
                }

                /* set the end */
                blend.Positions [count - 1] = 1.0f;
                blend.Factors [count - 1] = 0.0f;
            }

            return blend;
        }