{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Catmull-Rom splines ##" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Definition of this class of curves ###" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Catmull-Rom interpolation problem defined in [Catmull, E. and R. Rom, *A Class of Local Interpolationg Splines*, in Barnhill R.E. and R.F. Riesenfeld (eds.), Computer Aided Geometric Design, Academic Press, New York, 1974.] is formulated as follows:\n", "\n", "Given $n+1$ points, $P_0, P_1, \\ldots, P_n$, $n\\geq 3$, find a piecewise cubic curve, parameterized by\n", "$c:[1, n-1]\\to\\mathbb{R}^d$ (usually, d=2,3) such \n", "that $c(i)=P_{i}$, for $i\\in\\{1,2\\ldots, n-1\\}$, and the tangent vector at each interpolatory point, $P_i$, $i=\\overline{1, n-1}$, to be colinear with the vector $\\overrightarrow{P_{i-1}P_{i+1}}$:\n", "\n", "$$\\vec{\\dot{c}}(i)=s\\overrightarrow{P_{i-1}P_{i+1}},\n", "$$ where $s\\in(0,1]$. Usually one takes s=0.5.\n", "\n", "Hence given n+1 points, $P_0, P_1, \\ldots, P_n$, a CR curve interporlates only the points $P_1, P_2, \\ldots, P_{n-1}$.\n", "The first and the last point influence only the direction of tangent at $P_1$, respectively, $P_{n-1}$.\n", "\n", "\n", "\n", "Since the distance between two consecutive knots, $t_i=i$, $t_{i+1}=i+1$ is constant, such a curve is called uniform parameterized Catmull-Rom curve.\n", "\n", "Being a cubic above each interval $[i, i+1]$, an arc of CR curve on such an interval can be defined\n", "as a Bézier curve of control points ${\\bf b}_0, {\\bf b}_1, {\\bf b}_2, {\\bf b}_3$,\n", "with\n", "${\\bf b}_0=P_i, {\\bf b}_3=P_{i+1}$.\n", "\n", "But the tangent at end points, ${\\bf b}_0$ and ${\\bf b}_3$, of a Bézier curve, is\n", " $3\\overrightarrow{{\\bf b}_0{\\bf b}_1}$, respectively $3\\overrightarrow{{\\bf b}_2{\\bf b}_3}$.\n", "Thus we get:\n", "\n", "$$ {\\bf b}_1=P_i+s(P_{i+1}-P_{i-1})/3, \\:\\: {\\bf b}_2=P_{i+1}-s(P_{i+2}-P_{i})/3$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "Below we illustrate the above stated properties of a CR curve, defined by 7 points. Attached to the third arc, joining the points $P_3, P_4$,\n", "is the Bézier control polygon defining that arc of curve. The tangent at $P_2$ is obviously parallel to \n", "$\\overrightarrow{P_1P_3}$." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAgAElEQVR4XuydC5xWVbn/nwEGhjuK\nekwDsuwoKKjpCRU4WZkVTFoaXoYuFl4YtUxNhbyFWkAnNbXA9BztVFy8dNEAb4gamJaUHsDLv0wF\nNfNWw51hhpn/57dxT++8vDPzzjzvZV+++/PxQ8G79l7r+6x3Zn33Ws9aFc3Nzc3GBQEIQAACEIAA\nBCAAAQhAoAQEKhCQElDmERCAAAQgAAEIQAACEIBAQAABoSNAAAIQgAAEIAABCEAAAiUjgICUDDUP\nggAEIAABCEAAAhCAAAQQEPoABCAAAQhAAAIQgAAEIFAyAghIyVDzIAhAAAIQgAAEIAABCEAAAaEP\nQAACEIAABCAAAQhAAAIlI4CAlAw1D4IABCAAAQhAAAIQgAAEEBD6AAQgAAEIQAACEIAABCBQMgII\nSMlQ8yAIQAACEIAABCAAAQhAAAGhD0AAAhCAAAQgAAEIQAACJSOAgJQMNQ+CAAQgAAEIQAACEIAA\nBBAQ+gAEIAABCEAAAhCAAAQgUDICCEjJUPMgCEAAAhCAAAQgAAEIQAABoQ9AAAIQgAAEIAABCEAA\nAiUjgICUDDUPggAEIAABCEAAAhCAAAQQEPoABCAAAQhAAAIQgAAEIFAyAghIyVDzIAhAAAIQgAAE\nIAABCEAAAaEPQAACEIAABCAAAQhAAAIlI4CAlAw1D4IABCAAAQhAAAIQgAAEEBD6AAQgAAEIQAAC\nEIAABCBQMgIISMlQ8yAIQAACEIAABCAAAQhAAAGhD0AAAhCAAAQgAAEIQAACJSOAgJQMNQ+CAAQg\nAAEIQAACEIAABBAQ+gAEIAABCEAAAhCAAAQgUDICCEjJUPMgCEAAAhCAAAQgAAEIQAABoQ9AAAIQ\ngAAEIAABCEAAAiUjgICUDDUPggAEIAABCEAAAhCAAAQQEPoABCAAAQhAAAIQgAAEIFAyAghIyVDz\nIAhAAAIQgAAEIAABCEAAAaEPQAACEIAABCAAAQhAAAIlI4CAlAw1D4IABCAAAQhAAAIQgAAEEBD6\nAAQgAAEIQAACEIAABCBQMgIISMlQ8yAIQAACEIAABCAAAQhAAAGhD0AAAhCAAAQgAAEIQAACJSOA\ngJQMNQ+CAAQgAAEIQAACEIAABBAQ+gAEIAABCEAAAhCAAAQgUDICCEjJUPMgCEAAAhCAAAQgAAEI\nQAABoQ9AIIPAunXrbMuWLS1/U1lZaVVVVXb33XfbihUrbOzYsXb88cfbmjVrbMmSJfbHP/7Rzjrr\nLDvwwAMjzfGdd96xbt262S677FL2ejY0NNjNN99sYv23v/3NfvjDH5a9Trkq0NzcbC+99JK9//3v\nb/XPq1evtl/96lf25ptvBn3hox/9aCTrn9ZKbd261dTf995774IjeO211+yBBx6wJ5980k4//XQ7\n5JBDOnzG+vXr7e9//7vV19db7969bbfddrNBgwZ1WK6UH9DPtkceecRefPFFu+6666xXr162cOFC\n+8Mf/mB9+/a1iy++uM3qbNy40fRf5tW9e3fr379/8LOTCwIQgEAuAggI/QICGQQ0uHz44Yftnnvu\nsSOPPNI++clPBn/qOu200+w//uM/7Mwzzwz+vwbQn//85+2qq66yww8/PNIcVfcePXrYTTfdVPZ6\n3nnnncFAR4Oan/zkJ3bqqaeWvU65KvDb3/42iO306dNb+sC2bduspqbGbrzxRmtqarLnnnvOjj76\n6EjWP62VUmw0eL7rrruCQXChL72gOPbYY+2yyy6z//zP/2zz9k899ZTdeuutQR1GjhxpPXv2DETk\niSeeCMr87Gc/K3TVXPcL+7t+9kmUdIml+vjs2bPbvLe+y8uWLbOf//zn9oEPfMA++MEP2ubNm+0v\nf/lLIDL62TN69GhX3SgMAQgkjwACkryY0iIngT//+c929tln23nnnWfjx49vuVuxBWTTpk2mQYtm\nWTxXrvssX748mAEJZcpzf2/ZCy64IBiQRVU8wvbpzbUGY8cdd1zLQPb//u//7Jvf/Kbdf//9AU+u\nwhIQV0m/5/rrX/9qipNmp4px5SMgGpBLXqdOnWof+9jHWlVD4qq//973vpdX9TQzccQRRwSD+WJe\nXRUQ1Sl8GSM5/8pXvhJUU+2UvP/+978P5EQzP1wQgAAEQgIICH0BAlkEyiUgCxYssH/84x/Bki7P\nVaj7eOrQXlmJhwZlX/rSl4r1iKLdd+nSpTZjxgx78MEHi/aMtN5Yb9qvv/76SMzStRcDLfH6zGc+\n0+YMiJZafeELX7D99tvPrr766py3Uj/KFpNcH9SzNKj/6U9/av369Stq1yi0gKiyjz76aMDg29/+\nto0ZM6ao9efmEIBAvAggIPGKF7UtAYGuCshDDz1k9957rx166KF2yimnBMst9Ab96aeftgsvvND2\n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\n4iBAgAABAk0JCJCmuCwmQIAAgX/+85/R2dkZ69atiyuvvDI6OjqgECBAgACBfgsIkH5TWUiAAAEC\nxQfQv/GNb8SiRYvipz/9adxxxx2xcuXKGDZsGBwCBAgQINAvAQHSLyaLCBAgQKD4APqNN94Yxx9/\nfMydOzceeeSRWLZsWUyaNCkWLFgQY8eOhUSAAAECBBoKCJCGRBYQIECAAAECBAgQINAqAQHSKknP\nQ4AAAQIECBAgQIBAQwEB0pDIAgIECBAgQIAAAQIEWiUgQFol6XkIECBAgAABAgQIEGgoIEAaEllA\ngAABAgQIECBAgECrBARIqyQ9DwECBAgQIECAAAECDQUESEMiCwgQIECAAAECBAgQaJWAAGmVpOch\nQIAAAQIECBAgQKChgABpSGQBAQIECBAgQIAAAQKtEhAgrZL0PAQIECBAgAABAgQINBQQIA2JLCBA\ngAABAgQIECBAoFUCAqRVkp6HAAECBAgQIECAAIGGAgKkIZEFBAgQIECAAAECBAi0SkCAtErS8xAg\nQIAAAQIECBAg0FBAgDQksoAAAQIECBAgQIAAgVYJCJBWSXoeAgQIECBAgAABAgQaCgiQhkQWECBA\ngAABAgQIECDQKgEB0ipJz0OAAAECBAgQIECAQEMBAdKQyAICBAgQIECAAAECBFolIEBaJel5CBAg\nQIAAAQIECBBoKCBAGhJZQIAAAQIECBAgQIBAqwQESKskPQ8BAgQIECBAgAABAg0FBEhDIgsIECBA\ngAABAgQIEGiVgABplaTnIUCAAAECBAgQIECgoYAAaUhkAQECBAgQIECAAAECrRIQIK2S9DwECBAg\nQIAAAQIECDQUECANiSwgQIAAAQIECBAgQKBVAgKkVZKehwABAgQIECBAgACBhgL/B53nEeaQZqW3\nAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import Image\n", "Image(filename='Imag/Catmull-Rom-curve.png')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Catmull-Rom interpolating curves can be evaluated\n", "at a point using a recursive scheme similar to the [de Boor algorithm](http://nbviewer.jupyter.org/github/empet/geom_modeling/blob/master/FP-Bezier-Bspline.ipynb) for B-spline curves.\n", "\n", "Usually a cubic spline curve is $C^2$ at knots. Although the CR curves are only $C^1$ at each knot, \n", "they are sometimes called Catmull Rom spline curves, due to the similarities of the algorithms of\n", "evaluation, and other common properties.\n" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Let us point out the drawback of the uniform parameterization, that led to defining CR splines with\n", "non-uniform knots.\n", "\n", "A $C^1$-parameterization, $c:[a,b]\\to\\mathbb{R}^d$, of a curve can be interpreted as defining the motion of the point c(t), along the trace of $c$, during the time from a to b.\n", "\n", "When the parameterization of a CR curve is uniform, the point $c(t)$ spends the same amount of time on each arc of ends $P_i, P_{i+1}$, $i=1,2, ...n-1$, irrespective of the distance between $P_i, P_{i+1}$.\n", "\n", "If the distance between two data points is large, the point c(t)\n", "moves with a high speed. If the next two interpolatory points, $P_{i+1}, P_{i+2}$, are closer, then the moving point will overshoot since it cannot abruptly change its speed.\n", "\n", "Barry and Goldman [P. J. Barry, R. N. Goldman, *A recursive evaluation algorithm for a class of Catmull–Rom splines*, SIGGRAPH Computer Graphics, 22(4):199-204, 1988] extended the definition of uniform parameterized CR splines to curves whose parameterization incorporates the\n", "distance between any two adjacent interpolatory points. \n", "\n", "Namely, given the points $P_0, P_1, \\ldots, P_n$, one defines a knot sequence, $t_0, t_1, \\ldots, t_{n}$ as follows:\n", " \n", "$$\\begin{array}{lll}t_0&=&0\\\\\n", " t_i&=&t_{i-1}+||\\overrightarrow{P_{i-1}P_i}||^\\alpha, \\quad \\alpha\\in[0,1]\\end{array}$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " A $C^1$-piecewise cubic, that interpolates the given points, i.e. $c(t_i)=P_i$, $i=1,2, \\ldots, n-1$, is defined at any $u\\in[t_i, t_{i+1}]$ through a recursive scheme in which are involved only four points, $P_{i-1}, P_i, P_{i+1}, P_{i+2}$\n", " and the knots $t_{i-1}, t_i, t_{i+1}, t_{i+2}$:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$P_j^r=(1-\\omega^{r-1}_j)P^{r-1}_j+\\omega^{r-1}_jP^{r-1}_{j+1}, \\quad r=1,2,\\quad j=i-1, i, i+1, i+2,\n", "$$\n", "\n", "with $\\omega^r_j(u)=\\displaystyle\\frac{u-t_j}{t_{j+1+r}-t_j}$. The superscript $r$ points out the level of recursion. $P_j^0=P_j$.\n", "\n", "\n", "The last two points, $P^2_{i-1}$, $P^2_{i}$, are finally interpolated linearly, to get $c(u)$, the point on the CR curve corresponding to the parameter $u\\in[t_i, t_{i+1}]$:\n", "\n", "$$c(u)=\\left(1-\\displaystyle\\frac{u-t_i}{t_{i+1}-t_i}\\right) P^2_{i-1}+\\displaystyle\\frac{u-t_i}{t_{i+1}-t_i} P^2_{i}$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We note that in the first two steps, the points $P_j^r$, $r=1,2$, are computed via de Boor algorithm for B-splines, while in the last step, $c(u)$ is computed according to the [Neville algorithm](https://en.wikipedia.org/wiki/Neville%27s_algorithm) for evaluating Lagrange polynomials." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The parameter $\\alpha$ in the definition of knots controls the geometry of the interpolating CR curve.\n", "For $\\alpha=0.5$ the corresponding CR curve is called centripetal Catmull-Rom curve, for $\\alpha=1$, chordal Catmull\n", "Rom curve, while for $\\alpha=0$ we get the initial uniform parameterized CR spline.\n", "\n", "For $\\alpha$ close to $0$ the corresponding CR curve can exhibit singular points (self intersections or cusps) within short curve segments(with small distance between $P_i, P_{i+1}$).\n", "\n", "In [C Yuksel, S Schaefer, J Keyser,\n", "*Parameterization and Applications of Catmull-Rom Curves*,\n", "Computer Aided Design, 43, 7, 2011] it was deduced that the optimal parameter that corresponds to CR splines with no singular points is $\\alpha=0.5$.\n", "Moreover a centripetal CR curve follows more tightly the interpolatory points than CR curves corresponding to $\\alpha$ close to 0 or to 1.\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "That is why centripetal Catmull-Rom splines are now widely used in interactive generation of interpolating curves." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Python implementation of the Catmull-Rom spline generation ###" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of the above mixture of the de Boor and Neville algorithm we generate each segment of CR curve,\n", "as a Bezier curve.\n", "\n", "Over each interval $[t_i, t_{i+1}]$, the CR curve is a cubic polynomial curve, hence it can be defined as\n", "a Bézier curve, parameterized over $[0,1]$. Theoretically, the standard polynomial parameterization\n", "is obtained applying (using a Computer Algebra System) the two steps of de Boor algorithm defined above, and a step of the Neville algo.\n", "Then this parameterization is converted to one in which the polynomial components are expressed \n", "in Bernstein basis, to get the Bézier form of that polynomial segment of curve.\n", "\n", "The expression of the Bézier control points as combinations of four consecutive interpolatory \n", "points, $P_{0}, P_1, P_{2}, P_{3}$, involved in the definition of a CR segment, is given in the function `ctrl_bezier(P, d)`. `d` is a list of values involved in knot definition, $d_j=||\\overrightarrow{P_{j}P_{j+1}}||^\\alpha$, $j=0,1,2$." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define the function `knot_interval`, that computes the values \n", "$d_j=||\\overrightarrow{P_{j}P_{j+1}}||^\\alpha$, $j=\\overline{0, n-1}$. If we want define a closed curve, then we extend the list of points $P_0, P_1, \\ldots, P_n$ with $P_0, P_1, P_2$:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def knot_interval(i_pts, alpha=0.5, closed=False):\n", " if len(i_pts)<4:\n", " raise ValueError('CR-curves need at least 4 interpolatory points')\n", " #i_pts is the list of interpolatory points P[0], P[1], ... P[n]\n", " if closed:\n", " i_pts+=[i_pts[0], i_pts[1], i_pts[2]]\n", " i_pts=np.array(i_pts)\n", " dist=np.linalg.norm(i_pts[1:, :]-i_pts[:-1,:], axis=1)\n", " return dist**alpha\n", " \n", "\n", "def ctrl_bezier(P, d):\n", " #Associate to 4 consecutive interpolatory points and the corresponding three d-values, \n", " #the Bezier control points\n", " if len(P)!=len(d)+1!=4:\n", " raise ValueError('The list of points and knot intervals have inappropriate len ')\n", " P=np.array(P) \n", " bz=[0]*4\n", " bz[0]=P[1]\n", " bz[1]=(d[0]**2*P[2]-d[1]**2*P[0] +(2*d[0]**2+3*d[0]*d[1]+d[1]**2)*P[1])/(3*d[0]*(d[0]+d[1]))\n", " bz[2]=(d[2]**2*P[1]-d[1]**2*P[3] +(2*d[2]**2+3*d[2]*d[1]+d[1]**2)*P[2])/(3*d[2]*(d[1]+d[2]))\n", " bz[3]=P[2]\n", " return bz\n", "\n", "def Bezier_curve(bz, nr=100):\n", " #implements the de Casteljau algorithm to compute nr points on a Bezier curve\n", " \n", " t=np.linspace(0,1, nr)\n", " N=len(bz) \n", " points=[]# the list of points to be computed on the Bezier curve\n", " for i in range(nr):#for each parameter t[i] evaluate a point on the Bezier curve \n", " #via De Casteljau algorithm\n", " aa=np.copy(bz) \n", " for r in range(1,N):\n", " aa[:N-r,:]=(1-t[i])*aa[:N-r,:]+t[i]*aa[1:N-r+1,:]# convex combination\n", " points.append(aa[0,:]) \n", " return points \n", "\n", "def Catmull_Rom(i_pts, alpha=0.5, closed=False):\n", " #returns the list of points computed on the interpolating CR curve\n", " #i_pts the list of interpolatory points P[0], P[1], ...P[n]\n", " curve_pts=[]#the list of all points to be computed on the CR curve\n", " d=knot_interval(i_pts, alpha=alpha, closed=closed)\n", " for k in range(len(i_pts)-3):\n", " cb=ctrl_bezier(i_pts[k:k+4], d[k:k+3])\n", " curve_pts.extend(Bezier_curve(cb, nr=100))\n", " \n", " return np.array(curve_pts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we give a list of points and define the CR curve corresponding to $\\alpha=0,0.5,1$:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "P=[[-0.72, -0.3], [0,0], [1., 0.8], [1.1, 0.5], [2.7, 1.2], [3.4, 0.27]]\n", "\n", "curve0=Catmull_Rom(P, alpha=0, closed=False)\n", "curve1=Catmull_Rom(P, alpha=0.5, closed=False)\n", "curve2=Catmull_Rom(P, alpha=1.0, closed=False)\n", "xp, yp=zip(*P)\n", "\n", "fig=plt.figure(figsize=(9,6))\n", "plt.plot(curve0[:,0], curve0[:,1], 'r', xp, yp, 'go' )\n", "plt.plot(curve1[:,0], curve1[:,1], 'g')\n", "plt.plot(curve2[:,0], curve2[:,1], 'b')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The green curve is the centripetal CR spline interpolating the central 4 from 6 points. It folows closely\n", "the given interpolatory points." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to get more insights into CR curves properties we give the possibility to generate them interactively.\n", "Choose the interpolatory points, by clicking the left mouse button at the desired position. When the right button is pressed, the corresponding curve is generated:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#enable interactivity in notebook:\n", "%matplotlib notebook " ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def curve_plot(i_pts, alpha=0.5, closed=False):\n", " curve_pts=Catmull_Rom(i_pts, alpha, closed=closed)\n", " # plot the interpolating curve\n", " plt.plot(curve_pts[:,0], curve_pts[:,1], 'b') " ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class catrom(object): \n", " \n", " def __init__(self, alpha=0.5, closed=False):\n", " self.interp_pts=[] # list of interpolating points\n", " self.alpha=alpha\n", " self.closed=closed# boolean value\n", " def callback(self, event): #select interpolating points with left mouse button click\n", " if event.button==1 and event.inaxes:\n", " x,y = event.xdata, event.ydata\n", " self.interp_pts.append([x,y]) \n", " plt.plot(x, y, 'bo') \n", " \n", " elif event.button==3: #press right button to plot the curve\n", " curve_plot(self.interp_pts, self.alpha, self.closed)\n", " plt.draw() \n", " \n", " else: pass\n", " \n", " def caxis(self):#define axes for plot\n", " fig = plt.figure(figsize=(8, 6))\n", " ax = fig.add_subplot(111)\n", " \n", " ax.set_xlim(0,10)\n", " ax.set_ylim(0,10)\n", " ax.grid('on') \n", " ax.set_autoscale_on(False)\n", " fig.canvas.mpl_connect('button_press_event', self.callback)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\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", " 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", " this.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 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);\n", " canvas.attr('height', height);\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": [ "cv=catrom(closed=True)\n", "cv.caxis()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\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", " 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", " this.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 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);\n", " canvas.attr('height', height);\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 = $('