Issue
I am trying to draw a simplified top-down perspective of a wing. I am using sliders to change the wingspan (b) and wing surface (S).
I am using matplotlib.patch.Polygon to draw it symmetrically from the 0,0 point. But only the positive quarter is visible and plot limits are not updating with sliders. x and y max ticks are stuck at 1 and 1. The goal is to see the whole wing in the center of the plot with ticks updating.
The code below is a modified showcase from: https://matplotlib.org/stable/gallery/widgets/slider_demo.html
code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Button, Slider
%matplotlib widget
# Define initial parameters
init_S = 50
init_b = 50
# Create the figure and the polygon that we will manipulate
fig, ax = plt.subplots()
ax.add_patch(Rectangle((-init_b/2, -(init_S/init_b)/2), init_b, init_S/init_b, alpha=0.4))
ax.set_xlabel('Wingspan [m]')
ax.set_xlabel('Chord [m]')
# adjust the main plot to make room for the sliders
fig.subplots_adjust(left=0.25, bottom=0.25)
# Make a horizontal slider to control the wingspan
axb = fig.add_axes([0.25, 0.1, 0.65, 0.03])
b_slider = Slider(axb, r"Wingspan [$m$]", 0.1, 50, init_b, orientation="horizontal")
# Make a vertically oriented slider to control the surface
axsurf = fig.add_axes([0.1, 0.25, 0.0225, 0.63])
S_slider = Slider(axsurf, r"Surface [$m^2$]", 0.1, 50, init_S, orientation = "vertical")
# The function to be called anytime a slider's value changes
def update(val):
ax.cla() # clear plot before update
ax.add_patch(Rectangle((-b_slider.val/2, -(S_slider.val/b_slider.val)/2), b_slider.val, S_slider.val/b_slider.val, alpha=0.4))
plt.autoscale()
fig.canvas.draw_idle()
# register the update function with each slider
b_slider.on_changed(update)
S_slider.on_changed(update)
# Create a `matplotlib.widgets.Button` to reset the sliders to initial values.
resetax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', hovercolor='0.975')
def reset(event):
S_slider.reset()
b_slider.reset()
button.on_clicked(reset)
plt.autoscale()
plt.show()
Solution
Perhaps the simplest way to do so is to define a Polygon and plot it within an update function, then use interact from ipywidgets to make the sliders, where you can set the limits, steps and initial values of variables:
import matplotlib.pyplot as plt
from shapely.geometry import Polygon
from ipywidgets import *
def update(b, S):
a = S/b
polygon = Polygon([[-b/2, -a/2],
[b/2, -a/2],
[b/2, a/2],
[-b/2, a/2]])
fig, ax = plt.subplots()
ax.fill(*polygon.exterior.xy, alpha=0.4)
ax.axis('equal')
ax.set_xlabel('$x$ [m]')
ax.set_ylabel('$y$ [m]')
ax.set_title(f'wingspan = {b} m, surface area = {S} m$^2$')
plt.show()
interact(update,
b=widgets.IntSlider(min=0, max=20, step=1, value=10),
S=widgets.IntSlider(min=0, max=400, step=10, value=50))
Answered By - Jeff
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.