这是一个使用 PHP 开发的 AIS 数据分析 API,用于检测指定区域内船舶航线轨迹的异常情况。

API 支持以下功能:

  • 根据时间范围选择数据
  • 根据区域选择数据
  • 返回包含船舶经纬度、航向和异常状态的 JSON 数据

使用方法:

  1. 提交 POST 请求到 API 地址
  2. 在请求参数中指定时间范围和区域
  3. API 将返回包含船舶轨迹数据的 JSON 数据

请求参数:

  • polySelect: 区域选择,例如 'poly1'、'poly2' 等
  • startTime: 开始时间,时间戳格式
  • endTime: 结束时间,时间戳格式

返回数据:

API 返回 JSON 数据,包含以下信息:

  • LON: 经度
  • LAT: 纬度
  • COG: 航向
  • code: 异常状态,1 表示正常,0 表示异常

示例:

[{'LON':121.5000,'LAT':31.2000,'COG':180,'code':1},{'LON':121.5001,'LAT':31.2001,'COG':181,'code':1},{'LON':121.5002,'LAT':31.2002,'COG':179,'code':0}]

注意:

  • API 使用 MySQL 数据库存储 AIS 数据
  • API 使用 'is_point_in_polygon' 函数判断船舶是否位于指定区域内
  • API 使用 'course_threshold' 表存储航向阈值信息

代码示例:

<?php
header('Access-Control-Allow-Origin:*');
header('Content-type:text/json');
define( 'WP_MAX_MEMORY_LIMIT' , '512M' );
$servername = 'localhost';
$username = 'root';
$password = '1234';
$dbname = 'ais_dk';
$polySelect=$_POST['polySelect']; // get data from html
$startTime = $_POST['startTime'];
$startTime = intval(substr($startTime, 0, 10));
$endTime = $_POST['endTime'];
$endTime = intval(substr($endTime, 0, 10));

// $polySelect = 'poly2';
// $startTime = 1483978000;
// $endTime = 1484100000;


$polygon = 0;
switch($polySelect){
    case('poly1'):
        $polygon = 1;
        break;
    case('poly2'):
        $polygon = 2;
        break;
    case('poly3'):
        $polygon = 3;
        break;
    case('poly4'):
        $polygon = 4;
        break;
    case('poly5'):
        $polygon = 5;
        break;
    default:
        // $polygon = 1;
        echo 'Area select error!';
}

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die('连接失败: ' . $conn->connect_error);
}

mysqli_query($conn, 'set names utf8');
// get speed threshold from speed_threshold table
$sql1 = 'SELECT * FROM course_threshold where area = $polygon';
$result1 = $conn->query($sql1);
$arr1 = array();  
while($row = $result1->fetch_assoc()) {  
    $count=count($row);  
    for($i=0;$i<$count;$i++){  
        unset($row[$i]);//删除冗余数据  
    }  
    array_push($arr1,$row);  
}

// consider that course threshold consists of different scopes, define a switch case sentence to pick threshold
$min = array_column($arr1, 'min'); // get minimum value of course threshold
$max = array_column($arr1, 'max'); // get maximum value of course threshold

