using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using System.Linq;
using TMPro;

public class CanvasKdTree : MonoBehaviour
{
	[SerializeField] private Material circleMaterial;
	[SerializeField] private Transform quadPointPrefab;
	[SerializeField] private Transform circlePointPrefab;
	
	[SerializeField] private bool startWithStart;
	
	[SerializeField] private TextAsset dataFile;
	
	[SerializeField] private Color colorClass1;
	[SerializeField] private Color colorClass2;
	[SerializeField] private Color unKnownColor;
	
	[SerializeField] private List<Vector2> parsedPointsType1 = new List<Vector2>{};
	[SerializeField] private List<Vector2> parsedPointsType2 = new List<Vector2>{};
	
	[SerializeField] private List<Transform> pointsType1 = new List<Transform>();
	[SerializeField] private List<Transform> pointsType2 = new List<Transform>();
	
	[SerializeField] private bool useRangeForScheme;
	[SerializeField] private int rangeCreatorPointMinX;
	[SerializeField] private int rangeCreatorPointMaxX;
	[SerializeField] private int rangeCreatorPointMinY;
	[SerializeField] private int rangeCreatorPointMaxY;
	
	[SerializeField] [Range(000, 500)] private int coefficientMultiplier;
	
	[SerializeField] private bool useRandomUnKnownPoint;
	[SerializeField] private Vector2 unKnownPointPosition;
	[SerializeField] private Transform unKnownPointTransform;

	private void OnDrawGizmos()
	{

	}
	
	private void Start()
	{
		if (!startWithStart)
		{
			return;
		}
		
		ParseData();
		MultiplyValues();
		CreatePoints();
		CalculatePointRanges();
		CreateUnKnownPoint();
		//DrawScheme();
	}

	private void ParseData()
	{
		string[] lines = dataFile.text.Split('\n');
		
		string[] xCoords = lines[1].Split(',');
		List<float> xValues = xCoords.Skip(1).Select(x => float.Parse(x, CultureInfo.InvariantCulture)).ToList();
		
		string[] yCoords = lines[2].Split(',');
		List<float> yValues = yCoords.Skip(1).Select(y => float.Parse(y, CultureInfo.InvariantCulture)).ToList();
		
		string[] pointTypes = lines[3].Split(',');
		List<int> typeValues = pointTypes.Skip(1).Select(pointType => int.Parse(pointType, NumberStyles.Float, CultureInfo.InvariantCulture)).ToList();
		
		for (int i = 0; i < xValues.Count; i++)
		{
			Vector2 point = new Vector2(xValues[i], yValues[i]);
			int pointType = typeValues[i];

			switch (pointType)
			{
				case 0:
					parsedPointsType1.Add(point);
					break;
				case 1:
					parsedPointsType2.Add(point);
					break;
				case 2:

					if ((i % 2) == 0) {
						parsedPointsType1.Add(point);
					} else {
						parsedPointsType2.Add(point);
					}

					break;
				default:
					Debug.LogError("Unsupported point type: " + pointType);
					break;
			}
		}
	}
	
	private void MultiplyValues()
	{
		List<List<Vector2>> all = new List<List<Vector2>>() {parsedPointsType1, parsedPointsType2};
		
		for (int i = 0; i < all.Count; i++)
		{
			for (int j = 0; j < all[i].Count; j++)
			{
				Vector2 originalValue = all[i][j];
				Vector2 multipliedValue = originalValue * coefficientMultiplier;
				all[i][j] = multipliedValue;
			}
		}
	}

	private void CreatePoints()
	{
		pointsType1 = PointCreator(parsedPointsType1, colorClass1).ToList();
		pointsType2 = PointCreator(parsedPointsType2, colorClass2).ToList();
	}
	
	private void CalculatePointRanges()
	{
		if (!useRangeForScheme)
		{
			return;
		}

		if (parsedPointsType1.Count > 0 && parsedPointsType2.Count > 0)
		{
			float minX = float.MaxValue;
			float maxX = float.MinValue;
			float minY = float.MaxValue;
			float maxY = float.MinValue;

			foreach (Vector2 point in parsedPointsType1)
			{
				minX = Mathf.Min(minX, point.x);
				maxX = Mathf.Max(maxX, point.x);
				minY = Mathf.Min(minY, point.y);
				maxY = Mathf.Max(maxY, point.y);
			}

			foreach (Vector2 point in parsedPointsType2)
			{
				minX = Mathf.Min(minX, point.x);
				maxX = Mathf.Max(maxX, point.x);
				minY = Mathf.Min(minY, point.y);
				maxY = Mathf.Max(maxY, point.y);
			}

			rangeCreatorPointMinX = Mathf.FloorToInt(minX);
			rangeCreatorPointMaxX = Mathf.CeilToInt(maxX);
			rangeCreatorPointMinY = Mathf.FloorToInt(minY);
			rangeCreatorPointMaxY = Mathf.CeilToInt(maxY);
		}
		else
		{
			Debug.LogError("There are no points for calculating boundaries");
		}
	}

	private void CreateUnKnownPoint()
	{
		if (useRandomUnKnownPoint)
		{
			unKnownPointPosition = new Vector2(Random.Range(rangeCreatorPointMinX, rangeCreatorPointMaxX), Random.Range(rangeCreatorPointMinY, rangeCreatorPointMaxY));
			unKnownPointTransform = PointCreator(new List<Vector2>(1){unKnownPointPosition}, unKnownColor).First();
		}
		else
		{
			unKnownPointTransform = PointCreator(new List<Vector2>(1){unKnownPointPosition}, unKnownColor).First();
		}
	}


	private Transform[] PointCreator(List<Vector2> points, Color typeColor)
	{
		Transform[] transforms = new Transform[points.Count];
		for (int i = 0; i < points.Count; i++)
		{
			Transform pointTr = Instantiate(circlePointPrefab, transform);
			pointTr.localPosition = new Vector3(points[i].x, points[i].y);
			transforms[i] = pointTr;
			
			pointTr.GetComponentInChildren<TextMeshProUGUI>().color = typeColor;
			Vector2 pointPos = pointTr.GetComponent<RectTransform>().anchoredPosition;
			pointTr.name = "Pont. Class1. " + " X: " + FormatNumber((int)pointPos.x, 3) + " Y: " + FormatNumber((int)pointPos.y, 3);
		}
		return transforms;
	}
	
	private static string FormatNumber(int number, int digits)
	{
		string format = "D" + digits.ToString();
		return number.ToString(format);
	}
}

У меня есть вот такой код на C# для unity. Он уже правильно и корректно строит координаты. Напиши мне дополнительно методы, которые я вставлю себе в скрипт. Этот скрипт будет строить KD мерное дерево.