<?php //方法一 /** * 判断一个坐标是否在一个多边形内(由多个坐标围成的) * 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则 * 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。 * @param $point 指定点坐标 * @param $pts 多边形坐标 顺时针方向 */ function is_point_in_polygon($point, $pts) { $N = count($pts); $boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true $intersectCount = 0; $precision = 2e-10; //浮点类型计算时候与0比较时候的容差 $p1 = 0; $p2 = 0; $p = $point; //测试点 $p1 = $pts[0]; for ($i = 1; $i <= $N; ++$i) { if ($p['lng'] == $p1['lng'] && $p['lat'] == $p1['lat']) { return $boundOrVertex; } $p2 = $pts[$i % $N]; if ($p['lat'] < min($p1['lat'], $p2['lat']) || $p['lat'] > max($p1['lat'], $p2['lat'])) { $p1 = $p2; continue; } if ($p['lat'] > min($p1['lat'], $p2['lat']) && $p['lat'] < max($p1['lat'], $p2['lat'])) { if($p['lng'] <= max($p1['lng'], $p2['lng'])){ if ($p1['lat'] == $p2['lat'] && $p['lng'] >= min($p1['lng'], $p2['lng'])) { return $boundOrVertex; } if ($p1['lng'] == $p2['lng']) { if ($p1['lng'] == $p['lng']) { return $boundOrVertex; } else { ++$intersectCount; } } else { $xinters = ($p['lat'] - $p1['lat']) * ($p2['lng'] - $p1['lng']) / ($p2['lat'] - $p1['lat']) + $p1['lng']; if (abs($p['lng'] - $xinters) < $precision) { return $boundOrVertex; } if ($p['lng'] < $xinters) { ++$intersectCount; } } } } else { if ($p['lat'] == $p2['lat'] && $p['lng'] <= $p2['lng']) { $p3 = $pts[($i+1) % $N]; if ($p['lat'] >= min($p1['lat'], $p3['lat']) && $p['lat'] <= max($p1['lat'], $p3['lat'])) { ++$intersectCount; } else { $intersectCount += 2; } } } $p1 = $p2; } if ($intersectCount % 2 == 0) { return 0; //在多边形外 返回0 } return 1; //在多边形内 返回1 } $arr=[ [ 'lng'=>1, 'lat'=>1 ], [ 'lng'=>1, 'lat'=>3 ], [ 'lng'=>1.5, 'lat'=>4 ], [ 'lng'=>3, 'lat'=>2 ], [ 'lng'=>2, 'lat'=>1 ], ]; $point=[ 'lng'=>2, 'lat'=>2 ]; $a= is_point_in_polygon($point, $arr); var_dump($a); //方法二 /*判断函数,$arr放入多边形各个顶点的坐标, $t为判断点的位置,$n为顶点坐标的个数-1; 若点在多边形内则返回1,否则返回0; */ function inpolygon($arr,$t,$n){ for($i = 0;$i<=$n;$i++){ $arr[$i][0]-=$t[0]; $arr[$i][1]-=$t[1]; } $t1 = $arr[0][0]>=0?($arr[0][1]>=0?0:3):($arr[0][1]>=0?1:2); for($sum =0,$i=1;$i<=$n;$i++){ if(!$arr[$i][0] && !$arr[$i][1]){ break; } $f = $arr[$i][1]*$arr[$i-1][0] - $arr[$i][0]*$arr[$i-1][1]; if(!$f && $arr[$i-1][0]*$arr[$i][0]<=0 && $arr[$i-1][1]*$arr[$i][1]<=0){ break; } $t2 = $arr[$i][0]>=0?($arr[$i][1]>=0?0:3):($arr[$i][1]>=0?1:2); if($t2 == ($t1+1)%4){ $sum +=1; } else if($t2 == ($t1+3)%4){ $sum -=1; } else if($t2 == ($t1+2)%4){ if($f>0)$sum+=2; else $sum-=2; } $t1 = $t2; } if($i<=$n || $sum){ return 1; //点在多边形内则返回1 } return 0; //点在多边形外则返回0 } $arr = array( array(1,1), array(1,3), array(1.5,4), array(3,2), array(2,1) ); $xy = array(1,2); /*调用函数*/ var_dump(inpolygon($arr,$xy,count($arr)-1));