Here are my code that uses instruction from a text file to build an image... the instruction assign a turtle and a direction x and y, for example: 1, 100, 100. Uses the turtle number one this turtle goes to x = 100 and y = 100.
from swampy.TurtleWorld import *
def draw_to(t,x,y,steps):
x_diff = x - t.get_x()
x_step = 1.0*x_diff/steps
y_diff = y - t.get_y()
y_step = 1.0*y_diff/steps
for step in range(steps):
t.fd(x_step)
t.lt()
t.fd(y_step)
t.rt()
def process (s,tlist):
parts = s.split(',')
t = tlist[int(parts[0])-1]
x = int(parts[1])
y = int(parts[2])
draw_to(t,x,y,50)
fturtles = open('turtles.txt','r')
instructions = fturtles.readlines()
fturtles.close()
world = TurtleWorld()
turtle_list = []
num_turtles = int(instructions[0])
for tNum in range(num_turtles):
new_turtle = Turtle(world)
new_turtle.set_delay(0.01)
turtle_list.append(new_turtle)
for lineNum in range(1,len(instructions)):
process(instructions[lineNum],turtle_list)
print "just processed", instructions[lineNum]
wait_for_user()
The code works fine, the problem is i tried to improve the functionality by changing the color of the pen of turtle, for example, in text file if i put : 1,100, 100, red, it will tell the turtle to use the color red. I tried to use that in a new function but i dont have any idea how to do that. If somebody can help me to clarify how to do that, it will be aprecciated.
How about redefining your process() function as follows:
STEPS = 50
# ...
def process(instruction, turtle_list):
index, x, y, color = instruction.split(',')
t = turtle_list[int(index) - 1]
t.set_pen_color(color.strip())
draw_to(t, int(x), int(y), STEPS)
Using a simple turtle.txt file:
3
1, 100, 100, red
2, 100, 0, blue
3, 0, 100, green
I get:
My rework of your code follows but note that I used Python 3 and the turtle module that comes with it, not TurtleWorld, but most things map over fairly well:
import sys
from turtle import *
class TurtleWorld(Turtle):
""" for Turtle World compatibility """
def set_pen_color(self, *args):
return self.pencolor(*args)
def get_x(self): return self.xcor()
def get_y(self): return self.ycor()
STEPS = 50
DELAY = 0
instruction_filename = sys.argv[1]
def draw_to(t, x, y, steps):
x_diff = x - t.get_x()
x_step = x_diff / float(steps)
y_diff = y - t.get_y()
y_step = y_diff / float(steps)
for step in range(steps):
t.fd(x_step)
t.lt(90)
t.fd(y_step)
t.rt(90)
def process(instruction, turtle_list):
index, x, y, color = instruction.split(',')
t = turtle_list[int(index) - 1]
t.set_pen_color(color.strip())
draw_to(t, int(x), int(y), STEPS)
instruction_file = open(instruction_filename)
instructions = instruction_file.readlines()
instruction_file.close()
turtle_list = []
num_turtles = int(instructions[0])
for tNum in range(num_turtles):
new_turtle = TurtleWorld()
turtle_list.append(new_turtle)
delay(DELAY)
for instruction in instructions[1:]:
process(instruction, turtle_list)
print("just processed", instruction)
exitonclick()
Related
Currently my code returns no errors, and generates a weird looking set of points, totally not a Mandelbulb. I've looked over the formulas multiple times and everything seems right, but I could definitely be overlooking something. Any ideas? Just to note, I'm quite inexperienced with Python (I work in Java a lot though so I get the main ideas). Here's my code:
import bpy
import numpy as np
import math
def mandelbulb(x, y, z, iterations):
c = x + y*1j + z*1j
z = c
r = 0
for i in range(iterations):
r2 = x*x + y*y + z*z
if r2 > 2:
return math.sqrt(r2)
theta = math.atan2(math.sqrt(x*x + y*y), z)
phi = math.atan2(y, x)
r = math.sqrt(abs(x*x + y*y + z*z))
x = r*r*r*r * math.cos(4*theta) * math.cos(4*phi) + c.real
y = r*r*r*r * math.cos(4*theta) * math.sin(4*phi) + c.imag
z = r*r*r*r * math.sin(4*theta)
return 0
def generate_mesh(size, iterations):
vertices = []
for x in np.linspace(-2, 2, size):
for y in np.linspace(-2, 2, size):
for z in np.linspace(-2, 2, size):
value = mandelbulb(x, y, z, iterations)
if value >= 2:
vertices.append((x, y, z))
return vertices, []
def create_mesh_object(vertices, faces, name):
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(vertices, [], faces)
mesh.update()
object = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(object)
def execute(size, iterations):
vertices, faces = generate_mesh(size, iterations)
create_mesh_object(vertices, faces, "Mandelbulb")
class MandelbulbOperator(bpy.types.Operator):
bl_idname = "object.mandelbulb_operator"
bl_label = "Mandelbulb Operator"
bl_options = {'REGISTER', 'UNDO'}
size: bpy.props.IntProperty(
name="Size",
default=32,
min=1,
max=256,
step=1
)
iterations: bpy.props.IntProperty(
name="Iterations",
default=64,
min=1,
max=512,
step=1
)
def execute(self, context):
execute(self.size, self.iterations)
return {'FINISHED'}
def draw(self, context):
layout = self.layout
layout.label(text="Create a 3D Mandelbulb")
layout.prop(self, "size")
layout.prop(self, "iterations")
def register():
bpy.utils.register_class(MandelbulbOperator)
def unregister():
bpy.utils.unregister_class(MandelbulbOperator)
if __name__ == "__main__":
register()
I tried messing with values, such as size and iterations but nothing seemed to change the look of the result, and changing the iterations straight up did nothing. I've also tried using variations on the main Mandelbulb formula but to no avail. Any suggestions are welcome.
I'm trying to learn and understand Inverse Kinematics by making it in PyGame. I've made a Bone class that has members a which is a PyGame Vector2 an angle and length. Finally it has a property b which is the calculated based on the previous 3 members.
In code it's like this:
import math
from pygame import Vector2
class Bone():
def __init__(self, x: float, y: float, length: float) -> None:
self.a = Vector2(x, y)
self.angle = 0
self.length = length
#property
def b(self):
return Vector2(self.a.x + self.length * math.cos(self.angle),
self.a.y + self.length * math.sin(self.angle))
def rotate_and_translate(self, target: Vector2):
dir = target - self.a
self.angle = math.atan2(dir.y, dir.x)
#???
self.a.update(target.x + dir.x - self.length * np.cos(self.angle),target.y + dir.y - self.length * np.sin(self.angle))
#???
print(f'dir: {dir}, dir_mag: {dir.magnitude()}, target + dir: {target + dir}, a: {self.a}')
def rotate(self, target: Vector2):
"""
a(x1,y1) b(x2, y2)
x-----------x
\ alpha
\
\ target - a
\
\
x(target)
"""
dir = target - self.a
self.angle = math.atan2(dir.y, dir.x)
The main program looks like so:
import sys, pygame
from bone import Bone
from pygame.math import Vector2
pygame.init()
shape = width, height = 1500, 850
screen = pygame.display.set_mode(shape)
def draw(bones: list[Bone], target: Vector2):
black = 0, 0, 0
white = 255, 255, 255
screen.fill(white)
for bone in bones:
pygame.draw.aaline(screen, black, bone.a, bone.b)
pygame.draw.circle(screen, black, (int(target[0]), int(target[1])), 2)
pygame.display.flip()
def IK(bones: list[Bone], target: Vector2):
i = len(bones) - 2
bones[-1].rotate_and_translate(target)
while i >= 0:
if i != 0:
bones[i].rotate_and_translate(bones[i + 1].a)
else:
bones[i].rotate(bones[i + 1].a)
i -= 1
return bones
def main():
bones = []
root = Bone(width / 2, height / 2, 100)
bones.append(root)
#for i in range(1, 1):
# bones.append(Bone(bones[i - 1].b.x, bones[i - 1].b.y, 100))
while 1:
target = Vector2(pygame.mouse.get_pos())
bones = IK(bones, target)
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
draw(bones, target)
if __name__ == "__main__":
main()
To summarize, I instantiate the bones (currently just 1) and am trying to get it to both rotate and translate so that its b property is on the target. As I understand it, every bone except the root can rotate_and_translate(), while the root can only rotate().
Currently only the rotation is working as intended and I'm a bit stumped on how to rotate and translate properly.
The closest I got to the answer was the bone following the point, but the angle was fixed and it would never rotate.
This is all the code there is for now. As always any and all advice is appreciated.
EDIT:
I added the self.a.update() line into rotate_and_translate() which yields behaviour somewhat close to what I want but it's x and y values constantly flip between a set of 2 values at every point...
OK, so in my infinite silliness I was using the correct formula the wrong way.
Basically, the way I want the bone to behave, b would equate to the target. and b is calculated like so:
Vector2(self.a.x + self.length * np.cos(self.angle),
self.a.y + self.length * np.sin(self.angle))
Which reliably yields a point that is a fixed distance away from a at all times.
So I just assumed that it'd make sense to use the same formula to calculate the new a aswell and I was right. The problem was that I foolishly thought id have to factor in the coordinates of dir when calculating a new a, which was a mistake since dir is the difference between target and a which then yields the angle through arctan2. All I needed to do was remove the + dir.x and + dir.y from the formula and it worked like a charm:
self.a.update(target.x - self.length * np.cos(self.angle),
target.y - self.length * np.sin(self.angle))
Here I have made a code to create random sized bubbles which can be destroyed by collision of another object:
import tkinter
window = tkinter.Tk()
window.title("...")
c = tkinter.Canvas(width=800, height=500, bg="...")
ojct_id1 = c.create_polygon(...)
ojct_id2 = c.create_oval(...) # A polygon in an oval should constitute the object
def move ojct(event):
...
from random import randint
bubbles = list()
bubbles_r = list() # radius
bubbles_speed = list()
def create_bub():
...
def move_bubbles():
...
from time import sleep
while True:
if randint(1, 10) == 1:
create_bub()
move_bubbles()
window.update()
sleep(0.01)
The following code determines the position of any bubble:That helps to find out collision.
def hole_coord(id_num):
pos = c.coords(id_num)
x = (pos[0] + pos[2])/2
y = (pos[1] + pos[3])/2
return x, y
Now I have to make func. for deleting bubbles:
def del_bubbles():
del bubbles_r[i]
del bubbles_speed[i]
c.delete(bubbles[i])
del bubbles[i]
The following code determines, if the two objects are colliding:
from math import sqrt
def distance(id1, id2):
x1, y1 = hole_coord(id1)
x2, y2 = hole_coord(id2)
return sqrt((x2 - x1)/2 + (y2 - y1)/2)
def collision():
for bub in range(len(bubbles)-1, -1, -1):
if distance(ojct_id2, bubbles[bub]) < (15 + bubbles_r[bub]):
del_bubbles(bub)
Here it is sth. wrong: bubbles get deleted without a hit but if they are hit
often they don't get deleted. Can anybody help me? Thanks!
You are not computing the euclidean distance correctly.
def distance(id1, id2):
x1, y1 = hole_coord(id1)
x2, y2 = hole_coord(id2)
return sqrt((x2 - x1)/2 + (y2 - y1)/2) # <----- this is wrong
should be
def distance(id1, id2):
x1, y1 = hole_coord(id1)
x2, y2 = hole_coord(id2)
return sqrt((x2 - x1)**2 + (y2 - y1)**2) # <----- square instead of halve
I've found some flaky resources online about what to do when a matplotlib animation crashes Python.
Here is the code. I know that certain changes to the number of points or smallness of the dt variable might cause some overwhelming computation, but I could really use some help. Overall it behaves extremely slowly and I need to have this running smoothly. The code is for a physics class and it is not an optimization problem - the goal of the project is not to optimize matplotlib's animation facilities but to model a system in phase space. I could use any help I can get.
import matplotlib
#matplotlib.use("TkAgg")
from matplotlib import animation
import matplotlib.pyplot as plt
import matplotlib.pylab as pl
import numpy as np
import math
# Create the window and the plot.
fig = plt.figure()
fig.canvas.set_window_title("Modelling Non-Linear Chaotic Systems in Phase ")
ax = fig.add_subplot(111)
##### CONSTANTS #####
NUM_POINTS = 40 # The number of points to discretize.
AUTOSCALE = False # Sets autoscale to true or false. If true, there will be odd (expected to a degree) behavior as time goes on.
NO_TRAIL = False # Adds a trail.
##### CONSTANTS #####
##### Cool Settings #####
# Double tail swirl.
# k = .2
# alpha = .4
# dt = .1
##### #####
##### VARIABLES #####
m = 1 # mass constant
k = 5 # spring constant
alpha = .3 # stretch/deformation constant
dt = .01 # change in time
interval = 100 # interval in milliseconds between each animation
##### VARIABLES #####
class Point():
def x():
return self.x
def y():
return self.y
def pos(xy):
self.x=xy[0]
self.y=xy[1]
# initial_pos is a tuple
def __init__(self, initial_pos):
self.initial_position = initial_pos
self._x = initial_pos[0]
self._y = initial_pos[1]
self.x = self._x
self.y = self._y
def evolve(x_map, y_map, l):
return [Point([x_map(el), y_map(el)]) for el in l]
"""
Lagrangian
L = T - V = .5dq^2 - .5kq^2 - .333alpha*q^3
p = mdq; dx = p/m
Hamiltonian
H = p^2/m - L
H = p^2/m - p^2/2m + .5kq^2 + .333alpha*q^3
dp = -partial(H)/partial(q) = -kq - alpha*q^2
dx = partial(H)/partial(p) = p/m
"""
def time_dependent_funcs(name, dt):
### This is the adjustment of p over time. ###
def p_map(point):
p = point.y
q = point.x
try:
dp = -1*k*q-alpha*q**2
ddp = -k*p/m-alpha*q*p/m
return p+dp*dt+ddp*dt**2
except:
return p
### End adjustment of p. ###
### This is the adjustment of q over time. ###
def q_map(point):
q = point.x
p = point.y
try:
dq = p/m
dp = -1*k*q-alpha*q**2
ddp = -k*p/m-alpha*q*p/m
return q+dq*dt+ddp*dt**2/m
except:
return q
### End adjustment of q. ###
if name == "p_map":
return p_map
elif name == "q_map":
return q_map
# Used this post to help create this function: http://stackoverflow.com/questions/14619876/how-do-i-generate-pair-of-random-points-in-a-circle-using-matlab
def circle(r, n):
l = []
for i in range(n):
x=r+1 # necessary to enter loop
y=r+1 # necessary to enter loop
while (x**2 + y**2) > r**2:
x = 2*r*np.random.randn()
y = 2*r*np.random.randn()
l.append(Point([x,y]))
return l
### DOESN'T CURRENTLY WORK
def square(h, n):
l = []
for i in range(n):
x=h+1 # necessary to enter loop
y=h+1 # necessary to enter loop
while x < h and y < h:
x = np.random.randn()
y = np.random.randn()
l.append(Point([x,y]))
return l
def rand(n):
return [Point([np.random.randn(),np.random.randn()]) for i in range(n)]
def x(l):
return [el.x for el in l]
def y(l):
return [el.y for el in l]
#list_of_points = rand(NUM_POINTS) # works
#list_of_points = square(.2, 400) # doesn't currently work
list_of_points = circle(20,NUM_POINTS) # need this to be a global
def init():
global list_of_points, dt
scat = ax.scatter(x(list_of_points), y(list_of_points),color="blue", animated=NO_TRAIL)
if NO_TRAIL:
return scat,
def animate(i):
global list_of_points, dt
map_p = time_dependent_funcs("p_map", dt)
map_q = time_dependent_funcs("q_map", dt)
### evolve the points ###
list_of_points = evolve(map_q, map_p, list_of_points)
scat = ax.scatter(x(list_of_points), y(list_of_points), color="blue",lw=2, animated=NO_TRAIL)
if NO_TRAIL:
return scat,
### Animates the figure fig by executing init_func init (initially) followed by animation function
### animate for 10 frames at an interval of 100ms all the while erasing the last animation (blit=True).
ani = animation.FuncAnimation(fig, animate, init_func=init, frames = 100, interval=interval,blit=NO_TRAIL,save_count=0)
if not AUTOSCALE:
plt.autoscale(enable=False)
plt.show()
I am trying to create a solution to this problem, with my code focusing on looping(for and while):
Let parameter Q be a list of "rectangles", specified by width, height,
and (x,y)-location of the lower left corner. Enclosure(Q) returns the
smallest rectangle that contains each rectangle in Q . The way a
rectangle is represented is by tuple, (x,y,width,height).
Here is my code so far:
def Enclosure(Q):
c = []
d = []
for (x,y,width,height) in sorted(Q):
c.append(x)
d.append(y)
print(c)
print(min(c))
e=tuple([min(c)]+[min(d)])
print(e)
Ignore the print statements, those are only there for debugging purposes. My code to this point creates a tuple of the (x,y) coordinates of the lower left corner of the enclosing rectangle that I am trying to have the program form. But after this point, I have absolutely no idea on how to find the (height,width) of the enclosing rectangle. How can I do that?
Also, here is an example of the program should do when it runs:
R1 = (10,20,5,100) #R1,R2,R3 are each rectangles
R2 = (15,5,30,150) #layout of the tuple:(x,y,width,height)
R3 = (-4,30,20,17)
Enclosure([R1,R2,R3])
(-4, 5, 49, 150) #rectangle that encloses R1,R2,R3
Try this:
def Enclosure(Q):
c = []
d = []
x2 = []
y2 = []
for (x,y,width,height) in sorted(Q):
c.append(x)
d.append(y)
x2.append(width + x)
y2.append(height + y)
e = tuple([min(c)]+[min(d)] + [max(x2) - min(c)] + [max(y2) - min(d)])
print(e)
You could replace e = tuple... to:
e=(min(c), min(d), max(x2) - min(c), max(y2) - min(d)) # This makes a tuple directly
to avoid making first a list, and converting it to tuple as you did.
Make sure you can explain why you used inheritance or your teacher will know you are cheating:
class Geometry(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Point(Geometry):
def __repr__(self):
return "<Point at {s.x},{s.y}>".format(s=self)
class Rectangle(Geometry):
def __init__(self, x, y, width, height):
super(Rectangle, self).__init__(x, y)
self.width = width
self.height = height
#property
def oposite_corner(self):
return Point(self.x + self.width, self.y + self.height)
def __repr__(self):
return "<Rectange of {s.width}x{s.height} at {s.x},{s.y}>".format(s=self)
def enclosing_rectangle(rect_list):
x1, y1, x2, y2 = (
min([r.x for r in rect_list]),
min([r.y for r in rect_list]),
max([r.oposite_corner.x for r in rect_list]),
max([r.oposite_corner.y for r in rect_list]),
)
return Rectangle(x1, y1, x2 - x1, y2 - y1)
Please test and fix any bug by yourself (hint: super changed):
>>> l = [Rectangle(1, 2, 3, 4), Rectangle(-1, -1, 1, 1), Rectangle(3, 4, 1, 1)]
>>> enclosing_rectangle(l)
<Rectangle of 5x7 at -1,-1>
[update]
What?!? A delete vote? Care to explain what is so offensive with this answer?