internal void AddMapPin(MapPin mapPinToAdd) { mapPinToAdd.LocationChanged += MapPinLocationChanged; var latLon = mapPinToAdd.Location; // Insert into max LOD. TileId maxLodTileId; { var lodIndex = _maxLod.Value - 1; maxLodTileId = new TileId(latLon, _maxLod); if (!_tiledSpatialIndex[lodIndex].TryGetValue(maxLodTileId.Value, out TileData maxLodTileData)) { maxLodTileData = new TileData { MapPins = new List <MapPin> { mapPinToAdd } }; _tiledSpatialIndex[lodIndex].Add(maxLodTileId.Value, maxLodTileData); } else { maxLodTileData.MapPins.Add(mapPinToAdd); } maxLodTileData.MapPinCount++; maxLodTileData.TotalLat += latLon.LatitudeInDegrees; maxLodTileData.TotalLon += latLon.LongitudeInDegrees; } // Bubble up tile into parent LODs. maxLodTileId.TryGetParent(out var parentTileId); var parentLodIndex = parentTileId.CalculateLevelOfDetail().Value - 1; while (parentLodIndex >= 0) { if (!_tiledSpatialIndex[parentLodIndex].TryGetValue(parentTileId.Value, out var parentTileData)) { // This is a new tile. Create and add a new TileData for this LOD. parentTileData = new TileData { MapPins = new List <MapPin> { mapPinToAdd }, MapPinCount = 1, TotalLat = latLon.LatitudeInDegrees, TotalLon = latLon.LongitudeInDegrees }; _tiledSpatialIndex[parentLodIndex].Add(parentTileId.Value, parentTileData); } else { // We already have a tile with points or clusters. // In either case, track the LatLong. parentTileData.MapPinCount++; parentTileData.TotalLat += latLon.LatitudeInDegrees; parentTileData.TotalLon += latLon.LongitudeInDegrees; var isCluster = _isClusteringEnabled && parentTileData.MapPinCount > ClusterThreshold; if (isCluster) { parentTileData.MapPins = null; } else { parentTileData.MapPins.Add(mapPinToAdd); } } parentLodIndex--; parentTileId.TryGetParent(out parentTileId); } }
private void RemoveMapPin(MapPin mapPinToRemove, LatLon locationOverride) { // Find the MapPin in the spatial index at the max LOD. var lodIndex = _maxLod.Value - 1; var maxLodTileId = new TileId(locationOverride, _maxLod); var indexChanged = false; if (_tiledSpatialIndex[lodIndex].TryGetValue(maxLodTileId.Value, out TileData maxLodTileData)) { if (maxLodTileData.MapPins.Remove(mapPinToRemove)) { indexChanged = true; mapPinToRemove.LocationChanged -= MapPinLocationChanged; maxLodTileData.MapPinCount--; if (maxLodTileData.MapPinCount == 0) { // Remove tile if now empty. _tiledSpatialIndex[lodIndex].Remove(maxLodTileId.Value); } else { maxLodTileData.TotalLat -= locationOverride.LatitudeInDegrees; maxLodTileData.TotalLon -= locationOverride.LongitudeInDegrees; } } } // Bubble up change to parent tiles. if (indexChanged) { maxLodTileId.TryGetParent(out var parentTileId); var parentLodIndex = parentTileId.CalculateLevelOfDetail().Value - 1; while (parentLodIndex >= 0) { _tiledSpatialIndex[parentLodIndex].TryGetValue(parentTileId.Value, out var parentTileData); parentTileData.MapPinCount--; if (parentTileData.MapPinCount == 0) { // No more pins left in this tile. Remove it from the spatial index. _tiledSpatialIndex[parentLodIndex].Remove(parentTileId.Value); #if DEBUG // It shouldn't be clustered. Assert.IsTrue(parentTileData.ClusterMapPin == null); #endif } else { parentTileData.TotalLat -= locationOverride.LatitudeInDegrees; parentTileData.TotalLon -= locationOverride.LongitudeInDegrees; var isCluster = _isClusteringEnabled && parentTileData.MapPinCount > ClusterThreshold; if (!isCluster) { if (parentTileData.MapPins != null) { parentTileData.MapPins.Remove(mapPinToRemove); } else { // When we remove the MapPin, this tile will fall under the cluster threshold so we will need to repopulate // the children list. parentTileData.MapPins = GatherChildren(parentTileId); // Destroy the ClusterMapPin game object if it exists. if (parentTileData.ClusterMapPin != null) { _clusterMapPins.Remove(parentTileData.ClusterMapPin); UnityEngine.Object.Destroy(parentTileData.ClusterMapPin.gameObject); parentTileData.ClusterMapPin = null; } } } } parentLodIndex--; parentTileId.TryGetParent(out parentTileId); } } }
private void MapPinLocationChanged(MapPin mapPinToUpdate, LatLon oldLocation) { RemoveMapPin(mapPinToUpdate, oldLocation); AddMapPin(mapPinToUpdate); }
internal void RemoveMapPin(MapPin mapPinToRemove) { RemoveMapPin(mapPinToRemove, mapPinToRemove.Location); }