How to index the faces of an icosahedron?

I am writing a simulation that acts on a grid displayed over the surface of a sphere. The grid itself is subdivided into Icosahedron (however, the level of the subsection is not known in advance)

With a grid of squares, itโ€™s easy to find neighboring cells, because they will be plus or minus 1 along the x or y axis. But this does not apply to any of these triangles, my mind has difficulty visualizing the way cell indexing.

Is there any coordinate system that I could use to refer to the faces of the icosahedron, which at least makes it easier to get three cells adjacent to any arbitrary cell in the icosahedron?

+5
source share
4 answers

For each side of the icosahedron, you can match triangles with a grid, each square of the grid is divided into two parts, for example. (hexadecimal index numbering for easy formatting):

A + |\ |0\ +--+ |\2|\ |1\|3\ +--+--+ |\5|\7|\ |4\|6\|8\ +--+--+--+ |\A|\C|\E|\ |9\|B\|D\|F\ +--+--+--+--+ BC 

For a side divided by n times, there are 4 n triangles on the side, so you can create an array of this size for each side of the icosahedron to store any data for the triangle for your simulation.

The triangle reference can be saved as (side, row, column)

Row and column indices are based on 0. A column index is based on the number of triangles in a row (i.e. 2 per square grid).

If you have a side, row and column, you can calculate the index in the array for that side as follows:

 index = (row * row) + column 

So, you can store data in a 2d array and access it as follows:

 value = data[side][(row * row) + column] 

Adjacent triangles for an even column triangle:

 (side, row, column - 1) (side, row, column + 1) (side, row + 1, column + 1) 

Adjacent triangles for an odd number triangle:

 (side, row, column - 1) (side, row, column + 1) (side, row - 1, column - 1) 

This makes it easy to refer to triangles in a divided triangular grid without explicitly storing adjacency information.

