Skip to content

Commit

Permalink
Cleanup, comments, removal of unused code
Browse files Browse the repository at this point in the history
This removes `Grid.getAdjacent()`, which wasn't used at all. It was
mostly a remnant of previous puzzle programs I've written.
  • Loading branch information
mbrown1413 committed Jul 23, 2024
1 parent 1d74409 commit 7b3b471
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 152 deletions.
83 changes: 20 additions & 63 deletions lib/Grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import {SerializableClass} from "~/lib/serialize.ts"
* implementation, that is, you should never count on the voxel values being
* meaningful. However, under the hood, `Voxel` is actually just a string, so
* you can use it as keys datatypes like `Set` or `Map`.
*
* Grids should not use "\n" or ";" characters in voxel values. This allows
* algorithms using grids to manipulate lists of voxels in various ways.
*/
export type Voxel = string

Expand All @@ -35,7 +38,9 @@ export type SideInfo = {

export type PieceBoundsEditInfo = {
dimensions: {
/** Name to show in UI for this dimension. */
name: string,
/** Property on Bounds object that should be edited for this dimension. */
boundsProperty: string,
}[]
}
Expand Down Expand Up @@ -105,29 +110,19 @@ export type Transform = string
*/
export abstract class Grid extends SerializableClass {

/**
* Return a reasonable bounds size to use for a piece.
*/
/** Return a reasonable bounds size to use for a piece. */
abstract getDefaultPieceBounds(): Bounds

/**
* Information about how to edit the bounds for a piece.
*/
/** Information about how to edit the bounds for a piece. */
abstract get boundsEditInfo(): PieceBoundsEditInfo

/**
* Is the given voxel inside the bounds?
*/
/** Is the given voxel inside the bounds? */
abstract isInBounds(voxel: Voxel, bounds: Bounds): boolean

/**
* Returns the smallest bounds which contains all of the given voxels.
*/
/** Returns the smallest bounds which contains all of the given voxels. */
abstract getVoxelBounds(...voxels: Voxel[]): Bounds

/**
* Returns the smallest bounds which contains all of the given bounds.
*/
/** Returns the smallest bounds which contains all of the given bounds. */
abstract getBoundsMax(...bounds: Bounds[]): Bounds

/**
Expand All @@ -137,46 +132,15 @@ export abstract class Grid extends SerializableClass {
*/
abstract getBoundsOrigin(bounds: Bounds): Voxel

/**
* Return info describing the voxel.
*/
/** Return info describing the voxel. */
abstract getVoxelInfo(voxel: Voxel): VoxelInfo

/**
* Return all voxels in the grid inside the bounds.
*/
/** Return all voxels in the grid inside the bounds. */
abstract getVoxels(bounds: Bounds): Voxel[]

/** Return info describing one side of a voxel. */
abstract getSideInfo(voxel: Voxel, direction: Direction): SideInfo

/**
* Get voxel next to the given voxel in the given direction.
*
* Even though no bounds are passed in, this method may still return null
* if the grid is finite or irregular.
*
* @return [
* The adjacent voxel or null if there is no voxel there,
* The opposite direction (the direction which will get back to the original voxel)
* ]
*/
abstract getAdjacent(
voxel: Voxel,
direction: Direction
): [neighbor: Voxel|null, oppositeDirection: Direction]

/**
* Same as `getAdjacent()`, but adjacent voxels out of bounds are returned as null.
*/
getAdjacentInBounds(voxel: Voxel, direction: Direction, bounds: Bounds): [Voxel|null, Direction] {
const [neighbor, oppositeDir] = this.getAdjacent(voxel, direction)
if(neighbor !== null && !this.isInBounds(neighbor, bounds)) {
return [null, oppositeDir]
} else {
return [neighbor, oppositeDir]
}
}

/**
* Perform a transformation, mapping an existing set of voxels to a new set
* of the same size.
Expand All @@ -199,25 +163,18 @@ export abstract class Grid extends SerializableClass {
*/
abstract scaleTransform(transform: Transform, amount: number): Transform

/**
* List all possible ways a set of voxels can be rotated.
*/
/** List all possible ways a set of voxels can be rotated. */
abstract getRotations(includeMirrors: boolean): Transform[]

/**
* Return a translation which would move one voxel to another.
*/
/** Return a translation which would move one voxel to another. */
abstract getTranslation(from: Voxel, to: Voxel): Transform

abstract getViewpoints(): Viewpoint[]

/**
* Get transforms which should be used as movements when disassembling.
*/
/** Get transforms which should be used as movements when disassembling. */
abstract getDisassemblyTransforms(): Transform[]

/**
* Are the two groups of voxels trivially separable from each other?
*/
/** Are the two groups of voxels trivially separable from each other? */
abstract isSeparate(group1: Voxel[], group2: Voxel[]): boolean

/** Get a list of viewpoints which the user can switch between. */
abstract getViewpoints(): Viewpoint[]
}
12 changes: 0 additions & 12 deletions lib/grids/CubicGrid.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,6 @@ describe("Cubic grid", () => {
])
})

