Skip to content

Commit

Permalink
Set partition line on framing edge, not midline
Browse files Browse the repository at this point in the history
  • Loading branch information
GioMusto committed Mar 9, 2025
1 parent 8b7a52b commit 45cfe75
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 14 deletions.
36 changes: 29 additions & 7 deletions kikit/intervals.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,21 @@ def collectHardStops(boxes: Iterable[Box]) -> Tuple[List[AxialLine], List[AxialL
def defaultSeedFilter(boxIdA: object, boxIdB: object, vertical: bool, seedline: AxialLine) -> bool:
return True

def collectSeedLines(boxes: Dict[object, Box], seedFilter: Callable[[object, object, bool, AxialLine], bool]) \
def getSeedLinePosition(a: float, b: float, isAGhost: bool, isBGhost: bool) -> float:
"""
Given two points, and an indication if they belong to a "ghost" box,
return the point where to put the seed line.
If both are ghosts, or both are not ghosts, the seed is the midpoint,
otherwise it is the ghost point.
"""
if isAGhost == isBGhost:
return (a + b) / 2
elif isAGhost:
return a
return b

def collectSeedLines(boxes: Dict[object, Box], seedFilter: Callable[[object, object, bool, AxialLine], bool], ghosts: set[int]=set()) \
-> Tuple[List[AxialLine], List[AxialLine]]:
"""
Given a dictionary ident -> box return a list of all midlines between
Expand All @@ -336,32 +350,38 @@ def collectSeedLines(boxes: Dict[object, Box], seedFilter: Callable[[object, obj
serves as a predicate that can filter unwanted seed lines - e.g., too far
apart or comming from ghost boxes.
The ghosts parameter is a set containing the IDs of all "ghost" boxes.
Returns (horlines, verlines), where the lines are tagged with ident
"""
neighbors = BoxNeighbors(boxes)
horlines: List[AxialLine] = []
verlines: List[AxialLine] = []
for identA, boxA in boxes.items():
for identB, shadow in neighbors.leftC(identA):
mid = (boxA[0] + boxes[identB][2]) / 2
mid = getSeedLinePosition(boxA[0], boxes[identB][2],
identA in ghosts, identB in ghosts)
candidates = [AxialLine(mid, e.min, e.max, identA)
for e in shadow.intervals]
verlines.extend([x for x in candidates
if seedFilter(identA, identB, True, x)])
for identB, shadow in neighbors.rightC(identA):
mid = (boxA[2] + boxes[identB][0]) / 2
mid = getSeedLinePosition(boxA[2], boxes[identB][0],
identA in ghosts, identB in ghosts)
candidates = [AxialLine(mid, e.min, e.max, identA)
for e in shadow.intervals]
verlines.extend([x for x in candidates
if seedFilter(identA, identB, True, x)])
for identB, shadow in neighbors.topC(identA):
mid = (boxA[1] + boxes[identB][3]) / 2
mid = getSeedLinePosition(boxA[1], boxes[identB][3],
identA in ghosts, identB in ghosts)
candidates = [AxialLine(mid, e.min, e.max, identA)
for e in shadow.intervals]
horlines.extend([x for x in candidates
if seedFilter(identA, identB, False, x)])
for identB, shadow in neighbors.bottomC(identA):
mid = (boxA[3] + boxes[identB][1]) / 2
mid = getSeedLinePosition(boxA[3], boxes[identB][1],
identA in ghosts, identB in ghosts)
candidates = [AxialLine(mid, e.min, e.max, identA)
for e in shadow.intervals]
horlines.extend([x for x in candidates
Expand Down Expand Up @@ -480,21 +500,23 @@ class BoxPartitionLines:

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

hstops, vstops = collectHardStops(boxes.values())
hSafeStops, vSafeStops = collectHardStops([
shpBBoxExpand(x, safeVerticalMargin, safeHorizontalMargin) for x in boxes.values()])
hseeds, vseeds = collectSeedLines(boxes, seedFilter)
hseeds, vseeds = collectSeedLines(boxes, seedFilter, ghosts)
hshadows = buildShadows(hseeds, chain(vstops, vSafeStops))
vshadows = buildShadows(vseeds, chain(hstops, hSafeStops))

Expand Down
8 changes: 4 additions & 4 deletions kikit/panelize_ui_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,13 @@ def dummyFramingSubstrate(substrates, preset):
# algorithm (as there is no distinguishion between left and right side)
width = fromMm(1)
if vSpace is not None:
top = box(minx, miny - 2 * vSpace - width, maxx, miny - 2 * vSpace)
bottom = box(minx, maxy + 2 * vSpace, maxx, maxy + 2 * vSpace + width)
top = box(minx, miny - vSpace - width, maxx, miny - vSpace)
bottom = box(minx, maxy + vSpace, maxx, maxy + vSpace + width)
dummy.append(polygonToSubstrate(top))
dummy.append(polygonToSubstrate(bottom))
if hSpace is not None:
left = box(minx - 2 * hSpace - width, miny, minx - 2 * hSpace, maxy)
right = box(maxx + 2 * hSpace, miny, maxx + 2 * hSpace + width, maxy)
left = box(minx - hSpace - width, miny, minx - hSpace, maxy)
right = box(maxx + hSpace, miny, maxx + hSpace + width, maxy)
dummy.append(polygonToSubstrate(left))
dummy.append(polygonToSubstrate(right))
return dummy
Expand Down
5 changes: 2 additions & 3 deletions kikit/substrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1086,9 +1086,8 @@ def seedFilter(idA, idB, v, l):
return False
return idA not in ghosts or idB not in ghosts
self._partition = BoxPartitionLines(
self._preprocessBoxes(boxes),
seedFilter,
safeHorizontalMargin, safeVerticalMargin)
self._preprocessBoxes(boxes), seedFilter,
safeHorizontalMargin, safeVerticalMargin, ghosts)

def _preprocessBoxes(self, boxes):
"""
Expand Down

0 comments on commit 45cfe75

Please sign in to comment.