Skip to content

Commit

Permalink
actual pipeline stub
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscorn committed Dec 16, 2023
1 parent 4d5a7bb commit 6927e54
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 154 deletions.
67 changes: 31 additions & 36 deletions nusamai-plateau/citygml/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,15 @@ fn generate_citygml_struct_model(
) -> Result<TokenStream, Error> {
let mut attribute_arms = Vec::new();
let mut chlid_arms = Vec::new();
let mut objectify_stmts = Vec::new();
let mut geom_objectify_expr = quote! { None };
let mut into_object_stmts = Vec::new();
let mut geom_into_object_expr = quote! { None };
let mut id_value = quote!(None);

for field in &struct_data.fields {
let Some(field_ident) = &field.ident else {
continue;
};

if field_ident == "id" {
id_value = quote! {
if let Some(id) = &self.id {
Some(id.as_ref())
} else {
None
}
};
};

let field_ty = &field.ty;
for attr in &field.attrs {
if !attr.path().is_ident(CITYGML_ATTR_IDENT) {
Expand All @@ -50,23 +40,29 @@ fn generate_citygml_struct_model(
Ok(())
}
});
objectify_stmts.push(
quote! {
if let Some(v) = self.#field_ident.objectify() {
attributes.insert(stringify!(#field_ident).into(), v);
if field_ident == "id" {
id_value = quote! {
self.id
};
} else {
into_object_stmts.push(
quote! {
if let Some(v) = self.#field_ident.into_object() {
attributes.insert(stringify!(#field_ident).into(), v);
}
}
}
)
)
}
} else {
// XML child elements (e.g. bldg:measuredHeight)
chlid_arms.push(
quote! {
#path => <#field_ty as CityGMLElement>::parse(&mut self.#field_ident, st),
}
);
objectify_stmts.push(
into_object_stmts.push(
quote! {
if let Some(v) = self.#field_ident.objectify() {
if let Some(v) = self.#field_ident.into_object() {
attributes.insert(stringify!(#field_ident).into(), v);
}
}
Expand All @@ -85,7 +81,7 @@ fn generate_citygml_struct_model(
let geomtype = format_ident!("{}", geomtype);

chlid_arms.push(quote! {
#pat => st.parse_geometric_attr(&mut self.#field_ident, #lod, ::citygml::geometric::GeometryParseType::#geomtype),
#pat => st.parse_geometric_attr(&mut self.#field_ident, #lod, ::citygml::geometry::GeometryParseType::#geomtype),
});
};

Expand All @@ -102,8 +98,8 @@ fn generate_citygml_struct_model(
add_arm(4, b"lod4Geometry", "Geometry");
add_arm(1, b"tin", "Triangulated");

geom_objectify_expr = quote! {
Some(&self.#field_ident)
geom_into_object_expr = quote! {
Some(self.#field_ident)
};

Ok(())
Expand Down Expand Up @@ -139,18 +135,17 @@ fn generate_citygml_struct_model(
})
}

fn objectify(&self) -> Option<::citygml::object::ObjectValue> {
let attributes = {
let mut attributes = ::std::collections::HashMap::new();
#(#objectify_stmts)*
attributes
};
fn into_object(self) -> Option<::citygml::object::ObjectValue> {
Some(::citygml::ObjectValue::FeatureOrData(
::citygml::FeatureOrData {
typename: stringify!(#struct_name).into(),
id: #id_value,
attributes,
geometries: #geom_objectify_expr,
attributes: {
let mut attributes = ::std::collections::HashMap::new();
#(#into_object_stmts)*
attributes
},
geometries: #geom_into_object_expr,
}
))
}
Expand All @@ -163,7 +158,7 @@ fn generate_citygml_enum_model(
enum_data: &DataEnum,
) -> Result<TokenStream, Error> {
let mut child_arms = Vec::new();
let mut objectify_arms = Vec::new();
let mut into_object_arms = Vec::new();

for variant in &enum_data.variants {
if variant.fields.len() > 1 {
Expand Down Expand Up @@ -196,8 +191,8 @@ fn generate_citygml_enum_model(
Ok(())
}
});
objectify_arms.push(quote! {
Self::#variant_ident(v) => v.objectify()
into_object_arms.push(quote! {
Self::#variant_ident(v) => v.into_object()
});
}
Ok(())
Expand All @@ -219,9 +214,9 @@ fn generate_citygml_enum_model(
})
}

fn objectify(&self) -> Option<::citygml::object::ObjectValue> {
fn into_object(self) -> Option<::citygml::object::ObjectValue> {
match self {
#(#objectify_arms,)*
#(#into_object_arms,)*
_ => None,
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use nusamai_geometry::{MultiLineString, MultiPolygon};
use nusamai_geometry::{MultiLineString, MultiPoint, MultiPolygon};

#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -39,6 +39,7 @@ pub struct Geometries {
pub vertices: Vec<[f64; 3]>,
pub multipolygon: MultiPolygon<'static, 1, u32>,
pub multilinestring: MultiLineString<'static, 1, u32>,
pub multipoint: MultiPoint<'static, 1, u32>,
}

/// Store for collecting vertices and polygons from GML.
Expand All @@ -47,6 +48,7 @@ pub struct GeometryCollector {
pub vertices: indexmap::IndexSet<[u64; 3]>,
pub multipolygon: MultiPolygon<'static, 1, u32>,
pub multilinestring: MultiLineString<'static, 1, u32>,
pub multipoint: MultiPoint<'static, 1, u32>,
}

impl GeometryCollector {
Expand All @@ -70,7 +72,7 @@ impl GeometryCollector {
}));
}

pub fn to_geometries(&self) -> Geometries {
pub fn into_geometries(self) -> Geometries {
let mut vertices = Vec::with_capacity(self.vertices.len());
for vbits in &self.vertices {
vertices.push([
Expand All @@ -81,14 +83,9 @@ impl GeometryCollector {
}
Geometries {
vertices,
multipolygon: self.multipolygon.clone(),
multilinestring: self.multilinestring.clone(),
multipolygon: self.multipolygon,
multilinestring: self.multilinestring,
multipoint: self.multipoint,
}
}

pub fn clear(&mut self) {
self.vertices.clear();
self.multipolygon.clear();
self.multilinestring.clear();
}
}
6 changes: 3 additions & 3 deletions nusamai-plateau/citygml/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pub mod geometric;
pub mod geometry;
pub mod namespace;
pub mod object;
pub mod parser;
pub mod values;

pub use geometric::*;
pub use geometry::*;
pub use namespace::*;
pub use object::*;
pub use parser::*;
Expand All @@ -15,5 +15,5 @@ pub use macros::CityGMLElement;
pub trait CityGMLElement: Sized {
fn parse<R: std::io::BufRead>(&mut self, st: &mut SubTreeReader<R>) -> Result<(), ParseError>;

fn objectify(&self) -> Option<ObjectValue>;
fn into_object(self) -> Option<ObjectValue>;
}
35 changes: 18 additions & 17 deletions nusamai-plateau/citygml/src/object.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
//! Objectify CityGML features and their thematic/geometric attributes
//! Objectified representation of the city objects.

use crate::geometric::GeometryRef;
use crate::geometry::GeometryRef;
use crate::values::{Code, Point, URI};
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug)]
pub struct FeatureOrData<'a> {
pub typename: &'a str,
pub id: Option<&'a str>,
pub attributes: HashMap<String, ObjectValue<'a>>,
pub geometries: Option<&'a GeometryRef>,
#[derive(Debug, Serialize, Deserialize)]
pub struct FeatureOrData {
pub typename: String,
pub id: Option<String>,
pub attributes: HashMap<String, ObjectValue>,
pub geometries: Option<GeometryRef>,
}

#[derive(Debug)]
pub enum ObjectValue<'a> {
String(&'a str),
Code(&'a Code),
#[derive(Debug, Serialize, Deserialize)]
pub enum ObjectValue {
String(String),
Code(Code),
Integer(i64),
Double(f64),
Measure(f64),
Boolean(bool),
URI(&'a URI),
Date(&'a NaiveDate),
Point(&'a Point),
Array(Vec<ObjectValue<'a>>),
FeatureOrData(FeatureOrData<'a>),
URI(URI),
Date(NaiveDate),
Point(Point),
Array(Vec<ObjectValue>),
FeatureOrData(FeatureOrData),
}
13 changes: 9 additions & 4 deletions nusamai-plateau/citygml/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::geometric::{
use crate::geometry::{
Geometries, GeometryCollector, GeometryParseType, GeometryRef, GeometryRefEntry, GeometryType,
};
use crate::namespace::normalize_ns_prefix;
Expand Down Expand Up @@ -68,12 +68,18 @@ impl CityGMLReader {
state.path_buf.push(b'/');
state.path_buf.extend(normalize_ns_prefix(&nsres));
state.path_buf.extend(localname.as_ref());
state.current_start = Some(start.into_owned());
return Ok(SubTreeReader {
reader,
state,
path_start: 0,
});
}
Ok(Event::Eof) => {
return Err(ParseError::XmlError(quick_xml::Error::UnexpectedEof(
"Unexpected EOF".into(),
)))
}
Ok(_) => (),
Err(e) => return Err(e.into()),
}
Expand Down Expand Up @@ -214,9 +220,8 @@ impl<R: BufRead> SubTreeReader<'_, R> {
}

pub fn collect_geometries(&mut self) -> Geometries {
let geometries: Geometries = self.state.geometry_collector.to_geometries();
self.state.geometry_collector.clear();
geometries
let collector = std::mem::take(&mut self.state.geometry_collector);
collector.into_geometries()
}

/// Expect a geometric attribute of CityGML
Expand Down
Loading

0 comments on commit 6927e54

Please sign in to comment.