在 GIS 生成的网络中,Turtle 无法 select 到达目的地的路径,除非删除重复和未连接的节点

Turtle cannot select path to destination in GIS generated network unless duplicate and unconnected nodes are removed

我一直在尝试研究如何让一只乌龟根据 GIS 路线图在网络中从一个节点移动到另一个节点。问题是乌龟无法使用 nw:turtles-on-path-to 设置路径,除非我删除节点重复项和未连接的节点(我使用的相关代码块来自其他人的模型)。下面是我删除重复项和未连接节点时有效的代码:

    foreach gis:feature-list-of roads-dataset [ vector-feature ->
    foreach  gis:vertex-lists-of vector-feature [ vertex ->
      let previous-turtle nobody
      let first-turtle nobody
      foreach vertex [point ->
        let location gis:location-of point
        if not empty? location
        [ 
          create-nodes 1
          [ set myneighbours n-of 0 turtles
            set xcor item 0 location
            set ycor item 1 location
            set road-type gis:property-value vector-feature "Classification"
            ;set shape "circle"
            ;set size 0.5
            ifelse previous-turtle = nobody
            [ set first-turtle self ]
            [ create-link-with previous-turtle ]
            set hidden? true
            set previous-turtle self ]
        ]
      ]
    ] ]

    delete-duplicates
    ask nodes [ set myneighbours link-neighbors ]

    delete-not-connected
    ask nodes [ set myneighbours link-neighbors ]

    to delete-duplicates
      ask nodes [
        if count nodes-here with [ description = "road" ] > 1[
          ask other nodes-here with [ description = "road" ][

            ask myself [create-links-with other [link-neighbors] of myself]
            die]
        ]
        ]
    end   

    to delete-not-connected
       ask nodes [set test 0]
       ask one-of nodes [set test 1]
         repeat 500 [
           ask nodes with [test = 1]
           [ask myneighbours [set test 1]]]
       ask nodes with [test = 0][die]
    end

    to go
      ask person [
        if destination = 0 [ create-link select-destination ]
        if mypath = 0 [ select-path ]
        if mypath != 0 [ move ]
      ]
      tick
    end

    to create-link
      create-link-with min-one-of nodes [ distance myself ]
      ask links [ set hidden? true ]
    end

    to select-destination
      set destination one-of nodes with [ road-type = "main road" ]
    end

    to select-path
      set mypath nw:turtles-on-path-to destination
    end

    to move
     ifelse length mypath > 0
     [ move-to item 0 mypath set mypath remove-item 0 mypath ]
     [ stop ]
    end

这段代码工作得很好。然而,在删除重复和未连接的节点后,道路网络会发生扭曲——道路网络的外观与原始道路网络不一样。乌龟可以沿着网络移动的唯一方法是将代码保持在上面的格式中。如果我排除 delete-duplicatesdelete-not-connected 那么 mypath returns false.

请问有什么方法既可以保持原来网络的外观,又可以让乌龟自己设定路径,沿着路径移动到达目的地?除非使用 delete-duplicatesdelete-not-connected,否则不允许乌龟设置路径的问题是什么?

非常感谢您的支持。谢谢。

你确定delete-duplicates是必要的吗?我的猜测是 delete-not-connected 是必要的原因是因为没有它,select-destination 可以 select 海龟无法到达的节点。稍后我将介绍如何解决此问题。首先,您的代码存在一些问题,我们应该讨论一下。

首先,您让海龟在它们和它们当前位置之间创建一个 link。这有点奇怪,因为它本质上是在说这只乌龟是路网上的一条路,这是没有道理的。实际上,如果您希望海龟前往 select 新目的地,这会变得很奇怪。他们仍然会 link 使用他们开始的节点进行编辑!这将允许他们 "teleport" 在网络中。不好!相反,我建议创建一个名为 current-location 的海龟变量,它跟踪海龟所在的节点。

所以,create-link应该变成

to set-location
  set current-location min-one-of nodes [ distance myself ]
end

move 然后变成(我从你的代码中删除了 stop 因为它是不必要的):

to move
  if not empty? mypath [
    set current-location first mypath
    move-to current-location
    set mypath but-first mypath
  ]
end

select-path变为:

