1#pragma once
2
3#include <vector>
4#include <boost/noncopyable.hpp>
5#include <common/Types.h>
6#include "GeodataProviders/IHierarchiesProvider.h"
7
8
9class IRegionsHierarchyDataProvider;
10
11/** A class that lets you know if a region belongs to one RegionID region with another RegionID.
12 * Information about the hierarchy of regions is downloaded from a text file.
13 * Can on request update the data.
14 */
15class RegionsHierarchy : private boost::noncopyable
16{
17private:
18 /// Relationship parent; 0, if there are no parents, the usual lookup table.
19 using RegionParents = std::vector<RegionID>;
20 /// type of region
21 using RegionTypes = std::vector<RegionType>;
22 /// depth in the tree, starting from the country (country: 1, root: 0)
23 using RegionDepths = std::vector<RegionDepth>;
24 /// population of the region. If more than 2 ^ 32 - 1, then it is equated to this maximum.
25 using RegionPopulations = std::vector<RegionPopulation>;
26
27 /// region -> parent region
28 RegionParents parents;
29 /// region -> city, including it or 0, if there is none
30 RegionParents city;
31 /// region -> country including it or 0, if there is none
32 RegionParents country;
33 /// region -> area that includes it or 0, if not
34 RegionParents area;
35 /// region -> district, including it or 0, if there is none
36 RegionParents district;
37 /// region -> the continent (the first when climbing in the hierarchy of regions), including it or 0, if there is none
38 RegionParents continent;
39 /// region -> the continent (the latter when you climb the hierarchy of regions), including it or 0, if there is none
40 RegionParents top_continent;
41
42 /// region -> population or 0, if unknown.
43 RegionPopulations populations;
44
45 /// region - depth in the tree
46 RegionDepths depths;
47
48 IRegionsHierarchyDataSourcePtr data_source;
49
50public:
51 RegionsHierarchy(IRegionsHierarchyDataSourcePtr data_source_);
52
53 /// Reloads, if necessary, the hierarchy of regions. Not threadsafe.
54 void reload();
55
56
57 bool in(RegionID lhs, RegionID rhs) const
58 {
59 if (lhs >= parents.size())
60 return false;
61
62 while (lhs != 0 && lhs != rhs)
63 lhs = parents[lhs];
64
65 return lhs != 0;
66 }
67
68 RegionID toCity(RegionID region) const
69 {
70 if (region >= city.size())
71 return 0;
72 return city[region];
73 }
74
75 RegionID toCountry(RegionID region) const
76 {
77 if (region >= country.size())
78 return 0;
79 return country[region];
80 }
81
82 RegionID toArea(RegionID region) const
83 {
84 if (region >= area.size())
85 return 0;
86 return area[region];
87 }
88
89 RegionID toDistrict(RegionID region) const
90 {
91 if (region >= district.size())
92 return 0;
93 return district[region];
94 }
95
96 RegionID toContinent(RegionID region) const
97 {
98 if (region >= continent.size())
99 return 0;
100 return continent[region];
101 }
102
103 RegionID toTopContinent(RegionID region) const
104 {
105 if (region >= top_continent.size())
106 return 0;
107 return top_continent[region];
108 }
109
110 RegionID toParent(RegionID region) const
111 {
112 if (region >= parents.size())
113 return 0;
114 return parents[region];
115 }
116
117 RegionDepth getDepth(RegionID region) const
118 {
119 if (region >= depths.size())
120 return 0;
121 return depths[region];
122 }
123
124 RegionPopulation getPopulation(RegionID region) const
125 {
126 if (region >= populations.size())
127 return 0;
128 return populations[region];
129 }
130};
131