use crate::geometry::primitives::Point;
use crate::geometry::shapes::Polygon;
use crate::geometry::traits::{DiagramShape, Polygonize};
use crate::plotting::regions::{decompose_regions, RegionPolygons};
use crate::spec::{Combination, DiagramSpec};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy)]
pub struct PlotOptions {
pub n_vertices: usize,
pub label_precision: f64,
}
impl Default for PlotOptions {
fn default() -> Self {
Self {
n_vertices: 200,
label_precision: 0.01,
}
}
}
#[derive(Debug, Clone)]
pub struct PlotData {
pub regions: RegionPolygons,
pub region_anchors: HashMap<Combination, Point>,
pub set_anchors: HashMap<String, Point>,
pub shape_outlines: Vec<Polygon>,
}
pub(crate) fn build_plot_data<S>(shapes: &[S], spec: &DiagramSpec, options: PlotOptions) -> PlotData
where
S: DiagramShape + Polygonize,
{
let regions = decompose_regions(shapes, spec.set_names(), spec, options.n_vertices);
let region_anchors = regions.label_points(options.label_precision);
let set_anchors = regions.set_label_points(spec.set_names(), options.label_precision);
let shape_outlines = shapes
.iter()
.map(|s| s.polygonize(options.n_vertices))
.collect();
PlotData {
regions,
region_anchors,
set_anchors,
shape_outlines,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::fitter::Fitter;
use crate::geometry::shapes::Circle;
use crate::spec::{DiagramSpecBuilder, InputType};
#[test]
fn test_plot_options_default() {
let opts = PlotOptions::default();
assert_eq!(opts.n_vertices, 200);
assert!((opts.label_precision - 0.01).abs() < 1e-12);
}
#[test]
fn test_plot_data_two_circles() {
let spec = DiagramSpecBuilder::new()
.set("A", 5.0)
.set("B", 3.0)
.intersection(&["A", "B"], 1.0)
.input_type(InputType::Exclusive)
.build()
.unwrap();
let layout = Fitter::<Circle>::new(&spec).seed(42).fit().unwrap();
let plot = layout.plot_data(&spec, PlotOptions::default());
for combo in plot.regions.iter().map(|(c, _)| c) {
assert!(plot.region_anchors.contains_key(combo));
}
assert_eq!(plot.shape_outlines.len(), spec.set_names().len());
for name in spec.set_names() {
assert!(plot.set_anchors.contains_key(name));
}
}
}