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
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 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 need to check if a circle is intersected by a line algebraically. I've attempted to do this by taking a perpendicular line to the infinite that passes through the center of the circle. I then measure the perpendicular against the radius of the circle, and it states that the line does not intersect if d > r.
import java.util.Scanner;
public class LineCircle_Intersection {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double p1x, p2x, p1y, p2y, cx, cy, r;
System.out.print("Enter p1x: ");
p1x = in.nextDouble();
System.out.print("Enter p1y: ");
p1y = in.nextDouble();
System.out.print("Enter p2x: ");
p2x = in.nextDouble();
System.out.print("Enter p2y: ");
p2y = in.nextDouble();
System.out.print("Enter cx: ");
cx = in.nextDouble();
System.out.print("Enter cy: ");
cy = in.nextDouble();
System.out.print("Enter r: ");
r = in.nextDouble();
double m = (p2y - p1y) / (p2x - p1x);
double pem = -1 / m;
double pey = pem + p1y; // pe = perpendicular line (used E instead of L because lowercase l looks too much like 1)
double pex = (pey - p1y) / pem;
double d = Math.sqrt((pex - cx) * (pex - cx) + (pey - cy) * (pey - cy));
if (d <= r) {
if (d == r) {
System.out.println("Line intersects the circle at one point.");
} else {
System.out.println("Line intersects the circle at two points.");
}
} else if (m == 1) {
if (d <= r) // There's a problem in this area. I'm not sure what, or how to fix it.
{
if (d == r) {
System.out.println("The line intersects the circle at one point.");
} else {
System.out.println("Line intersects the circle at two points.");
}
} else {
System.out.println("Line does not intersect the circle.");
}
} else {
System.out.println("Else."); //This says "Else" for testing purposes.
}
}
}
Here's where things start to go wrong. There are several points that can be input that clearly should intersect or not intersect, but the program frequently says otherwise.
Will be working on this for a few hours, so if I solve it before someone else I'll post an update and how I solved it.
The principle is correct, but I won't verify your computations.
In short:
boolean intersects=false, is_tangent=false;
double p2p1x=p2x-p1x, p2p1y=p2y-p1y;
double p1p2DistSq=p2p1x*p2p1x+p2p1y*p2p1y;
if(p1p2DistSq > 1e-12) { // well-behaved line
double p1cx=p1x-cx, p1cy=p1y-cy;
double crossprod=p2p1x*p1cy-p2p1y*p1cx;
double distCenterToLineSquare=crossprod*crossprod/p1p2DistSq;
double rSquare=r*r;
intersects = (distCenterToLineSquare <= rSquare); // r is radius
// for practical purposes, if the relative error of
// (r-dist) is 1e-6 of r, we might consider the line as tangent.
is_tangent = Math.abs(distCenterToLineSquare - rSquare)/rSquare < 1e-12;
} // cowardly refusing to deal with ill-configured lines
In details:
Preliminary (and take this as an easy way to deduce the distance between a point and a line if you don't have internet at the moment)
The cross-product between two vectors
{ax, ay} x {bx, by} = |a|*|b|*sin(angle_between_dir_a_and_b)
Also this cross-product is (ax*by-ay*bx)
Now, assume a line passing through P1 with direction defined by the unitary vector {ux, uy}. The distance of a point {cx. cy} to this line will be
dist=sin(alpha)*|P1-C|
where |P1-C| is the distance between C and P1 and alpha is the angle between the direction {ux, uy} and the direction of the line {P1,C}. Let's denote with {vx,vy} the unitary direction of {P1,C} line. In this case, since u and v are unitary (|u|=|v|=1)
sin(alpha)=ux*vy-uy*vx
Thus
dist=(ux*vy-uy*vx)*|P1-C|
Plugging in the vx, vy using
vx=(P1x-Cx)/|P1-C| // it's a unitary vector
vy=(P1y-Cy)/|P1-C|
results in
dist=ux*(P1y-Cy)-uy*(P1x-Cx)
Now, the only thing that remains, is ux and uy. Since your line is defined by P1 and P2
ux=(P2x-P1x)/|P1-P2|
uy=(P2y-P1y)/|P1-P2|
(with |P1-P2| again, the distance between P1 and P2)
dist=( (P2x-P1x)*(P1y-Cy)-(P2y-P1y)*(P1x-Cx) )/ |P1-P2|
Ok, |P1-P2| requires an sqrt evaluation and we can get rid of it by comparing your dist^2 with the radius^2
The 'line intersect circle' then becomes
double p1cx=p1x-cx, p1cy=p1y-cy;
double p2p1x=p2x-p1x, p2p1y=p2y-p1y;
double crossprod=p2p1x*p1cy-p2p1y*p1cx;
double distCenterToLineSquare=crossprod*crossprod/(p2p1x*p2p1x+p2p1y*p2p1y);
boolean intersects= (distCenterToLineSquare <= r*r); // r is radius
I have two points store in two variable, which forms a line. I want to find a point which is perpendicular to that line from one end point in that line.
Suppose I have two points P1(x1,y1) and P2(x2,y2) then i want to find a third point P3 such that line(P1-P2) is perpendicular to line(P2,P3) and intersect at P2.
First, the angle:
public static double angle (double x1, double y1, double x2, double y2) {
double xdiff = x1 - x2;
double ydiff = y1 - y2;
//double tan = xdiff / ydiff;
double atan = Math.atan2(ydiff, xdiff);
return atan;
}
To get the perpendicular, you must add PI/2 to the angle of the line defined by your two points.
Once you have that angle, the formula is:
x = interceptPt.x + sin(perp_angle) * distance;
y = interceptPt.y + cos(perp_angle) * distance;
If you want to use Java I can recommend to use JTS. Create a LineSegment and use the pointAlongOffset method. Given Points p1 and p2 the code would look like that:
// create LineSegment
LineSegment ls = new LineSegment(p1.getX(), p1.getY(), p2.getX(), p2.getY());
// perpendicular distance to line
double offsetDistance = 10;
// calculate Point right to start point
Coordinate startRight = ls.pointAlongOffset(0, offsetDistance);
// calculate Point left to start point
Coordinate startLeft = ls.pointAlongOffset(0, -offsetDistance);
// calculate Point right to end point
Coordinate endRight = ls.pointAlongOffset(1, offsetDistance);
// calculate Point left to end point
Coordinate endLeft = ls.pointAlongOffset(1, -offsetDistance);
ControlAltDel is already answered but he did a mistake, replaced cos to sin
x = interceptPt.x + cos(angle + 90) * distance;
y = interceptPt.y + sin(angle + 90) * distance;
x,y is point away from (interceptPt.x,interceptPt.y) at (distance) .
(interceptPt.x,interceptPt.y) is point in your line where perpendicular start to drawn.
angle = your line angle with horizontal axis
I got the answer at http://jsfiddle.net/eLxcB/2/
// Start and end point
var startX = 120
var startY = 150
var endX = 180
var endY = 130
R.circle(startX,startY,2);
// Calculate how far above or below the control point should be
var centrePointX = startX
var centrePointY = startY;
// Calculate slopes and Y intersects
var lineSlope = (endY - startY) / (endX - startX);
var perpendicularSlope = -1 / lineSlope;
var yIntersect = centrePointY - (centrePointX * perpendicularSlope);
// Draw a line between the two original points
R.path('M '+startX+' '+startY+', L '+endX+' '+endY);
// Plot some test points to show the perpendicular line has been found
R.circle(100, (perpendicularSlope * 100) + yIntersect, 2);
You can store your points in vec2d, then use some mathematical equations to get the perpendicular point.
vec2d getPerpendicularPoint(vec2d A, vec2d B, float distance)
{
vec2d M = (A + B) / 2;
vec2d p = A - B;
vec2d n = (-p.y, p.x);
int norm_length = sqrt((n.x * n.x) + (n.y * n.y));
n.x /= norm_length;
n.y /= norm_length;
return (M + (distance * n));
}
I have two GPS coordinates which link together to make a line. I also have a GPS point which is near to, but never exactly on, the line. My question is, how do I find the nearest point along the line to the given point?
Game Dev has an answer to this, it is in C++ but it should be easy to port over. Which CarlG has kindly done (hopefully he does not mind me reposting):
public static Point2D nearestPointOnLine(double ax, double ay, double bx, double by, double px, double py,
boolean clampToSegment, Point2D dest) {
// Thanks StackOverflow!
// https://stackoverflow.com/questions/1459368/snap-point-to-a-line-java
if (dest == null) {
dest = new Point2D.Double();
}
double apx = px - ax;
double apy = py - ay;
double abx = bx - ax;
double aby = by - ay;
double ab2 = abx * abx + aby * aby;
double ap_ab = apx * abx + apy * aby;
double t = ap_ab / ab2;
if (clampToSegment) {
if (t < 0) {
t = 0;
} else if (t > 1) {
t = 1;
}
}
dest.setLocation(ax + abx * t, ay + aby * t);
return dest;
}
Try this:
ratio = (((x1-x0)^2+(y1-y0)^2)*((x2-x1)^2 + (y2-y1)^2) - ((x2-x1)(y1-y0) - (x1-x0)(y2-y1))^2)^0.5
-----------------------------------------------------------------------------------------
((x2-x1)^2 + (y2-y1)^2)
xc = x1 + (x2-x1)*ratio;
yc = y1 + (y2-y1)*ratio;
Where:
x1,y1 = point#1 on the line
x2,y2 = point#2 on the line
x0,y0 = Another point near the line
xc,yx = The nearest point of x0,y0 on the line
ratio = is the ratio of distance of x1,y1 to xc,yc and distance of x1,y1 to x2,y2
^2 = square
^0.5 = square root
The formular is derived after we find the distant from point x0,y0 to line (x1,y1 -> x2,y3).
See here
I've test this code here (this particular one I gave you above) but I've used it similar method years ago and it work so you may try.
You can use JTS for that.
Create a LineSegment (your line)
Create a Coordinate (the point you want to snap to the line)
Get Point on the line by using the closestPoint method
Very simple code example:
// create Line: P1(0,0) - P2(0,10)
LineSegment ls = new LineSegment(0, 0, 0, 10);
// create Point: P3(5,5)
Coordinate c = new Coordinate(5, 5);
// create snapped Point: P4(0,5)
Coordinate snappedPoint = ls.closestPoint(c);