企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
​ ### 讲解:抽稀算法用于点集合较多的情况下的运算,缩放比例用于静态图显示轨迹api时候适应图片的一个缩放尺寸 > 一、下面的方法调用就可以得到抽稀后的点集合 ~~~php sparePoints($points, $max) ~~~ ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") > 二、缩放比例的参数可以自己边测试边调整,用到了首位点计算路线长度的运算来做辅助,[点击测试](http://api.map.baidu.com/staticimage/v2?ak=hYQdrXKpQvFB0rtHZn1VXT1PLZHM1wHN&width=500&height=350&zoom=17&paths=116.457788,39.968536;116.457835,39.968622;116.458037,39.968722;116.458446,39.96846;116.458643,39.968332;116.458441,39.968149;116.458252,39.967976;116.457992,39.967762;116.457731,39.967516;116.457628,39.967437;116.457498,39.967302;116.4573,39.967115;116.457143,39.966967;116.456981,39.966828;116.456743,39.966628;116.456604,39.966877;116.456519,39.966949;116.456267,39.96699;&pathStyles=0xff0000,5,1 "点击测试")  ,链接里面的参数zoom就是缩放比例,对应的 [api ](http://lbs.baidu.com/index.php?title=static "api ")用来显示静态图轨迹 ~~~php <?php namespace app\admin\controller; class Dglspksf { /** * 点到直线的距离 * @param $a float * @param $b float * @param $c float * @param $xy string 点坐标例如 "2,2" * @return number */ public function getDistanceFromPointToLine($a, $b, $c, $xy) { $x = explode(",", $xy)[0]; $y = explode(",", $xy)[1]; return abs(($a * $x + $b * $y + $c) / sqrt($a * $a + $b * $b)); } /** * 计算两点地理坐标之间的距离 * @param Decimal $longitude1 起点经度 * @param Decimal $latitude1 起点纬度 * @param Decimal $longitude2 终点经度 * @param Decimal $latitude2 终点纬度 * @param Int $unit 单位 1:米 2:公里 * @param Int $decimal 精度 保留小数位数 * @return Decimal */ public function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=2, $decimal=2){ $EARTH_RADIUS = 6370.996; // 地球半径系数 $PI = 3.1415926; $radLat1 = $latitude1 * $PI / 180.0; $radLat2 = $latitude2 * $PI / 180.0; $radLng1 = $longitude1 * $PI / 180.0; $radLng2 = $longitude2 * $PI /180.0; $a = $radLat1 - $radLat2; $b = $radLng1 - $radLng2; $distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2))); $distance = $distance * $EARTH_RADIUS * 1000; if($unit==2){ $distance = $distance / 1000; } return round($distance, $decimal); } /*获取缩放比例*/ public function getZoom($gatherids){ $len=1; $gatherids=explode(';',$gatherids); if($gatherids){ if(count($gatherids)>1){ $a=$gatherids[0]; $b=$gatherids[count($gatherids)-1]; $len=$this->getDistance(explode(',',$a)[0],explode(',',$a)[1],explode(',',$b)[0],explode(',',$b)[1],1); }else{ $len=1; } } $zoom=14; if($len>=1 && $len<=200){ $zoom=19; } if($len>200 && $len<=1000){ $zoom=18; } if($len>1000 && $len<=2000){ $zoom=15; } if($len>2000 && $len<=5000){ $zoom=14; } if($len>5000 && $len<=10000){ $zoom=13; } if($len>10000 && $len<=20000){ $zoom=12; } if($len>20000 && $len<=25000){ $zoom=11; } if($len>25000 && $len<=50000){ $zoom=10; } if($len>50000 && $len<=100000){ $zoom=9; } if($len>100000 && $len<=200000){ $zoom=8; } if($len>200000 && $len<=500000){ $zoom=6; } return $zoom; } /** * 根据两个点求直线方程 ax+by+c=0 * @param $xy1 string 点1,例如"1,1" * @param $xy2 string 点2,例如"2,2" * @return array */ public function getLineByPoint($xy1, $xy2) { $x1 = explode(",", $xy1)[0];//第一个点的横坐标 $y1 = explode(",", $xy1)[1];//第一个点的纵坐标 $x2 = explode(",", $xy2)[0];//第二个点的横坐标 $y2 = explode(",", $xy2)[1];//第二个点的横坐标 $a = $y2 - $y1; $b = $x1 - $x2; $c = ($y1 - $y2) * $x1 - $y1 * ($x1 - $x2); return [$a, $b, $c]; } /** * 稀疏点 * @param $points array 参数为["1,2","2,3"]点集 * @param $max float 阈值,越大稀疏效果越好但是细节越差 * @return array */ public function sparePoints($points, $max) { if (count($points) < 20) { return $points; } $xy1 = $points[0];//取第一个点 $xy2 = end($points);//取最后一个点 list($a, $b, $c) = $this->getLineByPoint($xy1, $xy2);//获取直线方程的a,b,c值 $ret = [];//最后稀疏以后的点集 $dmax = 0;//记录点到直线的最大距离 $split = 0;//分割位置 for ($i = 1; $i < count($points) - 1; $i++) { $d = $this->getDistanceFromPointToLine($a, $b, $c, $points[$i]); if ($d > $dmax) { $split = $i; $dmax = $d; } } if ($dmax>$max) {//如果存在点到首位点连成直线的距离大于max的,即需要再次划分 $child1 = $this->sparePoints(array_slice($points, 0, $split + 1), $max);//按split分成左边一份,递归 $child2 = $this->sparePoints(array_slice($points, $split), $max);//按split分成右边一份,递归 //因为child1的最后一个点和child2的第一个点,肯定是同一个(即为分割点),合并的时候,需要注意一下 $ret = array_merge($ret, $child1, array_slice($child2, 1)); return $ret; } else {//如果不存在点到直线的距离大于阈值的,那么就直接是首尾点了 return [$points[0], end($points)]; } } } ~~~ ![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "点击并拖拽以移动") ​