We can solve the problem of segment intersection in 2D in O(nlgn) time. In this problem, we are given a set of line segments and we have to see if there is an intersection or not. Now her's a problem from CLRS.
Ques. Professor Charon has a set of n sticks, which are lying on top of each other in some
configuration. Each stick is specified by its endpoints, and each endpoint is an ordered triple giving its (x, y, z) coordinates. No stick is vertical. He wishes to pick up all the sticks, one at a time, subject to the condition that he may pick up a stick only if there is no other stick on top of it.
a. Give a procedure that takes two sticks a and b and reports whether a is above, below,
or unrelated to b.
b. Describe an efficient algorithm that determines whether it is possible to pick up all the sticks, and if so, provides a legal sequence of stick pickups to do so.
I find it is an extension of the segment intersection in 3D. In 2D, the sweep line moves in "y" and the array is sorted according to the "x" coordinate. I think in 3D, the sweep line should move in "z" dimension but m not sure how to sort now, since I have to take care of both "x" & "y".
If we somehow figure it out, I guess, if there is an intersection, then for part (b), its not possible to pick all the sticks.
Am I going in the right direction??
It is possible to use segment intersection in 2D to solve this problem.
Checking is one segment above the other is same as checking for there intersection in XY projection and if they intersect than compare Z coordinate of intersection point on each segment. E.g. for segments a=((0,0,0), (2,2,2)) and b=((0,2,3), (2,0,5)), projection on XY is ((0,0), (2,2)) and ((0,2), (2,0)). 2D intersection is (1,1), and Z value in (1,1) for a is 1, and for b is 4. That means b is above a.
So, use segment intersection in 2D to find which segments are in relation. To find in which order to remove segments use topological sorting.
Related
I have been given a strictly convex polygon of S sides and Q queries to process.
All points of polygon and query points are given in (x,y) pairs.The points of the polygon are given in anti-clockwise order.
The aforementioned variables are limited such that 1<=S<=10^6 and 1<=Q<=10^5 and 1<=|x|,|y|<=10^9.
For each query I should output Yes if the given point lies inside the polygon; otherwise, No.
I tried using an O(S) inclusion test (ray-casting) and it timed out for the bigger test cases but also didn't pass all the preliminary ones.
Obviously, the implementation didn't cover all the edge cases and I got to know about a specific algorithm for this question which could answer each query in O(log S) using binary search but I can't figure out how to implement it from the pseudocode (first time doing computational geometry).
Could anyone provide me with the algorithm which covers all edge cases within the required time complexity (Q log S) or guide me to a page or paper that implements it?
First, you can split your convex polygon into left and right parts both starting with the upper point and ending with the lower point. The points in both parts are already sorted by y-coordinate.
Assume that query point has coordinates (qx, qy). Now you can try to find (using a binary search) a segment from the left part and a segment from the right part that intersect with the line y = qy. If you could find both segments and qx is lying between x-coordinates of the segments' intersections with the line y = qy, it's inside the polygon.
The complexity of the query is O(log(S)).
You can do a scan line algorithm.
You need to sort the Q points by their x coordinate.
Then find the S point with the lowest x and consider a line moving along the x axis. You need to track the two sides of the polygon.
Then move along the polygon and the Q set in ascending x coordinate. For every point you now just have to check if it's between the two lines you are tracking.
Complexity is O(Q logQ + S) if Q is not sorted and O(Q+S) if Q is already sorted.
There is no need to sort, a convex polygon is already sorted !
For a convex polygon, point location is quick and easy: split the polygon in two using a straight line between vertex 0 and vertex S/2. The signed area test will tell you on which side the test point lies and which half to keep (the half is also a convex polygon).
Continue recursively until S=3 and compare against the supporting line of the third side.
O(Log(S)) tests in total per query.
(The numbers show the order of the splits.)
I am trying to write C++ code to find the intersection points of a segment intersecting a tetrahedron. I reduced the problem like this:
For each face of the tetrahedron (a triangle), find the intersection point of the line segment. Then, I have three cases:
a) The segment doesn't intersect any face - thus either the segment is entirely in the tetrahedron or completely outside.
b) The segment only intersects one face. Then I just need to determine the side of the segment that is in the tetrahedron and I get the two points that are in the tetrahedron.
c) The segment intersects two faces.
I am having trouble implementing this algorithm. Here are the issues:
If the segment and triangle are in the same plane, how do I find the intersection points?
How can I determine if the segment lies on one of the edges of the tetrahedron?
Thanks.
Hint:
You can't avoid a complex case discussion. Here I introduce the planar case of a line segment and a triangle.
The sides of the triangle define three straight lines that partition the plane in 7 regions, one bounded and 6 unbounded. On the figure, they are designated by the signs obtained when you plug the coordinates of a point in the three implicit equations of these lines.
If you need to consider endpoints exactly on a side, you need to add 6 half-lines and 3 segments to the discussion.
Then take all possible combinations of the starting and ending regions.
Many of the cases are straightforward. When the two segment endpoint belong to the same region, the segment is wholly inside or outside; when one of the regions is +++ and the other is different, there is exactly one intersection...
In the case of the figure (--+ to ++-), you are sure to have one intersection with the bottom edge; but which is the other intersected side is unsure: to answer this, you need to tell on what side of the line segment the top vertex lies.
With some courage, you can discuss all 16 x 15 / 2 = 120 cases, many of which are identical to a permutation of the elements.
This is just an appetizer compared to the 3D problem.
"How can I determine if the segment lies on one of the edges of the tetrahedron?"
Write a function that computes the area of the triangle determined by three points in space. This can be computed from a determinant, as explained here and many other sites.
Then write a function that determines if two segments ab and cd are collinear.
They are if and only if the area of abc is zero, and the area of abd is zero.
Finally, write a function that determines if one point c lies on the segment ab. With all this, the remainder is easy.
To answer the general question, i.e. how to find the (up to two) intersections between a segment and a tetrahedron, I'd prefer to avoid the painful case-by-case analysis (mentioned in your problem reduction and in another answer).
I would use a variant of Sutherland-Hogdman's reentrant clipping (explained in 2D in [1]): the idea is to consider the tetrahedron as the intersection between four oriented half-spaces (limited by the support planes of the four faces of the tetrahedron).
Thus to compute the intersection between a segment and a tetrahedron, you can proceed as follows:
S := your segment
for f := 0 to 3 {
H := half_space(tet, f)
S := intersect(S, H)
}
H is just a plane equation (coefficients a,b,c,d of equation ax+by+cz+d=0,
[a,b,c] is the normal to the facet, oriented towards the interior of the tetrahedron. d is obtained by injecting a vertex incident to the facet into the equation).
The function intersect() is simple to implement (just test the sign of ax+by+cz+d at both vertices of the segment, if they differ, there is an intersection, that can be computed by injecting a parametric equation of S
x=x1+t(x2-x1), y=y1+t(y2-y1), z=z1+t(z2-z1) into (ax+by+cz+d=0) and solving for t, where (x1,y1,z1) and (x2,y2,z2) denote the two extremities of S.
In addition, the function intersect() may compute two booleans, to keep track of which vertex of S is a generated intersection.
[1] https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
I have two sets of 2D points, separated from each other by a line in the plane. I'd like to efficiently find the pair of points, consisting of one point from each set, with the minimum distance between them. There's a really convenient looking paper by Radu Litiu, Closest Pair for Two Separated Sets of Points, but it uses an L1 (Manhattan) distance metric instead of Euclidean distance.
Does anyone know of a similar algorithm which works with Euclidean distance?
I can just about see an extension of the standard divide & conquer closest pair algorithm -- divide the two sets by a median line perpendicular to the original splitting line, recurse on the two sides, then look for a closer pair consisting of one point from each side of the median. If the minimal distance from the recursive step is d, then the companion for a point on one side of the median must lie within a box of dimensions 2d*d. But unlike with the original algorithm, I can't see any way to bound the number of points within that box, so the algorithm as a whole just becomes O(m*n).
Any ideas?
Evgeny's answer works, but it's a lot of effort without library support: compute a full Voronoi diagram plus an additional sweep line algorithm. It's easier to enumerate for both sets of points the points whose Voronoi cells intersect the separating line, in order, and then test all pairs of points whose cells intersect via a linear-time merge step.
To compute the needed fragment of the Voronoi diagram, assume that the x-axis is the separating line. Sort the points in the set by x-coordinate, discarding points with larger y than some other point with equal x. Begin scanning the points in order of x-coordinate, pushing them onto a stack. Between pushes, if the stack has at least three points, say p, q, r, with r most recently pushed, test whether the line bisecting pq intersects the separating line after the line bisecting qr. If so, discard q, and repeat the test with the new top three. Crude ASCII art:
Case 1: retain q
------1-2-------------- separating line
/ |
p / |
\ |
q-------r
Case 2: discard q
--2---1---------------- separating line
\ /
p X r
\ /
q
For each point of one set find closest point in other set. While doing this, keep only one pair of points having minimal distance between them. This reduces given problem to other one: "Algorithm to find for all points in set A the nearest neighbor in set B", which could be solved using sweep line algorithm over (1) one set of points and (2) Voronoi diagram for other set.
Algorithm complexity is O((M+N) log M). And this algorithm does not use the fact that two sets of points are separated from each other by a line.
well what about this:
determine on which side any point is:
let P be your points (P0,...Pi,...Pn)
let A,B be the separator line start-end points
so: side(Pi) = signum of ((B-A).(Pi-A))
this is based on simple fact that signum of scalar vector multiplication (dot product) depends on the order of points (see triangle/polygon winding rule for more info)
find minimal distance of any (Pi,Pj) where side(Pi)!=side(pj)
so first compute all sides for all points O(N)
then cycle through all Pi and inside that for
cycle through all Pj and search for min distance.
if the Pi and Pj groups aprox. equal size tahn it is O((N/2)^2)
you can further optimize the search by 'sort' the points Pi,Pj by 'distance' from AB
you can use another dot product to do that, this time instead (B-A)
use perpendicular vector to it let say (C-A)
discard all points from Pi2 (and similar Pj2 also)
where ((B-A).(P(i1)-A)) is close to ((B-A).(P(i2)-A))
and |((C-A).(P(i1)-A))| << |((C-A).(P(i2)-A))|
beacuese that means that Pi2 is behind Pi1 (farer from AB)
and close to the normal of AB going near Pi1
complexity after this optimization strongly depend on the dataset.
should be O(N+(Ni*Nj)) where Ni/Nj is number of remaining points Pi/Pj
you need 2N dot products, Ni*Nj distance comparision (do not neet to be sqrt-ed)
A typical approach to this problem is a sweep-line algorithm. Suppose you have a coordinate system that contains all points and the line separating points from different sets. Now imagine a line perpendicular to the separating line hopping from point to point in ascending order. For convenience, you may rotate and translate the point set and the separating line such that the separating line equals the x-axis. The sweep-line is now parallel with the y-axis.
Hopping from point to point with the sweep-line, keep track of the shortest distance of two points from different sets. If the first few points are all from the same set, it's easy to find a formula that will tell you which one you'll have to remember until you hit the first point from the other set.
Suppose you have a total of N points. You will have to sort all points in O(N*log(N)). The sweep-line algorithm itself will run in O(N).
(I'm not sure if this bears any similarity to David's idea...I only saw it now after I logged in to post my thoughts.) For the sake of the argument, let's say we transposed everything so the dividing line is the x axis and sorted our points by the x coordinate. Assuming N is not too large, if we scan along the x-axis (that is, traverse our sorted list of a's and b's), we can keep a record of the overall minimum and two lists of passed points. The current point in the scan is tested against each passed point from the other list while the distance from the point in the list to (x-coordinate of our scan,0) is greater than or equal to the overall min. In the example below, when reaching b2, we can stop testing at a2.
scan ->
Y
| a2
|
| a1 a3
X--------------------------
| b1 b3
| b2
I have a question.
I have N objects and N x N matrix M. Each entry M(i, j) contains (a kind of) relative gravitational force indicating how strongly i pulls j toward it (or inversely pull it away from it).
I want to place these N objects on a two-dimensional R x R plane by assigning a coordinate to each object.
Is there an algorithm/method that does this? There must be some commonly methods used in astrophysics, physics, chemistry, etc.
Thank you for your help.
You are interested in assigning co-ordinates (xi,yi,zi) and mass (mi) to each object such that gravitational force is consistent, right?
Consider 8 points at a time. You have a total of 32 unknowns and 28 equations. You can assume that first point is at origin and second point on x axis. That means, you will have 28 unknown and 28 equations.
So, first device and algorithm to solve for 8 points at a time. Then incrementally add one point at each iteration.
===Walkthrough===
Consider you are given n points in D dimensions. You only have distances between the points, but not the co-ordinates. Goal is to find co-ordinates for each point.
If D=1, you need to consider only two (+1) points at a time. Place first point at origin. Place second point on the positive side of origin. You can place third point in relation to origin, but place it right or left of it depending on the distance to first point and so on...
If D=2, place point 1 at origin, point to on positive side on x axis, third point on positive side of y axis depending on distance. From fourth point onward, you can use any two placed points to place the next and use any other point to refine the options (there will be two options).
Similar with D=3. Place first three points on xy plane (z=0) for all three. Next, place 4th point ofn postive part of z axist. And so on.
Coming back to gravity:
Your problem is complicated because you cannot exactly place mass at the origin. So you would need more than 5 points to place them. As I have shown above, you need at most 8 points though.
In case your mass are all equal, you can calculate distance (~inverse of gravity) and apply the case when D=3.
The problem is, given that we know the n*n distances between n objects, how to obtain their positions?
1. Put the first one, say a, at (0,0)
2. Put the second one b at ( |b-a|, 0 )
3. For the third one c, it is at the one of the two intersections of the two circles:
|p-a|=|c-a| and |p-b|=|c-b|.
Solve this system of quadratic equations using the well-known formula, choose
either of the solutions as the position of c.
4. For any other points p, do the same thing as we're done for c, but choose one of the
two solutions that is consistent with the distance |p-c|. And check the distance
between p and all previous points. If the check fails, return with failure.
Given:
(X,Y) coordinate, which is the position of a vehicle.
Array of (X,Y)'s, which are vertices in a polyline. Note that the polyline consists of straight segments only, no arcs.
What I want:
To calculate whether the vehicle is to the left or to the right of the polyline (or on top, ofcourse).
My approach:
Iterate over all line-segments, and compute the distance to each segment. Then for the closest segment you do a simple left-of test (as explained here for instance).
Possible issues:
When three points form an angle smaller than 90 degrees (such as shown in the image blow), a more complicated scenario arises. When the vehicle is in the red segment as shown below, the closest segment can be either one of the two. However, the left-of test will yield right if the first segment is chosen as the closest segment, and left otherwise. We can easily see (at least, I hope), that the correct result should be that the vehicle is left of the polyline.
My question:
How can I elegantly, but mostly efficiently take care of this specific situation?
My fix so far:
Compute for both segments a point on that segment, starting from the vertex point.
Compute the distance from the vehicle to both of the points, using Euclidian distance
Keep the segment for which the computed point is the closest.
I am not very happy with this fix, because I feel like I am missing a far more elegant solution, my fix feels rather "hacky". Efficiency is key though, because it is used on a realtime embedded system.
Existing codebase is in C++, so if you want to write in a specific language, C++ has my preference.
Thanks!
[edit]
I changed my fix, from a perpendicular point to a parallel point, as I think it is easier to follow the line segment than compute the outward normal.
This topic has been inactive for so long that I believe it's dead. I have a solution though.
However, the left-of test will yield right if the first segment is
chosen as the closest segment, and left otherwise.
You've used slightly ambiguous language. I'm gonna use segments to speak of the line segments in the polyline and quadrants to speak of the areas delimited by them. So in your case, you'd have a red quadrant which seems to be on the right of one segment and on the left of the other.
If the left-of test yields different answers for different segments, you should redo the test on the segments themselves. In your case, you'd have:
The quadrant is on the RIGHT of the first segment
The quadrant is on the LEFT of the second segment
Both segments disagree on where the quadrant lies, so you do two further disambiguation tests:
The second segment is on the RIGHT of the first segment
The first segment is on the RIGHT of the second segment
This allows us to conclude that the second segment is in between the first segment and the quadrant—since each of those two lies on a different side of the second segment. Therefore, the second segment is "closer" to the quadrant than the first and it's answer to the left-right test should be used as the correct one.
(I'm almost sure you can do with only one of the two disambiguation tests, I've put both in for clarity)
For the sake of completeness: I believe this solution also accounts for your demands of efficiency and elegance, since it uses the same method you've been using from the start (the left-of test), so it meets all the conditions specified: it's elegant, it's efficient and it takes care of the problem.
Let infinity = M where M is big enough. You can consider that everything is in the square [-M,M]x[-M,M], split the square with your polyline and you have now two polygons. Then checking if the car is in a given polygon can be done very simply with angles.
I consider that your first point and your last point have M in there coordinates. You may need to add some of these points to have a polygon: (-M,-M), (M,-M), (M,M) and (-M,M).
Once you have a polygon for the left of the polyline, sum the angles OĈP where O is a fixed point, C is the car and P is a point of the polygon. If the sum is 0 then the car is outside of the polygon, else it is inside.
Just a quick idea: would it be possible to connect the last and first vertex of your polyline, so that it would become a polygon? You could then do a simple inside/outside check do determine whether the vehicle is left/right of the line (this ofcourse depends on the direction of the polygon).
However, this method does assume that the polygon is still not self-intersecting after connecting the last and first vertex.
This is a standard sort of problem from computational geometry. Since you're looking to test whether a point (x0, y0) is left-of a given surface (your polyline), you need to identify which segment to test against by its height. One easy way to do this would be to build a tree of the lower point of each segment, and search in that for the test point's predecessor. Once you have that segment, you can do your left-of test directly: if it's left of both endpoints, or between them on the appropriate side, then you return true.
I am assuming here that you guarantee that the vertical extent of your polyline is greater than where you might find your query point, and that the line doesn't overlap itself vertically. The latter assumption might be quite poor.
Expansion in response to OP's comment:
Note that the angle example in the question contradicts the first assumption - the polyline does not reach the height of the search point.
One way to conceptualize my method is by sorting your segments vertically, and then iterating through them comparing your point's y-coordinate against the segments until your point is above the lower endpoint and below the higher endpoint. Then, use the endpoints of the segment to figure out the x-intercept at the given y. If the point has a lower x-cooordinate, it's to the left, and if it has a greater x-coordinate, it's to the right.
There are two ways to improve on this explanation in a real implementation, one of which I mentioned about:
Use a balanced search tree to find the right segment instead of iterating through a sorted list, to bring the time from O(n) to O(log n)
Reconceptualize the search as finding the intersection of the polyline and the horizontal line y = y0 through the search point. Then just compare the x value of the intersection against the search point.