forked from 1b-agent/opencadstudio-upstream
Recreate hatch regions with holes and nested island grouping
This commit is contained in:
1 parent
67f374c853
commit
dbd85c0559
1 file changed
+39
-16
+39
-16
@@ -4689,36 +4689,59 @@ impl OpenCADStudio {
|
|||||||
glam::DVec3::from_array(storage.x_axis),
|
glam::DVec3::from_array(storage.x_axis),
|
||||||
glam::DVec3::from_array(storage.y_axis),
|
glam::DVec3::from_array(storage.y_axis),
|
||||||
);
|
);
|
||||||
let entities = if region {
|
let (entities, path_groups) = if region {
|
||||||
let entities = source.paths.iter().map(|path| {
|
let loops = source.paths.iter().map(|path| {
|
||||||
let curves = path.edges.iter().map(crate::entities::hatch::edge_curve).collect::<Option<Vec<_>>>()?;
|
path.edges.iter().map(crate::entities::hatch::edge_curve).collect::<Option<Vec<_>>>()
|
||||||
crate::scene::model::presspull_model::region_from_loops(&[curves], plane)
|
|
||||||
}).collect::<Option<Vec<_>>>();
|
}).collect::<Option<Vec<_>>>();
|
||||||
let Some(entities) = entities else {
|
let Some(loops) = loops.filter(|loops| !loops.is_empty() && loops.iter().all(|ring| !ring.is_empty())) else {
|
||||||
|
self.discard_last_undo_entry(i);
|
||||||
self.command_line.push_error("HATCHEDIT: boundary cannot form a region.");
|
self.command_line.push_error("HATCHEDIT: boundary cannot form a region.");
|
||||||
return Task::none();
|
return Task::none();
|
||||||
};
|
};
|
||||||
entities
|
let contained = loops.iter().enumerate().map(|(inner, ring)| {
|
||||||
|
let seed = ring[0].point_at(0.0);
|
||||||
|
loops.iter().enumerate().map(|(outer, boundary)| {
|
||||||
|
inner != outer && cadkernel::geom2d::contains(boundary, seed, cadkernel::geom2d::Tolerance::new(1e-6))
|
||||||
|
}).collect::<Vec<_>>()
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
let depths = contained.iter().map(|row| row.iter().filter(|inside| **inside).count()).collect::<Vec<_>>();
|
||||||
|
let groups = depths.iter().enumerate().filter(|(_, depth)| **depth % 2 == 0).map(|(outer, depth)| {
|
||||||
|
let mut indices = vec![outer];
|
||||||
|
indices.extend((0..loops.len()).filter(|inner| depths[*inner] == *depth + 1 && contained[*inner][outer]));
|
||||||
|
indices
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
let entities = groups.iter().map(|indices| {
|
||||||
|
let profiles = indices.iter().map(|index| loops[*index].clone()).collect::<Vec<_>>();
|
||||||
|
crate::scene::model::presspull_model::region_from_loops(&profiles, plane)
|
||||||
|
}).collect::<Option<Vec<_>>>();
|
||||||
|
let Some(entities) = entities else {
|
||||||
|
self.discard_last_undo_entry(i);
|
||||||
|
self.command_line.push_error("HATCHEDIT: boundary cannot form a region.");
|
||||||
|
return Task::none();
|
||||||
|
};
|
||||||
|
(entities, groups)
|
||||||
} else {
|
} else {
|
||||||
let rings = crate::scene::hatch_boundary_rings(&source);
|
let rings = crate::scene::hatch_boundary_rings(&source);
|
||||||
crate::scene::boundary_entities(&rings, plane)
|
let entities = crate::scene::boundary_entities(&rings, plane);
|
||||||
|
let groups = (0..entities.len()).map(|index| vec![index]).collect();
|
||||||
|
(entities, groups)
|
||||||
};
|
};
|
||||||
let mut handles = Vec::new();
|
let mut path_handles = vec![None; source.paths.len()];
|
||||||
for entity in entities {
|
for (entity, paths) in entities.into_iter().zip(path_groups) {
|
||||||
if let Some(boundary) = self.commit_entity_handle(entity) {
|
if let Some(boundary) = self.commit_entity_handle(entity) {
|
||||||
handles.push(boundary);
|
for path in paths { if let Some(slot) = path_handles.get_mut(path) { *slot = Some(boundary); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if associate { if let Some(acadrust::EntityType::Hatch(hatch)) =
|
if associate { if let Some(acadrust::EntityType::Hatch(hatch)) =
|
||||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||||
{
|
{
|
||||||
for (path, boundary) in
|
for (path, boundary) in hatch.paths.iter_mut().zip(path_handles.iter().copied()) {
|
||||||
hatch.paths.iter_mut().zip(handles.iter().copied())
|
if let Some(boundary) = boundary {
|
||||||
{
|
path.boundary_handles = vec![boundary];
|
||||||
path.boundary_handles = vec![boundary];
|
path.flags.set_external(true);
|
||||||
path.flags.set_external(true);
|
}
|
||||||
}
|
}
|
||||||
hatch.is_associative = !handles.is_empty();
|
hatch.is_associative = path_handles.iter().all(Option::is_some);
|
||||||
} }
|
} }
|
||||||
self.tabs[i].scene.bump_entities(&[(
|
self.tabs[i].scene.bump_entities(&[(
|
||||||
handle,
|
handle,
|
||||||
|
|||||||
Reference in new issue
Block a user