check move
This commit is contained in:
parent
a5caeec29a
commit
159ac83e86
58
cross.py
58
cross.py
@ -14,7 +14,6 @@ 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):
|
||||||
@ -46,7 +45,19 @@ class Cross():
|
|||||||
|
|
||||||
# check whether a cross at pos interacts with cross
|
# check whether a cross at pos interacts with cross
|
||||||
def check_interaction(self,pos):
|
def check_interaction(self,pos):
|
||||||
return (pos-self.pos).int()**2>=5
|
# allow for error
|
||||||
|
return int(pos.x-self.pos.x+sgn(pos.x-self.pos.x)*1e-11)**2+int(pos.y-self.pos.y+sgn(pos.y-self.pos.y)*1e-11)**2>=5
|
||||||
|
|
||||||
|
# check whether a cross at position pos is touching self
|
||||||
|
def check_touch(self,pos):
|
||||||
|
rel=pos-self.pos
|
||||||
|
for i in [-3,-2,-1,1,2,3]:
|
||||||
|
# allow for error
|
||||||
|
if abs(rel.x-i)<1e-11 and abs(rel.y)<=4-abs(i)+1e-11 and abs(rel.y)>=3-abs(i)-1e-11:
|
||||||
|
return True
|
||||||
|
if abs(rel.y-i)<1e-11 and abs(rel.x)<=4-abs(i)+1e-11 and abs(rel.x)>=3-abs(i)-1e-11:
|
||||||
|
return True
|
||||||
|
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):
|
||||||
@ -92,7 +103,7 @@ 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
|
# move along edge of cross
|
||||||
def move_along(self,newpos,pos):
|
def move_along(self,newpos,pos):
|
||||||
rel=pos-self.pos
|
rel=pos-self.pos
|
||||||
# check if the particle is stuck in the x direction
|
# check if the particle is stuck in the x direction
|
||||||
@ -220,7 +231,7 @@ class Cross_painter(Widget):
|
|||||||
def on_touch_down(self,touch):
|
def on_touch_down(self,touch):
|
||||||
# create new cross
|
# create new cross
|
||||||
if touch.button=="right":
|
if touch.button=="right":
|
||||||
if self.check_add(Point(touch.x/Cross.size,touch.y/Cross.size)):
|
if self.check_interaction_any(Point(touch.x/Cross.size,touch.y/Cross.size),None):
|
||||||
new=Cross(touch.x/Cross.size,touch.y/Cross.size)
|
new=Cross(touch.x/Cross.size,touch.y/Cross.size)
|
||||||
with self.canvas:
|
with self.canvas:
|
||||||
new.draw()
|
new.draw()
|
||||||
@ -258,30 +269,37 @@ class Cross_painter(Widget):
|
|||||||
# none found
|
# none found
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# check whether a position intersects with any of the crosses
|
||||||
|
def check_interaction_any(self,pos,exception):
|
||||||
|
for other in self.crosses:
|
||||||
|
if other!=exception:
|
||||||
|
if other.check_interaction(pos)==False:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
# check that a cross can move to new position
|
# check that a cross can move to new position
|
||||||
def check_move(self,newpos,cross):
|
def check_move(self,newpos,cross):
|
||||||
|
# whether newpos is acceptable
|
||||||
|
accept_newpos=True
|
||||||
for other in self.crosses:
|
for other in self.crosses:
|
||||||
# do not compare a cross to itself
|
# do not compare a cross to itself
|
||||||
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:
|
||||||
# check if cross is stuck to other
|
accept_newpos=False
|
||||||
if cross.stuckto==other:
|
# check if cross touches other
|
||||||
|
if other.check_touch(cross.pos):
|
||||||
# move along other while remaining stuck
|
# move along other while remaining stuck
|
||||||
return other.move_along(newpos,cross.pos)
|
candidate=other.move_along(newpos,cross.pos)
|
||||||
else:
|
else:
|
||||||
# stick to the cross
|
candidate=other.move_on_line_to_stick(cross.pos,newpos-cross.pos)
|
||||||
cross.stuckto=other
|
if self.check_interaction_any(candidate,cross):
|
||||||
return other.move_on_line_to_stick(cross.pos,newpos-cross.pos)
|
return candidate
|
||||||
# reset stuckto if move is allowed
|
if accept_newpos:
|
||||||
cross.stuckto=None
|
return newpos
|
||||||
return newpos
|
else:
|
||||||
|
# cannot move cross at all, try again
|
||||||
# check that a cross can be added at position
|
return self.check_move(candidate,cross)
|
||||||
def check_add(self,pos):
|
|
||||||
for cross in self.crosses:
|
|
||||||
if cross.check_interaction(pos)==False:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user