cubegin 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/LICENSE +674 -0
- package/NOTICE +11 -0
- package/README.md +49 -0
- package/dist/scramble-core/src/batch.mjs +18 -0
- package/dist/scramble-core/src/generator.d.mts +35 -0
- package/dist/scramble-core/src/generator.mjs +136 -0
- package/dist/scramble-core/src/generators/clock.d.mts +11 -0
- package/dist/scramble-core/src/generators/clock.mjs +32 -0
- package/dist/scramble-core/src/generators/cube-random-turns.d.mts +11 -0
- package/dist/scramble-core/src/generators/cube-random-turns.mjs +54 -0
- package/dist/scramble-core/src/generators/four-by-four.d.mts +14 -0
- package/dist/scramble-core/src/generators/four-by-four.mjs +43 -0
- package/dist/scramble-core/src/generators/megaminx.d.mts +11 -0
- package/dist/scramble-core/src/generators/megaminx.mjs +18 -0
- package/dist/scramble-core/src/generators/pyraminx.d.mts +11 -0
- package/dist/scramble-core/src/generators/pyraminx.mjs +17 -0
- package/dist/scramble-core/src/generators/skewb.d.mts +11 -0
- package/dist/scramble-core/src/generators/skewb.mjs +17 -0
- package/dist/scramble-core/src/generators/square1.d.mts +11 -0
- package/dist/scramble-core/src/generators/square1.mjs +28 -0
- package/dist/scramble-core/src/generators/three-by-three.d.mts +25 -0
- package/dist/scramble-core/src/generators/three-by-three.mjs +85 -0
- package/dist/scramble-core/src/generators/two-by-two.d.mts +11 -0
- package/dist/scramble-core/src/generators/two-by-two.mjs +17 -0
- package/dist/scramble-core/src/random-source.d.mts +7 -0
- package/dist/scramble-core/src/random-source.mjs +8 -0
- package/dist/scramble-core/src/solvers/min2phase/coord-cube.mjs +10 -0
- package/dist/scramble-core/src/solvers/min2phase/cubie-cube.mjs +246 -0
- package/dist/scramble-core/src/solvers/min2phase/engine.mjs +1281 -0
- package/dist/scramble-core/src/solvers/min2phase/search-wca.mjs +21 -0
- package/dist/scramble-core/src/solvers/min2phase/search.mjs +25 -0
- package/dist/scramble-core/src/solvers/min2phase/tools.mjs +169 -0
- package/dist/scramble-core/src/solvers/min2phase/util.mjs +30 -0
- package/dist/scramble-core/src/solvers/pyraminx-solver.d.mts +17 -0
- package/dist/scramble-core/src/solvers/pyraminx-solver.mjs +350 -0
- package/dist/scramble-core/src/solvers/skewb-solver.d.mts +15 -0
- package/dist/scramble-core/src/solvers/skewb-solver.mjs +399 -0
- package/dist/scramble-core/src/solvers/sq12phase/full-cube.mjs +212 -0
- package/dist/scramble-core/src/solvers/sq12phase/search.mjs +520 -0
- package/dist/scramble-core/src/solvers/sq12phase/shape.mjs +214 -0
- package/dist/scramble-core/src/solvers/sq12phase/square.mjs +135 -0
- package/dist/scramble-core/src/solvers/threephase/center.mjs +798 -0
- package/dist/scramble-core/src/solvers/threephase/edge.mjs +632 -0
- package/dist/scramble-core/src/solvers/threephase/full-cube.mjs +554 -0
- package/dist/scramble-core/src/solvers/threephase/search.mjs +262 -0
- package/dist/scramble-core/src/solvers/threephase/tables.mjs +201 -0
- package/dist/scramble-core/src/solvers/two-by-two-solver.d.mts +15 -0
- package/dist/scramble-core/src/solvers/two-by-two-solver.mjs +298 -0
- package/dist/scramble-core.d.mts +15 -0
- package/dist/scramble-core.mjs +15 -0
- package/dist/scramble-image/src/color.d.mts +12 -0
- package/dist/scramble-image/src/color.mjs +11 -0
- package/dist/scramble-image/src/render.d.mts +10 -0
- package/dist/scramble-image/src/render.mjs +71 -0
- package/dist/scramble-image/src/renderers/clock.d.mts +6 -0
- package/dist/scramble-image/src/renderers/clock.mjs +145 -0
- package/dist/scramble-image/src/renderers/cube-isometric.d.mts +8 -0
- package/dist/scramble-image/src/renderers/cube-isometric.mjs +204 -0
- package/dist/scramble-image/src/renderers/cube-net.d.mts +8 -0
- package/dist/scramble-image/src/renderers/cube-net.mjs +52 -0
- package/dist/scramble-image/src/renderers/megaminx-isometric.d.mts +9 -0
- package/dist/scramble-image/src/renderers/megaminx-isometric.mjs +320 -0
- package/dist/scramble-image/src/renderers/megaminx.d.mts +9 -0
- package/dist/scramble-image/src/renderers/megaminx.mjs +173 -0
- package/dist/scramble-image/src/renderers/pyraminx-isometric.d.mts +9 -0
- package/dist/scramble-image/src/renderers/pyraminx-isometric.mjs +185 -0
- package/dist/scramble-image/src/renderers/pyraminx.d.mts +9 -0
- package/dist/scramble-image/src/renderers/pyraminx.mjs +111 -0
- package/dist/scramble-image/src/renderers/skewb-isometric.d.mts +9 -0
- package/dist/scramble-image/src/renderers/skewb-isometric.mjs +233 -0
- package/dist/scramble-image/src/renderers/skewb.d.mts +9 -0
- package/dist/scramble-image/src/renderers/skewb.mjs +187 -0
- package/dist/scramble-image/src/renderers/square1.d.mts +10 -0
- package/dist/scramble-image/src/renderers/square1.mjs +253 -0
- package/dist/scramble-image/src/svg/svg-document.d.mts +6 -0
- package/dist/scramble-image/src/svg/svg-document.mjs +7 -0
- package/dist/scramble-image/src/svg/svg-elements.d.mts +15 -0
- package/dist/scramble-image/src/svg/svg-elements.mjs +25 -0
- package/dist/scramble-image/src/svg/svg-serialize.mjs +29 -0
- package/dist/scramble-image.d.mts +15 -0
- package/dist/scramble-image.mjs +15 -0
- package/dist/scramble-puzzle/src/algorithm.d.mts +8 -0
- package/dist/scramble-puzzle/src/algorithm.mjs +16 -0
- package/dist/scramble-puzzle/src/algorithm2.mjs +16 -0
- package/dist/scramble-puzzle/src/clock/clock-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/clock/clock-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/clock/clock-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/clock/clock-parser.d.mts +18 -0
- package/dist/scramble-puzzle/src/clock/clock-parser.mjs +35 -0
- package/dist/scramble-puzzle/src/clock/clock-parser2.mjs +35 -0
- package/dist/scramble-puzzle/src/clock/clock-state.d.mts +8 -0
- package/dist/scramble-puzzle/src/clock/clock-state.mjs +212 -0
- package/dist/scramble-puzzle/src/clock/clock-state2.d.mts +13 -0
- package/dist/scramble-puzzle/src/clock/clock-state2.mjs +212 -0
- package/dist/scramble-puzzle/src/cube/cube-definition.d.mts +9 -0
- package/dist/scramble-puzzle/src/cube/cube-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/cube/cube-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/cube/cube-move.d.mts +4 -0
- package/dist/scramble-puzzle/src/cube/cube-move2.d.mts +17 -0
- package/dist/scramble-puzzle/src/cube/cube-parser.d.mts +7 -0
- package/dist/scramble-puzzle/src/cube/cube-parser.mjs +60 -0
- package/dist/scramble-puzzle/src/cube/cube-parser2.mjs +60 -0
- package/dist/scramble-puzzle/src/cube/cube-state.d.mts +12 -0
- package/dist/scramble-puzzle/src/cube/cube-state.mjs +187 -0
- package/dist/scramble-puzzle/src/cube/cube-state2.d.mts +15 -0
- package/dist/scramble-puzzle/src/cube/cube-state2.mjs +187 -0
- package/dist/scramble-puzzle/src/errors.d.mts +15 -0
- package/dist/scramble-puzzle/src/errors.mjs +24 -0
- package/dist/scramble-puzzle/src/errors2.mjs +30 -0
- package/dist/scramble-puzzle/src/events.d.mts +5 -0
- package/dist/scramble-puzzle/src/events.mjs +90 -0
- package/dist/scramble-puzzle/src/events2.d.mts +98 -0
- package/dist/scramble-puzzle/src/events2.mjs +109 -0
- package/dist/scramble-puzzle/src/index.mjs +22 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser.d.mts +5 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser.mjs +57 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.d.mts +20 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.mjs +57 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state.d.mts +9 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state.mjs +112 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state2.d.mts +14 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state2.mjs +112 -0
- package/dist/scramble-puzzle/src/puzzle-definition.d.mts +19 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.d.mts +5 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.mjs +34 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.d.mts +21 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.mjs +34 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.d.mts +11 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.mjs +90 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.d.mts +14 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.mjs +90 -0
- package/dist/scramble-puzzle/src/registry.d.mts +11 -0
- package/dist/scramble-puzzle/src/registry.mjs +13 -0
- package/dist/scramble-puzzle/src/skewb/skewb-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/skewb/skewb-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/skewb/skewb-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser.d.mts +5 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser.mjs +33 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser2.d.mts +14 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser2.mjs +33 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state.d.mts +11 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state.mjs +75 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state2.d.mts +14 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state2.mjs +75 -0
- package/dist/scramble-puzzle/src/square1/square1-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/square1/square1-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/square1/square1-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/square1/square1-parser.d.mts +17 -0
- package/dist/scramble-puzzle/src/square1/square1-parser.mjs +43 -0
- package/dist/scramble-puzzle/src/square1/square1-parser2.mjs +47 -0
- package/dist/scramble-puzzle/src/square1/square1-state.d.mts +9 -0
- package/dist/scramble-puzzle/src/square1/square1-state.mjs +115 -0
- package/dist/scramble-puzzle/src/square1/square1-state2.d.mts +21 -0
- package/dist/scramble-puzzle/src/square1/square1-state2.mjs +115 -0
- package/dist/scramble-puzzle.d.mts +25 -0
- package/dist/scramble-puzzle.mjs +23 -0
- package/package.json +37 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { DEFAULT_CUBE_COLORS } from "../color.mjs";
|
|
2
|
+
import { createSvgDocument } from "../svg/svg-document.mjs";
|
|
3
|
+
import { path } from "../svg/svg-elements.mjs";
|
|
4
|
+
//#region .build/vendor/scramble-image/src/renderers/cube-isometric.ts
|
|
5
|
+
const PADDING = 6;
|
|
6
|
+
const VIEW_GAP = 28;
|
|
7
|
+
const STROKE = "#000000";
|
|
8
|
+
const STROKE_WIDTH = 2.5;
|
|
9
|
+
const FACE_ORDER = [
|
|
10
|
+
"R",
|
|
11
|
+
"U",
|
|
12
|
+
"F",
|
|
13
|
+
"L",
|
|
14
|
+
"D",
|
|
15
|
+
"B"
|
|
16
|
+
];
|
|
17
|
+
const point = (x, y) => ({
|
|
18
|
+
x,
|
|
19
|
+
y
|
|
20
|
+
});
|
|
21
|
+
const transformFromCorners = (topLeft, topRight, bottomRight, bottomLeft) => ({
|
|
22
|
+
topLeft,
|
|
23
|
+
topRight,
|
|
24
|
+
bottomRight,
|
|
25
|
+
bottomLeft
|
|
26
|
+
});
|
|
27
|
+
const createCornerViewPoints = (geometry) => ({
|
|
28
|
+
top: point(geometry.centerX, geometry.topY),
|
|
29
|
+
leftTop: point(geometry.centerX - geometry.topHalfWidth, geometry.topEdgeY),
|
|
30
|
+
rightTop: point(geometry.centerX + geometry.topHalfWidth, geometry.topEdgeY),
|
|
31
|
+
center: point(geometry.centerX, geometry.centerY),
|
|
32
|
+
leftBottom: point(geometry.centerX - geometry.bottomHalfWidth, geometry.bottomEdgeY),
|
|
33
|
+
rightBottom: point(geometry.centerX + geometry.bottomHalfWidth, geometry.bottomEdgeY),
|
|
34
|
+
bottom: point(geometry.centerX, geometry.bottomY)
|
|
35
|
+
});
|
|
36
|
+
const frontView = createCornerViewPoints({
|
|
37
|
+
centerX: 84,
|
|
38
|
+
topY: 6,
|
|
39
|
+
topEdgeY: 42,
|
|
40
|
+
centerY: 80,
|
|
41
|
+
bottomEdgeY: 116,
|
|
42
|
+
bottomY: 160,
|
|
43
|
+
topHalfWidth: 74,
|
|
44
|
+
bottomHalfWidth: 74
|
|
45
|
+
});
|
|
46
|
+
const backView = createCornerViewPoints({
|
|
47
|
+
centerX: 84,
|
|
48
|
+
topY: 6,
|
|
49
|
+
topEdgeY: 42,
|
|
50
|
+
centerY: 80,
|
|
51
|
+
bottomEdgeY: 116,
|
|
52
|
+
bottomY: 160,
|
|
53
|
+
topHalfWidth: 74,
|
|
54
|
+
bottomHalfWidth: 74
|
|
55
|
+
});
|
|
56
|
+
const FRONT_VIEW_FACES = [
|
|
57
|
+
{
|
|
58
|
+
face: "U",
|
|
59
|
+
transform: transformFromCorners(frontView.leftTop, frontView.top, frontView.rightTop, frontView.center)
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
face: "F",
|
|
63
|
+
transform: transformFromCorners(frontView.leftTop, frontView.center, frontView.bottom, frontView.leftBottom)
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
face: "R",
|
|
67
|
+
transform: transformFromCorners(frontView.center, frontView.rightTop, frontView.rightBottom, frontView.bottom)
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
const BACK_VIEW_FACES = [
|
|
71
|
+
{
|
|
72
|
+
face: "D",
|
|
73
|
+
transform: transformFromCorners(backView.leftTop, backView.top, backView.rightTop, backView.center)
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
face: "B",
|
|
77
|
+
transform: transformFromCorners(backView.leftTop, backView.center, backView.bottom, backView.leftBottom)
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
face: "L",
|
|
81
|
+
transform: transformFromCorners(backView.center, backView.rightTop, backView.rightBottom, backView.bottom)
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
const interpolatePoint = (start, end, ratio) => ({
|
|
85
|
+
x: start.x + (end.x - start.x) * ratio,
|
|
86
|
+
y: start.y + (end.y - start.y) * ratio
|
|
87
|
+
});
|
|
88
|
+
const transformPoint = (pointValue, transform) => {
|
|
89
|
+
return interpolatePoint(interpolatePoint(transform.topLeft, transform.topRight, pointValue.x), interpolatePoint(transform.bottomLeft, transform.bottomRight, pointValue.x), pointValue.y);
|
|
90
|
+
};
|
|
91
|
+
const stickerPoints = (row, col, size, transform) => {
|
|
92
|
+
const left = col / size;
|
|
93
|
+
const right = (col + 1) / size;
|
|
94
|
+
const top = row / size;
|
|
95
|
+
const bottom = (row + 1) / size;
|
|
96
|
+
return [
|
|
97
|
+
transformPoint(point(left, top), transform),
|
|
98
|
+
transformPoint(point(right, top), transform),
|
|
99
|
+
transformPoint(point(right, bottom), transform),
|
|
100
|
+
transformPoint(point(left, bottom), transform)
|
|
101
|
+
];
|
|
102
|
+
};
|
|
103
|
+
const polygonPath = (points) => {
|
|
104
|
+
const [firstPoint, ...remainingPoints] = points;
|
|
105
|
+
if (!firstPoint) return "";
|
|
106
|
+
return [
|
|
107
|
+
`M ${formatCoordinate(firstPoint.x)} ${formatCoordinate(firstPoint.y)}`,
|
|
108
|
+
...remainingPoints.map((pointValue) => `L ${formatCoordinate(pointValue.x)} ${formatCoordinate(pointValue.y)}`),
|
|
109
|
+
"Z"
|
|
110
|
+
].join(" ");
|
|
111
|
+
};
|
|
112
|
+
const formatCoordinate = (value) => Number(value.toFixed(3));
|
|
113
|
+
const lineworkPath = (segments) => segments.map(({ start, end }) => `M ${formatCoordinate(start.x)} ${formatCoordinate(start.y)} L ${formatCoordinate(end.x)} ${formatCoordinate(end.y)}`).join(" ");
|
|
114
|
+
const cubeFaceIndex = (face) => FACE_ORDER.indexOf(face);
|
|
115
|
+
const createStickerPolygonsForView = (state, colors, faces) => {
|
|
116
|
+
const stickers = [];
|
|
117
|
+
for (const { face, transform } of faces) {
|
|
118
|
+
const faceIndex = cubeFaceIndex(face);
|
|
119
|
+
const faceImage = state.image[faceIndex];
|
|
120
|
+
for (let row = 0; row < state.size; row += 1) for (let col = 0; col < state.size; col += 1) stickers.push({
|
|
121
|
+
points: stickerPoints(row, col, state.size, transform),
|
|
122
|
+
fill: colors[faceImage[row][col]]
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return stickers;
|
|
126
|
+
};
|
|
127
|
+
const createStickerPolygons = (state, colors) => {
|
|
128
|
+
const frontViewStickers = createStickerPolygonsForView(state, colors, FRONT_VIEW_FACES);
|
|
129
|
+
const backViewStickers = createStickerPolygonsForView(state, colors, BACK_VIEW_FACES);
|
|
130
|
+
const [frontMinX, frontMinY, frontMaxX] = boundsFor(frontViewStickers);
|
|
131
|
+
const [backMinX, backMinY] = boundsFor(backViewStickers);
|
|
132
|
+
const backOffsetX = frontMaxX - frontMinX + VIEW_GAP;
|
|
133
|
+
const frontOffsetY = Math.max(0, backMinY - frontMinY);
|
|
134
|
+
const backOffsetY = Math.max(0, frontMinY - backMinY);
|
|
135
|
+
return [...frontViewStickers.map((sticker) => ({
|
|
136
|
+
points: translatePoints(sticker.points, -frontMinX, -frontMinY + frontOffsetY),
|
|
137
|
+
fill: sticker.fill
|
|
138
|
+
})), ...backViewStickers.map((sticker) => ({
|
|
139
|
+
points: translatePoints(sticker.points, backOffsetX - backMinX, -backMinY + backOffsetY),
|
|
140
|
+
fill: sticker.fill
|
|
141
|
+
}))];
|
|
142
|
+
};
|
|
143
|
+
const segmentKey = ({ start, end }) => {
|
|
144
|
+
const startKey = `${formatCoordinate(start.x)},${formatCoordinate(start.y)}`;
|
|
145
|
+
const endKey = `${formatCoordinate(end.x)},${formatCoordinate(end.y)}`;
|
|
146
|
+
return startKey < endKey ? `${startKey}|${endKey}` : `${endKey}|${startKey}`;
|
|
147
|
+
};
|
|
148
|
+
const createLineworkSegments = (stickers) => {
|
|
149
|
+
const segments = /* @__PURE__ */ new Map();
|
|
150
|
+
for (const sticker of stickers) for (let index = 0; index < sticker.points.length; index += 1) {
|
|
151
|
+
const segment = {
|
|
152
|
+
start: sticker.points[index],
|
|
153
|
+
end: sticker.points[(index + 1) % sticker.points.length]
|
|
154
|
+
};
|
|
155
|
+
segments.set(segmentKey(segment), segment);
|
|
156
|
+
}
|
|
157
|
+
return [...segments.values()];
|
|
158
|
+
};
|
|
159
|
+
const drawStickers = (stickers) => stickers.map((sticker) => path({
|
|
160
|
+
d: polygonPath(sticker.points.map((pointValue) => ({
|
|
161
|
+
x: pointValue.x + PADDING,
|
|
162
|
+
y: pointValue.y + PADDING
|
|
163
|
+
}))),
|
|
164
|
+
fill: sticker.fill,
|
|
165
|
+
stroke: "none"
|
|
166
|
+
}));
|
|
167
|
+
const drawLinework = (stickers) => path({
|
|
168
|
+
d: lineworkPath(createLineworkSegments(stickers.map((sticker) => ({
|
|
169
|
+
points: sticker.points.map((pointValue) => ({
|
|
170
|
+
x: pointValue.x + PADDING,
|
|
171
|
+
y: pointValue.y + PADDING
|
|
172
|
+
})),
|
|
173
|
+
fill: sticker.fill
|
|
174
|
+
})))),
|
|
175
|
+
fill: "none",
|
|
176
|
+
stroke: STROKE,
|
|
177
|
+
"stroke-linecap": "round",
|
|
178
|
+
"stroke-linejoin": "round",
|
|
179
|
+
"stroke-width": STROKE_WIDTH
|
|
180
|
+
});
|
|
181
|
+
const translatePoints = (points, offsetX, offsetY) => points.map((pointValue) => ({
|
|
182
|
+
x: pointValue.x + offsetX,
|
|
183
|
+
y: pointValue.y + offsetY
|
|
184
|
+
}));
|
|
185
|
+
const boundsFor = (stickers) => {
|
|
186
|
+
const points = stickers.flatMap((sticker) => sticker.points);
|
|
187
|
+
return [
|
|
188
|
+
Math.min(...points.map((pointValue) => pointValue.x)),
|
|
189
|
+
Math.min(...points.map((pointValue) => pointValue.y)),
|
|
190
|
+
Math.max(...points.map((pointValue) => pointValue.x)),
|
|
191
|
+
Math.max(...points.map((pointValue) => pointValue.y))
|
|
192
|
+
];
|
|
193
|
+
};
|
|
194
|
+
const renderCubeIsometric = (state, colorScheme = {}) => {
|
|
195
|
+
const stickers = createStickerPolygons(state, {
|
|
196
|
+
...DEFAULT_CUBE_COLORS,
|
|
197
|
+
...colorScheme
|
|
198
|
+
});
|
|
199
|
+
const [, , maxX, maxY] = boundsFor(stickers);
|
|
200
|
+
const nodes = [...drawStickers(stickers), drawLinework(stickers)];
|
|
201
|
+
return createSvgDocument(Math.ceil(maxX + 2 * PADDING), Math.ceil(maxY + 2 * PADDING), nodes);
|
|
202
|
+
};
|
|
203
|
+
//#endregion
|
|
204
|
+
export { renderCubeIsometric };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CubeFacelet, CubeState } from "../../../scramble-puzzle/src/cube/cube-state.mjs";
|
|
2
|
+
import { HexColor } from "../color.mjs";
|
|
3
|
+
|
|
4
|
+
//#region .build/vendor/scramble-image/src/renderers/cube-net.d.ts
|
|
5
|
+
type CubeColorScheme = Partial<Record<CubeFacelet, HexColor>>;
|
|
6
|
+
declare const renderCubeNet: (state: CubeState, colorScheme?: CubeColorScheme) => string;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { renderCubeNet };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { DEFAULT_CUBE_COLORS } from "../color.mjs";
|
|
2
|
+
import { createSvgDocument } from "../svg/svg-document.mjs";
|
|
3
|
+
import { rect } from "../svg/svg-elements.mjs";
|
|
4
|
+
//#region .build/vendor/scramble-image/src/renderers/cube-net.ts
|
|
5
|
+
const GAP = 2;
|
|
6
|
+
const STICKER = 10;
|
|
7
|
+
const STROKE = "#000000";
|
|
8
|
+
const STROKE_WIDTH = 1;
|
|
9
|
+
const FACE_ORDER = [
|
|
10
|
+
"R",
|
|
11
|
+
"U",
|
|
12
|
+
"F",
|
|
13
|
+
"L",
|
|
14
|
+
"D",
|
|
15
|
+
"B"
|
|
16
|
+
];
|
|
17
|
+
const createFaceOrigins = (unit) => ({
|
|
18
|
+
L: [GAP, 2 * GAP + unit],
|
|
19
|
+
D: [2 * GAP + unit, 3 * GAP + 2 * unit],
|
|
20
|
+
B: [4 * GAP + 3 * unit, 2 * GAP + unit],
|
|
21
|
+
R: [3 * GAP + 2 * unit, 2 * GAP + unit],
|
|
22
|
+
U: [2 * GAP + unit, GAP],
|
|
23
|
+
F: [2 * GAP + unit, 2 * GAP + unit]
|
|
24
|
+
});
|
|
25
|
+
const renderCubeNet = (state, colorScheme = {}) => {
|
|
26
|
+
const colors = {
|
|
27
|
+
...DEFAULT_CUBE_COLORS,
|
|
28
|
+
...colorScheme
|
|
29
|
+
};
|
|
30
|
+
const unit = state.size * STICKER;
|
|
31
|
+
const width = (unit + GAP) * 4 + GAP;
|
|
32
|
+
const height = (unit + GAP) * 3 + GAP;
|
|
33
|
+
const faceOrigins = createFaceOrigins(unit);
|
|
34
|
+
const nodes = [];
|
|
35
|
+
for (const [face, [originX, originY]] of Object.entries(faceOrigins)) {
|
|
36
|
+
const faceIndex = FACE_ORDER.indexOf(face);
|
|
37
|
+
const stickers = state.image[faceIndex];
|
|
38
|
+
for (let row = 0; row < state.size; row += 1) for (let col = 0; col < state.size; col += 1) nodes.push(rect({
|
|
39
|
+
x: originX + col * STICKER,
|
|
40
|
+
y: originY + row * STICKER,
|
|
41
|
+
width: STICKER,
|
|
42
|
+
height: STICKER,
|
|
43
|
+
fill: colors[stickers[row][col]],
|
|
44
|
+
stroke: STROKE,
|
|
45
|
+
"stroke-width": STROKE_WIDTH,
|
|
46
|
+
"shape-rendering": "crispEdges"
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
return createSvgDocument(width, height, nodes);
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { renderCubeNet };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MegaminxFace } from "../../../scramble-puzzle/src/megaminx/megaminx-parser.mjs";
|
|
2
|
+
import { MegaminxState } from "../../../scramble-puzzle/src/megaminx/megaminx-state.mjs";
|
|
3
|
+
import { HexColor } from "../color.mjs";
|
|
4
|
+
|
|
5
|
+
//#region .build/vendor/scramble-image/src/renderers/megaminx-isometric.d.ts
|
|
6
|
+
type MegaminxIsometricColorScheme = Partial<Record<MegaminxFace, HexColor>>;
|
|
7
|
+
declare const renderMegaminxIsometricState: (state: MegaminxState, colorScheme?: MegaminxIsometricColorScheme) => string;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { MegaminxIsometricColorScheme, renderMegaminxIsometricState };
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { MEGAMINX_FACES } from "../../../scramble-puzzle/src/megaminx/megaminx-parser.mjs";
|
|
2
|
+
import "../../../scramble-puzzle/src/index.mjs";
|
|
3
|
+
import { createSvgDocument } from "../svg/svg-document.mjs";
|
|
4
|
+
import { path } from "../svg/svg-elements.mjs";
|
|
5
|
+
//#region .build/vendor/scramble-image/src/renderers/megaminx-isometric.ts
|
|
6
|
+
const WIDTH = 410;
|
|
7
|
+
const HEIGHT = 190;
|
|
8
|
+
const PADDING = 8;
|
|
9
|
+
const VIEW_GAP = 24;
|
|
10
|
+
const FACE_RADIUS = 52;
|
|
11
|
+
const ADJACENT_DEPTH = .52;
|
|
12
|
+
const STROKE = "#000000";
|
|
13
|
+
const STROKE_WIDTH = 2.75;
|
|
14
|
+
const DEFAULT_MEGAMINX_COLORS = {
|
|
15
|
+
U: "#ffffff",
|
|
16
|
+
BL: "#ffcc00",
|
|
17
|
+
BR: "#0000b3",
|
|
18
|
+
R: "#dd0000",
|
|
19
|
+
F: "#006600",
|
|
20
|
+
L: "#8a1aff",
|
|
21
|
+
D: "#999999",
|
|
22
|
+
DR: "#ffffb3",
|
|
23
|
+
DBR: "#ff99ff",
|
|
24
|
+
B: "#71e600",
|
|
25
|
+
DBL: "#ff8433",
|
|
26
|
+
DL: "#88ddff"
|
|
27
|
+
};
|
|
28
|
+
const VIEW_SPECS = [{
|
|
29
|
+
centerFace: "F",
|
|
30
|
+
faceByEdge: [
|
|
31
|
+
"DL",
|
|
32
|
+
"L",
|
|
33
|
+
"U",
|
|
34
|
+
"R",
|
|
35
|
+
"DR"
|
|
36
|
+
],
|
|
37
|
+
rotation: Math.PI / 2
|
|
38
|
+
}, {
|
|
39
|
+
centerFace: "B",
|
|
40
|
+
faceByEdge: [
|
|
41
|
+
"BL",
|
|
42
|
+
"DBL",
|
|
43
|
+
"D",
|
|
44
|
+
"DBR",
|
|
45
|
+
"BR"
|
|
46
|
+
],
|
|
47
|
+
rotation: -Math.PI / 2
|
|
48
|
+
}];
|
|
49
|
+
const STICKER_ORIENTATIONS = {
|
|
50
|
+
U: {
|
|
51
|
+
mirrored: true,
|
|
52
|
+
rotation: 1
|
|
53
|
+
},
|
|
54
|
+
BL: {
|
|
55
|
+
mirrored: true,
|
|
56
|
+
rotation: 2
|
|
57
|
+
},
|
|
58
|
+
BR: {
|
|
59
|
+
mirrored: true,
|
|
60
|
+
rotation: 1
|
|
61
|
+
},
|
|
62
|
+
R: {
|
|
63
|
+
mirrored: true,
|
|
64
|
+
rotation: 3
|
|
65
|
+
},
|
|
66
|
+
F: {
|
|
67
|
+
mirrored: false,
|
|
68
|
+
rotation: 4
|
|
69
|
+
},
|
|
70
|
+
L: {
|
|
71
|
+
mirrored: true,
|
|
72
|
+
rotation: 0
|
|
73
|
+
},
|
|
74
|
+
D: {
|
|
75
|
+
mirrored: true,
|
|
76
|
+
rotation: 0
|
|
77
|
+
},
|
|
78
|
+
DR: {
|
|
79
|
+
mirrored: true,
|
|
80
|
+
rotation: 0
|
|
81
|
+
},
|
|
82
|
+
DBR: {
|
|
83
|
+
mirrored: true,
|
|
84
|
+
rotation: 2
|
|
85
|
+
},
|
|
86
|
+
B: {
|
|
87
|
+
mirrored: false,
|
|
88
|
+
rotation: 3
|
|
89
|
+
},
|
|
90
|
+
DBL: {
|
|
91
|
+
mirrored: true,
|
|
92
|
+
rotation: 4
|
|
93
|
+
},
|
|
94
|
+
DL: {
|
|
95
|
+
mirrored: true,
|
|
96
|
+
rotation: 1
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const formatCoordinate = (value) => Number(value.toFixed(3));
|
|
100
|
+
const wrapPentagonIndex = (index) => (index + 5) % 5;
|
|
101
|
+
const wrapStickerIndex = (index) => (index + 10) % 10;
|
|
102
|
+
const averagePoint = (first, second) => ({
|
|
103
|
+
x: (first.x + second.x) / 2,
|
|
104
|
+
y: (first.y + second.y) / 2
|
|
105
|
+
});
|
|
106
|
+
const pentagon = (rotation) => [
|
|
107
|
+
0,
|
|
108
|
+
1,
|
|
109
|
+
2,
|
|
110
|
+
3,
|
|
111
|
+
4
|
|
112
|
+
].map((index) => {
|
|
113
|
+
const angle = rotation + 2 * Math.PI * index / 5;
|
|
114
|
+
return {
|
|
115
|
+
x: FACE_RADIUS * Math.cos(angle),
|
|
116
|
+
y: FACE_RADIUS * Math.sin(angle)
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
const projectPointToLine = (pointValue, lineStart, lineEnd) => {
|
|
120
|
+
const deltaX = lineEnd.x - lineStart.x;
|
|
121
|
+
const deltaY = lineEnd.y - lineStart.y;
|
|
122
|
+
const lengthSquared = deltaX * deltaX + deltaY * deltaY;
|
|
123
|
+
const ratio = ((pointValue.x - lineStart.x) * deltaX + (pointValue.y - lineStart.y) * deltaY) / lengthSquared;
|
|
124
|
+
return {
|
|
125
|
+
x: lineStart.x + ratio * deltaX,
|
|
126
|
+
y: lineStart.y + ratio * deltaY
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
const reflectPointAcrossLine = (pointValue, lineStart, lineEnd) => {
|
|
130
|
+
const projected = projectPointToLine(pointValue, lineStart, lineEnd);
|
|
131
|
+
return {
|
|
132
|
+
x: 2 * projected.x - pointValue.x,
|
|
133
|
+
y: 2 * projected.y - pointValue.y
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
const compressPointAwayFromLine = (pointValue, lineStart, lineEnd, scale) => {
|
|
137
|
+
const projected = projectPointToLine(pointValue, lineStart, lineEnd);
|
|
138
|
+
return {
|
|
139
|
+
x: projected.x + (pointValue.x - projected.x) * scale,
|
|
140
|
+
y: projected.y + (pointValue.y - projected.y) * scale
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
const adjacentBoundary = (centerBoundary, edgeIndex) => {
|
|
144
|
+
const lineStart = centerBoundary[edgeIndex];
|
|
145
|
+
const lineEnd = centerBoundary[(edgeIndex + 1) % centerBoundary.length];
|
|
146
|
+
return centerBoundary.map((pointValue) => compressPointAwayFromLine(reflectPointAcrossLine(pointValue, lineStart, lineEnd), lineStart, lineEnd, ADJACENT_DEPTH));
|
|
147
|
+
};
|
|
148
|
+
const stitchAdjacentBoundaries = (boundaries) => {
|
|
149
|
+
const sharedOuterPoints = boundaries.map((boundary, vertexIndex) => {
|
|
150
|
+
const currentFacePoint = boundary[wrapPentagonIndex(vertexIndex + 4)];
|
|
151
|
+
const previousFacePoint = boundaries[wrapPentagonIndex(vertexIndex - 1)][wrapPentagonIndex(vertexIndex + 1)];
|
|
152
|
+
return averagePoint(currentFacePoint, previousFacePoint);
|
|
153
|
+
});
|
|
154
|
+
return boundaries.map((boundary, edgeIndex) => boundary.map((pointValue, pointIndex) => {
|
|
155
|
+
if (pointIndex === wrapPentagonIndex(edgeIndex + 4)) return sharedOuterPoints[edgeIndex];
|
|
156
|
+
if (pointIndex === wrapPentagonIndex(edgeIndex + 2)) return sharedOuterPoints[wrapPentagonIndex(edgeIndex + 1)];
|
|
157
|
+
return pointValue;
|
|
158
|
+
}));
|
|
159
|
+
};
|
|
160
|
+
const createViewPlacements = (spec) => {
|
|
161
|
+
const centerBoundary = pentagon(spec.rotation);
|
|
162
|
+
const adjacentBoundaries = stitchAdjacentBoundaries(spec.faceByEdge.map((_, edgeIndex) => adjacentBoundary(centerBoundary, edgeIndex)));
|
|
163
|
+
const adjacentPlacements = spec.faceByEdge.map((face, edgeIndex) => ({
|
|
164
|
+
face,
|
|
165
|
+
boundary: adjacentBoundaries[edgeIndex]
|
|
166
|
+
}));
|
|
167
|
+
return [{
|
|
168
|
+
face: spec.centerFace,
|
|
169
|
+
boundary: centerBoundary
|
|
170
|
+
}, ...adjacentPlacements];
|
|
171
|
+
};
|
|
172
|
+
const translatePoint = (pointValue, offsetX, offsetY) => ({
|
|
173
|
+
x: pointValue.x + offsetX,
|
|
174
|
+
y: pointValue.y + offsetY
|
|
175
|
+
});
|
|
176
|
+
const translatePolygon = (points, offsetX, offsetY) => points.map((pointValue) => translatePoint(pointValue, offsetX, offsetY));
|
|
177
|
+
const translatePlacements = (placements, offsetX, offsetY) => placements.map(({ face, boundary }) => ({
|
|
178
|
+
face,
|
|
179
|
+
boundary: translatePolygon(boundary, offsetX, offsetY)
|
|
180
|
+
}));
|
|
181
|
+
const boundsForPolygons = (polygons) => {
|
|
182
|
+
const points = polygons.flat();
|
|
183
|
+
const xs = points.map((pointValue) => pointValue.x);
|
|
184
|
+
const ys = points.map((pointValue) => pointValue.y);
|
|
185
|
+
return {
|
|
186
|
+
minX: Math.min(...xs),
|
|
187
|
+
minY: Math.min(...ys),
|
|
188
|
+
maxX: Math.max(...xs),
|
|
189
|
+
maxY: Math.max(...ys)
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
const boundsForPlacements = (placements) => boundsForPolygons(placements.map((placement) => placement.boundary));
|
|
193
|
+
const layoutPlacements = () => {
|
|
194
|
+
const [leftView, rightView] = VIEW_SPECS.map(createViewPlacements);
|
|
195
|
+
const leftBounds = boundsForPlacements(leftView);
|
|
196
|
+
const rightBounds = boundsForPlacements(rightView);
|
|
197
|
+
const leftWidth = leftBounds.maxX - leftBounds.minX;
|
|
198
|
+
const rightWidth = rightBounds.maxX - rightBounds.minX;
|
|
199
|
+
const startX = (WIDTH - (leftWidth + VIEW_GAP + rightWidth)) / 2;
|
|
200
|
+
const viewHeight = HEIGHT - 2 * PADDING;
|
|
201
|
+
const leftHeight = leftBounds.maxY - leftBounds.minY;
|
|
202
|
+
const rightHeight = rightBounds.maxY - rightBounds.minY;
|
|
203
|
+
const leftOffsetY = PADDING + (viewHeight - leftHeight) / 2 - leftBounds.minY;
|
|
204
|
+
const rightOffsetY = PADDING + (viewHeight - rightHeight) / 2 - rightBounds.minY;
|
|
205
|
+
return [...translatePlacements(leftView, startX - leftBounds.minX, leftOffsetY), ...translatePlacements(rightView, startX + leftWidth + VIEW_GAP - rightBounds.minX, rightOffsetY)];
|
|
206
|
+
};
|
|
207
|
+
const FACE_PLACEMENTS = layoutPlacements();
|
|
208
|
+
const det = (a, b, c, d) => a * d - b * c;
|
|
209
|
+
const lineIntersection = (firstStart, firstEnd, secondStart, secondEnd) => {
|
|
210
|
+
const firstDet = det(firstStart.x, firstStart.y, firstEnd.x, firstEnd.y);
|
|
211
|
+
const secondDet = det(secondStart.x, secondStart.y, secondEnd.x, secondEnd.y);
|
|
212
|
+
const divisor = det(firstStart.x - firstEnd.x, firstStart.y - firstEnd.y, secondStart.x - secondEnd.x, secondStart.y - secondEnd.y);
|
|
213
|
+
return {
|
|
214
|
+
x: det(firstDet, firstStart.x - firstEnd.x, secondDet, secondStart.x - secondEnd.x) / divisor,
|
|
215
|
+
y: det(firstDet, firstStart.y - firstEnd.y, secondDet, secondStart.y - secondEnd.y) / divisor
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
const polygonPath = (points) => {
|
|
219
|
+
const [firstPoint, ...remainingPoints] = points;
|
|
220
|
+
if (!firstPoint) return "";
|
|
221
|
+
return [
|
|
222
|
+
`M ${formatCoordinate(firstPoint.x)} ${formatCoordinate(firstPoint.y)}`,
|
|
223
|
+
...remainingPoints.map((pointValue) => `L ${formatCoordinate(pointValue.x)} ${formatCoordinate(pointValue.y)}`),
|
|
224
|
+
"Z"
|
|
225
|
+
].join(" ");
|
|
226
|
+
};
|
|
227
|
+
const lineworkPath = (segments) => segments.map(({ start, end }) => `M ${formatCoordinate(start.x)} ${formatCoordinate(start.y)} L ${formatCoordinate(end.x)} ${formatCoordinate(end.y)}`).join(" ");
|
|
228
|
+
const createStickerPolygons = (boundary) => {
|
|
229
|
+
const edgePoints = [];
|
|
230
|
+
for (let index = 0; index < 5; index += 1) {
|
|
231
|
+
const current = boundary[index];
|
|
232
|
+
const next = boundary[(index + 1) % 5];
|
|
233
|
+
edgePoints[index] = {
|
|
234
|
+
x: .4 * next.x + .6 * current.x,
|
|
235
|
+
y: .4 * next.y + .6 * current.y
|
|
236
|
+
};
|
|
237
|
+
edgePoints[index + 5] = {
|
|
238
|
+
x: .6 * next.x + .4 * current.x,
|
|
239
|
+
y: .6 * next.y + .4 * current.y
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const innerPentagon = [];
|
|
243
|
+
for (let index = 0; index < 5; index += 1) innerPentagon[index] = lineIntersection(edgePoints[index], edgePoints[5 + (3 + index) % 5], edgePoints[(index + 1) % 5], edgePoints[5 + (4 + index) % 5]);
|
|
244
|
+
const stickers = [];
|
|
245
|
+
for (let index = 0; index < 5; index += 1) {
|
|
246
|
+
stickers[2 * index] = [
|
|
247
|
+
boundary[index],
|
|
248
|
+
edgePoints[index],
|
|
249
|
+
innerPentagon[index],
|
|
250
|
+
edgePoints[5 + (4 + index) % 5]
|
|
251
|
+
];
|
|
252
|
+
stickers[2 * index + 1] = [
|
|
253
|
+
edgePoints[index],
|
|
254
|
+
edgePoints[index + 5],
|
|
255
|
+
innerPentagon[(index + 1) % 5],
|
|
256
|
+
innerPentagon[index]
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
stickers[10] = innerPentagon;
|
|
260
|
+
return stickers;
|
|
261
|
+
};
|
|
262
|
+
const stickerIndexForOrientation = (stickerIndex, orientation) => {
|
|
263
|
+
if (stickerIndex >= 10) return stickerIndex;
|
|
264
|
+
const offset = 2 * orientation.rotation;
|
|
265
|
+
if (orientation.mirrored) return wrapStickerIndex(offset - stickerIndex);
|
|
266
|
+
return wrapStickerIndex(stickerIndex + offset);
|
|
267
|
+
};
|
|
268
|
+
const colorForSticker = (facelet, colors) => colors[MEGAMINX_FACES[facelet] ?? "U"];
|
|
269
|
+
const createFaceStickers = (state, placement, colors) => {
|
|
270
|
+
const faceIndexValue = MEGAMINX_FACES.indexOf(placement.face);
|
|
271
|
+
const stickers = state.image[faceIndexValue];
|
|
272
|
+
const orientation = STICKER_ORIENTATIONS[placement.face];
|
|
273
|
+
return createStickerPolygons(placement.boundary).map((polygon, stickerIndex) => {
|
|
274
|
+
return {
|
|
275
|
+
points: polygon,
|
|
276
|
+
fill: colorForSticker(stickers[stickerIndexForOrientation(stickerIndex, orientation)], colors)
|
|
277
|
+
};
|
|
278
|
+
});
|
|
279
|
+
};
|
|
280
|
+
const segmentKey = ({ start, end }) => {
|
|
281
|
+
const startKey = `${formatCoordinate(start.x)},${formatCoordinate(start.y)}`;
|
|
282
|
+
const endKey = `${formatCoordinate(end.x)},${formatCoordinate(end.y)}`;
|
|
283
|
+
return startKey < endKey ? `${startKey}|${endKey}` : `${endKey}|${startKey}`;
|
|
284
|
+
};
|
|
285
|
+
const createLineworkSegments = (stickers) => {
|
|
286
|
+
const segments = /* @__PURE__ */ new Map();
|
|
287
|
+
for (const sticker of stickers) for (let index = 0; index < sticker.points.length; index += 1) {
|
|
288
|
+
const segment = {
|
|
289
|
+
start: sticker.points[index],
|
|
290
|
+
end: sticker.points[(index + 1) % sticker.points.length]
|
|
291
|
+
};
|
|
292
|
+
segments.set(segmentKey(segment), segment);
|
|
293
|
+
}
|
|
294
|
+
return [...segments.values()];
|
|
295
|
+
};
|
|
296
|
+
const drawStickers = (stickers) => stickers.map((sticker) => path({
|
|
297
|
+
d: polygonPath(sticker.points),
|
|
298
|
+
fill: sticker.fill,
|
|
299
|
+
stroke: "none"
|
|
300
|
+
}));
|
|
301
|
+
const drawLinework = (stickers) => path({
|
|
302
|
+
d: lineworkPath(createLineworkSegments(stickers)),
|
|
303
|
+
fill: "none",
|
|
304
|
+
stroke: STROKE,
|
|
305
|
+
"stroke-linecap": "round",
|
|
306
|
+
"stroke-linejoin": "round",
|
|
307
|
+
"stroke-width": STROKE_WIDTH
|
|
308
|
+
});
|
|
309
|
+
const drawFaces = (state, colors) => {
|
|
310
|
+
const stickers = FACE_PLACEMENTS.flatMap((placement) => createFaceStickers(state, placement, colors));
|
|
311
|
+
return [...drawStickers(stickers), drawLinework(stickers)];
|
|
312
|
+
};
|
|
313
|
+
const renderMegaminxIsometricState = (state, colorScheme = {}) => {
|
|
314
|
+
return createSvgDocument(WIDTH, HEIGHT, drawFaces(state, {
|
|
315
|
+
...DEFAULT_MEGAMINX_COLORS,
|
|
316
|
+
...colorScheme
|
|
317
|
+
}));
|
|
318
|
+
};
|
|
319
|
+
//#endregion
|
|
320
|
+
export { renderMegaminxIsometricState };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MegaminxFace } from "../../../scramble-puzzle/src/megaminx/megaminx-parser.mjs";
|
|
2
|
+
import { MegaminxState } from "../../../scramble-puzzle/src/megaminx/megaminx-state.mjs";
|
|
3
|
+
import { HexColor } from "../color.mjs";
|
|
4
|
+
|
|
5
|
+
//#region .build/vendor/scramble-image/src/renderers/megaminx.d.ts
|
|
6
|
+
type MegaminxColorScheme = Partial<Record<MegaminxFace, HexColor>>;
|
|
7
|
+
declare const renderMegaminxState: (state: MegaminxState, colorScheme?: MegaminxColorScheme) => string;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { MegaminxColorScheme, renderMegaminxState };
|