move along cross

This commit is contained in:
Ian Jauslin 2021-09-28 23:36:07 -04:00
parent 6851e1ab32
commit a5caeec29a
2 changed files with 100 additions and 3 deletions

View File

@ -1,8 +1,10 @@
import math
import sys
from kivy.graphics import Color,Line,Rectangle
from kivy.uix.widget import Widget
from point import Point
from tools import isint_nonzero,sgn
class Cross():
# size of central square
@ -12,6 +14,7 @@ class Cross():
self.pos=Point(x,y)
self.color=kwargs.get("color",(0,0,1))
self.selected=False
self.stuckto=None
# set position
def setpos(self,x,y):
@ -89,6 +92,87 @@ class Cross():
closest=self.move_on_line_to_stick_relative(Point(-x.x,x.y),Point(-v.x,v.y))
return Point(-closest.x,closest.y)
# move along edge of cross while remaining stuck
def move_along(self,newpos,pos):
rel=pos-self.pos
# check if the particle is stuck in the x direction
if isint_nonzero(rel.x):
# check y direction
if isint_nonzero(rel.y):
# in corner
# two types of corners: |x|_1=3 or |x|_1=4
if abs(rel.x)+abs(rel.y)<3.5:
if sgn(newpos.y-pos.y)==sgn(rel.y):
# stuck in x direction
return self.move_stuck_x(newpos,pos)
elif sgn(newpos.x-pos.x)==sgn(rel.x):
# stuck in y direction
return self.move_stuck_y(newpos,pos)
else:
if sgn(newpos.y-pos.y)==-sgn(rel.y):
# stuck in x direction
return self.move_stuck_x(newpos,pos)
elif sgn(newpos.x-pos.x)==-sgn(rel.x):
# stuck in y direction
return self.move_stuck_y(newpos,pos)
# stuck in both directions
return pos
else:
# stuck in x direction
return self.move_stuck_x(newpos,pos)
elif isint_nonzero(rel.y):
# stuck in y direction
return self.move_stuck_y(newpos,pos)
# this should never happen
else:
print("error: stuck particle has non-integer relative position: (",rel.x,",",rel.y,")",file=sys.stderr)
exit(-1)
# move when stuck in the x direction
def move_stuck_x(self,newpos,pos):
# only move in y direction
candidate=Point(pos.x,newpos.y)
# do not move past corners
rel=pos.y-self.pos.y
newrel=newpos.y-self.pos.y
if newpos.y>pos.y:
if self.check_interaction(candidate)==False or (rel<math.ceil(rel)-1e-11 and newrel>math.ceil(rel)+1e-11 and math.ceil(rel)!=0):
# in open corner
if rel>math.ceil(rel)-1e-11:
candidate.y=math.ceil(rel)+1+self.pos.y
else:
candidate.y=math.ceil(rel)+self.pos.y
else:
if self.check_interaction(candidate)==False or (rel>math.floor(rel)+1e-11 and newrel<math.floor(rel)-1e-11 and math.floor(rel)!=0):
# in open corner
if rel<math.floor(rel)+1e-11:
candidate.y=math.floor(rel)-1+self.pos.y
else:
candidate.y=math.floor(rel)+self.pos.y
return candidate
# move when stuck in the y direction
def move_stuck_y(self,newpos,pos):
# only move in x direction
candidate=Point(newpos.x,pos.y)
# do not move past corners
rel=pos.x-self.pos.x
newrel=newpos.x-self.pos.x
if newpos.x>pos.x:
if self.check_interaction(candidate)==False or (rel<math.ceil(rel)-1e-11 and newrel>math.ceil(rel)+1e-11 and math.ceil(rel)!=0):
# in open corner
if rel>math.ceil(rel)-1e-11:
candidate.x=math.ceil(rel)+1+self.pos.x
else:
candidate.x=math.ceil(rel)+self.pos.x
else:
if self.check_interaction(candidate)==False or (rel>math.floor(rel)+1e-11 and newrel<math.floor(rel)-1e-11 and math.floor(rel)!=0):
# in open corner
if rel<math.floor(rel)+1e-11:
candidate.x=math.floor(rel)-1+self.pos.x
else:
candidate.x=math.floor(rel)+self.pos.x
return candidate
# L_infinity distance rescalled by 3 in the x direction
def cross_distx(x,y):
@ -181,8 +265,16 @@ class Cross_painter(Widget):
if other!=cross:
# move would make cross overlap with other
if other.check_interaction(newpos)==False:
# check if cross is stuck to other
if cross.stuckto==other:
# move along other while remaining stuck
return other.move_along(newpos,cross.pos)
else:
# stick to the cross
cross.stuckto=other
return other.move_on_line_to_stick(cross.pos,newpos-cross.pos)
# reset stuckto if move is allowed
cross.stuckto=None
return newpos
# check that a cross can be added at position

View File

@ -1,6 +1,11 @@
# sign function
def sgn(x):
if x>=0:
return 1
return -1
# check whether a number is an integer (with tolerance)
def isint_nonzero(x):
if abs(x)<1e-11:
return False
return abs(round(x)-x)<1e-11