I am trying to understand why I am having a difficult time calling two different points into a method in order to determine the distance between the two points.
This is the text provided on the website "Practice-It", where I am currently working through problems:
Add the following method to the Point class:
public double distance(Point other)
Returns the distance between the current Point object and the given other Point object. The distance between two points is equal to the square root of the sum of the squares of the differences of their x- and y-coordinates. In other words, the distance between two points (x1, y1) and (x2, y2) can be expressed as the square root of (x2 - x1)2 + (y2 - y1)2. Two points with the same (x, y) coordinates should return a distance of 0.0."
I have tried multiple ways to get the points into the method without naming individual coordinates. I believe that I am only getting the coordinates of the first point and am trying to understand where I am going wrong as I've had this problem before. I realize that the "int x1 = p1.x", etc. is redundant and I could just type "p1.x" in the return, but I am wanting to see all of the moving parts individually. Thanks for your consideration and help.
public double distance(Point other){
Point p1 = new Point();
int x1 = p1.x;
int y1 = p1.y;
Point p2 = new Point();
int x2 = p2.x;
int y2 = p2.y;
return Math.sqrt(Math.pow(x * x2, 2) + Math.pow(y * y2, 2));
}
This is my result from one of the situations tested:
test #1:(5, 2) to (8, 6)
expected output:
5.0
5.0
your output:
0.0
0.0
differences:
1,2c1,2
< 5.0
< 5.0
> 0.0
> 0.0
result: fail
Your comparison logic is off. Assuming that distance() is a method inside the Point class, then you should be comparing the x,y values of the incoming other point against the x,y value in the class:
public double distance(Point other) {
int x1 = other.x;
int y1 = other.y;
return Math.sqrt(Math.pow(this.x * x1, 2) + Math.pow(this.y * y1, 2));
}
Note that is would be more ideal to provide getters for the x and y fields in Point. Here is a more complete suggested refactor:
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
public double distance(Point other) {
int x1 = other.getX();
int y1 = other.getY();
return Math.sqrt(Math.pow(this.x * x1, 2) + Math.pow(this.y * y1, 2));
}
}
Related
I'm kind of new to Java, and trying to write a code that calculate the distance of two points 2 and 3, and scale of 10. Somehow, it does not work. Can you give me a hint, so I can fix the code?
import java.lang.Math;
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public float scale(int factor) {
new Point(x * factor, y * factor);
return factor;
}
public float distance(){
double distance = Math.sqrt(x * x + y * y);
return distance;
}
public void main(String[] args) {
float p = new Point(2,3).scale(10);
System.out.println(distance);
}
}
In scale you are creating a new point with the scaled values and doing nothing with it. You're leaving x and y of the point in question untouched.
You probably mean to multiply x and y by factor, rather than creating a new point.
Also you're printing a variable named distance, which does not exist (so this probably doesnt even compile), rather than calling the method named distance() and printing its returned value.
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public static Point scalePoint(Point p, int factor) { //scale a given point p by a given factor
Point scaledPoint = new Point(p.x * factor, p.y * factor); //by multipling the x and y value with the factor
return scaledPoint; //and return the new scaled point
}
public static double calculateDistance(Point p1, Point p2){ //to calculate the distance between two points
double distance = Math.sqrt(p1.x * p2.x + p1.y * p2.y); //send the two points as parameter to this method
return distance; //and return the distance between this two as a double value
}
public static void main(String[] args) {
Point p = new Point(2,3);
Point scaledPoint = scalePoint(p, 10);
double distance = calculateDistance(p, scaledPoint);
System.out.println(distance);
}
}
At the moment your distance method is calculating the distance of a point from the origin (i.e. point 0,0). It would make more sense if you made that explicit:
class Point {
private static final Point ORIGIN = new Point(0, 0);
private final int x;
private final int y;
public float distanceTo(Point other) {
float xDelta = other.x - this.x;
float yDelta = other.y - this.y;
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
}
public Point scale(float factor) {
return new Point(x * factor, y * factor);
}
}
Then finding the distance to the origin becomes point.distanceTo(Point.ORIGIN) which makes the intent clearer.
package Geometry;
public class TestGeometryPoint {
public static void main(String[] args) {
//Creates the object PointA and Assigns values
Point pA = new Point(); //PointA(0, 0)
pA.setX(2.0); //PointA(2.0, 0)
pA.setY(5.0); //PointA(2.0, 5.0)
//Creates the object PointB and Assigns values
Point pB = new Point(4.0, 6.1); //PointB(4.0, 6.1)
//Calculates the distance between PointA and PointB
double d = pA.distance(4.0, 6.1); //Distance from class to a set of coordinates
double dP = pA.distance(pB); //Distance from class to another point
double dPtP = Point.distance(pA, pB); //Distance from point to point
//Prints the result of the calculations
System.out.println("Distance between Point A & B: " + d);
System.out.println("Distance between Point A & B: " + dP);
System.out.println("Distance between Point A & B: " + dPtP);
}
}
This is my Test Class and my Point class below.
package Geometry;
public class Point {
//Initializes the coordinates for a point on a graph with the values of x and y
private static double x;
private static double y;
//Defualt Constructor
public Point() {
x = 0;
y = 0;
}
//Point Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//Returns the x value
public double getX() {
return x;
}
//Changes the x value
public void setX(double x) {
Point.x = x;
}
//Returns the y value
public double getY() {
return y;
}
//Changes the y value
public void setY(double y) {
Point.y = y;
}
//Calculates the distance between the class's point coordinates and another set of point coordinates
public double distance(double x0, double y0) {
double distance = (Math.sqrt(((x0 - x) * 2.0) + ((y0 - y) * 2.0)));
return distance;
}
//Calculates the distance between the class's point and another Point class's location
public double distance(Point p) {
double distance = (Math.sqrt(((p.getX() - x) * (p.getX() - x)) + ((p.getY() - y) * (p.getY() - y))));
return distance;
}
//Calculates the distance between a Point class's location and another Point class's location
public static double distance(Point p1, Point p2) {
double distance = (Math.sqrt((Math.pow((p2.getX() - p1.getX()), 2.0) + (Math.pow((p2.getY() - p1.getY()), 2.0)))));
return distance;
}
}
d, dP, dPtP: all return 0.0 when compiled and run, but I have no idea why as I have tried changing code and checking my math when calculating distance. I think I might just need a new set of eyes to take a look at it.
I believe since your x and y variables are static, they belong to the class Point as a whole. When you create a Point(2,5);
You set the static variable of the class Point to be 2 and 5 and then, you create another Point(4,6) You set the same static value of x and y to be 4,6.
Therefore, comparing the distance between the same two Point are 0.
The right code for the class Point would be like so
public class Point {
//Initializes the coordinates for a point on a graph with the values of x and y
private double x;
private double y;
//Defualt Constructor
public Point() {
x = 0;
y = 0;
}
//Point Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//Returns the x value
public double getX() {
return x;
}
//Changes the x value
public void setX(double x) {
this.x = x;
}
//Returns the y value
public double getY() {
return y;
}
//Changes the y value
public void setY(double y) {
this.y = y;
}
//Calculates the distance between the class's point coordinates and another set of point coordinates
public double distance(double x0, double y0) {
double distance = (Math.sqrt(((x0 - x) * 2.0) + ((y0 - y) * 2.0)));
return distance;
}
//Calculates the distance between the class's point and another Point class's location
public double distance(Point p) {
double distance = (Math.sqrt(((p.getX() - x) * (p.getX() - x)) + ((p.getY() - y) * (p.getY() - y))));
return distance;
}
//Calculates the distance between a Point class's location and another Point class's location
public static double distance(Point p1, Point p2) {
double distance = (Math.sqrt((Math.pow((p2.getX() - p1.getX()), 2.0) + (Math.pow((p2.getY() - p1.getY()), 2.0)))));
return distance;
Your problem is that you are confusing static and non-static fields.
By putting that little static on your field declarations you are saying: all instances of this class should be seeing the exact same variables.
So, when you create two points
p1 = new Point(5, 5);
p2 = new Point(10, 10);
the declaration of p2 "overrides" the 5-5 from p1 ... because, as said: all Points are using the same x and y.
Thus, solution: simply drop that keyword from the definition of x and y. Then each point has is very own x and y.
And, more importantly: understand that each and any character in your source code matters. This means: you better understand each and any concept that your source code is making use of!
regarding the following code, can I make it better for distance() method?
It feels like it's not completely OOP with this method.. how can I change code to be better OOD for this one ?
Thanks !!
public class Line extends Shape {
private Point lineP1;
private Point lineP2;
public Line(int x1, int x2, int y1, int y2, Color myColor) {
super(x1, x2, y1, y2, myColor);
lineP1 = new Point(this.getX1(),this.getY1());
lineP2 = new Point(this.getX2(),this.getY2());
}
#Override
public void draw(Graphics g) {
g.drawLine(this.getX1(), this.getY1(), this.getX2(), this.getY2());
g.setColor(Color.GREEN);
}
#Override
public boolean contains(Point p) {
if((this.distance(lineP1, p)+this.distance(lineP2, p)) == this.distance(lineP1, lineP2))
return true;
return false;
}
/**#return distance between two given points
* This method return the distance between two given points*/
private double distance(Point p1,Point p2 ){
return Math.sqrt(Math.pow((p1.getX()-p2.getX()), 2) + Math.pow((p1.getY()-p2.getY()), 2));
}
}//class Line
Your distance method seems to be ok (but it would be more performant, if you saved the differences in variables and used the * operator to multiply those values with themselfs instear of using Math.pow).
However, since floating point calculations tend to return inexact results, I don't recomend using the sum of the distances between the end node and the point to test as criterium.
But there's another good way determining, if a point is near a line or not: using the hesse normal form. It works like this:
Let P1 and P2 be vectors corresponing to the end points. * denotes the scalar multiplication and || the length of a vector:
D = (P2 - P1) / |P2 - P1|;
Let N be the vector D with coordinates swaped and the new x coordinate multiplied with -1 (i.e. a vector ortogonal to D).
Then the distance of a point H to the line can be determined like this
| N * H - N * P1 |
Also if H is between P1 and P2 can be checked like this (assuming without loss of generality D * P1 < D * P2):
D * P1 <= D * H <= D * P2
Using scalar products has the additional benefit, that calculating a scalar product only takes 2 multiplication and 1 addition in a 2D space.
This is how you could do this in java code
// components of normal vector
private double normalX;
private double normalY;
// components of direction vector
private double directionX;
private double directionY;
// the value of (N * P) for all points P on the line
private double normalScalarProduct;
// the range allowed for (D * P) for points on the line
private double minDirectionScalarProduct;
private double maxDirectionScalarProduct;
// error ranges; adjust as appropriate
private static final double directionAllowedError = 0.1;
private static final double normalAllowedError = 0.1;
public Line(int x1, int x2, int y1, int y2, Color myColor) {
...
double dx = x2 - x1;
double dy = y2 - y1;
double length = distance(dx, dy);
if (length == 0) {
// choose arbitrary direction, if length == 0
length = 1;
dx = 1;
}
// normalize direction
dx /= length;
dy /= length;
// set D and N values
this.directionX = dx;
this.directionY = dy;
this.normalX = -dy;
this.normalY = dx;
double prod1 = scalarProduct(directionX, directionY, x1, y1);
double prod2 = scalarProduct(directionX, directionY, x2, y2);
if (prod1 < prod2) {
minDirectionScalarProduct = prod1 - directionAllowedError;
maxDirectionScalarProduct = prod2 + directionAllowedError;
} else {
minDirectionScalarProduct = prod2 - directionAllowedError;
maxDirectionScalarProduct = prod1 + directionAllowedError;
}
normalScalarProduct = scalarProduct(x1, y1, normalX, normalY);
}
private static double scalarProduct(double x1, double y1, double x2, double y2) {
return x1*x2 + y1*y2;
}
public boolean contains(Point p) {
if (Math.abs(scalarProduct(p.getX(), p.getX(), normalX, normalY) - normalScalarProduct) <= normalAllowedError) {
// close enough to the line -> check, if between end points
double d = scalarProduct(p.getX(), p.getX(), directionX, directionY);
return minDirectionScalarProduct <= d && d <= maxDirectionScalarProduct;
}
return false;
}
private double distance(double dx, double dy) {
return Math.sqrt(dx*dx + dy*dy);
}
So I finished up a program that recursively draws lines which takes an argument "n" to define the depth of the recursion. I have 2 functions, one which draws the relatively left line and another which draws the relatively right one. I tested it ant it seems to work for the first 4 levels, but then either the lines become too small to accurately represent or there's something wrong with my code because the breaks between the lines seem to become arbitrary. Was hoping somebody could test my code and see if they could find what the problem is.
The following image is of depth 10.
EDIT: fixed a part of code, still need help though
public class Art
{
//draws the relatively left line
public static void drawLeftLine(double x0, double y0, double x1, double y1)
{
//define new x coordinate for line
//double x2 = (1/3.0)*(x1 - x0);
//color of line
StdDraw.setPenColor(StdDraw.BLUE);
//draw line by adding new x coord to original
StdDraw.line(x0, y0, x1, y1);
}
//draw relatively right line
public static void drawRightLine(double x0, double y0, double x1, double y1)
{
//define new x coord for line
//double x2 = (2/3.0)*(x1 - x0);
//color of line
StdDraw.setPenColor(StdDraw.BLUE);
//draw line by adding new x coord to original
StdDraw.line(x0, y0, x1, y1);
}
public static void cantor(int n, double x0, double y0, double x1, double y1)
{
if (n == 0)
return;
drawLeftLine(x0, y0, x1, y1);
drawRightLine(x0, y0, x1, y1);
y0 = y0 - 0.1;
y1 = y1 - 0.1;
cantor(n-1, x0, y0, x0 + ((x1 - x0))/3.0, y1); //left
cantor(n-1, (2.0/ 3) * (x1 - x0) + x0, y0, x1, y1); //right
}
public static void main(String[] args)
{
//change n into integer (depth)
int n = Integer.parseInt(args[0]);
//specify inital values for line
double x0 = 0;
double y0 = 0.9;
double x1 = 0.9;
double y1 = 0.9;
//recursive function cantor
cantor(n, x0, y0, x1, y1);
}
}
I think that the drawing looks incorrect because the of the fact that all of the nice double values are being approximated with discrete pixels causing unwanted overlap between the line segments (see EDIT at the bottom). Some comments about your code however :
1) You don't need the drawLeftLine and drawRightLine methods since currently they are drawing exactly the same thing. Since at each step you are calling cantor twice (once for each side of the deleted inner third), you have one call to cantor for each line segment that has to be drawn. As such I would put all of the drawing directly into the cantor method.
2) Since y0 and y1 are both always the same, I would reduce them to just a single y variable.
3) I would simplify the math for computing the new x0 and x1 values down to
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
4) Instead of decrementing the y value by 0.1 every time, you should have a global variable that decides the amount by which this should be decremented (otherwise if you try n > 10 things will break). This value can just be set to 1.0 / n.
5) You don't need to set the color of the pen every time you paint. You can set it just once in the main method.
6) StdDraw already sets a border around the picture you are drawing so there is no need to start your coordinates from 0.9 - you can use 1 instead.
Following these suggestions the code would look like this :
private static double yIncrement;
public static void cantor(int n, double x0, double x1, double y) {
if (n == 0)
return;
StdDraw.line(x0, y, x1, y);
y = y - yIncrement;
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
}
public static void main(String[] args) {
//change n into integer (depth)
int n = Integer.parseInt(args[0]);
// specify inital values for line
double x0 = 0;
double x1 = 1;
double y = 1;
yIncrement = 1.0 / n;
StdDraw.setPenColor(Color.BLUE);
// recursive function cantor
cantor(n, x0, x1, y);
}
EDIT : Playing around with the StdDraw canvas size, canvas scaling settings, and line segment endpoint rounding mode you can get a slightly better picture (the code below produces a picture that looks mostly correct down to the 8th level)
private static double yIncrement;
public static void cantor(int n, double x0, double x1, double y) {
if (n == 0)
return;
x0 = Math.ceil(x0);
x1 = Math.floor(x1);
StdDraw.line(x0, y, x1, y);
y = y - yIncrement;
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
}
public static void main(String[] args) {
// change n into integer (depth)
int n = Integer.parseInt(args[0]);
int width = 1920;
int height = 1080;
StdDraw.setCanvasSize(width, height);
// specify inital values for line
double x0 = 0;
double x1 = width;
double y = 1;
yIncrement = 1.0 / n;
StdDraw.setPenColor(Color.BLUE);
StdDraw.setXscale(0, width);
// recursive function cantor
cantor(n, x0, x1, y);
}
To display everything down to the tenth level with absolute correctness you would need a width of 3^9 pixels (19K pixels). For level 9 that's 3^8 = 6K. For level 8 that's 3^7 = 2k, which is why it looks almost correct with 1.9K pixel width and integer rounding.
I need to create a class which calculates the distance between two points. I am stuck and I am a total beginner. Here are my classes:
package org.totalbeginner.tutorial;
public class Point {
public double x;
public double y;
Point(double xcoord, double ycoord){
this.x = xcoord;
this.y = ycoord;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
The second class.
package org.totalbeginner.tutorial;
public class Line {
double x;
double y;
Point p1 = new Point(2.0,2.0);
Point p2 = new Point(4.0,4.0);
Point mp = new Point(x,y);
public void midpoint() {
x = (p1.getX() + p2.getX()) / 2;
y = (p1.getY() + p2.getY()) / 2;
}
}
I am not sure how to get a point object (the middle point) between both defined points.
I can create point objects but I am not sure how to return a point object through my midpoint() method that lies between those two point objects.
The distance between two points (x1,y1) and (x2,y2) on a flat surface is:
____________________
/ 2 2
\/ (y2-y1) + (x2-x1)
But, if all you want is the midpoint of your two points, you should change your midpoint function to:
public Point midpoint (Point p1, Point p2) {
return new Point ((p1.getX() + p2.getX()) / 2, (p1.getY() + p2.getY()) / 2);
}
This will return a brand new point object with the points set to the middle of the given two points (without having to concern yourself with any other math). And, since your second class is a line, you only need the two end points to describe it, so I'd make some minor changes.
First Point.java:
class Point {
double x, y;
Point (double xcoord, double ycoord) {
this.x = xcoord;
this.y = ycoord;
}
public double getX() { return x; }
public double getY() { return y; }
}
Then Line.java:
public class Line {
Point p1, p2;
Line (Point point1, Point point2) {
this.p1 = point1;
this.p2 = point2;
}
public Point midpoint() {
return new Point ((p1.getX()+p2.getX())/2, (p1.getY()+p2.getY())/2);
}
public double abstand() {
return Math.sqrt(
(p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) +
(p1.getY() - p2.getY()) * (p1.getY() - p2.getY())
);
}
static public void main (String args[]) {
Line s = new Line (new Point(2.0, 2.0), new Point(5.0, 6.0));
Point mp = s.midpoint();
System.out.println ("Midpoint = (" + mp.getX() + "," + mp.getY() + ")");
double as = s.abstand();
System.out.println ("Length = " + as);
}
}
These two files, when compiled and run with the endpoints 2,2 and 5,6 (the hypotenuse of a classic 3/4/5 right-angled triangle), generate the correct:
Midpoint = (3.5,4.0)
Length = 5.0
Simple Pythag... root(dx^2 + dy^2)
Math.sqrt(Math.pow((p2.getX() - p1.getX()), 2) + Math.pow((p2.getY() - p1.getY()), 2))
X
+
|\
| \
a| \c
| \
| \
+-----+
b Y
Imagine X and Y are your points on a flat surface. Then a is X.y - Y.y and b is Y.x - X.x . The length of c is their distance, and is the length of the hypotenuse of that triangle. It is calculated using
sqrt(a^2 + b^2);
Since you see we are squaring a and b, the sign of them isn't relevant - it will come down to the same. So this method always works, where ever the points lie.
Lookup the Pythagorean theorem
Do you really need the distance, or are you trying to just get the midpoint? Because from your code snippet, it kind of looks like you just want to create a new point that is half-way between two existing points.
If you're really just after the midpoint, you don't really need an entire 2nd class (i.e., 'Line') to accomplish that. Since the thing you are trying to find is also a point, it makes sense to add a constructor to your existing Point class, like so ..
Point(Point a, Point b)
{
x = (a.x + b.x) / 2;
y = (a.y + b.y) / 2;
}
.. then, elsewhere let's say you already have a couple of points you want to use this on, you use the constructor thus:
Point p1 = new Point(2,2);
Point p2 = new Point(4,4);
Point midpoint = new Point(p1, p2);
and if you really want distance between two points, that's not really an attribute of either point, so it makes sense to use a static method for that, like so
public static double distance(Point a, Point b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
}
and back in the calling code, you can use it this way:
Point p1 = new Point(2,2);
Point p2 = new Point(4,4);
System.out.println("Distance between them is " + Point.distance(p1, p2));
You can use a Maths function for this:
public Point midpoint() {
//Calculate the difference between the old and new x/y
double dx = p1.getX() - p2.getX();
double dy = p1.getY() - p2.getY();
double newX = Math.pow(dx, 2D);
double newY = Math.pow(dz, 2D);
return new Point(newX, newZ);
}
Math.pow handles the issues with negative values and etc. For you,
using Math.pow gives you a safe method because it has a lot of checks built inside.
You can use the Pythagorean Theorem, as other said. Here is a visually demostration from the Wolfram Demostration Project.
alt text http://demonstrations.wolfram.com/DistanceBetweenTwoPoints/HTMLImages/index.en/popup_5.jpg
In your second class, it looks like you're trying to set the values of x and y that are used to construct your mp variable. All your formulas are correct, but you need to consider the order that everything is executed. In the code as it is, it's creating the x and y variables, which start out as 0, then the various Points. x and y are still 0, so mp is set to Point(0, 0).
What you probably want to do is change the return type of midpoint to Point, so that when you call that function, you get back a Point. Then you can create a new Point object with the values you calculate. It should look more like this:
public Point midpoint() {
// calculate the middle x and y
double x = (p1.getX() + p2.getX()) / 2;
double y = (p1.getY() + p2.getY()) / 2;
// now make a new Point with those values, and return it
return new Point(x, y);
}