This method is based on the original article. First we need to convert list of spring connectivity (spring
) into a graph:
g = Graph[Apply[UndirectedEdge, spring, 1], VertexCoordinates -> mass];
Then Kirchhoff (Laplacian/admittance/discrete Laplacian) matrix should be found using KirchhoffMatrix
:
m = KirchhoffMatrix[g] // Normal;
We also need to incorporate pinned coordinates into m
by replacing the corresponding rows to zero except the diagonal element:
km[[2]]f[i_] := Array[If[#1 == 2i, 1, 0] &, First@Dimensions[m]]Last@Dimensions[m]];
km[[3]]m = Array[If[#1m ==/. 3,(m[[#]] 1,-> 0]f[#] &, First@Dimensions[m]]/@ pinned)
Finally the problem is reduced to solve a matrix equation ($m\mathbf{r}=\mathbf{b}$) in $x$ and $y$ direction:
bx = If[MemberQ[pinned, #], mass[[#, 1]], 0] & /@Range[First@Dimensions[m]];
by = If[MemberQ[pinned, #], mass[[#, 2]], 0] & /@Range[First@Dimensions[m]];
list1xrelaxed = LinearSolve[m, bx];
list2yrelaxed = LinearSolve[m, by];
And relaxed positions are simply:
relaxedposition = Thread[{list1xrelaxed, list2yrelaxed}];