# Jumeau Numérique Urbain : Le Standard CityGML

> Créez des Jumeaux Numériques Urbains avec CityGML et Python. Guide sur les niveaux de détails (LOD), le parsing XML et la visualisation dans Cesium.

- Adresse : https://fr.learngeodata.eu/blog/jumeau-numerique-urbain-citygml-python
- Rubrique : Articles techniques
- Langue : fr
- Auteur : Dr. Florent Poux (https://fr.learngeodata.eu/formateur/florent-poux)
- Éditeur : 3D Geodata Academy (organisme de formation, France)
- Index du site pour les assistants : https://fr.learngeodata.eu/llms.txt
- Publié le 2025-11-30

---
Le résultat visé : un modèle de ville structuré, pas un nuage brut.

## 1. Le Concept de LOD (Level of Detail)

CityGML structure la ville en 5 niveaux de granularité. Comprendre cela est vital pour choisir la bonne donnée pour le bon usage.

- **LOD 0 :** Terrain 2.5D (MNT). Usage : Hydrologie.
- **LOD 1 :** Blocs extrudés ("Shoebox"). Usage : Planification urbaine macro.
- **LOD 2 :** Toits différenciés. Usage : Potentiel solaire.
- **LOD 3 :** Façades détaillées (Fenêtres, Portes). Usage : Architecture.
- **LOD 4 :** Intérieur des bâtiments (BIM). Usage : Gestion de crise.

## 2. Parser CityGML avec Python

CityGML est basé sur XML/GML. C'est verbeux et hiérarchique. Nous utilisons `lxml` pour naviguer efficacement dans ces fichiers qui peuvent peser des Gigaoctets.

```
from lxml import etree

ns = {'core': "https://www.opengis.net/citygml/2.0",
      'bldg': "https://www.opengis.net/citygml/building/2.0",
      'gml': "https://www.opengis.net/gml"}

def parse_buildings(file_path):
    tree = etree.parse(file_path)
    root = tree.getroot()
    
    # Trouver tous les bâtiments
    buildings = root.findall('.//bldg:Building', namespaces=ns)
    
    print(f"Found {len(buildings)} buildings.")
    
    for b in buildings:
        # Extraction hauteur (LOD1/2)
        measured_height = b.find('.//bldg:measuredHeight', namespaces=ns)
        height = float(measured_height.text) if measured_height is not None else 0.0
        print(f"Building Height: {height}m")
```

## 3. De CityGML vers le Web : 3D Tiles

Les navigateurs ne lisent pas le XML de 2 Go. Nous devons convertir notre CityGML en **3D Tiles**, un format binaire hiérarchique optimisé pour le streaming WebGL (JSON + binaires .b3dm).

En Python, nous utilisons souvent des briques de tuilage écrites en Python, comme `py3dtiles`.

```
# Conversion via Py3DTiles CLI
# 1. Convertir CityGML -> Point/Mesh intermédiaire
py3dtiles convert input.gml --out output_tileset/
```

## 4. Visualisation avec CesiumJS

Une fois tuilé, le jumeau numérique prend vie dans le navigateur.

```
const viewer = new Cesium.Viewer('cesiumContainer');

const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
        url: './output_tileset/tileset.json'
    })
);

tileset.readyPromise.then(function(tileset) {
    viewer.zoomTo(tileset);
    
    # Style conditionnel (Colorer par hauteur)
    tileset.style = new Cesium.Cesium3DTileStyle({
        color: {
            conditions: [
                ['${Height} >= 50', 'color("purple")'],
                ['${Height} >= 20', 'color("red")'],
                ['true', 'color("white")']
            ]
        }
    });
});
```

C'est ici que la magie opère : des millions de polygones diffusés de façon fluide sur un iPad.

### Construire la Smart City

Notre cursus "Urban Digital Twin" vous apprend à fusionner CityGML, IoT sensor data et IA pour le pilotage urbain en temps réel.

[Le programme et les tarifs →](https://fr.learngeodata.eu/tarifs)
