forked from organicmaps/organicmaps
[generator:regions] Add administrative place
This commit is contained in:
parent
3ce5c0a6fa
commit
63e08118fa
6 changed files with 129 additions and 64 deletions
|
@ -50,12 +50,12 @@ std::string MakeCollectorData()
|
|||
CollectorRegionInfo collector(filename);
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(1 /* id */, "2" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(2 /* id */, "2" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(3 /* id */, "4" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(4 /* id */, "4" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(5 /* id */, "4" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(6 /* id */, "6" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(7 /* id */, "6" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(8 /* id */, "4" /* adminLevel */));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(3 /* id */, "4" /* adminLevel */, "state"));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(4 /* id */, "4" /* adminLevel */, "state"));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(5 /* id */, "4" /* adminLevel */, "state"));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(6 /* id */, "6" /* adminLevel */, "district"));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(7 /* id */, "6" /* adminLevel */, "district"));
|
||||
collector.CollectFeature(kEmptyFeature, CreateOsmRelation(8 /* id */, "4" /* adminLevel */, "state"));
|
||||
collector.Save();
|
||||
return filename;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,17 @@ uint8_t const CollectorRegionInfo::kVersion = 0;
|
|||
PlaceType EncodePlaceType(std::string const & place)
|
||||
{
|
||||
static std::map<std::string, PlaceType> const m = {
|
||||
{"country", PlaceType::Country},
|
||||
{"state", PlaceType::State},
|
||||
{"province", PlaceType::Province},
|
||||
{"district", PlaceType::District},
|
||||
{"county", PlaceType::County},
|
||||
{"municipality", PlaceType::Municipality},
|
||||
{"city", PlaceType::City},
|
||||
{"town", PlaceType::Town},
|
||||
{"village", PlaceType::Village},
|
||||
{"suburb", PlaceType::Suburb},
|
||||
{"quarter", PlaceType::Quarter},
|
||||
{"neighbourhood", PlaceType::Neighbourhood},
|
||||
{"hamlet", PlaceType::Hamlet},
|
||||
{"isolated_dwelling", PlaceType::IsolatedDwelling}
|
||||
|
|
|
@ -26,7 +26,6 @@ namespace regions
|
|||
enum class AdminLevel : uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
One = 1,
|
||||
Two = 2,
|
||||
Three = 3,
|
||||
Four = 4,
|
||||
|
@ -44,13 +43,20 @@ enum class AdminLevel : uint8_t
|
|||
enum class PlaceType: uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
City = 9,
|
||||
Town = 10,
|
||||
Village = 11,
|
||||
Hamlet = 12,
|
||||
Suburb = 13,
|
||||
Neighbourhood = 14,
|
||||
IsolatedDwelling = 15,
|
||||
Country = 1,
|
||||
State = 2,
|
||||
Province = 3,
|
||||
District = 4,
|
||||
County = 5,
|
||||
Municipality = 6,
|
||||
City = 7,
|
||||
Town = 8,
|
||||
Village = 9,
|
||||
Hamlet = 10,
|
||||
Suburb = 11,
|
||||
Quarter = 12,
|
||||
Neighbourhood = 13,
|
||||
IsolatedDwelling = 14,
|
||||
};
|
||||
|
||||
PlaceType EncodePlaceType(std::string const & place);
|
||||
|
|
|
@ -72,10 +72,12 @@ double Region::GetRadiusByPlaceType(PlaceType place)
|
|||
return 0.0067;
|
||||
case PlaceType::Suburb:
|
||||
return 0.016;
|
||||
case PlaceType::Quarter:
|
||||
case PlaceType::Neighbourhood:
|
||||
case PlaceType::IsolatedDwelling:
|
||||
return 0.0035;
|
||||
case PlaceType::Unknown:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -105,10 +105,12 @@ Node::Ptr RegionsBuilder::BuildCountryRegionTree(Region const & outer,
|
|||
for (; itCurr != std::rend(nodes); ++itCurr)
|
||||
{
|
||||
auto const & currRegion = (*itCurr)->GetData();
|
||||
if (currRegion.Contains(firstRegion) ||
|
||||
(GetWeight(firstRegion) < GetWeight(currRegion) &&
|
||||
currRegion.Contains(firstRegion.GetCenter()) &&
|
||||
currRegion.CalculateOverlapPercentage(firstRegion) > 50.0))
|
||||
|
||||
if (!currRegion.ContainsRect(firstRegion) && !currRegion.Contains(firstRegion.GetCenter()))
|
||||
continue;
|
||||
|
||||
auto const c = Compare(currRegion, firstRegion);
|
||||
if (c == 1)
|
||||
{
|
||||
(*itFirstNode)->SetParent(*itCurr);
|
||||
(*itCurr)->AddChild(*itFirstNode);
|
||||
|
@ -122,6 +124,81 @@ Node::Ptr RegionsBuilder::BuildCountryRegionTree(Region const & outer,
|
|||
return nodes.front();
|
||||
}
|
||||
|
||||
// static
|
||||
int RegionsBuilder::Compare(LevelRegion const & l, LevelRegion const & r)
|
||||
{
|
||||
if (IsAreaLess(r, l) && l.Contains(r))
|
||||
return 1;
|
||||
if (IsAreaLess(l, r) && r.Contains(l))
|
||||
return -1;
|
||||
|
||||
if (l.CalculateOverlapPercentage(r) < 50.0)
|
||||
return 0;
|
||||
|
||||
auto const lArea = l.GetArea();
|
||||
auto const rArea = r.GetArea();
|
||||
if (0.5 * lArea >= rArea)
|
||||
{
|
||||
LOG(LDEBUG, ("Region", l.GetId(), GetRegionNotation(l), "contains partly",
|
||||
r.GetId(), GetRegionNotation(r)));
|
||||
return 1;
|
||||
}
|
||||
if (0.5 * rArea >= lArea)
|
||||
{
|
||||
LOG(LDEBUG, ("Region", r.GetId(), GetRegionNotation(r), "contains partly",
|
||||
l.GetId(), GetRegionNotation(l)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return RelateByWeight(l, r);
|
||||
}
|
||||
|
||||
// static
|
||||
bool RegionsBuilder::IsAreaLess(Region const & l, Region const & r)
|
||||
{
|
||||
constexpr auto lAreaRation = 1. + kAreaRelativeErrorPercent / 100.;
|
||||
return lAreaRation * l.GetArea() < r.GetArea();
|
||||
}
|
||||
|
||||
// static
|
||||
int RegionsBuilder::RelateByWeight(LevelRegion const & l, LevelRegion const & r)
|
||||
{
|
||||
if (l.GetLevel() != PlaceLevel::Unknown && r.GetLevel() != PlaceLevel::Unknown)
|
||||
{
|
||||
if (l.GetLevel() > r.GetLevel())
|
||||
return -1;
|
||||
if (l.GetLevel() < r.GetLevel())
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto const lPlaceType = l.GetPlaceType();
|
||||
auto const rPlaceType = r.GetPlaceType();
|
||||
if (lPlaceType != PlaceType::Unknown && rPlaceType != PlaceType::Unknown)
|
||||
{
|
||||
if (lPlaceType > rPlaceType)
|
||||
return -1;
|
||||
if (lPlaceType < rPlaceType)
|
||||
return 1;
|
||||
// Check by admin level (administrative city (district + city) > city).
|
||||
}
|
||||
|
||||
auto const lAdminLevel = l.GetAdminLevel();
|
||||
auto const rAdminLevel = r.GetAdminLevel();
|
||||
if (lAdminLevel != AdminLevel::Unknown && rAdminLevel != AdminLevel::Unknown)
|
||||
{
|
||||
if (lAdminLevel > rAdminLevel)
|
||||
return -1;
|
||||
if (lAdminLevel < rAdminLevel)
|
||||
return 1;
|
||||
}
|
||||
if (lAdminLevel != AdminLevel::Unknown)
|
||||
return 1;
|
||||
if (rAdminLevel != AdminLevel::Unknown)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RegionsBuilder::ForEachCountry(CountryFn fn)
|
||||
{
|
||||
for (auto const & countryName : GetCountryNames())
|
||||
|
@ -160,67 +237,35 @@ PlaceLevel RegionsBuilder::GetLevel(Region const & region)
|
|||
{
|
||||
switch (region.GetPlaceType())
|
||||
{
|
||||
case PlaceType::Country:
|
||||
return PlaceLevel::Country;
|
||||
case PlaceType::State:
|
||||
case PlaceType::Province:
|
||||
return PlaceLevel::Region;
|
||||
case PlaceType::District:
|
||||
case PlaceType::County:
|
||||
case PlaceType::Municipality:
|
||||
return PlaceLevel::Subregion;
|
||||
case PlaceType::City:
|
||||
case PlaceType::Town:
|
||||
case PlaceType::Village:
|
||||
case PlaceType::Hamlet:
|
||||
return PlaceLevel::Locality;
|
||||
case PlaceType::Suburb:
|
||||
case PlaceType::Neighbourhood:
|
||||
return PlaceLevel::Suburb;
|
||||
case PlaceType::Quarter:
|
||||
case PlaceType::Neighbourhood:
|
||||
return PlaceLevel::Sublocality;
|
||||
case PlaceType::IsolatedDwelling:
|
||||
return PlaceLevel::Sublocality;
|
||||
case PlaceType::Unknown:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (region.GetAdminLevel())
|
||||
{
|
||||
case AdminLevel::Two:
|
||||
if (region.GetAdminLevel() == AdminLevel::Two)
|
||||
return PlaceLevel::Country;
|
||||
case AdminLevel::Four:
|
||||
return PlaceLevel::Region;
|
||||
case AdminLevel::Six:
|
||||
return PlaceLevel::Subregion;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return PlaceLevel::Unknown;
|
||||
}
|
||||
|
||||
// static
|
||||
size_t RegionsBuilder::GetWeight(Region const & region)
|
||||
{
|
||||
switch (region.GetPlaceType())
|
||||
{
|
||||
case PlaceType::City:
|
||||
case PlaceType::Town:
|
||||
case PlaceType::Village:
|
||||
case PlaceType::Hamlet:
|
||||
return 3;
|
||||
case PlaceType::Suburb:
|
||||
case PlaceType::Neighbourhood:
|
||||
return 2;
|
||||
case PlaceType::IsolatedDwelling:
|
||||
return 1;
|
||||
case PlaceType::Unknown:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (region.GetAdminLevel())
|
||||
{
|
||||
case AdminLevel::Two:
|
||||
return 6;
|
||||
case AdminLevel::Four:
|
||||
return 5;
|
||||
case AdminLevel::Six:
|
||||
return 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace regions
|
||||
} // namespace generator
|
||||
|
|
|
@ -30,15 +30,20 @@ public:
|
|||
void ForEachCountry(CountryFn fn);
|
||||
|
||||
static PlaceLevel GetLevel(Region const & region);
|
||||
static size_t GetWeight(Region const & region);
|
||||
|
||||
private:
|
||||
static constexpr double kAreaRelativeErrorPercent = 0.1;
|
||||
|
||||
Regions FormRegionsInAreaOrder(Regions && regions);
|
||||
Regions ExtractCountriesOuters(Regions & regions);
|
||||
Node::PtrList BuildCountryRegionTrees(Regions const & outers);
|
||||
static Node::Ptr BuildCountryRegionTree(Region const & outer, Regions const & allRegions);
|
||||
static Node::PtrList MakeSelectedRegionsByCountry(Region const & outer,
|
||||
Regions const & allRegions);
|
||||
// Return: 0 - no relation, 1 - |l| contains |r|, -1 - |r| contains |l|.
|
||||
static int Compare(LevelRegion const & l, LevelRegion const & r);
|
||||
static bool IsAreaLess(Region const & l, Region const & r);
|
||||
static int RelateByWeight(LevelRegion const & l, LevelRegion const & r);
|
||||
|
||||
Regions m_countriesOuters;
|
||||
Regions m_regionsInAreaOrder;
|
||||
|
|
Loading…
Add table
Reference in a new issue