This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How can I tell if a point is nearby a certain line?
//Returns the point on the line traced from start to end which
//comes nearest to 500,000, 500,000. The points are scaled between
//1,000,000 and 0 from their original fp types.
Point closestToCentre(Point start, Point end);
Anyone know of quicker way than single stepping through the pixels?
Could some one more alert than me demonstrate their maths & geometry prowess please?
_______EDIT___________
Thanks Kris, this was confusing me :
[x; -a/bx-c/b]=[0; -c/b]-1/b[-b; a]x.
Now I see it is just splitting (mainly the y component) the vector into two which combine to yield the same result. Got the old partial fractions brain cell excited for a minute then :)
_______EDIT_________
Jason Moore, thanks for the inspiration, here is what I am doing, graphically,
I hope that is clearer.
____EDIT________
So I could reasonably expect to take a line at right angles to my sampled line and run it from the centre but how to tell when they touch?
I think Kris's page of equations is the way to go. If you're all telling me it is a two step process. It is just two simultaneous equations now, so I may not need Kris's derivations.
____EDIT_________
Whether good or bad thing, I don't know, but the beauty of stackoverflow as a search engine has revealed to me several routes of investigation. Chiefly I like the first solution here:
Shortest distance between a point and a line segment.
But to prove this to my self I needed the link from matti's solution at the bottom (but one):
http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Static
The derivation is so simple and elegant even I could follow it!
Given http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
This is a matter of linear projection of a point onto a line, which can be done with some fine vector gymnastics, as elaborated at MathWorld.
The article details how to find the shortest distance from a point to a line, and one of the intermediate steps is finding the perpendicular line from the point x,y to the original line. Intersecting these two lines will give you the point, on the line, closest to x,y.
Edit in response to comment: What equation (2) in the link is doing is transforming the vector into a form reminiscent of y = mx + c, which allows you to quickly and easily read off the gradient, from which the perpendicular gradient can be easily calculated.
I think the quickest way will be a two step process:
Assume your line is infinite in length, and find the intersection of your line and its perpendicular bisector through (500,000, 500,000).
Make sure that point is actually on your line, else find the closest endpoint.
Kris's post covers step 1 pretty well, all you have to do is add the check for step 2 because you have a line segment and you're golden.
Let point 1 = (x1, y1) and endpoint 2 = (x2, y2). Then the line containing these two points is
y = (y2 - y1)/(x2 - x1) * (x - x1) + y1
and the perp. bisector through (5e5, 5e5) is
y = (x1 - x2)/(y1 - y2) * (x - 5e5) + 5e5
Your point (x,y) is the solution (x,y) to the above two equations (or one of the two endpoints). This might be more straightforward than the mathworld link. Note that this solution fails, however, when your line is either almost vertical or almost horizontal whereas I don't think the mathworld solution style does, though I haven't looked very closely.
Related
I'm trying to find an efficient algorithm that can check if a line between two vertices in a simple (edit: simple concave) polygon contains points that lie outside the domain of the polygon. The closest question I could find is this one: https://stackoverflow.com/a/36378838/12135804
But I'm not sure the answer is quite right. It might be, in which case if someone could clarify that would be great.
The basic idea is illustrated in the below picture:
Where I would like the red line to fail and the green line to succeed. I know one can't naively test the midpoint as that wont work in every case, but finding any point on the line outside the polygon's domain should disqualify it.
I appreciate any and all help!
Edit: Forgot to include cross-post link to mathematics stack exchange:
https://math.stackexchange.com/q/4040059/892519
Let's assume that the topmost point is A and the others are named B, C ... counter-clockwise, so we know what we're talking about.
If you take the red segment B-D, the one point in between is on the left. If you take the green segment D-F, the one point in between is on the right. Now, a more interesting segment would be B-E, where C is on the left while D is on the right.
In order to determine left and right, use the vector product. The length depends on the sin function, so if you get a value less than zero it's one side and more than zero is the other side.
After a lot of googling, I finally found this answer to a stackoverflow question from ~12 years ago: https://stackoverflow.com/a/693877/12135804
Assuming the edges in the polygon follow a certain order, a simple ccw test can be created using a line's starting point (p), the next ccw point in the polygon from that starting point as an inflection point (q), and the endpoint of the line (r). For the red line BD, the test would check if B,C,D is ccw (it's not). For the green line DF, test if D,E,F is ccw (it is!). This would work even if the points are non-consecutive. However, this would fail when the order of the red-green lines is reversed. For instance, if the red line became DB, the test would check D,E,B, which would pass the ccw test.
I think a more robust solution is to search for the pair of two edges in the concave polygon that share the endpoints of the line to test. For both pairs, calculate the angle between the two edges to the x-axis. Calculate the angle of the line to the x-axis as well. If the line is within the polygon, the line's angle should lie between the max and min of the polygon edges' angles for both endpoints.
Whether to test the obtuse or acute range of angles depends on some factors, I think. The red line's angle at B w.r.t. to the x axis would be in the obtuse bound between AB and BC, and the same is true at point C. Visually, it's plain to see the acute bound is what needs to be used for the max/min test at both points. If the baseline to compute the bounds from can be chosen logically, then it can be done.
Of course, this doesn't work if the line crosses outside the polygon on the way between both endpoints, but this does handle the degenerate case for a normal line-polygon intersection test. Assuming it works in every degenerate case, that is.
I won't mark this an answer because I can't prove it.
Edit: Well, I came back to thinking about this again and decided to search for questions similar to the angular bounding I posed above, and found this: https://stackoverflow.com/a/17497339/12135804
This answer satisfies not knowing the orientation of the lines! However, it assumes the minimum bound between A and B should be tested. This doesn't work for concave vertices, when AxB is < 0. In this case, a line attached to the vertex shared by lines A and B will return true if it's pointing outside the polygon, and conversely false if it's inside. I think flipping the result based on the sign of AxB should be enough to account for this, though. (a hunch that is verified in this related answer: https://stackoverflow.com/a/43384516/12135804)
At the moment I try to learn and understand geometric algorithms and I found the smallest-circle-problem quite interesting. I found many solutions and different algorithms including this one of which I'm not sure if it is Emo Welzl's.
However, I don't understand one specific (important) part:
You're given N points on a (XY)-Plane.
You order those points randomly
Choose 3 points and create the circle where they are on the circle boundary.
Get the next point and check if it is enclosed by the circle:
a) If it is enclosed, repeat 4 until there are no more points left.
b) If is not enclosed, create a new circle where the new point is on the circle boundary and still all other points are inside or on the circle.
Steps 1) to 4a) are simple, my problem is step 4b). How can I find this new circle? To me, it seems like this is the same problem just with a smaller (sub)set of points. (Divide-et-Impera)
I guessed I have to replace one of the 3 original points (the first 3 points, that made up the first circle) with the new point, but I'm not sure
if this really works...
From the 3 points A,B,C you can calculate the centre O of the circle: the point that is equidistant to those three. Its coordinates xO and yO are the means of xA,xB,xC and yA, yB, yC respectively.
Let's call D the 4th point, trace the circle of centre 0 and radius OD.
OD > OA (and OA=OB=OC) so A, B and C are in the circle.
EDIT
The solution I proposed above is not optimal.
I found a good explanation of Welzl's algorithm: see link
Of course, you can get his paper easily by looking on Google Scholar, but it is quite hard to read.
The basic principle is that in 4b) the circle is computed from all the possible circles having D on the boundary as well as two other points that were on the boundary before (or one point if that doesn't work and it will be diametrically opposed to D).
I am trying to determine the distance from a point to a polygon in 2D space. The point can be inside or outside the polygon; The polygon can be convex or concave.
If the point is within the polygon or outside the polygon with a distance smaller than a user-defined constant d, the procedure should return True; False otherwise.
I have found a similar question: Distance from a point to a polyhedron or to a polygon. However, the space is 2D in my case and the polygon can be concave, so it's somehow different from that one.
I suppose there should be a method simpler than offsetting the polygon by d and determining it's inside or outside the polygon.
Any algorithm, code, or hints for me to google around would be appreciated.
Your best bet is to iterate over all the lines and find the minimum distance from a point to a line segment.
To find the distance from a point to a line segment, you first find the distance from a point to a line by picking arbitrary points P1 and P2 on the line (it might be wise to use your endpoints). Then take the vector from P1 to your point P0 and find (P2-P1) . (P0 - P1) where . is the dot product. Divide this value by ||P2-P1||^2 and get a value r.
Now if you picked P1 and P2 as your points, you can simply check if r is between 0 and 1. If r is greater than 1, then P2 is the closest point, so your distance is ||P0-P2||. If r is less than 0, then P1 is the closest point, so your distance is ||P0-P1||.
If 0<r<1, then your distance is sqrt(||P0-P1||^2 - (r * ||P2-P1||)^2)
The pseudocode is as follows:
for p1, p2 in vertices:
var r = dotProduct(vector(p2 - p1), vector(x - p1))
//x is the point you're looking for
r /= (magnitude(vector(p2 - p1)) ** 2)
if r < 0:
var dist = magnitude(vector(x - p1))
else if r > 1:
dist = magnitude(vector(p2 - x))
else:
dist = sqrt(magnitude(vector(x - p1)) ^ 2 - (r * magnitude(vector(p2-p1))) ^ 2)
minDist = min(dist,minDist)
In the event that this helps someone else, I reverse engineered doverbin's answer to understand why it worked showing graphically what the three cases are computing. (doverbin, feel free to incorporate this into your answer if you wish.)
If you have a working point to line segment distance function, you can use it to calculate the distance from the point to each of the edges of the polygon. Of course, you have to check if the point is inside the polygon first.
Do you need fast or simple?
Does it have to be always absolutely correct in edge cases or will good enough most of the time be OK?
Typical solution are to find the distance to each vertex and find the pair with the smallest values ( note that for a point outside a convex polygon these might not be adjacent) and then check point to line intersections for each segment.
For large complex shapes you can also store approx polygon bounding boxes (either rectangular or hexagons) and find the closest side before checking more detail.
You may also need code to handle the special case of exactly on a line.
I can help you with this pointers:
The distance can be calculated using Wikipedia entry, even with an untested snipped of code.
The inside/outside border can be solved with this Stack Post and links
and some remarks:
you should check only the nearest points, as Martin Beckett´s answer point outs, since another segment can "proyected" very near, but in reality don´t be close as need.
I do not know about the difference in performance with respect to the rest of answers, but in boost C++ libraries there is an generic implementation called distance. It has information about complexity in every case and in your problem case it is linear.
I was also looking for solutions to this problem some days ago and I want to share this finding. Hope it helps to someone.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Circle line collision detection
I'm trying to do collision testing between a finite line segment, and an arc segment. I have a collision test which does line segment vs. line segment, so I was going to approximate these arc segments with line segments and run my existing test.
The data I have defining the arc segment(s) are three points. Two of which are endpoints that lie on the circumference of a circle, and the third point is the center of that circle.
So far this is what I've got:
Let (a,b) be the center point of the circle, let 'r' be the radius of the circle, and (x1, y1), (x2, y2) be the endpoints of the arc segment which lies on the circumference of the circle.
The following parametric equations give the x, and y locations of an arc. 't' is the parametric variable.
x = a + r * cos(t)
y = b + r * sin(t)
To create the line segments from the arc, I wanted to walk the arc for some fixed ratio of 't' creating line segments along the way, until I've reached the end of the arc. To do this I figured I'd have to find the start and end angle. I'd start walking the arc from the start angle, and end at the end angle. Since I know the start and end points I figured I could use these equations to solve for these angles. The following are my equations for this:
t = arccos((x-a)/r)
or
t = acrcsin((y-b)/r)
The problem I'm having is that the range of values returned by these functions (http://en.wikipedia.org/wiki/Inverse_trigonometric_function) is limited, so there is a high probability that the angle I'm looking for will not be returned because these functions are multivalued: arcsin(0) = 0, but also arcsin(0) = π, arcsin(0) = 2π, etc
How do I get the exact angle(s) I'm looking for? Or, can you think of a better/different way of achieving my goal?
Take a look at the atan2 function, which should exist in whatever programming language or math library you're using. It takes two arguments, the x and y coordinates of a point (for you: (x-a)/r and (y-b)/r) and returns the angle in the range -π to +π.
At least IMO, you're going at this the wrong way. A line has an equation y=mx+b. A circle has an equation x2 + y2 = r2. You're looking for a point at which the x and y of the circle equals the x and y of the line. You can do that by substituting the mx+b equation for the line for the y equation in the circle, and then solve using the quadratic equation.
The equations involved do get a bit long, but quite a few web pages (e.g., http://www.sonoma.edu/users/w/wilsonst/papers/geometry/circles/default.html) have them, at which point it's simple matter of implementing the equations as a couple of functions and plugging in the values for your particular circle/line. A solution based on these equations complete avoids the ambiguity from using an arg tangent.
Your pseudo-code looks a lot like Python. If you don't mind using Python I would recommend the Shapely Library. If you just want the algorithm, check the source.
Shapely objects have the 'simplify' and 'intersection' methods.
How to find the minimum perpendicular distance of point from a line in 3D plane?
Please give me the logic and I will try to code on myself.
Please let me know how to do it in terms of x,y,z that is in terms of coordinate systems.
I am finding it a bit difficult to find the right solution which will be easy from a coding point of view. Online solutions are little bit rusty to understand. So please help me.
Please note line is given in terms of 3D space equation.
Given point A and a line, pick two different points on the line (B and C). Calculate the area of the triangle ABC with use of Heron's formula. Multiply the area by 2 and divide it by length of [BC]. You have the result you needed.
For an infinite line, the minimum distance is the length of line segment at right-angles to the infinite line passing through the point starting at the line and ending at the point. The direction of the perpendicular is given by the cross product of the unit normal to the plane and the unit vector along the line, the foot of the perpendicular is given by simultaneous solution of the equation for the first line, and for the perpendicular through the point. The distance between the points is what you are after.
For a finite line, this is a solution only if the foot of the perpendicular is on the segment; otherwise it's the shorter of the distance between the point and either end of the segment.
You say the line is given as an equation in 3D, but really planes are given by equations. And since the line is said to be lying in a 3D plane, presumably given by another equation, the line is actually the intersection of two planes.
To get the direction vector of the line, take the cross product of the normals to the two planes. If you use Pavel's method, you don't need this.
To get a point on the line, pick some value for x, say x = 0. Then solve the two equations for y and z after plugging in that value. To find another point to use in Pavel's method, set x to some other value, say x = 1, and solve the system again.
If the line is oriented the wrong way (perpendicular to the x axis), x may be a fixed value. In that case, try setting y to two fixed values. If that still doesn't work, try z. Also, check that the original planes are not parallel, so that there actually is a line of intersection.
To solve the question without Pavel's method, cross the direction of the line with the vector formed by the given point and a point you found on the line. Now cross that result with the line direction to get a new vector. Dot that vector with the original point and again with a point on the line. Take the difference, and divide by the length of the vector.