Get next point toward other point - java

I can't understand the http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm enough to write it in Java (I'm in 8th grade). From a starting point, I need to get a point toward a destination point. I have found several forum posts but no examples in Java.
I tried this (inside my Vector2 class):
public Vector2 getNextPointTowardOther(Vector2 dest, int speed) {
if (dest == null)
return this;
double deltaX = dest.getX() - this.x;
double deltaY = dest.getY() - this.y;
double direction = Math.atan(deltaY / deltaX);
double x = this.x + (speed * Math.cos(direction));
double y = this.y + (speed * Math.sin(direction));
return new Vector2(x, y);
}
But it never returns a negative x or y coordinate, and it just doesn't seem to be altogether accurate.

In order to move towards a certain destination point by a certain amount, you have to compute the direction from the current point towards the target point, and multiply this direction with the speed that you want to use, before adding it to the original point:
public Vector2 getNextPointTowardOther(Vector2 dest, int speed) {
if (dest == null)
return this;
double deltaX = dest.getX() - this.x;
double deltaY = dest.getY() - this.y;
// Compute the distance
double distance = Math.sqrt(deltaX*deltaX+deltaY*deltaY);
// Compute the (normalized) direction
double dirX = deltaX / distance;
double dirY = deltaY / distance;
// (The vector (dirX, dirY) now has length 1.0)
double x = this.x + speed * dirX;
double y = this.y + speed * dirY;
return new Vector2(x, y);
}

Related

How to find the other endpoint given an endpoint and the midpoint

I am working on a desktop app that will help students with algebra. I have a class called Vector2 that just stores two variables, x and y. I am working on a method that will return the endpoint of a line given an endpoint and a midpoint. Just to show how I have been doing this here is a method
public static Vector2 midpoint(double xa, double ya, double xb, double yb){
Vector2 v = new Vector2(0, 0);
v.x = (xa + xb) / 2;
v.y = (ya + yb) / 2;
return v;
}
Given this how would I make a method that will give me the other endpoint?
Example: if the given endpoint is (-3, -5) and the given midpoint is (-6, -2) then the output should be (-9, 1)
EDIT FOR NEW PPL: I have the answer, it is pretty simple. Here is the final method
public static Vector2 otherEndpoint(double endPointX, double EndPointY, double midPointX, double midPointY){
Vector2 v = new Vector2(0,0);
v.x = (endPointX + midPointX) / 2;
v.y = (EndPointY + midPointY) / 2;
v.multiply(2);
return v;
}
v.multiply() is a method that I made that will multiply each point by whatever number you put in
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static Point getMidpoint(Point one, Point two) {
int x = (one.x + two.x) / 2;
int y = (one.y + two.y) / 2;
return new Point(x, y);
}
public static Point getEndpoint(Point one, Point mid) {
int x = (2 * mid.x) - one.x;
int y = (2 * mid.y) - one.y;
return new Point(x, y);
}
public static Vector2 fromEndAndMidpoint(double xa, double ya, double xmid, double ymid) {
Vector2 v = new Vector2();
v.x = 2 * xmid - xa;
v.y = 2 * ymid - ya;
return v;
}
Here is the method that shows how to compute it.
Note that this works because you know that one point is in the middle. So the desired endpoint is just one step away from the middle or two steps away from the other end.
public static Vector2 midpoint(double xe, double ye, double xm,
double ym) {
// calculate the step to go from the end point to the middle
// for both x and y.
double xstep = xm - xe;
double ystep = ym - ye;
// then just add the step to the middle to get the end point.
return new Vector2(xm + xstep, ym + ystep);
}
Note that the above will not work to find any point. For that you must simply find the equation of the line y = mx + b by computing the slope, m, and y-intercept, b.

Java 2D Array Bicubic Interpolation

I have recently been playing around with Bicubic Interpolation, as I am wanting to generate the earth, based on real heightmaps inside Minecraft. The reason I am using the interpolation, is because I would like to make the world have more detail. After a lot of research, and a lot of trial and error, I decided to come ask here. :)
Because of limited memory, I can't scale the image on startup, and keep that loaded, I have to do the interpolation on the fly.
I seem to have gotten Cubic Interpolation to work, as seen here:
Visualisation of the interpolation
However, I can not get Bicubic Interpolation to work. For testing purposes, I am using a small image, and scaling it by 4. This is what the code does: Input -> Output
This is my current code:
public static double cubicInterpolate(double[] points, double x, double scale)
{
x /= scale;
double inBetweenPoint = x;
int xInHeightmap = (int) x;
inBetweenPoint -= xInHeightmap;
double beforePoint1 = safe(points, xInHeightmap - 1);
double point1 = safe(points, xInHeightmap);
double point2 = safe(points, xInHeightmap + 1);
double afterPoint2 = safe(points, xInHeightmap + 2);
double p = (afterPoint2 - point2) - (beforePoint1 - point1);
double q = (beforePoint1 - point1) - p;
double r = point2 - beforePoint1;
double s = point1;
return (p * Math.pow(inBetweenPoint, 3)) + (q * Math.pow(inBetweenPoint, 2)) + (r * inBetweenPoint) + s;
}
public static double bicubicInterpolate(double[][] points, double x, double y, double scale)
{
x /= scale;
double inBetweenPoint = x;
int xInHeightmap = (int) x;
inBetweenPoint -= xInHeightmap;
double beforePoint1 = cubicInterpolate(safe(points, xInHeightmap - 1), y, scale);
double point1 = cubicInterpolate(safe(points, xInHeightmap), y, scale);
double point2 = cubicInterpolate(safe(points, xInHeightmap + 1), y, scale);
double afterPoint2 = cubicInterpolate(safe(points, xInHeightmap + 2), y, scale);
return cubicInterpolate(new double[]{beforePoint1, point1, point2, afterPoint2}, inBetweenPoint + 1, scale);
}
public static double[] safe(double[][] p, int i)
{
return p[Math.max(0, Math.min(i, p.length - 1))];
}
public static double safe(double[] p, int i)
{
return p[Math.max(0, Math.min(i, p.length - 1))];
}
Thank you for your help :)
To my understanding, your implementaion treats the given x and y coordinates in a totally different way, which does not lead to the desired result. You should basically do the following.
First, you need to identify the four points (coordinate pairs) in the grid which will form the basis of the interpolation, as well as the distances in both directions from the grid to to the interpolation. This can be done as follows.
int xfloor = (int)x;
int yfloor = (int)y;
int xdelta = x - (double)xfloor;
int ydelta = y - (double)yfloor;
The desired coordinate pairs are then (depending on the orientation of the axes)
P1 = (xfloor, yfloor ) // left upper corner
P2 = (xfloor, yfloor + 1) // left lower corner
P3 = (xfloor + 1 ,yfloor + 1) // right lower corner
P4 = (xfloor + 1, yfloor ) // left upper corner
and finally you wouöd first interpolate along parallel axes and then in the middle, which can be done as follows using intermediate values.
val1 = cubic(value(P1), value(P2), deltay) // interpolate cubically on the left edge
val2 = cubic(value(P4), value(P3), deltay) // interpolate cubically on the right edge
val = cubic (val1, val2, deltax) // interpolate cubically between the intermediates
Interpolation methods are also discussed here.
In your bicubic-interpolation method you write:
//double inBetweenPoint = x;
//int xInHeightmap = (int) x;
//inBetweenPoint -= xInHeightmap;
return cubicInterpolate(new double[]{beforePoint1, point1, point2, afterPoint2}, inBetweenPoint, scale);
As you can easily see, inBetweenPoint will be in the interval [0, 1) at the call to cubicInterpolate. This means that interpolation will be between beforePoint1 and point1. not, as wanted, between point1 and point2.
The simple fix is writing
return cubicInterpolate(new double[]{beforePoint1, point1, point2, afterPoint2}, inBetweenPoint + 1, scale);

Move Object in direction of mouse

I have a bullet class and an algorithm that will move my bullet to where I pressed, but how would I have the bullet continuing on past the mouse_x and mouse_y when it was clicked?
In My Update method:
float xSpeed = (MoveToX - x) / 9;
float ySpeed = (MoveToY - y) / 9;
this.x += xSpeed;
this.y += ySpeed;
And this is when I first create the bullet:
Bullet(int Mx, int My){
c = Color.red;
MoveToX = Mx;
MoveToY = My;
MoveToX += Board.cam.camX;
MoveToY += Board.cam.camY;
Mx is the mouses x when it was clicked. Same with the y.
Edit:
This is my final product: everything works as it should
Bullet(int Mx, int My){
c = Color.red;
MoveToX = Mx + Board.cam.camX;
MoveToY = My + Board.cam.camY;
int speed = 5;
float distance = (float) Math.sqrt(Math.pow(MoveToX - x, 2) + Math.pow(MoveToY - y, 2));
amountToMoveX = (((MoveToX - x) / distance) * speed);
amountToMoveY = (((MoveToY - y) / distance) * speed);
}
public void update(){
x += amountToMoveX;
y += amountToMoveY;
}
The instance variables of your bullet shouldn't be moveTo_, but velocity and direction.
Calculate the direction (i.e. the angle) in the constructor, from the bullet position and the target position. velocity may also be a static constant, depending on your use case.
If it is an option, I would strongly recommend to use a physics- or game-engine. Those kind of problems were already solved a hundred times in those engines. They relieve you from those basic tasks and help you concentrate on your actual problem.

Making minecraft player look at point

im trying to make the player look at at specific point. What i have looks at the point but only if its in its field of vision. and i would like for it to look up and down as well
public static void lookAt(double x, double y, double z) {
double l;
double w;
double c;
l = x - playerX;
w = z - playerZ;
c = Math.sqrt(l * l + w + w);
double alpha1 = -Math.asin(l / c) / Math.PI * 180;
double alpha2 = Math.acos(w / c) / Math.PI * 180;
if (alpha2 > 180) {
playerYaw = 180 - (float) alpha1;
} else {
playerYaw = (float) alpha1;
}
}
i looked for a pitch algorithm but none seem to work.
Late answer but oh well, you can calculate the pitch and yaw with simple trigonometry if you can get a unit vector that represents the direction from your position to the point you want to look at.
To start you need to subtract the your position by the point and normalize the result, that will give us the directional vector(unit vector) that we need.
Now we can calculate the angles, the arc sine of Y will give us the the pitch angle, and the arc tan of X and Z will give us the yaw angle.
To understand why: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
and now you should have the pitch and yaw, don't forget to convert them to degrees!
here's some code:
public static void LookAt(double px, double py, double pz , EntityPlayer me)
{
double dirx = me.getPosition(0f).X - px;
double diry = me.getPosition(0f).Y - py;
double dirz = me.getPosition(0f).Z - pz;
double len = Math.sqrt(dirx*dirx + diry*diry + dirz*dirz);
dirx /= len
diry /= len;
dirz /= len;
double pitch = Math.asin(dir.y);
double yaw = Math.atan2(dir.z, dir.x);
//to degree
pitch = pitch * 180.0 / Math.PI;
yaw = yaw * 180.0 / Math.PI;
yaw += 90f;
me.rotationPitch = (float)pitch;
me.rotationYaw = (float)yaw;
}

Need a function to limit a line (known by its coordinates) in its length

I need a function which takes a line (known by its coordinates)
and return a line with same angle, but limited to certain length.
My code gives correct values only when the line is turned 'right'
(proven only empirically, sorry).
Am I missing something?
public static double getAngleOfLine(int x1, int y1, int x2, int y2) {
double opposite = y2 - y1;
double adjacent = x2 - x1;
if (adjacent == Double.NaN) {
return 0;
}
return Math.atan(opposite / adjacent);
}
// returns newly calculated destX and destY values as int array
public static int[] getLengthLimitedLine(int startX, int startY,
int destX, int destY, int lengthLimit) {
double angle = getAngleOfLine(startX, startY, destX, destY);
return new int[]{
(int) (Math.cos(angle) * lengthLimit) + startX,
(int) (Math.sin(angle) * lengthLimit) + startY
};
}
BTW: I know that returning arrays in Java is stupid,
but it's just for the example.
It would be easier to just treat it as a vector. Normalize it by dividing my its magnitude then multiply by a factor of the desired length.
In your example, however, try Math.atan2.
In Python because I don't have a Java compiler handy:
import math
def getLengthLimitedLine(x1, y1, x2, y2, lengthLimit):
length = math.sqrt((x2-x1)**2 + (y2-y1)**2)
if length > lengthLimit:
shrink_factor = lengthLimit / length
x2 = x1 + (x2-x1) * shrink_factor
y2 = y1 + (y2-y1) * shrink_factor
return x2, y2
print getLengthLimitedLine(10, 20, 25, -5, 12)
# Prints (16.17, 9.71) which looks right to me 8-)
It's an easy problem if you understand something about vectors.
Given two points (x1, y1) and (x2, y2), you can calculate the vector from point 1 to 2:
v12 = (x2-x1)i + (y2-y2)j
where i and j are unit vectors in the x and y directions.
You can calculate the magnitude of v by taking the square root of the sum of squares of the components:
v = sqrt((x2-x2)^2 + (y2-y1)^2)
The unit vector from point 1 to point 2 equals v12 divided by its magnitude.
Given that, you can calculate the point along the unit vector that's the desired distance away by multiply the unit vector times the length and adding that to point 1.
Encapsulate Line in a class, add a unit method and a scale method.
public class Line {
private float x;
private float y;
public Line(float x1, float x2, float y1, float y2) {
this(x2 - x1, y2 - y1);
}
public Line(float x, float y) {
this.x = x;
this.y = y;
}
public float getLength() {
return (float) Math.sqrt((x * x) + (y * y));
}
public Line unit() {
return scale(1 / getLength());
}
public Line scale(float scale) {
return new Line(x * scale, y * scale);
}
}
Now you can get a line of arbitrary length l by calling
Line result = new Line(x1, x2, y1, y2).unit().scale(l);
No need to use trig, which can have some nasty edge cases. Just use similar triangles:
public static int[] getLengthLimitedLine(int startX, int startY,
int destX, int destY, int lengthLimit)
{
int deltaX = destX - startX;
int deltaY = destY - startY;
int lengthSquared = deltaX * deltaX + deltaY * deltaY;
// already short enough
if(lengthSquared <= lengthLimit * lengthLimit)
return new int[]{destX, destY};
double length = Math.sqrt(lengthSquared);
double newDeltaX = deltaX * lengthLimit / length;
double newDeltaY = deltaY * lengthLimit / length;
return new int[]{(int)(startX + newDeltaX), (int)(startY + newDeltaY)};
}
Just use the Pythagorean theorem, like so:
public static int[] getLengthLimitedLine(int start[], int dest[], int lengthLimit) {
int xlen = dest[0] - start[0]
int ylen = dest[1] - start[1]
double length = Math.sqrt(xlen * xlen + ylen * ylen)
if (length > lengthLimit) {
return new int[] {start[0], start[1],
start[0] + xlen / lengthLimit,
start[1] + ylen / lengthLimit}
} else {
return new int[] {start[0], start[1], dest[0], dest[1];}
}
}

Categories