I am wanting to use the baseTriangle and baseSquare variables in my for loops in the rotateshape(), but when they are put in, the funnction seems to alter them, meaning that they get bigger with every loop. not sure why it does this, please help!!!
#! /usr/bin/env python
import Image, ImageDraw
import math
# functions
def rotateShape(shapeXCoordinates, shapeYCoordinates, baseXCoordinates, baseYCoordinates):
# Written by: some guy who had to do this once and thought it better to share rather than let other people suffer through the monotony
# This function below takes a shape and rotates, scales and translates it so that the first two coordinates are equal to the baseCoordinates
# Make sure that the distance between the first two shape coordinates is 1 and that they lie on the x-axis
# Find the dx, dy and the length of the baseCoordinates pair
#print 'Base coordinates: ' + str(zip(baseXCoordinates, baseYCoordinates))
dx = baseXCoordinates[1] - baseXCoordinates[0]
#print 'dx: ' + str(dx)
dy = baseYCoordinates[1] - baseYCoordinates[0]
#print 'dy: ' + str(dy)
magnitude = math.sqrt(dx**2+dy**2)
#print 'magnitude: ' + str(magnitude)
#print 'Start: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
# Rotate the matrix
a = dx/magnitude
b = -dy/magnitude
c = dy/magnitude
d = dx/magnitude
for i in range(0,len(shapeXCoordinates)):
# Find the new x value
newX = a*shapeXCoordinates[i]+b*shapeYCoordinates[i]
# Find the new y value
newY = c*shapeXCoordinates[i]+d*shapeYCoordinates[i]
# Replace the old with the new
shapeXCoordinates[i] = newX
shapeYCoordinates[i] = newY
#print 'After rotate: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
# Scale the matrix
for i in range(0,len(shapeXCoordinates)):
shapeXCoordinates[i] = shapeXCoordinates[i]*magnitude
shapeYCoordinates[i] = shapeYCoordinates[i]*magnitude
#print 'After scale: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
# Translate the matrix
for i in range(0,len(shapeXCoordinates)):
shapeXCoordinates[i] = shapeXCoordinates[i]+baseXCoordinates[0]
shapeYCoordinates[i] = shapeYCoordinates[i]+baseYCoordinates[0]
#print 'After translate: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
return (shapeXCoordinates, shapeYCoordinates)
# create a bitmap
img = Image.new('RGB', (3840, 2160))
draw = ImageDraw.Draw(img)
# setting up the varibales
# insert angle
angle = 30
angle_2 = 90 - angle
a = math.sin(angle_2) * 1
# working out the Y of the triangle
y = math.sin(angle) * a
# working out the X of Y
x = math.tan(angle)/y
baseTriangle_X = [0, 1, x]
baseTriangle_Y = [0, 0, y]
baseSquare_X = [0, 1, 1, 0]
baseSquare_Y = [0, 0, 1, 1]
startPosition_X = [1800, 2200] # flipped numbers as bitmap counts from the top left so that tree is created downwards
startPosition_Y = [0, 0]
# set number of iterations
numberOfIterations = 10
# set colour
redStart = 255
greenStart = 253
blueStart = 208
redEnd = 228
greenEnd = 82
blueEnd = 0
# colour change
redChange =(redEnd - redStart)/numberOfIterations
greenChange =(greenEnd - greenStart)/numberOfIterations
blueChange =(blueEnd - blueStart)/numberOfIterations
# set up the list of squares to make (fill with the start position)
squaresToMake_X = []
squaresToMake_Y = []
squaresToMake_X.extend(startPosition_X)
squaresToMake_Y.extend(startPosition_Y)
# set up the list of triangles
trianglesToMake_X = []
trianglesToMake_Y = []
# creating the tree
print '//////////////////////////////'
print '// // // // //'
print '//// //// ////// ////// //////'
print '//// //// ////// // //'
print '//// //// ////// ////// //////'
print '//// //// ////// // //'
print '//////////////////////////////'
# background colour
draw.rectangle((0,0,3839,2759), fill=(220, 255, 250))
for i in xrange(0, numberOfIterations):
redCurrent = redStart + redChange * i
greenCurrent = greenStart + greenChange * i
blueCurrent = blueStart + blueChange * i
# making squares
for j in xrange(0, len(squaresToMake_X)/2):
print 'Iteration ' + str(i) + ' of ' + str(numberOfIterations) + '. Square ' + str(j) + ' of ' + str(len(squaresToMake_X)/2)
k = j * 2
newVertices_X, newVertices_Y = rotateShape([0, 1, 1, 0], [0, 0, 1, 1], squaresToMake_X[k:k+2], squaresToMake_Y[k:k+2])
# merge x and y
combinedVertices = zip(newVertices_X, newVertices_Y)
# draw
#print 'Drawing square:'
#print combinedVertices
draw.polygon(combinedVertices, fill = (redCurrent, greenCurrent, blueCurrent))
trianglesToMake_X.extend([newVertices_X[3], newVertices_X[2]])
trianglesToMake_Y.extend([newVertices_Y[3], newVertices_Y[2]])
#print 'Triangles to make:'
#print zip(trianglesToMake_X, trianglesToMake_Y)
squaresToMake_X = []
squaresToMake_Y = []
# making triangles
for j in xrange(0, len(trianglesToMake_X)/2):
print 'Iteration ' + str(i) + ' of ' + str(numberOfIterations) + '. Triangle ' + str(j) + ' of ' + str(len(trianglesToMake_X)/2)
k = j * 2
newVertices_X, newVertices_Y = rotateShape([0, 1, 0.5], [0, 0, 0.5], trianglesToMake_X[k:k+2], trianglesToMake_Y[k:k+2])
# merge x and y
combinedVertices = zip(newVertices_X, newVertices_Y)
# draw
#print 'Drawing triangle:'
#print combinedVertices
draw.polygon(combinedVertices, fill = (redCurrent, greenCurrent, blueCurrent))
squaresToMake_X.extend([newVertices_X[0], newVertices_X[2], newVertices_X[2], newVertices_X[1]])
squaresToMake_Y.extend([newVertices_Y[0], newVertices_Y[2], newVertices_Y[2], newVertices_Y[1]])
#print 'Squares to make:'
#print zip(squaresToMake_X, squaresToMake_Y)
trianglesToMake_X = []
trianglesToMake_Y = []
print '----------'
img2=img.rotate(180)
img2.show()
list
objects are mutable, so when you pass them into a function, a reference to the original list is passed, rather than a copy. Therefore when you modify the list, such as with shapeXCoordinates[i] = newX
, you're modifying the original list at the same time.
If you only want modifications to stay local to the function, without changing the original, you need to make a copy of the list first:
shapeX = shapeXCoordinates[:]
Then reference shapeX
everywhere in the function, rather than shapeXCoordinates
.
Obviously name the variables however makes sense to you.