I'm trying to connect two polygons that are described as DCEL data structure and find it hard to do so at some edge cases where, for example, edges intersect with each other at their interior or overlap each other.
Here's the definition of the problem:
The polygons are of rectangular shape with straight edges (edges at vertices make straight angles)
There are no more than 8 edges that meet at the vertex. The only case where it's possible is that all 4 polygons meet at single vertex (aka 4 rectangles)
It's impossible to have more than 2 edges intersecting in their interior
It's impossible that polygons intersect not on segments. All intersections are done on edges and all of them are mix of overlapping cases or interior intersections
There are no holes in polygons
Dissolving internal faces is not allowed here. Edge in between still must be present
If this helps the polygons are representing imaginary regions enclosed under the imaginary country that's why they meet at edges only.
Here are some examples of polygons:
Case 1:
Overlapping edges
Case 2:
One edge contains another
PS: Right now I'm reading Bergs 'Computational Geometry' and trying to practice in DCEL implementation
PSS: In addition I've read a lot of info across the Internet regarding handling subdivision overlapping, but haven't seen the explanation about how to handle such cases. What I think here is that I need to handle edge removal while Berg does not tell this in his book.
Also extra source: same Berg, but with more fancy images
https://cw.fel.cvut.cz/b201/_media/courses/cg/lectures/09-intersect-split.pdf (p. 26/96)
So after tons of trials and errors I found the solution to my problem. It's not ideal because I still don't know the 'correct' answer on how to split edges when they are neighboring to each other for arbitrary polygon, but have a solution to my problem that I was trying to solve.
According to the algorithm that Berg described in his book edges must be refined using sweep line algorithm. Previous and next edge must be selected in the CCW or CW order (CCW = counter clockwise, CW = clockwise) depending in what direction edge is pointing, but it's hard to do so when you have overlapping edges. Additional complexity here will be that the edge consists of two half edges and it's a nightmare to refine both of them according to simplified algorithm described above. Instead, what we can do here is to forget about two half edges and use only one. It will always have incident face but no twin. In this case overlapping is detected perfectly using sweep line algorithm and polygon stitching becomes straightforward: the overlapping edges become twins to each other when edge refinement is done (splitting edge at the event point in case if edge contains it in the interior). When edge is split the other edge that belongs to another polygon becomes its twin
It looks a bit messy without thorough explanation, but I'll attach image that will show what I mean by that
On the image you can see edges like a2 that gets split into two new edges - a2' and a2'' plus old shrunk a2. Refinement of a2 was done at two points - v5 and v8. Each point is a beginning of the new half edge and the end of previous one. When we have two edges that are ending at a point (it's impossible to have more than 2 edges in my problem) we mark them as twins (b4 and a2'). Resolving next and previous here is really easy.
To bypass the contour of stitched polygon (black lines) you can use info about the twin of next edge. If it has a twin then switch to the twins next edge at next step (next_edge = a2'.twin.next is the same as next_edge = b4.next)
PS: it will not work for case when you have multiple polygons overlapping at the same edge. It's hard to make twins in such case, but it's a question whether the correct solution exists or not?
Related
I am writing some 2D graphic software. And in my project i used Voronoi algorithm. And result is correct as I expected (Pic 1). Then i want to add some feature on boundary points just like (Pic 2). So i think i need to implement Concave hull on boundary points and then create arcs on it.
Pic 1.
But my concave hull is not working correct because of concavity parameter. What is the best way and best algorithm to transform my software result into Pic 2.
Pic 2.
You can create a b/w bitmap with the concave hull and compare it with every point of the voronoi diagram. I used a php function imagefilledpolygon in my php implementation contour plot:https://cntm.codeplex.com/.
You can also try this answer and reconstruct voronoi edges at the border, usually infinity edges:Colorize Voronoi Diagram.
You should be able to do a walk around the voronoi looking for vertices with only a single adjacent edge (not a bad idea to start with a vertex that has just one adjacent edge). Find the first one, walk to the next one, then connect the edges with an arc, repeat until your back at the first edge. The algorithm should be rather efficient O(N) if the voronoi is structured as a graph.
The walk:
The walk is done by angle-sorting the edges and taking the next clockwise edge to the one you started on.
For example:
If the angles (in degrees) are 40, 50, 60, 70, and the previus edge was in the direction of the 50, then you would follow the 60 or 40 edge (depending on if you've decided to go clockwise or counterclockwise) but you wouldn't follow the 70 regardless as that leads inside rather than sticking to the outside.
I'm trying to draw multiple shapes in the same Sprite.graphics scope, and can't seem to find any reasonable solution to my problem.
Please keep in minde that I've been using the drawPath() method for a performance problem : I could use multiple shapes with blendmodes, but I'd like to avoid that and keep performances cost to the minimum.
I've been experimenting with the winding parameter of the drawPath() method, but one thing that I cannot understand, is how the winding direction is defined by Flash, so here is a first question before actually coming to the real problem :
Are points coordinates taken in account ? Or is it the angle between the produces lines that define the direction ?
That being said, here is my actual problem :
I want to draw a shape that is a projection from a rectangle on a line - think of a window and the light that passes through it that goes hit the floor.
To achieve that, I must take into account that the lightsource position can vary and have that kind of results :
Here on that second picture you can already see the problem I'm facing.
To draw my shape, I've been separately "drawing" (understand : placing the numbers in my coordinates vector) the different parts of my figure : the actual rectangle I want to project, the light projected from its left side, the light projected from its bottom side, and the light projected from its right side.
I've been trying to carefully keep the winding direction the same in every section, beginning from the top-left corner, but it seems something is wrong in my reasoning, since every time the center part overlaps with any side part, the shape is emptied there, and every time the two sides parts overlaps, the same happens.
As I'm writing that here, some revelation suddenly strike me, and now I guess that maybe ALL my points in my coordinates vector must be sorted in the same winding direction for my shape to work ?... (and not only the small parts I'm separately drawing in my mind ^^)
If I'm right (please correct me if I'm not, or if I've understood anything wrong ?...), that means I must either :
sort my points to be placed in the correct winding direction (thing that might be complicated and could result in some strange drawed shape once provided to the drawing API ?...)
only draw the shape from the most external points, depending on the shape's actual shape (thing that might be more complicated that I currently expect).
Could anyone here confirm or infirm my last suppositions, and give me a clue on what could be going on here and how to solve it ?...
Thanks a lot :-)
You want to have one shape composed out of three projector lines? Okay, you have determined the positions of two lower points, and you have 4 points of your window. You then construct a list like so:
Two topmost points are always in the list, as you write that your light will always fall down out of the window. So, put 0 in command, window's upper left point coordinates into path, 1 into command (lineTo), window's upper right point into path.
Now, if both of your floor points have X less than lower right angle of the window, you add the window's point into the path!
Then you add rightmost floor point, then leftmost.
Then, if both of your floor points have X greater than lower LEFT corner of the window, you add it to the list.
You're done. And you will no longer need 3 projections, you calculate only the bottommost one (it'll give you both points on the floor), and make your list. Should do. Please comment.
I'm currently building an as3 isometric game, but I'm having a lot of problem with depth sorting. I've searched for a solution, but didn't found anything that match my problem (rectangle objects).
Here is a screenshot of my game:
As you can see, depth sorting works well when it's between 1x1 tiles objects. I simply use their x and y coordinates (relative to the isometric map) to sort them.
The problem comes when I have bigger objects, like 2x2 or 1x4 or 4x1.
Any idea how should I handle depth sorting then?
I don't think it is possible to sort a scene based on a single x,y value for each object if some of them can be long enough that one end should be at a different depth than the other. For instance, consider how you'd handle the rendering if the brown chair in your picture was moved one square down-left (to the square between the blue chair and the long couch). It would be deeper in the scene than the red table behind the couch, but would need to be rendered on top of the couch, which would need to be on top of the table.
I think there are two simple solutions:
Design your
levels using only one sort of overlap for large objects. For
instance, you could specify that an object's depth is based on its
nearest corner, which would require you to avoid putting things in
front of its most distant bits (since it will render on top of them).
Or you could stick with your current code (which seems to use the
most distant corner for depth) and avoid putting anything behind the
nearer parts. You may still have trouble with characters and other
objects that move around though. You might be able to make the
troublesome tiles inaccessible if you're careful with your design,
but in some cases this may be too restrictive.
Break up your large objects into smaller ones
which would have their own depths. You will probably want to go right
down to 1x1 pieces, each of which will have an unambiguous depth. You
might choose keep the larger objects in the code as invisible
containers for the smaller pieces, or they could be eliminated
entirely, whichever makes it easier for you to load up and enable
interaction with the various bits.
Splitting larger objects in to 1x1 sized pieces can also be nice since you can make them modular. That is, you can build differently sized objects by putting together 1x1 pieces in different combinations. If you cut your 2x1 tables in your image in half vertically, for instance, and created a 1x1 middle tile that fit in between them, you could stretch the design out to 3x1 or 10x1, depending on how many times you repeat the middle tile. There's a lot of other ways to make tiled graphics look good with only a modest amount of art required.
Ultima Online emulators (specifically, POL, though there may be others) achieve this through the implementation and usage of the concept of a 'multi' -- a single object comprised of sections of cut-up larger graphics. These cut-up graphics are such that their sprites are vertically-split at the left- and right-corner points of iso grid boundaries.
Other considerations:
- render 'multi' pieces sorted screen-Y axis from top-to-bottom.
- the southern (i.e. screen bottom-left) component of a 'multi' becomes the anchoring tile position (in the case of your couch, its left-most piece).
- consider that each map location can also hold its own vertical stack of objects; offsetting each object's render by screen-Y simulates height/altitude, and these must be sorted bottom-to-top (e.g. lowest-altitude to highest altitude).
Good luck!
I currently develop an application that creates polygons from lines and I experience a small problem:
I have a set of points, representing a line. I would like to create a polygon that displays the line with a specific width (e.g. for a street). I have several ideas how to calculate the outer polygon points, but I think they are too complicated...
My best idea was the one pictured below: Every point of the line must be projected to at least two points: Both points must be 90° to the following line segment and have a distance half of the preferred polygon width.
This works good, as you can see at the end and start points of the pictured polygon. Now the complicated part: With this method, at a corner, each point gets four points. But these points are not correct for the outer polygon, because they are in the shape. The lines intersected and created an ugly polygon.
How can I find the correct points for such a polygon? I think my method is far too complicated for solving this problem.
Can anybody help me with this (propably very common) problem?
Info: I tagged this with openstreetmap because renderer like Mapnik have this problem, too.
What you are looking for is a polygon (or line) offsetting algorithm. This is not necessarily an easy problem to solve, by the way: An algorithm for inflating/deflating (offsetting, buffering) polygons.
For the last couple of weeks I've been working on a line offsetting algorithm for Maperitive. In my case I only needed to offset the line so I wasn't looking for a solution to create a buffered polygon around it, but I guess the algorithm could be extended further in the future:
Basic flow (roughly, but the devil is in the details):
For each polyline point find a point that has an L distance from the original point and lies on a line that's orthogonal to the original line and goes through the original point.
Now draw an offset line through that new point. The line must be parallel to the original line.
For corner angles you must extend the two neighbouring offset lines and find the intersection point, which will be the next point of the offset line.
Some things to observe:
Notice the miter limit applied on concave angles to the right of the picture.
Before calculating the offset line you need to simplify the original polyline to exclude segments that are too small to hold the offset (the results can be seen at the center left of the picture).
I only implemented support for miter joins, but a good algorithm should be able to render round joins, too (using arcs).
I have an array of thousands of quads; 4-sided 3D polygons. All I know are the coordinates of the quad corners.
A subset of these quads define the closed outer shell of a 3D shape. The remaining quads are on the inside of this closed solid.
How do I figure out which quads are part of the shell and which quads are part of the interior? This is not performance critical code.
Edit: Further constraints on the shape of the shell
There are no holes inside the shape, it is a single surface.
It contains both convex and concave portions.
I have a few points which are known to be on the inside of the shell.
This might be hard to implement if your shape self intersects, but if you can find one quad that you know is on the surface (possibly one furthest away from the centroid) then map out concentric circles of quads around it. Then find a continuous ring of quads outside that and so on, until you end up at the "opposite" side. If your quads intersect, or are internally connected, then that's more difficult. I'd try breaking apart those which intersect, then find all the possible smooth surfaces, and pick the one with the greatest internal volume.
How about this?
Calculate the normal vector of a quad (call this the 'current' quad).
Do an intersection test with that vector and all the remaining quads.
If it intersects another quad in the positive portion of the vector you know the current quad is an internal quad. Repeat for all the remaining quads.
This assumes the quads 'face' outward.
Consider that all of the quads live inside a large sealed box. Pick one quad. Do raytracing; treat that quad as a light source, and treat all other quads as reflective and fuzzy, where a hit to a quad will send light in all directions from that surface, but not around corners.
If no light rays hit the external box after all nodes have had a chance to be hit, treat that quad as internal.
If it's convex, or internal quads didn't share edges with external quads, there are easier ways.
It can be done quite easily if the shape is convex. When the shape is concave it is much harder.
In the convex case find the centroid by computing the average of all of the points. This gives a point that is in the interior for which the following property holds:
If you project four rays from the
centroid to each corner of a quad you
define a pyramid cut into two parts,
one part contains space interior to
the shape and the other part defines
space that might be exterior to the
shape.
These two volumes give you a decision process to check if a quad is on the boundary or not. If any point from another quad occurs in the outside volume then the quad is not on the boundary and can be discarded as an interior quad.
Edit: Just seen your clarification above. In the harder case that the shape is concave then you need one of two things;
A description (parameterisation) of the shape that you can use to choose quads with, or
Some other property such as all of the boundary quads being contiguous
Further edit: Just realised that what you are describing would be a concave hull for the points. Try looking at some of the results in this search page.
You may be able to make your problem easier by reducing the number of quads that you have to deal with.
You know that some of the quads form a closed shell. Therefore, those quads are connected at their edges. If three mutually adjacent edges of a quad (that is, the edges form a closed loop) overlap the edge of another quad, then these quads might be part of the shell (these mutually adjacent edges serve as the boundary of a 2D region; let's call that region the "connected face" of the quad). Make a list of these "shell candidates". Now, look through this list and throw out any candidate who has an edge that does not overlap with another candidate (that is, the edge overlaps an edge of a quad that is not in the list). Repeat this culling process until you are no longer able to remove any quads. What you have left should be your shell. Create a "non-shell quads" list containing all of the quads not in the "shell" list.
Draw a bounding box (or sphere, ellipse, etc) around this shell. Now, look through your list of non-shell quads, and throw out any quads that lie outside of the bounding region. These are definitely not in the interior.
Take the remaining non-shell quads. These may or may not be in the interior of the shape. For each of these quads, draw lines perpendicular to the quad from the center of each face that end on the surface of the bounding shape. Trace each line and count how many times the line crosses through the "connected face" of a quad in your shell list. If this number is odd, then that vertex lies in the interior of the shape. If it is even, the vertex is on the exterior. You can determine whether a quad is inside or outside based on whether its vertices are inside or outside.