Merge pull request #3734 from darina/smooth-perspective

Smooth perspective
This commit is contained in:
Roman Kuznetsov 2016-07-08 18:21:29 +03:00 committed by GitHub
commit 55857f993f
45 changed files with 809 additions and 937 deletions

View file

@ -19,7 +19,6 @@ public:
MapLinear,
MapScale,
MapFollow,
MapPerspective,
Arrow,
KineticScroll
};
@ -35,28 +34,7 @@ public:
{
Position,
Scale,
Angle,
AnglePerspective,
SwitchPerspective
};
struct SwitchPerspectiveParams
{
SwitchPerspectiveParams() = default;
SwitchPerspectiveParams(bool enable,
double startAngle, double endAngle,
double angleFOV)
: m_enable(enable)
, m_startAngle(startAngle)
, m_endAngle(endAngle)
, m_angleFOV(angleFOV)
{}
bool m_enable = false;
double m_startAngle = 0.0;
double m_endAngle = 0.0;
double m_angleFOV = 0.0;
Angle
};
struct PropertyValue
@ -64,8 +42,7 @@ public:
enum Type
{
ValueD,
ValuePointD,
ValuePerspectiveParams
ValuePointD
};
PropertyValue()
@ -81,18 +58,11 @@ public:
, m_valuePointD(value)
{}
explicit PropertyValue(SwitchPerspectiveParams const & params)
: m_type(ValuePerspectiveParams)
{
m_valuePerspectiveParams = params;
}
Type m_type;
union
{
m2::PointD m_valuePointD;
double m_valueD;
SwitchPerspectiveParams m_valuePerspectiveParams;
};
};

View file

@ -1,28 +1,31 @@
#include "follow_animation.hpp"
#include "animation_constants.hpp"
#include "animation_system.hpp"
#include "base/assert.hpp"
#include "base/logging.hpp"
namespace df
{
MapFollowAnimation::MapFollowAnimation(m2::PointD const & globalPosition,
double startScale, double endScale,
double startAngle, double endAngle,
m2::PointD const & startPixelPosition,
MapFollowAnimation::MapFollowAnimation(ScreenBase const & screen,
m2::PointD const & globalUserPosition,
m2::PointD const & endPixelPosition,
m2::RectD const & pixelRect)
double startScale, double endScale,
double startAngle, double endAngle)
: Animation(true /* couldBeInterrupted */, true /* couldBeBlended */)
, m_scaleInterpolator(startScale, endScale)
, m_pixelPosInterpolator(startPixelPosition, endPixelPosition, pixelRect)
, m_angleInterpolator(startAngle, endAngle)
, m_globalPosition(globalPosition)
, m_globalPosition(globalUserPosition)
, m_endPixelPosition(endPixelPosition)
{
double const duration = CalculateDuration();
m_scaleInterpolator.SetMinDuration(duration);
m_angleInterpolator.SetMinDuration(duration);
m_pixelPosInterpolator.SetMinDuration(duration);
m_offset = screen.PtoG(screen.P3dtoP(m_endPixelPosition)) - m_globalPosition;
m_offsetInterpolator = PositionInterpolator(duration, 0.0, m_offset, m2::PointD(0.0, 0.0));
m_objects.insert(Animation::MapPlane);
@ -30,7 +33,7 @@ MapFollowAnimation::MapFollowAnimation(m2::PointD const & globalPosition,
m_properties.insert(Animation::Scale);
if (m_angleInterpolator.IsActive())
m_properties.insert(Animation::Angle);
if (m_pixelPosInterpolator.IsActive())
if (m_offsetInterpolator.IsActive() || m_scaleInterpolator.IsActive() || m_angleInterpolator.IsActive())
m_properties.insert(Animation::Position);
}
@ -51,8 +54,8 @@ void MapFollowAnimation::Advance(double elapsedSeconds)
m_angleInterpolator.Advance(elapsedSeconds);
if (m_scaleInterpolator.IsActive())
m_scaleInterpolator.Advance(elapsedSeconds);
if (m_pixelPosInterpolator.IsActive())
m_pixelPosInterpolator.Advance(elapsedSeconds);
if (m_offsetInterpolator.IsActive())
m_offsetInterpolator.Advance(elapsedSeconds);
}
void MapFollowAnimation::Finish()
@ -61,8 +64,8 @@ void MapFollowAnimation::Finish()
m_angleInterpolator.Finish();
if (m_scaleInterpolator.IsActive())
m_scaleInterpolator.Finish();
if (m_pixelPosInterpolator.IsActive())
m_pixelPosInterpolator.Finish();
if (m_offsetInterpolator.IsActive())
m_offsetInterpolator.Finish();
Animation::Finish();
}
@ -72,8 +75,8 @@ void MapFollowAnimation::SetMaxDuration(double maxDuration)
m_angleInterpolator.SetMaxDuration(maxDuration);
if (m_scaleInterpolator.IsActive())
m_scaleInterpolator.SetMaxDuration(maxDuration);
if (m_pixelPosInterpolator.IsActive())
m_pixelPosInterpolator.SetMaxDuration(maxDuration);
if (m_offsetInterpolator.IsActive())
m_offsetInterpolator.SetMaxDuration(maxDuration);
}
double MapFollowAnimation::GetDuration() const
@ -83,33 +86,13 @@ double MapFollowAnimation::GetDuration() const
double MapFollowAnimation::CalculateDuration() const
{
return max(max(m_pixelPosInterpolator.GetDuration(),
m_angleInterpolator.GetDuration()), m_scaleInterpolator.GetDuration());
return max(m_offsetInterpolator.GetDuration(),
max(m_angleInterpolator.GetDuration(), m_scaleInterpolator.GetDuration()));
}
bool MapFollowAnimation::IsFinished() const
{
return m_pixelPosInterpolator.IsFinished() && m_angleInterpolator.IsFinished() &&
m_scaleInterpolator.IsFinished();
}
// static
m2::PointD MapFollowAnimation::CalculateCenter(ScreenBase const & screen, m2::PointD const & userPos,
m2::PointD const & pixelPos, double azimuth)
{
double const scale = screen.GlobalRect().GetLocalRect().SizeX() / screen.PixelRect().SizeX();
return CalculateCenter(scale, screen.PixelRect(), userPos, pixelPos, azimuth);
}
// static
m2::PointD MapFollowAnimation::CalculateCenter(double scale, m2::RectD const & pixelRect,
m2::PointD const & userPos, m2::PointD const & pixelPos,
double azimuth)
{
m2::PointD formingVector = (pixelRect.Center() - pixelPos) * scale;
formingVector.y = -formingVector.y;
formingVector.Rotate(azimuth);
return userPos + formingVector;
return m_angleInterpolator.IsFinished() && m_scaleInterpolator.IsFinished() && m_offsetInterpolator.IsFinished();
}
bool MapFollowAnimation::GetProperty(TObject object, TProperty property, PropertyValue & value) const
@ -126,17 +109,24 @@ bool MapFollowAnimation::GetProperty(TObject object, TProperty property, bool ta
{
if (property == Animation::Position)
{
m2::RectD const pixelRect = AnimationSystem::Instance().GetLastScreen().PixelRect();
ScreenBase tmp = AnimationSystem::Instance().GetLastScreen();
if (targetValue)
{
value = PropertyValue(CalculateCenter(m_scaleInterpolator.GetTargetScale(), pixelRect, m_globalPosition,
m_pixelPosInterpolator.GetTargetPosition(), m_angleInterpolator.GetTargetAngle()));
tmp.SetFromParams(m_globalPosition, m_angleInterpolator.GetTargetAngle(), m_scaleInterpolator.GetTargetScale());
tmp.MatchGandP3d(m_globalPosition, m_endPixelPosition);
}
else
{
value = PropertyValue(CalculateCenter(m_scaleInterpolator.GetScale(), pixelRect, m_globalPosition,
m_pixelPosInterpolator.GetPosition(), m_angleInterpolator.GetAngle()));
double const scale = m_scaleInterpolator.GetScale() / m_scaleInterpolator.GetStartScale();
double const angle = m_angleInterpolator.GetAngle() - m_angleInterpolator.GetStartAngle();
m2::PointD offset = m_offsetInterpolator.GetPosition() * scale;
offset.Rotate(angle);
m2::PointD pos = m_globalPosition + offset;
tmp.SetFromParams(m_globalPosition, m_angleInterpolator.GetAngle(), m_scaleInterpolator.GetScale());
tmp.MatchGandP3d(pos, m_endPixelPosition);
}
value = PropertyValue(tmp.GetOrg());
return true;
}
if (property == Animation::Angle)
@ -160,7 +150,7 @@ bool MapFollowAnimation::HasScale() const
bool MapFollowAnimation::HasPixelOffset() const
{
return m_pixelPosInterpolator.IsActive();
return m_offsetInterpolator.IsActive();
}
} // namespace df

View file

@ -9,18 +9,11 @@ namespace df
class MapFollowAnimation : public Animation
{
public:
MapFollowAnimation(m2::PointD const & globalPosition,
double startScale, double endScale,
double startAngle, double endAngle,
m2::PointD const & startPixelPosition,
MapFollowAnimation(ScreenBase const & screen,
m2::PointD const & globalUserPosition,
m2::PointD const & endPixelPosition,
m2::RectD const & pixelRect);
static m2::PointD CalculateCenter(ScreenBase const & screen, m2::PointD const & userPos,
m2::PointD const & pixelPos, double azimuth);
static m2::PointD CalculateCenter(double scale, m2::RectD const & pixelRect,
m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth);
double startScale, double endScale,
double startAngle, double endAngle);
Animation::Type GetType() const override { return Animation::MapFollow; }
@ -55,10 +48,13 @@ private:
double CalculateDuration() const;
ScaleInterpolator m_scaleInterpolator;
PositionInterpolator m_pixelPosInterpolator;
AngleInterpolator m_angleInterpolator;
PositionInterpolator m_offsetInterpolator;
m2::PointD const m_globalPosition;
m2::PointD const m_endPixelPosition;
m2::PointD m_offset;
TObjectProperties m_properties;
TAnimObjects m_objects;

View file

@ -87,8 +87,7 @@ PositionInterpolator::PositionInterpolator()
{}
PositionInterpolator::PositionInterpolator(double duration, double delay,
m2::PointD const & startPosition,
m2::PointD const & endPosition)
m2::PointD const & startPosition, m2::PointD const & endPosition)
: Interpolator(duration, delay)
, m_startPosition(startPosition)
, m_endPosition(endPosition)
@ -97,14 +96,13 @@ PositionInterpolator::PositionInterpolator(double duration, double delay,
SetActive(m_startPosition != m_endPosition);
}
PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition,
m2::PointD const & endPosition,
PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition,
ScreenBase const & convertor)
: PositionInterpolator(0.0 /* delay */, startPosition, endPosition, convertor)
{}
PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & startPosition,
m2::PointD const & endPosition,
PositionInterpolator::PositionInterpolator(double delay,
m2::PointD const & startPosition, m2::PointD const & endPosition,
ScreenBase const & convertor)
: Interpolator(PositionInterpolator::GetMoveDuration(startPosition, endPosition, convertor), delay)
, m_startPosition(startPosition)
@ -114,52 +112,51 @@ PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & star
SetActive(m_startPosition != m_endPosition);
}
PositionInterpolator::PositionInterpolator(m2::PointD const & startPxPosition,
m2::PointD const & endPxPosition,
m2::RectD const & pixelRect)
: PositionInterpolator(0.0 /* delay */, startPxPosition, endPxPosition, pixelRect)
PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition,
m2::RectD const & viewportRect, double scale)
: PositionInterpolator(0.0 /* delay */, startPosition, endPosition, viewportRect, scale)
{}
PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & startPxPosition,
m2::PointD const & endPxPosition, m2::RectD const & pixelRect)
: Interpolator(PositionInterpolator::GetPixelMoveDuration(startPxPosition, endPxPosition, pixelRect), delay)
, m_startPosition(startPxPosition)
, m_endPosition(endPxPosition)
, m_position(startPxPosition)
PositionInterpolator::PositionInterpolator(double delay,
m2::PointD const & startPosition, m2::PointD const & endPosition,
m2::RectD const & viewportRect, double scale)
: Interpolator(PositionInterpolator::GetMoveDuration(startPosition, endPosition, viewportRect, scale), delay)
, m_startPosition(startPosition)
, m_endPosition(endPosition)
, m_position(startPosition)
{
SetActive(m_startPosition != m_endPosition);
}
//static
double PositionInterpolator::GetMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition,
m2::RectD const & viewportRect, double scale)
{
double const kMinMoveDuration = 0.2;
double const kMinSpeedScalar = 0.2;
double const kMaxSpeedScalar = 7.0;
double const kEps = 1e-5;
double const pixelLength = endPosition.Length(startPosition) / scale;
if (pixelLength < kEps)
return 0.0;
double const minSize = min(viewportRect.SizeX(), viewportRect.SizeY());
if (pixelLength < kMinSpeedScalar * minSize)
return kMinMoveDuration;
double const pixelSpeed = kMaxSpeedScalar * minSize;
return CalcAnimSpeedDuration(pixelLength, pixelSpeed);
}
//static
double PositionInterpolator::GetMoveDuration(m2::PointD const & startPosition,
m2::PointD const & endPosition,
ScreenBase const & convertor)
{
return GetPixelMoveDuration(convertor.GtoP(startPosition),
convertor.GtoP(endPosition),
convertor.PixelRect());
return GetMoveDuration(startPosition, endPosition, convertor.PixelRectIn3d(), convertor.GetScale());
}
double PositionInterpolator::GetPixelMoveDuration(m2::PointD const & startPosition,
m2::PointD const & endPosition,
m2::RectD const & pixelRect)
{
double const kMinMoveDuration = 0.2;
double const kMinSpeedScalar = 0.2;
double const kMaxSpeedScalar = 7.0;
double const kEps = 1e-5;
double const pixelLength = endPosition.Length(startPosition);
if (pixelLength < kEps)
return 0.0;
double const minSize = min(pixelRect.SizeX(), pixelRect.SizeY());
if (pixelLength < kMinSpeedScalar * minSize)
return kMinMoveDuration;
double const pixelSpeed = kMaxSpeedScalar * minSize;
return CalcAnimSpeedDuration(pixelLength, pixelSpeed);
}
void PositionInterpolator::Advance(double elapsedSeconds)
{

View file

@ -40,25 +40,27 @@ class PositionInterpolator: public Interpolator
public:
PositionInterpolator();
PositionInterpolator(double duration, double delay,
m2::PointD const & startPosition,
m2::PointD const & endPosition);
PositionInterpolator(m2::PointD const & startPosition,
m2::PointD const & endPosition,
ScreenBase const & convertor);
PositionInterpolator(double delay, m2::PointD const & startPosition,
m2::PointD const & endPosition,
ScreenBase const & convertor);
PositionInterpolator(m2::PointD const & startPxPosition,
m2::PointD const & endPxPosition,
m2::RectD const & pixelRect);
PositionInterpolator(double delay, m2::PointD const & startPxPosition,
m2::PointD const & endPxPosition,
m2::RectD const & pixelRect);
m2::PointD const & startPosition, m2::PointD const & endPosition);
static double GetMoveDuration(m2::PointD const & startPosition,
m2::PointD const & endPosition, ScreenBase const & convertor);
static double GetPixelMoveDuration(m2::PointD const & startPosition,
m2::PointD const & endPosition, m2::RectD const & pixelRect);
PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition,
ScreenBase const & convertor);
PositionInterpolator(double delay,
m2::PointD const & startPosition, m2::PointD const & endPosition,
ScreenBase const & convertor);
PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition,
m2::RectD const & viewportRect, double scale);
PositionInterpolator(double delay,
m2::PointD const & startPosition, m2::PointD const & endPosition,
m2::RectD const & viewportRect, double scale);
static double GetMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition,
m2::RectD const & viewportRect, double scale);
static double GetMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition,
ScreenBase const & convertor);
// Interpolator overrides:
void Advance(double elapsedSeconds) override;
@ -89,6 +91,7 @@ public:
void Finish() override;
double GetScale() const { return m_scale; }
double GetStartScale() const { return m_startScale; }
double GetTargetScale() const { return m_endScale; }
private:
@ -114,6 +117,7 @@ public:
void Finish() override;
double GetAngle() const { return m_angle; }
double GetStartAngle() const { return m_startAngle; }
double GetTargetAngle() const { return m_endAngle; }
private:

View file

@ -39,6 +39,14 @@ void MapLinearAnimation::SetMove(m2::PointD const & startPos, m2::PointD const &
m_properties.insert(Animation::Position);
}
void MapLinearAnimation::SetMove(m2::PointD const & startPos, m2::PointD const & endPos,
m2::RectD const & viewportRect, double scale)
{
m_positionInterpolator = PositionInterpolator(startPos, endPos, viewportRect, scale);
if (m_positionInterpolator.IsActive())
m_properties.insert(Animation::Position);
}
void MapLinearAnimation::SetRotate(double startAngle, double endAngle)
{
m_angleInterpolator = AngleInterpolator(startAngle, endAngle);

View file

@ -15,6 +15,7 @@ public:
MapLinearAnimation();
void SetMove(m2::PointD const & startPos, m2::PointD const & endPos, ScreenBase const & convertor);
void SetMove(m2::PointD const & startPos, m2::PointD const & endPos, m2::RectD const & viewportRect, double scale);
void SetRotate(double startAngle, double endAngle);
void SetScale(double startScale, double endScale);

View file

@ -1,121 +0,0 @@
#include "perspective_animation.hpp"
namespace df
{
PerspectiveSwitchAnimation::PerspectiveSwitchAnimation(double startAngle, double endAngle, double angleFOV)
: Animation(false /* couldBeInterrupted */, false /* couldBeBlended */)
, m_angleInterpolator(GetRotateDuration(startAngle, endAngle), startAngle, endAngle)
, m_startAngle(startAngle)
, m_endAngle(endAngle)
, m_angleFOV(angleFOV)
, m_isEnablePerspectiveAnim(m_endAngle > 0.0)
, m_needPerspectiveSwitch(false)
{
m_objects.insert(Animation::MapPlane);
m_properties.insert(Animation::AnglePerspective);
m_properties.insert(Animation::SwitchPerspective);
}
// static
double PerspectiveSwitchAnimation::GetRotateDuration(double startAngle, double endAngle)
{
double const kScalar = 0.5;
return kScalar * fabs(endAngle - startAngle) / math::pi4;
}
Animation::TObjectProperties const & PerspectiveSwitchAnimation::GetProperties(TObject object) const
{
ASSERT_EQUAL(object, Animation::MapPlane, ());
return m_properties;
}
bool PerspectiveSwitchAnimation::HasProperty(TObject object, TProperty property) const
{
return HasObject(object) && m_properties.find(property) != m_properties.end();
}
bool PerspectiveSwitchAnimation::HasTargetProperty(TObject object, TProperty property) const
{
return HasObject(object) && property == Animation::SwitchPerspective;
}
void PerspectiveSwitchAnimation::Advance(double elapsedSeconds)
{
m_angleInterpolator.Advance(elapsedSeconds);
}
void PerspectiveSwitchAnimation::Finish()
{
m_angleInterpolator.Finish();
Animation::Finish();
}
void PerspectiveSwitchAnimation::OnStart()
{
if (m_isEnablePerspectiveAnim)
m_needPerspectiveSwitch = true;
Animation::OnStart();
}
void PerspectiveSwitchAnimation::OnFinish()
{
if (!m_isEnablePerspectiveAnim)
m_needPerspectiveSwitch = true;
Animation::OnFinish();
}
void PerspectiveSwitchAnimation::SetMaxDuration(double maxDuration)
{
m_angleInterpolator.SetMaxDuration(maxDuration);
}
double PerspectiveSwitchAnimation::GetDuration() const
{
return m_angleInterpolator.GetDuration();
}
bool PerspectiveSwitchAnimation::IsFinished() const
{
return m_angleInterpolator.IsFinished();
}
bool PerspectiveSwitchAnimation::GetTargetProperty(TObject object, TProperty property, PropertyValue & value) const
{
ASSERT_EQUAL(object, Animation::MapPlane, ());
if (property == Animation::SwitchPerspective)
{
value = PropertyValue(SwitchPerspectiveParams(m_isEnablePerspectiveAnim, m_endAngle, m_endAngle, m_angleFOV));
return true;
}
ASSERT(false, ("Wrong property:", property));
return false;
}
bool PerspectiveSwitchAnimation::GetProperty(TObject object, TProperty property, PropertyValue & value) const
{
ASSERT_EQUAL(object, Animation::MapPlane, ());
switch (property)
{
case Animation::AnglePerspective:
value = PropertyValue(m_angleInterpolator.GetAngle());
return true;
case Animation::SwitchPerspective:
if (m_needPerspectiveSwitch)
{
m_needPerspectiveSwitch = false;
value = PropertyValue(SwitchPerspectiveParams(m_isEnablePerspectiveAnim, m_startAngle, m_endAngle, m_angleFOV));
return true;
}
return false;
default:
ASSERT(false, ("Wrong property:", property));
}
return false;
}
} // namespace df

View file

@ -1,58 +0,0 @@
#pragma once
#include "animation.hpp"
#include "interpolators.hpp"
namespace df
{
class PerspectiveSwitchAnimation : public Animation
{
public:
PerspectiveSwitchAnimation(double startAngle, double endAngle, double angleFOV);
static double GetRotateDuration(double startAngle, double endAngle);
Animation::Type GetType() const override { return Animation::MapPerspective; }
TAnimObjects const & GetObjects() const override
{
return m_objects;
}
bool HasObject(TObject object) const override
{
return m_objects.find(object) != m_objects.end();
}
TObjectProperties const & GetProperties(TObject object) const override;
bool HasProperty(TObject object, TProperty property) const override;
bool HasTargetProperty(TObject object, TProperty property) const override;
void Advance(double elapsedSeconds) override;
void Finish() override;
void OnStart() override;
void OnFinish() override;
void SetMaxDuration(double maxDuration) override;
double GetDuration() const override;
bool IsFinished() const override;
bool GetProperty(TObject object, TProperty property, PropertyValue & value) const override;
bool GetTargetProperty(TObject object, TProperty property, PropertyValue & value) const override;
private:
AngleInterpolator m_angleInterpolator;
double m_startAngle;
double m_endAngle;
double m_angleFOV;
bool m_isEnablePerspectiveAnim;
mutable bool m_needPerspectiveSwitch;
TAnimObjects m_objects;
TObjectProperties m_properties;
};
} // namespace df

View file

@ -8,10 +8,10 @@ namespace df
{
MapScaleAnimation::MapScaleAnimation(double startScale, double endScale, m2::PointD const & globalScaleCenter,
m2::PointD const & pixelCenterOffset)
m2::PointD const & pxScaleCenter)
: Animation(true /* couldBeInterrupted */, true /* couldBeBlended */)
, m_scaleInterpolator(startScale, endScale)
, m_pixelCenterOffset(pixelCenterOffset)
, m_pxScaleCenter(pxScaleCenter)
, m_globalScaleCenter(globalScaleCenter)
{
m_objects.insert(Animation::MapPlane);
@ -64,7 +64,8 @@ bool MapScaleAnimation::GetProperty(TObject object, TProperty property, bool tar
{
ScreenBase screen = AnimationSystem::Instance().GetLastScreen();
screen.SetScale(targetValue ? m_scaleInterpolator.GetTargetScale() : m_scaleInterpolator.GetScale());
value = PropertyValue(screen.PtoG(screen.GtoP(m_globalScaleCenter) + m_pixelCenterOffset));
m2::PointD const pixelOffset = screen.PixelRect().Center() - screen.P3dtoP(m_pxScaleCenter);
value = PropertyValue(screen.PtoG(screen.GtoP(m_globalScaleCenter) + pixelOffset));
return true;
}
if (property == Animation::Scale)

View file

@ -10,7 +10,7 @@ class MapScaleAnimation : public Animation
{
public:
MapScaleAnimation(double startScale, double endScale,
m2::PointD const & globalScaleCenter, m2::PointD const & pixelCenterOffset);
m2::PointD const & globalScaleCenter, m2::PointD const & pxScaleCenter);
Animation::Type GetType() const override { return Animation::MapScale; }
@ -41,7 +41,7 @@ private:
bool GetProperty(TObject object, TProperty property, bool targetValue, PropertyValue & value) const;
ScaleInterpolator m_scaleInterpolator;
m2::PointD const m_pixelCenterOffset;
m2::PointD const m_pxScaleCenter;
m2::PointD const m_globalScaleCenter;
TObjectProperties m_properties;
TAnimObjects m_objects;

View file

@ -18,14 +18,6 @@ public:
void Blend(Animation::PropertyValue const & value)
{
// Now perspective parameters can't be blended.
if (value.m_type == Animation::PropertyValue::ValuePerspectiveParams)
{
m_value = value;
m_counter = 1;
return;
}
if (m_counter != 0)
{
// New value type resets current blended value.
@ -75,17 +67,22 @@ private:
} // namespace
bool AnimationSystem::GetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect)
void AnimationSystem::UpdateLastScreen(ScreenBase const & currentScreen)
{
return GetRect(currentScreen, bind(&AnimationSystem::GetProperty, this, _1, _2, _3), rect);
m_lastScreen = currentScreen;
}
void AnimationSystem::GetTargetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect)
bool AnimationSystem::GetScreen(ScreenBase const & currentScreen, ScreenBase & screen)
{
GetRect(currentScreen, bind(&AnimationSystem::GetTargetProperty, this, _1, _2, _3), rect);
return GetScreen(currentScreen, bind(&AnimationSystem::GetProperty, this, _1, _2, _3), screen);
}
bool AnimationSystem::GetRect(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, m2::AnyRectD & rect)
void AnimationSystem::GetTargetScreen(ScreenBase const & currentScreen, ScreenBase & screen)
{
GetScreen(currentScreen, bind(&AnimationSystem::GetTargetProperty, this, _1, _2, _3), screen);
}
bool AnimationSystem::GetScreen(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, ScreenBase & screen)
{
ASSERT(getPropertyFn != nullptr, ());
@ -105,36 +102,12 @@ bool AnimationSystem::GetRect(ScreenBase const & currentScreen, TGetPropertyFn c
if (getPropertyFn(Animation::MapPlane, Animation::Position, value))
pos = value.m_valuePointD;
m2::RectD localRect = currentScreen.PixelRect();
localRect.Offset(-localRect.Center());
localRect.Scale(scale);
rect = m2::AnyRectD(pos, angle, localRect);
screen = currentScreen;
screen.SetFromParams(pos, angle, scale);
return true;
}
bool AnimationSystem::GetPerspectiveAngle(double & angle)
{
Animation::PropertyValue value;
if (GetProperty(Animation::MapPlane, Animation::AnglePerspective, value))
{
angle = value.m_valueD;
return true;
}
return false;
}
bool AnimationSystem::SwitchPerspective(Animation::SwitchPerspectiveParams & params)
{
Animation::PropertyValue value;
if (GetProperty(Animation::MapPlane, Animation::SwitchPerspective, value))
{
params = value.m_valuePerspectiveParams;
return true;
}
return false;
}
bool AnimationSystem::GetArrowPosition(m2::PointD & position)
{
Animation::PropertyValue value;

View file

@ -19,11 +19,9 @@ class AnimationSystem : private noncopyable
public:
static AnimationSystem & Instance();
bool GetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect);
void GetTargetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect);
bool SwitchPerspective(Animation::SwitchPerspectiveParams & params);
bool GetPerspectiveAngle(double & angle);
void UpdateLastScreen(ScreenBase const & currentScreen);
bool GetScreen(ScreenBase const & currentScreen, ScreenBase & screen);
void GetTargetScreen(ScreenBase const & currentScreen, ScreenBase & screen);
bool GetArrowPosition(m2::PointD & position);
bool GetArrowAngle(double & angle);
@ -66,7 +64,7 @@ private:
using TGetPropertyFn = function<bool (Animation::TObject object, Animation::TProperty property,
Animation::PropertyValue & value)>;
bool GetRect(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, m2::AnyRectD & rect);
bool GetScreen(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, ScreenBase & screen);
bool GetProperty(Animation::TObject object, Animation::TProperty property,
Animation::PropertyValue & value) const;

View file

@ -76,6 +76,15 @@ void BackendRenderer::RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool ne
m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::Normal);
}
#ifdef RENRER_DEBUG_INFO_LABELS
void BackendRenderer::RecacheDebugLabels()
{
drape_ptr<gui::LayerRenderer> layerRenderer = m_guiCacher.RecacheDebugLabels(m_texMng);
drape_ptr<Message> outputMsg = make_unique_dp<GuiLayerRecachedMessage>(move(layerRenderer), false);
m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::Normal);
}
#endif
void BackendRenderer::RecacheChoosePositionMark()
{
drape_ptr<gui::LayerRenderer> layerRenderer = m_guiCacher.RecacheChoosePositionMark(m_texMng);
@ -117,6 +126,10 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
{
ref_ptr<GuiRecacheMessage> msg = message;
RecacheGui(msg->GetInitInfo(), msg->NeedResetOldGui());
#ifdef RENRER_DEBUG_INFO_LABELS
RecacheDebugLabels();
#endif
break;
}
case Message::GuiLayerLayout:

View file

@ -63,6 +63,10 @@ private:
void RecacheChoosePositionMark();
void RecacheMapShapes();
#ifdef RENRER_DEBUG_INFO_LABELS
void RecacheDebugLabels();
#endif
void AcceptMessage(ref_ptr<Message> message) override;
class Routine : public threads::IRoutine

View file

@ -265,11 +265,10 @@ void DrapeEngine::StopLocationFollow()
MessagePriority::High);
}
void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, double rotationAngle, double angleFOV)
void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d,
rotationAngle, angleFOV),
make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d),
MessagePriority::High);
}
@ -380,22 +379,21 @@ void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info)
MessagePriority::Normal);
}
void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV)
void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<Allow3dBuildingsMessage>(allow3dBuildings),
MessagePriority::Normal);
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation, allow3dBuildings,
rotationAngle, angleFOV),
make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation, allow3dBuildings),
MessagePriority::Normal);
}
void DrapeEngine::EnablePerspective(double rotationAngle, double angleFOV)
void DrapeEngine::EnablePerspective()
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<EnablePerspectiveMessage>(rotationAngle, angleFOV),
make_unique_dp<EnablePerspectiveMessage>(),
MessagePriority::Normal);
}

