From bce7487a963d275d939d9f3fae3951caea1fc198 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Thu, 26 May 2022 18:19:56 +0800 Subject: [PATCH] add differential_line_growth --- examples/differential_line_growth.scad | 18 +++ .../_impl/_differential_line_growth.scad | 109 ++++++++++++++++++ .../differential_line_growth.scad | 19 +++ 3 files changed, 146 insertions(+) create mode 100644 examples/differential_line_growth.scad create mode 100644 src/experimental/_impl/_differential_line_growth.scad create mode 100644 src/experimental/differential_line_growth.scad diff --git a/examples/differential_line_growth.scad b/examples/differential_line_growth.scad new file mode 100644 index 00000000..a84eb683 --- /dev/null +++ b/examples/differential_line_growth.scad @@ -0,0 +1,18 @@ +use ; +use ; + +$fn = 24; +r = 20; +times = 50; +thickness = 2; +node_option = [ + 0.5, // maxForce + 0.7, // maxSpeed + 12, // separationDistance + 1.5, // separationCohesionRatio + 10 // maxEdgeLength +]; + +init_shape = shape_circle(r); +linear_extrude(thickness) + polygon(differential_line_growth(init_shape, node_option, times)); diff --git a/src/experimental/_impl/_differential_line_growth.scad b/src/experimental/_impl/_differential_line_growth.scad new file mode 100644 index 00000000..7b673760 --- /dev/null +++ b/src/experimental/_impl/_differential_line_growth.scad @@ -0,0 +1,109 @@ +use <../../util/unit_vector.scad>; +use <../../util/sum.scad>; + +ZERO_VT = [0, 0]; + +function limit(vt, magnitude) = + let(m = norm(vt)) + m > magnitude ? vt / m * magnitude : vt; + +function setMagnitude(vt, magnitude) = vt == ZERO_VT ? vt : unit_vector(vt) * magnitude; + +// node +function node(position, option) = [ + position, // position + rands(0, 1, 2), // velocity + option // option +]; + +function position_of(node) = node[0]; +function velocity_of(node) = node[1]; +function option_of(node) = node[2]; +function maxForce_of(node) = node[2][0]; +function maxSpeed_of(node) = node[2][1]; +function separationDistance_of(node) = node[2][2]; +function separationCohesionRatio_of(node) = node[2][3]; +function maxEdgeLength_of(node) = node[2][4]; + +function cohesionWith(node, other) = + limit( + setMagnitude(other - position_of(node), maxSpeed_of(node)) - velocity_of(node), + maxForce_of(node) + ); + +function seperationFrom(node, other) = + let( + v = position_of(node) - position_of(other), + dist = norm(v) + ) + dist < separationDistance_of(node) ? v / dist : ZERO_VT; + +function applyForceTo(node, seperation, cohesion) = + let( + acceleration = limit(seperation, maxForce_of(node)) * separationCohesionRatio_of(node) + cohesion, + velocity = limit(velocity_of(node) + acceleration, + maxSpeed_of(node)) + ) + [ + position_of(node) + velocity, + velocity, + option_of(node) + ]; + +function suitableForGrowth(node, nxNode) = + norm(position_of(node) - position_of(nxNode)) > maxEdgeLength_of(node); + +function growNode(node, nxNode) = + node((position_of(node) + position_of(nxNode)) / 2, option_of(node)); + +// nodes + +function cohesion(nodes, leng, i) = + let( + node = nodes[i], + middlePt = (position_of(nodes[(leng + i - 1) % leng]) + position_of(nodes[(i + 1) % leng])) / 2 + ) + cohesionWith(node, middlePt); + +function grow(nodes, leng) = + [ + for(i = 0, j = 1; i < leng; i = i + 1, j = j + 1) + let( + node = nodes[i], + nxNode = nodes[j % leng] + ) + each [node, if(suitableForGrowth(node, nxNode)) growNode(node, nxNode)] + ]; + +function allSeperationFrom(nodes, leng, node, n) = [ + for(j = n; j < leng; j = j + 1) + seperationFrom(node, nodes[j]) +]; + +function updateAllSeperation(allSeperation, allSeperationFrom_i_1, leng, n) = [ + for(i = 0; i < leng; i = i + 1) + if(i < n) allSeperation[i] + else allSeperation[i] - allSeperationFrom_i_1[i - n] +]; + +function differentiate(nodes, leng) = + [ + for(i = 0, + allSep = [for(i = [0:leng - 1]) ZERO_VT], + allSeperationFrom_i_1 = allSeperationFrom(nodes, leng, nodes[i], i + 1); + i < leng; + allSep = updateAllSeperation(allSep, allSeperationFrom_i_1, leng, i + 1), + i = i + 1, + allSeperationFrom_i_1 = i < leng ? allSeperationFrom(nodes, leng, nodes[i], i + 1) : undef + ) + let( + seperation_i = sum([allSep[i], each allSeperationFrom_i_1]), + cohesion_i = cohesion(nodes, leng, i) + ) + applyForceTo(nodes[i], seperation_i, cohesion_i) + ]; + +function _differential_line_growth(nodes) = + let(leng = len(nodes)) + grow(differentiate(nodes, leng), leng); + \ No newline at end of file diff --git a/src/experimental/differential_line_growth.scad b/src/experimental/differential_line_growth.scad new file mode 100644 index 00000000..271a2904 --- /dev/null +++ b/src/experimental/differential_line_growth.scad @@ -0,0 +1,19 @@ +use <_impl/_differential_line_growth.scad>; + +function differential_line_growth(init_shape, option, times) = + let( + init_nodes = [ + for(p = init_shape) + node(p, option) + ], + nodes_lt = [ + for(i = 0, line = _differential_line_growth(init_nodes); + i < times; + i = i + 1, + line = _differential_line_growth(line) + ) + line + ] + ) + [for(node = nodes_lt[times - 1]) position_of(node)]; + \ No newline at end of file