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
use fj_interop::ext::ArrayExt;
use fj_math::Point;

use crate::{
    objects::{Cycle, Face, GlobalEdge, HalfEdge, Objects, Surface},
    operations::{Insert, UpdateHalfEdge},
    services::Service,
    storage::Handle,
};

use super::{BuildHalfEdge, BuildSurface};

/// Build a [`Face`]
pub trait BuildFace {
    /// Build a triangle
    fn triangle(
        points: [impl Into<Point<3>>; 3],
        edges: [Option<Handle<GlobalEdge>>; 3],
        objects: &mut Service<Objects>,
    ) -> Triangle {
        let [a, b, c] = points.map(Into::into);

        let surface = Surface::plane_from_points([a, b, c]).insert(objects);
        let (exterior, edges) = {
            let half_edges = [[a, b], [b, c], [c, a]].zip_ext(edges).map(
                |(points, global_form)| {
                    let mut half_edge =
                        HalfEdge::line_segment_from_global_points(
                            points, &surface, None, objects,
                        );

                    if let Some(global_form) = global_form {
                        half_edge = half_edge.update_global_form(global_form);
                    }

                    half_edge.insert(objects)
                },
            );

            let cycle = Cycle::new(half_edges.clone()).insert(objects);

            let global_edges =
                half_edges.map(|half_edge| half_edge.global_form().clone());

            (cycle, global_edges)
        };

        let face = Face::new(surface, exterior, [], None);

        Triangle { face, edges }
    }
}

impl BuildFace for Face {}

/// A triangle
///
/// Returned by [`BuildFace::triangle`].
pub struct Triangle {
    /// The face that forms the triangle
    pub face: Face,

    /// The edges of the triangle
    pub edges: [Handle<GlobalEdge>; 3],
}