@accelint/geo 0.6.0 → 0.7.0

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.
Files changed (93) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +98 -1
  3. package/catalog-info.yaml +1 -1
  4. package/dist/cartesian.js +1 -1
  5. package/dist/coordinates/coordinate.d.ts +1 -1
  6. package/dist/coordinates/coordinate.js +1 -1
  7. package/dist/coordinates/latlon/decimal-degrees/formatter.d.ts +36 -3
  8. package/dist/coordinates/latlon/decimal-degrees/formatter.js +34 -5
  9. package/dist/coordinates/latlon/decimal-degrees/formatter.js.map +1 -1
  10. package/dist/coordinates/latlon/decimal-degrees/parser.d.ts +1 -1
  11. package/dist/coordinates/latlon/decimal-degrees/parser.js +1 -1
  12. package/dist/coordinates/latlon/decimal-degrees/system.d.ts +1 -1
  13. package/dist/coordinates/latlon/decimal-degrees/system.js +6 -4
  14. package/dist/coordinates/latlon/decimal-degrees/system.js.map +1 -1
  15. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.d.ts +43 -3
  16. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js +61 -6
  17. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js.map +1 -1
  18. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.d.ts +1 -1
  19. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js +1 -1
  20. package/dist/coordinates/latlon/degrees-decimal-minutes/system.d.ts +1 -1
  21. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js +8 -7
  22. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js.map +1 -1
  23. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.d.ts +46 -3
  24. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js +67 -8
  25. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js.map +1 -1
  26. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.d.ts +1 -1
  27. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js +1 -1
  28. package/dist/coordinates/latlon/degrees-minutes-seconds/system.d.ts +1 -1
  29. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js +8 -7
  30. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js.map +1 -1
  31. package/dist/coordinates/latlon/internal/coordinate-system.d.ts +1 -1
  32. package/dist/coordinates/latlon/internal/coordinate-system.js +1 -1
  33. package/dist/coordinates/latlon/internal/create-cache.d.ts +1 -1
  34. package/dist/coordinates/latlon/internal/create-cache.js +1 -1
  35. package/dist/coordinates/latlon/internal/exhaustive-errors.js +1 -1
  36. package/dist/coordinates/latlon/internal/format.d.ts +50 -5
  37. package/dist/coordinates/latlon/internal/format.js +40 -10
  38. package/dist/coordinates/latlon/internal/format.js.map +1 -1
  39. package/dist/coordinates/latlon/internal/in-range.js +1 -1
  40. package/dist/coordinates/latlon/internal/index.d.ts +4 -3
  41. package/dist/coordinates/latlon/internal/index.js +4 -3
  42. package/dist/coordinates/latlon/internal/index.js.map +1 -1
  43. package/dist/coordinates/latlon/internal/lexer.js +3 -2
  44. package/dist/coordinates/latlon/internal/lexer.js.map +1 -1
  45. package/dist/coordinates/latlon/internal/normalize.js +1 -1
  46. package/dist/coordinates/latlon/internal/ordinal.d.ts +39 -9
  47. package/dist/coordinates/latlon/internal/ordinal.js +32 -13
  48. package/dist/coordinates/latlon/internal/ordinal.js.map +1 -1
  49. package/dist/coordinates/latlon/internal/parse-format.d.ts +1 -1
  50. package/dist/coordinates/latlon/internal/parse-format.js +1 -1
  51. package/dist/coordinates/latlon/internal/parse.d.ts +1 -1
  52. package/dist/coordinates/latlon/internal/parse.js +1 -1
  53. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.d.ts +1 -1
  54. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js +1 -1
  55. package/dist/coordinates/latlon/internal/pipes/check-numbers.d.ts +1 -1
  56. package/dist/coordinates/latlon/internal/pipes/check-numbers.js +1 -1
  57. package/dist/coordinates/latlon/internal/pipes/fix-bearings.d.ts +1 -1
  58. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js +1 -1
  59. package/dist/coordinates/latlon/internal/pipes/fix-dividers.d.ts +1 -1
  60. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js +1 -1
  61. package/dist/coordinates/latlon/internal/pipes/genome.d.ts +1 -1
  62. package/dist/coordinates/latlon/internal/pipes/genome.js +1 -1
  63. package/dist/coordinates/latlon/internal/pipes/index.d.ts +1 -1
  64. package/dist/coordinates/latlon/internal/pipes/index.js +1 -1
  65. package/dist/coordinates/latlon/internal/pipes/simpler.d.ts +1 -1
  66. package/dist/coordinates/latlon/internal/pipes/simpler.js +1 -1
  67. package/dist/coordinates/latlon/internal/plain-decimal.d.ts +35 -0
  68. package/dist/coordinates/latlon/internal/plain-decimal.js +59 -0
  69. package/dist/coordinates/latlon/internal/plain-decimal.js.map +1 -0
  70. package/dist/coordinates/latlon/internal/validate.d.ts +28 -1
  71. package/dist/coordinates/latlon/internal/validate.js +31 -2
  72. package/dist/coordinates/latlon/internal/validate.js.map +1 -1
  73. package/dist/coordinates/latlon/internal/violation.js +1 -1
  74. package/dist/coordinates/mgrs/parser.d.ts +1 -1
  75. package/dist/coordinates/mgrs/parser.js +1 -1
  76. package/dist/coordinates/mgrs/parts.d.ts +86 -0
  77. package/dist/coordinates/mgrs/parts.js +94 -0
  78. package/dist/coordinates/mgrs/parts.js.map +1 -0
  79. package/dist/coordinates/mgrs/system.d.ts +1 -1
  80. package/dist/coordinates/mgrs/system.js +5 -3
  81. package/dist/coordinates/mgrs/system.js.map +1 -1
  82. package/dist/coordinates/utm/parser.d.ts +1 -1
  83. package/dist/coordinates/utm/parser.js +1 -1
  84. package/dist/coordinates/utm/parts.d.ts +134 -0
  85. package/dist/coordinates/utm/parts.js +142 -0
  86. package/dist/coordinates/utm/parts.js.map +1 -0
  87. package/dist/coordinates/utm/system.d.ts +1 -1
  88. package/dist/coordinates/utm/system.js +5 -4
  89. package/dist/coordinates/utm/system.js.map +1 -1
  90. package/dist/index.d.ts +11 -8
  91. package/dist/index.js +11 -8
  92. package/dist/patterning.js +1 -1
  93. package/package.json +4 -1
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,7 +11,9 @@
11
11
  */
12
12
 
13
13
 
14
- import { BEARINGS, SYMBOLS, SYMBOL_PATTERNS } from "../internal/index.js";
14
+ import { toPlainDecimalString } from "../internal/plain-decimal.js";
15
+ import { SYMBOL_PATTERNS } from "../internal/index.js";
16
+ import { formatCoordinateSystem } from "../internal/format.js";
15
17
  import { parseDegreesDecimalMinutes } from "./parser.js";
16
18
 
17
19
  //#region src/coordinates/latlon/degrees-decimal-minutes/system.ts
@@ -53,12 +55,11 @@ const systemDegreesDecimalMinutes = {
53
55
  const [degrees, minutes, bear] = arg;
54
56
  return Number.parseFloat(((Number.parseFloat(degrees) + Number.parseFloat(minutes) / 60) * (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)).toFixed(9));
55
57
  },
