rstiff 0.2.0

A Rust library for high-precision, type-preserving GeoTiff I/O powered by GDAL.
///! 矢量文件窗口读取示例
///!
///! 展示如何根据 KML/Shapefile/GeoJSON 范围直接读取栅格数据,
///! 而不需要先加载整个文件再裁剪。
///!
///! 运行方式:
///! ```bash
///! cargo run --example vector_window_read
///! ```
use rstiff::GeoTiff;
use std::error::Error;
use std::path::Path;

fn main() -> Result<(), Box<dyn Error>> {
    let raster_path = Path::new("./data/Hawaiin_part.tif");
    let vector_path = Path::new("./data/hilo.kml"); // 或 .shp, .geojson

    // 检查文件存在
    if !raster_path.exists() {
        println!("请准备 ./data/Hawaiin_part.tif 文件");
        return Ok(());
    }
    if !vector_path.exists() {
        println!("请准备 ./data/test.kml 文件(或其他矢量文件)");
        println!("提示: 你可以使用 Google Earth 绘制一个多边形并导出为 KML");
        return Ok(());
    }

    // ============================================================
    // 方法1: read_by_vector (推荐 - 大文件优化)
    // ============================================================
    // 只读取矢量范围内的数据,不加载整个栅格
    // 这是处理大文件的最佳方式

    println!("=== 使用 read_by_vector (窗口化读取) ===");
    println!("栅格: {:?}", raster_path);
    println!("矢量: {:?}", vector_path);

    // apply_mask = true: 多边形外的像素设为 NoData
    // apply_mask = false: 只按矩形范围裁剪,不应用掩膜
    let roi = GeoTiff::read_by_vector(raster_path, vector_path, true)?;

    println!("读取成功!");
    println!("  数据尺寸: {:?}", roi.data.dim());
    println!("  NoData 值: {:?}", roi.nodata);
    println!(
        "  左上角坐标: ({:.6}, {:.6})",
        roi.geo_transform[0], roi.geo_transform[3]
    );

    // 保存结果
    let output = Path::new("./data/vector_window_output.tif");
    roi.write(output)?;
    println!("已保存到: {:?}", output);

    // ============================================================
    // 对比: crop_by_vector (传统方式)
    // ============================================================
    // 先加载整个文件,再裁剪
    // 对于小文件这种方式也可以,但大文件会消耗更多内存

    println!("\n=== 对比: crop_by_vector (传统方式) ===");
    println!("步骤1: 加载整个栅格文件...");
    let full_tif = GeoTiff::read(raster_path)?;
    println!("  完整尺寸: {:?}", full_tif.data.dim());

    println!("步骤2: 按矢量裁剪...");
    let cropped = full_tif.crop_by_vector(vector_path, true)?;
    println!("  裁剪后尺寸: {:?}", cropped.data.dim());

    // ============================================================
    // 内存对比
    // ============================================================
    println!("\n=== 内存使用对比 ===");

    let (bands, h, w) = full_tif.data.dim();
    let full_mem = bands * h * w * 8; // f64 = 8 bytes

    let (bands2, h2, w2) = roi.data.dim();
    let roi_mem = bands2 * h2 * w2 * 8;

    println!("传统方式 (crop_by_vector):");
    println!("  需要先加载: {:.2} MB", full_mem as f64 / 1024.0 / 1024.0);
    println!("  裁剪后保留: {:.2} MB", roi_mem as f64 / 1024.0 / 1024.0);

    println!("\n窗口读取 (read_by_vector):");
    println!("  直接读取: {:.2} MB", roi_mem as f64 / 1024.0 / 1024.0);
    println!(
        "  内存峰值减少: {:.1}%",
        (1.0 - roi_mem as f64 / full_mem as f64) * 100.0
    );

    println!("\n完成!");
    Ok(())
}