@tmlmobilidade/utils 20250628.1124.5 → 20250628.1632.4
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/src/dates/utils.d.ts +10 -1
- package/dist/src/dates/utils.js +22 -0
- package/dist/src/geo/chunk-line.d.ts +10 -0
- package/dist/src/geo/chunk-line.js +67 -0
- package/dist/src/geo/constants.d.ts +8 -0
- package/dist/src/geo/constants.js +8 -0
- package/dist/src/geo/conversions.d.ts +36 -0
- package/dist/src/geo/conversions.js +79 -0
- package/dist/src/geo/cut-line-at-length.d.ts +9 -0
- package/dist/src/geo/cut-line-at-length.js +53 -0
- package/dist/src/geo/index.d.ts +5 -1
- package/dist/src/geo/index.js +5 -1
- package/dist/src/geo/measurements.d.ts +42 -0
- package/dist/src/geo/measurements.js +71 -0
- package/package.json +1 -1
- package/dist/src/geo/convert-to-meters.d.ts +0 -11
- package/dist/src/geo/convert-to-meters.js +0 -30
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OperationalDate } from '@tmlmobilidade/types';
|
|
1
|
+
import { type OperationalDate, type UnixTimestamp } from '@tmlmobilidade/types';
|
|
2
2
|
/**
|
|
3
3
|
* Returns an array of individual dates from a given range of operational dates.
|
|
4
4
|
* @param start The start date of the range, in OperationalDate format.
|
|
@@ -6,3 +6,12 @@ import { OperationalDate } from '@tmlmobilidade/types';
|
|
|
6
6
|
* @returns An array of OperationalDate objects representing each date in the range.
|
|
7
7
|
*/
|
|
8
8
|
export declare function getOperationalDatesFromRange(start: OperationalDate, end: OperationalDate): OperationalDate[];
|
|
9
|
+
/**
|
|
10
|
+
* Sorts an array of objects by a Unix timestamp key in ascending or descending order.
|
|
11
|
+
* The key must be of type UnixTimestamp, which is a number representing the timestamp in milliseconds.
|
|
12
|
+
* @param data The array of objects to be sorted.
|
|
13
|
+
* @param key The key of the objects to sort by, which must be a UnixTimestamp.
|
|
14
|
+
* @param direction The direction to sort the data, either 'asc' for ascending or 'desc' for descending. Defaults to 'asc'.
|
|
15
|
+
* @returns A new array of objects sorted by the specified Unix timestamp key.
|
|
16
|
+
*/
|
|
17
|
+
export declare function sortByUnixTimestamp<T, K extends keyof T>(data: T[], key: K extends keyof T ? (T[K] extends UnixTimestamp ? K : never) : never, direction?: 'asc' | 'desc'): T[];
|
package/dist/src/dates/utils.js
CHANGED
|
@@ -29,3 +29,25 @@ export function getOperationalDatesFromRange(start, end) {
|
|
|
29
29
|
}
|
|
30
30
|
return dates;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Sorts an array of objects by a Unix timestamp key in ascending or descending order.
|
|
34
|
+
* The key must be of type UnixTimestamp, which is a number representing the timestamp in milliseconds.
|
|
35
|
+
* @param data The array of objects to be sorted.
|
|
36
|
+
* @param key The key of the objects to sort by, which must be a UnixTimestamp.
|
|
37
|
+
* @param direction The direction to sort the data, either 'asc' for ascending or 'desc' for descending. Defaults to 'asc'.
|
|
38
|
+
* @returns A new array of objects sorted by the specified Unix timestamp key.
|
|
39
|
+
*/
|
|
40
|
+
export function sortByUnixTimestamp(data, key, direction = 'asc') {
|
|
41
|
+
//
|
|
42
|
+
if (direction === 'desc') {
|
|
43
|
+
return [...data].sort((a, b) => {
|
|
44
|
+
return b[key] - a[key];
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//
|
|
48
|
+
// If direction is 'asc'
|
|
49
|
+
return [...data].sort((a, b) => {
|
|
50
|
+
return a[key] - b[key];
|
|
51
|
+
});
|
|
52
|
+
//
|
|
53
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type LineString } from 'geojson';
|
|
2
|
+
/**
|
|
3
|
+
* This function takes a GeoJSON LineString and splits it into equal chunks of a given precision
|
|
4
|
+
* using a custom implementation. This is useful to ensure greater precision when calculating the nearest
|
|
5
|
+
* point on a path, as some paths may have very long "straight" segments with only two points.
|
|
6
|
+
* @param line The LineString to be split into chunks.
|
|
7
|
+
* @param segmentLength The length of each segment in meters.
|
|
8
|
+
* @returns A GeoJSON LineString with the split chunks.
|
|
9
|
+
*/
|
|
10
|
+
export declare function chunkLineByDistance(line: LineString, segmentLength: number): LineString;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { toLineStringFromPositions } from './conversions.js';
|
|
3
|
+
import { getDistanceBetweenPositions, interpolatePositions } from './measurements.js';
|
|
4
|
+
/**
|
|
5
|
+
* This function takes a GeoJSON LineString and splits it into equal chunks of a given precision
|
|
6
|
+
* using a custom implementation. This is useful to ensure greater precision when calculating the nearest
|
|
7
|
+
* point on a path, as some paths may have very long "straight" segments with only two points.
|
|
8
|
+
* @param line The LineString to be split into chunks.
|
|
9
|
+
* @param segmentLength The length of each segment in meters.
|
|
10
|
+
* @returns A GeoJSON LineString with the split chunks.
|
|
11
|
+
*/
|
|
12
|
+
export function chunkLineByDistance(line, segmentLength) {
|
|
13
|
+
// Exit early if the line is empty
|
|
14
|
+
if (line.coordinates.length < 2)
|
|
15
|
+
return line;
|
|
16
|
+
// Setup variables to hold the coordinates of the chunked line
|
|
17
|
+
const chunkedLineCoordinates = [];
|
|
18
|
+
// Add the first point to the chunked line
|
|
19
|
+
chunkedLineCoordinates.push(line.coordinates[0]);
|
|
20
|
+
// Loop through the coordinates of the line
|
|
21
|
+
for (let i = 0; i < line.coordinates.length - 1; i++) {
|
|
22
|
+
// Extract the coordinates of the current and the next point
|
|
23
|
+
const [lngA, latA] = line.coordinates[i];
|
|
24
|
+
const [lngB, latB] = line.coordinates[i + 1];
|
|
25
|
+
// Calculate the length of the current segment
|
|
26
|
+
const currentSegmentLength = getDistanceBetweenPositions(line.coordinates[i], line.coordinates[i + 1]);
|
|
27
|
+
// If the current segment length is greater than the desired segment length
|
|
28
|
+
if (currentSegmentLength > segmentLength) {
|
|
29
|
+
// Calculate the number of segments needed to fill the current segment
|
|
30
|
+
const segmentsNeeded = Math.floor(currentSegmentLength / segmentLength);
|
|
31
|
+
// Calculate the length of each chunked segment
|
|
32
|
+
const chunkedSegmentLength = currentSegmentLength / segmentsNeeded;
|
|
33
|
+
// Calculate the remaining distance to be filled
|
|
34
|
+
let remainingDist = segmentLength;
|
|
35
|
+
// Loop through the segments needed
|
|
36
|
+
for (let j = 0; j < segmentsNeeded; j++) {
|
|
37
|
+
// Calculate the ratio of the segment
|
|
38
|
+
const ratio = remainingDist / chunkedSegmentLength;
|
|
39
|
+
// Interpolate the coordinates of the segment
|
|
40
|
+
const interpolated = interpolatePositions([lngA, latA], [lngB, latB], ratio);
|
|
41
|
+
// Add the interpolated coordinates to the chunked line
|
|
42
|
+
chunkedLineCoordinates.push(interpolated);
|
|
43
|
+
// Update the remaining distance to be filled
|
|
44
|
+
remainingDist -= chunkedSegmentLength;
|
|
45
|
+
}
|
|
46
|
+
// Add the last point of the segment to the chunked line
|
|
47
|
+
const lastPoint = line.coordinates[i + 1];
|
|
48
|
+
if (chunkedLineCoordinates[chunkedLineCoordinates.length - 1][0] !== lastPoint[0] || chunkedLineCoordinates[chunkedLineCoordinates.length - 1][1] !== lastPoint[1]) {
|
|
49
|
+
chunkedLineCoordinates.push(lastPoint);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// If the current segment length is less than or equal to the desired segment length
|
|
54
|
+
// Add the current point to the chunked line
|
|
55
|
+
if (chunkedLineCoordinates[chunkedLineCoordinates.length - 1][0] !== line.coordinates[i][0] || chunkedLineCoordinates[chunkedLineCoordinates.length - 1][1] !== line.coordinates[i][1]) {
|
|
56
|
+
chunkedLineCoordinates.push(line.coordinates[i]);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Add the last point of the line to the chunked line
|
|
61
|
+
const lastPoint = line.coordinates[line.coordinates.length - 1];
|
|
62
|
+
if (chunkedLineCoordinates[chunkedLineCoordinates.length - 1][0] !== lastPoint[0] || chunkedLineCoordinates[chunkedLineCoordinates.length - 1][1] !== lastPoint[1]) {
|
|
63
|
+
chunkedLineCoordinates.push(lastPoint);
|
|
64
|
+
}
|
|
65
|
+
// Return the chunked line as a GeoJSON LineString
|
|
66
|
+
return toLineStringFromPositions(chunkedLineCoordinates);
|
|
67
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type HashedShape } from '@tmlmobilidade/types';
|
|
2
|
+
import { type Feature, type GeoJsonProperties, type LineString, type Point, type Polygon, type Position } from 'geojson';
|
|
3
|
+
/**
|
|
4
|
+
* Converts a list of GTFS shape points into a GeoJSON LineString.
|
|
5
|
+
* @param hashedShape The hashed shape containing GTFS shape points.
|
|
6
|
+
* @returns GeoJSON LineString feature
|
|
7
|
+
*/
|
|
8
|
+
export declare function toLineStringFromHashedShape(hashedShape: HashedShape): LineString;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new LineString from the given set of coordinates.
|
|
11
|
+
* @param positions An array of coordinate positions for the LineString. Defaults to an empty array.
|
|
12
|
+
* @returns A GeoJSON LineString with the specified coordinates.
|
|
13
|
+
*/
|
|
14
|
+
export declare function toLineStringFromPositions(positions?: Position[]): LineString;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new Point from the given coordinates.
|
|
17
|
+
* @param position A coordinate position for the Point. Defaults to an empty array.
|
|
18
|
+
* @returns A GeoJSON Point with the specified coordinates.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toPointFromPositions(position?: Position): Point;
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new Feature from the given object and properties.
|
|
23
|
+
* @param object The object to convert to a Feature. Can be a LineString, Point, or Polygon.
|
|
24
|
+
* @param properties Optional properties to attach to the Feature. Defaults to an empty object.
|
|
25
|
+
* @returns A GeoJSON Feature with the specified object and properties.
|
|
26
|
+
*/
|
|
27
|
+
export declare function toFeatureFromObject<T extends LineString | Point | Polygon>(object: T, properties?: GeoJsonProperties): Feature<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Converts a value in kilometers or meters to meters based on a ballpark value.
|
|
30
|
+
* If the ballpark value is greater than 800 meters, it assumes the value is in meters.
|
|
31
|
+
* Otherwise, it assumes the value is in kilometers and converts it to meters.
|
|
32
|
+
* @param value The value to be converted, which can be a number or a string that can be converted to a number.
|
|
33
|
+
* @param ballpark The ballpark value to determine the unit of the value, which can also be a number or a string that can be converted to a number.
|
|
34
|
+
* @returns The converted value in meters.
|
|
35
|
+
*/
|
|
36
|
+
export declare function toMetersFromKilometersOrMeters(value: number | string, ballpark: number | string): number;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
/**
|
|
3
|
+
* Converts a list of GTFS shape points into a GeoJSON LineString.
|
|
4
|
+
* @param hashedShape The hashed shape containing GTFS shape points.
|
|
5
|
+
* @returns GeoJSON LineString feature
|
|
6
|
+
*/
|
|
7
|
+
export function toLineStringFromHashedShape(hashedShape) {
|
|
8
|
+
// Exit if no points are provided
|
|
9
|
+
if (!hashedShape.points?.length)
|
|
10
|
+
return toLineStringFromPositions([]);
|
|
11
|
+
// Sort points by shape_pt_sequence
|
|
12
|
+
const sortedPoints = [...hashedShape.points].sort((a, b) => a.shape_pt_sequence - b.shape_pt_sequence);
|
|
13
|
+
// Create a LineString feature
|
|
14
|
+
const coordinates = sortedPoints.map(p => [Number(p.shape_pt_lon), Number(p.shape_pt_lat)]);
|
|
15
|
+
// Return the LineString feature
|
|
16
|
+
return toLineStringFromPositions(coordinates);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new LineString from the given set of coordinates.
|
|
20
|
+
* @param positions An array of coordinate positions for the LineString. Defaults to an empty array.
|
|
21
|
+
* @returns A GeoJSON LineString with the specified coordinates.
|
|
22
|
+
*/
|
|
23
|
+
export function toLineStringFromPositions(positions = []) {
|
|
24
|
+
return {
|
|
25
|
+
coordinates: positions,
|
|
26
|
+
type: 'LineString',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new Point from the given coordinates.
|
|
31
|
+
* @param position A coordinate position for the Point. Defaults to an empty array.
|
|
32
|
+
* @returns A GeoJSON Point with the specified coordinates.
|
|
33
|
+
*/
|
|
34
|
+
export function toPointFromPositions(position = []) {
|
|
35
|
+
return {
|
|
36
|
+
coordinates: position,
|
|
37
|
+
type: 'Point',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new Feature from the given object and properties.
|
|
42
|
+
* @param object The object to convert to a Feature. Can be a LineString, Point, or Polygon.
|
|
43
|
+
* @param properties Optional properties to attach to the Feature. Defaults to an empty object.
|
|
44
|
+
* @returns A GeoJSON Feature with the specified object and properties.
|
|
45
|
+
*/
|
|
46
|
+
export function toFeatureFromObject(object, properties) {
|
|
47
|
+
return {
|
|
48
|
+
geometry: object,
|
|
49
|
+
properties: properties || {},
|
|
50
|
+
type: 'Feature',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Converts a value in kilometers or meters to meters based on a ballpark value.
|
|
55
|
+
* If the ballpark value is greater than 800 meters, it assumes the value is in meters.
|
|
56
|
+
* Otherwise, it assumes the value is in kilometers and converts it to meters.
|
|
57
|
+
* @param value The value to be converted, which can be a number or a string that can be converted to a number.
|
|
58
|
+
* @param ballpark The ballpark value to determine the unit of the value, which can also be a number or a string that can be converted to a number.
|
|
59
|
+
* @returns The converted value in meters.
|
|
60
|
+
*/
|
|
61
|
+
export function toMetersFromKilometersOrMeters(value, ballpark) {
|
|
62
|
+
//
|
|
63
|
+
const BALLPARK_THRESHOLD = 800; // meters
|
|
64
|
+
const valueAsNumber = Number(value);
|
|
65
|
+
const ballparkAsNumber = Number(ballpark);
|
|
66
|
+
if (Number.isNaN(valueAsNumber))
|
|
67
|
+
throw new Error('Value must be a number or a string that can be converted to a number.');
|
|
68
|
+
if (Number.isNaN(ballparkAsNumber))
|
|
69
|
+
throw new Error('Ballpark must be a number or a string that can be converted to a number.');
|
|
70
|
+
// If the ballpark is bigger than 800, then the value is in meters
|
|
71
|
+
// Otherwise, the value is in kilometers. This is because it is unlikely
|
|
72
|
+
// that a trip will be smaller than 800 meters, and longer than 800 kilometers.
|
|
73
|
+
if (ballparkAsNumber > BALLPARK_THRESHOLD) {
|
|
74
|
+
return valueAsNumber;
|
|
75
|
+
}
|
|
76
|
+
return valueAsNumber * 1000;
|
|
77
|
+
//
|
|
78
|
+
}
|
|
79
|
+
;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type LineString } from 'geojson';
|
|
2
|
+
/**
|
|
3
|
+
* Cuts a LineString at a specified length.
|
|
4
|
+
* If the line is shorter than the specified length, it returns the entire line.
|
|
5
|
+
* @param line The LineString to cut.
|
|
6
|
+
* @param length The length at which to cut the line, in meters, from the start of the line.
|
|
7
|
+
* @returns A new LineString that is cut at the specified length.
|
|
8
|
+
*/
|
|
9
|
+
export declare function cutLineStringAtLength(line: LineString, length: number): LineString;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { toLineStringFromPositions } from './conversions.js';
|
|
3
|
+
import { getDistanceBetweenPositions, interpolatePositions } from './measurements.js';
|
|
4
|
+
/**
|
|
5
|
+
* Cuts a LineString at a specified length.
|
|
6
|
+
* If the line is shorter than the specified length, it returns the entire line.
|
|
7
|
+
* @param line The LineString to cut.
|
|
8
|
+
* @param length The length at which to cut the line, in meters, from the start of the line.
|
|
9
|
+
* @returns A new LineString that is cut at the specified length.
|
|
10
|
+
*/
|
|
11
|
+
export function cutLineStringAtLength(line, length) {
|
|
12
|
+
// Return the line if it is empty
|
|
13
|
+
if (line.coordinates.length < 2)
|
|
14
|
+
return line;
|
|
15
|
+
// Return an empty line if the length is less than or equal to 0
|
|
16
|
+
if (length <= 0)
|
|
17
|
+
return toLineStringFromPositions();
|
|
18
|
+
// Hold the cumulative distance between points
|
|
19
|
+
// and the coordinates of the new line
|
|
20
|
+
let cumulativeLength = 0;
|
|
21
|
+
const newLinePositions = [];
|
|
22
|
+
// Loop through the coordinates of the line
|
|
23
|
+
for (let i = 0; i < line.coordinates.length - 1; i++) {
|
|
24
|
+
// Get the coordinates of the current and the next point
|
|
25
|
+
const coordA = line.coordinates[i];
|
|
26
|
+
const coordB = line.coordinates[i + 1];
|
|
27
|
+
// Calculate the distance between the two points
|
|
28
|
+
const segmentLength = getDistanceBetweenPositions(coordA, coordB);
|
|
29
|
+
// If the current segment length plus the cumulative length
|
|
30
|
+
// extends the desired length of the resulting string
|
|
31
|
+
// then the line should be cut at the interpolation point
|
|
32
|
+
if (cumulativeLength + segmentLength >= length) {
|
|
33
|
+
const remainingLength = length - cumulativeLength;
|
|
34
|
+
const relativePositionOnSegment = remainingLength / segmentLength;
|
|
35
|
+
const interpolated = interpolatePositions(coordA, coordB, relativePositionOnSegment);
|
|
36
|
+
newLinePositions.push(coordA, interpolated);
|
|
37
|
+
return toLineStringFromPositions(newLinePositions);
|
|
38
|
+
}
|
|
39
|
+
// Add the length of the current segment to the
|
|
40
|
+
// cumulative length of the line up until this point
|
|
41
|
+
cumulativeLength += segmentLength;
|
|
42
|
+
// If the cumulative length is already greater than the desired length
|
|
43
|
+
// then the line should be cut at this point. Break the loop now.
|
|
44
|
+
if (cumulativeLength > length)
|
|
45
|
+
break;
|
|
46
|
+
// If the cumulative length is not yet up to the desired length
|
|
47
|
+
// then the current point should be added to the new line
|
|
48
|
+
newLinePositions.push(coordA);
|
|
49
|
+
}
|
|
50
|
+
// If the entire line is shorter than the target length
|
|
51
|
+
newLinePositions.push(line.coordinates[line.coordinates.length - 1]);
|
|
52
|
+
return toLineStringFromPositions(newLinePositions);
|
|
53
|
+
}
|
package/dist/src/geo/index.d.ts
CHANGED
package/dist/src/geo/index.js
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Point, type Position } from 'geojson';
|
|
2
|
+
/**
|
|
3
|
+
* Calculates the distance between two points, in meters.
|
|
4
|
+
* This is a wrapper function around the `getDistanceBetweenPositions` function.
|
|
5
|
+
* @param pointA The first point.
|
|
6
|
+
* @param pointB The second point.
|
|
7
|
+
* @returns The distance between the two points, in meters.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDistanceBetweenPoints(pointA: Point, pointB: Point): number;
|
|
10
|
+
/**
|
|
11
|
+
* Calculates the distance between two coordinate positions, in meters.
|
|
12
|
+
* This function uses the Haversine formula to calculate the distance
|
|
13
|
+
* between two points on the Earth's surface, given their latitude and longitude.
|
|
14
|
+
* The formula accounts for the curvature of the Earth.
|
|
15
|
+
* It is important to note that this function assumes the Earth is a perfect sphere,
|
|
16
|
+
* which is not entirely accurate, but it provides a good approximation for small distances.
|
|
17
|
+
* @param positionA The first position.
|
|
18
|
+
* @param positionB The second position.
|
|
19
|
+
* @returns The distance between the two points, in meters.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getDistanceBetweenPositions(positionA: Position, positionB: Position): number;
|
|
22
|
+
/**
|
|
23
|
+
* Interpolates between two points at a given ratio (0..1).
|
|
24
|
+
* This is a wrapper function around the `interpolatePosition` function.
|
|
25
|
+
* @param pointA The first point.
|
|
26
|
+
* @param pointB The second point.
|
|
27
|
+
* @param ratio The ratio at which to interpolate (0 = pointA, 1 = pointB).
|
|
28
|
+
* @returns The interpolated point.
|
|
29
|
+
*/
|
|
30
|
+
export declare function interpolatePoints(pointA: Point, pointB: Point, ratio: number): Point;
|
|
31
|
+
/**
|
|
32
|
+
* Linearly interpolates between two positions at a given ratio (0..1).
|
|
33
|
+
* This function is useful for calculating intermediate points
|
|
34
|
+
* along a line segment defined by two positions.
|
|
35
|
+
* @param positionA The first position.
|
|
36
|
+
* @param positionB The second position.
|
|
37
|
+
* @param ratio The ratio at which to interpolate (0 = positionA, 1 = positionB).
|
|
38
|
+
* A ratio of 0.5 would give the midpoint between the two positions.
|
|
39
|
+
* A ratio of 0.25 would give a point closer to positionA.
|
|
40
|
+
* @returns The interpolated position.
|
|
41
|
+
*/
|
|
42
|
+
export declare function interpolatePositions(positionA: Position, positionB: Position, ratio: number): Position;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { METERS_PER_DEGREE } from './constants.js';
|
|
3
|
+
import { toPointFromPositions } from './conversions.js';
|
|
4
|
+
/**
|
|
5
|
+
* Calculates the distance between two points, in meters.
|
|
6
|
+
* This is a wrapper function around the `getDistanceBetweenPositions` function.
|
|
7
|
+
* @param pointA The first point.
|
|
8
|
+
* @param pointB The second point.
|
|
9
|
+
* @returns The distance between the two points, in meters.
|
|
10
|
+
*/
|
|
11
|
+
export function getDistanceBetweenPoints(pointA, pointB) {
|
|
12
|
+
return getDistanceBetweenPositions(pointA.coordinates, pointB.coordinates);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Calculates the distance between two coordinate positions, in meters.
|
|
16
|
+
* This function uses the Haversine formula to calculate the distance
|
|
17
|
+
* between two points on the Earth's surface, given their latitude and longitude.
|
|
18
|
+
* The formula accounts for the curvature of the Earth.
|
|
19
|
+
* It is important to note that this function assumes the Earth is a perfect sphere,
|
|
20
|
+
* which is not entirely accurate, but it provides a good approximation for small distances.
|
|
21
|
+
* @param positionA The first position.
|
|
22
|
+
* @param positionB The second position.
|
|
23
|
+
* @returns The distance between the two points, in meters.
|
|
24
|
+
*/
|
|
25
|
+
export function getDistanceBetweenPositions(positionA, positionB) {
|
|
26
|
+
// Extract coordinates from the points
|
|
27
|
+
const [lngA, latA] = positionA;
|
|
28
|
+
const [lngB, latB] = positionB;
|
|
29
|
+
// Calculate the average latitude
|
|
30
|
+
const averageLatitude = (latA + latB) / 2;
|
|
31
|
+
// Calculate the differences in longitude and latitude
|
|
32
|
+
const dx = (lngB - lngA) * METERS_PER_DEGREE * Math.cos((averageLatitude * Math.PI) / 180);
|
|
33
|
+
const dy = (latB - latA) * METERS_PER_DEGREE;
|
|
34
|
+
// Calculate the distance using the Pythagorean theorem
|
|
35
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Interpolates between two points at a given ratio (0..1).
|
|
39
|
+
* This is a wrapper function around the `interpolatePosition` function.
|
|
40
|
+
* @param pointA The first point.
|
|
41
|
+
* @param pointB The second point.
|
|
42
|
+
* @param ratio The ratio at which to interpolate (0 = pointA, 1 = pointB).
|
|
43
|
+
* @returns The interpolated point.
|
|
44
|
+
*/
|
|
45
|
+
export function interpolatePoints(pointA, pointB, ratio) {
|
|
46
|
+
const result = interpolatePositions(pointA.coordinates, pointB.coordinates, ratio);
|
|
47
|
+
return toPointFromPositions(result);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Linearly interpolates between two positions at a given ratio (0..1).
|
|
51
|
+
* This function is useful for calculating intermediate points
|
|
52
|
+
* along a line segment defined by two positions.
|
|
53
|
+
* @param positionA The first position.
|
|
54
|
+
* @param positionB The second position.
|
|
55
|
+
* @param ratio The ratio at which to interpolate (0 = positionA, 1 = positionB).
|
|
56
|
+
* A ratio of 0.5 would give the midpoint between the two positions.
|
|
57
|
+
* A ratio of 0.25 would give a point closer to positionA.
|
|
58
|
+
* @returns The interpolated position.
|
|
59
|
+
*/
|
|
60
|
+
export function interpolatePositions(positionA, positionB, ratio) {
|
|
61
|
+
// Extract coordinates from the points
|
|
62
|
+
const lng = positionA[0] + (positionB[0] - positionA[0]) * ratio;
|
|
63
|
+
const lat = positionA[1] + (positionB[1] - positionA[1]) * ratio;
|
|
64
|
+
// Preserve elevation if present
|
|
65
|
+
if (positionA.length > 2 && positionB.length > 2) {
|
|
66
|
+
const alt = positionA[2] + (positionB[2] - positionA[2]) * ratio;
|
|
67
|
+
return [lng, lat, alt];
|
|
68
|
+
}
|
|
69
|
+
// Return the interpolated position
|
|
70
|
+
return [lng, lat];
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function checks if a value is small enough to be considered a meter value,
|
|
3
|
-
* as it should be used exclusevely for trip distance values.
|
|
4
|
-
* If the value is greater than 1, it is considered to be in meters.
|
|
5
|
-
* Converts a value to meters if it is in kilometers, otherwise returns meters.
|
|
6
|
-
* @param value - The value to be checked
|
|
7
|
-
* @param context - The context in which the value is being used
|
|
8
|
-
* @param ballpark - A ballpark value to be used as a reference. It is recommended to use the total distance of the object.
|
|
9
|
-
* @returns The value in meters
|
|
10
|
-
*/
|
|
11
|
-
export declare function convertMetersOrKilometersToMeters(value: number | string, ballpark: number | string): number;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
const BALLPARK_THRESHOLD = 800; // meters
|
|
3
|
-
/**
|
|
4
|
-
* This function checks if a value is small enough to be considered a meter value,
|
|
5
|
-
* as it should be used exclusevely for trip distance values.
|
|
6
|
-
* If the value is greater than 1, it is considered to be in meters.
|
|
7
|
-
* Converts a value to meters if it is in kilometers, otherwise returns meters.
|
|
8
|
-
* @param value - The value to be checked
|
|
9
|
-
* @param context - The context in which the value is being used
|
|
10
|
-
* @param ballpark - A ballpark value to be used as a reference. It is recommended to use the total distance of the object.
|
|
11
|
-
* @returns The value in meters
|
|
12
|
-
*/
|
|
13
|
-
export function convertMetersOrKilometersToMeters(value, ballpark) {
|
|
14
|
-
//
|
|
15
|
-
const valueAsNumber = Number(value);
|
|
16
|
-
const ballparkAsNumber = Number(ballpark);
|
|
17
|
-
if (Number.isNaN(valueAsNumber))
|
|
18
|
-
throw new Error('Value must be a number or a string that can be converted to a number.');
|
|
19
|
-
if (Number.isNaN(ballparkAsNumber))
|
|
20
|
-
throw new Error('Ballpark must be a number or a string that can be converted to a number.');
|
|
21
|
-
// If the ballpark is bigger than 800, then the value is in meters
|
|
22
|
-
// Otherwise, the value is in kilometers. This is because it is unlikely
|
|
23
|
-
// that a trip will be smaller than 800 meters, and longer than 800 kilometers.
|
|
24
|
-
if (ballparkAsNumber > BALLPARK_THRESHOLD) {
|
|
25
|
-
return valueAsNumber;
|
|
26
|
-
}
|
|
27
|
-
return valueAsNumber * 1000;
|
|
28
|
-
//
|
|
29
|
-
}
|
|
30
|
-
;
|