我正在使用以下公式绘制正弦曲线,
this.x += this.speed
this.y = this.amp * Math.sin( this.x * this.cycles ) + this.center
我通过在每帧上绘制小圆圈来点画点.这样可以实现从左到右绘制的正弦曲线.但是,如果我想旋转此曲线以使其随机绘制360度,该如何修改代码?再说一遍,有时我希望曲线从左到右是相同的图,有时我希望曲线向下成45度,有时是向后等.
解决方法:
一种选择是计算笛卡尔坐标中的点,转换为极点,添加角度偏移,然后再次转换回笛卡尔坐标.
this.x += this.speed
this.y = this.amp * Math.sin( this.x * this.cycles ) + this.center
this.r = Math.sqrt(this.x * this.x + this.y * this.y);
this.a = Math.atan2(this.y, this.x);
this.a += rotation_angle;
this.x = this.r * Math.cos(this.a);
this.y = this.r * Math.sin(this.a);
这会将数学库调用的次数从一增加到五,因此我希望它的速度大约是原始计算的五分之一.这可能会或可能不会.实际上,我们可以使用三角恒等式sin(ab)= sin(a)cos(b)cos(a)sin(b)和cos(ab)= cos(a)cos(b)-sin(a (b)身份.
对于旋转的X坐标:
this.r * cos(this.a)
= this.r * cos(atan2(this.y, this.x) + rotation)
= this.r * (cos(atan2(this.y, this.x))cos(rotation) - sin(atan2(this.y, this.x))sin(rotation))
= this.r * ((this.x / this.r)cos(rotation) - (this.y / this.r)sin(rotation))
= this.x * cos(rotation) - this.y * sin(rotation)
对于旋转的Y坐标:
this.r * sin(this.a)
= this.r * sin(atan2(this.y, this.x) + rotation)
= this.r * (sin(atan2(this.y, this.x))cos(rotation) + cos(atan2(this.y, this.x))sin(rotation))
= this.r * ((this.y / this.r)cos(rotation) + (this.x / this.r)sin(rotation))
= this.y * cos(rotation) + this.x * sin(rotation)
我们的新代码如下所示:
x = this.x + this.speed
y = this.amp * Math.sin( x * this.cycles ) + this.center
this.x = x * cos(rotation_angle) - y * sin(rotation_angle);
this.y = y * cos(rotation_angle) + x * sin(rotation_angle);
我们引入了变量x和y,因为我们需要它们的原始形式来计算this.x和this.y中的每一个.我们不再需要在极坐标中工作,因为我们的身份使我们能够消除这些中间步骤.另外,如果rotation_angle为常数,则可以预先计算;否则,您可以将调用保留在每个点的计算中,并获得螺旋型效果.
如果您不想完全使用角度,则可以通过使用参数定义x = f(t)和y = g(t)定义一条曲线,确定每个点t的垂直线来使用任意函数进行工作-通过分析地找到f'(t)和g'(t)并对其进行编码-或通过在关注点附近对其进行数值近似.然后,您只需沿该指向法线的位移绘制一个点,该点等于您当前为此this.y计算的值.因此,如果您想沿着抛物线绘制正弦曲线,则可以执行以下操作:
t += speed;
r = this.amp * Math.sin(t * this.cycles) + this.center;
x = t;
y = t * t;
dxdt = 1;
dydt = 2t;
dydx = dydt / dxdt;
if (-epsilon <= dydt && dydt <= epsilon) {
this.x = x;
this.y = y + r;
} else {
normal = -1.0 / dydx;
this.x = x + r * ( 1.0 / Math.sqrt(1 + dydx * dydx));
this.y = y + r * (dydx / Math.sqrt(1 + dydx * dydx));
}
我没有尝试运行它,所以它可能会有一些错误,但是从理论上讲这些错误应该是可修复的,这样您才能获得预期的效果:正弦曲线围绕(定向!)抛物线y = x ^ 2定向为从从负到正x.