Finding whether a point is within a triangle - java

I have been on this for hours, attempting different methods looking at just about every question. Perhaps I have it completely wrong, but I feel that I have my math of it correct, but no matter what numbers I input, I get the same output. My code is off somewhere and I have to turn it in by midnight.
It is the all so fun: Find if a point is within a triangle code. (for beginners)
import java.util.Scanner;
public class PointsTriangle {
// checks if point entered is within the triangle
//given points of triangle are (0,0) (0,100) (200,0)
public static void main (String [] args) {
//obtain point (x,y) from user
System.out.print("Enter a point's x- and y-coordinates: ");
Scanner input = new Scanner(System.in);
double x = input.nextDouble();
double y = input.nextDouble();
//find area of triangle with given points
double ABC = ((0*(100-0 )+0*(0 -0)+200*(0-100))/2.0);
double PAB = ((x*(0 -100)+0*(100-y)+0 *(y- 0))/2.0);
double PBC = ((x*(100-0 )+0*(0 -y)+200*(y-100))/2.0);
double PAC = ((x*(0 -100)+0*(100-y)+200*(y- 0))/2.0);
boolean isInTriangle = PAB + PBC + PAC == ABC;
if (isInTriangle)
System.out.println("The point is in the triangle");
else
System.out.println("The point is not in the triangle");
}//end main
}//end PointsTriangle

You placed the wrong value order into your formula; therefore, the result is wrong. If the 3 vertices are as the following
A(x1, y1) B(x2, y2), C(x3, y3)
then the area is calculated as
double ABC = Math.abs (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2;
After that, you just replace each vertex with the input point, we will have the following triangles: PBC, APC, ABP.
Put everything together, we will have the correct one
int x1 = 0, y1 = 0;
int x2 = 0, y2 = 100;
int x3 = 200, y3 = 0;
// no need to divide by 2.0 here, since it is not necessary in the equation
double ABC = Math.abs (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2));
double ABP = Math.abs (x1 * (y2 - y) + x2 * (y - y1) + x * (y1 - y2));
double APC = Math.abs (x1 * (y - y3) + x * (y3 - y1) + x3 * (y1 - y));
double PBC = Math.abs (x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2));
boolean isInTriangle = ABP + APC + PBC == ABC;

If you draw a picture, you can see the point has to satisfy simple inequalities (below / above / to the right of certain lines). Whether "on the edge" is in or out I will leave up to you:
Y > 0 (above the X axis)
X > 0 (to the right of the Y axis)
X + 2* Y < 200 (below the hypotenuse)
Write an if statement around these three and you're done:
if( (y > 0) && (x > 0) && (x + 2*y < 200) )
System.out.println("The point is in the triangle");
else
System.out.println("The point is not in the triangle");

Related

How to generate a random polygon centered in Java?

