2016-10-25 2 views
0

Ich muss mit Julias Set Visualisierung beschäftigen. Ich habe nichts gefunden, das meinem Code mehr oder weniger ähnlich ist, also kann ich dieses Problem nicht lösen. Ich fand Tutorial, aber sein in russint, wenn jemand kann es hier lesen ist der Link:Julias setzen Visualisierung

https://habrahabr.ru/post/206516/#comment_7114136

Hier ist mein Code:

public class JuliaSet 
{ 

    ModelCanvas canvas; 

    public JuliaSet(ModelCanvas canvas, Complex c, int w, int h, int maxIter, 
    double xMin = Double.NaN, double yMin = Double.NaN, double xMax = Double.NaN, double yMax = Double.NaN) 
    { 
     this.canvas = canvas; 

     double r = CalculateR(c); 
     if (Double.IsNaN(xMin) || Double.IsNaN(xMax) || Double.IsNaN(yMin) || Double.IsNaN(yMax)) 
     { 
      xMin = -r; 
      yMin = -r; 
      xMax = r; 
      yMax = r; 
     } 
     //Logger.Instance.Log("R = " + r); 
     double xStep = Math.Abs(xMax - xMin)/w; 
     double yStep = Math.Abs(yMax - yMin)/h; 
     //XBitmap bmp = new XBitmap(w, h); 

     IDictionary<int, IDictionary<int, int>> xyIdx = new Dictionary<int, IDictionary<int, int>>(); 
     int maxIdx = 0; 
     for (int i = 0; i < w; i++) 
     { 
      xyIdx.Add(i, new Dictionary<int, int>()); 
      for (int j = 0; j < h; j++) 
      { 
       double x = xMin + i * xStep; 
       double y = yMin + j * yStep; 
       Complex z = new Complex(x, y); 
       IList<Complex> zIter = SqPolyIteration(z, c, maxIter, r); 
       int idx = zIter.Count - 1; 
       if (maxIdx < idx) 
       { 
        maxIdx = idx; // maxIdx = 1 
       } 
       xyIdx[i].Add(j, idx); 
      } 
     } 
     for (int i = 0; i < w; i++) 
     { 
      for (int j = 0; j < h; j++) 
      { 
       int idx = xyIdx[i][j]; 
       double x = xMin + i * xStep; 
       double y = yMin + j * yStep; 
       Complex z = new Complex(x, y); 
       //bmp.SetPixel(w - i - 1, j, ComplexHeatMap(idx, 0, maxIdx, z, r)); 
       this.canvas.SetPixel(w - i - 1, j, ComplexHeatMap(idx, 0, maxIdx, z, r)); 

      } 
     } 
     // return bmp; 
    } 

    public byte[] ComplexHeatMap(decimal value, decimal min, decimal max, Complex z, double r) 
    { 
     byte[] color = new byte[4]; 
     decimal val = (value - min)/(max - min); 
     color[3] = Convert.ToByte(255 * (Complex.abs(z)/r > 1 ? 1 : Complex.abs(z)/r)); 
     color[2] = Convert.ToByte(255 * (1 - val)); 
     color[1] = Convert.ToByte(255 * val); 
     color[0] = 255; 

     return color; 
    } 
    private static IList<Complex> SqPolyIteration(Complex z0, Complex c, int n, double r = 0) 
    { 
     IList<Complex> res = new List<Complex>(); 
     res.Add(z0); 
     for (int i = 0; i < n; i++) 
     { 
      if (r > 0) 
      { 
       if (Complex.abs(res.Last()) > r) 
       { 
        break; 
       } 
      } 
      res.Add((res.Last() * res.Last()) + c); 
     } 
     return res; 
    } 
    private double CalculateR(Complex c) 
    { 
     return (1+Math.Sqrt(1+4*Complex.abs(c)))/2; 
    } 
} 

alles aus dem Tutorial kopiert wird, aber alles Ich bekomme einen Kreis, der seine Farbe langsam näher an der Mitte ändert. So erhalten alle Pixel den gleichen Farbwert und alle Pixel werden gesetzt. Kann jeder hier einen Fehler finden, ich weiß, dass dies zu einer bestimmten Frage ist, aber ich kann es nicht alleine lösen.

Neben hier ist der Code für das Zeichnen

public class ModelCanvas 
{ 
    public int width; 
    public int height; 
    private byte[, ,] pixels; 
    private byte[] currentColor = { 0, 0, 0, 255 }; 


    public ModelCanvas(int width, int height) 
    { 
     this.height = height; 
     this.width = width; 

     pixels = new byte[width, height, 4]; 
     Array.Clear(pixels, 0, pixels.Length); 
    } 

    public void SetCurrentColor(byte r, byte g, byte b, byte alpha) 
    { 
     currentColor[0] = b; 
     currentColor[1] = g; 
     currentColor[2] = r; 
     currentColor[3] = alpha; 
    } 


    public void SetPixel(int x, int y) 
    { 
     SetPixel(x, y, currentColor); 
    } 

    public void SetPixel(int x, int y, byte[] colorData) 
    { 
     for (int i=0; i<4; i++) 
     { 
      pixels[x, y, i] = colorData[i]; 
     } 
    } 

    public WriteableBitmap GetWriteableBitmap() 
    { 
     int imageHeight = pixels.GetLength(1); 
     int imageWidth = pixels.GetLength(0); 

     WriteableBitmap wbitmap = new WriteableBitmap(imageWidth, imageHeight, 96, 96, PixelFormats.Bgra32, null); 

     byte[] pixels1d = new byte[imageWidth * imageHeight * 4]; 
     int index = 0; 
     for (int row = 0; row < imageHeight; row++) 
     { 
      for (int col = 0; col < imageWidth; col++) 
      { 
       for (int i = 0; i < 4; i++) 
        pixels1d[index++] = pixels[col, row, i]; 
      } 
     } 

     Int32Rect rect = new Int32Rect(0, 0, imageWidth, imageHeight); 
     int stride = 4 * imageWidth; 
     wbitmap.WritePixels(rect, pixels1d, stride, 0); 

     return wbitmap; 

    } 

} 
+0

Haben Sie versucht, den Wert von c zu ändern? Es gibt viele verschiedene Formen, die das Julia-Set annehmen kann, die vom Wert von c abhängen. Mit c = 0 ist das Julia-Set der Einheitskreis. Sehen Sie sich die Beispiele in https://en.wikipedia.org/wiki/Julia_set an, die die erwartete Form des Julia-Satzes für verschiedene c ergeben. –

+0

c wird aus 2 Eingabefeldern für den Realteil und für den Imaginärteil gesetzt. Habe viele Kombinationen ausprobiert. – GeekyNuns

+0

