From cba397a08c0174e93f666cf7180b5ab65bd0df61 Mon Sep 17 00:00:00 2001 From: Austin Gill Date: Sat, 26 Nov 2022 13:23:43 -0600 Subject: [PATCH] WIP: Start brainstorming transform tool --- Cargo.toml | 4 +++ tools/transform/cmdline.rs | 67 ++++++++++++++++++++++++++++++++++++++ tools/transform/main.rs | 36 ++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 tools/transform/cmdline.rs create mode 100644 tools/transform/main.rs diff --git a/Cargo.toml b/Cargo.toml index beb676b..517c0c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,10 @@ path = "tools/dla/main.rs" name = "point-cloud" path = "tools/point-cloud/main.rs" +[[bin]] +name = "transform" +path = "tools/transform/main.rs" + [dependencies] clap = {version="4.0", features=["derive"]} geo = "0.23" diff --git a/tools/transform/cmdline.rs b/tools/transform/cmdline.rs new file mode 100644 index 0000000..529932e --- /dev/null +++ b/tools/transform/cmdline.rs @@ -0,0 +1,67 @@ +use clap::{Parser, ValueEnum}; +use std::path::PathBuf; + +#[derive(Debug, Clone, ValueEnum)] +pub enum GeometryFormat { + Wkt, + WkbHex, +} + +#[derive(Debug, Clone, ValueEnum)] +pub enum Projection { + Xy, + Xz, + Yz, + Pca, + Svd, + Identity, + Isometric, +} + +/// Perform transformations on geometries +#[derive(Debug, Parser)] +#[clap(name = "transform")] +pub struct CmdlineOptions { + /// Increase logging verbosity. Defaults to ERROR level. + #[clap(short, long, action = clap::ArgAction::Count)] + pub verbosity: u8, + + /// Output file to write result to. Defaults to stdout. + #[clap(short, long)] + pub output: Option, + + /// Output geometry format. + #[clap(short = 'O', long, default_value = "wkt")] + pub output_format: GeometryFormat, + + /// Input file to read input from. Defaults to stdin. + #[clap(short, long)] + pub input: Option, + + /// Input geometry format. + #[clap(short = 'I', long, default_value = "wkt")] + pub input_format: GeometryFormat, + + /// CCW rotation, in degrees. + #[clap(short, long, default_value = "0.0")] + pub rotation: f64, + + /// Additive offset in the x direction + #[clap(long, default_value = "0.0")] + pub x_offset: f64, + + /// Additive offset in the y direction + #[clap(long, default_value = "0.0")] + pub y_offset: f64, + + /// Multiplicative scale in the x direction + #[clap(short, long, default_value = "1.0")] + pub x_scale: f64, + + /// Multiplicative scale in the y direction + #[clap(short, long, default_value = "1.0")] + pub y_scale: f64, + + // TODO: Add projections + // pub projection: Projection, +} diff --git a/tools/transform/main.rs b/tools/transform/main.rs new file mode 100644 index 0000000..9d68537 --- /dev/null +++ b/tools/transform/main.rs @@ -0,0 +1,36 @@ +mod cmdline; + +use clap::Parser; +use generative::stdio::{get_input_reader, get_output_writer}; +use generative::wkio::{read_wkt_geometries, write_wkt_geometries}; +use stderrlog::ColorChoice; + +fn main() { + let args = cmdline::CmdlineOptions::parse(); + + stderrlog::new() + .verbosity(args.verbosity as usize + 1) // Default to WARN level. + .color(ColorChoice::Auto) + .init() + .expect("Failed to initialize stderrlog"); + + let writer = get_output_writer(args.output).unwrap(); + let reader = get_input_reader(args.input).unwrap(); + + let geometries = read_wkt_geometries(reader); + write_wkt_geometries(writer, geometries); + + // TODO: I don't think there needs to be any flattening + // * linear transforms can be done with the MapCoordsInplace trait on-the-fly + // * projections can be done by collecting CoordsIter into an array, performing the projection, + // and running back over the geometries with MapCoordsInplace to replace the coordinates. + // In either case, I don't think there needs to be a recursive flattener, or a flattened and + // tagged point array. + + // TODO: Describe the offset, scale, and rotate as a linear transformation. + // TODO: Determe if it's more efficient (with my problem size) to do it on-the-fly or all at once. + // TODO: Perhaps allow switching between buffered and dynamic approaches? Or perhaps chunk the + // transformations? + // TODO: Projections + // TODO: WKB I/O +}