解析几何:计算两条线段的交点

news/2024/11/20 6:37:05/

大家好,我是前端西瓜哥。

今天来实现计算两条线段的交点的解析几何算法。

我们要实现 getLineSegIntersection 方法:提供两条线段,计算它们的交点。

每条线段会用两个点坐标表示。

const getLineSegIntersection = (p1, p2, p3, p4) => {// 待实现
}// 测试用例
getLineSegIntersection({ x: 1, y: 1 }, { x: 4, y: 4 },{ x: 1, y: 4 }, { x: 4, y: 1 }
);
// 期望 { x: 2.5, y: 2.5 }

思路

思路很简单,就是解两条直线对应的一个二元一次方程组,求出 x 和 y

如果无解或多解,说明直线平行,交点不存在。

如果有解,可拿到唯一交点,但也只能说明直线有交点,还需要判断线段是否有交点。

所以我们需要判断交点是否在线段的区间上。如果是,说明两线段有交点,返回交点。

克拉姆法则

解方程组需要用到 克拉姆法则

对于:

可转换为矩阵形式表示:

然后计算主矩阵(最左边的矩阵)的行列式,对角相乘然后相减:

如果行列式为 0,说明没有唯一解;

如果不为 0,则有唯一解:

回到我们的两条直线,我们用两点式表示直线:

转换成 Ax+By=C 的格式,得到:

image-20231012020643096

于是:

const a = y2 - y1;
const b = x1 - x2;
const c = x1 * y2 - x2 * y1;

第二条线段同理:

const d = y4 - y3;
const e = x3 - x4;
const f = x3 * y4 - x4 * y3;

算法实现

interface Point {x: number;y: number;
}const getLineSegIntersection = (p1: Point,p2: Point,p3: Point,p4: Point
): Point | null => {const { x: x1, y: y1 } = p1;const { x: x2, y: y2 } = p2;const { x: x3, y: y3 } = p3;const { x: x4, y: y4 } = p4;const a = y2 - y1;const b = x1 - x2;const c = x1 * y2 - x2 * y1;const d = y4 - y3;const e = x3 - x4;const f = x3 * y4 - x4 * y3;// 计算分母const denominator = a * e - b * d;// 判断分母是否为 0(代表平行)if (Math.abs(denominator) < 0.000000001) {// 这里有个特殊的重叠但只有一个交点的情况,可以考虑处理一下return null;}const px = (c * e - f * b) / denominator;const py = (a * f - c * d) / denominator;// 判断交点是否在两个线段上if (px >= Math.min(x1, x2) &&px <= Math.max(x1, x2) &&py >= Math.min(y1, y2) &&py <= Math.max(y1, y2) &&px >= Math.min(x3, x4) &&px <= Math.max(x3, x4) &&py >= Math.min(y3, y4) &&py <= Math.max(y3, y4)) {return { x: px, y: py };}return null;
};

变体

这个算法可以做一些变体,实现其他的算法。

变体1:两线段是否有交点

返回值换成布尔值即可。

判断两线段是否有交点,我之前还写了另一种解法,感兴趣可以看看:

《几何算法:判断两条线段是否相交》

变体2:计算两直线的交点

把判断直线交点是否在线段上的逻辑去掉,然后直接返回点坐标即可。

优化点

1、重叠但却只有一个交点的情况

如果线段平行,有两种情况:

  1. 没有重叠(0 个解)
  2. 有部分重叠(多解)

如果部分重叠,可能有多个点,多个点的情况下也不知道拿哪个点作为交点好,这种情况下还是返回 null。

但有一个特殊的情况:重叠只有一个点(比如线段 a 的末点刚好是线段 b 的起点)。如果你的场景下判断比较严格,你可以选择返回这个点。要实现这部分也是有点点复杂的。

2、误差处理。线段的两个端点的距离非常小,计算出的结果也会非常小,可能会进入了 0 的绝对误差范围了,考虑改成相对误差。

3、溢出风险。数值很大时有溢出风险,可以考虑计算一个缩放值,缩小后计算,计算完再放大回去。

结尾

总结一下,求两线段的交点,本质就是解方程,需要用到克莱姆法则,计算出来的交点是直线交点,不一定是线段交点,需要在判断点是否在线段范围内。

不复杂,就是有一点点小细节。

我是前端西瓜哥,欢迎关注我,学习更多解析几何知识。


http://www.ppmy.cn/news/1158407.html

相关文章

2023年10月工作经验及问题整理总结

目录 1.window自带的base64加密解密 2.ElementUI修改鼠标移动到表格的背景色 3.vscode保存时几万个eslint错误 4.Git 拉取Gitee仓库报错&#xff1a;“fatal: unable to access ": Failed to connect to 127.0.0.1 port 1080: Connection r... 4.1本地查看Git是否使用…

十五届蓝桥选拔赛Scratch-2023.08.20STEMA测评试题解析

2023年8月20日举行的第15届蓝桥杯STEMA测评Scratch编程中级组 T2 飞驰的高铁 具体要求: 1). 点击绿旗,角色、背景如图所示; 2). 按下一次数字1按键之后,画面中的景色持续向左侧水平移动(参照程序演示视频); 3). 按下一次数字2按键之后,程序结束。 评判标准: 5分:…

nginx正反向代理,负载均衡

Nginx 正向代理&#xff0c;反向代理 &#xff0c;负载均衡 Nginx有两种代理协议 七层代理&#xff08;http协议&#xff09; 四层代理&#xff08;tcp/udp流量转发&#xff09; 四层代理七层代理概念 四层代理 四层代理&#xff1a;基于tcp/ip协议层的转发代理方式&#…

【计网】计算机网络概述

目录 一、计算机网络的概念 二、计算机网络的组成 1、从组成部分上看 2、从工作方式上看 3、从功能组成上看 三、计算机网络的功能 1、数据通信 2、资源共享 3、分布式处理 4、提高可用性 5、负载均衡 四、计算机网络的分类 1、按分布范围 1.广域网 2.城域网 3.…

FPGA基于1G/2.5G Ethernet PCS/PMA or SGMII实现 UDP 网络视频传输,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、我这里已有的以太网方案3、设计思路框架视频源选择OV5640摄像头配置及采集动态彩条UDP协议栈UDP视频数据组包UDP协议栈数据发送UDP协议栈数据缓冲IP地址、端口号的修改Tri Mode Ethernet MAC1G/2.5G Ethernet PCS/PMA or SGMIIQT上位机和源…

好未来sre面经

好未来sre CDN DNS&#xff08;域名系统&#xff09;底层使用的是UDP&#xff08;用户数据报协议&#xff09;。 服务器响应慢怎么排查 检查网络连接&#xff1a;确保服务器与网络连接稳定&#xff0c;没有网络故障或带宽限制。可以尝试使用其他设备或工具测试网络连接。 检…

CentOS 7 上划分vlan复用接口配置多个ip地址——筑梦之路

需求场景 局域网内有一台服务器CentOS 7 系统&#xff0c;系统上只有一个网络接口&#xff0c;现需要在这台机器上配置多个ip地址&#xff0c;这些ip地址已经在交换机内配置&#xff0c;划分了不同vlan&#xff0c;但是这些vlan之间是互相不通的&#xff0c;应该在该系统上如何…

MDK Keil开发时出现问题汇总与解决办法--实战成功解决

文章目录 问题1&#xff1a;Error :Flash Download failed "Cortex-M4" 出现无法烧录问题点击烧录时出现下述图片&#xff1a;问题分析&#xff1a;发现没有添加编程算法描述&#xff1a;正确的情况是下面的点击Add按钮&#xff0c;选择主Flash添加&#xff1a;编译后…