Skip to content

Commit 45cfe75

Browse files
committed
Set partition line on framing edge, not midline
1 parent 8b7a52b commit 45cfe75

3 files changed

Lines changed: 35 additions & 14 deletions

File tree

kikit/intervals.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,21 @@ def collectHardStops(boxes: Iterable[Box]) -> Tuple[List[AxialLine], List[AxialL
326326
def defaultSeedFilter(boxIdA: object, boxIdB: object, vertical: bool, seedline: AxialLine) -> bool:
327327
return True
328328

329-
def collectSeedLines(boxes: Dict[object, Box], seedFilter: Callable[[object, object, bool, AxialLine], bool]) \
329+
def getSeedLinePosition(a: float, b: float, isAGhost: bool, isBGhost: bool) -> float:
330+
"""
331+
Given two points, and an indication if they belong to a "ghost" box,
332+
return the point where to put the seed line.
333+
334+
If both are ghosts, or both are not ghosts, the seed is the midpoint,
335+
otherwise it is the ghost point.
336+
"""
337+
if isAGhost == isBGhost:
338+
return (a + b) / 2
339+
elif isAGhost:
340+
return a
341+
return b
342+
343+
def collectSeedLines(boxes: Dict[object, Box], seedFilter: Callable[[object, object, bool, AxialLine], bool], ghosts: set[int]=set()) \
330344
-> Tuple[List[AxialLine], List[AxialLine]]:
331345
"""
332346
Given a dictionary ident -> box return a list of all midlines between
@@ -336,32 +350,38 @@ def collectSeedLines(boxes: Dict[object, Box], seedFilter: Callable[[object, obj
336350
serves as a predicate that can filter unwanted seed lines - e.g., too far
337351
apart or comming from ghost boxes.
338352
353+
The ghosts parameter is a set containing the IDs of all "ghost" boxes.
354+
339355
Returns (horlines, verlines), where the lines are tagged with ident
340356
"""
341357
neighbors = BoxNeighbors(boxes)
342358
horlines: List[AxialLine] = []
343359
verlines: List[AxialLine] = []
344360
for identA, boxA in boxes.items():
345361
for identB, shadow in neighbors.leftC(identA):
346-
mid = (boxA[0] + boxes[identB][2]) / 2
362+
mid = getSeedLinePosition(boxA[0], boxes[identB][2],
363+
identA in ghosts, identB in ghosts)
347364
candidates = [AxialLine(mid, e.min, e.max, identA)
348365
for e in shadow.intervals]
349366
verlines.extend([x for x in candidates
350367
if seedFilter(identA, identB, True, x)])
351368
for identB, shadow in neighbors.rightC(identA):
352-
mid = (boxA[2] + boxes[identB][0]) / 2
369+
mid = getSeedLinePosition(boxA[2], boxes[identB][0],
370+
identA in ghosts, identB in ghosts)
353371
candidates = [AxialLine(mid, e.min, e.max, identA)
354372
for e in shadow.intervals]
355373
verlines.extend([x for x in candidates
356374
if seedFilter(identA, identB, True, x)])
357375
for identB, shadow in neighbors.topC(identA):
358-
mid = (boxA[1] + boxes[identB][3]) / 2
376+
mid = getSeedLinePosition(boxA[1], boxes[identB][3],
377+
identA in ghosts, identB in ghosts)
359378
candidates = [AxialLine(mid, e.min, e.max, identA)
360379
for e in shadow.intervals]
361380
horlines.extend([x for x in candidates
362381
if seedFilter(identA, identB, False, x)])
363382
for identB, shadow in neighbors.bottomC(identA):
364-
mid = (boxA[3] + boxes[identB][1]) / 2
383+
mid = getSeedLinePosition(boxA[3], boxes[identB][1],
384+
identA in ghosts, identB in ghosts)
365385
candidates = [AxialLine(mid, e.min, e.max, identA)
366386
for e in shadow.intervals]
367387
horlines.extend([x for x in candidates
@@ -480,21 +500,23 @@ class BoxPartitionLines:
480500

481501
def __init__(self, boxes: Dict[object, Box],
482502
seedFilter: Callable[[object, object, bool, AxialLine], bool]=defaultSeedFilter,
483-
safeHorizontalMargin: float=0, safeVerticalMargin: float=0) -> None:
503+
safeHorizontalMargin: float=0, safeVerticalMargin: float=0, ghosts: set[int]=set()) -> None:
484504
"""
485505
Given a dictionary id -> box initializes the structure.
486506
487507
Boxes are represented by a tuple (minx, miny, maxx, maxy)
488508
489509
The margin guarantees there will be no partition line too close to edge
490510
(necessary to handle some pathological cases)
511+
512+
The ghosts parameter is a set containing the IDs of all "ghost" boxes.
491513
"""
492514
from kikit.common import shpBBoxExpand
493515

494516
hstops, vstops = collectHardStops(boxes.values())
495517
hSafeStops, vSafeStops = collectHardStops([
496518
shpBBoxExpand(x, safeVerticalMargin, safeHorizontalMargin) for x in boxes.values()])
497-
hseeds, vseeds = collectSeedLines(boxes, seedFilter)
519+
hseeds, vseeds = collectSeedLines(boxes, seedFilter, ghosts)
498520
hshadows = buildShadows(hseeds, chain(vstops, vSafeStops))
499521
vshadows = buildShadows(vseeds, chain(hstops, hSafeStops))
500522

kikit/panelize_ui_impl.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,13 @@ def dummyFramingSubstrate(substrates, preset):
418418
# algorithm (as there is no distinguishion between left and right side)
419419
width = fromMm(1)
420420
if vSpace is not None:
421-
top = box(minx, miny - 2 * vSpace - width, maxx, miny - 2 * vSpace)
422-
bottom = box(minx, maxy + 2 * vSpace, maxx, maxy + 2 * vSpace + width)
421+
top = box(minx, miny - vSpace - width, maxx, miny - vSpace)
422+
bottom = box(minx, maxy + vSpace, maxx, maxy + vSpace + width)
423423
dummy.append(polygonToSubstrate(top))
424424
dummy.append(polygonToSubstrate(bottom))
425425
if hSpace is not None:
426-
left = box(minx - 2 * hSpace - width, miny, minx - 2 * hSpace, maxy)
427-
right = box(maxx + 2 * hSpace, miny, maxx + 2 * hSpace + width, maxy)
426+
left = box(minx - hSpace - width, miny, minx - hSpace, maxy)
427+
right = box(maxx + hSpace, miny, maxx + hSpace + width, maxy)
428428
dummy.append(polygonToSubstrate(left))
429429
dummy.append(polygonToSubstrate(right))
430430
return dummy

kikit/substrate.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,9 +1086,8 @@ def seedFilter(idA, idB, v, l):
10861086
return False
10871087
return idA not in ghosts or idB not in ghosts
10881088
self._partition = BoxPartitionLines(
1089-
self._preprocessBoxes(boxes),
1090-
seedFilter,
1091-
safeHorizontalMargin, safeVerticalMargin)
1089+
self._preprocessBoxes(boxes), seedFilter,
1090+
safeHorizontalMargin, safeVerticalMargin, ghosts)
10921091

10931092
def _preprocessBoxes(self, boxes):
10941093
"""

0 commit comments

Comments
 (0)