TracksManager TracksManager::MergeTracksManager()

in opensfm/src/map/src/tracks_manager.cc [356:420]


TracksManager TracksManager::MergeTracksManager(
    const std::vector<const TracksManager*>& tracks_managers) {
  // Some typedefs claryfying the aggregations
  using FeatureId = std::pair<ShotId, int>;
  using SingleTrackId = std::pair<TrackId, int>;

  // Union-find main data
  std::vector<std::unique_ptr<UnionFindElement<SingleTrackId>>>
      union_find_elements;

  // Aggregate tracks be merged using (shot_id, feature_id)
  std::unordered_map<FeatureId, std::vector<int>, HashPair>
      observations_per_feature_id;
  for (int i = 0; i < tracks_managers.size(); ++i) {
    const auto& manager = tracks_managers[i];
    for (const auto& track_obses : manager->shots_per_track_) {
      const auto element_id = union_find_elements.size();
      for (const auto& shot_obs : track_obses.second) {
        observations_per_feature_id[std::make_pair(shot_obs.first,
                                                   shot_obs.second.feature_id)]
            .push_back(element_id);
      }
      union_find_elements.emplace_back(
          std::unique_ptr<UnionFindElement<SingleTrackId>>(
              new UnionFindElement<SingleTrackId>(
                  std::make_pair(track_obses.first, i))));
    }
  }

  TracksManager merged;
  if (union_find_elements.empty()) {
    return merged;
  }

  // Union-find any two tracks sharing a common FeatureId
  // For N tracks, make 0 the parent of [1, ... N-1[
  for (const auto& tracks_agg : observations_per_feature_id) {
    if (tracks_agg.second.empty()) {
      continue;
    }
    const auto e1 = union_find_elements[tracks_agg.second[0]].get();
    for (int i = 1; i < tracks_agg.second.size(); ++i) {
      const auto e2 = union_find_elements[tracks_agg.second[i]].get();
      Union(e1, e2);
    }
  }

  // Get clusters and construct new tracks
  const auto clusters = GetUnionFindClusters(&union_find_elements);
  for (int i = 0; i < clusters.size(); ++i) {
    const auto& tracks_agg = clusters[i];
    const auto merged_track_id = std::to_string(i);
    // Run over tracks to merged into a new single track
    for (const auto& manager_n_track_id : tracks_agg) {
      const auto manager_id = manager_n_track_id->data.second;
      const auto track_id = manager_n_track_id->data.first;
      const auto track =
          tracks_managers[manager_id]->shots_per_track_.at(track_id);
      for (const auto& shot_obs : track) {
        merged.AddObservation(shot_obs.first, merged_track_id, shot_obs.second);
      }
    }
  }
  return merged;
}