I need to calculate the overlap (amount or yes/no) that two rectangles make on a special x/y grid. The grid is 500x500 but the sides and corners connect (are continuous). So the next point after 499 becomes 0 again.
In a previous question I asked for a way to calculate the distance between two points in this grid. This turned out to be the Euclidean distance:
sqrt(min(|x1 - x2|, gridwidth - |x1 - x2|)^2 + min(|y1 - y2|, gridheight - |y1-y2|)^2)
What is the good mathematical way of calculating if two rectangles (defined by a point (x,y), width and height) have overlap in this grid?
Rectangle-1 ([x=0,y=0], w=20, h=20) and Rectangle-2 ([x=495,y=0], w=10, h=10) should have overlap. The overlapping rectangle (not really needed but) should be ([x=0,y=0], w=5, h=10)
First, compute the x and y range for each rectangle
(because you have a torus geometry do it mod gridsize).
So, given your Rectangle-1, compute:
x1 = x = 0, x2 = x + w = 20
y1 = y = 0, y2 = y + h = 20
Same for Rectangle-2:
x3 = 495, x4 = 505 mod 500 = 5
y3 = 0, y4 = 10
Create the x and y "regions" for each rectangle:
Reactangle-1: x-regions: (0, 20)
y-regions: (0, 20)
Rectangle-2: x-regions: (495, 500), (0, 5)
y-regions: (0, 10)
If any (both) x and y regions between the two rectangles have a non-null intersection, then your rectangles overlap.
Here the (0, 20) x-region of Rectangle-1 and the (0, 5) x-region of Rectangle-2 have a non-null intersection and so do the (0, 20) and (0, 10) y-regions.
Related
I have two points in a 3d space, one point is (x,0,z) and the other one is the origin (0,0,0), through those points there is a passing line with length L that is starting from the first point and continuing after the origin point, in the end of this line there is a perpendicular (to the line) flat board with dimensions of W x H, the line ends in the middle of this board.
Assume that x,z,L,H,W are given, I need a way to find all the 3D points coordinates where those points forming a pixels image over the board (meaning each point has a distance of 1 from its left, right, top, bottom neighboring points).
Attached a pretty ugly drawing :) I made trying to illustrate the problem (I marked the pixels points with two question marks but I need them all).
Thanks.
It is possible to define that plane. But there is no selected direction to build a grid uniquelly.
Let we choose OY direction as base (because normal has zero Y-component).
So we have:
Normal vector N = (xx, 0, zz) //I renamed values to avoid confusion with coordinate
variables
Unit normal vector n = (nx, 0, nz), where
nx = xx / Sqrt(xx*xx+zz*zz)
nz = zz / Sqrt(xx*xx+zz*zz)
Base point
B = (bx, 0, bz) = (xx - nx * L, 0, zz - nz * L)
Unit base vector in the plane
dy = (0, 1, 0)
Another base vector
dc = dy x n //vector product
= (-bz, 0, bx)
Now it is possible to generate a grid, using integer indexes i, j in ranges (-W/2..W/2) and (-H/2.. H/2). Grid nodes coordinates:
x(i, j) = bx - j * bz
y(i, j) = 0 + i
z(i, j) = bz + j * bx
I have a fairly complex problem that I don't really know where to start. I have a set of spatial points (X & Y) coordinates that also include information (Height).
set.seed(12345)
X = runif(100, 0, 45)
Y = runif(100, 0, 45)
Height = runif(100, 6, 9)
data <- data.frame("X" = X, "Y" = Y, "Height" = Height)
data$Radius_max = 1/3 * data$Height
The coordinates look something like this:
ggplot(data, aes(X, Y)) +
geom_point()
For each point, I need a buffer that is scaled by Height. The buffer is an equation that is scaled by height but is essentially a circular buffer similar to a cone. The following steps are what I've come up with to determine buffer size for each point:
Set bottom left point to radius_max.
Find the intersection of the radius at any given point relative to the next point.
Do this multiple times to refit a new radius for the intial point relative to new adjacent radii.
The reason for starting at an initial point is that each radii following will be constrained by the neighboring points (randomly generating points may or may not have this effect). No cone can be below another cone. Think trees. If possible, I would like to know the radius at 45 degree increments.
I'm ok with any solution and suspect there may be a way to do this with the spatial packages rather than doing some by hand. Where do I start?
I am not quite sure what you are after. Particularly the 45 degrees increments. Do you want the buffer to be circular? If so, perhaps the below is a solution.
Your example data
set.seed(12345)
X <- runif(100, 0, 45)
Y <- runif(100, 0, 45)
Height <- runif(100, 6, 9)
data <- data.frame("X" = X, "Y" = Y, "Height" = Height)
data$Radius_max <- 1/3 * data$Height
Possible solution
library(raster)
x <- pointDistance(data[,1:2], lonlat=FALSE)
diag(x) <- NA
mn <- apply(x, 1, min, na.rm=TRUE)
data$radius <- pmin(data$Radius_max, mn/2)
d <- SpatialPoints(data[, c('X', 'Y')], proj4string=CRS('+proj=utm +zone=1'))
b <- buffer(d, data$radius, dissolve=FALSE)
plot(b)
I am trying to calculate the area generated (in orange) by an arbitrary point in the space. here are some example pictures of different possible scenarios:
So basically in all three pictures I want to be able to calculate the orange area that is generated from point by drawing a horizontal and vertical line from the point to the blue area. The idea is simple but actually implementing is very challenging. I am writing this code in R so any help with R code would be great. Also, for the third example, we can just assume that the orange area is bounded at x and y equal to 8. And, we also know the coordinates of the green points. Any suggestion greatly appreciated!
Oh an here is my code for generating the plots below:
x = c(1,3,5)
y = c(5,3,1)
point1 = c(2,4)
point2 = c(2,2)
point3 = c(0,0)
plot(x,y,type="n",xlim=c(0,8),ylim=c(0,8))
rect(point1[1],point1[2],max(x)+10,max(y)+10,col="orange",border=NA)
rect(x,y,max(x)+10,max(y)+10,col="lightblue",border=NA)
points(x,y,pch=21,bg="green")
points(point1[1],point1[2],pch=21,bg="blue")
box()
plot(x,y,type="n",xlim=c(0,8),ylim=c(0,8))
rect(point2[1],point2[2],max(x)+10,max(y)+10,col="orange",border=NA)
rect(x,y,max(x)+10,max(y)+10,col="lightblue",border=NA)
points(x,y,pch=21,bg="green")
points(point2[1],point2[2],pch=21,bg="blue")
box()
plot(x,y,type="n",xlim=c(0,8),ylim=c(0,8))
rect(point3[1],point3[2],max(x)+10,max(y)+10,col="orange",border=NA)
rect(x,y,max(x)+10,max(y)+10,col="lightblue",border=NA)
points(x,y,pch=21,bg="green")
points(point3[1],point3[2],pch=21,bg="blue")
box()
You're working much harder than necessary. pracma::polyarea will calculate the area of any polygon given the coordinates of all vertices.
Think about the entire plotting region as an unequal grid of rectangles, with x- and y-grid points at the x- and y-coordinates of the rectangle vertices you're plotting.
x <- c(1, 3, 5)
y <- c(5, 3, 1)
max.x <- max(x) + 10
max.y <- max(y) + 10
point <- c(0, 0)
x.grid <- sort(unique(c(x, point[1], max.x)))
x.grid
# [1] 0 1 3 5 15
y.grid <- sort(unique(c(y, point[2], max.y)))
y.grid
# [1] 0 1 3 5 15
We'll keep track of the grid rectangles we painted orange with the matrix orange:
orange <- matrix(FALSE, nrow=length(y.grid)-1, ncol=length(x.grid)-1)
We'll make a plotting function that labels cells in orange based on the passed rectangle, with (x1, y1) as lower left and (x2, y2) as upper right:
plot.rect <- function(x1, y1, x2, y2, value) {
x1.idx <- which(x.grid == x1)
y1.idx <- which(y.grid == y1)
x2.idx <- which(x.grid == x2)
y2.idx <- which(y.grid == y2)
orange[y1.idx:(y2.idx-1),x1.idx:(x2.idx-1)] <<- value
}
Then, let's plot our orange rectangle (filling in TRUE) followed by all the blue ones (filling in FALSE):
plot.rect(point[1], point[2], max.x, max.y, TRUE)
for (idx in 1:length(x)) {
plot.rect(x[idx], y[idx], max.x, max.y, FALSE)
}
Finally, let's compute the size of each grid rectangle, enabling the final size computation (the point I selected at the top corresponds to your third plot; since the plot extends up 15 and to the right 15, it appears to be working as intended):
sizes <- t(outer(diff(x.grid), diff(y.grid)))
area <- sum(orange * sizes)
area
# [1] 41
I am writing a bilinear interpolation method.
This method can be abstract by solve the equation A*x = b, A is a 4x4 matrix below:
1 x1 y1 x1*y1
1 x2 y2 x2*y2
1 x3 y3 x3*y3
1 x4 y4 x4*y4
Here, (x1, y1), (x2, y2), (x3, y3) and (x4, y4) is four points containing the dst interpolation point.
My problem is when det(A) = 0(then x! = A-1*b), what is the quadrangle looks like?
The determinant becomes 0 when one of the rows or columns can be expressed as a linear combination of the others. Using columns, this equation must hold for some constants a, b, c for each of the four points:
a*1 + b*x + c*y + xy = 0
This is the equation a hyperbola with asymptotes parallel to the axis, so the determinant is zero if and only if the four points fall on the same hyperbola.
For example, if you pick the rectangle (-2, -1), (-1, -2), (1, 2), (2, 1) the determinant will be zero since the points fall on the hyperbola defined by t → (t, 2/t).
Another way to look at it: you are free to pick any 3 points. The three points define a unique hyperbola. The determinant is 0 if and only if you pick the fourth point from that hyperbola.
Joni's answer above is entirely correct, but here's a physical interpretation that you might like:
Picture a square as a well-behaved quadrilateral defined by the following four points: 1 = (0,0), 2 = (1,0), 3 = (1, 1), and 4 = (0, 1).
If you start skewing it by anchoring points 1 and 2 but tugging point 3 to the right in such a way that the sides remain the same length, but the angle between the x-axis and the line segment between points 2 and 3 changes from 90 degrees to 180 and the angle between the x-axis and the line segment between points 1 and 4 changes from 90 degrees to 0, the determinant will approach zero as the angle increases. When you have points 1 = (0,0), 2 = (1, 0), 3 = (2,0), and 4 = (1,0) the quad will be collapsed to a line segment and the determinant will be zero.
You can run this experiment with your matrix and see if I'm correct.
Example
Suppose I have two triangles:
A triangle with points (0, 0), (10, 0), (10, 0.5) and
a triangle with points (0, 0), (1, 0), (0.5, 11)
The resulting two plots without specifying the xlim and ylimlook like this:
Question
What do I need to do to satisfy all points listed below?
Make the triangle visible, so that no line of the triangle is hidden by an axis
Specify the same margin for all plots in mm, cm or other unit.
(in the example above only two triangles were used. Actually I have n triangles.)
As margin I mean the distance between the outer points of the triangle and the axis.
The resulting plots should look like this
with the difference that the distances, which are marked with the red arrows, should all be the same!
I don't know of a way to to it in cm/mm, but you can do it with the precentage of the total size:
# you don't really need this see bellow
#from matplotlib.backends.backend_pdf import PdfPages
import pylab
import matplotlib.pyplot as plt
left,bottom,width,height = 0.2,0.1,0.6,0.6 # margins as % of canvas size
fig = plt.figure(figsize=(4,4),facecolor="yellow") # figure size in Inches
fig.patch.set_alpha(0.8) # just a trick so you can see the difference
# between the "canvas" and the axes
ax1 = plt.Axes(fig,[left,bottom,width,height])
ax1.plot([1,2,3,4],'b') # plot on the first axes you created
fig.add_axes(ax1)
ax1.plot([0,1,1,0,0], [0,0,1,1,0],"ro") # plot on the first axes you created
ax1.set_xlim([-1.1,2])
ax1.set_ylim([-1.1,2])
# pylab.plot([0,1,1,0,0], [0,0,1,1,0],"ro") avoid usig if you
# want to control more frames in a plot
# see my answer here
#http://stackoverflow.com/questions/8176458/\
#remove-top-and-right-axis-in-matplotlib-after-\
#increasing-margins/8180844#8180844
# pdf = PdfPages("Test.pdf")# you don't really need this
# pylab.savefig(pdf, papertype = "a4", format = "pdf")
# automagically make your pdf like this
pylab.savefig("Test1.pdf", papertype="a4",facecolor='y')
pylab.show()
pylab.close()
# pdf.close()
and the output is:
corrected image:
Your two triangles with points (0, 0), (10, 0), (10, 0.5) and (0, 0), (1, 0), (0.5, 11) would be represented in pylab as:
Ax = [0, 10, 10]
Ay = [0, 0, 0.5]
Bx = [0, 1, 0.5]
By = [0, 0, 11]
pylab.plot(Ax, Ay)
pylab.plot(Bx, By)
Let's see what the lowest X value is:
lowestX = None
for x in Ax+Bx:
if lowestX==None or x<lowestX:
lowestX = x
Exercise for the reader to do the same for highestX, lowestY, and highestY.
Now, consider a boundary of 2 units, you can add / subtract these units from the lowest and highest values and set xlim and ylim:
margin = 2
pylab.xlim([lowestX-margin, highestX+margin])
pylab.ylim([lowestY-margin, highestY+margin])