Enforce recurrence depth, with error message

This commit is contained in:
Ian Jauslin 2021-11-24 22:49:42 -05:00
parent cf80682890
commit e68c671fc5

View File

@ -146,7 +146,7 @@ class Painter(Widget):
# only move on left click # only move on left click
if touch.button=="left" and self.modifiers==[] and self.undermouse!=None: if touch.button=="left" and self.modifiers==[] and self.undermouse!=None:
# attempted move determined by the relative position to the relative position of click within self.undermouse # attempted move determined by the relative position to the relative position of click within self.undermouse
delta=self.adjust_move(Point(touch.x/Square_element.size,touch.y/Square_element.size)-(self.offset+self.undermouse.squares[0].pos)) delta=self.adjust_move(Point(touch.x/Square_element.size,touch.y/Square_element.size)-(self.offset+self.undermouse.squares[0].pos),0)
for particle in self.selected: for particle in self.selected:
particle.move(delta) particle.move(delta)
@ -196,13 +196,13 @@ class Painter(Widget):
# try to move all selected particles by delta, adjust if needed to avoid overlap with unselected particles # try to move all selected particles by delta, adjust if needed to avoid overlap with unselected particles
# we only track whether these elements collide with unselected particles, not with each other # we only track whether these elements collide with unselected particles, not with each other
def adjust_move(self,delta): def adjust_move(self,delta,recursion_depth):
# actual_delta is the smallest (componentwise) of all the computed delta's # actual_delta is the smallest (componentwise) of all the computed delta's
actual_delta=Point(math.inf,math.inf) actual_delta=Point(math.inf,math.inf)
for particle in self.selected: for particle in self.selected:
for element in particle.squares: for element in particle.squares:
# compute adjustment move due to unselected obstacles # compute adjustment move due to unselected obstacles
adjusted_delta=self.adjust_move_element(delta,element) adjusted_delta=self.adjust_move_element(delta,element,0)
# only keep the smallest delta's (in absolute value) # only keep the smallest delta's (in absolute value)
if abs(adjusted_delta.x)<abs(actual_delta.x): if abs(adjusted_delta.x)<abs(actual_delta.x):
actual_delta.x=adjusted_delta.x actual_delta.x=adjusted_delta.x
@ -213,11 +213,16 @@ class Painter(Widget):
return actual_delta return actual_delta
else: else:
# cannot move particles at all, try again # cannot move particles at all, try again
return self.adjust_move(actual_delta) # give up if tried too many times
if recursion_depth>100:
print("warning: recursion depth exceeded when adjusting move by delta=(",delta.x,",",delta.y,")",file=sys.stderr)
return Point(0,0)
else:
return self.adjust_move(actual_delta,recursion_depth+1)
# trying to move a single element by delta, adjust if needed to avoid overlap with unselected particles # trying to move a single element by delta, adjust if needed to avoid overlap with unselected particles
def adjust_move_element(self,delta,element): def adjust_move_element(self,delta,element,recursion_depth):
# whether newpos is acceptable # whether newpos is acceptable
accept_newpos=True accept_newpos=True
for other in self.unselected: for other in self.unselected:
@ -237,7 +242,12 @@ class Painter(Widget):
return delta return delta
else: else:
# cannot move particle at all, try again # cannot move particle at all, try again
return self.adjust_move_element(newdelta,element) # give up if tried too many times
if recursion_depth>100:
print("warning: recursion depth exceeded when adjusting move of element at (",element.pos.x,",",element.pos.y,") by delta=(",delta.x,",",delta.y,")",file=sys.stderr)
return Point(0,0)
else:
return self.adjust_move_element(newdelta,element,recursion_depth+1)
# TODO adapt # TODO adapt