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

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输出的结果:

小结 


http://www.kler.cn/news/340288.html

相关文章:

  • 网络安全体系与网络安全模型
  • 芝法酱学习笔记(0.7)——harbor与项目容器化部署
  • 详解MySQL中MRR(多范围读取)如何优化范围查询
  • WebAPI的初步认识
  • 美国信用卡消费在八月份暴跌,是到额度上限了吗?
  • 欢迎加入凌鸥学园
  • 南京自闭症寄宿学校探索:为孩子提供多元发展机会
  • 【2024】前端学习笔记14-JavaScript常用数据类型-变量常量
  • python数据类型高级
  • 驱动开发系列19 - GBM 和 DRM 的关系(扫盲)
  • 大数据可视化分析建模论
  • Linux操作系统(内核源码阅读)——内核区域映射
  • 实验3 选择结构
  • PCL 计算3DSC并可视化
  • 微信小程序 实现上拉加载更多功能:从基础到优化
  • 架设传奇SF时提示此服务器满员,GEE引擎点开始游戏弹出服务器满员的解决方法
  • Linux:进程控制(一)
  • python操作.docx、.pptx文件
  • C++-再探构造函数(进阶)
  • 用户在网页上输入一个网址,它整个页面响应的流程是什么?