Compare commits

..

16 Commits

Author SHA1 Message Date
matheusgomesms
f4eb8628e0 Atualizar generator/maxspeeds_builder.cpp
Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-12-09 21:35:32 +01:00
matheusgomesms
4c715cd2ee Removing maxspeed estimate from generator
Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-12-09 15:04:24 +01:00
Jean-Baptiste
c2bc6c27aa [android] Add warning about speed cameras in settings
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-08 18:13:11 +01:00
gekeleda
1095e5dbc3 [android] Consider all system langs for TTS
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-08 15:55:49 +01:00
Leonardo Bishop
a1cbcc5885 [drape] Base zoom level on distance to next turn
This commit changes the auto zoom level behaviour during navigation
to be based off the distance to the next turn, rather than naively
coupling it to the current speed. This will improve the navigation
experience during driving.

Signed-off-by: Leonardo Bishop <me@leonardobishop.net>
2025-12-08 08:31:33 +01:00
Jean-Baptiste
641f2308c6 [android] Remove hardocded height of name text field
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-07 18:01:17 +01:00
Konstantin Pastbin
f858ebcce0 [generator] Make Taiwan_North use 5 threads for Index stage
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-07 14:06:13 +07:00
matheusgomesms
eb376f5afc Added missing Portuguese articles
Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-12-06 20:54:14 +01:00
x7z4w
71b47719af [search] Remove stop words
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-06 19:43:11 +00:00
Konstantin Pastbin
4f7230fcbe [generator] Clone repos shallowly --depth 1
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-06 08:12:42 +01:00
Konstantin Pastbin
2dafdd4338 [generator] Fix boolean action options handling
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-06 08:12:42 +01:00
Konstantin Pastbin
0237751afe [generator] Fix GENARGS in docker_maps_generator.sh
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-06 08:12:42 +01:00
Jean-Baptiste
e7fb3a2f2c [android] Improve padding of instructions during navigation
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-05 22:30:03 +01:00
x7z4w
e08d60bb40 [styles] Fix toilets label
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-05 22:11:42 +01:00
Jean-Baptiste
de4252f86c [android] Remove transparent background on textview
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-05 21:51:27 +01:00
Jean-Baptiste
9d87d77055 [android] Improve size of bookmarks button
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-05 17:53:54 +01:00
36 changed files with 307 additions and 192 deletions

View File

