Skip to content

Instantly share code, notes, and snippets.

Created December 2, 2016 12:08
Show Gist options
  • Save anonymous/18fbb7cd1cf6b1d35568a0a38dbf51b7 to your computer and use it in GitHub Desktop.
Save anonymous/18fbb7cd1cf6b1d35568a0a38dbf51b7 to your computer and use it in GitHub Desktop.
to do later?
{
"export_version": "0.062",
"framed_nodes": {},
"groups": {},
"nodes": {
"Scripted Node": {
"bl_idname": "SvScriptNode",
"color": [
0.0,
0.800000011920929,
0.949999988079071
],
"height": 100.0,
"hide": false,
"label": "treegen",
"location": [
-360.28607177734375,
-391.8294677734375
],
"params": {
"button_names": "",
"files_popup": "sv_lang_template.sn",
"float_list": [
0.0,
1.0,
0.5599997043609619,
0.9499994516372681,
2.5399997234344482,
34.45000076293945,
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,
30,
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": "treegen",
"script_str": "import numpy as np\nimport time\n\nfrom mathutils import Vector, Matrix \n\nfrom sverchok.data_structure import Matrix_listing\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 = Matrix_listing(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",
"user_name": "templates"
},
"width": 140.0
},
"Scripted Node Lite": {
"bl_idname": "SvScriptNodeLite",
"color": [
0.0,
0.800000011920929,
0.949999988079071
],
"height": 100.0,
"hide": false,
"label": "",
"location": [
-362.2015686035156,
-109.4034652709961
],
"params": {
"float_list": [
0.0,
65.0,
0.23000000417232513,
3.0,
4.0,
5.0,
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
],
"int_list": [
580,
1,
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": "Text",
"script_str": "\"\"\"\nin num_items s d=580 .=2\nin radius s d=65.0 .=2\nin reject_radius s d=0.23 n=2\nout verts v\n\"\"\"\nfrom random import random as rand\nfrom math import sqrt, cos, sin, pi as M_PI\nimport bmesh\n\nverts = []\nprelim_verts = []\n\nfor i in range(num_items):\n theta = rand() * 2 * M_PI\n r = rand() * radius\n prelim_verts.append((cos(theta)*sqrt(r), sin(theta)*sqrt(r), 0.0))\n\ndef remove_doubles(vertices, d):\n bm = bmesh.new()\n bm_verts = [bm.verts.new(v) for v in vertices]\n\n bmesh.ops.remove_doubles(bm, verts=bm_verts, dist=d)\n bm.verts.index_update()\n\n verts = [vert.co[:] for vert in bm.verts[:]]\n bm.clear()\n bm.free()\n return verts\n\nverts = [remove_doubles(prelim_verts, reject_radius)]"
},
"snlite_ui": [],
"width": 140.0
},
"Viewer Draw": {
"bl_idname": "ViewerNode2",
"color": [
1.0,
0.30000001192092896,
0.0
],
"height": 100.0,
"hide": false,
"label": "",
"location": [
25.79749298095703,
9.953826904296875
],
"params": {
"activate": 1
},
"width": 140.0
},
"Viewer Draw.001": {
"bl_idname": "ViewerNode2",
"color": [
1.0,
0.30000001192092896,
0.0
],
"height": 100.0,
"hide": false,
"label": "",
"location": [
33.30204772949219,
-276.875244140625
],
"params": {},
"width": 140.0
}
},
"update_lists": [
[
"Scripted Node Lite",
"verts",
"Viewer Draw",
"vertices"
],
[
"Scripted Node Lite",
"verts",
"Scripted Node",
"End Vertices"
],
[
"Scripted Node",
"Vertices",
"Viewer Draw.001",
"vertices"
],
[
"Scripted Node",
"Edges",
"Viewer Draw.001",
"edg_pol"
]
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment