Framework::GetVisiblePOI is working for symbols now.

This commit is contained in:
vng 2012-09-21 02:31:52 +03:00 committed by Alex Zolotarev
parent 94fa7d216c
commit d03e167bc0
15 changed files with 215 additions and 100 deletions

View file

@ -148,9 +148,22 @@ class FeatureType : public FeatureBase
{
typedef FeatureBase base_type;
/// @name This params define unique id for feature.
//@{
size_t m_mwmID;
uint32_t m_offset;
//@}
public:
void Deserialize(feature::LoaderBase * pLoader, BufferT buffer);
inline void SetID(size_t mwmID, uint32_t offset)
{
m_mwmID = mwmID;
m_offset = offset;
}
inline pair<size_t, uint32_t> GetID() const { return make_pair(m_mwmID, m_offset); }
/// @name Parse functions. Do simple dispatching to m_pLoader.
//@{
void ParseHeader2() const;

View file

@ -120,3 +120,15 @@ void Index::UpdateMwmInfo(MwmId id)
break;
}
}
Index::FeaturesLoaderGuard::FeaturesLoaderGuard(Index const & parent, MwmId id)
: m_lock(parent, id),
/// @note This guard is suitable when mwm is loaded
m_vector(m_lock.GetValue()->m_cont, m_lock.GetValue()->GetHeader())
{
}
void Index::FeaturesLoaderGuard::GetFeature(uint32_t offset, FeatureType & ft)
{
m_vector.Get(offset, ft);
}

View file

@ -77,6 +77,16 @@ public:
ForEachInIntervals(f, 2, m2::RectD::GetInfiniteRect(), scale);
}
/// Guard for loading features from particular MWM by demand.
class FeaturesLoaderGuard
{
MwmLock m_lock;
FeaturesVector m_vector;
public:
FeaturesLoaderGuard(Index const & parent, MwmId id);
void GetFeature(uint32_t offset, FeatureType & ft);
};
private:
template <typename F>
@ -85,16 +95,24 @@ private:
FeaturesVector const & m_V;
F & m_F;
unordered_set<uint32_t> & m_offsets;
MwmId m_mwmID;
public:
ReadFeatureFunctor(FeaturesVector const & v, F & f, unordered_set<uint32_t> & offsets)
: m_V(v), m_F(f), m_offsets(offsets) {}
ReadFeatureFunctor(FeaturesVector const & v, F & f,
unordered_set<uint32_t> & offsets, MwmId mwmID)
: m_V(v), m_F(f), m_offsets(offsets), m_mwmID(mwmID)
{
}
void operator() (uint32_t offset) const
{
if (m_offsets.insert(offset).second)
{
FeatureType feature;
m_V.Get(offset, feature);
feature.SetID(m_mwmID, offset);
m_F(feature);
}
}
@ -125,7 +143,7 @@ private:
// iterate through intervals
unordered_set<uint32_t> offsets;
ReadFeatureFunctor<F> f1(fv, f, offsets);
ReadFeatureFunctor<F> f1(fv, f, offsets, id);
for (size_t i = 0; i < interval.size(); ++i)
{
index.ForEachInIntervalAndScale(f1, interval[i].first, interval[i].second, scale);

View file

@ -425,6 +425,21 @@ namespace
};
}
namespace
{
/// Global instance for type checker.
/// @todo Possible need to add synhronization.
typedef DoGetAddressBase::TypeChecker CheckerT;
CheckerT * g_checker = 0;
CheckerT & GetChecker()
{
if (g_checker == 0)
g_checker = new CheckerT();
return *g_checker;
}
}
void Framework::GetAddressInfo(m2::PointD const & pt, AddressInfo & info) const
{
info.Clear();
@ -436,39 +451,59 @@ void Framework::GetAddressInfo(m2::PointD const & pt, AddressInfo & info) const
return;
}
int scale = scales::GetUpperScale();
int const scale = scales::GetUpperScale();
double addressR[] = {
15.0, // radius to search point POI's
100.0, // radius to search street names
5.0 // radius to search building numbers (POI's)
};
double const localityR = 20000.0; // radius to search localities
static DoGetAddressBase::TypeChecker checker;
// pass maximum value for all addressR
m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, addressR[1]);
DoGetAddressInfo getAddress(pt, scale, GetChecker(), addressR);
// first of all - get an address
m_model.ForEachFeature(rect, getAddress, scale);
getAddress.FillAddress(GetSearchEngine(), info);
GetLocality(pt, info);
}
void Framework::GetAddressInfo(FeatureType const & ft, m2::PointD const & pt, AddressInfo & info) const
{
info.Clear();
info.m_country = GetCountryName(pt);
if (info.m_country.empty())
{
// pass maximum value for all addressR
m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, addressR[1]);
DoGetAddressInfo getAddress(pt, scale, checker, addressR);
m_model.ForEachFeature(rect, getAddress, scale);
getAddress.FillAddress(GetSearchEngine(), info);
LOG(LINFO, ("Can't find region for point ", pt));
return;
}
// now - get the locality
{
scale = checker.GetLocalitySearchScale();
LOG(LDEBUG, ("Locality scale = ", scale));
double const inf = numeric_limits<double>::max();
double addressR[] = { inf, inf, inf };
m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, localityR);
DoGetLocality getLocality(pt, scale, checker, rect);
DoGetAddressInfo getAddress(pt, scales::GetUpperScale(), GetChecker(), addressR);
getAddress(ft);
getAddress.FillAddress(GetSearchEngine(), info);
m_model.ForEachFeature(rect, getLocality, scale);
GetLocality(pt, info);
}
getLocality.FillLocality(info, *this);
}
void Framework::GetLocality(m2::PointD const & pt, AddressInfo & info) const
{
CheckerT & checker = GetChecker();
int const scale = checker.GetLocalitySearchScale();
LOG(LDEBUG, ("Locality scale = ", scale));
// radius to search localities
m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, 20000.0);
DoGetLocality getLocality(pt, scale, checker, rect);
m_model.ForEachFeature(rect, getLocality, scale);
getLocality.FillLocality(info, *this);
}
string Framework::AddressInfo::FormatAddress() const

View file

@ -279,8 +279,11 @@ namespace fwork
else
m_hasNonCoast = true;
if (GetDrawer()->screen()->renderState())
GetDrawer()->screen()->renderState()->m_isEmptyModelCurrent = IsEmptyDrawing();
{
yg::gl::RenderState * pState = GetDrawer()->screen()->renderState().get();
if (pState)
pState->m_isEmptyModelCurrent = IsEmptyDrawing();
}
// remove duplicating identical drawing keys
PreProcessKeys(keys);
@ -324,7 +327,7 @@ namespace fwork
intName.clear();
}
shared_ptr<di::DrawInfo> ptr(new di::DrawInfo(
scoped_ptr<di::DrawInfo> ptr(new di::DrawInfo(
defaultName,
intName,
f.GetRoadNumber(),
@ -415,7 +418,7 @@ namespace fwork
}
if (isExist)
pDrawer->Draw(ptr.get(), rules.data(), count);
pDrawer->Draw(ptr.get(), rules.data(), count, f.GetID());
return true;
}

View file

@ -109,12 +109,14 @@ void DrawerYG::onSize(int w, int h)
m_pScreen->onSize(w, h);
}
void DrawerYG::drawSymbol(m2::PointD const & pt, string const & symbolName, yg::EPosition pos, int depth)
void DrawerYG::drawSymbol(m2::PointD const & pt, string const & symbolName,
yg::EPosition pos, int depth)
{
m_pScreen->drawSymbol(pt, symbolName.c_str(), pos, depth);
m_pScreen->drawSymbol(pt, symbolName, pos, depth);
}
void DrawerYG::drawCircle(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth)
void DrawerYG::drawCircle(m2::PointD const & pt, rule_ptr_t pRule,
yg::EPosition pos, int depth, FeatureID const & id)
{
yg::CircleInfo ci;
ConvertStyle(pRule->GetCircle(), m_visualScale, ci);
@ -122,12 +124,21 @@ void DrawerYG::drawCircle(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition
m_pScreen->drawCircle(pt, ci, pos, depth);
}
void DrawerYG::drawSymbol(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth)
void DrawerYG::drawSymbol(m2::PointD const & pt, rule_ptr_t pRule,
yg::EPosition pos, int depth, FeatureID const & id)
{
string name;
ConvertStyle(pRule->GetSymbol(), name);
m_pScreen->drawSymbol(pt, name, pos, depth);
yg::SymbolElement::Params params;
params.m_depth = depth;
params.m_position = pos;
params.m_pivot = pt;
params.m_symbolName.swap(name);
params.m_userInfo.m_mwmID = id.first;
params.m_userInfo.m_offset = id.second;
m_pScreen->drawSymbol(params);
}
void DrawerYG::drawPath(di::PathInfo const & info, di::DrawRule const * rules, size_t count)
@ -206,7 +217,8 @@ bool DrawerYG::filter_text_size(rule_ptr_t pRule) const
}
}
void DrawerYG::drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ptr_t pRule, yg::EPosition pos, int depth)
void DrawerYG::drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ptr_t pRule,
yg::EPosition pos, int depth, FeatureID const & id)
{
yg::FontDesc font;
ConvertStyle(pRule->GetCaption(0), m_visualScale, font);
@ -279,7 +291,8 @@ void DrawerYG::SetScale(int level)
m_level = level;
}
void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size_t count)
void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size_t count,
FeatureID const & id)
{
buffer_vector<di::DrawRule, 8> pathRules;
@ -306,8 +319,6 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size
}
}
bool isNumber = true;
for (size_t i = 0; i < count; ++i)
{
rule_ptr_t pRule = rules[i].m_rule;
@ -319,6 +330,8 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size
if (!isCaption)
{
double const sm = 2.0 * m_visualScale;
// draw area
if (isArea)
{
@ -330,7 +343,7 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size
if (isFill)
drawArea(i->m_path, pRule, depth);
else if (hasSym)
drawSymbol(i->GetCenter() + m2::PointD(0, 2 * m_visualScale), pRule, yg::EPosUnder, depth);
drawSymbol(i->GetCenter() + m2::PointD(0.0, sm), pRule, yg::EPosUnder, depth, id);
}
}
@ -338,9 +351,9 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size
if (!isPath && !isArea && ((pRule->GetType() & drule::node) != 0))
{
if (hasSymbol)
drawSymbol(pInfo->m_point + m2::PointD(0, 2 * m_visualScale), pRule, yg::EPosUnder, depth);
if (isCircle)
drawCircle(pInfo->m_point + m2::PointD(0, 2 * m_visualScale), pRule, yg::EPosUnder, depth);
drawSymbol(pInfo->m_point + m2::PointD(0.0, sm), pRule, yg::EPosUnder, depth, id);
else if (isCircle)
drawCircle(pInfo->m_point + m2::PointD(0.0, sm), pRule, yg::EPosUnder, depth, id);
}
}
else
@ -353,7 +366,7 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size
if (isArea/* && isN*/)
{
for (list<di::AreaInfo>::const_iterator i = pInfo->m_areas.begin(); i != pInfo->m_areas.end(); ++i)
drawText(i->GetCenter(), pInfo, pRule, yg::EPosAbove, depth);
drawText(i->GetCenter(), pInfo, pRule, yg::EPosAbove, depth, id);
}
// draw way name
@ -366,13 +379,13 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size
// draw point text
isN = ((pRule->GetType() & drule::node) != 0);
if (!isPath && !isArea && isN)
drawText(pInfo->m_point, pInfo, pRule, yg::EPosAbove, depth);
drawText(pInfo->m_point, pInfo, pRule, yg::EPosAbove, depth, id);
}
}
}
// draw road numbers
if (isNumber && isPath && !pInfo->m_road.empty() && m_level >= 12)
if (isPath && !pInfo->m_road.empty() && m_level >= 12)
{
for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
drawPathNumber(*i, pInfo);

View file

@ -78,13 +78,18 @@ class DrawerYG
static void ClearSkinPage(size_t threadID, uint8_t pipelineID);
typedef pair<size_t, uint32_t> FeatureID;
protected:
void drawSymbol(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth);
void drawCircle(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth);
void drawSymbol(m2::PointD const & pt, rule_ptr_t pRule,
yg::EPosition pos, int depth, FeatureID const & id);
void drawCircle(m2::PointD const & pt, rule_ptr_t pRule,
yg::EPosition pos, int depth, FeatureID const & id);
void drawPath(di::PathInfo const & info, di::DrawRule const * rules, size_t count);
void drawArea(vector<m2::PointD> const & pts, rule_ptr_t pRule, int depth);
void drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ptr_t pRule, yg::EPosition pos, int depth);
void drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ptr_t pRule,
yg::EPosition pos, int depth, FeatureID const & id);
bool drawPathText(di::PathInfo const & info, di::DrawInfo const * pInfo, rule_ptr_t pRule, int depth);
void drawPathNumber(di::PathInfo const & path, di::DrawInfo const * pInfo);
@ -116,7 +121,9 @@ public:
double VisualScale() const;
void SetScale(int level);
void Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size_t count);
void Draw(di::DrawInfo const * pInfo,
di::DrawRule const * rules, size_t count,
FeatureID const & id);
bool filter_text_size(rule_ptr_t pRule) const;
uint8_t get_text_font_size(rule_ptr_t pRule) const;

