fj_core/algorithms/approx/
edge.rs

1//! Edge approximation
2//!
3//! The approximation of a curve is its first vertex, combined with the
4//! approximation of its curve. The second vertex is left out, as edge
5//! approximations are usually used to build cycle approximations, and this way,
6//! the caller doesn't have to deal with duplicate vertices.
7
8use crate::{
9    geometry::SurfaceGeometry, objects::HalfEdge, storage::Handle, Core,
10};
11
12use super::{
13    curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint,
14    Tolerance,
15};
16
17impl Approx for (&Handle<HalfEdge>, &SurfaceGeometry) {
18    type Approximation = HalfEdgeApprox;
19    type Cache = HalfEdgeApproxCache;
20
21    fn approx_with_cache(
22        self,
23        tolerance: impl Into<Tolerance>,
24        cache: &mut Self::Cache,
25        core: &mut Core,
26    ) -> Self::Approximation {
27        let (half_edge, surface) = self;
28        let tolerance = tolerance.into();
29
30        let start_position_surface = half_edge.start_position();
31        let start_position =
32            match cache.start_position.get(half_edge.start_vertex()) {
33                Some(position) => position,
34                None => {
35                    let position_global = surface
36                        .point_from_surface_coords(start_position_surface);
37                    cache.start_position.insert(
38                        half_edge.start_vertex().clone(),
39                        position_global,
40                    )
41                }
42            };
43
44        let first = ApproxPoint::new(start_position_surface, start_position);
45
46        let rest = {
47            let approx = (
48                half_edge.curve(),
49                core.layers.geometry.of_half_edge(half_edge).path,
50                surface,
51                half_edge.boundary(),
52            )
53                .approx_with_cache(
54                    tolerance,
55                    &mut cache.curve,
56                    core,
57                );
58
59            approx.points.into_iter().map(|point| {
60                let point_surface = core
61                    .layers
62                    .geometry
63                    .of_half_edge(half_edge)
64                    .path
65                    .point_from_path_coords(point.local_form);
66
67                ApproxPoint::new(point_surface, point.global_form)
68            })
69        };
70
71        let mut points = vec![first];
72        points.extend(rest);
73
74        HalfEdgeApprox { points }
75    }
76}
77
78/// An approximation of a [`HalfEdge`]
79#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
80pub struct HalfEdgeApprox {
81    /// The points that approximate the half-edge
82    pub points: Vec<ApproxPoint<2>>,
83}
84
85/// Cache for half-edge approximations
86#[derive(Default)]
87pub struct HalfEdgeApproxCache {
88    start_position: VertexApproxCache,
89    curve: CurveApproxCache,
90}