@@ -107,6 +107,7 @@ import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.settings.RoadType; import app.organicmaps.sdk.settings.RoadType;
import app.organicmaps.sdk.settings.UnitLocale; import app.organicmaps.sdk.settings.UnitLocale;
import app.organicmaps.sdk.sound.TtsPlayer;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.PowerManagment; import app.organicmaps.sdk.util.PowerManagment;
@@ -132,7 +133,6 @@ import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
@@ -1813,6 +1813,18 @@ public class MwmActivity extends BaseMwmFragmentActivity
return false; return false;
} }
private void deliverTtsMessage()
{
if (Config.isTtsMessageDelivered())
return;
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
navigationStartMessage += TtsPlayer.INSTANCE.getLanguageDisplayName();
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
Config.setTtsMessageDelivered();
}
private boolean showStartPointNotice() private boolean showStartPointNotice()
{ {
final RoutingController controller = RoutingController.get(); final RoutingController controller = RoutingController.get();
@@ -2189,6 +2201,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!showRoutingDisclaimer()) if (!showRoutingDisclaimer())
return; return;
deliverTtsMessage();
closeFloatingPanels(); closeFloatingPanels();
setFullscreen(false); setFullscreen(false);
RoutingController.get().start(); RoutingController.get().start();

View File

@@ -24,6 +24,6 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:fontFamily="@string/robotoMedium" android:fontFamily="@string/robotoMedium"
tools:text="Some text should go here" tools:text="Some text should go here"
android:textAppearance="@style/MwmTextAppearance.Body3" android:textAppearance="@style/MwmTextAppearance.Body1"
android:textColor="?colorSecondary"/> android:textColor="?colorSecondary"/>
</LinearLayout> </LinearLayout>

View File

@@ -25,7 +25,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start|bottom" android:layout_gravity="start|bottom"
android:background="@android:color/transparent"
android:clickable="true" android:clickable="true"
android:gravity="start|top" android:gravity="start|top"
android:text="@string/category_desc_more" android:text="@string/category_desc_more"

View File

@@ -4,7 +4,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/editor_height_field" android:layout_height="wrap_content"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
@@ -14,8 +14,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:hint="@string/editor_edit_place_name_hint" android:hint="@string/editor_edit_place_name_hint">
android:textColorHint="?android:textColorSecondary">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/input" android:id="@+id/input"
style="@style/MwmWidget.Editor.FieldLayout.EditText" style="@style/MwmWidget.Editor.FieldLayout.EditText"
@@ -31,5 +30,5 @@
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:padding="@dimen/margin_half_plus" android:padding="@dimen/margin_half_plus"
app:srcCompat="@drawable/ic_close" app:srcCompat="@drawable/ic_close"
app:tint="@color/base_red" /> app:tint="?iconTint" />
</LinearLayout> </LinearLayout>

View File

@@ -35,10 +35,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:maxLines="2" android:maxLines="2"
android:padding="@dimen/margin_quarter" android:padding="@dimen/margin_half"
android:autoSizeTextType="uniform" android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="19sp" android:autoSizeMinTextSize="19sp"
android:autoSizeMaxTextSize="25sp" android:autoSizeMaxTextSize="24sp"
android:minHeight="60dp" android:minHeight="60dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:gravity="center" android:gravity="center"

View File

@@ -34,8 +34,7 @@
android:textAppearance="?android:attr/textAppearance" android:textAppearance="?android:attr/textAppearance"
android:gravity="start|top" android:gravity="start|top"
android:textColor="?attr/colorSecondary" android:textColor="?attr/colorSecondary"
android:text="@string/category_desc_more" android:text="@string/category_desc_more" />
android:background="@android:color/transparent"/>
<include <include
layout="@layout/item_divider"/> layout="@layout/item_divider"/>
</LinearLayout> </LinearLayout>

View File

@@ -23,6 +23,7 @@
<string name="pref_tts_info" translatable="false">TtsInfo</string> <string name="pref_tts_info" translatable="false">TtsInfo</string>
<string name="pref_tts_info_link" translatable="false">TtsInfoLink</string> <string name="pref_tts_info_link" translatable="false">TtsInfoLink</string>
<string name="pref_tts_speed_cameras" translatable="false">SpeedCameras</string> <string name="pref_tts_speed_cameras" translatable="false">SpeedCameras</string>
<string name="pref_tts_speed_cameras_info" translatable="false">SpeedCamerasInfo</string>
<string name="prefs_routing" translatable="false">RoutingOptions</string> <string name="prefs_routing" translatable="false">RoutingOptions</string>
<string name="pref_autodownload" translatable="false">AutoDownloadMap</string> <string name="pref_autodownload" translatable="false">AutoDownloadMap</string>
<string name="pref_3d" translatable="false">3D</string> <string name="pref_3d" translatable="false">3D</string>

View File

@@ -609,6 +609,7 @@
\nOpen your device\'s settings → Language and input → Speech → Text to speech output. \nOpen your device\'s settings → Language and input → Speech → Text to speech output.
\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine.</string> \nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine.</string>
<string name="prefs_languages_information_off_link">For more information please check this guide</string> <string name="prefs_languages_information_off_link">For more information please check this guide</string>
<string name="prefs_speed_cameras_information">Speed camera warnings are disabled in countries where alerts are prohibited by local law.</string>
<string name="transliteration_title">Transliterate into Latin alphabet</string> <string name="transliteration_title">Transliterate into Latin alphabet</string>
<string name="learn_more">Learn more</string> <string name="learn_more">Learn more</string>
<!-- User selected the destination by pressing Route To, but the current position is unknown. User needs to select a starting point of a route using search or by tapping on the map and then pressing "Route From". --> <!-- User selected the destination by pressing Route To, but the current position is unknown. User needs to select a starting point of a route using search or by tapping on the map and then pressing "Route From". -->
@@ -932,6 +933,7 @@
<string name="share_track">Share Track</string> <string name="share_track">Share Track</string>
<string name="delete_track_dialog_title">Delete %s?</string> <string name="delete_track_dialog_title">Delete %s?</string>
<string name="pref_tts_no_system_tts_short">No text-to-speech engine found, check the app settings</string> <string name="pref_tts_no_system_tts_short">No text-to-speech engine found, check the app settings</string>
<string name="navigation_start_tts_message">"Starting Navigation, voice instruction language: "</string>
<string name="unknown_power_output">unknown</string> <string name="unknown_power_output">unknown</string>
<string name="charge_socket_type2">Type 2 (no cable)</string> <string name="charge_socket_type2">Type 2 (no cable)</string>
<string name="charge_socket_type2_cable">Type 2 (w/ cable)</string> <string name="charge_socket_type2_cable">Type 2 (w/ cable)</string>

View File

@@ -57,4 +57,11 @@
android:entryValues="@array/speed_cameras_values" android:entryValues="@array/speed_cameras_values"
android:defaultValue="@string/auto_enum_value" android:defaultValue="@string/auto_enum_value"
app:iconSpaceReserved="false" /> app:iconSpaceReserved="false" />
<Preference
android:enabled="true"
android:key="@string/pref_tts_info_link"
android:persistent="false"
android:selectable="false"
android:summary="@string/prefs_speed_cameras_information"
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>

View File

@@ -1,6 +1,7 @@
package app.organicmaps.sdk.sound; package app.organicmaps.sdk.sound;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
@@ -14,6 +15,8 @@ import android.util.Pair;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat;
import androidx.media.AudioAttributesCompat; import androidx.media.AudioAttributesCompat;
import androidx.media.AudioFocusRequestCompat; import androidx.media.AudioFocusRequestCompat;
import androidx.media.AudioManagerCompat; import androidx.media.AudioManagerCompat;
@@ -23,6 +26,7 @@ import app.organicmaps.sdk.util.log.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set;
/** /**
* {@code TtsPlayer} class manages available TTS voice languages. * {@code TtsPlayer} class manages available TTS voice languages.
@@ -33,9 +37,9 @@ import java.util.Locale;
* unsupported voices are excluded. * unsupported voices are excluded.
* <p> * <p>
* At startup we check whether currently selected language is in our list of supported voices and its data is * At startup we check whether currently selected language is in our list of supported voices and its data is
* downloaded. If not, we check system default locale. If failed, the same check is made for English language. Finally, * downloaded. If not, we check system default locale. If failed, the same check is made for other system locales.
* if mentioned checks fail we manually disable TTS, so the user must go to the settings and select preferred voice * If those fail too, we check for English language. Then, as a final resort, all installed TTS locales are checked.
* language by hand. <p> If no core supported languages can be used by the system, TTS is locked down and can not be * <p> If no core supported languages can be used by the system, TTS is locked down and can not be
* enabled and used. * enabled and used.
*/ */
public enum TtsPlayer public enum TtsPlayer
@@ -78,6 +82,8 @@ public enum TtsPlayer
// TTS is locked down due to absence of supported languages // TTS is locked down due to absence of supported languages
private boolean mUnavailable; private boolean mUnavailable;
private LocaleListCompat mInstalledSystemLocales;
TtsPlayer() {} TtsPlayer() {}
private static @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs) private static @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs)
@@ -126,28 +132,57 @@ public enum TtsPlayer
return (lang != null && setLanguageInternal(lang)); return (lang != null && setLanguageInternal(lang));
} }
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs) public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
{
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
}
private @Nullable LanguageData getSystemLanguage(List<LanguageData> langs)
{ {
LanguageData res; LanguageData res;
// Try default system locale
Locale defLocale = Locale.getDefault(); Locale defLocale = Locale.getDefault();
if (defLocale != null) res = findSupportedLanguage(defLocale, langs);
if (res != null && res.downloaded)
return res;
// Try other installed system locales
for (int i = 0; i < mInstalledSystemLocales.size(); i++)
{ {
res = findSupportedLanguage(defLocale, langs); Locale loc = mInstalledSystemLocales.get(i);
res = findSupportedLanguage(loc, langs);
if (res != null && res.downloaded)
return res;
}
return null;
}
private @Nullable LanguageData getTTSLanguage(List<LanguageData> langs)
{
LanguageData res;
// Try all TTS installed languages
Set<Locale> ttsLocales = mTts.getAvailableLanguages();
for (Locale loc : ttsLocales)
{
res = findSupportedLanguage(loc, langs);
if (res != null && res.downloaded) if (res != null && res.downloaded)
return res; return res;
} }
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
if (res != null && res.downloaded)
return res;
return null; return null;
} }
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs) private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
{ {
return findSupportedLanguage(Config.TTS.getLanguage(), langs); LanguageData res;
// Try default app locale (en.US)
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
if (res != null && res.downloaded)
return res;
return null;
} }
private void lockDown() private void lockDown()
@@ -167,6 +202,10 @@ public enum TtsPlayer
// TextToSpeech.OnInitListener() can be called from a non-main thread // TextToSpeech.OnInitListener() can be called from a non-main thread
// on LineageOS '20.0-20231127-RELEASE-thyme' 'Xiaomi/thyme/thyme'. // on LineageOS '20.0-20231127-RELEASE-thyme' 'Xiaomi/thyme/thyme'.
// https://github.com/organicmaps/organicmaps/issues/6903 // https://github.com/organicmaps/organicmaps/issues/6903
Configuration config = context.getResources().getConfiguration();
mInstalledSystemLocales = ConfigurationCompat.getLocales(config);
mTts = new TextToSpeech(context, status -> UiThread.run(() -> { mTts = new TextToSpeech(context, status -> UiThread.run(() -> {
if (status == TextToSpeech.ERROR) if (status == TextToSpeech.ERROR)
{ {
@@ -239,6 +278,17 @@ public enum TtsPlayer
return (INSTANCE.mTts != null && !INSTANCE.mUnavailable && !INSTANCE.mInitializing); return (INSTANCE.mTts != null && !INSTANCE.mUnavailable && !INSTANCE.mInitializing);
} }
public Locale getVoiceLocale()
{
return mTts.getVoice().getLocale();
}
public String getLanguageDisplayName()
{
Locale locale = getVoiceLocale();
return locale.getDisplayName(locale);
}
public void speak(String textToSpeak) public void speak(String textToSpeak)
{ {
if (Config.TTS.isEnabled()) if (Config.TTS.isEnabled())
@@ -328,24 +378,49 @@ public enum TtsPlayer
if (outList.isEmpty()) if (outList.isEmpty())
{ {
// No supported languages found, lock down TTS :( Logger.d("TtsPlayer", "No supported languages found, lock down TTS :( ");
lockDown(); lockDown();
return null; return null;
} }
LanguageData res = getSelectedLanguage(outList); LanguageData res = getSelectedLanguage(outList);
if (res == null || !res.downloaded) if (res != null && res.downloaded)
// Selected locale is not available or not downloaded
res = getDefaultLanguage(outList);
if (res == null || !res.downloaded)
{ {
// Default locale can not be used too Logger.d("TtsPlayer", "Selected locale " + res.internalCode + " will be used for TTS");
Config.TTS.setEnabled(false); return res;
return null; }
Logger.d("TtsPlayer", "Selected locale " + Config.TTS.getLanguage()
+ " is not available or not downloaded, trying system locales...");
res = getSystemLanguage(outList);
if (res != null && res.downloaded)
{
Logger.d("TtsPlayer", "System locale " + res.internalCode + " will be used for TTS");
return res;
}
Logger.d("TtsPlayer",
"None of the system locales are available, or they are not downloaded, trying default locale...");
res = getDefaultLanguage(outList);
if (res != null && res.downloaded)
{
Logger.d("TtsPlayer", "Default locale " + res.internalCode + " will be used for TTS");
return res;
}
Logger.d("TtsPlayer",
"Default locale " + DEFAULT_LOCALE + " can not be used either, trying all installed TTS locales...");
res = getTTSLanguage(outList);
if (res != null && res.downloaded)
{
Logger.d("TtsPlayer", "TTS locale " + res.internalCode + " will be used for TTS");
return res;
} }
return res; Logger.d("TtsPlayer",
"None of the TTS engine locales are available, or they are not downloaded, disabling TTS :( ");
Config.TTS.setEnabled(false);
return null;
} }
public @NonNull List<LanguageData> refreshLanguages() public @NonNull List<LanguageData> refreshLanguages()

View File

@@ -36,6 +36,7 @@ public final class Config
private static final String KEY_PREF_USE_GS = "UseGoogleServices"; private static final String KEY_PREF_USE_GS = "UseGoogleServices";
private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved"; private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved";
private static final String KEY_MISC_TTS_MESSAGE_DELIVERED = "TtsMessageDelivered";
private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested"; private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested";
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData"; private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp"; private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
@@ -237,6 +238,16 @@ public final class Config
setBool(KEY_MISC_DISCLAIMER_ACCEPTED); setBool(KEY_MISC_DISCLAIMER_ACCEPTED);
} }
public static boolean isTtsMessageDelivered()
{
return getBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
}
public static void setTtsMessageDelivered()
{
setBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
}
public static boolean isLocationRequested() public static boolean isLocationRequested()
{ {
return getBool(KEY_MISC_LOCATION_REQUESTED); return getBool(KEY_MISC_LOCATION_REQUESTED);

View File

@@ -13,7 +13,6 @@ node[shop],
node[amenity=car_wash], node[amenity=car_wash],
node[amenity=fuel], node[amenity=fuel],
node[amenity=studio], node[amenity=studio],
node[amenity=toilets],
node[amenity=vehicle_inspection], node[amenity=vehicle_inspection],
node[craft], node[craft],
node[landuse=industrial][industrial=mine], node[landuse=industrial][industrial=mine],
@@ -138,6 +137,7 @@ node[amenity=prison],
node[amenity=recycling][recycling_type=centre], node[amenity=recycling][recycling_type=centre],
node[amenity=sailing_school], node[amenity=sailing_school],
node[amenity=school], node[amenity=school],
node[amenity=toilets],
node[amenity=townhall], node[amenity=townhall],
node[amenity=university][name], node[amenity=university][name],
node[barrier=border_control], node[barrier=border_control],

View File

@@ -151,7 +151,7 @@ public:
// Set speed as-is from parent link. // Set speed as-is from parent link.
if (parentHwType == hwType) if (parentHwType == hwType)
return {{s.GetForward(), s.GetUnits()}}; return {{s.GetForward(), s.GetUnits()}};
/*
using routing::HighwayType; using routing::HighwayType;
if ((*parentHwType == HighwayType::HighwayMotorway && hwType == HighwayType::HighwayMotorwayLink) || if ((*parentHwType == HighwayType::HighwayMotorway && hwType == HighwayType::HighwayMotorwayLink) ||
(*parentHwType == HighwayType::HighwayTrunk && hwType == HighwayType::HighwayTrunkLink) || (*parentHwType == HighwayType::HighwayTrunk && hwType == HighwayType::HighwayTrunkLink) ||
@@ -163,6 +163,7 @@ public:
return converter.ClosestValidMacro( return converter.ClosestValidMacro(
{base::asserted_cast<MaxspeedType>(std::lround(s.GetForward() * kLinkToMainSpeedFactor)), s.GetUnits()}); {base::asserted_cast<MaxspeedType>(std::lround(s.GetForward() * kLinkToMainSpeedFactor)), s.GetUnits()});
} }
*/
return {}; return {};
}; };

View File

@@ -441,12 +441,13 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
MessagePriority::Normal); MessagePriority::Normal);
} }
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo) location::RouteMatchingInfo const & routeInfo)
{ {
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, m_threadCommutator->PostMessage(
make_unique_dp<GpsInfoMessage>(info, isNavigable, routeInfo), ThreadsCommutator::RenderThread,
MessagePriority::Normal); make_unique_dp<GpsInfoMessage>(info, isNavigable, distToNextTurn, speedLimit, routeInfo),
MessagePriority::Normal);
} }
void DrapeEngine::SwitchMyPositionNextMode() void DrapeEngine::SwitchMyPositionNextMode()

View File

@@ -154,7 +154,8 @@ public:
void UpdateMapStyle(); void UpdateMapStyle();
void SetCompassInfo(location::CompassInfo const & info); void SetCompassInfo(location::CompassInfo const & info);
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo); void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo);
void SwitchMyPositionNextMode(); void SwitchMyPositionNextMode();
void LoseLocation(); void LoseLocation();
void StopLocationFollow(); void StopLocationFollow();

View File

@@ -438,7 +438,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break; break;
#endif #endif
ref_ptr<GpsInfoMessage> msg = message; ref_ptr<GpsInfoMessage> msg = message;
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen()); m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), msg->GetDistanceToNextTurn(),
msg->GetSpeedLimit(), m_userEventStream.GetCurrentScreen());
location::RouteMatchingInfo const & info = msg->GetRouteInfo(); location::RouteMatchingInfo const & info = msg->GetRouteInfo();
if (info.HasDistanceFromBegin()) if (info.HasDistanceFromBegin())

View File

@@ -481,9 +481,12 @@ private:
class GpsInfoMessage : public Message class GpsInfoMessage : public Message
{ {
public: public:
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo) GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo)
: m_info(info) : m_info(info)
, m_isNavigable(isNavigable) , m_isNavigable(isNavigable)
, m_distToNextTurn(distToNextTurn)
, m_speedLimit(speedLimit)
, m_routeInfo(routeInfo) , m_routeInfo(routeInfo)
{} {}
@@ -491,11 +494,15 @@ public:
location::GpsInfo const & GetInfo() const { return m_info; } location::GpsInfo const & GetInfo() const { return m_info; }
bool IsNavigable() const { return m_isNavigable; } bool IsNavigable() const { return m_isNavigable; }
double const & GetSpeedLimit() const { return m_speedLimit; }
double const & GetDistanceToNextTurn() const { return m_distToNextTurn; }
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; } location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
private: private:
location::GpsInfo const m_info; location::GpsInfo const m_info;
bool const m_isNavigable; bool const m_isNavigable;
double const m_distToNextTurn;
double const m_speedLimit;
location::RouteMatchingInfo const m_routeInfo; location::RouteMatchingInfo const m_routeInfo;
}; };

