in SupportingScripts/Runtime/Scripts/MapRenderer/Interaction/MapInteractionController.cs [283:332]
private void PanAndZoom(
Ray ray,
ValueTuple<MercatorCoordinate, double>? targetCoordinateAndAltitude,
float zoomLevelSpeed,
bool requireRayHitForZoom)
{
var zoomLevelDelta = ZoomLevelsPerSecond * Time.deltaTime * zoomLevelSpeed;
if (zoomLevelDelta != 0 &&
!(_mapRenderer.ZoomLevel >= _mapRenderer.MaximumZoomLevel && zoomLevelDelta > 0) &&
!(_mapRenderer.ZoomLevel <= _mapRenderer.MinimumZoomLevel && zoomLevelDelta < 0))
{
// If we're not panning, detemrine where the ray is intersecting the map. If it's not intersecting the map,
// no zoom will occur.
if (!targetCoordinateAndAltitude.HasValue)
{
if (_mapRenderer.Raycast(ray, out var hitInfo))
{
targetCoordinateAndAltitude = (hitInfo.Location.LatLon.ToMercatorCoordinate(), hitInfo.Location.AltitudeInMeters);
}
}
}
if (targetCoordinateAndAltitude.HasValue)
{
_mapRenderer.ZoomLevel += zoomLevelDelta;
var targetCoordinate = targetCoordinateAndAltitude.Value.Item1;
var targetAltitude = targetCoordinateAndAltitude.Value.Item2;
// Compute a plane that is parallel to the map's surface and passes through the target coordinate and altitude.
var newTargetLocationInWorldSpace =
_mapRenderer.TransformMercatorWithAltitudeToWorldPoint(targetCoordinate, targetAltitude);
var targetPlaneInWorldSpace = new Plane(_mapRenderer.transform.up, newTargetLocationInWorldSpace);
// Raycast this "target plane" to determine where the ray is hitting.
if (targetPlaneInWorldSpace.Raycast(ray, out var enter))
{
var pointInWorldSpace = ray.GetPoint(enter);
var planeHitPointInMercatorSpace = _mapRenderer.TransformWorldPointToMercator(pointInWorldSpace);
var deltaInMercatorSpace = planeHitPointInMercatorSpace - targetCoordinate;
var recoveredCenter = _mapRenderer.Center.ToMercatorCoordinate() - deltaInMercatorSpace;
var newCenter = recoveredCenter.ToLatLon();
_mapRenderer.Center = newCenter;
}
}
else if (!requireRayHitForZoom)
{
_mapRenderer.ZoomLevel += zoomLevelDelta;
}
}