{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Surface computations in SymPy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here I will compute the curvature for some surfaces in 3D." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from mpl_toolkits.mplot3d import Axes3D\n", "from matplotlib.colors import LightSource\n", "from sympy import *\n", "from sympy import init_printing" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%matplotlib notebook\n", "x, y, z, t = symbols('x y z t')\n", "u, v, a, b, R = symbols('u v a b R')\n", "k, m, n = symbols('k m n', integer=True)\n", "init_printing()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Torobius: Torus with the semi-axis following a Möbius strip" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start with an ellipse located in the $yz$ plane." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "ellipse = Matrix([[0, a*cos(u), b*sin(u)]]).T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can generate our surface as a composition of two rotations, one around the $z$-axis, and the other one with respect to an axis that is perpendicular to the ellipse.\n", "\n", "We can rotate that ellipse with respect to an axis that is perpendicular to it using the following matrix. Notice that we have a rotation angle that is a multiple of the parameter $v$. If we make $n=0$ we will have a doughnout like shape." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0\\\\0 & \\cos{\\left(n v \\right)} & - \\sin{\\left(n v \\right)}\\\\0 & \\sin{\\left(n v \\right)} & \\cos{\\left(n v \\right)}\\end{matrix}\\right]$" ], "text/plain": [ "⎡1 0 0 ⎤\n", "⎢ ⎥\n", "⎢0 cos(n⋅v) -sin(n⋅v)⎥\n", "⎢ ⎥\n", "⎣0 sin(n⋅v) cos(n⋅v) ⎦" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Qx = Matrix([[1, 0, 0],\n", " [0, cos(n*v), -sin(n*v)],\n", " [0, sin(n*v), cos(n*v)]])\n", "\n", "Qx" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And the rotation matrix around $z$ looks like" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}\\cos{\\left(v \\right)} & - \\sin{\\left(v \\right)} & 0\\\\\\sin{\\left(v \\right)} & \\cos{\\left(v \\right)} & 0\\\\0 & 0 & 1\\end{matrix}\\right]$" ], "text/plain": [ "⎡cos(v) -sin(v) 0⎤\n", "⎢ ⎥\n", "⎢sin(v) cos(v) 0⎥\n", "⎢ ⎥\n", "⎣ 0 0 1⎦" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Qz = Matrix([[cos(v), -sin(v), 0],\n", " [sin(v), cos(v), 0],\n", " [0, 0, 1]])\n", "\n", "Qz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need to translate the ellipse in the $y$ direction" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAACAAAABLCAYAAAARSYVtAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADR0lEQVRoBe1a3W0UMRDeQxGPKAoSBSwdHFABXAcBKgA6AKUCRDoAKkBJBwkVQNIBFIBEdOKRB5bv253ZeP2z53EO7sUjeW2PPTOfx/bac3tN0zRLpC6RTrqua26SoPdbQjfUds0eGpU+oMDOLn13K4Xld5Db92QfoX6oPPXA8iYjtcjC8EukwAMKaGO+WCw4Io5sjUSv3Uf6BI2XyE3kToFF8DM6v4XBUwoJoAvkK/BM03bLYlWM0X2tGicPZXqCYE5Yt5AZAJQ/RTqPGPkC3lK8EWmOs0oAPImr6tcDm1LtUTETAGd0V1FtA7OdaQuaTAAgfSAaOOc+Kai7fsNc3QpAdXEbboWsAHSUMePqnZ+xxhTPBEC2G3WpMVeveuXfvgdgkVtQjbkAFFRsi7r9JmWTB0SSL5uHEy1D5QGyS8dLkS4hywwABnhqXmFLjqeZbM9n4L8ITcxzSs8CjvYIhltRz+P1McD9n8NI3Pxmfmx5reYpyFOb36sCqB6oHqge2LkHzGcB3v+8lq+Q9DDqYwPU3SOaMSUPrSxaoheDU1NoJjJnMDQJXsFvpS0Z2KJ9DM2KpgBeIGjS2ZBdPwGINyJ65dDpd93BKxUBgA69+6duPwpw7dkLqqUAuAbWGG1w/mPUXBuchnPxRmDUZZQCoAeC0Yvxj2g7hXGC3Eglu0Ddy6j4tVigMYLiyjffjEy7AAZolLtmH6McdwDqXNkXPt/to2Xpi2rXlEyBzv9kgUEZR8/BHCFlEwHcQfqB9CdTKjX/XHgkzYda/HkbbNrsPfAL+T0pk5ckZ18H+x9CujbmwjfV/RsF2jRPAUdP+jpkkyev5qTxlzYAdl/PQ6v3tK6B55THfAf7H+zRMPuItxQwWVHai3I9JpS9B4vhWO9m1Bme8RwYDxyWwWfAskKOrAd63BdmHlkAoPzVjI6xKbffKICCdQpc2a2UK4DqgeqB6oGdeyDrVey/8vCu5ylXv5hoSFa/mOgS0UvqxkuICjA37QJZfJSbu/e17JBLJgBQeiCKdbSuHQVVv5jULyZB1OwuFL9sXYSUr19M6IX6xYRe2AqVLMKtGFYlFcDOPcCpYMy/0z8y8bfd1EfI2C8hBG2h2B+ZRvm/5e42tzHFIkgAAAAASUVORK5CYII=\n", "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}0\\\\R\\\\0\\end{matrix}\\right]$" ], "text/plain": [ "⎡0⎤\n", "⎢ ⎥\n", "⎢R⎥\n", "⎢ ⎥\n", "⎣0⎦" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "trans = Matrix([[0, R, 0]]).T\n", "\n", "trans" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The shape is then defined in parametric coordinates as" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}- \\left(R + a \\cos{\\left(u \\right)} \\cos{\\left(n v \\right)} - b \\sin{\\left(u \\right)} \\sin{\\left(n v \\right)}\\right) \\sin{\\left(v \\right)}\\\\\\left(R + a \\cos{\\left(u \\right)} \\cos{\\left(n v \\right)} - b \\sin{\\left(u \\right)} \\sin{\\left(n v \\right)}\\right) \\cos{\\left(v \\right)}\\\\a \\sin{\\left(n v \\right)} \\cos{\\left(u \\right)} + b \\sin{\\left(u \\right)} \\cos{\\left(n v \\right)}\\end{matrix}\\right]$" ], "text/plain": [ "⎡-(R + a⋅cos(u)⋅cos(n⋅v) - b⋅sin(u)⋅sin(n⋅v))⋅sin(v)⎤\n", "⎢ ⎥\n", "⎢(R + a⋅cos(u)⋅cos(n⋅v) - b⋅sin(u)⋅sin(n⋅v))⋅cos(v) ⎥\n", "⎢ ⎥\n", "⎣ a⋅sin(n⋅v)⋅cos(u) + b⋅sin(u)⋅cos(n⋅v) ⎦" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "torobius = Qz*(Qx*ellipse + trans)\n", "torobius" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "x_num = lambdify((u, v, n, a, b, R), torobius[0], \"numpy\")\n", "y_num = lambdify((u, v, n, a, b, R), torobius[1], \"numpy\")\n", "z_num = lambdify((u, v, n, a, b, R), torobius[2], \"numpy\")" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "u_par, v_par = np.mgrid[0:2*np.pi:50j, 0:2*np.pi:50j]\n", "\n", "X = x_num(u_par, v_par, 2, 0.5, 1., 5.)\n", "Y = y_num(u_par, v_par, 2, 0.5, 1., 5.)\n", "Z = z_num(u_par, v_par, 2, 0.5, 1., 5.)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " event.shiftKey = false;\n", " // Send a \"J\" for go to next cell\n", " event.which = 74;\n", " event.keyCode = 74;\n", " manager.command_mode();\n", " manager.handle_keydown(event);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = plt.figure(figsize=(6,5))\n", "ax = fig.add_subplot(111, projection='3d')\n", "gauss_K = gauss_num(u_par, v_par, 2, 0.5, 1., 5.)\n", "vmax = gauss_K.max()\n", "vmin = gauss_K.min()\n", "FC = (gauss_K - vmin) / (vmax - vmin)\n", "surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=plt.cm.YlGnBu(FC))\n", "surf.set_edgecolors(\"k\")\n", "ax.set_title(\"Gaussian curvature\", fontsize=18)\n", "ax.set_zlim(-2, 2);" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('