Capture is what you need to organize in the icosahedron. After calculating the links to neighboring triangles, you need to check that the new link is within the side:

 int rows = 1 << subdivision_count; if(row >= rows) { // compute (side, row, column) in adjacent side of icosahedron to BC edge } else if(column < 0) { // compute (side, row, column) in adjacent side of icosahedron to AB edge } else if(column >= ((row * 2) + 1)) { // compute (side, row, column) in adjacent side of icosahedron to AC edge } 

You will need to store adjacency information for each side, as well as the type of rib (AB, BC, AC).

You will be presented with 9 different possible comparisons that you will need to figure out, one for each edge type combination. For example, if a neighboring triangle intersects the edge AC, and this edge corresponds to the edge AB of the neighboring side, then

 side = adjacent side (from table) row = row column = column - ((row * 2) + 1) 

etc.

This is a more complex approach in some respects, but simpler in others. The benefits of all this:

  • No need to save adjacency information for individual triangles, only for icosahedron supporters
  • Three-dimensional triangular coordinates can be calculated for the triangle specified by the link (side, row, column) if you keep the three-dimensional position A, B, C for each side, so there is no need to store them on a triangle either
+2
source

Essentially, you want to pre-process your geometry in a specific data structure that allows you to quickly find neighboring triangles.

If this is your only requirement, itโ€™s easy to โ€œfold your own.โ€ For example, for each triangle you save its three edges, either as pointers to the structure of the edges, or as indices in the table of edges. Then for each edge you save two adjacent triangles (again either as pointers or as indices of the triangle).

This setting allows you to easily move from a triangle to each of its edges, and then find another neighboring triangle from the edge structure.

There are more complex data structures for triangulated surfaces that allow you to perform more interesting operations, for example, a doubly linked list of edges or a data structure for winged edges .

If you want to use the premade library, the library

+5
source

This is an interesting question. The exact answer depends on how you separate the faces of the icosahedron that you are not talking about. But I will give a framework for attacking this question.

First, let me say that, in my opinion, the question is simplified in the case of a square grid: there is a mathematical group structure that reflects the symmetry on the grid. To be precise, there are a couple of simple transformations (shift up, shift to the right), which together with their inverters generate each transformation of one grid cell to another. In addition, the up and down shift operations are switched: the order in which you apply the sequence of operations does not change the result. Up and right operations generate a commutative group of transformations on a grid of cells. The group is isomorphic to ZxZ , therefore beautiful coordinates are given by pairs of integers (m,n) .

The lack of such a structure on the icosahedron is one of the problems for your question. There is a group structure on the icosahedron with two generators, sometimes called "a" and "b", where "a" is a 180 degree rotation that displays a given edge onto itself, the reverse and b is a 120 degree rotation of a given face. The problem is that the group is not commutative, therefore ab! = Ba. This seriously complicates the calculations using group generators. Another problem is that this triple method covers every face (once for each rotation). There are 60 elements in the rotational symmetry group of the A5 icosahedron, but only 20 faces on the icosahedron.

A very interesting way to solve these problems was discovered by William Hamilton in > Icosian calculus and popularized in the Icosian Game . It is noteworthy that Hamilton gives generators for the icosahedron rotation group (which he symbolized with Greek iota and kappa instead of a and b) before the concepts of groups and generators were really invented (or, at least, well understood). Hamilton then used his Ikosyan calculus to find the Hamiltonian diagram on the graph of the vertices of the dodecahedron (or, equivalently, the graph of faces of the icosahedron, since the dodecahedron and icosahedron are dual to each other). See the graph here .

This graph can be used to index the faces of the icosahedron in a cyclic order from 0 to 19. Map the points on the graph of the vertices of the dodecahedron from 0 to 19 in the Hamiltonian cycle; which corresponds to the numbering of adjacent faces of the icosahedron also along the Hamiltonian cycle. Given the face m, two of its adjacent faces m-1 modulo 20 and m + 1 modulo 20; the third adjacent face is given by a dashed line in the graph . Maybe there is a good formula or template for the index of a third related person, but I do not see it out loud; it could be easily stored in a table.

If you divide the faces in a certain way, you can continue the Hamiltonian cycle in faces. Divide each face into three faces by entering a new dot in the center of the face. Then you can find the Hamiltonian path through three new triangles in the face (just go through them clockwise or counterclockwise, depending on the ratio between the edge of the entrance and the edge of the exit). If you further divide the faces in this way, you will get a Hamiltonian path through further separated triangles in the form of a space filling curve. The problem with this split face is that the maximum lengths of the edges of the triangles do not decrease.

For a more common way of splitting triangles (by splitting edges instead of introducing new points in the centers of the faces), I cannot find a way to extend the Hamiltonian cycle on the icosahedron to the Hamiltonian path on a new figure. Therefore, it will probably be easier for you to use one of the other methods proposed for indexing triangular faces in order to find neighboring triangles inside the face, and compare this with the method that I offer for indexing the faces of the icosahedron to find neighboring triangles in another face.

Update

I was thinking about indexing faces. Using images from the Wikipedia page for Triangular tilings , the face will consist of a large triangular section of an endless tile

Equilateral triangle tiling

The affine transform (which does not affect indexing) converts this image to

Right triangle tiling

However, the last image contains squares, so the triangles are easily indexed with the x coordinate of the lower corner of the square, the y coordinate of the lower corner of the square and one bit (0 or 1) to indicate whether the triangle is yellow or green. Three triangles next to the yellow triangle (m, n, 0) are equal (m-1, n, 1), (m, n-1,1) and (m, n, 1) and three triangles next to the green triangle (m , n, 1) are (m, n, 0), (m + 1, n, 0) and (m, n + 1,0); all of these operations are quick decrements, increments, or bit flips. Doubling the number of triangles is achieved by dividing the square into (m, n) into four smaller squares with coordinates (2m + 0,2n + 0), (2m + 1,2n + 0), (2m + 0,2n + 1) and (2m + 1,2n + 1); therefore, the yellow triangle in (m, n, 0) is divided into yellow triangles for (2m, 2n, 0), (2m + 1,2n, 0), (2m, 2n + 1,0 ) and the green triangle in (2m, 2n, 1), and the green triangle in (m, n, 1) is divided into green triangles for (2m + 1,2n, 1), (2m, 2n + 1,1), ( 2m + 1.2n + 1.1) and the yellow triangle at (2m + 1.2n + 1.0); all these operations are quick shifts, adds without hyphenation and flips the bit. Finally, we can determine if the triangle (x, y, c) is on the bottom border, if the y coordinate is negative, from the left border, if the x coordinate is negative and goes diagonally if x + y + c> regardless of the size of the triangle, another quick operation. No multiplications.

What do we mean by โ€œbottomโ€ for the faces of a three-dimensional figure? The Hamiltonian cycle also answers this: the "bottom" of any face is the side from which the (oriented) Hamiltonian cycle enters. This gives us a unique orientation on each face.

Thus, each sub-triangle now has a good coordinate: (f, x, y, c), where f is the face of the icosahedron counted along the Hamiltonian cycle, x is the x coordinate of the parallelogram containing the triangle, y is the y coordinate of the parallelogram, c - color (0 (yellow) for the lower left, 1 (green) for the upper right). Neighbors can be calculated in three quick operations, plus a simple test outside the boundaries, the division can only be performed with some shifts and adds without hyphenation. If the neighboring test goes beyond, you simply decrease f mod 20, increase f mod 20, or look at the โ€œdashed lineโ€ to the side. You can also scroll through each triangle in a simple way, first iterating over the faces, then through the triangles with x + y + c = constant inside each face.

+2
source

It is trivial to assign each triangle a set {s,x,y} , where s denotes a side, and x,y denotes a position inside this side:

  /\ /Y /__\ /\ /\ /__\/__\ ->X 

It would have the triangles {0,0}, {1,1} (middle), {2,0} and {0,2}. Within the plane (same s), the x & y coordinates indicate what the boundaries of the triangle are. You will need one table for 30 edges, which designates each edge whose triangles are located on both sides, and how their X, Y coordinates are ordered.

(Perhaps you could come up with smart numbering instead of a table, I couldn't.)

+1
source

All Articles