| | | 1 | | using System.Collections; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Linq; |
| | | 4 | | using UnityEngine; |
| | | 5 | | |
| | | 6 | | // 2D interpolator data point. |
| | | 7 | | public class Interpolator2DDataPoint { |
| | | 8 | | // 2D coordinates. |
| | | 9 | | public Vector2 Coordinates { get; } |
| | | 10 | | |
| | | 11 | | // Arbitrary data consisting of floats. |
| | | 12 | | public List<float> Data { get; } |
| | | 13 | | |
| | | 14 | | public Interpolator2DDataPoint() {} |
| | | 15 | | public Interpolator2DDataPoint(in Vector2 coordinates, in List<float> data) { |
| | | 16 | | Coordinates = coordinates; |
| | | 17 | | Data = data; |
| | | 18 | | } |
| | | 19 | | |
| | | 20 | | // Validate and parse the data from strings to floats. |
| | | 21 | | public static (bool, List<float>) ValidateAndParseData(in string[] values) { |
| | | 22 | | List<float> parsedValues = new List<float>(); |
| | | 23 | | for (int i = 0; i < values.Length; ++i) { |
| | | 24 | | if (!float.TryParse(values[i], out float parsedValue)) { |
| | | 25 | | return (false, new List<float>()); |
| | | 26 | | } |
| | | 27 | | parsedValues.Add(parsedValue); |
| | | 28 | | } |
| | | 29 | | return (true, parsedValues); |
| | | 30 | | } |
| | | 31 | | } |
| | | 32 | | |
| | | 33 | | // The 2D interpolator class interpolates values on a 2D grid. |
| | | 34 | | // The first two columns specify the coordinates of each data point that are used for interpolating |
| | | 35 | | // the remaining data values. |
| | | 36 | | public abstract class IInterpolator2D { |
| | | 37 | | // 2D interpolator data points. |
| | | 38 | | protected readonly List<Interpolator2DDataPoint> _data = new List<Interpolator2DDataPoint>(); |
| | | 39 | | |
| | | 40 | | public IInterpolator2D(in string[] csvLines) { |
| | | 41 | | foreach (string line in csvLines) { |
| | | 42 | | string[] values = line.Split(','); |
| | | 43 | | (bool success, List<float> parsedValues) = |
| | | 44 | | Interpolator2DDataPoint.ValidateAndParseData(values); |
| | | 45 | | if (success && parsedValues.Count >= 2) { |
| | | 46 | | _data.Add(new Interpolator2DDataPoint(new Vector2(parsedValues[0], parsedValues[1]), |
| | | 47 | | parsedValues.Skip(2).ToList())); |
| | | 48 | | } |
| | | 49 | | } |
| | | 50 | | } |
| | | 51 | | public IInterpolator2D(List<Interpolator2DDataPoint> data) { |
| | | 52 | | _data = data; |
| | | 53 | | } |
| | | 54 | | |
| | | 55 | | // Interpolate the value. |
| | | 56 | | public abstract Interpolator2DDataPoint Interpolate(float x, float y); |
| | | 57 | | public Interpolator2DDataPoint Interpolate(in Vector2 coordinates) { |
| | | 58 | | return Interpolate(coordinates.x, coordinates.y); |
| | | 59 | | } |
| | | 60 | | } |
| | | 61 | | |
| | | 62 | | // The 2D nearest neighbor interpolator class interpolates values on a 2D grid using nearest |
| | | 63 | | // neighbor interpolation. |
| | | 64 | | public class NearestNeighborInterpolator2D : IInterpolator2D { |
| | | 65 | | // K-D tree for nearest neighbor interpolation. |
| | | 66 | | private KDTree<Interpolator2DDataPoint> _tree; |
| | | 67 | | |
| | 0 | 68 | | public NearestNeighborInterpolator2D(in string[] csvLines) : base(csvLines) { |
| | 0 | 69 | | _tree = new KDTree<Interpolator2DDataPoint>( |
| | 0 | 70 | | _data, (Interpolator2DDataPoint point) => point.Coordinates); |
| | 0 | 71 | | } |
| | 0 | 72 | | public NearestNeighborInterpolator2D(List<Interpolator2DDataPoint> data) : base(data) { |
| | 0 | 73 | | _tree = new KDTree<Interpolator2DDataPoint>( |
| | 0 | 74 | | _data, (Interpolator2DDataPoint point) => point.Coordinates); |
| | 0 | 75 | | } |
| | | 76 | | |
| | | 77 | | // Interpolate the value using nearest neighbor interpolation. |
| | 0 | 78 | | public override Interpolator2DDataPoint Interpolate(float x, float y) { |
| | 0 | 79 | | Interpolator2DDataPoint closestPoint = _tree.NearestNeighbor(new Vector2(x, y)); |
| | 0 | 80 | | if (closestPoint == null) { |
| | 0 | 81 | | Debug.LogError("No data points available for interpolation."); |
| | 0 | 82 | | return new Interpolator2DDataPoint(new Vector2(x, y), new List<float>()); |
| | | 83 | | } |
| | 0 | 84 | | return closestPoint; |
| | 0 | 85 | | } |
| | | 86 | | } |