Code for feature uniting is more generic now.

Define any types for unite processing in WorldMapGenerator.
This commit is contained in:
vng 2011-03-11 00:54:50 +02:00 committed by Alex Zolotarev
parent 7b9871b5a8
commit ee406ece0c
7 changed files with 87 additions and 41 deletions

View file

@ -68,6 +68,22 @@ void FeatureBuilder1::AddName(string const & name)
m_Name = name;
}
bool FeatureBuilder1::IsTypeExist(uint32_t t) const
{
return (find(m_Types.begin(), m_Types.end(), t) != m_Types.end());
}
bool FeatureBuilder1::AssignType_SetDifference(vector<uint32_t> const & diffTypes)
{
vector<uint32_t> src;
src.swap(m_Types);
sort(src.begin(), src.end());
set_difference(src.begin(), src.end(), diffTypes.begin(), diffTypes.end(), back_inserter(m_Types));
return !m_Types.empty();
}
void FeatureBuilder1::AddLayer(int32_t layer)
{
int const bound = 10;

View file

@ -20,9 +20,6 @@ class FeatureBase;
/// Used for serialization\deserialization of features during --generate_features.
class FeatureBuilder1
{
// needed for hacky coastlines merging
friend class FeatureBuilder1Merger;
public:
FeatureBuilder1();
@ -57,6 +54,9 @@ public:
m_Types.clear();
m_Types.push_back(type);
}
bool IsTypeExist(uint32_t t) const;
bool AssignType_SetDifference(vector<uint32_t> const & diffTypes);
void AddLayer(int32_t layer);

View file

@ -11,7 +11,7 @@ FeatureBuilder1Merger::FeatureBuilder1Merger(FeatureBuilder1 const & fb)
bool FeatureBuilder1Merger::ReachedMaxPointsCount() const
{
return m_Geometry.size() > MAX_MERGED_POINTS_COUNT;
return (m_Geometry.size() > MAX_MERGED_POINTS_COUNT);
}
void FeatureBuilder1Merger::AppendFeature(FeatureBuilder1Merger const & fb)

View file

@ -11,7 +11,12 @@ public:
/// but only if they have common point
void AppendFeature(FeatureBuilder1Merger const & fb);
vector<uint32_t> const & Type() const { return m_Types; }
uint32_t KeyType() const
{
ASSERT_EQUAL ( m_Types.size(), 1, () );
return m_Types.front();
}
bool ReachedMaxPointsCount() const;
m2::PointD FirstPoint() const { return m_Geometry.front(); }

View file

@ -50,7 +50,7 @@ public:
Init();
}
void operator () (feature_builder_t const & fb)
void operator () (feature_builder_t & fb)
{
if (m_worldMap(fb))
return; // we do not duplicate features in world and bucket files

View file

@ -87,7 +87,7 @@ namespace feature
}
};
void operator () (FeatureBuilder1 const & fb)
void operator () (FeatureBuilder1 & fb)
{
if (m_worldMap(fb))
return; // do not duplicate feature in any country if it's stored in world map

View file

@ -37,7 +37,7 @@ class WorldMapGenerator
size_t m_areasCounter;
typedef unordered_map<m2::PointD, FeatureBuilder1Merger> FeaturesContainerT;
typedef map<vector<uint32_t>, FeaturesContainerT> TypesContainerT;
typedef map<uint32_t, FeaturesContainerT> TypesContainerT;
TypesContainerT m_features;
private:
@ -54,8 +54,9 @@ private:
base->second.AppendFeature(found->second);
features.erase(found);
++m_mergedCounter;
if (base->second.FirstPoint() == base->second.LastPoint())
{ // @TODO create area feature
{
(*m_worldBucket)(base->second);
features.erase(base);
++m_areasCounter;
@ -66,10 +67,9 @@ private:
return false;
}
void TryToMerge(FeatureBuilder1 const & fb)
void TryToMerge(FeatureBuilder1Merger & fbm)
{
FeatureBuilder1Merger fbm(fb);
FeaturesContainerT & container = m_features[fbm.Type()];
FeaturesContainerT & container = m_features[fbm.KeyType()];
FeaturesContainerT::iterator found = container.find(fbm.LastPoint());
if (found != container.end())
{
@ -80,28 +80,31 @@ private:
if (fbm.FirstPoint() == fbm.LastPoint())
{
// @TODO create area feature
(*m_worldBucket)(fbm);
++m_areasCounter;
return;
}
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)
else
{
LOG(LWARNING, ("Found features with common first point, points counts are:",
result.first->second.GetPointsCount(), fb.GetPointsCount()));
(*m_worldBucket)(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) << ".";
}
};
//struct FeatureTypePrinter
//{
// void operator()(uint32_t type) const
// {
// cout << classif().GetFullObjectName(type) << ".";
// }
//};
vector<uint32_t> m_MergeTypes;
public:
WorldMapGenerator(int maxWorldScale, bool mergeCoastlines,
@ -111,6 +114,21 @@ public:
{
if (maxWorldScale >= 0)
m_worldBucket.reset(new FeatureOutT(WORLD_FILE_NAME, featureOutInitData));
// fill vector with types that need to be merged
char const * arrMerge[][2] = { {"natural", "coastline"} };
for (size_t i = 0; i < ARRAY_SIZE(arrMerge); ++i)
{
vector<string> path(2);
path[0] = arrMerge[i][0];
path[1] = arrMerge[i][1];
m_MergeTypes.push_back(classif().GetTypeByPath(path));
ASSERT_NOT_EQUAL ( m_MergeTypes.back(), ftype::GetEmptyValue(), () );
}
sort(m_MergeTypes.begin(), m_MergeTypes.end());
}
~WorldMapGenerator()
@ -119,6 +137,7 @@ public:
{
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)
{
@ -137,29 +156,35 @@ public:
}
}
bool operator()(FeatureBuilder1 const & fb)
bool operator()(FeatureBuilder1 & fb)
{
if (m_worldBucket)
{
FeatureBase fBase = fb.GetFeatureBase();
int minScale = feature::MinDrawableScaleForFeature(fBase);
int const minScale = feature::MinDrawableScaleForFeature(fBase);
CHECK_GREATER(minScale, -1, ("Non-drawable feature found!?"));
if (m_maxWorldScale >= minScale)
{
FeatureTypePrinter typePrinter;
fBase.ForEachTypeRef(typePrinter);
cout << endl;
if (m_mergeCoastlines)
//FeatureTypePrinter typePrinter;
//fBase.ForEachTypeRef(typePrinter);
//cout << endl;
if (m_mergeCoastlines && fBase.GetFeatureType() == FeatureBase::FEATURE_TYPE_LINE)
{
// we're merging only linear features,
// areas and points are written immediately
if (fBase.GetFeatureType() != FeatureBase::FEATURE_TYPE_LINE)
(*m_worldBucket)(fb);
else
TryToMerge(fb);
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);
}
}
if (!fb.AssignType_SetDifference(m_MergeTypes))
return true;
}
else
(*m_worldBucket)(fb);
(*m_worldBucket)(fb);
return true;
}
}