Introduction
As part of a larger program (related to rendering of volumetric graphics), I have a small but tricky subproblem where an arbitrary (but finite) triangular 2D mesh needs to be labeled in a specific way. Already a while ago I wrote a solution (see below) which was good enough for the test meshes I had at the time, even though I realized that the approach will probably not work very well for every possible mesh that one could think of. Now I have finally encountered a mesh for which the present solution does not perform that well at all -- and it looks like I should come up with a totally different kind of an approach. Unfortunately, it seems that I am not really able to reset my lines of thinking, which is why I thought I'd ask here.
The problem
Consider the picture below. (The colors are not part of the problem; I just added them to improve (?) the visualization. Also the varying edge width is a totally irrelevant artifact.)
For every triangle (e.g., the orange ABC and the green ABD), each of the three edges needs to be given one of two labels, say "0" or "1". There are just two requirements:
Not all the edges of a triangle can have the same label. In other words, for every triangle there must be two "0"s and one "1", or two "1"s and one "0".
If an edge is shared by two triangles, it must have the same label for both. In other words, if the edge AB in the picture is labeled "0" for the triangle ABC, it must be labeled "0" for ABD, too.
The mesh is a genuine 2D one, and it is finite: i.e., it does not wrap, and it has a well-defined outer border. Obviously, on the border it is quite easy to satisfy the requirements -- but it gets more difficult inside.
Intuitively, it looks like at least one solution should always exist, even though I cannot prove it. (Usually there are several -- any one of them is enough.)
Current solution
My current solution is a really brute-force one (provided here just for completeness -- feel free to skip this section):
Maintain four sets of triangles -- one for each possible count (0..3) of edges remaining to be labeled. In the beginning, every triangle is in the set where three edges remain to be labeled.
For as long as there are triangles with non-labeled edges:Find the smallest non-zero number of unallocated edges for which there are still triangles left. In other words: at any given time, we try to minimize the number of triangles for which the labeling has been partially completed. The number of edges remaining will be anything between 1 and 3. Then, just pick one such triangle with this specific number of edges remaining to be allocated. For this triangle, do the following:
See if the labeling of any remaining edge is already imposed by the labeling of some other triangle. If so, assign the labels as implied by requirement #2 above.
If this results in a dead end (i.e., requirement #1 can no more be satisfied for the present triangle), then start over the whole process from the very beginning.
Allocate any remaining edges as follows:
If no edges have been labeled so far, assign the first one randomly.
When one edge already allocated, assign the second one so that it will have the opposite label.
When two edges allocated: if they have the same label, assign the third one to have the opposite label (obviously); if the two have different labels, assign the third one randomly.
Update the sets of triangles for the different counts of unallocated edges.
If we ever get here, then we have a solution -- hooray!
Usually this approach finds a solution within just a couple of iterations, but recently I encountered a mesh for which the algorithm tends to terminate only after one or two thousands of retries... Which obviously suggests that there may be meshes for which it never terminates.
Now, I would love to have a deterministic algorithm that is guaranteed to always find a solution. Computational complexity is not that big an issue, because the meshes are not very large and the labeling basically only has to be done when a new mesh is loaded, which does not happen all the time -- so an algorithm with (for example) exponential complexity ought to be fine, as long as it works. (But of course: the more efficient, the better.)
Thank you for reading this far. Now, any help would be greatly appreciated!
Edit: Results based on suggested solutions
Unfortunately, I cannot get the approach suggested by Dialecticus to work. Maybe I did not get it right... Anyway, consider the following mesh, with the start point indicated by a green dot:
Let's zoom in a little bit...
Now, let's start the algorithm. After the first step, the labeling looks like this (red = "starred paths", blue = "ringed paths"):
So far so good. After the second step:
And the third:
... fourth:
But now we have a problem! Let's do one more round - but please pay attention on the triangle plotted in magenta:
According to my current implementation, all the edges of the magenta triangle are on a ring path, so they should be blue -- which effectively makes this a counterexample. Now maybe I got it wrong somehow... But in any case the two edges that are nearest to the start node obviously cannot be red; and if the third one is labeled red, then it seems that the solution does not really fit the idea anymore.
Btw, here is the data used. Each row represents one edge, and the columns are to be interpreted as follows:
Index of first node
Index of second node
x coordinate of first node
y coordinate of first node
x coordinate of second node
y coordinate of second node
The start node is the one having index 1.
I guess that next I should try the method suggested by Rafał Dowgird... But perhaps I ought to do something completely different for a while :)
If you order the triangles so that for every triangle at most 2 of its neighbors precede it in the order, then you are set: just color them in this order. The condition guarantees that for each triangle being colored you will always have at least one uncolored edge whose color you can choose so that the condition is satisfied.
Such an order exists and can be constructed the following way:
Sort all of the vertices left-to-right, breaking ties by top-to-bottom order.
Sort the triangles by their last vertex in this order.
When several triangles share the same last vertex, break ties by sorting them clockwise.
Given any node in the mesh the mesh can be viewed as set of concentric rings around this node (like spider's web). Give all edges that are not in the ring (starred paths) a value of 0, and give all edges that are in the ring (ringed paths) a value of 1. I can't prove it, but I'm certain you will get the correct labeling. Every triangle will have exactly one edge that is part of some ring.
Related
I'm interested in writing a my own function that subtracts one 2D triangle from another, returning the remainder as a n array of triangles. (not using an existing geometry library)
Two examples of input & output, triangles are numbered, order isn't important.
While I'm familier with these kinds of algorithms, this seems like a general enough problem that there may be a known robust solution already written (if not I may look into writing one as an answer to this question)
I recently work on this problem and resolved it.
I tried to describe all the possibilities of layering and I got there.
There are 16 cases classified by number of points of the dimunuende triangle in the diminishing triangle and of the dimunutor in the diminuende.
For information in the subtraction a - b = c, a is the dimunende and b is the diminutive, c is the difference.
In the subtraction table, the diminishing triangle is represented in blue and the diminutive in red, at the bottom right of each box are indicated the points of each triangle included in the other. The number of triangles in the difference is at the top left of each box and finally the number of intersections in red at the bottom left.
My method consist to count intersections and points insides triangles. In some cases we must also determine the validity of the triangles either by intersection detection or by checking that it does not contain points. Finally i think, I believe, I managed to solve this problem.
Take a look on this forum for code source and more informations :
https://gb32.proboards.com/post/2112/thread
I'm developing a game similar to Pacman: consider this maze:
Each white square is a node from the maze where an object located at P, say X, is moving towards node A in the right-to-left direction. X cannot switch to its opposite direction unless it encounters a dead-end such as A. Thus the shortest path joining P and B goes through A because X cannot reverse its direction towards the rightmost-bottom node (call it C). A common A* algorithm would output:
to get to B from P first go rightward, then go upward;
which is wrong. So I thought: well, I can set the C's visited attribute to true before running A* and let the algorithm find the path. Obviously this method doesn't work for the linked maze, unless I allow it to rediscover some nodes (the question is: which nodes? How to discriminate from useless nodes?). The first thinking that crossed my mind was: use the previous method always keeping track of the last-visited cell; if the resulting path isn't empty, you are done. Otherwise, when you get to the last-visited dead-end, say Y, (this step is followed by the failing of A*) go to Y, then use standard A* to get to the goal (I'm assuming the maze is connected). My questions are: is this guaranteed to work always? Is there a more efficient algorithm, such as an A*-derived algorithm modified to this purpose? How would you tackle this problem? I would greatly appreciate an answer explaining both optimal and non-optimal search techniques (actually I don't need the shortest path, a slightly long path is good, but I'm curious if such an optimal algorithm running as efficiently as Dijkstra's algorithm exists; if it does, what is its running time compared to a non-optimal algorithm?)
EDIT For Valdo: I added 3 cells in order to generalize a bit: please tell me if I got the idea:
Good question. I can suggest the following approach.
Use Dijkstra (or A*) algorithm on a directed graph. Each cell in your maze should be represented by multiple (up to 4) graph nodes, each node denoting the visited cell in a specific state.
That is, in your example you may be in the cell denoted by P in one of 2 states: while going left, and while going right. Each of them is represented by a separate graph node (though spatially it's the same cell). There's also no direct link between those 2 nodes, since you can't switch your direction in this specific cell.
According to your rules you may only switch direction when you encounter an obstacle, this is where you put links between the nodes denoting the same cell in different states.
You may also think of your graph as your maze copied into 4 layers, each layer representing the state of your pacman. In the layer that represents movement to the right you put only links to the right, also w.r.t. to the geometry of your maze. In the cells with obstacles where moving right is not possible you put links to the same cells at different layers.
Update:
Regarding the scenario that you described in your sketch. It's actually correct, you've got the idea right, but it looks complicated because you decided to put links between different cells AND states.
I suggest the following diagram:
The idea is to split your inter-cell AND inter-state links. There are now 2 kinds of edges: inter-cell, marked by blue, and inter-state, marked by red.
Blue edges always connect nodes of the same state (arrow direction) between adjacent cells, whereas red edges connect different states within the same cell.
According to your rules the state change is possible where the obstacle is encountered, hence every state node is the source of either blue edges if no obstacle, or red if it encounters an obstacle (i.e. can't emit a blue edge). Hence I also painted the state nodes in blue and red.
If according to your rules state transition happens instantly, without delay/penalty, then red edges have weight 0. Otherwise you may assign a non-zero weight for them, the weight ratio between red/blue edges should correspond to the time period ratio of turn/travel.
I'm working with a really slow renderer, and I need to approximate polygons so that they look almost the same when confined to a screen area containing very few pixels. That is, I'd need an algorithm to go through a polygon and subtract/move a bunch of vertices until the end polygon has a good combination of shape preservation and economy of vertice usage.
I don't know if there's a formal name for these kind of problems, but if anyone knows what it is it would help me get started with my research.
My untested plan is to remove the vertices that change the polygon area the least, and protect the vertices that touch the bounding box from removal, until the difference in area from the original polygon to the proposed approximate one exceeds a tolerance I specify.
This would all be done only once, not in real time.
Any other ideas?
Thanks!
You're thinking about the problem in a slightly off way. If your goal is to reduce the number of vertices with a minimum of distortion, you should be defining your distortion in terms of those same vertices, which define the shape. There's a very simple solution here, which I believe would solve your problem:
Calculate distance between adjacent vertices
Choose a tolerance between vertices, below which the vertices are resolved into a single vertex
Replace all pairs of vertices with distances lower than your cutoff with a single vertex halfway between the two.
Repeat until no vertices are removed.
Since your area is ultimately decided by the vertex placement, this method preserves shape and minimizes shape distortion. The one drawback is that distance between vertices might be slightly less intuitive than polygon area, but the two are proportional. If you really wish, you could run through the change in area that would result from vertex removal, but that's a lot more work for questionable benefit imo.
As mentioned by Angus, if you want a direct solution for the change in area, it's not actually super difficult. Was originally going to leave this as an exercise to the reader, but it's totally possible to solve this exactly, though you need to include vertices on either side.
Assume you're looking at a window of vertices [A, B, C, D] that are connected in that order. In this example we're determining the "cost" of combining B and C.
Calculate the angle offset from collinearity from A toward C. Basically you just want to see how far from collinear the two points are. This is |sin(|arctan(B - A)| - |arctan(C - A)|)| Where pipes are absolute value, and differences are the sensical notion of difference.
Calculate the total distance over which the angle change will effectively be applied, this is just the euclidean distance from A to B times the euclidean distance from B to C.
Multiply the terms from 2 and 3 to get your first term
To get your second term, repeat steps 2 - 4 replacing A with D, B with C, and C with B (just going in the opposite direction)
Calculate the geometric mean of the two terms obtained.
The number that results in step 6 presents the full-picture minus a couple constants.
I tried my own plan first: Protect the vertices touching the bounding box, then remove the rest in the order that changes the resultant area the least, until you can't find a vertice to remove that keeps the new polygon area within X% of the original one. This is the result with X = 5%:
When the user zooms out really far these shapes fit the bill well enough for me. I haven't tried any of the other suggestions. The savings are quite astonishing, sometimes from 80-100 vertices down to 4 or 5.
I'm writing a program that needs to quickly check whether a contiguous region of space is fillable by tetrominoes (any type, any orientation). My first attempt was to simply check if the number of squares was divisible by 4. However, situations like this can still come up:
As you can see, even though these regions have 8 squares each, they are impossible to tile with tetrominoes.
I've been thinking for a bit and I'm not sure how to proceed. It seems to me that the "hub" squares, or squares that lead to more than two "tunnels", are the key to this. It's easy in the above examples, since you can quickly count the spaces in each such tunnel — 3, 1, and 3 in the first example, and 3, 1, 1, and 2 in the second — and determine that it's impossible to proceed due to the fact that each tunnel needs to connect to the hub square to fit a tetromino, which can't happen for all of them. However, you can have more complicated examples like this:
...where a simple counting technique just doesn't work. (At least, as far as I can tell.) And that's to say nothing of more open spaces with a very small number of hub squares. Plus, I don't have any proof that hub squares are the only trick here. For all I know, there may be tons of other impossible cases.
Is some sort of search algorithm (A*?) the best option for solving this? I'm very concerned about performance with hundreds, or even thousands, of squares. The algorithm needs to be very efficient, since it'll be used for real-time tiling (more or less), and in a browser at that.
Perfect matching on a perfect matching
[EDIT 28/10/2014: As noticed by pix, this approach never tries to use T-tetrominoes, so it is even more likely to give an incorrect "No" answer than I thought...]
This will not guarantee a solution on an arbitrary shape, but it will work quickly and well most of the time.
Imagine a graph in which there is a vertex for each white square, and an edge between two vertices if and only if their corresponding white squares are adjacent. (Each vertex can therefore touch at most 4 edges.) A perfect matching in this graph is a subset of edges such that every vertex touches exactly one edge in the subset. In other words, it is a way of pairing up adjacent vertices -- or in yet other words, a domino tiling of the white squares. Later I'll explain how to find a nicely random-looking perfect matching; for now, let's just assume that it can be done.
Then, starting from this domino tiling, we can just repeat the matching process, gluing dominos together into tetrominos! The only differences the second time around are that instead of having a vertex per white square, we have a vertex per domino; and because we must add an edge whenever two dominos are adjacent, a vertex can now have as many as 6 edges.
The first step (domino tiling) step cannot fail: if a domino tiling for the given shape exists, then one will be found. However, it is possible for the second step (gluing dominos together into tetrominos) to fail, because it has to work with the already-decided domino tiling, and this may limit its options. Here is an example showing how different domino tilings of the same shape can enable or spoil the tetromino tiling:
AABCDD --> XXXYYY Success :)
BC XY
AABBDD --> Failure.
CC
Solving the maximum matching problems
In order to generate a random pattern of dominos, the edges in the graph can be given random weights, and the maximum weighted matching problem can be solved. The weights should be in the range [1, V/(V-2)), to guarantee that it is never possible to achieve a higher score by leaving some vertices unpaired. The graph is in fact bipartite as it contains no odd-length cycles, meaning that the faster O(V^2*E) algorithm for the maximum weighted bipartite matching problem can be used for this step. (This is not true for the second matching problem: one domino can touch two other dominos that touch each other.)
If the second step fails to find a complete set of tetrominos, then either no solution is possible*, or a solution is possible using a different set of dominos. You can try randomly reweighting the graph used to find the domino tiling, and then rerunning the first step. Alternatively, instead of completely reweighting it from scratch, you could just increase the weights for the problematic dominos, and try again.
* For a plain square with even side lengths, we know that a solution is always possible: just fill it with 2x2 square tetrominos.
Just wondering if there was a nice (already implemented/documented) algorithm to do the following
boo! http://img697.imageshack.us/img697/7444/sdfhbsf.jpg
Given any shape (without crossing edges) and two points inside that shape, compute all the paths between the two points such that all reflections are perfect reflections. The path lengths should be limited to a certain length otherwise there are infinite solutions. I'm not interested in just shooting out rays to try to guess how close I can get, I'm interested in algorithms that can do it perfectly. Search based, not guess/improvement based.
I think you can do better than computing fans. Call your points A and B. You want to find paths of reflections from A to B.
Start off by reflecting A in an edge, and call the reflection A1. Can you draw a line from A1 to B that only hits that edge? If yes, that means you have a path from A to B that reflects on the edge. Do this for all the edges and you'll get all the single reflection paths that exist. It should be easy to construct these paths using the properties of reflections. Along the way, you need to check that the paths are legal, i.e. they do not cross other edges.
You can continue to find paths consisting of two reflections by reflecting all the first generation reflections of A in all the edges, and checking to see whether a line can be drawn from those points through the reflecting edge to B. Keep on doing this search until the distance of the reflected points from B exceeds a threshold.
I hope this makes sense. It should be easier than chasing fans and dealing with their breakups, even though you're still going to have to do some work.
By the way, this is a corner of a well studied field of billiards on tables of various geometries. Of course, a billiard ball bounces off the side of a table the same way light bounces off a mirror, so this is just another way of thinking of reflections. You can delve into this with search terms like polygonal billiards unfolding illumination, although the mathematicians tend to dwell on finding cases where there are no pool shots between two points on a polygonal table, as opposed to directly solving the problem you've posed.
Think not in terms of rays but fans. A fan would be all the rays emanating from one point and hitting a wall. You can then check if the fan contains the second point and if it does you can determine which ray hits it. Once a fan hits a wall, you can compute the reflected fan by transposing it's origin onto the outside of the wall - by doing this all fans are basically triangle shaped. There are some complications when a fan partially hits a wall and has to be broken into pieces to continue. Anyway, this tree of reflected fans can be traversed breadth first or depth first since you're limiting the total distance.
You may also want to look into radiosity methods, which is probably similar to what I've just described, but is usually done in 3d.
I do not know of any existing solutions for such a problem. Good luck to you if you find one, but incase you don't the first step to a complete but exponential (with regard to the line count) would be to break it into two parts:
Given an ordered subset of walls A,B,C and points P1, P2, calculate if a route is possible (either no solutions or a single unique solution).
Then generate permutations of your walls until you exceed whatever limit you had in mind.
The first part can be solved by a simple set of equations to find the necessary angles for each ray bounce. Then checking each line against existing lines for collisions would tell you if the path is possible.
The parameters to the system of equations would be
angle_1 = normal of line A with P1
angle_2 = normal of line B with intersection of line A
angle_3 = normal of line C with ...
angle_n = normal of line N-1 with P2
Each parameter is bounded by the constraints to hit the next line, which may not be linear (I have not checked). If they are not then you would probably have to pick suitable numerical non-linear solvers.
In response to brainjam
You still need wedges....
alt text http://img72.imageshack.us/img72/6959/ssdgk.jpg
In this situation, how would you know not to do the second reflection? How do you know what walls make sense to reflect over?