View file

@ -124,14 +124,14 @@ public:
void AddRoute(m2::PolylineD const & routePolyline, vector<double> const & turns,
df::ColorConstant color, df::RoutePattern pattern = df::RoutePattern());
void RemoveRoute(bool deactivateFollowing);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, double rotationAngle, double angleFOV);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d);
void DeactivateRouteFollowing();
void SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid);
void SetWidgetLayout(gui::TWidgetsLayoutInfo && info);
void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV);
void EnablePerspective(double rotationAngle, double angleFOV);
void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings);
void EnablePerspective();
void UpdateGpsTrackPoints(vector<df::GpsTrackPoint> && toAdd, vector<uint32_t> && toRemove);
void ClearGpsTrackPoints();

View file

@ -23,12 +23,12 @@ SOURCES += \
animation/scale_animation.cpp \
animation/sequence_animation.cpp \
animation/parallel_animation.cpp \
animation/perspective_animation.cpp \
animation/opacity_animation.cpp \
animation/show_hide_animation.cpp \
gui/choose_position_mark.cpp \
gui/compass.cpp \
gui/copyright_label.cpp \
gui/debug_label.cpp \
gui/drape_gui.cpp \
gui/gui_text.cpp \
gui/layer_render.cpp \
@ -115,13 +115,13 @@ HEADERS += \
animation/scale_animation.hpp \
animation/sequence_animation.hpp \
animation/parallel_animation.hpp \
animation/perspective_animation.hpp \
animation/opacity_animation.hpp \
animation/show_hide_animation.hpp \
animation/value_mapping.hpp \
gui/choose_position_mark.hpp \
gui/compass.hpp \
gui/copyright_label.hpp \
gui/debug_label.hpp \
gui/drape_gui.hpp \
gui/gui_text.hpp \
gui/layer_render.hpp \

View file

@ -37,7 +37,6 @@ public:
void CorrectGlobalScalePoint(m2::PointD & pt) const override {}
void OnScaleEnded() override {}
void OnAnimationStarted(ref_ptr<df::Animation> /* anim */) override {}
void OnPerspectiveSwitchRejected() override {}
void OnTouchMapAction() override {}
void OnAnimatedScaleEnded() override {}

View file

@ -484,8 +484,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (m_pendingFollowRoute != nullptr)
{
FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d,
m_pendingFollowRoute->m_rotationAngle, m_pendingFollowRoute->m_angleFOV);
FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d);
m_pendingFollowRoute.reset();
}
break;
@ -522,13 +521,11 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (m_routeRenderer->GetRouteData() == nullptr)
{
m_pendingFollowRoute.reset(
new FollowRouteData(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(),
msg->GetRotationAngle(), msg->GetAngleFOV()));
new FollowRouteData(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d()));
break;
}
FollowRoute(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(),
msg->GetRotationAngle(), msg->GetAngleFOV());
FollowRoute(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d());
break;
}
@ -613,9 +610,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
case Message::EnablePerspective:
{
ref_ptr<EnablePerspectiveMessage> const msg = message;
AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
false /* animated */, true /* immediately start */));
AddUserEvent(SetAutoPerspectiveEvent(true /* isAutoPerspective */));
break;
}
@ -628,11 +623,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (m_enablePerspectiveInNavigation == msg->AllowPerspective() &&
m_enablePerspectiveInNavigation != screen.isPerspective())
{
if (m_enablePerspectiveInNavigation)
AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
false /* animated */, true /* immediately start */));
else
AddUserEvent(DisablePerspectiveEvent());
AddUserEvent(SetAutoPerspectiveEvent(m_enablePerspectiveInNavigation));
}
#endif
@ -648,15 +639,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
m_enablePerspectiveInNavigation = msg->AllowPerspective();
if (m_myPositionController->IsInRouting())
{
if (m_enablePerspectiveInNavigation && !screen.isPerspective() && !m_perspectiveDiscarded)
{
AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
true /* animated */, true /* immediately start */));
}
else if (!m_enablePerspectiveInNavigation && (screen.isPerspective() || m_perspectiveDiscarded))
{
DisablePerspective();
}
AddUserEvent(SetAutoPerspectiveEvent(m_enablePerspectiveInNavigation));
}
}
break;
@ -750,18 +733,14 @@ unique_ptr<threads::IRoutine> FrontendRenderer::CreateRoutine()
return make_unique<Routine>(*this);
}
void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d,
double rotationAngle, double angleFOV)
void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d)
{
m_myPositionController->ActivateRouting(!m_enablePerspectiveInNavigation ? preferredZoomLevel
: preferredZoomLevelIn3d);
if (m_enablePerspectiveInNavigation)
{
bool immediatelyStart = !m_myPositionController->IsRotationAvailable();
AddUserEvent(EnablePerspectiveEvent(rotationAngle, angleFOV, true /* animated */, immediatelyStart));
}
AddUserEvent(SetAutoPerspectiveEvent(true /* isAutoPerspective */));
m_overlayTree->SetFollowingMode(true);
}
@ -811,17 +790,22 @@ void FrontendRenderer::InvalidateRect(m2::RectD const & gRect)
void FrontendRenderer::OnResize(ScreenBase const & screen)
{
m2::RectD const viewportRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect();
m2::RectD const viewportRect = screen.PixelRectIn3d();
double const kEps = 1e-5;
bool const viewportChanged = !m2::IsEqualSize(m_lastReadedModelView.PixelRectIn3d(), viewportRect, kEps, kEps);
m_myPositionController->UpdatePixelPosition(screen);
m_myPositionController->OnNewPixelRect();
m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY());
m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY());
if (viewportChanged)
{
m_myPositionController->OnNewViewportRect();
m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY());
m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY());
m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
}
RefreshProjection(screen);
RefreshPivotTransform(screen);
m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
}
void FrontendRenderer::AddToRenderGroup(dp::GLState const & state,
@ -1069,18 +1053,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
if (m_guiRenderer != nullptr)
{
if (isPerspective)
{
ScreenBase modelView2d = modelView;
modelView2d.ResetPerspective();
m_guiRenderer->Render(make_ref(m_gpuProgramManager), modelView2d);
}
else
{
m_guiRenderer->Render(make_ref(m_gpuProgramManager), modelView);
}
}
m_guiRenderer->Render(make_ref(m_gpuProgramManager), modelView);
GLFunctions::glEnable(gl_const::GLDepthTest);
@ -1232,7 +1205,18 @@ void FrontendRenderer::RefreshModelView(ScreenBase const & screen)
m_generalUniforms.SetMatrix4x4Value("modelView", mv.m_data);
float const zScale = 2.0f / (screen.GetHeight() * screen.GetScale());
float zScale;
if (screen.isPerspective())
{
// TODO: Calculate exact value of zScale
double const averageScale3d = 3.0;
zScale = 2.0f / (screen.PixelRectIn3d().SizeY() * averageScale3d * screen.GetScale());
}
else
{
zScale = 2.0f / (screen.GetHeight() * screen.GetScale());
}
m_generalUniforms.SetFloatValue("zScale", zScale);
}
@ -1266,8 +1250,7 @@ void FrontendRenderer::RefreshBgColor()
void FrontendRenderer::DisablePerspective()
{
m_perspectiveDiscarded = false;
AddUserEvent(DisablePerspectiveEvent());
AddUserEvent(SetAutoPerspectiveEvent(false /* isAutoPerspective */));
}
void FrontendRenderer::CheckIsometryMinScale(ScreenBase const & screen)
@ -1281,20 +1264,6 @@ void FrontendRenderer::CheckIsometryMinScale(ScreenBase const & screen)
}
}
void FrontendRenderer::CheckPerspectiveMinScale()
{
if (!m_enablePerspectiveInNavigation || m_userEventStream.IsInPerspectiveAnimation())
return;
bool const switchTo2d = !IsScaleAllowableIn3d(m_currentZoomLevel);
if ((!switchTo2d && !m_perspectiveDiscarded) ||
(switchTo2d && !m_userEventStream.GetCurrentScreen().isPerspective()))
return;
m_perspectiveDiscarded = switchTo2d;
AddUserEvent(SwitchViewModeEvent(switchTo2d));
}
void FrontendRenderer::ResolveZoomLevel(ScreenBase const & screen)
{
int const prevZoomLevel = m_currentZoomLevel;
@ -1304,7 +1273,6 @@ void FrontendRenderer::ResolveZoomLevel(ScreenBase const & screen)
UpdateCanBeDeletedStatus();
CheckIsometryMinScale(screen);
CheckPerspectiveMinScale();
UpdateDisplacementEnabled();
}
@ -1432,12 +1400,6 @@ void FrontendRenderer::OnAnimationStarted(ref_ptr<Animation> anim)
m_myPositionController->AnimationStarted(anim);
}
void FrontendRenderer::OnPerspectiveSwitchRejected()
{
if (m_perspectiveDiscarded)
m_perspectiveDiscarded = false;
}
void FrontendRenderer::OnTouchMapAction()
{
m_myPositionController->ResetRoutingNotFollowTimer();

View file

@ -174,7 +174,6 @@ private:
TTilesCollection ResolveTileKeys(ScreenBase const & screen);
void ResolveZoomLevel(ScreenBase const & screen);
void UpdateDisplacementEnabled();
void CheckPerspectiveMinScale();
void CheckIsometryMinScale(ScreenBase const & screen);
void DisablePerspective();
@ -195,7 +194,6 @@ private:
void OnScaleEnded() override;
void OnAnimatedScaleEnded() override;
void OnAnimationStarted(ref_ptr<Animation> anim) override;
void OnPerspectiveSwitchRejected() override;
void OnTouchMapAction() override;
class Routine : public threads::IRoutine
@ -223,8 +221,7 @@ private:
using TRenderGroupRemovePredicate = function<bool(drape_ptr<RenderGroup> const &)>;
void RemoveRenderGroupsLater(TRenderGroupRemovePredicate const & predicate);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d,
double rotationAngle, double angleFOV);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d);
void InvalidateRect(m2::RectD const & gRect);
bool CheckTileGenerations(TileKey const & tileKey);
void UpdateCanBeDeletedStatus();
@ -296,8 +293,6 @@ private:
TTilesCollection m_notFinishedTiles;
int m_currentZoomLevel = -1;
bool m_perspectiveDiscarded = false;
ref_ptr<RequestedTiles> m_requestedTiles;
uint64_t m_maxGeneration;
@ -306,19 +301,13 @@ private:
struct FollowRouteData
{
FollowRouteData(int preferredZoomLevel,
int preferredZoomLevelIn3d,
double rotationAngle,
double angleFOV)
int preferredZoomLevelIn3d)
: m_preferredZoomLevel(preferredZoomLevel)
, m_preferredZoomLevelIn3d(preferredZoomLevelIn3d)
, m_rotationAngle(rotationAngle)
, m_angleFOV(angleFOV)
{}
int m_preferredZoomLevel;
int m_preferredZoomLevelIn3d;
double m_rotationAngle;
double m_angleFOV;
};
unique_ptr<FollowRouteData> m_pendingFollowRoute;

View file

@ -37,7 +37,7 @@ public:
bool Update(ScreenBase const & screen) override
{
SetPivot(glsl::ToVec2(m2::PointF(screen.PixelRect().Center())));
SetPivot(glsl::ToVec2(m2::PointF(screen.PixelRectIn3d().Center())));
return TBase::Update(screen);
}
};

View file

@ -0,0 +1,94 @@
#include "debug_label.hpp"
#include "drape_gui.hpp"
#include "std/bind.hpp"
namespace gui
{
class DebugLabelHandle : public MutableLabelHandle
{
using TBase = MutableLabelHandle;
public:
DebugLabelHandle(uint32_t id, dp::Anchor anchor, m2::PointF const & pivot,
ref_ptr<dp::TextureManager> tex, TUpdateDebugLabelFn const & onUpdateFn)
: MutableLabelHandle(id, anchor, pivot)
, m_onUpdateFn(onUpdateFn)
{
SetTextureManager(tex);
}
bool Update(ScreenBase const & screen) override
{
string content;
bool const isVisible = m_onUpdateFn(screen, content);
SetIsVisible(isVisible);
SetContent(content);
return TBase::Update(screen);
}
private:
TUpdateDebugLabelFn m_onUpdateFn;
};
void AddSymbols(string const & str, set<char> & symbols)
{
for (size_t i = 0, sz = str.length(); i < sz; ++i)
symbols.insert(str[i]);
}
void DebugInfoLabels::AddLabel(ref_ptr<dp::TextureManager> tex, string const & caption, TUpdateDebugLabelFn const & onUpdateFn)
{
string alphabet;
set<char> symbols;
AddSymbols(caption, symbols);
AddSymbols("0123456789.-e", symbols);
alphabet.reserve(symbols.size());
for (auto const & ch : symbols)
alphabet.push_back(ch);
MutableLabelDrawer::Params params;
params.m_anchor = dp::LeftTop;
params.m_alphabet = alphabet;
params.m_maxLength = 100;
params.m_font = DrapeGui::GetGuiTextFont();
params.m_font.m_color = dp::Color(0, 0, 255, 255);
params.m_font.m_size *= 1.2;
params.m_pivot = m_position.m_pixelPivot;
#ifdef RENRER_DEBUG_INFO_LABELS
uint32_t const id = GuiHandleDebugLabel + m_labelsCount;
params.m_handleCreator = [id, onUpdateFn, tex](dp::Anchor anchor, m2::PointF const & pivot)
{
return make_unique_dp<DebugLabelHandle>(id, anchor, pivot, tex, onUpdateFn);
};
#endif
m_labelsParams.push_back(params);
++m_labelsCount;
}
drape_ptr<ShapeRenderer> DebugInfoLabels::Draw(ref_ptr<dp::TextureManager> tex)
{
drape_ptr<ShapeRenderer> renderer = make_unique_dp<ShapeRenderer>();
m2::PointF pos = m_position.m_pixelPivot;
for (auto & params : m_labelsParams)
{
params.m_pivot.y = pos.y;
m2::PointF textSize = MutableLabelDrawer::Draw(params, tex, bind(&ShapeRenderer::AddShape, renderer.get(), _1, _2));
pos.y += 2 * textSize.y;
}
m_labelsParams.clear();
return renderer;
}
} // namespace gui

View file

