I have two set's of longitude and latitude, i am desperately trying to figure out how many meters point A is displaced from point B, horizontally and vertically.
My goal would be have to +/-X and +/-Y values - I already have the shortest distance between the two points via Location.distanceBetween()....i thought i could use this with the Location.bearingTo() to find the values im looking for via basic trigonometry.
My thinking was i could use the bearing as angle A, 90 degrees as angle C and legnth of Side C (distanceBetween) to calculate the legnth of side A (x axis) and B (y axis) but the results were underwhelming to say the least lol
//CALCULATE ANGLES
double ANGLE_A;
ANGLE_A = current_Bearing; //Location.bearingTo()
ANGLE_A = ANGLE_A*Math.PI/180; //CONVERT DEGREES TO RADIANS
double ANGLE_C;
ANGLE_C = 90; // Always Right Angle
ANGLE_C = ANGLE_C*Math.PI/180; //CONVERT DEGREES TO RADIANS
double ANGLE_B;
ANGLE_B = 180 - ANGLE_A - ANGLE_C; // 3 sides of triangle must add up to 180, if 2 sides known 3rd can be calced
ANGLE_B = ANGLE_B*Math.PI/180; //CONVERT DEGREES TO RADIANS
//CALCULATE DISTANCES
double SIDE_C = calculatedDistance; //Location.distanceTo()
double SIDE_A = Math.sin(ANGLE_A) * SIDE_C /Math.sin(ANGLE_C);
double SIDE_B = Math.sin(ANGLE_B)*SIDE_C/Math.sin(ANGLE_C);
What im noticing is that my bearing changes very little between the two points regardless of how we move, though mind you im testing this at 10 - 100m distance, its always at 64.xxxxxxx and only the last few decimals really change.
All the online references i can find always look at computing the shortest path, and although this awesome site references x and y positions it always ends up combining them into shortest distance again
Would SUPER appreciate any pointers in the right direction!
Since the earth is not flat, your idea with 90 degree angles will not work properly.
What might be better, is this.
Lets say your 2 known points A and B have latitude and longitude latA, longA and latB, longB.
Now you could introduce two additional points C and D with latC = latA, longC = longB, and latD = latB, longD = longA, so the points A, B, C, D form a rectangle on the earth's surface.
Now you can simply use distanceBetween(A, C) and distanceBerween(A, D) to get the required distances.
It may be possible to utilize Location.distanceBetween(), if following conditions meet,
the points are located far apart from polar regions and
distance is short enough (compared to radius of the Earth).
The way is very simple. Just fix either longitude or latitude and vary only the other. Then calculate distance.
Location location1 = new Location("");
Location location2 = new Location("");
location1.setLatitude(37.4184359437);
location1.setLongitude(-122.088038921);
location2.setLatitude(37.3800232707);
location2.setLongitude(-122.073230422);
float[] distance = new float[3];
Location.distanceBetween(
location1.getLatitude(), location1.getLongitude(),
location2.getLatitude(), location2.getLongitude(),
distance
);
double lat_mid = (location1.getLatitude() + location2.getLatitude()) * 0.5;
double long_mid = (location1.getLongitude() + location2.getLongitude()) * 0.5;
float[] distanceLat = new float[3];
Location.distanceBetween(
location1.getLatitude(), long_mid,
location2.getLatitude(), long_mid,
distanceLat
);
float[] distanceLong = new float[3];
Location.distanceBetween(
lat_mid, location1.getLongitude(),
lat_mid, location2.getLongitude(),
distanceLong
);
double distance_approx = Math.sqrt(
Math.pow(distanceLong[0], 2.0) + Math.pow(distanceLat[0], 2.0)
);
Compare distance[0] and distance_approx, check whether accuracy meets your requiement.
If your points are close enough, you may easily calculate x-y distances from latitude / longitude once you know that 1 degree of latitude is 111km, and one degree of longitude is 111km * cos(latitude):
y_dist = abs(a.lat - b.lat) * 111000;
x_dist = abs(a.lon - b.lon) * 111000 * cos(a.lat);
For short distances we could easily ignore that earth is not exactly a sphere, the error is approximately 0.1-0.2% depending on your exact location.
There is no valid answer to this question until you define what projection.
The azimuth of a "straight" line varies along the route unless you are travelling exactly due south or due north. You can only calculate the angles at each node, or azimuth at a specific point along the route. Angles at the nodes will not add up to 180° because you're referring to an ellipsoidal triangle, and calculating an ellipsoidal triangle is a multiple-step process that in all honesty, is better left to the libraries out there such as OSGEO.
If you want to fit the geometry to a plane Cartesian, it is usually using the Lambert projection for areas mostly long on east and west directions, and Transverse Mercator on longer north to south projections. The entire Earth is mapped in the UTM (Universal Transverse Mercator) that will give you Cartesian coordinates anywhere, but in no case will you get perfect Eucldian geometry when dealing with geodetics. For instance, if you go south 10 miles, turn left 90° and go east for 10 miles, turn left 90° again, you can be anywhere from 10 miles from your starting point, to exactly back to where you started, if that point happened to be the North pole. So you may have a mathematically beautiful bearing on the UTM coordinate plane, but on the ground, you cannot turn the same angles as the UTM geometry indicates and follow that same path on ground. You will either follow a straight line on the ground and a curved line on a cartesian plane, or vice-versa.
You could do a distance between two points on the same northings and separately, the same eastings, and derive a north distance and an east distance. However, in reality the angles of this triangle will make sense only on paper, and not on the globe. If a plane took off at the bearing calculated by such a triangle, it would arrive in the wrong continent.
Related
Assume I have several bounding boxes with 4 coordinates pair (long/lat only) each representing the 4 corners of a square box. How can I check if 2 of those boxes intersects?
I know I could use java.awt.Rectangle to check if 2 rectangles intersects, but the problem is it is calculated using X/Y/Width/Height instead of coordinates.
Can someone please give me some directions on how can I do this calculations?
Thanks.
EDIT
What I am trying to accomplish is the same represented by this library.
Basically it calculates a square bounding box around a given point and check if the (imaginary) squares intersects with each other, like in this image:
(source: google.com)
So far I've been able to calculate the corners for each marker and now I need to somehow check if they intersect with each other. How can I do this intersection calculation?
EDIT 2
This is how I am calculating the corners:
private static double getLatitude(double distance, double lat, double angle) {
return toDegrees(asin(sin(toRadians(lat)) * cos(distance / RADIUS) + cos(toRadians(lat)) * sin(distance / RADIUS) * cos(toRadians(angle))));
}
private static double getLongitude(double distance, double lat, double lng, double angle) {
double newLat = getLatitude(distance, lat, angle);
return toDegrees(toRadians(lng) + atan2(sin(toRadians(angle)) * sin(distance / RADIUS) * cos(toRadians(lat)), cos(distance / RADIUS) - sin(toRadians(lat)) * sin(toRadians(newLat))));
}
Where RADIUS = 6378.1 and angle = 45/135/225/315 (top right, bottom right, bottom left and top left).
Example output
I'm assuming that in your "lat/long bounding box' each side follows the lines of constant longitude and latitude - in other words that the top side follows the line of constant latitude, and the left side the line of constant longitude.
While this is not actually a rectangle in real life, it can actually be treated as one for our purposes. Mathematically you can think of this as transforming the bounding box into a "lat/long' space, where the shape is in fact a rectangle. If that doesn't make sense you may have to take my word for it. In any case it is possible to show that the curved shapes in real space intersect if and only if the rectangles intersect in curved space.
The short version of this is: if you do a standard test for intersection of rectangles (using the Java Rectangle class code, and using latitude and longitude as the rectangle bounds) you will get the right result.
EXAMPLE
You have two areas, defined as:
The area between 50 and 52 degrees N and 75 and 77 degrees E
The area between 51 and 53 degrees N and 76 and 79 degrees E
You can correctly test for their intersection by doing:
Rectangle r1 = new Rectangle(75,50,2,2);
Rectangle r2 = new Rectangle(76,51,2,3);
boolean intersects = r1.insersects(r2);
It doesn't matter that the rectangles are not rectangular in Euclidean space.
P.S. This will not work if one of your rectangles actually contains either the north or south pole. In that case you will need to split each rectangle into two, one on each side of the pole. You need to normalize everything to +/- 90 latitude and +/- 180 longitude. You will need to do something clever if one or more of the rectangles overlaps the +/-180 longitude line.
I am trying to make a circle (actually a flat cylinder) rotate so that the edge crosses two points in world position. These two points can be anywhere on a sphere. The sphere has the same radius and position as the cylinder. the origin of both is [0,0,0].
It's a little bit hard to explain, so I included three pictures that I hope illustrates what I am trying to accomplish.
Here you see what I am trying to accomplish. The yellow circle represents one of the points along the sphere, while the red circle represents the other point. The blue line is actually a flat cylinder going through the sphere, and is rotated so that it goes through both points.
Here is another similar picture, but with the points at different locations.
In this picture one can see the cylinder in full, as the sphere has been hidden.
Now, I am really terrible at math, so I would really love an answer made up of pseudo code or a programming language. And if I should be so lucky, java.
The circles rotation can be represented with either a quaternion or a matrix
So far, what I have tried, is rotating the cylinder with an up vector towards one of the points, and a forward vector towards the other point. But I can't seem to make it work. I have also tried other solutions, most of them involving two rotations (one for each point), but I end up having trouble when combining the rotations.
Here is my current non-working code:
This code makes the circle go through the first point, and then rotates it with an "up vector" towards the same point, this second rotation varies depending on the first point position, and is kind off all over the place.
//calculate direction vector between the two points
point1point2dir.set(point1Pos);
//subtract point two position
point1point2dir.sub(point2Pos);
//normalize
point1point2dir.nor();
//make two quaternions for rotation
Quaternion rot1=new Quaternion();
Quaternion rot2=new Quaternion();
//set first rotation two a rotation between X-axis and point1 position. Vector3.X = (1,0,0)
rot1.set(m.quatUtils.getRot(Vector3.X, point1Pos));
//crossmuliply direction vector between the two points with X-axis
point1point2dir.crs(Vector3.X);
//set the second rotation to a rotation between Z-Axis and the crossmultiplied direction vector
rot2.set(m.quatUtils.getRot(Vector3.Z, point1point2dir));
//multiply the two rotations
rot1.mul(rot2);
//apply the rotation to the cylinders matrix
cylinderMatrix.rotate(rot1);
//the function that gets the quaternion rotation between two vectors
Quaternion getRot(Vector3 pStart, Vector3 pDest) {
start.set(pStart);
dest.set(pDest);
start.nor();
dest.nor();
cosTheta = Vector3.dot(start.x, start.y, start.z, dest.x, dest.y,
dest.z);
rotationAxis.set(0.0f, 0.0f, 0.0f);
if (cosTheta < -1.0f + 0.001f) {
rotationAxis.set(Z_AXIS);
rotationAxis.crs(start);
if (rotationAxis.len2() < 0.01f) {
rotationAxis.set(X_AXIS);
rotationAxis.crs(start);
}
rotationAxis.nor();
resultQuat.set(rotationAxis, 180.0f);
return resultQuat;
}
rotationAxis.set(start);
rotationAxis.crs(dest);
s = (float) Math.sqrt((1 + cosTheta) * 2);
invs = 1.0f / s;
resultQuat.set(rotationAxis.x * invs, rotationAxis.y * invs,
rotationAxis.z * invs, s * 0.5f);
return resultQuat;
}
I would suggest this solution:
Calculate v1 and v2 as the vectors from the center of the sphere to each point that you want the cylinder to pass trough.
Cross product v1 and v2 to get the vector up of the cylinder, let's call it n.
Position the center of the cylinder in the center of the sphere.
Rotate the cylinder using n as vector up.
I figured out the solution! It was actually really simple. I don't know how I managed to bungle the math as much as I did earlier. I actually did spend alot of time on this >:)
Sorry if I wasted anybodys time!
The solution:
find direction vector from point1 (A) to point2 (B).
crossmultiply direction vector with point2 to get (C)
Find the quaternion which represents the rotation from Z-axis to the crossmultiplied direction vector (C), function for doing this included in the code attached to the question.
apply rotation.
Here is the working code (yay):
//the rotation
Quaternion rot=new Quaternion();
//the direction from point1 to point 2 (the point positions are in this case also the direction vectors from center)
point1point2dir.set(point1Pos);
point1point2dir.sub(point2Pos);
point1point2dir.nor();
//crossmultiplied with point2
point1point2dir.crs(point2Pos);
//set the rotation to the rotation between Z-axis and the crossmultiplied direction between point 1 and 2
rot.set(m.quatUtils.getRot(Vector3.Z, point1point2dir));
//apply rotation
ekvatorMatrix.rotate(rot);
And here is the code for the function that returns the quaternion between two vectors:
Quaternion getRot(Vector3 pStart, Vector3 pDest) {
start.set(pStart);
dest.set(pDest);
start.nor();
dest.nor();
cosTheta = Vector3.dot(start.x, start.y, start.z, dest.x, dest.y,
dest.z);
rotationAxis.set(0.0f, 0.0f, 0.0f);
if (cosTheta < -1.0f + 0.001f) {
rotationAxis.set(Z_AXIS);
rotationAxis.crs(start);
if (rotationAxis.len2() < 0.01f) {
rotationAxis.set(X_AXIS);
rotationAxis.crs(start);
}
rotationAxis.nor();
resultQuat.set(rotationAxis, 180.0f);
return resultQuat;
}
rotationAxis.set(start);
rotationAxis.crs(dest);
s = (float) Math.sqrt((1 + cosTheta) * 2);
invs = 1.0f / s;
resultQuat.set(rotationAxis.x * invs, rotationAxis.y * invs,
rotationAxis.z * invs, s * 0.5f);
return resultQuat;
}
Assuming that the initial cylinder is axis aligned with the "circle" ends in positive and negative X direction, and assuming cylinder and sphere is initially unit size (radius=1.0) I would do the following:
Convert the world coordinate representation of the Red and "Yellow" points (let's just for fun call them A and B shall we) to normalized vectors pointing from centre [0,0,0] (from now on called C)
Calculate the angle between CA and CB (which is really just between A and B). Let's call this angle W
Calculate the vector perpendicular to both A and B by doing a cross product. Lets call this new vector D.
Find the rotation matrix that rotates from [0,0,1] to B. Lets call this M1. This can be done in the same way as in point 3 (create a perpendicular vector and rotate identity matrix around it with the angle between the normalized vectors).
Find the rotation matrix that rotates W around D. Let's call this M2
Combine M1 + M2 into M3
You result is M3
This was not tested and so I don't know if it works.
I am really struggeling to find the correct way to get the rotation angle around a single axis from an arbitrary quaternion. So other words I want to find the portion of the expressed rotation around a specified axis (in my case the Z-axis of the coordinate system, but an arbitrary solution would be nice) in terms of the angle. Can anyone point out to achieve this? Ideally some java fragment would be nice.
I tried the solution proposed in 1 for attitude, which is:
asin(2*qx*qy + 2*qz*qw)
However, this fails in some cases, e.g. a single rotation around the Z-axis with more than 0.6 * PI.
Angle and rotation axis of a quaternion
Every quaternion q can be decomposed as some kind of polar decomposition
q = r * (c + s * e)
where
r = |q|, s = |imag(q/r)|, c = real(q/r) and e = imag(q/s/r)
The axis of rotation of x ↦ q * x * q^(-1) is e, the angle is twice the angle α of the point (c,s)=(cos(α),sin(α)) on the unit circle.
To just compute the angle of rotation, the scaling by r is not that important, so
angle = 2*atan2( norm(imag(q)), real(q) )
Theory for Euler angles
A rotation about the X-axis is represented by a quaternion ca+sa*i, rotation about the Y axis by quaternion cb+sb*j and Z-axis by cc+sc*k where ca²+sa²=1 represent the cosine-sine pair of half the rotation angle a etc. Later 2a, c2a and s2a etc. will denote the double angle and its cosine and sine values.
Multiplying in the order xyz of application to the object at the origin gives a product
q=qw+qx*i+qy*j+qz*k
=(cc+sc*k)*(cb+sb*j)*(ca+sa*i)
Now interesting things happen in q*i*q^(-1) and q^(-1)*k*q, in that the inner terms commute and cancel, so that
q*i*q^(-1)*(-i) = (cc+sc*k)*(cb+sb*j)*(cb+sb*j)*(cc+sc*k)
= (cc+sc*k)*(c2b+s2b*j)*(cc+sc*k)
= (c2c+s2c*k)*c2b+s2b*j
(-k)*q^(-1)*k*q = (ca+sa*i)*(cb+sb*j)*(cb+sb*j)*(ca+sa*i)
=(ca+sa*i)*(c2b+s2b*j)*(ca+sa*i)
=(c2a+s2a*i)*c2b+s2b*j
which can then be used to isolate the angles 2a, 2b and 2c from
q*i*q^(-1)*(-i) = (q*i)*(i*q)^(-1)
= (qw*i-qx-qy*k+qz*j)*(-qw*i-qx-qy*k+qz*j)
= (qw²+qx²-qy²-qz²)
+ 2*(qw*qy-qx*qz)*j
+ 2*(qw*qz+qx*qy)*k
(-k)*q^(-1)*k*q = (q*k)^(-1)*(k*q)
= (-qw*k+qx*j-qy*i-qz)*(qw*k+qx*j-qy*i-qz)
= (qw²-qx²-qy²+qz²)
+ 2*(qw*qx+qy*qz)*i
+ 2*(qw*qy-qx*qz)*j
Resulting algorithm
Identifying expressions results in
s2b = 2*(qw*qy-qx*qz)
c2b*(c2a+s2a*i) = (qw²-qx²-qy²+qz²) + 2*(qw*qx+qy*qz)*i
c2b*(c2c+s2c*k) = (qw²+qx²-qy²-qz²) + 2*(qw*qz+qx*qy)*k
or
2a = atan2(2*(qw*qx+qy*qz), (qw²-qx²-qy²+qz²))
2b = asin(2*(qw*qy-qx*qz))
2c = atan2(2*(qw*qz+qx*qy), (qw²+qx²-qy²-qz²))
This constructs the angles in a way that
c2b=sqrt( (qw²+qx²+qy²+qz²)²+8*qw*qx*qy*qz )
is positive, so 2b is between -pi/2 and pi/2. By some sign manipulations, one could also obtain a solution where c2b is negative.
Answer to the question on the asin formula
Obviously, a different kind of rotation order was used, where the Z-rotation is the middle rotation. To be precise,
q = (cb+sb*j)*(cc+sc*k)*(ca+sa*i)
where
2b = heading
2a = bank
2c = attitude
To handle attitude rotation angles 2c larger that 0.5*pi, you need to compute the full set of Euler angles, since they will then contain two flips around the other axes before and after the Z-rotation.
Or you need to detect this situation, either by keeping the cosine of bank positive or by checking for overly large angle changes, and apply sign modifications inside the atan formulas, changing their resulting angle by pi (+or-), and change the Z angle computation to pi-asin(...)
Or, to only manipulate the angles after computation, if (2a,2b,2c) is the computed solution, then
(2a-sign(2a)*pi, 2b-sign(2b)*pi, sign(2c)*pi-2c)
is another solution giving the same quaternion and rotation. Chose the one that is closest to the expected behavior.
The answer can be found here Component of a quaternion rotation around an axis
"swing twist decomposition" from http://www.euclideanspace.com/maths/geometry/rotations/for/decomposition/
I'm implementing a simulation in Java using a GIS (WGS84). I want to place my agents shifted to each other. The latitude is easy 1 m is 1/111000 degrees. But I want to shift an agent on the longitude side I have to consider earth curvature (I guess!).
I found this formula on Wiki: a= (2*pi*r*cos(phi))/360
r : radius
phi: latitude
a : should be the distance
I tried now multiply my distances to 1/a, but the positions are not logical!
Is it your goal to calculate the distance between your two points?
I would use:
d(P1, P2) = ((r · pi)/180)) · cos−1 (cos(a1) · cos(a2) · cos(b1 − b2) + sin(a1) · sin(a2))
where d is distance, r would be the earth radius, cos-1 is the inverse cosinus and a1,a2,b1,b2 are the angles of your 2 agents
If you know the vertical and horizontal distance (l and h), you can simply calculate b1 = a1 - l/(2*pi*r*cos(angleFromEquator)*360) and a2 = h/(2*pi*r*360) + b2 if you are using spherical coordinates.
If you are at the equator (latitude = 0) and you shift 1.000 km to the east, you would end up ( 1.000 km / 40.000 km ) * 360° = 9° further east.
At a latitude of 45°, that would be ( 1.000 km / 28.000 km ) * 360° = 12.8°
If you'll move 1Km east, and then 1Km north, you'll reach a different location than if you'll move 1Km north and then 1Km east.
On extreme cases (specific latitudes near the north pole), moving 1Km east will bring you back to your original location.
Your concept of separating latitudinal and longitudinal 'shift' is wrong, since it is not suitable for locations on the surface of a sphere/ellipsoid.
Anyway, if your are looking for the earth's circumference at a given latitude, and a spherical model is accurate enough for your needs, look here.
I've been working on a top down car game for quite a while now, and it seems it always comes back to being able to do one thing properly. In my instance it's getting my car physics properly done.
I'm having a problem with my current rotation not being handled properly. I know the problem lies in the fact that my magnitude is 0 while multiplying it by Math.cos/sin direction, but I simply have no idea how to fix it.
This is the current underlying code.
private void move(int deltaTime) {
double secondsElapsed = (deltaTime / 1000.0);// seconds since last update
double speed = velocity.magnitude();
double magnitude = 0;
if (up)
magnitude = 100.0;
if (down)
magnitude = -100.0;
if (right)
direction += rotationSpeed * (speed/topspeed);// * secondsElapsed;
if (left)
direction -= rotationSpeed * (speed/topspeed);// * secondsElapsed;
double dir = Math.toRadians(direction - 90);
acceleration = new Vector2D(magnitude * Math.cos(dir), magnitude * Math.sin(dir));
Vector2D deltaA = acceleration.scale(secondsElapsed);
velocity = velocity.add(deltaA);
if (speed < 1.5 && speed != 0)
velocity.setLength(0);
Vector2D deltaP = velocity.scale(secondsElapsed);
position = position.add(deltaP);
...
}
My vector class emulates vector basics - including addition subtraction, multiplying by scalars... etc.
To re-iterate the underlying problem - that is magnitude * Math.cos(dir) = 0 when magnitude is 0, thus when a player only presses right or left arrow keys with no 'acceleration' direction doesn't change.
If anyone needs more information you can find it at
http://www.java-gaming.org/index.php/topic,23930.0.html
Yes, those physics calculations are all mixed up. The fundamental problem is that, as you've realized, multiplying the acceleration by the direction is wrong. This is because your "direction" is not just the direction the car is accelerating; it's the direction the car is moving.
The easiest way to straighten this out is to start by considering acceleration and steering separately. First, acceleration: For this, you've just got a speed, and you've got "up" and "down" keys. For that, the code looks like this (including your threshold code to reduce near-zero speeds to zero):
if (up)
acceleration = 100.0;
if (down)
acceleration = -100.0;
speed += acceleration * secondsElapsed;
if (abs(speed) < 1.5) speed = 0;
Separately, you have steering, which changes the direction of the car's motion -- that is, it changes the unit vector you multiply the speed by to get the velocity. I've also taken the liberty of modifying your variable names a little bit to look more like the acceleration part of the code, and clarify what they mean.
if (right)
rotationRate = maxRotationSpeed * (speed/topspeed);
if (left)
rotationRate = maxRotationSpeed * (speed/topspeed);
direction += rotationRate * secondsElapsed;
double dir = Math.toRadians(direction - 90);
velocity = new Vector2D(speed * Math.cos(dir), speed * Math.sin(dir));
You can simply combine these two pieces, using the speed from the first part in the velocity computation from the second part, to get a complete simple acceleration-and-steering simulation.
Since you asked about acceleration as a vector, here is an alternate solution which would compute things that way.
First, given the velocity (a Vector2D value), let's suppose you can compute a direction from it. I don't know your syntax, so here's a sketch of what that might be:
double forwardDirection = Math.toDegrees(velocity.direction()) + 90;
This is the direction the car is pointing. (Cars are always pointing in the direction of their velocity.)
Then, we get the components of the acceleration. First, the front-and-back part of the acceleration, which is pretty simple:
double forwardAcceleration = 0;
if (up)
forwardAcceleration = 100;
if (down)
forwardAcceleration = -100;
The acceleration due to steering is a little more complicated. If you're going around in a circle, the magnitude of the acceleration towards the center of that circle is equal to the speed squared divided by the circle's radius. And, if you're steering left, the acceleration is to the left; if you're steering right, it's to the right. So:
double speed = velocity.magnitude();
double leftAcceleration = 0;
if (right)
leftAcceleration = ((speed * speed) / turningRadius);
if (left)
leftAcceleration = -((speed * speed) / turningRadius);
Now, you have a forwardAcceleration value that contains the acceleration in the forward direction (negative for backward), and a leftAcceleration value that contains the acceleration in the leftward direction (negative for rightward). Let's convert that into an acceleration vector.
First, some additional direction variables, which we use to make unit vectors (primarily to make the code easy to explain):
double leftDirection = forwardDirection + 90;
double fDir = Math.toRadians(forwardDirection - 90);
double ldir = Math.toRadians(leftDirection - 90);
Vector2D forwardUnitVector = new Vector2D(Math.cos(fDir), Math.sin(fDir));
Vector2D leftUnitVector = new Vector2D(Math.cos(lDir), Math.sin(lDir));
Then, you can create the acceleration vector by assembling the forward and leftward pieces, like so:
Vector2D acceleration = forwardUnitVector.scale(forwardAcceleration);
acceleration = acceleration.add(leftUnitVector.scale(leftAcceleration));
Okay, so that's your acceleration. You convert that to a change in velocity like so (note that the correct term for this is deltaV, not deltaA):
Vector2D deltaV = acceleration.scale(secondsElapsed);
velocity = velocity.add(deltaV).
Finally, you probably want to know what direction the car is headed (for purposes of drawing it on screen), so you compute that from the new velocity:
double forwardDirection = Math.toDegrees(velocity.direction()) + 90;
And there you have it -- the physics computation done with acceleration as a vector, rather than using a one-dimensional speed that rotates with the car.
(This version is closer to what you were initially trying to do, so let me analyze a bit of where you went wrong. The part of the acceleration that comes from up/down is always in a direction that is pointed the way the car is pointed; it does not turn with the steering until the car turns. Meanwhile, the part of the acceleration that comes from steering is always purely to the left or right, and its magnitude has nothing to do with the front/back acceleration -- and, in particular, its magnitude can be nonzero even when the front/back acceleration is zero. To get the total acceleration vector, you need to compute these two parts separately and add them together as vectors.)
Neither of these computations are completely precise. In this one, you compute the "forward" and "left" directions from where the car started, but the car is rotating and so those directions change over the timestep. Thus, the deltaV = acceleration * time equation is only an estimate and will produce a slightly wrong answer. The other solution has similar inaccuracies -- but one of the reasons that the other solution is better is that, in this one, the small errors mean that the speed will increase if you steer the car left and right, even if you don't touch the "up" key -- whereas, in the other one, that sort of cross-error doesn't happen because we keep the speed and steering separate.