to select-path
  set mypath [ nw:turtles-on-path-to destination ] of current-location
end

其实,我们可以进一步简化这个。因为乌龟会跟踪它的当前位置,所以您不再需要自己跟踪路径。相反,删除 mypathselect-path 并将 move 更改为:

to move
  if current-location != destination [
    let next-node first [ nw:turtles-on-path-to destination ] of current-location
    set current-location next-node
    move-to current-location
  ]
end

并将go更改为:

to go
  ask person [
    if destination = 0 [
      set-location
      select-destination
    ]
    move
  ]
  tick
end

简单多了!请注意,这应该仍然很快,因为 nw 会记住节点之间的最短路径。如果你有一个非常大的网络或其他东西,你仍然可以根据需要自己跟踪路径,但我会先尝试这个。

好的,现在我们已准备好在不删除网络中任何内容的情况下修复断开连接的节点问题。基本上,select-destination 应该只选择乌龟可以到达的目的地。看起来像这样:

(编辑:此代码不正确。见下文)

to select-destination
  set destination one-of nodes with [
    road-type = "main road" and
    is-number? [ nw:distance-to [current-location] of myself ] of myself 
  ]
end

里面的[ nw:distance-to myself ] of myself会得到当前位置(第一个myself指的是什么)到潜在目的地(第二个[=33=指的是什么)的距离]指)。如果目标节点可以从源节点到达,nw:distance-to 将 return 一个数字(距离);否则它 returns false。所以 is-number? 检查以确保它确实给了我们一个号码。

希望这有助于解决您的问题,同时还能简化您的代码。重复的事情真的不应该重要。如果是,请回复评论或编辑您的问题,我会看看。

编辑:

感谢您上传模型和数据!我意识到我实际上搞砸了 select-destination 过程。应该是:

to select-destination
  set destination one-of [ nodes with [
    road-type = "road" and
    is-number? [ nw:distance-to myself ] of myself
  ] ] of current-location
end

也就是说,此人应该查询 current-location 可到达的道路。显然,由于人未联网,无法直接获得可达的道路。

接下来,看起来很严重的问题实际上是数据极度断开。您正在创建的网络包含 5619 个断开连接的组件,每个组件仅包含 3-5 个节点。所以难怪乌龟找不到它能到达的目的地!

我认为您可能对数据的解释不正确。我希望从不同功能列表创建的各种节点应该以某种方式连接,但你没有这样做(这就是为什么你最终会得到这么多断开连接的组件)。不幸的是,这是我们达到知识极限的地方;我对地理信息系统了解不多。我记得我的一位同事正在从事一个类似的项目,他不得不做一些事情,比如合并彼此重叠的顶点。这会将网络生成代码变成以下内容:

  foreach gis:feature-list-of roads-dataset [ vector-feature ->
    foreach  gis:vertex-lists-of vector-feature [ vertex ->
      let previous-turtle nobody
      foreach vertex [point ->
        let location gis:location-of point
        if not empty? location
        [
          let x item 0 location
          let y item 1 location
          let current-node one-of (turtles-on patch x y) with [ xcor = x and ycor = y ]
          if current-node = nobody [
            create-nodes 1 [
              setxy x y
              set shape "circle"
              set size 0.5
              set road-type "road"
              set hidden? true
              set current-node self
            ]
          ]
          ask current-node [
            if is-turtle? previous-turtle [
              create-link-with previous-turtle
            ]
            set previous-turtle self
          ]
        ]
      ]
    ]
  ]

这似乎是正确的。 (我还清理了一些我们正在做的事情)也就是说,它会查看 exact 位置是否已经有一个节点,如果有就连接到那个节点,否则它会创建一个新节点。

这是完整的更新代码:https://gist.github.com/qiemem/b59f3657bea34b9aa67648760b9c7471

我还调整了一些其他的东西:这个人现在在 setup 中设置他们的位置,这是有道理的:他们的位置在那之后应该正确更新。我在go的末尾添加了tick,所有模型都应该有。您可能希望将视图更新更改为 "on ticks"。最后,我让这个人在到达目的地进行测试时选择一个新位置。您现在可能想使 go 成为永久按钮;你会是从一个地方到另一个地方的人。

希望对您有所帮助!