Polygons from Coordinates

polygons from coordinates

The key to creating polygons is that the coordinates have to be in sequence to form a closed area (i.e., the last point is the same as the first point).

So your data will need a bit of manipulation to create the coordinates, and put them in order. In my example I've done this with an lapply

Then the rest can be taken from the sf examples

lst <- lapply(1:nrow(df), function(x){
## create a matrix of coordinates that also 'close' the polygon
res <- matrix(c(df[x, 'north_lat'], df[x, 'west_lng'],
df[x, 'north_lat'], df[x, 'east_lng'],
df[x, 'south_lat'], df[x, 'east_lng'],
df[x, 'south_lat'], df[x, 'west_lng'],
df[x, 'north_lat'], df[x, 'west_lng']) ## need to close the polygon
, ncol =2, byrow = T
)
## create polygon objects
st_polygon(list(res))

})

## st_sfc : creates simple features collection
## st_sf : creates simple feature object
sfdf <- st_sf(geohash = df[, 'geohash'], st_sfc(lst))

sfdf
# Simple feature collection with 2 features and 1 field
# geometry type: POLYGON
# dimension: XY
# bbox: xmin: 48.64746 ymin: -4.350586 xmax: 48.69141 ymax: -4.262695
# epsg (SRID): NA
# proj4string: NA
# geohash st_sfc.lst.
# 1 gbsuv POLYGON((48.69141 -4.350586...
# 2 gbsuy POLYGON((48.69141 -4.306641...

plot(sfdf)

Sample Image

How to convert the following coordinates to 'shapely' polygon?

If I understand problem you need simply this:

rect = [572.71063, 453.9848, 622.2049, 472.86023]

X1, Y1, X2, Y2 = rect

polygon = [(X1, Y1), (X2, Y1), (X2, Y2), (X1, Y2)]

EDIT:

Minimale working code:

from shapely.geometry import Polygon
import matplotlib.pyplot as plt

rect = [572.71063, 453.9848, 622.2049, 472.86023]

X1, Y1, X2, Y2 = rect

polygon = [(X1, Y1), (X2, Y1), (X2, Y2), (X1, Y2)]

p = Polygon(polygon)

x, y = p.exterior.xy

plt.plot(x, y)
plt.show()

Result:

Sample Image

How to know if a coordinate is inside a polygon of coordinates

  • have used countries as polygons / multipolygons (barrios)
  • have generated some points, some will fall within countries (puntos)
  • simple case of left sjoin() tells you which points are in a polygon and which are not
  • have visualised to demonstrate it works (green valid points, purple invalid)
import geopandas as gpd
import pandas as pd
import numpy as np

barrios = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))

# generate some points, some are valid some invalid
puntos = pd.DataFrame(
{
"Latitud": np.linspace(*barrios.total_bounds[[0, 2]], 100),
"Longitud": np.linspace(*barrios.total_bounds[[1, 3]], 100),
}
)

# find valid points by do an sjoin
valid = gpd.GeoDataFrame(puntos,
geometry=gpd.points_from_xy(puntos["Latitud"], puntos["Longitud"]), crs="epsg:4326"
).sjoin(barrios.loc[:, ["geometry"]], how="left").assign(
valid=lambda d: (~d["index_right"].isna()).astype(int)
)

sample output































































































LatitudLongitudgeometryindex_rightvalid
0-180-90POINT (-180 -90)nan0
1-176.364-88.246POINT (-176.3636363636364 -88.24600878787879)1591
2-172.727-86.492POINT (-172.7272727272727 -86.49201757575757)1591
3-169.091-84.738POINT (-169.0909090909091 -84.73802636363637)1591
4-165.455-82.984POINT (-165.4545454545454 -82.98403515151516)nan0
5-161.818-81.23POINT (-161.8181818181818 -81.23004393939394)nan0
6-158.182-79.4761POINT (-158.1818181818182 -79.47605272727273)nan0
7-154.545-77.7221POINT (-154.5454545454545 -77.72206151515152)1591
8-150.909-75.9681POINT (-150.9090909090909 -75.9680703030303)nan0
9-147.273-74.2141POINT (-147.2727272727273 -74.2140790909091)nan0

