以恒定的速度在阿基米德螺旋周围移动一个粒子

我想以恒定的速度在一个螺旋中移动一个粒子。 请注意,这不是一个恒定的角速度。 这certificate是相当困难的,我会通过我的方法到目前为止。

所讨论的螺旋是一个经典的阿基米德螺旋,极坐标方程r = ϑ ,参数方程x = t*cos(t), y = t*sin(t) 。 这看起来像这样: 在这里输入图像描述

我想在螺旋周围移动一个粒子,所以天真地,我可以把粒子的位置作为t的值,而速度就是t的增加。 这样粒子以恒定的角速度绕着螺旋运动。 但是,这意味着离中心越远,它的(非角度)速度越快。

所以,我不想让自己的速度增加,而是希望我的速度随着弧长的增加而增加。 获得一个螺旋的弧长是第一个挑战,但由于我使用的阿基米德螺旋不是太疯狂的事实,弧长函数是 ,其中a = 1 。 这使我可以将θ值转换为弧长,但这与我所需要的完全相反。 所以我需要find弧长函数的反函数,在这个障碍上,Wolfram-Alpha已经失败了。

那么是否有可能find弧长函数的倒数? 如果排除theta的负值,该函数是一对一映射。

谢谢,

劳瑞

让我们复杂你的螺旋:

p(t):=(cos(t)·f(t),sin(t)·f(t))

在你的情况f(t):= t,在我的f(t):= 1(所以我付出了我的复杂与简化:)

如果你想在这个退化的螺旋(一个圆圈)中以一定的速度前进,你必须知道你的螺旋在一个回合中有多长时间,所以你可以说每秒多less回合确保你的点以所需的速度行进。

现在我们知道每个完整的圆圈是2· π·r长:2· π·1在我们的情况下, 如果ω是公转速度(以每秒钟为单位),则速度V将是V = 2· π·1·ω或更一般的方式:

V = 2·π·r·ω

如果r是一般的半径, 这告诉我们:

V /(2·π·r)=ω

如果r是t的函数,我们可以说:

ω(t)= V /(2·π·r(t))

在我的“复杂”的情况下,这可以被重写如下:

ω(t)= V /(2·π·f(t))

在你的“简化”情况下,答案是:

ω(t)= V /(2·π·t)

你知道你所期望的恒定速度V,你知道:2, πt是你的variables:你知道一切,你准备好了!

在t中螺旋的无穷小邻域的圆逼近

t中螺旋的无穷小邻域的圆逼近

[免责声明]

这不是一个严格的math处理:它没有考虑到f的微分的贡献,也没有说什么types的函数不能被使用。

如果你不介意一个相当快速的相当准确的假设,这个简单的解决scheme工作得很好:

 theta = r = sqrt(2) . sqrt({time}) 

这是时间参数,非常方便。 不过,为了达到这个目的,我需要假定议案大致是循环的 – 即。 瞬时线速度与半径乘以角速度成正比:

 {velocity} ~= {radius} . d{theta} / d{time} 

为了显示解决scheme的工作原理,将其插入d{theta} / d{time}

 d{theta} / d{time} = d(sqrt(2).{time}^(1/2)) / d{time} = (sqrt(2) / 2) . {time}^(-1/2)) = 1 / {theta} = 1 / {radius} => {velocity} = {radius} / {radius} = 1, as required. 

{time}=1 ,这个距离原点的距离为sqrt(2) 。 在此之后,近似值显着提高:后续点之间的分离(线性,不沿着path)是1.13,1.08,1.06。 100分后,分离度小于1.0023。

在寻找一个解决scheme来计算对应于某个弧长的角度时,我偶然发现了这个问题和当前的答案。 不幸的是,这个答案和我在networking上find的任何其他资源都不能直接用于实现。

显然,计算弧长函数的倒数(在问题中也提供了)是非常困难的。 但是使用牛顿迭代法可以逼近这个逆。 以下是一个主要提供两种方法的类:

  • computeArcLength(double alpha, double angleRad) :计算阿基米德螺旋上一个点的弧长,其中alpha是连续转弯之间的距离, angleRad是以弧度表示的角度
  • computeAngle(double alpha, double arcLength, double epsilon) :计算给定弧长的点位于阿基米德螺旋上的角度,其中alpha是连续转弯之间的距离, epsilon是牛顿迭代的逼近阈值

