预备知识:
向量点积:↑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 ] ) ;
rec. push_back ( b[ 0 ] * a[ 2 ] - a[ 0 ] * b[ 2 ] ) ;
rec. push_back ( a[ 0 ] * b[ 1 ] - b[ 0 ] * a[ 1 ] ) ;
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 ] ) ;
}
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 ) ;
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>
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 ;
}