From ec9f0018f7d5bd71e7a3aaa0b5315db185e0a35f Mon Sep 17 00:00:00 2001 From: Ian Jauslin Date: Wed, 21 Sep 2022 17:37:05 -0400 Subject: [PATCH] Center logical coordinates (so that zooming in and out keeps center invariant) --- src/painter.py | 31 +++++++++++++++++++++------ src/polyomino.py | 54 +++++++++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/painter.py b/src/painter.py index 1b518bf..bd32c0a 100644 --- a/src/painter.py +++ b/src/painter.py @@ -53,6 +53,17 @@ class Painter(Widget): self.undermouse=None self.draw() + # 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 + def pos_tocoord_y(self,y): + return self.height/2+y*Square_element.size + def coord_topos_x(self,x): + return (x-self.width/2)/Square_element.size + def coord_topos_y(self,y): + return (y-self.height/2)/Square_element.size + + # draw all particles def draw(self): @@ -61,7 +72,7 @@ class Painter(Widget): # draw order: particles, then grids, then transparent particles for particle in self.particles: - particle.draw() + particle.draw(self) # draw grids for particle in self.particles: @@ -69,8 +80,9 @@ class Painter(Widget): self.draw_grid(particle.squares[0].pos,particle.grid) for particle in self.particles: - particle.draw(alpha=0.5) + particle.draw(self,alpha=0.5) + # draw a grid around a particle def draw_grid(self,pos,mesh): # height offset due to status bar and command prompt height_offset=self.app.status_bar.height+self.app.command_prompt.height @@ -156,10 +168,13 @@ class Painter(Widget): def on_touch_down(self,touch): # only respond to touch in drawing area if self.collide_point(*touch.pos): + # convert to logical + touchx=self.coord_topos_x(touch.x) + touchy=self.coord_topos_y(touch.y) # create new cross if touch.button=="right": - new=Cross(touch.x/Square_element.size,touch.y/Square_element.size) + new=Cross(touchx,touchy) if not self.check_interaction_any(new,Point(0,0)): # add to list self.particles.append(new) @@ -175,11 +190,11 @@ class Painter(Widget): # select particle if touch.button=="left": # find particle under touch - self.undermouse=self.find_particle(Point(touch.x/Square_element.size,touch.y/Square_element.size)) + self.undermouse=self.find_particle(Point(touchx,touchy)) # record relative position of click with respect to reference if self.undermouse!=None: - self.offset=Point(touch.x/Square_element.size,touch.y/Square_element.size)-self.undermouse.squares[0].pos + self.offset=Point(touchx,touchy)-self.undermouse.squares[0].pos # no modifiers if self.modifiers==[]: @@ -222,12 +237,16 @@ class Painter(Widget): # respond to drag def on_touch_move(self,touch): + # convert to logical + touchx=self.coord_topos_x(touch.x) + touchy=self.coord_topos_y(touch.y) + # only respond to touch in drawing area if self.collide_point(*touch.pos): # 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(touch.x/Square_element.size,touch.y/Square_element.size)-(self.offset+self.undermouse.squares[0].pos),0) + delta=self.adjust_move(Point(touchx,touchy)-(self.offset+self.undermouse.squares[0].pos),0) for particle in self.selected: particle.move(delta) diff --git a/src/polyomino.py b/src/polyomino.py index 4e39126..8a96de8 100644 --- a/src/polyomino.py +++ b/src/polyomino.py @@ -18,7 +18,7 @@ class Polyomino(): self.grid=kwargs.get("grid",0) # draw function - def draw(self,**kwargs): + def draw(self,painter,**kwargs): alpha=kwargs.get("alpha",1) # set color if not self.selected: @@ -29,22 +29,26 @@ class Polyomino(): Color(r/2,g/2,b/2,alpha) for square in self.squares: - Rectangle(pos=((square.pos.x-0.5)*square.size,(square.pos.y-0.5)*square.size),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,square.size)) # draw boundary - self.stroke() + self.stroke(painter) # draw boundary (override for connected polyominos) - def stroke(self): + def stroke(self,painter): + # convert to graphical coordinates + coordx=painter.pos_tocoord_x(square.pos.x) + coordy=painter.pos_tocoord_y(square.pos.y) + # white Color(1,1,1) for square in self.squares: Line(points=( - *((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) + *(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) )) # move by delta @@ -84,22 +88,26 @@ class Cross(Polyomino): ]) # redefine stroke to avoid lines between touching squares - def stroke(self): + 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) + Color(1,1,1) Line(points=( - *((self.squares[0].pos.x-0.5)*Square_element.size,(self.squares[0].pos.y-0.5)*Square_element.size), - *((self.squares[0].pos.x-0.5)*Square_element.size,(self.squares[0].pos.y-1.5)*Square_element.size), - *((self.squares[0].pos.x+0.5)*Square_element.size,(self.squares[0].pos.y-1.5)*Square_element.size), - *((self.squares[0].pos.x+0.5)*Square_element.size,(self.squares[0].pos.y-0.5)*Square_element.size), - *((self.squares[0].pos.x+1.5)*Square_element.size,(self.squares[0].pos.y-0.5)*Square_element.size), - *((self.squares[0].pos.x+1.5)*Square_element.size,(self.squares[0].pos.y+0.5)*Square_element.size), - *((self.squares[0].pos.x+0.5)*Square_element.size,(self.squares[0].pos.y+0.5)*Square_element.size), - *((self.squares[0].pos.x+0.5)*Square_element.size,(self.squares[0].pos.y+1.5)*Square_element.size), - *((self.squares[0].pos.x-0.5)*Square_element.size,(self.squares[0].pos.y+1.5)*Square_element.size), - *((self.squares[0].pos.x-0.5)*Square_element.size,(self.squares[0].pos.y+0.5)*Square_element.size), - *((self.squares[0].pos.x-1.5)*Square_element.size,(self.squares[0].pos.y+0.5)*Square_element.size), - *((self.squares[0].pos.x-1.5)*Square_element.size,(self.squares[0].pos.y-0.5)*Square_element.size), - *((self.squares[0].pos.x-0.5)*Square_element.size,(self.squares[0].pos.y-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*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), ))