C语言绘制希尔伯特曲线
希尔伯特曲线是一种空间填充曲线,可以通过递归的方式绘制,下面是一个用C语言实现绘制希尔伯特曲线的完整程序,使用SDL库进行图形显示。
完整代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <SDL2/SDL.h>
// 定义窗口大小
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 800
// 递归绘制希尔伯特曲线
void hilbert(SDL_Renderer *renderer, int x, int y, int xi, int xj, int yi, int yj, int n) {
if (n <= 0) {
// 绘制当前线段
SDL_RenderDrawLine(renderer, x, y, x + (xi + yi) / 2, y + (xj + yj) / 2);
return;
}
// 递归绘制四个子曲线
hilbert(renderer, x, y, yi / 2, yj / 2, xi / 2, xj / 2, n - 1);
hilbert(renderer, x + (xi + yi) / 2, y + (xj + yj) / 2, xi / 2, xj / 2, yi / 2, yj / 2, n - 1);
hilbert(renderer, x + (xi + yi) / 2 + (xi - yi) / 2, y + (xj + yj) / 2 + (xj - yj) / 2,
xi / 2, xj / 2, yi / 2, yj / 2, n - 1);
hilbert(renderer, x + (xi - yi) / 2, y + (xj - yj) / 2, -yi / 2, -yj / 2, -xi / 2, -xj / 2, n - 1);
}
int main(int argc, char *argv[]) {
// 初始化SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL初始化失败: %s\n", SDL_GetError());
return 1;
}
// 创建窗口
SDL_Window *window = SDL_CreateWindow("希尔伯特曲线",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WINDOW_WIDTH,
WINDOW_HEIGHT,
SDL_WINDOW_SHOWN);
if (window == NULL) {
fprintf(stderr, "窗口创建失败: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
// 创建渲染器
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
fprintf(stderr, "渲染器创建失败: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
// 设置绘制颜色
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // 白色背景
SDL_RenderClear(renderer);
// 设置曲线颜色
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // 蓝色曲线
// 绘制希尔伯特曲线
int order = 5; // 递归深度,值越大曲线越复杂
int size = WINDOW_WIDTH * 0.8; // 曲线大小
int margin = (WINDOW_WIDTH - size) / 2;
hilbert(renderer, margin, margin, size, 0, 0, size, order);
// 更新屏幕
SDL_RenderPresent(renderer);
// 等待用户关闭窗口
SDL_Event event;
int quit = 0;
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = 1;
}
}
SDL_Delay(100);
}
// 清理资源
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
代码说明
-
希尔伯特曲线递归函数
hilbert():- 参数解释:
(x, y): 当前线段的起点坐标(xi, xj): 方向向量x分量(yi, yj): 方向向量y分量n: 递归深度
- 参数解释:
-
主函数
main():- 初始化SDL库和创建窗口、渲染器
- 设置绘制颜色和背景
- 调用
hilbert()函数绘制曲线 - 等待用户关闭窗口
编译和运行
- 确保已安装SDL2库(在Linux上可以使用
sudo apt-get install libsdl2-dev) - 编译命令:
gcc hilbert_curve.c -o hilbert_curve -lSDL2
- 运行:
./hilbert_curve
效果
程序会显示一个窗口,其中绘制了蓝色的希尔伯特曲线,你可以通过修改order变量来改变曲线的递归深度(值越大曲线越复杂)。
其他实现方式
如果不使用SDL,也可以使用其他图形库如OpenGL或简单的控制台字符绘制,下面是一个简单的控制台版本:
#include <stdio.h>
void hilbert(int x, int y, int xi, int xj, int yi, int yj, int n) {
if (n <= 0) {
printf("(%d,%d) ", x + (xi + yi) / 2, y + (xj + yj) / 2);
return;
}
hilbert(x, y, yi/2, yj/2, xi/2, xj/2, n-1);
hilbert(x + (xi+yi)/2, y + (xj+yj)/2, xi/2, xj/2, yi/2, yj/2, n-1);
hilbert(x + (xi+yi)/2 + (xi-yi)/2, y + (xj+yj)/2 + (xj-yj)/2, xi/2, xj/2, yi/2, yj/2, n-1);
hilbert(x + (xi-yi)/2, y + (xj-yj)/2, -yi/2, -yj/2, -xi/2, -xj/2, n-1);
}
int main() {
printf("希尔伯特曲线坐标:\n");
hilbert(0, 0, 256, 0, 0, 256, 3);
printf("\n");
return 0;
}
这个版本会在控制台输出曲线的坐标点。
