move along cross
This commit is contained in:
parent
6851e1ab32
commit
a5caeec29a
96
cross.py
96
cross.py
@ -1,8 +1,10 @@
|
|||||||
import math
|
import math
|
||||||
|
import sys
|
||||||
from kivy.graphics import Color,Line,Rectangle
|
from kivy.graphics import Color,Line,Rectangle
|
||||||
from kivy.uix.widget import Widget
|
from kivy.uix.widget import Widget
|
||||||
|
|
||||||
from point import Point
|
from point import Point
|
||||||
|
from tools import isint_nonzero,sgn
|
||||||
|
|
||||||
class Cross():
|
class Cross():
|
||||||
# size of central square
|
# size of central square
|
||||||
@ -12,6 +14,7 @@ class Cross():
|
|||||||
self.pos=Point(x,y)
|
self.pos=Point(x,y)
|
||||||
self.color=kwargs.get("color",(0,0,1))
|
self.color=kwargs.get("color",(0,0,1))
|
||||||
self.selected=False
|
self.selected=False
|
||||||
|
self.stuckto=None
|
||||||
|
|
||||||
# set position
|
# set position
|
||||||
def setpos(self,x,y):
|
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))
|
closest=self.move_on_line_to_stick_relative(Point(-x.x,x.y),Point(-v.x,v.y))
|
||||||
return Point(-closest.x,closest.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
|
# L_infinity distance rescalled by 3 in the x direction
|
||||||
def cross_distx(x,y):
|
def cross_distx(x,y):
|
||||||
@ -181,8 +265,16 @@ class Cross_painter(Widget):
|
|||||||
if other!=cross:
|
if other!=cross:
|
||||||
# move would make cross overlap with other
|
# move would make cross overlap with other
|
||||||
if other.check_interaction(newpos)==False:
|
if other.check_interaction(newpos)==False:
|
||||||
# stick to the cross
|
# check if cross is stuck to other
|
||||||
return other.move_on_line_to_stick(cross.pos,newpos-cross.pos)
|
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
|
return newpos
|
||||||
|
|
||||||
# check that a cross can be added at position
|
# check that a cross can be added at position
|
||||||
|
Loading…
Reference in New Issue
Block a user