@ -0,0 +1,28 @@
#pragma once
#include "gui_text.hpp"
#include "shape.hpp"
#include "std/vector.hpp"
namespace gui
{
using TUpdateDebugLabelFn = function<bool(ScreenBase const & screen, string & content)>;
class DebugInfoLabels : public Shape
{
public:
DebugInfoLabels(gui::Position const & position)
: Shape(position)
{}
void AddLabel(ref_ptr<dp::TextureManager> tex, string const & caption, TUpdateDebugLabelFn const & onUpdateFn);
drape_ptr<ShapeRenderer> Draw(ref_ptr<dp::TextureManager> tex);
private:
vector<MutableLabelDrawer::Params> m_labelsParams;
uint32_t m_labelsCount = 0;
};
} // namespace gui

View file

@ -1,6 +1,7 @@
#include "choose_position_mark.hpp"
#include "compass.hpp"
#include "copyright_label.hpp"
#include "debug_label.hpp"
#include "drape_gui.hpp"
#include "gui_text.hpp"
#include "layer_render.hpp"
@ -12,6 +13,8 @@
#include "drape/batcher.hpp"
#include "drape/render_bucket.hpp"
#include "geometry/mercator.hpp"
#include "base/stl_add.hpp"
#include "std/bind.hpp"
@ -212,6 +215,100 @@ drape_ptr<LayerRenderer> LayerCacher::RecacheChoosePositionMark(ref_ptr<dp::Text
return renderer;
}
#ifdef RENRER_DEBUG_INFO_LABELS
drape_ptr<LayerRenderer> LayerCacher::RecacheDebugLabels(ref_ptr<dp::TextureManager> textures)
{
drape_ptr<LayerRenderer> renderer = make_unique_dp<LayerRenderer>();
float const vs = df::VisualParams::Instance().GetVisualScale();
DebugInfoLabels debugLabels = DebugInfoLabels(Position(m2::PointF(10.0f * vs, 50.0f * vs), dp::Center));
debugLabels.AddLabel(textures, "visible: km2, readed: km2, ratio:",
[](ScreenBase const & screen, string & content) -> bool
{
double const sizeX = screen.PixelRectIn3d().SizeX();
double const sizeY = screen.PixelRectIn3d().SizeY();
m2::PointD const p0 = screen.PtoG(screen.P3dtoP(m2::PointD(0.0, 0.0)));
m2::PointD const p1 = screen.PtoG(screen.P3dtoP(m2::PointD(0.0, sizeY)));
m2::PointD const p2 = screen.PtoG(screen.P3dtoP(m2::PointD(sizeX, sizeY)));
m2::PointD const p3 = screen.PtoG(screen.P3dtoP(m2::PointD(sizeX, 0.0)));
double const areaG = MercatorBounds::AreaOnEarth(p0, p1, p2) +
MercatorBounds::AreaOnEarth(p2, p3, p0);
double const sizeX_2d = screen.PixelRect().SizeX();
double const sizeY_2d = screen.PixelRect().SizeY();
m2::PointD const p0_2d = screen.PtoG(m2::PointD(0.0, 0.0));
m2::PointD const p1_2d = screen.PtoG(m2::PointD(0.0, sizeY_2d));
m2::PointD const p2_2d = screen.PtoG(m2::PointD(sizeX_2d, sizeY_2d));
m2::PointD const p3_2d = screen.PtoG(m2::PointD(sizeX_2d, 0.0));
double const areaGTotal = MercatorBounds::AreaOnEarth(p0_2d, p1_2d, p2_2d) +
MercatorBounds::AreaOnEarth(p2_2d, p3_2d, p0_2d);
ostringstream out;
out << fixed << setprecision(2)
<< "visible: " << areaG / 1000000.0 << " km2"
<< ", readed: " << areaGTotal / 1000000.0 << " km2"
<< ", ratio: " << areaGTotal / areaG;
content.assign(out.str());
return true;
});
debugLabels.AddLabel(textures, "scale2d: m/px, scale2d * vs: m/px",
[](ScreenBase const & screen, string & content) -> bool
{
double const distanceG = MercatorBounds::DistanceOnEarth(screen.PtoG(screen.PixelRect().LeftBottom()),
screen.PtoG(screen.PixelRect().RightBottom()));
double const vs = df::VisualParams::Instance().GetVisualScale();
double const scale = distanceG / screen.PixelRect().SizeX();
ostringstream out;
out << fixed << setprecision(2)
<< "scale2d: " << scale << " m/px"
<< ", scale2d * vs: " << scale * vs << " m/px";
content.assign(out.str());
return true;
});
debugLabels.AddLabel(textures, "distance: m",
[](ScreenBase const & screen, string & content) -> bool
{
double const sizeX = screen.PixelRectIn3d().SizeX();
double const sizeY = screen.PixelRectIn3d().SizeY();
double const distance = MercatorBounds::DistanceOnEarth(screen.PtoG(screen.P3dtoP(m2::PointD(sizeX / 2.0, 0.0))),
screen.PtoG(screen.P3dtoP(m2::PointD(sizeX / 2.0, sizeY))));
ostringstream out;
out << fixed << setprecision(2)
<< "distance: " << distance << " m";
content.assign(out.str());
return true;
});
debugLabels.AddLabel(textures, "angle: ",
[](ScreenBase const & screen, string & content) -> bool
{
ostringstream out;
out << fixed << setprecision(2)
<< "angle: " << screen.GetRotationAngle() * 180.0 / math::pi;
content.assign(out.str());
return true;
});
renderer->AddShapeRenderer(WIDGET_DEBUG_INFO, debugLabels.Draw(textures));
// Flush gui geometry.
GLFunctions::glFlush();
return renderer;
}
#endif
m2::PointF LayerCacher::CacheCompass(Position const & position, ref_ptr<LayerRenderer> renderer,
ref_ptr<dp::TextureManager> textures)
{

View file

@ -58,6 +58,10 @@ public:
ref_ptr<dp::TextureManager> textures);
drape_ptr<LayerRenderer> RecacheChoosePositionMark(ref_ptr<dp::TextureManager> textures);
#ifdef RENRER_DEBUG_INFO_LABELS
drape_ptr<LayerRenderer> RecacheDebugLabels(ref_ptr<dp::TextureManager> textures);
#endif
private:
m2::PointF CacheCompass(Position const & position, ref_ptr<LayerRenderer> renderer, ref_ptr<dp::TextureManager> textures);
m2::PointF CacheRuler(Position const & position, ref_ptr<LayerRenderer> renderer, ref_ptr<dp::TextureManager> textures);

View file

@ -91,7 +91,7 @@ void ShapeRenderer::Build(ref_ptr<dp::GpuProgramManager> mng)
void ShapeRenderer::Render(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng)
{
array<float, 16> m;
m2::RectD const & pxRect = screen.PixelRect();
m2::RectD const & pxRect = screen.PixelRectIn3d();
dp::MakeProjection(m, 0.0f, pxRect.SizeX(), pxRect.SizeY(), 0.0f);
dp::UniformValuesStorage uniformStorage;

View file

@ -6,6 +6,8 @@
#include "std/map.hpp"
//#define RENRER_DEBUG_INFO_LABELS
namespace gui
{
@ -16,7 +18,10 @@ enum EWidget
WIDGET_COPYRIGHT = 0x4,
WIDGET_SCALE_LABEL = 0x8,
/// Following widgets controlled by rendering kernel. Don't use them in platform code
WIDGET_CHOOSE_POSITION_MARK = 0x8000
WIDGET_CHOOSE_POSITION_MARK = 0x8000,
#ifdef RENRER_DEBUG_INFO_LABELS
WIDGET_DEBUG_INFO
#endif
};
enum EGuiHandle
@ -34,7 +39,10 @@ enum EGuiHandle
GuiHandleRetryButtonLabel,
GuiHandleCancelButton,
GuiHandleCancelButtonLabel,
GuiHandleChoosePositionMark
GuiHandleChoosePositionMark,
#ifdef RENRER_DEBUG_INFO_LABELS
GuiHandleDebugLabel = 100
#endif
};
struct Position

View file

@ -645,24 +645,18 @@ public:
class FollowRouteMessage : public Message
{
public:
FollowRouteMessage(int preferredZoomLevel, int preferredZoomLevelIn3d, double rotationAngle, double angleFOV)
FollowRouteMessage(int preferredZoomLevel, int preferredZoomLevelIn3d)
: m_preferredZoomLevel(preferredZoomLevel)
, m_preferredZoomLevelIn3d(preferredZoomLevelIn3d)
, m_rotationAngle(rotationAngle)
, m_angleFOV(angleFOV)
{}
Type GetType() const override { return Message::FollowRoute; }
int GetPreferredZoomLevel() const { return m_preferredZoomLevel; }
int GetPreferredZoomLevelIn3d() const { return m_preferredZoomLevelIn3d; }
double GetRotationAngle() const { return m_rotationAngle; }
double GetAngleFOV() const { return m_angleFOV; }
private:
int const m_preferredZoomLevel;
int const m_preferredZoomLevelIn3d;
double const m_rotationAngle;
double const m_angleFOV;
};
class InvalidateTexturesMessage : public BaseBlockingMessage
@ -694,24 +688,18 @@ public:
class Allow3dModeMessage : public Message
{
public:
Allow3dModeMessage(bool allowPerspective, bool allow3dBuildings, double rotationAngle, double angleFOV)
Allow3dModeMessage(bool allowPerspective, bool allow3dBuildings)
: m_allowPerspective(allowPerspective)
, m_allow3dBuildings(allow3dBuildings)
, m_rotationAngle(rotationAngle)
, m_angleFOV(angleFOV)
{}
Type GetType() const override { return Message::Allow3dMode; }
bool AllowPerspective() const { return m_allowPerspective; }
bool Allow3dBuildings() const { return m_allow3dBuildings; }
double GetRotationAngle() const { return m_rotationAngle; }
double GetAngleFOV() const { return m_angleFOV; }
private:
bool const m_allowPerspective;
bool const m_allow3dBuildings;
double const m_rotationAngle;
double const m_angleFOV;
};
class Allow3dBuildingsMessage : public Message
@ -731,19 +719,9 @@ private:
class EnablePerspectiveMessage : public Message
{
public:
EnablePerspectiveMessage(double rotationAngle, double angleFOV)
: m_rotationAngle(rotationAngle)
, m_angleFOV(angleFOV)
{}
EnablePerspectiveMessage() = default;
Type GetType() const override { return Message::EnablePerspective; }
double GetRotationAngle() const { return m_rotationAngle; }
double GetAngleFOV() const { return m_angleFOV; }
private:
double const m_rotationAngle;
double const m_angleFOV;
};
class CacheGpsTrackPointsMessage : public Message

View file

@ -52,7 +52,7 @@ string LocationModeStatisticsName(location::EMyPositionMode mode)
int GetZoomLevel(ScreenBase const & screen)
{
return my::clamp(fabs(log(screen.GetScale()) / log(2.0)), 1, scales::GetUpperStyleScale());
return df::GetZoomLevel(screen.GetScale());
}
int GetZoomLevel(ScreenBase const & screen, m2::PointD const & position, double errorRadius)
@ -63,6 +63,8 @@ int GetZoomLevel(ScreenBase const & screen, m2::PointD const & position, double
return GetZoomLevel(s);
}
} // namespace
MyPositionController::MyPositionController(location::EMyPositionMode initMode, double timeInBackground,
@ -103,7 +105,7 @@ MyPositionController::~MyPositionController()
{
}
void MyPositionController::OnNewPixelRect()
void MyPositionController::OnNewViewportRect()
{
UpdateViewport(kDoNotChangeZoom);
}
@ -112,8 +114,6 @@ void MyPositionController::UpdatePixelPosition(ScreenBase const & screen)
{
m_pixelRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect();
m_positionYOffset = screen.isPerspective() ? kPositionOffsetYIn3D : kPositionOffsetY;
m_centerPixelPositionRouting = screen.P3dtoP(GetRoutingRotationPixelCenter());
m_centerPixelPosition = screen.P3dtoP(m_pixelRect.Center());
}
void MyPositionController::SetListener(ref_ptr<MyPositionController::Listener> listener)
@ -266,7 +266,7 @@ void MyPositionController::NextMode(ScreenBase const & screen)
if (!m_isInRouting)
{
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_centerPixelPosition, preferredZoomLevel);
ChangeModelView(m_position, 0.0, m_pixelRect.Center(), preferredZoomLevel);
}
}
}
@ -317,7 +317,7 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool
ChangeModelView(m_position, kDoNotChangeZoom);
else if (m_mode == location::FollowAndRotate)
ChangeModelView(m_position, m_drawDirection,
m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition, kDoNotChangeZoom);
m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), kDoNotChangeZoom);
}
}
else if (m_mode == location::PendingPosition || m_mode == location::NotFollowNoPosition)
@ -525,7 +525,7 @@ void MyPositionController::OnCompassTapped()
if (m_mode == location::FollowAndRotate)
{
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_centerPixelPosition, kDoNotChangeZoom);
ChangeModelView(m_position, 0.0, m_pixelRect.Center(), kDoNotChangeZoom);
}
else
{
@ -567,7 +567,7 @@ void MyPositionController::UpdateViewport(int zoomLevel)
ChangeModelView(m_position, zoomLevel);
else if (m_mode == location::FollowAndRotate)
ChangeModelView(m_position, m_drawDirection,
m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition, zoomLevel);
m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), zoomLevel);
}
m2::PointD MyPositionController::GetRotationPixelCenter() const
@ -658,7 +658,7 @@ void MyPositionController::ActivateRouting(int zoomLevel)
if (IsRotationAvailable())
{
ChangeMode(location::FollowAndRotate);
ChangeModelView(m_position, m_drawDirection, m_centerPixelPositionRouting, zoomLevel);
ChangeModelView(m_position, m_drawDirection, GetRoutingRotationPixelCenter(), zoomLevel);
}
else
{
@ -675,7 +675,7 @@ void MyPositionController::DeactivateRouting()
m_isInRouting = false;
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_centerPixelPosition, kDoNotChangeZoom);
ChangeModelView(m_position, 0.0, m_pixelRect.Center(), kDoNotChangeZoom);
}
}

View file

@ -47,7 +47,7 @@ public:
bool isFirstLaunch, bool isRoutingActive);
~MyPositionController();
void OnNewPixelRect();
void OnNewViewportRect();
void UpdatePixelPosition(ScreenBase const & screen);
void SetListener(ref_ptr<Listener> listener);
@ -153,8 +153,6 @@ private:
double m_lastLocationTimestamp;
m2::RectD m_pixelRect;
m2::PointD m_centerPixelPositionRouting;
m2::PointD m_centerPixelPosition;
double m_positionYOffset;
bool m_isVisible;

View file

@ -19,23 +19,39 @@
namespace df
{
double const kDefault3dScale = 1.0;
Navigator::Navigator()
: m_InAction(false)
{
}
void Navigator::SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect)
void Navigator::SetFromScreen(ScreenBase const & screen)
{
m2::RectD const & worldR = df::GetWorldRect();
VisualParams const & p = VisualParams::Instance();
SetFromScreen(screen, p.GetTileSize(), p.GetVisualScale());
}
m_Screen.SetFromRects(glbRect, pxRect);
m_Screen = ScaleInto(m_Screen, worldR);
void Navigator::SetFromScreen(ScreenBase const & screen, uint32_t tileSize, double visualScale)
{
ScreenBase tmp = ScaleInto(screen, df::GetWorldRect());
if (!CheckMaxScale(tmp, tileSize, visualScale))
{
int const scale = scales::GetUpperStyleScale() - 1;
m2::RectD newRect = df::GetRectForDrawScale(scale, screen.GetOrg());
newRect.Scale(m_Screen.GetScale3d());
CheckMinMaxVisibleScale(newRect, scale, m_Screen.GetScale3d());
tmp = m_Screen;
tmp.SetFromRect(m2::AnyRectD(newRect));
ASSERT(CheckMaxScale(tmp, tileSize, visualScale), ());
}
m_Screen = tmp;
if (!m_InAction)
{
m_StartScreen.SetFromRects(glbRect, pxRect);
m_StartScreen = ScaleInto(m_StartScreen, worldR);
}
m_StartScreen = tmp;
}
void Navigator::SetFromRect(m2::AnyRectD const & r)
@ -46,25 +62,9 @@ void Navigator::SetFromRect(m2::AnyRectD const & r)
void Navigator::SetFromRect(m2::AnyRectD const & r, uint32_t tileSize, double visualScale)
{
m2::RectD const & worldR = df::GetWorldRect();
ScreenBase tmp = m_Screen;
tmp.SetFromRect(r);
tmp = ScaleInto(tmp, worldR);
if (!CheckMaxScale(tmp, tileSize, visualScale))
{
int const scale = scales::GetUpperStyleScale() - 1;
m2::RectD newRect = df::GetRectForDrawScale(scale, r.Center());
CheckMinMaxVisibleScale(newRect, scale);
tmp = m_Screen;
tmp.SetFromRect(m2::AnyRectD(newRect));
ASSERT(CheckMaxScale(tmp, tileSize, visualScale), ());
}
m_Screen = tmp;
if (!m_InAction)
m_StartScreen = tmp;
SetFromScreen(tmp, tileSize, visualScale);
}
void Navigator::CenterViewport(m2::PointD const & p)
@ -85,25 +85,11 @@ void Navigator::OnSize(int w, int h)
{
m2::RectD const & worldR = df::GetWorldRect();
double const fov = m_Screen.GetAngleFOV();
double const rotation = m_Screen.GetRotationAngle();
if (m_Screen.isPerspective())
{
m_Screen.ResetPerspective();
m_StartScreen.ResetPerspective();
}
m_Screen.OnSize(0, 0, w, h);
m_Screen = ShrinkAndScaleInto(m_Screen, worldR);
m_StartScreen.OnSize(0, 0, w, h);
m_StartScreen = ShrinkAndScaleInto(m_StartScreen, worldR);
if (fov != 0.0)
{
m_Screen.ApplyPerspective(rotation, rotation, fov);
m_StartScreen.ApplyPerspective(rotation, rotation, fov);
}
}
m2::PointD Navigator::GtoP(m2::PointD const & pt) const
@ -194,6 +180,7 @@ bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2,
{
m2::PointD const center3d = oldPt1;
m2::PointD const center2d = screen.P3dtoP(center3d);
m2::PointD const centerG = screen.PtoG(center2d);
m2::PointD const offset = center2d - center3d;
math::Matrix<double, 3, 3> const newM =
screen.GtoPMatrix() * ScreenBase::CalcTransform(oldPt1 + offset, oldPt2 + offset,
@ -201,6 +188,7 @@ bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2,
doRotateScreen);
ScreenBase tmp = screen;
tmp.SetGtoPMatrix(newM);
tmp.MatchGandP3d(centerG, center3d);
if (!skipMinScaleAndBordersCheck && !CheckMinScale(tmp))
return false;
@ -291,9 +279,18 @@ bool Navigator::IsRotatingDuringScale() const
return m_IsRotatingDuringScale;
}
void Navigator::Enable3dMode(double currentRotationAngle, double maxRotationAngle, double angleFOV)
void Navigator::SetAutoPerspective(bool enable)
{
m_Screen.ApplyPerspective(currentRotationAngle, maxRotationAngle, angleFOV);
m_Screen.SetAutoPerspective(enable);
}
void Navigator::Enable3dMode()
{
if (m_Screen.isPerspective())
return;
double const angle = m_Screen.CalculateAutoPerspectiveAngle(m_Screen.GetScale());
if (angle > 0)
m_Screen.ApplyPerspective(angle, angle, m_Screen.GetAngleFOV());
}
void Navigator::SetRotationIn3dMode(double rotationAngle)
@ -317,36 +314,38 @@ m2::AnyRectD ToRotated(Navigator const & navigator, m2::RectD const & rect)
m2::RectD(-dx/2, -dy/2, dx/2, dy/2));
}
void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale)
void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale, double scale3d)
{
m2::RectD const minRect = df::GetRectForDrawScale(scales::GetUpperStyleScale(), rect.Center(), tileSize, visualScale);
m2::RectD minRect = df::GetRectForDrawScale(scales::GetUpperStyleScale(), rect.Center(), tileSize, visualScale);
minRect.Scale(scale3d);
if (minRect.IsRectInside(rect))
rect = minRect;
}
void CheckMinGlobalRect(m2::RectD & rect)
void CheckMinGlobalRect(m2::RectD & rect, double scale3d)
{
VisualParams const & p = VisualParams::Instance();
CheckMinGlobalRect(rect, p.GetTileSize(), p.GetVisualScale());
CheckMinGlobalRect(rect, p.GetTileSize(), p.GetVisualScale(), scale3d);
}
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale,
uint32_t tileSize, double visualScale)
uint32_t tileSize, double visualScale, double scale3d)
{
CheckMinGlobalRect(rect, tileSize, visualScale);
CheckMinGlobalRect(rect, tileSize, visualScale, scale3d);
int scale = df::GetDrawTileScale(rect, tileSize, visualScale);
if (maxScale != -1 && scale > maxScale)
{
// limit on passed maximal scale
m2::PointD const c = rect.Center();
rect = df::GetRectForDrawScale(maxScale, c, tileSize, visualScale);
rect.Scale(scale3d);
}
}
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale)
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale, double scale3d)
{
VisualParams const & p = VisualParams::Instance();
CheckMinMaxVisibleScale(rect, maxScale, p.GetTileSize(), p.GetVisualScale());
CheckMinMaxVisibleScale(rect, maxScale, p.GetTileSize(), p.GetVisualScale(), scale3d);
}
} // namespace df

View file

@ -10,6 +10,8 @@
namespace df
{
extern double const kDefault3dScale;
/// Calculates screen parameters in navigation (dragging, scaling, etc.).
class Navigator
{
@ -17,9 +19,10 @@ public:
Navigator();
void SetFromRect(m2::AnyRectD const & r);
void CenterViewport(m2::PointD const & p);
void SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect);
void SetFromRect(m2::AnyRectD const & r, uint32_t tileSize, double visualScale);
void SetFromScreen(ScreenBase const & screen);
void SetFromScreen(ScreenBase const & screen, uint32_t tileSize, double visualScale);
void CenterViewport(m2::PointD const & p);
void OnSize(int w, int h);
@ -43,7 +46,8 @@ public:
void Scale(m2::PointD const & pixelScaleCenter, double factor);
bool InAction() const;
void Enable3dMode(double currentRotationAngle, double maxRotationAngle, double angleFOV);
void SetAutoPerspective(bool enable);
void Enable3dMode();
void SetRotationIn3dMode(double rotationAngle);
void Disable3dMode();
@ -75,10 +79,10 @@ private:
};
m2::AnyRectD ToRotated(Navigator const & navigator, m2::RectD const & rect);
void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale);
void CheckMinGlobalRect(m2::RectD & rect);
void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale, double scale3d = kDefault3dScale);
void CheckMinGlobalRect(m2::RectD & rect, double scale3d = kDefault3dScale);
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/, uint32_t tileSize, double visualScale);
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/);
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/, uint32_t tileSize, double visualScale, double scale3d = kDefault3dScale);
void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/, double scale3d = kDefault3dScale);
}

View file

@ -203,10 +203,10 @@ void RuleDrawer::operator()(FeatureType const & f)
double const lat = MercatorBounds::YToLat(featureCenter.y);
m2::RectD rectMercator = MercatorBounds::MetresToXY(lon, lat, heightInMeters);
areaHeight = m2::PointD(rectMercator.SizeX(), rectMercator.SizeY()).Length();
areaHeight = (rectMercator.SizeX() + rectMercator.SizeY()) / 2.0;
rectMercator = MercatorBounds::MetresToXY(lon, lat, minHeigthInMeters);
areaMinHeight = m2::PointD(rectMercator.SizeX(), rectMercator.SizeY()).Length();
areaMinHeight = (rectMercator.SizeX() + rectMercator.SizeY()) / 2.0;
}
bool applyPointStyle = s.PointStyleExists();

View file

@ -13,6 +13,12 @@ namespace df
string const kPrettyMoveAnim = "PrettyMove";
string const kPrettyFollowAnim = "PrettyFollow";
drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen)
{
return GetPrettyMoveAnimation(startScreen, startScreen.GetScale(), endScreen.GetScale(),
startScreen.GetOrg(), endScreen.GetOrg());
}
drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen,
m2::AnyRectD const & startRect, m2::AnyRectD const & endRect)
{
@ -25,7 +31,7 @@ drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen,
drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, double startScale, double endScale,
m2::PointD const & startPt, m2::PointD const & endPt)
{
double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, endPt, screen);
double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, endPt, screen.PixelRectIn3d(), startScale);
double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0;
auto sequenceAnim = make_unique_dp<SequenceAnimation>();
@ -50,28 +56,36 @@ drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, d
return sequenceAnim;
}
drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & screen, double startScale, double endScale,
m2::PointD const & startPt, m2::PointD const & userPos,
drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos, double targetScale,
double targetAngle, m2::PointD const & endPixelPos)
{
double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, userPos, screen);
double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0;
auto sequenceAnim = make_unique_dp<SequenceAnimation>();
sequenceAnim->SetCustomType(kPrettyFollowAnim);
m2::RectD const viewportRect = startScreen.PixelRectIn3d();
ScreenBase tmp = startScreen;
tmp.MatchGandP3d(userPos, viewportRect.Center());
double const moveDuration = PositionInterpolator::GetMoveDuration(startScreen.GetOrg(), tmp.GetOrg(), startScreen);
double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0;
tmp = startScreen;
tmp.SetScale(startScreen.GetScale() * scaleFactor);
auto zoomOutAnim = make_unique_dp<MapLinearAnimation>();
zoomOutAnim->SetScale(startScale, startScale * scaleFactor);
zoomOutAnim->SetScale(startScreen.GetScale(), tmp.GetScale());
zoomOutAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5);
//TODO (in future): Pass fixed duration instead of screen.
tmp.MatchGandP3d(userPos, viewportRect.Center());
auto moveAnim = make_unique_dp<MapLinearAnimation>();
moveAnim->SetMove(startPt, userPos, screen);
moveAnim->SetMove(startScreen.GetOrg(), tmp.GetOrg(), viewportRect, tmp.GetScale());
moveAnim->SetMaxDuration(kMaxAnimationTimeSec);
auto followAnim = make_unique_dp<MapFollowAnimation>(userPos, startScale * scaleFactor, endScale,
screen.GetAngle(), targetAngle,
screen.PixelRect().Center(), endPixelPos, screen.PixelRect());
auto followAnim = make_unique_dp<MapFollowAnimation>(tmp, userPos, endPixelPos,
tmp.GetScale(), targetScale,
tmp.GetAngle(), targetAngle);
followAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5);
sequenceAnim->AddAnimation(move(zoomOutAnim));
@ -80,6 +94,19 @@ drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & screen,
return sequenceAnim;
}
drape_ptr<MapLinearAnimation> GetRectAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen)
{
auto anim = make_unique_dp<MapLinearAnimation>();
anim->SetRotate(startScreen.GetAngle(), endScreen.GetAngle());
anim->SetMove(startScreen.GetOrg(), endScreen.GetOrg(),
startScreen.PixelRectIn3d(), (startScreen.GetScale() + endScreen.GetScale()) / 2.0);
anim->SetScale(startScreen.GetScale(), endScreen.GetScale());
anim->SetMaxScaleDuration(kMaxAnimationTimeSec);
return anim;
}
drape_ptr<MapLinearAnimation> GetSetRectAnimation(ScreenBase const & screen,
m2::AnyRectD const & startRect, m2::AnyRectD const & endRect)
{
@ -99,9 +126,8 @@ drape_ptr<MapLinearAnimation> GetSetRectAnimation(ScreenBase const & screen,
drape_ptr<MapFollowAnimation> GetFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos,
double targetScale, double targetAngle, m2::PointD const & endPixelPos)
{
auto anim = make_unique_dp<MapFollowAnimation>(userPos, startScreen.GetScale(), targetScale,
startScreen.GetAngle(), targetAngle,
startScreen.GtoP(userPos), endPixelPos, startScreen.PixelRect());
auto anim = make_unique_dp<MapFollowAnimation>(startScreen, userPos, endPixelPos, startScreen.GetScale(), targetScale,
startScreen.GetAngle(), targetAngle);
anim->SetMaxDuration(kMaxAnimationTimeSec);
return anim;
@ -113,9 +139,8 @@ drape_ptr<MapScaleAnimation> GetScaleAnimation(ScreenBase const & startScreen, m
ScreenBase endScreen = startScreen;
ApplyScale(pxScaleCenter, factor, endScreen);
m2::PointD const offset = startScreen.PixelRect().Center() - startScreen.P3dtoP(pxScaleCenter);
auto anim = make_unique_dp<MapScaleAnimation>(startScreen.GetScale(), endScreen.GetScale(),
glbScaleCenter, offset);
glbScaleCenter, pxScaleCenter);
anim->SetMaxDuration(kMaxAnimationTimeSec);
return anim;

View file

@ -15,15 +15,16 @@ class MapLinearAnimation;
class MapFollowAnimation;
class MapScaleAnimation;
drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen);
drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen,
m2::AnyRectD const & startRect, m2::AnyRectD const & endRect);
drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, double startScale, double endScale,
m2::PointD const & startPt, m2::PointD const & endPt);
drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & screen, double startScale, double endScale,
m2::PointD const & startPt, m2::PointD const & userPos,
double targetAngle, m2::PointD const & endPixelPos);
drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos,
double targetScale, double targetAngle, m2::PointD const & endPixelPos);
drape_ptr<MapLinearAnimation> GetRectAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen);
drape_ptr<MapLinearAnimation> GetSetRectAnimation(ScreenBase const & screen,
m2::AnyRectD const & startRect, m2::AnyRectD const & endRect);

View file

