848 lines
48 KiB
C++
848 lines
48 KiB
C++
|
|
#include "routing/edge_estimator.hpp"
|
|||
|
|
#include "routing/geometry.hpp"
|
|||
|
|
#include "routing/latlon_with_altitude.hpp"
|
|||
|
|
#include "routing/routing_helpers.hpp"
|
|||
|
|
#include "routing/traffic_stash.hpp"
|
|||
|
|
|
|||
|
|
#include "traffic/speed_groups.hpp"
|
|||
|
|
|
|||
|
|
#include "geometry/distance_on_sphere.hpp"
|
|||
|
|
#include "geometry/point_with_altitude.hpp"
|
|||
|
|
|
|||
|
|
#include "coding/csv_reader.hpp"
|
|||
|
|
|
|||
|
|
#include "base/assert.hpp"
|
|||
|
|
#include "base/logging.hpp"
|
|||
|
|
#include "platform/platform.hpp"
|
|||
|
|
|
|||
|
|
namespace routing
|
|||
|
|
{
|
|||
|
|
using namespace std;
|
|||
|
|
using namespace traffic;
|
|||
|
|
using measurement_utils::KmphToMps;
|
|||
|
|
|
|||
|
|
namespace
|
|||
|
|
{
|
|||
|
|
geometry::Altitude constexpr kMountainSicknessAltitudeM = 2500;
|
|||
|
|
|
|||
|
|
double TimeBetweenSec(ms::LatLon const & from, ms::LatLon const & to, double speedMpS)
|
|||
|
|
{
|
|||
|
|
ASSERT_GREATER(speedMpS, 0.0, ("from:", from, "to:", to));
|
|||
|
|
|
|||
|
|
double const distanceM = ms::DistanceOnEarth(from, to);
|
|||
|
|
return distanceM / speedMpS;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double CalcTrafficFactor(SpeedGroup speedGroup)
|
|||
|
|
{
|
|||
|
|
if (speedGroup == SpeedGroup::TempBlock)
|
|||
|
|
{
|
|||
|
|
// impossible driving factor
|
|||
|
|
return 1.0E4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double const percentage = 0.01 * kSpeedGroupThresholdPercentage[static_cast<size_t>(speedGroup)];
|
|||
|
|
ASSERT_GREATER(percentage, 0.0, (speedGroup));
|
|||
|
|
return 1.0 / percentage;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double GetSpeedMpS(EdgeEstimator::Purpose purpose, Segment const & segment, RoadGeometry const & road)
|
|||
|
|
{
|
|||
|
|
SpeedKMpH const & speed = road.GetSpeed(segment.IsForward());
|
|||
|
|
double const speedMpS = KmphToMps(purpose == EdgeEstimator::Purpose::Weight ? speed.m_weight : speed.m_eta);
|
|||
|
|
ASSERT_GREATER(speedMpS, 0.0, (segment));
|
|||
|
|
return speedMpS;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool IsTransit(std::optional<HighwayType> type)
|
|||
|
|
{
|
|||
|
|
return type && (type == HighwayType::RouteFerry || type == HighwayType::RouteShuttleTrain);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
template <class CalcSpeed>
|
|||
|
|
double CalcClimbSegment(EdgeEstimator::Purpose purpose, Segment const & segment, RoadGeometry const & road,
|
|||
|
|
CalcSpeed && calcSpeed)
|
|||
|
|
{
|
|||
|
|
double const distance = road.GetDistance(segment.GetSegmentIdx());
|
|||
|
|
double speedMpS = GetSpeedMpS(purpose, segment, road);
|
|||
|
|
|
|||
|
|
static double constexpr kSmallDistanceM = 1; // we have altitude threshold is 0.5m
|
|||
|
|
if (distance > kSmallDistanceM && !IsTransit(road.GetHighwayType()))
|
|||
|
|
{
|
|||
|
|
LatLonWithAltitude const & from = road.GetJunction(segment.GetPointId(false /* front */));
|
|||
|
|
LatLonWithAltitude const & to = road.GetJunction(segment.GetPointId(true /* front */));
|
|||
|
|
|
|||
|
|
ASSERT(to.GetAltitude() != geometry::kInvalidAltitude && from.GetAltitude() != geometry::kInvalidAltitude, ());
|
|||
|
|
auto const altitudeDiff = to.GetAltitude() - from.GetAltitude();
|
|||
|
|
|
|||
|
|
if (altitudeDiff != 0)
|
|||
|
|
{
|
|||
|
|
speedMpS = calcSpeed(speedMpS, altitudeDiff / distance, to.GetAltitude());
|
|||
|
|
ASSERT_GREATER(speedMpS, 0.0, (segment));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return distance / speedMpS;
|
|||
|
|
}
|
|||
|
|
} // namespace
|
|||
|
|
|
|||
|
|
double GetPedestrianClimbPenalty(EdgeEstimator::Purpose purpose, double tangent, geometry::Altitude altitudeM)
|
|||
|
|
{
|
|||
|
|
double constexpr kMinPenalty = 1.0;
|
|||
|
|
// Descent penalty is less then the ascent penalty.
|
|||
|
|
double const impact = tangent >= 0.0 ? 1.0 : 0.35;
|
|||
|
|
|
|||
|
|
if (altitudeM >= kMountainSicknessAltitudeM)
|
|||
|
|
return kMinPenalty + (10.0 + (altitudeM - kMountainSicknessAltitudeM) * 10.0 / 1500.0) * fabs(tangent) * impact;
|
|||
|
|
|
|||
|
|
// Use magic constant from this table: https://en.wikipedia.org/wiki/Tobler's_hiking_function#Sample_values
|
|||
|
|
// Tobler's returns unusually big values for bigger tangent.
|
|||
|
|
// See Australia_Mountains_Downlhill test.
|
|||
|
|
if (purpose == EdgeEstimator::Purpose::Weight || fabs(tangent) > 1.19)
|
|||
|
|
{
|
|||
|
|
tangent = fabs(tangent);
|
|||
|
|
// Some thoughts about gradient and foot walking: https://gre-kow.livejournal.com/26916.html
|
|||
|
|
// 3cm diff with avg foot length 60cm is imperceptible (see Hungary_UseFootways).
|
|||
|
|
double constexpr kTangentThreshold = 3.0 / 60.0;
|
|||
|
|
if (tangent < kTangentThreshold)
|
|||
|
|
return kMinPenalty;
|
|||
|
|
|
|||
|
|
// ETA coefficients are calculated in https://github.com/mapsme/omim-scripts/pull/21
|
|||
|
|
auto const penalty = purpose == EdgeEstimator::Purpose::Weight ? 5.0 * tangent + 7.0 * tangent * tangent
|
|||
|
|
: 3.01 * tangent + 3.54 * tangent * tangent;
|
|||
|
|
|
|||
|
|
return kMinPenalty + penalty * impact;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// Use Tobler’s Hiking Function for ETA like more comprehensive. See France_Uphill_Downlhill test.
|
|||
|
|
// Why not in Weight? See Crimea_Altitude_Mountains test.
|
|||
|
|
// https://mtntactical.com/research/yet-calculating-movement-uneven-terrain/
|
|||
|
|
// Returns factor: W(0) / W(tangent).
|
|||
|
|
return exp(-3.5 * (0.05 - fabs(tangent + 0.05)));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double GetBicycleClimbPenalty(EdgeEstimator::Purpose purpose, double tangent, geometry::Altitude altitudeM)
|
|||
|
|
{
|
|||
|
|
double constexpr kMinPenalty = 1.0;
|
|||
|
|
double const impact = tangent >= 0.0 ? 1.0 : 0.35;
|
|||
|
|
|
|||
|
|
if (altitudeM >= kMountainSicknessAltitudeM)
|
|||
|
|
return kMinPenalty + 50.0 * fabs(tangent) * impact;
|
|||
|
|
|
|||
|
|
// By VNG: This approach is strange at least because it always returns penalty > 1 (even for downhill)
|
|||
|
|
/*
|
|||
|
|
tangent = fabs(tangent);
|
|||
|
|
// ETA coefficients are calculated in https://github.com/mapsme/omim-scripts/pull/22
|
|||
|
|
auto const penalty = purpose == EdgeEstimator::Purpose::Weight
|
|||
|
|
? 10.0 * tangent + 26.0 * tangent * tangent
|
|||
|
|
: 8.8 * tangent + 6.51 * tangent * tangent;
|
|||
|
|
|
|||
|
|
return kMinPenalty + penalty * impact;
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
// https://web.tecnico.ulisboa.pt/~rosamfelix/gis/declives/SpeedSlopeFactor.html
|
|||
|
|
double const slope = tangent * 100;
|
|||
|
|
|
|||
|
|
double factor;
|
|||
|
|
if (slope < -30)
|
|||
|
|
factor = 1.5;
|
|||
|
|
else if (slope < 0)
|
|||
|
|
{
|
|||
|
|
// Min factor (max speed) will be at slope = -13.
|
|||
|
|
factor = 1 + 2 * 0.7 / 13.0 * slope + 0.7 / 169 * slope * slope;
|
|||
|
|
}
|
|||
|
|
else if (slope <= 20)
|
|||
|
|
factor = 1 + slope * slope / 49;
|
|||
|
|
else
|
|||
|
|
factor = 10.0;
|
|||
|
|
return factor;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double GetCarClimbPenalty(EdgeEstimator::Purpose, double, geometry::Altitude)
|
|||
|
|
{
|
|||
|
|
return 1.0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// EdgeEstimator -----------------------------------------------------------------------------------
|
|||
|
|
EdgeEstimator::EdgeEstimator(VehicleType vehicleType, double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
|
|||
|
|
DataSource * /*dataSourcePtr*/, std::shared_ptr<NumMwmIds> /*numMwmIds*/)
|
|||
|
|
: m_vehicleType(vehicleType)
|
|||
|
|
, m_maxWeightSpeedMpS(KmphToMps(maxWeightSpeedKMpH))
|
|||
|
|
, m_offroadSpeedKMpH(offroadSpeedKMpH)
|
|||
|
|
|
|||
|
|
//, m_dataSourcePtr(dataSourcePtr)
|
|||
|
|
//, m_numMwmIds(numMwmIds)
|
|||
|
|
{
|
|||
|
|
CHECK_GREATER(m_offroadSpeedKMpH.m_weight, 0.0, ());
|
|||
|
|
CHECK_GREATER(m_offroadSpeedKMpH.m_eta, 0.0, ());
|
|||
|
|
CHECK_GREATER_OR_EQUAL(m_maxWeightSpeedMpS, KmphToMps(m_offroadSpeedKMpH.m_weight), ());
|
|||
|
|
|
|||
|
|
if (m_offroadSpeedKMpH.m_eta != kNotUsed)
|
|||
|
|
CHECK_GREATER_OR_EQUAL(m_maxWeightSpeedMpS, KmphToMps(m_offroadSpeedKMpH.m_eta), ());
|
|||
|
|
|
|||
|
|
LOG(LINFO, ("Loading turn penalties for vehicle type:", static_cast<int>(vehicleType)));
|
|||
|
|
|
|||
|
|
struct TurnPenaltyMatrix
|
|||
|
|
{
|
|||
|
|
int road;
|
|||
|
|
VehicleType vehicleType;
|
|||
|
|
double penalty;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
struct TurnPenalty
|
|||
|
|
{
|
|||
|
|
HighwayType fromRoadType;
|
|||
|
|
HighwayType toRoadType;
|
|||
|
|
VehicleType vehicleType;
|
|||
|
|
double penalty;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
#define N 288
|
|||
|
|
|
|||
|
|
static auto constexpr kTurnPenaltyMatrix = []
|
|||
|
|
{
|
|||
|
|
array<TurnPenalty, N> constexpr kTable = {{
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTrunk, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.11},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayPrimary, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayService, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTertiary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTrunk, VehicleType::Car, 0.04},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.04},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayUnclassified, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayService, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayResidential, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTrunk, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayService, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayService, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayResidential, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayPrimary, VehicleType::Car, 0.05},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.03},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayResidential, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayService, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTertiary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTrunk, VehicleType::Car, 0.01},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.01},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.11},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.06},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.02},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.1},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayService, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTrunk, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayService, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.11},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayService, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.04},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.04},
|
|||
|
|
{HighwayType::HighwayPrimary, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayService, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayService, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayResidential, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayService, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwaySecondary, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayService, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.05},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayService, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayService, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayService, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiary, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayService, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.05},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.03},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayService, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.01},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.01},
|
|||
|
|
{HighwayType::HighwayTrunk, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.11},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.04},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayService, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.06},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.02},
|
|||
|
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.1},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayLivingStreet, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayPrimary, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayPrimaryLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayResidential, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwaySecondary, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwaySecondaryLink, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayService, VehicleType::Bicycle, 0.08},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTertiary, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTertiaryLink, VehicleType::Bicycle, 0.07},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTrunk, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTrunkLink, VehicleType::Bicycle, 0.09},
|
|||
|
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayUnclassified, VehicleType::Bicycle, 0.08},
|
|||
|
|
}};
|
|||
|
|
|
|||
|
|
array<TurnPenaltyMatrix, N> result{};
|
|||
|
|
|
|||
|
|
for (size_t i = 0; i < N; ++i)
|
|||
|
|
result[i] = {static_cast<int>(kTable[i].fromRoadType) * 65535 + static_cast<int>(kTable[i].toRoadType),
|
|||
|
|
kTable[i].vehicleType, kTable[i].penalty};
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}();
|
|||
|
|
|
|||
|
|
double totalPenalty = 0;
|
|||
|
|
|
|||
|
|
for (TurnPenaltyMatrix const & row : kTurnPenaltyMatrix)
|
|||
|
|
{
|
|||
|
|
if (row.vehicleType != vehicleType)
|
|||
|
|
continue;
|
|||
|
|
|
|||
|
|
m_turnPenaltyMap[row.road] += row.penalty;
|
|||
|
|
totalPenalty += row.penalty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!m_turnPenaltyMap.empty())
|
|||
|
|
{
|
|||
|
|
m_defaultPenalty = totalPenalty / m_turnPenaltyMap.size();
|
|||
|
|
LOG(LINFO, ("Loaded", m_turnPenaltyMap.size(), "turn penalties with default:", m_defaultPenalty));
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
LOG(LWARNING, ("No turn penalties loaded for vehicle type:", static_cast<int>(vehicleType)));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double EdgeEstimator::CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const
|
|||
|
|
{
|
|||
|
|
// For the correct A*, we should use maximum _possible_ speed here, including:
|
|||
|
|
// default model, feature stored, unlimited autobahn, ferry or rail transit.
|
|||
|
|
return TimeBetweenSec(from, to, m_maxWeightSpeedMpS);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double EdgeEstimator::ComputeDefaultLeapWeightSpeed() const
|
|||
|
|
{
|
|||
|
|
// 1.76 factor was computed as an average ratio of escape/enter speed to max MWM speed across all MWMs.
|
|||
|
|
// return m_maxWeightSpeedMpS / 1.76;
|
|||
|
|
|
|||
|
|
// By VNG: Current m_maxWeightSpeedMpS is > 120 km/h, so estimating speed was > 60km/h
|
|||
|
|
// for start/end fake edges by straight line! I strongly believe that this is very! optimistic.
|
|||
|
|
// Set speed to 57.5km/h (16m/s):
|
|||
|
|
// - lower bound Russia_MoscowDesnogorsk (https://github.com/organicmaps/organicmaps/issues/1071)
|
|||
|
|
// - upper bound RussiaSmolenskRussiaMoscowTimeTest
|
|||
|
|
return 16.0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
double EdgeEstimator::LoadLeapWeightSpeed(NumMwmId mwmId)
|
|||
|
|
{
|
|||
|
|
double leapWeightSpeed = ComputeDefaultLeapWeightSpeed();
|
|||
|
|
|
|||
|
|
if (m_dataSourcePtr)
|
|||
|
|
{
|
|||
|
|
MwmSet::MwmHandle handle =
|
|||
|
|
m_dataSourcePtr->GetMwmHandleByCountryFile(m_numMwmIds->GetFile(mwmId));
|
|||
|
|
if (!handle.IsAlive())
|
|||
|
|
MYTHROW(RoutingException, ("Mwm", m_numMwmIds->GetFile(mwmId), "cannot be loaded."));
|
|||
|
|
|
|||
|
|
if (handle.GetInfo())
|
|||
|
|
leapWeightSpeed = handle.GetInfo()->GetRegionData().GetLeapWeightSpeed(leapWeightSpeed);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (leapWeightSpeed > m_maxWeightSpeedMpS)
|
|||
|
|
leapWeightSpeed = m_maxWeightSpeedMpS;
|
|||
|
|
|
|||
|
|
return leapWeightSpeed;
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
double EdgeEstimator::GetLeapWeightSpeed(NumMwmId /*mwmId*/)
|
|||
|
|
{
|
|||
|
|
double defaultSpeed = ComputeDefaultLeapWeightSpeed();
|
|||
|
|
|
|||
|
|
/// @todo By VNG: We don't have LEAP_SPEEDS_FILE to assign RegionData::SetLeapWeightSpeed
|
|||
|
|
/// unique for each MWM, so this is useless now. And what about possible races here?
|
|||
|
|
// if (mwmId != kFakeNumMwmId)
|
|||
|
|
// {
|
|||
|
|
// auto [speedIt, inserted] = m_leapWeightSpeedMpS.emplace(mwmId, defaultSpeed);
|
|||
|
|
// if (inserted)
|
|||
|
|
// speedIt->second = LoadLeapWeightSpeed(mwmId);
|
|||
|
|
// return speedIt->second;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
return defaultSpeed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double EdgeEstimator::CalcLeapWeight(ms::LatLon const & from, ms::LatLon const & to, NumMwmId mwmId)
|
|||
|
|
{
|
|||
|
|
return TimeBetweenSec(from, to, GetLeapWeightSpeed(mwmId));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double EdgeEstimator::GetMaxWeightSpeedMpS() const
|
|||
|
|
{
|
|||
|
|
return m_maxWeightSpeedMpS;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double EdgeEstimator::CalcOffroad(ms::LatLon const & from, ms::LatLon const & to, Purpose purpose) const
|
|||
|
|
{
|
|||
|
|
auto const offroadSpeedKMpH = purpose == Purpose::Weight ? m_offroadSpeedKMpH.m_weight : m_offroadSpeedKMpH.m_eta;
|
|||
|
|
if (offroadSpeedKMpH == kNotUsed)
|
|||
|
|
return 0.0;
|
|||
|
|
|
|||
|
|
return TimeBetweenSec(from, to, KmphToMps(offroadSpeedKMpH));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// PedestrianEstimator -----------------------------------------------------------------------------
|
|||
|
|
class PedestrianEstimator final : public EdgeEstimator
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
PedestrianEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
|||
|
|
: EdgeEstimator(VehicleType::Pedestrian, maxWeightSpeedKMpH, offroadSpeedKMpH)
|
|||
|
|
{}
|
|||
|
|
|
|||
|
|
// EdgeEstimator overrides:
|
|||
|
|
double GetUTurnPenalty(Purpose /* purpose */) const override { return 0.0 /* seconds */; }
|
|||
|
|
|
|||
|
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
|||
|
|
bool is_left_hand_traffic = false) const override
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double GetFerryLandingPenalty(Purpose purpose) const override
|
|||
|
|
{
|
|||
|
|
switch (purpose)
|
|||
|
|
{
|
|||
|
|
case Purpose::Weight: return 10 * 60; // seconds
|
|||
|
|
case Purpose::ETA: return 8 * 60; // seconds
|
|||
|
|
}
|
|||
|
|
UNREACHABLE();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override
|
|||
|
|
{
|
|||
|
|
return CalcClimbSegment(purpose, segment, road,
|
|||
|
|
[purpose](double speedMpS, double tangent, geometry::Altitude altitude)
|
|||
|
|
{ return speedMpS / GetPedestrianClimbPenalty(purpose, tangent, altitude); });
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// BicycleEstimator --------------------------------------------------------------------------------
|
|||
|
|
class BicycleEstimator final : public EdgeEstimator
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
BicycleEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
|||
|
|
: EdgeEstimator(VehicleType::Bicycle, maxWeightSpeedKMpH, offroadSpeedKMpH)
|
|||
|
|
{}
|
|||
|
|
|
|||
|
|
// EdgeEstimator overrides:
|
|||
|
|
double GetUTurnPenalty(Purpose /* purpose */) const override { return 20.0 /* seconds */; }
|
|||
|
|
|
|||
|
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
|||
|
|
bool is_left_hand_traffic = false) const override;
|
|||
|
|
|
|||
|
|
double GetFerryLandingPenalty(Purpose purpose) const override
|
|||
|
|
{
|
|||
|
|
switch (purpose)
|
|||
|
|
{
|
|||
|
|
case Purpose::Weight: return 10 * 60; // seconds
|
|||
|
|
case Purpose::ETA: return 8 * 60; // seconds
|
|||
|
|
}
|
|||
|
|
UNREACHABLE();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override
|
|||
|
|
{
|
|||
|
|
return CalcClimbSegment(purpose, segment, road,
|
|||
|
|
[purpose, this](double speedMpS, double tangent, geometry::Altitude altitude)
|
|||
|
|
{
|
|||
|
|
auto const factor = GetBicycleClimbPenalty(purpose, tangent, altitude);
|
|||
|
|
ASSERT_GREATER(factor, 0.0, ());
|
|||
|
|
|
|||
|
|
/// @todo Take out "bad" bicycle road (path, track, footway, ...) check into BicycleModel?
|
|||
|
|
static double constexpr badBicycleRoadSpeed = KmphToMps(9);
|
|||
|
|
if (speedMpS <= badBicycleRoadSpeed)
|
|||
|
|
{
|
|||
|
|
if (factor > 1)
|
|||
|
|
speedMpS /= factor;
|
|||
|
|
}
|
|||
|
|
else if (factor > 1)
|
|||
|
|
{
|
|||
|
|
// Calculate uphill speed according to the average bicycle speed, because "good-roads" like
|
|||
|
|
// residential, secondary, cycleway are "equal-low-speed" uphill and road type doesn't matter.
|
|||
|
|
static double constexpr avgBicycleSpeed = KmphToMps(20);
|
|||
|
|
double const upperBound = avgBicycleSpeed / factor;
|
|||
|
|
if (speedMpS > upperBound)
|
|||
|
|
{
|
|||
|
|
// Add small weight to distinguish roads by class (10 is a max factor value).
|
|||
|
|
speedMpS = upperBound + (purpose == Purpose::Weight ? speedMpS / (10 * avgBicycleSpeed) : 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
speedMpS /= factor;
|
|||
|
|
|
|||
|
|
return std::min(speedMpS, GetMaxWeightSpeedMpS());
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
double BicycleEstimator::GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road,
|
|||
|
|
RoadGeometry const & to_road, bool is_left_hand_traffic) const
|
|||
|
|
{
|
|||
|
|
auto penalty = m_defaultPenalty;
|
|||
|
|
|
|||
|
|
if (from_road.GetHighwayType().has_value() && to_road.GetHighwayType().has_value())
|
|||
|
|
{
|
|||
|
|
int const from_road_idx = static_cast<int>(from_road.GetHighwayType().value());
|
|||
|
|
int const to_road_idx = static_cast<int>(to_road.GetHighwayType().value());
|
|||
|
|
auto const pen = m_turnPenaltyMap.find(from_road_idx * 65535 + to_road_idx);
|
|||
|
|
if (pen != m_turnPenaltyMap.end())
|
|||
|
|
penalty = pen->second;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Determine if turn crosses traffic based on driving side
|
|||
|
|
// For bicycles, crossing traffic is less dangerous than for cars but still a factor
|
|||
|
|
bool turn_crosses_traffic;
|
|||
|
|
if (is_left_hand_traffic)
|
|||
|
|
turn_crosses_traffic = angle < 0;
|
|||
|
|
else
|
|||
|
|
turn_crosses_traffic = angle > 0;
|
|||
|
|
|
|||
|
|
// Penalty multiplier for bicycles crossing traffic
|
|||
|
|
auto const extra_penalty = turn_crosses_traffic ? 2.0 : 1.0;
|
|||
|
|
auto const result = fabs(angle) * penalty * extra_penalty;
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CarEstimator ------------------------------------------------------------------------------------
|
|||
|
|
class CarEstimator final : public EdgeEstimator
|
|||
|
|
{
|
|||
|
|
public:
|
|||
|
|
CarEstimator(DataSource * dataSourcePtr, std::shared_ptr<NumMwmIds> numMwmIds, shared_ptr<TrafficStash> trafficStash,
|
|||
|
|
double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
|||
|
|
: EdgeEstimator(VehicleType::Car, maxWeightSpeedKMpH, offroadSpeedKMpH, dataSourcePtr, numMwmIds)
|
|||
|
|
, m_trafficStash(std::move(trafficStash))
|
|||
|
|
{}
|
|||
|
|
|
|||
|
|
// EdgeEstimator overrides:
|
|||
|
|
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override;
|
|||
|
|
double GetUTurnPenalty(Purpose /* purpose */) const override;
|
|||
|
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
|||
|
|
bool is_left_hand_traffic = false) const override;
|
|||
|
|
double GetFerryLandingPenalty(Purpose purpose) const override
|
|||
|
|
{
|
|||
|
|
switch (purpose)
|
|||
|
|
{
|
|||
|
|
case Purpose::Weight: return 20 * 60; // seconds
|
|||
|
|
case Purpose::ETA: return 20 * 60; // seconds
|
|||
|
|
}
|
|||
|
|
UNREACHABLE();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
std::shared_ptr<TrafficStash> m_trafficStash;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
double CarEstimator::GetUTurnPenalty(Purpose /* purpose */) const
|
|||
|
|
{
|
|||
|
|
// 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 CarEstimator::GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road,
|
|||
|
|
RoadGeometry const & to_road, bool is_left_hand_traffic) const
|
|||
|
|
{
|
|||
|
|
auto penalty = m_defaultPenalty;
|
|||
|
|
|
|||
|
|
if (from_road.GetHighwayType().has_value() && to_road.GetHighwayType().has_value())
|
|||
|
|
{
|
|||
|
|
int const from_road_idx = static_cast<int>(from_road.GetHighwayType().value());
|
|||
|
|
int const to_road_idx = static_cast<int>(to_road.GetHighwayType().value());
|
|||
|
|
auto const pen = m_turnPenaltyMap.find(from_road_idx * 65535 + to_road_idx);
|
|||
|
|
if (pen != m_turnPenaltyMap.end())
|
|||
|
|
penalty = pen->second;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Determine if turn crosses traffic based on driving side
|
|||
|
|
// @TODO We should really account for oneway roads etc.
|
|||
|
|
|
|||
|
|
bool turn_crosses_traffic;
|
|||
|
|
if (is_left_hand_traffic)
|
|||
|
|
turn_crosses_traffic = angle < 0;
|
|||
|
|
else
|
|||
|
|
turn_crosses_traffic = angle > 0;
|
|||
|
|
|
|||
|
|
// Twice as long to turn across traffic than not to
|
|||
|
|
auto const extra_penalty = turn_crosses_traffic ? 2.0 : 1.0;
|
|||
|
|
auto const result = fabs(angle) * penalty * extra_penalty;
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const
|
|||
|
|
{
|
|||
|
|
double result = road.GetDistance(segment.GetSegmentIdx()) / GetSpeedMpS(purpose, segment, road);
|
|||
|
|
|
|||
|
|
if (m_trafficStash)
|
|||
|
|
{
|
|||
|
|
SpeedGroup const speedGroup = m_trafficStash->GetSpeedGroup(segment);
|
|||
|
|
ASSERT_LESS(speedGroup, SpeedGroup::Count, ());
|
|||
|
|
double const trafficFactor = CalcTrafficFactor(speedGroup);
|
|||
|
|
result *= trafficFactor;
|
|||
|
|
if (speedGroup != SpeedGroup::Unknown && speedGroup != SpeedGroup::G5)
|
|||
|
|
{
|
|||
|
|
// Current time estimation are too optimistic.
|
|||
|
|
// Need more accurate tuning: traffic lights, traffic jams, road models and so on.
|
|||
|
|
// Add some penalty to make estimation more realistic.
|
|||
|
|
/// @todo Make accurate tuning, remove penalty.
|
|||
|
|
result *= 1.8;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// EdgeEstimator -----------------------------------------------------------------------------------
|
|||
|
|
// static
|
|||
|
|
shared_ptr<EdgeEstimator> EdgeEstimator::Create(VehicleType vehicleType, double maxWeighSpeedKMpH,
|
|||
|
|
SpeedKMpH const & offroadSpeedKMpH,
|
|||
|
|
shared_ptr<TrafficStash> trafficStash, DataSource * dataSourcePtr,
|
|||
|
|
std::shared_ptr<NumMwmIds> numMwmIds)
|
|||
|
|
{
|
|||
|
|
switch (vehicleType)
|
|||
|
|
{
|
|||
|
|
case VehicleType::Pedestrian:
|
|||
|
|
case VehicleType::Transit: return make_shared<PedestrianEstimator>(maxWeighSpeedKMpH, offroadSpeedKMpH);
|
|||
|
|
case VehicleType::Bicycle: return make_shared<BicycleEstimator>(maxWeighSpeedKMpH, offroadSpeedKMpH);
|
|||
|
|
case VehicleType::Car:
|
|||
|
|
return make_shared<CarEstimator>(dataSourcePtr, numMwmIds, trafficStash, maxWeighSpeedKMpH, offroadSpeedKMpH);
|
|||
|
|
case VehicleType::Count: CHECK(false, ("Can't create EdgeEstimator for", vehicleType)); return nullptr;
|
|||
|
|
}
|
|||
|
|
UNREACHABLE();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// static
|
|||
|
|
shared_ptr<EdgeEstimator> EdgeEstimator::Create(VehicleType vehicleType, VehicleModelInterface const & vehicleModel,
|
|||
|
|
shared_ptr<TrafficStash> trafficStash, DataSource * dataSourcePtr,
|
|||
|
|
std::shared_ptr<NumMwmIds> numMwmIds)
|
|||
|
|
{
|
|||
|
|
return Create(vehicleType, vehicleModel.GetMaxWeightSpeed(), vehicleModel.GetOffroadSpeed(), trafficStash,
|
|||
|
|
dataSourcePtr, numMwmIds);
|
|||
|
|
}
|
|||
|
|
} // namespace routing
|