Skip to content

Commit 42a6ee8

Browse files
committed
WIP
1 parent ee67ded commit 42a6ee8

File tree

4 files changed

+83
-13
lines changed

4 files changed

+83
-13
lines changed

lib/solvers/GapFillSolver.ts

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,10 @@ export class GapFillSolver extends BaseSolver {
236236
}
237237

238238
private stepCheckUnoccupied(): void {
239-
// Find all unoccupied sections at once (can be broken down further if needed)
240239
const primaryEdge = this.state.currentPrimaryEdge!
241240
this.state.currentUnoccupiedSections =
242241
this.findUnoccupiedSections(primaryEdge)
243242

244-
// Move to placing expansion points
245243
this.state.phase = "PLACE_EXPANSION_POINTS"
246244
}
247245

@@ -266,15 +264,80 @@ export class GapFillSolver extends BaseSolver {
266264
const point =
267265
this.state.currentExpansionPoints[this.state.currentExpansionIndex]!
268266

269-
// TODO: Actually expand the point into a rectangle
270-
// For now, just move to next point
267+
const filledRect = this.expandPointToRect(point)
268+
if (filledRect && !this.overlapsExistingFill(filledRect)) {
269+
this.state.filledRects.push(filledRect)
270+
}
271271

272272
this.state.currentExpansionIndex++
273273
} else {
274274
this.moveToNextEdge()
275275
}
276276
}
277277

278+
private overlapsExistingFill(candidate: Placed3D): boolean {
279+
for (const existing of this.state.filledRects) {
280+
const sharedLayers = candidate.zLayers.filter((z) =>
281+
existing.zLayers.includes(z),
282+
)
283+
if (sharedLayers.length === 0) continue
284+
285+
const overlapX =
286+
Math.max(candidate.rect.x, existing.rect.x) <
287+
Math.min(
288+
candidate.rect.x + candidate.rect.width,
289+
existing.rect.x + existing.rect.width,
290+
)
291+
const overlapY =
292+
Math.max(candidate.rect.y, existing.rect.y) <
293+
Math.min(
294+
candidate.rect.y + candidate.rect.height,
295+
existing.rect.y + existing.rect.height,
296+
)
297+
298+
if (overlapX && overlapY) {
299+
return true
300+
}
301+
}
302+
303+
return false
304+
}
305+
306+
private expandPointToRect(point: ExpansionPoint): Placed3D | null {
307+
const section = point.section
308+
const edge = section.edge
309+
310+
const nearbyEdge = this.state.currentNearbyEdges[0]
311+
if (!nearbyEdge) return null
312+
313+
let rect: { x: number; y: number; width: number; height: number }
314+
315+
if (Math.abs(edge.normal.x) > 0.5) {
316+
const x1 = Math.min(edge.x1, nearbyEdge.x1)
317+
const x2 = Math.max(edge.x1, nearbyEdge.x1)
318+
rect = {
319+
x: x1,
320+
y: section.y1,
321+
width: x2 - x1,
322+
height: section.y2 - section.y1,
323+
}
324+
} else {
325+
const y1 = Math.min(edge.y1, nearbyEdge.y1)
326+
const y2 = Math.max(edge.y1, nearbyEdge.y1)
327+
rect = {
328+
x: section.x1,
329+
y: y1,
330+
width: section.x2 - section.x1,
331+
height: y2 - y1,
332+
}
333+
}
334+
335+
return {
336+
rect,
337+
zLayers: [...point.zLayers],
338+
}
339+
}
340+
278341
private moveToNextEdge(): void {
279342
this.state.currentEdgeIndex++
280343
this.state.phase = "SELECT_PRIMARY_EDGE"
@@ -372,7 +435,7 @@ export class GapFillSolver extends BaseSolver {
372435
height: placed.rect.height,
373436
fill: "#f3f4f6",
374437
stroke: "#9ca3af",
375-
label: "existing",
438+
label: `input rect\npos: (${placed.rect.x.toFixed(2)}, ${placed.rect.y.toFixed(2)})\nsize: ${placed.rect.width.toFixed(2)} × ${placed.rect.height.toFixed(2)}\nz: [${placed.zLayers.join(", ")}]`,
376439
})
377440
}
378441

@@ -386,33 +449,43 @@ export class GapFillSolver extends BaseSolver {
386449
],
387450
strokeColor: "#3b82f6",
388451
strokeWidth: 0.08,
389-
label: "primary edge",
452+
label: `primary edge (${e.side})\n(${e.x1.toFixed(2)}, ${e.y1.toFixed(2)}) → (${e.x2.toFixed(2)}, ${e.y2.toFixed(2)})\nnormal: (${e.normal.x}, ${e.normal.y})\nz: [${e.zLayers.join(", ")}]`,
390453
})
391454
}
392455

393456
// Highlight nearby edges (orange)
394457
for (const edge of this.state.currentNearbyEdges) {
458+
const distance = this.state.currentPrimaryEdge
459+
? this.distanceBetweenEdges(
460+
this.state.currentPrimaryEdge,
461+
edge,
462+
).toFixed(2)
463+
: "?"
395464
lines.push({
396465
points: [
397466
{ x: edge.x1, y: edge.y1 },
398467
{ x: edge.x2, y: edge.y2 },
399468
],
400469
strokeColor: "#f97316",
401470
strokeWidth: 0.06,
402-
label: "nearby edge",
471+
label: `nearby edge (${edge.side})\n(${edge.x1.toFixed(2)}, ${edge.y1.toFixed(2)}) → (${edge.x2.toFixed(2)}, ${edge.y2.toFixed(2)})\ndist: ${distance}mm\nz: [${edge.zLayers.join(", ")}]`,
403472
})
404473
}
405474

406475
// Highlight unoccupied sections (green)
407476
for (const section of this.state.currentUnoccupiedSections) {
477+
const length = Math.sqrt(
478+
Math.pow(section.x2 - section.x1, 2) +
479+
Math.pow(section.y2 - section.y1, 2),
480+
)
408481
lines.push({
409482
points: [
410483
{ x: section.x1, y: section.y1 },
411484
{ x: section.x2, y: section.y2 },
412485
],
413486
strokeColor: "#10b981",
414487
strokeWidth: 0.04,
415-
label: "unoccupied",
488+
label: `unoccupied section\n(${section.x1.toFixed(2)}, ${section.y1.toFixed(2)}) → (${section.x2.toFixed(2)}, ${section.y2.toFixed(2)})\nlength: ${length.toFixed(2)}mm\nrange: ${(section.start * 100).toFixed(0)}%-${(section.end * 100).toFixed(0)}%`,
416489
})
417490
}
418491

@@ -423,7 +496,7 @@ export class GapFillSolver extends BaseSolver {
423496
y: point.y,
424497
fill: "#a855f7",
425498
stroke: "#7e22ce",
426-
label: "expand",
499+
label: `expansion point\npos: (${point.x.toFixed(2)}, ${point.y.toFixed(2)})\nz: [${point.zLayers.join(", ")}]`,
427500
} as any)
428501
}
429502

@@ -438,7 +511,7 @@ export class GapFillSolver extends BaseSolver {
438511
height: placed.rect.height,
439512
fill: "#d1fae5",
440513
stroke: "#10b981",
441-
label: "filled gap",
514+
label: `filled gap\npos: (${placed.rect.x.toFixed(2)}, ${placed.rect.y.toFixed(2)})\nsize: ${placed.rect.width.toFixed(2)} × ${placed.rect.height.toFixed(2)}\nz: [${placed.zLayers.join(", ")}]`,
442515
})
443516
}
444517

pages/repro/gap-fill-solver/simple-two-rect-with-gap.page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useMemo } from "react"
2-
import { SolverDebugger3d } from "../../../components/SolverDebugger3d"
32
import { GapFillSolver } from "../../../lib/solvers/GapFillSolver"
43
import type { SimpleRouteJson } from "../../../lib/types/srj-types"
54
import type { Placed3D } from "../../../lib/solvers/rectdiff/types"

pages/repro/gap-fill-solver/staggered-rects.page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useMemo } from "react"
2-
import { SolverDebugger3d } from "../../../components/SolverDebugger3d"
32
import { GapFillSolver } from "../../../lib/solvers/GapFillSolver"
43
import type { SimpleRouteJson } from "../../../lib/types/srj-types"
54
import type { Placed3D } from "../../../lib/solvers/rectdiff/types"

pages/repro/gap-fill-solver/vertical-and-horizontal-gaps.page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useMemo } from "react"
2-
import { SolverDebugger3d } from "../../../components/SolverDebugger3d"
32
import { GapFillSolver } from "../../../lib/solvers/GapFillSolver"
43
import type { SimpleRouteJson } from "../../../lib/types/srj-types"
54
import type { Placed3D } from "../../../lib/solvers/rectdiff/types"

0 commit comments

Comments
 (0)