Positioning in visible viewport.

This commit is contained in:
Daria Volvenkova 2016-09-05 13:17:07 +03:00
parent 12be223279
commit 24834ce40c
18 changed files with 221 additions and 29 deletions

View file

@ -1171,7 +1171,7 @@ Java_com_mapswithme_maps_Framework_nativeGetActiveObjectFormattedCuisine(JNIEnv
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_Framework_nativeSetVisibleRect(JNIEnv * env, jclass, jint left, jint top, jint right, jint bottom)
{
//TODO: call framework method
frm()->SetVisibleViewport(m2::RectD(left, top, right, bottom));
}
} // extern "C"

View file

@ -367,6 +367,23 @@ void OverlayTree::DeleteHandle(ref_ptr<OverlayHandle> const & handle)
Erase(handle);
}
bool OverlayTree::GetSelectedFeatureRect(ScreenBase const & screen, m2::RectD & featureRect)
{
if (!m_selectedFeatureID.IsValid())
return false;
featureRect.MakeEmpty();
for (auto const & handle : m_handlesCache)
{
if (handle->IsVisible() && handle->GetFeatureID() == m_selectedFeatureID)
{
m2::RectD rect = handle->GetPixelRect(screen, screen.isPerspective());
featureRect.Add(rect);
}
}
return true;
}
void OverlayTree::Select(m2::PointD const & glbPoint, TOverlayContainer & result) const
{
ScreenBase const & screen = m_traits.m_modelView;

View file

@ -66,6 +66,7 @@ public:
void SetDisplacementMode(int displacementMode);
void SetSelectedFeature(FeatureID const & featureID);
bool GetSelectedFeatureRect(ScreenBase const & screen, m2::RectD & featureRect);
#ifdef COLLECT_DISPLACEMENT_INFO
struct DisplacementData

View file

@ -111,6 +111,13 @@ void DrapeEngine::Resize(int w, int h)
ResizeImpl(w, h);
}
void DrapeEngine::SetVisibleViewport(m2::RectD const & rect) const
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<SetVisibleViewportMessage>(rect),
MessagePriority::Normal);
}
void DrapeEngine::Invalidate()
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,

View file

@ -89,6 +89,8 @@ public:
void Resize(int w, int h);
void Invalidate();
void SetVisibleViewport(m2::RectD const & rect) const;
void AddTouchEvent(TouchEvent const & event);
void Scale(double factor, m2::PointD const & pxPoint, bool isAnim);

View file

