fj_core/operations/sweep/path.rs
1use fj_math::{Circle, Line, Vector};
2
3use crate::{
4 geometry::{GlobalPath, SurfaceGeometry, SurfacePath},
5 objects::Surface,
6 operations::build::BuildSurface,
7 storage::Handle,
8 Core,
9};
10
11/// # Sweep a [`SurfacePath`]
12///
13/// See [module documentation] for more information.
14///
15/// [module documentation]: super
16pub trait SweepSurfacePath {
17 /// # Sweep the surface path
18 ///
19 /// Requires a reference to the surface that the path is defined on.
20 ///
21 ///
22 /// ## Implementation Note
23 ///
24 /// Sweeping a `SurfacePath` that is defined on a curved surface is
25 /// currently not supported:
26 /// <https://github.com/hannobraun/fornjot/issues/1112>
27 fn sweep_surface_path(
28 &self,
29 surface: &SurfaceGeometry,
30 path: impl Into<Vector<3>>,
31 core: &mut Core,
32 ) -> Handle<Surface>;
33}
34
35impl SweepSurfacePath for SurfacePath {
36 fn sweep_surface_path(
37 &self,
38 surface: &SurfaceGeometry,
39 path: impl Into<Vector<3>>,
40 core: &mut Core,
41 ) -> Handle<Surface> {
42 match surface.u {
43 GlobalPath::Circle(_) => {
44 // Sweeping a `Curve` creates a `Surface`. The u-axis of that
45 // `Surface` is a `GlobalPath`, which we are computing below.
46 // That computation might or might not work with an arbitrary
47 // surface. Probably not, but I'm not sure.
48 //
49 // What definitely won't work, is computing the bottom edge of
50 // the sweep. The edge sweeping code currently assumes that the
51 // bottom edge is a line (which is true when sweeping from a
52 // flat surface). But is the surface we're sweeping from is
53 // curved, there's simply no way to represent the curve of the
54 // resulting bottom edge.
55 todo!(
56 "Sweeping a curve that is defined on a curved surface is \
57 not supported yet."
58 )
59 }
60 GlobalPath::Line(_) => {
61 // We're sweeping from a curve on a flat surface, which is
62 // supported. Carry on.
63 }
64 }
65
66 let u = match self {
67 SurfacePath::Circle(circle) => {
68 let center = surface.point_from_surface_coords(circle.center());
69 let a = surface.vector_from_surface_coords(circle.a());
70 let b = surface.vector_from_surface_coords(circle.b());
71
72 let circle = Circle::new(center, a, b);
73
74 GlobalPath::Circle(circle)
75 }
76 SurfacePath::Line(line) => {
77 let origin = surface.point_from_surface_coords(line.origin());
78 let direction =
79 surface.vector_from_surface_coords(line.direction());
80
81 let line = Line::from_origin_and_direction(origin, direction);
82
83 GlobalPath::Line(line)
84 }
85 };
86
87 Surface::surface_from_uv(u, path, core)
88 }
89}