判断点是否在三角形内

  • 预备知识:
    • 向量点积:↑a·↑b=a1b1+a2b2+a3b3=|↑a|·|↑b|cosx,x为两向量夹角。
      • a·b>0 两向量方向基本相同,夹角在0°到90°之间
      • a·b=0 两向量正交,相互垂直
      • a·b<0 两向量方向基本相反,夹角在90°到180°之间
    • 向量叉积:↑a×↑b=(a2b3-a3b2)↑i+(a3b1-a1b3)↑j+(a1b2-a2b1)↑k=|↑a|·|↑b|sinx↑n,↑n为↑a×↑b方向。
      • ↑a与↑b的外积遵循右手定则:当右手的四指从a以不超过180度的转角转向b时,竖起的大拇指指向是c的方向。
    • 线性规划知识:
      • 直线两点式方程为 (y-y1)(x1-x2)-(y1-y2)(x-x1)=0
      • 当 (y-y1)(x1-x2)-(y1-y2)(x-x1)>0时,点(x,y)在直线的右侧
      • 当 (y-y1)(x1-x2)-(y1-y2)(x-x1)<0时,点(x,y)在直线的左侧

方向法1:

  • 思路: 点P是否在三角形abc内部,只需判断pa、pb的外积方向与pb、pc的外积方向与pc、pa的外积方向是否一致(主要依据外积方向确定时与两向量夹角是否超过180度)。
  • 代码:
#include<iostream>
using namespace std;
#include<vector>
#include<cassert>

/*
根据向量外积的公式计算外积
*/
vector<float> vec_out_product(vector<float> a, vector<float> b)
{
	vector<float> rec;
	assert(a.size() == 3 && b.size() == 3);
	
	rec.push_back(a[1] * b[2] - b[1] * a[2]);//外积计算公式:i向量值
	rec.push_back(b[0] * a[2] - a[0] * b[2]);//外积计算公式:j向量值
	rec.push_back(a[0] * b[1] - b[0] * a[1]);//外积计算公式:k向量值
	return rec;
}


/*
根据向量内积公式计算向量内积
*/
float vec_inn_product(vector<float> a, vector<float> b)
{
	assert(a.size() == 3 && b.size() == 3);
	return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
}

//判断点p是否在三角形abc内
bool point_in_tri(vector<float> a, vector<float> b, vector<float> c, vector<float> p)
{
	vector<float> pa = {a[0] - p[0], a[1] - p[1], a[2] - p[2]};
	vector<float> pb = { b[0] - p[0], b[1] - p[1], b[2] - p[2]};
	vector<float> pc = { c[0] - p[0], c[1] - p[1], c[2] - p[2] };

	vector<float> product_papb = vec_out_product(pa, pb);
	vector<float> product_pbpc = vec_out_product(pb, pc);
	vector<float> product_pcpa = vec_out_product(pc, pa);
	
	if (vec_inn_product(product_papb, product_pbpc) > 0  &&  vec_inn_product(product_papb, product_pcpa) > 0)
		return true;
	else
		return false;
}

int main(int argc, char* argv[])
{
	vector<float> a = {1.0f, 1.0f ,0.0f};
	vector<float> b = {3.0f, 5.0f, 0.0f};
	vector<float> c = {5.0f, 1.0f, 0.0f};
	vector<float> p = {1.1f, 1.1f, 0.0f};

	bool rec = point_in_tri(a, b, c, p);

	cout << "in tri :" << rec << endl;
	system("pause");
	return 0;
}

方向法2:

  • 根据线性规划的知识,点p在三角形abc内部,则点p、a在直线bc同侧,点p、b在直线ac同侧,点p、c在直线ab同侧。
  • 代码:
#include<iostream>
using namespace std;
#include<vector>
#include<cassert>


float judge_side(vector<float> a, vector<float> b, vector<float> q)
{
	//两点式直线方程下的线性规划
	return ((q[1] - a[1]) * (b[0] - a[0]) - (q[0] - a[0]) * (b[1] - a[1]));
}


bool point_in_tri(vector<float> a, vector<float> b, vector<float> c, vector<float> p)
{
	assert(a.size() == 2 && b.size() == 2 && c.size() == 2 && p.size() == 2);
	
	//judge point p and point c is on the same side of line ab, other point similarly.   

	if (judge_side(a, b, p) * judge_side(a, b, c) > 0 && judge_side(a, c, p) * judge_side(a, c, b) > 0 && judge_side(c, b, p) * judge_side(c, b, a) > 0)
		return true;
	else
		return false;
}

int main(int argc, char* argv[])
{
	vector<float> a = {1.0f, 1.0f };
	vector<float> b = {3.0f, 5.0f};
	vector<float> c = {5.0f, 1.0f};
	vector<float> p = {1.1f, 1.1f};

	bool rec = point_in_tri(a, b, c, p);

	cout << "in tri :" << rec << endl;
	system("pause");
	return 0;
}

面积法

  • 思路:
  • 点p若在三角形abc中,则所有子三角形pab、pac、pbc的面积和等于三角形abc的面积,否则不然(应该是大于三角形abc的面积)
  • 三角形的面积可以根据向量外积的公式求得(根据两向量外积的是两向量形成平行四边形的面积)
  • 向量外积计算时,按照三维向量求外积书写公式,将所有z=0带入公式即可得到二维平面上的向量外积的计算公式:
    在这里插入图片描述
  • 代码:
#include<iostream>
using namespace std;
#include<vector>
#include<cassert>
#include<cmath>

//calculate triangle area with vector out_porduct.
float cal_square(vector<float> a, vector<float> b, vector<float> p)
{
	vector<float> pa = {a[0] - p[0], a[1] - p[1]};
	vector<float> pb = { b[0] - p[0], b[1] - p[1] };
	return fabs(pa[0] * pb[1] - pa[1] * pb[0]) / 2;
}


bool point_in_tri(vector<float> a, vector<float> b, vector<float> c, vector<float> p)
{
	float sum_sqare = cal_square(a, b, p) + cal_square(b, c, p) + cal_square(a, c, p);
	float abc_sqare = cal_square(a, b, c);
	if (fabs(abc_sqare - sum_sqare) < 1e-5)
		return true;
	else
		return false;

}


int main(int argc, char* argv[])
{
	vector<float> a = {1.0f, 1.0f };
	vector<float> b = {3.0f, 5.0f};
	vector<float> c = {5.0f, 1.0f};
	vector<float> p = {2.1f, 4.1f};

	bool rec = point_in_tri(a, b, c, p);

	cout << "in tri :" << rec << endl;
	system("pause");
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值