Imagine I want to stretch a mesh with a 'rubberband-type' effect. That is, upon and elastic stretch from both side edges, the mesh centres simply scale as follows

enter image description here

where the points are seeds for updating Voronoi tessellations.

This was done by manually scaling the points, but I would like to get this effect by using an actual vertex model and having a mechanical force stretch the tissue. That is, instead of Voronoi seeds, such force would act on the cell vertices and I would get no cell intercalation (changing neighbours, or changing edges). Any idea or references on how to do this?

  • 3
    $\begingroup$ Out of curiosity, how did you manually distribute the points? $\endgroup$
    – user21
    Mar 22 at 15:44
  • 3
    $\begingroup$ (1) Once you have a mesh, you can stretch the mesh coordinates. (2) Is the stretching to preserve the volume/area of the cells? (Is there a physical model, or are you after a geometric effect that need not be physically accurate?) $\endgroup$
    – Michael E2
    Mar 22 at 17:13
  • $\begingroup$ @user21 initially, Lloyd's relaxation. the stretch was done by a parametrized rescaling $\endgroup$
    – sam wolfe
    Mar 22 at 23:37
  • $\begingroup$ @MichaelE2 there are plenty, mostly energy-based. Look at Farhadifar's vertex model, for example. But I'm looking for something simpler to avoid any kind of cell intercalations (or T1 transitions). So simply readjusting the vertex positions with some force transmission that preserves cell shape to some degree. $\endgroup$
    – sam wolfe
    Mar 22 at 23:39
  • $\begingroup$ One alternative to vertex models could be to consider a spring-based model, where each pair of vertices is connected by a spring with an associated stiffness, but I'm not too sure how to implement that, and whether stretch forces are easily transmissible on that system. Any suggestions are appreciated $\endgroup$
    – sam wolfe
    Mar 22 at 23:47

2 Answers 2


enter image description here

rescaley[t_] := 1 - t Rescale[#, {-t, t}, {0, 1}] (1 - Rescale[#, {-t, t}, {0, 1}]) &

stretch[t_] := ReplaceAll[{x_Real, y_Real} :>
    {t x, Rescale[y, {-1, 1}, {rescaley[t][t x], -rescaley[t][t x]}]}]

cba = Join @@ CoordinateBoundsArray[{{-1, 1}, {-1, 1}}, Into[15], Center] + 
   RandomReal[{-.03, .03}, {15^2, 2}];

show[t_] := Show[VoronoiMesh[stretch[t]@cba, {{-3, 3}, {-1, 1}}], 
   Graphics[{PointSize[Small], Black, Point[stretch[t]@cba]}], 
   ImageSize -> Large];

Animate[show[t], {t, 1, 3}]

enter image description here

The gif animation above obtained using:

Export["stretchVoronoi.gif", Table[show[t], {t, 1, 3, .05}]]

Update: Using stretch on polygon vertices:

polygons = MeshPrimitives[VoronoiMesh[cba, {{-1, 1}, {-1, 1}}], 2];

show2[t_] := Graphics[{EdgeForm[Gray], LightBlue, stretch[t] /@ polygons, 
    PointSize[Small], Black, Point[stretch[t]@cba]}, 
   ImageSize -> Large, PlotRange -> {{-3, 3}, {-3/2, 3/2}}];

Animate[show2[t], {t, 1, 3}]

enter image description here

Alternatively, per Michael E2.'s suggestion in comments, create new MeshRegion using stretch on cba and the mesh cells from VoronoiMesh[cba]:

{mc, cells} = Through[{MeshCoordinates, MeshCells[#, 2] &}@
    VoronoiMesh[cba, {{-3, 3}, {-1, 1}}]];

show3[t_] := Show[MeshRegion[stretch[t] @ mc, cells], 
   Graphics[{PointSize[Small], Black, Point[stretch[t]@cba]}], 
   PlotRange -> {{-3, 3}, {-1, 1}}, ImageSize -> Large];

Animate[show3[t], {t, 1, 3}]

enter image description here

  • $\begingroup$ Great answer! Is it possible to define the stretch function in such a way that, instead of acting on the Voronoi seeds (cell "centres"), it acts on the cell vertices instead? I guess it is only a question of tracking the corresponding edges, but I was just wondering if there is a straightforward way to do it with your code. That way I guarantee no cell intercalation (cells changing neighbours) happens and completely avoid using VoronoiMesh $\endgroup$
    – sam wolfe
    Mar 23 at 13:02
  • $\begingroup$ something like the example in the update? $\endgroup$
    – kglr
    Mar 23 at 13:39
  • $\begingroup$ Yes! That is exactly what I was looking for. Now I just which I could justify that deformation with some physical argument and an ode on the vertex positions. I know about potential-based vertex models and Hookean laws could help. Any suggestion is appreciated, but I understand this might be way beyond the scope of the question. Thank you nonetheless! $\endgroup$
    – sam wolfe
    Mar 23 at 14:32
  • $\begingroup$ Also, where is polygons defined? $\endgroup$
    – sam wolfe
    Mar 23 at 14:35
  • $\begingroup$ @samwolfe, fixed the cut/paste error re polygons. $\endgroup$
    – kglr
    Mar 23 at 14:46

Something like:

nx = 5; ny = 3;
 pts = Flatten[
   Table[{x d, 2 y} + 0.5 RandomReal[{-1, 1}, 2], {x, -nx, 
     nx}, {y, -ny, ny}], 1];
 Show[VoronoiMesh[pts], Graphics[Point[pts]], 
  PlotRange -> {5  nx {-1, 1}, 3 ny {-1, 1}}, ImageSize -> {500, 200},
   Axes -> True]
, {{d, 2}, 1, 3}]

still shot from the Manipulate


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.