@buley/hexgrid-3d 1.0.0
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/.eslintrc.json +28 -0
- package/LICENSE +39 -0
- package/README.md +291 -0
- package/examples/basic-usage.tsx +52 -0
- package/package.json +65 -0
- package/public/hexgrid-worker.js +1763 -0
- package/rust/Cargo.toml +41 -0
- package/rust/src/lib.rs +740 -0
- package/rust/src/math.rs +574 -0
- package/rust/src/spatial.rs +245 -0
- package/rust/src/statistics.rs +496 -0
- package/src/HexGridEnhanced.ts +16 -0
- package/src/Snapshot.ts +1402 -0
- package/src/adapters.ts +65 -0
- package/src/algorithms/AdvancedStatistics.ts +328 -0
- package/src/algorithms/BayesianStatistics.ts +317 -0
- package/src/algorithms/FlowField.ts +126 -0
- package/src/algorithms/FluidSimulation.ts +99 -0
- package/src/algorithms/GraphAlgorithms.ts +184 -0
- package/src/algorithms/OutlierDetection.ts +391 -0
- package/src/algorithms/ParticleSystem.ts +85 -0
- package/src/algorithms/index.ts +13 -0
- package/src/compat.ts +96 -0
- package/src/components/HexGrid.tsx +31 -0
- package/src/components/NarrationOverlay.tsx +221 -0
- package/src/components/index.ts +2 -0
- package/src/features.ts +125 -0
- package/src/index.ts +30 -0
- package/src/math/HexCoordinates.ts +15 -0
- package/src/math/Matrix4.ts +35 -0
- package/src/math/Quaternion.ts +37 -0
- package/src/math/SpatialIndex.ts +114 -0
- package/src/math/Vector3.ts +69 -0
- package/src/math/index.ts +11 -0
- package/src/note-adapter.ts +124 -0
- package/src/ontology-adapter.ts +77 -0
- package/src/stores/index.ts +1 -0
- package/src/stores/uiStore.ts +85 -0
- package/src/types/index.ts +3 -0
- package/src/types.ts +152 -0
- package/src/utils/image-utils.ts +25 -0
- package/src/wasm/HexGridWasmWrapper.ts +753 -0
- package/src/wasm/index.ts +7 -0
- package/src/workers/hexgrid-math.ts +177 -0
- package/src/workers/hexgrid-worker.worker.ts +1807 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure mathematical functions for hexgrid calculations.
|
|
3
|
+
* These functions have NO side effects, NO logging, and NO mutable state access.
|
|
4
|
+
* They are deterministic and testable in isolation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Calculate the bounding box of a set of 2D/3D positions.
|
|
9
|
+
* @pure - No side effects, deterministic
|
|
10
|
+
* @param positions Array of [x, y, z] coordinates
|
|
11
|
+
* @returns Object with min/max bounds and dimensions
|
|
12
|
+
*/
|
|
13
|
+
export function getGridBounds(positions: [number, number, number][]) {
|
|
14
|
+
if (!positions || positions.length === 0) {
|
|
15
|
+
return { minX: 0, maxX: 0, minY: 0, maxY: 0, width: 0, height: 0 }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let minX = Infinity,
|
|
19
|
+
maxX = -Infinity,
|
|
20
|
+
minY = Infinity,
|
|
21
|
+
maxY = -Infinity
|
|
22
|
+
|
|
23
|
+
for (const p of positions) {
|
|
24
|
+
if (!p) continue
|
|
25
|
+
minX = Math.min(minX, p[0])
|
|
26
|
+
maxX = Math.max(maxX, p[0])
|
|
27
|
+
minY = Math.min(minY, p[1])
|
|
28
|
+
maxY = Math.max(maxY, p[1])
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { minX, maxX, minY, maxY, width: maxX - minX, height: maxY - minY }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Calculate Euclidean distance between two 3D points with optional spherical wrapping.
|
|
36
|
+
* @pure - No side effects, deterministic
|
|
37
|
+
* @param a First point [x, y, z]
|
|
38
|
+
* @param b Second point [x, y, z]
|
|
39
|
+
* @param bounds Grid bounds for spherical calculation
|
|
40
|
+
* @param isSpherical Whether to apply spherical wrapping (toroidal distance)
|
|
41
|
+
* @returns Euclidean distance
|
|
42
|
+
*/
|
|
43
|
+
export function distanceBetween(
|
|
44
|
+
a: [number, number, number],
|
|
45
|
+
b: [number, number, number],
|
|
46
|
+
bounds: { width: number; height: number },
|
|
47
|
+
isSpherical: boolean
|
|
48
|
+
): number {
|
|
49
|
+
let dx = b[0] - a[0]
|
|
50
|
+
let dy = b[1] - a[1]
|
|
51
|
+
|
|
52
|
+
if (isSpherical && bounds.width > 0 && bounds.height > 0) {
|
|
53
|
+
// Apply toroidal wrapping: shortest distance considering wraparound
|
|
54
|
+
if (Math.abs(dx) > bounds.width / 2) {
|
|
55
|
+
dx = dx > 0 ? dx - bounds.width : dx + bounds.width
|
|
56
|
+
}
|
|
57
|
+
if (Math.abs(dy) > bounds.height / 2) {
|
|
58
|
+
dy = dy > 0 ? dy - bounds.height : dy + bounds.height
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return Math.sqrt(dx * dx + dy * dy)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Calculate UV texture coordinates for a tile based on its grid position.
|
|
67
|
+
* @pure - No side effects, deterministic
|
|
68
|
+
* @param gridCol Column index (0-based)
|
|
69
|
+
* @param gridRow Row index (0-based)
|
|
70
|
+
* @param tilesX Total number of columns in texture grid
|
|
71
|
+
* @param tilesY Total number of rows in texture grid
|
|
72
|
+
* @returns [minU, minV, maxU, maxV] in range [0, 1]
|
|
73
|
+
*
|
|
74
|
+
* Note: V=1.0 represents the top of the texture.
|
|
75
|
+
* Row 0 maps to top, so maxV=1 and minV=1-1/tilesY.
|
|
76
|
+
*/
|
|
77
|
+
export function calculateUvBoundsFromGridPosition(
|
|
78
|
+
gridCol: number,
|
|
79
|
+
gridRow: number,
|
|
80
|
+
tilesX: number,
|
|
81
|
+
tilesY: number
|
|
82
|
+
): [number, number, number, number] {
|
|
83
|
+
// Guard against invalid grid dimensions
|
|
84
|
+
if (tilesX <= 0 || tilesY <= 0) {
|
|
85
|
+
return [0, 0, 1, 1]
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const minU = gridCol / tilesX
|
|
89
|
+
const maxU = (gridCol + 1) / tilesX
|
|
90
|
+
// V=1 is top, so row 0 maps to top (maxV=1, minV=1-1/tilesY)
|
|
91
|
+
const minV = 1 - (gridRow + 1) / tilesY
|
|
92
|
+
const maxV = 1 - gridRow / tilesY
|
|
93
|
+
|
|
94
|
+
return [minU, minV, maxU, maxV]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Calculate contiguity score between indices (internal connectivity).
|
|
99
|
+
* Higher score means more indices in the set are neighbors with each other.
|
|
100
|
+
* @pure - No side effects, deterministic
|
|
101
|
+
* @param indices Set of position indices to measure
|
|
102
|
+
* @param positions Array of all positions
|
|
103
|
+
* @param hexRadius Radius for neighbor detection
|
|
104
|
+
* @param getNeighbors Function to get neighbors for an index (dependency injection)
|
|
105
|
+
* @returns Sum of neighbor connections within the set
|
|
106
|
+
*/
|
|
107
|
+
export function calculateContiguity(
|
|
108
|
+
indices: number[],
|
|
109
|
+
positions: [number, number, number][],
|
|
110
|
+
hexRadius: number,
|
|
111
|
+
getNeighbors: (index: number) => number[]
|
|
112
|
+
): number {
|
|
113
|
+
if (!indices || indices.length === 0) return 0
|
|
114
|
+
if (!positions || positions.length === 0) return 0
|
|
115
|
+
if (hexRadius <= 0) return 0
|
|
116
|
+
|
|
117
|
+
const set = new Set(indices)
|
|
118
|
+
let total = 0
|
|
119
|
+
|
|
120
|
+
for (const idx of indices) {
|
|
121
|
+
const neighbors = getNeighbors(idx)
|
|
122
|
+
for (const n of neighbors) {
|
|
123
|
+
if (set.has(n)) total++
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return total
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Calculate contiguity score for a photo's indices.
|
|
132
|
+
* @pure - No side effects, deterministic
|
|
133
|
+
* @param indices Indices belonging to a photo
|
|
134
|
+
* @param positions Array of all positions
|
|
135
|
+
* @param hexRadius Radius for neighbor detection
|
|
136
|
+
* @param getNeighbors Function to get neighbors for an index
|
|
137
|
+
* @returns Total contiguity score
|
|
138
|
+
*/
|
|
139
|
+
export function calculatePhotoContiguity(
|
|
140
|
+
indices: number[],
|
|
141
|
+
positions: [number, number, number][],
|
|
142
|
+
hexRadius: number,
|
|
143
|
+
getNeighbors: (index: number) => number[]
|
|
144
|
+
): number {
|
|
145
|
+
return calculateContiguity(indices, positions, hexRadius, getNeighbors)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Calculate contiguity after a hypothetical swap of two indices.
|
|
150
|
+
* @pure - No side effects, deterministic
|
|
151
|
+
* @param indices Current indices
|
|
152
|
+
* @param positions Array of all positions
|
|
153
|
+
* @param hexRadius Radius for neighbor detection
|
|
154
|
+
* @param fromIndex Index to swap from
|
|
155
|
+
* @param toIndex Index to swap to
|
|
156
|
+
* @param getNeighbors Function to get neighbors for an index
|
|
157
|
+
* @returns Contiguity score after swap
|
|
158
|
+
*/
|
|
159
|
+
export function calculateSwappedContiguity(
|
|
160
|
+
indices: number[],
|
|
161
|
+
positions: [number, number, number][],
|
|
162
|
+
hexRadius: number,
|
|
163
|
+
fromIndex: number,
|
|
164
|
+
toIndex: number,
|
|
165
|
+
getNeighbors: (index: number) => number[]
|
|
166
|
+
): number {
|
|
167
|
+
if (!indices || indices.length === 0) return 0
|
|
168
|
+
|
|
169
|
+
const tempIndices = [...indices]
|
|
170
|
+
const fromPos = tempIndices.indexOf(fromIndex)
|
|
171
|
+
const toPos = tempIndices.indexOf(toIndex)
|
|
172
|
+
|
|
173
|
+
if (fromPos !== -1) tempIndices[fromPos] = toIndex
|
|
174
|
+
if (toPos !== -1) tempIndices[toPos] = fromIndex
|
|
175
|
+
|
|
176
|
+
return calculatePhotoContiguity(tempIndices, positions, hexRadius, getNeighbors)
|
|
177
|
+
}
|