View file

@ -26,9 +26,7 @@ namespace model
private:
m2::RectD m_rect;
typedef Index index_t;
index_t m_multiIndex;
Index m_multiIndex;
public:
void InitClassificator();
@ -75,7 +73,7 @@ namespace model
}
//@}
index_t const & GetIndex() const { return m_multiIndex; }
Index const & GetIndex() const { return m_multiIndex; }
m2::RectD GetWorldRect() const;
};
}

View file

@ -1264,8 +1264,7 @@ shared_ptr<yg::OverlayElement> const GetClosestToPivot(list<shared_ptr<yg::Overl
it != l.end();
++it)
{
double curDist = pxPoint.SquareLength((*it)->pivot());
double const curDist = pxPoint.SquareLength((*it)->pivot());
if (curDist < dist)
{
dist = curDist;
@ -1276,42 +1275,47 @@ shared_ptr<yg::OverlayElement> const GetClosestToPivot(list<shared_ptr<yg::Overl
return res;
}
bool Framework::GetVisiblePOI(m2::PointD const & pxPoint,
m2::PointD & pv,
AddressInfo & info)
bool Framework::GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, AddressInfo & info) const
{
m2::PointD pt = GetNavigator().ShiftPoint(pxPoint);
if (!m_renderPolicy)
{
LOG(LINFO, ("GetVisiblePOI called without valid renderPolicy!"));
return false;
}
shared_ptr<yg::Overlay> overlay = m_renderPolicy->GetOverlay();
m2::PointD const pt = m_navigator.ShiftPoint(pxPoint);
double const halfSize = 12 * m_renderPolicy->VisualScale();
double halfSize = 12 * m_renderPolicy->VisualScale();
list<shared_ptr<yg::OverlayElement> > candidates;
typedef yg::OverlayElement ElementT;
list<shared_ptr<ElementT> > candidates;
m2::RectD rect(pt.x - halfSize, pt.y - halfSize,
pt.x + halfSize, pt.y + halfSize);
m_renderPolicy->GetOverlay()->selectOverlayElements(rect, candidates);
overlay->selectOverlayElements(rect, candidates);
shared_ptr<yg::OverlayElement> res;
res = GetClosestToPivot(candidates, pt);
shared_ptr<ElementT> res = GetClosestToPivot(candidates, pt);
if (res)
{
/// TODO : get featureID associated with res.
/// Obtain AddressInfo by this featureID.
ElementT::UserInfo const & ui = res->userInfo();
if (ui.IsValid())
{
Index::FeaturesLoaderGuard guard(m_model.GetIndex(), ui.m_mwmID);
return true;
FeatureType ft;
guard.GetFeature(ui.m_offset, ft);
/// @todo Get correct center point for feature.
m2::PointD const center = (ft.GetFeatureType() == feature::GEOM_POINT ?
ft.GetCenter() : PtoG(pxPoint));
GetAddressInfo(ft, center, info);
pxPivot = GtoP(center);
return true;
}
}
else
return false;
return false;
}
Navigator & Framework::GetNavigator()

View file

@ -292,9 +292,12 @@ public:
/// @param[in] pt Point in mercator coordinates.
void GetAddressInfo(m2::PointD const & pt, AddressInfo & info) const;
bool GetVisiblePOI(m2::PointD const & pxPoint,
m2::PointD & pv,
AddressInfo & info);
private:
void GetAddressInfo(FeatureType const & ft, m2::PointD const & pt, AddressInfo & info) const;
void GetLocality(m2::PointD const & pt, AddressInfo & info) const;
public:
bool GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, AddressInfo & info) const;
virtual void BeginPaint(shared_ptr<PaintEvent> const & e);
/// Function for calling from platform dependent-paint function.

View file

@ -343,17 +343,25 @@ namespace qt
QPoint const & pt = e->pos();
QMenu menu;
vector<string> types;
m_framework->GetFeatureTypes(m2::PointD(pt.x(), pt.y()), types);
Framework::AddressInfo info;
m2::PointD dummy;
if (m_framework->GetVisiblePOI(m2::PointD(pt.x(), pt.y()), dummy, info))
{
add_string(menu, "POI");
}
else
{
vector<string> types;
m_framework->GetFeatureTypes(m2::PointD(pt.x(), pt.y()), types);
for (size_t i = 0; i < types.size(); ++i)
add_string(menu, types[i]);
for (size_t i = 0; i < types.size(); ++i)
add_string(menu, types[i]);
m_framework->GetAddressInfo(m_framework->PtoG(m2::PointD(pt.x(), pt.y())), info);
}
(void)menu.addSeparator();
Framework::AddressInfo info;
m_framework->GetAddressInfo(m_framework->PtoG(m2::PointD(pt.x(), pt.y())), info);
if (!info.m_name.empty())
add_string(menu, info.m_name);
add_string(menu, info.FormatAddress());

View file

@ -10,11 +10,6 @@ namespace yg
: m_pivot(), m_position(yg::EPosAboveRight), m_depth(yg::maxDepth)
{}
OverlayElement::UserInfo::UserInfo()
: m_featureID0(0),
m_featureID1(0)
{}
OverlayElement::OverlayElement(Params const & p)
: m_pivot(p.m_pivot),
m_position(p.m_position),

