Reputation: 53
I am trying to create paths with mathplotlib.path, more precisely n-gons. Although I would like to add the constraint that all polygons have the same perimeter. In order to do that I would have to calculate the perimeter of the polygon, and the adjust the path length to a fixed variable.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as mpltPath
N = 10000
points = np.random.rand(N,2)
# regular polygon
sidepoly = 5
polygon = [[np.sin(x),np.cos(x)] for x in np.linspace(0, 2*np.pi, sidepoly)[:sidepoly]]
# Matplotlib mplPath
path = mpltPath.Path(polygon)
fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='none', lw=2)
ax.add_patch(patch)
ax.axis('equal')
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
plt.show()
Any recomendations?
Upvotes: 1
Views: 131
Reputation: 80299
The side length of a regular polygon can be calculated via twice the sine of half the angle (see e.g. here). The perimeter is just one side length multiplied by the number of sides. Using a radius that divides away the default perimeter and multiplies by the desired perimeter, creates a polygon with that perimeter.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as mpltPath
from matplotlib.colors import to_rgba
fig, axs = plt.subplots(ncols=5, nrows=2, figsize=(12,5))
for sidepoly, ax in zip(range(3, 3+axs.size), axs.flatten()):
# regular polygon
desired_perimeter = 5
default_perimeter = 2 * sidepoly * np.sin(np.pi / sidepoly)
theta = np.linspace(0, 2 * np.pi, sidepoly+1)
polygon = np.c_[np.sin(theta), np.cos(theta)] * desired_perimeter / default_perimeter
path = mpltPath.Path(polygon)
patch = patches.PathPatch(path, facecolor=to_rgba('dodgerblue', alpha=0.2), edgecolor='black', lw=2)
ax.add_patch(patch)
side_length = np.sqrt((polygon[1, 0] - polygon[0, 0]) ** 2 + (polygon[1, 1] - polygon[0, 1]) ** 2)
perimeter = side_length * sidepoly
ax.text(0, 0, f'{sidepoly}-gon\nside:{side_length:.2f}\nperim.:{perimeter:.2f}', ha='center', va='center')
ax.axis('equal')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
plt.tight_layout()
plt.show()
Upvotes: 1