从 .osm 文件中绘制未排序的 way/area 的节点引用
Plotting unsorted way/area's node reference from .osm file
所以我试图从 .osm 节点引用定义建筑物的确切形状(外层),因为我需要根据一些假设在其中创建更多细节结构(房间、墙壁)。
到目前为止,我已经使用 pyosmium 从它的 'building:part' 引用中提取了节点的坐标,将节点的坐标存储到元组列表中,使用 Polygon 函数从 shapely 中重建它并使用 mplleaflet 绘制它。但是不知何故,参考中的节点没有排序,当我尝试绘制它时,显示了很多交叉点。
我目前解决这个排序问题的方法如下:
def distance(current_data, x_point):
# find the shortest distance between x_point and all points in current data
# check if it's perpendicular to the line built before
return current_data[x] # which perpendicular and has shortest distance to x_point
def sort_nodes(nodes):
temp = []
for node in nodes:
if len(temp) < 2: # adding first 2 points as a starting line
temp.append(node)
else:
n = distance(temp, node)
# find index of current_data[x] in temp
return temp.insert(min_index, node)
仅按距离(最短)对坐标元组进行排序仍然不能解决问题。甚至根据它的程度对它进行排序可能会导致另一个问题,即并非所有建筑物都是矩形的。
这就是我根据距离排序到目前为止的方式。plotted image
有没有更好的方法来做到这一点?还是我做错了?我已经连续试了 2 天了。很抱歉,如果这太琐碎了,但我真的是编码新手,需要完成这项工作。感谢您的帮助。
编辑:对 scai 的回答
这是我提取节点的以下方法:
import osmium as osm
def way_filter():
class WayFilter(osm.SimpleHandler):
def __init__(self):
super(WayFilter, self).__init__()
self.nodes = []
def way(self, w):
if 'building:part' in w.tags and w.tags['building:part'] == 'hospital':
temp = []
for n in w.nodes:
temp.append(n.ref)
self.nodes.append(temp)
ways = WayFilter()
ways.apply_file(map)
return ways.nodes
def get_node(ref_node):
class ObjectCounterHandler(osm.SimpleHandler):
def __init__(self):
osm.SimpleHandler.__init__(self)
self.location = []
self.ref = ref_node
def write_object(self, lon, lat):
self.location.append([lon, lat])
def node(self, n):
try:
if any(n.id in sublist for sublist in self.ref):
self.write_object(n.location.lon, n.location.lat)
except TypeError:
if n.id in self.ref:
self.write_object(n.location.lon, n.location.lat)
h = ObjectCounterHandler()
h.apply_file(map)
return h.location
主程序
a = way_filter()
for ref in a:
b = get_node(ref)
c = next(colors)
loc = []
for x in b:
loc.append(tuple(x))
# plot the points
polygons = Polygon(loc)
x,y = polygons.exterior.xy
plt.plot(x,y, zorder=1)
mplleaflet.show()
这是没有排序的结果。 plot image without sort
节点以正确的顺序通过方式引用,即它们彼此相邻。如果您正确阅读了引用节点 ID 列表,则无需执行任何手动排序。只有关系元素需要手动排序。
很遗憾,我不熟悉 pyosmium,所以我无法告诉您您的代码有什么问题。
所以我试图从 .osm 节点引用定义建筑物的确切形状(外层),因为我需要根据一些假设在其中创建更多细节结构(房间、墙壁)。
到目前为止,我已经使用 pyosmium 从它的 'building:part' 引用中提取了节点的坐标,将节点的坐标存储到元组列表中,使用 Polygon 函数从 shapely 中重建它并使用 mplleaflet 绘制它。但是不知何故,参考中的节点没有排序,当我尝试绘制它时,显示了很多交叉点。
我目前解决这个排序问题的方法如下:
def distance(current_data, x_point):
# find the shortest distance between x_point and all points in current data
# check if it's perpendicular to the line built before
return current_data[x] # which perpendicular and has shortest distance to x_point
def sort_nodes(nodes):
temp = []
for node in nodes:
if len(temp) < 2: # adding first 2 points as a starting line
temp.append(node)
else:
n = distance(temp, node)
# find index of current_data[x] in temp
return temp.insert(min_index, node)
仅按距离(最短)对坐标元组进行排序仍然不能解决问题。甚至根据它的程度对它进行排序可能会导致另一个问题,即并非所有建筑物都是矩形的。
这就是我根据距离排序到目前为止的方式。plotted image
有没有更好的方法来做到这一点?还是我做错了?我已经连续试了 2 天了。很抱歉,如果这太琐碎了,但我真的是编码新手,需要完成这项工作。感谢您的帮助。
编辑:对 scai 的回答
这是我提取节点的以下方法:
import osmium as osm
def way_filter():
class WayFilter(osm.SimpleHandler):
def __init__(self):
super(WayFilter, self).__init__()
self.nodes = []
def way(self, w):
if 'building:part' in w.tags and w.tags['building:part'] == 'hospital':
temp = []
for n in w.nodes:
temp.append(n.ref)
self.nodes.append(temp)
ways = WayFilter()
ways.apply_file(map)
return ways.nodes
def get_node(ref_node):
class ObjectCounterHandler(osm.SimpleHandler):
def __init__(self):
osm.SimpleHandler.__init__(self)
self.location = []
self.ref = ref_node
def write_object(self, lon, lat):
self.location.append([lon, lat])
def node(self, n):
try:
if any(n.id in sublist for sublist in self.ref):
self.write_object(n.location.lon, n.location.lat)
except TypeError:
if n.id in self.ref:
self.write_object(n.location.lon, n.location.lat)
h = ObjectCounterHandler()
h.apply_file(map)
return h.location
主程序
a = way_filter()
for ref in a:
b = get_node(ref)
c = next(colors)
loc = []
for x in b:
loc.append(tuple(x))
# plot the points
polygons = Polygon(loc)
x,y = polygons.exterior.xy
plt.plot(x,y, zorder=1)
mplleaflet.show()
这是没有排序的结果。 plot image without sort
节点以正确的顺序通过方式引用,即它们彼此相邻。如果您正确阅读了引用节点 ID 列表,则无需执行任何手动排序。只有关系元素需要手动排序。
很遗憾,我不熟悉 pyosmium,所以我无法告诉您您的代码有什么问题。