OK, so I've written most of a program that will allow me to determine if two circles overlap.
I have no problems whatsoever with my program aside from one issue: the program won't accept the code I've written for the distance between the two center points. I can figure out the if/else logic to tell the user what happens depending on the value of distance later, but I want to know what's wrong now. Eclipse, the program I'm coding on, is telling me that distance should be resolved to an array, but I've already told you that it's an int.
Here is my code:
package circles;
import java.util.Scanner;
public class MathCircles {
// variable for the distance between the circles' centers
public static int distance;
// variable for the lengths of the radii combined
public static int radii;
public static void main(String[] args) {
// Get the x-value of the center of circle one
System.out.println("What is the x-coordinate for the center of circle one?");
Scanner keyboard = new Scanner(System.in);
int x1 = keyboard.nextInt();
//Get the y-value of the center of circle one
System.out.println("What is the y-coordinate for the center of circle one?");
Scanner keyboard1 = new Scanner(System.in);
int y1 = keyboard1.nextInt();
//Get the radius length of circle one.
System.out.println("How long is circle one's radius?");
Scanner keyboard2 = new Scanner(System.in);
int r1 = keyboard2.nextInt();
// Get the x-value of the center of circle two.
System.out.println("What is the x-coordinate for the center of circle two?");
Scanner keyboard3 = new Scanner(System.in);
int x2 = keyboard3.nextInt();
//Get the y-value of the center of circle two.
System.out.println("What is the y-coordinate for the center of circle two?");
Scanner keyboard4 = new Scanner(System.in);
int y2 = keyboard4.nextInt();
//Get the radius length of circle two.
System.out.println("How long is circle two's radius?");
Scanner keyboard5 = new Scanner(System.in);
int r2 = keyboard5.nextInt();
/*
* OK, so now I have the location of the two circles' centers,
* as well as the lengths of their radii.
* The circles are intersecting IF THE DISTANCE BETWEEN THE TWO CENTERS
* IS EQUAL TO OR LESS THAN THE COMBINED LENGTHS OF THE RADII.
* Now I need to get some math done.
*/
//calculate the combined lengths of the radii
radii = r1 + r2;
//calculate the distance
distance = Math.sqrt((x1-x2)(x1-x2) + (y1-y2)(y1-y2));
}
}
Based on the #trashgod's comment, this is the simpliest way to calculate distance:
double distance = Math.hypot(x1-x2, y1-y2);
From documentation of Math.hypot:
Returns: sqrt(x²+ y²) without intermediate overflow or underflow.
Unlike maths-on-paper notation, most programming languages (Java included) need a * sign to do multiplication. Your distance calculation should therefore read:
distance = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
Or alternatively:
distance = Math.sqrt(Math.pow((x1-x2), 2) + Math.pow((y1-y2), 2));
This may be OLD,
but here is the best answer:
float dist = (float) Math.sqrt(
Math.pow(x1 - x2, 2) +
Math.pow(y1 - y2, 2) );
Based on the #trashgod's comment, this is the simpliest way to calculate >distance:
double distance = Math.hypot(x1-x2, y1-y2);
From documentation of Math.hypot:
Returns: sqrt(x²+ y²) without intermediate overflow or underflow.
Bob
Below Bob's approved comment he said he couldn't explain what the
Math.hypot(x1-x2, y1-y2);
did. To explain a triangle has three sides. With two points you can find the length of those points based on the x,y of each. Xa=0, Ya=0 If thinking in Cartesian coordinates that is (0,0) and then Xb=5, Yb=9 Again, cartesian coordinates is (5,9). So if you were to plot those on a grid, the distance from from x to another x assuming they are on the same y axis is +5. and the distance along the Y axis from one to another assuming they are on the same x-axis is +9. (think number line) Thus one side of the triangle's length is 5, another side is 9. A hypotenuse is
(x^2) + (y^2) = Hypotenuse^2
which is the length of the remaining side of a triangle. Thus being quite the same as a standard distance formula where
Sqrt of (x1-x2)^2 + (y1-y2)^2 = distance
because if you do away with the sqrt on the lefthand side of the operation and instead make distance^2 then you still have to get the sqrt from the distance. So the distance formula is the Pythagorean theorem but in a way that teachers can call it something different to confuse people.
You need to explicitly tell Java that you wish to multiply.
(x1-x2) * (x1-x2) + (y1-y2) * (y1-y2)
Unlike written equations the compiler does not know this is what you wish to do.
You could also you Point2D Java API class:
public static double distance(double x1, double y1, double x2, double y2)
Example:
double distance = Point2D.distance(3.0, 4.0, 5.0, 6.0);
System.out.println("The distance between the points is " + distance);
Math.sqrt returns a double so you'll have to cast it to int as well
distance = (int)Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
Related
I'm working on a project and I have most of it done but I'm having trouble seeing how to get the coordinates to line up. I'm stuck and I'm not sure how to get a point to be at 3 o'clock and I'm stuck. I've tried finding examples but all I see is polygons that don't need to lineup with anything. Any help?
The instructions: Suppose an n-sided regular polygon is centered at (0, 0) with one point at the 3 o’clock position, as shown in Figure 5.4. Write a program that prompts the user to enter the number of the sides, the radius of the bounding circle of a polygon, and displays the coordinates of the corner points on the polygon.
import java.util.Scanner;
public class Polygon {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the number of sides: ");
int sides = input.nextInt();
System.out.print("Enter the radius of the bounding circle: ");
double radius = input.nextDouble();
input.close();
System.out.println("The coordinates of the points on the polygon are");
for (int i = 0; i < sides; i++) {
double x = radius * java.lang.Math.sin(2.0 * java.lang.Math.PI / sides * i);
double y = radius * java.lang.Math.cos(2.0 * java.lang.Math.PI / sides * i);
System.out.print("(");
System.out.printf("%.2f", x);
System.out.print(" ");
System.out.printf("%.2f",y);
System.out.print(")");
System.out.println();
}
}
}
You need to switch your sin and cos expressions. The the first point of your polygon will then always lie at (radius, 0), i.e. aligned with the 3-o'clock position.
double x = radius * java.lang.Math.cos(2.0 * java.lang.Math.PI / sides * i);
double y = radius * java.lang.Math.sin(2.0 * java.lang.Math.PI / sides * i);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have solved this problem but im not sure if its correct..
User should give the coordinates of a point and I should check if that point is within,outside or on the circle. I used the distance formula to solve this .
The given information about the circle are:
Circle is centered at ( 0,0 )
and radius is 10
public static void main(String[] strings) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a point with two coordinates");
double y1 = scanner.nextDouble();
double x1 = scanner.nextDouble();
// circle is centered at 0,0
double y2 = 0;
double x2 = 0;
double radius = 10;
double distance;
// using the distance formula to calculate the distance
// from the point given from the user and point where circle is centered
/**
* distance formula
* d = √ ( x2 - x1 )^2 + (y2 - y1 )^2
*/
distance = Math.pow( x2 - x1,2) + Math.pow(y2-y1,2);
// find square root
distance = Math.sqrt(distance);
String result="";
if(distance < radius) {
result = "("+y1+" , "+x1+")" +" is within the circle";
}
else if(distance > radius) {
result = y1+" , "+x1 +" is outside the circle";
}
else if(distance == radius) {
result =y1+" , "+x1 +" is on the circle";
}
System.out.println(result);
}
It's fine but sloppy.
There's no need to compute the square root. Work in units of distance squared.
Then compare using distance < radius * radius etc., perhaps renaming distance for the sake of clarity. Computing square roots is costly and imprecision can creep in which can be difficult to control. This is particularly important in your case where you want to test for a point being on the circle's edge.
Also consider writing (x2 - x1) * (x2 - x1) rather than using pow for the second power. Although Java possibly (I never remember for sure which is certainly a good enough reason for my not using it) optimises to the longer form, other languages (such as C) don't and imprecision can creep in there too.
Are you sure this question requires doubles as input? The examples given are integers. With integers you can be sure of a points location, with real numbers (doubles) you cannot be sure about the "on circle" or not which is another reason I think the question expects you to use integers.
And the trick for performance and accuracy is to not use Math.sqrt and only work with integers.
int x;
int y;
int centreX;
int centreY;
int deltaX = x - centreX;
int deltaY = y - centreY;
int distanceSquared = deltaX * deltaX + deltaY * deltaY;
int radiusSquared = radius * radius;
if (distanceSquared == radiusSquared) { //distance == radius
//on circle
} else if (distanceSquared < radiusSquared) { //distance < radius
//in circle
} else {
//out of circle
}
Consider using Math.hypot() to calculate a distance and compare double values using some small threshold:
static final double DELTA = 1E-5; // not necessarily 1E-5; see comments
//...
distance = Math.hypot(x2 - x1, y2 - y1);
if (Math.abs(distance - radius) < DELTA)
// on the circle
else if (distance > radius)
// outside
else
// inside
The reason for using DELTA is that there is a very small chance to get equal double values by calculations. If they differ in at least one bit, direct comparison will return false.
By appliying threshold, you check not whether the point lays exactly on the circle, but whether it lays inside a ring between radius - DELTA and radius + DELTA. So DELTA is a kind of tolerance limit which value should be chosen particularily for application, e. g. depending on absolute or relative input inaccuracy.
I'm practicing for an exam, and I'm doing one of the practice problems. I have a method that takes two arguments: one for the radius of a circle, and one for the number of dots to place within that circle. The method is below:
private void drawDots(int radius, int numDots){
double ycord;
double xcord;
for(int q = 0; q < numDots; q++){
ycord = -radius + random()*(radius+radius+1);
xcord = pow((pow(radius,2)-pow(ycord,2)),0.5);
turt.moveTo(xcord,ycord);
turt.penDown();
turt.forward(0);
turt.penUp();
}
}
turt is an object I'm using to draw with, and penDown()/penUp() is placing and removing the object from the canvas respectively.
I'm trying to define the x-coordinate and y-coordinate of the turt object to stay within a radius. Say the radius is 100, and the number of dots is 200, how do I keep the object within that radius?
The question states that:
"To constain the dots to a circle of radius r, a random y-coord in the interval -r, r is chosen. To x-coord is then randomly chosen in the interval -b, b, where b = sqrt(r^2 - y^2)."
I'm just not sure how to make sense of this math. The code above was my best attempt, but the output is strange.
Here is my failed output:
The distance from the center (0,0) to a dot must be less than the radius of the circle, r. The distance can be expressed as sqrt(x² + y²). Therefore, if you choose your y coordinate randomly between [-r, r], you just have to make sure that your x coordinate respects the previous equation, hence your math.
Demonstration
sqrt(x² + y²) < r
x² + y² < r²
x² < r² - y²
x < sqrt(r² - y²)
#
Your algorithm should be as follows. Once you chose the y coordinate, you can randomly choose x as long as it respects the distance constraint.
private void drawDots(int radius, int numDots){
double y;
double x;
double xMax;
for (int q = 0; q < numDots; q++){
// y is chosen randomly
y = -radius + random() * (radius + radius + 1);
// x must respect x² + y² < r²
xMax = pow((pow(radius,2)-pow(ycord,2)), 0.5);
x = random() * 2 * xMax - xMax;
turt.moveTo(x, y);
turt.penDown();
turt.forward(0);
turt.penUp();
}
}
Take a look at the documentation for random, you will see by default it produces a number between 0 and 1.
Basically this means that the expression you are looking for is:
ycord=-radius+random()*(radius*2);
This gives you a point on the y axis between -radius and radius (consider if the random() returns 0 you get -radius, it it returns 1 you get -radius+(2*radius())=radius.
You calculation for the x co-ordinate is correct but it gives you the x coordinate point on the circle (lets call it b). I suspect you want to use a new random to select an x co-ordinate between b and -b.
At present you are drawing points on the circle, not inside it. That is because you are not following the guideline correctly.
b = pow((pow(radius,2)-pow(ycord,2)),0.5); // this should be b
xcord = -b + random()*(b+b);
I have a circle that moves from point A to a random point B. When the object nears point B, a new random target location gets chosen. If the circle is moving parallel to the X-axis or Y-axis the object goes through all the pixels in the way and leaves a solid trace. But if the circle moves diagonally, it skips pixels and shakes slightly, making the animation not smooth and leaves a trace with unpainted pixels.
My algorithm is:
calculate the X and Y distances
check if the circle is near
if so, choose the new destination
if 2. is true, find the real distance using Pythagoras' theorem
if 2. is true, calculate the X and Y speed (the change of the coordinates)
set the new coordinates (no matter if 2. is true or not)
And here is the code:
public void move ()//движение
{
//finds the X and Y distance to the destination
int triangleX = nextLocationX - coorX;
int triangleY = nextLocationY - coorY;
//if too near the coordinates of the destination changes
if (Math.abs(triangleX) <= Math.abs(speedX) || Math.abs(triangleY) <= Math.abs(speedY))//setting the new target
{
//setting the new destinatio
int randInt;
for (;;)//I don't want the the new destination to be that same spot
{
randInt= randGen.nextInt(appletX);
if (randInt != nextLocationX)
{
nextLocationX = randInt + radius;
break;
}
}
for (;;)
{
randInt = randGen.nextInt(appletY);
if (randInt != nextLocationY)
{
nextLocationY = randInt + radius;
break;
}
}
//calculating the change of the circle's X and Y coordinates
triangleX = nextLocationX - coorX;
triangleY = nextLocationY - coorY;
speedX = ((double)(speed * triangleX) / (Math.sqrt (Math.pow(triangleX, 2) + Math.pow(triangleY, 2))));
speedY = ((double)(speed * triangleY) / (Math.sqrt (Math.pow(triangleX, 2) + Math.pow(triangleY, 2))));
}
//the realCoor variables are from type double
//they are the exact coordinates of the circle
//If I only use integers, the circle almost
//never reaches it's destination
//unless the change of the coordinates gets calculated
//after every time they change
realCoorX = realCoorX + speedX;
realCoorY = realCoorY + speedY;
coorX = (int)Math.round(realCoorX);
coorY = (int)Math.round(realCoorY);
}
I suspect that the problem is in the calculation of the change of the coordinates.
For me this sounds like a Aliasing problem. You would have the same problem if you draw(!) a line that is not aligned with the coordinate axis. As you know, i.e. diagonal lines need "half filled" pixels to look smooth.
Solution for you would be (depending on the technology for rendering) to use floating point position calculation.
I've issued myself a sort of challenge, and thought I could stand to ask for help getting my head around it. I want to use java Graphics to draw something that looks like lightning striking a given point.
Right now I just have this, which shoots cheap "lightning" in random directions, and I don't care where it ends up.
lightning[0] = new Point(370,130); //This is a given start point.
// Start in a random direction, each line segment has a length of 25
double theta = rand.nextDouble()*2*Math.PI;
int X = (int)(25*Math.cos(theta));
int Y = (int)(25*Math.sin(theta));
//Populate the array with more points
for (int i = 1 ; i < lightning.length ; i++)
{
lightning[i] = new Point(X + lightning[i-1].x, Y + lightning[i-1].y);
boolean plusminus = rand.nextBoolean();
if (plusminus) theta = theta + rand.nextDouble()*(Math.PI/2);
else theta = theta - rand.nextDouble()*(Math.PI/2);
X = (int)(25*Math.cos(theta));
Y = (int)(25*Math.sin(theta));
}
// Draw lines connecting each point
canvas.setColor(Color.WHITE);
for (int i = 1 ; i < lightning.length ; i++)
{
int Xbegin = lightning[i-1].x;
int Xend = lightning[i].x;
int Ybegin = lightning[i-1].y;
int Yend = lightning[i].y;
canvas.drawLine(Xbegin, Ybegin, Xend, Yend);
//if (Xend != Xbegin) theta = Math.atan((Yend - Ybegin)/(Xend - Xbegin));
// Restrict the angle to 90 degrees in either direction
boolean plusminus = rand.nextBoolean();
if (plusminus) theta = theta + rand.nextDouble()*(Math.PI/2);
else theta = theta - rand.nextDouble()*(Math.PI/2);
// 50/50 chance of creating a half-length off-shoot branch on the end
if (rand.nextBoolean())
{
int Xoff = (int)(Xend+(12*Math.cos(theta)));
int Yoff = (int)(Yend+(12*Math.sin(theta)));
canvas.drawLine(Xend, Yend, Xoff, Yoff);
}
}
I'm trying to think of some similar way to create this effect, but have the last point in the array pre-defined, so that the lightning can "strike" a specific point. In other words, I want to populate a Point array in a way that is random, but still converges on one final point.
Anyone care to weigh in?
I think this is fairly simple, accurate, and elegant approach. It uses a divide and conquer strategy. Start with only 2 values:
start point
end point
Calculate the midpoint. Offset that midpoint some value variance (which can be calculated relative to the length). The offset should ideally be normal to the vector connecting start and end, but you could be cheap by making that offset horizontal, as long as your bolts travel mostly vertically, like real lightning. Repeat above procedure for both (start, offset_mid) and (offset_mid, end), but this time using a smaller number for variance. This is a recursive approach which can terminate when either a threshold variance is achieved, or a threshold line segment length. As the recursion unwinds, you can draw all the connector segments. The idea is that the largest variance happens in the center of the bolt (when the start-to-end distance is the longest), and with each recursive call, the distance between points shrinks, and so does the variance. This way, the global variance of the bolt will be much greater than any local variances (like a real lightning bolt).
Here is an image of 3 different bolts generated from the same pre-determined points with this algorithm. Those points happen to be (250,100) and (500,800). If you want bolts that travel in any direction (not just "mostly vertical"), then you'll need to add more complexity to the point shifting code, shifting both X and Y based on the angle of travel of the bolt.
And here is some Java code for this approach. I used an ArrayList since the the divide and conquer approach doesn't know ahead of time how many elements it will end up with.
// play with these values to fine-tune the appearance of your bolt
private static final double VAR_FACTOR = 0.40;
private static final double VAR_DECREASE = 0.55;
private static final int MIN_LENGTH = 50;
public static ArrayList<Point> buildBolt(Point start, Point end) {
ArrayList<Point> bolt = new ArrayList<Point>();
double dx = start.getX() - end.getX();
double dy = start.getY() - end.getY();
double length = Math.sqrt(dx*dx + dy*dy);
double variance = length * VAR_FACTOR;
bolt.add(start);
buildBolt(start, end, bolt, variance);
return bolt;
}
private static void buildBolt(Point start, Point end,
List<Point> bolt, double variance) {
double dx = start.getX() - end.getX();
double dy = start.getY() - end.getY();
double length = Math.sqrt(dx*dx + dy*dy);
if (length > MIN_LENGTH) {
int varX = (int) ((Math.random() * variance * 2) - variance);
int midX = (start.x + end.x)/2 + varX;
int midY = (start.y + end.y)/2;
Point mid = new Point(midX, midY);
buildBolt(start, mid, bolt, variance * VAR_DECREASE);
buildBolt(mid, end, bolt, variance * VAR_DECREASE);
} else {
bolt.add(end);
}
return;
}
Without any graphics experience, I have this advice: it's going to be hard to pick a specific point, then try to reach it in a "random" way. Instead, I'd recommend creating a straight line from the origin to destination, then randomly bending parts of it. You could make several passes, bending smaller and smaller segments down to a certain limit to get the desired look. Again, I'm saying this without any knowledge of the graphics API.