二维平面上判断点在三角形内的最优算法

  园子里有很多关于点是否在三角形内的文章,提供了各种方法。这让人很纠结,到底该用哪种算法?这里提供一套我认为最优的算法。如果你有不同的意见,亦或有更好的算法,欢迎来讨论。

  算法使用的是同向法,其原理是:假设点P位于三角形ABC内,会有这样一个规律:三角形的每一个边,其对角点与P在边的同一侧;或者说三角形的每一个顶点与P在其对角边的同一侧。

(1)代码

// 2D vector
class Vec2
{
public:
    Vec2()
    {
        x = 0.0f;
        y = 0.0f;
    }

    Vec2(float fx, float fy)
        :x(fx), y(fy)
    {
    }

    // Add
    Vec2 operator + (const Vec2& v) const
    {
        return Vec2(x + v.x, y + v.y);
    }

    // Subtract
    Vec2 operator - (const Vec2& v) const
    {
        return Vec2(x - v.x, y - v.y) ;
    }

public:
    float x, y;
};
 1 // Dot product
 2 inline float Vec2Dot(const Vec2& v1, const Vec2& v2)
 3 {
 4     return v1.x * v2.x + v1.y * v2.y;
 5 }
 6
 7 // Cross product
 8 inline float Vec2Cross(const Vec2& v1, const Vec2& v2)
 9 {
10     return v1.x * v2.y - v1.y * v2.x;
11 }
12
13 // Determine whether two vectors v1 and v2 point to the same direction
14 // 判断C和P在直线AB的同一侧
15 inline bool IsSameSide(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& P)
16 {
17     Vec2 AB = B - A;
18     Vec2 AC = C - A;
19     Vec2 AP = P - A;
20
21     float f1 = Vec2Cross(AB, AC);
22     float f2 = Vec2Cross(AB, AP);
23
24     // f1 and f2 should to the same direction
25     return f1*f2 >= 0.0f;
26 }
27
28 // Same side method
29 // Determine whether point P in triangle ABC
30 inline bool IsPointInTriangle(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& P)
31 {
32     return IsSameSide(A, B, C, P) &&
33         IsSameSide(B, C, A, P) &&
34         IsSameSide(C, A, B, P);
35 }
36
37 // Determine whether point P in angle ABC
38 // 点P是否在角ABC内
39 inline bool IsPointInAngle(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& P)
40 {
41     return IsSameSide(A, B, C, P) && IsSameSide(B, C, A, P);
42 }

算法中没有使用三角函数的调用,因为这一原因,我认为它是最优的算法。

(2)测试效果

我生成一幅1024*1024大小的图像,并设置三个顶点,对图像中的所有像素调用IsPointInAngle函数,以测试其效率:

图中显示出图像生成时间为868.758毫秒,这是DEBUG版本的。

时间: 2024-10-13 07:41:05

二维平面上判断点在三角形内的最优算法的相关文章

二维平面上判断点是否在三角形内

最近在项目中碰到的这个问题,在此记录一下.已知三角形的三个顶点坐标,判断某个点是否在三角形中(在三角形的边上,我们也视作在三角形中),本文给出了三种方法.   算法1 利用面积法,如上图所示,如果点P在三角形ABC的内部,则三个小三角形PAB, PBC, PAC的面积之和 = ABC的面积,反之则不相等. 已知三角形的三个顶点坐标求其面积,可以根据向量的叉乘,参考here. 该算法详见后面的函数:IsPointInTriangle1   算法2 首先看一下这个问题,如何判断某两个点在某条直线的同

9.7数学与概率(四)——在二维平面上,有一些点,请找出经过点数最多的那条线

