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

feature_bucketer.hpp « indexer_tool « indexer - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 34de0e8d801ab2e6b58283a18e1cf42c8557c3f1 (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#pragma once

#include "world_map_generator.hpp"

#include "../../base/base.hpp"

#include "../../coding/file_writer.hpp"

#include "../../geometry/rect2d.hpp"

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

#include "../../std/string.hpp"

namespace feature
{

// Groups features in buckets according to their coordinates.
template <class FeatureOutT, class FeatureClipperT, class BoundsT, typename CellIdT>
class CellFeatureBucketer
{
  typedef typename FeatureClipperT::feature_builder_t feature_builder_t;

  void Init()
  {
    uint32_t const size = 1 << 2 * m_Level;
    m_Buckets.resize(size);
    for (uint32_t i = 0; i < m_Buckets.size(); ++i)
    {
      CellIdT cell = CellIdT::FromBitsAndLevel(i, m_Level);
      double minX, minY, maxX, maxY;
      CellIdConverter<BoundsT, CellIdT>::GetCellBounds(cell, minX, minY, maxX, maxY);
      m_Buckets[i].m_Rect = m2::RectD(minX, minY, maxX, maxY);
    }
  }

public:
  template <class TInfo>
  explicit CellFeatureBucketer(TInfo & info)
  : m_Level(info.cellBucketingLevel), m_FeatureOutInitData(info.datFilePrefix, info.datFileSuffix),
    m_worldMap(info.maxScaleForWorldFeatures, info.mergeCoastlines, m_FeatureOutInitData)
  {
    Init();
  }

  /// @note this constructor doesn't support world file generation
  CellFeatureBucketer(int level, typename FeatureOutT::InitDataType const & initData)
    : m_Level(level), m_FeatureOutInitData(initData), m_worldMap(-1, false, initData)
  {
    Init();
  }

  void operator () (feature_builder_t & fb)
  {
    m_worldMap(fb);

    FeatureClipperT clipper(fb);
    // TODO: Is feature fully inside GetLimitRect()?
    m2::RectD const limitRect = fb.GetLimitRect();
    for (uint32_t i = 0; i < m_Buckets.size(); ++i)
    {
      // First quick and dirty limit rect intersection.
      // Clipper may (or may not) do a better intersection.
      if (m_Buckets[i].m_Rect.IsIntersect(limitRect))
      {
        feature_builder_t clippedFb;
        if (clipper(m_Buckets[i].m_Rect, clippedFb))
        {
          if (!m_Buckets[i].m_pOut)
            m_Buckets[i].m_pOut = new FeatureOutT(BucketName(i), m_FeatureOutInitData);

          (*(m_Buckets[i].m_pOut))(clippedFb);
        }
      }
    }
  }

  template <typename F> void GetBucketNames(F f) const
  {
    for (uint32_t i = 0; i < m_Buckets.size(); ++i)
      if (m_Buckets[i].m_pOut)
        f(BucketName(i));
  }

private:
  inline string BucketName(uint32_t i) const
  {
    return CellIdT::FromBitsAndLevel(i, m_Level).ToString();
  }

  struct Bucket
  {
    Bucket() : m_pOut(NULL) {}
    ~Bucket() { delete m_pOut; }

    FeatureOutT * m_pOut;
    m2::RectD m_Rect;
  };

  int m_Level;
  typename FeatureOutT::InitDataType m_FeatureOutInitData;
  vector<Bucket> m_Buckets;
  WorldMapGenerator<FeatureOutT> m_worldMap;
};

class SimpleFeatureClipper
{
public:
  typedef FeatureBuilder1 feature_builder_t;

private:
  feature_builder_t const & m_Feature;

public:
  explicit SimpleFeatureClipper(feature_builder_t const & f) : m_Feature(f)
  {
  }

  bool operator () (m2::RectD const & /*rect*/, feature_builder_t & clippedF) const
  {
    clippedF = m_Feature;
    return true;
  }
};

}