From the docs:
QPainter offers two methods of painting QPolygons: drawPolygon and drawConvexPolygon.
Nowhere in the documentation is it made clear what the difference between them is. Additionally, the drawConvexPolygon docs state
If the supplied polygon is not convex, i.e. it contains at least one angle larger than 180 degrees, the results are undefined.
So... what is it for? I hoped the method would somehow find the convex hull of my polygon and paint that, however that doesn't seem to be the case.
The QPainter::drawConvexPolygon() documentation says:
On some platforms (e.g. X11), the drawConvexPolygon() function can be faster than the drawPolygon() function.
So,
drawPolygon() is more generic as it also allows to paint non-convex polygons (but drawing might be slower)
drawConvexPolygon() can only be used to draw convex polygons, but might be faster on specific platforms
For example, when doing 3D-rendering, you can use a Polygon Mesh which consists of convex polygons only to make rendering simpler, in which case the faster drawConvexPolygon() would be the better choice (since you need to paint a large number of convex polygons).
Determining which part of the polygon is the outside and inside (for filling purposes) makes different choices depending on if the polygon contains a convex region. Think about how to determine the inside of a star shape vs. the inside of a rectangle.
Related
Ok, here is the thing. Recently i decided i wanted to understand how Random map generation works. I found some papers and some arguments. The most interesting one was "Diamond Square algorithm" and "Midpoint Displacement". I still have to try to apply those to a software, but other than that, i ran into this site: http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/
As you can see, the idea is to use polygons. But i have no idea how to apply that a Tile-Based map, not even how to create those polygons using the tools i have (c++ and sdl). I am assuming there is no way to do it ( please correct me if i am wrong.) But if i am not, how does a non-tile map works, and how are these polygons generated?
This answer will not give you directly the answers you're looking for, but hopefully will get you close enough!
The Problem
I think what blocks you is how to represent the data. You're probably used to a 2D grid that simply represent the type of each tile. As you know, this is fine to handle a tile-based map, but doesn't properly allow you to model worlds where tiles are of a different shape.
Graphs
What I suggest to you, is to see the problem a bit differently. A grid is nothing more than a graph (more info) with nodes that have 4 (or 8 if you allow diagonals) implicit neighbor nodes. So first, what I would do if I was you, would be to move from your strict standard 2D grid to a more "loose" graph, where each node has a position, a position, a list of neighbors (in most cases you'll have corners with 2 neighbors, borders with 3 and "middle" tiles with 4) and finally a rendering component which simply draws your tile on screen at the given position. Once this is done, you should be able to have the exact same results on screen that you currently have with your "2D Tile-Based" engine by simply calling the rendering component with each node who's bounding box (didn't touch it in what you should add to your node, but I'll get back to this later) intersects with the camera's frustum (in a 2D world, it would most likely if the position +/- the size intersects the RECT currently being drawn).
Search
The more generic approach will also help you doing stuff like pathfinding with generic algorithms that explore nodes until they find a valid path (see A* or Dijkstra). Even if you decided to stick to a good old 2D Tile Map game, these techniques would still be useful!
Yeah but I want Polygons
I hear you! So, if you want polygons, basically all you need to do, is add to your nodes a list of vertices and the appropriate data that you might need to render your polygons (either vertex color, textures and U/V maps, etc...) and update your rendering component to do the appropriate OpenGL (this for example should help) calls to draw your nodes. Once again, the first step to iteratively upgrade your 2D Tile Engine to a polygon map engine would be to, for each tile in your map, give each of your nodes two triangles, a texture resource (the tile), and U/V mappings (0,0 - 0,1 - 1,0 and 1,1). Once again, when this step is done, you should have a "generic" polygon based tile map engine. The creation of most of this data can be created procedurally by calculating coordinates based on tile position, tile size, etc...
Convex Polygons
If you decide that you ever might need NPCs to navigate on your map or want to allow your player to navigate by clicking the map, I would suggest that you always use convex polygons (the triangle being the simplest for of a convex polygon). This allows your code that assume that two different positions on the same polygon can be navigated to in straight line.
Complex Maps
Based on the link you provided, you want to have rather complex maps. In this case, the author used Voronoi Diagrams to generate the polygons of the map. There are already solutions to do triangulation like that, but you might also want to use other techniques that are easier to work with if you're just switching to 3D like this one for example. Once you have interesting results, you should consider implementing serialization to save/open your map data from the game. If you want to create an editor, be aware that it might be a lot of work but can be worth it if you want people to help you creating maps or to add elements to the maps (like geometry that's not part of the terrain).
I went all over the place with this answer, but hopefully it helps!
Just iterate over all the tiles, and do a hit-test from the centre of the tile to the polys. Turn the type of the tile into the type of the polygon. Did you need more than that?
EDIT: Sorry, I realize that probably isn't helpful. Playing with procedural algorithms can be fun and profitable. Start with a loop that iterates over all tiles and chooses randomly whether or not the tile is occupied. Then, iterate over them again and choose whether it is occupied or its neighbour is.
Also, check out the source code for this: http://dustinfreeman.org/toys/wall7-dustin.html
I have been looking at posts about determining if a point lies within a polygon or not and the answers are either too vague, abstract, or complex for me. So I am going to try to ask my question specific to what I need to do.
I have a set of points that describe a non-straight line (sometimes a closed polygon). I have a rectangular "view" region. I need to determine as efficiently as possible whether any of the line segments (or polygon borders) pass through the view region.
I can't simply test each point to see if it lies within the view region. It is possible for a segment to pass through the region without any point actually inside the region (ie the line is drawn across the region).
Here is an example of what I want to determine (red means the function should return true for the set of points, blue means it should return false, example uses straight lines and rectangles because I am not an artist).
Another condition I want to be able to account for (though the method/function may be a separate one), is to determine not just whether a polygon's border passes through the rectangular region, but whether the region is entirely encompassed by the polygon. The nuance here is that in the situation first described above, if I am only concerned with drawing borders, the method should return false. But in the situation described here, if I need to fill the polygon region then I need the function to return true. I currently do not need to worry about testing "donut" shaped polygons (thank God!).
Here is an example illustrating the nuance (the red rectangle does not have a single vertex or border segment passing through the on-screen region, but it should still be considered on-screen):
For the "does any line segment or polygon border pass through or lie on screen?" problem I know I can come up with a solution (albeit perhaps not an efficient one). Even though it is more verbose, the conditions are clear to me. But the second "is polygon region on screen?" problem is a little harder. I'm hoping someone might have a good suggestion for doing this. And if one solution is easily implemented on top of the other, well, booya.
As always, thank you in advance for any help or suggestions.
PS I have a function for determining line intersection, but it seems like overkill to use it to compare each segment to each side of the on-screen region because the on-screen region is ALWAYS a plain [0, 0, width, height] rectangle. Isn't there some kind of short-cut?
What you are searching for is named a Collision Detection Algorithm A Google search will lead you to plenty of implementations in various language as well as a lot of theory
There are plenty of Geometric theory behind, from the simplest bisector calculus to Constrained Delaunay Triangulations and Voronoi Diagrams (that are just examples). It depends on the shape of Object, the number of dimensions and for sure the ratio between exactness needed and computing time afforded ;-)
Good read
PS I have a function for determining
line intersection, but it seems like
overkill to use it to compare each
segment to each side of the on-screen
region because the on-screen region is
ALWAYS a plain [0, 0, width, height]
rectangle. Isn't there some kind of
short-cut?
It's not an overkill, its neccessary here. The only kind of shortcut I can think of is to hardcode values [0, 0, width, height] into that function and simplify it a bit.
I have a 2D computational geometry / GIS problem that I think should be common and I'm hoping to find some existing code/library to use.
The problem is to check which subset of a big set (thousands) of small polygons intersect with a single large polygon. (By "small" and "large" I'm referring to the amount of space the polygons cover, not the number of points that define them, although in general suppose that the number of points defining a polygon is roughly proportional to its geometric size. And to give a sense of proportion, think of "large" as the polygon for a state in the United States, and "small" as the polygon for a town.)
Suppose the naive solution using a standard CheckIfPolygonsIntersect( P, p ) function, called for each small polygon p against the one large polygon P, is too slow. It seems that there are ways to pre-process the large polygon to make the intersection checks for the majority of the small polygons trivial. In particular, it seems like you could create a small set of rectangles that partially/almost fill the large polygon. And similarly you could create a small set of rectangles that partially/almost fill the area of the bounding box of the large polygon that is not actually within the large polygon. Then the vast majority of your small polygons could be trivially included or excluded: if they are fully outside the bounding rect of the large polygon, they are excluded. If they are fully inside the boundary of one of the inside-bounding-rect-but-outside-polygon rects, they are excluded. If any of their points are within any of the internal rects, they are included. And only if none of the above apply do you have to call the CheckIfPolygonsIntersect( P, p ) function.
Is that a well-known algorithm? Do you know of existing code to compute a reasonable set of interior/exterior rectangles for arbitrary (convex or concave) polygons? The rectangles don't have to be perfect in all cases; they just have to fill much of the polygon, and much of the inside-bounding-rect-but-outside-polygon area.
Here's a simple plan for how I might compute these rectangles:
take the bounding box of the large polygon and construct a, say, 10x10 grid of points over it
for each point, determine if it's inside or outside the polygon
"grow" each point into a rectangle by iteratively expanding it in each of the four directions until one of the rect edges crosses one of the polygon edges, in which case you've gone too far (this would actually be done in a "binary search" kind of iteration so with just a few iterations you could find the correct amount to expand in each direction; and of course there is some question of whether to maximize the edges one at a time or in concert with one another)
any not-yet-expanded grid point that get covered by another point's expansion just disappears
when all points have been expanded (or have disappeared), you have your set of interior and exterior rectangles
Of course, certain crazy concave shapes for the large polygon could lead to some poor/small rectangles. But assuming the polygons are mostly reasonable (e.g., say they were the shapes of the states of the United States), it seems like you'd get a good set of rectangles and could greatly optimize those thousands of intersection checks you'd subsequently do.
Is there a name (and code) for that algorithm?
Edit: I am already using a quad-tree to determine the small polygons that are likely to intersect with the bounding rect of the large polygon. So the problem is about checking which of those polygons actually do intersect with the large polygon.
Thanks for any help.
In your plan you described something very similar to the signed distance map method. Google 'distance map algorithm' for details. I hope it will be what you're looking for.
Given an arbitary polygon with vertices stored in either clockwise/counterclockwise fashion (depicted as a black rectangle in the diagram), I need to be able to subtract an arbitrary number of circles (in red on the diagram) from that polygon. Removing a circle could possibly split the polygon into two seperate polygons (as depicted by the second line in the diagram).
I'm not sure where to start.
Example http://www.freeimagehosting.net/uploads/89a0276d9d.jpg
Warning: getting code to do this absolutely right is tricky. (Conceptually it's fine, but you can quickly get bogged down in numerical errors and edge cases.) You're basically asking for a 2D version of Constructive Solid Geometry. You might want to see if you can use an existing library written by an expert in computational geometry. There are some libraries here that will probably do what you want, but you'll have to choose a representation that suits you best and convert what you have into that representation.
Here's a freeware polygon clipping library (written in Delphi and C++) that does what you're asking: http://sourceforge.net/projects/polyclipping/
I'm looking for a very simple algorithm for computing the polygon intersection/clipping.
That is, given polygons P, Q, I wish to find polygon T which is contained in P and in Q, and I wish T to be maximal among all possible polygons.
I don't mind the run time (I have a few very small polygons), I can also afford getting an approximation of the polygons' intersection (that is, a polygon with less points, but which is still contained in the polygons' intersection).
But it is really important for me that the algorithm will be simple (cheaper testing) and preferably short (less code).
edit: please note, I wish to obtain a polygon which represent the intersection. I don't need only a boolean answer to the question of whether the two polygons intersect.
I understand the original poster was looking for a simple solution, but unfortunately there really is no simple solution.
Nevertheless, I've recently created an open-source freeware clipping library (written in Delphi, C++ and C#) which clips all kinds of polygons (including self-intersecting ones). This library is pretty simple to use: https://github.com/AngusJohnson/Clipper2
You could use a Polygon Clipping algorithm to find the intersection between two polygons. However these tend to be complicated algorithms when all of the edge cases are taken into account.
One implementation of polygon clipping that you can use your favorite search engine to look for is Weiler-Atherton. wikipedia article on Weiler-Atherton
Alan Murta has a complete implementation of a polygon clipper GPC.
Edit:
Another approach is to first divide each polygon into a set of triangles, which are easier to deal with. The Two-Ears Theorem by Gary H. Meisters does the trick. This page at McGill does a good job of explaining triangle subdivision.
If you use C++, and don't want to create the algorithm yourself, you can use Boost.Geometry. It uses an adapted version of the Weiler-Atherton algorithm mentioned above.
You have not given us your representation of a polygon. So I am choosing (more like suggesting) one for you :)
Represent each polygon as one big convex polygon, and a list of smaller convex polygons which need to be 'subtracted' from that big convex polygon.
Now given two polygons in that representation, you can compute the intersection as:
Compute intersection of the big convex polygons to form the big polygon of the intersection. Then 'subtract' the intersections of all the smaller ones of both to get a list of subracted polygons.
You get a new polygon following the same representation.
Since convex polygon intersection is easy, this intersection finding should be easy too.
This seems like it should work, but I haven't given it more deeper thought as regards to correctness/time/space complexity.
Here's a simple-and-stupid approach: on input, discretize your polygons into a bitmap. To intersect, AND the bitmaps together. To produce output polygons, trace out the jaggy borders of the bitmap and smooth the jaggies using a polygon-approximation algorithm. (I don't remember if that link gives the most suitable algorithms, it's just the first Google hit. You might check out one of the tools out there to convert bitmap images to vector representations. Maybe you could call on them without reimplementing the algorithm?)
The most complex part would be tracing out the borders, I think.
Back in the early 90s I faced something like this problem at work, by the way. I muffed it: I came up with a (completely different) algorithm that would work on real-number coordinates, but seemed to run into a completely unfixable plethora of degenerate cases in the face of the realities of floating-point (and noisy input). Perhaps with the help of the internet I'd have done better!
I have no very simple solution, but here are the main steps for the real algorithm:
Do a custom double linked list for the polygon vertices and
edges. Using std::list won't do because you must swap next and
previous pointers/offsets yourself for a special operation on the
nodes. This is the only way to have simple code, and this will give
good performance.
Find the intersection points by comparing each pair of edges. Note
that comparing each pair of edge will give O(N²) time, but improving
the algorithm to O(N·logN) will be easy afterwards. For some pair of
edges (say a→b and c→d), the intersection point is found by using
the parameter (from 0 to 1) on edge a→b, which is given by
tₐ=d₀/(d₀-d₁), where d₀ is (c-a)×(b-a) and d₁ is (d-a)×(b-a). × is
the 2D cross product such as p×q=pₓ·qᵧ-pᵧ·qₓ. After having found tₐ,
finding the intersection point is using it as a linear interpolation
parameter on segment a→b: P=a+tₐ(b-a)
Split each edge adding vertices (and nodes in your linked list)
where the segments intersect.
Then you must cross the nodes at the intersection points. This is
the operation for which you needed to do a custom double linked
list. You must swap some pair of next pointers (and update the
previous pointers accordingly).
Then you have the raw result of the polygon intersection resolving algorithm. Normally, you will want to select some region according to the winding number of each region. Search for polygon winding number for an explanation on this.
If you want to make a O(N·logN) algorithm out of this O(N²) one, you must do exactly the same thing except that you do it inside of a line sweep algorithm. Look for Bentley Ottman algorithm. The inner algorithm will be the same, with the only difference that you will have a reduced number of edges to compare, inside of the loop.
The way I worked about the same problem
breaking the polygon into line segments
find intersecting line using IntervalTrees or LineSweepAlgo
finding a closed path using GrahamScanAlgo to find a closed path with adjacent vertices
Cross Reference 3. with DinicAlgo to Dissolve them
note: my scenario was different given the polygons had a common vertice. But Hope this can help
If you do not care about predictable run time you could try by first splitting your polygons into unions of convex polygons and then pairwise computing the intersection between the sub-polygons.
This would give you a collection of convex polygons such that their union is exactly the intersection of your starting polygons.
If the polygons are not aligned then they have to be aligned. I would do this by finding the centre of the polygon (average in X, average in Y) then incrementally rotating the polygon by matrix transformation, project the points to one of the axes and use the angle of minimum stdev to align the shapes (you could also use principal components). For finding the intersection, a simple algorithm would be define a grid of points. For each point maintain a count of points inside one polygon, or the other polygon or both (union) (there are simple & fast algorithms for this eg. http://wiki.unity3d.com/index.php?title=PolyContainsPoint). Count the points polygon1 & polygon2, divide by the amount of points in polygon1 or Polygon2 and you have a rough (depending on the grid sampling) estimate of proportion of polygons overlap. The intersection area would be given by the points corresponding to an AND operation.
eg.
function get_polygon_intersection($arr, $user_array)
{
$maxx = -999; // choose sensible limits for your application
$maxy = -999;
$minx = 999;
$miny = 999;
$intersection_count = 0;
$not_intersected = 0;
$sampling = 20;
// find min, max values of polygon (min/max variables passed as reference)
get_array_extent($arr, $maxx, $maxy, $minx, $miny);
get_array_extent($user_array, $maxx, $maxy, $minx, $miny);
$inc_x = $maxx-$minx/$sampling;
$inc_y = $maxy-$miny/$sampling;
// see if x,y is within poly1 and poly2 and count
for($i=$minx; $i<=$maxx; $i+= $inc_x)
{
for($j=$miny; $j<=$maxy; $j+= $inc_y)
{
$in_arr = pt_in_poly_array($arr, $i, $j);
$in_user_arr = pt_in_poly_array($user_array, $i, $j);
if($in_arr && $in_user_arr)
{
$intersection_count++;
}
else
{
$not_intersected++;
}
}
}
// return score as percentage intersection
return 100.0 * $intersection_count/($not_intersected+$intersection_count);
}
This can be a huge approximation depending on your polygons, but here's one :
Compute the center of mass for each
polygon.
Compute the min or max or average
distance from each point of the
polygon to the center of mass.
If C1C2 (where C1/2 is the center of the first/second polygon) >= D1 + D2 (where D1/2 is the distance you computed for first/second polygon) then the two polygons "intersect".
Though, this should be very efficient as any transformation to the polygon applies in the very same way to the center of mass and the center-node distances can be computed only once.