title: Calculate port to port over sea distance
body: <p>I'm currently working on a calculator that calculates a lot of things and one of these things is the route from 2 given points. Now I want to extand this route calculator by adding the over sea route distance from one port to the other port. The calculator already looks for the most nearby port from the two given locations. But now I'm stuck by adding the over sea route distance.</p>
  <p>This is my code so far</p>
  <p>bingroutecalculation.php</p>
  <pre><code>&lt;?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']) &amp;&amp; isset($_POST['dataSecondary'])){
              if($_POST['overseas'] == &quot;true&quot;){
                  $overseas = true;
                  $aRouteLegsSecondary = json_decode(stripslashes($_POST['dataSecondary']));
              }
          }
  
          $RouteDistance = $aRouteLegs[0]-&gt;summary-&gt;distance;
          $RouteTime = $aRouteLegs[0]-&gt;summary-&gt;time;
  
          if($overseas){
              $RouteDistance = ($aRouteLegs[0]-&gt;summary-&gt;distance + $aRouteLegsSecondary[0]-&gt;summary-&gt;distance);
          }
  
          //Starting Location
          $starturl = &quot;https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&amp;location=&quot;. $aRouteLegs[0]-&gt;startWaypointLocation-&gt;latitude .&quot;%2C&quot;. $aRouteLegs[0]-&gt;startWaypointLocation-&gt;longitude .&quot;&amp;outFormat=json&amp;thumbMaps=false&quot;;
          $startfiledata = file_get_contents($starturl);
          $startdata = json_decode($startfiledata);
          $startLocation = $startdata-&gt;results[0]-&gt;locations[0]-&gt;adminArea1;
          array_push($aPassedCountries, $startLocation);
  
          //End Location
          $endurl = &quot;https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&amp;location=&quot;. $aRouteLegs[0]-&gt;endWaypointLocation-&gt;latitude .&quot;%2C&quot;. $aRouteLegs[0]-&gt;endWaypointLocation-&gt;longitude .&quot;&amp;outFormat=json&amp;thumbMaps=false&quot;;
          $endfiledata = file_get_contents($endurl);
          $enddata = json_decode($endfiledata);
          $endLocation = $enddata-&gt;results[0]-&gt;locations[0]-&gt;adminArea1;
          // array_push($aPassedCountries, $startLocation);
  
  
          foreach($aRouteLegs[0]-&gt;itineraryItems as $routeLeg){
              if($whitelist){
                  $whitelist = false;
  
                  $url = &quot;https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&amp;location=&quot;. $routeLeg-&gt;coordinate-&gt;latitude .&quot;%2C&quot;. $routeLeg-&gt;coordinate-&gt;longitude .&quot;&amp;outFormat=json&amp;thumbMaps=false&quot;;
                  $filedata = file_get_contents($url);
                  $data = json_decode($filedata);
  
                  foreach($data-&gt;results as $obj){
                      array_push($aPassedCountries, $obj-&gt;locations[0]-&gt;adminArea1);
                  }
              }
  
              if(isset($routeLeg-&gt;warnings)){
                  foreach($routeLeg-&gt;warnings as $warning){
                      if (strpos($warning-&gt;text, 'Entering') !== false &amp;&amp; strpos($warning-&gt;text, ', ') !== false) {
                          $whitelist = true;
                      }
  
                      if(strpos($warning-&gt;text, 'timetable') !== false){
                          $whitelist = true;
                      }
                  }
              }
          }
  
          //secondary route
          if($overseas){
              //Starting Location
              $starturlsecondary = &quot;https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&amp;location=&quot;. $aRouteLegsSecondary[0]-&gt;startWaypointLocation-&gt;latitude .&quot;%2C&quot;. $aRouteLegsSecondary[0]-&gt;startWaypointLocation-&gt;longitude .&quot;&amp;outFormat=json&amp;thumbMaps=false&quot;;
              $startfiledatasecondary = file_get_contents($starturlsecondary);
              $startdatasecondary = json_decode($startfiledatasecondary);
              $startLocationsecondary = $startdatasecondary-&gt;results[0]-&gt;locations[0]-&gt;adminArea1;
              array_push($aPassedCountries, $startLocationsecondary);
  
  
              //sea distance
              $seaDistance = 10563;
                              
  
              foreach($aRouteLegsSecondary[0]-&gt;itineraryItems as $routeLeg){
                  if($whitelist){
                      $whitelist = false;
      
                      $url = &quot;https://www.mapquestapi.com/geocoding/v1/reverse?key=[API-KEY]&amp;location=&quot;. $routeLeg-&gt;coordinate-&gt;latitude .&quot;%2C&quot;. $routeLeg-&gt;coordinate-&gt;longitude .&quot;&amp;outFormat=json&amp;thumbMaps=false&quot;;
                      $filedata = file_get_contents($url);
                      $data = json_decode($filedata);
      
                      foreach($data-&gt;results as $obj){
                          array_push($aPassedCountries, $obj-&gt;locations[0]-&gt;adminArea1);
                      }
                  }
      
                  if(isset($routeLeg-&gt;warnings)){
                      foreach($routeLeg-&gt;warnings as $warning){
                          if (strpos($warning-&gt;text, 'Entering') !== false &amp;&amp; strpos($warning-&gt;text, ', ') !== false) {
                              $whitelist = true;
                          }
      
                          if(strpos($warning-&gt;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-&gt;CountryCode == $Country){
                      array_push($aLowestCountryWeight, $country-&gt;MaxWeight);
                  }
              }
          }
  
          echo json_encode(array(&quot;error&quot; =&gt; &quot;0&quot;, &quot;distance&quot; =&gt; $RouteDistance, &quot;seadistance&quot; =&gt; $seaDistance, &quot;time&quot; =&gt; $RouteTime, &quot;passedcountries&quot; =&gt; $aPassedCountries, &quot;lowestcountryweights&quot; =&gt; $aLowestCountryWeight, &quot;lowestcountryweight&quot; =&gt; min($aLowestCountryWeight), &quot;startLocation&quot; =&gt; $startLocation, &quot;endLocation&quot; =&gt; $endLocation));
      }
      else{
          echo json_encode(array(&quot;error&quot; =&gt; &quot;1&quot;, &quot;legs&quot; =&gt; &quot;No legs found.&quot;));
      }
  ?&gt;
  </code></pre>
  <p>Relevant code from main.js:</p>
  <pre><code>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){
                      $(&quot;#routemap2&quot;).css(&quot;display&quot;, &quot;block&quot;);
                      $(&quot;#routemap2info&quot;).css(&quot;display&quot;, &quot;block&quot;);
                      map2 = new Microsoft.Maps.Map('#routemap2', {
                          disableBirdseye: true,
                          enableClickableLogo: false,
                          navigationBarMode: Microsoft.Maps.NavigationBarMode.minified,
                          showTrafficButton: false,
                          showTermsLink: false
                      });
                  }
  
                  Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function () {
                      directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
                      
                      var startPoint = new Microsoft.Maps.Directions.Waypoint({ address: $(&quot;#routestart&quot;).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: $(&quot;#routedestination&quot;).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: $(&quot;#routedestination&quot;).val() });
                          directionsManager2.addWaypoint(destinationPoint);
                          
                          Microsoft.Maps.Events.addHandler(directionsManager2, 'directionsError', directionsError);
                          Microsoft.Maps.Events.addHandler(directionsManager2, 'directionsUpdated', directionsUpdated2);
                          
                          directionsManager2.calculateDirections();
                      }
                  });
              }
              
              renderBingMap();
          }
          
          function directionsUpdated(e) {
              scrollToPosition(&quot;resultmodal&quot;);
  
              if(!BingMapRender){
                  if(!BingMapSecondRender){
                      $(&quot;#resetroutebtn&quot;).css(&quot;display&quot;, &quot;block&quot;);
                  }
                  else{
                      BingMapSecondRender = false;
                  }
              }
  
              $(&quot;.modal-body &gt; .loader&quot;).css(&quot;display&quot;, &quot;block&quot;);
  
  
              //primary route
              var routeIdx = directionsManager.getRequestOptions().routeIndex;
              var aRouteLegs = [];
              aRouteLegs = e.route[routeIdx].routeLegs;
              primaryRoute = JSON.stringify(aRouteLegs);
                  
              calculateRoute();
          }
  
          function directionsUpdated2(e) {
              scrollToPosition(&quot;resultmodal&quot;);
              $(&quot;.modal-body &gt; .loader&quot;).css(&quot;display&quot;, &quot;block&quot;);
  
              if(!BingMapRenderSecondary){
                  if(!BingMapSecondRenderSecondary){
                      $(&quot;#resetroutebtn&quot;).css(&quot;display&quot;, &quot;block&quot;);
                  }
                  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: &quot;/wp-content/plugins/mega-inliner-calculator/php/bingroutecalculation.php&quot;,
                  type: &quot;POST&quot;,
                  dataType: 'JSON',
                  data: {
                      data : primaryRoute,
                      dataSecondary : secondaryRoute,
                      overseas : overseas
                  },
                  success: function(result){
                      console.log(result);
  
                      if(result.error != 0){
                          $(&quot;.modal-dialog&quot;).css(&quot;display&quot;, &quot;none&quot;);
                          $(&quot;.modal-body &gt; .results&quot;).css(&quot;display&quot;, &quot;none&quot;);
                          $(&quot;.modal-body &gt; .loader&quot;).css(&quot;display&quot;, &quot;none&quot;);
  
                          $(&quot;#routealerterrormessage&quot;).html(&quot;We don't have enough information in our system to make a calculation for this route.&quot;);
                          $(&quot;.routealert&quot;).css(&quot;display&quot;, &quot;block&quot;);
                          $(&quot;.routealert&quot;).css(&quot;opacity&quot;, &quot;1&quot;);
                          scrollToPosition('routeinputs');
                      }
                      else{
                          if(result.lowestcountryweights.length &gt; 0){
                              displayResults(result.distance, result.seadistance, result.lowestcountryweight, result.passedcountries);
                          }
                          else{
                              $(&quot;.modal-dialog&quot;).css(&quot;display&quot;, &quot;none&quot;);
                              $(&quot;.modal-body &gt; .results&quot;).css(&quot;display&quot;, &quot;none&quot;);
                              $(&quot;.modal-body &gt; .loader&quot;).css(&quot;display&quot;, &quot;none&quot;);
  
                              $(&quot;#routealerterrormessage&quot;).html(&quot;We don't have enough information in our system to make a calculation for this route.&quot;);
                              $(&quot;.routealert&quot;).css(&quot;display&quot;, &quot;block&quot;);
                              $(&quot;.routealert&quot;).css(&quot;opacity&quot;, &quot;1&quot;);
                              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 &gt; 1) {
                  dist = 1;
              }
              dist = Math.acos(dist)
              dist = dist * 180/Math.PI
              dist = dist * 60 * 1.1515
              if (unit==&quot;K&quot;) { dist = dist * 1.609344 }
              if (unit==&quot;N&quot;) { dist = dist * 0.8684 }
              return dist
          }
  
          function findnearestport(lat, lng){
              var nearestLocation = 99999;
              var nearestPort;
  
              var json = { };
              $.ajax({
                  url: &quot;/wp-content/plugins/mega-inliner-calculator/json/ports.json&quot;,
                  dataType: 'json',
                  async: false,
                  success: function(result) {
                      json = result;
                  }
              });
  
              for (var i = 0; i &lt; json.ports.length; i++){
                  var obj = json.ports[i];
                  if(obj['type'] == &quot;Seaport&quot;){
                      var distancetoport = findnearestportdistance(lat, lng, obj['geolat'], obj['geolong'], &quot;K&quot;);
                      if(distancetoport &lt; nearestLocation){
                          nearestLocation = distancetoport;
                          nearestPort = obj;
                      }
                  }
              }
  
              return nearestPort;
          }
  
  </code></pre>
  <p>For now I have given the sea distance an fixed value, but I want the calculator to calculate the shortest sea route based on the 2 ports. I don't want to show the route I only want the distance from port 1 to port 2 in nautical miles. For an example see: <a href="https://sea-distances.org/" rel="nofollow noreferrer">https://sea-distances.org/</a>. This is what I want to add to my calculator. Anyone any idea?</p>