@dartcom/ui-kit 10.5.15 → 10.5.16

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/dist/index.cjs CHANGED
@@ -23454,6 +23454,11 @@ class MapService {
23454
23454
  * Полный угол окружности в градусах.
23455
23455
  */
23456
23456
  FULL_CIRCLE_DEGREES = 360;
23457
+ /**
23458
+ * Эпсилон (в метрах) для сравнения координат по умолчанию.
23459
+ */
23460
+ COORDINATE_EQUALITY_EPSILON_M = 2e-3;
23461
+ constructor() { }
23457
23462
  /**
23458
23463
  * Половина окружности в градусах.
23459
23464
  *
@@ -23485,7 +23490,6 @@ class MapService {
23485
23490
  get RAD_TO_DEG() {
23486
23491
  return this.HALF_CIRCLE_DEGREES / Math.PI;
23487
23492
  }
23488
- constructor() { }
23489
23493
  /**
23490
23494
  * Преобразует объект Leaflet `LatLng` в внутренний формат координат `Coordinate`.
23491
23495
  *
@@ -23640,7 +23644,8 @@ class MapService {
23640
23644
  */
23641
23645
  distanceToMeters(distance, unit = 'meters') {
23642
23646
  const factor = DISTANCE_UNIT_FACTORS[unit];
23643
- return distance * factor;
23647
+ const distanceToMeters = distance * factor;
23648
+ return distanceToMeters;
23644
23649
  }
23645
23650
  /**
23646
23651
  * Вычисляет общую длину ломаной линии (полилинии) по массиву координат.
@@ -23662,6 +23667,198 @@ class MapService {
23662
23667
  }, 0);
23663
23668
  return this.convertDistance(totalLengthInMeters, unit);
23664
23669
  }
23670
+ /**
23671
+ * Проверяет, совпадают ли две координаты с учётом допустимой
23672
+ * погрешности Float64.
23673
+ *
23674
+ * @param a - Первая координата.
23675
+ * @param b - Вторая координата.
23676
+ * @returns `true`, если расстояние между точками ≤ {@link COORDINATE_EQUALITY_EPSILON_M}.
23677
+ */
23678
+ coordinatesEqual(a, b) {
23679
+ const isEqual = this.haversineDistance(a, b, 'meters') <=
23680
+ this.COORDINATE_EQUALITY_EPSILON_M;
23681
+ return isEqual;
23682
+ }
23683
+ /**
23684
+ * Заменяет все вхождения координаты в плоском массиве.
23685
+ * Используется как общее ядро для методов работы с геометриями.
23686
+ *
23687
+ * @param coordinates - Исходный массив координат.
23688
+ * @param oldCoordinate - Координата, которую нужно заменить.
23689
+ * @param newCoordinate - Новая координата.
23690
+ * @param isEqual - Функция сравнения координат. По умолчанию — {@link coordinatesEqual}.
23691
+ * @returns Новый массив координат с произведёнными заменами.
23692
+ */
23693
+ replaceInFlatRing(coordinates, oldCoordinate, newCoordinate, isEqual) {
23694
+ return coordinates.map((coord) => isEqual(coord, oldCoordinate) ? newCoordinate : coord);
23695
+ }
23696
+ /**
23697
+ * Заменяет все вхождения координаты в линии (одномерный массив координат).
23698
+ *
23699
+ * Оригинальный массив не мутируется — возвращается новый.
23700
+ *
23701
+ * @param line - Исходная линия (массив координат).
23702
+ * @param oldCoordinate - Координата, которую нужно заменить.
23703
+ * @param newCoordinate - Новая координата.
23704
+ * @param isEqual - Опциональная функция сравнения. По умолчанию — {@link coordinatesEqual}.
23705
+ * @returns Новая линия с заменёнными координатами.
23706
+ *
23707
+ * @example
23708
+ * mapService.replaceCoordinateInLine(
23709
+ * [{ lat: 0, lon: 0 }, { lat: 1, lon: 1 }],
23710
+ * { lat: 0, lon: 0 },
23711
+ * { lat: 5, lon: 5 },
23712
+ * );
23713
+ * // [{ lat: 5, lon: 5 }, { lat: 1, lon: 1 }]
23714
+ */
23715
+ replaceCoordinateInLine(line, oldCoordinate, newCoordinate, isEqual = this.coordinatesEqual.bind(this)) {
23716
+ return this.replaceInFlatRing(line, oldCoordinate, newCoordinate, isEqual);
23717
+ }
23718
+ /**
23719
+ * Заменяет все вхождения координаты в полигоне.
23720
+ *
23721
+ * Полигон представлен как массив колец (`Coordinate[][]`),
23722
+ * где первое кольцо — внешний контур, последующие — отверстия.
23723
+ * Оригинальный массив не мутируется.
23724
+ *
23725
+ * @param polygon - Исходный полигон (массив колец).
23726
+ * @param oldCoordinate - Координата, которую нужно заменить.
23727
+ * @param newCoordinate - Новая координата.
23728
+ * @param isEqual - Опциональная функция сравнения. По умолчанию — {@link coordinatesEqual}.
23729
+ * @returns Новый полигон с заменёнными координатами.
23730
+ */
23731
+ replaceCoordinateInPolygon(polygon, oldCoordinate, newCoordinate, isEqual = this.coordinatesEqual.bind(this)) {
23732
+ return polygon.map((ring) => this.replaceInFlatRing(ring, oldCoordinate, newCoordinate, isEqual));
23733
+ }
23734
+ /**
23735
+ * Заменяет все вхождения координаты в мультиполигоне.
23736
+ *
23737
+ * Мультиполигон представлен как массив полигонов (`Coordinate[][][]`).
23738
+ * Оригинальный массив не мутируется.
23739
+ *
23740
+ * @param multiPolygon - Исходный мультиполигон.
23741
+ * @param oldCoordinate - Координата, которую нужно заменить.
23742
+ * @param newCoordinate - Новая координата.
23743
+ * @param isEqual - Опциональная функция сравнения. По умолчанию — {@link coordinatesEqual}.
23744
+ * @returns Новый мультиполигон с заменёнными координатами.
23745
+ */
23746
+ replaceCoordinateInMultiPolygon(multiPolygon, oldCoordinate, newCoordinate, isEqual = this.coordinatesEqual.bind(this)) {
23747
+ return multiPolygon.map((polygon) => this.replaceCoordinateInPolygon(polygon, oldCoordinate, newCoordinate, isEqual));
23748
+ }
23749
+ /**
23750
+ * Выполняет выборку точек вдоль ломаной линии с фиксированным интервалом по расстоянию.
23751
+ *
23752
+ * Алгоритм:
23753
+ * - последовательно проходит все сегменты линии;
23754
+ * - накапливает пройденное расстояние;
23755
+ * - как только накопленное расстояние достигает кратного интервалу,
23756
+ * интерполирует точку на текущем сегменте;
23757
+ * - продолжает, пока не пройдена вся линия или не достигнут maxPoints.
23758
+ *
23759
+ * Внутренние расчёты ведутся в метрах, но интервал можно задавать
23760
+ * в других поддерживаемых единицах (километры, мили и т.д.).
23761
+ *
23762
+ * Метод корректно работает и для сильно ломаных линий: точки всегда
23763
+ * лежат на самой линии и распределены по её длине, а не по прямой.
23764
+ *
23765
+ * @param coordinates - Линия в виде массива координат.
23766
+ * @param options - Опции выборки.
23767
+ * @returns Массив координат, расположенных вдоль исходной линии
23768
+ * на заданном интервале.
23769
+ */
23770
+ sampleLineByDistance(coordinates, options = {}) {
23771
+ const { interval = 1000, maxPoints, unit = 'meters', includeStart = false, } = options;
23772
+ if (coordinates.length < 2) {
23773
+ return [];
23774
+ }
23775
+ const intervalInMeters = this.distanceToMeters(interval, unit);
23776
+ if (!Number.isFinite(intervalInMeters) || intervalInMeters <= 0) {
23777
+ return [];
23778
+ }
23779
+ const result = [];
23780
+ let accumulated = 0;
23781
+ let previous = coordinates[0];
23782
+ if (includeStart) {
23783
+ result.push(previous);
23784
+ }
23785
+ for (let i = 1; i < coordinates.length; i++) {
23786
+ const current = coordinates[i];
23787
+ const segmentDistance = this.haversineDistance(previous, current, 'meters');
23788
+ // сегмент нулевой длины — просто пропускаем его
23789
+ if (!Number.isFinite(segmentDistance) || segmentDistance === 0) {
23790
+ previous = current;
23791
+ continue;
23792
+ }
23793
+ accumulated += segmentDistance;
23794
+ while (accumulated >= intervalInMeters) {
23795
+ const distanceFromSegmentEnd = accumulated - intervalInMeters;
23796
+ const distanceAlongSegment = segmentDistance - distanceFromSegmentEnd;
23797
+ const fraction = distanceAlongSegment / segmentDistance;
23798
+ const lat = previous.lat + fraction * (current.lat - previous.lat);
23799
+ const lon = previous.lon + fraction * (current.lon - previous.lon);
23800
+ result.push({ lat, lon });
23801
+ if (maxPoints != null && result.length >= maxPoints) {
23802
+ return result;
23803
+ }
23804
+ accumulated -= intervalInMeters;
23805
+ }
23806
+ previous = current;
23807
+ }
23808
+ if (maxPoints != null) {
23809
+ return result.slice(0, maxPoints);
23810
+ }
23811
+ return result;
23812
+ }
23813
+ /**
23814
+ * Возвращает координату точки, расположенной посередине по длине ломаной.
23815
+ *
23816
+ * Под «центром» понимается точка, находящаяся на половине общей длины
23817
+ * линии, измеренной по её сегментам. Это особенно важно для сильно
23818
+ * ломаных линий: центр почти никогда не совпадает с геометрическим
23819
+ * центром по широте/долготе или с какой‑либо вершиной.
23820
+ *
23821
+ * Если линия короче двух точек, возвращает `null`.
23822
+ * Если все точки совпадают (нулевая длина) — возвращает первую.
23823
+ *
23824
+ * @param coordinates - Линия в виде массива координат.
23825
+ * @returns Координата в середине по длине ломаной или `null`, если
23826
+ * линия некорректна.
23827
+ */
23828
+ getPolylineCenter(coordinates) {
23829
+ if (coordinates.length === 0) {
23830
+ return null;
23831
+ }
23832
+ if (coordinates.length === 1) {
23833
+ return coordinates[0];
23834
+ }
23835
+ const totalLengthMeters = this.getPolylineLength(coordinates, 'meters');
23836
+ if (totalLengthMeters === 0) {
23837
+ return coordinates[0];
23838
+ }
23839
+ const halfDistance = totalLengthMeters / 2;
23840
+ let accumulated = 0;
23841
+ let previous = coordinates[0];
23842
+ for (let i = 1; i < coordinates.length; i++) {
23843
+ const current = coordinates[i];
23844
+ const segmentDistance = this.haversineDistance(previous, current, 'meters');
23845
+ if (segmentDistance === 0) {
23846
+ previous = current;
23847
+ continue;
23848
+ }
23849
+ if (accumulated + segmentDistance >= halfDistance) {
23850
+ const remaining = halfDistance - accumulated;
23851
+ const fraction = remaining / segmentDistance;
23852
+ const lat = previous.lat + fraction * (current.lat - previous.lat);
23853
+ const lon = previous.lon + fraction * (current.lon - previous.lon);
23854
+ return { lat, lon };
23855
+ }
23856
+ accumulated += segmentDistance;
23857
+ previous = current;
23858
+ }
23859
+ // На случай накопленных ошибок округления:
23860
+ return coordinates[coordinates.length - 1];
23861
+ }
23665
23862
  }
23666
23863
  /**
23667
23864
  * Сервис для работы с географическими координатами и базовыми
@@ -1,5 +1,5 @@
1
1
  import { Coordinate } from '../../lib';
2
- import { DistanceUnit } from './map.types';
2
+ import { CoordinateCompareFn, DistanceUnit, SampleLineOptions } from './map.types';
3
3
  import { LatLng } from 'leaflet';
4
4
  declare class MapService {
5
5
  /**
@@ -10,6 +10,11 @@ declare class MapService {
10
10
  * Полный угол окружности в градусах.
11
11
  */
12
12
  readonly FULL_CIRCLE_DEGREES = 360;
13
+ /**
14
+ * Эпсилон (в метрах) для сравнения координат по умолчанию.
15
+ */
16
+ readonly COORDINATE_EQUALITY_EPSILON_M = 0.002;
17
+ constructor();
13
18
  /**
14
19
  * Половина окружности в градусах.
15
20
  *
@@ -35,7 +40,6 @@ declare class MapService {
35
40
  * @returns Значение коэффициента перевода радиан в градусы.
36
41
  */
37
42
  get RAD_TO_DEG(): number;
38
- constructor();
39
43
  /**
40
44
  * Преобразует объект Leaflet `LatLng` в внутренний формат координат `Coordinate`.
41
45
  *
@@ -137,7 +141,7 @@ declare class MapService {
137
141
  * @param unit - Единица, в которой передано расстояние.
138
142
  * @returns Расстояние в метрах.
139
143
  */
