@osimatic/helpers-js 1.4.6 → 1.4.8
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 +100 -1
- package/open_street_map.js +9 -7
- package/package.json +1 -1
package/location.js
CHANGED
|
@@ -466,12 +466,85 @@ class Polygon {
|
|
|
466
466
|
if (r.length >= 3) {
|
|
467
467
|
const [lon0,lat0] = r[0];
|
|
468
468
|
const [lonL,latL] = r[r.length-1];
|
|
469
|
-
if (lon0 !== lonL || lat0 !== latL)
|
|
469
|
+
if (lon0 !== lonL || lat0 !== latL) {
|
|
470
|
+
r.push([lon0,lat0]);
|
|
471
|
+
}
|
|
470
472
|
}
|
|
471
473
|
return r;
|
|
472
474
|
});
|
|
473
475
|
return { type: 'Polygon', coordinates: rings };
|
|
474
476
|
}
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
// Test "sur le segment" en degrés (plan local) — suffisant pour le bord du polygone
|
|
480
|
+
static isPointOnSegmentDeg(lat, lon, A, B, EPS = 1e-12) {
|
|
481
|
+
const [x, y ] = [lon, lat];
|
|
482
|
+
const [x1, y1] = A; // A = [lon,lat]
|
|
483
|
+
const [x2, y2] = B; // B = [lon,lat]
|
|
484
|
+
const cross = (x - x1)*(y2 - y1) - (y - y1)*(x2 - x1);
|
|
485
|
+
if (Math.abs(cross) > EPS) {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const dot = (x - x1)*(x2 - x1) + (y - y1)*(y2 - y1);
|
|
490
|
+
if (dot < -EPS) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const len2 = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1);
|
|
495
|
+
return dot - len2 <= EPS;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Ray-casting + bords inclus pour un anneau (tableau de [lon,lat])
|
|
499
|
+
static isPointInRing(lat, lon, ring) {
|
|
500
|
+
const n0 = ring.length;
|
|
501
|
+
if (n0 < 3) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// fermer si nécessaire
|
|
506
|
+
const closed = ring[n0-1][0] === ring[0][0] && ring[n0-1][1] === ring[0][1];
|
|
507
|
+
const pts = closed ? ring : [...ring, ring[0]];
|
|
508
|
+
const n = pts.length;
|
|
509
|
+
|
|
510
|
+
// bord inclus
|
|
511
|
+
for (let i = 0; i < n - 1; i++) {
|
|
512
|
+
if (Polygon.isPointOnSegmentDeg(lat, lon, pts[i], pts[i+1])) {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// ray casting (x=lon, y=lat)
|
|
518
|
+
let inside = false;
|
|
519
|
+
for (let i = 0, j = n - 1; i < n; j = i++) {
|
|
520
|
+
const [xi, yi] = pts[i];
|
|
521
|
+
const [xj, yj] = pts[j];
|
|
522
|
+
const intersect = ((yi > lat) !== (yj > lat)) &&
|
|
523
|
+
(lon < ( (xj - xi) * (lat - yi) / ((yj - yi) || 1e-20) + xi ));
|
|
524
|
+
if (intersect) inside = !inside;
|
|
525
|
+
}
|
|
526
|
+
return inside;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Polygone avec trous: inside = dans outer ET pas dans un trou
|
|
530
|
+
static isPointInPolygon(lat, lon, geoJsonPolygon) {
|
|
531
|
+
const rings = geoJsonPolygon.coordinates;
|
|
532
|
+
if (!Array.isArray(rings) || rings.length === 0) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (!Polygon.isPointInRing(lat, lon, rings[0])) {
|
|
537
|
+
return false; // outer
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
for (let k = 1; k < rings.length; k++) {
|
|
541
|
+
if (Polygon.isPointInRing(lat, lon, rings[k])) {
|
|
542
|
+
return false; // dans un trou
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
475
548
|
}
|
|
476
549
|
|
|
477
550
|
class GeographicCoordinates {
|
|
@@ -553,6 +626,32 @@ class GeographicCoordinates {
|
|
|
553
626
|
return arr;
|
|
554
627
|
}
|
|
555
628
|
|
|
629
|
+
static isPointCorrespondingToLocationsList(lat, lon, locationsList, tolMeters = 1.0) {
|
|
630
|
+
for (const it of locationsList) {
|
|
631
|
+
if (!it) {
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
if (typeof it === 'string') {
|
|
636
|
+
const p = GeographicCoordinates.parse(it);
|
|
637
|
+
if (p && GeographicCoordinates.haversine(lat,lon,p[0],p[1]) <= tolMeters) {
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
else if (it.type === 'Point') {
|
|
642
|
+
const p = GeographicCoordinates.parse(it.coordinates);
|
|
643
|
+
if (p && GeographicCoordinates.haversine(lat,lon,p[0],p[1]) <= tolMeters) {
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
else if (it.type === 'Polygon' && Array.isArray(it.coordinates)) {
|
|
648
|
+
if (Polygon.isPointInPolygon(lat, lon, it)) {
|
|
649
|
+
return true;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
556
655
|
|
|
557
656
|
static haversine(lat1, long1, lat2, long2) {
|
|
558
657
|
const R = 6371000;
|
package/open_street_map.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
class OpenStreetMap {
|
|
7
7
|
|
|
8
|
-
constructor(mapContainer, options) {
|
|
8
|
+
constructor(mapContainer, options={}) {
|
|
9
9
|
/*let [lat, lng] = button.data('coordinates').split(',');
|
|
10
10
|
let map = L.map('modal_map_canvas2').setView([lat, lng], 17);
|
|
11
11
|
|
|
@@ -29,7 +29,7 @@ class OpenStreetMap {
|
|
|
29
29
|
this.centerOnFrance();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
static createMap(mapContainer, options) {
|
|
32
|
+
static createMap(mapContainer, options={}) {
|
|
33
33
|
if (!mapContainer.length) {
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
@@ -39,12 +39,14 @@ class OpenStreetMap {
|
|
|
39
39
|
container._leaflet_id = null;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const map = L.map(mapContainer[0], options
|
|
42
|
+
const map = L.map(mapContainer[0], options);
|
|
43
43
|
|
|
44
44
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
45
45
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
46
46
|
}).addTo(map);
|
|
47
47
|
|
|
48
|
+
OpenStreetMap.centerOnFrance(map);
|
|
49
|
+
|
|
48
50
|
return map;
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -55,7 +57,7 @@ class OpenStreetMap {
|
|
|
55
57
|
|
|
56
58
|
static getUrlFromCoordinates(locationCoordinates) {
|
|
57
59
|
locationCoordinates = locationCoordinates.split(',');
|
|
58
|
-
return
|
|
60
|
+
return OpenStreetMap.getUrl(parseFloat(locationCoordinates[0]), parseFloat(locationCoordinates[1]));
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
setZoom(zoom) {
|
|
@@ -123,7 +125,7 @@ class OpenStreetMap {
|
|
|
123
125
|
OpenStreetMap.centerMapToLocations(this.map, this.locations, padding);
|
|
124
126
|
}
|
|
125
127
|
|
|
126
|
-
static centerMapToLocations(map, locationsList, padding=[20,20]) {
|
|
128
|
+
static centerMapToLocations(map, locationsList, padding=[20,20], maxZoom=18) {
|
|
127
129
|
if (!map || locationsList.length === 0) {
|
|
128
130
|
return;
|
|
129
131
|
}
|
|
@@ -132,8 +134,8 @@ class OpenStreetMap {
|
|
|
132
134
|
|
|
133
135
|
const bounds = L.latLngBounds(locationsList);
|
|
134
136
|
map.fitBounds(bounds, { padding: padding });
|
|
135
|
-
if (map.getZoom() >
|
|
136
|
-
map.setZoom(
|
|
137
|
+
if (map.getZoom() > maxZoom) {
|
|
138
|
+
map.setZoom(maxZoom);
|
|
137
139
|
}
|
|
138
140
|
}
|
|
139
141
|
|