genthalili / searoute-py

A python package to calculate the shortest sea route between two points on Earth.
Apache License 2.0
81 stars 17 forks source link

Missing points when crossing from America to Asia through Pacific #11

Closed juanjops closed 1 year ago

juanjops commented 1 year ago

First off Great Library!

Just found an issue, when crossing from America to Asia through the pacific, the line of points misses some points, the ones after lon changes from negative to positive again, in the international day line, I cannot tell if the time calculated in hours is correct either, many thanks,

import searoute as sr
origin = [-94.572149, 29.351375]
destination = [117.42187500000001, 39.36827914916014]
route = sr.searoute(origin, destination, restrictions=["suez", "northwest"], append_orig_dest=False)
lon, lat = zip(*route.geometry["coordinates"])

image

juanjops commented 1 year ago

similar issue when going from usa to asia through Mediterranean sea, big gap of points in the Atlantic ocean image

genthalili commented 1 year ago

Hi @juanjops, thanks for the good words and hopefully this pckg is helping your project.

I checked your example and for me it shows correctly the linestring :

image

The source of your issue might be:

  1. check if your are not using an older version of this package
  2. check if something is incompatible with your map reading lon numbers <-180 .. like -220..

the geometry retured, I have :

{"geometry": {"coordinates": [[-94.6251, 29.3068], [-94.3779, 29.1479], [-93.8617, 28.8261], [-92.8863, 28.2242], [-90.8482, 26.185], [-86.05, 21.7333], [-82.8698, 16.0793], [-80, 9.75], [-79.900612, 9.208176], [-79.821304, 9.173012], [-79.803246, 9.118307], [-79.769669, 9.111314], [-79.741379, 9.118236], [-79.689331, 9.10639], [-79.641747, 9.035982], [-79.585922, 8.992656], [-79.494118, 8.796576], [-79.5, 8.6], [-80, 7], [-81.4, 6.9], [-82.8, 7.4167], [-88.3178, 10.1973], [-93.9243, 12.9057], [-99.644, 15.5163], [-105.5, 18], [-108.2357, 20.1502], [-111.0067, 22.3104], [-113.4508, 24.926], [-116.130461, 27.989265], [-120, 30], [-124.5844, 32.7301], [-129.4201, 35.3367], [-134.5487, 37.7741], [-140, 40], [-144.8826, 40.7555], [-149.8621, 41.3037], [-154.9099, 41.6367], [-159.9932, 41.749], [-165.0775, 41.6384], [-170.128, 41.3066], [-175.1119, 40.758], [-180, 40], [-180, 40], [-184.9996, 40.1067], [-190, 40], [-194.9996, 40.1067], [-200, 40], [-204.9996, 40.1067], [-207.127084, 40.061324], [-210, 40], [-217.75, 40.6], [-218.75, 41.9], [-220.6, 41.2], [-225.9157, 38.2106], [-230.8, 35], [-232.4, 34.2], [-234.4, 34.4], [-236.8, 37.1], [-237.8175, 37.8155], [-239.5204, 38.1013], [-241.8275, 38.7726]], "type": "LineString"}, "properties": {"duration_hours": 438.0691885561147, "length": 19471.299292942185, "units": "km"}, "type": "Feature"}

For the duration in hours is directly connected to the distance and speed (speed_knot by default it's 24, but you can change as per your need)

juanjops commented 1 year ago

Thanks for solving the issue of the lon < -180,

What about the second case? Could you check why the gap in points in the atlantic?

origin = [134.034736, 39.033257]

destination = [-94.659328, 29.168505]

route = sr.searoute(origin, destination, restrictions=["panama", "northwest"])

This is the output i receive

{"coordinates": [[134.2305, 39.6591], [129.3, 37.9], [130, 36.4], [129.2, 35], [127.6, 34.2], [122.9, 31.3], [122.6776, 30.8345], [122.875214, 30.181935], [122.211914, 28.733947], [121.3, 27.8], [120, 25.7], [119.761963, 25.085599], [118.937988, 24.542126], [118.103027, 23.765237], [117, 23], [114.1, 21.7], [112.0495, 16.9609], [110.1, 12.2], [107.3207, 7.6091], [104.482294, 1.341312], [103.6, 1.1], [102, 2], [100.6, 3.2], [97, 7], [94, 6.7], [90, 6.4664], [90.0001, 6.4665], [85.9479, 6.1983], [81.9, 5.9], [80.1, 5.8], [76.5251, 6.8131], [72.9354, 7.8014], [69.3291, 8.7613], [65.7044, 9.6889], [62.0601, 10.5802], [58.3951, 11.4317], [54.7085, 12.2395], [51, 13], [45, 12], [43.3, 12.7], [42, 15], [41.2, 16.3], [38.9, 20.75], [37, 23.6], [34.5, 27], [33.75, 27.9], [32.6, 29.7], [32.557983, 30.213982], [32.382202, 30.318359], [32.306671, 30.945814], [32.387159, 31.298117], [32.1, 31.7], [27.6298, 33.328], [23, 34.8], [15.2, 36.4], [11, 37.5], [7.5, 37.4], [3.1, 37.2], [-4.7, 36], [-5.269383, 35.97289], [-5.75, 35.95], [-64.6416, 31.9639], [-70, 30], [-74.4754, 28.2202], [-77.982056, 26.921361], [-77.968872, 26.86037], [-77.641418, 26.677553], [-77.698059, 26.513377], [-78.164429, 26.280548], [-78.8, 26.3], [-79.5356, 26.0942], [-79.815, 25.7903], [-79.9482, 25.3329], [-80.0286, 25.1157], [-80.3533, 24.7537], [-80.8143, 24.504], [-81.825, 24.2187], [-84.2612, 25.5211], [-85.7171, 26.3095], [-88.4725, 28.1053], [-89.8999, 28.2842], [-91.298, 28.4321], [-91.5477, 28.5846], [-93.214, 29.13], [-93.6685, 29.1321], [-94.3779, 29.1479], [-94.4267, 29.1293], [-94.609, 29.2761]], "type": "LineString"}

genthalili commented 1 year ago

It's because there is a straight line between the Point close to Spain and middle of the Atlantic ocean.

If you need to have Points, let say every 200km, you can do something like this:

import turfpy
import numpy as np
from geojson import FeatureCollection
#assuming that route is the result from searoute
length = route['properties']['length']
unit = route['properties']['units']
a_each = 200 #a point every 200 km (or unit)
lines = []

for i in np.arange(0.0, length, a_each):
    #https://turfpy.readthedocs.io/en/latest/measurements/along.html
    lines.append(turfpy.measurement.along(route,i,unit))

fc = FeatureCollection(lines)

Hope this helps..

image
juanjops commented 1 year ago

Many thanks for the solution!!, it worked perfectly.