简体   繁体   中英

Smooth line between set of points

I want the lines uniting the values to be smooth round lines. I tried wit interp1d but I do not seem to wrap my head around the 1-d array requirement.

from matplotlib import pyplot as plt

a = int(input("what number?\n"))

X_Values, Y_Values, fibonacci = [0] * a, [0] * a, [0] * a
X_Values[0], Y_Values [0] = 0, 0
X_Values[1], Y_Values[1] = 1, 1
fibonacci[0] = 1
fibonacci[1] = 1
counter = 2

for i in range(2,a):
   fibonacci[i] = fibonacci[i-1] + fibonacci[i-2]
   if counter == 0:
       X_Values[i] = 0
       Y_Values[i] = -fibonacci[i]
       counter += 1
   elif counter == 1:
       X_Values[i] = fibonacci[i]
       Y_Values[i] = 0
       counter += 1
   elif counter == 2:
       X_Values[i] = 0
       Y_Values[i] = fibonacci[i]
       counter += 1
   elif counter == 3:
       X_Values[i] = -fibonacci[i]
       Y_Values[i] = 0
       counter = 0


plt.axhline(y=0, color='k') 
plt.axvline(x=0, color='k')
plt.plot(X_Values, Y_Values, '*-g')
plt.title("Flow Chart of a Fibonacci series with %i elements" %a)
plt.figtext(0.5, 0.025, "The {0}th number of the Fibonacci serie is: {1}".format(a, fibonacci[-1]), ha="center", fontsize=8, bbox={"facecolor":"orange", "alpha":0.5, "pad":5})
print("The ", a, "th Fibonacci number is: ", fibonacci[a-1])
plt.show()

And is there a way to shorten the if elif loop to assign the coordinates to X and Y _values?

To create a smooth interpolation, you probably can use Bézier splines . You could calculate an in-between point by adding X[i] and X[i+1] , and Y[i] and Y[i+1] .

Things would look nicer using circular arcs. Starting angles will be -90, 0, 90, 180, 270, ... . End angles will be the start angle plus 90. The width and height are a bit tricky, as their role is constantly switched. It will either be Fibonacci number i and i+1, or the other way around. i % 2 and (i+1) % 2 will take care of the switching.

To make the calculation with less code, first note that counter isn't needed, as it is just i mod 4 . The rotating directions can be stored in two list, dir_x and dir_y . Also, the first two values can be set via an if-test ( if i < 2 ), so they can use the same assignments for the x and y position.

from matplotlib import pyplot as plt
from matplotlib.patches import Arc

a = int(input("what number?\n"))

X_Values, Y_Values, fibonacci = [0] * a, [0] * a, [0] * a

dir_x = [0, 1, 0, -1]
dir_y = [-1, 0, 1, 0]
for i in range(0, a):
    if i < 2:
        fibonacci[i] = 1
    else:
        fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2]
    X_Values[i] = dir_x[i % 4] * fibonacci[i]
    Y_Values[i] = dir_y[i % 4] * fibonacci[i]

fig, ax = plt.subplots()
for i in range(a - 1):
    ax.add_patch(Arc((0, 0), width=fibonacci[i + (i + 1) % 2] * 2, height=fibonacci[i + i % 2] * 2,
                     theta1=(i - 1) * 90, theta2=i * 90, color='crimson', lw=2))
# ax.relim() # needed to calculate the x and y limits if no lines are added to the plot
# ax.autoscale()
ax.axis('equal') # equal distances on x and on y
ax.axis('off') # hide the surrounding axes

ax.axhline(y=0, color='k')
ax.axvline(x=0, color='k')
ax.plot(X_Values, Y_Values, '*--g', lw=0.5)
ax.set_title("Flow Chart of a Fibonacci series with %i elements" % a)
ax.text(0.5, -0.05, f"The {a}th number of the Fibonacci serie is: {fibonacci[-1]}", ha="center",
        fontsize=8, bbox={"facecolor": "orange", "alpha": 0.5, "pad": 5}, transform=ax.transAxes)
print("The ", a, "th Fibonacci number is: ", fibonacci[a - 1])

plt.tight_layout()
plt.show()

示例图

PS: The code to create the arcs can be further simplified using its angle parameter. angle is an extra rotation given to the arc, which removes the need for alternating width and height.

ax.add_patch(Arc((0, 0), width=fibonacci[i] * 2, height=fibonacci[i + 1] * 2,
                 angle=(i - 1) * 90, theta1=0, theta2=90, color='crimson', lw=2))

The code to draw quadratic Bézier curves:

from matplotlib.patches import PathPatch, Path

x, y = X_Values, Y_Values
for i in range(a - 1):
    ax.add_patch(PathPatch(
        Path([(x[i], y[i]), (x[i] + x[i + 1], y[i] + y[i + 1]), (x[i + 1], y[i + 1])],
             [Path.MOVETO, Path.CURVE3, Path.CURVE3]),
        fc="none", ec='navy', transform=ax.transData))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM