Welcome to mirror list, hosted at ThFree Co, Russian Federation.

street_vicinity_loader.hpp « search - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3f3598054d3ab2f92da1a4290c5d21fd220e2ad5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#pragma once

#include "search/mwm_context.hpp"
#include "search/projection_on_street.hpp"
#include "search/stats_cache.hpp"

#include "indexer/feature.hpp"
#include "indexer/feature_algo.hpp"

#include "geometry/rect2d.hpp"

#include "base/macros.hpp"

#include "std/unordered_map.hpp"

namespace search
{
class MwmContext;

// This class is able to load features in a street's vicinity.
//
// NOTE: this class *IS NOT* thread-safe.
class StreetVicinityLoader
{
public:
  struct Street
  {
    Street() = default;
    Street(Street && street) = default;

    inline bool IsEmpty() const { return !m_calculator || m_rect.IsEmptyInterior(); }

    vector<uint32_t> m_features;
    m2::RectD m_rect;
    unique_ptr<ProjectionOnStreetCalculator> m_calculator;

    /// @todo Cache GetProjection results for features here, because
    /// feature::GetCenter and ProjectionOnStreetCalculator::GetProjection are not so fast.

    DISALLOW_COPY(Street);
  };

  StreetVicinityLoader(int scale, double offsetMeters);
  void SetContext(MwmContext * context);

  // Calls |fn| on each index in |sortedIds| where sortedIds[index]
  // belongs to the street's vicinity.
  template <typename TFn>
  void ForEachInVicinity(uint32_t streetId, vector<uint32_t> const & sortedIds, double offsetMeters,
                         TFn const & fn)
  {
    // Passed offset param should be less than the cached one, or the cache is invalid otherwise.
    ASSERT_LESS_OR_EQUAL(offsetMeters, m_offsetMeters, ());

    Street const & street = GetStreet(streetId);
    if (street.IsEmpty())
      return;

    ProjectionOnStreetCalculator const & calculator = *street.m_calculator;
    ProjectionOnStreet proj;
    for (uint32_t id : street.m_features)
    {
      // Load center and check projection only when |id| is in |sortedIds|.
      if (!binary_search(sortedIds.begin(), sortedIds.end(), id))
        continue;

      FeatureType ft;
      if (!m_context->GetFeature(id, ft))
        continue;  // Feature was deleted.

      if (calculator.GetProjection(feature::GetCenter(ft, FeatureType::WORST_GEOMETRY), proj) &&
          proj.m_distMeters <= offsetMeters)
      {
        fn(id);
      }
    }
  }

  void OnQueryFinished();

  Street const & GetStreet(uint32_t featureId);

private:
  void LoadStreet(uint32_t featureId, Street & street);

  MwmContext * m_context;
  int m_scale;
  double const m_offsetMeters;

  Cache<uint32_t, Street> m_cache;

  DISALLOW_COPY_AND_MOVE(StreetVicinityLoader);
};

}  // namespace search