%pip install ipywidgets
Requirement already satisfied: ipywidgets in c:\users\youri\anaconda3\lib\site-packages (7.6.5)
Requirement already satisfied: traitlets>=4.3.1 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (5.1.1)
Requirement already satisfied: jupyterlab-widgets>=1.0.0 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (1.0.0)
Requirement already satisfied: nbformat>=4.2.0 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (5.5.0)
Requirement already satisfied: ipython-genutils~=0.2.0 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (0.2.0)
Requirement already satisfied: ipykernel>=4.5.1 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (6.15.2)
Requirement already satisfied: widgetsnbextension~=3.5.0 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (3.5.2)
Requirement already satisfied: ipython>=4.0.0 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (7.31.1)
Requirement already satisfied: tornado>=6.1 in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (6.1)
Requirement already satisfied: debugpy>=1.0 in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (1.5.1)
Requirement already satisfied: packaging in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (21.3)
Requirement already satisfied: psutil in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (5.9.0)
Requirement already satisfied: nest-asyncio in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (1.5.5)
Requirement already satisfied: matplotlib-inline>=0.1 in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (0.1.6)
Requirement already satisfied: jupyter-client>=6.1.12 in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (7.3.4)
Requirement already satisfied: pyzmq>=17 in c:\users\youri\anaconda3\lib\site-packages (from ipykernel>=4.5.1->ipywidgets) (23.2.0)
Requirement already satisfied: backcall in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (0.2.0)
Requirement already satisfied: decorator in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (5.1.1)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (3.0.20)
Requirement already satisfied: pygments in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (2.11.2)
Requirement already satisfied: jedi>=0.16 in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (0.18.1)
Requirement already satisfied: colorama in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (0.4.5)
Requirement already satisfied: setuptools>=18.5 in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (63.4.1)
Requirement already satisfied: pickleshare in c:\users\youri\anaconda3\lib\site-packages (from ipython>=4.0.0->ipywidgets) (0.7.5)
Requirement already satisfied: jupyter_core in c:\users\youri\anaconda3\lib\site-packages (from nbformat>=4.2.0->ipywidgets) (4.11.1)
Requirement already satisfied: jsonschema>=2.6 in c:\users\youri\anaconda3\lib\site-packages (from nbformat>=4.2.0->ipywidgets) (4.16.0)
Requirement already satisfied: fastjsonschema in c:\users\youri\anaconda3\lib\site-packages (from nbformat>=4.2.0->ipywidgets) (2.16.2)
Requirement already satisfied: notebook>=4.4.1 in c:\users\youri\anaconda3\lib\site-packages (from widgetsnbextension~=3.5.0->ipywidgets) (6.4.12)
Requirement already satisfied: parso<0.9.0,>=0.8.0 in c:\users\youri\anaconda3\lib\site-packages (from jedi>=0.16->ipython>=4.0.0->ipywidgets) (0.8.3)
Requirement already satisfied: attrs>=17.4.0 in c:\users\youri\anaconda3\lib\site-packages (from jsonschema>=2.6->nbformat>=4.2.0->ipywidgets) (21.4.0)
Requirement already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in c:\users\youri\anaconda3\lib\site-packages (from jsonschema>=2.6->nbformat>=4.2.0->ipywidgets) (0.18.0)
Requirement already satisfied: python-dateutil>=2.8.2 in c:\users\youri\anaconda3\lib\site-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets) (2.8.2)
Requirement already satisfied: entrypoints in c:\users\youri\anaconda3\lib\site-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets) (0.4)
Requirement already satisfied: pywin32>=1.0 in c:\users\youri\anaconda3\lib\site-packages (from jupyter_core->nbformat>=4.2.0->ipywidgets) (302)
Requirement already satisfied: nbconvert>=5 in c:\users\youri\anaconda3\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (6.4.4)
Requirement already satisfied: Send2Trash>=1.8.0 in c:\users\youri\anaconda3\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (1.8.0)
Requirement already satisfied: prometheus-client in c:\users\youri\anaconda3\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.14.1)
Requirement already satisfied: terminado>=0.8.3 in c:\users\youri\anaconda3\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.13.1)
Requirement already satisfied: argon2-cffi in c:\users\youri\anaconda3\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (21.3.0)
Requirement already satisfied: jinja2 in c:\users\youri\anaconda3\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (2.11.3)
Requirement already satisfied: wcwidth in c:\users\youri\anaconda3\lib\site-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=4.0.0->ipywidgets) (0.2.5)
Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in c:\users\youri\anaconda3\lib\site-packages (from packaging->ipykernel>=4.5.1->ipywidgets) (3.0.9)
Requirement already satisfied: mistune<2,>=0.8.1 in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.8.4)
Requirement already satisfied: testpath in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.6.0)
Requirement already satisfied: nbclient<0.6.0,>=0.5.0 in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.5.13)
Requirement already satisfied: bleach in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (4.1.0)
Requirement already satisfied: jupyterlab-pygments in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.1.2)
Requirement already satisfied: pandocfilters>=1.4.1 in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (1.5.0)
Requirement already satisfied: defusedxml in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.7.1)
Requirement already satisfied: beautifulsoup4 in c:\users\youri\anaconda3\lib\site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (4.11.1)
Requirement already satisfied: MarkupSafe>=0.23 in c:\users\youri\anaconda3\lib\site-packages (from jinja2->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (2.0.1)
Requirement already satisfied: six>=1.5 in c:\users\youri\anaconda3\lib\site-packages (from python-dateutil>=2.8.2->jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets) (1.16.0)
Requirement already satisfied: pywinpty>=1.1.0 in c:\users\youri\anaconda3\lib\site-packages (from terminado>=0.8.3->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (2.0.2)
Requirement already satisfied: argon2-cffi-bindings in c:\users\youri\anaconda3\lib\site-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (21.2.0)
Requirement already satisfied: cffi>=1.0.1 in c:\users\youri\anaconda3\lib\site-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (1.15.1)
Requirement already satisfied: soupsieve>1.2 in c:\users\youri\anaconda3\lib\site-packages (from beautifulsoup4->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (2.3.1)
Requirement already satisfied: webencodings in c:\users\youri\anaconda3\lib\site-packages (from bleach->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (0.5.1)
Requirement already satisfied: pycparser in c:\users\youri\anaconda3\lib\site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.5.0->ipywidgets) (2.21)
Note: you may need to restart the kernel to use updated packages.
1. Introductie: Waarom goniometrie?¶
• Doel: Motiveer het onderwerp vanuit realiteit (bijv. dag-nacht-cyclus, seizoenen, geluidsgolven, hartslag). • Simulatie: Een schommelende slinger of een punt op een draaiende cirkel gekoppeld aan een golf. • Didactiek: Laat leerlingen voorspellen wat er gebeurt voordat je het toont. • Afbeelding: Realtime animatie van een sinusgolf die wordt gegenereerd door een draaiend punt op een cirkel (eenheidscirkel).
2. Graden vs. Radialen¶
2.1 Verband tussen graden en radialen¶
Een cirkel is gedefinieerd als 360°. De omtrek van een cirkel is beschreven met:
[
C = 2\pi r
]
Als je de booglengte van een deel van een cirkel wilt berekenen, doe je dat met een verhouding:
[
C = \left( \frac{\theta}{360^\circ} \right) \cdot 2\pi r
]
Voor een halve cirkel (( \theta = 180^\circ )) geeft dat een factor van ( \frac{1}{2} ).
Voor een kwart cirkel (( \theta = 90^\circ )) is dat ( \frac{1}{4} ).
Bij een cirkel met straal ( r = 1 ) (de eenheidscirkel) kunnen we booglengtes direct uitdrukken in radialen. Hier is een overzicht:
( \theta ) (°) | ( C ) (rad) |
---|---|
0° | ( 0 ) |
30° | ( \frac{1}{6} \pi ) |
45° | ( \frac{1}{4} \pi ) |
60° | ( \frac{1}{3} \pi ) |
90° | ( \frac{1}{2} \pi ) |
180° | ( \pi ) |
270° | ( \frac{3}{2} \pi ) |
360° | ( 2\pi ) |
Stel dat je op een eenheidscirkel loopt (een cirkel met ( r = 1 )), dan kun je je positie op de cirkel beschrijven met:
- de afgelegde hoek ( \theta ) in graden (°),
- óf de afgelegde booglengte ( C ) in radialen (rad).
De radiaal is dus een alternatieve eenheid voor de graad, net zoals je lengte kunt uitdrukken in zowel kilometers als mijlen.
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import IntSlider, interact
from matplotlib.lines import Line2D
# Updatefunctie
def update(theta_deg):
# Voorbereiding van figuur en plots
plt.figure(figsize=(6, 6))
plt.xlim(-1.2, 1.2)
plt.ylim(-1.2, 1.2)
plt.title("Eenheidscirkel met hoek θ")
plt.grid(True)
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
# Eenheidscirkel
circle_theta = np.linspace(0, 2 * np.pi, 1000)
circle_x = np.cos(circle_theta)
circle_y = np.sin(circle_theta)
plt.plot(circle_x, circle_y, 'lightgray')
# Lijnen en objecten die we gaan updaten
line_OP, = plt.plot([], [], 'r-', linewidth=2)
arc_line, = plt.plot([], [], 'b--', linewidth=2)
angle_arc, = plt.plot([], [], 'g-', linewidth=1.5)
point_P, = plt.plot([], [], 'ro')
# Teksten die we updaten
text_P = plt.text(0, 0, '', fontsize=12, color='red')
text_deg = plt.text(0, 0, '', fontsize=10, color='green', ha='center')
text_rad = plt.text(0, 0, '', fontsize=10, color='blue', ha='center')
# Extra vaste labels
plt.text(1.05, 0, 'x', fontsize=12)
plt.text(0, 1.05, 'y', fontsize=12)
plt.text(-0.1, -0.1, 'O', fontsize=12)
theta_rad = np.radians(theta_deg)
x = np.cos(theta_rad)
y = np.sin(theta_rad)
# Update lijn OP
line_OP.set_data([0, x], [0, y])
# Update boog
arc_theta = np.linspace(0, theta_rad, 300)
arc_line.set_data(np.cos(arc_theta), np.sin(arc_theta))
# Hoekboogje
angle_arc_theta = np.linspace(0, theta_rad, 100)
angle_arc_r = 0.3
angle_arc.set_data(angle_arc_r * np.cos(angle_arc_theta),
angle_arc_r * np.sin(angle_arc_theta))
# Punt P
point_P.set_data([x], [y])
text_P.set_position((x + 0.05 * np.sign(x), y + 0.05 * np.sign(y)))
text_P.set_text("P")
# Hoeklabels
text_deg.set_position((0.35 * np.cos(theta_rad / 2), 0.35 * np.sin(theta_rad / 2)))
text_deg.set_text(f"θ = {theta_deg}°")
text_rad.set_position((0.5 * np.cos(theta_rad / 2), 0.5 * np.sin(theta_rad / 2)))
text_rad.set_text(f"{round(theta_rad, 2)} rad")
# Titel
plt.title(f"θ = {theta_deg}° = {round(theta_rad, 2)} rad")
# Interactieve slider
interact(update, theta_deg=IntSlider(min=0, max=360, step=1, value=0, description="Hoek θ (°)"));
2.2 Omrekenen van graden en radialen¶
Rekenen met graden en radialen: We hebben dus gezien dat je radialen kan berekenen met graden C=(θ/(360°))2π. Omdat het eigenlijk een verhouding is kunnen we ook zeggen dat; θ_rad=(π/(180°)) θ_deg En de verhouding kan je ook omdraaien; θ_deg=((180°)/π) θ_rad Dus 1 rad zou dan gelijk moeten zijn aan 57,3°. Mochten verhoudingen toch een beetje lastig zijn kan je ook gebruik maken van een verhoudingstabel; Hoek Hele cirkel Cirkel gedeelte θ (graden) 360° 90° θ (radialen) 2π θ
Je kan de gewenste hoek o.a. met een kruistabel berekenen; 360°∙θ=2π∙90° wat θ=1/4 π geeft.
3. De eenheidscirkel en goniometrische functies¶
Als we een kijkje nemen op de eenheidscirkel kun je dus voor een bepaalde hoek θ op een punt (positie) P(x,y) staan. Dan kan je je voorstellen dat het interessant is om te berekenen met de hoek θ waar je staat op de eenheidscirkel. Maar hoe kunnen we het x-coordinaat en y-coordinaat beschrijven als functie van de hoek θ? Als we kijken in het onderstaande figuur zien we dat de afstand tussen P en de x-as het y-coördinaat voorstelt en de afstand tussen P en de y-as het x-coördinaat voorstelt. Dit vormt een rechte driehoek waar we SOS, CAS, TOA op kunnen loslaten; SOS; sin(θ)=y/1 CAS; cos(θ)=x/1 TOA; tan(θ)=y/x Wat we dus hebben geleerd is dat het punt P(x,y) berekent kan worden met x=cos(θ) y=sin(θ)
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import IntSlider, interact
import matplotlib.gridspec as gridspec
def plot_figure(theta):
# Zet figuur opnieuw op bij elke update
fig = plt.figure(figsize=(10, 12))
gs = gridspec.GridSpec(3, 1, height_ratios=[2, 1, 1])
ax_circle = plt.subplot(gs[0])
ax_cos = plt.subplot(gs[1])
ax_sin = plt.subplot(gs[2])
plt.subplots_adjust(left=0.1, bottom=0.15, hspace=0.4)
# Eenheidscirkel
circle = plt.Circle((0, 0), 1, color='purple', fill=False)
ax_circle.add_artist(circle)
ax_circle.set_xlim(-1.2, 1.2)
ax_circle.set_ylim(-1.2, 1.2)
ax_circle.set_aspect('equal')
ax_circle.grid(True)
ax_circle.set_title("Eenheidscirkel en Rechthoekige Driehoek")
# Assen door oorsprong
ax_circle.spines['left'].set_position('zero')
ax_circle.spines['bottom'].set_position('zero')
ax_circle.spines['right'].set_color('none')
ax_circle.spines['top'].set_color('none')
ax_circle.xaxis.set_ticks([-1, 1])
ax_circle.yaxis.set_ticks([-1, 1])
ax_circle.text(1.05, 0, 'x', fontsize=12)
ax_circle.text(0, 1.05, 'y', fontsize=12)
ax_circle.text(-0.15, -0.15, 'O', fontsize=12)
# Hoek en coördinaten
theta_rad = np.deg2rad(theta)
x = np.cos(theta_rad)
y = np.sin(theta_rad)
# Rechthoekige driehoek
ax_circle.plot([0, x], [0, y], color='black') # Hypotenusa
ax_circle.plot([0, x], [0, 0], color='red') # x-component
ax_circle.plot([x, x], [0, y], color='blue') # y-component
ax_circle.plot(x, y, 'ko') # Punt P
ax_circle.text(x + 0.05, y, f'P(', fontsize=10)
ax_circle.text(x + 0.15, y, f'{x:.2f}', fontsize=10, color='red')
ax_circle.text(x + 0.35, y, f', {y:.2f})', fontsize=10, color='blue')
# Hoekboog
arc_radius = 0.25
arc_angle = np.linspace(0, theta_rad, 100)
arc_x = arc_radius * np.cos(arc_angle)
arc_y = arc_radius * np.sin(arc_angle)
ax_circle.plot(arc_x, arc_y, 'gray')
ax_circle.text(
arc_radius * np.cos(theta_rad / 2),
arc_radius * np.sin(theta_rad / 2),
f'θ = {int(theta)}°',
fontsize=10
)
# Cos/Sin-grafieken
theta_deg = np.linspace(0, 360, 1000)
theta_rad_all = np.deg2rad(theta_deg)
cos_vals = np.cos(theta_rad_all)
sin_vals = np.sin(theta_rad_all)
ax_cos.plot(theta_deg, cos_vals, label='x(θ) = cos(θ)', color='red')
ax_cos.plot(theta, np.cos(theta_rad), 'ko')
ax_cos.text(theta + 5, np.cos(theta_rad), f'({int(theta)}°, {np.cos(theta_rad):.3f})', fontsize=9)
ax_sin.plot(theta_deg, sin_vals, label='y(θ) = sin(θ)', color='blue')
ax_sin.plot(theta, np.sin(theta_rad), 'ko')
ax_sin.text(theta + 5, np.sin(theta_rad), f'({int(theta)}°, {np.sin(theta_rad):.3f})', fontsize=9)
for ax, ylabel in zip([ax_cos, ax_sin], ['cos(θ)', 'sin(θ)']):
ax.set_xlim(0, 360)
ax.set_ylim(-1.2, 1.2)
ax.grid(True)
ax.axhline(0, color='black', linewidth=0.8)
ax.axvline(0, color='black', linewidth=0.8)
ax.set_ylabel(ylabel)
ax.set_xlabel('θ (graden)')
ax.spines['left'].set_position('zero')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xticks([0, 180, 360])
ax.set_yticks([-1, 1])
ax.legend()
plt.show()
# Interactieve slider
interact(plot_figure, theta=IntSlider(min=0, max=360, step=1, value=60, description='θ (graden)'));