gestion_table_tournante_libre/src/geometrie/designation.js

76 lines
3.2 KiB
JavaScript
Raw Normal View History

// © 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));
}