* Extract boundary loops from an array of boudnary segments. * Assuming boundary segments are orientated consistently. */
| 25 | * Assuming boundary segments are orientated consistently. |
| 26 | */ |
| 27 | Loops extract_loops(const MatrixIr& boundaries) { |
| 28 | assert(boundaries.cols() == 2); |
| 29 | const size_t num_boundaries = boundaries.rows(); |
| 30 | std::unordered_map<size_t, std::list<MatrixIr::Scalar> > adjacencies; |
| 31 | |
| 32 | for (size_t i=0; i<num_boundaries; i++) { |
| 33 | const VectorI& edge = boundaries.row(i); |
| 34 | auto itr = adjacencies.find(edge[0]); |
| 35 | if (itr != adjacencies.end()) { |
| 36 | itr->second.push_back(edge[1]); |
| 37 | } else { |
| 38 | adjacencies.insert({edge[0], {edge[1]}}); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | Loops loops; |
| 43 | std::unordered_set<size_t> visited; |
| 44 | for (const auto& itr : adjacencies) { |
| 45 | auto i = itr.first; |
| 46 | if (itr.second.empty()) continue; // Vertex not part of loop. |
| 47 | |
| 48 | Loop loop; |
| 49 | loop.push_back(i); |
| 50 | visited.insert(i); |
| 51 | do { |
| 52 | auto& neighbors = adjacencies[loop.back()]; |
| 53 | if (neighbors.empty()) { |
| 54 | throw RuntimeError("Open loop detected."); |
| 55 | } |
| 56 | int next = neighbors.front(); |
| 57 | neighbors.pop_front(); |
| 58 | loop.push_back(next); |
| 59 | visited.insert(next); |
| 60 | } while (loop.back() != loop.front()); |
| 61 | loop.pop_back(); |
| 62 | if (loop.size() > 0) loops.push_back(loop); |
| 63 | } |
| 64 | return loops; |
| 65 | } |
| 66 | |
| 67 | class PointConvert { |
| 68 | public: |
no test coverage detected