Splitting set of lines into intersecting segments - algorithm

I have a set of lines which may intersect at certain points. Each line is constructed of at least 2 points. What I want to do is to split each line when it intersects an other line and store all lines to a list. In this result list there may not be any line intersecting an other.
An intersection may only occur on a line's points what makes the intersection detection trivial (just compare each point with each other). What I consider to be very challenging is to find a performant algorithm to solve this problem.
Thanks for your help!
EDIT: Lines are represented as points, e.g. A = (0,0),(10,1),(20,2),(30,3),(35,4) and B = (12,-4), (10,1), (8, 5)

Plane sweep algorithm.
Look up a reference anywhere.
Essentially, we sweep along the x axis by, for each line segment, storing startx and endx as "events". Sort the events. Then you keep a second sorted list of "active" segments, add lines to the active list when you hit startx and removing it when you hit endx. The active list is sorted by y. So you only need a few actual intersection tests, where lines overlap in both x and y.

Related

Greedy algorithm to find minimum number of lines that can intersect all circles in the plane

I have a problem from homework where I need to find an O(n.log(n))
greedy algorithm for the minimum number of lines required to intersect all circles in the plane, as shown with the example below.
The starting point of all the lines is (0,0) which is the origin point. The set C contains n circles, where each circle c_i has information about its radius r_i and its centre coordinate (x_i, y_i).
I have tried making greedy rules:
iterate over each circle in the set C and pick c_i
construct 3 lines from origin to c_i, where 2 lines are tangent lines that only intersect 1 point in the circle, and 1 line is secant line that goes through the circle via its center.
iterate over other remaining circles c_j (j != i) and look how many circles intersect with these lines
choose the line L_i and remove the circles that intersect with it from the plane.
continue until the plane is empty.
But I don't think that this greedy rule will achieve the optimum solution and its complexity won't be O(n.log(n)).
Any hints or full solution is OK. It is also mentioned in the problem sheet that greedy rules that give minimum + 1 lines is fine.
Since you can use one line more than the minimum, you may start with an arbitrary line. Continue line by line clockwise until all circles are intersected. Each new line should have the greatest possible angle to the last as long as no circle lies between them. The 2 tangent lines you found is useful to find how far you can go in each step, but it will be time consuming to check every circle for each step. See if you can figure out how to speed it up.
This problem looks like “covering segments by points”. You can google for that or look here https://medium.com/competitive/covering-segments-by-points-fc2c56c4b038 for instance. In your case instead of segments you have angles for each of your circles. And lines instead of points.
The only difference is that the segments don’t lie on a line but on a circle. That’s why you’re allowed one extra line in your response to be able to pick a starting point arbitrarily.

Determine whether there is a line on which all points sit

I'm trying to create an algorithm which determines whether there is a horizontal or vertical line on a plane so that for each point on the place, it is either on the vertical line, the horizontal line, or both lines. This algorithm need only be sequential, and return true or false.
I have an idea of what needs to be done, i.e. I need to check each point for its location, but I'm not sure how to check whether its on a line. Any ideas?
Thanks in advance!!
Sort all your points by x co-ordinate and by y-coordinate. If every point is either on a horizontal line or on a vertical line then at least one of these lines must cover at least half the points, and there cannot be more than two horizontal lines like this, or more than two vertical lines like this, because you can't have more than two horizontal lines each with half the points on them.
So by sorting by x-coordinate and looking for lots of points on the same x-coordinate you have at most two candidates for vertical lines, and by sorting by y-coordinate at most two candidates for horizontal lines. For each of these (at most four) candidate lines look at all the points that don't fit on that lines and look at their y-coordinates (or x-coordinates) to see if they all fit on a lines of the other type. If they do, you are done. If not, try the at most three other possibilities.
You go through each point in sequence and compare their coordinates, knowing that they must share the same x component (abscissa), y component (ordinate), or both. Your goal is to determine these values, and then check that all the points have at least one of them.
the first point may have one or both correct, so you keep both components as potential correct values,
the second point should have at least one in common with the first, so you mark the common component as the correct one for either the horizontal (for x) or the vertical line (for y).
you loop on the next points until all of them share that same component you just found as common between the first two points, if you find one point which isn't on that line, then it must belong to the other, so you've discovered the second correct component,
Now you check all the remaining points l, if one of them doesn't have either component, the result is false.