Coordinate Points to Polygons

Here's the answer:

http://www.cs.man.ac.uk/~toby/alan/software//

Setting a list of (x,y) cooordinates into an array so polygons are drawn

From software engineering point of view, it is recomended to break your code into simple separate parts (i.e. make it modular).

First you will need a function for reading the input json and parsing it. I called it read_input in the code below.
The format of the parsed data depends on the application.

I chose to return a list of pairs of ndarrays. Each element in the list represents one polygon. Each polygon contains 2 ndarrays: 1 for the x coordinates, and 1 for the y coordinates. I chose this representation because it is convenient for drawing the polygons (see below).

Second you will need a function for drawing the polygons (draw_polygons). It will contain an iteration over the polygon list, and call a lower level function for drawing 1 polygon (draw_one_polygon), again for modular reasons.

See the code below:

import json
import numpy as np
from skimage.draw import polygon

def read_input(filename: str):
polygons = []
with open(filename) as f:
data = json.load(f)
shapes = data["shapes"]
for i in shapes:
cur_poly_points = i["points"]
tmp = list(zip(*cur_poly_points))
# NOTE: The following line assumes that the point coordinates are given as (x,y).
# Change the order of the indices if needed.
polygons.append((np.array(tmp[1]), np.array(tmp[0])))
return polygons

def draw_one_polygon(img, one_poly):
r = one_poly[0];
c = one_poly[1];
rr, cc = polygon(r, c)
img[rr,cc] = 1

def draw_polygons(img, polygons):
for poly in polygons:
draw_one_polygon(img, poly)

filename = '139cm_2000_frame27.json'
polygons = read_input(filename)
img = np.zeros((128, 128), dtype=np.uint8)
draw_polygons(img, polygons)
print(img)

Note: in your actual code you should verify that the coordinates do not exceed the image dimension.

Documentation and example: skimage.draw.polygon

If you are not familiar with this notation: *cur_poly_points, see here: How to unzip a list of tuples into individual lists?.

How to convert coordinates of sf polygons with holes to X and Y (without L1, L2)?

If I understood correctly, please find below one possible solution using sf and dplyr libraries.

The solution is based on the creation of a list containing n tables with the XY coordinates of the n features of your graph.

Reprex

  • Code
library(sf)
library(dplyr)

tables_XY <- polygon %>%
st_coordinates() %>% # retrieves coordinates in a matrix
as.data.frame %>% # converts into dataframe
split(.,.$L1) %>% # creates a list with one coordinates table for each feature
lapply(., `select`, c("X", "Y")) # keeps only X and Y columns for each table of the list

# To what it looks like:
tables_XY
#> $`1`
#> X Y
#> 1 1639 888
#> 2 2243 888
#> 3 2243 769
#> 4 2243 517
#> 5 1735 517
#> 6 1735 640
#> 7 1236 640
#> 8 1236 517
#> 9 1232 517
#> 10 1232 801
#> 11 1639 801
#> 12 1639 888
#>
#> $`2`
#> X Y
#> 13 2243 769
#> 14 1872 775
#> 15 1870 639
#> 16 2241 633
#> 17 2243 769
#>
#> $`3`
#> X Y
#> 18 1543 780
#> 19 1541 645
#> 20 1833 641
#> 21 1835 776
#> 22 1543 780
#>
#> $`4`
#> X Y
#> 23 1364 783
#> 24 1362 647
#> 25 1504 645
#> 26 1506 781
#> 27 1364 783
#>
#> $`5`
#> X Y
#> 28 1240 784
#> 29 1238 649
#> 30 1337 648
#> 31 1339 783
#> 32 1240 784
  • Visualization (i.e. your graph in a XY frame)
plot(tables_XY[[1]], type = "l")
lapply(tables_XY[2:length(tables_XY)], lines, type = "l")

Sample Image

Created on 2021-12-22 by the reprex package (v2.0.1)

Create polygon from outermost point spatial coordinates

something like this:

library(sf)
df <- data.frame(x = lon, y = lat)
pts1 <- st_as_sf(x = df, coords = c('x', 'y'))
my_hull <- st_convex_hull(st_union(pts1))
plot(my_hull)


Related Topics



Leave a reply



Submit