Moving circle from point A to B - python

I need to make the blue circle move in a straight line with animation.
The straight line code needs to stay as is. I just can't figure out the code for object animation.
The circle can be in any shape and colour it just need to move from point A to point B in a straight line.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt, patches
img=np.ones((200,200,3))
c=plt.Circle((50, 100))
def DrawLine(x1,y1,x2,y2):
dx = abs(x2-x1)
dy = abs(y2-y1)
if x1<x2:
xs=1
else:
xs=-1
if y1<y2:
ys=1
else:
ys=-1
x=x1
y=y1
p=2*dy-dx
if dx>dy:
while x!=x2:
x=x+xs
if p > 0:
y=y+ys
p=p+2*dy-2*dx
else:
p=p+2*dy
img[y,x]= 0
DrawLine(150,100,50,100)
fig = plt.figure()
plt.imshow(img)
plt.gca().add_artist(c)
plt.show()

Matplotlib has animations for this purpose:
import numpy as np
from matplotlib import pyplot as plt, animation
img = np.ones((200, 200, 3))
def DrawLine(x1, y1, x2, y2):
dx = abs(x2 - x1)
dy = abs(y2 - y1)
if x1 < x2:
xs = 1
else:
xs = -1
if y1 < y2:
ys = 1
else:
ys = -1
x = x1
y = y1
p = 2 * dy - dx
if dx > dy:
while x != x2:
x = x + xs
if p > 0:
y = y + ys
p = p + 2 * dy - 2 * dx
else:
p = p + 2 * dy
img[y, x] = 0
DrawLine(150, 100, 50, 100)
fig, ax = plt.subplots()
ax.imshow(img)
# define animation function
def animate(i):
c = plt.Circle((50+i % 100, 100))
circle = ax.add_artist(c)
return circle,
# define animation properties, see
# https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html
ani = animation.FuncAnimation(fig, animate, interval=20, blit=True)
plt.show()

Related

Simulate a rotating equal triangle by Python

can anyone help me, i stuck at the last step
[]
this is my code. then for the last step to rotate it, i didnt know what should i do to rotate the triangle
This is the perfect case for an animation:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
from matplotlib.animation import FuncAnimation
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
to=np.arange(0,2*np.pi,0.01)
x = r * np.cos(np.radians(theta))
y = r * np.sin(np.radians(theta))
xo = r * np.cos(to); yo = r * np.sin(to)
fig, ax = plt.subplots()
ax.plot(xo,yo)
# create artists: they will be used to update the position
# of the points being rendered
triangle, = ax.plot(x,y)
vertices = ax.scatter(x,y)
lim = r * 1.25
ax.set_xlim([-lim, lim]);ax.set_ylim([-lim, lim])
ax.set_aspect("equal")
w = 2
T = 2 * np.pi / w
# this defines the time steps of the animation
dt = np.linspace(0, 10 * T, num=500)
def animate(i):
x = r * np.cos(np.radians(theta) + w * dt[i])
y = r * np.sin(np.radians(theta) + w * dt[i])
# update the position of the points to be rendered
triangle.set_data(x, y)
vertices.set_offsets(np.stack([x, y]).T)
ax.set_title("Rotation #%s" % int(w * dt[i] / (2 * np.pi) + 1))
ani = FuncAnimation(fig, animate, frames=len(dt), repeat=False)
plt.show()
Check this out..
from IPython import display
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
w = 2
T = 2*np.pi/w
dt = np.linspace(0, 10*T, num=10) #increase num for more finely distributed rotations.
for d in dt:
to=np.arange(0,2*np.pi,0.01)
x = r*np.sin(np.radians(theta + d))
y=r*np.cos(np.radians(theta + d))
xo=r*np.sin(to);yo=r*np.cos(to)
plt.plot(xo,yo)
plt.plot(x,y)
plt.scatter(x,y)
plt.xlim([-1, 1]);plt.ylim([-1,1])

