• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

求点到线段的最短距离QT

武飞扬头像
三雷科技
帮助1

学新通

计算目录

一、原理分析

1.向量相乘为0,即向量垂直

2.垂点在线段上

垂点范围

X的范围

 Y的范围

二、代码实现

已知,线段的起点和终点,以及点的坐标。求点到线的最短距离

学新通

一、原理分析

线段的起点为 (学新通学新通,学新通) ,终点为(学新通学新通,学新通),点的坐标为(学新通学新通,学新通)

求垂点坐标:(学新通,学新通

 解答如下:

1.向量相乘为0,即向量垂直

由向量公式可以知道,两个向量相乘为0表示垂直。

假设线段向量为学新通,点和垂点向量为学新通

 学新通*学新通=0

学新通 = 学新通

学新通学新通

=>

学新通

2.垂点在线段上

由于 (学新通,学新通)经过线段因此假设线段为y=ax b,得到一下

学新通                        ------( 1` )

学新通                        ------( 2` )

学新通                      ------( 3` )


由1和2得到 ===>

学新通                       ----- ( 4` )


将4带入1 ===>

学新通        ------ ( 5` )


将4和5带入3 ===>

学新通                  --------- ( 6` ) 

学新通         --------- ( 7` ) 

由( 7` )  ===>

学新通                                     --------- ( 8` ) 


由 (6`)和(8`)   ===>

学新通

===>

学新通带入(8`)得到最后结果

计算好垂点,那么我们就要计算他们于起始点的位置。

判断垂点是否在线段中,如果不在,那么需要计算他距离最近的点。

3.垂点范围

学新通 的范围

如果: 学新通 ==>

那么满足 学新通,表示学新通在线段上

如果:学新通

那么满足 学新通,表示学新通在线段上

 学新通 的范围

如果: 学新通 ==>

那么满足 学新通,表示学新通在线段上

如果:学新通

那么满足 学新通,表示学新通在线段上

如果垂点不在线段上,那么点学新通到定点的距离最短。

二、代码实现

线段的数据结构:

startPoint:表示线段的开始坐标。

endPoint:表示线段的结束坐标。

  1.  
    struct LineSegment {
  2.  
    QPointF startPoint;
  3.  
    QPointF endPoint;
  4.  
    LineSegment(QPointF a, QPointF b)
  5.  
    {
  6.  
    startPoint = a;
  7.  
    endPoint = b;
  8.  
    }
  9.  
    LineSegment() {}
  10.  
    };

计算垂点代码如下:

计算垂点的坐标的请看上面的推导过程。

  1.  
    /**
  2.  
    * @brief 获取点到在线段上的线的垂点
  3.  
    * @param pt 点
  4.  
    * @param seg 线段
  5.  
    * @return
  6.  
    */
  7.  
    QPointF QDrawingPaperView::getPointToLineVerticalpoint(QPointF pt,
  8.  
    LineSegment seg)
  9.  
    {
  10.  
    QPointF np;
  11.  
     
  12.  
    double x_se = seg.startPoint.x() - seg.endPoint.x();
  13.  
    double y_se = seg.startPoint.y() - seg.endPoint.y();
  14.  
    // 表示线段的开始定点与解决顶点重合,因此直接返回其中一点即可
  15.  
    if(0 == x_se && 0 == y_se){
  16.  
    np.setX(seg.startPoint.x());
  17.  
    np.setY(seg.startPoint.y());
  18.  
    return np;
  19.  
    }
  20.  
    double x_se_2 = x_se * x_se; // x平方
  21.  
    double y_se_2 = y_se * y_se; // y平方
  22.  
    double x = (x_se_2 * pt.x() (pt.y() - seg.startPoint.y()) * y_se * x_se
  23.  
    seg.startPoint.x() * y_se_2) /
  24.  
    (x_se_2 y_se_2);
  25.  
    double y = pt.y() x_se * (pt.x() - x) / y_se;
  26.  
    np.setX(x);
  27.  
    np.setY(y);
  28.  
    return np;
  29.  
    }

 计算两点之间的距离如下:

学新通

  1.  
    // 计算两点之间的距离
  2.  
    double QDrawingPaperView::distance(QPointF startPoint, QPointF endPoint)
  3.  
    {
  4.  
    double dis = 0;
  5.  
    double width = startPoint.x() - endPoint.x();
  6.  
    double height = startPoint.y() - endPoint.y();
  7.  
    if(0 == width && 0==height){
  8.  
    return 0;
  9.  
    }
  10.  
    dis = qSqrt(width * width height * height);
  11.  
    return dis;
  12.  
    }

判断垂点是否在线段上:

假设垂点是一定在线段的直线上下面的公式才成立。

  1.  
     
  2.  
    bool QDrawingPaperView::verticalPointIsOnLine(QPoint np, LineSegment seg)
  3.  
    {
  4.  
    bool isOnX = false; // 垂点的x坐标是否在线段上
  5.  
    bool isOnY = false; // 垂点的y坐标是否在线段上
  6.  
    // 1.判断x坐标
  7.  
    // 1.1 判断线段的起始位置。从左向右还是从右向左
  8.  
    // 1.2 判断目录的x坐标是否在线段的区间内。
  9.  
    if (seg.startPoint.x() > seg.endPoint.x()) {
  10.  
    if (np.x() < seg.startPoint.x() && np.x() > seg.endPoint.x()) {
  11.  
    isOnX = true;
  12.  
    }
  13.  
    } else {
  14.  
    if (np.x() < seg.endPoint.x() && np.x() > seg.startPoint.x()) {
  15.  
    isOnX = true;
  16.  
    }
  17.  
    }
  18.  
    // 2.判断y坐标
  19.  
    // 2.1 判断线段的起始位置。从上向下还是从下向上
  20.  
    // 2.2 判断目录的y坐标是否在线段的区间内。
  21.  
    if (seg.startPoint.y() > seg.endPoint.y()) {
  22.  
    if (np.y() < seg.startPoint.y() && np.y() > seg.endPoint.y()) {
  23.  
    isOnY = true;
  24.  
    }
  25.  
    } else {
  26.  
    if (np.y() < seg.endPoint.y() && np.y() > seg.startPoint.y()) {
  27.  
    isOnY = true;
  28.  
    }
  29.  
    }
  30.  
    // 如果x,y坐标都在线段区间内那么认为坐标在线段上。
  31.  
    if (isOnX && isOnY) {
  32.  
    return true;
  33.  
    }
  34.  
    return false;
  35.  
    }

点计算距离线段距离

  1.  
    double QDrawingPaperView::pointToSegmentDis(QPointF pt, LineSegment seg)
  2.  
    {
  3.  
    // 1. 获取垂点
  4.  
    QPointF Verticalpoint;
  5.  
    Verticalpoint = getPointToLineVerticalpoint(pt, seg);
  6.  
    // 2. 判断垂点是否在线段上
  7.  
     
  8.  
    bool isOnSeg = verticalPointIsOnLine(Verticalpoint, seg);
  9.  
    if (isOnSeg) {
  10.  
    // 如果在线段上那么垂点到点的距离最短
  11.  
    return distance(pt, Verticalpoint);
  12.  
    } else {
  13.  
    // 如果不在点段上那么到两点的距离最短。
  14.  
    double startDistance = distance(pt, seg.startPoint);
  15.  
    double endDistance = distance(pt, seg.endPoint);
  16.  
    return startDistance < endDistance ? startDistance : endDistance;
  17.  
    }
  18.  
    }

git传送门

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggbfkk
系列文章
更多 icon
同类精品
更多 icon
继续加载