raffitz
3 years ago
8 changed files with 597 additions and 18 deletions
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
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)) |
||||
} |
@ -0,0 +1,274 @@
@@ -0,0 +1,274 @@
|
||||
use crate::astree; |
||||
use crate::astree::{Boundaries, Boundary, Condition, Expression, Junction}; |
||||
use crate::error; |
||||
use std::collections::HashMap; |
||||
|
||||
pub fn any_triangle<T: Into<String> + Clone>( |
||||
x_1: T, |
||||
y_1: T, |
||||
x_2: T, |
||||
y_2: T, |
||||
x_3: T, |
||||
y_3: T, |
||||
previous_labels: Option<HashMap<String, Expression>>, |
||||
) -> Result<astree::Structure, error::Error> { |
||||
let mut junctions = Vec::<Junction>::with_capacity(3); |
||||
|
||||
let labels = previous_labels.unwrap_or_default(); |
||||
let mut vars = HashMap::<char, f64>::new(); |
||||
vars.insert('s', 1_f64); |
||||
let vars_eval = Some(&vars); |
||||
|
||||
// Determine if clockwise
|
||||
let idents = Some(&labels); |
||||
let clockwise_exp = Expression::operation( |
||||
'+', |
||||
Expression::operation( |
||||
'+', |
||||
Expression::operation( |
||||
'*', |
||||
Expression::operation( |
||||
'-', |
||||
Expression::ident(x_3.clone().into()), |
||||
Expression::ident(x_2.clone().into()), |
||||
), |
||||
Expression::operation( |
||||
'+', |
||||
Expression::ident(y_3.clone().into()), |
||||
Expression::ident(y_2.clone().into()), |
||||
), |
||||
), |
||||
Expression::operation( |
||||
'*', |
||||
Expression::operation( |
||||
'-', |
||||
Expression::ident(x_1.clone().into()), |
||||
Expression::ident(x_3.clone().into()), |
||||
), |
||||
Expression::operation( |
||||
'+', |
||||
Expression::ident(y_1.clone().into()), |
||||
Expression::ident(y_3.clone().into()), |
||||
), |
||||
), |
||||
), |
||||
Expression::operation( |
||||
'*', |
||||
Expression::operation( |
||||
'-', |
||||
Expression::ident(x_2.clone().into()), |
||||
Expression::ident(x_1.clone().into()), |
||||
), |
||||
Expression::operation( |
||||
'+', |
||||
Expression::ident(y_2.clone().into()), |
||||
Expression::ident(y_1.clone().into()), |
||||
), |
||||
), |
||||
); |
||||
let clockwise = clockwise_exp.eval(&idents, &vars_eval)? > 1e-10_f64; |
||||
|
||||
let ident_x_1 = x_1.into(); |
||||
let ident_y_1 = y_1.into(); |
||||
let ident_x_2; |
||||
let ident_y_2; |
||||
let ident_x_3; |
||||
let ident_y_3; |
||||
if clockwise { |
||||
ident_x_2 = x_3.into(); |
||||
ident_y_2 = y_3.into(); |
||||
ident_x_3 = x_2.into(); |
||||
ident_y_3 = y_2.into(); |
||||
} else { |
||||
ident_x_2 = x_2.into(); |
||||
ident_y_2 = y_2.into(); |
||||
ident_x_3 = x_3.into(); |
||||
ident_y_3 = y_3.into(); |
||||
} |
||||
|
||||
let mut min_x = f64::MAX; |
||||
let mut min_x_label = String::from("error"); |
||||
let mut max_x = f64::MIN; |
||||
let mut max_x_label = String::from("error"); |
||||
|
||||
let mut min_y = f64::MAX; |
||||
let mut min_y_label = String::from("error"); |
||||
let mut max_y = f64::MIN; |
||||
let mut max_y_label = String::from("error"); |
||||
|
||||
let x_1_val = Expression::ident(ident_x_1.clone()).eval(&idents, &vars_eval)?; |
||||
let x_2_val = Expression::ident(ident_x_2.clone()).eval(&idents, &vars_eval)?; |
||||
let x_3_val = Expression::ident(ident_x_3.clone()).eval(&idents, &vars_eval)?; |
||||
let y_1_val = Expression::ident(ident_y_1.clone()).eval(&idents, &vars_eval)?; |
||||
let y_2_val = Expression::ident(ident_y_2.clone()).eval(&idents, &vars_eval)?; |
||||
let y_3_val = Expression::ident(ident_y_3.clone()).eval(&idents, &vars_eval)?; |
||||
|
||||
if x_1_val < min_x { |
||||
min_x = x_1_val; |
||||
min_x_label = ident_x_1.clone(); |
||||
} |
||||
if x_2_val < min_x { |
||||
min_x = x_2_val; |
||||
min_x_label = ident_x_2.clone(); |
||||
} |
||||
if x_3_val < min_x { |
||||
min_x_label = ident_x_3.clone(); |
||||
} |
||||
if x_1_val > max_x { |
||||
max_x = x_1_val; |
||||
max_x_label = ident_x_1.clone(); |
||||
} |
||||
if x_2_val > max_x { |
||||
max_x = x_2_val; |
||||
max_x_label = ident_x_2.clone(); |
||||
} |
||||
if x_3_val > max_x { |
||||
max_x_label = ident_x_3.clone(); |
||||
} |
||||
if y_1_val < min_y { |
||||
min_y = y_1_val; |
||||
min_y_label = ident_y_1.clone(); |
||||
} |
||||
if y_2_val < min_y { |
||||
min_y = y_2_val; |
||||
min_y_label = ident_y_2.clone(); |
||||
} |
||||
if y_3_val < min_y { |
||||
min_y_label = ident_y_3.clone(); |
||||
} |
||||
if y_1_val > max_y { |
||||
max_y = y_1_val; |
||||
max_y_label = ident_y_1.clone(); |
||||
} |
||||
if y_2_val > max_y { |
||||
max_y = y_2_val; |
||||
max_y_label = ident_y_2.clone(); |
||||
} |
||||
if y_3_val > max_y { |
||||
max_y_label = ident_y_3.clone(); |
||||
} |
||||
|
||||
let normal_1_y = Expression::operation( |
||||
'-', |
||||
Expression::ident(ident_x_1.clone()), |
||||
Expression::ident(ident_x_2.clone()), |
||||
) |
||||
.eval(&idents, &vars_eval)?; |
||||
let normal_1_x = Expression::operation( |
||||
'-', |
||||
Expression::ident(ident_y_2.clone()), |
||||
Expression::ident(ident_y_1.clone()), |
||||
) |
||||
.eval(&idents, &vars_eval)?; |
||||
let normal_2_y = Expression::operation( |
||||
'-', |
||||
Expression::ident(ident_x_2.clone()), |
||||
Expression::ident(ident_x_3.clone()), |
||||
) |
||||
.eval(&idents, &vars_eval)?; |
||||
let normal_2_x = Expression::operation( |
||||
'-', |
||||
Expression::ident(ident_y_3.clone()), |
||||
Expression::ident(ident_y_2.clone()), |
||||
) |
||||
.eval(&idents, &vars_eval)?; |
||||
let normal_3_y = Expression::operation( |
||||
'-', |
||||
Expression::ident(ident_x_3.clone()), |
||||
Expression::ident(ident_x_1.clone()), |
||||
) |
||||
.eval(&idents, &vars_eval)?; |
||||
let normal_3_x = Expression::operation( |
||||
'-', |
||||
Expression::ident(ident_y_1.clone()), |
||||
Expression::ident(ident_y_3.clone()), |
||||
) |
||||
.eval(&idents, &vars_eval)?; |
||||
|
||||
let j_exp = Expression::operation( |
||||
'+', |
||||
Expression::operation( |
||||
'*', |
||||
Expression::float(normal_1_x), |
||||
Expression::operation('-', Expression::var('x'), Expression::ident(ident_x_1)), |
||||
), |
||||
Expression::operation( |
||||
'*', |
||||
Expression::float(normal_1_y), |
||||
Expression::operation('-', Expression::var('y'), Expression::ident(ident_y_1)), |
||||
), |
||||
); |
||||
|
||||
junctions.push(Junction::singleton(Condition::new( |
||||
'≤', |
||||
j_exp, |
||||
Expression::float(0), |
||||
))); |
||||
|
||||
let j_exp = Expression::operation( |
||||
'+', |
||||
Expression::operation( |
||||
'*', |
||||
Expression::float(normal_2_x), |
||||
Expression::operation('-', Expression::var('x'), Expression::ident(ident_x_2)), |
||||
), |
||||
Expression::operation( |
||||
'*', |
||||
Expression::float(normal_2_y), |
||||
Expression::operation('-', Expression::var('y'), Expression::ident(ident_y_2)), |
||||
), |
||||
); |
||||
|
||||
junctions.push(Junction::singleton(Condition::new( |
||||
'≤', |
||||
j_exp, |
||||
Expression::float(0), |
||||
))); |
||||
|
||||
let j_exp = Expression::operation( |
||||
'+', |
||||
Expression::operation( |
||||
'*', |
||||
Expression::float(normal_3_x), |
||||
Expression::operation('-', Expression::var('x'), Expression::ident(ident_x_3)), |
||||
), |
||||
Expression::operation( |
||||
'*', |
||||
Expression::float(normal_3_y), |
||||
Expression::operation('-', Expression::var('y'), Expression::ident(ident_y_3)), |
||||
), |
||||
); |
||||
|
||||
junctions.push(Junction::singleton(Condition::new( |
||||
'≤', |
||||
j_exp, |
||||
Expression::float(0), |
||||
))); |
||||
|
||||
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(); |
||||
|
||||
let boundaries: Boundaries = [ |
||||
Boundary::new(Expression::float(0), '≤', 'z', '≤', Expression::float(0))?, |
||||
Boundary::new( |
||||
Expression::ident(min_x_label), |
||||
'≤', |
||||
'x', |
||||
'≤', |
||||
Expression::ident(max_x_label), |
||||
)?, |
||||
Boundary::new( |
||||
Expression::ident(min_y_label), |
||||
'≤', |
||||
'y', |
||||
'≤', |
||||
Expression::ident(max_y_label), |
||||
)?, |
||||
]; |
||||
|
||||
Ok((Some(labels), boundaries, the_junction)) |
||||
} |
Loading…
Reference in new issue