Pyplot how to plot math art

How would one plot these circle structures:
https://blogs.scientificamerican.com/guest-blog/making-mathematical-art/
in pyplot? I tried this:
x = np.arange(1,11)
def f(x):
return np.cos((10*np.pi*x)/14000)*(1-(1/2)*(np.square(np.cos((16*np.pi*x)/16000))))
def z(x):
return np.sin((10*np.pi*x)/14000)*(1-(1/2)*(np.square(np.cos((16*np.pi*x)/16000))))
def w(x):
return 1/200 + 1/10*np.power((np.sin(52*np.pi*x)/14000),4)
plt.ylim(-10, 10)
plt.title("Matplotlib demo")
plt.xlabel("x axis caption")
plt.ylabel("y axis caption")
x1=np.linspace(0,14000)
results=f(x1)
results2 = z(x1)
results3 = w(x1)
plt.plot(results)
plt.plot(results2)
plt.plot(results3)
plt.show()
But only get this:
Take the first example in the reported link:
So you have to do a for loop with k from 1 to N = 14000, in each iteration you draw a circle of radius R and center in (X, Y) defined in the above equations:
N = 14000
for k in range(1, N + 1):
X = cos(10*pi*k/N)*(1 - 1/2*(cos(16*pi*k/N))**2)
Y = sin(10*pi*k/N)*(1 - 1/2*(cos(16*pi*k/N))**2)
R = 1/200 + 1/10*(sin(52*pi*k/N))**4
At this point you have the coordinates of the circle's center and its radius, but not the circle iteself yet, so you you have to compute it. First of all you have to define an angle theta from 0 to 2*pi, then compute the cirle's points with:
N = 14000
theta = np.linspace(0, 2*pi, 361)
for k in range(1, N + 1):
X = cos(10*pi*k/N)*(1 - 1/2*(cos(16*pi*k/N))**2)
Y = sin(10*pi*k/N)*(1 - 1/2*(cos(16*pi*k/N))**2)
R = 1/200 + 1/10*(sin(52*pi*k/N))**4
x = R*np.cos(theta) + X
y = R*np.sin(theta) + Y
Finally, you can draw the circles in each iteration.
Complete code
import numpy as np
import matplotlib.pyplot as plt
from math import sin, cos, pi
N = 14000
theta = np.linspace(0, 2*pi, 361)
fig, ax = plt.subplots(figsize = (10, 10))
for k in range(1, N + 1):
X = cos(10*pi*k/N)*(1 - 1/2*(cos(16*pi*k/N))**2)
Y = sin(10*pi*k/N)*(1 - 1/2*(cos(16*pi*k/N))**2)
R = 1/200 + 1/10*(sin(52*pi*k/N))**4
x = R*np.cos(theta) + X
y = R*np.sin(theta) + Y
ax.plot(x, y, color = 'blue', linewidth = 0.1)
plt.show()

Python only plots last curve in a loop

