package mlgpx
Library and CLI for parsing and generating GPS Exchange (GPX) formats
Install
dune-project
Dependency
Authors
Maintainers
Sources
mlgpx-1.0.0.tbz
md5=5342bb7e601273245a9fe263e5a08770
sha512=cd73b16e988b3ed3cc427a6c6c6d6c9c745adb1eb7efaae3c34e8d006e9c03d9f9d2616cd4118564bd9873903969d3e4053b585e79dbd3e3e7d0f541e2faac83
doc/src/mlgpx.core/metadata.ml.html
Source file metadata.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
(** GPX metadata and bounds types *) (** Bounding box *) type bounds = { minlat : Coordinate.latitude; minlon : Coordinate.longitude; maxlat : Coordinate.latitude; maxlon : Coordinate.longitude; } (** Main metadata type *) type t = { name : string option; desc : string option; author : Link.person option; copyright : Link.copyright option; links : Link.t list; time : Ptime.t option; keywords : string option; bounds : bounds option; extensions : Extension.t list; } (** {2 Bounds Operations} *) module Bounds = struct type t = bounds (** Create bounds from coordinates *) let make ~minlat ~minlon ~maxlat ~maxlon = { minlat; minlon; maxlat; maxlon } (** Create bounds from float coordinates with validation *) let make_from_floats ~minlat ~minlon ~maxlat ~maxlon = match Coordinate.latitude minlat, Coordinate.longitude minlon, Coordinate.latitude maxlat, Coordinate.longitude maxlon with | Ok minlat, Ok minlon, Ok maxlat, Ok maxlon -> if Coordinate.latitude_to_float minlat <= Coordinate.latitude_to_float maxlat && Coordinate.longitude_to_float minlon <= Coordinate.longitude_to_float maxlon then Ok { minlat; minlon; maxlat; maxlon } else Error "Invalid bounds: min values must be <= max values" | Error e, _, _, _ | _, Error e, _, _ | _, _, Error e, _ | _, _, _, Error e -> Error e (** Get corner coordinates *) let min_coords t = Coordinate.make t.minlat t.minlon let max_coords t = Coordinate.make t.maxlat t.maxlon (** Get all bounds as tuple *) let bounds t = (t.minlat, t.minlon, t.maxlat, t.maxlon) (** Check if coordinate is within bounds *) let contains bounds coord = let lat = Coordinate.lat coord in let lon = Coordinate.lon coord in Coordinate.latitude_to_float bounds.minlat <= Coordinate.latitude_to_float lat && Coordinate.latitude_to_float lat <= Coordinate.latitude_to_float bounds.maxlat && Coordinate.longitude_to_float bounds.minlon <= Coordinate.longitude_to_float lon && Coordinate.longitude_to_float lon <= Coordinate.longitude_to_float bounds.maxlon (** Calculate bounds area *) let area t = let lat_diff = Coordinate.latitude_to_float t.maxlat -. Coordinate.latitude_to_float t.minlat in let lon_diff = Coordinate.longitude_to_float t.maxlon -. Coordinate.longitude_to_float t.minlon in lat_diff *. lon_diff (** Compare bounds *) let compare t1 t2 = let minlat_cmp = Float.compare (Coordinate.latitude_to_float t1.minlat) (Coordinate.latitude_to_float t2.minlat) in if minlat_cmp <> 0 then minlat_cmp else let minlon_cmp = Float.compare (Coordinate.longitude_to_float t1.minlon) (Coordinate.longitude_to_float t2.minlon) in if minlon_cmp <> 0 then minlon_cmp else let maxlat_cmp = Float.compare (Coordinate.latitude_to_float t1.maxlat) (Coordinate.latitude_to_float t2.maxlat) in if maxlat_cmp <> 0 then maxlat_cmp else Float.compare (Coordinate.longitude_to_float t1.maxlon) (Coordinate.longitude_to_float t2.maxlon) (** Test bounds equality *) let equal t1 t2 = compare t1 t2 = 0 (** Pretty print bounds *) let pp ppf t = Format.fprintf ppf "[(%g,%g) - (%g,%g)]" (Coordinate.latitude_to_float t.minlat) (Coordinate.longitude_to_float t.minlon) (Coordinate.latitude_to_float t.maxlat) (Coordinate.longitude_to_float t.maxlon) end (** {2 Metadata Operations} *) (** Create empty metadata *) let empty = { name = None; desc = None; author = None; copyright = None; links = []; time = None; keywords = None; bounds = None; extensions = []; } (** Create metadata with name *) let make ~name = { empty with name = Some name } (** Get name *) let name t = t.name (** Get description *) let description t = t.desc (** Get author *) let t = t.author (** Get copyright *) let copyright t = t.copyright (** Get links *) let links t = t.links (** Get time *) let time t = t.time (** Get keywords *) let keywords t = t.keywords (** Get bounds *) let bounds_opt t = t.bounds (** Get extensions *) let extensions t = t.extensions (** Update name *) let with_name t name = { t with name = Some name } (** Update description *) let with_description t desc = { t with desc = Some desc } (** Update keywords *) let with_keywords t keywords = { t with keywords = Some keywords } (** Update time *) let with_time t time = { t with time } (** Update bounds *) let with_bounds t bounds = { t with bounds = Some bounds } (** Update author *) let t = { t with author = Some author } (** Update copyright *) let with_copyright t copyright = { t with copyright = Some copyright } (** Add link *) let add_link t link = { t with links = link :: t.links } (** Add extensions *) let add_extensions t extensions = { t with extensions = extensions @ t.extensions } (** Compare metadata *) let compare t1 t2 = let name_cmp = Option.compare String.compare t1.name t2.name in if name_cmp <> 0 then name_cmp else let desc_cmp = Option.compare String.compare t1.desc t2.desc in if desc_cmp <> 0 then desc_cmp else Option.compare Ptime.compare t1.time t2.time (** Test metadata equality *) let equal t1 t2 = compare t1 t2 = 0 (** Pretty print metadata *) let pp ppf t = match t.name with | Some name -> Format.fprintf ppf "\"%s\"" name | None -> Format.fprintf ppf "(unnamed)"
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>