src/services/layout.mjs
BeforeProposed
+22−2
1import {ordered} from '../repositories/labels.mjs';
2import {project} from './projection.mjs';
3import {overlaps, inside} from './geometry.mjs';
14export function layout(data) {
2 // TODO: choose each label's first feasible candidate in priority order.
3 return {placed: [], hidden: data.labels.map(label => label.id)};
5 const occupied = data.obstacles.map(box => ({...box}));
6 const placed = [];
7 const hidden = [];
8 for (const label of ordered(data.labels)) {
9 let selected;
10 for (let index = 0; index < label.offsets.length; index++) {
11 const box = project(label, data.viewport, label.offsets[index]);
12 if (!inside(box, data.viewport) || occupied.some(other => overlaps(box, other))) continue;
13 selected = {id: label.id, offset: index, ...box};
14 break;
15 }
16 if (selected) {
17 placed.push(selected);
18 occupied.push(selected);
19 } else {
20 hidden.push(label.id);
21 }
22 }
23 return {placed, hidden};
424}