test("getAdjacent()", () => {
expect(grid.getAdjacent("0,0,0", "+X")).toEqual(["1,0,0", "-X"])
expect(grid.getAdjacent("0,0,0", "-X")).toEqual(["-1,0,0", "+X"])

expect(grid.getAdjacent("5,5,5", "+X")).toEqual(["6,5,5", "-X"])
expect(grid.getAdjacent("5,5,5", "-X")).toEqual(["4,5,5", "+X"])
expect(grid.getAdjacent("5,5,5", "+Y")).toEqual(["5,6,5", "-Y"])
expect(grid.getAdjacent("5,5,5", "-Y")).toEqual(["5,4,5", "+Y"])
expect(grid.getAdjacent("5,5,5", "+Z")).toEqual(["5,5,6", "-Z"])
expect(grid.getAdjacent("5,5,5", "-Z")).toEqual(["5,5,4", "+Z"])
})

test("rotations", () => {
const rotations = grid.getRotations(false)
const actualOrientations = makePlacementSet(
Expand Down
127 changes: 61 additions & 66 deletions lib/grids/CubicGrid.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Vector3, Matrix3, Matrix4, PlaneGeometry} from "three"

import {registerClass} from '~/lib/serialize.ts'
import {registerClass} from "~/lib/serialize.ts"
import {Grid, Voxel, Viewpoint, Transform} from "~/lib/Grid.ts"

type Coordinate3d = {x: number, y: number, z: number}
Expand Down Expand Up @@ -32,14 +32,6 @@ const CUBIC_DIR_DELTAS = {
"+Z": [ 0, 0, 1],
"-Z": [ 0, 0, -1],
}
const CUBIC_OPPOSITES: {[Property in CubicDirection]: CubicDirection} = {
"+X": "-X",
"-X": "+X",
"+Y": "-Y",
"-Y": "+Y",
"+Z": "-Z",
"-Z": "+Z",
}

const SIDE_POLYGONS: {[side in CubicDirection]: [number, number, number][]} = {
"+X": [[1, 0, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1]],
Expand All @@ -58,7 +50,8 @@ function isCubicDirection(d: string): d is CubicDirection {
}

export class CubicGrid extends Grid {
voxelToCoordinate(voxel: Voxel): Coordinate3d {

protected voxelToCoordinate(voxel: Voxel): Coordinate3d {
const coord = voxel.split(",", 3)
if(coord.length !== 3) {
throw new Error(`Invalid cubic coordinate: ${voxel}`)
Expand All @@ -70,7 +63,7 @@ export class CubicGrid extends Grid {
}
}

coordinateToVoxel(coordinate: Coordinate3d): Voxel {
protected coordinateToVoxel(coordinate: Coordinate3d): Voxel {
return `${coordinate.x},${coordinate.y},${coordinate.z}`
}

Expand Down Expand Up @@ -161,6 +154,24 @@ export class CubicGrid extends Grid {
}
}

getVoxels(bounds: CubicBounds) {
const ret = []
const xMin = bounds.x || 0
const yMin = bounds.y || 0
const zMin = bounds.z || 0
const xMax = xMin + bounds.xSize
const yMax = yMin + bounds.ySize
const zMax = zMin + bounds.zSize
for(let x=xMin; x < xMax; x++) {
for(let y=yMin; y < yMax; y++) {
for(let z=zMin; z < zMax; z++) {
ret.push(this.coordinateToVoxel({x, y, z}))
}
}
}
return ret
}

getSideInfo(voxel: Voxel, direction: CubicDirection) {
const {x, y, z} = this.voxelToCoordinate(voxel)
const translation = new Vector3(x, y, z)
Expand Down Expand Up @@ -203,33 +214,12 @@ export class CubicGrid extends Grid {
}
}

getVoxels(bounds: CubicBounds) {
const ret = []
const xMin = bounds.x || 0
const yMin = bounds.y || 0
const zMin = bounds.z || 0
const xMax = xMin + bounds.xSize
const yMax = yMin + bounds.ySize
const zMax = zMin + bounds.zSize
for(let x=xMin; x < xMax; x++) {
for(let y=yMin; y < yMax; y++) {
for(let z=zMin; z < zMax; z++) {
ret.push(this.coordinateToVoxel({x, y, z}))
}
}
}
return ret
}

getAdjacent(voxel: Voxel, direction: CubicDirection): [Voxel, CubicDirection] {
const {x, y, z} = this.voxelToCoordinate(voxel)
const [dx, dy, dz] = CUBIC_DIR_DELTAS[direction]
const [nx, ny, nz] = [x+dx, y+dy, z+dz]
const neighbor: Voxel|null = this.coordinateToVoxel({x: nx, y: ny, z: nz})
const oppositeDir = CUBIC_OPPOSITES[direction]
return [neighbor, oppositeDir]
}

/**
* Rotations start with "r:", followed by the side of a cube which should
* be rotated to point in the +X direction, followed by the number of times
* to rotate about the X axis. An "m" may be included at the end to
* additionally mirror about the Y-Z plane.
*/
getRotations(includeMirrors: boolean) {
const rotations = [
"r:+X,0", "r:+X,1", "r:+X,2", "r:+X,3",
Expand All @@ -247,6 +237,10 @@ export class CubicGrid extends Grid {
return rotations
}

/**
* Translations start with "t:" and contain numbers which are the amounts
* to translate in each axis.
*/
getTranslation(from: Voxel, to: Voxel) {
const fromCoordinate = this.voxelToCoordinate(from)
const toCoordinate = this.voxelToCoordinate(to)
Expand Down Expand Up @@ -361,34 +355,6 @@ export class CubicGrid extends Grid {
)
}

getViewpoints() {
const xy: Viewpoint = {
id: "xy",
name: "X-Y Plane",
forwardVector: new Vector3(0, 0, -1),
xVector: new Vector3(1, 0, 0),
getNLayers(bounds: CubicBounds) { return bounds.zSize },
isInLayer: (voxel, layerIndex) => this.voxelToCoordinate(voxel).z == layerIndex,
}
const xz: Viewpoint = {
id: "xz",
name: "X-Z Plane",
forwardVector: new Vector3(0, -1, 0),
xVector: new Vector3(1, 0, 0),
getNLayers(bounds: CubicBounds) { return bounds.ySize },
isInLayer: (voxel, layerIndex) => this.voxelToCoordinate(voxel).y == layerIndex,
}
const yz: Viewpoint = {
id: "yz",
name: "Y-Z Plane",
forwardVector: new Vector3(-1, 0, 0),
xVector: new Vector3(0, 0, -1),
getNLayers(bounds: CubicBounds) { return bounds.xSize },
isInLayer: (voxel, layerIndex) => this.voxelToCoordinate(voxel).x == layerIndex,
}
return [xy, xz, yz]
}

getDisassemblyTransforms(): Transform[] {
return Object.values(CUBIC_DIR_DELTAS).map(delta =>
this.getTranslation("0,0,0", `${delta[0]},${delta[1]},${delta[2]}`)
Expand Down Expand Up @@ -425,6 +391,35 @@ export class CubicGrid extends Grid {
const box2 = getBox(group2.map(this.voxelToCoordinate))
return boxesAreSeparate(box1, box2)
}

getViewpoints() {
const xy: Viewpoint = {
id: "xy",
name: "X-Y Plane",
forwardVector: new Vector3(0, 0, -1),
xVector: new Vector3(1, 0, 0),
getNLayers(bounds: CubicBounds) { return bounds.zSize },
isInLayer: (voxel, layerIndex) => this.voxelToCoordinate(voxel).z == layerIndex,
}
const xz: Viewpoint = {
id: "xz",
name: "X-Z Plane",
forwardVector: new Vector3(0, -1, 0),
xVector: new Vector3(1, 0, 0),
getNLayers(bounds: CubicBounds) { return bounds.ySize },
isInLayer: (voxel, layerIndex) => this.voxelToCoordinate(voxel).y == layerIndex,
}
const yz: Viewpoint = {
id: "yz",
name: "Y-Z Plane",
forwardVector: new Vector3(-1, 0, 0),
xVector: new Vector3(0, 0, -1),
getNLayers(bounds: CubicBounds) { return bounds.xSize },
isInLayer: (voxel, layerIndex) => this.voxelToCoordinate(voxel).x == layerIndex,
}
return [xy, xz, yz]
}

}

registerClass(CubicGrid)
22 changes: 11 additions & 11 deletions lib/grids/SquareGrid.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {registerClass} from '~/lib/serialize.ts'
import {registerClass} from "~/lib/serialize.ts"
import {CubicBounds, CubicGrid} from "~/lib/grids/CubicGrid.ts"
import {Piece} from '~/lib/Piece.ts'
import {Piece} from "~/lib/Piece.ts"

export class SquareGrid extends CubicGrid {

Expand Down Expand Up @@ -42,6 +42,15 @@ export class SquareGrid extends CubicGrid {
return rotations
}

getDisassemblyTransforms() {
return [
this.getTranslation("0,0,0", "1,0,0"),
this.getTranslation("0,0,0", "-1,0,0"),
this.getTranslation("0,0,0", "0,1,0"),
this.getTranslation("0,0,0", "0,-1,0"),
]
}

getViewpoints() {
let viewpoints = CubicGrid.prototype.getViewpoints.call(this)
viewpoints = viewpoints.filter(
Expand All @@ -53,15 +62,6 @@ export class SquareGrid extends CubicGrid {
return viewpoints
}

getDisassemblyTransforms() {
return [
this.getTranslation("0,0,0", "1,0,0"),
this.getTranslation("0,0,0", "-1,0,0"),
this.getTranslation("0,0,0", "0,1,0"),
this.getTranslation("0,0,0", "0,-1,0"),
]
}

/**
* Produce a set of pieces from a string representation.
*
Expand Down

0 comments on commit 7b3b471

Please sign in to comment.