Split element into their own file
This commit is contained in:
parent
5835c9003c
commit
c09600cd10
164
src/element.py
Normal file
164
src/element.py
Normal file
@ -0,0 +1,164 @@
|
||||
## elements that polyominoes are made of
|
||||
import math
|
||||
import sys
|
||||
|
||||
from point import Point,l_infinity
|
||||
from tools import isint_nonzero,sgn,in_interval
|
||||
|
||||
# parent class of all elements
|
||||
class Element():
|
||||
def __init__(self,x,y,size,**kwargs):
|
||||
self.pos=Point(x,y)
|
||||
self.size=size
|
||||
|
||||
# set position
|
||||
def setpos(self,x,y):
|
||||
self.pos.x=x
|
||||
self.pos.y=y
|
||||
|
||||
|
||||
# override in each subclass
|
||||
# check whether an element interacts with square
|
||||
def check_interaction(self,element):
|
||||
return False
|
||||
|
||||
# override in each subclass
|
||||
# whether x is in the support of the element
|
||||
def in_support(self,x):
|
||||
return False
|
||||
|
||||
# override in each subclass
|
||||
# check whether an element is touching self
|
||||
def check_touch(self,element):
|
||||
return False
|
||||
|
||||
# override in each subclass
|
||||
# find position along a line that comes in contact with the line going through element.pos in direction v
|
||||
def move_on_line_to_stick(self,element,v):
|
||||
return Point(0,0)
|
||||
|
||||
# override in each subclass
|
||||
# move along edge of element
|
||||
def move_along(self,delta,element):
|
||||
return element
|
||||
|
||||
|
||||
# square elements
|
||||
class Element_square(Element):
|
||||
|
||||
# check whether an element interacts with square
|
||||
def check_interaction(self,element):
|
||||
# allow for error
|
||||
return l_infinity(element.pos-self.pos)<(self.size+element.size)/2-1e-11
|
||||
|
||||
# whether x is in the support of the element
|
||||
def in_support(self,x):
|
||||
return l_infinity(self.pos-x)<=1/2
|
||||
|
||||
# check whether an element is touching self
|
||||
def check_touch(self,element):
|
||||
# allow for error
|
||||
if in_interval(l_infinity(element.pos-self.pos),(self.size+element.size)/2-1e-11,(self.size+element.size)/2+1e-11):
|
||||
return True
|
||||
return False
|
||||
|
||||
# find position along a line that comes in contact with the line going through element.pos in direction v
|
||||
def move_on_line_to_stick(self,element,v):
|
||||
# compute intersections with four lines making up square
|
||||
if v.x!=0:
|
||||
if v.y!=0:
|
||||
intersections=[\
|
||||
Point(self.pos.x+(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x+(self.size+element.size)/2-element.pos.x)),\
|
||||
Point(self.pos.x-(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x-(self.size+element.size)/2-element.pos.x)),\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y+(self.size+element.size)/2-element.pos.y),self.pos.y+(self.size+element.size)/2),\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y-(self.size+element.size)/2-element.pos.y),self.pos.y-(self.size+element.size)/2)\
|
||||
]
|
||||
else:
|
||||
intersections=[\
|
||||
Point(self.pos.x+(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x+(self.size+element.size)/2-element.pos.x)),\
|
||||
Point(self.pos.x-(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x-(self.size+element.size)/2-element.pos.x))
|
||||
]
|
||||
else:
|
||||
if v.y!=0:
|
||||
intersections=[\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y+(self.size+element.size)/2-element.pos.y),self.pos.y+(self.size+element.size)/2),\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y-(self.size+element.size)/2-element.pos.y),self.pos.y-(self.size+element.size)/2)\
|
||||
]
|
||||
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
|
||||
closest=None
|
||||
dist=math.inf
|
||||
for i in range(0,len(intersections)):
|
||||
# check that it is on square
|
||||
if abs(intersections[i].x-self.pos.x)<=(self.size+element.size)/2+1e-11 and abs(intersections[i].y-self.pos.y)<=(self.size+element.size)/2+1e-11:
|
||||
if (intersections[i]-element.pos)**2<dist:
|
||||
closest=intersections[i]
|
||||
dist=(intersections[i]-element.pos)**2
|
||||
|
||||
if closest==None:
|
||||
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)
|
||||
|
||||
# return difference to pos
|
||||
return closest-element.pos
|
||||
|
||||
# move along edge of square
|
||||
def move_along(self,delta,element):
|
||||
rel=element.pos-self.pos
|
||||
# check if the particle is stuck in the x direction
|
||||
if isint_nonzero(rel.x/((self.size+element.size)/2)):
|
||||
# check y direction
|
||||
if isint_nonzero(rel.y/((self.size+element.size)/2)):
|
||||
# in corner
|
||||
if sgn(delta.y)==-sgn(rel.y):
|
||||
# stuck in x direction
|
||||
return self.move_stuck_x(delta,element)
|
||||
elif sgn(delta.x)==-sgn(rel.x):
|
||||
# stuck in y direction
|
||||
return self.move_stuck_y(delta,element)
|
||||
# stuck in both directions
|
||||
return element.pos
|
||||
else:
|
||||
# stuck in x direction
|
||||
return self.move_stuck_x(delta,element)
|
||||
elif isint_nonzero(rel.y/((self.size+element.size)/2)):
|
||||
# stuck in y direction
|
||||
return self.move_stuck_y(delta,element)
|
||||
# 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,delta,element):
|
||||
# only move in y direction
|
||||
candidate=Point(0,delta.y)
|
||||
# do not move past corners
|
||||
rel=element.pos.y-self.pos.y
|
||||
if delta.y>0:
|
||||
if rel<math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and delta.y+rel>math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.y=math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.y-element.pos.y
|
||||
else:
|
||||
if rel>math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and delta.y+rel<math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.y=math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.y-element.pos.y
|
||||
return candidate
|
||||
# move when stuck in the y direction
|
||||
def move_stuck_y(self,delta,element):
|
||||
# onlx move in x direction
|
||||
candidate=Point(delta.x,0)
|
||||
# do not move past corners
|
||||
rel=element.pos.x-self.pos.x
|
||||
if delta.x>0:
|
||||
if rel<math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and delta.x+rel>math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.x=math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.x-element.pos.x
|
||||
else:
|
||||
if rel>math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and delta.x+rel<math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.x=math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.x-element.pos.x
|
||||
return candidate
|
||||
|
@ -6,7 +6,6 @@ from kivy.graphics import Color,Line
|
||||
|
||||
from point import Point
|
||||
from polyomino import Cross
|
||||
from polyomino import Square_element
|
||||
|
||||
from tools import remove_fromlist
|
||||
|
||||
@ -71,7 +70,7 @@ class Painter(Widget):
|
||||
|
||||
# snap all existing particles to grid
|
||||
for particle in self.particles:
|
||||
delta=self.lattice.nearest_delta(particle.squares[0].pos)
|
||||
delta=self.lattice.nearest_delta(particle.elements[0].pos)
|
||||
if not self.check_interaction_any(particle,delta):
|
||||
particle.move(delta)
|
||||
|
||||
@ -104,7 +103,7 @@ class Painter(Widget):
|
||||
# draw grids
|
||||
for particle in self.particles:
|
||||
if particle.grid>0:
|
||||
self.draw_grid(particle.squares[0].pos,particle.grid)
|
||||
self.draw_grid(particle.elements[0].pos,particle.grid)
|
||||
|
||||
for particle in self.particles:
|
||||
particle.draw(self,alpha=0.5)
|
||||
@ -217,7 +216,7 @@ class Painter(Widget):
|
||||
new=Cross(touchx,touchy)
|
||||
# snap to lattice
|
||||
if self.lattice!=None:
|
||||
new.move(self.lattice.nearest_delta(new.squares[0].pos))
|
||||
new.move(self.lattice.nearest_delta(new.elements[0].pos))
|
||||
|
||||
if not self.check_interaction_any(new,Point(0,0)):
|
||||
# add to list
|
||||
@ -238,7 +237,7 @@ class Painter(Widget):
|
||||
|
||||
# record relative position of click with respect to reference
|
||||
if self.undermouse!=None:
|
||||
self.offset=Point(touchx,touchy)-self.undermouse.squares[0].pos
|
||||
self.offset=Point(touchx,touchy)-self.undermouse.elements[0].pos
|
||||
|
||||
# no modifiers
|
||||
if self.modifiers==[]:
|
||||
@ -291,7 +290,7 @@ class Painter(Widget):
|
||||
# only move on left click
|
||||
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
|
||||
delta=self.adjust_move(Point(touchx,touchy)-(self.offset+self.undermouse.squares[0].pos),0)
|
||||
delta=self.adjust_move(Point(touchx,touchy)-(self.offset+self.undermouse.elements[0].pos),0)
|
||||
|
||||
# snap to lattice
|
||||
if self.lattice!=None:
|
||||
@ -347,10 +346,10 @@ class Painter(Widget):
|
||||
# check whether a candidate particle element with any of the unselected particles
|
||||
def check_interaction_unselected_element(self,element,offset):
|
||||
for particle in self.unselected:
|
||||
for square in particle.squares:
|
||||
for elt in particle.elements:
|
||||
# add offset
|
||||
element.pos+=offset
|
||||
if square.check_interaction(element):
|
||||
if elt.check_interaction(element):
|
||||
# reset offset
|
||||
element.pos-=offset
|
||||
return True
|
||||
@ -365,7 +364,7 @@ class Painter(Widget):
|
||||
# actual_delta is the smallest (componentwise) of all the computed delta's
|
||||
actual_delta=Point(math.inf,math.inf)
|
||||
for particle in self.selected:
|
||||
for element in particle.squares:
|
||||
for element in particle.elements:
|
||||
# compute adjustment move due to unselected obstacles
|
||||
adjusted_delta=self.adjust_move_element(delta,element,0)
|
||||
# only keep the smallest delta's (in absolute value)
|
||||
@ -391,7 +390,7 @@ class Painter(Widget):
|
||||
# whether newpos is acceptable
|
||||
accept_newpos=True
|
||||
for other in self.unselected:
|
||||
for obstacle in other.squares:
|
||||
for obstacle in other.elements:
|
||||
# move would make element overlap with obstacle
|
||||
element.pos+=delta
|
||||
if obstacle.check_interaction(element):
|
||||
@ -448,7 +447,7 @@ class Painter(Widget):
|
||||
for particle in self.particles:
|
||||
if type(particle)==Cross:
|
||||
ff.write("{:d};".format(CROSS_INDEX))
|
||||
ff.write("{:05.2f},{:05.2f};{:3.1f},{:3.1f},{:3.1f}\n".format(particle.squares[0].pos.x,particle.squares[0].pos.y,particle.color[0],particle.color[1],particle.color[2]))
|
||||
ff.write("{:05.2f},{:05.2f};{:3.1f},{:3.1f},{:3.1f}\n".format(particle.elements[0].pos.x,particle.elements[0].pos.y,particle.color[0],particle.color[1],particle.color[2]))
|
||||
ff.close()
|
||||
|
||||
# read configuration from file
|
||||
@ -561,7 +560,7 @@ class Painter(Widget):
|
||||
for particle in self.particles:
|
||||
if type(particle)==Cross:
|
||||
ff.write("\cross{"+colors.closest_color(particle.color,colors.xcolor_names)+"}")
|
||||
ff.write("{{({:05.2f},{:05.2f})}};\n".format(particle.squares[0].pos.x-self.particles[0].squares[0].pos.x,particle.squares[0].pos.y-self.particles[0].squares[0].pos.y))
|
||||
ff.write("{{({:05.2f},{:05.2f})}};\n".format(particle.elements[0].pos.x-self.particles[0].elements[0].pos.x,particle.elements[0].pos.y-self.particles[0].elements[0].pos.y))
|
||||
|
||||
ff.write("\\end{tikzpicture}\n")
|
||||
ff.write("\\end{document}\n")
|
||||
|
194
src/polyomino.py
194
src/polyomino.py
@ -1,15 +1,14 @@
|
||||
import math
|
||||
import sys
|
||||
# a polyomino is a collection of elements, defined in elements.py
|
||||
from kivy.graphics import Color,Line,Rectangle
|
||||
|
||||
from point import Point,l_infinity
|
||||
from tools import isint_nonzero,sgn,in_interval
|
||||
from point import l_infinity
|
||||
from element import Element_square
|
||||
|
||||
# parent class of all polyominos
|
||||
class Polyomino():
|
||||
def __init__(self,**kwargs):
|
||||
# square elements that make up the polyomino
|
||||
self.squares=kwargs.get("squares",[])
|
||||
# elements that make up the polyomino
|
||||
self.elements=kwargs.get("elements",[])
|
||||
|
||||
self.color=kwargs.get("color",(0,0,1))
|
||||
self.selected=False
|
||||
@ -28,8 +27,8 @@ class Polyomino():
|
||||
# darken selected
|
||||
Color(r/2,g/2,b/2,alpha)
|
||||
|
||||
for square in self.squares:
|
||||
Rectangle(pos=(painter.pos_tocoord_x(square.pos.x-0.5*square.size),painter.pos_tocoord_y(square.pos.y-0.5*square.size)),size=(square.size*painter.base_size,square.size*painter.base_size))
|
||||
for element in self.elements:
|
||||
Rectangle(pos=(painter.pos_tocoord_x(element.pos.x-0.5*element.size),painter.pos_tocoord_y(element.pos.y-0.5*element.size)),size=(element.size*painter.base_size,element.size*painter.base_size))
|
||||
|
||||
# draw boundary
|
||||
self.stroke(painter)
|
||||
@ -42,62 +41,62 @@ class Polyomino():
|
||||
|
||||
# white
|
||||
Color(1,1,1)
|
||||
for square in self.squares:
|
||||
for element in self.elements:
|
||||
Line(points=(
|
||||
*(coordx-0.5*square.size*painter.base_size,coordy-0.5*square.size*painter.base_size),
|
||||
*(coordx-0.5*square.size*painter.base_size,coordy+0.5*square.size*painter.base_size),
|
||||
*(coordx+0.5*square.size*painter.base_size,coordy+0.5*square.size*painter.base_size),
|
||||
*(coordx+0.5*square.size*painter.base_size,coordy-0.5*square.size*painter.base_size),
|
||||
*(coordx-0.5*square.size*painter.base_size,coordy-0.5*square.size*painter.base_size)
|
||||
*(coordx-0.5*element.size*painter.base_size,coordy-0.5*element.size*painter.base_size),
|
||||
*(coordx-0.5*element.size*painter.base_size,coordy+0.5*element.size*painter.base_size),
|
||||
*(coordx+0.5*element.size*painter.base_size,coordy+0.5*element.size*painter.base_size),
|
||||
*(coordx+0.5*element.size*painter.base_size,coordy-0.5*element.size*painter.base_size),
|
||||
*(coordx-0.5*element.size*painter.base_size,coordy-0.5*element.size*painter.base_size)
|
||||
))
|
||||
|
||||
# move by delta
|
||||
def move(self,delta):
|
||||
for square in self.squares:
|
||||
square.pos+=delta
|
||||
for element in self.elements:
|
||||
element.pos+=delta
|
||||
|
||||
# whether x is in the support of the polyomino
|
||||
def in_support(self,x):
|
||||
for square in self.squares:
|
||||
if l_infinity(square.pos-x)<=1/2:
|
||||
for element in self.elements:
|
||||
if element.in_support(x):
|
||||
return True
|
||||
return False
|
||||
|
||||
# check whether self interacts with candidate if candidate were moved by offset
|
||||
def check_interaction(self,candidate,offset):
|
||||
for square1 in self.squares:
|
||||
for square2 in candidate.squares:
|
||||
for element1 in self.elements:
|
||||
for element2 in candidate.elements:
|
||||
# add offset
|
||||
square2.pos+=offset
|
||||
if square1.check_interaction(square2):
|
||||
element2.pos+=offset
|
||||
if element1.check_interaction(element2):
|
||||
# reset offset
|
||||
square2.pos-=offset
|
||||
element2.pos-=offset
|
||||
return True
|
||||
# reset offset
|
||||
square2.pos-=offset
|
||||
element2.pos-=offset
|
||||
return False
|
||||
|
||||
# square
|
||||
class Square(Polyomino):
|
||||
def __init__(self,x,y,**kwargs):
|
||||
super(Square,self).__init__(**kwargs,squares=[Square_element(x,y,size=kwargs.get("size",1.0))])
|
||||
super(Square,self).__init__(**kwargs,elements=[Element_square(x,y,size=kwargs.get("size",1.0))])
|
||||
|
||||
# cross
|
||||
class Cross(Polyomino):
|
||||
def __init__(self,x,y,**kwargs):
|
||||
super(Cross,self).__init__(**kwargs,squares=[\
|
||||
Square_element(x,y,1),\
|
||||
Square_element(x+1,y,1),\
|
||||
Square_element(x-1,y,1),\
|
||||
Square_element(x,y+1,1),\
|
||||
Square_element(x,y-1,1)\
|
||||
super(Cross,self).__init__(**kwargs,elements=[\
|
||||
Element_square(x,y,1),\
|
||||
Element_square(x+1,y,1),\
|
||||
Element_square(x-1,y,1),\
|
||||
Element_square(x,y+1,1),\
|
||||
Element_square(x,y-1,1)\
|
||||
])
|
||||
|
||||
# redefine stroke to avoid lines between touching squares
|
||||
# redefine stroke to avoid lines between touching elements
|
||||
def stroke(self,painter):
|
||||
# convert to graphical coordinates
|
||||
coordx=painter.pos_tocoord_x(self.squares[0].pos.x)
|
||||
coordy=painter.pos_tocoord_y(self.squares[0].pos.y)
|
||||
coordx=painter.pos_tocoord_x(self.elements[0].pos.x)
|
||||
coordy=painter.pos_tocoord_y(self.elements[0].pos.y)
|
||||
|
||||
Color(1,1,1)
|
||||
Line(points=(
|
||||
@ -116,130 +115,3 @@ class Cross(Polyomino):
|
||||
*(coordx-0.5*painter.base_size,coordy-0.5*painter.base_size),
|
||||
))
|
||||
|
||||
|
||||
|
||||
# square building block of polyominos
|
||||
class Square_element():
|
||||
|
||||
def __init__(self,x,y,size,**kwargs):
|
||||
self.pos=Point(x,y)
|
||||
self.size=size
|
||||
|
||||
# set position
|
||||
def setpos(self,x,y):
|
||||
self.pos.x=x
|
||||
self.pos.y=y
|
||||
|
||||
|
||||
# check whether an element interacts with square
|
||||
def check_interaction(self,element):
|
||||
# allow for error
|
||||
return l_infinity(element.pos-self.pos)<(self.size+element.size)/2-1e-11
|
||||
|
||||
# check whether an element is touching self
|
||||
def check_touch(self,element):
|
||||
# allow for error
|
||||
if in_interval(l_infinity(element.pos-self.pos),(self.size+element.size)/2-1e-11,(self.size+element.size)/2+1e-11):
|
||||
return True
|
||||
return False
|
||||
|
||||
# find position along a line that comes in contact with the line going through element.pos in direction v
|
||||
def move_on_line_to_stick(self,element,v):
|
||||
# compute intersections with four lines making up square
|
||||
if v.x!=0:
|
||||
if v.y!=0:
|
||||
intersections=[\
|
||||
Point(self.pos.x+(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x+(self.size+element.size)/2-element.pos.x)),\
|
||||
Point(self.pos.x-(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x-(self.size+element.size)/2-element.pos.x)),\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y+(self.size+element.size)/2-element.pos.y),self.pos.y+(self.size+element.size)/2),\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y-(self.size+element.size)/2-element.pos.y),self.pos.y-(self.size+element.size)/2)\
|
||||
]
|
||||
else:
|
||||
intersections=[\
|
||||
Point(self.pos.x+(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x+(self.size+element.size)/2-element.pos.x)),\
|
||||
Point(self.pos.x-(self.size+element.size)/2,element.pos.y+v.y/v.x*(self.pos.x-(self.size+element.size)/2-element.pos.x))
|
||||
]
|
||||
else:
|
||||
if v.y!=0:
|
||||
intersections=[\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y+(self.size+element.size)/2-element.pos.y),self.pos.y+(self.size+element.size)/2),\
|
||||
Point(element.pos.x+v.x/v.y*(self.pos.y-(self.size+element.size)/2-element.pos.y),self.pos.y-(self.size+element.size)/2)\
|
||||
]
|
||||
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
|
||||
closest=None
|
||||
dist=math.inf
|
||||
for i in range(0,len(intersections)):
|
||||
# check that it is on square
|
||||
if abs(intersections[i].x-self.pos.x)<=(self.size+element.size)/2+1e-11 and abs(intersections[i].y-self.pos.y)<=(self.size+element.size)/2+1e-11:
|
||||
if (intersections[i]-element.pos)**2<dist:
|
||||
closest=intersections[i]
|
||||
dist=(intersections[i]-element.pos)**2
|
||||
|
||||
if closest==None:
|
||||
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)
|
||||
|
||||
# return difference to pos
|
||||
return closest-element.pos
|
||||
|
||||
# move along edge of square
|
||||
def move_along(self,delta,element):
|
||||
rel=element.pos-self.pos
|
||||
# check if the particle is stuck in the x direction
|
||||
if isint_nonzero(rel.x/((self.size+element.size)/2)):
|
||||
# check y direction
|
||||
if isint_nonzero(rel.y/((self.size+element.size)/2)):
|
||||
# in corner
|
||||
if sgn(delta.y)==-sgn(rel.y):
|
||||
# stuck in x direction
|
||||
return self.move_stuck_x(delta,element)
|
||||
elif sgn(delta.x)==-sgn(rel.x):
|
||||
# stuck in y direction
|
||||
return self.move_stuck_y(delta,element)
|
||||
# stuck in both directions
|
||||
return element.pos
|
||||
else:
|
||||
# stuck in x direction
|
||||
return self.move_stuck_x(delta,element)
|
||||
elif isint_nonzero(rel.y/((self.size+element.size)/2)):
|
||||
# stuck in y direction
|
||||
return self.move_stuck_y(delta,element)
|
||||
# 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,delta,element):
|
||||
# only move in y direction
|
||||
candidate=Point(0,delta.y)
|
||||
# do not move past corners
|
||||
rel=element.pos.y-self.pos.y
|
||||
if delta.y>0:
|
||||
if rel<math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and delta.y+rel>math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.y=math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.y-element.pos.y
|
||||
else:
|
||||
if rel>math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and delta.y+rel<math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.y=math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.y-element.pos.y
|
||||
return candidate
|
||||
# move when stuck in the y direction
|
||||
def move_stuck_y(self,delta,element):
|
||||
# onlx move in x direction
|
||||
candidate=Point(delta.x,0)
|
||||
# do not move past corners
|
||||
rel=element.pos.x-self.pos.x
|
||||
if delta.x>0:
|
||||
if rel<math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and delta.x+rel>math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.x=math.ceil(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.x-element.pos.x
|
||||
else:
|
||||
if rel>math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+1e-11 and delta.x+rel<math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)-1e-11 and math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)!=0:
|
||||
# stick to corner
|
||||
candidate.x=math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.x-element.pos.x
|
||||
return candidate
|
||||
|
||||
|
@ -45,9 +45,9 @@ class Status_bar(Label):
|
||||
spaces=int(self.width/self.char_width)-len(self.raw_text)-13
|
||||
if spaces>0:
|
||||
if self.app.painter.reference==None:
|
||||
self.raw_text+=" "*spaces+"({:05.2f},{:05.2f})\n".format(self.app.painter.selected[0].squares[0].pos.x,self.app.painter.selected[0].squares[0].pos.y)
|
||||
self.raw_text+=" "*spaces+"({:05.2f},{:05.2f})\n".format(self.app.painter.selected[0].elements[0].pos.x,self.app.painter.selected[0].elements[0].pos.y)
|
||||
else:
|
||||
self.raw_text+=" "*spaces+"({:05.2f},{:05.2f})\n".format(self.app.painter.selected[0].squares[0].pos.x-self.app.painter.reference.squares[0].pos.x,self.app.painter.selected[0].squares[0].pos.y-self.app.painter.reference.squares[0].pos.y)
|
||||
self.raw_text+=" "*spaces+"({:05.2f},{:05.2f})\n".format(self.app.painter.selected[0].elements[0].pos.x-self.app.painter.reference.elements[0].pos.x,self.app.painter.selected[0].elements[0].pos.y-self.app.painter.reference.elements[0].pos.y)
|
||||
|
||||
# do not wrap
|
||||
self.text=self.raw_text[:min(len(self.raw_text),int(self.width/self.char_width))]
|
||||
|
Loading…
Reference in New Issue
Block a user