diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index fdf54d7366..b390f84dc0 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -820,6 +820,24 @@ extern "C" jniEnv->CallVoidMethod(*obj.get(), methodId, j_name, j_type, j_address, lat, lon); } + pair NativeMetadataToJavaMetadata(JNIEnv * jniEnv, feature::FeatureMetadata const & metadata) + { + const vector metaTypes = metadata.GetPresentTypes(); + const jintArray j_metaTypes = jniEnv->NewIntArray(metadata.Size()); + jint * arr = jniEnv->GetIntArrayElements(j_metaTypes, 0); + const jobjectArray j_metaValues = jniEnv->NewObjectArray(metadata.Size(), jni::GetStringClass(jniEnv), 0); + + for (int i = 0; i < metaTypes.size(); i++) + { + arr[i] = metaTypes[i]; + feature::FeatureMetadata::EMetadataType metaType = static_cast(metaTypes[i]); + jniEnv->SetObjectArrayElement(j_metaValues, i, jni::ToJavaString(jniEnv, metadata.Get(metaType))); + } + jniEnv->ReleaseIntArrayElements(j_metaTypes, arr, 0); + + return make_pair(j_metaTypes, j_metaValues); + } + // POI void CallOnPoiActivatedListener(shared_ptr obj, m2::PointD const & globalPoint, search::AddressInfo const & addrInfo, feature::FeatureMetadata const & metadata) @@ -832,22 +850,12 @@ extern "C" const double lon = MercatorBounds::XToLon(globalPoint.x); const double lat = MercatorBounds::YToLat(globalPoint.y); - const vector metaTypes = metadata.GetPresentTypes(); - const jintArray j_metaTypes = jniEnv->NewIntArray(metadata.Size()); - jint * arr = jniEnv->GetIntArrayElements(j_metaTypes, 0); - const jobjectArray j_metaValues = jniEnv->NewObjectArray(metadata.Size(), jni::GetStringClass(jniEnv), 0); - for (int i = 0; i < metaTypes.size(); i++) - { - arr[i] = metaTypes[i]; - feature::FeatureMetadata::EMetadataType metaType = static_cast(metaTypes[i]); - jniEnv->SetObjectArrayElement(j_metaValues, i, jni::ToJavaString(jniEnv, metadata.Get(metaType))); - } - jniEnv->ReleaseIntArrayElements(j_metaTypes, arr, 0); + pair const meta = NativeMetadataToJavaMetadata(jniEnv, metadata); const char * signature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;DD[I[Ljava/lang/String;)V"; const jmethodID methodId = jni::GetJavaMethodID(jniEnv, *obj.get(), "onPoiActivated", signature); - jniEnv->CallVoidMethod(*obj.get(), methodId, j_name, j_type, j_address, lat, lon, j_metaTypes, j_metaValues); + jniEnv->CallVoidMethod(*obj.get(), methodId, j_name, j_type, j_address, lat, lon, meta.first, meta.second); } // Bookmark @@ -873,6 +881,7 @@ extern "C" ::Framework * fm = frm(); UserMark const * mark = markCopy->GetUserMark(); fm->ActivateUserMark(mark); + switch (mark->GetMarkType()) { case UserMark::API: @@ -880,32 +889,43 @@ extern "C" double lat, lon; mark->GetLatLon(lat, lon); CallOnApiPointActivatedListener(obj, CastMark(mark), lat, lon); + break; } - break; + case UserMark::BOOKMARK: { BookmarkAndCategory bmAndCat = fm->FindBookmark(mark); if (IsValid(bmAndCat)) + { + feature::FeatureMetadata metadata; + fm->FindClosestPOIMetadata(mark->GetOrg(), metadata); CallOnBookmarkActivatedListener(obj, bmAndCat); + } + break; } - break; + case UserMark::POI: { PoiMarkPoint const * poiMark = CastMark(mark); CallOnPoiActivatedListener(obj, mark->GetOrg(), poiMark->GetInfo(), poiMark->GetMetadata()); + break; } - break; + case UserMark::SEARCH: { SearchMarkPoint const * searchMark = CastMark(mark); + feature::FeatureMetadata metadata; + fm->FindClosestPOIMetadata(mark->GetOrg(), metadata); CallOnAdditionalLayerActivatedListener(obj, searchMark->GetOrg(), searchMark->GetInfo()); break; } + case UserMark::MY_POSITION: { double lat, lon; mark->GetLatLon(lat, lon); CallOnMyPositionActivatedListener(obj, lat, lon); + break; } } } diff --git a/map/framework.cpp b/map/framework.cpp index a2f6b4fbc0..d39f47dfaa 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1731,6 +1731,60 @@ bool Framework::GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, return false; } +namespace +{ + +/// POI - is a point or area feature. +class DoFindClosestPOI +{ + m2::PointD const & m_pt; + double m_distMeters; + FeatureID m_id; + +public: + DoFindClosestPOI(m2::PointD const & pt, double tresholdMeters) + : m_pt(pt), m_distMeters(tresholdMeters) + { + } + + void operator() (FeatureType & ft) + { + if (ft.GetFeatureType() == feature::GEOM_LINE) + return; + + double const dist = MercatorBounds::DistanceOnEarth(m_pt, feature::GetCenter(ft)); + if (dist < m_distMeters) + { + m_distMeters = dist; + m_id = ft.GetID(); + } + } + + void LoadMetadata(model::FeaturesFetcher const & model, feature::FeatureMetadata & metadata) const + { + if (!m_id.IsValid()) + return; + + Index::FeaturesLoaderGuard guard(model.GetIndex(), m_id.m_mwm); + + FeatureType ft; + guard.GetFeature(m_id.m_offset, ft); + + ft.ParseMetadata(); + metadata = ft.GetMetadata(); + } +}; + +} + +void Framework::FindClosestPOIMetadata(m2::PointD const & pt, feature::FeatureMetadata & metadata) const +{ + DoFindClosestPOI doFind(pt, 1.1 /* search radius in meters */); + m_model.ForEachFeature(m2::RectD(pt, pt), doFind, scales::GetUpperScale() /* scale level for POI */); + + doFind.LoadMetadata(m_model, metadata); +} + Animator & Framework::GetAnimator() { return m_animator; diff --git a/map/framework.hpp b/map/framework.hpp index fd4d3a7943..c1c0d256bb 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -358,6 +358,7 @@ private: public: bool GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, search::AddressInfo & info, feature::FeatureMetadata & metadata) const; + void FindClosestPOIMetadata(m2::PointD const & pt, feature::FeatureMetadata & metadata) const; #ifndef USE_DRAPE virtual void BeginPaint(shared_ptr const & e);