diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 9f686e521a..8cabcd64e3 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -2041,6 +2041,7 @@ bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport, rect.Inflate(r, r); targetRect.Inflate(r, r); } + double const ptZ = m_selectionShape->GetPositionZ(); double const kOffset = 50 * VisualParams::Instance().GetVisualScale(); rect.Inflate(kOffset, kOffset); @@ -2078,7 +2079,7 @@ bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport, m_selectionTrackInfo.get().m_snapSides.y = 1; } } - gOffset = screen.PtoG(screen.P3dtoP(pos + pOffset)) - screen.PtoG(screen.P3dtoP(pos)); + gOffset = screen.PtoG(screen.P3dtoP(pos + pOffset, ptZ)) - screen.PtoG(screen.P3dtoP(pos, ptZ)); return true; } diff --git a/drape_frontend/selection_shape.hpp b/drape_frontend/selection_shape.hpp index 757ea08315..afc48a5475 100644 --- a/drape_frontend/selection_shape.hpp +++ b/drape_frontend/selection_shape.hpp @@ -44,6 +44,7 @@ public: bool IsVisible(ScreenBase const & screen, m2::PointD & pxPos) const; double GetRadius() const { return m_radius; } + double GetPositionZ() const { return m_positionZ; } ESelectedObject GetSelectedObject() const; diff --git a/geometry/screenbase.cpp b/geometry/screenbase.cpp index 1721b3148f..e922aa3bd1 100644 --- a/geometry/screenbase.cpp +++ b/geometry/screenbase.cpp @@ -440,6 +440,11 @@ m2::PointD ScreenBase::PtoP3d(m2::PointD const & pt, double ptZ) const } m2::PointD ScreenBase::P3dtoP(m2::PointD const & pt) const +{ + return P3dtoP(pt, 0.0 /* ptZ */); +} + +m2::PointD ScreenBase::P3dtoP(m2::PointD const & pt, double ptZ) const { if (!m_isPerspective) return pt; @@ -448,14 +453,24 @@ m2::PointD ScreenBase::P3dtoP(m2::PointD const & pt) const double const normalizedY = -2.0 * pt.y / PixelRectIn3d().SizeY() + 1.0; double normalizedZ = 0.0; + if (m_3dAngleX != 0.0) { double const halfFOV = m_3dFOV / 2.0; double const cameraZ = 1.0 / tan(halfFOV); double const tanX = tan(m_3dAngleX); - double const cameraDistanceZ = - cameraZ * (1.0 + (normalizedY + 1.0) * tanX / (cameraZ - normalizedY * tanX)); + double cameraDistanceZ = cameraZ * (1.0 + (normalizedY + 1.0) * tanX / (cameraZ - normalizedY * tanX)); + + if (ptZ != 0.0) + { + double const t = sqrt(cameraZ * cameraZ + normalizedY * normalizedY); + double const cosBeta = cameraZ / t; + double const sinBeta = normalizedY / t; + double const dz = ptZ * GetZScale() * cosBeta / (cos(m_3dAngleX) * cosBeta - sin(m_3dAngleX) * sinBeta); + + cameraDistanceZ -= dz; + } double const a = (m_3dFarZ + m_3dNearZ) / (m_3dFarZ - m_3dNearZ); double const b = -2.0 * m_3dFarZ * m_3dNearZ / (m_3dFarZ - m_3dNearZ); diff --git a/geometry/screenbase.hpp b/geometry/screenbase.hpp index 2278883134..ffdaa96612 100644 --- a/geometry/screenbase.hpp +++ b/geometry/screenbase.hpp @@ -92,6 +92,7 @@ public: double GetDepth3d() const { return m_3dFarZ - m_3dNearZ; } m2::PointD P3dtoP(m2::PointD const & pt) const; + m2::PointD P3dtoP(m2::PointD const & pt, double ptZ) const; Matrix3dT const & Pto3dMatrix() const { return m_Pto3d; } bool isPerspective() const { return m_isPerspective; }