@ignfab/geocontext 0.8.0
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/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/gpf/adminexpress.d.ts +15 -0
- package/dist/gpf/adminexpress.js +50 -0
- package/dist/gpf/adminexpress.js.map +1 -0
- package/dist/gpf/altitude.d.ts +16 -0
- package/dist/gpf/altitude.js +35 -0
- package/dist/gpf/altitude.js.map +1 -0
- package/dist/gpf/geocode.d.ts +10 -0
- package/dist/gpf/geocode.js +27 -0
- package/dist/gpf/geocode.js.map +1 -0
- package/dist/gpf/parcellaire-express.d.ts +12 -0
- package/dist/gpf/parcellaire-express.js +74 -0
- package/dist/gpf/parcellaire-express.js.map +1 -0
- package/dist/gpf/urbanisme.d.ts +18 -0
- package/dist/gpf/urbanisme.js +95 -0
- package/dist/gpf/urbanisme.js.map +1 -0
- package/dist/gpf/wfs.d.ts +22 -0
- package/dist/gpf/wfs.js +65 -0
- package/dist/gpf/wfs.js.map +1 -0
- package/dist/helpers/distance.d.ts +7 -0
- package/dist/helpers/distance.js +17 -0
- package/dist/helpers/distance.js.map +1 -0
- package/dist/helpers/http.d.ts +6 -0
- package/dist/helpers/http.js +24 -0
- package/dist/helpers/http.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +25 -0
- package/dist/logger.js.map +1 -0
- package/dist/tools/AdminexpressTool.d.ts +22 -0
- package/dist/tools/AdminexpressTool.js +23 -0
- package/dist/tools/AdminexpressTool.js.map +1 -0
- package/dist/tools/AltitudeTool.d.ts +27 -0
- package/dist/tools/AltitudeTool.js +24 -0
- package/dist/tools/AltitudeTool.js.map +1 -0
- package/dist/tools/AssietteSupTool.d.ts +22 -0
- package/dist/tools/AssietteSupTool.js +23 -0
- package/dist/tools/AssietteSupTool.js.map +1 -0
- package/dist/tools/CadastreTool.d.ts +22 -0
- package/dist/tools/CadastreTool.js +23 -0
- package/dist/tools/CadastreTool.js.map +1 -0
- package/dist/tools/GeocodeTool.d.ts +17 -0
- package/dist/tools/GeocodeTool.js +20 -0
- package/dist/tools/GeocodeTool.js.map +1 -0
- package/dist/tools/GpfWfsDescribeTypeTool.d.ts +32 -0
- package/dist/tools/GpfWfsDescribeTypeTool.js +32 -0
- package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -0
- package/dist/tools/GpfWfsGetFeaturesTool.d.ts +42 -0
- package/dist/tools/GpfWfsGetFeaturesTool.js +89 -0
- package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -0
- package/dist/tools/GpfWfsListTypesTool.d.ts +10 -0
- package/dist/tools/GpfWfsListTypesTool.js +18 -0
- package/dist/tools/GpfWfsListTypesTool.js.map +1 -0
- package/dist/tools/GpfWfsSearchTypesTool.d.ts +22 -0
- package/dist/tools/GpfWfsSearchTypesTool.js +31 -0
- package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -0
- package/dist/tools/UrbanismeTool.d.ts +22 -0
- package/dist/tools/UrbanismeTool.js +23 -0
- package/dist/tools/UrbanismeTool.js.map +1 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Mickaël Borne <https://github.com/mborne>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# geocontext
|
|
2
|
+
|
|
3
|
+
Un serveur MCP expérimental fournissant du contexte spatial pour les LLM.
|
|
4
|
+
|
|
5
|
+
## Motivation
|
|
6
|
+
|
|
7
|
+
Les LLM renforcent l'idée que la magie est possible avec l'informatique. Il n'en est rien. Pour qu'un assistant soit en mesure de connaître la date et l'heure, il faut par exemple l'interfacer avec un [MCP time](https://mcpservers.org/servers/modelcontextprotocol/time). De même, pour qu'il soit en mesure de lire une page, il faut par exemple l'interfacer un [MCP fetch](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch#readme).
|
|
8
|
+
|
|
9
|
+
En matière de données géographique, si un utilisateur pose une question impliquant que l'assistant soit en mesure de [connaître la position d'une adresse, il y a de bonne chance que la réponse soit plausible mais fausse](https://github.com/mborne/llm-experimentations/tree/main/chatgpt-geocodage-limites#readme).
|
|
10
|
+
|
|
11
|
+
S'il est techniquement possible de brancher des API REST/GeoJSON telle APICARTO, la conception de ces dernières n'est pas adaptée (5000 résultat par défaut, grosse géométrie dans les réponses, géométries complexes à fournir,...).
|
|
12
|
+
|
|
13
|
+
L'idée est ici d'**expérimenter la conception d'un MCP rendant les données et les services de la Géoplateforme accessibles par un LLM**.
|
|
14
|
+
|
|
15
|
+
## Mises en garde
|
|
16
|
+
|
|
17
|
+
- Ce développement est un POC en incubation avec IgnFab (migration en cours de `mborne/geocontext` en `ignfab/geocontext`)
|
|
18
|
+
- S'il s'avère utile de l'industrialiser, le dépôt sera migré sous responsabilité IGN et l'outil sera renommé (ex : `IGNF/mcp-gpf-server`)
|
|
19
|
+
- Plusieurs problèmes et améliorations possibles ont été identifiés et sont en cours de mitigation/résolution (c.f. [issues](https://github.com/ignfab/geocontext/issues?q=is%3Aissue%20state%3Aopen%20label%3Ametadata)).
|
|
20
|
+
- Cet outil n'est pas magique (voir [Fonctionnalités](#fonctionnalités) pour avoir une idée de ses capacités)
|
|
21
|
+
|
|
22
|
+
## Principes de conception
|
|
23
|
+
|
|
24
|
+
- **Ne pas copier les données de la Géoplateforme** (but : identifier les améliorations possibles sur le services plutôt que les doublonner)
|
|
25
|
+
- **Limiter au maximum la taille des réponses** (but : optimiser le nombre de jeton / éviter les hallucinations / pouvoir utiliser des modèles locaux)
|
|
26
|
+
- ...
|
|
27
|
+
|
|
28
|
+
## Utilisation
|
|
29
|
+
|
|
30
|
+
### Utilisation de la version publiée
|
|
31
|
+
|
|
32
|
+
Par exemple, avec "Cursor Settings / MCP / Add server" :
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"geocontext": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "@ignfab/geocontext"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Utilisation avec Docker
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
docker compose build
|
|
49
|
+
docker compose up -d
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Ensuite :
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"geocontext": {
|
|
58
|
+
"url": "http://localhost:3000/mcp"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Développement
|
|
65
|
+
|
|
66
|
+
### Construction de la version locale
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/ignfab/geocontext
|
|
70
|
+
cd geocontext
|
|
71
|
+
npm install
|
|
72
|
+
npm run build
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Utilisation de la version locale
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"mcp-helloworld": {
|
|
81
|
+
"command": "node",
|
|
82
|
+
"args":["/chemin/absolu/vers/geocontext/dist/index.js"]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Debug de la version locale
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx -y @modelcontextprotocol/inspector node dist/index.js
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Paramétrage
|
|
95
|
+
|
|
96
|
+
Pour une utilisation avancée :
|
|
97
|
+
|
|
98
|
+
| Nom | Description | Valeur par défaut |
|
|
99
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------- |
|
|
100
|
+
| `TRANSPORT_TYPE` | [Transport](https://mcp-framework.com/docs/Transports/transports-overview) permet de choisir entre "stdio" et "http" | "stdio" |
|
|
101
|
+
|
|
102
|
+
## Fonctionnalités
|
|
103
|
+
|
|
104
|
+
### Utiliser des services spatiaux
|
|
105
|
+
|
|
106
|
+
Quelques services de la Géoplateforme :
|
|
107
|
+
|
|
108
|
+
* [geocode(text)](src/tools/GeocodeTool.ts) s'appuie sur le [service d’autocomplétion de la Géoplateforme](https://geoservices.ign.fr/documentation/services/services-geoplateforme/autocompletion) pour **convertir un nom de lieu en position (lon,lat)**.
|
|
109
|
+
|
|
110
|
+
> Ex : Quelle est la position (lon,lat) de la mairie de Vincennes?
|
|
111
|
+
|
|
112
|
+
* [altitude(lon,lat)](src/tools/AltitudeTool.ts) s'appuie sur le [service de calcul altimétrique de la Géoplateforme](https://geoservices.ign.fr/documentation/services/services-geoplateforme/altimetrie) pour **convertir une position en altitude**.
|
|
113
|
+
|
|
114
|
+
> Ex : Quelle est l'altitude de la mairie de Loray (25)?
|
|
115
|
+
|
|
116
|
+
### Recherche d'informations pour un lieu
|
|
117
|
+
|
|
118
|
+
L'idée est ici de répondre à des précises en traitant côté serveur les appels aux services WFS de la Géoplateforme :
|
|
119
|
+
|
|
120
|
+
* [adminexpress(lon,lat)](src/tools/AdminexpressTool.ts) permet de **récupérer les informations administratives (commune, département, région,...)** pour un lieu donné par sa position.
|
|
121
|
+
|
|
122
|
+
> Ex : Quelles sont les informations administrative pour la mairie de Vincennes?
|
|
123
|
+
|
|
124
|
+
* [cadastre(lon,lat)](src/tools/CadastreTool.ts) permet de **récupérer les informations cadastrales (parcelle, feuille,...)**.
|
|
125
|
+
|
|
126
|
+
> Ex : Quelles sont les informations du cadastre pour la mairie de Vincennes?
|
|
127
|
+
|
|
128
|
+
* [urbanisme(lon,lat)](src/tools/UrbanismeTool.ts) permet de **récupérer les informations d'urbanisme (PLU,POS,CC,PSMV)**
|
|
129
|
+
|
|
130
|
+
> Ex : Quel est le document PLU en vigueur pour le port de Marseille?
|
|
131
|
+
|
|
132
|
+
* [assiette_sup(lon,lat)](src/tools/AssietteSupTool.ts) permet de **récupérer les Servitude d'Utilité Publiques (SUP)**
|
|
133
|
+
|
|
134
|
+
### Explorer les données vecteurs
|
|
135
|
+
|
|
136
|
+
#### Explorer les tables
|
|
137
|
+
|
|
138
|
+
* [gpf_wfs_list_types()](src/tools/GpfWfsListTypesTool.ts) pour **lister les tables disponibles sur le WFS de la Géoplateforme** ([GetCapabilities](https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities)) - **déprécié (trop de résultats)**
|
|
139
|
+
* [gpf_wfs_search_types(keywords,max_results=10)](src/tools/GpfSearchFeatureTypes.ts) pour **rechercher les tables disponibles sur le WFS de la Géoplateforme** ([GetCapabilities](https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities))
|
|
140
|
+
|
|
141
|
+
> - Quels sont les millésimes ADMINEXPRESS disponibles sur la Géoplateforme?
|
|
142
|
+
> - Quelle est la table de la BDTOPO correspondant aux bâtiments?
|
|
143
|
+
> - Dans quelle table de la BDTOPO peut-on trouver les ponts?
|
|
144
|
+
|
|
145
|
+
#### Explorer la structure des tables
|
|
146
|
+
|
|
147
|
+
* [gpf_wfs_describe_type(typename)](src/tools/GpfWfsDescribeTypeTool.ts) pour récupérer le **schéma d'une table** ([DescribeFeatureType](https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=DescribeFeatureType&typename=ADMINEXPRESS-COG.LATEST:commune&outputFormat=application/json))
|
|
148
|
+
|
|
149
|
+
> - Quelles sont les informations disponibles pour les communes avec ADMINEXPRESS-COG.LATEST?
|
|
150
|
+
> - Compare le modèle des communes entre ADMINEXPRESS-COG:2024 et ADMINEXPRESS-COG.LATEST
|
|
151
|
+
|
|
152
|
+
#### Explorer les données des tables
|
|
153
|
+
|
|
154
|
+
* [gpf_wfs_get_features(typename,...)](src/tools/GpfWfsGetFeaturesTool.ts) pour **récupérer les données d'une table** ([GetFeature](https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetFeature&typename=ADMINEXPRESS-COG.LATEST:commune&outputFormat=application/json&count=1))
|
|
155
|
+
|
|
156
|
+
> - Quelles sont les 5 communes les plus peuplées du Doubs (25)?
|
|
157
|
+
> - Combien y-a-t'il de bâtiments à moins de 5 km de la tour Eiffel?
|
|
158
|
+
|
|
159
|
+
## Contribution
|
|
160
|
+
|
|
161
|
+
### Problèmes et demandes d'évolutions
|
|
162
|
+
|
|
163
|
+
N'hésitez pas à [créer une issue](https://github.com/ignfab/geocontext/issues) si vous rencontrez un problème! Merci de fournir :
|
|
164
|
+
|
|
165
|
+
- L'assistant et le modèle utilisé
|
|
166
|
+
- La demande que vous faite à l'assistant (ex : "Combien y a-t'il de pont franchissant la seine?")
|
|
167
|
+
|
|
168
|
+
### Proposer une nouvelle fonctionnalité
|
|
169
|
+
|
|
170
|
+
N'hésitez pas :
|
|
171
|
+
|
|
172
|
+
- Forker le dépôt
|
|
173
|
+
- Créer un nouveau tool
|
|
174
|
+
- Tester de votre côté
|
|
175
|
+
- Faire une pull-request
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
## Crédits
|
|
180
|
+
|
|
181
|
+
* [mcp-framework](https://mcp-framework.com) fournit le **cadre de développement du MCP** :
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Par exemple, pour exposer la liste des couches WMTS
|
|
185
|
+
mcp add tool gpf_wmts_layers
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
* [@camptocamp/ogc-client](https://camptocamp.github.io/ogc-client/#/) pour la **lecture des réponses XML des services WFS, WMTS,...**
|
|
189
|
+
* [MiniSearch](https://github.com/lucaong/minisearch) pour la **recherche par mot clé**.
|
|
190
|
+
* [jsts](https://bjornharrtell.github.io/jsts/) pour les **traitements géométriques** (ex : tri des réponses par distance au point recherché).
|
|
191
|
+
|
|
192
|
+
## Licence
|
|
193
|
+
|
|
194
|
+
[MIT](LICENSE)
|
|
195
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get administrative units (commune, departement,...) intersecting a given location
|
|
3
|
+
*
|
|
4
|
+
* @param {number} lon
|
|
5
|
+
* @param {number} lat
|
|
6
|
+
* @returns {object[]}
|
|
7
|
+
*/
|
|
8
|
+
export function getAdminUnits(lon: number, lat: number): object[];
|
|
9
|
+
/**
|
|
10
|
+
* ADMINEXPRESS-COG.LATEST:{type}
|
|
11
|
+
*
|
|
12
|
+
* https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
13
|
+
*/
|
|
14
|
+
export const ADMINEXPRESS_SOURCE: "G\u00E9oplateforme (WFS, ADMINEXPRESS-COG.LATEST)";
|
|
15
|
+
export const ADMINEXPRESS_TYPES: string[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { fetchJSON } from '../helpers/http.js';
|
|
2
|
+
import logger from '../logger.js';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
/**
|
|
5
|
+
* ADMINEXPRESS-COG.LATEST:{type}
|
|
6
|
+
*
|
|
7
|
+
* https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
8
|
+
*/
|
|
9
|
+
export const ADMINEXPRESS_SOURCE = "Géoplateforme (WFS, ADMINEXPRESS-COG.LATEST)";
|
|
10
|
+
export const ADMINEXPRESS_TYPES = [
|
|
11
|
+
'commune',
|
|
12
|
+
'canton',
|
|
13
|
+
'collectivite_territoriale',
|
|
14
|
+
'epci',
|
|
15
|
+
'departement',
|
|
16
|
+
'region',
|
|
17
|
+
'arrondissement'
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Get administrative units (commune, departement,...) intersecting a given location
|
|
21
|
+
*
|
|
22
|
+
* @param {number} lon
|
|
23
|
+
* @param {number} lat
|
|
24
|
+
* @returns {object[]}
|
|
25
|
+
*/
|
|
26
|
+
export async function getAdminUnits(lon, lat) {
|
|
27
|
+
logger.info(`[adminexpress] getAdminUnits(${lon},${lat})...`);
|
|
28
|
+
// note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
|
|
29
|
+
const cql_filter = `INTERSECTS(geometrie,Point(${lat} ${lon}))`;
|
|
30
|
+
// TODO : avoid useless geometry retrieval at WFS level
|
|
31
|
+
const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
|
|
32
|
+
service: 'WFS',
|
|
33
|
+
request: 'GetFeature',
|
|
34
|
+
typeName: ADMINEXPRESS_TYPES.map((type) => { return `ADMINEXPRESS-COG.LATEST:${type}`; }).join(','),
|
|
35
|
+
outputFormat: 'application/json',
|
|
36
|
+
cql_filter: cql_filter
|
|
37
|
+
}).toString();
|
|
38
|
+
const featureCollection = await fetchJSON(url);
|
|
39
|
+
return featureCollection.features.map((feature) => {
|
|
40
|
+
// parse type from id (ex: "commune.3837")
|
|
41
|
+
const type = feature.id.split('.')[0];
|
|
42
|
+
// ignore geometry and extend properties
|
|
43
|
+
return Object.assign({
|
|
44
|
+
type: type,
|
|
45
|
+
id: feature.id,
|
|
46
|
+
bbox: feature.bbox
|
|
47
|
+
}, feature.properties);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=adminexpress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,8CAA8C,CAAC;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAC9B,SAAS;IACT,QAAQ;IACR,2BAA2B;IAC3B,MAAM;IACN,aAAa;IACb,QAAQ;IACR,gBAAgB;CACnB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAG,EAAE,GAAG;IACxC,MAAM,CAAC,IAAI,CAAC,gCAAgC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAE9D,kFAAkF;IAClF,MAAM,UAAU,GAAG,8BAA8B,GAAG,IAAI,GAAG,IAAI,CAAC;IAEhE,uDAAuD;IACvD,MAAM,GAAG,GAAG,4BAA4B,GAAG,IAAI,eAAe,CAAC;QAC3D,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,2BAA2B,IAAI,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAClG,YAAY,EAAE,kBAAkB;QAChC,UAAU,EAAE,UAAU;KACzB,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,iBAAiB,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9C,0CAA0C;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,wCAAwC;QACxC,OAAO,MAAM,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;SACrB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get altitude for a given location.
|
|
3
|
+
*
|
|
4
|
+
* @see https://geoservices.ign.fr/documentation/services/services-deprecies/calcul-altimetrique-rest#1872
|
|
5
|
+
*
|
|
6
|
+
* @param {number} lon
|
|
7
|
+
* @param {number} lat
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
export function getAltitudeByLocation(lon: number, lat: number): Promise<{
|
|
11
|
+
lon: number;
|
|
12
|
+
lat: number;
|
|
13
|
+
altitude: any;
|
|
14
|
+
accuracy: any;
|
|
15
|
+
}>;
|
|
16
|
+
export const ALTITUDE_SOURCE: "G\u00E9oplateforme (altim\u00E9trie)";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import logger from "../logger.js";
|
|
2
|
+
import { fetchJSON } from "../helpers/http.js";
|
|
3
|
+
export const ALTITUDE_SOURCE = "Géoplateforme (altimétrie)";
|
|
4
|
+
/**
|
|
5
|
+
* Get altitude for a given location.
|
|
6
|
+
*
|
|
7
|
+
* @see https://geoservices.ign.fr/documentation/services/services-deprecies/calcul-altimetrique-rest#1872
|
|
8
|
+
*
|
|
9
|
+
* @param {number} lon
|
|
10
|
+
* @param {number} lat
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export async function getAltitudeByLocation(lon, lat) {
|
|
14
|
+
logger.info(`getAltitudeByLocation(${lon},${lat})...`);
|
|
15
|
+
const url = `https://data.geopf.fr/altimetrie/1.0/calcul/alti/rest/elevation.json?lon=${lon}&lat=${lat}&resource=ign_rge_alti_wld`;
|
|
16
|
+
try {
|
|
17
|
+
const json = await fetchJSON(url);
|
|
18
|
+
const elevation = json.elevations[0];
|
|
19
|
+
return {
|
|
20
|
+
lon: lon,
|
|
21
|
+
lat: lat,
|
|
22
|
+
altitude: elevation.z,
|
|
23
|
+
accuracy: elevation.acc,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
return {
|
|
28
|
+
lon: lon,
|
|
29
|
+
lat: lat,
|
|
30
|
+
altitude: null,
|
|
31
|
+
accuracy: 'No data',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=altitude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"altitude.js","sourceRoot":"","sources":["../../src/gpf/altitude.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG;IAChD,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAEvD,MAAM,GAAG,GAAG,4EAA4E,GAAG,QAAQ,GAAG,4BAA4B,CAAC;IACnI,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAE;QACtC,OAAO;YACH,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG;YACR,QAAQ,EAAE,SAAS,CAAC,CAAC;YACrB,QAAQ,EAAE,SAAS,CAAC,GAAG;SAC1B,CAAC;IACN,CAAC;IAAA,OAAM,CAAC,EAAC,CAAC;QACN,OAAO;YACH,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,SAAS;SACtB,CAAC;IACN,CAAC;AAGL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get coordinates for a given location
|
|
3
|
+
*
|
|
4
|
+
* @see https://geoservices.ign.fr/documentation/services/services-geoplateforme/autocompletion
|
|
5
|
+
*
|
|
6
|
+
* @param {string} text
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export function geocode(text: string): Promise<any>;
|
|
10
|
+
export const GEOCODE_SOURCE: "G\u00E9oplateforme (service d'autocompl\u00E9tion)";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import logger from "../logger.js";
|
|
2
|
+
import { fetchJSON } from "../helpers/http.js";
|
|
3
|
+
export const GEOCODE_SOURCE = "Géoplateforme (service d'autocomplétion)";
|
|
4
|
+
/**
|
|
5
|
+
* Get coordinates for a given location
|
|
6
|
+
*
|
|
7
|
+
* @see https://geoservices.ign.fr/documentation/services/services-geoplateforme/autocompletion
|
|
8
|
+
*
|
|
9
|
+
* @param {string} text
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export async function geocode(text) {
|
|
13
|
+
logger.info(`geocode(${JSON.stringify(text)})...`);
|
|
14
|
+
const url = 'https://data.geopf.fr/geocodage/completion/?' + new URLSearchParams({
|
|
15
|
+
text: text,
|
|
16
|
+
maximumResponses: 3
|
|
17
|
+
}).toString();
|
|
18
|
+
const json = await fetchJSON(url);
|
|
19
|
+
return json.results.map((item) => {
|
|
20
|
+
return {
|
|
21
|
+
lon: item.x,
|
|
22
|
+
lat: item.y,
|
|
23
|
+
fulltext: item.fulltext
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=geocode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geocode.js","sourceRoot":"","sources":["../../src/gpf/geocode.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAI;IAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEnD,MAAM,GAAG,GAAG,8CAA8C,GAAG,IAAI,eAAe,CAAC;QAC/E,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,CAAC;KACpB,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAC,EAAE;QAAC,OAAO;YACtC,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAA;IAAA,CAAC,CAAC,CAAC;AACR,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get items from CADASTRALPARCELS.PARCELLAIRE_EXPRESS near of a given location.
|
|
3
|
+
*
|
|
4
|
+
* @see https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
5
|
+
*
|
|
6
|
+
* @param {number} lon
|
|
7
|
+
* @param {number} lat
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
export function getParcellaireExpress(lon: number, lat: number): Promise<array<object>>;
|
|
11
|
+
export const PARCELLAIRE_EXPRESS_SOURCE: "G\u00E9oplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
|
|
12
|
+
export const PARCELLAIRE_EXPRESS_TYPES: string[];
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import logger from '../logger.js';
|
|
2
|
+
import distance from '../helpers/distance.js';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import { fetchJSON } from '../helpers/http.js';
|
|
5
|
+
// CADASTRALPARCELS.PARCELLAIRE_EXPRESS:
|
|
6
|
+
// https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
7
|
+
export const PARCELLAIRE_EXPRESS_SOURCE = "Géoplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
|
|
8
|
+
export const PARCELLAIRE_EXPRESS_TYPES = [
|
|
9
|
+
'arrondissement',
|
|
10
|
+
'commune',
|
|
11
|
+
'feuille',
|
|
12
|
+
'parcelle',
|
|
13
|
+
'subdivision_fiscale',
|
|
14
|
+
'localisant'
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Filter items by distance keeping the nearest for each type.
|
|
18
|
+
*
|
|
19
|
+
* @param {array<object>} items
|
|
20
|
+
* @returns {array<object>}
|
|
21
|
+
*/
|
|
22
|
+
function filterByDistance(items) {
|
|
23
|
+
const sortedItems = _.orderBy(items, ['type', 'distance'], ['asc', 'asc']);
|
|
24
|
+
const result = [];
|
|
25
|
+
let lastType = null;
|
|
26
|
+
for (const item of sortedItems) {
|
|
27
|
+
if (lastType == item.type) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
result.push(item);
|
|
31
|
+
lastType = item.type;
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get items from CADASTRALPARCELS.PARCELLAIRE_EXPRESS near of a given location.
|
|
37
|
+
*
|
|
38
|
+
* @see https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
39
|
+
*
|
|
40
|
+
* @param {number} lon
|
|
41
|
+
* @param {number} lat
|
|
42
|
+
* @returns
|
|
43
|
+
*/
|
|
44
|
+
export async function getParcellaireExpress(lon, lat) {
|
|
45
|
+
logger.info(`getParcellaireExpress(${lon},${lat}) ...`);
|
|
46
|
+
// note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
|
|
47
|
+
const cql_filter = `DWITHIN(geom,Point(${lat} ${lon}),10,meters)`;
|
|
48
|
+
const sourceGeom = {
|
|
49
|
+
"type": "Point",
|
|
50
|
+
"coordinates": [lon, lat]
|
|
51
|
+
};
|
|
52
|
+
// TODO : avoid useless geometry retrieval at WFS level
|
|
53
|
+
const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
|
|
54
|
+
service: 'WFS',
|
|
55
|
+
request: 'GetFeature',
|
|
56
|
+
typeName: PARCELLAIRE_EXPRESS_TYPES.map((type) => { return `CADASTRALPARCELS.PARCELLAIRE_EXPRESS:${type}`; }).join(','),
|
|
57
|
+
outputFormat: 'application/json',
|
|
58
|
+
cql_filter: cql_filter
|
|
59
|
+
}).toString();
|
|
60
|
+
const featureCollection = await fetchJSON(url);
|
|
61
|
+
return filterByDistance(featureCollection.features.map((feature) => {
|
|
62
|
+
// parse type from id (ex: "commune.3837")
|
|
63
|
+
const type = feature.id.split('.')[0];
|
|
64
|
+
// ignore geometry and extend properties
|
|
65
|
+
return Object.assign({
|
|
66
|
+
type: type,
|
|
67
|
+
id: feature.id,
|
|
68
|
+
bbox: feature.bbox,
|
|
69
|
+
distance: distance(sourceGeom, feature.geometry),
|
|
70
|
+
source: PARCELLAIRE_EXPRESS_SOURCE,
|
|
71
|
+
}, feature.properties);
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=parcellaire-express.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parcellaire-express.js","sourceRoot":"","sources":["../../src/gpf/parcellaire-express.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAE9C,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,wCAAwC;AACxC,kFAAkF;AAElF,MAAM,CAAC,MAAM,0BAA0B,GAAG,2DAA2D,CAAC;AACtG,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACrC,gBAAgB;IAChB,SAAS;IACT,SAAS;IACT,UAAU;IACV,qBAAqB;IACrB,YAAY;CACf,CAAC;AAEF;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,KAAK;IAC3B,MAAM,WAAW,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAE3E,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,KAAM,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACzB,SAAS;QACb,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAGD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG;IAChD,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC;IACxD,kFAAkF;IAClF,MAAM,UAAU,GAAG,sBAAsB,GAAG,IAAI,GAAG,cAAc,CAAC;IAElE,MAAM,UAAU,GAAG;QACf,MAAM,EAAE,OAAO;QACf,aAAa,EAAE,CAAC,GAAG,EAAC,GAAG,CAAC;KAC3B,CAAC;IAEF,uDAAuD;IACvD,MAAM,GAAG,GAAG,4BAA4B,GAAG,IAAI,eAAe,CAAC;QAC3D,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,wCAAwC,IAAI,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACtH,YAAY,EAAE,kBAAkB;QAChC,UAAU,EAAE,UAAU;KACzB,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,iBAAiB,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC/D,0CAA0C;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,wCAAwC;QACxC,OAAO,MAAM,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,QAAQ,CACd,UAAU,EACV,OAAO,CAAC,QAAQ,CACnB;YACD,MAAM,EAAE,0BAA0B;SACrC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC,CAAC;AACR,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get urbanism infos for a given location
|
|
3
|
+
*
|
|
4
|
+
* @param {number} lon
|
|
5
|
+
* @param {number} lat
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function getUrbanisme(lon: number, lat: number): Promise<any>;
|
|
9
|
+
/**
|
|
10
|
+
* Get SUP infos for a given location
|
|
11
|
+
*
|
|
12
|
+
* @param {number} lon
|
|
13
|
+
* @param {number} lat
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
export function getAssiettesServitudes(lon: number, lat: number): Promise<any>;
|
|
17
|
+
export const URBANISME_TYPES: string[];
|
|
18
|
+
export const URBANISME_SOURCE: "G\u00E9oplateforme - (WFS G\u00E9oportail de l'Urbanisme)";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import distance from "../helpers/distance.js";
|
|
2
|
+
import { fetchJSON } from "../helpers/http.js";
|
|
3
|
+
import logger from "../logger.js";
|
|
4
|
+
// https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
5
|
+
export const URBANISME_TYPES = [
|
|
6
|
+
'wfs_scot:scot',
|
|
7
|
+
'wfs_du:document',
|
|
8
|
+
'wfs_du:zone_urba',
|
|
9
|
+
'wfs_du:secteur_cc',
|
|
10
|
+
'wfs_du:info_pct',
|
|
11
|
+
'wfs_du:info_lin',
|
|
12
|
+
'wfs_du:info_surf',
|
|
13
|
+
'wfs_du:prescription_pct',
|
|
14
|
+
'wfs_du:prescription_lin',
|
|
15
|
+
'wfs_du:prescription_surf'
|
|
16
|
+
];
|
|
17
|
+
export const URBANISME_SOURCE = "Géoplateforme - (WFS Géoportail de l'Urbanisme)";
|
|
18
|
+
/**
|
|
19
|
+
* Get urbanism infos for a given location
|
|
20
|
+
*
|
|
21
|
+
* @param {number} lon
|
|
22
|
+
* @param {number} lat
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
export async function getUrbanisme(lon, lat) {
|
|
26
|
+
logger.info(`getUrbanisme(${lon},${lat})...`);
|
|
27
|
+
// note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
|
|
28
|
+
const cql_filter = `DWITHIN(the_geom,Point(${lat} ${lon}),30,meters)`;
|
|
29
|
+
const sourceGeom = {
|
|
30
|
+
"type": "Point",
|
|
31
|
+
"coordinates": [lon, lat]
|
|
32
|
+
};
|
|
33
|
+
// TODO : avoid useless geometry retrieval at WFS level
|
|
34
|
+
const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
|
|
35
|
+
service: 'WFS',
|
|
36
|
+
request: 'GetFeature',
|
|
37
|
+
typeName: URBANISME_TYPES.join(','),
|
|
38
|
+
outputFormat: 'application/json',
|
|
39
|
+
cql_filter: cql_filter
|
|
40
|
+
}).toString();
|
|
41
|
+
const featureCollection = await fetchJSON(url);
|
|
42
|
+
return featureCollection.features.map((feature) => {
|
|
43
|
+
// parse type from id (ex: "commune.3837")
|
|
44
|
+
const type = feature.id.split('.')[0];
|
|
45
|
+
// ignore geometry and extend properties
|
|
46
|
+
return Object.assign({
|
|
47
|
+
type: type,
|
|
48
|
+
id: feature.id,
|
|
49
|
+
bbox: feature.bbox,
|
|
50
|
+
distance: (distance(sourceGeom, feature.geometry) * 1000.0)
|
|
51
|
+
}, feature.properties);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const ASSIETTES_SUP_TYPES = [
|
|
55
|
+
'wfs_sup:assiette_sup_p',
|
|
56
|
+
'wfs_sup:assiette_sup_l',
|
|
57
|
+
'wfs_sup:assiette_sup_s',
|
|
58
|
+
];
|
|
59
|
+
/**
|
|
60
|
+
* Get SUP infos for a given location
|
|
61
|
+
*
|
|
62
|
+
* @param {number} lon
|
|
63
|
+
* @param {number} lat
|
|
64
|
+
* @returns
|
|
65
|
+
*/
|
|
66
|
+
export async function getAssiettesServitudes(lon, lat) {
|
|
67
|
+
logger.info(`getAssiettesServitudes(${lon},${lat})...`);
|
|
68
|
+
// note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
|
|
69
|
+
const cql_filter = `DWITHIN(the_geom,Point(${lat} ${lon}),30,meters)`;
|
|
70
|
+
const sourceGeom = {
|
|
71
|
+
"type": "Point",
|
|
72
|
+
"coordinates": [lon, lat]
|
|
73
|
+
};
|
|
74
|
+
// TODO : avoid useless geometry retrieval at WFS level
|
|
75
|
+
const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
|
|
76
|
+
service: 'WFS',
|
|
77
|
+
request: 'GetFeature',
|
|
78
|
+
typeName: ASSIETTES_SUP_TYPES.join(','),
|
|
79
|
+
outputFormat: 'application/json',
|
|
80
|
+
cql_filter: cql_filter
|
|
81
|
+
}).toString();
|
|
82
|
+
const featureCollection = await fetchJSON(url);
|
|
83
|
+
return featureCollection.features.map((feature) => {
|
|
84
|
+
// parse type from id (ex: "commune.3837")
|
|
85
|
+
const type = feature.id.split('.')[0];
|
|
86
|
+
// ignore geometry and extend properties
|
|
87
|
+
return Object.assign({
|
|
88
|
+
type: type,
|
|
89
|
+
id: feature.id,
|
|
90
|
+
bbox: feature.bbox,
|
|
91
|
+
distance: (distance(sourceGeom, feature.geometry) * 1000.0)
|
|
92
|
+
}, feature.properties);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=urbanisme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urbanisme.js","sourceRoot":"","sources":["../../src/gpf/urbanisme.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const GPF_WFS_URL = "https://data.geopf.fr/wfs";
|
|
2
|
+
import { WfsFeatureTypeBrief, WfsFeatureTypeFull } from "@camptocamp/ogc-client";
|
|
3
|
+
export declare class FeatureTypeNotFoundError extends Error {
|
|
4
|
+
constructor(name: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class FeatureTypeSearch {
|
|
7
|
+
private featureTypes;
|
|
8
|
+
private miniSearch;
|
|
9
|
+
constructor(featureTypes: WfsFeatureTypeBrief[]);
|
|
10
|
+
search(query: string): import("minisearch").SearchResult[];
|
|
11
|
+
}
|
|
12
|
+
export declare class WfsClient {
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
private endpoint;
|
|
15
|
+
private featureTypes;
|
|
16
|
+
private featureTypeSearch;
|
|
17
|
+
constructor(baseUrl?: string);
|
|
18
|
+
getFeatureTypes(): Promise<WfsFeatureTypeBrief[]>;
|
|
19
|
+
searchFeatureTypes(query: string, maxResults?: number): Promise<WfsFeatureTypeBrief[]>;
|
|
20
|
+
getFeatureType(name: string): Promise<WfsFeatureTypeFull>;
|
|
21
|
+
}
|
|
22
|
+
export declare const wfsClient: WfsClient;
|