From 582fcbddd5ec6825c6fad7e30ca897ef2567c527 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 10:15:09 +0100 Subject: [PATCH 01/18] Add dedicated directory for `services` --- crates/fj-kernel/src/{services.rs => services/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/fj-kernel/src/{services.rs => services/mod.rs} (100%) diff --git a/crates/fj-kernel/src/services.rs b/crates/fj-kernel/src/services/mod.rs similarity index 100% rename from crates/fj-kernel/src/services.rs rename to crates/fj-kernel/src/services/mod.rs From aaf5a8bc2ff76bda7fb5bbf862efdb1314fa9621 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:20:23 +0100 Subject: [PATCH 02/18] Move service infrastructure to dedicated module --- crates/fj-kernel/src/services/mod.rs | 121 +---------------------- crates/fj-kernel/src/services/service.rs | 118 ++++++++++++++++++++++ 2 files changed, 121 insertions(+), 118 deletions(-) create mode 100644 crates/fj-kernel/src/services/service.rs diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index 264c2a05b..f12581955 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -2,130 +2,15 @@ //! //! See [`Service`]. -use std::ops::Deref; +mod service; + +pub use self::service::{Service, State}; use crate::{ objects::{Object, Objects, WithHandle}, storage::Handle, }; -/// A service that controls access to some state -/// -/// `Service` is a generic wrapper around some state, as well as code that knows -/// how to operate on that state. It processes commands, changes the state based -/// on those command, and produces events that capture these changes. These -/// events are stored, providing a log of all changes to the state, and can be -/// replayed later to re-create the state at any point in time. -/// -/// The wrapped state must implement [`State`], which defines the type of -/// command that this service processes, and the type of event that captures -/// state changes. It also defines methods that operate on the state, commands, -/// and events. -/// -/// Implementations of [`State`] might also define an extension trait for a -/// specific `Service`, to provide a convenient API to callers. -/// -/// This design takes inspiration from, and uses the nomenclature of, this -/// article: -/// -pub struct Service { - state: S, - events: Vec, -} - -impl Service { - /// Create an instance of `Service` - pub fn new(state: S) -> Self { - Self { - state, - events: Vec::new(), - } - } - - /// Execute a command - /// - /// The command is executed synchronously. When this method returns, the - /// state has been updated and any events have been logged. - pub fn execute(&mut self, command: S::Command) { - let mut events = Vec::new(); - self.state.decide(command, &mut events); - - for event in &events { - self.state.evolve(event); - } - - self.events.extend(events); - } - - /// Access the events - pub fn events(&self) -> impl Iterator { - self.events.iter() - } - - /// Replay the provided events on the given state - pub fn replay<'event>( - state: &mut S, - events: impl IntoIterator, - ) where - ::Event: 'event, - { - for event in events { - state.evolve(event); - } - } -} - -impl Deref for Service { - type Target = S; - - fn deref(&self) -> &Self::Target { - &self.state - } -} - -/// Implemented for state that can be wrapped by a [`Service`] -/// -/// See [`Service`] for a detailed explanation. -pub trait State { - /// A command that relates to the state - /// - /// Commands are processed by [`State::decide`]. - type Command; - - /// An event that captures modifications to this state - /// - /// Events are produced by [`State::decide`] and processed by - /// [`State::evolve`]. - type Event; - - /// Convert this state into the service that wraps it - /// - /// This is a convenience method that just calls [`Service::new`] - /// internally. - fn into_service(self) -> Service - where - Self: Sized, - { - Service::new(self) - } - - /// Decide how to react to the provided command - /// - /// If the command must result in changes to the state, any number of events - /// that describe these state changes can be produced. - fn decide(&self, command: Self::Command, events: &mut Vec); - - /// Evolve the state according to the provided event - /// - /// This is the only method gets mutable access to the state, making sure - /// that all changes to the state are captured as events. - /// - /// Implementations of this method are supposed to be relatively dumb. Any - /// decisions that go into updating the state should be made in - /// [`State::decide`], and encoded into the event. - fn evolve(&mut self, event: &Self::Event); -} - impl State for Objects { type Command = InsertObject; type Event = ObjectToInsert; diff --git a/crates/fj-kernel/src/services/service.rs b/crates/fj-kernel/src/services/service.rs new file mode 100644 index 000000000..9ceaaa1e4 --- /dev/null +++ b/crates/fj-kernel/src/services/service.rs @@ -0,0 +1,118 @@ +use std::ops::Deref; + +/// A service that controls access to some state +/// +/// `Service` is a generic wrapper around some state, as well as code that knows +/// how to operate on that state. It processes commands, changes the state based +/// on those command, and produces events that capture these changes. These +/// events are stored, providing a log of all changes to the state, and can be +/// replayed later to re-create the state at any point in time. +/// +/// The wrapped state must implement [`State`], which defines the type of +/// command that this service processes, and the type of event that captures +/// state changes. It also defines methods that operate on the state, commands, +/// and events. +/// +/// Implementations of [`State`] might also define an extension trait for a +/// specific `Service`, to provide a convenient API to callers. +/// +/// This design takes inspiration from, and uses the nomenclature of, this +/// article: +/// +pub struct Service { + state: S, + events: Vec, +} + +impl Service { + /// Create an instance of `Service` + pub fn new(state: S) -> Self { + Self { + state, + events: Vec::new(), + } + } + + /// Execute a command + /// + /// The command is executed synchronously. When this method returns, the + /// state has been updated and any events have been logged. + pub fn execute(&mut self, command: S::Command) { + let mut events = Vec::new(); + self.state.decide(command, &mut events); + + for event in &events { + self.state.evolve(event); + } + + self.events.extend(events); + } + + /// Access the events + pub fn events(&self) -> impl Iterator { + self.events.iter() + } + + /// Replay the provided events on the given state + pub fn replay<'event>( + state: &mut S, + events: impl IntoIterator, + ) where + ::Event: 'event, + { + for event in events { + state.evolve(event); + } + } +} + +impl Deref for Service { + type Target = S; + + fn deref(&self) -> &Self::Target { + &self.state + } +} + +/// Implemented for state that can be wrapped by a [`Service`] +/// +/// See [`Service`] for a detailed explanation. +pub trait State { + /// A command that relates to the state + /// + /// Commands are processed by [`State::decide`]. + type Command; + + /// An event that captures modifications to this state + /// + /// Events are produced by [`State::decide`] and processed by + /// [`State::evolve`]. + type Event; + + /// Convert this state into the service that wraps it + /// + /// This is a convenience method that just calls [`Service::new`] + /// internally. + fn into_service(self) -> Service + where + Self: Sized, + { + Service::new(self) + } + + /// Decide how to react to the provided command + /// + /// If the command must result in changes to the state, any number of events + /// that describe these state changes can be produced. + fn decide(&self, command: Self::Command, events: &mut Vec); + + /// Evolve the state according to the provided event + /// + /// This is the only method gets mutable access to the state, making sure + /// that all changes to the state are captured as events. + /// + /// Implementations of this method are supposed to be relatively dumb. Any + /// decisions that go into updating the state should be made in + /// [`State::decide`], and encoded into the event. + fn evolve(&mut self, event: &Self::Event); +} From d2c438b0af78484ba375df670f4d124829261cbb Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:22:04 +0100 Subject: [PATCH 03/18] Move objects service to dedicated module --- crates/fj-kernel/src/services/mod.rs | 63 ++---------------------- crates/fj-kernel/src/services/objects.rs | 60 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 59 deletions(-) create mode 100644 crates/fj-kernel/src/services/objects.rs diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index f12581955..639e79c5f 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -2,65 +2,10 @@ //! //! See [`Service`]. +mod objects; mod service; -pub use self::service::{Service, State}; - -use crate::{ - objects::{Object, Objects, WithHandle}, - storage::Handle, +pub use self::{ + objects::ServiceObjectsExt, + service::{Service, State}, }; - -impl State for Objects { - type Command = InsertObject; - type Event = ObjectToInsert; - - fn decide(&self, command: Self::Command, events: &mut Vec) { - let event = ObjectToInsert { - object: command.object, - }; - events.push(event); - } - - fn evolve(&mut self, event: &Self::Event) { - // This operation being fallible goes against the spirit of the `evolve` - // method. The reason for that is, that `Objects` is not fully adapted - // to this new design yet. In the future, validation will most likely - // move into its own service, making this operation infallible. - event.object.clone().insert(self).unwrap(); - } -} - -/// Command for `Service` -/// -/// You might prefer to use [`ServiceObjectsExt::insert`], which is a convenient -/// wrapper around `Service::execute`. -pub struct InsertObject { - /// The object to insert - pub object: Object, -} - -/// Event produced by `Service` -pub struct ObjectToInsert { - /// The object to insert - pub object: Object, -} - -/// Convenient API for `Service` -pub trait ServiceObjectsExt { - /// Insert an object - fn insert(&mut self, handle: Handle, object: T) - where - (Handle, T): Into>; -} - -impl ServiceObjectsExt for Service { - fn insert(&mut self, handle: Handle, object: T) - where - (Handle, T): Into>, - { - self.execute(InsertObject { - object: (handle, object).into(), - }) - } -} diff --git a/crates/fj-kernel/src/services/objects.rs b/crates/fj-kernel/src/services/objects.rs new file mode 100644 index 000000000..b733e2407 --- /dev/null +++ b/crates/fj-kernel/src/services/objects.rs @@ -0,0 +1,60 @@ +use crate::{ + objects::{Object, Objects, WithHandle}, + storage::Handle, +}; + +use super::{Service, State}; + +impl State for Objects { + type Command = InsertObject; + type Event = ObjectToInsert; + + fn decide(&self, command: Self::Command, events: &mut Vec) { + let event = ObjectToInsert { + object: command.object, + }; + events.push(event); + } + + fn evolve(&mut self, event: &Self::Event) { + // This operation being fallible goes against the spirit of the `evolve` + // method. The reason for that is, that `Objects` is not fully adapted + // to this new design yet. In the future, validation will most likely + // move into its own service, making this operation infallible. + event.object.clone().insert(self).unwrap(); + } +} + +/// Command for `Service` +/// +/// You might prefer to use [`ServiceObjectsExt::insert`], which is a convenient +/// wrapper around `Service::execute`. +pub struct InsertObject { + /// The object to insert + pub object: Object, +} + +/// Event produced by `Service` +pub struct ObjectToInsert { + /// The object to insert + pub object: Object, +} + +/// Convenient API for `Service` +pub trait ServiceObjectsExt { + /// Insert an object + fn insert(&mut self, handle: Handle, object: T) + where + (Handle, T): Into>; +} + +impl ServiceObjectsExt for Service { + fn insert(&mut self, handle: Handle, object: T) + where + (Handle, T): Into>, + { + self.execute(InsertObject { + object: (handle, object).into(), + }) + } +} From c8c588b41b50ea4f15401ebd2e2d0b1d4b7c3467 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:34:37 +0100 Subject: [PATCH 04/18] Implement `Default` for `Service` --- crates/fj-kernel/src/services/service.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/fj-kernel/src/services/service.rs b/crates/fj-kernel/src/services/service.rs index 9ceaaa1e4..f540331ee 100644 --- a/crates/fj-kernel/src/services/service.rs +++ b/crates/fj-kernel/src/services/service.rs @@ -74,6 +74,15 @@ impl Deref for Service { } } +impl Default for Service +where + S: Default, +{ + fn default() -> Self { + Self::new(S::default()) + } +} + /// Implemented for state that can be wrapped by a [`Service`] /// /// See [`Service`] for a detailed explanation. From d1585b8e842e7685033ee59eab771a4483c6cdcd Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:35:16 +0100 Subject: [PATCH 05/18] Add `Services` --- crates/fj-kernel/src/services/mod.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index 639e79c5f..4f52467c4 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -5,7 +5,28 @@ mod objects; mod service; +use crate::objects::Objects; + pub use self::{ objects::ServiceObjectsExt, service::{Service, State}, }; + +/// The kernel services +#[derive(Default)] +pub struct Services { + /// The objects service + /// + /// Allows for inserting objects into a store after they were created. + /// + /// [`ServiceObjectsExt`] is available to provide a convenient API around + /// this service. + pub objects: Service, +} + +impl Services { + /// Construct an instance of `Services` + pub fn new() -> Self { + Self::default() + } +} From 34a3dc9814ddc121a6e50dfce9b051f84fcc876a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:55:15 +0100 Subject: [PATCH 06/18] Use `Services` in tests --- .../fj-kernel/src/algorithms/approx/curve.rs | 43 ++++++---- .../src/algorithms/intersect/curve_edge.rs | 36 ++++---- .../src/algorithms/intersect/curve_face.rs | 12 +-- .../src/algorithms/intersect/face_face.rs | 41 +++++---- .../src/algorithms/intersect/face_point.rs | 68 +++++++-------- .../src/algorithms/intersect/ray_face.rs | 72 ++++++++-------- .../algorithms/intersect/surface_surface.rs | 26 +++--- crates/fj-kernel/src/algorithms/sweep/edge.rs | 44 +++++----- crates/fj-kernel/src/algorithms/sweep/face.rs | 68 ++++++++------- .../fj-kernel/src/algorithms/sweep/vertex.rs | 24 +++--- .../src/algorithms/triangulate/mod.rs | 28 +++--- crates/fj-kernel/src/builder/edge.rs | 9 +- crates/fj-kernel/src/iter.rs | 86 ++++++++++--------- crates/fj-kernel/src/objects/full/edge.rs | 11 ++- crates/fj-kernel/src/validate/cycle.rs | 14 +-- crates/fj-kernel/src/validate/edge.rs | 44 ++++++---- crates/fj-kernel/src/validate/face.rs | 24 +++--- crates/fj-kernel/src/validate/vertex.rs | 33 +++---- 18 files changed, 363 insertions(+), 320 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index f55e2c4f4..bd9401386 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -203,27 +203,28 @@ mod tests { builder::{CurveBuilder, SurfaceBuilder}, geometry::path::GlobalPath, insert::Insert, - objects::Objects, partial::{PartialCurve, PartialSurface}, - services::State, + services::Services, }; use super::CurveApprox; #[test] fn approx_line_on_flat_surface() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let surface = PartialSurface::from_axes(GlobalPath::x_axis(), [0., 0., 1.]) - .build(&objects) - .insert(&mut objects); + .build(&services.objects) + .insert(&mut services.objects); let mut curve = PartialCurve { surface: Some(surface), ..Default::default() }; curve.update_as_line_from_points([[1., 1.], [2., 1.]]); - let curve = curve.build(&mut objects).insert(&mut objects); + let curve = curve + .build(&mut services.objects) + .insert(&mut services.objects); let range = RangeOnPath::from([[0.], [1.]]); let approx = (&curve, range).approx(1.); @@ -233,20 +234,22 @@ mod tests { #[test] fn approx_line_on_curved_surface_but_not_along_curve() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let surface = PartialSurface::from_axes( GlobalPath::circle_from_radius(1.), [0., 0., 1.], ) - .build(&objects) - .insert(&mut objects); + .build(&services.objects) + .insert(&mut services.objects); let mut curve = PartialCurve { surface: Some(surface), ..Default::default() }; curve.update_as_line_from_points([[1., 1.], [1., 2.]]); - let curve = curve.build(&mut objects).insert(&mut objects); + let curve = curve + .build(&mut services.objects) + .insert(&mut services.objects); let range = RangeOnPath::from([[0.], [1.]]); let approx = (&curve, range).approx(1.); @@ -256,18 +259,20 @@ mod tests { #[test] fn approx_line_on_curved_surface_along_curve() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let path = GlobalPath::circle_from_radius(1.); let surface = PartialSurface::from_axes(path, [0., 0., 1.]) - .build(&objects) - .insert(&mut objects); + .build(&services.objects) + .insert(&mut services.objects); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_line_from_points([[0., 1.], [1., 1.]]); - let curve = curve.build(&mut objects).insert(&mut objects); + let curve = curve + .build(&mut services.objects) + .insert(&mut services.objects); let range = RangeOnPath::from([[0.], [TAU]]); let tolerance = 1.; @@ -290,18 +295,20 @@ mod tests { #[test] fn approx_circle_on_flat_surface() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let surface = PartialSurface::from_axes(GlobalPath::x_axis(), [0., 0., 1.]) - .build(&objects) - .insert(&mut objects); + .build(&services.objects) + .insert(&mut services.objects); let mut curve = PartialCurve { surface: Some(surface), ..Default::default() }; curve.update_as_circle_from_radius(1.); - let curve = curve.build(&mut objects).insert(&mut objects); + let curve = curve + .build(&mut services.objects) + .insert(&mut services.objects); let range = RangeOnPath::from([[0.], [TAU]]); let tolerance = 1.; diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index dce4d3251..fa058e33e 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -76,27 +76,27 @@ mod tests { use crate::{ builder::{CurveBuilder, HalfEdgeBuilder}, - objects::{HalfEdge, Objects}, + objects::HalfEdge, partial::{HasPartial, PartialCurve}, - services::State, + services::Services, }; use super::CurveEdgeIntersection; #[test] fn compute_edge_in_front_of_curve_origin() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_u_axis(); - let curve = curve.build(&mut objects); + let curve = curve.build(&mut services.objects); let half_edge = HalfEdge::partial() .update_as_line_segment_from_points(surface, [[1., -1.], [1., 1.]]) - .build(&mut objects); + .build(&mut services.objects); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -110,21 +110,21 @@ mod tests { #[test] fn compute_edge_behind_curve_origin() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_u_axis(); - let curve = curve.build(&mut objects); + let curve = curve.build(&mut services.objects); let half_edge = HalfEdge::partial() .update_as_line_segment_from_points( surface, [[-1., -1.], [-1., 1.]], ) - .build(&mut objects); + .build(&mut services.objects); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -138,21 +138,21 @@ mod tests { #[test] fn compute_edge_parallel_to_curve() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_u_axis(); - let curve = curve.build(&mut objects); + let curve = curve.build(&mut services.objects); let half_edge = HalfEdge::partial() .update_as_line_segment_from_points( surface, [[-1., -1.], [1., -1.]], ) - .build(&mut objects); + .build(&mut services.objects); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -161,18 +161,18 @@ mod tests { #[test] fn compute_edge_on_curve() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_u_axis(); - let curve = curve.build(&mut objects); + let curve = curve.build(&mut services.objects); let half_edge = HalfEdge::partial() .update_as_line_segment_from_points(surface, [[-1., 0.], [1., 0.]]) - .build(&mut objects); + .build(&mut services.objects); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs index 737d5b969..7aee99816 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs @@ -151,25 +151,25 @@ where mod tests { use crate::{ builder::{CurveBuilder, FaceBuilder}, - objects::{Face, Objects}, + objects::Face, partial::{HasPartial, PartialCurve}, - services::State, + services::Services, }; use super::CurveFaceIntersection; #[test] fn compute() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_line_from_points([[-3., 0.], [-2., 0.]]); - let curve = curve.build(&mut objects); + let curve = curve.build(&mut services.objects); #[rustfmt::skip] let exterior = [ @@ -190,7 +190,7 @@ mod tests { .with_surface(surface) .with_exterior_polygon_from_points(exterior) .with_interior_polygon_from_points(interior) - .build(&mut objects); + .build(&mut services.objects); let expected = CurveFaceIntersection::from_intervals([[[1.], [2.]], [[4.], [5.]]]); diff --git a/crates/fj-kernel/src/algorithms/intersect/face_face.rs b/crates/fj-kernel/src/algorithms/intersect/face_face.rs index a2fefd953..f7dd3549e 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_face.rs @@ -71,16 +71,16 @@ mod tests { algorithms::intersect::CurveFaceIntersection, builder::{CurveBuilder, FaceBuilder}, insert::Insert, - objects::{Face, Objects}, + objects::Face, partial::{HasPartial, PartialCurve}, - services::State, + services::Services, }; use super::FaceFaceIntersection; #[test] fn compute_no_intersection() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); #[rustfmt::skip] let points = [ @@ -89,23 +89,26 @@ mod tests { [2., 2.], [1., 2.], ]; - let [a, b] = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()] - .map(|surface| { - Face::partial() - .with_surface(surface) - .with_exterior_polygon_from_points(points) - .build(&mut objects) - }); + let [a, b] = [ + services.objects.surfaces.xy_plane(), + services.objects.surfaces.xz_plane(), + ] + .map(|surface| { + Face::partial() + .with_surface(surface) + .with_exterior_polygon_from_points(points) + .build(&mut services.objects) + }); let intersection = - FaceFaceIntersection::compute([&a, &b], &mut objects); + FaceFaceIntersection::compute([&a, &b], &mut services.objects); assert!(intersection.is_none()); } #[test] fn compute_one_intersection() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); #[rustfmt::skip] let points = [ @@ -114,17 +117,19 @@ mod tests { [ 1., 1.], [-1., 1.], ]; - let surfaces = - [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()]; + let surfaces = [ + services.objects.surfaces.xy_plane(), + services.objects.surfaces.xz_plane(), + ]; let [a, b] = surfaces.clone().map(|surface| { Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(points) - .build(&mut objects) + .build(&mut services.objects) }); let intersection = - FaceFaceIntersection::compute([&a, &b], &mut objects); + FaceFaceIntersection::compute([&a, &b], &mut services.objects); let expected_curves = surfaces.map(|surface| { let mut curve = PartialCurve { @@ -132,7 +137,9 @@ mod tests { ..Default::default() }; curve.update_as_line_from_points([[0., 0.], [1., 0.]]); - curve.build(&mut objects).insert(&mut objects) + curve + .build(&mut services.objects) + .insert(&mut services.objects) }); let expected_intervals = CurveFaceIntersection::from_intervals([[[-1.], [1.]]]); diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index 375ddc9ed..90aea9fdc 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -139,21 +139,21 @@ mod tests { builder::FaceBuilder, insert::Insert, iter::ObjectIters, - objects::{Face, Objects}, + objects::Face, partial::HasPartial, - services::State, + services::Services, }; #[test] fn point_is_outside_face() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 1.], [0., 2.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([2., 1.]); let intersection = (&face, &point).intersect(); @@ -162,14 +162,14 @@ mod tests { #[test] fn ray_hits_vertex_while_passing_outside() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 1.], [0., 2.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -181,14 +181,14 @@ mod tests { #[test] fn ray_hits_vertex_at_cycle_seam() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[4., 2.], [0., 4.], [0., 0.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 2.]); let intersection = (&face, &point).intersect(); @@ -200,9 +200,9 @@ mod tests { #[test] fn ray_hits_vertex_while_staying_inside() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -211,8 +211,8 @@ mod tests { [3., 0.], [3., 4.], ]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -224,9 +224,9 @@ mod tests { #[test] fn ray_hits_parallel_edge_and_leaves_face_at_vertex() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -235,8 +235,8 @@ mod tests { [3., 1.], [0., 2.], ]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -248,9 +248,9 @@ mod tests { #[test] fn ray_hits_parallel_edge_and_does_not_leave_face_there() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -260,8 +260,8 @@ mod tests { [4., 0.], [4., 5.], ]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -273,14 +273,14 @@ mod tests { #[test] fn point_is_coincident_with_edge() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 0.], [0., 1.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 0.]); let intersection = (&face, &point).intersect(); @@ -301,14 +301,14 @@ mod tests { #[test] fn point_is_coincident_with_vertex() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let point = Point::from([1., 0.]); let intersection = (&face, &point).intersect(); diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index 16e2ed4ed..5bc0273c1 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -155,18 +155,18 @@ mod tests { builder::FaceBuilder, insert::Insert, iter::ObjectIters, - objects::{Face, Objects}, + objects::Face, partial::HasPartial, - services::State, + services::Services, }; #[test] fn ray_misses_whole_surface() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.yz_plane(); + let surface = services.objects.surfaces.yz_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -175,20 +175,20 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects) - .translate([-1., 0., 0.], &mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .translate([-1., 0., 0.], &mut services.objects); assert_eq!((&ray, &face).intersect(), None); } #[test] fn ray_hits_face() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.yz_plane(); + let surface = services.objects.surfaces.yz_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -197,9 +197,9 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects) - .translate([1., 0., 0.], &mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .translate([1., 0., 0.], &mut services.objects); assert_eq!( (&ray, &face).intersect(), @@ -209,11 +209,11 @@ mod tests { #[test] fn ray_hits_surface_but_misses_face() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.yz_plane(); + let surface = services.objects.surfaces.yz_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -222,20 +222,20 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects) - .translate([0., 0., 2.], &mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .translate([0., 0., 2.], &mut services.objects); assert_eq!((&ray, &face).intersect(), None); } #[test] fn ray_hits_edge() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.yz_plane(); + let surface = services.objects.surfaces.yz_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -244,9 +244,9 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects) - .translate([1., 1., 0.], &mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .translate([1., 1., 0.], &mut services.objects); let edge = face .half_edge_iter() @@ -264,11 +264,11 @@ mod tests { #[test] fn ray_hits_vertex() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.yz_plane(); + let surface = services.objects.surfaces.yz_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -277,9 +277,9 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects) - .translate([1., 1., 1.], &mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .translate([1., 1., 1.], &mut services.objects); let vertex = face .vertex_iter() @@ -295,11 +295,11 @@ mod tests { #[test] fn ray_is_parallel_to_surface_and_hits() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -308,8 +308,8 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!( (&ray, &face).intersect(), @@ -319,11 +319,11 @@ mod tests { #[test] fn ray_is_parallel_to_surface_and_misses() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ @@ -332,9 +332,9 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(&mut objects) - .insert(&mut objects) - .translate([0., 0., 1.], &mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .translate([0., 0., 1.], &mut services.objects); assert_eq!((&ray, &face).intersect(), None); } diff --git a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs index 01e73c4b8..baf1e7c0d 100644 --- a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs @@ -90,18 +90,17 @@ mod tests { use crate::{ algorithms::transform::TransformObject, builder::CurveBuilder, - insert::Insert, objects::Objects, partial::PartialCurve, - services::State, + insert::Insert, partial::PartialCurve, services::Services, }; use super::SurfaceSurfaceIntersection; #[test] fn plane_plane() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let xy = objects.surfaces.xy_plane(); - let xz = objects.surfaces.xz_plane(); + let xy = services.objects.surfaces.xy_plane(); + let xz = services.objects.surfaces.xz_plane(); // Coincident and parallel planes don't have an intersection curve. assert_eq!( @@ -110,10 +109,10 @@ mod tests { xy.clone(), xy.clone().transform( &Transform::translation([0., 0., 1.],), - &mut objects + &mut services.objects ) ], - &mut objects + &mut services.objects ), None, ); @@ -123,16 +122,23 @@ mod tests { ..Default::default() }; expected_xy.update_as_u_axis(); - let expected_xy = expected_xy.build(&mut objects).insert(&mut objects); + let expected_xy = expected_xy + .build(&mut services.objects) + .insert(&mut services.objects); let mut expected_xz = PartialCurve { surface: Some(xz.clone()), ..Default::default() }; expected_xz.update_as_u_axis(); - let expected_xz = expected_xz.build(&mut objects).insert(&mut objects); + let expected_xz = expected_xz + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!( - SurfaceSurfaceIntersection::compute([xy, xz], &mut objects), + SurfaceSurfaceIntersection::compute( + [xy, xz], + &mut services.objects + ), Some(SurfaceSurfaceIntersection { intersection_curves: [expected_xy, expected_xz], }) diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index d1a9ac051..5b2a5ca02 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -191,36 +191,36 @@ mod tests { algorithms::{reverse::Reverse, sweep::Sweep}, builder::HalfEdgeBuilder, insert::Insert, - objects::{Cycle, Face, HalfEdge, Objects}, + objects::{Cycle, Face, HalfEdge}, partial::{HasPartial, PartialSurfaceVertex, PartialVertex, Replace}, - services::State, + services::Services, }; #[test] fn sweep() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let half_edge = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.]], ) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); - let face = - (half_edge, Color::default()).sweep([0., 0., 1.], &mut objects); + let face = (half_edge, Color::default()) + .sweep([0., 0., 1.], &mut services.objects); let expected_face = { - let surface = objects.surfaces.xz_plane(); + let surface = services.objects.surfaces.xz_plane(); let bottom = HalfEdge::partial() .update_as_line_segment_from_points( surface.clone(), [[0., 0.], [1., 0.]], ) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let side_up = { let mut side_up = HalfEdge::partial(); side_up.replace(surface.clone()); @@ -242,8 +242,8 @@ mod tests { ..Default::default() }) .update_as_line_segment() - .build(&mut objects) - .insert(&mut objects) + .build(&mut services.objects) + .insert(&mut services.objects) }; let top = { let mut top = HalfEdge::partial(); @@ -261,9 +261,9 @@ mod tests { ..Default::default() }) .update_as_line_segment() - .build(&mut objects) - .insert(&mut objects) - .reverse(&mut objects) + .build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects) }; let side_down = { let mut side_down = HalfEdge::partial(); @@ -282,18 +282,18 @@ mod tests { ..Default::default() }) .update_as_line_segment() - .build(&mut objects) - .insert(&mut objects) - .reverse(&mut objects) + .build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects) }; let cycle = Cycle::new([bottom, side_up, top, side_down]) - .insert(&mut objects); + .insert(&mut services.objects); Face::partial() .with_exterior(cycle) - .build(&mut objects) - .insert(&mut objects) + .build(&mut services.objects) + .insert(&mut services.objects) }; assert_eq!(face, expected_face); diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 2447a35a6..0abe0d756 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -86,9 +86,9 @@ mod tests { algorithms::{reverse::Reverse, transform::TransformObject}, builder::{FaceBuilder, HalfEdgeBuilder}, insert::Insert, - objects::{Face, HalfEdge, Objects, Sketch}, + objects::{Face, HalfEdge, Sketch}, partial::HasPartial, - services::State, + services::Services, }; use super::Sweep; @@ -100,26 +100,26 @@ mod tests { #[test] fn sweep_up() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let solid = Sketch::builder() .with_surface(surface.clone()) - .with_polygon_from_points(TRIANGLE, &mut objects) - .build(&mut objects) - .sweep(UP, &mut objects); + .with_polygon_from_points(TRIANGLE, &mut services.objects) + .build(&mut services.objects) + .sweep(UP, &mut services.objects); let bottom = Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points(TRIANGLE) - .build(&mut objects) - .insert(&mut objects) - .reverse(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects); let top = Face::partial() - .with_surface(surface.translate(UP, &mut objects)) + .with_surface(surface.translate(UP, &mut services.objects)) .with_exterior_polygon_from_points(TRIANGLE) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert!(solid.find_face(&bottom).is_some()); assert!(solid.find_face(&top).is_some()); @@ -128,12 +128,12 @@ mod tests { let side_faces = triangle.array_windows_ext().map(|&[a, b]| { let half_edge = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [a, b], ) - .build(&mut objects) - .insert(&mut objects); - (half_edge, Color::default()).sweep(UP, &mut objects) + .build(&mut services.objects) + .insert(&mut services.objects); + (half_edge, Color::default()).sweep(UP, &mut services.objects) }); assert!(side_faces @@ -143,26 +143,28 @@ mod tests { #[test] fn sweep_down() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let solid = Sketch::builder() .with_surface(surface.clone()) - .with_polygon_from_points(TRIANGLE, &mut objects) - .build(&mut objects) - .sweep(DOWN, &mut objects); + .with_polygon_from_points(TRIANGLE, &mut services.objects) + .build(&mut services.objects) + .sweep(DOWN, &mut services.objects); let bottom = Face::partial() - .with_surface(surface.clone().translate(DOWN, &mut objects)) + .with_surface( + surface.clone().translate(DOWN, &mut services.objects), + ) .with_exterior_polygon_from_points(TRIANGLE) - .build(&mut objects) - .insert(&mut objects) - .reverse(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects); let top = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(TRIANGLE) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert!(solid.find_face(&bottom).is_some()); assert!(solid.find_face(&top).is_some()); @@ -171,13 +173,13 @@ mod tests { let side_faces = triangle.array_windows_ext().map(|&[a, b]| { let half_edge = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [a, b], ) - .build(&mut objects) - .insert(&mut objects) - .reverse(&mut objects); - (half_edge, Color::default()).sweep(DOWN, &mut objects) + .build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects); + (half_edge, Color::default()).sweep(DOWN, &mut services.objects) }); assert!(side_faces diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index 8c3621525..8b5a98f77 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -164,37 +164,39 @@ mod tests { algorithms::sweep::Sweep, builder::{CurveBuilder, HalfEdgeBuilder}, insert::Insert, - objects::{HalfEdge, Objects}, + objects::HalfEdge, partial::{HasPartial, PartialCurve, PartialVertex}, - services::State, + services::Services, }; #[test] fn vertex_surface() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xz_plane(); + let surface = services.objects.surfaces.xz_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_u_axis(); - let curve = curve.build(&mut objects).insert(&mut objects); + let curve = curve + .build(&mut services.objects) + .insert(&mut services.objects); let vertex = PartialVertex { position: Some([0.].into()), curve: curve.into(), ..Default::default() } - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); - let half_edge = - (vertex, surface.clone()).sweep([0., 0., 1.], &mut objects); + let half_edge = (vertex, surface.clone()) + .sweep([0., 0., 1.], &mut services.objects); let expected_half_edge = HalfEdge::partial() .update_as_line_segment_from_points(surface, [[0., 0.], [0., 1.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!(half_edge, expected_half_edge); } } diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 6d01dd8ac..ac1e19022 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -79,9 +79,9 @@ mod tests { algorithms::approx::{Approx, Tolerance}, builder::FaceBuilder, insert::Insert, - objects::{Face, Objects}, + objects::Face, partial::HasPartial, - services::State, + services::Services, storage::Handle, }; @@ -89,19 +89,19 @@ mod tests { #[test] fn simple() -> anyhow::Result<()> { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let a = [0., 0.]; let b = [2., 0.]; let c = [2., 2.]; let d = [0., 1.]; - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([a, b, c, d]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let a = Point::from(a).to_xyz(); let b = Point::from(b).to_xyz(); @@ -120,7 +120,7 @@ mod tests { #[test] fn simple_hole() -> anyhow::Result<()> { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let a = [0., 0.]; let b = [4., 0.]; @@ -132,13 +132,13 @@ mod tests { let g = [3., 3.]; let h = [3., 1.]; - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d]) .with_interior_polygon_from_points([e, f, g, h]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let triangles = triangulate(face)?; @@ -172,7 +172,7 @@ mod tests { #[test] fn sharp_concave_shape() -> anyhow::Result<()> { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); // e c // |\ /| @@ -191,12 +191,12 @@ mod tests { let d = [0.1, 0.1]; let e = [0.0, 1.0]; - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d, e]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); let triangles = triangulate(face)?; diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 93ca073a6..3381151d3 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -8,7 +8,7 @@ use crate::{ MaybePartial, MergeWith, PartialGlobalEdge, PartialHalfEdge, PartialSurfaceVertex, PartialVertex, Replace, }, - services::{Service, State}, + services::{Service, Services}, storage::Handle, }; @@ -162,9 +162,12 @@ impl HalfEdgeBuilder for PartialHalfEdge { // a hack, but I can't think of something better. let global_forms = { let must_switch_order = { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let vertices = vertices.clone().map(|vertex| { - vertex.into_full(&mut objects).global_form().clone() + vertex + .into_full(&mut services.objects) + .global_form() + .clone() }); let (_, must_switch_order) = diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index 8d1b197ea..ee26673b3 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -367,22 +367,24 @@ mod tests { Sketch, Solid, SurfaceVertex, Vertex, }, partial::{HasPartial, PartialCurve}, - services::State, + services::Services, }; use super::ObjectIters as _; #[test] fn curve() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut object = PartialCurve { surface: Some(surface), ..Default::default() }; object.update_as_u_axis(); - let object = object.build(&mut objects).insert(&mut objects); + let object = object + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!(1, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); @@ -399,17 +401,17 @@ mod tests { #[test] fn cycle() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let object = Cycle::partial() .with_poly_chain_from_points( surface, [[0., 0.], [1., 0.], [0., 1.]], ) .close_with_line_segment() - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!(3, object.curve_iter().count()); assert_eq!(1, object.cycle_iter().count()); @@ -426,14 +428,14 @@ mod tests { #[test] fn face() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let object = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!(3, object.curve_iter().count()); assert_eq!(1, object.cycle_iter().count()); @@ -450,9 +452,9 @@ mod tests { #[test] fn global_curve() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let object = GlobalCurve.insert(&mut objects); + let object = GlobalCurve.insert(&mut services.objects); assert_eq!(0, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); @@ -469,10 +471,10 @@ mod tests { #[test] fn global_vertex() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let object = - GlobalVertex::from_position([0., 0., 0.]).insert(&mut objects); + let object = GlobalVertex::from_position([0., 0., 0.]) + .insert(&mut services.objects); assert_eq!(0, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); @@ -489,15 +491,15 @@ mod tests { #[test] fn half_edge() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let object = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.]], ) - .build(&mut objects) - .insert(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!(1, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); @@ -514,11 +516,11 @@ mod tests { #[test] fn shell() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let object = Shell::builder() - .with_cube_from_edge_length(1., &mut objects) - .build(&mut objects); + .with_cube_from_edge_length(1., &mut services.objects) + .build(&mut services.objects); assert_eq!(24, object.curve_iter().count()); assert_eq!(6, object.cycle_iter().count()); @@ -535,15 +537,17 @@ mod tests { #[test] fn sketch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build(&mut objects) - .insert(&mut objects); - let object = Sketch::builder().with_faces([face]).build(&mut objects); + .build(&mut services.objects) + .insert(&mut services.objects); + let object = Sketch::builder() + .with_faces([face]) + .build(&mut services.objects); assert_eq!(3, object.curve_iter().count()); assert_eq!(1, object.cycle_iter().count()); @@ -560,11 +564,11 @@ mod tests { #[test] fn solid() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let object = Solid::builder() - .with_cube_from_edge_length(1., &mut objects) - .build(&mut objects); + .with_cube_from_edge_length(1., &mut services.objects) + .build(&mut services.objects); assert_eq!(24, object.curve_iter().count()); assert_eq!(6, object.cycle_iter().count()); @@ -600,22 +604,24 @@ mod tests { #[test] fn vertex() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() }; curve.update_as_u_axis(); - let curve = curve.build(&mut objects).insert(&mut objects); - let global_vertex = - GlobalVertex::from_position([0., 0., 0.]).insert(&mut objects); + let curve = curve + .build(&mut services.objects) + .insert(&mut services.objects); + let global_vertex = GlobalVertex::from_position([0., 0., 0.]) + .insert(&mut services.objects); let surface_vertex = SurfaceVertex::new([0., 0.], surface, global_vertex) - .insert(&mut objects); - let object = - Vertex::new([0.], curve, surface_vertex).insert(&mut objects); + .insert(&mut services.objects); + let object = Vertex::new([0.], curve, surface_vertex) + .insert(&mut services.objects); assert_eq!(1, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index 416f8c20f..b5a77e34e 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -170,27 +170,26 @@ mod tests { use pretty_assertions::assert_eq; use crate::{ - builder::HalfEdgeBuilder, objects::Objects, partial::HasPartial, - services::State, + builder::HalfEdgeBuilder, partial::HasPartial, services::Services, }; use super::HalfEdge; #[test] fn global_edge_equality() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); - let surface = objects.surfaces.xy_plane(); + let surface = services.objects.surfaces.xy_plane(); let a = [0., 0.]; let b = [1., 0.]; let a_to_b = HalfEdge::partial() .update_as_line_segment_from_points(surface.clone(), [a, b]) - .build(&mut objects); + .build(&mut services.objects); let b_to_a = HalfEdge::partial() .update_as_line_segment_from_points(surface, [b, a]) - .build(&mut objects); + .build(&mut services.objects); assert_eq!(a_to_b.global_form(), b_to_a.global_form()); } diff --git a/crates/fj-kernel/src/validate/cycle.rs b/crates/fj-kernel/src/validate/cycle.rs index 8e6bbeb48..1252029b4 100644 --- a/crates/fj-kernel/src/validate/cycle.rs +++ b/crates/fj-kernel/src/validate/cycle.rs @@ -68,23 +68,23 @@ mod tests { use crate::{ builder::{CycleBuilder, HalfEdgeBuilder, VertexBuilder}, insert::Insert, - objects::{Cycle, Objects}, + objects::Cycle, partial::HasPartial, - services::State, + services::Services, validate::Validate, }; #[test] fn cycle_half_edge_connections() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = Cycle::partial() .with_poly_chain_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.], [0., 1.]], ) .close_with_line_segment() - .build(&mut objects); + .build(&mut services.objects); let invalid = { let mut half_edges = valid .half_edges() @@ -104,7 +104,9 @@ mod tests { .infer_global_form(); let half_edges = half_edges.into_iter().map(|half_edge| { - half_edge.build(&mut objects).insert(&mut objects) + half_edge + .build(&mut services.objects) + .insert(&mut services.objects) }); Cycle::new(half_edges) diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index d3baeb6a1..a21739507 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -201,28 +201,30 @@ mod tests { use crate::{ builder::{HalfEdgeBuilder, VertexBuilder}, insert::Insert, - objects::{GlobalCurve, HalfEdge, Objects}, + objects::{GlobalCurve, HalfEdge}, partial::HasPartial, - services::State, + services::Services, validate::Validate, }; #[test] fn half_edge_curve_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.]], ) - .build(&mut objects); + .build(&mut services.objects); let invalid = { let mut vertices = valid.vertices().clone(); let mut vertex = vertices[1].to_partial(); // Arranging for an equal but not identical curve here. vertex.curve = valid.curve().to_partial().into(); - vertices[1] = vertex.build(&mut objects).insert(&mut objects); + vertices[1] = vertex + .build(&mut services.objects) + .insert(&mut services.objects); HalfEdge::new(vertices, valid.global_form().clone()) }; @@ -233,18 +235,19 @@ mod tests { #[test] fn half_edge_global_curve_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.]], ) - .build(&mut objects); + .build(&mut services.objects); let invalid = HalfEdge::new(valid.vertices().clone(), { let mut tmp = valid.global_form().to_partial(); - tmp.curve = GlobalCurve.insert(&mut objects).into(); - tmp.build(&mut objects).insert(&mut objects) + tmp.curve = GlobalCurve.insert(&mut services.objects).into(); + tmp.build(&mut services.objects) + .insert(&mut services.objects) }); assert!(valid.validate().is_ok()); @@ -253,14 +256,14 @@ mod tests { #[test] fn half_edge_global_vertex_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.]], ) - .build(&mut objects); + .build(&mut services.objects); let invalid = HalfEdge::new(valid.vertices().clone(), { let mut tmp = valid.global_form().to_partial(); tmp.vertices = valid @@ -269,7 +272,8 @@ mod tests { .access_in_normalized_order() // Creating equal but not identical vertices here. .map(|vertex| vertex.to_partial().into()); - tmp.build(&mut objects).insert(&mut objects) + tmp.build(&mut services.objects) + .insert(&mut services.objects) }); assert!(valid.validate().is_ok()); @@ -278,20 +282,22 @@ mod tests { #[test] fn half_edge_vertices_are_coincident() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = HalfEdge::partial() .update_as_line_segment_from_points( - objects.surfaces.xy_plane(), + services.objects.surfaces.xy_plane(), [[0., 0.], [1., 0.]], ) - .build(&mut objects); + .build(&mut services.objects); let invalid = HalfEdge::new( valid.vertices().clone().map(|vertex| { let mut vertex = vertex.to_partial(); vertex.position = Some([0.].into()); vertex.infer_surface_form(); - vertex.build(&mut objects).insert(&mut objects) + vertex + .build(&mut services.objects) + .insert(&mut services.objects) }), valid.global_form().clone(), ); diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index a6f040e8a..58391a8a5 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -107,30 +107,30 @@ mod tests { algorithms::reverse::Reverse, builder::{CycleBuilder, FaceBuilder}, insert::Insert, - objects::{Cycle, Face, Objects}, + objects::{Cycle, Face}, partial::HasPartial, - services::State, + services::Services, validate::Validate, }; #[test] fn face_surface_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = Face::partial() - .with_surface(objects.surfaces.xy_plane()) + .with_surface(services.objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) - .build(&mut objects); + .build(&mut services.objects); let invalid = { let interiors = [Cycle::partial() .with_poly_chain_from_points( - objects.surfaces.xz_plane(), + services.objects.surfaces.xz_plane(), [[1., 1.], [1., 2.], [2., 1.]], ) .close_with_line_segment() - .build(&mut objects) - .insert(&mut objects)]; + .build(&mut services.objects) + .insert(&mut services.objects)]; Face::new(valid.exterior().clone(), interiors, valid.color()) }; @@ -141,18 +141,18 @@ mod tests { #[test] fn face_invalid_interior_winding() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = Face::partial() - .with_surface(objects.surfaces.xy_plane()) + .with_surface(services.objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) - .build(&mut objects); + .build(&mut services.objects); let invalid = { let interiors = valid .interiors() .cloned() - .map(|cycle| cycle.reverse(&mut objects)) + .map(|cycle| cycle.reverse(&mut services.objects)) .collect::>(); Face::new(valid.exterior().clone(), interiors, valid.color()) diff --git a/crates/fj-kernel/src/validate/vertex.rs b/crates/fj-kernel/src/validate/vertex.rs index 8e98b4bca..a27afba8b 100644 --- a/crates/fj-kernel/src/validate/vertex.rs +++ b/crates/fj-kernel/src/validate/vertex.rs @@ -182,20 +182,20 @@ mod tests { use crate::{ builder::{CurveBuilder, SurfaceVertexBuilder}, insert::Insert, - objects::{GlobalVertex, Objects, SurfaceVertex, Vertex}, + objects::{GlobalVertex, SurfaceVertex, Vertex}, partial::{ HasPartial, PartialCurve, PartialSurfaceVertex, PartialVertex, }, - services::State, + services::Services, validate::Validate, }; #[test] fn vertex_surface_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let mut curve = PartialCurve { - surface: Some(objects.surfaces.xy_plane()), + surface: Some(services.objects.surfaces.xy_plane()), ..Default::default() }; curve.update_as_u_axis(); @@ -205,11 +205,12 @@ mod tests { curve: curve.into(), ..Default::default() } - .build(&mut objects); + .build(&mut services.objects); let invalid = Vertex::new(valid.position(), valid.curve().clone(), { let mut tmp = valid.surface_form().to_partial(); - tmp.surface = Some(objects.surfaces.xz_plane()); - tmp.build(&mut objects).insert(&mut objects) + tmp.surface = Some(services.objects.surfaces.xz_plane()); + tmp.build(&mut services.objects) + .insert(&mut services.objects) }); assert!(valid.validate().is_ok()); @@ -218,11 +219,11 @@ mod tests { #[test] fn vertex_position_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = { let mut curve = PartialCurve { - surface: Some(objects.surfaces.xy_plane()), + surface: Some(services.objects.surfaces.xy_plane()), ..Default::default() }; curve.update_as_u_axis(); @@ -232,13 +233,14 @@ mod tests { curve: curve.into(), ..Default::default() } - .build(&mut objects) + .build(&mut services.objects) }; let invalid = Vertex::new(valid.position(), valid.curve().clone(), { let mut tmp = valid.surface_form().to_partial(); tmp.position = Some([1., 0.].into()); tmp.infer_global_form(); - tmp.build(&mut objects).insert(&mut objects) + tmp.build(&mut services.objects) + .insert(&mut services.objects) }); assert!(valid.validate().is_ok()); @@ -247,18 +249,19 @@ mod tests { #[test] fn surface_vertex_position_mismatch() { - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let valid = PartialSurfaceVertex { position: Some([0., 0.].into()), - surface: Some(objects.surfaces.xy_plane()), + surface: Some(services.objects.surfaces.xy_plane()), ..Default::default() } - .build(&mut objects); + .build(&mut services.objects); let invalid = SurfaceVertex::new( valid.position(), valid.surface().clone(), - GlobalVertex::from_position([1., 0., 0.]).insert(&mut objects), + GlobalVertex::from_position([1., 0., 0.]) + .insert(&mut services.objects), ); assert!(valid.validate().is_ok()); From bed6a4a0623faecfad760068342aa723337832fe Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:55:53 +0100 Subject: [PATCH 07/18] Use `Services` in `ShapeProcessor` --- crates/fj-operations/src/shape_processor.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/fj-operations/src/shape_processor.rs b/crates/fj-operations/src/shape_processor.rs index 7842f5d28..2a6720608 100644 --- a/crates/fj-operations/src/shape_processor.rs +++ b/crates/fj-operations/src/shape_processor.rs @@ -6,8 +6,7 @@ use fj_kernel::{ approx::{InvalidTolerance, Tolerance}, triangulate::Triangulate, }, - objects::Objects, - services::State, + services::Services, validate::ValidationError, }; use fj_math::Scalar; @@ -43,9 +42,9 @@ impl ShapeProcessor { Some(user_defined_tolerance) => user_defined_tolerance, }; - let mut objects = Objects::new().into_service(); + let mut services = Services::new(); let mut debug_info = DebugInfo::new(); - let shape = shape.compute_brep(&mut objects, &mut debug_info); + let shape = shape.compute_brep(&mut services.objects, &mut debug_info); let mesh = (&shape, tolerance).triangulate(); Ok(ProcessedShape { From 6ed756588fdaafb8e70cac4b594cd46288575e40 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 13:56:05 +0100 Subject: [PATCH 08/18] Remove unused trait method --- crates/fj-kernel/src/services/service.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/fj-kernel/src/services/service.rs b/crates/fj-kernel/src/services/service.rs index f540331ee..43fa559e8 100644 --- a/crates/fj-kernel/src/services/service.rs +++ b/crates/fj-kernel/src/services/service.rs @@ -98,17 +98,6 @@ pub trait State { /// [`State::evolve`]. type Event; - /// Convert this state into the service that wraps it - /// - /// This is a convenience method that just calls [`Service::new`] - /// internally. - fn into_service(self) -> Service - where - Self: Sized, - { - Service::new(self) - } - /// Decide how to react to the provided command /// /// If the command must result in changes to the state, any number of events From 1e8d985db07a56374bcebf92ed7cb2435a0dab47 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 15:04:11 +0100 Subject: [PATCH 09/18] Derive some traits for objects service types --- crates/fj-kernel/src/services/objects.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/fj-kernel/src/services/objects.rs b/crates/fj-kernel/src/services/objects.rs index b733e2407..754b4acb0 100644 --- a/crates/fj-kernel/src/services/objects.rs +++ b/crates/fj-kernel/src/services/objects.rs @@ -29,12 +29,14 @@ impl State for Objects { /// /// You might prefer to use [`ServiceObjectsExt::insert`], which is a convenient /// wrapper around `Service::execute`. +#[derive(Clone, Debug)] pub struct InsertObject { /// The object to insert pub object: Object, } /// Event produced by `Service` +#[derive(Clone, Debug)] pub struct ObjectToInsert { /// The object to insert pub object: Object, From 7c13f0ee82742179b92fd929702f7fb83fce7c18 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 10:50:37 +0100 Subject: [PATCH 10/18] Derive `Clone` for validation errors --- crates/fj-kernel/src/validate/cycle.rs | 2 +- crates/fj-kernel/src/validate/edge.rs | 2 +- crates/fj-kernel/src/validate/face.rs | 2 +- crates/fj-kernel/src/validate/mod.rs | 2 +- crates/fj-kernel/src/validate/vertex.rs | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/validate/cycle.rs b/crates/fj-kernel/src/validate/cycle.rs index 1252029b4..5de62f585 100644 --- a/crates/fj-kernel/src/validate/cycle.rs +++ b/crates/fj-kernel/src/validate/cycle.rs @@ -25,7 +25,7 @@ impl Validate for Cycle { } /// [`Cycle`] validation error -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum CycleValidationError { /// Half-edges are not connected #[error( diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index a21739507..fff2d900d 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -45,7 +45,7 @@ impl Validate for GlobalEdge { } /// [`HalfEdge`] validation failed -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum HalfEdgeValidationError { /// [`HalfEdge`] vertices are not defined on the same `Curve` #[error( diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index 58391a8a5..db9a082ec 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -21,7 +21,7 @@ impl Validate for Face { } /// [`Face`] validation error -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum FaceValidationError { /// [`Surface`] of an interior [`Cycle`] doesn't match [`Face`]'s `Surface` #[error( diff --git a/crates/fj-kernel/src/validate/mod.rs b/crates/fj-kernel/src/validate/mod.rs index 8bcf5eb84..e2934ea04 100644 --- a/crates/fj-kernel/src/validate/mod.rs +++ b/crates/fj-kernel/src/validate/mod.rs @@ -74,7 +74,7 @@ impl Default for ValidationConfig { /// An error that can occur during a validation #[allow(clippy::large_enum_variant)] -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum ValidationError { /// `Cycle` validation error #[error(transparent)] diff --git a/crates/fj-kernel/src/validate/vertex.rs b/crates/fj-kernel/src/validate/vertex.rs index a27afba8b..a58adc629 100644 --- a/crates/fj-kernel/src/validate/vertex.rs +++ b/crates/fj-kernel/src/validate/vertex.rs @@ -46,7 +46,7 @@ impl Validate for GlobalVertex { } /// [`Vertex`] validation failed -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum VertexValidationError { /// Mismatch between the surface's of the curve and surface form #[error( @@ -126,7 +126,7 @@ impl VertexValidationError { } /// [`SurfaceVertex`] validation error -#[derive(Debug, thiserror::Error)] +#[derive(Clone, Debug, thiserror::Error)] pub enum SurfaceVertexValidationError { /// Mismatch between position and position of global form #[error( From 3b563eaa4bbb5dd69e0526df2ec1ae37ea2ff931 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 10:51:53 +0100 Subject: [PATCH 11/18] Require commands and events to be `Clone` --- crates/fj-kernel/src/services/service.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/services/service.rs b/crates/fj-kernel/src/services/service.rs index 43fa559e8..f5414eab0 100644 --- a/crates/fj-kernel/src/services/service.rs +++ b/crates/fj-kernel/src/services/service.rs @@ -90,13 +90,13 @@ pub trait State { /// A command that relates to the state /// /// Commands are processed by [`State::decide`]. - type Command; + type Command: Clone; /// An event that captures modifications to this state /// /// Events are produced by [`State::decide`] and processed by /// [`State::evolve`]. - type Event; + type Event: Clone; /// Decide how to react to the provided command /// From 3e47a434a86c71f4b3667961a1f257039ca2af5f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 10:53:27 +0100 Subject: [PATCH 12/18] Make it possible to subscribe to services --- crates/fj-kernel/src/services/service.rs | 29 +++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/services/service.rs b/crates/fj-kernel/src/services/service.rs index f5414eab0..5ce2a50d9 100644 --- a/crates/fj-kernel/src/services/service.rs +++ b/crates/fj-kernel/src/services/service.rs @@ -1,4 +1,6 @@ -use std::ops::Deref; +use std::{ops::Deref, sync::Arc}; + +use parking_lot::Mutex; /// A service that controls access to some state /// @@ -22,6 +24,7 @@ use std::ops::Deref; pub struct Service { state: S, events: Vec, + subscribers: Vec>>>, } impl Service { @@ -30,9 +33,18 @@ impl Service { Self { state, events: Vec::new(), + subscribers: Vec::new(), } } + /// Add a subscriber + pub fn subscribe( + &mut self, + subscriber: Arc>>, + ) { + self.subscribers.push(subscriber); + } + /// Execute a command /// /// The command is executed synchronously. When this method returns, the @@ -43,6 +55,11 @@ impl Service { for event in &events { self.state.evolve(event); + + for subscriber in &self.subscribers { + let mut subscriber = subscriber.lock(); + subscriber.handle_event(event); + } } self.events.extend(events); @@ -83,6 +100,12 @@ where } } +impl Subscriber for Service { + fn handle_event(&mut self, event: &S::Command) { + self.execute(event.clone()); + } +} + /// Implemented for state that can be wrapped by a [`Service`] /// /// See [`Service`] for a detailed explanation. @@ -114,3 +137,7 @@ pub trait State { /// [`State::decide`], and encoded into the event. fn evolve(&mut self, event: &Self::Event); } + +pub trait Subscriber { + fn handle_event(&mut self, event: &T); +} From ab4edf6dd80111aa91216d6071aa5c9db62e998c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 10:56:27 +0100 Subject: [PATCH 13/18] Implement `Default` in terms of constructor --- crates/fj-kernel/src/services/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index 4f52467c4..c12d5467f 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -13,7 +13,6 @@ pub use self::{ }; /// The kernel services -#[derive(Default)] pub struct Services { /// The objects service /// @@ -27,6 +26,13 @@ pub struct Services { impl Services { /// Construct an instance of `Services` pub fn new() -> Self { - Self::default() + let objects = Service::default(); + Self { objects } + } +} + +impl Default for Services { + fn default() -> Self { + Self::new() } } From 35423c36335d488eb7d702af7eeb30393dd76cbe Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 25 Nov 2022 14:38:29 +0100 Subject: [PATCH 14/18] Add validation service --- crates/fj-kernel/src/services/mod.rs | 2 + crates/fj-kernel/src/services/validation.rs | 61 +++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 crates/fj-kernel/src/services/validation.rs diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index c12d5467f..c9129de85 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -4,12 +4,14 @@ mod objects; mod service; +mod validation; use crate::objects::Objects; pub use self::{ objects::ServiceObjectsExt, service::{Service, State}, + validation::{Validation, ValidationEvent}, }; /// The kernel services diff --git a/crates/fj-kernel/src/services/validation.rs b/crates/fj-kernel/src/services/validation.rs new file mode 100644 index 000000000..a0db159ed --- /dev/null +++ b/crates/fj-kernel/src/services/validation.rs @@ -0,0 +1,61 @@ +use std::collections::BTreeMap; + +use crate::{ + objects::{BehindHandle, Object}, + storage::ObjectId, + validate::ValidationError, +}; + +use super::{objects::ObjectToInsert, State}; + +/// Errors that occurred while validating the objects inserted into the stores +#[derive(Default)] +pub struct Validation( + pub BTreeMap, ValidationError)>, +); + +impl Drop for Validation { + fn drop(&mut self) { + if !self.0.is_empty() { + println!("Dropping `Validation` with unhandled validation errors:"); + + for (_, err) in self.0.values() { + println!("{err}"); + } + + panic!(); + } + } +} + +impl State for Validation { + type Command = ObjectToInsert; + type Event = ValidationEvent; + + fn decide(&self, command: Self::Command, events: &mut Vec) { + let err = command.object.validate().err(); + events.push(ValidationEvent { + object: command.object.into(), + err, + }); + } + + fn evolve(&mut self, event: &Self::Event) { + if let Some(err) = &event.err { + self.0 + .insert(event.object.id(), (event.object.clone(), err.clone())); + } + } +} + +/// An event produced by the validation service +#[derive(Clone)] +pub struct ValidationEvent { + /// The object for which validation has been attempted + pub object: Object, + + /// The validation error, if the validation resulted in one + /// + /// If this is `None`, the object has been validated successfully. + pub err: Option, +} From 546a53acf02a3d808692c75e82dcd9f79264c7d5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 11:10:32 +0100 Subject: [PATCH 15/18] Add validation service to `Services` --- crates/fj-kernel/src/services/mod.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/services/mod.rs b/crates/fj-kernel/src/services/mod.rs index c9129de85..eb55c2a2d 100644 --- a/crates/fj-kernel/src/services/mod.rs +++ b/crates/fj-kernel/src/services/mod.rs @@ -6,6 +6,10 @@ mod objects; mod service; mod validation; +use std::sync::Arc; + +use parking_lot::Mutex; + use crate::objects::Objects; pub use self::{ @@ -23,13 +27,25 @@ pub struct Services { /// [`ServiceObjectsExt`] is available to provide a convenient API around /// this service. pub objects: Service, + + /// The validation service + /// + /// Validates objects that are inserted using the objects service. + pub validation: Arc>>, } impl Services { /// Construct an instance of `Services` pub fn new() -> Self { - let objects = Service::default(); - Self { objects } + let mut objects = Service::::default(); + let validation = Arc::new(Mutex::new(Service::default())); + + objects.subscribe(validation.clone()); + + Self { + objects, + validation, + } } } From 7e04ec7a922f93041a192a2e2760d9806781b39a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 12:12:25 +0100 Subject: [PATCH 16/18] Separate object validation from insertion There is a separate validation service now. --- crates/fj-kernel/src/objects/object.rs | 2 +- crates/fj-kernel/src/objects/stores.rs | 94 ++++---------------------- 2 files changed, 14 insertions(+), 82 deletions(-) diff --git a/crates/fj-kernel/src/objects/object.rs b/crates/fj-kernel/src/objects/object.rs index a4f3d9fb4..8bfff413a 100644 --- a/crates/fj-kernel/src/objects/object.rs +++ b/crates/fj-kernel/src/objects/object.rs @@ -68,7 +68,7 @@ macro_rules! object { match self { $( Self::$ty((handle, object)) => { - objects.$store.insert(handle.clone(), object)?; + objects.$store.insert(handle.clone(), object); Ok(handle.into()) } )* diff --git a/crates/fj-kernel/src/objects/stores.rs b/crates/fj-kernel/src/objects/stores.rs index d9444317b..3a88fd64a 100644 --- a/crates/fj-kernel/src/objects/stores.rs +++ b/crates/fj-kernel/src/objects/stores.rs @@ -1,14 +1,8 @@ -use std::convert::Infallible; - use fj_math::Vector; use crate::{ geometry::{path::GlobalPath, surface::SurfaceGeometry}, storage::{Handle, Store}, - validate::{ - CycleValidationError, FaceValidationError, HalfEdgeValidationError, - SurfaceVertexValidationError, Validate, VertexValidationError, - }, }; use super::{ @@ -86,14 +80,8 @@ impl Curves { } /// Insert a [`Curve`] into the store - pub fn insert( - &mut self, - handle: Handle, - curve: Curve, - ) -> Result<(), Infallible> { - curve.validate()?; + pub fn insert(&mut self, handle: Handle, curve: Curve) { self.store.insert(handle, curve); - Ok(()) } } @@ -110,14 +98,8 @@ impl Cycles { } /// Insert a [`Cycle`] into the store - pub fn insert( - &mut self, - handle: Handle, - cycle: Cycle, - ) -> Result<(), CycleValidationError> { - cycle.validate()?; + pub fn insert(&mut self, handle: Handle, cycle: Cycle) { self.store.insert(handle, cycle); - Ok(()) } } @@ -134,14 +116,8 @@ impl Faces { } /// Insert a [`Face`] into the store - pub fn insert( - &mut self, - handle: Handle, - face: Face, - ) -> Result<(), FaceValidationError> { - face.validate()?; + pub fn insert(&mut self, handle: Handle, face: Face) { self.store.insert(handle, face); - Ok(()) } } @@ -162,10 +138,8 @@ impl GlobalCurves { &mut self, handle: Handle, global_curve: GlobalCurve, - ) -> Result<(), Infallible> { - global_curve.validate()?; + ) { self.store.insert(handle, global_curve); - Ok(()) } } @@ -186,10 +160,8 @@ impl GlobalEdges { &mut self, handle: Handle, global_edge: GlobalEdge, - ) -> Result<(), Infallible> { - global_edge.validate()?; + ) { self.store.insert(handle, global_edge); - Ok(()) } } @@ -210,10 +182,8 @@ impl GlobalVertices { &mut self, handle: Handle, global_vertex: GlobalVertex, - ) -> Result<(), Infallible> { - global_vertex.validate()?; + ) { self.store.insert(handle, global_vertex); - Ok(()) } } @@ -230,14 +200,8 @@ impl HalfEdges { } /// Insert a [`HalfEdge`] into the store - pub fn insert( - &mut self, - handle: Handle, - half_edge: HalfEdge, - ) -> Result<(), HalfEdgeValidationError> { - half_edge.validate()?; + pub fn insert(&mut self, handle: Handle, half_edge: HalfEdge) { self.store.insert(handle, half_edge); - Ok(()) } } @@ -254,14 +218,8 @@ impl Shells { } /// Insert a [`Shell`] into the store - pub fn insert( - &mut self, - handle: Handle, - shell: Shell, - ) -> Result<(), Infallible> { - shell.validate()?; + pub fn insert(&mut self, handle: Handle, shell: Shell) { self.store.insert(handle, shell); - Ok(()) } } @@ -278,14 +236,8 @@ impl Sketches { } /// Insert a [`Sketch`] into the store - pub fn insert( - &mut self, - handle: Handle, - sketch: Sketch, - ) -> Result<(), Infallible> { - sketch.validate()?; + pub fn insert(&mut self, handle: Handle, sketch: Sketch) { self.store.insert(handle, sketch); - Ok(()) } } @@ -302,14 +254,8 @@ impl Solids { } /// Insert a [`Solid`] into the store - pub fn insert( - &mut self, - handle: Handle, - solid: Solid, - ) -> Result<(), Infallible> { - solid.validate()?; + pub fn insert(&mut self, handle: Handle, solid: Solid) { self.store.insert(handle, solid); - Ok(()) } } @@ -330,10 +276,8 @@ impl SurfaceVertices { &mut self, handle: Handle, surface_vertex: SurfaceVertex, - ) -> Result<(), SurfaceVertexValidationError> { - surface_vertex.validate()?; + ) { self.store.insert(handle, surface_vertex); - Ok(()) } } @@ -354,14 +298,8 @@ impl Surfaces { } /// Insert a [`Surface`] into the store - pub fn insert( - &mut self, - handle: Handle, - surface: Surface, - ) -> Result<(), Infallible> { - surface.validate()?; + pub fn insert(&mut self, handle: Handle, surface: Surface) { self.store.insert(handle, surface); - Ok(()) } /// Access the xy-plane @@ -432,13 +370,7 @@ impl Vertices { } /// Insert a [`Vertex`] into the store - pub fn insert( - &mut self, - handle: Handle, - vertex: Vertex, - ) -> Result<(), VertexValidationError> { - vertex.validate()?; + pub fn insert(&mut self, handle: Handle, vertex: Vertex) { self.store.insert(handle, vertex); - Ok(()) } } From 7f910f5ae41f221a2514f390e6caaf11ba5d6c20 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 12:14:28 +0100 Subject: [PATCH 17/18] Simplify method signature --- crates/fj-kernel/src/objects/object.rs | 14 ++------------ crates/fj-kernel/src/services/objects.rs | 6 +----- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/crates/fj-kernel/src/objects/object.rs b/crates/fj-kernel/src/objects/object.rs index 8bfff413a..4bbb24fa8 100644 --- a/crates/fj-kernel/src/objects/object.rs +++ b/crates/fj-kernel/src/objects/object.rs @@ -1,7 +1,6 @@ use std::any::Any; use crate::{ - insert::Insert, objects::{ Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, Shell, Sketch, Solid, Surface, SurfaceVertex, Vertex, @@ -55,21 +54,12 @@ macro_rules! object { impl Object { /// Insert the object into its respective store - pub fn insert( - self, - objects: &mut Objects, - ) -> Result, ValidationError> - where - $( - crate::objects::$ty: Insert, - ValidationError: From<<$ty as Validate>::Error>, - )* - { + pub fn insert(self, objects: &mut Objects) -> Object { match self { $( Self::$ty((handle, object)) => { objects.$store.insert(handle.clone(), object); - Ok(handle.into()) + handle.into() } )* } diff --git a/crates/fj-kernel/src/services/objects.rs b/crates/fj-kernel/src/services/objects.rs index 754b4acb0..9bbd43610 100644 --- a/crates/fj-kernel/src/services/objects.rs +++ b/crates/fj-kernel/src/services/objects.rs @@ -17,11 +17,7 @@ impl State for Objects { } fn evolve(&mut self, event: &Self::Event) { - // This operation being fallible goes against the spirit of the `evolve` - // method. The reason for that is, that `Objects` is not fully adapted - // to this new design yet. In the future, validation will most likely - // move into its own service, making this operation infallible. - event.object.clone().insert(self).unwrap(); + event.object.clone().insert(self); } } From 7e4c0af90c73dd0a071903c446c545b698bbc367 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 29 Nov 2022 12:17:27 +0100 Subject: [PATCH 18/18] Remove store types that no longer have a purpose Now that validation is separate from insertion, most of them no longer did anything. --- crates/fj-kernel/src/objects/mod.rs | 6 +- crates/fj-kernel/src/objects/stores.rs | 256 ++----------------------- 2 files changed, 13 insertions(+), 249 deletions(-) diff --git a/crates/fj-kernel/src/objects/mod.rs b/crates/fj-kernel/src/objects/mod.rs index 8cfa8facc..6036e2b73 100644 --- a/crates/fj-kernel/src/objects/mod.rs +++ b/crates/fj-kernel/src/objects/mod.rs @@ -90,9 +90,5 @@ pub use self::{ vertex::{GlobalVertex, SurfaceVertex, Vertex}, }, object::{Bare, BehindHandle, Form, Object, WithHandle}, - stores::{ - Curves, Cycles, Faces, GlobalCurves, GlobalEdges, GlobalVertices, - HalfEdges, Objects, Shells, Sketches, Solids, SurfaceVertices, - Surfaces, Vertices, - }, + stores::{Objects, Surfaces}, }; diff --git a/crates/fj-kernel/src/objects/stores.rs b/crates/fj-kernel/src/objects/stores.rs index 3a88fd64a..1f5adf652 100644 --- a/crates/fj-kernel/src/objects/stores.rs +++ b/crates/fj-kernel/src/objects/stores.rs @@ -21,43 +21,43 @@ use super::{ #[derive(Debug, Default)] pub struct Objects { /// Store for [`Curve`]s - pub curves: Curves, + pub curves: Store, /// Store for [`Cycle`]s - pub cycles: Cycles, + pub cycles: Store, /// Store for [`Face`]s - pub faces: Faces, + pub faces: Store, /// Store for [`GlobalCurve`]s - pub global_curves: GlobalCurves, + pub global_curves: Store, /// Store for [`GlobalEdge`]s - pub global_edges: GlobalEdges, + pub global_edges: Store, /// Store for [`GlobalVertex`] objects - pub global_vertices: GlobalVertices, + pub global_vertices: Store, /// Store for [`HalfEdge`]s - pub half_edges: HalfEdges, + pub half_edges: Store, /// Store for [`Shell`]s - pub shells: Shells, + pub shells: Store, /// Store for [`Sketch`]es - pub sketches: Sketches, + pub sketches: Store, /// Store for [`Solid`]s - pub solids: Solids, + pub solids: Store, /// Store for [`SurfaceVertex`] objects - pub surface_vertices: SurfaceVertices, + pub surface_vertices: Store, /// Store for [`Surface`]s pub surfaces: Surfaces, /// Store for [`Vertex`] objects - pub vertices: Vertices, + pub vertices: Store, } impl Objects { @@ -67,220 +67,6 @@ impl Objects { } } -/// Store for [`Curve`]s -#[derive(Debug, Default)] -pub struct Curves { - store: Store, -} - -impl Curves { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Curve`] into the store - pub fn insert(&mut self, handle: Handle, curve: Curve) { - self.store.insert(handle, curve); - } -} - -/// Store for [`Cycle`]s -#[derive(Debug, Default)] -pub struct Cycles { - store: Store, -} - -impl Cycles { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Cycle`] into the store - pub fn insert(&mut self, handle: Handle, cycle: Cycle) { - self.store.insert(handle, cycle); - } -} - -/// Store for [`Face`]s -#[derive(Debug, Default)] -pub struct Faces { - store: Store, -} - -impl Faces { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Face`] into the store - pub fn insert(&mut self, handle: Handle, face: Face) { - self.store.insert(handle, face); - } -} - -/// Store for [`GlobalCurve`]s -#[derive(Debug, Default)] -pub struct GlobalCurves { - store: Store, -} - -impl GlobalCurves { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`GlobalCurve`] into the store - pub fn insert( - &mut self, - handle: Handle, - global_curve: GlobalCurve, - ) { - self.store.insert(handle, global_curve); - } -} - -/// Store for [`GlobalEdge`]s -#[derive(Debug, Default)] -pub struct GlobalEdges { - store: Store, -} - -impl GlobalEdges { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`GlobalEdge`] into the store - pub fn insert( - &mut self, - handle: Handle, - global_edge: GlobalEdge, - ) { - self.store.insert(handle, global_edge); - } -} - -/// Store for [`GlobalVertex`] objects -#[derive(Debug, Default)] -pub struct GlobalVertices { - store: Store, -} - -impl GlobalVertices { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`GlobalVertex`] into the store - pub fn insert( - &mut self, - handle: Handle, - global_vertex: GlobalVertex, - ) { - self.store.insert(handle, global_vertex); - } -} - -/// Store for [`HalfEdge`]s -#[derive(Debug, Default)] -pub struct HalfEdges { - store: Store, -} - -impl HalfEdges { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`HalfEdge`] into the store - pub fn insert(&mut self, handle: Handle, half_edge: HalfEdge) { - self.store.insert(handle, half_edge); - } -} - -/// Store for [`Shell`]s -#[derive(Debug, Default)] -pub struct Shells { - store: Store, -} - -impl Shells { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Shell`] into the store - pub fn insert(&mut self, handle: Handle, shell: Shell) { - self.store.insert(handle, shell); - } -} - -/// Store for [`Sketch`]es -#[derive(Debug, Default)] -pub struct Sketches { - store: Store, -} - -impl Sketches { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Sketch`] into the store - pub fn insert(&mut self, handle: Handle, sketch: Sketch) { - self.store.insert(handle, sketch); - } -} - -/// Store for [`Solid`]s -#[derive(Debug, Default)] -pub struct Solids { - store: Store, -} - -impl Solids { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Solid`] into the store - pub fn insert(&mut self, handle: Handle, solid: Solid) { - self.store.insert(handle, solid); - } -} - -/// Store for [`SurfaceVertex`] objects -#[derive(Debug, Default)] -pub struct SurfaceVertices { - store: Store, -} - -impl SurfaceVertices { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`SurfaceVertex`] into the store - pub fn insert( - &mut self, - handle: Handle, - surface_vertex: SurfaceVertex, - ) { - self.store.insert(handle, surface_vertex); - } -} - /// Store for [`Surface`]s #[derive(Debug)] pub struct Surfaces { @@ -356,21 +142,3 @@ impl Default for Surfaces { } } } - -/// Store for [`Vertex`] objects -#[derive(Debug, Default)] -pub struct Vertices { - store: Store, -} - -impl Vertices { - /// Reserve a slot for an object in the store - pub fn reserve(&self) -> Handle { - self.store.reserve() - } - - /// Insert a [`Vertex`] into the store - pub fn insert(&mut self, handle: Handle, vertex: Vertex) { - self.store.insert(handle, vertex); - } -}