Dev Investigation Notes

How to recover the original snap interval from coordinate data with no recorded grid size

This is a translated article. Read the original in Korean ↗

In formation, a web app that overlays a grid on dance practice videos and lets users mark dancer positions at different times to edit formations and movement paths, the task was to align choreography data for 12 dancers across 83 keyframes to a grid. But the coordinate file had no record of the grid size originally used — it was an older format containing only an array of numbers, so the grid setting itself was gone.

Conclusion

If coordinates "roughly" fit a grid but don't line up exactly, and the grid size isn't recorded in the file, you can reverse-engineer it by trying candidate grid sizes and comparing how closely the points align with grid lines (the fit rate). When doing this, check not just a "full-cell" grid but also a half-cell grid (a grid that includes both lines and cell centers). In this case, the full-cell grid had a 55% fit rate, while the half-cell grid reached 91% — the grid with half the spacing was the actual answer .

오차·적합률 계산법: 좌표를 후보 격자 간격(step)으로 나눈 나머지를 구해, 가장 가까운 격자선까지의
거리로 바꾼다(나머지가 step/2보다 크면 step에서 뺀 값을 쓴다). 이 거리를 step 대비 비율로 정규화한
게 "오차"(0~50%)다. 오차가 허용오차(예: step의 10% 이내) 안에 드는 점의 비율이 "적합률"이다 —
허용오차를 좁게 잡을수록 맞는 후보와 틀린 후보의 적합률 격차가 커져 구분이 쉬워진다.

