I have a mesh in a form like this. with a list of indices representing each polygon at the end. I need to generate a list of neighboring polygons for each polygon, and was w
Without precomputed data it is not possible to do it faster than looping through all faces.
For precomputed data it is enough for each vertex to hold a list of faces where it is used. Finding neighbors is done with intersecting face lists of 2 vertices.
Provided that you are solely interested in triangulized meshes (or any simplex in n-D), there actually are faster solutions! The time complexity of the suggestion you make is O(k^2), where k is the number of triangles. This means that for a large number of triangles the time needed to compute the neighbors increases quadratic, which is computationally prohibitive in most situations.
I would suggest you read the article of Ueng and Sikorski ("A note on a linear time algorithm for constructing adjacency graphs of 3D FEA data", The Visual Computer 12: pp. 445-450, 1996). The authors explain a linear time algorithm O(k) for finding the neighbors in a tetrahedral mesh, from which you can easily deduce a similar algorithm for triangulized meshes. Perhaps you will be able to expand this to general polygons as well!
Let me know if this works for you!
Ouch, XML meshes :).
I actually had a good look at this, my first answer was pretty lazy. you can write better (as posted above), and it's not that complicated, I wouldn't fork out $40 for a journal article over this. Here's a pseudo-code solution which should work for you.
Note: When I say table, I mean 'lookup table'.
Assume each triangle is numbered and composed of vertices, v1, v2, v3, which are uniquely numbered and can be compared using the < operator (so we can obtain unique key-combinations).
We need two look-up tables:
A table which tells us which triangles use a given edge, and another which tells us which edges a a given triangle is comprised of. We build these lists as follows:
for t = next triangle
// Determine the ordering of vertices.
min_vertex = min(t.v1, t.v2, t.v3);
mid_vertex = median(p.v1, t.v2, t.v3);
max_vertex = max(t.v1, t.v2, t.v3);
// Register which edges this triangle uses.
edge_triangles[min_vertex][mid_vertex].append(t);
edge_triangles[mid_vertex][max_vertex].append(t);
edge_triangles[min_vertex][max_vertex].append(t);
// Set the edges that make up this triangle.
triangle_edges[t].append({min_vertex, mid_vertex});
triangle_edges[t].append({mid_vertex, max_vertex});
triangle_edges[t].append({min_vertex, max_vertex});
for next t
Using these lists, we can take the edges in a given triangle, use these as the key into the edge table, and see which polygons share that edge. Thus, the adjacent triangles. So for a triangle t we could do the following:
adjacent = edge_faces[face_edges[t][0]];
which is pseudo-code for 'adjacent is equal to the list of triangles that share the 0th edge of the triangle t', where 0th is just the first.
We use min, median and max to make sure that that we don't have different entries for identical edges: for example {v1, v2} and {v2, v1}, where v1 and v2 are two vertices. We could actually ignore this and add a 'compact' step, where we concatenate lists which correspond to different entries in our edge list but actually correspond to the same edge.
One other possible problem with this is if you have two edges which are coincident but don't share common vertices. In this case, you could reduce either edge to a parametric equation, compare them for coincidence, and form a lookup table which tells you, for a given edge, which edges are coincident, so map:
We use yet another look-up table because we can't concatenate the edge->faces table. Cosider if edges e1 and e2 are adjacent, e2 and e3 are, but e1 and e3 aren't. if we concatenated the e1, e2 and e3 entries in the edge->face list, you'd end up with some wildly incorrect data. This a probably bit more than you want to do, but it's the problem I had to solve this morning :).
In the case where each edge can only correspond to at most 2 triangles, we can do away with the 'list' in the traditional sense that we can append, and use a fixed-size array of size 2. This will reduce your memory overhead and improve memory efficiency. so our edge table would be more akin to:
Anyway, the basic algorithm is extensible to any number of polygons with any number of edges (not necessarily the same between all polygons), and is O(N) time with respect to the number of triangles (or polygons in the general case). Space complexity is O(E + N) Where E is edges and N is the number of polygons. The look-up time should be close to O(1), assuming you have good hashing algorithms.