// // Copyright (C) 2004 Tanguy Fautré. // For conditions of distribution and use, // see copyright notice in tri_stripper.h // ////////////////////////////////////////////////////////////////////// // SVN: $Id: connectivity_graph.cpp 86 2005-06-08 17:47:27Z gpsnoopy $ ////////////////////////////////////////////////////////////////////// #include "detail/connectivity_graph.h" #include namespace triangle_stripper { namespace detail { namespace { class tri_edge : public triangle_edge { public: tri_edge(index A, index B, size_t TriPos) : triangle_edge(A, B), m_TriPos(TriPos) { } size_t TriPos() const { return m_TriPos; } private: size_t m_TriPos; }; class cmp_tri_edge_lt { public: bool operator() (const tri_edge & a, const tri_edge & b) const; }; typedef std::vector edge_map; void LinkNeighbours(graph_array & Triangles, const edge_map & EdgeMap, const tri_edge Edge); } void make_connectivity_graph(graph_array & Triangles, const indices & Indices) { assert(Triangles.size() == (Indices.size() / 3)); // Fill the triangle data for (size_t i = 0; i < Triangles.size(); ++i) Triangles[i] = triangle(Indices[i * 3 + 0], Indices[i * 3 + 1], Indices[i * 3 + 2]); // Build an edge lookup table edge_map EdgeMap; EdgeMap.reserve(Triangles.size() * 3); for (size_t i = 0; i < Triangles.size(); ++i) { const triangle & Tri = * Triangles[i]; EdgeMap.push_back(tri_edge(Tri.A(), Tri.B(), i)); EdgeMap.push_back(tri_edge(Tri.B(), Tri.C(), i)); EdgeMap.push_back(tri_edge(Tri.C(), Tri.A(), i)); } std::sort(EdgeMap.begin(), EdgeMap.end(), cmp_tri_edge_lt()); // Link neighbour triangles together using the lookup table for (size_t i = 0; i < Triangles.size(); ++i) { const triangle & Tri = * Triangles[i]; LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.B(), Tri.A(), i)); LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.C(), Tri.B(), i)); LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.A(), Tri.C(), i)); } } namespace { inline bool cmp_tri_edge_lt::operator() (const tri_edge & a, const tri_edge & b) const { const index A1 = a.A(); const index B1 = a.B(); const index A2 = b.A(); const index B2 = b.B(); if ((A1 < A2) || ((A1 == A2) && (B1 < B2))) return true; else return false; } void LinkNeighbours(graph_array & Triangles, const edge_map & EdgeMap, const tri_edge Edge) { // Find the first edge equal to Edge edge_map::const_iterator it = std::lower_bound(EdgeMap.begin(), EdgeMap.end(), Edge, cmp_tri_edge_lt()); // See if there are any other edges that are equal // (if so, it means that more than 2 triangles are sharing the same edge, // which is unlikely but not impossible) for (; (it != EdgeMap.end()) && (Edge == (* it)); ++it) Triangles.insert_arc(Edge.TriPos(), it->TriPos()); // Note: degenerated triangles will also point themselves as neighbour triangles } } } // namespace detail } // namespace detail