From 610f7f140df87462c982b2c38c13134d23f4160e Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 12 Jun 2026 01:06:29 +0300 Subject: [PATCH] fix(trim): trim/extend against polyline boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build_geos only turned Line/Arc/Circle/Ray/XLine/Ellipse/Spline into cutting-edge geometry, so a polyline contributed no boundary and a line could not be trimmed (or extended) against it — even though trimming the polyline itself against lines already worked. Explode each polyline (LwPolyline / Polyline / Polyline2D / Polyline3D) into its Line + Arc segments and add them as boundaries, tagged with the polyline's handle so the click-target self-exclusion still holds. Factored the per-entity Geo build into geo_from_entity and exposed explode_polyline_segments. Co-Authored-By: Claude Opus 4.8 --- src/modules/home/modify/explode.rs | 14 ++++++++++ src/modules/home/modify/trim.rs | 44 ++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/modules/home/modify/explode.rs b/src/modules/home/modify/explode.rs index fe6b27624..c4869b81e 100644 --- a/src/modules/home/modify/explode.rs +++ b/src/modules/home/modify/explode.rs @@ -41,6 +41,20 @@ pub fn tool() -> ToolDef { // ── Geometry helpers ──────────────────────────────────────────────────────── +/// Explode just the polyline family (LwPolyline / Polyline / Polyline2D / +/// Polyline3D) into Line + Arc segments. No document needed — used where a +/// polyline must be treated as its constituent edges (e.g. TRIM boundaries). +/// Returns empty for any other entity type. +pub fn explode_polyline_segments(entity: &EntityType) -> Vec { + match entity { + EntityType::LwPolyline(p) => explode_lwpolyline(p), + EntityType::Polyline2D(p) => explode_polyline2d(p), + EntityType::Polyline(p) => explode_polyline(p), + EntityType::Polyline3D(p) => explode_polyline3d(p), + _ => vec![], + } +} + /// Decompose an entity into its constituent simple entities. /// Returns an empty vec if the entity cannot be exploded. pub fn explode_entity(entity: &EntityType, document: &CadDocument) -> Vec { diff --git a/src/modules/home/modify/trim.rs b/src/modules/home/modify/trim.rs index b7c6836cc..7269afb16 100644 --- a/src/modules/home/modify/trim.rs +++ b/src/modules/home/modify/trim.rs @@ -269,11 +269,39 @@ enum Geo { } fn build_geos(entities: &[EntityType]) -> Vec { - entities - .iter() - .filter_map(|e| { - let h = e.common().handle; - match e { + let mut out = Vec::new(); + for e in entities { + let h = e.common().handle; + match e { + // A polyline acts as a boundary through its constituent edges, so + // a Line/Arc/… can be trimmed against it. Explode into Line + Arc + // segments and tag each with the polyline's own handle (so trim + // still excludes it as the click target). + EntityType::LwPolyline(_) + | EntityType::Polyline(_) + | EntityType::Polyline2D(_) + | EntityType::Polyline3D(_) => { + for seg in crate::modules::home::modify::explode::explode_polyline_segments(e) { + if let Some(g) = geo_from_entity(h, &seg) { + out.push(g); + } + } + } + _ => { + if let Some(g) = geo_from_entity(h, e) { + out.push(g); + } + } + } + } + out +} + +/// Convert a simple boundary entity (Line / Arc / Circle / Ray / XLine / +/// Ellipse / Spline) into a `Geo`, tagged with `h`. Returns `None` for types +/// that do not act as trim boundaries. +fn geo_from_entity(h: Handle, e: &EntityType) -> Option { + match e { EntityType::Line(l) => Some(Geo::Line { handle: h, p1: [l.start.x, l.start.y], @@ -344,10 +372,8 @@ fn build_geos(entities: &[EntityType]) -> Vec { .collect(); Some(Geo::Spline { handle: h, segs }) } - _ => None, - } - }) - .collect() + _ => None, + } } // ── Intersection helpers ──────────────────────────────────────────────────