{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "In Lecture 28 of MCS 320, we animate two and three dimensional plots." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Increasing the Frequency" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider a periodic function, where the frequence is a parameter." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f(k) = exp(-x^2)*sin(2*k*pi*x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ``f`` is a function in one variable ``k`` which controls the frequency of the expression for the periodic function with decaying amplitude." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An animation is a list of frames. Let us plot the first two frames, for ``k`` equal to 1 and 2." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "one = plot(f(1), (x, -2, 2))\n", "one.show(figsize=3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "two = plot(f(2), (x, -2, 2))\n", "two.show(figsize=3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "onetwo = animate([one, two])\n", "onetwo.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Even already in this very simple animation with two frames, we have already made the mistake of not fixing the range of ``y`` with ``ymin`` and ``ymax``." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot(f(1), (x, -2, 2), ymin=-1, ymax=1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "frames = [plot(f(i), (x, -2, 2), ymin=-1, ymax=1) for i in range(1, 11)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "frames[0].show(figsize=3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = animate(frames)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With ``iterations`` we set the number of iterations (by default, the animation runs in a loop) and with ``delay`` we control the speed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.show(iterations=20, delay=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A ``graphics_array`` is convenient to display the frames in the animation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = a[:5].graphics_array(ncols=5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g.show(figsize=[8,2], axes=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can save the animation as a ``.gif`` file." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.save(filename='ourfirstanimation.gif')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. A Moving Tangent Line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider the tangent line to a moving point on the unit circle." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider an animation of the tangent line moving to any point on the unit circle.\n", "First we make an animation of the moving point, using 10 frames.\n", "The first frame draws the unit circle and the first point at angle $2 \\pi/10$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of ``implicit_plot``, we use the primitives ``circle`` and ``line`` for the circle and the tangent line." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "unitcircle = circle((0,0),1)\n", "firstpoint = point((cos(2*pi/10), sin(2*pi/10)), color='red',size=50)\n", "(unitcircle+firstpoint).show(figsize=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we make a list of points.\n", "The angle will be $2 k \\pi/10$, for $k$ ranging from 1 to 10.\n", "In the animate we must give the xmin, xmax, ymin, ymax, because otherwise the point remains fixed\n", "and the coordinate axes are moving." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "movingpoints = [point((cos(2*k*pi/10), sin(2*k*pi/10)), color='red', size=50) for k in range(1,11)]\n", "a = animate(movingpoints,xmin=-1,xmax=1,ymin=-1,ymax=1)\n", "a.show(iterations=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the tangent line, we know that vectors perpendicular to $(\\cos(t), \\sin(t))$\n", "are $(-\\sin(t),\\cos(t))$ and $(\\sin(t), -\\cos(t))$ which we use as the end points of the tangent line. We define functions to make the points because we will generate lists of plots." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pt(k) = (cos(2*k*pi/10), sin(2*k*pi/10))\n", "v1(k) = (-sin(2*k*pi/10), cos(2*k*pi/10))\n", "v2(k) = (-v1(k)[0],-v1(k)[1])\n", "print(pt)\n", "print(v1)\n", "print(v2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A(k) = ((pt(k)[0]+v1(k)[0]),pt(k)[1]+v1(k)[1])\n", "B(k) = ((pt(k)[0]+v2(k)[0]),pt(k)[1]+v2(k)[1])\n", "print(A)\n", "print(B)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "tangentline1 = line([A(1), B(1)],color='green')\n", "(unitcircle+firstpoint+tangentline1).show(figsize=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we make the animation of 10 tangent lines." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "movinglines = [unitcircle+line([A(k), B(k)], color='green') for k in range(1,11)]\n", "a = animate(movinglines,figsize=4,xmin=-1.5,xmax=1.5,ymin=-1.5,ymax=1.5)\n", "g = a.graphics_array(ncols=10)\n", "g.show(axes=False, figsize=[10,10])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "frames = [movinglines[k]+movingpoints[k] for k in range(10)]\n", "a = animate(frames, figsize=4, xmin=-1.5,xmax=1.5,ymin=-1.5,ymax=1.5,axes=False)\n", "a.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us look at all frames all at once." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = a.graphics_array(ncols=10)\n", "g.show(axes=False, figsize=[10,10])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. Spin Plot of a Surface" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One useful animation of a surface is to make a spin plot. We can spin a surface by rotating the x-, y-, or z-axis." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "x, y, z = var('x, y, z')\n", "c2 = implicit_plot3d(x^2 - y, (x, -1, 1), (y, 0 , 1), (z, -1, 1))\n", "show(c2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Xframes = [implicit_plot3d(x^2 - y, (x, -1, 1), (y, 0 , 1), (z, -1, 1)).rotateX(k*2*pi/10) for k in range(1, 21)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Xa = animate(Xframes)\n", "Xa.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Yframes = [implicit_plot3d(x^2 - y, (x, -1, 1), (y, 0 , 1), (z, -1, 1)).rotateY(k*2*pi/10) for k in range(1, 21)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Ya = animate(Yframes)\n", "Ya.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Zframes = [implicit_plot3d(x^2 - y, (x, -1, 1), (y, 0 , 1), (z, -1, 1)).rotateZ(k*2*pi/10) for k in range(1, 21)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Za = animate(Zframes)\n", "Za.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4. A Space Curve Knot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A space curve is defined by functions in one parameter. One natural animation is to extend the range of the parameter in each frame of the animation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "reset()\n", "t = var('t')\n", "r = 2 + 4/5*cos(7*t)\n", "z = sin(7*t)\n", "curve = [r*cos(4*t), r*sin(4*t), z]\n", "parametric_plot3d(curve,(t,0,2*pi), thickness=5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "frames = [parametric_plot3d(curve,(t,0,2*k*pi/20), thickness=5) for k in range(1,21)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = animate(frames, xmin=-3, xmax=3, ymin=-3, ymax=3, zmin=-3, zmax=3)\n", "a.show()" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 10.3", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10" } }, "nbformat": 4, "nbformat_minor": 4 }