判断有限长线段是否部分重合
判断两线段是否有重合:仅有一个端点重合不算两线段重合,完全重合也算重合。
// 判断两线段是否有重合,仅有一个端点重合不算两线段重合,完全重合也算重合
const bool Geo::is_coincide(const Point &start0, const Point &end0, const Point &start1, const Point &end1)
{
if ((start0 == start1 && end0 == end1) || (start0 == end1 && end0 == start0))
{
return true;
}
if (start0.x == end0.x)
{
if (start1.x == end1.x && start0.x == start1.x)
{
const bool result0 = (start1.y < start0.y && start0.y < end1.y)
|| (end1.y < start0.y && start0.y < start1.y);
const bool result1 = (start1.y < end0.y && end0.y < end1.y)
|| (end1.y < end0.y && end0.y < start1.y);
const bool result2 = (start0.y < start1.y && start1.y < end0.y)
|| (end0.y < start1.y && start1.y < start0.y);
const bool result3 = (start0.y < end1.y && end1.y < end0.y)
|| (end0.y < end1.y && end1.y < start0.y);
return result0 || result1 || result2 || result3;
}
else
{
return false;
}
}
else if (start0.y == end0.y)
{
if (start1.y == end1.y && start0.y == start1.y)
{
const bool result0 = (start1.x < start0.x && start0.x < end1.x)
|| (end1.x < start0.x && start0.x < start1.x);
const bool result1 = (start1.x < end0.x && end0.x < end1.x)
|| (end1.x < end0.x && end0.x < start1.x);
const bool result2 = (start0.x < start1.x && start1.x < end0.x)
|| (end0.x < start1.x && start1.x < start0.x);
const bool result3 = (start0.x < end1.x && end1.x < end0.x)
|| (end0.x < end1.x && end1.x < start0.x);
return result0 || result1 || result2 || result3;
}
else
{
return false;
}
}
const double a0 = end0.y - start0.y,
b0 = start0.x - end0.x,
c0 = end0.x * start0.y - start0.x * end0.y;
const double a1 = end1.y - start1.y,
b1 = start1.x - end1.x,
c1 = end1.x * start1.y - start1.x * end1.y;
if (std::abs(a0 * b1 - a1 * b0) < Geo::EPSILON && std::abs(a0 * c1 - a1 * c0) < Geo::EPSILON
&& std::abs(b0 * c1 - b1 * c0) < Geo::EPSILON)
{
return Geo::distance((start0 + end0) / 2, (start1 + end1) / 2) * 2
< Geo::distance(start0, end0) + Geo::distance(start1, end1);
}
else
{
return false;
}
}
判断有限长线段是否与多边形某一边重合
// 判断有限长线段是否与多边形某一边重合
const bool Geo::is_coincide(const Point &start, const Point &end, const Polygon &polygon)
{
const size_t index0 = polygon.index(start.x, start.y), index1 = polygon.index(end.x, end.y);
if (std::max(index0, index1) - std::min(index0, index1) == 1)
{
return true;
}
if (index0 < SIZE_MAX)
{
return Geo::is_coincide(start, end, start, polygon.last_point(index0))
|| Geo::is_coincide(start, end, start, polygon.next_point(index0));
}
else if (index1 < SIZE_MAX)
{
return Geo::is_coincide(start, end, end, polygon.last_point(index1))
|| Geo::is_coincide(start, end, end, polygon.next_point(index1));
}
else
{
for (size_t i = 1, count = polygon.size(); i < count; ++i)
{
if (Geo::is_coincide(start, end, polygon[i - 1], polygon[i]))
{
return true;
}
}
return false;
}
}
判断一个有限长线段是否是另一个有限长线段的一部分(完全重合)
// 判断一个有限长线段是否是另一个有限长线段的一部分
const bool Geo::is_part(const Point &start0, const Point &end0, const Point &start1, const Point &end1)
{
if (Geo::is_coincide(start0, end0, start1, end1))
{
if (start0.x == end0.x)
{
const double top0 = std::max(start0.y, end0.y), bottom0 = std::min(start0.y, end0.y);
const double top1 = std::max(start1.y, end1.y), bottom1 = std::min(start1.y, end1.y);
return bottom1 <= bottom0 && bottom0 <= top1 && bottom1 <= top0 && top0 <= top1;
}
else
{
const double left0 = std::min(start0.x, end0.x), right0 = std::max(start0.x, end0.x);
const double left1 = std::min(start1.x, end1.x), right1 = std::max(start1.x, end1.x);
return left1 <= left0 && left0 <= right0 && left1 <= right0 && right0 <= right1;
}
}
else
{
return false;
}
}
// 判断一个有限长线段是否是另一个有限长线段的一部分
const bool Geo::is_part(const Line &line0, const Line &line1)
{
return Geo::is_part(line0.front(), line0.back(), line1.front(), line1.back());
}