php 判断一个百度坐标是否在一个多边形内(由多个坐标围成的)

<?php


/**
 * 判断一个百度坐标是否在一个多边形内(由多个坐标围成的)
 * 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
 * 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
 * @param $point 指定点坐标
 * @param $pts 多边形坐标 顺时针方向
 * 传值举例
 * $point['lng'] = '116.453101';
 * $point['lat'] = '39.966293';
 * $arr[0]['lng'] = '116.319181';
 * $arr[0]['lat'] = '39.969369';
 * $arr[1]['lng'] = '116.453712';
 * $arr[1]['lat'] = '39.967157';
 * $arr[2]['lng'] = '116.456586';
 * $arr[2]['lat'] = '39.868433';
 * $arr[3]['lng'] = '116.326655';
 * $arr[3]['lat'] = '39.86223';
 */
function is_point_in_polygon($point, $pts) {
    
    
    $N = count($pts);
    $boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
    $intersectCount = 0;//cross points count of x 
    $precision = 2e-10; //浮点类型计算时候与0比较时候的容差
    $p1 = 0;//neighbour bound vertices
    $p2 = 0;
    $p = $point; //测试点
    $p1 = $pts[0];//left vertex        
    for ($i = 1; $i <= $N; ++$i) {
    
    //check all rays
        // dump($p1);
        if ($p['lng'] == $p1['lng'] && $p['lat'] == $p1['lat']) {
    
    
            return $boundOrVertex;//p is an vertex
        }
         
        $p2 = $pts[$i % $N];//right vertex            
        if ($p['lat'] < min($p1['lat'], $p2['lat']) || $p['lat'] > max($p1['lat'], $p2['lat'])) {
    
    //ray is outside of our interests
            $p1 = $p2; 
            continue;//next ray left point
        }
         
        if ($p['lat'] > min($p1['lat'], $p2['lat']) && $p['lat'] < max($p1['lat'], $p2['lat'])) {
    
    //ray is crossing over by the algorithm (common part of)
            if($p['lng'] <= max($p1['lng'], $p2['lng'])){
    
    //x is before of ray
                if ($p1['lat'] == $p2['lat'] && $p['lng'] >= min($p1['lng'], $p2['lng'])) {
    
    //overlies on a horizontal ray
                    return $boundOrVertex;
                }
                 
                if ($p1['lng'] == $p2['lng']) {
    
    //ray is vertical                        
                    if ($p1['lng'] == $p['lng']) {
    
    //overlies on a vertical ray
                        return $boundOrVertex;
                    } else {
    
    //before ray
                        ++$intersectCount;
                    }
                } else {
    
    //cross point on the left side
                    $xinters = ($p['lat'] - $p1['lat']) * ($p2['lng'] - $p1['lng']) / ($p2['lat'] - $p1['lat']) + $p1['lng'];//cross point of lng
                    if (abs($p['lng'] - $xinters) < $precision) {
    
    //overlies on a ray
                        return $boundOrVertex;
                    }
                     
                    if ($p['lng'] < $xinters) {
    
    //before ray
                        ++$intersectCount;
                    } 
                }
            }
        } else {
    
    //special case when ray is crossing through the vertex
            if ($p['lat'] == $p2['lat'] && $p['lng'] <= $p2['lng']) {
    
    //p crossing over p2
                $p3 = $pts[($i+1) % $N]; //next vertex
                if ($p['lat'] >= min($p1['lat'], $p3['lat']) && $p['lat'] <= max($p1['lat'], $p3['lat'])) {
    
     //p.lat lies between p1.lat & p3.lat
                    ++$intersectCount;
                } else {
    
    
                    $intersectCount += 2;
                }
            }
        }
        $p1 = $p2;//next ray left point
    }
    if ($intersectCount % 2 == 0) {
    
    //偶数在多边形外
		return false;
	} else {
    
     //奇数在多边形内
		return true;
	}

}
/**
 * @name 围栏算法,判断一个坐标,是否在围栏里面.如:['113.664673,34.810146','113.681667,34.796896','113.69231,34.794711','113.702009,34.809159']
 * @author macnie <[email protected]>
 * @param array $fences 围栏,是一组坐标数组 如:113.674458,34.804719
 * @param string $point 要判断的坐标
 * @return bool
 */
function in_fences($fences, $point) {
    
    
    $nvert = count($fences);
    $vertx = [];
    $verty = [];
    list($testy, $testx) = explode(',', $point);
    foreach ($fences as $r) {
    
    
        list($lng, $lat) = explode(',', $r);
        $vertx[] = $lat;
        $verty[] = $lng;
    }
    $i = $j = $c = 0;
    for ($i = 0, $j = $nvert - 1; $i < $nvert; $j = $i++) {
    
    
        if (( ($verty[$i] > $testy) != ($verty[$j] > $testy) ) &&
            ($testx < ($vertx[$j] - $vertx[$i]) * ($testy - $verty[$i]) / ($verty[$j] - $verty[$i]) + $vertx[$i]))
            $c = !$c;
    }
    return $c;
}


$row['points'] = "[{&quot;lat&quot;:&quot;40.12322836633086&quot;,&quot;lng&quot;:&quot;116.41199941056614&quot;},{&quot;lat&quot;:&quot;40.11382108206903&quot;,&quot;lng&quot;:&quot;116.40995127400339&quot;},{&quot;lat&quot;:&quot;40.11084137540158&quot;,&quot;lng&quot;:&quot;116.42946246968012&quot;},{&quot;lat&quot;:&quot;40.1226490700158&quot;,&quot;lng&quot;:&quot;116.43273230173644&quot;}]";
$row['points'] = str_replace('&quot;', '"', $row['points']);
//print_r($row['points']);
$points = json_decode($row['points'], true);
print_r($points);
$_gis_jd="116.421242";
$_gis_wd="40.119014";
$point = array(
				"lng" => $_gis_jd,
				"lat" => $_gis_wd
			);
$in =  is_point_in_polygon($point, $points);
var_dump($in);

foreach($points as $v){
    
    
	$fences[] = implode(",",$v);
}

$point = implode(",",$point);		
$in =  in_fences($fences, $point);
var_dump($in);


	
	
	
	
	
?>

猜你喜欢

转载自blog.csdn.net/lizhihua0625/article/details/130667219
今日推荐