mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-29 06:18:12 +08:00
Add path-bool library (#1952)
* Add path-bool library * Cleanup code * Cargo format * Integrate boolean ops into graphite * Add test for editor crash * Fix edge sort floating point instability * Add unit test for red-dress failure * Backport tests and aux functions * Use curvature based sorting * Convert linear cubic splines to line segments * Deduplicate reversed path segments * Fix epsilon for empty segments * Remove parameter based intersection pruning * Add support for reversed paths * Add benchmark infrastructure * Add intersection benchmark * Add recursion bound * Implement support for overlapping path segments * Remove rouge prinln * Fix sorting for bezier segments with one control point at the start of the segment * Cleanup log statements * Directly translate graphite paths to Path segments * Round data before passing it to path_bool * Fix flag_faces traversal order * Add test for white dots in bottom right of painted dreams * Make rounding configurable * Update demo artwork to remove manual path modifications * Convert from path segments to manipulator groups directly * Remove dead code * Fix clippy lints * Replace functions in path segment with methods and add documentation * Add more documentation * Close subpaths * Reorganize files and add README.md * Add license information * Code review * Fix license info * Adopt new node macro and fix demo artwork * Close subpaths with Z --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
2febbfd698
commit
3eb98c6d6d
@@ -0,0 +1,121 @@
|
||||
use crate::aabb::Aabb;
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct QuadTree<T> {
|
||||
bounding_box: Aabb,
|
||||
depth: usize,
|
||||
inner_node_capacity: usize,
|
||||
subtrees: Option<Box<[QuadTree<T>; 4]>>,
|
||||
pairs: Vec<(Aabb, T)>,
|
||||
}
|
||||
|
||||
impl<T: Clone> QuadTree<T> {
|
||||
pub fn new(bounding_box: Aabb, depth: usize, inner_node_capacity: usize) -> Self {
|
||||
QuadTree {
|
||||
bounding_box,
|
||||
depth,
|
||||
inner_node_capacity,
|
||||
subtrees: None,
|
||||
pairs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, bounding_box: Aabb, value: T) -> bool {
|
||||
if !crate::aabb::bounding_boxes_overlap(&bounding_box, &self.bounding_box) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.depth > 0 && self.pairs.len() >= self.inner_node_capacity {
|
||||
self.ensure_subtrees();
|
||||
for tree in self.subtrees.as_mut().unwrap().iter_mut() {
|
||||
tree.insert(bounding_box, value.clone());
|
||||
}
|
||||
} else {
|
||||
self.pairs.push((bounding_box, value));
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn find(&self, bounding_box: &Aabb) -> HashSet<T>
|
||||
where
|
||||
T: Eq + std::hash::Hash + Clone,
|
||||
{
|
||||
let mut set = HashSet::new();
|
||||
self.find_internal(bounding_box, &mut set);
|
||||
set
|
||||
}
|
||||
|
||||
fn find_internal(&self, bounding_box: &Aabb, set: &mut HashSet<T>)
|
||||
where
|
||||
T: Eq + std::hash::Hash + Clone,
|
||||
{
|
||||
if !crate::aabb::bounding_boxes_overlap(bounding_box, &self.bounding_box) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (key, value) in &self.pairs {
|
||||
if crate::aabb::bounding_boxes_overlap(bounding_box, key) {
|
||||
set.insert(value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(subtrees) = &self.subtrees {
|
||||
for tree in subtrees.iter() {
|
||||
tree.find_internal(bounding_box, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_subtrees(&mut self) {
|
||||
if self.subtrees.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let midx = (self.bounding_box.left + self.bounding_box.right) / 2.0;
|
||||
let midy = (self.bounding_box.top + self.bounding_box.bottom) / 2.0;
|
||||
|
||||
self.subtrees = Some(Box::new([
|
||||
QuadTree::new(
|
||||
Aabb {
|
||||
top: self.bounding_box.top,
|
||||
right: midx,
|
||||
bottom: midy,
|
||||
left: self.bounding_box.left,
|
||||
},
|
||||
self.depth - 1,
|
||||
self.inner_node_capacity,
|
||||
),
|
||||
QuadTree::new(
|
||||
Aabb {
|
||||
top: self.bounding_box.top,
|
||||
right: self.bounding_box.right,
|
||||
bottom: midy,
|
||||
left: midx,
|
||||
},
|
||||
self.depth - 1,
|
||||
self.inner_node_capacity,
|
||||
),
|
||||
QuadTree::new(
|
||||
Aabb {
|
||||
top: midy,
|
||||
right: midx,
|
||||
bottom: self.bounding_box.bottom,
|
||||
left: self.bounding_box.left,
|
||||
},
|
||||
self.depth - 1,
|
||||
self.inner_node_capacity,
|
||||
),
|
||||
QuadTree::new(
|
||||
Aabb {
|
||||
top: midy,
|
||||
right: self.bounding_box.right,
|
||||
bottom: self.bounding_box.bottom,
|
||||
left: midx,
|
||||
},
|
||||
self.depth - 1,
|
||||
self.inner_node_capacity,
|
||||
),
|
||||
]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user