I have 2 coordinates (A1 and A2), connected by a straight line (my path). How can I calculate the shortest distance of a given coordinate (B1 or B2) from the straight line?
Mathematically :
As explained in wikipedia
the shortest distance between a line and a dot, can be calculated as
follows:
If the line passes through two points P1=(x1,y1) and P2=(x2,y2) then the distance of (x0,y0) from the line is:
Java implimentaion
class Point {
double x,y;
Point(double pX, double pY){
this.x= pX;
this.y= pY;
}
public double distance(Point A1, Point A2){
double numerator = Math.abs((A2.y - A1.y)*this.x + (A2.x - A1.x)*this.y + A2.x*A1.y - A2.y*A1.x);
double denominator = Math.sqrt(Math.pow(A2.y - A1.y,2) + Math.pow(A2.x - A1.x,2));
return numerator/denominator;
}
}
To calculate the distance between Point B and the line defined by Points A1 and A2, you use the method distance like this:
public static void main (String[] args) throws java.lang.Exception
{
Point A1 = new Point(0,3);
Point A2 = new Point(2,0);
Point B = new Point(0,0);
System.out.println(
B.distance(A1,A2)
);
}
And here is the code up and running in ideone.
But pleas go buck to the basics, chose some good and funny coding book or tut and give it a go, happy coding :)
Related
I have a polygon that have been divided up with multiple lines, creating new smaller polygons that make up the whole. How would I go about finding the slice with the largest area?
Imagine something like this: sliced polygon green points are vertices, lines intersect creating more vertices, looking for the largest yellow marked area.
I figured this could be solved by generating a directed graph in order to define each unique shape. I can't come up with a way to link all vertices correctly though.
All vertices and edge lengths are either given or calculated with these methods.
public static double calcDistanceBetweenPoints(Point a, Point b){
return Math.sqrt((b.y - a.y) * (b.y - a.y) + (b.x - a.x) * (b.x - a.x));
}
public static Point findIntersection(Point A, Point B, Point C, Point D){
// Line AB represented as a1x + b1y = c1
double a1 = B.y - A.y;
double b1 = A.x - B.x;
double c1 = a1*(A.x) + b1*(A.y);
// Line CD represented as a2x + b2y = c2
double a2 = D.y - C.y;
double b2 = C.x - D.x;
double c2 = a2*(C.x)+ b2*(C.y);
double determinant = a1*b2 - a2*b1;
if (determinant == 0)
{
// The lines are parallel
return new Point(Double.MAX_VALUE, Double.MAX_VALUE);
}
else
{
double x = (b2*c1 - b1*c2)/determinant;
double y = (a1*c2 - a2*c1)/determinant;
return new Point(x, y);
}
}
Data collected from the System.in input stream looks something like this:
n m
x1 y1
x.. y...
xn yn
x11 y11 x21 y21
x.. y.. x.. y..
x1m y1m x2m y2m
So I get all the starting and ending points for each line from the input.
Thanks for the help
I'm writing exercise program with user input of three points in coordinate system, so it get's you length of all sides of given triangle, so as perimeter and area. My goal is to define height of given triangle, so that i can tell if input points equals to straight line in coo-system, triangle doesnt exist, becouse height=0, also to define area of triangle.So how can i define height by given only A, B and C? Any suggestions for typing my code to look better is always welcome! :)
So, my code looks like this:
import java.text.DecimalFormat;
import java.util.Scanner;
public class MainTriangle {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double aX;
double aY;
double bX;
double bY;
double cX;
double cY;
System.out.println("-Distance between 3 points in coordinate system-");
System.out.println();
System.out.print("point A(x):");
aX = sc.nextDouble();
System.out.print("point A(y):");
aY = sc.nextDouble();
System.out.print("point B(x):");
bX = sc.nextDouble();
System.out.print("point B(y):");
bY = sc.nextDouble();
System.out.print("point C(x):");
cX = sc.nextDouble();
System.out.print("point C(y):");
cY = sc.nextDouble();
System.out.println();
sc.close();
double dX = bX - aX;
double dY = bY - aY;
double eX = cX - bX;
double eY = cY - bY;
double fX = cX - aX;
double fY = cY - aY;
double sD = Math.pow(dX, 2) + Math.pow(dY, 2);
double d = Math.sqrt(sD); // length of d (from point A to point B)
double sE = Math.pow(eX, 2) + Math.pow(eY, 2);
double e = Math.sqrt(sE); // length of e (from point B to point C)
double sF = Math.pow(fX, 2) + Math.pow(fY, 2);
double f = Math.sqrt(sF); // length of f (from point C to point A)
System.out.println("Distance from point A to point B is "+new DecimalFormat("##.##").format(d));
System.out.println();
System.out.println("Distance from point B to point C is "+new DecimalFormat("##.##").format(e));
System.out.println();
System.out.println("Distance from point C to point A is "+new DecimalFormat("##.##").format(f));
System.out.println();
double p = d+e+f; // (perameter)
System.out.println("Perameter of triangle ABC is "+new DecimalFormat("##.##").format(p));
}
}
double p = d + e + f;
double area = Math.sqrt( p * (p-d) * (p-e) * (p-f) );
double heightD = (2 * area) / d; //height of edge d
according to question; d, e and f are edges of the triangle. you can calculate area by knowing an edge and height of that edge or by knowing 3 edges lenghts. If you know all edges lenghts, you can get height of an edge
You want to find height of the triangle based on the given points, right? Every triangle has three heights, so you can calculate them using Heron's formula.
For any triangle with sides a, b, c and semiperimeter s = (a + b + c) / 2 the altitude from side a is given by: ha = (2*sqrt(s*(s-a)*(s-b)*(s-c)))/a
Note that a,b,c here are the lengths of the sides of the triangle.
Then you can check if any of the heights are zero.
The height of a 'real' triangle depends on which side is on the floor. But you are looking for a non-triangle. i.e. a non-triangle who's three points lie on a straight line.
To work this out you can simply work out the gradient of two of the 'sides'. If they are the same then you know you have a 'non-triangle'
gradient1 = (y2 -y1)/(x2 - x1)
gradient2 = (y3 -y1)/(x3 - x1)
If gradient1 == gradient2 then you have a 'non-triangle'. As double type arithmetic can lead to slight difference you might want to be able to tolerate minor difference in gradient (e.g. if the difference is < 0.0001 then it's a non-triangle)
Update: Probably also need to cater for divide by zero error too!
The height of the triangle is existent between three units.
The A) Base-A
The B) Base-B
The H) Height-C
A^2 + B^2 = C^2
I have 3 vertices of a triangle and I'm trying to find all the integer points that lie on the inside and ON THE SIDES of the triangle. I've tried numerous methods and they all succeed in finding the inside points, but fail in finding the points on the sides of the triangle. Currently I'm using barycentric coordinates:
private static boolean pointInTriangle(int[] p, int[] c1, int[] c2, int[] c3){
float alpha = ((c2[1] - c3[1])*(p[0] - c3[0]) + (c3[0] - c2[0])*(p[1] - c3[1])) /
((c2[1] - c3[1])*(c1[0] - c3[0]) + (c3[0] - c2[0])*(c1[1] - c3[1]));
float beta = ((c3[1] - c1[1])*(p[0] - c3[0]) + (c1[0] - c3[0])*(p[1] - c3[1])) /
((c2[1] - c3[1])*(c1[0] - c3[0]) + (c3[0] - c2[0])*(c1[1] - c3[1]));
float gamma = 1.0f - alpha - beta;
return ( (alpha>=0.0f) && (beta>=0.0f) && (gamma>=0.0f) );
For example, for vertices (0,0),(0,10),(10,10) this does find (10,8) but it also finds (11,8) which is not correct.
Can somebody help me?
Thanks in advance!
Use the code you alreay have to find if a position is inside the triangle. Then for the other part, if a point is on the line or not..
I would do it like this..
Check by calculating the distance between 2 vertices at a time.
Lets say we have vertices a, b and c. And the point p.
Check if p is on the line between a and b.
This can be done by measuring the distance between a -> p and p -> b.
If those two distances equals the distance of a -> b then it is on the line. If p should be off the line the distance will be longer.
Here is a method to caluclate distance (pythagoran teorem):
private static double GetDistance(double x1, double y1, double x2, double y2)
{
double a = Math.abs(x1-x2);
double b = Math.abs(y1-y2);
return Math.sqrt(a * a + b * b);
}
So I to create a method that checks if the point " ponto " is inside the triangle given by the points A,B,C as vertices.
So far I have this :
final double PRECISION = 0.1;
public boolean dentroDoTriangulo (Point A, Point B, Point C, Point ponto){
//total
double ABC = Math.abs ((A.x*(B.y-C.y)+B.x*(C.y-A.y)+ C.x*(A.y-B.y))/2);
//parcial
double ABP = Math.abs((A.x*(B.y-ponto.y)+B.x*(ponto.y-A.y)+ponto.x*(A.y-B.y))/2);
double APC = Math.abs (A.x*(ponto.y-C.y)+ponto.x*(C.y-A.y)+C.x*(A.y-ponto.y))/2;
double PBC = Math.abs (ponto.x*(B.y-C.y)+B.x*(C.y-ponto.y)+C.x*(ponto.y-B.y))/2;
double parciais = ABP + APC + PBC ;
return Math.abs(ABC - parciais) <= PRECISION;
}
I've already tried doing it like :
ABP +APC +PBC == ABC
Nothing either, can someone help me understand what am I doing wrong here ?
EDIT: Your code seems to work OK. Here's a Point class example in case that's where you are crashing.
public class Point {
float x;
float y;
Point() {
x = 0;
y = 0;
}
Point(float x, float y) {
this.x = x;
this.y = y;
}
}
Just in case, I propose another solution:
Check out this algorithm for determining if the point is inside a triangle.
I cannot see your Point class so I do not know if there is a bug there. I assume it is two floats for x&y coordinates. We'll assume it's ok.
Can you explain your algorithm a bit better? I looks like you are taking three areas of the sub-triangles and adding them up to compare against the original triangle (with PRECISION tolerance). Try the "SameSide" function three times as mentioned in hyperlink if you want--which takes two cross products and then the dot product of the results of the cross products to determine if a point is on the "correct side" of a line between any two of the vertices (there are three such lines).
Code snippet for algorithm:
boolean SameSide(p1, p2, a, b) {
int[] cp1 = CrossProduct(b - a, p1 - a);
int[] cp2 = CrossProduct(b - a, p2 - a);
if (DotProduct(cp1, cp2) >= 0) {
return true;
}
return false;
}
boolean PointInTriangle(p, a, b, c) {
if (SameSide(p, a, b, c) && SameSide(p, b, a, c) &&
SameSide(p, c, a, b) {
return true;
}
return false;
}
Where a, b, c are the vertices and p is the point. I recommend int [] to hold the vectors. You will need to write the helper functions to calculate vector manipulations.
I could not follow your algorithm, but you could send out horizontal (or any direction for that matter) rays in two directions from the point. If it hits the triangle in both directions, then the point will be inside the triangle. You will need to be careful of special conditions where the ray hits a vertex. That would be considered as hitting two lines on one side. But as long as the ray hits the triangle in both directions, the point will be inside.
So I used your code for method dentroDoTriangulo and stuck is inside a class. I used the Point class given above. Then I called your method using the quick and dirty code given below. It seems to work without any problems. Like #TNT says above, a test case would be helpful.
public class Caller {
public static void main(String[] args) {
Triangle myTraingle = new Triangle();
boolean isInside = myTraingle.dentroDoTriangulo(new Point(1,0), new Point(3,0), new Point(2,2), new Point(2,1));
if (isInside) {
System.out.println("Point is inside");
} else {
System.out.println("Point is outside");
}
}
}
i really need help with figuring out a velocity equation to launch a player from one X Y Z location to another. from looking at other threads i created the following code (the code doesn't work)
public void vJump(Entity entity, Location loc, double time)
{
this.entity = entity;
entity.setVelocity(getV(entity.getLocation(), loc, time));
}
private Vector getV(Location p1, Location p2, double t)
{
double x = p2.getX() - p1.getX();
double y = p2.getY() - p1.getY();
double z = p2.getZ() - p1.getZ();
double gravity = -14.266;
return new Vector(getVelocity(x,gravity,t), getVelocity(y,gravity,t), getVelocity(z,gravity,t));
}
private double getVelocity(double d, double a, double t)
{
a*=-.5;
a*=Math.pow(t,2);
d-=a;
return d/t;
}
i do not know the gravity in Minecraft nor do i know the movement friction. the problem with the code above is that it doesn't go in the right direction nor does it create the parabola effect i was looking for.
based on Nick Rhodes answer i removed gravity for all but the y (in minecraft, up and down is y). and then i doubled the velocity for all planes by 2 and it ended up working! here is the code. also i found out that gravity was actually 0.1.
public void vJump(Entity entity, Location loc, double time)
{
this.entity = entity;
entity.setVelocity(getV(entity.getLocation(), loc, time));
}
private Vector getV(Location p1, Location p2, double t)
{
double x = p2.getX() - p1.getX();
double y = p2.getY() - p1.getY();
double z = p2.getZ() - p1.getZ();
double gravity = 0.1;
return new Vector(getVelocity(x,0,t), getVelocity(y,gravity,t), getVelocity(z,0,t));
}
private double getVelocity(double d, double a, double t)
{
a*=-.5;
a*=Math.pow(t,2);
d-=a;
return 2*(d/t);
}
Part of the problem lies in the fact that gravity will only come into play for the z vector. There will be no gravitational force in the x or y directions. This may explain why your code produces movement in another direction than expected.
try (assuming that t is defined as the total time of transit):
return new Vector(getVelocity(x,0,t), getVelocity(y,0,t), getVelocity(z,gravity,t));