For a given line of an equation y = mx + c where m is the gradient and c is the y-intercept. How would I determine the "edge-points" on a graph?
To clarify what I mean by "edge-points", I've added an example below.
The edge-points are circled in red. To determine the edge-points here it would simply be (0, c) & (maximum x-value, m * maximum x-value + c). However, the problem arises when I consider lines with a different m value. For example:
I can't apply the same logic here, instead the edge-points would be ((maximum y-value - c) * m, maximum y-value) & (-c * m, 0), which was derived from the equation y = mx + c. So my question is how would I determine these 2 edge-points given any m or c? Is there a certain pattern I'm not seeing here?
You need to solve 4 simple linear equations (not equation system!):
y = m * 0 + c = c
y = m * maxX + c
0 = m * x + c
maxY = m * x + c
and get points of intersections with axes and with max lines. Then filter out points with negative coordinates and too large ones, because you want only the 1st quadrant
The first one equation is already solved y=c
The second gives point of intersection with right vertical line
The third gives point of intersection with OX axis
The fourth gives point of intersection with top horizontal line
Example:
maxX = 5
maxY = 5
line y = 2 *x - 1
x0, y0 = 0, -1
x1, y1 = 5, 9
x2, y2 = 1/2, 0
x3, y3 = 2, 5
First pair contains negative coordinate y=-1
Second pair contains y=9 > maxY
Third and fourth ones fulfill your constraints.
So this line gives segment (1/2, 0)-(2, 5) (like near vertical segment at your second picture)
This algo might be considered as simple kind of line clippping by rectangle
For the line to be in the given rectangle there is a constraint given by the x values and a constraint given by the y values.
The x constraint trivially leads to an interval in which the x values must be.
The y constraint also gives you such an interval for the x values but only after some easy calculation.
Now determine the intersection of the two intervals (which may also be empty).
Related
A coworker gave me this problem to try out my knowledge:
Consider two points, 1 and 2, having coordinates (x1, y1) and (x2, y2), respectively. In the same plane as these two points is a vertical line whose top and bottom are represented by (xTop, yTop) and (xBot, yBot), respectively. The two points may be on opposite sides of the wall, on the same side of the wall, or directly above/below the wall. For simplicity, neither of the points can be directly on the wall. A line is drawn from point 1 to point 2; if an intersection on the wall (the vertical line) occurs, it will occur at point (xInt, yIint).
Given two points and one wall, write an algorithm to determine if the two points can see one another. This can only occur if the line drawn from point 1 to point 2 does not touch the wall.
I correctly identified that if both points' x-values are less/greater than that of the wall's, they can see one another. The same goes for the y-values. I believe that there is a lot of geometry involved in this problem. But, I'm an old man, just getting back into programming for fun and this is really trying for me to comprehend. Any help would be immensely appreciated. Thank you.
-Jon N.
the equation for a line is y = mx + b, where m is the slope, and b is the y-intercept.
To determine if a line between two points intersects another (in your case vertical) line, first determine the slope of the line that connects the two points.
m = slope = (rise/run) = (y2 - y1)/(x2 - x1)
next, determine the y-intercept.
given (x1, y1) is on the line, and y = mx + b is the equation for a line, then y1 = mx1 + b. Since we know y1, x1, and m, we can solve for b.
b = y-intercept = y1 - mx1 = y1 - ((y2 - y1)/(x2 - x1))x1
Now, to determine if the line intercepts the wall, simply put in the x-coordinate for the wall into the equation for the line connecting the two points, and if the result is outside of the range of y values for the wall, then it does not intercept the wall (the two points can see each other).
Y#wall = mxbot + b
If YBot <= Y#wall <= YTop, then the wall is between the two points.
Hope this helps you!
Like many geometric algorithms, there are a bunch of special cases. Let's make a table. L means left of the wall, A means above, B means below, and R means right. Y means yes, ? means maybe, n means no (existence of an intersection).
L A B R
L n n n ?
A n n Y n
B n Y n n
R ? n n n
When one point is to the left and the other is to the right, we compute the intersection with the line containing the wall and check whether it's in the wall.
Code:
def intersects(x1, y1, x2, y2, wallx, wallymin, wallymax):
if (x1 < wallx and x2 > wallx) or (x1 > wallx and x2 < wallx):
iy = ((x2 - wallx) * y1 + (wallx - x1) * y2) / (x2 - x1)
return iy >= wallymin and iy <= wallymax
elif x1 == wallx and x2 == wallx:
return (y1 < wallymin and y2 > wallymax) or (y1 > wallymax and y2 > wallymin)
else:
return False
I'm working on a project in Matlab and need to find the area between two lines inside of the square [-1,+1]x[-1,+1] intersecting in a point (xIntersection,yIntersection). So the idea is to subtract the two lines and integrate between [-1, xIntersection] and [xIntersection, +1], sum the results and if it's negative, change its sign.
For details on how I find the intersection of the two lines check this link.
I'm using Matlab's function integral(), here a snippet of my code:
xIntersection = ((x_1 * y_2 - y_1 * x_2) * (x_3 - x_4) - (x_1 - x_2) * (x_3 * y_4 - y_3 * x_4) ) / ((x_1 - x_2) * (y_3 - y_4) - (y_1 - y_2) * (x_3 - x_4));
d = #(x) g(x) - f(x);
result = integral(d, -1, xIntersection) - int( d, xIntersection, 1)
if(result < 0),
result = result * -1;
end
Note that I defined previously in the code g(x) and f(x) but haven't reported it in the snippet.
The problem is that I soon realized that the lines could intersect either inside or outside of the square, furthermore they could intersect the square on any of its sides and the number of possible combinations grows up very quickly.
I.e.:
These are just 4 cases, but considering that f(+1), f(-1), g(+1), g(-1) could be inside the interval [-1,+1], above it or under it and that the intersection could be inside or outside of the square the total number is 3*3*3*3*2 = 162.
Obviously in each case the explicit function to integrate in order to get the area between the two lines is different, but I can't possibly think of writing a switch case for each one.
Any ideas?
I think my answer to your previous question still applies, for the most part.
If you want to compute the area of the region bounded by the smaller angle of the two lines and the boundaries of the square, then you can forget about the intersection, and forget about all the different cases.
You can just use the fact that
the area of the square S is equal to 4
the value of this integral
A = quadgk(#(x) ...
abs( max(min(line1(x),+1),-1) - max(min(line2(x),+1),-1) ), -1, +1);
gives you the area between the lines (sometimes the large angle, sometimes the small angle)
the value of of min(A, S-A) is the correct answer (always the small angle).
Assuming “between the lines” means “inside the smaller angle formed by the lines”:
With the lines l and h, S := [-1,+1]x[-1,+1] and B as the border of S.
Transform l to the form l_1 + t*l_2 with l_1 and l_2 beeing vectors. Do the same for h.
If the intersection is not inside S, find the 4 intersections of l and h with B. Sort them so you get a convex quadrilateral. Calculate its area.
Else:
Find the intersection point p and find the intersection angle α between l_2 and h_2. and then check:
If α in [90°,180°] or α in [270°,360°], swap l and h.
If α > 180°, set l_2 = −l_2
Set l_1 := h_1 := p. Do once for positive t and negative t
(forwards and backwards along l_2 and h_2 from p):
Find intersections s_l and s_h of l and h with B.
If on same border of B: compute area of triangle s_l, s_h, p
If on adjacent borders of B: find the corner c of B in between the hit borders and once again sort the four points s_l, s_h, p and c so you get an convex quadrilateral and calculate it’s area.
If on opposite borders, find the matching side of B (you can do this by looking at the direction of s_l-p). Using its two corner points c_1 and c_2, you now have 5 points that form a polygon. Sort them so the polygon is convex and calculate its area.
This is still quite a few cases, but I don’t think there’s a way around that. You can simplify this somewhat by also using the polygon formula for the triangle and the quadrilateral.
How to sort the points so you get a convex polygon/quadrilateral: select any one of them as p_1 and then sort the rest of the points according to angle to p_1.
If you define an intersection function and a polygon_area that takes a list of points, sorts them and returns the area, this algorithm should be rather simple to implement.
edit: Image to help explain the comment:
Hey guys thanks for your answers, I also thought of an empirical method to find the area between the lines and wanted to share it for the sake of discussion and completeness.
If you take a large number of random points within the square [-1,+1]x[-1,+1] you can measure the area as the fraction of the points which fall in the area between the two lines.
Here's a little snippet and two images to show the different accuracy of empirical result obtained with different number of points.
minX = -1;
maxX = +1;
errors = 0;
size = 10000;
for j=1:size,
%random point in [-1,+1]
T(j,:) = minX + (maxX - minX).*rand(2,1);
%equation of the two lines is used to compute the y-value
y1 = ( ( B(2) - A(2) ) / ( B(1) - A(1) ) ) * (T(j,1) - A(1)) + A(2);
y2 = (- W(1) / W(2)) * T(j,1) -tresh / W(2);
if(T(j,2) < y1),
%point is under line one
Y1 = -1;
else
%point is above line one
Y1 = +1;
end
if(T(j,2) < y2),
%point is under line two
Y2 = -1;
else
%point is above line two
Y2 = +1;
end
if(Y1 * Y2 < 0),
errors = errors + 1;
scatter(T(j,1),T(j,2),'fill','r')
else
scatter(T(j,1),T(j,2),'fill','g')
end
end
area = (errors / size) / 4;
And here are two images, it sure takes longer than the solution posted by #Rody but as you can see you can make it accurate.
Number of points = 2000
Number of points = 10000
I am given 2 points inside a circle. I have to find a point on the circle (not inside, not outside) so that the sum of the distances between the given 2 points and the point i found is minimum. I only have to find the minimum distance, not the position of the point.
It is a minimization problem:
minimize sqrt((x1-x0)^2 + (y1-y0)^2) + sqrt((x2-x0)^2 + (y2-y0)^2)
^ ^
(distance from point1) (distance from point 2)
subject to constraints:
x1 = C1
y1 = C2
x2 = C3
x4 = C4
x0^2 + y0^2 = r^2
(assuming the coordinates are already aligned to the center of the circle as (0,0)).
(C1,C2,C3,C4,r) are given constants, just need to assign them.
After assigning x1,y1,x2,y2 - you are given a minimization problem with 2 variables (x0,y0) and a constraint. The minimization problem can be solved using lagrange multiplier.
Let (x1, y1) and (x2, y2) be the points inside the circle, (x, y) be the point on the circle, r be the radius of the circle.
Your problem reduces to a Lagrange conditional extremum problem, namely:
extremum function:
f(x, y) = sqrt((x-x1)^2 + (y-y1)^2) + sqrt((x-x2)^2 + (y-y2)^2)
condition:
g(x, y) = x^2 + y^2 = r^2 (1)
Introduce an auxiliary function(reference):
Λ(x, y, λ) = f(x, y) + λ(g(x, y) - r^2)
Let ∂Λ / ∂x = 0, we have:
(x-x1)/sqrt((x-x1)^2 + (y-y1)^2) + (x-x2)/sqrt((x-x2)^2 + (y-y2)^2) + 2λx = 0 (2)
Let ∂Λ / ∂y = 0, we have:
(y-y1)/sqrt((x-x1)^2 + (y-y1)^2) + (y-y2)/sqrt((x-x2)^2 + (y-y2)^2) + 2λy = 0 (3)
Now we have 3 variables(i.e. x, y and λ) and 3 equations(i.e. (1), (2) and (3)), so it's solvable.
Please be noted that there should be two solutions(unless two inside points happen to be the center of the circle). One is the minimal value(which is what you need), the other is the maximal value(which will be ignored).
just another approach(which is more directly):
for simplicity, assume the circle is at (0,0) with radius r
and suppose two points are P1(x1,y1) and P2(x2,y2)
we can calculate the polar angle of these two points, suppose they are alpha1 and alpha2
obviously, the point which is on the circle and having the minimum sum of distance to P1 and P2 is within the circular sector composed of alpha1 and alpha2
meanwhile, the sum of distance between the point on the circle within that sector and P1 and P2 is a quadratic function. so, the minimum distance can be found by using trichotomy.
I am trying to find the angle of the outer line of the object in the green region of the image as shown in the image above…
For that, I have scanned the green region and get the points (dark blue points as shown in the image)...
As you can see, the points are not making straight line so I can’t find angle easily.
So I think I have to find a middle way and
that is to find the line so that the distance between each point and line remain as minimum as possible.
So how can I find the line so that each point exposes minimum distance to it……?
Is there any algorithm for this or is there any good way other than this?
The obvious route would be to do a least-squares linear regression through the points.
The standard least squares regression formulae for x on y or y on x assume there is no error in one coordinate and minimize the deviations in the coordinate from the line.
However, it is perfectly possible to set up a least squares calculation such that the value minimized is the sum of squares of the perpendicular distances of the points from the lines. I'm not sure whether I can locate the notebooks where I did the mathematics - it was over twenty years ago - but I did find the code I wrote at the time to implement the algorithm.
With:
n = ∑ 1
sx = ∑ x
sx2 = ∑ x2
sy = ∑ y
sy2 = ∑ y2
sxy = ∑ x·y
You can calculate the variances of x and y and the covariance:
vx = sx2 - ((sx * sx) / n)
vy = sy2 - ((sy * sy) / n)
vxy = sxy - ((sx * sy) / n)
Now, if the covariance is 0, then there is no semblance of a line. Otherwise, the slope and intercept can be found from:
slope = quad((vx - vy) / vxy, vxy)
intcpt = (sy - slope * sx) / n
Where quad() is a function that calculates the root of quadratic equation x2 + b·x - 1 with the same sign as c. In C, that would be:
double quad(double b, double c)
{
double b1;
double q;
b1 = sqrt(b * b + 4.0);
if (c < 0.0)
q = -(b1 + b) / 2;
else
q = (b1 - b) / 2;
return (q);
}
From there, you can find the angle of your line easily enough.
Obviously the line will pass through averaged point (x_average,y_average).
For direction you may use the following algorithm (derived directly from minimizing average square distance between line and points):
dx[i]=x[i]-x_average;
dy[i]=y[i]-y_average;
a=sum(dx[i]^2-dy[i]^2);
b=sum(2*dx[i]*dy[i]);
direction=atan2(b,a);
Usual linear regression will not work here, because it assumes that variables are not symmetric - one depends on other, so if you will swap x and y, you will have another solution.
The hough transform might be also a good option:
http://en.wikipedia.org/wiki/Hough_transform
You might try searching for "total least squares", or "least orthogonal distance" but when I tried that I saw nothing immediately applicable.
Anyway suppose you have points x[],y[], and the line is represented by a*x+b*y+c = 0, where hypot(a,b) = 1. The least orthogonal distance line is the one that minimises Sum{ (a*x[i]+b*y[i]+c)^2}. Some algebra shows that:
c is -(a*X+b*Y) where X is the mean of the x's and Y the mean of the y's.
(a,b) is the eigenvector of C corresponding to it's smaller eigenvalue, where C is the covariance matrix of the x's and y's
I have a line, defined by the parameters m, h, where
y = m*x + h
This line goes across a grid (i.e. pixels). For each square (a, b) of the grid (ie the square [a, a+1] x [b, b+1]), I want to determine if the given line crosses this square or not, and if so, what is the length of the segment in the square.
Eventually, I would like to be able to do this with multiple lines at once (ie m and h are vectors, matlab-style), but we can focus on the "simple" case for now.
I figured how to determine if the line crosses the square:
Compute the intersection of the line with the vertical lines x = a and x = a + 1, and the horizontal lines y = b and y = b + 1
Check if 2 of these 4 points are on the square boundaries (ie a <= x < a + 1 and b <= y < b + 1)
If two on these points are on the square, the line crosses it. Then, to compute the length, you simply subtract the two points, and use Pythagorean theorem.
My problem is more on the implementation side: how can I implement that nicely (especially when selecting which 2 points to subtract) ?
Let square be defined by corner points (a,b), (a+1,b), (a,b+1), (a+1,b+1).
Step 1: Check if the line intersects the square...
(a)Substitute each of the coordinates of the 4 corner points, in turn into y - mx - h. If the sign of this evaluation includes both positive and negative terms, go to step b. Otherwise, the line does not intersect the square.
(b)Now there are two sub-cases:
(b1)Case 1: In step (a) you had three points for which y - mx - h evaluated to one sign and the fourth point evaluated to the other sign. Let this 4th point be some (x*,y*). Then the points of intersection are (x*,mx*+h) and ((y*-h)/m,y*).
(b2)Case 2: In step (a) you had two points for which y - mx - h evaluate to one sign and the other two points evaluated to the other sign. Pick any two points that evaluated to the same sign, say (x*,y*) and (x*+1, y*). Then the intersection points are (x*, mx* + h) and (x*+1,m(x*+1) + h).
You would have to consider some degenerate cases where the line touches exactly one of the four corner points and the case where the line lies exactly on one side of the square.
Your proposed method may meet with problems in step (1) when m is 0 (when trying to compute the intersection with y = k).
if m is 0, then it's easy (the line segment length is either 1 or 0, depending on whether b <= h <= b+1).
Otherwise, you can find the intersections with x = a and a+1, say, y_a, y_{a+1} via a substitution. Then, clip y_a and y_{a+1} to between b and b+1 (say, y1 and y2, i.e. y1 = min(b+1, max(b, y_a)) and similarly for y2), and use the proportion abs((y1-y2)/m) * sqrt(m^2+1).
This makes use of the fact that the line segment between x=k and x=k+1 is sqrt(m^2+1), and the difference in y is m, and similarity.
You can do like this:
first find center of square and then find length of diagonal. If the distance from center of square to line is less than length of diagonal then the line will intersect the square. and once you know that line will intersect then you can easily find the intersected line segment. I think you are trying to make weight matrix for Algebraic reconstruction technique. I hope this is correct answer. This was my first answer in stack flow. :)