Check if point is on line in Java Swing - java

I have drawn a line and then a point, and then I want to check if the point is on the line or not. I have taken a line coordinate in array (as there was more than one line). I want to check the current point in on the last line or not?
if (positionX1 == positionX2 && positionY1 == positionY2) {
float m = line.getSlope(
drawLines[currentLines - 1][2], drawLines[currentLines - 1][3],
drawLines[currentLines - 1][0], drawLines[currentLines - 1][1]);
m = Float.parseFloat(df.format(m));
float c = line.getIntercept(
drawLines[currentLines - 1][2], drawLines[currentLines - 1][3],
drawLines[currentLines - 1][0], drawLines[currentLines - 1][1]);
c = Math.round(c);
m1 = line.getSlope(positionX2, positionY2,
drawLines[currentLines - 1][0], drawLines[currentLines - 1][1]);
m1 = Float.parseFloat(df.format(m1));
System.out.println(m + " " + m1);
c1 = line.getIntercept(positionX2, positionY2,
drawLines[currentLines - 1][0], drawLines[currentLines - 1][1]);
c1 = Math.round(c1);
if (m == m1 && ((c == c1) || (c == c1 - 1) || (c == c1 + 1))) {
System.out.println("Point is on Line");
}
}
Problem is when a point is near the starting point of line or when a line is about vertical values of m1 and c1 changes with big difference. So, there's a problem for detecting if a point on line or not. How can I check for this situation?

Line2D.ptSegDist(x1, y1, x2, y2, xP, yP) returns 0.0 if the point (xP, yP) is on the line segment from (x1, y1) to (x2, y2). Line2D.ptLineDist does the same thing for the infinite line.

Use the vector form of the distance from a point to a line where the line is x = a + t n.
If instead of a unit vector n you use a non-unit vector N, then d = ||(a - p) - ((a - p) · N) N / ( N · N) ||, which eliminates a square root.
Assuming that the arrays of floats you are using to describe lines are interpreted as { x1, y1, x2, y2 }, then a = ( x1, y1 ) and N = ( x2 - x1, y2 - y1 ).
If the calculated distance is comparable to the measurement or arithmetic errors, the point is on the line. Again, you don't need to calculate the square root in the modulus but can compare the squared value.

In terms of an algorithm, a line (other than one which is vertical which has equation like x = constant) has a form y = mx + b. If your point satisfies that equation, then it is on the line. So all you need to is find the slope value of the line, and its y-intercept and check to see if the point's x and y values satisfy the equation for each line.
EDIT:
As is pointed out in an above comment, you could use the point-slope form (with slope being (y2-y1)/(x2/x1)) instead of the slope-intercept form. This would give you an equation that depends solely on y,x and the start and end points of the lines which would be much easier to code out (since you define a line by its start and end points, at least in swing). The only reason I suggested the slope-intercept form was because you were already attempting to use it in your algorithm.

Related

Test if point is within line range on 2D space

