VoxelGraph

class VoxelGraph @JvmOverloads constructor(val columns: Int, val rows: Int, val layers: Int, val torus: Boolean = false, val movementRule: VoxelMovementRule = VoxelMovementRule.MOORE_26, val allowCornerCutting: Boolean = false)(source)

A 3D-lattice graph: voxels are first-class nodes, edges represent allowed movement between adjacent voxels, and voxels carry movement costs and blocked / passable status. The 3D analog of GridGraph. Separate from VoxelProjection, which places agents on a lattice but doesn't model the lattice's navigation structure.

Use VoxelGraph for:

  • 3D pathfinding: drones / robots routing through an environment with 3D obstacles (no-fly zones, buildings, warehouse racks with vertical extent).

  • 3D distance fields: precompute "distance to goal voxels" for every voxel via distanceField, then have agents follow the gradient.

  • 3D reachability analysis: which voxels can reach a given altitude / corridor / charging volume.

Edge model:

  • Each voxel has a voxelCost, default 1.0. Set via setVoxelCost (and read via voxelCostOf).

  • Edge cost from voxel u to neighbor v is voxelCost(v) * stepLength, where stepLength is:

    • 1.0 for orthogonal (face-adjacent) moves

    • √2 for face-diagonal (edge-adjacent) moves

    • √3 for body-diagonal (corner-adjacent) moves

  • Blocked voxels (set via block) have no incident edges and are unreachable from any other voxel.

Boundary semantics:

  • Bounded (default) — coordinates outside the bounds throw. Voxels on the boundary have fewer neighbors.

  • Torus (torus = true) — coordinates wrap on all three axes.

Time complexity:

Parameters

columns

lattice width (x-axis)

rows

lattice depth (y-axis)

layers

lattice height (z-axis, typically altitude) Corner-cutting (MOORE_26 only):

  • By default (allowCornerCutting = false) a diagonal move (face-diagonal √2 or body-diagonal √3) is permitted only when every axis-neighbor it passes between is passable — i.e. for each nonzero offset component, the voxel reached by that component alone must be passable. This prevents agents from clipping through blocked voxels at shared edges/corners.

  • Set allowCornerCutting = true to require only that the destination voxel be passable.

  • Has no effect under VON_NEUMANN_6 (only orthogonal moves).

torus

if true, coordinates wrap at boundaries

movementRule

MOORE_26 (26-way) or VON_NEUMANN_6 (6-way)

allowCornerCutting

if true, diagonal moves ignore the passability of the in-between axis-neighbor voxels (default false)

Constructors

Link copied to clipboard
constructor(columns: Int, rows: Int, layers: Int, torus: Boolean = false, movementRule: VoxelMovementRule = VoxelMovementRule.MOORE_26, allowCornerCutting: Boolean = false)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
Link copied to clipboard

Number of voxels currently marked as blocked.

Link copied to clipboard
Link copied to clipboard
val layers: Int
Link copied to clipboard

The minimum voxel cost across the grid: min(1.0, smallest explicitly-set cost). Equals 1.0 for a uniform grid. Pass to VoxelHeuristics.scaled to keep an A* heuristic admissible when some voxels cost less than 1.0.

Link copied to clipboard
Link copied to clipboard
val rows: Int
Link copied to clipboard
Link copied to clipboard

Total voxel count (columns × rows × layers).

Functions

Link copied to clipboard
fun block(voxel: Voxel)

Mark voxel as impassable.

Link copied to clipboard

Multi-source distance field: for each passable voxel, the shortest-path cost from the nearest source in sources. The canonical use case is "distance from any charging-station voxel" for drone models — compute once at setup, then every drone follows the gradient toward zero in O(1) per step.

Single-source distance field: for each passable voxel, the shortest-path cost from source to that voxel. Unreachable voxels are absent from the result map. Useful when many agents share the same goal; compute the field once via multi-source distanceField, then look up distances per-voxel in O(1).

Link copied to clipboard
fun edgeWeight(from: Voxel, to: Voxel): Double

Weight of the edge from from to to. Equals voxelCostOf(to) * stepLength, where stepLength is:

Link copied to clipboard
fun isPassable(voxel: Voxel): Boolean

True if voxel is in bounds (always true on a torus) and not blocked.

Link copied to clipboard
fun isReachable(from: Voxel, to: Voxel): Boolean

True if to is reachable from from. Uses early-exit BFS; faster than to in reachableFrom(from) for large grids where the target is close.

Link copied to clipboard

Passable neighbors of voxel under the configured movement rule. Excludes blocked voxels and (for non-torus grids) out-of-range voxels.

Link copied to clipboard

All voxels reachable from start via passable neighbors (BFS). Includes start itself if it's passable; returns an empty set if start is blocked.

Link copied to clipboard
fun setVoxelCost(voxel: Voxel, cost: Double)

Set the per-step cost of entering voxel. Must be ≥ 0. Voxels with no explicit cost have cost 1.0 implicitly.

Link copied to clipboard
fun shortestPath(from: Voxel, to: Voxel, heuristic: (current: Voxel, target: Voxel) -> Double = VoxelHeuristics.ZERO): WeightedPath<Voxel>?

Shortest weighted path from from to to. Returns the path (including both endpoints) plus total cost, or null if to is unreachable. A self-path returns WeightedPath(listOf(from), 0.0).

Link copied to clipboard
fun shortestPathLength(from: Voxel, to: Voxel, heuristic: (current: Voxel, target: Voxel) -> Double = VoxelHeuristics.ZERO): Double

Convenience accessor: total weighted cost from from to to, or Double.POSITIVE_INFINITY if unreachable. Returns 0.0 for the self-path.

Link copied to clipboard
fun unblock(voxel: Voxel)

Mark voxel as passable (no-op if it wasn't blocked).

Link copied to clipboard
fun voxelCostOf(voxel: Voxel): Double

Read the cost of entering voxel. Default 1.0 for voxels not explicitly set.