当前位置: 首页 > 知识库问答 >
问题:

在C#中设置Mandelbrot上的点缩放-它可以工作,除非鼠标移动

司寇瑾瑜
2023-03-14

只要缩放开始后鼠标不移动,我就可以在Mandelbrot集合上指向缩放。我尝试过计算一个标准化的delta(新坐标-旧坐标)*(oldzoom),但结果是图像似乎跳转到一个新位置。我以前见过这个问题。我在这里更加挣扎,因为我必须以某种方式将鼠标位置的增量转换回Mandelbrot集合的-2,2坐标空间。

这是我的密码。重要的是GetZoomPoint方法,然后是定义x0和y0的代码行。此外,我还使用Range类将值从一个范围缩放到另一个范围。我使用的是deltaTrans(这就是我之前提到的,我用旧的刻度标准化鼠标的delta)。

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;
        }
    }
}

共有1个答案

别俊誉
2023-03-14

我重构了我的代码,也想出了解决这个问题的办法。好的,所以我找到了一个用C#编写的CodeProject解决方案,我很容易适应我的项目。我不知道为什么我在发布这个问题时没有意识到这一点,但是我需要解决这个问题的是创建一个缩放的“窗口”,而不是用“点缩放”来思考。是的,即使我试图直接放大到一个点,那个点只是某种窗口的中心。

这里是我的方法,它需要开始和结束鼠标向下坐标(屏幕空间),并相应地转换mandelbrot设置窗口大小。

    public void ApplyZoom(double x0, double y0, double x1, double y1)
    {
        if (x1 == x0 && y0 == y1)
        {
            //This was just a click, no movement occurred
            return;
        }

        /*
            * XMin, YMin and XMax, YMax are the current extent of the set
            * mx0,my0 and mx1,my1 are the part we html" target="_blank">selected
            * do the math to draw the selected rectangle
            * */
        double scaleX, scaleY;

        scaleX = (XMax - XMin) / (float)BitmapSize;
        scaleY = (YMax - YMin) / (float)BitmapSize;
        XMax = (float)x1 * scaleX + XMin;
        YMax = (float)y1 * scaleY + YMin;
        XMin = (float)x0 * scaleX + XMin;
        YMin = (float)y0 * scaleY + YMin;

        this.Refresh(); // force mandelbrot to redraw

    }

基本上,我们计算的是mandelbrot窗口大小与我们绘制的屏幕大小之间的比率。然后,使用该比例,我们基本上将鼠标向下坐标转换为mandelbrot集合坐标(x1*scaleX等),并使用它们操纵当前的最小和最大坐标,使用最小值作为轴心点。

下面是我用作参考的CodeProject的链接:CodeProject链接

 类似资料:
  • 在过去的几天里,我一直在开发C Mandelbrot集合程序,我设法让它工作得很好,然而,我的最终目标是能够用我的鼠标平稳地放大集合,这是我还没有做到的,所以我可能需要一些帮助! 这是我的部分代码(嗯,完整的mandelbrot函数): 这是输出的图片:(抱歉,它不是很漂亮,颜色不是我的首要任务,但我一定会尽快处理它们,只要我弄清楚变焦!) 曼德布罗特 我希望能够做到的是: 左键单击- (已经有一

  • 我有一个自定义图表,我使用以下代码缩放它: 我注意到当我用鼠标滚轮滚动图表时,我不能缩放鼠标指向的图表。相反,图表会向左或向右缩放。

  • 我在Java中编码了一个Mandelbrot集分形,并包含了平移和放大分形的能力。唯一的问题是,当我平移图像并试图放大时,它看起来好像试图放大中心并平移一点。平移和缩放不是真正的平移或缩放,而是对分形的重新计算,看起来像是平移或缩放。 这是我的代码。 我能告诉用户在哪里可以让相机更精确地缩放吗? 先谢谢你。 编辑:图片对于任何想知道这个程序将呈现什么。

  • 我有一个特别的问题。用例是在搜索元素后转到搜索结果。但是,单击搜索按钮后,鼠标指针会无限旋转,直到有人移动鼠标指针。问题是,即使我应用了偏移移动,鼠标指针仍处于旋转位置。整个页面嵌套在一个框架中。移动偏移在以前的方法中是有效的,但不是为了这个,我附加了屏幕截图和代码,在屏幕截图中无法捕获鼠标指针 截图

  • 我有一套mandelbrot电视机,我想放大。“缩放曼德拉”和“缩放曼德拉”是围绕曼德拉坐标计算的。原始的mandelbrot以real=-0.6和im=0.4为中心,real和im的大小均为2。 我希望能够点击图像中的一个点,并计算一个新的点,放大该点 包含它的窗口是800x800px,所以我想这将使右下角的单击等于真实=0.4和im=-0.6的中心,左上角的单击为真实=-1.6和im=1.4

  • 我一直在做曼德尔布洛特集,并试图缩放,但缩放模式变得非常麻烦。当我缩放它完美地缩放,但图像大小减少到原来的一半。下次我再次缩放时,图片大小会增加,并试图跳过查看窗口。代码是c /opengl.在这里发布之前,我试图让我的代码变得干净一点。 执行时