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

PHP如何使用GD库绘制二次贝塞尔曲线?

在GD库中模拟二次贝塞尔曲线的实现方案

一、直线分段近似(推荐,简单易实现)

二次贝塞尔曲线的核心数学公式为:
给定起点 $P_0(x_0,y_0)$、控制点 $P_1(x_1,y_1)$、终点 $P_2(x_2,y_2)$,曲线上任意点 $P(t)$ 的坐标计算方式是:

x(t) = (1-t)²*x0 + 2*t*(1-t)*x1 + t²*x2
y(t) = (1-t)²*y0 + 2*t*(1-t)*y1 + t²*y2

其中 $t$ 的取值范围是 $[0, 1]$。

我们可以将 $t$ 拆分成若干等间隔的小步长(比如0.01,即分100段),计算每个 $t$ 对应的坐标点,再用GD的imageline依次连接这些点,就能模拟出平滑的曲线。步长越小,曲线越接近真实的贝塞尔曲线。

对应GD库的实现代码

function draw_bezier_curve_gd($img, $color, $start_x, $start_y, $points) {
    // 分段精度:t的步长,值越小曲线越平滑
    $step = 0.01;
    $current_x = $start_x;
    $current_y = $start_y;

    foreach ($points as $point) {
        $p1_x = $point['x1'];
        $p1_y = $point['y1'];
        $end_x = $point['x'];
        $end_y = $point['y'];

        // 遍历t从step到1,计算每个点并连线
        for ($t = $step; $t <= 1.0; $t += $step) {
            $inv_t = 1 - $t;
            // 计算当前t对应的坐标
            $x = $inv_t * $inv_t * $current_x + 2 * $t * $inv_t * $p1_x + $t * $t * $end_x;
            $y = $inv_t * $inv_t * $current_y + 2 * $t * $inv_t * $p1_y + $t * $t * $end_y;

            // 绘制线段连接上一个点与当前点
            imageline($img, (int)$current_x, (int)$current_y, (int)$x, (int)$y, $color);

            // 更新当前点为下一段的起点
            $current_x = $x;
            $current_y = $y;
        }

        // 强制连接到终点,避免步长累积误差
        imageline($img, (int)$current_x, (int)$current_y, (int)$end_x, (int)$end_y, $color);
        $current_x = $end_x;
        $current_y = $end_y;
    }
}

// 使用示例
$width = 800;
$height = 600;
$img = imagecreatetruecolor($width, $height);
$bg_color = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $bg_color);
$curve_color = imagecolorallocate($img, 255, 0, 0);

// 构造与你Imagick代码兼容的points参数
$points = [
    ['x1' => 400, 'y1' => 100, 'x' => 600, 'y' => 500],
    ['x1' => 200, 'y1' => 400, 'x' => 100, 'y' => 200]
];

draw_bezier_curve_gd($img, $curve_color, 100, 100, $points);

// 输出图像
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);

二、圆弧近似(进阶,适合性能优化)

如果不想用大量线段,也可以用单段或少量圆弧拟合二次贝塞尔曲线,核心是找到与贝塞尔曲线在起点、终点切线一致,且尽可能贴合中间部分的圆弧,计算步骤如下:

  • 计算贝塞尔曲线起点 $P0$ 的切线方向:向量 $P1 - P0$
  • 计算贝塞尔曲线终点 $P2$ 的切线方向:向量 $P2 - P1$
  • 找到两条切线的交点,确定圆弧圆心的角平分线方向
  • 求解圆心坐标(满足:到 $P0$、$P2$ 的距离相等;与 $P0$ 的连线垂直于起点切线;与 $P2$ 的连线垂直于终点切线)
  • 用GD的imagearc绘制圆弧

这种方法计算量较大,且对曲率变化大的贝塞尔曲线拟合误差明显,仅适合曲线形态平缓的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:57:02