connected_components.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2016 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #include <algorithm>
20 #include <unordered_set>
21 
22 #include "cartographer/mapping/proto/connected_components.pb.h"
23 #include "glog/logging.h"
24 
25 namespace cartographer {
26 namespace mapping {
27 
29  : lock_(), forest_(), connection_map_() {}
30 
31 void ConnectedComponents::Add(const int trajectory_id) {
32  common::MutexLocker locker(&lock_);
33  forest_.emplace(trajectory_id, trajectory_id);
34 }
35 
36 void ConnectedComponents::Connect(const int trajectory_id_a,
37  const int trajectory_id_b) {
38  common::MutexLocker locker(&lock_);
39  Union(trajectory_id_a, trajectory_id_b);
40  auto sorted_pair = std::minmax(trajectory_id_a, trajectory_id_b);
41  ++connection_map_[sorted_pair];
42 }
43 
44 void ConnectedComponents::Union(const int trajectory_id_a,
45  const int trajectory_id_b) {
46  forest_.emplace(trajectory_id_a, trajectory_id_a);
47  forest_.emplace(trajectory_id_b, trajectory_id_b);
48  const int representative_a = FindSet(trajectory_id_a);
49  const int representative_b = FindSet(trajectory_id_b);
50  forest_[representative_a] = representative_b;
51 }
52 
53 int ConnectedComponents::FindSet(const int trajectory_id) {
54  auto it = forest_.find(trajectory_id);
55  CHECK(it != forest_.end());
56  if (it->first != it->second) {
57  // Path compression for efficiency.
58  it->second = FindSet(it->second);
59  }
60  return it->second;
61 }
62 
63 bool ConnectedComponents::TransitivelyConnected(const int trajectory_id_a,
64  const int trajectory_id_b) {
65  if (trajectory_id_a == trajectory_id_b) {
66  return true;
67  }
68 
69  common::MutexLocker locker(&lock_);
70 
71  if (forest_.count(trajectory_id_a) == 0 ||
72  forest_.count(trajectory_id_b) == 0) {
73  return false;
74  }
75  return FindSet(trajectory_id_a) == FindSet(trajectory_id_b);
76 }
77 
78 std::vector<std::vector<int>> ConnectedComponents::Components() {
79  // Map from cluster exemplar -> growing cluster.
80  std::unordered_map<int, std::vector<int>> map;
81  common::MutexLocker locker(&lock_);
82  for (const auto& trajectory_id_entry : forest_) {
83  map[FindSet(trajectory_id_entry.first)].push_back(
84  trajectory_id_entry.first);
85  }
86 
87  std::vector<std::vector<int>> result;
88  result.reserve(map.size());
89  for (auto& pair : map) {
90  result.emplace_back(std::move(pair.second));
91  }
92  return result;
93 }
94 
95 std::vector<int> ConnectedComponents::GetComponent(const int trajectory_id) {
96  common::MutexLocker locker(&lock_);
97  const int set_id = FindSet(trajectory_id);
98  std::vector<int> trajectory_ids;
99  for (const auto& entry : forest_) {
100  if (FindSet(entry.first) == set_id) {
101  trajectory_ids.push_back(entry.first);
102  }
103  }
104  return trajectory_ids;
105 }
106 
107 int ConnectedComponents::ConnectionCount(const int trajectory_id_a,
108  const int trajectory_id_b) {
109  common::MutexLocker locker(&lock_);
110  const auto it =
111  connection_map_.find(std::minmax(trajectory_id_a, trajectory_id_b));
112  return it != connection_map_.end() ? it->second : 0;
113 }
114 
115 proto::ConnectedComponents ToProto(
116  std::vector<std::vector<int>> connected_components) {
117  proto::ConnectedComponents proto;
118  for (auto& connected_component : connected_components) {
119  std::sort(connected_component.begin(), connected_component.end());
120  }
121  std::sort(connected_components.begin(), connected_components.end());
122  for (const auto& connected_component : connected_components) {
123  auto* proto_connected_component = proto.add_connected_component();
124  for (const int trajectory_id : connected_component) {
125  proto_connected_component->add_trajectory_id(trajectory_id);
126  }
127  }
128  return proto;
129 }
130 
131 } // namespace mapping
132 } // namespace cartographer
bool TransitivelyConnected(int trajectory_id_a, int trajectory_id_b) EXCLUDES(lock_)
std::vector< int > GetComponent(int trajectory_id) EXCLUDES(lock_)
std::vector< std::vector< int > > Components() EXCLUDES(lock_)
int ConnectionCount(int trajectory_id_a, int trajectory_id_b) EXCLUDES(lock_)
int FindSet(int trajectory_id) REQUIRES(lock_)
void Connect(int trajectory_id_a, int trajectory_id_b) EXCLUDES(lock_)
void Add(int trajectory_id) EXCLUDES(lock_)
proto::MapLimits ToProto(const MapLimits &map_limits)
Definition: map_limits.h:92
void Union(int trajectory_id_a, int trajectory_id_b) REQUIRES(lock_)
Mutex::Locker MutexLocker
Definition: mutex.h:95


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58