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
use fj_math::{Circle, Line, Vector};

use crate::{
    builder::SurfaceBuilder,
    geometry::path::{GlobalPath, SurfacePath},
    insert::Insert,
    objects::{Curve, Objects, Surface},
    partial::{PartialObject, PartialSurface},
    services::Service,
    storage::Handle,
};

use super::{Sweep, SweepCache};

impl Sweep for Handle<Curve> {
    type Swept = Handle<Surface>;

    fn sweep_with_cache(
        self,
        path: impl Into<Vector<3>>,
        _: &mut SweepCache,
        objects: &mut Service<Objects>,
    ) -> Self::Swept {
        match self.surface().geometry().u {
            GlobalPath::Circle(_) => {
                // Sweeping a `Curve` creates a `Surface`. The u-axis of that
                // `Surface` is a `GlobalPath`, which we are computing below.
                // That computation might or might not work with an arbitrary
                // surface. Probably not, but I'm not sure.
                //
                // What definitely won't work, is computing the bottom edge of
                // the sweep. The edge sweeping code currently assumes that the
                // bottom edge is a line (which is true when sweeping from a
                // flat surface). But is the surface we're sweeping from is
                // curved, there's simply no way to represent the curve of the
                // resulting bottom edge.
                todo!(
                    "Sweeping a curve that is defined on a curved surface is \
                    not supported yet."
                )
            }
            GlobalPath::Line(_) => {
                // We're sweeping from a curve on a flat surface, which is
                // supported. Carry on.
            }
        }

        let u = match self.path() {
            SurfacePath::Circle(circle) => {
                let center = self
                    .surface()
                    .geometry()
                    .point_from_surface_coords(circle.center());
                let a = self
                    .surface()
                    .geometry()
                    .vector_from_surface_coords(circle.a());
                let b = self
                    .surface()
                    .geometry()
                    .vector_from_surface_coords(circle.b());

                let circle = Circle::new(center, a, b);

                GlobalPath::Circle(circle)
            }
            SurfacePath::Line(line) => {
                let origin = self
                    .surface()
                    .geometry()
                    .point_from_surface_coords(line.origin());
                let direction = self
                    .surface()
                    .geometry()
                    .vector_from_surface_coords(line.direction());

                let line = Line::from_origin_and_direction(origin, direction);

                GlobalPath::Line(line)
            }
        };

        PartialSurface::from_axes(u, path)
            .build(objects)
            .insert(objects)
    }
}