You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

四点构成的两条直线相交判断程序优化及问题排查请求

判断两条直线(线段)是否存在交点的简便实现及问题修复

给定四个点坐标,将前两点连成一条线段、后两点连成另一条线段,判断二者是否存在交点。针对你原程序的问题,这里给出更鲁棒的实现方案,并分析原代码的问题:

原程序的核心问题

  • 错误处理垂直x轴的线段:原代码遇到x1 == x2或x3 == x4直接exit(0),但垂直x轴的线段是合法的;且直接用浮点数==判断相等存在精度误差,应该用极小阈值(如fabs(x1-x2) < 1e-8)判断。
  • 未处理线段重合/共线情况:原代码仅通过斜率和截距计算交点,完全忽略了两条线段共线且重叠的场景。
  • 区间判断逻辑漏洞:原代码仅验证交点的x坐标是否在线段区间内,未同步验证y坐标,存在误判可能。

更简便鲁棒的实现:向量叉积法

向量叉积可以避免除法运算,无需处理斜率不存在的情况,还能精准判断线段的位置关系(相交、平行、共线重合)。

原理简述

对于两点构成的向量vec1 = (x2-x1, y2-y1)和vec2 = (x3-x1, y3-y1),叉积计算规则为:

double cross(double x1, double y1, double x2, double y2, double x3, double y3) {
    return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
}
  • 叉积绝对值小于极小阈值:两点与基准点共线;
  • 叉积正负:判断点在直线的哪一侧。

对于线段L1(A1,A2)和L2(A3,A4):

  1. 计算四个叉积:c1 = cross(A1,A2,A3)、c2 = cross(A1,A2,A4)、c3 = cross(A3,A4,A1)、c4 = cross(A3,A4,A2);
  2. 若c1和c2异号,且c3和c4异号,则两线段相交;
  3. 若存在叉积为0,则判断对应点是否在线段上(覆盖共线重合的情况)。

完整C++代码

#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

const double EPS = 1e-8; // 处理浮点数精度的极小阈值

// 计算向量叉积:(A2-A1) × (P-A1)
double cross(double x1, double y1, double x2, double y2, double x3, double y3) {
    return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
}

// 判断点(x,y)是否在线段(x1,y1)-(x2,y2)上
bool isPointOnSegment(double x, double y, double x1, double y1, double x2, double y2) {
    // 先判断是否共线
    if (fabs(cross(x1, y1, x2, y2, x, y)) > EPS) {
        return false;
    }
    // 再判断坐标是否在线段的区间内
    return (min(x1, x2) - EPS <= x && x <= max(x1, x2) + EPS) &&
           (min(y1, y2) - EPS <= y && y <= max(y1, y2) + EPS);
}

// 判断两条线段是否有交点
bool hasIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
    double c1 = cross(x1, y1, x2, y2, x3, y3);
    double c2 = cross(x1, y1, x2, y2, x4, y4);
    double c3 = cross(x3, y3, x4, y4, x1, y1);
    double c4 = cross(x3, y3, x4, y4, x2, y2);

    // 情况1:两线段互相跨立,直接相交
    if (c1 * c2 < -EPS && c3 * c4 < -EPS) {
        return true;
    }

    // 情况2:其中一个线段的端点在另一个线段上
    if (isPointOnSegment(x3, y3, x1, y1, x2, y2)) return true;
    if (isPointOnSegment(x4, y4, x1, y1, x2, y2)) return true;
    if (isPointOnSegment(x1, y1, x3, y3, x4, y4)) return true;
    if (isPointOnSegment(x2, y2, x3, y3, x4, y4)) return true;

    // 其他情况:平行或无交点
    return false;
}

int main() {
    double x1, y1, x2, y2, x3, y3, x4, y4;
    cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> x4 >> y4;

    cout << (hasIntersection(x1, y1, x2, y2, x3, y3, x4, y4) ? "1" : "0") << endl;

    return 0;
}

代码优势

  • 避免除法运算,彻底解决斜率不存在的问题;
  • 用EPS处理浮点数精度误差,避免因精度问题导致的误判;
  • 覆盖所有场景:相交、共线重合、端点在另一条线段上、平行无交点;
  • 逻辑清晰,易于维护和扩展。

内容的提问来源于stack exchange,提问作者Arash Alipoor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:05:16