You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.5 KiB
121 lines
3.5 KiB
3 years ago
|
use crate::astree;
|
||
|
use crate::astree::{Expression, Junction};
|
||
|
use crate::error;
|
||
|
use crate::ngon;
|
||
|
use crate::triangle::any_triangle;
|
||
|
use std::collections::HashMap;
|
||
|
|
||
|
pub fn generate<T: Into<String> + Clone, S: Into<f64> + Copy>(
|
||
|
n: u8,
|
||
|
prefix_val: Option<T>,
|
||
|
offset: (Option<T>, Option<T>),
|
||
|
angle_offset: Option<T>,
|
||
|
scale: Option<S>,
|
||
|
star_scale: Option<S>,
|
||
|
previous_labels: Option<HashMap<String, Expression>>,
|
||
|
) -> Result<astree::Structure, error::Error> {
|
||
|
let prefix = if let Some(val) = prefix_val {
|
||
|
val.into()
|
||
|
} else {
|
||
|
"".to_string()
|
||
|
};
|
||
|
|
||
|
let mut junctions = Vec::<Junction>::with_capacity(n as usize);
|
||
|
|
||
|
let mut labels = previous_labels.unwrap_or_default();
|
||
|
|
||
|
let (x_offset, y_offset) = offset;
|
||
|
|
||
|
let center_x;
|
||
|
let center_y;
|
||
|
if let Some(x_label) = x_offset {
|
||
|
center_x = x_label.into();
|
||
|
} else {
|
||
|
center_x = format!("@{}centerx", prefix);
|
||
|
labels.insert(center_x.clone(), Expression::float(0_f64));
|
||
|
}
|
||
|
if let Some(y_label) = y_offset {
|
||
|
center_y = y_label.into();
|
||
|
} else {
|
||
|
center_y = format!("@{}centery", prefix);
|
||
|
labels.insert(center_y.clone(), Expression::float(0_f64));
|
||
|
}
|
||
|
|
||
|
let new_angle_offset = angle_offset.map(|a| a.into());
|
||
|
let new_scale = scale.map(|s| s.into());
|
||
|
|
||
|
let inner_prefix = format!("{}inner", prefix);
|
||
|
|
||
|
let (new_labels, _, _) = ngon::generate(
|
||
|
n,
|
||
|
Some(inner_prefix.clone()),
|
||
|
(Some(center_x.clone()), Some(center_y.clone())),
|
||
|
new_angle_offset,
|
||
|
new_scale,
|
||
|
Some(labels),
|
||
|
)?;
|
||
|
|
||
|
let angle_offset_label = format!("@{}innernangle0", prefix);
|
||
|
let outer_prefix = format!("{}outer", prefix);
|
||
|
|
||
|
let outer_scale = star_scale.map(|s| s.into()).unwrap_or(2_f64) * new_scale.unwrap_or(1_f64);
|
||
|
|
||
|
let (definitive_labels, boundaries, _) = ngon::generate(
|
||
|
n,
|
||
|
Some(outer_prefix.clone()),
|
||
|
(Some(center_x.clone()), Some(center_y.clone())),
|
||
|
Some(angle_offset_label),
|
||
|
Some(outer_scale),
|
||
|
new_labels,
|
||
|
)?;
|
||
|
|
||
|
let mut input_labels = definitive_labels;
|
||
|
|
||
|
for i in 0..n {
|
||
|
let label_x_1 = format!("@{}x{}", inner_prefix, i);
|
||
|
let label_y_1 = format!("@{}y{}", inner_prefix, i);
|
||
|
let label_x_2 = format!("@{}x{}", outer_prefix, i);
|
||
|
let label_y_2 = format!("@{}y{}", outer_prefix, i);
|
||
|
let (definitive_labels, _, junction) = any_triangle(
|
||
|
center_x.clone(),
|
||
|
center_y.clone(),
|
||
|
label_x_1,
|
||
|
label_y_1,
|
||
|
label_x_2,
|
||
|
label_y_2,
|
||
|
input_labels,
|
||
|
)?;
|
||
|
|
||
|
input_labels = definitive_labels;
|
||
|
|
||
|
junctions.push(junction);
|
||
|
|
||
|
let label_x_1 = format!("@{}x{}", outer_prefix, i);
|
||
|
let label_y_1 = format!("@{}y{}", outer_prefix, i);
|
||
|
let label_x_2 = format!("@{}x{}", inner_prefix, (i + 1) % n);
|
||
|
let label_y_2 = format!("@{}y{}", inner_prefix, (i + 1) % n);
|
||
|
let (definitive_labels, _, junction) = any_triangle(
|
||
|
center_x.clone(),
|
||
|
center_y.clone(),
|
||
|
label_x_1,
|
||
|
label_y_1,
|
||
|
label_x_2,
|
||
|
label_y_2,
|
||
|
input_labels,
|
||
|
)?;
|
||
|
|
||
|
input_labels = definitive_labels;
|
||
|
|
||
|
junctions.push(junction);
|
||
|
}
|
||
|
|
||
|
while junctions.len() > 1 {
|
||
|
let left = junctions.remove(0);
|
||
|
let right = junctions.remove(0);
|
||
|
junctions.push(Junction::meta('⋁', left, right));
|
||
|
}
|
||
|
let the_junction = junctions.pop().unwrap();
|
||
|
|
||
|
Ok((input_labels, boundaries, the_junction))
|
||
|
}
|