| 59 | using namespace WireEdgePeriodicIndexAttributeHelper; |
| 60 | |
| 61 | void WireEdgePeriodicIndexAttribute::compute(const WireNetwork& network) { |
| 62 | const Float EPS = 1e-6; |
| 63 | const size_t num_vertices = network.get_num_vertices(); |
| 64 | const size_t num_edges = network.get_num_edges(); |
| 65 | const MatrixFr& vertices = network.get_vertices(); |
| 66 | const MatrixIr& edges = network.get_edges(); |
| 67 | |
| 68 | const VectorF bbox_min = vertices.colwise().minCoeff(); |
| 69 | const VectorF bbox_max = vertices.colwise().maxCoeff(); |
| 70 | const VectorF bbox_size = bbox_max - bbox_min; |
| 71 | |
| 72 | std::vector<bool> on_min_border(num_vertices, false); |
| 73 | HashGrid::Ptr grid = HashGrid::create(EPS, network.get_dim()); |
| 74 | for (size_t i=0; i<num_vertices; i++) { |
| 75 | const VectorF& v = vertices.row(i); |
| 76 | grid->insert(i, v); |
| 77 | if ((v-bbox_min).cwiseAbs().minCoeff() < EPS) { |
| 78 | on_min_border[i] = true; |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | m_values.resize(num_edges, 1); |
| 83 | DupletMap<size_t> edge_map; |
| 84 | for (size_t i=0; i<num_edges; i++) { |
| 85 | const VectorI& edge = edges.row(i); |
| 86 | Duplet key(edge[0], edge[1]); |
| 87 | edge_map.insert(key, i); |
| 88 | m_values(i, 0) = i; |
| 89 | } |
| 90 | |
| 91 | FunctionList transforms = get_periodic_transforms(bbox_size); |
| 92 | |
| 93 | for (auto transform : transforms) { |
| 94 | for (size_t i=0; i<num_edges; i++) { |
| 95 | const VectorI& edge = edges.row(i); |
| 96 | if (on_min_border[edge[0]] || on_min_border[edge[1]]) { |
| 97 | VectorF v0 = transform(vertices.row(edge[0])); |
| 98 | VectorF v1 = transform(vertices.row(edge[1])); |
| 99 | |
| 100 | VectorI opposite_v0_index = grid->get_items_near_point(v0); |
| 101 | VectorI opposite_v1_index = grid->get_items_near_point(v1); |
| 102 | if (opposite_v0_index.size() != 1 || |
| 103 | opposite_v1_index.size() != 1) { continue; } |
| 104 | |
| 105 | Duplet key(opposite_v0_index[0], opposite_v1_index[0]); |
| 106 | auto itr = edge_map.find(key); |
| 107 | if (itr != edge_map.end()) { |
| 108 | if (itr->second.size() != 1) { |
| 109 | throw RuntimeError("Duplicated edge detected"); |
| 110 | } |
| 111 | size_t j = itr->second[0]; |
| 112 | size_t label = std::min(m_values(i, 0), m_values(j, 0)); |
| 113 | m_values(i, 0) = label; |
| 114 | m_values(j, 0) = label; |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | } |
nothing calls this directly
no test coverage detected