Cartesian coordinates in Java - java

I'm trying to draw a function's curve, so I need a method to convert my curve points coordinates to screen coordinates but I can't get it to work.
Here's the method I use to convert:
public Point tradPoint(Point P){
Point Ptd = new Point();
Ptd.x=getWidth()/2 + P.x*getWidth()/20;
Ptd.y=getHeight()/2 - P.y*getHeight()/20;
return Ptd;
}
but it doesn't work.
I should mention that I'm using a Cartesian coordinate system and a unit=20.
Any suggestions?
Thanks

Should be
Ptd.x = getWidth() / 2 + P.x * 20;
Ptd.y = getHeight() / 2 - P.y * 20;
where 20 is the unit width.
Also, Ptd should be pTd or even better pointTranslated and P should be p or point. Java identifiers should start with a lowercase letter and be descriptive.

Related

Orbit Simulator in Java returning odd values for velocity etc. despite correct math

I am using LibGDX to make an orbit simulator (elliptical as planets possess their own initial velocity) and I have the physics mapped out like so:
public void move(float deltaTime, Planet planet) {
float deltaX = planet.getPos().x - this.pos.x;
float deltaY = planet.getPos().y - this.pos.y;
float alpha = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
float distance = (float) Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
float F = G * this.m * planet.getM() / distance*distance;
this.force.x = F * MathUtils.cos(alpha);
this.force.y = F * MathUtils.sin(alpha);
this.vel.x += (this.force.x / this.m) * deltaTime;
this.vel.y += (this.force.y / this.m) * deltaTime;
this.pos.x += this.vel.x * deltaTime;
this.pos.y += this.vel.y * deltaTime;
}
The problem is that my planet wobbles around and doesn't orbit at all. I fear my calculations in the code might be wrong as the physics are definitely double-checked and correct.
Each celestial object is a planet and I have no 'Sun' classes of any type so far. Only one Planet class, which only has Getter and Setter methods, a render() method (which seems irrelevant) and the presented move() method.
I find nothing necessitates the following however I will add the parameters' values I chose for the both planets:
planet1 = new Planet(30, 1, new Vector2(300, 300));
planet2 = new Planet(70, 332000, new Vector2(400, 400));
I am also aware LibGDX won't have the x, y coordinates of my circle in the middle but rather the bottom left. Therefore I have modified that in the constructor:
this.pos = pos;
this.pos.x -= r;
this.pos.y -= r;
I have been messing around and debugging the code and realised it was a very minor mistake, a classic mistake to assume that the math library's cos() and sin() functions use degrees. They don't. They use radians and that was the whole problem all along.
Instead of:
this.force.x = F * MathUtils.cos(alpha);
this.force.y = F * MathUtils.sin(alpha);
One must do:
this.force.x = F * MathUtils.cosDeg(alpha);
this.force.y = F * MathUtils.sinDeg(alpha);
I will make sure to edit the question to emphasize this problem and solution for future viewers of it.

How to measure distance using ARCore?

Is it possible to calculate distance between two HitResult `s ?
Or how we can calculate real distance (e.g. meters) using ARCore?
In Java ARCore world units are meters (I just realized we might not document this... aaaand looks like nope. Oops, bug filed). By subtracting the translation component of two Poses you can get the distance between them. Your code would look something like this:
On first hit as hitResult:
startAnchor = session.addAnchor(hitResult.getHitPose());
On second hit as hitResult:
Pose startPose = startAnchor.getPose();
Pose endPose = hitResult.getHitPose();
// Clean up the anchor
session.removeAnchors(Collections.singleton(startAnchor));
startAnchor = null;
// Compute the difference vector between the two hit locations.
float dx = startPose.tx() - endPose.tx();
float dy = startPose.ty() - endPose.ty();
float dz = startPose.tz() - endPose.tz();
// Compute the straight-line distance.
float distanceMeters = (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
Assuming that these hit results don't happen on the same frame, creating an Anchor is important because the virtual world can be reshaped every time you call Session.update(). By holding that location with an anchor instead of just a Pose, its Pose will update to track the physical feature across those reshapings.
You can extract the two HitResult poses using getHitPose() and then compare their translation component (getTranslation()).
The translation is defined as
...the position vector from the destination (usually
world) coordinate frame to the local coordinate frame, expressed in
destination (world) coordinates.
As for the physical unit of this I could not find any remark. With a calibrated camera this should be mathematically possible but I don't know if they actually provide an API for this
The answer is: Yes, you definitely can calculate distance between two HitResult's. The working units of ARCore, as well as ARKit, are meters. Sometimes, it's more useful to use centimetres. Here are a few ways how you do it with Java and great old Pythagorean theorem.
import com.google.ar.core.HitResult
MotionEvent tap = queuedSingleTaps.poll();
if (tap != null && camera.getTrackingState() == TrackingState.TRACKING) {
for (HitResult hit : frame.hitTest(tap)) {
// some logic...
}
}
// Here's the principle how you can calculate the distance
// between two anchors in 3D space using Java:
private double getDistanceMeters(Pose pose0, Pose pose1) {
float distanceX = pose0.tx() - pose1.tx();
float distanceY = pose0.ty() - pose1.ty();
float distanceZ = pose0.tz() - pose1.tz();
return Math.sqrt(distanceX * distanceX +
distanceY * distanceY +
distanceZ * distanceZ);
}
// Convert Meters into Centimetres
double distanceCm = ((int)(getDistanceMeters(pose0, pose1) * 1000))/10.0f;
// pose0 is the location of first Anchor
// pose1 is the location of second Anchor
Alternatively, you can use the following math:
Pose pose0 = firstAnchor.getPose() // first pose
Pose pose1 = secondAnchor.getPose() // second pose
double distanceM = Math.sqrt(Math.pow((pose0.tx() - pose1.tx()), 2) +
Math.pow((pose0.ty() - pose1.ty()), 2) +
Math.pow((pose0.tz() - pose1.tz()), 2));
double distanceCm = ((int)(distanceM * 1000))/10.0f;

Moving an object in a periodical circular path around a point

I'm working on a game for a game jam right now, and the problem is related to the flight path of a certain game enemy. I'm trying to have several of them fly in formation, and the idea was to have them fly in a wide radius circle around the center of the screen so they essentially box in the player. To do this, I tried to use the following formula...
public Pair<Double> move(Pair<Double> currPos, Pair<Double> playerPos) {
Pair<Double> newPos = new Pair<>(currPos.x, currPos.y);
// The radius used as the distance from the center.
double r = (Framework.CANVAS_WIDTH / 2) - Player.SHIP_SIZE;
// X,Y coords for center of the screen.
double cX = (Framework.CANVAS_WIDTH / 2);
double cY = (Framework.CANVAS_HEIGHT / 2);
// Trigonometric equation for transforming the object in a circle.
newPos.x = cX + (r * Math.cos(Framework.getHypotenuse(currPos, new Pair<Double>(cX, cY)) + (Math.PI / 90)));
newPos.y = cY + (r * Math.sin(Framework.getHypotenuse(currPos, new Pair<Double>(cX, cY)) + (Math.PI / 90)));
return newPos;
}
I can't figure out why the equation doesn't seem to work. When I test the movement pattern, there seem to be two enemies on screen rotating around the center, even though I only spawned one. However, they're blinking really fast, which makes it seem like maybe the ship is jumping back and forth really fast. This is supported by the fact that when I took a screenshot, there was only one ship. Is there something wrong with my trigonometry that would cause this, or does the problem lie elsewhere?
The following pseudocode gives the standard way to make an object move in a circular path:
double r = (...); // Radius of circle
double cX = (...); // x-coordinate of center of rotation
double cY = (...); // y-coordinate of center of rotation
double omega = (...); // Angular velocity, like 1
double t = (...); // Time step, like 0.00, 0.01, 0.02, 0.03, etc.
newPos.x = cX + r * Math.cos(t * omega);
newPos.y = cY + r * Math.sin(t * omega);

Java: Rotate a Point around an other using Google Maps Coordinates

From Google Earth I got a Box with coordinates for a picture, like following:
<LatLonBox>
<north>53.10685</north>
<south>53.10637222222223</south>
<east>8.853144444444444</east>
<west>8.851858333333333</west>
<rotation>-26.3448</rotation>
</LatLonBox>
Now I want to test weather a point intersect with this LatLonBox.
My base idea to check, whether a point intersect with the LatLonBox was, to rotate the point back by the given angle, and then to test whether the point intersect with a regular (not rotated) rectangle.
I tried to calculate the rotation manually:
public static MyGeoPoint rotatePoint(MyGeoPoint point, MyGeoPoint origion, double degree)
{
double x = origion.getLatitude() + (Math.cos(Math.toRadians(degree)) * (point.getLatitude() - origion.getLatitude()) - Math.sin(Math.toRadians(degree)) * (point.getLongitude() - origion.getLongitude()));
double y = origion.getLongitude() + (Math.sin(Math.toRadians(degree)) * (point.getLatitude() - origion.getLatitude()) + Math.cos(Math.toRadians(degree)) * (point.getLongitude() - origion.getLongitude()));
return new MyGeoPoint(x, y);
}
public boolean intersect(MyGeoPoint geoPoint)
{
geoPoint = MyGeoPoint.rotatePoint(geoPoint, this.getCenter(), - this.getRotation());
return (geoPoint.getLatitude() < getTopLeftLatitude()
&& geoPoint.getLatitude() > getBottomRightLatitude()
&& geoPoint.getLongitude() > getTopLeftLongitude()
&& geoPoint.getLongitude() < getBottomRightLongitude());
}
And it seems that the results are wrong.
LatLonBox box = new LatLonBox(53.10685, 8.851858333333333, 53.10637222222223, 8.853144444444444, -26.3448);
MyGeoPoint point1 = new MyGeoPoint(53.106872, 8.852311);
MyGeoPoint point2 = new MyGeoPoint(53.10670378322918, 8.852967186822669);
MyGeoPoint point3 = new MyGeoPoint(53.10652664993972, 8.851994565566875);
MyGeoPoint point4 = new MyGeoPoint(53.10631650700605, 8.85270995172055);
System.out.println(box.intersect(point1));
System.out.println(box.intersect(point2));
System.out.println(box.intersect(point3));
System.out.println(box.intersect(point4));
The result is true, false, false, true. But it should be 4x true.
Probably I´, making some kind of error in reasoning.
Maybe because the latitude values are getting bigger upwards. But I don´t knwo how to change the formular.
I need some help ...
EDIT:
I think my basic idea and formular is right. Also I found similar solutions eg. link and couldn´t find any difference.
So I think the only possible error source is, that the axis are not proportional. So the problem is how to take account of this.
I hope someone has got an idea.
The problem was indeed that the axis were not proportional.
The following method takes care of it.
public static MyGeoPoint rotatePoint(MyGeoPoint point, MyGeoPoint origion, double degree)
{
double x = origion.longitude + (Math.cos(Math.toRadians(degree)) * (point.longitude - origion.longitude) - Math.sin(Math.toRadians(degree)) * (point.latitude - origion.latitude) / Math.abs(Math.cos(Math.toRadians(origion.latitude)));
double y = origion.latitude + (Math.sin(Math.toRadians(degree)) * (point.longitude - origion.longitude) * Math.abs(Math.cos(Math.toRadians(origion.latitude))) + Math.cos(Math.toRadians(degree)) * (point.latitude - origion.latitude));
return new MyGeoPoint(x, y);
}
if I understand correctly you want to check if these four points are in rotated rectangle.
I would recommend checking not by corner points because your rectangle is rotated but:
if you have rotated rectangle ABCD then calculate lines |AB|, |BC|,|CD| and |DA|. If you have two points then use y=ax+b (you will calculate a,b by by giving [x,y] of both coordinates that gives you two easy equatations).
Finally function intersect will check
if point <= line |CD|
AND point >= line |AB|
AND point <= line |BC|
AND point >= |DA|
then it is inside rect.
This can be done when your point P[x,y] you put in ax+y+b (a>0 or -ax-y-b). If it is zero it is lying on the line, if it is < than it is under line or "on the left side". Hope I helped..
BTW why are you using -degree value, which you multiply by -1 , is it necessary?
The problem appears to be that the data structure LatLonBox doesn't make any sense as a description for the boundary of a picture. A box in lat-lon coordinates is not a geometric rectangle. (Think about a box near or including the north pole.) You need to re-think your application to deal in a lat/lon coordinate for the center of the picture and then deal with the rotation as an angle with respect to lines of latitude (parallel to the equator). (Even then, a picture with center on the north or south pole will be a degenerate case that must be handled separately.) So a box should properly be something like:
<geobox>
<center_lat>41</center_lat>
<center_lon>-74</center_lon>
<rotation_degrees_ccw>-23</rotation_degrees_ccw>
<width>1000</width> <!-- in pixels or meters, but not in degrees! -->
<height>600</height> <!-- same as above -->
</geobox>
Having said all that, suppose you have a true geometric box centered at (x0,y0), width w, height h, rotated angle T about its center. Then you can test a point P(x,y) for membership in the box with the following. You need the transformation that takes the box to the origin and aligns it with the axes. This is Translate(-x0,-y0) then Rotate(-T). This transformation as a matrix is
[cos(-T) -sin(-T) 0][1 0 -x0] [ cos(T) sin(T) -x0*cos(T)-y0*sin(T)]
[sin(-T) cos(-T) 0][0 1 -y0] = [-sin(T) cos(T) x0*sin(T)-y0*cos(T)]
[0 0 1][0 0 1] [ 0 0 1 ]
You want to apply this transformation to the point to be tested and then see if it lies in the desired box:
// Transform the point to be tested.
ct = cos(T);
st = sin(T);
xp = ct * x + st * y - x0 * ct - y0 * st;
yp = -st * x + ct * y + x0 * st - y0 * ct;
// Test for membership in the box.
boolean inside = xp >= -w/2 && xp <= w/2 && yp >= -h/2 && yp <= h/2;
It's late and I haven't checked this arithmetic, but it's close. Say if it doesn't work.

Getting distance of a point in a 2d triangle without calculating perpendicular vectors?

Alright, so I'm trying to get the distance of a point in a 2d triangle without calculating perpendicular vectors.
float qd = Vector2f.dot(new Vector2f(pos.x, pos.z),
new Vector2f(normal.pos.x, normal.pos.z)) -
Vector2f.dot(new Vector2f(q.center.x, q.center.z),
new Vector2f(normal.pos.x, normal.pos.z));
That's the code I'm using. (Note: it's converting 3f vectors to 2d ones, but you don't have to worry about that). I need the result of the calculation to be between 0 and 1 I.E. 0.5 or something.
If I'm still not explaining right maybe this will help?
My question is: How do I get the distance of a point in a 2d triangle without calculating perpendicular vector's distance? I.E. if the triangle is facing up (y = -1) without any tilt
I would need the distance in the triangle without any X.
Edit1: About what you're saying, Banthar, This is what I got out of it, and it doesn't work, but it seems like it's close to working.
float d = (float) Math.sqrt( 0 /*cause the two x's should be the same */ + Math.pow(pos.z - q.max.z, 2));
float h = (float) Math.sqrt( 0 /*cause the two x's should be the same */ + Math.pow(q.min.z - q.max.z, 2));
float myDist = d/h;
Let's say your triangle is ABC and the point is P.
The number you are looking for is the distance from P to AB divided by the distance from C to AB.
This is the same as the ratio of the corresponding areas. So you can compute the two areas:
Area(ABP) / Area(ABC)
The best way to compute the triangle area depends on what information you have about your triangle.
If you have the vertices only, then you can use:
Area(ABP) / Area(ABC) = ( Ax*By - Ax*Py + Ay*Px - Ay*Bx + Bx*Py - By*Px ) /
( Ax*By - Ax*Cy + Ay*Cx - Ay*Bx + Bx*Cy - By*Cx )

Categories

Resources