2010-10-29 189 views
3

我正在编码Java中的植绒算法,但我被困在某个点(使用Ardor3D库,在一个2D平面)。查找三角形角度用于旋转给定实体的位置,初始旋转和目标点'面向'

基本上,我需要找到要添加到当前旋转的角度差。如果你只能用极坐标指向北极0度的位置而不考虑差别,不用担心 - 我有一种方法可以返回角度差,同时考虑角度和负角度的环绕。

alt text

此刻,我有以下的代码,这显然不会因为算法的工作没有参考初始旋转:

long tpf = currUpdateTimeMS - lastUpdateTimeMS; 

    Vector2 pos = new Vector2(); 
    rt.getPosition(pos); 

    double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal()); 
    rt.setRotation(rot); 

    pos.addLocal(
    Math.cos((rot - MathUtils.HALF_PI)) * (tpf/10f), 
    Math.sin((rot - MathUtils.HALF_PI)) * (tpf/10f) 
); 
    rt.setPosition(pos); 

    super.updateLogic(); 

更新后的代码(不工作,从第一个答案):

long tpf = currUpdateTimeMS - lastUpdateTimeMS; 
    //rt.setRotation(rt.getRotation() + ((tpf/(ROT_SPEED/2f)) % 360)); 

    Vector2 avgpos = app.getAvgBoidPos(new Vector2()); 
    Vector2 pos = rt.getPosition(new Vector2()); 
    avgpos.subtractLocal(pos); 

    double angleRads = rt.getRotation() * FastMath.DEG_TO_RAD; 
    double rot = MathUtils.acos((
     (avgpos.getX() * MathUtils.sin(angleRads) 
    ) + 
     (avgpos.getY() * MathUtils.cos(angleRads) 
    ))/((Math.pow(avgpos.getX(), 2) + Math.pow(avgpos.getY(), 2)) * 0.5)); 

    double adegdiff = rot * FastMath.RAD_TO_DEG; 

    rt.setRotation(rt.getRotation() - adegdiff); 
    double newrot = rt.getRotation(); 

    pos.addLocal(
     Math.cos((newrot - MathUtils.HALF_PI)) * (tpf/10f), 
     Math.sin((newrot - MathUtils.HALF_PI)) * (tpf/10f) 
    ); 
    rt.setPosition(pos); 

    super.updateLogic(); 

基于对方的回答另一种修饰:

long tpf = currUpdateTimeMS - lastUpdateTimeMS; 
    //rt.setRotation(rt.getRotation() + ((tpf/(ROT_SPEED/2f)) % 360)); 

    Vector2 avgpos = app.getAvgBoidPos(new Vector2()); 
    Vector2 pos = rt.getPosition(new Vector2()); 
    avgpos.subtractLocal(pos); 

    double rot = pos.angleBetween(
     app.getAvgBoidPos(new Vector2()).normalizeLocal() 
    ) - (rt.getRotation() * MathUtils.DEG_TO_RAD); 

    rt.setRotation(rt.getRotation() - (rot * MathUtils.RAD_TO_DEG)); 
    double newrot = rt.getRotation(); 

    pos.addLocal(
     Math.cos((newrot - MathUtils.HALF_PI)) * (tpf/10f), 
     Math.sin((newrot - MathUtils.HALF_PI)) * (tpf/10f) 
    ); 
    rt.setPosition(pos); 

    super.updateLogic(); 

我不是一个真正的数学问题不太好,所以代码将是有益的,而不是公式:)

输入

  • 实体的当前位置
  • 当前实体的旋转(极性取向)以度

输出

  • 度或弧度来增加或减少当前旋转
  • ...或学位或弧度提前表示为导向的极角

谢谢如果你能帮助:)

克里斯

+0

所以'rt.getPosition'给出了实体的位置和'app.getAvgBOIDPos'给出了目标位置,是这样吗?什么给了实体的方向? – Beta 2010-10-29 15:41:07

+0

这就是rt.getRotation(),它是以面向极坐标的度数表示的:) – 2010-10-29 15:42:25

+0

糟糕,忘记说你对应用程序是正确的,getAvgBoidPos()给出了实体向实体移动的平均位置。 – 2010-10-29 15:53:58

回答

2

可以使用点积来确定当前方向与要面对的点之间的角度(弧度)的余弦。假设进行观看的代理位于原点并且面向相对于Y轴(即,0度是“上”或“北”)的角度θ给出的某个方向。你想找到该方向和面对点(x,y)之间的角度差θ'。

θ' = cos-1[(x*sin(θ) + y*cos(θ))/sqrt(x2 + y2)]

减去θ“从θ会朝向目标的代理:即由下式给出。

如果代理不在原点,只需将代理的位置从要查看的对象中减去以将其置于上面的表单中即可。

+0

明白了。我会尝试实施这个,并回来给你,如果有任何问题:) – 2010-10-29 16:18:09

+0

我实现了它,但它似乎并没有工作。我认为位置的x和y元素由于在某处被零除而得到NaN?无论如何,我用新代码更新了这个问题:) – 2010-10-29 16:44:01

+0

@Chris Dennett:我认为我为了自己的利益而努力过于聪明。您将分母乘以1/2。我试图把它提升到1/2的平方根。对于x和y的某些值,这可能导致商不在[-1,1]的范围内,这会导致NaN。我更新了我的等式以更好地表明这一点。 – andand 2010-10-29 18:38:51

0

继承人是如何找到具有共同起源的两个向量之间的角度的实现。 http://www.wikihow.com/Find-the-Angle-Between-Two-Vectors

public class DeltaDoodle { 

    private double delta(ColumnVector v1,ColumnVector v2) throws Exception{ 
     double sp=scalarProduct(v1,v2); 
     double magV1=magnitude(v1); 
     double magV2=magnitude(v2); 
     return Math.acos(sp/(magV1*magV2)) * (180/Math.PI); 
    } 

    private double scalarProduct(ColumnVector a, ColumnVector b) { 
     return (a.x*b.x) + (a.y*b.y); 
    } 
    private double magnitude(ColumnVector a){ 
     return Math.sqrt((a.x*a.x) + (a.y*a.y)); 
    } 

    public static void main(String[] args) { 
     DeltaDoodle v=new DeltaDoodle(); 
     try { 
      System.out.println("angle: " + v.delta(new ColumnVector(5, 5), new ColumnVector(1,1))); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

public class ColumnVector { 
    public final double x, y; 

    public ColumnVector(double x1, double x2) { 
     this.x = x1; 
     this.y = x2; 
    } 
} 

希望帮助...

0

如果我正确理解这些功能,这可能只是工作:

Vector2 pos = new Vector2(); 
rt.getPosition(pos); 

double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal()) - rt.getRotation(); 

基于有描述的算法在这个被黑客攻击了一起PS忘了提及:这rot旨在是角度差异。通过这么多的旋转实体,它应该指向目标。

编辑:
谢谢,代码没有帮助(我误解angleBetween)。让我再试一次:

下面是从实体点(原谅我,如果我得到的语法错了,我不知道的Java)的载体:

Vector2 pos = new Vector2(); 
rt.getPosition(pos); 

Vector2 direction = app.getAvgBoidPos(new Vector2()); 
direction.subtractLocal(pos); 

现在我们正常化它来获得朝向点指向的单位向量,并采取了角的差

double rot = rt.getRotation().angleBetween(direction.normalizeLocal()) 
+0

不工作:/如果有帮助,这里是Vector2源代码:http://ardorlabs.trac.cvsdude.com/Ardor3Dv1/browser/trunk/ardor3d-core/src/main/java/com/ardor3d/math/Vector2 .java?rev = 152 – 2010-10-29 18:54:52

1

稍微偏离主题,但你可能会发现粒子群,并在我们的特效软件包徜徉代码(ardor3d效果)也很有趣。

他们可以在热情SVN发现,这里还是:

http://ardorlabs.trac.cvsdude.com/Ardor3Dv1/browser/trunk/ardor3d-effects/src/main/java/com/ardor3d/extension/effect/particle/

+0

哦,欢呼雷南瑟! :D – 2010-11-27 19:26:47

+0

顺便说一下,这并不完全脱离主题,因为我想要实现的东西无论如何都是蜂拥而至:)'发现平均位置'元素是其中的一部分,我得到了它的工作。但也有其他元素的问题,这似乎已经在这里被整理:) – 2010-11-27 19:31:40

+0

唯一的问题是,粒子代码没有旋转和速度,我可以做 - 它只有速度在X ,y和z。但它们之间转换不应该很难。如果我将速度作为旋转和速度的乘积(我已经有公式),那应该没问题。 – 2010-11-27 19:36:16