@ -38,6 +38,11 @@ public:
void OnScaleEnded() override {}
void OnTouchMapAction() override {}
void OnAnimatedScaleEnded() override {}
bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport,
m2::PointD & gOffset) override
{
return false;
}
void AddUserEvent(df::TouchEvent const & event)
{

View file

@ -387,6 +387,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
{
ProcessSelection(make_ref(m_selectObjectMessage));
m_selectObjectMessage.reset();
AddUserEvent(make_unique_dp<SetVisibleViewportEvent>(m_userEventStream.GetVisibleViewport()));
}
}
break;
@ -452,6 +453,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
ProcessSelection(msg);
AddUserEvent(make_unique_dp<SetVisibleViewportEvent>(m_userEventStream.GetVisibleViewport()));
break;
}
@ -718,6 +721,15 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
case Message::SetVisibleViewport:
{
ref_ptr<SetVisibleViewportMessage> msg = message;
AddUserEvent(make_unique_dp<SetVisibleViewportEvent>(msg->GetRect()));
m_myPositionController->SetVisibleViewport(msg->GetRect());
m_myPositionController->UpdatePosition();
break;
}
case Message::Invalidate:
{
m_myPositionController->ResetRoutingNotFollowTimer();
@ -843,11 +855,11 @@ void FrontendRenderer::OnResize(ScreenBase const & screen)
double const kEps = 1e-5;
bool const viewportChanged = !m2::IsEqualSize(m_lastReadedModelView.PixelRectIn3d(), viewportRect, kEps, kEps);
m_myPositionController->UpdatePixelPosition(screen);
m_myPositionController->OnUpdateScreen(screen);
if (viewportChanged)
{
m_myPositionController->OnNewViewportRect();
m_myPositionController->UpdatePosition();
m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY());
}
@ -1438,6 +1450,48 @@ void FrontendRenderer::OnTouchMapAction()
m_myPositionController->ResetRoutingNotFollowTimer();
}
bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset)
{
gOffset = m2::PointD(0, 0);
if (m_myPositionController->IsModeChangeViewport() || m_selectionShape == nullptr)
return false;
ScreenBase const & screen = m_userEventStream.GetCurrentScreen();
m2::PointD pos;
double const vs = VisualParams::Instance().GetVisualScale();
if (m_selectionShape->IsVisible(screen, pos))
{
m2::RectD rect(pos, pos);
if (!(m_selectionShape->GetSelectedObject() == SelectionShape::OBJECT_POI &&
m_overlayTree->GetSelectedFeatureRect(screen, rect)))
{
double const r = m_selectionShape->GetRadius();
rect.Inflate(r, r);
}
if (oldViewport.IsIntersect(rect) && !newViewport.IsRectInside(rect))
{
double const kOffset = 50 * vs;
m2::PointD pOffset(0.0, 0.0);
if (rect.minX() < newViewport.minX())
pOffset.x = newViewport.minX() - rect.minX() + kOffset;
else if (rect.maxX() > newViewport.maxX())
pOffset.x = newViewport.maxX() - rect.maxX() - kOffset;
if (rect.minY() < newViewport.minY())
pOffset.y = newViewport.minY() - rect.minY() + kOffset;
else if (rect.maxY() > newViewport.maxY())
pOffset.y = newViewport.maxY() - rect.maxY() - kOffset;
gOffset = screen.PtoG(screen.P3dtoP(pos + pOffset)) - screen.PtoG(screen.P3dtoP(pos));
}
return true;
}
return false;
}
TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen)
{
m2::RectD const & rect = screen.ClipRect();
@ -1726,7 +1780,7 @@ void FrontendRenderer::PrepareScene(ScreenBase const & modelView)
RefreshZScale(modelView);
RefreshPivotTransform(modelView);
m_myPositionController->UpdatePixelPosition(modelView);
m_myPositionController->OnUpdateScreen(modelView);
m_routeRenderer->UpdateRoute(modelView, bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
}

View file

@ -203,6 +203,7 @@ private:
void OnScaleEnded() override;
void OnAnimatedScaleEnded() override;
void OnTouchMapAction() override;
bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) override;
class Routine : public threads::IRoutine
{

View file

@ -63,7 +63,8 @@ public:
SetDisplacementMode,
AllowAutoZoom,
RequestSymbolsSize,
RecoverGLResources
RecoverGLResources,
SetVisibleViewport
};
virtual ~Message() {}

View file