View File

@@ -56,32 +56,18 @@ inline double GetVisualScale()
return df::VisualParams::Instance().GetVisualScale(); return df::VisualParams::Instance().GetVisualScale();
} }
// Calculate zoom value in meters per pixel double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
{ {
using TSpeedScale = std::pair<double, double>; using TSpeedScale = std::pair<double, double>;
static std::array<TSpeedScale, 6> const scales3d = {{ static std::array<TSpeedScale, 2> const scales2d = {{
{20.0, 0.25}, {0.0, 1.75}, {77.0, 4.50} // 48 mph
{40.0, 0.75},
{60.0, 1.50},
{75.0, 2.50},
{85.0, 3.75},
{95.0, 6.00},
}}; }};
static std::array<TSpeedScale, 2> const scales3d = {{{0.0, 1.00}, {77.0, 4.50}}};
static std::array<TSpeedScale, 6> const scales2d = {{ std::array<TSpeedScale, 2> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
{20.0, 0.70},
{40.0, 1.25},
{60.0, 2.25},
{75.0, 3.00},
{85.0, 3.75},
{95.0, 6.00},
}};
std::array<TSpeedScale, 6> const & scales = isPerspectiveAllowed ? scales3d : scales2d; double constexpr kDefaultSpeedLimitKmpH = 50.0;
double const speedKmpH = speedMpS > 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedLimitKmpH;
double constexpr kDefaultSpeedKmpH = 80.0;
double const speedKmpH = speedMpS >= 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedKmpH;
size_t i = 0; size_t i = 0;
for (size_t sz = scales.size(); i < sz; ++i) for (size_t sz = scales.size(); i < sz; ++i)
@@ -92,20 +78,64 @@ double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
if (i == 0) if (i == 0)
return scales.front().second / vs; return scales.front().second / vs;
if (i == scales.size())
return scales.back().second / vs;
double const minSpeed = scales[i - 1].first; return scales[i - 1].second / vs;
double const maxSpeed = scales[i].first; }
double const k = (speedKmpH - minSpeed) / (maxSpeed - minSpeed);
double const minScale = scales[i - 1].second; double CalculateZoomByDistanceToTurn(double distance, bool isPerspectiveAllowed)
double const maxScale = scales[i].second; {
using TSpeedScale = std::pair<double, double>;
static std::array<TSpeedScale, 5> const scales2d = {{
{200, 0.50},
{500, 0.80}, // 0.3 mi
{1200, 1.75}, // 0.75 mi
{2000, 3.50}, // 1.2 mi
{5000, 6.50} // 3 mi
}};
static std::array<TSpeedScale, 5> const scales3d = {{
{200, 0.25},
{500, 0.60}, // 0.3 mi
{1200, 1.25}, // 0.75 mi
{2000, 3.50}, // 1.2 mi
{5000, 6.50} // 3 mi
}};
std::array<TSpeedScale, 5> const & scale = isPerspectiveAllowed ? scales3d : scales2d;
double constexpr kDefaultDistance = 2000;
double const distanceM = distance >= 0 ? distance : kDefaultDistance;
size_t i = 0;
for (size_t sz = scale.size(); i < sz; ++i)
if (scale[i].first >= distanceM)
break;
double const vs = GetVisualScale();
if (i == 0)
return scale.front().second / vs;
if (i == scale.size())
return scale.back().second / vs;
double const minDist = scale[i - 1].first;
double const maxDist = scale[i].first;
double const k = (distanceM - minDist) / (maxDist - minDist);
double const minScale = scale[i - 1].second;
double const maxScale = scale[i].second;
double const zoom = minScale + k * (maxScale - minScale); double const zoom = minScale + k * (maxScale - minScale);
return zoom / vs; return zoom / vs;
} }
double CalculateAutoZoom(double speedMpS, double distanceToTurn, bool isPerspectiveAllowed)
{
double const zoomByDistance = CalculateZoomByDistanceToTurn(distanceToTurn, isPerspectiveAllowed);
double const zoomByMaxSpeed = CalculateZoomByMaxSpeed(speedMpS, isPerspectiveAllowed);
return std::min(zoomByDistance, zoomByMaxSpeed);
}
void ResetNotification(uint64_t & notifyId) void ResetNotification(uint64_t & notifyId)
{ {
notifyId = DrapeNotifier::kInvalidId; notifyId = DrapeNotifier::kInvalidId;
@@ -395,7 +425,8 @@ void MyPositionController::NextMode(ScreenBase const & screen)
} }
} }
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen) void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn,
double speedLimit, ScreenBase const & screen)
{ {
m2::PointD const oldPos = GetDrawablePosition(); m2::PointD const oldPos = GetDrawablePosition();
double const oldAzimut = GetDrawableAzimut(); double const oldAzimut = GetDrawableAzimut();
@@ -407,11 +438,13 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool
m_errorRadius = rect.SizeX() * 0.5; m_errorRadius = rect.SizeX() * 0.5;
m_horizontalAccuracy = info.m_horizontalAccuracy; m_horizontalAccuracy = info.m_horizontalAccuracy;
if (info.m_speed > 0.0) if (distanceToNextTurn >= 0.0 || speedLimit >= 0.0)
{ {
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy; double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
m_autoScale2d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, false /* isPerspectiveAllowed */); m_autoScale2d =
m_autoScale3d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, true /* isPerspectiveAllowed */); mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, false /* isPerspectiveAllowed */);
m_autoScale3d =
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, true /* isPerspectiveAllowed */);
} }
else else
{ {

View File

@@ -117,7 +117,8 @@ public:
void OnEnterBackground(); void OnEnterBackground();
void OnCompassTapped(); void OnCompassTapped();
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn, double speedLimit,
ScreenBase const & screen);
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen); void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen, void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,