This question is a bit hard to formulate so I'll start by showing this image:
I want to test if points (such as p1 and p2 on the image) are within the dotted lines that are perpendicular to the line at its limits. I know the coordinates of the points to test and the line's limits.
So for p1 it would be false, and for p2 it would be true.
What would be the most computationaly efficient way to calculate this?
I'm working with floats in Java.
This can be very efficiently done with the dot product:
This is positive if A has a component parallel to B, and negative if anti-parallel.
Therefore if you have a line segment defined by points A and B, and a test point P, you only need two dot product operations to test:
dot(A - B, P - B) >= 0 && dot(B - A, P - A) >= 0
EDIT: a graphical explanation:
The dot product can be shown to be:
Thus if θ > 90 then dot(A, B) < 0, and vice versa. Now for your problem:
In case 1, when dot(A - B, P - B) > 0 we say that P is on the correct side of the dotted line at B, and vice versa in case 2. By symmetry we can then do the same operation at A, by swapping A and B.
If the point to test (tp), together with start point (sp) and end point (ep) of the range, form an obtuse triangle and you can conclude that it is out of range.
https://en.wikipedia.org/wiki/Acute_and_obtuse_triangles
A special case would be tp is same slope as sp and ep, then you calculate the 2 distances:
distSpAndTp - distance between sp and tp
distEpAndTp - distance between ep and tp
If the sum of these 2 distances = distance between sp and ep, then tp is in range, otherwise it is out of range.
The best approach would be to first create a rectangle Rect (of android.graphics package), with x and width being the beginning and end of line, and y and height being the beginning and end of screen height.
Then use the Rect method Rect.contains(int x, int y) to check if the point coordinates lie within.
For floats, use RectF class instead.
This approach involves using 2D vectors (which you should have been using anyway, makes working in any coordinate system a lot easier) and the dot (scalar) product. It does not require any relatively expensive operations like the square root or trignometic functions, and therefore is very performant.
Let A and B be the start and end points (by point I mean a vector representing a position in 2D space) of the line segment, in any order. If P is the point to test, then:
If dot(PA, AB) and dot(PB, AB) have the same sign, the point lies outside the region (like p1 in your example).
If the dot products above have opposite signs, the point lies inside the region (like p2).
Where PA = A - P, PB = B - P and AB = B - A.
This condition can be surmised as follows:
if dot(PA, AB) * dot(PB, AB) <= 0 {
// Opposite signs, inside region
// If the product is equal to zero, the point is on one of the dotted lines
}
else {
// Same signs, outside region
}
Let's say, x1 is the beginning of the line and x2 is the end. Then ax is the dot in an horizontal plan and; y1, y2 and ay in vertical plan.
if((ax >= x1 && ax <= x2) && (ay >= y1 && ay <= y2)){ // do your work
}
There are a few answers already but there is another solution that will give you the unit distance on the line segment that the points is perpendicular to.
Where then line is x1,y1 to x2,y2 and the point is px,py
Find the vector from line start to end
vx = x2 - x1;
vy = y2 - y1;
And the vector from the line start (or end) to the point
vpx = px - x1;
vpy = py - y1;
And then divide the dot product of the two vectors by the length squared of the line.
unitDist = (vx * vpx + vy * vpy) / (vx * vx + vy * vy);
If the perpendicular intercept is on the line segment then unitDist will be 0 <= unitDist <= 1
In shortened form
x2 -= x1;
y2 -= y1;
unitDist = (x2 * (px - x1) + y2 * (py - y1)) / (x2^2 + y2^2);
if (unitDist >= 0 && unitDist <= 1) {
// point px,py perpendicular to line segment x1,y1,x2,y2
}
You also get the benefit of being able to get the point on the line where the intercept is.
p2x = vx * unitDist + x1;
p2y = vy * unitDist + y1;
And thus the distance that the point is from the line (note not line segment but line)
dist = hypot(p2x - px, p2y - py);
Which is handy if you are using a point to select from many lines by using the minimum distance to determine the selected line.
This can be solved nicely using complex numbers.
Let a and b the endpoints of the segment. We use the transformation that maps the origin 0 to a and the point 1 to b. This transformation is a similarity and its expresion is simply
p = (b - a) q + a
as you can verify by substituting q=0 or q=1. It maps the whole stripe perpendicular to the given segment to the stripe perpendicular to the segment 0-1.
Now the inverse transform is obviously
q = (p - a) / (b - a),
and the desired condition is
0 <= Re((p - a) / (b - a)) <= 1.
To avoid the division, you can rewrite
0 <= Re((p - a) (b - a)*) <= |b-a|²
or
0 <= (px - ax)(bx - ax) + (py - ay)(by - ay) <= (bx - ax)² + (by - ay)².

Easiest way to check integer is either +1 or -1 Java

I want to the difference between two integers is +1 or -1. I think my code below is very clumsy to write. Is there any shorter way to check if two integers are just 1 apart? This seems like a simple solution, but I have 2d array of coordinates I want to check if two coordinates in the direct vicinity (either north, east, west, or south) of each other are selected.
Yes they are standard coordinates as the top left corner is 0,0, and the bottom right is 7,7. Essentially if one coordinate is selected, I wanted to check if there exists another coordinate where x or y differs by (+-) one.
//Since it's a 2d array, I am doing a nested loop. But comparison is below
int x1 = range(0,8); //all ints are range from 0 to 7
int y1 = range(0,8); //represent the current indices from the loop
int x2 = ...; //x2 represents the x index value of the previous loop
int y2 = ...; //y2 represents the y index value of the previous loop
if(x1+1 == x2){
Found an existing X coord just larger by one
}else if (x1-1 == x2){
Found an existing X coord smaller, and differ by one
}else if(y1+1 == y2){
Found an existing Y coord just 1 larger
}else if(y-1 == y2){
Found an existing Y coord just 1 smaller
}
Since we don't care whether the difference between x1 and x2 is 1 or -1, we can use the absolute value:
if (Math.abs(x1 - x2) == 1){
// x coordinates differ by 1
} else if (Math.abs(y1 - y2) == 1){
// y coordinates differ by 1
}
This works because if x1 is less than x2, then Math.abs(x1 - x2) = Math.abs(-1) = 1.
The simplest way I can think of is:
boolean differenceOfOne = Math.abs(n1 - n2) == 1;
Where n1 and n2 are numbers.
How about:
Math.abs(difference)==1
You can use Math.abs to evaluate the difference:
boolean isDifferenceOne = Math.abs(x1 - x2) == 1 && Math.abs(y1 - y2) == 1