@ -794,6 +794,20 @@ public:
bool IsGLContextDependent() const override { return true; }
};
class SetVisibleViewportMessage : public Message
{
public:
SetVisibleViewportMessage(m2::RectD const & rect)
: m_rect(rect)
{}
Type GetType() const override { return Message::SetVisibleViewport; }
m2::RectD const & GetRect() const { return m_rect; }
private:
m2::RectD m_rect;
};
class DeactivateRouteFollowingMessage : public Message
{
public:

View file

@ -167,15 +167,22 @@ MyPositionController::~MyPositionController()
{
}
void MyPositionController::OnNewViewportRect()
void MyPositionController::UpdatePosition()
{
UpdateViewport(kDoNotChangeZoom);
}
void MyPositionController::UpdatePixelPosition(ScreenBase const & screen)
void MyPositionController::OnUpdateScreen(ScreenBase const & screen)
{
m_pixelRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect();
m_positionYOffset = screen.isPerspective() ? kPositionOffsetYIn3D : kPositionOffsetY;
if (m_visiblePixelRect.IsEmptyInterior())
m_visiblePixelRect = m_pixelRect;
}
void MyPositionController::SetVisibleViewport(const m2::RectD &rect)
{
m_visiblePixelRect = rect;
}
void MyPositionController::SetListener(ref_ptr<MyPositionController::Listener> listener)
@ -344,7 +351,7 @@ void MyPositionController::NextMode(ScreenBase const & screen)
if (!m_isInRouting)
{
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_pixelRect.Center(), preferredZoomLevel);
ChangeModelView(m_position, 0.0, m_visiblePixelRect.Center(), preferredZoomLevel);
}
}
}
@ -399,7 +406,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 ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), kDoNotChangeZoom);
m_isInRouting ? GetRoutingRotationPixelCenter() : m_visiblePixelRect.Center(), kDoNotChangeZoom);
}
}
else if (m_mode == location::PendingPosition || m_mode == location::NotFollowNoPosition)
@ -635,7 +642,7 @@ void MyPositionController::OnCompassTapped()
if (m_mode == location::FollowAndRotate)
{
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_pixelRect.Center(), kDoNotChangeZoom);
ChangeModelView(m_position, 0.0, m_visiblePixelRect.Center(), kDoNotChangeZoom);
}
else
{
@ -688,24 +695,24 @@ void MyPositionController::UpdateViewport(int zoomLevel)
ChangeModelView(m_position, zoomLevel);
else if (m_mode == location::FollowAndRotate)
ChangeModelView(m_position, m_drawDirection,
m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), zoomLevel);
m_isInRouting ? GetRoutingRotationPixelCenter() : m_visiblePixelRect.Center(), zoomLevel);
}
m2::PointD MyPositionController::GetRotationPixelCenter() const
{
if (m_mode == location::Follow)
return m_pixelRect.Center();
return m_visiblePixelRect.Center();
if (m_mode == location::FollowAndRotate)
return m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center();
return m_isInRouting ? GetRoutingRotationPixelCenter() : m_visiblePixelRect.Center();
return m2::PointD::Zero();
}
m2::PointD MyPositionController::GetRoutingRotationPixelCenter() const
{
return m2::PointD(m_pixelRect.Center().x,
m_pixelRect.maxY() - m_positionYOffset * VisualParams::Instance().GetVisualScale());
return m2::PointD(m_visiblePixelRect.Center().x,
m_visiblePixelRect.maxY() - m_positionYOffset * VisualParams::Instance().GetVisualScale());
}
m2::PointD MyPositionController::GetDrawablePosition()
@ -806,7 +813,7 @@ void MyPositionController::DeactivateRouting()
m_isInRouting = false;
ChangeMode(location::Follow);
ChangeModelView(m_position, 0.0, m_pixelRect.Center(), kDoNotChangeZoom);
ChangeModelView(m_position, 0.0, m_visiblePixelRect.Center(), kDoNotChangeZoom);
}
}

View file

@ -44,8 +44,10 @@ public:
bool isFirstLaunch, bool isRoutingActive, bool isAutozoomEnabled);
~MyPositionController();
void OnNewViewportRect();
void UpdatePixelPosition(ScreenBase const & screen);
void UpdatePosition();
void OnUpdateScreen(ScreenBase const & screen);
void SetVisibleViewport(m2::RectD const & rect);
void SetListener(ref_ptr<Listener> listener);
m2::PointD const & Position() const;
@ -97,12 +99,12 @@ public:
bool IsInRouting() const { return m_isInRouting; }
bool IsRouteFollowingActive() const;
bool IsWaitingForTimers() const;
bool IsModeChangeViewport() const;
bool IsWaitingForLocation() const;
m2::PointD GetDrawablePosition();
private:
bool IsModeChangeViewport() const;
void ChangeMode(location::EMyPositionMode newMode);
void SetDirection(double bearing);
@ -161,6 +163,7 @@ private:
double m_lastLocationTimestamp;
m2::RectD m_pixelRect;
m2::RectD m_visiblePixelRect;
double m_positionYOffset;
bool m_isVisible;

View file

