// © 2026 TechnoLibre (http://www.technolibre.ca) // License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) // La désignation d'un siège (§ 7.3, § 14.10) : ce que contient un point de // dessin, lu sur les géométries de tables.js, celles mêmes que le dessin pose. // Le dépôt d'un glissement ne cherche pas sa cible dans le DOM : il convertit // le point en coordonnées de dessin et le passe à designer. /** Taille d'écran minimale d'une cible de siège, en px (§ 7.3). */ export const CIBLE_MIN_PX = 24; // Vrai quand le point est dans le disque (ronde) ou le carré aux côtés // parallèles aux axes (carrée) de demi-taille donnée, centré sur la table, // bord compris. function dans(point, { centre, forme }, demiTaille) { const dx = point.x - centre.x; const dy = point.y - centre.y; return forme === 'ronde' ? Math.hypot(dx, dy) <= demiTaille : Math.max(Math.abs(dx), Math.abs(dy)) <= demiTaille; } /** * Régime des cibles d'une table au zoom k : 'sieges' quand k × pas ≥ * CIBLE_MIN_PX, 'table' sinon. Le seuil se décide table par table, sur le * pas de chacune. * * @param {number} k px/cm * @param {import('./tables.js').GeometrieTable} geometrie * @returns {'sieges'|'table'} */ export function regimeCibles(k, geometrie) { return k * geometrie.pas >= CIBLE_MIN_PX ? 'sieges' : 'table'; } /** * Ce que désigne un point de dessin au zoom k. * * Les tables s'examinent de la dernière reçue à la première, l'ordre inverse * de la peinture : la première dont la surface peinte contient le point * décide. En régime table, la surface est l'emprise — disque d'une ronde, * carré d'une carrée — et la table est désignée. En régime sièges, elle est * le plateau et les chaises : un point dans une chaise désigne son siège ; * un point sur le plateau ne désigne rien, et cache les chaises des tables * peintes dessous ; entre les chaises, le point passe aux tables de dessous. * Deux chaises d'une même table ne se recouvrent pas. * * @param {{x: number, y: number}} point cm * @param {import('./tables.js').GeometrieTable[]} geometries dans l'ordre du dessin * @param {number} k px/cm * @returns {{table: number, siege: number}|{table: number}|null} */ export function designer(point, geometries, k) { for (let i = geometries.length - 1; i >= 0; i -= 1) { const geometrie = geometries[i]; if (regimeCibles(k, geometrie) === 'table') { if (dans(point, geometrie, geometrie.rayonEmprise)) return { table: geometrie.id }; continue; } const chaise = geometrie.chaises.find((c) => Math.hypot(point.x - c.x, point.y - c.y) <= c.rayon); if (chaise !== undefined) return { table: geometrie.id, siege: chaise.siege }; if (dans(point, geometrie, geometrie.demiTaille)) return null; } return null; } /** * Vrai quand le point n'est dans l'emprise — disque ou carré — d'aucune * table : le sol, où un dépôt retire la personne du tour. * * @param {{x: number, y: number}} point cm * @param {import('./tables.js').GeometrieTable[]} geometries * @returns {boolean} */ export function surLeSol(point, geometries) { return !geometries.some((geometrie) => dans(point, geometrie, geometrie.rayonEmprise)); }