- Inversion axe Y du DTM pour orientation nord correcte - Fallback filters.range pour fichiers LAZ avec ReturnNumber=0 - Flèche nord vectorielle noire au-dessus de la légende - 9/9 fichiers traités avec succès Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
3.0 KiB
Python
Executable File
100 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Script pour analyser et corriger les fichiers LAZ avec ReturnNumber=0
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
def analyze_return_numbers(laz_file):
|
|
"""Analyse les valeurs ReturnNumber dans un fichier LAZ"""
|
|
print(f"Analyse de {laz_file}...")
|
|
|
|
# Pipeline PDAL pour extraire les statistiques ReturnNumber
|
|
stats_pipeline = [
|
|
{
|
|
"type": "readers.las",
|
|
"filename": str(laz_file)
|
|
},
|
|
{
|
|
"type": "filters.stats",
|
|
"dimensions": "ReturnNumber,NumberOfReturns"
|
|
}
|
|
]
|
|
|
|
stats_json = json.dumps(stats_pipeline)
|
|
stats_file = Path("/tmp/analyze_stats.json")
|
|
with open(stats_file, 'w') as f:
|
|
f.write(stats_json)
|
|
|
|
result = subprocess.run(['pdal', 'pipeline', str(stats_file)],
|
|
capture_output=True, text=True)
|
|
|
|
if result.returncode == 0:
|
|
data = json.loads(result.stdout)
|
|
stats = data.get('stats', {}).get('statistic', [])
|
|
print(f" Statistiques ReturnNumber:")
|
|
for stat in stats:
|
|
if stat.get('name') == 'ReturnNumber':
|
|
counts = stat.get('counts', {})
|
|
for val, count in counts.items():
|
|
if count > 0:
|
|
pct = count / stat.get('total', 1) * 100
|
|
print(f" ReturnNumber={val}: {count} points ({pct:.1f}%)")
|
|
else:
|
|
print(f" Erreur: {result.stderr}")
|
|
|
|
def fix_return_numbers(laz_file, output_file):
|
|
"""Corrige les valeurs ReturnNumber=0 en utilisant une approche différente"""
|
|
print(f"Tentative de correction de {laz_file}...")
|
|
|
|
# Approche: utiliser filters.python pour modifier les valeurs
|
|
fix_pipeline = [
|
|
{
|
|
"type": "readers.las",
|
|
"filename": str(laz_file)
|
|
},
|
|
{
|
|
"type": "filters.python",
|
|
"script": """
|
|
def filter(ins, args):
|
|
for point in ins:
|
|
if point.ReturnNumber == 0:
|
|
point.ReturnNumber = 1
|
|
if point.NumberOfReturns == 0:
|
|
point.NumberOfReturns = 1
|
|
return True
|
|
"""
|
|
},
|
|
{
|
|
"type": "writers.las",
|
|
"filename": str(output_file),
|
|
"extra_dims": "all"
|
|
}
|
|
]
|
|
|
|
fix_json = json.dumps(fix_pipeline, indent=2)
|
|
fix_file = Path("/tmp/fix_pipeline.json")
|
|
with open(fix_file, 'w') as f:
|
|
f.write(fix_json)
|
|
|
|
result = subprocess.run(['pdal', 'pipeline', str(fix_file)],
|
|
capture_output=True, text=True)
|
|
|
|
if result.returncode == 0:
|
|
print(f" ✓ Correction réussie: {output_file}")
|
|
return True
|
|
else:
|
|
print(f" ✗ Erreur correction: {result.stderr}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
laz_file = sys.argv[1] if len(sys.argv) > 1 else "/data/input/LHD_FXX_1000_6882_PTS_LAMB93_IGN69.copc.laz"
|
|
|
|
analyze_return_numbers(laz_file)
|
|
|
|
output_file = laz_file.replace(".laz", "_fixed.laz").replace("/input/", "/temp/")
|
|
fix_return_numbers(laz_file, output_file)
|