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.
Related
I have a method that gets the area of a triangle, however it is returning 0.0.
public double getArea() {
//Find the length of sides
double side1 = p1.findLength(p2);
double side2 = p2.findLength(p3);
double side3 = p3.findLength(p1);
//Get area
double s = (side1 + side2 + side3) / 2;
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
My Point class with findLength(). This function works as intended in my testing:
public double findLength(Point another) {
return Math.sqrt(((another.getX() - this.getX()) * (another.getX() - this.getX()) )+
((another.getY() - this.getY()) * (another.getY() - this.getY())));
}
I can't seem to figure out why it isn't working.
Entire Point class:
/**
* Created by wilson on 9/8/2014.
*/
import java.math.*;
public class Point {
private double x, y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double findLength(Point another) {
return Math.sqrt(((another.getX() - this.getX()) * (another.getX() - this.getX()) )+
((another.getY() - this.getY()) * (another.getY() - this.getY())));
}
}
My Test Program:
Point p1 = new Point(0,0);
Point p2 = new Point(3,3);
Point p3 = new Point(-3,-3);
Triangle2D t1 = new Triangle2D(p1, p2, p3);
System.out.println("Area of triangle: " + t1.getArea());
The "triangle" you tested:
Point p1 = new Point(0,0);
Point p2 = new Point(3,3);
Point p3 = new Point(-3,-3);
actually consists of three points all on the same line (the line x = y). Therefore, 0 is the correct answer. As far as I can tell, the code is correct.
Side note: I recommend using Math.hypot, which computes sqrt(x2 + y2) in the findLength function. Besides making findLength easier to read, it has the advantage that it won't overflow if x or y is so large that x2 or y2 won't fit in a floating-point number. (Not that it's likely you'll run into that problem, but why not do things right?)
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.
I'm Suppoused to write a class with a constructor for a Point and a Line and in the Line class I'm suppoused to write a method that finds if two lines intersect or not. This is my Point class:
public class Point {
static double x;
static double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
This is my Line Class
public class Line {
public Line(Point x, Point y) {
}
// create two points for a line
static Point x1y1;
static Point x2y2;
// create another two points for another line
static Point x3y3;
static Point x4y4;
public static void main(String[] args) {
// create lines
Line line1 = new Line(x1y1, x2y2);
Line line2 = new Line(x3y3, x4y4);
//initialize points
x1y1 = new Point(1.0, 1.0);
x2y2 = new Point(3.0, 3.0);
x3y3 = new Point(1.0, 2.0);
x4y4 = new Point(4.0, 2.0);
//call method to find if lines intersect
findIntersection(line1, line2);
System.out.println(x1y1.x);
}
public static void findIntersection(Line line1, Line line2) {
double denominator = (x1y1.x - x2y2.x) * (x3y3.y - x4y4.y)
- (x1y1.y - x2y2.y) * (x3y3.x - x4y4.x);
double px = 0;
double py = 0;
if (denominator == 0) {
System.out.println("Lines are parallel, they do not intersect");
} else {
px = ((x1y1.x * x2y2.y - x1y1.y * x2y2.x) * (x3y3.x - x4y4.x) - (x1y1.x - x2y2.x)
* (x3y3.x * x4y4.y - x3y3.y * x4y4.x))
/ denominator;
py = ((x1y1.x * x2y2.y - x1y1.y * x2y2.x) * (x3y3.y - x4y4.y) - (x1y1.y - x2y2.y)
* (x3y3.x * x4y4.y - x3y3.y * x4y4.x))
/ denominator;
System.out.println(px + "," + py);
}
}
}
The problem is I initialize all the points so that the lines should intersect, but when I try to print out the values of the points, the values of the x-es and y-s of the firss 3 points are equal to the 4th one although I'm initializing them with different values and thus the method calcutes that the lines do not intersect. Why are the values of the first three y and x equal to the 4th?
It's because x and y of Point class are static. It means, every instance of Point class will use the same values. Remove static to fix it.
public class Point {
double x;
double y;
You should improve the class design too anyway: Two classes (Point, Lines) another with main method.
The same for Line too. Or you will end up with the same Points for every line. (You avoited this using 4 variables i think.)
Something like this
public class Point {
double x;
double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
public class Line {
Point a;
Point b;
public Line(Point a, Point b) {
this.a = a;
this.b = b;
}
public Point itIntersect(Line line) {
// here change the logic
Point point = null;
double denominator = (x1y1.x - x2y2.x) * (x3y3.y - x4y4.y)
- (x1y1.y - x2y2.y) * (x3y3.x - x4y4.x);
double px = 0;
double py = 0;
if (denominator != 0) {
px = ((x1y1.x * x2y2.y - x1y1.y * x2y2.x) * (x3y3.x - x4y4.x) - (x1y1.x - x2y2.x)
* (x3y3.x * x4y4.y - x3y3.y * x4y4.x))
/ denominator;
py = ((x1y1.x * x2y2.y - x1y1.y * x2y2.x) * (x3y3.y - x4y4.y) - (x1y1.y - x2y2.y)
* (x3y3.x * x4y4.y - x3y3.y * x4y4.x))
/ denominator;
// System.out.println(px + "," + py);
point = new Point(px, py);
}
return point;
}
}
P.S I didn't changed the logic of intersect because it's too long, but you could do something like this to improve the design.
Then you need to do Point point = line.itIntersect(anotherLine);
If it's null it don't intersect, else it will return the point.
P.S Make x and y private, i didn't because it was an example.
I am calculating Geometric median of some (x,y) points in java. To calculate Geometric median, first i am calculating centroid of all the points, then this centroid is used to calculate Geometric median. My code works fine, but sometimes it goes to an infinite loop (i think.). The problem is with my while condition. This while condition should be change according to input points, but i don't know how. Below I am putting the complete code.
import java.util.ArrayList;
public class GeometricMedian {
private static ArrayList<Point> points = new ArrayList<Point>();
private class Point {
private double x;
private double y;
Point(double a, double b) {
x = a;
y = b;
}
}
public static void main(String[] args) {
GeometricMedian gm = new GeometricMedian();
gm.addPoints();
Point centroid = gm.getCentroid();
Point geoMedian = gm.getGeoMedian(centroid);
System.out.println("GeometricMedian= {" + (float) geoMedian.x + ", "
+ (float) geoMedian.y + "}");
}
public void addPoints() {
points.add(new Point(0, 1));
points.add(new Point(2, 5));
points.add(new Point(3, 1));
points.add(new Point(4, 0));
}
public Point getCentroid() {
double cx = 0.0D;
double cy = 0.0D;
for (int i = 0; i < points.size(); i++) {
Point pt = points.get(i);
cx += pt.x;
cy += pt.y;
}
return new Point(cx / points.size(), cy / points.size());
}
public Point getGeoMedian(Point start) {
double cx = 0;
double cy = 0;
double centroidx = start.x;
double centroidy = start.y;
do {
double totalWeight = 0;
for (int i = 0; i < points.size(); i++) {
Point pt = points.get(i);
double weight = 1 / distance(pt.x, pt.y, centroidx, centroidy);
cx += pt.x * weight;
cy += pt.y * weight;
totalWeight += weight;
}
cx /= totalWeight;
cy /= totalWeight;
} while (Math.abs(cx - centroidx) > 0.5
|| Math.abs(cy - centroidy) > 0.5);// Probably this condition
// needs to change
return new Point(cx, cy);
}
private static double distance(double x1, double y1, double x2, double y2) {
x1 -= x2;
y1 -= y2;
return Math.sqrt(x1 * x1 + y1 * y1);
}
}
Please help me to fix the bug, also if there exitis any better way to calculate Geometric median of some 2D points, write here. Thank you.
I don't see why you need two loops. You only need the loop over all the points. What is the reason for the other one, in your view?
One way to solve this is to iterate certain number of times. This similar to K-Means method where it either converges to a specific threshold or stops after a predefined number of iterations.
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];}
}
}