【发布时间】:2021-11-26 11:01:39
【问题描述】:
我有一长串 shapely.geometry.LineStrings 部分重叠(准确地说,它们是德国高速公路网络上的行驶路线)。每个 LineString 都有一个关联的值(在我的例子中是延迟和走那条路线的汽车数量)。我的目标是找到这些不同的LineStrings 之间的重叠部分,并将它们对应的值相加。最终结果应该类似于下图所示:
我目前的方法大致如下(代码在帖子末尾):
- 维护已检查路线的列表
- 对于每条新路线:检查新路线和已检查的路线之间是否有重叠
- 如果是,则将组合值分配给重叠部分并仅对剩余的非重叠部分继续检查
这种方法有效并产生了预期的结果。然而,问题在于,如果要检查的路由数量非常多,算法的运行时间就会变得过长。原因是越来越多的 LineStrings 必须检查交叉点。是否有人知道可用于解决此问题的现有算法、程序包等?或者您对如何加速算法有好的建议?
在代码中,实现如下(诚然尚未完善):
def intersects_rectangles(bounds, other_bounds):
return not (bounds[2] < other_bounds[0] or bounds[0] > other_bounds[2] or bounds[3] < other_bounds[1] or bounds[1] > other_bounds[3])
def main_function(route_df) -> Dict[tuple, List[Union[LineString, float]]]:
# The index of route_df contains ids that lead to files that contain the LineStrings
# The columns contain the relevant values associated with each route
table_merged: Dict[tuple, List[Union[LineString, float]]] = {}
routes_covered = 0
tot_routes = len(route_df)
print(f'Creating a merged view of all routes. Nr. routes: {tot_routes}')
for (route_name, car_name), line in route_df.iterrows():
with open('buffer_data/' + route_name + '/' + BufferFileHierarchy.route.value, 'rb') as f:
linestring: LineString
linestring, _ = pickle.load(f)
current_cum_delay = line['sum']
current_count = line['count']
if len(table_merged) == 0:
table_merged[(route_name, )] = [linestring, linestring.buffer(0.001).buffer(0), current_cum_delay, current_count] # The buffer is necessary to also include LineStrings describing the opposite side of the road
continue
for other_contained_routes in list(table_merged.keys()):
[other_linestring, other_linestring_buffer, other_cum_delay, other_cum_count] = table_merged[other_contained_routes]
if route_name in other_contained_routes:
continue
seg_intersects = linestring.intersection(other_linestring_buffer)
if seg_intersects.is_empty:
continue
if not intersects_rectangles(linestring.bounds, other_linestring.bounds):
continue
if seg_intersects.length > 0.0002:
seg_intersects_buffer = seg_intersects.buffer(0.001).buffer(0)
linestring_remainder = linestring.difference(seg_intersects_buffer)
other_linestring_remainder = other_linestring.difference(seg_intersects_buffer)
table_merged[(*other_contained_routes, route_name)] = [seg_intersects, seg_intersects_buffer, current_cum_delay + other_cum_delay, current_count + other_cum_count]
if other_linestring_remainder.is_empty:
del table_merged[other_contained_routes]
else:
table_merged[other_contained_routes] = [other_linestring_remainder, other_linestring_remainder.buffer(0.001).buffer(0), other_cum_delay, other_cum_count]
linestring = linestring_remainder
if linestring.is_empty:
break
if not linestring.is_empty:
table_merged[(route_name, )] = [linestring, linestring.buffer(0.001).buffer(0), current_cum_delay, current_count]
routes_covered += 1
if routes_covered % 100 == 0:
progress_bar.print_progress_bar(routes_covered, tot_routes)
progress_bar.print_progress_bar(routes_covered, tot_routes)
return table_merged
【问题讨论】: