Reputation: 11
I need to draw a circle that's not perfect, I mean at some points on the circle the radius needs to change (be greater or lower) in order to cause the desired deformation.
This image for instance shows a circle with 1 single deformation:
The number of the deformations is random and the positions also.
I am using the code below to draw a normal circle :
import numpy as np
import matplotlib.pyplot as plt
theta = np.linspace(0, 2*np.pi, 200)
radius = 0.4
a = radius * np.cos(theta)
b = radius * np.sin(theta)
figure, axes = plt.subplots(1)
axes.plot(a, b)
axes.set_aspect(1)
plt.show()
Do you have any ideas how can I achieve this?
Upvotes: 1
Views: 500
Reputation: 80429
Making the radius depend on theta, we could have a function f
such that:
theta1
: f(t) = 1
f(1) = f(2) = 1
theta1
there is a deformation such that f(0) = k
, for some k
t
, we can use f
on the absolute valueIf f
would be a polynomial, it could be of degree 4, so f = a*t**4 + b*t**3 + c*t**2 + d*t + e
. The symbolic math library, sympy, can find suitable values for these parameters with the given constraints.
from sympy import Eq, solve
from sympy.abc import a, b, c, d, e, t, k
f = a * t ** 4 + b * t ** 3 + c * t ** 2 + d * t + e
eq1 = Eq(f.subs(t, 0), k)
eq2 = Eq(f.subs(t, 1), 1)
eq3 = Eq(f.subs(t, 2), 1)
eq4 = Eq(f.diff(t).subs(t, 0), 0)
eq5 = Eq(f.diff(t).subs(t, 2), 0)
sol = solve([eq1, eq2, eq3, eq4, eq5], (a, b, c, d, e))
This generates (after some rewriting), the following expression for f
:
k + (2 * t ** 2 - 9 * t + 11) * t ** 2 * (1 - k) / 4
Now, use this function to draw the deformed circle:
import matplotlib.pyplot as plt
import numpy as np
theta = np.linspace(0, 2 * np.pi)
k = 0.8
theta1 = 80 * np.pi / 180 # a deformation at theta 80 degrees
alpha = 36 * np.pi / 180 # have a special point every 36 degrees (10 on the circle)
th = theta - theta1 # the difference between the angles, still needs to be careful to make this difference symmetrical to zero
t = np.abs(np.where(th < np.pi, th, th - 2 * np.pi)) / alpha # use absolute value and let alpha represent a step of 1
r = np.where(t > 2, 1, k + (2 * t ** 2 - 9 * t + 11) * t ** 2 * (1 - k) / 4) # the deformed radius
plt.plot(np.cos(theta), np.sin(theta), ':r')
plt.plot(r * np.cos(theta), r * np.sin(theta), '-b')
plt.fill(r * np.cos(theta), r * np.sin(theta), color='blue', alpha=0.2)
for i in range(-5, 5):
plt.plot(np.cos(theta1 + i * alpha), np.sin(theta1 + i * alpha), 'xk')
plt.axis('equal')
plt.show()
Upvotes: 4