use crate::cityjson::core::boundary::Boundary;
use crate::cityjson::core::vertex::VertexIndex;
use crate::cityjson::core::vertex::VertexRef;
use crate::error;
pub type BoundaryNestedMultiPoint16 = Vec<u16>;
pub type BoundaryNestedMultiLineString16 = Vec<BoundaryNestedMultiPoint16>;
pub type BoundaryNestedMultiOrCompositeSurface16 = Vec<BoundaryNestedMultiLineString16>;
pub type BoundaryNestedSolid16 = Vec<BoundaryNestedMultiOrCompositeSurface16>;
pub type BoundaryNestedMultiOrCompositeSolid16 = Vec<BoundaryNestedSolid16>;
pub type BoundaryNestedMultiPoint32 = Vec<u32>;
pub type BoundaryNestedMultiLineString32 = Vec<BoundaryNestedMultiPoint32>;
pub type BoundaryNestedMultiOrCompositeSurface32 = Vec<BoundaryNestedMultiLineString32>;
pub type BoundaryNestedSolid32 = Vec<BoundaryNestedMultiOrCompositeSurface32>;
pub type BoundaryNestedMultiOrCompositeSolid32 = Vec<BoundaryNestedSolid32>;
pub type BoundaryNestedMultiPoint64 = Vec<u64>;
pub type BoundaryNestedMultiLineString64 = Vec<BoundaryNestedMultiPoint64>;
pub type BoundaryNestedMultiOrCompositeSurface64 = Vec<BoundaryNestedMultiLineString64>;
pub type BoundaryNestedSolid64 = Vec<BoundaryNestedMultiOrCompositeSurface64>;
pub type BoundaryNestedMultiOrCompositeSolid64 = Vec<BoundaryNestedSolid64>;
pub type BoundaryNestedMultiPoint<T> = Vec<T>;
pub type BoundaryNestedMultiLineString<T> = Vec<BoundaryNestedMultiPoint<T>>;
pub type BoundaryNestedMultiOrCompositeSurface<T> = Vec<BoundaryNestedMultiLineString<T>>;
pub type BoundaryNestedSolid<T> = Vec<BoundaryNestedMultiOrCompositeSurface<T>>;
pub type BoundaryNestedMultiOrCompositeSolid<T> = Vec<BoundaryNestedSolid<T>>;
#[inline]
fn next_index<T: VertexRef>(index: VertexIndex<T>) -> error::Result<VertexIndex<T>> {
index.next().ok_or_else(|| error::Error::IndexOverflow {
index_type: std::any::type_name::<T>().to_string(),
value: index.value().to_string(),
})
}
impl<T: VertexRef> From<BoundaryNestedMultiPoint<T>> for Boundary<T> {
fn from(value: BoundaryNestedMultiPoint<T>) -> Self {
if value.is_empty() {
Self::default()
} else {
Self {
vertices: value.iter().map(|v| VertexIndex::new(*v)).collect(),
..Self::default()
}
}
}
}
impl<T: VertexRef> TryFrom<BoundaryNestedMultiLineString<T>> for Boundary<T> {
type Error = error::Error;
fn try_from(value: BoundaryNestedMultiLineString<T>) -> error::Result<Self> {
if value.is_empty() {
Ok(Self::default())
} else {
let mut vertices = Vec::new();
let mut rings = Vec::with_capacity(value.len());
let mut ring_start = VertexIndex::new(T::zero());
for ring in &value {
rings.push(ring_start);
for vertex in ring {
vertices.push(VertexIndex::new(*vertex));
ring_start = next_index(ring_start)?;
}
}
Ok(Self {
vertices,
rings,
..Self::default()
})
}
}
}
impl<T: VertexRef> TryFrom<BoundaryNestedMultiOrCompositeSurface<T>> for Boundary<T> {
type Error = error::Error;
fn try_from(value: BoundaryNestedMultiOrCompositeSurface<T>) -> error::Result<Self> {
if value.is_empty() {
return Ok(Self::default());
}
let mut boundary = Self::with_capacity(
value
.iter()
.map(|surface| surface.iter().map(std::vec::Vec::len).sum::<usize>())
.sum::<usize>(),
value.iter().map(std::vec::Vec::len).sum::<usize>(),
value.len(),
0,
0,
);
let mut vertex_idx = VertexIndex::new(T::zero());
for surface in value {
boundary
.surfaces
.push(VertexIndex::<T>::try_from(boundary.rings.len())?);
for ring in surface {
boundary.rings.push(vertex_idx);
for vertex in ring {
boundary.vertices.push(VertexIndex::new(vertex));
vertex_idx = next_index(vertex_idx)?;
}
}
}
Ok(boundary)
}
}
impl<T: VertexRef> TryFrom<BoundaryNestedSolid<T>> for Boundary<T> {
type Error = error::Error;
fn try_from(value: BoundaryNestedSolid<T>) -> error::Result<Self> {
if value.is_empty() {
return Ok(Self::default());
}
let vertices_cap = value
.iter()
.map(|shell| {
shell
.iter()
.map(|surface| surface.iter().map(std::vec::Vec::len).sum::<usize>())
.sum::<usize>()
})
.sum::<usize>();
let rings_cap = value
.iter()
.map(|shell| shell.iter().map(std::vec::Vec::len).sum::<usize>())
.sum::<usize>();
let surfaces_cap = value.iter().map(std::vec::Vec::len).sum::<usize>();
let mut boundary =
Self::with_capacity(vertices_cap, rings_cap, surfaces_cap, value.len(), 0);
let mut vertex_idx = VertexIndex::new(T::zero());
for shell in value {
boundary
.shells
.push(VertexIndex::<T>::try_from(boundary.surfaces.len())?);
for surface in shell {
boundary
.surfaces
.push(VertexIndex::<T>::try_from(boundary.rings.len())?);
for ring in surface {
boundary.rings.push(vertex_idx);
for vertex in ring {
boundary.vertices.push(VertexIndex::new(vertex));
vertex_idx = next_index(vertex_idx)?;
}
}
}
}
Ok(boundary)
}
}
impl<T: VertexRef> TryFrom<BoundaryNestedMultiOrCompositeSolid<T>> for Boundary<T> {
type Error = error::Error;
fn try_from(value: BoundaryNestedMultiOrCompositeSolid<T>) -> error::Result<Self> {
if value.is_empty() {
return Ok(Self::default());
}
let vertices_cap = value
.iter()
.map(|solid| {
solid
.iter()
.map(|shell| {
shell
.iter()
.map(|surface| surface.iter().map(std::vec::Vec::len).sum::<usize>())
.sum::<usize>()
})
.sum::<usize>()
})
.sum::<usize>();
let rings_cap = value
.iter()
.map(|solid| {
solid
.iter()
.map(|shell| shell.iter().map(std::vec::Vec::len).sum::<usize>())
.sum::<usize>()
})
.sum::<usize>();
let surfaces_cap = value
.iter()
.map(|solid| solid.iter().map(std::vec::Vec::len).sum::<usize>())
.sum::<usize>();
let shells_cap = value.iter().map(std::vec::Vec::len).sum::<usize>();
let mut boundary = Self::with_capacity(
vertices_cap,
rings_cap,
surfaces_cap,
shells_cap,
value.len(),
);
let mut vertex_idx = VertexIndex::new(T::zero());
for solid in value {
boundary
.solids
.push(VertexIndex::<T>::try_from(boundary.shells.len())?);
for shell in solid {
boundary
.shells
.push(VertexIndex::<T>::try_from(boundary.surfaces.len())?);
for surface in shell {
boundary
.surfaces
.push(VertexIndex::<T>::try_from(boundary.rings.len())?);
for ring in surface {
boundary.rings.push(vertex_idx);
for vertex in ring {
boundary.vertices.push(VertexIndex::new(vertex));
vertex_idx = next_index(vertex_idx)?;
}
}
}
}
}
Ok(boundary)
}
}