Skip to content

Commit

Permalink
feat(hex): add isHex() function and overload corners() to either acce…
Browse files Browse the repository at this point in the history
…pt a hex or hex settings

isHex() uses the newly added readonly property __isHoneycombHex to determine if the passed value is
a hex (which has this property on its prototype).
  • Loading branch information
flauwekeul committed Apr 22, 2021
1 parent b8bab92 commit 893c829
Show file tree
Hide file tree
Showing 8 changed files with 26 additions and 8 deletions.
2 changes: 1 addition & 1 deletion playground/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const draw = SVG().addTo('body').size('100%', '100%')
export const render = (hex: Hex) => {
const { x, y } = hexToPoint(hex)
const polygon = draw
.polygon(corners(hex, hex).map(({ x, y }) => `${x},${y}`))
.polygon(corners(hex).map(({ x, y }) => `${x},${y}`))
.fill('none')
.stroke({ width: 1, color: '#999' })
const text = draw
Expand Down
14 changes: 11 additions & 3 deletions src/hex/functions/corners.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Hex, HexSettings, Orientation, Point } from '../types'
import { heightFlat, heightPointy } from './height'
import { hexToPoint } from './hexToPoint'
import { isHex } from './isHex'
import { widthFlat, widthPointy } from './width'

export const cornersPointy = (width: number, height: number, { x, y }: Point) => [
Expand All @@ -21,9 +22,16 @@ export const cornersFlat = (width: number, height: number, { x, y }: Point) => [
{ x: x - width * 0.25, y: y - height * 0.5 },
]

// todo: use separate functions for absolute and relative corners?
export const corners = ({ orientation, dimensions: { xRadius, yRadius }, origin }: HexSettings, hex?: Hex): Point[] => {
const point = hex ? hexToPoint(hex) : origin
// todo: add to docs that when passed a hex, its corners relative to the "origin hex" are returned (different per hex coordinates)
// and when passed hexSettings, corners relative to any hex's origin are returned (always the same)
export function corners(hex: Hex): Point[]
export function corners(hexSettings: HexSettings): Point[]
export function corners(hexOrHexSettings: HexSettings): Point[] {
const {
orientation,
dimensions: { xRadius, yRadius },
} = hexOrHexSettings
const point = isHex(hexOrHexSettings) ? hexToPoint(hexOrHexSettings) : hexOrHexSettings.origin
return orientation === Orientation.POINTY
? cornersPointy(widthPointy(xRadius), heightPointy(yRadius), point)
: cornersFlat(widthFlat(xRadius), heightFlat(yRadius), point)
Expand Down
3 changes: 2 additions & 1 deletion src/hex/functions/createHexPrototype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const createHexPrototype = <T extends DefaultHexPrototype>(
// use Object.defineProperties() to create readonly properties
// origin is set in the final "step"
Object.defineProperties(prototype, {
__isHoneycombHex: { value: true },
// todo: all props set with `value` are writable (somehow the default `writable: false` doesn't apply). Not sure if this is a problem though
// see: Object.getOwnPropertyDescriptors(hexPrototype)
col: {
Expand All @@ -112,7 +113,7 @@ export const createHexPrototype = <T extends DefaultHexPrototype>(
},
corners: {
get() {
return corners(this, this)
return corners(this)
},
},
dimensions: { value: normalizeDimensions(prototype) },
Expand Down
1 change: 1 addition & 0 deletions src/hex/functions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './height'
export * from './hexToOffset'
export * from './hexToPoint'
export * from './isFlat'
export * from './isHex'
export * from './isPointy'
export * from './offsetToAxial'
export * from './width'
4 changes: 4 additions & 0 deletions src/hex/functions/isHex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { isObject } from '../../utils'
import { Hex } from '../types'

export const isHex = (value: unknown): value is Hex => isObject<Hex>(value) && !!value.__isHoneycombHex
6 changes: 3 additions & 3 deletions src/hex/functions/offsetToAxial.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { offsetFromZero } from '../../utils'
import { DefaultHexPrototype, HexCoordinates, OffsetCoordinates } from '../types'
import { AxialCoordinates, DefaultHexPrototype, OffsetCoordinates } from '../types'

export const offsetToAxialPointy = (col: number, row: number, offset: number): HexCoordinates => ({
export const offsetToAxialPointy = (col: number, row: number, offset: number): AxialCoordinates => ({
q: col - offsetFromZero(offset, row),
r: row,
})

export const offsetToAxialFlat = (col: number, row: number, offset: number): HexCoordinates => ({
export const offsetToAxialFlat = (col: number, row: number, offset: number): AxialCoordinates => ({
q: col,
r: row - offsetFromZero(offset, col),
})
Expand Down
1 change: 1 addition & 0 deletions src/hex/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface HexSettings {
}

export interface DefaultHexPrototype extends HexSettings {
readonly __isHoneycombHex: true
readonly col: number
readonly corners: Point[]
readonly height: number
Expand Down
3 changes: 3 additions & 0 deletions src/utils/isObject.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/**
* In TypeScript: pass a type variable to isObject() for best result. E.g.: `isObject<MyObject>(value)`
*/
export const isObject = <T = Record<string, unknown>>(value: unknown): value is T =>
typeof value === 'object' && value !== null

0 comments on commit 893c829

Please sign in to comment.