{"_id":"@arijitgupta/geo-bounds","name":"@arijitgupta/geo-bounds","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@arijitgupta/geo-bounds","version":"1.0.0","description":"Calculate the smallest geographic bounding box for coordinates with decimal-degree, DMS, and antimeridian support.","type":"module","repository":{"type":"git","url":"git+https://github.com/ArijitGupta-in/geo-bounds.git"},"homepage":"https://github.com/ArijitGupta-in/geo-bounds","bugs":{"url":"https://github.com/ArijitGupta-in/geo-bounds/issues"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","test":"vitest run","check":"tsc --noEmit","prepublishOnly":"npm run check && npm test && npm run build"},"keywords":["geo","geospatial","bounds","bounding-box","coordinates","latitude","longitude","antimeridian","dateline","dms","geography"],"author":{"name":"Arijit Gupta"},"license":"MIT","devDependencies":{"markdownlint-cli2":"^0.23.2","typescript":"^7.0.2","vitest":"^4.1.11"},"gitHead":"12ff2e19b141b671ee3e52fd8abd93d454e2de71","_id":"@arijitgupta/geo-bounds@1.0.0","_nodeVersion":"24.20.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-FiJE7HoQOtqoS4xrur9ihfphm/DyhmYtBEADkcjQmSAh/tlHUTX3F5iSFRi+uexH4J2YCzAK7kxLw0aW/i9abA==","shasum":"3733fe25bfc2f37109b133e757f5e2dc6840c57b","tarball":"https://registry.npmjs.org/@arijitgupta/geo-bounds/-/geo-bounds-1.0.0.tgz","fileCount":19,"unpackedSize":25240,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIE0kIDqHhdmMDF0Pv/ISKh7oFCB5vOx4kp5PHKYO8O/sAiEAhYJcronwXKrLZcC8lkLpzJGB+rCnjTqDpyCJ+741GOQ="}]},"_npmUser":{"name":"arijitgupta","email":"arijitdesignsit@gmail.com"},"directories":{},"maintainers":[{"name":"arijitgupta","email":"arijitdesignsit@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/geo-bounds_1.0.0_1788872675706_0.3677666058174829"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-08T13:04:35.540Z","1.0.0":"2026-09-08T13:04:35.834Z","modified":"2026-09-08T13:04:36.048Z"},"maintainers":[{"name":"arijitgupta","email":"arijitdesignsit@gmail.com"}],"description":"Calculate the smallest geographic bounding box for coordinates with decimal-degree, DMS, and antimeridian support.","homepage":"https://github.com/ArijitGupta-in/geo-bounds","keywords":["geo","geospatial","bounds","bounding-box","coordinates","latitude","longitude","antimeridian","dateline","dms","geography"],"repository":{"type":"git","url":"git+https://github.com/ArijitGupta-in/geo-bounds.git"},"author":{"name":"Arijit Gupta"},"bugs":{"url":"https://github.com/ArijitGupta-in/geo-bounds/issues"},"license":"MIT","readme":"# @arijitgupta/geo-bounds\r\n\r\n[![npm version](https://img.shields.io/npm/v/@arijitgupta/geo-bounds)](https://www.npmjs.com/package/@arijitgupta/geo-bounds)\r\n[![license](https://img.shields.io/npm/l/@arijitgupta/geo-bounds)](https://opensource.org/licenses/MIT)\r\n\r\nA lightweight, dependency-free TypeScript utility for calculating the smallest geographic bounding box containing a set of coordinates.\r\n\r\nAccepts coordinates in **decimal degrees** or **Degrees, Minutes, Seconds (DMS)** format. Longitude is treated as a circular value, so bounds can cross the antimeridian.\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @arijitgupta/geo-bounds\r\n```\r\n\r\n## Usage\r\n\r\n### Decimal degrees\r\n\r\n```ts\r\nimport {\r\n    getBounds,\r\n    type Coordinate,\r\n} from \"@arijitgupta/geo-bounds\";\r\n\r\nconst coordinates: Coordinate[] = [\r\n    { latitude: 22.5726, longitude: 88.3639 },\r\n    { latitude: 22.595, longitude: 88.4 },\r\n    { latitude: 22.55, longitude: 88.34 },\r\n];\r\n\r\nconst bounds = getBounds(coordinates);\r\n// { north: 22.595, south: 22.55, east: 88.4, west: 88.34 }\r\n```\r\n\r\n### Antimeridian-crossing bounds\r\n\r\nWhen the smallest box crosses the antimeridian, `west` is greater than `east`.\r\n\r\n```ts\r\nimport { getBounds } from \"@arijitgupta/geo-bounds\";\r\n\r\nconst bounds = getBounds([\r\n    { latitude: 10, longitude: 179 },\r\n    { latitude: 20, longitude: -179 },\r\n]);\r\n\r\n// { north: 20, south: 10, east: -179, west: 179 }\r\n```\r\n\r\n### DMS coordinates\r\n\r\n```ts\r\nimport {\r\n    getBounds,\r\n    type DMSCoordinate,\r\n} from \"@arijitgupta/geo-bounds\";\r\n\r\nconst coordinates: DMSCoordinate[] = [\r\n    {\r\n        latitude:  { degrees: 22, minutes: 34, seconds: 21.36, direction: \"N\" },\r\n        longitude: { degrees: 88, minutes: 21, seconds: 50.04, direction: \"E\" },\r\n    },\r\n];\r\n\r\nconst bounds = getBounds(coordinates);\r\n// { north: 22.5726, south: 22.5726, east: 88.3639, west: 88.3639 }\r\n```\r\n\r\nDecimal and DMS coordinates can be mixed in the same array.\r\n\r\n### Converting DMS to decimal degrees\r\n\r\n```ts\r\nimport {\r\n    dmsToDecimal,\r\n    type DMSCoordinate,\r\n} from \"@arijitgupta/geo-bounds\";\r\n\r\nconst dms: DMSCoordinate = {\r\n    latitude:  { degrees: 22, minutes: 34, seconds: 21.36, direction: \"N\" },\r\n    longitude: { degrees: 88, minutes: 21, seconds: 50.04, direction: \"E\" },\r\n};\r\n\r\nconst decimal = dmsToDecimal(dms);\r\n// { latitude: 22.5726, longitude: 88.3639 }\r\n```\r\n\r\n## API\r\n\r\n### `getBounds(coordinates)`\r\n\r\nReturns the smallest geographic bounding box containing all supplied coordinates.\r\n\r\n| Parameter | Type | Description |\r\n| --- | --- | --- |\r\n| `coordinates` | `(Coordinate \\| DMSCoordinate)[]` | One or more geographic coordinates |\r\n\r\n**Returns:** `Bounds` - the northernmost, southernmost, easternmost, and westernmost limits.\r\n\r\n**Throws:** `Error` if the array is empty.\r\n\r\n**Throws:** `RangeError` if a decimal coordinate or DMS component is invalid.\r\n\r\nThe longitude calculation treats `-180` and `180` as the same meridian. For a box that crosses the antimeridian, `west` is greater than `east`.\r\n\r\n### `dmsToDecimal(dms)`\r\n\r\nConverts a `DMSCoordinate` to a decimal-degree `Coordinate`.\r\n\r\n**Throws:** `RangeError` if any DMS component is out of range.\r\n\r\n### `validateCoordinate(coordinate)`\r\n\r\nValidates a decimal-degree `Coordinate`.\r\n\r\n**Throws:** `RangeError` if latitude is outside `[-90, 90]`, longitude is outside `[-180, 180]`, or either value is not finite.\r\n\r\n### `Coordinate`\r\n\r\n```ts\r\ninterface Coordinate {\r\n    latitude: number;   // -90 to 90\r\n    longitude: number;  // -180 to 180\r\n}\r\n```\r\n\r\n### `DMSCoordinate`\r\n\r\n```ts\r\ninterface DMSCoordinate {\r\n    latitude:  LatitudeDMS;\r\n    longitude: LongitudeDMS;\r\n}\r\n\r\ninterface LatitudeDMS {\r\n    degrees:   number;             // 0-90\r\n    minutes:   number;             // 0-59\r\n    seconds:   number;             // 0-<60\r\n    direction: \"N\" | \"S\";\r\n}\r\n\r\ninterface LongitudeDMS {\r\n    degrees:   number;             // 0-180\r\n    minutes:   number;             // 0-59\r\n    seconds:   number;             // 0-<60\r\n    direction: \"E\" | \"W\";\r\n}\r\n```\r\n\r\n**Validation rules:**\r\n\r\n- `minutes` must be in `[0, 60)`.\r\n- `seconds` must be in `[0, 60)`.\r\n- `latitude.degrees` must be in `[0, 90]`; the combined value must not exceed 90 degrees.\r\n- `longitude.degrees` must be in `[0, 180]`; the combined value must not exceed 180 degrees.\r\n\r\n### `Bounds`\r\n\r\n```ts\r\ntype Bounds = {\r\n    north: number;\r\n    south: number;\r\n    east: number;\r\n    west: number;\r\n};\r\n```\r\n\r\n## Behavior\r\n\r\n- Uses the minimum and maximum latitude values for `south` and `north`.\r\n- Finds the largest empty gap between longitudes and returns everything outside that gap as the smallest longitude interval.\r\n- Supports bounds that cross the antimeridian.\r\n- Uses a deterministic non-wrapping result when multiple longitude intervals are equally small.\r\n- Has no runtime dependencies.\r\n\r\n## Development\r\n\r\n```bash\r\nnpm install       # install dev dependencies\r\nnpm test          # run tests with Vitest\r\nnpm run check     # type-check without emitting output\r\nnpm run build     # compile TypeScript to dist/\r\n```\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md","_rev":"1-fcc89cb03730717eb5ca898f34242cbb"}