use std::collections::BTreeMap;
use super::{id_list, real, ProductGeometry, StepWriter};
#[derive(Clone, Debug, Default)]
pub struct StepColors {
by_name: BTreeMap<String, [u8; 3]>,
}
impl StepColors {
pub fn new() -> Self {
Self::default()
}
pub fn set(&mut self, name: &str, rgb: [u8; 3]) {
if name.is_empty() {
return;
}
self.by_name.insert(name.to_string(), rgb);
}
pub fn is_empty(&self) -> bool {
self.by_name.is_empty()
}
pub fn len(&self) -> usize {
self.by_name.len()
}
pub(crate) fn resolve(&self, prefixes: &[String], name: &str) -> Option<[u8; 3]> {
prefixes.iter().find_map(|prefix| {
if prefix.is_empty() {
self.by_name.get(name).copied()
} else {
self.by_name.get(&format!("{prefix}{name}")).copied()
}
})
}
}
pub(crate) fn write_colour_rgb(
writer: &mut StepWriter,
rgb: [f64; 3],
) -> Result<usize, String> {
Ok(writer.add(format!(
"COLOUR_RGB('',{},{},{})",
real(rgb[0])?,
real(rgb[1])?,
real(rgb[2])?
)))
}
pub(crate) fn write_style_assignment(writer: &mut StepWriter, elements: &str) -> usize {
writer.add(format!("PRESENTATION_STYLE_ASSIGNMENT(({elements}))"))
}
pub(crate) fn write_styled_item(
writer: &mut StepWriter,
name: &str,
style: usize,
item: usize,
) -> usize {
writer.add(format!("STYLED_ITEM('{name}',(#{style}),#{item})"))
}
pub(crate) fn styled_items(
geometry: &ProductGeometry,
colors: &StepColors,
prefixes: &[String],
) -> Vec<(usize, [u8; 3])> {
let mut items = Vec::new();
for (name, id) in &geometry.solids {
if let Some(rgb) = colors.resolve(prefixes, name) {
items.push((*id, rgb));
}
}
for (name, id) in &geometry.faces {
if let Some(rgb) = colors.resolve(prefixes, name) {
items.push((*id, rgb));
}
}
items
}
pub(crate) fn write_geometry_styles(
writer: &mut StepWriter,
geometry_context: usize,
items: &[(usize, [u8; 3])],
) -> Result<usize, String> {
if items.is_empty() {
return Ok(0);
}
let mut assignments: BTreeMap<[u8; 3], usize> = BTreeMap::new();
let mut styled = Vec::with_capacity(items.len());
for (item, rgb) in items {
let assignment = match assignments.get(rgb) {
Some(id) => *id,
None => {
let id = write_surface_style(writer, *rgb)?;
assignments.insert(*rgb, id);
id
}
};
styled.push(write_styled_item(writer, "color", assignment, *item));
}
writer.add(format!(
"MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',{},#{geometry_context})",
id_list(&styled)
));
Ok(styled.len())
}
fn write_surface_style(writer: &mut StepWriter, rgb: [u8; 3]) -> Result<usize, String> {
let colour = write_colour_rgb(
writer,
[
rgb[0] as f64 / 255.0,
rgb[1] as f64 / 255.0,
rgb[2] as f64 / 255.0,
],
)?;
let fill_colour = writer.add(format!("FILL_AREA_STYLE_COLOUR('',#{colour})"));
let fill_area = writer.add(format!("FILL_AREA_STYLE('',(#{fill_colour}))"));
let fill_style = writer.add(format!("SURFACE_STYLE_FILL_AREA(#{fill_area})"));
let side_style = writer.add(format!("SURFACE_SIDE_STYLE('',(#{fill_style}))"));
let usage = writer.add(format!("SURFACE_STYLE_USAGE(.BOTH.,#{side_style})"));
Ok(write_style_assignment(writer, &format!("#{usage}")))
}