#include <iostream>
#include <array>
#include <vector>
#include <map>
using TIndices = std::vector<int>;
using TFace = std::array<int, 3>;
using TFaces = std::vector<TFace>;
using TVertex = std::array<float, 3>;
using TVertices = std::vector<TVertex>;
void GenerateAdjacencies( const TVertices &vertices, const TFaces &faces, TIndices &adj )
{
// associate each geometric vertex position with an unique ID
std::vector<int> uniqueMap;
std::map<TVertex,int> tempUniqueVertices;
int uniqueIndex = 0;
for ( size_t vI = 0; vI < vertices.size(); ++ vI )
{
auto vIt = tempUniqueVertices.find( vertices[vI] );
if ( vIt == tempUniqueVertices.end() )
{
tempUniqueVertices[ vertices[vI] ] = uniqueIndex;
uniqueMap.push_back( uniqueIndex );
uniqueIndex ++;
}
else
uniqueMap.push_back( vIt->second );
}
tempUniqueVertices.clear();
// find all edges and associate the edge with all the points, which form a triangle with it.
std::map< std::tuple<int, int>, std::vector<int> > edges;
for ( auto & f : faces )
{
for ( int pI = 0; pI < 3; ++ pI )
{
int edgeU[2]{ uniqueMap[f[pI]], uniqueMap[f[(pI+1) % 3]] };
int i0 = edgeU[0] < edgeU[1] ? 0 : 1;
edges[{ edgeU[i0], edgeU[1-i0] }].push_back( f[(pI+2) % 3] );
}
}
// create the adjacencies
for ( auto & f : faces )
{
for ( int pI = 0; pI < 3; ++ pI )
{
int edgeU[2]{ uniqueMap[f[pI]], uniqueMap[f[(pI+1) % 3]] };
int i0 = edgeU[0] < edgeU[1] ? 0 : 1;
auto &adjs = edges[{ edgeU[i0], edgeU[1 - i0] }];
int adjI = adjs.size() > 1 && adjs[0] == f[(pI+2) % 3] ? 1 : 0;
adj.push_back( f[pI] );
adj.push_back( adjs[adjI] );
}
}
}
int main( void )
{
TVertices pt{
{ 1.0f, -1.0f, -1.0f },
{ 1.0f, -1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f },
{ 1.0f, 1.0f, -1.0f },
{ 1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f }
};
TFaces indices{
{ 2, 3, 4 },
{ 8, 7, 6 },
{ 5, 6, 2 },
{ 6, 7, 3 },
{ 3, 7, 8 },
{ 1, 4, 8 },
{ 1, 2, 4 },
{ 5, 8, 6 },
{ 1, 5, 2 },
{ 2, 6, 3 },
{ 4, 3, 8 },
{ 5, 1, 8 }
};
TVertices vertices;
TFaces faces;
int vI = 0;
for ( auto &f : indices )
{
for ( int i = 0; i < 3; ++ i )
vertices.push_back( pt[f[i]-1] );
faces.push_back( { vI++, vI++, vI++ } );
}
TIndices adj;
GenerateAdjacencies( vertices, faces, adj );
for ( size_t fI = 0; fI < faces.size(); ++ fI )
{
std::cout << "(" << faces[fI][0] << ", " << faces[fI][1] << ", " << faces[fI][2] << ") -> ";
for ( size_t aI = 0; aI < 6; ++ aI )
std::cout << adj[fI*6+aI] << " ";
std::cout << std::endl;
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPiAKI2luY2x1ZGUgPGFycmF5PgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bWFwPgoKdXNpbmcgVEluZGljZXMgID0gc3RkOjp2ZWN0b3I8aW50PjsKdXNpbmcgVEZhY2UgICAgID0gc3RkOjphcnJheTxpbnQsIDM+Owp1c2luZyBURmFjZXMgICAgPSBzdGQ6OnZlY3RvcjxURmFjZT47CnVzaW5nIFRWZXJ0ZXggICA9IHN0ZDo6YXJyYXk8ZmxvYXQsIDM+Owp1c2luZyBUVmVydGljZXMgPSBzdGQ6OnZlY3RvcjxUVmVydGV4PjsKCnZvaWQgR2VuZXJhdGVBZGphY2VuY2llcyggY29uc3QgVFZlcnRpY2VzICZ2ZXJ0aWNlcywgY29uc3QgVEZhY2VzICZmYWNlcywgVEluZGljZXMgJmFkaiApCiAgICB7CiAgICAgICAgLy8gYXNzb2NpYXRlIGVhY2ggZ2VvbWV0cmljIHZlcnRleCBwb3NpdGlvbiB3aXRoIGFuIHVuaXF1ZSBJRAogICAgICAgIHN0ZDo6dmVjdG9yPGludD4gICAgICB1bmlxdWVNYXA7CiAgICAgICAgc3RkOjptYXA8VFZlcnRleCxpbnQ+IHRlbXBVbmlxdWVWZXJ0aWNlczsKICAgICAgICBpbnQgdW5pcXVlSW5kZXggPSAwOwogICAgICAgIGZvciAoIHNpemVfdCB2SSA9IDA7IHZJIDwgdmVydGljZXMuc2l6ZSgpOyArKyB2SSApCiAgICAgICAgewogICAgICAgICAgICBhdXRvIHZJdCA9IHRlbXBVbmlxdWVWZXJ0aWNlcy5maW5kKCB2ZXJ0aWNlc1t2SV0gKTsKICAgICAgICAgICAgaWYgKCB2SXQgPT0gdGVtcFVuaXF1ZVZlcnRpY2VzLmVuZCgpICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGVtcFVuaXF1ZVZlcnRpY2VzWyB2ZXJ0aWNlc1t2SV0gXSA9IHVuaXF1ZUluZGV4OwogICAgICAgICAgICAgICAgdW5pcXVlTWFwLnB1c2hfYmFjayggdW5pcXVlSW5kZXggKTsKICAgICAgICAgICAgICAgIHVuaXF1ZUluZGV4ICsrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHVuaXF1ZU1hcC5wdXNoX2JhY2soIHZJdC0+c2Vjb25kICk7CiAgICAgICAgfQogICAgICAgIHRlbXBVbmlxdWVWZXJ0aWNlcy5jbGVhcigpOwoKICAgICAgICAvLyBmaW5kIGFsbCBlZGdlcyBhbmQgYXNzb2NpYXRlIHRoZSBlZGdlIHdpdGggYWxsIHRoZSBwb2ludHMsIHdoaWNoIGZvcm0gYSB0cmlhbmdsZSB3aXRoIGl0LiAKICAgICAgICBzdGQ6Om1hcDwgc3RkOjp0dXBsZTxpbnQsIGludD4sIHN0ZDo6dmVjdG9yPGludD4gPiBlZGdlczsKICAgICAgICBmb3IgKCBhdXRvICYgZiA6IGZhY2VzICkKICAgICAgICB7CiAgICAgICAgICBmb3IgKCBpbnQgcEkgPSAwOyBwSSA8IDM7ICsrIHBJICkKICAgICAgICAgIHsKICAgICAgICAgICAgaW50IGVkZ2VVWzJdeyB1bmlxdWVNYXBbZltwSV1dLCB1bmlxdWVNYXBbZlsocEkrMSkgJSAzXV0gfTsKICAgICAgICAgICAgaW50IGkwID0gZWRnZVVbMF0gPCBlZGdlVVsxXSA/IDAgOiAxOwogICAgICAgICAgICBlZGdlc1t7IGVkZ2VVW2kwXSwgZWRnZVVbMS1pMF0gfV0ucHVzaF9iYWNrKCBmWyhwSSsyKSAlIDNdICk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBjcmVhdGUgdGhlIGFkamFjZW5jaWVzCiAgICAgICAgZm9yICggYXV0byAmIGYgOiBmYWNlcyApCiAgICAgICAgewogICAgICAgICAgICBmb3IgKCBpbnQgcEkgPSAwOyBwSSA8IDM7ICsrIHBJICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaW50IGVkZ2VVWzJdeyB1bmlxdWVNYXBbZltwSV1dLCB1bmlxdWVNYXBbZlsocEkrMSkgJSAzXV0gfTsKICAgICAgICAgICAgICAgIGludCAgIGkwICAgPSBlZGdlVVswXSA8IGVkZ2VVWzFdID8gMCA6IDE7CiAgICAgICAgICAgICAgICBhdXRvICZhZGpzID0gZWRnZXNbeyBlZGdlVVtpMF0sIGVkZ2VVWzEgLSBpMF0gfV07CiAgICAgICAgICAgICAgICBpbnQgICBhZGpJID0gYWRqcy5zaXplKCkgPiAxICYmIGFkanNbMF0gPT0gZlsocEkrMikgJSAzXSA/IDEgOiAwOwogICAgICAgICAgICAgICAgYWRqLnB1c2hfYmFjayggZltwSV0gKTsKICAgICAgICAgICAgICAgIGFkai5wdXNoX2JhY2soIGFkanNbYWRqSV0gKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCmludCBtYWluKCB2b2lkICkKewogICAgVFZlcnRpY2VzIHB0ewogICAgICAgIHsgIDEuMGYsIC0xLjBmLCAtMS4wZiB9LAogICAgICAgIHsgIDEuMGYsIC0xLjBmLCAgMS4wZiB9LAogICAgICAgIHsgLTEuMGYsIC0xLjBmLCAgMS4wZiB9LAogICAgICAgIHsgLTEuMGYsIC0xLjBmLCAtMS4wZiB9LAogICAgICAgIHsgIDEuMGYsICAxLjBmLCAtMS4wZiB9LAogICAgICAgIHsgIDEuMGYsICAxLjBmLCAgMS4wZiB9LAogICAgICAgIHsgLTEuMGYsICAxLjBmLCAgMS4wZiB9LAogICAgICAgIHsgLTEuMGYsICAxLjBmLCAtMS4wZiB9CiAgICB9OwoKICAgIFRGYWNlcyBpbmRpY2VzewogICAgICAgIHsgMiwgMywgNCB9LAogICAgICAgIHsgOCwgNywgNiB9LAogICAgICAgIHsgNSwgNiwgMiB9LAogICAgICAgIHsgNiwgNywgMyB9LAogICAgICAgIHsgMywgNywgOCB9LAogICAgICAgIHsgMSwgNCwgOCB9LAogICAgICAgIHsgMSwgMiwgNCB9LAogICAgICAgIHsgNSwgOCwgNiB9LAogICAgICAgIHsgMSwgNSwgMiB9LAogICAgICAgIHsgMiwgNiwgMyB9LAogICAgICAgIHsgNCwgMywgOCB9LAogICAgICAgIHsgNSwgMSwgOCB9CiAgICB9OwoKICAgIFRWZXJ0aWNlcyB2ZXJ0aWNlczsKICAgIFRGYWNlcyAgICBmYWNlczsKICAgIGludCB2SSA9IDA7CiAgICBmb3IgKCBhdXRvICZmIDogaW5kaWNlcyApCiAgICB7CiAgICAgIGZvciAoIGludCBpID0gMDsgaSA8IDM7ICsrIGkgKQogICAgICAgIHZlcnRpY2VzLnB1c2hfYmFjayggcHRbZltpXS0xXSApOwogICAgICBmYWNlcy5wdXNoX2JhY2soIHsgdkkrKywgdkkrKywgdkkrKyB9ICk7CiAgICB9CgogICAgVEluZGljZXMgYWRqOwogICAgR2VuZXJhdGVBZGphY2VuY2llcyggdmVydGljZXMsIGZhY2VzLCBhZGogKTsKCiAgICBmb3IgKCBzaXplX3QgZkkgPSAwOyBmSSA8IGZhY2VzLnNpemUoKTsgKysgZkkgKQogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCAiKCIgPDwgZmFjZXNbZkldWzBdIDw8ICIsICIgPDwgZmFjZXNbZkldWzFdIDw8ICIsICIgPDwgZmFjZXNbZkldWzJdIDw8ICIpIC0+ICI7CgogICAgICAgIGZvciAoIHNpemVfdCBhSSA9IDA7IGFJIDwgNjsgKysgYUkgKQogICAgICAgICAgc3RkOjpjb3V0IDw8IGFkaltmSSo2K2FJXSA8PCAiICI7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKICAgIH0KCiAgICByZXR1cm4gMDsKfQ==