GPS Exchange Format library/CLI in OCaml
1(** High-level Unix API for GPX operations *)
2
3(** Result binding operators *)
4let (let*) = Result.bind
5
6(* Re-export IO module *)
7module IO = Gpx_io
8
9(* Re-export common types *)
10open Gpx
11
12(** Convenience functions for common operations *)
13
14(** Read and parse GPX file *)
15let read = IO.read_file
16
17(** Write GPX to file *)
18let write = IO.write_file
19
20(** Write GPX to file with backup *)
21let write_with_backup = IO.write_file_with_backup
22
23(** Convert GPX to string *)
24let to_string = write_string
25
26(** Parse GPX from string *)
27let from_string = parse_string
28
29(** Quick validation check *)
30let is_valid = is_valid
31
32(** Get validation issues *)
33let validate = validate_gpx
34
35(** Create simple waypoint *)
36let make_waypoint ~lat ~lon ?name ?desc () =
37 match (Coordinate.latitude lat, Coordinate.longitude lon) with
38 | (Ok lat, Ok lon) ->
39 let wpt = Waypoint.make lat lon in
40 let wpt = { wpt with name; desc } in
41 Ok wpt
42 | (Error e, _) | (_, Error e) -> Error (Gpx.Error.invalid_coordinate e)
43
44(** Create simple track from coordinate list *)
45let make_track_from_coords ~name coords =
46 let make_trkpt (lat, lon) =
47 match (Coordinate.latitude lat, Coordinate.longitude lon) with
48 | (Ok lat, Ok lon) -> Ok (Waypoint.make lat lon)
49 | (Error e, _) | (_, Error e) -> Error (Gpx.Error.invalid_coordinate e)
50 in
51 let rec convert_coords acc = function
52 | [] -> Ok (List.rev acc)
53 | coord :: rest ->
54 match make_trkpt coord with
55 | Ok trkpt -> convert_coords (trkpt :: acc) rest
56 | Error e -> Error e
57 in
58 let* _trkpts = convert_coords [] coords in
59 Ok (Track.make_from_coords ~name coords)
60
61(** Create simple route from coordinate list *)
62let make_route_from_coords ~name coords =
63 let make_rtept (lat, lon) =
64 match (Coordinate.latitude lat, Coordinate.longitude lon) with
65 | (Ok lat, Ok lon) -> Ok (Waypoint.make lat lon)
66 | (Error e, _) | (_, Error e) -> Error (Gpx.Error.invalid_coordinate e)
67 in
68 let rec convert_coords acc = function
69 | [] -> Ok (List.rev acc)
70 | coord :: rest ->
71 match make_rtept coord with
72 | Ok rtept -> convert_coords (rtept :: acc) rest
73 | Error e -> Error e
74 in
75 let* _rtepts = convert_coords [] coords in
76 Ok (Route.make_from_coords ~name coords)
77
78(** Extract coordinates from waypoints *)
79let waypoint_coords wpt = Waypoint.to_floats wpt
80
81(** Extract coordinates from track *)
82let track_coords track = Track.to_coords track
83
84(** Extract coordinates from route *)
85let route_coords route = Route.to_coords route
86
87(** Count total points in GPX *)
88let count_points gpx =
89 let waypoints = Doc.waypoints gpx in
90 let routes = Doc.routes gpx in
91 let tracks = Doc.tracks gpx in
92 List.length waypoints +
93 List.fold_left (fun acc r -> acc + List.length (Route.points r)) 0 routes +
94 List.fold_left (fun acc t -> acc + Track.point_count t) 0 tracks
95
96(** Get GPX statistics *)
97type gpx_stats = {
98 waypoint_count : int;
99 route_count : int;
100 track_count : int;
101 total_points : int;
102 has_elevation : bool;
103 has_time : bool;
104}
105
106let stats gpx =
107 let waypoints = Doc.waypoints gpx in
108 let routes = Doc.routes gpx in
109 let tracks = Doc.tracks gpx in
110 {
111 waypoint_count = List.length waypoints;
112 route_count = List.length routes;
113 track_count = List.length tracks;
114 total_points = count_points gpx;
115 has_elevation = List.exists (fun w -> Waypoint.elevation w <> None) waypoints;
116 has_time = List.exists (fun w -> Waypoint.time w <> None) waypoints;
117 }
118
119(** Pretty print GPX statistics *)
120let print_stats gpx =
121 let stats = stats gpx in
122 Printf.printf "GPX Statistics:\n";
123 Printf.printf " Waypoints: %d\n" stats.waypoint_count;
124 Printf.printf " Routes: %d\n" stats.route_count;
125 Printf.printf " Tracks: %d\n" stats.track_count;
126 Printf.printf " Total points: %d\n" stats.total_points;
127 Printf.printf " Has elevation data: %s\n" (if stats.has_elevation then "yes" else "no");
128 Printf.printf " Has time data: %s\n" (if stats.has_time then "yes" else "no")