I have finite 2D space with wrapped coordinates both way (I mean going left will wrap around into right edge, the same going for up/down).
I also have a set of box aligned to axes. These boxes have float coordinates inside space.
Problem: find smallest bounding box aligned to axes enclosing all boxes. Bounding box CAN be wrapped around.
Samples:
(Pink denotes space boundaries, red boxes needs to be enclosed, blue border denotes smallest possible bounding box)
A sweeping algorithm can be used to find the largest vertical gap, i.e. maximally distant two vertical lines that have no boxes between them.
Similarly, a sweeping algorithm can be used to find the largest horizontal gap. Obviously, both gaps can wrap around edges.
The shape left by removing the gaps from the 2D space is the smallest bounding box containing all boxes. I am not sure if it's guaranteed to have the smallest area of all the containing boxes, but there exists no bounding box that has both dimensions smaller than this one. If it existed, it would define two gaps (vertical & horizontal) both larger than the maximal ones.
The sweeping to detect both gaps can be done in O(N * log N) where N is the number of boxes.
The % of the total area enclosed by a bounding box will be:
% of total area enclosed by bounding box = (% of horizontal range enclosed by horizontal bounds) * (% of vertical range enclosed by vertical bounds)
Taking wrapping into account obviously. Therefore you can minimize the horizontal and vertical bounds independently in order to minimize the total area.
To minimize the horizontal bounds, you need to find the largest gap between one rectangle's right edge and the next's left edge. You can do this efficiently by sorting all edges (left and right) into a single list and iterating across it, incrementing a count when you get a left and decrementing when you get a right. Your largest gap is the biggest difference in x values when the count goes from 0 -> 1. You'll have to handle the wrap-around case specially, you could easily do this just by repeating the rectangles once horizontally, offset by the width of the total area. You also have to take into account wrapped-around rectangles when initializing the count at the start.
Then do likewise for the vertical bounds.
Related
Problem
I need to place rectangle with size n×m into free area of matrix with size N×M, where N=n*2-1, M=m*2-1. Matrix cell is considered free if it's true, and occupied if it's false. Center cell is always true, and always will be inside rectangle due to rectangle and matrix's sizes.
Additional requirement is that distance between upper left corner of rectangle and center cell must be as minimal as possible.
Example with n=8 and m=5:
Where gray cells - occupied, green - center cell, blue cells - solution rectangle, red line - distance between upper left corner of rectangle and center cell.
Attempts
Brute force solution would have O(N×M×n×m) time complexity, which is not very optimal. I can eliminate calculations in some cells if I preprocess matrix, but that still would take too much time.
Initially I thought I can take Max Rectangle Problem and just modify condition from max to needed, but it went to dead end (I would need to list all rectangles in a histogram, which I don't know how). Then I thought it's like packing problem, but all I could find was versions of it with initially completely empty space and multiple rectangles, which is not applicable to this problem.
Context
In the past, when user clicks on a grid, my program would place rectangle, with upper left corner coinciding with a click point, if it's empty and fail if it have occupied cells where rectangle would lay. I decided to modify this behavior and instead of failing, find most suitable position for rectangle, while still containing a click point. In matrix pic above, click point is a green cell, and matrix size represents all possible positions of a rectangle.
P.S. I would prefer real language example instead of pseudo-code, if possible. My program is written in Java, but any language is fine.
You can do this in O(N.M) space and time complexity by:
Compute the summed area table in O(N.M)
Iterate over all top-left corners, check that the summed area in the rectangle is equal to n.m, and update the best position if the distance to the centre has improved. The test is O(1) per top-left corner, and there are O(N.M) top-left corners, so overall O(N.M)
The key idea is that the summed area table allows you to compute the sum of an arbitrary rectangle in O(1) time.
I'm trying to come up with an algorithm to optimize the shape of a polygon (or multiple polygons) to maximize the value contained within that shape.
I have data with 3 columns:
X: the location on the x axis
Y: the location on the y axis
Value: Value of the block which can have positive and negative values.
This data is from a regular grid so the spacing between each x and y value is consistent.
I want to create a bounding polygon that maximizes the contained value with the added condition.
There needs to be a minimum radius maintained at all points of the polygon. This means that we will either lose some positive value blocks or gain some negative value blocks.
The current algorithm I'm using does the following
Finds the maximum block value as a starting point (or user defined)
Finds all blocks within the minimum radius and determines if it is a viable point by checking the overall value is positive
Removes all blocks in the minimum search radius from further value calculations and flags them as part of the final shape
Moves onto the next point determined by a spiraling around the original point. (center is always a grid point so moves by deltaX or deltaY)
This appears to be picking up some cells that aren't needed. I'm sure there are shape algorithms out there but I don't have any idea what to look up to find help.
Below is a picture that hopefully helps outline the question. Positive cells are shown in red (negative cells are not shown). The black outline shows the shape my current routine is returning. I believe the left side should be brought in more. The minimum radius is 100m the bottom left black circle is approximately this.
Right now the code is running in R but I will probably move to something else if I can get the algorithm correct.
In response to the unclear vote the problem I am trying to solve without the background or attempted solution is:
"Create a bounding polygon (or polygons) around a series of points to maximize the contained value, while maintaining a minimum radius of curvature along the polygon"
Edit:
Data
I should have included some data it can be found here.
The file is a csv. 4 columns (X,Y,Z [not used], Value), length is ~25k size is 800kb.
Graphical approach
I would approach this graphically. My intuition tells me that the inside points are fully inside the casted circles with min radius r from all of the footprint points nearby. That means if you cast circle from each footprint point with radius r then all points that are inside at least half of all neighboring circles are inside your polygon. To be less vague if you are deeply inside polygon then you got Pi*r^2 such overlapping circles at any pixel. if you are on edge that you got half of them. This is easily computable.
First I need the dataset. As you did provide just jpg file I do not have the vales just the plot. So I handle this problem like a binary image. First I needed to recolor the image to remove jpg color distortions. After that this is my input:
I choose black background to easily apply additive math on image and also I like it more then white and leave the footprint red (maximally saturated). Now the algorithm:
create temp image
It should be the same size and cleared to black (color=0). Handle its pixels like integer counters of overlapping circles.
cast circles
for each red pixel in source image add +1 to each pixel inside the circle with minimal radius r around the same pixel but in the temp image. The result is like this (Blue are the lower bits of my pixelformat):
As r I used r=24 as that is the bottom left circle radius in your example +/-pixel.
select inside pixels only
so recolor temp image. All the pixels with color < 0.5*pi*r^2 recolor to black and the rest to red. The result is like this:
select polygon circumference points only
Just recolor all red pixels near black pixels to some neutral color blue and the rest to black. Result:
Now just polygonize the result. To compare with the input image you can combine them both (I OR them together):
[Notes]
You can play with the min radius or the area treshold property to achieve different behavior. But I think this is pretty close match to your problem.
Here some C++ source code for this:
//picture pic0,pic1;
// pic0 - source
// pic1 - output/temp
int x,y,xx,yy;
const int r=24; // min radius
const int s=float(1.570796*float(r*r)); // half of min radius area
const DWORD c_foot=0x00FF0000; // red
const DWORD c_poly=0x000000FF; // blue
// resize and clear temp image
pic1=pic0;
pic1.clear(0);
// add min radius circle to temp around any footprint pixel found in input image
for (y=r;y<pic1.ys-r;y++)
for (x=r;x<pic1.xs-r;x++)
if (pic0.p[y][x].dd==c_foot)
for (yy=-r;yy<=r;yy++)
for (xx=-r;xx<=r;xx++)
if ((xx*xx)+(yy*yy)<=r*r)
pic1.p[y+yy][x+xx].dd++;
pic1.save("out0.png");
// select only pixels which are inside footprint with min radius (half of area circles are around)
for (y=0;y<pic1.ys;y++)
for (x=0;x<pic1.xs;x++)
if (pic1.p[y][x].dd>=s) pic1.p[y][x].dd=c_foot;
else pic1.p[y][x].dd=0;
pic1.save("out1.png");
// slect only outside pixels
pic1.growfill(c_foot,0,c_poly);
for (y=0;y<pic1.ys;y++)
for (x=0;x<pic1.xs;x++)
if (pic1.p[y][x].dd==c_foot) pic1.p[y][x].dd=0;
pic1.save("out2.png");
pic1|=pic0; // combine in and out images to compare
pic1.save("out3.png");
I use my own picture class for images so some members are:
xs,ys size of image in pixels
p[y][x].dd is pixel at (x,y) position as 32 bit integer type
clear(color) - clears entire image
resize(xs,ys) - resizes image to new resolution
[Edit1] I got a small bug in source code
I noticed some edges were too sharp so I check the code and I forgot to add the circle condition while filling so it filled squares instead. I repaired the source code above. I really just added line if ((xx*xx)+(yy*yy)<=r*r). The results are slightly changed so I also updated the images with new results
I played with the inside area coefficient ratio and this one:
const int s=float(0.75*1.570796*float(r*r));
Leads to even better match for you. The smaller it is the more the polygon can overlap outside footprint. Result:
If the solution set must be a union of disks of given radius, I would try a greedy approach. (I suspect that the problem might be intractable - exponential running time - if you want an exact solution.)
For all pixels (your "blocks"), compute the sum of values in the disk around it and take the one with the highest sum. Mark this pixel and adjust the sums of all the pixels that are in its disk by deducing its value, because the marked pixel has been "consumed". Then scan all pixels in contact with it by an edge or a corner, and mark the pixel with the highest sum.
Continue this process until all sums are negative. Then the sum cannot increase anymore.
For an efficient implementation, you will need to keep a list of the border pixels, i.e. the unmarked pixels that are neighbors of a marked pixel. After you have picked the border pixel with the largest sum and marked it, you remove it from the list and recompute the sums for the unmarked pixels inside its disk; you also add the unmarked pixels that touch it.
On the picture, the pixels are marked in blue and the border pixels in green. The highlighted pixels are
the one that gets marked,
the ones for which the sum needs to be recomputed.
The computing time will be proportional to the area of the image times the area of a disk (for the initial computation of the sums), plus the area of the shape times the area of a disk (for the updates of the sums), plus the total of the lengths of the successive perimeters of the shape while it grows (to find the largest sum). [As the latter terms might be costly - on the order of the product of the area of the shape by its perimeter length -, it is advisable to use a heap data structure, which will reduce the sum of the lengths to the sum of their logarithm.]
I have a set of arbitrary rotated filled rectangles plotted on a Cartesian grid (2D integer array, each cell is either 0 - empty space or 1 - rectangle pixel) and would like to test whether a particular rectangle has any obstacles around it given that the center of rectangle is known along with the coordinates of its four edges.
For example, let's say we want to test if rectangle is obstacle free 5 units from either of its edges.
Rectangles marked with green dot are ok, while the unmarked are clearly collide.
It seems trivial for non rotated rectangles however, I am having a hard time coming up with algorithm which can handle rotated rectangles.
Simply looping starting from the center till we hit empty space and then checking for obstacles in the empty space doesn't seem to work if rectangles are touching each other.
Since you seem to be operating with an image-oriented mindset, you can use image processing.
Apply a radius-2.5 dilation filter to your image.
Treat the image as a graph where there is an edge between two pixels if they both have a red value above some threshold.
Any rectangles that have a path between them are at most 5 apart. (Although, note that this will give you the transitive closure of the "too close" relationship.)
Given a set of n points (a_1, b_1), (a_2, b_2), ..., (a_n, b_n). Need to find the minimum x such that three axis parallel squares each of length x together covers all of the points.
I can find the rectangle with smallest area enclosing all the points. Can this rectangle be used somehow? Or any hint on how to approach this problem?
I think, it is enough to consider two cases:
When each square touches some edge of smallest-area rectangle.
When two squares are located at opposite corners of smallest-area rectangle while third one lies inside (does not touch any edge of smallest-area rectangle).
In first case we could fix corner of one square at one of 4 rectangle's corners, then fix corners of other two squares somewhere at two opposite (to chosen corner) edges of the rectangle (n possible positions for each one), then for each point determine optimal square where it belongs and minimum x.
In second case try two opposite pairs of rectangle corners for "outer" squares, then fix one of corners of the "inner" square at all n*n positions determined by all x and y point coordinates, then for each point determine optimal square where it belongs and minimum x.
Time complexity would be O(n3).
The answer of #EvgenyKluev seems to go in the right direction, but there's a couple of subtleties that I'd like to address.
Since I didn't see a restriction for x being integer, you might want to go with binary search on x to guide your algorithm, and find suitable terminating conditions when the range still available for x is small enough (you would do binary search for integer x as well, but there you don't need a terminating condition).
The placement of a square in one corner of the rectangle (something that you will have to do, somewhat straightforward to prove) limits your search space for the placement of the other two squares: let A be the set of points covered by the corner-aligned first square, and let S be the set of all points. Take S-A and find the enclosing rectangle of that set of points. Placing the remaining two squares at opposite corners of the enclosing rectangle of S-A will always be a solution (only one pair of opposite corners might fit), if one exists.
Thus, one algorithm could - very high level - go like this
binary search for x on [0,N]:
find R(S), the enclosing rectangle of S
for each corner C of R(S):
align one square at C, let the points covered by that square be A
find R(S-A)
do two squares aligned at opposite corners of R(S-A) cover S-A?
As for the binary search, I can't really say how fast that will converge to a range that allows only one alignment of squares, at which point you can directly calculate the value x - I expect that with arbitrary precision, you can make that arbitrarily bad. Each iteration takes O(n log n) for sorting the points in both cardinal directions.
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.