140
- private distanceToMeters;
144
+ distanceToMeters(distance: number, unit?: DistanceUnit): number;
141
145
  /**
142
146
  * Вычисляет общую длину ломаной линии (полилинии) по массиву координат.
143
147
  *
@@ -149,6 +153,111 @@ declare class MapService {
149
153
  * @returns Общая длина полилинии в выбранной единице.
150
154
  */
151
155
  getPolylineLength(coordinates: Coordinate[], unit?: DistanceUnit): number;
156
+ /**
157
+ * Проверяет, совпадают ли две координаты с учётом допустимой
158
+ * погрешности Float64.
159
+ *
160
+ * @param a - Первая координата.
161
+ * @param b - Вторая координата.
162
+ * @returns `true`, если расстояние между точками ≤ {@link COORDINATE_EQUALITY_EPSILON_M}.
163
+ */
164
+ coordinatesEqual(a: Coordinate, b: Coordinate): boolean;
165
+ /**
166
+ * Заменяет все вхождения координаты в плоском массиве.
167
+ * Используется как общее ядро для методов работы с геометриями.
168
+ *
169
+ * @param coordinates - Исходный массив координат.
170
+ * @param oldCoordinate - Координата, которую нужно заменить.
171
+ * @param newCoordinate - Новая координата.
172
+ * @param isEqual - Функция сравнения координат. По умолчанию — {@link coordinatesEqual}.
173
+ * @returns Новый массив координат с произведёнными заменами.
174
+ */
175
+ private replaceInFlatRing;
176
+ /**
177
+ * Заменяет все вхождения координаты в линии (одномерный массив координат).
178
+ *
179
+ * Оригинальный массив не мутируется — возвращается новый.
180
+ *
181
+ * @param line - Исходная линия (массив координат).
182
+ * @param oldCoordinate - Координата, которую нужно заменить.
183
+ * @param newCoordinate - Новая координата.
184
+ * @param isEqual - Опциональная функция сравнения. По умолчанию — {@link coordinatesEqual}.
185
+ * @returns Новая линия с заменёнными координатами.
186
+ *
187
+ * @example
188
+ * mapService.replaceCoordinateInLine(
189
+ * [{ lat: 0, lon: 0 }, { lat: 1, lon: 1 }],
190
+ * { lat: 0, lon: 0 },
191
+ * { lat: 5, lon: 5 },
192
+ * );
193
+ * // [{ lat: 5, lon: 5 }, { lat: 1, lon: 1 }]
194
+ */
195
+ replaceCoordinateInLine(line: Coordinate[], oldCoordinate: Coordinate, newCoordinate: Coordinate, isEqual?: CoordinateCompareFn): Coordinate[];
196
+ /**
197
+ * Заменяет все вхождения координаты в полигоне.
198
+ *
199
+ * Полигон представлен как массив колец (`Coordinate[][]`),
200
+ * где первое кольцо — внешний контур, последующие — отверстия.
201
+ * Оригинальный массив не мутируется.
202
+ *
203
+ * @param polygon - Исходный полигон (массив колец).
204
+ * @param oldCoordinate - Координата, которую нужно заменить.
205
+ * @param newCoordinate - Новая координата.
206
+ * @param isEqual - Опциональная функция сравнения. По умолчанию — {@link coordinatesEqual}.
207
+ * @returns Новый полигон с заменёнными координатами.
208
+ */
209
+ replaceCoordinateInPolygon(polygon: Coordinate[][], oldCoordinate: Coordinate, newCoordinate: Coordinate, isEqual?: CoordinateCompareFn): Coordinate[][];
210
+ /**
211
+ * Заменяет все вхождения координаты в мультиполигоне.
212
+ *
213
+ * Мультиполигон представлен как массив полигонов (`Coordinate[][][]`).
214
+ * Оригинальный массив не мутируется.
215
+ *
216
+ * @param multiPolygon - Исходный мультиполигон.
217
+ * @param oldCoordinate - Координата, которую нужно заменить.
218
+ * @param newCoordinate - Новая координата.
219
+ * @param isEqual - Опциональная функция сравнения. По умолчанию — {@link coordinatesEqual}.
220
+ * @returns Новый мультиполигон с заменёнными координатами.
221
+ */
222
+ replaceCoordinateInMultiPolygon(multiPolygon: Coordinate[][][], oldCoordinate: Coordinate, newCoordinate: Coordinate, isEqual?: CoordinateCompareFn): Coordinate[][][];
223
+ /**
224
+ * Выполняет выборку точек вдоль ломаной линии с фиксированным интервалом по расстоянию.
225
+ *
226
+ * Алгоритм:
227
+ * - последовательно проходит все сегменты линии;
228
+ * - накапливает пройденное расстояние;
229
+ * - как только накопленное расстояние достигает кратного интервалу,
230
+ * интерполирует точку на текущем сегменте;
231
+ * - продолжает, пока не пройдена вся линия или не достигнут maxPoints.
232
+ *
233
+ * Внутренние расчёты ведутся в метрах, но интервал можно задавать
234
+ * в других поддерживаемых единицах (километры, мили и т.д.).
235
+ *
236
+ * Метод корректно работает и для сильно ломаных линий: точки всегда
237
+ * лежат на самой линии и распределены по её длине, а не по прямой.
238
+ *
239
+ * @param coordinates - Линия в виде массива координат.
240
+ * @param options - Опции выборки.
241
+ * @returns Массив координат, расположенных вдоль исходной линии
242
+ * на заданном интервале.
243
+ */
244
+ sampleLineByDistance(coordinates: Coordinate[], options?: SampleLineOptions): Coordinate[];
245
+ /**
246
+ * Возвращает координату точки, расположенной посередине по длине ломаной.
247
+ *
248
+ * Под «центром» понимается точка, находящаяся на половине общей длины
249
+ * линии, измеренной по её сегментам. Это особенно важно для сильно
250
+ * ломаных линий: центр почти никогда не совпадает с геометрическим
251
+ * центром по широте/долготе или с какой‑либо вершиной.
252
+ *
253
+ * Если линия короче двух точек, возвращает `null`.
254
+ * Если все точки совпадают (нулевая длина) — возвращает первую.
255
+ *
256
+ * @param coordinates - Линия в виде массива координат.
257
+ * @returns Координата в середине по длине ломаной или `null`, если
258
+ * линия некорректна.
259
+ */
260
+ getPolylineCenter(coordinates: Coordinate[]): Coordinate | null;
152
261
  }
153
262
  /**
154
263
  * Сервис для работы с географическими координатами и базовыми
@@ -1 +1 @@
1
- {"version":3,"file":"map.service.d.ts","sourceRoot":"","sources":["../../../src/services/map/map.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAGnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,cAAM,UAAU;IACd;;OAEG;IACH,SAAgB,cAAc,WAAa;IAE3C;;OAEG;IACH,SAAgB,mBAAmB,OAAO;IAE1C;;;;;;;OAOG;IACH,IAAW,mBAAmB,WAE7B;IAED;;;;;;OAMG;IACH,IAAW,UAAU,WAEpB;IAED;;;;;;OAMG;IACH,IAAW,UAAU,WAEpB;;IAID;;;;;OAKG;IACI,qBAAqB,CAAC,MAAM,EAAE,MAAM;IAW3C;;;;;OAKG;IACI,qBAAqB,CAAC,UAAU,EAAE,UAAU;IAQnD;;;;;;;;;;;;OAYG;IACI,gBAAgB,CAAC,OAAO,EAAE,MAAM;IAOvC;;;;;;;;;OASG;IACI,kBAAkB,CAAC,GAAG,EAAE,MAAM;IAQrC;;;;;;;;;;;;;OAaG;IACI,oBAAoB,GAAI,0CAK5B;QACD,UAAU,EAAE,UAAU,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,YAAY,CAAC;KACrB;;;MAwBC;IAEF;;;;;;;;;;;OAWG;IACI,iBAAiB,CACtB,CAAC,EAAE,UAAU,EACb,CAAC,EAAE,UAAU,EACb,IAAI,GAAE,YAAuB;IAkB/B;;;;;;;;;OASG;IACI,cAAc,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU;IAkBlD;;;;;;OAMG;IACI,eAAe,CACpB,gBAAgB,EAAE,MAAM,EACxB,IAAI,GAAE,YAAuB;IAO/B;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;;;OASG;IACI,iBAAiB,CACtB,WAAW,EAAE,UAAU,EAAE,EACzB,IAAI,GAAE,YAAuB;CAqBhC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,YAAmB,CAAC"}
1
+ {"version":3,"file":"map.service.d.ts","sourceRoot":"","sources":["../../../src/services/map/map.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAGnC,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,cAAM,UAAU;IACd;;OAEG;IACH,SAAgB,cAAc,WAAa;IAE3C;;OAEG;IACH,SAAgB,mBAAmB,OAAO;IAE1C;;OAEG;IACH,SAAgB,6BAA6B,SAAQ;;IAIrD;;;;;;;OAOG;IACH,IAAW,mBAAmB,WAE7B;IAED;;;;;;OAMG;IACH,IAAW,UAAU,WAEpB;IAED;;;;;;OAMG;IACH,IAAW,UAAU,WAEpB;IAED;;;;;OAKG;IACI,qBAAqB,CAAC,MAAM,EAAE,MAAM;IAW3C;;;;;OAKG;IACI,qBAAqB,CAAC,UAAU,EAAE,UAAU;IAQnD;;;;;;;;;;;;OAYG;IACI,gBAAgB,CAAC,OAAO,EAAE,MAAM;IAOvC;;;;;;;;;OASG;IACI,kBAAkB,CAAC,GAAG,EAAE,MAAM;IAQrC;;;;;;;;;;;;;OAaG;IACI,oBAAoB,GAAI,0CAK5B;QACD,UAAU,EAAE,UAAU,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,YAAY,CAAC;KACrB;;;MAwBC;IAEF;;;;;;;;;;;OAWG;IACI,iBAAiB,CACtB,CAAC,EAAE,UAAU,EACb,CAAC,EAAE,UAAU,EACb,IAAI,GAAE,YAAuB;IAkB/B;;;;;;;;;OASG;IACI,cAAc,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU;IAkBlD;;;;;;OAMG;IACI,eAAe,CACpB,gBAAgB,EAAE,MAAM,EACxB,IAAI,GAAE,YAAuB;IAO/B;;;;;;OAMG;IACI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,YAAuB;IAQvE;;;;;;;;;OASG;IACI,iBAAiB,CACtB,WAAW,EAAE,UAAU,EAAE,EACzB,IAAI,GAAE,YAAuB;IAsB/B;;;;;;;OAOG;IACI,gBAAgB,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU;IAQpD;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;;;;;;;;;;;;;;;OAkBG;IACI,uBAAuB,CAC5B,IAAI,EAAE,UAAU,EAAE,EAClB,aAAa,EAAE,UAAU,EACzB,aAAa,EAAE,UAAU,EACzB,OAAO,GAAE,mBAAsD;IAKjE;;;;;;;;;;;;OAYG;IACI,0BAA0B,CAC/B,OAAO,EAAE,UAAU,EAAE,EAAE,EACvB,aAAa,EAAE,UAAU,EACzB,aAAa,EAAE,UAAU,EACzB,OAAO,GAAE,mBAAsD;IAOjE;;;;;;;;;;;OAWG;IACI,+BAA+B,CACpC,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE,EAC9B,aAAa,EAAE,UAAU,EACzB,aAAa,EAAE,UAAU,EACzB,OAAO,GAAE,mBAAsD;IAYjE;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,oBAAoB,CACzB,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,GAAE,iBAAsB;IAwEjC;;;;;;;;;;;;;;OAcG;IACI,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE;CAoDnD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,YAAmB,CAAC"}
@@ -1 +1 @@
1
- import{DISTANCE_UNIT_FACTORS as t}from"./map.constants.esm.js";import{a as s}from"../../_virtual/leaflet-src.esm.js";const n=new class{EARTH_RADIUS_M=6371e3;FULL_CIRCLE_DEGREES=360;get HALF_CIRCLE_DEGREES(){return this.FULL_CIRCLE_DEGREES/2}get DEG_TO_RAD(){return Math.PI/this.HALF_CIRCLE_DEGREES}get RAD_TO_DEG(){return this.HALF_CIRCLE_DEGREES/Math.PI}constructor(){}getCoordinateByLatLng(t){const{lat:s,lng:n}=t;return{lat:s,lon:n}}getLatLngByCoordinate(t){const{lat:n,lon:a}=t;return new s.LatLng(n,a)}normalizeBearing(t){return(t%this.FULL_CIRCLE_DEGREES+this.FULL_CIRCLE_DEGREES)%this.FULL_CIRCLE_DEGREES}normalizeLongitude(t){return(t+this.FULL_CIRCLE_DEGREES+this.HALF_CIRCLE_DEGREES)%this.FULL_CIRCLE_DEGREES-this.HALF_CIRCLE_DEGREES}calculateDestination=({coordinate:t,distance:s,azimuth:n,unit:a="meters"})=>{const e=t.lat*this.DEG_TO_RAD,i=t.lon*this.DEG_TO_RAD,r=this.normalizeBearing(n)*this.DEG_TO_RAD,E=this.distanceToMeters(s,a)/this.EARTH_RADIUS_M,h=Math.sin(e),_=Math.cos(e),o=Math.sin(E),D=Math.cos(E),R=Math.sin(r),L=Math.cos(r),c=Math.asin(h*D+_*o*L),l=i+Math.atan2(R*o*_,D-h*Math.sin(c));return{lat:c*this.RAD_TO_DEG,lon:this.normalizeLongitude(l*this.RAD_TO_DEG)}};haversineDistance(t,s,n="meters"){const a=t.lat*this.DEG_TO_RAD,e=s.lat*this.DEG_TO_RAD,i=(s.lat-t.lat)*this.DEG_TO_RAD,r=(s.lon-t.lon)*this.DEG_TO_RAD,E=Math.sin(i/2)**2+Math.cos(a)*Math.cos(e)*Math.sin(r/2)**2,h=2*Math.atan2(Math.sqrt(E),Math.sqrt(1-E)),_=this.EARTH_RADIUS_M*h;return this.convertDistance(_,n)}initialBearing(t,s){const n=t.lat*this.DEG_TO_RAD,a=s.lat*this.DEG_TO_RAD,e=t.lon*this.DEG_TO_RAD,i=s.lon*this.DEG_TO_RAD,r=Math.sin(i-e)*Math.cos(a),E=Math.cos(n)*Math.sin(a)-Math.sin(n)*Math.cos(a)*Math.cos(i-e);return this.normalizeBearing(Math.atan2(r,E)*this.RAD_TO_DEG)}convertDistance(s,n="meters"){return s/t[n]}distanceToMeters(s,n="meters"){return s*t[n]}getPolylineLength(t,s="meters"){const n=t.reduce((t,s,n,a)=>{const e=a[n+1];if(!e)return t;return t+this.haversineDistance(s,e,"meters")},0);return this.convertDistance(n,s)}};export{n as mapService};
1
+ import{DISTANCE_UNIT_FACTORS as t}from"./map.constants.esm.js";import{a as e}from"../../_virtual/leaflet-src.esm.js";const n=new class{EARTH_RADIUS_M=6371e3;FULL_CIRCLE_DEGREES=360;COORDINATE_EQUALITY_EPSILON_M=.002;constructor(){}get HALF_CIRCLE_DEGREES(){return this.FULL_CIRCLE_DEGREES/2}get DEG_TO_RAD(){return Math.PI/this.HALF_CIRCLE_DEGREES}get RAD_TO_DEG(){return this.HALF_CIRCLE_DEGREES/Math.PI}getCoordinateByLatLng(t){const{lat:e,lng:n}=t;return{lat:e,lon:n}}getLatLngByCoordinate(t){const{lat:n,lon:s}=t;return new e.LatLng(n,s)}normalizeBearing(t){return(t%this.FULL_CIRCLE_DEGREES+this.FULL_CIRCLE_DEGREES)%this.FULL_CIRCLE_DEGREES}normalizeLongitude(t){return(t+this.FULL_CIRCLE_DEGREES+this.HALF_CIRCLE_DEGREES)%this.FULL_CIRCLE_DEGREES-this.HALF_CIRCLE_DEGREES}calculateDestination=({coordinate:t,distance:e,azimuth:n,unit:s="meters"})=>{const i=t.lat*this.DEG_TO_RAD,r=t.lon*this.DEG_TO_RAD,a=this.normalizeBearing(n)*this.DEG_TO_RAD,o=this.distanceToMeters(e,s)/this.EARTH_RADIUS_M,l=Math.sin(i),h=Math.cos(i),E=Math.sin(o),_=Math.cos(o),c=Math.sin(a),D=Math.cos(a),u=Math.asin(l*_+h*E*D),R=r+Math.atan2(c*E*h,_-l*Math.sin(u));return{lat:u*this.RAD_TO_DEG,lon:this.normalizeLongitude(R*this.RAD_TO_DEG)}};haversineDistance(t,e,n="meters"){const s=t.lat*this.DEG_TO_RAD,i=e.lat*this.DEG_TO_RAD,r=(e.lat-t.lat)*this.DEG_TO_RAD,a=(e.lon-t.lon)*this.DEG_TO_RAD,o=Math.sin(r/2)**2+Math.cos(s)*Math.cos(i)*Math.sin(a/2)**2,l=2*Math.atan2(Math.sqrt(o),Math.sqrt(1-o)),h=this.EARTH_RADIUS_M*l;return this.convertDistance(h,n)}initialBearing(t,e){const n=t.lat*this.DEG_TO_RAD,s=e.lat*this.DEG_TO_RAD,i=t.lon*this.DEG_TO_RAD,r=e.lon*this.DEG_TO_RAD,a=Math.sin(r-i)*Math.cos(s),o=Math.cos(n)*Math.sin(s)-Math.sin(n)*Math.cos(s)*Math.cos(r-i);return this.normalizeBearing(Math.atan2(a,o)*this.RAD_TO_DEG)}convertDistance(e,n="meters"){return e/t[n]}distanceToMeters(e,n="meters"){return e*t[n]}getPolylineLength(t,e="meters"){const n=t.reduce((t,e,n,s)=>{const i=s[n+1];if(!i)return t;return t+this.haversineDistance(e,i,"meters")},0);return this.convertDistance(n,e)}coordinatesEqual(t,e){return this.haversineDistance(t,e,"meters")<=this.COORDINATE_EQUALITY_EPSILON_M}replaceInFlatRing(t,e,n,s){return t.map(t=>s(t,e)?n:t)}replaceCoordinateInLine(t,e,n,s=this.coordinatesEqual.bind(this)){return this.replaceInFlatRing(t,e,n,s)}replaceCoordinateInPolygon(t,e,n,s=this.coordinatesEqual.bind(this)){return t.map(t=>this.replaceInFlatRing(t,e,n,s))}replaceCoordinateInMultiPolygon(t,e,n,s=this.coordinatesEqual.bind(this)){return t.map(t=>this.replaceCoordinateInPolygon(t,e,n,s))}sampleLineByDistance(t,e={}){const{interval:n=1e3,maxPoints:s,unit:i="meters",includeStart:r=!1}=e;if(t.length<2)return[];const a=this.distanceToMeters(n,i);if(!Number.isFinite(a)||a<=0)return[];const o=[];let l=0,h=t[0];r&&o.push(h);for(let e=1;e<t.length;e++){const n=t[e],i=this.haversineDistance(h,n,"meters");if(Number.isFinite(i)&&0!==i){for(l+=i;l>=a;){const t=(i-(l-a))/i,e=h.lat+t*(n.lat-h.lat),r=h.lon+t*(n.lon-h.lon);if(o.push({lat:e,lon:r}),null!=s&&o.length>=s)return o;l-=a}h=n}else h=n}return null!=s?o.slice(0,s):o}getPolylineCenter(t){if(0===t.length)return null;if(1===t.length)return t[0];const e=this.getPolylineLength(t,"meters");if(0===e)return t[0];const n=e/2;let s=0,i=t[0];for(let e=1;e<t.length;e++){const r=t[e],a=this.haversineDistance(i,r,"meters");if(0!==a){if(s+a>=n){const t=(n-s)/a;return{lat:i.lat+t*(r.lat-i.lat),lon:i.lon+t*(r.lon-i.lon)}}s+=a,i=r}else i=r}return t[t.length-1]}};export{n as mapService};
@@ -1,5 +1,39 @@
1
+ import { Coordinate } from '../../lib';
1
2
  /**
2
3
  * Поддерживаемые единицы измерения расстояния.
3
4
  */
4
5
  export type DistanceUnit = 'meters' | 'kilometers' | 'miles' | 'nauticalMiles';
6
+ /**
7
+ * Функция сравнения двух координат.
8
+ * Возвращает `true`, если координаты считаются равными.
9
+ *
10
+ * Позволяет задавать собственный критерий равенства —
11
+ * например, с учётом допустимой погрешности Float64.
12
+ */
13
+ export type CoordinateCompareFn = (a: Coordinate, b: Coordinate) => boolean;
14
+ /**
15
+ * Опции выборки координат вдоль линии.
16
+ */
17
+ export interface SampleLineOptions {
18
+ /**
19
+ * Интервал между соседними точками выборки в выбранной единице.
20
+ * По умолчанию 1000 (метров).
21
+ */
22
+ interval?: number;
23
+ /**
24
+ * Максимальное количество точек в результате.
25
+ * Если не задано — возвращаются все возможные точки.
26
+ */
27
+ maxPoints?: number;
28
+ /**
29
+ * Единица измерения интервала.
30
+ * По умолчанию — метры.
31
+ */
32
+ unit?: DistanceUnit;
33
+ /**
34
+ * Включать ли первую точку линии в результат.
35
+ * Если true — начальная координата всегда будет первой в массиве.
36
+ */
37
+ includeStart?: boolean;
38
+ }
5
39
  //# sourceMappingURL=map.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"map.types.d.ts","sourceRoot":"","sources":["../../../src/services/map/map.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,eAAe,CAAC"}
1
+ {"version":3,"file":"map.types.d.ts","sourceRoot":"","sources":["../../../src/services/map/map.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,eAAe,CAAC;AAE/E;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dartcom/ui-kit",
3
- "version": "10.5.15",
3
+ "version": "10.5.16",
4
4
  "description": "Кастомная библиотека компонентов Dartcom",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",