// point in polygon function
function is_point_in_polygon($point, $pts) {
    $N = count($pts);
    $boundOrVertex = 1; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
    $intersectCount = 0; 
    $precision = 2e-10; //浮点类型计算时候与0比较时候的容差
    $p1 = 0;
    $p2 = 0;
    $p = $point; //测试点
    $p1 = $pts[0];
    for ($i = 1; $i <= $N; ++$i) {
        if ($p['lon'] == $p1['lon'] && $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['lon'] <= max($p1['lon'], $p2['lon'])){  
                if ($p1['lat'] == $p2['lat'] && $p['lon'] >= min($p1['lon'], $p2['lon'])) {
                    return $boundOrVertex;
                }

                if ($p1['lon'] == $p2['lon']) {
                    if ($p1['lon'] == $p['lon']) {
                        return $boundOrVertex;
                    } else {
                        ++$intersectCount;
                    }
                } else {
                    $xinters = ($p['lat'] - $p1['lat']) * ($p2['lon'] - $p1['lon']) / ($p2['lat'] - $p1['lat']) + $p1['lon'];
                    if (abs($p['lon'] - $xinters) < $precision) {
                        return $boundOrVertex;
                    }
                     
                    if ($p['lon'] < $xinters) {
                        ++$intersectCount;
                    } 
                }
            }
        } else {
            if ($p['lat'] == $p2['lat'] && $p['lon'] <= $p2['lon']) {
                $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;   //if point is NOT in polygon, return 0
    }
    return 1;       //if point is in polygon, return 1
}


// get lon&lat info of selected polygon from MySQL db
$sql2 = 'SELECT * FROM polygon where polygon = $polygon';
$result2 = $conn->query($sql2);
$arr2 = array();  
while($row = $result2->fetch_assoc()) {  
    $count=count($row); 
    for($i=0;$i<$count;$i++){  
        unset($row[$i]);
    }  
    array_push($arr2,$row);  
}

// get selected polygon lat&lon scope from db
$lonlist = array_column($arr2, 'longitude'); 
$latlist = array_column($arr2, 'latitude');
$lonmin = min($lonlist);
$lonmax = max($lonlist);
$latmin = min($latlist);
$latmax = max($latlist);
// create a array of [lon, lat] for is_in_polygon function

$lon_lat = array();  
for($i=0;$i<count($lonlist);$i++){
    $temp = ['lon'=>$lonlist[$i],'lat'=>$latlist[$i]];
    array_push($lon_lat,$temp);
};

// $tables=array(1=>'ais_dk_table1',2=>'ais_dk_table2',3=>'ais_dk_table3',4=>'ais_dk_table4',5=>'ais_dk_table5',6=>'ais_dk_table6',7=>'ais_dk_table7',8=>'ais_dk_table8',9=>'ais_dk_table9',10=>'ais_dk_table10',11=>'ais_dk_table11',12=>'ais_dk_table12',13=>'ais_dk_table13',14=>'ais_dk_table14',15=>'ais_dk_table15',16=>'ais_dk_table16',17=>'ais_dk_table17');
$tables = array(1=>'ais_table1', 2=>'ais_table2', 3=>'ais_table3', 4=>'ais_table4', 5=>'ais_table5', 6=>'ais_table6', 7=>'ais_table7', 8=>'ais_table8', 9=>'ais_table9');
$data = array(); // array to store selected data
foreach($tables as $value){
    $sql3 = 'SELECT LON,LAT,COG FROM $value where TimeStamp > $startTime and TimeStamp < $endTime and LON > $lonmin and LON < $lonmax and LAT > $latmin and LAT < $latmax';
    $result3 = $conn->query($sql3);
    while($row = $result3->fetch_assoc()) {  
        // $count=count($row); 
        // for($i=0;$i<$count;$i++){  
        //     unset($row[$i]);
        // }
        $lon = $row['LON'];
        $lat = $row['LAT'];
        $point = [
            'lon'=>$lon,
            'lat'=>$lat
        ];
        // because function array_shift takes one entry each operation and it's irreversible
        $min = array_column($arr1, 'min'); // get minimum value of course threshold
        $max = array_column($arr1, 'max'); // get maximum value of course threshold
        if (is_point_in_polygon($point, $lon_lat) == 1){
            if(count($min) == 1){
                $min1 = array_shift($min);
                $max1 = array_shift($max);
                if($row['COG']>=$min1 and $row['COG']<=$max1){
                    $row['code'] = 1; //1 course normal, 0 course abnormal
                }
                else{
                    $row['code'] = 0;
                }
            }
            elseif(count($min) == 2){
                $min1 = array_shift($min);
                $max1 = array_shift($max);
                $min2 = array_shift($min);
                $max2 = array_shift($max);
                if(($row['COG']>=$min1 and $row['COG']<=$max1) or ($row['COG']>=$min2 and $row['COG']<=$max2)){
                    $row['code'] = 1; //1 course normal, 0 course abnormal
                }
                else{
                    $row['code'] = 0;
                }
            }
            elseif(count($min) == 3){
                $min1 = array_shift($min);
                $max1 = array_shift($max);
                $min2 = array_shift($min);
                $max2 = array_shift($max);
                $min3 = array_shift($min);
                $max3 = array_shift($max);
                if(($row['COG']>=$min1 and $row['COG']<=$max1) or ($row['COG']>=$min2 and $row['COG']<=$max2) or ($row['COG']>=$min3 and $row['COG']<=$max3)){
                    $row['code'] = 1; //1 course normal, 0 course abnormal
                }
                else{
                    $row['code'] = 0;
                }
            }
            elseif(count($min) == 4){
                $min1 = array_shift($min);
                $max1 = array_shift($max);
                $min2 = array_shift($min);
                $max2 = array_shift($max);
                $min3 = array_shift($min);
                $max3 = array_shift($max);
                $min4 = array_shift($min);
                $max4 = array_shift($max);
                if(($row['COG']>=$min1 and $row['COG']<=$max1) or ($row['COG']>=$min2 and $row['COG']<=$max2) or ($row['COG']>=$min3 and $row['COG']<=$max3) or ($row['COG']>=$min4 and $row['COG']<=$max4)){
                    $row['code'] = 1; //1 course normal, 0 course abnormal
                }
                else{
                    $row['code'] = 0;
                }
            }
            array_push($data,$row);
        }
    }};


// var_dump($arr3);
// $SOG = array_column($arr3, 'SOG','SOG');
// foreach ($arr3 as $k1 => $v1){
// 	    unset($arr3[$k1]['SOG']);
// }
// $data = array_splice($data, 0, 10); // too many points
// $data = json_encode($arr);
// file_put_contents('point1.json',$data);
echo json_encode($data,JSON_UNESCAPED_UNICODE);

$conn->close();
?>
AIS 数据分析:航线轨迹异常检测 API

原文地址: https://www.cveoy.top/t/topic/XTn 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录