use energyml_geometry::fence::point_at;
use serde::{Deserialize, Serialize};
use crate::layout::fill::{self, Span};
use crate::layout::trace_colour;
use crate::model::{Catalogue, FillChoice, Item, Section, SectionKey, TraceItem, View};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Panel {
pub section: SectionKey,
pub key: String,
pub colour: String,
pub polygons: Vec<Vec<[f64; 3]>>,
pub sz: Vec<Vec<[f64; 2]>>,
}
pub fn panels(catalogue: &Catalogue, view: &View) -> Vec<Panel> {
let mut out = Vec::new();
if view.fills.is_empty() {
return out;
}
for section in std::iter::once(&catalogue.long).chain(catalogue.crosses.iter()) {
of_section(section, view, &mut out);
}
out
}
fn of_section(section: &Section, view: &View, out: &mut Vec<Panel>) {
let mut kept: Vec<(String, &TraceItem, String, Vec<Span>)> = Vec::new();
for item in §ion.items {
let Item::Trace(t) = item else { continue };
let key = t.object.key();
if view.hidden.contains(&key) {
continue;
}
let spans: Vec<Span> = t.spans.iter().filter(|s| s.len() >= 2).cloned().collect();
if spans.is_empty() {
continue;
}
let colour = trace_colour(view, t);
kept.push((key, t, colour, spans));
}
let lines: Vec<fill::Line<'_>> = kept
.iter()
.map(|(k, item, _, s)| fill::Line {
key: k,
item,
spans: s,
})
.collect();
for ((key, _, colour, _), mine) in kept.iter().zip(&lines) {
let Some(FillChoice { up, down, .. }) = view.fills.iter().find(|f| f.key == *key) else {
continue;
};
let mut polygons = Vec::new();
let mut sz = Vec::new();
for (wanted, is_up) in [(*up, true), (*down, false)] {
if !wanted {
continue;
}
for poly in fill::polygons(mine, &lines, is_up) {
polygons.push(
poly.iter()
.map(|&[s, z]| {
let [x, y] = point_at(§ion.trace, s);
[x, y, z]
})
.collect(),
);
sz.push(poly);
}
}
if !polygons.is_empty() {
out.push(Panel {
section: section.key,
key: key.clone(),
colour: colour.clone(),
polygons,
sz,
});
}
}
}