Class GridUtil
Static utility class providing grid algorithms for all three Scylla grid topologies: square, hexagonal, and triangular. Covers distance computation, line rasterization, area queries, coordinate system conversions, geometric transformations, and topology-agnostic pathfinding primitives.
Inherited Members
Namespace: Scylla.Core.Structures
Assembly: ScyllaCore.dll
Syntax
public static class GridUtil
Remarks
All methods in this class are stateless, allocation-free (where feasible), and designed for use in hot paths. Caller-supplied span buffers are used throughout to avoid heap allocations; size each buffer according to the documented formula or the algorithm's worst-case output count.
Square grid methods operate on SquareCoord and
are organised in the SQUARE GRID ALGORITHMS region. They include
Bresenham's line, supercover line, and multi-metric distance via
SquareDistanceMetric.
Hex grid methods operate on HexCoord (axial
coordinates) and are organised in the HEX GRID ALGORITHMS and
HEX COORDINATE CONVERSIONS regions. They include line drawing, range/ring/
spiral enumeration, 60-degree rotation, and bidirectional conversions between
axial and offset (odd-r, even-r, odd-q, even-q) as well as doubled-width and
doubled-height representations.
Triangle grid methods operate on TriCoord and
are organised in the TRIANGLE GRID ALGORITHMS region. Currently only
distance is provided; neighbor enumeration is available directly on
GetEdgeNeighbors(TriCoord, Span<TriCoord>).
Generic algorithms in the GENERIC ALGORITHMS region
operate over any coordinate type that satisfies the
NeighborWriter<TCoord> contract, allowing a single implementation
to be used across all topologies.
Methods
AxialToDoubledHeight(HexCoord, out int, out int)
Converts an axial HexCoord to doubled-height coordinates.
Declaration
public static void AxialToDoubledHeight(HexCoord coord, out int col, out int row)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to convert. |
| int | col | When this method returns, contains the doubled-height column: |
| int | row | When this method returns, contains the doubled-height row:
|
Remarks
This is the inverse of DoubledHeightToAxial(int, int). The output pair always
satisfies (row - col) % 2 == 0.
See Also
AxialToDoubledWidth(HexCoord, out int, out int)
Converts an axial HexCoord to doubled-width coordinates.
Declaration
public static void AxialToDoubledWidth(HexCoord coord, out int col, out int row)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to convert. |
| int | col | When this method returns, contains the doubled-width column:
|
| int | row | When this method returns, contains the doubled-width row: |
Remarks
This is the inverse of DoubledWidthToAxial(int, int). The output pair always
satisfies (col - row) % 2 == 0.
See Also
AxialToEvenQ(HexCoord, out int, out int)
Converts an axial HexCoord to offset coordinates using the even-q layout (flat-top orientation, even columns shifted down).
Declaration
public static void AxialToEvenQ(HexCoord coord, out int col, out int row)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to convert. |
| int | col | When this method returns, contains the offset column index: |
| int | row | When this method returns, contains the offset row index:
|
Remarks
This is the inverse of EvenQToAxial(int, int).
See Also
AxialToEvenR(HexCoord, out int, out int)
Converts an axial HexCoord to offset coordinates using the even-r layout (pointy-top orientation, even rows shifted right).
Declaration
public static void AxialToEvenR(HexCoord coord, out int col, out int row)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to convert. |
| int | col | When this method returns, contains the offset column index:
|
| int | row | When this method returns, contains the offset row index: |
Remarks
This is the inverse of EvenRToAxial(int, int).
See Also
AxialToOddQ(HexCoord, out int, out int)
Converts an axial HexCoord to offset coordinates using the odd-q layout (flat-top orientation, odd columns shifted down).
Declaration
public static void AxialToOddQ(HexCoord coord, out int col, out int row)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to convert. |
| int | col | When this method returns, contains the offset column index: |
| int | row | When this method returns, contains the offset row index:
|
Remarks
This is the inverse of OddQToAxial(int, int).
See Also
AxialToOddR(HexCoord, out int, out int)
Converts an axial HexCoord to offset coordinates using the odd-r layout (pointy-top orientation, odd rows shifted right).
Declaration
public static void AxialToOddR(HexCoord coord, out int col, out int row)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The axial hex coordinate to convert. |
| int | col | When this method returns, contains the offset column index:
|
| int | row | When this method returns, contains the offset row index: |
Remarks
This is the inverse of OddRToAxial(int, int). Use it to convert a computed HexCoord back to a 2D array index for odd-r storage layouts.
See Also
ComputeFieldOfView(HexCoord, int, Func<HexCoord, bool>, Span<HexCoord>)
Writes every hex within radius of center that is visible
from it (per IsVisible(HexCoord, HexCoord, Func<HexCoord, bool>)) into visible.
Declaration
public static int ComputeFieldOfView(HexCoord center, int radius, Func<HexCoord, bool> isBlocked, Span<HexCoord> visible)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The viewpoint at the center of the field of view. |
| int | radius | The maximum sight distance. Must be at least 0. |
| Func<HexCoord, bool> | isBlocked | A predicate returning |
| Span<HexCoord> | visible | A span to receive the visible hexes, including the center. Writing stops when full. |
Returns
| Type | Description |
|---|---|
| int | The number of visible hexes written into |
Remarks
Casts a line from center to every hex in range and keeps those whose line is
unobstructed. A blocked hex that is itself reachable by a clear line (for example a wall facing the
viewer) is reported as visible.
This naive ray-cast tests every hex in range with an independent line walk, so the cost grows on
the order of radius^3. It is intended for modest sight radii; for large radii or per-frame
use, prefer a dedicated shadow-casting field-of-view.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
| ArgumentNullException | Thrown when |
See Also
CoordToSpiralIndex(HexCoord, HexCoord)
Converts a hex coordinate to its spiral index relative to center
(0 = center, expanding ring by ring). Inverse of SpiralIndexToCoord(HexCoord, int).
Declaration
public static int CoordToSpiralIndex(HexCoord center, HexCoord coord)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center the spiral expands around. |
| HexCoord | coord | The coordinate to locate. |
Returns
| Type | Description |
|---|---|
| int | The spiral index of |
See Also
Distance(HexCoord, HexCoord)
Computes the hex distance between two axial coordinates - the minimum number of
single-step moves required to travel from a to b.
Declaration
public static int Distance(HexCoord a, HexCoord b)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | a | The first coordinate in axial (q, r) notation. |
| HexCoord | b | The second coordinate in axial (q, r) notation. |
Returns
| Type | Description |
|---|---|
| int | A non-negative integer equal to |
Remarks
This is a convenience wrapper around Distance(HexCoord, HexCoord). The cube-distance formula is the standard metric for hexagonal grids (Amit Patel / Red Blob Games) and represents the shortest path assuming all six directions are equally traversable.
See Also
Distance(SquareCoord, SquareCoord, SquareDistanceMetric)
Computes the distance between two square grid coordinates using the specified metric.
Declaration
public static float Distance(SquareCoord a, SquareCoord b, SquareDistanceMetric metric)
Parameters
| Type | Name | Description |
|---|---|---|
| SquareCoord | a | The first coordinate. |
| SquareCoord | b | The second coordinate. |
| SquareDistanceMetric | metric | The distance metric to apply. Choose based on the movement model: Manhattan for 4-way movement, Chebyshev for uniform 8-way movement, Euclidean for straight-line geometric distance, or Octile for the recommended A* heuristic with realistic 8-way diagonal weighting. |
Returns
| Type | Description |
|---|---|
| float | The distance between |
Remarks
This is a convenience wrapper around DistanceTo(SquareCoord, SquareDistanceMetric). Use the instance method directly when repeatedly computing distances from the same source coordinate to avoid redundant parameter passing.
See Also
Distance(TriCoord, TriCoord)
Computes the step distance between two triangle coordinates using three-axis lane arithmetic.
Declaration
public static int Distance(TriCoord a, TriCoord b)
Parameters
| Type | Name | Description |
|---|---|---|
| TriCoord | a | The first triangle coordinate in lane (a, b, c) notation. |
| TriCoord | b | The second triangle coordinate in lane (a, b, c) notation. |
Returns
| Type | Description |
|---|---|
| int | The triangle distance defined as |
Remarks
This is a convenience wrapper around Distance(TriCoord, TriCoord).
Because upward triangles have a + b + c = 2 and downward triangles have
a + b + c = 1, a distance of 1 always crosses an edge between an upward
and a downward triangle. A distance of 2 always connects two triangles of the
same orientation.
See Also
DoubledHeightDistance(int, int, int, int)
Computes the step distance between two doubled-height (flat-top) offset coordinates directly, without converting to axial.
Declaration
public static int DoubledHeightDistance(int aCol, int aRow, int bCol, int bRow)
Parameters
| Type | Name | Description |
|---|---|---|
| int | aCol | Column of the first coordinate. |
| int | aRow | Row of the first coordinate. |
| int | bCol | Column of the second coordinate. |
| int | bRow | Row of the second coordinate. |
Returns
| Type | Description |
|---|---|
| int | The non-negative hex distance between the two doubled-height coordinates. |
Remarks
Valid doubled-height coordinates satisfy the parity constraint (col + row) is even; passing
coordinates that violate it yields a value that does not correspond to a real hex path. Differences
are taken in long to avoid 32-bit overflow at extreme coordinate values.
See Also
DoubledHeightToAxial(int, int)
Converts doubled-height offset coordinates to an axial HexCoord.
In doubled-height coordinates, vertically-adjacent hexes differ by 2 in
row rather than 1 and row + col is always even. This scheme
is the flat-top analogue of doubled-width, used in some tile-map tools to
represent flat-top hexagons without fractional offsets.
Declaration
public static HexCoord DoubledHeightToAxial(int col, int row)
Parameters
| Type | Name | Description |
|---|---|---|
| int | col | The doubled-height column. |
| int | row | The doubled-height row. Must satisfy |
Returns
| Type | Description |
|---|---|
| HexCoord | The equivalent axial HexCoord where |
Remarks
To convert back, use AxialToDoubledHeight(HexCoord, out int, out int).
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when |
See Also
DoubledWidthDistance(int, int, int, int)
Computes the step distance between two doubled-width (pointy-top) offset coordinates directly, without converting to axial.
Declaration
public static int DoubledWidthDistance(int aCol, int aRow, int bCol, int bRow)
Parameters
| Type | Name | Description |
|---|---|---|
| int | aCol | Column of the first coordinate. |
| int | aRow | Row of the first coordinate. |
| int | bCol | Column of the second coordinate. |
| int | bRow | Row of the second coordinate. |
Returns
| Type | Description |
|---|---|
| int | The non-negative hex distance between the two doubled-width coordinates. |
Remarks
Valid doubled-width coordinates satisfy the parity constraint (col + row) is even; passing
coordinates that violate it yields a value that does not correspond to a real hex path. Differences
are taken in long to avoid 32-bit overflow at extreme coordinate values.
See Also
DoubledWidthToAxial(int, int)
Converts doubled-width offset coordinates to an axial HexCoord.
In doubled-width coordinates, every hex is stored at a (col, row) position where
col + row is always even and horizontally-adjacent hexes differ by 2 in
col rather than 1. This scheme is used in some tile-map tools to represent
pointy-top hexagons without fractional offsets.
Declaration
public static HexCoord DoubledWidthToAxial(int col, int row)
Parameters
| Type | Name | Description |
|---|---|---|
| int | col | The doubled-width column. Must satisfy |
| int | row | The doubled-width row. |
Returns
| Type | Description |
|---|---|
| HexCoord | The equivalent axial HexCoord where
|
Remarks
Doubled-width coordinates are a lossless representation; every valid doubled-width pair maps to a unique hex. To convert back, use AxialToDoubledWidth(HexCoord, out int, out int).
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when |
See Also
DrawLine(HexCoord, HexCoord, Span<HexCoord>)
Rasterizes a line between two hexagonal coordinates using linear interpolation in
fractional cube space followed by cube rounding, writing each traversed hex into
buffer.
Declaration
public static int DrawLine(HexCoord from, HexCoord to, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | from | The starting hex coordinate. Always included as the first element. |
| HexCoord | to | The ending hex coordinate. Always included as the last element when the buffer is large enough. |
| Span<HexCoord> | buffer | A caller-supplied span to receive the rasterized hex coordinates in order from
|
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
A small epsilon nudge (1e-6) is applied to both endpoints before
interpolating to ensure consistent behavior when the geometric line passes
exactly along a hex edge - otherwise the rounding algorithm would
non-deterministically choose between two equally valid hexes. The nudge and the
interpolation are evaluated in double precision so the tie-break remains
effective for large coordinate magnitudes (a single-precision nudge of this size is
lost to rounding once a coordinate exceeds roughly 32).
The algorithm uses Round() (cube rounding,
Charles Fu 1994) at each interpolated point. If from
equals to, exactly one coordinate is written.
See Also
DrawLine(SquareCoord, SquareCoord, Span<SquareCoord>)
Rasterizes a line between two square grid coordinates using Bresenham's line algorithm,
writing each cell center the line passes through into buffer.
Declaration
public static int DrawLine(SquareCoord from, SquareCoord to, Span<SquareCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| SquareCoord | from | The starting coordinate. Always included as the first element in the output. |
| SquareCoord | to | The ending coordinate. Always included as the last element in the output when the buffer is large enough. |
| Span<SquareCoord> | buffer | A caller-supplied span to receive the rasterized cell coordinates, written in
order from |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
Bresenham's algorithm produces a thin line - at most one cell per column or row, depending on the dominant axis. When the geometric line passes exactly through a grid corner, one of the two touching cells is chosen deterministically (the horizontal step is favoured). To include all cells the line passes through - including corner-touching cells - use DrawLineSupercover(SquareCoord, SquareCoord, Span<SquareCoord>) instead.
If from equals to, exactly one coordinate
is written and 1 is returned.
See Also
DrawLineSupercover(SquareCoord, SquareCoord, Span<SquareCoord>)
Rasterizes a supercover line between two square grid coordinates, writing every cell
that the geometric line segment touches - including cells only grazed at a corner -
into buffer.
Declaration
public static int DrawLineSupercover(SquareCoord from, SquareCoord to, Span<SquareCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| SquareCoord | from | The starting coordinate. Always included as the first element in the output. |
| SquareCoord | to | The ending coordinate. Always included as the last element in the output when the buffer is large enough. |
| Span<SquareCoord> | buffer | A caller-supplied span to receive the rasterized cell coordinates.
Size the buffer to at least |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
Unlike DrawLine(SquareCoord, SquareCoord, Span<SquareCoord>) (Bresenham), the supercover variant includes all cells the line geometrically intersects. This is important for collision detection, field-of-view and line-of-sight checks where a thin Bresenham line would erroneously skip corner cells that a projectile or ray would actually pass through.
At exact corner crossings, two intermediate cells are emitted before the diagonal step: first the horizontally-adjacent cell, then the vertically-adjacent cell. The final cell after the diagonal step is then emitted in the normal loop body.
If from equals to, exactly one coordinate
is written and 1 is returned.
See Also
EvenQToAxial(int, int)
Converts an offset coordinate using the even-q layout to an axial HexCoord. In even-q layout, even-numbered columns are shifted down by half a hex height (flat-top orientation).
Declaration
public static HexCoord EvenQToAxial(int col, int row)
Parameters
| Type | Name | Description |
|---|---|---|
| int | col | The offset column index in even-q space. |
| int | row | The offset row index in even-q space. |
Returns
| Type | Description |
|---|---|
| HexCoord | The equivalent axial HexCoord where |
Remarks
Use the even-q layout for flat-top hex maps where even columns are visually shifted downward. To convert back, use AxialToEvenQ(HexCoord, out int, out int).
See Also
EvenRToAxial(int, int)
Converts an offset coordinate using the even-r layout to an axial HexCoord. In even-r layout, even-numbered rows are shifted right by half a hex width (pointy-top orientation).
Declaration
public static HexCoord EvenRToAxial(int col, int row)
Parameters
| Type | Name | Description |
|---|---|---|
| int | col | The offset column index in even-r space. |
| int | row | The offset row index in even-r space. |
Returns
| Type | Description |
|---|---|
| HexCoord | The equivalent axial HexCoord where |
Remarks
Use the even-r layout when even-numbered rows are visually offset to the right. This convention is less common than odd-r; verify your map data's row parity before choosing between OddRToAxial(int, int) and this method. To convert back, use AxialToEvenR(HexCoord, out int, out int).
See Also
FloodFill<TCoord>(TCoord, Func<TCoord, bool>, NeighborWriter<TCoord>, TCoord[], HashSet<TCoord>, Queue<TCoord>)
Performs a topology-agnostic flood fill from a seed coordinate using breadth-first search, expanding into all reachable neighbors that satisfy a passability predicate.
Declaration
public static int FloodFill<TCoord>(TCoord start, Func<TCoord, bool> isPassable, NeighborWriter<TCoord> getNeighbors, TCoord[] neighborBuffer, HashSet<TCoord> result, Queue<TCoord> frontier) where TCoord : struct, IEquatable<TCoord>
Parameters
| Type | Name | Description |
|---|---|---|
| TCoord | start | The seed coordinate at which the fill begins. If |
| Func<TCoord, bool> | isPassable | A predicate invoked for each candidate coordinate. Returns |
| NeighborWriter<TCoord> | getNeighbors | A NeighborWriter<TCoord> delegate that writes the neighbors of a
given coordinate into |
| TCoord[] | neighborBuffer | A pre-allocated array used as scratch space for neighbor storage during each BFS expansion step. Size to hold the maximum possible neighbor count for the target grid topology:
Reuse the same array across multiple calls to avoid repeated allocation. |
| HashSet<TCoord> | result | A HashSet<T> to receive all coordinates in the filled region,
including |
| Queue<TCoord> | frontier | A Queue<T> used internally as the BFS frontier. Cleared at the beginning of this method. Reuse across calls to amortize queue allocation. |
Returns
| Type | Description |
|---|---|
| int | The total number of coordinates added to |
Type Parameters
| Name | Description |
|---|---|
| TCoord | The coordinate type. Must be a value type that implements IEquatable<T>. Works with SquareCoord, HexCoord, TriCoord, or any custom grid coordinate. |
Remarks
Time complexity is O(n) where n is the size of the filled region, assuming O(1) average-case HashSet<T> operations.
This method does not allocate during its execution; all temporary storage is
provided by the caller via neighborBuffer,
result, and frontier. Allocate these
once and reuse them across many flood fill calls for best performance.
The fill is unbounded - it will continue expanding until no more passable
neighbors are found. Ensure isPassable correctly rejects
out-of-bounds coordinates to prevent unbounded growth on sparse or infinite grids.
var grid = new ScyllaSquareGrid<bool>(16, 16, layout);
var neighborBuf = new SquareCoord[4];
var result = new HashSet<SquareCoord>();
var frontier = new Queue<SquareCoord>();
NeighborWriter<SquareCoord> getNeighbors = (c, buf) =>
grid.GetNeighborsNonAlloc(c, buf, SquareAdjacency.VonNeumann);
var count = GridUtil.FloodFill(
new SquareCoord(8, 8),
c => grid.TryGet(c, out var passable) && passable,
getNeighbors,
neighborBuf,
result,
frontier);
See Also
GetHexagonalRegion(int, Span<HexCoord>)
Writes the axial coordinates of a filled hexagonal region of the given radius, centered on
Zero, into buffer.
Declaration
public static int GetHexagonalRegion(int range, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| int | range | The maximum step distance from the center (rings from the center). Must be at least 0. |
| Span<HexCoord> | buffer | A span to receive the coordinates. Writing stops when full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written; a complete region holds |
Remarks
Convenience wrapper over GetRange(HexCoord, int, Span<HexCoord>) centered on the origin (equivalent to
GetRange(HexCoord.Zero, range, buffer)), provided alongside the other shape generators
(GetRectangularRegion(int, HexLayoutMode, HexOrientation, Span<HexCoord>), GetTriangularRegion(int, bool, Span<HexCoord>),
GetRhombusRegion(int, int, Span<HexCoord>)) so map shapes share one vocabulary.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
See Also
GetRange(HexCoord, int, Span<HexCoord>)
Writes all hex coordinates within the specified step distance of a center hex into
buffer, including the center itself.
Declaration
public static int GetRange(HexCoord center, int range, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center coordinate of the range query. |
| int | range | The maximum number of steps away from |
| Span<HexCoord> | buffer | A caller-supplied span to receive the hex coordinates. Size the buffer to at
least |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
Iterates over all (q, r) pairs in the rectangular axial bounding box of the range,
selecting only those that satisfy the cube-coordinate constraint. Order of output
is row-major across the q axis from -range to +range.
To enumerate the same area as a series of concentric rings, use
GetSpiral(HexCoord, int, Span<HexCoord>) instead.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
See Also
GetRangeIntersection(HexCoord, int, HexCoord, int, Span<HexCoord>)
Writes every hex coordinate that lies within rangeA steps of
a and within rangeB steps of b
into buffer (the intersection of two hexagonal ranges).
Declaration
public static int GetRangeIntersection(HexCoord a, int rangeA, HexCoord b, int rangeB, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | a | The center of the first range. |
| int | rangeA | The radius of the first range. Must be at least 0. |
| HexCoord | b | The center of the second range. |
| int | rangeB | The radius of the second range. Must be at least 0. |
| Span<HexCoord> | buffer | A caller-supplied span to receive the intersecting coordinates. Writing stops when full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
A hexagonal range is the set of cube coordinates whose q, r, and s each lie within the radius of the center on that axis. Intersecting two ranges intersects the per-axis intervals (max of the lows, min of the highs) and enumerates the resulting region directly.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when either range is negative. |
See Also
GetReachable(HexCoord, int, Func<HexCoord, bool>, Dictionary<HexCoord, int>, Queue<HexCoord>)
Computes the set of hexes reachable from start in at most
maxSteps steps, treating blocked hexes as impassable, via breadth-first search.
Declaration
public static int GetReachable(HexCoord start, int maxSteps, Func<HexCoord, bool> isBlocked, Dictionary<HexCoord, int> distances, Queue<HexCoord> frontier)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | start | The origin of the search. If blocked, the result is empty. |
| int | maxSteps | The movement budget (maximum step distance). Must be at least 0. |
| Func<HexCoord, bool> | isBlocked | A predicate returning |
| Dictionary<HexCoord, int> | distances | A caller-supplied dictionary that receives each reachable hex mapped to its step distance from
|
| Queue<HexCoord> | frontier | A caller-supplied queue used internally as the BFS frontier. Cleared on entry; reuse across calls. |
Returns
| Type | Description |
|---|---|
| int | The number of reachable hexes, equal to |
Remarks
Unlike the unweighted FloodFill<TCoord>(TCoord, Func<TCoord, bool>, NeighborWriter<TCoord>, TCoord[], HashSet<TCoord>, Queue<TCoord>), this caps expansion at
maxSteps and records per-hex step counts, making it suitable for movement
ranges and reachable-area highlighting. The distances map doubles as the
visited set and as the result.
To avoid first-call rehashing, size distances to the reachable-cell count
(1 + 3 * maxSteps * (maxSteps + 1)) when constructing it.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
| ArgumentNullException | Thrown when |
See Also
GetRectangularRegion(int, HexLayoutMode, HexOrientation, Span<HexCoord>)
Writes the axial coordinates of a centered rectangular hex region into buffer.
The region spans (2 * radius + 1) cells per side and is centered on Zero.
Declaration
public static int GetRectangularRegion(int radius, HexLayoutMode mode, HexOrientation orientation, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| int | radius | The half-extent in columns and rows. Must be at least 0. |
| HexLayoutMode | mode | |
| HexOrientation | orientation | The hex orientation, which selects the offset convention used by Staggered. |
| Span<HexCoord> | buffer | A span to receive the region coordinates. Writing stops when the buffer is full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written to |
Remarks
The mode selects the region's arrangement when the coordinates are drawn
with a hex layout:
-
Slanted emits an axial rectangle (
QandReach range over[-radius, radius]), which renders as a parallelogram. -
Staggered emits an offset rectangle (offset column and row
each range over
[-radius, radius], converted to axial), which renders as an upright rectangle. The offset convention is odd-r for PointyTop and odd-q for FlatTop.
Both modes preserve true hex adjacency, so range, ring, line, and spiral queries computed on the resulting coordinates render correctly under either arrangement. Cells are written in row-major order. Writing stops when the buffer is full.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
GetRhombusRegion(int, int, Span<HexCoord>)
Writes the axial coordinates of a rhombus (parallelogram) region with corner at
Zero spanning [0, width] in Q and [0, height] in R into
buffer.
Declaration
public static int GetRhombusRegion(int width, int height, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| int | width | The Q extent in cells. Must be at least 0. |
| int | height | The R extent in cells. Must be at least 0. |
| Span<HexCoord> | buffer | A span to receive the coordinates. Writing stops when full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written; a complete region holds |
Remarks
This is the corner-anchored parallelogram. GetRectangularRegion(int, HexLayoutMode, HexOrientation, Span<HexCoord>) with Slanted produces the origin-centered equivalent.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
GetRing(HexCoord, int, Span<HexCoord>)
Writes all hex coordinates at exactly radius steps from
center into buffer, tracing the perimeter ring.
Declaration
public static int GetRing(HexCoord center, int radius, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center coordinate of the ring. |
| int | radius | The exact step distance from |
| Span<HexCoord> | buffer | A caller-supplied span to receive the ring coordinates. Size the buffer to at least
|
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
The ring starts at center + Direction(4) * radius (one step west of center, scaled
by radius) and walks clockwise around all six sides using
GetNeighbor(int). Each side contributes exactly
radius hexes. Coordinates are emitted in clockwise order.
To collect all hexes from the center outward through multiple rings, use
GetSpiral(HexCoord, int, Span<HexCoord>).
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
See Also
GetSpiral(HexCoord, int, Span<HexCoord>)
Writes hex coordinates in a spiral order starting from center
and expanding outward through each ring up to and including radius.
Declaration
public static int GetSpiral(HexCoord center, int radius, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center coordinate where the spiral begins. |
| int | radius | The outermost ring radius to include. A value of |
| Span<HexCoord> | buffer | A caller-supplied span to receive the coordinates. Size to at least
|
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written into |
Remarks
Iterates rings 0 through radius in order, appending
each ring's output (via GetRing(HexCoord, int, Span<HexCoord>)) contiguously into the buffer.
The result is useful for algorithms that need to visit nearby hexes first,
such as nearest-neighbor search or progressive revelation effects.
If the buffer fills before all rings are written, the spiral is truncated at
buffer.Length.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
See Also
GetTriangularRegion(int, bool, Span<HexCoord>)
Writes the axial coordinates of a triangular hex region with corner at Zero
and the given side length into buffer.
Declaration
public static int GetTriangularRegion(int size, bool pointingUp, Span<HexCoord> buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| int | size | The triangle side length in cells. Must be at least 0. |
| bool | pointingUp | When true the triangle points up (cells satisfy |
| Span<HexCoord> | buffer | A span to receive the coordinates. Writing stops when full. |
Returns
| Type | Description |
|---|---|
| int | The number of coordinates written; a complete region holds |
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
IsVisible(HexCoord, HexCoord, Func<HexCoord, bool>)
Determines whether to is visible from from by tracing a
hex line between them and checking that no intervening hex is blocked.
Declaration
public static bool IsVisible(HexCoord from, HexCoord to, Func<HexCoord, bool> isBlocked)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | from | The viewer's hex. |
| HexCoord | to | The target hex. |
| Func<HexCoord, bool> | isBlocked | A predicate returning |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
This is the simple ray-cast line-of-sight used by ComputeFieldOfView(HexCoord, int, Func<HexCoord, bool>, Span<HexCoord>). It is easy and symmetric but, like any single-line model, can produce edge cases; callers needing richer visibility should layer their own rules on top.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
See Also
OddQToAxial(int, int)
Converts an offset coordinate using the odd-q layout to an axial HexCoord. In odd-q layout, odd-numbered columns are shifted down by half a hex height (flat-top orientation).
Declaration
public static HexCoord OddQToAxial(int col, int row)
Parameters
| Type | Name | Description |
|---|---|---|
| int | col | The offset column index in odd-q space. |
| int | row | The offset row index in odd-q space. |
Returns
| Type | Description |
|---|---|
| HexCoord | The equivalent axial HexCoord where |
Remarks
Use the odd-q layout for flat-top hex maps where odd columns are visually shifted downward. To convert back, use AxialToOddQ(HexCoord, out int, out int).
See Also
OddRToAxial(int, int)
Converts an offset coordinate using the odd-r layout to an axial HexCoord. In odd-r layout, odd-numbered rows are shifted right by half a hex width (pointy-top orientation).
Declaration
public static HexCoord OddRToAxial(int col, int row)
Parameters
| Type | Name | Description |
|---|---|---|
| int | col | The offset column index in odd-r space. |
| int | row | The offset row index in odd-r space. |
Returns
| Type | Description |
|---|---|
| HexCoord | The equivalent axial HexCoord where |
Remarks
Use the odd-r layout when your map data is stored as a 2D array indexed by (col, row) where odd rows are visually offset to the right. To convert back to offset coordinates, use AxialToOddR(HexCoord, out int, out int).
See Also
RotateCCW(HexCoord, HexCoord)
Rotates a hex coordinate 60 degrees counter-clockwise around an arbitrary pivot center.
Declaration
public static HexCoord RotateCCW(HexCoord coord, HexCoord center)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The coordinate to rotate. |
| HexCoord | center | The pivot center of rotation. Use Zero to rotate around the grid origin. |
Returns
| Type | Description |
|---|---|
| HexCoord | The coordinate that |
Remarks
Implemented by translating coord relative to
center, applying the origin-relative cube rotation
(q, r, s) -> (-s, -q, -r) via RotateCCW(HexCoord),
and then translating back. Six successive counter-clockwise rotations return
the original coordinate.
See Also
RotateCW(HexCoord, HexCoord)
Rotates a hex coordinate 60 degrees clockwise around an arbitrary pivot center.
Declaration
public static HexCoord RotateCW(HexCoord coord, HexCoord center)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | coord | The coordinate to rotate. |
| HexCoord | center | The pivot center of rotation. Use Zero to rotate around the grid origin. |
Returns
| Type | Description |
|---|---|
| HexCoord | The coordinate that |
Remarks
Implemented by translating coord relative to
center, applying the origin-relative cube rotation
(q, r, s) -> (-r, -s, -q) via RotateCW(HexCoord),
and then translating back. Six successive clockwise rotations return the original
coordinate.
See Also
SpiralIndexToCoord(HexCoord, int)
Converts a spiral index (0 = center, expanding ring by ring) to its hex coordinate relative to
center. Inverse of CoordToSpiralIndex(HexCoord, HexCoord).
Declaration
public static HexCoord SpiralIndexToCoord(HexCoord center, int index)
Parameters
| Type | Name | Description |
|---|---|---|
| HexCoord | center | The center the spiral expands around. |
| int | index | The spiral index. Must be at least 0. |
Returns
| Type | Description |
|---|---|
| HexCoord | The coordinate at spiral position |
Remarks
The traversal matches GetSpiral(HexCoord, int, Span<HexCoord>) exactly: each ring starts one step west of the center scaled by the radius and proceeds clockwise around the six sides.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
See Also
SpiralIndexToRadius(int)
Returns the ring radius that contains the cell at the given spiral index.
Declaration
public static int SpiralIndexToRadius(int index)
Parameters
| Type | Name | Description |
|---|---|---|
| int | index | The spiral index. Must be at least 0. |
Returns
| Type | Description |
|---|---|
| int | The radius of the ring containing |
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |
See Also
SpiralRingStart(int)
Returns the spiral index at which ring radius begins, for a spiral that
starts at the center (index 0) and expands ring by ring, matching GetSpiral(HexCoord, int, Span<HexCoord>).
Declaration
public static int SpiralRingStart(int radius)
Parameters
| Type | Name | Description |
|---|---|---|
| int | radius | The ring radius. Must be at least 0. |
Returns
| Type | Description |
|---|---|
| int | The index of the first cell of ring |
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when |