{
  "export_version": "0.072",
  "framed_nodes": {},
  "groups": {},
  "nodes": {
    "A Number": {
      "bl_idname": "SvNumberNode",
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        -1034.716552734375,
        -193.28817749023438
      ],
      "params": {
        "float_": 0.0,
        "int_": 2,
        "selected_mode": "int"
      },
      "width": 140.0
    },
    "Circle": {
      "bl_idname": "SvCircleNode",
      "color": [
        0.0,
        0.5,
        0.5
      ],
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        -1038.1312255859375,
        -293.2105712890625
      ],
      "params": {
        "rad_": 0.5,
        "vert_": 6
      },
      "use_custom_color": true,
      "width": 140.0
    },
    "IcoSphere": {
      "bl_idname": "SvIcosphereNode",
      "color": [
        0.0,
        0.5,
        0.5
      ],
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        -417.37249755859375,
        -628.9933471679688
      ],
      "params": {
        "radius": 10.0,
        "subdivisions": 2
      },
      "use_custom_color": true,
      "width": 140.0
    },
    "Scripted Node": {
      "bl_idname": "SvScriptNode",
      "color": [
        0.0,
        0.800000011920929,
        0.949999988079071
      ],
      "height": 100.0,
      "hide": false,
      "label": "tree_generator.py",
      "location": [
        -208.36695861816406,
        -468.2001037597656
      ],
      "params": {
        "button_names": "",
        "files_popup": "tree_generator.py",
        "float_list": [
          0.0,
          1.0,
          0.5,
          2.0,
          30.0,
          0.009999999776482582,
          6.0,
          7.0,
          8.0,
          9.0,
          10.0,
          11.0,
          12.0,
          13.0,
          14.0,
          15.0,
          16.0,
          17.0,
          18.0,
          19.0,
          20.0,
          21.0,
          22.0,
          23.0,
          24.0,
          25.0,
          26.0,
          27.0,
          28.0,
          29.0,
          30.0,
          31.0
        ],
        "has_buttons": 0,
        "int_list": [
          0,
          200,
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30,
          31
        ],
        "script_name": "tree_generator.py",
        "script_str": "import numpy as np\nimport time\n\nfrom mathutils import Vector, Matrix    \n\n\n\ndef closest_np2(xyz1, xyz2):\n    x2 = np.subtract.outer(xyz2[:,0], xyz1[:,0])\n    y2 = np.subtract.outer(xyz2[:,1], xyz1[:,1])\n    z2 = np.subtract.outer(xyz2[:,2], xyz1[:,2])\n    d2 = np.sum((x2**2, y2**2, z2**2), axis=0)\n    ci = d2.argmin(axis=1)\n    column_i = range(d2.shape[0])\n    dout = np.sqrt(d2[column_i, ci])\n    v = np.vstack((x2[column_i, ci], y2[column_i, ci], z2[column_i, ci]))    \n    return dout, ci, v.T\n\nclass SCA:\n\n    def __init__(self, d=0.3, NBP=2000, KILLDIST=5, INFLUENCE=15, endpoints=[], \n                 TROPISM=0.0, max_time=1.0, startpoints=[]):\n        self.killdistance = KILLDIST\n        self.branchlength = d\n        self.maxiterations = NBP\n        self.tropism = np.array(TROPISM)\n        self.influence = INFLUENCE if INFLUENCE > 0 else 1e16\n        self.max_time = max_time\n        \n        if len(startpoints) > 0:            \n            self.bpalln = np.array(startpoints)\n        else:\n            self.bpalln = np.array([[0, 0, 0]])      \n        \n        self.bpp = [None] * self.bpalln.shape[0]\n        self.bpc = [0] * self.bpalln.shape[0]\n        self.bpg = [0] * self.bpalln.shape[0]\n            \n        self.epn = np.array(endpoints)        \n        d, ci, v = closest_np2(self.bpalln, self.epn)\n        self.epbn = ci\n        self.epdn = d\n        self.epvn = v / self.epdn.reshape((-1, 1))\n        self.epbn[self.epdn >= self.influence] = -2\n        \n        \n    def addBranchPoint(self, bpn, pi, generation):\n        self.bpalln = np.append(self.bpalln, [bpn], axis=0)\n\n        self.bpp.append(pi)\n        self.bpc.append(0)\n        #self.bpg.append(generation + 1)\n        self.bpg = np.append(self.bpg, [generation+1])\n        self.bpc[pi] += 1  \n        bi = self.bpalln.shape[0] - 1\n        v = self.epn - bpn\n        d2 = (v**2).sum(axis=1)\n        index = (self.epbn != -1) & (d2 < self.epdn**2) & (d2 > self.killdistance**2)\n         \n        d  = np.sqrt(d2[index])\n        self.epvn[index] = v[index, :] / d.reshape((-1,1))\n        self.epdn[index] = d\n        \n        index2 = (index & (d2 < self.influence**2))               \n        self.epbn[index2] = bi\n        \n        index3 = (index & (d2 >= self.influence**2))                \n        self.epbn[index3] = -2\n        \n        index4 = (self.epbn != -1) & (d2 < self.epdn**2) & (d2 <= self.killdistance**2)                \n        self.epbn[index4] = -1    \n               \n        if self.bpc[pi] > 1:  # a branch point with two children will not grow any new branches ...\n            index_e = (self.epbn == pi)\n            index_b = (np.array(self.bpc) <= 1)\n            d, c, v = closest_np2(self.bpalln[index_b], self.epn[index_e])\n            # this turns c indixes into self.bpalln[index_b] into u indices into self.bpalln\n            #needs better variable names\n            t = np.arange(self.bpalln.shape[0])[index_b]\n            u = t[c]\n            # set points not within influence distance to -2 so they will be\n            # ignored in growBranches\n            u[d >= self.influence] = -2\n\n            self.epdn[index_e] = d\n            self.epbn[index_e] = u            \n            self.epvn[index_e] = v / d.reshape((-1,1))    \n                         \n    def growBranches(self, generation):\n        index = self.epbn >= 0        \n        epbn = self.epbn[index]\n        bis = np.unique(epbn)\n        \n        v_sums = np.empty((bis.shape[0], 3))\n        for col in range(3):\n            v_sums[:, col] = np.bincount(epbn, weights=self.epvn[index, col])[bis]\n#        d2 = (v_sums**2).sum(axis=1)\n#        d = np.sqrt(d2) /self.branchlength\n#        vd = v_sums / d.reshape((-1, 1))\n\n        n_hat = v_sums/(((v_sums**2).sum(axis=1))**0.5).reshape((-1,1))\n        n_tilde = (n_hat + self.tropism)\n        n_tilde = n_tilde/(((n_tilde**2).sum(axis=1))**0.5).reshape((-1,1))\n       \n        newbps = self.bpalln[bis] + n_tilde * self.branchlength\n        newbpps = bis        \n                \n        for newbp, newbpp in zip(newbps, newbpps):\n            self.addBranchPoint(newbp, newbpp, generation)\n                        \n    def iterate(self):\n        t0 = time.time()\n        for i in range(self.maxiterations):\n            nbp = self.bpalln.shape[0]    \n            self.growBranches(i)\n            if self.bpalln.shape[0] == nbp:\n                return\n            if (time.time() - t0) > self.max_time:\n                print('SCA timed out')\n                return\n        return\n\n    def bp_verts_edges_n(self):\n        \"\"\"\n        returns branchpoints verts as a list of positions\n        and edges as index to connect the branch points\n        and leaves matrices \n        \"\"\"\n        verts = []\n        edges = []\n        ends = []\n        ends_inds = []\n        for i, b in enumerate(self.bpalln):\n            bp_parent = self.bpp[i]\n            verts.append(list(b))\n            if bp_parent != None:\n                edges.append((bp_parent, i))\n            if self.bpc[i] == 0:\n                ends.append(True)\n                ends_inds.append(i)\n            else:\n                ends.append(False)  \n        process = ends_inds\n        # branch radii\n        br = [int(t) for t in ends]\n        finished = []\n        while len(process) > 0:\n            process.sort()\n            i = process.pop()\n            finished.append(i)\n            p = self.bpp[i]\n            if p != None:\n                br[p] = br[p] + br[i]\n                if p not in process:\n                    if p not in finished:\n                        process.insert(0, p)    \n                        \n        mats= []\n        for edge in edges:           \n            if ends[edge[1]]:\n                #calculate leaf directions\n                #end will always be edge[1]\n                v0 = Vector(verts[edge[0]])\n                v1 = Vector(verts[edge[1]])\n                dir1 = (v1 - v0).normalized()\n                dir2 = (dir1.cross(Vector((0.0, 0.0, 1.0)))).normalized()               \n                dir3 = -(dir1.cross(dir2)).normalized() \n                m = Matrix.Identity(4)\n                m[0][0:3] = dir1\n                m[1][0:3] = dir2\n                m[2][0:3] = dir3\n                m[3][0:3] = v1\n                m.transpose()\n                mats.append(m)\n\n        mats_out =  mats\n     \n        return verts, edges, ends, br, mats_out\n        \ndef sv_main(npoints=100 , dist=0.05, min_dist=0.05, max_dist=2.0, tip_radius=0.01, trop=[], verts_in=[], verts_start=[]):\n\n    in_sockets = [\n        ['s', 'maximum branches', npoints],\n        ['s', 'branch length', dist],\n        ['s', 'minimum distance', min_dist],\n        ['s', 'maximum distance', max_dist],\n        ['s', 'tip radius', tip_radius], \n        ['v', 'tropism', trop],\n        ['v', 'End Vertices',  verts_in],\n        ['v', 'Start Vertices', verts_start]\n    ]\n    verts_out = []\n    edges_out = []\n    rad_out = []\n    ends_out = []\n    mats_out = []\n    if not verts_start:\n        verts_start = [[]]\n    if not trop:\n        trop = [0., 0., 0.]    \n        \n    if verts_in :\n        sca = SCA(NBP = npoints,\n                  d=dist,\n                  KILLDIST=min_dist,\n                  INFLUENCE=max_dist, \n                  TROPISM=trop[0],\n                  endpoints=verts_in[0],\n                  startpoints = verts_start[0])\n\n        sca.iterate()\n        verts_out, edges_out, ends_out, br, mats_out = sca.bp_verts_edges_n()\n        rad_out = [tip_radius*b**0.5 for b in br]\n        \n    out_sockets = [\n        ['v', 'Vertices', [verts_out]],\n        ['s', 'Edges', [edges_out]],\n        ['s', 'Branch radii', [rad_out]],\n        ['s', 'Ends mask', [ends_out]],\n        ['m', 'Leaf matrices', mats_out],\n    ]\n\n    return in_sockets, out_sockets\n",
        "user_name": "elfnor"
      },
      "use_custom_color": true,
      "width": 166.56326293945312
    },
    "Scripted Node.001": {
      "bl_idname": "SvScriptNode",
      "color": [
        0.0,
        0.800000011920929,
        0.949999988079071
      ],
      "height": 100.0,
      "hide": false,
      "label": "L-system_initial.py",
      "location": [
        -159.05369567871094,
        -40.540061950683594
      ],
      "params": {
        "button_names": "",
        "files_popup": "L-system_initial.py",
        "float_list": [
          0.0,
          1.0,
          9.13800048828125,
          3.0,
          4.0,
          1.0,
          1.0,
          7.0,
          8.0,
          9.0,
          10.0,
          11.0,
          12.0,
          13.0,
          14.0,
          15.0,
          16.0,
          17.0,
          18.0,
          19.0,
          20.0,
          21.0,
          22.0,
          23.0,
          24.0,
          25.0,
          26.0,
          27.0,
          28.0,
          29.0,
          30.0,
          31.0
        ],
        "has_buttons": 0,
        "int_list": [
          0,
          7,
          3,
          3000,
          5,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30,
          31
        ],
        "script_name": "L-system_initial.py",
        "script_str": "# https://groups.google.com/d/msg/tributary/9kI-CGVVQb4/J6joc8q6VhwJ\n\nimport math\nfrom math import sin, cos, radians, degrees, pi, pow\n\nimport random\nfrom random import random\n\nimport ast\nfrom ast import literal_eval\n\n\ndef sv_main(i_user=8, bend=-10.71875, arm_dist=5890):\n\n    def to_rad(degrees):\n        return degrees * 2 * pi / 360\n\n    in_sockets = [\n        ['s', 'i_user', i_user],\n        ['s', 'bend', bend],\n        ['s', 'arm_dist', arm_dist]]\n\n    verts_out = []\n    out_sockets = [\n        ['v', 'verts', verts_out]\n    ]\n\n    bend = 2 * bend                       # angle to twist (degrees)\n    iterations = min(8, i_user)           # number of rewrites (recursion levels in grammar)\n    F = arm_dist / (pow(2.4, iterations)) # arm distance\n    x_start = 0\n    y_start = 0\n\n    Lvals = {\n        'angle_offset': to_rad(bend),     # angle as radian\n        'angle_rad': 0,                   # the current angle for drawing\n        'x_start': x_start,               # drawing start x\n        'y_start': y_start,               # drawing start y\n        'x_current': x_start,             # current cursor position x\n        'y_current': y_start              # current cursor position y\n    }\n    rules = {}                            # a map of the rules\n    commands = {}                         # a map of the commands\n\n    def get_xy(angle_rad, Lv):\n        return {'x': cos(angle_rad) * Lv, 'y': sin(angle_rad) * Lv}\n\n    def command_from_rad(command):\n        command_parts = command.split(\" \")\n        Lv = literal_eval(command_parts[1])\n        if len(command_parts) > 2:\n            if command_parts[2] == \"R\":\n                Lv = Lv * (1 + (literal_eval(command_parts[3]) * (random() - 0.5)) / 100)\n\n        c = get_xy(Lvals['angle_rad'], Lv)\n        Lvals['x_current'] += c['x']\n        Lvals['y_current'] += c['y']\n\n        if (command_parts[0] == \"L\"):\n            # tributary.ctx.lineTo(x_current, y_current)\n            verts_out.append((Lvals['x_current'], Lvals['y_current'], 0))\n\n        if (command_parts[0] == \"M\"):\n            # tributary.ctx.stroke()\n            # tributary.ctx.moveTo(x_current, y_current)\n            verts_out.append((Lvals['x_current'], Lvals['y_current'], 0))\n\n    def make_path(rules, commands, start_string):\n        # tributary.ctx.moveTo(x_start,y_start)\n\n        verts_out.append((0, 0, 0))\n\n        recursive_path(rules, commands, start_string, 0)\n        # tributary.ctx.stroke()\n\n    # L-systems grammar rewriting\n    def recursive_path(rules, commands, input_string, iteration):\n        token = \"\"\n\n        for i in range(len(input_string)):\n            token = input_string[i]\n            if (token == '-'):\n                Lvals['angle_rad'] += Lvals['angle_offset']\n            elif (token == '+'):\n                Lvals['angle_rad'] -= Lvals['angle_offset']\n            elif (token in rules):\n\n                if (iteration >= iterations and token in commands):\n                    ''' if we're at the bottom level, move forward '''\n                    command_from_rad(commands[token])\n\n                else:\n                    ''' else go deeper down the rabbit hole... '''\n                    recursive_path(rules, commands, rules[token], iteration + 1)\n\n            elif (token in commands):\n                command_from_rad(commands[token])\n\n    '''\n    The rules:\n    + means turn left by bend degrees\n    - means turn right by bend degrees\n    Variables (like A or B) get replaced by the rule when encountered\n    This keeps repeating until the maximum number of iterations is reached\n    You need one rule entry per variable used\n    '''\n\n    rules[\"A\"] = \"BB----BB+++++++++++++BB----BB\"\n    rules[\"B\"] = \"-----------A++++++++++++++\"\n\n    '''\n    The commands:\n    \"L nn\" means draw a line of length nn, e.g. L90 means draw a line 90 pixels long\n    \"M nn\" means move nn pixels forward, e.g. M90 means move the current cursor 90 pixels forward\n    \"R nn\" at the end of the command means add +/- nn% random noise to the length\n    '''\n    commands[\"A\"] = \"L \" + str(F)\n    start = \"A\"\n\n    make_path(rules, commands, start)\n\n    out_sockets[0][2] = [verts_out]\n    return in_sockets, out_sockets\n",
        "user_name": "zeffii"
      },
      "use_custom_color": true,
      "width": 139.15541076660156
    },
    "Scripted Node.002": {
      "bl_idname": "SvScriptNode",
      "height": 100.0,
      "hide": false,
      "label": "LSystem_blender.py",
      "location": [
        -1027.3973388671875,
        -108.62008666992188
      ],
      "params": {
        "button_names": "",
        "files_popup": "L-system_initial.py",
        "float_list": [
          0.0,
          1.0,
          9.22800064086914,
          3.0,
          4.0,
          1.0,
          1.0,
          7.0,
          8.0,
          9.0,
          10.0,
          11.0,
          12.0,
          13.0,
          14.0,
          15.0,
          16.0,
          17.0,
          18.0,
          19.0,
          20.0,
          21.0,
          22.0,
          23.0,
          24.0,
          25.0,
          26.0,
          27.0,
          28.0,
          29.0,
          30.0,
          31.0
        ],
        "has_buttons": 0,
        "int_list": [
          0,
          6,
          3,
          1000,
          5,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30,
          31
        ],
        "script_name": "LSystem_blender.py",
        "script_str": "import random\nimport mathutils as mu\n\nimport xml.etree.cElementTree as etree\nfrom xml.etree.cElementTree import fromstring\n\nclass LSystem:\n\n    \"\"\"\n    Takes an XML string.\n    \"\"\"\n    def __init__(self, rules, maxObjects):\n        self._tree = fromstring(rules)\n        self._maxDepth = int(self._tree.get(\"max_depth\"))\n        self._progressCount = 0\n        self._maxObjects = maxObjects\n\n    \"\"\"\n    Returns a list of \"shapes\".\n    Each shape is a 2-tuple: (shape name, transform matrix).\n    \"\"\"\n    def evaluate(self, seed = 0 ):\n        random.seed(seed)\n        rule = _pickRule(self._tree, \"entry\")\n        entry = (rule, 0, mu.Matrix.Identity(4))\n        shapes = self._evaluate(entry)\n        return shapes\n        \n    def _evaluate(self, entry):\n        stack = [entry]\n        shapes = []\n        while len(stack) > 0:\n            \n            if len(shapes) > self._maxObjects:\n                print('max objects reached')\n                break\n    \n            if len(shapes) > self._progressCount + 1000:\n                print(len(shapes), \"curve segments so far\")\n                print(self._maxObjects)\n                self._progressCount = len(shapes)\n                \n            \n            rule, depth, matrix = stack.pop()\n\n    \n            local_max_depth = self._maxDepth\n            if \"max_depth\" in rule.attrib:\n                local_max_depth = int(rule.get(\"max_depth\"))\n    \n            if len(stack) >= self._maxDepth:\n                shapes.append(None)\n                continue\n    \n            if depth >= local_max_depth:\n                if \"successor\" in rule.attrib:\n                    successor = rule.get(\"successor\")\n                    rule = _pickRule(self._tree, successor)\n                    stack.append((rule, 0, matrix))\n                shapes.append(None)\n                continue\n        \n            for statement in rule:              \n                tstr = statement.get(\"transforms\",\"\")\n                if not(tstr):\n                    tstr = ''\n                    for t in ['tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sa', 'sx', 'sy', 'sz']:\n                        tvalue = statement.get(t)\n                        if tvalue:\n                            n = eval(tvalue)\n                            tstr += \"{} {:f} \".format(t,n) \n                xform = _parseXform(tstr)\n                count = int(statement.get(\"count\", 1))\n                for n in range(count):\n                    matrix *= xform\n                    \n                    if statement.tag == \"call\":\n                        rule = _pickRule(self._tree, statement.get(\"rule\"))\n                        cloned_matrix = matrix.copy()\n                        entry = (rule, depth + 1, cloned_matrix)     \n                        stack.append(entry)\n                  \n                    elif statement.tag == \"instance\":\n                        name = statement.get(\"shape\")\n                        shape = (name, matrix)\n                        shapes.append(shape)\n                                                  \n                    else:\n                        print(\"malformed xml\")\n                        quit()\n    \n        print(\"\\nGenerated %d shapes.\" % len(shapes))\n        return shapes\n        # end of _evaluate\n        \n    def make_tube(self, mats, verts):\n        \"\"\"\n        takes a list of vertices and a list of matrices\n        the vertices are to be joined in a ring, copied and transformed by the 1st matrix \n        and this ring joined to the previous ring.\n\n        The ring dosen't have to be planar.\n        outputs lists of vertices, edges and faces\n        \"\"\"\n        \n        edges_out = []\n        verts_out = [] \n        faces_out = []\n        vID = 0\n        if len(mats) > 1:\n            #print('len mats', len(mats))\n            #print(mats[0])\n            nring = len(verts[0])\n            #end face\n            faces_out.append(list(range(nring)))\n            for i,m in enumerate(mats):\n                for j,v in enumerate(verts[0]):\n                    vout = mu.Matrix(m) * mu.Vector(v)\n                    verts_out.append(vout.to_tuple())\n                    vID = j + i*nring\n                    #rings\n                    if j != 0:\n                        edges_out.append([vID, vID - 1])\n                    else: \n                        edges_out.append([vID, vID + nring-1]) \n                    #lines\n                    if i != 0:\n                        edges_out.append([vID, vID - nring]) \n                        #faces\n                        if j != 0:\n                            faces_out.append([vID, vID - nring, vID - nring - 1, vID-1,])\n                        else:\n                            faces_out.append([vID, vID - nring,  vID-1, vID + nring-1])\n            #end face\n            #reversing list fixes face normal direction keeps mesh manifold\n            f = list(range(vID, vID-nring, -1))\n            faces_out.append(f)\n        return verts_out, edges_out, faces_out\n                            \ndef _pickRule(tree, name):\n\n    rules = tree.findall(\"rule\")\n    elements = []\n    for r in rules:\n        if r.get(\"name\") == name:\n            elements.append(r)\n\n    if len(elements) == 0:\n        print(\"Error, no rules found with name '%s'\" % name)\n        quit()\n\n    sum, tuples = 0, []\n    for e in elements:\n        weight = int(e.get(\"weight\", 1))\n        sum = sum + weight\n        tuples.append((e, weight))\n    n = random.randint(0, sum - 1)\n    for (item, weight) in tuples:\n        if n < weight:\n            break\n        n = n - weight\n    return item\n\n_xformCache = {}\n\ndef _parseXform(xform_string):\n    if xform_string in _xformCache:\n        return _xformCache[xform_string]\n        \n    matrix = mu.Matrix.Identity(4)\n    tokens = xform_string.split(' ')\n    t = 0\n    while t < len(tokens) - 1:\n            command, t = tokens[t], t + 1\n    \n            # Translation\n            if command == 'tx':\n                x, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Translation(mu.Vector((x, 0, 0)))\n            elif command == 'ty':\n                y, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Translation(mu.Vector((0, y, 0)))\n            elif command == 'tz':\n                z, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Translation(mu.Vector((0, 0, z)))\n            elif command == 't':\n                x, t = eval(tokens[t]), t + 1\n                y, t = eval(tokens[t]), t + 1\n                z, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Translation(mu.Vector((x, y, z)))\n    \n            # Rotation\n            elif command == 'rx':\n                theta, t = _radians(eval(tokens[t])), t + 1\n                matrix *= mu.Matrix.Rotation(theta, 4, 'X')\n                \n            elif command == 'ry':\n                theta, t = _radians(eval(tokens[t])), t + 1\n                matrix *= mu.Matrix.Rotation(theta, 4, 'Y')\n            elif command == 'rz':\n                theta, t = _radians(eval(tokens[t])), t + 1\n                matrix *= mu.Matrix.Rotation(theta, 4, 'Z')\n    \n            # Scale\n            elif command == 'sx':\n                x, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Scale(x, 4, mu.Vector((1.0, 0.0, 0.0)))\n            elif command == 'sy':\n                y, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Scale(y, 4, mu.Vector((0.0, 1.0, 0.0)))\n            elif command == 'sz':\n                z, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Scale(z, 4, mu.Vector((0.0, 0.0, 1.0)))\n            elif command == 'sa':\n                v, t = eval(tokens[t]), t + 1\n                matrix *= mu.Matrix.Scale(v, 4)\n            elif command == 's':\n                x, t = eval(tokens[t]), t + 1\n                y, t = eval(tokens[t]), t + 1\n                z, t = eval(tokens[t]), t + 1\n                mx = mu.Matrix.Scale(x, 4, mu.Vector((1.0, 0.0, 0.0)))\n                my = mu.Matrix.Scale(y, 4, mu.Vector((0.0, 1.0, 0.0)))\n                mz = mu.Matrix.Scale(z, 4, mu.Vector((0.0, 0.0, 1.0)))\n                mxyz = mx*my*mz\n                matrix *= mxyz\n\n            else:\n                print(\"unrecognized transformation: '%s' at position %d in '%s'\" % (command, t, xform_string))\n                quit()\n\n    _xformCache[xform_string] = matrix\n    return matrix\n\ndef _radians(d):\n    return float(d * 3.141 / 180.0)\n",
        "user_name": "zeffii"
      },
      "width": 139.15541076660156
    },
    "Scripted Node.003": {
      "bl_idname": "SvScriptNode",
      "height": 100.0,
      "hide": false,
      "label": "GA_xml.py",
      "location": [
        -852.3323974609375,
        -113.60025787353516
      ],
      "params": {
        "button_names": "",
        "files_popup": "GA_xml.py",
        "has_buttons": 0,
        "script_name": "GA_xml.py",
        "script_str": "Library = {}\n\nLibrary[\"Tree\"] = \"\"\"\n<rules max_depth=\"200\">\n    <rule name=\"entry\">\n        <call  rule=\"spiral\"/>\n    </rule>\n    <rule name=\"spiral\" weight=\"100\">\n        <instance shape=\"tubey\"/>\n        <call transforms=\"tz 0.4 rx 1 sa 0.995\" rule=\"spiral\"/>\n    </rule>\n    <rule name=\"spiral\" weight=\"100\">\n        <instance shape=\"tubey\"/>\n        <call transforms=\"tz 0.4 rx 1 ry 1 sa 0.995\" rule=\"spiral\"/>\n    </rule>\n    <rule name=\"spiral\" weight=\"100\">\n        <instance shape=\"tubey\"/>\n        <call transforms=\"tz 0.4 rx 1 rz -1 sa 0.995\" rule=\"spiral\"/>\n    </rule>\n    <rule name=\"spiral\" weight=\"6\">\n        <call transforms=\"rx 15\" rule=\"spiral\"/>\n        <call transforms=\"rz 180\" rule=\"spiral\"/>\n    </rule>\n</rules>\"\"\"\n\nLibrary[\"Octopod\"] = \"\"\"\n<rules max_depth=\"20\">\n    <rule name=\"entry\">\n        <call count=\"300\" transforms=\"rx 3.6\" rule=\"arm\"/>\n    </rule>\n    <rule name=\"arm\">\n        <call transforms=\"sa 0.9 ry 6 tz 1\" rule=\"arm\"/>\n        <instance transforms=\"s 0.2 0.5 1\" shape=\"box\"/>\n    </rule>\n    <rule name=\"arm\">\n        <call transforms=\"sa 0.9 ry -6 tz 1\" rule=\"arm\"/>\n        <instance transforms=\"s 0.2 0.5 1\" shape=\"sphere\"/>\n    </rule>\n</rules>\n\"\"\"\n\nLibrary[\"Nouveau\"] = \"\"\"\n<rules max_depth=\"2000\">\n    <rule name=\"entry\">\n        <call count=\"16\" transforms=\"rz 20\" rule=\"hbox\"/>\n    </rule>\n    <rule name=\"hbox\"><call rule=\"r\"/></rule>\n    <rule name=\"r\"><call rule=\"forward\"/></rule>\n    <rule name=\"r\"><call rule=\"turn\"/></rule>\n    <rule name=\"r\"><call rule=\"turn2\"/></rule>\n    <rule name=\"r\"><call rule=\"turn4\"/></rule>\n    <rule name=\"r\"><call rule=\"turn3\"/></rule>\n    <rule name=\"forward\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"rz 2 tx 0.1 sa 0.996\" rule=\"forward\"/>\n    </rule>\n    <rule name=\"turn\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"rz 2 tx 0.1 sa 0.996\" rule=\"turn\"/>\n    </rule>\n    <rule name=\"turn2\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"rz -2 tx 0.1 sa 0.996\" rule=\"turn2\"/>\n    </rule>\n    <rule name=\"turn3\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"ry -2 tx 0.1 sa 0.996\" rule=\"turn3\"/>\n    </rule>\n    <rule name=\"turn4\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"ry -2 tx 0.1 sa 0.996\" rule=\"turn4\"/>\n    </rule>\n    <rule name=\"turn5\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"rx -2 tx 0.1 sa 0.996\" rule=\"turn5\"/>\n    </rule>\n    <rule name=\"turn6\" max_depth=\"90\" successor=\"r\">\n        <call rule=\"dbox\"/>\n        <call transforms=\"rx -2 tx 0.1 sa 0.996\" rule=\"turn6\"/>\n    </rule>\n    <rule name=\"dbox\">\n        <instance transforms=\"s 0.55 2.0 1.25 ry 90 rz 45\" shape=\"boxy\"/>\n    </rule>\n</rules>\n\"\"\"\n\nLibrary[\"Spirals\"] = \"\"\"\n<rules max_depth=\"400\">\n    <rule name=\"entry\">\n        <call count=\"3\" transforms=\"ry 120\" rule=\"R1\"/>\n        <call count=\"3\" transforms=\"ry 120\" rule=\"R2\"/>\n    </rule>\n    <rule name=\"R1\" >\n        <call transforms=\"tz 1.3 rz 1.57 ry 6 rx 3 sa 0.99\" rule=\"R1\"/>\n        <instance transforms=\"sa 4\" shape=\"sphere\"/>\n    </rule>\n    <rule name=\"R2\">\n        <call transforms=\"tz -1.3 ry 6 rx 3 sa 0.99\" rule=\"R2\"/>\n        <instance transforms=\"sa 4\" shape=\"sphere\"/>\n    </rule>\n</rules>\n\"\"\"\n\nLibrary[\"SpiralsBumpy\"] = \"\"\"\n<rules max_depth=\"400\">\n    <rule name=\"entry\">\n        <call count=\"3\" transforms=\"ry 120\" rule=\"R1\"/>\n        <call count=\"3\" transforms=\"ry 120\" rule=\"R2\"/>\n    </rule>\n    <rule name=\"R1\" >\n        <call transforms=\"tz 1.3 rz 1.57 ry 6 rx 3 sa 0.99\" rule=\"R1\"/>\n        <instance transforms=\"sa 4\" shape=\"sphere\"/>\n    </rule>\n    <rule name=\"R2\">\n        <call transforms=\"tz -1.3 ry 6 rx 3 sa 0.99\" rule=\"R2\"/>\n        <instance transforms=\"sa 4\" shape=\"sphere\"/>\n    </rule>\n    <rule name=\"R2\">\n        <call transforms=\"tz -1.3 ry 6 rx 3 sa 0.99\" rule=\"R2\"/>\n        <instance transforms=\"sa 8\" shape=\"sphere\"/>\n    </rule>\n</rules>\n\"\"\"\n\nLibrary[\"Ball\"] = \"\"\"\n<rules max_depth=\"2000\">\n    <rule name=\"entry\">\n        <call rule=\"R1\"/>\n    </rule>\n    <rule name=\"R1\" weight = \"10\">\n        <call transforms=\"tx 1 rz 5 ry 2\" rule=\"R1\"/>\n        <instance transforms=\"sa 3 ry 90\" shape=\"box\"/>\n    </rule>\n    <rule name=\"R1\" weight = \"10\">\n        <call transforms=\"tx 1 rz -5 ry 2\" rule=\"R1\"/>\n        <instance transforms=\"sa 3 ry 90\" shape=\"box\"/>\n    </rule>\n        \n</rules>\n\"\"\"\n\nLibrary[\"Fern\"] = \"\"\"\n<rules max_depth=\"2000\">\n    <rule name=\"entry\">\n        <call  rule=\"curl1\" />  \n        <call  rule=\"curl2\" />      \n    </rule>\n    \n    <rule name=\"curl1\" max_depth=\"80\">\n        <call transforms=\"rx 12.5 tz 0.9 s 0.98 0.95 1.0\" rule=\"curl1\"/>\n        <instance shape=\"box\"/>        \n    </rule>\n    \n    <rule name=\"curl2\" max_depth=\"80\">\n        <call transforms=\"rx 12.5 tz 0.9 s 0.95 0.95 1.0\" rule=\"curl2\"/>\n        <call transforms=\"tx 0.1 ty -0.45 ry 40 sa 0.25\" rule=\"curlsmall\" />     \n    </rule>    \n    \n    <rule name=\"curlsmall\" max_depth=\"80\">\n        <call transforms=\"rx 25 tz 1.2 s 0.9 0.9 1.0\" rule=\"curlsmall\"/>\n        <instance shape=\"box\"/>     \n    </rule>    \n</rules>\n\"\"\"\n\nLibrary[\"Default\"] = Library[\"Tree\"]\n",
        "user_name": "elfnor"
      },
      "width": 140.0
    },
    "Scripted Node.004": {
      "bl_idname": "SvScriptNode",
      "color": [
        0.0,
        0.800000011920929,
        0.949999988079071
      ],
      "height": 100.0,
      "hide": false,
      "label": "GA_node.py",
      "location": [
        -852.947265625,
        -189.74053955078125
      ],
      "params": {
        "button_names": "",
        "files_popup": "GA_node.py",
        "has_buttons": 0,
        "int_list": [
          0,
          26,
          2000,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30,
          31
        ],
        "script_name": "GA_node.py",
        "script_str": "from sverchok.data_structure import fullList\n\nimport LSystem_blender as LSystem\nimport GA_xml\n\nimport imp\n\nimp.reload(LSystem)\n\ndef flat(*args):\n    for x in args:\n        if hasattr(x, '__iter__'):\n            for y in flat(*x):\n                yield y\n        else:\n            yield x\n\ndef sv_main(rseed=21, max_mats=5000, vars = [], verts=[]):\n\n    in_sockets = [['s', 'rseed', rseed],\n                  ['s', 'max matrices', max_mats], \n                  ['s', 'variables', vars],    \n                  ['v', 'Vertices', verts]]\n       \n    imp.reload(GA_xml)\n       \n    tree = GA_xml.Library[\"Default\"]\n    \n    nvars = tree.count('{') #this may be too large because of repeats\n\n    \n    #flatten vars\n    if vars: \n        vars = list(flat(vars))\n        fullList(vars, nvars)\n    else: \n        vars = [0]*nvars\n           \n    tree = tree.format(*vars)\n            \n    lsys = LSystem.LSystem(tree, max_mats)\n    shapes = lsys.evaluate(seed = rseed)\n       \n    names = [shape[0] for shape in shapes if shape] \n    #convert names to integer list\n    iddict = {k:v for v,k in enumerate(set(names))}   \n       \n    mat_sublist = []\n    mat_list  = []     \n    mask = [] \n    mask_sub = []               \n    for i, shape in enumerate(shapes):\n        if shape:\n            mat_sublist.append(shape[1])\n            mask_sub.append(iddict[shape[0]])\n        else: \n            if len(mat_sublist) > 0:\n                mat_list.append(mat_sublist)\n                mask.append(mask_sub)\n            mat_sublist = []\n            mask_sub = []\n\n    edges_out = []\n    verts_out = [] \n    faces_out = []             \n    if verts:\n        #make tubes                   \n        for sublist in mat_list:\n            v, e, f = lsys.make_tube(sublist, verts)\n            if v:\n                verts_out.append(v)\n                edges_out.append(e)\n                faces_out.append(f)\n \n    mat_out =  mat_list\n     \n    out_sockets = [\n        ['m', 'matrices', mat_out],\n        ['s', 'mask', mask],\n        ['v', 'Vertices', verts_out],\n        ['s', 'Edges', edges_out],\n        ['s', 'Faces', faces_out]]\n    \n    return in_sockets, out_sockets",
        "user_name": "elfnor"
      },
      "use_custom_color": true,
      "width": 140.0
    },
    "UV Connection": {
      "bl_idname": "LineConnectNodeMK2",
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        24.13121223449707,
        -45.831729888916016
      ],
      "params": {
        "polygons": "Edges"
      },
      "width": 140.0
    },
    "Vector in": {
      "bl_idname": "GenVectorsNode",
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        -402.83135986328125,
        -777.779541015625
      ],
      "params": {
        "z_": -5.0
      },
      "width": 100.0
    },
    "Vector in.001": {
      "bl_idname": "GenVectorsNode",
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        -388.9963684082031,
        -469.7427673339844
      ],
      "params": {
        "z_": 1.0
      },
      "width": 100.0
    },
    "Viewer Draw": {
      "bl_idname": "ViewerNode2",
      "color": [
        1.0,
        0.30000001192092896,
        0.0
      ],
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        201.7696075439453,
        -41.49746322631836
      ],
      "params": {
        "display_verts": 0,
        "edge_width": 1
      },
      "use_custom_color": true,
      "width": 140.0
    },
    "Viewer Draw.001": {
      "bl_idname": "ViewerNode2",
      "color": [
        1.0,
        0.30000001192092896,
        0.0
      ],
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        31.398942947387695,
        -469.66046142578125
      ],
      "params": {},
      "use_custom_color": true,
      "width": 140.0
    },
    "Viewer Draw.002": {
      "bl_idname": "ViewerNode2",
      "color": [
        1.0,
        0.30000001192092896,
        0.0
      ],
      "height": 100.0,
      "hide": false,
      "label": "",
      "location": [
        -683.421875,
        -185.6544189453125
      ],
      "params": {
        "display_edges": 0,
        "display_verts": 0,
        "shading": 1
      },
      "use_custom_color": true,
      "width": 140.0
    }
  },
  "update_lists": [
    [
      "Scripted Node.001",
      0,
      "UV Connection",
      0
    ],
    [
      "UV Connection",
      0,
      "Viewer Draw",
      0
    ],
    [
      "UV Connection",
      1,
      "Viewer Draw",
      1
    ],
    [
      "Vector in.001",
      0,
      "Scripted Node",
      5
    ],
    [
      "IcoSphere",
      0,
      "Scripted Node",
      6
    ],
    [
      "Vector in",
      0,
      "Scripted Node",
      7
    ],
    [
      "Scripted Node",
      0,
      "Viewer Draw.001",
      0
    ],
    [
      "Scripted Node",
      1,
      "Viewer Draw.001",
      1
    ],
    [
      "A Number",
      0,
      "Scripted Node.004",
      2
    ],
    [
      "Circle",
      0,
      "Scripted Node.004",
      3
    ],
    [
      "Scripted Node.004",
      2,
      "Viewer Draw.002",
      0
    ],
    [
      "Scripted Node.004",
      4,
      "Viewer Draw.002",
      1
    ]
  ]
}
