Fill polygon with holes - shapely

I have a shapely Polygon with holes, that I want to fill using pycairo.
Is there an easy way to split this polygon into multiple polygons, without holes, that cover the same surface?
Or is there a better way to fill a polygon with holes using pycairo?

I figured out a solution using the cairo clipping feature:
def fill_polygon(self, context, polygon):
context.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
poly = polygon.exterior
for x, y in poly.coords:
context.line_to(x, y)
context.clip_preserve()
for poly in polygon.interiors:
context.move_to(*poly.coords[-1])
for x, y in poly.coords:
context.line_to(x, y)
context.fill()
context.reset_clip()

Related

Determine which points lay outside an irregularly-shaped data footprint in R?

I have a series of points in an area whose 'footprint' shape is highly irregular:
I'd like to determine all of the coordinates within the footprint's vertices. The end goal is to determine which data points lay outside this footprint.
Does anyone have an efficient way to go about doing this??
My best idea to approaching this is to draw a polygon based on the green area's vertices and then use said polygon's coordinates to determine 'outlier' points' (though, I'm not sure how to do that yet -- one step at a time!).
However, when I try creating a convex hull, it obviously creates problems because of the irregular shape of my green space. [Anyone know of a way to create CONCAVE hulls?]
Alternatively, is there a way to draw polygons manually using a 'click the graph' type method?
...Again, if you have a better solution to my problem than using polygons, please by all means suggest that solution!
Alternatively, is there a way to draw polygons manually using a 'click
the graph' type method?
Here's one idea. First, some random points:
library(manipulate)
library(sp)
set.seed(1)
par(pch = 19, cex=.5)
x <- runif(1000)
y <- runif(1000)
Now, draw and capture the polygon:
coords <- data.frame()
manipulate({
plot(y~x)
res <- manipulatorMouseClick()
coords <<- rbind(coords, data.frame(x=res$userX, y=res$userY))
if (length(coords)) lines(coords)
})
And determine which points are inside/outside of it (see ?point.in.polygon):
res <- point.in.polygon(x, y, coords$x, coords$y)!=0
plot(y~x, col = res + 1L)
lines(coords)

How can I use the quadratic formula when the y is reversed?

When you graph a parabola on a normal graph, you can use ax^2+bx+c but when I want to graph a parabola in a window, This doesn't work for me. I assume this is because the y axis is reversed. Is there a workaround or a different formula to counter this? For example, if I have a player at (100,150) and I am trying to shoot an arrow at an apple at (500,150) How would I do this? I am trying to stay pure to math without getting to complicated. I am still in high school, and am just learning about these so please try to keep it simple. My math teacher mentioned something about quadratic regression, what is this?
One way to address this is to have two different coordinate systems, one for the screen and another for your model.
The y axis of the screen would point down. The y axis of your model up. Both systems will share the very same x axis.
Now, the idea is: think using your model's coordinates and map them to the screen only for display.
The transformation that maps a point with coordinates (x, y) in one system to the other is
(x, y) -> (x, h - y)
where h is the heigh of your screen (h > 0).
The inverse transformation (i.e., the one that maps the screen onto your model) is the same because from the viewpoint of the upward y axis the screen y axis is also at distance h from its origin.
Applying this to your equation your model would have points of the form
(x, ax^2 + bx +c)
and these would map to points
(x, h -ax^2 - bx -c) = (x, -ax^2 - bx + h-c)
in screen coordinates.

Concentric circles R

I want to create 50 concentric circles. I did it with python but now I want to do this in R. I have tried the symbols function but with no result. I want my circles to start from x,y coordinates and the radius of each circle to be 3times bigger than the previous.
step=1
for(i in seq(1,50,1)){
symbols (x, y, circles=50, col="grey")
step=step+3
}
From this I get one circle as a result.
I am new in programming so it is probably very simple. Should I use a specific package?
The beauty of R is that many things can be vectorized, including the imput to the 'symbols' function. Here's an example for you:
#vector of radii
#written in a way that's easily changable
n_circles <- 50
my_circles <- seq(1,by=1,length.out = n_circles)
#generate x and y
x <- rep(1,n_circles)
y <- rep(1, n_circles)
#plot
symbols(x,y,1:n_circles)

Plotting ellipsoids / oblate spheroids in rgl

I have been using rgl to plot spheres, but now I need to plot ellipsoids.
The package includes ellipse3d; however, this seems to be for fitting ellipsoids to data, using matrices and stuff I'm not very good at.
What I want is a simple way to plot ellipsoids, in a similar way to spheres, using the centre coordinates and the scales in each direction. Can anyone help me out?
If you don't need the ellipse rotated around the axes, then you can just use a diagonal matrix for x (this plots a sphere, and defines the virtual "axes" along the x, y, z axes) and use the centre and scale parameters to shift the location and change the proportions.
plot3d(ellipse3d(diag(3),centre=c(1,2,4),scale=c(1,2,5)))
There's one in my cda package,
library(cda)
library(rgl)
## single ellipsoid
plot3d(rgl.ellipsoid(a=2,b=1,c=5))
## multiple ellipsoids, translated and rotated
cl <- helix(0.5, 1, 36, delta=pi/6, n.smooth=1e3)
sizes <- equal_sizes(0.04,0.02,0.02,NROW(cl$positions))
rgl.ellipsoids(cl$positions, sizes, cl$angles, col="gold")

Plotting 3D maps with RGL

I'm trying to plot flat maps in RGL's 3d environment because it should enable maps to be custom zoomed/tilted for a projection that best suits both the data and required output image aspect. This thread describes the process for plotting images using rgl.surface(). But its not clear if this method is adaptable for OSM/other map objects. Very grateful for any ideas you may have.
This is the starting point, which fails because Error in is.matrix(z) : 'z' is missing. Any idea how I can insert some zeros for z coordinates?
require(rgl)
open3d() # R crashes if this is done later(?)
#Sys.setenv(NOAWT=1) # fix an {OSM} X11 issue in Mac
require(OpenStreetMap)
require(ggplot2)
lat <- c(53, 50); lon <- c(-5, 1)
map <- openmap(c(lat[1],lon[1]),c(lat[2],lon[2]), 5, 'osm')
map <- openproj(map)
rgl.surface(map)
You need to create a matrix of zeroes for heights and use the col= argument to surface3d to set the colour of the image.
Getting all the dimensions and ordering and all that out of the map object is a faff, so here's a function to do it:
map3d <- function(map,...){
if(length(map$tiles)!=1){
stop("multiple tiles not implemented")
}
nx = map$tiles[[1]]$xres
ny = map$tiles[[1]]$yres
xmin = map$tiles[[1]]$bbox$p1[1]
xmax = map$tiles[[1]]$bbox$p2[1]
ymin = map$tiles[[1]]$bbox$p1[2]
ymax = map$tiles[[1]]$bbox$p2[2]
xc = seq(xmin,xmax,len=ny)
yc = seq(ymin,ymax,len=nx)
colours = matrix(map$tiles[[1]]$colorData,ny,nx)
m = matrix(0,ny,nx)
surface3d(xc,yc,m,col=colours,...)
}
Which gives us:
Now, note it only works if there's one tile in the returned map, but the principle is there.
Also, I'm not totally convinced the coordinate alignment is exact. The coordinates may be centre of pixels or edges of the image, so maybe there's a +1 missing somewhere. And I'm not sure if it applies to the gray border or not.

Resources