如何找出哪些管道朝向错误的方向

How to find out which pipes are facing wrong direction

我正在尝试计算区域供暖系统。我从 shapefile 中获取信息——对于管道,我有一个带有开始和结束坐标的线串几何形状。我创建了一个 geopandas 数据框:

+-------+----------------------------------------------------------------------------------------------------------------------+
|       |                                                                                                                      |
| ID    | geometry                                                                                                             |
+-------+----------------------------------------------------------------------------------------------------------------------+
|       |                                                                                                                      |
| 0     | LINESTRING (1679896.423 5802688.586,   1679896.034 5802688.745)                                                      |
+-------+----------------------------------------------------------------------------------------------------------------------+
|       |                                                                                                                      |
| 1     | LINESTRING (1679896.034 5802688.745, 1679892.419 5802689.660)                                                        |
+-------+----------------------------------------------------------------------------------------------------------------------+
|       |                                                                                                                      |
| 2     | LINESTRING (1679908.185 5802692.533, 1679911.830 5802691.936,   1679927.258 5802689.562, 1679945.682 5802686.042)    |
+-------+----------------------------------------------------------------------------------------------------------------------+
|       |                                                                                                                      |
| 3     | LINESTRING (1679945.667 5802685.478, 1679945.653 5802685.247)                                                        |
+-------+----------------------------------------------------------------------------------------------------------------------+
|       |                                                                                                                      |
| 4     | ….                                                                                                                   |
+-------+----------------------------------------------------------------------------------------------------------------------+

对于计算,我必须确定线之间的所有连接(当前管道必须定义上一个管道和下一个管道)。我这样做的方式是创建线串的起点和终点,并将数据框与其自身合并(终点与起点成对)。问题是,一些线串(大约 1/5)朝向错误的方向,所以我只是为它们得到 NaN 结果(因为现在当前管道的终点没有触及下一个管道的起点,而只是另一个终点点)。

+-------+-------------+-----------------+------------------------------------+------------------------------------+--------------------------------------------------------------------+
|       |             |                 |                                    |                                    |                                                                    |
| ID    | PipeNext    | PipePrevious    | StartPoint                         | EndPoint                           | Geometry                                                           |
+-------+-------------+-----------------+------------------------------------+------------------------------------+--------------------------------------------------------------------+
|       |             |                 |                                    |                                    |                                                                    |
| 1     | 2           | 477             | POINT (1679896.423 5802688.586)    | POINT (1679896.034 5802688.745)    | LINESTRING (1679896.423 5802688.586,   1679896.034 5802688.745)    |
|       |             |                 |                                    |                                    |                                                                    |
|       |             |                 |                                    |                                    |                                                                    |
+-------+-------------+-----------------+------------------------------------+------------------------------------+--------------------------------------------------------------------+
|       |             |                 |                                    |                                    |                                                                    |
| 7     | 8           | 477             | POINT (1679896.423 5802688.586)    | POINT (1679898.491 5802694.799)    | LINESTRING (1679896.423 5802688.586, 1679898.491 5802694.799)      |
|       |             |                 |                                    |                                    |                                                                    |
|       |             |                 |                                    |                                    |                                                                    |
+-------+-------------+-----------------+------------------------------------+------------------------------------+--------------------------------------------------------------------+
|       |             |                 |                                    |                                    |                                                                    |
| 3     | 467, 468    | Nan             | POINT (1679077.671 5802691.617)    | POINT (1679060.406 5802674.810)    | LINESTRING (1679077.671 5802691.617,   1679060.406 5802674.810)    |
|       |             |                 |                                    |                                    |                                                                    |
|       |             |                 |                                    |                                    |                                                                    |
+-------+-------------+-----------------+------------------------------------+------------------------------------+--------------------------------------------------------------------+

另一个问题是,有 10 个管道连续面对错误方向的示例(所以在它们之间,我实际上得到了结果,但它们是错误的)——另一个问题是,有时 PipeNext 是 NaN 仅仅是因为当前行是结束行。 有什么方法可以确定管道朝向错误的方向吗?如果不是,是否可以使线条的方向在绘图上可见?

编辑 - 添加当前代码:

import pandas as pd
import geopandas as gpd
import folium

import shapefile
import matplotlib.pyplot as plt
from geopandas import GeoDataFrame
import contextily as ctx
df_pipes=gpd.read_file("DO_Hrastnik_odsek.shp")
df_user=gpd.read_file("DO_Hrastnik_objekt.shp")

df_pipes.crs = {'init': 'epsg:3912'}
df_pipes=df_pipes.to_crs("EPSG:3857")
df_user.crs = {'init': 'epsg:3912'}
df_user=df_user.to_crs("EPSG:3857")

df_pipes["ID"] = df_pipes.index + 1
df_pipes['ID']=df_pipes['ID'].astype(str)

df_pipes=df_pipes[["geometry","ID","LENGTH_3D"]].copy()

from shapely.geometry import Point, LineString

df_pipes["node_ups"] = gpd.GeoSeries([Point(list(pt['geometry'].coords)[0]) for i,pt in df_pipes.iterrows()])
df_pipes["node_dws"] = gpd.GeoSeries([Point(list(pt['geometry'].coords)[-1]) for i,pt in df_pipes.iterrows()])

tmp = df_pipes[['ID', 'node_dws', 'node_ups']]

df_connections=pd.merge(tmp, tmp, left_on='node_dws', right_on='node_ups',how="outer")
df_connections=pd.merge(df_connections, tmp, left_on='node_ups_x', right_on='node_dws',how="outer")

df_connections.drop(['node_dws_y', 'node_ups_y','node_dws', 'node_ups'], axis=1, inplace=True)

df_connections = df_connections[df_connections['ID_x'].notna()]

df_connections = df_connections.rename(columns={'ID_x': 'ID_pipe', 'node_dws_x': 'node_dws','node_ups_x': 'node_ups', 'ID_y': 'pipeNext','ID': 'pipePrevious'})

tmp = df_connections[['ID_pipe', 'pipeNext', 'pipePrevious']]
df_connections=pd.merge(tmp, df_pipes, left_on='ID_pipe', right_on='ID',how="outer")

您根据评论提出的检查端点相交位置的想法是可行的方法,它并不像您说的那么复杂。从网络的起始管道开始(所有水都来自这里——我假设那是一根管道)并使用递归函数沿着网络向下移动:

from shapely.geometry import Point, LineString # You can delete your own code after this line.

# df.apply is faster than iterrows, so I rewrote the following two lines
df_pipes['node_ups'] = df_pipes.geometry.apply(lambda linestring: Point(list(linestring.coords)[0])
df_pipes['node_dws'] = df_pipes.geometry.apply(lambda linestring: Point(list(linestring.coords)[-1])

def check_downstream(pipe_id, pipes):
    """Set next and previous pipe ID for all downstream pipes"""

    endpoint = pipes.loc[pipe_id, 'node_dws']
    next_ids = list(pipes['node_ups' == endpoint]['ID'])
    reversed_ids = list(pipes[(pipes['node_dws'] == endpoint) & (pipes['ID'] != pipe_id)]['ID'])
    for rev_id in reversed_ids:
        pipes.loc[rev_id, 'node_ups'], pipes.loc[rev_id, 'node_dws'] = pipes.loc[rev_id, 'node_dws'], pipes.loc[rev_id, 'node_ups']
    next_ids = next_ids + reversed_ids
    for nxt_id in next_ids:
        pipes.loc[pipe_id, 'pipeNext'] = nxt_id
        pipes.loc[nxt_id, 'pipePrevious'] = pipe_id
        check_downstream(nxt_id, pipes) # This is the recursive function call.


df_connections = df_pipes.copy()
df_connections['pipePrevious'] = 'undetermined'
df_connections['pipeNext'] = 'undetermined'

first_id = 99 # or whatever it is
check_downstream(first_id, df_connections)

请注意,这不会反转线串本身,但如果需要,您也可以这样做。