向量和三角形

930 阅读4分钟

本文主要是记录一下,选择图形,即点在图形中的基础知识。

三角微元

要判断一个点(比如鼠标点)是否在一个封闭图形中,就是判断点是否在边界内部或者在组成图形的三角形内部。 由于可能有凹多边形,还是判断是否在三角形内比较靠谱。三角形是边数最少的多边形了, 一个图形不管你怎么分割,也不可能分出个两边形。三角形被分割后仍然是三角形。就叫它三角微元

为什么要分割为三角微元,当然是因为不规则的图形没有十分通用的更好的判断方法。

向量三角形

为了便于判断,我们需要给三角形一个方向。这个方向是顺时针还是逆时针不重要,重要的是知道它的方向

image.png

已知向量三角形ACB 的三条边 BA  AC  BC  总的来说就是顺时针方向,这个方向是顺时针还是逆时针不重要。重要的是知道它有方向。  

我们通过判断三角形的每一条边和点的关系,来判断点是否在三角形中。这就是同向法,不过,这种方法只适用于共面的点和三角形

 

向量和点之间的关系

这里拿边BA来举例说明。

P和向量BA其实只有两种关系(除开点在线上这种情况), 要么点在向量的左边,要么点在向量的右边。

这里的左右,是相对于BA方向朝上来说的。  PD1D2的情况是一样的都在右边。这个左右同样不重要。

因为我们现在不关心这个点和其他边的关系,所以是一样的。画出来是为了后续。

点和三角形

我们用点P和边BA组成新的三角形。 那么这个新的三角形同样也有方向,有法向量。

如果新的三角形BAP BAD和原来的三角形BAC 方向相同,那么这个点有可能在三角形内。

点在三角形内的充要条件是,点和三条边组成的三角形都和原本的三角形同向

只要有有一条边不满足,那么这个点就肯定不在三角形中。

具体的, 画一下 三角形 ACP CBP ,然后想象一下随着点p的移动,这些三角形方向的变化,就知道了。

前面说了,在共面的情况下,可以通过判断点P 是否在三边的同侧。在三维空间中,我们需要更强的约束。

可以通过, 判断点和三边组成的新的三角形的法向量是否同向来判断。 这里的法向量需要单位画,便于计算。 单位向量的点积为1,即为同向。

法向量同向,也就意味着,这四点共面了。 同时也意味着,新的三角形,其绘制方向和原三角形相同。 这就与点和向量的关系联系上了。 所以我们直接判断,新的三个三角形的法向量是否同向,就可以判断,点是否在三角形中 。

叉乘

三角形的方向, 可以确定这个三角形的平面的法向量。在右手坐标系中,叉乘遵循右手螺旋, x轴叉乘y轴得到z轴。四指缠绕的方向就是x轴到y轴, 结果就是大拇指的方向z轴。 我们这里只需要知道方向即可,不关心其他。

image.png

所以要判断两个三角形的方向, 只要判断他们的法向量的方向,也就是两条边的叉乘结果。

然后用向量点积的结果的来判断。平行向量的点积, 同向为正,反向为负。

    点积公式 a · b  = |a|*|b|*cosθ. 0的余弦值是1180度的余弦是值1.

代码示例

以下代码使用了three.js的数学库。

  import {
      Vector3,

   } from 'https://unpkg.com/three/build/three.module.js';

  const A = new Vector3(-6, 9, -4)
  const B = new Vector3(0, 9, 4)
  const C = new Vector3(6, 9, -4)
  const triangle = [A, B,C]
  
  function inTriangle(M, triangle){
      let bool = true 
      for (let i =0; i< 3;i++){
          const j = (i+1)%3
          const [a,b] = [triangle[i], triangle[j]] 
          const ma = a.clone().sub(M)
          const ab = b.clone().sub(a)
          /* 这种叉乘 相当于把用点和三角形的一条边组成了新的三角形 如果新的三角形的方向和三角形的方向相反 这个点肯定就不在三角形内 */
          const d = ma.clone().cross(ab)
          const len = d.dot(n)
          if(len < 0){
              return bool= false
          }
      }
      return bool 
  }