线 c++实现

本文详细解释了计算几何中线段(line)的向量表示方法,探讨了斜率、线的位置关系、交点计算、法线和角度测量。通过实例展示了如何判断线段相交,求解线的交点,并涉及线与平面的交点计算。核心概念包括向量方向、点线关系和几何运算。
摘要由CSDN通过智能技术生成

计算几何中线line的表示

在这里插入图片描述
这类比于y=bt+a
b表示斜率,这里将b用向量ab来代替,因为向量ab也表示方向,而斜率b也是一种方向的表示,所以可以得到图中表示的方法。
分情况讨论:
0<t<1: t在线段ab之间
t>1:t在向量ab的正向延长线
t<0:t在向量ab的反向延长线
那么
0<t<1: 可以说明这是个线段
t>0:可以说明这是个射线
t在±∞:可以说明这是个线
在这里插入图片描述
推出
在这里插入图片描述
在这里插入图片描述
找出相交点:
在这里插入图片描述
在这里插入图片描述
当t=s时候是相交点求出t=s=1
所以相交点为(6,9,6)

法线

在这里插入图片描述

template <typename coord_type, size_t dim= DIM3>
    class Line
    {
        Vector<coord_type, dim> dir;
        Vector<coord_type, dim> point;

    public:
        Line() {}

        Line(Vector<coord_type, dim> &p1,
             Vector<coord_type, dim> &p2)
            : dir(p2 - p1), point(p1)
        {
        }
    public:
        Vector<coord_type,dim> getPoint();
        Vector<coord_type,dim> getDir();
    };

    template <typename coord_type, size_t dim>
    inline Vector<coord_type,dim> Line<coord_type,dim>::getPoint()
    {
        return point;
    }
    
    template <typename coord_type, size_t dim>
    inline Vector<coord_type,dim> Line<coord_type,dim>::getDir()
    {
        return dir;
    }

求线的交点

在程序上要关注两个问题:
1.两条线是否相交
2.两条线的交点是哪个
在这里插入图片描述
一个线段有两端点,分别判断这两个端点相对于另一条直线所处的位置。
利用上面判断点相对于线位置的程序即可。

bool intersection(const Point2d &a, const Point2d &b,
                          const Point2d &c, const Point2d &d)
{
    auto ab_c = orientation2d(a, b, c);
    auto ab_d = orientation2d(a, b, d);
    auto cd_a = orientation2d(c, d, a);
    auto cd_b = orientation2d(c, d, b);
    if (ab_c == BETWEEN || ab_c == ORIGIN || ab_c == DESTINATION ||
        ab_d == BETWEEN || ab_d == ORIGIN || ab_d == DESTINATION ||
        cd_a == BETWEEN || cd_a == ORIGIN || cd_a == DESTINATION ||
        cd_b == BETWEEN || cd_b == ORIGIN || cd_b == DESTINATION)
        return true;
    return _xor(ab_c == LEFT, ab_d == LEFT) &&
           _xor(cd_a == LEFT, cd_b == LEFT);
}

求两线段的交点

在这里插入图片描述
假设ab与cd的交点为p
那么之间p(t)=cp·t+c
那么cp直线的方向向量为p(t)-c=cp·t
再假设n为cd的法线n
这里将P(t)用(b-a)t+a去代,为啥?因为求交点当t=x,交点的横坐标的时候(b-a)x+a在P(t)
在这里插入图片描述
推出
t=n·(c-a)/n·(b-a)

bool Intersection(const Point2d &a, const Point2d &b,
                          const Point2d &c, const Point2d &d,
                          Point2d &intersection)
{
    Vector2f AB = b - a;

    Vector2f CD = d - c;
    Vector2f n(CD[Y], -CD[X]); // 自定义法线
    auto deno = dotProduct(n, AB);
    if (!isEqualDouble(deno, ZERO))
    {
        auto AC = c - a;
        auto numer = dotProduct(n, AC);
        auto t = numer / deno;
        auto x = a[X] + t * AB[X];
        auto y = a[Y] + t * AB[Y];
        intersection.assign(X, x);
        intersection.assign(Y, y);
        return true;
    }

    else
        return false;
}

bool Intersection(const Line2d &l1, const Line2d &l2,
                          Point2d &intersection)
{
    auto l1_start = l1.getPoint();
    auto l1_end = l1_start + l1.getDir(); // 假设t=1取的一个任一点
    auto l2_start = l2.getPoint();
    auto l2_end = l2_start + l2.getDir(); // 假设t=1取的一个任一点

    return Intersection(l1_start, l1_end, l2_start, l2_end);
}

求两条线的角度

利用两条向量的点积
在这里插入图片描述

 float AngleLine2D(const Line2d &l1, const Line2d &l2)
{
    auto l1_mag = l1.getDir().magnitude();
    auto l2_mag = l2.getDir().magnitude();

    auto dot = dotProduct(l1.getDir(),l2.getDir())
    auto theta = acos(fabs(dot)/l1_mag*l2_mag);
    return RadianceToDegrees(theta);
}

线与平面的交点

90°-线与法线相交

两个平面的交点

两个平面的法线相交

    template <typename T, size_t dim>
    static float getAngle(const Vector<T, dim> &v1,
                          const Vector<T, dim> &v2)
    {
        auto dot = dotProduct(v1, v2);
        auto theta = acos(fabs(dot));
        return RadianceToDegrees(theta);
    }

    float AngleLines2d(const Line2d &l1, const Line2d &l2)
    {
        return getAngle(l1.getDir(),l2.getDir());
    }

    float AngleLines3d(const Line3d &l1, const Line3d &l2)
    {
        return getAngle(l1.getDir(), l2.getDir());
    }

    float AngleLinePlane(const Line3d &l1, const Planef &p)
    {
        auto angle = getAngle(l1.getDir(), p.getNormal());
        return 90 - angle;
    }

    float AnglePlanes(const Planef&p1,const Planef&p2)
    {
        return getAngle(p1.getNormal(),p2.getNormal());
    }

判断共线与共面的情况

在这里插入图片描述
注意共线的情况是包括平行
在这里插入图片描述
在这里插入图片描述

四面体的体积->可以判断四个点或者三条向量是否共面的问题,即判断四面体的体积是否为0

在这里插入图片描述

bool coplaner(const Point3d &a, const Point3d &b, const Point3d &c, const Point3d &d)
{
    auto AB = b-a;
    auto AC = c-a;
    auto AD = d-a;
    return coplaner(AB,AC,AD);
}

bool coplaner(const Vector3f &a, const Vector3f &b, const Vector3f &c)
{
    float value = scalerTripleProduct(a,b,c);
    return isEqualDouble(value,ZERO);
}

点与线之间的距离

在这里插入图片描述
V是x(t)的方向向量,即Y(t)的法线向量
在这里插入图片描述
在这里插入图片描述
已知t1就可以求出X(t)->这是表示一个点。两个点相减得到的向量 模就是距离。

float distance(Line3d &line, Point3d &c)
    {
        auto AC = c - line.getPoint();
        auto t = dotProduct(line.getDir(),AC);
        auto xt = line.getPoint() + line.getDir()*t;
        auto dist_vec = xt - c;
        return dist_vec.magnitude();
    }

0<t<1:找到的距离点是在线段之间。
t<0:找到的距离点是在起始点之外。
t>1:找到的距离点是在终点之外。

点到面之间的距离

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

float distance(Planef &p, Point3d &q)
    {
        auto result = dotProduct(p.getNormal(), q) - p.getD();
        return result;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yhaida

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

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

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

打赏作者

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

抵扣说明:

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

余额充值