move Square_element.size to painter, and allow for squares to determine their own size

This commit is contained in:
Ian Jauslin 2022-09-23 19:33:05 -04:00
parent fba87c564a
commit b9be36b4e0
2 changed files with 58 additions and 56 deletions

View File

@ -43,6 +43,9 @@ class Painter(Widget):
# modifiers
self.modifiers=[]
# base size for all particles
self.base_size=50
# init Widget
super(Painter,self).__init__(**kwargs)
@ -75,13 +78,13 @@ class Painter(Widget):
# convert logical coordinates (normalized and centered) to the ones that are plotted
def pos_tocoord_x(self,x):
return self.width/2+x*Square_element.size
return self.width/2+x*self.base_size
def pos_tocoord_y(self,y):
return self.height/2+y*Square_element.size
return self.height/2+y*self.base_size
def coord_topos_x(self,x):
return (x-self.width/2)/Square_element.size
return (x-self.width/2)/self.base_size
def coord_topos_y(self,y):
return (y-self.height/2)/Square_element.size
return (y-self.height/2)/self.base_size
@ -176,10 +179,10 @@ class Painter(Widget):
# zoom
elif text=="+":
# increment by 10%
self.set_zoom(Square_element.size/50*1.1)
self.set_zoom(self.base_size/50*1.1)
elif text=="-":
# decrease by 10%
self.set_zoom(Square_element.size/50*0.9)
self.set_zoom(self.base_size/50*0.9)
elif text=="=":
# reset
self.set_zoom(1)
@ -557,7 +560,7 @@ class Painter(Widget):
# set zoom level
def set_zoom(self,level):
Square_element.size=level*50
self.base_size=level*50
self.draw()

View File

@ -29,7 +29,7 @@ class Polyomino():
Color(r/2,g/2,b/2,alpha)
for square in self.squares:
Rectangle(pos=(painter.pos_tocoord_x(square.pos.x-0.5),painter.pos_tocoord_y(square.pos.y-0.5)),size=(square.size,square.size))
Rectangle(pos=(painter.pos_tocoord_x(square.pos.x-0.5),painter.pos_tocoord_y(square.pos.y-0.5)),size=(square.size*painter.base_size,square.size*painter.base_size))
# draw boundary
self.stroke(painter)
@ -44,11 +44,11 @@ class Polyomino():
Color(1,1,1)
for square in self.squares:
Line(points=(
*(coordx-0.5*square.size,coordy-0.5*square.size),
*(coordx-0.5*square.size,coordy+0.5*square.size),
*(coordx+0.5*square.size,coordy+0.5*square.size),
*(coordx+0.5*square.size,coordy-0.5*square.size),
*(coordx-0.5*square.size,coordy-0.5*square.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*square.size*painter.base_size,coordy-0.5*square.size*painter.base_size)
))
# move by delta
@ -74,17 +74,17 @@ class Polyomino():
# square
class Square(Polyomino):
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,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),\
Square_element(x+1,y),\
Square_element(x-1,y),\
Square_element(x,y+1),\
Square_element(x,y-1)\
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)\
])
# redefine stroke to avoid lines between touching squares
@ -95,30 +95,29 @@ class Cross(Polyomino):
Color(1,1,1)
Line(points=(
*(coordx-0.5*Square_element.size,coordy-0.5*Square_element.size),
*(coordx-0.5*Square_element.size,coordy-1.5*Square_element.size),
*(coordx+0.5*Square_element.size,coordy-1.5*Square_element.size),
*(coordx+0.5*Square_element.size,coordy-0.5*Square_element.size),
*(coordx+1.5*Square_element.size,coordy-0.5*Square_element.size),
*(coordx+1.5*Square_element.size,coordy+0.5*Square_element.size),
*(coordx+0.5*Square_element.size,coordy+0.5*Square_element.size),
*(coordx+0.5*Square_element.size,coordy+1.5*Square_element.size),
*(coordx-0.5*Square_element.size,coordy+1.5*Square_element.size),
*(coordx-0.5*Square_element.size,coordy+0.5*Square_element.size),
*(coordx-1.5*Square_element.size,coordy+0.5*Square_element.size),
*(coordx-1.5*Square_element.size,coordy-0.5*Square_element.size),
*(coordx-0.5*Square_element.size,coordy-0.5*Square_element.size),
*(coordx-0.5*painter.base_size,coordy-0.5*painter.base_size),
*(coordx-0.5*painter.base_size,coordy-1.5*painter.base_size),
*(coordx+0.5*painter.base_size,coordy-1.5*painter.base_size),
*(coordx+0.5*painter.base_size,coordy-0.5*painter.base_size),
*(coordx+1.5*painter.base_size,coordy-0.5*painter.base_size),
*(coordx+1.5*painter.base_size,coordy+0.5*painter.base_size),
*(coordx+0.5*painter.base_size,coordy+0.5*painter.base_size),
*(coordx+0.5*painter.base_size,coordy+1.5*painter.base_size),
*(coordx-0.5*painter.base_size,coordy+1.5*painter.base_size),
*(coordx-0.5*painter.base_size,coordy+0.5*painter.base_size),
*(coordx-1.5*painter.base_size,coordy+0.5*painter.base_size),
*(coordx-1.5*painter.base_size,coordy-0.5*painter.base_size),
*(coordx-0.5*painter.base_size,coordy-0.5*painter.base_size),
))
# square building block of polyominos
class Square_element():
# size
size=50
def __init__(self,x,y,**kwargs):
def __init__(self,x,y,size,**kwargs):
self.pos=Point(x,y)
self.size=size
# set position
def setpos(self,x,y):
@ -128,12 +127,12 @@ class Square_element():
# check whether a square at pos interacts with square
def check_interaction(self,pos):
return l_infinity(pos-self.pos)<1
return l_infinity(pos-self.pos)<self.size
# check whether a square at position pos is touching self
def check_touch(self,pos):
# allow for error
if in_interval(l_infinity(pos-self.pos),1-1e-11,1+1e-11):
if in_interval(l_infinity(pos-self.pos),self.size-1e-11,self.size+1e-11):
return True
return False
@ -143,21 +142,21 @@ class Square_element():
if v.x!=0:
if v.y!=0:
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)),\
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)\
Point(self.pos.x+self.size,pos.y+v.y/v.x*(self.pos.x+self.size-pos.x)),\
Point(self.pos.x-self.size,pos.y+v.y/v.x*(self.pos.x-self.size-pos.x)),\
Point(pos.x+v.x/v.y*(self.pos.y+self.size-pos.y),self.pos.y+self.size),\
Point(pos.x+v.x/v.y*(self.pos.y-self.size-pos.y),self.pos.y-self.size)\
]
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))
Point(self.pos.x+self.size,pos.y+v.y/v.x*(self.pos.x+self.size-pos.x)),\
Point(self.pos.x-self.size,pos.y+v.y/v.x*(self.pos.x-self.size-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)\
Point(pos.x+v.x/v.y*(self.pos.y+self.size-pos.y),self.pos.y+self.size),\
Point(pos.x+v.x/v.y*(self.pos.y-self.size-pos.y),self.pos.y-self.size)\
]
else:
print("error: move_on_line_to_stick called with v=0, please file a bug report with the developer",file=sys.stderr)
@ -168,7 +167,7 @@ class Square_element():
dist=math.inf
for i in range(0,len(intersections)):
# check that it is on square
if abs(intersections[i].x-self.pos.x)<=1+1e-11 and abs(intersections[i].y-self.pos.y)<=1+1e-11:
if abs(intersections[i].x-self.pos.x)<=self.size+1e-11 and abs(intersections[i].y-self.pos.y)<=self.size+1e-11:
if (intersections[i]-pos)**2<dist:
closest=intersections[i]
dist=(intersections[i]-pos)**2
@ -184,9 +183,9 @@ class Square_element():
def move_along(self,delta,pos):
rel=pos-self.pos
# check if the particle is stuck in the x direction
if isint_nonzero(rel.x):
if isint_nonzero(rel.x/self.size):
# check y direction
if isint_nonzero(rel.y):
if isint_nonzero(rel.y/self.size):
# in corner
if sgn(delta.y)==-sgn(rel.y):
# stuck in x direction
@ -199,7 +198,7 @@ class Square_element():
else:
# stuck in x direction
return self.move_stuck_x(delta,pos)
elif isint_nonzero(rel.y):
elif isint_nonzero(rel.y/self.size):
# stuck in y direction
return self.move_stuck_y(delta,pos)
# this should never happen
@ -213,11 +212,11 @@ class Square_element():
# do not move past corners
rel=pos.y-self.pos.y
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/self.size)*self.size-1e-11 and delta.y+rel>math.ceil(rel/self.size)*self.size+1e-11 and math.ceil(rel/self.size)*self.size!=0:
# stick to corner
candidate.y=math.ceil(rel)+self.pos.y-pos.y
candidate.y=math.ceil(rel/self.size)*self.size+self.pos.y-pos.y
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/self.size)*self.size+1e-11 and delta.y+rel<math.floor(rel/self.size)*self.size-1e-11 and math.floor(rel/self.size)*self.size!=0:
# stick to corner
candidate.y=math.floor(rel)+self.pos.y-pos.y
return candidate
@ -228,12 +227,12 @@ class Square_element():
# do not move past corners
rel=pos.x-self.pos.x
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/self.size)*self.size-1e-11 and delta.x+rel>math.ceil(rel/self.size)*self.size+1e-11 and math.ceil(rel/self.size)*self.size!=0:
# stick to corner
candidate.x=math.ceil(rel)+self.pos.x-pos.x
candidate.x=math.ceil(rel/self.size)*self.size+self.pos.x-pos.x
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/self.size)*self.size+1e-11 and delta.x+rel<math.floor(rel/self.size)*self.size-1e-11 and math.floor(rel/self.size)*self.size!=0:
# stick to corner
candidate.x=math.floor(rel)+self.pos.x-pos.x
candidate.x=math.floor(rel/self.size)*self.size+self.pos.x-pos.x
return candidate