Basic hitomezashi pattern
This commit is contained in:
commit
b797f66721
12 changed files with 2345 additions and 0 deletions
76
src/main.ts
Normal file
76
src/main.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import { line, group, translate, asSvg, svgDoc } from "@thi.ng/geom";
|
||||
import { $canvas } from "@thi.ng/rdom-canvas";
|
||||
import { reactive } from "@thi.ng/rstream";
|
||||
import { cycle, takeWhile, comp, mapIndexed, transduce, push, map } from "@thi.ng/transducers"
|
||||
|
||||
const xs = cycle([0,1,0,1,0,1])
|
||||
const ys = cycle([1,0,1,1,0,1])
|
||||
|
||||
const cellSize = 25
|
||||
|
||||
// available size for a2: 420 * 594
|
||||
const width = 420
|
||||
const height = 594
|
||||
|
||||
const minPadding = cellSize
|
||||
|
||||
// calculate available drawing area
|
||||
|
||||
const xCells = Math.floor((width - 2 * minPadding) / cellSize)
|
||||
const xPadding = (width - (xCells * cellSize)) / 2
|
||||
|
||||
const yCells = Math.floor((height - 2 * minPadding) / cellSize)
|
||||
const yPadding = (height - (yCells * cellSize)) / 2
|
||||
|
||||
const size = [width, height]
|
||||
|
||||
// build a list of start positions
|
||||
|
||||
const startPoints = (pattern: Iterable<number>, maxCoord: number) =>
|
||||
transduce(
|
||||
comp(
|
||||
mapIndexed((cell, val) => [cell * cellSize, val] as const),
|
||||
takeWhile(([coord, _]) => coord <= maxCoord),
|
||||
),
|
||||
push(),
|
||||
pattern
|
||||
)
|
||||
|
||||
const xStarts = startPoints(xs, width - 2 * xPadding)
|
||||
const yStarts = startPoints(ys, height - 2 * yPadding)
|
||||
|
||||
const yLines = xStarts.flatMap(
|
||||
([xCoord, val]: [number, number]) =>
|
||||
Array
|
||||
.from({ length: yCells })
|
||||
.map((_, cell) => (cell + val) % 2 === 0 // start at the beginning or skip it
|
||||
? line([xCoord, cell * cellSize], [xCoord, (cell + 1) * cellSize])
|
||||
: null)
|
||||
.filter(v => v != null)
|
||||
)
|
||||
|
||||
console.log({ xStarts, yStarts })
|
||||
|
||||
const xLines = yStarts.flatMap(
|
||||
([yCoord, val]: [number, number]) =>
|
||||
Array
|
||||
.from({ length: xCells })
|
||||
.map((_, cell) => (cell + val) % 2 === 0 // start at the beginning or skip it
|
||||
? line([cell * cellSize, yCoord], [(cell + 1) * cellSize, yCoord])
|
||||
: null)
|
||||
.filter(v => v != null)
|
||||
)
|
||||
|
||||
const scene = reactive(
|
||||
translate(
|
||||
group(
|
||||
{__background: '#eee', stroke: '#222' },
|
||||
[...yLines, ...xLines]
|
||||
),
|
||||
[xPadding, yPadding]
|
||||
)
|
||||
)
|
||||
|
||||
$canvas(scene, size).mount(document.body)
|
||||
|
||||
// console.log(asSvg(svgDoc({ viewBox: `0 0 ${size[0]} ${size[1]}` }, scene.deref())))
|
||||
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
||||
Loading…
Add table
Add a link
Reference in a new issue