zoukankan      html  css  js  c++  java
  • 计算几何---点与三角形面片的关系

    点是否再三角形面之内的位置关系判定

      常用的方法是,如果点在三角形内部,则连接与三角形的三个顶点,并计算组成的组成矢量的角度和,如果为2pei, 则在三角形内部,否则不再三角形内不。理论上该方法可行,但是效率非常慢。

      因为要计算夹角,需要多次计算平方根。

    1. 判定是否同边的技术原理(Same Side Technique)

      快速且简洁的方法如下:

       

      如图,三角形,线段AB, BC, and CA,每一条都半分剩下的部分,且剩下的在三角形的外部部分,我们可以利用这个特性做如下处理:

      如果一个点在三角形内部,则点必然在AB下面, BC左面,AC右边。如果不符合这个特性,则判定结果比在三角形外面,因此这个判定很快。

    (1)计算一个点在一个线段的位置关系

      

      通过叉积的方式,用[B - A ]和[p - A ]组成的叉积,即AB * Ap, 如果结果为正(叉积朝向屏幕外面),则p 在AB的左边, 否则(叉积朝向屏幕里面)在AB的右边。

      因为在3D空间中,AB方向线段,与点p的位置关系,可以借助点C来判定,因为ABC组成一个平面,因此C可以作为参考值。

      继而,判定任意点p, 如果[B - A ]和[p - A ]叉积方向,与[B - A ]和[C - A]的叉积方向不相同,则可直接判定没有在三角形内部; 如果与叉积方向相同,则可以继续对余下的边进行同样的判定方式。

      判断两个叉积结果的方向是否同向,使用点乘的方式。

      实现方面的方法非常容易,可以实现一个方法来判定是否在相同的边的位置。在判定的时候可以分别调用:

    function SameSide(p1,p2, a,b)
        cp1 = CrossProduct(b-a, p1-a)
        cp2 = CrossProduct(b-a, p2-a)
        if DotProduct(cp1, cp2) >= 0 then return true
        else return false
    
    function PointInTriangle(p, a,b,c)
        if SameSide(p,a, b,c) and SameSide(p,b, a,c)
            and SameSide(p,c, a,b) then return true
        else return false
    

       这样的方法非常高效,不需要计算平方根,弧度反求,等等。

    2 判定中心的技术原理(Barycentric Technique)

      还有一种方法可以执行的更快,原理更简单的方法,与数学知识有一点点关联。

      因为三角形的三个点确定一个平面,在这个平面中,可以任意选择一点,其他的点都是作为相对位置关系。如以点A为例,然后选定[C-A][B-A]两个向量作为该平面的坐标分量,因此三角形平面中任意一点都可以用这连个向量AB,AC表示。

      即  P = A + u * (C - A) + v * (B - A)

    注意:如果系数u或者v都< 0, 则p点必然在三角形区域之外。同样,如果u 或者v > 1, 则 点 p则在三角形之外,最后,如果 u + v > 1, 同样越过BC边,而到三角形之外

      

      因此可以计算出P在u,v系数下的表示。但是怎么获取p点在上述公式中的系数u,v呢?

      可以使用下述的公式推导:

        // We have two unknowns (u and v) so we need two equations to solve
        // for them.  Dot both sides by v0 to get one and dot both sides by
        // v1 to get a second.
        (v2) . v0 = (u * v0 + v * v1) . v0
        (v2) . v1 = (u * v0 + v * v1) . v1
    
        // Distribute v0 and v1
        v2 . v0 = u * (v0 . v0) + v * (v1 . v0)
        v2 . v1 = u * (v0 . v1) + v * (v1 . v1)
    
        // Now we have two equations and two unknowns and can solve one 
        // equation for one variable and substitute into the other.  Or
        // if you're lazy like me, fire up Mathematica and save yourself
        // some handwriting.
        Solve[v2.v0 == {u(v0.v0) + v(v1.v0), v2.v1 == u(v0.v1) + v(v1.v1)}, {u, v}]
        u = ((v1.v1)(v2.v0)-(v1.v0)(v2.v1)) / ((v0.v0)(v1.v1) - (v0.v1)(v1.v0))
        v = ((v0.v0)(v2.v1)-(v0.v1)(v2.v0)) / ((v0.v0)(v1.v1) - (v0.v1)(v1.v0))

      下面是用于编程的快速实现:

      

    // Compute vector,计算向量AC, AB, CP    
    v0 = C - A
    v1 = B - A
    v2 = P - A
    
    // Compute dot products 计算点乘
    dot00 = dot(v0, v0)
    dot01 = dot(v0, v1)
    dot02 = dot(v0, v2)
    dot11 = dot(v1, v1)
    dot12 = dot(v1, v2)
    
    // Compute barycentric coordinates 计算系数坐标
    invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
    u = (dot11 * dot02 - dot01 * dot12) * invDenom
    v = (dot00 * dot12 - dot01 * dot02) * invDenom
    
    // Check if point is in triangle 检测
    return (u >= 0) && (v >= 0) && (u + v < 1)

     

    技巧:

    (1)判定相交性:

      一般情况下, 空间三角形三个空间坐标确定三角形平面在三维空间的姿态。但是如果每个顶点,只计算(Y,Z)分量,则将三角形转化为YZ平面空间内的三角形。

      对于三给空间中的一条射线如(y=Y1, z=Z1),即在(Y,Z)确定的平面相当于一个(Y1,Z1)

      因此,判定射线与三角形平面的相交性,即转化为判定二维三角形平面中的点与三角形的位置关系。

    (2)如果相交,则求交点

      这样可以利用上述公式,求出交点。即得到与UV坐标,然后对原三角形三个定点,利用公式,仅仅对于X分量计算,即可求得交点的Xcut坐标。

      因此交点即为:(Xcut,Y,Z),空间坐标点。

      

      

    endl;

      

      

  • 相关阅读:
    营销运营中会遇到的名词及解释
    常用excel函数公式及操作示例
    opensuse安装pycharm
    Atom 基础使用
    git使用
    初学Python(第一课)
    django新手第一课
    浅谈session,cookie,sessionStorage,localStorage的区别及应用场景
    事件冒泡的应用
    django站点管理
  • 原文地址:https://www.cnblogs.com/icmzn/p/7273677.html
Copyright © 2011-2022 走看看