You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现Mandelbrot集:平移与缩放功能问题求助

Mandelbrot集平移与缩放问题求助

我正在用C语言完成Mandelbrot集的学校项目,以下是我的相关代码:

核心计算函数

int mandelbrot(int x, int y, t_data *data)
{
    double complex  c;
    double complex  z;
    double          cx;
    double          cy;
    int             i;

    cx = map(x, 0, WIDTH, data->min, data->max);
    cy = map(y, 0, HEIGHT, data->min, data->max);
    c = cx + cy * I;
    z = 0;
    i = 0;
    while (i < data->max_iteration)
    {
        z = z * z + c;
        if (creal(z) * creal(z) + cimag(z) * cimag(z) > 4)
            break;
        i++;
    }
    
    return (get_color(i, *data));
}

坐标映射函数

我用map()函数将窗口坐标转换为复平面坐标,也用来获取光标在复平面的坐标:

double map(double value, double screen_min, double screen_max
                       , double image_min, double image_max)
{
    return ((value - screen_min ) \
            * (image_max - image_min) \
            / (screen_max - screen_min) \
            + image_min);
}

数据结构体

t_data结构体包含实现所需的变量:

typedef struct mouse
{
    double          cursor_cx; // 光标在复平面的x坐标
    double          cursor_cy; // 光标在复平面的y坐标
    double          min; // Mandelbrot集的边界最小值,初始为-2
    double          max; // 边界最大值,初始为2
    int             max_iteration; // 最大迭代次数,初始为100
    mlx_t           *mlx;  // 窗口指针
    mlx_image_t     *g_img; // 绘图用图像指针
}   t_data;

当前遇到的问题

1. 缩放问题

我通过修改min和max实现缩放,但多次缩放后图像会反转,继续操作甚至会反向缩放。原因是min从-2逐渐变到0,再继续会到2,max则相反。我需要实现基于光标位置的无限缩放,直到达到计算机精度极限,且不会出现图像反转的情况。

2. 平移问题

我尝试用按键控制平移,但当前代码无效,会导致图像沿对角线缩放,无法实现正常的上下左右平移:

void key_hook(void *param)
{
    t_data  *data;
    float   step;

    step = 0.1;
    data = param;
    if (mlx_is_key_down(data->mlx, MLX_KEY_ESCAPE))
        mlx_close_window(data->mlx);
    if (mlx_is_key_down(data->mlx, MLX_KEY_RIGHT))
        data->min -= step;
    if (mlx_is_key_down(data->mlx, MLX_KEY_LEFT))
        data->min += step;
    if (mlx_is_key_down(data->mlx, MLX_KEY_UP))
        data->max += step;
    if (mlx_is_key_down(data->mlx, MLX_KEY_DOWN))
        data->max -= step;
}

解决方案

针对缩放问题的修复

问题出在你用min和max同时控制x、y轴的边界,且缩放时直接修改这两个值导致边界交叉。正确的做法是分别维护x轴和y轴的边界,并基于光标位置计算缩放后的边界:

  1. 修改t_data结构体,分别存储x和y的边界:
typedef struct mouse
{
    double          cursor_cx;
    double          cursor_cy;
    double          x_min; // x轴最小值,初始-2
    double          x_max; // x轴最大值,初始2
    double          y_min; // y轴最小值,初始-2
    double          y_max; // y轴最大值,初始2
    int             max_iteration;
    mlx_t           *mlx;
    mlx_image_t     *g_img;
}   t_data;
  1. 调整mandelbrot函数中的坐标映射:
cx = map(x, 0, WIDTH, data->x_min, data->x_max);
cy = map(y, 0, HEIGHT, data->y_min, data->y_max);
  1. 实现基于光标位置的缩放函数(可绑定鼠标滚轮触发):
// zoom_factor < 1 是放大,>1 是缩小
void zoom(t_data *data, double zoom_factor)
{
    // 获取光标对应的复平面坐标
    double cursor_x = data->cursor_cx;
    double cursor_y = data->cursor_cy;

    // 以光标为中心缩放x轴边界
    double x_range = data->x_max - data->x_min;
    data->x_min = cursor_x - (cursor_x - data->x_min) * zoom_factor;
    data->x_max = cursor_x + (data->x_max - cursor_x) * zoom_factor;

    // 保持宽高比计算y轴边界,避免图像拉伸
    double y_range = x_range * ((double)HEIGHT / WIDTH);
    data->y_min = cursor_y - (y_range / 2);
    data->y_max = cursor_y + (y_range / 2);
}

这样缩放时始终以光标位置为中心,x、y轴边界不会交叉,能一直缩放直到精度极限。

针对平移问题的修复

当前平移代码错误地修改了min和max,导致同时改变x和y的边界引发缩放效果。正确做法是根据方向平移对应轴的边界,且平移步长与当前视图范围成正比:

void key_hook(void *param)
{
    t_data  *data;
    double   step;

    data = param;
    // 步长设为当前视图宽度的1/10,缩放后自动适配速度
    step = (data->x_max - data->x_min) * 0.1;

    if (mlx_is_key_down(data->mlx, MLX_KEY_ESCAPE))
        mlx_close_window(data->mlx);
    
    // 左右平移:同步修改x轴的两个边界
    if (mlx_is_key_down(data->mlx, MLX_KEY_RIGHT))
    {
        data->x_min += step;
        data->x_max += step;
    }
    if (mlx_is_key_down(data->mlx, MLX_KEY_LEFT))
    {
        data->x_min -= step;
        data->x_max -= step;
    }
    
    // 上下平移:同步修改y轴的两个边界
    if (mlx_is_key_down(data->mlx, MLX_KEY_UP))
    {
        data->y_min += step;
        data->y_max += step;
    }
    if (mlx_is_key_down(data->mlx, MLX_KEY_DOWN))
    {
        data->y_min -= step;
        data->y_max -= step;
    }
}

这里步长基于当前x轴范围计算,保证平移速度在任何缩放级别下一致,平移时同步修改对应轴的两个边界,确保视图整体移动。


内容的提问来源于stack exchange,提问作者Bradass_FaLLaG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:45:13