use crate::model::*;
use derive_more::{Deref, DerefMut};
use microcad_core::BooleanOp;
#[derive(Debug, Default, Clone, PartialEq, Deref, DerefMut)]
pub struct Models(Vec<Model>);
impl Models {
pub fn single_model(&self) -> Option<Model> {
match self.0.len() {
1 => self.0.first().cloned(),
_ => None,
}
}
pub fn to_multiplicity(&self, src_ref: SrcRef) -> Model {
match self.single_model() {
Some(model) => model,
None => ModelBuilder::new(Element::Multiplicity, src_ref)
.add_children(self.clone())
.build(),
}
}
pub fn union(&self) -> Model {
self.boolean_op(microcad_core::BooleanOp::Union)
}
pub fn boolean_op(&self, op: BooleanOp) -> Model {
match self.single_model() {
Some(model) => model,
None => ModelBuilder::new(Element::BuiltinWorkpiece(op.into()), SrcRef::none())
.add_children(
[ModelBuilder::new(Element::Group, SrcRef::none())
.add_children(self.clone())
.build()]
.into_iter()
.collect(),
)
.build(),
}
}
pub fn filter_by_source_hash(&self, source_hash: u64) -> Models {
self.iter()
.filter(|model| source_hash == model.source_hash())
.cloned()
.collect()
}
pub fn deduce_output_type(&self) -> OutputType {
self.iter().map(|model| model.deduce_output_type()).fold(
OutputType::NotDetermined,
|result_output_type, model_output_type| result_output_type.merge(&model_output_type),
)
}
}
impl From<Vec<Model>> for Models {
fn from(value: Vec<Model>) -> Self {
Self(value)
}
}
impl From<Option<Model>> for Models {
fn from(value: Option<Model>) -> Self {
Self(value.into_iter().collect())
}
}
impl std::fmt::Display for Models {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.iter().try_for_each(|model| model.fmt(f))
}
}
impl FromIterator<Model> for Models {
fn from_iter<T: IntoIterator<Item = Model>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl TreeDisplay for Models {
fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result {
self.iter().try_for_each(|child| child.tree_print(f, depth))
}
}