git-hash-art 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.
@@ -0,0 +1,93 @@
1
+ export const drawCircle = (ctx, size) => {
2
+ ctx.beginPath();
3
+ ctx.arc(0, 0, size / 2, 0, Math.PI * 2);
4
+ };
5
+
6
+ export const drawSquare = (ctx, size) => {
7
+ ctx.beginPath();
8
+ ctx.rect(-size / 2, -size / 2, size, size);
9
+ };
10
+
11
+ export const drawTriangle = (ctx, size) => {
12
+ ctx.beginPath();
13
+ ctx.moveTo(0, -size / 2);
14
+ ctx.lineTo(-size / 2, size / 2);
15
+ ctx.lineTo(size / 2, size / 2);
16
+ ctx.closePath();
17
+ };
18
+
19
+ export const drawHexagon = (ctx, size) => {
20
+ ctx.beginPath();
21
+ for (let i = 0; i < 6; i++) {
22
+ const angle = (Math.PI / 8) * i;
23
+ const x = (size / 2) * Math.cos(angle);
24
+ const y = (size / 2) * Math.sin(angle);
25
+ if (i === 0) ctx.moveTo(x, y);
26
+ else ctx.lineTo(x, y);
27
+ }
28
+ ctx.closePath();
29
+ };
30
+
31
+ export const drawStar = (ctx, size) => {
32
+ ctx.beginPath();
33
+ for (let i = 0; i < 10; i++) {
34
+ const angle = Math.PI / 5 + (Math.PI / 5) * i * 3;
35
+ const radius = i % 2 === 0 ? size / 2 : size / 4;
36
+ const x = radius * Math.cos(angle);
37
+ const y = radius * Math.sin(angle);
38
+ if (i === 0) ctx.moveTo(x, y);
39
+ else ctx.lineTo(x, y);
40
+ }
41
+ ctx.closePath();
42
+ };
43
+
44
+ export const drawJackedStar = (ctx, size) => {
45
+ ctx.beginPath();
46
+ for (let i = 0; i < 10; i++) {
47
+ const angle = Math.PI / 30 + (Math.PI / 30) * i * 8;
48
+ const radius = i % 2 === 0 ? size / 2 : size / 8;
49
+ const x = radius * Math.cos(angle);
50
+ const y = radius * Math.sin(angle);
51
+ if (i === 0) ctx.moveTo(x, y);
52
+ else ctx.lineTo(x, y);
53
+ }
54
+ ctx.closePath();
55
+ };
56
+
57
+ export const drawHeart = (ctx, size) => {
58
+ ctx.beginPath();
59
+ ctx.moveTo(0, size / 4);
60
+ ctx.quadraticCurveTo(size / 2, size / 4, 0, -size / 4);
61
+ ctx.quadraticCurveTo(-size / 2, size / 4, 0, size / 4);
62
+ };
63
+
64
+ export const drawDiamond = (ctx, size) => {
65
+ ctx.beginPath();
66
+ ctx.moveTo(0, -size / 2);
67
+ ctx.lineTo(size / 2, 0);
68
+ ctx.lineTo(0, size / 2);
69
+ ctx.lineTo(-size / 2, 0);
70
+ ctx.closePath();
71
+ };
72
+
73
+ export const drawCube = (ctx, size) => {
74
+ ctx.beginPath();
75
+ ctx.moveTo(-size / 2, -size / 2);
76
+ ctx.lineTo(size / 2, -size / 2);
77
+ ctx.lineTo(size / 2, size / 2);
78
+ ctx.lineTo(-size / 2, size / 2);
79
+ ctx.closePath();
80
+ };
81
+
82
+ // Optional: Create a shape map for easier lookup
83
+ export const basicShapes = {
84
+ circle: drawCircle,
85
+ square: drawSquare,
86
+ triangle: drawTriangle,
87
+ hexagon: drawHexagon,
88
+ star: drawStar,
89
+ "jacked-star": drawJackedStar,
90
+ heart: drawHeart,
91
+ diamond: drawDiamond,
92
+ cube: drawCube
93
+ };
@@ -0,0 +1,205 @@
1
+ import { defaultShapeConfig } from "../../constants";
2
+ import { applyTransforms, createCirclePoints, restoreContext } from "./utils";
3
+
4
+ export const ShapeConfigs = {
5
+ platonic: {
6
+ tetrahedron: { vertices: 4, faces: 4 },
7
+ cube: { vertices: 8, faces: 6 },
8
+ octahedron: { vertices: 6, faces: 8 },
9
+ dodecahedron: { vertices: 20, faces: 12 },
10
+ icosahedron: { vertices: 12, faces: 20 },
11
+ },
12
+ fibonacci: {
13
+ iterations: 13,
14
+ growthFactor: 1.618034, // Golden ratio
15
+ },
16
+ goldenRatio: {
17
+ iterations: 8,
18
+ ratio: 1.618034,
19
+ },
20
+ };
21
+
22
+ export const drawPlatonicSolid = (ctx, size, type, config = {}) => {
23
+ const finalConfig = { ...defaultShapeConfig, ...config };
24
+ applyTransforms(ctx, size, finalConfig);
25
+
26
+ const {
27
+ vertices,
28
+ // faces
29
+ } = ShapeConfigs.platonic[type];
30
+ const radius = size / 2;
31
+
32
+ // Calculate vertices based on platonic solid type
33
+ const points = createCirclePoints(0, 0, radius, vertices);
34
+
35
+ ctx.beginPath();
36
+ // Draw edges between vertices
37
+ points.forEach((p1, i) => {
38
+ points.slice(i + 1).forEach((p2) => {
39
+ ctx.moveTo(p1.x, p1.y);
40
+ ctx.lineTo(p2.x, p2.y);
41
+ });
42
+ });
43
+
44
+ if (finalConfig.fillStyle !== "transparent") {
45
+ ctx.fill();
46
+ }
47
+ ctx.stroke();
48
+ restoreContext(ctx);
49
+ };
50
+
51
+ export const drawFibonacciSpiral = (ctx, size, config = {}) => {
52
+ const finalConfig = {
53
+ ...defaultShapeConfig,
54
+ ...ShapeConfigs.fibonacci,
55
+ ...config,
56
+ };
57
+ applyTransforms(ctx, size, finalConfig);
58
+
59
+ let current = 1;
60
+ let previous = 1;
61
+ let scale = size / Math.pow(finalConfig.growthFactor, finalConfig.iterations);
62
+
63
+ ctx.beginPath();
64
+ for (let i = 0; i < finalConfig.iterations; i++) {
65
+ const radius = scale * current;
66
+ const centerX = radius / 2;
67
+ const centerY = radius / 2;
68
+
69
+ ctx.arc(centerX, centerY, radius, Math.PI, Math.PI * 1.5);
70
+
71
+ // Calculate next Fibonacci number
72
+ const next = current + previous;
73
+ previous = current;
74
+ current = next;
75
+
76
+ // Transform for next iteration
77
+ ctx.translate(radius, 0);
78
+ ctx.rotate(Math.PI / 2);
79
+ }
80
+
81
+ ctx.stroke();
82
+ restoreContext(ctx);
83
+ };
84
+
85
+ export const drawIslamicPattern = (ctx, size, config = {}) => {
86
+ const finalConfig = { ...defaultShapeConfig, ...config };
87
+ applyTransforms(ctx, size, finalConfig);
88
+
89
+ const gridSize = 8;
90
+ const unit = size / gridSize;
91
+
92
+ ctx.beginPath();
93
+ // Create base grid
94
+ for (let i = 0; i <= gridSize; i++) {
95
+ for (let j = 0; j <= gridSize; j++) {
96
+ const x = (i - gridSize / 2) * unit;
97
+ const y = (j - gridSize / 2) * unit;
98
+
99
+ // Draw star pattern at each intersection
100
+ const radius = unit / 2;
101
+ for (let k = 0; k < 8; k++) {
102
+ const angle = (k / 8) * Math.PI * 2;
103
+ const x1 = x + Math.cos(angle) * radius;
104
+ const y1 = y + Math.sin(angle) * radius;
105
+ if (k === 0) {
106
+ ctx.moveTo(x1, y1);
107
+ } else {
108
+ ctx.lineTo(x1, y1);
109
+ }
110
+ }
111
+ ctx.closePath();
112
+ }
113
+ }
114
+
115
+ if (finalConfig.fillStyle !== "transparent") {
116
+ ctx.fill();
117
+ }
118
+ ctx.stroke();
119
+ restoreContext(ctx);
120
+ };
121
+
122
+ export const drawCelticKnot = (ctx, size, config = {}) => {
123
+ const finalConfig = { ...defaultShapeConfig, ...config };
124
+ applyTransforms(ctx, size, finalConfig);
125
+
126
+ const gridSize = 4;
127
+ const unit = size / gridSize;
128
+
129
+ const drawKnotSegment = (x, y, type) => {
130
+ ctx.beginPath();
131
+ switch (type) {
132
+ case "over":
133
+ ctx.moveTo(x, y);
134
+ ctx.bezierCurveTo(
135
+ x + unit / 2,
136
+ y,
137
+ x + unit / 2,
138
+ y + unit,
139
+ x + unit,
140
+ y + unit
141
+ );
142
+ break;
143
+ case "under":
144
+ ctx.moveTo(x, y + unit);
145
+ ctx.bezierCurveTo(x + unit / 2, y + unit, x + unit / 2, y, x + unit, y);
146
+ break;
147
+ }
148
+ ctx.stroke();
149
+ };
150
+
151
+ // Create knot pattern
152
+ for (let i = 0; i < gridSize; i++) {
153
+ for (let j = 0; j < gridSize; j++) {
154
+ const x = (i - gridSize / 2) * unit;
155
+ const y = (j - gridSize / 2) * unit;
156
+ drawKnotSegment(x, y, (i + j) % 2 === 0 ? "over" : "under");
157
+ }
158
+ }
159
+
160
+ restoreContext(ctx);
161
+ };
162
+
163
+ export const drawMerkaba = (ctx, size, config = {}) => {
164
+ const finalConfig = { ...defaultShapeConfig, ...config };
165
+ applyTransforms(ctx, size, finalConfig);
166
+
167
+ const radius = size / 2;
168
+
169
+ // Draw two intersecting tetrahedra
170
+ ctx.beginPath();
171
+ // First tetrahedron
172
+ const points1 = createCirclePoints(0, 0, radius, 3);
173
+ points1.forEach((p1, i) => {
174
+ points1.slice(i + 1).forEach((p2) => {
175
+ ctx.moveTo(p1.x, p1.y);
176
+ ctx.lineTo(p2.x, p2.y);
177
+ });
178
+ });
179
+
180
+ // Second tetrahedron (rotated)
181
+ ctx.rotate(Math.PI / 6);
182
+ const points2 = createCirclePoints(0, 0, radius, 3);
183
+ points2.forEach((p1, i) => {
184
+ points2.slice(i + 1).forEach((p2) => {
185
+ ctx.moveTo(p1.x, p1.y);
186
+ ctx.lineTo(p2.x, p2.y);
187
+ });
188
+ });
189
+
190
+ if (finalConfig.fillStyle !== "transparent") {
191
+ ctx.fill();
192
+ }
193
+ ctx.stroke();
194
+ restoreContext(ctx);
195
+ };
196
+
197
+ export const complexShapes = {
198
+ platonicSolid: (ctx, size, type = "tetrahedron", config) =>
199
+ drawPlatonicSolid(ctx, size, type, config),
200
+ fibonacciSpiral: (ctx, size, config) =>
201
+ drawFibonacciSpiral(ctx, size, config),
202
+ islamicPattern: (ctx, size, config) => drawIslamicPattern(ctx, size, config),
203
+ celticKnot: (ctx, size, config) => drawCelticKnot(ctx, size, config),
204
+ merkaba: (ctx, size, config) => drawMerkaba(ctx, size, config),
205
+ };
@@ -0,0 +1,9 @@
1
+ import { basicShapes } from "./basic";
2
+ import { complexShapes } from "./complex";
3
+ import { sacredShapes } from "./sacred";
4
+
5
+ export const shapes = {
6
+ ...basicShapes,
7
+ ...complexShapes,
8
+ ...sacredShapes,
9
+ };
@@ -0,0 +1,173 @@
1
+ import { createCirclePoints } from "./utils";
2
+
3
+ export const drawFlowerOfLife = (ctx, size) => {
4
+ const radius = size / 6;
5
+ const centers = [
6
+ { x: 0, y: 0 },
7
+ { x: radius * Math.sqrt(3), y: 0 },
8
+ { x: radius * Math.sqrt(3) / 2, y: 1.5 * radius },
9
+ { x: -radius * Math.sqrt(3) / 2, y: 1.5 * radius },
10
+ { x: -radius * Math.sqrt(3), y: 0 },
11
+ { x: -radius * Math.sqrt(3) / 2, y: -1.5 * radius },
12
+ { x: radius * Math.sqrt(3) / 2, y: -1.5 * radius }
13
+ ];
14
+
15
+ ctx.beginPath();
16
+ centers.forEach(center => {
17
+ ctx.moveTo(center.x + radius, center.y);
18
+ ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);
19
+ });
20
+ };
21
+
22
+ export const drawTreeOfLife = (ctx, size) => {
23
+ const radius = size / 12;
24
+ const spacing = radius * 2.5;
25
+
26
+ // Sephirot positions (traditional layout)
27
+ const positions = [
28
+ { x: 0, y: -spacing * 2 }, // Kether
29
+ { x: -spacing, y: -spacing }, // Chokmah
30
+ { x: spacing, y: -spacing }, // Binah
31
+ { x: -spacing, y: 0 }, // Chesed
32
+ { x: spacing, y: 0 }, // Geburah
33
+ { x: 0, y: 0 }, // Tiphereth
34
+ { x: -spacing, y: spacing }, // Netzach
35
+ { x: spacing, y: spacing }, // Hod
36
+ { x: 0, y: spacing * 2 }, // Yesod
37
+ { x: 0, y: spacing * 3 } // Malkuth
38
+ ];
39
+
40
+ // Draw circles
41
+ ctx.beginPath();
42
+ positions.forEach(pos => {
43
+ ctx.moveTo(pos.x + radius, pos.y);
44
+ ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);
45
+ });
46
+
47
+ // Draw connecting lines
48
+ ctx.moveTo(positions[0].x, positions[0].y);
49
+ positions.forEach((pos, i) => {
50
+ if (i > 0) {
51
+ positions.slice(i + 1).forEach(nextPos => {
52
+ ctx.moveTo(pos.x, pos.y);
53
+ ctx.lineTo(nextPos.x, nextPos.y);
54
+ });
55
+ }
56
+ });
57
+ };
58
+
59
+ export const drawMetatronsCube = (ctx, size) => {
60
+ const radius = size / 3;
61
+
62
+ // Create 13 points - one center and 12 vertices of an icosahedron
63
+
64
+ // const phi = (1 + Math.sqrt(5)) / 2; // Golden ratio
65
+
66
+ const vertices = [
67
+ { x: 0, y: 0 }, // Center point
68
+ ...createCirclePoints(0, 0, radius, 6), // Inner hexagon
69
+ ...createCirclePoints(0, 0, radius * 1.5, 6) // Outer hexagon
70
+ ];
71
+
72
+ ctx.beginPath();
73
+ // Draw all connecting lines
74
+ vertices.forEach((v1, i) => {
75
+ vertices.slice(i + 1).forEach(v2 => {
76
+ ctx.moveTo(v1.x, v1.y);
77
+ ctx.lineTo(v2.x, v2.y);
78
+ });
79
+ });
80
+ };
81
+
82
+ export const drawSriYantra = (ctx, size) => {
83
+ const radius = size / 2;
84
+ ctx.beginPath();
85
+
86
+ // Draw outer triangles
87
+ for (let i = 0; i < 9; i++) {
88
+ const angle = (i / 9) * Math.PI * 2;
89
+ const x1 = Math.cos(angle) * radius;
90
+ const y1 = Math.sin(angle) * radius;
91
+ const x2 = Math.cos(angle + Math.PI / 9) * radius;
92
+ const y2 = Math.sin(angle + Math.PI / 9) * radius;
93
+
94
+ ctx.moveTo(0, 0);
95
+ ctx.lineTo(x1, y1);
96
+ ctx.lineTo(x2, y2);
97
+ ctx.lineTo(0, 0);
98
+ }
99
+
100
+ // Draw inner triangles
101
+ const innerRadius = radius * 0.6;
102
+ for (let i = 0; i < 9; i++) {
103
+ const angle = (i / 9) * Math.PI * 2 + Math.PI / 18;
104
+ const x1 = Math.cos(angle) * innerRadius;
105
+ const y1 = Math.sin(angle) * innerRadius;
106
+ const x2 = Math.cos(angle + Math.PI / 9) * innerRadius;
107
+ const y2 = Math.sin(angle + Math.PI / 9) * innerRadius;
108
+
109
+ ctx.moveTo(0, 0);
110
+ ctx.lineTo(x1, y1);
111
+ ctx.lineTo(x2, y2);
112
+ ctx.lineTo(0, 0);
113
+ }
114
+ };
115
+
116
+ export const drawSeedOfLife = (ctx, size) => {
117
+ const radius = size / 4;
118
+ const centers = [
119
+ { x: 0, y: 0 },
120
+ ...createCirclePoints(0, 0, radius * 2, 6)
121
+ ];
122
+
123
+ ctx.beginPath();
124
+ centers.forEach(center => {
125
+ ctx.moveTo(center.x + radius, center.y);
126
+ ctx.arc(center.x, center.y, radius, 0, Math.PI * 2);
127
+ });
128
+ };
129
+
130
+ export const drawVesicaPiscis = (ctx, size) => {
131
+ const radius = size / 3;
132
+ ctx.beginPath();
133
+
134
+ // Draw two overlapping circles
135
+ ctx.arc(-radius/2, 0, radius, 0, Math.PI * 2);
136
+ ctx.arc(radius/2, 0, radius, 0, Math.PI * 2);
137
+ };
138
+
139
+ export const drawTorus = (ctx, size) => {
140
+ const outerRadius = size / 2;
141
+ const innerRadius = size / 4;
142
+ const steps = 36;
143
+
144
+ ctx.beginPath();
145
+ for (let i = 0; i < steps; i++) {
146
+ const angle1 = (i / steps) * Math.PI * 2;
147
+ // const angle2 = ((i + 1) / steps) * Math.PI * 2;
148
+
149
+ for (let j = 0; j < steps; j++) {
150
+ const phi1 = (j / steps) * Math.PI * 2;
151
+ const phi2 = ((j + 1) / steps) * Math.PI * 2;
152
+
153
+ const x1 = (outerRadius + innerRadius * Math.cos(phi1)) * Math.cos(angle1);
154
+ const y1 = (outerRadius + innerRadius * Math.cos(phi1)) * Math.sin(angle1);
155
+ const x2 = (outerRadius + innerRadius * Math.cos(phi2)) * Math.cos(angle1);
156
+ const y2 = (outerRadius + innerRadius * Math.cos(phi2)) * Math.sin(angle1);
157
+
158
+ ctx.moveTo(x1, y1);
159
+ ctx.lineTo(x2, y2);
160
+ }
161
+ }
162
+ };
163
+
164
+ // Add to the existing shapes map
165
+ export const sacredShapes = {
166
+ // flowerOfLife: drawFlowerOfLife,
167
+ // treeOfLife: drawTreeOfLife,
168
+ metatronsCube: drawMetatronsCube,
169
+ sriYantra: drawSriYantra,
170
+ seedOfLife: drawSeedOfLife,
171
+ vesicaPiscis: drawVesicaPiscis,
172
+ torus: drawTorus
173
+ };
@@ -0,0 +1,37 @@
1
+ export const degToRad = (degrees) => (degrees * Math.PI) / 180;
2
+
3
+ export const applyTransforms = (ctx, size, config) => {
4
+ ctx.save();
5
+ ctx.translate(0, 0);
6
+ if (config.rotation) {
7
+ ctx.rotate(degToRad(config.rotation));
8
+ }
9
+ ctx.lineWidth = config.lineWidth;
10
+ ctx.strokeStyle = config.strokeStyle;
11
+ ctx.fillStyle = config.fillStyle;
12
+ };
13
+
14
+ export const restoreContext = (ctx) => {
15
+ ctx.restore();
16
+ };
17
+
18
+ // Animation configuration stub for future use
19
+ export const createAnimationConfig = (type) => ({
20
+ enabled: false,
21
+ duration: 1000,
22
+ easing: "linear",
23
+ type,
24
+ // Add more animation-specific properties as needed
25
+ });
26
+
27
+ export const createCirclePoints = (cx, cy, radius, segments) => {
28
+ const points = [];
29
+ for (let i = 0; i < segments; i++) {
30
+ const angle = (i / segments) * Math.PI * 2;
31
+ points.push({
32
+ x: cx + Math.cos(angle) * radius,
33
+ y: cy + Math.sin(angle) * radius,
34
+ });
35
+ }
36
+ return points;
37
+ };
@@ -0,0 +1,138 @@
1
+ export const PRESETS = {
2
+ // Standard sizes with different hashes
3
+ react: {
4
+ hash: "46192e59d42f741c761cbea79462a8b3815dd905",
5
+ width: 1024,
6
+ height: 1024,
7
+ },
8
+ angular: {
9
+ hash: "f31a6c3e94420f43c0cd323a5a6a99376ee59ff8",
10
+ width: 1024,
11
+ height: 1024,
12
+ gridSize: 6, // Higher density grid
13
+ },
14
+ // Wide format variations
15
+ banner: {
16
+ hash: "d847ffd4269b22c54d6e85ad3c1892a298e961fb",
17
+ width: 1920,
18
+ height: 480,
19
+ gridSize: 8, // More horizontal cells for wide format
20
+ shapesPerLayer: 40,
21
+ },
22
+ ultrawide: {
23
+ hash: "a3e126e537ed2cd11ddf3a96c37066e97c7afee6",
24
+ width: 3440,
25
+ height: 1440,
26
+ gridSize: 12, // Extra wide needs more cells
27
+ shapesPerLayer: 60,
28
+ },
29
+ // Social media sizes
30
+ "instagram-square": {
31
+ hash: "ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0",
32
+ width: 1080,
33
+ height: 1080,
34
+ },
35
+ "instagram-story": {
36
+ hash: "abc123def456abc123def456abc123def456abc1",
37
+ width: 1080,
38
+ height: 1920,
39
+ gridSize: 6,
40
+ layers: 6,
41
+ },
42
+ "twitter-header": {
43
+ hash: "7777777777777777777777777777777777777777",
44
+ width: 1500,
45
+ height: 500,
46
+ gridSize: 8,
47
+ shapesPerLayer: 35,
48
+ },
49
+ "linkedin-banner": {
50
+ hash: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
51
+ width: 1584,
52
+ height: 396,
53
+ gridSize: 8,
54
+ shapesPerLayer: 35,
55
+ },
56
+ // Mobile sizes
57
+ "phone-wallpaper": {
58
+ hash: "ffffffffffffffffffffffffffffffffaaaaaaaa",
59
+ width: 1170,
60
+ height: 2532, // iPhone 13 Pro size
61
+ gridSize: 5,
62
+ layers: 6,
63
+ },
64
+ "tablet-wallpaper": {
65
+ hash: "123456789abcdef0123456789abcdef012345678",
66
+ width: 2048,
67
+ height: 2732, // iPad Pro size
68
+ gridSize: 7,
69
+ layers: 6,
70
+ },
71
+ // Special configurations
72
+ minimal: {
73
+ hash: "000000000000000000000000000000000fffffff",
74
+ width: 1024,
75
+ height: 1024,
76
+ layers: 3,
77
+ baseOpacity: 0.8,
78
+ shapesPerLayer: 15,
79
+ },
80
+ complex: {
81
+ hash: "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
82
+ width: 2048,
83
+ height: 2048,
84
+ gridSize: 8,
85
+ layers: 7,
86
+ shapesPerLayer: 50,
87
+ minShapeSize: 30,
88
+ maxShapeSize: 250,
89
+ },
90
+ };
91
+
92
+ // Basic configuration that applies to all shapes
93
+ export const defaultShapeConfig = {
94
+ strokeStyle: "#000000",
95
+ fillStyle: "transparent",
96
+ lineWidth: 1,
97
+ rotation: 0,
98
+ iterations: 1,
99
+ animate: false, // For future use
100
+ };
101
+
102
+ // Base configuration types that can be extended per shape
103
+ export const ShapeConfigTypes = {
104
+ BASIC: "basic",
105
+ DETAILED: "detailed",
106
+ ANIMATED: "animated",
107
+ };
108
+
109
+ // Golden ratio and other important proportions
110
+ export const Proportions = {
111
+ GOLDEN_RATIO: 1.618034,
112
+ SQUARE_ROOT_2: Math.sqrt(2),
113
+ SQUARE_ROOT_3: Math.sqrt(3),
114
+ SQUARE_ROOT_5: Math.sqrt(5),
115
+ PI: Math.PI,
116
+ PHI: (1 + Math.sqrt(5)) / 2,
117
+ };
118
+
119
+ // Helper for creating common sacred geometry combinations
120
+ export const PatternPresets = {
121
+ flowerOfLifeMandala: (size) => [
122
+ // { type: "flowerOfLife", config: { size } },
123
+ { type: "merkaba", config: { size: size * 0.8 } },
124
+ { type: "sriYantra", config: { size: size * 0.5 } },
125
+ ],
126
+
127
+ platonicProgression: (size) => [
128
+ { type: "platonicSolid", config: { size, type: "tetrahedron" } },
129
+ { type: "platonicSolid", config: { size: size * 0.8, type: "cube" } },
130
+ { type: "platonicSolid", config: { size: size * 0.6, type: "octahedron" } },
131
+ ],
132
+
133
+ cosmicTree: (size) => [
134
+ // { type: "treeOfLife", config: { size } },
135
+ { type: "fibonacciSpiral", config: { size: size * 0.9 } },
136
+ { type: "metatronsCube", config: { size: size * 0.7 } },
137
+ ],
138
+ };
@@ -0,0 +1,59 @@
1
+ import { shapes } from "./canvas/shapes";
2
+
3
+ export function gitHashToSeed(gitHash) {
4
+ return parseInt(gitHash.slice(0, 8), 16);
5
+ }
6
+
7
+ export function getRandomFromHash(hash, index, min, max) {
8
+ const hexPair = hash.substr((index * 2) % hash.length, 2);
9
+ const decimal = parseInt(hexPair, 16);
10
+ return min + (decimal / 255) * (max - min);
11
+ }
12
+
13
+ // Golden ratio and other important proportions
14
+ export const Proportions = {
15
+ GOLDEN_RATIO: 1.618034,
16
+ SQUARE_ROOT_2: Math.sqrt(2),
17
+ SQUARE_ROOT_3: Math.sqrt(3),
18
+ SQUARE_ROOT_5: Math.sqrt(5),
19
+ PI: Math.PI,
20
+ PHI: (1 + Math.sqrt(5)) / 2,
21
+ };
22
+
23
+ // Pattern combination utilities
24
+ export class PatternCombiner {
25
+ static getProportionalSize(baseSize, proportion) {
26
+ return baseSize * proportion;
27
+ }
28
+
29
+ static centerPattern(ctx, width, height) {
30
+ ctx.translate(width / 2, height / 2);
31
+ }
32
+
33
+ // Combines sacred geometry patterns with proper proportions
34
+ static layerPatterns(ctx, patterns, config) {
35
+ const {
36
+ baseSize,
37
+ baseOpacity = 0.6,
38
+ opacityReduction = 0.1,
39
+ rotationOffset = 0,
40
+ proportionType = "GOLDEN_RATIO",
41
+ } = config;
42
+
43
+ patterns.forEach((pattern, index) => {
44
+ const size = this.getProportionalSize(
45
+ baseSize,
46
+ Math.pow(Proportions[proportionType], index)
47
+ );
48
+ const opacity = Math.max(0.1, baseOpacity - index * opacityReduction);
49
+ const rotation = rotationOffset * index;
50
+
51
+ ctx.save();
52
+ ctx.globalAlpha = opacity;
53
+ ctx.rotate((rotation * Math.PI) / 180);
54
+
55
+ shapes[pattern.type](ctx, size, pattern.config);
56
+ ctx.restore();
57
+ });
58
+ }
59
+ }