View file

@ -19,9 +19,11 @@ namespace yg
struct UserInfo
{
uint32_t m_featureID0;
uint32_t m_featureID1;
UserInfo();
size_t m_mwmID;
uint32_t m_offset;
UserInfo() : m_mwmID(size_t(-1)) {}
inline bool IsValid() const { return (m_mwmID != size_t(-1)); }
};
private:

View file

@ -29,19 +29,11 @@ namespace yg
{
}
void OverlayRenderer::drawSymbol(m2::PointD const & pt,
string const & symbolName,
EPosition pos,
int depth)
void OverlayRenderer::drawSymbol(SymbolElement::Params & params)
{
if (!m_drawSymbols)
return;
SymbolElement::Params params;
params.m_depth = depth;
params.m_position = pos;
params.m_pivot = pt;
params.m_symbolName = symbolName;
params.m_skin = skin().get();
shared_ptr<OverlayElement> oe(new SymbolElement(params));
@ -54,6 +46,17 @@ namespace yg
m_overlay->processOverlayElement(oe);
}
void OverlayRenderer::drawSymbol(m2::PointD const & pt, string const & symbolName, EPosition pos, int depth)
{
yg::SymbolElement::Params params;
params.m_depth = depth;
params.m_position = pos;
params.m_pivot = pt;
params.m_symbolName = symbolName;
drawSymbol(params);
}
void OverlayRenderer::drawCircle(m2::PointD const & pt,
yg::CircleInfo const & ci,
EPosition pos,

View file

@ -33,6 +33,7 @@ namespace yg
OverlayRenderer(Params const & p);
/// Drawing POI symbol
void drawSymbol(SymbolElement::Params & params);
void drawSymbol(m2::PointD const & pt, string const & symbolName, EPosition pos, int depth);
/// Drawing circle