Reputation: 424
How may I take a shape that was created with more points at its curves and subdivide it so that the points are distributed more equally along the curve? In my research I thought that numpy
's interp might be the right function to use, but I don't know what to use for the parameters (x
, xp
, fp
, left
, right
, & period
). Any help would be very appreciated!
Here is an animation showing the desired output.
This is the code for the input rounded rectangle:
from matplotlib import pyplot as plt
import numpy as np
x_values = [1321.4, 598.6, 580.6, 563.8, 548.6, 535.4, 524.5, 516.2, 511,
509.2, 509.2, 511, 516.2, 524.5, 535.4, 548.6, 563.8, 580.6, 598.6, 1321.4, 1339.4,
1356.2, 1371.4, 1384.6, 1395.5, 1403.8, 1409, 1410.8, 1410.8, 1409, 1403.8, 1395.5,
1384.6, 1371.4, 1356.2, 1339.4, 1321.4]
y_values = [805.4, 805.4, 803.5, 798.3, 790.1,
779.2, 766, 750.8, 734, 716, 364, 346, 329.2, 314, 300.8, 289.9, 281.7, 276.5, 274.6,
274.6, 276.5, 281.7, 289.9, 300.8, 314, 329.2, 346, 364, 716, 734, 750.8, 766, 779.2,
790.1, 798.3, 803.5, 805.4]
fig, ax = plt.subplots(1)
ax.plot(x_values,y_values)
ax.scatter(x_values,y_values)
ax.set_aspect('equal')
plt.show()
Thank you!
Upvotes: 3
Views: 1116
Reputation: 493
This is a very rudimental solution, where you interpolate between the neighbouring points on a line.
Basically what the code does is, that it places "temporary" points on the line between the neighbour points evenly spaced with approximately stepsize
spacing. This will result in an approximately even spacing on the curve (the smaller the stepsize
the denser the more points you have). Now if you pick every skipper
-th point on it, the spacing between those points will be approx skipper*stepsize
.
There is a small flaw in it, the first and the last points are not guaranteed to be this far from eachother, so you have to play with the skipper
to fix that.
The code:
stepsize = 10**-2
new_x = np.array([])
new_y = np.array([])
for i in range(len(x_values)):
x0 = x_values[i]
x1 = x_values[(i+1)%len(x_values)]
y0 = y_values[i]
y1 = y_values[(i+1)%len(x_values)]
dx = x1-x0
dy = y1-y0
length = np.sqrt(dx**2+dy**2)
N = int(length/stepsize)
new_x = np.append(new_x,np.linspace(x_values[i],x_values[(i+1)%len(x_values)],N))
new_y = np.append(new_y,np.linspace(y_values[i],y_values[(i+1)%len(x_values)],N))
skipper = 6650
fig, ax = plt.subplots(1)
ax.plot(x_values,y_values)
ax.scatter(new_x[::skipper],new_y[::skipper])
ax.set_aspect('equal')
plt.show()
Upvotes: 1
Reputation: 25023
from matplotlib import pyplot as plt
import numpy as np
x = np.array([1321.4, 598.6, 580.6, 563.8, 548.6, 535.4, 524.5, 516.2, 511,
509.2, 509.2, 511, 516.2, 524.5, 535.4, 548.6, 563.8, 580.6, 598.6, 1321.4, 1339.4,
1356.2, 1371.4, 1384.6, 1395.5, 1403.8, 1409, 1410.8, 1410.8, 1409, 1403.8, 1395.5,
1384.6, 1371.4, 1356.2, 1339.4, 1321.4])
y = np.array([805.4, 805.4, 803.5, 798.3, 790.1,
779.2, 766, 750.8, 734, 716, 364, 346, 329.2, 314, 300.8, 289.9, 281.7, 276.5, 274.6,
274.6, 276.5, 281.7, 289.9, 300.8, 314, 329.2, 346, 364, 716, 734, 750.8, 766, 779.2,
790.1, 798.3, 803.5, 805.4])
fig, ax = plt.subplots(1)
ax.set_aspect('equal')
ax.scatter(x, y, s=40, zorder=3, alpha=0.3)
# compute the distances, ds, between points
dx, dy = x[+1:]-x[:-1], y[+1:]-y[:-1]
ds = np.array((0, *np.sqrt(dx*dx+dy*dy)))
# compute the total distance from the 1st point, measured on the curve
s = np.cumsum(ds)
# interpolate using 200 point
xinter = np.interp(np.linspace(0,s[-1], 200), s, x)
yinter = np.interp(np.linspace(0,s[-1], 200), s, y)
# plot the interpolated points
ax.scatter(xinter, yinter, s=5, zorder=4)
plt.show()
Upvotes: 5
Reputation: 694
One way to do this is with the shapely library. You can use your points to make a LineString
object, and then interpolate that using numpy.linspace
like you expected.
import numpy as np
import matplotlib.pyplot as plt
import shapely
x_values = [1321.4, 598.6, 580.6, 563.8, 548.6, 535.4, 524.5, 516.2, 511,
509.2, 509.2, 511, 516.2, 524.5, 535.4, 548.6, 563.8, 580.6, 598.6, 1321.4, 1339.4,
1356.2, 1371.4, 1384.6, 1395.5, 1403.8, 1409, 1410.8, 1410.8, 1409, 1403.8, 1395.5,
1384.6, 1371.4, 1356.2, 1339.4, 1321.4]
y_values = [805.4, 805.4, 803.5, 798.3, 790.1,
779.2, 766, 750.8, 734, 716, 364, 346, 329.2, 314, 300.8, 289.9, 281.7, 276.5, 274.6,
274.6, 276.5, 281.7, 289.9, 300.8, 314, 329.2, 346, 364, 716, 734, 750.8, 766, 779.2,
790.1, 798.3, 803.5, 805.4]
coords = np.array([x_values, y_values]).T
poly = shapely.LineString(coords)
coords_new = poly.interpolate(np.linspace(0, 1, num=51), normalized=True)
x_new = [pt.x for pt in coords_new]
y_new = [pt.y for pt in coords_new]
plt.plot(x_new, y_new)
plt.scatter(x_new, y_new)
plt.show()
Upvotes: 1