线段部分重合与完全重合判断算法

判断有限长线段是否部分重合

判断两线段是否有重合:仅有一个端点重合不算两线段重合,完全重合也算重合。

// 判断两线段是否有重合,仅有一个端点重合不算两线段重合,完全重合也算重合
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());
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值