Why's the red polygon goes out of plane, then returns to its specified place again? - python-3.x

I want to put the red polygon in place of the empty one. But it goes above it first before returning again to it. Can someone help me with that?
Why's the red polygon goes out of plane, then returns to its specified place again?
def Rotating(Rotating_angle, polygon_points): # Drawing the rotated figure
my_points = (re.findall("\(\-?\d*\.?\d*\,\-?\d*\.?\d*\)", polygon_points))
sleep_time = .5
my_new_points = [] # Scale_points
for point in my_points:
new_point = str(point).replace(")", "").replace("(", "").split(",")
# creating a list with all coordinates components
all_coordinates_components = []
all_coordinates_components.append(abs(eval(new_point[0])))
all_coordinates_components.append(abs(eval(new_point[1])))
point = (scale * eval(new_point[0]), scale * eval(new_point[1]))
my_new_points.append(point)
rotated_points = []
for point in my_new_points:
new_point = str(point).replace(")", "").replace("(", "").split(",")
theta = Rotating_angle
X = (eval(new_point[0]) * cos(theta * pi / 180)) - (eval(new_point[1]) * sin(theta * pi / 180))
Y = (eval(new_point[0]) * sin(theta * pi / 180)) + (eval(new_point[1]) * cos(theta * pi / 180))
# length = sqrt((X) ** 2 + (Y) ** 2)
point = (X, Y)
rotated_points.append(point)
# draw steps
time.sleep(sleep_time)
draw_rotation_steps(my_new_points, theta) # draw steps ((((( 3 )))))
# drawing rotated polygon
draw_polygon(rotated_points) # draw rotated polygon ((((( 4 )))))
s = Shape('compound')
poly1 = (my_new_points)
s.addcomponent(poly1, fill="red")
register_shape('myshape', s)
shape('myshape')
polygon = Turtle(visible=False)
polygon.setheading(90)
polygon.speed('slowest')
polygon.penup()
polygon.shape('myshape')
polygon.st()
polygon.circle(0, theta)
pen_dot = Turtle(visible=False)
pen_dot.speed('fastest')
for point in rotated_points:
pen_dot.penup()
pen_dot.goto(point)
pen_dot.pendown()
pen_dot.dot(5, 'blue violet')

I can't reproduce the behaviour you describe. But your code is riddled with issues that should be addressed so perhaps fixing those might also fix the positioning issue:
These loops are nested, but they shouldn't be:
my_new_points = []
for point in my_points:
...
rotated_points = []
for point in my_new_points:
They both should be at the same level.
You shouldn't use eval(). In this situation, use float():
point = (scale * eval(new_point[0]), scale * eval(new_point[1]))
Here, you've already converted the points but you turn them back into strings and reconvert them:
new_point = str(point).replace(")", "").replace("(", "").split(",")
X = (eval(new_point[0]) * cos(theta * pi / 180)) - (eval(new_point[1]) * sin(theta * pi / 180))
when you can simply do:
X = point[0] * cos(theta * pi / 180) - point[1] * sin(theta * pi / 180)
You don't have to put the pen down for the .dot() method to work:
pen_dot.goto(point)
pen_dot.pendown()
pen_dot.dot(5, 'blue violet')
so you can move the penup() out of the loop.
Below is my rework of your example code. I've added just enough code to make it runnable and removed anything that had nothing to do with the problem. See if this gives you any ideas of how to simplify and fix your own code:
import re
from math import sin, cos, pi
from turtle import *
scale = 20
def draw_rotation_steps(points, theta):
''' Not supplied by OP '''
pass
def draw_polygon(rotated_points):
''' Simple replacement since not supplied by OP '''
hideturtle()
penup()
goto(rotated_points[-1])
pendown()
for point in rotated_points:
goto(point)
def Rotating(theta, polygon_points): # Drawing the rotated figure
my_points = re.findall(r"\(\-?\d*\.?\d*\,\-?\d*\.?\d*\)", polygon_points)
my_new_points = [] # Scaled points
for point in my_points:
X, Y = point.replace(")", "").replace("(", "").split(",")
point = (scale * float(X), scale * float(Y))
my_new_points.append(point)
rotated_points = []
for point in my_new_points:
X = point[0] * cos(theta * pi / 180) - point[1] * sin(theta * pi / 180)
Y = point[0] * sin(theta * pi / 180) + point[1] * cos(theta * pi / 180)
point = (X, Y)
rotated_points.append(point)
# draw steps
draw_rotation_steps(my_new_points, theta) # draw steps
# drawing rotated polygon
draw_polygon(rotated_points) # draw rotated polygon
s = Shape('compound')
s.addcomponent(my_new_points, fill="red")
register_shape('myshape', s)
polygon = Turtle('myshape', visible=False)
polygon.setheading(90)
polygon.showturtle()
polygon.circle(0, theta, steps=100) # added steps to visually slow it down
pen_dot = Turtle(visible=False)
pen_dot.penup()
for point in rotated_points:
pen_dot.goto(point)
pen_dot.dot(5, 'blue violet')
Rotating(180, "(-8,-6) (-6,-3) (-3,-4)")
mainloop()

Related

How change the spiral movement in 2D space?

I have two points in 2D space as we can see in the figure to move from the blue point to the red points we can use the equation (1). Where b is a constant used to limit the shape of the logarithmic spiral, l is a random number in [−1,1], which is used to
control the indentation effect of the movement, D indicates the distance between blue points and the current point
I need another movement that can move from blue points to the red points like in the figure
You can use sinusoidal model.
For start point (X0, Y0) and end point (X1,Y1) we have vector end-start, determine it's length - distance between points L, and angle of vector Fi (using atan2).
Then generate sinusoidal curve for some standard situation - for example, along OX axis, with magnitude A, N periods for distance 2 * Pi * N:
Scaled sinusoid in intermediate point with parameter t, where t is in range 0..1 (t=0 corresponds to start point (X0,Y0))
X(t) = t * L
Y(t) = A * Sin(2 * N * Pi * t)
Then shift and rotate sinusoid using X and Y calculated above
X_result = X0 + X * Cos(Fi) - Y * Sin(Fi)
Y_result = Y0 + X * Sin(Fi) + Y * Cos(Fi)
Example Python code:
import math
x0 = 100
y0 = 100
x1 = 400
y1 = 200
nperiods = 4
amp = 120
nsteps = 20
leng = math.hypot(x1 - x0, y1 - y0)
an = math.atan2(y1 - y0, x1 - x0)
arg = 2 * nperiods* math.pi
points = []
for t in range(1, nsteps + 1):
r = t / nsteps
xx = r * leng
yy = amp * math.sin(arg * r)
rx = x0 + xx * math.cos(an) - yy * math.sin(an)
ry = y0 + xx * math.sin(an) + yy * math.cos(an)
points.append([rx, ry])
print(points)
Draw points:

Random function in python to generate random pair inside a circle

In python how to generate a random pair of points (x,y) that lies inside a circle of radius r.
Basically the x and y should satisfy the condition x^2 + y^2 = r^2.
To generate uniformly distributed point inside origin-centered circle of radius r, you can generate two uniform values t,u in range 0..1 and use the next formula:
import math, random
r = 4
t = random.random()
u = random.random()
x = r * math.sqrt(t) * math.cos(2 * math.pi * u)
y = r * math.sqrt(t) * math.sin(2 * math.pi * u)
print (x,y)
Using numpy to generate more than one point at a time:
import numpy as np
import matplotlib.pyplot as plt
n_samples = 1000
r = 4
# make a simple unit circle
theta = np.linspace(0, 2*np.pi, n_samples)
a, b = r * np.cos(theta), r * np.sin(theta)
t = np.random.uniform(0, 1, size=n_samples)
u = np.random.uniform(0, 1, size=n_samples)
x = r*np.sqrt(t) * np.cos(2*np.pi*u)
y = r*np.sqrt(t) * np.sin(2*np.pi*u)
# Plotting
plt.figure(figsize=(7,7))
plt.plot(a, b, linestyle='-', linewidth=2, label='Circle', color='red')
plt.scatter(x, y, marker='o', label='Samples')
plt.ylim([-r*1.5,r*1.5])
plt.xlim([-r*1.5,r*1.5])
plt.grid()
plt.legend(loc='upper right')
plt.show(block=True)
which results in:

Animating multiple Circles in each frames in Python

