6
$\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$
3
  • 1
    $\begingroup$ Do you need to use the shoelace formula, or will the built in function Area suffice? $\endgroup$
    – Greg Hurst
    Commented Sep 8, 2018 at 19:45
  • $\begingroup$ Yes. I need to use the shoelace formula, not built-in function. $\endgroup$
    – Eman
    Commented Sep 8, 2018 at 20:54
  • $\begingroup$ See this for an implementation of the shoelace formula. $\endgroup$ Commented Oct 12, 2018 at 16:24

3 Answers 3

2
$\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$
6
  • $\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
    Commented Sep 8, 2018 at 19:20
  • 1
    $\begingroup$ Have a look at the last edit. $\endgroup$ Commented Sep 8, 2018 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
    Commented Sep 8, 2018 at 19:37
  • 1
    $\begingroup$ Is it better now? $\endgroup$ Commented Sep 8, 2018 at 19:42
  • 1
    $\begingroup$ You're welcome. $\endgroup$ Commented Sep 8, 2018 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$
4
  • $\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
    Commented Sep 8, 2018 at 18:41
  • 1
    $\begingroup$ How are you ordering them? $\endgroup$
    – M.R.
    Commented Sep 8, 2018 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
    Commented Sep 8, 2018 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$
    – Greg Hurst
    Commented Sep 8, 2018 at 19:52
3
$\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$
1
  • $\begingroup$ Thanks so much for your help. $\endgroup$
    – Eman
    Commented Sep 8, 2018 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.