My agentic slop goes here. Not intended for anyone else!
at main 1.6 kB view raw
1(** Geographic vector module *) 2 3type t = { 4 dx : float; (* km *) 5 dy : float; (* km *) 6} 7 8let deg_to_rad = Float.pi /. 180.0 9let rad_to_deg = 180.0 /. Float.pi 10 11let create_cartesian ~dx ~dy = { dx; dy } 12 13let create_polar ~heading ~distance = 14 (* Convert heading to mathematical angle (east = 0, counterclockwise) *) 15 let angle = (90.0 -. heading) *. deg_to_rad in 16 { 17 dx = distance *. cos angle; 18 dy = distance *. sin angle; 19 } 20 21let between p1 p2 = 22 (* Calculate vector between two coordinates *) 23 let dist = Coord.distance_haversine p1 p2 in 24 let bearing = Coord.bearing p1 p2 in 25 create_polar ~heading:bearing ~distance:dist 26 27let dx t = t.dx 28let dy t = t.dy 29 30let heading t = 31 (* Convert from mathematical angle to geographic heading *) 32 let angle = atan2 t.dy t.dx *. rad_to_deg in 33 mod_float (90.0 -. angle +. 360.0) 360.0 34 35let distance t = 36 sqrt (t.dx ** 2.0 +. t.dy ** 2.0) 37 38let add v1 v2 = { 39 dx = v1.dx +. v2.dx; 40 dy = v1.dy +. v2.dy; 41} 42 43let sub v1 v2 = { 44 dx = v1.dx -. v2.dx; 45 dy = v1.dy -. v2.dy; 46} 47 48let scale v factor = { 49 dx = v.dx *. factor; 50 dy = v.dy *. factor; 51} 52 53let neg v = { 54 dx = -.v.dx; 55 dy = -.v.dy; 56} 57 58let rotate v degrees = 59 let angle = degrees *. deg_to_rad in 60 let cos_a = cos angle in 61 let sin_a = sin angle in 62 { 63 dx = v.dx *. cos_a -. v.dy *. sin_a; 64 dy = v.dx *. sin_a +. v.dy *. cos_a; 65 } 66 67let apply coord v = 68 Coord.offset coord ~heading:(heading v) ~distance:(distance v) 69 70let to_string t = 71 Printf.sprintf "Vector(heading=%.2f°, distance=%.2fkm)" (heading t) (distance t)