Skip to content

Commit

Permalink
extended citygml data structures
Browse files Browse the repository at this point in the history
  • Loading branch information
benediktschwab committed Aug 5, 2024
1 parent 60bad3a commit ebb45d2
Show file tree
Hide file tree
Showing 42 changed files with 2,284 additions and 672 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ on:
pull_request: {}


env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10
RUST_BACKTRACE: short


jobs:

build:
Expand Down
13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,24 @@ members = [
resolver = "2"

[workspace.package]
version = "0.0.1-alpha.3"
version = "0.0.1-alpha.4"
authors = ["Benedikt Schwab <benedikt.schwab@gmail.com>"]
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/envis-space/ecitygml"

[workspace.dependencies]
egml = { version = "0.0.1-alpha.3" }
egml = { version = "0.0.1-alpha.4" }

thiserror = "1.0.61"
clap = "4.5.9"
thiserror = "1.0.63"
clap = "4.5.13"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
nalgebra = "0.33.0"
serde = "1.0.204"
serde_yaml = "0.9"
quick-xml = "0.36.0"
quick-xml = "0.36.1"
itertools = "0.13.0"
rayon = "1.10.0"
walkdir = "2.5.0"
uuid = "1.3.2"
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

A Rust library for processing [CityGML](https://www.ogc.org/standard/citygml/) data.

> [!WARNING]
> The library is at an early stage of development.
The library is at an early stage of development.

## Contributing

Expand Down
3 changes: 2 additions & 1 deletion crates/ecitygml-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ repository.workspace = true
description = "CLI tool for processing CityGML data."

[dependencies]
ecitygml = { version = "0.0.1-alpha.3", path = "../ecitygml" }
ecitygml = { version = "0.0.1-alpha.4", path = "../ecitygml" }

egml = { workspace = true }

clap = { workspace = true, features = ["derive"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
nalgebra = { workspace = true }
walkdir = { workspace = true }
3 changes: 1 addition & 2 deletions crates/ecitygml-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

CLI tool for processing [CityGML](https://www.ogc.org/standard/citygml/) data.

> [!WARNING]
> The library is at an early stage of development.
The library is at an early stage of development.

## Contributing

Expand Down
223 changes: 176 additions & 47 deletions crates/ecitygml-cli/src/commands/statistics.rs
Original file line number Diff line number Diff line change
@@ -1,102 +1,231 @@
use ecitygml::io::{FILE_EXTENSION_CITYGML_GML_FORMAT, FILE_EXTENSION_CITYGML_XML_FORMAT};
use ecitygml::model::construction::{GroundSurface, RoofSurface, WallSurface};
use ecitygml::model::core::{OccupiedSpace, Space, ThematicSurface};
use ecitygml::operations::FeatureWithGeometry;
use std::path::Path;

use std::time::Instant;
use tracing::info;
use walkdir::WalkDir;

pub fn run(path: impl AsRef<Path>) {
info!("Creating statistics for: {}", path.as_ref().display());

if path.as_ref().is_file() {
print_citygml_model_statistics(path);
} else if path.as_ref().is_dir() {
for entry in WalkDir::new(path)
.sort_by(|a, b| a.file_name().cmp(b.file_name()))
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.file_type().is_file() && e.path().extension().is_some())
.filter(|e| {
e.path().extension().expect("must have an extension")
== FILE_EXTENSION_CITYGML_GML_FORMAT
|| e.path().extension().expect("must have an extension")
== FILE_EXTENSION_CITYGML_XML_FORMAT
})
{
info!("Start reading: {:?}", entry);
let now = Instant::now();
let citygml_model = ecitygml::io::CitygmlReader::from_path(entry.into_path())
.unwrap()
.finish()
.unwrap();
info!("Read model in {:.3?}", now.elapsed());
}
}
}

pub fn run(file_path: impl AsRef<Path>) {
fn print_citygml_model_statistics(file_path: impl AsRef<Path>) {
let now = Instant::now();
let citygml_model = ecitygml::io::CitygmlReader::from_path(file_path)
.unwrap()
.finish()
.unwrap();
info!("Read model in {:.3?}", now.elapsed());

info!(
"Number of city objects: {}\n",
citygml_model.number_of_objects()
);

let envelope = citygml_model.envelope().unwrap();
info!(
"Envelope: lower corner{}, upper corner {}\n",
envelope.lower_corner(),
envelope.upper_corner()
);

info!("Total Building: {}", citygml_model.building.len());
let wall_surfaces: Vec<&WallSurface> = citygml_model
.building
.iter()
.flat_map(|x| &x.wall_surface)
.collect();
info!("Total WallSurface: {}", wall_surfaces.len());
if !wall_surfaces.is_empty() {
print_statistics_thematic_surface(
wall_surfaces.iter().map(|x| &x.thematic_surface).collect(),
);
}

let roof_surfaces: Vec<&RoofSurface> = citygml_model
.building
.iter()
.flat_map(|x| &x.roof_surface)
.collect();
info!("Total RoofSurface: {}", roof_surfaces.len());
if !roof_surfaces.is_empty() {
print_statistics_thematic_surface(
roof_surfaces.iter().map(|x| &x.thematic_surface).collect(),
);
}

let ground_surfaces: Vec<&GroundSurface> = citygml_model
.building
.iter()
.flat_map(|x| &x.ground_surface)
.collect();
info!("Total GroundSurface: {}", ground_surfaces.len());
if !ground_surfaces.is_empty() {
print_statistics_thematic_surface(
ground_surfaces
.iter()
.map(|x| &x.thematic_surface)
.collect(),
);
}

info!(
"Total CityFurniture: {}",
citygml_model.city_furniture().len()
citygml_model.city_furniture.len()
);
if !citygml_model.city_furniture.is_empty() {
print_statistics_occupied_space(
citygml_model
.city_furniture
.iter()
.map(|x| &x.occupied_space)
.collect(),
);
}

info!("Total Road: {}", citygml_model.road.len());

info!(
"\t- with lod1_solid: {}",
citygml_model
.city_furniture()
"Total SolitaryVegetationObject: {}",
citygml_model.solitary_vegetation_object.len()
);
if !citygml_model.solitary_vegetation_object.is_empty() {
print_statistics_occupied_space(
citygml_model
.solitary_vegetation_object
.iter()
.map(|x| &x.occupied_space)
.collect(),
);
}

/*info!("Offset city model");
let translation = nalgebra::Vector3::new(-678071.2478652871, -5403609.8367785765, -415.28);
let isometry = Isometry3::new(translation, Default::default());
citygml_model.apply_transform(&isometry);
info!(
"Number of city objects: {}",
citygml_model.number_of_objects()
);*/
}

fn print_statistics_occupied_space(occupied_space: Vec<&OccupiedSpace>) {
info!(
"\t- with lod1_implicit_representation: {}",
occupied_space
.iter()
.filter(|c| c.lod1_solid().is_some())
.filter(|x| x.lod1_implicit_representation.is_some())
.count()
);
info!(
"\t- with lod2_solid: {}",
citygml_model
.city_furniture()
"\t- with lod2_implicit_representation: {}",
occupied_space
.iter()
.filter(|c| c.lod2_solid().is_some())
.filter(|x| x.lod2_implicit_representation.is_some())
.count()
);
info!(
"\t- with lod2_multi_surface: {}",
citygml_model
.city_furniture()
"\t- with lod3_implicit_representation: {}",
occupied_space
.iter()
.filter(|c| c.lod2_multi_surface().is_some())
.filter(|x| x.lod3_implicit_representation.is_some())
.count()
);

print_statistics_space(occupied_space.iter().map(|x| &x.space).collect());
}

fn print_statistics_space(space: Vec<&Space>) {
info!(
"\t- with lod1_solid: {}",
space.iter().filter(|x| x.lod1_solid.is_some()).count()
);
info!(
"\t- with lod2_solid: {}",
space.iter().filter(|x| x.lod2_solid.is_some()).count()
);
info!(
"\t- with reference_point: {}",
citygml_model
.city_furniture()
"\t- with lod3_solid: {}",
space.iter().filter(|x| x.lod3_solid.is_some()).count()
);

info!(
"\t- with lod0_multi_surface: {}",
space
.iter()
.filter(|c| c.reference_point().is_some())
.filter(|x| x.lod0_multi_surface.is_some())
.count()
);

info!("Total TrafficArea: {}", citygml_model.traffic_area().len());
info!(
"\t- with lod2_multi_surface: {}",
citygml_model
.traffic_area()
space
.iter()
.filter(|x| x.lod2_multi_surface.is_some())
.count()
);
info!(
"\t- with lod3_multi_surface: {}",
space
.iter()
.filter(|c| c.lod2_multi_surface().is_some())
.filter(|x| x.lod3_multi_surface.is_some())
.count()
);
}

fn print_statistics_thematic_surface(thematic_surface: Vec<&ThematicSurface>) {
info!(
"Total SolitaryVegetationObject: {}",
citygml_model.solitary_vegetation_object().len()
"\t- with lod0_multi_surface: {}",
thematic_surface
.iter()
.filter(|x| x.lod0_multi_surface.is_some())
.count()
);
info!(
"\t- with lod1_solid: {}",
citygml_model
.solitary_vegetation_object()
"\t- with lod1_multi_surface: {}",
thematic_surface
.iter()
.filter(|c| c.lod1_solid().is_some())
.filter(|x| x.lod1_multi_surface.is_some())
.count()
);

info!("Total WallSurface: {}", citygml_model.wall_surface().len());
info!(
"\t- with lod2_multi_surface: {}",
citygml_model
.wall_surface()
thematic_surface
.iter()
.filter(|c| c.lod2_multi_surface().is_some())
.filter(|x| x.lod2_multi_surface.is_some())
.count()
);
info!(
"\t- with lod3_multi_surface: {}",
citygml_model
.wall_surface()
thematic_surface
.iter()
.filter(|c| c.lod3_multi_surface().is_some())
.filter(|x| x.lod3_multi_surface.is_some())
.count()
);

info!("Offset city model");
let offset = nalgebra::Vector3::new(-678071.2478652871, -5403609.8367785765, -415.28);
let transformed_citygml_model =
ecitygml::transform::offset::offset_citygml_model(citygml_model, &offset).unwrap();
info!(
"Number of city objects: {}",
transformed_citygml_model.number_of_objects()
);
}
1 change: 1 addition & 0 deletions crates/ecitygml-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ egml = { workspace = true }

thiserror = { workspace = true }
nalgebra = { workspace = true }
rayon = { workspace = true }
# parry3d-f64 = { workspace = true, features = ["f64"] }
3 changes: 1 addition & 2 deletions crates/ecitygml-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

Core primitives and operations for processing [CityGML](https://www.ogc.org/standard/citygml/) data.

> [!WARNING]
> The library is at an early stage of development.
The library is at an early stage of development.

## Contributing

Expand Down
19 changes: 3 additions & 16 deletions crates/ecitygml-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
mod error;
mod model;

#[doc(inline)]
pub use model::city_model::CitygmlModel;

#[doc(inline)]
pub use model::city_furniture::CityFurniture;

#[doc(inline)]
pub use model::transportation::TrafficArea;

#[doc(inline)]
pub use model::solitary_vegetation_object::SolitaryVegetationObject;

#[doc(inline)]
pub use model::construction::WallSurface;
pub mod model;
pub mod operations;
pub mod util;

#[doc(inline)]
pub use error::Error;
Loading

0 comments on commit ebb45d2

Please sign in to comment.