Related
I'm creating a function to draw a office tower:
windows are 20 pixels square
the gap between the windows is 10 pixels
the door is 20 pixels wide, 50 pixels tall, and orange
My code doesn't draw it properly:
from graphics import *
from random import *
def add_window(win, nH, nV):
w, h = win.getWidth(), win.getHeight()
rects = []
for x in range(nH):
rects.append([])
for y in range(nV):
r = Rectangle(Point( x *w//nH, y *h//vV),
Point((x+1)*w//nH, (y+1)*h//nV))
window = [ r,
True,
[ 'red', 'green' ]
]
rects[x].append(window)
rects[x][y][0].draw(win)
rects[x][y][0].setOutline('blue')
color = window[2][randint[0,1]]
rects[x][y][0].setFill(color)
return rects
WIN_W, WIN_H = 500, 400
#Top left coner of the building
BLDG_LEFT, BLDG_TOP = 50, 50
#How many floors, how many windows perfloor, window digit and gap
FLOORS, WIN_FLR, WIN_SZ, GAP = 10, 5, 20, 5
win = None
#Syntax : window[x][y]
# [0] : Rectangle() object
# [1] : True/False
windows = []
#--------------------------------------------------------------------
def draw_window(x, y):
global windows
windows = []
left = BLDG_LEFT + GAP + x* (WIN_SZ+GAP)
top = BLDG_TOP + GAP + y* (WIN_SZ+GAP)
r = Rectangle(Point( x *WIN_SZ+GAP, y *(WIN_SZ+GAP)),
Point((x+1)*WIN_SZ+GAP, (y+1)*(WIN_SZ+GAP)))
windows[x][y].append(r)
bit = randint(0,1)
windows[x][y].append(bool(bit))
windows[x][y][0].setFill(COLORS[bit])
windows[x][y][0].draw(win)
def draw_windows():
for i in range(WIN_FLR):
windows.append([])
for j in range(FLOORS):
windows[i].append([])
draw_window(i, j)
def office_tower():
global win
win = GraphWin("OFFICE TOWER", WIN_W, WIN_H)
draw_window(1, 1)
while True:
pt = win.getmouse()
if pt.x < 10 and pt.y < 10:
break
# windows coordinates
x = int((pt.x - BLDG_LEFT - GAP)/(WIN_SZ + GAP))
y = int((pt.y - BLDG_TOP - GAP)/(WIN_SZ + GAP))
print(str((pt.x, pt.y)) + ' --> ' + str((x, y)))
windows[x][y][1] = netwindows[x][y][1]
windows[x][y][0].setFill(COLORS[windows[x][y][1]])
def draw_building():
global windows
win = GraphWin("OFFICE TOWER", WIN_W, WIN_H)
N_H, N_V = 5, 10
while True:
pt = win.getMouse()
m_x, m_y = pt.getX(), pt.getY()
# Grid coordinates:
g_x = m_x // (WIN_W//N_H)
g_y = m_y // (WIN_H//N_V)
# For development purposes:
if m_x < 10 and m_y < 10:
break
This seems to be the worst virtual high-rise disaster since Irwin Allen's "Towering Inferno". There appear to be at least two different incomplete implementations in the file where most of the functions are never called and the code draws nothing. Here's my salvage job on the ruins:
from random import randint
from graphics import *
GRAPHIC_WINDOW_WIDTH, GRAPHIC_WINDOW_HEIGHT = 500, 400
# Top left coner of the building
BUILDING_LEFT, BUILDING_TOP = 50, 50
COLORS = ['gray25', 'gray85'] # lights off, lights on
# How many BUILDING_FLOORS, how many windows per floor, window size and gap
BUILDING_FLOORS, WINDOWS_PER_FLOOR, WINDOW_SIZE, WINDOW_GAP = 10, 5, 20, 5
WINDOW_FRAME = WINDOW_SIZE + WINDOW_GAP
# Syntax : window[x][y]
# [0] : Rectangle() object
# [1] : True/False
#--------------------------------------------------------------------
def draw_window(row, column, left, top):
r = Rectangle(Point(left + column * WINDOW_FRAME, top + row * WINDOW_FRAME), \
Point(left + (column + 1) * WINDOW_FRAME, top + (row + 1) * WINDOW_FRAME))
bit = bool(randint(0, 1))
r.setFill(COLORS[bit])
r.draw(win)
windows[row][column] = [r, bit]
def draw_windows(left, top):
for row in range(BUILDING_FLOORS):
windows.append([])
for column in range(WINDOWS_PER_FLOOR):
windows[row].append(None)
draw_window(row, column, left, top)
def office_tower():
draw_windows(BUILDING_LEFT, BUILDING_TOP)
while True:
pt = win.getMouse()
if pt.x < BUILDING_LEFT and pt.y < BUILDING_TOP:
break # clean exit stategy
# windows coordinates
column = int((pt.x - BUILDING_LEFT - WINDOW_GAP) / WINDOW_FRAME)
row = int((pt.y - BUILDING_TOP - WINDOW_GAP) / WINDOW_FRAME)
# print((pt.x, pt.y), '-->', (row, column))
windows[row][column][1] = not windows[row][column][1]
windows[row][column][0].setFill(COLORS[windows[row][column][1]])
win = GraphWin('OFFICE TOWER', GRAPHIC_WINDOW_WIDTH, GRAPHIC_WINDOW_HEIGHT)
windows = []
office_tower()
win.close()
This draws the following building:
Where you can click on the windows to toggle their color. (I chose an 'on' / 'off' motif.) Clicking to the upper left of the building exits.
i'm having trouble with having my CGI picture and vignette profile image going together to make a vignette picture where the picture is slightly darker around the edges of the picture without compromising the image anywhere else, i am getting everything so far that i think is right but my picture is showing up dark in the middle instead of showing the image normal but with slightly darker colored edges.
this is what i have currently:
def main():
inputPic = makePicture(pickAFile())
vignette = makePicture(pickAFile())
addVignette(inputPic, vignette)
def addVignette(inputPic, vignette):
if getWidth(inputPic) == getWidth(vignette) and getHeight(inputPic) == getHeight(vignette):
explore(inputPic)
explore(vignette)
px1 = getPixels(inputPic)
px2 = getPixels(vignette)
for px in getPixels(inputPic):
x = getX(px)
y = getY(px)
px2 = getPixelAt(vignette, x, y)
x2 = getX(px2)
y2 = getY(px2)
r1 = getRed(px)
r2 = getRed(px2)
g1 = getGreen(px)
g2 = getGreen(px2)
b1 = getBlue(px)
b2 = getBlue(px2)
newR = (r1-r2+104)
newG = (g1-g2+88)
newB = (b1-b2+48)
newC = makeColor(newR, newG, newB)
setColor(px, newC)
explore(inputPic)
folder = pickAFolder()
filename = requestString("enter file name: ")
path = folder+filename+".jpg"
writePictureTo(inputPic, path)
http://i.stack.imgur.com/PqW7K.jpg
picture 1 is what the image needs to be
http://i.stack.imgur.com/PtS4U.jpg
picture 2 is my image i get at the end of my coding
Any help to get me in the right direction would be very much appreciated
After absolutely getting this wrong the first 3 times I worked it out with the help of my little friend the modules operator.
def addVignette(inputPic, vignette):
# Create empty canvas
canvas = makeEmptyPicture(getWidth(inputPic), getHeight(inputPic))
for x in range(0, getWidth(inputPic)):
for y in range(0, getHeight(inputPic)):
px = getPixel(canvas, x, y)
inputPixel = getPixel(inputPic, x, y)
vignettePixel = getPixel(vignette, x, y)
# Make a new color from those values
newColor = getNewColorValues(inputPixel, vignettePixel)
# Assign this new color to the current pixel of the input image
setColor(px, newColor)
explore(canvas)
def getNewColorValues(inputPixel, vignettePixel):
inputRed = getRed(inputPixel)
vignetteRed = getRed(vignettePixel)
inputGreen = getGreen(inputPixel)
vignetteGreen = getGreen(vignettePixel)
inputBlue = getBlue(inputPixel)
vignetteBlue = getBlue(vignettePixel)
newR = inputRed - (255 % vignetteRed) / 3
newG = inputGreen - (255 % vignetteGreen) / 3
newB = inputBlue - (255 % vignetteBlue) / 3
newC = makeColor(newR, newG, newB)
return newC
I want to create a hexagonal grid using XYZ coordinates that is constructed in a spiraling pattern. This is my current code, which produces a grid depicted by the red arrows below. My problem area is circled. Rather than going from [-1,0,1] to [0,-2,2] I need to move from [-1,0,1] to [-1,-1,2] (following the blue line).
The complete code appears below the hash line- I am creating the visualization in Blender 2.65a
radius = 11 # determines size of field
deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]]
hex_coords = []
for r in range(radius):
x = 0
y = -r
z = +r
points = x,y,z
hex_coords.append(points)
for j in range(6):
if j==5:
num_of_hexas_in_edge = r-1
else:
num_of_hexas_in_edge = r
for i in range(num_of_hexas_in_edge):
x = x+deltas[j][0]
y = y+deltas[j][1]
z = z+deltas[j][2]
plot = x,y,z
hex_coords.append(plot)
-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-
import bpy
FOXP2 = '''
CTTGAACCTTTGTCACCCCTCACGTTGCACACCAAAGACATACCCTAGTGATTAAATGCTGATTTTGTGT
ACGATTGTCCACGGACGCCAAAACAATCACAGAGCTGCTTGATTTGTTTTAATTACCAGCACAAAATGCC
CAATTCCTCCTCGACTACCTCCTCCAACACTTCCAAAGCATCACCACCAATAACTCATCATTCCATAGTG
AATGGACAGTCTTCAGTTCTAAGTGCAAGACGAGACAGCTCGTCACATGAGGAGACTGGGGCCTCTCACA
CTCTCTATGGCCATGGAGTTTGCAAATGGCCAGGCTGTGAAAGCATTTGTGAAGATTTTGGACAGTTTTT
AAAGCACCTTAACAATGAACACGCATTGGATGACCGAAGCACTGCTCAGTGTCGAGTGCAAATGCAGGTG
GTGCAACAGTTAGAAATACAGCTTTCTAAAGAACGCGAACGTCTTCAAGCAATGATGACCCACTTGCACA
'''
set_size = len(FOXP2)
def makeMaterial(name, diffuse, specular, alpha):
mat = bpy.data.materials.new(name)
mat.diffuse_color = diffuse
mat.diffuse_shader = 'LAMBERT'
mat.diffuse_intensity = 1.0
mat.specular_color = specular
mat.specular_shader = 'COOKTORR'
mat.specular_intensity = 0.5
mat.alpha = alpha
mat.ambient = 1
return mat
def setMaterial(ob, mat):
me = ob.data
me.materials.append(mat)
# Create four materials
red = makeMaterial('Red', (1,0,0), (0,0,0), .5)
blue = makeMaterial('BlueSemi', (0,0,1), (0,0,0), 0.5)
green = makeMaterial('Green',(0,1,0), (0,0,0), 0.5)
yellow = makeMaterial('Yellow',(1,1,0), (0,0,0), 0.5)
black = makeMaterial('Black',(0,0,0), (0,0,0), 0.5)
white = makeMaterial('White',(1,1,1), (0,0,0), 0.5)
def make_sphere(volume, position):
create = bpy.ops.mesh.primitive_uv_sphere_add
create(size=volume, location=position)
# Builds a list of coordinate points
radius = 11
deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]]
hex_coords = []
for r in range(radius):
x = 0
y = -r
z = +r
points = x,y,z
hex_coords.append(points)
for j in range(6):
if j==5:
num_of_hexas_in_edge = r-1
else:
num_of_hexas_in_edge = r
for i in range(num_of_hexas_in_edge):
x = x+deltas[j][0]
y = y+deltas[j][1]
z = z+deltas[j][2]
plot = x,y,z
hex_coords.append(plot)
# Color-codes sequence and appends to color_array
color_array = []
for x in FOXP2:
if x == 'A':
color_array.append(1)
elif x == 'T':
color_array.append(1)
elif x == 'C':
color_array.append(0)
elif x == 'G':
color_array.append(0)
else:
pass
# Pulls from sequence data and applies color to sphere
# Positions sphere to coordinates
# Pulls from color_code and applies color scheme to sphere object
for x in color_array:
if x =='RED':
coord_tuple = hex_coords.pop(0)
make_sphere(1, coord_tuple)
setMaterial(bpy.context.object, red)
elif x =='GREEN':
coord_tuple = hex_coords.pop(0)
make_sphere(1, coord_tuple)
setMaterial(bpy.context.object, green)
elif x =='BLUE':
coord_tuple = hex_coords.pop(0)
make_sphere(1, coord_tuple)
setMaterial(bpy.context.object, blue)
elif x =='YELLOW':
coord_tuple = hex_coords.pop(0)
make_sphere(1, coord_tuple)
setMaterial(bpy.context.object, yellow)
else:
pass
I would like to make random mouse movements in specified rectangle area (limited with coordinates x1, y1, x2, y2, x3, y3, x4, y4).
Movements should be smooth, random, not just straight lines, go randomly up/down/left/right/etc for specified time duration.
Could you give me a hand or working example I can learn from?
many thanks
This code works on Windows only. You can experiment with the parameters inside the random_movement function to get better results. Good luck!
import ctypes
import random
import time
import math
def move_mouse(pos):
x_pos, y_pos = pos
screen_size = ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1)
x = 65536L * x_pos / screen_size[0] + 1
y = 65536L * y_pos / screen_size[1] + 1
return ctypes.windll.user32.mouse_event(32769, x, y, 0, 0)
def random_movement(top_left_corner, bottom_right_corner, min_speed=100, max_speed=200):
'''speed is in pixels per second'''
x_bound = top_left_corner[0], bottom_right_corner[0]
y_bound = top_left_corner[1], bottom_right_corner[1]
pos = (random.randrange(*x_bound),
random.randrange(*y_bound))
speed = min_speed + random.random()*(max_speed-min_speed)
direction = 2*math.pi*random.random()
def get_new_val(min_val, max_val, val, delta=0.01):
new_val = val + random.randrange(-1,2)*(max_val-min_val)*delta
if new_val<min_val or new_val>max_val:
return get_new_val(min_val, max_val, val, delta)
return new_val
steps_per_second = 35.0
while True:
move_mouse(pos)
time.sleep(1.0/steps_per_second)
speed = get_new_val(min_speed, max_speed, speed)
direction+=random.randrange(-1,2)*math.pi/5.0*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
while new_pos[0] not in xrange(*x_bound) or new_pos[1] not in xrange(*y_bound):
direction = 2*math.pi*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
pos=new_pos
Example:
random_movement((300,300),(600,600))
For random smooth movements constrained to a rectangle I'd try to use Lissajous curves with randomly changing coefficients.
Here is a demo of random X,Y positions you can play as your requirements:
from time import sleep
import pyautogui
import numpy as np
# Check your screen size
print(pyautogui.size())
count=0
while count<1000:
x=np.random.randint(1,1792)
y=np.random.randint(1,1120)
pyautogui.moveTo(x, y)
print(x)
print(y)
sleep(20)
count+=1
Note: install first
pip3 install pyautogui
I made this based on Piotr Dabkowski's code, with some extra features (taking random breaks, random scrolls, and users can end early by right clicking). This works for Python 3, and again, for Windows only.
import ctypes
import random
import time
import math
import win32gui
xmax = ctypes.windll.user32.GetSystemMetrics(0)
ymax = ctypes.windll.user32.GetSystemMetrics(1)
def get_position():
_, _, (x,y) = win32gui.GetCursorInfo()
return (x,y)
def move_mouse(pos):
x_pos, y_pos = pos
x = int(65536 * x_pos / xmax + 1)
y = int(65536 * y_pos / ymax + 1)
return ctypes.windll.user32.mouse_event(32769, x, y, 0, 0)
def start(t=30, min_speed=10, max_speed=500, x_bound=[0,xmax], y_bound=[0,ymax],
p_break = 0.005, break_range = (10, 60), p_scroll = 0.01, scroll_range = (100, 1000)):
def get_new_speed(min_val, max_val, val, delta=0.01):
new_val = val + random.randrange(-1,2)*(max_val-min_val)*delta
if new_val<min_val or new_val>max_val:
return get_new_speed(min_val, max_val, val, delta)
return new_val
steps_per_second = 35.0
print('Started.')
endtime = time.time() + int(t*60)
# Initialize position, speed and direction
pos = get_position()
speed = min_speed + random.random()*(max_speed-min_speed)
direction = 2*math.pi*random.random()
inside_boundary = False
right_clicked = False
# Keep moving mouse until end time, or until right click
while (not right_clicked) and (time.time() < endtime):
if ctypes.windll.user32.GetKeyState(0x02) not in [0,1]:
right_clicked = True
time.sleep(1.0/steps_per_second)
# Taking a break of random duration
duration = random.randint(*break_range) # in unit of seconds
break_endtime = time.time() + duration
r = random.random()
if (1-p_break) <= r < 1:
# Keep checking for right click to exit loop
while (not right_clicked) and (time.time() < break_endtime):
if ctypes.windll.user32.GetKeyState(0x02) not in [0,1]:
right_clicked = True
time.sleep(1.0/steps_per_second)
time_left = break_endtime - time.time()
print('Paused %d / %ds' % (time_left,duration) + ' '*50, end='\r')
pos = get_position()
print(' '*50, end='\r')
# Random scroll
r = random.random()
lines = random.randint(*scroll_range)
sign = random.random()
sign = -1 if sign < 0.5 else 1
if (1-p_scroll) <= r < 1:
time.sleep(random.random())
ctypes.windll.user32.mouse_event(2048, 0, 0, sign*lines, 0)
time.sleep(random.random())
pos = get_position()
# Random move
move_mouse(pos)
time_left = endtime - time.time()
print('Running (time left: %ds)' % time_left + ' '*50, end='\r')
if (pos[0] in range(*x_bound)) and (pos[1] in range(*y_bound)):
inside_boundary = True
# Update position, speed and direction
speed = get_new_speed(min_speed, max_speed, speed)
direction+=random.randrange(-1,2)*math.pi/5.0*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
# Once mouse position is inside boundary, new position must also be inside
if inside_boundary:
while new_pos[0] not in range(*x_bound) or new_pos[1] not in range(*y_bound):
direction = 2*math.pi*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
pos=new_pos
print('Stopped.' + ' ' * 50)
For performing the movements there is a third-party package call PyUserInput that will allow you to control mouse or keyboard, and it is cross-platform. Install it using pip:
$ pip install PyUserInput
For doing smooth movements you can try what 9000 proposes in his answer.
I'm looking at creating map tiles based on a 3D model made in blender,
The map is 16 x 16 in blender.
I've got 4 different zoom levels and each tile is 100 x 100 pixels. The entire map at the most zoomed out level is 4 x 4 tiles constructing an image of 400 x 400.
The most zoomed in level is 256 x 256 obviously constructing an image of 25600 x 25600
What I need is a script for blender that can create the tiles from the model.
I've never written in python before so I've been trying to adapt a couple of the scripts which are already there.
So far I've come up with a script, but it doesn't work very well. I'm having real difficulties getting the tiles to line up seamlessly. I'm not too concerned about changing the height of the camera as I can always create the same zoomed out tiles at 6400 x 6400 images and split the resulting images into the correct tiles.
Here is what I've got so far...
#!BPY
"""
Name: 'Export Map Tiles'
Blender: '242'
Group: 'Export'
Tip: 'Export to Map'
"""
import Blender
from Blender import Scene,sys
from Blender.Scene import Render
def init():
thumbsize = 200
CameraHeight = 4.4
YStart = -8
YMove = 4
XStart = -8
XMove = 4
ZoomLevel = 1
Path = "/Images/Map/"
Blender.drawmap = [thumbsize,CameraHeight,YStart,YMove,XStart,XMove,ZoomLevel,Path]
def show_prefs():
buttonthumbsize = Blender.Draw.Create(Blender.drawmap[0]);
buttonCameraHeight = Blender.Draw.Create(Blender.drawmap[1])
buttonYStart = Blender.Draw.Create(Blender.drawmap[2])
buttonYMove = Blender.Draw.Create(Blender.drawmap[3])
buttonXStart = Blender.Draw.Create(Blender.drawmap[4])
buttonXMove = Blender.Draw.Create(Blender.drawmap[5])
buttonZoomLevel = Blender.Draw.Create(Blender.drawmap[6])
buttonPath = Blender.Draw.Create(Blender.drawmap[7])
block = []
block.append(("Image Size", buttonthumbsize, 0, 500))
block.append(("Camera Height", buttonCameraHeight, -0, 10))
block.append(("Y Start", buttonYStart, -10, 10))
block.append(("Y Move", buttonYMove, 0, 5))
block.append(("X Start", buttonXStart,-10, 10))
block.append(("X Move", buttonXMove, 0, 5))
block.append(("Zoom Level", buttonZoomLevel, 1, 10))
block.append(("Export Path", buttonPath,0,200,"The Path to save the tiles"))
retval = Blender.Draw.PupBlock("Draw Map: Preferences" , block)
if retval:
Blender.drawmap[0] = buttonthumbsize.val
Blender.drawmap[1] = buttonCameraHeight.val
Blender.drawmap[2] = buttonYStart.val
Blender.drawmap[3] = buttonYMove.val
Blender.drawmap[4] = buttonXStart.val
Blender.drawmap[5] = buttonXMove.val
Blender.drawmap[6] = buttonZoomLevel.val
Blender.drawmap[7] = buttonPath.val
Export()
def Export():
scn = Scene.GetCurrent()
context = scn.getRenderingContext()
def cutStr(str): #cut off path leaving name
c = str.find("\\")
while c != -1:
c = c + 1
str = str[c:]
c = str.find("\\")
str = str[:-6]
return str
#variables from gui:
thumbsize,CameraHeight,YStart,YMove,XStart,XMove,ZoomLevel,Path = Blender.drawmap
XMove = XMove / ZoomLevel
YMove = YMove / ZoomLevel
Camera = Scene.GetCurrent().getCurrentCamera()
Camera.LocZ = CameraHeight / ZoomLevel
YStart = YStart + (YMove / 2)
XStart = XStart + (XMove / 2)
#Point it straight down
Camera.RotX = 0
Camera.RotY = 0
Camera.RotZ = 0
TileCount = 4**ZoomLevel
#Because the first thing we do is move the camera, start it off the map
Camera.LocY = YStart - YMove
for i in range(0,TileCount):
Camera.LocY = Camera.LocY + YMove
Camera.LocX = XStart - XMove
for j in range(0,TileCount):
Camera.LocX = Camera.LocX + XMove
Render.EnableDispWin()
context.extensions = True
context.renderPath = Path
#setting thumbsize
context.imageSizeX(thumbsize)
context.imageSizeY(thumbsize)
#could be put into a gui.
context.imageType = Render.PNG
context.enableOversampling(0)
#render
context.render()
#save image
ZasString = '%s' %(int(ZoomLevel))
XasString = '%s' %(int(j+1))
YasString = '%s' %(int((3-i)+1))
context.saveRenderedImage("Z" + ZasString + "X" + XasString + "Y" + YasString)
#close the windows
Render.CloseRenderWindow()
try:
type(Blender.drawmap)
except:
#print 'initialize extern variables'
init()
show_prefs()
This was relatively simple in the end.
I scaled up the model so that 1 tile on the map was 1 grid in blender.
Set the camera to be orthographic.
Set the scale on the camera to 1 for the highest zoom, 4 for the next one, 16 for the next one and so on.
Updated the start coordinates and move values accordingly.