From 396f1a1032608bd179346c949a5167505f81c468 Mon Sep 17 00:00:00 2001 From: Sorami Hisamoto Date: Tue, 19 Dec 2023 15:48:36 +0900 Subject: [PATCH] =?UTF-8?q?nusamai-geosjon:=20=E3=83=88=E3=83=83=E3=83=97?= =?UTF-8?q?=E3=83=AC=E3=83=99=E3=83=AB=E9=83=BD=E5=B8=82=E3=82=AA=E3=83=96?= =?UTF-8?q?=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88=E3=82=92=E5=A4=89=E6=8F=9B?= =?UTF-8?q?=EF=BC=88=E3=82=B8=E3=82=AA=E3=83=A1=E3=83=88=E3=83=AA=E3=81=AE?= =?UTF-8?q?=E3=81=BF=EF=BC=89=20(#79)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #62 - 従来のコードは、 `nusamai-geometry` の Geometryを直接扱って、変換していた - → 「トップレベル都市オブジェクト」を入力として、GeoJSONへの変換処理を行う - #78 で用意されたものを利用している `Geometries` にある `multipolygon`, `multilinestring`, `multipoint` 、それぞれをFeatureにしている。 - [x] 変換処理の書き換え - `nusamai-geojson/src/conversion.rs` - `nusamai-geojson/src/lib.rs` - [x] CityGMLファイルをパースしてGeoJSONを出力するexampleの追加 - `nusamai-geojson/examples/gml2geojson.rs` - その他 - [x] Tauri側の暫定処理を、この変更に合わせて修正: `app/src-tauri/*` - [x] いにしえのパースexampleの削除: `nusamai-geojson/examples/citygml_polygons.rs` 属性はこのPRでは考慮していない。 トップレベル都市オブジェクトの ` cityobj: FeatureOrData<'a>` を扱う必要がある。 別途対応する #46 --- app/src-tauri/src/example.rs | 40 +++++++++++++++++++++++-- nusamai-geojson/Cargo.toml | 4 +-- nusamai-geojson/examples/gml2geojson.rs | 6 ++-- nusamai-geojson/src/lib.rs | 23 ++++---------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/app/src-tauri/src/example.rs b/app/src-tauri/src/example.rs index 1477bad12..30a9279ed 100644 --- a/app/src-tauri/src/example.rs +++ b/app/src-tauri/src/example.rs @@ -1,13 +1,50 @@ //! デモ用 //! nusamai-geojson の exmaple/gml2geojson を元にした、暫定的な処理 +//! nusamai-geojson の exmaple/gml2geojson を元にした、暫定的な処理 +use citygml::{CityGMLElement, CityGMLReader, ParseError, SubTreeReader}; +use nusamai_geojson::toplevel_cityobj_to_geojson_features; +use nusamai_plateau::TopLevelCityObject; use citygml::{CityGMLElement, CityGMLReader, ParseError, SubTreeReader}; use nusamai_geojson::toplevel_cityobj_to_geojson_features; use nusamai_plateau::TopLevelCityObject; use std::fs; use std::io::BufRead; +use std::io::BufRead; use std::io::BufWriter; +fn toplevel_dispatcher( + st: &mut SubTreeReader, +) -> Result, ParseError> { + let mut cityobjs: Vec = vec![]; + + match st.parse_children(|st| match st.current_path() { + b"core:cityObjectMember" => { + let mut cityobj: nusamai_plateau::models::TopLevelCityObject = Default::default(); + cityobj.parse(st)?; + let geometries = st.collect_geometries(); + + if let Some(root) = cityobj.into_object() { + let obj = TopLevelCityObject { root, geometries }; + cityobjs.push(obj); + } + + Ok(()) + } + b"gml:boundedBy" | b"app:appearanceMember" => { + st.skip_current_element()?; + Ok(()) + } + other => Err(ParseError::SchemaViolation(format!( + "Unrecognized element {}", + String::from_utf8_lossy(other) + ))), + }) { + Ok(_) => Ok(cityobjs), + Err(e) => { + println!("Err: {:?}", e); + Err(e) + fn toplevel_dispatcher( st: &mut SubTreeReader, ) -> Result, ParseError> { @@ -47,8 +84,7 @@ pub fn citygml_to_geojson(input_path: &str, output_path: &str) { let reader = std::io::BufReader::new(std::fs::File::open(input_path).unwrap()); let mut xml_reader = quick_xml::NsReader::from_reader(reader); - let context = citygml::ParseContext::default(); - let cityobjs = match CityGMLReader::new(context).start_root(&mut xml_reader) { + let cityobjs = match CityGMLReader::new().start_root(&mut xml_reader) { Ok(mut st) => match toplevel_dispatcher(&mut st) { Ok(items) => items, Err(e) => panic!("Err: {:?}", e), diff --git a/nusamai-geojson/Cargo.toml b/nusamai-geojson/Cargo.toml index 5cfcd9f59..8bc5378b6 100644 --- a/nusamai-geojson/Cargo.toml +++ b/nusamai-geojson/Cargo.toml @@ -9,9 +9,9 @@ edition = "2021" geojson = "0.24.1" nusamai-geometry = { path = "../nusamai-geometry" } nusamai-plateau = { path = "../nusamai-plateau" } -citygml = {path = "../nusamai-plateau/citygml" } -serde_json = "1.0.108" [dev-dependencies] +citygml = {path = "../nusamai-plateau/citygml" } clap = { version = "4.4.8", features = ["derive"] } quick-xml = "0.31.0" +serde_json = "1.0.108" \ No newline at end of file diff --git a/nusamai-geojson/examples/gml2geojson.rs b/nusamai-geojson/examples/gml2geojson.rs index d2e46c767..ef98a9a9e 100644 --- a/nusamai-geojson/examples/gml2geojson.rs +++ b/nusamai-geojson/examples/gml2geojson.rs @@ -3,6 +3,7 @@ use citygml::{CityGMLElement, CityGMLReader, ParseError, SubTreeReader}; use clap::Parser; use nusamai_geojson::toplevel_cityobj_to_geojson_features; +use nusamai_plateau::models::CityObject; use nusamai_plateau::TopLevelCityObject; use std::fs; use std::io::BufRead; @@ -21,7 +22,7 @@ fn toplevel_dispatcher( match st.parse_children(|st| match st.current_path() { b"core:cityObjectMember" => { - let mut cityobj: nusamai_plateau::models::TopLevelCityObject = Default::default(); + let mut cityobj: CityObject = Default::default(); cityobj.parse(st)?; let geometries = st.collect_geometries(); @@ -55,8 +56,7 @@ fn main() { let reader = std::io::BufReader::new(std::fs::File::open(args.filename).unwrap()); let mut xml_reader = quick_xml::NsReader::from_reader(reader); - let context = citygml::ParseContext::default(); - let cityobjs = match CityGMLReader::new(context).start_root(&mut xml_reader) { + let cityobjs = match CityGMLReader::new().start_root(&mut xml_reader) { Ok(mut st) => match toplevel_dispatcher(&mut st) { Ok(items) => items, Err(e) => panic!("Err: {:?}", e), diff --git a/nusamai-geojson/src/lib.rs b/nusamai-geojson/src/lib.rs index 54d1ff52d..ee3c7877a 100644 --- a/nusamai-geojson/src/lib.rs +++ b/nusamai-geojson/src/lib.rs @@ -1,21 +1,10 @@ mod conversion; -use citygml::attribute_to_json; + use conversion::{ multilinestring_to_geojson_geometry, multipoint_to_geojson_geometry, multipolygon_to_geojson_geometry, }; use nusamai_plateau::TopLevelCityObject; -use serde_json::Value; - -fn extract_attributes(obj: &TopLevelCityObject) -> serde_json::Map { - let mut attributes = serde_json::Map::new(); - - if let citygml::ObjectValue::FeatureOrData(fod) = &obj.root { - let a = attribute_to_json(fod); - attributes = a.as_object().unwrap().clone(); - } - attributes -} /// Create GeoJSON features from a TopLevelCityObject /// Each feature for MultiPolygon, MultiLineString, and MultiPoint will be created (if it exists) @@ -23,19 +12,17 @@ fn extract_attributes(obj: &TopLevelCityObject) -> serde_json::Map Vec { let mut geojson_features: Vec = vec![]; - let attributes = extract_attributes(obj); if !obj.geometries.multipolygon.is_empty() { let mpoly_geojson_geom = multipolygon_to_geojson_geometry( &obj.geometries.vertices, &obj.geometries.multipolygon, ); - let mpoly_geojson_feat = geojson::Feature { bbox: None, geometry: Some(mpoly_geojson_geom), id: None, - properties: Some(attributes.clone().into_iter().collect()), + properties: None, // TODO: from `obj.root` foreign_members: None, }; geojson_features.push(mpoly_geojson_feat); @@ -50,7 +37,7 @@ pub fn toplevel_cityobj_to_geojson_features(obj: &TopLevelCityObject) -> Vec Vec