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

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvng <viktor.govako@gmail.com>2011-05-29 18:33:44 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:18:17 +0300
commit9020980cfc4e9e427b69b49e0d40a1c5c2a7a13f (patch)
tree7a440fd65ad8d4d47a06d79b7e3e33619cb53f74 /generator/feature_merger.cpp
parentca58f00bebbc83d30d4454f158d4e280fd6e07b5 (diff)
Correct processing of closed linear features (highway's roundabouts) during merging.
Diffstat (limited to 'generator/feature_merger.cpp')
-rw-r--r--generator/feature_merger.cpp168
1 files changed, 121 insertions, 47 deletions
diff --git a/generator/feature_merger.cpp b/generator/feature_merger.cpp
index a7ea704234..beefb7cf2c 100644
--- a/generator/feature_merger.cpp
+++ b/generator/feature_merger.cpp
@@ -4,39 +4,52 @@
#include "../indexer/classificator.hpp"
-MergedFeatureBuilder1::MergedFeatureBuilder1(FeatureBuilder1 const & fb, bool isOK)
- : FeatureBuilder1(fb), m_isOK(isOK)
+MergedFeatureBuilder1::MergedFeatureBuilder1(FeatureBuilder1 const & fb)
+ : FeatureBuilder1(fb), m_isRound(false)
{
m_Params.FinishAddingTypes();
}
-void MergedFeatureBuilder1::AppendFeature(MergedFeatureBuilder1 const & fb, bool toBack)
+void MergedFeatureBuilder1::SetRound()
{
- if (fb.m_isOK)
- m_isOK = true;
+ m_isRound = true;
+ m_roundBounds[0] = m_roundBounds[1] = m_Geometry;
+}
+
+void MergedFeatureBuilder1::AppendFeature(MergedFeatureBuilder1 const & fb, bool fromBegin, bool toBack)
+{
+ if (fb.m_isRound)
+ {
+ if (toBack)
+ m_roundBounds[1] = fb.m_Geometry;
+ else
+ m_roundBounds[0] = fb.m_Geometry;
+ return;
+ }
- m2::PointD const pt = toBack ? LastPoint() : FirstPoint();
+ if (toBack)
+ m_roundBounds[1].clear();
+ else
+ m_roundBounds[0].clear();
- bool fromEnd = false;
- if ((pt.SquareLength(fb.FirstPoint()) > pt.SquareLength(fb.LastPoint())) == toBack)
- fromEnd = true;
+ m_isRound = false;
for (size_t i = 0; i < fb.m_Geometry.size(); ++i)
m_LimitRect.Add(fb.m_Geometry[i]);
- if (fromEnd)
+ if (fromBegin)
{
if (toBack)
- m_Geometry.insert(m_Geometry.end(), fb.m_Geometry.rbegin() + 1, fb.m_Geometry.rend());
+ m_Geometry.insert(m_Geometry.end(), fb.m_Geometry.begin() + 1, fb.m_Geometry.end());
else
- m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.rbegin(), fb.m_Geometry.rend() - 1);
+ m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.begin(), fb.m_Geometry.end() - 1);
}
else
{
if (toBack)
- m_Geometry.insert(m_Geometry.end(), fb.m_Geometry.begin() + 1, fb.m_Geometry.end());
+ m_Geometry.insert(m_Geometry.end(), fb.m_Geometry.rbegin() + 1, fb.m_Geometry.rend());
else
- m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.begin(), fb.m_Geometry.end() - 1);
+ m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.rbegin(), fb.m_Geometry.rend() - 1);
}
}
@@ -45,6 +58,36 @@ bool MergedFeatureBuilder1::EqualGeometry(MergedFeatureBuilder1 const & fb) cons
return (m_Geometry == fb.m_Geometry);
}
+pair<m2::PointD, bool> MergedFeatureBuilder1::GetKeyPoint(size_t i) const
+{
+ size_t sz = m_roundBounds[0].size();
+ if (i < sz) return make_pair(m_roundBounds[0][i], false);
+ i -= sz;
+
+ if (i == 0) return make_pair(FirstPoint(), false);
+
+ sz = m_roundBounds[1].size();
+ if (i < sz) return make_pair(m_roundBounds[1][i], true);
+
+ i -= sz;
+
+ ASSERT_EQUAL ( i, 1, () );
+ return make_pair(LastPoint(), true);
+}
+
+size_t MergedFeatureBuilder1::GetKeyPointsCount() const
+{
+ return m_roundBounds[0].size() + m_roundBounds[1].size() + 2;
+}
+
+double MergedFeatureBuilder1::GetPriority() const
+{
+ double pr = 0.0;
+ for (size_t i = 1; i < m_Geometry.size(); ++i)
+ pr += m_Geometry[i-1].SquareLength(m_Geometry[i]);
+ return pr;
+}
+
FeatureMergeProcessor::key_t FeatureMergeProcessor::get_key(m2::PointD const & p)
{
@@ -58,7 +101,7 @@ FeatureMergeProcessor::FeatureMergeProcessor(uint32_t coordBits)
void FeatureMergeProcessor::operator() (FeatureBuilder1 const & fb)
{
- this->operator() (new MergedFeatureBuilder1(fb, true));
+ this->operator() (new MergedFeatureBuilder1(fb));
}
void FeatureMergeProcessor::operator() (MergedFeatureBuilder1 * p)
@@ -69,16 +112,29 @@ void FeatureMergeProcessor::operator() (MergedFeatureBuilder1 * p)
m_map[k1].push_back(p);
if (k1 != k2)
m_map[k2].push_back(p);
+ else
+ {
+ ///@ todo Do it only for small round features!
+ p->SetRound();
+
+ p->ForEachMiddlePoints(bind(&FeatureMergeProcessor::Insert, this, _1, p));
+ }
+}
+
+void FeatureMergeProcessor::Insert(m2::PointD const & pt, MergedFeatureBuilder1 * p)
+{
+ m_map[get_key(pt)].push_back(p);
}
void FeatureMergeProcessor::Remove(key_t key, MergedFeatureBuilder1 const * p)
{
map_t::iterator i = m_map.find(key);
- CHECK(i != m_map.end(), ());
-
- vector_t & v = i->second;
- v.erase(remove(v.begin(), v.end(), p), v.end());
- if (v.empty()) m_map.erase(i);
+ if (i != m_map.end())
+ {
+ vector_t & v = i->second;
+ v.erase(remove(v.begin(), v.end(), p), v.end());
+ if (v.empty()) m_map.erase(i);
+ }
}
void FeatureMergeProcessor::Remove(MergedFeatureBuilder1 const * p)
@@ -89,6 +145,12 @@ void FeatureMergeProcessor::Remove(MergedFeatureBuilder1 const * p)
Remove(k1, p);
if (k1 != k2)
Remove(k2, p);
+ else
+ {
+ ASSERT ( p->IsRound(), () );
+
+ p->ForEachMiddlePoints(bind(&FeatureMergeProcessor::Remove1, this, _1, p));
+ }
}
void FeatureMergeProcessor::DoMerge(FeatureEmitterIFace & emitter)
@@ -113,53 +175,65 @@ void FeatureMergeProcessor::DoMerge(FeatureEmitterIFace & emitter)
MergedFeatureBuilder1 curr(*p);
curr.SetType(type);
- // Cycle while merging.
- while (true)
+ // Iterate through key points while merging.
+ size_t ind = 0;
+ while (ind < curr.GetKeyPointsCount()) // GetKeyPointsCount() can be different on each iteration
{
- bool isMerged = false;
-
- bool toBack = true;
- map_t::iterator it = m_map.find(get_key(curr.LastPoint()));
- if (it == m_map.end())
- {
- it = m_map.find(get_key(curr.FirstPoint()));
- toBack = false;
- }
+ pair<m2::PointD, bool> const pt = curr.GetKeyPoint(ind++);
+ map_t::const_iterator it = m_map.find(get_key(pt.first));
+ MergedFeatureBuilder1 * pp = 0;
if (it != m_map.end())
{
// Find best feature to continue.
+ double bestPr = -1.0;
for (size_t i = 0; i < it->second.size(); ++i)
{
- MergedFeatureBuilder1 * pp = it->second[i];
-
- if (pp->HasType(type))
+ MergedFeatureBuilder1 * pTest = it->second[i];
+ if (pTest->HasType(type))
{
- isMerged = true;
- curr.AppendFeature(*pp, toBack);
-
- if (pp->PopExactType(type))
+ double const pr = pTest->GetPriority();
+ ASSERT_GREATER ( pr, 0.0, () );
+ if (pr > bestPr)
{
- Remove(pp);
- delete pp;
+ pp = pTest;
+ bestPr = pr;
}
- break;
}
}
- }
- if (!isMerged)
- break;
+ // Merge current feature with best feature.
+ if (pp)
+ {
+ bool const toBack = pt.second;
+ bool fromBegin = true;
+ if ((pt.first.SquareLength(pp->FirstPoint()) > pt.first.SquareLength(pp->LastPoint())) == toBack)
+ fromBegin = false;
+
+ curr.AppendFeature(*pp, fromBegin, toBack);
+
+ if (pp->PopExactType(type))
+ {
+ Remove(pp);
+ delete pp;
+ }
+
+ // start from the beginning if we have a successful merge
+ ind = 0;
+ }
+ }
}
- // Push feature p to output.
if (m_last.NotEmpty() && m_last.EqualGeometry(curr))
+ {
+ // curr is equal with m_last by geometry - just add new type to m_last
m_last.AddType(type);
+ }
else
{
+ // emit m_last and set curr as last processed feature (m_last)
if (m_last.NotEmpty())
emitter(m_last);
-
m_last = curr;
}
@@ -204,7 +278,7 @@ void FeatureTypesProcessor::SetMappingTypes(char const * arr1[2], char const * a
MergedFeatureBuilder1 * FeatureTypesProcessor::operator() (FeatureBuilder1 const & fb)
{
- MergedFeatureBuilder1 * p = new MergedFeatureBuilder1(fb, true);
+ MergedFeatureBuilder1 * p = new MergedFeatureBuilder1(fb);
p->ForEachChangeTypes(do_change_types(*this));