Change the way QuadTree.getLeafUnder() locate the leaf.

* Change: In cumulus/plugins.Block.getLeafUnder(): formerly, we where
    using the cut-lines (x/y) to locate which leaf a point is under.
    But in case of incomplete tree, it is difficult to manage.
      Now we chosse the leaf according to the distance to the center
    of the leaf area. Choose the shorter, of course.
      This solve the H-Tree DFF bad assignment around the PLL (top
    right corner) in LS180.
This commit is contained in:
Jean-Paul Chaput 2021-06-06 10:55:24 +02:00
parent a2daf26fca
commit 352ca94483
1 changed files with 25 additions and 21 deletions

View File

@ -345,6 +345,10 @@ class QuadTree ( object ):
if self.tr: self.tr.removeUnusedBuffers() if self.tr: self.tr.removeUnusedBuffers()
self.pool._removeUnuseds() self.pool._removeUnuseds()
def getDistance ( self, point ):
"""Return the Manhattan distance between ``point`` and the area center."""
return self.area.getCenter().manhattanDistance( point )
def rshowPoolUse ( self ): def rshowPoolUse ( self ):
rused = 0 rused = 0
rtotal = 0 rtotal = 0
@ -696,27 +700,27 @@ class QuadTree ( object ):
def getLeafUnder ( self, position ): def getLeafUnder ( self, position ):
"""Find the QuadTree leaf under ``position``.""" """Find the QuadTree leaf under ``position``."""
if self.isLeaf(): return self if self.isLeaf(): return self
if self.isHBipart(): candidate = None
if position.getX() < self.xcut: return self.bl.getLeafUnder(position) minDist = None
return self.br.getLeafUnder(position) if self.bl:
if self.isVBipart(): minDist = self.bl.getDistance( position )
if position.getY() < self.ycut: return self.bl.getLeafUnder(position) candidate = self.bl
return self.tl.getLeafUnder(position) if self.br:
leaf = None distance = self.br.getDistance( position )
if position.getX() < self.xcut: if (candidate is None) or (distance < minDist):
if position.getY() < self.ycut: leaf = self.bl minDist = distance
else: leaf = self.tl candidate = self.br
else: if self.tl:
if position.getY() < self.ycut: leaf = self.br distance = self.tl.getDistance( position )
else: leaf = self.tr if (candidate is None) or (distance < minDist):
if not leaf: minDist = distance
dx = abs( position.getX() - self.xcut ) candidate = self.tl
dy = abs( position.getY() - self.ycut ) if self.tr:
if self.tr and ((dx < dy) or not leaf): leaf = self.tr distance = self.tr.getDistance( position )
if self.tl and ((dx < dy) or not leaf): leaf = self.tl if (candidate is None) or (distance < minDist):
if self.br and ((dx >= dy) or not leaf): leaf = self.br minDist = distance
if self.bl and ((dx >= dy) or not leaf): leaf = self.bl candidate = self.tr
return leaf.getLeafUnder(position) return candidate.getLeafUnder(position)
def getFreeLeafUnder ( self, area, attractor=None ): def getFreeLeafUnder ( self, area, attractor=None ):
""" """