如何修正递归C代码以正确绘制蟹曲线(Crab Curve)?
蟹曲线递归生成函数的问题修复
问题分析
你的递归函数在m>1时无法生成预期蟹曲线,核心错误在于没有考虑原线段的方向,直接使用全局角度计算中间控制点,导致递归后的线段方向完全偏离蟹曲线的等腰折线规则。此外,中间点的位置计算逻辑错误,不是从线段起点沿固定角度延伸,而是需要从线段中点向垂直方向偏移。
修复后的代码
#include <math.h> /* x1: 起点x坐标 y1: 起点y坐标 x2: 终点x坐标 y2: 终点y坐标 m: 递归步数 */ void crab_curve(double x1, double y1, double x2, double y2, int m) { if (m == 0) // 递归终止,绘制基础直线 { draw_line(x1, y1, x2, y2, 1, 0, 0, 0); return; } // 计算原线段的向量与长度 double dx = x2 - x1; double dy = y2 - y1; double l = sqrt(dx * dx + dy * dy); if (l < 1e-6) { // 避免线段过短导致计算异常 draw_line(x1, y1, x2, y2, 1, 0, 0, 0); return; } // 计算原线段的单位向量,以及垂直于线段的单位向量(控制折线偏移方向) double ux = dx / l; double uy = dy / l; double vx = -uy; // 顺时针垂直方向,若需逆时针偏移可改为 uy double vy = ux; // 计算当前递归深度对应的折角 // 原代码逻辑:折角随m增大而增大(m*π/4),若需标准蟹曲线可改为 angle = M_PI/2.0 / (1 << m) double angle = m * 0.25 * M_PI; double half_length = l / 2.0; double offset_height = half_length * tan(angle); // 等腰折线的偏移高度 // 计算中间控制点坐标:线段中点 + 垂直方向偏移 double mid_x = (x1 + x2) / 2.0; double mid_y = (y1 + y2) / 2.0; double ctrl_x = mid_x + offset_height * vx; double ctrl_y = mid_y + offset_height * vy; // 递归绘制两段折线 crab_curve(x1, y1, ctrl_x, ctrl_y, m - 1); crab_curve(ctrl_x, ctrl_y, x2, y2, m - 1); }
关键修改说明
- 线段方向适配:通过计算原线段的单位向量和垂直向量,确保折线偏移方向始终与当前线段垂直,而非固定全局角度。
- 控制点位置修正:从线段中点出发计算偏移,符合蟹曲线“将线段替换为等腰折线”的生成规则。
- 边界处理:增加了线段长度过小的判断,避免递归到深层时出现除以零或数值溢出问题。
- 折角可调整:保留原代码的折角逻辑,若需要标准蟹曲线效果,可将折角计算改为
angle = M_PI/2.0 / (1 << m)(每递归一步折角减半)。
内容的提问来源于stack exchange,提问作者aheuchamps
相关产品推荐
相关产品推荐

