一、前言
点到直线的距离很简单,直接套用公式计算就行;
点到线段的距离要分情况讨论:
- 1、点的投射在线段上,等效于点到直线;
- 2、点的投射在线段外,点到线段的距离为该点到线段最近端点的距离;
- 3、点在线段上,距离为0;
二、详细代码
#ifndef
#define
#include <QObject>
#include <qmath.h>
#include <QPointF>
const double esp=1e-6;
class dot_line_dis : public QObject
{
Q_OBJECT
public:
explicit dot_line_dis(QObject *parent = nullptr);
int sign(double x);
double dis(QPointF a,QPointF b); //两点之间的距离
double cmult(QPointF a,QPointF b,QPointF c); //叉积
double pmult(QPointF a,QPointF b); //点积 这里的ab表示的是向量
double pldis(QPointF a,QPointF b,QPointF c); //点a,线段起点b,线段终点c
};
#endif// DOT_LINE_DIS_H
#include "dot_line_dis.h"
dot_line_dis::dot_line_dis(QObject *parent) : QObject(parent)
{
}
int dot_line_dis::sign(double x)
{
if(fabs(x)<esp)
return 0;
return x>0?1:-1;
}
double dot_line_dis::dis(QPointF a,QPointF b)
{
return qSqrt(pow(a.x()-b.x(),2)+pow(a.y()-b.y(),2));
}
double dot_line_dis::cmult(QPointF a,QPointF b,QPointF c)///叉积
{
return (b.x()-a.x())*(c.y()-a.y())-(c.x()-a.x())*(b.y()-a.y());
}
double dot_line_dis::pmult(QPointF a,QPointF b)///点积 这里的ab表示的是向量
{
return a.x()*b.x()+a.y()*b.y();
}
///如何判断点是否在线段上且距离线段的最短距离是多少
double dot_line_dis::pldis(QPointF a,QPointF b,QPointF c)
{
QPointF s1,s2,s3;
s1.setX(c.x()-b.x());
s1.setY(c.y()-b.y());
s2.setX(a.x()-b.x());
s2.setY(a.y()-b.y());
s3.setX(a.x()-c.x());
s3.setY(a.y()-c.y());
if(b.x()==c.x() && b.y()==c.y())
return dis(a,b);
if(sign(pmult(s1,s2))<0) { ///两向量成钝角
return dis(a,b);
}else if(sign(pmult(s1,s3))>0) {
return dis(a,c);
}else { ///该处为c在线段上方
//两向量组成的三角形的面积为此两向的叉积的二倍,所以知道面积和底边就可以求出高
return fabs(cmult(b,a,c))/dis(b,c);
}
}
三、使用流程
dot_line_dis* d = new dot_line_dis;
qDebug()<<d->pldis(QPointF(-1,1),QPointF(0,0),QPointF(10,0));