say we want to generate a zig-zag set of points as a numpy array like the following image such that the array elements' order is similar to moving on the path:
we are given:
What is the simplest way to generate such numpy array? I tried scipy square wave but aside from other required features it only generates the teeth edge points but not all the path in a way that can be shown with scatter plot
Apologies in advance for ignoring your starting point and teeth direction . I started without considering them and when I was finished and only had to add them I thought that you can very likely do that yourself. I also think there could be a more pretty solution to your x pixel point distance request than just getting a lot of points and filtering them so that is satisfied. Let me know if that's important to you. That aside I think this is a nice solution.
def zig_zag(x_interval,y_interval,tooth_width,step_size):
#finding the teeth edge points
x_vals = np.arange(*x_interval,tooth_width)
idx = np.arange(x_vals.shape[0]*2-1)%4
mask = ((idx == 0) | (idx == 1))
x = np.empty(mask.shape, dtype='int')
y = np.empty(mask.shape, dtype='int')
x[mask] = x_vals
x[~mask] = x_vals[1:]
y[mask] = y_interval[1]
y[~mask] = y_interval[0]
#interpolating between the teeth edge points and get way to many points
tck, u = interpolate.splprep([x,y],s=0,k=1)
x, y = interpolate.splev(np.linspace(0, 1, 10**6), tck)
#pick the perfect points
arr = np.array(tuple(filter_points(x,y,step_size)))
x = arr[:,0]
y = arr[:,1]
#plot it
ax = plt.gca()
ax.scatter(x, y)
ax.set_aspect('equal')
plt.savefig("teeth.png")
def filter_points(x,y,step_size):
found = x[0],y[0]
step_size **= 2
yield found
for x,y in zip(x,y):
if (found[0]-x)**2+(found[1]-y)**2 >= step_size:
found = x,y
yield found
zig_zag((0,700),(0, 200),100,5)
I have so far the following answer:
from copy import copy
import numpy as np
class ZigZagTraj(object):
def __init__(self, xs, ys, xe, ye, tooth_direction='x', tooth_width=0.2, step=0.05):
self.xs, self.ys, self.xe, self.ye = xs, ys, xe, ye
self.tooth_direction = tooth_direction
self.tooth_width = tooth_width
self.step = step
self.bounds = {'x': {'lb':None, 'ub':None },
'y': {'lb':None, 'ub':None }}
if xe - xs > 0:
self.bounds['x']['ub'] = self.xe
self.bounds['x']['lb'] = self.xs
else:
self.bounds['x']['ub'] = self.xs
self.bounds['x']['lb'] = self.xe
if ye - ys > 0:
self.bounds['y']['ub'] = self.ye
self.bounds['y']['lb'] = self.ys
else:
self.bounds['y']['ub'] = self.ys
self.bounds['y']['lb'] = self.ye
self.x_increment_sign = np.sign(self.xe - self.xs)
self.y_increment_sign = np.sign(self.ye - self.ys)
self.curr_direction = tooth_direction
self.curr_tooth_width = 0
self.traj = []
self.traj.append([xs, ys])
def change_curr_direction(self):
if self.curr_direction == 'x':
self.curr_direction = 'y'
elif self.curr_direction == 'y':
self.curr_direction = 'x'
return self.curr_direction
def in_bound(self,new_point):
return self.in_x_bound(new_point) and self.in_y_bound(new_point)
def in_x_bound(self,new_point):
return self.bounds['x']['lb'] <= new_point[0] <= self.bounds['x']['ub']
def in_y_bound(self, new_point):
return self.bounds['y']['lb'] <= new_point[1] <= self.bounds['y']['ub']
def generate_trajectory(self):
self.tooth_direction = self.tooth_direction
curr_tooth_width = 0
traj = []
traj.append([self.xs, self.ys])
#print('self.x_increment_sign',self.x_increment_sign, 'self.x_increment_sign',self.x_increment_sign)
while True:
#print(traj[-1], 'for direction', self.curr_direction)
new_point = copy(traj[-1])
if self.curr_direction == 'x':
new_point[0] += self.step * self.x_increment_sign
elif self.curr_direction == 'y':
new_point[1] += self.step * self.y_increment_sign
if self.curr_direction != self.tooth_direction: # we're on a tooth
curr_tooth_width += self.step
#print('checking if tooth width is reached', curr_tooth_width, tooth_width)
if curr_tooth_width >= self.tooth_width:
if self.tooth_direction == 'x': # along the tooth direction we should now run backwards
self.x_increment_sign *= -1
else:
self.y_increment_sign *= -1
curr_tooth_width = 0
self.change_curr_direction()
#print('not append(tooth width). moving to direction: ', self.curr_direction)
continue
elif not self.in_bound(new_point): # we're on tooth length ( out of bound for lenght direction)
self.change_curr_direction()
#print('not append(tooth length)')
continue
#print('checking if we should append')
#print('new point', new_point)
#print(self.in_x_bound(new_point), self.in_y_bound(new_point))
if not self.in_x_bound(new_point) or not self.in_y_bound(new_point):
#print('not append(break)')
break
new_point[0] = round(new_point[0], 3)
new_point[1] = round(new_point[1], 3)
traj.append(new_point)
return np.array(traj)
with the following result:
[![zig = ZigZagTraj( 1.2, 1.2, 0, 0, tooth_direction='x', tooth_width=0.2, step=0.05)
traj = zig.generate_trajectory()
fig, ax = plt.subplots()
ax.scatter(traj\[:, 0\], traj\[:, 1\])
plt.show()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.