56
- toFormat(format, [left, right]) {
57
- return [left, right].map((num, index) => {
58
- const abs = Math.abs(num);
58
+ toFormat(format, coordinates) {
59
+ return formatCoordinateSystem(format, coordinates, (abs) => {
59
60
  const deg = Math.floor(abs);
60
- return `${deg} ${Number.parseFloat(((abs - deg) * 60).toFixed(10))} ${BEARINGS[format][index][+(num < 0)]}`;
61
- }).join(` ${SYMBOLS.DIVIDER} `);
61
+ return `${deg} ${toPlainDecimalString(Number.parseFloat(((abs - deg) * 60).toFixed(10)))}`;
62
+ });
62
63
  }
63
64
  };
64
65
 
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","names":["systemDegreesDecimalMinutes: CoordinateSystem"],"sources":["../../../../src/coordinates/latlon/degrees-decimal-minutes/system.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n BEARINGS,\n type Compass,\n type Format,\n SYMBOL_PATTERNS,\n SYMBOLS,\n} from '../internal';\nimport { parseDegreesDecimalMinutes } from './parser';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\n/**\n * Degrees Decimal Minutes coordinate system implementation.\n *\n * Provides parsing, conversion, and formatting for coordinates in degrees decimal minutes notation.\n * Coordinates are expressed as integer degrees and decimal minutes (e.g., 37° 46.4940' N).\n *\n * @property name - Human-readable name of the coordinate system.\n * @property parse - Parses degrees decimal minutes coordinate strings.\n * @property toFloat - Converts parsed coordinate components to floating point numbers.\n * @property toFormat - Formats numeric coordinates back to degrees decimal minutes string.\n *\n * @example\n * ```typescript\n * // Parse a coordinate string\n * const [coords, errors] = systemDegreesDecimalMinutes.parse('37° 46.4940' N / 122° 25.1640' W', 'LATLON');\n * ```\n *\n * @example\n * ```typescript\n * // Convert to float\n * const lat = systemDegreesDecimalMinutes.toFloat(['37', '46.4940', 'N']);\n * // 37.7749\n * ```\n *\n * @example\n * ```typescript\n * // Format to string\n * const formatted = systemDegreesDecimalMinutes.toFormat('LATLON', [37.7749, -122.4194]);\n * // '37 46.494 N / 122 25.164 W'\n * ```\n */\nexport const systemDegreesDecimalMinutes: CoordinateSystem = {\n name: 'Degrees Decimal Minutes',\n\n parse: parseDegreesDecimalMinutes,\n\n toFloat(arg) {\n const [degrees, minutes, bear] = arg as [string, string, Compass];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) + Number.parseFloat(minutes) / 60) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, [left, right]: [number, number]) {\n return [left, right]\n .map((num, index) => {\n const abs = Math.abs(num);\n const deg = Math.floor(abs);\n const min = Number.parseFloat(((abs - deg) * 60).toFixed(10));\n\n return `${deg} ${min} ${BEARINGS[format][index as 0 | 1][+(num < 0)]}`;\n })\n .join(` ${SYMBOLS.DIVIDER} `);\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAaA,8BAAgD;CAC3D,MAAM;CAEN,OAAO;CAEP,QAAQ,KAAK;EACX,MAAM,CAAC,SAAS,SAAS,QAAQ;AAEjC,SAAO,OAAO,aAET,OAAO,WAAW,QAAQ,GAAG,OAAO,WAAW,QAAQ,GAAG,OAC1D,gBAAgB,kBAAkB,KAAK,KAAK,GAAG,KAAK,IACrD,QAAQ,EAAE,CACb;;CAGH,SAAS,QAAgB,CAAC,MAAM,QAA0B;AACxD,SAAO,CAAC,MAAM,MAAM,CACjB,KAAK,KAAK,UAAU;GACnB,MAAM,MAAM,KAAK,IAAI,IAAI;GACzB,MAAM,MAAM,KAAK,MAAM,IAAI;AAG3B,UAAO,GAAG,IAAI,GAFF,OAAO,aAAa,MAAM,OAAO,IAAI,QAAQ,GAAG,CAAC,CAExC,GAAG,SAAS,QAAQ,OAAgB,EAAE,MAAM;IACjE,CACD,KAAK,IAAI,QAAQ,QAAQ,GAAG;;CAElC"}
1
+ {"version":3,"file":"system.js","names":["systemDegreesDecimalMinutes: CoordinateSystem"],"sources":["../../../../src/coordinates/latlon/degrees-decimal-minutes/system.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Compass, type Format, SYMBOL_PATTERNS } from '../internal';\nimport { formatCoordinateSystem } from '../internal/format';\nimport { toPlainDecimalString } from '../internal/plain-decimal';\nimport { parseDegreesDecimalMinutes } from './parser';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\n/**\n * Degrees Decimal Minutes coordinate system implementation.\n *\n * Provides parsing, conversion, and formatting for coordinates in degrees decimal minutes notation.\n * Coordinates are expressed as integer degrees and decimal minutes (e.g., 37° 46.4940' N).\n *\n * @property name - Human-readable name of the coordinate system.\n * @property parse - Parses degrees decimal minutes coordinate strings.\n * @property toFloat - Converts parsed coordinate components to floating point numbers.\n * @property toFormat - Formats numeric coordinates back to degrees decimal minutes string.\n *\n * @example\n * ```typescript\n * // Parse a coordinate string\n * const [coords, errors] = systemDegreesDecimalMinutes.parse('37° 46.4940' N / 122° 25.1640' W', 'LATLON');\n * ```\n *\n * @example\n * ```typescript\n * // Convert to float\n * const lat = systemDegreesDecimalMinutes.toFloat(['37', '46.4940', 'N']);\n * // 37.7749\n * ```\n *\n * @example\n * ```typescript\n * // Format to string\n * const formatted = systemDegreesDecimalMinutes.toFormat('LATLON', [37.7749, -122.4194]);\n * // '37 46.494 N / 122 25.164 W'\n * ```\n */\nexport const systemDegreesDecimalMinutes: CoordinateSystem = {\n name: 'Degrees Decimal Minutes',\n\n parse: parseDegreesDecimalMinutes,\n\n toFloat(arg) {\n const [degrees, minutes, bear] = arg as [string, string, Compass];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) + Number.parseFloat(minutes) / 60) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, coordinates: [number, number]) {\n return formatCoordinateSystem(format, coordinates, (abs) => {\n const deg = Math.floor(abs);\n const min = Number.parseFloat(((abs - deg) * 60).toFixed(10));\n\n return `${deg} ${toPlainDecimalString(min)}`;\n });\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,MAAaA,8BAAgD;CAC3D,MAAM;CAEN,OAAO;CAEP,QAAQ,KAAK;EACX,MAAM,CAAC,SAAS,SAAS,QAAQ;AAEjC,SAAO,OAAO,aAET,OAAO,WAAW,QAAQ,GAAG,OAAO,WAAW,QAAQ,GAAG,OAC1D,gBAAgB,kBAAkB,KAAK,KAAK,GAAG,KAAK,IACrD,QAAQ,EAAE,CACb;;CAGH,SAAS,QAAgB,aAA+B;AACtD,SAAO,uBAAuB,QAAQ,cAAc,QAAQ;GAC1D,MAAM,MAAM,KAAK,MAAM,IAAI;AAG3B,UAAO,GAAG,IAAI,GAAG,qBAFL,OAAO,aAAa,MAAM,OAAO,IAAI,QAAQ,GAAG,CAAC,CAEnB;IAC1C;;CAEL"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,9 +11,52 @@
11
11
  */
12
12
 
13
13
  import { FormatOptions } from "../internal/format.js";
14
+ import { Axis, Hemisphere } from "../internal/ordinal.js";
14
15
 
15
16
  //#region src/coordinates/latlon/degrees-minutes-seconds/formatter.d.ts
16
-
17
+ /** Default number of decimal places for degrees-minutes-seconds formatting. */
18
+ declare const DMS_PRECISION = 2;
19
+ /**
20
+ * Structured degrees-minutes-seconds parts for a single signed coordinate value.
21
+ *
22
+ * `degrees`, `minutes`, and `seconds` are non-negative; carry keeps `seconds`
23
+ * and `minutes` below `60`. The signed value is recoverable from the axis and
24
+ * `hemisphere`.
25
+ */
26
+ type DmsParts = {
27
+ degrees: number;
28
+ minutes: number;
29
+ seconds: number;
30
+ hemisphere: Hemisphere;
31
+ };
32
+ /**
33
+ * Converts a single signed coordinate value into degrees-minutes-seconds parts.
34
+ *
35
+ * Applies the seconds/minutes carry (`60″ → +1′`, `60′ → +1°`) after rounding
36
+ * so `seconds` and `minutes` never reach `60`, then attaches the hemisphere
37
+ * letter for the axis.
38
+ *
39
+ * This is the display path: it rounds to `precision` and carries. The
40
+ * lossless round-trip representation returned by `createCoordinate(...).dms()`
41
+ * lives separately in `degrees-minutes-seconds/system.ts` (`toFormat`, via the
42
+ * shared `formatCoordinateSystem`), which keeps full precision and applies no
43
+ * carry so a value survives format → parse unchanged. The two are
44
+ * intentionally not shared — do not route one through the other.
45
+ *
46
+ * @param value - The signed coordinate value.
47
+ * @param axis - Whether the value is a latitude (`'lat'`) or longitude (`'lon'`).
48
+ * @param precision - Decimal places for the seconds (default `2`).
49
+ * @returns The `{ degrees, minutes, seconds, hemisphere }` parts object.
50
+ *
51
+ * @remarks pure function
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * toDmsParts(-77.0369, 'lon');
56
+ * // { degrees: 77, minutes: 2, seconds: 12.84, hemisphere: 'W' }
57
+ * ```
58
+ */
59
+ declare const toDmsParts: (value: number, axis: Axis, precision?: number) => DmsParts;
17
60
  /**
18
61
  * Formats latitude/longitude coordinates in degrees minutes seconds notation.
19
62
  *
@@ -35,5 +78,5 @@ import { FormatOptions } from "../internal/format.js";
35
78
  */
36
79
  declare const formatDegreesMinutesSeconds: (coordinates: [number, number], config?: FormatOptions) => string;
37
80
  //#endregion
38
- export { formatDegreesMinutesSeconds };
81
+ export { DMS_PRECISION, DmsParts, formatDegreesMinutesSeconds, toDmsParts };
39
82
  //# sourceMappingURL=formatter.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,13 +11,74 @@
11
11
  */
12
12
 
13
13
 
14
+ import { getHemisphere } from "../internal/ordinal.js";
14
15
  import { createFormatter } from "../internal/format.js";
15
16
 
16
17
  //#region src/coordinates/latlon/degrees-minutes-seconds/formatter.ts
18
+ /** Default number of decimal places for degrees-minutes-seconds formatting. */
19
+ const DMS_PRECISION = 2;
20
+ /**
21
+ * Splits a non-negative magnitude into whole degrees, whole minutes, and
22
+ * decimal seconds, rounding the seconds to `precision` and carrying
23
+ * `60″ → +1′ → +1°` so the output stays a valid coordinate. Shared core of
24
+ * {@link toDmsParts} and the display string formatter.
25
+ *
26
+ * @param magnitude - Non-negative coordinate magnitude in degrees.
27
+ * @param precision - Decimal places for the seconds.
28
+ * @returns The `{ degrees, minutes, seconds }` triple.
29
+ *
30
+ * @remarks pure function
31
+ */
32
+ const toDmsMagnitude = (magnitude, precision) => {
33
+ let degrees = Math.floor(magnitude);
34
+ const minutesFull = (magnitude - degrees) * 60;
35
+ let minutes = Math.floor(minutesFull);
36
+ let seconds = Number(((minutesFull - minutes) * 60).toFixed(precision));
37
+ minutes += Math.floor(seconds / 60);
38
+ seconds %= 60;
39
+ degrees += Math.floor(minutes / 60);
40
+ minutes %= 60;
41
+ return {
42
+ degrees,
43
+ minutes,
44
+ seconds
45
+ };
46
+ };
47
+ /**
48
+ * Converts a single signed coordinate value into degrees-minutes-seconds parts.
49
+ *
50
+ * Applies the seconds/minutes carry (`60″ → +1′`, `60′ → +1°`) after rounding
51
+ * so `seconds` and `minutes` never reach `60`, then attaches the hemisphere
52
+ * letter for the axis.
53
+ *
54
+ * This is the display path: it rounds to `precision` and carries. The
55
+ * lossless round-trip representation returned by `createCoordinate(...).dms()`
56
+ * lives separately in `degrees-minutes-seconds/system.ts` (`toFormat`, via the
57
+ * shared `formatCoordinateSystem`), which keeps full precision and applies no
58
+ * carry so a value survives format → parse unchanged. The two are
59
+ * intentionally not shared — do not route one through the other.
60
+ *
61
+ * @param value - The signed coordinate value.
62
+ * @param axis - Whether the value is a latitude (`'lat'`) or longitude (`'lon'`).
63
+ * @param precision - Decimal places for the seconds (default `2`).
64
+ * @returns The `{ degrees, minutes, seconds, hemisphere }` parts object.
65
+ *
66
+ * @remarks pure function
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * toDmsParts(-77.0369, 'lon');
71
+ * // { degrees: 77, minutes: 2, seconds: 12.84, hemisphere: 'W' }
72
+ * ```
73
+ */
74
+ const toDmsParts = (value, axis, precision = DMS_PRECISION) => ({
75
+ ...toDmsMagnitude(Math.abs(value), precision),
76
+ hemisphere: getHemisphere(value, axis)
77
+ });
17
78
  /**
18
79
  * Converts a coordinate value to degrees minutes seconds format.
19
80
  *
20
- * @param num - The coordinate value to format.
81
+ * @param value - The coordinate value to format.
21
82
  * @returns Formatted coordinate string with degrees, minutes, and seconds (e.g., "45° 30' 15.23″").
22
83
  *
23
84
  * @example
@@ -32,11 +93,9 @@ import { createFormatter } from "../internal/format.js";
32
93
  * // '122° 25' 9.84″'
33
94
  * ```
34
95
  */
35
- const toDegreesMinutesSeconds = (num) => {
36
- const degrees = Math.floor(Math.abs(num));
37
- const minutesFull = (Math.abs(num) - degrees) * 60;
38
- const minutes = Math.floor(minutesFull);
39
- return `${degrees}° ${minutes}' ${((minutesFull - minutes) * 60).toFixed(2)}″`;
96
+ const toDegreesMinutesSeconds = (value) => {
97
+ const { degrees, minutes, seconds } = toDmsMagnitude(Math.abs(value), DMS_PRECISION);
98
+ return `${degrees}° ${minutes}' ${seconds.toFixed(DMS_PRECISION)}″`;
40
99
  };
41
100
  /**
42
101
  * Formats latitude/longitude coordinates in degrees minutes seconds notation.
@@ -60,5 +119,5 @@ const toDegreesMinutesSeconds = (num) => {
60
119
  const formatDegreesMinutesSeconds = createFormatter(toDegreesMinutesSeconds);
61
120
 
62
121
  //#endregion
63
- export { formatDegreesMinutesSeconds };
122
+ export { DMS_PRECISION, formatDegreesMinutesSeconds, toDmsParts };
64
123
  //# sourceMappingURL=formatter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatter.js","names":[],"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/formatter.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { createFormatter } from '../internal/format';\n\n/**\n * Converts a coordinate value to degrees minutes seconds format.\n *\n * @param num - The coordinate value to format.\n * @returns Formatted coordinate string with degrees, minutes, and seconds (e.g., \"45° 30' 15.23″\").\n *\n * @example\n * ```typescript\n * toDegreesMinutesSeconds(45.5042);\n * // '45° 30' 15.12″'\n * ```\n *\n * @example\n * ```typescript\n * toDegreesMinutesSeconds(-122.4194);\n * // '122° 25' 9.84″'\n * ```\n */\nconst toDegreesMinutesSeconds = (num: number): string => {\n const degrees = Math.floor(Math.abs(num));\n const minutesFull = (Math.abs(num) - degrees) * 60;\n const minutes = Math.floor(minutesFull);\n const seconds = ((minutesFull - minutes) * 60).toFixed(2);\n\n return `${degrees}° ${minutes}' ${seconds}″`;\n};\n\n/**\n * Formats latitude/longitude coordinates in degrees minutes seconds notation.\n *\n * @param coordinates - Tuple of [latitude, longitude] values.\n * @param config - Optional formatting configuration.\n * @returns Formatted coordinate string in degrees minutes seconds format.\n *\n * @example\n * ```typescript\n * formatDegreesMinutesSeconds([37.7749, -122.4194]);\n * // '37° 46' 29.64″ N, 122° 25' 9.84″ W'\n * ```\n *\n * @example\n * ```typescript\n * formatDegreesMinutesSeconds([37.7749, -122.4194], { separator: ' / ' });\n * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'\n * ```\n */\nexport const formatDegreesMinutesSeconds = createFormatter(\n toDegreesMinutesSeconds,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAM,2BAA2B,QAAwB;CACvD,MAAM,UAAU,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC;CACzC,MAAM,eAAe,KAAK,IAAI,IAAI,GAAG,WAAW;CAChD,MAAM,UAAU,KAAK,MAAM,YAAY;AAGvC,QAAO,GAAG,QAAQ,IAAI,QAAQ,MAFZ,cAAc,WAAW,IAAI,QAAQ,EAAE,CAEf;;;;;;;;;;;;;;;;;;;;;AAsB5C,MAAa,8BAA8B,gBACzC,wBACD"}
1
+ {"version":3,"file":"formatter.js","names":[],"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/formatter.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { createFormatter } from '../internal/format';\nimport { type Axis, getHemisphere, type Hemisphere } from '../internal/ordinal';\n\n/** Default number of decimal places for degrees-minutes-seconds formatting. */\nexport const DMS_PRECISION = 2;\n\n/**\n * Structured degrees-minutes-seconds parts for a single signed coordinate value.\n *\n * `degrees`, `minutes`, and `seconds` are non-negative; carry keeps `seconds`\n * and `minutes` below `60`. The signed value is recoverable from the axis and\n * `hemisphere`.\n */\nexport type DmsParts = {\n degrees: number;\n minutes: number;\n seconds: number;\n hemisphere: Hemisphere;\n};\n\n/**\n * Splits a non-negative magnitude into whole degrees, whole minutes, and\n * decimal seconds, rounding the seconds to `precision` and carrying\n * `60″ → +1′ → +1°` so the output stays a valid coordinate. Shared core of\n * {@link toDmsParts} and the display string formatter.\n *\n * @param magnitude - Non-negative coordinate magnitude in degrees.\n * @param precision - Decimal places for the seconds.\n * @returns The `{ degrees, minutes, seconds }` triple.\n *\n * @remarks pure function\n */\nconst toDmsMagnitude = (\n magnitude: number,\n precision: number,\n): Pick<DmsParts, 'degrees' | 'minutes' | 'seconds'> => {\n let degrees = Math.floor(magnitude);\n const minutesFull = (magnitude - degrees) * 60;\n let minutes = Math.floor(minutesFull);\n let seconds = Number(((minutesFull - minutes) * 60).toFixed(precision));\n\n // Rounding can produce 60 seconds (e.g. 40.9999999 -> 40° 59' 60.00″);\n // carry into minutes (and degrees) so the output stays a valid coordinate.\n minutes += Math.floor(seconds / 60);\n seconds %= 60;\n degrees += Math.floor(minutes / 60);\n minutes %= 60;\n\n return { degrees, minutes, seconds };\n};\n\n/**\n * Converts a single signed coordinate value into degrees-minutes-seconds parts.\n *\n * Applies the seconds/minutes carry (`60″ → +1′`, `60′ → +1°`) after rounding\n * so `seconds` and `minutes` never reach `60`, then attaches the hemisphere\n * letter for the axis.\n *\n * This is the display path: it rounds to `precision` and carries. The\n * lossless round-trip representation returned by `createCoordinate(...).dms()`\n * lives separately in `degrees-minutes-seconds/system.ts` (`toFormat`, via the\n * shared `formatCoordinateSystem`), which keeps full precision and applies no\n * carry so a value survives format → parse unchanged. The two are\n * intentionally not shared — do not route one through the other.\n *\n * @param value - The signed coordinate value.\n * @param axis - Whether the value is a latitude (`'lat'`) or longitude (`'lon'`).\n * @param precision - Decimal places for the seconds (default `2`).\n * @returns The `{ degrees, minutes, seconds, hemisphere }` parts object.\n *\n * @remarks pure function\n *\n * @example\n * ```typescript\n * toDmsParts(-77.0369, 'lon');\n * // { degrees: 77, minutes: 2, seconds: 12.84, hemisphere: 'W' }\n * ```\n */\nexport const toDmsParts = (\n value: number,\n axis: Axis,\n precision: number = DMS_PRECISION,\n): DmsParts => ({\n ...toDmsMagnitude(Math.abs(value), precision),\n hemisphere: getHemisphere(value, axis),\n});\n\n/**\n * Converts a coordinate value to degrees minutes seconds format.\n *\n * @param value - The coordinate value to format.\n * @returns Formatted coordinate string with degrees, minutes, and seconds (e.g., \"45° 30' 15.23″\").\n *\n * @example\n * ```typescript\n * toDegreesMinutesSeconds(45.5042);\n * // '45° 30' 15.12″'\n * ```\n *\n * @example\n * ```typescript\n * toDegreesMinutesSeconds(-122.4194);\n * // '122° 25' 9.84″'\n * ```\n */\nconst toDegreesMinutesSeconds = (value: number): string => {\n const { degrees, minutes, seconds } = toDmsMagnitude(\n Math.abs(value),\n DMS_PRECISION,\n );\n\n return `${degrees}° ${minutes}' ${seconds.toFixed(DMS_PRECISION)}″`;\n};\n\n/**\n * Formats latitude/longitude coordinates in degrees minutes seconds notation.\n *\n * @param coordinates - Tuple of [latitude, longitude] values.\n * @param config - Optional formatting configuration.\n * @returns Formatted coordinate string in degrees minutes seconds format.\n *\n * @example\n * ```typescript\n * formatDegreesMinutesSeconds([37.7749, -122.4194]);\n * // '37° 46' 29.64″ N, 122° 25' 9.84″ W'\n * ```\n *\n * @example\n * ```typescript\n * formatDegreesMinutesSeconds([37.7749, -122.4194], { separator: ' / ' });\n * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'\n * ```\n */\nexport const formatDegreesMinutesSeconds = createFormatter(\n toDegreesMinutesSeconds,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgBA,MAAa,gBAAgB;;;;;;;;;;;;;AA4B7B,MAAM,kBACJ,WACA,cACsD;CACtD,IAAI,UAAU,KAAK,MAAM,UAAU;CACnC,MAAM,eAAe,YAAY,WAAW;CAC5C,IAAI,UAAU,KAAK,MAAM,YAAY;CACrC,IAAI,UAAU,SAAS,cAAc,WAAW,IAAI,QAAQ,UAAU,CAAC;AAIvE,YAAW,KAAK,MAAM,UAAU,GAAG;AACnC,YAAW;AACX,YAAW,KAAK,MAAM,UAAU,GAAG;AACnC,YAAW;AAEX,QAAO;EAAE;EAAS;EAAS;EAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BtC,MAAa,cACX,OACA,MACA,YAAoB,mBACN;CACd,GAAG,eAAe,KAAK,IAAI,MAAM,EAAE,UAAU;CAC7C,YAAY,cAAc,OAAO,KAAK;CACvC;;;;;;;;;;;;;;;;;;;AAoBD,MAAM,2BAA2B,UAA0B;CACzD,MAAM,EAAE,SAAS,SAAS,YAAY,eACpC,KAAK,IAAI,MAAM,EACf,cACD;AAED,QAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,QAAQ,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBnE,MAAa,8BAA8B,gBACzC,wBACD"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,7 +11,9 @@
11
11
  */
12
12
 
13
13
 
14
- import { BEARINGS, SYMBOLS, SYMBOL_PATTERNS } from "../internal/index.js";
14
+ import { toPlainDecimalString } from "../internal/plain-decimal.js";
15
+ import { SYMBOL_PATTERNS } from "../internal/index.js";
16
+ import { formatCoordinateSystem } from "../internal/format.js";
15
17
  import { parseDegreesMinutesSeconds } from "./parser.js";
16
18
 
17
19
  //#region src/coordinates/latlon/degrees-minutes-seconds/system.ts
@@ -53,14 +55,13 @@ const systemDegreesMinutesSeconds = {
53
55
  const [degrees, minutes, seconds, bear] = arg;
54
56
  return Number.parseFloat(((Number.parseFloat(degrees) + Number.parseFloat(minutes) / 60 + Number.parseFloat(seconds) / 3600) * (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)).toFixed(9));
55
57
  },
56
- toFormat(format, [left, right]) {
57
- return [left, right].map((num, index) => {
58
- const abs = Math.abs(num);
58
+ toFormat(format, coordinates) {
59
+ return formatCoordinateSystem(format, coordinates, (abs) => {
59
60
  const deg = Math.floor(abs);
60
61
  const rem = (abs - deg) * 60;
61
62
  const min = Math.floor(rem);
62
- return `${deg} ${min} ${Number.parseFloat(((rem - min) * 60).toFixed(10))} ${BEARINGS[format][index][+(num < 0)]}`;
63
- }).join(` ${SYMBOLS.DIVIDER} `);
63
+ return `${deg} ${min} ${toPlainDecimalString(Number.parseFloat(((rem - min) * 60).toFixed(10)))}`;
64
+ });
64
65
  }
65
66
  };
66
67
 
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","names":["systemDegreesMinutesSeconds: CoordinateSystem"],"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/system.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n BEARINGS,\n type Compass,\n type Format,\n SYMBOL_PATTERNS,\n SYMBOLS,\n} from '../internal';\nimport { parseDegreesMinutesSeconds } from './parser';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\n/**\n * Degrees Minutes Seconds coordinate system implementation.\n *\n * Provides parsing, conversion, and formatting for coordinates in degrees minutes seconds notation.\n * Coordinates are expressed as integer degrees, integer minutes, and decimal seconds (e.g., 37° 46' 29.64″ N).\n *\n * @property name - Human-readable name of the coordinate system.\n * @property parse - Parses degrees minutes seconds coordinate strings.\n * @property toFloat - Converts parsed coordinate components to floating point numbers.\n * @property toFormat - Formats numeric coordinates back to degrees minutes seconds string.\n *\n * @example\n * ```typescript\n * // Parse a coordinate string\n * const [coords, errors] = systemDegreesMinutesSeconds.parse('37° 46' 29.64″ N / 122° 25' 9.84″ W', 'LATLON');\n * ```\n *\n * @example\n * ```typescript\n * // Convert to float\n * const lat = systemDegreesMinutesSeconds.toFloat(['37', '46', '29.64', 'N']);\n * // 37.7749\n * ```\n *\n * @example\n * ```typescript\n * // Format to string\n * const formatted = systemDegreesMinutesSeconds.toFormat('LATLON', [37.7749, -122.4194]);\n * // '37 46 29.64 N / 122 25 9.84 W'\n * ```\n */\nexport const systemDegreesMinutesSeconds: CoordinateSystem = {\n name: 'Degrees Minutes Seconds',\n\n parse: parseDegreesMinutesSeconds,\n\n toFloat(arg) {\n const [degrees, minutes, seconds, bear] = arg as [\n string,\n string,\n string,\n Compass,\n ];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) +\n Number.parseFloat(minutes) / 60 +\n Number.parseFloat(seconds) / 3600) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, [left, right]: [number, number]) {\n return [left, right]\n .map((num, index) => {\n const abs = Math.abs(num);\n const deg = Math.floor(abs);\n const rem = (abs - deg) * 60;\n const min = Math.floor(rem);\n const sec = Number.parseFloat(((rem - min) * 60).toFixed(10));\n\n return `${deg} ${min} ${sec} ${BEARINGS[format][index as 0 | 1][+(num < 0)]}`;\n })\n .join(` ${SYMBOLS.DIVIDER} `);\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAaA,8BAAgD;CAC3D,MAAM;CAEN,OAAO;CAEP,QAAQ,KAAK;EACX,MAAM,CAAC,SAAS,SAAS,SAAS,QAAQ;AAO1C,SAAO,OAAO,aAET,OAAO,WAAW,QAAQ,GACzB,OAAO,WAAW,QAAQ,GAAG,KAC7B,OAAO,WAAW,QAAQ,GAAG,SAC9B,gBAAgB,kBAAkB,KAAK,KAAK,GAAG,KAAK,IACrD,QAAQ,EAAE,CACb;;CAGH,SAAS,QAAgB,CAAC,MAAM,QAA0B;AACxD,SAAO,CAAC,MAAM,MAAM,CACjB,KAAK,KAAK,UAAU;GACnB,MAAM,MAAM,KAAK,IAAI,IAAI;GACzB,MAAM,MAAM,KAAK,MAAM,IAAI;GAC3B,MAAM,OAAO,MAAM,OAAO;GAC1B,MAAM,MAAM,KAAK,MAAM,IAAI;AAG3B,UAAO,GAAG,IAAI,GAAG,IAAI,GAFT,OAAO,aAAa,MAAM,OAAO,IAAI,QAAQ,GAAG,CAAC,CAEjC,GAAG,SAAS,QAAQ,OAAgB,EAAE,MAAM;IACxE,CACD,KAAK,IAAI,QAAQ,QAAQ,GAAG;;CAElC"}
1
+ {"version":3,"file":"system.js","names":["systemDegreesMinutesSeconds: CoordinateSystem"],"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/system.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Compass, type Format, SYMBOL_PATTERNS } from '../internal';\nimport { formatCoordinateSystem } from '../internal/format';\nimport { toPlainDecimalString } from '../internal/plain-decimal';\nimport { parseDegreesMinutesSeconds } from './parser';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\n/**\n * Degrees Minutes Seconds coordinate system implementation.\n *\n * Provides parsing, conversion, and formatting for coordinates in degrees minutes seconds notation.\n * Coordinates are expressed as integer degrees, integer minutes, and decimal seconds (e.g., 37° 46' 29.64″ N).\n *\n * @property name - Human-readable name of the coordinate system.\n * @property parse - Parses degrees minutes seconds coordinate strings.\n * @property toFloat - Converts parsed coordinate components to floating point numbers.\n * @property toFormat - Formats numeric coordinates back to degrees minutes seconds string.\n *\n * @example\n * ```typescript\n * // Parse a coordinate string\n * const [coords, errors] = systemDegreesMinutesSeconds.parse('37° 46' 29.64″ N / 122° 25' 9.84″ W', 'LATLON');\n * ```\n *\n * @example\n * ```typescript\n * // Convert to float\n * const lat = systemDegreesMinutesSeconds.toFloat(['37', '46', '29.64', 'N']);\n * // 37.7749\n * ```\n *\n * @example\n * ```typescript\n * // Format to string\n * const formatted = systemDegreesMinutesSeconds.toFormat('LATLON', [37.7749, -122.4194]);\n * // '37 46 29.64 N / 122 25 9.84 W'\n * ```\n */\nexport const systemDegreesMinutesSeconds: CoordinateSystem = {\n name: 'Degrees Minutes Seconds',\n\n parse: parseDegreesMinutesSeconds,\n\n toFloat(arg) {\n const [degrees, minutes, seconds, bear] = arg as [\n string,\n string,\n string,\n Compass,\n ];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) +\n Number.parseFloat(minutes) / 60 +\n Number.parseFloat(seconds) / 3600) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, coordinates: [number, number]) {\n return formatCoordinateSystem(format, coordinates, (abs) => {\n const deg = Math.floor(abs);\n const rem = (abs - deg) * 60;\n const min = Math.floor(rem);\n const sec = Number.parseFloat(((rem - min) * 60).toFixed(10));\n\n return `${deg} ${min} ${toPlainDecimalString(sec)}`;\n });\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,MAAaA,8BAAgD;CAC3D,MAAM;CAEN,OAAO;CAEP,QAAQ,KAAK;EACX,MAAM,CAAC,SAAS,SAAS,SAAS,QAAQ;AAO1C,SAAO,OAAO,aAET,OAAO,WAAW,QAAQ,GACzB,OAAO,WAAW,QAAQ,GAAG,KAC7B,OAAO,WAAW,QAAQ,GAAG,SAC9B,gBAAgB,kBAAkB,KAAK,KAAK,GAAG,KAAK,IACrD,QAAQ,EAAE,CACb;;CAGH,SAAS,QAAgB,aAA+B;AACtD,SAAO,uBAAuB,QAAQ,cAAc,QAAQ;GAC1D,MAAM,MAAM,KAAK,MAAM,IAAI;GAC3B,MAAM,OAAO,MAAM,OAAO;GAC1B,MAAM,MAAM,KAAK,MAAM,IAAI;AAG3B,UAAO,GAAG,IAAI,GAAG,IAAI,GAAG,qBAFZ,OAAO,aAAa,MAAM,OAAO,IAAI,QAAQ,GAAG,CAAC,CAEZ;IACjD;;CAEL"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,10 +1,53 @@
1
+ /*
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { Format } from "./index.js";
14
+
1
15
  //#region src/coordinates/latlon/internal/format.d.ts
2
- interface FormatOptions {
16
+ /**
17
+ * Display options for the `format*` coordinate formatters: text wrapped around
18
+ * the whole string, the divider between axes, and whether each axis carries
19
+ * its `N`/`S`/`E`/`W` letter.
20
+ */
21
+ type FormatOptions = {
3
22
  prefix: string;
4
23
  suffix: string;
5
24
  separator: string;
6
25
  withOrdinal?: boolean;
7
- }
26
+ };
27
+ /**
28
+ * Shared scaffold for a `CoordinateSystem`'s `toFormat` round-trip string.
29
+ *
30
+ * This is the loss-less internal representation `createCoordinate(...).dd()` /
31
+ * `.ddm()` / `.dms()` returns — deliberately distinct from the display
32
+ * formatters in each system's `formatter.ts`. The `to*Parts` / `format*`
33
+ * functions round and carry to a fixed precision for human display; this path
34
+ * keeps full precision and applies **no** carry so a value survives a
35
+ * format → parse → float round-trip unchanged. The two must not be merged.
36
+ *
37
+ * Owns the parts every system's `toFormat` shares — the `[lat, lon]` map, the
38
+ * ` / ` divider join, and the signed → `N`/`S`/`E`/`W` direction lookup — and
39
+ * defers only the per-axis magnitude rendering (which is all that differs
40
+ * between DD, DDM, and DMS) to `renderMagnitude`.
41
+ *
42
+ * @param format - Axis ordering (`'LATLON'` or `'LONLAT'`).
43
+ * @param coordinates - Signed `[left, right]` values in the given ordering.
44
+ * @param renderMagnitude - Renders the space-separated magnitude components of
45
+ * one axis (e.g. `"37 46.494"` for DDM) from its absolute value.
46
+ * @returns The joined round-trip string, e.g. `"37 46.494 N / 122 25.164 W"`.
47
+ *
48
+ * @remarks pure function
49
+ */
50
+ declare const formatCoordinateSystem: (format: Format, [left, right]: [number, number], renderMagnitude: (magnitude: number) => string) => string;
8
51
  /**
9
52
  * Creates a coordinate formatter function from a coordinate conversion function.
10
53
  *
@@ -13,8 +56,10 @@ interface FormatOptions {
13
56
  *
14
57
  * @example
15
58
  * ```typescript
16
- * const formatDD = createFormatter((num) => `${num.toFixed(6)}°`);
17
- * formatDD([37.7749, -122.4194]);
59
+ * const formatDD = createFormatter(
60
+ * (value, withOrdinal) => `${(withOrdinal ? Math.abs(value) : value).toFixed(6)}°`,
61
+ * );
62
+ * formatDD([37.7749, -122.4194], { withOrdinal: true });
18
63
  * // '37.774900° N, 122.419400° W'
19
64
  * ```
20
65
  *
@@ -27,5 +72,5 @@ interface FormatOptions {
27
72
  */
28
73
  declare const createFormatter: (fn: (coord: number, withOrdinal?: boolean) => string) => (coordinates: [number, number], config?: FormatOptions) => string;
29
74
  //#endregion
30
- export { FormatOptions, createFormatter };
75
+ export { FormatOptions, createFormatter, formatCoordinateSystem };
31
76
  //# sourceMappingURL=format.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,10 +11,38 @@
11
11
  */
12
12
 
13
13
 
14
- import { getOrdinal } from "./ordinal.js";
14
+ import { BEARINGS, SYMBOLS } from "./index.js";
15
+ import { getHemisphere } from "./ordinal.js";
15
16
 
16
17
  //#region src/coordinates/latlon/internal/format.ts
17
18
  /**
19
+ * Shared scaffold for a `CoordinateSystem`'s `toFormat` round-trip string.
20
+ *
21
+ * This is the loss-less internal representation `createCoordinate(...).dd()` /
22
+ * `.ddm()` / `.dms()` returns — deliberately distinct from the display
23
+ * formatters in each system's `formatter.ts`. The `to*Parts` / `format*`
24
+ * functions round and carry to a fixed precision for human display; this path
25
+ * keeps full precision and applies **no** carry so a value survives a
26
+ * format → parse → float round-trip unchanged. The two must not be merged.
27
+ *
28
+ * Owns the parts every system's `toFormat` shares — the `[lat, lon]` map, the
29
+ * ` / ` divider join, and the signed → `N`/`S`/`E`/`W` direction lookup — and
30
+ * defers only the per-axis magnitude rendering (which is all that differs
31
+ * between DD, DDM, and DMS) to `renderMagnitude`.
32
+ *
33
+ * @param format - Axis ordering (`'LATLON'` or `'LONLAT'`).
34
+ * @param coordinates - Signed `[left, right]` values in the given ordering.
35
+ * @param renderMagnitude - Renders the space-separated magnitude components of
36
+ * one axis (e.g. `"37 46.494"` for DDM) from its absolute value.
37
+ * @returns The joined round-trip string, e.g. `"37 46.494 N / 122 25.164 W"`.
38
+ *
39
+ * @remarks pure function
40
+ */
41
+ const formatCoordinateSystem = (format, [left, right], renderMagnitude) => [left, right].map((value, index) => {
42
+ const direction = BEARINGS[format][index][+(value < 0)];
43
+ return `${renderMagnitude(Math.abs(value))} ${direction}`;
44
+ }).join(` ${SYMBOLS.DIVIDER} `);
45
+ /**
18
46
  * Creates a coordinate formatter function from a coordinate conversion function.
19
47
  *
20
48
  * @param fn - Function that converts a single coordinate value to a formatted string.
@@ -22,8 +50,10 @@ import { getOrdinal } from "./ordinal.js";
22
50
  *
23
51
  * @example
24
52
  * ```typescript
25
- * const formatDD = createFormatter((num) => `${num.toFixed(6)}°`);
26
- * formatDD([37.7749, -122.4194]);
53
+ * const formatDD = createFormatter(
54
+ * (value, withOrdinal) => `${(withOrdinal ? Math.abs(value) : value).toFixed(6)}°`,
55
+ * );
56
+ * formatDD([37.7749, -122.4194], { withOrdinal: true });
27
57
  * // '37.774900° N, 122.419400° W'
28
58
  * ```
29
59
  *
@@ -36,15 +66,15 @@ import { getOrdinal } from "./ordinal.js";
36
66
  */
37
67
  const createFormatter = (fn) => (coordinates, config) => {
38
68
  const [latitude, longitude] = coordinates;
39
- const latOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(latitude, true)}` : ""}`;
40
- const lonOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(longitude, false)}` : ""}`;
41
- const lat = fn(latitude, config?.withOrdinal);
42
- const lon = fn(longitude, config?.withOrdinal);
69
+ const latOrdinal = config?.withOrdinal ? ` ${getHemisphere(latitude, "lat")}` : "";
70
+ const lonOrdinal = config?.withOrdinal ? ` ${getHemisphere(longitude, "lon")}` : "";
71
+ const latValue = fn(latitude, config?.withOrdinal);
72
+ const lonValue = fn(longitude, config?.withOrdinal);
43
73
  const prefix = config?.prefix ?? "";
44
74
  const suffix = config?.suffix ?? "";
45
- return `${prefix}${lat}${latOrdinal}${config?.separator ?? ", "}${lon}${lonOrdinal}${suffix}`;
75
+ return `${prefix}${latValue}${latOrdinal}${config?.separator ?? ", "}${lonValue}${lonOrdinal}${suffix}`;
46
76
  };
47
77
 
48
78
  //#endregion
49
- export { createFormatter };
79
+ export { createFormatter, formatCoordinateSystem };
50
80
  //# sourceMappingURL=format.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/format.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n// __private-exports\n\nimport { getOrdinal } from './ordinal';\n\nexport interface FormatOptions {\n prefix: string;\n suffix: string;\n separator: string;\n withOrdinal?: boolean;\n}\n\n/**\n * Creates a coordinate formatter function from a coordinate conversion function.\n *\n * @param fn - Function that converts a single coordinate value to a formatted string.\n * @returns Formatter function that takes coordinate pair and optional config.\n *\n * @example\n * ```typescript\n * const formatDD = createFormatter((num) => `${num.toFixed(6)}°`);\n * formatDD([37.7749, -122.4194]);\n * // '37.774900° N, 122.419400° W'\n * ```\n *\n * @example\n * ```typescript\n * const formatDMS = createFormatter(toDegreesMinutesSeconds);\n * formatDMS([37.7749, -122.4194], { separator: ' / ', withOrdinal: true });\n * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'\n * ```\n */\nexport const createFormatter =\n (fn: (coord: number, withOrdinal?: boolean) => string) =>\n (coordinates: [number, number], config?: FormatOptions): string => {\n const [latitude, longitude] = coordinates;\n const latOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(latitude, true)}` : ''}`;\n const lonOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(longitude, false)}` : ''}`;\n const lat = fn(latitude, config?.withOrdinal);\n const lon = fn(longitude, config?.withOrdinal);\n const prefix = config?.prefix ?? '';\n const suffix = config?.suffix ?? '';\n const separator = config?.separator ?? ', ';\n\n return `${prefix}${lat}${latOrdinal}${separator}${lon}${lonOrdinal}${suffix}`;\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAa,mBACV,QACA,aAA+B,WAAmC;CACjE,MAAM,CAAC,UAAU,aAAa;CAC9B,MAAM,aAAa,GAAG,QAAQ,cAAc,IAAI,WAAW,UAAU,KAAK,KAAK;CAC/E,MAAM,aAAa,GAAG,QAAQ,cAAc,IAAI,WAAW,WAAW,MAAM,KAAK;CACjF,MAAM,MAAM,GAAG,UAAU,QAAQ,YAAY;CAC7C,MAAM,MAAM,GAAG,WAAW,QAAQ,YAAY;CAC9C,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,SAAS,QAAQ,UAAU;AAGjC,QAAO,GAAG,SAAS,MAAM,aAFP,QAAQ,aAAa,OAEW,MAAM,aAAa"}
1
+ {"version":3,"file":"format.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/format.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n// __private-exports\n\nimport { BEARINGS, type Format, SYMBOLS } from '.';\nimport { getHemisphere } from './ordinal';\n\n/**\n * Display options for the `format*` coordinate formatters: text wrapped around\n * the whole string, the divider between axes, and whether each axis carries\n * its `N`/`S`/`E`/`W` letter.\n */\nexport type FormatOptions = {\n prefix: string;\n suffix: string;\n separator: string;\n withOrdinal?: boolean;\n};\n\n/**\n * Shared scaffold for a `CoordinateSystem`'s `toFormat` round-trip string.\n *\n * This is the loss-less internal representation `createCoordinate(...).dd()` /\n * `.ddm()` / `.dms()` returns — deliberately distinct from the display\n * formatters in each system's `formatter.ts`. The `to*Parts` / `format*`\n * functions round and carry to a fixed precision for human display; this path\n * keeps full precision and applies **no** carry so a value survives a\n * format → parse → float round-trip unchanged. The two must not be merged.\n *\n * Owns the parts every system's `toFormat` shares — the `[lat, lon]` map, the\n * ` / ` divider join, and the signed → `N`/`S`/`E`/`W` direction lookup — and\n * defers only the per-axis magnitude rendering (which is all that differs\n * between DD, DDM, and DMS) to `renderMagnitude`.\n *\n * @param format - Axis ordering (`'LATLON'` or `'LONLAT'`).\n * @param coordinates - Signed `[left, right]` values in the given ordering.\n * @param renderMagnitude - Renders the space-separated magnitude components of\n * one axis (e.g. `\"37 46.494\"` for DDM) from its absolute value.\n * @returns The joined round-trip string, e.g. `\"37 46.494 N / 122 25.164 W\"`.\n *\n * @remarks pure function\n */\nexport const formatCoordinateSystem = (\n format: Format,\n [left, right]: [number, number],\n renderMagnitude: (magnitude: number) => string,\n): string =>\n [left, right]\n .map((value, index) => {\n const direction = BEARINGS[format][index as 0 | 1][+(value < 0)];\n\n return `${renderMagnitude(Math.abs(value))} ${direction}`;\n })\n .join(` ${SYMBOLS.DIVIDER} `);\n\n/**\n * Creates a coordinate formatter function from a coordinate conversion function.\n *\n * @param fn - Function that converts a single coordinate value to a formatted string.\n * @returns Formatter function that takes coordinate pair and optional config.\n *\n * @example\n * ```typescript\n * const formatDD = createFormatter(\n * (value, withOrdinal) => `${(withOrdinal ? Math.abs(value) : value).toFixed(6)}°`,\n * );\n * formatDD([37.7749, -122.4194], { withOrdinal: true });\n * // '37.774900° N, 122.419400° W'\n * ```\n *\n * @example\n * ```typescript\n * const formatDMS = createFormatter(toDegreesMinutesSeconds);\n * formatDMS([37.7749, -122.4194], { separator: ' / ', withOrdinal: true });\n * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'\n * ```\n */\nexport const createFormatter =\n (fn: (coord: number, withOrdinal?: boolean) => string) =>\n (coordinates: [number, number], config?: FormatOptions): string => {\n const [latitude, longitude] = coordinates;\n const latOrdinal = config?.withOrdinal\n ? ` ${getHemisphere(latitude, 'lat')}`\n : '';\n const lonOrdinal = config?.withOrdinal\n ? ` ${getHemisphere(longitude, 'lon')}`\n : '';\n const latValue = fn(latitude, config?.withOrdinal);\n const lonValue = fn(longitude, config?.withOrdinal);\n const prefix = config?.prefix ?? '';\n const suffix = config?.suffix ?? '';\n const separator = config?.separator ?? ', ';\n\n return `${prefix}${latValue}${latOrdinal}${separator}${lonValue}${lonOrdinal}${suffix}`;\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,0BACX,QACA,CAAC,MAAM,QACP,oBAEA,CAAC,MAAM,MAAM,CACV,KAAK,OAAO,UAAU;CACrB,MAAM,YAAY,SAAS,QAAQ,OAAgB,EAAE,QAAQ;AAE7D,QAAO,GAAG,gBAAgB,KAAK,IAAI,MAAM,CAAC,CAAC,GAAG;EAC9C,CACD,KAAK,IAAI,QAAQ,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;AAwBjC,MAAa,mBACV,QACA,aAA+B,WAAmC;CACjE,MAAM,CAAC,UAAU,aAAa;CAC9B,MAAM,aAAa,QAAQ,cACvB,IAAI,cAAc,UAAU,MAAM,KAClC;CACJ,MAAM,aAAa,QAAQ,cACvB,IAAI,cAAc,WAAW,MAAM,KACnC;CACJ,MAAM,WAAW,GAAG,UAAU,QAAQ,YAAY;CAClD,MAAM,WAAW,GAAG,WAAW,QAAQ,YAAY;CACnD,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,SAAS,QAAQ,UAAU;AAGjC,QAAO,GAAG,SAAS,WAAW,aAFZ,QAAQ,aAAa,OAEgB,WAAW,aAAa"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,7 +11,8 @@
11
11
  */
12
12
 
13
13
  import { CoordinateInput, CoordinateInternalValue, CoordinateObject, CoordinateTuple, LatLonTuple, LonLatTuple, isCoordinateObject, isCoordinateTuple, normalizeObjectToLatLon, tupleToLatLon } from "./normalize.js";
14
- import { isFiniteNumber, validateNumericCoordinate, validateSignedRange } from "./validate.js";
14
+ import { toPlainDecimalString } from "./plain-decimal.js";
15
+ import { isFiniteNumber, isValidNumericCoordinate, validateNumericCoordinate, validateSignedRange } from "./validate.js";
15
16
 
16
17
  //#region src/coordinates/latlon/internal/index.d.ts
17
18
  type Axes = 'LAT' | 'LON';
@@ -72,5 +73,5 @@ declare const PARTIAL_PATTERNS: {
72
73
  readonly secDec: RegExp;
73
74
  };
74
75
  //#endregion
75
- export { Axes, BEARINGS, Compass, type CoordinateInput, type CoordinateInternalValue, type CoordinateObject, type CoordinateTuple, Errors, FORMATS, FORMATS_DEFAULT, Format, LIMITS, type LatLonTuple, type LonLatTuple, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, isCoordinateObject, isCoordinateTuple, isFiniteNumber, normalizeObjectToLatLon, tupleToLatLon, validateNumericCoordinate, validateSignedRange };
76
+ export { Axes, BEARINGS, Compass, type CoordinateInput, type CoordinateInternalValue, type CoordinateObject, type CoordinateTuple, Errors, FORMATS, FORMATS_DEFAULT, Format, LIMITS, type LatLonTuple, type LonLatTuple, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, isCoordinateObject, isCoordinateTuple, isFiniteNumber, isValidNumericCoordinate, normalizeObjectToLatLon, toPlainDecimalString, tupleToLatLon, validateNumericCoordinate, validateSignedRange };
76
77
  //# sourceMappingURL=index.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -13,7 +13,8 @@
13
13
 
14
14
  import { capture, merge, optional } from "../../../patterning.js";
15
15
  import { isCoordinateObject, isCoordinateTuple, normalizeObjectToLatLon, tupleToLatLon } from "./normalize.js";
16
- import { isFiniteNumber, validateNumericCoordinate, validateSignedRange } from "./validate.js";
16
+ import { toPlainDecimalString } from "./plain-decimal.js";
17
+ import { isFiniteNumber, isValidNumericCoordinate, validateNumericCoordinate, validateSignedRange } from "./validate.js";
17
18
 
18
19
  //#region src/coordinates/latlon/internal/index.ts
19
20
  /**
@@ -98,5 +99,5 @@ const PARTIAL_PATTERNS = {
98
99
  };
99
100
 
100
101
  //#endregion
101
- export { BEARINGS, FORMATS, FORMATS_DEFAULT, LIMITS, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, isCoordinateObject, isCoordinateTuple, isFiniteNumber, normalizeObjectToLatLon, tupleToLatLon, validateNumericCoordinate, validateSignedRange };
102
+ export { BEARINGS, FORMATS, FORMATS_DEFAULT, LIMITS, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, isCoordinateObject, isCoordinateTuple, isFiniteNumber, isValidNumericCoordinate, normalizeObjectToLatLon, toPlainDecimalString, tupleToLatLon, validateNumericCoordinate, validateSignedRange };
102
103
  //# sourceMappingURL=index.js.map