spacr.ops_solve¶
Absolute tile positions from the pairwise displacements one well produced.
spacr.ops_layout determines which tiles touch,
spacr.ops_register measures how far apart a touching pair is, and
this module computes where every tile ends up. It is kept separate from both
because ops_layout is pure geometry that imports only math and
should stay importable anywhere, and ops_register handles only two tiles
and one shift at a time.
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.
Positions come from a least-squares solve, not a walk along the edges. 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