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 # modifiers
self.modifiers=[] self.modifiers=[]
# base size for all particles
self.base_size=50
# init Widget # init Widget
super(Painter,self).__init__(**kwargs) super(Painter,self).__init__(**kwargs)
@ -75,13 +78,13 @@ class Painter(Widget):
# convert logical coordinates (normalized and centered) to the ones that are plotted # convert logical coordinates (normalized and centered) to the ones that are plotted
def pos_tocoord_x(self,x): 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): 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): 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): 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 # zoom
elif text=="+": elif text=="+":
# increment by 10% # increment by 10%
self.set_zoom(Square_element.size/50*1.1) self.set_zoom(self.base_size/50*1.1)
elif text=="-": elif text=="-":
# decrease by 10% # decrease by 10%
self.set_zoom(Square_element.size/50*0.9) self.set_zoom(self.base_size/50*0.9)
elif text=="=": elif text=="=":
# reset # reset
self.set_zoom(1) self.set_zoom(1)
@ -557,7 +560,7 @@ class Painter(Widget):
# set zoom level # set zoom level
def set_zoom(self,level): def set_zoom(self,level):
Square_element.size=level*50 self.base_size=level*50
self.draw() self.draw()

View File

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