Class ScyllaGridGraphAdapter<TCoord, TCell>
Adapter that presents an IScyllaGrid<TCoord, TCell> as an IScyllaReadOnlyGraph, enabling standard graph algorithms to operate directly on grid data without building an explicit adjacency structure.
Inherited Members
Namespace: Scylla.Core.Structures
Assembly: ScyllaCore.dll
Syntax
public sealed class ScyllaGridGraphAdapter<TCoord, TCell> : IScyllaReadOnlyGraph, IScyllaGraph, IScyllaCollection where TCoord : struct, IEquatable<TCoord>
Type Parameters
| Name | Description |
|---|---|
| TCoord | The coordinate type of the underlying grid. Must be a value type that implements IEquatable<T> so that coordinate comparisons in neighbor queries are allocation-free. |
| TCell | The type of data stored in each grid cell. Used only by the optional
|
Remarks
This is a lazy, on-demand adapter. No pre-computation of adjacency data is performed at construction time; neighbor relationships and edge weights are computed on the fly from the underlying grid each time a traversal query is issued. This means the adapter always reflects the current state of the grid, but repeated traversals over the same grid will recompute neighbors each time. For scenarios where the grid is static and traversal is performance-critical, consider converting the adapter to a ScyllaCSRGraph using CreateFromGraph(IScyllaReadOnlyGraph), which will freeze the graph topology into a cache-friendly CSR array.
Node IDs are compact integers computed from grid coordinates via the
coordToNodeID delegate. The specific formula depends on the grid type and
is configured automatically by the static factory methods
(FromSquareGrid(ScyllaSquareGrid<TCell>, Func<TCell, bool>, Func<SquareCoord, SquareCoord, float>, SquareAdjacency), FromHexGrid(ScyllaHexGrid<TCell>, Func<TCell, bool>, Func<HexCoord, HexCoord, float>), FromTriGrid(ScyllaTriGrid<TCell>, Func<TCell, bool>, Func<TriCoord, TriCoord, float>)).
Custom coordinate-to-ID mappings can also be supplied via the public constructor.
Walkability filtering is applied lazily: a cell and all of its neighbors are
checked against the optional isWalkable predicate each time
GetNeighborCount(int) or GetNeighborsNonAlloc(int, Span<ScyllaGraphEdge>) is called.
Unwalkable cells contribute zero outgoing edges.
Grid graphs are always undirected (the adapter does not set
Directed). They are weighted only when a
non-null costFunction is provided at construction time.
EdgeCount returns -1 because the total number of walkable
edges is not pre-computed. Callers should use CopyAllEdges(Span<ScyllaGraphEdge>) and
inspect the return value if the actual edge count is needed.
Clear() is not supported and always throws InvalidOperationException.
Adapt a square grid and run Dijkstra on it:
var grid = new ScyllaSquareGrid<bool>(10, 10, true);
// Mark some cells as unwalkable.
grid.TrySet(new SquareCoord(3, 3), false);
var graph = ScyllaGridGraphAdapter<SquareCoord, bool>.FromSquareGrid(
grid,
isWalkable: cell => cell);
var path = ScyllaGraphAlgorithms.Dijkstra(graph, 0, 99);
Constructors
ScyllaGridGraphAdapter(IScyllaGrid<TCoord, TCell>, Func<TCoord, int>, Func<int, TCoord>, Func<TCoord, TCoord[], int>, int, int, Func<TCell, bool>, Func<TCoord, TCoord, float>)
Creates a new grid graph adapter with fully customizable coordinate mapping. For standard grid types, prefer the static factory methods (FromSquareGrid(ScyllaSquareGrid<TCell>, Func<TCell, bool>, Func<SquareCoord, SquareCoord, float>, SquareAdjacency), FromHexGrid(ScyllaHexGrid<TCell>, Func<TCell, bool>, Func<HexCoord, HexCoord, float>), FromTriGrid(ScyllaTriGrid<TCell>, Func<TCell, bool>, Func<TriCoord, TriCoord, float>)) which configure all delegates automatically.
Declaration
public ScyllaGridGraphAdapter(IScyllaGrid<TCoord, TCell> grid, Func<TCoord, int> coordToNodeID, Func<int, TCoord> nodeIDToCoord, Func<TCoord, TCoord[], int> getNeighborCoords, int maxNeighbors, int nodeCount, Func<TCell, bool> isWalkable = null, Func<TCoord, TCoord, float> costFunction = null)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaGrid<TCoord, TCell> | grid | The grid to adapt. Must not be |
| Func<TCoord, int> | coordToNodeID | Function that converts a grid coordinate to a non-negative integer node ID.
Must produce unique IDs in the range |
| Func<int, TCoord> | nodeIDToCoord | Function that converts a node ID back to its grid coordinate. Must be the exact
inverse of |
| Func<TCoord, TCoord[], int> | getNeighborCoords | Function that fills the provided |
| int | maxNeighbors | Maximum number of neighbors a single node can have. Used to size the internal reusable scratch buffer. For square grids: 4 (VonNeumann) or 8 (Moore). For hex grids: 6. For triangle grids: 3. |
| int | nodeCount | Total number of nodes (grid cells) represented by this adapter. |
| Func<TCell, bool> | isWalkable | Optional predicate applied to cell data to determine walkability. When |
| Func<TCoord, TCoord, float> | costFunction | Optional function that returns the traversal cost (edge weight) between two adjacent
coordinates. When |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
Properties
Capabilities
Gets the capability flags for this collection. Reports SupportsContains only. SupportsCopyTo is not reported because edge count is dynamic and not pre-computed.
Declaration
public ScyllaCollectionCapabilities Capabilities { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaCollectionCapabilities |
Count
Gets the number of items in the collection, which equals NodeCount. Satisfies the Count contract where nodes are treated as the primary collection element.
Declaration
public int Count { get; }
Property Value
| Type | Description |
|---|---|
| int |
EdgeCount
Gets the number of edges in the graph.
Always returns -1 because the adapter does not pre-compute the total number
of walkable edges. Use CopyAllEdges(Span<ScyllaGraphEdge>) and inspect its return value if
the actual count is needed.
Declaration
public int EdgeCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
IsEmpty
Gets a value indicating whether the graph contains no nodes.
Returns true when NodeCount is zero (i.e., the grid has zero
area).
Declaration
public bool IsEmpty { get; }
Property Value
| Type | Description |
|---|---|
| bool |
NodeCount
Gets the total number of nodes in the adapted graph.
For a dense grid of width W and height H, this equals
W * H for square and hex grids, or W * H * 2 for triangle grids
(two triangle orientations per grid position).
Declaration
public int NodeCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
Properties
Gets the structural property flags describing this graph.
Grid graphs are always undirected, so Directed
is never set. Weighted is set only when a
non-null costFunction was provided at construction time.
Declaration
public ScyllaGraphProperties Properties { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaGraphProperties |
SyncRoot
Gets the synchronization root for this collection.
Always returns null because this adapter provides no synchronization mechanism.
Declaration
public object SyncRoot { get; }
Property Value
| Type | Description |
|---|---|
| object |
ThreadSafety
Gets the thread-safety classification for this graph. Reported as Unsynchronized. The adapter is not thread-safe because Scylla.Core.Structures.ScyllaGridGraphAdapter<TCoord, TCell>._neighborBuffer is a shared mutable scratch buffer reused across all neighbor queries.
Declaration
public ScyllaCollectionThreadSafety ThreadSafety { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaCollectionThreadSafety |
Methods
Clear()
Not supported. ScyllaGridGraphAdapter<TCoord, TCell> is a read-only view over a grid and cannot be cleared.
Declaration
public void Clear()
Exceptions
| Type | Condition |
|---|---|
| InvalidOperationException | Always thrown. To modify grid contents, operate directly on the underlying IScyllaGrid<TCoord, TCell>. |
ContainsEdge(int, int)
Determines whether a walkable edge connects two adjacent nodes.
Declaration
public bool ContainsEdge(int fromID, int toID)
Parameters
| Type | Name | Description |
|---|---|---|
| int | fromID | ID of the source node. |
| int | toID | ID of the target node. |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
An edge exists between fromID and toID if
and only if all of the following conditions hold:
- Both node IDs resolve to valid grid coordinates.
- If a walkability predicate was provided, both cells pass it (an edge to or from an unwalkable cell does not exist).
-
The target coordinate is reported as a neighbor of the source coordinate
by the
getNeighborCoordsdelegate.
ContainsNode(int)
Determines whether a node with the specified ID corresponds to a valid coordinate within the bounds of the underlying grid.
Declaration
public bool ContainsNode(int nodeID)
Parameters
| Type | Name | Description |
|---|---|---|
| int | nodeID | The integer node ID to check. Must be in range |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
The check is performed by converting nodeID back to a grid
coordinate via _nodeIDToCoord and then calling
Contains(TCoord). Node IDs outside the valid
range [0, NodeCount) immediately return false without invoking the
coordinate conversion delegate.
CoordToNode(TCoord)
Converts a grid coordinate to its node ID. Use this to obtain the source and target IDs to pass to a graph search.
Declaration
public int CoordToNode(TCoord coord)
Parameters
| Type | Name | Description |
|---|---|---|
| TCoord | coord | The grid coordinate to convert. |
Returns
| Type | Description |
|---|---|
| int | The node ID corresponding to |
CopyAllEdges(Span<ScyllaGraphEdge>)
Copies all walkable edge descriptors from the graph into the provided span.
Edges are generated on the fly by iterating all nodes and calling
GetNeighborsNonAlloc(int, Span<ScyllaGraphEdge>) on each. Because the graph is undirected,
only the canonical direction (FromID < ToID) is copied so that each
logical edge appears exactly once in the output.
Copying stops when destination is full.
Declaration
public int CopyAllEdges(Span<ScyllaGraphEdge> destination)
Parameters
| Type | Name | Description |
|---|---|---|
| Span<ScyllaGraphEdge> | destination | Span into which the ScyllaGraphEdge descriptors will be written. |
Returns
| Type | Description |
|---|---|
| int | The number of edges written into |
Remarks
This operation is O(N * maxNeighbors) where N is NodeCount, because neighbor coordinates must be computed for every node. For static grids where bulk edge enumeration is frequent, prefer converting the adapter to a ScyllaCSRGraph via CreateFromGraph(IScyllaReadOnlyGraph).
CopyAllNodes(Span<ScyllaGraphNode>)
Copies all node descriptors (one per grid position) into the provided span.
Nodes are written in ascending node ID order (i.e., row-major order for most grid
types). For each node, the ScyllaGraphNodeFlags are computed via
TryGetNodeFlags(int, out ScyllaGraphNodeFlags).
If destination is smaller than NodeCount,
only as many nodes as fit are copied.
Declaration
public int CopyAllNodes(Span<ScyllaGraphNode> destination)
Parameters
| Type | Name | Description |
|---|---|---|
| Span<ScyllaGraphNode> | destination | Span into which the ScyllaGraphNode descriptors will be written. |
Returns
| Type | Description |
|---|---|
| int | The number of nodes written into |
FromHexGrid(ScyllaHexGrid<TCell>, Func<TCell, bool>, Func<HexCoord, HexCoord, float>)
Creates a ScyllaGridGraphAdapter<TCoord, TCell> that wraps a
ScyllaHexGrid<TCell> using the offset-normalized node ID formula
nodeID = (r - rMin) * width + (q - qMin), where qMin and rMin
are the minimum axial coordinate values of the grid's bounding rectangle.
Declaration
public static ScyllaGridGraphAdapter<HexCoord, TCell> FromHexGrid(ScyllaHexGrid<TCell> grid, Func<TCell, bool> isWalkable = null, Func<HexCoord, HexCoord, float> costFunction = null)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaHexGrid<TCell> | grid | The hex grid to adapt. Must not be |
| Func<TCell, bool> | isWalkable | Optional predicate applied to cell data to determine walkability. When |
| Func<HexCoord, HexCoord, float> | costFunction | Optional function that returns the traversal cost between two adjacent
HexCoord coordinates. When |
Returns
| Type | Description |
|---|---|
| ScyllaGridGraphAdapter<HexCoord, TCell> | A new ScyllaGridGraphAdapter<TCoord, TCell> parameterized as
|
Remarks
Hex grids use axial (q, r) coordinates. The node ID formula normalizes these to
zero-based indices so that node IDs are compact integers in the range
[0, NodeCount). The inverse mapping is:
q = nodeID % width + qMin, r = nodeID / width + rMin.
Each hex cell has up to 6 neighbors, so the internal scratch buffer is sized to 6.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
FromSparseHexGrid(ScyllaSparseHexGrid<TCell>, Func<TCell, bool>, Func<HexCoord, HexCoord, float>)
Creates a ScyllaGridGraphAdapter<TCoord, TCell> that wraps a bounded
ScyllaSparseHexGrid<TCell> using the same offset-normalized node ID formula as
FromHexGrid(ScyllaHexGrid<TCell>, Func<TCell, bool>, Func<HexCoord, HexCoord, float>): nodeID = (r - rMin) * width + (q - qMin).
Declaration
public static ScyllaGridGraphAdapter<HexCoord, TCell> FromSparseHexGrid(ScyllaSparseHexGrid<TCell> grid, Func<TCell, bool> isWalkable = null, Func<HexCoord, HexCoord, float> costFunction = null)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaSparseHexGrid<TCell> | grid | The bounded sparse hex grid to adapt. Must not be |
| Func<TCell, bool> | isWalkable | Optional predicate applied to cell data to determine walkability. |
| Func<HexCoord, HexCoord, float> | costFunction | Optional per-edge traversal cost between adjacent hexes; |
Returns
| Type | Description |
|---|---|
| ScyllaGridGraphAdapter<HexCoord, TCell> | A new |
Remarks
Only cells that have actually been set in the sparse grid are graph nodes (the adapter's
node-existence check uses Contains(TCoord), which for a
sparse grid means "has a value"). Set the cells that make up walkable terrain; unset cells act
as walls. The isWalkable predicate filters set cells further.
The grid must be bounded so node IDs form a compact range; an unbounded sparse grid throws.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
| ArgumentException | Thrown when |
FromSquareGrid(ScyllaSquareGrid<TCell>, Func<TCell, bool>, Func<SquareCoord, SquareCoord, float>, SquareAdjacency)
Creates a ScyllaGridGraphAdapter<TCoord, TCell> that wraps a
ScyllaSquareGrid<TCell> using the row-major node ID formula
nodeID = row * width + col.
Declaration
public static ScyllaGridGraphAdapter<SquareCoord, TCell> FromSquareGrid(ScyllaSquareGrid<TCell> grid, Func<TCell, bool> isWalkable = null, Func<SquareCoord, SquareCoord, float> costFunction = null, SquareAdjacency adjacency = SquareAdjacency.VonNeumann)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaSquareGrid<TCell> | grid | The square grid to adapt. Must not be |
| Func<TCell, bool> | isWalkable | Optional predicate applied to cell data to determine walkability. When |
| Func<SquareCoord, SquareCoord, float> | costFunction | Optional function that returns the traversal cost between two adjacent
SquareCoord coordinates. When |
| SquareAdjacency | adjacency | Adjacency mode for neighbor generation. Defaults to VonNeumann (4-connected). |
Returns
| Type | Description |
|---|---|
| ScyllaGridGraphAdapter<SquareCoord, TCell> | A new ScyllaGridGraphAdapter<TCoord, TCell> parameterized as
|
Remarks
The inverse mapping is col = nodeID % width, row = nodeID / width.
The adjacency mode controls the maximum neighbor count per node:
- VonNeumann (default) - 4-connected (N, S, E, W); max 4 neighbors.
- Moore - 8-connected (N, S, E, W plus all diagonals); max 8 neighbors.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
FromTriGrid(ScyllaTriGrid<TCell>, Func<TCell, bool>, Func<TriCoord, TriCoord, float>)
Creates a ScyllaGridGraphAdapter<TCoord, TCell> that wraps a
ScyllaTriGrid<TCell> using the orientation-encoded node ID formula
nodeID = ((B - 1) * width + (A - 1)) * 2 + orientation, where
orientation is 0 for downward triangles (A + B + C = 1) and
1 for upward triangles (A + B + C = 2).
Declaration
public static ScyllaGridGraphAdapter<TriCoord, TCell> FromTriGrid(ScyllaTriGrid<TCell> grid, Func<TCell, bool> isWalkable = null, Func<TriCoord, TriCoord, float> costFunction = null)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaTriGrid<TCell> | grid | The triangle grid to adapt. Must not be |
| Func<TCell, bool> | isWalkable | Optional predicate applied to cell data to determine walkability. When |
| Func<TriCoord, TriCoord, float> | costFunction | Optional function that returns the traversal cost between two adjacent
TriCoord coordinates. When |
Returns
| Type | Description |
|---|---|
| ScyllaGridGraphAdapter<TriCoord, TCell> | A new ScyllaGridGraphAdapter<TCoord, TCell> parameterized as
|
Remarks
Triangle grids use three-axis lane coordinates (A, B, C). Each grid position
contains two triangles - one pointing downward and one pointing upward - so the
total node count is width * height * 2.
The inverse node-ID-to-coordinate mapping is:
orientation = nodeID % 2cellIndex = nodeID / 2col = cellIndex % width,row = cellIndex / widthA = col + 1,B = row + 1-
C = (orientation == 1) ? (2 - A - B) : (1 - A - B)
Each triangle cell has up to 3 neighbors, so the internal scratch buffer is sized to 3.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
GetNeighborCount(int)
Returns the number of walkable neighbors reachable from the specified node.
Declaration
public int GetNeighborCount(int nodeID)
Parameters
| Type | Name | Description |
|---|---|---|
| int | nodeID | The ID of the node to query. |
Returns
| Type | Description |
|---|---|
| int | The count of walkable neighbors, or |
Remarks
Neighbor coordinates are obtained by calling _getNeighborCoords into the
shared Scylla.Core.Structures.ScyllaGridGraphAdapter<TCoord, TCell>._neighborBuffer. Each candidate neighbor is then filtered by
grid bounds and, if a walkability predicate is configured, by cell walkability.
The source cell itself is also checked for walkability; if it is unwalkable,
0 is returned immediately.
GetNeighborsNonAlloc(int, Span<ScyllaGraphEdge>)
Copies the walkable outgoing edges of the specified node into a caller-provided span, avoiding any heap allocation.
Declaration
public int GetNeighborsNonAlloc(int nodeID, Span<ScyllaGraphEdge> destination)
Parameters
| Type | Name | Description |
|---|---|---|
| int | nodeID | The ID of the node whose outgoing edges should be retrieved. |
| Span<ScyllaGraphEdge> | destination | Span into which the ScyllaGraphEdge descriptors will be written. Must be allocated by the caller; no allocation is performed by this method. |
Returns
| Type | Description |
|---|---|
| int | The number of edges written into |
Remarks
For each valid, walkable neighbor, an edge descriptor is written to
destination with:
-
FromID set to
nodeID. - ToID set to the neighbor's node ID.
-
Weight set to the result of the
costFunctiondelegate, or1.0fif no cost function was provided.
If destination fills before all neighbors are processed,
copying stops and the number of edges written so far is returned. Use
GetNeighborCount(int) to pre-size the buffer if all edges are needed.
NodeToCoord(int)
Converts a node ID back to its grid coordinate. Use this to translate the node IDs in a ScyllaGraphPath (returned by Dijkstra or A*) into grid coordinates.
Declaration
public TCoord NodeToCoord(int nodeID)
Parameters
| Type | Name | Description |
|---|---|---|
| int | nodeID | The node ID to convert. |
Returns
| Type | Description |
|---|---|
| TCoord | The grid coordinate corresponding to |
TryGetEdge(int, int, out ScyllaGraphEdge)
Attempts to retrieve the edge descriptor for a walkable connection between two nodes.
The edge weight is computed on demand using the configured cost function, or defaults
to 1.0f if no cost function was provided.
Declaration
public bool TryGetEdge(int fromID, int toID, out ScyllaGraphEdge edge)
Parameters
| Type | Name | Description |
|---|---|---|
| int | fromID | ID of the source node. |
| int | toID | ID of the target node. |
| ScyllaGraphEdge | edge | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|
TryGetNodeFlags(int, out ScyllaGraphNodeFlags)
Attempts to retrieve the ScyllaGraphNodeFlags for the specified node.
Walkability is determined dynamically from the cell data via the configured
isWalkable predicate. If no predicate was provided, all valid cells are
reported as Walkable.
Declaration
public bool TryGetNodeFlags(int nodeID, out ScyllaGraphNodeFlags flags)
Parameters
| Type | Name | Description |
|---|---|---|
| int | nodeID | The ID of the node to query. |
| ScyllaGraphNodeFlags | flags | When this method returns |
Returns
| Type | Description |
|---|---|
| bool |
|