diff --git a/iphone/Maps/Core/Location/MWMLocationManager.mm b/iphone/Maps/Core/Location/MWMLocationManager.mm index d97c6df33..22a9f5c25 100644 --- a/iphone/Maps/Core/Location/MWMLocationManager.mm +++ b/iphone/Maps/Core/Location/MWMLocationManager.mm @@ -10,6 +10,10 @@ #include "map/gps_tracker.hpp" +#if TARGET_OS_SIMULATOR +#include "MountainElevationGenerator.hpp" +#endif + namespace { using Observer = id; @@ -472,6 +476,25 @@ void setShowLocationAlert(BOOL needShow) { if (location.horizontalAccuracy < 0.) return; +#if TARGET_OS_SIMULATOR + // There is no simulator < 15.0 in the new XCode. + if (@available(iOS 15.0, *)) + { + // iOS Simulator doesn't provide any elevation in its locations. Mock it. + static MountainElevationGenerator generator; + location = [[CLLocation alloc] initWithCoordinate:location.coordinate + altitude:generator.NextElevation() + horizontalAccuracy:location.horizontalAccuracy + verticalAccuracy:location.horizontalAccuracy + course:location.course + courseAccuracy:location.courseAccuracy + speed:location.speed + speedAccuracy:location.speedAccuracy + timestamp:location.timestamp + sourceInfo:location.sourceInformation]; + } +#endif + self.lastLocationStatus = MWMLocationStatusNoError; self.locationSource = location::EAppleNative; [self processLocationUpdate:location]; diff --git a/iphone/Maps/Core/Location/MountainElevationGenerator.hpp b/iphone/Maps/Core/Location/MountainElevationGenerator.hpp new file mode 100644 index 000000000..4b3b84f40 --- /dev/null +++ b/iphone/Maps/Core/Location/MountainElevationGenerator.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +class MountainElevationGenerator +{ + static double constexpr kRandom{-1.}; + + std::mt19937_64 rng; + + double const minElevation; + double const maxElevation; + double const maxSlopeChange; + + std::normal_distribution slopeChangeDist; + + double currentElevation; + double currentSlope; + + double ValueOrRandomInRange(double value, double min, double max) + { + if (value != kRandom) + return value; + + return std::uniform_int_distribution<>(min, max)(rng); + } + +public: + MountainElevationGenerator(double minElevation = kRandom, double maxElevation = kRandom, + double startElevation = kRandom, double maxSlopeChange = kRandom, + time_t seed = std::time(nullptr)) + : rng(seed) + , minElevation(ValueOrRandomInRange(minElevation, 0., 2000.)) + , maxElevation(ValueOrRandomInRange(maxElevation, 3000., 7000.)) + , maxSlopeChange(ValueOrRandomInRange(maxSlopeChange, 1., 5.)) + , slopeChangeDist(0.0, maxSlopeChange) + , currentElevation(ValueOrRandomInRange(startElevation, minElevation, maxElevation)) + , currentSlope(0.0) + {} + + double NextElevation() + { + // Change the slope gradually + currentSlope += slopeChangeDist(rng); + + // Limit maximum steepness + currentSlope = std::max(-maxSlopeChange, std::min(maxSlopeChange, currentSlope)); + + // Update elevation based on current slope + currentElevation += currentSlope; + + // Ensure we stay within elevation bounds + if (currentElevation < minElevation) + { + currentElevation = minElevation; + currentSlope = std::abs(currentSlope) * 0.5; // Bounce back up + } + if (currentElevation > maxElevation) + { + currentElevation = maxElevation; + currentSlope = -std::abs(currentSlope) * 0.5; // Start going down + } + + return currentElevation; + } +}; diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 78d8979f9..6fd4564eb 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -1746,6 +1746,7 @@ FA3C4FE52D0DB7A600E6C03A /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/InfoPlist.strings; sourceTree = ""; }; FA3C4FE62D0DB7A700E6C03A /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/Localizable.strings; sourceTree = ""; }; FA3C4FE72D0DB7A700E6C03A /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sr; path = sr.lproj/Localizable.stringsdict; sourceTree = ""; }; + FA439D842DF618670023C181 /* MountainElevationGenerator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MountainElevationGenerator.hpp; sourceTree = ""; }; FA456C3B26BDC6AD00B83C20 /* Chart.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Chart.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FA456C4026BDCC8E00B83C20 /* shaders.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = shaders.xcodeproj; path = ../../xcode/shaders/shaders.xcodeproj; sourceTree = ""; }; FA459EB314327AF700B5BB3C /* WorldCoasts.mwm */ = {isa = PBXFileReference; lastKnownFileType = file; name = WorldCoasts.mwm; path = ../../data/WorldCoasts.mwm; sourceTree = ""; }; @@ -2098,6 +2099,7 @@ 340475291E081A4600C92850 /* Location */ = { isa = PBXGroup; children = ( + FA439D842DF618670023C181 /* MountainElevationGenerator.hpp */, 3404752A1E081A4600C92850 /* MWMLocationHelpers.h */, 3404752B1E081A4600C92850 /* MWMLocationManager.h */, 3404752C1E081A4600C92850 /* MWMLocationManager.mm */,