Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/jni/com/mapswithme/maps/Framework.cpp12
-rw-r--r--android/jni/com/mapswithme/maps/Framework.hpp2
-rw-r--r--android/src/com/mapswithme/maps/Framework.java2
-rw-r--r--android/src/com/mapswithme/maps/MwmActivity.java2
-rw-r--r--drape/overlay_tree.cpp24
-rw-r--r--drape/overlay_tree.hpp4
-rw-r--r--drape_frontend/drape_engine.cpp17
-rw-r--r--drape_frontend/drape_engine.hpp7
-rwxr-xr-xdrape_frontend/frontend_renderer.cpp63
-rwxr-xr-xdrape_frontend/frontend_renderer.hpp8
-rw-r--r--drape_frontend/gui/layer_render.cpp5
-rw-r--r--drape_frontend/gui/layer_render.hpp2
-rw-r--r--drape_frontend/message.hpp3
-rw-r--r--drape_frontend/message_subclasses.hpp28
-rw-r--r--drape_frontend/my_position_controller.hpp5
-rw-r--r--geometry/triangle2d.cpp65
-rw-r--r--geometry/triangle2d.hpp30
-rw-r--r--indexer/scales.hpp10
-rw-r--r--iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.h6
-rw-r--r--iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.mm12
-rw-r--r--iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.h2
-rw-r--r--iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm2
-rw-r--r--iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm11
-rw-r--r--iphone/Maps/Classes/MWMPlacePageViewManager.mm4
-rw-r--r--iphone/Maps/Classes/MWMPlacePageViewManagerDelegate.h3
-rw-r--r--map/framework.cpp31
-rw-r--r--map/framework.hpp8
-rw-r--r--qt/draw_widget.cpp4
28 files changed, 314 insertions, 58 deletions
diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp
index 023f771aae..be4e891825 100644
--- a/android/jni/com/mapswithme/maps/Framework.cpp
+++ b/android/jni/com/mapswithme/maps/Framework.cpp
@@ -203,11 +203,12 @@ void Framework::Get3dMode(bool & allow3d, bool & allow3dBuildings)
m_work.Load3dMode(allow3d, allow3dBuildings);
}
-void Framework::SetChoosePositionMode(bool isChoosePositionMode)
+void Framework::SetChoosePositionMode(bool isChoosePositionMode, bool isBusiness,
+ bool hasPosition, m2::PointD const & position)
{
m_isChoosePositionMode = isChoosePositionMode;
m_work.BlockTapEvents(isChoosePositionMode);
- m_work.EnableChoosePositionMode(isChoosePositionMode);
+ m_work.EnableChoosePositionMode(isChoosePositionMode, isBusiness, hasPosition, position);
}
Storage & Framework::Storage()
@@ -986,11 +987,10 @@ Java_com_mapswithme_maps_Framework_nativeOnBookmarkCategoryChanged(JNIEnv * env,
}
JNIEXPORT void JNICALL
-Java_com_mapswithme_maps_Framework_nativeTurnChoosePositionMode(JNIEnv *, jclass, jboolean turnOn)
+Java_com_mapswithme_maps_Framework_nativeTurnChoosePositionMode(JNIEnv *, jclass, jboolean turnOn, jboolean isBusiness)
{
- ::Framework * fr = frm();
- fr->EnableChoosePositionMode(turnOn);
- fr->BlockTapEvents(turnOn);
+ //TODO(Android team): implement positioning
+ g_framework->SetChoosePositionMode(turnOn, isBusiness, false /* hasPosition */, m2::PointD());
}
JNIEXPORT jboolean JNICALL
diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp
index 7cb9e93bf1..754571d3f9 100644
--- a/android/jni/com/mapswithme/maps/Framework.hpp
+++ b/android/jni/com/mapswithme/maps/Framework.hpp
@@ -137,7 +137,7 @@ namespace android
void Set3dMode(bool allow3d, bool allow3dBuildings);
void Get3dMode(bool & allow3d, bool & allow3dBuildings);
- void SetChoosePositionMode(bool isChoosePositionMode);
+ void SetChoosePositionMode(bool isChoosePositionMode, bool isBusiness, bool hasPosition, m2::PointD const & position);
void SetupWidget(gui::EWidget widget, float x, float y, dp::Anchor anchor);
void ApplyWidgets();
diff --git a/android/src/com/mapswithme/maps/Framework.java b/android/src/com/mapswithme/maps/Framework.java
index 8b987c42cf..93b64dedef 100644
--- a/android/src/com/mapswithme/maps/Framework.java
+++ b/android/src/com/mapswithme/maps/Framework.java
@@ -197,7 +197,7 @@ public class Framework
public static native void nativeZoomToPoint(double lat, double lon, int zoom, boolean animate);
- public static native void nativeTurnChoosePositionMode(boolean turnedOn);
+ public static native void nativeTurnChoosePositionMode(boolean turnedOn, boolean isBusiness);
public static native boolean nativeIsDownloadedMapAtScreenCenter();
diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java
index 6b1cde5da2..fabffc1f61 100644
--- a/android/src/com/mapswithme/maps/MwmActivity.java
+++ b/android/src/com/mapswithme/maps/MwmActivity.java
@@ -400,7 +400,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
UiUtils.showIf(show, mPositionChooser);
setFullscreen(show);
- Framework.nativeTurnChoosePositionMode(show);
+ Framework.nativeTurnChoosePositionMode(show, false /* isBusiness */); //TODO(Android team): set isBusiness correctly
closePlacePage();
mSearchController.hide();
}
diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp
index b50317e67e..394ce7e0a6 100644
--- a/drape/overlay_tree.cpp
+++ b/drape/overlay_tree.cpp
@@ -8,6 +8,7 @@ namespace dp
int const kFrameUpdatePeriod = 10;
int const kAverageHandlesCount[dp::OverlayRanksCount] = { 300, 200, 50 };
+int const kInvalidFrame = -1;
namespace
{
@@ -59,8 +60,9 @@ private:
} // namespace
OverlayTree::OverlayTree()
- : m_frameCounter(-1)
+ : m_frameCounter(kInvalidFrame)
, m_followingMode(false)
+ , m_isDisplacementEnabled(true)
{
for (size_t i = 0; i < m_handles.size(); i++)
m_handles[i].reserve(kAverageHandlesCount[i]);
@@ -73,14 +75,14 @@ bool OverlayTree::Frame()
m_frameCounter++;
if (m_frameCounter >= kFrameUpdatePeriod)
- m_frameCounter = -1;
+ m_frameCounter = kInvalidFrame;
return IsNeedUpdate();
}
bool OverlayTree::IsNeedUpdate() const
{
- return m_frameCounter == -1;
+ return m_frameCounter == kInvalidFrame;
}
void OverlayTree::StartOverlayPlacing(ScreenBase const & screen)
@@ -97,11 +99,11 @@ void OverlayTree::StartOverlayPlacing(ScreenBase const & screen)
void OverlayTree::Remove(ref_ptr<OverlayHandle> handle)
{
- if (m_frameCounter == -1)
+ if (m_frameCounter == kInvalidFrame)
return;
if (m_handlesCache.find(handle) != m_handlesCache.end())
- m_frameCounter = -1;
+ m_frameCounter = kInvalidFrame;
}
void OverlayTree::Add(ref_ptr<OverlayHandle> handle)
@@ -161,6 +163,12 @@ void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle,
ScreenBase const & modelView = GetModelView();
m2::RectD const pixelRect = handle->GetExtendedPixelRect(modelView);
+ if (!m_isDisplacementEnabled)
+ {
+ m_handlesCache.insert(handle);
+ TBase::Add(handle, pixelRect);
+ return;
+ }
TOverlayContainer rivals;
HandleComparator comparator(true /* enableMask */, m_followingMode);
@@ -383,6 +391,12 @@ void OverlayTree::SetFollowingMode(bool mode)
m_followingMode = mode;
}
+void OverlayTree::SetDisplacementEnabled(bool enabled)
+{
+ m_isDisplacementEnabled = enabled;
+ m_frameCounter = kInvalidFrame;
+}
+
#ifdef COLLECT_DISPLACEMENT_INFO
OverlayTree::TDisplacementInfo const & OverlayTree::GetDisplacementInfo() const
diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp
index 817680ff45..3b11413352 100644
--- a/drape/overlay_tree.hpp
+++ b/drape/overlay_tree.hpp
@@ -63,6 +63,8 @@ public:
void SetFollowingMode(bool mode);
+ void SetDisplacementEnabled(bool enabled);
+
#ifdef COLLECT_DISPLACEMENT_INFO
struct DisplacementData
{
@@ -90,6 +92,8 @@ private:
unordered_set<ref_ptr<OverlayHandle>, detail::OverlayHasher> m_handlesCache;
bool m_followingMode;
+ bool m_isDisplacementEnabled;
+
#ifdef COLLECT_DISPLACEMENT_INFO
TDisplacementInfo m_displacementInfo;
#endif
diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp
index a0afd187c7..992c35ec54 100644
--- a/drape_frontend/drape_engine.cpp
+++ b/drape_frontend/drape_engine.cpp
@@ -70,7 +70,7 @@ DrapeEngine::DrapeEngine(Params && params)
RecacheGui(false);
if (params.m_showChoosePositionMark)
- EnableChoosePositionMode(true);
+ EnableChoosePositionMode(true, move(params.m_boundAreaTriangles), false, m2::PointD());
ResizeImpl(m_viewport.GetWidth(), m_viewport.GetHeight());
}
@@ -436,26 +436,27 @@ void DrapeEngine::ClearGpsTrackPoints()
MessagePriority::Normal);
}
-void DrapeEngine::EnableChoosePositionMode(bool enable)
+void DrapeEngine::EnableChoosePositionMode(bool enable, vector<m2::TriangleD> && boundAreaTriangles,
+ bool hasPosition, m2::PointD const & position)
{
m_choosePositionMode = enable;
+ bool kineticScroll = m_kineticScrollEnabled;
if (enable)
{
StopLocationFollow();
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<ShowChoosePositionMarkMessage>(),
MessagePriority::High);
- m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<SetKineticScrollEnabledMessage>(false /* enabled */),
- MessagePriority::High);
+ kineticScroll = false;
}
else
{
RecacheGui(true);
- m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<SetKineticScrollEnabledMessage>(m_kineticScrollEnabled),
- MessagePriority::High);
}
+ m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
+ make_unique_dp<SetAddNewPlaceModeMessage>(enable, move(boundAreaTriangles),
+ kineticScroll, hasPosition, position),
+ MessagePriority::High);
}
void DrapeEngine::BlockTapEvents(bool block)
diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp
index 19da53eb08..dbfecf1933 100644
--- a/drape_frontend/drape_engine.hpp
+++ b/drape_frontend/drape_engine.hpp
@@ -13,6 +13,7 @@
#include "geometry/polyline2d.hpp"
#include "geometry/screenbase.hpp"
+#include "geometry/triangle2d.hpp"
#include "base/strings_bundle.hpp"
@@ -43,6 +44,7 @@ public:
bool allow3dBuildings,
bool blockTapEvents,
bool showChoosePositionMark,
+ vector<m2::TriangleD> && boundAreaTriangles,
bool firstLaunch)
: m_factory(factory)
, m_stringsBundle(stringBundle)
@@ -54,6 +56,7 @@ public:
, m_allow3dBuildings(allow3dBuildings)
, m_blockTapEvents(blockTapEvents)
, m_showChoosePositionMark(showChoosePositionMark)
+ , m_boundAreaTriangles(move(boundAreaTriangles))
, m_isFirstLaunch(firstLaunch)
{}
@@ -67,6 +70,7 @@ public:
bool m_allow3dBuildings;
bool m_blockTapEvents;
bool m_showChoosePositionMark;
+ vector<m2::TriangleD> m_boundAreaTriangles;
bool m_isFirstLaunch;
};
@@ -129,7 +133,8 @@ public:
void UpdateGpsTrackPoints(vector<df::GpsTrackPoint> && toAdd, vector<uint32_t> && toRemove);
void ClearGpsTrackPoints();
- void EnableChoosePositionMode(bool enable);
+ void EnableChoosePositionMode(bool enable, vector<m2::TriangleD> && boundAreaTriangles,
+ bool hasPosition, m2::PointD const & position);
void BlockTapEvents(bool block);
void SetKineticScrollEnabled(bool enabled);
diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp
index 5e2cacad1c..26a8863c43 100755
--- a/drape_frontend/frontend_renderer.cpp
+++ b/drape_frontend/frontend_renderer.cpp
@@ -119,6 +119,7 @@ FrontendRenderer::FrontendRenderer(Params const & params)
, m_enable3dBuildings(params.m_allow3dBuildings)
, m_isIsometry(false)
, m_blockTapEvents(params.m_blockTapEvents)
+ , m_choosePositionMode(false)
, m_viewport(params.m_viewport)
, m_modelViewChangedFn(params.m_modelViewChangedFn)
, m_tapEventInfoFn(params.m_tapEventFn)
@@ -347,6 +348,16 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
m_guiRenderer = move(renderer);
else
m_guiRenderer->Merge(make_ref(renderer));
+
+ bool oldMode = m_choosePositionMode;
+ m_choosePositionMode = m_guiRenderer->HasWidget(gui::WIDGET_CHOOSE_POSITION_MARK);
+ if (oldMode != m_choosePositionMode)
+ {
+ ScreenBase const & screen = m_userEventStream.GetCurrentScreen();
+ CheckIsometryMinScale(screen);
+ UpdateDisplacementEnabled();
+ InvalidateRect(screen.ClipRect());
+ }
break;
}
@@ -694,6 +705,27 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
+ case Message::SetAddNewPlaceMode:
+ {
+ ref_ptr<SetAddNewPlaceModeMessage> msg = message;
+ m_userEventStream.SetKineticScrollEnabled(msg->IsKineticScrollEnabled());
+ m_dragBoundArea = msg->AcceptBoundArea();
+ if (msg->IsEnabled())
+ {
+ if (!m_dragBoundArea.empty())
+ {
+ PullToBoundArea(true /* randomPlace */, true /* applyZoom */);
+ }
+ else
+ {
+ m2::PointD const pt = msg->HasPosition()? msg->GetPosition() :
+ m_userEventStream.GetCurrentScreen().GlobalRect().Center();
+ AddUserEvent(SetCenterEvent(pt, scales::GetAddNewPlaceScale(), true));
+ }
+ }
+ break;
+ }
+
case Message::Invalidate:
{
// Do nothing here, new frame will be rendered because of this message processing.
@@ -882,6 +914,22 @@ void FrontendRenderer::PrepareGpsTrackPoints(size_t pointsCount)
MessagePriority::Normal);
}
+void FrontendRenderer::PullToBoundArea(bool randomPlace, bool applyZoom)
+{
+ if (m_dragBoundArea.empty())
+ return;
+
+ ScreenBase const & screen = m_userEventStream.GetCurrentScreen();
+ m2::PointD const center = screen.GlobalRect().Center();
+ if (!m2::IsPointInsideTriangles(center, m_dragBoundArea))
+ {
+ m2::PointD const dest = randomPlace ? m2::GetRandomPointInsideTriangles(m_dragBoundArea) :
+ m2::ProjectPointToTriangles(center, m_dragBoundArea);
+ int const zoom = applyZoom ? scales::GetAddNewPlaceScale() : m_currentZoomLevel;
+ AddUserEvent(SetCenterEvent(dest, zoom, true));
+ }
+}
+
void FrontendRenderer::BeginUpdateOverlayTree(ScreenBase const & modelView)
{
if (m_overlayTree->Frame())
@@ -1189,10 +1237,10 @@ void FrontendRenderer::DisablePerspective()
AddUserEvent(DisablePerspectiveEvent());
}
-void FrontendRenderer::CheckIsometryMinScale(const ScreenBase &screen)
+void FrontendRenderer::CheckIsometryMinScale(ScreenBase const & screen)
{
bool const isScaleAllowableIn3d = UserEventStream::IsScaleAllowableIn3d(m_currentZoomLevel);
- bool const isIsometry = m_enable3dBuildings && isScaleAllowableIn3d;
+ bool const isIsometry = m_enable3dBuildings && !m_choosePositionMode && isScaleAllowableIn3d;
if (m_isIsometry != isIsometry)
{
m_isIsometry = isIsometry;
@@ -1224,6 +1272,15 @@ void FrontendRenderer::ResolveZoomLevel(ScreenBase const & screen)
CheckIsometryMinScale(screen);
CheckPerspectiveMinScale();
+ UpdateDisplacementEnabled();
+}
+
+void FrontendRenderer::UpdateDisplacementEnabled()
+{
+ if (m_choosePositionMode)
+ m_overlayTree->SetDisplacementEnabled(m_currentZoomLevel < scales::GetAddNewPlaceScale());
+ else
+ m_overlayTree->SetDisplacementEnabled(true);
}
void FrontendRenderer::OnTap(m2::PointD const & pt, bool isLongTap)
@@ -1298,6 +1355,7 @@ void FrontendRenderer::OnDragStarted()
void FrontendRenderer::OnDragEnded(m2::PointD const & distance)
{
m_myPositionController->DragEnded(distance);
+ PullToBoundArea(false /* randomPlace */, false /* applyZoom */);
}
void FrontendRenderer::OnScaleStarted()
@@ -1328,6 +1386,7 @@ void FrontendRenderer::CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) con
void FrontendRenderer::OnScaleEnded()
{
m_myPositionController->ScaleEnded();
+ PullToBoundArea(false /* randomPlace */, false /* applyZoom */);
}
void FrontendRenderer::OnAnimationStarted(ref_ptr<BaseModelViewAnimation> anim)
diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp
index 461dc51aba..4e9e4d363d 100755
--- a/drape_frontend/frontend_renderer.hpp
+++ b/drape_frontend/frontend_renderer.hpp
@@ -32,6 +32,7 @@
#include "platform/location.hpp"
#include "geometry/screenbase.hpp"
+#include "geometry/triangle2d.hpp"
#include "std/function.hpp"
#include "std/map.hpp"
@@ -168,6 +169,7 @@ private:
TTilesCollection ResolveTileKeys(ScreenBase const & screen);
void ResolveZoomLevel(ScreenBase const & screen);
+ void UpdateDisplacementEnabled();
void CheckPerspectiveMinScale();
void CheckIsometryMinScale(ScreenBase const & screen);
@@ -229,6 +231,8 @@ private:
void PrepareGpsTrackPoints(size_t pointsCount);
+ void PullToBoundArea(bool randomPlace, bool applyZoom);
+
private:
drape_ptr<dp::GpuProgramManager> m_gpuProgramManager;
@@ -272,6 +276,8 @@ private:
bool m_blockTapEvents;
+ bool m_choosePositionMode;
+
Viewport m_viewport;
UserEventStream m_userEventStream;
TModelViewChanged m_modelViewChangedFn;
@@ -309,6 +315,8 @@ private:
unique_ptr<FollowRouteData> m_pendingFollowRoute;
+ vector<m2::TriangleD> m_dragBoundArea;
+
#ifdef DEBUG
bool m_isTeardowned;
#endif
diff --git a/drape_frontend/gui/layer_render.cpp b/drape_frontend/gui/layer_render.cpp
index 8ec711ab78..3282fc89ca 100644
--- a/drape_frontend/gui/layer_render.cpp
+++ b/drape_frontend/gui/layer_render.cpp
@@ -129,6 +129,11 @@ void LayerRenderer::OnTouchCancel(m2::RectD const & touchArea)
}
}
+bool LayerRenderer::HasWidget(EWidget widget) const
+{
+ return m_renderers.find(widget) != m_renderers.end();
+}
+
namespace
{
diff --git a/drape_frontend/gui/layer_render.hpp b/drape_frontend/gui/layer_render.hpp
index dd8f63e444..f48cf76c0c 100644
--- a/drape_frontend/gui/layer_render.hpp
+++ b/drape_frontend/gui/layer_render.hpp
@@ -35,6 +35,8 @@ public:
void OnTouchUp(m2::RectD const & touchArea);
void OnTouchCancel(m2::RectD const & touchArea);
+ bool HasWidget(EWidget widget) const;
+
private:
void DestroyRenderers();
diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp
index 52bfbde85e..ac33cf2521 100644
--- a/drape_frontend/message.hpp
+++ b/drape_frontend/message.hpp
@@ -54,7 +54,8 @@ public:
ShowChoosePositionMark,
SetKineticScrollEnabled,
BlockTapEvents,
- SetTimeInBackground
+ SetTimeInBackground,
+ SetAddNewPlaceMode
};
virtual ~Message() {}
diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp
index 84556e7cdd..b42da8c053 100644
--- a/drape_frontend/message_subclasses.hpp
+++ b/drape_frontend/message_subclasses.hpp
@@ -18,6 +18,7 @@
#include "geometry/polyline2d.hpp"
#include "geometry/rect2d.hpp"
#include "geometry/screenbase.hpp"
+#include "geometry/triangle2d.hpp"
#include "drape/glstate.hpp"
#include "drape/pointers.hpp"
@@ -328,6 +329,33 @@ private:
bool m_enabled;
};
+class SetAddNewPlaceModeMessage : public Message
+{
+public:
+ SetAddNewPlaceModeMessage(bool enable, vector<m2::TriangleD> && boundArea, bool enableKineticScroll,
+ bool hasPosition, m2::PointD const & position)
+ : m_enable(enable)
+ , m_boundArea(move(boundArea))
+ , m_enableKineticScroll(enableKineticScroll)
+ , m_hasPosition(hasPosition)
+ , m_position(position)
+ {}
+
+ Type GetType() const override { return Message::SetAddNewPlaceMode; }
+ vector<m2::TriangleD> && AcceptBoundArea() { return move(m_boundArea); }
+ bool IsEnabled() const { return m_enable; }
+ bool IsKineticScrollEnabled() const { return m_enableKineticScroll; }
+ bool HasPosition() const { return m_hasPosition; }
+ m2::PointD const & GetPosition() const { return m_position; }
+
+private:
+ bool m_enable;
+ vector<m2::TriangleD> m_boundArea;
+ bool m_enableKineticScroll;
+ bool m_hasPosition;
+ m2::PointD m_position;
+};
+
class BlockTapEventsMessage : public Message
{
public:
diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp
index 65200a910c..30ba569d01 100644
--- a/drape_frontend/my_position_controller.hpp
+++ b/drape_frontend/my_position_controller.hpp
@@ -95,12 +95,14 @@ public:
bool IsRouteFollowingActive() const;
bool IsWaitingForTimers() const;
+ bool IsWaitingForLocation() const;
+ m2::PointD GetDrawablePosition() const;
+
private:
bool IsModeChangeViewport() const;
void ChangeMode(location::EMyPositionMode newMode);
void SetDirection(double bearing);
- bool IsWaitingForLocation() const;
bool IsVisible() const { return m_isVisible; }
void SetIsVisible(bool isVisible) { m_isVisible = isVisible; }
@@ -114,7 +116,6 @@ private:
m2::PointD GetRotationPixelCenter() const;
m2::PointD GetRoutingRotationPixelCenter() const;
- m2::PointD GetDrawablePosition() const;
double GetDrawableAzimut() const;
void CheckAnimFinished() const;
void CreateAnim(m2::PointD const & oldPos, double oldAzimut, ScreenBase const & screen);
diff --git a/geometry/triangle2d.cpp b/geometry/triangle2d.cpp
index 1bd0f56f4c..c143729d72 100644
--- a/geometry/triangle2d.cpp
+++ b/geometry/triangle2d.cpp
@@ -1,8 +1,14 @@
#include "triangle2d.hpp"
+#include "distance.hpp"
#include "robust_orientation.hpp"
#include "segment2d.hpp"
+#include "base/math.hpp"
+
+#include "std/chrono.hpp"
+#include "std/random.hpp"
+
using namespace m2::robust;
namespace m2
@@ -37,4 +43,63 @@ bool IsPointStrictlyInsideTriangle(m2::PointD const & pt, m2::PointD const & p1,
(s1 < 0.0 && s2 < 0.0 && s3 < 0.0));
}
+bool IsPointInsideTriangles(m2::PointD const & pt, vector<m2::TriangleD> const & v)
+{
+ for (auto const & triangle : v)
+ {
+ if (IsPointInsideTriangle(pt, triangle.p1(), triangle.p2(), triangle.p3()))
+ return true;
+ }
+ return false;
+}
+
+m2::PointD GetRandomPointInsideTriangle(m2::TriangleD const & t)
+{
+ size_t kDistribMax = 1000;
+
+ default_random_engine engine(system_clock::now().time_since_epoch().count());
+ uniform_int_distribution<> distrib(0, kDistribMax);
+ double const r1 = sqrt(static_cast<double>(distrib(engine)) / kDistribMax);
+ double const r2 = static_cast<double>(distrib(engine)) / kDistribMax;
+ return t.m_points[0] * (1.0 - r1) + t.m_points[1] * r1 * (1.0 - r2) + t.m_points[2] * r2 * r1;
+}
+
+m2::PointD GetRandomPointInsideTriangles(vector<m2::TriangleD> const & v)
+{
+ if (v.empty())
+ return m2::PointD();
+
+ default_random_engine engine(system_clock::now().time_since_epoch().count());
+ uniform_int_distribution<> distrib(0, v.size() - 1);
+ return GetRandomPointInsideTriangle(v[distrib(engine)]);
+}
+
+m2::PointD ProjectPointToTriangles(m2::PointD const & pt, vector<m2::TriangleD> const & v)
+{
+ if (v.empty())
+ return pt;
+
+ auto distToLine = m2::DistanceToLineSquare<m2::PointD>();
+ int minT = -1;
+ int minI = -1;
+ double minDist = numeric_limits<double>::max();
+ for (int t = 0; t < static_cast<int>(v.size()); t++)
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ distToLine.SetBounds(v[t].m_points[i], v[t].m_points[(i + 1) % 3]);
+ double const dist = distToLine(pt);
+ if (dist < minDist)
+ {
+ minDist = dist;
+ minT = t;
+ minI = i;
+ }
+ }
+ }
+ auto projectToLine = m2::ProjectionToSection<m2::PointD>();
+ projectToLine.SetBounds(v[minT].m_points[minI], v[minT].m_points[(minI + 1) % 3]);
+ return projectToLine(pt);
+}
+
} // namespace m2;
diff --git a/geometry/triangle2d.hpp b/geometry/triangle2d.hpp
index 6dbfebde85..e63e8ee832 100644
--- a/geometry/triangle2d.hpp
+++ b/geometry/triangle2d.hpp
@@ -2,15 +2,43 @@
#include "point2d.hpp"
+#include "std/vector.hpp"
+
namespace m2
{
+template <typename T> struct Triangle
+{
+ Point<T> m_points[3];
+
+ Triangle(Point<T> const & p1, Point<T> const & p2, Point<T> const & p3)
+ {
+ m_points[0] = p1;
+ m_points[1] = p2;
+ m_points[2] = p3;
+ }
+
+ Point<T> const & p1() const { return m_points[0]; }
+ Point<T> const & p2() const { return m_points[1]; }
+ Point<T> const & p3() const { return m_points[2]; }
+};
+
+using TriangleF = Triangle<float>;
+using TriangleD = Triangle<double>;
+
template <class T>
double GetTriangleArea(Point<T> const & p1, Point<T> const & p2, Point<T> const & p3)
{
return 0.5 * fabs((p2.x - p1.x)*(p3.y - p1.y) - (p3.x - p1.x)*(p2.y - p1.y));
}
+m2::PointD GetRandomPointInsideTriangle(m2::TriangleD const & t);
+m2::PointD GetRandomPointInsideTriangles(vector<m2::TriangleD> const & v);
+
+// Project point to the nearest edge of the nearest triangle from list of triangles.
+// pt must be outside triangles.
+m2::PointD ProjectPointToTriangles(m2::PointD const & pt, vector<m2::TriangleD> const & v);
+
/// @param[in] pt - Point to check
/// @param[in] p1, p2, p3 - Triangle
//@{
@@ -19,6 +47,8 @@ bool IsPointInsideTriangle(m2::PointD const & pt, m2::PointD const & p1,
bool IsPointStrictlyInsideTriangle(m2::PointD const & pt, m2::PointD const & p1,
m2::PointD const & p2, m2::PointD const & p3);
+
+bool IsPointInsideTriangles(m2::PointD const & pt, vector<m2::TriangleD> const & v);
//@}
} // namespace m2
diff --git a/indexer/scales.hpp b/indexer/scales.hpp
index 2e0b21048a..10d9cc1c4a 100644
--- a/indexer/scales.hpp
+++ b/indexer/scales.hpp
@@ -18,14 +18,16 @@ namespace scales
constexpr int GetUpperCountryScale() { return GetUpperWorldScale() + 1; }
/// Upper scale for user comfort view (e.g. location zoom).
constexpr int GetUpperComfortScale() { return UPPER_STYLE_SCALE - 2; }
- /// Default navigation mode scale
+ /// Default navigation mode scale.
constexpr int GetNavigationScale() { return UPPER_STYLE_SCALE - 3; }
- /// Default pedestrian navigation mode scale
+ /// Default pedestrian navigation mode scale.
constexpr int GetPedestrianNavigationScale() { return UPPER_STYLE_SCALE - 2; }
- /// Default navigation 3d mode scale
+ /// Default navigation 3d mode scale.
constexpr int GetNavigation3dScale() { return UPPER_STYLE_SCALE - 2; }
- /// Default pedestrian navigation 3d mode scale
+ /// Default pedestrian navigation 3d mode scale.
constexpr int GetPedestrianNavigation3dScale() { return UPPER_STYLE_SCALE - 2; }
+ /// Default scale in adding-new-place mode.
+ constexpr int GetAddNewPlaceScale() { return 18; }
int GetMinAllowableIn3dScale();
diff --git a/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.h b/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.h
index afbe13ece1..b3fc3166dc 100644
--- a/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.h
+++ b/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.h
@@ -1,5 +1,9 @@
+#include "geometry/point2d.hpp"
+
@interface MWMAddPlaceNavigationBar : SolidTouchView
-+ (void)showInSuperview:(nonnull UIView *)superview doneBlock:(nonnull TMWMVoidBlock)done cancelBlock:(nonnull TMWMVoidBlock)cancel;
++ (void)showInSuperview:(UIView *)superview isBusiness:(BOOL)isBusiness
+ applyPosition:(BOOL)applyPosition position:(m2::PointD const &)position
+ doneBlock:(TMWMVoidBlock)done cancelBlock:(TMWMVoidBlock)cancel;
@end
diff --git a/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.mm b/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.mm
index 49338c74af..3fd88dae6e 100644
--- a/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.mm
+++ b/iphone/Maps/Classes/Components/MWMAddPlaceNavigationBar.mm
@@ -12,7 +12,9 @@
@implementation MWMAddPlaceNavigationBar
-+ (void)showInSuperview:(UIView *)superview doneBlock:(TMWMVoidBlock)done cancelBlock:(TMWMVoidBlock)cancel
++ (void)showInSuperview:(UIView *)superview isBusiness:(BOOL)isBusiness
+ applyPosition:(BOOL)applyPosition position:(m2::PointD const &)position
+ doneBlock:(TMWMVoidBlock)done cancelBlock:(TMWMVoidBlock)cancel
{
MWMAddPlaceNavigationBar * navBar = [[[NSBundle mainBundle] loadNibNamed:self.className owner:nil options:nil] firstObject];
navBar.width = superview.width;
@@ -22,13 +24,13 @@
[navBar setNeedsLayout];
navBar.origin = {0., -navBar.height};
[superview addSubview:navBar];
- [navBar show];
+ [navBar show:isBusiness applyPosition:applyPosition position:position];
}
-- (void)show
+- (void)show:(BOOL)enableBounds applyPosition:(BOOL)applyPosition position:(m2::PointD const &)position
{
auto & f = GetFramework();
- f.EnableChoosePositionMode(true);
+ f.EnableChoosePositionMode(true /* enable */, enableBounds, applyPosition, position);
f.BlockTapEvents(true);
[UIView animateWithDuration:kDefaultAnimationDuration animations:^
@@ -40,7 +42,7 @@
- (void)dismiss
{
auto & f = GetFramework();
- f.EnableChoosePositionMode(false);
+ f.EnableChoosePositionMode(false /* enable */, false /* enableBounds */, false /* applyPosition */, m2::PointD());
f.BlockTapEvents(false);
[UIView animateWithDuration:kDefaultAnimationDuration animations:^
diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.h b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.h
index af66ba8c48..b7cda5a317 100644
--- a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.h
+++ b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.h
@@ -9,7 +9,7 @@
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode;
- (void)closeInfoScreens;
-- (void)addPlace;
+- (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point;
- (void)didFinishAddingPlace;
@end
diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm
index 22081c793f..2ad3c43d8c 100644
--- a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm
+++ b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm
@@ -351,7 +351,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell)
{
[Statistics logEvent:kStatEditorAddClick withParameters:@{kStatValue : kStatMenu}];
self.state = self.restoreState;
- [self.delegate addPlace];
+ [self.delegate addPlace:NO hasPoint:NO point:m2::PointD()];
}
- (void)menuActionDownloadMaps
diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm
index dc9298bce9..70a41a3a94 100644
--- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm
+++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm
@@ -305,14 +305,15 @@ extern NSString * const kAlohalyticsTapEventKey;
#pragma mark - MWMBottomMenuControllerProtocol && MWMPlacePageViewManagerProtocol
-- (void)addPlace
+- (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point
{
self.menuState = MWMBottomMenuStateHidden;
static_cast<EAGLView *>(self.ownerController.view).widgetsManager.fullScreen = YES;
[self.placePageManager dismissPlacePage];
self.searchManager.state = MWMSearchManagerStateHidden;
- [MWMAddPlaceNavigationBar showInSuperview:self.ownerController.view doneBlock:^
+ [MWMAddPlaceNavigationBar showInSuperview:self.ownerController.view
+ isBusiness:isBusiness applyPosition:hasPoint position:point doneBlock:^
{
auto & f = GetFramework();
@@ -361,12 +362,6 @@ extern NSString * const kAlohalyticsTapEventKey;
}
}
-- (void)addBusinessToPoint:(m2::PointD const &)point
-{
- GetFramework().SetViewportCenter(point);
- [self addPlace];
-}
-
- (void)updateStatusBarStyle
{
[self.ownerController updateStatusBarStyle];
diff --git a/iphone/Maps/Classes/MWMPlacePageViewManager.mm b/iphone/Maps/Classes/MWMPlacePageViewManager.mm
index 325e244df2..0e9c81ff09 100644
--- a/iphone/Maps/Classes/MWMPlacePageViewManager.mm
+++ b/iphone/Maps/Classes/MWMPlacePageViewManager.mm
@@ -260,12 +260,12 @@ extern NSString * const kBookmarksChangedNotification;
- (void)addBusiness
{
- [self.delegate addBusinessToPoint:self.entity.mercator];
+ [self.delegate addPlace:YES hasPoint:NO point:m2::PointD()];
}
- (void)addPlace
{
- [self.delegate addPlace];
+ [self.delegate addPlace:NO hasPoint:YES point:self.entity.mercator];
}
- (void)addBookmark
diff --git a/iphone/Maps/Classes/MWMPlacePageViewManagerDelegate.h b/iphone/Maps/Classes/MWMPlacePageViewManagerDelegate.h
index 104d40707b..6421213899 100644
--- a/iphone/Maps/Classes/MWMPlacePageViewManagerDelegate.h
+++ b/iphone/Maps/Classes/MWMPlacePageViewManagerDelegate.h
@@ -9,7 +9,6 @@
- (void)updateStatusBarStyle;
- (void)apiBack;
- (void)placePageDidClose;
-- (void)addBusinessToPoint:(m2::PointD const &)point;
-- (void)addPlace;
+- (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point;
@end \ No newline at end of file
diff --git a/map/framework.cpp b/map/framework.cpp
index b69c1b8e7a..5d4f9922eb 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -60,6 +60,7 @@
#include "geometry/angles.hpp"
#include "geometry/distance_on_sphere.hpp"
+#include "geometry/triangle2d.hpp"
#include "base/math.hpp"
#include "base/timer.hpp"
@@ -1489,7 +1490,7 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> contextFactory,
params.m_visualScale, move(params.m_widgetsInitInfo),
make_pair(params.m_initialMyPositionState, params.m_hasMyPositionState),
allow3dBuildings, params.m_isChoosePositionMode,
- params.m_isChoosePositionMode, params.m_isFirstLaunch);
+ params.m_isChoosePositionMode, GetSelectedFeatureTriangles(), params.m_isFirstLaunch);
m_drapeEngine = make_unique_dp<df::DrapeEngine>(move(p));
AddViewportListener([this](ScreenBase const & screen)
@@ -1858,6 +1859,7 @@ void Framework::ActivateMapSelection(bool needAnimation, df::SelectionShape::ESe
place_page::Info const & info) const
{
ASSERT_NOT_EQUAL(selectionType, df::SelectionShape::OBJECT_EMPTY, ("Empty selections are impossible."));
+ m_selectedFeature = info.GetID();
CallDrapeFunction(bind(&df::DrapeEngine::SelectObject, _1, selectionType, info.GetMercator(),
needAnimation));
if (m_activateMapSelectionFn)
@@ -2418,9 +2420,32 @@ void Framework::Load3dMode(bool & allow3d, bool & allow3dBuildings)
allow3dBuildings = true;
}
-void Framework::EnableChoosePositionMode(bool enable)
+void Framework::EnableChoosePositionMode(bool enable, bool enableBounds, bool applyPosition, m2::PointD const & position)
{
- CallDrapeFunction(bind(&df::DrapeEngine::EnableChoosePositionMode, _1, enable));
+ if (m_drapeEngine != nullptr)
+ m_drapeEngine->EnableChoosePositionMode(enable, enableBounds ? GetSelectedFeatureTriangles() : vector<m2::TriangleD>(),
+ applyPosition, position);
+}
+
+vector<m2::TriangleD> Framework::GetSelectedFeatureTriangles() const
+{
+ vector<m2::TriangleD> triangles;
+ if (m_selectedFeature.IsValid())
+ {
+ Index::FeaturesLoaderGuard const guard(m_model.GetIndex(), m_selectedFeature.m_mwmId);
+ FeatureType ft;
+ guard.GetFeatureByIndex(m_selectedFeature.m_index, ft);
+ if (ftypes::IsBuildingChecker::Instance()(feature::TypesHolder(ft)))
+ {
+ triangles.reserve(10);
+ ft.ForEachTriangle([&](m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3)
+ {
+ triangles.push_back(m2::TriangleD(p1, p2, p3));
+ }, scales::GetUpperScale());
+ }
+ m_selectedFeature = FeatureID();
+ }
+ return triangles;
}
void Framework::BlockTapEvents(bool block)
diff --git a/map/framework.hpp b/map/framework.hpp
index 18ca2d8a50..8666b610c1 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -276,7 +276,7 @@ public:
void InvalidateRendering();
- void EnableChoosePositionMode(bool enable);
+ void EnableChoosePositionMode(bool enable, bool enableBounds, bool applyPosition, m2::PointD const & position);
void BlockTapEvents(bool block);
using TCurrentCountryChanged = function<void(storage::TCountryId const &)>;
@@ -303,6 +303,12 @@ private:
TActivateMapSelectionFn m_activateMapSelectionFn;
TDeactivateMapSelectionFn m_deactivateMapSelectionFn;
+ /// Here we store last selected feature to get its polygons in case of adding organization.
+ mutable FeatureID m_selectedFeature;
+
+private:
+ vector<m2::TriangleD> GetSelectedFeatureTriangles() const;
+
public:
/// @name GPS location updates routine.
diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp
index 3988b3df26..916abe3185 100644
--- a/qt/draw_widget.cpp
+++ b/qt/draw_widget.cpp
@@ -231,12 +231,12 @@ void DrawWidget::SliderReleased()
void DrawWidget::ChoosePositionModeEnable()
{
m_framework->BlockTapEvents(true);
- m_framework->EnableChoosePositionMode(true);
+ m_framework->EnableChoosePositionMode(true, false, false, m2::PointD());
}
void DrawWidget::ChoosePositionModeDisable()
{
- m_framework->EnableChoosePositionMode(false);
+ m_framework->EnableChoosePositionMode(false, false, false, m2::PointD());
m_framework->BlockTapEvents(false);
}