2

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.

enter image description here

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.