【几何数学】【Python】【C++】判断两条线段是否相交,若相交则求出交点坐标

news2024/11/24 12:31:38

判断线段是否相交的办法(使用了向量叉积的方法):

首先,通过给定的线段端点坐标p1、p2、p3和p4构建了四个向量v1、v2、v3和v4:
v1表示从p1指向p2的向量,其分量为[p2[0] - p1[0], p2[1] - p1[1]]。
v2表示从p3指向p4的向量,其分量为[p4[0] - p3[0], p4[1] - p3[1]]。
v3表示从p1指向p3的向量,其分量为[p3[0] - p1[0], p3[1] - p1[1]]。
v4表示从p1指向p4的向量,其分量为[p4[0] - p1[0], p4[1] - p1[1]]。
接下来,计算了两个叉积cross1和cross2:
cross1表示v1和v3的叉积,计算公式为v1[0] * v3[1] - v1[1] * v3[0]。
cross2表示v1和v4的叉积,计算公式为v1[0] * v4[1] - v1[1] * v4[0]。
最后,根据两个叉积的乘积进行判断:
如果cross1和cross2的乘积小于等于0,意味着v1和v3位于不同的半平面或者其中一个线段的某个端点在另一个线段上,这时可以判断两条线段相交。
如果cross1和cross2的乘积大于0,意味着v1和v3位于同一侧或者两个线段没有交点,这时可以判断两条线段不相交。
根据以上逻辑,如果条件满足,则返回True表示线段相交,否则返回False表示线段不相交。

Python代码实现:

def are_lines_intersect(p1, p2, p3, p4):
    v1 = [p2[0] - p1[0], p2[1] - p1[1]]
    v2 = [p4[0] - p3[0], p4[1] - p3[1]]
    v3 = [p3[0] - p1[0], p3[1] - p1[1]]
    v4 = [p4[0] - p1[0], p4[1] - p1[1]]

    cross1 = v1[0] * v3[1] - v1[1] * v3[0]
    cross2 = v1[0] * v4[1] - v1[1] * v4[0]

    if cross1 * cross2 <= 0:
        return True
    else:
        return False


def compute_intersection(p1, p2, p3, p4):
    if p1[0] == p2[0]:  # p1p2为垂直线
        x = p1[0]
        slope2 = (p4[1] - p3[1]) / (p4[0] - p3[0])
        intercept2 = p3[1] - slope2 * p3[0]
        y = slope2 * x + intercept2
    elif p3[0] == p4[0]:  # p3p4为垂直线
        x = p3[0]
        slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0])
        intercept1 = p1[1] - slope1 * p1[0]
        y = slope1 * x + intercept1
    else:
        slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0])
        slope2 = (p4[1] - p3[1]) / (p4[0] - p3[0])
        intercept1 = p1[1] - slope1 * p1[0]
        intercept2 = p3[1] - slope2 * p3[0]
        x = (intercept2 - intercept1) / (slope1 - slope2)
        y = slope1 * x + intercept1

    return [x, y]


if __name__ == '__main__':
    p1 = [10, 20]
    p2 = [0, 100]
    p3 = [100, 50]
    p4 = [200, 30]
    # p1 p2 是一条线段
    # p3 p4 是另一条线段
    # 判断是否相交,相交且求交点
    if are_lines_intersect(p1, p2, p3, p4):
        print(compute_intersection(p1, p2, p3, p4))
        x, y = compute_intersection(p1, p2, p3, p4)
    else:
        print("No intersection")

    # 画图
    import matplotlib.pyplot as plt

    plt.plot([p1[0], p2[0]], [p1[1], p2[1]], color='r')
    plt.plot([p3[0], p4[0]], [p3[1], p4[1]], color='b')
    # 加注释
    plt.annotate('p1', xy=(p1[0], p1[1]), xytext=(p1[0] + 10, p1[1] + 10))
    plt.annotate('p2', xy=(p2[0], p2[1]), xytext=(p2[0] + 10, p2[1] + 10))
    plt.annotate('p3', xy=(p3[0], p3[1]), xytext=(p3[0] + 10, p3[1] + 10))
    plt.annotate('p4', xy=(p4[0], p4[1]), xytext=(p4[0] + 10, p4[1] + 10))
    try:
        # 绘制交点
        plt.scatter(x, y, color='g')
        # 给交点加注释
        plt.annotate('intersection', xy=(x, y), xytext=(x + 10, y + 10),
                     arrowprops=dict(facecolor='g', shrink=0.05))
    except:
        pass
    # 坐标轴等距
    plt.axis('equal')
    plt.show()


绘制的图:
在这里插入图片描述
在这里插入图片描述
不相交:
在这里插入图片描述

C++ 借助opencv的数据结构

// are_lines_intersect: 判断两条线段是否相交
// 原理:判断两条线段的端点是否在另一条线段的两侧
bool are_lines_intersect(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3, cv::Point2f p4) {
    cv::Point2f v1 = p2 - p1;
    cv::Point2f v2 = p4 - p3;
    cv::Point2f v3 = p3 - p1;
    cv::Point2f v4 = p4 - p1;
    float cross1 = v1.x * v3.y - v1.y * v3.x;
    float cross2 = v1.x * v4.y - v1.y * v4.x;
    if (cross1 * cross2 <= 0) {
        return true;
    } else {
        return false;
    }
}
// compute_intersection: 计算两条线段的交点
// 原理:计算两条线段的斜率和截距,然后解方程
cv::Point2f compute_intersection(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3, cv::Point2f p4) {
    cv::Point2f intersection;
    if (p1.x == p2.x) {
        intersection.x = p1.x;
        float slope2 = (p4.y - p3.y) / (p4.x - p3.x);
        float intercept2 = p3.y - slope2 * p3.x;
        intersection.y = slope2 * intersection.x + intercept2;
    } else if (p3.x == p4.x) {
        intersection.x = p3.x;
        float slope1 = (p2.y - p1.y) / (p2.x - p1.x);
        float intercept1 = p1.y - slope1 * p1.x;
        intersection.y = slope1 * intersection.x + intercept1;
    } else {
        float slope1 = (p2.y - p1.y) / (p2.x - p1.x);
        float slope2 = (p4.y - p3.y) / (p4.x - p3.x);
        float intercept1 = p1.y - slope1 * p1.x;
        float intercept2 = p3.y - slope2 * p3.x;
        intersection.x = (intercept2 - intercept1) / (slope1 - slope2);
        intersection.y = slope1 * intersection.x + intercept1;
    }
    return intersection;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/709628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Camtasia Studio2023标准版屏幕录制和视频剪辑软件

Camtasia Studio2023提供了强大的屏幕录像、视频的剪辑和编辑、视频菜单制作、视频剧场和视频播放功能等。它能在任何颜色模式下轻松地记录屏幕动作&#xff0c;包括影像、音效、鼠标移动的轨迹&#xff0c;解说声音等等&#xff0c;另外&#xff0c;它还具有及时播放和编辑压缩…

[前端]JS——join()与split()的使用

Array.join():数组转换为字符串,"()"里元素指定数组转为字符串用什么串联&#xff0c;默认为空。 Array.join()的使用&#xff1a; <script>let arr[1,2,3,4]console.log("arr未转换前:",arr,typeof(arr));console.log("arr使用join():"…

Netty核心技术八--Netty编解码器和handler的调用机制

1.基本说明 netty的组件设计&#xff1a;Netty的主要组件有Channel、EventLoop、ChannelFuture、 ChannelHandler、ChannelPipe等 ChannelHandler充当了处理入站和出站数据的应用程序逻辑的容器。 例如&#xff0c;实现ChannelInboundHandler接口&#xff08;或ChannelInbound…

Typora图床配置-OSS对象存储

Typora图床配置-OSS对象存储 1.PicGo下载 下载地址&#xff1a; Release 2.3.0 Molunerfinn/PicGo GitHub https://github.com/Molunerfinn/PicGo/releases/tag/v2.3.1 下载如下&#xff1a; 2.安装和配置 进入阿里云创建OSS对象存储服务。 设置为公共读才能被别人访问到。…

树与图的深度优先遍历

树的重心 本题的本质是树的dfs&#xff0c; 每次dfs可以确定以u为重心的最大连通块的节点数&#xff0c;并且更新一下ans。 也就是说&#xff0c;dfs并不直接返回答案&#xff0c;而是在每次更新中迭代一次答案。 这样的套路会经常用到&#xff0c;在 树的dfs 题目中 #includ…

IMU 互补滤波

IMU学名惯性测量单元&#xff0c;所有的运动都可以分解为一个直线运动和一个旋转运动&#xff0c;故这个惯性测量单元就是测量这两种运动&#xff0c;直线运动通过加速度计可以测量&#xff0c;旋转运动则通过陀螺。 void IMUupdate(float gx, float gy, float gz, float ax,fl…

Go 语言 context 都能做什么?

原文链接&#xff1a; Go 语言 context 都能做什么&#xff1f; 很多 Go 项目的源码&#xff0c;在读的过程中会发现一个很常见的参数 ctx&#xff0c;而且基本都是作为函数的第一个参数。 为什么要这么写呢&#xff1f;这个参数到底有什么用呢&#xff1f;带着这样的疑问&am…

postgresql数据库登录代理解析(包含登录协议包解析)

文章目录 postgresql数据库登录代理解析&#xff08;包含登录协议包解析&#xff09;背景描述版本不同对应的账号密码加密目标解析方法相关代码位置断点关键位置及相关重要变量 登录通信流程&#xff08;SCRAM-SHA-256方式&#xff09;代码实现相关参考资料 postgresql数据库登…

Python count()函数详解

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 count 1、指定搜索位置2、参数为负数3、列表的coun…

以太网OSI参考模型(四)

目录 OSI模型 一、物理层 二、数据链路层 三、网络层 四、传输层 五、会话层 六、表示层 七、应用层 OSI模型 OSI七层模型&#xff0c;是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)1984年联合制定的开放系统互联参考模型&#xff0c;为开放式互联信息系统提供…

06-C++学习笔记-指针的定义与使用

指针是C中非常重要的概念&#xff0c;它允许直接访问内存地址&#xff0c;并通过地址操作变量。本篇笔记将介绍指针的定义与使用方法&#xff0c;以及指针与数组的关系。 1️⃣ 指针的引入 指针的引入是为了解决需要直接访问内存地址的情况。通过指针&#xff0c;可以间接访问…

Android TextView 展示特殊字符高度变高问题解决

背景 #在我们的项目中&#xff0c;展示文字是很常见的需求&#xff0c;但是在线上展示中发现&#xff0c;有些信息是特殊字符展示的&#xff0c;而且这些字符的高度会导致TextView的高度变高&#xff08;与正常字符比&#xff09;。 效果如下&#xff1a; 很明显&#xff0…

森云+优控配置摄像头进行录像和拍照测试

森云和优控配置摄像头进行录像和拍照测试 现在其实已经基本上明确自己的环境了&#xff0c;就是在ubuntu下的pycharm和vscode&#xff0c;然后下载conda&#xff08;但是不要默认的base环境&#xff0c;只要conda create -n xxx 这样的基本功能就好了&#xff09; 显示opencv…

AI绘画StableDiffusion:云端在线版使用笔记分享(Kaggle版)

玩AI绘画&#xff08;SD&#xff09;&#xff0c;自己电脑配置不够&#xff1f;今天给大家介绍一下如何baipiao在线版AI绘画StableDiffusion。 Kaggle 是世界上最大的数据科学社区&#xff0c;拥有强大的工具和资源&#xff0c;可帮助您实现数据科学目标。&#xff08;每周可以…

【MySQL学习笔记】(六)MySQL基本查询

表的增删查改 1 create1.1 单行数据全列插入1.2 多行数据 指定列插入1.3 插入否则更新1.4 替换 2 retrieve2.1 select列2.1.1 全列查询2.2.2 指定列查询2.2.3 查询字段为表达式2.2.4 为查询结果指定别名2.2.5 结果去重 2.2 where 条件2.2.1 null的查询 2.3 结果排序2.4 筛选分…

如何搭建一个实时对话转录应用(类似zoom中的文本转录功能)并部署到 Heroku

文章目录 应用搭建Assembly AI文件夹结构前端搭建HTMLindex.js 后端搭建server.jspackage.json Heroku 部署创建账号创建Heroku应用上传仓库 应用搭建 应用基于 html javascript使用的第三方 API 是 Assembly AI 提供的 Assembly AI 要使用 real-time transcript 功能&…

ChatGPT:为教育创新提供五大机遇

随着智能技术的不断发展&#xff0c;ChatGPT在教育场景中的创新价值可能比我们能够意识到的还要多。比如它可以自动处理作业、在线答疑&#xff0c;可以辅助语言学习、实时沟通&#xff0c;甚至还可以用于评估诊断、科学研究。国内外关于利用ChatGPT实现教育创新的场景描绘已经…

【Matplotlib】多级雷达图绘制

一、实例1&#xff1a;个人能力画像雷达图 # -*- coding: utf-8 -*- """ Created on Sat Jul 1 20:52:54 2023author: zcq """import numpy as np import matplotlib.pyplot as plt import matplotlibmatplotlib.rcParams[font.family]SimHei …

灯夹三角架

2个卡箍1个无头螺丝拼1个灯夹 还需要1个三脚架固定 difference(){union(){translate([18,-7,0])cube([14,14,1]);translate([-7,18,40])cube([14,14,1]);translate([-7,-32,40])cube([14,14,1]);points [[7,-32,40], //0[18,-7,0], //1[18,7,0], //2[7,-18,40], //3[7,…

【C++面向对象】足球比赛数据统计系统(面向对象练习)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、51CTO技术博主 &#x…