Find all line intersections with tolerance (preferably a pre existing implementation) - computational-geometry

The Bentley-Ottmann algorithm can be used to scan for all intersections in a set of line segments in n log n time. But is there a version out there that can do this with variable precision? i.e. where lines are considered to intersect if they come closer than a certain distance?

Assuming you're talking about line segments in 2D.
AFAIK, there's nothing special about that. You simply adjust the intersects(...) function of the LineSegment class/object. Instead of returning a boolean (or other) value indicating a "real" intersection, you return true if the smallest distance between the two segments is below your predefined threshold, indicating your definition of an intersection. No change in the algorithm.
1 See:
Shortest distance between two line segments
Connect two Line Segments

If 2 segments do not intersect, than minimal distance between them is on at least one segment end point. Because of that, in your case, it is enough to test if pair of segments intersect or some segment end point is near other segment.
First test is standard in Bentley-Ottmann algorithm, second part can be done in adding and removing segment from sweep line. When segment is added to SL (left endpoint) than it is enough to test segments on SL that are near left endpoint and segments that ended on given distance from SL to left. Similar when segment is removed from SL.
I think, because of symmetry, that is enough to test only one side, e.g. adding of segment to SL.
Since end points are sorted, this search should be fast. If there is some guaranty that segments are not dense regarding tolerance, than this change doesn't change n log n running time of original algorithm.

Related

Queries to figure out if point lies inside polygon

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.)

Covering N line segments with unit disks

Given a set of N disjoint horizontal line segments (parallel to the X-axis) of variable length and variable perpendicular distances in between, we need to place minimum numbers of unit disks that intersects at least one line segment or a unit disk such that the union of line segments and disks is connected. Is there any existing algorithm or anything I can use to solve this?
Finding an optimal solution is possibly NP-hard, as #j_random_hacker says. But perhaps a greedy algorithm produces a reasonable approximation.
Sort your segments by their left endpoints, and process the segments in that order, left-to-right. At any stage, you have a connected set of segments and disks to the left of the current not-yet-incorporated segment s. Find the closest object (segment or disk) to the left endpoint of s. Suppose this distance is d. Then connect s by a sequence of ceiling(d/2) disks along the line realizing that minimum distance d. s is now incorporated, and you can move on to the next segment.
One could easily create examples where this performs poorly, but there is quite a bit of room to improve via heuristics.

Intersect n line segments (on integer grid)

I have a problem that looks almost like a classic CS problem of finding all intersection points of given line segments.
The slight modification is the fact that:
1. I need to split all the segments at their intersection points
2. The resulting split segments must have integer coordinates.
If I just apply standard sweepline algorithm to find all the intersection points, and than cast coordinates of these points to integers, I sometimes get new intersections caused by the moving of intersections points to the integer grid.
I may apply this algorithm repeatedly, and probably (I can't prove it), in limited number of steps reach a state where I find no new intersections.
But I'm convinced there must be a simpler, more elegant solution.
I was trying to find a paper about such algorithm, but somehow couldn't find one that would deal with exactly this problem.
Can you tell point me to such a pape, or a description of an algorithm used by graphics libraries (such as Boost Polygon Library)?
Thank you.
This is an interesting variation to Line-segment intersection problem. Original problem of finding co-ordinates of point of intersection of these segments can be done solved using Line Sweep algorithm.
Here is an in depth article talking about Line-Sweep technique implementation for above problem. With this, intersection can be found in O(n*logn) time.
Now, in order to find the integer co-ordinates, you can cast the intersection points. But here you need to make sure about the direction of casting (which will later help in convergence).
If C in an intersection point on line segment AB, then split it into AC and CB. In AC, you cast C in direction of A, while in CB you cast it in direction of B. (By direction, I don't mean along the line segment direction, but along the half plane containing another end point.) This ensures that length of line segment will be reduced after each intersection.
PROOF: Consider, M to be maximum length of an line segment. Every time an intersection point lies on it, the length of new line segment is reduced by at least one unit. So number of iterations is bounded by M
Thus, overall iterations of your algorithm cannot exceed M.
Complexity = O(M* n *logn)

How to find and print intersections of n given circles in O(n*log(n)) time?

I'm looking for an O(n*logn) algorithm to find and print the intersections of n given circles. Each circle is specified by its center and radius.
An O(n2) algorithm consists in checking if the distance between the centers is less than or equal to the sum of the radii (of the two circles being compared). However, I'm looking for a faster one!
A similar problem is intersection of line segments. I think even my problem can be solved using line sweep algorithm, but I am unable to figure out how to modify the event queue in-case of circles.
Please, take also care of the following corner case. The black points indicate the event points (as per User Sneftel's solution below the intersection of circles marked by arrows won't be printed)
The line sweep algorithm will simply add circles to a list when you encounter their left extrema (that is, (x-r, y)), and removed from the list when you encounter their right extrema. Right before you add a circle to the list, check it against the circles already in the list. So your event queue is basically the left and right extrema of all circles, sorted by x. (Note that you know all the events ahead of time, so it's not really a "queue" in the normal sense.)
This is also known as "sweep and prune".
This is the correct solution I found based on a modification of User Sneftel's algorithm that wasn't working for all cases.
Fig 1 : Represent each circle by a bounded box.
Now to use the sweep line method, moving the sweep line parallel to y-axis we need TWO line segments to represent each circle's y-range as shown in figure 2.
Having done that the problem reduces to the following :
Here 2 line segments represent one circle.
Sweep line status can be maintained as any balanced dynamic data structure like AVL tree, Skip Lists, Red Black Trees having insertion/Update/Deletion/Retrieval time at-most O(logn).
The comparison function in this case will check if the two circles corresponding to the adjacent line segments intersect or not(In place of checking for line segments to intersect as in the original line sweep method for finding out line segment intersections). This can be done in O(1) time as constant amount of operations are required.
Number of Event Points : 4n (for n circles => 2n line segments => 4n end points)
Complexity = O(4nlog(4n)) = O(nlogn)

Elegant "Left-of" test for Polyline

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.

Resources