@osimatic/helpers-js 1.4.13 → 1.4.15
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/location.js +60 -11
- package/open_street_map.js +106 -1
- package/package.json +1 -1
package/location.js
CHANGED
|
@@ -429,9 +429,7 @@ class PostalAddress {
|
|
|
429
429
|
|
|
430
430
|
class Polygon {
|
|
431
431
|
static format(geoJsonPolygon) {
|
|
432
|
-
|
|
433
|
-
geoJsonPolygon = JSON.parse(geoJsonPolygon);
|
|
434
|
-
}
|
|
432
|
+
geoJsonPolygon = typeof geoJsonPolygon == 'string' ? JSON.parse(geoJsonPolygon) : geoJsonPolygon;
|
|
435
433
|
|
|
436
434
|
const rings = geoJsonPolygon.coordinates || [];
|
|
437
435
|
const ring0 = rings[0] || [];
|
|
@@ -452,6 +450,19 @@ class Polygon {
|
|
|
452
450
|
};
|
|
453
451
|
}
|
|
454
452
|
|
|
453
|
+
static getStartCoordinates(geoJsonPolygon, asString=false) {
|
|
454
|
+
geoJsonPolygon = typeof geoJsonPolygon == 'string' ? JSON.parse(geoJsonPolygon) : geoJsonPolygon;
|
|
455
|
+
|
|
456
|
+
const rings = geoJsonPolygon.coordinates || [];
|
|
457
|
+
const ring0 = rings[0] || [];
|
|
458
|
+
if (ring0.length === 0) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const [firstLon, firstLat] = ring0[0];
|
|
463
|
+
return asString ? str.join(',') : [firstLat, firstLon];
|
|
464
|
+
}
|
|
465
|
+
|
|
455
466
|
static convertToGeoJson(latlngs) {
|
|
456
467
|
let rings = [];
|
|
457
468
|
if (Array.isArray(latlngs) && Array.isArray(latlngs[0])) {
|
|
@@ -475,6 +486,38 @@ class Polygon {
|
|
|
475
486
|
return { type: 'Polygon', coordinates: rings };
|
|
476
487
|
}
|
|
477
488
|
|
|
489
|
+
static toLatLngRings(geoJsonPolygon) {
|
|
490
|
+
geoJsonPolygon = typeof geoJsonPolygon == 'string' ? JSON.parse(geoJsonPolygon) : geoJsonPolygon;
|
|
491
|
+
|
|
492
|
+
const polygonCoords = geoJsonPolygon.coordinates;
|
|
493
|
+
if (!Array.isArray(polygonCoords) || polygonCoords.length === 0) {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// polygonCoords: [ [ [lon,lat], ... ] , ... ]
|
|
498
|
+
const rings = [];
|
|
499
|
+
for (const ring of polygonCoords) {
|
|
500
|
+
const latlngRing = [];
|
|
501
|
+
for (const coord of ring) {
|
|
502
|
+
if (!Array.isArray(coord) || coord.length < 2) {
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const [lon, lat] = coord;
|
|
506
|
+
latlngRing.push([lat, lon]);
|
|
507
|
+
}
|
|
508
|
+
if (latlngRing.length > 0) {
|
|
509
|
+
// Fermer l'anneau si nécessaire (Leaflet accepte ouvert/fermé, on nettoie par sécurité)
|
|
510
|
+
const first = latlngRing[0];
|
|
511
|
+
const last = latlngRing[latlngRing.length - 1];
|
|
512
|
+
if (first[0] !== last[0] || first[1] !== last[1]) {
|
|
513
|
+
latlngRing.push([first[0], first[1]]);
|
|
514
|
+
}
|
|
515
|
+
rings.push(latlngRing);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return rings;
|
|
519
|
+
}
|
|
520
|
+
|
|
478
521
|
|
|
479
522
|
// Test "sur le segment" en degrés (plan local) — suffisant pour le bord du polygone
|
|
480
523
|
static isPointOnSegmentDeg(lat, lon, A, B, EPS = 1e-12) {
|
|
@@ -545,6 +588,7 @@ class Polygon {
|
|
|
545
588
|
|
|
546
589
|
return true;
|
|
547
590
|
}
|
|
591
|
+
|
|
548
592
|
}
|
|
549
593
|
|
|
550
594
|
class GeographicCoordinates {
|
|
@@ -581,11 +625,7 @@ class GeographicCoordinates {
|
|
|
581
625
|
}
|
|
582
626
|
|
|
583
627
|
static formatPoint(geoJsonPoint, fractionDigit=6) {
|
|
584
|
-
|
|
585
|
-
geoJsonPoint = JSON.parse(geoJsonPoint);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
const [long, lat] = geoJsonPoint.coordinates || [];
|
|
628
|
+
const [long, lat] = GeographicCoordinates.parseFromGeoJson(geoJsonPoint);
|
|
589
629
|
if (typeof long == 'undefined' || typeof lat == 'undefined') {
|
|
590
630
|
return '';
|
|
591
631
|
}
|
|
@@ -596,11 +636,20 @@ class GeographicCoordinates {
|
|
|
596
636
|
return { type: 'Point', coordinates: [Number(long), Number(lat)] };
|
|
597
637
|
}
|
|
598
638
|
|
|
599
|
-
static
|
|
600
|
-
|
|
601
|
-
|
|
639
|
+
static parseFromGeoJson(geoJsonPoint, asString=false) {
|
|
640
|
+
geoJsonPoint = typeof geoJsonPoint == 'string' ? JSON.parse(geoJsonPoint) : geoJsonPoint;
|
|
641
|
+
|
|
642
|
+
const [long, lat] = geoJsonPoint.coordinates || [];
|
|
643
|
+
if (typeof long == 'undefined' || typeof lat == 'undefined') {
|
|
644
|
+
return null;
|
|
602
645
|
}
|
|
603
646
|
|
|
647
|
+
return asString ? str.join(',') : [lat, lon];
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
static getAllLatLongsFromGeoJsonList(geoJsonList) {
|
|
651
|
+
geoJsonList = typeof geoJsonList == 'string' ? JSON.parse(geoJsonList) : geoJsonList;
|
|
652
|
+
|
|
604
653
|
const arr = [];
|
|
605
654
|
for (const geoJsonItem of geoJsonList) {
|
|
606
655
|
if (!geoJsonItem) {
|
package/open_street_map.js
CHANGED
|
@@ -77,7 +77,7 @@ class OpenStreetMap {
|
|
|
77
77
|
listLocations.forEach(location => this.addMarker(location, icon));
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
addMarker(
|
|
80
|
+
addMarker(geoJson, options) {
|
|
81
81
|
let locationCoordinates = coordinates.split(',');
|
|
82
82
|
let latitude = parseFloat(locationCoordinates[0]);
|
|
83
83
|
let longitude = parseFloat(locationCoordinates[1]);
|
|
@@ -105,6 +105,111 @@ class OpenStreetMap {
|
|
|
105
105
|
this.locations.push([latitude, longitude]);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
addGeoJson(geoJson, options) {
|
|
109
|
+
OpenStreetMap.displayGeoJSONOnMap(this.map, geoJson, options);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Affiche un GeoJSON (string) sur une carte Leaflet (OSM).
|
|
114
|
+
* Gère: Point, Polygon, et Feature/FeatureCollection contenant ces types.
|
|
115
|
+
*
|
|
116
|
+
* @param {L.Map} map - instance Leaflet déjà créée
|
|
117
|
+
* @param {string} geoJson - GeoJSON en texte
|
|
118
|
+
* @param {object} [opts]
|
|
119
|
+
* - layerGroup: L.LayerGroup | L.FeatureGroup (facultatif, cible d'ajout)
|
|
120
|
+
* - pointMarker: options Leaflet pour le marker (ex: { draggable:false })
|
|
121
|
+
* - polygonStyle: options Leaflet pour le polygon (ex: { color:'#007bff' })
|
|
122
|
+
* - fit: boolean (par défaut true) → adapte la vue à la géométrie
|
|
123
|
+
* - pointZoom: number (zoom si Point et fit=true, défaut 16)
|
|
124
|
+
* - popup: string (facultatif) → bindPopup commun pour l'entité
|
|
125
|
+
* @returns {L.Layer | null} couche ajoutée (marker ou polygon), sinon null
|
|
126
|
+
*/
|
|
127
|
+
static displayGeoJSONOnMap(map, geoJson, opts = {}) {
|
|
128
|
+
if (!map) {
|
|
129
|
+
console.warn('displayGeoJSONOnMap: paramètres invalides');
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (typeof geoJson == 'string') {
|
|
134
|
+
geoJson = JSON.parse(geoJson);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const {
|
|
138
|
+
layerGroup = null,
|
|
139
|
+
polygonStyle = { color: '#3388ff', weight: 3, opacity: 0.9, fillOpacity: 0.2 },
|
|
140
|
+
fit = true,
|
|
141
|
+
pointZoom = 16,
|
|
142
|
+
icon = null,
|
|
143
|
+
title = null,
|
|
144
|
+
popup = null
|
|
145
|
+
} = opts;
|
|
146
|
+
|
|
147
|
+
function addLayer(layer) {
|
|
148
|
+
layer.on('popupopen', () => {
|
|
149
|
+
//console.log('popupopen');
|
|
150
|
+
if (typeof opts['on_click'] == 'function') {
|
|
151
|
+
opts['on_click']();
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (layerGroup && typeof layerGroup.addLayer === 'function') {
|
|
157
|
+
layerGroup.addLayer(layer);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
layer.addTo(map);
|
|
161
|
+
}
|
|
162
|
+
if (popup) {
|
|
163
|
+
layer.bindPopup(popup);
|
|
164
|
+
}
|
|
165
|
+
return layer;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (geoJson.type === 'Point') {
|
|
169
|
+
const coords = geoJson.coordinates;
|
|
170
|
+
if (!Array.isArray(coords) || coords.length < 2) {
|
|
171
|
+
console.warn('displayGeoJSONOnMap: Point invalide');
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const [lon, lat] = coords;
|
|
175
|
+
const marker = L.marker([lat, lon], {
|
|
176
|
+
icon: L.icon({
|
|
177
|
+
iconUrl: icon,
|
|
178
|
+
iconSize: [22, 32],
|
|
179
|
+
}),
|
|
180
|
+
title: title,
|
|
181
|
+
});
|
|
182
|
+
addLayer(marker);
|
|
183
|
+
|
|
184
|
+
if (fit) {
|
|
185
|
+
map.setView([lat, lon], pointZoom);
|
|
186
|
+
setTimeout(function() { map.invalidateSize(true); }, 30);
|
|
187
|
+
}
|
|
188
|
+
return marker;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (geoJson.type === 'Polygon') {
|
|
192
|
+
const rings = Polygon.toLatLngRings(geoJson.coordinates);
|
|
193
|
+
if (!rings.length) {
|
|
194
|
+
console.warn('displayGeoJSONOnMap: Polygon invalide');
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
// Leaflet accepte un tableau d’anneaux pour L.polygon
|
|
198
|
+
const poly = L.polygon(rings, polygonStyle);
|
|
199
|
+
addLayer(poly);
|
|
200
|
+
|
|
201
|
+
if (fit) {
|
|
202
|
+
const b = poly.getBounds();
|
|
203
|
+
map.fitBounds(b, { padding: [20, 20] });
|
|
204
|
+
setTimeout(function() { map.invalidateSize(true); }, 30);
|
|
205
|
+
}
|
|
206
|
+
return poly;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
console.warn('displayGeoJSONOnMap: type non géré');
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
108
213
|
setView(location, zoom) {
|
|
109
214
|
this.map.setView(location, zoom);
|
|
110
215
|
}
|