- Nouveau mode "cloud_compare" (en plus de "const_height") : comparaison entre une surface
superieure et une limite inferieure, avec appariement de densite avant le niveau 0 puis
decimation synchronisee x2 sur 5 etapes. UI : selecteur de mode + upload double avec labels
explicites (surface superieure / limite inferieure).
- Remplissage des trous de scan (interpolation Delaunay bornee par max-edge-length) avant chaque
calcul de volume, dans les deux modes. -VOLUME n'ayant aucune option native pour ca (verifie dans
les sources CloudCompare), on rasterize+comble+exporte en nuage avant de le passer a -VOLUME.
Override utilisateur possible pour la distance max, afin de ne pas combler les parties concaves
du contour de l'objet mesure.
- Fix critique : CloudCompare formate les grands nombres avec une virgule comme separateur de
milliers ("Volume: 14,244.46") ; le parsing tronquait silencieusement a la premiere virgule
(14 244 devenait 14). Trouve en testant avec un vrai nuage industriel.
- Validation avec 2 vrais nuages utilisateur : le mode Z constant donnait ~50m3 (plan de reference
sans rapport avec la base reelle de l'amas, nuage contenant du contexte environnant) ; le nouveau
mode comparaison donne ~14 244m3, stable a +/-4% meme a 16x de decimation.
- CLAUDE.md mis a jour avec tous ces findings (limitation -VOLUME/LEAVE_EMPTY, technique de
contournement, piege du separateur de milliers, architecture du mode 2 nuages).
45 lines
2.3 KiB
TypeScript
45 lines
2.3 KiB
TypeScript
import * as path from 'path';
|
|
|
|
function envInt(name: string, fallback: number): number {
|
|
const v = process.env[name];
|
|
if (!v) return fallback;
|
|
const n = Number(v);
|
|
return Number.isFinite(n) ? n : fallback;
|
|
}
|
|
|
|
export const config = {
|
|
port: envInt('PORT', 3000),
|
|
dataDir: process.env.DATA_DIR ?? path.resolve(process.cwd(), 'data'),
|
|
cloudCompareBin: process.env.CLOUDCOMPARE_BIN ?? 'CloudCompare',
|
|
pythonBin: process.env.PYTHON_BIN ?? 'python3',
|
|
// Pipeline constants (voir plan: facteur 2, 5 etapes)
|
|
decimationFactor: 2,
|
|
decimationSteps: 5,
|
|
// Nombre max de points echantillonnes pour estimer la distance moyenne au plus proche voisin
|
|
statsSampleCap: envInt('STATS_SAMPLE_CAP', 50000),
|
|
// Grille de calcul du volume = pas spatial DE CHAQUE NIVEAU x ce multiplicateur (adaptee
|
|
// dynamiquement a chaque niveau, pas figee sur la resolution du niveau 0 - voir CLAUDE.md).
|
|
gridStepMultiplier: 2,
|
|
// Remplissage des trous (occlusions de scan) avant -VOLUME : distance max d'interpolation
|
|
// Delaunay = gridStep du niveau x ce multiplicateur. Empeche de combler les parties concaves
|
|
// du contour de l'amas (qui doivent rester "vides") tout en bouchant les petits trous de scan.
|
|
// Voir CLAUDE.md : -VOLUME n'a PAS d'option de remplissage native, on passe par -RASTERIZE.
|
|
maxEdgeLengthMultiplier: 3,
|
|
// En dessous de ce nombre de points, on arrete la decimation progressive (cloud devenu inexploitable)
|
|
minPointsToContinue: 25,
|
|
// Seuil d'alerte robustesse : si "matching cells %" du rapport CloudCompare passe sous ce seuil,
|
|
// le resultat est signale comme peu fiable dans l'UI.
|
|
matchingCellsWarnThreshold: 90,
|
|
// Taille max d'upload (octets)
|
|
maxUploadBytes: envInt('MAX_UPLOAD_MB', 2048) * 1024 * 1024,
|
|
// Timeout par appel CloudCompare CLI (ms)
|
|
ccTimeoutMs: envInt('CC_TIMEOUT_MS', 10 * 60 * 1000),
|
|
// Auth HTTP Basic (UI + API). Si l'une des deux variables est absente, l'auth est desactivee
|
|
// (pratique en dev local) - un warning est logge au demarrage dans ce cas, voir main.ts.
|
|
authUsername: process.env.AUTH_USERNAME ?? null,
|
|
authPasswordHash: process.env.AUTH_PASSWORD_HASH ?? null,
|
|
};
|
|
|
|
export const uploadsDir = () => path.join(config.dataDir, 'uploads');
|
|
export const resultsDir = () => path.join(config.dataDir, 'results');
|
|
export const dbPath = () => path.join(config.dataDir, 'app.db');
|