-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(grid): line() now accepts either "line as vector" options or "li…
…ne between" options The line() traverser can create a line of hexes starting at the given coordinates in a given (compass) direction with a given length. Or it can create a line of hexes between start and end coordinates. These end coordinates can be passed as either "until" or "through". Being similar to "at" and "start", where "until" excludes the terminal coordinate and "through" includes the terminal coordinate.
- Loading branch information
1 parent
052342e
commit 2fe7f1d
Showing
4 changed files
with
90 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,65 @@ | ||
import { CompassDirection } from '../../compass' | ||
import { Hex } from '../../hex' | ||
import { neighborOf } from '../functions' | ||
import { StartOrAt, Traverser } from '../types' | ||
import { | ||
assertCubeCoordinates, | ||
AxialCoordinates, | ||
CubeCoordinates, | ||
Hex, | ||
HexCoordinates, | ||
PartialCubeCoordinates, | ||
round, | ||
} from '../../hex' | ||
import { distance, neighborOf } from '../functions' | ||
import { StartOrAt, Traverser, XOR } from '../types' | ||
|
||
export const line = <T extends Hex>({ direction, start, at, length = 1 }: LineOptions): Traverser<T, T[]> => { | ||
export function line<T extends Hex>(options: LineAsVectorOptions): Traverser<T, T[]> | ||
export function line<T extends Hex>(options: LineBetweenOptions): Traverser<T, T[]> | ||
export function line<T extends Hex>(options: LineAsVectorOptions | LineBetweenOptions): Traverser<T, T[]> { | ||
return (cursor, getHex) => { | ||
const { start, at } = options | ||
const startHex = start && getHex(start) | ||
const hexes: T[] = startHex ? [startHex] : [] | ||
let _cursor = startHex ?? (at ? getHex(at) : cursor) | ||
|
||
for (let i = 1; i <= length; i++) { | ||
_cursor = getHex(neighborOf(_cursor, direction)) | ||
hexes.push(_cursor) | ||
if ((options as LineAsVectorOptions).direction in CompassDirection) { | ||
const { direction, length = 1 } = options as LineAsVectorOptions | ||
let _cursor = startHex ?? (at ? getHex(at) : cursor) | ||
|
||
for (let i = 1; i <= length; i++) { | ||
_cursor = getHex(neighborOf(_cursor, direction)) | ||
hexes.push(_cursor) | ||
} | ||
} else { | ||
const { until, through } = options as LineBetweenOptions | ||
const _start = start ?? at ?? cursor | ||
const _through = until ?? (through as HexCoordinates) | ||
const startCube = assertCubeCoordinates(_start, cursor) | ||
const throughCube = assertCubeCoordinates(_through, cursor) | ||
const length = distance(cursor, _start, _through) | ||
const step = 1.0 / Math.max(length, 1) | ||
|
||
for (let i = 1; until ? i < length : i <= length; i++) { | ||
const coordinates = round(lerp(nudge(startCube), nudge(throughCube), step * i)) | ||
hexes.push(getHex(coordinates)) | ||
} | ||
} | ||
|
||
return hexes | ||
} | ||
} | ||
|
||
export type LineOptions = StartOrAt & { | ||
export type LineAsVectorOptions = StartOrAt & { | ||
direction: CompassDirection | ||
length?: number | ||
} | ||
|
||
export type LineBetweenOptions = StartOrAt & XOR<{ until: HexCoordinates }, { through: HexCoordinates }> | ||
|
||
function nudge({ q, r, s }: CubeCoordinates): CubeCoordinates { | ||
return { q: q + 1e-6, r: r + 1e-6, s: s + -2e-6 } | ||
} | ||
|
||
// linear interpolation | ||
function lerp(a: PartialCubeCoordinates, b: PartialCubeCoordinates, t: number): AxialCoordinates { | ||
const q = a.q * (1 - t) + b.q * t | ||
const r = a.r * (1 - t) + b.r * t | ||
return { q, r } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters