I am working with C# OpenTK, but any code in C++ OpenGL is fine, i understand it.
I have a list of Markers. A Marker is defined as a 2 coordinate, and a pointer to the next marker in the loop. Essentially, if you were to follow the path of those pointers, you would eventually reach the Marker you started with. This is how shapes are initially defined.
One of those 'loops' may not be all the markers in the list. Multiple 'loops' may be contained. Take the letter 'A' for example:
This shape here would be defined by 2 'loops'. One is the outline (8 Markers), while the other loop would be the triangle within (3 Markers).
(Marker - Pointer)
1-2, 2-3, 3-4, 4-5, 5-6, 6-7, 7-8, 8-1
9-10, 10-11, 11-9
I need a method that will allow me to draw something like this to the screen. The solutions stated here would correctly solve the issue on a bitmap level (going through pixel after pixel to check if it within the polygon), however would be quite inefficient, especially given the fact that these markers shall be moved continuously at run time.
It is required that these shapes should be able to include things such as the triangle in an A (inverting), and preferably would allow for overlapping boundaries of the 'loops', but this second thing is not a necessity.
I'm guessing the direction taken will either be some sort of conversion to triangles, or some fancy trick with built in OpenGL features.
You're looking for triangulation with holes.
Check out the General Polygon Clipper (GPC).
Related
This question already has answers here:
Non-Affine image transformations in .NET
(3 answers)
Closed 1 year ago.
I need to combine two images in C# ( 4.7.2 ), and have the top image transformed putting each of the four corners at specific coordinates in the image.
Is that possible? Preferably with a solution that doesn't require spending a ton of money. As far as I can tell i can't do it with the Bitmap/Graphics classes.
Image of what I'm trying to do
Shear (or skew), which is what an affine transform such as used in GDI+ or WPF, is unlikely to do what you want, if I understand the question correctly. With shear/skew the transformed coordinate space is still a parallelogram, whereas in your image, the original rectangle is squeezed or stretched arbitrarily.
Assuming that's correct, I would recommend using the features in the WPF Media3D namespace (WPF, simply because it's the most accessible 3D API in the .NET context). In particular, you will want to define a texture that is your original bitmap. Then you will want to define a quadrilateral 2D surface in 3D coordinate space with sufficient resolution (i.e. triangles) for your purposes (see below), and where the triangles in that surface are constructed by tessellating the shape that you want as your final image, and where you've interpolated the texture (UV) coordinates for that shape across the vertexes that result from the tessllation.
How many triangles you actually want depends on the desired quality. In theory, you could use just two. This is the simplest approach, and determining the UV coordinates is trivial, because you only have your original four corners. But there will be a visual discontinuity along the diagonal where the two triangles meet, where the interpolation of the texture pixels changes direction due to the triangles not being square to each other.
For better results, you'll need to use more triangles. But then this complicates the assignment of the UV coordinates. For each inner vertex of this surface, you'll need to interpolate across the surface. This is probably easier to do if you generate the tessellation in the first place by subdividing the quadrilateral with lines connecting opposite sides (which will form smaller interior quadrilaterals bounded by intersecting lines) and then just divide each of those quadrilaterals into pairs of triangles. If you do it this way, then you can use the distance along each line to determine the appropriate U or V coordinate at each vertex that line goes through.
Having created the appropriate texture and geometry, it's a simple matter to render the result into a RenderTargetBitmap via the Viewport3DVisual class, and then do whatever you want with that bitmap.
Now, all that said…
If it turns out that your problem can be simplified such that shear/skew is sufficient for your needs, you can look at De-skew characters in binary image for help with that. In that particular example, they are trying to undo skew caused by optical effects, but skewing is skewing; the same exact principle works in either direction.
Even if your problem is not amenable to shear/skew approaches, before you implement your own solution (e.g. based on my outline above), you may want to look at other available tools. Information about some options can be found in, for example, Image Modification (cropping and de-skewing) in C# and Image comparison - rotation, alignment and scaling.
I've searched the Internet and maybe I'm missing some correct keywords but I managed to find nothing like this. I only found the poly-lines (or just the lines) which are not exactly the graphs. I would like to generate a graph outline (of radius r) as seen in the picture. Is there something already available? I would like to avoid reinventing the wheel so to speak.
If anyone can at hint me at something or at least at some basic principle how to do it it would be great. Otherwise I'll "invent" one on my own of course.
Optimally in C#.
Update: I need to calculate outline polygon, not just visually draw it. The green points represents the resulting polygon. Also the "inner" holes are ignored completely. Only one outline polygon should be enough.
Update 2: Better picture to show some more extreme cases. Also the edges of graph never overlap so no need to accommodate for that.
Update 3: Picture updated yet again to reflect the bevel joins.
First, for every "line piece" from point A to B, generate the rectangle to it (all 4 points as "path", so to say). Then search two overlapping rectangles and merge them:
Merging is a bit complicated, the idea: Start with calculating the angle of all 8 lines (eg. if the rectangles are traversed clockwise). Then traverse one rectangle until the first line-line-intersection, check with the angles which direction is "outside", and move along the crossing line of the second rectangle ... until you arrive at the start point again => Now you traversed the shape of both together (and hopefully saved it somewhere).
Merge until only one large piece is left (or multiple non-overlapping pieces). In theory, starting from any point, you can traverse the whole shape, but there´s another problem: Holes are possible.
If one shape has two or more disjuct sets of points (where no point from set 2 is reachable from set 1 and vice-versa), all but one disjunct path is of a hole. An easy possibility to get the real outer border is to search for an extremum, ie. the point with the largest or smallest X or Y coordinate (only one of the 4 combinations in enough). This point surely is a part of the outer border.
I have some images that I'd like to draw a polyon around the outer edges. The images themselves are on transparent backgrounds and I've created an array of the pixels in the images which contain a point and are not transparent (or white).
Now, my question is: how do I draw an accurate polygon around the outer edge points? I've used a Graham Scan algorithm that I read about to create a convex hull around the edges but this doesn't seem to work for objects with concavities. For example:
http://i48.tinypic.com/4s0lna.png
The image on the left gets filled in using this method with the one on the right. As you can see, it's 'filling in' a little too much.
I assume there must be some other algorithm or approach that can be used to solve this, but I'm not sure of where to look or what it might be called. Could anyone point me in the right direction? I'm using C#/.net and hopefully there might be something that already exists which could work along these lines.
I think the 2D "Alpha shapes" algorithm would the right choice for you.
http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Alpha_shapes_2/Chapter_main.html
Alpha shapes can be considered as a generalization for the "convex Hull" algorithm that allows for generation of more general shapes.
By using alpha shapes you will be having control over the level of details to be captured by the resultant shape by changing the alpha parameter value.
You can try the java applet here : http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/alpha.html
to have better understanding about does this algorithm do.
You can start on a pixel by pixel level, using a flood-fill approach.
Start in the corner, checking that it does have zero alpha.
Check the neighbours for zero alpha and iterate until we have no unchecked neighhours.
This gives you a mask for the image which will consist of two simply connected regions, the interior and exterior.
The set you seek then consists of:
all the points in the exterior which are on the boundary of the interior.
You can then turn that into a polygon by:
Take an initial polygon that consists of all the points in the edge set
Remove redundant vertices that lie along straight edges.
I'm making a game in C# and XNA, and I was trying to come up with a method to render massive terrains without using a tremendous amount of memory or passing the poly limit hard-coded into XNA.
My solution so far is to create a massive heightmap, and that heightmap is loaded into memory at the beginning of the game in the initialization phase. Then, terrain is only generated nearest to the camera. This is accomplished by projecting a triangle whose vertex is the character and the other two endpoints extend to the sides of the character's viewing area. Then, all the pixels inside that triangle on the heightmap are rendered and drawn into the game, thus only rendering what is seen.
The problem is, I've successfully found (I think, can't test until I get terrain rendering) the three vertices of the triangle. Now I need to find a list of the coordinates for every single pixel inside that triangle - whole numbers only, because I just need a list of pixels to render.
I know it sounds a little confusing, so here's the gist of it:
I have an image, and I project a triangle onto that image. The only thing I know about that triangle are the three vertices. I need a list of the pixels inside that triangle.
I've been Googling around for maybe 20 minutes now, and I figured I midas well go ahead and post something here due to the fact that what I'm trying to do isn't all that common. If I find an answer, I'll be sure to post it here.
But until then, can anyone tell me how to accomplish this?
Edit: A formula, please. If you can provide a formula or algorithm, and an explanation, that would be just perfect.
Edit: I've posted a new question, as I've ditched this method of rendering large terrains. The question is here.
Start here:
http://mathworld.wolfram.com/TriangleInterior.html
One of the non-trivial problems, not mentioned there, that you have to deal with is the pixelization along the boundary.
I'm trying to draw a polygon using c# and directx
All I get is an ordered list of points from a file and I need to draw the flat polygon in a 3d world.
I can load the points and draw a convex shape using a trianglefan and drawuserprimitives.
This obviously leads to incorrect results when the polygon is very concave (which it may be).
I can't imagine I'm the only person to grapple with this problem (tho I'm a gfx/directx neophyte - my background is in gui\windows application development).
Can anyone point me towards a simple to follow resource\tutorial\algorithm which may assist me?
Direct3D can only draw triangles (well, it can draw lines and points as well, but that's besides the point). So if you want to draw any shape that is more complex than a triangle, you have to draw a bunch of touching triangles that equal to that shape.
In your case, it's a concave polygon triangulation problem. Given a bunch of vertices, you can keep them as is, you just need to compute the "index buffer" (in simplest case, three indices per triangle that say which vertices the triangle uses). Then draw that by putting into vertex/index buffers or using DrawUserPrimitives.
Some algorithms for triangulating simple (convex or concave, but without self-intersections or holes) polygons are at VTerrain site.
I have used Ratcliff's code in the past; very simple and works well. VTerrain has a dead link to it; the code can be found here. It's C++, but porting that over to C# should be straightforward.
Oh, and don't use triangle fans. They are of very limited use, inefficient and are going away soon (e.g. Direct3D 10 does not support them anymore). Just use triangle lists.
If you are able to use the stencil buffer, it should not be hard to do. Here's a general algorithm:
Clear the stencil buffer to 1.
Pick an arbitrary vertex v0, probably somewhere near the polygon to reduce floating-point errors.
For each vertex v[i] of the polygon in clockwise order:
let s be the segment v[i]->v[i+1] (where i+1 will wrap to 0 when the last vertex is reached)
if v0 is to the "right" of s:
draw a triangle defined by v0, v[i], v[i+1] that adds 1 to the stencil buffer
else
draw a triangle defined by v0, v[i], v[i+1] that subtracts 1 from the stencil buffer
end for
fill the screen with the desired color/texture, testing for stencil buffer values >= 2.
By "right of s" I mean from the perspective of someone standing on v[i] and facing v[i+1]. This can be tested by using a cross product:
cross(v0 - v[i], v[i+1] - v[i]) > 0
Triangulation is he obvious answer, but it's hard to write a solid triangulator. Unless you have two month time to waste don't even try it.
There are a couple of codes that may help you:
The GPC Library. Very easy to use, but you may not like it's license:
http://www.cs.man.ac.uk/~toby/alan/software/gpc.html
There is also triangle:
http://www.cs.cmu.edu/~quake/triangle.html
And FIST:
http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html
Another (and my prefered) option would be to use the GLU tesselator. You can load and use the GLU library from DirectX programs just fine. It does not need an OpenGL context to use it and it's pre-installed on all windows machines. If you want source you can lift off the triangulation code from the SGI reference implementation. I did that once and it took me just a couple of hours.
So far for triangulation. There is a different way as well: You can use stencil tricks.
The general algorithm goes like this:
Disable color- and depth writes. Enable stencil writes and setup your stencil buffer that it will invert the current stencil value. One bit of stencil is sufficient. Oh - your stencil buffer should be cleared as well.
Pick a random point on the screen. Any will do. Call this point your Anchor.
For each edge of your polygon build a triangle from the two vertices that build the edge and your anchor. Draw that triangle.
Once you've drawn all these triangles, turn off stencil write, turn on stencil test and color-write and draw a fullscreen quad in your color of choice. This will fill just the pixels inside your convex polygon.
It's a good idea to place the anchor into the middle of the polygon and just draw a rectangle as large as the boundary box of your polygon. That saves a bit of fillrate.
Btw - the stencil technique works for self-intersecting polygons as well.
Hope it helps,
Nils
I just had to do this for a project. The simplest algorithm I found is called "Ear Clipping". A great paper on it is here: TriangulationByEarClipping.pdf
I took me about 250 lines of c++ code and 4 hours to implement the brute force version of it. Other algorithms have better performance, but this was simple to implement and understand.