コード例 #1
0
        /// <summary>
        /// Mouse-up handler for main form. The coordinates of the rectangle are
        /// saved so the new drawing can be rendered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mouseUpOnForm(object sender, MouseEventArgs e)
        {
            if (zoomCheckbox.Checked)
            {
                double x = Convert.ToDouble(e.X);
                double y = Convert.ToDouble(e.Y);

                ComplexPoint pixelCoord = new ComplexPoint((int)(xValue + (1005 / (zoomScale)) / 4), (int)(yValue + (691 / (zoomScale)) / 4));//
                zoomCoord2 = myPixelManager.GetAbsoluteMathsCoord(pixelCoord);

                // Swap to ensure that zoomCoord1 stores the lower-left
                // coordinate for the zoom region, and zoomCoord2 stores the
                // upper right coordinate.
                if (zoomCoord2.real < zoomCoord1.real)
                {
                    double temp = zoomCoord1.real;
                    zoomCoord1.real = zoomCoord2.real;
                    zoomCoord2.real = temp;
                }
                if (zoomCoord2.img < zoomCoord1.img)
                {
                    double temp = zoomCoord1.img;
                    zoomCoord1.img = zoomCoord2.img;
                    zoomCoord2.img = temp;
                }
                yMinCheckBox.Text = Convert.ToString(zoomCoord1.img);
                yMaxCheckBox.Text = Convert.ToString(zoomCoord2.img);
                xMinCheckBox.Text = Convert.ToString(zoomCoord1.real);
                xMaxCheckBox.Text = Convert.ToString(zoomCoord2.real);
                RenderImage();
            }
        }
コード例 #2
0
        /// <summary>
        /// Add complex value, arg, to this complex point, Z. The result is
        /// another complex number.
        /// </summary>
        /// <param name="arg">Complex number to add</param>
        /// <returns>Z + arg</returns>
        public ComplexPoint doCmplxAdd(ComplexPoint arg)
        {
            real += arg.real;
            img  += arg.img;

            return(this);
        }
コード例 #3
0
        /// <summary>
        /// On-click handler for main form. Defines the points (lower-left and upper-right)
        /// of a zoom rectangle.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mouseClickOnForm(object sender, MouseEventArgs e)
        {
            if (zoomCheckbox.Checked)
            {
                Pen    box = new Pen(Color.Black);
                double x   = Convert.ToDouble(e.X);
                xValue = x;
                double y = Convert.ToDouble(e.Y);
                yValue = y;

                try {
                    zoomScale = Convert.ToInt16(zoomTextBox.Text);
                } catch (Exception c) {
                    MessageBox.Show("Error: " + c.Message, "Error");
                }
                // Zoom scale has to be above 0, or their is no point in zooming.
                if (zoomScale < 1)
                {
                    MessageBox.Show("Zoom scale must be above 0");
                    zoomScale        = 7;
                    zoomTextBox.Text = "7";
                    return;
                }

                ComplexPoint pixelCoord = new ComplexPoint((int)(xValue - (1005 / (zoomScale)) / 4), (int)(yValue - (691 / (zoomScale)) / 4));//
                zoomCoord1 = myPixelManager.GetAbsoluteMathsCoord(pixelCoord);
            }
        }
コード例 #4
0
        /// <summary>
        /// Add complex value, arg, to this complex point, Z. The result is
        /// another complex number.
        /// </summary>
        /// <param name="arg">Complex number to add</param>
        /// <returns>Z + arg</returns>
        public ComplexPoint doCmplxAdd(ComplexPoint arg)
        {
            x += arg.x;
            y += arg.y;

            return(this);
        }
コード例 #5
0
ファイル: ScreenPixelManage.cs プロジェクト: LarsBusk/Learing
        /// <summary>
        /// Converts a pixel-coordinate increment (small change in X, Y
        /// screen coordiante) to the corresponding increment in mathematical
        /// coordinates. This is used, for example, when drawing the Mandlebrot
        /// set with chosen X, Y pixel steps, for which the cooresponding
        /// mathematical steps need to be known.
        ///
        /// This is done using the transformation functions that convert
        /// from maths coordinates to pixel coordinates. If these are
        /// respectively:
        ///
        /// Fx() and Fy() for the x and y domains, then to convert in the
        /// opposite direction, from pixels to maths coordinates we need
        /// to use:
        ///
        /// dFx()/dx and dFy()/dy (which are the derivates of each function),
        /// then multiply each by the corresponding pixel increments in
        /// either x or y.
        ///
        /// This implementation uses pre-calculated constant scale factors
        /// for an efficient implementation.
        ///
        /// </summary>
        /// <param name="pixelCoord">Screen coordinate</param>
        /// <returns></returns>
        public ComplexPoint GetDeltaMathsCoord(ComplexPoint pixelCoord)
        {
            ComplexPoint result = new ComplexPoint(
                pixelCoord.x / convConstX1,
                pixelCoord.y / convConstY2);

            return(result);
        }
