14

I have a polygon and I would like to generate $n$ evenly spaced points along the boundary.

David G. Stork
  • 41,180
  • 3
  • 34
  • 96
SidTheSloth
  • 141
  • 2
  • 3
    Welcome! If you have already tried, please share your attempt with us, and it will be easier for us to help – Johu Aug 30 '18 at 21:07

5 Answers5

11

You can use piecewise linear interpolation:

Let's generate a random polygon:

R = ConvexHullMesh[RandomPoint[Disk[], 100]]
polygon = Append[#, #[[1]]] &@MeshCoordinates[R][[MeshCells[R, 2][[1, 1]]]];

enter image description here

Creating a piecewise-linear interpolation which is parameterized by arc length.

t = Prepend[Accumulate[Norm /@ Differences[polygon]], 0.];
γ = Interpolation[Transpose[{t, polygon}], 
   InterpolationOrder -> 1, 
   PeriodicInterpolation -> True
   ];

Sampling it uniformly:

s = Subdivide[γ[[1, 1, 1]], γ[[1, 1, 2]], 100];
newpts = γ[s];

And plotting the generated points:

Show[
 R,
 ListPlot[newpts]
 ]

enter image description here

Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309
8

If you just want to generate a graphic, then you could use an Arrow with a custom Arrowheads directive. For example, here is a Polygon object:

poly = Polygon[{
    {7.361093855790543, 0.2777667989114292}, {8.37955832193947, 4.837661706721057},
    {8.064449639390588, 8.016729782194783}, {3.518023168010062, 8.74578450698846}, 
    {0.8343834304870779, 2.2170380309534554}, {4.807772222882807, 0.09815872747936005}, 
    {7.361093855790543, 0.2777667989114292}
}];

Graphics[RegionBoundary @ poly]

enter image description here

Show 10 evenly spaced points:

Graphics[{
    Arrowheads @ Append[
        ConstantArray[
            {.1, Automatic, Graphics[{PointSize[Large], Point[{0,0}]}]},
            10
        ],
        0
    ],
    Arrow @@ RegionBoundary[poly]
}]  

enter image description here

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
6

You can use BSplineFunction and ParametricPlot with ArcLength as option value for the option MeshFunctions:

SeedRandom[77]
pts = RandomReal[{-1, 1}, {7, 2}];
coords = pts[[FindShortestTour[pts][[2]]]];
n = 10;

bsF = BSplineFunction[coords, SplineDegree -> 1];
ParametricPlot[bsF[t], {t, 0, 1}, Frame -> True, Axes -> False, AspectRatio -> Automatic, 
 MeshFunctions -> {ArcLength}, 
 Mesh -> n, 
 MeshStyle -> Directive[Red, PointSize[Large]], 
 Epilog -> {Red, PointSize[Large] , Point@bsF[0]}]

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896
6

We could also use mesh functions, as Vitaliy showed here:

plot = ListLinePlot[
   coords,
   Mesh -> 20,
   MeshFunctions -> {"ArcLength"}
   ];
pts = Cases[Normal[plot], Point[pt_] :> pt, Infinity];
pts = Prepend[pts, First[coords]];

Graphics[{
  Line[coords],
  PointSize[Large], Red, Point[pts]
  }]

Mathematica graphics

I reused the polygon in Carl's answer.

C. E.
  • 70,533
  • 6
  • 140
  • 264
0

I think that the broad scheme of doing it would be as follows:

  1. Load the Polytopes package:

    << Polytopes`

  2. Use the vertices command (e.g. assuming that you are working with an octagon):

    a=Vertices[Octagon]

  3. Set up a function which interpolates between two points using a parameter t.

  4. Use the Map command to calculate the interpolated co-ordinates for any given value of t on successive values of your vertices.

GerardF123
  • 194
  • 8