I have 4 points, three of the points make two lines like a V or a < or a >, you get the idea, now I got a point that's in that cone (the V) and I can get the dist from the top to the bottom left, and bottom right, but not where the bottom pos is.
Maybe this will help.
And I have code to go along with this problem:
public float GetDist(Vector3f one, Vector3f two, Vector3f three, Vector3f p){
Vector3f one_to_point = new Vector3f(0,0,0);
Vector3f.sub(p,one,one_to_point); //Storing vector A->P
Vector3f one_to_two = new Vector3f(0,0,0);
Vector3f.sub(two, one, one_to_two); //Storing vector A->B
Vector3f one_to_three = new Vector3f(0,0,0);
Vector3f.sub(three, one, one_to_three); //Storing vector A->C
float q1 = Vector3f.dot(one_to_point, one_to_two) / one_to_two.lengthSquared(); // The normalized "distance" from a to b
float q2 = Vector3f.dot(one_to_point, one_to_three) / one_to_three.lengthSquared(); // The normalized "distance" from a to c
Now I already know that the pos vector is in the cone, so what do I need to do to get the pos as shown by the green circle's pos in the image?
You have 4 points in the plane : A,B,C and D (where D is what you label as pos in your diagram). A unique straight line can be drawn between any 2 distinct points so find the straight line that links A and D and get its equation in the form
y = m_1 * x + c_1
Do the same for line the points B and C to get
y = m_2 * x + c_2
Now you know the 2 lines, you can solve this pair of simultaneous equations to get the point (x,y) that lies at the green circle on your diagram - I shall call this E. Given E, calculate the length of vector BE and divide by the length of vector BC. This value is the value of X that you are looking for in your question.
If you do not know how to find the equation for a line that goes through 2 points look at this link for details http://www.ugrad.math.ubc.ca/coursedoc/math100/notes/zoo/eqline.html
I do not doubt that there is a simpler more elegant way to do this but if you get no other answer here, this approach will serve your purpose.
It's been a while since I've done vector algebra, but let me see if I got this right. You're looking for the green point, which is where a line from A to Pos intersects a line from B to C.
I believe if you knew the ratio of the angle that B-A-Pos forms to the angle that B-A-C forms, that ratio would be the same as the ratio of the distance from B to Green to the distance from B to C. From B, the direction of Green is the same as the direction of C, so the vector that represents Green's location is
VectorGreen = VectorB + (x1 / x2)(VectorC - VectorB) //The vector to B plus a fraction of the vector from B to C
x1 = arccos ( Normalize(VectorP - VectorA ) * Normalize(VectorB - VectorA) )//Angle between A to B and A to Pos
x2 = arccos ( Normalize(VectorB - VectorA ) * Normalize(VectorC - VectorA) ) //Angle between A to B and A to C
Related
I'm trying to create a method which calculates the x and y in a grid and eventually the distance between that point and the middle. The problem is, I only know a few values. To explain the case a bit better an image:
(the values between '(..,..)' are lat/long combinations).
As you can see, I know the following values:
start of canvas: xy(0,0)
middle of canvas: xy(540,800) and lat/long(52.3702160, 4.8951680)
max dimension of canvas: x 1080, y 1600
point: xy(?,?) and lat/long(52.4167267, 4.8052174)
point: xy(?,?) and lat/long(52,2422306, 5.1129068)
First, I need to do something to calculate the missing x and y's from the points.
I already tried doing the following:
double mapWidth = screenWidth;
double mapHeight = screenHeight;
// get x value
x = (location.getLongitude()+180)*(mapWidth/360);
// convert from degrees to radians
double latRad = location.getLatitude()*Math.PI/180;
// get y value
double mercN = Math.log(Math.tan((Math.PI/4)+(latRad/2)));
y = (mapHeight/2)-(mapWidth*mercN/(2*Math.PI));
point = new PointF((float)x,(float)y);
This works but I'm getting the wrong x and y values.
For example if my points lat/long are further away the x and y's are getting bigger (more to the middle). But they need to be more at the side because the lat/long point is further away.
All lat/long points inside 2km diameter need to be in my grid, if the point is for example 0.9km away from the center it needs to be nearly at the side.
After that I need to calculate the distance between the two points. I already got that part using the following:
Math.sqrt((point.x - point2.x) * (point.x - point2.x) + (point.y - point2.y) * (point.y - point2.y));
My main problem is calculating the x and y from my lat/long points.
If anyone wants to help, thanks in advance!
I completely rethought my way of calculating the x and y.
I solved it by doing the following:
double distanceMeters = mCurrentLocation.distanceTo(location);
x = ((1000+distanceMeters)*mMiddleCoords.x)/1000; //1000 = radius.
y = ((1000+distanceMeters)*mMiddleCoords.y)/1000;
You can't directly use the distance formula from latitude and longitude. You'll have to take into account the curvature of the sphere to calculate the distance.
The minimum distance between two points on a sphere (and hence earth, simplifying it to a perfect sphere) is the length of the chord on what is called the Great Circle running through those points. A Great Circle is a circle with its center running through the center of the sphere).
From Wikipedia:
C = SQRT(X^2 + Y^2 + Z^2)
where:
X = cos(lat2) * cos(long2) - cos(lat1) * cos(long1)
Y = cos(lat2) * sin(long2) - cos(lat1) * sin(long1)
Z = sin(lat2) - sin(lat1)
And the distance is (2 * R * arcsin(C/2)) where R is the radius of the earth or 6371 km
The other alternative - if you know you will always have the Android libraries - is the Location.distanceTo() method.
What is the formula for calculating the position of 3D point after it has been rotated around another 3D point a certain radians/degrees? I am using Java / LWLJGL.
Could someone just fill in the blanks in the following?
public Vector3f rotate(Vector3f origin, Vector3f rotation)
{
Vector3f ret = new Vector3f();
ret.x = __________;
ret.y = __________;
ret.z = __________;
}
Consider your fixed point has coordinates (a,b,c) and moving object (x1,y1,z1) at time t1 and at (x2,y2,z2) at time t2.
option 1
you can consider projection on x-yplane and projection on y-z plane and calculate angle in that 2D space.
option 2
you can consider two vectors. say vector A and B
A=(x1-a)i+(y1-b)j+(z1-c)k
B=(x2-a)i+(y2-b)j+(z2-c)k
Now use dot product of A and B
A . B = |A||B|cos(angle)
Let there be two balls, one of which is moving about in the Cartesian coordinate plane, while the other is stationary and immobile. At some point, the moving ball collides with the inert ball. Assuming the moving ball is traveling in a straight line, how can one derive the new angle that the moving ball will be propelled given the following information:
The moving ball's center coordinates (X0, Y0), radius (R0), and angle of travel before impact (A0)
The stationary ball's center coordinates (X1, Y1) and radius (R1)
If your second ball has infinite mass:
Where phi (after a long calc) is:
phi= -ArcTan[
( 2 R^2 Sin[A0] + 2 (YD Cos[A0] - XD Sin[A0]) (2 H Cos[A0] +
2 XD Sin[A0]^2 - YD Sin[2 A0])) /
((2 R^2 - XD^2 - 3 YD^2) Cos[A0] + (XD^2 - YD^2) Cos[3 A0] +
8 XD YD Cos[A0]^2 Sin[A0] + 4 H Sin[A0] (-YD Cos[A0] + XD Sin[A0]))
]
Where:
H = (R0 + R1)^2 - ((Y0 - Y1) Cos[A0] + (X0 - X1) Sin[A0])^2
R^2 = (R0 + R1)^2
XD = X1 - X0
YD = Y1 - Y0
Edit
To determine the whole trajectory, you'll also need the coordinates for the center of the moving ball at the time of impact. They are:
{X,Y}= {X1+Sin[A0] ((Y1-Y0) Cos[A0]+ (X0-X1) Sin[A0])-Cos[A0] Sqrt[H],
Y1+Cos[A0] ((Y0-Y1) Cos[A0]+(-X0+X1) Sin[A0])-Sin[A0] Sqrt[H]}
Page 3 of Pool Hall Lessons by Joe van den Heuvel, Miles Jackson gives a great example of how to do this.
// First, find the normalized vector n from the center of circle1 to the center of circle2
Vector n = circle1.center - circle2.center;
n.normalize();
// Find the length of the component of each of the movement vectors along n.
float a1 = v1.dot(n);
float a2 = v2.dot(n);
float optimizedP = (2.0 * (a1 - a2)) / (circle1.mass + circle2.mass);
// Calculate v1', the new movement vector of circle1
// v1 = v1 - optimizedP * m2 * n
Vector v1 = v1 - optimizedP * circle2.mass * n;
// Calculate v2', the new movement vector of circle2
// v2 = v2 + optimizedP * m1 * n
Vector v2 = v2 + optimizedP * circle1.mass * n;
circle1.setMovementVector(v1);
circle2.setMovementVector(v2);
Read at least page three to understand whats going on here.
You should take a look at the elastic collision article on wikipedia. I would explain here, but everything I could have said, wikipedia says it better and with clear examples and equations.
[A long, long time ago I studied this as an undergrad. ]
You need to be clear on the masses. Probably you are assuming equal mass for both balls, as opposed to one being of infinite mass.
The second thing is: Are you interested in considering rolling constraints as well as linear momentum. The treatments you will come across which talk along the lines of a simplistic elastic collision ignore all this. As an example, consider shots in pool/ snooker where you deliberately strike the ball away from the midpoint to generate front or backspin.
Do you want to able to do this?
If so, you need to consider the friction between a spinning ball and the surface.
For example in a "simple" straight-on collision between a rolling ball and a stationary one, if we assume perfectly elastic (again not quite true):
the initial collision stops the moving ball 'A'
the stationary ball 'B' starts moving at the impact speed of 'A'
'A' still has spin, it grips the surface and picks up some small velocity
'B' starts without spin and has to match it to its speed in order to roll. This results in it slowing slightly.
For the simplistic case, the calculation is much easier if you transform to the coordinates of the centre of mass. In that frame, the collision is always a straight-on collision, reversing the direction of the balls. You then just transform back to get the resultants.
Assuming indetical masses and speeds prior to the impact of v1 and w1.
V0 = centre of mass speed = (v1+w1)/2
v1_prime = v of mass_1 in transformed coords = v1 - V0
w1_prime = w1 - V0
Post collision, we have a simple reflection:
v2_prime = -v1_prime (== w1_prime)
w2_prime = -vw_prime (== v1_prime)
v2 = v2_prime + V0
w2 = w2_prime + V0
It simply reflects from the stationary ball. So compute the point of contact (the centres of the balls will be R0 + R1 apart) and the axis of reflection will be the line joining the centres.
EDIT: By which I mean the line joining the centres at the point of contact will have an angle, and you can use this angle to help compute the new angle of the moving ball.
I'm looking for advice on the best way to proceed. I'm trying to find whether a given point A:(a, b) is inside a regular hexagon, defined with center O:(x, y) and diameter of circumscribing circle.
It seems like overkill to use Ray-casting, or Winding-number to determine this, for such a simple case, and I'm currently looking at the option of finding the angle (from horizontal) of the line OA, and "normalising" (probably not the right word) it into one of the 6 equilateral triangles and seeing if this new point lies within this triangle.
I get the feeling I'm missing something simple, and there's an easy way (or if I'm really lucky, a Java API) to do this simply and efficiently.
Thanks for your help.
Edit: The hexagon is oriented such that one of the sides is flat with the horizontal.
You can use the equations for each of the sides of the hexagon; with them you can find out if a given point is in the same half-plane as the center of the hexagon.
For example, the top-right side has the equation:
-sqrt(3)x - y + sqrt(3)/2 = 0
You plug in this the coordinates of the point and then the coordinates of the center. If the results have the same sign, then the point is in the bottom-left half-plane (so it may be inside the hexagon).
You then repeat by using the equations of the others sides.
Note that this algorithm will work for any convex polygon.
If you reduce the problem down to checking {x = 0, y = 0, d = 1} in a single quadrant, you could make very simple.
public boolean IsInsideHexagon(float x0, float y0, float d, float x, float y) {
float dx = Math.abs(x - x0)/d;
float dy = Math.abs(y - y0)/d;
float a = 0.25 * Math.sqrt(3.0);
return (dy <= a) && (a*dx + 0.25*dy <= 0.5*a);
}
dy <= a checks that the point is below the horizontal edge.
a*dx + 0.25*dy <= 0.5*a checks that the point is to the left of the sloped right edge.
For {x0 = 0, y0 = 0, d = 1}, the corner points would be (±0.25, ±0.43) and (±0.5, 0.0).
This is what I have been using:
public bool InsideHexagon(float x, float y)
{
// Check length (squared) against inner and outer radius
float l2 = x * x + y * y;
if (l2 > 1.0f) return false;
if (l2 < 0.75f) return true; // (sqrt(3)/2)^2 = 3/4
// Check against borders
float px = x * 1.15470053838f; // 2/sqrt(3)
if (px > 1.0f || px < -1.0f) return false;
float py = 0.5f * px + y;
if (py > 1.0f || py < -1.0f) return false;
if (px - py > 1.0f || px - py < -1.0f) return false;
return true;
}
px and py are the coordinates of x and y projected onto a coordinate system where it is much easier to check the boundaries.
Looks like you know general solution: "It seems like overkill to use...". So here is my idea:
Calculate distance from point to center and let's call it l.
Then you can compare it to inradius (r) and circumradius (R). if l < r then point is inside hexagon, if l > R then outside. If r < l < R then you have to check against each side respectively, but since R - r is very small (13% of length of side of hex) so probability that you will have to do complex calculations is tiny.
Formulas can be found here: http://mathworld.wolfram.com/Hexagon.html
I would first check if the point is inside the inscribed circle (you can compute the inscribed circle radius easily) or outside the circumscribed circle (that you already have).
The first means the point is in, the latter means it's out.
Statistically, most of the input points should allow you to decide based on the above simple tests.
For the worst case scenario (point is in between the inscribed and circumscribed circles), I think you can find the two vertices that are closest to the point and then see on which side of the segment V1V2 the point is (inner or outer, as relative to the O center).
Special case: point is equal to one of the vertices => it's in.
If I'll have a more clever idea (or if I'll ever start to really learn trigonometry), I'll edit the answer to let you know :)
Subtract the position of the center of the hexagon from your point P to get a vector V. Then, take the dot product of V with the following vectors, which correspond to the three pairs of opposing hexagon edges:
[0,1] ; the edges that are flat with the horizontal
[cos(30),sin(30)] ; the upper-right and lower-left edges
[cos(-30),sin(-30)] ; the lower-right and upper-left edges
If any of the dot products are greater in magnitude than the distance from the center of the hexagon to one of its edges, then the point is not inside the hexagon.
For reference, the dot product of vectors [a,b] and [c,d] is a*c+b*d.
The angle "30" above is in degrees ;)
What you want is the code to find out whether a point is inside a convex polygon, an hexagon being a particular case of that.
Here's a good answer:
https://stackoverflow.com/a/34689268/516188
I did modify that function for my use, I find my version clearer. It's typescript (you just squint and it's javascript):
function vectorX(v: Vector): number {
return v[1].x - v[0].x;
}
function vectorY(v: Vector): number {
return v[1].y - v[0].y;
}
function crossProduct(v1: Vector, v2: Vector): number {
return vectorX(v1)*vectorY(v2) - vectorY(v1)*vectorX(v2);
}
function isInConvexPolygon(testPoint: Point, polygon: Polygon): boolean {
// https://stackoverflow.com/a/34689268/516188
if (polygon.length < 3) {
throw "Only supporting polygons of length at least 3";
}
// going through all the edges around the polygon. compute the
// vector cross-product http://allenchou.net/2013/07/cross-product-of-2d-vectors/
// to find out for each edge on which side of the edge is the point.
// if the point is on the same side for all the edges, it's inside
let initCrossIsPositive = undefined;
for (var i=0;i<polygon.length;i++) {
if (polygon[i].x === testPoint.x &&
polygon[i].y === testPoint.y) {
// testPoint is an edge of the polygon
return true;
}
const curPointOnEdge = polygon[i];
const nextPointOnEdge = polygon[(i+1)%polygon.length];
const vector1 = <[Point,Point]>[curPointOnEdge, nextPointOnEdge];
const vector2 = <[Point,Point]>[curPointOnEdge, testPoint];
const cross = crossProduct(vector1, vector2);
if (initCrossIsPositive === undefined) {
initCrossIsPositive = cross > 0;
} else {
if (initCrossIsPositive !== (cross > 0)) {
return false;
}
}
}
// all the cross-products have the same sign: we're inside
return true;
}
There's a nice generalization to a hex lattice using homogeneous coordinates, by representing the lattice as the cube-lattice intersected with the plane x+y+z=0, see https://www.redblobgames.com/grids/hexagons/#coordinates
What is the best way to go about moving a Point2D.Double x distance closer to another Point2D.Double?
Edit: Tried to edit, but so went down for maintenance. No this is not homework
I need to move a plane (A) towards the end of a runway (C) and point it in the correct direction (angle a).
alt text http://img246.imageshack.us/img246/9707/planec.png
Here is what I have so far, but it seems messy, what is the usual way to go about doing something like this?
//coordinate = plane coordinate (Point2D.Double)
//Distance = max distance the plane can travel in this frame
Triangle triangle = new Triangle(coordinate, new Coordinate(coordinate.x, landingCoordinate.y), landingCoordinate);
double angle = 0;
//Above to the left
if (coordinate.x <= landingCoordinate.x && coordinate.y <= landingCoordinate.y)
{
angle = triangle.getAngleC();
coordinate.rotate(angle, distance);
angle = (Math.PI-angle);
}
//Above to the right
else if (coordinate.x >= landingCoordinate.x && coordinate.y <= landingCoordinate.y)
{
angle = triangle.getAngleC();
coordinate.rotate(Math.PI-angle, distance);
angle = (Math.PI*1.5-angle);
}
plane.setAngle(angle);
The triangle class can be found at http://pastebin.com/RtCB2kSZ
Bearing in mind the plane can be in in any position around the runway point
You can minimize the difference along both axis by a percent (that depends on how much you want to move the points).
For example:
Point2D.Double p1, p2;
//p1 and p2 inits
// you don't use abs value and use the still point as the first one of the subtraction
double deltaX = p2.getX() - p1.getX();
double deltaY = p2.getY() - p1.getY();
// now you know how much far they are
double coeff = 0.5; //this coefficient can be tweaked to decice how much near the two points will be after the update.. 0.5 = 50% of the previous distance
p1.setLocation(p1.getX() + coeff*deltaX, p1.getY() + coeff*deltaY);
So you moved p1 halfway toward p2. The good thing avoid abs is that, if you choose which point will be moved and which one will stand still you can avoid if tests and just use the raw coefficient.
The shortest distance between two points is a line, so simply move that point x units along the line that connects the two points.
Edit: I didn't want to give away the specifics of the answer if this is homework, but this is simple enough that it can be illustrated without being too spoiler-y.
Let us assume you have two points A = (x1, y1) and B = (x2, y2). The line that includes these two points has the equation
(x1, y1) + t · (x2 - x1, y2 - y1)
where t is some parameter. Notice that when t = 1, the point specified by the line is B, and when t = 0, the point specified by the line is A.
Now, you would like to move B to B', a point which is a new distance d away from A:
A B' B
(+)---------------------(+)-----------(+)
<========={ d }=========>
The point B', like any other point on the line, is also governed by the equation we showed earlier. But what value of t do we use? Well, when t is 1, the equation points to B, which is |AB| units away from A. So the value of t that specifies B' is t = d/|AB|.
Solving for |AB| and plugging this into the above equation is left as an exercise to the reader.
Vectors to the rescue!
Given points A and B. Create a vector V from A to B (by doing B-A). Normalize vector V into a unit vector and then just multiply it with the distance, d, you want and finally add the resulting vector to point A. ie:
A_moved = A + |(B-A)|*d
Java(ish)
Vector2D a_moved = a.add(b.subtract(a).norm().multiply(d));
No angles, no nasty trig needed.
double angle = Math.atan2(landingCoordinate.y-coordinate.y, landingCoordinate.x-coordinate.x);
coordinate.x += Math.cos(angle)*distance;
coordinate.y += Math.sin(angle)*distance;
//Add 90 degress to the plane angle
plane.setAngle(angle + 1.57079633);
(point A is to be moved closer to B)
if (A.x > B.x)
//decrement A.x
if (A.x < B.x)
//increment A.x
that might be the basic idea in pseudocode, but there's a lot more to it than that. How do you define 'best' way?
Certain things need to be considered:
Is there a specific measure/ratio you want the points to be apart from each other, or do you just want them closer?
Should both coordinates always be modified? (e.g. if you want to move (1,50) closer to (0,0), do you make it (.5, 25) or just (1,25)?
if the point is to be 1 unit away, should it be 1 unit horizontally? directly diagonally? 1 unit away on the line between the 2 points?
Give us a little more detail and we'll see what we've got. :D
In this game, integral coordinates are used to represent squares in a grid. The method move(int row, int col) moves toward the specified row and column by advancing one square in one of eight semi-cardinal directions, as seen here.