PHP计算点到线段的最短距离
本帖最后由 nihuge 于 2019-12-6 14:04 编辑最近有一个项目是用PHP做飞行器飞控平台的,其中一项需求是系统自动同步抓取中国民航局规范的禁飞区,如果和飞控平台连接的飞行器靠近禁飞区,将警告操作手并显示禁飞区距离,如果飞行器驶入了禁飞区,则通过微信通知管理员,管理员可以暂停飞行器移动然后降落。
这个需求中有一些功能需要实现,比如说全国有一百多个机场永久禁飞区(大兴机场),政府规定的永久禁飞区(首都五环以内、QC等)和临时禁飞区(上海进博会期间全市禁飞)。如何和一百多台飞行器每秒通讯一次的过程中判断飞行器是否靠近了这些禁行区且不能算的慢。还有飞行器通讯传输过来的GPS位置是地理坐标系统,需要转换为对应地图的位置用于展示给客户(网上流传的转换位置源码相差几十米,无法接受的误差)等等。
第一个问题目前已经解决了,主体思路为录入禁飞区的顶点坐标至数据库时多录入一个经geohash编码后的坐标数据(编码规范可以自行百度),然后添加索引。检索飞行器附近的禁飞区时只需要使用右模糊查询就可以很方便的查询到附近的禁飞区顶点(右模糊查询时索引有效)。这种思路也被部分人用于查找附近的人之类的功能。获取到附近的顶点坐标后,利用数据库获取这些顶点所在禁飞区的所有顶点,然后判断飞行器是否在这些禁飞区内(算法网上一大堆,判断点是否在多边形内),如果不在禁飞区内则从中拿出最近顶点的前后两个顶点,依次连线的同时依次判断连线后的线段和飞行器位置点的最短距离,比对出最短的那一个距离就是距离。
说了那么多废话,其实我只想讲一下如何利用3个点(两个线段端,一个位置点),得出位置点距离线段最近的距离。
/**
* 计算3角型3个角的角度
* @Param array $point1 端点1A点
* @param array $point2 端点2B点
* @param array $point3 位置点 C点
* @Return float|int 最短距离
*/
public static function getCoses(array $point1, array $point2, array $point3)
{
//求3边边长,利用勾股定理分别做3角型求出边长
$pointAB = sqrt(pow($point1 - $point2, 2) + pow($point1 - $point2, 2));
$pointBC = sqrt(pow($point2 - $point3, 2) + pow($point2 - $point3, 2));
$pointCA = sqrt(pow($point3 - $point1, 2) + pow($point3 - $point1, 2));
//求3边反余弦弧度后转换成角度
$cosABC = rad2deg(acos(($pointAB * $pointAB + $pointBC * $pointBC - $pointCA * $pointCA) / (2 * $pointAB * $pointBC)));
$cosBCA = rad2deg(acos(($pointBC * $pointBC + $pointCA * $pointCA - $pointAB * $pointAB) / (2 * $pointBC * $pointCA)));
$cosCAB = rad2deg(acos(($pointCA * $pointCA + $pointAB * $pointAB - $pointBC * $pointBC) / (2 * $pointCA * $pointAB)));
if ($cosABC >= 90) return $pointBC;
if ($cosCAB >= 90) return $pointCA;
if ($cosABC < 90 && $cosCAB < 90) return $pointCA * sin(deg2rad($cosCAB));
}
方法内根据3个顶点的坐标两两分别做直角三角形然后利用勾股定理得出每个线段的边长,然后求3边的反余弦弧度再转角度就可以得出三角形三个角的角度,此时判断位置和线段两端的两个角是否是锐角,如果是都锐角则最短距离为位置点和线段的垂线距离。
如果其中一个是钝角或直角,则最短距离为位置点到线段端点的距离。
由此得出最短距离。 哥们,你公司接的都是什么项目的活啊、。?好像看起来好高大上 时效性 飞控PHP微信
靠谱吗?
我是外行,不太理解! 小小学生 发表于 2019-12-6 14:21
哥们,你公司接的都是什么项目的活啊、。?好像看起来好高大上
不是很高大上,飞行器通讯用的tcp协议。其他逻辑也不是很难。 dazhuangzhuang 发表于 2019-12-6 14:25
时效性 飞控PHP微信
靠谱吗?
我是外行,不太理解!
飞控就是飞行管控,PHP就是开发用的编程语言,微信更简单,官方有现成的API可以调用,申请一个公众号就可以发送模板消息。用户只需要关注公众号就可以接收到公众号下发的模板消息,php通过逻辑调用API就好了 nihuge 发表于 2019-12-6 14:30
不是很高大上,飞行器通讯用的tcp协议。其他逻辑也不是很难。
这种高大上的项目为什么不用C++的socket进行通讯,可靠性实时性都比较好的。 dazhuangzhuang 发表于 2019-12-6 14:48
这种高大上的项目为什么不用C++的socket进行通讯,可靠性实时性都比较好的。
因为我不会c++,而且一期的时候我没有参与,用的php,后来发现性能还可以就一直用了,这次是开发二期 nihuge 发表于 2019-12-6 14:54
因为我不会c++,而且一期的时候我没有参与,用的php,后来发现性能还可以就一直用了,这次是开发二期
方便够用就是最好的!{:1_921:}
页:
[1]