1

How can I determine the angles belonging to the vertices of each interior Voronoi mesh cell?

SeedRandom[314];
pts = RandomReal[5, {20, 2}];
vor = VoronoiMesh[pts, {{0, 5}, {0, 5}}];
vm = Graphics[{White, EdgeForm[Black], MeshPrimitives[vor, 2]}];
vmInterior = 
  Graphics[{LightBlue, EdgeForm[Black], 
    MeshPrimitives[vor, {2, "Interior"}]}];
Show[vm, vmInterior, Graphics[{Orange, Point[pts]}], Axes -> True]

enter image description here

Here I have marked manually as example one of the angels $\alpha$ of a single mesh cell.

mrz
  • 11,686
  • 2
  • 25
  • 81

1 Answers1

4

This will give all the interior angles (thanks J.M. for finding my mistake)

VectorAngle[#1 - #2, #3 - #2] & @@@ Partition[#, 3, 1, {1, 1}] & /@ 
 MeshPrimitives[vor, {2, "Interior"}][[All, 1]]
(* {{2.52338, 0.458066, 1.70496, 1.59678}, {2.16596, 1.13255, 
  1.49028, 1.4944}, {2.76314, 1.73676, 1.3406, 2.81003, 
  0.774249}, {1.59378, 2.11081, 1.88852, 1.9605, 1.87116}, {2.65508, 
  2.79652, 2.45916, 2.25544, 1.34444, 1.78211, 2.41521}, {1.92314, 
  3.01509, 2.22179, 2.6078, 2.31291, 2.30653, 1.32071}, {2.2712, 
  2.64414, 2.32233, 2.15127, 1.68457, 1.64889, 2.98556}} *)

Thanks to RunnyKine for shortening the code.

But the list of angles is only so useful in my opinion, until you have a graphical way of showing the angles with the polygons. Borrowing from Silvia's code we can make this function,

angleLabeledPolygon[Polygon[pts__]] := Module[{angles},
  angles = 
   VectorAngle[#1 - #2, #3 - #2] & @@@ Partition[pts, 3, 1, {1, 1}];
  Graphics[{LightBlue, Polygon@pts,
     Text[Style[#1, Red, Bold],
              #2[[2]],

       Normalize[
        Most[Cross[{0, 0, 1}, 
          Append[Total[Normalize /@ Differences[#2]], 
           0]]]]] & @@@
     ({angles, 
        Partition[pts, 3, 1, {1, 1}]}\[Transpose])
    }
   ]
  ]

Show[angleLabeledPolygon@#, ImageSize -> 400] & /@ 
 MeshPrimitives[vor, {2, "Interior"}]

enter image description here

Jason B.
  • 68,381
  • 3
  • 139
  • 286
  • You can replace First /@ (List @@@ MeshPrimitives[vor, {2, "Interior"}]) with MeshPrimitives[vor, {2, "Interior"}][[All, 1]] – RunnyKine Mar 21 '16 at 12:22
  • @RunnyKine - Thanks, I used to never use First and always do the Part specifications. But using this site, it kinda rubbed off on me – Jason B. Mar 21 '16 at 12:25
  • There are a few angles which are greater than 90 deg. That means VectorAngle should show values > 1. The maximum of your values is 0.676899 which corresponds to less than 45 degree. I think there must be a small error, or ? – mrz Mar 21 '16 at 12:43
  • 2
    @mrz, yes, that's because the answer forgot to compensate for the fact that the corners are not centered at the origin. Here's the correct version: VectorAngle[#1 - #2, #3 - #2] & @@@ Partition[#, 3, 1, {2, -2}] & /@ MeshPrimitives[vor, {2, "Interior"}][[All, 1]]. – J. M.'s missing motivation Mar 21 '16 at 12:47
  • @J. M., Yes ... thanks for your help... now the values are as expected – mrz Mar 21 '16 at 13:00
  • Thanks for the great solution ... could you mention the compensation by J. M. in your answer? – mrz Mar 21 '16 at 13:07
  • 1
    I've said it before, but someone could build an entire reputation score on this site by following @J.M. around and posting his comments as answers, and I'm not above doing that as well. See the edit above, I think it would be neat to have the angles show up inside the polygon so that you could have it in the larger plot, but then the angle labels would get crowded in certain areas. – Jason B. Mar 21 '16 at 13:15
  • Imagine I would have only hexagons with a certain disorder and I want to give information about the mean of all angles with its standard deviation (or a histogram of all inner angles) - this is a helpful value. With your code I produced the following plot http://goo.gl/HmB3rm (example for experimental 2D hexagonal plasma crystal data) – mrz Mar 21 '16 at 14:38