Fixes to motion of squares
This commit is contained in:
parent
a7c18641a6
commit
bf365bc725
@ -4,6 +4,7 @@ from kivy.core.window import Window
|
|||||||
|
|
||||||
from point import Point
|
from point import Point
|
||||||
from polyomino import Square
|
from polyomino import Square
|
||||||
|
from polyomino import Square_element
|
||||||
|
|
||||||
# painter class
|
# painter class
|
||||||
class Painter(Widget):
|
class Painter(Widget):
|
||||||
@ -128,6 +129,7 @@ class Painter(Widget):
|
|||||||
if touch.button=="left" and self.modifiers==[] and self.undermouse!=None:
|
if touch.button=="left" and self.modifiers==[] and self.undermouse!=None:
|
||||||
# change in position
|
# change in position
|
||||||
delta=self.check_move(Point(touch.x/Square_element.size,touch.y/Square_element.size)-(self.offset+self.undermouse.squares[0].pos),self.undermouse)
|
delta=self.check_move(Point(touch.x/Square_element.size,touch.y/Square_element.size)-(self.offset+self.undermouse.squares[0].pos),self.undermouse)
|
||||||
|
self.undermouse.move(delta)
|
||||||
# multiple particles
|
# multiple particles
|
||||||
# TODO: group moves
|
# TODO: group moves
|
||||||
#else:
|
#else:
|
||||||
@ -173,7 +175,8 @@ class Painter(Widget):
|
|||||||
# check whether a position intersects with any of the particles
|
# check whether a position intersects with any of the particles
|
||||||
def check_interaction_any(self,candidate,offset):
|
def check_interaction_any(self,candidate,offset):
|
||||||
for particle in self.particles:
|
for particle in self.particles:
|
||||||
if particle.check_interaction(candidate,offset):
|
# do not check interaction if candidate=particle
|
||||||
|
if candidate!=particle and particle.check_interaction(candidate,offset):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -193,7 +196,7 @@ class Painter(Widget):
|
|||||||
# TODO: this assumes other is a square
|
# TODO: this assumes other is a square
|
||||||
newdelta=other.squares[0].move_along(delta,particle.squares[0].pos)
|
newdelta=other.squares[0].move_along(delta,particle.squares[0].pos)
|
||||||
else:
|
else:
|
||||||
newdelta=other.move_on_line_to_stick(particle.squares[0].pos,delta)
|
newdelta=other.squares[0].move_on_line_to_stick(particle.squares[0].pos,delta)
|
||||||
if not self.check_interaction_any(particle,newdelta):
|
if not self.check_interaction_any(particle,newdelta):
|
||||||
return newdelta
|
return newdelta
|
||||||
if accept_newpos:
|
if accept_newpos:
|
||||||
|
57
polyomino.py
57
polyomino.py
@ -39,9 +39,15 @@ class Polyomino():
|
|||||||
*((square.pos.x-0.5)*square.size,(square.pos.y-0.5)*square.size),
|
*((square.pos.x-0.5)*square.size,(square.pos.y-0.5)*square.size),
|
||||||
*((square.pos.x-0.5)*square.size,(square.pos.y+0.5)*square.size),
|
*((square.pos.x-0.5)*square.size,(square.pos.y+0.5)*square.size),
|
||||||
*((square.pos.x+0.5)*square.size,(square.pos.y+0.5)*square.size),
|
*((square.pos.x+0.5)*square.size,(square.pos.y+0.5)*square.size),
|
||||||
*((square.pos.x+0.5)*square.size,(square.pos.y-0.5)*square.size)
|
*((square.pos.x+0.5)*square.size,(square.pos.y-0.5)*square.size),
|
||||||
|
*((square.pos.x-0.5)*square.size,(square.pos.y-0.5)*square.size)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# move by delta
|
||||||
|
def move(self,delta):
|
||||||
|
for square in self.squares:
|
||||||
|
square.pos+=delta
|
||||||
|
|
||||||
# whether x is in the support of the polyomino
|
# whether x is in the support of the polyomino
|
||||||
def in_support(self,x):
|
def in_support(self,x):
|
||||||
for square in self.squares:
|
for square in self.squares:
|
||||||
@ -69,7 +75,7 @@ class Polyomino():
|
|||||||
# square
|
# square
|
||||||
class Square(Polyomino):
|
class Square(Polyomino):
|
||||||
def __init__(self,x,y,**kwargs):
|
def __init__(self,x,y,**kwargs):
|
||||||
super(Square,self).__init__(kwargs,squares=[Square_element(x,y)])
|
super(Square,self).__init__(**kwargs,squares=[Square_element(x,y)])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -94,35 +100,52 @@ class Square_element():
|
|||||||
# check whether a square at position pos is touching self
|
# check whether a square at position pos is touching self
|
||||||
def check_touch(self,pos):
|
def check_touch(self,pos):
|
||||||
# allow for error
|
# allow for error
|
||||||
if in_interval(l_infinity(pos-solf.pos),1-1e-11,1+1e-11):
|
if in_interval(l_infinity(pos-self.pos),1-1e-11,1+1e-11):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# find position along a line that comes in contact with the line going through pos in direction v
|
# find position along a line that comes in contact with the line going through pos in direction v
|
||||||
def move_on_line_to_stick(self,pos,v):
|
def move_on_line_to_stick(self,pos,v):
|
||||||
# compute intersections with four lines making up square
|
# compute intersections with four lines making up square
|
||||||
|
if v.x!=0:
|
||||||
|
if v.y!=0:
|
||||||
intersections=[\
|
intersections=[\
|
||||||
Point(self.pos.x+1/2,pos.y+v.y/v.x*(self.pos.x+1/2-pos.x)),\
|
Point(self.pos.x+1,pos.y+v.y/v.x*(self.pos.x+1-pos.x)),\
|
||||||
Point(self.pos.x-1/2,pos.y+v.y/v.x*(self.pos.x-1/2-pos.x)),\
|
Point(self.pos.x-1,pos.y+v.y/v.x*(self.pos.x-1-pos.x)),\
|
||||||
Point(pos.x+v.x/v.y*(self.pos.y+1/2-pos.y),self.pos.y+1/2),\
|
Point(pos.x+v.x/v.y*(self.pos.y+1-pos.y),self.pos.y+1),\
|
||||||
Point(pos.x+v.x/v.y*(self.pos.y-1/2-pos.y),self.pos.y-1/2)\
|
Point(pos.x+v.x/v.y*(self.pos.y-1-pos.y),self.pos.y-1)\
|
||||||
]
|
]
|
||||||
|
else:
|
||||||
|
intersections=[\
|
||||||
|
Point(self.pos.x+1,pos.y+v.y/v.x*(self.pos.x+1-pos.x)),\
|
||||||
|
Point(self.pos.x-1,pos.y+v.y/v.x*(self.pos.x-1-pos.x))
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
if v.y!=0:
|
||||||
|
intersections=[\
|
||||||
|
Point(pos.x+v.x/v.y*(self.pos.y+1-pos.y),self.pos.y+1),\
|
||||||
|
Point(pos.x+v.x/v.y*(self.pos.y-1-pos.y),self.pos.y-1)\
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
print("error: move_on_line_to_stick called with v=0, please file a bug report with the developer",file=sys.stderr)
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
# compute closest one, on square
|
# compute closest one, on square
|
||||||
closest=None
|
closest=None
|
||||||
dist=math.inf
|
dist=math.inf
|
||||||
for i in range(0,4):
|
for i in range(0,len(intersections)):
|
||||||
# check that it is on square
|
# check that it is on square
|
||||||
if abs(intersections[i].x-self.pos.x)<=1/2+1e-11 and abs(intersections[i].y-self.pos.y)<=1/2+1e-11:
|
if abs(intersections[i].x-self.pos.x)<=1+1e-11 and abs(intersections[i].y-self.pos.y)<=1+1e-11:
|
||||||
if (intersections[i]-pos)**2<dist:
|
if (intersections[i]-pos)**2<dist:
|
||||||
closest=intersections[i]
|
closest=intersections[i]
|
||||||
dist=(intersections[i]-pos)**2
|
dist=(intersections[i]-pos)**2
|
||||||
|
|
||||||
if closest==None:
|
if closest==None:
|
||||||
print("error: cannot move particle at (",pos.x,",",pos.y,") to the boundary of (",self.pos.x,",",self.pos.y,")",file=sys.stderr)
|
print("error: cannot move particle at (",pos.x,",",pos.y,") to the boundary of (",self.pos.x,",",self.pos.y,") in direction (",v.x,",",v.y,")",file=sys.stderr)
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
return closest
|
# return difference to pos
|
||||||
|
return closest-pos
|
||||||
|
|
||||||
# move along edge of square
|
# move along edge of square
|
||||||
def move_along(self,delta,pos):
|
def move_along(self,delta,pos):
|
||||||
@ -153,31 +176,31 @@ class Square_element():
|
|||||||
# move when stuck in the x direction
|
# move when stuck in the x direction
|
||||||
def move_stuck_x(self,delta,pos):
|
def move_stuck_x(self,delta,pos):
|
||||||
# only move in y direction
|
# only move in y direction
|
||||||
candidate=Point(pos.x,pos.x+delta.y)
|
candidate=Point(0,delta.y)
|
||||||
# do not move past corners
|
# do not move past corners
|
||||||
rel=pos.y-self.pos.y
|
rel=pos.y-self.pos.y
|
||||||
if delta.y>0:
|
if delta.y>0:
|
||||||
if rel<math.ceil(rel)-1e-11 and delta.y+rel>math.ceil(rel)+1e-11 and math.ceil(rel)!=0:
|
if rel<math.ceil(rel)-1e-11 and delta.y+rel>math.ceil(rel)+1e-11 and math.ceil(rel)!=0:
|
||||||
# stick to corner
|
# stick to corner
|
||||||
candidate.y=math.ceil(rel)+self.pos.y
|
candidate.y=math.ceil(rel)+self.pos.y-pos.y
|
||||||
else:
|
else:
|
||||||
if rel>math.floor(rel)+1e-11 and delta.y+rel<math.floor(rel)-1e-11 and math.floor(rel)!=0:
|
if rel>math.floor(rel)+1e-11 and delta.y+rel<math.floor(rel)-1e-11 and math.floor(rel)!=0:
|
||||||
# stick to corner
|
# stick to corner
|
||||||
candidate.y=math.floor(rel)+self.pos.y
|
candidate.y=math.floor(rel)+self.pos.y-pos.y
|
||||||
return candidate
|
return candidate
|
||||||
# move when stuck in the y direction
|
# move when stuck in the y direction
|
||||||
def move_stuck_y(self,delta,pos):
|
def move_stuck_y(self,delta,pos):
|
||||||
# onlx move in x direction
|
# onlx move in x direction
|
||||||
candidate=Point(pos.x,newpos.x)
|
candidate=Point(delta.x,0)
|
||||||
# do not move past corners
|
# do not move past corners
|
||||||
rel=pos.x-self.pos.x
|
rel=pos.x-self.pos.x
|
||||||
if delta.x>0:
|
if delta.x>0:
|
||||||
if rel<math.ceil(rel)-1e-11 and delta.x+rel>math.ceil(rel)+1e-11 and math.ceil(rel)!=0:
|
if rel<math.ceil(rel)-1e-11 and delta.x+rel>math.ceil(rel)+1e-11 and math.ceil(rel)!=0:
|
||||||
# stick to corner
|
# stick to corner
|
||||||
candidate.x=math.ceil(rel)+self.pos.x
|
candidate.x=math.ceil(rel)+self.pos.x-pos.x
|
||||||
else:
|
else:
|
||||||
if rel>math.floor(rel)+1e-11 and delta.x+rel<math.floor(rel)-1e-11 and math.floor(rel)!=0:
|
if rel>math.floor(rel)+1e-11 and delta.x+rel<math.floor(rel)-1e-11 and math.floor(rel)!=0:
|
||||||
# stick to corner
|
# stick to corner
|
||||||
candidate.x=math.floor(rel)+self.pos.x
|
candidate.x=math.floor(rel)+self.pos.x-pos.x
|
||||||
return candidate
|
return candidate
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user