当前位置: 首页 > news >正文

QT:计算点到线段的垂线段的距离

描述 

在Qt中,要计算一个点到一条线段的垂线段的长度(即点到线段上最近点的距离,且这个点是垂直于线段的),你不能直接使用QVector2D::distanceToLine,因为这个方法计算的是点到直线的垂直距离,而不是到线段的垂直距离。线段有起点和终点,而直线是无限延伸的。

为了计算点到线段的垂线段长度,你需要考虑几种情况:

  1. 如果点的投影在线段上,则垂线段长度就是点到投影点的距离。
  2. 如果点的投影在线段的起点或终点之外,则垂线段长度是点到线段起点或终点的距离中的较小值(这个没搞清楚。好在我当前的需求,不会出现投影在线段之外的情况)。

下面是一个使用QVector2D和简单的几何计算来实现这一功能的示例代码:

实验代码 

函数:

qreal Widget::pointToSegmentDistance(const QVector2D &point, const QVector2D &segmentStart, const QVector2D &segmentEnd) {QVector2D segmentDirection = segmentEnd - segmentStart;QVector2D vecFromStartToPoint = point - segmentStart;// 计算投影系数qreal t = QVector2D::dotProduct(vecFromStartToPoint, segmentDirection) / QVector2D::dotProduct(segmentDirection, segmentDirection);qDebug() << t;// 如果投影系数小于0,则最近点是线段起点if (t < 0.0) {return QVector2D(point - segmentStart).length();}// 如果投影系数大于1,则最近点是线段终点if (t > 1.0) {return QVector2D(point - segmentEnd).length();}// 投影在线段上,计算垂线段长度QVector2D projection = segmentStart + t * segmentDirection;return QVector2D(point - projection).length();
}

在paintEvent函数中实现划线,并调用 pointToSegmentDistance计算垂线段距离

void Widget::paintEvent(QPaintEvent *event)
{qreal distance;QPainter painter(this);QPen pen(Qt::blue,3);painter.setPen(pen);QPointF point(100,100);pen.setColor(Qt::blue);painter.setPen(pen);painter.drawPoint(point);pen.setColor(Qt::red);painter.setPen(pen);painter.drawText(QPointF(100,100),"point");QVector2D point_2d(point);QLineF line(50,50,50,150);pen.setColor(Qt::blue);painter.setPen(pen);painter.drawLine(line);pen.setColor(Qt::red);painter.setPen(pen);painter.drawText(line.center(),"line_1");QVector2D line_start_2d(line.p1());QVector2D line_end_2d(line.p2());distance = pointToSegmentDistance(point_2d,line_start_2d,line_end_2d);qDebug() << " to line 1 distance : " << distance;QLineF line2(50,50,150,50);pen.setColor(Qt::blue);painter.setPen(pen);painter.drawLine(line2);pen.setColor(Qt::red);painter.setPen(pen);painter.drawText(line2.center(),"line_2");QVector2D line2_start_2d(line2.p1());QVector2D line2_end_2d(line2.p2());distance = pointToSegmentDistance(point_2d,line2_start_2d,line2_end_2d);qDebug() << " to line 2 distance : " << distance;QLineF line3(150,50,150,150);pen.setColor(Qt::blue);painter.setPen(pen);painter.drawLine(line3);pen.setColor(Qt::red);painter.setPen(pen);painter.drawText(line3.center(),"line_3");QVector2D line3_start_2d(line3.p1());QVector2D line3_end_2d(line3.p2());distance = pointToSegmentDistance(point_2d,line3_start_2d,line3_end_2d);qDebug() << " to line 3 distance : " << distance;QLineF line4(150,200,150,300);pen.setColor(Qt::blue);painter.setPen(pen);painter.drawLine(line4);pen.setColor(Qt::red);painter.setPen(pen);painter.drawText(line4.center(),"line_4");QVector2D line4_start_2d(line4.p1());QVector2D line4_end_2d(line4.p2());distance = pointToSegmentDistance(point_2d,line4_start_2d,line4_end_2d);qDebug() << " to line 4 distance : " << distance;QLineF line5(300,200,300,150);pen.setColor(Qt::blue);painter.setPen(pen);painter.drawLine(line5);pen.setColor(Qt::red);painter.setPen(pen);painter.drawText(line5.center(),"line_5");QVector2D line5_start_2d(line5.p1());QVector2D line5_end_2d(line5.p2());distance = pointToSegmentDistance(point_2d,line5_start_2d,line5_end_2d);qDebug() << " to line 5 distance : " << distance;
}