@ -240,13 +240,10 @@ ScreenBase const ShrinkAndScaleInto(ScreenBase const & screen, m2::RectD boundRe
bool ApplyScale(m2::PointD const & pixelScaleCenter, double factor, ScreenBase & screen)
{
m2::PointD const globalScaleCenter = screen.PtoG(screen.P3dtoP(pixelScaleCenter));
m2::PointD const pixelCenterOffset = screen.PixelRect().Center() - screen.P3dtoP(pixelScaleCenter);
ScreenBase tmp = screen;
tmp.Scale(factor);
m2::PointD newCenter = tmp.PtoG(tmp.GtoP(globalScaleCenter) + pixelCenterOffset);
tmp.SetOrg(newCenter);
tmp.MatchGandP3d(globalScaleCenter, pixelScaleCenter);
if (!CheckMinScale(tmp))
return false;

View file

@ -2,7 +2,6 @@
#include "drape_frontend/animation/linear_animation.hpp"
#include "drape_frontend/animation/scale_animation.hpp"
#include "drape_frontend/animation/follow_animation.hpp"
#include "drape_frontend/animation/perspective_animation.hpp"
#include "drape_frontend/animation/sequence_animation.hpp"
#include "drape_frontend/animation_constants.hpp"
#include "drape_frontend/animation_system.hpp"
@ -147,12 +146,11 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
swap(m_events, events);
}
m2::RectD const prevPixelRect = GetCurrentScreen().PixelRect();
m_modelViewChanged = !events.empty() || m_state == STATE_SCALE || m_state == STATE_DRAG;
for (UserEvent const & e : events)
{
if (m_perspectiveAnimation && FilterEventWhile3dAnimation(e.m_type))
continue;
bool breakAnim = false;
switch (e.m_type)
@ -163,7 +161,6 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
break;
case UserEvent::EVENT_RESIZE:
m_navigator.OnSize(e.m_resize.m_width, e.m_resize.m_height);
m_viewportChanged = true;
breakAnim = true;
TouchCancel(m_touches);
if (m_state == STATE_DOUBLE_TAP_HOLD)
@ -174,11 +171,6 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
TouchCancel(m_touches);
break;
case UserEvent::EVENT_SET_RECT:
if (m_perspectiveAnimation)
{
m_pendingEvent.reset(new UserEvent(e.m_rectEvent));
break;
}
breakAnim = SetRect(e.m_rectEvent.m_rect, e.m_rectEvent.m_zoom, e.m_rectEvent.m_applyRotation, e.m_rectEvent.m_isAnim);
TouchCancel(m_touches);
break;
@ -194,8 +186,9 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
ScreenBase const & screen = m_navigator.Screen();
if (screen.isPerspective())
{
m2::PointD pt = screen.P3dtoP(screen.PixelRectIn3d().Center());
breakAnim = SetFollowAndRotate(screen.PtoG(pt), pt, e.m_rotate.m_targetAzimut, kDoNotChangeZoom, true);
m2::PointD pt = screen.PixelRectIn3d().Center();
breakAnim = SetFollowAndRotate(screen.PtoG(screen.P3dtoP(pt)), pt,
e.m_rotate.m_targetAzimut, kDoNotChangeZoom, true);
}
else
{
@ -211,27 +204,8 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
e.m_followAndRotate.m_isAnim);
TouchCancel(m_touches);
break;
case UserEvent::EVENT_ENABLE_PERSPECTIVE:
SetEnable3dMode(e.m_enable3dMode.m_rotationAngle, e.m_enable3dMode.m_angleFOV,
e.m_enable3dMode.m_isAnim, e.m_enable3dMode.m_immediatelyStart);
m_discardedFOV = m_discardedAngle = 0.0;
break;
case UserEvent::EVENT_DISABLE_PERSPECTIVE:
SetDisable3dModeAnimation();
m_discardedFOV = m_discardedAngle = 0.0;
break;
case UserEvent::EVENT_SWITCH_VIEW_MODE:
if (e.m_switchViewMode.m_to2d)
{
m_discardedFOV = m_navigator.Screen().GetAngleFOV();
m_discardedAngle = m_navigator.Screen().GetRotationAngle();
SetDisable3dModeAnimation();
}
else if (m_discardedFOV > 0.0)
{
SetEnable3dMode(m_discardedAngle, m_discardedFOV, true /* isAnim */, true /* immediatelyStart */);
m_discardedFOV = m_discardedAngle = 0.0;
}
case UserEvent::EVENT_AUTO_PERSPECTIVE:
SetAutoPerspective(e.m_autoPerspective.m_isAutoPerspective);
break;
default:
ASSERT(false, ());
@ -244,21 +218,6 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
ApplyAnimations();
if (m_perspectiveAnimation)
{
TouchCancel(m_touches);
}
else
{
if (m_pendingEvent != nullptr && m_pendingEvent->m_type == UserEvent::EVENT_SET_RECT)
{
SetRect(m_pendingEvent->m_rectEvent.m_rect, m_pendingEvent->m_rectEvent.m_zoom,
m_pendingEvent->m_rectEvent.m_applyRotation, m_pendingEvent->m_rectEvent.m_isAnim);
m_pendingEvent.reset();
m_modelViewChanged = true;
}
}
if (GetValidTouchesCount(m_touches) == 1)
{
if (m_state == STATE_WAIT_DOUBLE_TAP)
@ -267,10 +226,14 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
DetectLongTap(m_touches[0]);
}
if (m_modelViewChanged)
m_animationSystem.UpdateLastScreen(GetCurrentScreen());
modelViewChanged = m_modelViewChanged;
viewportChanged = m_viewportChanged;
double const kEps = 1e-5;
viewportChanged = !m2::IsEqualSize(prevPixelRect, GetCurrentScreen().PixelRect(), kEps, kEps);
m_modelViewChanged = false;
m_viewportChanged = false;
return m_navigator.Screen();
}
@ -279,31 +242,9 @@ void UserEventStream::ApplyAnimations()
{
if (m_animationSystem.AnimationExists(Animation::MapPlane))
{
m2::AnyRectD rect;
if (m_animationSystem.GetRect(GetCurrentScreen(), rect))
m_navigator.SetFromRect(rect);
Animation::SwitchPerspectiveParams switchPerspective;
if (m_animationSystem.SwitchPerspective(switchPerspective))
{
if (switchPerspective.m_enable)
{
m_navigator.Enable3dMode(switchPerspective.m_startAngle, switchPerspective.m_endAngle,
switchPerspective.m_angleFOV);
}
else
{
m_navigator.Disable3dMode();
}
m_viewportChanged = true;
}
double perspectiveAngle;
if (m_animationSystem.GetPerspectiveAngle(perspectiveAngle) &&
GetCurrentScreen().isPerspective())
{
m_navigator.SetRotationIn3dMode(perspectiveAngle);
}
ScreenBase screen;
if (m_animationSystem.GetScreen(GetCurrentScreen(), screen))
m_navigator.SetFromScreen(screen);
m_modelViewChanged = true;
}
@ -361,82 +302,35 @@ bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor,
bool UserEventStream::SetCenter(m2::PointD const & center, int zoom, bool isAnim)
{
m2::PointD targetCenter = center;
ang::AngleD angle;
m2::RectD localRect;
ScreenBase const & currentScreen = GetCurrentScreen();
ScreenBase screen = currentScreen;
bool finishIn2d = false;
bool finishIn3d = false;
if (zoom != kDoNotChangeZoom)
{
bool const isScaleAllowableIn3d = IsScaleAllowableIn3d(zoom);
finishIn3d = m_discardedFOV > 0.0 && isScaleAllowableIn3d;
finishIn2d = currentScreen.isPerspective() && !isScaleAllowableIn3d;
if (finishIn3d)
screen.ApplyPerspective(m_discardedAngle, m_discardedAngle, m_discardedFOV);
else if (finishIn2d)
screen.ResetPerspective();
}
double const scale3d = screen.PixelRect().SizeX() / screen.PixelRectIn3d().SizeX();
ScreenBase screen = GetCurrentScreen();
if (zoom == kDoNotChangeZoom)
{
m2::AnyRectD const r = GetTargetRect();
angle = r.Angle();
localRect = r.GetLocalRect();
GetTargetScreen(screen);
screen.MatchGandP3d(center, screen.PixelRectIn3d().Center());
}
else
{
angle = screen.GlobalRect().Angle();
localRect = df::GetRectForDrawScale(zoom, center);
CheckMinGlobalRect(localRect);
CheckMinMaxVisibleScale(localRect, zoom);
localRect.Offset(-center);
localRect.Scale(scale3d);
double const aspectRatio = screen.PixelRect().SizeY() / screen.PixelRect().SizeX();
if (aspectRatio > 1.0)
localRect.Inflate(0.0, localRect.SizeY() * 0.5 * aspectRatio);
else
localRect.Inflate(localRect.SizeX() * 0.5 / aspectRatio, 0.0);
screen.SetFromParams(center, screen.GetAngle(), GetScale(zoom));
screen.MatchGandP3d(center, screen.PixelRectIn3d().Center());
}
if (screen.isPerspective())
{
double const centerOffset3d = localRect.SizeY() * (1.0 - 1.0 / (scale3d * cos(screen.GetRotationAngle()))) * 0.5;
targetCenter = targetCenter.Move(centerOffset3d, angle.cos(), -angle.sin());
}
ASSERT_GREATER_OR_EQUAL(zoom, scales::GetUpperWorldScale(), ());
ASSERT_LESS_OR_EQUAL(zoom, scales::GetUpperStyleScale(), ());
if (finishIn2d || finishIn3d)
{
double const scale = currentScreen.PixelRect().SizeX() / currentScreen.PixelRectIn3d().SizeX();
double const scaleToCurrent = finishIn2d ? scale : 1.0 / scale3d;
ShrinkAndScaleInto(screen, df::GetWorldRect());
double const currentGSizeY = localRect.SizeY() * scaleToCurrent;
targetCenter = targetCenter.Move((currentGSizeY - localRect.SizeY()) * 0.5,
angle.cos(), -angle.sin());
localRect.Scale(scaleToCurrent);
}
return SetRect(m2::AnyRectD(targetCenter, angle, localRect), isAnim);
return SetScreen(screen, isAnim);
}
bool UserEventStream::SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim)
{
CheckMinGlobalRect(rect);
CheckMinMaxVisibleScale(rect, zoom);
CheckMinGlobalRect(rect, kDefault3dScale);
CheckMinMaxVisibleScale(rect, zoom, kDefault3dScale);
m2::AnyRectD targetRect = applyRotation ? ToRotated(m_navigator, rect) : m2::AnyRectD(rect);
return SetRect(targetRect, isAnim);
}
bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim)
bool UserEventStream::SetScreen(ScreenBase const & endScreen, bool isAnim)
{
if (isAnim)
{
@ -446,17 +340,16 @@ bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim)
m_listener->OnAnimationStarted(animation);
};
m2::AnyRectD const startRect = GetCurrentRect();
ScreenBase const & screen = GetCurrentScreen();
drape_ptr<Animation> anim = GetSetRectAnimation(screen, startRect, rect);
drape_ptr<Animation> anim = GetRectAnimation(screen, endScreen);
if (!df::IsAnimationAllowed(anim->GetDuration(), screen))
{
anim.reset();
double const moveDuration = PositionInterpolator::GetMoveDuration(startRect.GlobalCenter(),
rect.GlobalCenter(), screen);
double const moveDuration = PositionInterpolator::GetMoveDuration(screen.GetOrg(),
endScreen.GetOrg(), screen);
if (moveDuration > kMaxAnimationTimeSec)
anim = GetPrettyMoveAnimation(screen, startRect, rect);
anim = GetPrettyMoveAnimation(screen, endScreen);
}
if (anim != nullptr)
@ -468,10 +361,19 @@ bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim)
}
ResetMapPlaneAnimations();
m_navigator.SetFromRect(rect);
m_navigator.SetFromScreen(endScreen);
return true;
}
bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim)
{
ScreenBase tmp = GetCurrentScreen();
tmp.SetFromRects(rect, tmp.PixelRectIn3d());
tmp.MatchGandP3d(rect.GlobalCenter(), tmp.PixelRectIn3d().Center());
return SetScreen(tmp, isAnim);
}
bool UserEventStream::InterruptFollowAnimations(bool force)
{
Animation const * followAnim = m_animationSystem.FindAnimation<MapFollowAnimation>(Animation::MapFollow);
@ -497,22 +399,24 @@ bool UserEventStream::InterruptFollowAnimations(bool force)
bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD const & pixelPos,
double azimuth, int preferredZoomLevel, bool isAnim)
{
// Extract target local rect from current animation or calculate it from preferredZoomLevel
// to preserve final scale.
m2::RectD targetLocalRect;
if (preferredZoomLevel != kDoNotChangeZoom)
ScreenBase const & currentScreen = GetCurrentScreen();
ScreenBase screen = currentScreen;
if (preferredZoomLevel == kDoNotChangeZoom)
{
ScreenBase newScreen = GetCurrentScreen();
m2::RectD r = df::GetRectForDrawScale(preferredZoomLevel, m2::PointD::Zero());
CheckMinGlobalRect(r);
CheckMinMaxVisibleScale(r, preferredZoomLevel);
newScreen.SetFromRect(m2::AnyRectD(r));
targetLocalRect = newScreen.GlobalRect().GetLocalRect();
GetTargetScreen(screen);
screen.SetAngle(-azimuth);
}
else
{
targetLocalRect = GetTargetRect().GetLocalRect();
screen.SetFromParams(userPos, -azimuth, GetScale(preferredZoomLevel));
}
screen.MatchGandP3d(userPos, pixelPos);
ASSERT_GREATER_OR_EQUAL(preferredZoomLevel, scales::GetUpperWorldScale(), ());
ASSERT_LESS_OR_EQUAL(preferredZoomLevel, scales::GetUpperStyleScale(), ());
ShrinkAndScaleInto(screen, df::GetWorldRect());
if (isAnim)
{
@ -527,26 +431,21 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD
};
drape_ptr<Animation> anim;
ScreenBase const & screen = m_navigator.Screen();
double const targetScale = CalculateScale(screen.PixelRect(), targetLocalRect);
m2::PointD const startPt = GetCurrentRect().GlobalCenter();
bool const changeZoom = preferredZoomLevel != kDoNotChangeZoom;
double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, userPos, screen);
double const moveDuration = PositionInterpolator::GetMoveDuration(currentScreen.GetOrg(), screen.GetOrg(),
currentScreen.PixelRectIn3d(),
(currentScreen.GetScale() + screen.GetScale()) / 2.0);
if (moveDuration > kMaxAnimationTimeSec)
{
// Run pretty move animation if we are far from userPos.
double const startScale = CalculateScale(screen.PixelRect(), GetCurrentRect().GetLocalRect());
anim = GetPrettyFollowAnimation(screen, startScale, targetScale, startPt, userPos, -azimuth, pixelPos);
anim = GetPrettyFollowAnimation(currentScreen, userPos, screen.GetScale(), -azimuth, pixelPos);
}
else
{
// Run follow-and-rotate animation.
anim = GetFollowAnimation(screen, userPos, targetScale, -azimuth, pixelPos);
anim = GetFollowAnimation(currentScreen, userPos, screen.GetScale(), -azimuth, pixelPos);
}
if (changeZoom)
if (preferredZoomLevel != kDoNotChangeZoom)
{
anim->SetCouldBeInterrupted(false);
anim->SetCouldBeBlended(false);
@ -558,70 +457,18 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD
}
ResetMapPlaneAnimations();
m2::PointD const center = MapFollowAnimation::CalculateCenter(m_navigator.Screen(), userPos, pixelPos, -azimuth);
m_navigator.SetFromRect(m2::AnyRectD(center, -azimuth, targetLocalRect));
m_navigator.SetFromScreen(screen);
return true;
}
bool UserEventStream::FilterEventWhile3dAnimation(UserEvent::EEventType type) const
void UserEventStream::SetAutoPerspective(bool isAutoPerspective)
{
return type != UserEvent::EVENT_RESIZE && type != UserEvent::EVENT_SET_RECT &&
type != UserEvent::EVENT_ENABLE_PERSPECTIVE &&
type != UserEvent::EVENT_DISABLE_PERSPECTIVE &&
type != UserEvent::EVENT_SWITCH_VIEW_MODE;
}
void UserEventStream::SetEnable3dMode(double maxRotationAngle, double angleFOV,
bool isAnim, bool immediatelyStart)
{
ResetAnimationsBeforeSwitch3D();
if (immediatelyStart)
InterruptFollowAnimations(true /* force */);
double const startAngle = isAnim ? 0.0 : maxRotationAngle;
double const endAngle = maxRotationAngle;
auto anim = make_unique_dp<PerspectiveSwitchAnimation>(startAngle, endAngle, angleFOV);
anim->SetOnStartAction([this, startAngle, endAngle, angleFOV](ref_ptr<Animation>)
{
m_perspectiveAnimation = true;
});
anim->SetOnFinishAction([this](ref_ptr<Animation>)
{
m_perspectiveAnimation = false;
});
if (immediatelyStart)
m_animationSystem.CombineAnimation(move(anim));
if (isAutoPerspective)
m_navigator.Enable3dMode();
else
m_animationSystem.PushAnimation(move(anim));
}
void UserEventStream::SetDisable3dModeAnimation()
{
ResetAnimationsBeforeSwitch3D();
InterruptFollowAnimations(true /* force */);
if (m_discardedFOV > 0.0 && IsScaleAllowableIn3d(GetDrawTileScale(GetCurrentScreen())))
{
m_discardedFOV = m_discardedAngle = 0.0;
m_listener->OnPerspectiveSwitchRejected();
return;
}
double const startAngle = m_navigator.Screen().GetRotationAngle();
double const endAngle = 0.0;
auto anim = make_unique_dp<PerspectiveSwitchAnimation>(startAngle, endAngle, m_navigator.Screen().GetAngleFOV());
anim->SetOnStartAction([this](ref_ptr<Animation>)
{
m_perspectiveAnimation = true;
});
anim->SetOnFinishAction([this](ref_ptr<Animation>)
{
m_perspectiveAnimation = false;
});
m_animationSystem.CombineAnimation(move(anim));
m_navigator.Disable3dMode();
m_navigator.SetAutoPerspective(isAutoPerspective);
return;
}
void UserEventStream::ResetAnimations(Animation::Type animType, bool finishAll)
@ -648,24 +495,21 @@ void UserEventStream::ResetMapPlaneAnimations()
ApplyAnimations();
}
void UserEventStream::ResetAnimationsBeforeSwitch3D()
{
ResetAnimations(Animation::MapLinear);
ResetAnimations(Animation::Sequence, kPrettyMoveAnim);
ResetAnimations(Animation::MapScale);
ResetAnimations(Animation::MapPerspective, true /* finishAll */);
}
m2::AnyRectD UserEventStream::GetCurrentRect() const
{
return m_navigator.Screen().GlobalRect();
}
void UserEventStream::GetTargetScreen(ScreenBase & screen) const
{
m_animationSystem.GetTargetScreen(m_navigator.Screen(), screen);
}
m2::AnyRectD UserEventStream::GetTargetRect() const
{
m2::AnyRectD targetRect;
m_animationSystem.GetTargetRect(m_navigator.Screen(), targetRect);
return targetRect;
ScreenBase targetScreen;
m_animationSystem.GetTargetScreen(m_navigator.Screen(), targetScreen);
return targetScreen.GlobalRect();
}
bool UserEventStream::ProcessTouch(TouchEvent const & touch)
@ -1169,7 +1013,7 @@ void UserEventStream::EndTapDetector(Touch const & touch)
void UserEventStream::CancelTapDetector()
{
TEST_CALL(CANCEL_TAP_DETECTOR);
ASSERT(m_state == STATE_TAP_DETECTION || m_state == STATE_WAIT_DOUBLE_TAP, ());
ASSERT(m_state == STATE_TAP_DETECTION || m_state == STATE_WAIT_DOUBLE_TAP || m_state == STATE_WAIT_DOUBLE_TAP_HOLD, ());
m_state = STATE_EMPTY;
}
@ -1219,7 +1063,7 @@ void UserEventStream::UpdateDoubleTapAndHold(Touch const & touch)
TEST_CALL(DOUBLE_TAP_AND_HOLD);
ASSERT_EQUAL(m_state, STATE_DOUBLE_TAP_HOLD, ());
float const kPowerModifier = 10.0f;
float const scaleFactor = exp(kPowerModifier * (touch.m_location.y - m_startDoubleTapAndHold.y) / GetCurrentScreen().PixelRect().SizeY());
float const scaleFactor = exp(kPowerModifier * (touch.m_location.y - m_startDoubleTapAndHold.y) / GetCurrentScreen().PixelRectIn3d().SizeY());
m_startDoubleTapAndHold = touch.m_location;
m2::PointD scaleCenter = m_startDragOrg;
@ -1247,11 +1091,6 @@ bool UserEventStream::IsWaitingForActionCompletion() const
return m_state != STATE_EMPTY;
}
bool UserEventStream::IsInPerspectiveAnimation() const
{
return m_perspectiveAnimation;
}
void UserEventStream::SetKineticScrollEnabled(bool enabled)
{
m_kineticScrollEnabled = enabled;

View file

@ -145,32 +145,13 @@ struct FollowAndRotateEvent
bool m_isAnim;
};
struct EnablePerspectiveEvent
struct SetAutoPerspectiveEvent
{
EnablePerspectiveEvent(double rotationAngle, double angleFOV,
bool isAnim, bool immediatelyStart)
: m_isAnim(isAnim)
, m_immediatelyStart(immediatelyStart)
, m_rotationAngle(rotationAngle)
, m_angleFOV(angleFOV)
SetAutoPerspectiveEvent(bool isAutoPerspective)
: m_isAutoPerspective(isAutoPerspective)
{}
bool m_isAnim;
bool m_immediatelyStart;
double m_rotationAngle;
double m_angleFOV;
};
struct DisablePerspectiveEvent
{
DisablePerspectiveEvent() {}
};
struct SwitchViewModeEvent
{
SwitchViewModeEvent(bool to2d): m_to2d(to2d) {}
bool m_to2d;
bool m_isAutoPerspective;
};
struct RotateEvent
@ -200,9 +181,7 @@ struct UserEvent
EVENT_RESIZE,
EVENT_ROTATE,
EVENT_FOLLOW_AND_ROTATE,
EVENT_ENABLE_PERSPECTIVE,
EVENT_DISABLE_PERSPECTIVE,
EVENT_SWITCH_VIEW_MODE
EVENT_AUTO_PERSPECTIVE
};
UserEvent(TouchEvent const & e) : m_type(EVENT_TOUCH) { m_touchEvent = e; }
@ -213,9 +192,7 @@ struct UserEvent
UserEvent(ResizeEvent const & e) : m_type(EVENT_RESIZE) { m_resize = e; }
UserEvent(RotateEvent const & e) : m_type(EVENT_ROTATE) { m_rotate = e; }
UserEvent(FollowAndRotateEvent const & e) : m_type(EVENT_FOLLOW_AND_ROTATE) { m_followAndRotate = e; }
UserEvent(EnablePerspectiveEvent const & e) : m_type(EVENT_ENABLE_PERSPECTIVE) { m_enable3dMode = e; }
UserEvent(DisablePerspectiveEvent const & e) : m_type(EVENT_DISABLE_PERSPECTIVE) { m_disable3dMode = e; }
UserEvent(SwitchViewModeEvent const & e) : m_type(EVENT_SWITCH_VIEW_MODE) { m_switchViewMode = e; }
UserEvent(SetAutoPerspectiveEvent const & e) : m_type(EVENT_AUTO_PERSPECTIVE) { m_autoPerspective = e; }
EEventType m_type;
union
@ -228,9 +205,7 @@ struct UserEvent
ResizeEvent m_resize;
RotateEvent m_rotate;
FollowAndRotateEvent m_followAndRotate;
EnablePerspectiveEvent m_enable3dMode;
DisablePerspectiveEvent m_disable3dMode;
SwitchViewModeEvent m_switchViewMode;
SetAutoPerspectiveEvent m_autoPerspective;
};
};
@ -259,7 +234,6 @@ public:
virtual void OnAnimatedScaleEnded() = 0;
virtual void OnAnimationStarted(ref_ptr<Animation> anim) = 0;
virtual void OnPerspectiveSwitchRejected() = 0;
virtual void OnTouchMapAction() = 0;
};
@ -269,9 +243,9 @@ public:
ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged);
ScreenBase const & GetCurrentScreen() const;
void GetTargetScreen(ScreenBase & screen) const;
m2::AnyRectD GetTargetRect() const;
bool IsInUserAction() const;
bool IsInPerspectiveAnimation() const;
bool IsWaitingForActionCompletion() const;
void SetListener(ref_ptr<Listener> listener) { m_listener = listener; }
@ -306,13 +280,10 @@ private:
bool SetCenter(m2::PointD const & center, int zoom, bool isAnim);
bool SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim);
bool SetRect(m2::AnyRectD const & rect, bool isAnim);
bool SetScreen(ScreenBase const & screen, bool isAnim);
bool SetFollowAndRotate(m2::PointD const & userPos, m2::PointD const & pixelPos,
double azimuth, int preferredZoomLevel, bool isAnim);
bool FilterEventWhile3dAnimation(UserEvent::EEventType type) const;
void SetEnable3dMode(double maxRotationAngle, double angleFOV,
bool isAnim, bool immediatelyStart);
void SetDisable3dModeAnimation();
void SetAutoPerspective(bool isAutoPerspective);
m2::AnyRectD GetCurrentRect() const;
@ -357,7 +328,6 @@ private:
void ResetAnimations(Animation::Type animType, bool finishAll = false);
void ResetAnimations(Animation::Type animType, string const & customType, bool finishAll = false);
void ResetMapPlaneAnimations();
void ResetAnimationsBeforeSwitch3D();
bool InterruptFollowAnimations(bool force);
list<UserEvent> m_events;
@ -383,12 +353,8 @@ private:
AnimationSystem & m_animationSystem;
bool m_modelViewChanged = false;
bool m_viewportChanged = false;
bool m_perspectiveAnimation = false;
unique_ptr<UserEvent> m_pendingEvent;
double m_discardedFOV = 0.0;
double m_discardedAngle = 0.0;
ref_ptr<Listener> m_listener;

