博客列表 >php判断坐标点是否在多边形内

php判断坐标点是否在多边形内

₉₄₇的博客
₉₄₇的博客原创
2019年08月28日 11:43:451559浏览
<?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));


声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议