forked from organicmaps/organicmaps
Compare commits
1 commit
master
...
vng-alt-ro
Author | SHA1 | Date | |
---|---|---|---|
|
382385a7ec |
20 changed files with 427 additions and 13 deletions
|
@ -10,6 +10,12 @@ routing::RoutingOptions::Road makeValue(jint option)
|
|||
return static_cast<routing::RoutingOptions::Road>(road);
|
||||
}
|
||||
|
||||
routing::EdgeEstimator::Strategy makeStrategyValue(jint strategy)
|
||||
{
|
||||
int convertedStrat = static_cast<int>(strategy);
|
||||
return static_cast<routing::EdgeEstimator::Strategy>(convertedStrat);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
|
@ -22,6 +28,14 @@ Java_app_organicmaps_routing_RoutingOptions_nativeHasOption(JNIEnv * env, jclass
|
|||
return static_cast<jboolean>(routingOptions.Has(road));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_mapswithme_maps_routing_RoutingOptions_nativeGetStrategy(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
CHECK(g_framework, ("Framework isn't created yet!"));
|
||||
routing::EdgeEstimator::Strategy routingStrategy = routing::EdgeEstimator::LoadRoutingStrategyFromSettings();
|
||||
return static_cast<jint>(routingStrategy);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_routing_RoutingOptions_nativeAddOption(JNIEnv * env, jclass clazz, jint option)
|
||||
{
|
||||
|
@ -32,7 +46,6 @@ Java_app_organicmaps_routing_RoutingOptions_nativeAddOption(JNIEnv * env, jclass
|
|||
routing::RoutingOptions::SaveCarOptionsToSettings(routingOptions);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_routing_RoutingOptions_nativeRemoveOption(JNIEnv * env, jclass clazz, jint option)
|
||||
{
|
||||
|
@ -42,4 +55,11 @@ Java_app_organicmaps_routing_RoutingOptions_nativeRemoveOption(JNIEnv * env, jcl
|
|||
routingOptions.Remove(road);
|
||||
routing::RoutingOptions::SaveCarOptionsToSettings(routingOptions);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_mapswithme_maps_routing_RoutingOptions_nativeSetStrategy(JNIEnv * env, jclass clazz, jint strategy)
|
||||
{
|
||||
CHECK(g_framework, ("Framework isn't created yet!"));
|
||||
routing::EdgeEstimator::SaveRoutingStrategyToSettings(makeStrategyValue(strategy));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package app.organicmaps.routing;
|
|||
import androidx.annotation.NonNull;
|
||||
|
||||
import app.organicmaps.settings.RoadType;
|
||||
import app.organicmaps.settings.RoutingStrategyType;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -24,9 +25,21 @@ public class RoutingOptions
|
|||
return nativeHasOption(roadType.ordinal());
|
||||
}
|
||||
|
||||
public static int getStrategy()
|
||||
{
|
||||
return nativeGetStrategy();
|
||||
}
|
||||
|
||||
public static void setStrategy(@NonNull RoutingStrategyType routingStrategyType)
|
||||
{
|
||||
nativeSetStrategy(routingStrategyType.ordinal());
|
||||
}
|
||||
|
||||
private static native void nativeAddOption(int option);
|
||||
private static native void nativeRemoveOption(int option);
|
||||
private static native boolean nativeHasOption(int option);
|
||||
private static native int nativeGetStrategy();
|
||||
private static native void nativeSetStrategy(int strategy);
|
||||
|
||||
public static boolean hasAnyOptions()
|
||||
{
|
||||
|
@ -49,4 +62,10 @@ public class RoutingOptions
|
|||
}
|
||||
return roadTypes;
|
||||
}
|
||||
|
||||
public static RoutingStrategyType getActiveRoutingStrategyType()
|
||||
{
|
||||
int strategyType = getStrategy();
|
||||
return RoutingStrategyType.values()[strategyType];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -25,8 +26,11 @@ import java.util.Set;
|
|||
public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
||||
{
|
||||
public static final String BUNDLE_ROAD_TYPES = "road_types";
|
||||
public static final String BUNDLE_ROUTING_STRATEGY_TYPE = "routing_strategy_type";
|
||||
@NonNull
|
||||
private Set<RoadType> mRoadTypes = Collections.emptySet();
|
||||
@NonNull
|
||||
private RoutingStrategyType mStrategy = RoutingStrategyType.Fastest;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -38,6 +42,9 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||
mRoadTypes = savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_ROAD_TYPES)
|
||||
? makeRouteTypes(savedInstanceState)
|
||||
: RoutingOptions.getActiveRoadTypes();
|
||||
mStrategy = savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_ROUTING_STRATEGY_TYPE)
|
||||
? makeRoutingStrategyType(savedInstanceState)
|
||||
: RoutingOptions.getActiveRoutingStrategyType();
|
||||
return root;
|
||||
}
|
||||
|
||||
|
@ -53,6 +60,13 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private RoutingStrategyType makeRoutingStrategyType(@NonNull Bundle bundle)
|
||||
{
|
||||
RoutingStrategyType result = Objects.requireNonNull((RoutingStrategyType)bundle.getSerializable(BUNDLE_ROUTING_STRATEGY_TYPE));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState)
|
||||
{
|
||||
|
@ -63,12 +77,15 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||
savedRoadTypes.add(each.ordinal());
|
||||
}
|
||||
outState.putIntegerArrayList(BUNDLE_ROAD_TYPES, savedRoadTypes);
|
||||
|
||||
outState.putSerializable(BUNDLE_ROUTING_STRATEGY_TYPE, mStrategy);
|
||||
}
|
||||
|
||||
private boolean areSettingsNotChanged()
|
||||
{
|
||||
Set<RoadType> lastActiveRoadTypes = RoutingOptions.getActiveRoadTypes();
|
||||
return mRoadTypes.equals(lastActiveRoadTypes);
|
||||
RoutingStrategyType lastActiveStrategyType = RoutingOptions.getActiveRoutingStrategyType();
|
||||
return mRoadTypes.equals(lastActiveRoadTypes) && mStrategy.equals(lastActiveStrategyType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,6 +121,26 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||
CompoundButton.OnCheckedChangeListener dirtyBtnListener =
|
||||
new ToggleRoutingOptionListener(RoadType.Dirty);
|
||||
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener);
|
||||
|
||||
RadioGroup strategyRadioGroup = root.findViewById(R.id.routing_strategy_types);
|
||||
RoutingStrategyType currentStrategy = RoutingOptions.getActiveRoutingStrategyType();
|
||||
int currentCheckedStrategyId;
|
||||
switch (currentStrategy)
|
||||
{
|
||||
case Shortest:
|
||||
currentCheckedStrategyId = R.id.use_strategy_shortest;
|
||||
break;
|
||||
case FewerTurns:
|
||||
currentCheckedStrategyId = R.id.use_strategy_fewerTurns;
|
||||
break;
|
||||
default:
|
||||
currentCheckedStrategyId = R.id.use_strategy_fastest;
|
||||
break;
|
||||
}
|
||||
strategyRadioGroup.check(currentCheckedStrategyId);
|
||||
RadioGroup.OnCheckedChangeListener strategyRadioGroupListener =
|
||||
new ToggleRoutingStrategyListener();
|
||||
strategyRadioGroup.setOnCheckedChangeListener(strategyRadioGroupListener);
|
||||
}
|
||||
|
||||
private static class ToggleRoutingOptionListener implements CompoundButton.OnCheckedChangeListener
|
||||
|
@ -125,4 +162,26 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||
RoutingOptions.removeOption(mRoadType);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ToggleRoutingStrategyListener implements RadioGroup.OnCheckedChangeListener
|
||||
{
|
||||
private ToggleRoutingStrategyListener() {}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(RadioGroup group, int checkedId)
|
||||
{
|
||||
switch (checkedId)
|
||||
{
|
||||
case R.id.use_strategy_fastest:
|
||||
RoutingOptions.setStrategy(RoutingStrategyType.Fastest);
|
||||
break;
|
||||
case R.id.use_strategy_shortest:
|
||||
RoutingOptions.setStrategy(RoutingStrategyType.Shortest);
|
||||
break;
|
||||
case R.id.use_strategy_fewerTurns:
|
||||
RoutingOptions.setStrategy(RoutingStrategyType.FewerTurns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package app.organicmaps.settings;
|
||||
|
||||
public enum RoutingStrategyType
|
||||
{
|
||||
Fastest,
|
||||
Shortest,
|
||||
FewerTurns
|
||||
}
|
|
@ -104,4 +104,46 @@
|
|||
android:padding="@dimen/margin_half_double_plus"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dp"
|
||||
android:background="@android:color/darker_gray"/>
|
||||
<TextView
|
||||
android:text="@string/driving_options_subheader2"
|
||||
android:textAppearance="?android:attr/textAppearance"
|
||||
android:textColor="?colorAccent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginTop="@dimen/margin_half_double_plus"
|
||||
android:paddingEnd="@dimen/margin_base"
|
||||
android:paddingStart="@dimen/margin_base"/>
|
||||
<RadioGroup
|
||||
android:id="@+id/routing_strategy_types"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_base">
|
||||
<RadioButton
|
||||
android:id="@+id/use_strategy_fastest"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_half_plus"
|
||||
android:checked="true"
|
||||
android:text="@string/use_strategy_fastest"/>
|
||||
<RadioButton
|
||||
android:id="@+id/use_strategy_shortest"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_half_plus"
|
||||
android:checked="false"
|
||||
android:text="@string/use_strategy_shortest"/>
|
||||
<RadioButton
|
||||
android:id="@+id/use_strategy_fewerTurns"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_half_plus"
|
||||
android:checked="false"
|
||||
android:text="@string/use_strategy_fewerTurns"/>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -687,12 +687,16 @@
|
|||
<string name="access_rules_author_only">Online editing</string>
|
||||
<string name="driving_options_title">Routing options</string>
|
||||
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
|
||||
<string name="driving_options_subheader2">Routing Strategy</string>
|
||||
<string name="avoid_tolls">Avoid tolls</string>
|
||||
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
|
||||
<string name="avoid_unpaved">Avoid unpaved roads</string>
|
||||
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
|
||||
<string name="avoid_ferry">Avoid ferries</string>
|
||||
<string name="avoid_motorways">Avoid freeways</string>
|
||||
<string name="use_strategy_fastest">Fastest</string>
|
||||
<string name="use_strategy_shortest">Shortest</string>
|
||||
<string name="use_strategy_fewerTurns">Fewer turns</string>
|
||||
<string name="unable_to_calc_alert_title">Unable to calculate route</string>
|
||||
<string name="unable_to_calc_alert_subtitle">A route could not be found. This may be caused by your routing options or incomplete OpenStreetMap data. Please change your routing options and retry.</string>
|
||||
<string name="define_to_avoid_btn">Define roads to avoid</string>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "map/framework.hpp"
|
||||
|
||||
#include "routing/router.hpp"
|
||||
#include "routing/edge_estimator.hpp"
|
||||
|
||||
#include "platform/settings.hpp"
|
||||
|
||||
|
@ -24,12 +25,26 @@ std::string const kUseCachedRoutingSettings = "use_cached_settings_desktop";
|
|||
std::string const kStartCoordsCachedSettings = "start_coords_desktop";
|
||||
std::string const kFinishCoordsCachedSettings = "finish_coords_desktop";
|
||||
std::string const kRouterTypeCachedSettings = "router_type_desktop";
|
||||
std::string const kRouterStrategyCachedSettings = "router_strategy";
|
||||
std::string const kAvoidRoutingOptionSettings = "avoid_routing_options_car";
|
||||
|
||||
int constexpr DefaultRouterIndex()
|
||||
{
|
||||
// Car router by default.
|
||||
return static_cast<int>(routing::RouterType::Vehicle);
|
||||
}
|
||||
|
||||
int constexpr DefaultStrategyIndex()
|
||||
{
|
||||
// Routing strategy by default
|
||||
return static_cast<int>(routing::EdgeEstimator::Strategy::Fastest);
|
||||
}
|
||||
|
||||
int constexpr DefaultAvoidOptionIndex()
|
||||
{
|
||||
// Avoid routing option by default
|
||||
return static_cast<int>(routing::RoutingOptions::Road::Usual);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
|
@ -93,6 +108,8 @@ void RoutingSettings::LoadSession(Framework & framework)
|
|||
settings::Delete(kStartCoordsCachedSettings);
|
||||
settings::Delete(kFinishCoordsCachedSettings);
|
||||
settings::Delete(kRouterTypeCachedSettings);
|
||||
settings::Delete(kRouterStrategyCachedSettings);
|
||||
settings::Delete(kAvoidRoutingOptionSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,6 +151,20 @@ RoutingSettings::RoutingSettings(QWidget * parent, Framework & framework)
|
|||
m_routerType->insertItem(static_cast<int>(RouterType::Ruler), "ruler");
|
||||
form->addRow("Choose router:", m_routerType);
|
||||
|
||||
m_routerStrategy = new QComboBox(frame);
|
||||
m_routerStrategy->insertItem(static_cast<int>(EdgeEstimator::Strategy::Fastest), "fastest");
|
||||
m_routerStrategy->insertItem(static_cast<int>(EdgeEstimator::Strategy::Shortest), "shortest");
|
||||
m_routerStrategy->insertItem(static_cast<int>(EdgeEstimator::Strategy::FewerTurns), "fewer turns");
|
||||
form->addRow("Choose strategy:", m_routerStrategy);
|
||||
|
||||
m_avoidRoutingOptions = new QComboBox(frame);
|
||||
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Dirty), "dirty");
|
||||
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Ferry), "ferry");
|
||||
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Motorway), "motorway");
|
||||
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Toll), "toll");
|
||||
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Usual), "usual");
|
||||
form->addRow("Choose avoid option:", m_avoidRoutingOptions);
|
||||
|
||||
m_showTurnsCheckbox = new QCheckBox({}, frame);
|
||||
form->addRow("Show turns:", m_showTurnsCheckbox);
|
||||
|
||||
|
@ -190,6 +221,8 @@ bool RoutingSettings::SaveSettings()
|
|||
settings::Set(kUseDebugGuideSettings, m_useDebugGuideCheckbox->isChecked());
|
||||
settings::Set(kUseCachedRoutingSettings, m_saveSessionCheckbox->isChecked());
|
||||
settings::Set(kRouterTypeCachedSettings, m_routerType->currentIndex());
|
||||
settings::Set(kRouterStrategyCachedSettings, m_routerStrategy->currentIndex());
|
||||
settings::Set(kAvoidRoutingOptionSettings, m_avoidRoutingOptions->currentIndex());
|
||||
return ValidateAndSaveCoordsFromInput();
|
||||
}
|
||||
|
||||
|
@ -207,6 +240,14 @@ void RoutingSettings::LoadSettings()
|
|||
settings::TryGet(kRouterTypeCachedSettings, routerType);
|
||||
m_routerType->setCurrentIndex(routerType);
|
||||
|
||||
int routerStrategy = DefaultStrategyIndex();
|
||||
settings::TryGet(kRouterStrategyCachedSettings, routerStrategy);
|
||||
m_routerStrategy->setCurrentIndex(routerStrategy);
|
||||
|
||||
int avoidRoutingOption = DefaultAvoidOptionIndex();
|
||||
settings::TryGet(kAvoidRoutingOptionSettings, avoidRoutingOption);
|
||||
m_avoidRoutingOptions->setCurrentIndex(avoidRoutingOption);
|
||||
|
||||
bool showTurns = false;
|
||||
settings::TryGet(kShowTurnsSettings, showTurns);
|
||||
m_showTurnsCheckbox->setChecked(showTurns);
|
||||
|
|
|
@ -40,6 +40,8 @@ private:
|
|||
QLineEdit * m_finishInput;
|
||||
|
||||
QComboBox * m_routerType;
|
||||
QComboBox * m_routerStrategy;
|
||||
QComboBox * m_avoidRoutingOptions;
|
||||
QCheckBox * m_showTurnsCheckbox;
|
||||
QCheckBox * m_useDebugGuideCheckbox;
|
||||
QCheckBox * m_saveSessionCheckbox;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "routing/async_router.hpp"
|
||||
#include "routing/routing_options.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
|
@ -343,6 +344,12 @@ void AsyncRouter::CalculateRoute()
|
|||
if (absentRegionsFinder)
|
||||
absentRegionsFinder->GenerateAbsentRegions(checkpoints, delegateProxy->GetDelegate());
|
||||
|
||||
RoutingOptions const routingOptions = RoutingOptions::LoadCarOptionsFromSettings();
|
||||
router->SetEstimatorOptions(routingOptions.GetOptions());
|
||||
|
||||
EdgeEstimator::Strategy routingStrategy = EdgeEstimator::LoadRoutingStrategyFromSettings();
|
||||
router->SetEstimatorStrategy(routingStrategy);
|
||||
|
||||
// Run basic request.
|
||||
code = router->CalculateRoute(checkpoints, startDirection, adjustToPrevRoute,
|
||||
delegateProxy->GetDelegate(), *route);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include "routing/edge_estimator.hpp"
|
||||
|
||||
#include "platform/settings.hpp"
|
||||
|
||||
#include "routing/geometry.hpp"
|
||||
#include "routing/latlon_with_altitude.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
#include "routing/routing_options.hpp"
|
||||
#include "routing/traffic_stash.hpp"
|
||||
|
||||
#include "traffic/speed_groups.hpp"
|
||||
|
@ -60,12 +63,15 @@ bool IsTransit(std::optional<HighwayType> type)
|
|||
}
|
||||
|
||||
template <class CalcSpeed>
|
||||
double CalcClimbSegment(EdgeEstimator::Purpose purpose, Segment const & segment,
|
||||
RoadGeometry const & road, CalcSpeed && calcSpeed)
|
||||
double CalcClimbSegment(EdgeEstimator::Purpose purpose, EdgeEstimator::Strategy strategy,
|
||||
Segment const & segment, RoadGeometry const & road, CalcSpeed && calcSpeed)
|
||||
{
|
||||
double const distance = road.GetDistance(segment.GetSegmentIdx());
|
||||
double speedMpS = GetSpeedMpS(purpose, segment, road);
|
||||
|
||||
if (strategy == EdgeEstimator::Strategy::Shortest && purpose == EdgeEstimator::Purpose::Weight)
|
||||
speedMpS = 1.0;
|
||||
|
||||
static double constexpr kSmallDistanceM = 1; // we have altitude threshold is 0.5m
|
||||
if (distance > kSmallDistanceM && !IsTransit(road.GetHighwayType()))
|
||||
{
|
||||
|
@ -167,6 +173,26 @@ double GetCarClimbPenalty(EdgeEstimator::Purpose, double, geometry::Altitude)
|
|||
}
|
||||
|
||||
// EdgeEstimator -----------------------------------------------------------------------------------
|
||||
|
||||
string const EdgeEstimator::kRoutingStrategySettings = "router_strategy";
|
||||
|
||||
// static
|
||||
EdgeEstimator::Strategy EdgeEstimator::LoadRoutingStrategyFromSettings()
|
||||
{
|
||||
int mode = 0;
|
||||
if (!settings::Get(kRoutingStrategySettings, mode))
|
||||
mode = 0;
|
||||
|
||||
return (EdgeEstimator::Strategy) mode;
|
||||
}
|
||||
|
||||
// static
|
||||
void EdgeEstimator::SaveRoutingStrategyToSettings(Strategy strategy)
|
||||
{
|
||||
settings::Set(kRoutingStrategySettings,
|
||||
strings::to_string(static_cast<int>(strategy)));
|
||||
}
|
||||
|
||||
EdgeEstimator::EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
|
||||
DataSource * /*dataSourcePtr*/, std::shared_ptr<NumMwmIds> /*numMwmIds*/)
|
||||
: m_maxWeightSpeedMpS(KmphToMps(maxWeightSpeedKMpH))
|
||||
|
@ -180,6 +206,9 @@ EdgeEstimator::EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroa
|
|||
|
||||
if (m_offroadSpeedKMpH.m_eta != kNotUsed)
|
||||
CHECK_GREATER_OR_EQUAL(m_maxWeightSpeedMpS, KmphToMps(m_offroadSpeedKMpH.m_eta), ());
|
||||
|
||||
m_avoidRoutingOptions = RoutingOptions();
|
||||
m_strategy = EdgeEstimator::Strategy::Fastest;
|
||||
}
|
||||
|
||||
double EdgeEstimator::CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const
|
||||
|
@ -260,6 +289,26 @@ double EdgeEstimator::CalcOffroad(ms::LatLon const & from, ms::LatLon const & to
|
|||
return TimeBetweenSec(from, to, KmphToMps(offroadSpeedKMpH));
|
||||
}
|
||||
|
||||
RoutingOptions EdgeEstimator::GetAvoidRoutingOptions() const
|
||||
{
|
||||
return m_avoidRoutingOptions;
|
||||
}
|
||||
|
||||
void EdgeEstimator::SetAvoidRoutingOptions(RoutingOptions::RoadType options)
|
||||
{
|
||||
m_avoidRoutingOptions.SetOptions(options);
|
||||
}
|
||||
|
||||
EdgeEstimator::Strategy EdgeEstimator::GetStrategy() const
|
||||
{
|
||||
return m_strategy;
|
||||
}
|
||||
|
||||
void EdgeEstimator::SetStrategy(EdgeEstimator::Strategy strategy)
|
||||
{
|
||||
m_strategy = strategy;
|
||||
}
|
||||
|
||||
// PedestrianEstimator -----------------------------------------------------------------------------
|
||||
class PedestrianEstimator final : public EdgeEstimator
|
||||
{
|
||||
|
@ -270,7 +319,20 @@ public:
|
|||
}
|
||||
|
||||
// EdgeEstimator overrides:
|
||||
double GetUTurnPenalty(Purpose /* purpose */) const override { return 0.0 /* seconds */; }
|
||||
double GetUTurnPenalty(Purpose purpose) const override
|
||||
{
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
|
||||
return 60 * 60;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double GetTurnPenalty(Purpose purpose) const override
|
||||
{
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
|
||||
return 60 * 60;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double GetFerryLandingPenalty(Purpose purpose) const override
|
||||
{
|
||||
switch (purpose)
|
||||
|
@ -283,11 +345,16 @@ public:
|
|||
|
||||
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override
|
||||
{
|
||||
return CalcClimbSegment(purpose, segment, road,
|
||||
double result = CalcClimbSegment(purpose, GetStrategy(), segment, road,
|
||||
[purpose](double speedMpS, double tangent, geometry::Altitude altitude)
|
||||
{
|
||||
return speedMpS / GetPedestrianClimbPenalty(purpose, tangent, altitude);
|
||||
});
|
||||
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && !road.SuitableForOptions(EdgeEstimator::GetAvoidRoutingOptions()))
|
||||
result += (24 * 60 * 60);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -301,7 +368,20 @@ public:
|
|||
}
|
||||
|
||||
// EdgeEstimator overrides:
|
||||
double GetUTurnPenalty(Purpose /* purpose */) const override { return 20.0 /* seconds */; }
|
||||
double GetUTurnPenalty(Purpose purpose) const override
|
||||
{
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
|
||||
return 60 * 60;
|
||||
return 20.0;
|
||||
}
|
||||
|
||||
double GetTurnPenalty(Purpose purpose) const override
|
||||
{
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
|
||||
return 60 * 60;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double GetFerryLandingPenalty(Purpose purpose) const override
|
||||
{
|
||||
switch (purpose)
|
||||
|
@ -314,7 +394,7 @@ public:
|
|||
|
||||
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override
|
||||
{
|
||||
return CalcClimbSegment(purpose, segment, road,
|
||||
double result = CalcClimbSegment(purpose, GetStrategy(), segment, road,
|
||||
[purpose, this](double speedMpS, double tangent, geometry::Altitude altitude)
|
||||
{
|
||||
auto const factor = GetBicycleClimbPenalty(purpose, tangent, altitude);
|
||||
|
@ -347,6 +427,12 @@ public:
|
|||
|
||||
return std::min(speedMpS, GetMaxWeightSpeedMpS());
|
||||
});
|
||||
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && !road.SuitableForOptions(EdgeEstimator::GetAvoidRoutingOptions()))
|
||||
result += (24 * 60 * 60);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -364,14 +450,24 @@ public:
|
|||
|
||||
// EdgeEstimator overrides:
|
||||
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override;
|
||||
double GetUTurnPenalty(Purpose /* purpose */) const override
|
||||
double GetUTurnPenalty(Purpose purpose) const override
|
||||
{
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
|
||||
return 60 * 60;
|
||||
|
||||
// Adds 2 minutes penalty for U-turn. The value is quite arbitrary
|
||||
// and needs to be properly selected after a number of real-world
|
||||
// experiments.
|
||||
return 2 * 60; // seconds
|
||||
}
|
||||
|
||||
double GetTurnPenalty(Purpose purpose) const override
|
||||
{
|
||||
if (purpose == EdgeEstimator::Purpose::Weight)
|
||||
return 60 * 60;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double GetFerryLandingPenalty(Purpose purpose) const override
|
||||
{
|
||||
switch (purpose)
|
||||
|
@ -390,6 +486,9 @@ double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry con
|
|||
{
|
||||
double result = road.GetDistance(segment.GetSegmentIdx()) / GetSpeedMpS(purpose, segment, road);
|
||||
|
||||
if (purpose == EdgeEstimator::Purpose::Weight && !road.SuitableForOptions(EdgeEstimator::GetAvoidRoutingOptions()))
|
||||
result += (24 * 60 * 60);
|
||||
|
||||
if (m_trafficStash)
|
||||
{
|
||||
SpeedGroup const speedGroup = m_trafficStash->GetSpeedGroup(segment);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/routing_options.hpp"
|
||||
#include "routing/segment.hpp"
|
||||
#include "routing/vehicle_mask.hpp"
|
||||
|
||||
|
@ -27,10 +28,22 @@ public:
|
|||
ETA
|
||||
};
|
||||
|
||||
static std::string const kRoutingStrategySettings;
|
||||
|
||||
enum class Strategy
|
||||
{
|
||||
Fastest,
|
||||
Shortest,
|
||||
FewerTurns
|
||||
};
|
||||
|
||||
EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
|
||||
DataSource * dataSourcePtr = nullptr, std::shared_ptr<NumMwmIds> numMwmIds = nullptr);
|
||||
virtual ~EdgeEstimator() = default;
|
||||
|
||||
static Strategy LoadRoutingStrategyFromSettings();
|
||||
static void SaveRoutingStrategyToSettings(Strategy strategy);
|
||||
|
||||
double CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const;
|
||||
// Estimates time in seconds it takes to go from point |from| to point |to| along a leap (fake)
|
||||
// edge |from|-|to| using real features.
|
||||
|
@ -45,9 +58,16 @@ public:
|
|||
// Estimates time in seconds it takes to go from point |from| to point |to| along direct fake edge.
|
||||
double CalcOffroad(ms::LatLon const & from, ms::LatLon const & to, Purpose purpose) const;
|
||||
|
||||
RoutingOptions GetAvoidRoutingOptions() const;
|
||||
void SetAvoidRoutingOptions(RoutingOptions::RoadType options);
|
||||
|
||||
Strategy GetStrategy() const;
|
||||
void SetStrategy(Strategy strategy);
|
||||
|
||||
virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road,
|
||||
Purpose purpose) const = 0;
|
||||
virtual double GetUTurnPenalty(Purpose purpose) const = 0;
|
||||
virtual double GetTurnPenalty(Purpose purpose) const = 0;
|
||||
virtual double GetFerryLandingPenalty(Purpose purpose) const = 0;
|
||||
|
||||
static std::shared_ptr<EdgeEstimator> Create(VehicleType vehicleType, double maxWeighSpeedKMpH,
|
||||
|
@ -65,6 +85,8 @@ public:
|
|||
private:
|
||||
double const m_maxWeightSpeedMpS;
|
||||
SpeedKMpH const m_offroadSpeedKMpH;
|
||||
RoutingOptions m_avoidRoutingOptions;
|
||||
Strategy m_strategy;
|
||||
|
||||
//DataSource * m_dataSourcePtr;
|
||||
//std::shared_ptr<NumMwmIds> m_numMwmIds;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "base/timer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
@ -254,8 +255,8 @@ void IndexGraph::GetNeighboringEdges(astar::VertexData<Segment, RouteWeight> con
|
|||
if (!road.IsValid())
|
||||
return;
|
||||
|
||||
if (useRoutingOptions && !road.SuitableForOptions(m_avoidRoutingOptions))
|
||||
return;
|
||||
// if (useRoutingOptions && !road.SuitableForOptions(m_avoidRoutingOptions))
|
||||
// return;
|
||||
|
||||
bool const bidirectional = !road.IsOneWay();
|
||||
auto const & from = fromVertexData.m_vertex;
|
||||
|
@ -282,8 +283,8 @@ void IndexGraph::GetSegmentCandidateForRoadPoint(RoadPoint const & rp, NumMwmId
|
|||
if (!road.IsValid())
|
||||
return;
|
||||
|
||||
if (!road.SuitableForOptions(m_avoidRoutingOptions))
|
||||
return;
|
||||
// if (!road.SuitableForOptions(m_avoidRoutingOptions))
|
||||
// return;
|
||||
|
||||
bool const bidirectional = !road.IsOneWay();
|
||||
auto const pointId = rp.GetPointId();
|
||||
|
@ -514,6 +515,9 @@ RouteWeight IndexGraph::GetPenalties(EdgeEstimator::Purpose purpose, Segment con
|
|||
if (IsUTurn(u, v))
|
||||
weightPenalty += m_estimator->GetUTurnPenalty(purpose);
|
||||
|
||||
if (IsTurn(u, v))
|
||||
weightPenalty += m_estimator->GetTurnPenalty(purpose);
|
||||
|
||||
if (IsBoarding(fromPenaltyData.m_isFerry, toPenaltyData.m_isFerry))
|
||||
weightPenalty += m_estimator->GetFerryLandingPenalty(purpose);
|
||||
|
||||
|
@ -549,6 +553,57 @@ bool IndexGraph::IsUTurnAndRestricted(Segment const & parent, Segment const & ch
|
|||
return uTurn.m_atTheEnd && turnPoint == n - 1;
|
||||
}
|
||||
|
||||
bool IndexGraph::IsTurn(Segment const & u, Segment const & v) const
|
||||
{
|
||||
// Boundary check for segmentIdx
|
||||
if (u.GetSegmentIdx() == 0 && !(u.IsForward()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (v.GetSegmentIdx() == 0 && !(v.IsForward()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto geoU = GetRoadGeometry(u.GetFeatureId());
|
||||
auto startPointU = geoU.GetPoint(u.GetSegmentIdx());
|
||||
auto endPointU = geoU.GetPoint(u.IsForward() ? u.GetSegmentIdx() + 1: u.GetSegmentIdx() - 1);
|
||||
|
||||
auto geoV = GetRoadGeometry(v.GetFeatureId());
|
||||
auto startPointV = geoV.GetPoint(v.GetSegmentIdx());
|
||||
auto endPointV = geoV.GetPoint(v.IsForward() ? v.GetSegmentIdx() + 1: v.GetSegmentIdx() - 1);
|
||||
|
||||
if (!(endPointU == startPointV))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double vectorU[2] = {endPointU.m_lat - startPointU.m_lat, endPointU.m_lon - startPointU.m_lon};
|
||||
double vectorV[2] = {endPointV.m_lat - startPointV.m_lat, endPointV.m_lon - startPointV.m_lon};
|
||||
|
||||
//dot product
|
||||
double dot = vectorU[0] * vectorV[0] + vectorU[1] * vectorV[1];
|
||||
|
||||
//determinant
|
||||
double det = vectorU[0] * vectorV[1] - vectorU[1] * vectorV[0];
|
||||
|
||||
//calculate the anlge
|
||||
double angle = atan2(det, dot);
|
||||
|
||||
//convert to degree value
|
||||
angle = angle * 180 / 3.141592;
|
||||
|
||||
if (abs(angle) >= 15)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RouteWeight IndexGraph::CalculateEdgeWeight(EdgeEstimator::Purpose purpose, bool isOutgoing,
|
||||
Segment const & from, Segment const & to,
|
||||
std::optional<RouteWeight const> const & prevWeight) const
|
||||
|
@ -556,7 +611,18 @@ RouteWeight IndexGraph::CalculateEdgeWeight(EdgeEstimator::Purpose purpose, bool
|
|||
auto const & segment = isOutgoing ? to : from;
|
||||
auto const & road = GetRoadGeometry(segment.GetFeatureId());
|
||||
|
||||
// m_estimator->SetAvoidRoutingOptions(this->m_avoidRoutingOptions.GetOptions());
|
||||
|
||||
auto const weight = RouteWeight(m_estimator->CalcSegmentWeight(segment, road, purpose));
|
||||
|
||||
if (purpose == EdgeEstimator::Purpose::Weight)
|
||||
{
|
||||
if(m_estimator->GetStrategy() == EdgeEstimator::Strategy::Shortest)
|
||||
{
|
||||
return weight;
|
||||
}
|
||||
}
|
||||
|
||||
auto const penalties = GetPenalties(purpose, isOutgoing ? from : to, isOutgoing ? to : from, prevWeight);
|
||||
|
||||
return weight + penalties;
|
||||
|
|
|
@ -133,6 +133,8 @@ public:
|
|||
|
||||
bool IsUTurnAndRestricted(Segment const & parent, Segment const & child, bool isOutgoing) const;
|
||||
|
||||
bool IsTurn(Segment const & u, Segment const & v) const;
|
||||
|
||||
/// @param[in] isOutgoing true, when movig from -> to, false otherwise.
|
||||
/// @param[in] prevWeight used for fetching access:conditional.
|
||||
/// I suppose :) its time when user will be at the end of |from| (|to| if \a isOutgoing == false) segment.
|
||||
|
|
|
@ -326,6 +326,10 @@ bool IndexRouter::FindClosestProjectionToRoad(m2::PointD const & point,
|
|||
return true;
|
||||
}
|
||||
|
||||
void IndexRouter::SetEstimatorOptions(RoutingOptions::RoadType options) {m_estimator ->SetAvoidRoutingOptions(options);}
|
||||
|
||||
void IndexRouter::SetEstimatorStrategy(EdgeEstimator::Strategy strategy) {m_estimator ->SetStrategy(strategy);}
|
||||
|
||||
void IndexRouter::SetGuides(GuidesTracks && guides) { m_guides = GuidesConnections(guides); }
|
||||
|
||||
RouterResultCode IndexRouter::CalculateRoute(Checkpoints const & checkpoints,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "routing/regions_decl.hpp"
|
||||
#include "routing/router.hpp"
|
||||
#include "routing/routing_callbacks.hpp"
|
||||
#include "routing/routing_options.hpp"
|
||||
#include "routing/segment.hpp"
|
||||
#include "routing/segmented_route.hpp"
|
||||
|
||||
|
@ -77,6 +78,10 @@ public:
|
|||
std::string GetName() const override { return m_name; }
|
||||
void ClearState() override;
|
||||
|
||||
void SetEstimatorOptions(RoutingOptions::RoadType options) override;
|
||||
|
||||
void SetEstimatorStrategy(EdgeEstimator::Strategy strategy) override;
|
||||
|
||||
void SetGuides(GuidesTracks && guides) override;
|
||||
RouterResultCode CalculateRoute(Checkpoints const & checkpoints,
|
||||
m2::PointD const & startDirection, bool adjustToPrevRoute,
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/checkpoints.hpp"
|
||||
#include "routing/edge_estimator.hpp"
|
||||
#include "routing/road_graph.hpp"
|
||||
#include "routing/router_delegate.hpp"
|
||||
#include "routing/routing_callbacks.hpp"
|
||||
#include "routing/routing_options.hpp"
|
||||
|
||||
#include "kml/type_utils.hpp"
|
||||
|
||||
|
@ -62,6 +64,10 @@ public:
|
|||
/// Clear all temporary buffers.
|
||||
virtual void ClearState() {}
|
||||
|
||||
virtual void SetEstimatorOptions(RoutingOptions::RoadType options) {}
|
||||
|
||||
virtual void SetEstimatorStrategy(EdgeEstimator::Strategy strategy) {}
|
||||
|
||||
virtual void SetGuides(GuidesTracks && guides) = 0;
|
||||
|
||||
/// Override this function with routing implementation.
|
||||
|
|
|
@ -50,6 +50,11 @@ bool RoutingOptions::Has(RoutingOptions::Road type) const
|
|||
return (m_options & static_cast<RoadType>(type)) != 0;
|
||||
}
|
||||
|
||||
void RoutingOptions::SetOptions(RoadType options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
// RoutingOptionsClassifier ---------------------------------------------------------------------------
|
||||
|
||||
RoutingOptionsClassifier::RoutingOptionsClassifier()
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
bool Has(Road type) const;
|
||||
|
||||
RoadType GetOptions() const { return m_options; }
|
||||
void SetOptions(RoadType options);
|
||||
|
||||
private:
|
||||
RoadType m_options = 0;
|
||||
|
|
|
@ -146,6 +146,7 @@ double WeightedEdgeEstimator::CalcSegmentWeight(Segment const & segment,
|
|||
}
|
||||
|
||||
double WeightedEdgeEstimator::GetUTurnPenalty(Purpose purpose) const { return 0.0; }
|
||||
double WeightedEdgeEstimator::GetTurnPenalty(Purpose purpose) const { return 0.0; }
|
||||
double WeightedEdgeEstimator::GetFerryLandingPenalty(Purpose purpose) const { return 0.0; }
|
||||
|
||||
// TestIndexGraphTopology --------------------------------------------------------------------------
|
||||
|
|
|
@ -181,6 +181,7 @@ public:
|
|||
EdgeEstimator::Purpose purpose) const override;
|
||||
|
||||
double GetUTurnPenalty(Purpose purpose) const override;
|
||||
double GetTurnPenalty(Purpose purpose) const override;
|
||||
double GetFerryLandingPenalty(Purpose purpose) const override;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Add table
Reference in a new issue