sl-glw 0.4.0

Fetch, parse, and render GlobalWind (GLW) wind/current/wave event overlays for Second Life sailing maps
Documentation
# sl-glw

sl-glw:
[![Crates.io Version sl-glw][crates-img]][crates-link]
[![lib.rs Version sl-glw][libs-img]][libs-link]
[![docs.rs sl-glw][docs-img]][docs-link]
[![Dependency status sl-glw][deps-img]][deps-link]

Fetch, parse, and render [GlobalWind][glw] (GLW) wind/current/wave event
overlays for Second Life sailing maps.

GlobalWind is a community weather system for Second Life sailing: a GLW
"event" describes a base wind/current/wave state for an area of the grid,
plus per-region rectangular *areas* and *circles* that override it. This
crate fetches an event from a GLW server, parses its JSON into strongly
typed values, and draws the wind arrows, current arrows, wave glyphs,
override labels, and an optional legend onto a Second Life map image.

It builds on [`sl-map-apis`][sl-map-apis] (the `MapLike` map image and grid
geometry) and [`sl-types`][sl-types] (grid coordinates and zoom levels).

## What it gives you

- **Typed model** of a GLW event (`GlwEvent`, `Base`, `Area`, `Circle`, and
  the per-quantity newtypes like `WindDirection`, `KnotSpeed`, `WaveHeight`)
  with validating constructors that reject out-of-range values.
- **Fetching** by numeric id or string key, either through the low-level
  `GlwClient` / `fetch_event_by_*` functions or the caching `GlwEventCache`.
- **HTTP caching** via `http-cache-semantics`, layered as an in-memory LRU
  over a persistent on-disk [`redb`] store, so repeated lookups respect the
  server's cache headers instead of re-fetching.
- **Rendering** through the `MapLikeGlwExt` extension trait, which adds
  `draw_glw_event` / `draw_glw_event_with_font` (and per-shape helpers) to
  any `sl-map-apis` `MapLike`. Appearance is controlled by `GlwStyle` and
  `GlwColorPalette`.

## Fonts

The crate **never bundles a font.** Label and legend rendering takes any
[`ab_glyph::Font`] you supply, so you choose the typeface and licensing.
The drawing methods that emit text (`draw_glw_event_with_font` and the
`*_label` / `*_legend` helpers) require a font argument; `draw_glw_event`
draws only the geometric overlay and needs none. A copy of DejaVuSans is
checked in at the workspace root for examples and tests.

## Example

Fetch an event and draw it onto a map. `GlwEventCache::new` takes a cache
directory and an optional base URL (`None` uses the GLW default); the
`MapLike` here is whatever `sl-map-apis` map you are rendering onto.

```rust,ignore
use sl_glw::{EventId, GlwEventCache, GlwStyle, MapLikeGlwExt as _};
use sl_map_apis::coverage::PlacementSlot;

// Persistent cache under ./cache, default GLW server.
let mut cache = GlwEventCache::new("cache".into(), None)?;

// Returns Ok(None) if the server reports no such event.
if let Some(event) = cache.get_event_by_id(EventId::new(6910)).await? {
    let style = GlwStyle {
        legend_position: Some(PlacementSlot::TopLeft),
        ..GlwStyle::default()
    };

    // The caller supplies the font; the library never does.
    let bytes = std::fs::read("DejaVuSans.ttf")?;
    let font = ab_glyph::FontVec::try_from_vec(bytes)?;

    map.draw_glw_event_with_font(&event, &style, &font)?;
}
```

For a complete, runnable program — including a minimal in-memory `MapLike`
that needs no map tiles — see [`examples/render_sample.rs`][example]:

```text
cargo run -p sl-glw --example render_sample -- DejaVuSans.ttf
```

The [`sl-map-cli`][sl-map-cli] and [`sl-map-web`][sl-map-web] crates in the
same workspace show the overlay wired into real map renders.

## License

Licensed under either of the Apache License, Version 2.0 or the MIT license
at your option (`MIT OR Apache-2.0`).

[glw]: http://globalwind.net
[sl-map-apis]: https://crates.io/crates/sl-map-apis
[sl-types]: https://crates.io/crates/sl-types
[sl-map-cli]: https://crates.io/crates/sl-map-cli
[sl-map-web]: https://github.com/taladar/sl-map-tools/tree/master/sl-map-web
[example]: https://github.com/taladar/sl-map-tools/blob/master/sl-glw/examples/render_sample.rs
[`redb`]: https://crates.io/crates/redb
[`ab_glyph::Font`]: https://docs.rs/ab_glyph/latest/ab_glyph/trait.Font.html

[crates-img]: https://img.shields.io/crates/v/sl-glw
[crates-link]: https://crates.io/crates/sl-glw
[libs-img]: https://img.shields.io/crates/v/sl-glw?label=lib.rs
[libs-link]: https://lib.rs/crates/sl-glw
[docs-img]: https://img.shields.io/docsrs/sl-glw
[docs-link]: https://docs.rs/sl-glw/latest/sl-glw
[deps-img]: https://deps.rs/crate/sl-glw/latest/status.svg
[deps-link]: https://deps.rs/crate/sl-glw/