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

world_map_generator.hpp « generator - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 27ad626acd9d270dd6324faada7705c7f85cd981 (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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#pragma once

#include "feature_merger.hpp"

#include "../defines.hpp"

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

#include "../indexer/classificator.hpp"
#include "../indexer/feature.hpp"
#include "../indexer/feature_visibility.hpp"
#include "../indexer/point_to_int64.hpp"

#include "../std/map.hpp"
#include "../std/vector.hpp"
#include "../std/iostream.hpp"
#include "../std/scoped_ptr.hpp"
#include "../std/unordered_map.hpp"


namespace m2
{
  inline size_t hash_value(m2::PointD const & pt)
  {
    return static_cast<size_t>(PointToInt64(pt.x, pt.y));
  }
}

template <class FeatureOutT>
class WorldMapGenerator
{
  /// if NULL, separate world data file is not generated
  scoped_ptr<FeatureOutT> m_worldBucket;
  /// features visible before or at this scale level will go to World map
  int m_maxWorldScale;
  bool m_mergeCoastlines;

  size_t m_mergedCounter;
  size_t m_areasCounter;

  typedef unordered_map<m2::PointD, FeatureBuilder1Merger> FeaturesContainerT;
  typedef map<uint32_t, FeaturesContainerT> TypesContainerT;
  TypesContainerT m_features;

private:
  bool EmitAreaFeature(FeatureBuilder1Merger & fbm)
  {
    if (fbm.FirstPoint() == fbm.LastPoint())
    {
      fbm.SetAreaSafe();
      (*m_worldBucket)(fbm);
      ++m_areasCounter;
      return true;
    }
    else return false;
  }

  /// scans all features and tries to merge them with each other
  /// @return true if one feature was merged
  bool ReMergeFeatures(FeaturesContainerT & features)
  {
    for (FeaturesContainerT::iterator base = features.begin(); base != features.end(); ++base)
    {
      FeaturesContainerT::iterator found = features.find(base->second.LastPoint());
      if (found != features.end())
      {
        CHECK(found != base, ());
        base->second.AppendFeature(found->second);
        features.erase(found);
        ++m_mergedCounter;

        if (EmitAreaFeature(base->second))
          features.erase(base);
        return true;
      }
    }
    return false;
  }

  void TryToMerge(FeatureBuilder1Merger & fbm)
  {
    FeaturesContainerT & container = m_features[fbm.KeyType()];
    FeaturesContainerT::iterator found = container.find(fbm.LastPoint());
    if (found != container.end())
    {
      fbm.AppendFeature(found->second);
      container.erase(found);
      ++m_mergedCounter;
    }

    if (!EmitAreaFeature(fbm))
    {
      pair<FeaturesContainerT::iterator, bool> result = container.insert(make_pair(fbm.FirstPoint(), fbm));
      // if we found feature with the same starting point, emit it directly
      if (!result.second)
      {
        LOG(LWARNING, ("Found features with common first point, points counts are:",
                       result.first->second.GetPointsCount(), fbm.GetPointsCount()));
        (*m_worldBucket)(fbm);
      }
    }
  }

  //struct FeatureTypePrinter
  //{
  //  void operator()(uint32_t type) const
  //  {
  //    cout << classif().GetFullObjectName(type) << ".";
  //  }
  //};

  vector<uint32_t> m_MergeTypes;

public:
  WorldMapGenerator(int maxWorldScale, bool mergeCoastlines,
                    typename FeatureOutT::InitDataType featureOutInitData)
  : m_maxWorldScale(maxWorldScale), m_mergeCoastlines(mergeCoastlines),
    m_mergedCounter(0), m_areasCounter(0)
  {
    if (maxWorldScale >= 0)
      m_worldBucket.reset(new FeatureOutT(WORLD_FILE_NAME, featureOutInitData));

    // fill vector with types that need to be merged
    static size_t const MAX_TYPES_IN_PATH = 3;
    char const * arrMerge[][MAX_TYPES_IN_PATH] = {
      {"natural", "coastline", ""},
      {"boundary", "administrative", "2"}
    };

    for (size_t i = 0; i < ARRAY_SIZE(arrMerge); ++i)
    {
      vector<string> path;
      for (size_t j = 0; j < MAX_TYPES_IN_PATH; ++j)
      {
        string const strType(arrMerge[i][j]);
        if (!strType.empty())
          path.push_back(strType);
      }
      m_MergeTypes.push_back(classif().GetTypeByPath(path));

      ASSERT_NOT_EQUAL ( m_MergeTypes.back(), ftype::GetEmptyValue(), () );
    }

    sort(m_MergeTypes.begin(), m_MergeTypes.end());
  }

  ~WorldMapGenerator()
  {
    if (m_mergeCoastlines)
    {
      LOG(LINFO, ("Final merging of coastlines started"));
    }

    // try to merge all merged features with each other
    for (TypesContainerT::iterator it = m_features.begin(); it != m_features.end(); ++it)
    {
      LOG(LINFO, (it->second.size()));
      while (ReMergeFeatures(it->second))
      {}
      // emit all merged features
      for (FeaturesContainerT::iterator itF = it->second.begin(); itF != it->second.end(); ++itF)
        (*m_worldBucket)(itF->second);
    }

    if (m_mergeCoastlines)
    {
      LOG(LINFO, ("Final merging of coastlines ended"));
      LOG(LINFO, ("Merged features:", m_mergedCounter, "new areas created:", m_areasCounter));
    }
  }

  void operator()(FeatureBuilder1 const & fb)
  {
    if (m_worldBucket)
    {
      FeatureBase fBase = fb.GetFeatureBase();
      int const minScale = feature::MinDrawableScaleForFeature(fBase);
      CHECK_GREATER(minScale, -1, ("Non-drawable feature found!?"));

      if (m_maxWorldScale >= minScale)
      {
        if (m_mergeCoastlines && fBase.GetFeatureType() == FeatureBase::FEATURE_TYPE_LINE)
        {
          for (size_t i = 0; i < m_MergeTypes.size(); ++i)
          {
            if (fb.IsTypeExist(m_MergeTypes[i]))
            {
              FeatureBuilder1Merger fbm(fb);
              fbm.SetType(m_MergeTypes[i]);
              TryToMerge(fbm);
            }
          }
        }

        FeatureBuilder1 fbm(fb);
        if (fbm.AssignType_SetDifference(m_MergeTypes))
            (*m_worldBucket)(fbm);
      }
    }
  }
};