MCPcopy Create free account
hub / github.com/AmazingAng/PolyWorld / offsetColocated

Function offsetColocated

src/components/WorldMap.tsx:161–202  ·  view source on GitHub ↗
(markets: ProcessedMarket[])

Source from the content-addressed store, hash-verified

159// Uses FIXED geographic offsets — zoom-in naturally separates bubbles via map projection.
160// No zoom dependency: avoids the "separate then collapse" problem of recalculating on zoom.
161function offsetColocated(markets: ProcessedMarket[]): ProcessedMarket[] {
162 // Group nearby markets using a grid with 0.5° cells
163 const cellSize = 0.5;
164 const groups = new Map<string, ProcessedMarket[]>();
165 for (const m of markets) {
166 if (!m.coords) continue;
167 const key = `${Math.floor(m.coords[0] / cellSize)},${Math.floor(m.coords[1] / cellSize)}`;
168 const arr = groups.get(key) || [];
169 arr.push(m);
170 groups.set(key, arr);
171 }
172
173 const goldenAngle = Math.PI * (3 - Math.sqrt(5));
174
175 const result: ProcessedMarket[] = [];
176 for (const m of markets) {
177 if (!m.coords) {
178 result.push(m);
179 continue;
180 }
181 const key = `${Math.floor(m.coords[0] / cellSize)},${Math.floor(m.coords[1] / cellSize)}`;
182 const group = groups.get(key)!;
183 if (group.length <= 1) {
184 result.push(m);
185 continue;
186 }
187 const idx = group.indexOf(m);
188 // Tighter spacing to keep bubbles near their country centroid.
189 const spacing = group.length > 50 ? 0.4 : group.length > 15 ? 0.3 : group.length > 5 ? 0.2 : 0.15;
190 // Start from idx+1 so first item is NOT at center (avoids pile-up at origin)
191 const n = idx + 1;
192 const angle = n * goldenAngle;
193 const r = spacing * Math.sqrt(n);
194 const offsetLat = r * Math.cos(angle);
195 const offsetLng = r * Math.sin(angle);
196 result.push({
197 ...m,
198 coords: [m.coords[0] + offsetLat, m.coords[1] + offsetLng] as [number, number],
199 });
200 }
201 return result;
202}
203
204function setsEqual<T>(a?: Set<T>, b?: Set<T>): boolean {
205 if (a === b) return true;

Callers 1

WorldMapInnerFunction · 0.85

Calls 2

getMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected