我正在制作一个简单用法的简单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;
}
它将两个向量转换为坐标,然后用三角函数转换回来,但是那些非常慢,并且该方法将非常频繁地使用。
还有更好的办法吗?
答案 0 :(得分:2)
首先,一些术语101:
点:无空间的实体,空间由。
组成空间:一组积分。
欧几里德空间:一组点,连同一组线和近似概念(拓扑)。这组线由欧几里德的公理约束。它的维度是唯一定义的。
向量:欧几里德空间中两点之间的平移不变关系。
坐标系:从实数元组到某些空间中的点或向量的映射。
笛卡尔坐标系:一个特定的映射,其属性(在欧几里德2D空间的情况下)点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)]
一样简单。那是两个三角函数(最多 - 你可以缓存这些值)来旋转整个矢量数组。