From 61426b5e79b1290695ffc3c3a0b7ced14ffba99b Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 13 May 2026 13:15:01 +0200 Subject: [PATCH] Refactor path deletion logic and add utilities for managing spline corridor path clip intervals --- src/commands/delete-path-command.ts | 31 +++++++----- src/spline-corridor/spline-corridor-clips.ts | 51 ++++++++++++++++++++ 2 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 src/spline-corridor/spline-corridor-clips.ts diff --git a/src/commands/delete-path-command.ts b/src/commands/delete-path-command.ts index ccdaa6ee..4a3b78c9 100644 --- a/src/commands/delete-path-command.ts +++ b/src/commands/delete-path-command.ts @@ -65,19 +65,24 @@ export function createDeletePathCommand(pathId: string): EditorCommand { ...currentDocument.paths }; delete nextPaths[pathId]; - const nextJunctions = Object.fromEntries( - Object.entries(currentDocument.splineCorridorJunctions) - .map(([junctionId, junction]) => [ - junctionId, - cloneSplineCorridorJunction({ - ...junction, - connections: junction.connections.filter( - (connection) => connection.pathId !== pathId - ) - }) - ]) - .filter(([, junction]) => junction.connections.length >= 2) - ); + const nextJunctions: Record = {}; + + for (const [junctionId, junction] of Object.entries( + currentDocument.splineCorridorJunctions + )) { + const connections = junction.connections.filter( + (connection) => connection.pathId !== pathId + ); + + if (connections.length < 2) { + continue; + } + + nextJunctions[junctionId] = cloneSplineCorridorJunction({ + ...junction, + connections + }); + } context.setDocument({ ...currentDocument, diff --git a/src/spline-corridor/spline-corridor-clips.ts b/src/spline-corridor/spline-corridor-clips.ts new file mode 100644 index 00000000..24d76e2d --- /dev/null +++ b/src/spline-corridor/spline-corridor-clips.ts @@ -0,0 +1,51 @@ +export interface SplineCorridorPathClipInterval { + junctionId: string; + startDistance: number; + endDistance: number; +} + +export type SplineCorridorPathClipIntervalMap = Map< + string, + SplineCorridorPathClipInterval[] +>; + +export function isDistanceInSplineCorridorClipIntervals( + distance: number, + intervals: readonly SplineCorridorPathClipInterval[] | undefined +): boolean { + if (intervals === undefined || intervals.length === 0) { + return false; + } + + return intervals.some( + (interval) => + distance >= interval.startDistance && distance <= interval.endDistance + ); +} + +export function mergeSplineCorridorPathClipIntervals( + intervals: readonly SplineCorridorPathClipInterval[] +): SplineCorridorPathClipInterval[] { + if (intervals.length <= 1) { + return [...intervals]; + } + + const sortedIntervals = [...intervals].sort( + (left, right) => left.startDistance - right.startDistance + ); + const merged: SplineCorridorPathClipInterval[] = []; + + for (const interval of sortedIntervals) { + const previous = merged[merged.length - 1]; + + if (previous === undefined || interval.startDistance > previous.endDistance) { + merged.push({ ...interval }); + continue; + } + + previous.endDistance = Math.max(previous.endDistance, interval.endDistance); + } + + return merged; +} +