2

我正在使用简单的用法制作一个简单的 Vector 类,所以我不想为我自己可以做的事情导入整个库(如 JScience ...)。

目前我已经制作了这段代码:

public void add(Vector2D v){
    double ang = this.angle*Math.PI/180;
    double mag = this.magnitude;
    double ang0 = v.angle*Math.PI/180;
    double mag0 = v.magnitude;
    //vector to coordinates
    double x1 = mag*Math.cos(ang);
    double y1 =-mag*Math.sin(ang);
    //adding the other vector's coordinates
    double x2 =x1+mag*Math.cos(ang0);
    double y2 =y1-mag*Math.sin(ang0);
    //back to vector form
    double newMagnitude = Math.sqrt(x2*x2+y2*y2);
    double newAngle = Math.atan2(y2,x2);
    this.magnitude = newMagnitude;
    this.angle = newAngle;

}

它将两个向量都转换为坐标,然后用三角函数返回,但是这些非常慢,并且该方法将被非常频繁地使用。

有没有更好的办法?

4

1 回答 1

2

首先,一些术语 101:

点:构成空间的无量纲实体。

空间:一组点。

欧几里得空间:一组点,一组线和紧密度(拓扑)的概念。这组线受欧几里得公理的约束。它由其维度唯一定义。

向量:欧几里得空间中两点之间的平移不变关系。

坐标系:从实数元组到某个空间中的点或向量的映射。

笛卡尔坐标系:一种特定的映射,具有以下属性(在欧几里得二维空间的情况下)点集ax+by+c=0是一条线,除非a,b两者都为零,向量[0,1][1,0]是垂直的和单位长度,并且空间中的点是接近的如果它们在所有坐标中都靠近,则在一起。这就是您所说的“坐标”。

极坐标系:另一个特定的映射,可以从笛卡尔坐标定义:[arg,mag]极坐标映射到[cos(arg)*mag, sin(arg)*mag]笛卡尔坐标。这就是您所说的“矢量形式”。


与极坐标系相比,笛卡尔坐标系具有多个优点。其中之一是更容易加法:[x1,y1]+[x2,y2]=[x1+x2,y1+y2]和标量乘法:[x1,y1].[x2,y2]=x1*x2+y1*y2。加法反转也稍微容易一些:-[x,y]=[-x,-y]

另一个好处是,虽然极坐标是严格的 2D 坐标(没有唯一的扩展 - 球坐标系是一个候选者),但笛卡尔坐标自然地扩展到任意数量的维度。

出于这个原因,总是以笛卡尔坐标形式存储向量是有益的——而且通常是这样的。

如果您需要极坐标形式的向量,那么(并且仅在那时)一劳永逸地进行转换。

极坐标没那么有用。它们可用于输入和输出,但很少用于计算。


您继续以极坐标形式存储向量。您将它们转换为笛卡尔形式进行计算,然后转换回极坐标 - 只是再次将它们转换为笛卡尔形式。

您应该以笛卡尔形式存储向量。如果放弃冗余转换,性能改进应该是清晰可见的。

即使要旋转矢量,转换为极坐标并返回也无济于事。旋转一个有符号的角度a就像[x*cos(a)+y*sin(a), y*cos(a)-x*sin(a)]. 这是两个三角函数(最多 - 你可以缓存这些值)来旋转整个向量数组。

于 2013-01-01T03:25:00.560 回答