mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-30 20:58:00 -06:00
Shape Builder: a merge walks the arrangement once per batch of faces
A merge found the contours of the faces it unites with one contour pass over the whole arrangement for each coverage among them, and the search for slivers next to them did the same for each neighboring coverage. Each in-place remnant of a merge is such a merge too, so a click on many overlapping shapes made one pass over the whole arrangement for each coverage, for the merged faces and again for each remnant. Both now use the batching that Divide's regions use: one pass for each batch of coverages whose faces share no vertex. The batching looks a face's coverage up by a hash of the inputs that cover it, computed as it walks them. The search for slivers looks up the merged faces' coverages the same way. Merging a frame no longer takes in an island of the same coverage in its hole: each face is its outer contour and the holes directly in it, as the regions are.
This commit is contained in:
@@ -14,6 +14,12 @@ use vectorcraft_geom::{Anchor, FillRule, PathData, SubPath};
|
||||
use crate::PathOpsError;
|
||||
use crate::fit::{end_tangent, fit_single, is_straight, sample, start_tangent};
|
||||
|
||||
#[cfg(test)]
|
||||
thread_local! {
|
||||
/// The contour passes made over an arrangement on this thread, each of which walks all of it.
|
||||
pub(crate) static CONTOUR_PASSES: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
|
||||
}
|
||||
|
||||
/// Default curve-refit tolerance (document points) used to merge split curve pieces back together.
|
||||
/// Similar in spirit to Illustrator's Pathfinder "Precision" option (0.028 pt).
|
||||
pub const DEFAULT_PRECISION: f64 = 0.01;
|
||||
@@ -314,11 +320,13 @@ impl Arrangement {
|
||||
|
||||
/// [`Arrangement::contours`] with the test on the windings themselves (see [`Self::covered`]).
|
||||
pub(crate) fn contours_where(&self, pred: impl Fn(&Multi) -> bool) -> Contours {
|
||||
#[cfg(test)]
|
||||
CONTOUR_PASSES.with(|n| n.set(n.get() + 1));
|
||||
self.top.contours(pred)
|
||||
}
|
||||
|
||||
pub(crate) fn contours(&self, pred: impl Fn(&[bool]) -> bool) -> Contours {
|
||||
self.top.contours(|w| pred(&self.mask(w)))
|
||||
self.contours_where(|w| pred(&self.mask(w)))
|
||||
}
|
||||
|
||||
/// All distinct non-empty coverage masks that occur next to some edge, sorted.
|
||||
|
||||
Reference in New Issue
Block a user