fj_kernel/algorithms/sweep/
curve.rs

1use fj_math::{Circle, Line, Vector};
2
3use crate::{
4    geometry::{
5        curve::{Curve, GlobalPath},
6        surface::SurfaceGeometry,
7    },
8    objects::Surface,
9    operations::Insert,
10    services::Services,
11    storage::Handle,
12};
13
14use super::{Sweep, SweepCache};
15
16impl Sweep for (Curve, &Surface) {
17    type Swept = Handle<Surface>;
18
19    fn sweep_with_cache(
20        self,
21        path: impl Into<Vector<3>>,
22        _: &mut SweepCache,
23        services: &mut Services,
24    ) -> Self::Swept {
25        let (curve, surface) = self;
26
27        match surface.geometry().u {
28            GlobalPath::Circle(_) => {
29                // Sweeping a `Curve` creates a `Surface`. The u-axis of that
30                // `Surface` is a `GlobalPath`, which we are computing below.
31                // That computation might or might not work with an arbitrary
32                // surface. Probably not, but I'm not sure.
33                //
34                // What definitely won't work, is computing the bottom edge of
35                // the sweep. The edge sweeping code currently assumes that the
36                // bottom edge is a line (which is true when sweeping from a
37                // flat surface). But is the surface we're sweeping from is
38                // curved, there's simply no way to represent the curve of the
39                // resulting bottom edge.
40                todo!(
41                    "Sweeping a curve that is defined on a curved surface is \
42                    not supported yet."
43                )
44            }
45            GlobalPath::Line(_) => {
46                // We're sweeping from a curve on a flat surface, which is
47                // supported. Carry on.
48            }
49        }
50
51        let u = match curve {
52            Curve::Circle(circle) => {
53                let center = surface
54                    .geometry()
55                    .point_from_surface_coords(circle.center());
56                let a =
57                    surface.geometry().vector_from_surface_coords(circle.a());
58                let b =
59                    surface.geometry().vector_from_surface_coords(circle.b());
60
61                let circle = Circle::new(center, a, b);
62
63                GlobalPath::Circle(circle)
64            }
65            Curve::Line(line) => {
66                let origin =
67                    surface.geometry().point_from_surface_coords(line.origin());
68                let direction = surface
69                    .geometry()
70                    .vector_from_surface_coords(line.direction());
71
72                let line = Line::from_origin_and_direction(origin, direction);
73
74                GlobalPath::Line(line)
75            }
76        };
77
78        Surface::new(SurfaceGeometry { u, v: path.into() }).insert(services)
79    }
80}