Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

地下埋設物を対象とした平面直角座標系への対応 #640

Merged
merged 12 commits into from
Sep 15, 2024
9 changes: 8 additions & 1 deletion nusamai-citygml/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub struct SurfaceSpan {
#[derive(Default)]
pub(crate) struct GeometryCollector {
pub vertices: indexmap::IndexSet<[u64; 3], ahash::RandomState>,
pub epsg: Option<EpsgCode>,
pub multipolygon: MultiPolygon<'static, u32>,
pub multilinestring: MultiLineString<'static, u32>,
pub multipoint: MultiPoint<'static, u32>,
Expand Down Expand Up @@ -132,8 +133,14 @@ impl GeometryCollector {
]);
}

let epsg = if let Some(epsg) = self.epsg {
epsg
} else {
EPSG_JGD2011_GEOGRAPHIC_3D
};

GeometryStore {
epsg: EPSG_JGD2011_GEOGRAPHIC_3D,
epsg,
vertices,
multipolygon: self.multipolygon,
multilinestring: self.multilinestring,
Expand Down
19 changes: 17 additions & 2 deletions nusamai-citygml/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{io::BufRead, mem, str};

use nusamai_projection::crs::EpsgCode;
use quick_xml::{
events::{BytesStart, Event},
name::{Namespace, ResolveResult::Bound},
Expand Down Expand Up @@ -514,19 +515,29 @@
lod: u8,
) -> Result<(), ParseError> {
let mut surface_id = None;
let mut epsg = None;
loop {
match self.reader.read_event_into(&mut self.state.buf1) {
Ok(Event::Start(start)) => {
let (nsres, localname) = self.reader.resolve_element(start.name());
let poly_begin = self.state.geometry_collector.multipolygon.len();

// surface id
for attr in start.attributes().flatten() {
let (nsres, localname) = self.reader.resolve_attribute(attr.key);
// surface id
if nsres == Bound(GML31_NS) && localname.as_ref() == b"id" {
let id = String::from_utf8_lossy(attr.value.as_ref()).to_string();
surface_id = Some(self.state.context.id_to_integer_id(id));
break;
}
// epsg
if localname.as_ref() == b"srsName" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q)質問でした!
parse_geometry_propメソッドを修正しているということは、gml:boudedBy.gml:EnvelopsrsNameを取得して一括で座標系を適用させる、ということではなく、全ての個別地物の座標系を取得して個別に適用させている、という認識で良いでしょうか?

Copy link
Contributor Author

@TadaTeruki TadaTeruki Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gml: EnvelopesrsNameは、全体というよりも、Envelopeそのものの空間参照系を指すattributionという認識でした。意味的には地物単体から取得するのが合理的と考えているのですが、いかがでしょうか...?

https://www.mlit.go.jp/plateaudocument

(11) エンベロープ型(gml:Envelope)
任意の次元で対向する角となる一対の位置(最小となる座標値と最大となる座標値)を用いて、矩形により範囲を定義する型。srsName属性とsrsDimension属性をもつことができる。srsName属性は、座標に使用される空間参照系を指定する。また、srsDimension属性は、座標の次元数を指定する。

Copy link
Contributor Author

@TadaTeruki TadaTeruki Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(なおデータのミスから各地物でepsgが間違っている・そもそも指定されていないものがある、という点も考慮が必要そうです。判断をお任せしてよろしいでしょうか。

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TadaTeruki 同じく地物単体から座標系を取得し、個別に適用するのが合理的と思っています!
今でも、全ての地物に対して個別にtransformをかけているので、パフォーマンスにもさほど影響はないはずですし…

その上で、以下の点を考慮する必要がありますね。

  • データのミスから各地物でepsgが間違っている
    • データが悪いため、無視
  • そもそも指定されていない
    • デフォルト値として「gml:Envelope」を取得し、設定する

これでいきましょうか!

let srsname = String::from_utf8_lossy(attr.value.as_ref()).to_string();
let epsg_head = "http://www.opengis.net/def/crs/EPSG/0/";
if srsname.starts_with(epsg_head) {
if let Some(stripped) = srsname.strip_prefix(epsg_head) {
epsg = stripped.parse::<EpsgCode>().ok();
}
}

Check warning on line 540 in nusamai-citygml/src/parser.rs

View check run for this annotation

Codecov / codecov/patch

nusamai-citygml/src/parser.rs#L540

Added line #L540 was not covered by tests
}
}

Expand Down Expand Up @@ -595,6 +606,10 @@
end: poly_end as u32,
});
}

if let Some(epsg) = epsg {
self.state.geometry_collector.epsg = Some(epsg);
}
}
}
Ok(Event::End(_)) => break,
Expand Down
Loading
Loading