I have a curve that I want to rotate along the z-axis N times in a loop, and each time I want to plot it to the same figure. However I only get the last curve overdrawn multiple times. If instead, I use different figures in every iteration I get the expected result. Where is the mistake? This is the code, the comments are to test creating new figures in each iteration:
o = 2*pi/N
for m in range(N):
#fig = plt.figure()
#ax = fig.add_subplot(111, projection='3d')
#ax.view_init(45,)
#fig.set_size_inches(10,10)
for n in range(len(x1)):
x1[n],y1[n] = cos(o)*x1[n] - sin(o)*y1[n], sin(o)*x1[n] + cos(o)*y1[n]
ax.plot(x1,y1,z1,'k')
#plt.show()
This is what I want more or less, that I've achieved using a diferent method:
but instead i get:
Here is how I calculate x1,y1,z1 if someone wants to test it
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from numpy import array, linspace
from math import pi, cos, sin, atan2, sqrt
def pltcono(xo,yo,a):
N = 100
x1 = []
y1 = []
z1 = []
for t in linspace(0,1,N):
x = (xo[1]-xo[0])*t + xo[0]
y = (yo[1]-yo[0])*t + yo[0]
r = sqrt(x**2 + y**2)
if (r > 1.0000000001):
return x1,y1,z1
o = atan2(y,x)
x1 += [a*r/(2*pi)*cos(2*pi*o/a)]
y1 += [a*r/(2*pi)*sin(2*pi*o/a)]
z1 += [-r*sqrt(1-(a/(2*pi))**2)]
return x1,y1,z1
def cono(a):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.view_init(45,)
fig.set_size_inches(10,10)
o = a/2
r = 1
N = 10
p = a/10
x = [r*cos(p)]
y = [r*sin(p)]
x += [r*sin(o-p)/sin(o)]
y += [0]
x1,y1,z1 = pltcono(x,y,a)
while (o + a < pi):
o+= a
x[0] = x[1]*cos(a)
y[0] = x[1]*sin(a)
x[1] = r*sin(a/2-p)/sin(o)
xt,yt,zt = pltcono(x,y,a)
x1 += xt
y1 += yt
z1 += zt
x[0] = x[1]*cos(a)
y[0] = x[1]*sin(a)
x[1] = x[0] - cos(o+a)
y[1] = y[0] - sin(o+a)
xt,yt,zt = pltcono(x,y,a)
x1 += xt
y1 += yt
z1 += zt
x1 = array(x1)
y1 = array(y1)
z1 = array(z1)
o = 2*pi/N
for m in range(N):
#fig = plt.figure()
#ax = fig.add_subplot(111, projection='3d')
#ax.view_init(45,)
#fig.set_size_inches(10,10)
for n in range(len(x1)):
x1[n],y1[n] = cos(o)*x1[n] - sin(o)*y1[n], sin(o)*x1[n] + cos(o)*y1[n]
ax.plot(x1,y1,z1,'k')
#plt.show()
cono(pi/6+pi/24+0.001)
Note that you need to create a figure every time or pyplot will plot in the first one created.
import math
import matplotlib.pyplot as plt
o = 2*pi/N
for m in range(N):
for n in range(len(x1)):
x1[n],y1[n] = math.cos(o)*x1[n] - math.sin(o)*y1[n], math.sin(o)*x1[n] + math.cos(o)*y1[n]
plt.figure()
plt.plot(x1,y1,z1,'k')
I assigned random values to x1,y1,z1,N and got the following output:
It is not the whole output, just signifies multiple plots.
Look here for more ways to do the same.

Bloch Sphere appears for some reasons

I'm trying to draw something called the bloch sphere, but I got its image even when it's not supposed to happen. I wrote the following codes.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
class quantum_gates:
def __init__(self,x2,y2,z2):
x2 = input("x:")
y2 = input("y:")
z2 = input("z:")
x2 = float(x2)
y2 = float(y2)
z2 = float(z2)
self.x2 = x2
self.y2 = y2
self.z2 = z2
if self.x2**2 + self.y2**2 + self.z2**2 != 1:
print("Wrong input(x^2+y^2+z^2 has to be 1)")
else:
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = np.cos(v)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.plot_wireframe(x, y, z, color="black")
ax.quiver(0,0,0,x2,y2,z2,color="red")
For example, when I put quantum_gates(2,3,1),which is self.x2^2 + self.y2^2 + self.z2^2 != 1, I get the image of the sphere and a red arrow.
What am I supposed to do to get them only when self.x2^2+self^y2+self.z2^2 = 1?

Arc between points in circle