代码在这里用Java实现,但是这些核心方法应该是相当的语言不可知的:

 import java.awt.geom.Point2D; /** * A class for computations related to an Archimedean Spiral */ class ArchimedeanSpiral { /** * Computes an approximation of the angle at which an Archimedean Spiral * with the given distance between successive turnings has the given * arc length.<br> * <br> * Note that the result is computed using an approximation, and not * analytically. * * @param alpha The distance between successive turnings * @param arcLength The desired arc length * @param epsilon A value greater than 0 indicating the precision * of the approximation * @return The angle at which the desired arc length is achieved * @throws IllegalArgumentException If the given arc length is negative * or the given epsilon is not positive */ static double computeAngle( double alpha, double arcLength, double epsilon) { if (arcLength < 0) { throw new IllegalArgumentException( "Arc length may not be negative, but is "+arcLength); } if (epsilon <= 0) { throw new IllegalArgumentException( "Epsilon must be positive, but is "+epsilon); } double angleRad = Math.PI + Math.PI; while (true) { double d = computeArcLength(alpha, angleRad) - arcLength; if (Math.abs(d) <= epsilon) { return angleRad; } double da = alpha * Math.sqrt(angleRad * angleRad + 1); angleRad -= d / da; } } /** * Computes the arc length of an Archimedean Spiral with the given * parameters * * @param alpha The distance between successive turnings * @param angleRad The angle, in radians * @return The arc length * @throws IllegalArgumentException If the given alpha is negative */ static double computeArcLength( double alpha, double angleRad) { if (alpha < 0) { throw new IllegalArgumentException( "Alpha may not be negative, but is "+alpha); } double u = Math.sqrt(1 + angleRad * angleRad); double v = Math.log(angleRad + u); return 0.5 * alpha * (angleRad * u + v); } /** * Compute the point on the Archimedean Spiral for the given parameters.<br> * <br> * If the given result point is <code>null</code>, then a new point will * be created and returned. * * @param alpha The distance between successive turnings * @param angleRad The angle, in radians * @param result The result point * @return The result point * @throws IllegalArgumentException If the given alpha is negative */ static Point2D computePoint( double alpha, double angleRad, Point2D result) { if (alpha < 0) { throw new IllegalArgumentException( "Alpha may not be negative, but is "+alpha); } double distance = angleRad * alpha; double x = Math.sin(angleRad) * distance; double y = Math.cos(angleRad) * distance; if (result == null) { result = new Point2D.Double(); } result.setLocation(x, y); return result; } /** * Private constructor to prevent instantiation */ private ArchimedeanSpiral() { // Private constructor to prevent instantiation } } 

下面的代码给出了如何在问题中描述的目标中使用它的一个例子:它在螺旋上产生一定数量的点,点之间具有所需的(弧长!)距离:

 import java.awt.geom.Point2D; import java.util.Locale; public class ArchimedeanSpiralExample { public static void main(String[] args) { final int numPoints = 50; final double pointArcDistance = 0.1; final double alpha = 0.5; final double epsilon = 1e-5; double totalArcLength = 0.0; double previousAngleRad = 0.0; for (int i=0; i<numPoints; i++) { double angleRad = ArchimedeanSpiral.computeAngle(alpha, totalArcLength, epsilon); Point2D point = ArchimedeanSpiral.computePoint(alpha, angleRad, null); totalArcLength += pointArcDistance; // Compute and print the arc lengths, for validation: double currentArcLength = ArchimedeanSpiral.computeArcLength(alpha, angleRad); double previousArcLength = ArchimedeanSpiral.computeArcLength(alpha, previousAngleRad); double arcDistance = (currentArcLength - previousArcLength); System.out.printf(Locale.ENGLISH, "Point (%6.2f, %6.2f distance in arc " + "length from previous is %6.2f\n", point.getX(), point.getY(), arcDistance); previousAngleRad = angleRad; } } } 

计算点的实际弧长距离被打印出来,人们可以看到它们实际上是等距的,并具有所需的弧长距离。

我也在为此苦苦挣扎。

我所做的是保持速度不变,并改变物体的方向。

如果我是这样的角度(度)等于从原点的距离,乘以一个常数,我得到一个不错的完美阿基米德螺旋。 更大的常量在行之间获得更less的空间。 唯一的问题是,如果速度太高,那么它就跳上轨道,变得混乱起来。 所以更紧密的螺旋需要更慢的速度来可靠地跟踪。

direction = ((spiral_factor*(current_distance) mod 360);

其中,current_distance是从像素位置到生成点的半径,由发送给我的引擎函数抓取。

什么东西把我拉上了墙壁,是相反的。 把对象放在外面,让它跟踪阿基米德螺旋向内。 以相反的方式移动粒子不起作用。 只是旋转180度的螺旋。 反方向给出顺时针的一个。