【问题标题】:Point inside a 3d closed volume点在 3d 封闭体积内
【发布时间】:2016-11-07 22:00:02
【问题描述】:

我有一个由 6 个曲面定义的 3d 封闭体积,每个曲面都有 4 个顶点。

所以,我想检查给定点是在体积内还是在体积外。我想到的一个解决方案是:

  1. 从给定点绘制一条随机线,并检查它与包围体积的表面的交点。由于我使用矢量代数来计算线和曲面的交点,因此交点可以位于 3d 无限曲面上的任何位置。

  2. 现在我检查这个交点是否恰好位于无限平面上并包围体积的那个面上。

为此,我再次想从我的交点绘制一条随机射线到体积的相应面,并检查点是否位于面上。

But I don't know how to check this feature of locating if it is on the surface  
or not. Can someone please suggest how can I do it.



P.S. One way of doing this was extending ray casting to 3d but that involves 
comparison of slopes to check the orientation. So how can I check orientation 
of 3 points in 3d space. I have 4 vertices which make up that face, I know the 
point under consideration. How can I check if this point lies clockwise or   
counter clockwise to the surface. 

【问题讨论】:

    标签: c++ 3d raycasting point-in-polygon


    【解决方案1】:

    您可以为每个表面创建一个布尔条件,以确定给定点是在表面内部还是外部。这可能需要您添加有关每个曲面的法线的信息(即曲面的哪一侧是“向外”)。如果该条件对六个曲面中的每一个都成立,则该点位于体积内。

    另一种类似的思考方式是创建一个线性不等式系统,使用每个表面创建一个不等式,创建一个代表您的体积的封闭空间。这也归结为满足该点是在每个曲面“内部”还是“外部”,并检查该点是否在所有曲面内部。

    【讨论】:

    • 我同意这个解决方案,但我正在寻找的是一种通用算法,它不涉及太多线性代数,并且可以像在 2d 中实现光线投射的方式来实现。
    • @AnkitMishra 光线投射怎么不涉及线性代数?
    • 是的,但是它以一种非常简单的方式进行,它计算点 (P0,P1) 和 (P1,P2) 的斜率,并得出结论是顺时针还是逆时针。所以,这就是我试图做的原因,比较斜率并查看线上两点的方向是否与形成表面的线不同,然后该线与线段相交。但我不确定如何在 3d 空间中做到这一点
    • @AnkitMishra,光线投射总是假设多面体是凸的,因此解决方案并不像您想象的那么普遍。看看我的回答,了解没有凸属性的一般多面体的复杂性(抱歉,由于明显的原因,它被解释为 2D 多边形)
    【解决方案2】:

    看看这个问题:signed distance between plane and point

    现在,您只需检查您的点是否在每个体积表面的右侧(正确符号)。像这样的:

    bool isInside(const std::vector<Planes>& planes, const Point& point){
    
      for(const auto& plane : planes){
        const auto dist = 
           dotProduct(plane.normal, vectorSubtract(point, plane.point));
        if(dist>0) return false;
      }
    
      return true;
    };
    

    【讨论】:

    • 我同意这种方法,但它会给我点和无限平面之间的距离,因为我计算了交点,所以我知道它为零。但我想检查该点是否位于由我知道的四组点组成的有限表面上。我怎样才能做到这一点?带符号的距离是无限平面与点之间的距离。
    • 嗯,每个位面的边总是其他位面的交叉点。您只需要将每个曲面视为无限。如果该点位于边缘之外,则表示其他一些(无限)曲面的另一侧。考虑 2d 的情况:您可以通过检查 x>a 来检查一个点是否在 x=a,by=c,d 的正方形内,(即:ac,y
    • 所以,这就是我的理解,如果我找出 3d 线和平面的交点,然后检查它是否位于通过这样做形成面的四个顶点内。令 P(x,y,z) 为线与平面的交点,然后如果它位于由曲面末端形成的长方体中,即 xlow、xhigh、ylow、yhigh、zlow、zhigh。这是否能证明重点在脸上。我认为应该,只是想要一个意见。
    • 我没有关注。我建议您首先将每个表面声明为法线和点,然后按照我的回答。如果没有一些线性代数,比如标量积(投影),你真的不能做这样的事情。
    • @AnkitMishra,不确定。听起来似乎是合理的——必须绘制它并考虑它可能遗漏的情况(如果有的话)。尝试这两种方法并与一些简单的案例进行比较,如果您需要快速进行分析。
    【解决方案3】:

    所以,我认为我可以做到的一种方法是:

    将光线投射扩展到 3d 表面,但这涉及到从所考虑的点发出的光线穿过体积的次数。这涉及找到线和体积面的交点。

    So what I can do is for a single face (and I will extend it to all the faces)
    is, I check for the point of intersection of 3d line and plane by doing simple
    algebra and then check if the point lies inside the cuboid formed by 
    extremities of the vertices forming the face. i.e check if P(x.y,z) which is 
    the point of intersection of line and plane lies inside the region defined by
    extremities of the surface.
    i.e.
    
    x > xlow and x < xhigh and y > ylow and y < yhigh and z > zlow and z < zhigh.
    
    These two conditions i.e. ray intersects the 3d plane and the intersection
    lies in this region proves that the intersection of ray and plane lies on the 
    surface which encloses the volume.
    
    
    I can count the number of such intersections if it is odd, the point
    lies inside the volume if it is even the point lies outside the volume.
    
    
    Does anyone see a problem with this algorithm?
    

    【讨论】:

      【解决方案4】:

      要考虑您的问题,我们必须首先考虑内部或外部的含义。对于四个曲面实体,每个曲面将空间精确地划分为两侧,通常,四个曲面将空间划分为 9 个区域,其中只有一个是有界的,从而界定了一个四面体(但如果我们仔细选择曲面,我们可以达到甚至没有边界区域——例如使它们中的两个平行)。所以,一般来说,你必须决定平面的哪一边标记内侧或外侧(嗯,这也没有关系,在外面和不在里面是一样的)。

      面越多,问题就越复杂(并且更复杂),因为您可以有多个也定义实体的有界区域,因此您需要更多信息,而不仅仅是界定它的平面。如果该区域导致非凸区域,问题甚至会更加复杂,因为您的点可能位于区域的某些部分,与某些平面的 一侧 和错误一侧的 匹配 为他人,并继续在你的固体里面。只需看到这样的定界多边形

      以及制作有界区域的可能性

      您需要做的第一件事是充分定义实体,用边界定面,并在一定程度上确定界定一个面的边和顶点,以及面如何相互连接以形成实体。

      一旦遇到这种情况,您就会有一组面,并且每个面的向量都指向外部(以连续的方式,因此您不会以面法线指向上方结束,下一个指向下方)。接下来你需要做的是将你的实体划分为一个凸实体。可以证明,对于一个由平面构成的 3d 立体,它可以细分为一组有限的凸立体。

      我将尝试在 2D 中说明相同的问题,但在 3D 中基本相同:

      首先,我们有初始的 poligon,假设它是凸的(这是用于此目的的重要属性,我稍后会提到):

      让我们想象它是一颗 3D 小行星,而您是在其表面行走的人。如果您开始步行,您将穿过所有用黄色标出的线。这些是法线,因此您需要从每个面知道哪些面是可到达的,并按照我所做的那样构建这些表面的法线贴图。当您在小行星上行走时,您标记法线以了解小行星内部的位置,并且您正在划定它。现在,我们有了一张包含所有法线的小行星地图。让我们画出我们下方的半空间(我们下方的表面的一侧)在几何学中,这可以用平面表示(平面具有所有点都与向量正交的属性,所以X*V=0其中@987654344 @代表点积,如果我们把我们的poligon的中心和法向量作为我们绘图中的黄色向量,我们会得到(X - P)*N = 0,其中X是平面中一个点的位置,@987654347 @ 是我们的位置(脸的中心),N 是垂直于平面的向量,指向上方(指向小行星的外侧)

      嗯,这个等式的性质是,如果我们用空间中的任何位置替换X,平面下方的所有点X 都有一个值(X - P)*N &lt; 0,所有天空值都有它&gt; 0

      如果我对四个法线做同样的事情,我会得到这个: ... 处理 只有当四个平面给出(X - X_face)*(N_face) &lt; 0 时,问题点X 才会被埋入小行星中,现在,X_face 是面的中心,N_face 是指向小行星外部的面法线。 满足四个条件时,该点才会位于小行星内部。

      但是如果小行星不是凸面的会发生什么?

      如果您绘制法线,这将无济于事......因为小行星内部有一些点并且未通过某些测试(请记住,该点必须低于所有表面,但不是(如如下所示):

      问题是多边形(或多面体)不是凸的,我们不能在那里应用算法。所以首先我们要解决让它凸的问题。

      如果您在越过边缘时开始沿着小行星的所有表面(保留法线),您将到达另一个增加或减少坡度的平面,因此如果它增加坡度,您将标记该边缘(多边形中的顶点)为异常(我们将它们标记为红色),如果它减少,我们将它们标记为正常(我们将它们标记为绿色):

      当所有边缘都正常时,没问题,因为我们的小行星将是凸的,但是当其中任何一个异常时,我们必须继续在那个平面上(在所有平面上挖掘小行星)直到我们到达另一个表面(我们延长了平面以划分我们的 poligon):

      因为我们有有限数量的边,并且只有其中一些被标记为异常,所以这个过程是有保证的(请记住,您可以让 另一边试图找到一张脸顶点向上和顶点向下的多面体(多边形)的(边)(在我们之前解释的意义上))

      所以你已经将你的多面体分成了一组有限的凸多面体,可以应用第一个算法。

      【讨论】:

        猜你喜欢
        • 2010-11-27
        • 2015-12-18
        • 2012-09-07
        • 2013-02-04
        • 2021-05-14
        • 1970-01-01
        • 1970-01-01
        • 2015-12-18
        • 1970-01-01
        相关资源
        最近更新 更多