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)
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:
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
Latitud | Longitud | geometry | index_right | valid | |
---|---|---|---|---|---|
0 | -180 | -90 | POINT (-180 -90) | nan | 0 |
1 | -176.364 | -88.246 | POINT (-176.3636363636364 -88.24600878787879) | 159 | 1 |
2 | -172.727 | -86.492 | POINT (-172.7272727272727 -86.49201757575757) | 159 | 1 |
3 | -169.091 | -84.738 | POINT (-169.0909090909091 -84.73802636363637) | 159 | 1 |
4 | -165.455 | -82.984 | POINT (-165.4545454545454 -82.98403515151516) | nan | 0 |
5 | -161.818 | -81.23 | POINT (-161.8181818181818 -81.23004393939394) | nan | 0 |
6 | -158.182 | -79.4761 | POINT (-158.1818181818182 -79.47605272727273) | nan | 0 |
7 | -154.545 | -77.7221 | POINT (-154.5454545454545 -77.72206151515152) | 159 | 1 |
8 | -150.909 | -75.9681 | POINT (-150.9090909090909 -75.9680703030303) | nan | 0 |
9 | -147.273 | -74.2141 | POINT (-147.2727272727273 -74.2140790909091) | nan | 0 |
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 ndarray
s. Each element in the list represents one polygon. Each polygon contains 2 ndarray
s: 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")
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
How to Define the Version of a Package in R Install.Packages
Scraping Tables on Multiple Web Pages with Rvest in R
Visualising and Rotating a Matrix
How to Add Colorbar with Perspective Plot in R
Separate Ordering in Ggplot Facets
Plot Line on Top of Stacked Bar Chart in Ggplot2
Installing R Studio with Anaconda
Use Loop to Split a List into Multiple Dataframes
How to Classify a Given Date/Time by the Season (E.G. Summer, Autumn)
Use of .By and .Eachi in the Data.Table Package
R Reshape2 'Aggregation Function Missing: Defaulting to Length'
Combine Result from Top_N with an "Other" Category in Dplyr
R - How to One Hot Encoding a Single Column While Keep Other Columns Still
How to Find Which Polygon a Point Belong to via Sf
How to Select_If in Dplyr, Where the Logical Condition Is Negated