Here is an implementation operating on a triangle-mesh, finding and connecting all non-doubled edges as explained also in this answer.
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iostream>
typedef int Vertex;
class Triangle {
public:
const Vertex& operator [] (size_t i) const {
return p[i];
}
Vertex p[3];
};
std::list<std::list<Vertex>> find_contours(const std::vector<Triangle>& triangles) {
std::set<std::pair<Vertex, Vertex>> edges;
std::map<Vertex, Vertex> neighbors;
for(const auto& t : triangles) {
edges.insert(std::make_pair(t[0], t[1]));
edges.insert(std::make_pair(t[1], t[2]));
edges.insert(std::make_pair(t[2], t[0]));
}
for(const auto& t : triangles) {
edges.erase(std::make_pair(t[1], t[0]));
edges.erase(std::make_pair(t[2], t[1]));
edges.erase(std::make_pair(t[0], t[2]));
}
for(const auto& t : triangles) {
if (edges.find(std::make_pair(t[0], t[1])) != edges.end()) {
neighbors[t[0]] = t[1];
}
if (edges.find(std::make_pair(t[1], t[2])) != edges.end()) {
neighbors[t[1]] = t[2];
}
if (edges.find(std::make_pair(t[2], t[0])) != edges.end()) {
neighbors[t[2]] = t[0];
}
}
std::list<std::list<Vertex>> result;
while(!neighbors.empty()) {
std::list<Vertex> contour;
auto v0 = neighbors.begin()->first;
auto v = v0;
while(neighbors.find(v) != neighbors.end()) {
contour.push_back(v);
auto old_v = v;
v = neighbors.at(v);
neighbors.erase(old_v);
}
if (v != v0) {
throw std::runtime_error("Contour is not closed");
}
neighbors.erase(v);
result.push_back(contour);
}
return result;
}
int main() {
int v00 = 0;
int v10 = 1;
int v01 = 2;
int v11 = 3;
std::vector<Triangle> v{
{v00, v10, v11},
{v00, v11, v01}};
for(const auto& c : find_contours(v)) {
for(const auto& v : c) {
std::cerr << v << " | ";
}
std::cerr << std::endl;
}
std::cerr << std::endl;
return 0;
}