我试图安排线段以使用python创建一个闭合的多边形。目前我已经设法解决了这个问题,但是当细分数量增加时(它就像一个泡泡排序,但是对于细分的终点)来说真的很慢。我附加了一个sample file坐标(真正的坐标非常复杂,但对于测试目的很有用)。该文件包含两个separetes闭合多边形的段的坐标。下面的图片是我附上的坐标的结果。
这是我加入细分的代码。 “Curve”文件位于上面的保管箱链接中:
from ast import literal_eval as make_tuple
from random import shuffle
from Curve import Point, Curve, Segment
def loadFile():
print 'Loading File'
file = open('myFiles/coordinates.txt','r')
for line in file:
pairs.append(make_tuple(line))
file.close()
def sortSegment(segPairs):
polygons = []
segments = segPairs
while (len(segments) > 0):
counter = 0
closedCurve = Curve(Point(segments[0][0][0], segments[0][0][1]), Point(segments[0][1][0], segments[0][1][1]))
segments.remove(segments[0])
still = True
while (still):
startpnt = Point(segments[counter][0][0], segments[counter][0][1])
endpnt = Point(segments[counter][1][0], segments[counter][1][1])
seg = Segment(startpnt, endpnt)
val= closedCurve.isAppendable(seg)
if(closedCurve.isAppendable(seg)):
if(closedCurve.isClosed(seg)):
still =False
polygons.append(closedCurve.vertex)
segments.remove(segments[counter])
else:
closedCurve.appendSegment(Segment(Point(segments[counter][0][0], segments[counter][0][1]), Point(segments[counter][1][0], segments[counter][1][1])))
segments.remove(segments[counter])
counter = 0
else:
counter+=1
if(len(segments)<=counter):
counter = 0
return polygons
def toTupleList(list):
curveList = []
for curve in list:
pointList = []
for point in curve:
pointList.append((point.x,point.y))
curveList.append(pointList)
return curveList
def convertPolyToPath(polyList):
path = []
for curves in polyList:
curves.insert(1, 'L')
curves.insert(0, 'M')
curves.append('z')
path = path + curves
return path
if __name__ == '__main__':
pairs =[]
loadFile();
polygons = sortSegment(pairs)
polygons = toTupleList(polygons)
polygons = convertPolyToPath(polygons)
答案 0 :(得分:2)
假设您只是在寻找方法,而不是代码,我会尝试这样做。
当您从文件中读取片段坐标时,请继续将坐标添加到字典中,其中片段的一个坐标(字符串形式)作为键,另一个坐标作为值。最后,它应该是这样的:
{
'5,-1': '5,-2',
'4,-2': '4,-3',
'5,-2': '4,-2',
...
}
现在从这本词典中选择任何一个键值对。接下来,从字典中选择键值对,其中键与前一个键值对中的值相同。因此,如果第一个键值对为'5,-1': '5,-2'
,则下次查找键'5,-2'
,您将获得'5,-2': '4,-2'
。接下来查找键'4,-2'
等等。
继续从字典中删除键值对,这样一旦完成一个多边形,就可以检查是否还有任何元素,这意味着可能有更多的多边形。
如果您还需要代码,请告诉我。
答案 1 :(得分:2)
我不得不做类似的事情。我需要将海岸线线段(未正确排序)转换为多边形。我使用NetworkX将分段排列成连接的组件,并使用this function对其进行排序。
事实证明,我的代码也适用于此示例。我使用geopandas
来显示结果,但是该依赖性对于此处的原始问题是可选的。我还使用shapely
将线段列表转换为多边形,但是您可以只使用CoastLine.rings
来获取线段列表。
我计划将此代码包含在下一版PyRiv中。
from shapely.geometry import Polygon
import geopandas as gpd
import networkx as nx
class CoastLine(nx.Graph):
def __init__(self, *args, **kwargs):
"""
Build a CoastLine object.
Parameters
----------
Returns
-------
A CoastLine object
"""
self = super(CoastLine, self).__init__(*args, **kwargs)
@classmethod
def read_shp(cls, shp_fn):
"""
Construct a CoastLine object from a shapefile.
"""
dig = nx.read_shp(shp_fn, simplify=False)
return cls(dig)
def connected_subgraphs(self):
"""
Get the connected component subgraphs. See the NetworkX
documentation for `connected_component_subgraphs` for more
information.
"""
return nx.connected_component_subgraphs(self)
def rings(self):
"""
Return a list of rings. Each ring is a list of nodes. Each
node is a coordinate pair.
"""
rings = [list(nx.dfs_preorder_nodes(sg)) for sg in self.connected_subgraphs()]
return rings
def polygons(self):
"""
Return a list of `shapely.Polygon`s representing each ring.
"""
return [Polygon(r) for r in self.rings()]
def poly_geodataframe(self):
"""
Return a `geopandas.GeoDataFrame` of polygons.
"""
return gpd.GeoDataFrame({'geometry': self.polygons()})
使用此类,可以解决原始问题:
edge_list = [
((5, -1), (5, -2)),
((6, -1), (5, -1)),
((1, 0), (1, 1)),
((4, -3), (2, -3)),
((2, -2), (1, -2)),
((9, 0), (9, 1)),
((2, 1), (2, 2)),
((0, -1), (0, 0)),
((5, 0), (6, 0)),
((2, -3), (2, -2)),
((6, 0), (6, -1)),
((4, 1), (5, 1)),
((10, -1), (8, -1)),
((10, 1), (10, -1)),
((2, 2), (4, 2)),
((5, 1), (5, 0)),
((8, -1), (8, 0)),
((9, 1), (10, 1)),
((8, 0), (9, 0)),
((1, -2), (1, -1)),
((1, 1), (2, 1)),
((5, -2), (4, -2)),
((4, 2), (4, 1)),
((4, -2), (4, -3)),
((1, -1), (0, -1)),
((0, 0), (1, 0)) ]
eG = CoastLine()
for e in edge_list:
eG.add_edge(*e)
eG.poly_geodataframe().plot()
这将是结果: