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

MVT Sink の初期実装 #163

Merged
merged 20 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ members = [
"nusamai",
]
resolver = "2"

[profile.release]
lto = true
panic = "abort"
codegen-units = 1
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
- [`macros`](./nusamai-plateau/citygml/macros/) — パーサ導出用の proc macros
- 変換先形式のためのライブラリ:
- [`nusamai-3dtiles`](./nusamai-3dtiles/) — 3D Tiles
- [`nusamai-mvt`](./nusamai-mvt/) — Mapbox Vector Tile (MVT)
- [`nusamai-mvt`](./nusamai-mvt/) — Mapbox Vector Tiles (MVT)
- [`nusamai-gpkg`](./nusamai-gpkg/) — GeoPackage
- [`nusamai-gltf`](./nusamai-gltf/) — glTF
- [`nusamai-geojson`](./nusamai-geojson/) — GeoJSON
Expand Down
6 changes: 3 additions & 3 deletions app/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::sync::{Arc, Mutex};
use nusamai::pipeline::Canceller;
use nusamai::sink::DataSinkProvider;
use nusamai::sink::{
geojson::GeoJsonSinkProvider, gpkg::GpkgSinkProvider, serde::SerdeSinkProvider,
tiling2d::Tiling2DSinkProvider,
geojson::GeoJsonSinkProvider, gpkg::GpkgSinkProvider, mvt::MVTSinkProvider,
serde::SerdeSinkProvider,
};
use nusamai::source::citygml::CityGMLSourceProvider;
use nusamai::source::DataSourceProvider;
Expand Down Expand Up @@ -52,7 +52,7 @@ fn run(input_path: String, output_path: String, filetype: String) {
"GeoJSON" => Box::new(GeoJsonSinkProvider {}),
"GeoPackage" => Box::new(GpkgSinkProvider {}),
"Serde" => Box::new(SerdeSinkProvider {}),
"Tiling2D" => Box::new(Tiling2DSinkProvider {}),
"Vector Tiles" => Box::new(MVTSinkProvider {}),
_ => {
log::error!("Unknown filetype: {}", filetype);
return;
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const fileTypeOptions = ['GeoJSON', 'GeoPackage', 'Serde', 'Tiling2D'];
const fileTypeOptions = ['GeoJSON', 'GeoPackage', 'Serde', 'Vector Tiles'];

const crsOptions = [
{ value: 'EPSG:6678', label: 'JGD2011 / Japan Plane Rectangular CS X' },
Expand Down
2 changes: 1 addition & 1 deletion nusamai-citygml/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub enum GeometryType {
}

#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Debug, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub struct GeometryRefEntry {
#[serde(rename = "type")]
pub ty: GeometryType,
Expand Down
6 changes: 3 additions & 3 deletions nusamai-citygml/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ pub struct CityObject {
pub geometries: geometry::GeometryStore,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Feature {
pub typename: Cow<'static, str>,
pub id: Option<String>,
pub attributes: Map,
pub geometries: Option<GeometryRef>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Data {
pub typename: Cow<'static, str>,
pub attributes: Map,
}

/// Nodes for the "Object" representation of the city object.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Value {
String(String),
Code(Code),
Expand Down
8 changes: 4 additions & 4 deletions nusamai-citygml/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl CityGMLElement for String {
}
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Default, PartialEq, Eq)]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default, PartialEq, Eq)]
pub struct URI(String);

impl URI {
Expand All @@ -56,7 +56,7 @@ impl CityGMLElement for URI {
}
}

#[derive(Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Code {
value: String,
code: String,
Expand Down Expand Up @@ -210,7 +210,7 @@ impl CityGMLElement for bool {
}
}

#[derive(Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Measure {
pub value: f64,
// pub uom: Option<String>,
Expand Down Expand Up @@ -262,7 +262,7 @@ impl CityGMLElement for Date {
}
}

#[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
pub struct Point {
// TODO
}
Expand Down
8 changes: 4 additions & 4 deletions nusamai-geojson/src/conversion.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use nusamai_geometry::{CoordNum, MultiLineString, MultiPoint, MultiPolygon};

/// Create a GeoJSON MultiPolygon from `nusamai_geometry::MultiPolygon`.
pub fn multipolygon_to_geometry(mpoly: &MultiPolygon<3>) -> geojson::Geometry {
pub fn multipolygon_to_geometry<const D: usize>(mpoly: &MultiPolygon<D>) -> geojson::Geometry {
multipolygon_to_geometry_with_mapping(mpoly, |c| c.to_vec())
}

Expand All @@ -16,7 +16,7 @@ pub fn indexed_multipolygon_to_geometry(
/// Create a GeoJSON MultiPolygon from `nusamai_geometry::MultiPolygon` with a mapping function.
pub fn multipolygon_to_geometry_with_mapping<const D: usize, T: CoordNum>(
mpoly: &MultiPolygon<D, T>,
mapping: impl Fn(&[T]) -> Vec<f64>,
mapping: impl Fn([T; D]) -> Vec<f64>,
) -> geojson::Geometry {
let coords: Vec<geojson::PolygonType> = mpoly
.iter()
Expand Down Expand Up @@ -49,7 +49,7 @@ pub fn indexed_multilinestring_to_geometry(
/// Create a GeoJSON MultiLineString from `nusamai_geometry::MultiPolygon` with a mapping function.
pub fn multilinestring_to_geometry_with_mapping<const D: usize, T: CoordNum>(
mls: &MultiLineString<D, T>,
mapping: impl Fn(&[T]) -> Vec<f64>,
mapping: impl Fn([T; D]) -> Vec<f64>,
) -> geojson::Geometry {
let coords = mls
.iter()
Expand Down Expand Up @@ -79,7 +79,7 @@ pub fn indexed_multipoint_to_geometry(
/// Create a GeoJSON MultiPoint from `nusamai_geometry::MultiPoint` with a mapping function.
pub fn multipoint_to_geometry_with_mapping<const D: usize, T: CoordNum>(
mpoint: &MultiPoint<D, T>,
mapping: impl Fn(&[T]) -> Vec<f64>,
mapping: impl Fn([T; D]) -> Vec<f64>,
) -> geojson::Geometry {
let coords = mpoint
.iter()
Expand Down
46 changes: 27 additions & 19 deletions nusamai-geometry/src/compact/linestring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<'a, const D: usize, T: CoordNum> LineString<'a, D, T> {
}

/// Reverses the coordinates in the LineString.
pub fn reverse(&mut self) {
pub fn reverse_inplace(&mut self) {
let len = self.coords.len();
if len > 0 {
let data = self.coords.to_mut();
Expand All @@ -98,7 +98,7 @@ impl<'a, const D: usize, T: CoordNum> LineString<'a, D, T> {
}

/// Reverses the winding order of the coordinates in the ring, preserving the first coordinate.
pub fn ring_reverse(&mut self) {
pub fn reverse_ring_inplace(&mut self) {
let len = self.coords.len();
if len > D {
let data = self.coords.to_mut();
Expand All @@ -118,13 +118,18 @@ impl<'a, T: CoordNum> LineString<'a, 2, T> {
self.signed_ring_area() > 0.0
}

/// Returns true if the ring is clockwise.
pub fn is_cw(&self) -> bool {
self.signed_ring_area() < 0.0
}

/// Calculates the area of this LineString as a ring.
pub fn ring_area(&self) -> f64 {
self.signed_ring_area().abs()
}

/// Calculates the signed area of this LineString as a ring.
fn signed_ring_area(&self) -> f64 {
pub fn signed_ring_area(&self) -> f64 {
if self.is_empty() {
return 0.0;
}
Expand All @@ -147,7 +152,7 @@ impl<const D: usize, T: CoordNum> AsRef<[T]> for LineString<'_, D, T> {
}

impl<'a, const D: usize, T: CoordNum> IntoIterator for &'a LineString<'_, D, T> {
type Item = &'a [T];
type Item = [T; D];
type IntoIter = Iter<'a, D, T>;

fn into_iter(self) -> Self::IntoIter {
Expand All @@ -162,14 +167,14 @@ pub struct Iter<'a, const D: usize, T: CoordNum> {
}

impl<'a, const D: usize, T: CoordNum> Iterator for Iter<'a, D, T> {
type Item = &'a [T];
type Item = [T; D];

fn next(&mut self) -> Option<Self::Item> {
self.pos += D;
if self.pos <= self.slice.len() {
Some(&self.slice[self.pos - D..self.pos])
Some(self.slice[self.pos - D..self.pos].try_into().unwrap())
} else if self.close && self.slice.len() >= D && self.pos == self.slice.len() + D {
Some(&self.slice[..D])
Some(self.slice[..D].try_into().unwrap())
} else {
None
}
Expand All @@ -188,10 +193,10 @@ mod tests {
assert!(!line.is_empty());
for (i, coord) in line.iter().enumerate() {
match i {
0 => assert_eq!(coord, &[0., 1.]),
1 => assert_eq!(coord, &[2., 3.]),
2 => assert_eq!(coord, &[4., 5.]),
3 => assert_eq!(coord, &[6., 7.]),
0 => assert_eq!(coord, [0., 1.]),
1 => assert_eq!(coord, [2., 3.]),
2 => assert_eq!(coord, [4., 5.]),
3 => assert_eq!(coord, [6., 7.]),
_ => unreachable!(),
}
}
Expand Down Expand Up @@ -227,10 +232,10 @@ mod tests {
assert!(!line.is_empty());
for (i, coord) in line.iter_closed().enumerate() {
match i {
0 => assert_eq!(coord, &[0., 1.]),
1 => assert_eq!(coord, &[2., 3.]),
2 => assert_eq!(coord, &[4., 5.]),
3 => assert_eq!(coord, &[0., 1.]),
0 => assert_eq!(coord, [0., 1.]),
1 => assert_eq!(coord, [2., 3.]),
2 => assert_eq!(coord, [4., 5.]),
3 => assert_eq!(coord, [0., 1.]),
_ => unreachable!(),
}
}
Expand All @@ -255,28 +260,31 @@ mod tests {
fn test_winding_order() {
let line = LineString2::from_raw(vec![0.0, 0.0, 3.0, 0.0, 3.0, 3.0, 0.0, 3.0].into());
assert!(line.is_ccw());
assert!(!line.is_cw());

let line = LineString2::from_raw(vec![0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 0.0].into());
assert!(!line.is_ccw());
assert!(line.is_cw());

let line = LineString2::from_raw(vec![0.0, 0.0, 0.0, 0.0].into());
assert!(!line.is_ccw());
assert!(!line.is_cw());
}

#[test]
fn test_reverse() {
let mut line = LineString2::from_raw(
vec![0.0, 0.0, 3.0, 0.0, 3.0, 1.0, 3.0, 3.0, 1.0, 3.0, 0.0, 3.0].into(),
);
line.reverse();
line.reverse_inplace();
assert_eq!(
line.coords(),
vec![0.0, 3.0, 1.0, 3.0, 3.0, 3.0, 3.0, 1.0, 3.0, 0.0, 0.0, 0.0]
);

let mut line =
LineString2::from_raw(vec![0.0, 0.0, 3.0, 0.0, 6.0, 0.0, 6.0, 3.0, 3.0, 3.0].into());
line.reverse();
line.reverse_inplace();
assert_eq!(
line.coords(),
vec![3.0, 3.0, 6.0, 3.0, 6.0, 0.0, 3.0, 0.0, 0.0, 0.0]
Expand All @@ -288,15 +296,15 @@ mod tests {
let mut line = LineString2::from_raw(
vec![0.0, 0.0, 3.0, 0.0, 3.0, 1.0, 3.0, 3.0, 1.0, 3.0, 0.0, 3.0].into(),
);
line.ring_reverse();
line.reverse_ring_inplace();
assert_eq!(
line.coords(),
vec![0.0, 0.0, 0.0, 3.0, 1.0, 3.0, 3.0, 3.0, 3.0, 1.0, 3.0, 0.0]
);

let mut line =
LineString2::from_raw(vec![0.0, 0.0, 3.0, 0.0, 6.0, 0.0, 6.0, 3.0, 3.0, 3.0].into());
line.ring_reverse();
line.reverse_ring_inplace();
assert_eq!(
line.coords(),
vec![0.0, 0.0, 3.0, 3.0, 6.0, 3.0, 6.0, 0.0, 3.0, 0.0]
Expand Down
10 changes: 5 additions & 5 deletions nusamai-geometry/src/compact/multi_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<const D: usize, T: CoordNum> AsRef<[T]> for MultiPoint<'_, D, T> {
}

impl<'a, const D: usize, T: CoordNum> IntoIterator for &'a MultiPoint<'_, D, T> {
type Item = &'a [T];
type Item = [T; D];
type IntoIter = Iter<'a, D, T>;

fn into_iter(self) -> Self::IntoIter {
Expand All @@ -99,12 +99,12 @@ pub struct Iter<'a, const D: usize, T: CoordNum> {
}

impl<'a, const D: usize, T: CoordNum> Iterator for Iter<'a, D, T> {
type Item = &'a [T];
type Item = [T; D];

fn next(&mut self) -> Option<Self::Item> {
self.pos += D;
if self.pos <= self.slice.len() {
Some(&self.slice[self.pos - D..self.pos])
Some(self.slice[self.pos - D..self.pos].try_into().unwrap())
} else {
None
}
Expand Down Expand Up @@ -134,8 +134,8 @@ mod tests {

for (i, point) in mpoints.iter().enumerate() {
match i {
0 => assert_eq!(point, &[0.0, 0.0]),
1 => assert_eq!(point, &[1.0, 1.0]),
0 => assert_eq!(point, [0.0, 0.0]),
1 => assert_eq!(point, [1.0, 1.0]),
_ => unreachable!(),
}
}
Expand Down
11 changes: 8 additions & 3 deletions nusamai-geometry/src/compact/multi_polygon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,19 @@ impl<'a, const D: usize, T: CoordNum> MultiPolygon<'a, D, T> {
}

/// Create a new MultiPolygon by applying the given transformation to all coordinates.
pub fn transform(&self, f: impl Fn(&[T; D]) -> [T; D]) -> Self {
Self {
pub fn transform<const D2: usize, T2: CoordNum>(
&self,
f: impl Fn(&[T; D]) -> [T2; D2],
) -> MultiPolygon<D2, T2> {
MultiPolygon {
all_coords: self
.all_coords
.chunks_exact(D)
.flat_map(|v| f(&v.try_into().unwrap()))
.collect(),
..self.clone()
coords_spans: self.coords_spans.clone(),
all_hole_indices: self.all_hole_indices.clone(),
holes_spans: self.holes_spans.clone(),
}
}

Expand Down
Loading