Files
plct-lab/cross-checker/src/cross-checker.cpp

59 lines
1.6 KiB
C++

#include <cmath>
#include <algorithm>
#include "cross-checker.h"
// 计算向量叉积的方向
// 返回值:
// 0 表示三点共线
// 1 表示逆时针方向(正)
// -1 表示顺时针方向(负)
int cross_checker::Point::orientation(const Point& p, const Point& q, const Point& r)
{
const double val = (q.x - p.x) * (r.y - p.y) - (r.x - p.x) * (q.y - p.y);
if (std::fabs(val) < 1e-9) return 0; // 共线
return (val > 0) ? 1 : -1;
}
bool cross_checker::Point::onSegment(const Point& p, const Point& q, const Point& r)
{
return q.x <= std::max(p.x, r.x) && q.x >= std::min(p.x, r.x) &&
q.y <= std::max(p.y, r.y) && q.y >= std::min(p.y, r.y);
}
bool cross_checker::Line::intersect(const Line& other)
{
const int o1 = Point::orientation(startPoint, endPoint, other.startPoint);
const int o2 = Point::orientation(startPoint, endPoint, other.endPoint);
const int o3 = Point::orientation(other.startPoint, other.endPoint, startPoint);
const int o4 = Point::orientation(other.startPoint, other.endPoint, endPoint);
// 普通情况:跨立实验
if (o1 != o2 && o3 != o4)
{
return true;
}
// 特殊情况:共线
if (o1 == 0 && Point::onSegment(startPoint, other.startPoint, endPoint))
{
return true;
}
if (o2 == 0 && Point::onSegment(startPoint, other.endPoint, endPoint))
{
return true;
}
if (o3 == 0 && Point::onSegment(other.startPoint, startPoint, other.endPoint))
{
return true;
}
if (o4 == 0 && Point::onSegment(other.startPoint, endPoint, other.endPoint))
{
return true;
}
return false;
}