@ -104,10 +104,10 @@ SelectionShape::SelectionShape(ref_ptr<dp::TextureManager> mng)
batcher.InsertTriangleList(state, make_ref(&provider), nullptr);
}
double r = 15.0f * VisualParams::Instance().GetVisualScale();
m_mapping.AddRangePoint(0.6, 1.3 * r);
m_mapping.AddRangePoint(0.85, 0.8 * r);
m_mapping.AddRangePoint(1.0, r);
m_radius = 15.0f * VisualParams::Instance().GetVisualScale();
m_mapping.AddRangePoint(0.6, 1.3 * m_radius);
m_mapping.AddRangePoint(0.85, 0.8 * m_radius);
m_mapping.AddRangePoint(1.0, m_radius);
}
void SelectionShape::Show(ESelectedObject obj, m2::PointD const & position, double positionZ, bool isAnimate)
@ -128,6 +128,20 @@ void SelectionShape::Hide()
m_selectedObject = OBJECT_EMPTY;
}
bool SelectionShape::IsVisible(ScreenBase const & screen, m2::PointD & pxPos) const
{
m2::PointD const pt = screen.GtoP(m_position);
ShowHideAnimation::EState state = m_animation.GetState();
if ((state == ShowHideAnimation::STATE_VISIBLE || state == ShowHideAnimation::STATE_SHOW_DIRECTION) &&
!screen.IsReverseProjection3d(pt))
{
pxPos = screen.PtoP3d(pt, -m_positionZ);
return true;
}
return false;
}
void SelectionShape::Render(ScreenBase const & screen, int zoomLevel, ref_ptr<dp::GpuProgramManager> mng,
dp::UniformValuesStorage const & commonUniforms)
{

View file

@ -38,6 +38,9 @@ public:
void Render(ScreenBase const & screen, int zoomLevel, ref_ptr<dp::GpuProgramManager> mng,
dp::UniformValuesStorage const & commonUniforms);
bool IsVisible(ScreenBase const & screen, m2::PointD & pxPos) const;
double GetRadius() const { return m_radius; }
ESelectedObject GetSelectedObject() const;
private:
@ -46,6 +49,7 @@ private:
private:
m2::PointD m_position;
double m_positionZ;
double m_radius;
ShowHideAnimation m_animation;
ESelectedObject m_selectedObject;

View file

@ -180,6 +180,8 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
{
ref_ptr<ResizeEvent> resizeEvent = make_ref(e);
m_navigator.OnSize(resizeEvent->GetWidth(), resizeEvent->GetHeight());
if (m_visibleViewport.IsEmptyInterior())
m_visibleViewport = m2::RectD(0, 0, resizeEvent->GetWidth(), resizeEvent->GetHeight());
viewportChanged = true;
breakAnim = true;
TouchCancel(m_touches);
@ -236,6 +238,21 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
SetAutoPerspective(perspectiveEvent->IsAutoPerspective());
}
break;
case UserEvent::EventType::VisibleViewport:
{
ref_ptr<SetVisibleViewportEvent> viewportEvent = make_ref(e);
m2::RectD prevVisibleViewport = m_visibleViewport;
m_visibleViewport = viewportEvent->GetRect();
m2::PointD gOffset;
if (m_listener->OnNewVisibleViewport(prevVisibleViewport, m_visibleViewport, gOffset))
{
ScreenBase screen = GetCurrentScreen();
screen.MoveG(gOffset);
SetScreen(screen, true /* isAnim */);
}
}
break;
default:
ASSERT(false, ());
break;
@ -284,6 +301,11 @@ ScreenBase const & UserEventStream::GetCurrentScreen() const
return m_navigator.Screen();
}
m2::RectD const & UserEventStream::GetVisibleViewport() const
{
return m_visibleViewport;
}
bool UserEventStream::OnSetScale(ref_ptr<ScaleEvent> scaleEvent)
{
double factor = scaleEvent->GetFactor();
@ -359,12 +381,12 @@ bool UserEventStream::OnSetCenter(ref_ptr<SetCenterEvent> centerEvent)
if (zoom == kDoNotChangeZoom)
{
GetTargetScreen(screen);
screen.MatchGandP3d(center, screen.PixelRectIn3d().Center());
screen.MatchGandP3d(center, m_visibleViewport.Center());
}
else
{
screen.SetFromParams(center, screen.GetAngle(), GetScale(zoom));
screen.MatchGandP3d(center, screen.PixelRectIn3d().Center());
screen.MatchGandP3d(center, m_visibleViewport.Center());
}
ShrinkAndScaleInto(screen, df::GetWorldRect());
@ -381,16 +403,19 @@ bool UserEventStream::SetAngle(double azimuth, TAnimationCreator const & paralle
{
ScreenBase screen;
GetTargetScreen(screen);
m2::PointD pt = m_visibleViewport.Center();
m2::PointD gPt = screen.PtoG(screen.P3dtoP(pt));
if (screen.isPerspective())
{
m2::PointD pt = screen.PixelRectIn3d().Center();
return SetFollowAndRotate(screen.PtoG(screen.P3dtoP(pt)), pt,
return SetFollowAndRotate(gPt, pt,
azimuth, kDoNotChangeZoom, kDoNotAutoZoom,
true /* isAnim */, false /* isAutoScale */,
parallelAnimCreator);
}
screen.SetAngle(azimuth);
screen.MatchGandP3d(gPt, pt);
return SetScreen(screen, true /* isAnim */, parallelAnimCreator);
}

View file

@ -38,7 +38,8 @@ public:
Resize,
Rotate,
FollowAndRotate,
AutoPerspective
AutoPerspective,
VisibleViewport
};
virtual ~UserEvent() {}
@ -306,6 +307,21 @@ private:
uint32_t m_height;
};
class SetVisibleViewportEvent : public UserEvent
{
public:
SetVisibleViewportEvent(m2::RectD const & rect)
: m_rect(rect)
{}
EventType GetType() const override { return UserEvent::EventType::VisibleViewport; }
m2::RectD const & GetRect() const { return m_rect; }
private:
m2::RectD m_rect;
};
class UserEventStream
{
public:
@ -331,12 +347,15 @@ public:
virtual void OnAnimatedScaleEnded() = 0;
virtual void OnTouchMapAction() = 0;
virtual bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) = 0;
};
UserEventStream();
void AddEvent(drape_ptr<UserEvent> && event);
ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged);
ScreenBase const & GetCurrentScreen() const;
m2::RectD const & GetVisibleViewport() const;
void GetTargetScreen(ScreenBase & screen);
m2::AnyRectD GetTargetRect();
@ -444,6 +463,8 @@ private:
TEventsList m_events;
mutable mutex m_lock;
m2::RectD m_visibleViewport;
Navigator m_navigator;
my::Timer m_touchTimer;
enum ERecognitionState

View file

@ -948,6 +948,11 @@ m2::PointD Framework::GetPixelCenter() const
: m_currentModelView.PixelRect().Center();
}
m2::PointD Framework::GetVisiblePixelCenter() const
{
return m_visibleViewport.Center();
}
m2::PointD const & Framework::GetViewportCenter() const
{
return m_currentModelView.GetOrg();
@ -968,6 +973,14 @@ m2::RectD Framework::GetCurrentViewport() const
return m_currentModelView.ClipRect();
}
void Framework::SetVisibleViewport(m2::RectD const & rect)
{
if (m_drapeEngine == nullptr)
return;
m_visibleViewport = rect;
m_drapeEngine->SetVisibleViewport(rect);
}
void Framework::ShowRect(m2::RectD const & rect, int maxScale)
{
CallDrapeFunction(bind(&df::DrapeEngine::SetModelViewRect, _1, rect, true, maxScale, true));
@ -1016,7 +1029,7 @@ void Framework::Scale(Framework::EScaleMode mode, m2::PointD const & pxPoint, bo
void Framework::Scale(double factor, bool isAnim)
{
Scale(factor, GetPixelCenter(), isAnim);
Scale(factor, GetVisiblePixelCenter(), isAnim);
}
void Framework::Scale(double factor, m2::PointD const & pxPoint, bool isAnim)

View file

@ -134,6 +134,7 @@ protected:
search::QuerySaver m_searchQuerySaver;
ScreenBase m_currentModelView;
m2::RectD m_visibleViewport;
using TViewportChanged = df::DrapeEngine::TModelViewListenerFn;
TViewportChanged m_viewportChanged;
@ -531,12 +532,14 @@ public:
void ShowAll();
m2::PointD GetPixelCenter() const;
m2::PointD GetVisiblePixelCenter() const;
m2::PointD const & GetViewportCenter() const;
void SetViewportCenter(m2::PointD const & pt);
void SetViewportCenter(m2::PointD const & pt, int zoomLevel);
m2::RectD GetCurrentViewport() const;
void SetVisibleViewport(m2::RectD const & rect);
/// - Check minimal visible scale according to downloaded countries.
void ShowRect(m2::RectD const & rect, int maxScale = -1);