Basic Verlet Integration implementation
Bunch of points
pts0 = RandomReal[{-1,1}, {10, 2}];
pts1 = pts0; pts2 = pts0;
Graphics[{Rectangle[{-10,-10}, {10,10}], Red, Point[pts0 // Offload]}]
With[{\[Delta]t = 0.5},
pts0 = 2 pts1 - pts2 + Table[{0,-1}, {Length[pts0]}] (*SpB[*)Power[\[Delta]t(*|*),(*|*)2](*]SpB*);
pts2 = pts1;
pts1 = pts0;
]
bonds = RandomGraph[Length[pts0]{1, 2}, VertexCoordinates->pts0]
getDir[bonds_, pts_] := Map[(pts[[#[[1]]]] - pts[[#[[2]]]]) &, bonds]
applyBond[pairs_, k_:1.0, maxDelta_:0.1][p_] := Module[{pts = p},
MapThread[Function[{edge, length}, With[{
diff = pts[[edge[[1]]]] - pts[[edge[[2]]]]
},
With[{
delta =Min[k ( (*FB[*)((length)(*,*)/(*,*)(Norm[diff]+0.001))(*]FB*) - 1), maxDelta] diff
},
pts[[edge[[1]]]] += delta/2.0;
pts[[edge[[2]]]] -= delta/2.0;
]
] ], RandomSample[pairs]//Transpose];
pts
]
showGeometry[points_, bonds_, opts___] := Graphics[{
Gray, Rectangle[5{-1,-1}, 5{1,1}], Blue,
Table[
With[{i = edge[[1]], j = edge[[2]]},
Line[With[{
p = points
}, {p[[i]], p[[j]]}]] // Offload
]
, {edge, bonds}],
Red, Point[points // Offload]
}, opts]
SetAttributes[showGeometry, HoldFirst];
showGeometry[pts0, EdgeList @ bonds]
pts0 = RandomReal[{-1,1}, {10, 2}];
pts1 = pts0; pts2 = pts0;
bonds = EdgeList[RandomGraph[Length[pts0]{1, 3}]];
lengths = Norm /@ getDir[bonds, pts0];
pairs = {bonds, lengths} // Transpose;
Do[With[{\[Delta]t = 0.05},
pts0 = Clip[applyBond[pairs, 1.0][
2 pts1 - pts2 + Table[{0,-1}, {i, Length[pts0]}] (*SpB[*)Power[\[Delta]t(*|*),(*|*)2](*]SpB*)
], {-5,5}];
pts2 = pts1;
pts1 = pts0;
Pause[0.01];
], {i, 200}]
Animation widget
Module[{pts0, pts1, pts2, trigger, button, bonds, lengths, pairs, cache},
trigger = EventObject[];
button = InputButton["Restart"];
EventHandler[button, Function[Null,
pts0 = RandomReal[{-1,1}, {10, 2}];
pts1 = pts0; pts2 = pts0;
bonds = EdgeList[RandomGraph[Length[pts0]{1, 3}]];
lengths = Norm /@ getDir[bonds, pts0];
pairs = {bonds, lengths} // Transpose;
]];
button // EventFire;
{
button,
"","",
Animate[showGeometry[pts0, EdgeList @ bonds], {n,1,100,1},
"UpdateFunction"->Function[n,
With[{\[Delta]t = 0.05},
pts0 = Clip[applyBond[pairs, 1.0][
2 pts1 - pts2 + Table[{0,-1}, {i, Length[pts0]}] (*SpB[*)Power[\[Delta]t(*|*),(*|*)2](*]SpB*)
], {-5,5}];
pts2 = pts1;
pts1 = pts0;
];
(* prevent default action of Animate*)
False
],
"TriggerEvent"->EventClone[button], AnimationRate->30
]
} // Column // Panel
]
Procedurally generated structures
Rim
rim = Join @@
(Table[#{Sin[x], Cos[x]}, {x,-Pi, Pi, Pi/6}] &/@ {1, 0.9} // Transpose);
rbonds = Graph[
Join[
Table[i<->i+1, {i, 1, Length[rim]-1}],
Table[i<->i+2, {i, 1, Length[rim]-2, 2 }],
Table[i<->i+2, {i, 2, Length[rim]-4, 2 }],
{Length[rim]-2 <-> 2},
{Length[rim]-1 <-> 1}
]
, VertexCoordinates->rim]
rbonds = EdgeList[rbonds];
rpairs = {rbonds, Norm /@ getDir[rbonds, 2.0 rim]} // Transpose;
rim0 = 2.0 rim; rim1 = rim0; rim2 = rim0;
rimR = rim0;
mousePos = {100.,0.};
EventHandler[
showGeometry[rimR, rbonds, TransitionType->None, "Controls"->False, Epilog->{
AnimationFrameListener[rimR // Offload, "Event"->"anim"],
Circle[mousePos // Offload, 0.5]
}, PlotRange->{{-5,5}, {-5,5}}]
, {"mousemove" -> Function[xy,
mousePos = xy;
]}]
Button["Start",
EventHandler["anim", With[{}, Do[With[{\[Delta]t = 0.006},
rim0 = applyBond[rpairs, 1.0, 0.8][
Clip[(2 rim1 - rim2) + Table[
If[Max[Abs[i - mousePos]] < 2.0, {0,-1} - 7.0 (i - mousePos), {0,-1}]
, {i, rim0}] (*SpB[*)Power[\[Delta]t(*|*),(*|*)2](*]SpB*), {-5,5}]
];
rim2 = rim1;
rim1 = rim0;
], {i, 10}];
rimR = rim0;
]&];
rimR = rim0;
]
Button["Stop", EventRemove["anim"]]
Button["Reset", With[{}, rim0 = 2.0 rim; rim1 = rim0; rim2 = rim0;
rimR = rim0;]]
Generate a Mesh from an Image
mask = NotebookStore["reburying-4d2"];
EventHandler[InputRaster[mask], (mask = #)&]
mesh = TriangulateMesh[
ImageMesh[ImageResize[mask , 100]// ColorNegate]
, MaxCellMeasure->{"Area"->100}];
graph = MeshConnectivityGraph[mesh, 0] // IndexGraph
vertices = graph // GraphEmbedding;
edges = (List @@ #) &/@ (graph // EdgeList) (*BB[*)(*convert to list of lists*)(*,*)(*"1:eJxTTMoPSmNhYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCS4g4Zyfm5uaV+KUXxEMUqxsbm6exgSSBPGCSnNSg9mAjOCSosy8dLBYSFFpKpoKkDkeqYkpEFXBILO1sCgJSczMQVYCAOFrJEU="*)(*]BB*);
vertices = Map[Function[x, x - {0.4,-1.2}], 0.04 vertices] (*BB[*)(*scale and translate*)(*,*)(*"1:eJxTTMoPSmNhYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCS4g4Zyfm5uaV+KUXxEMUqxsbm6exgSSBPGCSnNSg9mAjOCSosy8dLBYSFFpKpoKkDkeqYkpEFXBILO1sCgJSczMQVYCAOFrJEU="*)(*]BB*);
vertices0 = vertices; vertices1 = vertices0; vertices2 = vertices0;
verticesR = vertices0;
vpairs = {edges, Norm /@ getDir[edges, vertices0]} // Transpose;
mousePos = {100.,0.};
EventHandler[
showGeometry[verticesR, edges, TransitionType->None, "Controls"->False, Epilog->{
AnimationFrameListener[verticesR // Offload, "Event"->"anim2"],
Circle[mousePos // Offload, 0.5]
}, PlotRange->{{-5,5}, {-5,5}}]
, {"mousemove" -> Function[xy,
mousePos = xy;
]}]
Button["Start",
EventHandler["anim2", With[{}, Do[With[{\[Delta]t = 0.003},
vertices0 = applyBond[vpairs, 1.0, 0.8][
Clip[(2 vertices1 - vertices2) + Table[
If[Max[Abs[i - mousePos]] < 2.0, {0,-1} - 7.0 (i - mousePos), {0,-1}]
, {i, vertices0}] (*SpB[*)Power[\[Delta]t(*|*),(*|*)2](*]SpB*), {-5,5}]
];
vertices2 = vertices1;
vertices1 = vertices0;
], {i, 3}];
verticesR = vertices0;
]&];
verticesR = vertices0;
]
Button["Stop", EventRemove["anim"]]
Button["Reset", With[{}, vertices0 = vertices; vertices1 = vertices0; vertices2 = vertices0;
verticesR = vertices0;]]