View File

@@ -1171,6 +1171,7 @@ void RoutingManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAl
{ {
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache); auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(), m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
routeMatchingInfo); routeMatchingInfo);
m_gpsInfoCache.reset(); m_gpsInfoCache.reset();
} }
@@ -1515,7 +1516,9 @@ void RoutingManager::OnExtrapolatedLocationUpdate(location::GpsInfo const & info
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo); m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo); auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(), routeMatchingInfo); m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(),
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
routeMatchingInfo);
} }
void RoutingManager::DeleteSavedRoutePoints() void RoutingManager::DeleteSavedRoutePoints()

View File

@@ -11,7 +11,6 @@
#include "base/assert.hpp" #include "base/assert.hpp"
#include "base/buffer_vector.hpp" #include "base/buffer_vector.hpp"
#include <execution>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@@ -118,31 +117,27 @@ public:
template <class FnT> template <class FnT>
void ForEachEnter(FnT && fn) const void ForEachEnter(FnT && fn) const
{ {
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair) for (auto const & [key, transit] : m_transitions)
{ {
auto const & [key, transit] = pair;
if (transit.m_forwardIsEnter) if (transit.m_forwardIsEnter)
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true)); fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
if (!transit.m_oneWay && !transit.m_forwardIsEnter) if (!transit.m_oneWay && !transit.m_forwardIsEnter)
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false)); fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
}); }
} }
template <class FnT> template <class FnT>
void ForEachExit(FnT && fn) const void ForEachExit(FnT && fn) const
{ {
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair) for (auto const & [key, transit] : m_transitions)
{ {
auto const & [key, transit] = pair;
if (!transit.m_forwardIsEnter) if (!transit.m_forwardIsEnter)
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true)); fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
if (!transit.m_oneWay && transit.m_forwardIsEnter) if (!transit.m_oneWay && transit.m_forwardIsEnter)
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false)); fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
}); }
} }
void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const

View File

@@ -4,14 +4,16 @@
#include "routing/routing_options.hpp" #include "routing/routing_options.hpp"
#include "routing/world_graph.hpp" #include "routing/world_graph.hpp"
#include "platform/settings.hpp"
#include "base/assert.hpp" #include "base/assert.hpp"
#include "base/checked_cast.hpp" #include "base/checked_cast.hpp"
#include "base/exception.hpp"
#include "base/timer.hpp" #include "base/timer.hpp"
#include "geometry/distance_on_sphere.hpp" #include "geometry/distance_on_sphere.hpp"
#include <algorithm> #include <algorithm>
#include <execution>
#include <limits> #include <limits>
#include <utility> #include <utility>
@@ -319,9 +321,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
auto const & weightTimeToParent = parentVertexData.m_realDistance; auto const & weightTimeToParent = parentVertexData.m_realDistance;
auto const & parentJoint = parentVertexData.m_vertex; auto const & parentJoint = parentVertexData.m_vertex;
for (size_t i = 0; i < firstChildren.size(); ++i)
auto const range = std::ranges::views::iota(0uz, firstChildren.size());
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
{ {
auto const & firstChild = firstChildren[i]; auto const & firstChild = firstChildren[i];
auto const lastPointId = lastPointIds[i]; auto const lastPointId = lastPointIds[i];
@@ -335,21 +335,22 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
{ return currentPointId < lastPointId ? pointId + 1 : pointId - 1; }; { return currentPointId < lastPointId ? pointId + 1 : pointId - 1; };
if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */)) if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */))
return; continue;
if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */)) if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */))
return; continue;
if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing)) if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing))
return; continue;
if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents)) if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents))
return; continue;
RouteWeight summaryWeight; RouteWeight summaryWeight;
// Check current JointSegment for bad road access between segments. // Check current JointSegment for bad road access between segments.
RoadPoint rp = firstChild.GetRoadPoint(isOutgoing); RoadPoint rp = firstChild.GetRoadPoint(isOutgoing);
uint32_t start = currentPointId; uint32_t start = currentPointId;
bool noRoadAccess = false;
do do
{ {
// This is optimization: we calculate accesses of road points before calculating weight of // This is optimization: we calculate accesses of road points before calculating weight of
@@ -359,13 +360,19 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
// until this |rp|. But we assume that segments have small length and inaccuracy will not // until this |rp|. But we assume that segments have small length and inaccuracy will not
// affect user. // affect user.
if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */)) if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */))
return; {
noRoadAccess = true;
break;
}
start = increment(start); start = increment(start);
rp.SetPointId(start); rp.SetPointId(start);
} }
while (start != lastPointId); while (start != lastPointId);
if (noRoadAccess)
continue;
bool forward = currentPointId < lastPointId; bool forward = currentPointId < lastPointId;
Segment current = firstChild; Segment current = firstChild;
Segment prev = parent; Segment prev = parent;
@@ -389,7 +396,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild), jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild),
summaryWeight); summaryWeight);
}); }
} }
void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to, void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to,

View File

@@ -18,6 +18,8 @@
#include "indexer/feature_meta.hpp" #include "indexer/feature_meta.hpp"
#include "geometry/point2d.hpp"
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <unordered_map> #include <unordered_map>

View File

@@ -13,7 +13,6 @@
#include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning #include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning
#include <algorithm> #include <algorithm>
#include <execution>
#include <map> #include <map>
#include <optional> #include <optional>
#include <queue> #include <queue>
@@ -475,8 +474,7 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex)); CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex));
Weight const weight = it->second; Weight const weight = it->second;
auto const range = std::ranges::views::iota(0uz, edges.size()); for (size_t i = 0; i < edges.size(); ++i)
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
{ {
// Saving weight of current edges for returning in the next iterations. // Saving weight of current edges for returning in the next iterations.
auto & w = edges[i].GetWeight(); auto & w = edges[i].GetWeight();
@@ -492,7 +490,7 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
// |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" + // |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" +
// "parentWeight[i]". // "parentWeight[i]".
w = weight + parentWeights[i]; w = weight + parentWeights[i];
}); }
// Delete useless weight of parent JointSegment. // Delete useless weight of parent JointSegment.
m_savedWeight.erase(vertex); m_savedWeight.erase(vertex);
@@ -500,9 +498,8 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
else else
{ {
// This needs for correct weights calculation of FakeJointSegments during forward A* search. // This needs for correct weights calculation of FakeJointSegments during forward A* search.
auto const range = std::ranges::views::iota(firstFakeId, edges.size()); for (size_t i = firstFakeId; i < edges.size(); ++i)
std::for_each(std::execution::par_unseq, range.begin(), range.end(), edges[i].GetWeight() += parentWeights[i];
[&edges, &parentWeights](auto const i) { edges[i].GetWeight() += parentWeights[i]; });
} }
auto const vertexMwmId = vertex.GetMwmId(); auto const vertexMwmId = vertex.GetMwmId();
@@ -513,12 +510,12 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
/// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight) /// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight)
/// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations. /// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations.
std::for_each(std::execution::par_unseq, edges.begin(), edges.end(), [&, this](auto & e) for (auto & e : edges)
{ {
auto const targetMwmId = e.GetTarget().GetMwmId(); auto const targetMwmId = e.GetTarget().GetMwmId();
if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId) if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId)
e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId); e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId);
}); }
} }
} }

