Consider a random irregular convex polygon, for example, the 6-side polygon
I want to define a function that, given a certain parameter r
(roundness), rounds each corner and creates a smooth polygon. Something like
Following this answer and my previous question, using the following code gets me pretty close to my goal
arcgen[{p1_, p2_, p3_}, r_, n_] :=
Module[{dc = Normalize[p1 - p2] + Normalize[p3 - p2], cc, th},
cc = p2 + r dc/EuclideanDistance[dc, Projection[dc, p1 - p2]];
th = Sign[
Det[PadRight[{p1, p2, p3}, {3, 3}, 1]]] (\[Pi] -
VectorAngle[p3 - p2, p1 - p2])/(n - 1);
NestList[RotationTransform[th, cc],
p2 + Projection[cc - p2, p1 - p2], n - 1]]
roundedPolygon[Polygon[opts_?MatrixQ], r_?NumericQ,
n : (_Integer?Positive) : 12] :=
With[{pts = Split[opts][[All, 1]]},
Polygon[Flatten[
arcgen[#, r, n] & /@
Partition[
If[TrueQ[First[pts] == Last[pts]], Most, Identity][pts], 3,
1, {2, -2}], 1]]];
This works perfectly for regular polygons. However, when considering random irregular polygons (from a Voronoi mesh, for example), something odd starts to happen
L1 = 3; L2 = 3;
pts = {RandomReal[L1, L1 L2], RandomReal[L2, L1 L2]} // Transpose;
mesh = VoronoiMesh[pts];
pol = RandomChoice[MeshPrimitives[mesh, 2]];
ListAnimate[Table[Graphics[{EdgeForm[Thick], White, roundedPolygon[pol, r]}],
{r, .01, .4, .01}]]
It seems that if two or more vertices are "too close" and for some values of the roundness r
, the drawing circles overlap and create this extra structures that I want to avoid. Notice that only happens for specific values of r
, which might depend on the random polygon extracted from the Voronoi mesh.
Now, I believe there are two ways to go about this:
Simply removing these external circumference bits is enough for my goal, but how do I do it efficiently? That is, how do I trim such parts (if they occur) and keep the (almost) rounded polygon?
Perhaps more challenging, how do I implement this roundness idea to a random irregular convex polygon? I guess mapping the polygon to a circle would be good (could the area be kept constant?), maybe following something like the Schwarz–Christoffel mapping? Alternatively, could I maybe determine an automatic "cutoff" for each vertex and its proximity to other vertex?
1 is my main goal, but I'm open to more elegant solutions. Any ideas?
Just for a bit of context, my background and motivation: I'm modelling an epithelium with a convex mesh, where each polygon is represents a biological cell. My goal is to simply provide a more realistic look to each cell by rounding its vertices. For example, a transformation like
If there is a nicer way of doing this, please let me know. The left mesh is given by the following code
L1 = 4; L2 = 4; ptr = .2;
pts = Table[
Flatten[Table[{3/2 i, Sqrt[3] j + Mod[i, 2] Sqrt[3]/2}, {i,
L2 + 4}, {j, L1 + 4}], 1][[j]] + {RandomReal[{-ptr, ptr}],
RandomReal[{-ptr, ptr}]}, {j, (L1 + 4) (L2 + 4)}] // N;
mesh0 = VoronoiMesh[pts];
mesh1 = MeshRegion[MeshCoordinates[mesh0],
With[{a = PropertyValue[{mesh0, 2}, MeshCellMeasure]},
With[{m = 6}, Pick[MeshCells[mesh0, 2], UnitStep[a - m], 0]]]];
mesh = MeshRegion[MeshCoordinates[mesh1],
MeshCells[mesh1, {2, "Interior"}]]
ListAnimate
, just a function that rounds the cells. $\endgroup$