geo_aid_script/unroll/library/
bisector.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! The `bisector` function

use crate::math::Build;

use super::{angle::display_angle_arms, prelude::*};

/// bisector(point, point, point) - an angle's bisector.
pub fn point_point_point(
    a: Expr<Point>,
    b: Expr<Point>,
    c: Expr<Point>,
    context: &CompileContext,
    mut display: Properties,
) -> Expr<Line> {
    let display_arms = display.get("display_arms").maybe_unset(true);
    let arms_style = display.get("arms_style").maybe_unset(Style::default());
    let line_type = display.get("line_type").maybe_unset(LineType::Ray);
    let arms_type = display.get("arms_type").maybe_unset(LineType::Segment);

    let mut expr = context.bisector_ppp_display(a, b, c, display);

    if let Some(node) = &mut expr.node {
        node.insert_data("display_arms", display_arms);
        node.insert_data("arms_style", arms_style);
        node.insert_data("line_type", line_type);
        node.insert_data("arms_type", arms_type);

        node.set_associated(Associated);
    }
    expr
}

/// ```
/// # use geo_aid_figure::Style;
/// struct Associated {
///     display_arms: bool,
///     arms_style: Style
/// }
/// ```
#[derive(Debug)]
pub struct Associated;

impl BuildAssociated<LineNode> for Associated {
    fn build_associated(
        self: Box<Self>,
        build: &mut Build,
        associated: &mut HierarchyNode<LineNode>,
    ) {
        let display_arms = associated
            .get_data("display_arms")
            .unwrap()
            .as_bool()
            .unwrap()
            .unwrap();

        let arms_style = associated
            .get_data("arms_style")
            .unwrap()
            .as_style()
            .unwrap()
            .unwrap();

        let mut line_type = associated
            .get_data("line_type")
            .unwrap()
            .as_line_type()
            .unwrap();

        let arms_type = associated
            .get_data("arms_type")
            .unwrap()
            .as_line_type()
            .unwrap()
            .unwrap();

        // The old value takes advantage only if it has been manually set and the `line_type` prop has not.
        line_type.try_set_if_unset(associated.root.line_type.try_get().copied());
        associated.root.line_type.set(line_type.unwrap());

        if display_arms {
            match associated.root.expr.data.as_ref() {
                Line::AngleBisector(a_expr, b_expr, c_expr) => {
                    display_angle_arms(build, a_expr, b_expr, c_expr, arms_type, arms_style);
                }
                _ => unreachable!(),
            }
        }
    }
}

/// bisector(point, point) - a segment's perpendicular bisector line.
pub fn point_point(
    a: Expr<Point>,
    b: Expr<Point>,
    context: &CompileContext,
    display: Properties,
) -> Expr<Line> {
    use super::perpendicular::line_point;

    line_point(
        context.line(a.clone_without_node(), b.clone_without_node()),
        context.average_p(vec![a, b]),
        context,
        display,
    )
}

/// Register the function
pub fn register(library: &mut Library) {
    library.add(
        Function::new("bisector")
            .overload(|mut col: Pc<3>, context: &CompileContext, display| {
                point_point_point(
                    index!(node col,0),
                    index!(node col,1),
                    index!(node col,2),
                    context,
                    display,
                )
            })
            .overload(point_point_point)
            .overload(|mut col: Pc<2>, context: &mut CompileContext, display| {
                point_point(index!(node col,0), index!(node col,1), context, display)
            })
            .overload(point_point),
    );
}