added separate Ruler class.

This commit is contained in:
rachytski 2011-09-14 18:57:03 +03:00 committed by Alex Zolotarev
parent ba950b9fb6
commit 97a982f984
9 changed files with 326 additions and 110 deletions

View file

@ -83,7 +83,12 @@ Framework<TModel>::Framework(shared_ptr<WindowHandle> windowHandle,
size_t bottomShift)
: m_windowHandle(windowHandle),
m_metresMinWidth(20),
m_metresMaxWidth(1000000),
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_WINDOWS) || defined(OMIM_OS_LINUX)
m_minRulerWidth(97),
#else
m_minRulerWidth(48),
#endif
m_centeringMode(EDoNothing),
m_tileSize(GetPlatform().TileSize())
{
@ -105,7 +110,7 @@ Framework<TModel>::Framework(shared_ptr<WindowHandle> windowHandle,
m_informationDisplay.enableCenter(true);
m_informationDisplay.enableRuler(true);
m_informationDisplay.setRulerParams(m_minRulerWidth, m_metresMinWidth);
m_informationDisplay.setRulerParams(m_minRulerWidth, m_metresMinWidth, m_metresMaxWidth);
m_navigator.SetMinScreenParams(m_minRulerWidth, m_metresMinWidth);
#ifdef DEBUG

View file

@ -107,6 +107,7 @@ protected:
InformationDisplay m_informationDisplay;
double const m_metresMinWidth;
double const m_metresMaxWidth;
int const m_minRulerWidth;
enum TGpsCenteringMode

View file

@ -20,6 +20,7 @@
#include "../std/iomanip.hpp"
InformationDisplay::InformationDisplay()
: m_ruler(Ruler::Params())
{
enableDebugPoints(false);
enableRuler(false);
@ -40,6 +41,7 @@ InformationDisplay::InformationDisplay()
void InformationDisplay::setScreen(ScreenBase const & screen)
{
m_screen = screen;
m_ruler.setScreen(screen);
}
void InformationDisplay::setBottomShift(double bottomShift)
@ -77,116 +79,33 @@ void InformationDisplay::enableRuler(bool doEnable)
m_isRulerEnabled = doEnable;
}
void InformationDisplay::setRulerParams(unsigned pxMinWidth, double metresMinWidth)
void InformationDisplay::setRulerParams(unsigned pxMinWidth, double metresMinWidth, double metresMaxWidth)
{
m_pxMinWidth = pxMinWidth;
m_metresMinWidth = metresMinWidth;
m_ruler.setMinPxWidth(pxMinWidth);
m_ruler.setMinUnitsWidth(metresMinWidth);
m_ruler.setMaxUnitsWidth(metresMaxWidth);
}
void InformationDisplay::drawRuler(DrawerYG * pDrawer)
{
/// Compute Scaler
/// scaler should be between minPixSize and maxPixSize
int minPixSize = m_pxMinWidth;
m_ruler.setFontDesc(m_fontDesc);
m_ruler.setVisualScale(m_visualScale);
m2::PointD const scalerOrg =
m2::PointD(m_displayRect.minX(), m_displayRect.maxY() - m_bottomShift * m_visualScale)
+ m2::PointD(10 * m_visualScale, -10 * m_visualScale);
#ifdef OMIM_OS_IPHONE
m2::PointD pivot(m2::PointD(m_displayRect.maxX(), m_displayRect.maxY() - m_bottomShift * m_visualScale)
+ m2::PointD(-10 * m_visualScale, -10 * m_visualScale));
m_ruler.setPosition(yg::EPosAboveLeft);
#else
m2::PointD pivot(m2::PointD(m_displayRect.minX(), m_displayRect.maxY() - m_bottomShift * m_visualScale)
+ m2::PointD(10 * m_visualScale, -10 * m_visualScale));
m2::PointD pt0 = m_screen.PtoG(scalerOrg);
m2::PointD pt1 = m_screen.PtoG(m_screen.GtoP(pt0) + m2::PointD(minPixSize, 0));
m_ruler.setPosition(yg::EPosAboveRight);
#endif
m_ruler.setPivot(pivot);
m_ruler.update();
double const lonDiffCorrection = cos(MercatorBounds::YToLat(pt0.y) / 180.0 * math::pi);
double lonDiff = fabs(MercatorBounds::XToLon(pt1.x) - MercatorBounds::XToLon(pt0.x));
double metresDiff = lonDiff / MercatorBounds::degreeInMetres * lonDiffCorrection;
/// finding the closest higher metric value
unsigned curFirstDigit = 2;
unsigned curVal = static_cast<unsigned>(m_metresMinWidth);
unsigned maxVal = 1000000;
bool lessThanMin = false;
bool isInfinity = false;
if (metresDiff > maxVal)
{
isInfinity = true;
curVal = maxVal;
}
else
if (metresDiff < curVal)
lessThanMin = true;
else
while (true)
{
unsigned nextVal = curFirstDigit == 2 ? (curVal * 5 / 2) : curVal * 2;
unsigned nextFirstDigit = curFirstDigit == 2 ? (curFirstDigit * 5 / 2) : curFirstDigit * 2;
if (nextFirstDigit >= 10)
nextFirstDigit /= 10;
if ((curVal <= metresDiff) && (nextVal > metresDiff))
{
curVal = nextVal;
curFirstDigit = nextFirstDigit;
break;
}
curVal = nextVal;
curFirstDigit = nextFirstDigit;
}
/// translating meters to pixels
double scalerWidthLatDiff = (double)curVal * MercatorBounds::degreeInMetres / lonDiffCorrection;
double scalerWidthXDiff = MercatorBounds::LonToX(pt0.x + scalerWidthLatDiff) - MercatorBounds::LonToX(pt0.x);
double scalerWidthInPx = m_screen.GtoP(pt0).x - m_screen.GtoP(pt0 + m2::PointD(scalerWidthXDiff, 0)).x;
scalerWidthInPx = (lessThanMin || isInfinity) ? minPixSize : abs(my::rounds(scalerWidthInPx));
string scalerText;
if (isInfinity)
scalerText = ">";
else
if (lessThanMin)
scalerText = "<";
if (curVal >= 1000)
scalerText += strings::to_string(curVal / 1000) + " km";
else
scalerText += strings::to_string(curVal) + " m";
m2::PointD scalerPts[4];
scalerPts[0] = scalerOrg + m2::PointD(0, -14 * m_visualScale);
scalerPts[1] = scalerOrg;
scalerPts[2] = scalerOrg + m2::PointD(scalerWidthInPx, 0);
scalerPts[3] = scalerPts[2] + m2::PointD(0, -14 * m_visualScale);
pDrawer->screen()->drawPath(
scalerPts, 4, 0,
pDrawer->screen()->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0)),
yg::maxDepth);
// m2::RectD textRect = pDrawer->screen()->textRect(fontDesc, scalerText.c_str(), false);
pDrawer->screen()->drawText(m_fontDesc,
scalerPts[1] + m2::PointD(7, -7),
yg::EPosAboveRight,
scalerText.c_str(),
yg::maxDepth,
false);
/* m2::PointD minPixPath[4];
minPixPath[0] = scalerOrg + m2::PointD(0, -14);
minPixPath[1] = scalerOrg;
minPixPath[2] = scalerOrg + m2::PointD(minPixSize, 0);
minPixPath[3] = minPixPath[2] + m2::PointD(0, -14);
pDrawer->screen()->drawPath(
minPixPath, 4, 0,
pDrawer->screen()->skin()->mapPenInfo(yg::PenInfo(yg::Color(255, 0, 0, 255), 4, 0, 0, 0)),
yg::maxDepth);
*/
m_ruler.draw(pDrawer->screen().get(), math::Identity<double, 3>());
// pDrawer->screen()->drawRectangle(m2::Inflate(m2::RectD(pivot, pivot), 2.0, 2.0), yg::Color(0, 0, 0, 255), yg::maxDepth);
}
void InformationDisplay::setVisualScale(double visualScale)
@ -215,11 +134,19 @@ void InformationDisplay::drawCenter(DrawerYG * drawer)
<< fixed << setprecision(4) << setw(8) << m_centerPtLonLat.x << ")";
yg::StraightTextElement::Params params;
params.m_depth = yg::maxDepth;
params.m_fontDesc = m_fontDesc;
params.m_log2vis = false;
#ifdef OMIM_OS_IPHONE
params.m_pivot = m2::PointD(m_displayRect.maxX() - 10 * m_visualScale,
m_displayRect.maxY() - (m_bottomShift + 10) * m_visualScale - 5);
m_displayRect.maxY() - 20 * m_visualScale - 5);
#else
params.m_pivot = m2::PointD(m_displayRect.maxX() - 10 * m_visualScale,
m_displayRect.maxY() - (/*m_bottomShift*/ + 14) * m_visualScale - 5);
#endif
params.m_position = yg::EPosAboveLeft;
params.m_glyphCache = drawer->screen()->glyphCache();
params.m_logText = strings::MakeUniString(out.str());

View file

@ -1,6 +1,7 @@
#pragma once
#include "window_handle.hpp"
#include "ruler.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/rect2d.hpp"
#include "../geometry/screenbase.hpp"
@ -33,9 +34,7 @@ private:
m2::PointD m_DebugPts[10];
bool m_isRulerEnabled;
m2::PointD m_basePoint;
unsigned m_pxMinWidth;
double m_metresMinWidth;
Ruler m_ruler;
bool m_isCenterEnabled;
m2::PointD m_centerPtLonLat;
@ -87,7 +86,7 @@ public:
void enableRuler(bool doEnable);
void drawRuler(DrawerYG * pDrawer);
void setRulerParams(unsigned pxMinWidth, double metresMinWidth);
void setRulerParams(unsigned pxMinWidth, double metresMinWidth, double metresMaxWidth);
void enableCenter(bool doEnable);
void setCenter(m2::PointD const & latLongPt);

View file

@ -38,7 +38,8 @@ HEADERS += \
render_policy_mt.hpp \
render_queue.hpp \
render_queue_routine.hpp \
benchmark_render_policy_mt.hpp
benchmark_render_policy_mt.hpp \
ruler.hpp \
SOURCES += \
feature_vec_model.cpp \
@ -66,7 +67,8 @@ SOURCES += \
render_policy_mt.cpp \
render_queue_routine.cpp \
render_queue.cpp \
benchmark_render_policy_mt.cpp
benchmark_render_policy_mt.cpp \
ruler.cpp \
!iphone*:!bada*:!android* {
HEADERS += qgl_render_context.hpp
@ -75,3 +77,5 @@ SOURCES += \
}

208
map/ruler.cpp Normal file
View file

@ -0,0 +1,208 @@
#include "../base/SRC_FIRST.hpp"
#include "ruler.hpp"
#include "../yg/overlay_renderer.hpp"
#include "../yg/skin.hpp"
#include "../indexer/mercator.hpp"
#include "../base/logging.hpp"
#include "../base/string_utils.hpp"
Ruler::Ruler(Params const & p)
: base_t(p)
{}
void Ruler::setScreen(ScreenBase const & screen)
{
m_screen = screen;
}
ScreenBase const & Ruler::screen() const
{
return m_screen;
}
void Ruler::setMinPxWidth(unsigned minPxWidth)
{
m_minPxWidth = minPxWidth;
}
void Ruler::setMinUnitsWidth(double minUnitsWidth)
{
m_minUnitsWidth = minUnitsWidth;
}
void Ruler::setMaxUnitsWidth(double maxUnitsWidth)
{
m_maxUnitsWidth = maxUnitsWidth;
}
void Ruler::setVisualScale(double visualScale)
{
m_visualScale = visualScale;
}
void Ruler::setFontDesc(yg::FontDesc const & fontDesc)
{
m_fontDesc = fontDesc;
}
unsigned Ruler::ceil(double unitsDiff)
{
/// finding the closest higher metric value
unsigned curVal = (unsigned)m_minUnitsWidth;
unsigned curFirstDigit = m_minUnitsWidth;
while (curFirstDigit > 10)
curFirstDigit /= 10;
if (unitsDiff > m_maxUnitsWidth)
curVal = m_maxUnitsWidth + 1;
else
if (unitsDiff < m_minUnitsWidth)
curVal = m_minUnitsWidth - 1;
else
while (true)
{
unsigned nextVal = curFirstDigit == 2 ? (curVal * 5 / 2) : curVal * 2;
unsigned nextFirstDigit = curFirstDigit == 2 ? (curFirstDigit * 5 / 2) : curFirstDigit * 2;
if (nextFirstDigit >= 10)
nextFirstDigit /= 10;
if ((curVal <= unitsDiff) && (nextVal > unitsDiff))
{
curVal = nextVal;
curFirstDigit = nextFirstDigit;
break;
}
curVal = nextVal;
curFirstDigit = nextFirstDigit;
}
return curVal;
}
void Ruler::update()
{
m2::PointD glbPivot = m_screen.PtoG(pivot());
int rulerHeight = 14 * m_visualScale;
unsigned minPxWidth = m_minPxWidth * m_visualScale;
m2::PointD pt0 = m_screen.PtoG(pivot() - m2::PointD(minPxWidth / 2, 0));
m2::PointD pt1 = m_screen.PtoG(pivot() + m2::PointD(minPxWidth / 2, 0));
/// correction factor, calculated from Y-coordinate.
double const lonDiffCorrection = cos(MercatorBounds::YToLat(glbPivot.y) / 180.0 * math::pi);
/// longitude difference between two points
double lonDiff = fabs(MercatorBounds::XToLon(pt0.x) - MercatorBounds::XToLon(pt1.x));
/// converting into metres
/// TODO : calculate in different units
m_unitsDiff = lonDiff / MercatorBounds::degreeInMetres * lonDiffCorrection;
m_unitsDiff = ceil(m_unitsDiff);
/// updating scaler text
bool higherThanMax = m_unitsDiff > m_maxUnitsWidth;
bool lessThanMin = m_unitsDiff < m_minUnitsWidth;
m_scalerText = "";
if (higherThanMax)
{
m_scalerText = ">";
m_unitsDiff = m_maxUnitsWidth;
}
else
if (lessThanMin)
{
m_scalerText = "<";
m_unitsDiff = m_minUnitsWidth;
}
if (m_unitsDiff >= 1000)
m_scalerText += strings::to_string(m_unitsDiff / 1000) + " km";
else
m_scalerText += strings::to_string(m_unitsDiff) + " m";
/// translating units into pixels
double scalerWidthLatDiff = (double)m_unitsDiff * MercatorBounds::degreeInMetres / lonDiffCorrection;
double scalerWidthXDiff = MercatorBounds::LonToX(glbPivot.x + scalerWidthLatDiff / 2)
- MercatorBounds::LonToX(glbPivot.x - scalerWidthLatDiff / 2);
double scalerWidthInPx = m_screen.GtoP(glbPivot).x - m_screen.GtoP(glbPivot + m2::PointD(scalerWidthXDiff, 0)).x;
scalerWidthInPx = (higherThanMax || lessThanMin) ? minPxWidth : abs(my::rounds(scalerWidthInPx));
m2::PointD scalerOrg = pivot() + m2::PointD(-scalerWidthInPx / 2, rulerHeight / 2);
if (position() & yg::EPosLeft)
scalerOrg.x -= scalerWidthInPx / 2;
if (position() & yg::EPosRight)
scalerOrg.x += scalerWidthInPx / 2;
if (position() & yg::EPosAbove)
scalerOrg.y -= rulerHeight / 2;
if (position() & yg::EPosUnder)
scalerOrg.y += rulerHeight / 2;
m_path.clear();
m_path.push_back(scalerOrg + m2::PointD(0, -rulerHeight));
m_path.push_back(scalerOrg);
m_path.push_back(scalerOrg + m2::PointD(scalerWidthInPx, 0));
m_path.push_back(m_path[2] + m2::PointD(0, -rulerHeight));
/// calculating bound rect
m_boundRect = m2::RectD(m_path[0], m_path[0]);
m_boundRect.Add(m_path[1]);
m_boundRect.Add(m_path[2]);
m_boundRect.Add(m_path[3]);
}
m2::AARectD const Ruler::boundRect() const
{
return m2::AARectD(m_boundRect);
}
void Ruler::draw(yg::gl::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const
{
s->drawPath(
&m_path[0], m_path.size(), 0,
s->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0)),
depth());
if (position() & yg::EPosLeft)
s->drawText(m_fontDesc,
m_path[2] + m2::PointD(-7, -7),
yg::EPosAboveLeft,
m_scalerText.c_str(),
depth(),
false);
else
if (position() & yg::EPosRight)
s->drawText(m_fontDesc,
m_path[1] + m2::PointD(7, -7),
yg::EPosAboveRight,
m_scalerText.c_str(),
depth(),
false);
else
s->drawText(m_fontDesc,
(m_path[1] + m_path[2]) * 0.5 + m2::PointD(0, -7),
yg::EPosAbove,
m_scalerText.c_str(),
depth(),
false);
}
void Ruler::cache(yg::StylesCache * stylesCache)
{
}

67
map/ruler.hpp Normal file
View file

@ -0,0 +1,67 @@
#pragma once
#include "../geometry/screenbase.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/aa_rect2d.hpp"
#include "../yg/overlay_element.hpp"
#include "../yg/font_desc.hpp"
namespace yg
{
class StylesCache;
namespace gl
{
class Screen;
class OverlayRenderer;
}
}
class Ruler : public yg::OverlayElement
{
private:
unsigned m_minPxWidth;
unsigned m_maxPxWidth;
double m_minUnitsWidth;
double m_maxUnitsWidth;
double m_visualScale;
yg::FontDesc m_fontDesc;
ScreenBase m_screen;
float m_unitsDiff; //< current diff in units between two endpoints of the ruler.
string m_scalerText;
vector<m2::PointD> m_path;
m2::RectD m_boundRect;
unsigned ceil(double unitsDiff);
typedef OverlayElement base_t;
public:
void update(); //< update internal params after some other params changed.
struct Params : public base_t::Params
{
};
Ruler(Params const & p);
void setScreen(ScreenBase const & screen);
ScreenBase const & screen() const;
void setMinPxWidth(unsigned minPxWidth);
void setMinUnitsWidth(double minUnitsWidth);
void setMaxUnitsWidth(double maxUnitsWidth);
void setVisualScale(double visualScale);
void setFontDesc(yg::FontDesc const & fontDesc);
m2::AARectD const boundRect() const;
void draw(yg::gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
void cache(yg::StylesCache * stylesCache);
};

View file

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

View file

@ -34,6 +34,7 @@ namespace yg
m2::PointD m_pivot;
yg::EPosition m_position;
double m_depth;
Params();
};
OverlayElement(Params const & p);