测试结果:

qDebug输出的结果:

小结 

相关文章:

QT:计算点到线段的垂线段的距离

描述 在Qt中&#xff0c;要计算一个点到一条线段的垂线段的长度&#xff08;即点到线段上最近点的距离&#xff0c;且这个点是垂直于线段的&#xff09;&#xff0c;你不能直接使用QVector2D::distanceToLine&#xff0c;因为这个方法计算的是点到直线的垂直距离&#xff0c;而…...

经典5级流水线概述

抽象化的流水线结构&#xff1a; 流水线的基本概念 多个任务重叠&#xff08;并发/并行&#xff09;执行&#xff0c;但使用不同的资源流水线技术提高整个系统的吞吐率&#xff0c;不能缩短单个任务的执行时间其潜在的加速比&#xff1d;流水线的级数 流水线正常工作的基本条件…...

LSTM模型实现电力数据预测

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色&a…...

jmeter学习(7)beanshell

beanshell preprocessor 发送请求前执行 beanshell postprocessor 发送请求前执行 获取请求相关信息 String body sampler.getArguments().getArgument(0).getValue(); String url sampler.getPath(); 获取响应报文 String responseprev.getResponseDataAsString(); 获…...

TCP_SOCKET编程实现

文章目录 与UDP_SOCKET的区别第一代Tcp_ServerTcp_Client第二代Tcp_Server第三代Tcp_server多线程版本Tcp_Server线程池版的Tcp_Server使用inet_ntop来解决线程安全问题 业务逻辑编写总结补充说明&&业务代码完成ping的真实作用Translate编写Transform业务代码 整体总结…...

螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习07(基于docker容器的防火墙及NAT企业实战)

7.1 网络准备 7.2 网络规划 1&#xff09;虚拟网络编辑器 点击右下方“更改设置”&#xff0c;点击“添加网络”假如vmnet3和vmnet4&#xff0c;然后分别选择vmnet3和vmnet4&#xff0c;设置为“仅主机模式”&#xff0c;按③处处理&#xff0c;去掉“使用DHCP”&#xff0c;…...

②EtherNet/IP转ModbusTCP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ftt&id822721028899 协议转换通信网关 EtherNet/IP 转 Modbus TCP &#xff08;接上一章&#xff09; GW系列型号 配置使用 与 EtherNet/IP 主站进行组态说明 这里介…...

Java 集合(Collection)

1.什么是集合&#xff1f; 对象的容器&#xff0c;定义了对多个对象进行操作的常用方法&#xff0c;属于接口类型。 2.集合和数组的区别 &#xff08;1&#xff09;数组长度固定&#xff0c;集合长度不固定 &#xff08;2&#xff09;数组可以存储基本类型和引用类型&#…...

Windows系统编程(三)线程并发

进程与线程 进程&#xff1a;直观的说就是任务管理器中各种正在运行的程序。对于操作系统来说&#xff0c;进程仅仅是一个数据结构&#xff0c;并不会真实的执行代码 线程&#xff1a;通常被称作但并不真的是轻量级进程或实际工作中的进程&#xff0c;它会真实的执行代码。每…...

【Qt】控件概述(2)—— 按钮类控件

控件概述&#xff08;2&#xff09; 1. PushButton2. RadioButton——单选按钮2.1 使用2.2 区分信号 clicked&#xff0c;clicked(bool)&#xff0c;pressed&#xff0c;released&#xff0c;toggled(bool)2.3 QButtonGroup分组 3. CheckBox——复选按钮 1. PushButton QPushB…...

