我正在解决一个确定点是否在三角形内的经典问题,而我正在使用重心坐标方法。 由于某种原因(我认为这是逻辑,而不是精度)它没有通过所有测试。 可能有什么不对?
代码是这样的:
#include <iostream>
using namespace std;
struct point
{
int x;
int y;
};
bool Place(point &A, point &B, point &C, point &P)
{
double det = (B.y - C.y)*(A.x - C.x) + (C.x - B.x)*(A.y - C.y);
double factor_alpha = (B.y - C.y)*(P.x - C.x) + (C.x - B.x)*(P.y - C.y);
double factor_beta = (C.y - A.y)*(P.x - C.x) + (A.x - C.x)*(P.y - C.y);
double alpha = factor_alpha / det;
double beta = factor_beta / det;
double gamma = 1.0 - alpha - beta;
bool In = false;
if (((A.x == P.x) & (A.y == P.y)) | ((B.x == P.x) & (B.y == P.y)) | ((C.x == P.x) & (C.y == P.y)))
In = true; // the sneaky guys are trying to see if the vertice of the triangle belongs to it
// the problem statement says it does.
if ((alpha == 0) | (beta == 0) | (gamma == 0))
In = true; // the point is on the edge of the triangle
if (( (0 < alpha) & (alpha < 1)) & ((0 < beta) & (beta < 1)) & ((0 < gamma) & (gamma < 1)))
In = true; // in this case P is actually within the triangle area
return In;
}
int main()
{
point A, B, C, P;
cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> P.x >> P.y;
Place(A, B, C, P) ? cout << "In\n" : cout << "Out\n";
return 0;
}
答案 0 :(得分:1)
您的逻辑表明,如果alpha
,beta
或gamma
中至少有一个为0,则该点就在边缘。
这是必要但不充分的;其他的也必须在[0, 1]
区间。
由于您对&#34; edge&#34;不感兴趣具体而言,你可以写
if (0 <= alpha && alpha <= 1 && 0 <= beta && beta <= 1 && 0 <= gamma && gamma <= 1)
In = true;
(我删除了一些括号,并用逻辑&
替换了按位&&
。)
可读性建议:
引入一些函数使得代码看起来更像是一个数学定义:
bool operator ==(const point& a, const point& b)
{
return a.x == b.x && a.y == b.y;
}
bool within(double x)
{
return 0 <= x <= 1;
}
bool Place(const point &A, const point &B, const point &C, const point &P)
{
double det = (B.y - C.y)*(A.x - C.x) + (C.x - B.x)*(A.y - C.y);
double factor_alpha = (B.y - C.y)*(P.x - C.x) + (C.x - B.x)*(P.y - C.y);
double factor_beta = (C.y - A.y)*(P.x - C.x) + (A.x - C.x)*(P.y - C.y);
double alpha = factor_alpha / det;
double beta = factor_beta / det;
double gamma = 1.0 - alpha - beta;
return P == A || P == B || P == C || (within(alpha) && within(beta) && within(gamma));
}
答案 1 :(得分:1)
尝试此功能(假设您有一个Point
类模板,其中T
是存储类型,并且您已经超载operator*
来计算点积:)
template <typename T>
bool is_point_in_triangle(const Point<3,T>& p,
const Point<3,T>& a,
const Point<3,T>& b,
const Point<3,T>& c) {
typedef Point<3,T> point_type;
point_type v0 = b-a, v1 = c-a, v2 = p-a;
T d00 = v0*v0;
T d01 = v0*v1;
T d11 = v1*v1;
T d20 = v2*v0;
T d21 = v2*v1;
T denom = d00*d11 - d01*d01;
// compute parametric coordinates
Real v = (d11 * d20 - d01 * d21) / denom;
Real w = (d00 * d21 - d01 * d20) / denom;
return v >= 0. && w >= 0. && v + w <= 1.;
}
作为旁注,您使用int
来存储坐标,因此截断时您的测试可能会失败?
祝你好运!