VoronoiMesh as a Graph

With IGraph/M, you can use

IGLatticeMesh["Hexagonal", Rectangle[{0, 0}, {2, 4}]]

enter image description here

IGLatticeMesh first fills the region Rectangle[{0, 0}, {2, 4}] with lattice points, then places a unit mesh cell at each lattice point. You can use a different region to obtain a different overall shape. Keep in mind that it is not the mesh that is being cropped to this region, but only the points that define the locations of unit cells.

IGMeshGraph[%]

enter image description here


L = 3;
pts = Flatten[Table[{3/2 i, Sqrt[3] j + Mod[i, 2] Sqrt[3]/2}, {i, L + 4}, {j, L + 4}], 1];

mesh0 = VoronoiMesh[pts];
mr0 = DiscretizeGraphics[Select[MeshPrimitives[mesh0, 2], 
    RegionWithin[Rectangle @@ Transpose[CoordinateBounds[pts]], #] &]];

el0 = MeshCells[mr0, 1] /. Line -> Apply[UndirectedEdge];
vc0 = MeshCoordinates[mr0];

Show[mesh0, Graph[el0, VertexCoordinates -> vc0, EdgeStyle -> Thick]]

enter image description here

Slightly more convenient approach is to provide the coordinate bounds in the second argument of VoronoiMesh and discretize the interior polygons:

mesh1 = VoronoiMesh[pts, CoordinateBounds[pts]];

mr1 = DiscretizeGraphics[MeshPrimitives[mesh1, {2, "Interior"}]];

el1 = MeshCells[mr1, 1] /. Line -> Apply[UndirectedEdge];
vc1 = MeshCoordinates[mr1];

Show[mesh1, 
 Graph[el1, VertexCoordinates -> vc1, EdgeStyle -> Thick]]

enter image description here