/
Alcatraz
/
Wagomon
Обзор
Документация
Войти
/
Alcatraz
/
Wagomon
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/lib/visualization/layout.js
116 строк
3 KB
saitgalineu
vkr
26 май 2026, 10:08
26 май 2026, 10:08
f9b2919
Код
Авторство
О чём код?
export const GRID_COLS = 12; export const GRID_GAP = 12; export const GRID_ROW_HEIGHT = 140; export const MIN_GRID_ROWS = 8; /** * * * * @param {Array<{ x: number, y: number, w: number, h: number }>} sensors * @returns {{ x: number, y: number }} */ export function findFreePositionForSensors(sensors) { const list = Array.isArray(sensors) ? sensors : []; const occupied = new Set(); for (const s of list) { const yStart = Number(s?.y) || 0; const xStart = Number(s?.x) || 0; const h = Number(s?.h) || 0; const w = Number(s?.w) || 0; for (let row = yStart; row < yStart + h; row++) { for (let col = xStart; col < xStart + w; col++) { occupied.add(`${row}-${col}`); } } } const currentBottom = list.reduce( (max, s) => Math.max(max, (Number(s?.y) || 0) + (Number(s?.h) || 0)), 0 ); const searchRows = Math.max(MIN_GRID_ROWS, currentBottom + 3); const widgetH = 3; const widgetW = 4; for (let row = 0; row <= searchRows - widgetH; row++) { for (let col = 0; col <= GRID_COLS - widgetW; col++) { let free = true; for (let r = row; r < row + widgetH; r++) { for (let c = col; c < col + widgetW; c++) { if (occupied.has(`${r}-${c}`)) { free = false; break; } } if (!free) break; } if (free) return { x: col, y: row }; } } return { x: 0, y: Math.max(MIN_GRID_ROWS, currentBottom) }; } /** * * @param {{ x: number, y: number, w: number, h: number }} a * @param {{ x: number, y: number, w: number, h: number }} b */ export function rectsOverlap(a, b) { if (!a || !b) return false; return ( a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y ); } /** * * * * @param {Array<{ x: number, y: number, w: number, h: number }>} sensors * @param {number} activeIndex * @returns {Array<{ x: number, y: number, w: number, h: number }>} */ export function resolveCollisionsForSensors(sensors, activeIndex) { const next = (sensors || []).map((s) => ({ ...s })); const maxPasses = next.length * next.length + 50; let passes = 0; let changed = true; while (changed && passes < maxPasses) { passes++; changed = false; const order = next .map((_, i) => i) .sort((i, j) => { if (i === activeIndex && j !== activeIndex) return -1; if (j === activeIndex && i !== activeIndex) return 1; return next[i].y - next[j].y || next[i].x - next[j].x; }); for (const i of order) { for (const j of order) { if (i === j) continue; const a = next[i]; const b = next[j]; if (!rectsOverlap(a, b)) continue; const newY = a.y + a.h; if (b.y !== newY) { b.y = newY; changed = true; } } } } return next; }