I want to generate some randoms polygon but I want it to be more or less centered in the middle of the given window coordinates.
Here is my code, it generates a random polygon but most of the time it's on the bottom of the window and I'd like to have it a bit more centered:
private static final double CORNER_MARGIN = 100.0; // max offset for a corner of the field, to randomize the polygon
private static double[] standardPolygon(double x1, double x2, double y1, double y2) {
// minX maxX minY maxY --> it's the coordinate of the window
double centerX = (x1 + x2) / 2;
double centerY = (y1 + y2) / 2;
// this is a standard polygon "centered" in the middle of the program window
return new double[]{
x1 - (x2 - x1) * RANDOM.nextDouble(), y2 + (y2 - y1) *RANDOM.nextDouble() * CORNER_MARGIN,
x2 + (x2 - x1) * RANDOM.nextDouble(), y2 + (y2 - y1) *RANDOM.nextDouble() * CORNER_MARGIN,
x2 + (x2 - x1) * RANDOM.nextDouble(), y1 - (y2 - y1) *RANDOM.nextDouble() * CORNER_MARGIN,
x1 - (x2 - x1) * RANDOM.nextDouble(), y1 - (y2 - y1) *RANDOM.nextDouble() * CORNER_MARGIN,
};
/*return new double[]{
x1 - RANDOM.nextDouble() * CORNER_MARGIN, y2 + RANDOM.nextDouble() * CORNER_MARGIN, // up left
x2 + RANDOM.nextDouble() * CORNER_MARGIN, y2 + RANDOM.nextDouble() * CORNER_MARGIN, // up right
x2 + RANDOM.nextDouble() * CORNER_MARGIN, y1 - RANDOM.nextDouble() * CORNER_MARGIN, // down right
x1 - RANDOM.nextDouble() * CORNER_MARGIN, y1 - RANDOM.nextDouble() * CORNER_MARGIN, // down left
};*/
}
The code in comment is working but now I tried to center it but I only get some rectangles/squares. How can I manage to keep random polygon forms but a bit more centered ?
[EDIT]
Here is how I draw the area of the polygon :
private void drawZone(Group group, IGameParameters gameParameters) {
Polygon polygon = new Polygon();
double[] points = gameParameters.dronePadDeliveryZonePolygon();
List<Double> pointsList = new ArrayList<>();
for (double point : points) pointsList.add(point);
polygon.getPoints().addAll(pointsList);
polygon.setFill(Color.ANTIQUEWHITE);
group.getChildren().add(polygon);
}```
You calculated the center but don't use it anywhere. Just so I understand correctly, this is a 4-sided polygon only and the corners randomly positioned at most 100 from the corner of the window?
I'm not 100% sure on how you want the polygon to be shaped but give this a try. Logically it works in my head, but I don't have a way to test the code right now.
private static final double CORNER_MARGIN = 100.0;
private static double[] standardPolygon(double x1, double x2, double y1, double y2) {
double centerX = (x1 + x2) / 2;
double centerY = (y1 + y2) / 2;
// Get the corner offsets
ox1 = x1 + CORNER_MARGIN * RANDOM.nextDouble(); // top left
oy1 = y1 + CORNER_MARGIN * RANDOM.nextDouble();
ox2 = x2 - CORNER_MARGIN * RANDOM.nextDouble(); // top right
oy2 = y1 + CORNER_MARGIN * RANDOM.nextDouble();
ox3 = x1 + CORNER_MARGIN * RANDOM.nextDouble(); // bottom left
oy3 = y2 - CORNER_MARGIN * RANDOM.nextDouble();
ox4 = x2 - CORNER_MARGIN * RANDOM.nextDouble(); // bottom right
oy4 = y2 - CORNER_MARGIN * RANDOM.nextDouble();
// Calculate the center of the polygon
double cx = (ox2 - ox1) / 2;
double cy = (oy2 - oy1) / 2;
// difference between window's center and polygon
double offsetX = centerX - cx;
double offsetY = centerY - cy;
// offset the calculated points so the polygon's center matches the window
ox1 += offsetX;
oy1 += offsetY;
ox2 += offsetX;
oy2 += offsetY;
ox3 += offsetX;
oy3 += offsetY;
ox4 += offsetX;
oy4 += offsetY;
// this is a standard polygon "centered" in the middle of the program window
return new double[]{
ox1, oy1,
ox2, oy2,
ox3, oy3,
ox4, oy4
};
}

Java: .print not working the way I intended in my code

So this is my very first homework assignment regarding code and I've spent the past few hours trying to figure this out but I'm completely stumped.
I'm trying to find the area of a triangle by inputting its three sides (Which I managed to figure out how to do), but when I actually compile and run the code, my .print isn't working as intended.
Here's my code thus far:
import java.util.Scanner;
// Purpose: To get the area of a triangle
public class ComputeTriangleArea {
// main method
public static void main(String[] args) {
// Creating a scanner
Scanner scanner = new Scanner(System.in);
// Entering dimensions
double x1 = scanner.nextDouble(); double y1 = scanner.nextDouble();
double x2 = scanner.nextDouble(); double y2 = scanner.nextDouble();
double x3 = scanner.nextDouble(); double y3 = scanner.nextDouble();
// Inputting side 1
System.out.print("Enter the dimensions of side 1: ");
double side1 = Math.sqrt((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2));
// Inputting side 2
System.out.print("Enter the dimensions of side 2: ");
double side2 = Math.sqrt((x1-x3) * (x1-x3) + (y2-y3) * (y2-y3));
// Inputting side 3
System.out.print("Enter the dimensions of side 3: ");
double side3 = Math.sqrt((x2-x3) * (x2-x3) + (y2-y3) * (y2-y3));
// Convert to Area
double s = (side1+side2+side3) / 2;
double area = Math.sqrt(s * (s-side1) * (s-side2) * (s-side3));
// Display the result
System.out.printf("The area is %.2f\n", area);
}
}
and the result is if I input let's say 1, 2, 3, 4, 5, 6
it shows up as:
java -cp . ComputeTriangleArea
1
2
3
4
5
6
Enter the dimensions of side 1: Enter the dimensions of side 2: Enter the dimensions of side 3: The area is 3.87
Exit code: 0
Would anyone mind guiding me in the right direction?
Thank you so so much!
Edit: Here's the code I managed to get from the help of everyone in the comments below:
import java.util.Scanner;
// Purpose: To get the area of a triangle
public class ComputeTriangleArea {
// main method
public static void main(String[] args) {
// Creating a scanner
Scanner scanner = new Scanner(System.in);
// Inputting side 1
scanner = new Scanner(System.in);
System.out.print("Enter the dimensions of side 1: ");
double x1 = scanner.nextDouble();
double y1 = scanner.nextDouble();
// Inputting side 2
System.out.print("Enter the dimensions of side 2: ");
double x2 = scanner.nextDouble();
double y2 = scanner.nextDouble();
// Inputting side 3
System.out.print("Enter the dimensions of side 3: ");
double x3 = scanner.nextDouble();
double y3 = scanner.nextDouble();
double side1 = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
double side2 = Math.sqrt((x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3));
double side3 = Math.sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3));
// Convert to Area
double s = (side1 + side2 + side3) / 2;
double area = Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
// Display the result
System.out.printf("The area is %.2f\n", area);
}
}
You can try below code:
// main method
public static void main(String[] args) {
// Creating a scanner
Scanner scanner = new Scanner(System.in);
// Inputting side 1
System.out.print("Enter the dimensions of side 1: ");
double x1 = scanner.nextDouble();
double y1 = scanner.nextDouble();
// Inputting side 2
System.out.print("Enter the dimensions of side 2: ");
double x2 = scanner.nextDouble();
double y2 = scanner.nextDouble();
// Inputting side 3
System.out.print("Enter the dimensions of side 3: ");
double x3 = scanner.nextDouble();
double y3 = scanner.nextDouble();
double side1 = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
double side2 = Math.sqrt((x1 - x3) * (x1 - x3) + (y2 - y3) * (y2 - y3));
double side3 = Math.sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3));
// Convert to Area
double s = (side1 + side2 + side3) / 2;
double area = Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
// Display the result
System.out.printf("The area is %.2f\n", area);
}
Updated
Use single Scanner instead of multiple create Scanner, the enter key would not break System.in(Which i'm incorrect previously with thought enter key would break System.in)
That output is expected from the code you wrote.
I assume you want the output to be (please provide expected output)
Enter the dimensions of side 1: 1 2
Enter the dimensions of side 2: 3 4
Enter the dimensions of side 3: 5 6
The area is 3.87
If you observe your code, you've scanned all the 6 numbers first and are then printing the statements. Thus the output is as you've got.
If you want the output to appear as I've shown, then you need to print statement for each side, scan 2 numbers after each print statement.

Distance in BlueJ

OUTPUT should look like:
Enter the x and y coordinates of the first point: 3 -2
Enter the x and y coordinates of the second point: 9 2
Distance: 7.211
Positive Slope
I have updated the OP with what the code should look like if you're trying to find the distance.
Here is what my code looks like right now:
import java.util.Scanner;
public class LineEvaluator
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.print("Enter the x and y coordinates of the first point: ");
double x1 = input.nextDouble();
double y1 = input.nextDouble();
System.out.print("Enter the x and y coordinates of the second point: ");
double x2 = input.nextDouble();
double y2 = input.nextDouble();
double distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
System.out.printf("Distance: %.3f", distance);
double slope = ((y2 - y1) / (x2 - x1));
if(slope > 0)
System.out.println("Positive Slope");
else if(slope < 0)
System.out.println("Negative Slope");
else if(slope == 0)
System.out.println("Horizontal");
}
}
So... First of all don't say int to double like that - go in the documentations and you'll find that input.nextDouble() exists and you can use that instead directly.
e.x.:
int y2 = input.nextInt();
double g = y2;
to...
double g = input.nextDouble()
Also, in your distance formula, you are using:
double distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2)*(y1 - y2));
If you're using that, please name your doubles to the proper names(x1, x2, etc...)
When you use int, it truncates. Read up on the differences:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Then, you can calculate the slope, say you store it in a variable slope.
When you're trying to find a slope that has infinite slope, you will get this error: ArithmeticException.
You can fix this by a try catch, surrounding the code you might divide by 0, and then System.out.println("Vertical Line") at that situation, or you could evaluate later and leave the try catch blank. Use this: Double.isInfinite(double) to evaluate later on.
Try catch example:
try{
slope = (y2-y1)/(x2-x1)//if it's divide by zero then we will get this error
}catch(ArithmeticException e){
//Take care of the error as we discussed.
}
Use if-elses or switch statements to evaluate the slope:
if(slope > 0)
System.out.println("Positive slope")
else if(slope == 0)
System.out.println("Flat slope")...
Hope you got the idea.

Accurate Circular Orbit Equation in java

public void move(){
double angle;
for(int i = 0; i < planets.size(); i++){
if(Math.abs(Math.sqrt(Math.pow(ship.locX - (planets.get(i).locX + planets.get(i).radi), 2) + Math.pow(ship.locY - (planets.get(i).locY + planets.get(i).radi), 2))) < planets.get(i).gravrange){
//Distance formula between spaceship and planets to determine whether the ship is within the influence of the planet.
angle = ((Math.atan2((planets.get(i).locX + planets.get(i).radi) - ship.locX, (planets.get(i).locY + planets.get(i).radi) - ship.locY)) / Math.PI) + 1;
//The problematic math equation.
Produces a double from 0 to 2, 0 being when ship.locY < planets.get(i).locY && ship.locX == (planets.get(i).locX - planets.get(i).radi). (when relative X = 0 and relative Y < 0.)
if(ship.locX > (planets.get(i).locX + planets.get(i).radi)){xm += Math.cos(angle) * planets.get(i).gravrate;}
else{xm -= Math.cos(angle) * planets.get(i).gravrate;}
if(ship.locY > (planets.get(i).locY + planets.get(i).radi)){ym += Math.sin(angle) * planets.get(i).gravrate;}
else{ym -= Math.sin(angle) * planets.get(i).gravrate;}
}
}
This uses the data to modify the X and Y velocities of the spacecraft.
This equation works for the majority of an orbit, but under certain circumstances has an issue in which the spacecraft undergoes a retrograde force, slowing it. Shortly afterward it begins to be repelled by the planetary body, which after a short period begins attracting it again. When the spacecraft reaches the original position at which this occurred, it begins to move in the opposite direction of its original orbit.
This continues to occur until the spacecraft begins a wavelike motion.
Is there a way to solve this, or am I simply using the wrong equation? I've been attempting to fix this for about two weeks now. I have no education in physics nor calculus at this point in time, so my understanding is limited.
Edit: The comments had questions about my math, so I'll attempt to answer them here. From what I know about atan2, it produces a number from -pi to pi. I divide by pi to produce a number from -1 to 1, then add 1 to produce 0 to 2. I then use this number as a radian measurement. My knowledge of radians (unit circle) is that a circle's radian measure is 0 to 2pi.
Edit 2: The following code has very different math but produces the desired results, save for issues of repelling rather than attracting when approaching the North and South 'poles' of the planet.
public void move(){
double angle;
double x1, x2, y1, y2;
for(int i = 0; i < planets.size(); i++){
x1 = ship.locX;
y1 = ship.locY;
x2 = planets.get(i).locX + planets.get(i).radi;
y2 = planets.get(i).locY + planets.get(i).radi;
if(Math.abs(Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))) < planets.get(i).gravrange){
//Distance formula between spaceship and planets
angle = (y2 - y1)/(x2 - x1); //Gets slope of line between points.
if(angle > 0){
if(y1 > y2){
xm += Math.cos(angle) * planets.get(i).gravrate;
ym += Math.sin(angle) * planets.get(i).gravrate;
}else{
xm -= Math.cos(angle) * planets.get(i).gravrate;
ym -= Math.sin(angle) * planets.get(i).gravrate;
}
}
else{
if(y1 > y2){
xm -= Math.cos(angle) * planets.get(i).gravrate;
ym -= Math.sin(angle) * planets.get(i).gravrate;
}else{
xm += Math.cos(angle) * planets.get(i).gravrate;
ym += Math.sin(angle) * planets.get(i).gravrate;}
}
}
}
I wrote it up very quickly to see if using the slope of the line rather than that strange atan2 equation would help. Apparently it did. I also made the code a bit more readable in this section.
The following code fixed my issue. I was overcomplicating my math equations as I usually do. Took me three weeks of Googling, asking people with degrees in physics and mathematics, and reading Javadocs before I figured that one out. Turns out how atan2 works is simply different from how I thought it worked and I was improperly using it.
The solution was simplifying the atan2 equation beforehand and removing the unnecessary additions.
x1 = ship.locX;
y1 = ship.locY;
x2 = planets.get(i).locX + planets.get(i).radi;
y2 = planets.get(i).locY + planets.get(i).radi;
if(Math.abs(Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))) < planets.get(i).gravrange){
//Distance formula between spaceship and planets
angle = Math.atan2((y2 - y1),(x2 - x1)); //Converts the difference to polar coordinates and returns theta.
xm -= Math.cos(angle) * planets.get(i).gravrate; //Converts theta to X/Y
ym -= Math.sin(angle) * planets.get(i).gravrate; //velocity values.
}

Java Circle-Circle Collision Detection

Here is the circle class:
public class Circle {
private double radius;
private double x;
private double y;
}
How can I tell if two objects from this class (circles) are colliding?
P.S. Can you use the method that avoids taking a square root?
double xDif = x1 - x2;
double yDif = y1 - y2;
double distanceSquared = xDif * xDif + yDif * yDif;
boolean collision = distanceSquared < (radius1 + radius2) * (radius1 + radius2);
dx = x2 - x1;
dy = y2 - y1;
radiusSum = radius1 + radius2;
return dx * dx + dy * dy <= radiusSum * radiusSum; // true if collision
The link from #instanceofTom in the comments is better... with pictures.
The circles will touch when the distance between their centres is equal to the sum of their radii, or collide when the distance is less.
Since we are using absolute distance, it is Ok to compare the square of the distance between centres with the square of the sum of the radii.
Here's the updated Java solution:
public boolean hasCollision(Circle circle){
double xDiff = x - circle.getX();
double yDiff = y - circle.getY;
double distance = Math.sqrt((Math.pow(xDiff, 2) + Math.pow(yDiff, 2)));
return distance < (radius + circle.getRadius());
}

Categories

Resources