Given two triangles in 3D, defined by points [t1.v1, t1.v2, t1.v3] and [t2.v1, t2.v2, t2.v3], where vX are points with variables (x, y, z).
How can I calculate the force of gravity between them?
Formula for point masses:
force = constant*mass1*mass2/(distance^2);
For my application, the triangles will be close together, and approximating via point masses would not have the required precision.
I understand that this could be solved with a quadruple integral, but I don't have much mathematical know-how towards creating or solving such a complicated equation.
Edit:
My similar (related) question on math.stackexchange: https://math.stackexchange.com/questions/1082860/general-solution-for-the-gravity-between-two-3d-triangles/
Related
The answer to Direct way of computing clockwise angle between 2 vectors was helpful in getting the clockwise angle between two vectors, but what I need to know is how to get the angle from two vectors going in the clockwise direction from a specific vector.
Here's a visual explanation of what I am trying to say. When going in the clockwise direction from the red vector, the clockwise angle is this: (Excuse the bad drawing)
But when going in the clockwise direction from the black vector, the clockwise angle is this:
EDIT: I'll rephrase my question. This is what I am trying to achieve. I have been following this old but useful link on generating triangle meshes: http://www.geom.uiuc.edu/~samuelp/del_project.html#algorithms
With the above images, I always want the angle going in a clockwise direction from a specific vector. I have been using the code from the linked SO answer to get the angle, but its incorrect in my situation
float dotProd = vx*ux + vy*uy;
float det = vx*uy - vy*ux;
float angle = MathUtils.atan2(det, dotProd);//in radians
if(angle < 0) angle += MathUtils.PI;
The angle calculation incorrectly allows unnecessary edges to be connected.
How can I fix this?
I'm sure there is a shorter way to do it, but if you know where you 0,0 is
first do a check in which quarter your vector is and then perform the calculation accordingly.
it will solve your solution but mathematically I think you can get there faster.
I did these experiments:
int[] v1={5, 2}, v2={3, 4}, v3={5, 0};
double d1=v1[0]*v2[0]+v1[1]*v2[1], d2=v1[0]*v2[1]-v1[1]*v2[0];
System.out.println(Math.toDegrees(Math.atan2(d2, d1)));
d2=v2[0]*v1[1]-v2[1]*v1[0];
System.out.println(Math.toDegrees(Math.atan2(d2, d1)));
d1=v3[0]*v1[0]+v3[1]*v1[1]; d2=v3[0]*v1[1]-v3[1]*v1[0];
System.out.println(Math.toDegrees(Math.atan2(d2, d1)));
d1=v1[0]*v3[0]+v1[1]*v3[1]; d2=v1[0]*v3[1]-v1[1]*v3[0];
System.out.println(Math.toDegrees(Math.atan2(d2, d1)));
d1=v2[0]*v3[0]+v2[1]*v3[1]; d2=v3[0]*v2[1]-v3[1]*v2[0];
System.out.println(Math.toDegrees(Math.atan2(d2, d1)));
It seems the angle computed is the immediate angle: if it's positive the direction is counter clockwise (from v3 to v2 for example), if it is negative then it is clockwise.
I used standard java atan2 I dont know what you are using.
Therefore to get the clock wise always you have to check the result: if it is positive then subtract 360 degrees.
You have to do your own experiments to confirm this negative/positive.
I want to use the equation of "straight line" with given 2 Latitude+Longitude points on a map.
can i use the raw material of Latitude and Longitude to do the calculation like this-
poly1_lngY= list.get(i).getLongitude(); // Y1 point on a line
poly2_lngY= list.get(j).getLongitude(); // Y2 point on a line
poly1_latX=list.get(i).getLatitude(); // X1 point on a line
poly2_latX=list.get(j).getLatitude(); // X2 point on a line
incline_poly= (poly2_lngY-poly1_lngY)/(poly2_latX-poly1_latX);
or should i use Math class?
if i need to use the Math class, I would appreciate an answer to how to do that
No, what you're suggesting is not correct at all.
Lat and lon are angles in spherical coordinate systems. You should treat them as such.
The earth's radius is large enough and your distances small enough so that treating the earth as a plane is probably okay. But you need to convert those points to rectangular coordinates before calculating distance.
A better solution would be to know how to calculate distance in the correct coordinate system so it's always correct. Go look up how to do it for spherical coordinates or learn something about tensor calculus and metric tensors.
I am studying the following code.
boolean convex(double x1, double y1, double x2, double y2,
double x3, double y3)
{
if (area(x1, y1, x2, y2, x3, y3) < 0)
return true;
else
return false;
}
/* area: determines area of triangle formed by three points
*/
double area(double x1, double y1, double x2, double y2,
double x3, double y3)
{
double areaSum = 0;
areaSum += x1 * (y3 - y2);
areaSum += x2 * (y1 - y3);
areaSum += x3 * (y2 - y1);
/* for actual area, we need to multiple areaSum * 0.5, but we are
* only interested in the sign of the area (+/-)
*/
return areaSum;
}
I do not understand the concept that area being negative.
Shouldn't area be always positive? maybe I am lacking some understanding of terms here.
I tried to contact the original writer but this code is about 8 years old and I have no way to contact the original writer.
This method of determining if the given vertex x2y2 is convex seems really mobile. I really want to understand it.
Any direction or reference to help me understand this piece of code will be appreciated greatly.
Source code : http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applets/BruteForceEarCut.java
The algorithm use a very simple formula with which you can compute twice the area of a triangle.
This formula has two advantages:
it doesn't require any division
it returns a negative area if the point are in the counterclockwise order.
In the code sample, the actual value of the area doesn't matter, only the sign of the result is needed.
The formula can also be used to check if three points are colinear.
You can find more information about this formula on this site : http://www.mathopenref.com/coordtrianglearea.html
This algorithm is basically using the dot product of two vectors and interpreting the results. This is the core of the Gift Wrapping Algorithm used to find convex hulls.
Since a dot b is also equal to |a|*|b|*cos(theta) then if the result is positive, cos of theta must be positive and thus convex. Per a wiki article on cross products...
Because the magnitude of the cross product goes by the sine of the
angle between its arguments, the cross product can be thought of as a
measure of ‘perpendicularity’ in the same way that the dot product is
a measure of ‘parallelism’. Given two unit vectors, their cross
product has a magnitude of 1 if the two are perpendicular and a
magnitude of zero if the two are parallel. The opposite is true for
the dot product of two unit vectors.
The use of "area" is slightly misleading on part of the original coder in my opinion.
You know about how integrals work, right? One way to think of integrals is in terms of the area under the integrated curve. For functions that are strictly positive, that definition works great, but when the function becomes negative at some point, there is a problem because then you have to take the absolute value, right?
That is not always so, actually, and it can be quite useful in some contexts to leave the curve negative. Think back to what was said earlier: the area under the curve. All that space between negative infinity and our function. Clearly, that is absurd, right? A better way to think of it is as the difference between the area under the curve, and the area under the x axis. That way, when the function is positive, our curve is gaining more area, and when it is negative, it is gaining less than the x axis.
The same thing applies to plane figures that are not strict functions. In order to really determine this, we have to define which direction our edge is going as it travels around the figure. We can define it so that all the area on the right of our curve is inside the region, and all the area to the left is outside (or we can define it the other way around, but I will use the first way).
So our figure includes all the area from there to the edge at infinity of the plane that is directly to our right. Regions enclosed clockwise really include their conventional interior twice. Regions enclosed counterclockwise don't include their conventional interior at all. The area, then, is the difference between our region and the whole plane.
The application of this to concavity is fairly simple, if you understand what it actually means to be concave or convex. The triangle you are given is concave if it is cutting an area out from the plane, and it is convex if you are adding extra area to it. That is the exact same thing we were doing to determine the our area, so positive area corresponds to a convex shape, and negative area corresponds to a concave shape.
You can also do other weird things with this conceptual model. For instance, you can turn a region 'inside out' by reversing the edge direction.
I'm sorry if this has been a little hard to follow, but this is the actual way I understand negative area.
I'm making a simple Vector class with a simple usage, so I don't want to import a whole library (like JScience...) for something that I can do myself.
Currently I have made this code so far:
public void add(Vector2D v){
double ang = this.angle*Math.PI/180;
double mag = this.magnitude;
double ang0 = v.angle*Math.PI/180;
double mag0 = v.magnitude;
//vector to coordinates
double x1 = mag*Math.cos(ang);
double y1 =-mag*Math.sin(ang);
//adding the other vector's coordinates
double x2 =x1+mag*Math.cos(ang0);
double y2 =y1-mag*Math.sin(ang0);
//back to vector form
double newMagnitude = Math.sqrt(x2*x2+y2*y2);
double newAngle = Math.atan2(y2,x2);
this.magnitude = newMagnitude;
this.angle = newAngle;
}
It's converting both vectors to coordinates and then back with the trigonometric functions, But those are extremely slow, and the method will be used very frequently.
Is there any better way?
First off, some terminology 101:
Point: a dimensionless entity that a space is made of.
Space: a set of points.
Euclidean space: a set of points, together with a set of lines and with the notion of closeness (topology). The set of lines is bound by the Euclid's axioms. It is uniquely defined by its dimension.
Vector: a translation-invariant relationship between two points in an Euclidean space.
Coordinate system: a mapping from tuples of real numbers to points or vectors in some space.
Cartesian coordinate system: A specific mapping, with the properties (in case of the Euclidean 2D space) that the set of points ax+by+c=0 is a line unless a,b are both zero, that the vectors [0,1] and [1,0] are perpendicular and unit length, and that points in space are close together iff they are close together in all coordinates. This is what you refer to as "coordinates".
Polar coordinate system: Another specific mapping, that can be defined from the cartesian coordinates: [arg,mag] in polar coordinates map to [cos(arg)*mag, sin(arg)*mag] in cartesian coordinates. This is what you refer to as "vector form".
The cartesian coordinate system has multiple benefits over the polar coordinate system. One of them is easier addition: [x1,y1]+[x2,y2]=[x1+x2,y1+y2] and scalar multiplication: [x1,y1].[x2,y2]=x1*x2+y1*y2. Additive inversion is slightly easier as well: -[x,y]=[-x,-y]
Another benefit is that while polar coordinates are strictly 2D (there is no unique extension - the spherical coordinate system is a candidate, though), cartesian coordinates extend naturally to any number of dimensions.
For this reason, it is beneficial - and usual - to always store vectors in their cartesian coordinate form.
If you ever need vectors in their polar form, then (and only then) convert, once and for all.
Polar coordinates not as useful. They can be used for input and output, but they are rarely useful for computation.
You keep storing your vectors in the polar form. You convert them to their cartesian form for computation, then convert back to polar - only to convert them to the cartesian again.
You should store your vectors in the cartesian form. The performance improvement should be clearly visible if you drop the redundant conversion.
Even if you want to rotate a vector, it's not beneficial to convert to polar and back. Rotation by a signed angle a is as easy as [x*cos(a)+y*sin(a), y*cos(a)-x*sin(a)]. That's two trigonometric functions (at most - you can cache these values) to rotate an entire array of vectors.
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)
}