I have been trying to find what I am actually doing wrong for a day now and can't figure out what the problem with my approach might be. So, a little background is in place:
I have a dataframe with a bunch of coordinates:
index id x_polygon y_polygon \
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 27.03 38.58
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 28.26 38.58
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 28.26 44.38
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 27.03 44.38
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 27.03 38.58
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 28.26 38.58
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 28.26 44.38
3 3 13e70e96-2554-49c5-9c2e-4df1beb8efb1 27.03 44.38
0 0 168bb0ea-3748-42ad-84c3-aa20e62c73b3 32.99 37.25
0 0 168bb0ea-3748-42ad-84c3-aa20e62c73b3 33.57 37.25
0 0 168bb0ea-3748-42ad-84c3-aa20e62c73b3 33.57 44.86
0 0 168bb0ea-3748-42ad-84c3-aa20e62c73b3 32.99 44.86
5 5 5e36fbc5-b5d4-4f32-9f53-d713e389b13d 19.03 45.93
5 5 5e36fbc5-b5d4-4f32-9f53-d713e389b13d 31.39 45.93
5 5 5e36fbc5-b5d4-4f32-9f53-d713e389b13d 31.39 46.52
5 5 5e36fbc5-b5d4-4f32-9f53-d713e389b13d 19.03 46.52
edges.id edges.linkable
3 66689e8c-fd24-4eb1-b46c-b4371d354aff True
3 66689e8c-fd24-4eb1-b46c-b4371d354aff True
3 66689e8c-fd24-4eb1-b46c-b4371d354aff True
3 66689e8c-fd24-4eb1-b46c-b4371d354aff True
3 e49832f7-af6b-4da3-b2c2-8a66cb16cc39 True
3 e49832f7-af6b-4da3-b2c2-8a66cb16cc39 True
3 e49832f7-af6b-4da3-b2c2-8a66cb16cc39 True
3 e49832f7-af6b-4da3-b2c2-8a66cb16cc39 True
0 ab68fa67-2f46-49cf-b319-8454d5820f9d True
0 ab68fa67-2f46-49cf-b319-8454d5820f9d True
0 ab68fa67-2f46-49cf-b319-8454d5820f9d True
0 ab68fa67-2f46-49cf-b319-8454d5820f9d True
5 8395d1d1-b676-43a0-92dd-e4038df9549c True
5 8395d1d1-b676-43a0-92dd-e4038df9549c True
5 8395d1d1-b676-43a0-92dd-e4038df9549c True
5 8395d1d1-b676-43a0-92dd-e4038df9549c True
Here is a dict-version of it:
{'index': {3: 3, 0: 0, 5: 5}, 'id': {3: '13e70e96-2554-49c5-9c2e-4df1beb8efb1', 0: '168bb0ea-3748-42ad-84c3-aa20e62c73b3', 5: '5e36fbc5-b5d4-4f32-9f53-d713e389b13d'}, 'x_polygon': {3: 27.031515, 0: 32.987843, 5: 19.034254}, 'y_polygon': {3: 44.37576, 0: 44.86328, 5: 46.517555}, 'edges.id': {3: 'e49832f7-af6b-4da3-b2c2-8a66cb16cc39', 0: 'ab68fa67-2f46-49cf-b319-8454d5820f9d', 5: '8395d1d1-b676-43a0-92dd-e4038df9549c'}, 'edges.linkable': {3: True, 0: True, 5: True}}
I transform the coordinates into POLYGON objects
geostore_obstacles_geometry = gpd.GeoDataFrame(geometry=geostore_obstacles.groupby(['id']).apply(
lambda g: Polygon(gpd.points_from_xy(g['x_polygon'], g['y_polygon']))))
geostore_obstacles_geometry = geostore_obstacles_geometry.reset_index()
geostore_obstacles_geometry
which returns:
id \
0 13e70e96-2554-49c5-9c2e-4df1beb8efb1
1 168bb0ea-3748-42ad-84c3-aa20e62c73b3
2 5e36fbc5-b5d4-4f32-9f53-d713e389b13d
geometry
0 POLYGON ((27.03151 38.58253, 28.26146 38.58253...
1 POLYGON ((32.98784 37.25187, 33.56717 37.25187...
2 POLYGON ((19.03425 45.92993, 31.38868 45.92993...
and merge with the original dataframe. The reason I am doing this is that I also want every point as a geometrical object POINT:
geostore_obstacles_geometry_with_points = geostore_obstacles_geometry.merge(geostore_obstacles, left_on =['id'],right_on =['id'])
geostore_obstacles_geometry_with_points =geostore_obstacles_geometry_with_points.rename_geometry('geometry_obstacle')
geostore_obstacles_geometry_with_points
geostore_obstacles_geometry_with_geopoints = gpd.GeoDataFrame(geostore_obstacles_geometry_with_points, geometry = gpd.points_from_xy(geostore_obstacles_geometry_with_points['x_polygon'], geostore_obstacles_geometry_with_points['y_polygon']))
which gives:
id \
0 13e70e96-2554-49c5-9c2e-4df1beb8efb1
1 13e70e96-2554-49c5-9c2e-4df1beb8efb1
2 13e70e96-2554-49c5-9c2e-4df1beb8efb1
geometry_obstacle index x_polygon \
0 POLYGON ((27.03151 38.58253, 28.26146 38.58253... 3 27.03
1 POLYGON ((27.03151 38.58253, 28.26146 38.58253... 3 28.26
2 POLYGON ((27.03151 38.58253, 28.26146 38.58253... 3 28.26
y_polygon edges.id edges.linkable \
0 38.58 66689e8c-fd24-4eb1-b46c-b4371d354aff True
1 38.58 66689e8c-fd24-4eb1-b46c-b4371d354aff True
2 44.38 66689e8c-fd24-4eb1-b46c-b4371d354aff True
geometry
0 POINT (27.03151 38.58253)
1 POINT (28.26146 38.58253)
2 POINT (28.26146 44.37576)
My objective from here is to split all the boundaries of the polygons in its individual edges and the way I found to do this is first by using gemgis
and explode the polygons into LINESTRING objects (which are the boundaries) and then use shapely.os.split
to split the linestrings at the points I determined above:
geostore_obstacles_geometry_with_geopoints=geostore_obstacles_geometry_with_geopoints.rename(columns ={'geometry_obstacle':'geometry', 'geometry':'point'})
geostore_obstacles_geometry_with_geopoints['geometry'] = geostore_obstacles_geometry_with_geopoints['geometry'].buffer(0)
geostore_obstacles_geometry_with_geopoints = gemgis.vector.explode_polygons(gdf=geostore_obstacles_geometry_with_geopoints)
def get_side_of_rect(row, linecol="geometry", pointcol="point"):
return split(row[linecol], row[pointcol])
Full_geometry = (
geostore_obstacles_geometry_with_geopoints.assign(sides=lambda df: df.apply(get_side_of_rect, axis=1))
)
Full_geometry = Full_geometry.set_geometry('sides')
exploded = Full_geometry.explode(ignore_index=False)
exploded = exploded.reset_index()
Full_geometry = exploded.drop(['geometry'], axis=1)
Full_geometry
level_0 level_1 id index x_polygon \
0 0 0 13e70e96-2554-49c5-9c2e-4df1beb8efb1 3 27.03
1 1 0 13e70e96-2554-49c5-9c2e-4df1beb8efb1 3 28.26
2 1 1 13e70e96-2554-49c5-9c2e-4df1beb8efb1 3 28.26
3 2 0 13e70e96-2554-49c5-9c2e-4df1beb8efb1 3 28.26
4 2 1 13e70e96-2554-49c5-9c2e-4df1beb8efb1 3 28.26
y_polygon edges.id edges.linkable \
0 38.58 66689e8c-fd24-4eb1-b46c-b4371d354aff True
1 38.58 66689e8c-fd24-4eb1-b46c-b4371d354aff True
2 38.58 66689e8c-fd24-4eb1-b46c-b4371d354aff True
3 44.38 66689e8c-fd24-4eb1-b46c-b4371d354aff True
4 44.38 66689e8c-fd24-4eb1-b46c-b4371d354aff True
point \
0 POINT (27.03151 38.58253)
1 POINT (28.26146 38.58253)
2 POINT (28.26146 38.58253)
3 POINT (28.26146 44.37576)
4 POINT (28.26146 44.37576)
sides
0 LINESTRING (27.03151 38.58253, 27.03151 44.375...
1 LINESTRING (27.03151 38.58253, 27.03151 44.375...
2 LINESTRING (28.26146 38.58253, 27.03151 38.58253)
3 LINESTRING (27.03151 38.58253, 27.03151 44.375...
4 LINESTRING (28.26146 44.37576, 28.26146 38.582...
As you see, I have the sides of the polygons. And I can determine those that have only 2 vertices by first calculating the number of vertices of each LINESTRING and then selecting what I want:
Full_geometry = Full_geometry.rename(columns={'id':'id_gondola','edges.id':'edges_id'})
n_vertices=[]
for i, row in Full_geometry.iterrows():
ls= row.sides.type.startswith("LINE")
if ls:
n = 0
for part in row.sides:
n += len(part.coords)
else:
n = len(row.sides.coords)
n_vertices.append(n)
Full_geometry["n_vertices"] = n_vertices
Full_geometry_complete = Full_geometry[Full_geometry['n_vertices']==2]
print(len(Full_geometry_complete))
Full_geometry_complete = Full_geometry_complete.drop(['level_0','level_1'], axis=1).drop_duplicates()
Full_geometry_complete = Full_geometry_complete.reset_index()
Full_geometry_complete['part'] = Full_geometry_complete['level_0'].astype(str)
Full_geometry_complete['Facing_sub'] = Full_geometry_complete.id_gondola.str.cat(Full_geometry_complete.edges_id.astype(str), sep='_')
Full_geometry_complete['Facing'] = Full_geometry_complete.Facing_sub.str.cat(Full_geometry_complete.part.astype(str), sep='_')
Full_geometry_complete = Full_geometry_complete.drop(['level_0','id_gondola','edges_id','part','Facing_sub'], axis=1)
But now, if I plot these, I only have half of the edges (they should be rectangles and I should be able to plot any of these sides individually). I would like to know what I am doing wrong and/or have an easier way to get all sides as unique objects.