diff --git a/crates/fj-core/src/objects/kinds/vertex.rs b/crates/fj-core/src/objects/kinds/vertex.rs index 10d5a80f6..8fc398ee8 100644 --- a/crates/fj-core/src/objects/kinds/vertex.rs +++ b/crates/fj-core/src/objects/kinds/vertex.rs @@ -1,21 +1,71 @@ -/// A vertex, defined in global (3D) coordinates +/// # A vertex that identifies a point in space /// -/// This struct exists to distinguish between vertices and points at the type -/// level. This is a relevant distinction, as vertices are part of a shape that -/// help define its topology. +/// ## Purpose /// -/// Points, on the other hand, might be used to approximate a shape for various -/// purposes, without presenting any deeper truth about the shape's structure. +/// Vertices are referenced by [`HalfEdge`]s. They are topological objects, +/// which means that their purpose is to define how parts of a shape relate to +/// each other. They *identify* a point in space, but they do not define its +/// position. /// -/// # Validation +/// In fact, this struct does not contain any data at all which could define +/// anything. As such, [`Vertex`] is solely intended to be used through a +/// [`Handle`], which provides the vertex with a unique identity, allowing it +/// to do its job. /// -/// Vertices must be unique within a shape, meaning an identical vertex must not -/// exist in the same shape. In the context of vertex uniqueness, points that -/// are close to each other are considered identical. The minimum distance -/// between distinct vertices can be configured using the respective field in -/// [`ValidationConfig`]. +/// Having a unique identity for a point in space is very valuable, as we can't +/// just rely on the value of points to compare them. If two half-edges connect, +/// we expect them to connect at a single point, not two points that are very +/// close to each other. /// -/// # Equality +/// Due to the realities of computing (and specifically, the realities of +/// computing floating-point numbers), we might very well end up *thinking* that +/// our code computed a single point, when in fact it does not, which only shows +/// up outside of our testing environment. This can be a pervasive source of +/// bugs, if left unchecked. +/// +/// With [`Vertex`], we can provide a unique identity to each point where it is +/// computed. This allows [validation code](crate::validate) to exist, which can +/// identify where our code generates multiple distinct points that might end up +/// in slightly different positions in a real-life scenario. +/// +/// +/// ## Positions +/// +/// (Warning: If the following information is relevant to you, please double- +/// check it by looking at the code that this section references. Everything +/// here is true at the time of writing, but there are planned changes which +/// could make this section obsolete.) +/// +/// A vertex can exist in multiple distinct spaces, and can thus have multiple +/// positions. Those positions are defined by the objects that reference the +/// vertex. How exactly that happens depends on the overall shape. +/// +/// If the shape is defined by a [`Sketch`], it is 2D-only. The (2D) position of +/// the vertex will then be defined by the half-edges that reference it. +/// Validation code can make sure that those redundant definitions don't result +/// in wildly different values. +/// +/// If the shape is defined by a [`Solid`], then it it 3-dimensional. The +/// referencing half-edges still define the surface-local 2D positions of the +/// vertex. Since such half-edges could meet in the same surface, or exist where +/// multiple surfaces meet, these positions could end up being in one or more +/// surfaces. +/// +/// The corresponding [`Surface`] objects can then be used to convert those 2D +/// positions into global 3D positions. +/// +/// As you might have noted, in each case, we still have redundant definitions +/// of the vertex position, and might end up with multiple values for the +/// position that are not exactly equal. However, since we know these positions +/// belong to the same vertex, this is not a problem. +/// +/// Validation code can make sure that the actual values are very close +/// together, and where we lose this identity information(when generating a +/// triangle mesh for a file export, for example), we can choose exactly one of +/// those values. +/// +/// +/// ## Equality /// /// `Vertex` contains no data and exists purely to be used within a `Handle`, /// where `Handle::id` can be used to compare different instances of `Vertex`. @@ -28,12 +78,16 @@ /// `Eq`/`Ord`/..., you can use `HandleWrapper` to do that. It will /// use `Handle::id` to provide those `Eq`/`Ord`/... implementations. /// -/// [`ValidationConfig`]: crate::validate::ValidationConfig +/// [`HalfEdge`]: crate::objects::HalfEdge +/// [`Handle`]: crate::storage::Handle +/// [`Sketch`]: crate::objects::Sketch +/// [`Solid`]: crate::objects::Solid +/// [`Surface`]: crate::objects::Surface #[derive(Clone, Copy, Debug, Default, Hash)] pub struct Vertex {} impl Vertex { - /// Construct a `Vertex` from a position + /// Construct a `Vertex` pub fn new() -> Self { Self::default() }