Files
moteurs/dist/commun/geometrie.js
T
JulesandClaude Fable 5.1 69809df5d1 LOT P1.0 : paquet @transformer/moteurs v0.1.0
Extraction du cœur autonomie de calculs.trans-former.fr (12 modules, sans
singleton, couplages sans mutation, console derrière debug), découpage en trois
moteurs d'axe + intégrateur (mode global = calculs, mode par_axe = plateforme),
moteurs commun.contexte (Corse 2A/2B, DOM 97x corrigés) et commun.geometrie,
table des coefficients harmonisés (docs/CONSTANTES.md pour Jules, R-7),
validation structurelle des données (schemas/), tests hors ligne : 28 assertions
d'origine + épingle générée depuis le code d'astro-pro + écarts d'harmonisation
figés + contrat des moteurs. dist/ committé.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019UBHYPdeQYy2m1GVJp6b12
2026-09-28 17:06:49 +02:00

80 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// geometrie.ts — moteur `commun.geometrie` : emprise, niveaux, hauteur, pente,
// mitoyenneté → surfaces de parois, SHAB estimée, volume. Reprend les formules
// de `calcSurfaces` du simulateur autoconstruction V1 (calculs), sans le DOM,
// avec les coefficients sortis dans coefficients.ts.
import { Trace } from './contrat.js';
import { COEFFICIENTS } from './coefficients.js';
import { arrondi2 } from './argent.js';
import { VERSION } from '../version.js';
export function calculeGeometrie(entrees, coefficients = COEFFICIENTS) {
const trace = new Trace();
const c = coefficients;
const emprise = Math.max(0, entrees.emprise_m2 || 0);
const niveaux = Math.max(1, Math.round(entrees.niveaux ?? 1));
if (entrees.niveaux == null)
trace.avertit('nombre de niveaux inconnu : 1 niveau supposé');
let hauteur = entrees.hauteur_m ?? 0;
if (!(hauteur > 0)) {
hauteur = niveaux * c.geometrie_hauteur_etage_m.valeur;
trace.avertit(`hauteur inconnue : ${niveaux} × ${c.geometrie_hauteur_etage_m.valeur} m supposés`);
trace.source('geometrie_hauteur_etage_m', c.geometrie_hauteur_etage_m.valeur, c.geometrie_hauteur_etage_m.source, c.geometrie_hauteur_etage_m.date);
}
const hauteur_etage = hauteur / niveaux;
let pente = entrees.pente_toit_deg;
if (pente == null || !(pente >= 0) || pente >= 90) {
pente = c.geometrie_pente_defaut_deg.valeur;
trace.avertit(`pente de toit inconnue : ${pente}° supposés`);
trace.source('geometrie_pente_defaut_deg', pente, c.geometrie_pente_defaut_deg.source, c.geometrie_pente_defaut_deg.date);
}
const mitoyen = Math.min(2, Math.max(0, Math.round(entrees.mitoyennete ?? 0)));
// SHAB
let shab;
let shab_estimee;
if (entrees.surface_habitable_m2 && entrees.surface_habitable_m2 > 0) {
shab = entrees.surface_habitable_m2;
shab_estimee = false;
}
else {
shab = emprise * niveaux * c.geometrie_ratio_shab_emprise.valeur;
shab_estimee = true;
trace.avertit('surface habitable estimée depuis l\'emprise (aucune surface connue)');
trace.source('geometrie_ratio_shab_emprise', c.geometrie_ratio_shab_emprise.valeur, c.geometrie_ratio_shab_emprise.source, c.geometrie_ratio_shab_emprise.date);
}
// Périmètre (V1 : √(S × 1,3) × 4) et part exposée
const perimetre = 4 * Math.sqrt(emprise * c.geometrie_facteur_perimetre.valeur);
trace.source('geometrie_facteur_perimetre', c.geometrie_facteur_perimetre.valeur, c.geometrie_facteur_perimetre.source, c.geometrie_facteur_perimetre.date);
const perimetre_expose = perimetre * (1 - c.geometrie_part_mur_mitoyen.valeur * mitoyen);
if (mitoyen > 0)
trace.source('geometrie_part_mur_mitoyen', c.geometrie_part_mur_mitoyen.valeur, c.geometrie_part_mur_mitoyen.source, c.geometrie_part_mur_mitoyen.date);
// Parois
const murs_exterieurs = perimetre_expose * hauteur;
const vitrage = shab * c.geometrie_ratio_vitrage_shab.valeur;
trace.source('geometrie_ratio_vitrage_shab', arrondi2(c.geometrie_ratio_vitrage_shab.valeur), c.geometrie_ratio_vitrage_shab.source, c.geometrie_ratio_vitrage_shab.date);
const murs_opaques = Math.max(0, murs_exterieurs - vitrage);
const rad = (pente * Math.PI) / 180;
const toiture = (emprise / Math.cos(rad)) * c.geometrie_majoration_toiture.valeur;
trace.source('geometrie_majoration_toiture', c.geometrie_majoration_toiture.valeur, c.geometrie_majoration_toiture.source, c.geometrie_majoration_toiture.date);
const volume = shab * hauteur_etage;
const sorties = {
shab_m2: arrondi2(shab),
shab_estimee,
perimetre_m: arrondi2(perimetre),
perimetre_expose_m: arrondi2(perimetre_expose),
murs_exterieurs_m2: arrondi2(murs_exterieurs),
murs_opaques_m2: arrondi2(murs_opaques),
vitrage_m2: arrondi2(vitrage),
toiture_m2: arrondi2(toiture),
plancher_bas_m2: arrondi2(emprise),
volume_m3: arrondi2(volume),
hauteur_m: arrondi2(hauteur),
hauteur_etage_m: arrondi2(hauteur_etage),
};
return trace.resultat(sorties, VERSION);
}
export const geometrie = {
id: 'commun.geometrie',
calculer(entrees, donnees) {
return calculeGeometrie(entrees, donnees?.coefficients ?? COEFFICIENTS);
},
};