function in_geo( array $points , array $arr ){
if( empty( $points ) || !is_array( $points ) ){
return false;
}
if( empty( $arr ) || !is_array( $arr ) ){
return false;
}
$new_points = [];
foreach ( $points as $k => $v ){
$new_points[] = [$v['latitude'],$v['longitude']];
}
$center = $this->GetCenterFromDegrees( $new_points );
foreach ( $arr as $key => $val ){
$val = json_decode( $val['points'] , true );
$val = $this->update_array( $val );
$range = $this->getDistance( $val[0] ,$val[1] , $center[0] , $center[1] );
$arr[$key]['range'] = $range;
}
$arr = $this->array_sort( $arr );
$new_arr = json_decode( $arr[0]['points'] , true );
foreach ( $new_arr as $kk => $vv ){
$geo[] = $vv['longitude'] . ',' . $vv['latitude'];
}
for ( $p = 0; $p <= count( $points ) -1; $p++ ){
$fences = $points[$p]['longitude'] . ',' . $points[$p]['latitude'];
if( $this->in_fences( $geo , $fences ) ){
return 1;
}
}
$arr_line = $this->changeLine( $new_arr );
$points_line = $this->changeLine( $points );
$num = 0;
for ( $i = 0; $i <= count( $points_line ) -1; $i++ ){
for ( $j = $i; $j <= count( $points_line ) -1; $j++){
$line = $this -> isSegmentsIntersectant( $points_line[$i] , $arr_line[$j] );
if( $line ){
$num++;
}
}
}
return $num;
}
以下为算法中运用到的其他算法
[GetCenterFromDegrees方法](https:
function update_array( array $data ){
if( !is_array( $data ) ) return false;
if( count( $data ) <= 1 ){
foreach ( $data as $key => $val ){
return [ $val['latitude'] , $val['longitude'] ];
}
}else {
foreach ($data as $k => $v) {
if ( array_key_exists('name', $v ) ) {
unset($data[$k]['address']);
unset($data[$k]['name']);
} else {
unset($data[$k]['address']);
}
$data[$k][0] = $data[$k]['latitude'];
$data[$k][1] = $data[$k]['longitude'];
unset($data[$k]['latitude']);
unset($data[$k]['longitude']);
}
}
return $this->GetCenterFromDegrees( $data );
}
[getDistance方法](https:
function array_sort( array $data = [] ){
if( empty( $data ) ){
return [];
}
if( !is_array( $data ) ){
return [];
}
for ( $i = 0; $i < count( $data ); $i++ ){
$arr = '';
for ( $j = $i; $j < count( $data ) -1; $j++ ){
if( $data[$i]['range'] > $data[$j+1]['range'] ){
$arr = $data[$i];
$data[$i] = $data[$j+1];
$data[$j+1] = $arr;
}
}
if ($data[$i]['range'] < 1) {
$data[$i]['range'] = $data[$i]['range'] * 1000;
$data[$i]['range'] = round( $data[$i]['range'] ) . 'm';
} else {
$data[$i]['range'] = round( $data[$i]['range'] , 2 ) . 'km';
}
}
return $data;
}
[in_fences方法](https:
function changeLine( array $arr ){
if( empty( $arr ) ){
return [];
}
if( count( $arr ) == 1 ){
return $arr;
}
for ( $i = 0; $i < count( $arr ) -1; $i++ ){
for ( $j = $i +1; $j <= count( $arr ) -1; $j++ ){
$data[] = [ [ 'x' => $arr[$i]['latitude'] , 'y' => $arr[$i]['longitude'] , 'name' => $arr[$i]['name'] ] , ['x' => $arr[$j]['latitude'] , 'y' => $arr[$j]['longitude'] , 'name' => $arr[$j]['name'] ] ];
}
}
return $data;
}
function isSegmentsIntersectant($segA, $segB) {
$abc = ($segA[0]['x'] - $segB[0]['x']) * ($segA[1]['y'] - $segB[0]['y']) - ($segA[0]['y'] - $segB[0]['y']) * ($segA[1]['x'] - $segB[0]['x']);
$abd = ($segA[0]['x'] - $segB[1]['x']) * ($segA[1]['y'] - $segB[1]['y']) - ($segA[0]['y'] - $segB[1]['y']) * ($segA[1]['x'] - $segB[1]['x']);
if ($abc * $abd >= 0) {
return false;
}
$cda = ($segB[0]['x'] - $segA[0]['x']) * ($segB[1]['y'] - $segA[0]['y']) - ($segB[0]['y'] - $segA[0]['y']) * ($segB[1]['x'] - $segA[0]['x']);
$cdb = $cda + $abc - $abd;
return !($cda * $cdb >= 0);
}
该算法并非无问题,如有能人异士可改善,欢迎评论