I need to take a point, and determine what the point is that's N miles north-west of it, and N miles south-east of it. It'll essentially create a bounding box around the initial point.
I've looked around a bit, and found some stuff about Haversine, but it seems like all of the code implementations are for the distance between two points, not a new point component from a point.
Is there an existing implementation of such a thing, preferably in Java, that already exists? Or any other language?
Here is the methods I'd imagine that'd I'd need:
public float longitudeFromPoint( float lat, float long, int vertical, int horizontal )
{
// something
}
public float latitudeFromPoint( float lat, float long, int vertical, int horizontal )
{
// something
}
float startLat = 41.829347;
float startLong = -87.633788
float northWestLat = latitudeFromPoint( startLat, startLong, 1, -1 );
float northWestLong = latitudeFromPoint( startLat, startLong, 1, -1 );
float southWestLat = latitudeFromPoint( startLat, startLong, -1, 1 );
float southWestLong = latitudeFromPoint( startLat, startLong, -1, 1 );
This may be worth reading: Finding Points Within a Distance of a Latitude/Longitude Using Bounding Coordinates. It gives a short theoretical background on spherical coordinates and provides some java code.
The link is borrowed from the accepted answer to this thread on SO:
Calculating bounding box a certain distance away from a lat/long coordinate in Java
Related
Im writing a program, that takes 3d coordinates and places them on a 3d globe, projected onto a 2d screen. To turn the coordinates around an axis, i wanted to use the normal of the two points (start- and end- point (of the flight)), to turn it onto the x3 axis and then turn the rest of the points in the same manner, to eventually calculate the points, that i need to animate a point, that goes from point A to point B. the matrix I use to put the points onto the globe is:
public double[] genXYZ(double phi, double theta) {
double[] coords3D = new double[3];
phi = Math.toRadians(phi);
theta = Math.toRadians(theta);
coords3D[0] = Math.cos(theta) * Math.cos(phi);
coords3D[1] = Math.cos(theta) * Math.sin(phi);
coords3D[2] = Math.sin(theta);
return coords3D;
}
everything works just fine. Until I try to calculate the phi and theta angles of the normal (after I calculate the normal correctly).
public double[] getNAngles(double[] ncoords) {
double[] NAngles = new double[2];
NAngles[1] = Math.asin(Math.toRadians(ncoords[2]));
NAngles[0] = Math.acos(ncoords[0] / Math.cos(NAngles[1]));
NAngles[0] = Math.toDegrees(NAngles[0]);
NAngles[1] = Math.toDegrees(NAngles[1]);
System.out.println("N phi: " + NAngles[0]);
System.out.println("N theta: " + NAngles[1]);
return NAngles;
}
Globe
Cyan: start (Greenwich)
Magenta: end (Istanbul)
Black: normal
Pink: what the code calculated, what angles black has.
Thanks in advance!
Remove Math.toRadians call because coords are not angles, they are dimensionless values in range -1..1
NAngles[1] = Math.asin(ncoords[2]);
Also consider using atan2 function for NAngles[0] calculation to exclude sign effects and arccosine angle limit (0..Pi).
NAngles[0] = Math.atan2(ncoords[1], ncoords[0]);
I'm trying to do some basic trigonometry with Java and LibGDX on android.
I've spent a long time googling "How to find an angle in right triangles".
I still don't really understand :(
I want to give an Actor subclass a random direction to follow. So what is the angle - and what should I set xSpeed and ySpeed to, in order to move at the correct angle.
I started writing an app to help me see how it works.
There are two objects - An origin point and a touch point. User presses screen, touchPoint moves to where user touched. Methods fire to figure out the appropriate values. I know the XDistance and YDistance between the two points. That means I know the Opposite length and the Adjacent length. So all I need to do is tan-1 of (opposite / adjacent), am I right?
I just don't understand what to do with the numbers my program spits out.
Some code:
In create event of main class:
stage.addListener(new ClickListener() {
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer) {
touchPoint.setX(x);
touchPoint.setY(y);
touchPoint.checkDistance(); // saves x and y distances from origin in private fields
atan2D = getAtan2(touchPoint.getYDistance(), touchPoint.getXDistance());
tanhD = getTanh(touchPoint.getYDistance(), touchPoint.getXDistance());
xDistanceLbl.setText("X Distance: " + touchPoint.getXDistance());
yDistanceLbl.setText("Y Distance: " + touchPoint.getYDistance());
atan2Lbl.setText("Atan2: " + atan2D);
tanhLbl.setText("Tanh: " + tanhD);
angleLbl.setText("Angle: No idea");
}
})
...
private double getAtan2(float adjacent, float opposite) {
return Math.atan2(adjacent, opposite);
}
private double getTanh(float adjacent, float opposite) {
return Math.tanh((adjacent / opposite));
}
These two functions give me numbers between (atan2: -pi to pi) and (tanh: -1.0 to 1.0)
How do I turn these values into angles from which I can then work backwards and get the opposite and adjacent again?
Doing this should allow me to create and object with a random direction, which I can use in 2D games.
atan2 gives you direction in radians. Direction from origin (0,0) to touchPoint. If you need direction from some object to touchPoint, then subtract object coordinates. Perhaps you also want to see direction in degrees (this is only for human eyes)
dx = x - o.x
dy = y - o.y
dir = atan2(dy, dx)
dir_in_degrees = 180 * dir / Pi
I you have direction and want to retrieve coordinate differences, you need to store distance
distance = sqrt(dx*dx + dy*dy)
later
dx = distance * cos(dir)
dy = distance * sin(dir)
But note that often storing dx and dy is better, because some calculations might be performed without trigonometric functions
Just noticed - using tanh is completely wrong, this is hyperbolic tangent function, it has no relation to geometry.
You can use arctan, but it gives angle in half-range only (compared with atan2)
I have got some trees, which are greatly lagging the game, so I would like to check if the trees are in front of the camera or not.
I have had some help from the Mathematics forum, and also had a look at This link to help me convert pitch/yaw to the directional vector needed.
But for some reason, whenever I move the camera to the left, the trees become visible, wheras whenever I move it to the right, they become unvisible (So if camera is pointing at +1 on the Z axis, it seems to be rendering the trees, but -1 on the Z axis and it seems to not render them).
(See http://i.gyazo.com/cdd05dc3f5dbdc07577c6e41fab3a549 for a less-jumpy .mp4)
I am using the following code to check if an object is in front of the camera or not:
Ship you = shipsID.get(UID);
int dis = 300;
Vector3f X = new Vector3f(camera.x(), camera.y(), camera.z());
float x = (float) (Math.cos(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float y = (float) (Math.sin(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float z = (float) Math.sin(Math.toRadians(camera.pitch()));
Vector3f V = new Vector3f(x, y, z);
for (Tree tree : trees){
Vector3f Y = new Vector3f(tree.location.x, tree.location.y, tree.location.z);
Vector3f YMinusX = Y.negate(X);//new Vector3f(Y.x - X.x, Y.y - X.y, Y.z - X.z);
float dot = Vector3f.dot(YMinusX, V);
if (dot > 0){
tree.render();
}
}
Is anyone able to tell me what I have done wrong here? I can't work out if it's the math.. Or the code.. Or what?
Camera translation code:
public void applyTranslations() {
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_MODELVIEW);
glRotatef(pitch, 1, 0, 0);
glRotatef(yaw, 0, 1, 0);
lastYaw = yaw;
glRotatef(roll, 0, 0, 1);
glTranslatef(-x, -y, -z);
glPopAttrib();
}
UPDATE:
It appears to be where the camera is looking. For example, if I look to -Z, nothing happens, but if I look to +Z, they all render.
The if (dot > 0) code appears to somehow being +Z rather than +TheCameraRotation.
Your camera rotations yaw around Y, implying Y is your up vector. However, float z = (float) Math.sin(Math.toRadians(camera.pitch())); gives Z for your up vector. There is an inconsistency. I'd start by swapping y and z here, then print everything out every frame so you can see what happens as you rotate the camera. Also render just one tree and print dot. E.g. you might quickly notice the numbers approach 1.0 only when you look at 90 degrees left of the tree which narrows down the problem. As #DWilches notes, swapping cos/sin will change the phase of the rotation, which would produce such an effect.
You might consider limiting the dot product to the camera's field of view. There are still problems in that trees are not just points. A better way would be to test tree bounding boxes against the camera frustum, as #glampert suggests.
Still, the tree geometry doesn't look that complex. Optimization wise, I'd start trying to draw them faster. Are you using VBOs? Perhaps look at methods to reduce draw calls such as instancing. Perhaps even use a few models for LOD or billboards. Going even further, billboards with multiple trees on them. Occlusion culling methods could be used to ignore trees behind mountains.
[EDIT]
Since your trees are all roughly on a plane, you could limit the problem to the camera's yaw:
float angleToTree = Math.atan2(tree.location.z - camera.z(), tree.location.x - camera.x());
float angleDiff = angleToTree - camera.yaw();
if (angleDiff > Math.PI)
angleDiff -= 2.0f * Math.PI;
if (angleDiff < -Math.PI)
angleDiff += 2.0f * Math.PI;
if (abs(angleDiff) < cameraFOV + 0.1f) //bias as trees are not points
tree.render();
Could you write it like this
Ship you = shipsID.get(UID);
int dis = 300;
Vector3f X = new Vector3f(camera.x(), camera.y(), camera.z());
float x = (float) (Math.cos(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float y = (float) (Math.sin(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float z = (float) Math.sin(Math.toRadians(camera.pitch()));
Vector3f V = new Vector3f(x, y, z);
for (Tree tree : trees){
Vector3f Y = new Vector3f(tree.location.x, tree.location.y, tree.location.z);
Vector3f YMinusX = Y.negate(X);//new Vector3f(Y.x - X.x, Y.y - X.y, Y.z - X.z);
float dot = Vector3f.dot(YMinusX, V);
if (dot > 0){
tree.render();
}
}
As you can see there is far less calculation being performed for each tree.
For what I see here the correct formulas are:
x = Math.sin(pitch) * Math.cos(yaw);
y = Math.sin(pitch) * Math.sin(yaw);
z = Math.cos(pitch);
Could you try them ?
I have the following setup of items in real life:
The radar is static, which means it always has the same position. The A-item can move and its position can be whatever. From the radar I can read the x and y coordinates of A in relation to the radar. I have written the following classes to describe the position of each item:
public class Position {
public enum Direction {
EAST, WEST, NORTH, SOUTH
};
public final Direction latitudeDirection, longitudeDirection;
public final float latitude, longitude, altitude;
public Position(Direction latitudeDirection, Direction longitudeDirection,
float latitude, float longitude, float altitude) {
this.latitudeDirection = latitudeDirection;
this.longitudeDirection = longitudeDirection;
this.latitude = latitude;
this.longitude = longitude;
this.altitude = altitude;
}
public Position(float radarX, float radarY) {
// TODO: Implement the question here
this.altitude = Config.RADAR_POSITION.altitude;
}
}
class Config {
// Position of the radar
public static final Position RADAR_POSITION = new Position(
Position.Direction.NORTH, // Latitude direction
Position.Direction.EAST, // Longitude direction
55.0f, // Latitude
13.0f, // Longitude
60.0f); // Altitude
// Facing direction of the radar in degrees. 0° is north, advancing
// clockwise.
public static final float RADAR_FACING_DIRECTION = 10.0f;
}
Now given the geographic coordinates of the radar, the x and y coordinates of A relative to the radar and the facing direction of the radar relative to the North, how can I calculate the absolute geographic coordinates of A?
The curvature of the earth is not an issue since the maximum value of x and/or y cannot be more than a couple hundred meters.
As an example, you can use trigonometric functions to create triangles to find coordinates of A:
In this case, Ax = (y)(cos 10) - (x)(cos 80), and you could work out Ay similarly.
This way, you are never stuck in degrees, you are simply working in meters.
The robust solution is Vishal's comment in the OP, which was posted whilst I was drawing and scanning:
xnew = x * cos(theta) - y * sin(theta);
ynew = x * sin(theta) + y * cos(theta);
In general, you can use the following steps:
transform your radar position (lat, lon, height) into metric earth centered earth fixed xyz-system (ECEF)
You can then use/combine any rotation and translation arguments/matrices, which describe radar rotation and object position, in this metric system
back transform newly acquired xzy coordinates to lat/lon/h
There are many ressources for such transformations, check this, for instance: http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf
You can also introduce a scene coordinate system, if needed (ENU). Here is a fairly good overview describing the relation of UTM, ECEF, ENU and geodotic coordinates(Lat/lon/h):
http://www.dirsig.org/docs/new/coordinates.html
If you need sample code for ECEF to/from Geodetic conversion, have a look at the matlab code, http://www.mathworks.de/de/help/map/ref/ecef2geodetic.html,
or use a library like GDAL (http://www.gdal.org/)
I think it should be possible to do it this way: Convert the x and y coordinates to polar coordinates r and theta, (with the radar as the origin). Subtract the radar's rotation, and convert back to cartesian coordinates. Then you just have to convert to latitude and longitude and add the coordinates of the radar.
double r = Math.hypot(radarX, radarY);
double theta = Math.atan2(radarY, radarX);
theta -= Math.toRadians(Config.RADAR_FACING_DIRECTION);
float x = (float) r * Math.cos(theta);
float y = (float) r * Math.sin(theta);
longitude = metersToLongitude(Config.RADAR_POSITION, y) + Config.RADAR_POSITION.longitude;
latitude = metersToLatitude(Config.RADAR_POSITION, x) + Config.RADAR_POSITION.latitude;
I found formulae for the length of a degree of latitude and longitude on Wikipedia. A degree of latitude is the same everywhere but longitude gets smaller near the poles.
static float metersToLatitude(Position near, float meters) {
return meters / 110.6*1000;
}
static float metersToLongitude(Position near, float meters) {
float lat = Math.toRadians(near.latitude);
return meters /
(111132.954 - 559.822 * Math.cos(2*lat) + 1.175 * Math.cos(4*lat));
}
Unfortunately this doesn't seem to work and I can't figure out why.
If you want to express your coordinates in positive degrees east/west/north/south you'll also have to check if they're negative and invert them and the direction in that case.
Does this help for conversion?
http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF ?
Finally I solved it. The code is attached below. Since Samuel Edwin Ward's answer is the one that inspired me, I will accept his answer.
public Position(float radarX, float radarY) {
// Convert A's position to distance and bearing in relation to the North
double objDistance = (Math.hypot(radarX, radarY) / 6367500 /* Mean earth radius */);
double objBearing = (Math.atan2(radarY, radarX) + Math.toRadians(Config.RADAR_BEARING));
// Convert the Radar's geographic coordinates to radians
double latitudeRadar = Math.toRadians(Config.RADAR_POSITION.latitude);
double longitudeRadar = Math.toRadians(Config.RADAR_POSITION.longitude);
// Calculate A's geographic coordinates in radians
double latitudeObject = Math.asin(Math.sin(latitudeRadar)*Math.cos(objDistance) +
Math.cos(latitudeRadar)*Math.sin(objDistance)*Math.cos(objBearing));
double longitudeObject = longitudeRadar + Math.atan2(Math.sin(objBearing)*Math.sin(objDistance)*Math.cos(latitudeRadar),
Math.cos(objDistance)-Math.sin(latitudeRadar)*Math.sin(latitudeObject));
// Normalize to -180 ... +180 degrees
longitudeObject = (longitudeObject+3*Math.PI) % (2*Math.PI) - Math.PI;
// Set the A's coordinates in degrees
this.latitude = (float) Math.toDegrees(latitudeObject);
this.longitude = (float) Math.toDegrees(longitudeObject);
// Set the rest of the arguments
this.latitudeDirection = Config.RADAR_POSITION.latitudeDirection;
this.longitudeDirection = Config.RADAR_POSITION.longitudeDirection;
this.altitude = Config.RADAR_POSITION.altitude;
}
You rotate all coordinates in the local system of the radar -10° and are then able to just add the radar's x/y coordinates to the A object coordinates.
I am trying to write a simple physics simulation where balls with varying radii and masses bounce around in a perfectly elastic and frictionless environment. I wrote my own code following this resource: http://www.vobarian.com/collisions/2dcollisions2.pdf and I also tested the code from here: Ball to Ball Collision - Detection and Handling
QUESTION EDITED
With the help of Rick Goldstein and Ralph, I have gotten my code to work (there was a typo..). Thanks so much for you help. However I am still confused as to why the other algorithm isn't working for me. The balls bounce off in the correct directions, but the total energy of the system is never conserved. The velocities get faster and faster until the balls just start blinking in static positions on the screen. I actually want to use this code in my program, because it is a lot more concise than the one I wrote.
Here is the functional algorithm that I wrote (although I did take the first bit from that other source). Its in a Bubble class:
public void resolveCollision(Bubble b)
{
// get the minimum translation distance
Vector2 delta = (position.subtract(b.position));
float d = delta.getMagnitude();
// minimum translation distance to push balls apart after intersecting
Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / b.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
b.position = b.position.subtract(mtd.multiply(im2 / (im1 + im2)));
//get the unit normal and unit tanget vectors
Vector2 uN = b.position.subtract(this.position).normalize();
Vector2 uT = new Vector2(-uN.Y, uN.X);
//project ball 1 & 2 's velocities onto the collision axis
float v1n = uN.dot(this.velocity);
float v1t = uT.dot(this.velocity);
float v2n = uN.dot(b.velocity);
float v2t = uT.dot(b.velocity);
//calculate the post collision normal velocities (tangent velocities don't change)
float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass+b.mass);
float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass);
//convert scalar velocities to vectors
Vector2 postV1N = uN.multiply(v1nPost);
Vector2 postV1T = uT.multiply(v1t);
Vector2 postV2N = uN.multiply(v2nPost);
Vector2 postV2T = uT.multiply(v2t);
//change the balls velocities
this.velocity = postV1N.add(postV1T);
b.velocity = postV2N.add(postV2T);
}
And here is the one that doesn't work
public void resolveCollision(Bubble b)
{
// get the minimum translation distance
Vector2 delta = (position.subtract(b.position));
float d = delta.getMagnitude();
// minimum translation distance to push balls apart after intersecting
Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / b.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
b.position = b.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2 v = (this.velocity.subtract(b.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse (1f is the coefficient of restitution)
float i = (-(1.0f + 1f) * vn) / (im1 + im2);
Vector2 impulse = mtd.multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
b.velocity = b.velocity.subtract(impulse.multiply(im2));
}
Let me know if you find anything. Thanks
Is there a typo in the line that sets v1nPost? Looks like the denominator should be this.mass + b.mass, not this.mass * b.mass.
Also, because you're computing a collision between this and b, are you checking to make sure you're not also doing the same collision between b and this, thus doubling the delta applied to each participating bubble in the collision?
I do a first guess: getMass() return an integer(or int) (and not a float or double)?
If this is true, than you problem is that 1 / getMass() will result in an integer value (and can be only 1 or most time 0)). To fix this replace 1 by 1.0 or 1.0f
Because the general rule is simple:
If you have a math operation (+,-,*,/) the resulting type will be integer if none of the both operants is a floating point data structure (double or float)
Anyway: there could be a second problem, may your calcualtion is not precise enougth. Then you should use double instead of float.
There is a part that looks strange:
The two calculations:
float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass*b.mass);
float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass);
are symmetric, except the last operation, in the first it is * in the second it is +