My agentic slop goes here. Not intended for anyone else!
1(** Latitude module *)
2
3type t = float
4
5let is_valid f = f >= -90.0 && f <= 90.0
6
7let create f =
8 if not (is_valid f) then
9 raise (Error.Coordinate_error (Error.Invalid_latitude f))
10 else f
11
12let unsafe_create f = f
13
14let clamp f =
15 if f < -90.0 then -90.0
16 else if f > 90.0 then 90.0
17 else f
18
19let of_dms ~degree ~minute ~second =
20 let sign = if degree < 0 || minute < 0 || second < 0.0 then -1.0 else 1.0 in
21 let d = abs degree in
22 let m = abs minute in
23 let s = abs_float second in
24 let decimal = float_of_int d +. (float_of_int m /. 60.0) +. (s /. 3600.0) in
25 create (sign *. decimal)
26
27let to_float t = t
28
29let degree t = int_of_float t
30
31let decimal_minute t =
32 let d = abs_float t in
33 (d -. floor d) *. 60.0
34
35let minute t = int_of_float (decimal_minute t)
36
37let second t =
38 let dm = decimal_minute t in
39 (dm -. floor dm) *. 60.0
40
41let hemisphere t = if t < 0.0 then `S else `N
42
43let add t delta = create (t +. delta)
44let sub t delta = create (t -. delta)
45let neg t = create (-.t)
46let abs t = abs_float t
47
48let equal a b = a = b
49let compare = Float.compare
50let ( = ) = equal
51let ( < ) a b = compare a b < 0
52let ( > ) a b = compare a b > 0
53let ( <= ) a b = compare a b <= 0
54let ( >= ) a b = compare a b >= 0
55
56let to_string t = Printf.sprintf "%.6f" t
57
58let format ?(precision = 6) t =
59 Printf.sprintf "%.*f" precision t
60
61let to_dms_string t =
62 let h = match hemisphere t with `N -> "N" | `S -> "S" in
63 let d = abs_float (float_of_int (degree t)) |> int_of_float in
64 let m = minute (abs_float t) in
65 let s = second (abs_float t) in
66 Printf.sprintf "%d°%02d'%05.2f\"%s" d m s h