spacr.ops_solve¶
Absolute tile positions from the pairwise displacements one well produced.
THE THIRD VERB. spacr.ops_layout says which tiles touch,
spacr.ops_register says how far apart a touching pair is, and this
says where every tile ends up. Kept separate from both because
ops_layout is pure geometry that imports only math and should
stay importable anywhere, and ops_register’s whole subject is two tiles
and one shift.
Functions¶
|
Absolute tile positions from the pairwise displacements. |
Module Contents¶
- spacr.ops_solve.solve_placements(edges: Dict[Tuple[int, int], Tuple[float, float]], sites: List[int]) Dict[int, Tuple[float, float]][source]¶
Absolute tile positions from the pairwise displacements.
A LEAST-SQUARES SOLVE, NOT A WALK. Chaining placements from a seed gives every tile the accumulated error of whatever path reached it, and on a round well the paths are long; solving all the edges at once spreads the residual instead and gives one answer no matter which tile is called the origin.
The origin is pinned to the lowest-numbered site of each connected component, so a well that registers in two pieces still returns both rather than failing – the caller can see the components in the result and say so.
- Parameters:
edges –
(a, b) -> (dy, dx), b’s position minus a’s.sites – every site to place, including any with no edge.
- Returns:
site -> (y, x)in pixels, one component pinned at the origin and the others pinned at their own lowest site.
Nested helpers¶
- solve_placements.find(node: int) int¶
The representative of
node’s component, path-compressed.- Parameters:
node – a tile index.
- Returns:
the index that stands for its connected component.
Halving as it walks –
parent[node] = parent[parent[node]]– so a long chain costs its length once rather than on every later lookup. The components are what decide where the pins go, and a component that is found twice under two names puts two pins in one place and leaves another with none.spacr/ops_solve.py:59