I have with me the polygon coordinates and the line coordinates for the horizontal and vertical lines? The intention is to find all the intersecting grid (rectangles) existing outside of the polygons?
Starting point is this :
(step-2)The blue and the red lines are formed by stretching each and every coordinate of the polygons in horiztonal and vertical direction until the nearest intersection.
I can find the intersections for sure but defining rectangles from it seems to be tricky.
Add grid lines on the border.
For every grid line, horizontal or vertical, list all the intersection points on it in left-to-right or top-to-bottom order.
Foe every intersection point, store its nearest neighbor along a grid line to the right, and its nearest neighbor along a grid line to the bottom.
For every intersection point A, if it has both neighbors, proceed to the right neighbor B until it has a bottom neighbor. Also, proceed to the bottom neighbor C until it has a right neighbor. The three points A, B, and C are three corners of a rectangle.
If necessary, for each rectangle, detect whether it is inside or outside one of the given polygons.
I'd go with a two-pass sweep-line algorithm.
The first pass would compute how far the horizontal lines extend to the right: sweep left to right keeping track of the active horizontal lines in a set sorted by y.
When a vertical line V is encountered, for each active horizontal line H with y coordinate between V endpoints:
extend H up to the current x coordinate (note: keep the original unextended endpoints for the next pass).
remove H from the active set.
When a horizontal line left end is encountered, add it to the active set.
In the end, extend the unterminated active lines to infinity.
The second pass would compute how far the horizontal lines extend to the left, and emit the rectangles on the go: sweep right to left, again keeping track of the active horizontal lines sorted by y.
When a vertical line V is encountered:
find the two nearest active horizontal lines H1, H2 that bound V from the top and the bottom: a line H bounds V if V.x is contained within the original unextended endpoints of H.
generate all the rectangles between the active horizontal lines between H1 and H2.
remove all the active lines between H1 and H2 with y coordinates contained within V endpoints (i.e. those that V terminates on the left).
When a horizontal line extended-to-the-right end point is encountered, add that line to the active set.
Related
Consider the picture :
Given the black "irregular line" segments, I want to have the green boundary surrounding them.
My Attempt to solve :
Note, that I need to capture the concavity. Thus the convex hull algorithm will not work. I have used some interpolations, to draw the straight line segments indicated by overlayed red stripes. Then I attempted to run a sweep algorithm. These stripes are roughly parallel, if that helps.
That is, their headings lay within some small interval.
Heading H in { angle alpha - x , angle alpha +x } union { angle alpha - x + 180 , angle alpha +x+ 180 } for some small x
However, it needs to be guaranteed, that the green boundary should not intersect any red lines.
So, my naive attempt was :
Start at leftmost vertex of all lines.
Pick the line attached to the vertices. (if more vertices, then take the top most and bottom most)
Use this line to "partition" the plane. (or two lines or two "separatices", if 2 vertices)
Pick the next leftmost unvisited vertices.
See if the vertex lies above the top separatrix or below the bottom separatrix.
If above the top separatrix, add it to a set called "top chain", if below the bottom one, the add to bottom chain.
But this runs into problems.
The problem
To determine whether the newly picked point is at the top or at the bottom of a separatrix, I use the vector product method. But consider this :
Imagine you are at the green square. Your separatrix now is the black line, vector pointing to the left, as the arrow shows.
At this stage, you compare this with the green vector showing the next vertex to be picked on the blue line. The vector method, intended to measure angles between -Pi to Pi will consider this a negative value. Thus the point, although necessary, will not be picked up.
If you reverse the direction of the vector, then the Magenta line will not be picked up.
Question
How to efficiently solve this problem? I am using D, so bonus if there is a D library capable of this.
Filling concavities is a somewhat arbitrary operation. Have a look at Alpha-shapes, a generalization of the convex hulls.
https://en.wikipedia.org/wiki/Alpha_shape
Given some rectangles inside of a larger rectangle, is there any algorithm to split the remaining space into rectangles, and preferably as few as possible?
One way to solve the problem is to reduce the rectangles to a mesh. Each rectangle corner becomes a vertex (x,y) and each rectangle's side is a line that references two vertices. Vertices that are on a line (eg two rectangle are touching) must split the line at that vertex. There may only be one line joining any two vertices. The bounding rectangle is included.
Once you have the rectangles converted to a mesh then for each vertices count the number of lines that use that vertex.
If a vertex has only 2 lines joining it and is not a bounding corner, then it must be extended, it will have two optional directions, horizontal and vertical. There is no rule in which direction is the best so pick a random direction. In that direction and moving away from the lines coming to the vertex add a vertex to the closest intersecting line. Continue the process until no vertices (apart from the bounding corners) have less than 3 lines connected to it.
Now start at the top left most vertex and trace the lines in a clockwise direction, each 4 lines is a rectangle when you get back to the starting vertex you have a new rectangle Use the min and max vertex coordinates in the x and y direction to define the size of the rectangle. For each line decrease its vertices line count by 1. When a vertex has a line count of zero remove the vertex; When all vertices are removed you are done.
This will create the minimum number of rectangles possible.
To know if a solution is the minimum rectangle count check that each vertex has ONLY 3 lines joining it (Your example image is the minimum number of rectangle because no vertex has more than 3 lines joining it)
The only exception to this rule is if the existing rectangles are touching at a corner. Only existing vertices may have 4 lines joining.
Using a bsp tree: insert each rectangle edge in the tree. This will partition the space into convex subsets. Since your input are rectangles, the convex subsets can only be rectangles (https://en.wikipedia.org/wiki/Binary_space_partitioning).
Note that the partition depends on the order in which you insert the edges.
I'm not sure though that this will give you the minimum number of rectangles, but you will get close.
Points from (0,0) to (R,C) in the cartesian plane are colored r, g or b. Make a triangle using these points such that-
a) All three vertices are of different colors.
b) At least one side of triangle is parallel to either of the axes.
c) Area of the triangle is maximum possible.
Output the maximum possible area.
Constraints : 1<=R<=1000 , 1<=C<=1000
Can someone please let me know the approach to this question?
The area of a triangle is 1/2 * base * height. So if one side of the triangle is parallel to the
x-axis, then the base of the triangle is formed by two colors on the same row (spread as far apart as possible), and the third color should be on the row that's farthest from the base. Hence, you can preprocess the data to find:
the top-most and bottom-most row for each color
the left-most and right-most column for each color on every row
Then for every row, you have twelve possibilities for forming a triangle, e.g.
left-most-red, right-most-blue, top-most green
left-most-red, right-most-blue, bottom-most green
left-most-red, right-most-green, top-most blue
...
And of course, there's the corresponding process for triangles with one edge parallel to the y-axis.
Thus, the problem can be solved in O(R*C) time, where most of the time is spent in the preprocessing.
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.
Given is a 2D are with the polygons. I need to find out the polygons visible in a perpendicular line of sight from the a given line segment lying within that area. e.g.
Further,
What can be the optimizations when the polygons have only vertical and horizontal edges.
I'd suggest the following ...
Rotate the problem so your 'line of sight' segment is aligned to the x axis.
Find the (axis aligned) bounding rectangle (BR) of each polygon.
Sort the polygons using the Y coordinate of the bottom edge of each BR
Create a clipping 'range buffer' to mark the portions of the viewing segment that will be no longer visible.
For each polygon C (current) in the sorted list do ...
Use C's left and right bounds as its initial clipping range.
Trim C's clipping range with the range already marked as clipped in the 'range buffer'.
Now for each subsequent polygon S of a similar depth (ie where S's BR bottom edge starts below C's BR top edge) ...
loop to next S if it doesn't overlap horizontally with C
determine if S is overlapping from the left or right (eg by comparing the BR horizontal midpoints of S and C). If S overlaps from the right and S's left-most vertex is below C's right-most vertex, then truncate C's clipping range accordingly. (Likewise if S overlaps from the left.)
If the residual clipping range isn't empty, then at least part of C is visible from your viewing segment. Now add C's residual clipping range to the clipping 'range buffer'.