mirror of
https://github.com/JustinSDK/dotSCAD.git
synced 2025-08-28 08:50:30 +02:00
add differential_line_growth
This commit is contained in:
18
examples/differential_line_growth.scad
Normal file
18
examples/differential_line_growth.scad
Normal file
@@ -0,0 +1,18 @@
|
||||
use <shape_circle.scad>;
|
||||
use <experimental/differential_line_growth.scad>;
|
||||
|
||||
$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));
|
109
src/experimental/_impl/_differential_line_growth.scad
Normal file
109
src/experimental/_impl/_differential_line_growth.scad
Normal file
@@ -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);
|
||||
|
19
src/experimental/differential_line_growth.scad
Normal file
19
src/experimental/differential_line_growth.scad
Normal file
@@ -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)];
|
||||
|
Reference in New Issue
Block a user