I have a (not necessarily convex) polygon. I'd like to find a set of rectangles that take up all space in the world bounds ((0,0) to (100,100)) without taking up any space inside the polygon. What's the easiest way to find these polygons? Are there algorithms for this sort of thing?
Thanks!
For example, the polygon
__ __
| |__| |
|________|
could be broken in to the following five rectangles:
aaabbbbbbbbbbeee
aaa| |cc| |eee
aaa|________|eee
aaaddddddddddeee
or, alternatively, the following six rectangles:
aaaaaaabbccccccc
eee| |bb| |ddd
eee|________|ddd
ffffffffffffffff
Is there an easy way to break a polygon into the rectangles between the polygon and the world boundaries?
All that I can glean: It's possible but impractical (especially if your polygon has slanted lines). I don't need this answer any more, but I guess that the algorithm would look something like the following:
Use triangles to make all edges of the polygon either vertical or horizontal
Use four rectangles to cut out as much space as you can on the top/bottom/left/right
Now you're left with a polygon that has only vertical/horizontal edges and which extends to every border
Greedily place the biggest rectangle you can in the biggest holes in the shape
Look for the largest gaps between sides
Fill the triangles from step 1 up to a terminal precision
Related
I am trying to implement a decal mesh generator as described here: http://blog.wolfire.com/2009/06/how-to-project-decals/. The blog suggests an algorithm for triangulation of the intersection polygon between a triangle and square:
First, we can start with one border at a time. Let's pick the left
border. To crop the triangle, we start by marking every vertex in
violation of the rule -- in this case, the leftmost one. Then we look
at every line between a marked vertex and an unmarked vertex, and add
a vertex at the point at which it crosses the border.
We can then simply remove the marked vertex (or vertices), and move
onto the next border.
Once we've checked all the borders, we have a cropped triangle!
I attempted this algorithm on paper and it doesn't seem like its covering all cases. It seems that its description is missing some critical detail that I have missed. Could someone post a pseudo code implementation?
EDIT: To be more specific, the part that I am unclear on is how the algorithm is able to determine the right "cut" between (black line)
and
When there are multiple choices.
Secondly why does the algorithm not make a cut between the top point of polygon and the bottom left point in picture 2? The algorithm states that "we look
at every line between a marked vertex and an unmarked vertex, and add
a vertex at the point at which it crosses the border", isnt the bottom left point an unmarked vertex?
A reliable way to derive the algorithm is to consider the problem of intersecting a triangle and a half-plane.
First determine if the vertices are in or out of the half plane. This leads to 8 configurations: one such that the whole triangle is discarded, one such that it is left unchanged, three such that it is cropped to a quadrilateral and three such that it is cropped to another triangle.
In the case of a quadrilateral, you split it in two via a diagonal.
After this step, you have 0, 1 or 2 triangles remaining, and you just repeat the operation with the next clipping half-plane on each of them. Bulletproof.
If the triangles are large and are often clipped on several sides (which I doubt), you can consider intersecting with two half-planes forming a stripe at a time. There are 27 cases and the output is made of from 0 to 3 sub-triangles. This can save a few comparisons and intersection computations.
Direct clipping by a rectangle seems complicated.
I have arbitrary many lines in 3D space which are all parallel to each other. Now I want to find the convex hull of these lines. To illustrate this, I've drawn a picture:
I know the start- and endpoints of all lines (the blue dots). The lines are not equally long. If a viewer looks in the direction of the lines (marked as the viewer direction in the pic) he sees only the dots. Now I want to find the convex hull of these dots. Hopefully its clear what I mean.
My idea was to project the start or endpoints on a plane which is perpendicular to the line's direction. After that I can apply some kind of convex hull algorithm to these points. But I have no idea how.
Your idea is exactly correct. One way to accomplish this is to define a vector v along your viewing direction, and then rotate v to the z-axis. The same rotation will convert lines to vertical lines. Then drop the z-coordinate of the endpoints to get your projected points. Then compute the convex hull. There are hull algorithms all over the web, including my own here.
Here's a suggestion based on the calculus of variations.
Consider enclosing your collection of parallel line segments in a simple closed curve minimizing the area of the curve given the constraint that it has to enclose all your segments.
Your "curve" is going to be piecewise linear, so there you might be able to use a P.W basis function in the iterations, though it's possible that you could run into some singularities when the algorithm needs to drop a segment.
I know the Bresenham and related algorithms, and I found a good algorithm to draw a circle with a 1-pixel wide border. Is there any 'standard' algorithm to draw a circle with an n-pixel wide border, without restoring to drawing n circles?
Drawing the pixel and n2 surrounding pixels might be a solution, but it draws many more pixels than needed.
I am writing a graphics library for an embedded system, so I am not looking for a way to do this using an existing library, although a library that does this function and is open source might be a lead.
Compute the points for a single octant for both radii at the same time and simultaneously replicate it eight ways, which is how Bresenham circles are usually drawn anyway. To avoid overdrawing (e.g., for XOR drawing), the second octant should be constrained to draw outside the first octant's x-extents.
Note that this approach breaks down if the line is very thick compared to the radius.
Treat it as a rasterization problem:
Take the bounding box of your annulus.
Consider the image rows falling in the bounding box.
For each row, compute the intersection with the 2 circles (ie solve x^2+y^2=r^2, so x=sqrt(r^2-y^2) for each, for x,y relative to the circle centres.
Fill in the spans. Repeat for next row.
This approach generalizes to all sorts of shapes, can produce sub-pixel coordinates useful for anti-aliasing and scales better with increasing resolution than hacky solutions involving multiple shifted draws.
If the sqrt looks scary for an embedded system, bear in mind there are fast approximate algorithms which would probably be good enough, especially if you're rounding off to the nearest pixel.
I have an interesting problem that I've been trying to solve for a while. There is no "right" solution to this, as there is no strict criteria for success. What I want to accomplish is a smooth transition between two simple polygons, from polygon A to polygon B. Polygon A is completely contained within polygon B.
My criteria for this transition are:
The transition is continuous in time and space
The area that is being "filled" from polygon A into polygon B should be filled in as if there was a liquid in A that was pouring out into the shape of B
It is important that this animation can be calculated either on the fly, or be defined by a set of parameters that require little space, say less than a few Kb.
Cheating is perfectly fine, any way to solve this so that it looks good is a possible solution.
Solutions I've considered, and mostly ruled out:
Pairing up vertices in A and B and simply interpolate. Will not look good and does not work in the case of concave polygons.
Dividing the area B-A into convex polygons, perhaps a Voronoi diagram, and calculate the discrete states of the polygon by doing a BFS on the smaller convex polygons. Then I interpolate between the discrete states. Note: If polygon B-A is convex, the transition is fairly trivial. I didn't go with this solution because dividing B-A into equally sized small convex polygons was surprisingly difficult
Simulation: Subdivide polygon A. Move each vertex along the polygon line normal (outwards) in discrete but small steps. For each step, check if vertex is still inside B. If not, then move back to previous position. Repeat until A equals B. I don't like this solution because the check to see whether a vertex is inside a polygon is slow.
Does anybody have any different ideas?
If you want to keep this simple and somewhat fast, you could go ahead with your last idea where you consider scaling polygon A so that it gradually fills polygon B. You don't necessarily have to check if the scaled-outward vertices are still inside polygon B. Depending on what your code environment and API is like, you could mask the pixels of the expanding polygon A with the outline of polygon B.
In modern OpenGL, you could do this inside a fragment shader. You would have to render polygon B to a texture, send that texture to the shader, and then use that texture to look up if the current fragment being rendered maps to a texture value that has been set by polygon B. If it is not, the fragment gets discarded. You would need to have the texture be as large as the screen. If not, you would need to include some camera calculations in your shaders so you can "render" the fragment-to-test into the texture in the same way you rendered polygon B into that texture.
I am working with a Microchip dsPIC33FJ128GP802. It's a small DSP-based microcontroller, and it doesn't have much power (40 million instructions per second). I'm looking for a way to render a convex (i.e. simple) polygon. I am only dealing with 2D shapes, integer math, and set or clear pixels (i.e. 1 bit per pixel.) I already have routines for drawing fast horizontal and vertical lines (writing up to 16 pixels in 88 cycles), so I would like to use a scanline algorithm.
However, all the algorithms I have found seem to depend on division (which takes 18 cycles on this processor) and floating point math (which is emulated in software and so is very slow; it also takes up a lot of ROM), or assume that I have a large amount of memory. I only have 2K left, ~14K is used for graphics RAM of my 16K. So does anyone know of any good, embedded machine algorithms they can point me to with a simple C or pseudocode implementation which I can implement in assembly? Preferably on the 'net, I don't live near any good bookstores with many programming books.
Thanks. :)
EDIT: Clarification, this is a polygon filling algorithm I'm looking for. I can implement a polygon outline algorithm using Bresenham's line drawing algorithm (as Marc B suggests.)
EDIT #2: I wanted to let everyone know I got a basic algorithm up in Python. Here's a link to the code. Public domain code.
http://dl.dropbox.com/u/1134084/bresenham_demos.py
How about Bresenham's Line algorithm? After some setup, it's pure integer math, and can be adapted to draw a polygon by simple iteration of starting points along the polygon edges.
comments followup:
I'll try to draw this in ASCII, but it'll probably look like crud. Bresenham's can be used to draw a filled polygon by picking a starting edge, and iteratively moving a bresenham line across the canvas parallel to that point.
Let's say you've got some points like this:
*(1)
*(3)
*(2)
*(4)
These are numbered in left-right sort priority, so you pick the left-most starting point (1) and decide if you want to go vertically (start 1,2) or horizontally (1,3). That'd probably depend on how your DSP does its display, but let's go with vertical.
So... You use the 1-2 line as your starting bresenham line. You calculate the starting points of your fill lines by using lines 1-3 and 2-4 as your start/end points. Start a bresenham calculation for each, and draw another Bresenham between those two points. Kinda like:
1.1 -> 2.1, then 1.2 -> 2.2, then 1.3 -> 2.3
etc... until you reach the end of either of those lines. In this case, that'd be when the lower starting point reaches (4). At that point, you start iterating up the 4,3 line, until you reach point 3 with both starting points, and you're done.
*-------
\\\\\\\\ *
\\\\\\\\
*-----\\
------- *
Where the dashes are the starting points you calculated along 1-3 and 2-4, and the slashes are the fill lines.
Of course, this only works if the points are properly sorted, and you've got a convex polygon. If it's concave, you'll have to be very careful to not let your fill lines cross over the border, or do some pre-processing and subdivide the original poly into two or more convex ones.
You may want to look at Michael Abrash's articles on Dr Dobbs about polygon fill/raster/etc. It uses fixed-point math
Thomas, if you have a Bresenham line drawing algorithm available, then use it as a basis for further enhancement: divide your polygon to sub-polygons with an horizontal cutting line through every vertex. Then, start tracing the 2 left and right sides of each of these sub-polys, using Bresenham. This way you have the 2 end-points of each scan line in your polygon.
I would start by converting the polygon to a collection of triangles and render those, because triangles are easy to render by scanlines. Although even so there are some details.
Essentially, the draw-triangle sub-procedure will be given a raw triangle and proceed:
Reject degenerate triangles (where two of the three vertices overlap).
Sort the vertices in Y (since there are only three you can hardcode the sorting logic).
Now, at this point you should know that there will be three kinds of triangles: ones with a flat top, ones with a flat bottom, and "general" triangles. You want to handle a general triangle by essentially splitting it into one each of the flat types. This is because you don't want to have an if test every scanline to detect if the slope changed.
To render a flat triangle, you would run two Bresenham algorithms in parallel to iterate the pixels comprising the edges, and use the points they give you as the endpoints of each horizontal scanline.
It may be easier to break the problem into two parts. First, locate/write an algorithm that draws and fills a triangle. Second, write an algorithm that breaks up an arbitrary polygon into triangles (using different combinations of the vertices).
To draw/fill a triangle, use Bresenham's Line Algorithm to simultaneously draw a line between points 0 and 1, and between 1 and 2. For each input point x, draw the pixel if it is equal to or in between the y points generated by the two lines. When you reach one endpoint, continue by using the unfinished side and the side that has not yet been used.
Edit:
To break your convex polygon into triangles, arrange the points in order and call them P1, P2, ... PN. Let P1 be your "root" point, and build triangles using that point and combinations of adjacent points. For example, a pentagon would yield the three triangles P1-P2-P3, P1-P3-P4, and P1-P4-P5. In general, a convex polygon with N sides will decompose into N-2 triangles.