mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 22:21:59 +00:00
Object > Path > Remove Anchor Points removed each selected anchor with its own Vec::remove, shifting the rest of the subpath every time, so removing k anchors from an n-anchor subpath took O(k*n) moves. - pathops: remove_anchors removes a subpath's anchors the last first, reading each anchor's current neighbors, handles, length and closed state as removing them one at a time does, and compacts the anchor list once. remove_anchor and remove_anchors share one refit, so the result is bit for bit the same. - engine: the command groups the selected anchors by subpath, works out the next selected anchor with each subpath reading only its own selected anchors, and takes emptied paths out of the selection together (Selection::remove_all). - Tests compare remove_anchors bit for bit with remove_anchor over 600 generated subpaths and focused cases, count the anchors moved (2001 anchors, every other one removed: at most one move per anchor left, 500,500 one at a time), and compare the next-anchor selection and the command on many paths and subpaths with removing one at a time.
50 lines
2.1 KiB
Rust
50 lines
2.1 KiB
Rust
//! VectorCraft path operations: booleans (Pathfinder), shape builder regions, offset, outline stroke,
|
|
//! simplify and the other Object → Path commands.
|
|
//!
|
|
//! Booleans are curve-preserving: `linesweeper`'s robust sweep-line works directly on cubic
|
|
//! Béziers, and the pieces it splits curves into are refitted afterwards so results carry few
|
|
//! anchors. See the crate README for the API overview.
|
|
#![forbid(unsafe_code)]
|
|
|
|
pub mod addons;
|
|
mod boolean;
|
|
mod budget;
|
|
mod edit;
|
|
mod fit;
|
|
mod offset;
|
|
mod pathfinder;
|
|
mod planar;
|
|
mod sweep_axis;
|
|
mod trap;
|
|
|
|
pub use boolean::{
|
|
BoolOp, DEFAULT_PRECISION, area, boolean, boolean_n, normalize, try_area, try_boolean, try_boolean_n, try_normalize, try_unite_all,
|
|
try_unite_all_with, unite_all, unite_all_with,
|
|
};
|
|
pub use edit::{
|
|
AverageAxis, SIMPLIFY_LEVEL, SMOOTH_AUTO_LEVEL, SimplifiedPart, SimplifyOptions, add_anchor_points, auto_simplify_level, average, join,
|
|
remove_anchor, remove_anchors, remove_redundant_points, simplify, simplify_level_tolerance, simplify_part, simplify_with, smooth, smooth_level,
|
|
smooth_options, split_into_grid,
|
|
};
|
|
pub use fit::{fit_cubics, fit_cubics_through};
|
|
pub use offset::{Cap, Join, MAX_OFFSET_SEGMENT_PAIRS, offset_path, outline_stroke, stroke_region, try_offset_path};
|
|
pub use pathfinder::{FaceMerger, PathfinderOp, Region, Shape, merge_regions, pathfinder, pathfinder_with, region_at, regions, regions_within};
|
|
pub use planar::{
|
|
BuilderArrangement, SHAPE_BUILDER_MAX_GAP, SHAPE_BUILDER_MAX_SEGMENTS, cut_out, encloses_area, find_gaps, has_open_path, interior_point,
|
|
live_paint, live_paint_with_gaps, run_around, shape_builder, shape_builder_with_gap,
|
|
};
|
|
pub use trap::{TRAP_HEIGHT_WIDTH_RANGE, TRAP_MAX_WIDTH, TRAP_MIN_WIDTH, trap_band};
|
|
|
|
/// Errors from fallible operations.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
|
|
pub enum PathOpsError {
|
|
#[error("input contains NaN or infinite coordinates")]
|
|
NonFinite,
|
|
#[error("input path could not be closed")]
|
|
OpenPath,
|
|
#[error("the shapes are too degenerate to combine")]
|
|
Degenerate,
|
|
#[error("the shapes cross themselves and each other too often to combine")]
|
|
TooComplex,
|
|
}
|