Crate d3_geo_rs

source ·
Expand description

A port of d3/d3-geo into rust_d3_geo.

A library with a wide range of geographic projections, spherical shapes and spherical trigonometry.

Features :-

  • Each projection builder supports - scaling, rotating and translation to yield the desired map view.

  • Large datasets can be resampled to reduce compute.

  • As well as displaying to a HTML CANVAS element or SVG, various metric can be computed on the geometry such as Area, Centroids, and Bounds on polygons and lines.

Each projection has default builder, which can be programmed.

Stereographic for example

use geo_types::Coord;
use d3_geo_rs::projection::Build;
use d3_geo_rs::projection::RawBase as ProjectionRawBase;
use d3_geo_rs::projection::stereographic::Stereographic;
use d3_geo_rs::projection::ClipAngleAdjust;
use d3_geo_rs::projection::PrecisionAdjust;
use d3_geo_rs::projection::ScaleSet;
use d3_geo_rs::projection::TranslateSet;
use d3_geo_rs::stream::DrainStub;

    let stereographic = Stereographic::<f64>::builder::<DrainStub<f64>>()
      .scale_set(100_f64)
      .translate_set(&Coord {
         x: 300_f64,
         y: 300_f64,
      })
      .clip_angle(90_f64)
      .precision_set(&10_f64)
      .build();

§Examples

The examples directory contains a large selection of applications demonstration web applications rendering to a CANVAS or SVG elements. It serves as a migration guide examples/projection shows each projection in turn, with the javascript and rust version drawn side by side.

examples/globe - demonstrates that this library can process larger datasets than is possible which javascript The javascript version operate on a 110m dataset of the globe while, the RUST version use a denser 50m dataset.

Here is code snippet from example/projection/globe/ showing the rendering of a globe.


extern crate js_sys;
extern crate rust_topojson_client;
extern crate topojson;
extern crate web_sys;

use geo_types::Coord;
use geo::Geometry;
use geo::MultiLineString;
use topojson::Topology;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use gloo_utils::format::JsValueSerdeExt;
use wasm_bindgen_futures::JsFuture;
use web_sys::*;

use d3_geo_rs::graticule::generate_mls;
use d3_geo_rs::path::builder::Builder as PathBuilder;
use d3_geo_rs::path::Result as PathResult;
use d3_geo_rs::path::endpoint::Endpoint as PathEndpoint;
use d3_geo_rs::projection::orthographic::Orthographic;
use d3_geo_rs::projection::Build;
use d3_geo_rs::projection::RawBase as ProjectionRawBase;
use d3_geo_rs::projection::RotateSet;
use d3_geo_rs::projection::ScaleSet;
use d3_geo_rs::projection::TranslateSet;
use rust_topojson_client::feature::feature_from_name;

fn document() -> Result<Document, JsValue> {
    let window = web_sys::window().unwrap();
    Ok(window.document().unwrap())
}

/// Entry point
#[wasm_bindgen(start)]
pub async fn start() -> Result<(), JsValue> {
    let document = document()?;
    let window = web_sys::window().expect("Failed to get window");

    // Get data from world map.
    let mut opts = RequestInit::new();
    opts.method("GET");
    opts.mode(RequestMode::Cors);
    let request = Request::new_with_str_and_init("/world-atlas/world/50m.json", &opts)?;

    let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
    let resp: Response = resp_value.dyn_into().unwrap();

    let json = JsFuture::from(resp.json()?).await?;

    let topology =
        JsValueSerdeExt::into_serde::<Topology>(&json).expect("Did not get a valid Topology");

    // Grab canvas.
    let canvas = document
        .get_element_by_id("c")
        .unwrap()
        .dyn_into::<web_sys::HtmlCanvasElement>()?;

    let context_raw = canvas
        .get_context("2d")?
        .unwrap()
        .dyn_into::<web_sys::CanvasRenderingContext2d>()?;

    let width: f64 = canvas.width().into();
    let height: f64 = canvas.height().into();

    let countries = feature_from_name(&topology, "countries").expect("Did not extract geometry");
    let path2d = Path2d::new()?;
    let ep = PathEndpoint::new(path2d);

    let pb = PathBuilder::new(ep);

    let ortho = Orthographic::builder()
        .scale_set(width as f64 / 1.3_f64 / std::f64::consts::PI)
        .translate_set(&Coord {
            x: width / 2_f64,
            y: height / 2_f64,
        })
        .rotate2_set(&[270_f64, 00_f64])
        .build();

    let mut path = pb.build(ortho);
    context_raw.set_stroke_style(&"#333".into());
    context_raw.set_line_width(0.5);
    path.object(&countries);
    let path2d = path.context.result();
    context_raw.stroke_with_path(&path2d);

    // Graticule
    let graticule =
        generate_mls();
    context_raw.set_stroke_style(&"#ccc".into());
    path.object(&graticule);
    let path2d = path.context.result();
    context_raw.stroke_with_path(&path2d);

    Ok(())
}

Modules§

  • Area Endpoint.
  • Vector arithmetic operations on 3-D vectors.
  • Use to calculate the centroid point for a given object.
  • Related to the injection of circles into a stream.
  • Streamable Data objects.
  • Used to calculate distances on a spherical surface.
  • A graticule is a network of lines used for plotting, scaling.
  • A stream path stage.
  • Testing and debug helpers.
  • Records the last point. Useful when displaying a side projection within a main projection area. See AlbersUsa
  • Endpoint used to calculate the lengths of polygons and lines etc.
  • Mathematical constants.
  • A path builder and a collection of endpoints.
  • A stripped down version of path
  • Determines when points are located inside data objects.
  • Holds projections and associated builders.
  • Generates range of T values from start to stop by step.
  • Rotation transforms.
  • A path is a series of connected transform nodes, over which data is STREAMed.

Traits§

  • 2-D Transform common to projections and, rotations.