5
$\begingroup$

The following code gets all vertices of all polygons (mesh cells) of VoronoiMesh[pts]:

SeedRandom[3]; 
pts = RandomReal[{-1, 1}, {25, 2}];
mesh = VoronoiMesh[pts];
vertices = MeshCoordinates[mesh];
Show[mesh, Graphics[{Black, Point[pts], Red, Point[vertices]}]]

This outputs:

Voronoi

My question

How can I get a list of vertices for each polygon and compute the area of each polygon using the Shoelace formula?

The output should be similar to:

Output

So, by clicking on the polygon number, it should show its vertices and its size.

I found this tool-tip image in Finding the perimeter, area and number of sides of a Voronoi cell

$\endgroup$
  • 1
    $\begingroup$ Do you need to use the shoelace formula, or will the built in function Area suffice? $\endgroup$ – Chip Hurst Sep 8 '18 at 19:45
  • $\begingroup$ Yes. I need to use the shoelace formula, not built-in function. $\endgroup$ – Eman Sep 8 '18 at 20:54
  • $\begingroup$ See this for an implementation of the shoelace formula. $\endgroup$ – J. M. will be back soon Oct 12 '18 at 16:24
1
$\begingroup$
polygons = Join @@ MeshCells[mesh, 2, "Multicells" -> True][[All, 1]];
polygondata = With[{x = MeshCoordinates[mesh]}, Map[
    p \[Function] Partition[x[[p]], 2, 1, 1],
    polygons
    ]];
areas = 0.5 Total[Map[Det, polygondata, {2}], {2}];
circumferences = Total[Map[Norm, Differences /@ polygondata, {2}], {2}];

For the tooltipping, you can also use the option MeshCellLabel of MeshRegion, but that's are a bit unwieldy:

MeshRegion[mesh, MeshCellLabel -> Map[
   i \[Function] ({2, i} -> Tooltip[
       i,
       Grid[{
         {"Vertices", polygons[[i]]},
         {"Vertex Coordinates", polygondata[[i, All, 1]]},
         {"Area", areas[[i]]},
         {"Perimeter", circumferences[[i]]}
         },
        Alignment -> {Left, Top}
        ]
       ]
     ),
   Range[MeshCellCount[mesh, 2]]
   ]
 ]
$\endgroup$
  • $\begingroup$ Thanks so much for your help and your edit. That is helpful for getting the polygons' sizes of each polygon. If I want to show the vertices values of each polygon also. How can I do that?? Any suggestions?? $\endgroup$ – Eman Sep 8 '18 at 19:20
  • 1
    $\begingroup$ Have a look at the last edit. $\endgroup$ – Henrik Schumacher Sep 8 '18 at 19:28
  • $\begingroup$ Thanks so much for your help. I am really sorry for disturbance. But, I think the vertices in the code, gives the order of the vertices of each polygon, not the values of the vertices' points. $\endgroup$ – Eman Sep 8 '18 at 19:37
  • 1
    $\begingroup$ Is it better now? $\endgroup$ – Henrik Schumacher Sep 8 '18 at 19:42
  • 1
    $\begingroup$ You're welcome. $\endgroup$ – Henrik Schumacher Sep 8 '18 at 20:57
4
$\begingroup$

Use MeshPrimitives like this:

Show[Graphics[{FaceForm@RGBColor[
    0.666, 0.776, 0.952], 
   Table[Tooltip[p, 
     Grid@{{"Perimeter", Perimeter@p}, {"Area", Area@p}, {"Edges", 
        Length @@ p}}], {p, MeshPrimitives[mesh, 2]}]}], 
 Graphics[{Black, Point[pts], Red, Point[vertices]}]]

enter image description here

$\endgroup$
  • $\begingroup$ Thanks so much for your help. But, if I want the vertices of each polygon to be shown also with area,edges and Perimeter. How to do that?? $\endgroup$ – Eman Sep 8 '18 at 18:41
  • 1
    $\begingroup$ How are you ordering them? $\endgroup$ – M.R. Sep 8 '18 at 18:47
  • $\begingroup$ Thanks so much for your help and your reply. What did you mean by them ? Did you mean the vertices?? If you mean the vertices, I don't order them. the code get all vertices of all voronoi polygons. I want to get the vertices of each polygon, separately. So, by clicking on each polygon; I can get its vertices. $\endgroup$ – Eman Sep 8 '18 at 19:12
  • 2
    $\begingroup$ Note that PropertyValue[{mesh, 2}, MeshCellMeasure] is a faster way to get all of the areas. However I don't think the other properties can be computed in this way. $\endgroup$ – Chip Hurst Sep 8 '18 at 19:52
2
$\begingroup$

Here's an efficient way to implement the shoelace formula, assuming no self intersections:

ShoelaceArea[Polygon[pts_?MatrixQ]] := 
  0.5 * #1.(RotateLeft[#2] - RotateRight[#2])& @@ Transpose[pts]

A comparison:

shoeareas = ShoelaceArea /@ MeshPrimitives[mesh, 2]; // AbsoluteTiming
 {0.000233, Null}
areas = PropertyValue[{mesh, 2}, MeshCellMeasure]; // AbsoluteTiming
 {0.000013, Null}
Max[Abs[shoeareas - areas]]
3.33067*10^-16
$\endgroup$
  • $\begingroup$ Thanks so much for your help. $\endgroup$ – Eman Sep 8 '18 at 21:12

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.