首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >放大Mandelbrot

放大Mandelbrot
EN

Stack Overflow用户
提问于 2017-06-21 14:06:09
回答 1查看 2.4K关注 0票数 0

我正试图找出一种方法来放大我的Mandelbrot设置点击。我有它,所以当我点击它时,会稍微放大,但它不会相应地移动Mandelbrot。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Numerics;

namespace Project_V2
{
    public partial class FractalGen : Form
    {
        public double zoom = 2.4;
        public FractalGen()
        {
            InitializeComponent();
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            zoom -= 0.3;
            Mandelbrot();
        }

        private void button1_Click(object sender, EventArgs e)
        {
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Mandelbrot();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {

        }

        private void Mandelbrot()
        {
            Bitmap bm = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            DateTime StartT = DateTime.Now;
            for (int x = 0; x < pictureBox1.Width; x++)
            {
                for (int y = 0; y < pictureBox1.Height; y++)
                {
                    double a = (double)(x - (pictureBox1.Width / 1.25)) / (double)(pictureBox1.Width / zoom);
                    double b = (double)(y - (pictureBox1.Height / 2)) / (double)(pictureBox1.Height / zoom);
                    Complex C = new Complex(a, b);
                    Complex Z = new Complex(0, 0);
                    int u = 0;
                    do
                    {
                        u++;
                        Z = Z * Z;
                        Z = Z + C;
                        double Mag = Complex.Abs(Z);
                        if (Mag > 2.0) break;
                    } while (u < 255);
                    Color rgbInside = Color.FromArgb(0, 0, 0);
                    Color rgbOutside = Color.FromArgb(u >= 127 ? 255 : 2 * u, u >= 127 ? (u - 127) : 0, 0);
                    bm.SetPixel(x, y, u < 255 ? rgbOutside : rgbInside);
                }
            }
            pictureBox1.Image = bm;
            DateTime EndT = DateTime.Now;
            string Time = Convert.ToString((EndT - StartT).TotalSeconds);
            textBox1.Text = "Time Taken: " + Time + " Seconds";
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            zoom = 2.4;
            Mandelbrot();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            string name = saveFileDialog1.FileName;
            pictureBox1.Image.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Png);
        }
    }
}

当前代码将picturebox的宽度和高度除以一个值,但我希望它能够放大我单击的位置。如何缩放图片框相对于我点击的位置?

EN

回答 1

Stack Overflow用户

发布于 2017-06-22 00:06:01

了解已经提供给你的指导是有帮助的。我从this comment中推断,您可能已经提出了一个问题,然后将其删除,其中讨论了这个问题。如果不知道已经提供了什么帮助,以及具体是什么你无法理解,很难知道如何最好地提出一个新的答案。

也就是说,要实现你想要的行为,你必须解决两个基本问题:

  1. 确定鼠标被单击的位置。当前,您使用的是Click事件,该事件只向您的代码报告控件已被单击,而不是单击该控件的位置。
  2. 修正您的呈现代码以适应应该绘制的边界的更改。目前,您总是将位图中的像素范围映射到以(-0.72,0)为中心的复杂平面上的范围,只调整显示的距离(即zoom变量)。

要处理#1,您需要订阅MouseClick事件。这将向处理程序传递一个MouseEventArgs对象,该处理程序具有一个Location属性,该属性指示控件的工作区内实际单击的点(即所报告的坐标相对于控件左上角的原点)。

要处理#2,需要向类中添加一些变量,以跟踪要绘制的相对位置。有很多方法可以做到这一点,但按照当前的惯例,将当前的“缩放”因子表示为呈现区域的宽度和高度,跟踪正在呈现的空间的中心似乎是有意义的,即鼠标被单击的位置,即绘制的复杂平面上的位置。

我强烈反对那些在执行长期运行的任务时锁定UI的程序。因此,在修改代码示例的过程中,我修改了它,使它能够在工作线程中呈现图像,并通过在我添加到表单的Label上提供状态消息来报告呈现进度。(这涉及到使Mandelbrot()方法成为async方法…。在调用await以抑制编译器警告时,我继续使用它,但是在这种情况下,严格地不需要await)。)

我没有做的一件事是在代码中添加进一步的优化。这些倾向于混淆与你的问题直接相关的变化。您可以对代码做一些事情,以帮助提高性能,消除多余的计算,或者使用数学关系来执行比Mandelbrot算法的直译成本更低的计算。

互联网上有很多关于如何渲染Mandelbrot图像的信息,所以一旦你有了基本的想法,你就可以环顾四周找出类似的建议。此外,目前每像素只有255次迭代和相对较小的位图,性能并不是一个重要的考虑因素。

下面是我想出的代码的版本:

代码语言:javascript
复制
public partial class Form1 : Form
{
    double zoom = 2.4;
    double centerX = -0.72, centerY = 0;

    public Form1()
    {
        InitializeComponent();
    }

    private async void pictureBox1_MouseClick(object sender, MouseEventArgs e)
    {
        double minX = centerX - zoom / 2, minY = centerY - zoom / 2;
        centerX = minX + (double)e.Location.X / pictureBox1.Width * zoom;
        centerY = minY + (double)e.Location.Y / pictureBox1.Height * zoom;
        zoom -= 0.3;
        await Mandelbrot();
    }

    private async void Form1_Load(object sender, EventArgs e)
    {
        await Mandelbrot();
    }

    private async Task Mandelbrot()
    {
        IProgress<double> progress = new Progress<double>(x => label1.Text = $"{x * 100:0}% done");

        DateTime StartT = DateTime.UtcNow;
        pictureBox1.Image = await Task.Run(() => _GenerateBitmap(progress));
        DateTime EndT = DateTime.UtcNow;
        string Time = Convert.ToString((EndT - StartT).TotalSeconds);
        textBox1.Text = "Time Taken: " + Time + " Seconds";
    }

    private Bitmap _GenerateBitmap(IProgress<double> progress)
    {
        Bitmap bm = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        double minX = centerX - zoom / 2, minY = centerY - zoom / 2;

        for (int x = 0; x < pictureBox1.Width; x++)
        {
            for (int y = 0; y < pictureBox1.Height; y++)
            {
                double a = minX + (double)x / pictureBox1.Width * zoom;
                double b = minY + (double)y / pictureBox1.Height * zoom;
                Complex C = new Complex(a, b);
                Complex Z = new Complex(0, 0);
                int u = 0;
                do
                {
                    u++;
                    Z = Z * Z;
                    Z = Z + C;
                    double Mag = Complex.Abs(Z);
                    if (Mag > 2.0) break;
                } while (u < 255);
                Color rgbInside = Color.FromArgb(0, 0, 0);
                Color rgbOutside = Color.FromArgb(u >= 127 ? 255 : 2 * u, u >= 127 ? (u - 127) : 0, 0);
                bm.SetPixel(x, y, u < 255 ? rgbOutside : rgbInside);
            }

            progress.Report((double)x / pictureBox1.Width);
        }

        return bm;
    }

    private async void button1_Click_1(object sender, EventArgs e)
    {
        zoom = 2.4;
        await Mandelbrot();
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44678435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档