use ifc_model::{EntityId, Model, Transaction, Value};
use ifc_schema::Schema;
use crate::authoring::{build_named, invalid_authoring, validate_ref};
use crate::StyleResult;
#[derive(Debug, Clone, Copy)]
pub struct ImageTextureDraft<'a> {
pub repeat_s: bool,
pub repeat_t: bool,
pub mode: Option<&'a str>,
pub texture_transform: Option<EntityId>,
pub url_reference: &'a str,
}
pub fn create_image_texture(
tx: &mut Transaction,
model: &Model,
schema: &Schema,
draft: ImageTextureDraft<'_>,
) -> StyleResult<EntityId> {
if draft.url_reference.trim().is_empty() {
return Err(invalid_authoring(
"IfcImageTexture",
"URLReference",
"expected a reference to an image, found nothing",
));
}
if let Some(transform) = draft.texture_transform {
validate_ref(
tx,
model,
schema,
transform,
"IfcCartesianTransformationOperator2D",
)?;
}
let mut values = vec![
("RepeatS", Value::Bool(draft.repeat_s)),
("RepeatT", Value::Bool(draft.repeat_t)),
("URLReference", Value::Text(draft.url_reference.into())),
];
if let Some(mode) = draft.mode {
values.push(("Mode", Value::Text(mode.into())));
}
if let Some(transform) = draft.texture_transform {
values.push(("TextureTransform", Value::Ref(transform)));
}
Ok(tx.create(build_named(schema, "IfcImageTexture", values)?))
}
pub fn create_texture_map(
tx: &mut Transaction,
model: &Model,
schema: &Schema,
maps: &[EntityId],
vertices: &[EntityId],
mapped_to: EntityId,
) -> StyleResult<EntityId> {
if maps.is_empty() {
return Err(invalid_authoring(
"IfcTextureMap",
"Maps",
"expected at least one surface texture, found none",
));
}
if vertices.len() < 3 {
return Err(invalid_authoring(
"IfcTextureMap",
"Vertices",
format!("expected at least 3 vertices, found {}", vertices.len()),
));
}
validate_ref(tx, model, schema, mapped_to, "IfcFace")?;
let values = vec![
(
"Maps",
Value::List(maps.iter().copied().map(Value::Ref).collect()),
),
(
"Vertices",
Value::List(vertices.iter().copied().map(Value::Ref).collect()),
),
("MappedTo", Value::Ref(mapped_to)),
];
Ok(tx.create(build_named(schema, "IfcTextureMap", values)?))
}
pub fn create_texture_coordinate_generator(
tx: &mut Transaction,
schema: &Schema,
maps: &[EntityId],
mode: &str,
parameters: &[f64],
) -> StyleResult<EntityId> {
if maps.is_empty() {
return Err(invalid_authoring(
"IfcTextureCoordinateGenerator",
"Maps",
"expected at least one surface texture, found none",
));
}
if mode.trim().is_empty() {
return Err(invalid_authoring(
"IfcTextureCoordinateGenerator",
"Mode",
"expected a generating function, found nothing",
));
}
if let Some(value) = parameters.iter().find(|value| !value.is_finite()) {
return Err(invalid_authoring(
"IfcTextureCoordinateGenerator",
"Parameter",
format!("expected finite parameters, found {value}"),
));
}
let mut values = vec![
(
"Maps",
Value::List(maps.iter().copied().map(Value::Ref).collect()),
),
("Mode", Value::Text(mode.into())),
];
if !parameters.is_empty() {
values.push((
"Parameter",
Value::List(parameters.iter().copied().map(Value::Real).collect()),
));
}
Ok(tx.create(build_named(
schema,
"IfcTextureCoordinateGenerator",
values,
)?))
}