<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UtyMap.Unity;
using UtyMap.Unity.Data;
using UtyMap.Unity.Infrastructure.Primitives;
using UtyMap.Unity.Utils;
using Object = UnityEngine.Object;

namespace Assets.Scripts.Scene.Tiling
{
    internal sealed class SphereTileController : TileController
    {
        private readonly Vector3 _origin = Vector3.zero;

        private readonly Transform _camera;
        private readonly float _radius;
        private readonly Dictionary<QuadKey, Tile> _loadedQuadKeys = new Dictionary<QuadKey, Tile>();

        private float _zoom;
        private float _distanceToOrigin;
        private Vector3 _position;
        private Vector3 _rotation;

        public SphereTileController(IMapDataStore dataStore, Stylesheet stylesheet, ElevationDataType elevationType,
            Transform pivot, Range<int> lodRange, float radius) :
            base(dataStore, stylesheet, elevationType, pivot, lodRange)
        {
            _radius = radius;

            LodTree = GetLodTree();
            FieldOfView = 60;
            Projection = new SphericalProjection(radius);

            _camera = pivot.Find("Camera").transform;

            HeightRange = new Range<float>(LodTree.Min, LodTree.Max);
            ResetToDefaults();
        }

        /// <inheritdoc />
        protected override float Height { get { return _distanceToOrigin; } }

        /// <inheritdoc />
        public override Range<float> HeightRange { get; protected set; }

        /// <inheritdoc />
        public override float FieldOfView { get; protected set; }

        /// <inheritdoc />
        public override IProjection Projection { get; protected set; }

        /// <inheritdoc />
        public override float Zoom { get { return _zoom; } }

        /// <inheritdoc />
        public override bool IsAboveMax { get { return HeightRange.Maximum < Height; } }

        /// <inheritdoc />
        public override bool IsBelowMin { get { return HeightRange.Minimum > Height; } }

        /// <inheritdoc />
        public override GeoCoordinate Coordinate
        {
            get
            {
                var latitude = _rotation.x;
                var longitude = (-90 - _rotation.y) % 360;

                if (latitude > 90) latitude -= 360;
                if (longitude < -180) longitude += 360;

                return new GeoCoordinate(latitude, longitude);
            }
        }

        /// <inheritdoc />
        public override void Dispose()
        {
            ResetToDefaults();

            foreach (var quadkey in _loadedQuadKeys.Keys.ToArray())
                SafeDestroy(quadkey);

            Resources.UnloadUnusedAssets();
        }

        /// <inheritdoc />
        public override void Update(Transform target)
        {
            var position = _camera.localPosition;
            var rotation = Pivot.rotation.eulerAngles;

            if (Vector3.Distance(_rotation, rotation) < float.Epsilon &&
                Vector3.Distance(position, _position) < float.Epsilon)
                return;

            _position = position;
            _rotation = rotation;
            _distanceToOrigin = Vector3.Distance(_position, _origin);
            _zoom = CalculateZoom(_distanceToOrigin);

            if (IsAboveMax || IsBelowMin)
                return;

            if (_loadedQuadKeys.Any())
                BuildIfNecessary(target);
            else
                BuildInitial(target);
        }

        #region LOD calculations

        private RangeTree<float, int> GetLodTree()
        {
            var lodTree = new RangeTree<float, int>();

            for (int lod = LodRange.Minimum; lod <= LodRange.Maximum; ++lod)
            {<commit_msg>demo: fix out of min zoom level issue<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UtyMap.Unity;
using UtyMap.Unity.Data;
using UtyMap.Unity.Infrastructure.Primitives;
using UtyMap.Unity.Utils;
using Object = UnityEngine.Object;

namespace Assets.Scripts.Scene.Tiling
{
    internal sealed class SphereTileController : TileController
    {
        private readonly Vector3 _origin = Vector3.zero;

        private readonly Transform _camera;
        private readonly float _radius;
        private readonly Dictionary<QuadKey, Tile> _loadedQuadKeys = new Dictionary<QuadKey, Tile>();

        private float _zoom;
        private float _distanceToOrigin;
        private Vector3 _position;
        private Vector3 _rotation;

        public SphereTileController(IMapDataStore dataStore, Stylesheet stylesheet, ElevationDataType elevationType,
            Transform pivot, Range<int> lodRange, float radius) :
            base(dataStore, stylesheet, elevationType, pivot, lodRange)
        {
            _radius = radius;

            LodTree = GetLodTree();
            FieldOfView = 60;
            Projection = new SphericalProjection(radius);

            _camera = pivot.Find("Camera").transform;

            HeightRange = new Range<float>(LodTree.Min, LodTree.Max);
            ResetToDefaults();
        }

        /// <inheritdoc />
        protected override float Height { get { return _distanceToOrigin; } }

        /// <inheritdoc />
        public override Range<float> HeightRange { get; protected set; }

        /// <inheritdoc />
        public override float FieldOfView { get; protected set; }

        /// <inheritdoc />
        public override IProjection Projection { get; protected set; }

        /// <inheritdoc />
        public override float Zoom { get { return _zoom; } }

        /// <inheritdoc />
        public override bool IsAboveMax { get { return HeightRange.Maximum < Height; } }

        /// <inheritdoc />
        public override bool IsBelowMin { get { return HeightRange.Minimum > Height; } }

        /// <inheritdoc />
        public override GeoCoordinate Coordinate
        {
            get
            {
                var latitude = _rotation.x;
                var longitude = (-90 - _rotation.y) % 360;

                if (latitude > 90) latitude -= 360;
                if (longitude < -180) longitude += 360;

                return new GeoCoordinate(latitude, longitude);
            }
        }

        /// <inheritdoc />
        public override void Dispose()
        {
            ResetToDefaults();

            foreach (var quadkey in _loadedQuadKeys.Keys.ToArray())
                SafeDestroy(quadkey);

            Resources.UnloadUnusedAssets();
        }

        /// <inheritdoc />
        public override void Update(Transform target)
        {
            var position = _camera.localPosition;
            var rotation = Pivot.rotation.eulerAngles;

            if (Vector3.Distance(_rotation, rotation) < float.Epsilon &&
                Vector3.Distance(position, _position) < float.Epsilon)
                return;

            _position = position;
            _rotation = rotation;
            _distanceToOrigin = Vector3.Distance(_position, _origin);
            
            if (IsAboveMax || IsBelowMin)
                return;

            _zoom = CalculateZoom(_distanceToOrigin);

            if (_loadedQuadKeys.Any())
                BuildIfNecessary(target);
            else
                BuildInitial(target);
        }

        #region LOD calculations

        private RangeTree<float, int> GetLodTree()
        {
            var lodTree = new RangeTree<float, int>();

            for (int lod = LodRange.Minimum; lod <= LodRange.Maximum; ++lod)
            {
{'fraction_non_alphanumeric': 0.08844075392118096, 'fraction_numerical': 0.006590220113351786, 'mean_word_length': 1.9218328840970351, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6719487', 'n_tokens_mistral': 2059, 'n_tokens_neox': 1876, 'n_words': 505}