Skip to content

Commit

Permalink
add Hexagon
Browse files Browse the repository at this point in the history
  • Loading branch information
ericyd committed Jan 11, 2024
1 parent 2e29d5a commit de1743c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 12 deletions.
67 changes: 67 additions & 0 deletions lib/components/hexagon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { vec2 } from '../vector2.js'
import { Polygon } from './polygon.js'

/** @typedef {import('../vector2.js').Vector2} Vector2 */

/**
* @typedef {object} HexagonAttributes
* @property {Vector2} center
* @property {number} [circumradius] the radius of the circumscribed circle. Either the apothem or the circumradius must be defined.
* @property {number} [apothem] the radius of the inscribed circle. Either the apothem or the circumradius must be defined.
* @property {Radians} [rotation=0]
*/

export class Hexagon extends Polygon {
/** @type {number} */
#rotation = 0
/** @type {number} */
#circumradius
/** @type {number} */
#apothem
/** @type {Vector2} */
#center

/**
* @param {HexagonAttributes} attributes
*/
constructor({ center, circumradius, apothem, rotation = 0, ...attributes }) {
if (typeof circumradius !== 'number' && typeof apothem !== 'number') {
throw new Error('Must provide either circumradius or apothem')
}

// @ts-expect-error either circumradius or apothem is defined at this point
const cr = circumradius ?? (apothem * 2) / Math.sqrt(3)
const points = new Array(6)
for (let i = 0; i < 6; i++) {
const angle = (Math.PI / 3) * i + rotation
points[i] = center.add(
vec2(Math.cos(angle), Math.sin(angle)).multiply(cr),
)
}

super({ ...attributes, points })
this.#center = center
this.#circumradius = cr
this.#apothem = apothem ?? (cr * Math.sqrt(3)) / 2
}

/**
* @returns {Hexagon[]} the list of neighboring hexagons, assuming a hexagonal grid
*/
neighbors() {
const hexagons = new Array(6)
for (let i = 0; i < 6; i++) {
const angle = (Math.PI / 3) * i + this.#rotation + Math.PI / 6
const center = this.#center.add(
vec2(Math.cos(angle), Math.sin(angle)).multiply(this.#apothem * 2),
)
hexagons[i] = new Hexagon({
center,
circumradius: this.#circumradius,
rotation: this.#rotation,
...this.attributes,
})
}
return hexagons
}
}
33 changes: 33 additions & 0 deletions lib/components/hexagon.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import assert from 'node:assert'
import { describe, it } from 'node:test'
import { Hexagon } from './hexagon.js'
import { vec2 } from '../vector2.js'

describe('Hexagon', () => {
it('renders a hexagonal polygon', () => {
const hex = new Hexagon({
center: vec2(10, 10),
circumradius: 1,
rotation: Math.PI / 6,
})
hex.numericPrecision = 2
assert.strictEqual(
hex.render(),
'<polygon points="10.87,10.5 10,11 9.13,10.5 9.13,9.5 10,9 10.87,9.5"></polygon>',
)
})

describe('.neighbors', () => {
it('returns the correct number of neighbors', () => {
const hex = new Hexagon({
center: vec2(10, 10),
circumradius: 1,
rotation: Math.PI / 6,
})
const neighbors = hex.neighbors()
assert.strictEqual(neighbors.length, 6)
})

it.todo('returns the correct neighbors')
})
})
9 changes: 5 additions & 4 deletions lib/components/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export * from './tag.js'
export * from './svg.js'
export * from './circle.js'
export * from './path.js'
export * from './defs.js'
export * from './rectangle.js'
export * from './hexagon.js'
export * from './path.js'
export * from './polygon.js'
export * from './polyline.js'
export * from './rectangle.js'
export * from './svg.js'
export * from './tag.js'
16 changes: 8 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
export * from './random.js'
export * from './math.js'
export * from './util.js'
export * from './vector2.js'
export * from './color/rgb.js'
export { ColorHsl, hsl } from './color/hsl.js'
export * from './color/color-sequence.js'
export * from './constants.js'
export * from './color/rgb.js'
export * from './components/index.js'
export * from './data-structures/grid.js'
export * from './constants.js'
export * from './data-structures/fractalized-line.js'
export * from './noise/oscillator.js'
export * from './data-structures/grid.js'
export * from './math.js'
export * from './noise/oscillator-noise.js'
export * from './noise/oscillator.js'
export * from './random.js'
export * from './render.js'
export * from './util.js'
export { Vector2, vec2 } from './vector2.js'

0 comments on commit de1743c

Please sign in to comment.