View File

@@ -363,6 +363,32 @@ void GetFullRoadName(RouteSegment::RoadNameInfo & road, std::string & name)
} }
} }
double RoutingSession::GetDistanceToNextTurn() const
{
if (!m_route->IsValid())
return -1;
double distanceToTurnMeters = 0.;
turns::TurnItem turn;
m_route->GetNearestTurn(distanceToTurnMeters, turn);
return distanceToTurnMeters;
}
double RoutingSession::GetCurrentSpeedLimit() const
{
if (!m_route->IsValid())
return -1;
SpeedInUnits speedLimit;
m_route->GetCurrentSpeedLimit(speedLimit);
if (speedLimit.IsNumeric())
return measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
return 0;
else
return -1.0;
}
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
{ {
CHECK_THREAD_CHECKER(m_threadChecker, ()); CHECK_THREAD_CHECKER(m_threadChecker, ());
@@ -392,14 +418,7 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters); info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
info.m_turn = turn.m_turn; info.m_turn = turn.m_turn;
SpeedInUnits speedLimit; info.m_speedLimitMps = GetCurrentSpeedLimit();
m_route->GetCurrentSpeedLimit(speedLimit);
if (speedLimit.IsNumeric())
info.m_speedLimitMps = measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
info.m_speedLimitMps = 0;
else
info.m_speedLimitMps = -1.0;
// The turn after the next one. // The turn after the next one.
if (m_routingSettings.m_showTurnAfterNext) if (m_routingSettings.m_showTurnAfterNext)

View File

@@ -100,6 +100,8 @@ public:
SessionState OnLocationPositionChanged(location::GpsInfo const & info); SessionState OnLocationPositionChanged(location::GpsInfo const & info);
void GetRouteFollowingInfo(FollowingInfo & info) const; void GetRouteFollowingInfo(FollowingInfo & info) const;
double GetDistanceToNextTurn() const;
double GetCurrentSpeedLimit() const;
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo); bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
void MatchLocationToRoadGraph(location::GpsInfo & location); void MatchLocationToRoadGraph(location::GpsInfo & location);

View File

@@ -76,7 +76,7 @@ char const * g_strings[] = {
// ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt // ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt
// tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' | // tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' |
// sort | uniq // sort | uniq
vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN", array<string_view, 48> constexpr g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN", "N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN",
"NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS", "NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS",
"S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS", "S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
@@ -85,13 +85,14 @@ vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L
"NNBNL"}; "NNBNL"};
// List of patterns which look like house numbers more than other patterns. Constructed by hand. // List of patterns which look like house numbers more than other patterns. Constructed by hand.
vector<string> const g_patternsStrict = {"N", "NBN", "NBL", "NL"}; array<string_view, 4> constexpr g_patternsStrict = {"N", "NBN", "NBL", "NL"};
// List of common synonyms for building parts. Constructed by hand. // List of common synonyms for building parts. Constructed by hand.
char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус", char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"}; "корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"};
// List of common stop words for buildings. Constructed by hand. // List of common stop words for buildings. Constructed by hand.
// TODO: add more stop words?
UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")}; UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")};
bool IsStopWord(UniString const & s, bool isPrefix) bool IsStopWord(UniString const & s, bool isPrefix)
@@ -167,7 +168,8 @@ class HouseNumberClassifier
public: public:
using Patterns = StringSet<Token::Type, 4>; using Patterns = StringSet<Token::Type, 4>;
HouseNumberClassifier(vector<string> const & patterns = g_patterns) template <size_t size>
HouseNumberClassifier(array<string_view, size> const & patterns)
{ {
for (auto const & p : patterns) for (auto const & p : patterns)
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType)); m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType));
@@ -590,7 +592,7 @@ bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & qu
bool LooksLikeHouseNumber(UniString const & s, bool isPrefix) bool LooksLikeHouseNumber(UniString const & s, bool isPrefix)
{ {
static HouseNumberClassifier const classifier; static HouseNumberClassifier const classifier(g_patterns);
return classifier.LooksGood(s, isPrefix); return classifier.LooksGood(s, isPrefix);
} }

View File

@@ -298,8 +298,7 @@ void LocalityScorer::GetDocVecs(uint32_t localityId, vector<DocVec> & dvs) const
DocVec::Builder builder; DocVec::Builder builder;
ForEachNormalizedToken(name, [&](strings::UniString const & token) ForEachNormalizedToken(name, [&](strings::UniString const & token)
{ {
if (!IsStopWord(token)) builder.Add(token);
builder.Add(token);
}); });
dvs.emplace_back(std::move(builder)); dvs.emplace_back(std::move(builder));
} }

View File

