예제 #1
0
 public FractalSettings(IFractalAlgorithm algorithm, int screenWidth, int screenHeight, Rectangle <double> fractalRect, int maxIterations)
 {
     this.Algorithm     = algorithm;
     this.FractalRect   = fractalRect;
     this.MaxIterations = maxIterations;
     this.ScreenWidth   = screenWidth;
     this.ScreenHeight  = screenHeight;
 }
예제 #2
0
 public void RegisterFractalAlgorithm(IFractalAlgorithm algorithm)
 {
     this.algorithms.Add(algorithm);
 }
예제 #3
0
        /// <summary>
        /// Draws the specified fractal algorithm.
        /// </summary>
        /// <param name="color">The color parameter.</param>
        /// <param name="motion">The motion parameter.</param>
        /// <param name="algorithm">The fractal algorithm.</param>
        /// <param name="techniques">The coloring techniques.</param>
        /// <param name="combinationFunction">The combination function.</param>
        /// <param name="maxParallelism">The maximum parallelism. By default will take all the CPUs available.</param>
        /// <returns>The final bitmap.</returns>
        public byte[] Draw(
            double color,
            double motion,
            IFractalAlgorithm algorithm,
            IEnumerable <IColoringTechnique> techniques,
            Func <Color[], Color> combinationFunction,
            int maxParallelism = -1)
        {
            // if the max parallelism is not provided, the system will try to create
            // one thread per logical processor available.
            if (maxParallelism <= 0)
            {
                maxParallelism = this.GetMaxParallelism();
            }

            // creates an memory array for all the pixels in the final drawing.
            var bitmapArray = new byte[this.Width * this.Height * 4];

            // separates the image array into smaller slices, once per thread. The idea is to
            // calculate sectors of the fractal in parallel.
            var memorySlices = bitmapArray.SliceArray(maxParallelism);

            // converts the enumeration to a list just to prevent multiple enumerations later.
            var colorTechniques = techniques.ToList();

            //  runs the algorithm and then the coloring techniques for each slice, in parallel.
            Parallel.ForEach(memorySlices, new ParallelOptions {
                MaxDegreeOfParallelism = maxParallelism
            }, memorySlice =>
            {
                var span  = memorySlice.Span;
                var start = memorySlice.Start;

                for (var i = 0; i < span.Length; i += 4)
                {
                    ////////////////////////////////////////////////////////////////////////////////////////////////////////
                    // first we need to calculate the pixel position based on the linear array index:
                    //
                    //    x = index % width
                    //    y = index % height
                    //
                    // but take in account that the index is slice-based, so 0 is not really 0, but 0 + slice start.
                    // so the formula now looks like:
                    //
                    //    x = (index + start) % width
                    //    y = (index + start) / width
                    //
                    ////////////////////////////////////////////////////////////////////////////////////////////////////////
                    var realIndex = i + start;
                    var x         = (int)(realIndex / 4.0f) % this.Width;
                    var y         = (int)(realIndex / 4.0f) / this.Width;

                    // now we have the correct pixel coordinates, but we are working with a different coordinate system
                    // in the complex space, dictated by the TopLeft and BottomRight corners, so we need to convert the
                    // pixel coordinates to the fractal space.
                    var complexNumber = this.ToFractalSpace(new Point(x, y));

                    // calculates the fractal algorithm for the complex number.
                    var result = algorithm.Calculate(complexNumber, motion);

                    // calculates all the colors based on the techniques.
                    var colors = colorTechniques.Select(t => t.Colorize(result, color)).ToArray();

                    // calculates a final color combining all the different colors.
                    var finalColor = combinationFunction(colors).ToSystemColor();

                    // sets the color coordinates in the slice.
                    span[i]     = finalColor.B;
                    span[i + 1] = finalColor.G;
                    span[i + 2] = finalColor.R;
                    span[i + 3] = finalColor.A;
                }
            });

            return(bitmapArray);
        }
예제 #4
0
 public IAction CreateChangeAlgorithmAction(IFractalContext context, IFractalAlgorithm algorithm)
 {
     return(new ChangeParameterSelectionAction <IFractalAlgorithm>(context, c => c.CurrentAlgorithm, algorithm));
 }