This post is a reply to: 3D Ray-Quad intersection test in java
Because I can't yet comment.
My question is, how did they get:
A point M belongs to this plane iff it satisfies this equation: n . ( M - S1 ) = 0
How is the (dotProduct(n, (M - S1)) == 0) suppose to tell us that the ray intersects the quad?
In my opinion Wikipedia answers this question quite well: Wiki
In a manner analogous to the way lines in a two-dimensional space are described using a point-slope form for their equations, planes in a three dimensional space have a natural description using a point in the plane and a vector orthogonal to it (the normal vector) to indicate its "inclination".
Specifically, let r0 be the position vector of some point P0 = (x0,
y0, z0), and let n = (a, b, c) be a nonzero vector. The plane
determined by the point P0 and the vector n consists of those points
P, with position vector r, such that the vector drawn from P0 to P is
perpendicular to n. Recalling that two vectors are perpendicular if
and only if their dot product is zero, it follows that the desired
plane can be described as the set of all points r such that
With other words you have a normal vector of a plane and a vector created by a point of the plane and the point you are checking if it is on the plane. The dot-product tells you something about the angle between the two vector. Therefore if the vector is parallel to the plane, the point has to be on the plane.
Related
Let us consider a 2-D (latitude, longitude) point set. The points in the set are equispaced (approx.) with mutual distance 0.1 degree \times 0.1 degree . Each point in the set is the centre of a square grid of side length 0.1 degree (i.e., intersect point of two diagonals of the square). Each square is adjacent to the neighbouring squares.
Our goal is to get the coordinates of the outline polygon formed by the bounding sides of the square grids with given direction (will be illustrated with a figure). This polygon has no hole inside.
Let us consider a sample data set of size 10 (point set).
lat_x <- c(21.00749, 21.02675, 21.00396, 21.04602, 21.02317,
21.06524, 21.00008, 21.04247, 21.08454, 21.0192)
and
lon_y <- c(88.21993, 88.25369, 88.31292, 88.28740, 88.34669,
88.32118, 88.40608, 88.38045, 88.35494, 88.43984)
Here is the rough plot of the above points followed by some illustration,
The black points are the (lat,lon) points in the above sample.
The blue square boxes are the square grid.
The given directions (\theta) of the squares are $theta$=50 degree.
Our goal is to get the ordered (clockwise or counter clockwise) co-ordinates of the outline polygon (in yellow colour).
Note: This question is very similar to this with a nice answer given by #laune. There the goal is to get the outline polygon without direction (or 0 degree direction). But in the the present set up I need to include the direction (non-zero) while drawing the square grids and the resulted polygon.
I would gratefully appreciate any suggestion, java or R codes or helpful reference given by anyone solving the above problem.
I would do it like this:
may be some 2D array point grouping to match the grid
that should speed up all the following operations.
compute average grid sizes (img1 from left)
as two vectors
create blue points (img2)
as: gray_point (+/-) 0.5*blue_vector
create red points (img3)
as: blue_point (+/-) 0.5*red_vector
create list of gray lines (img4)
take all 2 original (gray) points that have distance close to average grid distance and add line for them
create list of red lines (img4)
take all 2 original (gray) points that have distance close to average grid distance and add line for them if it is not intersecting any line from gray lines
reorder line points to match polygon winding ...
angle
compute angle of red vector (via atan2)
compute angle of blue vector (via atan2)
return the one with smaller absolute value
[edit1] response to comments
grid size
find few points that are closest to each other so pick any point and find all closest points to it. The possible distances should be near:
sqrt(1.0)*d,sqrt(1+1)*d,sqrt(1+2)*d,sqrt(2+2)*d,...
where d is the grid size so compute d for few picked points. Remember the first smallest d found and throw away all that are not similar to smallest one. Make average of them and let call it d
grid vectors
Take any point A and find closest point B to it with distance near d. For example +/-10% comparison: |(|A-B|-d)|<=0.1*d Now the grid vector is (B-A). Find few of them (picking different A,B) and group them by sign of x,y coordinates into 4 groups.
Then join negative direction groups together by negating one group vectors so you will have 2 list of vectors (red,blue direction) and make average vectors from them (red,blue vectors)
shifting points
You take any point A and add or substract half of red or blue vector to it (not its size!!!) for example:
A.x+=0.5*red_vector.x;
A.y+=0.5*red_vector.y;
line lists
Make 2 nested fors per each 2 point combination A,B (original for gray lines,shifted red ones for red outline lines) and add condition for distance
|(|A-B|-d)|<=0.1*d
if it is true add line (A,B) to the list. Here pseudo C++ example:
int i,j,N=?; // N is number of input points in pnt[]
double x,y,d=?,dd=d*d,de=0.1*d; // d is the avg grid size
double pnt[N][2]=?; // your 2D points
for (i=0;i<N;i++) // i - all points
for (j=i+1;j<N;j++) // j - just the rest no need to test already tested combinations
{
x=pnt[i][0]-pnt[j][0];
y=pnt[i][1]-pnt[j][1];
if (fabs((x*x)+(y*y)-dd)<=de) ... // add line pnt[i],pnt[j] to the list...
}
Does anybody know how to find out if a set of coordinates are within a triangle for which you have the coordinates for. i know how to work out length of sides, area and perimeter, but i have no idea where to begin working out the whereabouts within the triangle of other points.
Any advice would be appreciated
You can create a Polygon object.
Polygon triangle = new Polygon();
Add the vertexes of your triangle with the addPoint(int x, int y) method.
And then, you just need to check if the set of coordinates is inside your triangle using contains(double x, double y) method.
Use the contains method of the Polygon class as documented here.
For a solution without using the Polygon-class:
Assume that you have giving three points A,B,C the vertices of your polygon. Let P be the point you want to check. First calculate the vectors representing the edges of your triangle. Let us call them AB, BC, CA. Also calculate the three vectors PA, PB, PC.
Now calculate the cross product between the first two of the vectors from above.
The cross product of the first pair gives you the sin(alpha), where alpha is the angle between AB and PA, multiplied with a vector pendenpicular to AB and PA. Ignore this vector because we are interested in the angle and take a look at the sine (in the case of 2D vectors you can imagine it as the vector standing perpendicular to your screen).
The sine can take values between (let's say for the ease) betwenn 0 and 2*Pi. It's 0 exactly at 0 and Pi. For every value in between the sine is positive and for every value between Pi and 2*Pi it's negative.
So let's say your Point p is on the left hand side of AB, so the sine would be positive.
By taking the cross product of each pair from above, you could easily guess that the point P is on the left hand side of each edge from the triangle. This just means that it has to be inside the triangle.
Of course this method can even be used from calculating whether a point P is in a polygon. Be aware of the fact, that this method only works if the sides of the polygon are directed.
I'm writing a game in java with the lwjgl. Basically i have two plans that i want to check if they intersect each other, like the image below.
I have the four points for each plane, can someone help me.
The 2 planes do not intersect if they are parallel (and not the same plane).
Let p1, p2, p3 and p4 be your 4 points defining the plane and n=(a,b,c) the normal vector computed as n=cross(p2-p1, p3-p1). The plane equation is
ax + by + cz + d = 0
where d=-dot(n,p1)
You have 2 planes
ax + by + cz + d = 0
a’x + b’y + c’z + d’ = 0
they are parallel (and not same) iff
a/a’ == b/b’ == c/c’ != d/d’
When you implement this predicate you have to check the divide by 0
I can't show this is enough, but I believe these three tests should be sufficient:
for two planes...
project each plane onto the x axis, check if there is any overlap
project each plane onto the y axis, check if there is any overlap
project each plane onto the z axis, check if there is any overlap
if there is no overlap in any of those three cases, the planes do not intersect. otherwise,
the planes intersect.
let me know if you are not sure how to project onto an axis or calculate an overlap. also, let me know if these three tests are insufficient.
Edit 1:
Algorithm: You don't actually have to project, rather you can just find the maximum range. Let's do the x axis as an example. You find the minimum x value on plane 1 and the maximum x value on the plane 1. Next, you find the minimum x value on plane 2 and the maximum x value on plane 2. If their ranges overlap ( for example, [1 , 5] overlaps with [2 , 9] ), then there's overlap with the projections onto the x axis. Note that finding the range of x values might not be easy if edges of your plane segment aren't parallel with the x axis. If you're dealing with more complicated plane segments that don't have edges parallel to the axes, I can't really help then. You might have to use something else like matrices.
The test, by the way, is called a separating-axis test. I think the x, y, and z axis tests should be enough to test for plane segments intersecting.
Source: (Book) Game Physics Engine Development: How To Build A Robust Commercial-Grade Physics Engine For Your Game (Second Edition) by Ian Millington
Edit 2:
Actually, you'll need to check more axes.
I'm trying to write a 2D game in Java that uses the Separating Axis Theorem for collision detection. In order to resolve collisions between two polygons, I need to know the Minimum Translation Vector of the collision, and I need to know which direction it points relative to the polygons (so that I can give one polygon a penalty force along that direction and the other a penalty force in the opposite direction). For reference, I'm trying to implement the algorithm here.
I'd like to guarantee that if I call my collision detection function collide(Polygon polygon1, Polygon polygon2) and it detects a collision, the returned MTV will always point away from polygon1, toward polygon2. In order to do this, I need to guarantee that the separating axes that I generate, which are the normals of the polygon edges, always point away from the polygon that generated them. (That way, I know to negate any axis from polygon2 before using it as the MTV).
Unfortunately, it seems that whether or not the normal I generate for a polygon edge points towards the interior of the polygon or the exterior depends on whether the polygon's points are declared in clockwise or counterclockwise order. I'm using the algorithm described here to generate normals, and assuming that I pick (x, y) => (y, -x) for the "perpendicular" method, the resulting normals will only point away from the polygon if I iterate over the vertices in clockwise order.
Given that I can't force the client to declare the points of the polygon in clockwise order (I'm using java.awt.Polygon, which just exposes two arrays for x and y coordinates), is there a mathematical way to guarantee that the direction of the normal vectors I generate is toward the exterior of the polygon? I'm not very good at vector math, so there may be an obvious solution to this that I'm missing. Most Internet resources about the SAT just assume that you can always iterate over the vertices of a polygon in clockwise order.
You can just calculate which direction each polygon is ordered, using, for example, the answer to this question, and then multiply your normal by -1 if the two polygons have different orders.
You could also check each polygon passed to your algorithm to see if it is ordered incorrectly, again using the algorithm above, and reverse the vertex order if necessary.
Note that when calculating the vertex order, some algorithms will work for all polygons and some just for convex polygons.
I finally figured it out, but the one answer posted was not the complete solution so I'm not going to accept it. I was able to determine the ordering of the polygon using the basic algorithm described in this SO answer (also described less clearly in David Norman's link), which is:
for each edge in polygon:
sum += (x2 - x1) * (y2 + y1)
However, there's an important caveat which none of these answers mention. Normally, you can decide that the polygon's vertices are clockwise if this sum is positive, and counterclockwise if the sum is negative. But the comparison is inverted in Java's 2D graphics system, and in fact in many graphics systems, because the positive y axis points downward. So in a normal, mathematical coordinate system, you can say
if sum > 0 then polygon is clockwise
but in a graphics coordinate system with an inverted y-axis, it's actually
if sum < 0 then polygon is clockwise
My actual code, using Java's Polygon, looked something like this:
//First, find the normals as if the polygon was clockwise
int sum = 0;
for(int i = 0; i < polygon.npoints; i++) {
int nextI = (i + 1 == polygon.npoints ? 0 : i + 1);
sum += (polygon.xpoints[nextI] - polygon.xpoints[i]) *
(polygon.ypoints[nextI] + polygon.ypoints[i]);
}
if(sum > 0) {
//reverse all the normals (multiply them by -1)
}
First of all I am having trouble with the concept of a mathematical Vector when being applied to a Vector3d. I understand a vector to be just like a line except it has a direction property.
Now, Vector3d only takes in 3 arguments (x,y,z) in its constructor. I assumed this to be because the vector initially is assumed to start at the origin and go through the designated point. How can we ever have a vector which does not intersect the origin if the only attributes contained in Vector3d are x,y,z?
For example, I am trying to program a function which calculates the distance between two points on a sphere:
//Returns the shortest distance between two points on a sphere
public static double getGreatCircleDistance(Point3d p1, Point3d p2){
Vector3d v1 = getVector(viewSphereOrigin, p1);
Vector3d v2 = getVector(viewSphereOrigin, p2);
v1.normalize();
v2.normalize();
return Math.acos(v1.dot(v2)*(viewSphereDiameter/2));
}
//Returns a vector through two given Points in 3d space
public static Vector3d getVector(Point3d start, Point3d terminal){
return new Vector3d(terminal.x-start.x, terminal.y-start.y, terminal.z-start.z);
}
I do not understand however how getVector() can return a vector which passes through the two given points. I researched how to obtain a vector connecting two points:
http://emweb.unl.edu/math/mathweb/vectors/vectors.html#vec6
however fundamentally I still do not understand this. Can someone clear up the logic behind Vector3d for me please and how it can represent an arbitrary vector in 3D space yet it only contains x,y,z?
Thanks!
A vector is not a line; it is an entity with a magnitude and a direction. What it does not have is location.
You can represent a vector as the line segment between any two points: the magnitude is the distance between the points, and the direction is given by the direction of the line. Every time the distance and direction of the line are the same you get the same vector.
Since a vector does not have a location, we can arbitrarily choose one of the points to be the origin. This way a triple «x,y,z» uniquely represent a vector with the direction of the line from the point (0,0,0) to the point (x,y,z). But you get the same vector also by picking the points (5,4,2) and (5+x, 4+y, 2+z), or any other two points that are at the same distance and direction from each other.
As I know Vector3D means a [x,y,z] starting from the origin. If you would like to store a vector in 3D space (called Ray) you should store two Vector3D:
1. the starting point and the end point of the vector
OR
2. the origin and the direction of the vector.