{ "cells": [ { "cell_type": "markdown", "id": "1c2bb917", "metadata": { "lines_to_next_cell": 2 }, "source": [ "# Plot 2D" ] }, { "cell_type": "code", "execution_count": null, "id": "845dcf1a", "metadata": {}, "outputs": [], "source": [ "\n", "# Copyright (c) 2018-2025 William Emerison Six\n", "#\n", "# This program is free software; you can redistribute it and/or\n", "# modify it under the terms of the GNU General Public License\n", "# as published by the Free Software Foundation; either version 2\n", "# of the License, or (at your option) any later version.\n", "#\n", "# This program is distributed in the hope that it will be useful,\n", "# but WITHOUT ANY WARRANTY; without even the implied warranty of\n", "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n", "# GNU General Public License for more details.\n", "#\n", "# You should have received a copy of the GNU General Public License\n", "# along with this program; if not, write to the Free Software\n", "# Foundation, Inc., 59 Temple Place - Suite 330,\n", "# Boston, MA 02111-1307, USA." ] }, { "cell_type": "markdown", "id": "b70a86ce", "metadata": {}, "source": [ "Problem 1\n", "---------\n" ] }, { "cell_type": "code", "execution_count": null, "id": "64fe7159", "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "import sympy\n", "\n", "from modelviewprojection.mathutils import (\n", " Vector1D,\n", " Vector2D,\n", " Vector3D,\n", " compose,\n", " compose_intermediate_fns,\n", " identity,\n", " inverse,\n", ")\n", "from modelviewprojection.mathutils import rotate as R\n", "from modelviewprojection.mathutils import scale_non_uniform_2d as S\n", "from modelviewprojection.mathutils import translate as T\n", "from modelviewprojection.nbplotutils import (\n", " create_basis,\n", " create_graphs,\n", " create_unit_circle,\n", " create_x_and_y,\n", " draw_isoceles_triangle,\n", " draw_right_triangle,\n", " draw_screen,\n", " draw_second_right_triangle,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "b58e1763", "metadata": {}, "outputs": [], "source": [ "T(Vector1D(5))" ] }, { "cell_type": "code", "execution_count": null, "id": "20b50649", "metadata": {}, "outputs": [], "source": [ "S(5, 6)" ] }, { "cell_type": "code", "execution_count": null, "id": "3b539e31", "metadata": {}, "outputs": [], "source": [ "inverse(T(Vector1D(5)))" ] }, { "cell_type": "code", "execution_count": null, "id": "5b64929e", "metadata": {}, "outputs": [], "source": [ "T(Vector2D(5, 6))" ] }, { "cell_type": "code", "execution_count": null, "id": "8b1ea187", "metadata": {}, "outputs": [], "source": [ "T(Vector3D(5, 6, 7))" ] }, { "cell_type": "code", "execution_count": null, "id": "af0f697f", "metadata": {}, "outputs": [], "source": [ "inverse(T(Vector3D(5, 6, 7)))" ] }, { "cell_type": "code", "execution_count": null, "id": "2d3a0e7f", "metadata": {}, "outputs": [], "source": [ "R(sympy.pi / 2)" ] }, { "cell_type": "code", "execution_count": null, "id": "f6e85ad8", "metadata": {}, "outputs": [], "source": [ "compose([R(sympy.pi / 2), T(Vector2D(5, 6))])" ] }, { "cell_type": "code", "execution_count": null, "id": "aab6550a", "metadata": {}, "outputs": [], "source": [ "inverse(compose([R(sympy.pi / 2), T(Vector2D(5, 6))]))" ] }, { "cell_type": "markdown", "id": "520df956", "metadata": {}, "source": [ "Draw graph paper\n", "----------------\n", "\n", "Just draw graph paper, where one unit in the x direction is blue,\n", "and one unit in the y direction is pink. The graph paper corresponds\n", "to the numbers on the left and on the bottom.\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "3187d56f", "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "fn = R(math.radians(53.130102))\n", "with create_graphs(graph_bounds=(5, 5)) as axes:\n", " create_basis(fn=fn)\n", " create_x_and_y(fn=fn)\n", " create_unit_circle(fn=fn)\n", " axes.set_title(fn._repr_latex_())" ] }, { "cell_type": "markdown", "id": "25098879", "metadata": {}, "source": [ "Draw relative graph paper\n", "-------------------------\n", "\n", "Draw two relative number lines, making a relative graph paper,\n", "but keep the original coordinate system on the left and bottom.\n", "Any point in the plane can be described using two different\n", "graph papers." ] }, { "cell_type": "code", "execution_count": null, "id": "4dd64f1d", "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "fn = R(math.radians(53.130102))\n", "with create_graphs(graph_bounds=(5, 5)) as axes:\n", " create_basis(fn=R(0.0))\n", " create_x_and_y(fn=R(0.0))\n", " create_basis(\n", " fn=fn,\n", " xcolor=(0, 1, 0),\n", " ycolor=(1, 1, 0),\n", " )\n", " create_x_and_y(\n", " fn=fn,\n", " xcolor=(0, 1, 0),\n", " ycolor=(1, 1, 0),\n", " )\n", " create_unit_circle(fn=fn)\n", " axes.set_title(fn._repr_latex_())" ] }, { "cell_type": "markdown", "id": "6539400e", "metadata": {}, "source": [ "Draw relative graph paper\n", "-------------------------\n", "\n", "Draw two relative number lines, making a relative graph paper,\n", "but keep the original coordinate system on the left and bottom.\n", "Any point in the plane can be described using two different\n", "graph papers." ] }, { "cell_type": "code", "execution_count": null, "id": "8efe6aec", "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "fn = R(math.radians(53.130102))\n", "with create_graphs(graph_bounds=(5, 5)) as axes:\n", " create_basis(fn=R(0.0))\n", " create_x_and_y(fn=R(0.0))\n", " create_basis(\n", " fn=fn,\n", " xcolor=(0, 1, 0),\n", " ycolor=(1, 1, 0),\n", " )\n", " create_x_and_y(\n", " fn=fn,\n", " xcolor=(0, 1, 0),\n", " ycolor=(1, 1, 0),\n", " )\n", " create_unit_circle(fn=fn)\n", " draw_right_triangle()\n", " draw_second_right_triangle()\n", " axes.set_title(fn._repr_latex_())" ] }, { "cell_type": "markdown", "id": "1d4561a0", "metadata": {}, "source": [ "Draw relative graph paper, defined by composed functions\n", "--------------------------------------------------------\n", "\n", "Draw a translated and rotated graph paper.\n", "You can read the sequence of composed functions\n", "in the order that they are applied, or in reverse order" ] }, { "cell_type": "code", "execution_count": null, "id": "c53099eb", "metadata": {}, "outputs": [], "source": [ "fn = compose(\n", " [\n", " R(sympy.pi / 4),\n", " T(Vector2D(x=2.0, y=0.0)),\n", " ]\n", ")\n", "with create_graphs() as axes:\n", " create_basis(\n", " fn=fn,\n", " )\n", " create_x_and_y(fn=fn)\n", " create_unit_circle(fn=fn)\n", " axes.set_title(fn._repr_latex_())" ] }, { "cell_type": "markdown", "id": "1e0f09d4", "metadata": {}, "source": [ "Composed functions, read bottom up\n", "----------------------------------\n", "\n", "The sequence of functions shown, where the translate\n", "is applied first, and operations are relative to the\n", "units on the left and bottom." ] }, { "cell_type": "code", "execution_count": null, "id": "f118c9a5", "metadata": {}, "outputs": [], "source": [ "for f in compose_intermediate_fns([R(sympy.pi / 4), T(Vector2D(x=2.0, y=0.0))]):\n", " # TODO - figure out if I can render the latex as part of one markdown command,\n", " # if I were to uncomment out this line and other markdown lines,\n", " # the build of HTML would fail\n", "\n", " with create_graphs() as axes:\n", " create_basis(fn=f)\n", " create_x_and_y(fn=f)\n", " create_x_and_y()\n", " draw_isoceles_triangle(fn=f)\n", " create_unit_circle(fn=f)\n", " create_unit_circle()\n", " axes.set_title(f._repr_latex_())" ] }, { "cell_type": "markdown", "id": "c39eee95", "metadata": {}, "source": [ "Composed functions, read top down\n", "---------------------------------\n", "\n", "The sequence of functions shown, where we visualize\n", "the rotate first, and then the translate relative to\n", "that relative graph paper.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "07523f4a", "metadata": { "lines_to_next_cell": 0 }, "outputs": [], "source": [ "for f in compose_intermediate_fns(\n", " [\n", " R(sympy.pi / 4),\n", " T(Vector2D(x=1.0, y=0.0)),\n", " ],\n", " relative_basis=True,\n", "):\n", " with create_graphs() as axes:\n", " create_basis(fn=f)\n", " create_x_and_y(fn=f)\n", " draw_isoceles_triangle(fn=f)\n", " create_unit_circle(fn=f)\n", " axes.set_title(f._repr_latex_())" ] }, { "cell_type": "code", "execution_count": null, "id": "721d6804", "metadata": { "lines_to_next_cell": 0 }, "outputs": [], "source": [ "screen_width: int = 4\n", "screen_height: int = 3\n", "\n", "for f in compose_intermediate_fns(\n", " [\n", " T(Vector2D(-0.5, -0.5)),\n", " S(screen_width, screen_height),\n", " S(0.5, 0.5),\n", " T(Vector2D(x=1.0, y=1.0)),\n", " ],\n", " relative_basis=False,\n", "):\n", " with create_graphs(graph_bounds=(6, 6)) as axes:\n", " # create_basis(fn=f)\n", " # create_x_and_y(fn=f)\n", " create_basis(fn=identity())\n", " create_x_and_y(fn=identity())\n", " # draw_ndc(fn=f)\n", " draw_screen(width=screen_width, height=screen_height, fn=f)\n", " axes.set_title(f._repr_latex_())" ] }, { "cell_type": "code", "execution_count": null, "id": "86508fd2", "metadata": {}, "outputs": [], "source": [ "screen_width: int = 4\n", "screen_height: int = 3\n", "\n", "for f in compose_intermediate_fns(\n", " [\n", " T(Vector2D(-0.5, -0.5)),\n", " S(screen_width, screen_height),\n", " S(0.5, 0.5),\n", " T(Vector2D(x=1.0, y=1.0)),\n", " ],\n", " relative_basis=True,\n", "):\n", " with create_graphs(graph_bounds=(6, 6)) as axes:\n", " # create_basis(fn=f)\n", " # create_x_and_y(fn=f)\n", " create_basis(fn=identity())\n", " create_x_and_y(fn=f)\n", " # draw_ndc(fn=f)\n", " draw_screen(width=screen_width, height=screen_height, fn=f)\n", " axes.set_title(f._repr_latex_())" ] }, { "cell_type": "code", "execution_count": null, "id": "d30b1619", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "f47fc2f5", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }