Random non-intersecting walk through triangulation #57
-
I'm trying to compute a random non-intersecting walk through a triangulation. My algorithm (which I believe works logically) is:
So I'm expecting something like this: However, I'm getting something like this: It's not clear to me whether it's a problem with my logic/code or an incorrect assumption about how pinwheel or vertex or edges work in Tinfour -- hoping you could clarify where I might be going wrong. Thanks. The Code:
|
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
I'll look at this tomorrow. In the mean time, perhaps it would be useful to
keep track of where your path has been using a Java Bitset and and the edge
indices.
…On Fri, Feb 5, 2021, 4:25 PM Michael Carleton ***@***.***> wrote:
I'm trying to compute a random non-intersecting walk through a
triangulation.
My algorithm (which I believe works logically) is:
- Start with a random edge.
- Get edges connected to its A vertex via pinwheel() [1]
- Randomly choose an edge connected to A: if its B vertex hasn't been
seen, choose this edge for next iteration
- Reverse the edge, so that the its pinwheel will operate on the an
unseen vertex (instead of the one we just came from)
- Loop back to [1] unless we've reached the maximum path length
So I'm expecting something like this:
[image: image]
<https://user-images.githubusercontent.com/9304234/107088322-b4ec5380-67f4-11eb-95d5-f254c99acb7c.png>
However, I'm getting something like this:
[image: image]
<https://user-images.githubusercontent.com/9304234/107089769-17465380-67f7-11eb-8bf2-ccc680369c3a.png>
It's not clear to me whether it's a problem with my logic/code or an
incorrect assumption about how pinwheel or vertex or edges work in Tinfour
-- hoping you could clarify where I might be going wrong. Thanks.
The Code:
IncrementalTin tin = new IncrementalTin(10);
tin.add(vertexList, null);
HashSet<Vertex> seen = new HashSet<>();
ArrayList<Vertex> pathVertices = new ArrayList<>();
int pathLength = 100; // path vertex count
IQuadEdge lastEdge = tin.getStartingEdge();
int n = 1;
while (n < pathLength) {
List<IQuadEdge> list = new ArrayList<>();
lastEdge.pinwheel().forEach(list::add); // get edges connected to A; add to array
// edges returned by pinwheel have A at the pinwheel and point to new vertices
// B?
IQuadEdge nextEdge;
int attempts = 0;
do {
nextEdge = list.get((int) random(list.size())).getForward();
attempts++;
} while (!seen.contains(nextEdge.getB()) && attempts < 50);
if (attempts > 50) {
return; // path ended prematurely (no possible edges to take)
}
lastEdge = nextEdge.getReverse(); // A and B flip around, so A is at a unique point, ready for pinwheel next
// iter
pathVertices.add(lastEdge.getB()); // add the point we just came from
seen.add(lastEdge.getB());
n++;
}
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#57>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEWJDYMM7VGXYIRGL6GRQALS5RO3HANCNFSM4XFOSNVQ>
.
|
Beta Was this translation helpful? Give feedback.
-
I take it that the restriction is never pass through a vertex more than
once?
…On Fri, Feb 5, 2021, 7:47 PM Gary Lucas ***@***.***> wrote:
I'll look at this tomorrow. In the mean time, perhaps it would be useful
to keep track of where your path has been using a Java Bitset and and the
edge indices.
On Fri, Feb 5, 2021, 4:25 PM Michael Carleton ***@***.***>
wrote:
> I'm trying to compute a random non-intersecting walk through a
> triangulation.
>
> My algorithm (which I believe works logically) is:
>
> - Start with a random edge.
> - Get edges connected to its A vertex via pinwheel() [1]
> - Randomly choose an edge connected to A: if its B vertex hasn't been
> seen, choose this edge for next iteration
> - Reverse the edge, so that the its pinwheel will operate on the an
> unseen vertex (instead of the one we just came from)
> - Loop back to [1] unless we've reached the maximum path length
>
> So I'm expecting something like this:
>
> [image: image]
> <https://user-images.githubusercontent.com/9304234/107088322-b4ec5380-67f4-11eb-95d5-f254c99acb7c.png>
>
> However, I'm getting something like this:
>
> [image: image]
> <https://user-images.githubusercontent.com/9304234/107089769-17465380-67f7-11eb-8bf2-ccc680369c3a.png>
>
> It's not clear to me whether it's a problem with my logic/code or an
> incorrect assumption about how pinwheel or vertex or edges work in Tinfour
> -- hoping you could clarify where I might be going wrong. Thanks.
>
> The Code:
>
> IncrementalTin tin = new IncrementalTin(10);
>
> tin.add(vertexList, null);
> HashSet<Vertex> seen = new HashSet<>();
>
> ArrayList<Vertex> pathVertices = new ArrayList<>();
> int pathLength = 100; // path vertex count
>
> IQuadEdge lastEdge = tin.getStartingEdge();
>
> int n = 1;
> while (n < pathLength) {
>
> List<IQuadEdge> list = new ArrayList<>();
> lastEdge.pinwheel().forEach(list::add); // get edges connected to A; add to array
>
> // edges returned by pinwheel have A at the pinwheel and point to new vertices
> // B?
>
> IQuadEdge nextEdge;
> int attempts = 0;
> do {
> nextEdge = list.get((int) random(list.size())).getForward();
> attempts++;
> } while (!seen.contains(nextEdge.getB()) && attempts < 50);
>
> if (attempts > 50) {
> return; // path ended prematurely (no possible edges to take)
> }
> lastEdge = nextEdge.getReverse(); // A and B flip around, so A is at a unique point, ready for pinwheel next
> // iter
> pathVertices.add(lastEdge.getB()); // add the point we just came from
> seen.add(lastEdge.getB());
> n++;
> }
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <#57>, or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AEWJDYMM7VGXYIRGL6GRQALS5RO3HANCNFSM4XFOSNVQ>
> .
>
|
Beta Was this translation helpful? Give feedback.
-
I'm working on this now and having pretty much the same problem that you did. One thing to note. Where you want to flip the edge around to get its mirror image, and your code calls getReverse()
It should be calling getDual(). The getReverse() call gets the reverse link of the edge. And getForward() gets the forward link. Tinfour uses the term "dual" of an edge to indicate its opposite side (so the dual of A-to-B is B-to-A). You would use getForward() or getReverse() if you were building a triangle. On a side topic, something that might help your drawing code... I notice some spikey line joins. These are probably due to you using the default Java basic stroke, which specifies mitered joins. When a rendering has sharp turns, I find it cleaner to use bevel joins:
Here's my work so far. And although I haven't solved the real problem, at least it shows the join effect I'm talking about. |
Beta Was this translation helpful? Give feedback.
-
Okay, I made some progress. The main problem was in the way your code used getForward() in the do-while loop. A lesser problem was in your post loop test where you checked for attempts>50 it should have been attempts == 50. I also had to add some checks for "ghost" vertices (the null vertex) for cases where the pinwheel would rotate to an edge outside the tin... When I designed the pinwheel, I debated about whether it should do that, but decided that I needed to capability for other purposes. Here's my code:
Incidentally, I was unfamiliar with that Java forEach syntax that you used:
So thanks for showing me a new trick... I'm sure t will come in handy in the future. |
Beta Was this translation helpful? Give feedback.
Okay, I made some progress. The main problem was in the way your code used getForward() in the do-while loop. A lesser problem was in your post loop test where you checked for attempts>50 it should have been attempts == 50. I also had to add some checks for "ghost" vertices (the null vertex) for cases where the pinwheel would rotate to an edge outside the tin... When I designed the pinwheel, I debated about whether it should do that, but decided that I needed to capability for other purposes.
Here's my code: