{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Demo version of the ``square_limit`` topic notebook in ``examples/topics/geometry``.\n",
"\n",
"Most examples work across multiple plotting backends, this example is also available for:\n",
"* [Bokeh - square_limit](../bokeh/square_limit.ipynb)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import holoviews as hv\n",
"import numpy as np\n",
"from matplotlib.path import Path\n",
"from matplotlib.transforms import Affine2D\n",
"hv.extension('matplotlib')\n",
"hv.output(fig='svg')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Declaring data and transforms"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"spline=[(0.0,1.0),(0.08,0.98),(0.22,0.82),(0.29,0.72),(0.29,0.72),(0.3,0.64),(0.29,0.57),(0.3,0.5),\n",
"(0.3,0.5),(0.34,0.4),(0.43,0.32),(0.5,0.26),(0.5,0.26),(0.58,0.21),(0.66,0.22),(0.76,0.2),(0.76,0.2),\n",
"(0.82,0.12),(0.94,0.05),(1.0,0.0),(1.0,0.0),(0.9,0.03),(0.81,0.04),(0.76,0.05),(0.76,0.05),(0.69,0.04),\n",
"(0.62,0.04),(0.55,0.04),(0.55,0.04),(0.49,0.1),(0.4,0.17),(0.35,0.2),(0.35,0.2),(0.29,0.24),(0.19,0.28),\n",
"(0.14,0.31),(0.14,0.31),(0.09,0.35),(-0.03,0.43),(-0.05,0.72),(-0.05,0.72),(-0.04,0.82),(-0.02,0.95),(0.0,1.0),\n",
"(0.1,0.85),(0.14,0.82),(0.18,0.78),(0.18,0.75),(0.18,0.75),(0.16,0.74),(0.14,0.73),(0.12,0.73),(0.12,0.73),\n",
"(0.11,0.77),(0.11,0.81),(0.1,0.85),(0.05,0.82),(0.1,0.8),(0.08,0.74),(0.09,0.7),(0.09,0.7),(0.07,0.68),\n",
"(0.06,0.66),(0.04,0.67),(0.04,0.67),(0.04,0.73),(0.04,0.81),(0.05,0.82),(0.11,0.7),(0.16,0.56),(0.24,0.39),\n",
"(0.3,0.34),(0.3,0.34),(0.41,0.22),(0.62,0.16),(0.8,0.08),(0.23,0.8),(0.35,0.8),(0.44,0.78),(0.5,0.75),\n",
"(0.5,0.75),(0.5,0.67),(0.5,0.59),(0.5,0.51),(0.5,0.51),(0.46,0.47),(0.42,0.43),(0.38,0.39),(0.29,0.71),\n",
"(0.36,0.74),(0.43,0.73),(0.48,0.69),(0.34,0.61),(0.38,0.66),(0.44,0.64),(0.48,0.63),(0.34,0.51),(0.38,0.56),\n",
"(0.41,0.58),(0.48,0.57),(0.45,0.42),(0.46,0.4),(0.47,0.39),(0.48,0.39),(0.42,0.39),(0.43,0.36),(0.46,0.32),\n",
"(0.48,0.33),(0.25,0.26),(0.17,0.17),(0.08,0.09),(0.0,0.01),(0.0,0.01),(-0.08,0.09),(-0.17,0.18),(-0.25,0.26),\n",
"(-0.25,0.26),(-0.2,0.37),(-0.11,0.47),(-0.03,0.57),(-0.17,0.26),(-0.13,0.34),(-0.08,0.4),(-0.01,0.44),\n",
"(-0.12,0.21),(-0.07,0.29),(-0.02,0.34),(0.05,0.4),(-0.06,0.14),(-0.03,0.23),(0.03,0.28),(0.1,0.34),(-0.02,0.08),\n",
"(0.02,0.16),(0.09,0.23),(0.16,0.3)]\n",
"\n",
"rotT = Affine2D().rotate_deg(90).translate(1, 0)\n",
"rot45T = Affine2D().rotate_deg(45).scale(1. / np.sqrt(2.), 1. / np.sqrt(2.)).translate(1 / 2., 1 / 2.)\n",
"flipT = Affine2D().scale(-1, 1).translate(1, 0)\n",
"\n",
"def combine(obj):\n",
" \"Collapses overlays of Splines to allow transforms of compositions\"\n",
" if not isinstance(obj, hv.Overlay): return obj\n",
" return hv.Spline((np.vstack([el.data[0] for el in obj.values()]),\n",
" np.hstack([el.data[1] for el in obj.values()])))\n",
" \n",
"def T(spline, transform):\n",
" \"Apply a transform to a spline or overlay of splines\"\n",
" spline = combine(spline) \n",
" result = Path(spline.data[0], codes=spline.data[1]).transformed(transform)\n",
" return hv.Spline((result.vertices, result.codes))\n",
"\n",
"def beside(spline1, spline2, n=1, m=1):\n",
" den = float(n + m)\n",
" t1 = Affine2D().scale(n / den, 1)\n",
" t2 = Affine2D().scale(m / den, 1).translate(n / den, 0)\n",
" return combine(T(spline1, t1) * T(spline2, t2))\n",
"\n",
"def above(spline1, spline2, n=1, m=1):\n",
" den = float(n + m)\n",
" t1 = Affine2D().scale(1, n / den).translate(0, m / den)\n",
" t2 = Affine2D().scale(1, m / den)\n",
" return combine(T(spline1, t1) * T(spline2, t2))\n",
"\n",
"def nonet(p, q, r, s, t, u, v, w, x):\n",
" return above(beside(p, beside(q, r), 1, 2),\n",
" above(beside(s, beside(t, u), 1, 2),\n",
" beside(v, beside(w, x), 1, 2)), 1, 2)\n",
"\n",
"def quartet(p, q, r, s):\n",
" return above(beside(p, q), beside(r, s))\n",
"\n",
"def side(n,t):\n",
" if n == 0: \n",
" return hv.Spline(([(np.nan, np.nan)],[1]))\n",
" else: \n",
" return quartet(side(n-1,t), side(n-1,t), rot(t), t)\n",
"\n",
"def corner(n,u,t):\n",
" if n == 0:\n",
" return hv.Spline(([(np.nan, np.nan)],[1]))\n",
" else:\n",
" return quartet(corner(n-1,u,t), side(n-1,t), rot(side(n-1,t)), u)\n",
" \n",
"def squarelimit(n,u,t):\n",
" return nonet(corner(n,u,t), side(n,t), rot(rot(rot(corner(n,u,t)))),\n",
" rot(side(n,t)), u, rot(rot(rot(side(n,t)))), \n",
" rot(corner(n,u,t)), rot(rot(side(n,t))), rot(rot(corner(n,u,t))))\n",
"\n",
"def rot(el): return T(el,rotT)\n",
"def rot45(el): return T(el, rot45T)\n",
"def flip(el): return T(el, flipT)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Plot"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fish = hv.Spline((spline, [1,4,4,4]*34)) # Cubic splines\n",
"smallfish = flip(rot45(fish))\n",
"t = fish * smallfish * rot(rot(rot(smallfish)))\n",
"u = smallfish * rot(smallfish) * rot(rot(smallfish)) * rot(rot(rot(smallfish)))\n",
"\n",
"squarelimit(3,u,t).opts(\n",
" aspect='equal', bgcolor='white', linewidth=0.8,\n",
" fig_size=250, xaxis=None, yaxis=None)"
]
}
],
"metadata": {
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}