计算几何——线段和平面的交点的实现

原理:
在这里插入图片描述
我们用向量sv0点乘法向量N,向量se点乘法向量N,二者相除再乘以向量se,我们就可以得到sv0在法向量上的投影比上se在法向量上的投影,根据相似三角形再乘以向量se即可得到s与线段和平面交点的向量,再加上s坐标即为交点坐标。

#include <iostream>
#include <math.h>
using namespace std;

struct Point
{
    double x;    // x坐标
    double y;    // y坐标
    double z;    // z坐标(默认为0,如果需要三维点则给z赋值)

    Point(double a = 0, double b = 0, double c = 0) { x = a; y = b; z = c; } // 构造函数
};
struct Line
{
    Point s;    // 起点
    Point e;    // 终点
    bool is_seg; // 是否是线段

    Line() {};    // 默认构造函数
    Line(Point a, Point b, bool _is_seg = true) { s = a; e = b; is_seg = _is_seg; }    // 构造函数(默认是线段)
};
struct Triangle//三点确定的平面 
{
    Point v0;
    Point v1;
    Point v2;
    bool is_plane;

    Triangle() {}; // 默认构造函数
    Triangle(Point a, Point b, Point c, bool _is_plane = false) { v0 = a; v1 = b; v2 = c; is_plane = _is_plane; }// 构造函数(默认是三角形)
};
Point div(const Point& p, double ratio)//向量除法 
{
    Point res;
    
    res.x = p.x / ratio;
    res.y = p.y / ratio;
    res.z = p.z / ratio;

    return res;
}
double length(const Point& vec)//向量长度
{
    return (sqrt(pow(vec.x, 2) + pow(vec.y, 2) + pow(vec.z, 2)));
}
Point normalize(const Point& vec)//矢量标准化(矢量的长度规约到1)
{
    Point res;
    res = div(vec, length(vec));//向量除以向量长度
    return res;
}
Point sub(const Point& lhs, const Point& rhs)//向量相减 
{
    Point res;

    res.x = lhs.x - rhs.x;
    res.y = lhs.y - rhs.y;
    res.z = lhs.z - rhs.z;

    return res;
}
Point add(const Point& lhs, const Point& rhs)//向量加法 
{
    Point res;

    res.x = lhs.x + rhs.x;
    res.y = lhs.y + rhs.y;
    res.z = lhs.z + rhs.z;

    return res;
}
Point multiply(const Point& vec1, const Point& vec2)//向量叉乘 
{
    Point result;

    result.x = vec1.y * vec2.z - vec2.y * vec1.z;
    result.y = vec1.z * vec2.x - vec2.z * vec1.x;
    result.z = vec1.x * vec2.y - vec2.x * vec1.y;

    return result;
}
double dotMultiply(const Point& vec1, const Point& vec2)//向量点乘 
{
    return(vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z);
}
Point getUnitNormal(const Triangle& t)//获取平面法向量 
{
    Point vec1 = sub(t.v1, t.v0);
    Point vec2 = sub(t.v2, t.v0);

    return normalize(multiply(vec1, vec2));
}
Point mul(const Point& p, double ratio)//向量乘法 
{
    Point res;

    res.x = p.x * ratio;
    res.y = p.y * ratio;
    res.z = p.z * ratio;

    return res;
}
Point ltotInterPoint(const Triangle& t, const Line& l)
{
    Point line_vec = sub(l.e, l.s);
    Point point_vec = sub(t.v0, l.s);
    Point unit_plane_normal = getUnitNormal(t);

    double ratio = dotMultiply(point_vec, unit_plane_normal) / dotMultiply(unit_plane_normal, line_vec);

    return add(l.s, mul(line_vec, ratio));
}
int main()
{
	//测试数据 
	Point e(0.0,0.0,0.0),s(0.0,0.0,1.0);
	Line l(e,s,true);
	Point a(1.0,0.0,0.0),b(-1.0,0.0,0.0),c(0.0,1.0,0.0);
	Triangle t(a,b,c,true);
	cout<<ltotInterPoint(t,l).x<<","<<ltotInterPoint(t,l).y<<","<<ltotInterPoint(t,l).z;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值