基于OSM数据构建交通通行网络图(1/3)

1 构建两条道路空间通行关系判断规则

假设有两条道路A和B,道路A为源道路,道路B为目标道路,实验的目标是判断从道路A出发能否到达道路B。首先根据道路类别建立通行规则,然后根据两条道路的空间拓扑关系判断道路A是否能够通往道路B。

道路空间通行关系规则决策树

1.1 实现方法概述

首先从OSM中获取的路网数据存储了道路类型信息,其将道路分为高速路、快速路、主干道、次干道、其他道路等,并且道路是单向通行的。因此不同道路的通行规则是能够基于道路类型属性快速区分。其次,道路的行车方向与空间线条点集顺序一致,即从第一个点前往最后一个点。最后,影响两条道路通行关系的空间拓扑包括三类:连续(Connected)、接触(Touch)和相交(Intersect),需基于一些算法具体判断道路间的空间拓扑关系。

以下WKT格式表示的道路起点、终点和行车方向如图所示。

text 复制代码
LINESTRING(118.7668063525639 32.05806454085803,118.7667190099296 32.05807233008715,118.7666316672952 32.0580801193163,118.7665443246609 32.05808790854542,118.7664569820266 32.05809569777457,118.7663696393922 32.05810348700371,118.7662822967579 32.05811127623283,118.7661949541236 32.05811906546198,118.7661076114892 32.0581268546911,118.7660202688549 32.05813464392023,118.7659329262206 32.05814243314938,118.7658452646464 32.05814450350625,118.7657576030723 32.05814657386314,118.7656699414982 32.05814864422003,118.765582279924 32.05815071457692,118.7654946183499 32.05815278493378,118.7654069567757 32.05815485529067,118.7653192952016 32.05815692564755,118.7652316336275 32.05815899600444,118.7651439720534 32.05816106636131,118.7650577766283 32.05815226087318,118.7649715812032 32.05814345538508,118.7648853857781 32.05813464989693,118.764799190353 32.05812584440881,118.7647129949279 32.05811703892068,118.7646267995028 32.05810823343255,118.7645406040777 32.05809942794443,118.7644544086526 32.0580906224563,118.7643682132275 32.05808181696818)

1.2 空间拓扑关系判断的特殊情况

  1. 由于OSM数据本身会存在一些误差,比如现实世界中相连接的道路,OSM数据中两条线是不相交的。经测算,两条道路空间拓扑关系判断的空间容差(Tolerance)不超过100m。对于地理学,使用了0.00001米的距离公差(因此非常接近的点被认为是相交的)。
  2. 拓扑关系的不确定性。在二维地图中,相交的道路在实际三维世界中并不一定是相交关系,比如高架桥和地下隧道。

2 技术选型与代码示例

  1. 利用存储Postgresql+PostGIS管理空间数据,neo4j管理道路通行网络知识图谱。

  2. 通过编写python算法实现道路通行知识图的构建,其中关键用到了python sqlalchemy和geoalchemy2访问空间数据库,python neo4j库访问neo4j数据库。

在两条道路空间通行关系判断规则中,需基于道路空间拓扑关系判断以确定两条道路是否可通行。以下利用Python编程实现了指定"源道路"空间接触计算、空间相交计算和给定距离线查询等三个方法。

  • 连接Postgresql数据库
python 复制代码
from sqlalchemy import create_engine, func
from sqlalchemy.orm import sessionmaker

DATABASE_URI = f'postgresql://{username}:{password}@localhost:5432/{dbname}'  # 数据库连接信息
engine = create_engine(DATABASE_URI, echo=False)
# 创建会话
Session = sessionmaker(bind=engine)
session = Session()
  • 空间接触计算

    1. 方法描述:

      ST_Touches --- Tests if two geometries have at least one point in common, but their interiors do not intersect.

      Description: Returns TRUE if A and B intersect, but their interiors do not intersect. Equivalently, A and B have at least one point in common, and the common points lie in at least one boundary. For Point/Point inputs the relationship is always FALSE, since points do not have a boundary.


    2. 示例代码

    python 复制代码
    def get_touch_br(source_br: BaseRoad):
        touch_br_list = []
        touch_res = session.query(BaseRoad, func.ST_AsText(BaseRoad.geom)) \
            .filter(func.ST_Touches(BaseRoad.geom, source_br.geom))
        for br, geom in touch_res:
            touch_br_list.append(br)
            br_geom_list.append(wkt.loads(geom))
        return touch_br_list
    1. 示例结果

  • 空间相交计算

    1. 方法描述

      ST_Intersects --- Tests if two geometries intersect (they have at least one point in common).

      Description: Compares two geometries and returns true if they intersect. Geometries intersect if they have any point in common.For geography, a distance tolerance of 0.00001 meters is used (so points that are very close are considered to intersect).

    2. 示例代码

    python 复制代码
    def get_intersects_br(source_br: BaseRoad):
        intersects_br_list = []
        br_geom_list = []
        # 查询与source_br相交的道路
        intersects_res = session.query(BaseRoad) \
            .filter(func.ST_Intersects(BaseRoad.geom, source_br.geom))
        for br in intersects_res:
            intersects_br_list.append(br)
            br_geom_list.append(wkb.loads(WKBElement._data_from_desc(br.geom.desc)))
        return intersects_br_list
    1. 示例结果

  • 给定距离线查询

    1. 方法描述

      ST_DWithin --- Tests if two geometries are within a given distance.

      Description: The distance is specified in units defined by the spatial reference system of the geometries. For this function to make sense, the source geometries must be in the same coordinate system (have the same SRID).

    2. 示例代码

    python 复制代码
    def get_dwithin_br(source_br: BaseRoad):
        dwithin_br_list = []
        dwithin_res = session.query(BaseRoad, func.ST_AsText(BaseRoad.geom)) \
            .filter(func.ST_DWithin(func.ST_GeomFromEWKB(BaseRoad.geom), func.ST_GeomFromEWKB(source_br.geom), Tolerance))
        for br, geom in dwithin_res:
            dwithin_br_list.append(br)
            br_geom_list.append(wkt.loads(geom))
       return dwithin_br_list
    1. 示例结果

相关推荐
怕浪猫3 小时前
RAG 面试 6 连问,从原理到优化全部覆盖
python·算法·面试
高洁014 小时前
具身智能中的世界模型训练
人工智能·python·深度学习·机器学习·transformer
无线通信科研笔记4 小时前
IEEE TVT 2026 论文精读与完整复现|相位误差如何重塑近场 RIS 的幅相响应
论文阅读·人工智能·python·算法·论文笔记
朝朝辞暮i4 小时前
VLA 系统学习第 1 课:VLA 到底在干什么?
人工智能·python·计算机视觉·vla
2601_962885724 小时前
如何用 Python 自动识别股票的支撑位与压力位?
开发语言·python
北冥有鱼被烹5 小时前
VCSEL全景解析:与光模块NPO CPO的关系、市场量化分析与产业链影响
python
caoerzhong5 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
正在走向自律5 小时前
AI数据分析与可视化:从基础到应用实践
服务器·人工智能·python·机器学习·数据分析·pandas
databook6 小时前
从手动检查到自动监控:一个数据质量工作流的实现
后端·python·数据分析
北冥有鱼被烹8 小时前
砷化镓与磷化铟:光模块的地基——从化学键到AI缺货潮的底层逻辑
人工智能·python