I'm trying to plot a Chord diagram using Matplotlib. I am aware that already existing libraries, such as Plotly give me that functionality but I would really like to do it in matplotlib.
The code I have so far looks like this:
import itertools
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
fig, ax = plt.subplots()
ax.axhline(0, color='black', linestyle='--')
ax.axvline(0, color='black', linestyle='--')
npoints = 3
# Calculate the xy coords for each point on the circle
s = 2 * np.pi / npoints
verts = np.zeros((npoints, 2))
for i in np.arange(npoints):
angle = s * i
x = npoints * np.cos(angle)
y = npoints * np.sin(angle)
verts[i] = [x, y]
# Plot the arcs
numbers = [i for i in xrange(npoints)]
for i, j in itertools.product(numbers, repeat=2):
if i == j:
continue
x1y1 = x1, y1 = verts[i]
x2y2 = x2, y2 = verts[j]
# Calculate the centre of the Arc
mxmy = mx, my = [(x1 + x2) / 2, (y1 + y2) / 2]
r = np.sqrt((x1 - mx)**2 + (y1 - my)**2)
xy = [mx - r, my - r]
width = 2 * r
height = 2 * r
start_angle = np.arctan2(y1 - my, x1 - mx) * 180 / np.pi
end_angle = np.arctan2(y2 - my, x2 - mx) * 180 / np.pi
arc = patches.Arc(mxmy, width, height, start_angle, end_angle)
ax.add_patch(arc)
# Plot the points
x, y = verts.T
ax.scatter(x, y, marker='o', s=50, c='r')
ax.annotate("1", (x[0], y[0]), xytext=(x[0] + .5, y[0] + .5))
ax.annotate("2", (x[1], y[1]), xytext=(x[1] - 1, y[1] + .5))
ax.annotate("3", (x[2], y[2]), xytext=(x[2] - 1, y[2] - 1))
ax.set_xlim(-npoints - 5, npoints + 6)
ax.set_ylim(-npoints - 5, npoints + 6)
ax.set(aspect=1)
Is anyone able to tell me why my plot looks like this?
I'm expecting something more like the following (image taken from Plotly)
Edit 1
I would like to draw arcs between the following points:
1 and 2
1 and 3
2 and 3
These arcs should ideally be on the inside.
Edit 2
After some further investigation I figured that the end_angle seems to be the root of the problem.
After #f5r5e5d pointing out the Bézier curve used in plotly, I've decided to give this one a go. It looks like this is the way to go in my case, too.
import itertools
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
import sys
%matplotlib inline
fig, ax = plt.subplots()
npoints = 5
# Calculate the xy coords for each point on the circle
s = 2 * np.pi / npoints
verts = np.zeros((npoints, 2))
for i in np.arange(npoints):
angle = s * i
x = npoints * np.cos(angle)
y = npoints * np.sin(angle)
verts[i] = [x, y]
# Plot the Bezier curves
numbers = [i for i in xrange(npoints)]
bezier_path = np.arange(0, 1.01, 0.01)
for a, b in itertools.product(numbers, repeat=2):
if a == b:
continue
x1y1 = x1, y1 = verts[a]
x2y2 = x2, y2 = verts[b]
xbyb = xb, yb = [0, 0]
# Compute and store the Bezier curve points
x = (1 - bezier_path)** 2 * x1 + 2 * (1 - bezier_path) * bezier_path * xb + bezier_path** 2 * x2
y = (1 - bezier_path)** 2 * y1 + 2 * (1 - bezier_path) * bezier_path * yb + bezier_path** 2 * y2
ax.plot(x, y, 'k-')
x, y = verts.T
ax.scatter(x, y, marker='o', s=50, c='r')
ax.set_xlim(-npoints - 5, npoints + 6)
ax.set_ylim(-npoints - 5, npoints + 6)
ax.set(aspect=1)
The code above plots what I wanted it do to. Some modifications on the style and it should be good to go.
Since the underlying problem was "how can I draw a chord diagram in matplotlib", I just want to let you know that there is now a python library to do that: mpl-chord-diagram.
You can just do pip install mpl-chord-diagram.
[disclaimer] I am the current maintainer [/disclaimer]

Categories

Resources