コード例 #6
0
ファイル: ScreenPixelManage.cs プロジェクト: LarsBusk/Learing
        /// <summary>
        /// Convert from maths coordinates to pixel coordinates.
        /// </summary>
        /// <param name="cmplxPoint">Complex number (mathematical coordiantes)</param>
        /// <returns>Pixel coordinate, also a complex number but represented
        /// as an X,Y screen coordinate</returns>
        public PixelCoord GetPixelCoord(ComplexPoint cmplxPoint)
        {
            PixelCoord result = new PixelCoord();

            result.xPixel = (int)(convConstX1 * cmplxPoint.x - convConstX2);
            result.yPixel = (int)(convConstY1 - convConstY2 * cmplxPoint.y);
            return(result);
        }
コード例 #7
0
ファイル: ScreenPixelManage.cs プロジェクト: LarsBusk/Learing
        /// <summary>
        /// Get absolute maths coordinate from pixel coordinate. This is effectively
        /// an inverse calcuate: given a pixel screen coordinate it returns the
        /// corresponding mathematical point.
        /// </summary>
        /// <param name="pixelCoord">Screen coordinate</param>
        /// <returns>Mathematical point corresponding to pixelCoord</returns>
        public ComplexPoint GetAbsoluteMathsCoord(ComplexPoint pixelCoord)
        {
            ComplexPoint result = new ComplexPoint(
                (convConstX2 + pixelCoord.x) / convConstX1,
                (convConstY1 - pixelCoord.y) / convConstY2);

            return(result);
        }
コード例 #8
0
        /// <summary>
        /// Calculate the square of complex point, Z**2. The
        /// result is another complex number: (x*x - y*y) + i*2*x*y.
        /// </summary>
        /// <returns>Square of complex point</returns>
        public ComplexPoint doCmplxSq()
        {
            ComplexPoint result = new ComplexPoint(0, 0);

            result.x = x * x - y * y;
            result.y = 2 * x * y;

            return(result);
        }
コード例 #9
0
        /// <summary>
        /// Calculate complex square plus complex constant. The result
        /// is another complex number.
        /// </summary>
        /// <param name="arg"></param>
        /// <returns>Z**2 + arg</returns>
        public ComplexPoint DoCmplxSqPlusConst(ComplexPoint arg)
        {
            ComplexPoint result = DoCmplxSq(); //new ComplexPoint(0, 0);

            //result.real = real * real - img * img;
            //result.img = 2 * real * img;
            result.real += arg.real;
            result.img  += arg.img;
            return(result);
        }
コード例 #10
0
        /// <summary>
        /// Calculate complex square plus complex constant. The result
        /// is another complex number.
        /// </summary>
        /// <param name="arg"></param>
        /// <returns>Z**2 + arg</returns>
        public ComplexPoint doCmplxSqPlusConst(ComplexPoint arg)
        {
            ComplexPoint result = new ComplexPoint(0, 0);

            result.x  = x * x - y * y;
            result.y  = 2 * x * y;
            result.x += arg.x;
            result.y += arg.y;
            return(result);
        }
コード例 #11
0
ファイル: ScreenPixelManage.cs プロジェクト: LarsBusk/Learing
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="screenBottomLeftCorner"></param>
        /// <param name="screenTopRightCorner"></param>
        public ScreenPixelManage(Graphics graphics, ComplexPoint screenBottomLeftCorner, ComplexPoint screenTopRightCorner)
        {
            // Transform from mathematical to pixel coordinates.
            //
            // The following are long-handed calulations, now replaced with more efficient calculations
            // using convConst** values.
            //       this.xPixel = (int) ((graphics.VisibleClipBounds.Size.Width) / (screenTopRightCorner.x - screenBottomLeftCorner.x) * (cmplxPoint.x - screenBottomLeftCorner.x));
            //       this.yPixel = (int) (graphics.VisibleClipBounds.Size.Height - graphics.VisibleClipBounds.Size.Height / (screenTopRightCorner.y - screenBottomLeftCorner.y) * (cmplxPoint.y - screenBottomLeftCorner.y));

            convConstX1 = graphics.VisibleClipBounds.Size.Width / (screenTopRightCorner.x - screenBottomLeftCorner.x);
            convConstX2 = convConstX1 * screenBottomLeftCorner.x;

            convConstY1 = graphics.VisibleClipBounds.Size.Height * (1.0 + screenBottomLeftCorner.y / (screenTopRightCorner.y - screenBottomLeftCorner.y));
            convConstY2 = graphics.VisibleClipBounds.Size.Height / (screenTopRightCorner.y - screenBottomLeftCorner.y);
        }