View file

@ -6,6 +6,8 @@
#include "geometry/mercator.hpp"
#include "indexer/scales.hpp"
#include "std/limits.hpp"
#include "std/algorithm.hpp"
@ -270,4 +272,14 @@ int GetDrawTileScale(m2::RectD const & r)
return GetDrawTileScale(r, p.GetTileSize(), p.GetVisualScale());
}
double GetZoomLevel(double scale)
{
return my::clamp(fabs(log(scale) / log(2.0)), 1, scales::GetUpperStyleScale());
}
double GetScale(double zoomLevel)
{
return pow(2.0, -zoomLevel);
}
} // namespace df

View file

@ -75,4 +75,7 @@ m2::RectD GetRectForDrawScale(double drawScale, m2::PointD const & center);
int CalculateTileSize(int screenWidth, int screenHeight);
double GetZoomLevel(double scale);
double GetScale(double zoomLevel);
} // namespace df

View file

@ -287,6 +287,12 @@ namespace m2
return true;
}
template <typename T>
inline bool IsEqualSize(Rect<T> const & r1, Rect<T> const & r2, double epsX, double epsY)
{
return fabs(r1.SizeX() - r2.SizeX()) < epsX && fabs(r1.SizeY() - r2.SizeY()) < epsY;
}
template <typename T>
inline m2::Rect<T> const Add(m2::Rect<T> const & r, m2::Point<T> const & p)
{

View file

@ -7,26 +7,33 @@
#include "std/cmath.hpp"
double constexpr kPerspectiveAngleFOV = math::pi / 3.0;
double constexpr kMaxPerspectiveAngle1 = math::pi4;
double constexpr kMaxPerspectiveAngle2 = math::pi * 55.0 / 180.0;
double constexpr kStartPerspectiveScale1 = 1.7e-5;
double constexpr kEndPerspectiveScale1 = 0.3e-5;
double constexpr kEndPerspectiveScale2 = 0.13e-5;
ScreenBase::ScreenBase() :
m_PixelRect(0, 0, 640, 480),
m_ViewportRect(0, 0, 640, 480),
m_PixelRect(m_ViewportRect),
m_Scale(0.1),
m_Angle(0.0),
m_Org(320, 240),
m_3dFOV(0.0),
m_3dFOV(kPerspectiveAngleFOV),
m_3dNearZ(0.001),
m_3dFarZ(0.0),
m_3dAngleX(0.0),
m_3dMaxAngleX(0.0),
m_3dScaleX(1.0),
m_3dScaleY(1.0),
m_3dScale(1.0),
m_isPerspective(false),
m_isAutoPerspective(false),
m_GlobalRect(m_Org, ang::AngleD(0), m2::RectD(-320, -240, 320, 240)),
m_ClipRect(m2::RectD(0, 0, 640, 480))
{
m_GtoP = math::Identity<double, 3>();
m_PtoG = math::Identity<double, 3>();
// UpdateDependentParameters();
}
ScreenBase::ScreenBase(m2::RectI const & pxRect, m2::AnyRectD const & glbRect)
@ -37,7 +44,7 @@ ScreenBase::ScreenBase(m2::RectI const & pxRect, m2::AnyRectD const & glbRect)
ScreenBase::ScreenBase(ScreenBase const & s,
m2::PointD const & org, double scale, double angle)
: m_PixelRect(s.m_PixelRect),
: m_ViewportRect(s.m_ViewportRect),
m_Scale(scale), m_Angle(angle), m_Org(org)
{
UpdateDependentParameters();
@ -45,6 +52,8 @@ ScreenBase::ScreenBase(ScreenBase const & s,
void ScreenBase::UpdateDependentParameters()
{
m_PixelRect = CalculatePixelRect(m_Scale);
m_PtoG = math::Shift( /// 5. shifting on (E0, N0)
math::Rotate( /// 4. rotating on the screen angle
math::Scale( /// 3. scaling to translate pixel sizes to global
@ -73,6 +82,50 @@ void ScreenBase::UpdateDependentParameters()
m_GlobalRect = m2::AnyRectD(m_Org, m_Angle, m2::RectD(-szX, -szY, szX, szY));
m_ClipRect = m_GlobalRect.GetGlobalRect();
double const kEps = 1e-5;
double angle = CalculatePerspectiveAngle(m_Scale);
m_isPerspective = angle > 0.0;
if (fabs(angle - m_3dAngleX) > kEps)
{
m_3dMaxAngleX = angle;
m_3dScale = CalculateScale3d(angle);
SetRotationAngle(angle);
}
}
double ScreenBase::CalculateAutoPerspectiveAngle(double scale)
{
if (scale > kStartPerspectiveScale1)
return 0.0;
if (scale > kEndPerspectiveScale1)
{
double const k = (kStartPerspectiveScale1 - scale) / (kStartPerspectiveScale1 - kEndPerspectiveScale1);
return kMaxPerspectiveAngle1 * k;
}
if (scale > kEndPerspectiveScale2)
{
double const k = (kEndPerspectiveScale1 - scale) / (kEndPerspectiveScale1 - kEndPerspectiveScale2);
return kMaxPerspectiveAngle1 + (kMaxPerspectiveAngle2 - kMaxPerspectiveAngle1) * k;
}
return kMaxPerspectiveAngle2 * 0.99;
}
double ScreenBase::CalculatePerspectiveAngle(double scale) const
{
if (!m_isAutoPerspective)
return m_3dAngleX;
return CalculateAutoPerspectiveAngle(scale);
}
void ScreenBase::SetAutoPerspective(bool isAutoPerspective)
{
m_isAutoPerspective = isAutoPerspective;
UpdateDependentParameters();
}
void ScreenBase::SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect)
@ -92,6 +145,26 @@ void ScreenBase::SetFromRect(m2::AnyRectD const & glbRect)
SetFromRects(glbRect, m_PixelRect);
}
void ScreenBase::SetFromParams(m2::PointD const & org, double angle, double scale)
{
m_Scale = scale;
m_Angle = angle;
m_Org = org;
UpdateDependentParameters();
}
void ScreenBase::MatchGandP(m2::PointD const & g, m2::PointD const & p)
{
m2::PointD g_current = PtoG(p);
SetOrg(m_Org - g_current + g);
}
void ScreenBase::MatchGandP3d(m2::PointD const & g, m2::PointD const &p3d)
{
m2::PointD g_current = PtoG(P3dtoP(p3d));
SetOrg(m_Org - g_current + g);
}
void ScreenBase::SetOrg(m2::PointD const & p)
{
m_Org = p;
@ -124,7 +197,7 @@ void ScreenBase::Rotate(double angle)
void ScreenBase::OnSize(m2::RectI const & r)
{
m_PixelRect = m2::RectD(r);
m_ViewportRect = m2::RectD(r);
UpdateDependentParameters();
}
@ -133,11 +206,6 @@ void ScreenBase::OnSize(int x0, int y0, int w, int h)
OnSize(m2::RectI(x0, y0, x0 + w, y0 + h));
}
double ScreenBase::GetMinPixelRectSize() const
{
return min(m_PixelRect.SizeX(), m_PixelRect.SizeY());
}
void ScreenBase::SetScale(double scale)
{
m_Scale = scale;
@ -254,6 +322,32 @@ void ScreenBase::ExtractGtoPParams(MatrixT const & m,
dy = m(2, 1);
}
double ScreenBase::CalculateScale3d(double rotationAngle) const
{
double const halfFOV = m_3dFOV / 2.0;
double const cameraZ = 1.0 / tan(halfFOV);
// Ratio of the expanded plane's size to the original size.
double const y3dScale = cos(rotationAngle) + sin(rotationAngle) * tan(halfFOV + rotationAngle);
double const x3dScale = 1.0 + 2 * sin(rotationAngle) * cos(halfFOV) / (cameraZ * cos(halfFOV + rotationAngle));
return max(x3dScale, y3dScale);
}
m2::RectD ScreenBase::CalculatePixelRect(double scale) const
{
double const angle = CalculatePerspectiveAngle(scale);
if (angle > 0.0)
{
double const scale3d = CalculateScale3d(angle);
return m2::RectD(m2::PointD(0.0, 0.0),
m2::PointD(m_ViewportRect.maxX(), m_ViewportRect.maxY()) * scale3d);
}
return m_ViewportRect;
}
// Place the camera at the distance, where it gives the same view of plane as the
// orthogonal projection does. Calculate what part of the map would be visible,
// when it is rotated through maxRotationAngle around its near horizontal side.
@ -264,38 +358,28 @@ void ScreenBase::ApplyPerspective(double currentRotationAngle, double maxRotatio
ASSERT_GREATER_OR_EQUAL(maxRotationAngle, 0.0, ());
ASSERT_LESS(maxRotationAngle, math::pi2, ());
if (m_isPerspective)
ResetPerspective();
m_isPerspective = true;
m_isAutoPerspective = false;
m_3dMaxAngleX = maxRotationAngle;
m_3dAngleX = currentRotationAngle;
m_3dFOV = angleFOV;
double const halfFOV = m_3dFOV / 2.0;
double const cameraZ = 1.0 / tan(halfFOV);
double const old_dy = m_ViewportRect.SizeY() * (m_3dScale - 1.0);
// Ratio of the expanded plane's size to the original size.
m_3dScaleY = cos(m_3dMaxAngleX) + sin(m_3dMaxAngleX) * tan(halfFOV + m_3dMaxAngleX);
m_3dScaleX = 1.0 + 2 * sin(m_3dMaxAngleX) * cos(halfFOV) / (cameraZ * cos(halfFOV + m_3dMaxAngleX));
m_3dScaleX = m_3dScaleY = max(m_3dScaleX, m_3dScaleY);
double const dy = m_PixelRect.SizeY() * (m_3dScaleX - 1.0);
m_PixelRect.setMaxX(m_PixelRect.maxX() * m_3dScaleX);
m_PixelRect.setMaxY(m_PixelRect.maxY() * m_3dScaleY);
Move(0.0, dy / 2.0);
m_3dScale = CalculateScale3d(m_3dMaxAngleX);
double const new_dy = m_ViewportRect.SizeY() * (m_3dScale - 1.0);
SetRotationAngle(currentRotationAngle);
Move(0.0, (new_dy - old_dy) / 2.0);
}
// Place the camera at the distance, where it gives the same view of plane as the
// orthogonal projection does and rotate the map plane around its near horizontal side.
void ScreenBase::SetRotationAngle(double rotationAngle)
{
ASSERT(m_isPerspective, ());
ASSERT(rotationAngle == 0.0 || (rotationAngle > 0.0 && m_isPerspective), ());
ASSERT_GREATER_OR_EQUAL(rotationAngle, 0.0, ());
ASSERT_LESS_OR_EQUAL(rotationAngle, m_3dMaxAngleX, ());
@ -307,12 +391,12 @@ void ScreenBase::SetRotationAngle(double rotationAngle)
double const halfFOV = m_3dFOV / 2.0;
double const cameraZ = 1.0 / tan(halfFOV);
double const offsetZ = cameraZ + sin(m_3dAngleX) * m_3dScaleY;
double const offsetY = cos(m_3dAngleX) * m_3dScaleX - 1.0;
double const offsetZ = cameraZ + sin(m_3dAngleX) * m_3dScale;
double const offsetY = cos(m_3dAngleX) * m_3dScale - 1.0;
Matrix3dT scaleM = math::Identity<double, 4>();
scaleM(0, 0) = m_3dScaleX;
scaleM(1, 1) = m_3dScaleY;
scaleM(0, 0) = m_3dScale;
scaleM(1, 1) = m_3dScale;
Matrix3dT rotateM = math::Identity<double, 4>();
rotateM(1, 1) = cos(m_3dAngleX);
@ -325,7 +409,7 @@ void ScreenBase::SetRotationAngle(double rotationAngle)
translateM(3, 2) = offsetZ;
Matrix3dT projectionM = math::Zero<double, 4>();
m_3dFarZ = cameraZ + 2.0 * sin(m_3dAngleX) * m_3dScaleY;
m_3dFarZ = cameraZ + 2.0 * sin(m_3dAngleX) * m_3dScale;
projectionM(0, 0) = projectionM(1, 1) = cameraZ;
projectionM(2, 2) = m_3dAngleX != 0.0 ? (m_3dFarZ + m_3dNearZ) / (m_3dFarZ - m_3dNearZ)
: 0.0;
@ -340,18 +424,15 @@ void ScreenBase::SetRotationAngle(double rotationAngle)
void ScreenBase::ResetPerspective()
{
m_isPerspective = false;
m_isAutoPerspective = false;
double const dy = m_PixelRect.SizeY() * (1.0 - 1.0 / m_3dScaleX);
double const old_dy = m_ViewportRect.SizeY() * (m_3dScale - 1.0);
m_PixelRect.setMaxX(m_PixelRect.maxX() / m_3dScaleX);
m_PixelRect.setMaxY(m_PixelRect.maxY() / m_3dScaleY);
Move(0, -dy / 2.0);
m_3dScaleX = m_3dScaleY = 1.0;
m_3dScale = 1.0;
m_3dAngleX = 0.0;
m_3dMaxAngleX = 0.0;
m_3dFOV = 0.0;
Move(0.0, -old_dy / 2.0);
}
m2::PointD ScreenBase::PtoP3d(m2::PointD const & pt) const

View file

@ -15,6 +15,7 @@ public:
using Vector3dT = math::Matrix<double, 1, 4>;
private:
m2::RectD m_ViewportRect;
m2::RectD m_PixelRect;
double m_Scale;
@ -26,9 +27,9 @@ private:
double m_3dFarZ;
double m_3dAngleX;
double m_3dMaxAngleX;
double m_3dScaleX;
double m_3dScaleY;
double m_3dScale;
bool m_isPerspective;
bool m_isAutoPerspective;
protected:
/// @group Dependent parameters
@ -64,6 +65,8 @@ public:
m2::PointD const & org, double scale, double angle);
void SetFromRect(m2::AnyRectD const & rect);
void SetFromParams(m2::PointD const & org, double angle, double scale);
void SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect);
void SetOrg(m2::PointD const & p);
@ -115,6 +118,9 @@ public:
void GtoP(m2::RectD const & gr, m2::RectD & sr) const;
void PtoG(m2::RectD const & pr, m2::RectD & gr) const;
void MatchGandP(m2::PointD const & g, m2::PointD const & p);
void MatchGandP3d(m2::PointD const & g, m2::PointD const & p3d);
void GetTouchRect(m2::PointD const & pixPoint, double pixRadius, m2::AnyRectD & glbRect) const;
void GetTouchRect(m2::PointD const & pixPoint, double const pxWidth,
double const pxHeight, m2::AnyRectD & glbRect) const;
@ -131,13 +137,16 @@ public:
void SetRotationAngle(double rotationAngle);
double GetRotationAngle() const { return m_3dAngleX; }
double GetMaxRotationAngle() const { return m_3dMaxAngleX; }
double GetAngleFOV() const { return m_3dFOV; }
double GetScale3d() const { return m_3dScale; }
m2::PointD P3dtoP(m2::PointD const & pt) const;
Matrix3dT const & Pto3dMatrix() const { return m_Pto3d; }
bool isPerspective() const { return m_isPerspective; }
bool isAutoPerspective() const { return m_isAutoPerspective; }
void SetAutoPerspective(bool isAutoPerspective);
bool IsReverseProjection3d(m2::PointD const & pt) const;
@ -146,16 +155,21 @@ public:
m2::RectD PixelRectIn3d() const
{
return m2::RectD(0.0, 0.0, m_PixelRect.maxX() / m_3dScaleX, m_PixelRect.maxY() / m_3dScaleY);
return m_ViewportRect;
}
double GetMinPixelRectSize() const;
double CalculateScale3d(double rotationAngle) const;
m2::RectD CalculatePixelRect(double scale) const;
double CalculatePerspectiveAngle(double scale) const;
static double CalculateAutoPerspectiveAngle(double scale);
/// Compute arbitrary pixel transformation, that translates the (oldPt1, oldPt2) -> (newPt1, newPt2)
static MatrixT const CalcTransform(m2::PointD const & oldPt1, m2::PointD const & oldPt2,
m2::PointD const & newPt1, m2::PointD const & newPt2,
bool allowRotate);
/// Setting GtoP matrix extracts the Angle and m_Org parameters, leaving PixelRect intact
void SetGtoPMatrix(MatrixT const & m);

View file

@ -111,9 +111,6 @@ char const kAllow3dBuildingsKey[] = "Buildings3d";
double const kDistEqualQuery = 100.0;
double const kRotationAngle = math::pi4;
double const kAngleFOV = math::pi / 3.0;
// TODO!
// To adjust GpsTrackFilter was added secret command "?gpstrackaccuracy:xxx;"
// where xxx is a new value for horizontal accuracy.
@ -1386,10 +1383,7 @@ void Framework::ShowSearchResult(search::Result const & res)
}
m2::PointD const center = info.GetMercator();
if (m_currentModelView.isPerspective())
CallDrapeFunction(bind(&df::DrapeEngine::SetModelViewCenter, _1, center, scale, true));
else
ShowRect(df::GetRectForDrawScale(scale, center));
CallDrapeFunction(bind(&df::DrapeEngine::SetModelViewCenter, _1, center, scale, true));
UserMarkContainer::UserMarkForPoi()->SetPtOrg(center);
ActivateMapSelection(false, df::SelectionShape::OBJECT_POI, info);
@ -1611,7 +1605,7 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> contextFactory,
{
InsertRoute(m_routingSession.GetRoute());
if (allow3d && m_routingSession.IsFollowing())
m_drapeEngine->EnablePerspective(kRotationAngle, kAngleFOV);
m_drapeEngine->EnablePerspective();
}
if (m_connectToGpsTrack)
@ -2294,7 +2288,7 @@ void Framework::FollowRoute()
: scales::GetNavigationScale();
int const scale3d = (m_currentRouterType == RouterType::Pedestrian) ? scales::GetPedestrianNavigation3dScale()
: scales::GetNavigation3dScale();
m_drapeEngine->FollowRoute(scale, scale3d, kRotationAngle, kAngleFOV);
m_drapeEngine->FollowRoute(scale, scale3d);
m_drapeEngine->SetRoutePoint(m2::PointD(), true /* isStart */, false /* isValid */);
}
@ -2537,7 +2531,7 @@ void Framework::SetRouteFinishPoint(m2::PointD const & pt, bool isValid)
void Framework::Allow3dMode(bool allow3d, bool allow3dBuildings)
{
CallDrapeFunction(bind(&df::DrapeEngine::Allow3dMode, _1, allow3d, allow3dBuildings, kRotationAngle, kAngleFOV));
CallDrapeFunction(bind(&df::DrapeEngine::Allow3dMode, _1, allow3d, allow3dBuildings));
}
void Framework::Save3dMode(bool allow3d, bool allow3dBuildings)