How to calculate Polygon points from a simple line for a specific width? - language-agnostic

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).

Related

HTML5 Canvas: Quadratic Curve with lengthwise color split

Problem
I struggle to split a CanvasRenderingContext2D.quadraticCurveTo() path lengthwise into two colors.
Question (framings)
How can I split the color of a quadratic curve lengthwise?
How can a draw two parallel quadratic curves?
Background
The user must draw a line in an annotation tool and indicate polarity based on the line's color (this convention is predefined and can not be changed). Example:
Current best solution
The user specifies N points through which to draw a smooth line (based on this StackOverflow answer). To split the path, I calculate a perpendicular vector for each subpath, merge them to find the average perpendicular vector for the entire path, and redraw the line twice, once shifted up and once shifted down along the perpendicular.
This approach works fine for most curves:
However, it fails, e.g., for back curving curves:
Next, I would try using a perpendicular gradient as described in this blog. However, the computation seems to be highly inefficient and I would appreciate any hints on how else I could solve this problem.

DCEL data structure edge refinement algorithm (edge cases)

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?

How to create arcs on boundary points of voronoi?

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.

AS3 with Nape physics: How can I find a tangent from a point to a body?

The short question: Is there any simple way in Nape to calculate the points of tangency with a Nape body object or shape given a point outside that body?
What I'm trying to do is create Worms-style rope physics. It basically works as an extendable line/distance joint that automatically breaks into segments when it comes in contact with the level geometry. I do this by raycasting from the most recent pivot point; if there is a collision I offset from the collision point by a couple of pixels, create a new rope segment, and make that point the new pivot. In case my character is swinging around a sharp corner, I then recast from that point, looping as necessary, until I'm clear of the level geometry.
It works amazingly well given my lack of experience, but there's one little cosmetic glitch. The rope won't wrap "tightly" around a horn-shaped protrusion. It's pretty easy to see why this is happening. Refer to the figure below.
I cast a ray each time I step the Nape world at 60 frames/second. Figure 1 shows the difference between two example raycasts. The character (not pictured) is at the end of the line, and he's fallen past the cliff "edge" in relation to the pivot in one step, so the collision point falls short of the desired point of tangency.
Figure 2 is what I end up with. The wraparound logic still works, by offsetting from the surface and recasting, but it doesn't appear "taut."
What I want is something like Figure 3, which corrects the angle to find the actual point of tangency with the body and creates the new pivot from that.
My planned fallback is to offset the angle of the raycast by small increments and recast until I no longer strike the level geometry, then back up one and use that as the collision point. Even that will probably require fewer computations than "curving" around like in Figure 2, but I'm still wondering: is there an even simpler way?
Excuse me for not commenting, but I don't have needed points for that :)
I've used something similar before (not exactly the same) and I think the way to go is to save the points of each cast, get the one with highest difference from the starting point, based on the y axis (if the rope goes up, then you get the point with smallest y and vice versa (rope going down from starting point)).
Then you can fix the angle to point to this specific point, marked as an "edge". Later you can continue with the common pattern, as the rope will go in the other direction (exactly like the edge of a cliff).

AS3 - drawPath() & winding overlaps producing strange behavior

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.