求点到线段的最短距离QT
计算目录
已知,线段的起点和终点,以及点的坐标。求点到线的最短距离
一、原理分析
线段的起点为 (,) ,终点为(,),点的坐标为(,)
求垂点坐标:(,)
解答如下:
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:表示线段的结束坐标。
-
struct LineSegment {
-
QPointF startPoint;
-
QPointF endPoint;
-
LineSegment(QPointF a, QPointF b)
-
{
-
startPoint = a;
-
endPoint = b;
-
}
-
LineSegment() {}
-
};
计算垂点代码如下:
计算垂点的坐标的请看上面的推导过程。
-
/**
-
* @brief 获取点到在线段上的线的垂点
-
* @param pt 点
-
* @param seg 线段
-
* @return
-
*/
-
QPointF QDrawingPaperView::getPointToLineVerticalpoint(QPointF pt,
-
LineSegment seg)
-
{
-
QPointF np;
-
-
double x_se = seg.startPoint.x() - seg.endPoint.x();
-
double y_se = seg.startPoint.y() - seg.endPoint.y();
-
// 表示线段的开始定点与解决顶点重合,因此直接返回其中一点即可
-
if(0 == x_se && 0 == y_se){
-
np.setX(seg.startPoint.x());
-
np.setY(seg.startPoint.y());
-
return np;
-
}
-
double x_se_2 = x_se * x_se; // x平方
-
double y_se_2 = y_se * y_se; // y平方
-
double x = (x_se_2 * pt.x() (pt.y() - seg.startPoint.y()) * y_se * x_se
-
seg.startPoint.x() * y_se_2) /
-
(x_se_2 y_se_2);
-
double y = pt.y() x_se * (pt.x() - x) / y_se;
-
np.setX(x);
-
np.setY(y);
-
return np;
-
}
计算两点之间的距离如下:
-
// 计算两点之间的距离
-
double QDrawingPaperView::distance(QPointF startPoint, QPointF endPoint)
-
{
-
double dis = 0;
-
double width = startPoint.x() - endPoint.x();
-
double height = startPoint.y() - endPoint.y();
-
if(0 == width && 0==height){
-
return 0;
-
}
-
dis = qSqrt(width * width height * height);
-
return dis;
-
}
判断垂点是否在线段上:
假设垂点是一定在线段的直线上下面的公式才成立。
-
-
bool QDrawingPaperView::verticalPointIsOnLine(QPoint np, LineSegment seg)
-
{
-
bool isOnX = false; // 垂点的x坐标是否在线段上
-
bool isOnY = false; // 垂点的y坐标是否在线段上
-
// 1.判断x坐标
-
// 1.1 判断线段的起始位置。从左向右还是从右向左
-
// 1.2 判断目录的x坐标是否在线段的区间内。
-
if (seg.startPoint.x() > seg.endPoint.x()) {
-
if (np.x() < seg.startPoint.x() && np.x() > seg.endPoint.x()) {
-
isOnX = true;
-
}
-
} else {
-
if (np.x() < seg.endPoint.x() && np.x() > seg.startPoint.x()) {
-
isOnX = true;
-
}
-
}
-
// 2.判断y坐标
-
// 2.1 判断线段的起始位置。从上向下还是从下向上
-
// 2.2 判断目录的y坐标是否在线段的区间内。
-
if (seg.startPoint.y() > seg.endPoint.y()) {
-
if (np.y() < seg.startPoint.y() && np.y() > seg.endPoint.y()) {
-
isOnY = true;
-
}
-
} else {
-
if (np.y() < seg.endPoint.y() && np.y() > seg.startPoint.y()) {
-
isOnY = true;
-
}
-
}
-
// 如果x,y坐标都在线段区间内那么认为坐标在线段上。
-
if (isOnX && isOnY) {
-
return true;
-
}
-
return false;
-
}
点计算距离线段距离
-
double QDrawingPaperView::pointToSegmentDis(QPointF pt, LineSegment seg)
-
{
-
// 1. 获取垂点
-
QPointF Verticalpoint;
-
Verticalpoint = getPointToLineVerticalpoint(pt, seg);
-
// 2. 判断垂点是否在线段上
-
-
bool isOnSeg = verticalPointIsOnLine(Verticalpoint, seg);
-
if (isOnSeg) {
-
// 如果在线段上那么垂点到点的距离最短
-
return distance(pt, Verticalpoint);
-
} else {
-
// 如果不在点段上那么到两点的距离最短。
-
double startDistance = distance(pt, seg.startPoint);
-
double endDistance = distance(pt, seg.endPoint);
-
return startDistance < endDistance ? startDistance : endDistance;
-
}
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhggbfkk
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13