How to add 'border' to Voronoi diagram
Update 2: An alternative way to specify the cropping region:
ClearAll[bsf, explode]
bsf = BSplineFunction[outerpoints[[FindShortestTour[outerpoints][[2]]]],
SplineDegree -> Automatic, SplineClosed -> True];
explode[f_] := f[#] + {{0, -#2}, {#2, 0}}.Normalize[f'[t] /. t -> #] &;
borderpoly = Polygon[explode[bsf][#, .2] & /@ Subdivide[100]];
pieces2 = BoundaryDiscretizeRegion[#, BaseStyle -> Opacity[.25, RandomColor[]]] & /@
(Graphics`PolygonUtils`PolygonIntersection[#, borderpoly] & /@
MeshPrimitives[vm, 2]);
Show[pieces2, Graphics[{Red, Point[pts], Purple, PointSize[Medium],
Point @ outerpoints}], ImageSize -> Medium]
Use explode[bsf][#, .4] &
when defining borderpoly
to get
Update: Cropping frontier polygons and lines:
SeedRandom[1]
pts = RandomReal[{-1, 1}, {100, 2}];
vm = VoronoiMesh[pts];
mc = MeshCells[VoronoiMesh[pts], {1 | 2, "Frontier"}];
intm = RegionDifference[vm, MeshRegion[MeshCoordinates[vm], mc]];
borderpolygon = MeshPrimitives[BoundaryDiscretizeRegion[
TransformedRegion[intm, ScalingTransform[1.3 {1, 1}]]], 2][[1]];
pieces = BoundaryDiscretizeRegion[#,
BaseStyle -> Opacity[.25, RandomColor[]]] & /@
(Graphics`PolygonUtils`PolygonIntersection[#, borderpolygon] & /@
MeshPrimitives[vm, 2]);
outerpoints = Select[pts, Not @* RegionMember[intm]];
Row[{Show[vm, pieces, Graphics[{Red, Point[pts], Purple, PointSize[Medium],
Point @ outerpoints}], ImageSize -> Medium],
Show[pieces, Graphics[{Red, Point[pts], Purple, PointSize[Medium],
Point @ outerpoints}], ImageSize -> Medium]}]
Original answer:
You can use the second argument of VoronoiMesh
to specify coordinate bounds:
SeedRandom[1]
pts = RandomReal[{-1, 1}, {100, 2}];
Show[VoronoiMesh[pts, 1.1 {{-1, 1}, {-1, 1}}], Graphics[{Red, Point[pts]}]]
You can do it like this in Cropping a Voronoi diagram but the result is a bit ugly
pts = RandomReal[{-1, 1}, {100, 2}];
vmsh = VoronoiMesh[pts];
poly2disk[cell_, radius_] :=
Block[{pts = MeshPrimitives[cell, 0][[All, 1]]},
Return[Disk[Mean[pts], radius]]
]
disks = DiscretizeRegion[
RegionUnion[poly2disk[#, 0.3] & /@ MeshPrimitives[vmsh, 2]]];
DeleteCases[
RegionIntersection[DiscretizeGraphics@#, disks] & /@
MeshPrimitives[vmsh, 2], _RegionIntersection] //
RegionPlot[#, AspectRatio -> Automatic] &
You could also mask the mesh with the convex hull if you're happy with the points lying on the edge having no space around them. Here I show the result on top.
cvxh=ConvexHullMesh[pts];
Show[
vmsh,
DeleteCases[
RegionIntersection[DiscretizeGraphics@#, cvxh] & /@
MeshPrimitives[vmsh, 2], _RegionIntersection] //
RegionPlot[#, AspectRatio -> Automatic] &
,
Graphics[Point[pts]]
]
Maybe scaling up the new mesh about the center of all points would expand the convex hull enough to include some space around the edges too if that's desired.