(伪)点到线段的距离 C++

之前写过一篇关于点到直线距离的文章,这回我来研究一下点到线段距离

回顾一下,推导出的点到直线距离公式为:

详细请见原博客

分析

在某种情况下,线段外一点P到线段AB的距离可以看做上述P到直线AB的距离:

就像这样子:

但是这样却不行(蓝线为实际距离,红线为到直线距离):

不难看出:

三角形ABP的形状 点到线段的距离
锐角三角形 P到直线AB的距离
直角三角形

PA,PB的较小者;P到直线AB的距离

钝角三角形 PA,PB的较小者

如图所示。

判断三角形的形状

不妨设三边中,最短的两边为a,b,最长边为c。

不难想到,判断直角三角形,就用勾股定理:

对于锐角三角形:

同理推出,在钝角三角形中,

接下来,便是令人兴奋的代码了。

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
double dist(double x1,double x2,double y1,double y2)
{return sqrt(pow(x2-x1,2)+pow(y2-y1,2));}//返回(x1,y1),(x2,y2)之间的距离 
int main()
{
	double x1,x2,x3,y1,y2,y3;
	/*A(x1,y1)
	  B(x2,y2)
	  P(x3,y3)*/
	cin>>x1>>y1>>x2>>y2>>x3>>y3;
	//判断三角形形状
	double a,b,c,d;
	a=dist(x1,x2,y1,y2);
	b=dist(x2,x3,y2,y3);
	c=dist(x1,x3,y1,y3);
	if(c<a or c<b)
	{
		if(c<a)
		{
			int t=a;
			a=c;
			c=t;
		}
		if(c<b)
		{
			int t=b;
			b=c;
			c=t;
		}
	}
	if(a*a+b*b<=c*c)//直角三角形或钝角三角形 
	d=min(dist(x1,x3,y1,y3),dist(x2,x3,y2,y3));
	else
	d=sqrt(pow((x3-x1)*(y2-y1)+(y3-y1)*(x1-x2),2)/(pow(y2-y1,2)+pow(x1-x2,2)));
	printf("%.3lf",d);
	return 0;
}

但是... ...

有2个测试点没过。80分。

是哪儿出了问题呢?

#以下是改来改去的过程。比较乱。请选择性阅读。#

[灵光一闪]   哦!会不会是没考虑到点在线段(所在直线)上的情况呢?

返回判断三角形的那一步,我们考虑一下这种情况。

让我来改一下代码。

if(a*a+b*b<=c*c)//直角三角形或钝角三角形 
	{
		d=min(dist(x1,x3,y1,y3),dist(x2,x3,y2,y3));
		if(a+b==c)//点在线段上
		d=0; 
	}

在此做修改(原代码36行)。

看看对不对呢......?!

Emmm mmmm mmmm... ... ...(不要急不要急不要急)

[灵光再现] 我使了个坏。看到锐角三角形部分有些乱,会不会是那里错了?

于是我把else后面的计算部分删了,交了上去。

哈哈哈哈!找到了!还是80分,也就是说,是else后的计算错了!

让我来换个思路。

由于d是P垂直AB的长度,即AB边上的高,所以通过面积法即可求出!

不知道大家知不知道,有一条根据边长计算面积的公式,叫海伦公式

于是,求出面积,除以AB即可。

if(a*a+b*b>c*c)
{
	int p=(dist(x1,x2,y1,y2)+dist(x1,x3,y1,y3)+dist(x3,x2,y3,y2));
	int s=sqrt(p*(p-dist(x1,x2,y1,y2))*(p-dist(x3,x2,y3,y2))*(p-dist(x1,x3,y1,y3)));
	d=s/dist(x1,x2,y1,y2);
}

。。。还是80分。(烂尾警告)

等我!我会搞好的!

猜你喜欢

转载自blog.csdn.net/Commander_WingT/article/details/89293447