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

towns_dumper.cpp « generator - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 87073f1cfdcb951afd2e1cbf4a23883fac8b0f5e (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
#include "towns_dumper.hpp"

#include "geometry/distance_on_sphere.hpp"
#include "geometry/tree4d.hpp"

#include "base/logging.hpp"

#include <fstream>
#include <limits>
#include <string>
#include <vector>

namespace
{
uint64_t constexpr kTownsEqualityMeters = 500000;
}  // namespace

TownsDumper::TownsDumper() {}
void TownsDumper::FilterTowns()
{
  LOG(LINFO, ("Preprocessing started. Have", m_records.size(), "towns."));
  m4::Tree<Town> resultTree;
  std::vector<Town> towns;
  towns.reserve(m_records.size());
  for (auto const & town : m_records)
  {
    if (town.capital)
      resultTree.Add(town);
    else
      towns.push_back(town);
  }
  sort(towns.begin(), towns.end());

  LOG(LINFO, ("Tree of capitals has size", resultTree.GetSize(), "towns has size:", towns.size()));
  m_records.clear();

  while (!towns.empty())
  {
    auto const & top = towns.back();
    bool isUniq = true;
    resultTree.ForEachInRect(
        MercatorBounds::RectByCenterXYAndSizeInMeters(MercatorBounds::FromLatLon(top.point),
                                                      kTownsEqualityMeters),
        [&top, &isUniq](Town const & candidate)
        {
          if (ms::DistanceOnEarth(top.point, candidate.point) < kTownsEqualityMeters)
            isUniq = false;
        });
    if (isUniq)
      resultTree.Add(top);
    towns.pop_back();
  }

  resultTree.ForEach([this](Town const & town)
                     {
                       m_records.push_back(town);
                     });
  LOG(LINFO, ("Preprocessing finished. Have", m_records.size(), "towns."));
}

void TownsDumper::CheckElement(OsmElement const & em)
{
  if (em.type != OsmElement::EntityType::Node)
    return;

  uint64_t population = 1;
  bool town = false;
  bool capital = false;
  int admin_level = std::numeric_limits<int>::max();
  for (auto const & tag : em.Tags())
  {
    std::string key(tag.key), value(tag.value);
    if (key == "population")
    {
      if (!strings::to_uint64(value, population))
        continue;
    }
    else if (key == "admin_level")
    {
      if (!strings::to_int(value, admin_level))
        continue;
    }
    else if (key == "capital" && value == "yes")
    {
      capital = true;
    }
    else if (key == "place" && (value == "city" || value == "town"))
    {
      town = true;
    }
  }

  // Ignore regional capitals.
  if (capital && admin_level > 2)
    capital = false;

  if (town || capital)
    m_records.emplace_back(em.lat, em.lon, em.id, capital, population);
}

void TownsDumper::Dump(std::string const & filePath)
{
  FilterTowns();
  ASSERT(!filePath.empty(), ());
  std::ofstream stream(filePath);
  stream.precision(9);
  for (auto const & record : m_records)
  {
    std::string const isCapital = record.capital ? "t" : "f";
    stream << record.point.lat << ";" << record.point.lon << ";" << record.id << ";" << isCapital <<  std::endl;
  }
}