diff --git a/lib/solvers/GapFillSolver/ExpandEdgesToEmptySpaceSolver.ts b/lib/solvers/GapFillSolver/ExpandEdgesToEmptySpaceSolver.ts index fb21c92..60b6bd5 100644 --- a/lib/solvers/GapFillSolver/ExpandEdgesToEmptySpaceSolver.ts +++ b/lib/solvers/GapFillSolver/ExpandEdgesToEmptySpaceSolver.ts @@ -174,17 +174,63 @@ export class ExpandEdgesToEmptySpaceSolver extends BaseSolver { const nodeWidth = nodeBounds.maxX - nodeBounds.minX const nodeHeight = nodeBounds.maxY - nodeBounds.minY - const expandedSegment = { - segment, - newNode: { - capacityMeshNodeId: `new-${segment.parent.capacityMeshNodeId}-${this.expandedSegments.length}`, - center: nodeCenter, - width: nodeWidth, - height: nodeHeight, - availableZ: [segment.z], - layer: segment.parent.layer, - }, + let expandedSegment: ExpandedSegment + + if (segment.isSegmentSameLengthAsParentEdge) { + // Segment is broken, create a new node + expandedSegment = { + segment, + newNode: { + capacityMeshNodeId: `new-${segment.parent.capacityMeshNodeId}-${this.expandedSegments.length}`, + center: nodeCenter, + width: nodeWidth, + height: nodeHeight, + availableZ: [segment.z], + layer: segment.parent.layer, + }, + } + } else { + // Segment is not broken (original size), expand the parent node + const parentBounds = { + minX: segment.parent.center.x - segment.parent.width / 2, + minY: segment.parent.center.y - segment.parent.height / 2, + maxX: segment.parent.center.x + segment.parent.width / 2, + maxY: segment.parent.center.y + segment.parent.height / 2, + } + + // Merge the parent bounds with the new expansion bounds + const mergedBounds = { + minX: Math.min(parentBounds.minX, nodeBounds.minX), + minY: Math.min(parentBounds.minY, nodeBounds.minY), + maxX: Math.max(parentBounds.maxX, nodeBounds.maxX), + maxY: Math.max(parentBounds.maxY, nodeBounds.maxY), + } + + const mergedCenter = { + x: (mergedBounds.minX + mergedBounds.maxX) / 2, + y: (mergedBounds.minY + mergedBounds.maxY) / 2, + } + const mergedWidth = mergedBounds.maxX - mergedBounds.minX + const mergedHeight = mergedBounds.maxY - mergedBounds.minY + + // Merge availableZ arrays (remove duplicates) + const mergedAvailableZ = Array.from( + new Set([...segment.parent.availableZ, segment.z]), + ) + + expandedSegment = { + segment, + newNode: { + capacityMeshNodeId: `expanded-${mergedWidth}-${mergedHeight}-${segment.parent.capacityMeshNodeId}`, + center: mergedCenter, + width: mergedWidth, + height: mergedHeight, + availableZ: mergedAvailableZ, + layer: segment.parent.layer, + }, + } } + this.lastExpandedSegment = expandedSegment if (nodeWidth < EPS || nodeHeight < EPS) { diff --git a/lib/solvers/GapFillSolver/FindSegmentsWithAdjacentEmptySpaceSolver.ts b/lib/solvers/GapFillSolver/FindSegmentsWithAdjacentEmptySpaceSolver.ts index a6280aa..a2c8c7d 100644 --- a/lib/solvers/GapFillSolver/FindSegmentsWithAdjacentEmptySpaceSolver.ts +++ b/lib/solvers/GapFillSolver/FindSegmentsWithAdjacentEmptySpaceSolver.ts @@ -13,6 +13,7 @@ export interface SegmentWithAdjacentEmptySpace { end: { x: number; y: number } z: number facingDirection: "x+" | "x-" | "y+" | "y-" + isSegmentSameLengthAsParentEdge: boolean } const EPS = 1e-4 @@ -73,6 +74,7 @@ export class FindSegmentsWithAdjacentEmptySpaceSolver extends BaseSolver { end, facingDirection: edge.facingDirection, z, + isSegmentSameLengthAsParentEdge: false, }) } } @@ -111,14 +113,14 @@ export class FindSegmentsWithAdjacentEmptySpaceSolver extends BaseSolver { candidateEdge.end.y + EPS, ) - const overlappingEdges = nearbyEdges + const mightBeOverlappingEdges = nearbyEdges .map((i) => this.allEdges[i]!) .filter((e) => e.z === candidateEdge.z) - this.lastOverlappingEdges = overlappingEdges + this.lastOverlappingEdges = mightBeOverlappingEdges const uncoveredSegments = projectToUncoveredSegments( candidateEdge, - overlappingEdges, + mightBeOverlappingEdges, ) this.lastUncoveredSegments = uncoveredSegments this.segmentsWithAdjacentEmptySpace.push(...uncoveredSegments) diff --git a/lib/solvers/GapFillSolver/GapFillSolverPipeline.ts b/lib/solvers/GapFillSolver/GapFillSolverPipeline.ts index cb2e231..94b8f81 100644 --- a/lib/solvers/GapFillSolver/GapFillSolverPipeline.ts +++ b/lib/solvers/GapFillSolver/GapFillSolverPipeline.ts @@ -59,10 +59,24 @@ export class GapFillSolverPipeline extends BasePipelineSolver !es.segment.isSegmentSameLengthAsParentEdge) + .map((es) => es.segment.parent.capacityMeshNodeId), + ) + + // Filter out parent nodes that were expanded + const nonExpandedOriginalNodes = this.inputProblem.meshNodes.filter( + (node) => !expandedParentNodeIds.has(node.capacityMeshNodeId), + ) + + // Add all expanded nodes (both broken and non-broken segments) const expandedNodes = expandedSegments.map((es) => es.newNode) return { - outputNodes: [...this.inputProblem.meshNodes, ...expandedNodes], + outputNodes: [...nonExpandedOriginalNodes, ...expandedNodes], } } diff --git a/lib/solvers/GapFillSolver/projectToUncoveredSegments.ts b/lib/solvers/GapFillSolver/projectToUncoveredSegments.ts index f73088e..f8a5bd1 100644 --- a/lib/solvers/GapFillSolver/projectToUncoveredSegments.ts +++ b/lib/solvers/GapFillSolver/projectToUncoveredSegments.ts @@ -4,7 +4,7 @@ const EPS = 1e-4 export function projectToUncoveredSegments( primaryEdge: SegmentWithAdjacentEmptySpace, - overlappingEdges: SegmentWithAdjacentEmptySpace[], + mightBeOverlappingEdges: SegmentWithAdjacentEmptySpace[], ): Array { const isHorizontal = Math.abs(primaryEdge.start.y - primaryEdge.end.y) < EPS const isVertical = Math.abs(primaryEdge.start.x - primaryEdge.end.x) < EPS @@ -23,7 +23,7 @@ export function projectToUncoveredSegments( // 1) project each overlapping edge to an interval on the primary edge const intervals: Array<{ s: number; e: number }> = [] - for (const e of overlappingEdges) { + for (const e of mightBeOverlappingEdges) { if (e === primaryEdge) continue // only consider edges parallel + colinear (within EPS) with the primary edge @@ -48,6 +48,7 @@ export function projectToUncoveredSegments( ...primaryEdge, start: { ...primaryEdge.start }, end: { ...primaryEdge.end }, + isSegmentSameLengthAsParentEdge: false, }, ] } @@ -87,6 +88,7 @@ export function projectToUncoveredSegments( start, end, z: primaryEdge.z, + isSegmentSameLengthAsParentEdge: true, } }) } diff --git a/tests/__snapshots__/should-expand-node.snap.svg b/tests/__snapshots__/should-expand-node.snap.svg index 8282007..7f4db56 100644 --- a/tests/__snapshots__/should-expand-node.snap.svg +++ b/tests/__snapshots__/should-expand-node.snap.svg @@ -1,4 +1,4 @@ -