격자 정의: cell = gridSize × (w/800)
화면 gridSize=50 기준 정규화 간격: 가로 0.0625 / 세로 0.1111 [S:dae2585f#24][S:dae2585f#25]

1차 실측(전체 칸 격자): x 중앙값 4% · y 중앙값 7% 벗어남 → 격자 기반은 맞는데 딱 맞진 않음 [S:dae2585f#27]
2차 실측(반 칸 격자): 91% 적합 (전체 칸은 55%) → 반 칸이 실제 격자 [S:dae2585f#28]
gridSize 20~100 전체 스캔 → stepX=0.03125, stepY=0.05556 (gridSize 50의 반 칸)에서 x 90%·y 91% 최적 [S:dae2585f#29][S:dae2585f#30]

Situation

formation also has a live feature: when one leader plays a video, everyone else can connect on their phones and view the video and formation at the same point. But this case came from the step before that — cleaning up coordinates placed in the editor. Both x and y coordinates are stored normalized to 0–1 , and the grid is defined in screen pixels as cell = gridSize × (w/800) . With a video resolution of 1920×1080 (16:9), even grid cells that are square on screen have different spacing in normalized coordinates: 0.0625 horizontally and 0.1111 vertically .

Work was already underway to remove coordinate jitter and snap positions into alignment when a request kicked off the grid investigation: "Can you check the grid size too? I want to arrange the positions on the grid, but right now they're a little crooked and don't line up" .

Symptom

Calculating the grid spacing and measuring the coordinates showed that they weren't completely off (median errors of 4% for x and 7% for y) — the layout was indeed based on a grid, but snapping it directly to full cells would be wrong. Some points clustered around the middle of the cells (half-cell) . Forcing them onto full cells would destroy positions that had intentionally been placed halfway between grid lines.

Cause

Fix

All we had was a suspicion that the layout was grid-based and a set of coordinate numbers with an unknown grid size. So we scanned a broad range of candidate grid sizes to reverse-engineer it statistically.

  1. Measure against the full-cell grid first. Calculate each coordinate's distance from the nearest grid line as an error (using the method above), then examine the median and distribution. In this case, x at 4% and y at 7% signaled that the layout was grid-based, but the fit wasn't exact .
  2. Look for a half-cell bias in the error distribution. If the errors cluster near the middle of a cell (half-cell) rather than near zero, halve the grid size and measure again. The half-cell grid had a 91% fit rate, far ahead of the full-cell grid's 55% .
  3. If the grid size itself is unknown, define a range and scan all of it. In this case, the code confirmed that the editor's slider ranged from 20 to 100, so we scanned that entire range, calculating x and y fit rates for each gridSize (and its half-cell spacing) using the method above. stepX=0.03125, stepY=0.05556 (= half a cell at gridSize 50 = a gridSize 25 grid) gave the best fit, at 90% for x and 91% for y .
  4. Snap every point to the nearest grid point on the recovered grid, and move any two points occupying the same cell to nearby empty cells. All 1034 coordinates landed on grid points, only 7 moved more than 3% of the stage (a maximum of 3.6%), and 6 collisions were resolved by moving points to empty cells .
  5. A follow-up request to "try placing them more densely" led to reducing the grid from gridSize 50→25 (halving the snap interval again) and reapplying it. The maximum movement dropped from 3.6%→1.7%, with zero movements exceeding 3% . Applying the same method to another choreography file (927 coordinates) found that the same grid fit at 98% for x and 93% for y, confirming that the method's success wasn't a coincidence specific to one file .

The key was turning the feeling that "this seems to fit a grid" into a numerical fit rate, and scanning candidates that included multiples and halves of the spacing, alongside full cells. If you simply snap points while assuming you already know the grid size, you can force them into the wrong cells and destroy the intended layout, as would have happened here.

Bonus — an implementation report and actual verification are separate things

Throughout this work, each step produced reports such as "Done" and "All 1034 points landed exactly on grid points" , but this session contains no explicit sign-off from anyone who actually opened the result (the comparison viewer) and visually checked that the grid snapping was correct. The question about overwriting the original file () also went unanswered as the session moved on to another topic (mobile network configuration) . Finding a grid that fits statistically and getting visual confirmation that the result is usable are separate steps.

Reporter's Notes — why the grid was off by half a cell

The four gathered with the grid-snapping work log on screen.

Park Doeun
The request was to align the dancer positions to the grid, but when I ran it, the numbers didn't land exactly on the grid lines. I don't even know the grid size.
Jung Bada
It's not recorded in the file itself? Then can't we just use the on-screen slider's default? It's 50.
Jung Haneul
There's no guarantee that default was the value used during editing. Let's measure how well the coordinates fit that grid first.
Park Doeun
I did. The median deviation is 4% for x and 7% for y. It looks grid-based, but it doesn't fit exactly .
Jung Bada
Then we're good. Can't we just pull everything onto the grid lines by that amount?
Park Dohyun
Hold on. You can only call it "slightly off" if the errors cluster near zero. Where does the distribution cluster?
Park Doeun
That's the strange part. They cluster halfway through the cells (half-cell), near the cell centers rather than the lines .
Jung Haneul
Then let's halve the grid size and measure again. If that fits, it means the original grid used half cells, not full cells.
Park Doeun
With half cells, 91% fit. Full cells were at 55%, so that completely flips the result .
Jung Bada
Wow, so our assumption was wrong. But is that half-cell spacing actually half of gridSize 50? It could be half a cell at some other gridSize.
Park Dohyun
Good point. What's the editor slider's range?
Park Doeun
The code says 20 to 100 ([formation7.html:120]). And it never had snapping while dragging — that's why placing points by eye introduced errors .
Jung Haneul
Then instead of guessing that it's half of 50, we need to scan everything from 20 to 100 and score the fit rate for each.
Park Doeun
I ran it. stepX=0.03125, stepY=0.05556 gives the best fit, at 90% for x and 91% for y. The calculation shows that's exactly half a cell at gridSize 50 — in other words, a gridSize 25 grid .
Jung Bada
So the choreography was laid out using both the lines and cell centers of the on-screen grid at 50, and the positions were slightly off because the editor didn't snap them as they were placed by hand. If we'd gone with my initial suggestion to just force the default, we'd have wrecked all the points placed in the middle.
Park Dohyun
So what mattered was testing all the candidates using numerical fit rates, rather than just feeling that it looked grid-based. If we'd stopped at full cells, we'd have forced points into the wrong cells.
Jung Haneul
I snapped all 1034 points to the recovered grid and moved overlapping ones to empty cells. Only 7 moved more than 3% .
Park Doeun
Shouldn't we check whether the same grid fits another choreography file? If it's just a coincidence with this file, it doesn't mean anything.
Jung Bada
I ran another file (927 coordinates), and the same grid fits at 98% for x and 93% for y. That means it's the right grid, not a coincidence .
Park Dohyun
Good. But has anyone actually looked at the comparison view and confirmed that the result is right?
Park Doeun
...No. We kept reporting "Done," but there's no visual sign-off in the session. The question about overwriting the original went unanswered too, and the conversation moved on .
Jung Haneul
So matching the numbers doesn't mean we're done. Statistically recovering the grid size and confirming that the result is ready to use are completely different steps.