开启辅助访问 天气与日历

登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 2593|回复: 0

贝塞尔曲线分析和示例

[复制链接]

76

主题

78

帖子

858

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
858

活跃会员热心会员推广达人宣传达人灌水之王突出贡献优秀版主荣誉管理论坛元老

发表于 2023-7-27 09:39:55 | 显示全部楼层 |阅读模式 来自 中国陕西西安
路径追踪算法,贝塞尔曲线,分直线,二阶贝塞尔,三阶贝塞尔
  1. #include <stdio.h>
  2. #include <math.h>

  3. // 二维坐标结构体
  4. typedef struct {
  5.     double x;  // X坐标值
  6.     double y;  // Y坐标值
  7. } Point;

  8. // 二维向量结构体
  9. typedef struct {
  10.     double dx;  // X分量
  11.     double dy;  // Y分量
  12. } Vector;

  13. // 计算两点之间的距离
  14. // p1: 第一个点
  15. // p2: 第二个点
  16. double distance(Point p1, Point p2) {
  17.     double dx = p2.x - p1.x;
  18.     double dy = p2.y - p1.y;
  19.     return sqrt(dx*dx + dy*dy);
  20. }

  21. // 计算二阶贝塞尔曲线上的点
  22. // p0: 起始点
  23. // p1: 控制点
  24. // p2: 终点
  25. // t: 参数值,[0, 1]范围内的值
  26. Point calculateQuadraticBezier(Point p0, Point p1, Point p2, double t) {
  27.     double u = 1 - t;
  28.     double tt = t * t;
  29.     double uu = u * u;
  30.     double ut = u * t;

  31.     Point p;
  32.     p.x = uu * p0.x + 2 * ut * p1.x + tt * p2.x; // 二阶贝塞尔曲线的x坐标计算公式
  33.     p.y = uu * p0.y + 2 * ut * p1.y + tt * p2.y; // 二阶贝塞尔曲线的y坐标计算公式
  34.     return p;
  35. }

  36. // 计算三阶贝塞尔曲线上的点
  37. // p0: 起始点
  38. // p1: 控制点1
  39. // p2: 控制点2
  40. // p3: 终点
  41. // t: 参数值,[0, 1]范围内的值
  42. Point calculateCubicBezier(Point p0, Point p1, Point p2, Point p3, double t) {
  43.     double u = 1 - t;
  44.     double tt = t * t;
  45.     double uu = u * u;
  46.     double ut = u * t;

  47.     Point p;
  48.     p.x = uu * u * p0.x + 3 * uu * t * p1.x + 3 * u * tt * p2.x + tt * t * p3.x; // 三阶贝塞尔曲线的x坐标计算公式
  49.     p.y = uu * u * p0.y + 3 * uu * t * p1.y + 3 * u * tt * p2.y + tt * t * p3.y; // 三阶贝塞尔曲线的y坐标计算公式
  50.     return p;
  51. }

  52. int main() {
  53.     // 示例用法
  54.     Point p0 = {0, 0};  // 起始点
  55.     Point p1 = {1, 2};  // 控制点1
  56.     Point p2 = {3, 4};  // 控制点2
  57.     Point p3 = {5, 6};  // 终点

  58.     int numSteps = 10;  // 贝塞尔曲线上的点数

  59.     Vector tangent;    // 切线向量
  60.     double t;          // 时间参数

  61.     for (int i = 0; i <= numSteps; i++) {
  62.         t = (double)i / numSteps;

  63.         // 计算二阶贝塞尔曲线上的点
  64.         Point point = calculateQuadraticBezier(p0, p1, p2, t);

  65.         // 计算切线向量
  66.         Vector v;
  67.         v.dx = 2 * (p1.x - p0.x) * (1 - t) + 2 * (p2.x - p1.x) * t; // 切线向量的x分量计算公式
  68.         v.dy = 2 * (p1.y - p0.y) * (1 - t) + 2 * (p2.y - p1.y) * t; // 切线向量的y分量计算公式

  69.         // 将切线向量单位化
  70.         double length = sqrt(v.dx * v.dx + v.dy * v.dy); //  计算切线向量的模长度

  71. // 通过平方和的开方计算切线向量的模。
  72. // 切线向量的模表示向量的长度。
  73. // 使用勾股定理将x和y分量的平方和开方,得到向量的长度。
  74.         tangent.dx = v.dx / length; // 单位化后的切线向量的x分量
  75.         tangent.dy = v.dy / length; // 单位化后的切线向量的y分量

  76.         // 计算预览点的位置
  77.         Point previewPoint;
  78.         previewPoint.x = point.x + tangent.dx; // 预览点的x坐标
  79.         previewPoint.y = point.y + tangent.dy; // 预览点的y坐标

  80.         printf("Point %d: (%.2lf, %.2lf)\n", i, previewPoint.x, previewPoint.y);
  81.     }

  82.     return 0;
  83. }
  84. 参数值 `t` 是一个范围在 [0, 1] 内的值,用于控制贝塞尔曲线上的点的位置。

  85. 在贝塞尔曲线的定义中,我们使用控制点来塑造曲线的形状。贝塞尔曲线的起始点和终点是通过调整参数 `t` 来确定的。当 `t` 的值为 0 时,表示我们取贝塞尔曲线上的起始点;当 `t` 的值为 1 时,表示我们取贝塞尔曲线上的终点。

  86. 当 `t` 的值在 (0, 1) 的范围内时,我们可以根据具体的数值来确定贝塞尔曲线上的中间点的位置。较小的 `t` 值会使我们更靠近起始点,而较大的 `t` 值会使我们更接近终点。在 (0, 1) 范围内,我们可以通过调整 `t` 的值来获得沿着贝塞尔曲线平滑变化的点的位置。

  87. 需要注意的是,贝塞尔曲线上的点并不一定要在参数 `t` 等于整数值时才存在。实际上,我们可以使用更多的小数值来控制曲线上的更多点的位置,以获得更精细的曲线形状。通过在 [0, 1] 范围内对 `t` 的连续变化,我们可以生成贝塞尔曲线上的连续点集,从而绘制出平滑曲线形状。

  88. 总之,参数值 `t` 表示在贝塞尔曲线上选择点的位置,范围在 [0, 1] 内,可以通过调整 `t` 的大小来控制点在曲线上的位置和移动的路径。
复制代码
这个程序中,我们首先定义了一个二维坐标结构体Point和一个二维向量结构体Vector。然后我们实现了计算两点之间距离的函数distance,计算二阶贝塞尔曲线上的点的函数calculateQuadraticBezier,以及计算三阶贝塞尔曲线上的点的函数calculateCubicBezier。

在main函数中,我们先定义了起始点p0、控制点1p1、控制点2p2和终点p3。然后定义了一个整型变量numSteps,表示贝塞尔曲线上的点数。接下来,我们定义了一个切线向量Vector和一个时间参数t。

在for循环中,我们根据参数t的值,通过调用calculateQuadraticBezier函数计算出贝塞尔曲线上的点point。然后,我们根据贝塞尔曲线的性质计算切线向量v,并将其单位化得到Vector类型的切线向量tangent。最后,根据切线向量和贝塞尔曲线上的点,计算预览点的位置previewPoint。

程序以格式化输出的方式打印出每个预览点的坐标信息。

最后,返回0表示程序正常结束。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Geek Planet ( 陕ICP备19010480号 )

GMT+8, 2024-11-21 14:29 , Processed in 0.072435 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表