@@ -69,21 +69,6 @@ m2::RectD GetRectAroundPosition(m2::PointD const & position)
return mercator::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM); return mercator::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM);
} }
// Removes all full-token stop words from |tokens|.
// Does nothing if all tokens are non-prefix stop words.
void RemoveStopWordsIfNeeded(QueryTokens & tokens, strings::UniString & prefix)
{
size_t numStopWords = 0;
for (auto const & token : tokens)
if (IsStopWord(token))
++numStopWords;
if (numStopWords == tokens.size() && prefix.empty())
return;
tokens.erase_if(&IsStopWord);
}
void TrimLeadingSpaces(string & s) void TrimLeadingSpaces(string & s)
{ {
while (!s.empty() && strings::IsASCIISpace(s.front())) while (!s.empty() && strings::IsASCIISpace(s.front()))
@@ -277,9 +262,6 @@ void Processor::SetQuery(string const & query, bool categorialRequest /* = false
} }
} }
// Remove stopwords *after* FillCategories call (it makes exact tokens match).
RemoveStopWordsIfNeeded(m_query.m_tokens, m_query.m_prefix);
if (!m_isCategorialRequest) if (!m_isCategorialRequest)
{ {
// Assign tokens and prefix to scorer. // Assign tokens and prefix to scorer.

View File

@@ -1482,13 +1482,7 @@ unordered_map<string, vector<string>> const kSynonyms = {
// QueryParams::Token ------------------------------------------------------------------------------ // QueryParams::Token ------------------------------------------------------------------------------
void QueryParams::Token::AddSynonym(string const & s) void QueryParams::Token::AddSynonym(string const & s)
{ {
AddSynonym(strings::MakeUniString(s)); m_synonyms.push_back(strings::MakeUniString(s));
}
void QueryParams::Token::AddSynonym(String const & s)
{
if (!IsStopWord(s))
m_synonyms.push_back(s);
} }
string DebugPrint(QueryParams::Token const & token) string DebugPrint(QueryParams::Token const & token)
@@ -1510,10 +1504,12 @@ void QueryParams::ClearStreetIndices()
AdditionalCommonTokens() AdditionalCommonTokens()
{ {
char const * arr[] = { char const * arr[] = {
"the", // English "a", "and", "s", "the", // English
"der", "zum", "und", "auf", // German "am", "an", "auf", "der", "im", "und", "zum", // German
"del", "les", // Spanish "as", "d", "da", "das", "de", "del", "di", "do",
"в", "на" // Cyrillic "dos", "du", "e", "el", "et", "la", "las", "le",
"les", "los", "o", "os", "y", // French, Italian, Portuguese, Spanish
"в", "и", "на", "я" // Cyrillic
}; };
for (char const * s : arr) for (char const * s : arr)
m_strings.insert(NormalizeAndSimplifyString(s)); m_strings.insert(NormalizeAndSimplifyString(s));

View File

@@ -28,7 +28,6 @@ public:
Token(String const & original) : m_original(original) {} Token(String const & original) : m_original(original) {}
void AddSynonym(std::string const & s); void AddSynonym(std::string const & s);
void AddSynonym(String const & s);
template <typename Fn> template <typename Fn>
void ForEachSynonym(Fn && fn) const void ForEachSynonym(Fn && fn) const

View File

@@ -94,42 +94,9 @@ ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token, strings::UniStr
} }
} // namespace impl } // namespace impl
bool IsStopWord(UniString const & s)
{
/// @todo Get all common used stop words and take out this array into search_string_utils.cpp module for example.
/// Should skip this tokens when building search index?
class StopWordsChecker
{
set<UniString> m_set;
public:
StopWordsChecker()
{
// Don't want to put _full_ stopwords list, not to break current ranking.
// Only 2-letters and the most common.
char const * arr[] = {
"a", "s", "the", // English
"am", "im", "an", // German
"d", "da", "de", "di", "du", "la", "le", // French, Spanish, Italian
"и", "я" // Cyrillic
};
for (char const * s : arr)
m_set.insert(MakeUniString(s));
}
bool Has(UniString const & s) const { return m_set.count(s) > 0; }
};
static StopWordsChecker const swChecker;
return swChecker.Has(s);
}
TokensVector::TokensVector(string_view name) TokensVector::TokensVector(string_view name)
{ {
ForEachNormalizedToken(name, [this](strings::UniString && token) m_tokens = NormalizeAndTokenizeString(std::move(name));
{
if (!IsStopWord(token))
m_tokens.push_back(std::move(token));
});
Init(); Init();
} }

View File

@@ -180,9 +180,6 @@ struct NameScores
std::string DebugPrint(NameScore const & score); std::string DebugPrint(NameScore const & score);
std::string DebugPrint(NameScores const & scores); std::string DebugPrint(NameScores const & scores);
// Returns true when |s| is a stop-word and may be removed from a query.
bool IsStopWord(strings::UniString const & s);
class TokensVector class TokensVector
{ {
std::vector<strings::UniString> m_tokens; std::vector<strings::UniString> m_tokens;

View File

@@ -44,11 +44,7 @@ public:
m_scorer.SetPivotForTesting(pivot); m_scorer.SetPivotForTesting(pivot);
vector<UniString> tokens; vector<UniString> tokens;
search::ForEachNormalizedToken(query, [&tokens](strings::UniString && token) tokens = NormalizeAndTokenizeString(query);
{
if (!IsStopWord(token))
tokens.push_back(std::move(token));
});
m_params.Init(query, tokens, lastTokenIsPrefix); m_params.Init(query, tokens, lastTokenIsPrefix);
} }

View File

@@ -38,7 +38,7 @@ def multithread_run_if_one_country(func):
kwargs.update({"threads_count": settings.THREADS_COUNT}) kwargs.update({"threads_count": settings.THREADS_COUNT})
# Otherwise index stage of Taiwan_* mwms continues to run after all other mwms have finished: # Otherwise index stage of Taiwan_* mwms continues to run after all other mwms have finished:
elif country == 'Taiwan_North': elif country == 'Taiwan_North':
kwargs.update({"threads_count": 3}) kwargs.update({"threads_count": 5})
elif country == 'Taiwan_South': elif country == 'Taiwan_South':
kwargs.update({"threads_count": 2}) kwargs.update({"threads_count": 2})
func(env, country, **kwargs) func(env, country, **kwargs)

View File

@@ -20,7 +20,7 @@ MAIN_OUT_PATH: /mnt/4tbexternal/osm-maps
# Path to the data/ folder in the repository: # Path to the data/ folder in the repository:
USER_RESOURCE_PATH: ${Developer:OMIM_PATH}/data USER_RESOURCE_PATH: ${Developer:OMIM_PATH}/data
# Features stage only parallelism level. Set to 0 for auto detection. # Features stage only parallelism level. Set to 0 for auto detection.
THREADS_COUNT_FEATURES_STAGE: 64 THREADS_COUNT_FEATURES_STAGE: 0
# Do not change it. This is determined automatically. # Do not change it. This is determined automatically.
NODE_STORAGE: mem NODE_STORAGE: mem