Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #Test parameters
- # Resolution of screen
- screen_res = (1024,768)
- # Path to test surface (if `None`, one will be created procedurally)
- image_path = None
- # Resolution of the image (resized as-necessary)
- image_testres = (400,100)
- # Blit position of un-rotated image (marked with an unfilled light-blue dot).
- image_blitpos = (400,300)
- # If `True`, uses different function that supports rotating around
- # an arbitrary point, instead of the center of the image. Either way,
- # the rotation point is marked with a red dot.
- use_arbitrary_centers = True
- if use_arbitrary_centers:
- # Coordinates of rotation center in [0,1] space over the image.
- image_rotation_center_uv = (0.2,0.7)
- # If `True`, draws crosshairs at mouse position
- draw_crosshairs = False
- #Test program
- import os, sys
- import traceback
- with open(os.devnull, "w") as f:
- oldstdout=sys.stdout; sys.stdout=f; import pygame; sys.stdout=oldstdout
- from pygame.locals import *
- if sys.platform in ["win32","win64"]: os.environ["SDL_VIDEO_CENTERED"]="1"
- pygame.display.init()
- pygame.font.init()
- icon=pygame.Surface((1,1)); icon.set_alpha(0); pygame.display.set_icon(icon)
- pygame.display.set_caption("Rotation Around Point - Ian Mallett - 2019")
- surfdisp = pygame.display.set_mode(screen_res)
- font12 = pygame.font.SysFont("Times New Roman",12,bold=True)
- ##font25 = pygame.font.SysFont("Times New Roman",25)
- def rndint(x): return int(round(x))
- # Setup test image
- if use_arbitrary_centers:
- image_rotation_center_pixels = ( image_testres[0]*image_rotation_center_uv[0], image_testres[1]*image_rotation_center_uv[1] )
- else:
- image_rotation_center_pixels = ( image_testres[0]*0.5, image_testres[1]*0.5 )
- tmp = (rndint(image_rotation_center_pixels[0]),rndint(image_rotation_center_pixels[1]))
- ##rounded_center_u = float(tmp[0])!=image_rotation_center_pixels[0]
- ##rounded_center_v = float(tmp[1])!=image_rotation_center_pixels[1]
- image_rotation_center_pixels = tmp
- if image_path == None:
- surftest = pygame.Surface(image_testres)
- for j in range(image_testres[1]):
- for i in range(image_testres[0]):
- surftest.set_at((i,j),( rndint((255.0*i)/image_testres[0]), rndint((255.0*j)/image_testres[1]), 0 ))
- pygame.draw.rect(surftest,(192,192,192),(0,0,image_testres[0],image_testres[1]),1)
- ## surftest.blit(font25.render("Hello World",True,(0,0,0)),(5,5))
- surftest.set_at((0,0),(128,0,128))
- else:
- surftest = pygame.image.load(image_path).convert()
- surftest = pygame.transform.smoothscale(surftest,image_testres)
- pygame.draw.line(surftest,(255,255,255),(0,image_rotation_center_pixels[1]),image_rotation_center_pixels,1)
- pygame.draw.line(surftest,(255,255,255),(image_rotation_center_pixels[0],0),image_rotation_center_pixels,1)
- ##labelu = font12.render(u"u*w = (%g)(%d) %s %d"%(image_rotation_center_uv[0],image_testres[0],("=",u"≈")[int(rounded_center_u)],image_rotation_center_pixels[0]),True,(255,255,255))
- ##labelv = font12.render(u"v*h = (%g)(%d) %s %d"%(image_rotation_center_uv[1],image_testres[1],("=",u"≈")[int(rounded_center_v)],image_rotation_center_pixels[1]),True,(255,255,255))
- labelu = font12.render("u=%g"%image_rotation_center_uv[0],True,(255,255,255))
- labelv = font12.render("v=%g"%image_rotation_center_uv[1],True,(255,255,255))
- surftest.blit(labelu,(image_rotation_center_pixels[0]//2-labelu.get_width()//2,image_rotation_center_pixels[1]+5))
- surftest.blit(labelv,(image_rotation_center_pixels[0]+5,image_rotation_center_pixels[1]//2-labelu.get_height()//2))
- pygame.draw.circle(surftest,(255,0,0),image_rotation_center_pixels,3)
- def get_input():
- keys_pressed = pygame.key.get_pressed()
- mouse_buttons = pygame.mouse.get_pressed()
- mouse_position = pygame.mouse.get_pos()
- mouse_rel = pygame.mouse.get_rel()
- for event in pygame.event.get():
- if event.type == QUIT: return False
- elif event.type == KEYDOWN:
- if event.key == K_ESCAPE: return False
- return True
- import math
- def blit_rotated_center( dest, source,coord,angle_deg, area=None,special_flags=0 ):
- """Draws surface `source` onto surface `dest` at coordinate `coord`, but as-if it had been
- rotated by `angle_deg` degrees around its center first. The `area` and `special_flags` are as
- for ordinary blits."""
- x, y = coord
- w, h = source.get_size()
- source_rotated = pygame.transform.rotate(source,angle_deg)
- angle_rad = math.radians(angle_deg)
- costheta, sintheta = math.cos(angle_rad), math.sin(angle_rad)
- abscostheta, abssintheta = abs(costheta), abs(sintheta)
- ## shift = (
- ## 0.5*w - 0.5*( w*abscostheta+h*abssintheta ),
- ## 0.5*h - 0.5*( w*abssintheta+h*abscostheta )
- ## )
- shift = (
- 0.5*(w - w*abscostheta - h*abssintheta ),
- 0.5*(h - h*abscostheta - w*abssintheta )
- )
- x_new = x + shift[0]
- y_new = y + shift[1]
- dest.blit(source_rotated,(x_new,y_new),area=area,special_flags=special_flags)
- return (x_new,y_new)
- def blit_rotated_point ( dest, source,coord,angle_deg,center_uv=(0.5,0.5), area=None,special_flags=0 ):
- """Draws surface `source` onto surface `dest` at coordinate `coord`, but as-if it had been
- rotated first by `angle_deg` degrees around the rotation center defined by `center_uv`, a point
- in the UV space of the texture (e.g. `(0,0)` is the top left, `(1,0)` is the top right, etc.).
- The `area` and `special_flags` are as for ordinary blits."""
- x, y = coord
- w, h = source.get_size()
- u, v = center_uv[0], 1-center_uv[1]
- source_rotated = pygame.transform.rotate(source,angle_deg)
- angle_rad = math.radians(angle_deg)
- costheta, sintheta = math.cos(angle_rad), math.sin(angle_rad)
- #This is perhaps more-descriptive, but the uncommented version is simpler and faster.
- ## def transform(pt):
- ## pt = ( pt[0]-u*w, pt[1]-v*h )
- ## pt = (
- ## pt[0]*costheta - pt[1]*sintheta,
- ## pt[0]*sintheta + pt[1]*costheta
- ## )
- ## pt = ( pt[0]+u*w, pt[1]+v*h )
- ## return pt
- ## pt00 = transform((0,0))
- ## ptw0 = transform((w,0))
- ## pt0h = transform((0,h))
- ## ptwh = transform((w,h))
- ## shift = (
- ## min( pt00[0], ptw0[0], pt0h[0], ptwh[0] ),
- ## min( pt00[1], ptw0[1], pt0h[1], ptwh[1] )
- ## )
- shift = (
- ( (min(-u*costheta,(1-u)*costheta)+u)*w + (min( v*sintheta,(v-1)*sintheta) )*h ),
- ( (min(-u*sintheta,(1-u)*sintheta) )*w + (min(-v*costheta,(1-v)*costheta)+v)*h )
- )
- x_new = x + shift[0]
- y_new = source.get_height()+y - (source_rotated.get_height()+shift[1])
- dest.blit(source_rotated,(x_new,y_new),area=area,special_flags=special_flags)
- return (x_new,y_new)
- label1 = font12.render(u"Rotation center →",True,(255,255,255))
- label1 = pygame.transform.rotate(label1,90)
- label2 = font12.render(u"Original blit position →",True,(255,255,255))
- label3 = font12.render(u"New blit position →",True,(255,255,255))
- angle_deg = 0
- def draw():
- global angle_deg
- surfdisp.fill((64,64,64))
- if use_arbitrary_centers:
- image_blitpos_transformed = blit_rotated_point ( surfdisp, surftest,image_blitpos,angle_deg,image_rotation_center_uv )
- else:
- image_blitpos_transformed = blit_rotated_center( surfdisp, surftest,image_blitpos,angle_deg )
- surfdisp.blit(label1,(image_blitpos[0]+image_rotation_center_pixels[0]-label1.get_width()//2,image_blitpos[1]+image_rotation_center_pixels[1]+5))
- surfdisp.blit(label2,(image_blitpos[0]-label2.get_width()-5,image_blitpos[1]-label2.get_height()//2))
- pygame.draw.circle(surfdisp, (0,192,255), image_blitpos, 3, 1)
- surfdisp.blit(label3,(image_blitpos_transformed[0]-label3.get_width()-5,image_blitpos_transformed[1]-label3.get_height()//2))
- pygame.draw.circle(surfdisp, (192,0,192), (rndint(image_blitpos_transformed[0]),rndint(image_blitpos_transformed[1])), 3, 1)
- surfdisp.blit(font12.render(u"Angle: %3d°"%angle_deg,True,(255,255,255)),(15,15))
- if draw_crosshairs:
- x,y = pygame.mouse.get_pos()
- pygame.draw.line(surfdisp,(192,192,192),(x,0),(x,screen_res[1]),1)
- pygame.draw.line(surfdisp,(192,192,192),(0,y),(screen_res[0],y),1)
- pygame.display.flip()
- angle_deg = (angle_deg+1) % 360
- def main():
- clock = pygame.time.Clock()
- while True:
- if not get_input(): break
- draw()
- clock.tick(60)
- pygame.quit()
- if __name__ == "__main__":
- try:
- main()
- except:
- traceback.print_exc()
- pygame.quit()
- input()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement