判断空间中的一个点是否在一个多面体内

射线法

1.从点P发射一条射线,射线的方向可以是任意的,但是要避免平行多面体任何一个面的法向量,避免射线落在多面体的边界上。

2.检测射线与多面体的交点,判断射线是否与每个多面体的面相交。

3.计算交点数量,若为奇数则点在多面体内,若为偶数,则线在多面体外。

//以空间中任意凸六面体为例
//定义点(向量)
class Point {
    double x, y, z;

    Point(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}

    Point operator-(const Point& v) const {
        return Point(x - v.x, y - v.y, z - v.z);
    }

    //向量点乘
    double dotProduct(const Point& v) const{
        return x * v.x + y * v.y + z * v.z;
    }

    //向量叉乘
    Point crossProduct(const Point& v) const{
        return Point(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x)
    }
};

// 六面体结构体
struct Hexahedron {
    std::array<Point, 8> vertices;
    std::array<std::array<int, 4>, 6> faces;

    Hexahedron(const std::array<Point, 8>& verts) : vertices(verts) {
        faces = {{
            {0, 1, 5, 4}, {7, 6, 2, 3},  // 前后面
            {3, 0, 4, 7}, {1, 2, 6, 5},  // 左右面
            {4, 5, 6, 7}, {3, 2, 1, 0}   // 上下面
        }};
    }
};

//检测一条射线是否与三角形相交
bool intersectTriangle(const Point& rayOrigin, const Point& rayDirection, const Point& v0, const Point& v1, const Point& v2) {
    const double EPSILON = 1e-6;

    Point edge1 = v1 - v0;
    Point edge2 = v2 - v0;
    Point h = rayDirection.crossProduct(edge2);
    double a = edge1.dotProduct(h);

    if (a > -EPSILON && a < EPSILON) return false;

    double f = 1.0 / a;
    Point s = rayOrigin - v0;
    double u = f * s.dotProduct(h);

    if (u < 0.0 || u > 1.0) return false;

    Point q = s.crossProduct(edge1);
    double v = f * rayDirection.dotProduct(q);

    if (v < 0.0 || u + v > 1.0) return false;

    double t = f * edge2.dotProduct(q);

    return t > EPSILON;
}


//判断点是否在六面体中
bool pointInHexahedron(const Point& point, const Hexahedron& hexahedron) {
    Point rayDirection(1, 0, 0);  // 沿x轴正方向的射线
    int intersectionCount = 0;

    for (const auto& face : hexahedron.faces) {
        if (intersectTriangle(point, rayDirection, 
                              hexahedron.vertices[face[0]],
                              hexahedron.vertices[face[1]],
                              hexahedron.vertices[face[2]]))
            ++intersectionCount;
        if (intersectTriangle(point, rayDirection, 
                              hexahedron.vertices[face[0]],
                              hexahedron.vertices[face[2]],
                              hexahedron.vertices[face[3]]))
            ++intersectionCount;
    }

    return intersectionCount % 2 == 1;
}

点到面的有向距离

点到平面的有向距离是指从空间中的一个点到一个给定平面的垂直距离,并且这个距离是有方向性的。这意味着它不仅可以告诉我们点离平面有多远,还可以告诉我们点是在平面的哪一侧。计算点到所有面的有向距离,若符号都一致,则该点在多面体内。

//判断点在平面的哪一侧
bool isPointOnSameSide(const Point& p, const Point& p0, const Point& p1, const Point& p2)
{
	//计算平面法向量
	Point v1=p1-p0;
    Point v2=p2-p0;
	
    Point h=v1.crossProduct(v2); 

	return normal.dotProduct(p - h) <= 0;
}

//判断点是否在六面体内部
bool isPointInHex(const Point& p, const Hexahedron& hexahedron)
{
	for (const auto& face : hexahedron.faces)
	{
		//检查点是否在平面的同一侧
		if (!isPointOnSameSide(p, hexahedron.vertices[face[0]], hexahedron.vertices[face[1]], hexahedron.vertices[face[2]]))
		{
			return false;
		}
	}
	return true;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值