登山第四梯:三维圆生成——我站起来了

一 简介

        圆作为几何图形中一种常见的图形,经常被用于描述生活中的各种物体,如隧道截面轮廓、结构柱截面轮廓、树干截面轮廓。因此,如何对圆进行参数方程表达,将是对这些对象建模的关键之处,而如何对三维空间中的圆(任意圆)进行参数方程表达,将是我们这次的主要任务。

这次的内容主要包括三个:

(1)2D特殊圆的参数方程表达;

(2)2D任意圆的参数方程表达;

(3)3D任意圆的参数方程表达;

(4)代码展示:

二 2D特殊圆的参数方程表达

如上图所示,该处2D特殊圆是指圆心在坐标空间原点。众所周知,圆心在原点,半径为r的圆形参数方程可以表示为:

x=r*cosα,可以理解为OP在X轴上的投影为圆周上点P的x坐标

y=r*sinα,可以理解为OP在Y轴上的投影为圆周上点P的y坐标

也可以通过向量的思路去理解:

OP为向量,可视作直角三角形斜边向量,因此,可通过两条直角边向量相加得到,

OP=OP*cosα+OP*sinα

三 2D任意圆的参数方程表达

同上,我们通过向量的思维来理解2D任意圆的参数方程表达(以下表达均为向量)。

首先,OP=OC+CP

接着,CP=CP_a+CP_b,其中,CP_a为向量CP在坐标轴a上的投影向量,CP_b为向量CP在坐标轴b上的投影向量。

然后,CP_a=||CP||*cosα*a=r*cosα*a,CP_b=||CP||*sinα*b=r*sinα*b,其中a可认为是x轴单位向量(1,0),b可认为是y轴单位向量(0,1)。

最后,OC为圆心与原点构建的向量(cx,cy)。

综上所述,2D任意圆的参数方程能够表示为:

x=cx+r*cosα*a_x+r*sinα*b_x

y=cy+r*cosα*a_y+r*sinα*b_y

因此,如果已知圆心坐标、圆半径,并能在二维空间中描绘出圆形。

四 3D任意圆的参数方程表达

同上,我们通过向量法来推导3D任意圆的参数方程表达式(以下均为向量表示):

首先,OP=OC+CP

接着,CP=CP_a+CP_b,其中,CP_a为向量CP在坐标轴a上的投影向量,CP_b为向量CP在坐标轴b上的投影向量。

然后,CP_a=||CP||*cosα*a=r*cosα*a,CP_b=||CP||*sinα*b=r*sinα*b。

其中,向量a和向量b为3D圆所在平面中一组正交的单位向量,可以通过法向量N进行求得。

如:

c=(0,0,1)——可任意设置,只要不与法向量平行即可

a=N x c

b=N x a

x表示叉乘。

最后,OC为圆心与原点构建的向量(cx,cy,cz)。

综上所述,3D任意圆的参数方程能够表示为:

x=cx+r*cosα*a_x+r*sinα*b_x

y=cy+r*cosα*a_y+r*sinα*b_y

z=cz+r*cosα*a_z+r*sinα*b_z

因此,如果已知圆心坐标、圆半径以及圆所在平面法向量,并能在三维空间中描绘出圆形。

五 代码展示

// 三维空间中,根据圆心、半径、法向量求 require_number 个圆上的点(按顺序排列)
/*
* 注:根据一个 7 维向量拟合圆,coefM_为一个 7 维向量,依次为:圆心(x,y,z),半径,法向量(nx,ny,nz)
*/
std::vector<Eigen::Vector3f> createCircleBy_Center_Radius_Normal_3D(Eigen::VectorXf coefM_,
       int require_number)
{
       assert(coefM_.size() == 7);
       assert(require_number > 0);
       std::vector<Eigen::Vector3f> circleEdge;
       float stepSize = 2 * M_PI / require_number;
       Eigen::VectorXf theta(require_number+1);
       for (int i = 0; i <= require_number; ++i) {
              theta[i] = i * stepSize;
       }
       Eigen::Vector3f Center = coefM_.head(3);
       Eigen::Vector3f N = coefM_.tail(3);
       float R = coefM_[3];
       Eigen::Vector3f V1 = N.cross(Eigen::Vector3f(0, 0, 1));
       if (V1[0] == 0 && V1[1] == 0 && V1[2] == 0) {
              V1 = N.cross(Eigen::Vector3f(0, 1, 0));
       }
       V1.normalize();
       Eigen::Vector3f V2 = N.cross(V1);
       V2.normalize();
       circleEdge.resize(require_number);
       for (int i = 0; i < require_number; ++i) {
              if (i > 9) continue;
              circleEdge[i][0] = std::cos(theta[i]) * R * V1[0] +  std::sin(theta[i]) * R * V2[0] + Center[0];
              circleEdge[i][1] = std::cos(theta[i]) * R * V1[1] +  std::sin(theta[i]) * R * V2[1] + Center[1];
              circleEdge[i][2] = std::cos(theta[i]) * R * V1[2] +  std::sin(theta[i]) * R * V2[2] + Center[2];
       }
       return circleEdge;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云登山者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值