@ignfab/geocontext 0.9.2 → 0.9.5
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 +46 -28
- package/dist/gpf/adminexpress.js +7 -27
- package/dist/gpf/adminexpress.js.map +1 -1
- package/dist/gpf/parcellaire-express.js +13 -33
- package/dist/gpf/parcellaire-express.js.map +1 -1
- package/dist/gpf/urbanisme.d.ts +4 -2
- package/dist/gpf/urbanisme.js +20 -61
- package/dist/gpf/urbanisme.js.map +1 -1
- package/dist/gpf/wfs.d.ts +2 -2
- package/dist/gpf/wfs.js +17 -71
- package/dist/gpf/wfs.js.map +1 -1
- package/dist/helpers/distance.d.ts +4 -2
- package/dist/helpers/distance.js +20 -5
- package/dist/helpers/distance.js.map +1 -1
- package/dist/helpers/http.d.ts +4 -0
- package/dist/helpers/http.js +103 -1
- package/dist/helpers/http.js.map +1 -1
- package/dist/helpers/jsonSchema.d.ts +3 -0
- package/dist/helpers/jsonSchema.js +8 -0
- package/dist/helpers/jsonSchema.js.map +1 -0
- package/dist/helpers/schemas.d.ts +13 -0
- package/dist/helpers/schemas.js +18 -0
- package/dist/helpers/schemas.js.map +1 -0
- package/dist/helpers/toolAnnotations.d.ts +6 -0
- package/dist/helpers/toolAnnotations.js.map +1 -0
- package/dist/helpers/wfs.d.ts +27 -0
- package/dist/helpers/wfs.js +55 -0
- package/dist/helpers/wfs.js.map +1 -0
- package/dist/helpers/wfs_internal/compile.d.ts +46 -0
- package/dist/helpers/wfs_internal/compile.js +595 -0
- package/dist/helpers/wfs_internal/compile.js.map +1 -0
- package/dist/helpers/wfs_internal/request.d.ts +38 -0
- package/dist/helpers/wfs_internal/request.js +92 -0
- package/dist/helpers/wfs_internal/request.js.map +1 -0
- package/dist/helpers/wfs_internal/response.d.ts +21 -0
- package/dist/helpers/wfs_internal/response.js +29 -0
- package/dist/helpers/wfs_internal/response.js.map +1 -0
- package/dist/helpers/wfs_internal/schema.d.ts +167 -0
- package/dist/helpers/wfs_internal/schema.js +81 -0
- package/dist/helpers/wfs_internal/schema.js.map +1 -0
- package/dist/index.js +47 -25
- package/dist/index.js.map +1 -1
- package/dist/tools/AdminexpressTool.d.ts +56 -6
- package/dist/tools/AdminexpressTool.js +12 -15
- package/dist/tools/AdminexpressTool.js.map +1 -1
- package/dist/tools/AltitudeTool.d.ts +6 -6
- package/dist/tools/AltitudeTool.js +5 -14
- package/dist/tools/AltitudeTool.js.map +1 -1
- package/dist/tools/AssietteSupTool.d.ts +59 -7
- package/dist/tools/AssietteSupTool.js +13 -16
- package/dist/tools/AssietteSupTool.js.map +1 -1
- package/dist/tools/CadastreTool.d.ts +56 -6
- package/dist/tools/CadastreTool.js +14 -16
- package/dist/tools/CadastreTool.js.map +1 -1
- package/dist/tools/GeocodeTool.d.ts +6 -6
- package/dist/tools/GeocodeTool.js +7 -5
- package/dist/tools/GeocodeTool.js.map +1 -1
- package/dist/tools/GpfWfsDescribeTypeTool.d.ts +20 -20
- package/dist/tools/GpfWfsDescribeTypeTool.js +5 -4
- package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -1
- package/dist/tools/GpfWfsGetFeaturesTool.d.ts +174 -48
- package/dist/tools/GpfWfsGetFeaturesTool.js +162 -115
- package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -1
- package/dist/tools/GpfWfsSearchTypesTool.d.ts +12 -6
- package/dist/tools/GpfWfsSearchTypesTool.js +13 -10
- package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -1
- package/dist/tools/UrbanismeTool.d.ts +57 -7
- package/dist/tools/UrbanismeTool.js +10 -16
- package/dist/tools/UrbanismeTool.js.map +1 -1
- package/package.json +11 -6
- package/dist/resources/WfsCqlFilterResource.d.ts +0 -10
- package/dist/resources/WfsCqlFilterResource.js +0 -21
- package/dist/resources/WfsCqlFilterResource.js.map +0 -1
- package/dist/resources/readMarkdownResource.d.ts +0 -1
- package/dist/resources/readMarkdownResource.js +0 -21
- package/dist/resources/readMarkdownResource.js.map +0 -1
- package/dist/tools/GpfWfsListTypesTool.d.ts +0 -22
- package/dist/tools/GpfWfsListTypesTool.js +0 -26
- package/dist/tools/GpfWfsListTypesTool.js.map +0 -1
- package/dist/tools/toolAnnotations.d.ts +0 -6
- package/dist/tools/toolAnnotations.js.map +0 -1
- /package/dist/{tools → helpers}/toolAnnotations.js +0 -0
package/README.md
CHANGED
|
@@ -42,19 +42,19 @@ Par exemple, avec "Cursor Settings / MCP / Add server" :
|
|
|
42
42
|
}
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
### Utilisation avec Docker
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
docker compose build
|
|
49
|
-
docker compose up -d
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Remarque :
|
|
53
|
-
|
|
54
|
-
- le `docker-compose.yaml` fournit `HTTP_HOST=0.0.0.0` pour rendre le serveur HTTP joignable depuis l'hôte ;
|
|
55
|
-
- sans ce paramètre, `mcp-framework` écoute par défaut sur `127.0.0.1` en mode HTTP, ce qui n'est pas adapté à une exécution en conteneur.
|
|
56
|
-
|
|
57
|
-
Ensuite :
|
|
45
|
+
### Utilisation avec Docker
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
docker compose build
|
|
49
|
+
docker compose up -d
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Remarque :
|
|
53
|
+
|
|
54
|
+
- le `docker-compose.yaml` fournit `HTTP_HOST=0.0.0.0` pour rendre le serveur HTTP joignable depuis l'hôte ;
|
|
55
|
+
- sans ce paramètre, `mcp-framework` écoute par défaut sur `127.0.0.1` en mode HTTP, ce qui n'est pas adapté à une exécution en conteneur.
|
|
56
|
+
|
|
57
|
+
Ensuite :
|
|
58
58
|
|
|
59
59
|
```json
|
|
60
60
|
{
|
|
@@ -123,11 +123,13 @@ npx -y @modelcontextprotocol/inspector node dist/index.js
|
|
|
123
123
|
|
|
124
124
|
Pour une utilisation avancée :
|
|
125
125
|
|
|
126
|
-
| Nom
|
|
127
|
-
|
|
|
128
|
-
| `TRANSPORT_TYPE`
|
|
129
|
-
| `HTTP_HOST`
|
|
130
|
-
| `GPF_WFS_MINISEARCH_OPTIONS` | Chaîne JSON optionnelle pour ajuster les options MiniSearch utilisées par `gpf_wfs_search_types` (`fields`, `combineWith`, `fuzzy`, `boost.namespace`, `boost.name`, `boost.title`, `boost.description`, `boost.properties`, `boost.enums`, `boost.identifierTokens`). | options par défaut de `@ignfab/gpf-schema-store` |
|
|
126
|
+
| Nom | Description | Valeur par défaut |
|
|
127
|
+
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
|
128
|
+
| `TRANSPORT_TYPE` | [Transport](https://mcp-framework.com/docs/Transports/transports-overview) permet de choisir entre "stdio" et "http" | "stdio" |
|
|
129
|
+
| `HTTP_HOST` | Adresse d'écoute en mode HTTP. Utile avec Docker pour exposer le service via `0.0.0.0`. | défaut `mcp-framework` (`127.0.0.1`) |
|
|
130
|
+
| `GPF_WFS_MINISEARCH_OPTIONS` | Chaîne JSON optionnelle pour ajuster les options MiniSearch utilisées par `gpf_wfs_search_types` (`fields`, `combineWith`, `fuzzy`, `boost.namespace`, `boost.name`, `boost.title`, `boost.description`, `boost.properties`, `boost.enums`, `boost.identifierTokens`). | options par défaut de `@ignfab/gpf-schema-store` |
|
|
131
|
+
| `LOG_FORMAT` | Le format d'écriture des logs : "json" ou "simple". | "simple" |
|
|
132
|
+
| `LOG_LEVEL` | Le niveau d'écriture des logs : ["error", "info", ou "debug"](https://github.com/winstonjs/winston#logging-levels) | "debug" |
|
|
131
133
|
|
|
132
134
|
Exemple :
|
|
133
135
|
|
|
@@ -139,7 +141,7 @@ Si `GPF_WFS_MINISEARCH_OPTIONS` est absent ou vide, les options par défaut rest
|
|
|
139
141
|
|
|
140
142
|
Remarque :
|
|
141
143
|
|
|
142
|
-
- Les outils `
|
|
144
|
+
- Les outils `gpf_wfs_search_types` et `gpf_wfs_describe_type` s'appuient sur un catalogue de schémas embarqué fourni par `@ignfab/gpf-schema-store`.
|
|
143
145
|
- L'outil `gpf_wfs_get_features` interroge toujours le service WFS de la Géoplateforme en direct.
|
|
144
146
|
- Le catalogue embarqué améliore la description des featureTypes mais il peut être légèrement décalé par rapport à l'état courant du WFS.
|
|
145
147
|
|
|
@@ -175,27 +177,43 @@ L'idée est ici de répondre à des précises en traitant côté serveur les app
|
|
|
175
177
|
|
|
176
178
|
* [assiette_sup(lon,lat)](src/tools/AssietteSupTool.ts) permet de **récupérer les Servitude d'Utilité Publiques (SUP)**
|
|
177
179
|
|
|
180
|
+
Les tools WFS orientés "objet" (`adminexpress`, `cadastre`, `urbanisme`, `assiette_sup`) exposent un `feature_ref { typename, feature_id }` quand l'objet source est réutilisable tel quel dans un appel ultérieur à `gpf_wfs_get_features`, notamment avec `spatial_operator="intersects_feature"`.
|
|
181
|
+
|
|
178
182
|
### Explorer les données vecteurs
|
|
179
183
|
|
|
180
|
-
#### Explorer les tables
|
|
181
|
-
|
|
182
|
-
* [
|
|
183
|
-
* [gpf_wfs_search_types(keywords,max_results=10)](src/tools/GpfWfsSearchTypesTool.ts) pour **rechercher un type WFS pertinent à partir de mots-clés et obtenir un `typename` valide**. La recherche est textuelle et configurable via `GPF_WFS_MINISEARCH_OPTIONS`.
|
|
184
|
+
#### Explorer les tables
|
|
185
|
+
|
|
186
|
+
* [gpf_wfs_search_types(keywords,max_results=10)](src/tools/GpfWfsSearchTypesTool.ts) pour **rechercher un type WFS pertinent à partir de mots-clés et obtenir un `typename` valide**. La recherche est textuelle et configurable via `GPF_WFS_MINISEARCH_OPTIONS`.
|
|
184
187
|
|
|
185
188
|
> - Quels sont les millésimes ADMINEXPRESS disponibles sur la Géoplateforme?
|
|
186
189
|
> - Quelle est la table de la BDTOPO correspondant aux bâtiments?
|
|
187
190
|
> - Dans quelle table de la BDTOPO peut-on trouver les ponts?
|
|
188
191
|
|
|
189
|
-
#### Explorer la structure des tables
|
|
190
|
-
|
|
191
|
-
* [gpf_wfs_describe_type(typename)](src/tools/GpfWfsDescribeTypeTool.ts) pour récupérer le **schéma détaillé d'un type WFS** depuis le catalogue embarqué (`id`, `namespace`, `name`, `title`, `description`, `properties`), en particulier avant d'appeler `gpf_wfs_get_features`
|
|
192
|
+
#### Explorer la structure des tables
|
|
193
|
+
|
|
194
|
+
* [gpf_wfs_describe_type(typename)](src/tools/GpfWfsDescribeTypeTool.ts) pour récupérer le **schéma détaillé d'un type WFS** depuis le catalogue embarqué (`id`, `namespace`, `name`, `title`, `description`, `properties`), en particulier avant d'appeler `gpf_wfs_get_features`
|
|
192
195
|
|
|
193
196
|
> - Quelles sont les informations disponibles pour les communes avec ADMINEXPRESS-COG.LATEST?
|
|
194
197
|
> - Compare le modèle des communes entre ADMINEXPRESS-COG:2024 et ADMINEXPRESS-COG.LATEST
|
|
195
198
|
|
|
196
199
|
#### Explorer les données des tables
|
|
197
200
|
|
|
198
|
-
* [gpf_wfs_get_features(typename,...)](src/tools/GpfWfsGetFeaturesTool.ts) pour **récupérer les données d'une table** depuis le service WFS de la Géoplateforme
|
|
201
|
+
* [gpf_wfs_get_features(typename,...)](src/tools/GpfWfsGetFeaturesTool.ts) pour **récupérer les données d'une table** depuis le service WFS de la Géoplateforme sans écrire de CQL à la main.
|
|
202
|
+
|
|
203
|
+
Le tool accepte un contrat structuré :
|
|
204
|
+
|
|
205
|
+
- `select` pour choisir les propriétés à renvoyer
|
|
206
|
+
- `where` pour filtrer les objets
|
|
207
|
+
- `order_by` pour trier les résultats
|
|
208
|
+
- `spatial_operator` et ses paramètres dédiés pour le spatial en `lon/lat`
|
|
209
|
+
- `result_type="request"` pour récupérer la requête compilée en `POST`, ainsi qu'une `get_url` dérivée quand elle reste raisonnablement portable en GET
|
|
210
|
+
|
|
211
|
+
Exemples :
|
|
212
|
+
|
|
213
|
+
- `where=[{ property: "code_insee", operator: "eq", value: "25000" }]`
|
|
214
|
+
- `spatial_operator="bbox"` avec `bbox_west`, `bbox_south`, `bbox_east`, `bbox_north`
|
|
215
|
+
- `spatial_operator="dwithin_point"` avec `dwithin_lon`, `dwithin_lat`, `dwithin_distance_m`
|
|
216
|
+
- `spatial_operator="intersects_feature"` avec `intersects_feature_typename` et `intersects_feature_id` issus d'une `feature_ref`
|
|
199
217
|
|
|
200
218
|
> - Quelles sont les 5 communes les plus peuplées du Doubs (25)?
|
|
201
219
|
> - Combien y-a-t'il de bâtiments à moins de 5 km de la tour Eiffel?
|
|
@@ -229,10 +247,10 @@ N'hésitez pas :
|
|
|
229
247
|
mcp add tool gpf_wmts_layers
|
|
230
248
|
```
|
|
231
249
|
|
|
232
|
-
* [@camptocamp/ogc-client](https://camptocamp.github.io/ogc-client/#/) pour la **lecture des réponses XML des services WFS, WMTS,...**
|
|
233
250
|
* [@ignfab/gpf-schema-store](https://www.npmjs.com/package/@ignfab/gpf-schema-store) pour le **catalogue de schémas embarqué** utilisé par les outils d'exploration WFS.
|
|
234
251
|
* [MiniSearch](https://github.com/lucaong/minisearch) pour la **recherche par mot clé** utilisée dans `@ignfab/gpf-schema-store`.
|
|
235
252
|
* [jsts](https://bjornharrtell.github.io/jsts/) pour les **traitements géométriques** (ex : tri des réponses par distance au point recherché).
|
|
253
|
+
* [turfjs/distance](https://turfjs.org/docs/api/distance) pour les **calculs de distance** avec la [formule de Haversine](https://en.wikipedia.org/wiki/Haversine_formula).
|
|
236
254
|
|
|
237
255
|
## Licence
|
|
238
256
|
|
package/dist/gpf/adminexpress.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { fetchJSON } from '../helpers/http.js';
|
|
1
|
+
import { fetchWfsFeatures, mapWfsFeature } from '../helpers/wfs.js';
|
|
3
2
|
import logger from '../logger.js';
|
|
4
3
|
/**
|
|
5
4
|
* ADMINEXPRESS-COG.LATEST:{type}
|
|
@@ -24,31 +23,12 @@ export const ADMINEXPRESS_TYPES = [
|
|
|
24
23
|
* @param {(url: string) => Promise<any>} [fetcher]
|
|
25
24
|
* @returns {object[]}
|
|
26
25
|
*/
|
|
27
|
-
export async function getAdminUnits(lon, lat, fetcher
|
|
26
|
+
export async function getAdminUnits(lon, lat, fetcher) {
|
|
28
27
|
logger.info(`[adminexpress] getAdminUnits(${lon},${lat})...`);
|
|
29
|
-
//
|
|
30
|
-
const cql_filter = `INTERSECTS(geometrie,
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
request: 'GetFeature',
|
|
35
|
-
typeName: ADMINEXPRESS_TYPES.map((type) => { return `ADMINEXPRESS-COG.LATEST:${type}`; }).join(','),
|
|
36
|
-
outputFormat: 'application/json',
|
|
37
|
-
cql_filter: cql_filter
|
|
38
|
-
}).toString();
|
|
39
|
-
const featureCollection = await fetcher(url);
|
|
40
|
-
if (!Array.isArray(featureCollection?.features)) {
|
|
41
|
-
throw new Error("Le service ADMINEXPRESS n'a pas retourné de collection d'objets exploitable");
|
|
42
|
-
}
|
|
43
|
-
return featureCollection.features.map((feature) => {
|
|
44
|
-
// parse type from id (ex: "commune.3837")
|
|
45
|
-
const type = feature.id.split('.')[0];
|
|
46
|
-
// ignore geometry and extend properties
|
|
47
|
-
return Object.assign({
|
|
48
|
-
type: type,
|
|
49
|
-
id: feature.id,
|
|
50
|
-
bbox: feature.bbox
|
|
51
|
-
}, feature.properties);
|
|
52
|
-
});
|
|
28
|
+
// Using EWKT format with SRID=4326 prefix for standard lon,lat order
|
|
29
|
+
const cql_filter = `INTERSECTS(geometrie,SRID=4326;POINT(${lon} ${lat}))`;
|
|
30
|
+
const typeNames = ADMINEXPRESS_TYPES.map((type) => `ADMINEXPRESS-COG.LATEST:${type}`);
|
|
31
|
+
const features = await fetchWfsFeatures(typeNames, cql_filter, 'ADMINEXPRESS', fetcher);
|
|
32
|
+
return features.map((feature) => mapWfsFeature(feature, typeNames));
|
|
53
33
|
}
|
|
54
34
|
//# sourceMappingURL=adminexpress.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.js"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC;;;;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;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO;IACjD,MAAM,CAAC,IAAI,CAAC,gCAAgC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAE9D,qEAAqE;IACrE,MAAM,UAAU,GAAG,wCAAwC,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1E,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;IAEtF,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IACxF,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import distance from '../helpers/distance.js';
|
|
3
|
-
import {
|
|
3
|
+
import { fetchWfsFeatures, mapWfsFeature, toGeoJsonPoint } from '../helpers/wfs.js';
|
|
4
4
|
import logger from '../logger.js';
|
|
5
5
|
// CADASTRALPARCELS.PARCELLAIRE_EXPRESS:
|
|
6
6
|
// https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
@@ -24,7 +24,7 @@ function filterByDistance(items) {
|
|
|
24
24
|
const result = [];
|
|
25
25
|
let lastType = null;
|
|
26
26
|
for (const item of sortedItems) {
|
|
27
|
-
if (lastType
|
|
27
|
+
if (lastType === item.type) {
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
30
|
result.push(item);
|
|
@@ -42,37 +42,17 @@ function filterByDistance(items) {
|
|
|
42
42
|
* @param {(url: string) => Promise<any>} [fetcher]
|
|
43
43
|
* @returns
|
|
44
44
|
*/
|
|
45
|
-
export async function getParcellaireExpress(lon, lat, fetcher
|
|
45
|
+
export async function getParcellaireExpress(lon, lat, fetcher) {
|
|
46
46
|
logger.info(`getParcellaireExpress(${lon},${lat}) ...`);
|
|
47
|
-
//
|
|
48
|
-
const cql_filter = `DWITHIN(geom,
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
typeName: PARCELLAIRE_EXPRESS_TYPES.map((type) => { return `CADASTRALPARCELS.PARCELLAIRE_EXPRESS:${type}`; }).join(','),
|
|
58
|
-
outputFormat: 'application/json',
|
|
59
|
-
cql_filter: cql_filter
|
|
60
|
-
}).toString();
|
|
61
|
-
const featureCollection = await fetcher(url);
|
|
62
|
-
if (!Array.isArray(featureCollection?.features)) {
|
|
63
|
-
throw new Error("Le service PARCELLAIRE_EXPRESS n'a pas retourné de collection d'objets exploitable");
|
|
64
|
-
}
|
|
65
|
-
return filterByDistance(featureCollection.features.map((feature) => {
|
|
66
|
-
// parse type from id (ex: "commune.3837")
|
|
67
|
-
const type = feature.id.split('.')[0];
|
|
68
|
-
// ignore geometry and extend properties
|
|
69
|
-
return Object.assign({
|
|
70
|
-
type: type,
|
|
71
|
-
id: feature.id,
|
|
72
|
-
bbox: feature.bbox,
|
|
73
|
-
distance: distance(sourceGeom, feature.geometry),
|
|
74
|
-
source: PARCELLAIRE_EXPRESS_SOURCE,
|
|
75
|
-
}, feature.properties);
|
|
76
|
-
}));
|
|
47
|
+
// Using EWKT format with SRID=4326 prefix for standard lon,lat order
|
|
48
|
+
const cql_filter = `DWITHIN(geom,SRID=4326;POINT(${lon} ${lat}),10,meters)`;
|
|
49
|
+
const typeNames = PARCELLAIRE_EXPRESS_TYPES.map((type) => `CADASTRALPARCELS.PARCELLAIRE_EXPRESS:${type}`);
|
|
50
|
+
const sourceGeom = toGeoJsonPoint(lon, lat);
|
|
51
|
+
const features = await fetchWfsFeatures(typeNames, cql_filter, 'PARCELLAIRE_EXPRESS', fetcher);
|
|
52
|
+
return filterByDistance(features.map((feature) => ({
|
|
53
|
+
...mapWfsFeature(feature, typeNames),
|
|
54
|
+
distance: distance(sourceGeom, feature.geometry),
|
|
55
|
+
source: PARCELLAIRE_EXPRESS_SOURCE,
|
|
56
|
+
})));
|
|
77
57
|
}
|
|
78
58
|
//# sourceMappingURL=parcellaire-express.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parcellaire-express.js","sourceRoot":"","sources":["../../src/gpf/parcellaire-express.js"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"parcellaire-express.js","sourceRoot":"","sources":["../../src/gpf/parcellaire-express.js"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,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,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,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;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO;IACzD,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC;IACxD,qEAAqE;IACrE,MAAM,UAAU,GAAG,gCAAgC,GAAG,IAAI,GAAG,cAAc,CAAC;IAC5E,MAAM,SAAS,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;IAE1G,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE5C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAC/F,OAAO,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,GAAG,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC;QACpC,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC;QAChD,MAAM,EAAE,0BAA0B;KACrC,CAAC,CAAC,CAAC,CAAC;AACT,CAAC"}
|
package/dist/gpf/urbanisme.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {(url: string) => Promise<any>} [fetcher]
|
|
7
7
|
* @returns
|
|
8
8
|
*/
|
|
9
|
-
export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<
|
|
9
|
+
export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{}[]>;
|
|
10
10
|
/**
|
|
11
11
|
* Get SUP infos for a given location
|
|
12
12
|
*
|
|
@@ -15,6 +15,8 @@ export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) =
|
|
|
15
15
|
* @param {(url: string) => Promise<any>} [fetcher]
|
|
16
16
|
* @returns
|
|
17
17
|
*/
|
|
18
|
-
export function getAssiettesServitudes(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<
|
|
18
|
+
export function getAssiettesServitudes(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{
|
|
19
|
+
distance: number;
|
|
20
|
+
}[]>;
|
|
19
21
|
export const URBANISME_TYPES: string[];
|
|
20
22
|
export const URBANISME_SOURCE: "G\u00E9oplateforme - (WFS G\u00E9oportail de l'Urbanisme)";
|
package/dist/gpf/urbanisme.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import distance from "../helpers/distance.js";
|
|
2
|
-
import {
|
|
2
|
+
import { fetchWfsFeatures, mapWfsFeature, toGeoJsonPoint } from "../helpers/wfs.js";
|
|
3
3
|
import logger from "../logger.js";
|
|
4
4
|
// https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
|
|
5
5
|
export const URBANISME_TYPES = [
|
|
@@ -15,7 +15,6 @@ export const URBANISME_TYPES = [
|
|
|
15
15
|
'wfs_du:prescription_surf'
|
|
16
16
|
];
|
|
17
17
|
export const URBANISME_SOURCE = "Géoplateforme - (WFS Géoportail de l'Urbanisme)";
|
|
18
|
-
const URBANISME_INVALID_COLLECTION_ERROR = "Le service Urbanisme n'a pas retourné de collection d'objets exploitable";
|
|
19
18
|
const URBANISME_EXCLUDED_PROPERTIES = new Set([
|
|
20
19
|
'gpu_status',
|
|
21
20
|
'urlfic'
|
|
@@ -41,36 +40,17 @@ function sanitizeUrbanismeItem(item) {
|
|
|
41
40
|
* @param {(url: string) => Promise<any>} [fetcher]
|
|
42
41
|
* @returns
|
|
43
42
|
*/
|
|
44
|
-
export async function getUrbanisme(lon, lat, fetcher
|
|
43
|
+
export async function getUrbanisme(lon, lat, fetcher) {
|
|
45
44
|
logger.info(`getUrbanisme(${lon},${lat})...`);
|
|
46
|
-
//
|
|
47
|
-
const cql_filter = `DWITHIN(the_geom,
|
|
48
|
-
const sourceGeom =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
request: 'GetFeature',
|
|
56
|
-
typeName: URBANISME_TYPES.join(','),
|
|
57
|
-
outputFormat: 'application/json',
|
|
58
|
-
cql_filter: cql_filter
|
|
59
|
-
}).toString();
|
|
60
|
-
const featureCollection = await fetcher(url);
|
|
61
|
-
if (!Array.isArray(featureCollection?.features)) {
|
|
62
|
-
throw new Error(URBANISME_INVALID_COLLECTION_ERROR);
|
|
63
|
-
}
|
|
64
|
-
return featureCollection.features.map((feature) => {
|
|
65
|
-
// parse type from id (ex: "commune.3837")
|
|
66
|
-
const type = feature.id.split('.')[0];
|
|
67
|
-
// ignore geometry and extend properties
|
|
68
|
-
const item = Object.assign({
|
|
69
|
-
type: type,
|
|
70
|
-
id: feature.id,
|
|
71
|
-
bbox: feature.bbox,
|
|
72
|
-
distance: (distance(sourceGeom, feature.geometry) * 1000.0)
|
|
73
|
-
}, feature.properties);
|
|
45
|
+
// Using EWKT format with SRID=4326 prefix for standard lon,lat order
|
|
46
|
+
const cql_filter = `DWITHIN(the_geom,SRID=4326;POINT(${lon} ${lat}),30,meters)`;
|
|
47
|
+
const sourceGeom = toGeoJsonPoint(lon, lat);
|
|
48
|
+
const features = await fetchWfsFeatures(URBANISME_TYPES, cql_filter, 'Urbanisme', fetcher);
|
|
49
|
+
return features.map((feature) => {
|
|
50
|
+
const item = {
|
|
51
|
+
...mapWfsFeature(feature, URBANISME_TYPES),
|
|
52
|
+
distance: distance(sourceGeom, feature.geometry),
|
|
53
|
+
};
|
|
74
54
|
return sanitizeUrbanismeItem(item);
|
|
75
55
|
});
|
|
76
56
|
}
|
|
@@ -87,36 +67,15 @@ const ASSIETTES_SUP_TYPES = [
|
|
|
87
67
|
* @param {(url: string) => Promise<any>} [fetcher]
|
|
88
68
|
* @returns
|
|
89
69
|
*/
|
|
90
|
-
export async function getAssiettesServitudes(lon, lat, fetcher
|
|
70
|
+
export async function getAssiettesServitudes(lon, lat, fetcher) {
|
|
91
71
|
logger.info(`getAssiettesServitudes(${lon},${lat})...`);
|
|
92
|
-
//
|
|
93
|
-
const cql_filter = `DWITHIN(the_geom,
|
|
94
|
-
const sourceGeom =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
service: 'WFS',
|
|
101
|
-
request: 'GetFeature',
|
|
102
|
-
typeName: ASSIETTES_SUP_TYPES.join(','),
|
|
103
|
-
outputFormat: 'application/json',
|
|
104
|
-
cql_filter: cql_filter
|
|
105
|
-
}).toString();
|
|
106
|
-
const featureCollection = await fetcher(url);
|
|
107
|
-
if (!Array.isArray(featureCollection?.features)) {
|
|
108
|
-
throw new Error(URBANISME_INVALID_COLLECTION_ERROR);
|
|
109
|
-
}
|
|
110
|
-
return featureCollection.features.map((feature) => {
|
|
111
|
-
// parse type from id (ex: "commune.3837")
|
|
112
|
-
const type = feature.id.split('.')[0];
|
|
113
|
-
// ignore geometry and extend properties
|
|
114
|
-
return Object.assign({
|
|
115
|
-
type: type,
|
|
116
|
-
id: feature.id,
|
|
117
|
-
bbox: feature.bbox,
|
|
118
|
-
distance: (distance(sourceGeom, feature.geometry) * 1000.0)
|
|
119
|
-
}, feature.properties);
|
|
120
|
-
});
|
|
72
|
+
// Using EWKT format with SRID=4326 prefix for standard lon,lat order
|
|
73
|
+
const cql_filter = `DWITHIN(the_geom,SRID=4326;POINT(${lon} ${lat}),30,meters)`;
|
|
74
|
+
const sourceGeom = toGeoJsonPoint(lon, lat);
|
|
75
|
+
const features = await fetchWfsFeatures(ASSIETTES_SUP_TYPES, cql_filter, 'Urbanisme', fetcher);
|
|
76
|
+
return features.map((feature) => ({
|
|
77
|
+
...mapWfsFeature(feature, ASSIETTES_SUP_TYPES),
|
|
78
|
+
distance: distance(sourceGeom, feature.geometry),
|
|
79
|
+
}));
|
|
121
80
|
}
|
|
122
81
|
//# sourceMappingURL=urbanisme.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urbanisme.js","sourceRoot":"","sources":["../../src/gpf/urbanisme.js"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"urbanisme.js","sourceRoot":"","sources":["../../src/gpf/urbanisme.js"],"names":[],"mappings":"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"}
|
package/dist/gpf/wfs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Collection, MiniSearchCollectionSearchOptions } from '@ignfab/gpf-schema-store';
|
|
1
|
+
import { Collection, CollectionSearchResult, MiniSearchCollectionSearchOptions } from '@ignfab/gpf-schema-store';
|
|
2
2
|
export declare const GPF_WFS_URL = "https://data.geopf.fr/wfs";
|
|
3
3
|
type MiniSearchOptions = MiniSearchCollectionSearchOptions;
|
|
4
4
|
export declare class FeatureTypeNotFoundError extends Error {
|
|
@@ -12,7 +12,7 @@ export declare class WfsClient {
|
|
|
12
12
|
miniSearch?: MiniSearchOptions;
|
|
13
13
|
});
|
|
14
14
|
getFeatureTypes(): Promise<Collection[]>;
|
|
15
|
-
|
|
15
|
+
searchFeatureTypesWithScores(query: string, maxResults?: number): Promise<CollectionSearchResult[]>;
|
|
16
16
|
getFeatureType(name: string): Promise<Collection>;
|
|
17
17
|
}
|
|
18
18
|
export declare const wfsClient: WfsClient;
|
package/dist/gpf/wfs.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// --- Imports ---
|
|
2
2
|
import { getCollectionCatalog, MiniSearchCollectionSearchEngine, } from '@ignfab/gpf-schema-store';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
// --- Constants ---
|
|
4
5
|
export const GPF_WFS_URL = "https://data.geopf.fr/wfs";
|
|
5
6
|
// Environment variable used to inject MiniSearch options at runtime (JSON string).
|
|
6
7
|
const GPF_WFS_MINISEARCH_OPTIONS_ENV = "GPF_WFS_MINISEARCH_OPTIONS";
|
|
7
|
-
// Keys accepted at the top level of the search options object.
|
|
8
|
-
const TOP_LEVEL_MINISEARCH_OPTION_KEYS = ["fields", "combineWith", "fuzzy", "boost"];
|
|
9
8
|
// Shared keys used by both `fields` and `boost` in MiniSearchCollectionSearchOptions.
|
|
10
9
|
const MINISEARCH_INDEXED_OPTION_KEYS = [
|
|
11
10
|
"namespace",
|
|
@@ -16,9 +15,7 @@ const MINISEARCH_INDEXED_OPTION_KEYS = [
|
|
|
16
15
|
"enums",
|
|
17
16
|
"identifierTokens",
|
|
18
17
|
];
|
|
19
|
-
const MINISEARCH_FIELD_OPTION_KEYS = MINISEARCH_INDEXED_OPTION_KEYS;
|
|
20
18
|
const MINISEARCH_COMBINE_WITH_VALUES = ["AND", "OR"];
|
|
21
|
-
const MINISEARCH_BOOST_OPTION_KEYS = MINISEARCH_INDEXED_OPTION_KEYS;
|
|
22
19
|
// --- Errors ---
|
|
23
20
|
export class FeatureTypeNotFoundError extends Error {
|
|
24
21
|
constructor(name) {
|
|
@@ -27,78 +24,27 @@ export class FeatureTypeNotFoundError extends Error {
|
|
|
27
24
|
}
|
|
28
25
|
}
|
|
29
26
|
// --- Helpers ---
|
|
30
|
-
function isPlainObject(value) {
|
|
31
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32
|
-
}
|
|
33
|
-
function isFiniteNumber(value) {
|
|
34
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
35
|
-
}
|
|
36
27
|
function invalidSearchOptionsError(reason) {
|
|
37
28
|
return new Error(`Invalid ${GPF_WFS_MINISEARCH_OPTIONS_ENV}: ${reason}`);
|
|
38
29
|
}
|
|
39
|
-
// --- Search options
|
|
30
|
+
// --- Search options schema ---
|
|
31
|
+
const miniSearchOptionsSchema = z.object({
|
|
32
|
+
fields: z.array(z.enum(MINISEARCH_INDEXED_OPTION_KEYS)).optional(),
|
|
33
|
+
combineWith: z.enum(MINISEARCH_COMBINE_WITH_VALUES).optional(),
|
|
34
|
+
fuzzy: z.number().finite().optional(),
|
|
35
|
+
boost: z.record(z.enum(MINISEARCH_INDEXED_OPTION_KEYS), z.number().finite()).optional(),
|
|
36
|
+
}).strict();
|
|
40
37
|
// Parses and validates a plain-object value into MiniSearchCollectionSearchOptions.
|
|
41
38
|
// Throws a descriptive error if the value has unexpected keys or wrong value types.
|
|
42
39
|
function parseMiniSearchOptions(value) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const options = {};
|
|
52
|
-
if (value.fields !== undefined) {
|
|
53
|
-
if (!Array.isArray(value.fields)) {
|
|
54
|
-
throw invalidSearchOptionsError("expected 'fields' to be an array");
|
|
55
|
-
}
|
|
56
|
-
const fields = [];
|
|
57
|
-
for (const field of value.fields) {
|
|
58
|
-
if (typeof field !== "string") {
|
|
59
|
-
throw invalidSearchOptionsError("expected every 'fields' item to be a string");
|
|
60
|
-
}
|
|
61
|
-
if (!MINISEARCH_FIELD_OPTION_KEYS.includes(field)) {
|
|
62
|
-
throw invalidSearchOptionsError(`unexpected value 'fields.${field}'`);
|
|
63
|
-
}
|
|
64
|
-
fields.push(field);
|
|
65
|
-
}
|
|
66
|
-
options.fields = fields;
|
|
67
|
-
}
|
|
68
|
-
if (value.combineWith !== undefined) {
|
|
69
|
-
if (typeof value.combineWith !== "string") {
|
|
70
|
-
throw invalidSearchOptionsError("expected 'combineWith' to be a string");
|
|
71
|
-
}
|
|
72
|
-
const combineWith = value.combineWith;
|
|
73
|
-
if (!MINISEARCH_COMBINE_WITH_VALUES.includes(combineWith)) {
|
|
74
|
-
throw invalidSearchOptionsError("expected 'combineWith' to be 'AND' or 'OR'");
|
|
75
|
-
}
|
|
76
|
-
options.combineWith = combineWith;
|
|
77
|
-
}
|
|
78
|
-
if (value.fuzzy !== undefined) {
|
|
79
|
-
if (!isFiniteNumber(value.fuzzy)) {
|
|
80
|
-
throw invalidSearchOptionsError("expected 'fuzzy' to be a finite number");
|
|
81
|
-
}
|
|
82
|
-
options.fuzzy = value.fuzzy;
|
|
83
|
-
}
|
|
84
|
-
if (value.boost !== undefined) {
|
|
85
|
-
if (!isPlainObject(value.boost)) {
|
|
86
|
-
throw invalidSearchOptionsError("expected 'boost' to be an object");
|
|
87
|
-
}
|
|
88
|
-
const boost = {};
|
|
89
|
-
for (const key of Object.keys(value.boost)) {
|
|
90
|
-
if (!MINISEARCH_BOOST_OPTION_KEYS.includes(key)) {
|
|
91
|
-
throw invalidSearchOptionsError(`unexpected key 'boost.${key}'`);
|
|
92
|
-
}
|
|
93
|
-
const rawScore = value.boost[key];
|
|
94
|
-
if (!isFiniteNumber(rawScore)) {
|
|
95
|
-
throw invalidSearchOptionsError(`expected 'boost.${key}' to be a finite number`);
|
|
96
|
-
}
|
|
97
|
-
boost[key] = rawScore;
|
|
98
|
-
}
|
|
99
|
-
options.boost = boost;
|
|
40
|
+
const result = miniSearchOptionsSchema.safeParse(value);
|
|
41
|
+
if (!result.success) {
|
|
42
|
+
const issue = result.error.issues[0];
|
|
43
|
+
const path = issue.path.length > 0 ? issue.path.join('.') : undefined;
|
|
44
|
+
const detail = path ? `${path}: ${issue.message}` : issue.message;
|
|
45
|
+
throw invalidSearchOptionsError(detail);
|
|
100
46
|
}
|
|
101
|
-
return
|
|
47
|
+
return result.data;
|
|
102
48
|
}
|
|
103
49
|
function createMiniSearchEngineOptions(miniSearch) {
|
|
104
50
|
if (!miniSearch) {
|
|
@@ -139,8 +85,8 @@ export class WfsClient {
|
|
|
139
85
|
async getFeatureTypes() {
|
|
140
86
|
return this.catalog.list();
|
|
141
87
|
}
|
|
142
|
-
async
|
|
143
|
-
return this.catalog.
|
|
88
|
+
async searchFeatureTypesWithScores(query, maxResults = 20) {
|
|
89
|
+
return this.catalog.searchWithScores(query, {
|
|
144
90
|
limit: maxResults,
|
|
145
91
|
});
|
|
146
92
|
}
|
package/dist/gpf/wfs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wfs.js","sourceRoot":"","sources":["../../src/gpf/wfs.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,OAAO,
|
|
1
|
+
{"version":3,"file":"wfs.js","sourceRoot":"","sources":["../../src/gpf/wfs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Compute approximative distance in
|
|
2
|
+
* Compute approximative distance in meters between gA and gB.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* TODO: replace the lon/lat planar nearest-point step with a geodesic geometry distance.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} gA GeoJSON Geometry
|
|
5
7
|
* @param {object} gB GeoJSON Geometry
|
|
6
8
|
*/
|
|
7
9
|
export default function distance(gA: object, gB: object): number;
|
package/dist/helpers/distance.js
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader.js';
|
|
2
2
|
import { DistanceOp } from 'jsts/org/locationtech/jts/operation/distance.js';
|
|
3
|
+
import turfDistance from '@turf/distance';
|
|
4
|
+
import { point as turfPoint } from '@turf/helpers';
|
|
3
5
|
/**
|
|
4
|
-
* Compute approximative distance in
|
|
6
|
+
* Compute approximative distance in meters between gA and gB.
|
|
5
7
|
*
|
|
6
|
-
*
|
|
8
|
+
* TODO: replace the lon/lat planar nearest-point step with a geodesic geometry distance.
|
|
9
|
+
*
|
|
10
|
+
* @param {object} gA GeoJSON Geometry
|
|
7
11
|
* @param {object} gB GeoJSON Geometry
|
|
8
12
|
*/
|
|
9
13
|
export default function distance(gA, gB) {
|
|
10
14
|
const geojsonReader = new GeoJSONReader();
|
|
11
15
|
const a = geojsonReader.read(gA);
|
|
12
16
|
const b = geojsonReader.read(gB);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
/*
|
|
18
|
+
* Get the 2 nearest points between a and b
|
|
19
|
+
*
|
|
20
|
+
* Note that it will project according to longitude and latitude axis,
|
|
21
|
+
* so it is not really accurate, but it is a good approximation
|
|
22
|
+
*/
|
|
23
|
+
const nearestPoints = DistanceOp.nearestPoints(a, b);
|
|
24
|
+
if (nearestPoints.length !== 2) {
|
|
25
|
+
throw new Error('DistanceOp.nearestPoints should return 2 points');
|
|
26
|
+
}
|
|
27
|
+
/*
|
|
28
|
+
* haversine distance between the 2 nearest points (see https://turfjs.org/docs/api/distance)
|
|
29
|
+
*/
|
|
30
|
+
return turfDistance(turfPoint([nearestPoints[0].x, nearestPoints[0].y]), turfPoint([nearestPoints[1].x, nearestPoints[1].y]), { units: 'meters' });
|
|
16
31
|
}
|
|
17
32
|
//# sourceMappingURL=distance.js.map
|