Zur Referenz: Sie können einige Glsl-Implementierungen auf [shadertoy] (https://www.shadertoy.com/) finden. – mlkn

Antwort

1

Nun, ich übersetzt habe den Code zu Java und es funktioniert einwandfrei (Pixel/Farben einstellen).

Alles, was ich tat, war verschiedene Methoden in ihre Java-Äquivalente zu konvertieren.

package toys; 

import java.awt.Graphics; 
import java.awt.image.BufferedImage; 
import java.util.ArrayDeque; 
import java.util.Deque; 
import java.util.HashMap; 
import java.util.Map; 

import javax.swing.JApplet; 

public class Julia extends JApplet { 
    private static final long serialVersionUID = 1L; 

    private BufferedImage image; 

    static class Complex { 
     double x,y; 

     public Complex(double x, double y) { 
      super(); 
      this.x = x; 
      this.y = y; 
     } 

     public static double abs(Complex last) { 
      return Math.hypot(last.x, last.y); 
     } 

     public Complex mul(Complex last) { 
      double z = x * last.x - y * last.y; 
      double w = x * last.y + y * last.x; 
      return new Complex(z,w); 
     } 

     public Complex add(Complex last) { 
      double z = x + last.x; 
      double w = y + last.y; 
      return new Complex(z,w); 
     } 

    } 
    public void JuliaSet(BufferedImage canvas, Complex c, int w, int h, int maxIter) { 
     double xMin = Double.NaN; 
     double yMin = Double.NaN; 
     double xMax = Double.NaN; 
     double yMax = Double.NaN; 

     double r = CalculateR(c); 
     if (Double.isNaN(xMin) || Double.isNaN(xMax) || Double.isNaN(yMin) || Double.isNaN(yMax)) 
     { 
      xMin = -r; 
      yMin = -r; 
      xMax = r; 
      yMax = r; 
     } 
     //Logger.Instance.Log("R = " + r); 
     double xStep = Math.abs(xMax - xMin)/w; 
     double yStep = Math.abs(yMax - yMin)/h; 
     //XBitmap bmp = new XBitmap(w, h); 


     Map<Integer, Map<Integer, Integer>> xyIdx = new HashMap<>(); 
     int maxIdx = 0; 
     for (int i = 0; i < w; i++) 
     { 
      xyIdx.put(i, new HashMap<>()); 
      for (int j = 0; j < h; j++) 
      { 
       double x = xMin + i * xStep; 
       double y = yMin + j * yStep; 
       Complex z = new Complex(x, y); 
       Deque<Complex> zIter = SqPolyIteration(z, c, maxIter, r); 
       int idx = zIter.size() - 1; 
       if (maxIdx < idx) 
       { 
        maxIdx = idx; // maxIdx = 1 
       } 
       xyIdx.get(i).put(j, idx); 
      } 
     } 
     for (int i = 0; i < w; i++) 
     { 
      for (int j = 0; j < h; j++) 
      { 
       int idx = xyIdx.get(i).get(j); 
       double x = xMin + i * xStep; 
       double y = yMin + j * yStep; 
       Complex z = new Complex(x, y); 
       //bmp.SetPixel(w - i - 1, j, ComplexHeatMap(idx, 0, maxIdx, z, r)); 
       canvas.setRGB(w - i - 1, j, ComplexHeatMap(idx, 0, maxIdx, z, r)); 


      } 
     } 
     // return bmp; 
    } 

    public int ComplexHeatMap(double value, double min, double max, Complex z, double r) 
    { 
     double val = (value - min)/(max - min); 
     byte red = (byte) (255 * (Complex.abs(z)/r > 1 ? 1 : Complex.abs(z)/r)); 
     byte g = (byte) (255 * (1 - val)); 
     byte b = (byte) (255 * val); 
     byte a = (byte) 255; 

     int color = (red<<16) + (g <<8) + (b) + (a << 24); 
     return color; 
    } 

    private static Deque<Complex> SqPolyIteration(Complex z0, Complex c, int n, double r) 
    { 
     Deque<Complex> res = new ArrayDeque<>(); 
     res.add(z0); 
     for (int i = 0; i < n; i++) 
     { 
      if (r > 0) 
      { 
       if (Complex.abs(res.getLast()) > r) 
       { 
        break; 
       } 
      } 
      res.add(res.getLast().mul(res.getLast()).add(c)); 
     } 
     return res; 
    } 
    private double CalculateR(Complex c) 
    { 
     return (1+Math.sqrt(1+4*Complex.abs(c)))/2; 
    } 

    int h,w; 
    @Override 
    public void paint(Graphics g) { 
     g.drawImage(image, 0, 0, null); 
    } 

    @Override 
    public void init() { 
     try { 
      h = 400; 
      w = 400; 
      image = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB); 
      this.JuliaSet(image, new Complex(0.285,0.), w, h, 20); 
//   System.arraycopy(source, 0, dest, 0, w*h); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 


    } 
} 

Und hier ist der Ausgang, der richtig aussieht.

enter image description here

Also ich bin nicht sicher, was es falsch mit Ihrem C# -Version. Es könnte in der Implementierung des Complex-Typs sein.

+1

Ich hatte den dümmsten Fehler aller Zeiten, es war in meiner komplexen Klasse, also habe ich keine richtigen komplexen Zahlen bekommen. – GeekyNuns