Where would i go to look for algorithms that take a 2d grid of values that are either 0 or 1 as input and then identifies all possible non-overlapping rectangles in it?
In a more practical explanation: I am drawing a grid that is represented by a number of squares, and i wish to find a way to combine as many adjacent squares into rectangles as possible, in order to cut down on the time spent on cycling through each square and drawing it.
Maximum efficiency is not needed, speed is more important.
Addendum: Apparently what i am looking for seems to be a technique called Tesselation. Now i only need to find a good description for this specific case.
Addendum 2: The boundary of the "1" squares will be irregular and in some cases not even connected, as the distribution of "1" squares will be completely random. I need these irregular shapes to be identified and split up into regular rectangles.
Correct answer: To get the best balance between speed and efficiency it is optimal to use the grid data to fill a quad-tree with each node having a status value of either empty/partly filled/filled.
I've done something similar for a quick-and-dirty voxel visualization of 3d boxes with OpenGL.
I started from the top left box and stored the empty/filled flag. Then I tried to expand the rectangle to the right until I hit a box with a different flag. I did the same in the down direction.
Draw the rectangle, if it is filled.
If there are boxes remaing, recursivly repeat the procedure for all three remaing rectangles induced by the last rectangle, which are right, bottom and bottom right:
xxxx 1111
xxxx 1111
xxxx 1111
2222 3333
2222 3333
2222 3333
Have a look at this article from Dr Dobb's Portal on finding a maximal rectangle in your situation. It is a very detailed discussion of an extremely efficient algorithm, and I think that repeating it iteratively would possibly solve your problem.
As you are not looking for the minimum number of squares I would suggest using a compromise that still keeps your algorithm simple.
What the best solution is depends on your data, but one simple alternative is to just collect boxes along one row. I.e:
0 0 1 1 1 0 0 0 1 1 1 1 0
Will result in:
skip 2
draw 3
skip 3
draw 4
skip 1
This will reduce the number of calls to draw box without any need of caching (i.e you can build your boxes on the fly).
If you want to create bigger boxes I would suggest a backtracking algorithm there you find the first 1 and try to expand the box in all directions. Build a list of boxes and clear the 1:s as you have used them.
So you are looking for the rectangular boundary of the 'ON' squares?
Do you want the inner or outer bound?
ie. Must the boundary only have 'ON' squares or do you want the rectangle to contain all the 'ON' squares in a group?
I had to solve a similar problem, my algorithm supports jagged arrays, I have heavily tested and commented it but it's slower than joel-in-gö's suggestion :
https://stackoverflow.com/a/13802336
Related
In my study I calculate some ratios. The theoretical background is as follows:
There is the effect of Binocular Rivalry, where a different picture is presented to the left eye than to the right eye (e.g. a black and a white square). Most of the time, the test persons do not see a mixture of colours (i.e. something grey), but the picture changes back and forth, so a black square is seen once and then a white one. During the time of the trial (e.g. 60 seconds) the test persons indicate what they see (black square, white square, mixed picture). These durations can be used to calculate the predominance ratio as an indication of whether one stimulus is seen significantly more often than the other. The ratio is calculated from [T(stimulus1)-T(stimulus2)/T(stimulus1)+T(stimulus2)], where T is the cumulative time the stimulus was seen during the 60 seconds. The times for the mixed image are completely omitted from this calculation. In the end the ratio is tested if it is significantly different from zero with a one-sample t-test. If it is significantly different from zero and positive, stimulus 1 is seen longer, if it is significantly different from zero and negative, stimulus 2 is seen longer. Now I have two conditions and I calculate a predominance ratio for each.
Let us suppose that condition 1 would be the squares I mentioned above and condition 2 would be a stick figure in black and a tree in white. I want to know if there is a significant predominance ratio in the stickman/tree condition, but without the influence of the colors. Therefore I want to somehow deduct the predominance ratio from condition 1 from condition 2. So I would like to do a kind of "baseline correction". The value of this predominance ratio can vary between -1 and 1. Now my question is how to do this correction without changing the metrics of the ratio. In order to test the corrected ratio towards zero in a meaningful way, it must not take any other values than from -1 to 1.
Does anyone have an idea?
Thanks a lot!
wondering if anyone has any insight as to how to ascertain the order of differently sized rectangles from left to right and from top to bottom when they are not already aligned to any grid, and they are differently sized and/or rotated. Some might also be missing.
As anyone can see from the illustration, the objects should be numbered as shown. But how, mathematically or programmatically, can I determine this? What is the logic? I don't even know what words to use to describe the problem.
This looks like a rather complex problem; maybe some algorithm already exists, IDK.
Approach 1: grid positioning.
One approach could start with trying to position the rectangles on a grid whose mesh size will have to be calculated; maybe a best fit to the size of the rectangles (H & W, or surface, maybe?)
Once a reasonable grid has been determined, it must be appropriately placed over the rectangles; maybe in such a way that minimizes row overlap and column overlap of the rectangles?
The last step would consist of traversing the grid row by row, and assigning a label to each rectangle; maybe based on the max common surface shared by a grid cell and a rectangle?
There will be many edge cases to identify and resolve.
Approach 2: sweep line.
Alternatively, a sweep line numbering of the rectangles from N, S, E, and W, and an appropriate weighting/averaging of the numbering of the rectangles from each direction, might give good results?
It may require several passes, after identifying what could be rows and columns, in order to find a "best fit".
This second approach is likely easier to implement.
Concerning tree searching algorithms, particularly quad-tree and r-tree, how do they account for edge errors when finding nearest neighbors. I'm not good at explaining this with words so I made some pictures.
For the picture the input coordinate to find the nearest neighbor is green, what I would assume end up being the "found" nearest neighbor is red. The actual nearest neighbor is blue.
In this quad-tree, the blue lower-right quadrant would be searched in with only that one red point while in actuality, the input coordinate (green) is so close to the edge it's actually closer to the blue point.
Similar with an R-tree if the coordinate is within one rectangle but so close to the edge it's closer to a point in another rectangle like below, where white dot is given coordinate:
It's wholly within the red box but closer to a point in the magenta box.
In both cases it is necessary to do a fine-grain distance check between elements - the boxes or divisions just help find candidates for the real distance check.
A way to look at it is, use the boxes to tell you what NOT to check. If an entire box is farther away than something you already know, you don't need to check anything in that box. If some of the box is close, better check the elements in it.
If you would bother to read the R-tree publication...
It uses a minimum distance, of the query point to a neighboring page.
If mindist(query, rectangle) <= dist(query, known neighbor) then the search needs to continue in the other rectangle, because there could be a better neighbor there.
It's actually quite straightforward, and should be explained in any book on R-trees and similar indexes.
I have a set of 2D points, unorganized, and I want to find the "contour" of this set (not the convex hull). I can't use alpha shapes because I have a speed objective (less than 10ms on an average computer).
My first approach was to compute a grid and find the outline squares (squares which have an empty square as a neighbor). So I think I downsized efficiently my numbers of points (from 22000 to 3000 roughly). But I still need to refine this new set.
My question is : how do I find the real outlines points among my green points ?
After a weekend full of reflexions, I may have found a convenient solution.
So we need a grid, we need to fill it with our points, no difficulty here.
We have to decide which squares are considered as "Contour". Our criteria is : at least one empty neighbor and at least 3 non empty neighbors.
We lack connectivity information. So we choose a "Contour" square which as 2 "Contour" neighbors or less. We then pick one of the neighbor. From that, we can start the expansion. We just circle around the current square to find the next "Contour" square, knowing the previous "Contour" squares. Our contour criteria prevent us from a dead end.
We now have vectors of connected squares, and normally if our shape doesn't have a hole, only one vector of connected squares !
Now for each square, we need to find the best point for the contour. We select the one which is farther from the barycenter of our plane. It works for most of the shapes. Another technique is to compute the barycenter of the empty neighbors of the selected square and choose the nearest point.
The red points are the contour of the green one. The technique used is the plane barycenter one.
For a set of 28000 points, this techniques take 8 ms. CGAL's Alpha shapes would take an average 125 ms for 28000 points.
PS : I hope I made myself clear, English is not my mothertongue :s
You really should use the alpha shapes. Maybe use only green points as inputs of the alpha alpha algorithm.
I have brown filled svg paths and i want to detect and alert my user if there is any shape behind or above another shape. I know intersection list gets if they intersect at the edges but what happens if i want to detect a shape that is behind another shape but doesnt intersect at the edges?
The encoluseList method seems to be dealing with bounding boxes and not this.
Any ideas?
To detect if a path/shape overlaps another
1. Calculating the area covered by the final shape achieved
2. Calculating the sum of areas of all the shapes independently(since this is SVG and the details of each path element is known, this can be done)
3. Comparing the 2 areas.If the 2 areas are the same, then there is no overlapping otherwise at least 2 shapes overlap.
The tricky step is step 1 which can be approximately calculated using pixel painting algorithm(my preference). For other methods, you can go through the following stackoverflow question concerning area of overlapping circles