Using FlatCityBuf with Rust

Table of contents

  1. Adding to your project
  2. Basic reading and spatial queries
  3. HTTP streaming

For maximum performance and control, you can use FlatCityBuf directly in Rust applications.

Adding to your project

Initialise a new Rust project:

cargo new fcb_demo
cd fcb_demo

Add FlatCityBuf to your Cargo.toml:

[dependencies]
fcb_core = "0.5.0"

# For HTTP support
fcb_core = { version = "0.5.0", features = ["http"] }

Basic reading and spatial queries

Use bounding box queries with the packed R-tree index:

use fcb_core::{FcbReader, packed_rtree::Query};
use std::fs::File;
use std::io::BufReader;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let input_file = File::open("../delft.fcb")?;
    let input_reader = BufReader::new(input_file);

    // Define bounding box
    let minx = 84227.77;
    let miny = 445377.33;
    let maxx = 85323.23;
    let maxy = 446334.69;

    let mut reader = FcbReader::open(input_reader)?.select_query(
        Query::BBox(minx, miny, maxx, maxy),
        None,
        None,
    )?;

    let mut count = 0;
    while let Some(feature_buf) = reader.next()? {
        let cj_feature = feature_buf.cur_cj_feature()?;
        println!("Feature in bbox: {}", cj_feature.id);
        count += 1;
    }

    println!("Found {} features in bounding box", count);

    Ok(())
}

then run it with:

cargo run

HTTP streaming

For cloud-based FCB files, use the async HTTP reader: Don’t forget to add tokio to your Cargo.toml:

[dependencies]
tokio = { version = "1.48.0", features = ["rt-multi-thread", "macros"] }

use fcb_core::{FcbReader, HttpFcbReader, packed_rtree::Query};
use std::fs::File;
use std::io::BufReader;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let http_reader =
        HttpFcbReader::open("https://storage.googleapis.com/flatcitybuf/3dbag_all_index.fcb")
            .await?;

    // Get header information
    let header = http_reader.header();
    println!("Features: {}", header.features_count());

    // Spatial query over HTTP
    let minx = 84227.77;
    let miny = 445377.33;
    let maxx = 85323.23;
    let maxy = 446334.69;

    let mut iter = http_reader
        .select_query(Query::BBox(minx, miny, maxx, maxy))
        .await?;

    while let Some(feature) = iter.next().await? {
        let cj_feature = feature.cj_feature()?;
        println!("Feature: {}", cj_feature.id);
    }

    Ok(())
}