passerelle-geo-components 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -0
- package/examples/README.md +175 -0
- package/examples/choropleth-demographique.json +90 -0
- package/examples/corpus-documentaire.json +170 -0
- package/examples/diagnostic-temporel.json +160 -0
- package/examples/heatmap-rag.json +84 -0
- package/examples/maquette-3d.json +153 -0
- package/examples/minimal.json +19 -0
- package/examples/multi-layers-narrative.json +119 -0
- package/examples/timeline-overlay-simple.json +90 -0
- package/examples/validation-terrain-zebra.json +98 -0
- package/geo-components.js +1719 -0
- package/package.json +77 -0
- package/schemas/README.md +125 -0
- package/schemas/scene_manifest.pydantic.py +1000 -0
- package/schemas/scene_manifest.schema.json +905 -0
- package/schemas/scene_manifest.zod.ts +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# passerelle-geo-components
|
|
2
|
+
|
|
3
|
+
**Web Components pour cartes MapLibre + composants controllers pilotes — brique commune multi-projet.**
|
|
4
|
+
|
|
5
|
+
Zero dependance runtime (peer `maplibre-gl@^5.6.1`, `geoai-kit@^0.2.0` optionnel), ES module, executable dans un navigateur — widget SPA, PWA, page HTML statique, iframe SSR, storymap.
|
|
6
|
+
|
|
7
|
+
> **Statut** : `0.2.0-alpha.1` (developpement). API stable prevue en `0.2.0` a l'issue du Sprint V0.2.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install passerelle-geo-components
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Peer runtime :
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install maplibre-gl
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Import direct dans le HTML ou via bundler :
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<script type="module" src="node_modules/passerelle-geo-components/geo-components.js"></script>
|
|
29
|
+
|
|
30
|
+
<geo-map params='{"basemap":"osm","bbox":[5.3,43.28,5.42,43.34]}'></geo-map>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Ou via bundler :
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import "passerelle-geo-components";
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Composants exposes
|
|
40
|
+
|
|
41
|
+
- `<geo-map>` — carte MapLibre pilotee par attribut `params` (SceneManifest V0.3.1)
|
|
42
|
+
- `<geo-timeline>` — controller temporel `input[type=range]` liee par `target`
|
|
43
|
+
- `<geo-legend>` — legende declarative (mode auto ou items explicites)
|
|
44
|
+
- `<geo-3d-scene>` — slot composition Three.js chargee a la demande (opt-in 3D)
|
|
45
|
+
|
|
46
|
+
Voir la source `geo-components.js` pour l'API complete des attributs.
|
|
47
|
+
|
|
48
|
+
## Contract SceneManifest V0.3.1
|
|
49
|
+
|
|
50
|
+
Le composant `<geo-map>` accepte un `params` conforme au JSON Schema `scene_manifest.schema.json` livre dans ce package :
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
import schema from "passerelle-geo-components/schemas/scene-manifest";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Ou en TypeScript :
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { SceneManifestSchema } from "passerelle-geo-components/schemas/scene-manifest-zod";
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
9 exemples canoniques disponibles dans `examples/` — minimal, diagnostic-temporel, corpus-documentaire, choropleth-demographique, heatmap-rag, timeline-overlay-simple, multi-layers-narrative, maquette-3d, validation-terrain.
|
|
63
|
+
|
|
64
|
+
## Peer dependencies
|
|
65
|
+
|
|
66
|
+
- `maplibre-gl@^5.6.1` (obligatoire)
|
|
67
|
+
- `geoai-kit@^0.2.0` (optionnel — primitives geo)
|
|
68
|
+
|
|
69
|
+
## Licence
|
|
70
|
+
|
|
71
|
+
EUPL-1.2 — Licence publique de l'Union europeenne.
|
|
72
|
+
|
|
73
|
+
## Repository
|
|
74
|
+
|
|
75
|
+
Source : https://github.com/nic01asFr/Passerelle/tree/main/sdk/js/geo-components
|
|
76
|
+
|
|
77
|
+
Rapports de bug, discussions, roadmap et documentation etendue dans le repo.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Exemples canoniques — SceneManifest V0.3.1
|
|
2
|
+
|
|
3
|
+
Ce dossier contient les **8 exemples canoniques** du contract `SceneManifest V0.3.1`, un par pattern métier prioritaire de l'écosystème.
|
|
4
|
+
|
|
5
|
+
Chaque exemple est **complet, valide V0.3.1**, testable via `pnpm run validate:examples`, et sert de :
|
|
6
|
+
- **Contract-book pour agents LLM** (retournés par `describe_entity_schema` filtré par `use_case`)
|
|
7
|
+
- **Fixtures CI cross-projet** (garantissent la non-régression sur PR de la lib)
|
|
8
|
+
- **Point de départ par analogie** pour un dev démarrant un nouveau projet
|
|
9
|
+
|
|
10
|
+
Voir [`../CONTRACT-V0.3.1.md`](../CONTRACT-V0.3.1.md) pour la spec complète.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Table des exemples
|
|
15
|
+
|
|
16
|
+
| # | Fichier | Pattern | Producer | Cas d'usage typique | Anti-pattern à éviter |
|
|
17
|
+
|---|---|---|---|---|---|
|
|
18
|
+
| 1 | [`minimal.json`](./minimal.json) | Point de départ incrémental | `manual` | Nouveau projet, prototype rapide, test agent | Rester bloqué à ce minimum en prod |
|
|
19
|
+
| 2 | [`diagnostic-temporel.json`](./diagnostic-temporel.json) | Classification graduated + timeline + hillshade | `qgis-sspcloud` | Diagnostic bâti par période, storymap DSFR | Oublier `opacity.reactive` (timeline devient statique) |
|
|
20
|
+
| 3 | [`corpus-documentaire.json`](./corpus-documentaire.json) | Rôles emprise/site + groupement N docs/emprise | `livrables` | Widget corpus documentaire, editeur narratif | Mélanger polygons+points dans même layer sans role |
|
|
21
|
+
| 4 | [`choropleth-demographique.json`](./choropleth-demographique.json) | `classification.color.mode=expression` + interpolate | `x_crm_grist_storymap` | Choroplèthe communal, dashboard CRM | Utiliser `mode=graduated` pour continuous data (préférer expression) |
|
|
22
|
+
| 5 | [`heatmap-rag.json`](./heatmap-rag.json) | Heatmap + `maplibre_paint_override` | `x_mobscidat` | RAG géo-sémantique, dashboard science des données | Créer une couche circle pour simuler heatmap (impossible) |
|
|
23
|
+
| 6 | [`timeline-overlay-simple.json`](./timeline-overlay-simple.json) | Timeline `opacity.reactive` sans classification | `qgis-sspcloud` | Animation temporelle simple (événements datés) | Rajouter classification par période inutile |
|
|
24
|
+
| 7 | [`multi-layers-narrative.json`](./multi-layers-narrative.json) | 3 layers avec rôles `context/primary/emprise` | `qgis-sspcloud` | Storymap narrative multi-échelles | Empiler des layers sans role (perte de sens) |
|
|
25
|
+
| 8 | [`maquette-3d.json`](./maquette-3d.json) | Terrain LIDAR + sky solaire + custom_layers GLTF | `atlas` | Maquette 3D territoriale immersive | Mettre les instances GLTF dans `custom_layers.params.instances[]` (utiliser `source_layer_id`) |
|
|
26
|
+
| 9* | [`validation-terrain-zebra.json`](./validation-terrain-zebra.json) | Grist bridge bidirectionnel + `feature_state.selected` | `x_zebra` | Validation terrain widget Grist | Oublier `feature_state_selected_field` (perte sync Grist↔carte) |
|
|
27
|
+
|
|
28
|
+
*Exemple bonus pour illustrer le pattern `source.type: "grist_table"` + `sync: "reactive"`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Comment lire un exemple
|
|
33
|
+
|
|
34
|
+
### Structure standard
|
|
35
|
+
|
|
36
|
+
Tout exemple V0.3.1 comporte au minimum :
|
|
37
|
+
- `$schema` (URL du JSON Schema publié)
|
|
38
|
+
- `manifest_version: "0.3.1"`
|
|
39
|
+
- `produced_at` (ISO datetime)
|
|
40
|
+
- `provenance.producer` + `provenance.producer_version`
|
|
41
|
+
- `title`
|
|
42
|
+
- `basemap.id`
|
|
43
|
+
- `zone` (discriminated union sur `kind`)
|
|
44
|
+
- `layers[]` (peut être vide)
|
|
45
|
+
|
|
46
|
+
Les champs immuables (`scene_hash`, `manifest_id`) sont ajoutés par le hub au moment du publish — l'agent LLM ne les produit pas.
|
|
47
|
+
|
|
48
|
+
### Discriminated unions
|
|
49
|
+
|
|
50
|
+
Certains sous-modèles utilisent des unions typées strictes :
|
|
51
|
+
- `source.type` : `geojson | geojson_path | vector | pmtiles | grist_table | wfs | boundary_admin`
|
|
52
|
+
- `classification.color.mode` : `single | categorized | graduated | expression`
|
|
53
|
+
- `legend.mode` : `auto | manual`
|
|
54
|
+
- `zone.kind` : `manual | commune | insee_arm | auto_bounds`
|
|
55
|
+
- `opacity.kind` : `static | reactive`
|
|
56
|
+
- `custom_layers.kind` : `gltf_instances | custom_3d_layer`
|
|
57
|
+
|
|
58
|
+
**Un agent LLM doit choisir UNE variante par union.** Ne pas mélanger les champs de plusieurs variantes.
|
|
59
|
+
|
|
60
|
+
### Extensions par-projet
|
|
61
|
+
|
|
62
|
+
Chaque niveau du manifest accepte `extensions: {[prefix]: object}` avec prefix = nom projet (`x_livrables`, `x_atlas`, `x_zebra`, ...).
|
|
63
|
+
|
|
64
|
+
Le contenu de chaque extension est libre (`additionalProperties: true`). Les extensions inconnues sont **ignorées** par le renderer standard.
|
|
65
|
+
|
|
66
|
+
Voir `corpus-documentaire.json` (Livrables `sidebar_items`) et `maquette-3d.json` (Atlas `native_payload_hash`) pour des exemples réels.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Anti-patterns communs à éviter
|
|
71
|
+
|
|
72
|
+
### 1. `geojson_inline` catastrophique
|
|
73
|
+
```jsonc
|
|
74
|
+
// ❌ MAUVAIS : 22 MB payload pour 14 270 features
|
|
75
|
+
"source": {
|
|
76
|
+
"type": "geojson",
|
|
77
|
+
"data": { "type": "FeatureCollection", "features": [ /* 14 270 features */ ] }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ✅ BON : utilise geojson_path avec fetch séparé streamé
|
|
81
|
+
"source": {
|
|
82
|
+
"type": "geojson_path",
|
|
83
|
+
"path": "/data/.../batiments.geojson"
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Seuils : `geojson` inline autorisé uniquement si `n_features ≤ 500` OU `payload ≤ 500 KB`.
|
|
88
|
+
|
|
89
|
+
### 2. Discriminated union floue
|
|
90
|
+
```jsonc
|
|
91
|
+
// ❌ MAUVAIS : mélange champs de modes différents
|
|
92
|
+
"color": {
|
|
93
|
+
"mode": "graduated",
|
|
94
|
+
"value": "#1d70b8", // ❌ "value" appartient à mode=single
|
|
95
|
+
"categories": [ /* ... */ ], // ❌ "categories" appartient à mode=categorized
|
|
96
|
+
"breaks": [1900, 1945] // ✅ correct pour graduated
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ✅ BON : un seul mode, ses champs spécifiques
|
|
100
|
+
"color": {
|
|
101
|
+
"mode": "graduated",
|
|
102
|
+
"field": "date_d_apparition",
|
|
103
|
+
"method": "manual",
|
|
104
|
+
"breaks": [1900, 1945, 1975, 2000],
|
|
105
|
+
"palette": "ColorBrewer.PRGn.6",
|
|
106
|
+
"default": "#9e9e9e"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Enum inconnu sans convention `x_*`
|
|
111
|
+
```jsonc
|
|
112
|
+
// ❌ MAUVAIS : "validation-cluster" hors enum + pas de convention x_*
|
|
113
|
+
"role": "validation-cluster"
|
|
114
|
+
|
|
115
|
+
// ✅ BON : préfixe x_<projet>_* + fallback graceful primary
|
|
116
|
+
"role": "x_zebra_validation_cluster"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 4. Magic strings d'événements
|
|
120
|
+
```jsonc
|
|
121
|
+
// ❌ MAUVAIS : nom d'événement custom (non émis par la lib)
|
|
122
|
+
"click_event": "custom-click-handler"
|
|
123
|
+
|
|
124
|
+
// ✅ BON : événements canoniques fixés par la lib
|
|
125
|
+
"emits_events": true
|
|
126
|
+
// → émet automatiquement geo:feature-click, geo:feature-hover
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 5. `dimension` explicite au manifest
|
|
130
|
+
```jsonc
|
|
131
|
+
// ❌ MAUVAIS : dimension supprimée du contract V0.3.1
|
|
132
|
+
"dimension": "3d"
|
|
133
|
+
|
|
134
|
+
// ✅ BON : dérivée par le renderer selon présence de custom_layers[]
|
|
135
|
+
// (rien à mettre dans le manifest)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Tests de validation
|
|
141
|
+
|
|
142
|
+
Depuis `sdk/js/geo-components/` :
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Valide un exemple contre le JSON Schema canonique
|
|
146
|
+
pnpm exec ajv validate -s schemas/scene_manifest.schema.json -d examples/minimal.json --spec=draft2020
|
|
147
|
+
|
|
148
|
+
# Valide tous les exemples
|
|
149
|
+
pnpm run validate:examples
|
|
150
|
+
|
|
151
|
+
# Round-trip Zod (à venir après build:zod)
|
|
152
|
+
pnpm run test:schemas
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Ajout d'un nouvel exemple
|
|
158
|
+
|
|
159
|
+
Un nouvel exemple `examples/<nom>.json` doit :
|
|
160
|
+
|
|
161
|
+
1. Illustrer un **pattern métier distinct** des 8 existants (pas de doublon)
|
|
162
|
+
2. Valider contre `schemas/scene_manifest.schema.json`
|
|
163
|
+
3. Ajouter une entrée dans le tableau ci-dessus
|
|
164
|
+
4. Décrire l'anti-pattern à éviter dans un usage similaire
|
|
165
|
+
5. Passer les tests CI cross-projet
|
|
166
|
+
|
|
167
|
+
Les nouveaux exemples deviennent **automatiquement disponibles** pour les agents LLM via `describe_entity_schema(entity_type="component", kind="interactive_map", use_case="<nom>")`.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Références
|
|
172
|
+
|
|
173
|
+
- [CONTRACT-V0.3.1.md](../CONTRACT-V0.3.1.md) — spec humaine complète du contract
|
|
174
|
+
- [schemas/README.md](../schemas/README.md) — pipeline codegen 3 dialectes
|
|
175
|
+
- [SPRINT-V0.2-STATUS.md](../SPRINT-V0.2-STATUS.md) — Sprint V0.2 tracker
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://cerema.github.io/geo-components/schemas/scene_manifest/0.3.1.json",
|
|
3
|
+
"manifest_version": "0.3.1",
|
|
4
|
+
"produced_at": "2026-07-10T11:00:00+02:00",
|
|
5
|
+
"provenance": {
|
|
6
|
+
"producer": "x_crm_grist_storymap",
|
|
7
|
+
"producer_version": "v17.0"
|
|
8
|
+
},
|
|
9
|
+
"title": "Concentration adhérents CEREMA par EPCI",
|
|
10
|
+
"source_text": "Table Grist Organismes — CRM CEREMA V17",
|
|
11
|
+
"basemap": {
|
|
12
|
+
"id": "cartodb-positron-nolabels"
|
|
13
|
+
},
|
|
14
|
+
"zone": {
|
|
15
|
+
"kind": "manual",
|
|
16
|
+
"bbox": [-5.0, 41.3, 9.5, 51.2],
|
|
17
|
+
"center": [2.5, 46.5],
|
|
18
|
+
"zoom": 5
|
|
19
|
+
},
|
|
20
|
+
"layers": [
|
|
21
|
+
{
|
|
22
|
+
"id": "epci_metric_norm",
|
|
23
|
+
"name": "Concentration adhérents (métrique normalisée)",
|
|
24
|
+
"role": "primary",
|
|
25
|
+
"geometry_type": "polygon",
|
|
26
|
+
"source": {
|
|
27
|
+
"type": "boundary_admin",
|
|
28
|
+
"catalog_id": "epci_france"
|
|
29
|
+
},
|
|
30
|
+
"n_features": 1245,
|
|
31
|
+
"bbox": [-5.0, 41.3, 9.5, 51.2],
|
|
32
|
+
"attribute_stats": {
|
|
33
|
+
"metric_norm": {
|
|
34
|
+
"min": 0.0,
|
|
35
|
+
"max": 1.0,
|
|
36
|
+
"null_count": 12,
|
|
37
|
+
"distinct_count": 1233
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"style": {
|
|
41
|
+
"z_index": 10,
|
|
42
|
+
"opacity": { "kind": "static", "value": 0.75 },
|
|
43
|
+
"classification": {
|
|
44
|
+
"color": {
|
|
45
|
+
"mode": "expression",
|
|
46
|
+
"expr": [
|
|
47
|
+
"interpolate",
|
|
48
|
+
["linear"],
|
|
49
|
+
["coalesce", ["get", "metric_norm"], 0],
|
|
50
|
+
0.0, "#f7f7f7",
|
|
51
|
+
0.25, "#c6dbef",
|
|
52
|
+
0.5, "#6baed6",
|
|
53
|
+
0.75, "#2171b5",
|
|
54
|
+
1.0, "#08306b"
|
|
55
|
+
],
|
|
56
|
+
"default": "#e0e0e0"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"outline": {
|
|
60
|
+
"enabled": true,
|
|
61
|
+
"color": "#ffffff",
|
|
62
|
+
"width": 0.5
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"interactions": {
|
|
66
|
+
"popup_template": {
|
|
67
|
+
"kind": "handlebars",
|
|
68
|
+
"body": "<h4>{{nom_epci}}</h4><p><strong>{{count_adherents}}</strong> adhérent(s)</p><p>Score : {{metric_norm}}</p>"
|
|
69
|
+
},
|
|
70
|
+
"tooltip_field": "nom_epci",
|
|
71
|
+
"hover_attributes": ["nom_epci", "count_adherents", "metric_norm"],
|
|
72
|
+
"emits_events": true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"legend": {
|
|
77
|
+
"mode": "auto",
|
|
78
|
+
"from_layer": "epci_metric_norm",
|
|
79
|
+
"position": "bottom-left",
|
|
80
|
+
"format": "gradient_bar",
|
|
81
|
+
"title": "Concentration adhérents (0-1)"
|
|
82
|
+
},
|
|
83
|
+
"extensions": {
|
|
84
|
+
"x_crm_grist_storymap": {
|
|
85
|
+
"grist_table": "Organismes",
|
|
86
|
+
"metric_field": "score_norm",
|
|
87
|
+
"join_field": "code_epci"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://cerema.github.io/geo-components/schemas/scene_manifest/0.3.1.json",
|
|
3
|
+
"manifest_version": "0.3.1",
|
|
4
|
+
"produced_at": "2026-07-10T10:00:00+02:00",
|
|
5
|
+
"provenance": {
|
|
6
|
+
"producer": "cerema-livrables",
|
|
7
|
+
"producer_version": "0.4.0",
|
|
8
|
+
"extensions": {
|
|
9
|
+
"cerema_livrables": {
|
|
10
|
+
"mode": "subject",
|
|
11
|
+
"corpus_version": "2026-07"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"title": "Livrables CEREMA — corpus Méditerranée",
|
|
16
|
+
"source_text": "CeremaDoc via Syracuse RSS + Strate — Licence Ouverte 2.0",
|
|
17
|
+
"basemap": {
|
|
18
|
+
"id": "plan-ign-v2"
|
|
19
|
+
},
|
|
20
|
+
"zone": {
|
|
21
|
+
"kind": "manual",
|
|
22
|
+
"bbox": [3.0, 42.5, 7.5, 44.5],
|
|
23
|
+
"center": [5.5, 43.5],
|
|
24
|
+
"zoom": 7
|
|
25
|
+
},
|
|
26
|
+
"layers": [
|
|
27
|
+
{
|
|
28
|
+
"id": "livrables_emprises",
|
|
29
|
+
"name": "Emprises documentées",
|
|
30
|
+
"role": "emprise",
|
|
31
|
+
"geometry_type": "polygon",
|
|
32
|
+
"source": {
|
|
33
|
+
"type": "geojson_path",
|
|
34
|
+
"path": "/data/publications/cerema-livrables/scenes/subject-corpus-mediterranee.geojson"
|
|
35
|
+
},
|
|
36
|
+
"n_features": 24,
|
|
37
|
+
"bbox": [3.0, 42.5, 7.5, 44.5],
|
|
38
|
+
"attribute_stats": {
|
|
39
|
+
"scale": { "distinct_values": ["batiment", "zone", "rue", "ville", "epci"] }
|
|
40
|
+
},
|
|
41
|
+
"style": {
|
|
42
|
+
"z_index": 10,
|
|
43
|
+
"opacity": { "kind": "static", "value": 0.35 },
|
|
44
|
+
"classification": {
|
|
45
|
+
"color": {
|
|
46
|
+
"mode": "categorized",
|
|
47
|
+
"field": "scale",
|
|
48
|
+
"categories": [
|
|
49
|
+
{ "value": "batiment", "color": "#000091" },
|
|
50
|
+
{ "value": "zone", "color": "#1212a3" },
|
|
51
|
+
{ "value": "rue", "color": "#2e2eb5" },
|
|
52
|
+
{ "value": "ville", "color": "#4a4ac7" },
|
|
53
|
+
{ "value": "epci", "color": "#7676d9" }
|
|
54
|
+
],
|
|
55
|
+
"default": "#9e9e9e"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"outline": {
|
|
59
|
+
"enabled": true,
|
|
60
|
+
"color": "#000091",
|
|
61
|
+
"width": 1.5
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"interactions": {
|
|
65
|
+
"popup_template": {
|
|
66
|
+
"kind": "handlebars",
|
|
67
|
+
"body": "<h4>{{count}} livrable(s) sur {{territoire}}</h4><ul>{{#each members}}<li><a href=\"{{source_url}}\" target=\"_blank\">{{titre}}</a> ({{millesime}}) — {{commanditaire}}</li>{{/each}}</ul>"
|
|
68
|
+
},
|
|
69
|
+
"tooltip_field": "titre",
|
|
70
|
+
"hover_attributes": ["scale", "count", "territoire"],
|
|
71
|
+
"emits_events": true,
|
|
72
|
+
"feature_state_selected_field": "group_key"
|
|
73
|
+
},
|
|
74
|
+
"extensions": {
|
|
75
|
+
"cerema_livrables": {
|
|
76
|
+
"role_semantic": "emprise",
|
|
77
|
+
"group_key_field": "group_key"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "livrables_points_approx",
|
|
83
|
+
"name": "Livrables sans emprise vérifiée",
|
|
84
|
+
"role": "site",
|
|
85
|
+
"geometry_type": "point",
|
|
86
|
+
"source": {
|
|
87
|
+
"type": "geojson_path",
|
|
88
|
+
"path": "/data/publications/cerema-livrables/scenes/subject-points-approximatifs.geojson"
|
|
89
|
+
},
|
|
90
|
+
"n_features": 6,
|
|
91
|
+
"bbox": [3.5, 42.8, 7.0, 44.0],
|
|
92
|
+
"style": {
|
|
93
|
+
"z_index": 15,
|
|
94
|
+
"opacity": { "kind": "static", "value": 0.9 },
|
|
95
|
+
"classification": {
|
|
96
|
+
"color": {
|
|
97
|
+
"mode": "categorized",
|
|
98
|
+
"field": "geom_statut",
|
|
99
|
+
"categories": [
|
|
100
|
+
{ "value": "verifie", "color": "#000091" },
|
|
101
|
+
{ "value": "approximatif", "color": "#e1000f" }
|
|
102
|
+
],
|
|
103
|
+
"default": "#9e9e9e"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"hollow_point": {
|
|
107
|
+
"enabled": true,
|
|
108
|
+
"stroke_color_from_field": "geom_statut",
|
|
109
|
+
"radius": 8
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"interactions": {
|
|
113
|
+
"popup_template": {
|
|
114
|
+
"kind": "handlebars",
|
|
115
|
+
"body": "<h4>{{titre}}</h4><p>Emprise : <strong>{{geom_statut}}</strong> ({{geom_source}})</p><p>{{count}} livrable(s) groupé(s)</p>"
|
|
116
|
+
},
|
|
117
|
+
"tooltip_field": "titre",
|
|
118
|
+
"emits_events": true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"legend": {
|
|
123
|
+
"mode": "manual",
|
|
124
|
+
"items": [
|
|
125
|
+
{ "label": "Bâtiment", "color": "#000091" },
|
|
126
|
+
{ "label": "Zone / ZI", "color": "#1212a3" },
|
|
127
|
+
{ "label": "Rue", "color": "#2e2eb5" },
|
|
128
|
+
{ "label": "Ville", "color": "#4a4ac7" },
|
|
129
|
+
{ "label": "EPCI", "color": "#7676d9" },
|
|
130
|
+
{ "label": "Approximatif (point)", "color": "#e1000f" }
|
|
131
|
+
],
|
|
132
|
+
"position": "bottom-left",
|
|
133
|
+
"format": "chips",
|
|
134
|
+
"title": "Échelle documentaire"
|
|
135
|
+
},
|
|
136
|
+
"scalebar": {
|
|
137
|
+
"position": "bottom-right",
|
|
138
|
+
"unit": "metric"
|
|
139
|
+
},
|
|
140
|
+
"extensions": {
|
|
141
|
+
"cerema_livrables": {
|
|
142
|
+
"sidebar_items": [
|
|
143
|
+
{
|
|
144
|
+
"id": "doc-uuid-1",
|
|
145
|
+
"titre": "Rapport littoral MTPM 2024",
|
|
146
|
+
"scale": "epci",
|
|
147
|
+
"zoom": 10,
|
|
148
|
+
"domaine": "Risques",
|
|
149
|
+
"commanditaire": "Métropole TPM",
|
|
150
|
+
"millesime": 2024,
|
|
151
|
+
"source_url": "https://doc.cerema.fr/...",
|
|
152
|
+
"group_key": "epci:200055529",
|
|
153
|
+
"lon": 5.926, "lat": 43.124,
|
|
154
|
+
"geom_statut": "verifie"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"national": [
|
|
158
|
+
{
|
|
159
|
+
"id": "doc-nat-1",
|
|
160
|
+
"titre": "Guide méthodologique passages piétons",
|
|
161
|
+
"domaine": "Risques",
|
|
162
|
+
"commanditaire": "DGITM",
|
|
163
|
+
"millesime": 2024,
|
|
164
|
+
"source_url": "https://doc.cerema.fr/..."
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
"count": 42
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://cerema.github.io/geo-components/schemas/scene_manifest/0.3.1.json",
|
|
3
|
+
"manifest_version": "0.3.1",
|
|
4
|
+
"produced_at": "2026-07-10T09:15:23+02:00",
|
|
5
|
+
"provenance": {
|
|
6
|
+
"producer": "qgis-sspcloud",
|
|
7
|
+
"producer_version": "v1.20.6",
|
|
8
|
+
"source_project": "/data/studies/c9fef0955a53/projects/72e3da47b1f7/project.qgz",
|
|
9
|
+
"recipe_used": {
|
|
10
|
+
"slug": "diagnostic-parc-bati",
|
|
11
|
+
"version_sha": "sha256:9f8a1e7c4d2b3f5e8a1c9d0e2f3b4a5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"title": "Parc bâti du 4e arrondissement, par année de construction",
|
|
15
|
+
"subtitle": "Diagnostic CEREMA – juillet 2026",
|
|
16
|
+
"description": "Cartographie de l'ensemble du parc bâti du 4e arrondissement de Marseille à partir de la BD TOPO® de l'IGN et de son attribut de date d'apparition. Explore visuellement l'évolution du bâti au fil du temps.",
|
|
17
|
+
"source_text": "BD TOPO® IGN 2024 — CEREMA, juillet 2026",
|
|
18
|
+
"caveat": "Étude à vocation pédagogique — chiffres fictifs, non exploitables opérationnellement.",
|
|
19
|
+
"projection": "mercator",
|
|
20
|
+
"basemap": {
|
|
21
|
+
"id": "plan-ign-v2-gris"
|
|
22
|
+
},
|
|
23
|
+
"zone": {
|
|
24
|
+
"kind": "insee_arm",
|
|
25
|
+
"insee": "13204",
|
|
26
|
+
"buffer_km": 0.2,
|
|
27
|
+
"pitch": 0,
|
|
28
|
+
"bearing": 0
|
|
29
|
+
},
|
|
30
|
+
"terrain": {
|
|
31
|
+
"source_id": "ign-lidar",
|
|
32
|
+
"encoding": "mapbox",
|
|
33
|
+
"exaggeration": 1.0,
|
|
34
|
+
"adapter": "ignmnt",
|
|
35
|
+
"hillshade": {
|
|
36
|
+
"opacity": 0.35,
|
|
37
|
+
"blend_mode": "multiply"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"layers": [
|
|
41
|
+
{
|
|
42
|
+
"id": "batiments_bd_topo",
|
|
43
|
+
"name": "Bâtiments par période",
|
|
44
|
+
"role": "primary",
|
|
45
|
+
"geometry_type": "polygon",
|
|
46
|
+
"source": {
|
|
47
|
+
"type": "geojson_path",
|
|
48
|
+
"path": "/data/studies/c9fef0955a53/scene_store/c52d9d669bf5d09c/layers/batiments_bd_topo.geojson",
|
|
49
|
+
"crs": "EPSG:4326"
|
|
50
|
+
},
|
|
51
|
+
"n_features": 14270,
|
|
52
|
+
"bbox": [5.379, 43.289, 5.427, 43.334],
|
|
53
|
+
"attribute_stats": {
|
|
54
|
+
"date_d_apparition": {
|
|
55
|
+
"min": 1850,
|
|
56
|
+
"max": 2024,
|
|
57
|
+
"null_count": 7550,
|
|
58
|
+
"distinct_count": 195
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"style": {
|
|
62
|
+
"visible": true,
|
|
63
|
+
"z_index": 10,
|
|
64
|
+
"opacity": {
|
|
65
|
+
"kind": "reactive",
|
|
66
|
+
"prop": "time",
|
|
67
|
+
"matched": 0.85,
|
|
68
|
+
"before": 0.85,
|
|
69
|
+
"after": 0.12,
|
|
70
|
+
"null_value": 0.35
|
|
71
|
+
},
|
|
72
|
+
"classification": {
|
|
73
|
+
"color": {
|
|
74
|
+
"mode": "graduated",
|
|
75
|
+
"field": "date_d_apparition",
|
|
76
|
+
"method": "manual",
|
|
77
|
+
"breaks": [1900, 1945, 1975, 2000],
|
|
78
|
+
"palette": "ColorBrewer.PRGn.6",
|
|
79
|
+
"default": "#9e9e9e",
|
|
80
|
+
"_compiled_expression": [
|
|
81
|
+
"step",
|
|
82
|
+
["get", "date_d_apparition"],
|
|
83
|
+
"#7b3294",
|
|
84
|
+
1900, "#c2a5cf",
|
|
85
|
+
1945, "#f7f7f7",
|
|
86
|
+
1975, "#a6dba0",
|
|
87
|
+
2000, "#008837"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"size": { "mode": "single", "value": 8 },
|
|
91
|
+
"label": { "enabled": false }
|
|
92
|
+
},
|
|
93
|
+
"outline": {
|
|
94
|
+
"enabled": true,
|
|
95
|
+
"color": "#000091",
|
|
96
|
+
"width": 0.5
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"interactions": {
|
|
100
|
+
"popup_template": {
|
|
101
|
+
"kind": "handlebars",
|
|
102
|
+
"body": "<h4>Bâtiment {{nature}}</h4><dl><dt>Construction</dt><dd>{{date_d_apparition}}</dd><dt>Usage principal</dt><dd>{{usage_1}}</dd><dt>Logements</dt><dd>{{nombre_de_logements}}</dd><dt>Hauteur</dt><dd>{{hauteur}} m ({{nombre_d_etages}} niveaux)</dd></dl>"
|
|
103
|
+
},
|
|
104
|
+
"tooltip_field": "date_d_apparition",
|
|
105
|
+
"hover_attributes": ["nature", "usage_1", "hauteur", "nombre_de_logements"],
|
|
106
|
+
"emits_events": true
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "arrondissement_13204",
|
|
111
|
+
"name": "4e arrondissement (limite)",
|
|
112
|
+
"role": "context",
|
|
113
|
+
"geometry_type": "polygon",
|
|
114
|
+
"source": {
|
|
115
|
+
"type": "boundary_admin",
|
|
116
|
+
"catalog_id": "arrondissements_marseille",
|
|
117
|
+
"filter": { "insee_arm": "13204" }
|
|
118
|
+
},
|
|
119
|
+
"style": {
|
|
120
|
+
"visible": true,
|
|
121
|
+
"z_index": 5,
|
|
122
|
+
"opacity": { "kind": "static", "value": 0.05 },
|
|
123
|
+
"classification": {
|
|
124
|
+
"color": { "mode": "single", "value": "#000091" }
|
|
125
|
+
},
|
|
126
|
+
"outline": {
|
|
127
|
+
"enabled": true,
|
|
128
|
+
"color": "#000091",
|
|
129
|
+
"width": 2
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"interactions": {
|
|
133
|
+
"emits_events": false
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"legend": {
|
|
138
|
+
"mode": "auto",
|
|
139
|
+
"from_layer": "batiments_bd_topo",
|
|
140
|
+
"position": "bottom-left",
|
|
141
|
+
"format": "chips",
|
|
142
|
+
"title": "Période de construction"
|
|
143
|
+
},
|
|
144
|
+
"scalebar": {
|
|
145
|
+
"position": "bottom-right",
|
|
146
|
+
"unit": "metric"
|
|
147
|
+
},
|
|
148
|
+
"north_arrow": {
|
|
149
|
+
"position": "top-right"
|
|
150
|
+
},
|
|
151
|
+
"counters": [
|
|
152
|
+
{
|
|
153
|
+
"id": "cnt_bati_filtered",
|
|
154
|
+
"bind": "time",
|
|
155
|
+
"expr": "filtered_count",
|
|
156
|
+
"template": "{{count}} / 14 270 bâtiments ({{pct}} %)",
|
|
157
|
+
"position": "top-left"
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|