如何判断一个点是否在一个任意三角形内部(最优算法)?

woxoxow 2002-08-04 10:10:38
已知该点坐标(x,y),
三角形三个顶点坐标(x1,y1),(x2,y2),(x3,y3).
直角坐标系:

0-------->X
|
|
|
\/
Y
...全文
2250 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
qinghero 2002-08-05
  • 打赏
  • 举报
回复
正好大学时学过计算机图形学:
当时老师介绍了两个方法,但楼上的老兄已经说出来了
一种是用矢量叉乘法:由三个顶点向所求的点引出矢量(注意方向),然后任意用其中两个矢量形成平面,再用这个平面和剩下的矢量叉乘,得出一个新矢量,方向向里,则在三角形外,反之在里面。
这种方法看似麻烦,但都有公式套入,并不是很复杂。

一种是行扫描法:
就是把三角形的三条边连起来,然后从要求的点从左向右引出射线,如果有奇数个交点,则在三角形内,否则在外面。但这种算法要注意的是:要考虑如果有三角形的一条边与水平线平行的问题,也就是边界问题。

至于是不是最有效率的,就不知道了。
madmanahong 2002-08-04
  • 打赏
  • 举报
回复
madmanahong@163.com
howtotell 2002-08-04
  • 打赏
  • 举报
回复
HRGN hrgn;
hrgn=CreatePolygonRgn(...)
if(PtInRegion(hrgn,px,py))
{
}
xyz119 2002-08-04
  • 打赏
  • 举报
回复
呵呵!
没看到前面已有人回答了。
xyz119 2002-08-04
  • 打赏
  • 举报
回复
最快最简单的方法:
用CRgn类。用CreatePolygonRgn传入三点坐标。用PtInRegion判断点是否在三角形内。
wistaria 2002-08-04
  • 打赏
  • 举报
回复
方法1:过该点作一条射线,然后判断该射线与三条边的相交情况;
方法2:分别连接P点和三个顶点A,B,C,然后判断矢量PA,PB,PC所夹角之和是否为360度,如果是360度则P在三角形内

1.
#include <stdio.h>
#include <math.h>

struct TPoint
{
float x;
float y;
};

float area(struct TPoint p1,struct TPoint p2,struct TPoint p3){
return fabs((p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y));
}

float mul(struct TPoint p1,struct TPoint p2,struct TPoint p0){
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}

int inside(struct TPoint tr[],struct TPoint p){
int i;
for (i=0;i<3;i++)
if (mul(p,tr[i],tr[(i+1)%3])*mul(p,tr[(i+2)%3],tr[(i+1)%3])>0)
return 0;
return 1;
}

int inside2(struct TPoint tr[],struct TPoint p){
if (fabs(area(tr[0],tr[1],tr[2])-
area(p,tr[1],tr[2])-
area(tr[0],p,tr[2])-
area(tr[0],tr[1],p))<1.0e-20)
return 1;
else
return 0;
}

main(){
struct TPoint tr[3]={{-1,1},{1,0},{3,0}},p={1,2};
printf("algorithm 1:");
if (inside(tr,p))
printf("In\n");
else
printf("Out\n");
printf("algorithm 2:");
if (inside2(tr,p))
printf("In\n");
else
printf("Out\n");
}

2
就是判断点到三个顶点的夹角之和为2*PI
// 返回1 表示在那,0表示在外
int inside3(const struct TPoint tr[], struct TPoint p)
{
TPoint p0,p1,p2;
p0.x = tr[0].x - p.x ; p0.y = tr[0].y - p.y;
p1.x = tr[1].x - p.x ; p1.y = tr[1].y - p.y;
p2.x = tr[2].x - p.x ; p2.y = tr[2].y - p.y;

double arg1 = acos((p0.x*p1.x + p0.y*p1.y)/sqrt(p0.x*p0.x + p0.y*p0.y)/sqrt(p1.x*p1.x+p1.y*p1.y));
double arg2 = acos((p0.x*p2.x + p0.y*p2.y)/sqrt(p0.x*p0.x + p0.y*p0.y)/sqrt(p2.x*p2.x+p2.y*p2.y));
double arg3 = acos((p2.x*p1.x + p2.y*p1.y)/sqrt(p2.x*p2.x + p2.y*p2.y)/sqrt(p1.x*p1.x+p1.y*p1.y));

if( fabs(2*3.1415926-arg1-arg2-arg3)<0.0001 ) return 1;
return 0;
}

In355Hz 2002-08-04
  • 打赏
  • 举报
回复
从该点引一射线,如果与该闭合曲线相交为奇数次,该点在曲线内...
不过应该不是最有效率的方法。
masterz 2002-08-04
  • 打赏
  • 举报
回复
first create a triangle region
BOOL CRgn::CreatePolygonRgn( LPPOINT lpPoints, int nCount, int nMode );
then use CRgn::PtInRegion to check
ironsmith 2002-08-04
  • 打赏
  • 举报
回复
如果分两步判断可能会快点,但是否是最优化算法我不知道:
1.以三角形的最上、最下、最左、最右的坐标值形成一个矩形,若点在此矩形之外肯定不在三角形内部。
2.若点在此矩形之内,再判断点与三角形三个顶点的脸先是否与三角形的线相交,若不则点在三角形内部。
Fanjj 2002-08-04
  • 打赏
  • 举报
回复
比较简单、效率较高的方法:
用三角形三个顶点按顺序生成三条线,
判断该点是否同时满足在三条线的左边
或右边,如果满足条件点在三角形内。


19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