{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Dragon curve example from the [L-systems](../../topics/geometry/lsystems.ipynb) topic notebook in ``examples/topics/geometry``.\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "* [Matplotlib - dragon_curve](../matplotlib/dragon_curve.ipynb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import holoviews as hv\n", "from holoviews import opts\n", "import numpy as np\n", "hv.extension('bokeh')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## L-system definition" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following class is a simplified version of the approach used in the [L-systems](../../topics/geometry/lsystems.ipynb) notebook, made specifically for plotting the [Dragon Curve](https://en.wikipedia.org/wiki/Dragon_curve)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class DragonCurve(object):\n", " \"L-system agent that follows rules to generate the Dragon Curve\"\n", " \n", " initial ='FX'\n", " productions = {'X':'X+YF+', 'Y':'-FX-Y'}\n", " dragon_rules = {'F': lambda t,d,a: t.forward(d),\n", " 'B': lambda t,d,a: t.back(d),\n", " '+': lambda t,d,a: t.rotate(-a),\n", " '-': lambda t,d,a: t.rotate(a),\n", " 'X':lambda t,d,a: None,\n", " 'Y':lambda t,d,a: None }\n", " \n", " def __init__(self, x=0,y=0, iterations=1):\n", " self.heading = 0\n", " self.distance = 5\n", " self.angle = 90\n", " self.x, self.y = x,y\n", " self.trace = [(self.x, self.y)]\n", " self.process(self.expand(iterations), self.distance, self.angle)\n", " \n", " def process(self, instructions, distance, angle):\n", " for i in instructions: \n", " self.dragon_rules[i](self, distance, angle)\n", " \n", " def expand(self, iterations):\n", " \"Expand an initial symbol with the given production rules\"\n", " expansion = self.initial\n", " \n", " for i in range(iterations):\n", " intermediate = \"\"\n", " for ch in expansion:\n", " intermediate = intermediate + self.productions.get(ch,ch)\n", " expansion = intermediate\n", " return expansion\n", "\n", " def forward(self, distance):\n", " self.x += np.cos(2*np.pi * self.heading/360.0)\n", " self.y += np.sin(2*np.pi * self.heading/360.0)\n", " self.trace.append((self.x,self.y))\n", " \n", " def rotate(self, angle):\n", " self.heading += angle\n", " \n", " def back(self, distance):\n", " self.heading += 180\n", " self.forward(distance)\n", " self.heading += 180\n", " \n", " @property\n", " def path(self):\n", " return hv.Path([self.trace])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hmap = hv.HoloMap(kdims='Iteration')\n", "for i in range(7,17):\n", " hmap[i] = DragonCurve(-200, 0, i).path\n", "\n", "hmap.opts(\n", " opts.Path(axiswise=False, color='black', line_width=1, \n", " title='', xaxis=None, yaxis=None, framewise=True))" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 2 }