Advertisement
Guest User

Untitled

a guest
Jun 3rd, 2022
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.55 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5.  
  6. namespace Wunderwunsch.HexMapLibrary
  7. {
  8.     /// <summary>
  9.     /// Converts between cartesian coordinates and two different hexagonal-grid-coordinates (called "offset" and "cube")
  10.     /// </summary>
  11.     /// Using the cartesian coordinate system (the "normal" one you use all the time) does not work well with hexagons as you end up with fractional numbers which
  12.     /// make things very non-intuitive and which are also often not suited to calculate on the grid. Therefore it is useful to use other coordinate systems which allow
  13.     /// us to work with integer values and which are better suited to perform grid-based calculations.  
  14.     ///
  15.     /// This library uses two different hexagonal coordinate systems called "offset" and "cube", we mostly use the cube coordinate system as this is a lot easier to work with
  16.     /// and has proper straight axes.  
  17.     ///
  18.     /// For most tasks you can just use the library without worrying too much about the details of the coordinate systems, however if you are interested to dive a bit deeper,
  19.     /// I recommend reading Amit Patel's great introduction to hexagons: https://www.redblobgames.com/grids/hexagons/ .
  20.     /// ![Coordinates & axes of cartesian coordinate system](CartesianCoordinatesCombined.png)  
  21.     ///      
  22.     ///
  23.     /// ![Coordinates & 'axes' of offset coordinate system](OffsetCoordinatesCombined.png)  
  24.     ///
  25.     ///      
  26.     /// ![Coordinates & axes of cube coordinate system](CubeCoordinatesCombined.png)
  27.     public static class HexConverter
  28.     {
  29.         private static float invertedScale = 1; //1 = 1m , 2 = 50cm , 4 = 25cm, 5 = 20cm , 0,5 = 2m , 0,1 = 10m
  30.         private static float scale = 1;
  31.  
  32.         public static void SetScale(float tileSizeInUnits)
  33.         {
  34.             scale = tileSizeInUnits;
  35.             invertedScale = 1 / tileSizeInUnits;
  36.         }
  37.  
  38.         /// <summary>
  39.         /// cached value of square root of 3.
  40.         /// </summary>
  41.         private static float sqrt3 = Mathf.Sqrt(3);
  42.  
  43.         /// <summary>
  44.         /// converts the input cartesian coordinate to its equivalent offset tile coordinate
  45.         /// </summary>
  46.         public static Vector2Int CartesianCoordToOffsetCoord(Vector3 cartesianCoord)
  47.         {
  48.             float x = (cartesianCoord.x / sqrt3)*invertedScale;
  49.             float z = cartesianCoord.z * invertedScale;
  50.             float temp = Mathf.Floor(x + z + 1);
  51.  
  52.             float c = Mathf.Floor((Mathf.Floor(2 * x + 1) + temp) / 3f);
  53.             float r = Mathf.Floor((temp + Mathf.Floor(-x + z + 1)) / 3);
  54.             return new Vector2Int((int)(c - (r + ((int)r & 1)) / 2), (int)r);
  55.         }
  56.  
  57.         /// <summary>
  58.         /// converts the input cartesian coordinate to its equivalent tile coordinate
  59.         /// </summary>
  60.         public static Vector3Int CartesianCoordToTileCoord(Vector3 cartesianCoord)
  61.         {
  62.             float x = (cartesianCoord.x / sqrt3) * invertedScale;
  63.             float z = (cartesianCoord.z) * invertedScale;
  64.             float temp = Mathf.Floor(x + z + 1);
  65.  
  66.             float q = Mathf.Floor((Mathf.Floor(2 * x + 1) + temp) / 3f);
  67.             float r = Mathf.Floor((temp + Mathf.Floor(-x + z + 1)) / 3);
  68.  
  69.             int cX = (int)q - (int)r;
  70.             int cY = (int)r;
  71.             int cZ = -cX - cY;
  72.             return new Vector3Int(cX, cY, cZ);
  73.         }
  74.  
  75.         /// <summary>
  76.         /// convers the input offset tile coordinate to its equivalent cartesian coordinate
  77.         /// </summary>
  78.         public static Vector3 OffsetTileCoordToCartesianCoord(Vector2Int offsetTileCoord)
  79.         {
  80.             float offsetXAdjustment;
  81.             if (offsetTileCoord.y % 2 == 0) offsetXAdjustment = 0;
  82.             else offsetXAdjustment = (0.5f * sqrt3) * scale;
  83.  
  84.             float cartesianX = (offsetTileCoord.x * sqrt3 + offsetXAdjustment)*scale;
  85.             float cartesianZ = (offsetTileCoord.y * 1.5f)*scale;
  86.             return new Vector3(cartesianX, 0, cartesianZ);
  87.         }
  88.  
  89.         /// <summary>
  90.         /// converts the input offset tile coordinate to its equivalent tile coordinate
  91.         /// </summary>
  92.         public static Vector3Int OffsetTileCoordToTileCoord(Vector2Int offsetTileCoord)
  93.         {
  94.             int x = offsetTileCoord.x - (offsetTileCoord.y - (offsetTileCoord.y & 1)) / 2;
  95.             int y = offsetTileCoord.y;
  96.             int z = -x - y;
  97.             return new Vector3Int(x, y, z);
  98.         }
  99.  
  100.         /// <summary>
  101.         /// converts the input tile tile coordinate to its equivalent cartesian coordinate
  102.         /// </summary>
  103.         /// <param name="tileCoord">input tile coordinate</param>
  104.         /// <param name="yCoord">explicitly sets cartesian y-coordinate</param>
  105.         public static Vector3 TileCoordToCartesianCoord(Vector3Int tileCoord, float yCoord = 0)
  106.         {
  107.             float x = (sqrt3 * (tileCoord.x + tileCoord.y / 2f))*scale;
  108.             float z = (3 / 2f * tileCoord.y)*scale;
  109.             float y = yCoord;
  110.             return new Vector3(x, y, z);
  111.         }
  112.  
  113.         /// <summary>
  114.         /// converts the input tile coordinate to its equivalent offset coordinate
  115.         /// </summary>
  116.         public static Vector2Int TileCoordToOffsetTileCoord(Vector3Int tileCoord)
  117.         {
  118.             int x = tileCoord.x + (tileCoord.y - (tileCoord.y & 1)) / 2;
  119.             int y = tileCoord.y;
  120.             return new Vector2Int(x, y);
  121.         }
  122.  
  123.         /// <summary>
  124.         /// returns the midpoint of the edge in cartesian coordinates.
  125.         /// </summary>
  126.         public static Vector3 EdgeCoordToCartesianCoord(Vector3Int edgeCoord, float yCoord = 0)
  127.         {
  128.             Vector3 worldPos = HexConverter.TileCoordToCartesianCoord(edgeCoord);
  129.             worldPos = new Vector3(worldPos.x / 2f, yCoord, worldPos.z / 2f);
  130.             return worldPos;
  131.         }
  132.  
  133.  
  134.         /// <summary>
  135.         /// converts the input cartesian coordinate to the edge coordinate closest to it.
  136.         /// </summary> //TODO: is a bit inefficient and allocates memory, so improve later
  137.         public static Vector3Int CartesianCoordToClosestEdgeCoord(Vector3 cartesianCoord)
  138.         {
  139.             Vector3Int tileCoord = CartesianCoordToTileCoord(cartesianCoord);
  140.             List<Vector3Int> edgeCoords = HexGrid.GetEdges.OfTile(tileCoord);
  141.             Vector3Int closestEdge = new Vector3Int(-1, -1, -1); //invalid default coordinate
  142.             float minDistanceSoFar = float.MaxValue;
  143.             for (int i = 0; i < edgeCoords.Count; i++)
  144.             {
  145.                 Vector3 worldPos = HexConverter.TileCoordToCartesianCoord(edgeCoords[i]);
  146.                 worldPos = new Vector3(worldPos.x / 2f, 1, worldPos.z / 2f);
  147.                 float distance = Vector3.Distance(worldPos, cartesianCoord);
  148.                 if (distance < minDistanceSoFar)
  149.                 {
  150.                     closestEdge = edgeCoords[i];
  151.                     minDistanceSoFar = distance;
  152.                 }
  153.             }
  154.             return closestEdge;
  155.         }
  156.  
  157.         /// <summary>
  158.         /// converts the input cartesian coordinate to the cord coordinate closest to it.
  159.         /// </summary> //TODO: is a bit inefficient and allocates memory, so improve later
  160.         /// <param name="cartesianCoord"></param>
  161.         /// <returns></returns>
  162.         public static Vector3Int CartesianCoordToClosestCornerCoord(Vector3 cartesianCoord)
  163.         {
  164.             Vector3Int tileCoord = CartesianCoordToTileCoord(cartesianCoord);
  165.             List<Vector3Int> cornerCoords = HexGrid.GetCorners.OfTile(tileCoord);
  166.             Vector3Int closestCorner = new Vector3Int(-1, -1, -1); //invalid default coordinate
  167.             float minDistanceSoFar = float.MaxValue;
  168.             for (int i = 0; i < cornerCoords.Count; i++)
  169.             {
  170.                 Vector3 worldPos = HexConverter.TileCoordToCartesianCoord(cornerCoords[i]);
  171.                 worldPos = new Vector3(worldPos.x / 3f, 1, worldPos.z / 3f);
  172.                 float distance = Vector3.Distance(worldPos, cartesianCoord);
  173.                 if (distance < minDistanceSoFar)
  174.                 {
  175.                     closestCorner = cornerCoords[i];
  176.                     minDistanceSoFar = distance;
  177.                 }
  178.             }
  179.             return closestCorner;
  180.         }
  181.  
  182.         /// <summary>
  183.         /// returns the cartesian coordinate of the input corner coordinate.
  184.         /// </summary>
  185.         public static Vector3 CornerCoordToCartesianCoord(Vector3Int cornerCoord, float yCoord = 0)
  186.         {
  187.             Vector3 worldPos = HexConverter.TileCoordToCartesianCoord(cornerCoord);
  188.             worldPos = new Vector3(worldPos.x / 3f, yCoord, worldPos.z / 3f);
  189.             return worldPos;
  190.         }
  191.  
  192.         public static Vector2 TileCoordToNormalizedPosition(Vector3Int tileCoordinate, float minX, float maxX, float minZ, float maxZ)
  193.         {
  194.             Vector3 cartesianCoord = HexConverter.TileCoordToCartesianCoord(tileCoordinate);
  195.             return CartesianCoordToNormalizedPosition(cartesianCoord, minX, maxX, minZ,maxZ);
  196.         }
  197.  
  198.         public static Vector2 EdgeCoordToNormalizedPosition(Vector3Int edgeCoordinate, float minX, float maxX, float minZ, float maxZ)
  199.         {
  200.             Vector3 cartesianCoord = HexConverter.EdgeCoordToCartesianCoord(edgeCoordinate);
  201.             return CartesianCoordToNormalizedPosition(cartesianCoord, minX, maxX, minZ, maxZ);
  202.         }
  203.  
  204.         public static Vector2 CornerCoordToNormalizedPosition(Vector3Int cornerCoordinate, float minX, float maxX, float minZ, float maxZ)
  205.         {
  206.             Vector3 cartesianCoord = HexConverter.CornerCoordToCartesianCoord(cornerCoordinate);
  207.             return CartesianCoordToNormalizedPosition(cartesianCoord, minX, maxX, minZ, maxZ);
  208.         }
  209.  
  210.         public static Vector2 CartesianCoordToNormalizedPosition(Vector3 cartesianCoordinate, float minX, float maxX, float minZ, float maxZ)
  211.         {
  212.             float normalizedX = Mathf.InverseLerp(minX, maxX,cartesianCoordinate.x);
  213.             float normalizedZ = Mathf.InverseLerp(minZ, maxZ, cartesianCoordinate.z);
  214.             return (new Vector2(normalizedX, normalizedZ));
  215.         }
  216.  
  217.  
  218.         // TODO: add Methods which convert Containers
  219.         public static List<Vector3> CornerCoordsToCartesianCoords(List<Vector3Int> inputCoords, float yCoord = 0)
  220.         {
  221.             List<Vector3> output = new List<Vector3>();
  222.             foreach(var c in inputCoords)
  223.             {
  224.                 output.Add(HexConverter.CornerCoordToCartesianCoord(c));
  225.             }
  226.             return output;
  227.         }
  228.  
  229.         public static HashSet<Vector3> CornerCoordsToCartesianCoords(HashSet<Vector3Int> inputCoords, float yCoord = 0)
  230.         {
  231.             HashSet<Vector3> output = new HashSet<Vector3>();
  232.             foreach (var c in inputCoords)
  233.             {
  234.                 output.Add(HexConverter.CornerCoordToCartesianCoord(c,yCoord));
  235.             }
  236.             return output;
  237.         }
  238.  
  239.         public static Generic.Tile<T>[,] TilesToOffsetCoord2DArray<T>(ICollection<Generic.Tile<T>> inputTiles, MapSizeData mapSizeData) where T: new()
  240.         {
  241.             Generic.Tile<T>[,] grid = new Generic.Tile<T>[1+mapSizeData.offsetTileMaxValX - mapSizeData.offsetTileMinValX, 1+mapSizeData.offsetTileMaxValZ - mapSizeData.offsetTileMinValZ];
  242.             foreach(var t in inputTiles)
  243.             {
  244.                 Vector2Int offSetCoord = HexConverter.TileCoordToOffsetTileCoord(t.Position);
  245.                 grid[offSetCoord.x, offSetCoord.y] = t;
  246.             }
  247.             return grid;
  248.         }
  249.     }
  250. }
  251.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement