@@ -326,7 +326,21 @@ def collectHardStops(boxes: Iterable[Box]) -> Tuple[List[AxialLine], List[AxialL
326326def 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
0 commit comments