use ifc_model::{EntityId, Model, Transaction, Value};
use super::{invalid, optional_text, refs, require_accepts, require_exists, require_type};
use crate::error::MaterialResult;
use crate::release::Release;
pub fn create_material_properties(
tx: &mut Transaction,
model: &Model,
name: Option<&str>,
description: Option<&str>,
properties: &[EntityId],
material: EntityId,
) -> MaterialResult<EntityId> {
const ENTITY: &str = "IFCMATERIALPROPERTIES";
let release = Release::of(model);
release.require_entity(ENTITY, None)?;
if properties.is_empty() {
return Err(invalid(
ENTITY,
"Properties",
"expected at least one property",
));
}
for property in properties {
require_exists(tx, model, *property)?;
}
require_accepts(tx, model, release, ENTITY, "Material", material)?;
let record = release.record(
ENTITY,
vec![
("Name", optional_text(name)),
("Description", optional_text(description)),
("Properties", refs(properties)),
("Material", Value::Ref(material)),
],
)?;
Ok(tx.create(record))
}
pub fn create_material_relationship(
tx: &mut Transaction,
model: &Model,
name: Option<&str>,
description: Option<&str>,
relating: EntityId,
related: &[EntityId],
expression: Option<&str>,
) -> MaterialResult<EntityId> {
const ENTITY: &str = "IFCMATERIALRELATIONSHIP";
let release = Release::of(model);
release.require_entity(ENTITY, None)?;
if related.is_empty() {
return Err(invalid(
ENTITY,
"RelatedMaterials",
"expected at least one related material",
));
}
if related.contains(&relating) {
return Err(invalid(
ENTITY,
"RelatedMaterials",
"a material cannot be derived from itself",
));
}
require_type(tx, model, release, relating, &["IFCMATERIAL"])?;
for material in related {
require_type(tx, model, release, *material, &["IFCMATERIAL"])?;
}
let record = release.record(
ENTITY,
vec![
("Name", optional_text(name)),
("Description", optional_text(description)),
("RelatingMaterial", Value::Ref(relating)),
("RelatedMaterials", refs(related)),
("Expression", optional_text(expression)),
],
)?;
Ok(tx.create(record))
}
pub fn create_material_classification_relationship(
tx: &mut Transaction,
model: &Model,
classifications: &[EntityId],
material: EntityId,
) -> MaterialResult<EntityId> {
const ENTITY: &str = "IFCMATERIALCLASSIFICATIONRELATIONSHIP";
let release = Release::of(model);
release.require_entity(ENTITY, None)?;
if classifications.is_empty() {
return Err(invalid(
ENTITY,
"MaterialClassifications",
"expected at least one classification",
));
}
for classification in classifications {
require_exists(tx, model, *classification)?;
}
require_type(tx, model, release, material, &["IFCMATERIAL"])?;
let record = release.record(
ENTITY,
vec![
("MaterialClassifications", refs(classifications)),
("ClassifiedMaterial", Value::Ref(material)),
],
)?;
Ok(tx.create(record))
}
pub fn create_material_definition_representation(
tx: &mut Transaction,
model: &Model,
name: Option<&str>,
description: Option<&str>,
representations: &[EntityId],
material: EntityId,
) -> MaterialResult<EntityId> {
const ENTITY: &str = "IFCMATERIALDEFINITIONREPRESENTATION";
let release = Release::of(model);
release.require_entity(ENTITY, None)?;
if representations.is_empty() {
return Err(invalid(
ENTITY,
"Representations",
"expected at least one styled representation",
));
}
for representation in representations {
require_type(
tx,
model,
release,
*representation,
&["IFCSTYLEDREPRESENTATION"],
)?;
}
require_type(tx, model, release, material, &["IFCMATERIAL"])?;
let record = release.record(
ENTITY,
vec![
("Name", optional_text(name)),
("Description", optional_text(description)),
("Representations", refs(representations)),
("RepresentedMaterial", Value::Ref(material)),
],
)?;
Ok(tx.create(record))
}