linear equation java [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am trying to convert the equation below into programming code. The purpose is to find the intersecting point of the two lines. And to pront
(y1 - y2)x - (x1 - x2)y = (y1 - y2)x1 - (x1 - x2)y1
(y3 - y4)x - (x3 - x4)y = (y3 - y4)x3 - (x3 - x4)y3
I've been told to use cramers rule, but cramers rule has 6 diff variables. I'll be starting off with 4 different points as 8 variables (x1, y1, x2, y2, x3, y3, x4, y4)
I'm using Java. Any help would be appreciated. All the asked questions on this site are for different types of linear equations with long complicated code, I didnt find anything that was relevant to me.
This is what I have, not much but the transition from the above equation to something programmable really stumps me.
import java.util.Scanner;
public class E325 {
public static void main(String[] args) {
/*
* The purpose of this program is to find the intersect
* of two lines given by the user by four points
*
* Get the four points. x1,y1 x2,y2 x3,y3 x4,y4
*/
Scanner input = new Scanner(System.in);
System.out.print("Enter x1 y1, x2 y2, x3 y3, x4 y4: ");
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
double x3 = input.nextDouble();
double y3 = input.nextDouble();
double x4 = input.nextDouble();
double y4 = input.nextDouble();
}
}
I don't know matrices, so I would solve it a different way.
You know enough to calculate m and b for each line
m = (y2-y1)/(x2-x1)
b = y1 - m(x1)
Calculate m and b for one line and m' and b' for the other.
Now at the intersection, x,y are the same on the two lines, so
y = mx + b and y = m'x + b'. Therefore
mx + b = m'x + b'
x = (m'x + b' - b)/m
Plug x into mx + b to get y for that x.
You still have to ensure that the x,y you have found are on your line SEGMENTS; unless the lines are parallel, they will intersect somewhere, but not necessarily between the endpoints of the line segments you've started with.
(y1 - y2)x - (x1 - x2)y = (y1 - y2)x1 - (x1 - x2)y1
(y3 - y4)x - (x3 - x4)y = (y3 - y4)x3 - (x3 - x4)y3
I've been told to use cramers rule, but cramers rule has 6 diff variables.
No. That's completely wrong. Cramer's rule is a simple technique to solve equations of the form Ax = b, but where A is a NxN matrix, and x and b are N vectors. What you need to do is to formulate those two equations as a matrix expression. I'll give you the left hand side that corresponds to the above. I'll leave the right hand side and the application of Cramer's rule up to you.
A * x = b
⌈ y1-y2 -(x1-x2) ⌉ ⌈ x ⌉
| | * | |
⌊ y3-y4 -(x3-x4) ⌋ ⌊ y ⌋
Multiplying that matrix A and the vector [x,y] yields
⌈ y1-y2 -(x1-x2) ⌉ ⌈ x ⌉ ⌈ (y1-y2)*x - (x1-x2)*y ⌉
| | * | | = | |
⌊ y3-y4 -(x3-x4) ⌋ ⌊ y ⌋ ⌊ (y3-y4)*x - (x3-x4)*y ⌋
Note that this result is exactly the same as the left hand sides of your pair of equations.
A line passes through two points.
You have four points and two lines.
The equation of a line is well known:
y = m*x + b
where m is the slope and b is the y-intercept.
If you have two lines, they look like this:
-m1*x + y = b1
-m2*x + y = b2
You can see the matrix equation, can't you?
[ -m1 1 ]{x} = {b1}
[ -m2 1 ]{y} {b2}
Invert this to solve for (x, y) where the two lines intersect. If you can't invert the matrix, it means they don't intersect.
Cramer's Rule? Sure, it's easy to write for a 2x2 case. LU decomposition would be more general.

Line2D Java - Get coordinates where y = value?

Given a line segment defined by (x1, y1) and (x2, y2), find the location on the line where y = a certain value.
I understand I could obtain the equation of the line, then solve using simultaneous equations, but is this possible using Line2D or any other Java classes?
Any suggestions or comments would be appreciated!
Kelvin.
I don't think there's anything in the Java API to actually calculate the intersection. The closest you can get, I think, is to use Line2D to test whether the line segment intersects the (vertical) line y = k for some constant k:
Line2D line = new Line2D.Double(x1, y1, x2, y2);
if (line.intersectsLine(Double.MIN_VALUE, k, Double.MAX_VALUE, k)) {
double x = (x2 - x1) * (k - y1) / (y2 - y1);
// intersection is at (x, k)
} else {
// intersection is outside extend of the line segment
}
However, it would probably be more efficient to just check that y1 != y2, compute the intersection, and then check whether the x coordinate is in the range [x1, x2].
I would suggest apache commons math for tasks like this.
http://commons.apache.org/math/apidocs/index.html
There are a number of ways you can do this. One way would be
org.apache.commons.math3.geometry.euclidean.twod.Line lineOne = new org.apache.commons.math3.geometry.euclidean.twod.Line(p,angle);
org.apache.commons.math3.geometry.euclidean.twod.Line horizontalLine = new org.apache.commons.math3.geometry.euclidean.twod.Line(new vector2d(0,yToSolveFor),pi/2);
Vector2D intersection=lineOne.intersect(horizontalLine);
intersection.getX(); // The answer

Find point farthest from line

I have an array of points, as well as two more points (A and B). The last two points form a line, and I'm trying to find which of the points in my array are furthest from the line. How would I do this in Java?
I'm wondering if it's something along the lines of finding the distance from A and B, but that doesn't sit well in my head.
Additional info:
I think it's a line segment. Given this is QuickHull, I don't know if it makes a difference.
I've never been the greatest when it comes to math and formulas, so more explanation is better. Thanks!
Note that each 3 points [a,b,p] for each p in the array form a trianle, whose area is denoted by: (ab) * h /2 [where h is the distance from p to ab]
You can compute the area these trianles create, and select the minimal. Since ab is constant for all - it guarantees that the trianle with the minimal area will also have the minimal h.
You can find it [the area of each triangle] using
T=(1/2)* abs((x_a - x_p) * (y_b-y_a) - (x_a - x_b)* (y_p - y_a))
[where x_a,x_b,x_p and y_a,y_b,y_p are the x,y coordinates of a,b,p respectively].
Though I find this method very elegant, I believe there are better
ways to do it.
ArrayList<Point> points=new ArrayList();//YOUR POINTS
Point a=new Point(1,1);
Point b=new Point(1,1);
Point ABcenter=new Point((a.x+b.x)/2,(a.y+b.y)/2);//THE CENTER OF THE A AND B POINTS ,USE A OR B IF YOU WANT
int furthestid=0;
float furthestdis=0;
for(int c=0;c<points.size();c++)
{
if(calculate_distance(ABcenter.x,ABcenter.y,points.get(c).x,points.get(c).y)>furthestdis)
{
furthestid=c;
}
}
//closestid now contains the id of the furthest point ,use it like this points.get(c).x ...
public static double calculate_distance (float x1,float y1,float x2 ,float y2){
return Math.sqrt((((x1-x2) * (x1-x2)) + ((y1- y2) * (y1- y2))));
}
I'm assuming you mean the Euclidean distance. If you're working in the plane, then the answer is simple.
First, compute the equation of the line in the form
ax + by + c = 0
In slope-intercept form, this is the same as
y = (-a/b)x + (-c/b)
Now compute the distance from any point (p,q) to the line by
|a*p + b*q + c| / (a^2 + b^2)^(1/2)
For more than 2 dimensions, it's probably easiest to think in terms of parametrized vectors. This means think of points on the line as
p(t) = (A1 + (B1-A1)*t, A2 + (B2-A2)*t, ..., An + (Bn-An)*t)
where the two points are A = (A1,...,An) and B = (B1,...,Bn). Let X = (X1,...,Xn) be any other point. Then the distance between X and p(t), the point on the line corresponding to t, is the square root of
[(A1-X1) + (B1-A1)t]^2 + ... + [(An-Xn) + (Bn-An)t]^2
The distance to the line is the distance to p(t) where t is the unique value minimizing this distance. To compute that, just take the derivative with respect to t and set it to 0. It's a very straightforward problem from here, so I'll leave that bit to you.
If you want a further hint, then check out this link for the 3-dimensional case which reduces nicely.
If the problem is as you have stated it, you can't do much better then computing the distance for each point and choosing the smallest of these.
However you can simplify the calculation of the distance a bit by using a generalized line equation for the line passing through A and B. This would be an equation of the form ax + by + c = 0
You can compute such equation for a line passing through two arbitrary points quite easily:
x * (A.y - B.y) + y * (B.x - A.x) + A.x * B.y - A.y * B.x,
i.e. a = A.y - B.y, b = B.x - A.x and c = A.x * B.y - A.y * B.x
Now that you have computed such equation for the line, you can compute the distance from an arbitrary point P in the plane to the line a * x + b * y + c by substituting x and y with the coordinates of P:
abs(a * P.x + b * P.y + c) / sqrt(a * a + b * b). But as the denominator will be the same for all points, you may igonore it and simply choose the point for which abs(a * P.x + b * P.y + c) is smallest
Here is a link that explains how to compute 2-d distance to a line once you have it's generalized equation.
I'm assuming you talking about line segment not line. First you should find your points distance from your line segment, and you can do it, as the way suggested in this similar question, after that find minimum/maximum distance over all inputs.
Edit: Also from this top coder article you can find distance simply:
//Compute the dot product AB ⋅ BC
int dot(int[] A, int[] B, int[] C){
AB = new int[2];
BC = new int[2];
AB[0] = B[0]-A[0];
AB[1] = B[1]-A[1];
BC[0] = C[0]-B[0];
BC[1] = C[1]-B[1];
int dot = AB[0] * BC[0] + AB[1] * BC[1];
return dot;
}
//Compute the cross product AB x AC
int cross(int[] A, int[] B, int[] C){
AB = new int[2];
AC = new int[2];
AB[0] = B[0]-A[0];
AB[1] = B[1]-A[1];
AC[0] = C[0]-A[0];
AC[1] = C[1]-A[1];
int cross = AB[0] * AC[1] - AB[1] * AC[0];
return cross;
}
//Compute the distance from A to B
double distance(int[] A, int[] B){
int d1 = A[0] - B[0];
int d2 = A[1] - B[1];
return sqrt(d1*d1+d2*d2);
}
//Compute the distance from AB to C
//if isSegment is true, AB is a segment, not a line.
double linePointDist(int[] A, int[] B, int[] C, boolean isSegment){
double dist = cross(A,B,C) / distance(A,B);
if(isSegment){
int dot1 = dot(A,B,C);
if(dot1 > 0)return distance(B,C);
int dot2 = dot(B,A,C);
if(dot2 > 0)return distance(A,C);
}
return abs(dist);
}
I think code has self explanation, if you are familiar with basic geometry, but if you aren't familiar, you should to read the article, if there is any problem for you we can help you.

Categories

Resources