- Backend NestJS orchestrant CloudCompare CLI (stats, decimation x2 sur 5 etapes, volume, assemblage .bin) - Scripts Python (laspy, scipy, matplotlib) pour la conversion LAS/LAZ et la generation d'images - Frontend web simple (Tailwind CDN) avec historique des runs - Image Docker (debian:trixie-slim + cloudcompare apt + xvfb) prete pour deploiement Coolify - Lint/typecheck/tests unitaires integres comme portes de qualite au build Docker - CLAUDE.md documentant les comportements CloudCompare CLI verifies empiriquement
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Convertit un fichier LAS/LAZ/COPC (via laspy) en nuage ASCII XYZ brut, lisible
|
|
nativement par CloudCompare sans plugin LAS (le paquet apt Debian de CloudCompare
|
|
ne fournit pas le plugin LAS/LAZ - seulement le plugin "Core I/O").
|
|
|
|
Un .copc.laz est simplement lu comme un LAZ standard (les points sont
|
|
identiques, seule l'indexation octree COPC, inutile ici, est ignoree).
|
|
|
|
Usage:
|
|
python3 las_to_xyz.py --input nuage.laz --output nuage.xyz
|
|
"""
|
|
import argparse
|
|
import json
|
|
import sys
|
|
|
|
import laspy
|
|
import numpy as np
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--input", required=True)
|
|
parser.add_argument("--output", required=True)
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
total = 0
|
|
with laspy.open(args.input) as reader, open(args.output, "w", encoding="ascii") as out:
|
|
for chunk in reader.chunk_iterator(2_000_000):
|
|
xyz = np.column_stack([np.asarray(chunk.x), np.asarray(chunk.y), np.asarray(chunk.z)])
|
|
np.savetxt(out, xyz, fmt="%.6f")
|
|
total += xyz.shape[0]
|
|
except Exception as exc:
|
|
print(json.dumps({"error": f"conversion LAS/LAZ impossible: {exc}"}))
|
|
return 1
|
|
|
|
if total == 0:
|
|
print(json.dumps({"error": "le fichier LAS/LAZ ne contient aucun point"}))
|
|
return 1
|
|
|
|
print(json.dumps({"ok": True, "count": total}))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|