如何解决计算港口到港口的海上距离
我目前正在使用一个计算器来计算很多东西,其中之一是从 2 个给定点开始的路线。现在我想通过添加从一个港口到另一个港口的海上航线距离来扩展这个航线计算器。计算器已经从两个给定位置寻找最近的港口。但现在我被添加海上航线距离所困扰。
这是我目前的代码
<?PHP
if(isset($_POST['data'])){
$overseas = false;
$aRouteLegsSecondary;
$seadistance = 0;
$aRouteLegs = json_decode(stripslashes($_POST['data']));
$aLegs = array();
$aPassedCountries = array();
$whitelist = false;
if(isset($_POST['overseas']) && isset($_POST['dataSecondary'])){
if($_POST['overseas'] == "true"){
$overseas = true;
$aRouteLegsSecondary = json_decode(stripslashes($_POST['dataSecondary']));
}
}
$Routedistance = $aRouteLegs[0]->summary->distance;
$RouteTime = $aRouteLegs[0]->summary->time;
if($overseas){
$Routedistance = ($aRouteLegs[0]->summary->distance + $aRouteLegsSecondary[0]->summary->distance);
}
//Starting Location
$starturl = "https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&location=". $aRouteLegs[0]->startWaypointLocation->latitude ."%2C". $aRouteLegs[0]->startWaypointLocation->longitude ."&outFormat=json&thumbMaps=false";
$startfiledata = file_get_contents($starturl);
$startdata = json_decode($startfiledata);
$startLocation = $startdata->results[0]->locations[0]->adminArea1;
array_push($aPassedCountries,$startLocation);
//End Location
$endurl = "https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&location=". $aRouteLegs[0]->endWaypointLocation->latitude ."%2C". $aRouteLegs[0]->endWaypointLocation->longitude ."&outFormat=json&thumbMaps=false";
$endfiledata = file_get_contents($endurl);
$enddata = json_decode($endfiledata);
$endLocation = $enddata->results[0]->locations[0]->adminArea1;
// array_push($aPassedCountries,$startLocation);
foreach($aRouteLegs[0]->itineraryItems as $routeLeg){
if($whitelist){
$whitelist = false;
$url = "https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&location=". $routeLeg->coordinate->latitude ."%2C". $routeLeg->coordinate->longitude ."&outFormat=json&thumbMaps=false";
$filedata = file_get_contents($url);
$data = json_decode($filedata);
foreach($data->results as $obj){
array_push($aPassedCountries,$obj->locations[0]->adminArea1);
}
}
if(isset($routeLeg->warnings)){
foreach($routeLeg->warnings as $warning){
if (strpos($warning->text,'Entering') !== false && strpos($warning->text,',') !== false) {
$whitelist = true;
}
if(strpos($warning->text,'tiMetable') !== false){
$whitelist = true;
}
}
}
}
//secondary route
if($overseas){
//Starting Location
$starturlsecondary = "https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&location=". $aRouteLegsSecondary[0]->startWaypointLocation->latitude ."%2C". $aRouteLegsSecondary[0]->startWaypointLocation->longitude ."&outFormat=json&thumbMaps=false";
$startfiledatasecondary = file_get_contents($starturlsecondary);
$startdatasecondary = json_decode($startfiledatasecondary);
$startLocationsecondary = $startdatasecondary->results[0]->locations[0]->adminArea1;
array_push($aPassedCountries,$startLocationsecondary);
//sea distance
$seadistance = 10563;
foreach($aRouteLegsSecondary[0]->itineraryItems as $routeLeg){
if($whitelist){
$whitelist = false;
$url = "https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&location=". $routeLeg->coordinate->latitude ."%2C". $routeLeg->coordinate->longitude ."&outFormat=json&thumbMaps=false";
$filedata = file_get_contents($url);
$data = json_decode($filedata);
foreach($data->results as $obj){
array_push($aPassedCountries,$obj->locations[0]->adminArea1);
}
}
if(isset($routeLeg->warnings)){
foreach($routeLeg->warnings as $warning){
if (strpos($warning->text,') !== false) {
$whitelist = true;
}
if(strpos($warning->text,'tiMetable') !== false){
$whitelist = true;
}
}
}
}
}
$aPassedCountries = array_unique($aPassedCountries);
$jsonPath = 'https://www.mega-inliner.com/wp-content/plugins/mega-inliner-calculator/json/max_weight_road.json';
$json = file_get_contents($jsonPath);
$aMaxWeight = json_decode($json);
$aLowestCountryWeight = array();
foreach($aPassedCountries as $Country){
foreach($aMaxWeight as $country){
if($country->CountryCode == $Country){
array_push($aLowestCountryWeight,$country->MaxWeight);
}
}
}
echo json_encode(array("error" => "0","distance" => $Routedistance,"seadistance" => $seadistance,"time" => $RouteTime,"passedcountries" => $aPassedCountries,"lowestcountryweights" => $aLowestCountryWeight,"lowestcountryweight" => min($aLowestCountryWeight),"startLocation" => $startLocation,"endLocation" => $endLocation));
}
else{
echo json_encode(array("error" => "1","legs" => "No legs found."));
}
?>
来自 main.js 的相关代码:
function getRouteRequest() {
function renderBingMap() {
map = new Microsoft.Maps.Map('#routemap',{
disableBirdseye: true,enableClickablelogo: false,navigationBarMode: Microsoft.Maps.NavigationBarMode.minified,showTrafficButton: false,showTermsLink: false
});
if(overseas){
$("#routemap2").css("display","block");
$("#routemap2info").css("display","block");
map2 = new Microsoft.Maps.Map('#routemap2',{
disableBirdseye: true,showTermsLink: false
});
}
Microsoft.Maps.loadModule('Microsoft.Maps.Directions',function () {
directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
var startPoint = new Microsoft.Maps.Directions.Waypoint({ address: $("#routestart").val() });
directionsManager.addWaypoint(startPoint);
if(overseas){
var destinationPoint = new Microsoft.Maps.Directions.Waypoint({ address: overseasPortLocation1.city });
directionsManager.addWaypoint(destinationPoint);
}
else{
var destinationPoint = new Microsoft.Maps.Directions.Waypoint({ address: $("#routedestination").val() });
directionsManager.addWaypoint(destinationPoint);
}
Microsoft.Maps.Events.addHandler(directionsManager,'directionsError',directionsError);
Microsoft.Maps.Events.addHandler(directionsManager,'directionsUpdated',directionsUpdated);
directionsManager.calculateDirections();
if(overseas){
directionsManager2 = new Microsoft.Maps.Directions.DirectionsManager(map2);
var startPoint = new Microsoft.Maps.Directions.Waypoint({ address: overseasPortLocation2.city });
directionsManager2.addWaypoint(startPoint);
var destinationPoint = new Microsoft.Maps.Directions.Waypoint({ address: $("#routedestination").val() });
directionsManager2.addWaypoint(destinationPoint);
Microsoft.Maps.Events.addHandler(directionsManager2,directionsError);
Microsoft.Maps.Events.addHandler(directionsManager2,directionsUpdated2);
directionsManager2.calculateDirections();
}
});
}
renderBingMap();
}
function directionsUpdated(e) {
scrollToPosition("resultmodal");
if(!BingMapRender){
if(!BingMapSecondRender){
$("#resetroutebtn").css("display","block");
}
else{
BingMapSecondRender = false;
}
}
$(".modal-body > .loader").css("display","block");
//primary route
var routeIdx = directionsManager.getRequestOptions().routeIndex;
var aRouteLegs = [];
aRouteLegs = e.route[routeIdx].routeLegs;
primaryRoute = JSON.stringify(aRouteLegs);
calculateRoute();
}
function directionsUpdated2(e) {
scrollToPosition("resultmodal");
$(".modal-body > .loader").css("display","block");
if(!BingMapRenderSecondary){
if(!BingMapSecondRenderSecondary){
$("#resetroutebtn").css("display","block");
}
else{
BingMapSecondRenderSecondary = false;
}
}
//secondary route
var routeIdxOverseas = directionsManager2.getRequestOptions().routeIndex;
var aRouteLegsOverseas = [];
aRouteLegsOverseas = e.route[routeIdxOverseas].routeLegs;
secondaryRoute = JSON.stringify(aRouteLegsOverseas);
calculateRoute();
}
function calculateRoute() {
$.ajax({
url: "/wp-content/plugins/mega-inliner-calculator/PHP/bingroutecalculation.PHP",type: "POST",dataType: 'JSON',data: {
data : primaryRoute,dataSecondary : secondaryRoute,overseas : overseas
},success: function(result){
console.log(result);
if(result.error != 0){
$(".modal-dialog").css("display","none");
$(".modal-body > .results").css("display","none");
$(".modal-body > .loader").css("display","none");
$("#routealerterrormessage").html("We don't have enough information in our system to make a calculation for this route.");
$(".routealert").css("display","block");
$(".routealert").css("opacity","1");
scrollToPosition('routeinputs');
}
else{
if(result.lowestcountryweights.length > 0){
displayResults(result.distance,result.seadistance,result.lowestcountryweight,result.passedcountries);
}
else{
$(".modal-dialog").css("display","none");
$(".modal-body > .results").css("display","none");
$(".modal-body > .loader").css("display","none");
$("#routealerterrormessage").html("We don't have enough information in our system to make a calculation for this route.");
$(".routealert").css("display","block");
$(".routealert").css("opacity","1");
scrollToPosition('routeinputs');
}
}
},error: function(xhr) {
console.log(xhr.responseText);
}
});
}
function findnearestportdistance(lat1,lon1,lat2,lon2,unit) {
var radlat1 = Math.PI * lat1/180
var radlat2 = Math.PI * lat2/180
var theta = lon1-lon2
var radtheta = Math.PI * theta/180
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;
}
dist = Math.acos(dist)
dist = dist * 180/Math.PI
dist = dist * 60 * 1.1515
if (unit=="K") { dist = dist * 1.609344 }
if (unit=="N") { dist = dist * 0.8684 }
return dist
}
function findnearestport(lat,lng){
var nearestLocation = 99999;
var nearestPort;
var json = { };
$.ajax({
url: "/wp-content/plugins/mega-inliner-calculator/json/ports.json",dataType: 'json',async: false,success: function(result) {
json = result;
}
});
for (var i = 0; i < json.ports.length; i++){
var obj = json.ports[i];
if(obj['type'] == "Seaport"){
var distancetoport = findnearestportdistance(lat,lng,obj['geolat'],obj['geolong'],"K");
if(distancetoport < nearestLocation){
nearestLocation = distancetoport;
nearestPort = obj;
}
}
}
return nearestPort;
}
现在我已经给了海距一个固定值,但我希望计算器根据 2 个港口计算最短的海路。我不想显示路线,我只想显示从港口 1 到港口 2 的海里距离。有关示例,请参阅:https://sea-distances.org/。这就是我想添加到我的计算器中的内容。有人知道吗?
解决方法
Marine Traffic 有一个很好的 API 来进行这类计算。函数 VI03 -Port Distances and Routes 将计算端口之间的距离(简单响应),甚至提供轨迹(扩展响应)。
简单的响应将为您提供以海里为单位的距离以及船舶是否必须通过巴拿马运河、苏伊士运河或两者。
然而,正如您所料,这不是免费的,每次调用都需要 API 积分或订阅。
同样,searoutes.com 提供了类似的 API,但您必须再次订阅才能访问。
另一种方法是找到一个距离矩阵来显示每个端口之间的距离。
这里有一个公开的国家/地区距离列表:https://zenodo.org/record/46822#.YNGpZEzTWUm。但这并不完全是您想要的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。