@trackunit/geo-json-utils 0.0.1

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/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Trackunit geo-json-utils
2
+
3
+ The `@trackunit/geo-json-utils` package is the home of Trackunits public react components used for...
4
+
5
+ This library is exposed publicly for use in the the Trackunit [Iris App SDK](https://www.npmjs.com/package/@trackunit/iris-app).
6
+
7
+ To browse all avaliable components visit our [Public Storybook](https://apps.iris.trackunit.com/storybook/).
8
+
9
+ For more info and a full guide on Iris App SDK Development, please visit our [Developer Hub](https://developers.trackunit.com/).
10
+
11
+ ## Development
12
+
13
+ At this point this library is only developed by Trackunit Employees.
14
+ For development related information see the [development readme](https://github.com/Trackunit/manager/blob/master/libs/react/components/DEVELOPMENT.md).
15
+
16
+ ## Trackunit
17
+
18
+ This package was developed by Trackunit ApS.
19
+ Trackunit is the leading SaaS-based IoT solution for the construction industry, offering an ecosystem of hardware, fleet management software & telematics.
20
+
21
+ ![The Trackunit logo](https://trackunit.com/wp-content/uploads/2022/03/top-logo.svg)
package/index.cjs.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index";
package/index.cjs.js ADDED
@@ -0,0 +1,520 @@
1
+ 'use strict';
2
+
3
+ var zod = require('zod');
4
+ var polygonClipping = require('polygon-clipping');
5
+
6
+ // * NOTE: For simplicity these tools are built for 2D coordinate space only!
7
+ /**
8
+ * A Position is an array of coordinates. [x, y]
9
+ * https://tools.ietf.org/html/rfc7946#section-3.1.1
10
+ */
11
+ const geoJsonPositionSchema = zod.z.tuple([zod.z.number(), zod.z.number()]);
12
+ /**
13
+ * Point geometry object.
14
+ * https://tools.ietf.org/html/rfc7946#section-3.1.2
15
+ */
16
+ const geoJsonPointSchema = zod.z.strictObject({
17
+ type: zod.z.literal("Point"),
18
+ coordinates: geoJsonPositionSchema,
19
+ });
20
+ /**
21
+ * MultiPoint geometry object.
22
+ * https://tools.ietf.org/html/rfc7946#section-3.1.3
23
+ */
24
+ const geoJsonMultiPointSchema = zod.z.strictObject({
25
+ type: zod.z.literal("MultiPoint"),
26
+ coordinates: zod.z.array(geoJsonPositionSchema),
27
+ });
28
+ /**
29
+ * LineString geometry object.
30
+ * Minimum length of 2 positions.
31
+ * https://tools.ietf.org/html/rfc7946#section-3.1.4
32
+ */
33
+ const geoJsonLineStringSchema = zod.z.strictObject({
34
+ type: zod.z.literal("LineString"),
35
+ coordinates: zod.z.array(geoJsonPositionSchema).min(2),
36
+ });
37
+ /**
38
+ * MultiLineString geometry object.
39
+ * https://tools.ietf.org/html/rfc7946#section-3.1.5
40
+ */
41
+ const geoJsonMultiLineStringSchema = zod.z.strictObject({
42
+ type: zod.z.literal("MultiLineString"),
43
+ coordinates: zod.z.array(zod.z.array(geoJsonPositionSchema)),
44
+ });
45
+ /**
46
+ * Helper type for reuse across polygon schemas.
47
+ *
48
+ * - A linear ring is a closed LineString with four or more positions.
49
+ * - The first and last positions are equivalent, and they MUST contain
50
+ identical values; their representation SHOULD also be identical
51
+ * - A linear ring is the boundary of a surface or the boundary of a
52
+ hole in a surface
53
+ * - A linear ring MUST follow the right-hand rule with respect to the
54
+ area it bounds, i.e., exterior rings are counterclockwise, and
55
+ holes are clockwise
56
+ */
57
+ const geoJsonLinearRingSchema = zod.z
58
+ .array(geoJsonPositionSchema)
59
+ .min(4, {
60
+ 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)",
61
+ })
62
+ .superRefine((coords, ctx) => {
63
+ const first = coords[0];
64
+ const last = coords[coords.length - 1];
65
+ // Check if first and last coordinates match
66
+ if (JSON.stringify(first) !== JSON.stringify(last)) {
67
+ ctx.addIssue({
68
+ code: zod.z.ZodIssueCode.custom,
69
+ message: "First and last coordinate positions must be identical (to close the linear ring aka polygon).",
70
+ });
71
+ }
72
+ // Check if consecutive points are identical (excluding first and last)
73
+ for (let i = 1; i < coords.length - 1; i++) {
74
+ if (JSON.stringify(coords[i]) === JSON.stringify(coords[i - 1])) {
75
+ ctx.addIssue({
76
+ code: zod.z.ZodIssueCode.custom,
77
+ message: `Consecutive coordinates at index ${i - 1} and ${i} should not be identical.`,
78
+ });
79
+ }
80
+ }
81
+ });
82
+ /**
83
+ * Polygon geometry object.
84
+ * https://tools.ietf.org/html/rfc7946#section-3.1.6
85
+ */
86
+ const geoJsonPolygonSchema = zod.z.strictObject({
87
+ type: zod.z.literal("Polygon"),
88
+ coordinates: zod.z.array(geoJsonLinearRingSchema),
89
+ });
90
+ /**
91
+ * MultiPolygon geometry object.
92
+ * https://tools.ietf.org/html/rfc7946#section-3.1.7
93
+ */
94
+ const geoJsonMultiPolygonSchema = zod.z.strictObject({
95
+ type: zod.z.literal("MultiPolygon"),
96
+ coordinates: zod.z.array(zod.z.array(geoJsonLinearRingSchema)),
97
+ });
98
+ // The same for Geometry, GeometryCollection, GeoJsonProperties, Feature, FeatureCollection, etc.
99
+ const geoJsonGeometrySchema = zod.z.union([
100
+ geoJsonPointSchema,
101
+ geoJsonMultiPointSchema,
102
+ geoJsonLineStringSchema,
103
+ geoJsonMultiLineStringSchema,
104
+ geoJsonPolygonSchema,
105
+ geoJsonMultiPolygonSchema,
106
+ ]);
107
+ //* -------- Bbox -------- *//
108
+ /**
109
+ * 2D bounding box of the GeoJSON object.
110
+ * The value of the Bbox member is an array of length 4.
111
+ *
112
+ * [min_lon, min_lat, max_lon, max_lat]
113
+ */
114
+ const geoJsonBboxSchema = zod.z
115
+ .tuple([zod.z.number(), zod.z.number(), zod.z.number(), zod.z.number()])
116
+ .refine(([minLng, minLat, maxLng, maxLat]) => maxLng > minLng && maxLat > minLat, {
117
+ message: "Invalid bounding box: maxLng should be greater than minLng, and maxLat should be greater than minLat.",
118
+ });
119
+
120
+ const EARTH_RADIUS = 6378137; // Earth’s mean radius in meters
121
+ /**
122
+ * @description Creates a polygon (with no holes) from a bounding box.
123
+ */
124
+ const getPolygonFromBbox = (bbox) => {
125
+ const [minLon, minLat, maxLon, maxLat] = bbox;
126
+ return {
127
+ type: "Polygon",
128
+ coordinates: [
129
+ [
130
+ [minLon, minLat],
131
+ [maxLon, minLat],
132
+ [maxLon, maxLat],
133
+ [minLon, maxLat],
134
+ [minLon, minLat],
135
+ ],
136
+ ],
137
+ };
138
+ };
139
+ /**
140
+ * @description Creates a bounding box from a GeoJSON Polygon.
141
+ */
142
+ const getBboxFromGeoJsonPolygon = (polygon) => {
143
+ const polygonParsed = geoJsonPolygonSchema.safeParse(polygon);
144
+ if (!polygonParsed.success) {
145
+ return null;
146
+ }
147
+ const points = polygonParsed.data.coordinates[0];
148
+ if (!points) {
149
+ // Should never happen since the schema checks for it
150
+ return null;
151
+ }
152
+ const latitudes = points.map(point => point[1]);
153
+ const longitudes = points.map(point => point[0]);
154
+ return [Math.min(...longitudes), Math.min(...latitudes), Math.max(...longitudes), Math.max(...latitudes)];
155
+ };
156
+ /**
157
+ * @description Creates a round polygon from a point and a radius.
158
+ */
159
+ const getPolygonFromPointAndRadius = (point, radius) => {
160
+ const [lon, lat] = point.coordinates;
161
+ // Adjust the number of points based on radius (resolution)
162
+ const pointsCount = Math.max(32, Math.floor(radius / 100)); // More points for larger radius
163
+ const angleStep = (2 * Math.PI) / pointsCount;
164
+ const coordinates = [];
165
+ for (let i = 0; i <= pointsCount; i++) {
166
+ const angle = i * angleStep;
167
+ // Calculate offset in latitude and longitude
168
+ const deltaLat = (radius / EARTH_RADIUS) * (180 / Math.PI);
169
+ const deltaLon = deltaLat / Math.cos((lat * Math.PI) / 180);
170
+ // Calculate new coordinates based on angle
171
+ const newLat = lat + deltaLat * Math.sin(angle);
172
+ const newLon = lon + deltaLon * Math.cos(angle);
173
+ coordinates.push([newLon, newLat]);
174
+ }
175
+ return {
176
+ type: "Polygon",
177
+ coordinates: [coordinates],
178
+ };
179
+ };
180
+ /**
181
+ * @description Creates a TU bounding box from a GeoJson Polygon.
182
+ */
183
+ const getBoundingBoxFromGeoJsonPolygon = (polygon) => {
184
+ const polygonParsed = geoJsonPolygonSchema.safeParse(polygon);
185
+ if (!polygonParsed.success) {
186
+ return null;
187
+ }
188
+ const points = polygonParsed.data.coordinates[0];
189
+ if (!points) {
190
+ // Should never happen since the schema checks for it
191
+ return null;
192
+ }
193
+ const latitudes = points.map(point => point[1]);
194
+ const longitudes = points.map(point => point[0]);
195
+ return {
196
+ nw: {
197
+ latitude: Math.max(...latitudes),
198
+ longitude: Math.min(...longitudes),
199
+ },
200
+ se: {
201
+ latitude: Math.min(...latitudes),
202
+ longitude: Math.max(...longitudes),
203
+ },
204
+ };
205
+ };
206
+ /**
207
+ * @description Creates a GeoJSON Polygon from a TU bounding box.
208
+ */
209
+ const getGeoJsonPolygonFromBoundingBox = (boundingBox) => {
210
+ const { nw, se } = boundingBox;
211
+ return {
212
+ type: "Polygon",
213
+ coordinates: [
214
+ [
215
+ [nw.longitude, nw.latitude], // Northwest corner
216
+ [se.longitude, nw.latitude], // Northeast corner
217
+ [se.longitude, se.latitude], // Southeast corner
218
+ [nw.longitude, se.latitude], // Southwest corner
219
+ [nw.longitude, nw.latitude], // Close the loop back to Northwest corner
220
+ ],
221
+ ],
222
+ };
223
+ };
224
+ /**
225
+ * @description Creates TU point coordinate from a GeoJSON Point.
226
+ */
227
+ const getPointCoordinateFromGeoJsonPoint = (point) => {
228
+ return { latitude: point.coordinates[1], longitude: point.coordinates[0] };
229
+ };
230
+ /**
231
+ * @description Gets the extreme point of a polygon in a given direction.
232
+ * @param {object} params - The parameters object
233
+ * @param {GeoJsonPolygon} params.polygon - The polygon to get the extreme point from
234
+ * @param {("top" | "right" | "bottom" | "left")} params.direction - The direction to get the extreme point in
235
+ * @returns {GeoJsonPoint} The extreme point in the given direction
236
+ */
237
+ const getExtremeGeoJsonPointFromPolygon = ({ polygon, direction, }) => {
238
+ var _a, _b, _c;
239
+ const polygonParsed = geoJsonPolygonSchema.safeParse(polygon);
240
+ if (!polygonParsed.success) {
241
+ return null;
242
+ }
243
+ const firstPoint = (_a = polygonParsed.data.coordinates[0]) === null || _a === void 0 ? void 0 : _a[0];
244
+ if (!firstPoint) {
245
+ // Should never happen since the schema checks for it
246
+ return null;
247
+ }
248
+ const extremePosition = (_b = polygonParsed.data.coordinates[0]) === null || _b === void 0 ? void 0 : _b.reduce((extremePoint, currentPoint) => {
249
+ var _a, _b, _c, _d;
250
+ switch (direction) {
251
+ case "top":
252
+ return currentPoint[1] > ((_a = extremePoint === null || extremePoint === void 0 ? void 0 : extremePoint[1]) !== null && _a !== void 0 ? _a : -Infinity) ? currentPoint : extremePoint !== null && extremePoint !== void 0 ? extremePoint : currentPoint;
253
+ case "right":
254
+ return currentPoint[0] > ((_b = extremePoint === null || extremePoint === void 0 ? void 0 : extremePoint[0]) !== null && _b !== void 0 ? _b : -Infinity) ? currentPoint : extremePoint !== null && extremePoint !== void 0 ? extremePoint : currentPoint;
255
+ case "bottom":
256
+ return currentPoint[1] < ((_c = extremePoint === null || extremePoint === void 0 ? void 0 : extremePoint[1]) !== null && _c !== void 0 ? _c : Infinity) ? currentPoint : extremePoint !== null && extremePoint !== void 0 ? extremePoint : currentPoint;
257
+ case "left":
258
+ return currentPoint[0] < ((_d = extremePoint === null || extremePoint === void 0 ? void 0 : extremePoint[0]) !== null && _d !== void 0 ? _d : Infinity) ? currentPoint : extremePoint !== null && extremePoint !== void 0 ? extremePoint : currentPoint;
259
+ default: {
260
+ throw new Error(`${direction} is not known`);
261
+ }
262
+ }
263
+ }, (_c = polygonParsed.data.coordinates[0]) === null || _c === void 0 ? void 0 : _c[0]);
264
+ return extremePosition
265
+ ? {
266
+ type: "Point",
267
+ coordinates: extremePosition,
268
+ }
269
+ : null; // Should never happen since the schema checks for it
270
+ };
271
+ /**
272
+ * Checks if a position is inside a linear ring. On edge is considered inside.
273
+ */
274
+ const isGeoJsonPositionInLinearRing = ({ position, linearRing, }) => {
275
+ const linearRingParsed = geoJsonLinearRingSchema.safeParse(linearRing);
276
+ if (!linearRingParsed.success) {
277
+ return null;
278
+ }
279
+ let inside = false;
280
+ const [x, y] = position;
281
+ for (let i = 0, j = linearRingParsed.data.length - 1; i < linearRingParsed.data.length; j = i++) {
282
+ const point1 = linearRingParsed.data[i];
283
+ const point2 = linearRingParsed.data[j];
284
+ if (!point1 || !point2) {
285
+ continue;
286
+ }
287
+ const [xi, yi] = point1;
288
+ const [xj, yj] = point2;
289
+ const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
290
+ if (intersect) {
291
+ inside = !inside;
292
+ }
293
+ }
294
+ return inside;
295
+ };
296
+ /**
297
+ * @description Checks if a point is inside a polygon.
298
+ */
299
+ const isGeoJsonPointInPolygon = ({ point, polygon, }) => {
300
+ const polygonParsed = geoJsonPolygonSchema.safeParse(polygon);
301
+ if (!polygonParsed.success) {
302
+ return null;
303
+ }
304
+ return polygonParsed.data.coordinates.some(linearRing => isGeoJsonPositionInLinearRing({ position: point.coordinates, linearRing }));
305
+ };
306
+ /**
307
+ * Checks if polygon1 is fully contained within polygon2
308
+ */
309
+ const isFullyContainedInGeoJsonPolygon = (polygon1, polygon2) => {
310
+ const polygon1Parsed = geoJsonPolygonSchema.safeParse(polygon1);
311
+ const polygon2Parsed = geoJsonPolygonSchema.safeParse(polygon2);
312
+ // The schema checks more than a TypeScript type can represent
313
+ if (!polygon1Parsed.success || !polygon2Parsed.success) {
314
+ return null;
315
+ }
316
+ return polygon1Parsed.data.coordinates.every(linearRing => polygon2Parsed.data.coordinates.some(lr => linearRing.every(position => isGeoJsonPositionInLinearRing({ position, linearRing: lr }))));
317
+ };
318
+ /**
319
+ * @description Gets the intersection between two GeoJSON polygons. If one polygon is fully contained within the other,
320
+ * returns the contained polygon. Otherwise returns a MultiPolygon representing the intersection.
321
+ * @param polygon1 The first polygon to check intersection
322
+ * @param polygon2 The second polygon to check intersection
323
+ * @returns {(GeoJsonMultiPolygon | GeoJsonPolygon)} The intersection as either a Polygon (if one contains the other) or MultiPolygon
324
+ */
325
+ const getGeoJsonPolygonIntersection = (polygon1, polygon2) => {
326
+ const polygon1Parsed = geoJsonPolygonSchema.safeParse(polygon1);
327
+ const polygon2Parsed = geoJsonPolygonSchema.safeParse(polygon2);
328
+ if (!polygon1Parsed.success || !polygon2Parsed.success) {
329
+ return null;
330
+ }
331
+ if (isFullyContainedInGeoJsonPolygon(polygon1, polygon2)) {
332
+ return polygon1;
333
+ }
334
+ if (isFullyContainedInGeoJsonPolygon(polygon2, polygon1)) {
335
+ return polygon2;
336
+ }
337
+ const intersectionResult = polygonClipping.intersection(polygon1.coordinates, polygon2.coordinates);
338
+ if (intersectionResult.length === 1 && intersectionResult[0]) {
339
+ return {
340
+ type: "Polygon",
341
+ coordinates: intersectionResult[0],
342
+ };
343
+ }
344
+ return {
345
+ type: "MultiPolygon",
346
+ coordinates: polygonClipping.intersection(polygon1.coordinates, polygon2.coordinates),
347
+ };
348
+ };
349
+
350
+ //! These tools are used to bridge the gap with out poorly typed graphql types
351
+ // Should be ideally be avoided but are needed until we fix the graphql types
352
+ const isDoubleNestedCoords = (coords) => Array.isArray(coords) &&
353
+ Array.isArray(coords[0]) &&
354
+ Array.isArray(coords[0][0]) &&
355
+ typeof coords[0][0][0] === "number";
356
+ const isSingleCoords = (coords) => typeof coords[0] === "number";
357
+ /**
358
+ * @description Returns coordinates in consistent format
359
+ * @param inconsistentCoordinates Single point, array of points or nested array of points
360
+ * @returns {GeoJsonPosition[]} Array of standardized coordinates
361
+ */
362
+ const coordinatesToStandardFormat = (inconsistentCoordinates) => {
363
+ if (!inconsistentCoordinates) {
364
+ return [];
365
+ }
366
+ if (isSingleCoords(inconsistentCoordinates)) {
367
+ return [inconsistentCoordinates];
368
+ }
369
+ if (isDoubleNestedCoords(inconsistentCoordinates)) {
370
+ return inconsistentCoordinates[0] || [];
371
+ }
372
+ if (inconsistentCoordinates[0] && typeof inconsistentCoordinates[0][0] === "number") {
373
+ return inconsistentCoordinates;
374
+ }
375
+ return [];
376
+ };
377
+ /**
378
+ * @description Extracts a point coordinate from a GeoJSON object.
379
+ * @param geoObject A GeoJSON object.
380
+ * @returns {PointCoordinate} A point coordinate.
381
+ */
382
+ const getPointCoordinateFromGeoJsonObject = (geoObject) => {
383
+ if (!geoObject) {
384
+ return undefined;
385
+ }
386
+ else if ("geometry" in geoObject) {
387
+ return getPointCoordinateFromGeoJsonObject(geoObject.geometry);
388
+ }
389
+ else if ("coordinates" in geoObject &&
390
+ Array.isArray(geoObject.coordinates) &&
391
+ typeof geoObject.coordinates[0] === "number" &&
392
+ typeof geoObject.coordinates[1] === "number") {
393
+ const [point] = coordinatesToStandardFormat(geoObject.coordinates);
394
+ if (point) {
395
+ return { latitude: point[1], longitude: point[0] };
396
+ }
397
+ else {
398
+ throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
399
+ }
400
+ }
401
+ else {
402
+ throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
403
+ }
404
+ };
405
+ /**
406
+ * @description Extracts multiple point coordinates from a GeoJSON object.
407
+ * @param geoObject A GeoJSON object.
408
+ * @returns {PointCoordinate[]} An array of point coordinates.
409
+ * @example getMultipleCoordinatesFromGeoJsonObject({ type: "Point", coordinates: [1, 2] }) // [{ longitude: 1, latitude: 2 }]
410
+ */
411
+ const getMultipleCoordinatesFromGeoJsonObject = (geoObject) => {
412
+ if (!geoObject) {
413
+ return undefined;
414
+ }
415
+ else if ("geometry" in geoObject) {
416
+ return getMultipleCoordinatesFromGeoJsonObject(geoObject.geometry);
417
+ }
418
+ else if ("coordinates" in geoObject) {
419
+ return coordinatesToStandardFormat(geoObject.coordinates).map(([longitude, latitude]) => ({ longitude, latitude }));
420
+ }
421
+ else {
422
+ throw new Error(`Unable to extract point coordinate from ${JSON.stringify(geoObject)}`);
423
+ }
424
+ };
425
+
426
+ //* -------- Trackunit-invented schemas and types to extend the GeoJson spec -------- *//
427
+ /**
428
+ * Polygon geometry object that explicitly disallows holes.
429
+ *
430
+ * Same as geoJsonPolygonSchema but type disallows holes by
431
+ * using tuple of one single linear ring instead of an array.
432
+ */
433
+ const tuGeoJsonPolygonNoHolesSchema = zod.z.strictObject({
434
+ //The type is still "Polygon" (not PolygonNoHoles or similar) since it's always
435
+ //compliant with Polygon, just not the other way around
436
+ type: zod.z.literal("Polygon"),
437
+ //uses tuple instead of array to enforce only 1 linear ring aka the polygon itself
438
+ coordinates: zod.z.tuple([geoJsonLinearRingSchema]),
439
+ });
440
+ /**
441
+ * Point radius object.
442
+ * For when you wish to define an area by a point and a radius.
443
+ *
444
+ * radius is in meters
445
+ */
446
+ const tuGeoJsonPointRadiusSchema = zod.z.strictObject({
447
+ type: zod.z.literal("PointRadius"),
448
+ coordinates: geoJsonPositionSchema,
449
+ radius: zod.z.number().positive(), // in meters
450
+ });
451
+ /**
452
+ * A Polygon with exactly 5 points and 4 horizontal/vertical sides that form a normal rectangular box.
453
+ */
454
+ const tuGeoJsonRectangularBoxPolygonSchema = zod.z
455
+ .strictObject({
456
+ type: zod.z.literal("Polygon"),
457
+ coordinates: zod.z.array(geoJsonLinearRingSchema),
458
+ })
459
+ .superRefine((data, ctx) => {
460
+ const coordinates = data.coordinates[0];
461
+ // Validate polygon has exactly 5 points
462
+ if ((coordinates === null || coordinates === void 0 ? void 0 : coordinates.length) !== 5) {
463
+ ctx.addIssue({
464
+ code: zod.z.ZodIssueCode.custom,
465
+ message: "Polygon must have exactly 5 coordinates to form a closed box.",
466
+ });
467
+ return;
468
+ }
469
+ // Check each side is either horizontal or vertical
470
+ for (let i = 0; i < 4; i++) {
471
+ const point1 = coordinates[i];
472
+ const point2 = coordinates[i + 1];
473
+ if (point1 === undefined || point2 === undefined) {
474
+ ctx.addIssue({
475
+ code: zod.z.ZodIssueCode.custom,
476
+ message: "Each coordinate must be a defined point.",
477
+ });
478
+ return;
479
+ }
480
+ const [x1, y1] = point1;
481
+ const [x2, y2] = point2;
482
+ // Ensure each line segment is either horizontal or vertical
483
+ if (x1 !== x2 && y1 !== y2) {
484
+ ctx.addIssue({
485
+ code: zod.z.ZodIssueCode.custom,
486
+ message: "Polygon sides must be horizontal or vertical to form a box shape.",
487
+ });
488
+ return;
489
+ }
490
+ }
491
+ });
492
+
493
+ exports.EARTH_RADIUS = EARTH_RADIUS;
494
+ exports.coordinatesToStandardFormat = coordinatesToStandardFormat;
495
+ exports.geoJsonBboxSchema = geoJsonBboxSchema;
496
+ exports.geoJsonGeometrySchema = geoJsonGeometrySchema;
497
+ exports.geoJsonLineStringSchema = geoJsonLineStringSchema;
498
+ exports.geoJsonLinearRingSchema = geoJsonLinearRingSchema;
499
+ exports.geoJsonMultiLineStringSchema = geoJsonMultiLineStringSchema;
500
+ exports.geoJsonMultiPointSchema = geoJsonMultiPointSchema;
501
+ exports.geoJsonMultiPolygonSchema = geoJsonMultiPolygonSchema;
502
+ exports.geoJsonPointSchema = geoJsonPointSchema;
503
+ exports.geoJsonPolygonSchema = geoJsonPolygonSchema;
504
+ exports.geoJsonPositionSchema = geoJsonPositionSchema;
505
+ exports.getBboxFromGeoJsonPolygon = getBboxFromGeoJsonPolygon;
506
+ exports.getBoundingBoxFromGeoJsonPolygon = getBoundingBoxFromGeoJsonPolygon;
507
+ exports.getExtremeGeoJsonPointFromPolygon = getExtremeGeoJsonPointFromPolygon;
508
+ exports.getGeoJsonPolygonFromBoundingBox = getGeoJsonPolygonFromBoundingBox;
509
+ exports.getGeoJsonPolygonIntersection = getGeoJsonPolygonIntersection;
510
+ exports.getMultipleCoordinatesFromGeoJsonObject = getMultipleCoordinatesFromGeoJsonObject;
511
+ exports.getPointCoordinateFromGeoJsonObject = getPointCoordinateFromGeoJsonObject;
512
+ exports.getPointCoordinateFromGeoJsonPoint = getPointCoordinateFromGeoJsonPoint;
513
+ exports.getPolygonFromBbox = getPolygonFromBbox;
514
+ exports.getPolygonFromPointAndRadius = getPolygonFromPointAndRadius;
515
+ exports.isFullyContainedInGeoJsonPolygon = isFullyContainedInGeoJsonPolygon;
516
+ exports.isGeoJsonPointInPolygon = isGeoJsonPointInPolygon;
517
+ exports.isGeoJsonPositionInLinearRing = isGeoJsonPositionInLinearRing;
518
+ exports.tuGeoJsonPointRadiusSchema = tuGeoJsonPointRadiusSchema;
519
+ exports.tuGeoJsonPolygonNoHolesSchema = tuGeoJsonPolygonNoHolesSchema;
520
+ exports.tuGeoJsonRectangularBoxPolygonSchema = tuGeoJsonRectangularBoxPolygonSchema;
package/index.esm.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index";