Python 3.x 如何在python中检查向量何时旋转一圈
我实际上是在处理表示2d空间中(大致)嘈杂圆圈的数据。我一次采集一个点的数据,目标是知道这些点何时形成一个圆 为了做到这一点,我将每个连续的点视为只有一个稍微转动的向量。为了知道什么时候转了一圈(也就是说什么时候形成了圆),我检查了x和y坐标是否两次改变了符号(也就是说向量已经转了2*0.5圈=1圈)。然后我再等半圈来补偿启动错误。事实上,这取决于它在最初的四分之一空间中的起始位置,它可能没有完成一个完整的转弯 我不需要非常精确。所以这对我来说很好,但我想知道是否有另一种方法更有效,可以告诉我实际的圈数。这可能会加快一点过程,因为积分到达的速度很慢(避免我再等一个无用的半圈) 重要的一点是,我只能使用Numpy 编辑:更精确地说,每个点之间的距离不是规则的。首先,圆圈开始慢慢形成,然后加速。因此,开始时的点比结束时的点更密集。另一件事是,(0,0)点甚至可能不包含在圆中。最后,我说的是大致呈圆形,因为它往往是省略号形状,但形状不是很糟糕,只是有噪音Python 3.x 如何在python中检查向量何时旋转一圈,python-3.x,computational-geometry,Python 3.x,Computational Geometry,我实际上是在处理表示2d空间中(大致)嘈杂圆圈的数据。我一次采集一个点的数据,目标是知道这些点何时形成一个圆 为了做到这一点,我将每个连续的点视为只有一个稍微转动的向量。为了知道什么时候转了一圈(也就是说什么时候形成了圆),我检查了x和y坐标是否两次改变了符号(也就是说向量已经转了2*0.5圈=1圈)。然后我再等半圈来补偿启动错误。事实上,这取决于它在最初的四分之一空间中的起始位置,它可能没有完成一个完整的转弯 我不需要非常精确。所以这对我来说很好,但我想知道是否有另一种方法更有效,可以告诉我实
很抱歉,我不能提供数据,至少现在是这样。我将告诉您这周是否可行。如果保证每个新数据点的极角大于前一个,即圆以增量形式形成,且过程中没有任何点“后退”,然后,对于每一对连续的点,你可以计算它们之间的角度,然后当总和达到2π时,你可以停止。例如:
angle = 0
points = [next(generator)] # 'generator' produces the data points
while angle < 2*pi:
points.append(next(generator))
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below 2 pi
角度=0
points=[next(generator)]#“generator”生成数据点
当角度<2*pi时:
添加点(下一个(生成器))
角度+=np.arccos(
np.点(点[-2],点[-1])/
(np.linalg.norm(点[-2])*np.linalg.norm(点[-1]))
)
删除点[-1]#可选择删除最后一点,以保持在2π以下
以下是使用上述方法绘制的示例图:
以及示例代码:
from math import pi
import random
import matplotlib.pyplot as plt
import numpy as np
def generate():
angle = 0
angle_upper_lim = 0.002
while True:
angle += 2*pi * random.uniform(0.001, angle_upper_lim)
radius = random.uniform(0.95, 1.05)
yield radius*np.cos(angle), radius*np.sin(angle)
angle_upper_lim *= 1.03 # make the circle fill faster
generator = generate()
angle = 0
points = [next(generator)] # 'generator' produces the data points
while angle < 2*pi:
points.append(next(generator))
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below 2 pi
fig, ax = plt.subplots()
ax.scatter(*np.stack(points, axis=1), s=5)
ax.set_title(f'Total angle: {angle/pi:.2f} pi')
ax.plot([0, points[ 0][0]], [0, points[ 0][1]], '--s', ms=8, label='First point', color='#2ca02c')
ax.plot([0, points[-1][0]], [0, points[-1][1]], '--*', ms=12, label='Last point', color='#ff7f0e')
ax.legend()
plt.show()
from math import pi
import random
import matplotlib.pyplot as plt
import numpy as np
def generate():
angle = pi/4
angle_upper_lim = 0.002
while True:
angle += 2*pi * random.uniform(0.001, angle_upper_lim)
radius = 1
yield np.array([3 + radius*np.cos(angle), 5 + radius*np.sin(angle)])
angle_upper_lim *= 1.03 # make the circle fill faster
generator = generate()
angle = 0
offset = next(generator) # 'generator' produces the data points
points = [next(generator) - offset]
while angle <= pi:
points.append(next(generator) - offset)
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below pi
fig, ax = plt.subplots(figsize=(4.8, 4.8))
ax.scatter(*np.stack(points, axis=1), s=5, c=np.arange(len(points)))
ax.set_title(f'Total angle: {angle/pi:.2f} pi')
ax.plot(*points[ 0], 's', ms=8, label='First point', color='#2ca02c')
ax.plot(*points[-1], '*', ms=12, label='Last point', color='#ff7f0e')
ax.legend()
plt.show()
from math import pi
import random
import matplotlib.pyplot as plt
import numpy as np
def generate():
angle = pi/4
angle_upper_lim = 0.002
while True:
angle += 2*pi * random.uniform(0.001, angle_upper_lim)
# radius = random.uniform(0.95, 1.05)
radius = 1
yield np.array([3 + radius*np.cos(angle), 5 + radius*np.sin(angle)])
angle_upper_lim *= 1.03 # make the circle fill faster
generator = generate()
def next_point(n=1):
"""n: number of points per group"""
return sum(next(generator) for __ in range(n)) / n
distances = []
points = [next_point()]
while True: # break below
points.append(next_point())
distances.append(np.linalg.norm(points[-1] - points[0]))
if len(distances) >= 3:
left = distances[-2] - distances[-3]
right = distances[-1] - distances[-2]
if left < 0 and right > 0: # minimum detected
break
del points[-1], distances[-1] # optionally delete the last point in order to leave the circle open
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10.8, 4.8))
plt.subplots_adjust(wspace=0.11)
ax1.set_title('Data points')
ax1.scatter(*np.stack(points, axis=1), s=5, c=np.arange(len(points)))
ax1.plot(*points[ 0], 's', ms=8, label='First point', color='#2ca02c')
ax1.plot(*points[-1], '*', ms=12, label='Last point', color='#ff7f0e')
ax1.legend(loc='center')
ax2.set(title='Distance of circle points to first point', xlabel='Point #', ylabel='Distance')
ax2.yaxis.tick_right()
ax2.yaxis.set_label_position('right')
ax2.plot(distances, '-o', ms=4)
ax2.plot(len(distances)-1, distances[-1], '*', ms=10, label='circle closed')
ax2.legend()
plt.show()
从数学导入pi
随机输入
将matplotlib.pyplot作为plt导入
将numpy作为np导入
def generate():
角度=0
角度_上_直线=0.002
尽管如此:
角度+=2*pi*随机均匀(0.001,角度上界)
半径=随机均匀(0.95,1.05)
屈服半径*np.cos(角度),半径*np.sin(角度)
角度_upper_lim*=1.03#使圆填充速度更快
生成器=生成()
角度=0
points=[next(generator)]#“generator”生成数据点
当角度<2*pi时:
添加点(下一个(生成器))
角度+=np.arccos(
np.点(点[-2],点[-1])/
(np.linalg.norm(点[-2])*np.linalg.norm(点[-1]))
)
删除点[-1]#可选择删除最后一点,以保持在2π以下
图,ax=plt.子批次()
最大散射(*np.叠加(点,轴=1),s=5)
ax.set_title(f'总角度:{angle/pi:.2f}pi')
ax.plot([0,点[0][0]],[0,点[0][1]],'-s',ms=8,label='First point',color='2ca02c')
ax.plot([0,点[-1][0]],[0,点[-1][1]],'-*',ms=12,label='Last point',color='#ff7f0e')
ax.图例()
plt.show()
您可以使用第一个点作为偏移量,该偏移量将从所有点中减去。这会将圆的边移动到原点。现在想象一条与圆相切的直线(在任意点,但我们将使用原点),然后圆完全位于切线的一侧。切线本身跨越180度,如果我们从原点开始沿着圆走,总是测量连续向量之间的角度,那么一旦我们回到原点,我们将总共测量180度(如果圆上的点之间的间隔是无限小的)。这允许计算角度的累积和,并在达到180度(=π)时停止。现在,由于实际上这些点的间距是有限的,我们将错过圆的起点和终点(原点的w.r.t.)180度的一部分。这意味着,当我们达到180度时,我们收集的点将略多于闭合圆所需的点;OP表示这是所需的行为,即圆必须闭合(有些重叠比不闭合好)
这是算法的相关代码:
angle = 0
offset = next(generator) # 'generator' produces the data points
points = [next(generator) - offset]
while angle <= pi:
points.append(next(generator) - offset)
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below pi
distances = []
points = [next_point()]
while True: # break below
points.append(next_point())
distances.append(np.linalg.norm(points[-1] - points[0]))
if len(distances) >= 3:
left = distances[-2] - distances[-3]
right = distances[-1] - distances[-2]
if left < 0 and right > 0: # minimum detected
break
del points[-1], distances[-1] # optionally delete the last point in order to leave the circle open
角度=0
偏移量=下一个(生成器)#“生成器”生成数据点
点=[下一个(生成器)-偏移]
当角度时,您可以监控每个点到第一个点的距离,当该距离达到最小值时,表示圆已闭合。下图显示了到圆上第一个点的点距离图:
这是算法的相关代码:
angle = 0
offset = next(generator) # 'generator' produces the data points
points = [next(generator) - offset]
while angle <= pi:
points.append(next(generator) - offset)
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below pi
distances = []
points = [next_point()]
while True: # break below
points.append(next_point())
distances.append(np.linalg.norm(points[-1] - points[0]))
if len(distances) >= 3:
left = distances[-2] - distances[-3]
right = distances[-1] - distances[-2]
if left < 0 and right > 0: # minimum detected
break
del points[-1], distances[-1] # optionally delete the last point in order to leave the circle open
距离=[]
点=[下一个点()]
如果为True:#请在下面打断
points.append(next_point())
距离.附加(np.linalg.norm(点[-1]-点[0]))
如果len(距离)>=3:
左=距离[-2]-距离[-3]
右=距离[-1]-距离[-2]
如果左侧<0且右侧>0:#检测到最小值
打破
删除点[-1],距离[-1]#可以选择删除最后一个点,以保持圆打开
在改变角度差和半径的数据集上进行测试,得到以下结果:
以下是完整的示例代码:
from math import pi
import random
import matplotlib.pyplot as plt
import numpy as np
def generate():
angle = 0
angle_upper_lim = 0.002
while True:
angle += 2*pi * random.uniform(0.001, angle_upper_lim)
radius = random.uniform(0.95, 1.05)
yield radius*np.cos(angle), radius*np.sin(angle)
angle_upper_lim *= 1.03 # make the circle fill faster
generator = generate()
angle = 0
points = [next(generator)] # 'generator' produces the data points
while angle < 2*pi:
points.append(next(generator))
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below 2 pi
fig, ax = plt.subplots()
ax.scatter(*np.stack(points, axis=1), s=5)
ax.set_title(f'Total angle: {angle/pi:.2f} pi')
ax.plot([0, points[ 0][0]], [0, points[ 0][1]], '--s', ms=8, label='First point', color='#2ca02c')
ax.plot([0, points[-1][0]], [0, points[-1][1]], '--*', ms=12, label='Last point', color='#ff7f0e')
ax.legend()
plt.show()
from math import pi
import random
import matplotlib.pyplot as plt
import numpy as np
def generate():
angle = pi/4
angle_upper_lim = 0.002
while True:
angle += 2*pi * random.uniform(0.001, angle_upper_lim)
radius = 1
yield np.array([3 + radius*np.cos(angle), 5 + radius*np.sin(angle)])
angle_upper_lim *= 1.03 # make the circle fill faster
generator = generate()
angle = 0
offset = next(generator) # 'generator' produces the data points
points = [next(generator) - offset]
while angle <= pi:
points.append(next(generator) - offset)
angle += np.arccos(
np.dot(points[-2], points[-1]) /
(np.linalg.norm(points[-2]) * np.linalg.norm(points[-1]))
)
del points[-1] # optionally delete the last point in order to stay below pi
fig, ax = plt.subplots(figsize=(4.8, 4.8))
ax.scatter(*np.stack(points, axis=1), s=5, c=np.arange(len(points)))
ax.set_title(f'Total angle: {angle/pi:.2f} pi')
ax.plot(*points[ 0], 's', ms=8, label='First point', color='#2ca02c')
ax.plot(*points[-1], '*', ms=12, label='Last point', color='#ff7f0e')
ax.legend()
plt.show()
from math import pi
import random
import matplotlib.pyplot as plt
import numpy as np
def generate():
angle = pi/4
angle_upper_lim = 0.002
while True:
angle += 2*pi * random.uniform(0.001, angle_upper_lim)
# radius = random.uniform(0.95, 1.05)
radius = 1
yield np.array([3 + radius*np.cos(angle), 5 + radius*np.sin(angle)])
angle_upper_lim *= 1.03 # make the circle fill faster
generator = generate()
def next_point(n=1):
"""n: number of points per group"""
return sum(next(generator) for __ in range(n)) / n
distances = []
points = [next_point()]
while True: # break below
points.append(next_point())
distances.append(np.linalg.norm(points[-1] - points[0]))
if len(distances) >= 3:
left = distances[-2] - distances[-3]
right = distances[-1] - distances[-2]
if left < 0 and right > 0: # minimum detected
break
del points[-1], distances[-1] # optionally delete the last point in order to leave the circle open
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10.8, 4.8))
plt.subplots_adjust(wspace=0.11)
ax1.set_title('Data points')
ax1.scatter(*np.stack(points, axis=1), s=5, c=np.arange(len(points)))
ax1.plot(*points[ 0], 's', ms=8, label='First point', color='#2ca02c')
ax1.plot(*points[-1], '*', ms=12, label='Last point', color='#ff7f0e')
ax1.legend(loc='center')
ax2.set(title='Distance of circle points to first point', xlabel='Point #', ylabel='Distance')
ax2.yaxis.tick_right()
ax2.yaxis.set_label_position('right')
ax2.plot(distances, '-o', ms=4)
ax2.plot(len(distances)-1, distances[-1], '*', ms=10, label='circle closed')
ax2.legend()
plt.show()
从数学导入pi
随机输入
将matplotlib.pyplot作为plt导入
将numpy作为np导入
def generate():
角度=π/4
角度_上_直线=0.002
尽管如此:
角度+=2*pi*随机均匀(0.001,角度上界)
#半径=随机均匀(0.95,1.05)
半径=