/** * 功能:在二维平面上,有一些点,请找出经过点数最多的那条线. /** * 思路:在任意两点之间画一条无线长的直线,用散列表追踪那条直线出现的次数最多.时间复杂度O(N*N) * 注意: * 1)用斜率和y轴截距来确定是否是同一条直线. * 2)浮点数不一定能用二进制数准确表示,因此检查两个浮点数的差值是否在某个极小值(epsilon)内. * 3)对于散列表而言,斜率相等,未必散列值相同.因此,将斜率减去一个极小值,并以得到的结果flooredSlope作为散列键. * 4)取得所有可

数字之魅:寻找二维平面上的最近的点对

在二维平面上的n个点中,如何快速的找出最近的一对点,就是最近点对问题. 初看这个题,可能感觉有点儿复杂. 方案一:蛮力法.数组中总共包含N个数,所以我们可以把平面内所有的点按X轴排序,然后依次算出后一个坐标与前面所有左边的距离,然后用Min和position来记录最近的距离和两个坐标.该方案和在一维空间求两个最近点的距离有点儿类似,其时间复杂度为:O(N*N). 方案二:在一维空间里,我们知道如果数组有序,我们可以很快找出最近的两个点.我们可以用O(N*logN)的时间复杂度来对数据进行排序[快

9.7数学与概率(三)——在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分

/** * 功能:在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分. * 假定正方形的上下两条边与x轴平行. */ /** * 考虑: * 线的准确含义,可能性有: * 1)由斜率和y轴截距确定: * 2)由这条边上的任意两点确定: * 3)线段,以正方形的边作为起点和终点. * * 假设:这条线的端点应该落在正方形的边上. * 思路:要将两个正方形对半分,这条线必须连接两个正方形的中心点. */ public class Square { //正方形的四条边 int lef

编写一个表示二维平面上的点的类MyPoint,满足以下条件: 1、定义private的成员变量x和y,表示点的x和y坐标,类型为double

编写一个表示二维平面上的点的类MyPoint,满足以下条件:1.定义private的成员变量x和y,表示点的x和y坐标,类型为double2.定义两个MyPoint的构造方法,一个构造方法不带参数,而且x和y的初始值为0,另一个构造方法有两个参数,参数名为x和y,类型为double,用这两个参数分别作为初始x和y坐标3.定义一个getD方法,有一个类型为MyPoint的对象参数,功能为返回当前对象和参数对象这两个坐标点的距离,返回值为double类型4.编写测试的main方法,调用getD计算两

golang 二维平面求多重遮挡三角形总面积

解决问题描述:二维平面有很多三角形错落,可能会相互叠加落在一起,也可能互相远离.目标求出这些三角形的总占地面积. 我最开始想的解决方案是用总面积-总重叠面积 = 总占地面积.后来实现起来发现当面临多次重叠时,这样算是错误的. 后来参考了一些文献,得出结论:这个问题抽象出来就是求n个集合的并集问题.公式如下: A1∪A2∪......∪An = A1 + A2 + ......+ An ﹣(A1∩A2 + A1∩A3 + ......+ A[n-1]∩An) + (A1∩A2∩A3 + A1∩A2

几种方法判断平面点在三角形内

最近在做一个Unity实现的3D建模软件,其中需要在模型表面进行操作的时候,需要用到点和三角形位置关系的判定算法.由于一个模型往往是几千个三角片,所以这个判定算法必须高效,否则会影响最终程序的整体性能.这里记录一下一些算法,如有误请指出,谢谢! 首先假设点和三角形在同一平面内,如果不在同一平面,需要用其它方法先筛选. 常用的几种平面点-三角形位置关系判定方法有(以下算法执行必须先保证点和三角形位于同平面): 1.顺时针/逆时针判定法 该方法要求点的顺序是顺时针或逆时针的,如果是顺时针的点,沿着3

在二维平面上,有一些点。请找出经过点数最多的那条线

Line findBestLine(GraphPoint[] points) { Line bestLine =null; int bestCount=0; HashMap<Double ,ArrayList<Line>> linesBySlope= new HashMap<Double,ArrayList<Line>>(); for(int i=0;i<points.length;i++) { for(int j=i+1;j<points.le

POJ 3241 Object Clustering 二维平面曼哈顿距离最小生成树

题目链接:点击打开链接 题意: 给定二维平面上的n个点坐标,常数k 下面n行给出坐标 求一个最小生成树,问第k大的边是多少. 任意两个点间建一条边的花费是其曼哈顿距离. 思路:转自:点击打开链接 一.曼哈顿距离最小生成树 曼哈顿距离最小生成树问题可以简述如下: 给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价. 朴素的算法可以用O(N2)的Prim,或者处理出所有边做Kruskal,但在这里总边数有O(N2)条,所以Kruskal的复杂度变成了O(N2logN