Java访问器方法和更改器方法

一.访问器方法 1.访问器方法的定义和用途 访问器方法&#xff0c;通常也称为getter方法&#xff0c;是一种在面向对象编程中用于从类的外部访问私有字段值的特殊方法。这些方法的设计目的是为了提供对类内部状态的受限访问&#xff0c;同时保持类的封装性。通过使用访问器方法&…...

CAN协议帧结构

一、数据帧的整体结构 ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐ │ SOF │ ID[11]│ RTR │ IDE │ DLC │ Data …...

valgrind 单例模式的自动释放(多线程)

单例模式&#xff0c;其中对象是由_pInstance指针来保存的&#xff0c;而在使用单例设计模式的过程中&#xff0c;也难免会遇到内存泄漏的问题。那么是否有一个方法&#xff0c;可以让对象自动释放&#xff0c;而不需要程序员自己手动去释放呢&#xff1f; ——嵌套类 5.1、内…...

OpenFegin

文章目录 一、OpenFegin是什么&#xff1f;二、基本使用三、超时重试机制4.自定义超时重传机制五、底层实现 一、OpenFegin是什么&#xff1f; OpenFeign的全称为Spring Cloud OpenFeign(下文简称OpenFeign),是Spring Cloud团队开发的一款基于 Feign的框架&#xff0c;声明式W…...

LeetCode-2608. 图中的最短环【广度优先搜索 图,腾讯面试真题】

LeetCode-2608. 图中的最短环【广度优先搜索 图&#xff0c;腾讯面试真题】 题目描述&#xff1a;解题思路一&#xff1a;【一图秒懂】枚举起点跑 BFS解题思路二&#xff1a;背诵版解题思路三&#xff1a; 题目描述&#xff1a; 现有一个含 n 个顶点的 双向 图&#xff0c;每个…...

IDEA 编译报错 “java: 常量字符串过长” 的解决办法

目录 一、问题描述二、问题原因2.1 理论角度2.2 源码角度 三、解决方案解决方案①&#xff1a;StringBuilder 拼接解决方案②&#xff1a;读取文件内容 四、方案验证 在线文本换行工具&#xff1a; https://lzltool.cn/Toolkit/WrapWordsInText 一、问题描述 今天在开发过程中…...

RK3568平台开发系列讲解(I2C篇)I2C 总线实现 client 设备方法

🚀返回专栏总目录 文章目录 一、非设备树实现 i2c client1.1、i2c_new_device1.2、i2c client二、设备树实现 i2c2.1、i2c_client 结构体的生成2.2、i2c_driver 驱动2.2.1、module_i2c_driver2.2.2、fan53555_regulator_probe沉淀、分享、成长,让自己和他人都能有所收获!�…...

K8S安装和部署

环境部署说明 主机IPmaster172.25.254.100node10172.25.254.10node20172.25.254.20harbor172.25.254.233 所有节点禁用selinux和防火墙 所有节点同步时间和解析 所有节点安装docker-ce 所有节点禁用swap&#xff0c;注意注释掉/etc/fstab文件中的定义 解析配置&#xff08;…...

Singleton(单例模式)

1. 意图 在开发中&#xff0c;若某些模块或功能只需要一个类实例&#xff0c;所有调用地方通过着一个类对象访问功能&#xff0c;单例模式符合这种类实例创建模式&#xff0c;并且通过提供统一类实例接口访问类对象。 2. 适用性 《Gof 设计模式-可复用面向对象软件的基础》中对…...

【Linux报错】“-bash: cd: too many arguments“

问题描述 今天使用 cd 想要调整某个文件目录时&#xff0c;发现以下报错 原因分析&#xff1a; arguments 是参数的意思&#xff0c;该报错提示参数过多&#xff0c;意味着系统识别到了多余参数 本质原因&#xff1a;你的命令中输入了多余的 ”空格“ &#xff0c;检查一…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...