将图输出为`.xml`

0 投票
1 回答
968 浏览
提问于 2025-04-21 09:41

我有一个形状文件(shapefile),我想把它转换成一个 .xml 文件,以便在 MATSim 中使用。这个文件的结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE network SYSTEM "http://www.matsim.org/files/dtd/network_v1.dtd">
<network name="VISUM export national network 2007-11-28">

<!-- ====================================================================== -->
    <nodes>
        <node id="1000" x="730065.3125" y="220415.9531" type="2" origid="1000" />
        <node id="1001" x="731010.5" y="220146.2969" type="2" origid="1001" />
        .....
    </nodes>
<!-- ====================================================================== -->
    <links capperiod="01:00:00" effectivecellsize="7.5" effectivelanewidth="3.75">
        <link id="100365" from="226" to="227" length="921.0" freespeed="33.3333333333333" capacity="5600.0" permlanes="2.0" oneway="1" modes="car" origid="183" type="10" />
    ...
    </links>
<!-- ====================================================================== -->
</network>

我正在使用 NetworkX 这个 Python 库来完成这个任务,它可以把形状文件当作图形来读取,并把这个图形导出为 GEXF 对象。这个代码(基本上)输出的结果接近于网络规范,但还不够准确。

import networkx as nx

G = nx.read_shp("expcuts1.shp")
start = 0
G = nx.convert_node_labels_to_integers(G, first_label=start, 
        label_attribute = "coord")

# Build a new object with the elements that you need
H = nx.DiGraph(name = "Python NetworkX export from FAF 3.4")
H.add_edges_from(G.edges())

# store coordinates in node attributes
for i in range(len(H)):
    H.node[i]['x'] = G.node[i]['coord'][0]
    H.node[i]['y'] = G.node[i]['coord'][1]

# export as xml (really, gexl, but that's pretty close)
nx.write_gexf(H, 'test.xml') 
<gexf version="1.1" xmlns="http://www.gexf.net/1.1draft" xmlns:viz="http://www.gexf.net/1.1draft/viz" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/XMLSchema-instance">
  <graph defaultedgetype="undirected" mode="static">
    <attributes class="node" mode="static">
      <attribute id="0" title="y" type="double" />
      <attribute id="1" title="x" type="double" />
    </attributes>
    <nodes>
      <node id="0" label="0">
        <attvalues>
          <attvalue for="0" value="1389860.27495" />
          <attvalue for="1" value="2237913.99085" />
        </attvalues>
      </node>

另外,GEXF 使用的是节点和 ,而 MATSim 的术语要求使用节点和 链接。我在考虑是修改 NetworkX 的 write_gexf 函数更简单,还是手动用 ElementTree API 写出 XML 文件更容易。有什么建议吗?

1 个回答

0

简单来说,如果这是一个一次性的项目,可以稍微调整一下 write_gexf 这个函数,来自 NetworkX。

详细一点:

在使用 MATSim 时,你需要一个有方向的图。Gexf 格式支持这个,使用 defaultedgetype="directed" 就可以了。你还可以给边(连接点的线)添加其他属性,比如容量、车道数等等。

<edge weight="1.0" target="109001663" source="109001672" label="network link" id="99999">
 <attvalues>
  <attvalue start="0.0" value="0" for="capacity"/>
  <attvalue start="0.0" value="0" for="length"/>
 </attvalues>
</edge>

因为你已经有了一个 gexf 文件,最后一步就是进行一对一的转换。gexf 中的节点会直接转换成 MATSim 中的节点,而边在 MATSim 中叫做链接。不过,你需要给 MATSim 提供网络的一些属性。

节点只需要 x 和 y 坐标。

对于链接,你可能还想添加链接的实际长度(不是简单的直线距离)。此外,你还需要提供最大允许速度(freespeed)、容量(通常以每小时的 PCU 来表示)和车道数。

需要注意的是,容量是和时间段有关的,比如 capperiod="01:00:00" 表示这个容量在一小时内有效。

顺便提一下,你还可以查看一下 gexf 包,里面有一些 gexf 辅助类,主要是用来将 MATSim 网络转换成 gexf 格式,方便在 Gephi 中分析。

撰写回答