/*****************************************************************/ // Methods /*****************************************************************/ #region Methods #region CreateGrid /// <summary> /// Creates a rectangular grid of hexagons. /// </summary> /// <param name="width"></param> /// <param name="height"></param> private void CreateGrid(int width, int height) { if (width < 1 || height < 1) { throw new ArgumentException("The given width and height can not be less than 1!"); } this.Width = width; this.Height = height; // Fill grid with cells. for (int q = 0; q < width; q++) // Columns { for (int r = 0; r < height; r++) // Rows { // Get coordinates. Point offsetCoords = new Point(q, r); Point3I cubeCoords = this.GetOffsetToCube(offsetCoords); // Create new cell. HexagonCell oCell = new HexagonCell(cubeCoords, offsetCoords); // Add cell to data structure. this.Cells.Add(oCell); this.dictCellCube.Add(cubeCoords, oCell); this.dictCellOffset.Add(offsetCoords, oCell); } } }
/// <summary> /// Returns axial coordinates for the given cube coordinates. /// </summary> /// <param name="cubeCoords"></param> /// <returns></returns> public Point GetCubeToAxial(Point3I cubeCoords) { var q = cubeCoords.X; // q -> column -> x var r = cubeCoords.Z; // r -> row -> z return(new Point(q, r)); }
/// <summary> /// Returns a list of all neighbors of the given vertex. /// </summary> /// <param name="cubeCoords"></param> /// <param name="allowImpassable">If true, also returns vertices marked as impassable. </param> /// <returns></returns> public IEnumerable <HexagonCell> GetNeighbors(Point3I cubeCoords, bool allowImpassable) { // List of all neighbors to return. List <HexagonCell> neighbors = new List <HexagonCell>(); // Add neighbors. foreach (Point3I dir in Directions) { Point3I cubeCoordsAt = new Point3I( cubeCoords.X + dir.X, cubeCoords.Y + dir.Y, cubeCoords.Z + dir.Z ); HexagonCell neighbor = this.GetCell(cubeCoordsAt); if (neighbor == null || (!allowImpassable && neighbor.impassable)) { continue; } neighbors.Add(neighbor); } return(neighbors); }
/// <summary> /// Returns a cell at the given cube coordinates or null, if no cell could /// be found at the given coordinates. /// </summary> /// <param name="cubeCoords">Cube coordinates of the cell to get. </param> /// <returns></returns> public HexagonCell GetCell(Point3I cubeCoords) { HexagonCell oCell = null; this.dictCellCube.TryGetValue(cubeCoords, out oCell); return(oCell); }
/// <summary> /// Returns all the points along a line, using linear interpolation. /// </summary> /// <param name="coordsA"></param> /// <param name="coordsB"></param> /// <returns></returns> public IEnumerable <HexagonCell> GetLine(Point3I coordsA, Point3I coordsB) { HexagonCell vertexA = this.GetCell(coordsA); HexagonCell vertexB = this.GetCell(coordsB); return(this.GetLine(vertexA, vertexB)); }
/// <summary> /// Returns the points of a hexagon at the given cartesian coordinates. /// </summary> /// <param name="cartesianCoords">Cartesian coordinates of the hex to get. </param> /// <returns></returns> public IEnumerable <PointF> GetCellPoly(PointF cartesianCoords) { // Convert cartesian to cube coordinates. Point3I pntCube = this.GetCartesianToCube(cartesianCoords); // Get polygon. return(this.GetCellPoly(new Point3I(pntCube.X, pntCube.Y, pntCube.Z))); }
/// <summary> /// Returns interpolated cube coordinates, based on the given cube coordiantes and interpolation value. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="t"></param> /// <returns></returns> private Point3F GetLerpCube(Point3I a, Point3I b, float t) { return(new Point3F( this.GetLerp(a.X, b.X, t), this.GetLerp(a.Y, b.Y, t), this.GetLerp(a.Z, b.Z, t) )); }
/// <summary> /// Returns cartesian coordinates for the given cube coordinates. /// </summary> /// <param name="cubeCoords">Cube coordinates. </param> /// <returns></returns> public PointF GetCubeToCartesian(Point3I cubeCoords) { Point offsetCoords = this.GetCubeToOffset(cubeCoords); if (this.PointyTop) { int odd = offsetCoords.Y & 1; float x = this.SizeHex.Width; float y = this.SizeHex.Height * 0.75F; float offset = 0; if (odd == 1) { if (this.Odd) { offset = this.SizeHexHalf.Width; } else { offset = -this.SizeHexHalf.Width; } } return(new PointF( offsetCoords.X * x + offset, offsetCoords.Y * y )); } else // Flat topped. { int odd = offsetCoords.X & 1; float x = this.SizeHex.Width * 0.75F; float y = this.SizeHex.Height; float offset = 0; if (odd == 1) { if (this.Odd) { offset = this.SizeHexHalf.Height; } else { offset = -this.SizeHexHalf.Height; } } return(new PointF( offsetCoords.X * x, offsetCoords.Y * y + offset )); } }
/// <summary> /// Converts from the given cube coordinates to offset coordinates, /// based on this grid's type. /// </summary> /// <param name="cubeCoords">Cube coordinates, in the grid's type. </param> /// <returns></returns> public Point GetCubeToOffset(Point3I cubeCoords) { if (this.PointyTop) // Rows { return(this.GetCubeToOffsetRow(cubeCoords)); } else // Columns { return(this.GetCubeToOffsetColumn(cubeCoords)); } }
/// <summary> /// Returns the points of a hexagon at the given cube coordinates. /// </summary> /// <param name="cubeCoords">Cube coordinates of the hex to get. </param> /// <returns></returns> public IEnumerable <PointF> GetCellPoly(Point3I cubeCoords) { // Convert to cartesian coordinates. PointF cartesianCoords = this.GetCubeToCartesian(cubeCoords); // Get new hexagon at origin. IEnumerable <PointF> polyHex = HexagonGrid.GetHexPoly(this.SizeHexSide, this.PointyTop); // Move to cartesian position. polyHex = HexagonGrid.OffsetPoly(polyHex, cartesianCoords); return(polyHex); }
/// <summary> /// Converts from cube coordinates to offset row coordinates. /// Use with pointy-topped hexes. /// </summary> /// <param name="cubeCoords"></param> /// <returns></returns> private Point GetCubeToOffsetRow(Point3I cubeCoords) { int col = 0; int row = cubeCoords.Z; if (this.Odd) { col = cubeCoords.X + (cubeCoords.Z - (cubeCoords.Z & 1)) / 2; } else { col = cubeCoords.X + (cubeCoords.Z + (cubeCoords.Z & 1)) / 2; } return(new Point(col, row)); }
/// <summary> /// Converts from cube coordinates to offset column coordinates. /// Use with flat-topped hexes. /// </summary> /// <param name="cubeCoords"></param> /// <returns></returns> private Point GetCubeToOffsetColumn(Point3I cubeCoords) { // Column coordinate. int q = cubeCoords.X; // Row coordinate. int r = 0; if (this.Odd) { r = cubeCoords.Z + (cubeCoords.X - (cubeCoords.X & 1)) / 2; } else { r = cubeCoords.Z + (cubeCoords.X + (cubeCoords.X & 1)) / 2; } return(new Point(q, r)); }
/// <summary> /// Creates a circular (hexagonal) grid of hexagons. /// </summary> /// <param name="radius"></param> private void CreateGrid(int radius) { this.Width = radius * 2; this.Height = radius * 2; for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { int z = 0; if (x == 0) { z = -y; } else if (y == 0) { z = -x; } else { z = -x - y; } if (z > radius || z < -radius) // radius-constraint violated. { continue; } // Get coordinates. Point3I cubeCoords = new Point3I(x, y, z); Point offsetCoords = this.GetCubeToOffset(cubeCoords); // Create new cell. HexagonCell oCell = new HexagonCell(cubeCoords, offsetCoords); // Add cell to data structure. this.Cells.Add(oCell); this.dictCellCube.Add(cubeCoords, oCell); this.dictCellOffset.Add(offsetCoords, oCell); } } }
/// <summary> /// Returns all the points along a line, using linear interpolation. /// </summary> /// <param name="vertexA"></param> /// <param name="vertexB"></param> /// <returns></returns> public IEnumerable <HexagonCell> GetLine(HexagonCell vertexA, HexagonCell vertexB) { float n = this.GetDistance(vertexA, vertexB); List <HexagonCell> results = new List <HexagonCell>(); for (int i = 0; i <= n; i++) { float t = 1.0F / n * i; Point3F cubeLerped = this.GetLerpCube(vertexA.Location, vertexB.Location, t); Point3I cubeRounded = this.GetCubeRounded(cubeLerped); HexagonCell oCell = this.GetCell(cubeRounded); if (oCell != null) { results.Add(oCell); } } return(results); }
/// <summary> /// Returns a range of cells around the given cell, with "n" distance. /// </summary> /// <param name="cubeCoords"></param> /// <param name="n"></param> /// <returns></returns> public IEnumerable <HexagonCell> GetRange(Point3I cubeCoords, int n) { List <HexagonCell> result = new List <HexagonCell>(); for (int x = -n; x <= n; x++) { for (int y = -n; y <= n; y++) { int z = 0; if (x == 0) { z = -y; } else if (y == 0) { z = -x; } else { z = -x - y; } if (z > n || z < -n) // n-constraint violated. { continue; } // Get cell at coordinates. Point3I pntCell = new Point3I(x + cubeCoords.X, y + cubeCoords.Y, z + cubeCoords.Z); HexagonCell oCell = this.GetCell(pntCell); if (oCell != null) { result.Add(oCell); // Add cell to result list. } } } return(result); }
/// <summary> /// Returns a list of all neighbors of the given vertex that are not marked as impassable. /// </summary> /// <param name="cubeCoords"></param> /// <returns></returns> public IEnumerable <HexagonCell> GetNeighbors(Point3I cubeCoords) { return(this.GetNeighbors(cubeCoords, false)); }
public HexagonCell(Point3I cubeCoords, Point LocationOffset) : this(cubeCoords.X, cubeCoords.Y, cubeCoords.Z, LocationOffset) { }
public HexagonCell(Point3I cubeCoords, int cost, bool impassable, Point LocationOffset) : this(cubeCoords.X, cubeCoords.Y, cubeCoords.Z, LocationOffset) { }
/// <summary> /// Returns true, if the given cube coordinates are out of bounds. /// </summary> /// <param name="cubeCoords"></param> /// <returns></returns> public bool IsOutOfBounds(Point3I cubeCoords) { return(this.IsOutOfBounds(cubeCoords.X, cubeCoords.Y, cubeCoords.Z)); }