Ich kann auf das Mandelbrot-Set zoomen, solange sich die Maus nicht bewegt, nachdem das Zoomen begonnen hat. Ich habe versucht, ein normalisiertes Delta (neue Koordinate - alte Koordinate) * (oldzoom) zu berechnen, aber was passiert, ist, dass das Bild an einen neuen Ort springt. Ich habe dieses Problem schon einmal gesehen. Ich kämpfe hier mehr, weil ich das Delta der Mausposition irgendwie in den -2,2-Koordinatenraum des Mandelbrot-Sets umwandeln muss.Punkt-Zoom auf Mandelbrot-Set in C# - Es funktioniert, außer wenn die Maus bewegt wurde
Hier ist mein Code. Wichtig ist die GetZoomPoint-Methode und dann die Codezeilen, die x0 und y0 definieren. Außerdem verwende ich die Range-Klasse, um Werte von einem Bereich zum anderen zu skalieren. I WAS mit deltaTrans (das ist die Sache, über die ich früher gesprochen habe, wo ich das Maus-Delta mit der alten Skala normalisiere).
using OpenTK.Graphics.OpenGL;
using SpriteSheetMaker;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Fractal.Fractal
{
public class Mandelbrot : BaseTexture
{
private static Transform GlobalTransform = SpriteSheetMaker.Global.Transform;
private static Vector3 GlobalScale = GlobalTransform.Scale;
private static Vector3 GlobalTrans = GlobalTransform.Translation;
private static Vector3 LastWindowPoint = null;
private static Vector3 ZoomFactor = Vector3.ONE * 1.2f;
private static Vector3 Displacement = Vector3.ZERO;
private static int WindowSize = 100;
public static Vector3 GetZoomPoint()
{
var zP = OpenGLHelpers.LastZoomPoint.Clone();
if (LastWindowPoint == null)
{
LastWindowPoint = zP.Clone();
}
var delta = zP - LastWindowPoint;
var oldZoom = GlobalScale/ZoomFactor;
var deltaTrans = delta.XY * oldZoom.XY;
var factor = ZoomFactor.Clone();
Range xR = new Range(0, WindowSize);
Range yR = new Range(0, WindowSize);
Range complexRange = new Range(-2, 2);
// Calculate displacement of zooming position.
var dx = (zP.X - Displacement.X) * (factor.X - 1f);
var dy = (zP.Y - Displacement.Y) * (factor.Y - 1f);
// Compensate for displacement.
Displacement.X -= dx;
Displacement.Y -= dy;
zP -= Displacement;
var x = complexRange.ScaleValue(zP.X, xR);
var y = complexRange.ScaleValue(zP.Y, yR);
var rtn = new Vector3(x, y);
LastWindowPoint = zP.Clone();
return rtn;
}
public static Mandelbrot Generate()
{
var size = new Size(WindowSize, WindowSize);
var radius = new Size(size.Width/2, size.Height/2);
Bitmap bmp = new Bitmap(size.Width, size.Height);
LockBitmap.LockBitmapUnsafe lbm = new LockBitmap.LockBitmapUnsafe(bmp);
lbm.LockBits();
var pt = Mandelbrot.GetZoomPoint();
Parallel.For(0, size.Width, i =>
{
// float x0 = complexRangeX.ScaleValue(i, xRange);
float x0 = ((i - radius.Width)/GlobalScale.X) + pt.X;
Parallel.For(0, size.Height, j =>
{
// float y0 = complexRangeY.ScaleValue(j, yRange);
float y0 = ((j - radius.Height)/GlobalScale.Y) + pt.Y;
float value = 0f;
float x = 0.0f;
float y = 0.0f;
int iteration = 0;
int max_iteration = 100;
while (x * x + y * y <= 4.0 && iteration < max_iteration)
{
float xtemp = x * x - y * y + x0;
y = 2.0f * x * y + y0;
x = xtemp;
iteration += 1;
if (iteration == max_iteration)
{
value = 255;
break;
}
else
{
value = iteration * 50f % 255f;
}
}
int v = (int)value;
lbm.SetPixel(i, j, new ColorLibrary.HSL(v/255f, 1.0, 0.5).ToDotNetColor());
});
});
lbm.UnlockBits();
var tex = new BaseTextureImage(bmp);
var rtn = new Mandelbrot(tex);
return rtn;
}
public override void Draw()
{
base._draw();
}
private Mandelbrot(BaseTextureImage graphic)
{
var topLeft = new Vector3(0, 1);
var bottomLeft = new Vector3(0, 0);
var bottomRight = new Vector3(1, 0);
var topRight = new Vector3(1, 1);
this.Vertices = new List<Vector3>()
{
topLeft,bottomLeft,bottomRight,topRight
};
this.Size.X = WindowSize;
this.Size.Y = WindowSize;
this.Texture2D = graphic;
}
}
}
Was ist 'GetZoomPoint'? Googeln zeigt diese Frage an der Spitze. –
HAHA, ok ja, ich habe das ziemlich schlecht geplant. Das mache ich manchmal, um die Entwicklung kurzfristig zu beschleunigen. Um dies zu vereinfachen, gibt es globale Transformationen (Skalieren, Übersetzen usw.), auf die diese zugreifen können. Außerhalb dieser Klasse werden der globale Maßstab und die Übersetzung über das Mausrad aktualisiert. GetZoomPoint versucht, die globale Skalierung und die Übersetzung zu verwenden, um herauszufinden, wo im Mandelbrot-Set der Fokus gesetzt werden sollte. Die generierte Bitmap wird im Wesentlichen als GPU-Textur behandelt, aber da ich die Basis Draw überschreibe, gelten die Transformationen nicht. Ist das klar, was GetZoomPoint macht? – applejacks01
Vielleicht eine bessere Frage, die ich stellen könnte, ist, angesichts einer gewünschten Fenstergröße, einer Mauskoordinate (die sich jederzeit bewegen kann) und eines gewünschten Maßstabs, wie kann ich in die Mandelbrotmenge (oder irgendeinen beliebigen zweidimensionalen Begrenzungsraum) hineinzoomen – applejacks01