从沿海点A到沿海点B,找到海上路径

时间:2011-11-14 10:59:15

标签: algorithm google-maps google-maps-api-3 gis geocoding

我有一个看似棘手的挑战,试图通过海路从一个海港到另一个海港。最终的目标是将其作为折线在Google(或Bing)地图上绘制。

路径需要:

  • 看似合理,因为船不能越过陆地(显然)
  • 不要太靠近海岸线。船不能靠近岸边
  • 不要太复杂。它将在Google地图上绘制,因此2000点折线不会。
  • 是最短的,但不能牺牲上述三点

所以,我的第一个想法是获取全球海岸线的数据。这样的事情可以here。不幸的是,它不完整。 OpenStreetMap显示此数据和加勒比岛屿等海岸线的遗失。

我还考虑过地理编码(不够可靠,加上我会烧掉数千个试图绘制路线的请求)

我的下一个想法是以某种方式使用Google地图并测试点是否为蓝色。 GMaps.NET是一个很棒的.NET Mapping组件,它允许我通过创建它渲染的位图并测试像素的颜色来实现这一点。

第一个问题是这个命中测试的准确性仅与我测试的图像的分辨率图像一样好。对于彼此靠近的端口,这对于更远的端口来说是好的,精度会受到影响。

第二个问题,假设我使用某种“蓝色像素测试”方法,是什么算法适合查找路线。 A* algorithm看起来很有希望,但我不确定如何将这条路从“存在”推向“靠近海岸”。也不是如何降低折线的复杂性。

所以... 任何输入:欢迎提出想法,想法,链接,示例代码等。感谢。

(我应该补充一点,这是一个旅游网站。准确性不是太重要,我不是指导运输或任何东西)

4 个答案:

答案 0 :(得分:3)

简化折线,例如: A *搜索,您可以使用Douglas-Peucker之类的算法。另请参阅此参考列表:http://maven.smith.edu/~orourke/TOPP/P24.html

另类想法:应用A *的常用方法是将每个像素视为可能的状态(位置),但没有理由不使用像素的子集作为可能的状态。如果你使开始点和终点附近的状态密度高,并且远离任一端点的状态密度低,那么你将自动获得以短而精确的运动开始和结束的路径,但在中间有长的直线段(例如,当穿越太平洋时)。如果你这样做,你可能还想增加陆地附近的位置密度。

另一种可能的A *调整:您可以将“当前方向”合并到状态中,并惩罚导致方向改变的移动。这将在您的路径中产生长直线。这会使你的状态空间乘以8,但这可能是可以忍受的。因为您只是增加了解决方案的成本,所以通常使用的直线到目标启发式算法仍然可以接受这个新的成本函数,因此不会出现任何复杂情况。

答案 1 :(得分:2)

  

第二个问题,假设我使用某种'蓝色像素测试'方法,是什么算法适合寻找路线。 A *算法看起来很有希望,但我不确定如何将路径从“存在”推向“靠近海岸”。也不是如何降低折线的复杂性。

首先创建世界的二进制海图像(白色:是海,黑色:不是海),然后侵蚀图像。侵蚀后的所有白点都可以通航。当然,忽略了一两个奇怪的沙洲。

正如您可能猜到的那样,这种方法揭示了寻路中的一个核心问题:大多数船只必须非常靠近陆地才能到达港口,违反了导航规则。但是,这可以通过在与给定港口相邻的最近的可通航海点开始导航来解决。

答案 2 :(得分:1)

这是一个使用R的解决方案。只需将某些区域的最短路径算法变得昂贵或便宜,就可以对其进行改进。例如,排除北冰洋,允许主要河流/运河,使已知的运输路线适合旅行。

library(raster)
library(gdistance)
library(maptools)
library(rgdal)

# make a raster of the world, low resolution for simplicity
# with all land having "NA" value
# use your own shapefile or raster if you have it
# the wrld_simpl data set is from maptools package
data(wrld_simpl)

# a typical world projection
world_crs <- crs(wrld_simpl)
world <- wrld_simpl
worldshp <- spTransform(world, world_crs)
ras <- raster(nrow=300, ncol=300)

# rasterize will set ocean to NA so we just inverse it
# and set water to "1"
# land is equal to zero because it is "NOT" NA
worldmask <- rasterize(worldshp, ras)
worldras <- is.na(worldmask)

# originally I set land to "NA"
# but that would make some ports impossible to visit
# so at 999 land (ie everything that was zero)
# becomes very expensive to cross but not "impossible" 
worldras[worldras==0] <- 999
# each cell antras now has value of zero or 999, nothing else

# create a Transition object from the raster
# this calculation took a bit of time
tr <- transition(worldras, function(x) 1/mean(x), 16)
tr = geoCorrection(tr, scl=FALSE)

# distance matrix excluding the land, must be calculated
# from a point of origin, specified in the CRS of your raster
# let's start with latlong in Black Sea as a challenging route
port_origin <- structure(c(30, 40), .Dim = 1:2)
port_origin <- project(port_origin, crs(world_crs, asText = TRUE))
points(port_origin)

# function accCost uses the transition object and point of origin
A <- accCost(tr, port_origin)

# now A still shows the expensive travel over land
# so we mask it out to display sea travel only
A <- mask(A, worldmask, inverse=TRUE)

# and calculation of a travel path, let's say to South Africa
port_destination <- structure(c(20, -35), .Dim = 1:2)
port_destination <- project(port_destination, crs(world_crs, asText = TRUE))

path <- shortestPath(tr, port_origin, port_destination, output = "SpatialLines")

# make a demonstration plot
plot(A)
points(rbind(port_origin, port_destination))
lines(path)

# we can wrap all this in a customized function
# if you two points in the projected coordinate system,
# and a raster whose cells are weighted 
# according to ease of shipping
RouteShip <- function(from_port, to_port, cost_raster, land_mask) {
  tr <- transition(cost_raster, function(x) 1/mean(x), 16)
  tr = geoCorrection(tr, scl=FALSE)
  A <- accCost(tr, from_port)
  A <- mask(A, land_mask, inverse=TRUE)
  path <- shortestPath(tr, from_port, to_port, output = "SpatialLines")

  plot(A)
  points(rbind(from_port, to_port))
  lines(path)
}

RouteShip(port_origin, port_destination, worldras, worldmask)

enter image description here

答案 3 :(得分:0)

如果我是你,我会选择图论方法。您唯一的问题是收集数据库的边缘。如果你有它们,你可以使用A *或Dijkstra的算法来规划最短的路线。 无论如何,如果我认为正确,你需要类似于(Searoutefinder)的东西吗?祝你好运!