使用 .shp 文件中的开始和结束节点创建和命名链接
Creating and naming links using start and end nodes from .shp file
.shp 文件的属性 table 格式如下:
street_name start_node end_node
street_1 A B
street_1 B C
street_2 B D
如何使用开始和结束节点创建 link,然后为每个 link 分配与其开始和结束节点关联的街道名称。例如,起始节点 A 和结束节点 B 的 link 应命名为 "street_1",起始节点 B 和结束节点 D 的街道应命名为 "street_2".
我使用 foreach gis:feature-list-of
到 link 数据集的节点,但是这样我就不能根据它们的开始和结束节点来命名 link,因为有些节点是在街段之间共享。
非常感谢。
编辑:
我感兴趣的属性table的列是name1、startNode和endNode。我已经使用下面的代码连接了节点,现在我有了一个完全连接的道路网络。我不确定如何集成您的代码,以便节点之间的 link 获得与构成 link 的节点组合相关联的名称。
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 size 0.2
set shape "circle"
set color black
set hidden? true
set name gis:property-value vector-feature "name1"
set current-node self
]
]
ask current-node [
if is-turtle? previous-turtle [
create-link-with previous-turtle
]
set previous-turtle self
]
]
]
]
]
你是说你的节点现在在你的模型中正确命名了吗?如果是这种情况,这里有一个可能对您有用的方法的简化版本。我会注意到这不是一个非常有效的方法来解决这个问题,因为它循环遍历你的 links 和你的属性 table,所以如果你有很多很多 links 它将需要一会儿。首先,因为我没有你的 shapefile,所以我制作了你的 links 示例的一个版本:
extensions [csv]
globals [ whole-file ]
turtles-own [ node ]
links-own [ name ]
to setup
ca
reset-ticks
let names [ "A" "B" "C" "D" ]
let n 0
crt 4 [
setxy random 30 - 15 random 30 - 15
set node item n names
set n n + 1
]
ask turtles with [ node = "A" ] [
create-links-to turtles with [node = "B" ]
]
ask turtles with [ node = "B" ] [
create-links-to turtles with [ node = "C" or node = "D" ]
]
end
这只构建了四只海龟,links 如示例 shapefile 属性 table 中所示。我正在使用一个名为 "node_example.csv" 的文件,它看起来像这样:
street_name start_node end_node
1 street_1 A B
2 street_1 B C
3 street_2 B D
有四列,其中第一列是观察编号。
本质上,该方法是遍历列表并提取节点的名称,从 end1
到 end2
反之亦然(因为 both-ends
会将它们拉入随机顺序),并将它们与 table 中的每个 start_node
和 end_node
组合进行比较。如果它们匹配,则将该行中的 street_name
分配给具有匹配项的 link:
to link-name
set whole-file csv:from-file "node_example.csv"
foreach sort links [
[ i ] ->
show i
let way-1 list ( [node] of [end1] of i ) ( [node] of [end2] of i )
let way-2 list ( [node] of [end2] of i ) ( [node] of [end1] of i )
foreach whole-file [
[j] ->
if sublist j 2 4 = way-1 or sublist j 2 4 = way-2 [
ask i [
set name item 1 j
]
]
]
]
ask links [
print name
print (word [node] of end1 [node] of end2 )
]
end
显然,这取决于您的节点在您的模型中被命名(在此示例中,使用的变量是 node
)- 如果不是这种情况,这将不起作用。
编辑 1
好的,我使用了您的 shapefile 进行了一些尝试。这还不完美,我暂时不能再研究它了,但也许它会让你开始。使用此设置:
extensions [gis]
breed [ nodes node ]
globals [ roads-dataset ]
turtles-own [ name line-start line-end]
links-own [ lname ]
我的想法是将起点和终点节点名称分配给沿线要素的每个点,以便 link 可以对照要素列表进行检查。评论中有更具体的说明,但我基本上修改了你的 gis-feature-node 代码来做到这一点。稍微尝试一下(需要一段时间 运行),你会发现有一些我还没有完全弄清楚的差距 - 也许你可以取得进步。
to gis-feature-node
set roads-dataset gis:load-dataset "road_links.shp"
foreach gis:feature-list-of roads-dataset [ vector-feature ->
; First, grab the names of the starting and ending node for the current
; vector feature in order to assign common names to all nodes within
; the feature
let first-vertex gis:property-value vector-feature "startNode"
let last-vertex gis:property-value vector-feature "endNode"
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 size 0.05
set shape "circle"
set color white
set hidden? false
set name gis:property-value vector-feature "name1"
; Here you assign the first-vertex and last-vertex of the entire line
; to each node
set line-start first-vertex
set line-end last-vertex
set current-node self
]
]
ask current-node [
if is-turtle? previous-turtle [
create-link-with previous-turtle
]
set previous-turtle self
]
]
]
]
]
ask links [
;; Here is a major slowdown- reiterate through the entire roads-dataset
; and, if the names in "startNode" and "endNode" match, assign the
; value from "name1" to the link currently being created.
let way-1 list [line-start] of end1 [line-end] of end2
let way-2 list [line-end] of end1 [line-start] of end2
foreach gis:feature-list-of roads-dataset [ vector-feature-sub ->
let vector-start gis:property-value vector-feature-sub "startNode"
let vector-end gis:property-value vector-feature-sub "endNode"
let start-end list vector-start vector-end
if way-1 = start-end or way-2 = start-end [
set lname gis:property-value vector-feature-sub "name1"
]
]
]
ask links with [ lname = "Hamilton Place" ] [
set color red
set thickness 0.2
]
ask links with [ lname = "Whitcomb Street" ] [
set color yellow
set thickness 0.2
]
end
编辑 2
下面的代码已经过测试并且可以工作 - 问题已解决。
ask links [
set is-road? true
;; Here is a major slowdown- reiterate through the entire roads-dataset
; and, if the names in "startNode" and "endNode" match, assign the
; value from "name1" to the link currently being created.
let way-1 list [line-start] of end1 [line-end] of end2
let way-2 list [line-end] of end1 [line-start] of end2
let way-3 list [ line-start ] of end1 [ line-end ] of end1
let way-4 list [ line-start ] of end2 [ line-end ] of end2
foreach gis:feature-list-of roads-dataset [ vector-feature-sub ->
let vector-start gis:property-value vector-feature-sub "startNode"
let vector-end gis:property-value vector-feature-sub "endNode"
let start-end list vector-start vector-end
let end-start list vector-end vector-start
if way-1 = start-end or way-2 = start-end or way-3 = start-end or way-4 = start-end [
set lname gis:property-value vector-feature-sub "name1"
]
]
]
.shp 文件的属性 table 格式如下:
street_name start_node end_node
street_1 A B
street_1 B C
street_2 B D
如何使用开始和结束节点创建 link,然后为每个 link 分配与其开始和结束节点关联的街道名称。例如,起始节点 A 和结束节点 B 的 link 应命名为 "street_1",起始节点 B 和结束节点 D 的街道应命名为 "street_2".
我使用 foreach gis:feature-list-of
到 link 数据集的节点,但是这样我就不能根据它们的开始和结束节点来命名 link,因为有些节点是在街段之间共享。
非常感谢。
编辑:
我感兴趣的属性table的列是name1、startNode和endNode。我已经使用下面的代码连接了节点,现在我有了一个完全连接的道路网络。我不确定如何集成您的代码,以便节点之间的 link 获得与构成 link 的节点组合相关联的名称。
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 size 0.2
set shape "circle"
set color black
set hidden? true
set name gis:property-value vector-feature "name1"
set current-node self
]
]
ask current-node [
if is-turtle? previous-turtle [
create-link-with previous-turtle
]
set previous-turtle self
]
]
]
]
]
你是说你的节点现在在你的模型中正确命名了吗?如果是这种情况,这里有一个可能对您有用的方法的简化版本。我会注意到这不是一个非常有效的方法来解决这个问题,因为它循环遍历你的 links 和你的属性 table,所以如果你有很多很多 links 它将需要一会儿。首先,因为我没有你的 shapefile,所以我制作了你的 links 示例的一个版本:
extensions [csv]
globals [ whole-file ]
turtles-own [ node ]
links-own [ name ]
to setup
ca
reset-ticks
let names [ "A" "B" "C" "D" ]
let n 0
crt 4 [
setxy random 30 - 15 random 30 - 15
set node item n names
set n n + 1
]
ask turtles with [ node = "A" ] [
create-links-to turtles with [node = "B" ]
]
ask turtles with [ node = "B" ] [
create-links-to turtles with [ node = "C" or node = "D" ]
]
end
这只构建了四只海龟,links 如示例 shapefile 属性 table 中所示。我正在使用一个名为 "node_example.csv" 的文件,它看起来像这样:
street_name start_node end_node
1 street_1 A B
2 street_1 B C
3 street_2 B D
有四列,其中第一列是观察编号。
本质上,该方法是遍历列表并提取节点的名称,从 end1
到 end2
反之亦然(因为 both-ends
会将它们拉入随机顺序),并将它们与 table 中的每个 start_node
和 end_node
组合进行比较。如果它们匹配,则将该行中的 street_name
分配给具有匹配项的 link:
to link-name
set whole-file csv:from-file "node_example.csv"
foreach sort links [
[ i ] ->
show i
let way-1 list ( [node] of [end1] of i ) ( [node] of [end2] of i )
let way-2 list ( [node] of [end2] of i ) ( [node] of [end1] of i )
foreach whole-file [
[j] ->
if sublist j 2 4 = way-1 or sublist j 2 4 = way-2 [
ask i [
set name item 1 j
]
]
]
]
ask links [
print name
print (word [node] of end1 [node] of end2 )
]
end
显然,这取决于您的节点在您的模型中被命名(在此示例中,使用的变量是 node
)- 如果不是这种情况,这将不起作用。
编辑 1
好的,我使用了您的 shapefile 进行了一些尝试。这还不完美,我暂时不能再研究它了,但也许它会让你开始。使用此设置:
extensions [gis]
breed [ nodes node ]
globals [ roads-dataset ]
turtles-own [ name line-start line-end]
links-own [ lname ]
我的想法是将起点和终点节点名称分配给沿线要素的每个点,以便 link 可以对照要素列表进行检查。评论中有更具体的说明,但我基本上修改了你的 gis-feature-node 代码来做到这一点。稍微尝试一下(需要一段时间 运行),你会发现有一些我还没有完全弄清楚的差距 - 也许你可以取得进步。
to gis-feature-node
set roads-dataset gis:load-dataset "road_links.shp"
foreach gis:feature-list-of roads-dataset [ vector-feature ->
; First, grab the names of the starting and ending node for the current
; vector feature in order to assign common names to all nodes within
; the feature
let first-vertex gis:property-value vector-feature "startNode"
let last-vertex gis:property-value vector-feature "endNode"
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 size 0.05
set shape "circle"
set color white
set hidden? false
set name gis:property-value vector-feature "name1"
; Here you assign the first-vertex and last-vertex of the entire line
; to each node
set line-start first-vertex
set line-end last-vertex
set current-node self
]
]
ask current-node [
if is-turtle? previous-turtle [
create-link-with previous-turtle
]
set previous-turtle self
]
]
]
]
]
ask links [
;; Here is a major slowdown- reiterate through the entire roads-dataset
; and, if the names in "startNode" and "endNode" match, assign the
; value from "name1" to the link currently being created.
let way-1 list [line-start] of end1 [line-end] of end2
let way-2 list [line-end] of end1 [line-start] of end2
foreach gis:feature-list-of roads-dataset [ vector-feature-sub ->
let vector-start gis:property-value vector-feature-sub "startNode"
let vector-end gis:property-value vector-feature-sub "endNode"
let start-end list vector-start vector-end
if way-1 = start-end or way-2 = start-end [
set lname gis:property-value vector-feature-sub "name1"
]
]
]
ask links with [ lname = "Hamilton Place" ] [
set color red
set thickness 0.2
]
ask links with [ lname = "Whitcomb Street" ] [
set color yellow
set thickness 0.2
]
end
编辑 2
下面的代码已经过测试并且可以工作 - 问题已解决。
ask links [
set is-road? true
;; Here is a major slowdown- reiterate through the entire roads-dataset
; and, if the names in "startNode" and "endNode" match, assign the
; value from "name1" to the link currently being created.
let way-1 list [line-start] of end1 [line-end] of end2
let way-2 list [line-end] of end1 [line-start] of end2
let way-3 list [ line-start ] of end1 [ line-end ] of end1
let way-4 list [ line-start ] of end2 [ line-end ] of end2
foreach gis:feature-list-of roads-dataset [ vector-feature-sub ->
let vector-start gis:property-value vector-feature-sub "startNode"
let vector-end gis:property-value vector-feature-sub "endNode"
let start-end list vector-start vector-end
let end-start list vector-end vector-start
if way-1 = start-end or way-2 = start-end or way-3 = start-end or way-4 = start-end [
set lname gis:property-value vector-feature-sub "name1"
]
]
]