1

假设我们想要生成一个 zig-zag 点集作为 numpy 数组,如下图所示,使得数组元素的顺序类似于在路径上移动:

我们得到:

  • 此路径应位于的边界(例如,上图中的 x=[-2500:2500], y=[-200, 200])
  • 定义此类路径中点顺序的起点(例如,在打击图像中它是 (2500, 200)
  • 牙齿方向(例如,下图是y)方向,这就是起点开始向下的原因)
  • 每个点之间的步长(例如,10)
  • 每颗牙齿的宽度

生成这种 numpy 数组的最简单方法是什么?我尝试了 scipy 方波,但除了其他必需的功能外,它只生成牙齿边缘点,但不是所有路径都可以用散点图显示

在此处输入图像描述

4

2 回答 2

2

提前为忽略您的出发点牙齿方向道歉。我开始时没有考虑它们,当我完成后只需要添加它们,我认为您很可能自己可以做到这一点。我还认为,对于您的 x 像素点距离请求,可能有一个更漂亮的解决方案,而不是仅仅获得很多点并过滤它们以便满足。让我知道这对你是否重要。除此之外,我认为这是一个不错的解决方案。

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)

牙齿

于 2022-01-16T22:39:59.850 回答
0

到目前为止,我有以下答案:

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)

结果如下:

[![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()

在此处输入图像描述

于 2022-01-17T14:04:38.510 回答