コード例 #12
0
        private void RenderImage()
        {
            try {
                statusLabel.Text = "Status: Rendering";
                if (Convert.ToBoolean(pixelStepTextBox.Text.Equals("")) ||
                    Convert.ToBoolean(pixelStepTextBox.Text.Equals("0")) ||
                    Convert.ToBoolean(iterationCountTextBox.Text.Equals("")) ||
                    Convert.ToBoolean(yMinCheckBox.Text.Equals("")) ||
                    Convert.ToBoolean(yMaxCheckBox.Text.Equals("")) ||
                    Convert.ToBoolean(xMinCheckBox.Text.Equals("")) ||
                    Convert.ToBoolean(xMaxCheckBox.Text.Equals("")))
                {
                    // Choose default parameters and warn the user if the settings are all empty.
                    pixelStepTextBox.Text      = "1";
                    iterationCountTextBox.Text = "85";
                    yMinCheckBox.Text          = "-1";
                    yMaxCheckBox.Text          = "1";
                    xMinCheckBox.Text          = "-2";
                    xMaxCheckBox.Text          = "1";
                    MessageBox.Show("Invalid fields detected. Using default values.");
                    statusLabel.Text = "Status: Error";
                    return;
                }
                else
                {
                    // Show zoom and undo controls.
                    zoomCheckbox.Show();
                    undoButton.Show();
                    undoNum++;
                }

                // Mandelbrot iteration count.
                kMax       = Convert.ToInt32(iterationCountTextBox.Text);
                numColours = kMax;

                // If colourTable is not yet created or kMax has changed, create colourTable.
                if ((colourTable == null) || (kMax != colourTable.kMax) || (numColours != colourTable.nColour))
                {
                    colourTable = new ColourTable(numColours, kMax);
                }

                // Get the x, y range (mathematical coordinates) to plot.
                yMin = Convert.ToDouble(yMinCheckBox.Text);
                yMax = Convert.ToDouble(yMaxCheckBox.Text);
                xMin = Convert.ToDouble(xMinCheckBox.Text);
                xMax = Convert.ToDouble(xMaxCheckBox.Text);

                // Zoom scale.
                zoomScale = Convert.ToInt16(zoomTextBox.Text);

                // Clear any existing graphics content.
                g.Clear(Color.White);

                // Initialise working variables.
                int    height = (int)g.VisibleClipBounds.Size.Height;
                int    kLast  = -1;
                double modulusSquared;
                Color  color;
                Color  colorLast = Color.Red;

                // Get screen boundary (lower left & upper right). This is
                // used when calculating the pixel scaling factors.
                ComplexPoint screenBottomLeft = new ComplexPoint(xMin, yMin);
                ComplexPoint screenTopRight   = new ComplexPoint(xMax, yMax);

                // Create pixel manager. This sets up the scaling factors used when
                // converting from mathemathical to screen (pixel units) using the
                myPixelManager = new ScreenPixelManage(g, screenBottomLeft, screenTopRight);

                // The pixel step size defines the increment in screen pixels for each point
                // at which the Mandelbrot calcualtion will be done. e.g. a Step of 5 means
                // that the calcualtion will be done a 5-pixel increments. The X & Y increments
                // are the same.
                //
                // This increment is converted to mathematical coordinates.
                int          xyPixelStep = Convert.ToInt16(pixelStepTextBox.Text);
                ComplexPoint pixelStep   = new ComplexPoint(xyPixelStep, xyPixelStep);
                ComplexPoint xyStep      = myPixelManager.GetDeltaMathsCoord(pixelStep);

                // Start stopwatch - used to measure performance improvements
                // (from improving the efficiency of the maths implementation).
                Stopwatch sw = new Stopwatch();
                sw.Start();

                // Main loop, nested over Y (outer) and X (inner) values.
                int lineNumber = 0;
                int yPix       = myBitmap.Height - 1;
                for (double y = yMin; y < yMax; y += xyStep.img)
                {
                    int xPix = 0;
                    for (double x = xMin; x < xMax; x += xyStep.real)
                    {
                        // Create complex point C = x + i*y.
                        ComplexPoint c = new ComplexPoint(x, y);

                        // Initialise complex value Zk.
                        ComplexPoint zk = new ComplexPoint(0, 0);

                        // Do the main Mandelbrot calculation. Iterate until the equation
                        // converges or the maximum number of iterations is reached.
                        int k = 0;
                        do
                        {
                            zk             = zk.DoCmplxSqPlusConst(c);
                            modulusSquared = zk.DoMoulusSq();
                            k++;
                        } while ((modulusSquared <= 4.0) && (k < kMax));

                        if (k < kMax)
                        {
                            // Max number of iterations was not reached. This means that the
                            // equation converged. Now assign a colour to the current pixel that
                            // depends on the number of iterations, k, that were done.

                            if (k == kLast)
                            {
                                // If the iteration count is the same as the last count, re-use the
                                // last pen. This avoids re-calculating colour factors which is
                                // computationally intensive. We benefit from this often because
                                // adjacent pixels are often the same colour, especially in large parts
                                // of the Mandelbrot set that are away from the areas of detail.
                                color = colorLast;
                            }
                            else
                            {
                                // Calculate coluor scaling, from k. We don't use complicated/fancy colour
                                // lookup tables. Instead, the following simple conversion works well:
                                //
                                // hue = (k/kMax)**0.25 where the constant 0.25 can be changed if wanted.
                                // This formula stretches colours allowing more to be assigned at higher values
                                // of k, which brings out detail in the Mandelbrot images.

                                // The following is a full colour calculation, replaced now with colour table.
                                // Uncomment and disable the colour table if wanted. The colour table works
                                // well but supports fewer colours than full calculation of hue and colour
                                // using double-precision arithmetic.
                                //double colourIndex = ((double)k) / kMax;
                                //double hue = Math.Pow(colourIndex, 0.25);

                                // Colour table lookup.
                                // Convert the hue value to a useable colour and assign to current pen.
                                // The saturation and lightness are hard-coded at 0.9 and 0.6 respectively,
                                // which work well.
                                color     = colourTable.GetColour(k);
                                colorLast = color;
                            }

                            // Draw single pixel
                            if (xyPixelStep == 1)
                            {
                                // Pixel step is 1, set a single pixel.
                                if ((xPix < myBitmap.Width) && (yPix >= 0))
                                {
                                    myBitmap.SetPixel(xPix, yPix, color);
                                }
                            }
                            else
                            {
                                // Pixel step is > 1, set a square of pixels.
                                for (int pX = 0; pX < xyPixelStep; pX++)
                                {
                                    for (int pY = 0; pY < xyPixelStep; pY++)
                                    {
                                        if (((xPix + pX) < myBitmap.Width) && ((yPix - pY) >= 0))
                                        {
                                            myBitmap.SetPixel(xPix + pX, yPix - pY, color);
                                        }
                                    }
                                }
                            }
                        }
                        xPix += xyPixelStep;
                    }
                    yPix -= xyPixelStep;
                    lineNumber++;
                    if ((lineNumber % 120) == 0)
                    {
                        Refresh();
                    }
                }
                // Finished rendering. Stop the stopwatch and show the elapsed time.
                sw.Stop();
                Refresh();
                stopwatchLabel.Text = Convert.ToString(sw.Elapsed.TotalSeconds);
                statusLabel.Text    = "Status: Render complete";

                // Save current settings to undo file.
                StreamWriter writer = new StreamWriter(@"C:\Users\" + userName + "\\mandelbrot_config\\Undo\\undo" + undoNum + ".txt");
                writer.Write(pixelStepTextBox.Text + Environment.NewLine + iterationCountTextBox.Text + Environment.NewLine + yMinCheckBox.Text + Environment.NewLine + yMaxCheckBox.Text + Environment.NewLine + xMinCheckBox.Text + Environment.NewLine + xMaxCheckBox.Text);
                writer.Close();
                writer.Dispose();
            } catch (Exception e2) {
                MessageBox.Show("Exception Trapped: " + e2.Message, "Error");
                statusLabel.Text = "Status: Error";
            }
        }