geop_core_topology/loop_sampling.rs
1//! Sample a coedge loop's pcurves into a closed `(u, v)` polygon.
2//!
3//! Lives in `geop-core-topology` rather than `geop-ops-rasterize` (which
4//! also uses it, for triangulation) because `geop-core-topology`'s own edit
5//! code (`splice_edge_into_face`'s loop-orientation check) needs it too,
6//! and topology sits below rasterize in the dependency order.
7
8use geop_core_math::{geop_error::GeopResult, scalars::Scalar, vector::Vector2};
9
10use crate::{CoedgeId, Model};
11
12/// Sample the pcurves of the loop anchored at `first` (in traversal order)
13/// into a closed `(u, v)` polygon, `n` samples per coedge (the last sample of
14/// each coedge is dropped, since it coincides with the next coedge's first
15/// sample).
16pub fn sample_loop_to_polygon<S: Scalar>(
17 model: &Model<S>,
18 first: CoedgeId,
19 n: usize,
20) -> GeopResult<Vec<Vector2<S>>> {
21 let mut poly = Vec::new();
22 for current in model.iterate_loop_coedges(first) {
23 let pcurve = &model.coedges[¤t].pcurve;
24 let (t0, t1) = pcurve.domain();
25 for i in 0..n - 1 {
26 let frac = S::from_ratio(i as i64, (n - 1) as i64)?;
27 let t = t0.add(t1.sub(t0).mul(frac));
28 poly.push(pcurve.evaluate(t)?);
29 }
30 }
31 Ok(poly)
32}