diff --git a/drape_frontend/animation/interpolations.cpp b/drape_frontend/animation/interpolations.cpp index 515ffb7a08..bcfe0568a2 100644 --- a/drape_frontend/animation/interpolations.cpp +++ b/drape_frontend/animation/interpolations.cpp @@ -5,12 +5,27 @@ namespace df { +double InterpolateDouble(double startV, double endV, double t) +{ + return startV + (endV - startV) * t; +} + m2::PointD InterpolatePoint(m2::PointD const & startPt, m2::PointD const & endPt, double t) { m2::PointD diff = endPt - startPt; return startPt + diff * t; } +m2::RectD InterpolateRect(m2::RectD const & startRect, m2::RectD const & endRect, double t) +{ + m2::PointD center = InterpolatePoint(startRect.Center(), endRect.Center(), t); + double halfSizeX = 0.5 * InterpolateDouble(startRect.SizeX(), endRect.SizeX(), t); + double haldSizeY = 0.5 * InterpolateDouble(startRect.SizeY(), endRect.SizeY(), t); + + return m2::RectD(center.x - halfSizeX, center.y - haldSizeY, + center.x + halfSizeX, center.y + haldSizeY); +} + InerpolateAngle::InerpolateAngle(double startAngle, double endAngle) { m_startAngle = ang::AngleIn2PI(startAngle); @@ -22,5 +37,22 @@ double InerpolateAngle::Interpolate(double t) return m_startAngle + m_delta * t; } +InterpolateAnyRect::InterpolateAnyRect(m2::AnyRectD const & startRect, m2::AnyRectD const & endRect) + : m_startZero(startRect.GlobalZero()) + , m_endZero(endRect.GlobalZero()) + , m_angleInterpolator(startRect.Angle().val(), endRect.Angle().val()) + , m_startRect(startRect.GetLocalRect()) + , m_endRect(endRect.GetLocalRect()) +{ +} + +m2::AnyRectD InterpolateAnyRect::Interpolate(double t) +{ + double angle = m_angleInterpolator.Interpolate(t); + m2::PointD zero = InterpolatePoint(m_startZero, m_endZero, t); + m2::RectD rect = InterpolateRect(m_startRect, m_endRect, t); + + return m2::AnyRectD(zero, angle, rect); +} } // namespace df diff --git a/drape_frontend/animation/interpolations.hpp b/drape_frontend/animation/interpolations.hpp index 729fd21d00..0db4ca542d 100644 --- a/drape_frontend/animation/interpolations.hpp +++ b/drape_frontend/animation/interpolations.hpp @@ -1,11 +1,15 @@ #pragma once #include "geometry/point2d.hpp" +#include "geometry/rect2d.hpp" +#include "geometry/any_rect2d.hpp" namespace df { +double InterpolateDouble(double startV, double endV, double t); m2::PointD InterpolatePoint(m2::PointD const & startPt, m2::PointD const & endPt, double t); +m2::RectD InterpolateRect(m2::RectD const & startRect, m2::RectD const & endRect, double t); class InerpolateAngle { @@ -18,4 +22,16 @@ private: double m_delta; }; +class InterpolateAnyRect +{ +public: + InterpolateAnyRect(m2::AnyRectD const & startRect, m2::AnyRectD const & endRect); + m2::AnyRectD Interpolate(double t); + +private: + m2::PointD m_startZero, m_endZero; + InerpolateAngle m_angleInterpolator; + m2::RectD m_startRect, m_endRect; +}; + } // namespace df diff --git a/drape_frontend/animation/modelview_complex_animation.cpp b/drape_frontend/animation/modelview_complex_animation.cpp new file mode 100644 index 0000000000..b80ea4da83 --- /dev/null +++ b/drape_frontend/animation/modelview_complex_animation.cpp @@ -0,0 +1,17 @@ +#include "modelview_complex_animation.hpp" + +namespace df +{ + +ModelViewComplexAnimation::ModelViewComplexAnimation(m2::AnyRectD const & startRect, m2::AnyRectD const & endRect, double duration) + : BaseModeViewAnimation(duration) + , m_interpolator(startRect, endRect) +{ +} + +void ModelViewComplexAnimation::Apply(df::Navigator & navigator) +{ + navigator.SetFromRect(m_interpolator.Interpolate(GetT())); +} + +} diff --git a/drape_frontend/animation/modelview_complex_animation.hpp b/drape_frontend/animation/modelview_complex_animation.hpp new file mode 100644 index 0000000000..c9e07b3225 --- /dev/null +++ b/drape_frontend/animation/modelview_complex_animation.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "drape_frontend/animation/base_modelview_animation.hpp" +#include "drape_frontend/animation/interpolations.hpp" + +namespace df +{ + +class ModelViewComplexAnimation : public BaseModeViewAnimation +{ +public: + ModelViewComplexAnimation(m2::AnyRectD const & startRect, m2::AnyRectD const & endRect, double duration); + void Apply(Navigator & navigator) override; + +private: + InterpolateAnyRect m_interpolator; +}; + +} diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 803cc36bf5..03b7b1c719 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -12,6 +12,7 @@ SOURCES += \ animation/base_interpolator.cpp \ animation/modelview_angle_animation.cpp \ animation/modelview_center_animation.cpp \ + animation/modelview_complex_animation.cpp \ animation/interpolation_holder.cpp \ animation/interpolations.cpp \ apply_feature_functors.cpp \ @@ -56,6 +57,7 @@ HEADERS += \ animation/base_modelview_animation.hpp \ animation/modelview_angle_animation.hpp \ animation/modelview_center_animation.hpp \ + animation/modelview_complex_animation.hpp \ animation/interpolation_holder.hpp \ animation/interpolations.hpp \ animation/base_interpolator.hpp \ diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 51b303a743..89dc7d0c9b 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -1,3 +1,4 @@ +#include "drape_frontend/animation/modelview_complex_animation.hpp" #include "drape_frontend/animation/modelview_angle_animation.hpp" #include "drape_frontend/user_event_stream.hpp" #include "drape_frontend/visual_params.hpp" @@ -93,7 +94,13 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChange, bool & ProcessTouch(e.m_touchEvent); break; case UserEvent::EVENT_ROTATE: - m_animation.reset(new ModelViewAngleAnimation(m_navigator.Screen().GetAngle(), e.m_rotate.m_targetAzimut)); + { + m2::AnyRectD rect = m_navigator.Screen().GlobalRect(); + m2::AnyRectD dstRect = rect; + dstRect.SetAngle(e.m_rotate.m_targetAzimut); + double duration = ModelViewAngleAnimation::GetStandardDuration(rect.Angle().val(), dstRect.Angle().val()); + m_animation.reset(new ModelViewComplexAnimation(rect, dstRect, duration)); + } break; default: ASSERT(false, ());