finding boundaries of circle division by straight line

Given a circle, I add a straight line that goes through the circle and intersects it at two points as well as intersects every previous line at one point.
I want to repeat this procedure (adding one straight line at a time) and figure out the points that make up the boundaries of the sections the circle is divided into.
For example the first time I do this (first line) it divides the circle into 2 pieces:
When I add a second line it will divide each of these 2 pieces of the circle into 4 pieces:
When I add a third line it will divide the circle into 7 pieces:
What is an efficient algorithm to get these points?
Every time I add a line I can compute all the points that line intersects the circle and the other previous lines but I have to somehow figure out which regions these points are the boundary to
Not sure I completely understand the question but:
1) line/line intersection is achieved by Cramer. http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
2) line/circle intersection is achieved by solving a quadratic equation http://mathworld.wolfram.com/Circle-LineIntersection.html
3) you can classify the points per region by considering all signs obtained when injecting the point coordinates in the parametric equation of the splitting lines (in other words, is the point on the left or on the right of the line); this gives you a binary labeling of all regions (some of the labels being impossible).
You can also consider a ternary notation if you need to handle points known to be exactly on a line.

Given many horizontal and vertical lines, how to find all the rectangles that do have any sub-rectangle inside them?

I have many horizontal and vertical lines which make up rectangle such as in this example.
Is there an algorithm or code which can locate every rectangle which does not contain another rectangle. I mean, the largest rectangle in this image is not a rectangle I am looking for because it contains other rectangles inside of it.
The rectangles I am looking for must be empty. I have a list of the starting points and end points of each line like (a,b) to (c,d). I want as a result a list of rectangles (x,y,w,h) or equivalent.
Note that some lines have lines intersecting them at right angles, for example the top line of the widest rectangle in this image is a single line it has an intersecting vertical line going downwards.
These kind of questions are largely answered by some standard Computational Geometry algorithms. I can think of a vertical sweep line algorithm for this particular problem.
Assuming a rectangle is represented by a pair of points (p1, p2), where p1 is the upper left corner and p2 is the bottom right corner. And a point has two attributes (can be accessed as p.x and p.y).
Here is the algorithm.
Sort all the pairs of points - O(n log n)
Initialize a list called sweep line status. This will hold all the rectangles that are encountered till now, that are alive. Also initialize another list called event queue that holds upcoming events. This event queue currently holds starting points of all the rectagles.
Process the events, start from the first element in the event queue.
If the event is a start point, then add that rectangle to sweep line status (in sorted order by y-coordinate) (in O(log n) time) and add its bottom-right point to the event queue at the appropriate position (sorted by the points) (again in O(log n) time). When you add it to sweep line status, you just need to check if this point lies in the rectangle alive just above it in the sweep line status. If it does lie inside, this is not your rectangle, otherwise, add this to your list of required rectangles.
If the event is an end point, just remove the correspoinding rectangle from the sweep line status.
Running time (for n rectangles):
Sorting takes O(n log n).
Number of events = 2*n = O(n)
Each event takes O(log n) time (for insertions in event queue as well as sweep line status. So total is O(n log n).
Therefore, O(n log n).
For more details, please refer to Bentley–Ottmann algorithm. The above just a simple modification of this.
EDIT:
Just realized that input is in terms of line segments, but since they always form rectangles (according to question), a linear traversal for a pre-process can convert them into the rectangle (pair of points) form.
I think a different representation will help you solve your problem. As an example, consider the large rectangle (without the block on the end). There are four unique x and y coordinates, sort and index them. Pictorially it would look like this:
If there is a corner of a rectangle on the coordinate (x_i, y_j) put it in a matrix like so:
__|_1__2__3__4_
1 | x x 0 x
2 | x x 0 0
3 | 0 x x x
4 | x x x x
Now by definition, a rectangle in real space is a rectangle on the matrix coordinates. For example there is a rectangle at (3,2) (3,4) (4,4), (4,3) but it is not a "base" rectangle since it contains a sub-rectangle (3,3) (3,4), (4,4), (4,3). A recursive algorithm is easily seen here and for added speed use memoization to prevent repetitive calculations.
A sweep-line algorithm...
Structures required:
V = A set of the vertical lines, sorted by x-coordinate.
H = A set of all start and end points of the horizontal lines (and have each point keep a reference to the line) and sorted by x-coordinate.
CH = An (initially empty) sorted (by y-coordinate) set of current horizontal lines.
CR = A sorted (by y-coordinate) set of current rectangles. These rectangles will have left, top and bottom coordinates, but not yet a right coordinate. Note that there will be no overlap in this set.
Algorithm:
Simultaneously process V and H from left to right.
Whenever a start of horizontal line is encountered, add the line to CH.
Whenever an end of horizontal line is encountered, remove this from CH.
Whenever a vertical line is encountered:
Remove from CR all rectangles that overlap with the line. For all removed rectangle, if it is completely contained within the line, compare its size with the best rectangle thus far and store it if better.
Process each element in CH iteratively between the bottom point and the top point of the line as follows:
Add a rectangle to CR with the last processed point as bottom, the current point as top and the vertical line's y-coordinate as left.
Done.
Note:
When the x-coordinate of horizontal start points or end points or vertical lines are equal the following order must be maintained:
x of horizontal start < x of vertical line < x of horizontal finish
Otherwise you'll miss rectangles.
Are all your lines parallel to either x or y axis? Or, all your lines either parallel or perpendicular?
From the example you gave I am assuming all your lines are parallel to x or y axis. In such case your lines are going to be [(a,b), (a,d)] or [(a,b), (c,b)].
In any case, the first task is to find the corners. that is set of points where two perpendicular lines meet.
The second task is to detect rectangles. For every pair of corners you can check if they do form rectangles.
The third task is to find if a rectangle has any rectangles within itself.
For the first task, you need to separate lines into two sets: vertical and horizontal. After that sort one of the sets. Ex. Sort vertical lines according to their x axis coordinates. Then you can take all the horizontal lines and do a binary search to find all the intersecting points.
For the second task, consider every pair of corners and see if the other two corners exist. If yes, then see if there are lines to join all these four corners. If yes, you have a rectangle.
For the third task, put all the rectangles in a interval tree. After that you can check if two rectangles overlap.

How to select outer line segments

I am having 2D line segments. My goal is to make different closed polygons. But, in here, I want to select most outer line segments when there are few parallel line segments stay closed to each other. with different line combinations, I can make different closed polygons.I was thinking and struggling to know how to get most outer lines as I need the polygon which make by outer most lines. (Polyogns are at the end constructed by intersecting adjoying line segments.)
I was thinking to get a large bounding box containing all segments and get the centroid and then find the perpendicular distances to each line. In this process, I found nearby line segments which oriented close to each other (i.e. near parallel lines). So, from those nearby parallel lines I want outer most one. (that is red one).
But If I used the centroid and compare the distnaces, then longest distance (among nearby parallel lines) does not give correct outer most line when more concave and convex turns exist as some cases outer most (red) one does not give by the longest distance. What I have is; end point coordinates of each line segments. (that is vector data)
So, I am looking for some good way to get most outer line segments from nearby parallel lines.
For you to understand I have attached a sample data which i have. The most outer line segments are shown in red color. finally this red lines give me the boundary of my polygon. So, I want to get red lines out of corresponding nearby parallel black lines.
NOTE: My line segments are oriented into different direction. And not only to X & Y axes. Also, nearby lines donot make always 90 or 180 angles with adjacent lines.
please suggest me a method. thanks in advance
for example, if A,B and C,D are nearby parallel line segments. then outer most line should be B and C. But, If i compare distances from centroid (O), then I can get C as outer most, but B can not get as distance from O to B is smaller than O to A. My method fails in this type of spots. So, look alternatives..
A general way to find lines is using the Hough Transform.
http://en.wikipedia.org/wiki/Hough_transform
However, the sample data you give has lines parallel to the axes. I don't know if that is the nature of all of your data, but if it is then the Hough Transform basically breaks down to simply summing up the intensities by rows for lines parallel to the x-axis and summing by columns for lines parallel to the y-axis.
You will end up with two 1D arrays, one with row sums and one with column sums. Since the lines are black and the foreground is white, local minimums in these arrays will represent line locations along each axis. Since you only need the outer lines, you do not have to sum every column/row - just start at the edges of the image and compute the sums until you hit a local min. Once you have the line's placement on the axis, you can traverse that cut of the axis in the image to find the endpoints of the line.

Resources