三维空间常用函数(二) c++ Qt

        上一篇文章介绍完了点、线、面的基本函数,链接如下。

三维空间常用函数(一) c++ Qt_嘟嘟噜噜噜啦啦的博客-CSDN博客

        接下来介绍一下投影以及求交的方法。

1、点投影到平面与直线

        点投影到平面

        求点到平面的投影点,可以看成以这个点为起点,以平面法向量为方向的直线,与平面的交点,直线可以表示为:p + t * dir,只需求出平面上的点的t值大小即可,如图:

        从图中可以看出,投影点 P = P0 + t * nor,而 t = cenP0 * cosθ,cenP0为以cen和P0组成线段的长度,而θ为cenP0与nor的夹角,从之前点乘的定义,很容易得到 t = cenP0 * nor,所以点投影到三维平面的函数如下

// 点投影到平面
QVector3D ProjectionToPlane(const QVector3D& plane_center, const QVector3D& plane_normal, const QVector3D& point)
{
    QVector3D nor = plane_normal.normalized();

    QVector3D temp_point;
    // 求点到平面的距离
    double t = QVector3D::dotProduct(nor, (plane_center - point));
    temp_point = t * nor + point;// 点到平面的距离乘法向量
    return temp_point;
}

        点投影到直线

        有了点投影到平面之后,点投影到直线就十分简单了,如图:

        点P0投影到以cen为起点,dir为方向向量的直线上的投影点P,可以看成是点cen投影到以P0为中心点,以dir为法向量的平面的投影点,所以点投影到三维直线的函数如下:

QVector3D ProjectionToLine(const QVector3D& line_center, const QVector3D& line_dir, const QVector3D& point)
{
    return ProjectionToPlane(point, line_dir, line_center);
}

2.线与面相交

        直线与平面相交

        直线与平面相交,需要先对直线的方向向量进行判断,当直线与平面不平行的时候,那就一定会有一个交点,平行根据直线方向向量与法向量是否垂直判断即可。有交点的时候如图:

        图中平面的中心点为cen,法向量为nor,直线上一点为P0,方向向量为dir,直线与平面的交点假设为P,则根据之前点投影到平面的公式,有 t = cenP0 * nor = PP0 * nor,而线段PP0  = P - P0, 因为P在直线上,所以P = P0 + x * dir,其中x为线段PP0的长度。所以可以得到

        cenP0 * nor = (P - P0) * nor = (P0 + x * dir - P0) * nor = x * dir * nor

→ x = cenP0 * nor / (dir * nor) 

        得到了x之后,交点P的坐标就可以用P0 + x * dir得到。所以计算直线和平面的交点的函数如下:

bool LineIntersectPlane(const QVector3D& line_p, const QVector3D& line_dir, const QVector3D& plane_cen, const QVector3D& plane_nor, QVector3D& out_point)
{
    if (qAbs(QVector3D::dotProduct(line_dir, plane_nor)) < 0.0001) // 平行
        return false;
    double t = QVector3D::dotProduct(plane_cen - line_p, plane_nor) / QVector3D::dotProduct(line_dir, plane_nor);
    out_point = line_p + t * line_dir;
    return true;
}

        如果判断是射线的话,只要加个t大于等于0的判断即可。如果为线段,则判断t的值是否在线段的范围内即可。

        参考链接:【寒江雪】计算直线与平面的交点坐标_平面img_285与直线img_286的交点坐标为__寒江雪_的博客-CSDN博客

        射线与三角形相交

        原理和代码参考:

https://www.cnblogs.com/graphics/archive/2010/08/09/1795348.html

        这里给出改成Qt使用的函数:

// 求射线与三角形的交点,射线起点,方向向量,三角形三个顶点坐标,交点方向分量,有交点返回真,无交点返回假
bool IntersectTriangle(QVector3D orig, QVector3D dir, QVector3D v0, QVector3D v1, QVector3D v2, double& t)
{
    // 射线上的点表示为  起点 + t * 方向向量,三角形内部所以点的参数方程为(1-u-v)*v0+u*v1+v*v2,他们相等就是交点
    // 三未知量u,v,t使用三阶齐次矩阵来求解
    // 三向量的行列式等于x1点乘x2叉乘x3
    double u, v;
    QVector3D E1 = v1 - v0;
    QVector3D E2 = v2 - v0;
    QVector3D P = QVector3D::crossProduct(dir, E2);
    double det = QVector3D::dotProduct(E1, P);
    QVector3D T;
    if (det > 0)
    {
        T = orig - v0;
    }
    else
    {
        T = v0 - orig;
        det = -det;
    }
    if (det < 0.0001f)
    {
        return false;
    }
    u = QVector3D::dotProduct(T, P);
    if (u<0.0f || u>det)// 没有交点,返回假
        return false;
    QVector3D Q = QVector3D::crossProduct(T, E1);
    v = QVector3D::dotProduct(dir, Q);
    if (v<0.0f || u + v>det)// 没有交点,返回假
        return false;
    t = QVector3D::dotProduct(E2, Q);
    t = t / det;
    return true;// 计算完毕之后,返回真
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值