2017-06-21 51 views
-1

我想找出一種方法放大我的Mandelbrot設置點擊。我有它,所以當我點擊它稍微放大,但它不會相應地移動Mandelbrot。放大Mandelbrot

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的寬度和高度,但是我想擁有它,所以它放大了我點擊的位置。 如何根據點擊的位置縮放圖片框?

+1

你需要找回並與mouseposition工作。這個答案有解決方案,甚至準備一個圖片框https://stackoverflow.com/questions/7055211/how-to-get-the-position-of-a-click –

+0

忘掉圖片框,專注於數據! - 哦,我以前告訴過你,你忽略了它。那麼,祝你好運.. – TaW

+0

@ Taw:_「我已經告訴過你,在......之前 - 在什麼情況下?您提供該信息時是否存在刪除的問題?這有助於瞭解已經提供給OP的建議,更好地理解他們可能已經聽到的內容以及他們可能難以理解的內容。 –

回答

2

這將有助於瞭解已經提供給您的指導。我從this comment推斷,可能存在您詢問並刪除的現有問題,其中討論了此問題。如果不知道已經提供了哪些幫助,哪些是你無法理解的,就很難知道如何最好地提出新的答案。

這就是說,還有你必須解決,以實現你要找的行爲兩個基本問題:

  1. 識別點擊鼠標時的位置。目前,您正在使用Click事件,該事件僅向您的代碼報告控件已被點擊,而不是,其中被點擊。
  2. 修復您的渲染代碼以適應應該繪製的邊界的變化。目前,你總是在你的位圖繪製的像素範圍的範圍集中在(-0.72,0),從該中心僅調整多遠呈現複平面(即zoom變量。

爲了解決#1,您需要訂閱MouseClick事件,這會將MouseEventArgs對象傳遞給您的處理程序,該處理程序具有Location屬性,該屬性表示控件客戶區中實際單擊的點(即,所報告的座標相對於原點位於控件的左上角)

要解決#2問題,您需要向班級添加一些變量以跟蹤您的相對位置想畫畫。有很多方法可以做到這一點,但保留當前的表示當前「縮放」因子作爲渲染區域的寬度和高度的約定,似乎有意義的是跟蹤正在渲染的空間的中心,即按照繪製的複雜平面上的位置點擊鼠標的位置。

我強烈反對程序在執行長時間運行的任務時鎖定用戶界面。因此,在修改代碼示例的過程中,我對其進行了修改,以便在工作線程中呈現圖像,並通過在我添加到表單上的Label提供狀態消息來報告呈現進度。 (這涉及到讓你Mandelbrot()方法的async方法&hellip;我繼續調用它來抑制編譯器警告時使用await,當然,在這方面沒有嚴格要求的await S)

有一件事我沒有的確是爲代碼添加進一步的優化。這些往往會混淆與你的問題直接相關的變化。通過去除冗餘計算或使用數學關係執行比Mandelbrot算法的字面翻譯更便宜的計算,您可以對代碼執行許多操作來幫助提高性能。

互聯網上有很多關於如何渲染Mandelbrot圖像的東西,所以你可以環顧四周,找到那種建議,一旦你的基本想法奏效。此外,目前,每個像素只有255次迭代和相對較小的位圖,性能並不是一個嚴肅的考慮因素。

這裏是你的代碼的版本,我想出了:

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(); 
    } 
} 
+0

你能解釋一下這行代碼在做什麼? IProgress progress = new進度(x => label1.Text = $(「{x * 100:0}%done」); –

+0

這會創建一個'Progress '的實例,在此處使用'double'的泛型類在UI線程中創建時,會自動執行在該UI線程上傳遞給它的處理程序,這種情況下的處理程序是lambda表達式,它接收狀態值「x」並將其格式化以通過分配顯示在屏幕上將格式化的字符串傳遞給'label1.Text'。通過將這個完整的'Progress '實例(鍵入爲'IProgress ',進度報告界面'Progress '實現)傳遞給可以工作的方法,它可以報告進度因爲它去了。 –