AS3 - drawPath() & winding overlaps producing strange behavior - actionscript-3

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.

Related

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?

Detect coordinates within a shape

Theres 2 parts to my problem and they are related. I have a weird shape on my interface illustrated below, I am trying to randomly spawn MovieClips within its' boundaries but I am having some trouble finding a good way to do it.
Question 1: I can run an If condition to check with bitMapData.hitTest to see if the MovieClip has randomly spawn within this shape, if it doesn't simply retry with a new set of random coordinates. However, is there a better way? Like a way to only take into account coordinates within the shape? There will be plenty of MC spawned at one go so I am hoping to lessen the load, or at least find an efficient way to do this calculation.
Question 2: The MovieClips spawned within this shape will eventually have collision detection mechanics that will repel itself when interacted with. Is there a way to contain them within this shape via some kind of boundary detection?
If it was a square, we could easily have contained them with a quick check on all 4 edges, but not with this shape. Currently I am thinking of using bitMapData.hitTest again to detect for out-of-bounds after being repelled, but how do I know which Point() is the nearest 'edge' of this shape to return the MC to?
For question 1: I'm going to go on an assumption that you have some geometry data about the shape.
One method you can use to check if a point is within a shape is to take that point, then draw a line from that point to infinity (the edge of the screen) in one direction. Then count how many times that line intersects an edge of the shape. If it's odd, the point is within the shape (or on the edge) and if it's even, than that point is outside of the shape.
First link in google: https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/
Or can also try a more simple method (at the cost of doing more work): if the above shape is generated with all squares and rectangles and you know the point and size of all of those: can just do a check for the point vs all the squares and rectangles that make up the shape.
For question 2: As Organis mentioned, I'd go with a library like Box2D to do this. You'll most likely spend tons of time (that you may not want to) if you try to implement this alone.
The big issue is how much cpu or gpu the code uses. You're trying to avoid using any collision detection. Collision detection is having code do calculations to determine the edges of an object. It should be the last option.
Most of the time you know there's no need for collision detection. You know where everything is and how big it is. Everything has a centerpoint and comparing simple number coordinates is the lightweight way to check if there's a need to check further.
When things get near each other, you only need to do a collision detection on the immediate area around an object. See how your shape fits in a box that is easy to check for collisions? That box should get a collision check before the actual jagged shape inside it.
Yes that collision detection box has to be drawn or mapped but it's done when the object is defined, not when the game is playing. If you are using sprite sheets, keep an xml of the boxes or circles around the shapes.

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

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

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

How could I reduce the complexity of an image map?

I'm using KImageMapEditor on Linux (Ubuntu) to create an image map. The shapes in the image are a little complex so I'm using the freehand tool to draw them. However, this is really the same as the polygon tool so the shapes have ended up with a lot of points, which has made the HTML pretty huge.
Does anyone know of a way to reduce the complexity of the shapes, like "smoothing out" the lines?
I should also mention the reason I want the shapes to be fairly accurate is because I'm intending to do something like this, where each shape is highlighted on mouseover: http://davidlynch.org/js/maphilight/docs/demo_usa.html
Since users aren't going to click to the pixel, give them some leeway and create a "sloppy" map which roughly outlines each shape instead of clinging to the actual pixel outline.
This is in the same way as you don't expect a click on a link to fail just because you click on the background which shines through the text. You expect the bounding box of the text to act as the click-able area instead of the "black pixels".
Algorithm: Given three consecutive points, eliminate the middle point if the angle created is less than some tolerated error e.
Polygonal path simplification with angle constraint