I am trying to create the animation in this video using Python. But I stuck on the very first step. Till now I've created a Circle and a point rotating around its circumference. My code is given below. Now I want to plot the y values corresponding to x=np.arange(0, I*np.pi, 0.01) along the x-axis (as shown in update() function in the code). For this I have to define another function to plot these x and y and pass that function inside a new animation.FuncAnimation().
Is there any way to plot everything using only the update() function?
Note I have found a code of this animation in here. But it is written in Java!
My Code
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
W = 6.5
H = 2
radius = 1
I = 2
T = 3
N = 2
plt.style.use(['ggplot', 'dark_background'])
def create_circle(x, y, r):
circle = plt.Circle((x, y), radius=r, fill=False, alpha=0.7, color='w')
return circle
def create_animation():
fig = plt.figure()
ax = plt.axes(xlim=(-2, W + 2), ylim=(-H, H))
circle = create_circle(0, 0, radius)
ax.add_patch(circle)
line1, = ax.plot(0, 1, marker='o', markersize=3, color='pink', alpha=0.7)
def update(theta):
x = radius * np.cos(theta)
y = radius * np.sin(theta)
line1.set_data([0, x], [0, y])
return line1,
anim = []
anim.append(animation.FuncAnimation(fig, update,
frames=np.arange(0, I * np.pi, 0.01),
interval=10, repeat=True))
# anim.append(animation.FuncAnimation(fig, update_line, len(x),
# fargs=[x, y, line, line1], interval=10))
plt.grid(False)
plt.gca().set_aspect('equal')
plt.gca().spines['left'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['bottom'].set_visible(False)
plt.gca().set_xticks([])
plt.gca().set_yticks([])
plt.show()
if __name__ == '__main__':
create_animation()
Edit. I've improved the task by defining a global variable pos and changing the update() function in the following manner ...The animation now looks better but still having bugs!
Improved Portion
plot, = ax.plot([], [], color='w', alpha=0.7)
level = np.arange(0, I * np.pi, 0.01)
num = []
frames = []
for key, v in enumerate(level):
num.append(key)
frames.append(v)
def update(theta):
global pos
x = radius * np.cos(theta)
y = radius * np.sin(theta)
wave.append(y)
plot.set_data(np.flip(level[:pos] + T), wave[:pos])
line1.set_data([0, x], [0, y])
pos += 1
return line1, plot,
Edit Till now I've done the following:
def update(theta):
global pos
x, y = 0, 0
for i in range(N):
prev_x = x
prev_y = y
n = 2 * i + 1
rad = radius * (4 / (n * np.pi))
x += rad * np.cos(n * theta)
y += rad * np.sin(n * theta)
wave.append(y)
circle = create_circle(prev_x, prev_y, rad)
ax.add_patch(circle)
plot.set_data(np.flip(level[:pos] + T), wave[:pos])
line2.set_data([x, T], [y, y])
line1.set_data([prev_x, x], [prev_y, y])
pos += 1
return line1, plot, line2,
Output
Please help to correct this animation. Or, is there any efficient way to do this animation?
Edit Well, now the animation is partially working. But there is a little issue: In my code (inside the definition of update()) I have to add circles centered at (prev_x, prev_y) of radius defined as rad for each frame. For this reason I try to use a for loop in the definition of update() but then all the circles remains in the figure (see the output below). But I want one circle in each frame with the centre and radius as mentioned above. Also the same problem is with the plot. I try to use ax.clear() inside the for loop but it didn't work.

(Tkinter, py3) How to make a rotation animation?

I want to rotate an oval around it's center. Currently I can display the static object witohut rotation, and I can't seem to find what to do wit it.
EDIT: I made a rotation function based on complex number multiplication, which seemed to work on lower polygons but the ellipse kinda looks the same.
A potato-level noob C.S. student.
also, the code:
from tkinter import*
import cmath, math
import time
def poly_rot(tup, deg):
rad=deg*0.0174533
crot=cmath.exp(rad*1j)
rotpol=[]
i=0
while i < len(tup):
x=tup[i]
y=tup[i+1]
z=crot*complex(x,y)
rotpol.append(400+z.real)
rotpol.append(400+z.imag)
i=i+2
return rotpol
def poly_oval(x0,y0, x1,y1, steps=60, rotation=0):
"""return an oval as coordinates suitable for create_polygon"""
# x0,y0,x1,y1 are as create_oval
# rotation is in degrees anti-clockwise, convert to radians
rotation = rotation * math.pi / 180.0
# major and minor axes
a = (x1 - x0) / 2.0
b = (y1 - y0) / 2.0
# center
xc = x0 + a
yc = y0 + b
point_list = []
# create the oval as a list of points
for i in range(steps):
# Calculate the angle for this step
# 360 degrees == 2 pi radians
theta = (math.pi * 2) * (float(i) / steps)
x1 = a * math.cos(theta)
y1 = b * math.sin(theta)
# rotate x, y
x = (x1 * math.cos(rotation)) + (y1 * math.sin(rotation))
y = (y1 * math.cos(rotation)) - (x1 * math.sin(rotation))
point_list.append(round(x + xc))
point_list.append(round(y + yc))
return point_list
inp= input("We need an ellipse. One to fit in a 800*800 window. Give the size of it's axes separated by ','-s (ex: lx,ly)!\n")
inpu= inp.split(',')
lx=int(inpu[0])
ly=int(inpu[1])
x0=400-lx//2
x1=400+lx//2
y0=400-ly//2
y1=400+ly//2
deg= float(input("Let's rotate this ellipse! But how much, in degrees, should we?"))
pre=poly_oval(x0, y0, x1, y1)
post=poly_rot(poly_oval(x0, y0, x1, y1), deg)
root =Tk()
w = Canvas(root, width=801, height=801)
w.config(background="dark green")
w.pack()
w.create_polygon(tuple(post), fill="yellow", outline="yellow" )
root.mainloop()

Turtle inner circle boundary in python

Okay, I've been at this all day and haven't a clue. I need to get my turtle object to draw random lines outside of a circle.
I've made code that restricts the random lines within the boundaries before, so I thought all I had to do was change the sign, but that didn't work. I'm not allowed to use coordinate geometry - it has to be something more basic...
Here's my code in it's current format:
import turtle, random
mRoshi = turtle.Turtle()
def draw_any_shape(myTurtle, sideLength, numSides):
turnAng = 360/numSides
for i in range(numSides):
myTurtle.forward(sideLength)
myTurtle.right(turnAng)
def drawCircle(myTurtle, radius, startX, startY):
circumference = 2*3.1415*radius
sideLength = circumference/360
myTurtle.penup()
myTurtle.goto(startX, startY)
#myTurtle.dot()
myTurtle.goto(startX, startY+radius)
myTurtle.pendown()
draw_any_shape(myTurtle, sideLength, 360)
def stumblingTurtle(myTurtle, radius, startX, startY, paramN5):
circumference = 2*3.1415*radius
myTurtle.speed(6)
drawCircle(myTurtle, radius, startX, startY)
myTurtle.penup()
for i in range(paramN5):
drx = random.randint(-800, 800)
drw = random.randint(-800, 800)
if (drx**2 + drw**2) > radius**2:
myTurtle.goto(drx,drw)
crx = random.randint(-800, 800)
crw = random.randint(-800, 800)
xdif = crx-drx
ydif = crw-drw
for j in range(drx, crx):
for k in range(drw, crw):
if (xdif**2 + ydif**2) > radius**2:
myTurtle.goto(crx,crw)
Does this do what you want? It's also based on code that originally kept the turtle within a circle. It uses Python3 turtle's undo capability to allow the turtle to accidentally wander into the circle and then undo that accident as if it never happened:
import turtle
import random
RADIUS = 50
MAXIMUM_TURN = 45
STEP_SIZE = 10
BORDER = 20
def bounded_random_move():
yertle.forward(STEP_SIZE)
x, y = yertle.position()
if (x * x + y * y) < RADIUS * RADIUS or x < -window_width/2 or x > window_width/2 or y < -window_height/2 or y > window_height/2:
yertle.undo() # undo misstep
turn = random.randint(180 - MAXIMUM_TURN, 180 + MAXIMUM_TURN)
yertle.left(turn)
turtle.ontimer(bounded_random_move, 100)
turtle.setup(RADIUS * 10, RADIUS * 10)
window_width = turtle.window_width() - BORDER
window_height = turtle.window_height() - BORDER
magic_marker = turtle.Turtle(visible=False)
magic_marker.penup()
magic_marker.color("red")
magic_marker.sety(-RADIUS)
magic_marker.pendown()
magic_marker.circle(RADIUS)
yertle = turtle.Turtle(shape="turtle", visible=False)
yertle.speed("fastest")
yertle.penup()
yertle.goto(RADIUS * 2, RADIUS * 2) # start outside circle
yertle.pendown()
yertle.showturtle()
turtle.ontimer(bounded_random_move, 100)
turtle.exitonclick()
My undo trick might not be rigorous enough for everyone, however.

Resources