@trackunit/shared-utils 0.0.84 → 0.0.86
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/index.cjs.js +0 -358
- package/index.esm.js +1 -338
- package/package.json +2 -3
- package/src/index.d.ts +0 -2
- package/src/GeoJson/GeoJsonSchemas.d.ts +0 -210
- package/src/GeoJson/GeoJsonUtils.d.ts +0 -59
package/index.cjs.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var zod = require('zod');
|
|
4
3
|
var uuid = require('uuid');
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -414,342 +413,6 @@ searchTerm) => {
|
|
|
414
413
|
.every(term => filterableProps(asset).some(value => value.toLowerCase().includes(term.toLowerCase()))));
|
|
415
414
|
};
|
|
416
415
|
|
|
417
|
-
// * NOTE: For simplicity these tools are built for 2D coordinate space only!
|
|
418
|
-
/**
|
|
419
|
-
* A Position is an array of coordinates. [x, y]
|
|
420
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.1
|
|
421
|
-
*/
|
|
422
|
-
const geoJsonPositionSchema = zod.z.tuple([zod.z.number(), zod.z.number()]);
|
|
423
|
-
/**
|
|
424
|
-
* Point geometry object.
|
|
425
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.2
|
|
426
|
-
*/
|
|
427
|
-
const geoJsonPointSchema = zod.z.strictObject({
|
|
428
|
-
type: zod.z.literal("Point"),
|
|
429
|
-
coordinates: geoJsonPositionSchema,
|
|
430
|
-
});
|
|
431
|
-
/**
|
|
432
|
-
* MultiPoint geometry object.
|
|
433
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.3
|
|
434
|
-
*/
|
|
435
|
-
const geoJsonMultiPointSchema = zod.z.strictObject({
|
|
436
|
-
type: zod.z.literal("MultiPoint"),
|
|
437
|
-
coordinates: zod.z.array(geoJsonPositionSchema),
|
|
438
|
-
});
|
|
439
|
-
/**
|
|
440
|
-
* LineString geometry object.
|
|
441
|
-
* Minimum length of 2 positions.
|
|
442
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.4
|
|
443
|
-
*/
|
|
444
|
-
const geoJsonLineStringSchema = zod.z.strictObject({
|
|
445
|
-
type: zod.z.literal("LineString"),
|
|
446
|
-
coordinates: zod.z.array(geoJsonPositionSchema).min(2),
|
|
447
|
-
});
|
|
448
|
-
/**
|
|
449
|
-
* MultiLineString geometry object.
|
|
450
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.5
|
|
451
|
-
*/
|
|
452
|
-
const geoJsonMultiLineStringSchema = zod.z.strictObject({
|
|
453
|
-
type: zod.z.literal("MultiLineString"),
|
|
454
|
-
coordinates: zod.z.array(zod.z.array(geoJsonPositionSchema)),
|
|
455
|
-
});
|
|
456
|
-
/**
|
|
457
|
-
* Helper type for reuse across polygon schemas.
|
|
458
|
-
*
|
|
459
|
-
* - A linear ring is a closed LineString with four or more positions.
|
|
460
|
-
* - The first and last positions are equivalent, and they MUST contain
|
|
461
|
-
identical values; their representation SHOULD also be identical
|
|
462
|
-
* - A linear ring is the boundary of a surface or the boundary of a
|
|
463
|
-
hole in a surface
|
|
464
|
-
* - A linear ring MUST follow the right-hand rule with respect to the
|
|
465
|
-
area it bounds, i.e., exterior rings are counterclockwise, and
|
|
466
|
-
holes are clockwise
|
|
467
|
-
*/
|
|
468
|
-
const geoJsonLinearRingSchema = zod.z
|
|
469
|
-
.array(geoJsonPositionSchema)
|
|
470
|
-
.min(4, {
|
|
471
|
-
message: "Coordinates array must contain at least 4 positions. 3 to make a non-line shape and 1 to close the shape (duplicate of first)",
|
|
472
|
-
})
|
|
473
|
-
.superRefine((coords, ctx) => {
|
|
474
|
-
const first = coords[0];
|
|
475
|
-
const last = coords[coords.length - 1];
|
|
476
|
-
// Check if first and last coordinates match
|
|
477
|
-
if (JSON.stringify(first) !== JSON.stringify(last)) {
|
|
478
|
-
ctx.addIssue({
|
|
479
|
-
code: zod.z.ZodIssueCode.custom,
|
|
480
|
-
message: "First and last coordinate positions must be identical (to close the linear ring aka polygon).",
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
// Check if any coordinate is (0, 0)
|
|
484
|
-
coords.forEach((coord, index) => {
|
|
485
|
-
if (coord[0] === 0 && coord[1] === 0) {
|
|
486
|
-
ctx.addIssue({
|
|
487
|
-
code: zod.z.ZodIssueCode.custom,
|
|
488
|
-
message: `Coordinate at index ${index} should not be (0, 0). This is likely not a valid coordinate.`,
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
// Check if consecutive points are identical (excluding first and last)
|
|
493
|
-
for (let i = 1; i < coords.length - 1; i++) {
|
|
494
|
-
if (JSON.stringify(coords[i]) === JSON.stringify(coords[i - 1])) {
|
|
495
|
-
ctx.addIssue({
|
|
496
|
-
code: zod.z.ZodIssueCode.custom,
|
|
497
|
-
message: `Consecutive coordinates at index ${i - 1} and ${i} should not be identical.`,
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
/**
|
|
503
|
-
* Polygon geometry object.
|
|
504
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
505
|
-
*/
|
|
506
|
-
const geoJsonPolygonSchema = zod.z.strictObject({
|
|
507
|
-
type: zod.z.literal("Polygon"),
|
|
508
|
-
coordinates: zod.z.array(geoJsonLinearRingSchema),
|
|
509
|
-
});
|
|
510
|
-
/**
|
|
511
|
-
* MultiPolygon geometry object.
|
|
512
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.7
|
|
513
|
-
*/
|
|
514
|
-
const geoJsonMultiPolygonSchema = zod.z.strictObject({
|
|
515
|
-
type: zod.z.literal("MultiPolygon"),
|
|
516
|
-
coordinates: zod.z.array(zod.z.array(geoJsonLinearRingSchema)),
|
|
517
|
-
});
|
|
518
|
-
// The same for Geometry, GeometryCollection, GeoJsonProperties, Feature, FeatureCollection, etc.
|
|
519
|
-
const geoJsonGeometrySchema = zod.z.union([
|
|
520
|
-
geoJsonPointSchema,
|
|
521
|
-
geoJsonMultiPointSchema,
|
|
522
|
-
geoJsonLineStringSchema,
|
|
523
|
-
geoJsonMultiLineStringSchema,
|
|
524
|
-
geoJsonPolygonSchema,
|
|
525
|
-
geoJsonMultiPolygonSchema,
|
|
526
|
-
]);
|
|
527
|
-
//* -------- Bbox -------- *//
|
|
528
|
-
/**
|
|
529
|
-
* 2D bounding box of the GeoJSON object.
|
|
530
|
-
* The value of the Bbox member is an array of length 4.
|
|
531
|
-
*
|
|
532
|
-
* [min_lon, min_lat, max_lon, max_lat]
|
|
533
|
-
*/
|
|
534
|
-
const geoJsonBboxSchema = zod.z
|
|
535
|
-
.tuple([zod.z.number(), zod.z.number(), zod.z.number(), zod.z.number()])
|
|
536
|
-
.refine(([minLng, minLat, maxLng, maxLat]) => maxLng > minLng && maxLat > minLat, {
|
|
537
|
-
message: "Invalid bounding box: maxLng should be greater than minLng, and maxLat should be greater than minLat.",
|
|
538
|
-
});
|
|
539
|
-
//* -------- Extras -------- *//
|
|
540
|
-
/**
|
|
541
|
-
* Polygon geometry object that explicitly disallows holes.
|
|
542
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
543
|
-
*/
|
|
544
|
-
const geoJsonPolygonNoHolesSchema = zod.z.strictObject({
|
|
545
|
-
type: zod.z.literal("Polygon"),
|
|
546
|
-
//uses tuple instead of array to enforce only 1 linear ring aka the polygon itself
|
|
547
|
-
coordinates: zod.z.tuple([geoJsonLinearRingSchema]),
|
|
548
|
-
});
|
|
549
|
-
/**
|
|
550
|
-
* A Polygon with exactly 5 points and 4 horizontal/vertical sides that form a normal rectangular box.
|
|
551
|
-
*/
|
|
552
|
-
const geoJsonRectangularBoxPolygonSchema = zod.z
|
|
553
|
-
.strictObject({
|
|
554
|
-
type: zod.z.literal("Polygon"),
|
|
555
|
-
coordinates: zod.z.array(geoJsonLinearRingSchema),
|
|
556
|
-
})
|
|
557
|
-
.superRefine((data, ctx) => {
|
|
558
|
-
const coordinates = data.coordinates[0];
|
|
559
|
-
// Validate polygon has exactly 5 points
|
|
560
|
-
if ((coordinates === null || coordinates === void 0 ? void 0 : coordinates.length) !== 5) {
|
|
561
|
-
ctx.addIssue({
|
|
562
|
-
code: zod.z.ZodIssueCode.custom,
|
|
563
|
-
message: "Polygon must have exactly 5 coordinates to form a closed box.",
|
|
564
|
-
});
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
// Check each side is either horizontal or vertical
|
|
568
|
-
for (let i = 0; i < 4; i++) {
|
|
569
|
-
const point1 = coordinates[i];
|
|
570
|
-
const point2 = coordinates[i + 1];
|
|
571
|
-
if (!point1 || !point2) {
|
|
572
|
-
ctx.addIssue({
|
|
573
|
-
code: zod.z.ZodIssueCode.custom,
|
|
574
|
-
message: "Each coordinate must be a defined point.",
|
|
575
|
-
});
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
const [x1, y1] = point1;
|
|
579
|
-
const [x2, y2] = point2;
|
|
580
|
-
// Ensure each line segment is either horizontal or vertical
|
|
581
|
-
if (x1 !== x2 && y1 !== y2) {
|
|
582
|
-
ctx.addIssue({
|
|
583
|
-
code: zod.z.ZodIssueCode.custom,
|
|
584
|
-
message: "Polygon sides must be horizontal or vertical to form a box shape.",
|
|
585
|
-
});
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
const EARTH_RADIUS = 6378137; // Earth’s mean radius in meters
|
|
592
|
-
const isDoubleNestedCoords = (coords) => Array.isArray(coords) &&
|
|
593
|
-
Array.isArray(coords[0]) &&
|
|
594
|
-
Array.isArray(coords[0][0]) &&
|
|
595
|
-
typeof coords[0][0][0] === "number";
|
|
596
|
-
const isSingleCoords = (coords) => typeof coords[0] === "number";
|
|
597
|
-
/**
|
|
598
|
-
* @description Returns coordinates in consistent format
|
|
599
|
-
* @param inconsistentCoordinates Single point, array of points or nested array of points
|
|
600
|
-
* @returns GeoPoint[]
|
|
601
|
-
*/
|
|
602
|
-
const coordinatesToStandardFormat = (inconsistentCoordinates) => {
|
|
603
|
-
if (!inconsistentCoordinates) {
|
|
604
|
-
return [];
|
|
605
|
-
}
|
|
606
|
-
if (isSingleCoords(inconsistentCoordinates)) {
|
|
607
|
-
return [inconsistentCoordinates];
|
|
608
|
-
}
|
|
609
|
-
if (isDoubleNestedCoords(inconsistentCoordinates)) {
|
|
610
|
-
return inconsistentCoordinates[0] || [];
|
|
611
|
-
}
|
|
612
|
-
if (inconsistentCoordinates[0] && typeof inconsistentCoordinates[0][0] === "number") {
|
|
613
|
-
return inconsistentCoordinates;
|
|
614
|
-
}
|
|
615
|
-
return [];
|
|
616
|
-
};
|
|
617
|
-
/**
|
|
618
|
-
* @description Extracts a point coordinate from a GeoJSON object.
|
|
619
|
-
* @param geoObject A GeoJSON object.
|
|
620
|
-
* @returns {PointCoordinate} A point coordinate.
|
|
621
|
-
*/
|
|
622
|
-
const getPointCoordinateFromGeoJsonObject = (geoObject) => {
|
|
623
|
-
if (!geoObject) {
|
|
624
|
-
return undefined;
|
|
625
|
-
}
|
|
626
|
-
else if ("geometry" in geoObject) {
|
|
627
|
-
return getPointCoordinateFromGeoJsonObject(geoObject.geometry);
|
|
628
|
-
}
|
|
629
|
-
else if ("coordinates" in geoObject &&
|
|
630
|
-
Array.isArray(geoObject.coordinates) &&
|
|
631
|
-
typeof geoObject.coordinates[0] === "number" &&
|
|
632
|
-
typeof geoObject.coordinates[1] === "number") {
|
|
633
|
-
const [point] = coordinatesToStandardFormat(geoObject.coordinates);
|
|
634
|
-
if (point) {
|
|
635
|
-
return { latitude: point[1], longitude: point[0] };
|
|
636
|
-
}
|
|
637
|
-
else {
|
|
638
|
-
throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
else {
|
|
642
|
-
throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
|
|
643
|
-
}
|
|
644
|
-
};
|
|
645
|
-
/**
|
|
646
|
-
* @description Extracts multiple point coordinates from a GeoJSON object.
|
|
647
|
-
* @param geoObject A GeoJSON object.
|
|
648
|
-
* @returns {PointCoordinate[]} An array of point coordinates.
|
|
649
|
-
* @example getMultipleCoordinatesFromGeoJsonObject({ type: "Point", coordinates: [1, 2] }) // [{ longitude: 1, latitude: 2 }]
|
|
650
|
-
*/
|
|
651
|
-
const getMultipleCoordinatesFromGeoJsonObject = (geoObject) => {
|
|
652
|
-
if (!geoObject) {
|
|
653
|
-
return undefined;
|
|
654
|
-
}
|
|
655
|
-
else if ("geometry" in geoObject) {
|
|
656
|
-
return getMultipleCoordinatesFromGeoJsonObject(geoObject.geometry);
|
|
657
|
-
}
|
|
658
|
-
else if ("coordinates" in geoObject) {
|
|
659
|
-
return coordinatesToStandardFormat(geoObject.coordinates).map(([longitude, latitude]) => ({ longitude, latitude }));
|
|
660
|
-
}
|
|
661
|
-
else {
|
|
662
|
-
throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
|
|
663
|
-
}
|
|
664
|
-
};
|
|
665
|
-
/**
|
|
666
|
-
* @description Creates a polygon from a bounding box.
|
|
667
|
-
*/
|
|
668
|
-
const getPolygonFromBbox = (bbox) => {
|
|
669
|
-
const [minLon, minLat, maxLon, maxLat] = bbox;
|
|
670
|
-
return {
|
|
671
|
-
type: "Polygon",
|
|
672
|
-
coordinates: [
|
|
673
|
-
[
|
|
674
|
-
[minLon, minLat],
|
|
675
|
-
[maxLon, minLat],
|
|
676
|
-
[maxLon, maxLat],
|
|
677
|
-
[minLon, maxLat],
|
|
678
|
-
[minLon, minLat],
|
|
679
|
-
],
|
|
680
|
-
],
|
|
681
|
-
};
|
|
682
|
-
};
|
|
683
|
-
/**
|
|
684
|
-
* @description Creates a round polygon from a point and a radius.
|
|
685
|
-
*/
|
|
686
|
-
const getPolygonFromPointAndRadius = (point, radius) => {
|
|
687
|
-
const [lon, lat] = point.coordinates;
|
|
688
|
-
// Adjust the number of points based on radius (resolution)
|
|
689
|
-
const pointsCount = Math.max(32, Math.floor(radius / 100)); // More points for larger radius
|
|
690
|
-
const angleStep = (2 * Math.PI) / pointsCount;
|
|
691
|
-
const coordinates = [];
|
|
692
|
-
for (let i = 0; i <= pointsCount; i++) {
|
|
693
|
-
const angle = i * angleStep;
|
|
694
|
-
// Calculate offset in latitude and longitude
|
|
695
|
-
const deltaLat = (radius / EARTH_RADIUS) * (180 / Math.PI);
|
|
696
|
-
const deltaLon = deltaLat / Math.cos((lat * Math.PI) / 180);
|
|
697
|
-
// Calculate new coordinates based on angle
|
|
698
|
-
const newLat = lat + deltaLat * Math.sin(angle);
|
|
699
|
-
const newLon = lon + deltaLon * Math.cos(angle);
|
|
700
|
-
coordinates.push([newLon, newLat]);
|
|
701
|
-
}
|
|
702
|
-
return {
|
|
703
|
-
type: "Polygon",
|
|
704
|
-
coordinates: [coordinates],
|
|
705
|
-
};
|
|
706
|
-
};
|
|
707
|
-
/**
|
|
708
|
-
* @description Creates a TU bounding box from a GeoJson Polygon.
|
|
709
|
-
*/
|
|
710
|
-
const getBoundingBoxFromGeoJsonPolygon = (polygon) => {
|
|
711
|
-
const points = polygon.coordinates[0];
|
|
712
|
-
const latitudes = points === null || points === void 0 ? void 0 : points.map(point => point[1]);
|
|
713
|
-
const longitudes = points === null || points === void 0 ? void 0 : points.map(point => point[0]);
|
|
714
|
-
if (!latitudes || !longitudes) {
|
|
715
|
-
return undefined;
|
|
716
|
-
}
|
|
717
|
-
return {
|
|
718
|
-
nw: {
|
|
719
|
-
latitude: Math.max(...latitudes),
|
|
720
|
-
longitude: Math.min(...longitudes),
|
|
721
|
-
},
|
|
722
|
-
se: {
|
|
723
|
-
latitude: Math.min(...latitudes),
|
|
724
|
-
longitude: Math.max(...longitudes),
|
|
725
|
-
},
|
|
726
|
-
};
|
|
727
|
-
};
|
|
728
|
-
/**
|
|
729
|
-
* @description Creates a GeoJSON Polygon from a TU bounding box.
|
|
730
|
-
*/
|
|
731
|
-
const getGeoJsonPolygonFromBoundingBox = (boundingBox) => {
|
|
732
|
-
const { nw, se } = boundingBox;
|
|
733
|
-
return {
|
|
734
|
-
type: "Polygon",
|
|
735
|
-
coordinates: [
|
|
736
|
-
[
|
|
737
|
-
[nw.longitude, nw.latitude], // Northwest corner
|
|
738
|
-
[se.longitude, nw.latitude], // Northeast corner
|
|
739
|
-
[se.longitude, se.latitude], // Southeast corner
|
|
740
|
-
[nw.longitude, se.latitude], // Southwest corner
|
|
741
|
-
[nw.longitude, nw.latitude], // Close the loop back to Northwest corner
|
|
742
|
-
],
|
|
743
|
-
],
|
|
744
|
-
};
|
|
745
|
-
};
|
|
746
|
-
/**
|
|
747
|
-
* @description Creates TU point coordinate from a GeoJSON Point.
|
|
748
|
-
*/
|
|
749
|
-
const getPointCoordinateFromGeoJsonPoint = (point) => {
|
|
750
|
-
return { latitude: point.coordinates[1], longitude: point.coordinates[0] };
|
|
751
|
-
};
|
|
752
|
-
|
|
753
416
|
/**
|
|
754
417
|
* Group an array of items by a key.
|
|
755
418
|
*
|
|
@@ -1397,7 +1060,6 @@ const uuidv4 = () => {
|
|
|
1397
1060
|
const uuidv5 = (name, namespace) => uuid.v5(name, namespace);
|
|
1398
1061
|
|
|
1399
1062
|
exports.DateTimeFormat = DateTimeFormat;
|
|
1400
|
-
exports.EARTH_RADIUS = EARTH_RADIUS;
|
|
1401
1063
|
exports.align = align;
|
|
1402
1064
|
exports.alphabeticallySort = alphabeticallySort;
|
|
1403
1065
|
exports.arrayLengthCompare = arrayLengthCompare;
|
|
@@ -1407,7 +1069,6 @@ exports.capitalize = capitalize;
|
|
|
1407
1069
|
exports.convertBlobToBase64 = convertBlobToBase64;
|
|
1408
1070
|
exports.convertMetersToYards = convertMetersToYards;
|
|
1409
1071
|
exports.convertYardsToMeters = convertYardsToMeters;
|
|
1410
|
-
exports.coordinatesToStandardFormat = coordinatesToStandardFormat;
|
|
1411
1072
|
exports.dateCompare = dateCompare;
|
|
1412
1073
|
exports.deleteUndefinedKeys = deleteUndefinedKeys;
|
|
1413
1074
|
exports.difference = difference;
|
|
@@ -1420,29 +1081,10 @@ exports.filterByMultiple = filterByMultiple;
|
|
|
1420
1081
|
exports.formatAddress = formatAddress;
|
|
1421
1082
|
exports.formatCoordinates = formatCoordinates;
|
|
1422
1083
|
exports.fuzzySearch = fuzzySearch;
|
|
1423
|
-
exports.geoJsonBboxSchema = geoJsonBboxSchema;
|
|
1424
|
-
exports.geoJsonGeometrySchema = geoJsonGeometrySchema;
|
|
1425
|
-
exports.geoJsonLineStringSchema = geoJsonLineStringSchema;
|
|
1426
|
-
exports.geoJsonLinearRingSchema = geoJsonLinearRingSchema;
|
|
1427
|
-
exports.geoJsonMultiLineStringSchema = geoJsonMultiLineStringSchema;
|
|
1428
|
-
exports.geoJsonMultiPointSchema = geoJsonMultiPointSchema;
|
|
1429
|
-
exports.geoJsonMultiPolygonSchema = geoJsonMultiPolygonSchema;
|
|
1430
|
-
exports.geoJsonPointSchema = geoJsonPointSchema;
|
|
1431
|
-
exports.geoJsonPolygonNoHolesSchema = geoJsonPolygonNoHolesSchema;
|
|
1432
|
-
exports.geoJsonPolygonSchema = geoJsonPolygonSchema;
|
|
1433
|
-
exports.geoJsonPositionSchema = geoJsonPositionSchema;
|
|
1434
|
-
exports.geoJsonRectangularBoxPolygonSchema = geoJsonRectangularBoxPolygonSchema;
|
|
1435
|
-
exports.getBoundingBoxFromGeoJsonPolygon = getBoundingBoxFromGeoJsonPolygon;
|
|
1436
1084
|
exports.getDifferenceBetweenDates = getDifferenceBetweenDates;
|
|
1437
1085
|
exports.getEndOfDay = getEndOfDay;
|
|
1438
1086
|
exports.getFirstLevelObjectPropertyDifferences = getFirstLevelObjectPropertyDifferences;
|
|
1439
|
-
exports.getGeoJsonPolygonFromBoundingBox = getGeoJsonPolygonFromBoundingBox;
|
|
1440
1087
|
exports.getISOStringFromDate = getISOStringFromDate;
|
|
1441
|
-
exports.getMultipleCoordinatesFromGeoJsonObject = getMultipleCoordinatesFromGeoJsonObject;
|
|
1442
|
-
exports.getPointCoordinateFromGeoJsonObject = getPointCoordinateFromGeoJsonObject;
|
|
1443
|
-
exports.getPointCoordinateFromGeoJsonPoint = getPointCoordinateFromGeoJsonPoint;
|
|
1444
|
-
exports.getPolygonFromBbox = getPolygonFromBbox;
|
|
1445
|
-
exports.getPolygonFromPointAndRadius = getPolygonFromPointAndRadius;
|
|
1446
1088
|
exports.getResizedDimensions = getResizedDimensions;
|
|
1447
1089
|
exports.getStartOfDay = getStartOfDay;
|
|
1448
1090
|
exports.groupBy = groupBy;
|
package/index.esm.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
1
|
import { v3, v4, v5 } from 'uuid';
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -412,342 +411,6 @@ searchTerm) => {
|
|
|
412
411
|
.every(term => filterableProps(asset).some(value => value.toLowerCase().includes(term.toLowerCase()))));
|
|
413
412
|
};
|
|
414
413
|
|
|
415
|
-
// * NOTE: For simplicity these tools are built for 2D coordinate space only!
|
|
416
|
-
/**
|
|
417
|
-
* A Position is an array of coordinates. [x, y]
|
|
418
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.1
|
|
419
|
-
*/
|
|
420
|
-
const geoJsonPositionSchema = z.tuple([z.number(), z.number()]);
|
|
421
|
-
/**
|
|
422
|
-
* Point geometry object.
|
|
423
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.2
|
|
424
|
-
*/
|
|
425
|
-
const geoJsonPointSchema = z.strictObject({
|
|
426
|
-
type: z.literal("Point"),
|
|
427
|
-
coordinates: geoJsonPositionSchema,
|
|
428
|
-
});
|
|
429
|
-
/**
|
|
430
|
-
* MultiPoint geometry object.
|
|
431
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.3
|
|
432
|
-
*/
|
|
433
|
-
const geoJsonMultiPointSchema = z.strictObject({
|
|
434
|
-
type: z.literal("MultiPoint"),
|
|
435
|
-
coordinates: z.array(geoJsonPositionSchema),
|
|
436
|
-
});
|
|
437
|
-
/**
|
|
438
|
-
* LineString geometry object.
|
|
439
|
-
* Minimum length of 2 positions.
|
|
440
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.4
|
|
441
|
-
*/
|
|
442
|
-
const geoJsonLineStringSchema = z.strictObject({
|
|
443
|
-
type: z.literal("LineString"),
|
|
444
|
-
coordinates: z.array(geoJsonPositionSchema).min(2),
|
|
445
|
-
});
|
|
446
|
-
/**
|
|
447
|
-
* MultiLineString geometry object.
|
|
448
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.5
|
|
449
|
-
*/
|
|
450
|
-
const geoJsonMultiLineStringSchema = z.strictObject({
|
|
451
|
-
type: z.literal("MultiLineString"),
|
|
452
|
-
coordinates: z.array(z.array(geoJsonPositionSchema)),
|
|
453
|
-
});
|
|
454
|
-
/**
|
|
455
|
-
* Helper type for reuse across polygon schemas.
|
|
456
|
-
*
|
|
457
|
-
* - A linear ring is a closed LineString with four or more positions.
|
|
458
|
-
* - The first and last positions are equivalent, and they MUST contain
|
|
459
|
-
identical values; their representation SHOULD also be identical
|
|
460
|
-
* - A linear ring is the boundary of a surface or the boundary of a
|
|
461
|
-
hole in a surface
|
|
462
|
-
* - A linear ring MUST follow the right-hand rule with respect to the
|
|
463
|
-
area it bounds, i.e., exterior rings are counterclockwise, and
|
|
464
|
-
holes are clockwise
|
|
465
|
-
*/
|
|
466
|
-
const geoJsonLinearRingSchema = z
|
|
467
|
-
.array(geoJsonPositionSchema)
|
|
468
|
-
.min(4, {
|
|
469
|
-
message: "Coordinates array must contain at least 4 positions. 3 to make a non-line shape and 1 to close the shape (duplicate of first)",
|
|
470
|
-
})
|
|
471
|
-
.superRefine((coords, ctx) => {
|
|
472
|
-
const first = coords[0];
|
|
473
|
-
const last = coords[coords.length - 1];
|
|
474
|
-
// Check if first and last coordinates match
|
|
475
|
-
if (JSON.stringify(first) !== JSON.stringify(last)) {
|
|
476
|
-
ctx.addIssue({
|
|
477
|
-
code: z.ZodIssueCode.custom,
|
|
478
|
-
message: "First and last coordinate positions must be identical (to close the linear ring aka polygon).",
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
// Check if any coordinate is (0, 0)
|
|
482
|
-
coords.forEach((coord, index) => {
|
|
483
|
-
if (coord[0] === 0 && coord[1] === 0) {
|
|
484
|
-
ctx.addIssue({
|
|
485
|
-
code: z.ZodIssueCode.custom,
|
|
486
|
-
message: `Coordinate at index ${index} should not be (0, 0). This is likely not a valid coordinate.`,
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
// Check if consecutive points are identical (excluding first and last)
|
|
491
|
-
for (let i = 1; i < coords.length - 1; i++) {
|
|
492
|
-
if (JSON.stringify(coords[i]) === JSON.stringify(coords[i - 1])) {
|
|
493
|
-
ctx.addIssue({
|
|
494
|
-
code: z.ZodIssueCode.custom,
|
|
495
|
-
message: `Consecutive coordinates at index ${i - 1} and ${i} should not be identical.`,
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
});
|
|
500
|
-
/**
|
|
501
|
-
* Polygon geometry object.
|
|
502
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
503
|
-
*/
|
|
504
|
-
const geoJsonPolygonSchema = z.strictObject({
|
|
505
|
-
type: z.literal("Polygon"),
|
|
506
|
-
coordinates: z.array(geoJsonLinearRingSchema),
|
|
507
|
-
});
|
|
508
|
-
/**
|
|
509
|
-
* MultiPolygon geometry object.
|
|
510
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.7
|
|
511
|
-
*/
|
|
512
|
-
const geoJsonMultiPolygonSchema = z.strictObject({
|
|
513
|
-
type: z.literal("MultiPolygon"),
|
|
514
|
-
coordinates: z.array(z.array(geoJsonLinearRingSchema)),
|
|
515
|
-
});
|
|
516
|
-
// The same for Geometry, GeometryCollection, GeoJsonProperties, Feature, FeatureCollection, etc.
|
|
517
|
-
const geoJsonGeometrySchema = z.union([
|
|
518
|
-
geoJsonPointSchema,
|
|
519
|
-
geoJsonMultiPointSchema,
|
|
520
|
-
geoJsonLineStringSchema,
|
|
521
|
-
geoJsonMultiLineStringSchema,
|
|
522
|
-
geoJsonPolygonSchema,
|
|
523
|
-
geoJsonMultiPolygonSchema,
|
|
524
|
-
]);
|
|
525
|
-
//* -------- Bbox -------- *//
|
|
526
|
-
/**
|
|
527
|
-
* 2D bounding box of the GeoJSON object.
|
|
528
|
-
* The value of the Bbox member is an array of length 4.
|
|
529
|
-
*
|
|
530
|
-
* [min_lon, min_lat, max_lon, max_lat]
|
|
531
|
-
*/
|
|
532
|
-
const geoJsonBboxSchema = z
|
|
533
|
-
.tuple([z.number(), z.number(), z.number(), z.number()])
|
|
534
|
-
.refine(([minLng, minLat, maxLng, maxLat]) => maxLng > minLng && maxLat > minLat, {
|
|
535
|
-
message: "Invalid bounding box: maxLng should be greater than minLng, and maxLat should be greater than minLat.",
|
|
536
|
-
});
|
|
537
|
-
//* -------- Extras -------- *//
|
|
538
|
-
/**
|
|
539
|
-
* Polygon geometry object that explicitly disallows holes.
|
|
540
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
541
|
-
*/
|
|
542
|
-
const geoJsonPolygonNoHolesSchema = z.strictObject({
|
|
543
|
-
type: z.literal("Polygon"),
|
|
544
|
-
//uses tuple instead of array to enforce only 1 linear ring aka the polygon itself
|
|
545
|
-
coordinates: z.tuple([geoJsonLinearRingSchema]),
|
|
546
|
-
});
|
|
547
|
-
/**
|
|
548
|
-
* A Polygon with exactly 5 points and 4 horizontal/vertical sides that form a normal rectangular box.
|
|
549
|
-
*/
|
|
550
|
-
const geoJsonRectangularBoxPolygonSchema = z
|
|
551
|
-
.strictObject({
|
|
552
|
-
type: z.literal("Polygon"),
|
|
553
|
-
coordinates: z.array(geoJsonLinearRingSchema),
|
|
554
|
-
})
|
|
555
|
-
.superRefine((data, ctx) => {
|
|
556
|
-
const coordinates = data.coordinates[0];
|
|
557
|
-
// Validate polygon has exactly 5 points
|
|
558
|
-
if ((coordinates === null || coordinates === void 0 ? void 0 : coordinates.length) !== 5) {
|
|
559
|
-
ctx.addIssue({
|
|
560
|
-
code: z.ZodIssueCode.custom,
|
|
561
|
-
message: "Polygon must have exactly 5 coordinates to form a closed box.",
|
|
562
|
-
});
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
// Check each side is either horizontal or vertical
|
|
566
|
-
for (let i = 0; i < 4; i++) {
|
|
567
|
-
const point1 = coordinates[i];
|
|
568
|
-
const point2 = coordinates[i + 1];
|
|
569
|
-
if (!point1 || !point2) {
|
|
570
|
-
ctx.addIssue({
|
|
571
|
-
code: z.ZodIssueCode.custom,
|
|
572
|
-
message: "Each coordinate must be a defined point.",
|
|
573
|
-
});
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
const [x1, y1] = point1;
|
|
577
|
-
const [x2, y2] = point2;
|
|
578
|
-
// Ensure each line segment is either horizontal or vertical
|
|
579
|
-
if (x1 !== x2 && y1 !== y2) {
|
|
580
|
-
ctx.addIssue({
|
|
581
|
-
code: z.ZodIssueCode.custom,
|
|
582
|
-
message: "Polygon sides must be horizontal or vertical to form a box shape.",
|
|
583
|
-
});
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
const EARTH_RADIUS = 6378137; // Earth’s mean radius in meters
|
|
590
|
-
const isDoubleNestedCoords = (coords) => Array.isArray(coords) &&
|
|
591
|
-
Array.isArray(coords[0]) &&
|
|
592
|
-
Array.isArray(coords[0][0]) &&
|
|
593
|
-
typeof coords[0][0][0] === "number";
|
|
594
|
-
const isSingleCoords = (coords) => typeof coords[0] === "number";
|
|
595
|
-
/**
|
|
596
|
-
* @description Returns coordinates in consistent format
|
|
597
|
-
* @param inconsistentCoordinates Single point, array of points or nested array of points
|
|
598
|
-
* @returns GeoPoint[]
|
|
599
|
-
*/
|
|
600
|
-
const coordinatesToStandardFormat = (inconsistentCoordinates) => {
|
|
601
|
-
if (!inconsistentCoordinates) {
|
|
602
|
-
return [];
|
|
603
|
-
}
|
|
604
|
-
if (isSingleCoords(inconsistentCoordinates)) {
|
|
605
|
-
return [inconsistentCoordinates];
|
|
606
|
-
}
|
|
607
|
-
if (isDoubleNestedCoords(inconsistentCoordinates)) {
|
|
608
|
-
return inconsistentCoordinates[0] || [];
|
|
609
|
-
}
|
|
610
|
-
if (inconsistentCoordinates[0] && typeof inconsistentCoordinates[0][0] === "number") {
|
|
611
|
-
return inconsistentCoordinates;
|
|
612
|
-
}
|
|
613
|
-
return [];
|
|
614
|
-
};
|
|
615
|
-
/**
|
|
616
|
-
* @description Extracts a point coordinate from a GeoJSON object.
|
|
617
|
-
* @param geoObject A GeoJSON object.
|
|
618
|
-
* @returns {PointCoordinate} A point coordinate.
|
|
619
|
-
*/
|
|
620
|
-
const getPointCoordinateFromGeoJsonObject = (geoObject) => {
|
|
621
|
-
if (!geoObject) {
|
|
622
|
-
return undefined;
|
|
623
|
-
}
|
|
624
|
-
else if ("geometry" in geoObject) {
|
|
625
|
-
return getPointCoordinateFromGeoJsonObject(geoObject.geometry);
|
|
626
|
-
}
|
|
627
|
-
else if ("coordinates" in geoObject &&
|
|
628
|
-
Array.isArray(geoObject.coordinates) &&
|
|
629
|
-
typeof geoObject.coordinates[0] === "number" &&
|
|
630
|
-
typeof geoObject.coordinates[1] === "number") {
|
|
631
|
-
const [point] = coordinatesToStandardFormat(geoObject.coordinates);
|
|
632
|
-
if (point) {
|
|
633
|
-
return { latitude: point[1], longitude: point[0] };
|
|
634
|
-
}
|
|
635
|
-
else {
|
|
636
|
-
throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
else {
|
|
640
|
-
throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
/**
|
|
644
|
-
* @description Extracts multiple point coordinates from a GeoJSON object.
|
|
645
|
-
* @param geoObject A GeoJSON object.
|
|
646
|
-
* @returns {PointCoordinate[]} An array of point coordinates.
|
|
647
|
-
* @example getMultipleCoordinatesFromGeoJsonObject({ type: "Point", coordinates: [1, 2] }) // [{ longitude: 1, latitude: 2 }]
|
|
648
|
-
*/
|
|
649
|
-
const getMultipleCoordinatesFromGeoJsonObject = (geoObject) => {
|
|
650
|
-
if (!geoObject) {
|
|
651
|
-
return undefined;
|
|
652
|
-
}
|
|
653
|
-
else if ("geometry" in geoObject) {
|
|
654
|
-
return getMultipleCoordinatesFromGeoJsonObject(geoObject.geometry);
|
|
655
|
-
}
|
|
656
|
-
else if ("coordinates" in geoObject) {
|
|
657
|
-
return coordinatesToStandardFormat(geoObject.coordinates).map(([longitude, latitude]) => ({ longitude, latitude }));
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
/**
|
|
664
|
-
* @description Creates a polygon from a bounding box.
|
|
665
|
-
*/
|
|
666
|
-
const getPolygonFromBbox = (bbox) => {
|
|
667
|
-
const [minLon, minLat, maxLon, maxLat] = bbox;
|
|
668
|
-
return {
|
|
669
|
-
type: "Polygon",
|
|
670
|
-
coordinates: [
|
|
671
|
-
[
|
|
672
|
-
[minLon, minLat],
|
|
673
|
-
[maxLon, minLat],
|
|
674
|
-
[maxLon, maxLat],
|
|
675
|
-
[minLon, maxLat],
|
|
676
|
-
[minLon, minLat],
|
|
677
|
-
],
|
|
678
|
-
],
|
|
679
|
-
};
|
|
680
|
-
};
|
|
681
|
-
/**
|
|
682
|
-
* @description Creates a round polygon from a point and a radius.
|
|
683
|
-
*/
|
|
684
|
-
const getPolygonFromPointAndRadius = (point, radius) => {
|
|
685
|
-
const [lon, lat] = point.coordinates;
|
|
686
|
-
// Adjust the number of points based on radius (resolution)
|
|
687
|
-
const pointsCount = Math.max(32, Math.floor(radius / 100)); // More points for larger radius
|
|
688
|
-
const angleStep = (2 * Math.PI) / pointsCount;
|
|
689
|
-
const coordinates = [];
|
|
690
|
-
for (let i = 0; i <= pointsCount; i++) {
|
|
691
|
-
const angle = i * angleStep;
|
|
692
|
-
// Calculate offset in latitude and longitude
|
|
693
|
-
const deltaLat = (radius / EARTH_RADIUS) * (180 / Math.PI);
|
|
694
|
-
const deltaLon = deltaLat / Math.cos((lat * Math.PI) / 180);
|
|
695
|
-
// Calculate new coordinates based on angle
|
|
696
|
-
const newLat = lat + deltaLat * Math.sin(angle);
|
|
697
|
-
const newLon = lon + deltaLon * Math.cos(angle);
|
|
698
|
-
coordinates.push([newLon, newLat]);
|
|
699
|
-
}
|
|
700
|
-
return {
|
|
701
|
-
type: "Polygon",
|
|
702
|
-
coordinates: [coordinates],
|
|
703
|
-
};
|
|
704
|
-
};
|
|
705
|
-
/**
|
|
706
|
-
* @description Creates a TU bounding box from a GeoJson Polygon.
|
|
707
|
-
*/
|
|
708
|
-
const getBoundingBoxFromGeoJsonPolygon = (polygon) => {
|
|
709
|
-
const points = polygon.coordinates[0];
|
|
710
|
-
const latitudes = points === null || points === void 0 ? void 0 : points.map(point => point[1]);
|
|
711
|
-
const longitudes = points === null || points === void 0 ? void 0 : points.map(point => point[0]);
|
|
712
|
-
if (!latitudes || !longitudes) {
|
|
713
|
-
return undefined;
|
|
714
|
-
}
|
|
715
|
-
return {
|
|
716
|
-
nw: {
|
|
717
|
-
latitude: Math.max(...latitudes),
|
|
718
|
-
longitude: Math.min(...longitudes),
|
|
719
|
-
},
|
|
720
|
-
se: {
|
|
721
|
-
latitude: Math.min(...latitudes),
|
|
722
|
-
longitude: Math.max(...longitudes),
|
|
723
|
-
},
|
|
724
|
-
};
|
|
725
|
-
};
|
|
726
|
-
/**
|
|
727
|
-
* @description Creates a GeoJSON Polygon from a TU bounding box.
|
|
728
|
-
*/
|
|
729
|
-
const getGeoJsonPolygonFromBoundingBox = (boundingBox) => {
|
|
730
|
-
const { nw, se } = boundingBox;
|
|
731
|
-
return {
|
|
732
|
-
type: "Polygon",
|
|
733
|
-
coordinates: [
|
|
734
|
-
[
|
|
735
|
-
[nw.longitude, nw.latitude], // Northwest corner
|
|
736
|
-
[se.longitude, nw.latitude], // Northeast corner
|
|
737
|
-
[se.longitude, se.latitude], // Southeast corner
|
|
738
|
-
[nw.longitude, se.latitude], // Southwest corner
|
|
739
|
-
[nw.longitude, nw.latitude], // Close the loop back to Northwest corner
|
|
740
|
-
],
|
|
741
|
-
],
|
|
742
|
-
};
|
|
743
|
-
};
|
|
744
|
-
/**
|
|
745
|
-
* @description Creates TU point coordinate from a GeoJSON Point.
|
|
746
|
-
*/
|
|
747
|
-
const getPointCoordinateFromGeoJsonPoint = (point) => {
|
|
748
|
-
return { latitude: point.coordinates[1], longitude: point.coordinates[0] };
|
|
749
|
-
};
|
|
750
|
-
|
|
751
414
|
/**
|
|
752
415
|
* Group an array of items by a key.
|
|
753
416
|
*
|
|
@@ -1394,4 +1057,4 @@ const uuidv4 = () => {
|
|
|
1394
1057
|
*/
|
|
1395
1058
|
const uuidv5 = (name, namespace) => v5(name, namespace);
|
|
1396
1059
|
|
|
1397
|
-
export { DateTimeFormat,
|
|
1060
|
+
export { DateTimeFormat, HoursAndMinutesFormat, align, alphabeticallySort, arrayLengthCompare, arrayNotEmpty, booleanCompare, capitalize, convertBlobToBase64, convertMetersToYards, convertYardsToMeters, dateCompare, deleteUndefinedKeys, difference, doNothing, enumFromValue, enumFromValueTypesafe, enumOrUndefinedFromValue, exhaustiveCheck, filterByMultiple, formatAddress, formatCoordinates, fuzzySearch, getDifferenceBetweenDates, getEndOfDay, getFirstLevelObjectPropertyDifferences, getISOStringFromDate, getResizedDimensions, getStartOfDay, groupBy, groupTinyDataToOthers, hourIntervals, intersection, isArrayEqual, isSorted, isUUID, isValidImage, nonNullable, numberCompare, numberCompareUnknownAfterHighest, objNotEmpty, objectEntries, objectFromEntries, objectKeys, objectValues, pick, removeLeftPadding, resizeBlob, resizeImage, size, stringCompare, stringCompareFromKey, stringNaturalCompare, stripHiddenCharacters, titleCase, toID, toIDs, toUUID, trimIds, trimPath, truthy, unionArraysByKey, uuidv3, uuidv4, uuidv5 };
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/shared-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.86",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.x"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"uuid": "^10.0.0"
|
|
11
|
-
"zod": "3.22.4"
|
|
10
|
+
"uuid": "^10.0.0"
|
|
12
11
|
},
|
|
13
12
|
"module": "./index.esm.js",
|
|
14
13
|
"main": "./index.cjs.js",
|
package/src/index.d.ts
CHANGED
|
@@ -9,8 +9,6 @@ export * from "./enumUtils";
|
|
|
9
9
|
export * from "./exhaustiveCheck";
|
|
10
10
|
export * from "./fastArrayOperations";
|
|
11
11
|
export * from "./filter";
|
|
12
|
-
export * from "./GeoJson/GeoJsonSchemas";
|
|
13
|
-
export * from "./GeoJson/GeoJsonUtils";
|
|
14
12
|
export * from "./groupBy/groupBy";
|
|
15
13
|
export * from "./GroupingUtility";
|
|
16
14
|
export * from "./idUtils";
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
/**
|
|
3
|
-
* A Position is an array of coordinates. [x, y]
|
|
4
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.1
|
|
5
|
-
*/
|
|
6
|
-
export declare const geoJsonPositionSchema: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
7
|
-
export type GeoJsonPosition = z.infer<typeof geoJsonPositionSchema>;
|
|
8
|
-
/**
|
|
9
|
-
* Point geometry object.
|
|
10
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.2
|
|
11
|
-
*/
|
|
12
|
-
export declare const geoJsonPointSchema: z.ZodObject<{
|
|
13
|
-
type: z.ZodLiteral<"Point">;
|
|
14
|
-
coordinates: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
15
|
-
}, "strict", z.ZodTypeAny, {
|
|
16
|
-
type: "Point";
|
|
17
|
-
coordinates: [number, number];
|
|
18
|
-
}, {
|
|
19
|
-
type: "Point";
|
|
20
|
-
coordinates: [number, number];
|
|
21
|
-
}>;
|
|
22
|
-
export type GeoJsonPoint = z.infer<typeof geoJsonPointSchema>;
|
|
23
|
-
/**
|
|
24
|
-
* MultiPoint geometry object.
|
|
25
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.3
|
|
26
|
-
*/
|
|
27
|
-
export declare const geoJsonMultiPointSchema: z.ZodObject<{
|
|
28
|
-
type: z.ZodLiteral<"MultiPoint">;
|
|
29
|
-
coordinates: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">;
|
|
30
|
-
}, "strict", z.ZodTypeAny, {
|
|
31
|
-
type: "MultiPoint";
|
|
32
|
-
coordinates: [number, number][];
|
|
33
|
-
}, {
|
|
34
|
-
type: "MultiPoint";
|
|
35
|
-
coordinates: [number, number][];
|
|
36
|
-
}>;
|
|
37
|
-
export type GeoJsonMultiPoint = z.infer<typeof geoJsonMultiPointSchema>;
|
|
38
|
-
/**
|
|
39
|
-
* LineString geometry object.
|
|
40
|
-
* Minimum length of 2 positions.
|
|
41
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.4
|
|
42
|
-
*/
|
|
43
|
-
export declare const geoJsonLineStringSchema: z.ZodObject<{
|
|
44
|
-
type: z.ZodLiteral<"LineString">;
|
|
45
|
-
coordinates: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">;
|
|
46
|
-
}, "strict", z.ZodTypeAny, {
|
|
47
|
-
type: "LineString";
|
|
48
|
-
coordinates: [number, number][];
|
|
49
|
-
}, {
|
|
50
|
-
type: "LineString";
|
|
51
|
-
coordinates: [number, number][];
|
|
52
|
-
}>;
|
|
53
|
-
export type GeoJsonLineString = z.infer<typeof geoJsonLineStringSchema>;
|
|
54
|
-
/**
|
|
55
|
-
* MultiLineString geometry object.
|
|
56
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.5
|
|
57
|
-
*/
|
|
58
|
-
export declare const geoJsonMultiLineStringSchema: z.ZodObject<{
|
|
59
|
-
type: z.ZodLiteral<"MultiLineString">;
|
|
60
|
-
coordinates: z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, "many">;
|
|
61
|
-
}, "strict", z.ZodTypeAny, {
|
|
62
|
-
type: "MultiLineString";
|
|
63
|
-
coordinates: [number, number][][];
|
|
64
|
-
}, {
|
|
65
|
-
type: "MultiLineString";
|
|
66
|
-
coordinates: [number, number][][];
|
|
67
|
-
}>;
|
|
68
|
-
export type GeoJsonMultiLineString = z.infer<typeof geoJsonMultiLineStringSchema>;
|
|
69
|
-
/**
|
|
70
|
-
* Helper type for reuse across polygon schemas.
|
|
71
|
-
*
|
|
72
|
-
* - A linear ring is a closed LineString with four or more positions.
|
|
73
|
-
* - The first and last positions are equivalent, and they MUST contain
|
|
74
|
-
identical values; their representation SHOULD also be identical
|
|
75
|
-
* - A linear ring is the boundary of a surface or the boundary of a
|
|
76
|
-
hole in a surface
|
|
77
|
-
* - A linear ring MUST follow the right-hand rule with respect to the
|
|
78
|
-
area it bounds, i.e., exterior rings are counterclockwise, and
|
|
79
|
-
holes are clockwise
|
|
80
|
-
*/
|
|
81
|
-
export declare const geoJsonLinearRingSchema: z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>;
|
|
82
|
-
export type GeoJsonLinearRing = z.infer<typeof geoJsonLinearRingSchema>;
|
|
83
|
-
/**
|
|
84
|
-
* Polygon geometry object.
|
|
85
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
86
|
-
*/
|
|
87
|
-
export declare const geoJsonPolygonSchema: z.ZodObject<{
|
|
88
|
-
type: z.ZodLiteral<"Polygon">;
|
|
89
|
-
coordinates: z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>, "many">;
|
|
90
|
-
}, "strict", z.ZodTypeAny, {
|
|
91
|
-
type: "Polygon";
|
|
92
|
-
coordinates: [number, number][][];
|
|
93
|
-
}, {
|
|
94
|
-
type: "Polygon";
|
|
95
|
-
coordinates: [number, number][][];
|
|
96
|
-
}>;
|
|
97
|
-
export type GeoJsonPolygon = z.infer<typeof geoJsonPolygonSchema>;
|
|
98
|
-
/**
|
|
99
|
-
* MultiPolygon geometry object.
|
|
100
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.7
|
|
101
|
-
*/
|
|
102
|
-
export declare const geoJsonMultiPolygonSchema: z.ZodObject<{
|
|
103
|
-
type: z.ZodLiteral<"MultiPolygon">;
|
|
104
|
-
coordinates: z.ZodArray<z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>, "many">, "many">;
|
|
105
|
-
}, "strict", z.ZodTypeAny, {
|
|
106
|
-
type: "MultiPolygon";
|
|
107
|
-
coordinates: [number, number][][][];
|
|
108
|
-
}, {
|
|
109
|
-
type: "MultiPolygon";
|
|
110
|
-
coordinates: [number, number][][][];
|
|
111
|
-
}>;
|
|
112
|
-
export type GeoJsonMultiPolygon = z.infer<typeof geoJsonMultiPolygonSchema>;
|
|
113
|
-
export declare const geoJsonGeometrySchema: z.ZodUnion<[z.ZodObject<{
|
|
114
|
-
type: z.ZodLiteral<"Point">;
|
|
115
|
-
coordinates: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
116
|
-
}, "strict", z.ZodTypeAny, {
|
|
117
|
-
type: "Point";
|
|
118
|
-
coordinates: [number, number];
|
|
119
|
-
}, {
|
|
120
|
-
type: "Point";
|
|
121
|
-
coordinates: [number, number];
|
|
122
|
-
}>, z.ZodObject<{
|
|
123
|
-
type: z.ZodLiteral<"MultiPoint">;
|
|
124
|
-
coordinates: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">;
|
|
125
|
-
}, "strict", z.ZodTypeAny, {
|
|
126
|
-
type: "MultiPoint";
|
|
127
|
-
coordinates: [number, number][];
|
|
128
|
-
}, {
|
|
129
|
-
type: "MultiPoint";
|
|
130
|
-
coordinates: [number, number][];
|
|
131
|
-
}>, z.ZodObject<{
|
|
132
|
-
type: z.ZodLiteral<"LineString">;
|
|
133
|
-
coordinates: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">;
|
|
134
|
-
}, "strict", z.ZodTypeAny, {
|
|
135
|
-
type: "LineString";
|
|
136
|
-
coordinates: [number, number][];
|
|
137
|
-
}, {
|
|
138
|
-
type: "LineString";
|
|
139
|
-
coordinates: [number, number][];
|
|
140
|
-
}>, z.ZodObject<{
|
|
141
|
-
type: z.ZodLiteral<"MultiLineString">;
|
|
142
|
-
coordinates: z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, "many">;
|
|
143
|
-
}, "strict", z.ZodTypeAny, {
|
|
144
|
-
type: "MultiLineString";
|
|
145
|
-
coordinates: [number, number][][];
|
|
146
|
-
}, {
|
|
147
|
-
type: "MultiLineString";
|
|
148
|
-
coordinates: [number, number][][];
|
|
149
|
-
}>, z.ZodObject<{
|
|
150
|
-
type: z.ZodLiteral<"Polygon">;
|
|
151
|
-
coordinates: z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>, "many">;
|
|
152
|
-
}, "strict", z.ZodTypeAny, {
|
|
153
|
-
type: "Polygon";
|
|
154
|
-
coordinates: [number, number][][];
|
|
155
|
-
}, {
|
|
156
|
-
type: "Polygon";
|
|
157
|
-
coordinates: [number, number][][];
|
|
158
|
-
}>, z.ZodObject<{
|
|
159
|
-
type: z.ZodLiteral<"MultiPolygon">;
|
|
160
|
-
coordinates: z.ZodArray<z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>, "many">, "many">;
|
|
161
|
-
}, "strict", z.ZodTypeAny, {
|
|
162
|
-
type: "MultiPolygon";
|
|
163
|
-
coordinates: [number, number][][][];
|
|
164
|
-
}, {
|
|
165
|
-
type: "MultiPolygon";
|
|
166
|
-
coordinates: [number, number][][][];
|
|
167
|
-
}>]>;
|
|
168
|
-
export type GeoJsonGeometry = z.infer<typeof geoJsonGeometrySchema>;
|
|
169
|
-
/**
|
|
170
|
-
* 2D bounding box of the GeoJSON object.
|
|
171
|
-
* The value of the Bbox member is an array of length 4.
|
|
172
|
-
*
|
|
173
|
-
* [min_lon, min_lat, max_lon, max_lat]
|
|
174
|
-
*/
|
|
175
|
-
export declare const geoJsonBboxSchema: z.ZodEffects<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber], null>, [number, number, number, number], [number, number, number, number]>;
|
|
176
|
-
export type GeoJsonBbox = z.infer<typeof geoJsonBboxSchema>;
|
|
177
|
-
/**
|
|
178
|
-
* Polygon geometry object that explicitly disallows holes.
|
|
179
|
-
* https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
180
|
-
*/
|
|
181
|
-
export declare const geoJsonPolygonNoHolesSchema: z.ZodObject<{
|
|
182
|
-
type: z.ZodLiteral<"Polygon">;
|
|
183
|
-
coordinates: z.ZodTuple<[z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>], null>;
|
|
184
|
-
}, "strict", z.ZodTypeAny, {
|
|
185
|
-
type: "Polygon";
|
|
186
|
-
coordinates: [[number, number][]];
|
|
187
|
-
}, {
|
|
188
|
-
type: "Polygon";
|
|
189
|
-
coordinates: [[number, number][]];
|
|
190
|
-
}>;
|
|
191
|
-
export type GeoJsonPolygonNoHoles = z.infer<typeof geoJsonPolygonNoHolesSchema>;
|
|
192
|
-
/**
|
|
193
|
-
* A Polygon with exactly 5 points and 4 horizontal/vertical sides that form a normal rectangular box.
|
|
194
|
-
*/
|
|
195
|
-
export declare const geoJsonRectangularBoxPolygonSchema: z.ZodEffects<z.ZodObject<{
|
|
196
|
-
type: z.ZodLiteral<"Polygon">;
|
|
197
|
-
coordinates: z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>, "many">;
|
|
198
|
-
}, "strict", z.ZodTypeAny, {
|
|
199
|
-
type: "Polygon";
|
|
200
|
-
coordinates: [number, number][][];
|
|
201
|
-
}, {
|
|
202
|
-
type: "Polygon";
|
|
203
|
-
coordinates: [number, number][][];
|
|
204
|
-
}>, {
|
|
205
|
-
type: "Polygon";
|
|
206
|
-
coordinates: [number, number][][];
|
|
207
|
-
}, {
|
|
208
|
-
type: "Polygon";
|
|
209
|
-
coordinates: [number, number][][];
|
|
210
|
-
}>;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { GeoJsonBbox, GeoJsonPoint, GeoJsonPolygon } from "./GeoJsonSchemas";
|
|
2
|
-
export declare const EARTH_RADIUS = 6378137;
|
|
3
|
-
interface PointCoordinate {
|
|
4
|
-
longitude: number;
|
|
5
|
-
latitude: number;
|
|
6
|
-
}
|
|
7
|
-
interface BoundingBox {
|
|
8
|
-
nw: PointCoordinate;
|
|
9
|
-
se: PointCoordinate;
|
|
10
|
-
}
|
|
11
|
-
export type GeoPoint = [number, number];
|
|
12
|
-
interface GeoJSONGeometry {
|
|
13
|
-
type?: unknown;
|
|
14
|
-
coordinates?: GeoPoint | GeoPoint[] | GeoPoint[][] | null;
|
|
15
|
-
}
|
|
16
|
-
interface GeoJsonFeature {
|
|
17
|
-
type?: unknown;
|
|
18
|
-
geometry?: GeoJSONGeometry | null;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* @description Returns coordinates in consistent format
|
|
22
|
-
* @param inconsistentCoordinates Single point, array of points or nested array of points
|
|
23
|
-
* @returns GeoPoint[]
|
|
24
|
-
*/
|
|
25
|
-
export declare const coordinatesToStandardFormat: (inconsistentCoordinates: GeoPoint | GeoPoint[] | GeoPoint[][] | null | undefined) => GeoPoint[];
|
|
26
|
-
/**
|
|
27
|
-
* @description Extracts a point coordinate from a GeoJSON object.
|
|
28
|
-
* @param geoObject A GeoJSON object.
|
|
29
|
-
* @returns {PointCoordinate} A point coordinate.
|
|
30
|
-
*/
|
|
31
|
-
export declare const getPointCoordinateFromGeoJsonObject: (geoObject: GeoJsonFeature | GeoJSONGeometry | undefined | null) => PointCoordinate | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* @description Extracts multiple point coordinates from a GeoJSON object.
|
|
34
|
-
* @param geoObject A GeoJSON object.
|
|
35
|
-
* @returns {PointCoordinate[]} An array of point coordinates.
|
|
36
|
-
* @example getMultipleCoordinatesFromGeoJsonObject({ type: "Point", coordinates: [1, 2] }) // [{ longitude: 1, latitude: 2 }]
|
|
37
|
-
*/
|
|
38
|
-
export declare const getMultipleCoordinatesFromGeoJsonObject: (geoObject: GeoJsonFeature | GeoJSONGeometry | undefined | null) => PointCoordinate[] | undefined;
|
|
39
|
-
/**
|
|
40
|
-
* @description Creates a polygon from a bounding box.
|
|
41
|
-
*/
|
|
42
|
-
export declare const getPolygonFromBbox: (bbox: GeoJsonBbox) => GeoJsonPolygon;
|
|
43
|
-
/**
|
|
44
|
-
* @description Creates a round polygon from a point and a radius.
|
|
45
|
-
*/
|
|
46
|
-
export declare const getPolygonFromPointAndRadius: (point: GeoJsonPoint, radius: number) => GeoJsonPolygon;
|
|
47
|
-
/**
|
|
48
|
-
* @description Creates a TU bounding box from a GeoJson Polygon.
|
|
49
|
-
*/
|
|
50
|
-
export declare const getBoundingBoxFromGeoJsonPolygon: (polygon: GeoJsonPolygon) => BoundingBox | undefined;
|
|
51
|
-
/**
|
|
52
|
-
* @description Creates a GeoJSON Polygon from a TU bounding box.
|
|
53
|
-
*/
|
|
54
|
-
export declare const getGeoJsonPolygonFromBoundingBox: (boundingBox: BoundingBox) => GeoJsonPolygon;
|
|
55
|
-
/**
|
|
56
|
-
* @description Creates TU point coordinate from a GeoJSON Point.
|
|
57
|
-
*/
|
|
58
|
-
export declare const getPointCoordinateFromGeoJsonPoint: (point: GeoJsonPoint) => PointCoordinate;
|
|
59
|
-
export {};
|