How to plot the equation for a semicircle - python

My half circle doesn't really look like how I expected.
Am I doing this right or am I missing something pretty big here ?
import math
import numpy as np
import matplotlib.pyplot as plt
coord_list = []
h = 0
k = 0
r = 6
for x in range((1 + h - r), (h + r - 1), 1):
y1 = k + math.sqrt(r**2 - (x-h)**2)
coord_list.append([x, y1])
for each in coord_list:
print(each)
data = np.array([coord_list])
x, y = data.T
figure = plt.scatter(x, y)
figure = plt.grid(color = 'green', linestyle = '--', linewidth = 0.2)
figure = plt.show()

Use np.linspace to create an array for the x values. Use many points to create the circle
Use np.sqrt to solve for an array, instead of looping through each value.
import numpy as np
import matplotlib.pyplot as plt
# function for semicircle
def semicircle(r, h, k):
x0 = h - r # determine x start
x1 = h + r # determine x finish
x = np.linspace(x0, x1, 10000) # many points to solve for y
# use numpy for array solving of the semicircle equation
y = k + np.sqrt(r**2 - (x - h)**2)
return x, y
x, y = semicircle(6, 0, 0) # function call
plt.scatter(x, y, s=3, c='turquoise') # plot
plt.gca().set_aspect('equal', adjustable='box') # set the plot aspect to be equal

Answering my own question.
Plotting the output of the code:
import math
import numpy as np
import matplotlib.pyplot as plt
coord_list = []
h = 0
k = 0
r = 6
for x in range((1 + h - r), (h + r - 1), 1):
y1 = k + math.sqrt(r**2 - (x-h)**2)
coord_list.append([x, y1])
for each in coord_list:
print(each)
data = np.array([coord_list])
x, y = data.T
figure = plt.scatter(x, y)
figure = plt.grid(color = 'green', linestyle = '--', linewidth = 0.2)
figure = plt.show()
[-5, 3.3166247903554]
[-4, 4.47213595499958]
[-3, 5.196152422706632]
[-2, 5.656854249492381]
[-1, 5.916079783099616]
[0, 6.0]
[1, 5.916079783099616]
[2, 5.656854249492381]
[3, 5.196152422706632]
[4, 4.47213595499958]
Looking at the output of the coordinates, it doesn't appear to be a circle.
But if we take our equation and our coordinates and graph them on this website we see that they are indeed a circle. It's an optical illusion that they aren't. Partially because the graph is not evenly displayed and also because plotting points in a range function with steps of 1 (line 13) doesn't plot points at equal arc length distances away from each other.

Related

3D plane in Python

I used the following code to try and plot a 3D plane of on its x axis the height (is also the momentum arm) and on its y axis the mass (in kg) which has a linear connection with the force used. The Z axis is the resulting momentum.
Unfortunately I get the following error:
ValueError: Argument Z must be 2-dimensional.
However I do believe that Z, thus the momentum is dependent on both the mass and the height, thus is Z 2d.
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits import mplot3d
g = 9.81
m = np.linspace(0, 1, 301)
H_1 = np.arange(100, 401, 1)
for i, kg in enumerate(m):
    Fg = -m[i]*g
    M = np.zeros(len(H_1))
    for i, mm in enumerate(H_1):
        F1 = np.array([0, Fg])
        F2 = np.array([Fg * np.sin(np.arctan(200 / H_1[i])), Fg * np.cos(np.arctan(200 / H_1[i]))])
        Fres = np.add(F1, F2)
        M_arm = np.array([0, H_1[i]])
        M[i] = np.cross(M_arm, Fres)/10e3
x,y = np.meshgrid(H_1,m)
z = M
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(x, y, z)
ax.set_xlabel('hoogte toren in (mm)')
ax.set_ylabel('massa')
ax.set_zlabel('momentum')
plt.show()
Check this out:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits import mplot3d
g = 9.81
m = np.linspace(0, 1, 301)
H_1 = np.arange(100, 401, 1)
Fg = -m * g
M = np.zeros(len(H_1))
for i, mm in enumerate(H_1):
F1 = np.array([0, Fg[i]])
F2 = np.array([Fg[i] * np.sin(np.arctan(200 / H_1[i])), Fg[i] * np.cos(np.arctan(200 / H_1[i]))])
Fres = np.add(F1, F2)
M_arm = np.array([0, H_1[i]])
M[i] = np.cross(M_arm, Fres) / 10e3
x, y = np.meshgrid(H_1, m)
z = M
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(x, y, z)
ax.set_xlabel('hoogte toren in (mm)')
ax.set_ylabel('massa')
ax.set_zlabel('momentum')
plt.show()
I made the following changes to your code:
Moved the calculation of Fg outside the loop.
Used the correct index i to access the elements of m and Fg in the loop.
Used the correct array index i to access the elements of H_1 in the loop.
Removed the unnecessary enumerate call in the inner loop.
Used the correct array index i to access the elements of M in the loop.
These changes should fix the errors in your code and produce the expected plot.
:)

How to distribute points evenly on a circle in matplotlib?

I'm trying to create 10 points distributed on a circle, just like a watch but with 10 numbers instead of 12. and also be able to use the dots/points to plot lines between them.
This is the code I used to create a circle but can't figure out how to make them 10 points, and also how to use the points' coordinates in my code.
import matplotlib.pyplot as plt
import numpy as np
# T = testing
# myList = testing.digitcounter(18, 20)
def circle_points(r, n):
circles = []
for r, n in zip(r, n):
t = np.linspace(0, 2*np.pi, n)
x = r * np.cos(t)
y = r * np.sin(t)
circles.append(np.c_[x, y])
return circles
r = [0.15]
n = [15]
circles = circle_points(r, n)
fig, ax = plt.subplots()
for circle in circles:
ax.scatter(circle[:, 0], circle[:, 1])
ax.set_aspect('equal')
plt.show()
With t = np.linspace(0, 2*np.pi, 10, endpoint=False), you can create 10 angles equally distributed over a circle. The default endpoint=True would have the first and last angle coincide. To have the first point at the top, and going clockwise, interchange cos and sin in the formula.
To plot a continuous line between digits, you could use ax.plot(circle[digits, 0], circle[digits, 1]), with digits a numpy array of integers between 0 and 1. Note that this will contain a line of zero length when two subsequent digits would be equal.
import matplotlib.pyplot as plt
import numpy as np
def circle_points(r, n):
circles = []
for r, n in zip(r, n):
t = np.linspace(0, 2 * np.pi, n, endpoint=False)
x = r * np.sin(t)
y = r * np.cos(t)
circles.append(np.c_[x, y])
return circles
digits = np.random.randint(0, 10, 7) # 7 random digits between 0 and 9
circle10 = circle_points([0.15], [10])[0] # 10 points on a circle
circle10 = circle10[(np.arange(10) - 3) % 10, :] # with 3 at the top
fig, ax = plt.subplots()
ax.scatter(circle10[:, 0], circle10[:, 1], color='crimson')
ax.plot(circle10[digits, 0], circle10[digits, 1], color='dodgerblue', lw=3)
for i, (x, y) in enumerate(circle10):
ax.text(x * 1.1, y * 1.1, i, ha='center', va='center', color='crimson')
ax.set_aspect('equal')
ax.margins(x=0.1, y=0.1) # extra margins, because the text isn't taken into account for the default margins
ax.set_title("".join([f'{d}' for d in digits]), size=16)
ax.axis('off')
plt.show()
Similarly, a 17-pointed star could be drawn with:
N = 17
circle = circle_points([0.15], [N])[0]
for i in range(N):
ax.plot([circle[i, 0], circle[(i + 6) % N, 0]],
[circle[i, 1], circle[(i + 6) % N, 1]],
color='dodgerblue', lw=3)

How to find all intersection points of graphs in a loop in Python?

I plot a certain set of circles as follows:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(1, figsize=(10,10))
numbers = [2,4,6]
for i in range(1,len(numbers)+1):
for n in numbers:
for j in range(1,4):
x = np.linspace(-20, 25, 100)
y = np.linspace(-20, 20, 100)
X, Y = np.meshgrid(x,y)
F = (X-i)**2 + Y**2 - (numbers[i-1]*j)**2
ax = plt.gca()
ax.set_aspect(1)
plt.contour(X,Y,F,[0])
plt.grid(linestyle='--')
plt.show()
And I receive:
How can I find all intersection points between circles?
Here is some SymPy code to find all the intersections. Note that your code generates a lot of circles multiple times, so I put them in a set. (The circle-circle intersection of a circle with itself is of course itself, in which case intersect doesn't return a list, but just the circle.)
from sympy import *
from sympy.geometry import *
import itertools
numbers = [2,4,6]
circles = set()
for i in range(1,len(numbers)+1):
for n in numbers:
for j in range(1,4):
circles.add(Circle(Point(i, 0), numbers[i-1]*j))
all_intersections = []
for c1, c2 in itertools.combinations(circles, 2):
all_intersections += c1.intersection(c2)
print(all_intersections)
all_intersections_as_tuple = [tuple(p.evalf()) for p in all_intersections]
Which outputs:
[Point2D(5/2, -5*sqrt(23)/2), Point2D(5/2, 5*sqrt(23)/2), Point2D(-3, 0), Point2D(3/2, -3*sqrt(7)/2), Point2D(3/2, 3*sqrt(7)/2), Point2D(2, sqrt(35)), Point2D(2, -sqrt(35))]
Adding them to your plot:
plt.plot([x for x, y in all_intersections_as_tuple], [y for x, y in all_intersections_as_tuple], 'or', color='red')

How to close the ends of a cylinder in matplotlib

I am trying to make a 'closed' cylinder in matplotlib but I am not sure how to go about doing this. So far I have a cylinder with the ends open, the code for this is as follows:
#make a cylinder without the ends closed
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.linalg import norm
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
import math
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
origin = [0,0,0]
#radius = R
p0 = np.array(origin)
p1 = np.array([8, 8, 8])
origin = np.array(origin)
R = 4
#vector in direction of axis
v = p1 - p0
#find magnitude of vector
mag = norm(v)
#unit vector in direction of axis
v = v / mag
#make some vector not in the same direction as v
not_v = np.array([1, 0, 0])
if (v == not_v).all():
not_v = np.array([0, 1, 0])
#make vector perpendicular to v
n1 = np.cross(v, not_v)
#normalize n1
n1 /= norm(n1)
#make unit vector perpendicular to v and n1
n2 = np.cross(v, n1)
#surface ranges over t from 0 to length of axis and 0 to 2*pi
t = np.linspace(0, mag, 600)
theta = np.linspace(0, 2 * np.pi, 100)
#use meshgrid to make 2d arrays
t, theta = np.meshgrid(t, theta)
#generate coordinates for surface
X, Y, Z = [p0[i] + v[i] * t + R * np.sin(theta) * n1[i] + R * np.cos(theta) * n2[i] for i in [0, 1, 2]]
#make the color for the faces
col1 = plt.cm.autumn(np.ones(600)) # linear gradient along the t-axis
col1 = np.repeat(col1[np.newaxis,:, :], 100, axis=0) # expand over the theta-axis
ax.plot_surface(X, Y,Z, facecolors = col1, shade = True,edgecolors = "None", alpha = 0.4, linewidth = 0)
plt.show()
Running this code produces the following image
How would I close the ends of the cylinder with a solid circle (i.e. disk)?
A quick and easy way that's similar to your other code is to generate a surface using strips from r=0 to r=R. Right before plt.show() add the following lines:
R = np.array([0,R])
# cap at t=0
X, Y, Z = [p0[i] + np.outer(R, np.sin(theta)) * n1[i] + np.outer(R, np.cos(theta))*n2[i] for i in [0, 1, 2]]
ax.plot_surface(X, Y, Z, edgecolors = "r", alpha=.4, linewidth = .1)
# cap at t=mag
X, Y, Z = [p0[i] + v[i]*mag + np.outer(R, np.sin(theta)) * n1[i] + np.outer(R, np.cos(theta))*n2[i] for i in [0, 1, 2]]
ax.plot_surface(X, Y, Z, edgecolors = "r", alpha=.4, linewidth = .1)
Here the colors are more for illustrative purposes, mostly so you can see the strips. The result looks like:

Plotting multiple 2d curves with matplotlib in 3d

I'm trying to plot a fourier series of a triangular wave with matplotlib.
I've managed to plot the elements on top of each other in 2d, but I'd like to plot them in 3d instead, as that makes it more easy to see.
Here's the plot my current code generates
triangular wave
Here's an image of what I'd like to plot, but for the triangular wave instead of a square wave.
square wave
Here's the current code
%matplotlib inline
import numpy as np
from matplotlib import pyplot as plt
import scipy as sp
x1 = np.arange(0, L / 2.0, 0.01)
x2 = np.arange(L/2.0,L,0.01)
x = np.concatenate((x1,x2))
y1 = 2* x1
y2 = 2*(1 - x2)
triangle_y = np.concatenate((y1,y2))
L = 1;
def triangle_function(x, L):
'''given x, returns y as defined by the triangle function defined in the range 0 <= x <= L
'''
if x< 0:
print 'Error: the value of x should be between 0 and L'
y = None
elif x<L/2.0:
y = 2*x
elif x <= L:
y = 2*(1 - x)
else:
print 'Error: the value of x should be between 0 and L'
y = None
return y
def projection_integrand(x, n, L):
'''The inputs to the function are:
x ---> vector of x values.
n ---> the n-number associated to the sine functions
L --> L, upper limit of integration
'''
sine_function = np.sin(n * np.pi * x / np.double(L)) # this is the sine function sin(n*pi*x/L)
integrand = (2.0 / L) * sine_function * triangle_function(x, L) # this is the product of the two functions, with the 2/L factor
#return(sine_function*f_x)
return integrand
from scipy.integrate import quad
n_max = 5
x = np.arange(0, L, 0.01) # x vector
triangle_approx = np.zeros(len(x))
func_list = []
for n in range(1, n_max + 1):
c_n = quad(projection_integrand, 0, L, (n, L))
sin_arg = n* np.pi*x/np.double(L)
current = c_n[0]* np.sin(sin_arg)
triangle_approx += current
func_list.append(current)
from mpl_toolkits.mplot3d import Axes3D
plt.hold(True)
plt.plot(x, func_list[0])
plt.plot(x, func_list[1])
plt.plot(x, func_list[2])
plt.plot(x, func_list[3])
plt.plot(x, func_list[4])
plt.plot(x, triangle_approx)
plt.plot(x, triangle_y)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('approximating the triangle function as a sum of sines, n = 1 ...' + str(n_max))
plt.legend(['approximation', 'triangle function'])
plt.show()
I have found a way based on this matplotlib official example.
Add this code below your code and you will get something close to what you want:
fig = plt.figure()
ax = fig.gca(projection='3d')
z = np.array([1.0 for point in x])
for n, armonic in enumerate(func_list):
ax.plot(x, armonic, z*n, label='armonic{}'.format(n))
ax.legend()
plt.show()

Categories

Resources